Home | History | Annotate | Download | only in amd64
      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 }
     89