MIPS: Correct FP ISA requirements
authorMaciej W. Rozycki <macro@linux-mips.org>
Fri, 3 Apr 2015 22:26:49 +0000 (23:26 +0100)
committerRalf Baechle <ralf@linux-mips.org>
Tue, 7 Apr 2015 23:10:05 +0000 (01:10 +0200)
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>
arch/mips/include/asm/cpu-features.h
arch/mips/kernel/traps.c
arch/mips/math-emu/cp1emu.c

index 62a4730de86a3bf22752d1efe291569366dbe795..fc2ad332541c2978786b15fc45dd793ff65acffe 100644 (file)
 #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_4_5_r2_r6 (cpu_has_mips_4_5 | cpu_has_mips_r2 | \
-                                cpu_has_mips_r6)
+#define cpu_has_mips_3_4_5_64_r2_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_mips64 (cpu_has_mips64r1 | cpu_has_mips64r2 | cpu_has_mips64r6)
index dc6eaf4d93ea70354223f8fcd2f7551293e78b06..88f04f0d2d2165f32647808427842680fc53c5a3 100644 (file)
@@ -1349,19 +1349,18 @@ asmlinkage void do_cpu(struct pt_regs *regs)
 
        case 3:
                /*
-                * Old (MIPS I and MIPS II) processors will set this code
-                * for COP1X opcode instructions that replaced the original
-                * COP3 space.  We don't limit COP1 space instructions in
-                * the emulator according to the CPU ISA, so we want to
-                * treat COP1X instructions consistently regardless of which
-                * code the CPU chose.  Therefore we redirect this trap to
-                * the FP emulator too.
-                *
-                * Then some newer FPU-less processors use this code
-                * erroneously too, so they are covered by this choice
-                * as well.
+                * The COP3 opcode space and consequently the CP0.Status.CU3
+                * bit and the CP0.Cause.CE=3 encoding have been removed as
+                * of the MIPS III ISA.  From the MIPS IV and MIPS32r2 ISAs
+                * up the space has been reused for COP1X instructions, that
+                * are enabled by the CP0.Status.CU1 bit and consequently
+                * use the CP0.Cause.CE=1 encoding for Coprocessor Unusable
+                * exceptions.  Some FPU-less processors that implement one
+                * of these ISAs however use this code erroneously for COP1X
+                * instructions.  Therefore we redirect this trap to the FP
+                * emulator too.
                 */
-               if (raw_cpu_has_fpu) {
+               if (raw_cpu_has_fpu || !cpu_has_mips_4_5_64_r2_r6) {
                        force_sig(SIGILL, current);
                        break;
                }
index be983850eb3945803d474e7319b3fded9009b32e..732c3a37d7b9dea3325293530be70ac144d3a10a 100644 (file)
@@ -1115,17 +1115,18 @@ emul:
                        likely = 0;
                        switch (MIPSInst_RT(ir) & 3) {
                        case bcfl_op:
-                               likely = 1;
+                               if (cpu_has_mips_2_3_4_5_r)
+                                       likely = 1;
+                               /* Fall through */
                        case bcf_op:
                                cond = !cond;
                                break;
                        case bctl_op:
-                               likely = 1;
+                               if (cpu_has_mips_2_3_4_5_r)
+                                       likely = 1;
+                               /* Fall through */
                        case bct_op:
                                break;
-                       default:
-                               /* thats an illegal instruction */
-                               return SIGILL;
                        }
 
                        set_delay_slot(xcp);
@@ -1165,36 +1166,34 @@ emul:
 
                                switch (MIPSInst_OPCODE(ir)) {
                                case lwc1_op:
-                                       goto emul;
-
                                case swc1_op:
                                        goto emul;
 
                                case ldc1_op:
                                case sdc1_op:
-                                       if (cpu_has_mips_2_3_4_5 ||
-                                           cpu_has_mips64)
+                                       if (cpu_has_mips_2_3_4_5_r)
                                                goto emul;
 
                                        return SIGILL;
-                                       goto emul;
 
                                case cop1_op:
                                        goto emul;
 
                                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 */
                                                goto emul;
 
                                        return SIGILL;
 
                                case spec_op:
-                                       if (!cpu_has_mips_4_5_r)
-                                               return SIGILL;
+                                       switch (MIPSInst_FUNC(ir)) {
+                                       case movc_op:
+                                               if (cpu_has_mips_4_5_r)
+                                                       goto emul;
 
-                                       if (MIPSInst_FUNC(ir) == movc_op)
-                                               goto emul;
+                                               return SIGILL;
+                                       }
                                        break;
                                }
 
@@ -1228,7 +1227,7 @@ emul:
                break;
 
        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;
 
                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 */
                case fsqrt_op:
-                       if (!cpu_has_mips_4_5_r)
+                       if (!cpu_has_mips_2_3_4_5_r)
                                return SIGILL;
 
                        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.
                 */
                case frsqrt_op:
-                       if (!cpu_has_mips_4_5_r2_r6)
+                       if (!cpu_has_mips_4_5_64_r2_r6)
                                return SIGILL;
 
                        handler.u = fpemu_sp_rsqrt;
                        goto scopuop;
 
                case frecip_op:
-                       if (!cpu_has_mips_4_5_r2_r6)
+                       if (!cpu_has_mips_4_5_64_r2_r6)
                                return SIGILL;
 
                        handler.u = fpemu_sp_recip;
@@ -1682,7 +1681,7 @@ copcsr:
                case ftrunc_op:
                case fceil_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;
 
                        oldrm = ieee754_csr.rm;
@@ -1694,7 +1693,7 @@ copcsr:
                        goto copcsr;
 
                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;
 
                        SPFROMREG(fs, MIPSInst_FS(ir));
@@ -1706,7 +1705,7 @@ copcsr:
                case ftruncl_op:
                case fceill_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;
 
                        oldrm = ieee754_csr.rm;
@@ -1775,13 +1774,13 @@ copcsr:
                 * achieve full IEEE-754 accuracy - however this emulator does.
                 */
                case frsqrt_op:
-                       if (!cpu_has_mips_4_5_r2_r6)
+                       if (!cpu_has_mips_4_5_64_r2_r6)
                                return SIGILL;
 
                        handler.u = fpemu_dp_rsqrt;
                        goto dcopuop;
                case frecip_op:
-                       if (!cpu_has_mips_4_5_r2_r6)
+                       if (!cpu_has_mips_4_5_64_r2_r6)
                                return SIGILL;
 
                        handler.u = fpemu_dp_recip;
@@ -1871,7 +1870,7 @@ dcopuop:
                        goto copcsr;
 
                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;
 
                        DPFROMREG(fs, MIPSInst_FS(ir));
@@ -1883,7 +1882,7 @@ dcopuop:
                case ftruncl_op:
                case fceill_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;
 
                        oldrm = ieee754_csr.rm;
@@ -1942,7 +1941,7 @@ dcopuop:
 
        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;
 
                DIFROMREG(bits, MIPSInst_FS(ir));
@@ -2006,7 +2005,7 @@ dcopuop:
                SITOREG(rv.w, MIPSInst_FD(ir));
                break;
        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;
 
                DITOREG(rv.l, MIPSInst_FD(ir));