1/* { dg-do link } */
2/* { dg-require-effective-target sync_int_128_runtime } */
3/* { dg-options "-mcx16" { target { x86_64-*-* i?86-*-* } } } */
4/* { dg-final { simulate-thread } } */
5
6#include <stdio.h>
7#include "simulate-thread.h"
8
9/* Test all the __sync routines for proper atomicity on 16 byte values.  */
10
11__int128_t zero = 0;
12__int128_t max = ~0;
13__int128_t changing_value = 0;
14__int128_t value = 0;
15__int128_t ret;
16
17void test_abort()
18{
19  static int reported = 0;
20  if (!reported)
21    {
22      printf ("FAIL: improper execution of __sync builtin.\n");
23      reported = 1;
24    }
25}
26
27void simulate_thread_other_threads ()
28{
29}
30
31int simulate_thread_step_verify ()
32{
33  if (value != zero && value != max)
34    {
35      printf ("FAIL: invalid intermediate result for value.\n");
36      return 1;
37    }
38  return 0;
39}
40
41int simulate_thread_final_verify ()
42{
43  if (value != 0)
44    {
45      printf ("FAIL: invalid final result for value.\n");
46      return 1;
47    }
48  return 0;
49}
50
51/* All values written to 'value' alternate between 'zero' and 'max'. Any other
52   value detected by simulate_thread_step_verify() between instructions would indicate
53   that the value was only partially written, and would thus fail this
54   atomicity test.
55
56   This function tests each different __atomic routine once, with the
57   exception of the load instruction which requires special testing.  */
58__attribute__((noinline))
59void simulate_thread_main()
60{
61
62  ret = __atomic_exchange_n (&value, max, __ATOMIC_SEQ_CST);
63  if (ret != zero || value != max)
64    test_abort();
65
66  __atomic_store_n (&value, zero, __ATOMIC_SEQ_CST);
67  if (value != zero)
68    test_abort();
69
70  ret = __atomic_fetch_add (&value, max, __ATOMIC_SEQ_CST);
71  if (value != max || ret != zero)
72    test_abort ();
73
74  ret = __atomic_fetch_sub (&value, max, __ATOMIC_SEQ_CST);
75  if (value != zero || ret != max)
76    test_abort ();
77
78  ret = __atomic_fetch_or (&value, max, __ATOMIC_SEQ_CST);
79  if (value != max || ret != zero)
80    test_abort ();
81
82  ret = __atomic_fetch_and (&value, max, __ATOMIC_SEQ_CST);
83  if (value != max || ret != max)
84    test_abort ();
85
86  ret = __atomic_fetch_xor (&value, max, __ATOMIC_SEQ_CST);
87  if (value != zero || ret != max)
88    test_abort ();
89
90  ret = __atomic_add_fetch (&value, max, __ATOMIC_SEQ_CST);
91  if (value != max || ret != max)
92    test_abort ();
93
94  ret = __atomic_sub_fetch (&value, max, __ATOMIC_SEQ_CST);
95  if (value != zero || ret != zero)
96    test_abort ();
97
98  ret = __atomic_or_fetch (&value, max, __ATOMIC_SEQ_CST);
99  if (value != max || ret != max)
100    test_abort ();
101
102  ret = __atomic_and_fetch (&value, max, __ATOMIC_SEQ_CST);
103  if (value != max || ret != max)
104    test_abort ();
105
106  ret = __atomic_xor_fetch (&value, max, __ATOMIC_SEQ_CST);
107  if (value != zero || ret != zero)
108    test_abort ();
109}
110
111int main()
112{
113  simulate_thread_main ();
114  simulate_thread_done ();
115  return 0;
116}
117