Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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);