1  /* { dg-do run { target { powerpc*-*-linux* } } } */
       2  /* { dg-require-effective-target ppc_float128_sw } */
       3  /* { dg-require-effective-target vsx_hw } */
       4  /* { dg-options "-mvsx -O2" } */
       5  
       6  #ifdef DEBUG
       7  #include <stdio.h>
       8  #include <stddef.h>
       9  #include <stdint.h>
      10  #include <inttypes.h>
      11  #endif
      12  
      13  #if !defined(__FLOAT128__) || !defined(_ARCH_PPC)
      14  static __float128
      15  pass_through (__float128 x)
      16  {
      17    return x;
      18  }
      19  
      20  __float128 (*no_optimize) (__float128) = pass_through;
      21  #endif
      22  
      23  #ifdef DEBUG
      24  __attribute__((__noinline__))
      25  static void
      26  print_f128 (__float128 x)
      27  {
      28    unsigned sign;
      29    unsigned exponent;
      30    uint64_t mantissa1;
      31    uint64_t mantissa2;
      32    uint64_t upper;
      33    uint64_t lower;
      34  
      35  #if defined(_ARCH_PPC) && defined(__BIG_ENDIAN__)
      36    struct ieee128 {
      37      uint64_t upper;
      38      uint64_t lower;
      39    };
      40  
      41  #elif (defined(_ARCH_PPC) && defined(__LITTLE_ENDIAN__)) || defined(__x86_64__)
      42    struct ieee128 {
      43      uint64_t lower;
      44      uint64_t upper;
      45    };
      46  
      47  #else
      48  #error "Unknown system"
      49  #endif
      50  
      51    union {
      52      __float128 f128;
      53      struct ieee128 s128;
      54    } u;
      55  
      56    u.f128 = x;
      57    upper  = u.s128.upper;
      58    lower  = u.s128.lower;
      59  
      60    sign      = (unsigned)((upper >> 63) & 1);
      61    exponent  = (unsigned)((upper >> 48) & ((((uint64_t)1) << 16) - 1));
      62    mantissa1 = (upper & ((((uint64_t)1) << 48) - 1));
      63    mantissa2 = lower;
      64  
      65    printf ("%c 0x%.4x 0x%.12" PRIx64 " 0x%.16" PRIx64,
      66  	  sign ? '-' : '+',
      67  	  exponent,
      68  	  mantissa1,
      69  	  mantissa2);
      70  }
      71  #endif
      72  
      73  __attribute__((__noinline__))
      74  static void
      75  do_test (__float128 expected, __float128 got, const char *name)
      76  {
      77    int equal_p = (expected == got);
      78  
      79  #ifdef DEBUG
      80    printf ("Test %s, expected: ", name);
      81    print_f128 (expected);
      82    printf (" %5g, got: ", (double) expected);
      83    print_f128 (got);
      84    printf (" %5g, result %s\n",
      85  	  (double) got,
      86  	  (equal_p) ? "equal" : "not equal");
      87  #endif
      88  
      89    if (!equal_p)
      90      __builtin_abort ();
      91  }
      92  
      93  
      94  int
      95  main (void)
      96  {
      97    __float128 one	= 1.0q;
      98    __float128 two	= 2.0q;
      99    __float128 three	= 3.0q;
     100    __float128 four	= 4.0q;
     101    __float128 five	= 5.0q;
     102    __float128 add_result = (1.0q + 2.0q);
     103    __float128 mul_result = ((1.0q + 2.0q) * 3.0q);
     104    __float128 div_result = (((1.0q + 2.0q) * 3.0q) / 4.0q);
     105    __float128 sub_result = ((((1.0q + 2.0q) * 3.0q) / 4.0q) - 5.0q);
     106    __float128 neg_result = - sub_result;
     107    __float128 add_xresult;
     108    __float128 mul_xresult;
     109    __float128 div_xresult;
     110    __float128 sub_xresult;
     111    __float128 neg_xresult;
     112  
     113  #if defined(__FLOAT128__) && defined(_ARCH_PPC)
     114    __asm__ (" #prevent constant folding, %x0" : "+wa" (one));
     115    __asm__ (" #prevent constant folding, %x0" : "+wa" (two));
     116    __asm__ (" #prevent constant folding, %x0" : "+wa" (three));
     117    __asm__ (" #prevent constant folding, %x0" : "+wa" (four));
     118    __asm__ (" #prevent constant folding, %x0" : "+wa" (five));
     119  
     120  #else
     121    one   = no_optimize (one);
     122    two   = no_optimize (two);
     123    three = no_optimize (three);
     124    four  = no_optimize (four);
     125    five  = no_optimize (five);
     126  #endif
     127  
     128    add_xresult = (one + two);
     129    do_test (add_result, add_xresult, "add");
     130  
     131    mul_xresult = add_xresult * three;
     132    do_test (mul_result, mul_xresult, "mul");
     133  
     134    div_xresult = mul_xresult / four;
     135    do_test (div_result, div_xresult, "div");
     136  
     137    sub_xresult = div_xresult - five;
     138    do_test (sub_result, sub_xresult, "sub");
     139  
     140    neg_xresult = - sub_xresult;
     141    do_test (neg_result, neg_xresult, "neg");
     142  
     143  #ifdef DEBUG
     144    printf ("Passed\n");
     145  #endif
     146  
     147    return 0;
     148  }