[POWERPC] Fix performance monitor on machines with logical PVR
[linux-2.6] / arch / powerpc / 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             _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)                                             \
138 do {                                                                         \
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)                        \
298 do {                                                    \
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)                        \
359 do {                                                    \
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)                                          \
477 do {                                                                    \
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