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 
btsq_mem(char * base,Word bitno)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 
btrq_mem(char * base,Word bitno)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 
btcq_mem(char * base,Word bitno)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 
btq_mem(char * base,Word bitno)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 
btsl_mem(char * base,Word bitno)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 
btrl_mem(char * base,Word bitno)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 
btcl_mem(char * base,Word bitno)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 
btl_mem(char * base,Word bitno)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 
btsw_mem(char * base,Word bitno)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 
btrw_mem(char * base,Word bitno)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 
btcw_mem(char * base,Word bitno)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 
btw_mem(char * base,Word bitno)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 
btsq_reg(ULong reg_in,Word bitno,ULong * reg_out_p)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 
btrq_reg(ULong reg_in,Word bitno,ULong * reg_out_p)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 
btcq_reg(ULong reg_in,Word bitno,ULong * reg_out_p)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 
btq_reg(ULong reg_in,Word bitno,ULong * reg_out_p)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 
btsl_reg(ULong reg_in,Word bitno,ULong * reg_out_p)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 
btrl_reg(ULong reg_in,Word bitno,ULong * reg_out_p)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 
btcl_reg(ULong reg_in,Word bitno,ULong * reg_out_p)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 
btl_reg(ULong reg_in,Word bitno,ULong * reg_out_p)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 
btsw_reg(ULong reg_in,Word bitno,ULong * reg_out_p)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 
btrw_reg(ULong reg_in,Word bitno,ULong * reg_out_p)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 
btcw_reg(ULong reg_in,Word bitno,ULong * reg_out_p)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 
btw_reg(ULong reg_in,Word bitno,ULong * reg_out_p)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 
rol1(ULong x)400 ULong rol1 ( ULong x )
401 {
402   return (x << 1) | (x >> 63);
403 }
404 
main(void)405 int main ( void )
406 {
407    UInt   n, op;
408    ULong  carrydep, c, res;
409    char*  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