1
2 #include <stdio.h>
3 #include <string.h>
4
5 typedef unsigned long long int ULong;
6 typedef unsigned int UInt;
7
8 #define CC_SHIFT_O 11
9 #define CC_SHIFT_S 7
10 #define CC_SHIFT_Z 6
11 #define CC_SHIFT_A 4
12 #define CC_SHIFT_C 0
13 #define CC_SHIFT_P 2
14
15 #define CC_MASK_O (1ULL << CC_SHIFT_O)
16 #define CC_MASK_S (1ULL << CC_SHIFT_S)
17 #define CC_MASK_Z (1ULL << CC_SHIFT_Z)
18 #define CC_MASK_A (1ULL << CC_SHIFT_A)
19 #define CC_MASK_C (1ULL << CC_SHIFT_C)
20 #define CC_MASK_P (1ULL << CC_SHIFT_P)
21
22 #define CC_MASK_OSZACP \
23 (CC_MASK_O | CC_MASK_S | CC_MASK_Z | CC_MASK_A | CC_MASK_C | CC_MASK_P)
24
25
showFlags(char * str,int nStr,ULong flags)26 void showFlags(/*OUT*/char* str, int nStr, ULong flags)
27 {
28 // Ignore everything except OSZACP, because V differs from real h/w in
29 // flags other than OSZACP, and we don't want that to confuse the
30 // results here
31 memset(str, 0, nStr);
32 sprintf(str, "%c%c%c%c%c%c",
33 (flags & CC_MASK_O) ? 'o' : '-',
34 (flags & CC_MASK_S) ? 's' : '-',
35 (flags & CC_MASK_Z) ? 'z' : '-',
36 (flags & CC_MASK_A) ? 'a' : '-',
37 (flags & CC_MASK_C) ? 'c' : '-',
38 (flags & CC_MASK_P) ? 'p' : '-');
39 }
40
41 __attribute__((noinline))
do_test(ULong val,UInt ix)42 void do_test ( ULong val, UInt ix )
43 {
44 ULong o, s, z, a, c, p, flags_before;
45 for (o = 0; o < 2; o++) {
46 for (s = 0; s < 2; s++) {
47 for (z = 0; z < 2; z++) {
48 for (a = 0; a < 2; a++) {
49 for (c = 0; c < 2; c++) {
50 for (p = 0; p < 2; p++) {
51 flags_before = (o ? CC_MASK_O : 0)
52 | (s ? CC_MASK_S : 0)
53 | (z ? CC_MASK_Z : 0)
54 | (a ? CC_MASK_A : 0)
55 | (c ? CC_MASK_C : 0)
56 | (p ? CC_MASK_P : 0);
57 ULong block[4] = { flags_before, val, ix, 0 };
58 __asm__ __volatile__(
59 "movq 0(%0), %%r15" "\n\t" // flags_before
60 "pushq %%r15" "\n\t"
61 "popfq" "\n\t"
62 "movq 8(%0), %%r14" "\n\t" // val
63 "movq 16(%0), %%r13" "\n\t" // ix
64 "bt %%r13, %%r14" "\n\t"
65 "pushfq" "\n\t"
66 "popq %%r15" "\n\t"
67 "movq %%r15, 24(%0)" "\n" // block[3]
68 : : "r"(&block[0]) : "cc","memory","r13","r14","r15"
69 );
70 ULong flags_after = block[3];
71 flags_after &= CC_MASK_OSZACP;
72 char flags_after_str[100];
73 char flags_before_str[100];
74 showFlags(flags_before_str, 100, flags_before);
75 showFlags(flags_after_str, 100, flags_after);
76 printf("flags 0x%03llx(%s) val 0x%llx ix %d -> flags 0x%03llx(%s)\n",
77 flags_before, flags_before_str, val, ix,
78 flags_after, flags_after_str);
79 }}}}}}
80 }
81
main(void)82 int main ( void )
83 {
84 do_test(0x8000, 14); // should always return C == 0
85 printf("\n");
86 do_test(0x8000, 15); // should always return C == 1
87 return 0;
88 }
89