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
|
/** bit-precise integers
width: 2, 4, 7, 8, 9, 15, 16, 17, 24, 32, 33, 40, 48, 63, 64, 65
*/
#include <testfwk.h>
// clang 11 supports bit-precise types, but deviates a bit from C23.
#if __clang_major__ == 11
#define __SDCC_BITINT_MAXWIDTH 128
#define _BitInt _ExtInt
#endif
#if __SDCC_BITINT_MAXWIDTH >= {width} // TODO: When we can regression-test in --std-c23 mode, use the standard macro from limits.h instead!
#if {width} <= 40 || !defined (__SDCC_pdk14) // Lack of memory
typedef _BitInt({width}) bitinttype;
typedef unsigned _BitInt({width}) ubitinttype;
volatile bitinttype a, b;
volatile ubitinttype ua, ub;
volatile char c = 1;
#endif
#endif
void testBitIntArith(void)
{
#ifndef __clang_major__ // clang 11 doesn't support == between _BitInt and int
#if __SDCC_BITINT_MAXWIDTH >= {width} // TODO: When we can regression-test in --std-c23 mode, use the standard macro from limits.h instead!
#if ({width} <= 40 || !defined (__SDCC_pdk14)) && ({width} <= 48 || !defined (__SDCC_pdk15)) // Lack of memory
a = -1, b = 1;
ASSERT(a + b == 0);
ua = 1, ub = 1;
ASSERT(ua + ub == 2);
// From here on, we do the computation on the left at runtime, the one on the right at compile time, to check both.
a = 3, ua = 3;
#if {width} >= 4
ASSERT(a << 1 == (bitinttype)(3) << 1);
ASSERT(ua << 1 == (ubitinttype)(3) << 1);
ASSERT(ua << 3 == (ubitinttype)(3) << 3);
#endif
ASSERT(a >> 1 == (bitinttype)(3) >> 1);
ASSERT(ua >> 1 == (ubitinttype)(3) >> 1);
ua = 0xffffffff;
ASSERT(ua << 1 == (ubitinttype)(0xffffffff) << 1);
ASSERT(ua >> 1 == (ubitinttype)(0xffffffff) >> 1);
ASSERT(ua << c == (ubitinttype)(0xffffffff) << 1);
ASSERT(ua >> c == (ubitinttype)(0xffffffff) >> 1);
a = 23, b = -42;
ua = 23, ub = -42;
#if {width} >= 8 // Signed overflow is undefined behaviour
ASSERT(a + b == (bitinttype)(23) + (bitinttype)(-42));
ASSERT(a - b == (bitinttype)(23) - (bitinttype)(-42));
#endif
// Wrap on unsigned overflow
ASSERT(ua + ub == (ubitinttype)(23) + (ubitinttype)(-42));
ASSERT(ua - ub == (ubitinttype)(23) - (ubitinttype)(-42));
#if !defined(__SDCC_pdk13) && !defined(__SDCC_pdk14) && !defined(__SDCC_pdk15) // Lack of memory
#if {width} >= 11 // Signed overflow is undefined behaviour
ASSERT(a * b == (bitinttype)(23) * (bitinttype)(-42));
#endif
#if {width} >= 8 // Signed overflow is undefined behaviour
ASSERT(a % b == (bitinttype)(23) % (bitinttype)(-42));
ASSERT(a / b == (bitinttype)(23) / (bitinttype)(-42));
#endif
ASSERT(ua * ub == (ubitinttype)(23) * (ubitinttype)(-42));
ASSERT(ua % ub == (ubitinttype)(23) % (ubitinttype)(-42));
ASSERT(ua / ub == (ubitinttype)(23) / (ubitinttype)(-42));
#if !defined(__SDCC_mcs51) && !defined(__SDCC_ds390) // Bug #3355
ASSERT((a < b) == ((bitinttype)(23) < (bitinttype)(-42)));
ASSERT((a <= b) == ((bitinttype)(23) <= (bitinttype)(-42)));
ASSERT((ua < ub) == ((ubitinttype)(23) < (ubitinttype)(-42)));
ASSERT((ua <= ub) == ((ubitinttype)(23) <= (ubitinttype)(-42)));
#endif
ASSERT((ua & ub) == ((ubitinttype)(23) & (ubitinttype)(-42)));
ASSERT((ua | ub) == ((ubitinttype)(23) | (ubitinttype)(-42)));
ASSERT((ua ^ ub) == ((ubitinttype)(23) ^ (ubitinttype)(-42)));
// Test increment / decrement and it wraparound for unsigned _BitInt.
ua = 1;
ASSERT(--ua == 0);
ASSERT(--ua == (ubitinttype)0xffffffffffffffffull);
ASSERT(++ua == 0);
ua = 1ull << ({width} - 1);
ASSERT(ua / 4 == (1ull << ({width} - 1)) / 4ull); // Underlying issue of bug #3855: a signed division was used for some unsigned _BitInt divisions.
#endif
#endif
#endif
#endif
}
|