• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 /* This is a test program that checks the parsing of instructions with
3    xacquire and xrelease prefixes.  The tested insns are, afaics,
4    exactly those listed in the Intel description for the two prefixes
5    ("XACQUIRE/XRELEASE -- Hardware Lock Elision Prefix Hints"). */
6 
7 #include <stdio.h>
8 
9 typedef  unsigned long long int  ULong;
10 
11 #define CAT2(_x,_y) _x##_y
12 #define CAT(_x,_y) CAT2(_x,_y)
13 
14 #define GEN_BINARY(_insn) \
15    void CAT(do_,_insn) ( void ) \
16    { \
17       volatile ULong n = 0x5555555555555555ULL; \
18       ULong some = 0x271831415927D459ULL; \
19       __asm__ __volatile__( \
20          "\t" \
21          "stc"                                            "\n\t" \
22          "xacquire lock " #_insn "q $123456789, (%0)"     "\n\t" \
23          "xrelease lock " #_insn "q $123456789, (%0)"     "\n\t" \
24          "xacquire lock " #_insn "l $0x12345FE, (%0)"     "\n\t" \
25          "xrelease lock " #_insn "l $0x12345FE, (%0)"     "\n\t" \
26          "xacquire lock " #_insn "w $0x9876,    (%0)"     "\n\t" \
27          "xrelease lock " #_insn "w $0x9876,    (%0)"     "\n\t" \
28          "xacquire lock " #_insn "b $0x45,      (%0)"     "\n\t" \
29          "xrelease lock " #_insn "b $0x45,      (%0)"     "\n\t" \
30          "xacquire lock " #_insn "q %1,         (%0)"     "\n\t" \
31          "xrelease lock " #_insn "q %1,         (%0)"     "\n\t" \
32          "xacquire lock " #_insn "l %k1,        (%0)"     "\n\t" \
33          "xrelease lock " #_insn "l %k1,        (%0)"     "\n\t" \
34          "xacquire lock " #_insn "w %w1,        (%0)"     "\n\t" \
35          "xrelease lock " #_insn "w %w1,        (%0)"     "\n\t" \
36          "xacquire lock " #_insn "b %b1,        (%0)"     "\n\t" \
37          "xrelease lock " #_insn "b %b1,        (%0)"     "\n\t" \
38          : : "r"(&n), "r"(some) : "cc", "memory" \
39       ); \
40       printf("result for '%-3s' is %016llx\n", #_insn, n);  \
41    }
42 
43 GEN_BINARY(add)
GEN_BINARY(adc)44 GEN_BINARY(adc)
45 GEN_BINARY(and)
46 GEN_BINARY(or)
47 GEN_BINARY(sbb)
48 GEN_BINARY(sub)
49 GEN_BINARY(xor)
50 
51 #define GEN_UNARY(_insn) \
52    void CAT(do_,_insn) ( void ) \
53    { \
54       volatile ULong n = 0x5555555555555555ULL; \
55       __asm__ __volatile__( \
56          "\t" \
57          "stc"                                "\n\t" \
58          "xacquire lock " #_insn "q (%0)"     "\n\t" \
59          "xrelease lock " #_insn "q (%0)"     "\n\t" \
60          "xacquire lock " #_insn "l (%0)"     "\n\t" \
61          "xrelease lock " #_insn "l (%0)"     "\n\t" \
62          "xacquire lock " #_insn "w (%0)"     "\n\t" \
63          "xrelease lock " #_insn "w (%0)"     "\n\t" \
64          "xacquire lock " #_insn "b (%0)"     "\n\t" \
65          "xrelease lock " #_insn "b (%0)"     "\n\t" \
66          : : "r"(&n) : "cc", "memory" \
67       ); \
68       printf("result for '%-3s' is %016llx\n", #_insn, n);  \
69    }
70 
71 GEN_UNARY(dec)
72 GEN_UNARY(inc)
73 GEN_UNARY(neg)
74 GEN_UNARY(not)
75 
76 void do_btc ( void )
77 {
78    volatile ULong n = 0x5555555555555555ULL;
79    __asm__ __volatile__(
80       "xacquire lock btcq %1,  (%0)"     "\n\t"
81       "xacquire lock btcq $57, (%0)"     "\n\t"
82       "xrelease lock btcq %1,  (%0)"     "\n\t"
83       "xrelease lock btcq $55, (%0)"     "\n\t"
84       "xacquire lock btcl %k1, (%0)"     "\n\t"
85       "xacquire lock btcl $27, (%0)"     "\n\t"
86       "xrelease lock btcl %k1, (%0)"     "\n\t"
87       "xrelease lock btcl $25, (%0)"     "\n\t"
88       "xacquire lock btcw %w1, (%0)"     "\n\t"
89       "xacquire lock btcw $12, (%0)"     "\n\t"
90       "xrelease lock btcw %w1, (%0)"     "\n\t"
91       "xrelease lock btcw $11, (%0)"     "\n\t"
92       : : "r"(&n), "r"(6ULL) : "cc", "memory"
93    );
94    printf("result for '%-3s' is %016llx\n", "btc", n); \
95 }
96 
do_btr(void)97 void do_btr ( void )
98 {
99    volatile ULong n = 0x5555555555555555ULL;
100    __asm__ __volatile__(
101       "xacquire lock btrq %1,  (%0)"     "\n\t"
102       "xacquire lock btrq $57, (%0)"     "\n\t"
103       "xrelease lock btrq %1,  (%0)"     "\n\t"
104       "xrelease lock btrq $55, (%0)"     "\n\t"
105       "xacquire lock btrl %k1, (%0)"     "\n\t"
106       "xacquire lock btrl $27, (%0)"     "\n\t"
107       "xrelease lock btrl %k1, (%0)"     "\n\t"
108       "xrelease lock btrl $25, (%0)"     "\n\t"
109       "xacquire lock btrw %w1, (%0)"     "\n\t"
110       "xacquire lock btrw $12, (%0)"     "\n\t"
111       "xrelease lock btrw %w1, (%0)"     "\n\t"
112       "xrelease lock btrw $11, (%0)"     "\n\t"
113       : : "r"(&n), "r"(6ULL) : "cc", "memory"
114    );
115    printf("result for '%-3s' is %016llx\n", "btr", n); \
116 }
117 
do_bts(void)118 void do_bts ( void )
119 {
120    volatile ULong n = 0x5555555555555555ULL;
121    __asm__ __volatile__(
122       "xacquire lock btsq %1,  (%0)"     "\n\t"
123       "xacquire lock btsq $57, (%0)"     "\n\t"
124       "xrelease lock btsq %1,  (%0)"     "\n\t"
125       "xrelease lock btsq $55, (%0)"     "\n\t"
126       "xacquire lock btsl %k1, (%0)"     "\n\t"
127       "xacquire lock btsl $27, (%0)"     "\n\t"
128       "xrelease lock btsl %k1, (%0)"     "\n\t"
129       "xrelease lock btsl $25, (%0)"     "\n\t"
130       "xacquire lock btsw %w1, (%0)"     "\n\t"
131       "xacquire lock btsw $12, (%0)"     "\n\t"
132       "xrelease lock btsw %w1, (%0)"     "\n\t"
133       "xrelease lock btsw $11, (%0)"     "\n\t"
134       : : "r"(&n), "r"(6ULL) : "cc", "memory"
135    );
136    printf("result for '%-3s' is %016llx\n", "bts", n); \
137 }
138 
do_cmpxchg(void)139 void do_cmpxchg ( void )
140 {
141    volatile ULong n = 0x5555555555555555ULL;
142    ULong some = 0x271831415927D459ULL;
143    __asm__ __volatile__(
144       "\t"
145       "stc"                                         "\n\t"
146       // zero out rax and get the flags in a known state
147       "xorq    %%rax, %%rax"                        "\n\t"
148       "xacquire lock cmpxchgq %1,         (%0)"     "\n\t"
149       "xrelease lock cmpxchgq %1,         (%0)"     "\n\t"
150       "xacquire lock cmpxchgl %k1,        (%0)"     "\n\t"
151       "xrelease lock cmpxchgl %k1,        (%0)"     "\n\t"
152       "xacquire lock cmpxchgw %w1,        (%0)"     "\n\t"
153       "xrelease lock cmpxchgw %w1,        (%0)"     "\n\t"
154       "xacquire lock cmpxchgb %b1,        (%0)"     "\n\t"
155       "xrelease lock cmpxchgb %b1,        (%0)"     "\n\t"
156       : : "r"(&n), "r"(some) : "cc", "memory", "rax"
157    );
158    printf("result for '%-3s' is %016llx\n", "cmpxchg", n);
159 }
160 
do_cmpxchg8b(void)161 void do_cmpxchg8b ( void )
162 {
163    volatile ULong n = 0x5555555555555555ULL;
164    __asm__ __volatile__(
165       "xorq     %%rax, %%rax"     "\n\t"
166       "xorq     %%rdx, %%rdx"     "\n\t"
167       "movabsq $0x1122334455667788, %%rcx"   "\n\t"
168       "movabsq $0xffeeddccbbaa9988, %%rbx"   "\n\t"
169       "xacquire lock cmpxchg8b (%0)"     "\n\t"
170       "xrelease lock cmpxchg8b (%0)"     "\n\t"
171       : : "r"(&n) : "cc", "memory", "rax", "rbx", "rcx", "rdx"
172    );
173    printf("result for '%-3s' is %016llx\n", "cmpxchg8b", n);
174 }
175 
do_xadd(void)176 void do_xadd ( void )
177 {
178    volatile ULong n = 0x5555555555555555ULL;
179    ULong some = 0x271831415927D459ULL;
180    __asm__ __volatile__(
181       "\t"
182       "stc"                                         "\n\t"
183       // zero out rax and get the flags in a known state
184       "xorq    %%rax, %%rax"                        "\n\t"
185       "xacquire lock xaddq %1,         (%0)"     "\n\t"
186       "xrelease lock xaddq %1,         (%0)"     "\n\t"
187       "xacquire lock xaddl %k1,        (%0)"     "\n\t"
188       "xrelease lock xaddl %k1,        (%0)"     "\n\t"
189       "xacquire lock xaddw %w1,        (%0)"     "\n\t"
190       "xrelease lock xaddw %w1,        (%0)"     "\n\t"
191       "xacquire lock xaddb %b1,        (%0)"     "\n\t"
192       "xrelease lock xaddb %b1,        (%0)"     "\n\t"
193       : : "r"(&n), "r"(some) : "cc", "memory", "rax"
194       // not sure this constraint string is really correct, since %1
195       // is written as well as read, in this case.  But I can't figure
196       // out how to tell gcc that.
197    );
198    printf("result for '%-3s' is %016llx\n", "xadd", n);
199 }
200 
do_xchg(void)201 void do_xchg ( void )
202 {
203    volatile ULong n = 0x5555555555555555ULL;
204    ULong some = 0x271831415927D459ULL;
205    __asm__ __volatile__(
206       "\t"
207       "stc"                                         "\n\t"
208       // zero out rax and get the flags in a known state
209       "xorq    %%rax, %%rax"                        "\n\t"
210       "xacquire lock xchgq %1,         (%0)"     "\n\t"
211       "xrelease lock xchgq %1,         (%0)"     "\n\t"
212       "xacquire lock xchgl %k1,        (%0)"     "\n\t"
213       "xrelease lock xchgl %k1,        (%0)"     "\n\t"
214       "xacquire lock xchgw %w1,        (%0)"     "\n\t"
215       "xrelease lock xchgw %w1,        (%0)"     "\n\t"
216       "xacquire lock xchgb %b1,        (%0)"     "\n\t"
217       "xrelease lock xchgb %b1,        (%0)"     "\n\t"
218       : : "r"(&n), "r"(some) : "cc", "memory", "rax"
219       // not sure this constraint string is really correct, since %1
220       // is written as well as read, in this case.  But I can't figure
221       // out how to tell gcc that.
222    );
223    printf("result for '%-3s' is %016llx\n", "xchg", n);
224 }
225 
do_xchg_no_lock(void)226 void do_xchg_no_lock ( void )
227 {
228    volatile ULong n = 0x5555555555555555ULL;
229    ULong some = 0x271831415927D459ULL;
230    __asm__ __volatile__(
231       "\t"
232       "stc"                                         "\n\t"
233       // zero out rax and get the flags in a known state
234       "xorq    %%rax, %%rax"                        "\n\t"
235       "xacquire xchgq %1,         (%0)"     "\n\t"
236       "xrelease xchgq %1,         (%0)"     "\n\t"
237       "xacquire xchgl %k1,        (%0)"     "\n\t"
238       "xrelease xchgl %k1,        (%0)"     "\n\t"
239       "xacquire xchgw %w1,        (%0)"     "\n\t"
240       "xrelease xchgw %w1,        (%0)"     "\n\t"
241       "xacquire xchgb %b1,        (%0)"     "\n\t"
242       "xrelease xchgb %b1,        (%0)"     "\n\t"
243       : : "r"(&n), "r"(some) : "cc", "memory", "rax"
244       // not sure this constraint string is really correct, since %1
245       // is written as well as read, in this case.  But I can't figure
246       // out how to tell gcc that.
247    );
248    printf("result for '%-3s' is %016llx\n", "xchg-no-lock", n);
249 }
250 
do_mov(void)251 void do_mov ( void )
252 {
253    // According to the Intel docs, we only need to allow xrelease here.
254    volatile ULong n = 0x5555555555555555ULL;
255    ULong some = 0x271831415927D459ULL;
256    __asm__ __volatile__(
257       "\t"
258       "xrelease movq %1,   0(%0)"     "\n\t"
259       "xrelease movl %k1,  1(%0)"     "\n\t"
260       "xrelease movw %w1,  3(%0)"     "\n\t"
261       "xrelease movb %b1,  7(%0)"     "\n\t"
262       : : "r"(&n), "r"(some) : "cc", "memory"
263    );
264    printf("result for '%-3s' is %016llx\n", "mov-reg", n);
265    n = 0xAAAAAAAAAAAAAAAAULL;
266    __asm__ __volatile__(
267       "\t"
268       "xrelease movq $-0x79876543, 0(%0)"     "\n\t"
269       "xrelease movl $0xEFCDAB89, 1(%0)"     "\n\t"
270       "xrelease movw $0xF00D,     3(%0)"     "\n\t"
271       "xrelease movb $0x42,       7(%0)"     "\n\t"
272       : : "r"(&n) : "cc", "memory"
273    );
274    printf("result for '%-3s' is %016llx\n", "mov-imm", n);
275 }
276 
main(void)277 int main ( void )
278 {
279   do_add();
280   do_adc();
281   do_and();
282   do_or();
283   do_sbb();
284   do_sub();
285   do_xor();
286   do_dec();
287   do_inc();
288   do_neg();
289   do_not();
290   do_btc();
291   do_btr();
292   do_bts();
293   do_cmpxchg();
294   do_cmpxchg8b();
295   do_xadd();
296   do_xchg();
297   do_xchg_no_lock();
298   do_mov();
299   return 0;
300 }
301