#include #include typedef unsigned long long int ULong; typedef unsigned int UInt; #define CC_SHIFT_O 11 #define CC_SHIFT_S 7 #define CC_SHIFT_Z 6 #define CC_SHIFT_A 4 #define CC_SHIFT_C 0 #define CC_SHIFT_P 2 #define CC_MASK_O (1ULL << CC_SHIFT_O) #define CC_MASK_S (1ULL << CC_SHIFT_S) #define CC_MASK_Z (1ULL << CC_SHIFT_Z) #define CC_MASK_A (1ULL << CC_SHIFT_A) #define CC_MASK_C (1ULL << CC_SHIFT_C) #define CC_MASK_P (1ULL << CC_SHIFT_P) #define CC_MASK_OSZACP \ (CC_MASK_O | CC_MASK_S | CC_MASK_Z | CC_MASK_A | CC_MASK_C | CC_MASK_P) void showFlags(/*OUT*/char* str, int nStr, ULong flags) { // Ignore everything except OSZACP, because V differs from real h/w in // flags other than OSZACP, and we don't want that to confuse the // results here memset(str, 0, nStr); sprintf(str, "%c%c%c%c%c%c", (flags & CC_MASK_O) ? 'o' : '-', (flags & CC_MASK_S) ? 's' : '-', (flags & CC_MASK_Z) ? 'z' : '-', (flags & CC_MASK_A) ? 'a' : '-', (flags & CC_MASK_C) ? 'c' : '-', (flags & CC_MASK_P) ? 'p' : '-'); } __attribute__((noinline)) void do_test ( ULong val, UInt ix ) { ULong o, s, z, a, c, p, flags_before; for (o = 0; o < 2; o++) { for (s = 0; s < 2; s++) { for (z = 0; z < 2; z++) { for (a = 0; a < 2; a++) { for (c = 0; c < 2; c++) { for (p = 0; p < 2; p++) { flags_before = (o ? CC_MASK_O : 0) | (s ? CC_MASK_S : 0) | (z ? CC_MASK_Z : 0) | (a ? CC_MASK_A : 0) | (c ? CC_MASK_C : 0) | (p ? CC_MASK_P : 0); ULong block[4] = { flags_before, val, ix, 0 }; __asm__ __volatile__( "movq 0(%0), %%r15" "\n\t" // flags_before "pushq %%r15" "\n\t" "popfq" "\n\t" "movq 8(%0), %%r14" "\n\t" // val "movq 16(%0), %%r13" "\n\t" // ix "bt %%r13, %%r14" "\n\t" "pushfq" "\n\t" "popq %%r15" "\n\t" "movq %%r15, 24(%0)" "\n" // block[3] : : "r"(&block[0]) : "cc","memory","r13","r14","r15" ); ULong flags_after = block[3]; flags_after &= CC_MASK_OSZACP; char flags_after_str[100]; char flags_before_str[100]; showFlags(flags_before_str, 100, flags_before); showFlags(flags_after_str, 100, flags_after); printf("flags 0x%03llx(%s) val 0x%llx ix %d -> flags 0x%03llx(%s)\n", flags_before, flags_before_str, val, ix, flags_after, flags_after_str); }}}}}} } int main ( void ) { do_test(0x8000, 14); // should always return C == 0 printf("\n"); do_test(0x8000, 15); // should always return C == 1 return 0; }