MIPS: Correct FP ISA requirements
Correct ISA requirements for floating-point instructions: * the CU3 exception signifies a real COP3 instruction in MIPS I & II, * the BC1FL and BC1TL instructions are not supported in MIPS I, * the SQRT.fmt instructions are indeed supported in MIPS II, * the LDC1 and SDC1 instructions are indeed supported in MIPS32r1, * the CEIL.W.fmt, FLOOR.W.fmt, ROUND.W.fmt and TRUNC.W.fmt instructions are indeed supported in MIPS32, * the CVT.L.fmt and CVT.fmt.L instructions are indeed supported in MIPS32r2 and MIPS32r6, * the CEIL.L.fmt, FLOOR.L.fmt, ROUND.L.fmt and TRUNC.L.fmt instructions are indeed supported in MIPS32r2 and MIPS32r6, * the RSQRT.fmt and RECIP.fmt instructions are indeed supported in MIPS64r1, Also simplify conditionals for MIPS III and MIPS IV FPU instructions and the handling of the MOVCI minor opcode. Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org> Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/9700/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
This commit is contained in:
parent
80cbfad790
commit
2d83fea786
@ -221,8 +221,11 @@
|
|||||||
#define cpu_has_mips_4_5_r (cpu_has_mips_4 | cpu_has_mips_5_r)
|
#define cpu_has_mips_4_5_r (cpu_has_mips_4 | cpu_has_mips_5_r)
|
||||||
#define cpu_has_mips_5_r (cpu_has_mips_5 | cpu_has_mips_r)
|
#define cpu_has_mips_5_r (cpu_has_mips_5 | cpu_has_mips_r)
|
||||||
|
|
||||||
#define cpu_has_mips_4_5_r2_r6 (cpu_has_mips_4_5 | cpu_has_mips_r2 | \
|
#define cpu_has_mips_3_4_5_64_r2_r6 \
|
||||||
cpu_has_mips_r6)
|
(cpu_has_mips_3 | cpu_has_mips_4_5_64_r2_r6)
|
||||||
|
#define cpu_has_mips_4_5_64_r2_r6 \
|
||||||
|
(cpu_has_mips_4_5 | cpu_has_mips64r1 | \
|
||||||
|
cpu_has_mips_r2 | cpu_has_mips_r6)
|
||||||
|
|
||||||
#define cpu_has_mips32 (cpu_has_mips32r1 | cpu_has_mips32r2 | cpu_has_mips32r6)
|
#define cpu_has_mips32 (cpu_has_mips32r1 | cpu_has_mips32r2 | cpu_has_mips32r6)
|
||||||
#define cpu_has_mips64 (cpu_has_mips64r1 | cpu_has_mips64r2 | cpu_has_mips64r6)
|
#define cpu_has_mips64 (cpu_has_mips64r1 | cpu_has_mips64r2 | cpu_has_mips64r6)
|
||||||
|
@ -1349,19 +1349,18 @@ asmlinkage void do_cpu(struct pt_regs *regs)
|
|||||||
|
|
||||||
case 3:
|
case 3:
|
||||||
/*
|
/*
|
||||||
* Old (MIPS I and MIPS II) processors will set this code
|
* The COP3 opcode space and consequently the CP0.Status.CU3
|
||||||
* for COP1X opcode instructions that replaced the original
|
* bit and the CP0.Cause.CE=3 encoding have been removed as
|
||||||
* COP3 space. We don't limit COP1 space instructions in
|
* of the MIPS III ISA. From the MIPS IV and MIPS32r2 ISAs
|
||||||
* the emulator according to the CPU ISA, so we want to
|
* up the space has been reused for COP1X instructions, that
|
||||||
* treat COP1X instructions consistently regardless of which
|
* are enabled by the CP0.Status.CU1 bit and consequently
|
||||||
* code the CPU chose. Therefore we redirect this trap to
|
* use the CP0.Cause.CE=1 encoding for Coprocessor Unusable
|
||||||
* the FP emulator too.
|
* exceptions. Some FPU-less processors that implement one
|
||||||
*
|
* of these ISAs however use this code erroneously for COP1X
|
||||||
* Then some newer FPU-less processors use this code
|
* instructions. Therefore we redirect this trap to the FP
|
||||||
* erroneously too, so they are covered by this choice
|
* emulator too.
|
||||||
* as well.
|
|
||||||
*/
|
*/
|
||||||
if (raw_cpu_has_fpu) {
|
if (raw_cpu_has_fpu || !cpu_has_mips_4_5_64_r2_r6) {
|
||||||
force_sig(SIGILL, current);
|
force_sig(SIGILL, current);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1115,17 +1115,18 @@ emul:
|
|||||||
likely = 0;
|
likely = 0;
|
||||||
switch (MIPSInst_RT(ir) & 3) {
|
switch (MIPSInst_RT(ir) & 3) {
|
||||||
case bcfl_op:
|
case bcfl_op:
|
||||||
likely = 1;
|
if (cpu_has_mips_2_3_4_5_r)
|
||||||
|
likely = 1;
|
||||||
|
/* Fall through */
|
||||||
case bcf_op:
|
case bcf_op:
|
||||||
cond = !cond;
|
cond = !cond;
|
||||||
break;
|
break;
|
||||||
case bctl_op:
|
case bctl_op:
|
||||||
likely = 1;
|
if (cpu_has_mips_2_3_4_5_r)
|
||||||
|
likely = 1;
|
||||||
|
/* Fall through */
|
||||||
case bct_op:
|
case bct_op:
|
||||||
break;
|
break;
|
||||||
default:
|
|
||||||
/* thats an illegal instruction */
|
|
||||||
return SIGILL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
set_delay_slot(xcp);
|
set_delay_slot(xcp);
|
||||||
@ -1165,36 +1166,34 @@ emul:
|
|||||||
|
|
||||||
switch (MIPSInst_OPCODE(ir)) {
|
switch (MIPSInst_OPCODE(ir)) {
|
||||||
case lwc1_op:
|
case lwc1_op:
|
||||||
goto emul;
|
|
||||||
|
|
||||||
case swc1_op:
|
case swc1_op:
|
||||||
goto emul;
|
goto emul;
|
||||||
|
|
||||||
case ldc1_op:
|
case ldc1_op:
|
||||||
case sdc1_op:
|
case sdc1_op:
|
||||||
if (cpu_has_mips_2_3_4_5 ||
|
if (cpu_has_mips_2_3_4_5_r)
|
||||||
cpu_has_mips64)
|
|
||||||
goto emul;
|
goto emul;
|
||||||
|
|
||||||
return SIGILL;
|
return SIGILL;
|
||||||
goto emul;
|
|
||||||
|
|
||||||
case cop1_op:
|
case cop1_op:
|
||||||
goto emul;
|
goto emul;
|
||||||
|
|
||||||
case cop1x_op:
|
case cop1x_op:
|
||||||
if (cpu_has_mips_4_5 || cpu_has_mips64 || cpu_has_mips32r2)
|
if (cpu_has_mips_4_5_64_r2_r6)
|
||||||
/* its one of ours */
|
/* its one of ours */
|
||||||
goto emul;
|
goto emul;
|
||||||
|
|
||||||
return SIGILL;
|
return SIGILL;
|
||||||
|
|
||||||
case spec_op:
|
case spec_op:
|
||||||
if (!cpu_has_mips_4_5_r)
|
switch (MIPSInst_FUNC(ir)) {
|
||||||
return SIGILL;
|
case movc_op:
|
||||||
|
if (cpu_has_mips_4_5_r)
|
||||||
|
goto emul;
|
||||||
|
|
||||||
if (MIPSInst_FUNC(ir) == movc_op)
|
return SIGILL;
|
||||||
goto emul;
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1228,7 +1227,7 @@ emul:
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case cop1x_op:
|
case cop1x_op:
|
||||||
if (!cpu_has_mips_4_5 && !cpu_has_mips64 && !cpu_has_mips32r2)
|
if (!cpu_has_mips_4_5_64_r2_r6)
|
||||||
return SIGILL;
|
return SIGILL;
|
||||||
|
|
||||||
sig = fpux_emu(xcp, ctx, ir, fault_addr);
|
sig = fpux_emu(xcp, ctx, ir, fault_addr);
|
||||||
@ -1561,7 +1560,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
|
|||||||
|
|
||||||
/* unary ops */
|
/* unary ops */
|
||||||
case fsqrt_op:
|
case fsqrt_op:
|
||||||
if (!cpu_has_mips_4_5_r)
|
if (!cpu_has_mips_2_3_4_5_r)
|
||||||
return SIGILL;
|
return SIGILL;
|
||||||
|
|
||||||
handler.u = ieee754sp_sqrt;
|
handler.u = ieee754sp_sqrt;
|
||||||
@ -1573,14 +1572,14 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
|
|||||||
* achieve full IEEE-754 accuracy - however this emulator does.
|
* achieve full IEEE-754 accuracy - however this emulator does.
|
||||||
*/
|
*/
|
||||||
case frsqrt_op:
|
case frsqrt_op:
|
||||||
if (!cpu_has_mips_4_5_r2_r6)
|
if (!cpu_has_mips_4_5_64_r2_r6)
|
||||||
return SIGILL;
|
return SIGILL;
|
||||||
|
|
||||||
handler.u = fpemu_sp_rsqrt;
|
handler.u = fpemu_sp_rsqrt;
|
||||||
goto scopuop;
|
goto scopuop;
|
||||||
|
|
||||||
case frecip_op:
|
case frecip_op:
|
||||||
if (!cpu_has_mips_4_5_r2_r6)
|
if (!cpu_has_mips_4_5_64_r2_r6)
|
||||||
return SIGILL;
|
return SIGILL;
|
||||||
|
|
||||||
handler.u = fpemu_sp_recip;
|
handler.u = fpemu_sp_recip;
|
||||||
@ -1682,7 +1681,7 @@ copcsr:
|
|||||||
case ftrunc_op:
|
case ftrunc_op:
|
||||||
case fceil_op:
|
case fceil_op:
|
||||||
case ffloor_op:
|
case ffloor_op:
|
||||||
if (!cpu_has_mips_2_3_4_5 && !cpu_has_mips64)
|
if (!cpu_has_mips_2_3_4_5_r)
|
||||||
return SIGILL;
|
return SIGILL;
|
||||||
|
|
||||||
oldrm = ieee754_csr.rm;
|
oldrm = ieee754_csr.rm;
|
||||||
@ -1694,7 +1693,7 @@ copcsr:
|
|||||||
goto copcsr;
|
goto copcsr;
|
||||||
|
|
||||||
case fcvtl_op:
|
case fcvtl_op:
|
||||||
if (!cpu_has_mips_3_4_5 && !cpu_has_mips64)
|
if (!cpu_has_mips_3_4_5_64_r2_r6)
|
||||||
return SIGILL;
|
return SIGILL;
|
||||||
|
|
||||||
SPFROMREG(fs, MIPSInst_FS(ir));
|
SPFROMREG(fs, MIPSInst_FS(ir));
|
||||||
@ -1706,7 +1705,7 @@ copcsr:
|
|||||||
case ftruncl_op:
|
case ftruncl_op:
|
||||||
case fceill_op:
|
case fceill_op:
|
||||||
case ffloorl_op:
|
case ffloorl_op:
|
||||||
if (!cpu_has_mips_3_4_5 && !cpu_has_mips64)
|
if (!cpu_has_mips_3_4_5_64_r2_r6)
|
||||||
return SIGILL;
|
return SIGILL;
|
||||||
|
|
||||||
oldrm = ieee754_csr.rm;
|
oldrm = ieee754_csr.rm;
|
||||||
@ -1775,13 +1774,13 @@ copcsr:
|
|||||||
* achieve full IEEE-754 accuracy - however this emulator does.
|
* achieve full IEEE-754 accuracy - however this emulator does.
|
||||||
*/
|
*/
|
||||||
case frsqrt_op:
|
case frsqrt_op:
|
||||||
if (!cpu_has_mips_4_5_r2_r6)
|
if (!cpu_has_mips_4_5_64_r2_r6)
|
||||||
return SIGILL;
|
return SIGILL;
|
||||||
|
|
||||||
handler.u = fpemu_dp_rsqrt;
|
handler.u = fpemu_dp_rsqrt;
|
||||||
goto dcopuop;
|
goto dcopuop;
|
||||||
case frecip_op:
|
case frecip_op:
|
||||||
if (!cpu_has_mips_4_5_r2_r6)
|
if (!cpu_has_mips_4_5_64_r2_r6)
|
||||||
return SIGILL;
|
return SIGILL;
|
||||||
|
|
||||||
handler.u = fpemu_dp_recip;
|
handler.u = fpemu_dp_recip;
|
||||||
@ -1871,7 +1870,7 @@ dcopuop:
|
|||||||
goto copcsr;
|
goto copcsr;
|
||||||
|
|
||||||
case fcvtl_op:
|
case fcvtl_op:
|
||||||
if (!cpu_has_mips_3_4_5 && !cpu_has_mips64)
|
if (!cpu_has_mips_3_4_5_64_r2_r6)
|
||||||
return SIGILL;
|
return SIGILL;
|
||||||
|
|
||||||
DPFROMREG(fs, MIPSInst_FS(ir));
|
DPFROMREG(fs, MIPSInst_FS(ir));
|
||||||
@ -1883,7 +1882,7 @@ dcopuop:
|
|||||||
case ftruncl_op:
|
case ftruncl_op:
|
||||||
case fceill_op:
|
case fceill_op:
|
||||||
case ffloorl_op:
|
case ffloorl_op:
|
||||||
if (!cpu_has_mips_3_4_5 && !cpu_has_mips64)
|
if (!cpu_has_mips_3_4_5_64_r2_r6)
|
||||||
return SIGILL;
|
return SIGILL;
|
||||||
|
|
||||||
oldrm = ieee754_csr.rm;
|
oldrm = ieee754_csr.rm;
|
||||||
@ -1942,7 +1941,7 @@ dcopuop:
|
|||||||
|
|
||||||
case l_fmt:
|
case l_fmt:
|
||||||
|
|
||||||
if (!cpu_has_mips_3_4_5 && !cpu_has_mips64)
|
if (!cpu_has_mips_3_4_5_64_r2_r6)
|
||||||
return SIGILL;
|
return SIGILL;
|
||||||
|
|
||||||
DIFROMREG(bits, MIPSInst_FS(ir));
|
DIFROMREG(bits, MIPSInst_FS(ir));
|
||||||
@ -2006,7 +2005,7 @@ dcopuop:
|
|||||||
SITOREG(rv.w, MIPSInst_FD(ir));
|
SITOREG(rv.w, MIPSInst_FD(ir));
|
||||||
break;
|
break;
|
||||||
case l_fmt:
|
case l_fmt:
|
||||||
if (!cpu_has_mips_3_4_5 && !cpu_has_mips64)
|
if (!cpu_has_mips_3_4_5_64_r2_r6)
|
||||||
return SIGILL;
|
return SIGILL;
|
||||||
|
|
||||||
DITOREG(rv.l, MIPSInst_FD(ir));
|
DITOREG(rv.l, MIPSInst_FD(ir));
|
||||||
|
Loading…
Reference in New Issue
Block a user