Index: gcc/testsuite/gcc.target/powerpc/float128-1.c =================================================================== --- gcc/testsuite/gcc.target/powerpc/float128-1.c (.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk) (revision 0) +++ gcc/testsuite/gcc.target/powerpc/float128-1.c (revision 212529) @@ -0,0 +1,27 @@ +/* { dg-do run { target { powerpc*-*-linux* } } } */ +/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */ +/* { dg-skip-if "" { powerpc*-*-*spe* } { "*" } { "" } } */ +/* { dg-require-effective-target vsx_hw } */ +/* { dg-options "-mcpu=power7 -O2 -mfloat128-vsx" } */ + +int +main (void) +{ + __float128 one = 1.0q; + __float128 two = 2.0q; + __float128 three = 3.0q; + __float128 four = 4.0q; + __float128 result = ((1.0q + 2.0q) * 3.0q) / 4.0q; + __float128 xresult; + + __asm__ (" #prevent constant folding, %x0" : "+wa" (one)); + __asm__ (" #prevent constant folding, %x0" : "+wa" (two)); + __asm__ (" #prevent constant folding, %x0" : "+wa" (three)); + __asm__ (" #prevent constant folding, %x0" : "+wa" (four)); + + xresult = ((one + two) * three) / four; + if (result != xresult) + __builtin_abort (); + + return 0; +} Index: gcc/testsuite/gcc.target/powerpc/float128-2.c =================================================================== --- gcc/testsuite/gcc.target/powerpc/float128-2.c (.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk) (revision 0) +++ gcc/testsuite/gcc.target/powerpc/float128-2.c (revision 212529) @@ -0,0 +1,27 @@ +/* { dg-do run { target { powerpc*-*-linux* } } } */ +/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */ +/* { dg-skip-if "" { powerpc*-*-*spe* } { "*" } { "" } } */ +/* { dg-require-effective-target ppc_recip_hw } */ +/* { dg-options "-O2 -mfloat128-ref" } */ + +int +main (void) +{ + __float128 one = 1.0q; + __float128 two = 2.0q; + __float128 three = 3.0q; + __float128 four = 4.0q; + __float128 result = ((1.0q + 2.0q) * 3.0q) / 4.0q; + __float128 xresult; + + __asm__ (" #prevent constant folding, %0" : "+d" (one)); + __asm__ (" #prevent constant folding, %0" : "+d" (two)); + __asm__ (" #prevent constant folding, %0" : "+d" (three)); + __asm__ (" #prevent constant folding, %0" : "+d" (four)); + + xresult = ((one + two) * three) / four; + if (result != xresult) + __builtin_abort (); + + return 0; +} Index: gcc/testsuite/gcc.target/powerpc/float128-3.c =================================================================== --- gcc/testsuite/gcc.target/powerpc/float128-3.c (.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk) (revision 0) +++ gcc/testsuite/gcc.target/powerpc/float128-3.c (revision 212529) @@ -0,0 +1,182 @@ +/* { dg-do run { target { powerpc*-*-linux* } } } */ +/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */ +/* { dg-skip-if "" { powerpc*-*-*spe* } { "*" } { "" } } */ +/* { dg-require-effective-target vsx_hw } */ +/* { dg-options "-mcpu=power7 -O2 -mfloat128-vsx" } */ + +/* + * Test program to make sure we are getting more precision than the 53 bits we + * get with IEEE double. + */ + +#include +#include +#include +#include + +#ifndef TYPE +#define TYPE __float128 +#endif + +#ifndef NO_INLINE +#define NO_INLINE __attribute__((__noinline__)) +#endif + +static TYPE power_of_two (ssize_t) NO_INLINE; +static TYPE calc1 (TYPE) NO_INLINE; +static TYPE calc2 (TYPE) NO_INLINE; +static TYPE calc3 (TYPE) NO_INLINE; + + +/* + * Print TYPE in hex. + */ + + +#ifdef DEBUG +static void print_hex (const char *prefix, TYPE, const char *suffix) NO_INLINE; + +#if defined (__i386__) || defined (__x86_64__) || defined (__LITTLE_ENDIAN__) +#define ENDIAN_REVERSE(N, MAX) ((MAX) - 1 - (N)) + +#else +#define ENDIAN_REVERSE(N, MAX) (N) +#endif + +static void +print_hex (const char *prefix, TYPE value, const char *suffix) +{ + union { + TYPE f128; + unsigned char uc[sizeof (TYPE)]; + } u; + + size_t i; + + u.f128 = value; + printf ("%s0x", prefix); + for (i = 0; i < sizeof (TYPE); i++) + printf ("%.2x", u.uc[ ENDIAN_REVERSE (i, sizeof (TYPE)) ]); + + printf (", %24.2Lf%s", (long double)value, suffix); +} +#endif + + +/* + * Return a power of two. + */ + +static TYPE +power_of_two (ssize_t num) +{ + TYPE ret = (TYPE) 1.0; + ssize_t i; + + if (num >= 0) + { + for (i = 0; i < num; i++) + ret *= (TYPE) 2.0; + } + else + { + ssize_t num2 = -num; + for (i = 0; i < num2; i++) + ret /= (TYPE) 2.0; + } + +#ifdef DEBUG + printf ("power_of_two (%2ld) = ", (long) num); + print_hex ("", ret, "\n"); +#endif + + return ret; +} + + +/* + * Various calculations. Add in 2**60, and subtract 2**59 twice, and we should + * get the original value. + */ + +static TYPE +calc1 (TYPE num) +{ + TYPE num2 = power_of_two (60) + num; + TYPE ret; + +#ifdef DEBUG + print_hex ("calc1 (before call) = ", num2, "\n"); +#endif + + ret = calc2 (num2); + +#ifdef DEBUG + print_hex ("calc1 (after call) = ", ret, "\n"); +#endif + + return ret; +} + +static TYPE +calc2 (TYPE num) +{ + TYPE num2 = num - power_of_two (59); + TYPE ret; + +#ifdef DEBUG + print_hex ("calc2 (before call) = ", num2, "\n"); +#endif + + ret = calc3 (num2); + +#ifdef DEBUG + print_hex ("calc2 (after call) = ", ret, "\n"); +#endif + + return ret; +} + +static TYPE +calc3 (TYPE num) +{ + TYPE ret = num - (((TYPE) 2.0) * power_of_two (58)); + +#ifdef DEBUG + print_hex ("calc3 = ", ret, "\n"); +#endif + + return ret; +} + + +int +main (void) +{ + TYPE input, output; + +#ifdef DEBUG + printf ("Testing %s, %ld bytes\n", TYPE_NAME, (long) sizeof (TYPE)); +#endif + + input = power_of_two (-1); + output = calc1 (input); + + if (input != (TYPE) 0.5) + { +#ifdef DEBUG + print_hex ("Input should be 0.5: ", output, "\n"); +#endif + __builtin_abort (); + } + + if (output != (TYPE) 0.5) + { +#ifdef DEBUG + print_hex ("Output should be 0.5: ", output, "\n"); +#endif + __builtin_abort (); + } + + return 0; +} Index: gcc/testsuite/gcc.target/powerpc/float128-4.c =================================================================== --- gcc/testsuite/gcc.target/powerpc/float128-4.c (.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk) (revision 0) +++ gcc/testsuite/gcc.target/powerpc/float128-4.c (revision 212529) @@ -0,0 +1,182 @@ +/* { dg-do run { target { powerpc*-*-linux* } } } */ +/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */ +/* { dg-skip-if "" { powerpc*-*-*spe* } { "*" } { "" } } */ +/* { dg-require-effective-target ppc_recip_hw } */ +/* { dg-options "-O2 -mfloat128-ref" } */ + +/* + * Test program to make sure we are getting more precision than the 53 bits we + * get with IEEE double. + */ + +#include +#include +#include +#include + +#ifndef TYPE +#define TYPE __float128 +#endif + +#ifndef NO_INLINE +#define NO_INLINE __attribute__((__noinline__)) +#endif + +static TYPE power_of_two (ssize_t) NO_INLINE; +static TYPE calc1 (TYPE) NO_INLINE; +static TYPE calc2 (TYPE) NO_INLINE; +static TYPE calc3 (TYPE) NO_INLINE; + + +/* + * Print TYPE in hex. + */ + + +#ifdef DEBUG +static void print_hex (const char *prefix, TYPE, const char *suffix) NO_INLINE; + +#if defined (__i386__) || defined (__x86_64__) || defined (__LITTLE_ENDIAN__) +#define ENDIAN_REVERSE(N, MAX) ((MAX) - 1 - (N)) + +#else +#define ENDIAN_REVERSE(N, MAX) (N) +#endif + +static void +print_hex (const char *prefix, TYPE value, const char *suffix) +{ + union { + TYPE f128; + unsigned char uc[sizeof (TYPE)]; + } u; + + size_t i; + + u.f128 = value; + printf ("%s0x", prefix); + for (i = 0; i < sizeof (TYPE); i++) + printf ("%.2x", u.uc[ ENDIAN_REVERSE (i, sizeof (TYPE)) ]); + + printf (", %24.2Lf%s", (long double)value, suffix); +} +#endif + + +/* + * Return a power of two. + */ + +static TYPE +power_of_two (ssize_t num) +{ + TYPE ret = (TYPE) 1.0; + ssize_t i; + + if (num >= 0) + { + for (i = 0; i < num; i++) + ret *= (TYPE) 2.0; + } + else + { + ssize_t num2 = -num; + for (i = 0; i < num2; i++) + ret /= (TYPE) 2.0; + } + +#ifdef DEBUG + printf ("power_of_two (%2ld) = ", (long) num); + print_hex ("", ret, "\n"); +#endif + + return ret; +} + + +/* + * Various calculations. Add in 2**60, and subtract 2**59 twice, and we should + * get the original value. + */ + +static TYPE +calc1 (TYPE num) +{ + TYPE num2 = power_of_two (60) + num; + TYPE ret; + +#ifdef DEBUG + print_hex ("calc1 (before call) = ", num2, "\n"); +#endif + + ret = calc2 (num2); + +#ifdef DEBUG + print_hex ("calc1 (after call) = ", ret, "\n"); +#endif + + return ret; +} + +static TYPE +calc2 (TYPE num) +{ + TYPE num2 = num - power_of_two (59); + TYPE ret; + +#ifdef DEBUG + print_hex ("calc2 (before call) = ", num2, "\n"); +#endif + + ret = calc3 (num2); + +#ifdef DEBUG + print_hex ("calc2 (after call) = ", ret, "\n"); +#endif + + return ret; +} + +static TYPE +calc3 (TYPE num) +{ + TYPE ret = num - (((TYPE) 2.0) * power_of_two (58)); + +#ifdef DEBUG + print_hex ("calc3 = ", ret, "\n"); +#endif + + return ret; +} + + +int +main (void) +{ + TYPE input, output; + +#ifdef DEBUG + printf ("Testing %s, %ld bytes\n", TYPE_NAME, (long) sizeof (TYPE)); +#endif + + input = power_of_two (-1); + output = calc1 (input); + + if (input != (TYPE) 0.5) + { +#ifdef DEBUG + print_hex ("Input should be 0.5: ", output, "\n"); +#endif + __builtin_abort (); + } + + if (output != (TYPE) 0.5) + { +#ifdef DEBUG + print_hex ("Output should be 0.5: ", output, "\n"); +#endif + __builtin_abort (); + } + + return 0; +}