]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
A minimal test case for the parsing of XACQUIRE and XRELEASE prefixes.
authorJulian Seward <jseward@acm.org>
Tue, 15 Oct 2013 11:37:16 +0000 (11:37 +0000)
committerJulian Seward <jseward@acm.org>
Tue, 15 Oct 2013 11:37:16 +0000 (11:37 +0000)
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@13645

none/tests/amd64/xacq_xrel.c [new file with mode: 0644]

diff --git a/none/tests/amd64/xacq_xrel.c b/none/tests/amd64/xacq_xrel.c
new file mode 100644 (file)
index 0000000..628d729
--- /dev/null
@@ -0,0 +1,298 @@
+
+/* This is a test program that checks the parsing of instructions with
+   xacquire and xrelease prefixes.  The tested insns are, afaics,
+   exactly those listed in the Intel description for the two prefixes
+   ("XACQUIRE/XRELEASE -- Hardware Lock Elision Prefix Hints"). */
+
+#include <stdio.h>
+
+typedef  unsigned long long int  ULong;
+
+#define CAT2(_x,_y) _x##_y
+#define CAT(_x,_y) CAT2(_x,_y)
+
+#define GEN_BINARY(_insn) \
+   void CAT(do_,_insn) ( void ) \
+   { \
+      volatile ULong n = 0x5555555555555555ULL; \
+      ULong some = 0x271831415927D459ULL; \
+      __asm__ __volatile__( \
+         "\t" \
+         "stc"                                            "\n\t" \
+         "xacquire lock " #_insn "q $123456789, (%0)"     "\n\t" \
+         "xrelease lock " #_insn "q $123456789, (%0)"     "\n\t" \
+         "xacquire lock " #_insn "l $0x12345FE, (%0)"     "\n\t" \
+         "xrelease lock " #_insn "l $0x12345FE, (%0)"     "\n\t" \
+         "xacquire lock " #_insn "w $0x9876,    (%0)"     "\n\t" \
+         "xrelease lock " #_insn "w $0x9876,    (%0)"     "\n\t" \
+         "xacquire lock " #_insn "b $0x45,      (%0)"     "\n\t" \
+         "xrelease lock " #_insn "b $0x45,      (%0)"     "\n\t" \
+         "xacquire lock " #_insn "q %1,         (%0)"     "\n\t" \
+         "xrelease lock " #_insn "q %1,         (%0)"     "\n\t" \
+         "xacquire lock " #_insn "l %k1,        (%0)"     "\n\t" \
+         "xrelease lock " #_insn "l %k1,        (%0)"     "\n\t" \
+         "xacquire lock " #_insn "w %w1,        (%0)"     "\n\t" \
+         "xrelease lock " #_insn "w %w1,        (%0)"     "\n\t" \
+         "xacquire lock " #_insn "b %b1,        (%0)"     "\n\t" \
+         "xrelease lock " #_insn "b %b1,        (%0)"     "\n\t" \
+         : : "r"(&n), "r"(some) : "cc", "memory" \
+      ); \
+      printf("result for '%-3s' is %016llx\n", #_insn, n);  \
+   }
+
+GEN_BINARY(add)
+GEN_BINARY(adc)
+GEN_BINARY(and)
+GEN_BINARY(or)
+GEN_BINARY(sbb)
+GEN_BINARY(sub)
+GEN_BINARY(xor)
+
+#define GEN_UNARY(_insn) \
+   void CAT(do_,_insn) ( void ) \
+   { \
+      volatile ULong n = 0x5555555555555555ULL; \
+      __asm__ __volatile__( \
+         "\t" \
+         "stc"                                "\n\t" \
+         "xacquire lock " #_insn "q (%0)"     "\n\t" \
+         "xrelease lock " #_insn "q (%0)"     "\n\t" \
+         "xacquire lock " #_insn "l (%0)"     "\n\t" \
+         "xrelease lock " #_insn "l (%0)"     "\n\t" \
+         "xacquire lock " #_insn "w (%0)"     "\n\t" \
+         "xrelease lock " #_insn "w (%0)"     "\n\t" \
+         "xacquire lock " #_insn "b (%0)"     "\n\t" \
+         "xrelease lock " #_insn "b (%0)"     "\n\t" \
+         : : "r"(&n) : "cc", "memory" \
+      ); \
+      printf("result for '%-3s' is %016llx\n", #_insn, n);  \
+   }
+
+GEN_UNARY(dec)
+GEN_UNARY(inc)
+GEN_UNARY(neg)
+GEN_UNARY(not)
+
+void do_btc ( void )
+{
+   volatile ULong n = 0x5555555555555555ULL;
+   __asm__ __volatile__(
+      "xacquire lock btcq %1,  (%0)"     "\n\t"
+      "xacquire lock btcq $57, (%0)"     "\n\t"
+      "xrelease lock btcq %1,  (%0)"     "\n\t"
+      "xrelease lock btcq $55, (%0)"     "\n\t"
+      "xacquire lock btcl %k1, (%0)"     "\n\t"
+      "xacquire lock btcl $27, (%0)"     "\n\t"
+      "xrelease lock btcl %k1, (%0)"     "\n\t"
+      "xrelease lock btcl $25, (%0)"     "\n\t"
+      "xacquire lock btcw %w1, (%0)"     "\n\t"
+      "xacquire lock btcw $12, (%0)"     "\n\t"
+      "xrelease lock btcw %w1, (%0)"     "\n\t"
+      "xrelease lock btcw $11, (%0)"     "\n\t"
+      : : "r"(&n), "r"(6ULL) : "cc", "memory"
+   );
+   printf("result for '%-3s' is %016llx\n", "btc", n); \
+}
+
+void do_btr ( void )
+{
+   volatile ULong n = 0x5555555555555555ULL;
+   __asm__ __volatile__(
+      "xacquire lock btrq %1,  (%0)"     "\n\t"
+      "xacquire lock btrq $57, (%0)"     "\n\t"
+      "xrelease lock btrq %1,  (%0)"     "\n\t"
+      "xrelease lock btrq $55, (%0)"     "\n\t"
+      "xacquire lock btrl %k1, (%0)"     "\n\t"
+      "xacquire lock btrl $27, (%0)"     "\n\t"
+      "xrelease lock btrl %k1, (%0)"     "\n\t"
+      "xrelease lock btrl $25, (%0)"     "\n\t"
+      "xacquire lock btrw %w1, (%0)"     "\n\t"
+      "xacquire lock btrw $12, (%0)"     "\n\t"
+      "xrelease lock btrw %w1, (%0)"     "\n\t"
+      "xrelease lock btrw $11, (%0)"     "\n\t"
+      : : "r"(&n), "r"(6ULL) : "cc", "memory"
+   );
+   printf("result for '%-3s' is %016llx\n", "btr", n); \
+}
+
+void do_bts ( void )
+{
+   volatile ULong n = 0x5555555555555555ULL;
+   __asm__ __volatile__(
+      "xacquire lock btsq %1,  (%0)"     "\n\t"
+      "xacquire lock btsq $57, (%0)"     "\n\t"
+      "xrelease lock btsq %1,  (%0)"     "\n\t"
+      "xrelease lock btsq $55, (%0)"     "\n\t"
+      "xacquire lock btsl %k1, (%0)"     "\n\t"
+      "xacquire lock btsl $27, (%0)"     "\n\t"
+      "xrelease lock btsl %k1, (%0)"     "\n\t"
+      "xrelease lock btsl $25, (%0)"     "\n\t"
+      "xacquire lock btsw %w1, (%0)"     "\n\t"
+      "xacquire lock btsw $12, (%0)"     "\n\t"
+      "xrelease lock btsw %w1, (%0)"     "\n\t"
+      "xrelease lock btsw $11, (%0)"     "\n\t"
+      : : "r"(&n), "r"(6ULL) : "cc", "memory"
+   );
+   printf("result for '%-3s' is %016llx\n", "bts", n); \
+}
+
+void do_cmpxchg ( void )
+{
+   volatile ULong n = 0x5555555555555555ULL;
+   ULong some = 0x271831415927D459ULL;
+   __asm__ __volatile__(
+      "\t"
+      "stc"                                         "\n\t"
+      // zero out rax and get the flags in a known state
+      "xorq    %%rax, %%rax"                        "\n\t"
+      "xacquire lock cmpxchgq %1,         (%0)"     "\n\t"
+      "xrelease lock cmpxchgq %1,         (%0)"     "\n\t"
+      "xacquire lock cmpxchgl %k1,        (%0)"     "\n\t"
+      "xrelease lock cmpxchgl %k1,        (%0)"     "\n\t"
+      "xacquire lock cmpxchgw %w1,        (%0)"     "\n\t"
+      "xrelease lock cmpxchgw %w1,        (%0)"     "\n\t"
+      "xacquire lock cmpxchgb %b1,        (%0)"     "\n\t"
+      "xrelease lock cmpxchgb %b1,        (%0)"     "\n\t"
+      : : "r"(&n), "r"(some) : "cc", "memory", "rax"
+   );
+   printf("result for '%-3s' is %016llx\n", "cmpxchg", n);
+}
+
+void do_cmpxchg8b ( void )
+{
+   volatile ULong n = 0x5555555555555555ULL;
+   __asm__ __volatile__(
+      "xorq     %%rax, %%rax"     "\n\t"
+      "xorq     %%rdx, %%rdx"     "\n\t"
+      "xacquire lock cmpxchg8b (%0)"     "\n\t"
+      "xrelease lock cmpxchg8b (%0)"     "\n\t"
+      : : "r"(&n) : "cc", "memory", "rax", "rdx"
+   );
+   printf("result for '%-3s' is %016llx\n", "cmpxchg8b", n);
+}
+
+void do_xadd ( void )
+{
+   volatile ULong n = 0x5555555555555555ULL;
+   ULong some = 0x271831415927D459ULL;
+   __asm__ __volatile__(
+      "\t"
+      "stc"                                         "\n\t"
+      // zero out rax and get the flags in a known state
+      "xorq    %%rax, %%rax"                        "\n\t"
+      "xacquire lock xaddq %1,         (%0)"     "\n\t"
+      "xrelease lock xaddq %1,         (%0)"     "\n\t"
+      "xacquire lock xaddl %k1,        (%0)"     "\n\t"
+      "xrelease lock xaddl %k1,        (%0)"     "\n\t"
+      "xacquire lock xaddw %w1,        (%0)"     "\n\t"
+      "xrelease lock xaddw %w1,        (%0)"     "\n\t"
+      "xacquire lock xaddb %b1,        (%0)"     "\n\t"
+      "xrelease lock xaddb %b1,        (%0)"     "\n\t"
+      : : "r"(&n), "r"(some) : "cc", "memory", "rax"
+      // not sure this constraint string is really correct, since %1
+      // is written as well as read, in this case.  But I can't figure
+      // out how to tell gcc that.
+   );
+   printf("result for '%-3s' is %016llx\n", "xadd", n);
+}
+
+void do_xchg ( void )
+{
+   volatile ULong n = 0x5555555555555555ULL;
+   ULong some = 0x271831415927D459ULL;
+   __asm__ __volatile__(
+      "\t"
+      "stc"                                         "\n\t"
+      // zero out rax and get the flags in a known state
+      "xorq    %%rax, %%rax"                        "\n\t"
+      "xacquire lock xchgq %1,         (%0)"     "\n\t"
+      "xrelease lock xchgq %1,         (%0)"     "\n\t"
+      "xacquire lock xchgl %k1,        (%0)"     "\n\t"
+      "xrelease lock xchgl %k1,        (%0)"     "\n\t"
+      "xacquire lock xchgw %w1,        (%0)"     "\n\t"
+      "xrelease lock xchgw %w1,        (%0)"     "\n\t"
+      "xacquire lock xchgb %b1,        (%0)"     "\n\t"
+      "xrelease lock xchgb %b1,        (%0)"     "\n\t"
+      : : "r"(&n), "r"(some) : "cc", "memory", "rax"
+      // not sure this constraint string is really correct, since %1
+      // is written as well as read, in this case.  But I can't figure
+      // out how to tell gcc that.
+   );
+   printf("result for '%-3s' is %016llx\n", "xchg", n);
+}
+
+void do_xchg_no_lock ( void )
+{
+   volatile ULong n = 0x5555555555555555ULL;
+   ULong some = 0x271831415927D459ULL;
+   __asm__ __volatile__(
+      "\t"
+      "stc"                                         "\n\t"
+      // zero out rax and get the flags in a known state
+      "xorq    %%rax, %%rax"                        "\n\t"
+      "xacquire xchgq %1,         (%0)"     "\n\t"
+      "xrelease xchgq %1,         (%0)"     "\n\t"
+      "xacquire xchgl %k1,        (%0)"     "\n\t"
+      "xrelease xchgl %k1,        (%0)"     "\n\t"
+      "xacquire xchgw %w1,        (%0)"     "\n\t"
+      "xrelease xchgw %w1,        (%0)"     "\n\t"
+      "xacquire xchgb %b1,        (%0)"     "\n\t"
+      "xrelease xchgb %b1,        (%0)"     "\n\t"
+      : : "r"(&n), "r"(some) : "cc", "memory", "rax"
+      // not sure this constraint string is really correct, since %1
+      // is written as well as read, in this case.  But I can't figure
+      // out how to tell gcc that.
+   );
+   printf("result for '%-3s' is %016llx\n", "xchg-no-lock", n);
+}
+
+void do_mov ( void )
+{
+   // According to the Intel docs, we only need to allow xrelease here.
+   volatile ULong n = 0x5555555555555555ULL;
+   ULong some = 0x271831415927D459ULL;
+   __asm__ __volatile__(
+      "\t"
+      "xrelease movq %1,   0(%0)"     "\n\t"
+      "xrelease movl %k1,  1(%0)"     "\n\t"
+      "xrelease movw %w1,  3(%0)"     "\n\t"
+      "xrelease movb %b1,  7(%0)"     "\n\t"
+      : : "r"(&n), "r"(some) : "cc", "memory"
+   );
+   printf("result for '%-3s' is %016llx\n", "mov-reg", n);
+   n = 0xAAAAAAAAAAAAAAAAULL;
+   __asm__ __volatile__(
+      "\t"
+      "xrelease movq $-0x79876543, 0(%0)"     "\n\t"
+      "xrelease movl $0xEFCDAB89, 1(%0)"     "\n\t"
+      "xrelease movw $0xF00D,     3(%0)"     "\n\t"
+      "xrelease movb $0x42,       7(%0)"     "\n\t"
+      : : "r"(&n) : "cc", "memory"
+   );
+   printf("result for '%-3s' is %016llx\n", "mov-imm", n);
+}
+
+int main ( void )
+{
+  do_add();
+  do_adc();
+  do_and();
+  do_or();
+  do_sbb();
+  do_sub();
+  do_xor();
+  do_dec();
+  do_inc();
+  do_neg();
+  do_not();
+  do_btc();
+  do_btr();
+  do_bts();
+  do_cmpxchg();
+  do_cmpxchg8b();
+  do_xadd();
+  do_xchg();
+  do_xchg_no_lock();
+  do_mov();
+  return 0;
+}