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