| /* { dg-do run { target { powerpc*-*-linux* } } } */ |
| /* { dg-require-effective-target ppc_float128_sw } */ |
| /* { dg-require-effective-target vsx_hw } */ |
| /* { dg-options "-mvsx -O2" } */ |
| |
| /* This is the same as test float128-1.c, using the _Float128 keyword instead |
| of __float128, and not using -mfloat128. */ |
| |
| #ifdef DEBUG |
| #include <stdio.h> |
| #include <stddef.h> |
| #include <stdint.h> |
| #include <inttypes.h> |
| #endif |
| |
| #if !defined(__FLOAT128__) || !defined(_ARCH_PPC) |
| static _Float128 |
| pass_through (_Float128 x) |
| { |
| return x; |
| } |
| |
| _Float128 (*no_optimize) (_Float128) = pass_through; |
| #endif |
| |
| #ifdef DEBUG |
| __attribute__((__noinline__)) |
| static void |
| print_f128 (_Float128 x) |
| { |
| unsigned sign; |
| unsigned exponent; |
| uint64_t mantissa1; |
| uint64_t mantissa2; |
| uint64_t upper; |
| uint64_t lower; |
| |
| #if defined(_ARCH_PPC) && defined(__BIG_ENDIAN__) |
| struct ieee128 { |
| uint64_t upper; |
| uint64_t lower; |
| }; |
| |
| #elif (defined(_ARCH_PPC) && defined(__LITTLE_ENDIAN__)) || defined(__x86_64__) |
| struct ieee128 { |
| uint64_t lower; |
| uint64_t upper; |
| }; |
| |
| #else |
| #error "Unknown system" |
| #endif |
| |
| union { |
| _Float128 f128; |
| struct ieee128 s128; |
| } u; |
| |
| u.f128 = x; |
| upper = u.s128.upper; |
| lower = u.s128.lower; |
| |
| sign = (unsigned)((upper >> 63) & 1); |
| exponent = (unsigned)((upper >> 48) & ((((uint64_t)1) << 16) - 1)); |
| mantissa1 = (upper & ((((uint64_t)1) << 48) - 1)); |
| mantissa2 = lower; |
| |
| printf ("%c 0x%.4x 0x%.12" PRIx64 " 0x%.16" PRIx64, |
| sign ? '-' : '+', |
| exponent, |
| mantissa1, |
| mantissa2); |
| } |
| #endif |
| |
| __attribute__((__noinline__)) |
| static void |
| do_test (_Float128 expected, _Float128 got, const char *name) |
| { |
| int equal_p = (expected == got); |
| |
| #ifdef DEBUG |
| printf ("Test %s, expected: ", name); |
| print_f128 (expected); |
| printf (" %5g, got: ", (double) expected); |
| print_f128 (got); |
| printf (" %5g, result %s\n", |
| (double) got, |
| (equal_p) ? "equal" : "not equal"); |
| #endif |
| |
| if (!equal_p) |
| __builtin_abort (); |
| } |
| |
| |
| int |
| main (void) |
| { |
| _Float128 one = 1.0f128; |
| _Float128 two = 2.0f128; |
| _Float128 three = 3.0f128; |
| _Float128 four = 4.0f128; |
| _Float128 five = 5.0f128; |
| _Float128 add_result = (1.0f128 + 2.0f128); |
| _Float128 mul_result = ((1.0f128 + 2.0f128) * 3.0f128); |
| _Float128 div_result = (((1.0f128 + 2.0f128) * 3.0f128) / 4.0f128); |
| _Float128 sub_result = ((((1.0f128 + 2.0f128) * 3.0f128) / 4.0f128) |
| - 5.0f128); |
| _Float128 neg_result = - sub_result; |
| _Float128 add_xresult; |
| _Float128 mul_xresult; |
| _Float128 div_xresult; |
| _Float128 sub_xresult; |
| _Float128 neg_xresult; |
| |
| #if defined(__FLOAT128__) && defined(_ARCH_PPC) |
| __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)); |
| __asm__ (" #prevent constant folding, %x0" : "+wa" (five)); |
| |
| #else |
| one = no_optimize (one); |
| two = no_optimize (two); |
| three = no_optimize (three); |
| four = no_optimize (four); |
| five = no_optimize (five); |
| #endif |
| |
| add_xresult = (one + two); |
| do_test (add_result, add_xresult, "add"); |
| |
| mul_xresult = add_xresult * three; |
| do_test (mul_result, mul_xresult, "mul"); |
| |
| div_xresult = mul_xresult / four; |
| do_test (div_result, div_xresult, "div"); |
| |
| sub_xresult = div_xresult - five; |
| do_test (sub_result, sub_xresult, "sub"); |
| |
| neg_xresult = - sub_xresult; |
| do_test (neg_result, neg_xresult, "neg"); |
| |
| #ifdef DEBUG |
| printf ("Passed\n"); |
| #endif |
| |
| return 0; |
| } |