net: hns3: support tx-scatter-gather-fraglist feature
[platform/kernel/linux-rpi.git] / include / math-emu / op-common.h
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           /* Fall through */                                                 \
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           /* Fall through */                                                 \
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     /* FALLTHRU */                                                           \
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         /* Fall through */                              \
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         /* Fall through */                              \
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           /* Fall through */                            \
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           case FP_CLS_ZERO:                                                     \
666             r = 0;                                                              \
667           }                                                                     \
668         else if (X##_e >= rsize - (rsigned > 0 || X##_s)                        \
669                  || (!rsigned && X##_s))                                        \
670           {     /* overflow */                                                  \
671           case FP_CLS_NAN:                                                      \
672           case FP_CLS_INF:                                                      \
673             if (rsigned == 2)                                                   \
674               {                                                                 \
675                 if (X##_c != FP_CLS_NORMAL                                      \
676                     || X##_e >= rsize - 1 + _FP_WFRACBITS_##fs)                 \
677                   r = 0;                                                        \
678                 else                                                            \
679                   {                                                             \
680                     _FP_FRAC_SLL_##wc(X, (X##_e - _FP_WFRACBITS_##fs + 1));     \
681                     _FP_FRAC_ASSEMBLE_##wc(r, X, rsize);                        \
682                   }                                                             \
683               }                                                                 \
684             else if (rsigned)                                                   \
685               {                                                                 \
686                 r = 1;                                                          \
687                 r <<= rsize - 1;                                                \
688                 r -= 1 - X##_s;                                                 \
689               }                                                                 \
690             else                                                                \
691               {                                                                 \
692                 r = 0;                                                          \
693                 if (!X##_s)                                                     \
694                   r = ~r;                                                       \
695               }                                                                 \
696             FP_SET_EXCEPTION(FP_EX_INVALID);                                    \
697           }                                                                     \
698         else                                                                    \
699           {                                                                     \
700             if (_FP_W_TYPE_SIZE*wc < rsize)                                     \
701               {                                                                 \
702                 _FP_FRAC_ASSEMBLE_##wc(r, X, rsize);                            \
703                 r <<= X##_e - _FP_WFRACBITS_##fs;                               \
704               }                                                                 \
705             else                                                                \
706               {                                                                 \
707                 if (X##_e >= _FP_WFRACBITS_##fs)                                \
708                   _FP_FRAC_SLL_##wc(X, (X##_e - _FP_WFRACBITS_##fs + 1));       \
709                 else if (X##_e < _FP_WFRACBITS_##fs - 1)                        \
710                   {                                                             \
711                     _FP_FRAC_SRS_##wc(X, (_FP_WFRACBITS_##fs - X##_e - 2),      \
712                                       _FP_WFRACBITS_##fs);                      \
713                     if (_FP_FRAC_LOW_##wc(X) & 1)                               \
714                       FP_SET_EXCEPTION(FP_EX_INEXACT);                          \
715                     _FP_FRAC_SRL_##wc(X, 1);                                    \
716                   }                                                             \
717                 _FP_FRAC_ASSEMBLE_##wc(r, X, rsize);                            \
718               }                                                                 \
719             if (rsigned && X##_s)                                               \
720               r = -r;                                                           \
721           }                                                                     \
722         break;                                                                  \
723       }                                                                         \
724   } while (0)
725
726 #define _FP_TO_INT_ROUND(fs, wc, r, X, rsize, rsigned)                          \
727   do {                                                                          \
728     r = 0;                                                                      \
729     switch (X##_c)                                                              \
730       {                                                                         \
731       case FP_CLS_NORMAL:                                                       \
732         if (X##_e >= _FP_FRACBITS_##fs - 1)                                     \
733           {                                                                     \
734             if (X##_e < rsize - 1 + _FP_WFRACBITS_##fs)                         \
735               {                                                                 \
736                 if (X##_e >= _FP_WFRACBITS_##fs - 1)                            \
737                   {                                                             \
738                     _FP_FRAC_ASSEMBLE_##wc(r, X, rsize);                        \
739                     r <<= X##_e - _FP_WFRACBITS_##fs + 1;                       \
740                   }                                                             \
741                 else                                                            \
742                   {                                                             \
743                     _FP_FRAC_SRL_##wc(X, _FP_WORKBITS - X##_e                   \
744                                       + _FP_FRACBITS_##fs - 1);                 \
745                     _FP_FRAC_ASSEMBLE_##wc(r, X, rsize);                        \
746                   }                                                             \
747               }                                                                 \
748           }                                                                     \
749         else                                                                    \
750           {                                                                     \
751             int _lz0, _lz1;                                                     \
752             if (X##_e <= -_FP_WORKBITS - 1)                                     \
753               _FP_FRAC_SET_##wc(X, _FP_MINFRAC_##wc);                           \
754             else                                                                \
755               _FP_FRAC_SRS_##wc(X, _FP_FRACBITS_##fs - 1 - X##_e,               \
756                                 _FP_WFRACBITS_##fs);                            \
757             _FP_FRAC_CLZ_##wc(_lz0, X);                                         \
758             _FP_ROUND(wc, X);                                                   \
759             _FP_FRAC_CLZ_##wc(_lz1, X);                                         \
760             if (_lz1 < _lz0)                                                    \
761               X##_e++; /* For overflow detection.  */                           \
762             _FP_FRAC_SRL_##wc(X, _FP_WORKBITS);                                 \
763             _FP_FRAC_ASSEMBLE_##wc(r, X, rsize);                                \
764           }                                                                     \
765         if (rsigned && X##_s)                                                   \
766           r = -r;                                                               \
767         if (X##_e >= rsize - (rsigned > 0 || X##_s)                             \
768             || (!rsigned && X##_s))                                             \
769           {     /* overflow */                                                  \
770           case FP_CLS_NAN:                                                      \
771           case FP_CLS_INF:                                                      \
772             if (!rsigned)                                                       \
773               {                                                                 \
774                 r = 0;                                                          \
775                 if (!X##_s)                                                     \
776                   r = ~r;                                                       \
777               }                                                                 \
778             else if (rsigned != 2)                                              \
779               {                                                                 \
780                 r = 1;                                                          \
781                 r <<= rsize - 1;                                                \
782                 r -= 1 - X##_s;                                                 \
783               }                                                                 \
784             FP_SET_EXCEPTION(FP_EX_INVALID);                                    \
785           }                                                                     \
786         break;                                                                  \
787       case FP_CLS_ZERO:                                                         \
788         break;                                                                  \
789       }                                                                         \
790   } while (0)
791
792 #define _FP_FROM_INT(fs, wc, X, r, rsize, rtype)                        \
793   do {                                                                  \
794     if (r)                                                              \
795       {                                                                 \
796         unsigned rtype ur_;                                             \
797         X##_c = FP_CLS_NORMAL;                                          \
798                                                                         \
799         if ((X##_s = (r < 0)))                                          \
800           ur_ = (unsigned rtype) -r;                                    \
801         else                                                            \
802           ur_ = (unsigned rtype) r;                                     \
803         (void) (((rsize) <= _FP_W_TYPE_SIZE)                            \
804                 ? ({ __FP_CLZ(X##_e, ur_); })                           \
805                 : ({                                                    \
806                      __FP_CLZ_2(X##_e, (_FP_W_TYPE)(ur_ >> _FP_W_TYPE_SIZE),  \
807                                                             (_FP_W_TYPE)ur_); \
808                   }));                                                  \
809         if (rsize < _FP_W_TYPE_SIZE)                                    \
810                 X##_e -= (_FP_W_TYPE_SIZE - rsize);                     \
811         X##_e = rsize - X##_e - 1;                                      \
812                                                                         \
813         if (_FP_FRACBITS_##fs < rsize && _FP_WFRACBITS_##fs <= X##_e)   \
814           __FP_FRAC_SRS_1(ur_, (X##_e - _FP_WFRACBITS_##fs + 1), rsize);\
815         _FP_FRAC_DISASSEMBLE_##wc(X, ur_, rsize);                       \
816         if ((_FP_WFRACBITS_##fs - X##_e - 1) > 0)                       \
817           _FP_FRAC_SLL_##wc(X, (_FP_WFRACBITS_##fs - X##_e - 1));       \
818       }                                                                 \
819     else                                                                \
820       {                                                                 \
821         X##_c = FP_CLS_ZERO, X##_s = 0;                                 \
822       }                                                                 \
823   } while (0)
824
825
826 #define FP_CONV(dfs,sfs,dwc,swc,D,S)                    \
827   do {                                                  \
828     _FP_FRAC_CONV_##dwc##_##swc(dfs, sfs, D, S);        \
829     D##_e = S##_e;                                      \
830     D##_c = S##_c;                                      \
831     D##_s = S##_s;                                      \
832   } while (0)
833
834 /*
835  * Helper primitives.
836  */
837
838 /* Count leading zeros in a word.  */
839
840 #ifndef __FP_CLZ
841 #if _FP_W_TYPE_SIZE < 64
842 /* this is just to shut the compiler up about shifts > word length -- PMM 02/1998 */
843 #define __FP_CLZ(r, x)                          \
844   do {                                          \
845     _FP_W_TYPE _t = (x);                        \
846     r = _FP_W_TYPE_SIZE - 1;                    \
847     if (_t > 0xffff) r -= 16;                   \
848     if (_t > 0xffff) _t >>= 16;                 \
849     if (_t > 0xff) r -= 8;                      \
850     if (_t > 0xff) _t >>= 8;                    \
851     if (_t & 0xf0) r -= 4;                      \
852     if (_t & 0xf0) _t >>= 4;                    \
853     if (_t & 0xc) r -= 2;                       \
854     if (_t & 0xc) _t >>= 2;                     \
855     if (_t & 0x2) r -= 1;                       \
856   } while (0)
857 #else /* not _FP_W_TYPE_SIZE < 64 */
858 #define __FP_CLZ(r, x)                          \
859   do {                                          \
860     _FP_W_TYPE _t = (x);                        \
861     r = _FP_W_TYPE_SIZE - 1;                    \
862     if (_t > 0xffffffff) r -= 32;               \
863     if (_t > 0xffffffff) _t >>= 32;             \
864     if (_t > 0xffff) r -= 16;                   \
865     if (_t > 0xffff) _t >>= 16;                 \
866     if (_t > 0xff) r -= 8;                      \
867     if (_t > 0xff) _t >>= 8;                    \
868     if (_t & 0xf0) r -= 4;                      \
869     if (_t & 0xf0) _t >>= 4;                    \
870     if (_t & 0xc) r -= 2;                       \
871     if (_t & 0xc) _t >>= 2;                     \
872     if (_t & 0x2) r -= 1;                       \
873   } while (0)
874 #endif /* not _FP_W_TYPE_SIZE < 64 */
875 #endif /* ndef __FP_CLZ */
876
877 #define _FP_DIV_HELP_imm(q, r, n, d)            \
878   do {                                          \
879     q = n / d, r = n % d;                       \
880   } while (0)
881
882 #endif /* __MATH_EMU_OP_COMMON_H__ */