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, ®); break;
193 case 1: c = btrl_reg(reg, bitoff, ®); break;
194 case 2: c = btcl_reg(reg, bitoff, ®); break;
195 case 3: c = btl_reg(reg, bitoff, ®); 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