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