]> git.ipfire.org Git - thirdparty/glibc.git/blame - soft-fp/op-common.h
soft-fp: Fix _FP_TO_INT latent bug in overflow handling.
[thirdparty/glibc.git] / soft-fp / op-common.h
CommitLineData
d876f532 1/* Software floating-point emulation. Common operations.
d4697bc9 2 Copyright (C) 1997-2014 Free Software Foundation, Inc.
d876f532
UD
3 This file is part of the GNU C Library.
4 Contributed by Richard Henderson (rth@cygnus.com),
5 Jakub Jelinek (jj@ultra.linux.cz),
6 David S. Miller (davem@redhat.com) and
7 Peter Maydell (pmaydell@chiark.greenend.org.uk).
8
9 The GNU C Library is free software; you can redistribute it and/or
41bdb6e2
AJ
10 modify it under the terms of the GNU Lesser General Public
11 License as published by the Free Software Foundation; either
12 version 2.1 of the License, or (at your option) any later version.
d876f532 13
638a783c
RM
14 In addition to the permissions in the GNU Lesser General Public
15 License, the Free Software Foundation gives you unlimited
16 permission to link the compiled version of this file into
17 combinations with other programs, and to distribute those
18 combinations without any restriction coming from the use of this
19 file. (The Lesser General Public License restrictions do apply in
20 other respects; for example, they cover modification of the file,
21 and distribution when not linked into a combine executable.)
22
d876f532
UD
23 The GNU C Library is distributed in the hope that it will be useful,
24 but WITHOUT ANY WARRANTY; without even the implied warranty of
25 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
41bdb6e2 26 Lesser General Public License for more details.
d876f532 27
41bdb6e2 28 You should have received a copy of the GNU Lesser General Public
59ba27a6
PE
29 License along with the GNU C Library; if not, see
30 <http://www.gnu.org/licenses/>. */
d876f532 31
a0d7066a 32#define _FP_DECL(wc, X) \
51ca9e29
JM
33 _FP_I_TYPE X##_c __attribute__ ((unused)); \
34 _FP_I_TYPE X##_s __attribute__ ((unused)); \
ace614b8 35 _FP_I_TYPE X##_e __attribute__ ((unused)); \
51ca9e29 36 _FP_FRAC_DECL_##wc (X)
d876f532 37
2848b105 38/* Test whether the qNaN bit denotes a signaling NaN. */
51ca9e29
JM
39#define _FP_FRAC_SNANP(fs, X) \
40 ((_FP_QNANNEGATEDP) \
41 ? (_FP_FRAC_HIGH_RAW_##fs (X) & _FP_QNANBIT_##fs) \
42 : !(_FP_FRAC_HIGH_RAW_##fs (X) & _FP_QNANBIT_##fs))
43#define _FP_FRAC_SNANP_SEMIRAW(fs, X) \
44 ((_FP_QNANNEGATEDP) \
45 ? (_FP_FRAC_HIGH_##fs (X) & _FP_QNANBIT_SH_##fs) \
46 : !(_FP_FRAC_HIGH_##fs (X) & _FP_QNANBIT_SH_##fs))
2848b105 47
c4fe3ea7
JM
48/* Finish truly unpacking a native fp value by classifying the kind
49 of fp value and normalizing both the exponent and the fraction. */
d876f532 50
1e145589
JM
51#define _FP_UNPACK_CANONICAL(fs, wc, X) \
52 do \
53 { \
54 switch (X##_e) \
55 { \
56 default: \
51ca9e29
JM
57 _FP_FRAC_HIGH_RAW_##fs (X) |= _FP_IMPLBIT_##fs; \
58 _FP_FRAC_SLL_##wc (X, _FP_WORKBITS); \
1e145589
JM
59 X##_e -= _FP_EXPBIAS_##fs; \
60 X##_c = FP_CLS_NORMAL; \
61 break; \
62 \
63 case 0: \
51ca9e29 64 if (_FP_FRAC_ZEROP_##wc (X)) \
1e145589
JM
65 X##_c = FP_CLS_ZERO; \
66 else \
67 { \
c4fe3ea7 68 /* A denormalized number. */ \
9c37ec0b
JM
69 _FP_I_TYPE _FP_UNPACK_CANONICAL_shift; \
70 _FP_FRAC_CLZ_##wc (_FP_UNPACK_CANONICAL_shift, \
71 X); \
72 _FP_UNPACK_CANONICAL_shift -= _FP_FRACXBITS_##fs; \
73 _FP_FRAC_SLL_##wc (X, (_FP_UNPACK_CANONICAL_shift \
74 + _FP_WORKBITS)); \
75 X##_e -= (_FP_EXPBIAS_##fs - 1 \
76 + _FP_UNPACK_CANONICAL_shift); \
1e145589 77 X##_c = FP_CLS_NORMAL; \
51ca9e29 78 FP_SET_EXCEPTION (FP_EX_DENORM); \
1e145589
JM
79 } \
80 break; \
81 \
82 case _FP_EXPMAX_##fs: \
51ca9e29 83 if (_FP_FRAC_ZEROP_##wc (X)) \
1e145589
JM
84 X##_c = FP_CLS_INF; \
85 else \
86 { \
87 X##_c = FP_CLS_NAN; \
c4fe3ea7 88 /* Check for signaling NaN. */ \
51ca9e29
JM
89 if (_FP_FRAC_SNANP (fs, X)) \
90 FP_SET_EXCEPTION (FP_EX_INVALID); \
1e145589
JM
91 } \
92 break; \
93 } \
94 } \
95 while (0)
d876f532 96
fe0b1e85
RM
97/* Finish unpacking an fp value in semi-raw mode: the mantissa is
98 shifted by _FP_WORKBITS but the implicit MSB is not inserted and
99 other classification is not done. */
51ca9e29 100#define _FP_UNPACK_SEMIRAW(fs, wc, X) _FP_FRAC_SLL_##wc (X, _FP_WORKBITS)
fe0b1e85
RM
101
102/* A semi-raw value has overflowed to infinity. Adjust the mantissa
103 and exponent appropriately. */
104#define _FP_OVERFLOW_SEMIRAW(fs, wc, X) \
1e145589 105 do \
fe0b1e85 106 { \
1e145589
JM
107 if (FP_ROUNDMODE == FP_RND_NEAREST \
108 || (FP_ROUNDMODE == FP_RND_PINF && !X##_s) \
109 || (FP_ROUNDMODE == FP_RND_MINF && X##_s)) \
110 { \
111 X##_e = _FP_EXPMAX_##fs; \
51ca9e29 112 _FP_FRAC_SET_##wc (X, _FP_ZEROFRAC_##wc); \
1e145589
JM
113 } \
114 else \
115 { \
116 X##_e = _FP_EXPMAX_##fs - 1; \
51ca9e29 117 _FP_FRAC_SET_##wc (X, _FP_MAXFRAC_##wc); \
1e145589 118 } \
51ca9e29
JM
119 FP_SET_EXCEPTION (FP_EX_INEXACT); \
120 FP_SET_EXCEPTION (FP_EX_OVERFLOW); \
fe0b1e85 121 } \
1e145589 122 while (0)
fe0b1e85
RM
123
124/* Check for a semi-raw value being a signaling NaN and raise the
125 invalid exception if so. */
1e145589
JM
126#define _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, X) \
127 do \
128 { \
129 if (X##_e == _FP_EXPMAX_##fs \
51ca9e29
JM
130 && !_FP_FRAC_ZEROP_##wc (X) \
131 && _FP_FRAC_SNANP_SEMIRAW (fs, X)) \
132 FP_SET_EXCEPTION (FP_EX_INVALID); \
1e145589
JM
133 } \
134 while (0)
fe0b1e85
RM
135
136/* Choose a NaN result from an operation on two semi-raw NaN
137 values. */
138#define _FP_CHOOSENAN_SEMIRAW(fs, wc, R, X, Y, OP) \
1e145589
JM
139 do \
140 { \
141 /* _FP_CHOOSENAN expects raw values, so shift as required. */ \
51ca9e29
JM
142 _FP_FRAC_SRL_##wc (X, _FP_WORKBITS); \
143 _FP_FRAC_SRL_##wc (Y, _FP_WORKBITS); \
144 _FP_CHOOSENAN (fs, wc, R, X, Y, OP); \
145 _FP_FRAC_SLL_##wc (R, _FP_WORKBITS); \
1e145589
JM
146 } \
147 while (0)
fe0b1e85 148
2848b105
MR
149/* Make the fractional part a quiet NaN, preserving the payload
150 if possible, otherwise make it the canonical quiet NaN and set
151 the sign bit accordingly. */
1e145589
JM
152#define _FP_SETQNAN(fs, wc, X) \
153 do \
154 { \
155 if (_FP_QNANNEGATEDP) \
156 { \
51ca9e29
JM
157 _FP_FRAC_HIGH_RAW_##fs (X) &= _FP_QNANBIT_##fs - 1; \
158 if (_FP_FRAC_ZEROP_##wc (X)) \
1e145589
JM
159 { \
160 X##_s = _FP_NANSIGN_##fs; \
51ca9e29 161 _FP_FRAC_SET_##wc (X, _FP_NANFRAC_##fs); \
1e145589
JM
162 } \
163 } \
164 else \
51ca9e29 165 _FP_FRAC_HIGH_RAW_##fs (X) |= _FP_QNANBIT_##fs; \
1e145589
JM
166 } \
167 while (0)
168#define _FP_SETQNAN_SEMIRAW(fs, wc, X) \
169 do \
170 { \
171 if (_FP_QNANNEGATEDP) \
172 { \
51ca9e29
JM
173 _FP_FRAC_HIGH_##fs (X) &= _FP_QNANBIT_SH_##fs - 1; \
174 if (_FP_FRAC_ZEROP_##wc (X)) \
1e145589
JM
175 { \
176 X##_s = _FP_NANSIGN_##fs; \
51ca9e29
JM
177 _FP_FRAC_SET_##wc (X, _FP_NANFRAC_##fs); \
178 _FP_FRAC_SLL_##wc (X, _FP_WORKBITS); \
1e145589
JM
179 } \
180 } \
181 else \
51ca9e29 182 _FP_FRAC_HIGH_##fs (X) |= _FP_QNANBIT_SH_##fs; \
1e145589
JM
183 } \
184 while (0)
2848b105 185
fe0b1e85
RM
186/* Test whether a biased exponent is normal (not zero or maximum). */
187#define _FP_EXP_NORMAL(fs, wc, X) (((X##_e + 1) & _FP_EXPMAX_##fs) > 1)
188
189/* Prepare to pack an fp value in semi-raw mode: the mantissa is
190 rounded and shifted right, with the rounding possibly increasing
191 the exponent (including changing a finite value to infinity). */
192#define _FP_PACK_SEMIRAW(fs, wc, X) \
1e145589
JM
193 do \
194 { \
ace614b8
JM
195 int _FP_PACK_SEMIRAW_is_tiny \
196 = X##_e == 0 && !_FP_FRAC_ZEROP_##wc (X); \
197 if (_FP_TININESS_AFTER_ROUNDING \
198 && _FP_PACK_SEMIRAW_is_tiny) \
199 { \
200 FP_DECL_##fs (_FP_PACK_SEMIRAW_T); \
201 _FP_FRAC_COPY_##wc (_FP_PACK_SEMIRAW_T, X); \
202 _FP_PACK_SEMIRAW_T##_s = X##_s; \
203 _FP_PACK_SEMIRAW_T##_e = X##_e; \
204 _FP_FRAC_SLL_##wc (_FP_PACK_SEMIRAW_T, 1); \
205 _FP_ROUND (wc, _FP_PACK_SEMIRAW_T); \
206 if (_FP_FRAC_OVERP_##wc (fs, _FP_PACK_SEMIRAW_T)) \
207 _FP_PACK_SEMIRAW_is_tiny = 0; \
208 } \
51ca9e29 209 _FP_ROUND (wc, X); \
ace614b8 210 if (_FP_PACK_SEMIRAW_is_tiny) \
1e145589 211 { \
47594329
MS
212 if ((FP_CUR_EXCEPTIONS & FP_EX_INEXACT) \
213 || (FP_TRAPPING_EXCEPTIONS & FP_EX_UNDERFLOW)) \
51ca9e29 214 FP_SET_EXCEPTION (FP_EX_UNDERFLOW); \
1e145589 215 } \
51ca9e29 216 if (_FP_FRAC_HIGH_##fs (X) \
1e145589 217 & (_FP_OVERFLOW_##fs >> 1)) \
ae251b0b 218 { \
51ca9e29 219 _FP_FRAC_HIGH_##fs (X) &= ~(_FP_OVERFLOW_##fs >> 1); \
1e145589
JM
220 X##_e++; \
221 if (X##_e == _FP_EXPMAX_##fs) \
51ca9e29 222 _FP_OVERFLOW_SEMIRAW (fs, wc, X); \
1e145589 223 } \
51ca9e29
JM
224 _FP_FRAC_SRL_##wc (X, _FP_WORKBITS); \
225 if (X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc (X)) \
1e145589
JM
226 { \
227 if (!_FP_KEEPNANFRACP) \
228 { \
51ca9e29 229 _FP_FRAC_SET_##wc (X, _FP_NANFRAC_##fs); \
1e145589
JM
230 X##_s = _FP_NANSIGN_##fs; \
231 } \
232 else \
51ca9e29 233 _FP_SETQNAN (fs, wc, X); \
ae251b0b 234 } \
fe0b1e85 235 } \
1e145589 236 while (0)
fe0b1e85 237
c4fe3ea7
JM
238/* Before packing the bits back into the native fp result, take care
239 of such mundane things as rounding and overflow. Also, for some
240 kinds of fp values, the original parts may not have been fully
241 extracted -- but that is ok, we can regenerate them now. */
d876f532 242
1e145589
JM
243#define _FP_PACK_CANONICAL(fs, wc, X) \
244 do \
245 { \
246 switch (X##_c) \
247 { \
248 case FP_CLS_NORMAL: \
249 X##_e += _FP_EXPBIAS_##fs; \
250 if (X##_e > 0) \
251 { \
51ca9e29
JM
252 _FP_ROUND (wc, X); \
253 if (_FP_FRAC_OVERP_##wc (fs, X)) \
1e145589 254 { \
51ca9e29 255 _FP_FRAC_CLEAR_OVERP_##wc (fs, X); \
1e145589
JM
256 X##_e++; \
257 } \
51ca9e29 258 _FP_FRAC_SRL_##wc (X, _FP_WORKBITS); \
1e145589
JM
259 if (X##_e >= _FP_EXPMAX_##fs) \
260 { \
c4fe3ea7 261 /* Overflow. */ \
1e145589
JM
262 switch (FP_ROUNDMODE) \
263 { \
264 case FP_RND_NEAREST: \
265 X##_c = FP_CLS_INF; \
266 break; \
267 case FP_RND_PINF: \
268 if (!X##_s) \
269 X##_c = FP_CLS_INF; \
270 break; \
271 case FP_RND_MINF: \
272 if (X##_s) \
273 X##_c = FP_CLS_INF; \
274 break; \
275 } \
276 if (X##_c == FP_CLS_INF) \
277 { \
c4fe3ea7 278 /* Overflow to infinity. */ \
1e145589 279 X##_e = _FP_EXPMAX_##fs; \
51ca9e29 280 _FP_FRAC_SET_##wc (X, _FP_ZEROFRAC_##wc); \
1e145589
JM
281 } \
282 else \
283 { \
c4fe3ea7 284 /* Overflow to maximum normal. */ \
1e145589 285 X##_e = _FP_EXPMAX_##fs - 1; \
51ca9e29 286 _FP_FRAC_SET_##wc (X, _FP_MAXFRAC_##wc); \
1e145589 287 } \
51ca9e29
JM
288 FP_SET_EXCEPTION (FP_EX_OVERFLOW); \
289 FP_SET_EXCEPTION (FP_EX_INEXACT); \
1e145589
JM
290 } \
291 } \
292 else \
293 { \
c4fe3ea7 294 /* We've got a denormalized number. */ \
ace614b8
JM
295 int _FP_PACK_CANONICAL_is_tiny = 1; \
296 if (_FP_TININESS_AFTER_ROUNDING && X##_e == 0) \
297 { \
298 FP_DECL_##fs (_FP_PACK_CANONICAL_T); \
299 _FP_FRAC_COPY_##wc (_FP_PACK_CANONICAL_T, X); \
300 _FP_PACK_CANONICAL_T##_s = X##_s; \
301 _FP_PACK_CANONICAL_T##_e = X##_e; \
302 _FP_ROUND (wc, _FP_PACK_CANONICAL_T); \
303 if (_FP_FRAC_OVERP_##wc (fs, _FP_PACK_CANONICAL_T)) \
304 _FP_PACK_CANONICAL_is_tiny = 0; \
305 } \
1e145589
JM
306 X##_e = -X##_e + 1; \
307 if (X##_e <= _FP_WFRACBITS_##fs) \
308 { \
51ca9e29
JM
309 _FP_FRAC_SRS_##wc (X, X##_e, _FP_WFRACBITS_##fs); \
310 _FP_ROUND (wc, X); \
311 if (_FP_FRAC_HIGH_##fs (X) \
1e145589
JM
312 & (_FP_OVERFLOW_##fs >> 1)) \
313 { \
314 X##_e = 1; \
51ca9e29
JM
315 _FP_FRAC_SET_##wc (X, _FP_ZEROFRAC_##wc); \
316 FP_SET_EXCEPTION (FP_EX_INEXACT); \
1e145589
JM
317 } \
318 else \
319 { \
320 X##_e = 0; \
51ca9e29 321 _FP_FRAC_SRL_##wc (X, _FP_WORKBITS); \
1e145589 322 } \
ace614b8
JM
323 if (_FP_PACK_CANONICAL_is_tiny \
324 && ((FP_CUR_EXCEPTIONS & FP_EX_INEXACT) \
325 || (FP_TRAPPING_EXCEPTIONS \
326 & FP_EX_UNDERFLOW))) \
51ca9e29 327 FP_SET_EXCEPTION (FP_EX_UNDERFLOW); \
1e145589
JM
328 } \
329 else \
330 { \
c4fe3ea7 331 /* Underflow to zero. */ \
1e145589 332 X##_e = 0; \
51ca9e29 333 if (!_FP_FRAC_ZEROP_##wc (X)) \
1e145589 334 { \
51ca9e29
JM
335 _FP_FRAC_SET_##wc (X, _FP_MINFRAC_##wc); \
336 _FP_ROUND (wc, X); \
337 _FP_FRAC_LOW_##wc (X) >>= (_FP_WORKBITS); \
1e145589 338 } \
51ca9e29 339 FP_SET_EXCEPTION (FP_EX_UNDERFLOW); \
1e145589
JM
340 } \
341 } \
342 break; \
343 \
344 case FP_CLS_ZERO: \
345 X##_e = 0; \
51ca9e29 346 _FP_FRAC_SET_##wc (X, _FP_ZEROFRAC_##wc); \
1e145589
JM
347 break; \
348 \
349 case FP_CLS_INF: \
350 X##_e = _FP_EXPMAX_##fs; \
51ca9e29 351 _FP_FRAC_SET_##wc (X, _FP_ZEROFRAC_##wc); \
1e145589
JM
352 break; \
353 \
354 case FP_CLS_NAN: \
355 X##_e = _FP_EXPMAX_##fs; \
356 if (!_FP_KEEPNANFRACP) \
357 { \
51ca9e29 358 _FP_FRAC_SET_##wc (X, _FP_NANFRAC_##fs); \
1e145589
JM
359 X##_s = _FP_NANSIGN_##fs; \
360 } \
361 else \
51ca9e29 362 _FP_SETQNAN (fs, wc, X); \
1e145589
JM
363 break; \
364 } \
365 } \
366 while (0)
d876f532
UD
367
368/* This one accepts raw argument and not cooked, returns
c4fe3ea7 369 1 if X is a signaling NaN. */
1e145589
JM
370#define _FP_ISSIGNAN(fs, wc, X) \
371 ({ \
9c37ec0b 372 int _FP_ISSIGNAN_ret = 0; \
1e145589
JM
373 if (X##_e == _FP_EXPMAX_##fs) \
374 { \
51ca9e29
JM
375 if (!_FP_FRAC_ZEROP_##wc (X) \
376 && _FP_FRAC_SNANP (fs, X)) \
9c37ec0b 377 _FP_ISSIGNAN_ret = 1; \
1e145589 378 } \
9c37ec0b 379 _FP_ISSIGNAN_ret; \
1e145589 380 })
d876f532
UD
381
382
383
384
385
fe0b1e85 386/* Addition on semi-raw values. */
1e145589
JM
387#define _FP_ADD_INTERNAL(fs, wc, R, X, Y, OP) \
388 do \
389 { \
390 if (X##_s == Y##_s) \
391 { \
392 /* Addition. */ \
393 R##_s = X##_s; \
9c37ec0b
JM
394 int _FP_ADD_INTERNAL_ediff = X##_e - Y##_e; \
395 if (_FP_ADD_INTERNAL_ediff > 0) \
1e145589
JM
396 { \
397 R##_e = X##_e; \
398 if (Y##_e == 0) \
399 { \
400 /* Y is zero or denormalized. */ \
51ca9e29 401 if (_FP_FRAC_ZEROP_##wc (Y)) \
1e145589 402 { \
51ca9e29
JM
403 _FP_CHECK_SIGNAN_SEMIRAW (fs, wc, X); \
404 _FP_FRAC_COPY_##wc (R, X); \
1e145589
JM
405 goto add_done; \
406 } \
407 else \
408 { \
51ca9e29 409 FP_SET_EXCEPTION (FP_EX_DENORM); \
9c37ec0b
JM
410 _FP_ADD_INTERNAL_ediff--; \
411 if (_FP_ADD_INTERNAL_ediff == 0) \
1e145589 412 { \
51ca9e29 413 _FP_FRAC_ADD_##wc (R, X, Y); \
1e145589
JM
414 goto add3; \
415 } \
416 if (X##_e == _FP_EXPMAX_##fs) \
417 { \
51ca9e29
JM
418 _FP_CHECK_SIGNAN_SEMIRAW (fs, wc, X); \
419 _FP_FRAC_COPY_##wc (R, X); \
1e145589
JM
420 goto add_done; \
421 } \
422 goto add1; \
423 } \
424 } \
425 else if (X##_e == _FP_EXPMAX_##fs) \
426 { \
427 /* X is NaN or Inf, Y is normal. */ \
51ca9e29
JM
428 _FP_CHECK_SIGNAN_SEMIRAW (fs, wc, X); \
429 _FP_FRAC_COPY_##wc (R, X); \
1e145589
JM
430 goto add_done; \
431 } \
432 \
433 /* Insert implicit MSB of Y. */ \
51ca9e29 434 _FP_FRAC_HIGH_##fs (Y) |= _FP_IMPLBIT_SH_##fs; \
1e145589
JM
435 \
436 add1: \
9c37ec0b
JM
437 /* Shift the mantissa of Y to the right \
438 _FP_ADD_INTERNAL_EDIFF steps; remember to account \
439 later for the implicit MSB of X. */ \
440 if (_FP_ADD_INTERNAL_ediff <= _FP_WFRACBITS_##fs) \
441 _FP_FRAC_SRS_##wc (Y, _FP_ADD_INTERNAL_ediff, \
442 _FP_WFRACBITS_##fs); \
51ca9e29
JM
443 else if (!_FP_FRAC_ZEROP_##wc (Y)) \
444 _FP_FRAC_SET_##wc (Y, _FP_MINFRAC_##wc); \
445 _FP_FRAC_ADD_##wc (R, X, Y); \
1e145589 446 } \
9c37ec0b 447 else if (_FP_ADD_INTERNAL_ediff < 0) \
1e145589 448 { \
9c37ec0b 449 _FP_ADD_INTERNAL_ediff = -_FP_ADD_INTERNAL_ediff; \
1e145589
JM
450 R##_e = Y##_e; \
451 if (X##_e == 0) \
452 { \
453 /* X is zero or denormalized. */ \
51ca9e29 454 if (_FP_FRAC_ZEROP_##wc (X)) \
1e145589 455 { \
51ca9e29
JM
456 _FP_CHECK_SIGNAN_SEMIRAW (fs, wc, Y); \
457 _FP_FRAC_COPY_##wc (R, Y); \
1e145589
JM
458 goto add_done; \
459 } \
460 else \
461 { \
51ca9e29 462 FP_SET_EXCEPTION (FP_EX_DENORM); \
9c37ec0b
JM
463 _FP_ADD_INTERNAL_ediff--; \
464 if (_FP_ADD_INTERNAL_ediff == 0) \
1e145589 465 { \
51ca9e29 466 _FP_FRAC_ADD_##wc (R, Y, X); \
1e145589
JM
467 goto add3; \
468 } \
469 if (Y##_e == _FP_EXPMAX_##fs) \
470 { \
51ca9e29
JM
471 _FP_CHECK_SIGNAN_SEMIRAW (fs, wc, Y); \
472 _FP_FRAC_COPY_##wc (R, Y); \
1e145589
JM
473 goto add_done; \
474 } \
475 goto add2; \
476 } \
477 } \
478 else if (Y##_e == _FP_EXPMAX_##fs) \
479 { \
480 /* Y is NaN or Inf, X is normal. */ \
51ca9e29
JM
481 _FP_CHECK_SIGNAN_SEMIRAW (fs, wc, Y); \
482 _FP_FRAC_COPY_##wc (R, Y); \
1e145589
JM
483 goto add_done; \
484 } \
485 \
486 /* Insert implicit MSB of X. */ \
51ca9e29 487 _FP_FRAC_HIGH_##fs (X) |= _FP_IMPLBIT_SH_##fs; \
1e145589
JM
488 \
489 add2: \
9c37ec0b
JM
490 /* Shift the mantissa of X to the right \
491 _FP_ADD_INTERNAL_EDIFF steps; remember to account \
492 later for the implicit MSB of Y. */ \
493 if (_FP_ADD_INTERNAL_ediff <= _FP_WFRACBITS_##fs) \
494 _FP_FRAC_SRS_##wc (X, _FP_ADD_INTERNAL_ediff, \
495 _FP_WFRACBITS_##fs); \
51ca9e29
JM
496 else if (!_FP_FRAC_ZEROP_##wc (X)) \
497 _FP_FRAC_SET_##wc (X, _FP_MINFRAC_##wc); \
498 _FP_FRAC_ADD_##wc (R, Y, X); \
1e145589
JM
499 } \
500 else \
501 { \
9c37ec0b 502 /* _FP_ADD_INTERNAL_ediff == 0. */ \
51ca9e29 503 if (!_FP_EXP_NORMAL (fs, wc, X)) \
1e145589
JM
504 { \
505 if (X##_e == 0) \
506 { \
507 /* X and Y are zero or denormalized. */ \
508 R##_e = 0; \
51ca9e29 509 if (_FP_FRAC_ZEROP_##wc (X)) \
1e145589 510 { \
51ca9e29
JM
511 if (!_FP_FRAC_ZEROP_##wc (Y)) \
512 FP_SET_EXCEPTION (FP_EX_DENORM); \
513 _FP_FRAC_COPY_##wc (R, Y); \
1e145589
JM
514 goto add_done; \
515 } \
51ca9e29 516 else if (_FP_FRAC_ZEROP_##wc (Y)) \
1e145589 517 { \
51ca9e29
JM
518 FP_SET_EXCEPTION (FP_EX_DENORM); \
519 _FP_FRAC_COPY_##wc (R, X); \
1e145589
JM
520 goto add_done; \
521 } \
522 else \
523 { \
51ca9e29
JM
524 FP_SET_EXCEPTION (FP_EX_DENORM); \
525 _FP_FRAC_ADD_##wc (R, X, Y); \
526 if (_FP_FRAC_HIGH_##fs (R) & _FP_IMPLBIT_SH_##fs) \
1e145589
JM
527 { \
528 /* Normalized result. */ \
51ca9e29
JM
529 _FP_FRAC_HIGH_##fs (R) \
530 &= ~(_FP_W_TYPE) _FP_IMPLBIT_SH_##fs; \
1e145589
JM
531 R##_e = 1; \
532 } \
533 goto add_done; \
534 } \
535 } \
536 else \
537 { \
538 /* X and Y are NaN or Inf. */ \
51ca9e29
JM
539 _FP_CHECK_SIGNAN_SEMIRAW (fs, wc, X); \
540 _FP_CHECK_SIGNAN_SEMIRAW (fs, wc, Y); \
1e145589 541 R##_e = _FP_EXPMAX_##fs; \
51ca9e29
JM
542 if (_FP_FRAC_ZEROP_##wc (X)) \
543 _FP_FRAC_COPY_##wc (R, Y); \
544 else if (_FP_FRAC_ZEROP_##wc (Y)) \
545 _FP_FRAC_COPY_##wc (R, X); \
1e145589 546 else \
51ca9e29 547 _FP_CHOOSENAN_SEMIRAW (fs, wc, R, X, Y, OP); \
1e145589
JM
548 goto add_done; \
549 } \
550 } \
551 /* The exponents of X and Y, both normal, are equal. The \
552 implicit MSBs will always add to increase the \
553 exponent. */ \
51ca9e29 554 _FP_FRAC_ADD_##wc (R, X, Y); \
1e145589 555 R##_e = X##_e + 1; \
51ca9e29 556 _FP_FRAC_SRS_##wc (R, 1, _FP_WFRACBITS_##fs); \
1e145589
JM
557 if (R##_e == _FP_EXPMAX_##fs) \
558 /* Overflow to infinity (depending on rounding mode). */ \
51ca9e29 559 _FP_OVERFLOW_SEMIRAW (fs, wc, R); \
1e145589
JM
560 goto add_done; \
561 } \
562 add3: \
51ca9e29 563 if (_FP_FRAC_HIGH_##fs (R) & _FP_IMPLBIT_SH_##fs) \
1e145589
JM
564 { \
565 /* Overflow. */ \
51ca9e29 566 _FP_FRAC_HIGH_##fs (R) &= ~(_FP_W_TYPE) _FP_IMPLBIT_SH_##fs; \
1e145589 567 R##_e++; \
51ca9e29 568 _FP_FRAC_SRS_##wc (R, 1, _FP_WFRACBITS_##fs); \
1e145589
JM
569 if (R##_e == _FP_EXPMAX_##fs) \
570 /* Overflow to infinity (depending on rounding mode). */ \
51ca9e29 571 _FP_OVERFLOW_SEMIRAW (fs, wc, R); \
1e145589
JM
572 } \
573 add_done: ; \
574 } \
575 else \
576 { \
577 /* Subtraction. */ \
9c37ec0b
JM
578 int _FP_ADD_INTERNAL_ediff = X##_e - Y##_e; \
579 if (_FP_ADD_INTERNAL_ediff > 0) \
1e145589
JM
580 { \
581 R##_e = X##_e; \
582 R##_s = X##_s; \
583 if (Y##_e == 0) \
584 { \
585 /* Y is zero or denormalized. */ \
51ca9e29 586 if (_FP_FRAC_ZEROP_##wc (Y)) \
1e145589 587 { \
51ca9e29
JM
588 _FP_CHECK_SIGNAN_SEMIRAW (fs, wc, X); \
589 _FP_FRAC_COPY_##wc (R, X); \
1e145589
JM
590 goto sub_done; \
591 } \
592 else \
593 { \
51ca9e29 594 FP_SET_EXCEPTION (FP_EX_DENORM); \
9c37ec0b
JM
595 _FP_ADD_INTERNAL_ediff--; \
596 if (_FP_ADD_INTERNAL_ediff == 0) \
1e145589 597 { \
51ca9e29 598 _FP_FRAC_SUB_##wc (R, X, Y); \
1e145589
JM
599 goto sub3; \
600 } \
601 if (X##_e == _FP_EXPMAX_##fs) \
602 { \
51ca9e29
JM
603 _FP_CHECK_SIGNAN_SEMIRAW (fs, wc, X); \
604 _FP_FRAC_COPY_##wc (R, X); \
1e145589
JM
605 goto sub_done; \
606 } \
607 goto sub1; \
608 } \
609 } \
610 else if (X##_e == _FP_EXPMAX_##fs) \
611 { \
612 /* X is NaN or Inf, Y is normal. */ \
51ca9e29
JM
613 _FP_CHECK_SIGNAN_SEMIRAW (fs, wc, X); \
614 _FP_FRAC_COPY_##wc (R, X); \
1e145589
JM
615 goto sub_done; \
616 } \
617 \
618 /* Insert implicit MSB of Y. */ \
51ca9e29 619 _FP_FRAC_HIGH_##fs (Y) |= _FP_IMPLBIT_SH_##fs; \
1e145589
JM
620 \
621 sub1: \
9c37ec0b
JM
622 /* Shift the mantissa of Y to the right \
623 _FP_ADD_INTERNAL_EDIFF steps; remember to account \
624 later for the implicit MSB of X. */ \
625 if (_FP_ADD_INTERNAL_ediff <= _FP_WFRACBITS_##fs) \
626 _FP_FRAC_SRS_##wc (Y, _FP_ADD_INTERNAL_ediff, \
627 _FP_WFRACBITS_##fs); \
51ca9e29
JM
628 else if (!_FP_FRAC_ZEROP_##wc (Y)) \
629 _FP_FRAC_SET_##wc (Y, _FP_MINFRAC_##wc); \
630 _FP_FRAC_SUB_##wc (R, X, Y); \
1e145589 631 } \
9c37ec0b 632 else if (_FP_ADD_INTERNAL_ediff < 0) \
1e145589 633 { \
9c37ec0b 634 _FP_ADD_INTERNAL_ediff = -_FP_ADD_INTERNAL_ediff; \
1e145589
JM
635 R##_e = Y##_e; \
636 R##_s = Y##_s; \
637 if (X##_e == 0) \
638 { \
639 /* X is zero or denormalized. */ \
51ca9e29 640 if (_FP_FRAC_ZEROP_##wc (X)) \
1e145589 641 { \
51ca9e29
JM
642 _FP_CHECK_SIGNAN_SEMIRAW (fs, wc, Y); \
643 _FP_FRAC_COPY_##wc (R, Y); \
1e145589
JM
644 goto sub_done; \
645 } \
646 else \
647 { \
51ca9e29 648 FP_SET_EXCEPTION (FP_EX_DENORM); \
9c37ec0b
JM
649 _FP_ADD_INTERNAL_ediff--; \
650 if (_FP_ADD_INTERNAL_ediff == 0) \
1e145589 651 { \
51ca9e29 652 _FP_FRAC_SUB_##wc (R, Y, X); \
1e145589
JM
653 goto sub3; \
654 } \
655 if (Y##_e == _FP_EXPMAX_##fs) \
656 { \
51ca9e29
JM
657 _FP_CHECK_SIGNAN_SEMIRAW (fs, wc, Y); \
658 _FP_FRAC_COPY_##wc (R, Y); \
1e145589
JM
659 goto sub_done; \
660 } \
661 goto sub2; \
662 } \
663 } \
664 else if (Y##_e == _FP_EXPMAX_##fs) \
665 { \
666 /* Y is NaN or Inf, X is normal. */ \
51ca9e29
JM
667 _FP_CHECK_SIGNAN_SEMIRAW (fs, wc, Y); \
668 _FP_FRAC_COPY_##wc (R, Y); \
1e145589
JM
669 goto sub_done; \
670 } \
671 \
672 /* Insert implicit MSB of X. */ \
51ca9e29 673 _FP_FRAC_HIGH_##fs (X) |= _FP_IMPLBIT_SH_##fs; \
1e145589
JM
674 \
675 sub2: \
9c37ec0b
JM
676 /* Shift the mantissa of X to the right \
677 _FP_ADD_INTERNAL_EDIFF steps; remember to account \
678 later for the implicit MSB of Y. */ \
679 if (_FP_ADD_INTERNAL_ediff <= _FP_WFRACBITS_##fs) \
680 _FP_FRAC_SRS_##wc (X, _FP_ADD_INTERNAL_ediff, \
681 _FP_WFRACBITS_##fs); \
51ca9e29
JM
682 else if (!_FP_FRAC_ZEROP_##wc (X)) \
683 _FP_FRAC_SET_##wc (X, _FP_MINFRAC_##wc); \
684 _FP_FRAC_SUB_##wc (R, Y, X); \
1e145589
JM
685 } \
686 else \
687 { \
688 /* ediff == 0. */ \
51ca9e29 689 if (!_FP_EXP_NORMAL (fs, wc, X)) \
1e145589
JM
690 { \
691 if (X##_e == 0) \
692 { \
693 /* X and Y are zero or denormalized. */ \
694 R##_e = 0; \
51ca9e29 695 if (_FP_FRAC_ZEROP_##wc (X)) \
1e145589 696 { \
51ca9e29
JM
697 _FP_FRAC_COPY_##wc (R, Y); \
698 if (_FP_FRAC_ZEROP_##wc (Y)) \
1e145589
JM
699 R##_s = (FP_ROUNDMODE == FP_RND_MINF); \
700 else \
701 { \
51ca9e29 702 FP_SET_EXCEPTION (FP_EX_DENORM); \
1e145589
JM
703 R##_s = Y##_s; \
704 } \
705 goto sub_done; \
706 } \
51ca9e29 707 else if (_FP_FRAC_ZEROP_##wc (Y)) \
1e145589 708 { \
51ca9e29
JM
709 FP_SET_EXCEPTION (FP_EX_DENORM); \
710 _FP_FRAC_COPY_##wc (R, X); \
1e145589
JM
711 R##_s = X##_s; \
712 goto sub_done; \
713 } \
714 else \
715 { \
51ca9e29
JM
716 FP_SET_EXCEPTION (FP_EX_DENORM); \
717 _FP_FRAC_SUB_##wc (R, X, Y); \
1e145589 718 R##_s = X##_s; \
51ca9e29 719 if (_FP_FRAC_HIGH_##fs (R) & _FP_IMPLBIT_SH_##fs) \
1e145589
JM
720 { \
721 /* |X| < |Y|, negate result. */ \
51ca9e29 722 _FP_FRAC_SUB_##wc (R, Y, X); \
1e145589
JM
723 R##_s = Y##_s; \
724 } \
51ca9e29 725 else if (_FP_FRAC_ZEROP_##wc (R)) \
1e145589
JM
726 R##_s = (FP_ROUNDMODE == FP_RND_MINF); \
727 goto sub_done; \
728 } \
729 } \
730 else \
731 { \
732 /* X and Y are NaN or Inf, of opposite signs. */ \
51ca9e29
JM
733 _FP_CHECK_SIGNAN_SEMIRAW (fs, wc, X); \
734 _FP_CHECK_SIGNAN_SEMIRAW (fs, wc, Y); \
1e145589 735 R##_e = _FP_EXPMAX_##fs; \
51ca9e29 736 if (_FP_FRAC_ZEROP_##wc (X)) \
1e145589 737 { \
51ca9e29 738 if (_FP_FRAC_ZEROP_##wc (Y)) \
1e145589
JM
739 { \
740 /* Inf - Inf. */ \
741 R##_s = _FP_NANSIGN_##fs; \
51ca9e29
JM
742 _FP_FRAC_SET_##wc (R, _FP_NANFRAC_##fs); \
743 _FP_FRAC_SLL_##wc (R, _FP_WORKBITS); \
744 FP_SET_EXCEPTION (FP_EX_INVALID); \
1e145589
JM
745 } \
746 else \
747 { \
748 /* Inf - NaN. */ \
749 R##_s = Y##_s; \
51ca9e29 750 _FP_FRAC_COPY_##wc (R, Y); \
1e145589
JM
751 } \
752 } \
753 else \
754 { \
51ca9e29 755 if (_FP_FRAC_ZEROP_##wc (Y)) \
1e145589
JM
756 { \
757 /* NaN - Inf. */ \
758 R##_s = X##_s; \
51ca9e29 759 _FP_FRAC_COPY_##wc (R, X); \
1e145589
JM
760 } \
761 else \
762 { \
763 /* NaN - NaN. */ \
51ca9e29 764 _FP_CHOOSENAN_SEMIRAW (fs, wc, R, X, Y, OP); \
1e145589
JM
765 } \
766 } \
767 goto sub_done; \
768 } \
769 } \
770 /* The exponents of X and Y, both normal, are equal. The \
771 implicit MSBs cancel. */ \
772 R##_e = X##_e; \
51ca9e29 773 _FP_FRAC_SUB_##wc (R, X, Y); \
1e145589 774 R##_s = X##_s; \
51ca9e29 775 if (_FP_FRAC_HIGH_##fs (R) & _FP_IMPLBIT_SH_##fs) \
1e145589
JM
776 { \
777 /* |X| < |Y|, negate result. */ \
51ca9e29 778 _FP_FRAC_SUB_##wc (R, Y, X); \
1e145589
JM
779 R##_s = Y##_s; \
780 } \
51ca9e29 781 else if (_FP_FRAC_ZEROP_##wc (R)) \
1e145589
JM
782 { \
783 R##_e = 0; \
784 R##_s = (FP_ROUNDMODE == FP_RND_MINF); \
785 goto sub_done; \
786 } \
787 goto norm; \
788 } \
789 sub3: \
51ca9e29 790 if (_FP_FRAC_HIGH_##fs (R) & _FP_IMPLBIT_SH_##fs) \
1e145589 791 { \
9c37ec0b 792 int _FP_ADD_INTERNAL_diff; \
1e145589
JM
793 /* Carry into most significant bit of larger one of X and Y, \
794 canceling it; renormalize. */ \
51ca9e29 795 _FP_FRAC_HIGH_##fs (R) &= _FP_IMPLBIT_SH_##fs - 1; \
1e145589 796 norm: \
9c37ec0b
JM
797 _FP_FRAC_CLZ_##wc (_FP_ADD_INTERNAL_diff, R); \
798 _FP_ADD_INTERNAL_diff -= _FP_WFRACXBITS_##fs; \
799 _FP_FRAC_SLL_##wc (R, _FP_ADD_INTERNAL_diff); \
800 if (R##_e <= _FP_ADD_INTERNAL_diff) \
1e145589
JM
801 { \
802 /* R is denormalized. */ \
9c37ec0b
JM
803 _FP_ADD_INTERNAL_diff \
804 = _FP_ADD_INTERNAL_diff - R##_e + 1; \
805 _FP_FRAC_SRS_##wc (R, _FP_ADD_INTERNAL_diff, \
806 _FP_WFRACBITS_##fs); \
1e145589
JM
807 R##_e = 0; \
808 } \
809 else \
810 { \
9c37ec0b 811 R##_e -= _FP_ADD_INTERNAL_diff; \
51ca9e29 812 _FP_FRAC_HIGH_##fs (R) &= ~(_FP_W_TYPE) _FP_IMPLBIT_SH_##fs; \
1e145589
JM
813 } \
814 } \
815 sub_done: ; \
816 } \
817 } \
818 while (0)
d876f532 819
51ca9e29 820#define _FP_ADD(fs, wc, R, X, Y) _FP_ADD_INTERNAL (fs, wc, R, X, Y, '+')
1e145589
JM
821#define _FP_SUB(fs, wc, R, X, Y) \
822 do \
823 { \
51ca9e29 824 if (!(Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc (Y))) \
1e145589 825 Y##_s ^= 1; \
51ca9e29 826 _FP_ADD_INTERNAL (fs, wc, R, X, Y, '-'); \
1e145589
JM
827 } \
828 while (0)
d876f532
UD
829
830
c4fe3ea7 831/* Main negation routine. The input value is raw. */
d876f532 832
1e145589
JM
833#define _FP_NEG(fs, wc, R, X) \
834 do \
835 { \
51ca9e29 836 _FP_FRAC_COPY_##wc (R, X); \
1e145589
JM
837 R##_e = X##_e; \
838 R##_s = 1 ^ X##_s; \
839 } \
840 while (0)
d876f532
UD
841
842
c4fe3ea7 843/* Main multiplication routine. The input values should be cooked. */
d876f532 844
1e145589
JM
845#define _FP_MUL(fs, wc, R, X, Y) \
846 do \
847 { \
848 R##_s = X##_s ^ Y##_s; \
849 R##_e = X##_e + Y##_e + 1; \
51ca9e29 850 switch (_FP_CLS_COMBINE (X##_c, Y##_c)) \
1e145589 851 { \
51ca9e29 852 case _FP_CLS_COMBINE (FP_CLS_NORMAL, FP_CLS_NORMAL): \
1e145589 853 R##_c = FP_CLS_NORMAL; \
77f01ab5 854 \
51ca9e29 855 _FP_MUL_MEAT_##fs (R, X, Y); \
77f01ab5 856 \
51ca9e29
JM
857 if (_FP_FRAC_OVERP_##wc (fs, R)) \
858 _FP_FRAC_SRS_##wc (R, 1, _FP_WFRACBITS_##fs); \
1e145589
JM
859 else \
860 R##_e--; \
861 break; \
77f01ab5 862 \
51ca9e29
JM
863 case _FP_CLS_COMBINE (FP_CLS_NAN, FP_CLS_NAN): \
864 _FP_CHOOSENAN (fs, wc, R, X, Y, '*'); \
1e145589 865 break; \
77f01ab5 866 \
51ca9e29
JM
867 case _FP_CLS_COMBINE (FP_CLS_NAN, FP_CLS_NORMAL): \
868 case _FP_CLS_COMBINE (FP_CLS_NAN, FP_CLS_INF): \
869 case _FP_CLS_COMBINE (FP_CLS_NAN, FP_CLS_ZERO): \
1e145589 870 R##_s = X##_s; \
77f01ab5 871 \
51ca9e29
JM
872 case _FP_CLS_COMBINE (FP_CLS_INF, FP_CLS_INF): \
873 case _FP_CLS_COMBINE (FP_CLS_INF, FP_CLS_NORMAL): \
874 case _FP_CLS_COMBINE (FP_CLS_ZERO, FP_CLS_NORMAL): \
875 case _FP_CLS_COMBINE (FP_CLS_ZERO, FP_CLS_ZERO): \
876 _FP_FRAC_COPY_##wc (R, X); \
1e145589
JM
877 R##_c = X##_c; \
878 break; \
77f01ab5 879 \
51ca9e29
JM
880 case _FP_CLS_COMBINE (FP_CLS_NORMAL, FP_CLS_NAN): \
881 case _FP_CLS_COMBINE (FP_CLS_INF, FP_CLS_NAN): \
882 case _FP_CLS_COMBINE (FP_CLS_ZERO, FP_CLS_NAN): \
1e145589 883 R##_s = Y##_s; \
77f01ab5 884 \
51ca9e29
JM
885 case _FP_CLS_COMBINE (FP_CLS_NORMAL, FP_CLS_INF): \
886 case _FP_CLS_COMBINE (FP_CLS_NORMAL, FP_CLS_ZERO): \
887 _FP_FRAC_COPY_##wc (R, Y); \
1e145589
JM
888 R##_c = Y##_c; \
889 break; \
77f01ab5 890 \
51ca9e29
JM
891 case _FP_CLS_COMBINE (FP_CLS_INF, FP_CLS_ZERO): \
892 case _FP_CLS_COMBINE (FP_CLS_ZERO, FP_CLS_INF): \
1e145589
JM
893 R##_s = _FP_NANSIGN_##fs; \
894 R##_c = FP_CLS_NAN; \
51ca9e29
JM
895 _FP_FRAC_SET_##wc (R, _FP_NANFRAC_##fs); \
896 FP_SET_EXCEPTION (FP_EX_INVALID); \
1e145589 897 break; \
77f01ab5 898 \
1e145589 899 default: \
51ca9e29 900 abort (); \
1e145589
JM
901 } \
902 } \
903 while (0)
904
905
906/* Fused multiply-add. The input values should be cooked. */
907
908#define _FP_FMA(fs, wc, dwc, R, X, Y, Z) \
909 do \
910 { \
9c37ec0b
JM
911 FP_DECL_##fs (_FP_FMA_T); \
912 _FP_FMA_T##_s = X##_s ^ Y##_s; \
913 _FP_FMA_T##_e = X##_e + Y##_e + 1; \
51ca9e29 914 switch (_FP_CLS_COMBINE (X##_c, Y##_c)) \
1e145589 915 { \
51ca9e29 916 case _FP_CLS_COMBINE (FP_CLS_NORMAL, FP_CLS_NORMAL): \
1e145589
JM
917 switch (Z##_c) \
918 { \
919 case FP_CLS_INF: \
920 case FP_CLS_NAN: \
921 R##_s = Z##_s; \
51ca9e29 922 _FP_FRAC_COPY_##wc (R, Z); \
1e145589
JM
923 R##_c = Z##_c; \
924 break; \
925 \
926 case FP_CLS_ZERO: \
927 R##_c = FP_CLS_NORMAL; \
9c37ec0b
JM
928 R##_s = _FP_FMA_T##_s; \
929 R##_e = _FP_FMA_T##_e; \
1e145589 930 \
51ca9e29 931 _FP_MUL_MEAT_##fs (R, X, Y); \
1e145589 932 \
51ca9e29
JM
933 if (_FP_FRAC_OVERP_##wc (fs, R)) \
934 _FP_FRAC_SRS_##wc (R, 1, _FP_WFRACBITS_##fs); \
1e145589
JM
935 else \
936 R##_e--; \
937 break; \
938 \
939 case FP_CLS_NORMAL:; \
9c37ec0b
JM
940 _FP_FRAC_DECL_##dwc (_FP_FMA_TD); \
941 _FP_FRAC_DECL_##dwc (_FP_FMA_ZD); \
942 _FP_FRAC_DECL_##dwc (_FP_FMA_RD); \
943 _FP_MUL_MEAT_DW_##fs (_FP_FMA_TD, X, Y); \
944 R##_e = _FP_FMA_T##_e; \
945 int _FP_FMA_tsh \
946 = _FP_FRAC_HIGHBIT_DW_##dwc (fs, _FP_FMA_TD) == 0; \
947 _FP_FMA_T##_e -= _FP_FMA_tsh; \
948 int _FP_FMA_ediff = _FP_FMA_T##_e - Z##_e; \
949 if (_FP_FMA_ediff >= 0) \
1e145589 950 { \
9c37ec0b
JM
951 int _FP_FMA_shift \
952 = _FP_WFRACBITS_##fs - _FP_FMA_tsh - _FP_FMA_ediff; \
953 if (_FP_FMA_shift <= -_FP_WFRACBITS_##fs) \
954 _FP_FRAC_SET_##dwc (_FP_FMA_ZD, _FP_MINFRAC_##dwc); \
1e145589
JM
955 else \
956 { \
9c37ec0b
JM
957 _FP_FRAC_COPY_##dwc##_##wc (_FP_FMA_ZD, Z); \
958 if (_FP_FMA_shift < 0) \
959 _FP_FRAC_SRS_##dwc (_FP_FMA_ZD, -_FP_FMA_shift, \
51ca9e29 960 _FP_WFRACBITS_DW_##fs); \
9c37ec0b
JM
961 else if (_FP_FMA_shift > 0) \
962 _FP_FRAC_SLL_##dwc (_FP_FMA_ZD, _FP_FMA_shift); \
1e145589 963 } \
9c37ec0b
JM
964 R##_s = _FP_FMA_T##_s; \
965 if (_FP_FMA_T##_s == Z##_s) \
966 _FP_FRAC_ADD_##dwc (_FP_FMA_RD, _FP_FMA_TD, \
967 _FP_FMA_ZD); \
1e145589
JM
968 else \
969 { \
9c37ec0b
JM
970 _FP_FRAC_SUB_##dwc (_FP_FMA_RD, _FP_FMA_TD, \
971 _FP_FMA_ZD); \
972 if (_FP_FRAC_NEGP_##dwc (_FP_FMA_RD)) \
1e145589
JM
973 { \
974 R##_s = Z##_s; \
9c37ec0b
JM
975 _FP_FRAC_SUB_##dwc (_FP_FMA_RD, _FP_FMA_ZD, \
976 _FP_FMA_TD); \
1e145589
JM
977 } \
978 } \
979 } \
980 else \
981 { \
982 R##_e = Z##_e; \
983 R##_s = Z##_s; \
9c37ec0b
JM
984 _FP_FRAC_COPY_##dwc##_##wc (_FP_FMA_ZD, Z); \
985 _FP_FRAC_SLL_##dwc (_FP_FMA_ZD, _FP_WFRACBITS_##fs); \
986 int _FP_FMA_shift = -_FP_FMA_ediff - _FP_FMA_tsh; \
987 if (_FP_FMA_shift >= _FP_WFRACBITS_DW_##fs) \
988 _FP_FRAC_SET_##dwc (_FP_FMA_TD, _FP_MINFRAC_##dwc); \
989 else if (_FP_FMA_shift > 0) \
990 _FP_FRAC_SRS_##dwc (_FP_FMA_TD, _FP_FMA_shift, \
51ca9e29 991 _FP_WFRACBITS_DW_##fs); \
9c37ec0b
JM
992 if (Z##_s == _FP_FMA_T##_s) \
993 _FP_FRAC_ADD_##dwc (_FP_FMA_RD, _FP_FMA_ZD, \
994 _FP_FMA_TD); \
1e145589 995 else \
9c37ec0b
JM
996 _FP_FRAC_SUB_##dwc (_FP_FMA_RD, _FP_FMA_ZD, \
997 _FP_FMA_TD); \
1e145589 998 } \
9c37ec0b 999 if (_FP_FRAC_ZEROP_##dwc (_FP_FMA_RD)) \
1e145589 1000 { \
9c37ec0b 1001 if (_FP_FMA_T##_s == Z##_s) \
1e145589
JM
1002 R##_s = Z##_s; \
1003 else \
1004 R##_s = (FP_ROUNDMODE == FP_RND_MINF); \
51ca9e29 1005 _FP_FRAC_SET_##wc (R, _FP_ZEROFRAC_##wc); \
1e145589
JM
1006 R##_c = FP_CLS_ZERO; \
1007 } \
1008 else \
1009 { \
9c37ec0b
JM
1010 int _FP_FMA_rlz; \
1011 _FP_FRAC_CLZ_##dwc (_FP_FMA_rlz, _FP_FMA_RD); \
1012 _FP_FMA_rlz -= _FP_WFRACXBITS_DW_##fs; \
1013 R##_e -= _FP_FMA_rlz; \
1014 int _FP_FMA_shift = _FP_WFRACBITS_##fs - _FP_FMA_rlz; \
1015 if (_FP_FMA_shift > 0) \
1016 _FP_FRAC_SRS_##dwc (_FP_FMA_RD, _FP_FMA_shift, \
51ca9e29 1017 _FP_WFRACBITS_DW_##fs); \
9c37ec0b
JM
1018 else if (_FP_FMA_shift < 0) \
1019 _FP_FRAC_SLL_##dwc (_FP_FMA_RD, -_FP_FMA_shift); \
1020 _FP_FRAC_COPY_##wc##_##dwc (R, _FP_FMA_RD); \
1e145589
JM
1021 R##_c = FP_CLS_NORMAL; \
1022 } \
1023 break; \
1024 } \
1025 goto done_fma; \
1026 \
51ca9e29 1027 case _FP_CLS_COMBINE (FP_CLS_NAN, FP_CLS_NAN): \
9c37ec0b 1028 _FP_CHOOSENAN (fs, wc, _FP_FMA_T, X, Y, '*'); \
1e145589
JM
1029 break; \
1030 \
51ca9e29
JM
1031 case _FP_CLS_COMBINE (FP_CLS_NAN, FP_CLS_NORMAL): \
1032 case _FP_CLS_COMBINE (FP_CLS_NAN, FP_CLS_INF): \
1033 case _FP_CLS_COMBINE (FP_CLS_NAN, FP_CLS_ZERO): \
9c37ec0b 1034 _FP_FMA_T##_s = X##_s; \
1e145589 1035 \
51ca9e29
JM
1036 case _FP_CLS_COMBINE (FP_CLS_INF, FP_CLS_INF): \
1037 case _FP_CLS_COMBINE (FP_CLS_INF, FP_CLS_NORMAL): \
1038 case _FP_CLS_COMBINE (FP_CLS_ZERO, FP_CLS_NORMAL): \
1039 case _FP_CLS_COMBINE (FP_CLS_ZERO, FP_CLS_ZERO): \
9c37ec0b
JM
1040 _FP_FRAC_COPY_##wc (_FP_FMA_T, X); \
1041 _FP_FMA_T##_c = X##_c; \
1e145589
JM
1042 break; \
1043 \
51ca9e29
JM
1044 case _FP_CLS_COMBINE (FP_CLS_NORMAL, FP_CLS_NAN): \
1045 case _FP_CLS_COMBINE (FP_CLS_INF, FP_CLS_NAN): \
1046 case _FP_CLS_COMBINE (FP_CLS_ZERO, FP_CLS_NAN): \
9c37ec0b 1047 _FP_FMA_T##_s = Y##_s; \
1e145589 1048 \
51ca9e29
JM
1049 case _FP_CLS_COMBINE (FP_CLS_NORMAL, FP_CLS_INF): \
1050 case _FP_CLS_COMBINE (FP_CLS_NORMAL, FP_CLS_ZERO): \
9c37ec0b
JM
1051 _FP_FRAC_COPY_##wc (_FP_FMA_T, Y); \
1052 _FP_FMA_T##_c = Y##_c; \
1e145589
JM
1053 break; \
1054 \
51ca9e29
JM
1055 case _FP_CLS_COMBINE (FP_CLS_INF, FP_CLS_ZERO): \
1056 case _FP_CLS_COMBINE (FP_CLS_ZERO, FP_CLS_INF): \
9c37ec0b
JM
1057 _FP_FMA_T##_s = _FP_NANSIGN_##fs; \
1058 _FP_FMA_T##_c = FP_CLS_NAN; \
1059 _FP_FRAC_SET_##wc (_FP_FMA_T, _FP_NANFRAC_##fs); \
51ca9e29 1060 FP_SET_EXCEPTION (FP_EX_INVALID); \
1e145589
JM
1061 break; \
1062 \
1063 default: \
51ca9e29 1064 abort (); \
1e145589
JM
1065 } \
1066 \
1067 /* T = X * Y is zero, infinity or NaN. */ \
9c37ec0b 1068 switch (_FP_CLS_COMBINE (_FP_FMA_T##_c, Z##_c)) \
1e145589 1069 { \
51ca9e29 1070 case _FP_CLS_COMBINE (FP_CLS_NAN, FP_CLS_NAN): \
9c37ec0b 1071 _FP_CHOOSENAN (fs, wc, R, _FP_FMA_T, Z, '+'); \
1e145589
JM
1072 break; \
1073 \
51ca9e29
JM
1074 case _FP_CLS_COMBINE (FP_CLS_NAN, FP_CLS_NORMAL): \
1075 case _FP_CLS_COMBINE (FP_CLS_NAN, FP_CLS_INF): \
1076 case _FP_CLS_COMBINE (FP_CLS_NAN, FP_CLS_ZERO): \
1077 case _FP_CLS_COMBINE (FP_CLS_INF, FP_CLS_NORMAL): \
1078 case _FP_CLS_COMBINE (FP_CLS_INF, FP_CLS_ZERO): \
9c37ec0b
JM
1079 R##_s = _FP_FMA_T##_s; \
1080 _FP_FRAC_COPY_##wc (R, _FP_FMA_T); \
1081 R##_c = _FP_FMA_T##_c; \
1e145589
JM
1082 break; \
1083 \
51ca9e29
JM
1084 case _FP_CLS_COMBINE (FP_CLS_INF, FP_CLS_NAN): \
1085 case _FP_CLS_COMBINE (FP_CLS_ZERO, FP_CLS_NAN): \
1086 case _FP_CLS_COMBINE (FP_CLS_ZERO, FP_CLS_NORMAL): \
1087 case _FP_CLS_COMBINE (FP_CLS_ZERO, FP_CLS_INF): \
1e145589 1088 R##_s = Z##_s; \
51ca9e29 1089 _FP_FRAC_COPY_##wc (R, Z); \
1e145589
JM
1090 R##_c = Z##_c; \
1091 break; \
1092 \
51ca9e29 1093 case _FP_CLS_COMBINE (FP_CLS_INF, FP_CLS_INF): \
9c37ec0b 1094 if (_FP_FMA_T##_s == Z##_s) \
1e145589
JM
1095 { \
1096 R##_s = Z##_s; \
51ca9e29 1097 _FP_FRAC_COPY_##wc (R, Z); \
1e145589
JM
1098 R##_c = Z##_c; \
1099 } \
1100 else \
1101 { \
1102 R##_s = _FP_NANSIGN_##fs; \
1103 R##_c = FP_CLS_NAN; \
51ca9e29
JM
1104 _FP_FRAC_SET_##wc (R, _FP_NANFRAC_##fs); \
1105 FP_SET_EXCEPTION (FP_EX_INVALID); \
1e145589
JM
1106 } \
1107 break; \
1108 \
51ca9e29 1109 case _FP_CLS_COMBINE (FP_CLS_ZERO, FP_CLS_ZERO): \
9c37ec0b 1110 if (_FP_FMA_T##_s == Z##_s) \
1e145589
JM
1111 R##_s = Z##_s; \
1112 else \
1113 R##_s = (FP_ROUNDMODE == FP_RND_MINF); \
51ca9e29 1114 _FP_FRAC_COPY_##wc (R, Z); \
1e145589
JM
1115 R##_c = Z##_c; \
1116 break; \
1117 \
1118 default: \
51ca9e29 1119 abort (); \
1e145589
JM
1120 } \
1121 done_fma: ; \
1122 } \
1123 while (0)
1124
1125
c4fe3ea7 1126/* Main division routine. The input values should be cooked. */
1e145589
JM
1127
1128#define _FP_DIV(fs, wc, R, X, Y) \
1129 do \
1130 { \
1131 R##_s = X##_s ^ Y##_s; \
1132 R##_e = X##_e - Y##_e; \
51ca9e29 1133 switch (_FP_CLS_COMBINE (X##_c, Y##_c)) \
1e145589 1134 { \
51ca9e29 1135 case _FP_CLS_COMBINE (FP_CLS_NORMAL, FP_CLS_NORMAL): \
1e145589 1136 R##_c = FP_CLS_NORMAL; \
77f01ab5 1137 \
51ca9e29 1138 _FP_DIV_MEAT_##fs (R, X, Y); \
1e145589 1139 break; \
77f01ab5 1140 \
51ca9e29
JM
1141 case _FP_CLS_COMBINE (FP_CLS_NAN, FP_CLS_NAN): \
1142 _FP_CHOOSENAN (fs, wc, R, X, Y, '/'); \
1e145589 1143 break; \
77f01ab5 1144 \
51ca9e29
JM
1145 case _FP_CLS_COMBINE (FP_CLS_NAN, FP_CLS_NORMAL): \
1146 case _FP_CLS_COMBINE (FP_CLS_NAN, FP_CLS_INF): \
1147 case _FP_CLS_COMBINE (FP_CLS_NAN, FP_CLS_ZERO): \
1e145589 1148 R##_s = X##_s; \
51ca9e29 1149 _FP_FRAC_COPY_##wc (R, X); \
1e145589
JM
1150 R##_c = X##_c; \
1151 break; \
77f01ab5 1152 \
51ca9e29
JM
1153 case _FP_CLS_COMBINE (FP_CLS_NORMAL, FP_CLS_NAN): \
1154 case _FP_CLS_COMBINE (FP_CLS_INF, FP_CLS_NAN): \
1155 case _FP_CLS_COMBINE (FP_CLS_ZERO, FP_CLS_NAN): \
1e145589 1156 R##_s = Y##_s; \
51ca9e29 1157 _FP_FRAC_COPY_##wc (R, Y); \
1e145589
JM
1158 R##_c = Y##_c; \
1159 break; \
77f01ab5 1160 \
51ca9e29
JM
1161 case _FP_CLS_COMBINE (FP_CLS_NORMAL, FP_CLS_INF): \
1162 case _FP_CLS_COMBINE (FP_CLS_ZERO, FP_CLS_INF): \
1163 case _FP_CLS_COMBINE (FP_CLS_ZERO, FP_CLS_NORMAL): \
1e145589
JM
1164 R##_c = FP_CLS_ZERO; \
1165 break; \
77f01ab5 1166 \
51ca9e29
JM
1167 case _FP_CLS_COMBINE (FP_CLS_NORMAL, FP_CLS_ZERO): \
1168 FP_SET_EXCEPTION (FP_EX_DIVZERO); \
1169 case _FP_CLS_COMBINE (FP_CLS_INF, FP_CLS_ZERO): \
1170 case _FP_CLS_COMBINE (FP_CLS_INF, FP_CLS_NORMAL): \
1e145589
JM
1171 R##_c = FP_CLS_INF; \
1172 break; \
77f01ab5 1173 \
51ca9e29
JM
1174 case _FP_CLS_COMBINE (FP_CLS_INF, FP_CLS_INF): \
1175 case _FP_CLS_COMBINE (FP_CLS_ZERO, FP_CLS_ZERO): \
1e145589
JM
1176 R##_s = _FP_NANSIGN_##fs; \
1177 R##_c = FP_CLS_NAN; \
51ca9e29
JM
1178 _FP_FRAC_SET_##wc (R, _FP_NANFRAC_##fs); \
1179 FP_SET_EXCEPTION (FP_EX_INVALID); \
1e145589 1180 break; \
77f01ab5 1181 \
1e145589 1182 default: \
51ca9e29 1183 abort (); \
1e145589
JM
1184 } \
1185 } \
1186 while (0)
d876f532
UD
1187
1188
73e28d9c
JM
1189/* Helper for comparisons. EX is 0 not to raise exceptions, 1 to
1190 raise exceptions for signaling NaN operands, 2 to raise exceptions
1191 for all NaN operands. */
1192
1193#define _FP_CMP_CHECK_NAN(fs, wc, X, Y, ex) \
1194 do \
1195 { \
1196 if (ex) \
1197 { \
1198 if ((ex) == 2 \
1199 || _FP_ISSIGNAN (fs, wc, X) \
1200 || _FP_ISSIGNAN (fs, wc, Y)) \
1201 FP_SET_EXCEPTION (FP_EX_INVALID); \
1202 } \
1203 } \
1204 while (0)
1205
c4fe3ea7 1206/* Main differential comparison routine. The inputs should be raw not
73e28d9c
JM
1207 cooked. The return is -1, 0, 1 for normal values, UN
1208 otherwise. */
d876f532 1209
73e28d9c 1210#define _FP_CMP(fs, wc, ret, X, Y, un, ex) \
1e145589
JM
1211 do \
1212 { \
c4fe3ea7 1213 /* NANs are unordered. */ \
51ca9e29
JM
1214 if ((X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc (X)) \
1215 || (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc (Y))) \
1e145589
JM
1216 { \
1217 ret = un; \
73e28d9c 1218 _FP_CMP_CHECK_NAN (fs, wc, X, Y, ex); \
1e145589
JM
1219 } \
1220 else \
1221 { \
9c37ec0b
JM
1222 int _FP_CMP_is_zero_x; \
1223 int _FP_CMP_is_zero_y; \
d876f532 1224 \
9c37ec0b
JM
1225 _FP_CMP_is_zero_x \
1226 = (!X##_e && _FP_FRAC_ZEROP_##wc (X)) ? 1 : 0; \
1227 _FP_CMP_is_zero_y \
1228 = (!Y##_e && _FP_FRAC_ZEROP_##wc (Y)) ? 1 : 0; \
d876f532 1229 \
9c37ec0b 1230 if (_FP_CMP_is_zero_x && _FP_CMP_is_zero_y) \
1e145589 1231 ret = 0; \
9c37ec0b 1232 else if (_FP_CMP_is_zero_x) \
1e145589 1233 ret = Y##_s ? 1 : -1; \
9c37ec0b 1234 else if (_FP_CMP_is_zero_y) \
1e145589
JM
1235 ret = X##_s ? -1 : 1; \
1236 else if (X##_s != Y##_s) \
1237 ret = X##_s ? -1 : 1; \
1238 else if (X##_e > Y##_e) \
1239 ret = X##_s ? -1 : 1; \
1240 else if (X##_e < Y##_e) \
1241 ret = X##_s ? 1 : -1; \
51ca9e29 1242 else if (_FP_FRAC_GT_##wc (X, Y)) \
1e145589 1243 ret = X##_s ? -1 : 1; \
51ca9e29 1244 else if (_FP_FRAC_GT_##wc (Y, X)) \
1e145589
JM
1245 ret = X##_s ? 1 : -1; \
1246 else \
1247 ret = 0; \
1248 } \
1249 } \
1250 while (0)
d876f532
UD
1251
1252
1253/* Simplification for strict equality. */
1254
73e28d9c 1255#define _FP_CMP_EQ(fs, wc, ret, X, Y, ex) \
1e145589
JM
1256 do \
1257 { \
c4fe3ea7 1258 /* NANs are unordered. */ \
51ca9e29
JM
1259 if ((X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc (X)) \
1260 || (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc (Y))) \
1e145589
JM
1261 { \
1262 ret = 1; \
73e28d9c 1263 _FP_CMP_CHECK_NAN (fs, wc, X, Y, ex); \
1e145589
JM
1264 } \
1265 else \
1266 { \
1267 ret = !(X##_e == Y##_e \
51ca9e29
JM
1268 && _FP_FRAC_EQ_##wc (X, Y) \
1269 && (X##_s == Y##_s || (!X##_e && _FP_FRAC_ZEROP_##wc (X)))); \
1e145589
JM
1270 } \
1271 } \
1272 while (0)
d876f532 1273
e7b8c7bc
RM
1274/* Version to test unordered. */
1275
73e28d9c 1276#define _FP_CMP_UNORD(fs, wc, ret, X, Y, ex) \
1e145589
JM
1277 do \
1278 { \
51ca9e29
JM
1279 ret = ((X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc (X)) \
1280 || (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc (Y))); \
73e28d9c
JM
1281 if (ret) \
1282 _FP_CMP_CHECK_NAN (fs, wc, X, Y, ex); \
1e145589
JM
1283 } \
1284 while (0)
e7b8c7bc 1285
c4fe3ea7 1286/* Main square root routine. The input value should be cooked. */
d876f532 1287
1e145589
JM
1288#define _FP_SQRT(fs, wc, R, X) \
1289 do \
1290 { \
9c37ec0b
JM
1291 _FP_FRAC_DECL_##wc (_FP_SQRT_T); \
1292 _FP_FRAC_DECL_##wc (_FP_SQRT_S); \
1293 _FP_W_TYPE _FP_SQRT_q; \
1e145589
JM
1294 switch (X##_c) \
1295 { \
1296 case FP_CLS_NAN: \
51ca9e29 1297 _FP_FRAC_COPY_##wc (R, X); \
1e145589
JM
1298 R##_s = X##_s; \
1299 R##_c = FP_CLS_NAN; \
1300 break; \
1301 case FP_CLS_INF: \
1302 if (X##_s) \
1303 { \
1304 R##_s = _FP_NANSIGN_##fs; \
1305 R##_c = FP_CLS_NAN; /* NAN */ \
51ca9e29
JM
1306 _FP_FRAC_SET_##wc (R, _FP_NANFRAC_##fs); \
1307 FP_SET_EXCEPTION (FP_EX_INVALID); \
1e145589
JM
1308 } \
1309 else \
1310 { \
1311 R##_s = 0; \
1312 R##_c = FP_CLS_INF; /* sqrt(+inf) = +inf */ \
1313 } \
1314 break; \
1315 case FP_CLS_ZERO: \
1316 R##_s = X##_s; \
1317 R##_c = FP_CLS_ZERO; /* sqrt(+-0) = +-0 */ \
1318 break; \
1319 case FP_CLS_NORMAL: \
1320 R##_s = 0; \
1321 if (X##_s) \
1322 { \
1323 R##_c = FP_CLS_NAN; /* NAN */ \
1324 R##_s = _FP_NANSIGN_##fs; \
51ca9e29
JM
1325 _FP_FRAC_SET_##wc (R, _FP_NANFRAC_##fs); \
1326 FP_SET_EXCEPTION (FP_EX_INVALID); \
1e145589
JM
1327 break; \
1328 } \
1329 R##_c = FP_CLS_NORMAL; \
1330 if (X##_e & 1) \
51ca9e29 1331 _FP_FRAC_SLL_##wc (X, 1); \
1e145589 1332 R##_e = X##_e >> 1; \
9c37ec0b 1333 _FP_FRAC_SET_##wc (_FP_SQRT_S, _FP_ZEROFRAC_##wc); \
51ca9e29 1334 _FP_FRAC_SET_##wc (R, _FP_ZEROFRAC_##wc); \
9c37ec0b
JM
1335 _FP_SQRT_q = _FP_OVERFLOW_##fs >> 1; \
1336 _FP_SQRT_MEAT_##wc (R, _FP_SQRT_S, _FP_SQRT_T, X, \
1337 _FP_SQRT_q); \
1e145589
JM
1338 } \
1339 } \
1340 while (0)
d876f532 1341
c4fe3ea7 1342/* Convert from FP to integer. Input is raw. */
d876f532
UD
1343
1344/* RSIGNED can have following values:
c4fe3ea7
JM
1345 0: the number is required to be 0..(2^rsize)-1, if not, NV is set plus
1346 the result is either 0 or (2^rsize)-1 depending on the sign in such
1347 case.
1348 1: the number is required to be -(2^(rsize-1))..(2^(rsize-1))-1, if not,
1349 NV is set plus the result is either -(2^(rsize-1)) or (2^(rsize-1))-1
1350 depending on the sign in such case.
1351 -1: the number is required to be -(2^(rsize-1))..(2^rsize)-1, if not, NV is
1352 set plus the result is either -(2^(rsize-1)) or (2^(rsize-1))-1
1353 depending on the sign in such case. */
fe0b1e85 1354#define _FP_TO_INT(fs, wc, r, X, rsize, rsigned) \
1e145589 1355 do \
fe0b1e85 1356 { \
1e145589 1357 if (X##_e < _FP_EXPBIAS_##fs) \
fe0b1e85 1358 { \
1e145589
JM
1359 r = 0; \
1360 if (X##_e == 0) \
fe0b1e85 1361 { \
51ca9e29 1362 if (!_FP_FRAC_ZEROP_##wc (X)) \
1e145589 1363 { \
51ca9e29
JM
1364 FP_SET_EXCEPTION (FP_EX_INEXACT); \
1365 FP_SET_EXCEPTION (FP_EX_DENORM); \
1e145589 1366 } \
fe0b1e85 1367 } \
1e145589 1368 else \
51ca9e29 1369 FP_SET_EXCEPTION (FP_EX_INEXACT); \
fe0b1e85 1370 } \
0022e688
JM
1371 else if (X##_e >= (_FP_EXPMAX_##fs < _FP_EXPBIAS_##fs + rsize \
1372 ? _FP_EXPMAX_##fs \
1373 : _FP_EXPBIAS_##fs + rsize - (rsigned > 0 || X##_s)) \
1e145589 1374 || (!rsigned && X##_s)) \
fe0b1e85 1375 { \
1e145589
JM
1376 /* Overflow or converting to the most negative integer. */ \
1377 if (rsigned) \
1378 { \
1379 r = 1; \
1380 r <<= rsize - 1; \
1381 r -= 1 - X##_s; \
4e8afe69
JM
1382 } \
1383 else \
1384 { \
1385 r = 0; \
1386 if (!X##_s) \
1387 r = ~r; \
1388 } \
a334319f 1389 \
0022e688
JM
1390 if (_FP_EXPBIAS_##fs + rsize - 1 < _FP_EXPMAX_##fs \
1391 && rsigned \
1392 && X##_s \
1393 && X##_e == _FP_EXPBIAS_##fs + rsize - 1) \
1e145589
JM
1394 { \
1395 /* Possibly converting to most negative integer; check the \
1396 mantissa. */ \
9c37ec0b 1397 int _FP_TO_INT_inexact = 0; \
51ca9e29
JM
1398 (void) ((_FP_FRACBITS_##fs > rsize) \
1399 ? ({ \
9c37ec0b 1400 _FP_FRAC_SRST_##wc (X, _FP_TO_INT_inexact, \
51ca9e29
JM
1401 _FP_FRACBITS_##fs - rsize, \
1402 _FP_FRACBITS_##fs); \
1403 0; \
1404 }) \
1405 : 0); \
1406 if (!_FP_FRAC_ZEROP_##wc (X)) \
1407 FP_SET_EXCEPTION (FP_EX_INVALID); \
9c37ec0b 1408 else if (_FP_TO_INT_inexact) \
51ca9e29 1409 FP_SET_EXCEPTION (FP_EX_INEXACT); \
1e145589
JM
1410 } \
1411 else \
51ca9e29 1412 FP_SET_EXCEPTION (FP_EX_INVALID); \
fe0b1e85
RM
1413 } \
1414 else \
1e145589 1415 { \
51ca9e29 1416 _FP_FRAC_HIGH_RAW_##fs (X) |= _FP_IMPLBIT_##fs; \
1e145589
JM
1417 if (X##_e >= _FP_EXPBIAS_##fs + _FP_FRACBITS_##fs - 1) \
1418 { \
51ca9e29 1419 _FP_FRAC_ASSEMBLE_##wc (r, X, rsize); \
1e145589
JM
1420 r <<= X##_e - _FP_EXPBIAS_##fs - _FP_FRACBITS_##fs + 1; \
1421 } \
1422 else \
1423 { \
9c37ec0b
JM
1424 int _FP_TO_INT_inexact; \
1425 _FP_FRAC_SRST_##wc (X, _FP_TO_INT_inexact, \
51ca9e29
JM
1426 (_FP_FRACBITS_##fs + _FP_EXPBIAS_##fs - 1 \
1427 - X##_e), \
1428 _FP_FRACBITS_##fs); \
9c37ec0b 1429 if (_FP_TO_INT_inexact) \
51ca9e29
JM
1430 FP_SET_EXCEPTION (FP_EX_INEXACT); \
1431 _FP_FRAC_ASSEMBLE_##wc (r, X, rsize); \
1e145589
JM
1432 } \
1433 if (rsigned && X##_s) \
1434 r = -r; \
1435 } \
fe0b1e85 1436 } \
1e145589
JM
1437 while (0)
1438
1439/* Convert integer to fp. Output is raw. RTYPE is unsigned even if
1440 input is signed. */
1441#define _FP_FROM_INT(fs, wc, X, r, rsize, rtype) \
1442 do \
fe0b1e85 1443 { \
1e145589 1444 if (r) \
fe0b1e85 1445 { \
9c37ec0b 1446 rtype _FP_FROM_INT_ur; \
1e145589
JM
1447 \
1448 if ((X##_s = (r < 0))) \
51ca9e29 1449 r = -(rtype) r; \
1e145589 1450 \
9c37ec0b 1451 _FP_FROM_INT_ur = (rtype) r; \
51ca9e29
JM
1452 (void) ((rsize <= _FP_W_TYPE_SIZE) \
1453 ? ({ \
9c37ec0b
JM
1454 int _FP_FROM_INT_lz; \
1455 __FP_CLZ (_FP_FROM_INT_lz, \
1456 (_FP_W_TYPE) _FP_FROM_INT_ur); \
1457 X##_e = (_FP_EXPBIAS_##fs + _FP_W_TYPE_SIZE - 1 \
1458 - _FP_FROM_INT_lz); \
51ca9e29
JM
1459 }) \
1460 : ((rsize <= 2 * _FP_W_TYPE_SIZE) \
1461 ? ({ \
9c37ec0b
JM
1462 int _FP_FROM_INT_lz; \
1463 __FP_CLZ_2 (_FP_FROM_INT_lz, \
1464 (_FP_W_TYPE) (_FP_FROM_INT_ur \
1465 >> _FP_W_TYPE_SIZE), \
1466 (_FP_W_TYPE) _FP_FROM_INT_ur); \
51ca9e29 1467 X##_e = (_FP_EXPBIAS_##fs + 2 * _FP_W_TYPE_SIZE - 1 \
9c37ec0b 1468 - _FP_FROM_INT_lz); \
51ca9e29
JM
1469 }) \
1470 : (abort (), 0))); \
1e145589
JM
1471 \
1472 if (rsize - 1 + _FP_EXPBIAS_##fs >= _FP_EXPMAX_##fs \
1473 && X##_e >= _FP_EXPMAX_##fs) \
1474 { \
1475 /* Exponent too big; overflow to infinity. (May also \
1476 happen after rounding below.) */ \
51ca9e29 1477 _FP_OVERFLOW_SEMIRAW (fs, wc, X); \
1e145589
JM
1478 goto pack_semiraw; \
1479 } \
1480 \
1481 if (rsize <= _FP_FRACBITS_##fs \
1482 || X##_e < _FP_EXPBIAS_##fs + _FP_FRACBITS_##fs) \
1483 { \
1484 /* Exactly representable; shift left. */ \
9c37ec0b 1485 _FP_FRAC_DISASSEMBLE_##wc (X, _FP_FROM_INT_ur, rsize); \
1e145589 1486 if (_FP_EXPBIAS_##fs + _FP_FRACBITS_##fs - 1 - X##_e > 0) \
51ca9e29
JM
1487 _FP_FRAC_SLL_##wc (X, (_FP_EXPBIAS_##fs \
1488 + _FP_FRACBITS_##fs - 1 - X##_e)); \
1e145589
JM
1489 } \
1490 else \
1491 { \
1492 /* More bits in integer than in floating type; need to \
1493 round. */ \
1494 if (_FP_EXPBIAS_##fs + _FP_WFRACBITS_##fs - 1 < X##_e) \
9c37ec0b
JM
1495 _FP_FROM_INT_ur \
1496 = ((_FP_FROM_INT_ur >> (X##_e - _FP_EXPBIAS_##fs \
1497 - _FP_WFRACBITS_##fs + 1)) \
1498 | ((_FP_FROM_INT_ur \
1499 << (rsize - (X##_e - _FP_EXPBIAS_##fs \
1500 - _FP_WFRACBITS_##fs + 1))) \
1501 != 0)); \
1502 _FP_FRAC_DISASSEMBLE_##wc (X, _FP_FROM_INT_ur, rsize); \
1e145589 1503 if ((_FP_EXPBIAS_##fs + _FP_WFRACBITS_##fs - 1 - X##_e) > 0) \
51ca9e29
JM
1504 _FP_FRAC_SLL_##wc (X, (_FP_EXPBIAS_##fs \
1505 + _FP_WFRACBITS_##fs - 1 - X##_e)); \
1506 _FP_FRAC_HIGH_##fs (X) &= ~(_FP_W_TYPE) _FP_IMPLBIT_SH_##fs; \
1e145589 1507 pack_semiraw: \
51ca9e29 1508 _FP_PACK_SEMIRAW (fs, wc, X); \
1e145589 1509 } \
fe0b1e85
RM
1510 } \
1511 else \
1512 { \
1e145589
JM
1513 X##_s = 0; \
1514 X##_e = 0; \
51ca9e29 1515 _FP_FRAC_SET_##wc (X, _FP_ZEROFRAC_##wc); \
fe0b1e85 1516 } \
fe0b1e85 1517 } \
1e145589 1518 while (0)
d876f532 1519
0ecb606c 1520
fe0b1e85
RM
1521/* Extend from a narrower floating-point format to a wider one. Input
1522 and output are raw. */
51ca9e29 1523#define FP_EXTEND(dfs, sfs, dwc, swc, D, S) \
1e145589
JM
1524 do \
1525 { \
1526 if (_FP_FRACBITS_##dfs < _FP_FRACBITS_##sfs \
1527 || (_FP_EXPMAX_##dfs - _FP_EXPBIAS_##dfs \
1528 < _FP_EXPMAX_##sfs - _FP_EXPBIAS_##sfs) \
1529 || (_FP_EXPBIAS_##dfs < _FP_EXPBIAS_##sfs + _FP_FRACBITS_##sfs - 1 \
1530 && _FP_EXPBIAS_##dfs != _FP_EXPBIAS_##sfs)) \
51ca9e29 1531 abort (); \
1e145589 1532 D##_s = S##_s; \
51ca9e29
JM
1533 _FP_FRAC_COPY_##dwc##_##swc (D, S); \
1534 if (_FP_EXP_NORMAL (sfs, swc, S)) \
1e145589
JM
1535 { \
1536 D##_e = S##_e + _FP_EXPBIAS_##dfs - _FP_EXPBIAS_##sfs; \
51ca9e29 1537 _FP_FRAC_SLL_##dwc (D, (_FP_FRACBITS_##dfs - _FP_FRACBITS_##sfs)); \
1e145589
JM
1538 } \
1539 else \
1540 { \
1541 if (S##_e == 0) \
1542 { \
51ca9e29 1543 if (_FP_FRAC_ZEROP_##swc (S)) \
1e145589
JM
1544 D##_e = 0; \
1545 else if (_FP_EXPBIAS_##dfs \
1546 < _FP_EXPBIAS_##sfs + _FP_FRACBITS_##sfs - 1) \
1547 { \
51ca9e29
JM
1548 FP_SET_EXCEPTION (FP_EX_DENORM); \
1549 _FP_FRAC_SLL_##dwc (D, (_FP_FRACBITS_##dfs \
1550 - _FP_FRACBITS_##sfs)); \
1e145589 1551 D##_e = 0; \
43059f42
JM
1552 if (FP_TRAPPING_EXCEPTIONS & FP_EX_UNDERFLOW) \
1553 FP_SET_EXCEPTION (FP_EX_UNDERFLOW); \
1e145589
JM
1554 } \
1555 else \
1556 { \
9c37ec0b 1557 int FP_EXTEND_lz; \
51ca9e29 1558 FP_SET_EXCEPTION (FP_EX_DENORM); \
9c37ec0b 1559 _FP_FRAC_CLZ_##swc (FP_EXTEND_lz, S); \
51ca9e29 1560 _FP_FRAC_SLL_##dwc (D, \
9c37ec0b 1561 FP_EXTEND_lz + _FP_FRACBITS_##dfs \
51ca9e29 1562 - _FP_FRACTBITS_##sfs); \
1e145589 1563 D##_e = (_FP_EXPBIAS_##dfs - _FP_EXPBIAS_##sfs + 1 \
9c37ec0b 1564 + _FP_FRACXBITS_##sfs - FP_EXTEND_lz); \
1e145589
JM
1565 } \
1566 } \
1567 else \
1568 { \
1569 D##_e = _FP_EXPMAX_##dfs; \
51ca9e29 1570 if (!_FP_FRAC_ZEROP_##swc (S)) \
1e145589 1571 { \
51ca9e29
JM
1572 if (_FP_FRAC_SNANP (sfs, S)) \
1573 FP_SET_EXCEPTION (FP_EX_INVALID); \
1574 _FP_FRAC_SLL_##dwc (D, (_FP_FRACBITS_##dfs \
1575 - _FP_FRACBITS_##sfs)); \
e5c2c2d0 1576 _FP_SETQNAN (dfs, dwc, D); \
1e145589
JM
1577 } \
1578 } \
1579 } \
1580 } \
1581 while (0)
fe0b1e85
RM
1582
1583/* Truncate from a wider floating-point format to a narrower one.
1584 Input and output are semi-raw. */
51ca9e29 1585#define FP_TRUNC(dfs, sfs, dwc, swc, D, S) \
1e145589
JM
1586 do \
1587 { \
1588 if (_FP_FRACBITS_##sfs < _FP_FRACBITS_##dfs \
1589 || (_FP_EXPBIAS_##sfs < _FP_EXPBIAS_##dfs + _FP_FRACBITS_##dfs - 1 \
1590 && _FP_EXPBIAS_##sfs != _FP_EXPBIAS_##dfs)) \
51ca9e29 1591 abort (); \
1e145589 1592 D##_s = S##_s; \
51ca9e29 1593 if (_FP_EXP_NORMAL (sfs, swc, S)) \
1e145589
JM
1594 { \
1595 D##_e = S##_e + _FP_EXPBIAS_##dfs - _FP_EXPBIAS_##sfs; \
1596 if (D##_e >= _FP_EXPMAX_##dfs) \
51ca9e29 1597 _FP_OVERFLOW_SEMIRAW (dfs, dwc, D); \
1e145589
JM
1598 else \
1599 { \
1600 if (D##_e <= 0) \
1601 { \
1602 if (D##_e < 1 - _FP_FRACBITS_##dfs) \
1603 { \
51ca9e29
JM
1604 _FP_FRAC_SET_##swc (S, _FP_ZEROFRAC_##swc); \
1605 _FP_FRAC_LOW_##swc (S) |= 1; \
1e145589
JM
1606 } \
1607 else \
1608 { \
51ca9e29
JM
1609 _FP_FRAC_HIGH_##sfs (S) |= _FP_IMPLBIT_SH_##sfs; \
1610 _FP_FRAC_SRS_##swc (S, (_FP_WFRACBITS_##sfs \
1611 - _FP_WFRACBITS_##dfs \
1612 + 1 - D##_e), \
1613 _FP_WFRACBITS_##sfs); \
1e145589
JM
1614 } \
1615 D##_e = 0; \
1616 } \
1617 else \
51ca9e29
JM
1618 _FP_FRAC_SRS_##swc (S, (_FP_WFRACBITS_##sfs \
1619 - _FP_WFRACBITS_##dfs), \
1620 _FP_WFRACBITS_##sfs); \
1621 _FP_FRAC_COPY_##dwc##_##swc (D, S); \
1e145589
JM
1622 } \
1623 } \
1624 else \
1625 { \
1626 if (S##_e == 0) \
1627 { \
1628 D##_e = 0; \
51ca9e29
JM
1629 if (_FP_FRAC_ZEROP_##swc (S)) \
1630 _FP_FRAC_SET_##dwc (D, _FP_ZEROFRAC_##dwc); \
1e145589
JM
1631 else \
1632 { \
51ca9e29 1633 FP_SET_EXCEPTION (FP_EX_DENORM); \
1e145589
JM
1634 if (_FP_EXPBIAS_##sfs \
1635 < _FP_EXPBIAS_##dfs + _FP_FRACBITS_##dfs - 1) \
1636 { \
51ca9e29
JM
1637 _FP_FRAC_SRS_##swc (S, (_FP_WFRACBITS_##sfs \
1638 - _FP_WFRACBITS_##dfs), \
1639 _FP_WFRACBITS_##sfs); \
1640 _FP_FRAC_COPY_##dwc##_##swc (D, S); \
1e145589
JM
1641 } \
1642 else \
1643 { \
51ca9e29
JM
1644 _FP_FRAC_SET_##dwc (D, _FP_ZEROFRAC_##dwc); \
1645 _FP_FRAC_LOW_##dwc (D) |= 1; \
1e145589
JM
1646 } \
1647 } \
1648 } \
1649 else \
1650 { \
1651 D##_e = _FP_EXPMAX_##dfs; \
51ca9e29
JM
1652 if (_FP_FRAC_ZEROP_##swc (S)) \
1653 _FP_FRAC_SET_##dwc (D, _FP_ZEROFRAC_##dwc); \
1e145589
JM
1654 else \
1655 { \
51ca9e29
JM
1656 _FP_CHECK_SIGNAN_SEMIRAW (sfs, swc, S); \
1657 _FP_FRAC_SRL_##swc (S, (_FP_WFRACBITS_##sfs \
1658 - _FP_WFRACBITS_##dfs)); \
1659 _FP_FRAC_COPY_##dwc##_##swc (D, S); \
1e145589 1660 /* Semi-raw NaN must have all workbits cleared. */ \
51ca9e29 1661 _FP_FRAC_LOW_##dwc (D) \
1e145589 1662 &= ~(_FP_W_TYPE) ((1 << _FP_WORKBITS) - 1); \
51ca9e29 1663 _FP_SETQNAN_SEMIRAW (dfs, dwc, D); \
1e145589
JM
1664 } \
1665 } \
1666 } \
1667 } \
1668 while (0)
d876f532 1669
c4fe3ea7 1670/* Helper primitives. */
d876f532
UD
1671
1672/* Count leading zeros in a word. */
1673
1674#ifndef __FP_CLZ
0d86378f 1675/* GCC 3.4 and later provide the builtins for us. */
1e145589
JM
1676# define __FP_CLZ(r, x) \
1677 do \
1678 { \
1679 if (sizeof (_FP_W_TYPE) == sizeof (unsigned int)) \
1680 r = __builtin_clz (x); \
1681 else if (sizeof (_FP_W_TYPE) == sizeof (unsigned long)) \
1682 r = __builtin_clzl (x); \
1683 else if (sizeof (_FP_W_TYPE) == sizeof (unsigned long long)) \
1684 r = __builtin_clzll (x); \
1685 else \
1686 abort (); \
1687 } \
1688 while (0)
d876f532
UD
1689#endif /* ndef __FP_CLZ */
1690
1691#define _FP_DIV_HELP_imm(q, r, n, d) \
1e145589
JM
1692 do \
1693 { \
1694 q = n / d, r = n % d; \
1695 } \
1696 while (0)
d876f532 1697
1a8aaf91
UD
1698
1699/* A restoring bit-by-bit division primitive. */
1700
1701#define _FP_DIV_MEAT_N_loop(fs, wc, R, X, Y) \
1e145589
JM
1702 do \
1703 { \
9c37ec0b
JM
1704 int _FP_DIV_MEAT_N_loop_count = _FP_WFRACBITS_##fs; \
1705 _FP_FRAC_DECL_##wc (_FP_DIV_MEAT_N_loop_u); \
1706 _FP_FRAC_DECL_##wc (_FP_DIV_MEAT_N_loop_v); \
1707 _FP_FRAC_COPY_##wc (_FP_DIV_MEAT_N_loop_u, X); \
1708 _FP_FRAC_COPY_##wc (_FP_DIV_MEAT_N_loop_v, Y); \
1e145589 1709 _FP_FRAC_SET_##wc (R, _FP_ZEROFRAC_##wc); \
9c37ec0b
JM
1710 /* Normalize _FP_DIV_MEAT_N_LOOP_U and _FP_DIV_MEAT_N_LOOP_V. */ \
1711 _FP_FRAC_SLL_##wc (_FP_DIV_MEAT_N_loop_u, _FP_WFRACXBITS_##fs); \
1712 _FP_FRAC_SLL_##wc (_FP_DIV_MEAT_N_loop_v, _FP_WFRACXBITS_##fs); \
1e145589
JM
1713 /* First round. Since the operands are normalized, either the \
1714 first or second bit will be set in the fraction. Produce a \
1715 normalized result by checking which and adjusting the loop \
1716 count and exponent accordingly. */ \
9c37ec0b 1717 if (_FP_FRAC_GE_1 (_FP_DIV_MEAT_N_loop_u, _FP_DIV_MEAT_N_loop_v)) \
1a8aaf91 1718 { \
9c37ec0b
JM
1719 _FP_FRAC_SUB_##wc (_FP_DIV_MEAT_N_loop_u, \
1720 _FP_DIV_MEAT_N_loop_u, \
1721 _FP_DIV_MEAT_N_loop_v); \
1a8aaf91 1722 _FP_FRAC_LOW_##wc (R) |= 1; \
9c37ec0b 1723 _FP_DIV_MEAT_N_loop_count--; \
1a8aaf91 1724 } \
1e145589
JM
1725 else \
1726 R##_e--; \
1727 /* Subsequent rounds. */ \
1728 do \
1729 { \
9c37ec0b
JM
1730 int _FP_DIV_MEAT_N_loop_msb \
1731 = (_FP_WS_TYPE) _FP_FRAC_HIGH_##wc (_FP_DIV_MEAT_N_loop_u) < 0; \
1732 _FP_FRAC_SLL_##wc (_FP_DIV_MEAT_N_loop_u, 1); \
1e145589 1733 _FP_FRAC_SLL_##wc (R, 1); \
9c37ec0b
JM
1734 if (_FP_DIV_MEAT_N_loop_msb \
1735 || _FP_FRAC_GE_1 (_FP_DIV_MEAT_N_loop_u, \
1736 _FP_DIV_MEAT_N_loop_v)) \
1e145589 1737 { \
9c37ec0b
JM
1738 _FP_FRAC_SUB_##wc (_FP_DIV_MEAT_N_loop_u, \
1739 _FP_DIV_MEAT_N_loop_u, \
1740 _FP_DIV_MEAT_N_loop_v); \
1e145589
JM
1741 _FP_FRAC_LOW_##wc (R) |= 1; \
1742 } \
1743 } \
9c37ec0b
JM
1744 while (--_FP_DIV_MEAT_N_loop_count > 0); \
1745 /* If there's anything left in _FP_DIV_MEAT_N_LOOP_U, the result \
1746 is inexact. */ \
1747 _FP_FRAC_LOW_##wc (R) \
1748 |= !_FP_FRAC_ZEROP_##wc (_FP_DIV_MEAT_N_loop_u); \
1e145589
JM
1749 } \
1750 while (0)
1a8aaf91
UD
1751
1752#define _FP_DIV_MEAT_1_loop(fs, R, X, Y) _FP_DIV_MEAT_N_loop (fs, 1, R, X, Y)
1753#define _FP_DIV_MEAT_2_loop(fs, R, X, Y) _FP_DIV_MEAT_N_loop (fs, 2, R, X, Y)
1754#define _FP_DIV_MEAT_4_loop(fs, R, X, Y) _FP_DIV_MEAT_N_loop (fs, 4, R, X, Y)