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

Commit 08a07904 authored by Ralf Baechle's avatar Ralf Baechle
Browse files

MIPS: math-emu: Remove most ifdefery.



Most of these tests should be runtime tests.  This also finally means
that on a MIPS III systems MIPS IV opcodes are going to result in an
exception as they're supposed to.

Signed-off-by: default avatarRalf Baechle <ralf@linux-mips.org>
parent 9e8bad1f
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -183,6 +183,17 @@
/*
 * Shortcuts ...
 */
#define cpu_has_mips_2_3_4_5	(cpu_has_mips_2 | cpu_has_mips_3_4_5)
#define cpu_has_mips_3_4_5	(cpu_has_mips_3 | cpu_has_mips_4_5)
#define cpu_has_mips_4_5	(cpu_has_mips_4 | cpu_has_mips_5)

#define cpu_has_mips_2_3_4_5_r	(cpu_has_mips_2 | cpu_has_mips_3_4_5_r)
#define cpu_has_mips_3_4_5_r	(cpu_has_mips_3 | cpu_has_mips_4_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_4_5_r2	(cpu_has_mips_4_5 | cpu_has_mips_r2)

#define cpu_has_mips32	(cpu_has_mips32r1 | cpu_has_mips32r2)
#define cpu_has_mips64	(cpu_has_mips64r1 | cpu_has_mips64r2)
#define cpu_has_mips_r1 (cpu_has_mips32r1 | cpu_has_mips64r1)
+128 −76
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@
 */
#include <linux/sched.h>
#include <linux/debugfs.h>
#include <linux/kconfig.h>
#include <linux/percpu-defs.h>
#include <linux/perf_event.h>

@@ -50,22 +51,13 @@

#include "ieee754.h"

/* Strap kernel emulator for full MIPS IV emulation */

#ifdef __mips
#undef __mips
#endif
#define __mips 4

/* Function which emulates a floating point instruction. */

static int fpu_emu(struct pt_regs *, struct mips_fpu_struct *,
	mips_instruction);

#if __mips >= 4 && __mips != 32
static int fpux_emu(struct pt_regs *,
	struct mips_fpu_struct *, mips_instruction, void *__user *);
#endif

/* Control registers */

@@ -95,7 +87,6 @@ static const unsigned char mips_rm[4] = {
	[IEEE754_RU] = FPU_CSR_RU,
};

