1/* Subroutines for long double support.
2   Copyright (C) 2000-2020 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 3, or (at your option)
9any later version.
10
11GCC is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14GNU General Public License for more details.
15
16Under Section 7 of GPL version 3, you are granted additional
17permissions described in the GCC Runtime Library Exception, version
183.1, as published by the Free Software Foundation.
19
20You should have received a copy of the GNU General Public License and
21a copy of the GCC Runtime Library Exception along with this program;
22see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
23<http://www.gnu.org/licenses/>.  */
24
25/* HPUX TFmode compare requires a library call to _U_Qfcmp.  It takes
26   a magic number as its third argument which indicates what to do.
27   The return value is an integer to be compared against zero.  The
28   comparison conditions are the same as those listed in Table 8-12
29   of the PA-RISC 2.0 Architecture book for the fcmp instruction.  */
30
31/* Raise FP_INVALID on SNaN as a side effect.  */
32#define QCMP_INV 1
33
34/* Comparison relations.  */
35#define QCMP_UNORD 2
36#define QCMP_EQ 4
37#define QCMP_LT 8
38#define QCMP_GT 16
39
40int _U_Qfcmp (long double a, long double b, int);
41long _U_Qfcnvfxt_quad_to_sgl (long double);
42
43int _U_Qfeq (long double, long double);
44int _U_Qfne (long double, long double);
45int _U_Qfgt (long double, long double);
46int _U_Qfge (long double, long double);
47int _U_Qflt (long double, long double);
48int _U_Qfle (long double, long double);
49int _U_Qfltgt (long double, long double);
50int _U_Qfunle (long double, long double);
51int _U_Qfunlt (long double, long double);
52int _U_Qfunge (long double, long double);
53int _U_Qfungt (long double, long double);
54int _U_Qfuneq (long double, long double);
55int _U_Qfunord (long double, long double);
56int _U_Qford (long double, long double);
57
58int _U_Qfcomp (long double, long double);
59
60long double _U_Qfneg (long double);
61long double _U_Qfcopysign (long double, long double);
62
63#ifdef __LP64__
64int __U_Qfcnvfxt_quad_to_sgl (long double);
65#endif
66unsigned int _U_Qfcnvfxt_quad_to_usgl(long double);
67long double _U_Qfcnvxf_usgl_to_quad (unsigned int);
68unsigned long long _U_Qfcnvfxt_quad_to_udbl(long double);
69long double _U_Qfcnvxf_udbl_to_quad (unsigned long long);
70
71int
72_U_Qfeq (long double a, long double b)
73{
74  return (_U_Qfcmp (a, b, QCMP_EQ) != 0);
75}
76
77int
78_U_Qfne (long double a, long double b)
79{
80  return (_U_Qfcmp (a, b, QCMP_EQ) == 0);
81}
82
83int
84_U_Qfgt (long double a, long double b)
85{
86  return (_U_Qfcmp (a, b, QCMP_INV | QCMP_GT) != 0);
87}
88
89int
90_U_Qfge (long double a, long double b)
91{
92  return (_U_Qfcmp (a, b, QCMP_INV | QCMP_EQ | QCMP_GT) != 0);
93}
94
95int
96_U_Qflt (long double a, long double b)
97{
98  return (_U_Qfcmp (a, b, QCMP_INV | QCMP_LT) != 0);
99}
100
101int
102_U_Qfle (long double a, long double b)
103{
104  return (_U_Qfcmp (a, b, QCMP_INV | QCMP_EQ | QCMP_LT) != 0);
105}
106
107int
108_U_Qfltgt (long double a, long double b)
109{
110  return (_U_Qfcmp (a, b, QCMP_INV | QCMP_LT | QCMP_GT) != 0);
111}
112
113int
114_U_Qfunle (long double a, long double b)
115{
116  return (_U_Qfcmp (a, b, QCMP_INV | QCMP_UNORD | QCMP_EQ | QCMP_LT) != 0);
117}
118
119int
120_U_Qfunlt (long double a, long double b)
121{
122  return (_U_Qfcmp (a, b, QCMP_INV | QCMP_UNORD | QCMP_LT) != 0);
123}
124
125int
126_U_Qfunge (long double a, long double b)
127{
128  return (_U_Qfcmp (a, b, QCMP_INV | QCMP_UNORD | QCMP_EQ | QCMP_GT) != 0);
129}
130
131int
132_U_Qfungt (long double a, long double b)
133{
134  return (_U_Qfcmp (a, b, QCMP_INV | QCMP_UNORD | QCMP_GT) != 0);
135}
136
137int
138_U_Qfuneq (long double a, long double b)
139{
140  return (_U_Qfcmp (a, b, QCMP_INV | QCMP_UNORD | QCMP_EQ) != 0);
141}
142
143int
144_U_Qfunord (long double a, long double b)
145{
146  return (_U_Qfcmp (a, b, QCMP_INV | QCMP_UNORD) != 0);
147}
148
149int
150_U_Qford (long double a, long double b)
151{
152  return (_U_Qfcmp (a, b, QCMP_INV | QCMP_EQ | QCMP_LT | QCMP_GT) != 0);
153}
154
155int
156_U_Qfcomp (long double a, long double b)
157{
158  if (_U_Qfcmp (a, b, QCMP_EQ) == 0)
159    return 0;
160
161  return (_U_Qfcmp (a, b, QCMP_UNORD | QCMP_EQ | QCMP_GT) != 0 ? 1 : -1);
162}
163
164/* Negate long double A.  */
165long double
166_U_Qfneg (long double a)
167{
168  union
169   {
170     long double ld;
171     int i[4];
172   } u;
173
174  u.ld = a;
175  u.i[0] ^= 0x80000000;
176  return u.ld;
177}
178
179/* Return long double A with sign changed to sign of long double B.  */
180long double
181_U_Qfcopysign (long double a, long double b)
182{
183  union
184   {
185     long double ld;
186     int i[4];
187   } ua, ub;
188
189  ua.ld = a;
190  ub.ld = b;
191  ua.i[0] &= 0x7fffffff;
192  ua.i[0] |= (0x80000000 & ub.i[0]);
193  return ua.ld;
194}
195
196#ifdef __LP64__
197/* This routine is only necessary for the PA64 port; for reasons unknown
198   _U_Qfcnvfxt_quad_to_sgl returns the integer in the high 32bits of the
199   return value.  Ugh.  */
200int
201__U_Qfcnvfxt_quad_to_sgl (long double a)
202{
203  return _U_Qfcnvfxt_quad_to_sgl (a) >> 32;
204}
205#endif
206
207/* HP only has signed conversion in the C library, so need to synthesize
208   unsigned versions.  */
209unsigned int
210_U_Qfcnvfxt_quad_to_usgl (long double a)
211{
212  extern long long _U_Qfcnvfxt_quad_to_dbl (long double a);
213  return (unsigned int) _U_Qfcnvfxt_quad_to_dbl (a);
214}
215
216long double
217_U_Qfcnvxf_usgl_to_quad (unsigned int a)
218{
219  extern long double _U_Qfcnvxf_dbl_to_quad (long long);
220  return _U_Qfcnvxf_dbl_to_quad ((long long) a);
221}
222
223typedef union {
224    unsigned long long u[2];
225    long double d[1];
226} quad_type;
227
228unsigned long long
229_U_Qfcnvfxt_quad_to_udbl (long double a)
230{
231  extern quad_type _U_Qfcnvfxt_quad_to_quad (long double a);
232  quad_type u;
233  u = _U_Qfcnvfxt_quad_to_quad(a);
234  return u.u[1];
235}
236
237long double
238_U_Qfcnvxf_udbl_to_quad (unsigned long long a)
239{
240  extern long double _U_Qfcnvxf_quad_to_quad (quad_type a);
241  quad_type u;
242  u.u[0] = 0;
243  u.u[1] = a;
244  return _U_Qfcnvxf_quad_to_quad (u);
245}
246