| /* { dg-do run { target { powerpc*-*-linux* } } } */ |
| /* { dg-skip-if "" { powerpc*-*-darwin* } } */ |
| /* { dg-require-effective-target powerpc_fprs } */ |
| /* { dg-require-effective-target longdouble128 } */ |
| /* { dg-options "-O2 -mhard-float" } */ |
| |
| #include <stddef.h> |
| #include <stdlib.h> |
| #include <math.h> |
| |
| #ifdef DEBUG |
| #include <stdio.h> |
| #endif |
| |
| #if defined(__LONG_DOUBLE_IEEE128__) |
| /* If long double is IEEE 128-bit, we need to use the __ibm128 type instead of |
| long double, and to use the appropriate pack/unpack routines. We can't use |
| __ibm128 on systems that don't support IEEE 128-bit floating point, because |
| the type is not enabled on those systems. */ |
| #define PACK __builtin_pack_ibm128 |
| #define UNPACK __builtin_unpack_ibm128 |
| #define LDOUBLE __ibm128 |
| |
| #elif defined(__LONG_DOUBLE_IBM128__) |
| #define PACK __builtin_pack_longdouble |
| #define UNPACK __builtin_unpack_longdouble |
| #define LDOUBLE long double |
| |
| #else |
| #error "long double must be either IBM 128-bit or IEEE 128-bit" |
| #endif |
| |
| int |
| main (void) |
| { |
| double high = pow (2.0, 60); |
| double low = 2.0; |
| LDOUBLE a = ((LDOUBLE)high) + ((LDOUBLE)low); |
| double x0 = UNPACK (a, 0); |
| double x1 = UNPACK (a, 1); |
| LDOUBLE b = PACK (x0, x1); |
| |
| #ifdef DEBUG |
| { |
| size_t i; |
| union { |
| LDOUBLE ld; |
| double d; |
| unsigned char uc[sizeof (LDOUBLE)]; |
| char c[sizeof (LDOUBLE)]; |
| } u; |
| |
| printf ("a = 0x"); |
| u.ld = a; |
| for (i = 0; i < sizeof (LDOUBLE); i++) |
| printf ("%.2x", u.uc[i]); |
| |
| printf (", %Lg\n", a); |
| |
| printf ("b = 0x"); |
| u.ld = b; |
| for (i = 0; i < sizeof (LDOUBLE); i++) |
| printf ("%.2x", u.uc[i]); |
| |
| printf (", %Lg\n", b); |
| |
| printf ("hi = 0x"); |
| u.d = high; |
| for (i = 0; i < sizeof (double); i++) |
| printf ("%.2x", u.uc[i]); |
| |
| printf (",%*s %g\n", (int)(2 * (sizeof (LDOUBLE) - sizeof (double))), "", high); |
| |
| printf ("lo = 0x"); |
| u.d = low; |
| for (i = 0; i < sizeof (double); i++) |
| printf ("%.2x", u.uc[i]); |
| |
| printf (",%*s %g\n", (int)(2 * (sizeof (LDOUBLE) - sizeof (double))), "", low); |
| |
| printf ("x0 = 0x"); |
| u.d = x0; |
| for (i = 0; i < sizeof (double); i++) |
| printf ("%.2x", u.uc[i]); |
| |
| printf (",%*s %g\n", (int)(2 * (sizeof (LDOUBLE) - sizeof (double))), "", x0); |
| |
| printf ("x1 = 0x"); |
| u.d = x1; |
| for (i = 0; i < sizeof (double); i++) |
| printf ("%.2x", u.uc[i]); |
| |
| printf (",%*s %g\n", (int)(2 * (sizeof (LDOUBLE) - sizeof (double))), "", x1); |
| } |
| #endif |
| |
| if (high != x0) |
| abort (); |
| |
| if (low != x1) |
| abort (); |
| |
| if (a != b) |
| abort (); |
| |
| if (x0 != high) |
| abort (); |
| |
| if (x1 != low) |
| abort (); |
| |
| return 0; |
| } |