1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <stdio.h>
3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <stdlib.h>
4ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <assert.h>
5ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef unsigned long long int ULong;
7ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef unsigned int   UInt;
8ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef unsigned short UShort;
9ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef unsigned char  UChar;
10ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
11ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef signed int    Int;
12ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef signed short  Short;
13ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
14ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef signed long int  Word;
15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ------------ MEM, Q ------------ */
17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong btsq_mem ( char* base, Word bitno )
19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar res;
21ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   __asm__
22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   __volatile__("btsq\t%2, %0\n\t"
23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                "setc\t%1"
24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                : "=m" (*base), "=q" (res)
25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                : "r" (bitno));
26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Pretty meaningless to dereference base here, but that's what you
27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      have to do to get a btsl insn which refers to memory starting at
28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      base. */
29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return res;
30ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
32ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong btrq_mem ( char* base, Word bitno )
33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar res;
35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   __asm__
36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   __volatile__("btrq\t%2, %0\n\t"
37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                "setc\t%1"
38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                : "=m" (*base), "=q" (res)
39ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                : "r" (bitno));
40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return res;
41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong btcq_mem ( char* base, Word bitno )
44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar res;
46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   __asm__
47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   __volatile__("btcq\t%2, %0\n\t"
48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                "setc\t%1"
49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                : "=m" (*base), "=q" (res)
50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                : "r" (bitno));
51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return res;
52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong btq_mem ( char* base, Word bitno )
55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar res;
57ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   __asm__
58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   __volatile__("btq\t%2, %0\n\t"
59ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                "setc\t%1"
60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                : "=m" (*base), "=q" (res)
61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                : "r" (bitno)
62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                : "cc", "memory");
63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return res;
64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ------------ MEM, L ------------ */
68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
69ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong btsl_mem ( char* base, Word bitno )
70ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
71ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar res;
72ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   __asm__
73ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   __volatile__("btsl\t%2, %0\n\t"
74ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                "setc\t%1"
75ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                : "=m" (*base), "=q" (res)
76ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                : "r" ((Int)bitno));
77ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Pretty meaningless to dereference base here, but that's what you
78ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      have to do to get a btsl insn which refers to memory starting at
79ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      base. */
80ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return res;
81ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
82ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
83ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong btrl_mem ( char* base, Word bitno )
84ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
85ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar res;
86ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   __asm__
87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   __volatile__("btrl\t%2, %0\n\t"
88ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                "setc\t%1"
89ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                : "=m" (*base), "=q" (res)
90ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                : "r" ((Int)bitno));
91ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return res;
92ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
93ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
94ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong btcl_mem ( char* base, Word bitno )
95ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
96ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar res;
97ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   __asm__
98ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   __volatile__("btcl\t%2, %0\n\t"
99ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                "setc\t%1"
100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                : "=m" (*base), "=q" (res)
101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                : "r" ((Int)bitno));
102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return res;
103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong btl_mem ( char* base, Word bitno )
106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar res;
108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   __asm__
109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   __volatile__("btl\t%2, %0\n\t"
110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                "setc\t%1"
111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                : "=m" (*base), "=q" (res)
112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                : "r" ((Int)bitno)
113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                : "cc", "memory");
114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return res;
115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ------------ MEM, W ------------ */
120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong btsw_mem ( char* base, Word bitno )
122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar res;
124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   __asm__
125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   __volatile__("btsw\t%2, %0\n\t"
126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                "setc\t%1"
127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                : "=m" (*base), "=q" (res)
128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                : "r" ((Short)bitno));
129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Pretty meaningless to dereference base here, but that's what you
130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      have to do to get a btsl insn which refers to memory starting at
131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      base. */
132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return res;
133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong btrw_mem ( char* base, Word bitno )
136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar res;
138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   __asm__
139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   __volatile__("btrw\t%2, %0\n\t"
140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                "setc\t%1"
141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                : "=m" (*base), "=q" (res)
142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                : "r" ((Short)bitno));
143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return res;
144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong btcw_mem ( char* base, Word bitno )
147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar res;
149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   __asm__
150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   __volatile__("btcw\t%2, %0\n\t"
151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                "setc\t%1"
152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                : "=m" (*base), "=q" (res)
153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                : "r" ((Short)bitno));
154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return res;
155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong btw_mem ( char* base, Word bitno )
158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar res;
160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   __asm__
161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   __volatile__("btw\t%2, %0\n\t"
162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                "setc\t%1"
163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                : "=m" (*base), "=q" (res)
164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                : "r" ((Short)bitno)
165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                : "cc", "memory");
166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return res;
167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ------------ REG, Q ------------ */
172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong btsq_reg ( ULong reg_in, Word bitno,
174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        ULong* reg_out_p )
175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar res;
177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ULong reg_out;
178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   __asm__
179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   __volatile__("movq\t%3, %%rax\n\t"
180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                "btsq\t%2, %%rax\n\t"
181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                "movq\t%%rax, %1\n\t"
182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                "setc\t%0"
183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                : "=q" (res), "=r" (reg_out)
184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                : "r" (bitno), "r" (reg_in)
185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                : "cc", "eax");
186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *reg_out_p = reg_out;
187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return res;
188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong btrq_reg ( ULong reg_in, Word bitno,
192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        ULong* reg_out_p )
193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar res;
195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ULong reg_out;
196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   __asm__
197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   __volatile__("movq\t%3, %%rax\n\t"
198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                "btrq\t%2, %%rax\n\t"
199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                "movq\t%%rax, %1\n\t"
200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                "setc\t%0"
201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                : "=q" (res), "=r" (reg_out)
202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                : "r" (bitno), "r" (reg_in)
203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                : "cc", "eax");
204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *reg_out_p = reg_out;
205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return res;
206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownULong btcq_reg ( ULong reg_in, Word bitno,
210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        ULong* reg_out_p )
211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar res;
213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ULong reg_out;
214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   __asm__
215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   __volatile__("movq\t%3, %%rax\n\t"
216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                "btcq\t%2, %%rax\n\t"
217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                "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
227ULong 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
248ULong 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
266ULong 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
284ULong 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
302ULong 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
323ULong 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
341ULong 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
359ULong 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
377ULong 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
400ULong rol1 ( ULong x )
401{
402  return (x << 1) | (x >> 63);
403}
404
405int main ( void )
406{
407   UInt   n, op;
408   ULong  carrydep, c, res;
409   UChar* 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