^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /* Machine-dependent software floating-point definitions. PPC version.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) Copyright (C) 1997 Free Software Foundation, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) This file is part of the GNU C Library.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) The GNU C Library is free software; you can redistribute it and/or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) modify it under the terms of the GNU Library General Public License as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) published by the Free Software Foundation; either version 2 of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) License, or (at your option) any later version.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) The GNU C Library is distributed in the hope that it will be useful,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) but WITHOUT ANY WARRANTY; without even the implied warranty of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) Library General Public License for more details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) You should have received a copy of the GNU Library General Public
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) License along with the GNU C Library; see the file COPYING.LIB. If
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) not, write to the Free Software Foundation, Inc.,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) Actually, this is a PPC (32bit) version, written based on the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) i386, sparc, and sparc64 versions, by me,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) Peter Maydell (pmaydell@chiark.greenend.org.uk).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) Comments are by and large also mine, although they may be inaccurate.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) In picking out asm fragments I've gone with the lowest common
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) denominator, which also happens to be the hardware I have :->
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) That is, a SPARC without hardware multiply and divide.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) /* basic word size definitions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define _FP_W_TYPE_SIZE 32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define _FP_W_TYPE unsigned int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define _FP_WS_TYPE signed int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define _FP_I_TYPE int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define __ll_B ((UWtype) 1 << (W_TYPE_SIZE / 2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define __ll_lowpart(t) ((UWtype) (t) & (__ll_B - 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define __ll_highpart(t) ((UWtype) (t) >> (W_TYPE_SIZE / 2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) /* You can optionally code some things like addition in asm. For
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) * example, i386 defines __FP_FRAC_ADD_2 as asm. If you don't
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) * then you get a fragment of C code [if you change an #ifdef 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) * in op-2.h] or a call to add_ssaaaa (see below).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) * Good places to look for asm fragments to use are gcc and glibc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) * gcc's longlong.h is useful.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) /* We need to know how to multiply and divide. If the host word size
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) * is >= 2*fracbits you can use FP_MUL_MEAT_n_imm(t,R,X,Y) which
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) * codes the multiply with whatever gcc does to 'a * b'.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) * _FP_MUL_MEAT_n_wide(t,R,X,Y,f) is used when you have an asm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) * function that can multiply two 1W values and get a 2W result.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) * Otherwise you're stuck with _FP_MUL_MEAT_n_hard(t,R,X,Y) which
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) * does bitshifting to avoid overflow.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) * For division there is FP_DIV_MEAT_n_imm(t,R,X,Y,f) for word size
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) * >= 2*fracbits, where f is either _FP_DIV_HELP_imm or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) * _FP_DIV_HELP_ldiv (see op-1.h).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) * _FP_DIV_MEAT_udiv() is if you have asm to do 2W/1W => (1W, 1W).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) * [GCC and glibc have longlong.h which has the asm macro udiv_qrnnd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) * to do this.]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) * In general, 'n' is the number of words required to hold the type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) * and 't' is either S, D or Q for single/double/quad.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) * -- PMM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) /* Example: SPARC64:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) * #define _FP_MUL_MEAT_S(R,X,Y) _FP_MUL_MEAT_1_imm(S,R,X,Y)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) * #define _FP_MUL_MEAT_D(R,X,Y) _FP_MUL_MEAT_1_wide(D,R,X,Y,umul_ppmm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) * #define _FP_MUL_MEAT_Q(R,X,Y) _FP_MUL_MEAT_2_wide(Q,R,X,Y,umul_ppmm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) * #define _FP_DIV_MEAT_S(R,X,Y) _FP_DIV_MEAT_1_imm(S,R,X,Y,_FP_DIV_HELP_imm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) * #define _FP_DIV_MEAT_D(R,X,Y) _FP_DIV_MEAT_1_udiv(D,R,X,Y)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) * #define _FP_DIV_MEAT_Q(R,X,Y) _FP_DIV_MEAT_2_udiv_64(Q,R,X,Y)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) * Example: i386:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) * #define _FP_MUL_MEAT_S(R,X,Y) _FP_MUL_MEAT_1_wide(S,R,X,Y,_i386_mul_32_64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) * #define _FP_MUL_MEAT_D(R,X,Y) _FP_MUL_MEAT_2_wide(D,R,X,Y,_i386_mul_32_64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) * #define _FP_DIV_MEAT_S(R,X,Y) _FP_DIV_MEAT_1_udiv(S,R,X,Y,_i386_div_64_32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) * #define _FP_DIV_MEAT_D(R,X,Y) _FP_DIV_MEAT_2_udiv_64(D,R,X,Y)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) #define _FP_MUL_MEAT_S(R,X,Y) _FP_MUL_MEAT_1_wide(_FP_WFRACBITS_S,R,X,Y,umul_ppmm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) #define _FP_MUL_MEAT_D(R,X,Y) _FP_MUL_MEAT_2_wide(_FP_WFRACBITS_D,R,X,Y,umul_ppmm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) #define _FP_DIV_MEAT_S(R,X,Y) _FP_DIV_MEAT_1_udiv_norm(S,R,X,Y)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) #define _FP_DIV_MEAT_D(R,X,Y) _FP_DIV_MEAT_2_udiv(D,R,X,Y)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) /* These macros define what NaN looks like. They're supposed to expand to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) * a comma-separated set of 32bit unsigned ints that encode NaN.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) #define _FP_NANFRAC_S ((_FP_QNANBIT_S << 1) - 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) #define _FP_NANFRAC_D ((_FP_QNANBIT_D << 1) - 1), -1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) #define _FP_NANFRAC_Q ((_FP_QNANBIT_Q << 1) - 1), -1, -1, -1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) #define _FP_NANSIGN_S 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) #define _FP_NANSIGN_D 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) #define _FP_NANSIGN_Q 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) #define _FP_KEEPNANFRACP 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) #ifdef FP_EX_BOOKE_E500_SPE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) #define FP_EX_INEXACT (1 << 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) #define FP_EX_INVALID (1 << 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) #define FP_EX_DIVZERO (1 << 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) #define FP_EX_UNDERFLOW (1 << 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) #define FP_EX_OVERFLOW (1 << 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) #define FP_INHIBIT_RESULTS 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) #define __FPU_FPSCR (current->thread.spefscr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) #define __FPU_ENABLED_EXC \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) ({ \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) (__FPU_FPSCR >> 2) & 0x1f; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) })
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) /* Exception flags. We use the bit positions of the appropriate bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) in the FPSCR, which also correspond to the FE_* bits. This makes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) everything easier ;-). */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) #define FP_EX_INVALID (1 << (31 - 2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) #define FP_EX_INVALID_SNAN EFLAG_VXSNAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) #define FP_EX_INVALID_ISI EFLAG_VXISI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) #define FP_EX_INVALID_IDI EFLAG_VXIDI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) #define FP_EX_INVALID_ZDZ EFLAG_VXZDZ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) #define FP_EX_INVALID_IMZ EFLAG_VXIMZ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) #define FP_EX_OVERFLOW (1 << (31 - 3))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) #define FP_EX_UNDERFLOW (1 << (31 - 4))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) #define FP_EX_DIVZERO (1 << (31 - 5))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) #define FP_EX_INEXACT (1 << (31 - 6))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) #define __FPU_FPSCR (current->thread.fp_state.fpscr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) /* We only actually write to the destination register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) * if exceptions signalled (if any) will not trap.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) #define __FPU_ENABLED_EXC \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) ({ \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) (__FPU_FPSCR >> 3) & 0x1f; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) })
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) * If one NaN is signaling and the other is not,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) * we choose that one, otherwise we choose X.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) #define _FP_CHOOSENAN(fs, wc, R, X, Y, OP) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) do { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) if ((_FP_FRAC_HIGH_RAW_##fs(Y) & _FP_QNANBIT_##fs) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) && !(_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs)) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) R##_s = X##_s; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) _FP_FRAC_COPY_##wc(R,X); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) else \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) R##_s = Y##_s; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) _FP_FRAC_COPY_##wc(R,Y); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) R##_c = FP_CLS_NAN; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) #define __FPU_TRAP_P(bits) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) ((__FPU_ENABLED_EXC & (bits)) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) #define __FP_PACK_S(val,X) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) ({ int __exc = _FP_PACK_CANONICAL(S,1,X); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) if(!__exc || !__FPU_TRAP_P(__exc)) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) _FP_PACK_RAW_1_P(S,val,X); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) __exc; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) })
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) #define __FP_PACK_D(val,X) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) do { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) _FP_PACK_CANONICAL(D, 2, X); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) if (!FP_CUR_EXCEPTIONS || !__FPU_TRAP_P(FP_CUR_EXCEPTIONS)) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) _FP_PACK_RAW_2_P(D, val, X); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) #define __FP_PACK_DS(val,X) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) do { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) FP_DECL_S(__X); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) FP_CONV(S, D, 1, 2, __X, X); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) _FP_PACK_CANONICAL(S, 1, __X); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) if (!FP_CUR_EXCEPTIONS || !__FPU_TRAP_P(FP_CUR_EXCEPTIONS)) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) _FP_UNPACK_CANONICAL(S, 1, __X); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) FP_CONV(D, S, 2, 1, X, __X); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) _FP_PACK_CANONICAL(D, 2, X); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) if (!FP_CUR_EXCEPTIONS || !__FPU_TRAP_P(FP_CUR_EXCEPTIONS)) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) _FP_PACK_RAW_2_P(D, val, X); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) /* Obtain the current rounding mode. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) #define FP_ROUNDMODE \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) ({ \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) __FPU_FPSCR & 0x3; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) })
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) /* the asm fragments go here: all these are taken from glibc-2.0.5's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) * stdlib/longlong.h
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) #include <asm/byteorder.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) /* add_ssaaaa is used in op-2.h and should be equivalent to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) * #define add_ssaaaa(sh,sl,ah,al,bh,bl) (sh = ah+bh+ (( sl = al+bl) < al))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) * add_ssaaaa(high_sum, low_sum, high_addend_1, low_addend_1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) * high_addend_2, low_addend_2) adds two UWtype integers, composed by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) * HIGH_ADDEND_1 and LOW_ADDEND_1, and HIGH_ADDEND_2 and LOW_ADDEND_2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) * respectively. The result is placed in HIGH_SUM and LOW_SUM. Overflow
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) * (i.e. carry out) is not stored anywhere, and is lost.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) #define add_ssaaaa(sh, sl, ah, al, bh, bl) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) do { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) if (__builtin_constant_p (bh) && (bh) == 0) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) __asm__ ("add%I4c %1,%3,%4\n\taddze %0,%2" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) : "=r" (sh), "=&r" (sl) : "r" (ah), "%r" (al), "rI" (bl));\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) else if (__builtin_constant_p (bh) && (bh) == ~(USItype) 0) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) __asm__ ("add%I4c %1,%3,%4\n\taddme %0,%2" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) : "=r" (sh), "=&r" (sl) : "r" (ah), "%r" (al), "rI" (bl));\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) else \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) __asm__ ("add%I5c %1,%4,%5\n\tadde %0,%2,%3" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) : "=r" (sh), "=&r" (sl) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) : "%r" (ah), "r" (bh), "%r" (al), "rI" (bl)); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) /* sub_ddmmss is used in op-2.h and udivmodti4.c and should be equivalent to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) * #define sub_ddmmss(sh, sl, ah, al, bh, bl) (sh = ah-bh - ((sl = al-bl) > al))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) * sub_ddmmss(high_difference, low_difference, high_minuend, low_minuend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) * high_subtrahend, low_subtrahend) subtracts two two-word UWtype integers,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) * composed by HIGH_MINUEND_1 and LOW_MINUEND_1, and HIGH_SUBTRAHEND_2 and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) * LOW_SUBTRAHEND_2 respectively. The result is placed in HIGH_DIFFERENCE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) * and LOW_DIFFERENCE. Overflow (i.e. carry out) is not stored anywhere,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) * and is lost.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) #define sub_ddmmss(sh, sl, ah, al, bh, bl) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) do { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) if (__builtin_constant_p (ah) && (ah) == 0) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) __asm__ ("subf%I3c %1,%4,%3\n\tsubfze %0,%2" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) : "=r" (sh), "=&r" (sl) : "r" (bh), "rI" (al), "r" (bl));\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) else if (__builtin_constant_p (ah) && (ah) == ~(USItype) 0) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) __asm__ ("subf%I3c %1,%4,%3\n\tsubfme %0,%2" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) : "=r" (sh), "=&r" (sl) : "r" (bh), "rI" (al), "r" (bl));\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) else if (__builtin_constant_p (bh) && (bh) == 0) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) __asm__ ("subf%I3c %1,%4,%3\n\taddme %0,%2" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) : "=r" (sh), "=&r" (sl) : "r" (ah), "rI" (al), "r" (bl));\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) else if (__builtin_constant_p (bh) && (bh) == ~(USItype) 0) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) __asm__ ("subf%I3c %1,%4,%3\n\taddze %0,%2" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) : "=r" (sh), "=&r" (sl) : "r" (ah), "rI" (al), "r" (bl));\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) else \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) __asm__ ("subf%I4c %1,%5,%4\n\tsubfe %0,%3,%2" \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) : "=r" (sh), "=&r" (sl) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) : "r" (ah), "r" (bh), "rI" (al), "r" (bl)); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) /* asm fragments for mul and div */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) /* umul_ppmm(high_prod, low_prod, multipler, multiplicand) multiplies two
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) * UWtype integers MULTIPLER and MULTIPLICAND, and generates a two UWtype
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) * word product in HIGH_PROD and LOW_PROD.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) #define umul_ppmm(ph, pl, m0, m1) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) do { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) USItype __m0 = (m0), __m1 = (m1); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) __asm__ ("mulhwu %0,%1,%2" : "=r" (ph) : "%r" (m0), "r" (m1)); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) (pl) = __m0 * __m1; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) /* udiv_qrnnd(quotient, remainder, high_numerator, low_numerator,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) * denominator) divides a UDWtype, composed by the UWtype integers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) * HIGH_NUMERATOR and LOW_NUMERATOR, by DENOMINATOR and places the quotient
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) * in QUOTIENT and the remainder in REMAINDER. HIGH_NUMERATOR must be less
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) * than DENOMINATOR for correct operation. If, in addition, the most
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) * significant bit of DENOMINATOR must be 1, then the pre-processor symbol
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) * UDIV_NEEDS_NORMALIZATION is defined to 1.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) #define udiv_qrnnd(q, r, n1, n0, d) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) do { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) UWtype __d1, __d0, __q1, __q0; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) UWtype __r1, __r0, __m; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) __d1 = __ll_highpart (d); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) __d0 = __ll_lowpart (d); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) __r1 = (n1) % __d1; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) __q1 = (n1) / __d1; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) __m = (UWtype) __q1 * __d0; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) __r1 = __r1 * __ll_B | __ll_highpart (n0); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) if (__r1 < __m) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) __q1--, __r1 += (d); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) if (__r1 >= (d)) /* i.e. we didn't get carry when adding to __r1 */\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) if (__r1 < __m) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) __q1--, __r1 += (d); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) __r1 -= __m; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) __r0 = __r1 % __d1; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) __q0 = __r1 / __d1; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) __m = (UWtype) __q0 * __d0; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) __r0 = __r0 * __ll_B | __ll_lowpart (n0); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) if (__r0 < __m) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) __q0--, __r0 += (d); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) if (__r0 >= (d)) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) if (__r0 < __m) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) __q0--, __r0 += (d); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) __r0 -= __m; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) (q) = (UWtype) __q1 * __ll_B | __q0; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) (r) = __r0; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) #define UDIV_NEEDS_NORMALIZATION 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) #define abort() \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) return 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) #ifdef __BIG_ENDIAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) #define __BYTE_ORDER __BIG_ENDIAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) #define __BYTE_ORDER __LITTLE_ENDIAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) /* Exception flags. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) #define EFLAG_INVALID (1 << (31 - 2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) #define EFLAG_OVERFLOW (1 << (31 - 3))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) #define EFLAG_UNDERFLOW (1 << (31 - 4))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) #define EFLAG_DIVZERO (1 << (31 - 5))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) #define EFLAG_INEXACT (1 << (31 - 6))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) #define EFLAG_VXSNAN (1 << (31 - 7))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) #define EFLAG_VXISI (1 << (31 - 8))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) #define EFLAG_VXIDI (1 << (31 - 9))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) #define EFLAG_VXZDZ (1 << (31 - 10))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) #define EFLAG_VXIMZ (1 << (31 - 11))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) #define EFLAG_VXVC (1 << (31 - 12))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) #define EFLAG_VXSOFT (1 << (31 - 21))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) #define EFLAG_VXSQRT (1 << (31 - 22))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) #define EFLAG_VXCVI (1 << (31 - 23))