Elliott Hughes | ed39800 | 2017-06-21 14:41:24 -0700 | [diff] [blame] | 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 | |
| 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)) |
| 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 | |
| 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 | } |