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
9typedef  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
43GEN_BINARY(add)
44GEN_BINARY(adc)
45GEN_BINARY(and)
46GEN_BINARY(or)
47GEN_BINARY(sbb)
48GEN_BINARY(sub)
49GEN_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
71GEN_UNARY(dec)
72GEN_UNARY(inc)
73GEN_UNARY(neg)
74GEN_UNARY(not)
75
76void 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
97void 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
118void 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
139void 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
161void 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, %%rdx"   "\n\t"
169      "xacquire lock cmpxchg8b (%0)"     "\n\t"
170      "xrelease lock cmpxchg8b (%0)"     "\n\t"
171      : : "r"(&n) : "cc", "memory", "rax", "rdx", "rcx", "rdx"
172   );
173   printf("result for '%-3s' is %016llx\n", "cmpxchg8b", n);
174}
175
176void 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
201void 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
226void 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
251void 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
277int 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