Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+5 −2
Original line number Original line Diff line number Diff line
@@ -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)
+11 −12
Original line number Original line Diff line number Diff line
@@ -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;
		}
		}
+27 −28
Original line number Original line Diff line number Diff line
@@ -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:
				if (cpu_has_mips_2_3_4_5_r)
					likely = 1;
					likely = 1;
				/* Fall through */
			case bcf_op:
			case bcf_op:
				cond = !cond;
				cond = !cond;
				break;
				break;
			case bctl_op:
			case bctl_op:
				if (cpu_has_mips_2_3_4_5_r)
					likely = 1;
					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)
					if (MIPSInst_FUNC(ir) == movc_op)
							goto emul;
							goto emul;

						return SIGILL;
					}
					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));