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