6 typedef unsigned long long int ULong
;
7 typedef unsigned int UInt
;
8 typedef unsigned short UShort
;
9 typedef unsigned char UChar
;
11 typedef signed int Int
;
12 typedef signed short Short
;
14 typedef signed long int Word
;
16 unsigned long myrandom(void)
18 /* Simple multiply-with-carry random generator. */
19 static unsigned long m_w
= 11;
20 static unsigned long m_z
= 13;
22 m_z
= 36969 * (m_z
& 65535) + (m_z
>> 16);
23 m_w
= 18000 * (m_w
& 65535) + (m_w
>> 16);
25 return (m_z
<< 16) + m_w
;
28 /* ------------ MEM, Q ------------ */
30 ULong
btsq_mem ( char* base
, Word bitno
)
34 __volatile__("btsq\t%2, %0\n\t"
36 : "=m" (*base
), "=q" (res
)
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
44 ULong
btrq_mem ( char* base
, Word bitno
)
48 __volatile__("btrq\t%2, %0\n\t"
50 : "=m" (*base
), "=q" (res
)
55 ULong
btcq_mem ( char* base
, Word bitno
)
59 __volatile__("btcq\t%2, %0\n\t"
61 : "=m" (*base
), "=q" (res
)
66 ULong
btq_mem ( char* base
, Word bitno
)
70 __volatile__("btq\t%2, %0\n\t"
72 : "=m" (*base
), "=q" (res
)
79 /* ------------ MEM, L ------------ */
81 ULong
btsl_mem ( char* base
, Word bitno
)
85 __volatile__("btsl\t%2, %0\n\t"
87 : "=m" (*base
), "=q" (res
)
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
95 ULong
btrl_mem ( char* base
, Word bitno
)
99 __volatile__("btrl\t%2, %0\n\t"
101 : "=m" (*base
), "=q" (res
)
106 ULong
btcl_mem ( char* base
, Word bitno
)
110 __volatile__("btcl\t%2, %0\n\t"
112 : "=m" (*base
), "=q" (res
)
117 ULong
btl_mem ( char* base
, Word bitno
)
121 __volatile__("btl\t%2, %0\n\t"
123 : "=m" (*base
), "=q" (res
)
131 /* ------------ MEM, W ------------ */
133 ULong
btsw_mem ( char* base
, Word bitno
)
137 __volatile__("btsw\t%2, %0\n\t"
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
147 ULong
btrw_mem ( char* base
, Word bitno
)
151 __volatile__("btrw\t%2, %0\n\t"
153 : "=m" (*base
), "=q" (res
)
154 : "r" ((Short
)bitno
));
158 ULong
btcw_mem ( char* base
, Word bitno
)
162 __volatile__("btcw\t%2, %0\n\t"
164 : "=m" (*base
), "=q" (res
)
165 : "r" ((Short
)bitno
));
169 ULong
btw_mem ( char* base
, Word bitno
)
173 __volatile__("btw\t%2, %0\n\t"
175 : "=m" (*base
), "=q" (res
)
183 /* ------------ REG, Q ------------ */
185 ULong
btsq_reg ( ULong reg_in
, Word bitno
,
191 __volatile__("movq\t%3, %%rax\n\t"
192 "btsq\t%2, %%rax\n\t"
193 "movq\t%%rax, %1\n\t"
195 : "=q" (res
), "=r" (reg_out
)
196 : "r" (bitno
), "r" (reg_in
)
198 *reg_out_p
= reg_out
;
203 ULong
btrq_reg ( ULong reg_in
, Word bitno
,
209 __volatile__("movq\t%3, %%rax\n\t"
210 "btrq\t%2, %%rax\n\t"
211 "movq\t%%rax, %1\n\t"
213 : "=q" (res
), "=r" (reg_out
)
214 : "r" (bitno
), "r" (reg_in
)
216 *reg_out_p
= reg_out
;
221 ULong
btcq_reg ( ULong reg_in
, Word bitno
,
227 __volatile__("movq\t%3, %%rax\n\t"
228 "btcq\t%2, %%rax\n\t"
229 "movq\t%%rax, %1\n\t"
231 : "=q" (res
), "=r" (reg_out
)
232 : "r" (bitno
), "r" (reg_in
)
234 *reg_out_p
= reg_out
;
239 ULong
btq_reg ( ULong reg_in
, Word bitno
,
245 __volatile__("movq\t%3, %%rax\n\t"
247 "movq\t%%rax, %1\n\t"
249 : "=q" (res
), "=r" (reg_out
)
250 : "r" (bitno
), "r" (reg_in
)
252 *reg_out_p
= reg_out
;
258 /* ------------ REG, L ------------ */
260 ULong
btsl_reg ( ULong reg_in
, Word bitno
,
266 __volatile__("movq\t%3, %%rax\n\t"
267 "btsl\t%2, %%eax\n\t"
268 "movq\t%%rax, %1\n\t"
270 : "=q" (res
), "=r" (reg_out
)
271 : "r" ((Int
)bitno
), "r" (reg_in
)
273 *reg_out_p
= reg_out
;
278 ULong
btrl_reg ( ULong reg_in
, Word bitno
,
284 __volatile__("movq\t%3, %%rax\n\t"
285 "btrl\t%2, %%eax\n\t"
286 "movq\t%%rax, %1\n\t"
288 : "=q" (res
), "=r" (reg_out
)
289 : "r" ((Int
)bitno
), "r" (reg_in
)
291 *reg_out_p
= reg_out
;
296 ULong
btcl_reg ( ULong reg_in
, Word bitno
,
302 __volatile__("movq\t%3, %%rax\n\t"
303 "btcl\t%2, %%eax\n\t"
304 "movq\t%%rax, %1\n\t"
306 : "=q" (res
), "=r" (reg_out
)
307 : "r" ((Int
)bitno
), "r" (reg_in
)
309 *reg_out_p
= reg_out
;
314 ULong
btl_reg ( ULong reg_in
, Word bitno
,
320 __volatile__("movq\t%3, %%rax\n\t"
322 "movq\t%%rax, %1\n\t"
324 : "=q" (res
), "=r" (reg_out
)
325 : "r" ((Int
)bitno
), "r" (reg_in
)
327 *reg_out_p
= reg_out
;
333 /* ------------ REG, W ------------ */
335 ULong
btsw_reg ( ULong reg_in
, Word bitno
,
341 __volatile__("movq\t%3, %%rax\n\t"
343 "movq\t%%rax, %1\n\t"
345 : "=q" (res
), "=r" (reg_out
)
346 : "r" ((Short
)bitno
), "r" (reg_in
)
348 *reg_out_p
= reg_out
;
353 ULong
btrw_reg ( ULong reg_in
, Word bitno
,
359 __volatile__("movq\t%3, %%rax\n\t"
361 "movq\t%%rax, %1\n\t"
363 : "=q" (res
), "=r" (reg_out
)
364 : "r" ((Short
)bitno
), "r" (reg_in
)
366 *reg_out_p
= reg_out
;
371 ULong
btcw_reg ( ULong reg_in
, Word bitno
,
377 __volatile__("movq\t%3, %%rax\n\t"
379 "movq\t%%rax, %1\n\t"
381 : "=q" (res
), "=r" (reg_out
)
382 : "r" ((Short
)bitno
), "r" (reg_in
)
384 *reg_out_p
= reg_out
;
389 ULong
btw_reg ( ULong reg_in
, Word bitno
,
395 __volatile__("movq\t%3, %%rax\n\t"
397 "movq\t%%rax, %1\n\t"
399 : "=q" (res
), "=r" (reg_out
)
400 : "r" ((Short
)bitno
), "r" (reg_in
)
402 *reg_out_p
= reg_out
;
412 ULong
rol1 ( ULong x
)
414 return (x
<< 1) | (x
>> 63);
420 ULong carrydep
, c
, res
;
425 /*------------------------ MEM-L -----------------------*/
428 block
= calloc(200,1);
430 /* Valid bit offsets are -800 .. 799 inclusive. */
432 for (n
= 0; n
< 10000; n
++) {
433 bitoff
= (myrandom() % 1600) - 800;
434 op
= myrandom() % 12;
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;
451 assert(c
== 0 || c
== 1);
452 carrydep
= c
? (rol1(carrydep
) ^ bitoff
) : carrydep
;
455 /* Compute final result */
458 for (n
= 0; n
< 200; n
++) {
460 /* printf("%d ", (int)block[n]); */
461 res
= rol1(res
) ^ (UInt
)ch
;
464 printf("MEM-L: final res 0x%llx, carrydep 0x%llx\n", res
, carrydep
);
466 /*------------------------ REG-L -----------------------*/
471 for (n
= 0; n
< 1000; n
++) {
472 bitoff
= (myrandom() % 100) - 50;
473 op
= myrandom() % 12;
476 case 0: c
= btsl_reg(reg
, bitoff
, ®
); break;
477 case 1: c
= btrl_reg(reg
, bitoff
, ®
); break;
478 case 2: c
= btcl_reg(reg
, bitoff
, ®
); break;
479 case 3: c
= btl_reg(reg
, bitoff
, ®
); break;
480 case 4: c
= btsq_reg(reg
, bitoff
, ®
); break;
481 case 5: c
= btrq_reg(reg
, bitoff
, ®
); break;
482 case 6: c
= btcq_reg(reg
, bitoff
, ®
); break;
483 case 7: c
= btq_reg(reg
, bitoff
, ®
); break;
484 case 8: c
= btsw_reg(reg
, bitoff
, ®
); break;
485 case 9: c
= btrw_reg(reg
, bitoff
, ®
); break;
486 case 10: c
= btcw_reg(reg
, bitoff
, ®
); break;
487 case 11: c
= btw_reg(reg
, bitoff
, ®
); break;
490 assert(c
== 0 || c
== 1);
491 carrydep
= c
? (rol1(carrydep
) ^ bitoff
) : carrydep
;
494 printf("REG-L: final res 0x%llx, carrydep 0x%llx\n", reg
, carrydep
);
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 */