#if __mips >= 4
/* convert condition code register number to csr bit */
static const unsigned int fpucondbit[8] = {
	FPU_CSR_COND0,
@@ -107,7 +98,6 @@ static const unsigned int fpucondbit[8] = {
	FPU_CSR_COND6,
	FPU_CSR_COND7
};
#endif

/* (microMIPS) Convert 16-bit register encoding to 32-bit register encoding. */
static const unsigned int reg16to32map[8] = {16, 17, 2, 3, 4, 5, 6, 7};
@@ -860,13 +850,13 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
 */
static inline int cop1_64bit(struct pt_regs *xcp)
{
#if defined(CONFIG_64BIT) && !defined(CONFIG_MIPS32_O32)
	if (config_enabled(CONFIG_64BIT) && !config_enabled(CONFIG_MIPS32_O32))
		return 1;
#elif defined(CONFIG_32BIT) && !defined(CONFIG_MIPS_O32_FP64_SUPPORT)
	else if (config_enabled(CONFIG_32BIT) &&
		 !config_enabled(CONFIG_MIPS_O32_FP64_SUPPORT))
		return 0;
#else

	return !test_thread_flag(TIF_32BIT_FPREGS);
#endif
}

#define SIFROMREG(si, x)						\
@@ -1070,8 +1060,10 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
	case cop1_op:
		switch (MIPSInst_RS(ir)) {

#if defined(__mips64)
		case dmfc_op:
			if (!cpu_has_mips_3_4_5 && !cpu_has_mips64)
				return SIGILL;

			/* copregister fs -> gpr[rt] */
			if (MIPSInst_RT(ir) != 0) {
				DIFROMREG(xcp->regs[MIPSInst_RT(ir)],
@@ -1080,10 +1072,12 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
			break;

		case dmtc_op:
			if (!cpu_has_mips_3_4_5 && !cpu_has_mips64)
				return SIGILL;

			/* copregister fs <- rt */
			DITOREG(xcp->regs[MIPSInst_RT(ir)], MIPSInst_RD(ir));
			break;
#endif

		case mfhc_op:
			if (!cpu_has_mips_r2)
@@ -1173,16 +1167,18 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
		}

		case bc_op:{
			unsigned int cbit;
			int likely = 0;

			if (delay_slot(xcp))
				return SIGILL;

#if __mips >= 4
			cond = ctx->fcr31 & fpucondbit[MIPSInst_RT(ir) >> 2];
#else
			cond = ctx->fcr31 & FPU_CSR_COND;
#endif
			if (cpu_has_mips_4_5_r)
				cbit = fpucondbit[MIPSInst_RT(ir) >> 2];
			else
				cbit = FPU_CSR_COND;
			cond = ctx->fcr31 & cbit;

			switch (MIPSInst_RT(ir) & 3) {
			case bcfl_op:
				likely = 1;
@@ -1235,23 +1231,32 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx,

				switch (MIPSInst_OPCODE(ir)) {
				case lwc1_op:
					goto emul;
				case swc1_op:
#if (__mips >= 2 || defined(__mips64))
					goto emul;
				case ldc1_op:
				case sdc1_op:
#endif
					if (cpu_has_mips_2_3_4_5 ||
					    cpu_has_mips64)
						goto emul;

					return SIGILL;
					goto emul;
				case cop1_op:
#if __mips >= 4 && __mips != 32
					goto emul;
				case cop1x_op:
#endif
					if (cpu_has_mips_4_5 || cpu_has_mips64)
						/* its one of ours */
						goto emul;
#if __mips >= 4

					return SIGILL;
				case spec_op:
					if (!cpu_has_mips_4_5_r)
						return SIGILL;

					if (MIPSInst_FUNC(ir) == movc_op)
						goto emul;
					break;
#endif
				}

				/*
@@ -1291,17 +1296,22 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
		}
		break;

#if __mips >= 4 && __mips != 32
	case cop1x_op:{
		int sig = fpux_emu(xcp, ctx, ir, fault_addr);
		int sig;

		if (!cpu_has_mips_4_5 && !cpu_has_mips64)
			return SIGILL;

		sig = fpux_emu(xcp, ctx, ir, fault_addr);
		if (sig)
			return sig;
		break;
	}
#endif

#if __mips >= 4
	case spec_op:
		if (!cpu_has_mips_4_5_r)
			return SIGILL;

		if (MIPSInst_FUNC(ir) != movc_op)
			return SIGILL;
		cond = fpucondbit[MIPSInst_RT(ir) >> 2];
@@ -1309,8 +1319,6 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
			xcp->regs[MIPSInst_RD(ir)] =
				xcp->regs[MIPSInst_RS(ir)];
		break;
#endif

	default:
sigill:
		return SIGILL;
@@ -1339,8 +1347,6 @@ static const unsigned char cmptab[8] = {
};


#if __mips >= 4 && __mips != 32

/*
 * Additional MIPS4 instructions
 */
@@ -1571,7 +1577,6 @@ static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,

	return 0;
}
#endif



@@ -1588,9 +1593,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
		union ieee754dp d;
		union ieee754sp s;
		int w;
#ifdef __mips64
		s64 l;
#endif
	} rv;			/* resulting value */

	MIPS_FPU_EMU_INC_STATS(cp1ops);
@@ -1617,21 +1620,34 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
			goto scopbop;

			/* unary  ops */
#if __mips >= 2 || defined(__mips64)
		case fsqrt_op:
			if (!cpu_has_mips_4_5_r)
				return SIGILL;

			handler.u = ieee754sp_sqrt;
			goto scopuop;
#endif
#if __mips >= 4 && __mips != 32
		/*
		 * Note that on some MIPS IV implementations such as the
		 * R5000 and R8000 the FSQRT and FRECIP instructions do not
		 * achieve full IEEE-754 accuracy - however this emulator does.
		 */
		case frsqrt_op:
			if (!cpu_has_mips_4_5_r2)
				return SIGILL;

			handler.u = fpemu_sp_rsqrt;
			goto scopuop;
		case frecip_op:
			if (!cpu_has_mips_4_5_r2)
				return SIGILL;

			handler.u = fpemu_sp_recip;
			goto scopuop;
#endif
#if __mips >= 4

		case fmovc_op:
			if (!cpu_has_mips_4_5_r)
				return SIGILL;

			cond = fpucondbit[MIPSInst_FT(ir) >> 2];
			if (((ctx->fcr31 & cond) != 0) !=
				((MIPSInst_FT(ir) & 1) != 0))
@@ -1639,16 +1655,21 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
			SPFROMREG(rv.s, MIPSInst_FS(ir));
			break;
		case fmovz_op:
			if (!cpu_has_mips_4_5_r)
				return SIGILL;

			if (xcp->regs[MIPSInst_FT(ir)] != 0)
				return 0;
			SPFROMREG(rv.s, MIPSInst_FS(ir));
			break;
		case fmovn_op:
			if (!cpu_has_mips_4_5_r)
				return SIGILL;

			if (xcp->regs[MIPSInst_FT(ir)] == 0)
				return 0;
			SPFROMREG(rv.s, MIPSInst_FS(ir));
			break;
#endif
		case fabs_op:
			handler.u = ieee754sp_abs;
			goto scopuop;
@@ -1712,7 +1733,6 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
			goto copcsr;
		}

#if __mips >= 2 || defined(__mips64)
		case fround_op:
		case ftrunc_op:
		case fceil_op:
@@ -1720,6 +1740,9 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
			unsigned int oldrm = ieee754_csr.rm;
			union ieee754sp fs;

			if (!cpu_has_mips_2_3_4_5 && !cpu_has_mips64)
				return SIGILL;

			SPFROMREG(fs, MIPSInst_FS(ir));
			ieee754_csr.rm = ieee_rm[modeindex(MIPSInst_FUNC(ir))];
			rv.w = ieee754sp_tint(fs);
@@ -1727,12 +1750,13 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
			rfmt = w_fmt;
			goto copcsr;
		}
#endif /* __mips >= 2 */

#if defined(__mips64)
		case fcvtl_op:{
			union ieee754sp fs;

			if (!cpu_has_mips_3_4_5 && !cpu_has_mips64)
				return SIGILL;

			SPFROMREG(fs, MIPSInst_FS(ir));
			rv.l = ieee754sp_tlong(fs);
			rfmt = l_fmt;
@@ -1746,6 +1770,9 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
			unsigned int oldrm = ieee754_csr.rm;
			union ieee754sp fs;

			if (!cpu_has_mips_3_4_5 && !cpu_has_mips64)
				return SIGILL;

			SPFROMREG(fs, MIPSInst_FS(ir));
			ieee754_csr.rm = ieee_rm[modeindex(MIPSInst_FUNC(ir))];
			rv.l = ieee754sp_tlong(fs);
@@ -1753,7 +1780,6 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
			rfmt = l_fmt;
			goto copcsr;
		}
#endif /* defined(__mips64) */

		default:
			if (MIPSInst_FUNC(ir) >= fcmp_op) {
@@ -1802,21 +1828,33 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
			goto dcopbop;

			/* unary  ops */
#if __mips >= 2 || defined(__mips64)
		case fsqrt_op:
			if (!cpu_has_mips_2_3_4_5_r)
				return SIGILL;

			handler.u = ieee754dp_sqrt;
			goto dcopuop;
#endif
#if __mips >= 4 && __mips != 32
		/*
		 * Note that on some MIPS IV implementations such as the
		 * R5000 and R8000 the FSQRT and FRECIP instructions do not
		 * achieve full IEEE-754 accuracy - however this emulator does.
		 */
		case frsqrt_op:
			if (!cpu_has_mips_4_5_r2)
				return SIGILL;

			handler.u = fpemu_dp_rsqrt;
			goto dcopuop;
		case frecip_op:
			if (!cpu_has_mips_4_5_r2)
				return SIGILL;

			handler.u = fpemu_dp_recip;
			goto dcopuop;
#endif
#if __mips >= 4
		case fmovc_op:
			if (!cpu_has_mips_4_5_r)
				return SIGILL;

			cond = fpucondbit[MIPSInst_FT(ir) >> 2];
			if (((ctx->fcr31 & cond) != 0) !=
				((MIPSInst_FT(ir) & 1) != 0))
@@ -1824,16 +1862,21 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
			DPFROMREG(rv.d, MIPSInst_FS(ir));
			break;
		case fmovz_op:
			if (!cpu_has_mips_4_5_r)
				return SIGILL;

			if (xcp->regs[MIPSInst_FT(ir)] != 0)
				return 0;
			DPFROMREG(rv.d, MIPSInst_FS(ir));
			break;
		case fmovn_op:
			if (!cpu_has_mips_4_5_r)
				return SIGILL;

			if (xcp->regs[MIPSInst_FT(ir)] == 0)
				return 0;
			DPFROMREG(rv.d, MIPSInst_FS(ir));
			break;
#endif
		case fabs_op:
			handler.u = ieee754dp_abs;
			goto dcopuop;
@@ -1886,7 +1929,6 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
			goto copcsr;
		}

#if __mips >= 2 || defined(__mips64)
		case fround_op:
		case ftrunc_op:
		case fceil_op:
@@ -1894,6 +1936,9 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
			unsigned int oldrm = ieee754_csr.rm;
			union ieee754dp fs;

			if (!cpu_has_mips_2_3_4_5_r)
				return SIGILL;

			DPFROMREG(fs, MIPSInst_FS(ir));
			ieee754_csr.rm = ieee_rm[modeindex(MIPSInst_FUNC(ir))];
			rv.w = ieee754dp_tint(fs);
@@ -1901,12 +1946,13 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
			rfmt = w_fmt;
			goto copcsr;
		}
