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