^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * arch/powerpc/math-emu/math_efp.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2006-2008, 2010 Freescale Semiconductor, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Author: Ebony Zhu, <ebony.zhu@freescale.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Yu Liu, <yu.liu@freescale.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Derived from arch/alpha/math-emu/math.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * arch/powerpc/math-emu/math.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * Description:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * This file is the exception handler to make E500 SPE instructions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * fully comply with IEEE-754 floating point standard.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/prctl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <asm/reg.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #define FP_EX_BOOKE_E500_SPE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <asm/sfp-machine.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <math-emu/soft-fp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <math-emu/single.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <math-emu/double.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define EFAPU 0x4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define VCT 0x4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define SPFP 0x6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define DPFP 0x7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define EFSADD 0x2c0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define EFSSUB 0x2c1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define EFSABS 0x2c4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define EFSNABS 0x2c5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define EFSNEG 0x2c6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define EFSMUL 0x2c8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define EFSDIV 0x2c9
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define EFSCMPGT 0x2cc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define EFSCMPLT 0x2cd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define EFSCMPEQ 0x2ce
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define EFSCFD 0x2cf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define EFSCFSI 0x2d1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define EFSCTUI 0x2d4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define EFSCTSI 0x2d5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #define EFSCTUF 0x2d6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define EFSCTSF 0x2d7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define EFSCTUIZ 0x2d8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #define EFSCTSIZ 0x2da
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define EVFSADD 0x280
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #define EVFSSUB 0x281
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define EVFSABS 0x284
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define EVFSNABS 0x285
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define EVFSNEG 0x286
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #define EVFSMUL 0x288
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #define EVFSDIV 0x289
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #define EVFSCMPGT 0x28c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #define EVFSCMPLT 0x28d
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #define EVFSCMPEQ 0x28e
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #define EVFSCTUI 0x294
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #define EVFSCTSI 0x295
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #define EVFSCTUF 0x296
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) #define EVFSCTSF 0x297
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #define EVFSCTUIZ 0x298
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #define EVFSCTSIZ 0x29a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) #define EFDADD 0x2e0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) #define EFDSUB 0x2e1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) #define EFDABS 0x2e4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #define EFDNABS 0x2e5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #define EFDNEG 0x2e6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) #define EFDMUL 0x2e8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) #define EFDDIV 0x2e9
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) #define EFDCTUIDZ 0x2ea
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) #define EFDCTSIDZ 0x2eb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) #define EFDCMPGT 0x2ec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) #define EFDCMPLT 0x2ed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) #define EFDCMPEQ 0x2ee
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) #define EFDCFS 0x2ef
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) #define EFDCTUI 0x2f4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) #define EFDCTSI 0x2f5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) #define EFDCTUF 0x2f6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) #define EFDCTSF 0x2f7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) #define EFDCTUIZ 0x2f8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) #define EFDCTSIZ 0x2fa
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) #define AB 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) #define XA 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) #define XB 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) #define XCR 5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) #define NOTYPE 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) #define SIGN_BIT_S (1UL << 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) #define SIGN_BIT_D (1ULL << 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) #define FP_EX_MASK (FP_EX_INEXACT | FP_EX_INVALID | FP_EX_DIVZERO | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) FP_EX_UNDERFLOW | FP_EX_OVERFLOW)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) static int have_e500_cpu_a005_erratum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) union dw_union {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) u64 dp[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) u32 wp[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) static unsigned long insn_type(unsigned long speinsn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) unsigned long ret = NOTYPE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) switch (speinsn & 0x7ff) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) case EFSABS: ret = XA; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) case EFSADD: ret = AB; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) case EFSCFD: ret = XB; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) case EFSCMPEQ: ret = XCR; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) case EFSCMPGT: ret = XCR; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) case EFSCMPLT: ret = XCR; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) case EFSCTSF: ret = XB; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) case EFSCTSI: ret = XB; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) case EFSCTSIZ: ret = XB; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) case EFSCTUF: ret = XB; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) case EFSCTUI: ret = XB; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) case EFSCTUIZ: ret = XB; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) case EFSDIV: ret = AB; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) case EFSMUL: ret = AB; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) case EFSNABS: ret = XA; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) case EFSNEG: ret = XA; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) case EFSSUB: ret = AB; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) case EFSCFSI: ret = XB; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) case EVFSABS: ret = XA; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) case EVFSADD: ret = AB; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) case EVFSCMPEQ: ret = XCR; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) case EVFSCMPGT: ret = XCR; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) case EVFSCMPLT: ret = XCR; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) case EVFSCTSF: ret = XB; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) case EVFSCTSI: ret = XB; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) case EVFSCTSIZ: ret = XB; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) case EVFSCTUF: ret = XB; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) case EVFSCTUI: ret = XB; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) case EVFSCTUIZ: ret = XB; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) case EVFSDIV: ret = AB; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) case EVFSMUL: ret = AB; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) case EVFSNABS: ret = XA; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) case EVFSNEG: ret = XA; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) case EVFSSUB: ret = AB; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) case EFDABS: ret = XA; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) case EFDADD: ret = AB; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) case EFDCFS: ret = XB; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) case EFDCMPEQ: ret = XCR; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) case EFDCMPGT: ret = XCR; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) case EFDCMPLT: ret = XCR; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) case EFDCTSF: ret = XB; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) case EFDCTSI: ret = XB; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) case EFDCTSIDZ: ret = XB; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) case EFDCTSIZ: ret = XB; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) case EFDCTUF: ret = XB; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) case EFDCTUI: ret = XB; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) case EFDCTUIDZ: ret = XB; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) case EFDCTUIZ: ret = XB; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) case EFDDIV: ret = AB; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) case EFDMUL: ret = AB; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) case EFDNABS: ret = XA; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) case EFDNEG: ret = XA; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) case EFDSUB: ret = AB; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) int do_spe_mathemu(struct pt_regs *regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) FP_DECL_EX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) int IR, cmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) unsigned long type, func, fc, fa, fb, src, speinsn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) union dw_union vc, va, vb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) if (get_user(speinsn, (unsigned int __user *) regs->nip))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) if ((speinsn >> 26) != EFAPU)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) return -EINVAL; /* not an spe instruction */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) type = insn_type(speinsn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) if (type == NOTYPE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) goto illegal;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) func = speinsn & 0x7ff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) fc = (speinsn >> 21) & 0x1f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) fa = (speinsn >> 16) & 0x1f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) fb = (speinsn >> 11) & 0x1f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) src = (speinsn >> 5) & 0x7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) vc.wp[0] = current->thread.evr[fc];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) vc.wp[1] = regs->gpr[fc];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) va.wp[0] = current->thread.evr[fa];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) va.wp[1] = regs->gpr[fa];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) vb.wp[0] = current->thread.evr[fb];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) vb.wp[1] = regs->gpr[fb];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) __FPU_FPSCR = mfspr(SPRN_SPEFSCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) pr_debug("speinsn:%08lx spefscr:%08lx\n", speinsn, __FPU_FPSCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) pr_debug("vc: %08x %08x\n", vc.wp[0], vc.wp[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) pr_debug("va: %08x %08x\n", va.wp[0], va.wp[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) pr_debug("vb: %08x %08x\n", vb.wp[0], vb.wp[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) switch (src) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) case SPFP: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) FP_DECL_S(SA); FP_DECL_S(SB); FP_DECL_S(SR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) switch (type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) case AB:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) case XCR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) FP_UNPACK_SP(SA, va.wp + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) case XB:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) FP_UNPACK_SP(SB, vb.wp + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) case XA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) FP_UNPACK_SP(SA, va.wp + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) pr_debug("SA: %ld %08lx %ld (%ld)\n", SA_s, SA_f, SA_e, SA_c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) pr_debug("SB: %ld %08lx %ld (%ld)\n", SB_s, SB_f, SB_e, SB_c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) switch (func) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) case EFSABS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) vc.wp[1] = va.wp[1] & ~SIGN_BIT_S;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) goto update_regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) case EFSNABS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) vc.wp[1] = va.wp[1] | SIGN_BIT_S;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) goto update_regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) case EFSNEG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) vc.wp[1] = va.wp[1] ^ SIGN_BIT_S;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) goto update_regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) case EFSADD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) FP_ADD_S(SR, SA, SB);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) goto pack_s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) case EFSSUB:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) FP_SUB_S(SR, SA, SB);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) goto pack_s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) case EFSMUL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) FP_MUL_S(SR, SA, SB);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) goto pack_s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) case EFSDIV:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) FP_DIV_S(SR, SA, SB);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) goto pack_s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) case EFSCMPEQ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) cmp = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) goto cmp_s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) case EFSCMPGT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) cmp = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) goto cmp_s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) case EFSCMPLT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) cmp = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) goto cmp_s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) case EFSCTSF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) case EFSCTUF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) if (SB_c == FP_CLS_NAN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) vc.wp[1] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) FP_SET_EXCEPTION(FP_EX_INVALID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) SB_e += (func == EFSCTSF ? 31 : 32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) FP_TO_INT_ROUND_S(vc.wp[1], SB, 32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) (func == EFSCTSF));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) goto update_regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) case EFSCFD: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) FP_DECL_D(DB);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) FP_CLEAR_EXCEPTIONS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) FP_UNPACK_DP(DB, vb.dp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) pr_debug("DB: %ld %08lx %08lx %ld (%ld)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) DB_s, DB_f1, DB_f0, DB_e, DB_c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) FP_CONV(S, D, 1, 2, SR, DB);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) goto pack_s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) case EFSCTSI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) case EFSCTUI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) if (SB_c == FP_CLS_NAN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) vc.wp[1] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) FP_SET_EXCEPTION(FP_EX_INVALID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) FP_TO_INT_ROUND_S(vc.wp[1], SB, 32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) ((func & 0x3) != 0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) goto update_regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) case EFSCTSIZ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) case EFSCTUIZ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) if (SB_c == FP_CLS_NAN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) vc.wp[1] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) FP_SET_EXCEPTION(FP_EX_INVALID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) FP_TO_INT_S(vc.wp[1], SB, 32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) ((func & 0x3) != 0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) goto update_regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) goto illegal;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) pack_s:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) pr_debug("SR: %ld %08lx %ld (%ld)\n", SR_s, SR_f, SR_e, SR_c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) FP_PACK_SP(vc.wp + 1, SR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) goto update_regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) cmp_s:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) FP_CMP_S(IR, SA, SB, 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) if (IR == 3 && (FP_ISSIGNAN_S(SA) || FP_ISSIGNAN_S(SB)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) FP_SET_EXCEPTION(FP_EX_INVALID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) if (IR == cmp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) IR = 0x4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) IR = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) goto update_ccr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) case DPFP: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) FP_DECL_D(DA); FP_DECL_D(DB); FP_DECL_D(DR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) switch (type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) case AB:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) case XCR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) FP_UNPACK_DP(DA, va.dp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) case XB:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) FP_UNPACK_DP(DB, vb.dp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) case XA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) FP_UNPACK_DP(DA, va.dp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) pr_debug("DA: %ld %08lx %08lx %ld (%ld)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) DA_s, DA_f1, DA_f0, DA_e, DA_c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) pr_debug("DB: %ld %08lx %08lx %ld (%ld)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) DB_s, DB_f1, DB_f0, DB_e, DB_c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) switch (func) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) case EFDABS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) vc.dp[0] = va.dp[0] & ~SIGN_BIT_D;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) goto update_regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) case EFDNABS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) vc.dp[0] = va.dp[0] | SIGN_BIT_D;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) goto update_regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) case EFDNEG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) vc.dp[0] = va.dp[0] ^ SIGN_BIT_D;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) goto update_regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) case EFDADD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) FP_ADD_D(DR, DA, DB);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) goto pack_d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) case EFDSUB:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) FP_SUB_D(DR, DA, DB);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) goto pack_d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) case EFDMUL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) FP_MUL_D(DR, DA, DB);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) goto pack_d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) case EFDDIV:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) FP_DIV_D(DR, DA, DB);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) goto pack_d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) case EFDCMPEQ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) cmp = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) goto cmp_d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) case EFDCMPGT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) cmp = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) goto cmp_d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) case EFDCMPLT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) cmp = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) goto cmp_d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) case EFDCTSF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) case EFDCTUF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) if (DB_c == FP_CLS_NAN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) vc.wp[1] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) FP_SET_EXCEPTION(FP_EX_INVALID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) DB_e += (func == EFDCTSF ? 31 : 32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) FP_TO_INT_ROUND_D(vc.wp[1], DB, 32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) (func == EFDCTSF));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) goto update_regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) case EFDCFS: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) FP_DECL_S(SB);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) FP_CLEAR_EXCEPTIONS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) FP_UNPACK_SP(SB, vb.wp + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) pr_debug("SB: %ld %08lx %ld (%ld)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) SB_s, SB_f, SB_e, SB_c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) FP_CONV(D, S, 2, 1, DR, SB);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) goto pack_d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) case EFDCTUIDZ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) case EFDCTSIDZ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) if (DB_c == FP_CLS_NAN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) vc.dp[0] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) FP_SET_EXCEPTION(FP_EX_INVALID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) FP_TO_INT_D(vc.dp[0], DB, 64,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) ((func & 0x1) == 0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) goto update_regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) case EFDCTUI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) case EFDCTSI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) if (DB_c == FP_CLS_NAN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) vc.wp[1] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) FP_SET_EXCEPTION(FP_EX_INVALID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) FP_TO_INT_ROUND_D(vc.wp[1], DB, 32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) ((func & 0x3) != 0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) goto update_regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) case EFDCTUIZ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) case EFDCTSIZ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) if (DB_c == FP_CLS_NAN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) vc.wp[1] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) FP_SET_EXCEPTION(FP_EX_INVALID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) FP_TO_INT_D(vc.wp[1], DB, 32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) ((func & 0x3) != 0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) goto update_regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) goto illegal;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) pack_d:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) pr_debug("DR: %ld %08lx %08lx %ld (%ld)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) DR_s, DR_f1, DR_f0, DR_e, DR_c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) FP_PACK_DP(vc.dp, DR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) goto update_regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) cmp_d:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) FP_CMP_D(IR, DA, DB, 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) if (IR == 3 && (FP_ISSIGNAN_D(DA) || FP_ISSIGNAN_D(DB)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) FP_SET_EXCEPTION(FP_EX_INVALID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) if (IR == cmp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) IR = 0x4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) IR = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) goto update_ccr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) case VCT: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) FP_DECL_S(SA0); FP_DECL_S(SB0); FP_DECL_S(SR0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) FP_DECL_S(SA1); FP_DECL_S(SB1); FP_DECL_S(SR1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) int IR0, IR1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) switch (type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) case AB:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) case XCR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) FP_UNPACK_SP(SA0, va.wp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) FP_UNPACK_SP(SA1, va.wp + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) case XB:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) FP_UNPACK_SP(SB0, vb.wp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) FP_UNPACK_SP(SB1, vb.wp + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) case XA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) FP_UNPACK_SP(SA0, va.wp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) FP_UNPACK_SP(SA1, va.wp + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) pr_debug("SA0: %ld %08lx %ld (%ld)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) SA0_s, SA0_f, SA0_e, SA0_c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) pr_debug("SA1: %ld %08lx %ld (%ld)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) SA1_s, SA1_f, SA1_e, SA1_c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) pr_debug("SB0: %ld %08lx %ld (%ld)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) SB0_s, SB0_f, SB0_e, SB0_c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) pr_debug("SB1: %ld %08lx %ld (%ld)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) SB1_s, SB1_f, SB1_e, SB1_c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) switch (func) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) case EVFSABS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) vc.wp[0] = va.wp[0] & ~SIGN_BIT_S;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) vc.wp[1] = va.wp[1] & ~SIGN_BIT_S;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) goto update_regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) case EVFSNABS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) vc.wp[0] = va.wp[0] | SIGN_BIT_S;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) vc.wp[1] = va.wp[1] | SIGN_BIT_S;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) goto update_regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) case EVFSNEG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) vc.wp[0] = va.wp[0] ^ SIGN_BIT_S;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) vc.wp[1] = va.wp[1] ^ SIGN_BIT_S;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) goto update_regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) case EVFSADD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) FP_ADD_S(SR0, SA0, SB0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) FP_ADD_S(SR1, SA1, SB1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) goto pack_vs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) case EVFSSUB:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) FP_SUB_S(SR0, SA0, SB0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) FP_SUB_S(SR1, SA1, SB1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) goto pack_vs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) case EVFSMUL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) FP_MUL_S(SR0, SA0, SB0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) FP_MUL_S(SR1, SA1, SB1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) goto pack_vs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) case EVFSDIV:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) FP_DIV_S(SR0, SA0, SB0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) FP_DIV_S(SR1, SA1, SB1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) goto pack_vs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) case EVFSCMPEQ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) cmp = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) goto cmp_vs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) case EVFSCMPGT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) cmp = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) goto cmp_vs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) case EVFSCMPLT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) cmp = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) goto cmp_vs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) case EVFSCTUF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) case EVFSCTSF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) if (SB0_c == FP_CLS_NAN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) vc.wp[0] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) FP_SET_EXCEPTION(FP_EX_INVALID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) SB0_e += (func == EVFSCTSF ? 31 : 32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) FP_TO_INT_ROUND_S(vc.wp[0], SB0, 32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) (func == EVFSCTSF));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) if (SB1_c == FP_CLS_NAN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) vc.wp[1] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) FP_SET_EXCEPTION(FP_EX_INVALID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) SB1_e += (func == EVFSCTSF ? 31 : 32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) FP_TO_INT_ROUND_S(vc.wp[1], SB1, 32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) (func == EVFSCTSF));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) goto update_regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) case EVFSCTUI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) case EVFSCTSI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) if (SB0_c == FP_CLS_NAN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) vc.wp[0] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) FP_SET_EXCEPTION(FP_EX_INVALID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) FP_TO_INT_ROUND_S(vc.wp[0], SB0, 32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) ((func & 0x3) != 0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) if (SB1_c == FP_CLS_NAN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) vc.wp[1] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) FP_SET_EXCEPTION(FP_EX_INVALID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) FP_TO_INT_ROUND_S(vc.wp[1], SB1, 32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) ((func & 0x3) != 0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) goto update_regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) case EVFSCTUIZ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) case EVFSCTSIZ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) if (SB0_c == FP_CLS_NAN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) vc.wp[0] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) FP_SET_EXCEPTION(FP_EX_INVALID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) FP_TO_INT_S(vc.wp[0], SB0, 32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) ((func & 0x3) != 0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) if (SB1_c == FP_CLS_NAN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) vc.wp[1] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) FP_SET_EXCEPTION(FP_EX_INVALID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) FP_TO_INT_S(vc.wp[1], SB1, 32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) ((func & 0x3) != 0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) goto update_regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) goto illegal;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) pack_vs:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) pr_debug("SR0: %ld %08lx %ld (%ld)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) SR0_s, SR0_f, SR0_e, SR0_c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) pr_debug("SR1: %ld %08lx %ld (%ld)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) SR1_s, SR1_f, SR1_e, SR1_c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) FP_PACK_SP(vc.wp, SR0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) FP_PACK_SP(vc.wp + 1, SR1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) goto update_regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) cmp_vs:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) int ch, cl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) FP_CMP_S(IR0, SA0, SB0, 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) FP_CMP_S(IR1, SA1, SB1, 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) if (IR0 == 3 && (FP_ISSIGNAN_S(SA0) || FP_ISSIGNAN_S(SB0)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) FP_SET_EXCEPTION(FP_EX_INVALID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) if (IR1 == 3 && (FP_ISSIGNAN_S(SA1) || FP_ISSIGNAN_S(SB1)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) FP_SET_EXCEPTION(FP_EX_INVALID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) ch = (IR0 == cmp) ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) cl = (IR1 == cmp) ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) IR = (ch << 3) | (cl << 2) | ((ch | cl) << 1) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) ((ch & cl) << 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) goto update_ccr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) update_ccr:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) regs->ccr &= ~(15 << ((7 - ((speinsn >> 23) & 0x7)) << 2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) regs->ccr |= (IR << ((7 - ((speinsn >> 23) & 0x7)) << 2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) update_regs:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) * If the "invalid" exception sticky bit was set by the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) * processor for non-finite input, but was not set before the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) * instruction being emulated, clear it. Likewise for the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) * "underflow" bit, which may have been set by the processor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) * for exact underflow, not just inexact underflow when the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) * flag should be set for IEEE 754 semantics. Other sticky
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) * exceptions will only be set by the processor when they are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) * correct according to IEEE 754 semantics, and we must not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) * clear sticky bits that were already set before the emulated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) * instruction as they represent the user-visible sticky
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) * exception status. "inexact" traps to kernel are not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) * required for IEEE semantics and are not enabled by default,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) * so the "inexact" sticky bit may have been set by a previous
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) * instruction without the kernel being aware of it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) __FPU_FPSCR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) &= ~(FP_EX_INVALID | FP_EX_UNDERFLOW) | current->thread.spefscr_last;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) __FPU_FPSCR |= (FP_CUR_EXCEPTIONS & FP_EX_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) mtspr(SPRN_SPEFSCR, __FPU_FPSCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) current->thread.spefscr_last = __FPU_FPSCR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) current->thread.evr[fc] = vc.wp[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) regs->gpr[fc] = vc.wp[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) pr_debug("ccr = %08lx\n", regs->ccr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) pr_debug("cur exceptions = %08x spefscr = %08lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) FP_CUR_EXCEPTIONS, __FPU_FPSCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) pr_debug("vc: %08x %08x\n", vc.wp[0], vc.wp[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) pr_debug("va: %08x %08x\n", va.wp[0], va.wp[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) pr_debug("vb: %08x %08x\n", vb.wp[0], vb.wp[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) if (current->thread.fpexc_mode & PR_FP_EXC_SW_ENABLE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) if ((FP_CUR_EXCEPTIONS & FP_EX_DIVZERO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) && (current->thread.fpexc_mode & PR_FP_EXC_DIV))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) if ((FP_CUR_EXCEPTIONS & FP_EX_OVERFLOW)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) && (current->thread.fpexc_mode & PR_FP_EXC_OVF))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) if ((FP_CUR_EXCEPTIONS & FP_EX_UNDERFLOW)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) && (current->thread.fpexc_mode & PR_FP_EXC_UND))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) if ((FP_CUR_EXCEPTIONS & FP_EX_INEXACT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) && (current->thread.fpexc_mode & PR_FP_EXC_RES))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) if ((FP_CUR_EXCEPTIONS & FP_EX_INVALID)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) && (current->thread.fpexc_mode & PR_FP_EXC_INV))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) illegal:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) if (have_e500_cpu_a005_erratum) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) /* according to e500 cpu a005 erratum, reissue efp inst */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) regs->nip -= 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) pr_debug("re-issue efp inst: %08lx\n", speinsn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) printk(KERN_ERR "\nOoops! IEEE-754 compliance handler encountered un-supported instruction.\ninst code: %08lx\n", speinsn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) return -ENOSYS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) int speround_handler(struct pt_regs *regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) union dw_union fgpr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) int s_lo, s_hi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) int lo_inexact, hi_inexact;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) int fp_result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) unsigned long speinsn, type, fb, fc, fptype, func;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) if (get_user(speinsn, (unsigned int __user *) regs->nip))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) if ((speinsn >> 26) != 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) return -EINVAL; /* not an spe instruction */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) func = speinsn & 0x7ff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) type = insn_type(func);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) if (type == XCR) return -ENOSYS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) __FPU_FPSCR = mfspr(SPRN_SPEFSCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) pr_debug("speinsn:%08lx spefscr:%08lx\n", speinsn, __FPU_FPSCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) fptype = (speinsn >> 5) & 0x7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) /* No need to round if the result is exact */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) lo_inexact = __FPU_FPSCR & (SPEFSCR_FG | SPEFSCR_FX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) hi_inexact = __FPU_FPSCR & (SPEFSCR_FGH | SPEFSCR_FXH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) if (!(lo_inexact || (hi_inexact && fptype == VCT)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) fc = (speinsn >> 21) & 0x1f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) s_lo = regs->gpr[fc] & SIGN_BIT_S;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) s_hi = current->thread.evr[fc] & SIGN_BIT_S;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) fgpr.wp[0] = current->thread.evr[fc];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) fgpr.wp[1] = regs->gpr[fc];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) fb = (speinsn >> 11) & 0x1f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) switch (func) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) case EFSCTUIZ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) case EFSCTSIZ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) case EVFSCTUIZ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) case EVFSCTSIZ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) case EFDCTUIDZ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) case EFDCTSIDZ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) case EFDCTUIZ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) case EFDCTSIZ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) * These instructions always round to zero,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) * independent of the rounding mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) case EFSCTUI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) case EFSCTUF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) case EVFSCTUI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) case EVFSCTUF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) case EFDCTUI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) case EFDCTUF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) fp_result = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) s_lo = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) s_hi = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) case EFSCTSI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) case EFSCTSF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) fp_result = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) /* Recover the sign of a zero result if possible. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) if (fgpr.wp[1] == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) s_lo = regs->gpr[fb] & SIGN_BIT_S;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) case EVFSCTSI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) case EVFSCTSF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) fp_result = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) /* Recover the sign of a zero result if possible. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) if (fgpr.wp[1] == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) s_lo = regs->gpr[fb] & SIGN_BIT_S;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) if (fgpr.wp[0] == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) s_hi = current->thread.evr[fb] & SIGN_BIT_S;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) case EFDCTSI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) case EFDCTSF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) fp_result = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) s_hi = s_lo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) /* Recover the sign of a zero result if possible. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) if (fgpr.wp[1] == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) s_hi = current->thread.evr[fb] & SIGN_BIT_S;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) fp_result = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) pr_debug("round fgpr: %08x %08x\n", fgpr.wp[0], fgpr.wp[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) switch (fptype) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) /* Since SPE instructions on E500 core can handle round to nearest
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) * and round toward zero with IEEE-754 complied, we just need
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) * to handle round toward +Inf and round toward -Inf by software.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) case SPFP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) if ((FP_ROUNDMODE) == FP_RND_PINF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) if (!s_lo) fgpr.wp[1]++; /* Z > 0, choose Z1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) } else { /* round to -Inf */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) if (s_lo) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) if (fp_result)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) fgpr.wp[1]++; /* Z < 0, choose Z2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) fgpr.wp[1]--; /* Z < 0, choose Z2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) case DPFP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) if (FP_ROUNDMODE == FP_RND_PINF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) if (!s_hi) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) if (fp_result)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) fgpr.dp[0]++; /* Z > 0, choose Z1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) fgpr.wp[1]++; /* Z > 0, choose Z1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) } else { /* round to -Inf */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) if (s_hi) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) if (fp_result)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) fgpr.dp[0]++; /* Z < 0, choose Z2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) fgpr.wp[1]--; /* Z < 0, choose Z2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) case VCT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) if (FP_ROUNDMODE == FP_RND_PINF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) if (lo_inexact && !s_lo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) fgpr.wp[1]++; /* Z_low > 0, choose Z1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) if (hi_inexact && !s_hi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) fgpr.wp[0]++; /* Z_high word > 0, choose Z1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) } else { /* round to -Inf */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) if (lo_inexact && s_lo) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) if (fp_result)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) fgpr.wp[1]++; /* Z_low < 0, choose Z2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) fgpr.wp[1]--; /* Z_low < 0, choose Z2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) if (hi_inexact && s_hi) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) if (fp_result)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) fgpr.wp[0]++; /* Z_high < 0, choose Z2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) fgpr.wp[0]--; /* Z_high < 0, choose Z2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) current->thread.evr[fc] = fgpr.wp[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) regs->gpr[fc] = fgpr.wp[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) pr_debug(" to fgpr: %08x %08x\n", fgpr.wp[0], fgpr.wp[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) if (current->thread.fpexc_mode & PR_FP_EXC_SW_ENABLE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) return (current->thread.fpexc_mode & PR_FP_EXC_RES) ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) int __init spe_mathemu_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) u32 pvr, maj, min;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) pvr = mfspr(SPRN_PVR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) if ((PVR_VER(pvr) == PVR_VER_E500V1) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) (PVR_VER(pvr) == PVR_VER_E500V2)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) maj = PVR_MAJ(pvr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) min = PVR_MIN(pvr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) * E500 revision below 1.1, 2.3, 3.1, 4.1, 5.1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) * need cpu a005 errata workaround
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) switch (maj) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) if (min < 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) have_e500_cpu_a005_erratum = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) if (min < 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) have_e500_cpu_a005_erratum = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) case 3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) case 4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) case 5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) if (min < 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) have_e500_cpu_a005_erratum = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) module_init(spe_mathemu_init);