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