1 /* Machine-dependent software floating-point definitions. 2 Sparc64 userland (_Q_* and _Qp_*) version. 3 Copyright (C) 1997-2017 Free Software Foundation, Inc. 4 This file is part of the GNU C Library. 5 Contributed by Richard Henderson (rth@cygnus.com), 6 Jakub Jelinek (jj@ultra.linux.cz) and 7 David S. Miller (davem@redhat.com). 8 9 The GNU C Library is free software; you can redistribute it and/or 10 modify it under the terms of the GNU Lesser General Public 11 License as published by the Free Software Foundation; either 12 version 2.1 of the 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 Lesser General Public License for more details. 18 19 You should have received a copy of the GNU Lesser General Public 20 License along with the GNU C Library; if not, see 21 <http://www.gnu.org/licenses/>. */ 22 23 #include <fpu_control.h> 24 #include <fenv.h> 25 #include <stdlib.h> 26 27 #define _FP_W_TYPE_SIZE 64 28 #define _FP_W_TYPE unsigned long 29 #define _FP_WS_TYPE signed long 30 #define _FP_I_TYPE long 31 32 /* Helper macros for _FP_MUL_MEAT_2_120_240_double. */ 33 #define _FP_MUL_MEAT_SET_FE_TZ \ 34 do { \ 35 static fpu_control_t _fetz = _FPU_RC_DOWN; \ 36 _FPU_SETCW(_fetz); \ 37 } while (0) 38 #ifndef _FP_MUL_MEAT_RESET_FE 39 #define _FP_MUL_MEAT_RESET_FE _FPU_SETCW(_fcw) 40 #endif 41 42 #define _FP_MUL_MEAT_S(R,X,Y) \ 43 _FP_MUL_MEAT_1_imm(_FP_WFRACBITS_S,R,X,Y) 44 #define _FP_MUL_MEAT_D(R,X,Y) \ 45 _FP_MUL_MEAT_1_wide(_FP_WFRACBITS_D,R,X,Y,umul_ppmm) 46 #define _FP_MUL_MEAT_Q(R,X,Y) \ 47 _FP_MUL_MEAT_2_120_240_double(_FP_WFRACBITS_Q,R,X,Y, \ 48 _FP_MUL_MEAT_SET_FE_TZ, \ 49 _FP_MUL_MEAT_RESET_FE) 50 51 #define _FP_DIV_MEAT_S(R,X,Y) _FP_DIV_MEAT_1_imm(S,R,X,Y,_FP_DIV_HELP_imm) 52 #define _FP_DIV_MEAT_D(R,X,Y) _FP_DIV_MEAT_1_udiv_norm(D,R,X,Y) 53 #define _FP_DIV_MEAT_Q(R,X,Y) _FP_DIV_MEAT_2_udiv(Q,R,X,Y) 54 55 #define _FP_NANFRAC_S ((_FP_QNANBIT_S << 1) - 1) 56 #define _FP_NANFRAC_D ((_FP_QNANBIT_D << 1) - 1) 57 #define _FP_NANFRAC_Q ((_FP_QNANBIT_Q << 1) - 1), -1 58 #define _FP_NANSIGN_S 0 59 #define _FP_NANSIGN_D 0 60 #define _FP_NANSIGN_Q 0 61 62 #define _FP_KEEPNANFRACP 1 63 #define _FP_QNANNEGATEDP 0 64 65 /* If one NaN is signaling and the other is not, 66 * we choose that one, otherwise we choose Y. 67 */ 68 #define _FP_CHOOSENAN(fs, wc, R, X, Y, OP) \ 69 do { \ 70 if ((_FP_FRAC_HIGH_RAW_##fs(Y) & _FP_QNANBIT_##fs) \ 71 && !(_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs)) \ 72 { \ 73 R##_s = X##_s; \ 74 _FP_FRAC_COPY_##wc(R,X); \ 75 } \ 76 else \ 77 { \ 78 R##_s = Y##_s; \ 79 _FP_FRAC_COPY_##wc(R,Y); \ 80 } \ 81 R##_c = FP_CLS_NAN; \ 82 } while (0) 83 84 /* Obtain the current rounding mode. */ 85 #ifndef FP_ROUNDMODE 86 #define FP_ROUNDMODE ((_fcw >> 30) & 0x3) 87 #endif 88 89 /* Exception flags. */ 90 #define FP_EX_INVALID (1 << 4) 91 #define FP_EX_OVERFLOW (1 << 3) 92 #define FP_EX_UNDERFLOW (1 << 2) 93 #define FP_EX_DIVZERO (1 << 1) 94 #define FP_EX_INEXACT (1 << 0) 95 96 #define _FP_TININESS_AFTER_ROUNDING 0 97 98 #define _FP_DECL_EX \ 99 fpu_control_t _fcw __attribute__ ((unused)) = (FP_RND_NEAREST << 30) 100 101 #define FP_INIT_ROUNDMODE \ 102 do { \ 103 _FPU_GETCW(_fcw); \ 104 } while (0) 105 106 #define FP_TRAPPING_EXCEPTIONS ((_fcw >> 23) & 0x1f) 107 #define FP_INHIBIT_RESULTS ((_fcw >> 23) & _fex) 108 109 /* Simulate exceptions using double arithmetics. */ 110 extern void __Qp_handle_exceptions(int exc); 111 112 #define FP_HANDLE_EXCEPTIONS \ 113 do { \ 114 if (!_fex) \ 115 { \ 116 /* This is the common case, so we do it inline. \ 117 * We need to clear cexc bits if any. \ 118 */ \ 119 __asm__ __volatile__("fzero %%f62\n\t" \ 120 "faddd %%f62, %%f62, %%f62" \ 121 : : : "f62"); \ 122 } \ 123 else \ 124 { \ 125 __Qp_handle_exceptions (_fex); \ 126 } \ 127 } while (0) 128 129 #define QP_HANDLE_EXCEPTIONS(_a) \ 130 do { \ 131 if ((_fcw >> 23) & _fex) \ 132 { \ 133 _a; \ 134 } \ 135 else \ 136 { \ 137 _fcw = (_fcw & ~0x1fL) | (_fex << 5) | _fex; \ 138 _FPU_SETCW(_fcw); \ 139 } \ 140 } while (0) 141 142 #define QP_NO_EXCEPTIONS \ 143 __asm ("fzero %%f62\n\t" \ 144 "faddd %%f62, %%f62, %%f62" : : : "f62") 145 146 #define QP_CLOBBER "memory", "f52", "f54", "f56", "f58", "f60", "f62" 147 #define QP_CLOBBER_CC QP_CLOBBER , "cc" 148