1/* Subroutines for long double support.
2   Copyright (C) 2000, 2002, 2004, 2005, 2006 Free Software Foundation, Inc.
3
4This file is part of GCC.
5
6GCC is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2, or (at your option)
9any later version.
10
11In addition to the permissions in the GNU General Public License, the
12Free Software Foundation gives you unlimited permission to link the
13compiled version of this file into combinations with other programs,
14and to distribute those combinations without any restriction coming
15from the use of this file.  (The General Public License restrictions
16do apply in other respects; for example, they cover modification of
17the file, and distribution when not linked into a combine
18executable.)
19
20GCC is distributed in the hope that it will be useful,
21but WITHOUT ANY WARRANTY; without even the implied warranty of
22MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23GNU General Public License for more details.
24
25You should have received a copy of the GNU General Public License
26along with GCC; see the file COPYING.  If not, write to
27the Free Software Foundation, 51 Franklin Street, Fifth Floor,
28Boston, MA 02110-1301, USA.  */
29
30/* HPUX TFmode compare requires a library call to _U_Qfcmp.  It takes
31   a magic number as its third argument which indicates what to do.
32   The return value is an integer to be compared against zero.  The
33   comparison conditions are the same as those listed in Table 8-12
34   of the PA-RISC 2.0 Architecture book for the fcmp instruction.  */
35
36/* Raise FP_INVALID on SNaN as a side effect.  */
37#define QCMP_INV 1
38
39/* Comparison relations.  */
40#define QCMP_UNORD 2
41#define QCMP_EQ 4
42#define QCMP_LT 8
43#define QCMP_GT 16
44
45int _U_Qfcmp (long double a, long double b, int);
46long _U_Qfcnvfxt_quad_to_sgl (long double);
47
48int _U_Qfeq (long double, long double);
49int _U_Qfne (long double, long double);
50int _U_Qfgt (long double, long double);
51int _U_Qfge (long double, long double);
52int _U_Qflt (long double, long double);
53int _U_Qfle (long double, long double);
54int _U_Qfltgt (long double, long double);
55int _U_Qfunle (long double, long double);
56int _U_Qfunlt (long double, long double);
57int _U_Qfunge (long double, long double);
58int _U_Qfungt (long double, long double);
59int _U_Qfuneq (long double, long double);
60int _U_Qfunord (long double, long double);
61int _U_Qford (long double, long double);
62
63int _U_Qfcomp (long double, long double);
64
65long double _U_Qfneg (long double);
66
67#ifdef __LP64__
68int __U_Qfcnvfxt_quad_to_sgl (long double);
69#endif
70unsigned int _U_Qfcnvfxt_quad_to_usgl(long double);
71unsigned long long _U_Qfcnvfxt_quad_to_udbl(long double);
72
73int
74_U_Qfeq (long double a, long double b)
75{
76  return (_U_Qfcmp (a, b, QCMP_EQ) != 0);
77}
78
79int
80_U_Qfne (long double a, long double b)
81{
82  return (_U_Qfcmp (a, b, QCMP_EQ) == 0);
83}
84
85int
86_U_Qfgt (long double a, long double b)
87{
88  return (_U_Qfcmp (a, b, QCMP_INV | QCMP_GT) != 0);
89}
90
91int
92_U_Qfge (long double a, long double b)
93{
94  return (_U_Qfcmp (a, b, QCMP_INV | QCMP_EQ | QCMP_GT) != 0);
95}
96
97int
98_U_Qflt (long double a, long double b)
99{
100  return (_U_Qfcmp (a, b, QCMP_INV | QCMP_LT) != 0);
101}
102
103int
104_U_Qfle (long double a, long double b)
105{
106  return (_U_Qfcmp (a, b, QCMP_INV | QCMP_EQ | QCMP_LT) != 0);
107}
108
109int
110_U_Qfltgt (long double a, long double b)
111{
112  return (_U_Qfcmp (a, b, QCMP_INV | QCMP_LT | QCMP_GT) != 0);
113}
114
115int
116_U_Qfunle (long double a, long double b)
117{
118  return (_U_Qfcmp (a, b, QCMP_INV | QCMP_UNORD | QCMP_EQ | QCMP_LT) != 0);
119}
120
121int
122_U_Qfunlt (long double a, long double b)
123{
124  return (_U_Qfcmp (a, b, QCMP_INV | QCMP_UNORD | QCMP_LT) != 0);
125}
126
127int
128_U_Qfunge (long double a, long double b)
129{
130  return (_U_Qfcmp (a, b, QCMP_INV | QCMP_UNORD | QCMP_EQ | QCMP_GT) != 0);
131}
132
133int
134_U_Qfungt (long double a, long double b)
135{
136  return (_U_Qfcmp (a, b, QCMP_INV | QCMP_UNORD | QCMP_GT) != 0);
137}
138
139int
140_U_Qfuneq (long double a, long double b)
141{
142  return (_U_Qfcmp (a, b, QCMP_INV | QCMP_UNORD | QCMP_EQ) != 0);
143}
144
145int
146_U_Qfunord (long double a, long double b)
147{
148  return (_U_Qfcmp (a, b, QCMP_INV | QCMP_UNORD) != 0);
149}
150
151int
152_U_Qford (long double a, long double b)
153{
154  return (_U_Qfcmp (a, b, QCMP_INV | QCMP_EQ | QCMP_LT | QCMP_GT) != 0);
155}
156
157int
158_U_Qfcomp (long double a, long double b)
159{
160  if (_U_Qfcmp (a, b, QCMP_EQ) == 0)
161    return 0;
162
163  return (_U_Qfcmp (a, b, QCMP_UNORD | QCMP_EQ | QCMP_GT) != 0 ? 1 : -1);
164}
165
166
167/* Negate long double A.  */
168long double
169_U_Qfneg (long double a)
170{
171  union
172   {
173     long double ld;
174     int i[4];
175   } u;
176
177  u.ld = a;
178  u.i[0] ^= 0x80000000;
179  return u.ld;
180}
181
182#ifdef __LP64__
183/* This routine is only necessary for the PA64 port; for reasons unknown
184   _U_Qfcnvfxt_quad_to_sgl returns the integer in the high 32bits of the
185   return value.  Ugh.  */
186int
187__U_Qfcnvfxt_quad_to_sgl (long double a)
188{
189  return _U_Qfcnvfxt_quad_to_sgl (a) >> 32;
190}
191#endif
192
193/* HP only has signed conversion in library, so need to synthesize an
194   unsigned version */
195unsigned int
196_U_Qfcnvfxt_quad_to_usgl(long double a)
197{
198  extern long long _U_Qfcnvfxt_quad_to_dbl (long double a);
199  return (unsigned int) _U_Qfcnvfxt_quad_to_dbl (a);
200}
201
202/* HP only has signed conversion in library, so need to synthesize an
203   unsigned version */
204typedef union {
205    long long unsigned int u[2];
206    long double d[1];
207} quad_type;
208
209unsigned long long
210_U_Qfcnvfxt_quad_to_udbl(long double a)
211{
212  extern quad_type _U_Qfcnvfxt_quad_to_quad (long double a);
213  quad_type u;
214  u = _U_Qfcnvfxt_quad_to_quad(a);
215  return u.u[1];
216}
217