Commit 2d83fea7 authored by Maciej W. Rozycki's avatar Maciej W. Rozycki Committed by Ralf Baechle

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: default avatarMaciej W. Rozycki <macro@linux-mips.org>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/9700/Signed-off-by: default avatarRalf Baechle <ralf@linux-mips.org>
parent 80cbfad7
...@@ -221,8 +221,11 @@ ...@@ -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) ...@@ -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 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx, ...@@ -1115,17 +1115,18 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
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 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx, ...@@ -1165,36 +1166,34 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
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 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx, ...@@ -1228,7 +1227,7 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
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, ...@@ -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, ...@@ -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 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, ...@@ -1682,7 +1681,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
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 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, ...@@ -1694,7 +1693,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
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 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, ...@@ -1706,7 +1705,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
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 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, ...@@ -1775,13 +1774,13 @@ 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_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 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, ...@@ -1871,7 +1870,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
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 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, ...@@ -1883,7 +1882,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
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 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, ...@@ -1942,7 +1941,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
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 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx, ...@@ -2006,7 +2005,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
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));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment