aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarkos Chandras <markos.chandras@imgtec.com>2015-08-13 03:56:28 -0400
committerRalf Baechle <ralf@linux-mips.org>2015-09-03 06:08:12 -0400
commitf8c3c6717a7128f9601b20f890d658283d59561a (patch)
treedf70666ac624fab548ba8653b8838016daa498d1
parent107d34009ef00d1680521be2c4a1cba31f9b69a6 (diff)
MIPS: math-emu: Add support for the CMP.condn.fmt R6 instruction
Add support for emulating the new CMP.condn.fmt R6 instructions and return SIGILL for the old C.cond.fmt if R2 emulation is not enabled since it's not supported by R6. The functionality of the new CMP.condn.fmt is the following one: If the comparison specified by the condn field of the instruction is true for the operand values, the result is true; otherwise, the result is false. If no exception is taken, the result is written into FPR fd; true is all 1s and false is all 0s repeated the operand width of fmt. All other bits beyond the operand width fmt are UNPREDICTABLE. Signed-off-by: Markos Chandras <markos.chandras@imgtec.com> Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/10953/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
-rw-r--r--arch/mips/math-emu/cp1emu.c130
1 files changed, 121 insertions, 9 deletions
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
index 8a5b0eb4ddef..ef41fc895e75 100644
--- a/arch/mips/math-emu/cp1emu.c
+++ b/arch/mips/math-emu/cp1emu.c
@@ -1394,6 +1394,14 @@ static const unsigned char cmptab[8] = {
1394 IEEE754_CLT | IEEE754_CEQ | IEEE754_CUN, /* cmp_ule (sig) cmp_ngt */ 1394 IEEE754_CLT | IEEE754_CEQ | IEEE754_CUN, /* cmp_ule (sig) cmp_ngt */
1395}; 1395};
1396 1396
1397static const unsigned char negative_cmptab[8] = {
1398 0, /* Reserved */
1399 IEEE754_CLT | IEEE754_CGT | IEEE754_CEQ,
1400 IEEE754_CLT | IEEE754_CGT | IEEE754_CUN,
1401 IEEE754_CLT | IEEE754_CGT,
1402 /* Reserved */
1403};
1404
1397 1405
1398/* 1406/*
1399 * Additional MIPS4 instructions 1407 * Additional MIPS4 instructions
@@ -1838,7 +1846,7 @@ copcsr:
1838 goto copcsr; 1846 goto copcsr;
1839 1847
1840 default: 1848 default:
1841 if (MIPSInst_FUNC(ir) >= fcmp_op) { 1849 if (!NO_R6EMU && MIPSInst_FUNC(ir) >= fcmp_op) {
1842 unsigned cmpop = MIPSInst_FUNC(ir) - fcmp_op; 1850 unsigned cmpop = MIPSInst_FUNC(ir) - fcmp_op;
1843 union ieee754sp fs, ft; 1851 union ieee754sp fs, ft;
1844 1852
@@ -2015,7 +2023,7 @@ dcopuop:
2015 goto copcsr; 2023 goto copcsr;
2016 2024
2017 default: 2025 default:
2018 if (MIPSInst_FUNC(ir) >= fcmp_op) { 2026 if (!NO_R6EMU && MIPSInst_FUNC(ir) >= fcmp_op) {
2019 unsigned cmpop = MIPSInst_FUNC(ir) - fcmp_op; 2027 unsigned cmpop = MIPSInst_FUNC(ir) - fcmp_op;
2020 union ieee754dp fs, ft; 2028 union ieee754dp fs, ft;
2021 2029
@@ -2057,10 +2065,65 @@ dcopuop:
2057 rv.d = ieee754dp_fint(fs.bits); 2065 rv.d = ieee754dp_fint(fs.bits);
2058 rfmt = d_fmt; 2066 rfmt = d_fmt;
2059 goto copcsr; 2067 goto copcsr;
2060 default: 2068 default: {
2061 return SIGILL; 2069 /* Emulating the new CMP.condn.fmt R6 instruction */
2070#define CMPOP_MASK 0x7
2071#define SIGN_BIT (0x1 << 3)
2072#define PREDICATE_BIT (0x1 << 4)
2073
2074 int cmpop = MIPSInst_FUNC(ir) & CMPOP_MASK;
2075 int sig = MIPSInst_FUNC(ir) & SIGN_BIT;
2076 union ieee754sp fs, ft;
2077
2078 /* This is an R6 only instruction */
2079 if (!cpu_has_mips_r6 ||
2080 (MIPSInst_FUNC(ir) & 0x20))
2081 return SIGILL;
2082
2083 /* fmt is w_fmt for single precision so fix it */
2084 rfmt = s_fmt;
2085 /* default to false */
2086 rv.w = 0;
2087
2088 /* CMP.condn.S */
2089 SPFROMREG(fs, MIPSInst_FS(ir));
2090 SPFROMREG(ft, MIPSInst_FT(ir));
2091
2092 /* positive predicates */
2093 if (!(MIPSInst_FUNC(ir) & PREDICATE_BIT)) {
2094 if (ieee754sp_cmp(fs, ft, cmptab[cmpop],
2095 sig))
2096 rv.w = -1; /* true, all 1s */
2097 if ((sig) &&
2098 ieee754_cxtest(IEEE754_INVALID_OPERATION))
2099 rcsr = FPU_CSR_INV_X | FPU_CSR_INV_S;
2100 else
2101 goto copcsr;
2102 } else {
2103 /* negative predicates */
2104 switch (cmpop) {
2105 case 1:
2106 case 2:
2107 case 3:
2108 if (ieee754sp_cmp(fs, ft,
2109 negative_cmptab[cmpop],
2110 sig))
2111 rv.w = -1; /* true, all 1s */
2112 if (sig &&
2113 ieee754_cxtest(IEEE754_INVALID_OPERATION))
2114 rcsr = FPU_CSR_INV_X | FPU_CSR_INV_S;
2115 else
2116 goto copcsr;
2117 break;
2118 default:
2119 /* Reserved R6 ops */
2120 pr_err("Reserved MIPS R6 CMP.condn.S operation\n");
2121 return SIGILL;
2122 }
2123 }
2124 break;
2125 }
2062 } 2126 }
2063 break;
2064 } 2127 }
2065 2128
2066 case l_fmt: 2129 case l_fmt:
@@ -2081,11 +2144,60 @@ dcopuop:
2081 rv.d = ieee754dp_flong(bits); 2144 rv.d = ieee754dp_flong(bits);
2082 rfmt = d_fmt; 2145 rfmt = d_fmt;
2083 goto copcsr; 2146 goto copcsr;
2084 default: 2147 default: {
2085 return SIGILL; 2148 /* Emulating the new CMP.condn.fmt R6 instruction */
2086 } 2149 int cmpop = MIPSInst_FUNC(ir) & CMPOP_MASK;
2087 break; 2150 int sig = MIPSInst_FUNC(ir) & SIGN_BIT;
2151 union ieee754dp fs, ft;
2152
2153 if (!cpu_has_mips_r6 ||
2154 (MIPSInst_FUNC(ir) & 0x20))
2155 return SIGILL;
2088 2156
2157 /* fmt is l_fmt for double precision so fix it */
2158 rfmt = d_fmt;
2159 /* default to false */
2160 rv.l = 0;
2161
2162 /* CMP.condn.D */
2163 DPFROMREG(fs, MIPSInst_FS(ir));
2164 DPFROMREG(ft, MIPSInst_FT(ir));
2165
2166 /* positive predicates */
2167 if (!(MIPSInst_FUNC(ir) & PREDICATE_BIT)) {
2168 if (ieee754dp_cmp(fs, ft,
2169 cmptab[cmpop], sig))
2170 rv.l = -1LL; /* true, all 1s */
2171 if (sig &&
2172 ieee754_cxtest(IEEE754_INVALID_OPERATION))
2173 rcsr = FPU_CSR_INV_X | FPU_CSR_INV_S;
2174 else
2175 goto copcsr;
2176 } else {
2177 /* negative predicates */
2178 switch (cmpop) {
2179 case 1:
2180 case 2:
2181 case 3:
2182 if (ieee754dp_cmp(fs, ft,
2183 negative_cmptab[cmpop],
2184 sig))
2185 rv.l = -1LL; /* true, all 1s */
2186 if (sig &&
2187 ieee754_cxtest(IEEE754_INVALID_OPERATION))
2188 rcsr = FPU_CSR_INV_X | FPU_CSR_INV_S;
2189 else
2190 goto copcsr;
2191 break;
2192 default:
2193 /* Reserved R6 ops */
2194 pr_err("Reserved MIPS R6 CMP.condn.D operation\n");
2195 return SIGILL;
2196 }
2197 }
2198 break;
2199 }
2200 }
2089 default: 2201 default:
2090 return SIGILL; 2202 return SIGILL;
2091 } 2203 }