#endif

#if defined(__mips64)
		case fcvtl_op:{
			union ieee754dp fs;

			if (!cpu_has_mips_3_4_5 && !cpu_has_mips64)
				return SIGILL;

			DPFROMREG(fs, MIPSInst_FS(ir));
			rv.l = ieee754dp_tlong(fs);
			rfmt = l_fmt;
@@ -1920,6 +1966,9 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
			unsigned int oldrm = ieee754_csr.rm;
			union ieee754dp fs;

			if (!cpu_has_mips_3_4_5 && !cpu_has_mips64)
				return SIGILL;

			DPFROMREG(fs, MIPSInst_FS(ir));
			ieee754_csr.rm = ieee_rm[modeindex(MIPSInst_FUNC(ir))];
			rv.l = ieee754dp_tlong(fs);
@@ -1927,7 +1976,6 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
			rfmt = l_fmt;
			goto copcsr;
		}
#endif /* __mips >= 3 */

		default:
			if (MIPSInst_FUNC(ir) >= fcmp_op) {
@@ -1978,9 +2026,12 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
		break;
	}

#if defined(__mips64)
	case l_fmt:{
		u64 bits;

		if (!cpu_has_mips_3_4_5 && !cpu_has_mips64)
			return SIGILL;

		DIFROMREG(bits, MIPSInst_FS(ir));

		switch (MIPSInst_FUNC(ir)) {
@@ -1999,7 +2050,6 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
		}
		break;
	}
