From c79fe8dbb90c54f3c06809d643d53dabbf5b503c Mon Sep 17 00:00:00 2001 From: Zachary Wassall Date: Mon, 18 Nov 2024 15:46:34 -0500 Subject: [PATCH] Update math_test example with 48-bit math (#520) The individual commits by @runer112 were: 817a526 Test 48-bit math routines 973bb53 Fix printing 43ee410 Test operations even if not hooked up to routines yet eab2d36 Try to coax compiler into using 24-bit and 48-bit math routines 059b8aa Use bit-precise integer types when available 422e489 Fix UB from casting e83d384 Remove unnecessary coments a4e66c6 Update test expected values --- .../math_test/autotest.json | 42 +- .../standalone_examples/math_test/src/main.c | 372 ++++++++++++------ 2 files changed, 263 insertions(+), 151 deletions(-) diff --git a/examples/standalone_examples/math_test/autotest.json b/examples/standalone_examples/math_test/autotest.json index dbda34df6..33b84685a 100644 --- a/examples/standalone_examples/math_test/autotest.json +++ b/examples/standalone_examples/math_test/autotest.json @@ -62,7 +62,7 @@ "start": "vram_start", "size": "vram_16_size", "expected_CRCs": [ - "0B3D9374" + "B9510AD8" ] }, "neg": { @@ -70,7 +70,7 @@ "start": "vram_start", "size": "vram_16_size", "expected_CRCs": [ - "10A84E1B" + "7122851F" ] }, "abs": { @@ -78,7 +78,7 @@ "start": "vram_start", "size": "vram_16_size", "expected_CRCs": [ - "D7807035" + "7614EAC3" ] }, "bitrev": { @@ -86,7 +86,7 @@ "start": "vram_start", "size": "vram_16_size", "expected_CRCs": [ - "BBADF82E" + "1492AAC4" ] }, "bswap": { @@ -94,7 +94,7 @@ "start": "vram_start", "size": "vram_16_size", "expected_CRCs": [ - "7709B5AE" + "C9C416BB" ] }, "popcnt": { @@ -102,7 +102,7 @@ "start": "vram_start", "size": "vram_16_size", "expected_CRCs": [ - "62628040" + "E3E46F91" ] }, "and": { @@ -110,7 +110,7 @@ "start": "vram_start", "size": "vram_16_size", "expected_CRCs": [ - "32DEF9D5" + "844F62ED" ] }, "or": { @@ -118,7 +118,7 @@ "start": "vram_start", "size": "vram_16_size", "expected_CRCs": [ - "4E247920" + "6529AA0B" ] }, "xor": { @@ -126,7 +126,7 @@ "start": "vram_start", "size": "vram_16_size", "expected_CRCs": [ - "257F7002" + "2CAD0372" ] }, "add": { @@ -134,7 +134,7 @@ "start": "vram_start", "size": "vram_16_size", "expected_CRCs": [ - "CD575A4D" + "F94DD5D6" ] }, "sub": { @@ -142,7 +142,7 @@ "start": "vram_start", "size": "vram_16_size", "expected_CRCs": [ - "EE1C5453" + "167FF1A7" ] }, "shl": { @@ -150,7 +150,7 @@ "start": "vram_start", "size": "vram_16_size", "expected_CRCs": [ - "FD8CA2EC" + "BF87D382" ] }, "shru": { @@ -158,7 +158,7 @@ "start": "vram_start", "size": "vram_16_size", "expected_CRCs": [ - "9754CB4F" + "0F7AE868" ] }, "shrs": { @@ -166,7 +166,7 @@ "start": "vram_start", "size": "vram_16_size", "expected_CRCs": [ - "AB5BE5CB" + "A0BA88A7" ] }, "mulu": { @@ -174,7 +174,7 @@ "start": "vram_start", "size": "vram_16_size", "expected_CRCs": [ - "C6A6FF7D" + "B7CBA439" ] }, "divu": { @@ -182,7 +182,7 @@ "start": "vram_start", "size": "vram_16_size", "expected_CRCs": [ - "F973C020" + "1AC569AB" ] }, "remu": { @@ -190,7 +190,7 @@ "start": "vram_start", "size": "vram_16_size", "expected_CRCs": [ - "5196C205" + "D29F5374" ] }, "divs": { @@ -198,7 +198,7 @@ "start": "vram_start", "size": "vram_16_size", "expected_CRCs": [ - "2A13A348" + "63331417" ] }, "rems": { @@ -206,7 +206,7 @@ "start": "vram_start", "size": "vram_16_size", "expected_CRCs": [ - "F45969EF" + "1322808B" ] }, "div_q": { @@ -214,7 +214,7 @@ "start": "vram_start", "size": "vram_16_size", "expected_CRCs": [ - "EAFFC6D3" + "B5F9B54D" ] }, "div_r": { @@ -222,7 +222,7 @@ "start": "vram_start", "size": "vram_16_size", "expected_CRCs": [ - "B9786654" + "60B1E228" ] }, "done": { diff --git a/examples/standalone_examples/math_test/src/main.c b/examples/standalone_examples/math_test/src/main.c index 72004bbac..9815152b1 100644 --- a/examples/standalone_examples/math_test/src/main.c +++ b/examples/standalone_examples/math_test/src/main.c @@ -13,6 +13,7 @@ #ifdef _EZ80 + # include # include # include @@ -24,10 +25,25 @@ # endif #else -# ifndef __cplusplus -typedef int32_t int24_t; -typedef uint32_t uint24_t; -# else + +# define x_printf printf + +# if __STDC_VERSION__ >= 202311L + +typedef _BitInt(24) int24_t; +typedef unsigned _BitInt(24) uint24_t; +typedef _BitInt(48) int48_t; +typedef unsigned _BitInt(48) uint48_t; + +# elif defined(__clang__) + +typedef _ExtInt(24) int24_t; +typedef unsigned _ExtInt(24) uint24_t; +typedef _ExtInt(48) int48_t; +typedef unsigned _ExtInt(48) uint48_t; + +# elif defined(__cplusplus) + template struct IntN final { @@ -44,19 +60,56 @@ struct IntN final }; using uint24_t = IntN<24, uint_fast32_t>; using int24_t = IntN<24, int_fast32_t>; +using uint48_t = IntN<48, uint_fast64_t>; +using int48_t = IntN<48, int_fast64_t>; + +# else + +#error "Use a more modern language standard/compiler" + # endif static int24_t __builtin_bitreverse24(int24_t x) { return __builtin_bitreverse32(x) >> 8; + // return __builtin_bitreverse16(x >> 8) | __builtin_bitreverse8(x) << 16; } + #endif +static int48_t __builtin_bitreverse48(int48_t x) +{ + // return __builtin_bitreverse64(x) >> 16; + return __builtin_bitreverse32(x >> 16) | (int48_t)__builtin_bitreverse16(x) << 32; +} +static uint24_t __builtin_bswap24(uint24_t x) +{ + return __builtin_bswap32(x) >> 8; + // return __builtin_bswap16(x >> 8) | (uint8_t)x << 16; +} +static uint48_t __builtin_bswap48(uint48_t x) +{ + return __builtin_bswap64(x) >> 16; + // return __builtin_bswap32(x >> 16) | (uint48_t)(uint16_t)x << 32; +} +static int __builtin_popcounti48(uint48_t x) +{ + return __builtin_popcountll(x & ((1LL << 48) - 1)); +} +static int24_t iabs(int24_t x) +{ + return x < 0 ? (int24_t)-x : x; +} +static int48_t i48abs(int48_t x) +{ + return x < 0 ? (int48_t)-x : x; +} -#if INTERACTIVE || !defined(_EZ80) -# define x_printf printf + +#if INTERACTIVE && defined(_EZ80) +# define x_printffull x_printf #else -# define x_printf(...) dbg_printf(__VA_ARGS__) +# define x_printffull(format, ...) x_printf(format "\n", __VA_ARGS__) #endif static void separateOutput() @@ -89,18 +142,18 @@ static void finishOutput() return (type)(op(x)); \ } -#define DEFINE_BINOP_FUNC_FUNC(type, name, func, post) \ - static type name##_(type x, type y) \ - { \ - return (type)(func(x, y)post); \ - } - #define DEFINE_BINOP_INFIX_FUNC(type, name, op) \ static type name##_(type x, type y) \ { \ return (type)(x op y); \ } +#define DEFINE_BINOP_DIV_LIKE_FUNC(type, name, func, post) \ + static type name##_(type x, type y) \ + { \ + return (type)(func(x + 0, y + 0)post); \ + } + #define DEFINE_UNOP_PREFIX_FUNC_B(u, name, op) \ DEFINE_UNOP_PREFIX_FUNC(u##int8_t, b##name, op) #define DEFINE_UNOP_PREFIX_FUNC_S(u, name, op) \ @@ -109,20 +162,11 @@ static void finishOutput() DEFINE_UNOP_PREFIX_FUNC(u##int24_t, i##name, op) #define DEFINE_UNOP_PREFIX_FUNC_L(u, name, op) \ DEFINE_UNOP_PREFIX_FUNC(u##int32_t, l##name, op) +#define DEFINE_UNOP_PREFIX_FUNC_I48(u, name, op) \ + DEFINE_UNOP_PREFIX_FUNC(u##int48_t, i48##name, op) #define DEFINE_UNOP_PREFIX_FUNC_LL(u, name, op) \ DEFINE_UNOP_PREFIX_FUNC(u##int64_t, ll##name, op) -#define DEFINE_BINOP_FUNC_FUNC_B(u, name, func, post) \ - DEFINE_BINOP_FUNC_FUNC(u##int8_t, b##name, b##func, post) -#define DEFINE_BINOP_FUNC_FUNC_S(u, name, func, post) \ - DEFINE_BINOP_FUNC_FUNC(u##int16_t, s##name, s##func, post) -#define DEFINE_BINOP_FUNC_FUNC_I(u, name, func, post) \ - DEFINE_BINOP_FUNC_FUNC(u##int24_t, i##name, func, post) -#define DEFINE_BINOP_FUNC_FUNC_L(u, name, func, post) \ - DEFINE_BINOP_FUNC_FUNC(u##int32_t, l##name, l##func, post) -#define DEFINE_BINOP_FUNC_FUNC_LL(u, name, func, post) \ - DEFINE_BINOP_FUNC_FUNC(u##int64_t, ll##name, ll##func, post) - #define DEFINE_BINOP_INFIX_FUNC_B(u, name, op) \ DEFINE_BINOP_INFIX_FUNC(u##int8_t, b##name, op) #define DEFINE_BINOP_INFIX_FUNC_S(u, name, op) \ @@ -131,9 +175,24 @@ static void finishOutput() DEFINE_BINOP_INFIX_FUNC(u##int24_t, i##name, op) #define DEFINE_BINOP_INFIX_FUNC_L(u, name, op) \ DEFINE_BINOP_INFIX_FUNC(u##int32_t, l##name, op) +#define DEFINE_BINOP_INFIX_FUNC_I48(u, name, op) \ + DEFINE_BINOP_INFIX_FUNC(u##int48_t, i48##name, op) #define DEFINE_BINOP_INFIX_FUNC_LL(u, name, op) \ DEFINE_BINOP_INFIX_FUNC(u##int64_t, ll##name, op) +#define DEFINE_BINOP_DIV_LIKE_FUNC_B(u, name, func, post) \ + DEFINE_BINOP_DIV_LIKE_FUNC(u##int8_t, b##name, b##func, post) +#define DEFINE_BINOP_DIV_LIKE_FUNC_S(u, name, func, post) \ + DEFINE_BINOP_DIV_LIKE_FUNC(u##int16_t, s##name, s##func, post) +#define DEFINE_BINOP_DIV_LIKE_FUNC_I(u, name, func, post) \ + DEFINE_BINOP_DIV_LIKE_FUNC(u##int24_t, i##name, func, post) +#define DEFINE_BINOP_DIV_LIKE_FUNC_L(u, name, func, post) \ + DEFINE_BINOP_DIV_LIKE_FUNC(u##int32_t, l##name, l##func, post) +#define DEFINE_BINOP_DIV_LIKE_FUNC_I48(u, name, func, post) \ + DEFINE_BINOP_DIV_LIKE_FUNC(u##int48_t, i48##name, i48##func, post) +#define DEFINE_BINOP_DIV_LIKE_FUNC_LL(u, name, func, post) \ + DEFINE_BINOP_DIV_LIKE_FUNC(u##int64_t, ll##name, ll##func, post) + #define DEFINE_UNOP_PREFIX_FUNC_B_TO_S(u, name, op) \ DEFINE_UNOP_PREFIX_FUNC_B(u, name, op) \ DEFINE_UNOP_PREFIX_FUNC_S(u, name, op) @@ -143,8 +202,11 @@ static void finishOutput() #define DEFINE_UNOP_PREFIX_FUNC_B_TO_L(u, name, op) \ DEFINE_UNOP_PREFIX_FUNC_B_TO_I(u, name, op) \ DEFINE_UNOP_PREFIX_FUNC_L(u, name, op) +#define DEFINE_UNOP_PREFIX_FUNC_B_TO_I48(u, name, op) \ + DEFINE_UNOP_PREFIX_FUNC_B_TO_L(u, name, op) \ + DEFINE_UNOP_PREFIX_FUNC_I48(u, name, op) #define DEFINE_UNOP_PREFIX_FUNC_B_TO_LL(u, name, op) \ - DEFINE_UNOP_PREFIX_FUNC_B_TO_L(u, name, op) \ + DEFINE_UNOP_PREFIX_FUNC_B_TO_I48(u, name, op) \ DEFINE_UNOP_PREFIX_FUNC_LL(u, name, op) #define DEFINE_BINOP_INFIX_FUNC_B_TO_S(u, name, op) \ @@ -156,38 +218,63 @@ static void finishOutput() #define DEFINE_BINOP_INFIX_FUNC_B_TO_L(u, name, op) \ DEFINE_BINOP_INFIX_FUNC_B_TO_I(u, name, op) \ DEFINE_BINOP_INFIX_FUNC_L(u, name, op) +#define DEFINE_BINOP_INFIX_FUNC_B_TO_I48(u, name, op) \ + DEFINE_BINOP_INFIX_FUNC_B_TO_L(u, name, op) \ + DEFINE_BINOP_INFIX_FUNC_I48(u, name, op) #define DEFINE_BINOP_INFIX_FUNC_B_TO_LL(u, name, op) \ - DEFINE_BINOP_INFIX_FUNC_B_TO_L(u, name, op) \ + DEFINE_BINOP_INFIX_FUNC_B_TO_I48(u, name, op) \ DEFINE_BINOP_INFIX_FUNC_LL(u, name, op) -#define DEFINE_BINOP_FUNC_FUNC_I_TO_L(u, name, func, post) \ - DEFINE_BINOP_FUNC_FUNC_I(u, name, func, post) \ - DEFINE_BINOP_FUNC_FUNC_L(u, name, func, post) -#define DEFINE_BINOP_FUNC_FUNC_I_TO_LL(u, name, func, post) \ - DEFINE_BINOP_FUNC_FUNC_I_TO_L(u, name, func, post) \ - DEFINE_BINOP_FUNC_FUNC_LL(u, name, func, post) - - -#define DEFINE_UNOP_TYPE(u) \ - typedef struct u##UnOp_ \ - { \ - const char *name; \ - u##int8_t (*b)(u##int8_t); \ - u##int16_t (*s)(u##int16_t); \ - u##int24_t (*i)(u##int24_t); \ - u##int32_t (*l)(u##int32_t); \ - u##int64_t (*ll)(u##int64_t); \ +#define DEFINE_BINOP_DIV_LIKE_FUNC_I_TO_L(u, name, func, post) \ + DEFINE_BINOP_DIV_LIKE_FUNC_I(u, name, func, post) \ + DEFINE_BINOP_DIV_LIKE_FUNC_L(u, name, func, post) +#define DEFINE_BINOP_DIV_LIKE_FUNC_I_TO_I48(u, name, func, post) \ + DEFINE_BINOP_DIV_LIKE_FUNC_I_TO_L(u, name, func, post) \ + // DEFINE_BINOP_DIV_LIKE_FUNC_I48(u, name, func, post) +#define DEFINE_BINOP_DIV_LIKE_FUNC_I_TO_LL(u, name, func, post) \ + DEFINE_BINOP_DIV_LIKE_FUNC_I_TO_I48(u, name, func, post) \ + DEFINE_BINOP_DIV_LIKE_FUNC_LL(u, name, func, post) + + +typedef struct Op_ +{ + bool isBinary; + bool isUnsigned; + const char *name; + void (*b)(); + void (*s)(); + void (*i)(); + void (*l)(); + void (*i48)(); + void (*ll)(); +} Op; + +#define DEFINE_UNOP_TYPE(u) \ + typedef struct u##UnOp_ \ + { \ + bool isBinary; \ + bool isUnsigned; \ + const char *name; \ + u##int8_t (*b)(u##int8_t); \ + u##int16_t (*s)(u##int16_t); \ + u##int24_t (*i)(u##int24_t); \ + u##int32_t (*l)(u##int32_t); \ + u##int48_t (*i48)(u##int48_t); \ + u##int64_t (*ll)(u##int64_t); \ } u##UnOp; -#define DEFINE_BINOP_TYPE(u) \ - typedef struct u##BinOp_ \ - { \ - const char *name; \ - u##int8_t (*b)(u##int8_t, u##int8_t); \ - u##int16_t (*s)(u##int16_t, u##int16_t); \ - u##int24_t (*i)(u##int24_t, u##int24_t); \ - u##int32_t (*l)(u##int32_t, u##int32_t); \ - u##int64_t (*ll)(u##int64_t, u##int64_t); \ +#define DEFINE_BINOP_TYPE(u) \ + typedef struct u##BinOp_ \ + { \ + bool isBinary; \ + bool isUnsigned; \ + const char *name; \ + u##int8_t (*b)(u##int8_t, u##int8_t); \ + u##int16_t (*s)(u##int16_t, u##int16_t); \ + u##int24_t (*i)(u##int24_t, u##int24_t); \ + u##int32_t (*l)(u##int32_t, u##int32_t); \ + u##int48_t (*i48)(u##int48_t, u##int48_t); \ + u##int64_t (*ll)(u##int64_t, u##int64_t); \ } u##BinOp; DEFINE_UNOP_TYPE() @@ -196,33 +283,47 @@ DEFINE_UNOP_TYPE(u) DEFINE_BINOP_TYPE() DEFINE_BINOP_TYPE(u) +static const bool _0IsUnsigned = 0; +static const bool _0IsUnsignedu = 1; + #define DEFINE_UNOP_STRUCT_B(u, name) \ - static const u##UnOp unop_##name = {#name, b##name##_}; + static const u##UnOp u##unop_##name = {0, _0IsUnsigned##u, #name, b##name##_}; #define DEFINE_UNOP_STRUCT_B_TO_S(u, name) \ - static const u##UnOp unop_##name = {#name, b##name##_, s##name##_}; + static const u##UnOp u##unop_##name = {0, _0IsUnsigned##u, #name, b##name##_, s##name##_}; #define DEFINE_UNOP_STRUCT_B_TO_I(u, name) \ - static const u##UnOp unop_##name = {#name, b##name##_, s##name##_, i##name##_}; + static const u##UnOp u##unop_##name = {0, _0IsUnsigned##u, #name, b##name##_, s##name##_, i##name##_}; #define DEFINE_UNOP_STRUCT_B_TO_L(u, name) \ - static const u##UnOp unop_##name = {#name, b##name##_, s##name##_, i##name##_, l##name##_}; + static const u##UnOp u##unop_##name = {0, _0IsUnsigned##u, #name, b##name##_, s##name##_, i##name##_, l##name##_}; +#define DEFINE_UNOP_STRUCT_B_TO_I48(u, name) \ + static const u##UnOp u##unop_##name = {0, _0IsUnsigned##u, #name, b##name##_, s##name##_, i##name##_, l##name##_, i48##name##_}; #define DEFINE_UNOP_STRUCT_B_TO_LL(u, name) \ - static const u##UnOp unop_##name = {#name, b##name##_, s##name##_, i##name##_, l##name##_, ll##name##_}; -#define DEFINE_UNOP_STRUCT_S_L_LL(u, name) \ - static const u##UnOp unop_##name = {#name, 0, s##name##_, 0, l##name##_, ll##name##_}; + static const u##UnOp u##unop_##name = {0, _0IsUnsigned##u, #name, b##name##_, s##name##_, i##name##_, l##name##_, i48##name##_, ll##name##_}; +#define DEFINE_UNOP_STRUCT_B_TO_LL_EXCEPT_I48(u, name) \ + static const u##UnOp u##unop_##name = {0, _0IsUnsigned##u, #name, b##name##_, s##name##_, i##name##_, l##name##_, NULL, ll##name##_}; +// clang version 15.0.0 (https://github.com/CE-Programming/llvm-project +// 23b78267b5d376b232475d0805a937e54b61e0d0): unable to legalize instruction: +// %5:_(s48) = G_BSWAP %0:_ (in function: i48bswap_) +#define DEFINE_UNOP_STRUCT_BSWAP(u, name) \ + static const u##UnOp u##unop_##name = {0, _0IsUnsigned##u, #name, NULL, s##name##_, i##name##_, l##name##_, NULL, ll##name##_}; #define DEFINE_BINOP_STRUCT_B(u, name) \ - static const u##BinOp binop_##name = {#name, b##name##_}; + static const u##BinOp u##binop_##name = {1, _0IsUnsigned##u, #name, b##name##_}; #define DEFINE_BINOP_STRUCT_B_TO_S(u, name) \ - static const u##BinOp binop_##name = {#name, b##name##_, s##name##_}; + static const u##BinOp u##binop_##name = {1, _0IsUnsigned##u, #name, b##name##_, s##name##_}; #define DEFINE_BINOP_STRUCT_B_TO_I(u, name) \ - static const u##BinOp binop_##name = {#name, b##name##_, s##name##_, i##name##_}; + static const u##BinOp u##binop_##name = {1, _0IsUnsigned##u, #name, b##name##_, s##name##_, i##name##_}; #define DEFINE_BINOP_STRUCT_B_TO_L(u, name) \ - static const u##BinOp binop_##name = {#name, b##name##_, s##name##_, i##name##_, l##name##_}; + static const u##BinOp u##binop_##name = {1, _0IsUnsigned##u, #name, b##name##_, s##name##_, i##name##_, l##name##_}; +#define DEFINE_BINOP_STRUCT_B_TO_I48(u, name) \ + static const u##BinOp u##binop_##name = {1, _0IsUnsigned##u, #name, b##name##_, s##name##_, i##name##_, l##name##_, i48##name##_}; #define DEFINE_BINOP_STRUCT_B_TO_LL(u, name) \ - static const u##BinOp binop_##name = {#name, b##name##_, s##name##_, i##name##_, l##name##_, ll##name##_}; + static const u##BinOp u##binop_##name = {1, _0IsUnsigned##u, #name, b##name##_, s##name##_, i##name##_, l##name##_, i48##name##_, ll##name##_}; #define DEFINE_BINOP_STRUCT_I_TO_L(u, name) \ - static const u##BinOp binop_##name = {#name, NULL, NULL, i##name##_, l##name##_}; + static const u##BinOp u##binop_##name = {1, _0IsUnsigned##u, #name, NULL, NULL, i##name##_, l##name##_}; +// #define DEFINE_BINOP_STRUCT_I_TO_I48(u, name) \ +// static const u##BinOp u##binop_##name = {1, _0IsUnsigned##u, #name, NULL, NULL, i##name##_, l##name##_, i48##name##_}; #define DEFINE_BINOP_STRUCT_I_TO_LL(u, name) \ - static const u##BinOp binop_##name = {#name, NULL, NULL, i##name##_, l##name##_, ll##name##_}; + static const u##BinOp u##binop_##name = {1, _0IsUnsigned##u, #name, NULL, NULL, i##name##_, l##name##_, NULL, ll##name##_}; #define DEFINE_UNOP_PREFIX_B(u, name, op) \ @@ -237,6 +338,9 @@ DEFINE_BINOP_TYPE(u) #define DEFINE_UNOP_PREFIX_B_TO_L(u, name, op) \ DEFINE_UNOP_PREFIX_FUNC_B_TO_L(u, name, op) \ DEFINE_UNOP_STRUCT_B_TO_L(u, name) +#define DEFINE_UNOP_PREFIX_B_TO_I48(u, name, op) \ + DEFINE_UNOP_PREFIX_FUNC_B_TO_I48(u, name, op) \ + DEFINE_UNOP_STRUCT_B_TO_I48(u, name) #define DEFINE_UNOP_PREFIX_B_TO_LL(u, name, op) \ DEFINE_UNOP_PREFIX_FUNC_B_TO_LL(u, name, op) \ DEFINE_UNOP_STRUCT_B_TO_LL(u, name) @@ -253,80 +357,97 @@ DEFINE_BINOP_TYPE(u) #define DEFINE_BINOP_INFIX_B_TO_L(u, name, op) \ DEFINE_BINOP_INFIX_FUNC_B_TO_L(u, name, op) \ DEFINE_BINOP_STRUCT_B_TO_L(u, name) +#define DEFINE_BINOP_INFIX_B_TO_I48(u, name, op) \ + DEFINE_BINOP_INFIX_FUNC_B_TO_I48(u, name, op) \ + DEFINE_BINOP_STRUCT_B_TO_I48(u, name) #define DEFINE_BINOP_INFIX_B_TO_LL(u, name, op) \ DEFINE_BINOP_INFIX_FUNC_B_TO_LL(u, name, op) \ DEFINE_BINOP_STRUCT_B_TO_LL(u, name) -static void testOp(bool isBinOp, const BinOp *op, int64_t x, int64_t y) +static void testOp(const Op *op, int64_t x, int64_t y) { - unsigned lhsLength = 8; + unsigned lhsLength = 9; unsigned nameLength = strlen(op->name); unsigned prefixLength = lhsLength - nameLength; - x_printf("%*s=%016llX\n", lhsLength, "x", (long long)x); - if (!isBinOp) + x_printffull("%*s=%016llX", lhsLength, "x", (long long)x); + if (!op->isBinary) { x_printf("\n"); } else { - x_printf("%*s=%016llX\n", lhsLength, "y", (long long)y); + x_printffull("%*s=%016llX", lhsLength, "y", (long long)y); } - -#define TEST_OP(prefix, bits) \ - x_printf("\n"); \ - if (op->prefix) \ - { \ - unsigned digits = (bits + 3) / 4; \ - unsigned long long result = (op->prefix)(x, y) & ((1ULL << (bits - 1) << 1) - 1); \ - x_printf("%*s%s=%*s%0*llX", prefixLength, #prefix, op->name, 16 - digits, "", digits, result); \ + x_printf("\n"); + +#define TEST_OP(prefix, bits) \ + if (op->prefix) \ + { \ + unsigned digits = (bits + 3) / 4; \ + unsigned long long result = \ + !op->isBinary \ + ? !op->isUnsigned \ + ? ((const UnOp *)(op))->prefix(x) \ + : ((const uUnOp *)(op))->prefix(x) \ + : !op->isUnsigned \ + ? ((const BinOp *)(op))->prefix(x, y) \ + : ((const uBinOp *)(op))->prefix(x, y); \ + result &= ((1ULL << (bits - 1) << 1) - 1); \ + x_printffull("%*s%s=%*s%0*llX", \ + prefixLength, \ + #prefix, \ + op->name, \ + 16 - digits, \ + "", \ + digits, \ + result); \ + } \ + else \ + { \ + x_printf("\n"); \ } TEST_OP(b, 8) TEST_OP(s, 16) TEST_OP(i, 24) TEST_OP(l, 32) + TEST_OP(i48, 48) TEST_OP(ll, 64) finishOutput(); } -static void testUnOp(const UnOp *op, int64_t x) -{ - testOp(false, (const BinOp*)op, x, 0); -} - -static void testBinOp(const BinOp *op, int64_t x, int64_t y) -{ - testOp(true, op, x, y); -} - DEFINE_UNOP_PREFIX_B_TO_LL( , not, ~) DEFINE_UNOP_PREFIX_B_TO_LL( , neg, -) -DEFINE_UNOP_PREFIX_FUNC_B_TO_I( , abs, abs) +DEFINE_UNOP_PREFIX_FUNC_B_TO_S( , abs, abs) +DEFINE_UNOP_PREFIX_FUNC_I( , abs, iabs) DEFINE_UNOP_PREFIX_FUNC_L( , abs, labs) +DEFINE_UNOP_PREFIX_FUNC_I48( , abs, i48abs) DEFINE_UNOP_PREFIX_FUNC_LL( , abs, llabs) -DEFINE_UNOP_STRUCT_B_TO_LL( , abs) +DEFINE_UNOP_STRUCT_B_TO_LL(, abs) DEFINE_UNOP_PREFIX_FUNC_B( , bitrev, __builtin_bitreverse8) DEFINE_UNOP_PREFIX_FUNC_S( , bitrev, __builtin_bitreverse16) DEFINE_UNOP_PREFIX_FUNC_I( , bitrev, __builtin_bitreverse24) DEFINE_UNOP_PREFIX_FUNC_L( , bitrev, __builtin_bitreverse32) +DEFINE_UNOP_PREFIX_FUNC_I48( , bitrev, __builtin_bitreverse48) DEFINE_UNOP_PREFIX_FUNC_LL( , bitrev, __builtin_bitreverse64) -DEFINE_UNOP_STRUCT_B_TO_LL( , bitrev) +DEFINE_UNOP_STRUCT_B_TO_LL(, bitrev) -// Needs to be unsigned to avoid extra bits from sign extension DEFINE_UNOP_PREFIX_FUNC_S(u, bswap, __builtin_bswap16) +DEFINE_UNOP_PREFIX_FUNC_I(u, bswap, __builtin_bswap24) DEFINE_UNOP_PREFIX_FUNC_L(u, bswap, __builtin_bswap32) +DEFINE_UNOP_PREFIX_FUNC_I48(u, bswap, __builtin_bswap48) DEFINE_UNOP_PREFIX_FUNC_LL(u, bswap, __builtin_bswap64) -DEFINE_UNOP_STRUCT_S_L_LL(u, bswap) +DEFINE_UNOP_STRUCT_BSWAP(u, bswap) -// Needs to be unsigned to avoid extra bits from sign extension DEFINE_UNOP_PREFIX_FUNC_B_TO_I(u, popcnt, __builtin_popcount) DEFINE_UNOP_PREFIX_FUNC_L(u, popcnt, __builtin_popcountl) +DEFINE_UNOP_PREFIX_FUNC_I48(u, popcnt, __builtin_popcounti48) DEFINE_UNOP_PREFIX_FUNC_LL(u, popcnt, __builtin_popcountll) DEFINE_UNOP_STRUCT_B_TO_LL(u, popcnt) @@ -344,39 +465,35 @@ DEFINE_BINOP_INFIX_B_TO_LL(u, remu, %) DEFINE_BINOP_INFIX_B_TO_LL( , divs, /) DEFINE_BINOP_INFIX_B_TO_LL( , rems, %) - -DEFINE_BINOP_FUNC_FUNC_I_TO_LL( , div_q, div, .quot) +DEFINE_BINOP_DIV_LIKE_FUNC_I_TO_LL( , div_q, div, .quot) DEFINE_BINOP_STRUCT_I_TO_LL( , div_q) -DEFINE_BINOP_FUNC_FUNC_I_TO_LL( , div_r, div, .rem) +DEFINE_BINOP_DIV_LIKE_FUNC_I_TO_LL( , div_r, div, .rem) DEFINE_BINOP_STRUCT_I_TO_LL( , div_r) -static const UnOp *unops[] = { - &unop_not, - &unop_neg, - &unop_abs, - &unop_bitrev, - (const UnOp *)&unop_bswap, - (const UnOp *)&unop_popcnt, -}; - -static const BinOp *binops[] = { - &binop_and, - &binop_or, - &binop_xor, - &binop_add, - &binop_sub, - &binop_shl, - (const BinOp *)&binop_shru, - &binop_shrs, - (const BinOp *)&binop_mulu, - (const BinOp *)&binop_divu, - (const BinOp *)&binop_remu, - &binop_divs, - &binop_rems, - &binop_div_q, - &binop_div_r, +static const Op *ops[] = { + (const Op *)&unop_not, + (const Op *)&unop_neg, + (const Op *)&unop_abs, + (const Op *)&unop_bitrev, + (const Op *)&uunop_bswap, + (const Op *)&uunop_popcnt, + (const Op *)&binop_and, + (const Op *)&binop_or, + (const Op *)&binop_xor, + (const Op *)&binop_add, + (const Op *)&binop_sub, + (const Op *)&binop_shl, + (const Op *)&ubinop_shru, + (const Op *)&binop_shrs, + (const Op *)&ubinop_mulu, + (const Op *)&ubinop_divu, + (const Op *)&ubinop_remu, + (const Op *)&binop_divs, + (const Op *)&binop_rems, + (const Op *)&binop_div_q, + (const Op *)&binop_div_r, }; @@ -387,14 +504,9 @@ int main(int argc, char *argv[]) separateOutput(); - for (size_t i = 0; i < sizeof(unops) / sizeof(*unops); i++) - { - testUnOp(unops[i], x); - } - - for (size_t i = 0; i < sizeof(binops) / sizeof(*binops); i++) + for (size_t i = 0; i < sizeof(ops) / sizeof(*ops); i++) { - testBinOp(binops[i], x, y); + testOp(ops[i], x, y); } return 0;