summaryrefslogtreecommitdiffstats
path: root/gitlab/issues/target_m68k/host_missing/accel_TCG/2290.toml
diff options
context:
space:
mode:
authorChristian Krinitsin <mail@krinitsin.com>2025-05-21 21:21:26 +0200
committerChristian Krinitsin <mail@krinitsin.com>2025-05-21 21:21:26 +0200
commit4b927bc37359dec23f67d3427fc982945f24f404 (patch)
tree245449ef9146942dc7fffd0235b48b7e70a00bf2 /gitlab/issues/target_m68k/host_missing/accel_TCG/2290.toml
parentaa8bd79cec7bf6790ddb01d156c2ef2201abbaab (diff)
downloademulator-bug-study-4b927bc37359dec23f67d3427fc982945f24f404.tar.gz
emulator-bug-study-4b927bc37359dec23f67d3427fc982945f24f404.zip
add gitlab issues in toml format
Diffstat (limited to 'gitlab/issues/target_m68k/host_missing/accel_TCG/2290.toml')
-rw-r--r--gitlab/issues/target_m68k/host_missing/accel_TCG/2290.toml151
1 files changed, 151 insertions, 0 deletions
diff --git a/gitlab/issues/target_m68k/host_missing/accel_TCG/2290.toml b/gitlab/issues/target_m68k/host_missing/accel_TCG/2290.toml
new file mode 100644
index 00000000..3e0c124c
--- /dev/null
+++ b/gitlab/issues/target_m68k/host_missing/accel_TCG/2290.toml
@@ -0,0 +1,151 @@
+id = 2290
+title = "Wrong multiplication result of 'long double' on m68k"
+state = "closed"
+created_at = "2024-04-18T11:31:12.121Z"
+closed_at = "2024-04-18T22:26:41.012Z"
+labels = ["Softfloat", "Stable::to backport", "accel: TCG", "kind::Bug", "target: m68k"]
+url = "https://gitlab.com/qemu-project/qemu/-/issues/2290"
+host-os = "Ubuntu 22.04"
+host-arch = "x86_64"
+qemu-version = "8.1.2"
+guest-os = "Debian 12"
+guest-arch = "m68k"
+description = """In both x86 and m68k, 'long double' is an 80-bit format consisting of
+ - 1 bit sign, 15 bits exponent,
+ - 1 explicit 1 bit, 63 fraction bits.
+
+According to <https://en.wikipedia.org/wiki/Extended_precision> and
+<https://www.nxp.com/docs/en/reference-manual/M68000PRM.pdf> table 1-6 (page 1-23), with two differences:
+ - In m68k, there are 16 zero bits as filler after the sign/exponent
+ word, so that the total size is 96 bits.
+ - In x86, the minimum exponent of normalized numbers is 1;
+ in m68k, the minimum exponent of normalized numbers is 0.
+
+The latter difference is reflected in the values of LDBL_MIN_EXP and
+LDBL_MIN in gcc:
+
+In x86:
+```
+$ echo '#include <float.h>' | gcc -E -dM - | grep __LDBL_MIN_EXP_
+#define LDBL_MIN_EXP __LDBL_MIN_EXP__
+#define __LDBL_MIN_EXP__ (-16381)
+$ echo '#include <float.h>' | gcc -E -dM - | grep __LDBL_MIN__
+#define __LDBL_MIN__ 3.36210314311209350626267781732175260e-4932L
+#define LDBL_MIN __LDBL_MIN__
+```
+In m68k (I use Debian 12/Linux):
+```
+$ echo '#include <float.h>' | gcc -E -dM - | grep __LDBL_MIN_EXP_
+#define LDBL_MIN_EXP __LDBL_MIN_EXP__
+#define __LDBL_MIN_EXP__ (-16382)
+$ echo '#include <float.h>' | gcc -E -dM - | grep __LDBL_MIN__
+#define __LDBL_MIN__ 1.68105157155604675313e-4932L
+#define LDBL_MIN __LDBL_MIN__
+```"""
+reproduce = """Take this program, foo.c:
+```
+/* Show extended-precision https://en.wikipedia.org/wiki/Extended_precision
+ multiplication bug in QEMU. */
+
+#include <stdio.h>
+
+static void
+show (const long double *p)
+{
+#ifdef __m68k__
+ printf("<S,E: 0x%08X M: 0x%08X%08X>",
+ ((const unsigned int *) p)[0],
+ ((const unsigned int *) p)[1],
+ ((const unsigned int *) p)[2]);
+#else /* x86 */
+ printf("<S,E: 0x%04X M: 0x%08X%08X>",
+ ((const unsigned short *) p)[4],
+ ((const unsigned int *) p)[1],
+ ((const unsigned int *) p)[0]);
+#endif
+ printf (" = %La = %Lg", *p, *p);
+}
+
+static void
+show_mult (long double a, long double b)
+{
+ printf ("Factors: ");
+ show (&a);
+ printf ("\\n and: ");
+ show (&b);
+ long double c = a * b;
+ printf ("\\nProduct: ");
+ show (&c);
+ printf ("\\n\\n");
+}
+
+/* Return 2^n. */
+static long double
+pow2l (int n)
+{
+ int k = n;
+ volatile long double x = 1;
+ volatile long double y = 2;
+ /* Invariant: 2^n == x * y^k. */
+ if (k < 0)
+ {
+ y = 0.5L;
+ k = - k;
+ }
+ while (k > 0)
+ {
+ if (k != 2 * (k / 2))
+ {
+ x = x * y;
+ k = k - 1;
+ }
+ if (k == 0)
+ break;
+ y = y * y;
+ k = k / 2;
+ }
+ /* Now k == 0, hence x == 2^n. */
+ return x;
+}
+
+int main ()
+{
+ show_mult (pow2l (-16382), 0.5L);
+ show_mult (pow2l (-16381), 0.25L);
+ return 0;
+}
+```
+Its output on x86:
+```
+$ ./a.out
+Factors: <S,E: 0x0001 M: 0x8000000000000000> = 0x8p-16385 = 3.3621e-4932
+ and: <S,E: 0x3FFE M: 0x8000000000000000> = 0x8p-4 = 0.5
+Product: <S,E: 0x0000 M: 0x4000000000000000> = 0x4p-16385 = 1.68105e-4932
+
+Factors: <S,E: 0x0002 M: 0x8000000000000000> = 0x8p-16384 = 6.72421e-4932
+ and: <S,E: 0x3FFD M: 0x8000000000000000> = 0x8p-5 = 0.25
+Product: <S,E: 0x0000 M: 0x4000000000000000> = 0x4p-16385 = 1.68105e-4932
+```
+Its output on m68k:
+```
+$ ./a.out
+Factors: <S,E: 0x00010000 M: 0x8000000000000000> = 0x8p-16385 = 3.3621e-4932
+ and: <S,E: 0x3FFE0000 M: 0x8000000000000000> = 0x8p-4 = 0.5
+Product: <S,E: 0x00000000 M: 0x4000000000000000> = 0x4p-16386 = 8.40526e-4933
+
+Factors: <S,E: 0x00020000 M: 0x8000000000000000> = 0x8p-16384 = 6.72421e-4932
+ and: <S,E: 0x3FFD0000 M: 0x8000000000000000> = 0x8p-5 = 0.25
+Product: <S,E: 0x00000000 M: 0x4000000000000000> = 0x4p-16386 = 8.40526e-4933
+```
+The product, computed by QEMU, is incorrect. It is only half as large as the
+correct value. The expected output should be:
+```
+Factors: <S,E: 0x00010000 M: 0x8000000000000000> = 0x8p-16385 = 3.3621e-4932
+ and: <S,E: 0x3FFE0000 M: 0x8000000000000000> = 0x8p-4 = 0.5
+Product: <S,E: 0x00000000 M: 0x8000000000000000> = 0x8p-16386 = 1.68105e-4932
+
+Factors: <S,E: 0x00020000 M: 0x8000000000000000> = 0x8p-16384 = 6.72421e-4932
+ and: <S,E: 0x3FFD0000 M: 0x8000000000000000> = 0x8p-5 = 0.25
+Product: <S,E: 0x00000000 M: 0x8000000000000000> = 0x8p-16386 = 1.68105e-4932
+```"""
+additional = """In QEMU's source code, I would guess that this multiplication is performed by the `floatx80_mul` function."""