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 truly 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 | FP_EX_INVALID_SNAN);		\
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  	    if (_FP_FRAC_HIGH_##fs(X)				\
143  		& (_FP_OVERFLOW_##fs >> 1))			\
144  	      {							\
145  	        X##_e = 1;					\
146  	        _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc);	\
147  	      }							\
148  	    else						\
149  	      {							\
150  		_FP_ROUND(wc, X);				\
151  		if (_FP_FRAC_HIGH_##fs(X)			\
152  		   & (_FP_OVERFLOW_##fs >> 1))			\
153  		  {						\
154  		    X##_e = 1;					\
155  		    _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc);	\
156  		    FP_SET_EXCEPTION(FP_EX_INEXACT);		\
157  		  }						\
158  		else						\
159  		  {						\
160  		    X##_e = 0;					\
161  		    _FP_FRAC_SRL_##wc(X, _FP_WORKBITS);		\
162  		  }						\
163  	      }							\
164  	    if ((FP_CUR_EXCEPTIONS & FP_EX_INEXACT) ||		\
165  		(FP_TRAPPING_EXCEPTIONS & FP_EX_UNDERFLOW))	\
166  		FP_SET_EXCEPTION(FP_EX_UNDERFLOW);		\
167  	  }							\
168  	else							\
169  	  {							\
170  	    /* underflow to zero */				\
171  	    X##_e = 0;						\
172  	    if (!_FP_FRAC_ZEROP_##wc(X))			\
173  	      {							\
174  	        _FP_FRAC_SET_##wc(X, _FP_MINFRAC_##wc);		\
175  	        _FP_ROUND(wc, X);				\
176  	        _FP_FRAC_LOW_##wc(X) >>= (_FP_WORKBITS);	\
177  	      }							\
178  	    FP_SET_EXCEPTION(FP_EX_UNDERFLOW);			\
179  	  }							\
180        }								\
181      break;							\
182  								\
183    case FP_CLS_ZERO:						\
184      X##_e = 0;							\
185      _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc);			\
186      break;							\
187  								\
188    case FP_CLS_INF:						\
189      X##_e = _FP_EXPMAX_##fs;					\
190      _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc);			\
191      break;							\
192  								\
193    case FP_CLS_NAN:						\
194      X##_e = _FP_EXPMAX_##fs;					\
195      if (!_FP_KEEPNANFRACP)					\
196        {								\
197  	_FP_FRAC_SET_##wc(X, _FP_NANFRAC_##fs);			\
198  	X##_s = _FP_NANSIGN_##fs;				\
199        }								\
200      else							\
201        _FP_FRAC_HIGH_RAW_##fs(X) |= _FP_QNANBIT_##fs;		\
202      break;							\
203    }								\
204  } while (0)
205  
206  /* This one accepts raw argument and not cooked,  returns
207   * 1 if X is a signaling NaN.
208   */
209  #define _FP_ISSIGNAN(fs, wc, X)					\
210  ({								\
211    int __ret = 0;						\
212    if (X##_e == _FP_EXPMAX_##fs)					\
213      {								\
214        if (!_FP_FRAC_ZEROP_##wc(X)				\
215  	  && !(_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs))	\
216  	__ret = 1;						\
217      }								\
218    __ret;							\
219  })
220  
221  
222  
223  
224  
225  /*
226   * Main addition routine.  The input values should be cooked.
227   */
228  
229  #define _FP_ADD_INTERNAL(fs, wc, R, X, Y, OP)				     \
230  do {									     \
231    switch (_FP_CLS_COMBINE(X##_c, Y##_c))				     \
232    {									     \
233    case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NORMAL):			     \
234      {									     \
235        /* shift the smaller number so that its exponent matches the larger */ \
236        _FP_I_TYPE diff = X##_e - Y##_e;					     \
237  									     \
238        if (diff < 0)							     \
239  	{								     \
240  	  diff = -diff;							     \
241  	  if (diff <= _FP_WFRACBITS_##fs)				     \
242  	    _FP_FRAC_SRS_##wc(X, diff, _FP_WFRACBITS_##fs);		     \
243  	  else if (!_FP_FRAC_ZEROP_##wc(X))				     \
244  	    _FP_FRAC_SET_##wc(X, _FP_MINFRAC_##wc);			     \
245  	  R##_e = Y##_e;						     \
246  	}								     \
247        else								     \
248  	{								     \
249  	  if (diff > 0)							     \
250  	    {								     \
251  	      if (diff <= _FP_WFRACBITS_##fs)				     \
252  	        _FP_FRAC_SRS_##wc(Y, diff, _FP_WFRACBITS_##fs);		     \
253  	      else if (!_FP_FRAC_ZEROP_##wc(Y))				     \
254  	        _FP_FRAC_SET_##wc(Y, _FP_MINFRAC_##wc);			     \
255  	    }								     \
256  	  R##_e = X##_e;						     \
257  	}								     \
258  									     \
259        R##_c = FP_CLS_NORMAL;						     \
260  									     \
261        if (X##_s == Y##_s)						     \
262  	{								     \
263  	  R##_s = X##_s;						     \
264  	  _FP_FRAC_ADD_##wc(R, X, Y);					     \
265  	  if (_FP_FRAC_OVERP_##wc(fs, R))				     \
266  	    {								     \
267  	      _FP_FRAC_SRS_##wc(R, 1, _FP_WFRACBITS_##fs);		     \
268  	      R##_e++;							     \
269  	    }								     \
270  	}								     \
271        else								     \
272  	{								     \
273  	  R##_s = X##_s;						     \
274  	  _FP_FRAC_SUB_##wc(R, X, Y);					     \
275  	  if (_FP_FRAC_ZEROP_##wc(R))					     \
276  	    {								     \
277  	      /* return an exact zero */				     \
278  	      if (FP_ROUNDMODE == FP_RND_MINF)				     \
279  		R##_s |= Y##_s;						     \
280  	      else							     \
281  		R##_s &= Y##_s;						     \
282  	      R##_c = FP_CLS_ZERO;					     \
283  	    }								     \
284  	  else								     \
285  	    {								     \
286  	      if (_FP_FRAC_NEGP_##wc(R))				     \
287  		{							     \
288  		  _FP_FRAC_SUB_##wc(R, Y, X);				     \
289  		  R##_s = Y##_s;					     \
290  		}							     \
291  									     \
292  	      /* renormalize after subtraction */			     \
293  	      _FP_FRAC_CLZ_##wc(diff, R);				     \
294  	      diff -= _FP_WFRACXBITS_##fs;				     \
295  	      if (diff)							     \
296  		{							     \
297  		  R##_e -= diff;					     \
298  		  _FP_FRAC_SLL_##wc(R, diff);				     \
299  		}							     \
300  	    }								     \
301  	}								     \
302        break;								     \
303      }									     \
304  									     \
305    case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NAN):				     \
306      _FP_CHOOSENAN(fs, wc, R, X, Y, OP);					     \
307      break;								     \
308  									     \
309    case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO):			     \
310      R##_e = X##_e;							     \
311  	fallthrough;							     \
312    case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL):			     \
313    case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF):				     \
314    case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO):				     \
315      _FP_FRAC_COPY_##wc(R, X);						     \
316      R##_s = X##_s;							     \
317      R##_c = X##_c;							     \
318      break;								     \
319  									     \
320    case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NORMAL):			     \
321      R##_e = Y##_e;							     \
322  	fallthrough;							     \
323    case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NAN):			     \
324    case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN):				     \
325    case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN):				     \
326      _FP_FRAC_COPY_##wc(R, Y);						     \
327      R##_s = Y##_s;							     \
328      R##_c = Y##_c;							     \
329      break;								     \
330  									     \
331    case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF):				     \
332      if (X##_s != Y##_s)							     \
333        {									     \
334  	/* +INF + -INF => NAN */					     \
335  	_FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs);				     \
336  	R##_s = _FP_NANSIGN_##fs;					     \
337  	R##_c = FP_CLS_NAN;						     \
338  	FP_SET_EXCEPTION(FP_EX_INVALID | FP_EX_INVALID_ISI);		     \
339  	break;								     \
340        }									     \
341      fallthrough;							     \
342  									     \
343    case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL):			     \
344    case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_ZERO):				     \
345      R##_s = X##_s;							     \
346      R##_c = FP_CLS_INF;							     \
347      break;								     \
348  									     \
349    case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_INF):			     \
350    case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_INF):				     \
351      R##_s = Y##_s;							     \
352      R##_c = FP_CLS_INF;							     \
353      break;								     \
354  									     \
355    case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_ZERO):			     \
356      /* make sure the sign is correct */					     \
357      if (FP_ROUNDMODE == FP_RND_MINF)					     \
358        R##_s = X##_s | Y##_s;						     \
359      else								     \
360        R##_s = X##_s & Y##_s;						     \
361      R##_c = FP_CLS_ZERO;						     \
362      break;								     \
363  									     \
364    default:								     \
365      abort();								     \
366    }									     \
367  } while (0)
368  
369  #define _FP_ADD(fs, wc, R, X, Y) _FP_ADD_INTERNAL(fs, wc, R, X, Y, '+')
370  #define _FP_SUB(fs, wc, R, X, Y)					     \
371    do {									     \
372      if (Y##_c != FP_CLS_NAN) Y##_s ^= 1;				     \
373      _FP_ADD_INTERNAL(fs, wc, R, X, Y, '-');				     \
374    } while (0)
375  
376  
377  /*
378   * Main negation routine.  FIXME -- when we care about setting exception
379   * bits reliably, this will not do.  We should examine all of the fp classes.
380   */
381  
382  #define _FP_NEG(fs, wc, R, X)		\
383    do {					\
384      _FP_FRAC_COPY_##wc(R, X);		\
385      R##_c = X##_c;			\
386      R##_e = X##_e;			\
387      R##_s = 1 ^ X##_s;			\
388    } while (0)
389  
390  
391  /*
392   * Main multiplication routine.  The input values should be cooked.
393   */
394  
395  #define _FP_MUL(fs, wc, R, X, Y)			\
396  do {							\
397    R##_s = X##_s ^ Y##_s;				\
398    switch (_FP_CLS_COMBINE(X##_c, Y##_c))		\
399    {							\
400    case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NORMAL):	\
401      R##_c = FP_CLS_NORMAL;				\
402      R##_e = X##_e + Y##_e + 1;				\
403  							\
404      _FP_MUL_MEAT_##fs(R,X,Y);				\
405  							\
406      if (_FP_FRAC_OVERP_##wc(fs, R))			\
407        _FP_FRAC_SRS_##wc(R, 1, _FP_WFRACBITS_##fs);	\
408      else						\
409        R##_e--;						\
410      break;						\
411  							\
412    case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NAN):		\
413      _FP_CHOOSENAN(fs, wc, R, X, Y, '*');		\
414      break;						\
415  							\
416    case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL):	\
417    case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF):		\
418    case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO):		\
419      R##_s = X##_s;					\
420  	  fallthrough;					\
421  							\
422    case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF):		\
423    case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL):	\
424    case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NORMAL):	\
425    case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_ZERO):	\
426      _FP_FRAC_COPY_##wc(R, X);				\
427      R##_c = X##_c;					\
428      break;						\
429  							\
430    case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NAN):	\
431    case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN):		\
432    case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN):		\
433      R##_s = Y##_s;					\
434  	  fallthrough;					\
435  							\
436    case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_INF):	\
437    case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO):	\
438      _FP_FRAC_COPY_##wc(R, Y);				\
439      R##_c = Y##_c;					\
440      break;						\
441  							\
442    case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_ZERO):		\
443    case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_INF):		\
444      R##_s = _FP_NANSIGN_##fs;				\
445      R##_c = FP_CLS_NAN;					\
446      _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs);		\
447      FP_SET_EXCEPTION(FP_EX_INVALID | FP_EX_INVALID_IMZ);\
448      break;						\
449  							\
450    default:						\
451      abort();						\
452    }							\
453  } while (0)
454  
455  
456  /*
457   * Main division routine.  The input values should be cooked.
458   */
459  
460  #define _FP_DIV(fs, wc, R, X, Y)			\
461  do {							\
462    R##_s = X##_s ^ Y##_s;				\
463    switch (_FP_CLS_COMBINE(X##_c, Y##_c))		\
464    {							\
465    case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NORMAL):	\
466      R##_c = FP_CLS_NORMAL;				\
467      R##_e = X##_e - Y##_e;				\
468  							\
469      _FP_DIV_MEAT_##fs(R,X,Y);				\
470      break;						\
471  							\
472    case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NAN):		\
473      _FP_CHOOSENAN(fs, wc, R, X, Y, '/');		\
474      break;						\
475  							\
476    case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL):	\
477    case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF):		\
478    case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO):		\
479      R##_s = X##_s;					\
480      _FP_FRAC_COPY_##wc(R, X);				\
481      R##_c = X##_c;					\
482      break;						\
483  							\
484    case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NAN):	\
485    case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN):		\
486    case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN):		\
487      R##_s = Y##_s;					\
488      _FP_FRAC_COPY_##wc(R, Y);				\
489      R##_c = Y##_c;					\
490      break;						\
491  							\
492    case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_INF):	\
493    case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_INF):		\
494    case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NORMAL):	\
495      R##_c = FP_CLS_ZERO;				\
496      break;						\
497  							\
498    case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO):	\
499      FP_SET_EXCEPTION(FP_EX_DIVZERO);			\
500  	fallthrough;					\
501    case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_ZERO):		\
502    case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL):	\
503      R##_c = FP_CLS_INF;					\
504      break;						\
505  							\
506    case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF):		\
507      R##_s = _FP_NANSIGN_##fs;				\
508      R##_c = FP_CLS_NAN;					\
509      _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs);		\
510      FP_SET_EXCEPTION(FP_EX_INVALID | FP_EX_INVALID_IDI);\
511      break;						\
512  							\
513    case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_ZERO):	\
514      R##_s = _FP_NANSIGN_##fs;				\
515      R##_c = FP_CLS_NAN;					\
516      _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs);		\
517      FP_SET_EXCEPTION(FP_EX_INVALID | FP_EX_INVALID_ZDZ);\
518      break;						\
519  							\
520    default:						\
521      abort();						\
522    }							\
523  } while (0)
524  
525  
526  /*
527   * Main differential comparison routine.  The inputs should be raw not
528   * cooked.  The return is -1,0,1 for normal values, 2 otherwise.
529   */
530  
531  #define _FP_CMP(fs, wc, ret, X, Y, un)					\
532    do {									\
533      /* NANs are unordered */						\
534      if ((X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(X))		\
535  	|| (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(Y)))	\
536        {									\
537  	ret = un;							\
538        }									\
539      else								\
540        {									\
541  	int __is_zero_x;						\
542  	int __is_zero_y;						\
543  									\
544  	__is_zero_x = (!X##_e && _FP_FRAC_ZEROP_##wc(X)) ? 1 : 0;	\
545  	__is_zero_y = (!Y##_e && _FP_FRAC_ZEROP_##wc(Y)) ? 1 : 0;	\
546  									\
547  	if (__is_zero_x && __is_zero_y)					\
548  		ret = 0;						\
549  	else if (__is_zero_x)						\
550  		ret = Y##_s ? 1 : -1;					\
551  	else if (__is_zero_y)						\
552  		ret = X##_s ? -1 : 1;					\
553  	else if (X##_s != Y##_s)					\
554  	  ret = X##_s ? -1 : 1;						\
555  	else if (X##_e > Y##_e)						\
556  	  ret = X##_s ? -1 : 1;						\
557  	else if (X##_e < Y##_e)						\
558  	  ret = X##_s ? 1 : -1;						\
559  	else if (_FP_FRAC_GT_##wc(X, Y))				\
560  	  ret = X##_s ? -1 : 1;						\
561  	else if (_FP_FRAC_GT_##wc(Y, X))				\
562  	  ret = X##_s ? 1 : -1;						\
563  	else								\
564  	  ret = 0;							\
565        }									\
566    } while (0)
567  
568  
569  /* Simplification for strict equality.  */
570  
571  #define _FP_CMP_EQ(fs, wc, ret, X, Y)					  \
572    do {									  \
573      /* NANs are unordered */						  \
574      if ((X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(X))		  \
575  	|| (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(Y)))	  \
576        {									  \
577  	ret = 1;							  \
578        }									  \
579      else								  \
580        {									  \
581  	ret = !(X##_e == Y##_e						  \
582  		&& _FP_FRAC_EQ_##wc(X, Y)				  \
583  		&& (X##_s == Y##_s || !X##_e && _FP_FRAC_ZEROP_##wc(X))); \
584        }									  \
585    } while (0)
586  
587  /*
588   * Main square root routine.  The input value should be cooked.
589   */
590  
591  #define _FP_SQRT(fs, wc, R, X)						\
592  do {									\
593      _FP_FRAC_DECL_##wc(T); _FP_FRAC_DECL_##wc(S);			\
594      _FP_W_TYPE q;							\
595      switch (X##_c)							\
596      {									\
597      case FP_CLS_NAN:							\
598  	_FP_FRAC_COPY_##wc(R, X);					\
599  	R##_s = X##_s;							\
600      	R##_c = FP_CLS_NAN;						\
601      	break;								\
602      case FP_CLS_INF:							\
603      	if (X##_s)							\
604      	  {								\
605      	    R##_s = _FP_NANSIGN_##fs;					\
606  	    R##_c = FP_CLS_NAN; /* NAN */				\
607  	    _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs);			\
608  	    FP_SET_EXCEPTION(FP_EX_INVALID);				\
609      	  }								\
610      	else								\
611      	  {								\
612      	    R##_s = 0;							\
613      	    R##_c = FP_CLS_INF; /* sqrt(+inf) = +inf */			\
614      	  }								\
615      	break;								\
616      case FP_CLS_ZERO:							\
617  	R##_s = X##_s;							\
618  	R##_c = FP_CLS_ZERO; /* sqrt(+-0) = +-0 */			\
619  	break;								\
620      case FP_CLS_NORMAL:							\
621      	R##_s = 0;							\
622          if (X##_s)							\
623            {								\
624  	    R##_c = FP_CLS_NAN; /* sNAN */				\
625  	    R##_s = _FP_NANSIGN_##fs;					\
626  	    _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs);			\
627  	    FP_SET_EXCEPTION(FP_EX_INVALID);				\
628  	    break;							\
629            }								\
630      	R##_c = FP_CLS_NORMAL;						\
631          if (X##_e & 1)							\
632            _FP_FRAC_SLL_##wc(X, 1);					\
633          R##_e = X##_e >> 1;						\
634          _FP_FRAC_SET_##wc(S, _FP_ZEROFRAC_##wc);			\
635          _FP_FRAC_SET_##wc(R, _FP_ZEROFRAC_##wc);			\
636          q = _FP_OVERFLOW_##fs >> 1;					\
637          _FP_SQRT_MEAT_##wc(R, S, T, X, q);				\
638      }									\
639    } while (0)
640  
641  /*
642   * Convert from FP to integer
643   */
644  
645  /* RSIGNED can have following values:
646   * 0:  the number is required to be 0..(2^rsize)-1, if not, NV is set plus
647   *     the result is either 0 or (2^rsize)-1 depending on the sign in such case.
648   * 1:  the number is required to be -(2^(rsize-1))..(2^(rsize-1))-1, if not, NV is
649   *     set plus the result is either -(2^(rsize-1)) or (2^(rsize-1))-1 depending
650   *     on the sign in such case.
651   * 2:  the number is required to be -(2^(rsize-1))..(2^(rsize-1))-1, if not, NV is
652   *     set plus the result is truncated to fit into destination.
653   * -1: the number is required to be -(2^(rsize-1))..(2^rsize)-1, if not, NV is
654   *     set plus the result is either -(2^(rsize-1)) or (2^(rsize-1))-1 depending
655   *     on the sign in such case.
656   */
657  #define _FP_TO_INT(fs, wc, r, X, rsize, rsigned)				\
658    do {										\
659      switch (X##_c)								\
660        {										\
661        case FP_CLS_NORMAL:							\
662  	if (X##_e < 0)								\
663  	  {									\
664  	    FP_SET_EXCEPTION(FP_EX_INEXACT);					\
665  	    fallthrough;							\
666  	  case FP_CLS_ZERO:							\
667  	    r = 0;								\
668  	  }									\
669  	else if (X##_e >= rsize - (rsigned > 0 || X##_s)			\
670  		 || (!rsigned && X##_s))					\
671  	  {	/* overflow */							\
672  	    fallthrough;							\
673  	  case FP_CLS_NAN:                                                      \
674  	  case FP_CLS_INF:							\
675  	    if (rsigned == 2)							\
676  	      {									\
677  		if (X##_c != FP_CLS_NORMAL					\
678  		    || X##_e >= rsize - 1 + _FP_WFRACBITS_##fs)			\
679  		  r = 0;							\
680  		else								\
681  		  {								\
682  		    _FP_FRAC_SLL_##wc(X, (X##_e - _FP_WFRACBITS_##fs + 1));	\
683  		    _FP_FRAC_ASSEMBLE_##wc(r, X, rsize);			\
684  		  }								\
685  	      }									\
686  	    else if (rsigned)							\
687  	      {									\
688  		r = 1;								\
689  		r <<= rsize - 1;						\
690  		r -= 1 - X##_s;							\
691  	      }									\
692  	    else								\
693  	      {									\
694  		r = 0;								\
695  		if (!X##_s)							\
696  		  r = ~r;							\
697  	      }									\
698  	    FP_SET_EXCEPTION(FP_EX_INVALID);					\
699  	  }									\
700  	else									\
701  	  {									\
702  	    if (_FP_W_TYPE_SIZE*wc < rsize)					\
703  	      {									\
704  		_FP_FRAC_ASSEMBLE_##wc(r, X, rsize);				\
705  		r <<= X##_e - _FP_WFRACBITS_##fs;				\
706  	      }									\
707  	    else								\
708  	      {									\
709  		if (X##_e >= _FP_WFRACBITS_##fs)				\
710  		  _FP_FRAC_SLL_##wc(X, (X##_e - _FP_WFRACBITS_##fs + 1));	\
711  		else if (X##_e < _FP_WFRACBITS_##fs - 1)			\
712  		  {								\
713  		    _FP_FRAC_SRS_##wc(X, (_FP_WFRACBITS_##fs - X##_e - 2),	\
714  				      _FP_WFRACBITS_##fs);			\
715  		    if (_FP_FRAC_LOW_##wc(X) & 1)				\
716  		      FP_SET_EXCEPTION(FP_EX_INEXACT);				\
717  		    _FP_FRAC_SRL_##wc(X, 1);					\
718  		  }								\
719  		_FP_FRAC_ASSEMBLE_##wc(r, X, rsize);				\
720  	      }									\
721  	    if (rsigned && X##_s)						\
722  	      r = -r;								\
723  	  }									\
724  	break;									\
725        }										\
726    } while (0)
727  
728  #define _FP_TO_INT_ROUND(fs, wc, r, X, rsize, rsigned)				\
729    do {										\
730      r = 0;									\
731      switch (X##_c)								\
732        {										\
733        case FP_CLS_NORMAL:							\
734  	if (X##_e >= _FP_FRACBITS_##fs - 1)					\
735  	  {									\
736  	    if (X##_e < rsize - 1 + _FP_WFRACBITS_##fs)				\
737  	      {									\
738  		if (X##_e >= _FP_WFRACBITS_##fs - 1)				\
739  		  {								\
740  		    _FP_FRAC_ASSEMBLE_##wc(r, X, rsize);			\
741  		    r <<= X##_e - _FP_WFRACBITS_##fs + 1;			\
742  		  }								\
743  		else								\
744  		  {								\
745  		    _FP_FRAC_SRL_##wc(X, _FP_WORKBITS - X##_e			\
746  				      + _FP_FRACBITS_##fs - 1);			\
747  		    _FP_FRAC_ASSEMBLE_##wc(r, X, rsize);			\
748  		  }								\
749  	      }									\
750  	  }									\
751  	else									\
752  	  {									\
753  	    int _lz0, _lz1;							\
754  	    if (X##_e <= -_FP_WORKBITS - 1)					\
755  	      _FP_FRAC_SET_##wc(X, _FP_MINFRAC_##wc);				\
756  	    else								\
757  	      _FP_FRAC_SRS_##wc(X, _FP_FRACBITS_##fs - 1 - X##_e,		\
758  				_FP_WFRACBITS_##fs);				\
759  	    _FP_FRAC_CLZ_##wc(_lz0, X);						\
760  	    _FP_ROUND(wc, X);							\
761  	    _FP_FRAC_CLZ_##wc(_lz1, X);						\
762  	    if (_lz1 < _lz0)							\
763  	      X##_e++; /* For overflow detection.  */				\
764  	    _FP_FRAC_SRL_##wc(X, _FP_WORKBITS);					\
765  	    _FP_FRAC_ASSEMBLE_##wc(r, X, rsize);				\
766  	  }									\
767  	if (rsigned && X##_s)							\
768  	  r = -r;								\
769  	if (X##_e >= rsize - (rsigned > 0 || X##_s)				\
770  	    || (!rsigned && X##_s))						\
771  	  {	/* overflow */							\
772  	    fallthrough;							\
773  	  case FP_CLS_NAN:                                                      \
774  	  case FP_CLS_INF:							\
775  	    if (!rsigned)							\
776  	      {									\
777  		r = 0;								\
778  		if (!X##_s)							\
779  		  r = ~r;							\
780  	      }									\
781  	    else if (rsigned != 2)						\
782  	      {									\
783  		r = 1;								\
784  		r <<= rsize - 1;						\
785  		r -= 1 - X##_s;							\
786  	      }									\
787  	    FP_SET_EXCEPTION(FP_EX_INVALID);					\
788  	  }									\
789  	break;									\
790        case FP_CLS_ZERO:								\
791          break;									\
792        }										\
793    } while (0)
794  
795  #define _FP_FROM_INT(fs, wc, X, r, rsize, rtype)			\
796    do {									\
797      if (r)								\
798        {									\
799          unsigned rtype ur_;						\
800  	X##_c = FP_CLS_NORMAL;						\
801  									\
802  	if ((X##_s = (r < 0)))						\
803  	  ur_ = (unsigned rtype) -r;					\
804  	else								\
805  	  ur_ = (unsigned rtype) r;					\
806  	(void) (((rsize) <= _FP_W_TYPE_SIZE)				\
807  		? ({ __FP_CLZ(X##_e, ur_); })				\
808  		: ({							\
809  		     __FP_CLZ_2(X##_e, (_FP_W_TYPE)(ur_ >> _FP_W_TYPE_SIZE),  \
810  							    (_FP_W_TYPE)ur_); \
811  		  }));							\
812  	if (rsize < _FP_W_TYPE_SIZE)					\
813  		X##_e -= (_FP_W_TYPE_SIZE - rsize);			\
814  	X##_e = rsize - X##_e - 1;					\
815  									\
816  	if (_FP_FRACBITS_##fs < rsize && _FP_WFRACBITS_##fs <= X##_e)	\
817  	  __FP_FRAC_SRS_1(ur_, (X##_e - _FP_WFRACBITS_##fs + 1), rsize);\
818  	_FP_FRAC_DISASSEMBLE_##wc(X, ur_, rsize);			\
819  	if ((_FP_WFRACBITS_##fs - X##_e - 1) > 0)			\
820  	  _FP_FRAC_SLL_##wc(X, (_FP_WFRACBITS_##fs - X##_e - 1));	\
821        }									\
822      else								\
823        {									\
824  	X##_c = FP_CLS_ZERO, X##_s = 0;					\
825        }									\
826    } while (0)
827  
828  
829  #define FP_CONV(dfs,sfs,dwc,swc,D,S)			\
830    do {							\
831      _FP_FRAC_CONV_##dwc##_##swc(dfs, sfs, D, S);	\
832      D##_e = S##_e;					\
833      D##_c = S##_c;					\
834      D##_s = S##_s;					\
835    } while (0)
836  
837  /*
838   * Helper primitives.
839   */
840  
841  /* Count leading zeros in a word.  */
842  
843  #ifndef __FP_CLZ
844  #if _FP_W_TYPE_SIZE < 64
845  /* this is just to shut the compiler up about shifts > word length -- PMM 02/1998 */
846  #define __FP_CLZ(r, x)				\
847    do {						\
848      _FP_W_TYPE _t = (x);			\
849      r = _FP_W_TYPE_SIZE - 1;			\
850      if (_t > 0xffff) r -= 16;			\
851      if (_t > 0xffff) _t >>= 16;			\
852      if (_t > 0xff) r -= 8;			\
853      if (_t > 0xff) _t >>= 8;			\
854      if (_t & 0xf0) r -= 4;			\
855      if (_t & 0xf0) _t >>= 4;			\
856      if (_t & 0xc) r -= 2;			\
857      if (_t & 0xc) _t >>= 2;			\
858      if (_t & 0x2) r -= 1;			\
859    } while (0)
860  #else /* not _FP_W_TYPE_SIZE < 64 */
861  #define __FP_CLZ(r, x)				\
862    do {						\
863      _FP_W_TYPE _t = (x);			\
864      r = _FP_W_TYPE_SIZE - 1;			\
865      if (_t > 0xffffffff) r -= 32;		\
866      if (_t > 0xffffffff) _t >>= 32;		\
867      if (_t > 0xffff) r -= 16;			\
868      if (_t > 0xffff) _t >>= 16;			\
869      if (_t > 0xff) r -= 8;			\
870      if (_t > 0xff) _t >>= 8;			\
871      if (_t & 0xf0) r -= 4;			\
872      if (_t & 0xf0) _t >>= 4;			\
873      if (_t & 0xc) r -= 2;			\
874      if (_t & 0xc) _t >>= 2;			\
875      if (_t & 0x2) r -= 1;			\
876    } while (0)
877  #endif /* not _FP_W_TYPE_SIZE < 64 */
878  #endif /* ndef __FP_CLZ */
879  
880  #define _FP_DIV_HELP_imm(q, r, n, d)		\
881    do {						\
882      q = n / d, r = n % d;			\
883    } while (0)
884  
885  #endif /* __MATH_EMU_OP_COMMON_H__ */
886