]>
Commit | Line | Data |
---|---|---|
d876f532 | 1 | /* Software floating-point emulation. Common operations. |
b168057a | 2 | Copyright (C) 1997-2015 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 | 65 | X##_c = FP_CLS_ZERO; \ |
454ac701 JM |
66 | else if (FP_DENORM_ZERO) \ |
67 | { \ | |
68 | X##_c = FP_CLS_ZERO; \ | |
69 | _FP_FRAC_SET_##wc (X, _FP_ZEROFRAC_##wc); \ | |
70 | FP_SET_EXCEPTION (FP_EX_DENORM); \ | |
71 | } \ | |
1e145589 JM |
72 | else \ |
73 | { \ | |
c4fe3ea7 | 74 | /* A denormalized number. */ \ |
9c37ec0b JM |
75 | _FP_I_TYPE _FP_UNPACK_CANONICAL_shift; \ |
76 | _FP_FRAC_CLZ_##wc (_FP_UNPACK_CANONICAL_shift, \ | |
77 | X); \ | |
78 | _FP_UNPACK_CANONICAL_shift -= _FP_FRACXBITS_##fs; \ | |
79 | _FP_FRAC_SLL_##wc (X, (_FP_UNPACK_CANONICAL_shift \ | |
80 | + _FP_WORKBITS)); \ | |
81 | X##_e -= (_FP_EXPBIAS_##fs - 1 \ | |
82 | + _FP_UNPACK_CANONICAL_shift); \ | |
1e145589 | 83 | X##_c = FP_CLS_NORMAL; \ |
51ca9e29 | 84 | FP_SET_EXCEPTION (FP_EX_DENORM); \ |
1e145589 JM |
85 | } \ |
86 | break; \ | |
87 | \ | |
88 | case _FP_EXPMAX_##fs: \ | |
51ca9e29 | 89 | if (_FP_FRAC_ZEROP_##wc (X)) \ |
1e145589 JM |
90 | X##_c = FP_CLS_INF; \ |
91 | else \ | |
92 | { \ | |
93 | X##_c = FP_CLS_NAN; \ | |
c4fe3ea7 | 94 | /* Check for signaling NaN. */ \ |
51ca9e29 | 95 | if (_FP_FRAC_SNANP (fs, X)) \ |
ff12c11f JM |
96 | FP_SET_EXCEPTION (FP_EX_INVALID \ |
97 | | FP_EX_INVALID_SNAN); \ | |
1e145589 JM |
98 | } \ |
99 | break; \ | |
100 | } \ | |
101 | } \ | |
102 | while (0) | |
d876f532 | 103 | |
fe0b1e85 RM |
104 | /* Finish unpacking an fp value in semi-raw mode: the mantissa is |
105 | shifted by _FP_WORKBITS but the implicit MSB is not inserted and | |
106 | other classification is not done. */ | |
51ca9e29 | 107 | #define _FP_UNPACK_SEMIRAW(fs, wc, X) _FP_FRAC_SLL_##wc (X, _FP_WORKBITS) |
fe0b1e85 | 108 | |
454ac701 JM |
109 | /* Check whether a raw or semi-raw input value should be flushed to |
110 | zero, and flush it to zero if so. */ | |
111 | #define _FP_CHECK_FLUSH_ZERO(fs, wc, X) \ | |
112 | do \ | |
113 | { \ | |
114 | if (FP_DENORM_ZERO \ | |
115 | && X##_e == 0 \ | |
116 | && !_FP_FRAC_ZEROP_##wc (X)) \ | |
117 | { \ | |
118 | _FP_FRAC_SET_##wc (X, _FP_ZEROFRAC_##wc); \ | |
119 | FP_SET_EXCEPTION (FP_EX_DENORM); \ | |
120 | } \ | |
121 | } \ | |
122 | while (0) | |
123 | ||
fe0b1e85 RM |
124 | /* A semi-raw value has overflowed to infinity. Adjust the mantissa |
125 | and exponent appropriately. */ | |
126 | #define _FP_OVERFLOW_SEMIRAW(fs, wc, X) \ | |
1e145589 | 127 | do \ |
fe0b1e85 | 128 | { \ |
1e145589 JM |
129 | if (FP_ROUNDMODE == FP_RND_NEAREST \ |
130 | || (FP_ROUNDMODE == FP_RND_PINF && !X##_s) \ | |
131 | || (FP_ROUNDMODE == FP_RND_MINF && X##_s)) \ | |
132 | { \ | |
133 | X##_e = _FP_EXPMAX_##fs; \ | |
51ca9e29 | 134 | _FP_FRAC_SET_##wc (X, _FP_ZEROFRAC_##wc); \ |
1e145589 JM |
135 | } \ |
136 | else \ | |
137 | { \ | |
138 | X##_e = _FP_EXPMAX_##fs - 1; \ | |
51ca9e29 | 139 | _FP_FRAC_SET_##wc (X, _FP_MAXFRAC_##wc); \ |
1e145589 | 140 | } \ |
51ca9e29 JM |
141 | FP_SET_EXCEPTION (FP_EX_INEXACT); \ |
142 | FP_SET_EXCEPTION (FP_EX_OVERFLOW); \ | |
fe0b1e85 | 143 | } \ |
1e145589 | 144 | while (0) |
fe0b1e85 RM |
145 | |
146 | /* Check for a semi-raw value being a signaling NaN and raise the | |
147 | invalid exception if so. */ | |
ff12c11f JM |
148 | #define _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, X) \ |
149 | do \ | |
150 | { \ | |
151 | if (X##_e == _FP_EXPMAX_##fs \ | |
152 | && !_FP_FRAC_ZEROP_##wc (X) \ | |
153 | && _FP_FRAC_SNANP_SEMIRAW (fs, X)) \ | |
154 | FP_SET_EXCEPTION (FP_EX_INVALID | FP_EX_INVALID_SNAN); \ | |
155 | } \ | |
1e145589 | 156 | while (0) |
fe0b1e85 RM |
157 | |
158 | /* Choose a NaN result from an operation on two semi-raw NaN | |
159 | values. */ | |
160 | #define _FP_CHOOSENAN_SEMIRAW(fs, wc, R, X, Y, OP) \ | |
1e145589 JM |
161 | do \ |
162 | { \ | |
163 | /* _FP_CHOOSENAN expects raw values, so shift as required. */ \ | |
51ca9e29 JM |
164 | _FP_FRAC_SRL_##wc (X, _FP_WORKBITS); \ |
165 | _FP_FRAC_SRL_##wc (Y, _FP_WORKBITS); \ | |
166 | _FP_CHOOSENAN (fs, wc, R, X, Y, OP); \ | |
167 | _FP_FRAC_SLL_##wc (R, _FP_WORKBITS); \ | |
1e145589 JM |
168 | } \ |
169 | while (0) | |
fe0b1e85 | 170 | |
2848b105 MR |
171 | /* Make the fractional part a quiet NaN, preserving the payload |
172 | if possible, otherwise make it the canonical quiet NaN and set | |
173 | the sign bit accordingly. */ | |
1e145589 JM |
174 | #define _FP_SETQNAN(fs, wc, X) \ |
175 | do \ | |
176 | { \ | |
177 | if (_FP_QNANNEGATEDP) \ | |
178 | { \ | |
51ca9e29 JM |
179 | _FP_FRAC_HIGH_RAW_##fs (X) &= _FP_QNANBIT_##fs - 1; \ |
180 | if (_FP_FRAC_ZEROP_##wc (X)) \ | |
1e145589 JM |
181 | { \ |
182 | X##_s = _FP_NANSIGN_##fs; \ | |
51ca9e29 | 183 | _FP_FRAC_SET_##wc (X, _FP_NANFRAC_##fs); \ |
1e145589 JM |
184 | } \ |
185 | } \ | |
186 | else \ | |
51ca9e29 | 187 | _FP_FRAC_HIGH_RAW_##fs (X) |= _FP_QNANBIT_##fs; \ |
1e145589 JM |
188 | } \ |
189 | while (0) | |
190 | #define _FP_SETQNAN_SEMIRAW(fs, wc, X) \ | |
191 | do \ | |
192 | { \ | |
193 | if (_FP_QNANNEGATEDP) \ | |
194 | { \ | |
51ca9e29 JM |
195 | _FP_FRAC_HIGH_##fs (X) &= _FP_QNANBIT_SH_##fs - 1; \ |
196 | if (_FP_FRAC_ZEROP_##wc (X)) \ | |
1e145589 JM |
197 | { \ |
198 | X##_s = _FP_NANSIGN_##fs; \ | |
51ca9e29 JM |
199 | _FP_FRAC_SET_##wc (X, _FP_NANFRAC_##fs); \ |
200 | _FP_FRAC_SLL_##wc (X, _FP_WORKBITS); \ | |
1e145589 JM |
201 | } \ |
202 | } \ | |
203 | else \ | |
51ca9e29 | 204 | _FP_FRAC_HIGH_##fs (X) |= _FP_QNANBIT_SH_##fs; \ |
1e145589 JM |
205 | } \ |
206 | while (0) | |
2848b105 | 207 | |
fe0b1e85 RM |
208 | /* Test whether a biased exponent is normal (not zero or maximum). */ |
209 | #define _FP_EXP_NORMAL(fs, wc, X) (((X##_e + 1) & _FP_EXPMAX_##fs) > 1) | |
210 | ||
211 | /* Prepare to pack an fp value in semi-raw mode: the mantissa is | |
212 | rounded and shifted right, with the rounding possibly increasing | |
213 | the exponent (including changing a finite value to infinity). */ | |
214 | #define _FP_PACK_SEMIRAW(fs, wc, X) \ | |
1e145589 JM |
215 | do \ |
216 | { \ | |
ace614b8 JM |
217 | int _FP_PACK_SEMIRAW_is_tiny \ |
218 | = X##_e == 0 && !_FP_FRAC_ZEROP_##wc (X); \ | |
219 | if (_FP_TININESS_AFTER_ROUNDING \ | |
220 | && _FP_PACK_SEMIRAW_is_tiny) \ | |
221 | { \ | |
222 | FP_DECL_##fs (_FP_PACK_SEMIRAW_T); \ | |
223 | _FP_FRAC_COPY_##wc (_FP_PACK_SEMIRAW_T, X); \ | |
224 | _FP_PACK_SEMIRAW_T##_s = X##_s; \ | |
225 | _FP_PACK_SEMIRAW_T##_e = X##_e; \ | |
226 | _FP_FRAC_SLL_##wc (_FP_PACK_SEMIRAW_T, 1); \ | |
227 | _FP_ROUND (wc, _FP_PACK_SEMIRAW_T); \ | |
228 | if (_FP_FRAC_OVERP_##wc (fs, _FP_PACK_SEMIRAW_T)) \ | |
229 | _FP_PACK_SEMIRAW_is_tiny = 0; \ | |
230 | } \ | |
51ca9e29 | 231 | _FP_ROUND (wc, X); \ |
ace614b8 | 232 | if (_FP_PACK_SEMIRAW_is_tiny) \ |
1e145589 | 233 | { \ |
47594329 MS |
234 | if ((FP_CUR_EXCEPTIONS & FP_EX_INEXACT) \ |
235 | || (FP_TRAPPING_EXCEPTIONS & FP_EX_UNDERFLOW)) \ | |
51ca9e29 | 236 | FP_SET_EXCEPTION (FP_EX_UNDERFLOW); \ |
1e145589 | 237 | } \ |
51ca9e29 | 238 | if (_FP_FRAC_HIGH_##fs (X) \ |
1e145589 | 239 | & (_FP_OVERFLOW_##fs >> 1)) \ |
ae251b0b | 240 | { \ |
51ca9e29 | 241 | _FP_FRAC_HIGH_##fs (X) &= ~(_FP_OVERFLOW_##fs >> 1); \ |
1e145589 JM |
242 | X##_e++; \ |
243 | if (X##_e == _FP_EXPMAX_##fs) \ | |
51ca9e29 | 244 | _FP_OVERFLOW_SEMIRAW (fs, wc, X); \ |
1e145589 | 245 | } \ |
51ca9e29 JM |
246 | _FP_FRAC_SRL_##wc (X, _FP_WORKBITS); \ |
247 | if (X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc (X)) \ | |
1e145589 JM |
248 | { \ |
249 | if (!_FP_KEEPNANFRACP) \ | |
250 | { \ | |
51ca9e29 | 251 | _FP_FRAC_SET_##wc (X, _FP_NANFRAC_##fs); \ |
1e145589 JM |
252 | X##_s = _FP_NANSIGN_##fs; \ |
253 | } \ | |
254 | else \ | |
51ca9e29 | 255 | _FP_SETQNAN (fs, wc, X); \ |
ae251b0b | 256 | } \ |
fe0b1e85 | 257 | } \ |
1e145589 | 258 | while (0) |
fe0b1e85 | 259 | |
c4fe3ea7 JM |
260 | /* Before packing the bits back into the native fp result, take care |
261 | of such mundane things as rounding and overflow. Also, for some | |
262 | kinds of fp values, the original parts may not have been fully | |
263 | extracted -- but that is ok, we can regenerate them now. */ | |
d876f532 | 264 | |
1e145589 JM |
265 | #define _FP_PACK_CANONICAL(fs, wc, X) \ |
266 | do \ | |
267 | { \ | |
268 | switch (X##_c) \ | |
269 | { \ | |
270 | case FP_CLS_NORMAL: \ | |
271 | X##_e += _FP_EXPBIAS_##fs; \ | |
272 | if (X##_e > 0) \ | |
273 | { \ | |
51ca9e29 JM |
274 | _FP_ROUND (wc, X); \ |
275 | if (_FP_FRAC_OVERP_##wc (fs, X)) \ | |
1e145589 | 276 | { \ |
51ca9e29 | 277 | _FP_FRAC_CLEAR_OVERP_##wc (fs, X); \ |
1e145589 JM |
278 | X##_e++; \ |
279 | } \ | |
51ca9e29 | 280 | _FP_FRAC_SRL_##wc (X, _FP_WORKBITS); \ |
1e145589 JM |
281 | if (X##_e >= _FP_EXPMAX_##fs) \ |
282 | { \ | |
c4fe3ea7 | 283 | /* Overflow. */ \ |
1e145589 JM |
284 | switch (FP_ROUNDMODE) \ |
285 | { \ | |
286 | case FP_RND_NEAREST: \ | |
287 | X##_c = FP_CLS_INF; \ | |
288 | break; \ | |
289 | case FP_RND_PINF: \ | |
290 | if (!X##_s) \ | |
291 | X##_c = FP_CLS_INF; \ | |
292 | break; \ | |
293 | case FP_RND_MINF: \ | |
294 | if (X##_s) \ | |
295 | X##_c = FP_CLS_INF; \ | |
296 | break; \ | |
297 | } \ | |
298 | if (X##_c == FP_CLS_INF) \ | |
299 | { \ | |
c4fe3ea7 | 300 | /* Overflow to infinity. */ \ |
1e145589 | 301 | X##_e = _FP_EXPMAX_##fs; \ |
51ca9e29 | 302 | _FP_FRAC_SET_##wc (X, _FP_ZEROFRAC_##wc); \ |
1e145589 JM |
303 | } \ |
304 | else \ | |
305 | { \ | |
c4fe3ea7 | 306 | /* Overflow to maximum normal. */ \ |
1e145589 | 307 | X##_e = _FP_EXPMAX_##fs - 1; \ |
51ca9e29 | 308 | _FP_FRAC_SET_##wc (X, _FP_MAXFRAC_##wc); \ |
1e145589 | 309 | } \ |
51ca9e29 JM |
310 | FP_SET_EXCEPTION (FP_EX_OVERFLOW); \ |
311 | FP_SET_EXCEPTION (FP_EX_INEXACT); \ | |
1e145589 JM |
312 | } \ |
313 | } \ | |
314 | else \ | |
315 | { \ | |
c4fe3ea7 | 316 | /* We've got a denormalized number. */ \ |
ace614b8 JM |
317 | int _FP_PACK_CANONICAL_is_tiny = 1; \ |
318 | if (_FP_TININESS_AFTER_ROUNDING && X##_e == 0) \ | |
319 | { \ | |
320 | FP_DECL_##fs (_FP_PACK_CANONICAL_T); \ | |
321 | _FP_FRAC_COPY_##wc (_FP_PACK_CANONICAL_T, X); \ | |
322 | _FP_PACK_CANONICAL_T##_s = X##_s; \ | |
323 | _FP_PACK_CANONICAL_T##_e = X##_e; \ | |
324 | _FP_ROUND (wc, _FP_PACK_CANONICAL_T); \ | |
325 | if (_FP_FRAC_OVERP_##wc (fs, _FP_PACK_CANONICAL_T)) \ | |
326 | _FP_PACK_CANONICAL_is_tiny = 0; \ | |
327 | } \ | |
1e145589 JM |
328 | X##_e = -X##_e + 1; \ |
329 | if (X##_e <= _FP_WFRACBITS_##fs) \ | |
330 | { \ | |
51ca9e29 JM |
331 | _FP_FRAC_SRS_##wc (X, X##_e, _FP_WFRACBITS_##fs); \ |
332 | _FP_ROUND (wc, X); \ | |
333 | if (_FP_FRAC_HIGH_##fs (X) \ | |
1e145589 JM |
334 | & (_FP_OVERFLOW_##fs >> 1)) \ |
335 | { \ | |
336 | X##_e = 1; \ | |
51ca9e29 JM |
337 | _FP_FRAC_SET_##wc (X, _FP_ZEROFRAC_##wc); \ |
338 | FP_SET_EXCEPTION (FP_EX_INEXACT); \ | |
1e145589 JM |
339 | } \ |
340 | else \ | |
341 | { \ | |
342 | X##_e = 0; \ | |
51ca9e29 | 343 | _FP_FRAC_SRL_##wc (X, _FP_WORKBITS); \ |
1e145589 | 344 | } \ |
ace614b8 JM |
345 | if (_FP_PACK_CANONICAL_is_tiny \ |
346 | && ((FP_CUR_EXCEPTIONS & FP_EX_INEXACT) \ | |
347 | || (FP_TRAPPING_EXCEPTIONS \ | |
348 | & FP_EX_UNDERFLOW))) \ | |
51ca9e29 | 349 | FP_SET_EXCEPTION (FP_EX_UNDERFLOW); \ |
1e145589 JM |
350 | } \ |
351 | else \ | |
352 | { \ | |
c4fe3ea7 | 353 | /* Underflow to zero. */ \ |
1e145589 | 354 | X##_e = 0; \ |
51ca9e29 | 355 | if (!_FP_FRAC_ZEROP_##wc (X)) \ |
1e145589 | 356 | { \ |
51ca9e29 JM |
357 | _FP_FRAC_SET_##wc (X, _FP_MINFRAC_##wc); \ |
358 | _FP_ROUND (wc, X); \ | |
359 | _FP_FRAC_LOW_##wc (X) >>= (_FP_WORKBITS); \ | |
1e145589 | 360 | } \ |
51ca9e29 | 361 | FP_SET_EXCEPTION (FP_EX_UNDERFLOW); \ |
1e145589 JM |
362 | } \ |
363 | } \ | |
364 | break; \ | |
365 | \ | |
366 | case FP_CLS_ZERO: \ | |
367 | X##_e = 0; \ | |
51ca9e29 | 368 | _FP_FRAC_SET_##wc (X, _FP_ZEROFRAC_##wc); \ |
1e145589 JM |
369 | break; \ |
370 | \ | |
371 | case FP_CLS_INF: \ | |
372 | X##_e = _FP_EXPMAX_##fs; \ | |
51ca9e29 | 373 | _FP_FRAC_SET_##wc (X, _FP_ZEROFRAC_##wc); \ |
1e145589 JM |
374 | break; \ |
375 | \ | |
376 | case FP_CLS_NAN: \ | |
377 | X##_e = _FP_EXPMAX_##fs; \ | |
378 | if (!_FP_KEEPNANFRACP) \ | |
379 | { \ | |
51ca9e29 | 380 | _FP_FRAC_SET_##wc (X, _FP_NANFRAC_##fs); \ |
1e145589 JM |
381 | X##_s = _FP_NANSIGN_##fs; \ |
382 | } \ | |
383 | else \ | |
51ca9e29 | 384 | _FP_SETQNAN (fs, wc, X); \ |
1e145589 JM |
385 | break; \ |
386 | } \ | |
387 | } \ | |
388 | while (0) | |
d876f532 UD |
389 | |
390 | /* This one accepts raw argument and not cooked, returns | |
c4fe3ea7 | 391 | 1 if X is a signaling NaN. */ |
1e145589 JM |
392 | #define _FP_ISSIGNAN(fs, wc, X) \ |
393 | ({ \ | |
9c37ec0b | 394 | int _FP_ISSIGNAN_ret = 0; \ |
1e145589 JM |
395 | if (X##_e == _FP_EXPMAX_##fs) \ |
396 | { \ | |
51ca9e29 JM |
397 | if (!_FP_FRAC_ZEROP_##wc (X) \ |
398 | && _FP_FRAC_SNANP (fs, X)) \ | |
9c37ec0b | 399 | _FP_ISSIGNAN_ret = 1; \ |
1e145589 | 400 | } \ |
9c37ec0b | 401 | _FP_ISSIGNAN_ret; \ |
1e145589 | 402 | }) |
d876f532 UD |
403 | |
404 | ||
405 | ||
406 | ||
407 | ||
fe0b1e85 | 408 | /* Addition on semi-raw values. */ |
1e145589 JM |
409 | #define _FP_ADD_INTERNAL(fs, wc, R, X, Y, OP) \ |
410 | do \ | |
411 | { \ | |
454ac701 JM |
412 | _FP_CHECK_FLUSH_ZERO (fs, wc, X); \ |
413 | _FP_CHECK_FLUSH_ZERO (fs, wc, Y); \ | |
1e145589 JM |
414 | if (X##_s == Y##_s) \ |
415 | { \ | |
416 | /* Addition. */ \ | |
d7423856 | 417 | __label__ add1, add2, add3, add_done; \ |
1e145589 | 418 | R##_s = X##_s; \ |
9c37ec0b JM |
419 | int _FP_ADD_INTERNAL_ediff = X##_e - Y##_e; \ |
420 | if (_FP_ADD_INTERNAL_ediff > 0) \ | |
1e145589 JM |
421 | { \ |
422 | R##_e = X##_e; \ | |
423 | if (Y##_e == 0) \ | |
424 | { \ | |
425 | /* Y is zero or denormalized. */ \ | |
51ca9e29 | 426 | if (_FP_FRAC_ZEROP_##wc (Y)) \ |
1e145589 | 427 | { \ |
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 | else \ | |
433 | { \ | |
51ca9e29 | 434 | FP_SET_EXCEPTION (FP_EX_DENORM); \ |
9c37ec0b JM |
435 | _FP_ADD_INTERNAL_ediff--; \ |
436 | if (_FP_ADD_INTERNAL_ediff == 0) \ | |
1e145589 | 437 | { \ |
51ca9e29 | 438 | _FP_FRAC_ADD_##wc (R, X, Y); \ |
1e145589 JM |
439 | goto add3; \ |
440 | } \ | |
441 | if (X##_e == _FP_EXPMAX_##fs) \ | |
442 | { \ | |
51ca9e29 JM |
443 | _FP_CHECK_SIGNAN_SEMIRAW (fs, wc, X); \ |
444 | _FP_FRAC_COPY_##wc (R, X); \ | |
1e145589 JM |
445 | goto add_done; \ |
446 | } \ | |
447 | goto add1; \ | |
448 | } \ | |
449 | } \ | |
450 | else if (X##_e == _FP_EXPMAX_##fs) \ | |
451 | { \ | |
452 | /* X is NaN or Inf, Y is normal. */ \ | |
51ca9e29 JM |
453 | _FP_CHECK_SIGNAN_SEMIRAW (fs, wc, X); \ |
454 | _FP_FRAC_COPY_##wc (R, X); \ | |
1e145589 JM |
455 | goto add_done; \ |
456 | } \ | |
457 | \ | |
458 | /* Insert implicit MSB of Y. */ \ | |
51ca9e29 | 459 | _FP_FRAC_HIGH_##fs (Y) |= _FP_IMPLBIT_SH_##fs; \ |
1e145589 JM |
460 | \ |
461 | add1: \ | |
9c37ec0b JM |
462 | /* Shift the mantissa of Y to the right \ |
463 | _FP_ADD_INTERNAL_EDIFF steps; remember to account \ | |
464 | later for the implicit MSB of X. */ \ | |
465 | if (_FP_ADD_INTERNAL_ediff <= _FP_WFRACBITS_##fs) \ | |
466 | _FP_FRAC_SRS_##wc (Y, _FP_ADD_INTERNAL_ediff, \ | |
467 | _FP_WFRACBITS_##fs); \ | |
51ca9e29 JM |
468 | else if (!_FP_FRAC_ZEROP_##wc (Y)) \ |
469 | _FP_FRAC_SET_##wc (Y, _FP_MINFRAC_##wc); \ | |
470 | _FP_FRAC_ADD_##wc (R, X, Y); \ | |
1e145589 | 471 | } \ |
9c37ec0b | 472 | else if (_FP_ADD_INTERNAL_ediff < 0) \ |
1e145589 | 473 | { \ |
9c37ec0b | 474 | _FP_ADD_INTERNAL_ediff = -_FP_ADD_INTERNAL_ediff; \ |
1e145589 JM |
475 | R##_e = Y##_e; \ |
476 | if (X##_e == 0) \ | |
477 | { \ | |
478 | /* X is zero or denormalized. */ \ | |
51ca9e29 | 479 | if (_FP_FRAC_ZEROP_##wc (X)) \ |
1e145589 | 480 | { \ |
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 | else \ | |
486 | { \ | |
51ca9e29 | 487 | FP_SET_EXCEPTION (FP_EX_DENORM); \ |
9c37ec0b JM |
488 | _FP_ADD_INTERNAL_ediff--; \ |
489 | if (_FP_ADD_INTERNAL_ediff == 0) \ | |
1e145589 | 490 | { \ |
51ca9e29 | 491 | _FP_FRAC_ADD_##wc (R, Y, X); \ |
1e145589 JM |
492 | goto add3; \ |
493 | } \ | |
494 | if (Y##_e == _FP_EXPMAX_##fs) \ | |
495 | { \ | |
51ca9e29 JM |
496 | _FP_CHECK_SIGNAN_SEMIRAW (fs, wc, Y); \ |
497 | _FP_FRAC_COPY_##wc (R, Y); \ | |
1e145589 JM |
498 | goto add_done; \ |
499 | } \ | |
500 | goto add2; \ | |
501 | } \ | |
502 | } \ | |
503 | else if (Y##_e == _FP_EXPMAX_##fs) \ | |
504 | { \ | |
505 | /* Y is NaN or Inf, X is normal. */ \ | |
51ca9e29 JM |
506 | _FP_CHECK_SIGNAN_SEMIRAW (fs, wc, Y); \ |
507 | _FP_FRAC_COPY_##wc (R, Y); \ | |
1e145589 JM |
508 | goto add_done; \ |
509 | } \ | |
510 | \ | |
511 | /* Insert implicit MSB of X. */ \ | |
51ca9e29 | 512 | _FP_FRAC_HIGH_##fs (X) |= _FP_IMPLBIT_SH_##fs; \ |
1e145589 JM |
513 | \ |
514 | add2: \ | |
9c37ec0b JM |
515 | /* Shift the mantissa of X to the right \ |
516 | _FP_ADD_INTERNAL_EDIFF steps; remember to account \ | |
517 | later for the implicit MSB of Y. */ \ | |
518 | if (_FP_ADD_INTERNAL_ediff <= _FP_WFRACBITS_##fs) \ | |
519 | _FP_FRAC_SRS_##wc (X, _FP_ADD_INTERNAL_ediff, \ | |
520 | _FP_WFRACBITS_##fs); \ | |
51ca9e29 JM |
521 | else if (!_FP_FRAC_ZEROP_##wc (X)) \ |
522 | _FP_FRAC_SET_##wc (X, _FP_MINFRAC_##wc); \ | |
523 | _FP_FRAC_ADD_##wc (R, Y, X); \ | |
1e145589 JM |
524 | } \ |
525 | else \ | |
526 | { \ | |
9c37ec0b | 527 | /* _FP_ADD_INTERNAL_ediff == 0. */ \ |
51ca9e29 | 528 | if (!_FP_EXP_NORMAL (fs, wc, X)) \ |
1e145589 JM |
529 | { \ |
530 | if (X##_e == 0) \ | |
531 | { \ | |
532 | /* X and Y are zero or denormalized. */ \ | |
533 | R##_e = 0; \ | |
51ca9e29 | 534 | if (_FP_FRAC_ZEROP_##wc (X)) \ |
1e145589 | 535 | { \ |
51ca9e29 JM |
536 | if (!_FP_FRAC_ZEROP_##wc (Y)) \ |
537 | FP_SET_EXCEPTION (FP_EX_DENORM); \ | |
538 | _FP_FRAC_COPY_##wc (R, Y); \ | |
1e145589 JM |
539 | goto add_done; \ |
540 | } \ | |
51ca9e29 | 541 | else if (_FP_FRAC_ZEROP_##wc (Y)) \ |
1e145589 | 542 | { \ |
51ca9e29 JM |
543 | FP_SET_EXCEPTION (FP_EX_DENORM); \ |
544 | _FP_FRAC_COPY_##wc (R, X); \ | |
1e145589 JM |
545 | goto add_done; \ |
546 | } \ | |
547 | else \ | |
548 | { \ | |
51ca9e29 JM |
549 | FP_SET_EXCEPTION (FP_EX_DENORM); \ |
550 | _FP_FRAC_ADD_##wc (R, X, Y); \ | |
551 | if (_FP_FRAC_HIGH_##fs (R) & _FP_IMPLBIT_SH_##fs) \ | |
1e145589 JM |
552 | { \ |
553 | /* Normalized result. */ \ | |
51ca9e29 JM |
554 | _FP_FRAC_HIGH_##fs (R) \ |
555 | &= ~(_FP_W_TYPE) _FP_IMPLBIT_SH_##fs; \ | |
1e145589 JM |
556 | R##_e = 1; \ |
557 | } \ | |
558 | goto add_done; \ | |
559 | } \ | |
560 | } \ | |
561 | else \ | |
562 | { \ | |
563 | /* X and Y are NaN or Inf. */ \ | |
51ca9e29 JM |
564 | _FP_CHECK_SIGNAN_SEMIRAW (fs, wc, X); \ |
565 | _FP_CHECK_SIGNAN_SEMIRAW (fs, wc, Y); \ | |
1e145589 | 566 | R##_e = _FP_EXPMAX_##fs; \ |
51ca9e29 JM |
567 | if (_FP_FRAC_ZEROP_##wc (X)) \ |
568 | _FP_FRAC_COPY_##wc (R, Y); \ | |
569 | else if (_FP_FRAC_ZEROP_##wc (Y)) \ | |
570 | _FP_FRAC_COPY_##wc (R, X); \ | |
1e145589 | 571 | else \ |
51ca9e29 | 572 | _FP_CHOOSENAN_SEMIRAW (fs, wc, R, X, Y, OP); \ |
1e145589 JM |
573 | goto add_done; \ |
574 | } \ | |
575 | } \ | |
576 | /* The exponents of X and Y, both normal, are equal. The \ | |
577 | implicit MSBs will always add to increase the \ | |
578 | exponent. */ \ | |
51ca9e29 | 579 | _FP_FRAC_ADD_##wc (R, X, Y); \ |
1e145589 | 580 | R##_e = X##_e + 1; \ |
51ca9e29 | 581 | _FP_FRAC_SRS_##wc (R, 1, _FP_WFRACBITS_##fs); \ |
1e145589 JM |
582 | if (R##_e == _FP_EXPMAX_##fs) \ |
583 | /* Overflow to infinity (depending on rounding mode). */ \ | |
51ca9e29 | 584 | _FP_OVERFLOW_SEMIRAW (fs, wc, R); \ |
1e145589 JM |
585 | goto add_done; \ |
586 | } \ | |
587 | add3: \ | |
51ca9e29 | 588 | if (_FP_FRAC_HIGH_##fs (R) & _FP_IMPLBIT_SH_##fs) \ |
1e145589 JM |
589 | { \ |
590 | /* Overflow. */ \ | |
51ca9e29 | 591 | _FP_FRAC_HIGH_##fs (R) &= ~(_FP_W_TYPE) _FP_IMPLBIT_SH_##fs; \ |
1e145589 | 592 | R##_e++; \ |
51ca9e29 | 593 | _FP_FRAC_SRS_##wc (R, 1, _FP_WFRACBITS_##fs); \ |
1e145589 JM |
594 | if (R##_e == _FP_EXPMAX_##fs) \ |
595 | /* Overflow to infinity (depending on rounding mode). */ \ | |
51ca9e29 | 596 | _FP_OVERFLOW_SEMIRAW (fs, wc, R); \ |
1e145589 JM |
597 | } \ |
598 | add_done: ; \ | |
599 | } \ | |
600 | else \ | |
601 | { \ | |
602 | /* Subtraction. */ \ | |
d7423856 | 603 | __label__ sub1, sub2, sub3, norm, sub_done; \ |
9c37ec0b JM |
604 | int _FP_ADD_INTERNAL_ediff = X##_e - Y##_e; \ |
605 | if (_FP_ADD_INTERNAL_ediff > 0) \ | |
1e145589 JM |
606 | { \ |
607 | R##_e = X##_e; \ | |
608 | R##_s = X##_s; \ | |
609 | if (Y##_e == 0) \ | |
610 | { \ | |
611 | /* Y is zero or denormalized. */ \ | |
51ca9e29 | 612 | if (_FP_FRAC_ZEROP_##wc (Y)) \ |
1e145589 | 613 | { \ |
51ca9e29 JM |
614 | _FP_CHECK_SIGNAN_SEMIRAW (fs, wc, X); \ |
615 | _FP_FRAC_COPY_##wc (R, X); \ | |
1e145589 JM |
616 | goto sub_done; \ |
617 | } \ | |
618 | else \ | |
619 | { \ | |
51ca9e29 | 620 | FP_SET_EXCEPTION (FP_EX_DENORM); \ |
9c37ec0b JM |
621 | _FP_ADD_INTERNAL_ediff--; \ |
622 | if (_FP_ADD_INTERNAL_ediff == 0) \ | |
1e145589 | 623 | { \ |
51ca9e29 | 624 | _FP_FRAC_SUB_##wc (R, X, Y); \ |
1e145589 JM |
625 | goto sub3; \ |
626 | } \ | |
627 | if (X##_e == _FP_EXPMAX_##fs) \ | |
628 | { \ | |
51ca9e29 JM |
629 | _FP_CHECK_SIGNAN_SEMIRAW (fs, wc, X); \ |
630 | _FP_FRAC_COPY_##wc (R, X); \ | |
1e145589 JM |
631 | goto sub_done; \ |
632 | } \ | |
633 | goto sub1; \ | |
634 | } \ | |
635 | } \ | |
636 | else if (X##_e == _FP_EXPMAX_##fs) \ | |
637 | { \ | |
638 | /* X is NaN or Inf, Y is normal. */ \ | |
51ca9e29 JM |
639 | _FP_CHECK_SIGNAN_SEMIRAW (fs, wc, X); \ |
640 | _FP_FRAC_COPY_##wc (R, X); \ | |
1e145589 JM |
641 | goto sub_done; \ |
642 | } \ | |
643 | \ | |
644 | /* Insert implicit MSB of Y. */ \ | |
51ca9e29 | 645 | _FP_FRAC_HIGH_##fs (Y) |= _FP_IMPLBIT_SH_##fs; \ |
1e145589 JM |
646 | \ |
647 | sub1: \ | |
9c37ec0b JM |
648 | /* Shift the mantissa of Y to the right \ |
649 | _FP_ADD_INTERNAL_EDIFF steps; remember to account \ | |
650 | later for the implicit MSB of X. */ \ | |
651 | if (_FP_ADD_INTERNAL_ediff <= _FP_WFRACBITS_##fs) \ | |
652 | _FP_FRAC_SRS_##wc (Y, _FP_ADD_INTERNAL_ediff, \ | |
653 | _FP_WFRACBITS_##fs); \ | |
51ca9e29 JM |
654 | else if (!_FP_FRAC_ZEROP_##wc (Y)) \ |
655 | _FP_FRAC_SET_##wc (Y, _FP_MINFRAC_##wc); \ | |
656 | _FP_FRAC_SUB_##wc (R, X, Y); \ | |
1e145589 | 657 | } \ |
9c37ec0b | 658 | else if (_FP_ADD_INTERNAL_ediff < 0) \ |
1e145589 | 659 | { \ |
9c37ec0b | 660 | _FP_ADD_INTERNAL_ediff = -_FP_ADD_INTERNAL_ediff; \ |
1e145589 JM |
661 | R##_e = Y##_e; \ |
662 | R##_s = Y##_s; \ | |
663 | if (X##_e == 0) \ | |
664 | { \ | |
665 | /* X is zero or denormalized. */ \ | |
51ca9e29 | 666 | if (_FP_FRAC_ZEROP_##wc (X)) \ |
1e145589 | 667 | { \ |
51ca9e29 JM |
668 | _FP_CHECK_SIGNAN_SEMIRAW (fs, wc, Y); \ |
669 | _FP_FRAC_COPY_##wc (R, Y); \ | |
1e145589 JM |
670 | goto sub_done; \ |
671 | } \ | |
672 | else \ | |
673 | { \ | |
51ca9e29 | 674 | FP_SET_EXCEPTION (FP_EX_DENORM); \ |
9c37ec0b JM |
675 | _FP_ADD_INTERNAL_ediff--; \ |
676 | if (_FP_ADD_INTERNAL_ediff == 0) \ | |
1e145589 | 677 | { \ |
51ca9e29 | 678 | _FP_FRAC_SUB_##wc (R, Y, X); \ |
1e145589 JM |
679 | goto sub3; \ |
680 | } \ | |
681 | if (Y##_e == _FP_EXPMAX_##fs) \ | |
682 | { \ | |
51ca9e29 JM |
683 | _FP_CHECK_SIGNAN_SEMIRAW (fs, wc, Y); \ |
684 | _FP_FRAC_COPY_##wc (R, Y); \ | |
1e145589 JM |
685 | goto sub_done; \ |
686 | } \ | |
687 | goto sub2; \ | |
688 | } \ | |
689 | } \ | |
690 | else if (Y##_e == _FP_EXPMAX_##fs) \ | |
691 | { \ | |
692 | /* Y is NaN or Inf, X is normal. */ \ | |
51ca9e29 JM |
693 | _FP_CHECK_SIGNAN_SEMIRAW (fs, wc, Y); \ |
694 | _FP_FRAC_COPY_##wc (R, Y); \ | |
1e145589 JM |
695 | goto sub_done; \ |
696 | } \ | |
697 | \ | |
698 | /* Insert implicit MSB of X. */ \ | |
51ca9e29 | 699 | _FP_FRAC_HIGH_##fs (X) |= _FP_IMPLBIT_SH_##fs; \ |
1e145589 JM |
700 | \ |
701 | sub2: \ | |
9c37ec0b JM |
702 | /* Shift the mantissa of X to the right \ |
703 | _FP_ADD_INTERNAL_EDIFF steps; remember to account \ | |
704 | later for the implicit MSB of Y. */ \ | |
705 | if (_FP_ADD_INTERNAL_ediff <= _FP_WFRACBITS_##fs) \ | |
706 | _FP_FRAC_SRS_##wc (X, _FP_ADD_INTERNAL_ediff, \ | |
707 | _FP_WFRACBITS_##fs); \ | |
51ca9e29 JM |
708 | else if (!_FP_FRAC_ZEROP_##wc (X)) \ |
709 | _FP_FRAC_SET_##wc (X, _FP_MINFRAC_##wc); \ | |
710 | _FP_FRAC_SUB_##wc (R, Y, X); \ | |
1e145589 JM |
711 | } \ |
712 | else \ | |
713 | { \ | |
714 | /* ediff == 0. */ \ | |
51ca9e29 | 715 | if (!_FP_EXP_NORMAL (fs, wc, X)) \ |
1e145589 JM |
716 | { \ |
717 | if (X##_e == 0) \ | |
718 | { \ | |
719 | /* X and Y are zero or denormalized. */ \ | |
720 | R##_e = 0; \ | |
51ca9e29 | 721 | if (_FP_FRAC_ZEROP_##wc (X)) \ |
1e145589 | 722 | { \ |
51ca9e29 JM |
723 | _FP_FRAC_COPY_##wc (R, Y); \ |
724 | if (_FP_FRAC_ZEROP_##wc (Y)) \ | |
1e145589 JM |
725 | R##_s = (FP_ROUNDMODE == FP_RND_MINF); \ |
726 | else \ | |
727 | { \ | |
51ca9e29 | 728 | FP_SET_EXCEPTION (FP_EX_DENORM); \ |
1e145589 JM |
729 | R##_s = Y##_s; \ |
730 | } \ | |
731 | goto sub_done; \ | |
732 | } \ | |
51ca9e29 | 733 | else if (_FP_FRAC_ZEROP_##wc (Y)) \ |
1e145589 | 734 | { \ |
51ca9e29 JM |
735 | FP_SET_EXCEPTION (FP_EX_DENORM); \ |
736 | _FP_FRAC_COPY_##wc (R, X); \ | |
1e145589 JM |
737 | R##_s = X##_s; \ |
738 | goto sub_done; \ | |
739 | } \ | |
740 | else \ | |
741 | { \ | |
51ca9e29 JM |
742 | FP_SET_EXCEPTION (FP_EX_DENORM); \ |
743 | _FP_FRAC_SUB_##wc (R, X, Y); \ | |
1e145589 | 744 | R##_s = X##_s; \ |
51ca9e29 | 745 | if (_FP_FRAC_HIGH_##fs (R) & _FP_IMPLBIT_SH_##fs) \ |
1e145589 JM |
746 | { \ |
747 | /* |X| < |Y|, negate result. */ \ | |
51ca9e29 | 748 | _FP_FRAC_SUB_##wc (R, Y, X); \ |
1e145589 JM |
749 | R##_s = Y##_s; \ |
750 | } \ | |
51ca9e29 | 751 | else if (_FP_FRAC_ZEROP_##wc (R)) \ |
1e145589 JM |
752 | R##_s = (FP_ROUNDMODE == FP_RND_MINF); \ |
753 | goto sub_done; \ | |
754 | } \ | |
755 | } \ | |
756 | else \ | |
757 | { \ | |
758 | /* X and Y are NaN or Inf, of opposite signs. */ \ | |
51ca9e29 JM |
759 | _FP_CHECK_SIGNAN_SEMIRAW (fs, wc, X); \ |
760 | _FP_CHECK_SIGNAN_SEMIRAW (fs, wc, Y); \ | |
1e145589 | 761 | R##_e = _FP_EXPMAX_##fs; \ |
51ca9e29 | 762 | if (_FP_FRAC_ZEROP_##wc (X)) \ |
1e145589 | 763 | { \ |
51ca9e29 | 764 | if (_FP_FRAC_ZEROP_##wc (Y)) \ |
1e145589 JM |
765 | { \ |
766 | /* Inf - Inf. */ \ | |
767 | R##_s = _FP_NANSIGN_##fs; \ | |
51ca9e29 JM |
768 | _FP_FRAC_SET_##wc (R, _FP_NANFRAC_##fs); \ |
769 | _FP_FRAC_SLL_##wc (R, _FP_WORKBITS); \ | |
ff12c11f JM |
770 | FP_SET_EXCEPTION (FP_EX_INVALID \ |
771 | | FP_EX_INVALID_ISI); \ | |
1e145589 JM |
772 | } \ |
773 | else \ | |
774 | { \ | |
775 | /* Inf - NaN. */ \ | |
776 | R##_s = Y##_s; \ | |
51ca9e29 | 777 | _FP_FRAC_COPY_##wc (R, Y); \ |
1e145589 JM |
778 | } \ |
779 | } \ | |
780 | else \ | |
781 | { \ | |
51ca9e29 | 782 | if (_FP_FRAC_ZEROP_##wc (Y)) \ |
1e145589 JM |
783 | { \ |
784 | /* NaN - Inf. */ \ | |
785 | R##_s = X##_s; \ | |
51ca9e29 | 786 | _FP_FRAC_COPY_##wc (R, X); \ |
1e145589 JM |
787 | } \ |
788 | else \ | |
789 | { \ | |
790 | /* NaN - NaN. */ \ | |
51ca9e29 | 791 | _FP_CHOOSENAN_SEMIRAW (fs, wc, R, X, Y, OP); \ |
1e145589 JM |
792 | } \ |
793 | } \ | |
794 | goto sub_done; \ | |
795 | } \ | |
796 | } \ | |
797 | /* The exponents of X and Y, both normal, are equal. The \ | |
798 | implicit MSBs cancel. */ \ | |
799 | R##_e = X##_e; \ | |
51ca9e29 | 800 | _FP_FRAC_SUB_##wc (R, X, Y); \ |
1e145589 | 801 | R##_s = X##_s; \ |
51ca9e29 | 802 | if (_FP_FRAC_HIGH_##fs (R) & _FP_IMPLBIT_SH_##fs) \ |
1e145589 JM |
803 | { \ |
804 | /* |X| < |Y|, negate result. */ \ | |
51ca9e29 | 805 | _FP_FRAC_SUB_##wc (R, Y, X); \ |
1e145589 JM |
806 | R##_s = Y##_s; \ |
807 | } \ | |
51ca9e29 | 808 | else if (_FP_FRAC_ZEROP_##wc (R)) \ |
1e145589 JM |
809 | { \ |
810 | R##_e = 0; \ | |
811 | R##_s = (FP_ROUNDMODE == FP_RND_MINF); \ | |
812 | goto sub_done; \ | |
813 | } \ | |
814 | goto norm; \ | |
815 | } \ | |
816 | sub3: \ | |
51ca9e29 | 817 | if (_FP_FRAC_HIGH_##fs (R) & _FP_IMPLBIT_SH_##fs) \ |
1e145589 | 818 | { \ |
9c37ec0b | 819 | int _FP_ADD_INTERNAL_diff; \ |
1e145589 JM |
820 | /* Carry into most significant bit of larger one of X and Y, \ |
821 | canceling it; renormalize. */ \ | |
51ca9e29 | 822 | _FP_FRAC_HIGH_##fs (R) &= _FP_IMPLBIT_SH_##fs - 1; \ |
1e145589 | 823 | norm: \ |
9c37ec0b JM |
824 | _FP_FRAC_CLZ_##wc (_FP_ADD_INTERNAL_diff, R); \ |
825 | _FP_ADD_INTERNAL_diff -= _FP_WFRACXBITS_##fs; \ | |
826 | _FP_FRAC_SLL_##wc (R, _FP_ADD_INTERNAL_diff); \ | |
827 | if (R##_e <= _FP_ADD_INTERNAL_diff) \ | |
1e145589 JM |
828 | { \ |
829 | /* R is denormalized. */ \ | |
9c37ec0b JM |
830 | _FP_ADD_INTERNAL_diff \ |
831 | = _FP_ADD_INTERNAL_diff - R##_e + 1; \ | |
832 | _FP_FRAC_SRS_##wc (R, _FP_ADD_INTERNAL_diff, \ | |
833 | _FP_WFRACBITS_##fs); \ | |
1e145589 JM |
834 | R##_e = 0; \ |
835 | } \ | |
836 | else \ | |
837 | { \ | |
9c37ec0b | 838 | R##_e -= _FP_ADD_INTERNAL_diff; \ |
51ca9e29 | 839 | _FP_FRAC_HIGH_##fs (R) &= ~(_FP_W_TYPE) _FP_IMPLBIT_SH_##fs; \ |
1e145589 JM |
840 | } \ |
841 | } \ | |
842 | sub_done: ; \ | |
843 | } \ | |
844 | } \ | |
845 | while (0) | |
d876f532 | 846 | |
51ca9e29 | 847 | #define _FP_ADD(fs, wc, R, X, Y) _FP_ADD_INTERNAL (fs, wc, R, X, Y, '+') |
1e145589 JM |
848 | #define _FP_SUB(fs, wc, R, X, Y) \ |
849 | do \ | |
850 | { \ | |
51ca9e29 | 851 | if (!(Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc (Y))) \ |
1e145589 | 852 | Y##_s ^= 1; \ |
51ca9e29 | 853 | _FP_ADD_INTERNAL (fs, wc, R, X, Y, '-'); \ |
1e145589 JM |
854 | } \ |
855 | while (0) | |
d876f532 UD |
856 | |
857 | ||
c4fe3ea7 | 858 | /* Main negation routine. The input value is raw. */ |
d876f532 | 859 | |
1e145589 JM |
860 | #define _FP_NEG(fs, wc, R, X) \ |
861 | do \ | |
862 | { \ | |
51ca9e29 | 863 | _FP_FRAC_COPY_##wc (R, X); \ |
1e145589 JM |
864 | R##_e = X##_e; \ |
865 | R##_s = 1 ^ X##_s; \ | |
866 | } \ | |
867 | while (0) | |
d876f532 UD |
868 | |
869 | ||
c4fe3ea7 | 870 | /* Main multiplication routine. The input values should be cooked. */ |
d876f532 | 871 | |
1e145589 JM |
872 | #define _FP_MUL(fs, wc, R, X, Y) \ |
873 | do \ | |
874 | { \ | |
875 | R##_s = X##_s ^ Y##_s; \ | |
876 | R##_e = X##_e + Y##_e + 1; \ | |
51ca9e29 | 877 | switch (_FP_CLS_COMBINE (X##_c, Y##_c)) \ |
1e145589 | 878 | { \ |
51ca9e29 | 879 | case _FP_CLS_COMBINE (FP_CLS_NORMAL, FP_CLS_NORMAL): \ |
1e145589 | 880 | R##_c = FP_CLS_NORMAL; \ |
77f01ab5 | 881 | \ |
51ca9e29 | 882 | _FP_MUL_MEAT_##fs (R, X, Y); \ |
77f01ab5 | 883 | \ |
51ca9e29 JM |
884 | if (_FP_FRAC_OVERP_##wc (fs, R)) \ |
885 | _FP_FRAC_SRS_##wc (R, 1, _FP_WFRACBITS_##fs); \ | |
1e145589 JM |
886 | else \ |
887 | R##_e--; \ | |
888 | break; \ | |
77f01ab5 | 889 | \ |
51ca9e29 JM |
890 | case _FP_CLS_COMBINE (FP_CLS_NAN, FP_CLS_NAN): \ |
891 | _FP_CHOOSENAN (fs, wc, R, X, Y, '*'); \ | |
1e145589 | 892 | break; \ |
77f01ab5 | 893 | \ |
51ca9e29 JM |
894 | case _FP_CLS_COMBINE (FP_CLS_NAN, FP_CLS_NORMAL): \ |
895 | case _FP_CLS_COMBINE (FP_CLS_NAN, FP_CLS_INF): \ | |
896 | case _FP_CLS_COMBINE (FP_CLS_NAN, FP_CLS_ZERO): \ | |
1e145589 | 897 | R##_s = X##_s; \ |
77f01ab5 | 898 | \ |
51ca9e29 JM |
899 | case _FP_CLS_COMBINE (FP_CLS_INF, FP_CLS_INF): \ |
900 | case _FP_CLS_COMBINE (FP_CLS_INF, FP_CLS_NORMAL): \ | |
901 | case _FP_CLS_COMBINE (FP_CLS_ZERO, FP_CLS_NORMAL): \ | |
902 | case _FP_CLS_COMBINE (FP_CLS_ZERO, FP_CLS_ZERO): \ | |
903 | _FP_FRAC_COPY_##wc (R, X); \ | |
1e145589 JM |
904 | R##_c = X##_c; \ |
905 | break; \ | |
77f01ab5 | 906 | \ |
51ca9e29 JM |
907 | case _FP_CLS_COMBINE (FP_CLS_NORMAL, FP_CLS_NAN): \ |
908 | case _FP_CLS_COMBINE (FP_CLS_INF, FP_CLS_NAN): \ | |
909 | case _FP_CLS_COMBINE (FP_CLS_ZERO, FP_CLS_NAN): \ | |
1e145589 | 910 | R##_s = Y##_s; \ |
77f01ab5 | 911 | \ |
51ca9e29 JM |
912 | case _FP_CLS_COMBINE (FP_CLS_NORMAL, FP_CLS_INF): \ |
913 | case _FP_CLS_COMBINE (FP_CLS_NORMAL, FP_CLS_ZERO): \ | |
914 | _FP_FRAC_COPY_##wc (R, Y); \ | |
1e145589 JM |
915 | R##_c = Y##_c; \ |
916 | break; \ | |
77f01ab5 | 917 | \ |
51ca9e29 JM |
918 | case _FP_CLS_COMBINE (FP_CLS_INF, FP_CLS_ZERO): \ |
919 | case _FP_CLS_COMBINE (FP_CLS_ZERO, FP_CLS_INF): \ | |
1e145589 JM |
920 | R##_s = _FP_NANSIGN_##fs; \ |
921 | R##_c = FP_CLS_NAN; \ | |
51ca9e29 | 922 | _FP_FRAC_SET_##wc (R, _FP_NANFRAC_##fs); \ |
ff12c11f | 923 | FP_SET_EXCEPTION (FP_EX_INVALID | FP_EX_INVALID_IMZ); \ |
1e145589 | 924 | break; \ |
77f01ab5 | 925 | \ |
1e145589 | 926 | default: \ |
51ca9e29 | 927 | abort (); \ |
1e145589 JM |
928 | } \ |
929 | } \ | |
930 | while (0) | |
931 | ||
932 | ||
933 | /* Fused multiply-add. The input values should be cooked. */ | |
934 | ||
935 | #define _FP_FMA(fs, wc, dwc, R, X, Y, Z) \ | |
936 | do \ | |
937 | { \ | |
d7423856 | 938 | __label__ done_fma; \ |
9c37ec0b JM |
939 | FP_DECL_##fs (_FP_FMA_T); \ |
940 | _FP_FMA_T##_s = X##_s ^ Y##_s; \ | |
941 | _FP_FMA_T##_e = X##_e + Y##_e + 1; \ | |
51ca9e29 | 942 | switch (_FP_CLS_COMBINE (X##_c, Y##_c)) \ |
1e145589 | 943 | { \ |
51ca9e29 | 944 | case _FP_CLS_COMBINE (FP_CLS_NORMAL, FP_CLS_NORMAL): \ |
1e145589 JM |
945 | switch (Z##_c) \ |
946 | { \ | |
947 | case FP_CLS_INF: \ | |
948 | case FP_CLS_NAN: \ | |
949 | R##_s = Z##_s; \ | |
51ca9e29 | 950 | _FP_FRAC_COPY_##wc (R, Z); \ |
1e145589 JM |
951 | R##_c = Z##_c; \ |
952 | break; \ | |
953 | \ | |
954 | case FP_CLS_ZERO: \ | |
955 | R##_c = FP_CLS_NORMAL; \ | |
9c37ec0b JM |
956 | R##_s = _FP_FMA_T##_s; \ |
957 | R##_e = _FP_FMA_T##_e; \ | |
1e145589 | 958 | \ |
51ca9e29 | 959 | _FP_MUL_MEAT_##fs (R, X, Y); \ |
1e145589 | 960 | \ |
51ca9e29 JM |
961 | if (_FP_FRAC_OVERP_##wc (fs, R)) \ |
962 | _FP_FRAC_SRS_##wc (R, 1, _FP_WFRACBITS_##fs); \ | |
1e145589 JM |
963 | else \ |
964 | R##_e--; \ | |
965 | break; \ | |
966 | \ | |
967 | case FP_CLS_NORMAL:; \ | |
9c37ec0b JM |
968 | _FP_FRAC_DECL_##dwc (_FP_FMA_TD); \ |
969 | _FP_FRAC_DECL_##dwc (_FP_FMA_ZD); \ | |
970 | _FP_FRAC_DECL_##dwc (_FP_FMA_RD); \ | |
971 | _FP_MUL_MEAT_DW_##fs (_FP_FMA_TD, X, Y); \ | |
972 | R##_e = _FP_FMA_T##_e; \ | |
973 | int _FP_FMA_tsh \ | |
974 | = _FP_FRAC_HIGHBIT_DW_##dwc (fs, _FP_FMA_TD) == 0; \ | |
975 | _FP_FMA_T##_e -= _FP_FMA_tsh; \ | |
976 | int _FP_FMA_ediff = _FP_FMA_T##_e - Z##_e; \ | |
977 | if (_FP_FMA_ediff >= 0) \ | |
1e145589 | 978 | { \ |
9c37ec0b JM |
979 | int _FP_FMA_shift \ |
980 | = _FP_WFRACBITS_##fs - _FP_FMA_tsh - _FP_FMA_ediff; \ | |
981 | if (_FP_FMA_shift <= -_FP_WFRACBITS_##fs) \ | |
982 | _FP_FRAC_SET_##dwc (_FP_FMA_ZD, _FP_MINFRAC_##dwc); \ | |
1e145589 JM |
983 | else \ |
984 | { \ | |
9c37ec0b JM |
985 | _FP_FRAC_COPY_##dwc##_##wc (_FP_FMA_ZD, Z); \ |
986 | if (_FP_FMA_shift < 0) \ | |
987 | _FP_FRAC_SRS_##dwc (_FP_FMA_ZD, -_FP_FMA_shift, \ | |
51ca9e29 | 988 | _FP_WFRACBITS_DW_##fs); \ |
9c37ec0b JM |
989 | else if (_FP_FMA_shift > 0) \ |
990 | _FP_FRAC_SLL_##dwc (_FP_FMA_ZD, _FP_FMA_shift); \ | |
1e145589 | 991 | } \ |
9c37ec0b JM |
992 | R##_s = _FP_FMA_T##_s; \ |
993 | if (_FP_FMA_T##_s == Z##_s) \ | |
994 | _FP_FRAC_ADD_##dwc (_FP_FMA_RD, _FP_FMA_TD, \ | |
995 | _FP_FMA_ZD); \ | |
1e145589 JM |
996 | else \ |
997 | { \ | |
9c37ec0b JM |
998 | _FP_FRAC_SUB_##dwc (_FP_FMA_RD, _FP_FMA_TD, \ |
999 | _FP_FMA_ZD); \ | |
1000 | if (_FP_FRAC_NEGP_##dwc (_FP_FMA_RD)) \ | |
1e145589 JM |
1001 | { \ |
1002 | R##_s = Z##_s; \ | |
9c37ec0b JM |
1003 | _FP_FRAC_SUB_##dwc (_FP_FMA_RD, _FP_FMA_ZD, \ |
1004 | _FP_FMA_TD); \ | |
1e145589 JM |
1005 | } \ |
1006 | } \ | |
1007 | } \ | |
1008 | else \ | |
1009 | { \ | |
1010 | R##_e = Z##_e; \ | |
1011 | R##_s = Z##_s; \ | |
9c37ec0b JM |
1012 | _FP_FRAC_COPY_##dwc##_##wc (_FP_FMA_ZD, Z); \ |
1013 | _FP_FRAC_SLL_##dwc (_FP_FMA_ZD, _FP_WFRACBITS_##fs); \ | |
1014 | int _FP_FMA_shift = -_FP_FMA_ediff - _FP_FMA_tsh; \ | |
1015 | if (_FP_FMA_shift >= _FP_WFRACBITS_DW_##fs) \ | |
1016 | _FP_FRAC_SET_##dwc (_FP_FMA_TD, _FP_MINFRAC_##dwc); \ | |
1017 | else if (_FP_FMA_shift > 0) \ | |
1018 | _FP_FRAC_SRS_##dwc (_FP_FMA_TD, _FP_FMA_shift, \ | |
51ca9e29 | 1019 | _FP_WFRACBITS_DW_##fs); \ |
9c37ec0b JM |
1020 | if (Z##_s == _FP_FMA_T##_s) \ |
1021 | _FP_FRAC_ADD_##dwc (_FP_FMA_RD, _FP_FMA_ZD, \ | |
1022 | _FP_FMA_TD); \ | |
1e145589 | 1023 | else \ |
9c37ec0b JM |
1024 | _FP_FRAC_SUB_##dwc (_FP_FMA_RD, _FP_FMA_ZD, \ |
1025 | _FP_FMA_TD); \ | |
1e145589 | 1026 | } \ |
9c37ec0b | 1027 | if (_FP_FRAC_ZEROP_##dwc (_FP_FMA_RD)) \ |
1e145589 | 1028 | { \ |
9c37ec0b | 1029 | if (_FP_FMA_T##_s == Z##_s) \ |
1e145589 JM |
1030 | R##_s = Z##_s; \ |
1031 | else \ | |
1032 | R##_s = (FP_ROUNDMODE == FP_RND_MINF); \ | |
51ca9e29 | 1033 | _FP_FRAC_SET_##wc (R, _FP_ZEROFRAC_##wc); \ |
1e145589 JM |
1034 | R##_c = FP_CLS_ZERO; \ |
1035 | } \ | |
1036 | else \ | |
1037 | { \ | |
9c37ec0b JM |
1038 | int _FP_FMA_rlz; \ |
1039 | _FP_FRAC_CLZ_##dwc (_FP_FMA_rlz, _FP_FMA_RD); \ | |
1040 | _FP_FMA_rlz -= _FP_WFRACXBITS_DW_##fs; \ | |
1041 | R##_e -= _FP_FMA_rlz; \ | |
1042 | int _FP_FMA_shift = _FP_WFRACBITS_##fs - _FP_FMA_rlz; \ | |
1043 | if (_FP_FMA_shift > 0) \ | |
1044 | _FP_FRAC_SRS_##dwc (_FP_FMA_RD, _FP_FMA_shift, \ | |
51ca9e29 | 1045 | _FP_WFRACBITS_DW_##fs); \ |
9c37ec0b JM |
1046 | else if (_FP_FMA_shift < 0) \ |
1047 | _FP_FRAC_SLL_##dwc (_FP_FMA_RD, -_FP_FMA_shift); \ | |
1048 | _FP_FRAC_COPY_##wc##_##dwc (R, _FP_FMA_RD); \ | |
1e145589 JM |
1049 | R##_c = FP_CLS_NORMAL; \ |
1050 | } \ | |
1051 | break; \ | |
1052 | } \ | |
1053 | goto done_fma; \ | |
1054 | \ | |
51ca9e29 | 1055 | case _FP_CLS_COMBINE (FP_CLS_NAN, FP_CLS_NAN): \ |
9c37ec0b | 1056 | _FP_CHOOSENAN (fs, wc, _FP_FMA_T, X, Y, '*'); \ |
1e145589 JM |
1057 | break; \ |
1058 | \ | |
51ca9e29 JM |
1059 | case _FP_CLS_COMBINE (FP_CLS_NAN, FP_CLS_NORMAL): \ |
1060 | case _FP_CLS_COMBINE (FP_CLS_NAN, FP_CLS_INF): \ | |
1061 | case _FP_CLS_COMBINE (FP_CLS_NAN, FP_CLS_ZERO): \ | |
9c37ec0b | 1062 | _FP_FMA_T##_s = X##_s; \ |
1e145589 | 1063 | \ |
51ca9e29 JM |
1064 | case _FP_CLS_COMBINE (FP_CLS_INF, FP_CLS_INF): \ |
1065 | case _FP_CLS_COMBINE (FP_CLS_INF, FP_CLS_NORMAL): \ | |
1066 | case _FP_CLS_COMBINE (FP_CLS_ZERO, FP_CLS_NORMAL): \ | |
1067 | case _FP_CLS_COMBINE (FP_CLS_ZERO, FP_CLS_ZERO): \ | |
9c37ec0b JM |
1068 | _FP_FRAC_COPY_##wc (_FP_FMA_T, X); \ |
1069 | _FP_FMA_T##_c = X##_c; \ | |
1e145589 JM |
1070 | break; \ |
1071 | \ | |
51ca9e29 JM |
1072 | case _FP_CLS_COMBINE (FP_CLS_NORMAL, FP_CLS_NAN): \ |
1073 | case _FP_CLS_COMBINE (FP_CLS_INF, FP_CLS_NAN): \ | |
1074 | case _FP_CLS_COMBINE (FP_CLS_ZERO, FP_CLS_NAN): \ | |
9c37ec0b | 1075 | _FP_FMA_T##_s = Y##_s; \ |
1e145589 | 1076 | \ |
51ca9e29 JM |
1077 | case _FP_CLS_COMBINE (FP_CLS_NORMAL, FP_CLS_INF): \ |
1078 | case _FP_CLS_COMBINE (FP_CLS_NORMAL, FP_CLS_ZERO): \ | |
9c37ec0b JM |
1079 | _FP_FRAC_COPY_##wc (_FP_FMA_T, Y); \ |
1080 | _FP_FMA_T##_c = Y##_c; \ | |
1e145589 JM |
1081 | break; \ |
1082 | \ | |
51ca9e29 JM |
1083 | case _FP_CLS_COMBINE (FP_CLS_INF, FP_CLS_ZERO): \ |
1084 | case _FP_CLS_COMBINE (FP_CLS_ZERO, FP_CLS_INF): \ | |
9c37ec0b JM |
1085 | _FP_FMA_T##_s = _FP_NANSIGN_##fs; \ |
1086 | _FP_FMA_T##_c = FP_CLS_NAN; \ | |
1087 | _FP_FRAC_SET_##wc (_FP_FMA_T, _FP_NANFRAC_##fs); \ | |
ff12c11f | 1088 | FP_SET_EXCEPTION (FP_EX_INVALID | FP_EX_INVALID_IMZ_FMA); \ |
1e145589 JM |
1089 | break; \ |
1090 | \ | |
1091 | default: \ | |
51ca9e29 | 1092 | abort (); \ |
1e145589 JM |
1093 | } \ |
1094 | \ | |
1095 | /* T = X * Y is zero, infinity or NaN. */ \ | |
9c37ec0b | 1096 | switch (_FP_CLS_COMBINE (_FP_FMA_T##_c, Z##_c)) \ |
1e145589 | 1097 | { \ |
51ca9e29 | 1098 | case _FP_CLS_COMBINE (FP_CLS_NAN, FP_CLS_NAN): \ |
9c37ec0b | 1099 | _FP_CHOOSENAN (fs, wc, R, _FP_FMA_T, Z, '+'); \ |
1e145589 JM |
1100 | break; \ |
1101 | \ | |
51ca9e29 JM |
1102 | case _FP_CLS_COMBINE (FP_CLS_NAN, FP_CLS_NORMAL): \ |
1103 | case _FP_CLS_COMBINE (FP_CLS_NAN, FP_CLS_INF): \ | |
1104 | case _FP_CLS_COMBINE (FP_CLS_NAN, FP_CLS_ZERO): \ | |
1105 | case _FP_CLS_COMBINE (FP_CLS_INF, FP_CLS_NORMAL): \ | |
1106 | case _FP_CLS_COMBINE (FP_CLS_INF, FP_CLS_ZERO): \ | |
9c37ec0b JM |
1107 | R##_s = _FP_FMA_T##_s; \ |
1108 | _FP_FRAC_COPY_##wc (R, _FP_FMA_T); \ | |
1109 | R##_c = _FP_FMA_T##_c; \ | |
1e145589 JM |
1110 | break; \ |
1111 | \ | |
51ca9e29 JM |
1112 | case _FP_CLS_COMBINE (FP_CLS_INF, FP_CLS_NAN): \ |
1113 | case _FP_CLS_COMBINE (FP_CLS_ZERO, FP_CLS_NAN): \ | |
1114 | case _FP_CLS_COMBINE (FP_CLS_ZERO, FP_CLS_NORMAL): \ | |
1115 | case _FP_CLS_COMBINE (FP_CLS_ZERO, FP_CLS_INF): \ | |
1e145589 | 1116 | R##_s = Z##_s; \ |
51ca9e29 | 1117 | _FP_FRAC_COPY_##wc (R, Z); \ |
1e145589 | 1118 | R##_c = Z##_c; \ |
1c7a4a51 | 1119 | R##_e = Z##_e; \ |
1e145589 JM |
1120 | break; \ |
1121 | \ | |
51ca9e29 | 1122 | case _FP_CLS_COMBINE (FP_CLS_INF, FP_CLS_INF): \ |
9c37ec0b | 1123 | if (_FP_FMA_T##_s == Z##_s) \ |
1e145589 JM |
1124 | { \ |
1125 | R##_s = Z##_s; \ | |
51ca9e29 | 1126 | _FP_FRAC_COPY_##wc (R, Z); \ |
1e145589 JM |
1127 | R##_c = Z##_c; \ |
1128 | } \ | |
1129 | else \ | |
1130 | { \ | |
1131 | R##_s = _FP_NANSIGN_##fs; \ | |
1132 | R##_c = FP_CLS_NAN; \ | |
51ca9e29 | 1133 | _FP_FRAC_SET_##wc (R, _FP_NANFRAC_##fs); \ |
ff12c11f | 1134 | FP_SET_EXCEPTION (FP_EX_INVALID | FP_EX_INVALID_ISI); \ |
1e145589 JM |
1135 | } \ |
1136 | break; \ | |
1137 | \ | |
51ca9e29 | 1138 | case _FP_CLS_COMBINE (FP_CLS_ZERO, FP_CLS_ZERO): \ |
9c37ec0b | 1139 | if (_FP_FMA_T##_s == Z##_s) \ |
1e145589 JM |
1140 | R##_s = Z##_s; \ |
1141 | else \ | |
1142 | R##_s = (FP_ROUNDMODE == FP_RND_MINF); \ | |
51ca9e29 | 1143 | _FP_FRAC_COPY_##wc (R, Z); \ |
1e145589 JM |
1144 | R##_c = Z##_c; \ |
1145 | break; \ | |
1146 | \ | |
1147 | default: \ | |
51ca9e29 | 1148 | abort (); \ |
1e145589 JM |
1149 | } \ |
1150 | done_fma: ; \ | |
1151 | } \ | |
1152 | while (0) | |
1153 | ||
1154 | ||
c4fe3ea7 | 1155 | /* Main division routine. The input values should be cooked. */ |
1e145589 JM |
1156 | |
1157 | #define _FP_DIV(fs, wc, R, X, Y) \ | |
1158 | do \ | |
1159 | { \ | |
1160 | R##_s = X##_s ^ Y##_s; \ | |
1161 | R##_e = X##_e - Y##_e; \ | |
51ca9e29 | 1162 | switch (_FP_CLS_COMBINE (X##_c, Y##_c)) \ |
1e145589 | 1163 | { \ |
51ca9e29 | 1164 | case _FP_CLS_COMBINE (FP_CLS_NORMAL, FP_CLS_NORMAL): \ |
1e145589 | 1165 | R##_c = FP_CLS_NORMAL; \ |
77f01ab5 | 1166 | \ |
51ca9e29 | 1167 | _FP_DIV_MEAT_##fs (R, X, Y); \ |
1e145589 | 1168 | break; \ |
77f01ab5 | 1169 | \ |
51ca9e29 JM |
1170 | case _FP_CLS_COMBINE (FP_CLS_NAN, FP_CLS_NAN): \ |
1171 | _FP_CHOOSENAN (fs, wc, R, X, Y, '/'); \ | |
1e145589 | 1172 | break; \ |
77f01ab5 | 1173 | \ |
51ca9e29 JM |
1174 | case _FP_CLS_COMBINE (FP_CLS_NAN, FP_CLS_NORMAL): \ |
1175 | case _FP_CLS_COMBINE (FP_CLS_NAN, FP_CLS_INF): \ | |
1176 | case _FP_CLS_COMBINE (FP_CLS_NAN, FP_CLS_ZERO): \ | |
1e145589 | 1177 | R##_s = X##_s; \ |
51ca9e29 | 1178 | _FP_FRAC_COPY_##wc (R, X); \ |
1e145589 JM |
1179 | R##_c = X##_c; \ |
1180 | break; \ | |
77f01ab5 | 1181 | \ |
51ca9e29 JM |
1182 | case _FP_CLS_COMBINE (FP_CLS_NORMAL, FP_CLS_NAN): \ |
1183 | case _FP_CLS_COMBINE (FP_CLS_INF, FP_CLS_NAN): \ | |
1184 | case _FP_CLS_COMBINE (FP_CLS_ZERO, FP_CLS_NAN): \ | |
1e145589 | 1185 | R##_s = Y##_s; \ |
51ca9e29 | 1186 | _FP_FRAC_COPY_##wc (R, Y); \ |
1e145589 JM |
1187 | R##_c = Y##_c; \ |
1188 | break; \ | |
77f01ab5 | 1189 | \ |
51ca9e29 JM |
1190 | case _FP_CLS_COMBINE (FP_CLS_NORMAL, FP_CLS_INF): \ |
1191 | case _FP_CLS_COMBINE (FP_CLS_ZERO, FP_CLS_INF): \ | |
1192 | case _FP_CLS_COMBINE (FP_CLS_ZERO, FP_CLS_NORMAL): \ | |
1e145589 JM |
1193 | R##_c = FP_CLS_ZERO; \ |
1194 | break; \ | |
77f01ab5 | 1195 | \ |
51ca9e29 JM |
1196 | case _FP_CLS_COMBINE (FP_CLS_NORMAL, FP_CLS_ZERO): \ |
1197 | FP_SET_EXCEPTION (FP_EX_DIVZERO); \ | |
1198 | case _FP_CLS_COMBINE (FP_CLS_INF, FP_CLS_ZERO): \ | |
1199 | case _FP_CLS_COMBINE (FP_CLS_INF, FP_CLS_NORMAL): \ | |
1e145589 JM |
1200 | R##_c = FP_CLS_INF; \ |
1201 | break; \ | |
77f01ab5 | 1202 | \ |
51ca9e29 JM |
1203 | case _FP_CLS_COMBINE (FP_CLS_INF, FP_CLS_INF): \ |
1204 | case _FP_CLS_COMBINE (FP_CLS_ZERO, FP_CLS_ZERO): \ | |
1e145589 JM |
1205 | R##_s = _FP_NANSIGN_##fs; \ |
1206 | R##_c = FP_CLS_NAN; \ | |
51ca9e29 | 1207 | _FP_FRAC_SET_##wc (R, _FP_NANFRAC_##fs); \ |
ff12c11f JM |
1208 | FP_SET_EXCEPTION (FP_EX_INVALID \ |
1209 | | (X##_c == FP_CLS_INF \ | |
1210 | ? FP_EX_INVALID_IDI \ | |
1211 | : FP_EX_INVALID_ZDZ)); \ | |
1e145589 | 1212 | break; \ |
77f01ab5 | 1213 | \ |
1e145589 | 1214 | default: \ |
51ca9e29 | 1215 | abort (); \ |
1e145589 JM |
1216 | } \ |
1217 | } \ | |
1218 | while (0) | |
d876f532 UD |
1219 | |
1220 | ||
73e28d9c JM |
1221 | /* Helper for comparisons. EX is 0 not to raise exceptions, 1 to |
1222 | raise exceptions for signaling NaN operands, 2 to raise exceptions | |
ff12c11f JM |
1223 | for all NaN operands. Conditionals are organized to allow the |
1224 | compiler to optimize away code based on the value of EX. */ | |
73e28d9c | 1225 | |
ff12c11f JM |
1226 | #define _FP_CMP_CHECK_NAN(fs, wc, X, Y, ex) \ |
1227 | do \ | |
1228 | { \ | |
1229 | /* The arguments are unordered, which may or may not result in \ | |
1230 | an exception. */ \ | |
1231 | if (ex) \ | |
1232 | { \ | |
1233 | /* At least some cases of unordered arguments result in \ | |
1234 | exceptions; check whether this is one. */ \ | |
1235 | if (FP_EX_INVALID_SNAN || FP_EX_INVALID_VC) \ | |
1236 | { \ | |
1237 | /* Check separately for each case of "invalid" \ | |
1238 | exceptions. */ \ | |
1239 | if ((ex) == 2) \ | |
1240 | FP_SET_EXCEPTION (FP_EX_INVALID | FP_EX_INVALID_VC); \ | |
1241 | if (_FP_ISSIGNAN (fs, wc, X) \ | |
1242 | || _FP_ISSIGNAN (fs, wc, Y)) \ | |
1243 | FP_SET_EXCEPTION (FP_EX_INVALID | FP_EX_INVALID_SNAN); \ | |
1244 | } \ | |
1245 | /* Otherwise, we only need to check whether to raise an \ | |
1246 | exception, not which case or cases it is. */ \ | |
1247 | else if ((ex) == 2 \ | |
1248 | || _FP_ISSIGNAN (fs, wc, X) \ | |
1249 | || _FP_ISSIGNAN (fs, wc, Y)) \ | |
1250 | FP_SET_EXCEPTION (FP_EX_INVALID); \ | |
1251 | } \ | |
1252 | } \ | |
73e28d9c JM |
1253 | while (0) |
1254 | ||
61f006c1 JM |
1255 | /* Helper for comparisons. If denormal operands would raise an |
1256 | exception, check for them, and flush to zero as appropriate | |
1257 | (otherwise, we need only check and flush to zero if it might affect | |
1258 | the result, which is done later with _FP_CMP_CHECK_FLUSH_ZERO). */ | |
1259 | #define _FP_CMP_CHECK_DENORM(fs, wc, X, Y) \ | |
1260 | do \ | |
1261 | { \ | |
1262 | if (FP_EX_DENORM != 0) \ | |
1263 | { \ | |
1264 | /* We must ensure the correct exceptions are raised for \ | |
1265 | denormal operands, even though this may not affect the \ | |
1266 | result of the comparison. */ \ | |
1267 | if (FP_DENORM_ZERO) \ | |
1268 | { \ | |
1269 | _FP_CHECK_FLUSH_ZERO (fs, wc, X); \ | |
1270 | _FP_CHECK_FLUSH_ZERO (fs, wc, Y); \ | |
1271 | } \ | |
1272 | else \ | |
1273 | { \ | |
1274 | if ((X##_e == 0 && !_FP_FRAC_ZEROP_##wc (X)) \ | |
1275 | || (Y##_e == 0 && !_FP_FRAC_ZEROP_##wc (Y))) \ | |
1276 | FP_SET_EXCEPTION (FP_EX_DENORM); \ | |
1277 | } \ | |
1278 | } \ | |
1279 | } \ | |
1280 | while (0) | |
1281 | ||
1282 | /* Helper for comparisons. Check for flushing denormals for zero if | |
1283 | we didn't need to check earlier for any denormal operands. */ | |
1284 | #define _FP_CMP_CHECK_FLUSH_ZERO(fs, wc, X, Y) \ | |
1285 | do \ | |
1286 | { \ | |
1287 | if (FP_EX_DENORM == 0) \ | |
1288 | { \ | |
1289 | _FP_CHECK_FLUSH_ZERO (fs, wc, X); \ | |
1290 | _FP_CHECK_FLUSH_ZERO (fs, wc, Y); \ | |
1291 | } \ | |
1292 | } \ | |
1293 | while (0) | |
1294 | ||
c4fe3ea7 | 1295 | /* Main differential comparison routine. The inputs should be raw not |
73e28d9c JM |
1296 | cooked. The return is -1, 0, 1 for normal values, UN |
1297 | otherwise. */ | |
d876f532 | 1298 | |
73e28d9c | 1299 | #define _FP_CMP(fs, wc, ret, X, Y, un, ex) \ |
1e145589 JM |
1300 | do \ |
1301 | { \ | |
61f006c1 | 1302 | _FP_CMP_CHECK_DENORM (fs, wc, X, Y); \ |
c4fe3ea7 | 1303 | /* NANs are unordered. */ \ |
51ca9e29 JM |
1304 | if ((X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc (X)) \ |
1305 | || (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc (Y))) \ | |
1e145589 | 1306 | { \ |
5c0508a3 JM |
1307 | (ret) = (un); \ |
1308 | _FP_CMP_CHECK_NAN (fs, wc, X, Y, (ex)); \ | |
1e145589 JM |
1309 | } \ |
1310 | else \ | |
1311 | { \ | |
9c37ec0b JM |
1312 | int _FP_CMP_is_zero_x; \ |
1313 | int _FP_CMP_is_zero_y; \ | |
d876f532 | 1314 | \ |
61f006c1 | 1315 | _FP_CMP_CHECK_FLUSH_ZERO (fs, wc, X, Y); \ |
454ac701 | 1316 | \ |
9c37ec0b JM |
1317 | _FP_CMP_is_zero_x \ |
1318 | = (!X##_e && _FP_FRAC_ZEROP_##wc (X)) ? 1 : 0; \ | |
1319 | _FP_CMP_is_zero_y \ | |
1320 | = (!Y##_e && _FP_FRAC_ZEROP_##wc (Y)) ? 1 : 0; \ | |
d876f532 | 1321 | \ |
9c37ec0b | 1322 | if (_FP_CMP_is_zero_x && _FP_CMP_is_zero_y) \ |
5c0508a3 | 1323 | (ret) = 0; \ |
9c37ec0b | 1324 | else if (_FP_CMP_is_zero_x) \ |
5c0508a3 | 1325 | (ret) = Y##_s ? 1 : -1; \ |
9c37ec0b | 1326 | else if (_FP_CMP_is_zero_y) \ |
5c0508a3 | 1327 | (ret) = X##_s ? -1 : 1; \ |
1e145589 | 1328 | else if (X##_s != Y##_s) \ |
5c0508a3 | 1329 | (ret) = X##_s ? -1 : 1; \ |
1e145589 | 1330 | else if (X##_e > Y##_e) \ |
5c0508a3 | 1331 | (ret) = X##_s ? -1 : 1; \ |
1e145589 | 1332 | else if (X##_e < Y##_e) \ |
5c0508a3 | 1333 | (ret) = X##_s ? 1 : -1; \ |
51ca9e29 | 1334 | else if (_FP_FRAC_GT_##wc (X, Y)) \ |
5c0508a3 | 1335 | (ret) = X##_s ? -1 : 1; \ |
51ca9e29 | 1336 | else if (_FP_FRAC_GT_##wc (Y, X)) \ |
5c0508a3 | 1337 | (ret) = X##_s ? 1 : -1; \ |
1e145589 | 1338 | else \ |
5c0508a3 | 1339 | (ret) = 0; \ |
1e145589 JM |
1340 | } \ |
1341 | } \ | |
1342 | while (0) | |
d876f532 UD |
1343 | |
1344 | ||
1345 | /* Simplification for strict equality. */ | |
1346 | ||
73e28d9c | 1347 | #define _FP_CMP_EQ(fs, wc, ret, X, Y, ex) \ |
1e145589 JM |
1348 | do \ |
1349 | { \ | |
61f006c1 | 1350 | _FP_CMP_CHECK_DENORM (fs, wc, X, Y); \ |
c4fe3ea7 | 1351 | /* NANs are unordered. */ \ |
51ca9e29 JM |
1352 | if ((X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc (X)) \ |
1353 | || (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc (Y))) \ | |
1e145589 | 1354 | { \ |
5c0508a3 JM |
1355 | (ret) = 1; \ |
1356 | _FP_CMP_CHECK_NAN (fs, wc, X, Y, (ex)); \ | |
1e145589 JM |
1357 | } \ |
1358 | else \ | |
1359 | { \ | |
61f006c1 | 1360 | _FP_CMP_CHECK_FLUSH_ZERO (fs, wc, X, Y); \ |
454ac701 | 1361 | \ |
5c0508a3 JM |
1362 | (ret) = !(X##_e == Y##_e \ |
1363 | && _FP_FRAC_EQ_##wc (X, Y) \ | |
1364 | && (X##_s == Y##_s \ | |
1365 | || (!X##_e && _FP_FRAC_ZEROP_##wc (X)))); \ | |
1e145589 JM |
1366 | } \ |
1367 | } \ | |
1368 | while (0) | |
d876f532 | 1369 | |
e7b8c7bc RM |
1370 | /* Version to test unordered. */ |
1371 | ||
73e28d9c | 1372 | #define _FP_CMP_UNORD(fs, wc, ret, X, Y, ex) \ |
1e145589 JM |
1373 | do \ |
1374 | { \ | |
61f006c1 | 1375 | _FP_CMP_CHECK_DENORM (fs, wc, X, Y); \ |
5c0508a3 JM |
1376 | (ret) = ((X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc (X)) \ |
1377 | || (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc (Y))); \ | |
73e28d9c | 1378 | if (ret) \ |
5c0508a3 | 1379 | _FP_CMP_CHECK_NAN (fs, wc, X, Y, (ex)); \ |
1e145589 JM |
1380 | } \ |
1381 | while (0) | |
e7b8c7bc | 1382 | |
c4fe3ea7 | 1383 | /* Main square root routine. The input value should be cooked. */ |
d876f532 | 1384 | |
ff12c11f JM |
1385 | #define _FP_SQRT(fs, wc, R, X) \ |
1386 | do \ | |
1387 | { \ | |
1388 | _FP_FRAC_DECL_##wc (_FP_SQRT_T); \ | |
1389 | _FP_FRAC_DECL_##wc (_FP_SQRT_S); \ | |
1390 | _FP_W_TYPE _FP_SQRT_q; \ | |
1391 | switch (X##_c) \ | |
1392 | { \ | |
1393 | case FP_CLS_NAN: \ | |
1394 | _FP_FRAC_COPY_##wc (R, X); \ | |
1395 | R##_s = X##_s; \ | |
1396 | R##_c = FP_CLS_NAN; \ | |
1397 | break; \ | |
1398 | case FP_CLS_INF: \ | |
1399 | if (X##_s) \ | |
1400 | { \ | |
1401 | R##_s = _FP_NANSIGN_##fs; \ | |
1402 | R##_c = FP_CLS_NAN; /* NAN */ \ | |
1403 | _FP_FRAC_SET_##wc (R, _FP_NANFRAC_##fs); \ | |
1404 | FP_SET_EXCEPTION (FP_EX_INVALID | FP_EX_INVALID_SQRT); \ | |
1405 | } \ | |
1406 | else \ | |
1407 | { \ | |
1408 | R##_s = 0; \ | |
1409 | R##_c = FP_CLS_INF; /* sqrt(+inf) = +inf */ \ | |
1410 | } \ | |
1411 | break; \ | |
1412 | case FP_CLS_ZERO: \ | |
1413 | R##_s = X##_s; \ | |
1414 | R##_c = FP_CLS_ZERO; /* sqrt(+-0) = +-0 */ \ | |
1415 | break; \ | |
1416 | case FP_CLS_NORMAL: \ | |
1417 | R##_s = 0; \ | |
1418 | if (X##_s) \ | |
1419 | { \ | |
1420 | R##_c = FP_CLS_NAN; /* NAN */ \ | |
1421 | R##_s = _FP_NANSIGN_##fs; \ | |
1422 | _FP_FRAC_SET_##wc (R, _FP_NANFRAC_##fs); \ | |
1423 | FP_SET_EXCEPTION (FP_EX_INVALID | FP_EX_INVALID_SQRT); \ | |
1424 | break; \ | |
1425 | } \ | |
1426 | R##_c = FP_CLS_NORMAL; \ | |
1427 | if (X##_e & 1) \ | |
1428 | _FP_FRAC_SLL_##wc (X, 1); \ | |
1429 | R##_e = X##_e >> 1; \ | |
1430 | _FP_FRAC_SET_##wc (_FP_SQRT_S, _FP_ZEROFRAC_##wc); \ | |
1431 | _FP_FRAC_SET_##wc (R, _FP_ZEROFRAC_##wc); \ | |
1432 | _FP_SQRT_q = _FP_OVERFLOW_##fs >> 1; \ | |
1433 | _FP_SQRT_MEAT_##wc (R, _FP_SQRT_S, _FP_SQRT_T, X, \ | |
1434 | _FP_SQRT_q); \ | |
1435 | } \ | |
1436 | } \ | |
1e145589 | 1437 | while (0) |
d876f532 | 1438 | |
c4fe3ea7 | 1439 | /* Convert from FP to integer. Input is raw. */ |
d876f532 UD |
1440 | |
1441 | /* RSIGNED can have following values: | |
c4fe3ea7 JM |
1442 | 0: the number is required to be 0..(2^rsize)-1, if not, NV is set plus |
1443 | the result is either 0 or (2^rsize)-1 depending on the sign in such | |
1444 | case. | |
1445 | 1: the number is required to be -(2^(rsize-1))..(2^(rsize-1))-1, if not, | |
1446 | NV is set plus the result is either -(2^(rsize-1)) or (2^(rsize-1))-1 | |
1447 | depending on the sign in such case. | |
a736ec37 JM |
1448 | 2: the number is required to be -(2^(rsize-1))..(2^(rsize-1))-1, if not, |
1449 | NV is set plus the result is reduced modulo 2^rsize. | |
c4fe3ea7 JM |
1450 | -1: the number is required to be -(2^(rsize-1))..(2^rsize)-1, if not, NV is |
1451 | set plus the result is either -(2^(rsize-1)) or (2^(rsize-1))-1 | |
1452 | depending on the sign in such case. */ | |
fe0b1e85 | 1453 | #define _FP_TO_INT(fs, wc, r, X, rsize, rsigned) \ |
1e145589 | 1454 | do \ |
fe0b1e85 | 1455 | { \ |
1e145589 | 1456 | if (X##_e < _FP_EXPBIAS_##fs) \ |
fe0b1e85 | 1457 | { \ |
5c0508a3 | 1458 | (r) = 0; \ |
1e145589 | 1459 | if (X##_e == 0) \ |
fe0b1e85 | 1460 | { \ |
51ca9e29 | 1461 | if (!_FP_FRAC_ZEROP_##wc (X)) \ |
1e145589 | 1462 | { \ |
454ac701 JM |
1463 | if (!FP_DENORM_ZERO) \ |
1464 | FP_SET_EXCEPTION (FP_EX_INEXACT); \ | |
51ca9e29 | 1465 | FP_SET_EXCEPTION (FP_EX_DENORM); \ |
1e145589 | 1466 | } \ |
fe0b1e85 | 1467 | } \ |
1e145589 | 1468 | else \ |
51ca9e29 | 1469 | FP_SET_EXCEPTION (FP_EX_INEXACT); \ |
fe0b1e85 | 1470 | } \ |
5c0508a3 | 1471 | else if ((rsigned) == 2 \ |
a736ec37 JM |
1472 | && (X##_e \ |
1473 | >= ((_FP_EXPMAX_##fs \ | |
5c0508a3 | 1474 | < _FP_EXPBIAS_##fs + _FP_FRACBITS_##fs + (rsize) - 1) \ |
a736ec37 | 1475 | ? _FP_EXPMAX_##fs \ |
5c0508a3 | 1476 | : _FP_EXPBIAS_##fs + _FP_FRACBITS_##fs + (rsize) - 1))) \ |
a736ec37 JM |
1477 | { \ |
1478 | /* Overflow resulting in 0. */ \ | |
5c0508a3 | 1479 | (r) = 0; \ |
a736ec37 JM |
1480 | FP_SET_EXCEPTION (FP_EX_INVALID \ |
1481 | | FP_EX_INVALID_CVI \ | |
1482 | | ((FP_EX_INVALID_SNAN \ | |
1483 | && _FP_ISSIGNAN (fs, wc, X)) \ | |
1484 | ? FP_EX_INVALID_SNAN \ | |
1485 | : 0)); \ | |
1486 | } \ | |
5c0508a3 JM |
1487 | else if ((rsigned) != 2 \ |
1488 | && (X##_e >= (_FP_EXPMAX_##fs < _FP_EXPBIAS_##fs + (rsize) \ | |
a736ec37 | 1489 | ? _FP_EXPMAX_##fs \ |
5c0508a3 JM |
1490 | : (_FP_EXPBIAS_##fs + (rsize) \ |
1491 | - ((rsigned) > 0 || X##_s))) \ | |
1492 | || (!(rsigned) && X##_s))) \ | |
fe0b1e85 | 1493 | { \ |
1e145589 JM |
1494 | /* Overflow or converting to the most negative integer. */ \ |
1495 | if (rsigned) \ | |
1496 | { \ | |
5c0508a3 JM |
1497 | (r) = 1; \ |
1498 | (r) <<= (rsize) - 1; \ | |
1499 | (r) -= 1 - X##_s; \ | |
4e8afe69 JM |
1500 | } \ |
1501 | else \ | |
1502 | { \ | |
5c0508a3 | 1503 | (r) = 0; \ |
4e8afe69 | 1504 | if (!X##_s) \ |
5c0508a3 | 1505 | (r) = ~(r); \ |
4e8afe69 | 1506 | } \ |
a334319f | 1507 | \ |
5c0508a3 JM |
1508 | if (_FP_EXPBIAS_##fs + (rsize) - 1 < _FP_EXPMAX_##fs \ |
1509 | && (rsigned) \ | |
0022e688 | 1510 | && X##_s \ |
5c0508a3 | 1511 | && X##_e == _FP_EXPBIAS_##fs + (rsize) - 1) \ |
1e145589 JM |
1512 | { \ |
1513 | /* Possibly converting to most negative integer; check the \ | |
1514 | mantissa. */ \ | |
9c37ec0b | 1515 | int _FP_TO_INT_inexact = 0; \ |
5c0508a3 | 1516 | (void) ((_FP_FRACBITS_##fs > (rsize)) \ |
51ca9e29 | 1517 | ? ({ \ |
9c37ec0b | 1518 | _FP_FRAC_SRST_##wc (X, _FP_TO_INT_inexact, \ |
5c0508a3 | 1519 | _FP_FRACBITS_##fs - (rsize), \ |
51ca9e29 JM |
1520 | _FP_FRACBITS_##fs); \ |
1521 | 0; \ | |
1522 | }) \ | |
1523 | : 0); \ | |
1524 | if (!_FP_FRAC_ZEROP_##wc (X)) \ | |
ff12c11f | 1525 | FP_SET_EXCEPTION (FP_EX_INVALID | FP_EX_INVALID_CVI); \ |
9c37ec0b | 1526 | else if (_FP_TO_INT_inexact) \ |
51ca9e29 | 1527 | FP_SET_EXCEPTION (FP_EX_INEXACT); \ |
1e145589 JM |
1528 | } \ |
1529 | else \ | |
ff12c11f JM |
1530 | FP_SET_EXCEPTION (FP_EX_INVALID \ |
1531 | | FP_EX_INVALID_CVI \ | |
1532 | | ((FP_EX_INVALID_SNAN \ | |
1533 | && _FP_ISSIGNAN (fs, wc, X)) \ | |
1534 | ? FP_EX_INVALID_SNAN \ | |
1535 | : 0)); \ | |
fe0b1e85 RM |
1536 | } \ |
1537 | else \ | |
1e145589 | 1538 | { \ |
a736ec37 | 1539 | int _FP_TO_INT_inexact = 0; \ |
51ca9e29 | 1540 | _FP_FRAC_HIGH_RAW_##fs (X) |= _FP_IMPLBIT_##fs; \ |
1e145589 JM |
1541 | if (X##_e >= _FP_EXPBIAS_##fs + _FP_FRACBITS_##fs - 1) \ |
1542 | { \ | |
5c0508a3 JM |
1543 | _FP_FRAC_ASSEMBLE_##wc ((r), X, (rsize)); \ |
1544 | (r) <<= X##_e - _FP_EXPBIAS_##fs - _FP_FRACBITS_##fs + 1; \ | |
1e145589 JM |
1545 | } \ |
1546 | else \ | |
1547 | { \ | |
9c37ec0b | 1548 | _FP_FRAC_SRST_##wc (X, _FP_TO_INT_inexact, \ |
51ca9e29 JM |
1549 | (_FP_FRACBITS_##fs + _FP_EXPBIAS_##fs - 1 \ |
1550 | - X##_e), \ | |
1551 | _FP_FRACBITS_##fs); \ | |
5c0508a3 | 1552 | _FP_FRAC_ASSEMBLE_##wc ((r), X, (rsize)); \ |
1e145589 | 1553 | } \ |
5c0508a3 JM |
1554 | if ((rsigned) && X##_s) \ |
1555 | (r) = -(r); \ | |
1556 | if ((rsigned) == 2 && X##_e >= _FP_EXPBIAS_##fs + (rsize) - 1) \ | |
a736ec37 JM |
1557 | { \ |
1558 | /* Overflow or converting to the most negative integer. */ \ | |
5c0508a3 | 1559 | if (X##_e > _FP_EXPBIAS_##fs + (rsize) - 1 \ |
a736ec37 | 1560 | || !X##_s \ |
5c0508a3 | 1561 | || (r) != (((typeof (r)) 1) << ((rsize) - 1))) \ |
a736ec37 JM |
1562 | { \ |
1563 | _FP_TO_INT_inexact = 0; \ | |
1564 | FP_SET_EXCEPTION (FP_EX_INVALID | FP_EX_INVALID_CVI); \ | |
1565 | } \ | |
1566 | } \ | |
1567 | if (_FP_TO_INT_inexact) \ | |
1568 | FP_SET_EXCEPTION (FP_EX_INEXACT); \ | |
1e145589 | 1569 | } \ |
fe0b1e85 | 1570 | } \ |
1e145589 JM |
1571 | while (0) |
1572 | ||
2004e7fb JM |
1573 | /* Convert from floating point to integer, rounding according to the |
1574 | current rounding direction. Input is raw. RSIGNED is as for | |
1575 | _FP_TO_INT. */ | |
1576 | #define _FP_TO_INT_ROUND(fs, wc, r, X, rsize, rsigned) \ | |
1577 | do \ | |
1578 | { \ | |
d7423856 | 1579 | __label__ _FP_TO_INT_ROUND_done; \ |
2004e7fb JM |
1580 | if (X##_e < _FP_EXPBIAS_##fs) \ |
1581 | { \ | |
1582 | int _FP_TO_INT_ROUND_rounds_away = 0; \ | |
1583 | if (X##_e == 0) \ | |
1584 | { \ | |
1585 | if (_FP_FRAC_ZEROP_##wc (X)) \ | |
1586 | { \ | |
1587 | (r) = 0; \ | |
1588 | goto _FP_TO_INT_ROUND_done; \ | |
1589 | } \ | |
1590 | else \ | |
1591 | { \ | |
1592 | FP_SET_EXCEPTION (FP_EX_DENORM); \ | |
1593 | if (FP_DENORM_ZERO) \ | |
1594 | { \ | |
1595 | (r) = 0; \ | |
1596 | goto _FP_TO_INT_ROUND_done; \ | |
1597 | } \ | |
1598 | } \ | |
1599 | } \ | |
1600 | /* The result is 0, 1 or -1 depending on the rounding mode; \ | |
1601 | -1 may cause overflow in the unsigned case. */ \ | |
1602 | switch (FP_ROUNDMODE) \ | |
1603 | { \ | |
1604 | case FP_RND_NEAREST: \ | |
1605 | _FP_TO_INT_ROUND_rounds_away \ | |
1606 | = (X##_e == _FP_EXPBIAS_##fs - 1 \ | |
1607 | && !_FP_FRAC_ZEROP_##wc (X)); \ | |
1608 | break; \ | |
1609 | case FP_RND_ZERO: \ | |
1610 | /* _FP_TO_INT_ROUND_rounds_away is already 0. */ \ | |
1611 | break; \ | |
1612 | case FP_RND_PINF: \ | |
1613 | _FP_TO_INT_ROUND_rounds_away = !X##_s; \ | |
1614 | break; \ | |
1615 | case FP_RND_MINF: \ | |
1616 | _FP_TO_INT_ROUND_rounds_away = X##_s; \ | |
1617 | break; \ | |
1618 | } \ | |
1619 | if ((rsigned) == 0 && _FP_TO_INT_ROUND_rounds_away && X##_s) \ | |
1620 | { \ | |
1621 | /* Result of -1 for an unsigned conversion. */ \ | |
1622 | (r) = 0; \ | |
1623 | FP_SET_EXCEPTION (FP_EX_INVALID | FP_EX_INVALID_CVI); \ | |
1624 | } \ | |
1625 | else if ((rsize) == 1 && (rsigned) > 0 \ | |
1626 | && _FP_TO_INT_ROUND_rounds_away && !X##_s) \ | |
1627 | { \ | |
1628 | /* Converting to a 1-bit signed bit-field, which cannot \ | |
1629 | represent +1. */ \ | |
1630 | (r) = ((rsigned) == 2 ? -1 : 0); \ | |
1631 | FP_SET_EXCEPTION (FP_EX_INVALID | FP_EX_INVALID_CVI); \ | |
1632 | } \ | |
1633 | else \ | |
1634 | { \ | |
1635 | (r) = (_FP_TO_INT_ROUND_rounds_away \ | |
1636 | ? (X##_s ? -1 : 1) \ | |
1637 | : 0); \ | |
1638 | FP_SET_EXCEPTION (FP_EX_INEXACT); \ | |
1639 | } \ | |
1640 | } \ | |
1641 | else if ((rsigned) == 2 \ | |
1642 | && (X##_e \ | |
1643 | >= ((_FP_EXPMAX_##fs \ | |
1644 | < _FP_EXPBIAS_##fs + _FP_FRACBITS_##fs + (rsize) - 1) \ | |
1645 | ? _FP_EXPMAX_##fs \ | |
1646 | : _FP_EXPBIAS_##fs + _FP_FRACBITS_##fs + (rsize) - 1))) \ | |
1647 | { \ | |
1648 | /* Overflow resulting in 0. */ \ | |
1649 | (r) = 0; \ | |
1650 | FP_SET_EXCEPTION (FP_EX_INVALID \ | |
1651 | | FP_EX_INVALID_CVI \ | |
1652 | | ((FP_EX_INVALID_SNAN \ | |
1653 | && _FP_ISSIGNAN (fs, wc, X)) \ | |
1654 | ? FP_EX_INVALID_SNAN \ | |
1655 | : 0)); \ | |
1656 | } \ | |
1657 | else if ((rsigned) != 2 \ | |
1658 | && (X##_e >= (_FP_EXPMAX_##fs < _FP_EXPBIAS_##fs + (rsize) \ | |
1659 | ? _FP_EXPMAX_##fs \ | |
1660 | : (_FP_EXPBIAS_##fs + (rsize) \ | |
1661 | - ((rsigned) > 0 && !X##_s))) \ | |
1662 | || ((rsigned) == 0 && X##_s))) \ | |
1663 | { \ | |
1664 | /* Definite overflow (does not require rounding to tell). */ \ | |
1665 | if ((rsigned) != 0) \ | |
1666 | { \ | |
1667 | (r) = 1; \ | |
1668 | (r) <<= (rsize) - 1; \ | |
1669 | (r) -= 1 - X##_s; \ | |
1670 | } \ | |
1671 | else \ | |
1672 | { \ | |
1673 | (r) = 0; \ | |
1674 | if (!X##_s) \ | |
1675 | (r) = ~(r); \ | |
1676 | } \ | |
1677 | \ | |
1678 | FP_SET_EXCEPTION (FP_EX_INVALID \ | |
1679 | | FP_EX_INVALID_CVI \ | |
1680 | | ((FP_EX_INVALID_SNAN \ | |
1681 | && _FP_ISSIGNAN (fs, wc, X)) \ | |
1682 | ? FP_EX_INVALID_SNAN \ | |
1683 | : 0)); \ | |
1684 | } \ | |
1685 | else \ | |
1686 | { \ | |
1687 | /* The value is finite, with magnitude at least 1. If \ | |
1688 | the conversion is unsigned, the value is positive. \ | |
1689 | If RSIGNED is not 2, the value does not definitely \ | |
1690 | overflow by virtue of its exponent, but may still turn \ | |
1691 | out to overflow after rounding; if RSIGNED is 2, the \ | |
1692 | exponent may be such that the value definitely overflows, \ | |
1693 | but at least one mantissa bit will not be shifted out. */ \ | |
1694 | int _FP_TO_INT_ROUND_inexact = 0; \ | |
1695 | _FP_FRAC_HIGH_RAW_##fs (X) |= _FP_IMPLBIT_##fs; \ | |
1696 | if (X##_e >= _FP_EXPBIAS_##fs + _FP_FRACBITS_##fs - 1) \ | |
1697 | { \ | |
1698 | /* The value is an integer, no rounding needed. */ \ | |
1699 | _FP_FRAC_ASSEMBLE_##wc ((r), X, (rsize)); \ | |
1700 | (r) <<= X##_e - _FP_EXPBIAS_##fs - _FP_FRACBITS_##fs + 1; \ | |
1701 | } \ | |
1702 | else \ | |
1703 | { \ | |
1704 | /* May need to shift in order to round (unless there \ | |
1705 | are exactly _FP_WORKBITS fractional bits already). */ \ | |
1706 | int _FP_TO_INT_ROUND_rshift \ | |
1707 | = (_FP_FRACBITS_##fs + _FP_EXPBIAS_##fs \ | |
1708 | - 1 - _FP_WORKBITS - X##_e); \ | |
1709 | if (_FP_TO_INT_ROUND_rshift > 0) \ | |
1710 | _FP_FRAC_SRS_##wc (X, _FP_TO_INT_ROUND_rshift, \ | |
1711 | _FP_WFRACBITS_##fs); \ | |
1712 | else if (_FP_TO_INT_ROUND_rshift < 0) \ | |
1713 | _FP_FRAC_SLL_##wc (X, -_FP_TO_INT_ROUND_rshift); \ | |
1714 | /* Round like _FP_ROUND, but setting \ | |
1715 | _FP_TO_INT_ROUND_inexact instead of directly setting \ | |
1716 | the "inexact" exception, since it may turn out we \ | |
1717 | should set "invalid" instead. */ \ | |
1718 | if (_FP_FRAC_LOW_##wc (X) & 7) \ | |
1719 | { \ | |
1720 | _FP_TO_INT_ROUND_inexact = 1; \ | |
1721 | switch (FP_ROUNDMODE) \ | |
1722 | { \ | |
1723 | case FP_RND_NEAREST: \ | |
1724 | _FP_ROUND_NEAREST (wc, X); \ | |
1725 | break; \ | |
1726 | case FP_RND_ZERO: \ | |
1727 | _FP_ROUND_ZERO (wc, X); \ | |
1728 | break; \ | |
1729 | case FP_RND_PINF: \ | |
1730 | _FP_ROUND_PINF (wc, X); \ | |
1731 | break; \ | |
1732 | case FP_RND_MINF: \ | |
1733 | _FP_ROUND_MINF (wc, X); \ | |
1734 | break; \ | |
1735 | } \ | |
1736 | } \ | |
1737 | _FP_FRAC_SRL_##wc (X, _FP_WORKBITS); \ | |
1738 | _FP_FRAC_ASSEMBLE_##wc ((r), X, (rsize)); \ | |
1739 | } \ | |
1740 | if ((rsigned) != 0 && X##_s) \ | |
1741 | (r) = -(r); \ | |
1742 | /* An exponent of RSIZE - 1 always needs testing for \ | |
1743 | overflow (either directly overflowing, or overflowing \ | |
1744 | when rounding up results in 2^RSIZE). An exponent of \ | |
1745 | RSIZE - 2 can overflow for positive values when rounding \ | |
1746 | up to 2^(RSIZE-1), but cannot overflow for negative \ | |
1747 | values. Smaller exponents cannot overflow. */ \ | |
1748 | if (X##_e >= (_FP_EXPBIAS_##fs + (rsize) - 1 \ | |
1749 | - ((rsigned) > 0 && !X##_s))) \ | |
1750 | { \ | |
1751 | if (X##_e > _FP_EXPBIAS_##fs + (rsize) - 1 \ | |
1752 | || (X##_e == _FP_EXPBIAS_##fs + (rsize) - 1 \ | |
1753 | && (X##_s \ | |
1754 | ? (r) != (((typeof (r)) 1) << ((rsize) - 1)) \ | |
1755 | : ((rsigned) > 0 || (r) == 0))) \ | |
1756 | || ((rsigned) > 0 \ | |
1757 | && !X##_s \ | |
1758 | && X##_e == _FP_EXPBIAS_##fs + (rsize) - 2 \ | |
1759 | && (r) == (((typeof (r)) 1) << ((rsize) - 1)))) \ | |
1760 | { \ | |
1761 | if ((rsigned) != 2) \ | |
1762 | { \ | |
1763 | if ((rsigned) != 0) \ | |
1764 | { \ | |
1765 | (r) = 1; \ | |
1766 | (r) <<= (rsize) - 1; \ | |
1767 | (r) -= 1 - X##_s; \ | |
1768 | } \ | |
1769 | else \ | |
1770 | { \ | |
1771 | (r) = 0; \ | |
1772 | (r) = ~(r); \ | |
1773 | } \ | |
1774 | } \ | |
1775 | _FP_TO_INT_ROUND_inexact = 0; \ | |
1776 | FP_SET_EXCEPTION (FP_EX_INVALID | FP_EX_INVALID_CVI); \ | |
1777 | } \ | |
1778 | } \ | |
1779 | if (_FP_TO_INT_ROUND_inexact) \ | |
1780 | FP_SET_EXCEPTION (FP_EX_INEXACT); \ | |
1781 | } \ | |
1782 | _FP_TO_INT_ROUND_done: ; \ | |
1783 | } \ | |
1784 | while (0) | |
1785 | ||
1e145589 JM |
1786 | /* Convert integer to fp. Output is raw. RTYPE is unsigned even if |
1787 | input is signed. */ | |
1788 | #define _FP_FROM_INT(fs, wc, X, r, rsize, rtype) \ | |
1789 | do \ | |
fe0b1e85 | 1790 | { \ |
d7423856 | 1791 | __label__ pack_semiraw; \ |
1e145589 | 1792 | if (r) \ |
fe0b1e85 | 1793 | { \ |
9c37ec0b | 1794 | rtype _FP_FROM_INT_ur; \ |
1e145589 | 1795 | \ |
5c0508a3 JM |
1796 | if ((X##_s = ((r) < 0))) \ |
1797 | (r) = -(rtype) (r); \ | |
1e145589 | 1798 | \ |
5c0508a3 JM |
1799 | _FP_FROM_INT_ur = (rtype) (r); \ |
1800 | (void) (((rsize) <= _FP_W_TYPE_SIZE) \ | |
51ca9e29 | 1801 | ? ({ \ |
9c37ec0b JM |
1802 | int _FP_FROM_INT_lz; \ |
1803 | __FP_CLZ (_FP_FROM_INT_lz, \ | |
1804 | (_FP_W_TYPE) _FP_FROM_INT_ur); \ | |
1805 | X##_e = (_FP_EXPBIAS_##fs + _FP_W_TYPE_SIZE - 1 \ | |
1806 | - _FP_FROM_INT_lz); \ | |
51ca9e29 | 1807 | }) \ |
5c0508a3 | 1808 | : (((rsize) <= 2 * _FP_W_TYPE_SIZE) \ |
51ca9e29 | 1809 | ? ({ \ |
9c37ec0b JM |
1810 | int _FP_FROM_INT_lz; \ |
1811 | __FP_CLZ_2 (_FP_FROM_INT_lz, \ | |
1812 | (_FP_W_TYPE) (_FP_FROM_INT_ur \ | |
1813 | >> _FP_W_TYPE_SIZE), \ | |
1814 | (_FP_W_TYPE) _FP_FROM_INT_ur); \ | |
51ca9e29 | 1815 | X##_e = (_FP_EXPBIAS_##fs + 2 * _FP_W_TYPE_SIZE - 1 \ |
9c37ec0b | 1816 | - _FP_FROM_INT_lz); \ |
51ca9e29 JM |
1817 | }) \ |
1818 | : (abort (), 0))); \ | |
1e145589 | 1819 | \ |
5c0508a3 | 1820 | if ((rsize) - 1 + _FP_EXPBIAS_##fs >= _FP_EXPMAX_##fs \ |
1e145589 JM |
1821 | && X##_e >= _FP_EXPMAX_##fs) \ |
1822 | { \ | |
1823 | /* Exponent too big; overflow to infinity. (May also \ | |
1824 | happen after rounding below.) */ \ | |
51ca9e29 | 1825 | _FP_OVERFLOW_SEMIRAW (fs, wc, X); \ |
1e145589 JM |
1826 | goto pack_semiraw; \ |
1827 | } \ | |
1828 | \ | |
5c0508a3 | 1829 | if ((rsize) <= _FP_FRACBITS_##fs \ |
1e145589 JM |
1830 | || X##_e < _FP_EXPBIAS_##fs + _FP_FRACBITS_##fs) \ |
1831 | { \ | |
1832 | /* Exactly representable; shift left. */ \ | |
5c0508a3 | 1833 | _FP_FRAC_DISASSEMBLE_##wc (X, _FP_FROM_INT_ur, (rsize)); \ |
1e145589 | 1834 | if (_FP_EXPBIAS_##fs + _FP_FRACBITS_##fs - 1 - X##_e > 0) \ |
51ca9e29 JM |
1835 | _FP_FRAC_SLL_##wc (X, (_FP_EXPBIAS_##fs \ |
1836 | + _FP_FRACBITS_##fs - 1 - X##_e)); \ | |
1e145589 JM |
1837 | } \ |
1838 | else \ | |
1839 | { \ | |
1840 | /* More bits in integer than in floating type; need to \ | |
1841 | round. */ \ | |
1842 | if (_FP_EXPBIAS_##fs + _FP_WFRACBITS_##fs - 1 < X##_e) \ | |
9c37ec0b JM |
1843 | _FP_FROM_INT_ur \ |
1844 | = ((_FP_FROM_INT_ur >> (X##_e - _FP_EXPBIAS_##fs \ | |
1845 | - _FP_WFRACBITS_##fs + 1)) \ | |
1846 | | ((_FP_FROM_INT_ur \ | |
5c0508a3 JM |
1847 | << ((rsize) - (X##_e - _FP_EXPBIAS_##fs \ |
1848 | - _FP_WFRACBITS_##fs + 1))) \ | |
9c37ec0b | 1849 | != 0)); \ |
5c0508a3 | 1850 | _FP_FRAC_DISASSEMBLE_##wc (X, _FP_FROM_INT_ur, (rsize)); \ |
1e145589 | 1851 | if ((_FP_EXPBIAS_##fs + _FP_WFRACBITS_##fs - 1 - X##_e) > 0) \ |
51ca9e29 JM |
1852 | _FP_FRAC_SLL_##wc (X, (_FP_EXPBIAS_##fs \ |
1853 | + _FP_WFRACBITS_##fs - 1 - X##_e)); \ | |
1854 | _FP_FRAC_HIGH_##fs (X) &= ~(_FP_W_TYPE) _FP_IMPLBIT_SH_##fs; \ | |
1e145589 | 1855 | pack_semiraw: \ |
51ca9e29 | 1856 | _FP_PACK_SEMIRAW (fs, wc, X); \ |
1e145589 | 1857 | } \ |
fe0b1e85 RM |
1858 | } \ |
1859 | else \ | |
1860 | { \ | |
1e145589 JM |
1861 | X##_s = 0; \ |
1862 | X##_e = 0; \ | |
51ca9e29 | 1863 | _FP_FRAC_SET_##wc (X, _FP_ZEROFRAC_##wc); \ |
fe0b1e85 | 1864 | } \ |
fe0b1e85 | 1865 | } \ |
1e145589 | 1866 | while (0) |
d876f532 | 1867 | |
0ecb606c | 1868 | |
fe0b1e85 | 1869 | /* Extend from a narrower floating-point format to a wider one. Input |
639e42eb JM |
1870 | and output are raw. If CHECK_NAN, then signaling NaNs are |
1871 | converted to quiet with the "invalid" exception raised; otherwise | |
1872 | signaling NaNs remain signaling with no exception. */ | |
1873 | #define _FP_EXTEND_CNAN(dfs, sfs, dwc, swc, D, S, check_nan) \ | |
1e145589 JM |
1874 | do \ |
1875 | { \ | |
1876 | if (_FP_FRACBITS_##dfs < _FP_FRACBITS_##sfs \ | |
1877 | || (_FP_EXPMAX_##dfs - _FP_EXPBIAS_##dfs \ | |
1878 | < _FP_EXPMAX_##sfs - _FP_EXPBIAS_##sfs) \ | |
1879 | || (_FP_EXPBIAS_##dfs < _FP_EXPBIAS_##sfs + _FP_FRACBITS_##sfs - 1 \ | |
1880 | && _FP_EXPBIAS_##dfs != _FP_EXPBIAS_##sfs)) \ | |
51ca9e29 | 1881 | abort (); \ |
1e145589 | 1882 | D##_s = S##_s; \ |
51ca9e29 JM |
1883 | _FP_FRAC_COPY_##dwc##_##swc (D, S); \ |
1884 | if (_FP_EXP_NORMAL (sfs, swc, S)) \ | |
1e145589 JM |
1885 | { \ |
1886 | D##_e = S##_e + _FP_EXPBIAS_##dfs - _FP_EXPBIAS_##sfs; \ | |
51ca9e29 | 1887 | _FP_FRAC_SLL_##dwc (D, (_FP_FRACBITS_##dfs - _FP_FRACBITS_##sfs)); \ |
1e145589 JM |
1888 | } \ |
1889 | else \ | |
1890 | { \ | |
1891 | if (S##_e == 0) \ | |
1892 | { \ | |
454ac701 | 1893 | _FP_CHECK_FLUSH_ZERO (sfs, swc, S); \ |
51ca9e29 | 1894 | if (_FP_FRAC_ZEROP_##swc (S)) \ |
1e145589 JM |
1895 | D##_e = 0; \ |
1896 | else if (_FP_EXPBIAS_##dfs \ | |
1897 | < _FP_EXPBIAS_##sfs + _FP_FRACBITS_##sfs - 1) \ | |
1898 | { \ | |
51ca9e29 JM |
1899 | FP_SET_EXCEPTION (FP_EX_DENORM); \ |
1900 | _FP_FRAC_SLL_##dwc (D, (_FP_FRACBITS_##dfs \ | |
1901 | - _FP_FRACBITS_##sfs)); \ | |
1e145589 | 1902 | D##_e = 0; \ |
43059f42 JM |
1903 | if (FP_TRAPPING_EXCEPTIONS & FP_EX_UNDERFLOW) \ |
1904 | FP_SET_EXCEPTION (FP_EX_UNDERFLOW); \ | |
1e145589 JM |
1905 | } \ |
1906 | else \ | |
1907 | { \ | |
9c37ec0b | 1908 | int FP_EXTEND_lz; \ |
51ca9e29 | 1909 | FP_SET_EXCEPTION (FP_EX_DENORM); \ |
9c37ec0b | 1910 | _FP_FRAC_CLZ_##swc (FP_EXTEND_lz, S); \ |
51ca9e29 | 1911 | _FP_FRAC_SLL_##dwc (D, \ |
9c37ec0b | 1912 | FP_EXTEND_lz + _FP_FRACBITS_##dfs \ |
51ca9e29 | 1913 | - _FP_FRACTBITS_##sfs); \ |
1e145589 | 1914 | D##_e = (_FP_EXPBIAS_##dfs - _FP_EXPBIAS_##sfs + 1 \ |
9c37ec0b | 1915 | + _FP_FRACXBITS_##sfs - FP_EXTEND_lz); \ |
1e145589 JM |
1916 | } \ |
1917 | } \ | |
1918 | else \ | |
1919 | { \ | |
1920 | D##_e = _FP_EXPMAX_##dfs; \ | |
51ca9e29 | 1921 | if (!_FP_FRAC_ZEROP_##swc (S)) \ |
1e145589 | 1922 | { \ |
639e42eb | 1923 | if (check_nan && _FP_FRAC_SNANP (sfs, S)) \ |
ff12c11f JM |
1924 | FP_SET_EXCEPTION (FP_EX_INVALID \ |
1925 | | FP_EX_INVALID_SNAN); \ | |
51ca9e29 JM |
1926 | _FP_FRAC_SLL_##dwc (D, (_FP_FRACBITS_##dfs \ |
1927 | - _FP_FRACBITS_##sfs)); \ | |
639e42eb JM |
1928 | if (check_nan) \ |
1929 | _FP_SETQNAN (dfs, dwc, D); \ | |
1e145589 JM |
1930 | } \ |
1931 | } \ | |
1932 | } \ | |
1933 | } \ | |
1934 | while (0) | |
fe0b1e85 | 1935 | |
639e42eb JM |
1936 | #define FP_EXTEND(dfs, sfs, dwc, swc, D, S) \ |
1937 | _FP_EXTEND_CNAN (dfs, sfs, dwc, swc, D, S, 1) | |
1938 | ||
fe0b1e85 RM |
1939 | /* Truncate from a wider floating-point format to a narrower one. |
1940 | Input and output are semi-raw. */ | |
51ca9e29 | 1941 | #define FP_TRUNC(dfs, sfs, dwc, swc, D, S) \ |
1e145589 JM |
1942 | do \ |
1943 | { \ | |
1944 | if (_FP_FRACBITS_##sfs < _FP_FRACBITS_##dfs \ | |
1945 | || (_FP_EXPBIAS_##sfs < _FP_EXPBIAS_##dfs + _FP_FRACBITS_##dfs - 1 \ | |
1946 | && _FP_EXPBIAS_##sfs != _FP_EXPBIAS_##dfs)) \ | |
51ca9e29 | 1947 | abort (); \ |
1e145589 | 1948 | D##_s = S##_s; \ |
51ca9e29 | 1949 | if (_FP_EXP_NORMAL (sfs, swc, S)) \ |
1e145589 JM |
1950 | { \ |
1951 | D##_e = S##_e + _FP_EXPBIAS_##dfs - _FP_EXPBIAS_##sfs; \ | |
1952 | if (D##_e >= _FP_EXPMAX_##dfs) \ | |
51ca9e29 | 1953 | _FP_OVERFLOW_SEMIRAW (dfs, dwc, D); \ |
1e145589 JM |
1954 | else \ |
1955 | { \ | |
1956 | if (D##_e <= 0) \ | |
1957 | { \ | |
1958 | if (D##_e < 1 - _FP_FRACBITS_##dfs) \ | |
1959 | { \ | |
51ca9e29 JM |
1960 | _FP_FRAC_SET_##swc (S, _FP_ZEROFRAC_##swc); \ |
1961 | _FP_FRAC_LOW_##swc (S) |= 1; \ | |
1e145589 JM |
1962 | } \ |
1963 | else \ | |
1964 | { \ | |
51ca9e29 JM |
1965 | _FP_FRAC_HIGH_##sfs (S) |= _FP_IMPLBIT_SH_##sfs; \ |
1966 | _FP_FRAC_SRS_##swc (S, (_FP_WFRACBITS_##sfs \ | |
1967 | - _FP_WFRACBITS_##dfs \ | |
1968 | + 1 - D##_e), \ | |
1969 | _FP_WFRACBITS_##sfs); \ | |
1e145589 JM |
1970 | } \ |
1971 | D##_e = 0; \ | |
1972 | } \ | |
1973 | else \ | |
51ca9e29 JM |
1974 | _FP_FRAC_SRS_##swc (S, (_FP_WFRACBITS_##sfs \ |
1975 | - _FP_WFRACBITS_##dfs), \ | |
1976 | _FP_WFRACBITS_##sfs); \ | |
1977 | _FP_FRAC_COPY_##dwc##_##swc (D, S); \ | |
1e145589 JM |
1978 | } \ |
1979 | } \ | |
1980 | else \ | |
1981 | { \ | |
1982 | if (S##_e == 0) \ | |
1983 | { \ | |
454ac701 | 1984 | _FP_CHECK_FLUSH_ZERO (sfs, swc, S); \ |
1e145589 | 1985 | D##_e = 0; \ |
51ca9e29 JM |
1986 | if (_FP_FRAC_ZEROP_##swc (S)) \ |
1987 | _FP_FRAC_SET_##dwc (D, _FP_ZEROFRAC_##dwc); \ | |
1e145589 JM |
1988 | else \ |
1989 | { \ | |
51ca9e29 | 1990 | FP_SET_EXCEPTION (FP_EX_DENORM); \ |
1e145589 JM |
1991 | if (_FP_EXPBIAS_##sfs \ |
1992 | < _FP_EXPBIAS_##dfs + _FP_FRACBITS_##dfs - 1) \ | |
1993 | { \ | |
51ca9e29 JM |
1994 | _FP_FRAC_SRS_##swc (S, (_FP_WFRACBITS_##sfs \ |
1995 | - _FP_WFRACBITS_##dfs), \ | |
1996 | _FP_WFRACBITS_##sfs); \ | |
1997 | _FP_FRAC_COPY_##dwc##_##swc (D, S); \ | |
1e145589 JM |
1998 | } \ |
1999 | else \ | |
2000 | { \ | |
51ca9e29 JM |
2001 | _FP_FRAC_SET_##dwc (D, _FP_ZEROFRAC_##dwc); \ |
2002 | _FP_FRAC_LOW_##dwc (D) |= 1; \ | |
1e145589 JM |
2003 | } \ |
2004 | } \ | |
2005 | } \ | |
2006 | else \ | |
2007 | { \ | |
2008 | D##_e = _FP_EXPMAX_##dfs; \ | |
51ca9e29 JM |
2009 | if (_FP_FRAC_ZEROP_##swc (S)) \ |
2010 | _FP_FRAC_SET_##dwc (D, _FP_ZEROFRAC_##dwc); \ | |
1e145589 JM |
2011 | else \ |
2012 | { \ | |
51ca9e29 JM |
2013 | _FP_CHECK_SIGNAN_SEMIRAW (sfs, swc, S); \ |
2014 | _FP_FRAC_SRL_##swc (S, (_FP_WFRACBITS_##sfs \ | |
2015 | - _FP_WFRACBITS_##dfs)); \ | |
2016 | _FP_FRAC_COPY_##dwc##_##swc (D, S); \ | |
1e145589 | 2017 | /* Semi-raw NaN must have all workbits cleared. */ \ |
51ca9e29 | 2018 | _FP_FRAC_LOW_##dwc (D) \ |
1e145589 | 2019 | &= ~(_FP_W_TYPE) ((1 << _FP_WORKBITS) - 1); \ |
51ca9e29 | 2020 | _FP_SETQNAN_SEMIRAW (dfs, dwc, D); \ |
1e145589 JM |
2021 | } \ |
2022 | } \ | |
2023 | } \ | |
2024 | } \ | |
2025 | while (0) | |
d876f532 | 2026 | |
c4fe3ea7 | 2027 | /* Helper primitives. */ |
d876f532 UD |
2028 | |
2029 | /* Count leading zeros in a word. */ | |
2030 | ||
2031 | #ifndef __FP_CLZ | |
0d86378f | 2032 | /* GCC 3.4 and later provide the builtins for us. */ |
1e145589 JM |
2033 | # define __FP_CLZ(r, x) \ |
2034 | do \ | |
2035 | { \ | |
2036 | if (sizeof (_FP_W_TYPE) == sizeof (unsigned int)) \ | |
5c0508a3 | 2037 | (r) = __builtin_clz (x); \ |
1e145589 | 2038 | else if (sizeof (_FP_W_TYPE) == sizeof (unsigned long)) \ |
5c0508a3 | 2039 | (r) = __builtin_clzl (x); \ |
1e145589 | 2040 | else if (sizeof (_FP_W_TYPE) == sizeof (unsigned long long)) \ |
5c0508a3 | 2041 | (r) = __builtin_clzll (x); \ |
1e145589 JM |
2042 | else \ |
2043 | abort (); \ | |
2044 | } \ | |
2045 | while (0) | |
d876f532 UD |
2046 | #endif /* ndef __FP_CLZ */ |
2047 | ||
2048 | #define _FP_DIV_HELP_imm(q, r, n, d) \ | |
1e145589 JM |
2049 | do \ |
2050 | { \ | |
5c0508a3 | 2051 | (q) = (n) / (d), (r) = (n) % (d); \ |
1e145589 JM |
2052 | } \ |
2053 | while (0) | |
d876f532 | 2054 | |
1a8aaf91 UD |
2055 | |
2056 | /* A restoring bit-by-bit division primitive. */ | |
2057 | ||
2058 | #define _FP_DIV_MEAT_N_loop(fs, wc, R, X, Y) \ | |
1e145589 JM |
2059 | do \ |
2060 | { \ | |
9c37ec0b JM |
2061 | int _FP_DIV_MEAT_N_loop_count = _FP_WFRACBITS_##fs; \ |
2062 | _FP_FRAC_DECL_##wc (_FP_DIV_MEAT_N_loop_u); \ | |
2063 | _FP_FRAC_DECL_##wc (_FP_DIV_MEAT_N_loop_v); \ | |
2064 | _FP_FRAC_COPY_##wc (_FP_DIV_MEAT_N_loop_u, X); \ | |
2065 | _FP_FRAC_COPY_##wc (_FP_DIV_MEAT_N_loop_v, Y); \ | |
1e145589 | 2066 | _FP_FRAC_SET_##wc (R, _FP_ZEROFRAC_##wc); \ |
9c37ec0b JM |
2067 | /* Normalize _FP_DIV_MEAT_N_LOOP_U and _FP_DIV_MEAT_N_LOOP_V. */ \ |
2068 | _FP_FRAC_SLL_##wc (_FP_DIV_MEAT_N_loop_u, _FP_WFRACXBITS_##fs); \ | |
2069 | _FP_FRAC_SLL_##wc (_FP_DIV_MEAT_N_loop_v, _FP_WFRACXBITS_##fs); \ | |
1e145589 JM |
2070 | /* First round. Since the operands are normalized, either the \ |
2071 | first or second bit will be set in the fraction. Produce a \ | |
2072 | normalized result by checking which and adjusting the loop \ | |
2073 | count and exponent accordingly. */ \ | |
9c37ec0b | 2074 | if (_FP_FRAC_GE_1 (_FP_DIV_MEAT_N_loop_u, _FP_DIV_MEAT_N_loop_v)) \ |
1a8aaf91 | 2075 | { \ |
9c37ec0b JM |
2076 | _FP_FRAC_SUB_##wc (_FP_DIV_MEAT_N_loop_u, \ |
2077 | _FP_DIV_MEAT_N_loop_u, \ | |
2078 | _FP_DIV_MEAT_N_loop_v); \ | |
1a8aaf91 | 2079 | _FP_FRAC_LOW_##wc (R) |= 1; \ |
9c37ec0b | 2080 | _FP_DIV_MEAT_N_loop_count--; \ |
1a8aaf91 | 2081 | } \ |
1e145589 JM |
2082 | else \ |
2083 | R##_e--; \ | |
2084 | /* Subsequent rounds. */ \ | |
2085 | do \ | |
2086 | { \ | |
9c37ec0b JM |
2087 | int _FP_DIV_MEAT_N_loop_msb \ |
2088 | = (_FP_WS_TYPE) _FP_FRAC_HIGH_##wc (_FP_DIV_MEAT_N_loop_u) < 0; \ | |
2089 | _FP_FRAC_SLL_##wc (_FP_DIV_MEAT_N_loop_u, 1); \ | |
1e145589 | 2090 | _FP_FRAC_SLL_##wc (R, 1); \ |
9c37ec0b JM |
2091 | if (_FP_DIV_MEAT_N_loop_msb \ |
2092 | || _FP_FRAC_GE_1 (_FP_DIV_MEAT_N_loop_u, \ | |
2093 | _FP_DIV_MEAT_N_loop_v)) \ | |
1e145589 | 2094 | { \ |
9c37ec0b JM |
2095 | _FP_FRAC_SUB_##wc (_FP_DIV_MEAT_N_loop_u, \ |
2096 | _FP_DIV_MEAT_N_loop_u, \ | |
2097 | _FP_DIV_MEAT_N_loop_v); \ | |
1e145589 JM |
2098 | _FP_FRAC_LOW_##wc (R) |= 1; \ |
2099 | } \ | |
2100 | } \ | |
9c37ec0b JM |
2101 | while (--_FP_DIV_MEAT_N_loop_count > 0); \ |
2102 | /* If there's anything left in _FP_DIV_MEAT_N_LOOP_U, the result \ | |
2103 | is inexact. */ \ | |
2104 | _FP_FRAC_LOW_##wc (R) \ | |
2105 | |= !_FP_FRAC_ZEROP_##wc (_FP_DIV_MEAT_N_loop_u); \ | |
1e145589 JM |
2106 | } \ |
2107 | while (0) | |
1a8aaf91 UD |
2108 | |
2109 | #define _FP_DIV_MEAT_1_loop(fs, R, X, Y) _FP_DIV_MEAT_N_loop (fs, 1, R, X, Y) | |
2110 | #define _FP_DIV_MEAT_2_loop(fs, R, X, Y) _FP_DIV_MEAT_N_loop (fs, 2, R, X, Y) | |
2111 | #define _FP_DIV_MEAT_4_loop(fs, R, X, Y) _FP_DIV_MEAT_N_loop (fs, 4, R, X, Y) |