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