aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ppc/math-emu/op-common.h
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /arch/ppc/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 'arch/ppc/math-emu/op-common.h')
-rw-r--r--arch/ppc/math-emu/op-common.h688
1 files changed, 688 insertions, 0 deletions
diff --git a/arch/ppc/math-emu/op-common.h b/arch/ppc/math-emu/op-common.h
new file mode 100644
index 000000000000..afb82b6498ce
--- /dev/null
+++ b/arch/ppc/math-emu/op-common.h
@@ -0,0 +1,688 @@
1#define _FP_DECL(wc, X) \
2 _FP_I_TYPE X##_c, X##_s, X##_e; \
3 _FP_FRAC_DECL_##wc(X)
4
5/*
6 * Finish truely unpacking a native fp value by classifying the kind
7 * of fp value and normalizing both the exponent and the fraction.
8 */
9
10#define _FP_UNPACK_CANONICAL(fs, wc, X) \
11do { \
12 switch (X##_e) \
13 { \
14 default: \
15 _FP_FRAC_HIGH_##wc(X) |= _FP_IMPLBIT_##fs; \
16 _FP_FRAC_SLL_##wc(X, _FP_WORKBITS); \
17 X##_e -= _FP_EXPBIAS_##fs; \
18 X##_c = FP_CLS_NORMAL; \
19 break; \
20 \
21 case 0: \
22 if (_FP_FRAC_ZEROP_##wc(X)) \
23 X##_c = FP_CLS_ZERO; \
24 else \
25 { \
26 /* a denormalized number */ \
27 _FP_I_TYPE _shift; \
28 _FP_FRAC_CLZ_##wc(_shift, X); \
29 _shift -= _FP_FRACXBITS_##fs; \
30 _FP_FRAC_SLL_##wc(X, (_shift+_FP_WORKBITS)); \
31 X##_e -= _FP_EXPBIAS_##fs - 1 + _shift; \
32 X##_c = FP_CLS_NORMAL; \
33 } \
34 break; \
35 \
36 case _FP_EXPMAX_##fs: \
37 if (_FP_FRAC_ZEROP_##wc(X)) \
38 X##_c = FP_CLS_INF; \
39 else \
40 /* we don't differentiate between signaling and quiet nans */ \
41 X##_c = FP_CLS_NAN; \
42 break; \
43 } \
44} while (0)
45
46
47/*
48 * Before packing the bits back into the native fp result, take care
49 * of such mundane things as rounding and overflow. Also, for some
50 * kinds of fp values, the original parts may not have been fully
51 * extracted -- but that is ok, we can regenerate them now.
52 */
53
54#define _FP_PACK_CANONICAL(fs, wc, X) \
55({int __ret = 0; \
56 switch (X##_c) \
57 { \
58 case FP_CLS_NORMAL: \
59 X##_e += _FP_EXPBIAS_##fs; \
60 if (X##_e > 0) \
61 { \
62 __ret |= _FP_ROUND(wc, X); \
63 if (_FP_FRAC_OVERP_##wc(fs, X)) \
64 { \
65 _FP_FRAC_SRL_##wc(X, (_FP_WORKBITS+1)); \
66 X##_e++; \
67 } \
68 else \
69 _FP_FRAC_SRL_##wc(X, _FP_WORKBITS); \
70 if (X##_e >= _FP_EXPMAX_##fs) \
71 { \
72 /* overflow to infinity */ \
73 X##_e = _FP_EXPMAX_##fs; \
74 _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \
75 __ret |= EFLAG_OVERFLOW; \
76 } \
77 } \
78 else \
79 { \
80 /* we've got a denormalized number */ \
81 X##_e = -X##_e + 1; \
82 if (X##_e <= _FP_WFRACBITS_##fs) \
83 { \
84 _FP_FRAC_SRS_##wc(X, X##_e, _FP_WFRACBITS_##fs); \
85 _FP_FRAC_SLL_##wc(X, 1); \
86 if (_FP_FRAC_OVERP_##wc(fs, X)) \
87 { \
88 X##_e = 1; \
89 _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \
90 } \
91 else \
92 { \
93 X##_e = 0; \
94 _FP_FRAC_SRL_##wc(X, _FP_WORKBITS+1); \
95 __ret |= EFLAG_UNDERFLOW; \
96 } \
97 } \
98 else \
99 { \
100 /* underflow to zero */ \
101 X##_e = 0; \
102 _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \
103 __ret |= EFLAG_UNDERFLOW; \
104 } \
105 } \
106 break; \
107 \
108 case FP_CLS_ZERO: \
109 X##_e = 0; \
110 _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \
111 break; \
112 \
113 case FP_CLS_INF: \
114 X##_e = _FP_EXPMAX_##fs; \
115 _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \
116 break; \
117 \
118 case FP_CLS_NAN: \
119 X##_e = _FP_EXPMAX_##fs; \
120 if (!_FP_KEEPNANFRACP) \
121 { \
122 _FP_FRAC_SET_##wc(X, _FP_NANFRAC_##fs); \
123 X##_s = 0; \
124 } \
125 else \
126 _FP_FRAC_HIGH_##wc(X) |= _FP_QNANBIT_##fs; \
127 break; \
128 } \
129 __ret; \
130})
131
132
133/*
134 * Main addition routine. The input values should be cooked.
135 */
136
137#define _FP_ADD(fs, wc, R, X, Y) \
138do { \
139 switch (_FP_CLS_COMBINE(X##_c, Y##_c)) \
140 { \
141 case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NORMAL): \
142 { \
143 /* shift the smaller number so that its exponent matches the larger */ \
144 _FP_I_TYPE diff = X##_e - Y##_e; \
145 \
146 if (diff < 0) \
147 { \
148 diff = -diff; \
149 if (diff <= _FP_WFRACBITS_##fs) \
150 _FP_FRAC_SRS_##wc(X, diff, _FP_WFRACBITS_##fs); \
151 else if (!_FP_FRAC_ZEROP_##wc(X)) \
152 _FP_FRAC_SET_##wc(X, _FP_MINFRAC_##wc); \
153 else \
154 _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \
155 R##_e = Y##_e; \
156 } \
157 else \
158 { \
159 if (diff > 0) \
160 { \
161 if (diff <= _FP_WFRACBITS_##fs) \
162 _FP_FRAC_SRS_##wc(Y, diff, _FP_WFRACBITS_##fs); \
163 else if (!_FP_FRAC_ZEROP_##wc(Y)) \
164 _FP_FRAC_SET_##wc(Y, _FP_MINFRAC_##wc); \
165 else \
166 _FP_FRAC_SET_##wc(Y, _FP_ZEROFRAC_##wc); \
167 } \
168 R##_e = X##_e; \
169 } \
170 \
171 R##_c = FP_CLS_NORMAL; \
172 \
173 if (X##_s == Y##_s) \
174 { \
175 R##_s = X##_s; \
176 _FP_FRAC_ADD_##wc(R, X, Y); \
177 if (_FP_FRAC_OVERP_##wc(fs, R)) \
178 { \
179 _FP_FRAC_SRS_##wc(R, 1, _FP_WFRACBITS_##fs); \
180 R##_e++; \
181 } \
182 } \
183 else \
184 { \
185 R##_s = X##_s; \
186 _FP_FRAC_SUB_##wc(R, X, Y); \
187 if (_FP_FRAC_ZEROP_##wc(R)) \
188 { \
189 /* return an exact zero */ \
190 if (FP_ROUNDMODE == FP_RND_MINF) \
191 R##_s |= Y##_s; \
192 else \
193 R##_s &= Y##_s; \
194 R##_c = FP_CLS_ZERO; \
195 } \
196 else \
197 { \
198 if (_FP_FRAC_NEGP_##wc(R)) \
199 { \
200 _FP_FRAC_SUB_##wc(R, Y, X); \
201 R##_s = Y##_s; \
202 } \
203 \
204 /* renormalize after subtraction */ \
205 _FP_FRAC_CLZ_##wc(diff, R); \
206 diff -= _FP_WFRACXBITS_##fs; \
207 if (diff) \
208 { \
209 R##_e -= diff; \
210 _FP_FRAC_SLL_##wc(R, diff); \
211 } \
212 } \
213 } \
214 break; \
215 } \
216 \
217 case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NAN): \
218 _FP_CHOOSENAN(fs, wc, R, X, Y); \
219 break; \
220 \
221 case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO): \
222 R##_e = X##_e; \
223 case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL): \
224 case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF): \
225 case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO): \
226 _FP_FRAC_COPY_##wc(R, X); \
227 R##_s = X##_s; \
228 R##_c = X##_c; \
229 break; \
230 \
231 case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NORMAL): \
232 R##_e = Y##_e; \
233 case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NAN): \
234 case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN): \
235 case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN): \
236 _FP_FRAC_COPY_##wc(R, Y); \
237 R##_s = Y##_s; \
238 R##_c = Y##_c; \
239 break; \
240 \
241 case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF): \
242 if (X##_s != Y##_s) \
243 { \
244 /* +INF + -INF => NAN */ \
245 _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \
246 R##_s = X##_s ^ Y##_s; \
247 R##_c = FP_CLS_NAN; \
248 break; \
249 } \
250 /* FALLTHRU */ \
251 \
252 case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL): \
253 case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_ZERO): \
254 R##_s = X##_s; \
255 R##_c = FP_CLS_INF; \
256 break; \
257 \
258 case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_INF): \
259 case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_INF): \
260 R##_s = Y##_s; \
261 R##_c = FP_CLS_INF; \
262 break; \
263 \
264 case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_ZERO): \
265 /* make sure the sign is correct */ \
266 if (FP_ROUNDMODE == FP_RND_MINF) \
267 R##_s = X##_s | Y##_s; \
268 else \
269 R##_s = X##_s & Y##_s; \
270 R##_c = FP_CLS_ZERO; \
271 break; \
272 \
273 default: \
274 abort(); \
275 } \
276} while (0)
277
278
279/*
280 * Main negation routine. FIXME -- when we care about setting exception
281 * bits reliably, this will not do. We should examine all of the fp classes.
282 */
283
284#define _FP_NEG(fs, wc, R, X) \
285 do { \
286 _FP_FRAC_COPY_##wc(R, X); \
287 R##_c = X##_c; \
288 R##_e = X##_e; \
289 R##_s = 1 ^ X##_s; \
290 } while (0)
291
292
293/*
294 * Main multiplication routine. The input values should be cooked.
295 */
296
297#define _FP_MUL(fs, wc, R, X, Y) \
298do { \
299 R##_s = X##_s ^ Y##_s; \
300 switch (_FP_CLS_COMBINE(X##_c, Y##_c)) \
301 { \
302 case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NORMAL): \
303 R##_c = FP_CLS_NORMAL; \
304 R##_e = X##_e + Y##_e + 1; \
305 \
306 _FP_MUL_MEAT_##fs(R,X,Y); \
307 \
308 if (_FP_FRAC_OVERP_##wc(fs, R)) \
309 _FP_FRAC_SRS_##wc(R, 1, _FP_WFRACBITS_##fs); \
310 else \
311 R##_e--; \
312 break; \
313 \
314 case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NAN): \
315 _FP_CHOOSENAN(fs, wc, R, X, Y); \
316 break; \
317 \
318 case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL): \
319 case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF): \
320 case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO): \
321 R##_s = X##_s; \
322 \
323 case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF): \
324 case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL): \
325 case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NORMAL): \
326 case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_ZERO): \
327 _FP_FRAC_COPY_##wc(R, X); \
328 R##_c = X##_c; \
329 break; \
330 \
331 case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NAN): \
332 case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN): \
333 case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN): \
334 R##_s = Y##_s; \
335 \
336 case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_INF): \
337 case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO): \
338 _FP_FRAC_COPY_##wc(R, Y); \
339 R##_c = Y##_c; \
340 break; \
341 \
342 case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_ZERO): \
343 case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_INF): \
344 R##_c = FP_CLS_NAN; \
345 _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \
346 break; \
347 \
348 default: \
349 abort(); \
350 } \
351} while (0)
352
353
354/*
355 * Main division routine. The input values should be cooked.
356 */
357
358#define _FP_DIV(fs, wc, R, X, Y) \
359do { \
360 R##_s = X##_s ^ Y##_s; \
361 switch (_FP_CLS_COMBINE(X##_c, Y##_c)) \
362 { \
363 case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NORMAL): \
364 R##_c = FP_CLS_NORMAL; \
365 R##_e = X##_e - Y##_e; \
366 \
367 _FP_DIV_MEAT_##fs(R,X,Y); \
368 break; \
369 \
370 case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NAN): \
371 _FP_CHOOSENAN(fs, wc, R, X, Y); \
372 break; \
373 \
374 case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL): \
375 case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF): \
376 case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO): \
377 R##_s = X##_s; \
378 _FP_FRAC_COPY_##wc(R, X); \
379 R##_c = X##_c; \
380 break; \
381 \
382 case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NAN): \
383 case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN): \
384 case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN): \
385 R##_s = Y##_s; \
386 _FP_FRAC_COPY_##wc(R, Y); \
387 R##_c = Y##_c; \
388 break; \
389 \
390 case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_INF): \
391 case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_INF): \
392 case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NORMAL): \
393 R##_c = FP_CLS_ZERO; \
394 break; \
395 \
396 case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO): \
397 case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_ZERO): \
398 case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL): \
399 R##_c = FP_CLS_INF; \
400 break; \
401 \
402 case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF): \
403 case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_ZERO): \
404 R##_c = FP_CLS_NAN; \
405 _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \
406 break; \
407 \
408 default: \
409 abort(); \
410 } \
411} while (0)
412
413
414/*
415 * Main differential comparison routine. The inputs should be raw not
416 * cooked. The return is -1,0,1 for normal values, 2 otherwise.
417 */
418
419#define _FP_CMP(fs, wc, ret, X, Y, un) \
420 do { \
421 /* NANs are unordered */ \
422 if ((X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(X)) \
423 || (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(Y))) \
424 { \
425 ret = un; \
426 } \
427 else \
428 { \
429 int __x_zero = (!X##_e && _FP_FRAC_ZEROP_##wc(X)) ? 1 : 0; \
430 int __y_zero = (!Y##_e && _FP_FRAC_ZEROP_##wc(Y)) ? 1 : 0; \
431 \
432 if (__x_zero && __y_zero) \
433 ret = 0; \
434 else if (__x_zero) \
435 ret = Y##_s ? 1 : -1; \
436 else if (__y_zero) \
437 ret = X##_s ? -1 : 1; \
438 else if (X##_s != Y##_s) \
439 ret = X##_s ? -1 : 1; \
440 else if (X##_e > Y##_e) \
441 ret = X##_s ? -1 : 1; \
442 else if (X##_e < Y##_e) \
443 ret = X##_s ? 1 : -1; \
444 else if (_FP_FRAC_GT_##wc(X, Y)) \
445 ret = X##_s ? -1 : 1; \
446 else if (_FP_FRAC_GT_##wc(Y, X)) \
447 ret = X##_s ? 1 : -1; \
448 else \
449 ret = 0; \
450 } \
451 } while (0)
452
453
454/* Simplification for strict equality. */
455
456#define _FP_CMP_EQ(fs, wc, ret, X, Y) \
457 do { \
458 /* NANs are unordered */ \
459 if ((X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(X)) \
460 || (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(Y))) \
461 { \
462 ret = 1; \
463 } \
464 else \
465 { \
466 ret = !(X##_e == Y##_e \
467 && _FP_FRAC_EQ_##wc(X, Y) \
468 && (X##_s == Y##_s || !X##_e && _FP_FRAC_ZEROP_##wc(X))); \
469 } \
470 } while (0)
471
472/*
473 * Main square root routine. The input value should be cooked.
474 */
475
476#define _FP_SQRT(fs, wc, R, X) \
477do { \
478 _FP_FRAC_DECL_##wc(T); _FP_FRAC_DECL_##wc(S); \
479 _FP_W_TYPE q; \
480 switch (X##_c) \
481 { \
482 case FP_CLS_NAN: \
483 R##_s = 0; \
484 R##_c = FP_CLS_NAN; \
485 _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \
486 break; \
487 case FP_CLS_INF: \
488 if (X##_s) \
489 { \
490 R##_s = 0; \
491 R##_c = FP_CLS_NAN; /* sNAN */ \
492 } \
493 else \
494 { \
495 R##_s = 0; \
496 R##_c = FP_CLS_INF; /* sqrt(+inf) = +inf */ \
497 } \
498 break; \
499 case FP_CLS_ZERO: \
500 R##_s = X##_s; \
501 R##_c = FP_CLS_ZERO; /* sqrt(+-0) = +-0 */ \
502 break; \
503 case FP_CLS_NORMAL: \
504 R##_s = 0; \
505 if (X##_s) \
506 { \
507 R##_c = FP_CLS_NAN; /* sNAN */ \
508 break; \
509 } \
510 R##_c = FP_CLS_NORMAL; \
511 if (X##_e & 1) \
512 _FP_FRAC_SLL_##wc(X, 1); \
513 R##_e = X##_e >> 1; \
514 _FP_FRAC_SET_##wc(S, _FP_ZEROFRAC_##wc); \
515 _FP_FRAC_SET_##wc(R, _FP_ZEROFRAC_##wc); \
516 q = _FP_OVERFLOW_##fs; \
517 _FP_FRAC_SLL_##wc(X, 1); \
518 _FP_SQRT_MEAT_##wc(R, S, T, X, q); \
519 _FP_FRAC_SRL_##wc(R, 1); \
520 } \
521 } while (0)
522
523/*
524 * Convert from FP to integer
525 */
526
527/* "When a NaN, infinity, large positive argument >= 2147483648.0, or
528 * large negative argument <= -2147483649.0 is converted to an integer,
529 * the invalid_current bit...should be set and fp_exception_IEEE_754 should
530 * be raised. If the floating point invalid trap is disabled, no trap occurs
531 * and a numerical result is generated: if the sign bit of the operand
532 * is 0, the result is 2147483647; if the sign bit of the operand is 1,
533 * the result is -2147483648."
534 * Similarly for conversion to extended ints, except that the boundaries
535 * are >= 2^63, <= -(2^63 + 1), and the results are 2^63 + 1 for s=0 and
536 * -2^63 for s=1.
537 * -- SPARC Architecture Manual V9, Appendix B, which specifies how
538 * SPARCs resolve implementation dependencies in the IEEE-754 spec.
539 * I don't believe that the code below follows this. I'm not even sure
540 * it's right!
541 * It doesn't cope with needing to convert to an n bit integer when there
542 * is no n bit integer type. Fortunately gcc provides long long so this
543 * isn't a problem for sparc32.
544 * I have, however, fixed its NaN handling to conform as above.
545 * -- PMM 02/1998
546 * NB: rsigned is not 'is r declared signed?' but 'should the value stored
547 * in r be signed or unsigned?'. r is always(?) declared unsigned.
548 * Comments below are mine, BTW -- PMM
549 */
550#define _FP_TO_INT(fs, wc, r, X, rsize, rsigned) \
551 do { \
552 switch (X##_c) \
553 { \
554 case FP_CLS_NORMAL: \
555 if (X##_e < 0) \
556 { \
557 /* case FP_CLS_NAN: see above! */ \
558 case FP_CLS_ZERO: \
559 r = 0; \
560 } \
561 else if (X##_e >= rsize - (rsigned != 0)) \
562 { /* overflow */ \
563 case FP_CLS_NAN: \
564 case FP_CLS_INF: \
565 if (rsigned) \
566 { \
567 r = 1; \
568 r <<= rsize - 1; \
569 r -= 1 - X##_s; \
570 } \
571 else \
572 { \
573 r = 0; \
574 if (!X##_s) \
575 r = ~r; \
576 } \
577 } \
578 else \
579 { \
580 if (_FP_W_TYPE_SIZE*wc < rsize) \
581 { \
582 _FP_FRAC_ASSEMBLE_##wc(r, X, rsize); \
583 r <<= X##_e - _FP_WFRACBITS_##fs; \
584 } \
585 else \
586 { \
587 if (X##_e >= _FP_WFRACBITS_##fs) \
588 _FP_FRAC_SLL_##wc(X, (X##_e - _FP_WFRACBITS_##fs + 1));\
589 else \
590 _FP_FRAC_SRL_##wc(X, (_FP_WFRACBITS_##fs - X##_e - 1));\
591 _FP_FRAC_ASSEMBLE_##wc(r, X, rsize); \
592 } \
593 if (rsigned && X##_s) \
594 r = -r; \
595 } \
596 break; \
597 } \
598 } while (0)
599
600#define _FP_FROM_INT(fs, wc, X, r, rsize, rtype) \
601 do { \
602 if (r) \
603 { \
604 X##_c = FP_CLS_NORMAL; \
605 \
606 if ((X##_s = (r < 0))) \
607 r = -r; \
608 /* Note that `r' is now considered unsigned, so we don't have \
609 to worry about the single signed overflow case. */ \
610 \
611 if (rsize <= _FP_W_TYPE_SIZE) \
612 __FP_CLZ(X##_e, r); \
613 else \
614 __FP_CLZ_2(X##_e, (_FP_W_TYPE)(r >> _FP_W_TYPE_SIZE), \
615 (_FP_W_TYPE)r); \
616 if (rsize < _FP_W_TYPE_SIZE) \
617 X##_e -= (_FP_W_TYPE_SIZE - rsize); \
618 X##_e = rsize - X##_e - 1; \
619 \
620 if (_FP_FRACBITS_##fs < rsize && _FP_WFRACBITS_##fs < X##_e) \
621 __FP_FRAC_SRS_1(r, (X##_e - _FP_WFRACBITS_##fs), rsize); \
622 r &= ~((_FP_W_TYPE)1 << X##_e); \
623 _FP_FRAC_DISASSEMBLE_##wc(X, ((unsigned rtype)r), rsize); \
624 _FP_FRAC_SLL_##wc(X, (_FP_WFRACBITS_##fs - X##_e - 1)); \
625 } \
626 else \
627 { \
628 X##_c = FP_CLS_ZERO, X##_s = 0; \
629 } \
630 } while (0)
631
632
633#define FP_CONV(dfs,sfs,dwc,swc,D,S) \
634 do { \
635 _FP_FRAC_CONV_##dwc##_##swc(dfs, sfs, D, S); \
636 D##_e = S##_e; \
637 D##_c = S##_c; \
638 D##_s = S##_s; \
639 } while (0)
640
641/*
642 * Helper primitives.
643 */
644
645/* Count leading zeros in a word. */
646
647#ifndef __FP_CLZ
648#if _FP_W_TYPE_SIZE < 64
649/* this is just to shut the compiler up about shifts > word length -- PMM 02/1998 */
650#define __FP_CLZ(r, x) \
651 do { \
652 _FP_W_TYPE _t = (x); \
653 r = _FP_W_TYPE_SIZE - 1; \
654 if (_t > 0xffff) r -= 16; \
655 if (_t > 0xffff) _t >>= 16; \
656 if (_t > 0xff) r -= 8; \
657 if (_t > 0xff) _t >>= 8; \
658 if (_t & 0xf0) r -= 4; \
659 if (_t & 0xf0) _t >>= 4; \
660 if (_t & 0xc) r -= 2; \
661 if (_t & 0xc) _t >>= 2; \
662 if (_t & 0x2) r -= 1; \
663 } while (0)
664#else /* not _FP_W_TYPE_SIZE < 64 */
665#define __FP_CLZ(r, x) \
666 do { \
667 _FP_W_TYPE _t = (x); \
668 r = _FP_W_TYPE_SIZE - 1; \
669 if (_t > 0xffffffff) r -= 32; \
670 if (_t > 0xffffffff) _t >>= 32; \
671 if (_t > 0xffff) r -= 16; \
672 if (_t > 0xffff) _t >>= 16; \
673 if (_t > 0xff) r -= 8; \
674 if (_t > 0xff) _t >>= 8; \
675 if (_t & 0xf0) r -= 4; \
676 if (_t & 0xf0) _t >>= 4; \
677 if (_t & 0xc) r -= 2; \
678 if (_t & 0xc) _t >>= 2; \
679 if (_t & 0x2) r -= 1; \
680 } while (0)
681#endif /* not _FP_W_TYPE_SIZE < 64 */
682#endif /* ndef __FP_CLZ */
683
684#define _FP_DIV_HELP_imm(q, r, n, d) \
685 do { \
686 q = n / d, r = n % d; \
687 } while (0)
688