diff options
| author | Zack Buhman <zack@buhman.org> | 2024-04-05 17:11:47 -1000 |
|---|---|---|
| committer | Richard Henderson <richard.henderson@linaro.org> | 2024-04-09 07:43:31 -1000 |
| commit | 7227c0cd506eaab5b1d89d15832cac7e05ecb412 (patch) | |
| tree | 8b3e6d9d0ca14105c8ef063827e5cd18481449c1 /tests | |
| parent | c97e8977dcacb3fa8362ee28bcee75ceb01fceaa (diff) | |
| download | focaccia-qemu-7227c0cd506eaab5b1d89d15832cac7e05ecb412.tar.gz focaccia-qemu-7227c0cd506eaab5b1d89d15832cac7e05ecb412.zip | |
target/sh4: Fix mac.w with saturation enabled
The saturation arithmetic logic in helper_macw is not correct. I tested and verified this behavior on a SH7091. Reviewd-by: Yoshinori Sato <ysato@users.sourceforge.jp> Signed-off-by: Zack Buhman <zack@buhman.org> Message-Id: <20240405233802.29128-3-zack@buhman.org> [rth: Reformat helper_macw, add a test case.] Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/tcg/sh4/Makefile.target | 3 | ||||
| -rw-r--r-- | tests/tcg/sh4/test-macw.c | 61 |
2 files changed, 64 insertions, 0 deletions
diff --git a/tests/tcg/sh4/Makefile.target b/tests/tcg/sh4/Makefile.target index 9a11c10924..4d09291c0c 100644 --- a/tests/tcg/sh4/Makefile.target +++ b/tests/tcg/sh4/Makefile.target @@ -14,3 +14,6 @@ VPATH += $(SRC_PATH)/tests/tcg/sh4 test-macl: CFLAGS += -O -g TESTS += test-macl + +test-macw: CFLAGS += -O -g +TESTS += test-macw diff --git a/tests/tcg/sh4/test-macw.c b/tests/tcg/sh4/test-macw.c new file mode 100644 index 0000000000..4eceec8634 --- /dev/null +++ b/tests/tcg/sh4/test-macw.c @@ -0,0 +1,61 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include <stdint.h> +#include <stdlib.h> +#include <stdio.h> + +int64_t mac_w(int64_t mac, const int16_t *a, const int16_t *b) +{ + register uint32_t macl __asm__("macl") = mac; + register uint32_t mach __asm__("mach") = mac >> 32; + + asm volatile("mac.w @%0+,@%1+" + : "+r"(a), "+r"(b), "+x"(macl), "+x"(mach)); + + return ((uint64_t)mach << 32) | macl; +} + +typedef struct { + int64_t mac; + int16_t a, b; + int64_t res[2]; +} Test; + +__attribute__((noinline)) +void test(const Test *t, int sat) +{ + int64_t res; + + if (sat) { + asm volatile("sets"); + } else { + asm volatile("clrs"); + } + res = mac_w(t->mac, &t->a, &t->b); + + if (res != t->res[sat]) { + fprintf(stderr, "%#llx + (%#x * %#x) = %#llx -- got %#llx\n", + t->mac, t->a, t->b, t->res[sat], res); + abort(); + } +} + +int main() +{ + static const Test tests[] = { + { 0, 2, 3, { 6, 6 } }, + { 0x123456787ffffffell, 2, -3, + { 0x123456787ffffff8ll, 0x123456787ffffff8ll } }, + { 0xabcdef127ffffffall, 2, 3, + { 0xabcdef1280000000ll, 0x000000017fffffffll } }, + { 0xfffffffffll, INT16_MAX, INT16_MAX, + { 0x103fff0000ll, 0xf3fff0000ll } }, + }; + + for (int i = 0; i < sizeof(tests) / sizeof(tests[0]); ++i) { + for (int j = 0; j < 2; ++j) { + test(&tests[i], j); + } + } + return 0; +} |