Home | History | Annotate | Download | only in x86
      1 
      2 #include <stdio.h>
      3 #include <stdlib.h>
      4 #include <assert.h>
      5 
      6 
      7 unsigned int btsl_mem ( char* base, int bitno )
      8 {
      9    unsigned char res;
     10    __asm__
     11    __volatile__("btsl\t%2, %0\n\t"
     12                 "setc\t%1"
     13                 : "=m" (*base), "=q" (res)
     14                 : "r" (bitno));
     15    /* Pretty meaningless to dereference base here, but that's what you
     16       have to do to get a btsl insn which refers to memory starting at
     17       base. */
     18    return res;
     19 }
     20 
     21 unsigned int btrl_mem ( char* base, int bitno )
     22 {
     23    unsigned char res;
     24    __asm__
     25    __volatile__("btrl\t%2, %0\n\t"
     26                 "setc\t%1"
     27                 : "=m" (*base), "=q" (res)
     28                 : "r" (bitno));
     29    return res;
     30 }
     31 
     32 unsigned int btcl_mem ( char* base, int bitno )
     33 {
     34    unsigned char res;
     35    __asm__
     36    __volatile__("btcl\t%2, %0\n\t"
     37                 "setc\t%1"
     38                 : "=m" (*base), "=q" (res)
     39                 : "r" (bitno));
     40    return res;
     41 }
     42 
     43 unsigned int btl_mem ( char* base, int bitno )
     44 {
     45    unsigned char res;
     46    __asm__
     47    __volatile__("btl\t%2, %0\n\t"
     48                 "setc\t%1"
     49                 : "=m" (*base), "=q" (res)
     50                 : "r" (bitno)
     51                 : "cc", "memory");
     52    return res;
     53 }
     54 
     55 
     56 
     57 
     58 unsigned int btsl_reg ( unsigned int reg_in, int bitno,
     59                         unsigned int* reg_out_p )
     60 {
     61    unsigned char res;
     62    unsigned int reg_out;
     63    __asm__
     64    __volatile__("movl\t%3, %%eax\n\t"
     65                 "btsl\t%2, %%eax\n\t"
     66                 "movl\t%%eax, %1\n\t"
     67                 "setc\t%0"
     68                 : "=q" (res), "=r" (reg_out)
     69                 : "r" (bitno), "r" (reg_in)
     70                 : "cc", "eax");
     71    *reg_out_p = reg_out;
     72    return res;
     73 }
     74 
     75 
     76 unsigned int btrl_reg ( unsigned int reg_in, int bitno,
     77                         unsigned int* reg_out_p )
     78 {
     79    unsigned char res;
     80    unsigned int reg_out;
     81    __asm__
     82    __volatile__("movl\t%3, %%eax\n\t"
     83                 "btrl\t%2, %%eax\n\t"
     84                 "movl\t%%eax, %1\n\t"
     85                 "setc\t%0"
     86                 : "=q" (res), "=r" (reg_out)
     87                 : "r" (bitno), "r" (reg_in)
     88                 : "cc", "eax");
     89    *reg_out_p = reg_out;
     90    return res;
     91 }
     92 
     93 
     94 unsigned int btcl_reg ( unsigned int reg_in, int bitno,
     95                         unsigned int* reg_out_p )
     96 {
     97    unsigned char res;
     98    unsigned int reg_out;
     99    __asm__
    100    __volatile__("movl\t%3, %%eax\n\t"
    101                 "btcl\t%2, %%eax\n\t"
    102                 "movl\t%%eax, %1\n\t"
    103                 "setc\t%0"
    104                 : "=q" (res), "=r" (reg_out)
    105                 : "r" (bitno), "r" (reg_in)
    106                 : "cc", "eax");
    107    *reg_out_p = reg_out;
    108    return res;
    109 }
    110 
    111 
    112 unsigned int btl_reg ( unsigned int reg_in, int bitno,
    113                        unsigned int* reg_out_p )
    114 {
    115    unsigned char res;
    116    unsigned int reg_out;
    117    __asm__
    118    __volatile__("movl\t%3, %%eax\n\t"
    119                 "btl\t%2, %%eax\n\t"
    120                 "movl\t%%eax, %1\n\t"
    121                 "setc\t%0"
    122                 : "=q" (res), "=r" (reg_out)
    123                 : "r" (bitno), "r" (reg_in)
    124                 : "cc", "eax");
    125    *reg_out_p = reg_out;
    126    return res;
    127 }
    128 
    129 
    130 
    131 
    132 
    133 
    134 
    135 typedef unsigned int UInt;
    136 typedef unsigned char UChar;
    137 
    138 UInt rol1 ( UInt x )
    139 {
    140   return (x << 1) | (x >> 31);
    141 }
    142 
    143 int main ( void )
    144 {
    145    UInt   n, bitoff, op;
    146    UInt   carrydep, c, res;
    147    UChar* block;
    148    UInt   reg;
    149 
    150    /*------------------------ MEM-L -----------------------*/
    151 
    152    carrydep = 0;
    153    block = calloc(200,1);
    154    block += 100;
    155    /* Valid bit offsets are -800 .. 799 inclusive. */
    156 
    157    for (n = 0; n < 10000; n++) {
    158       bitoff = (random() % 1600) - 800;
    159       op = random() % 4;
    160       c = 2;
    161       switch (op) {
    162          case 0: c = btsl_mem(block, bitoff); break;
    163          case 1: c = btrl_mem(block, bitoff); break;
    164          case 2: c = btcl_mem(block, bitoff); break;
    165          case 3: c = btl_mem(block, bitoff); break;
    166       }
    167       assert(c == 0 || c == 1);
    168       carrydep = c ? (rol1(carrydep) ^ bitoff) : carrydep;
    169    }
    170 
    171    /* Compute final result */
    172    block -= 100;
    173    res = 0;
    174    for (n = 0; n < 200; n++) {
    175       UChar ch = block[n];
    176       /* printf("%d ", (int)block[n]); */
    177       res = rol1(res) ^ (UInt)ch;
    178    }
    179 
    180    printf("MEM-L: final res 0x%x, carrydep 0x%x\n", res, carrydep);
    181 
    182    /*------------------------ REG-L -----------------------*/
    183 
    184    carrydep = 0;
    185    reg = 0;
    186 
    187    for (n = 0; n < 1000; n++) {
    188       bitoff = (random() % 100) - 50;
    189       op = random() % 4;
    190       c = 2;
    191       switch (op) {
    192          case 0: c = btsl_reg(reg, bitoff, &reg); break;
    193          case 1: c = btrl_reg(reg, bitoff, &reg); break;
    194          case 2: c = btcl_reg(reg, bitoff, &reg); break;
    195          case 3: c = btl_reg(reg, bitoff, &reg); break;
    196       }
    197       assert(c == 0 || c == 1);
    198       carrydep = c ? (rol1(carrydep) ^ bitoff) : carrydep;
    199    }
    200 
    201    printf("REG-L: final res 0x%x, carrydep 0x%x\n", reg, carrydep);
    202 
    203    block += 100;
    204 
    205    /* Just try one of these at once; more than one can cause a
    206       confusing merging of error messages. */
    207    //btsl_mem(block, -800);  /* should not complain */
    208    //btsl_mem(block, -801);  /* should complain */
    209    //btsl_mem(block, 799);   /* should not complain */
    210    //btsl_mem(block, 800);   /* should complain */
    211 
    212    block -= 100;
    213    free(block);
    214 
    215    return 0;
    216 }
    217 
    218