xref: /openbmc/qemu/tests/unit/test-int128.c (revision b1efff6bf031a93b5b8bf3912ddc720cc1653a61)
1  /*
2   * Test Int128 arithmetic
3   *
4   * This work is licensed under the terms of the GNU LGPL, version 2 or later.
5   * See the COPYING.LIB file in the top-level directory.
6   *
7   */
8  
9  #include "qemu/osdep.h"
10  #include "qemu/int128.h"
11  
12  /* clang doesn't support __noclone__ but it does have a mechanism for
13   * telling us this. We assume that if we don't have __has_attribute()
14   * then this is GCC and that GCC always supports __noclone__.
15   */
16  #if defined(__has_attribute)
17  #if !__has_attribute(__noclone__)
18  #define ATTRIBUTE_NOCLONE
19  #endif
20  #endif
21  #ifndef ATTRIBUTE_NOCLONE
22  #define ATTRIBUTE_NOCLONE __attribute__((__noclone__))
23  #endif
24  
25  static uint32_t tests[8] = {
26      0x00000000, 0x00000001, 0x7FFFFFFE, 0x7FFFFFFF,
27      0x80000000, 0x80000001, 0xFFFFFFFE, 0xFFFFFFFF,
28  };
29  
30  #define LOW    3ULL
31  #define HIGH   (1ULL << 63)
32  #define MIDDLE (-1ULL & ~LOW & ~HIGH)
33  
expand16(unsigned x)34  static uint64_t expand16(unsigned x)
35  {
36      return (x & LOW) | ((x & 4) ? MIDDLE : 0) | (x & 0x8000 ? HIGH : 0);
37  }
38  
expand(uint32_t x)39  static Int128 expand(uint32_t x)
40  {
41      uint64_t l, h;
42      l = expand16(x & 65535);
43      h = expand16(x >> 16);
44      return (Int128) int128_make128(l, h);
45  };
46  
test_and(void)47  static void test_and(void)
48  {
49      int i, j;
50  
51      for (i = 0; i < ARRAY_SIZE(tests); ++i) {
52          for (j = 0; j < ARRAY_SIZE(tests); ++j) {
53              Int128 a = expand(tests[i]);
54              Int128 b = expand(tests[j]);
55              Int128 r = expand(tests[i] & tests[j]);
56              Int128 s = int128_and(a, b);
57              g_assert_cmpuint(int128_getlo(r), ==, int128_getlo(s));
58              g_assert_cmpuint(int128_gethi(r), ==, int128_gethi(s));
59          }
60      }
61  }
62  
test_add(void)63  static void test_add(void)
64  {
65      int i, j;
66  
67      for (i = 0; i < ARRAY_SIZE(tests); ++i) {
68          for (j = 0; j < ARRAY_SIZE(tests); ++j) {
69              Int128 a = expand(tests[i]);
70              Int128 b = expand(tests[j]);
71              Int128 r = expand(tests[i] + tests[j]);
72              Int128 s = int128_add(a, b);
73              g_assert_cmpuint(int128_getlo(r), ==, int128_getlo(s));
74              g_assert_cmpuint(int128_gethi(r), ==, int128_gethi(s));
75          }
76      }
77  }
78  
test_sub(void)79  static void test_sub(void)
80  {
81      int i, j;
82  
83      for (i = 0; i < ARRAY_SIZE(tests); ++i) {
84          for (j = 0; j < ARRAY_SIZE(tests); ++j) {
85              Int128 a = expand(tests[i]);
86              Int128 b = expand(tests[j]);
87              Int128 r = expand(tests[i] - tests[j]);
88              Int128 s = int128_sub(a, b);
89              g_assert_cmpuint(int128_getlo(r), ==, int128_getlo(s));
90              g_assert_cmpuint(int128_gethi(r), ==, int128_gethi(s));
91          }
92      }
93  }
94  
test_neg(void)95  static void test_neg(void)
96  {
97      int i;
98  
99      for (i = 0; i < ARRAY_SIZE(tests); ++i) {
100          Int128 a = expand(tests[i]);
101          Int128 r = expand(-tests[i]);
102          Int128 s = int128_neg(a);
103          g_assert_cmpuint(int128_getlo(r), ==, int128_getlo(s));
104          g_assert_cmpuint(int128_gethi(r), ==, int128_gethi(s));
105      }
106  }
107  
test_nz(void)108  static void test_nz(void)
109  {
110      int i, j;
111  
112      for (i = 0; i < ARRAY_SIZE(tests); ++i) {
113          for (j = 0; j < ARRAY_SIZE(tests); ++j) {
114              Int128 a = expand(tests[i]);
115              g_assert_cmpuint(int128_nz(a), ==, tests[i] != 0);
116          }
117      }
118  }
119  
test_le(void)120  static void test_le(void)
121  {
122      int i, j;
123  
124      for (i = 0; i < ARRAY_SIZE(tests); ++i) {
125          for (j = 0; j < ARRAY_SIZE(tests); ++j) {
126              /* Signed comparison */
127              int32_t a = (int32_t) tests[i];
128              int32_t b = (int32_t) tests[j];
129              g_assert_cmpuint(int128_le(expand(a), expand(b)), ==, a <= b);
130          }
131      }
132  }
133  
test_lt(void)134  static void test_lt(void)
135  {
136      int i, j;
137  
138      for (i = 0; i < ARRAY_SIZE(tests); ++i) {
139          for (j = 0; j < ARRAY_SIZE(tests); ++j) {
140              /* Signed comparison */
141              int32_t a = (int32_t) tests[i];
142              int32_t b = (int32_t) tests[j];
143              g_assert_cmpuint(int128_lt(expand(a), expand(b)), ==, a < b);
144          }
145      }
146  }
147  
test_ge(void)148  static void test_ge(void)
149  {
150      int i, j;
151  
152      for (i = 0; i < ARRAY_SIZE(tests); ++i) {
153          for (j = 0; j < ARRAY_SIZE(tests); ++j) {
154              /* Signed comparison */
155              int32_t a = (int32_t) tests[i];
156              int32_t b = (int32_t) tests[j];
157              g_assert_cmpuint(int128_ge(expand(a), expand(b)), ==, a >= b);
158          }
159      }
160  }
161  
test_gt(void)162  static void test_gt(void)
163  {
164      int i, j;
165  
166      for (i = 0; i < ARRAY_SIZE(tests); ++i) {
167          for (j = 0; j < ARRAY_SIZE(tests); ++j) {
168              /* Signed comparison */
169              int32_t a = (int32_t) tests[i];
170              int32_t b = (int32_t) tests[j];
171              g_assert_cmpuint(int128_gt(expand(a), expand(b)), ==, a > b);
172          }
173      }
174  }
175  
176  /* Make sure to test undefined behavior at runtime! */
177  
178  static void __attribute__((__noinline__)) ATTRIBUTE_NOCLONE
test_rshift_one(uint32_t x,int n,uint64_t h,uint64_t l)179  test_rshift_one(uint32_t x, int n, uint64_t h, uint64_t l)
180  {
181      Int128 a = expand(x);
182      Int128 r = int128_rshift(a, n);
183      g_assert_cmpuint(int128_getlo(r), ==, l);
184      g_assert_cmpuint(int128_gethi(r), ==, h);
185  }
186  
test_rshift(void)187  static void test_rshift(void)
188  {
189      test_rshift_one(0x00010000U, 64, 0x0000000000000000ULL, 0x0000000000000001ULL);
190      test_rshift_one(0x80010000U, 64, 0xFFFFFFFFFFFFFFFFULL, 0x8000000000000001ULL);
191      test_rshift_one(0x7FFE0000U, 64, 0x0000000000000000ULL, 0x7FFFFFFFFFFFFFFEULL);
192      test_rshift_one(0xFFFE0000U, 64, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFEULL);
193      test_rshift_one(0x00010000U, 60, 0x0000000000000000ULL, 0x0000000000000010ULL);
194      test_rshift_one(0x80010000U, 60, 0xFFFFFFFFFFFFFFF8ULL, 0x0000000000000010ULL);
195      test_rshift_one(0x00018000U, 60, 0x0000000000000000ULL, 0x0000000000000018ULL);
196      test_rshift_one(0x80018000U, 60, 0xFFFFFFFFFFFFFFF8ULL, 0x0000000000000018ULL);
197      test_rshift_one(0x7FFE0000U, 60, 0x0000000000000007ULL, 0xFFFFFFFFFFFFFFE0ULL);
198      test_rshift_one(0xFFFE0000U, 60, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFE0ULL);
199      test_rshift_one(0x7FFE8000U, 60, 0x0000000000000007ULL, 0xFFFFFFFFFFFFFFE8ULL);
200      test_rshift_one(0xFFFE8000U, 60, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFE8ULL);
201      test_rshift_one(0x00018000U,  0, 0x0000000000000001ULL, 0x8000000000000000ULL);
202      test_rshift_one(0x80018000U,  0, 0x8000000000000001ULL, 0x8000000000000000ULL);
203      test_rshift_one(0x7FFE0000U,  0, 0x7FFFFFFFFFFFFFFEULL, 0x0000000000000000ULL);
204      test_rshift_one(0xFFFE0000U,  0, 0xFFFFFFFFFFFFFFFEULL, 0x0000000000000000ULL);
205      test_rshift_one(0x7FFE8000U,  0, 0x7FFFFFFFFFFFFFFEULL, 0x8000000000000000ULL);
206      test_rshift_one(0xFFFE8000U,  0, 0xFFFFFFFFFFFFFFFEULL, 0x8000000000000000ULL);
207  }
208  
209  static void __attribute__((__noinline__)) ATTRIBUTE_NOCLONE
test_urshift_one(uint32_t x,int n,uint64_t h,uint64_t l)210  test_urshift_one(uint32_t x, int n, uint64_t h, uint64_t l)
211  {
212      Int128 a = expand(x);
213      Int128 r = int128_urshift(a, n);
214      g_assert_cmpuint(int128_getlo(r), ==, l);
215      g_assert_cmpuint(int128_gethi(r), ==, h);
216  }
217  
test_urshift(void)218  static void test_urshift(void)
219  {
220      test_urshift_one(0x00010000U, 64, 0x0000000000000000ULL,
221                       0x0000000000000001ULL);
222      test_urshift_one(0x80010000U, 64, 0x0000000000000000ULL,
223                       0x8000000000000001ULL);
224      test_urshift_one(0x7FFE0000U, 64, 0x0000000000000000ULL,
225                       0x7FFFFFFFFFFFFFFEULL);
226      test_urshift_one(0xFFFE0000U, 64, 0x0000000000000000ULL,
227                       0xFFFFFFFFFFFFFFFEULL);
228      test_urshift_one(0x00010000U, 60, 0x0000000000000000ULL,
229                       0x0000000000000010ULL);
230      test_urshift_one(0x80010000U, 60, 0x0000000000000008ULL,
231                       0x0000000000000010ULL);
232      test_urshift_one(0x00018000U, 60, 0x0000000000000000ULL,
233                       0x0000000000000018ULL);
234      test_urshift_one(0x80018000U, 60, 0x0000000000000008ULL,
235                       0x0000000000000018ULL);
236      test_urshift_one(0x7FFE0000U, 60, 0x0000000000000007ULL,
237                       0xFFFFFFFFFFFFFFE0ULL);
238      test_urshift_one(0xFFFE0000U, 60, 0x000000000000000FULL,
239                       0xFFFFFFFFFFFFFFE0ULL);
240      test_urshift_one(0x7FFE8000U, 60, 0x0000000000000007ULL,
241                       0xFFFFFFFFFFFFFFE8ULL);
242      test_urshift_one(0xFFFE8000U, 60, 0x000000000000000FULL,
243                       0xFFFFFFFFFFFFFFE8ULL);
244      test_urshift_one(0x00018000U,  0, 0x0000000000000001ULL,
245                       0x8000000000000000ULL);
246      test_urshift_one(0x80018000U,  0, 0x8000000000000001ULL,
247                       0x8000000000000000ULL);
248      test_urshift_one(0x7FFE0000U,  0, 0x7FFFFFFFFFFFFFFEULL,
249                       0x0000000000000000ULL);
250      test_urshift_one(0xFFFE0000U,  0, 0xFFFFFFFFFFFFFFFEULL,
251                       0x0000000000000000ULL);
252      test_urshift_one(0x7FFE8000U,  0, 0x7FFFFFFFFFFFFFFEULL,
253                       0x8000000000000000ULL);
254      test_urshift_one(0xFFFE8000U,  0, 0xFFFFFFFFFFFFFFFEULL,
255                       0x8000000000000000ULL);
256  }
257  
main(int argc,char ** argv)258  int main(int argc, char **argv)
259  {
260      g_test_init(&argc, &argv, NULL);
261      g_test_add_func("/int128/int128_and", test_and);
262      g_test_add_func("/int128/int128_add", test_add);
263      g_test_add_func("/int128/int128_sub", test_sub);
264      g_test_add_func("/int128/int128_neg", test_neg);
265      g_test_add_func("/int128/int128_nz", test_nz);
266      g_test_add_func("/int128/int128_le", test_le);
267      g_test_add_func("/int128/int128_lt", test_lt);
268      g_test_add_func("/int128/int128_ge", test_ge);
269      g_test_add_func("/int128/int128_gt", test_gt);
270      g_test_add_func("/int128/int128_rshift", test_rshift);
271      g_test_add_func("/int128/int128_urshift", test_urshift);
272      return g_test_run();
273  }
274