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