• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <assert.h>
5 
6 
btsl_mem(char * base,int bitno)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 
btrl_mem(char * base,int bitno)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 
btcl_mem(char * base,int bitno)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 
btl_mem(char * base,int bitno)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 
btsl_reg(unsigned int reg_in,int bitno,unsigned int * reg_out_p)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 
btrl_reg(unsigned int reg_in,int bitno,unsigned int * reg_out_p)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 
btcl_reg(unsigned int reg_in,int bitno,unsigned int * reg_out_p)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 
btl_reg(unsigned int reg_in,int bitno,unsigned int * reg_out_p)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 
rol1(UInt x)138 UInt rol1 ( UInt x )
139 {
140   return (x << 1) | (x >> 31);
141 }
142 
main(void)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