1/* { dg-do run { target int128 } } */
2/* { dg-options "-std=gnu99" { target c } } */
3/* { dg-options "" { target c++ } } */
4
5#ifndef __cplusplus
6extern void abort (void);
7#else
8extern "C" void abort (void);
9#endif
10
11#define MK_CONST128(A,B,C,D) \
12        ( (((unsigned __int128) (unsigned int) A) << 96) \
13         | (((unsigned __int128) (unsigned int) B) << 64) \
14         | (((unsigned __int128) (unsigned int) C) << 32) \
15         | ((unsigned __int128) (unsigned int) D) )
16
17#define MK_CONST128_SIGNED(A,B,C,D) \
18        ((__int128) MK_CONST128(A, B, C, D))
19
20#define MINUS_2 MK_CONST128_SIGNED (0xffffffffu, 0xffffffffu, 0xffffffffu, \
21		0xfffffffeu)
22#define MINUS_3 MK_CONST128_SIGNED (0xffffffffu, 0xffffffffu, 0xffffffffu, \
23		0xfffffffdu)
24#define MINUS_6 MK_CONST128_SIGNED (0xffffffffu, 0xffffffffu, 0xffffffffu, \
25		0xfffffffau)
26#define PLUS_1	MK_CONST128_SIGNED (0, 0, 0, 1)
27#define PLUS_2	MK_CONST128_SIGNED (0, 0, 0, 2)
28#define PLUS_3	MK_CONST128_SIGNED (0, 0, 0, 3)
29#define PLUS_6	MK_CONST128_SIGNED (0, 0, 0, 6)
30#define PLUS_10	MK_CONST128_SIGNED (0, 0, 0, 10)
31
32#define U_8	MK_CONST128 (0, 0, 0, 8)
33#define U_MAX	MK_CONST128 (0xffffffff,0xffffffff,0xffffffff,0xffffffff)
34#define U_CST1	MK_CONST128 (0xbeeffeed, 0xdeafcafe, 0xaffefade, 0x12345678)
35#define U_CST2	MK_CONST128 (0x41100112, 0x21503501, 0x50010521, 0xedcba987)
36
37signed __int128 foo_neg (signed __int128 v)
38{
39  return -v;
40}
41
42unsigned __int128 foo_xor (unsigned __int128 x, unsigned __int128 y)
43{
44  return x ^ y;
45}
46
47unsigned __int128 foo_inv (unsigned __int128 v)
48{
49  return ~v;
50}
51
52unsigned __int128 foo_rotate_left (unsigned __int128 v)
53{
54  unsigned __int128 c;
55  int i;
56  for (i = 0; i < 128; i++)
57    {
58      c = v >> 127;
59      v <<= 1;
60      v |= c;
61    }
62  return v;
63}
64
65unsigned __int128 foo_rotate_right (unsigned __int128 v)
66{
67  unsigned __int128 c;
68  int i;
69  for (i = 0; i < 128; i++)
70    {
71      c = (v & ((unsigned __int128) 1)) << 127;
72      v >>= 1;
73      v |= c;
74    }
75  return v;
76}
77
78void foo_swap (unsigned __int128 *x, unsigned __int128 *y)
79{
80  unsigned __int128 x1 = x[0];
81  unsigned __int128 y1 = y[0];
82  x1 ^= y1 ^= x1 ^= y1;
83  x[0] = x1;
84  y[0] = y1;
85}
86
87__int128 foo_add (signed __int128 a, unsigned __int128 b)
88{
89  return (__int128) (a + (__int128) b);
90}
91
92__int128 foo_sub (unsigned __int128 a, signed __int128 b)
93{
94  return (__int128) ((__int128) a - b);
95}
96
97__int128 foo_mul (signed __int128 a, signed __int128 b)
98{
99  return a * b;
100}
101
102__int128 foo_div (signed __int128 a, signed __int128 b)
103{
104  return a / b;
105}
106
107__int128 foo_shl (signed __int128 a, int shift)
108{
109  return a << (shift & 127);
110}
111
112__int128 foo_shr (signed __int128 a, int shift)
113{
114  return a >> (shift & 127);
115}
116
117int main(void)
118{
119  __int128 rslt;
120  unsigned __int128 u1, u2;
121
122  rslt = foo_add (MINUS_2, U_8);
123  if (rslt != PLUS_6)
124    abort ();
125  rslt = foo_sub (U_8, MINUS_2);
126  if (rslt != PLUS_10)
127     abort ();
128  rslt = foo_sub ((unsigned __int128) foo_mul (MINUS_2, MINUS_2), MINUS_2);
129  if (rslt != PLUS_6)
130    abort ();
131  if (rslt != foo_shl (PLUS_3, 1))
132    abort ();
133  rslt = foo_shl (MINUS_3, 1);
134  if (rslt != MINUS_6)
135    abort ();
136  if (foo_shr (MINUS_6, 1) != MINUS_3)
137    abort ();
138  if (foo_div (MINUS_6, MINUS_3) != PLUS_2)
139    abort ();
140  if (foo_rotate_left (U_CST1) != U_CST1)
141    abort ();
142  if (foo_rotate_right (U_CST1) != U_CST1)
143    abort ();
144  u1 = U_CST1;
145  u2 = U_8;
146  foo_swap (&u1, &u2);
147  if (u1 != U_8 || u2 != U_CST1)
148    abort ();
149
150  if (foo_inv (U_CST2) != U_CST1)
151    abort ();
152  if (foo_neg (PLUS_2) != MINUS_2)
153    abort ();
154  if (foo_neg ((signed __int128) U_CST1) != foo_add (PLUS_1, foo_xor (U_CST1, U_MAX)))
155    abort ();
156  return 0;
157}
158