Home | History | Annotate | Download | only in amd64
      1 #include <stdlib.h>
      2 #include <stdio.h>
      3 
      4 typedef unsigned int UInt;
      5 typedef unsigned long long int ULong;
      6 
      7 void do_cmpxchg8b ( /*OUT*/
      8                     ULong* rdxOut,   ULong* raxOut,
      9 		    ULong* memHiOut, ULong* memLoOut,
     10                     ULong* zOut,
     11                     /*IN*/
     12                     ULong rdxIn,   ULong raxIn,
     13                     ULong memHiIn, ULong memLoIn,
     14                     ULong rcxIn,   ULong rbxIn )
     15 {
     16    UInt mem[2];
     17    ULong block[6];
     18    mem[0] = (UInt)memLoIn;
     19    mem[1] = (UInt)memHiIn;
     20    block[0] = rdxIn;
     21    block[1] = raxIn;
     22    block[2] = rcxIn;
     23    block[3] = rbxIn;
     24    block[4] = (ULong)&mem[0];
     25    block[5] = ~(0ULL);
     26    __asm__ __volatile__(
     27           "movq %0,%%r11\n"
     28         "\tmovq  0(%%r11),%%rdx\n"
     29         "\tmovq  8(%%r11),%%rax\n"
     30         "\tmovq 16(%%r11),%%rcx\n"
     31         "\tmovq 24(%%r11),%%rbx\n"
     32         "\tmovq 32(%%r11),%%r10\n"
     33         "\tlock cmpxchg8b (%%r10)\n"
     34         "\tmovabsq $0,%%r10\n"
     35         "\tsetz %%r10b\n"
     36         "\tmovq %%r10,40(%%r11)\n"
     37         "\tmovq %%rdx,0(%%r11)\n"
     38         "\tmovq %%rax,8(%%r11)\n"
     39 	  : /*out*/
     40 	  : /*in*/ "r"(&block[0])
     41 	  : /*trash*/ "%r11", "%r10", "%rax", "%rbx", "%rcx", "%rdx",
     42                       "cc", "memory" );
     43     *rdxOut = block[0];
     44     *raxOut = block[1];
     45     *memLoOut = (ULong)mem[0];
     46     *memHiOut = (ULong)mem[1];
     47     *zOut = block[5];
     48 }
     49 
     50 void try8b ( ULong d, ULong a, ULong mHi, ULong mLo, ULong c, ULong b )
     51 {
     52    ULong dd, aa, mmHi, mmLo, zz;
     53    do_cmpxchg8b( &dd, &aa, &mmHi, &mmLo, &zz,
     54 		 d,a,mHi,mLo,c,b);
     55    printf(" Q d:a=%llx:%llx mem=%llx:%llx c:b=%llx:%llx "
     56           "-> z=%lld d:a=%llx:%llx mem=%llx:%llx\n",
     57 	  d,a, mHi,mLo, c,b, zz, dd,aa, mmHi,mmLo );
     58 }
     59 
     60 void do_cmpxchg16b ( /*OUT*/
     61                      ULong* rdxOut,   ULong* raxOut,
     62 		     ULong* memHiOut, ULong* memLoOut,
     63                      ULong* zOut,
     64                      /*IN*/
     65                      ULong rdxIn,   ULong raxIn,
     66                      ULong memHiIn, ULong memLoIn,
     67                      ULong rcxIn,   ULong rbxIn )
     68 {
     69    ULong mem[2] __attribute__((aligned(16)));
     70    ULong block[6];
     71    mem[0] = memLoIn;
     72    mem[1] = memHiIn;
     73    block[0] = rdxIn;
     74    block[1] = raxIn;
     75    block[2] = rcxIn;
     76    block[3] = rbxIn;
     77    block[4] = (ULong)&mem[0];
     78    block[5] = ~(0ULL);
     79    __asm__ __volatile__(
     80           "movq %0,%%r11\n"
     81         "\tmovq  0(%%r11),%%rdx\n"
     82         "\tmovq  8(%%r11),%%rax\n"
     83         "\tmovq 16(%%r11),%%rcx\n"
     84         "\tmovq 24(%%r11),%%rbx\n"
     85         "\tmovq 32(%%r11),%%r10\n"
     86         "\t.byte 0xf0, 0x49, 0x0f, 0xc7, 0x0a\n" /* lock cmpxchg16b (%%r10) */
     87         "\tmovabsq $0,%%r10\n"
     88         "\tsetz %%r10b\n"
     89         "\tmovq %%r10,40(%%r11)\n"
     90         "\tmovq %%rdx,0(%%r11)\n"
     91         "\tmovq %%rax,8(%%r11)\n"
     92 	  : /*out*/
     93 	  : /*in*/ "r"(&block[0])
     94 	  : /*trash*/ "%r11", "%r10", "%rax", "%rbx", "%rcx", "%rdx",
     95                       "cc", "memory" );
     96     *rdxOut = block[0];
     97     *raxOut = block[1];
     98     *memLoOut = mem[0];
     99     *memHiOut = mem[1];
    100     *zOut = block[5];
    101 }
    102 
    103 void try16b ( ULong d, ULong a, ULong mHi, ULong mLo, ULong c, ULong b )
    104 {
    105    ULong dd, aa, mmHi, mmLo, zz;
    106    do_cmpxchg16b( &dd, &aa, &mmHi, &mmLo, &zz,
    107 		  d,a,mHi,mLo,c,b);
    108    printf("QQ d:a=%llx:%llx mem=%llx:%llx c:b=%llx:%llx "
    109           "-> z=%lld d:a=%llx:%llx mem=%llx:%llx\n",
    110 	  d,a, mHi,mLo, c,b, zz, dd,aa, mmHi,mmLo );
    111 }
    112 
    113 int main(void)
    114 {
    115    ULong z = 0xDEADBEEF00000000ULL;
    116 
    117    try8b( 0,1, 5,4, 3,2 );
    118    try8b( 0,1, 0,1, 3,2 );
    119 
    120    try8b( 0,1, 0,4, 3,2 );
    121    try8b( 0,1, 0,0, 3,2 );
    122 
    123    try8b( 0,1, 5,0, 3,2 );
    124    try8b( 0,1, 1,1, 3,2 );
    125 
    126    try8b( 0+z,1+z, 5+z,4+z, 3+z,2+z );
    127    try8b( 0+z,1+z, 0+z,1+z, 3+z,2+z );
    128 
    129    try8b( 0+z,1+z, 0+z,4+z, 3+z,2+z );
    130    try8b( 0+z,1+z, 0+z,0+z, 3+z,2+z );
    131 
    132    try8b( 0+z,1+z, 5+z,0+z, 3+z,2+z );
    133    try8b( 0+z,1+z, 1+z,1+z, 3+z,2+z );
    134 
    135    try16b( 0,1, 5,4, 3,2 );
    136    try16b( 0,1, 0,1, 3,2 );
    137 
    138    try16b( 0,1, 0,4, 3,2 );
    139    try16b( 0,1, 0,0, 3,2 );
    140 
    141    try16b( 0,1, 5,0, 3,2 );
    142    try16b( 0,1, 1,1, 3,2 );
    143 
    144    try16b( 0+z,1+z, 5+z,4+z, 3+z,2+z );
    145    try16b( 0+z,1+z, 0+z,1+z, 3+z,2+z );
    146 
    147    try16b( 0+z,1+z, 0+z,4+z, 3+z,2+z );
    148    try16b( 0+z,1+z, 0+z,0+z, 3+z,2+z );
    149 
    150    try16b( 0+z,1+z, 5+z,0+z, 3+z,2+z );
    151    try16b( 0+z,1+z, 1+z,1+z, 3+z,2+z );
    152 
    153    return 0;
    154 }
    155 
    156