[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Stable-8.2.3 093/116] target/sh4: Fix mac.w with saturation enabled
From: |
Michael Tokarev |
Subject: |
[Stable-8.2.3 093/116] target/sh4: Fix mac.w with saturation enabled |
Date: |
Thu, 18 Apr 2024 20:49:23 +0300 |
From: Zack Buhman <zack@buhman.org>
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>
(cherry picked from commit 7227c0cd506eaab5b1d89d15832cac7e05ecb412)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
diff --git a/target/sh4/helper.h b/target/sh4/helper.h
index 64056e4a39..29011d3dbb 100644
--- a/target/sh4/helper.h
+++ b/target/sh4/helper.h
@@ -12,7 +12,7 @@ DEF_HELPER_1(discard_movcal_backup, void, env)
DEF_HELPER_2(ocbi, void, env, i32)
DEF_HELPER_3(macl, void, env, s32, s32)
-DEF_HELPER_3(macw, void, env, i32, i32)
+DEF_HELPER_3(macw, void, env, s32, s32)
DEF_HELPER_2(ld_fpscr, void, env, i32)
diff --git a/target/sh4/op_helper.c b/target/sh4/op_helper.c
index c96c6008a1..8b7f378f23 100644
--- a/target/sh4/op_helper.c
+++ b/target/sh4/op_helper.c
@@ -179,22 +179,28 @@ void helper_macl(CPUSH4State *env, int32_t arg0, int32_t
arg1)
env->mac = res;
}
-void helper_macw(CPUSH4State *env, uint32_t arg0, uint32_t arg1)
+void helper_macw(CPUSH4State *env, int32_t arg0, int32_t arg1)
{
- int64_t res;
+ /* Inputs are already sign-extended from 16 bits. */
+ int32_t mul = arg0 * arg1;
- res = ((uint64_t) env->mach << 32) | env->macl;
- res += (int64_t) (int16_t) arg0 *(int64_t) (int16_t) arg1;
- env->mach = (res >> 32) & 0xffffffff;
- env->macl = res & 0xffffffff;
if (env->sr & (1u << SR_S)) {
- if (res < -0x80000000) {
- env->mach = 1;
- env->macl = 0x80000000;
- } else if (res > 0x000000007fffffff) {
+ /*
+ * In saturation arithmetic mode, the accumulator is 32-bit
+ * with carry. MACH is not considered during the addition
+ * operation nor the 32-bit saturation logic.
+ */
+ int32_t res, macl = env->macl;
+
+ if (sadd32_overflow(macl, mul, &res)) {
+ res = macl < 0 ? INT32_MIN : INT32_MAX;
+ /* If overflow occurs, the MACH register is set to 1. */
env->mach = 1;
- env->macl = 0x7fffffff;
}
+ env->macl = res;
+ } else {
+ /* In non-saturation arithmetic mode, the accumulator is 64-bit */
+ env->mac += mul;
}
}
diff --git a/tests/tcg/sh4/Makefile.target b/tests/tcg/sh4/Makefile.target
index 3c0695c7ca..c3d7fa86e3 100644
--- a/tests/tcg/sh4/Makefile.target
+++ b/tests/tcg/sh4/Makefile.target
@@ -17,3 +17,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;
+}
--
2.39.2
- [Stable-8.2.3 v2 000/116] Patch Round-up for stable 8.2.3, freeze on 2024-04-20, Michael Tokarev, 2024/04/18
- [Stable-8.2.3 088/116] tcg/optimize: Do not attempt to constant fold neg_vec, Michael Tokarev, 2024/04/18
- [Stable-8.2.3 089/116] linux-user: Fix waitid return of siginfo_t and rusage, Michael Tokarev, 2024/04/18
- [Stable-8.2.3 090/116] target/sh4: mac.w: memory accesses are 16-bit words, Michael Tokarev, 2024/04/18
- [Stable-8.2.3 091/116] target/sh4: Merge mach and macl into a union, Michael Tokarev, 2024/04/18
- [Stable-8.2.3 092/116] target/sh4: Fix mac.l with saturation enabled, Michael Tokarev, 2024/04/18
- [Stable-8.2.3 093/116] target/sh4: Fix mac.w with saturation enabled,
Michael Tokarev <=
- [Stable-8.2.3 094/116] target/sh4: add missing CHECK_NOT_DELAY_SLOT, Michael Tokarev, 2024/04/18
- [Stable-8.2.3 095/116] target/m68k: Map FPU exceptions to FPSR register, Michael Tokarev, 2024/04/18
- [Stable-8.2.3 096/116] hw/virtio: Introduce virtio_bh_new_guarded() helper, Michael Tokarev, 2024/04/18
- [Stable-8.2.3 097/116] hw/display/virtio-gpu: Protect from DMA re-entrancy bugs, Michael Tokarev, 2024/04/18
- [Stable-8.2.3 098/116] hw/char/virtio-serial-bus: Protect from DMA re-entrancy bugs, Michael Tokarev, 2024/04/18
- [Stable-8.2.3 099/116] hw/virtio/virtio-crypto: Protect from DMA re-entrancy bugs, Michael Tokarev, 2024/04/18
- [Stable-8.2.3 100/116] qemu-options: Fix CXL Fixed Memory Window interleave-granularity typo, Michael Tokarev, 2024/04/18
- [Stable-8.2.3 101/116] hw/block/nand: Factor nand_load_iolen() method out, Michael Tokarev, 2024/04/18
- [Stable-8.2.3 102/116] hw/block/nand: Have blk_load() take unsigned offset and return boolean, Michael Tokarev, 2024/04/18
- [Stable-8.2.3 104/116] hw/misc/applesmc: Fix memory leak in reset() handler, Michael Tokarev, 2024/04/18