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