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