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