aboutsummaryrefslogtreecommitdiff
path: root/tests/tcg/m68k
diff options
context:
space:
mode:
authorRichard Henderson <richard.henderson@linaro.org>2023-08-20 17:28:33 -0700
committerRichard Henderson <richard.henderson@linaro.org>2023-09-16 14:57:16 +0000
commit722460652b3aee89dc19df61f1f33df53a9b97c9 (patch)
tree84cca92504817a5b1ccb466fa918e8cebb262090 /tests/tcg/m68k
parent00f9ef8f3dd6940001311a6230985243c3ebb996 (diff)
downloadqemu-722460652b3aee89dc19df61f1f33df53a9b97c9.zip
qemu-722460652b3aee89dc19df61f1f33df53a9b97c9.tar.gz
qemu-722460652b3aee89dc19df61f1f33df53a9b97c9.tar.bz2
fpu: Handle m68k extended precision denormals properly
Motorola treats denormals with explicit integer bit set as having unbiased exponent 0, unlike Intel which treats it as having unbiased exponent 1 (more like all other IEEE formats that have no explicit integer bit). Add a flag on FloatFmt to differentiate the behaviour. Reported-by: Keith Packard <keithp@keithp.com> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Diffstat (limited to 'tests/tcg/m68k')
-rw-r--r--tests/tcg/m68k/Makefile.target2
-rw-r--r--tests/tcg/m68k/denormal.c53
2 files changed, 54 insertions, 1 deletions
diff --git a/tests/tcg/m68k/Makefile.target b/tests/tcg/m68k/Makefile.target
index 1163c7e..6ff214e 100644
--- a/tests/tcg/m68k/Makefile.target
+++ b/tests/tcg/m68k/Makefile.target
@@ -4,7 +4,7 @@
#
VPATH += $(SRC_PATH)/tests/tcg/m68k
-TESTS += trap
+TESTS += trap denormal
# On m68k Linux supports 4k and 8k pages (but 8k is currently broken)
EXTRA_RUNS+=run-test-mmap-4096 # run-test-mmap-8192
diff --git a/tests/tcg/m68k/denormal.c b/tests/tcg/m68k/denormal.c
new file mode 100644
index 0000000..20bd8c7
--- /dev/null
+++ b/tests/tcg/m68k/denormal.c
@@ -0,0 +1,53 @@
+/*
+ * Test m68k extended double denormals.
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+
+#define TEST(X, Y) { X, Y, X * Y }
+
+static volatile long double test[][3] = {
+ TEST(0x1p+16383l, 0x1p-16446l),
+ TEST(0x1.1p-8223l, 0x1.1p-8224l),
+ TEST(1.0l, 0x1p-16383l),
+};
+
+#undef TEST
+
+static void dump_ld(const char *label, long double ld)
+{
+ union {
+ long double d;
+ struct {
+ uint32_t exp:16;
+ uint32_t space:16;
+ uint32_t h;
+ uint32_t l;
+ };
+ } u;
+
+ u.d = ld;
+ printf("%12s: % -27La 0x%04x 0x%08x 0x%08x\n", label, u.d, u.exp, u.h, u.l);
+}
+
+int main(void)
+{
+ int i, n = sizeof(test) / sizeof(test[0]), err = 0;
+
+ for (i = 0; i < n; ++i) {
+ long double x = test[i][0];
+ long double y = test[i][1];
+ long double build_mul = test[i][2];
+ long double runtime_mul = x * y;
+
+ if (runtime_mul != build_mul) {
+ dump_ld("x", x);
+ dump_ld("y", y);
+ dump_ld("build_mul", build_mul);
+ dump_ld("runtime_mul", runtime_mul);
+ err = 1;
+ }
+ }
+ return err;
+}