File: /usr/src/linux/arch/ppc/math-emu/op-common.h

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