1 /*
2  * Copyright (c) 2015 Wind River Systems, Inc.
3  * Copyright (c) 2018 Intel Corporation
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #include <ztest.h>
9 
10 /* Built-time math test.  Zephyr code depends on a standard C ABI with
11  * 2's complement signed math.  As this isn't technically guaranteed
12  * by the compiler or language standard, validate it explicitly here.
13  */
14 
15 /* Recent GCC's can detect integer overflow in static expressions and
16  * will warn about it heplfully.  But obviously integer overflow is
17  * the whole point here, so turn that warning off.
18  */
19 #ifdef __GNUC__
20 #pragma GCC diagnostic ignored "-Woverflow"
21 #endif
22 
23 /* Two's complement negation check: "-N" must equal "(~N)+1" */
24 #define NEG_CHECK(T, N) BUILD_ASSERT((-((T)N)) == (~((T)N)) + 1)
25 
26 /* Checks that MAX+1==MIN in the given type */
27 #define ROLLOVER_CHECK(T, MAX, MIN) BUILD_ASSERT((T)((T)1 + (T)MAX) == (T)MIN)
28 
29 #ifdef __clang__
30 #pragma clang diagnostic push
31 #pragma clang diagnostic ignored "-Winteger-overflow"
32 #endif
33 
34 ROLLOVER_CHECK(unsigned int, 0xffffffff, 0);
35 ROLLOVER_CHECK(unsigned short, 0xffff, 0);
36 ROLLOVER_CHECK(unsigned char, 0xff, 0);
37 
38 NEG_CHECK(signed char, 1);
39 NEG_CHECK(signed char, 0);
40 NEG_CHECK(signed char, -1);
41 NEG_CHECK(signed char, 0x80);
42 NEG_CHECK(signed char, 0x7f);
43 ROLLOVER_CHECK(signed char, 127, -128);
44 
45 NEG_CHECK(short, 1);
46 NEG_CHECK(short, 0);
47 NEG_CHECK(short, -1);
48 NEG_CHECK(short, 0x8000);
49 NEG_CHECK(short, 0x7fff);
50 ROLLOVER_CHECK(short, 32767, -32768);
51 
52 NEG_CHECK(int, 1);
53 NEG_CHECK(int, 0);
54 NEG_CHECK(int, -1);
55 NEG_CHECK(int, 0x80000000);
56 NEG_CHECK(int, 0x7fffffff);
57 ROLLOVER_CHECK(int, 2147483647, -2147483648);
58 
59 #ifdef __clang__
60 #pragma clang diagnostic pop
61 #endif
62 
63 /**
64  * @addtogroup kernel_common_tests
65  * @{
66  */
67 
68 /**
69  * @brief Test integer arithmetic operations
70  *
71  * @details Test multiplication and division of two
72  * integers
73  */
test_intmath(void)74 void test_intmath(void)
75 {
76 	/*
77 	 * Declaring volatile so the compiler doesn't try to optimize any
78 	 * of the math away at build time
79 	 */
80 	volatile uint64_t bignum, ba, bb;
81 	volatile uint32_t num, a, b;
82 
83 	ba = 0x00000012ABCDEF12ULL;
84 	bb = 0x0000001000000111ULL;
85 	bignum = ba * bb;
86 	zassert_true((bignum == 0xbcdf0509369bf232ULL), "64-bit multiplication failed");
87 
88 	a = 30000U;
89 	b = 5872U;
90 	num = a * b;
91 	zassert_true((num == 176160000U), "32-bit multiplication failed");
92 
93 	a = 234424432U;
94 	b = 98982U;
95 	num = a / b;
96 	zassert_true((num == 2368U), "32-bit division failed");
97 }
98 /**
99  * @}
100  */
101 
102 
103 
test_main(void)104 void test_main(void)
105 {
106 	ztest_test_suite(intmath,
107 			 ztest_unit_test(test_intmath)
108 			 );
109 
110 	ztest_run_test_suite(intmath);
111 }
112