Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
op-common.h
Go to the documentation of this file.
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 ([email protected]),
5  Jakub Jelinek ([email protected]),
6  David S. Miller ([email protected]) and
7  Peter Maydell ([email protected]).
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  case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL): \
312  case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF): \
313  case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO): \
314  _FP_FRAC_COPY_##wc(R, X); \
315  R##_s = X##_s; \
316  R##_c = X##_c; \
317  break; \
318  \
319  case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NORMAL): \
320  R##_e = Y##_e; \
321  case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NAN): \
322  case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN): \
323  case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN): \
324  _FP_FRAC_COPY_##wc(R, Y); \
325  R##_s = Y##_s; \
326  R##_c = Y##_c; \
327  break; \
328  \
329  case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF): \
330  if (X##_s != Y##_s) \
331  { \
332  /* +INF + -INF => NAN */ \
333  _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \
334  R##_s = _FP_NANSIGN_##fs; \
335  R##_c = FP_CLS_NAN; \
336  FP_SET_EXCEPTION(FP_EX_INVALID | FP_EX_INVALID_ISI); \
337  break; \
338  } \
339  /* FALLTHRU */ \
340  \
341  case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL): \
342  case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_ZERO): \
343  R##_s = X##_s; \
344  R##_c = FP_CLS_INF; \
345  break; \
346  \
347  case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_INF): \
348  case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_INF): \
349  R##_s = Y##_s; \
350  R##_c = FP_CLS_INF; \
351  break; \
352  \
353  case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_ZERO): \
354  /* make sure the sign is correct */ \
355  if (FP_ROUNDMODE == FP_RND_MINF) \
356  R##_s = X##_s | Y##_s; \
357  else \
358  R##_s = X##_s & Y##_s; \
359  R##_c = FP_CLS_ZERO; \
360  break; \
361  \
362  default: \
363  abort(); \
364  } \
365 } while (0)
366 
367 #define _FP_ADD(fs, wc, R, X, Y) _FP_ADD_INTERNAL(fs, wc, R, X, Y, '+')
368 #define _FP_SUB(fs, wc, R, X, Y) \
369  do { \
370  if (Y##_c != FP_CLS_NAN) Y##_s ^= 1; \
371  _FP_ADD_INTERNAL(fs, wc, R, X, Y, '-'); \
372  } while (0)
373 
374 
375 /*
376  * Main negation routine. FIXME -- when we care about setting exception
377  * bits reliably, this will not do. We should examine all of the fp classes.
378  */
379 
380 #define _FP_NEG(fs, wc, R, X) \
381  do { \
382  _FP_FRAC_COPY_##wc(R, X); \
383  R##_c = X##_c; \
384  R##_e = X##_e; \
385  R##_s = 1 ^ X##_s; \
386  } while (0)
387 
388 
389 /*
390  * Main multiplication routine. The input values should be cooked.
391  */
392 
393 #define _FP_MUL(fs, wc, R, X, Y) \
394 do { \
395  R##_s = X##_s ^ Y##_s; \
396  switch (_FP_CLS_COMBINE(X##_c, Y##_c)) \
397  { \
398  case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NORMAL): \
399  R##_c = FP_CLS_NORMAL; \
400  R##_e = X##_e + Y##_e + 1; \
401  \
402  _FP_MUL_MEAT_##fs(R,X,Y); \
403  \
404  if (_FP_FRAC_OVERP_##wc(fs, R)) \
405  _FP_FRAC_SRS_##wc(R, 1, _FP_WFRACBITS_##fs); \
406  else \
407  R##_e--; \
408  break; \
409  \
410  case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NAN): \
411  _FP_CHOOSENAN(fs, wc, R, X, Y, '*'); \
412  break; \
413  \
414  case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL): \
415  case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF): \
416  case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO): \
417  R##_s = X##_s; \
418  \
419  case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF): \
420  case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL): \
421  case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NORMAL): \
422  case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_ZERO): \
423  _FP_FRAC_COPY_##wc(R, X); \
424  R##_c = X##_c; \
425  break; \
426  \
427  case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NAN): \
428  case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN): \
429  case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN): \
430  R##_s = Y##_s; \
431  \
432  case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_INF): \
433  case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO): \
434  _FP_FRAC_COPY_##wc(R, Y); \
435  R##_c = Y##_c; \
436  break; \
437  \
438  case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_ZERO): \
439  case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_INF): \
440  R##_s = _FP_NANSIGN_##fs; \
441  R##_c = FP_CLS_NAN; \
442  _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \
443  FP_SET_EXCEPTION(FP_EX_INVALID | FP_EX_INVALID_IMZ);\
444  break; \
445  \
446  default: \
447  abort(); \
448  } \
449 } while (0)
450 
451 
452 /*
453  * Main division routine. The input values should be cooked.
454  */
455 
456 #define _FP_DIV(fs, wc, R, X, Y) \
457 do { \
458  R##_s = X##_s ^ Y##_s; \
459  switch (_FP_CLS_COMBINE(X##_c, Y##_c)) \
460  { \
461  case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NORMAL): \
462  R##_c = FP_CLS_NORMAL; \
463  R##_e = X##_e - Y##_e; \
464  \
465  _FP_DIV_MEAT_##fs(R,X,Y); \
466  break; \
467  \
468  case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NAN): \
469  _FP_CHOOSENAN(fs, wc, R, X, Y, '/'); \
470  break; \
471  \
472  case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL): \
473  case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF): \
474  case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO): \
475  R##_s = X##_s; \
476  _FP_FRAC_COPY_##wc(R, X); \
477  R##_c = X##_c; \
478  break; \
479  \
480  case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NAN): \
481  case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN): \
482  case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN): \
483  R##_s = Y##_s; \
484  _FP_FRAC_COPY_##wc(R, Y); \
485  R##_c = Y##_c; \
486  break; \
487  \
488  case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_INF): \
489  case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_INF): \
490  case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NORMAL): \
491  R##_c = FP_CLS_ZERO; \
492  break; \
493  \
494  case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO): \
495  FP_SET_EXCEPTION(FP_EX_DIVZERO); \
496  case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_ZERO): \
497  case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL): \
498  R##_c = FP_CLS_INF; \
499  break; \
500  \
501  case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF): \
502  R##_s = _FP_NANSIGN_##fs; \
503  R##_c = FP_CLS_NAN; \
504  _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \
505  FP_SET_EXCEPTION(FP_EX_INVALID | FP_EX_INVALID_IDI);\
506  break; \
507  \
508  case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_ZERO): \
509  R##_s = _FP_NANSIGN_##fs; \
510  R##_c = FP_CLS_NAN; \
511  _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \
512  FP_SET_EXCEPTION(FP_EX_INVALID | FP_EX_INVALID_ZDZ);\
513  break; \
514  \
515  default: \
516  abort(); \
517  } \
518 } while (0)
519 
520 
521 /*
522  * Main differential comparison routine. The inputs should be raw not
523  * cooked. The return is -1,0,1 for normal values, 2 otherwise.
524  */
525 
526 #define _FP_CMP(fs, wc, ret, X, Y, un) \
527  do { \
528  /* NANs are unordered */ \
529  if ((X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(X)) \
530  || (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(Y))) \
531  { \
532  ret = un; \
533  } \
534  else \
535  { \
536  int __is_zero_x; \
537  int __is_zero_y; \
538  \
539  __is_zero_x = (!X##_e && _FP_FRAC_ZEROP_##wc(X)) ? 1 : 0; \
540  __is_zero_y = (!Y##_e && _FP_FRAC_ZEROP_##wc(Y)) ? 1 : 0; \
541  \
542  if (__is_zero_x && __is_zero_y) \
543  ret = 0; \
544  else if (__is_zero_x) \
545  ret = Y##_s ? 1 : -1; \
546  else if (__is_zero_y) \
547  ret = X##_s ? -1 : 1; \
548  else if (X##_s != Y##_s) \
549  ret = X##_s ? -1 : 1; \
550  else if (X##_e > Y##_e) \
551  ret = X##_s ? -1 : 1; \
552  else if (X##_e < Y##_e) \
553  ret = X##_s ? 1 : -1; \
554  else if (_FP_FRAC_GT_##wc(X, Y)) \
555  ret = X##_s ? -1 : 1; \
556  else if (_FP_FRAC_GT_##wc(Y, X)) \
557  ret = X##_s ? 1 : -1; \
558  else \
559  ret = 0; \
560  } \
561  } while (0)
562 
563 
564 /* Simplification for strict equality. */
565 
566 #define _FP_CMP_EQ(fs, wc, ret, X, Y) \
567  do { \
568  /* NANs are unordered */ \
569  if ((X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(X)) \
570  || (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(Y))) \
571  { \
572  ret = 1; \
573  } \
574  else \
575  { \
576  ret = !(X##_e == Y##_e \
577  && _FP_FRAC_EQ_##wc(X, Y) \
578  && (X##_s == Y##_s || !X##_e && _FP_FRAC_ZEROP_##wc(X))); \
579  } \
580  } while (0)
581 
582 /*
583  * Main square root routine. The input value should be cooked.
584  */
585 
586 #define _FP_SQRT(fs, wc, R, X) \
587 do { \
588  _FP_FRAC_DECL_##wc(T); _FP_FRAC_DECL_##wc(S); \
589  _FP_W_TYPE q; \
590  switch (X##_c) \
591  { \
592  case FP_CLS_NAN: \
593  _FP_FRAC_COPY_##wc(R, X); \
594  R##_s = X##_s; \
595  R##_c = FP_CLS_NAN; \
596  break; \
597  case FP_CLS_INF: \
598  if (X##_s) \
599  { \
600  R##_s = _FP_NANSIGN_##fs; \
601  R##_c = FP_CLS_NAN; /* NAN */ \
602  _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \
603  FP_SET_EXCEPTION(FP_EX_INVALID); \
604  } \
605  else \
606  { \
607  R##_s = 0; \
608  R##_c = FP_CLS_INF; /* sqrt(+inf) = +inf */ \
609  } \
610  break; \
611  case FP_CLS_ZERO: \
612  R##_s = X##_s; \
613  R##_c = FP_CLS_ZERO; /* sqrt(+-0) = +-0 */ \
614  break; \
615  case FP_CLS_NORMAL: \
616  R##_s = 0; \
617  if (X##_s) \
618  { \
619  R##_c = FP_CLS_NAN; /* sNAN */ \
620  R##_s = _FP_NANSIGN_##fs; \
621  _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \
622  FP_SET_EXCEPTION(FP_EX_INVALID); \
623  break; \
624  } \
625  R##_c = FP_CLS_NORMAL; \
626  if (X##_e & 1) \
627  _FP_FRAC_SLL_##wc(X, 1); \
628  R##_e = X##_e >> 1; \
629  _FP_FRAC_SET_##wc(S, _FP_ZEROFRAC_##wc); \
630  _FP_FRAC_SET_##wc(R, _FP_ZEROFRAC_##wc); \
631  q = _FP_OVERFLOW_##fs >> 1; \
632  _FP_SQRT_MEAT_##wc(R, S, T, X, q); \
633  } \
634  } while (0)
635 
636 /*
637  * Convert from FP to integer
638  */
639 
640 /* RSIGNED can have following values:
641  * 0: the number is required to be 0..(2^rsize)-1, if not, NV is set plus
642  * the result is either 0 or (2^rsize)-1 depending on the sign in such case.
643  * 1: the number is required to be -(2^(rsize-1))..(2^(rsize-1))-1, if not, NV is
644  * set plus the result is either -(2^(rsize-1)) or (2^(rsize-1))-1 depending
645  * on the sign in such case.
646  * 2: the number is required to be -(2^(rsize-1))..(2^(rsize-1))-1, if not, NV is
647  * set plus the result is truncated to fit into destination.
648  * -1: the number is required to be -(2^(rsize-1))..(2^rsize)-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  */
652 #define _FP_TO_INT(fs, wc, r, X, rsize, rsigned) \
653  do { \
654  switch (X##_c) \
655  { \
656  case FP_CLS_NORMAL: \
657  if (X##_e < 0) \
658  { \
659  FP_SET_EXCEPTION(FP_EX_INEXACT); \
660  case FP_CLS_ZERO: \
661  r = 0; \
662  } \
663  else if (X##_e >= rsize - (rsigned > 0 || X##_s) \
664  || (!rsigned && X##_s)) \
665  { /* overflow */ \
666  case FP_CLS_NAN: \
667  case FP_CLS_INF: \
668  if (rsigned == 2) \
669  { \
670  if (X##_c != FP_CLS_NORMAL \
671  || X##_e >= rsize - 1 + _FP_WFRACBITS_##fs) \
672  r = 0; \
673  else \
674  { \
675  _FP_FRAC_SLL_##wc(X, (X##_e - _FP_WFRACBITS_##fs + 1)); \
676  _FP_FRAC_ASSEMBLE_##wc(r, X, rsize); \
677  } \
678  } \
679  else if (rsigned) \
680  { \
681  r = 1; \
682  r <<= rsize - 1; \
683  r -= 1 - X##_s; \
684  } \
685  else \
686  { \
687  r = 0; \
688  if (X##_s) \
689  r = ~r; \
690  } \
691  FP_SET_EXCEPTION(FP_EX_INVALID); \
692  } \
693  else \
694  { \
695  if (_FP_W_TYPE_SIZE*wc < rsize) \
696  { \
697  _FP_FRAC_ASSEMBLE_##wc(r, X, rsize); \
698  r <<= X##_e - _FP_WFRACBITS_##fs; \
699  } \
700  else \
701  { \
702  if (X##_e >= _FP_WFRACBITS_##fs) \
703  _FP_FRAC_SLL_##wc(X, (X##_e - _FP_WFRACBITS_##fs + 1)); \
704  else if (X##_e < _FP_WFRACBITS_##fs - 1) \
705  { \
706  _FP_FRAC_SRS_##wc(X, (_FP_WFRACBITS_##fs - X##_e - 2), \
707  _FP_WFRACBITS_##fs); \
708  if (_FP_FRAC_LOW_##wc(X) & 1) \
709  FP_SET_EXCEPTION(FP_EX_INEXACT); \
710  _FP_FRAC_SRL_##wc(X, 1); \
711  } \
712  _FP_FRAC_ASSEMBLE_##wc(r, X, rsize); \
713  } \
714  if (rsigned && X##_s) \
715  r = -r; \
716  } \
717  break; \
718  } \
719  } while (0)
720 
721 #define _FP_TO_INT_ROUND(fs, wc, r, X, rsize, rsigned) \
722  do { \
723  r = 0; \
724  switch (X##_c) \
725  { \
726  case FP_CLS_NORMAL: \
727  if (X##_e >= _FP_FRACBITS_##fs - 1) \
728  { \
729  if (X##_e < rsize - 1 + _FP_WFRACBITS_##fs) \
730  { \
731  if (X##_e >= _FP_WFRACBITS_##fs - 1) \
732  { \
733  _FP_FRAC_ASSEMBLE_##wc(r, X, rsize); \
734  r <<= X##_e - _FP_WFRACBITS_##fs + 1; \
735  } \
736  else \
737  { \
738  _FP_FRAC_SRL_##wc(X, _FP_WORKBITS - X##_e \
739  + _FP_FRACBITS_##fs - 1); \
740  _FP_FRAC_ASSEMBLE_##wc(r, X, rsize); \
741  } \
742  } \
743  } \
744  else \
745  { \
746  if (X##_e <= -_FP_WORKBITS - 1) \
747  _FP_FRAC_SET_##wc(X, _FP_MINFRAC_##wc); \
748  else \
749  _FP_FRAC_SRS_##wc(X, _FP_FRACBITS_##fs - 1 - X##_e, \
750  _FP_WFRACBITS_##fs); \
751  _FP_ROUND(wc, X); \
752  _FP_FRAC_SRL_##wc(X, _FP_WORKBITS); \
753  _FP_FRAC_ASSEMBLE_##wc(r, X, rsize); \
754  } \
755  if (rsigned && X##_s) \
756  r = -r; \
757  if (X##_e >= rsize - (rsigned > 0 || X##_s) \
758  || (!rsigned && X##_s)) \
759  { /* overflow */ \
760  case FP_CLS_NAN: \
761  case FP_CLS_INF: \
762  if (!rsigned) \
763  { \
764  r = 0; \
765  if (X##_s) \
766  r = ~r; \
767  } \
768  else if (rsigned != 2) \
769  { \
770  r = 1; \
771  r <<= rsize - 1; \
772  r -= 1 - X##_s; \
773  } \
774  FP_SET_EXCEPTION(FP_EX_INVALID); \
775  } \
776  break; \
777  case FP_CLS_ZERO: \
778  break; \
779  } \
780  } while (0)
781 
782 #define _FP_FROM_INT(fs, wc, X, r, rsize, rtype) \
783  do { \
784  if (r) \
785  { \
786  unsigned rtype ur_; \
787  X##_c = FP_CLS_NORMAL; \
788  \
789  if ((X##_s = (r < 0))) \
790  ur_ = (unsigned rtype) -r; \
791  else \
792  ur_ = (unsigned rtype) r; \
793  if (rsize <= _FP_W_TYPE_SIZE) \
794  __FP_CLZ(X##_e, ur_); \
795  else \
796  __FP_CLZ_2(X##_e, (_FP_W_TYPE)(ur_ >> _FP_W_TYPE_SIZE), \
797  (_FP_W_TYPE)ur_); \
798  if (rsize < _FP_W_TYPE_SIZE) \
799  X##_e -= (_FP_W_TYPE_SIZE - rsize); \
800  X##_e = rsize - X##_e - 1; \
801  \
802  if (_FP_FRACBITS_##fs < rsize && _FP_WFRACBITS_##fs <= X##_e) \
803  __FP_FRAC_SRS_1(ur_, (X##_e - _FP_WFRACBITS_##fs + 1), rsize);\
804  _FP_FRAC_DISASSEMBLE_##wc(X, ur_, rsize); \
805  if ((_FP_WFRACBITS_##fs - X##_e - 1) > 0) \
806  _FP_FRAC_SLL_##wc(X, (_FP_WFRACBITS_##fs - X##_e - 1)); \
807  } \
808  else \
809  { \
810  X##_c = FP_CLS_ZERO, X##_s = 0; \
811  } \
812  } while (0)
813 
814 
815 #define FP_CONV(dfs,sfs,dwc,swc,D,S) \
816  do { \
817  _FP_FRAC_CONV_##dwc##_##swc(dfs, sfs, D, S); \
818  D##_e = S##_e; \
819  D##_c = S##_c; \
820  D##_s = S##_s; \
821  } while (0)
822 
823 /*
824  * Helper primitives.
825  */
826 
827 /* Count leading zeros in a word. */
828 
829 #ifndef __FP_CLZ
830 #if _FP_W_TYPE_SIZE < 64
831 /* this is just to shut the compiler up about shifts > word length -- PMM 02/1998 */
832 #define __FP_CLZ(r, x) \
833  do { \
834  _FP_W_TYPE _t = (x); \
835  r = _FP_W_TYPE_SIZE - 1; \
836  if (_t > 0xffff) r -= 16; \
837  if (_t > 0xffff) _t >>= 16; \
838  if (_t > 0xff) r -= 8; \
839  if (_t > 0xff) _t >>= 8; \
840  if (_t & 0xf0) r -= 4; \
841  if (_t & 0xf0) _t >>= 4; \
842  if (_t & 0xc) r -= 2; \
843  if (_t & 0xc) _t >>= 2; \
844  if (_t & 0x2) r -= 1; \
845  } while (0)
846 #else /* not _FP_W_TYPE_SIZE < 64 */
847 #define __FP_CLZ(r, x) \
848  do { \
849  _FP_W_TYPE _t = (x); \
850  r = _FP_W_TYPE_SIZE - 1; \
851  if (_t > 0xffffffff) r -= 32; \
852  if (_t > 0xffffffff) _t >>= 32; \
853  if (_t > 0xffff) r -= 16; \
854  if (_t > 0xffff) _t >>= 16; \
855  if (_t > 0xff) r -= 8; \
856  if (_t > 0xff) _t >>= 8; \
857  if (_t & 0xf0) r -= 4; \
858  if (_t & 0xf0) _t >>= 4; \
859  if (_t & 0xc) r -= 2; \
860  if (_t & 0xc) _t >>= 2; \
861  if (_t & 0x2) r -= 1; \
862  } while (0)
863 #endif /* not _FP_W_TYPE_SIZE < 64 */
864 #endif /* ndef __FP_CLZ */
865 
866 #define _FP_DIV_HELP_imm(q, r, n, d) \
867  do { \
868  q = n / d, r = n % d; \
869  } while (0)
870 
871 #endif /* __MATH_EMU_OP_COMMON_H__ */