aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/testsuite/ChangeLog12
-rw-r--r--gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d128-1.c30
-rw-r--r--gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d128-2.c42
-rw-r--r--gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d128-3.c5
-rw-r--r--gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d128-4.c6
-rw-r--r--gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d32-1.c26
-rw-r--r--gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d32-2.c5
-rw-r--r--gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d64-1.c26
-rw-r--r--gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d64-2.c5
-rw-r--r--libdecnumber/ChangeLog8
-rw-r--r--libdecnumber/bid/bid2dpd_dpd2bid.c22
11 files changed, 184 insertions, 3 deletions
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 8361b78..6cda5be 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,15 @@
+2019-12-09 Joseph Myers <joseph@codesourcery.com>
+
+ PR middle-end/91226
+ * gcc.dg/dfp/bid-non-canonical-d128-1.c,
+ gcc.dg/dfp/bid-non-canonical-d128-2.c,
+ gcc.dg/dfp/bid-non-canonical-d128-3.c,
+ gcc.dg/dfp/bid-non-canonical-d128-4.c,
+ gcc.dg/dfp/bid-non-canonical-d32-1.c,
+ gcc.dg/dfp/bid-non-canonical-d32-2.c,
+ gcc.dg/dfp/bid-non-canonical-d64-1.c,
+ gcc.dg/dfp/bid-non-canonical-d64-2.c: New tests.
+
2019-12-09 Matthew Malcomson <matthew.malcomson@arm.com>
PR middle-end/92410
diff --git a/gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d128-1.c b/gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d128-1.c
new file mode 100644
index 0000000..eee5471
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d128-1.c
@@ -0,0 +1,30 @@
+/* Test non-canonical BID significands: _Decimal128. Bug 91226. */
+/* { dg-do run { target { { i?86-*-* x86_64-*-* } && lp64 } } } */
+/* { dg-options "-std=gnu2x -O2" } */
+
+extern void abort (void);
+extern void exit (int);
+
+union u
+{
+ _Decimal128 d128;
+ unsigned __int128 u128;
+};
+
+#define U128(hi, lo) (((unsigned __int128) lo) \
+ | (((unsigned __int128) hi) << 64))
+
+int
+main (void)
+{
+ unsigned __int128 i = U128 (0x3041ed09bead87c0ULL, 0x378d8e6400000001ULL);
+ union u x;
+ _Decimal128 d128;
+ x.u128 = i;
+ d128 = x.d128;
+ volatile double d = d128;
+ if (d == 0)
+ exit (0);
+ else
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d128-2.c b/gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d128-2.c
new file mode 100644
index 0000000..6267121
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d128-2.c
@@ -0,0 +1,42 @@
+/* Test non-canonical BID significands: _Decimal128, case where
+ combination field starts 11. Bug 91226. */
+/* { dg-do run { target { { i?86-*-* x86_64-*-* } && lp64 } } } */
+/* { dg-options "-std=gnu2x -O2" } */
+
+extern void abort (void);
+extern void exit (int);
+
+union u
+{
+ _Decimal128 d128;
+ unsigned __int128 u128;
+};
+
+#define U128(hi, lo) (((unsigned __int128) lo) \
+ | (((unsigned __int128) hi) << 64))
+
+int
+main (void)
+{
+ unsigned __int128 i = U128 (0x6e79000000000000ULL, 0x1ULL);
+ union u x;
+ _Decimal128 d128;
+ x.u128 = i;
+ d128 = x.d128;
+ volatile double d = d128;
+ if (d != 0)
+ abort ();
+ /* The above number should have quantum exponent 1234. */
+ _Decimal128 t1233 = 0.e1233DL, t1234 = 0.e1234DL, t1235 = 0.e1235DL;
+ _Decimal128 dx;
+ dx = d128 + t1233;
+ if (__builtin_memcmp (&dx, &t1233, 16) != 0)
+ abort ();
+ dx = d128 + t1234;
+ if (__builtin_memcmp (&dx, &t1234, 16) != 0)
+ abort ();
+ dx = d128 + t1235;
+ if (__builtin_memcmp (&dx, &t1234, 16) != 0)
+ abort ();
+ exit (0);
+}
diff --git a/gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d128-3.c b/gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d128-3.c
new file mode 100644
index 0000000..9190dae
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d128-3.c
@@ -0,0 +1,5 @@
+/* Test non-canonical BID significands: _Decimal128. Bug 91226. */
+/* { dg-do run { target { { i?86-*-* x86_64-*-* } && lp64 } } } */
+/* { dg-options "-std=gnu2x -O0" } */
+
+#include "bid-non-canonical-d128-1.c"
diff --git a/gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d128-4.c b/gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d128-4.c
new file mode 100644
index 0000000..b148ce4
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d128-4.c
@@ -0,0 +1,6 @@
+/* Test non-canonical BID significands: _Decimal128, case where
+ combination field starts 11. Bug 91226. */
+/* { dg-do run { target { { i?86-*-* x86_64-*-* } && lp64 } } } */
+/* { dg-options "-std=gnu2x -O0" } */
+
+#include "bid-non-canonical-d128-2.c"
diff --git a/gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d32-1.c b/gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d32-1.c
new file mode 100644
index 0000000..b46b71c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d32-1.c
@@ -0,0 +1,26 @@
+/* Test non-canonical BID significands: _Decimal32. Bug 91226. */
+/* { dg-do run { target i?86-*-* x86_64-*-* } } */
+/* { dg-options "-std=gnu2x -O2" } */
+
+extern void abort (void);
+extern void exit (int);
+
+union u
+{
+ _Decimal32 d32;
+ unsigned int u32;
+};
+
+int
+main (void)
+{
+ union u x;
+ _Decimal32 d32;
+ x.u32 = 0x6cb89681U;
+ d32 = x.d32;
+ volatile double d = d32;
+ if (d == 0)
+ exit (0);
+ else
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d32-2.c b/gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d32-2.c
new file mode 100644
index 0000000..11d64dc
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d32-2.c
@@ -0,0 +1,5 @@
+/* Test non-canonical BID significands: _Decimal32. Bug 91226. */
+/* { dg-do run { target i?86-*-* x86_64-*-* } } */
+/* { dg-options "-std=gnu2x -O0" } */
+
+#include "bid-non-canonical-d32-1.c"
diff --git a/gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d64-1.c b/gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d64-1.c
new file mode 100644
index 0000000..87b1069
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d64-1.c
@@ -0,0 +1,26 @@
+/* Test non-canonical BID significands: _Decimal64. Bug 91226. */
+/* { dg-do run { target i?86-*-* x86_64-*-* } } */
+/* { dg-options "-std=gnu2x -O2" } */
+
+extern void abort (void);
+extern void exit (int);
+
+union u
+{
+ _Decimal64 d64;
+ unsigned long long int u64;
+};
+
+int
+main (void)
+{
+ union u x;
+ _Decimal64 d64;
+ x.u64 = 0x6c7386f26fc10001ULL;
+ d64 = x.d64;
+ volatile double d = d64;
+ if (d == 0)
+ exit (0);
+ else
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d64-2.c b/gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d64-2.c
new file mode 100644
index 0000000..3c10145
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/dfp/bid-non-canonical-d64-2.c
@@ -0,0 +1,5 @@
+/* Test non-canonical BID significands: _Decimal64. Bug 91226. */
+/* { dg-do run { target i?86-*-* x86_64-*-* } } */
+/* { dg-options "-std=gnu2x -O0" } */
+
+#include "bid-non-canonical-d64-1.c"
diff --git a/libdecnumber/ChangeLog b/libdecnumber/ChangeLog
index 62a2e57..6c61788 100644
--- a/libdecnumber/ChangeLog
+++ b/libdecnumber/ChangeLog
@@ -1,3 +1,11 @@
+2019-12-09 Joseph Myers <joseph@codesourcery.com>
+
+ PR middle-end/91226
+ * bid/bid2dpd_dpd2bid.c (_bid_to_dpd64): Handle non-canonical
+ significands.
+ (_bid_to_dpd128): Likewise. Check for case where combination
+ field starts 1100, 1101 or 1110.
+
2019-01-01 Jakub Jelinek <jakub@redhat.com>
Update copyright years.
diff --git a/libdecnumber/bid/bid2dpd_dpd2bid.c b/libdecnumber/bid/bid2dpd_dpd2bid.c
index 63d3cec..36aa56c 100644
--- a/libdecnumber/bid/bid2dpd_dpd2bid.c
+++ b/libdecnumber/bid/bid2dpd_dpd2bid.c
@@ -189,6 +189,8 @@ _bid_to_dpd64 (_Decimal64 *pres, _Decimal64 *px) {
if ((comb & 0xc00) == 0xc00) { /* G0..G1 = 11 -> exp is G2..G11 */
exp = (comb) & 0x3ff;
bcoeff = (x & 0x0007ffffffffffffull) | 0x0020000000000000ull;
+ if (bcoeff >= 10000000000000000ull)
+ bcoeff = 0;
} else {
exp = (comb >> 2) & 0x3ff;
bcoeff = (x & 0x001fffffffffffffull);
@@ -298,9 +300,23 @@ _bid_to_dpd128 (_Decimal128 *pres, _Decimal128 *px) {
if ((comb & 0x1e000) == 0x1e000) {
res = x;
} else { /* normal number */
- exp = ((x.w[1] & 0x7fff000000000000ull) >> 49) & 0x3fff;
- bcoeff.w[1] = (x.w[1] & 0x0001ffffffffffffull);
- bcoeff.w[0] = x.w[0];
+ if ((comb & 0x18000) == 0x18000) {
+ /* Noncanonical significand (prepending 8 or 9 to any 110-bit
+ trailing significand field produces a value above 10^34). */
+ exp = (comb & 0x7fff) >> 1;
+ bcoeff.w[1] = 0;
+ bcoeff.w[0] = 0;
+ } else {
+ exp = ((x.w[1] & 0x7fff000000000000ull) >> 49) & 0x3fff;
+ bcoeff.w[1] = (x.w[1] & 0x0001ffffffffffffull);
+ bcoeff.w[0] = x.w[0];
+ if (bcoeff.w[1] > 0x1ed09bead87c0ull
+ || (bcoeff.w[1] == 0x1ed09bead87c0ull
+ && bcoeff.w[0] >= 0x378d8e6400000000ull)) {
+ bcoeff.w[1] = 0;
+ bcoeff.w[0] = 0;
+ }
+ }
d1018 = reciprocals10_128[18];
__mul_128x128_high (BH, bcoeff, d1018);
amount = recip_scale[18];