1436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
2436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#include <stdio.h>
3436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#include <stdlib.h>
4436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
5436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* An ultra-lame test program for RTM support, as available
6436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   on Haswell CPUs. */
7436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
8436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* Attempt to run f(arg) as a transaction, and return a Boolean
9436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   indicating success or otherwise. */
10436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
11436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov__attribute__((noinline))
12436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic int transactionally_apply ( void(*f)(void*), void* arg )
13436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{
14436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov  register int ok;
15436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov  __asm__ __volatile__(
16436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov     "  xbegin .Lzzqqfail" );
17436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov  f(arg);
18436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov  __asm__ __volatile__(
19436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov     /* This is a bit tricky.  If the transaction succeeds, control
20436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov        will flow to this point.  If it fails, control continues at
21436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov        .Lzzqqfail, with the machine state looking the same as it did
22436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov        immediately before the xbegin was executed. */
23436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov     "  xend           \n\t"  /* declare the transaction to be complete */
24436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov     "  movl $1,%0     \n\t"  /* "ok = 1" */
25436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov     "  jmp .Lzzqqout  \n\t"  /* jump to the merge point */
26436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov     ".Lzzqqfail:      \n\t"  /* it failed .. */
27436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov     "  movl $0,%0     \n\t"  /* "ok = 0" */
28436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov     ".Lzzqqout:       \n\t"  /* this is the merge point */
29436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov     : "=r"(ok) : : "cc", "rax"
30436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov  );
31436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov  return ok;
32436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}
33436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
34436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovvoid testfn ( void* arg )
35436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{
36436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}
37436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
38436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovint main ( void )
39436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{
40436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov  long long int ok = transactionally_apply ( testfn, NULL );
41436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov  printf("transactionally_apply: ok = %lld (expected %d)\n", ok, 0);
42436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
43436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov  __asm__ __volatile__(
44436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov    "movq $0, %%rax  \n\t"
45436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov    "xtest           \n\t"
46436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov    "setz %%al       \n\t"
47436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov    "movq %%rax, %0  \n\t"
48436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov    : "=r"(ok) : : "cc","rax"
49436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov  );
50436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov  printf("xtest: rflags.Z = %lld (expected %d)\n", ok, 1);
51436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
52436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov  /*
53436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov  printf("testing XACQUIRE / XRELEASE\n");
54436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov  int n = 0;
55436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov  __asm__ __volatile__(
56436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov     "xacquire lock incl (%0)   \n\t"
57436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov     "xrelease lock decl (%0)   \n\t"
58436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov     : : "r"(&n) : "cc", "memory"
59436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov  );
60436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov  */
61436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
62436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov  __asm__ __volatile__( "xabort $0x1" );
63436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov  printf("xabort: outside transaction is nop.\n");
64436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
65436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov  return 0;
66436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}
67