aboutsummaryrefslogtreecommitdiff
path: root/gcc/testsuite/gcc.target/powerpc/pack02.c
blob: 07d3ba0c3906ef86976dda4c837a02c9754aadc3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
/* { 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;
}