diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 8361b783728..6cda5be58f9 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,15 @@ +2019-12-09 Joseph Myers + + 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 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 00000000000..eee5471cae0 --- /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 00000000000..626712153b4 --- /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 00000000000..9190daedaf6 --- /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 00000000000..b148ce445e7 --- /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 00000000000..b46b71cc3fc --- /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 00000000000..11d64dce193 --- /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 00000000000..87b106945d4 --- /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 00000000000..3c10145a314 --- /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 62a2e57467d..6c617881d25 100644 --- a/libdecnumber/ChangeLog +++ b/libdecnumber/ChangeLog @@ -1,3 +1,11 @@ +2019-12-09 Joseph Myers + + 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 Update copyright years. diff --git a/libdecnumber/bid/bid2dpd_dpd2bid.c b/libdecnumber/bid/bid2dpd_dpd2bid.c index 63d3cecfe8d..36aa56c540d 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];