[PATCH v2 1/2] target/sh4: add tests for sh4 fipr and ftrv instructions

Randy Schifflin <[email protected]>
Newsgroups gmane.comp.emulators.qemu
Message-ID <20260729-fixup-sh4-tcg-fpu-instructions-b4-v2-1-2c1c0fe04672@gmail.com>
Add tests for the TCG generation of the sh4-specific `fipr`
and `ftrv` instructions.

Signed-off-by: Randy Schifflin <[email protected]>
---
 tests/tcg/sh4/Makefile.target |   7 +++
 tests/tcg/sh4/test-fpu-fipr.c |  72 ++++++++++++++++++++++++++++
 tests/tcg/sh4/test-fpu-ftrv.c | 108 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 187 insertions(+)

diff --git a/tests/tcg/sh4/Makefile.target b/tests/tcg/sh4/Makefile.target
index b7a8737be0..0975fac72d 100644
--- a/tests/tcg/sh4/Makefile.target
+++ b/tests/tcg/sh4/Makefile.target
@@ -16,3 +16,10 @@ TESTS += test-addv
 
 test-subv: CFLAGS += -O -g
 TESTS += test-subv
+
+test-fpu-fipr: CFLAGS += -O -g
+TESTS += test-fpu-fipr
+
+test-fpu-ftrv: CFLAGS += -O -g
+TESTS += test-fpu-ftrv
+
diff --git a/tests/tcg/sh4/test-fpu-fipr.c b/tests/tcg/sh4/test-fpu-fipr.c
new file mode 100644
index 0000000000..1bf1a1b4ec
--- /dev/null
+++ b/tests/tcg/sh4/test-fpu-fipr.c
@@ -0,0 +1,72 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#include <limits.h>
+#include <stdlib.h>
+static const unsigned long FPSCR_PR_BIT = 1UL << 19;
+
+static void single_precision_mode(void)
+{
+    unsigned long fpscr;
+    /* Read FPSCR register */
+    asm volatile("sts fpscr, %0" : "=r" (fpscr));
+    /* Set precision mode to single-precision */
+    fpscr &= ~FPSCR_PR_BIT;
+    /* Write FPSCR register */
+    asm volatile("lds %0, fpscr" : : "r" (fpscr));
+}
+
+static float fipr(const float v1[4], const float v2[4])
+{
+    float fout = 0.0;
+    /*
+     * Perform inner product of fv4 and fv8
+     * Result is stored in the last float register of the last vector argument
+     */
+    asm volatile(
+        "fmov %1,fr4\n"
+        "fmov %2,fr5\n"
+        "fmov %3,fr6\n"
+        "fmov %4,fr7\n"
+        "fmov %5,fr8\n"
+        "fmov %6,fr9\n"
+        "fmov %7,fr10\n"
+        "fmov %8,fr11\n"
+        "fipr fv4,fv8\n" /* (fr4,fr5,fr6,fr7) dot (fr8,fr9,fr10,fr11) */
+        "fmov fr11,%0\n" /* Result in fr11 */
+        : "=f" (fout)
+        : "f" (v1[0]), "f" (v1[1]), "f" (v1[2]), "f" (v1[3]),
+          "f" (v2[0]), "f" (v2[1]), "f" (v2[2]), "f" (v2[3]));
+    return fout;
+}
+
+int main(void)
+{
+    /*
+     * The SH4 manual specifies `fipr` is only available when
+     * FPSCR register precision-mode (PR) bit is 0
+     */
+    single_precision_mode();
+
+    float v1[4] = {1.0, 0.0, 0.0, 0.0};
+    float mag_sq = 0.0;
+    float dot = 0.0;
+
+    mag_sq = fipr(v1, v1);
+    if (mag_sq != 1.0) {
+        abort();
+    }
+
+    v1[0] = 2.0;
+    mag_sq = fipr(v1, v1);
+    if (mag_sq != 4.0) {
+        abort();
+    }
+
+    float v2[4] = {1.0, 0.0, 0.0, 0.0};
+    dot = fipr(v1, v2);
+    if (dot != 2.0) {
+        abort();
+    }
+
+    return 0;
+}
diff --git a/tests/tcg/sh4/test-fpu-ftrv.c b/tests/tcg/sh4/test-fpu-ftrv.c
new file mode 100644
index 0000000000..041e03120e
--- /dev/null
+++ b/tests/tcg/sh4/test-fpu-ftrv.c
@@ -0,0 +1,108 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#include <limits.h>
+#include <stdlib.h>
+static const unsigned long FPSCR_PR_BIT = 1UL << 19;
+
+static void single_precision_mode(void)
+{
+    unsigned long fpscr;
+    /* Read FPSCR register */
+    asm volatile("sts fpscr, %0" : "=r" (fpscr));
+    /* Set precision mode to single-precision */
+    fpscr &= ~FPSCR_PR_BIT;
+    /* Write FPSCR register */
+    asm volatile("lds %0, fpscr" : : "r" (fpscr));
+}
+
+/* Set XMTRX registers to a doubling scale matrix */
+static void xmtrx_scale_2(void)
+{
+    asm volatile(
+        "fldi0 fr0\n" /* Pair dr0 (fr0, fr1) = zero,zero */
+        "fldi0 fr1\n"
+        "fldi1 fr2\n"
+        "fadd fr2,fr2\n" /* Pair dr2 (fr2,fr3) = two,zero */
+        "fldi0 fr3\n"
+        "fldi0 fr4\n"
+        "fmov fr2,fr5\n" /* Pair dr4 (fr4, fr5) = zero,two */
+
+        /* Enable pair-write */
+        "fschg\n"
+        /* matrix[0][0] = 2.0 */
+        /* matrix[0][1] = 0.0 */
+        "fmov dr2,xd0\n"
+        /* matrix[0][2] = 0.0 */
+        /* matrix[0][3] = 0.0 */
+        "fmov dr0,xd2\n"
+        /* matrix[1][0] = 0.0 */
+        /* matrix[1][1] = 2.0 */
+        "fmov dr4,xd4\n"
+        /* matrix[1][2] = 0.0 */
+        /* matrix[1][3] = 0.0 */
+        "fmov dr0,xd6\n"
+        /* matrix[2][0] = 0.0 */
+        /* matrix[2][1] = 0.0 */
+        "fmov dr0,xd8\n"
+        /* matrix[2][2] = 2.0 */
+        /* matrix[2][3] = 0.0 */
+        "fmov dr2,xd10\n"
+        /* matrix[3][0] = 0.0 */
+        /* matrix[3][1] = 0.0 */
+        "fmov dr0,xd12\n"
+        /* matrix[3][2] = 0.0 */
+        /* matrix[3][3] = 2.0 */
+        "fmov dr4,xd14\n"
+        /* Disable pair-write */
+        "fschg"
+        :
+        :
+        : "fr0", "fr1", "fr2", "fr3", "fr4", "fr5");
+}
+
+/* Transform vector vin by xmtrx; store result in vector vout */
+static void ftrv(const float vin[4], float vout[4])
+{
+    asm volatile("fmov %4,fr0\n"
+                 "fmov %5,fr1\n"
+                 "fmov %6,fr2\n"
+                 "fmov %7,fr3\n"
+                 "ftrv xmtrx,fv0\n"
+                 "fmov fr0,%0\n"
+                 "fmov fr1,%1\n"
+                 "fmov fr2,%2\n"
+                 "fmov fr3,%3"
+                 : "=f" (vout[0]), "=f" (vout[1]),
+                   "=f" (vout[2]), "=f" (vout[3])
+                 : "f" (vin[0]), "f" (vin[1]),
+                   "f" (vin[2]), "f" (vin[3])
+                 : "fr0", "fr1", "fr2", "fr3");
+}
+
+int main(void)
+{
+    /*
+     * The SH4 manual specifies `ftrv` is only available when
+     * FPSCR register precision-mode (PR) bit is 0
+     */
+    single_precision_mode();
+    xmtrx_scale_2();
+    float vin[4] = {1.0, 2.0, 3.0, 4.0};
+    float vout[4] = { 0.0, 0.0, 0.0, 0.0};
+
+    ftrv(vin, vout);
+    if (vout[0] != 2.0) {
+        abort();
+    }
+    if (vout[1] != 4.0) {
+        abort();
+    }
+    if (vout[2] != 6.0) {
+        abort();
+    }
+    if (vout[3] != 8.0) {
+        abort();
+    }
+
+    return 0;
+}

-- 
2.43.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.