Fortran: xfail signaling NaN testcases on x87
[official-gcc.git] / libgfortran / ieee / issignaling_fallback.h
blobe824cf8c59bde4b2cf58ac3834a3cf5e82f751c1
1 /* Fallback implementation of issignaling macro.
2 Copyright (C) 2022 Free Software Foundation, Inc.
3 Contributed by Francois-Xavier Coudert <fxcoudert@gcc.gnu.org>
5 This file is part of the GNU Fortran runtime library (libgfortran).
7 Libgfortran is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public
9 License as published by the Free Software Foundation; either
10 version 3 of the License, or (at your option) any later version.
12 Libgfortran is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 Under Section 7 of GPL version 3, you are granted additional
18 permissions described in the GCC Runtime Library Exception, version
19 3.1, as published by the Free Software Foundation.
21 You should have received a copy of the GNU General Public License and
22 a copy of the GCC Runtime Library Exception along with this program;
23 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24 <http://www.gnu.org/licenses/>. */
26 #include "libgfortran.h"
28 /* This header provides an implementation of the type-generic issignaling macro.
29 Some points of note:
31 - This header is only included if the issignaling macro is not defined.
32 - All targets for which Fortran IEEE modules are supported currently have
33 the high-order bit of the NaN mantissa clear for signaling (and set
34 for quiet), as recommended by IEEE.
35 - We use the __*_IS_IEC_60559__ macros to make sure we only deal with formats
36 we know. For other floating-point formats, we consider all NaNs as quiet.
40 typedef union
42 float value;
43 uint32_t word;
44 } ieee_float_shape_type;
46 static inline int
47 __issignalingf (float x)
49 #if __FLT_IS_IEC_60559__
50 uint32_t xi;
51 ieee_float_shape_type u;
53 u.value = x;
54 xi = u.word;
56 xi ^= 0x00400000;
57 return (xi & 0x7fffffff) > 0x7fc00000;
58 #else
59 return 0;
60 #endif
64 typedef union
66 double value;
67 uint64_t word;
68 } ieee_double_shape_type;
70 static inline int
71 __issignaling (double x)
73 #if __DBL_IS_IEC_60559__
74 ieee_double_shape_type u;
75 uint64_t xi;
77 u.value = x;
78 xi = u.word;
80 xi ^= UINT64_C (0x0008000000000000);
81 return (xi & UINT64_C (0x7fffffffffffffff)) > UINT64_C (0x7ff8000000000000);
82 #else
83 return 0;
84 #endif
88 #if __LDBL_DIG__ == __DBL_DIG__
90 /* Long double is the same as double. */
91 static inline int
92 __issignalingl (long double x)
94 return __issignaling (x);
97 #elif (__LDBL_DIG__ == 18) && __LDBL_IS_IEC_60559__
99 /* Long double is x86 extended type. */
101 typedef union
103 long double value;
104 struct
106 #if __FLOAT_WORD_ORDER == __BIG_ENDIAN
107 int sign_exponent:16;
108 unsigned int empty:16;
109 uint32_t msw;
110 uint32_t lsw;
111 #elif __FLOAT_WORD_ORDER == __LITTLE_ENDIAN
112 uint32_t lsw;
113 uint32_t msw;
114 int sign_exponent:16;
115 unsigned int empty:16;
116 #endif
117 } parts;
118 } ieee_long_double_shape_type;
120 static inline int
121 __issignalingl (long double x)
123 int ret;
124 uint32_t exi, hxi, lxi;
125 ieee_long_double_shape_type u;
127 u.value = x;
128 exi = u.parts.sign_exponent;
129 hxi = u.parts.msw;
130 lxi = u.parts.lsw;
132 /* Pseudo numbers on x86 are always signaling. */
133 ret = (exi & 0x7fff) && ((hxi & 0x80000000) == 0);
135 hxi ^= 0x40000000;
136 hxi |= (lxi | -lxi) >> 31;
137 return ret || (((exi & 0x7fff) == 0x7fff) && (hxi > 0xc0000000));
140 #elif (__LDBL_DIG__ = 33) && __LDBL_IS_IEC_60559__
142 /* Long double is 128-bit type. */
144 typedef union
146 long double value;
147 struct
149 #if __FLOAT_WORD_ORDER == __BIG_ENDIAN
150 uint64_t msw;
151 uint64_t lsw;
152 #elif __FLOAT_WORD_ORDER == __LITTLE_ENDIAN
153 uint64_t lsw;
154 uint64_t msw;
155 #endif
156 } parts64;
157 } ieee854_long_double_shape_type;
159 static inline int
160 __issignalingl (long double x)
162 uint64_t hxi, lxi;
163 ieee854_long_double_shape_type u;
165 u.value = x;
166 hxi = u.parts64.msw;
167 lxi = u.parts64.lsw;
169 hxi ^= UINT64_C (0x0000800000000000);
170 hxi |= (lxi | -lxi) >> 63;
171 return (hxi & UINT64_C (0x7fffffffffffffff)) > UINT64_C (0x7fff800000000000);
174 #else
176 static inline int
177 __issignalingl (long double x)
179 return 0;
182 #endif
185 #if __FLT128_IS_IEC_60559__
187 /* We have a _Float128 type. */
189 typedef union
191 __float128 value;
192 struct
194 #if __FLOAT_WORD_ORDER == __BIG_ENDIAN
195 uint64_t msw;
196 uint64_t lsw;
197 #elif __FLOAT_WORD_ORDER == __LITTLE_ENDIAN
198 uint64_t lsw;
199 uint64_t msw;
200 #endif
201 } parts64;
202 } ieee854_float128_shape_type;
204 static inline int
205 __issignalingf128 (__float128 x)
207 uint64_t hxi, lxi;
208 ieee854_float128_shape_type u;
210 u.value = x;
211 hxi = u.parts64.msw;
212 lxi = u.parts64.lsw;
214 hxi ^= UINT64_C (0x0000800000000000);
215 hxi |= (lxi | -lxi) >> 63;
216 return (hxi & UINT64_C (0x7fffffffffffffff)) > UINT64_C (0x7fff800000000000);
219 #endif
222 /* Define the type-generic macro based on the functions above. */
224 #if __FLT128_IS_IEC_60559__
225 # define issignaling(X) \
226 _Generic ((X), \
227 __float128: __issignalingf128, \
228 float: __issignalingf, \
229 double: __issignaling, \
230 long double: __issignalingl)(X)
231 #else
232 # define issignaling(X) \
233 _Generic ((X), \
234 float: __issignalingf, \
235 double: __issignaling, \
236 long double: __issignalingl)(X)
237 #endif