qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

test-int128.c (9338B)


      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 
     34 static uint64_t expand16(unsigned x)
     35 {
     36     return (x & LOW) | ((x & 4) ? MIDDLE : 0) | (x & 0x8000 ? HIGH : 0);
     37 }
     38 
     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 
     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 
     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 
     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 
     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 
    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 
    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 
    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 
    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 
    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
    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 
    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
    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 
    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 
    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 }