diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /include/math-emu/op-common.h |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'include/math-emu/op-common.h')
-rw-r--r-- | include/math-emu/op-common.h | 853 |
1 files changed, 853 insertions, 0 deletions
diff --git a/include/math-emu/op-common.h b/include/math-emu/op-common.h new file mode 100644 index 000000000000..93780abd01bc --- /dev/null +++ b/include/math-emu/op-common.h | |||
@@ -0,0 +1,853 @@ | |||
1 | /* Software floating-point emulation. Common operations. | ||
2 | Copyright (C) 1997,1998,1999 Free Software Foundation, Inc. | ||
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 | ||
10 | modify it under the terms of the GNU Library General Public License as | ||
11 | published by the Free Software Foundation; either version 2 of the | ||
12 | License, or (at your option) any later version. | ||
13 | |||
14 | The GNU C Library is distributed in the hope that it will be useful, | ||
15 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | Library General Public License for more details. | ||
18 | |||
19 | You should have received a copy of the GNU Library General Public | ||
20 | License along with the GNU C Library; see the file COPYING.LIB. If | ||
21 | not, write to the Free Software Foundation, Inc., | ||
22 | 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | ||
23 | |||
24 | #ifndef __MATH_EMU_OP_COMMON_H__ | ||
25 | #define __MATH_EMU_OP_COMMON_H__ | ||
26 | |||
27 | #define _FP_DECL(wc, X) \ | ||
28 | _FP_I_TYPE X##_c=0, X##_s=0, X##_e=0; \ | ||
29 | _FP_FRAC_DECL_##wc(X) | ||
30 | |||
31 | /* | ||
32 | * Finish truely unpacking a native fp value by classifying the kind | ||
33 | * of fp value and normalizing both the exponent and the fraction. | ||
34 | */ | ||
35 | |||
36 | #define _FP_UNPACK_CANONICAL(fs, wc, X) \ | ||
37 | do { \ | ||
38 | switch (X##_e) \ | ||
39 | { \ | ||
40 | default: \ | ||
41 | _FP_FRAC_HIGH_RAW_##fs(X) |= _FP_IMPLBIT_##fs; \ | ||
42 | _FP_FRAC_SLL_##wc(X, _FP_WORKBITS); \ | ||
43 | X##_e -= _FP_EXPBIAS_##fs; \ | ||
44 | X##_c = FP_CLS_NORMAL; \ | ||
45 | break; \ | ||
46 | \ | ||
47 | case 0: \ | ||
48 | if (_FP_FRAC_ZEROP_##wc(X)) \ | ||
49 | X##_c = FP_CLS_ZERO; \ | ||
50 | else \ | ||
51 | { \ | ||
52 | /* a denormalized number */ \ | ||
53 | _FP_I_TYPE _shift; \ | ||
54 | _FP_FRAC_CLZ_##wc(_shift, X); \ | ||
55 | _shift -= _FP_FRACXBITS_##fs; \ | ||
56 | _FP_FRAC_SLL_##wc(X, (_shift+_FP_WORKBITS)); \ | ||
57 | X##_e -= _FP_EXPBIAS_##fs - 1 + _shift; \ | ||
58 | X##_c = FP_CLS_NORMAL; \ | ||
59 | FP_SET_EXCEPTION(FP_EX_DENORM); \ | ||
60 | if (FP_DENORM_ZERO) \ | ||
61 | { \ | ||
62 | FP_SET_EXCEPTION(FP_EX_INEXACT); \ | ||
63 | X##_c = FP_CLS_ZERO; \ | ||
64 | } \ | ||
65 | } \ | ||
66 | break; \ | ||
67 | \ | ||
68 | case _FP_EXPMAX_##fs: \ | ||
69 | if (_FP_FRAC_ZEROP_##wc(X)) \ | ||
70 | X##_c = FP_CLS_INF; \ | ||
71 | else \ | ||
72 | { \ | ||
73 | X##_c = FP_CLS_NAN; \ | ||
74 | /* Check for signaling NaN */ \ | ||
75 | if (!(_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs)) \ | ||
76 | FP_SET_EXCEPTION(FP_EX_INVALID); \ | ||
77 | } \ | ||
78 | break; \ | ||
79 | } \ | ||
80 | } while (0) | ||
81 | |||
82 | /* | ||
83 | * Before packing the bits back into the native fp result, take care | ||
84 | * of such mundane things as rounding and overflow. Also, for some | ||
85 | * kinds of fp values, the original parts may not have been fully | ||
86 | * extracted -- but that is ok, we can regenerate them now. | ||
87 | */ | ||
88 | |||
89 | #define _FP_PACK_CANONICAL(fs, wc, X) \ | ||
90 | do { \ | ||
91 | switch (X##_c) \ | ||
92 | { \ | ||
93 | case FP_CLS_NORMAL: \ | ||
94 | X##_e += _FP_EXPBIAS_##fs; \ | ||
95 | if (X##_e > 0) \ | ||
96 | { \ | ||
97 | _FP_ROUND(wc, X); \ | ||
98 | if (_FP_FRAC_OVERP_##wc(fs, X)) \ | ||
99 | { \ | ||
100 | _FP_FRAC_CLEAR_OVERP_##wc(fs, X); \ | ||
101 | X##_e++; \ | ||
102 | } \ | ||
103 | _FP_FRAC_SRL_##wc(X, _FP_WORKBITS); \ | ||
104 | if (X##_e >= _FP_EXPMAX_##fs) \ | ||
105 | { \ | ||
106 | /* overflow */ \ | ||
107 | switch (FP_ROUNDMODE) \ | ||
108 | { \ | ||
109 | case FP_RND_NEAREST: \ | ||
110 | X##_c = FP_CLS_INF; \ | ||
111 | break; \ | ||
112 | case FP_RND_PINF: \ | ||
113 | if (!X##_s) X##_c = FP_CLS_INF; \ | ||
114 | break; \ | ||
115 | case FP_RND_MINF: \ | ||
116 | if (X##_s) X##_c = FP_CLS_INF; \ | ||
117 | break; \ | ||
118 | } \ | ||
119 | if (X##_c == FP_CLS_INF) \ | ||
120 | { \ | ||
121 | /* Overflow to infinity */ \ | ||
122 | X##_e = _FP_EXPMAX_##fs; \ | ||
123 | _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \ | ||
124 | } \ | ||
125 | else \ | ||
126 | { \ | ||
127 | /* Overflow to maximum normal */ \ | ||
128 | X##_e = _FP_EXPMAX_##fs - 1; \ | ||
129 | _FP_FRAC_SET_##wc(X, _FP_MAXFRAC_##wc); \ | ||
130 | } \ | ||
131 | FP_SET_EXCEPTION(FP_EX_OVERFLOW); \ | ||
132 | FP_SET_EXCEPTION(FP_EX_INEXACT); \ | ||
133 | } \ | ||
134 | } \ | ||
135 | else \ | ||
136 | { \ | ||
137 | /* we've got a denormalized number */ \ | ||
138 | X##_e = -X##_e + 1; \ | ||
139 | if (X##_e <= _FP_WFRACBITS_##fs) \ | ||
140 | { \ | ||
141 | _FP_FRAC_SRS_##wc(X, X##_e, _FP_WFRACBITS_##fs); \ | ||
142 | _FP_ROUND(wc, X); \ | ||
143 | if (_FP_FRAC_HIGH_##fs(X) \ | ||
144 | & (_FP_OVERFLOW_##fs >> 1)) \ | ||
145 | { \ | ||
146 | X##_e = 1; \ | ||
147 | _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \ | ||
148 | } \ | ||
149 | else \ | ||
150 | { \ | ||
151 | X##_e = 0; \ | ||
152 | _FP_FRAC_SRL_##wc(X, _FP_WORKBITS); \ | ||
153 | FP_SET_EXCEPTION(FP_EX_UNDERFLOW); \ | ||
154 | } \ | ||
155 | } \ | ||
156 | else \ | ||
157 | { \ | ||
158 | /* underflow to zero */ \ | ||
159 | X##_e = 0; \ | ||
160 | if (!_FP_FRAC_ZEROP_##wc(X)) \ | ||
161 | { \ | ||
162 | _FP_FRAC_SET_##wc(X, _FP_MINFRAC_##wc); \ | ||
163 | _FP_ROUND(wc, X); \ | ||
164 | _FP_FRAC_LOW_##wc(X) >>= (_FP_WORKBITS); \ | ||
165 | } \ | ||
166 | FP_SET_EXCEPTION(FP_EX_UNDERFLOW); \ | ||
167 | } \ | ||
168 | } \ | ||
169 | break; \ | ||
170 | \ | ||
171 | case FP_CLS_ZERO: \ | ||
172 | X##_e = 0; \ | ||
173 | _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \ | ||
174 | break; \ | ||
175 | \ | ||
176 | case FP_CLS_INF: \ | ||
177 | X##_e = _FP_EXPMAX_##fs; \ | ||
178 | _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \ | ||
179 | break; \ | ||
180 | \ | ||
181 | case FP_CLS_NAN: \ | ||
182 | X##_e = _FP_EXPMAX_##fs; \ | ||
183 | if (!_FP_KEEPNANFRACP) \ | ||
184 | { \ | ||
185 | _FP_FRAC_SET_##wc(X, _FP_NANFRAC_##fs); \ | ||
186 | X##_s = _FP_NANSIGN_##fs; \ | ||
187 | } \ | ||
188 | else \ | ||
189 | _FP_FRAC_HIGH_RAW_##fs(X) |= _FP_QNANBIT_##fs; \ | ||
190 | break; \ | ||
191 | } \ | ||
192 | } while (0) | ||
193 | |||
194 | /* This one accepts raw argument and not cooked, returns | ||
195 | * 1 if X is a signaling NaN. | ||
196 | */ | ||
197 | #define _FP_ISSIGNAN(fs, wc, X) \ | ||
198 | ({ \ | ||
199 | int __ret = 0; \ | ||
200 | if (X##_e == _FP_EXPMAX_##fs) \ | ||
201 | { \ | ||
202 | if (!_FP_FRAC_ZEROP_##wc(X) \ | ||
203 | && !(_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs)) \ | ||
204 | __ret = 1; \ | ||
205 | } \ | ||
206 | __ret; \ | ||
207 | }) | ||
208 | |||
209 | |||
210 | |||
211 | |||
212 | |||
213 | /* | ||
214 | * Main addition routine. The input values should be cooked. | ||
215 | */ | ||
216 | |||
217 | #define _FP_ADD_INTERNAL(fs, wc, R, X, Y, OP) \ | ||
218 | do { \ | ||
219 | switch (_FP_CLS_COMBINE(X##_c, Y##_c)) \ | ||
220 | { \ | ||
221 | case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NORMAL): \ | ||
222 | { \ | ||
223 | /* shift the smaller number so that its exponent matches the larger */ \ | ||
224 | _FP_I_TYPE diff = X##_e - Y##_e; \ | ||
225 | \ | ||
226 | if (diff < 0) \ | ||
227 | { \ | ||
228 | diff = -diff; \ | ||
229 | if (diff <= _FP_WFRACBITS_##fs) \ | ||
230 | _FP_FRAC_SRS_##wc(X, diff, _FP_WFRACBITS_##fs); \ | ||
231 | else if (!_FP_FRAC_ZEROP_##wc(X)) \ | ||
232 | _FP_FRAC_SET_##wc(X, _FP_MINFRAC_##wc); \ | ||
233 | R##_e = Y##_e; \ | ||
234 | } \ | ||
235 | else \ | ||
236 | { \ | ||
237 | if (diff > 0) \ | ||
238 | { \ | ||
239 | if (diff <= _FP_WFRACBITS_##fs) \ | ||
240 | _FP_FRAC_SRS_##wc(Y, diff, _FP_WFRACBITS_##fs); \ | ||
241 | else if (!_FP_FRAC_ZEROP_##wc(Y)) \ | ||
242 | _FP_FRAC_SET_##wc(Y, _FP_MINFRAC_##wc); \ | ||
243 | } \ | ||
244 | R##_e = X##_e; \ | ||
245 | } \ | ||
246 | \ | ||
247 | R##_c = FP_CLS_NORMAL; \ | ||
248 | \ | ||
249 | if (X##_s == Y##_s) \ | ||
250 | { \ | ||
251 | R##_s = X##_s; \ | ||
252 | _FP_FRAC_ADD_##wc(R, X, Y); \ | ||
253 | if (_FP_FRAC_OVERP_##wc(fs, R)) \ | ||
254 | { \ | ||
255 | _FP_FRAC_SRS_##wc(R, 1, _FP_WFRACBITS_##fs); \ | ||
256 | R##_e++; \ | ||
257 | } \ | ||
258 | } \ | ||
259 | else \ | ||
260 | { \ | ||
261 | R##_s = X##_s; \ | ||
262 | _FP_FRAC_SUB_##wc(R, X, Y); \ | ||
263 | if (_FP_FRAC_ZEROP_##wc(R)) \ | ||
264 | { \ | ||
265 | /* return an exact zero */ \ | ||
266 | if (FP_ROUNDMODE == FP_RND_MINF) \ | ||
267 | R##_s |= Y##_s; \ | ||
268 | else \ | ||
269 | R##_s &= Y##_s; \ | ||
270 | R##_c = FP_CLS_ZERO; \ | ||
271 | } \ | ||
272 | else \ | ||
273 | { \ | ||
274 | if (_FP_FRAC_NEGP_##wc(R)) \ | ||
275 | { \ | ||
276 | _FP_FRAC_SUB_##wc(R, Y, X); \ | ||
277 | R##_s = Y##_s; \ | ||
278 | } \ | ||
279 | \ | ||
280 | /* renormalize after subtraction */ \ | ||
281 | _FP_FRAC_CLZ_##wc(diff, R); \ | ||
282 | diff -= _FP_WFRACXBITS_##fs; \ | ||
283 | if (diff) \ | ||
284 | { \ | ||
285 | R##_e -= diff; \ | ||
286 | _FP_FRAC_SLL_##wc(R, diff); \ | ||
287 | } \ | ||
288 | } \ | ||
289 | } \ | ||
290 | break; \ | ||
291 | } \ | ||
292 | \ | ||
293 | case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NAN): \ | ||
294 | _FP_CHOOSENAN(fs, wc, R, X, Y, OP); \ | ||
295 | break; \ | ||
296 | \ | ||
297 | case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO): \ | ||
298 | R##_e = X##_e; \ | ||
299 | case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL): \ | ||
300 | case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF): \ | ||
301 | case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO): \ | ||
302 | _FP_FRAC_COPY_##wc(R, X); \ | ||
303 | R##_s = X##_s; \ | ||
304 | R##_c = X##_c; \ | ||
305 | break; \ | ||
306 | \ | ||
307 | case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NORMAL): \ | ||
308 | R##_e = Y##_e; \ | ||
309 | case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NAN): \ | ||
310 | case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN): \ | ||
311 | case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN): \ | ||
312 | _FP_FRAC_COPY_##wc(R, Y); \ | ||
313 | R##_s = Y##_s; \ | ||
314 | R##_c = Y##_c; \ | ||
315 | break; \ | ||
316 | \ | ||
317 | case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF): \ | ||
318 | if (X##_s != Y##_s) \ | ||
319 | { \ | ||
320 | /* +INF + -INF => NAN */ \ | ||
321 | _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \ | ||
322 | R##_s = _FP_NANSIGN_##fs; \ | ||
323 | R##_c = FP_CLS_NAN; \ | ||
324 | FP_SET_EXCEPTION(FP_EX_INVALID); \ | ||
325 | break; \ | ||
326 | } \ | ||
327 | /* FALLTHRU */ \ | ||
328 | \ | ||
329 | case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL): \ | ||
330 | case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_ZERO): \ | ||
331 | R##_s = X##_s; \ | ||
332 | R##_c = FP_CLS_INF; \ | ||
333 | break; \ | ||
334 | \ | ||
335 | case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_INF): \ | ||
336 | case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_INF): \ | ||
337 | R##_s = Y##_s; \ | ||
338 | R##_c = FP_CLS_INF; \ | ||
339 | break; \ | ||
340 | \ | ||
341 | case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_ZERO): \ | ||
342 | /* make sure the sign is correct */ \ | ||
343 | if (FP_ROUNDMODE == FP_RND_MINF) \ | ||
344 | R##_s = X##_s | Y##_s; \ | ||
345 | else \ | ||
346 | R##_s = X##_s & Y##_s; \ | ||
347 | R##_c = FP_CLS_ZERO; \ | ||
348 | break; \ | ||
349 | \ | ||
350 | default: \ | ||
351 | abort(); \ | ||
352 | } \ | ||
353 | } while (0) | ||
354 | |||
355 | #define _FP_ADD(fs, wc, R, X, Y) _FP_ADD_INTERNAL(fs, wc, R, X, Y, '+') | ||
356 | #define _FP_SUB(fs, wc, R, X, Y) \ | ||
357 | do { \ | ||
358 | if (Y##_c != FP_CLS_NAN) Y##_s ^= 1; \ | ||
359 | _FP_ADD_INTERNAL(fs, wc, R, X, Y, '-'); \ | ||
360 | } while (0) | ||
361 | |||
362 | |||
363 | /* | ||
364 | * Main negation routine. FIXME -- when we care about setting exception | ||
365 | * bits reliably, this will not do. We should examine all of the fp classes. | ||
366 | */ | ||
367 | |||
368 | #define _FP_NEG(fs, wc, R, X) \ | ||
369 | do { \ | ||
370 | _FP_FRAC_COPY_##wc(R, X); \ | ||
371 | R##_c = X##_c; \ | ||
372 | R##_e = X##_e; \ | ||
373 | R##_s = 1 ^ X##_s; \ | ||
374 | } while (0) | ||
375 | |||
376 | |||
377 | /* | ||
378 | * Main multiplication routine. The input values should be cooked. | ||
379 | */ | ||
380 | |||
381 | #define _FP_MUL(fs, wc, R, X, Y) \ | ||
382 | do { \ | ||
383 | R##_s = X##_s ^ Y##_s; \ | ||
384 | switch (_FP_CLS_COMBINE(X##_c, Y##_c)) \ | ||
385 | { \ | ||
386 | case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NORMAL): \ | ||
387 | R##_c = FP_CLS_NORMAL; \ | ||
388 | R##_e = X##_e + Y##_e + 1; \ | ||
389 | \ | ||
390 | _FP_MUL_MEAT_##fs(R,X,Y); \ | ||
391 | \ | ||
392 | if (_FP_FRAC_OVERP_##wc(fs, R)) \ | ||
393 | _FP_FRAC_SRS_##wc(R, 1, _FP_WFRACBITS_##fs); \ | ||
394 | else \ | ||
395 | R##_e--; \ | ||
396 | break; \ | ||
397 | \ | ||
398 | case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NAN): \ | ||
399 | _FP_CHOOSENAN(fs, wc, R, X, Y, '*'); \ | ||
400 | break; \ | ||
401 | \ | ||
402 | case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL): \ | ||
403 | case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF): \ | ||
404 | case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO): \ | ||
405 | R##_s = X##_s; \ | ||
406 | \ | ||
407 | case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF): \ | ||
408 | case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL): \ | ||
409 | case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NORMAL): \ | ||
410 | case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_ZERO): \ | ||
411 | _FP_FRAC_COPY_##wc(R, X); \ | ||
412 | R##_c = X##_c; \ | ||
413 | break; \ | ||
414 | \ | ||
415 | case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NAN): \ | ||
416 | case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN): \ | ||
417 | case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN): \ | ||
418 | R##_s = Y##_s; \ | ||
419 | \ | ||
420 | case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_INF): \ | ||
421 | case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO): \ | ||
422 | _FP_FRAC_COPY_##wc(R, Y); \ | ||
423 | R##_c = Y##_c; \ | ||
424 | break; \ | ||
425 | \ | ||
426 | case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_ZERO): \ | ||
427 | case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_INF): \ | ||
428 | R##_s = _FP_NANSIGN_##fs; \ | ||
429 | R##_c = FP_CLS_NAN; \ | ||
430 | _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \ | ||
431 | FP_SET_EXCEPTION(FP_EX_INVALID); \ | ||
432 | break; \ | ||
433 | \ | ||
434 | default: \ | ||
435 | abort(); \ | ||
436 | } \ | ||
437 | } while (0) | ||
438 | |||
439 | |||
440 | /* | ||
441 | * Main division routine. The input values should be cooked. | ||
442 | */ | ||
443 | |||
444 | #define _FP_DIV(fs, wc, R, X, Y) \ | ||
445 | do { \ | ||
446 | R##_s = X##_s ^ Y##_s; \ | ||
447 | switch (_FP_CLS_COMBINE(X##_c, Y##_c)) \ | ||
448 | { \ | ||
449 | case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NORMAL): \ | ||
450 | R##_c = FP_CLS_NORMAL; \ | ||
451 | R##_e = X##_e - Y##_e; \ | ||
452 | \ | ||
453 | _FP_DIV_MEAT_##fs(R,X,Y); \ | ||
454 | break; \ | ||
455 | \ | ||
456 | case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NAN): \ | ||
457 | _FP_CHOOSENAN(fs, wc, R, X, Y, '/'); \ | ||
458 | break; \ | ||
459 | \ | ||
460 | case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL): \ | ||
461 | case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF): \ | ||
462 | case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO): \ | ||
463 | R##_s = X##_s; \ | ||
464 | _FP_FRAC_COPY_##wc(R, X); \ | ||
465 | R##_c = X##_c; \ | ||
466 | break; \ | ||
467 | \ | ||
468 | case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NAN): \ | ||
469 | case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN): \ | ||
470 | case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN): \ | ||
471 | R##_s = Y##_s; \ | ||
472 | _FP_FRAC_COPY_##wc(R, Y); \ | ||
473 | R##_c = Y##_c; \ | ||
474 | break; \ | ||
475 | \ | ||
476 | case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_INF): \ | ||
477 | case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_INF): \ | ||
478 | case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NORMAL): \ | ||
479 | R##_c = FP_CLS_ZERO; \ | ||
480 | break; \ | ||
481 | \ | ||
482 | case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO): \ | ||
483 | FP_SET_EXCEPTION(FP_EX_DIVZERO); \ | ||
484 | case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_ZERO): \ | ||
485 | case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL): \ | ||
486 | R##_c = FP_CLS_INF; \ | ||
487 | break; \ | ||
488 | \ | ||
489 | case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF): \ | ||
490 | case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_ZERO): \ | ||
491 | R##_s = _FP_NANSIGN_##fs; \ | ||
492 | R##_c = FP_CLS_NAN; \ | ||
493 | _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \ | ||
494 | FP_SET_EXCEPTION(FP_EX_INVALID); \ | ||
495 | break; \ | ||
496 | \ | ||
497 | default: \ | ||
498 | abort(); \ | ||
499 | } \ | ||
500 | } while (0) | ||
501 | |||
502 | |||
503 | /* | ||
504 | * Main differential comparison routine. The inputs should be raw not | ||
505 | * cooked. The return is -1,0,1 for normal values, 2 otherwise. | ||
506 | */ | ||
507 | |||
508 | #define _FP_CMP(fs, wc, ret, X, Y, un) \ | ||
509 | do { \ | ||
510 | /* NANs are unordered */ \ | ||
511 | if ((X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(X)) \ | ||
512 | || (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(Y))) \ | ||
513 | { \ | ||
514 | ret = un; \ | ||
515 | } \ | ||
516 | else \ | ||
517 | { \ | ||
518 | int __is_zero_x; \ | ||
519 | int __is_zero_y; \ | ||
520 | \ | ||
521 | __is_zero_x = (!X##_e && _FP_FRAC_ZEROP_##wc(X)) ? 1 : 0; \ | ||
522 | __is_zero_y = (!Y##_e && _FP_FRAC_ZEROP_##wc(Y)) ? 1 : 0; \ | ||
523 | \ | ||
524 | if (__is_zero_x && __is_zero_y) \ | ||
525 | ret = 0; \ | ||
526 | else if (__is_zero_x) \ | ||
527 | ret = Y##_s ? 1 : -1; \ | ||
528 | else if (__is_zero_y) \ | ||
529 | ret = X##_s ? -1 : 1; \ | ||
530 | else if (X##_s != Y##_s) \ | ||
531 | ret = X##_s ? -1 : 1; \ | ||
532 | else if (X##_e > Y##_e) \ | ||
533 | ret = X##_s ? -1 : 1; \ | ||
534 | else if (X##_e < Y##_e) \ | ||
535 | ret = X##_s ? 1 : -1; \ | ||
536 | else if (_FP_FRAC_GT_##wc(X, Y)) \ | ||
537 | ret = X##_s ? -1 : 1; \ | ||
538 | else if (_FP_FRAC_GT_##wc(Y, X)) \ | ||
539 | ret = X##_s ? 1 : -1; \ | ||
540 | else \ | ||
541 | ret = 0; \ | ||
542 | } \ | ||
543 | } while (0) | ||
544 | |||
545 | |||
546 | /* Simplification for strict equality. */ | ||
547 | |||
548 | #define _FP_CMP_EQ(fs, wc, ret, X, Y) \ | ||
549 | do { \ | ||
550 | /* NANs are unordered */ \ | ||
551 | if ((X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(X)) \ | ||
552 | || (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(Y))) \ | ||
553 | { \ | ||
554 | ret = 1; \ | ||
555 | } \ | ||
556 | else \ | ||
557 | { \ | ||
558 | ret = !(X##_e == Y##_e \ | ||
559 | && _FP_FRAC_EQ_##wc(X, Y) \ | ||
560 | && (X##_s == Y##_s || !X##_e && _FP_FRAC_ZEROP_##wc(X))); \ | ||
561 | } \ | ||
562 | } while (0) | ||
563 | |||
564 | /* | ||
565 | * Main square root routine. The input value should be cooked. | ||
566 | */ | ||
567 | |||
568 | #define _FP_SQRT(fs, wc, R, X) \ | ||
569 | do { \ | ||
570 | _FP_FRAC_DECL_##wc(T); _FP_FRAC_DECL_##wc(S); \ | ||
571 | _FP_W_TYPE q; \ | ||
572 | switch (X##_c) \ | ||
573 | { \ | ||
574 | case FP_CLS_NAN: \ | ||
575 | _FP_FRAC_COPY_##wc(R, X); \ | ||
576 | R##_s = X##_s; \ | ||
577 | R##_c = FP_CLS_NAN; \ | ||
578 | break; \ | ||
579 | case FP_CLS_INF: \ | ||
580 | if (X##_s) \ | ||
581 | { \ | ||
582 | R##_s = _FP_NANSIGN_##fs; \ | ||
583 | R##_c = FP_CLS_NAN; /* NAN */ \ | ||
584 | _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \ | ||
585 | FP_SET_EXCEPTION(FP_EX_INVALID); \ | ||
586 | } \ | ||
587 | else \ | ||
588 | { \ | ||
589 | R##_s = 0; \ | ||
590 | R##_c = FP_CLS_INF; /* sqrt(+inf) = +inf */ \ | ||
591 | } \ | ||
592 | break; \ | ||
593 | case FP_CLS_ZERO: \ | ||
594 | R##_s = X##_s; \ | ||
595 | R##_c = FP_CLS_ZERO; /* sqrt(+-0) = +-0 */ \ | ||
596 | break; \ | ||
597 | case FP_CLS_NORMAL: \ | ||
598 | R##_s = 0; \ | ||
599 | if (X##_s) \ | ||
600 | { \ | ||
601 | R##_c = FP_CLS_NAN; /* sNAN */ \ | ||
602 | R##_s = _FP_NANSIGN_##fs; \ | ||
603 | _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \ | ||
604 | FP_SET_EXCEPTION(FP_EX_INVALID); \ | ||
605 | break; \ | ||
606 | } \ | ||
607 | R##_c = FP_CLS_NORMAL; \ | ||
608 | if (X##_e & 1) \ | ||
609 | _FP_FRAC_SLL_##wc(X, 1); \ | ||
610 | R##_e = X##_e >> 1; \ | ||
611 | _FP_FRAC_SET_##wc(S, _FP_ZEROFRAC_##wc); \ | ||
612 | _FP_FRAC_SET_##wc(R, _FP_ZEROFRAC_##wc); \ | ||
613 | q = _FP_OVERFLOW_##fs >> 1; \ | ||
614 | _FP_SQRT_MEAT_##wc(R, S, T, X, q); \ | ||
615 | } \ | ||
616 | } while (0) | ||
617 | |||
618 | /* | ||
619 | * Convert from FP to integer | ||
620 | */ | ||
621 | |||
622 | /* RSIGNED can have following values: | ||
623 | * 0: the number is required to be 0..(2^rsize)-1, if not, NV is set plus | ||
624 | * the result is either 0 or (2^rsize)-1 depending on the sign in such case. | ||
625 | * 1: the number is required to be -(2^(rsize-1))..(2^(rsize-1))-1, if not, NV is | ||
626 | * set plus the result is either -(2^(rsize-1)) or (2^(rsize-1))-1 depending | ||
627 | * on the sign in such case. | ||
628 | * 2: the number is required to be -(2^(rsize-1))..(2^(rsize-1))-1, if not, NV is | ||
629 | * set plus the result is truncated to fit into destination. | ||
630 | * -1: the number is required to be -(2^(rsize-1))..(2^rsize)-1, if not, NV is | ||
631 | * set plus the result is either -(2^(rsize-1)) or (2^(rsize-1))-1 depending | ||
632 | * on the sign in such case. | ||
633 | */ | ||
634 | #define _FP_TO_INT(fs, wc, r, X, rsize, rsigned) \ | ||
635 | do { \ | ||
636 | switch (X##_c) \ | ||
637 | { \ | ||
638 | case FP_CLS_NORMAL: \ | ||
639 | if (X##_e < 0) \ | ||
640 | { \ | ||
641 | FP_SET_EXCEPTION(FP_EX_INEXACT); \ | ||
642 | case FP_CLS_ZERO: \ | ||
643 | r = 0; \ | ||
644 | } \ | ||
645 | else if (X##_e >= rsize - (rsigned > 0 || X##_s) \ | ||
646 | || (!rsigned && X##_s)) \ | ||
647 | { /* overflow */ \ | ||
648 | case FP_CLS_NAN: \ | ||
649 | case FP_CLS_INF: \ | ||
650 | if (rsigned == 2) \ | ||
651 | { \ | ||
652 | if (X##_c != FP_CLS_NORMAL \ | ||
653 | || X##_e >= rsize - 1 + _FP_WFRACBITS_##fs) \ | ||
654 | r = 0; \ | ||
655 | else \ | ||
656 | { \ | ||
657 | _FP_FRAC_SLL_##wc(X, (X##_e - _FP_WFRACBITS_##fs + 1)); \ | ||
658 | _FP_FRAC_ASSEMBLE_##wc(r, X, rsize); \ | ||
659 | } \ | ||
660 | } \ | ||
661 | else if (rsigned) \ | ||
662 | { \ | ||
663 | r = 1; \ | ||
664 | r <<= rsize - 1; \ | ||
665 | r -= 1 - X##_s; \ | ||
666 | } \ | ||
667 | else \ | ||
668 | { \ | ||
669 | r = 0; \ | ||
670 | if (X##_s) \ | ||
671 | r = ~r; \ | ||
672 | } \ | ||
673 | FP_SET_EXCEPTION(FP_EX_INVALID); \ | ||
674 | } \ | ||
675 | else \ | ||
676 | { \ | ||
677 | if (_FP_W_TYPE_SIZE*wc < rsize) \ | ||
678 | { \ | ||
679 | _FP_FRAC_ASSEMBLE_##wc(r, X, rsize); \ | ||
680 | r <<= X##_e - _FP_WFRACBITS_##fs; \ | ||
681 | } \ | ||
682 | else \ | ||
683 | { \ | ||
684 | if (X##_e >= _FP_WFRACBITS_##fs) \ | ||
685 | _FP_FRAC_SLL_##wc(X, (X##_e - _FP_WFRACBITS_##fs + 1)); \ | ||
686 | else if (X##_e < _FP_WFRACBITS_##fs - 1) \ | ||
687 | { \ | ||
688 | _FP_FRAC_SRS_##wc(X, (_FP_WFRACBITS_##fs - X##_e - 2), \ | ||
689 | _FP_WFRACBITS_##fs); \ | ||
690 | if (_FP_FRAC_LOW_##wc(X) & 1) \ | ||
691 | FP_SET_EXCEPTION(FP_EX_INEXACT); \ | ||
692 | _FP_FRAC_SRL_##wc(X, 1); \ | ||
693 | } \ | ||
694 | _FP_FRAC_ASSEMBLE_##wc(r, X, rsize); \ | ||
695 | } \ | ||
696 | if (rsigned && X##_s) \ | ||
697 | r = -r; \ | ||
698 | } \ | ||
699 | break; \ | ||
700 | } \ | ||
701 | } while (0) | ||
702 | |||
703 | #define _FP_TO_INT_ROUND(fs, wc, r, X, rsize, rsigned) \ | ||
704 | do { \ | ||
705 | r = 0; \ | ||
706 | switch (X##_c) \ | ||
707 | { \ | ||
708 | case FP_CLS_NORMAL: \ | ||
709 | if (X##_e >= _FP_FRACBITS_##fs - 1) \ | ||
710 | { \ | ||
711 | if (X##_e < rsize - 1 + _FP_WFRACBITS_##fs) \ | ||
712 | { \ | ||
713 | if (X##_e >= _FP_WFRACBITS_##fs - 1) \ | ||
714 | { \ | ||
715 | _FP_FRAC_ASSEMBLE_##wc(r, X, rsize); \ | ||
716 | r <<= X##_e - _FP_WFRACBITS_##fs + 1; \ | ||
717 | } \ | ||
718 | else \ | ||
719 | { \ | ||
720 | _FP_FRAC_SRL_##wc(X, _FP_WORKBITS - X##_e \ | ||
721 | + _FP_FRACBITS_##fs - 1); \ | ||
722 | _FP_FRAC_ASSEMBLE_##wc(r, X, rsize); \ | ||
723 | } \ | ||
724 | } \ | ||
725 | } \ | ||
726 | else \ | ||
727 | { \ | ||
728 | if (X##_e <= -_FP_WORKBITS - 1) \ | ||
729 | _FP_FRAC_SET_##wc(X, _FP_MINFRAC_##wc); \ | ||
730 | else \ | ||
731 | _FP_FRAC_SRS_##wc(X, _FP_FRACBITS_##fs - 1 - X##_e, \ | ||
732 | _FP_WFRACBITS_##fs); \ | ||
733 | _FP_ROUND(wc, X); \ | ||
734 | _FP_FRAC_SRL_##wc(X, _FP_WORKBITS); \ | ||
735 | _FP_FRAC_ASSEMBLE_##wc(r, X, rsize); \ | ||
736 | } \ | ||
737 | if (rsigned && X##_s) \ | ||
738 | r = -r; \ | ||
739 | if (X##_e >= rsize - (rsigned > 0 || X##_s) \ | ||
740 | || (!rsigned && X##_s)) \ | ||
741 | { /* overflow */ \ | ||
742 | case FP_CLS_NAN: \ | ||
743 | case FP_CLS_INF: \ | ||
744 | if (!rsigned) \ | ||
745 | { \ | ||
746 | r = 0; \ | ||
747 | if (X##_s) \ | ||
748 | r = ~r; \ | ||
749 | } \ | ||
750 | else if (rsigned != 2) \ | ||
751 | { \ | ||
752 | r = 1; \ | ||
753 | r <<= rsize - 1; \ | ||
754 | r -= 1 - X##_s; \ | ||
755 | } \ | ||
756 | FP_SET_EXCEPTION(FP_EX_INVALID); \ | ||
757 | } \ | ||
758 | break; \ | ||
759 | case FP_CLS_ZERO: \ | ||
760 | break; \ | ||
761 | } \ | ||
762 | } while (0) | ||
763 | |||
764 | #define _FP_FROM_INT(fs, wc, X, r, rsize, rtype) \ | ||
765 | do { \ | ||
766 | if (r) \ | ||
767 | { \ | ||
768 | unsigned rtype ur_; \ | ||
769 | X##_c = FP_CLS_NORMAL; \ | ||
770 | \ | ||
771 | if ((X##_s = (r < 0))) \ | ||
772 | ur_ = (unsigned rtype) -r; \ | ||
773 | else \ | ||
774 | ur_ = (unsigned rtype) r; \ | ||
775 | if (rsize <= _FP_W_TYPE_SIZE) \ | ||
776 | __FP_CLZ(X##_e, ur_); \ | ||
777 | else \ | ||
778 | __FP_CLZ_2(X##_e, (_FP_W_TYPE)(ur_ >> _FP_W_TYPE_SIZE), \ | ||
779 | (_FP_W_TYPE)ur_); \ | ||
780 | if (rsize < _FP_W_TYPE_SIZE) \ | ||
781 | X##_e -= (_FP_W_TYPE_SIZE - rsize); \ | ||
782 | X##_e = rsize - X##_e - 1; \ | ||
783 | \ | ||
784 | if (_FP_FRACBITS_##fs < rsize && _FP_WFRACBITS_##fs < X##_e) \ | ||
785 | __FP_FRAC_SRS_1(ur_, (X##_e - _FP_WFRACBITS_##fs + 1), rsize);\ | ||
786 | _FP_FRAC_DISASSEMBLE_##wc(X, ur_, rsize); \ | ||
787 | if ((_FP_WFRACBITS_##fs - X##_e - 1) > 0) \ | ||
788 | _FP_FRAC_SLL_##wc(X, (_FP_WFRACBITS_##fs - X##_e - 1)); \ | ||
789 | } \ | ||
790 | else \ | ||
791 | { \ | ||
792 | X##_c = FP_CLS_ZERO, X##_s = 0; \ | ||
793 | } \ | ||
794 | } while (0) | ||
795 | |||
796 | |||
797 | #define FP_CONV(dfs,sfs,dwc,swc,D,S) \ | ||
798 | do { \ | ||
799 | _FP_FRAC_CONV_##dwc##_##swc(dfs, sfs, D, S); \ | ||
800 | D##_e = S##_e; \ | ||
801 | D##_c = S##_c; \ | ||
802 | D##_s = S##_s; \ | ||
803 | } while (0) | ||
804 | |||
805 | /* | ||
806 | * Helper primitives. | ||
807 | */ | ||
808 | |||
809 | /* Count leading zeros in a word. */ | ||
810 | |||
811 | #ifndef __FP_CLZ | ||
812 | #if _FP_W_TYPE_SIZE < 64 | ||
813 | /* this is just to shut the compiler up about shifts > word length -- PMM 02/1998 */ | ||
814 | #define __FP_CLZ(r, x) \ | ||
815 | do { \ | ||
816 | _FP_W_TYPE _t = (x); \ | ||
817 | r = _FP_W_TYPE_SIZE - 1; \ | ||
818 | if (_t > 0xffff) r -= 16; \ | ||
819 | if (_t > 0xffff) _t >>= 16; \ | ||
820 | if (_t > 0xff) r -= 8; \ | ||
821 | if (_t > 0xff) _t >>= 8; \ | ||
822 | if (_t & 0xf0) r -= 4; \ | ||
823 | if (_t & 0xf0) _t >>= 4; \ | ||
824 | if (_t & 0xc) r -= 2; \ | ||
825 | if (_t & 0xc) _t >>= 2; \ | ||
826 | if (_t & 0x2) r -= 1; \ | ||
827 | } while (0) | ||
828 | #else /* not _FP_W_TYPE_SIZE < 64 */ | ||
829 | #define __FP_CLZ(r, x) \ | ||
830 | do { \ | ||
831 | _FP_W_TYPE _t = (x); \ | ||
832 | r = _FP_W_TYPE_SIZE - 1; \ | ||
833 | if (_t > 0xffffffff) r -= 32; \ | ||
834 | if (_t > 0xffffffff) _t >>= 32; \ | ||
835 | if (_t > 0xffff) r -= 16; \ | ||
836 | if (_t > 0xffff) _t >>= 16; \ | ||
837 | if (_t > 0xff) r -= 8; \ | ||
838 | if (_t > 0xff) _t >>= 8; \ | ||
839 | if (_t & 0xf0) r -= 4; \ | ||
840 | if (_t & 0xf0) _t >>= 4; \ | ||
841 | if (_t & 0xc) r -= 2; \ | ||
842 | if (_t & 0xc) _t >>= 2; \ | ||
843 | if (_t & 0x2) r -= 1; \ | ||
844 | } while (0) | ||
845 | #endif /* not _FP_W_TYPE_SIZE < 64 */ | ||
846 | #endif /* ndef __FP_CLZ */ | ||
847 | |||
848 | #define _FP_DIV_HELP_imm(q, r, n, d) \ | ||
849 | do { \ | ||
850 | q = n / d, r = n % d; \ | ||
851 | } while (0) | ||
852 | |||
853 | #endif /* __MATH_EMU_OP_COMMON_H__ */ | ||