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, %%rbx" "\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