Re: [PATCH 1/2] target/sh4: add tests for sh4 fipr and ftrv instructions
[email protected] Tue, 30 Jun 2026 21:42:55 +0900
| Newsgroups | org.nongnu.qemu-trivial,org.nongnu.qemu-devel |
|---|---|
| Message-ID | <[email protected]> |
On Tue, 30 Jun 2026 06:49:12 +0900, Randy Schifflin wrote: > > 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 | 64 ++++++++++++++++++++++++++++ > tests/tcg/sh4/test-fpu-ftrv.c | 99 +++++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 170 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..bf8258fc36 > --- /dev/null > +++ b/tests/tcg/sh4/test-fpu-fipr.c > @@ -0,0 +1,64 @@ > +/* 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..1018da1b7c > --- /dev/null > +++ b/tests/tcg/sh4/test-fpu-ftrv.c > @@ -0,0 +1,99 @@ > +/* 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"); > +} > + > +// The SH4 manual specifies `ftrv` is only available when FPSCR register precision-mode (PR) bit is 0, aka single-precision > +// 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) > +{ > + 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 > Reviewed-by: Yoshinori Sato <[email protected]> -- Yosinori Sato