1 |
689 |
jeremybenn |
/* { dg-do run } */
|
2 |
|
|
/* { dg-require-effective-target sync_long_long_runtime } */
|
3 |
|
|
/* { dg-options "-std=gnu99" } */
|
4 |
|
|
/* { dg-additional-options "-march=pentium" { target { { i?86-*-* x86_64-*-* } && ia32 } } } */
|
5 |
|
|
|
6 |
|
|
/* { dg-message "note: '__sync_fetch_and_nand' changed semantics in GCC 4.4" "" { target *-*-* } 0 } */
|
7 |
|
|
/* { dg-message "note: '__sync_nand_and_fetch' changed semantics in GCC 4.4" "" { target *-*-* } 0 } */
|
8 |
|
|
|
9 |
|
|
|
10 |
|
|
/* Test basic functionality of the intrinsics. The operations should
|
11 |
|
|
not be optimized away if no one checks the return values. */
|
12 |
|
|
|
13 |
|
|
/* Based on ia64-sync-[12].c, but 1) long on ARM is 32 bit so use long long
|
14 |
|
|
(an explicit 64bit type maybe a better bet) and 2) Use values that cross
|
15 |
|
|
the 32bit boundary and cause carries since the actual maths are done as
|
16 |
|
|
pairs of 32 bit instructions. */
|
17 |
|
|
|
18 |
|
|
/* Note: This file is #included by some of the ARM tests. */
|
19 |
|
|
|
20 |
|
|
__extension__ typedef __SIZE_TYPE__ size_t;
|
21 |
|
|
|
22 |
|
|
extern void abort (void);
|
23 |
|
|
extern void *memcpy (void *, const void *, size_t);
|
24 |
|
|
extern int memcmp (const void *, const void *, size_t);
|
25 |
|
|
|
26 |
|
|
/* Temporary space where the work actually gets done. */
|
27 |
|
|
static long long AL[24];
|
28 |
|
|
/* Values copied into AL before we start. */
|
29 |
|
|
static long long init_di[24] = { 0x100000002ll, 0x200000003ll, 0, 1,
|
30 |
|
|
|
31 |
|
|
0x100000002ll, 0x100000002ll,
|
32 |
|
|
0x100000002ll, 0x100000002ll,
|
33 |
|
|
|
34 |
|
|
0, 0x1000e0de0000ll,
|
35 |
|
|
42 , 0xc001c0de0000ll,
|
36 |
|
|
|
37 |
|
|
-1ll, 0, 0xff00ff0000ll, -1ll,
|
38 |
|
|
|
39 |
|
|
0, 0x1000e0de0000ll,
|
40 |
|
|
42 , 0xc001c0de0000ll,
|
41 |
|
|
|
42 |
|
|
-1ll, 0, 0xff00ff0000ll, -1ll};
|
43 |
|
|
/* This is what should be in AL at the end. */
|
44 |
|
|
static long long test_di[24] = { 0x1234567890ll, 0x1234567890ll, 1, 0,
|
45 |
|
|
|
46 |
|
|
0x100000002ll, 0x100000002ll,
|
47 |
|
|
0x100000002ll, 0x100000002ll,
|
48 |
|
|
|
49 |
|
|
1, 0xc001c0de0000ll,
|
50 |
|
|
20, 0x1000e0de0000ll,
|
51 |
|
|
|
52 |
|
|
0x300000007ll , 0x500000009ll,
|
53 |
|
|
0xf100ff0001ll, ~0xa00000007ll,
|
54 |
|
|
|
55 |
|
|
1, 0xc001c0de0000ll,
|
56 |
|
|
20, 0x1000e0de0000ll,
|
57 |
|
|
|
58 |
|
|
0x300000007ll , 0x500000009ll,
|
59 |
|
|
0xf100ff0001ll, ~0xa00000007ll };
|
60 |
|
|
|
61 |
|
|
/* First check they work in terms of what they do to memory. */
|
62 |
|
|
static void
|
63 |
|
|
do_noret_di (void)
|
64 |
|
|
{
|
65 |
|
|
__sync_val_compare_and_swap (AL+0, 0x100000002ll, 0x1234567890ll);
|
66 |
|
|
__sync_bool_compare_and_swap (AL+1, 0x200000003ll, 0x1234567890ll);
|
67 |
|
|
__sync_lock_test_and_set (AL+2, 1);
|
68 |
|
|
__sync_lock_release (AL+3);
|
69 |
|
|
|
70 |
|
|
/* The following tests should not change the value since the
|
71 |
|
|
original does NOT match. */
|
72 |
|
|
__sync_val_compare_and_swap (AL+4, 0x000000002ll, 0x1234567890ll);
|
73 |
|
|
__sync_val_compare_and_swap (AL+5, 0x100000000ll, 0x1234567890ll);
|
74 |
|
|
__sync_bool_compare_and_swap (AL+6, 0x000000002ll, 0x1234567890ll);
|
75 |
|
|
__sync_bool_compare_and_swap (AL+7, 0x100000000ll, 0x1234567890ll);
|
76 |
|
|
|
77 |
|
|
__sync_fetch_and_add (AL+8, 1);
|
78 |
|
|
__sync_fetch_and_add (AL+9, 0xb000e0000000ll); /* + to both halves & carry. */
|
79 |
|
|
__sync_fetch_and_sub (AL+10, 22);
|
80 |
|
|
__sync_fetch_and_sub (AL+11, 0xb000e0000000ll);
|
81 |
|
|
|
82 |
|
|
__sync_fetch_and_and (AL+12, 0x300000007ll);
|
83 |
|
|
__sync_fetch_and_or (AL+13, 0x500000009ll);
|
84 |
|
|
__sync_fetch_and_xor (AL+14, 0xe00000001ll);
|
85 |
|
|
__sync_fetch_and_nand (AL+15, 0xa00000007ll);
|
86 |
|
|
|
87 |
|
|
/* These should be the same as the fetch_and_* cases except for
|
88 |
|
|
return value. */
|
89 |
|
|
__sync_add_and_fetch (AL+16, 1);
|
90 |
|
|
/* add to both halves & carry. */
|
91 |
|
|
__sync_add_and_fetch (AL+17, 0xb000e0000000ll);
|
92 |
|
|
__sync_sub_and_fetch (AL+18, 22);
|
93 |
|
|
__sync_sub_and_fetch (AL+19, 0xb000e0000000ll);
|
94 |
|
|
|
95 |
|
|
__sync_and_and_fetch (AL+20, 0x300000007ll);
|
96 |
|
|
__sync_or_and_fetch (AL+21, 0x500000009ll);
|
97 |
|
|
__sync_xor_and_fetch (AL+22, 0xe00000001ll);
|
98 |
|
|
__sync_nand_and_fetch (AL+23, 0xa00000007ll);
|
99 |
|
|
}
|
100 |
|
|
|
101 |
|
|
/* Now check return values. */
|
102 |
|
|
static void
|
103 |
|
|
do_ret_di (void)
|
104 |
|
|
{
|
105 |
|
|
if (__sync_val_compare_and_swap (AL+0, 0x100000002ll, 0x1234567890ll) !=
|
106 |
|
|
0x100000002ll) abort ();
|
107 |
|
|
if (__sync_bool_compare_and_swap (AL+1, 0x200000003ll, 0x1234567890ll) !=
|
108 |
|
|
1) abort ();
|
109 |
|
|
if (__sync_lock_test_and_set (AL+2, 1) != 0) abort ();
|
110 |
|
|
__sync_lock_release (AL+3); /* no return value, but keep to match results. */
|
111 |
|
|
|
112 |
|
|
/* The following tests should not change the value since the
|
113 |
|
|
original does NOT match. */
|
114 |
|
|
if (__sync_val_compare_and_swap (AL+4, 0x000000002ll, 0x1234567890ll) !=
|
115 |
|
|
0x100000002ll) abort ();
|
116 |
|
|
if (__sync_val_compare_and_swap (AL+5, 0x100000000ll, 0x1234567890ll) !=
|
117 |
|
|
0x100000002ll) abort ();
|
118 |
|
|
if (__sync_bool_compare_and_swap (AL+6, 0x000000002ll, 0x1234567890ll) !=
|
119 |
|
|
0) abort ();
|
120 |
|
|
if (__sync_bool_compare_and_swap (AL+7, 0x100000000ll, 0x1234567890ll) !=
|
121 |
|
|
0) abort ();
|
122 |
|
|
|
123 |
|
|
if (__sync_fetch_and_add (AL+8, 1) != 0) abort ();
|
124 |
|
|
if (__sync_fetch_and_add (AL+9, 0xb000e0000000ll) != 0x1000e0de0000ll) abort ();
|
125 |
|
|
if (__sync_fetch_and_sub (AL+10, 22) != 42) abort ();
|
126 |
|
|
if (__sync_fetch_and_sub (AL+11, 0xb000e0000000ll) != 0xc001c0de0000ll)
|
127 |
|
|
abort ();
|
128 |
|
|
|
129 |
|
|
if (__sync_fetch_and_and (AL+12, 0x300000007ll) != -1ll) abort ();
|
130 |
|
|
if (__sync_fetch_and_or (AL+13, 0x500000009ll) != 0) abort ();
|
131 |
|
|
if (__sync_fetch_and_xor (AL+14, 0xe00000001ll) != 0xff00ff0000ll) abort ();
|
132 |
|
|
if (__sync_fetch_and_nand (AL+15, 0xa00000007ll) != -1ll) abort ();
|
133 |
|
|
|
134 |
|
|
/* These should be the same as the fetch_and_* cases except for
|
135 |
|
|
return value. */
|
136 |
|
|
if (__sync_add_and_fetch (AL+16, 1) != 1) abort ();
|
137 |
|
|
if (__sync_add_and_fetch (AL+17, 0xb000e0000000ll) != 0xc001c0de0000ll)
|
138 |
|
|
abort ();
|
139 |
|
|
if (__sync_sub_and_fetch (AL+18, 22) != 20) abort ();
|
140 |
|
|
if (__sync_sub_and_fetch (AL+19, 0xb000e0000000ll) != 0x1000e0de0000ll)
|
141 |
|
|
abort ();
|
142 |
|
|
|
143 |
|
|
if (__sync_and_and_fetch (AL+20, 0x300000007ll) != 0x300000007ll) abort ();
|
144 |
|
|
if (__sync_or_and_fetch (AL+21, 0x500000009ll) != 0x500000009ll) abort ();
|
145 |
|
|
if (__sync_xor_and_fetch (AL+22, 0xe00000001ll) != 0xf100ff0001ll) abort ();
|
146 |
|
|
if (__sync_nand_and_fetch (AL+23, 0xa00000007ll) != ~0xa00000007ll) abort ();
|
147 |
|
|
}
|
148 |
|
|
|
149 |
|
|
int main ()
|
150 |
|
|
{
|
151 |
|
|
memcpy (AL, init_di, sizeof (init_di));
|
152 |
|
|
|
153 |
|
|
do_noret_di ();
|
154 |
|
|
|
155 |
|
|
if (memcmp (AL, test_di, sizeof (test_di)))
|
156 |
|
|
abort ();
|
157 |
|
|
|
158 |
|
|
memcpy (AL, init_di, sizeof (init_di));
|
159 |
|
|
|
160 |
|
|
do_ret_di ();
|
161 |
|
|
|
162 |
|
|
if (memcmp (AL, test_di, sizeof (test_di)))
|
163 |
|
|
abort ();
|
164 |
|
|
|
165 |
|
|
return 0;
|
166 |
|
|
}
|