Home | History | Annotate | Download | only in amd64
      1 
      2 #include <stdio.h>
      3 #include <stdlib.h>
      4 #include <assert.h>
      5 
      6 typedef unsigned long long int ULong;
      7 typedef unsigned int   UInt;
      8 typedef unsigned short UShort;
      9 typedef unsigned char  UChar;
     10 
     11 typedef signed int    Int;
     12 typedef signed short  Short;
     13 
     14 typedef signed long int  Word;
     15 
     16 /* ------------ MEM, Q ------------ */
     17 
     18 ULong btsq_mem ( char* base, Word bitno )
     19 {
     20    UChar res;
     21    __asm__
     22    __volatile__("btsq\t%2, %0\n\t"
     23                 "setc\t%1"
     24                 : "=m" (*base), "=q" (res)
     25                 : "r" (bitno));
     26    /* Pretty meaningless to dereference base here, but that's what you
     27       have to do to get a btsl insn which refers to memory starting at
     28       base. */
     29    return res;
     30 }
     31 
     32 ULong btrq_mem ( char* base, Word bitno )
     33 {
     34    UChar res;
     35    __asm__
     36    __volatile__("btrq\t%2, %0\n\t"
     37                 "setc\t%1"
     38                 : "=m" (*base), "=q" (res)
     39                 : "r" (bitno));
     40    return res;
     41 }
     42 
     43 ULong btcq_mem ( char* base, Word bitno )
     44 {
     45    UChar res;
     46    __asm__
     47    __volatile__("btcq\t%2, %0\n\t"
     48                 "setc\t%1"
     49                 : "=m" (*base), "=q" (res)
     50                 : "r" (bitno));
     51    return res;
     52 }
     53 
     54 ULong btq_mem ( char* base, Word bitno )
     55 {
     56    UChar res;
     57    __asm__
     58    __volatile__("btq\t%2, %0\n\t"
     59                 "setc\t%1"
     60                 : "=m" (*base), "=q" (res)
     61                 : "r" (bitno)
     62                 : "cc", "memory");
     63    return res;
     64 }
     65 
     66 
     67 /* ------------ MEM, L ------------ */
     68 
     69 ULong btsl_mem ( char* base, Word bitno )
     70 {
     71    UChar res;
     72    __asm__
     73    __volatile__("btsl\t%2, %0\n\t"
     74                 "setc\t%1"
     75                 : "=m" (*base), "=q" (res)
     76                 : "r" ((Int)bitno));
     77    /* Pretty meaningless to dereference base here, but that's what you
     78       have to do to get a btsl insn which refers to memory starting at
     79       base. */
     80    return res;
     81 }
     82 
     83 ULong btrl_mem ( char* base, Word bitno )
     84 {
     85    UChar res;
     86    __asm__
     87    __volatile__("btrl\t%2, %0\n\t"
     88                 "setc\t%1"
     89                 : "=m" (*base), "=q" (res)
     90                 : "r" ((Int)bitno));
     91    return res;
     92 }
     93 
     94 ULong btcl_mem ( char* base, Word bitno )
     95 {
     96    UChar res;
     97    __asm__
     98    __volatile__("btcl\t%2, %0\n\t"
     99                 "setc\t%1"
    100                 : "=m" (*base), "=q" (res)
    101                 : "r" ((Int)bitno));
    102    return res;
    103 }
    104 
    105 ULong btl_mem ( char* base, Word bitno )
    106 {
    107    UChar res;
    108    __asm__
    109    __volatile__("btl\t%2, %0\n\t"
    110                 "setc\t%1"
    111                 : "=m" (*base), "=q" (res)
    112                 : "r" ((Int)bitno)
    113                 : "cc", "memory");
    114    return res;
    115 }
    116 
    117 
    118 
    119 /* ------------ MEM, W ------------ */
    120 
    121 ULong btsw_mem ( char* base, Word bitno )
    122 {
    123    UChar res;
    124    __asm__
    125    __volatile__("btsw\t%2, %0\n\t"
    126                 "setc\t%1"
    127                 : "=m" (*base), "=q" (res)
    128                 : "r" ((Short)bitno));
    129    /* Pretty meaningless to dereference base here, but that's what you
    130       have to do to get a btsl insn which refers to memory starting at
    131       base. */
    132    return res;
    133 }
    134 
    135 ULong btrw_mem ( char* base, Word bitno )
    136 {
    137    UChar res;
    138    __asm__
    139    __volatile__("btrw\t%2, %0\n\t"
    140                 "setc\t%1"
    141                 : "=m" (*base), "=q" (res)
    142                 : "r" ((Short)bitno));
    143    return res;
    144 }
    145 
    146 ULong btcw_mem ( char* base, Word bitno )
    147 {
    148    UChar res;
    149    __asm__
    150    __volatile__("btcw\t%2, %0\n\t"
    151                 "setc\t%1"
    152                 : "=m" (*base), "=q" (res)
    153                 : "r" ((Short)bitno));
    154    return res;
    155 }
    156 
    157 ULong btw_mem ( char* base, Word bitno )
    158 {
    159    UChar res;
    160    __asm__
    161    __volatile__("btw\t%2, %0\n\t"
    162                 "setc\t%1"
    163                 : "=m" (*base), "=q" (res)
    164                 : "r" ((Short)bitno)
    165                 : "cc", "memory");
    166    return res;
    167 }
    168 
    169 
    170 
    171 /* ------------ REG, Q ------------ */
    172 
    173 ULong btsq_reg ( ULong reg_in, Word bitno,
    174                         ULong* reg_out_p )
    175 {
    176    UChar res;
    177    ULong reg_out;
    178    __asm__
    179    __volatile__("movq\t%3, %%rax\n\t"
    180                 "btsq\t%2, %%rax\n\t"
    181                 "movq\t%%rax, %1\n\t"
    182                 "setc\t%0"
    183                 : "=q" (res), "=r" (reg_out)
    184                 : "r" (bitno), "r" (reg_in)
    185                 : "cc", "eax");
    186    *reg_out_p = reg_out;
    187    return res;
    188 }
    189 
    190 
    191 ULong btrq_reg ( ULong reg_in, Word bitno,
    192                         ULong* reg_out_p )
    193 {
    194    UChar res;
    195    ULong reg_out;
    196    __asm__
    197    __volatile__("movq\t%3, %%rax\n\t"
    198                 "btrq\t%2, %%rax\n\t"
    199                 "movq\t%%rax, %1\n\t"
    200                 "setc\t%0"
    201                 : "=q" (res), "=r" (reg_out)
    202                 : "r" (bitno), "r" (reg_in)
    203                 : "cc", "eax");
    204    *reg_out_p = reg_out;
    205    return res;
    206 }
    207 
    208 
    209 ULong btcq_reg ( ULong reg_in, Word bitno,
    210                         ULong* reg_out_p )
    211 {
    212    UChar res;
    213    ULong reg_out;
    214    __asm__
    215    __volatile__("movq\t%3, %%rax\n\t"
    216                 "btcq\t%2, %%rax\n\t"
    217                 "movq\t%%rax, %1\n\t"
    218                 "setc\t%0"
    219                 : "=q" (res), "=r" (reg_out)
    220                 : "r" (bitno), "r" (reg_in)
    221                 : "cc", "eax");
    222    *reg_out_p = reg_out;
    223    return res;
    224 }
    225 
    226 
    227 ULong btq_reg ( ULong reg_in, Word bitno,
    228                        ULong* reg_out_p )
    229 {
    230    UChar res;
    231    ULong reg_out;
    232    __asm__
    233    __volatile__("movq\t%3, %%rax\n\t"
    234                 "btq\t%2, %%rax\n\t"
    235                 "movq\t%%rax, %1\n\t"
    236                 "setc\t%0"
    237                 : "=q" (res), "=r" (reg_out)
    238                 : "r" (bitno), "r" (reg_in)
    239                 : "cc", "eax");
    240    *reg_out_p = reg_out;
    241    return res;
    242 }
    243 
    244 
    245 
    246 /* ------------ REG, L ------------ */
    247 
    248 ULong btsl_reg ( ULong reg_in, Word bitno,
    249                         ULong* reg_out_p )
    250 {
    251    UChar res;
    252    ULong reg_out;
    253    __asm__
    254    __volatile__("movq\t%3, %%rax\n\t"
    255                 "btsl\t%2, %%eax\n\t"
    256                 "movq\t%%rax, %1\n\t"
    257                 "setc\t%0"
    258                 : "=q" (res), "=r" (reg_out)
    259                 : "r" ((Int)bitno), "r" (reg_in)
    260                 : "cc", "eax");
    261    *reg_out_p = reg_out;
    262    return res;
    263 }
    264 
    265 
    266 ULong btrl_reg ( ULong reg_in, Word bitno,
    267                         ULong* reg_out_p )
    268 {
    269    UChar res;
    270    ULong reg_out;
    271    __asm__
    272    __volatile__("movq\t%3, %%rax\n\t"
    273                 "btrl\t%2, %%eax\n\t"
    274                 "movq\t%%rax, %1\n\t"
    275                 "setc\t%0"
    276                 : "=q" (res), "=r" (reg_out)
    277                 : "r" ((Int)bitno), "r" (reg_in)
    278                 : "cc", "eax");
    279    *reg_out_p = reg_out;
    280    return res;
    281 }
    282 
    283 
    284 ULong btcl_reg ( ULong reg_in, Word bitno,
    285                         ULong* reg_out_p )
    286 {
    287    UChar res;
    288    ULong reg_out;
    289    __asm__
    290    __volatile__("movq\t%3, %%rax\n\t"
    291                 "btcl\t%2, %%eax\n\t"
    292                 "movq\t%%rax, %1\n\t"
    293                 "setc\t%0"
    294                 : "=q" (res), "=r" (reg_out)
    295                 : "r" ((Int)bitno), "r" (reg_in)
    296                 : "cc", "eax");
    297    *reg_out_p = reg_out;
    298    return res;
    299 }
    300 
    301 
    302 ULong btl_reg ( ULong reg_in, Word bitno,
    303                        ULong* reg_out_p )
    304 {
    305    UChar res;
    306    ULong reg_out;
    307    __asm__
    308    __volatile__("movq\t%3, %%rax\n\t"
    309                 "btl\t%2, %%eax\n\t"
    310                 "movq\t%%rax, %1\n\t"
    311                 "setc\t%0"
    312                 : "=q" (res), "=r" (reg_out)
    313                 : "r" ((Int)bitno), "r" (reg_in)
    314                 : "cc", "eax");
    315    *reg_out_p = reg_out;
    316    return res;
    317 }
    318 
    319 
    320 
    321 /* ------------ REG, W ------------ */
    322 
    323 ULong btsw_reg ( ULong reg_in, Word bitno,
    324                         ULong* reg_out_p )
    325 {
    326    UChar res;
    327    ULong reg_out;
    328    __asm__
    329    __volatile__("movq\t%3, %%rax\n\t"
    330                 "btsw\t%2, %%ax\n\t"
    331                 "movq\t%%rax, %1\n\t"
    332                 "setc\t%0"
    333                 : "=q" (res), "=r" (reg_out)
    334                 : "r" ((Short)bitno), "r" (reg_in)
    335                 : "cc", "eax");
    336    *reg_out_p = reg_out;
    337    return res;
    338 }
    339 
    340 
    341 ULong btrw_reg ( ULong reg_in, Word bitno,
    342                         ULong* reg_out_p )
    343 {
    344    UChar res;
    345    ULong reg_out;
    346    __asm__
    347    __volatile__("movq\t%3, %%rax\n\t"
    348                 "btrw\t%2, %%ax\n\t"
    349                 "movq\t%%rax, %1\n\t"
    350                 "setc\t%0"
    351                 : "=q" (res), "=r" (reg_out)
    352                 : "r" ((Short)bitno), "r" (reg_in)
    353                 : "cc", "eax");
    354    *reg_out_p = reg_out;
    355    return res;
    356 }
    357 
    358 
    359 ULong btcw_reg ( ULong reg_in, Word bitno,
    360                         ULong* reg_out_p )
    361 {
    362    UChar res;
    363    ULong reg_out;
    364    __asm__
    365    __volatile__("movq\t%3, %%rax\n\t"
    366                 "btcw\t%2, %%ax\n\t"
    367                 "movq\t%%rax, %1\n\t"
    368                 "setc\t%0"
    369                 : "=q" (res), "=r" (reg_out)
    370                 : "r" ((Short)bitno), "r" (reg_in)
    371                 : "cc", "eax");
    372    *reg_out_p = reg_out;
    373    return res;
    374 }
    375 
    376 
    377 ULong btw_reg ( ULong reg_in, Word bitno,
    378                        ULong* reg_out_p )
    379 {
    380    UChar res;
    381    ULong reg_out;
    382    __asm__
    383    __volatile__("movq\t%3, %%rax\n\t"
    384                 "btw\t%2, %%ax\n\t"
    385                 "movq\t%%rax, %1\n\t"
    386                 "setc\t%0"
    387                 : "=q" (res), "=r" (reg_out)
    388                 : "r" ((Short)bitno), "r" (reg_in)
    389                 : "cc", "eax");
    390    *reg_out_p = reg_out;
    391    return res;
    392 }
    393 
    394 
    395 
    396 
    397 
    398 
    399 
    400 ULong rol1 ( ULong x )
    401 {
    402   return (x << 1) | (x >> 63);
    403 }
    404 
    405 int main ( void )
    406 {
    407    UInt   n, op;
    408    ULong  carrydep, c, res;
    409    UChar* block;
    410    ULong  reg;
    411    Word   bitoff;
    412 
    413    /*------------------------ MEM-L -----------------------*/
    414 
    415    carrydep = 0;
    416    block = calloc(200,1);
    417    block += 100;
    418    /* Valid bit offsets are -800 .. 799 inclusive. */
    419 
    420    for (n = 0; n < 10000; n++) {
    421       bitoff = (random() % 1600) - 800;
    422       op = random() % 12;
    423       c = 2;
    424       switch (op) {
    425          case  0: c = btsl_mem(block, bitoff); break;
    426          case  1: c = btrl_mem(block, bitoff); break;
    427          case  2: c = btcl_mem(block, bitoff); break;
    428          case  3: c =  btl_mem(block, bitoff); break;
    429          case  4: c = btsq_mem(block, bitoff); break;
    430          case  5: c = btrq_mem(block, bitoff); break;
    431          case  6: c = btcq_mem(block, bitoff); break;
    432          case  7: c =  btq_mem(block, bitoff); break;
    433          case  8: c = btsw_mem(block, bitoff); break;
    434          case  9: c = btrw_mem(block, bitoff); break;
    435          case 10: c = btcw_mem(block, bitoff); break;
    436          case 11: c =  btw_mem(block, bitoff); break;
    437          default: assert(0);
    438       }
    439       assert(c == 0 || c == 1);
    440       carrydep = c ? (rol1(carrydep) ^ bitoff) : carrydep;
    441    }
    442 
    443    /* Compute final result */
    444    block -= 100;
    445    res = 0;
    446    for (n = 0; n < 200; n++) {
    447       UChar ch = block[n];
    448       /* printf("%d ", (int)block[n]); */
    449       res = rol1(res) ^ (UInt)ch;
    450    }
    451 
    452    printf("MEM-L: final res 0x%llx, carrydep 0x%llx\n", res, carrydep);
    453 
    454    /*------------------------ REG-L -----------------------*/
    455 
    456    carrydep = 0;
    457    reg = 0;
    458 
    459    for (n = 0; n < 1000; n++) {
    460       bitoff = (random() % 100) - 50;
    461       op = random() % 12;
    462       c = 2;
    463       switch (op) {
    464          case  0: c = btsl_reg(reg, bitoff, &reg); break;
    465          case  1: c = btrl_reg(reg, bitoff, &reg); break;
    466          case  2: c = btcl_reg(reg, bitoff, &reg); break;
    467          case  3: c =  btl_reg(reg, bitoff, &reg); break;
    468          case  4: c = btsq_reg(reg, bitoff, &reg); break;
    469          case  5: c = btrq_reg(reg, bitoff, &reg); break;
    470          case  6: c = btcq_reg(reg, bitoff, &reg); break;
    471          case  7: c =  btq_reg(reg, bitoff, &reg); break;
    472          case  8: c = btsw_reg(reg, bitoff, &reg); break;
    473          case  9: c = btrw_reg(reg, bitoff, &reg); break;
    474          case 10: c = btcw_reg(reg, bitoff, &reg); break;
    475          case 11: c =  btw_reg(reg, bitoff, &reg); break;
    476          default: assert(0);
    477       }
    478       assert(c == 0 || c == 1);
    479       carrydep = c ? (rol1(carrydep) ^ bitoff) : carrydep;
    480    }
    481 
    482    printf("REG-L: final res 0x%llx, carrydep 0x%llx\n", reg, carrydep);
    483 
    484    block += 100;
    485 
    486    /* Just try one of these at once; more than one can cause a
    487       confusing merging of error messages. */
    488    //btsl_mem(block, -800);  /* should not complain */
    489    //btsl_mem(block, -801);  /* should complain */
    490    //btsl_mem(block, 799);   /* should not complain */
    491    //btsl_mem(block, 800);   /* should complain */
    492 
    493    block -= 100;
    494    free(block);
    495 
    496    return 0;
    497 }
    498 
    499