#endif

	default:
		return SIGILL;
@@ -2022,18 +2072,19 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
	 * Now we can safely write the result back to the register file.
	 */
	switch (rfmt) {
	case -1:{
#if __mips >= 4
		cond = fpucondbit[MIPSInst_FD(ir) >> 2];
#else
		cond = FPU_CSR_COND;
#endif
		unsigned int cbit;
	case -1:

		if (cpu_has_mips_4_5_r)
			cbit = fpucondbit[MIPSInst_RT(ir) >> 2];
		else
			cbit = FPU_CSR_COND;
		if (rv.w)
			ctx->fcr31 |= cond;
			ctx->fcr31 |= cbit;
		else
			ctx->fcr31 &= ~cond;
			ctx->fcr31 &= ~cbit;
		break;
	}

	case d_fmt:
		DPTOREG(rv.d, MIPSInst_FD(ir));
		break;
@@ -2043,11 +2094,12 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
	case w_fmt:
		SITOREG(rv.w, MIPSInst_FD(ir));
		break;
#if defined(__mips64)
	case l_fmt:
		if (!cpu_has_mips_3_4_5 && !cpu_has_mips64)
			return SIGILL;

		DITOREG(rv.l, MIPSInst_FD(ir));
		break;
#endif
	default:
		return SIGILL;
	}
+5 −6
Original line number Diff line number Diff line
@@ -45,15 +45,14 @@
/* special constants
*/


#if (defined(BYTE_ORDER) && BYTE_ORDER == LITTLE_ENDIAN) || defined(__MIPSEL__)
#define SPSTR(s, b, m) {m, b, s}
#define DPSTR(s, b, mh, ml) {ml, mh, b, s}
#endif

#ifdef __MIPSEB__
#define SPSTR(s, b, m) {s, b, m}
#define DPSTR(s, b, mh, ml) {s, b, mh, ml}
#elif defined(__MIPSEL__)
#define SPSTR(s, b, m) {m, b, s}
#define DPSTR(s, b, mh, ml) {ml, mh, b, s}
#else /* !defined (__MIPSEB__) && !defined (__MIPSEL__) */
#error "MIPS but neither __MIPSEB__ nor __MIPSEL__?"
#endif

const struct ieee754dp_const __ieee754dp_spcvals[] = {