mirror of https://gitee.com/openkylin/linux.git
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: Ralf Baechle <ralf@linux-mips.org>
This commit is contained in:
parent
9e8bad1f9c
commit
08a07904e1
|
@ -183,6 +183,17 @@
|
||||||
/*
|
/*
|
||||||
* Shortcuts ...
|
* 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_mips32 (cpu_has_mips32r1 | cpu_has_mips32r2)
|
||||||
#define cpu_has_mips64 (cpu_has_mips64r1 | cpu_has_mips64r2)
|
#define cpu_has_mips64 (cpu_has_mips64r1 | cpu_has_mips64r2)
|
||||||
#define cpu_has_mips_r1 (cpu_has_mips32r1 | cpu_has_mips64r1)
|
#define cpu_has_mips_r1 (cpu_has_mips32r1 | cpu_has_mips64r1)
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
*/
|
*/
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
#include <linux/debugfs.h>
|
#include <linux/debugfs.h>
|
||||||
|
#include <linux/kconfig.h>
|
||||||
#include <linux/percpu-defs.h>
|
#include <linux/percpu-defs.h>
|
||||||
#include <linux/perf_event.h>
|
#include <linux/perf_event.h>
|
||||||
|
|
||||||
|
@ -50,22 +51,13 @@
|
||||||
|
|
||||||
#include "ieee754.h"
|
#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. */
|
/* Function which emulates a floating point instruction. */
|
||||||
|
|
||||||
static int fpu_emu(struct pt_regs *, struct mips_fpu_struct *,
|
static int fpu_emu(struct pt_regs *, struct mips_fpu_struct *,
|
||||||
mips_instruction);
|
mips_instruction);
|
||||||
|
|
||||||
#if __mips >= 4 && __mips != 32
|
|
||||||
static int fpux_emu(struct pt_regs *,
|
static int fpux_emu(struct pt_regs *,
|
||||||
struct mips_fpu_struct *, mips_instruction, void *__user *);
|
struct mips_fpu_struct *, mips_instruction, void *__user *);
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Control registers */
|
/* Control registers */
|
||||||
|
|
||||||
|
@ -95,7 +87,6 @@ static const unsigned char mips_rm[4] = {
|
||||||
[IEEE754_RU] = FPU_CSR_RU,
|
[IEEE754_RU] = FPU_CSR_RU,
|
||||||
};
|
};
|
||||||
|
|
||||||
#if __mips >= 4
|
|
||||||
/* convert condition code register number to csr bit */
|
/* convert condition code register number to csr bit */
|
||||||
static const unsigned int fpucondbit[8] = {
|
static const unsigned int fpucondbit[8] = {
|
||||||
FPU_CSR_COND0,
|
FPU_CSR_COND0,
|
||||||
|
@ -107,7 +98,6 @@ static const unsigned int fpucondbit[8] = {
|
||||||
FPU_CSR_COND6,
|
FPU_CSR_COND6,
|
||||||
FPU_CSR_COND7
|
FPU_CSR_COND7
|
||||||
};
|
};
|
||||||
#endif
|
|
||||||
|
|
||||||
/* (microMIPS) Convert 16-bit register encoding to 32-bit register encoding. */
|
/* (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};
|
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)
|
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;
|
return 1;
|
||||||
#elif defined(CONFIG_32BIT) && !defined(CONFIG_MIPS_O32_FP64_SUPPORT)
|
else if (config_enabled(CONFIG_32BIT) &&
|
||||||
return 0;
|
!config_enabled(CONFIG_MIPS_O32_FP64_SUPPORT))
|
||||||
#else
|
return 0;
|
||||||
|
|
||||||
return !test_thread_flag(TIF_32BIT_FPREGS);
|
return !test_thread_flag(TIF_32BIT_FPREGS);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define SIFROMREG(si, x) \
|
#define SIFROMREG(si, x) \
|
||||||
|
@ -1070,8 +1060,10 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
|
||||||
case cop1_op:
|
case cop1_op:
|
||||||
switch (MIPSInst_RS(ir)) {
|
switch (MIPSInst_RS(ir)) {
|
||||||
|
|
||||||
#if defined(__mips64)
|
|
||||||
case dmfc_op:
|
case dmfc_op:
|
||||||
|
if (!cpu_has_mips_3_4_5 && !cpu_has_mips64)
|
||||||
|
return SIGILL;
|
||||||
|
|
||||||
/* copregister fs -> gpr[rt] */
|
/* copregister fs -> gpr[rt] */
|
||||||
if (MIPSInst_RT(ir) != 0) {
|
if (MIPSInst_RT(ir) != 0) {
|
||||||
DIFROMREG(xcp->regs[MIPSInst_RT(ir)],
|
DIFROMREG(xcp->regs[MIPSInst_RT(ir)],
|
||||||
|
@ -1080,10 +1072,12 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case dmtc_op:
|
case dmtc_op:
|
||||||
|
if (!cpu_has_mips_3_4_5 && !cpu_has_mips64)
|
||||||
|
return SIGILL;
|
||||||
|
|
||||||
/* copregister fs <- rt */
|
/* copregister fs <- rt */
|
||||||
DITOREG(xcp->regs[MIPSInst_RT(ir)], MIPSInst_RD(ir));
|
DITOREG(xcp->regs[MIPSInst_RT(ir)], MIPSInst_RD(ir));
|
||||||
break;
|
break;
|
||||||
#endif
|
|
||||||
|
|
||||||
case mfhc_op:
|
case mfhc_op:
|
||||||
if (!cpu_has_mips_r2)
|
if (!cpu_has_mips_r2)
|
||||||
|
@ -1173,16 +1167,18 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
|
||||||
}
|
}
|
||||||
|
|
||||||
case bc_op:{
|
case bc_op:{
|
||||||
|
unsigned int cbit;
|
||||||
int likely = 0;
|
int likely = 0;
|
||||||
|
|
||||||
if (delay_slot(xcp))
|
if (delay_slot(xcp))
|
||||||
return SIGILL;
|
return SIGILL;
|
||||||
|
|
||||||
#if __mips >= 4
|
if (cpu_has_mips_4_5_r)
|
||||||
cond = ctx->fcr31 & fpucondbit[MIPSInst_RT(ir) >> 2];
|
cbit = fpucondbit[MIPSInst_RT(ir) >> 2];
|
||||||
#else
|
else
|
||||||
cond = ctx->fcr31 & FPU_CSR_COND;
|
cbit = FPU_CSR_COND;
|
||||||
#endif
|
cond = ctx->fcr31 & cbit;
|
||||||
|
|
||||||
switch (MIPSInst_RT(ir) & 3) {
|
switch (MIPSInst_RT(ir) & 3) {
|
||||||
case bcfl_op:
|
case bcfl_op:
|
||||||
likely = 1;
|
likely = 1;
|
||||||
|
@ -1235,23 +1231,32 @@ 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:
|
||||||
#if (__mips >= 2 || defined(__mips64))
|
goto emul;
|
||||||
case ldc1_op:
|
case ldc1_op:
|
||||||
case sdc1_op:
|
case sdc1_op:
|
||||||
#endif
|
if (cpu_has_mips_2_3_4_5 ||
|
||||||
case cop1_op:
|
cpu_has_mips64)
|
||||||
#if __mips >= 4 && __mips != 32
|
goto emul;
|
||||||
case cop1x_op:
|
|
||||||
#endif
|
return SIGILL;
|
||||||
/* its one of ours */
|
|
||||||
goto emul;
|
goto emul;
|
||||||
#if __mips >= 4
|
case cop1_op:
|
||||||
|
goto emul;
|
||||||
|
case cop1x_op:
|
||||||
|
if (cpu_has_mips_4_5 || cpu_has_mips64)
|
||||||
|
/* its one of ours */
|
||||||
|
goto emul;
|
||||||
|
|
||||||
|
return SIGILL;
|
||||||
case spec_op:
|
case spec_op:
|
||||||
|
if (!cpu_has_mips_4_5_r)
|
||||||
|
return SIGILL;
|
||||||
|
|
||||||
if (MIPSInst_FUNC(ir) == movc_op)
|
if (MIPSInst_FUNC(ir) == movc_op)
|
||||||
goto emul;
|
goto emul;
|
||||||
break;
|
break;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1291,17 +1296,22 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
#if __mips >= 4 && __mips != 32
|
|
||||||
case cop1x_op:{
|
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)
|
if (sig)
|
||||||
return sig;
|
return sig;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
#if __mips >= 4
|
|
||||||
case spec_op:
|
case spec_op:
|
||||||
|
if (!cpu_has_mips_4_5_r)
|
||||||
|
return SIGILL;
|
||||||
|
|
||||||
if (MIPSInst_FUNC(ir) != movc_op)
|
if (MIPSInst_FUNC(ir) != movc_op)
|
||||||
return SIGILL;
|
return SIGILL;
|
||||||
cond = fpucondbit[MIPSInst_RT(ir) >> 2];
|
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_RD(ir)] =
|
||||||
xcp->regs[MIPSInst_RS(ir)];
|
xcp->regs[MIPSInst_RS(ir)];
|
||||||
break;
|
break;
|
||||||
#endif
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
sigill:
|
sigill:
|
||||||
return SIGILL;
|
return SIGILL;
|
||||||
|
@ -1339,8 +1347,6 @@ static const unsigned char cmptab[8] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#if __mips >= 4 && __mips != 32
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Additional MIPS4 instructions
|
* Additional MIPS4 instructions
|
||||||
*/
|
*/
|
||||||
|
@ -1571,7 +1577,6 @@ static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -1588,9 +1593,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
|
||||||
union ieee754dp d;
|
union ieee754dp d;
|
||||||
union ieee754sp s;
|
union ieee754sp s;
|
||||||
int w;
|
int w;
|
||||||
#ifdef __mips64
|
|
||||||
s64 l;
|
s64 l;
|
||||||
#endif
|
|
||||||
} rv; /* resulting value */
|
} rv; /* resulting value */
|
||||||
|
|
||||||
MIPS_FPU_EMU_INC_STATS(cp1ops);
|
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;
|
goto scopbop;
|
||||||
|
|
||||||
/* unary ops */
|
/* unary ops */
|
||||||
#if __mips >= 2 || defined(__mips64)
|
|
||||||
case fsqrt_op:
|
case fsqrt_op:
|
||||||
|
if (!cpu_has_mips_4_5_r)
|
||||||
|
return SIGILL;
|
||||||
|
|
||||||
handler.u = ieee754sp_sqrt;
|
handler.u = ieee754sp_sqrt;
|
||||||
goto scopuop;
|
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:
|
case frsqrt_op:
|
||||||
|
if (!cpu_has_mips_4_5_r2)
|
||||||
|
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)
|
||||||
|
return SIGILL;
|
||||||
|
|
||||||
handler.u = fpemu_sp_recip;
|
handler.u = fpemu_sp_recip;
|
||||||
goto scopuop;
|
goto scopuop;
|
||||||
#endif
|
|
||||||
#if __mips >= 4
|
|
||||||
case fmovc_op:
|
case fmovc_op:
|
||||||
|
if (!cpu_has_mips_4_5_r)
|
||||||
|
return SIGILL;
|
||||||
|
|
||||||
cond = fpucondbit[MIPSInst_FT(ir) >> 2];
|
cond = fpucondbit[MIPSInst_FT(ir) >> 2];
|
||||||
if (((ctx->fcr31 & cond) != 0) !=
|
if (((ctx->fcr31 & cond) != 0) !=
|
||||||
((MIPSInst_FT(ir) & 1) != 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));
|
SPFROMREG(rv.s, MIPSInst_FS(ir));
|
||||||
break;
|
break;
|
||||||
case fmovz_op:
|
case fmovz_op:
|
||||||
|
if (!cpu_has_mips_4_5_r)
|
||||||
|
return SIGILL;
|
||||||
|
|
||||||
if (xcp->regs[MIPSInst_FT(ir)] != 0)
|
if (xcp->regs[MIPSInst_FT(ir)] != 0)
|
||||||
return 0;
|
return 0;
|
||||||
SPFROMREG(rv.s, MIPSInst_FS(ir));
|
SPFROMREG(rv.s, MIPSInst_FS(ir));
|
||||||
break;
|
break;
|
||||||
case fmovn_op:
|
case fmovn_op:
|
||||||
|
if (!cpu_has_mips_4_5_r)
|
||||||
|
return SIGILL;
|
||||||
|
|
||||||
if (xcp->regs[MIPSInst_FT(ir)] == 0)
|
if (xcp->regs[MIPSInst_FT(ir)] == 0)
|
||||||
return 0;
|
return 0;
|
||||||
SPFROMREG(rv.s, MIPSInst_FS(ir));
|
SPFROMREG(rv.s, MIPSInst_FS(ir));
|
||||||
break;
|
break;
|
||||||
#endif
|
|
||||||
case fabs_op:
|
case fabs_op:
|
||||||
handler.u = ieee754sp_abs;
|
handler.u = ieee754sp_abs;
|
||||||
goto scopuop;
|
goto scopuop;
|
||||||
|
@ -1712,7 +1733,6 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
|
||||||
goto copcsr;
|
goto copcsr;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if __mips >= 2 || defined(__mips64)
|
|
||||||
case fround_op:
|
case fround_op:
|
||||||
case ftrunc_op:
|
case ftrunc_op:
|
||||||
case fceil_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;
|
unsigned int oldrm = ieee754_csr.rm;
|
||||||
union ieee754sp fs;
|
union ieee754sp fs;
|
||||||
|
|
||||||
|
if (!cpu_has_mips_2_3_4_5 && !cpu_has_mips64)
|
||||||
|
return SIGILL;
|
||||||
|
|
||||||
SPFROMREG(fs, MIPSInst_FS(ir));
|
SPFROMREG(fs, MIPSInst_FS(ir));
|
||||||
ieee754_csr.rm = ieee_rm[modeindex(MIPSInst_FUNC(ir))];
|
ieee754_csr.rm = ieee_rm[modeindex(MIPSInst_FUNC(ir))];
|
||||||
rv.w = ieee754sp_tint(fs);
|
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;
|
rfmt = w_fmt;
|
||||||
goto copcsr;
|
goto copcsr;
|
||||||
}
|
}
|
||||||
#endif /* __mips >= 2 */
|
|
||||||
|
|
||||||
#if defined(__mips64)
|
|
||||||
case fcvtl_op:{
|
case fcvtl_op:{
|
||||||
union ieee754sp fs;
|
union ieee754sp fs;
|
||||||
|
|
||||||
|
if (!cpu_has_mips_3_4_5 && !cpu_has_mips64)
|
||||||
|
return SIGILL;
|
||||||
|
|
||||||
SPFROMREG(fs, MIPSInst_FS(ir));
|
SPFROMREG(fs, MIPSInst_FS(ir));
|
||||||
rv.l = ieee754sp_tlong(fs);
|
rv.l = ieee754sp_tlong(fs);
|
||||||
rfmt = l_fmt;
|
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;
|
unsigned int oldrm = ieee754_csr.rm;
|
||||||
union ieee754sp fs;
|
union ieee754sp fs;
|
||||||
|
|
||||||
|
if (!cpu_has_mips_3_4_5 && !cpu_has_mips64)
|
||||||
|
return SIGILL;
|
||||||
|
|
||||||
SPFROMREG(fs, MIPSInst_FS(ir));
|
SPFROMREG(fs, MIPSInst_FS(ir));
|
||||||
ieee754_csr.rm = ieee_rm[modeindex(MIPSInst_FUNC(ir))];
|
ieee754_csr.rm = ieee_rm[modeindex(MIPSInst_FUNC(ir))];
|
||||||
rv.l = ieee754sp_tlong(fs);
|
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;
|
rfmt = l_fmt;
|
||||||
goto copcsr;
|
goto copcsr;
|
||||||
}
|
}
|
||||||
#endif /* defined(__mips64) */
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (MIPSInst_FUNC(ir) >= fcmp_op) {
|
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;
|
goto dcopbop;
|
||||||
|
|
||||||
/* unary ops */
|
/* unary ops */
|
||||||
#if __mips >= 2 || defined(__mips64)
|
|
||||||
case fsqrt_op:
|
case fsqrt_op:
|
||||||
|
if (!cpu_has_mips_2_3_4_5_r)
|
||||||
|
return SIGILL;
|
||||||
|
|
||||||
handler.u = ieee754dp_sqrt;
|
handler.u = ieee754dp_sqrt;
|
||||||
goto dcopuop;
|
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:
|
case frsqrt_op:
|
||||||
|
if (!cpu_has_mips_4_5_r2)
|
||||||
|
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)
|
||||||
|
return SIGILL;
|
||||||
|
|
||||||
handler.u = fpemu_dp_recip;
|
handler.u = fpemu_dp_recip;
|
||||||
goto dcopuop;
|
goto dcopuop;
|
||||||
#endif
|
|
||||||
#if __mips >= 4
|
|
||||||
case fmovc_op:
|
case fmovc_op:
|
||||||
|
if (!cpu_has_mips_4_5_r)
|
||||||
|
return SIGILL;
|
||||||
|
|
||||||
cond = fpucondbit[MIPSInst_FT(ir) >> 2];
|
cond = fpucondbit[MIPSInst_FT(ir) >> 2];
|
||||||
if (((ctx->fcr31 & cond) != 0) !=
|
if (((ctx->fcr31 & cond) != 0) !=
|
||||||
((MIPSInst_FT(ir) & 1) != 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));
|
DPFROMREG(rv.d, MIPSInst_FS(ir));
|
||||||
break;
|
break;
|
||||||
case fmovz_op:
|
case fmovz_op:
|
||||||
|
if (!cpu_has_mips_4_5_r)
|
||||||
|
return SIGILL;
|
||||||
|
|
||||||
if (xcp->regs[MIPSInst_FT(ir)] != 0)
|
if (xcp->regs[MIPSInst_FT(ir)] != 0)
|
||||||
return 0;
|
return 0;
|
||||||
DPFROMREG(rv.d, MIPSInst_FS(ir));
|
DPFROMREG(rv.d, MIPSInst_FS(ir));
|
||||||
break;
|
break;
|
||||||
case fmovn_op:
|
case fmovn_op:
|
||||||
|
if (!cpu_has_mips_4_5_r)
|
||||||
|
return SIGILL;
|
||||||
|
|
||||||
if (xcp->regs[MIPSInst_FT(ir)] == 0)
|
if (xcp->regs[MIPSInst_FT(ir)] == 0)
|
||||||
return 0;
|
return 0;
|
||||||
DPFROMREG(rv.d, MIPSInst_FS(ir));
|
DPFROMREG(rv.d, MIPSInst_FS(ir));
|
||||||
break;
|
break;
|
||||||
#endif
|
|
||||||
case fabs_op:
|
case fabs_op:
|
||||||
handler.u = ieee754dp_abs;
|
handler.u = ieee754dp_abs;
|
||||||
goto dcopuop;
|
goto dcopuop;
|
||||||
|
@ -1886,7 +1929,6 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
|
||||||
goto copcsr;
|
goto copcsr;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if __mips >= 2 || defined(__mips64)
|
|
||||||
case fround_op:
|
case fround_op:
|
||||||
case ftrunc_op:
|
case ftrunc_op:
|
||||||
case fceil_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;
|
unsigned int oldrm = ieee754_csr.rm;
|
||||||
union ieee754dp fs;
|
union ieee754dp fs;
|
||||||
|
|
||||||
|
if (!cpu_has_mips_2_3_4_5_r)
|
||||||
|
return SIGILL;
|
||||||
|
|
||||||
DPFROMREG(fs, MIPSInst_FS(ir));
|
DPFROMREG(fs, MIPSInst_FS(ir));
|
||||||
ieee754_csr.rm = ieee_rm[modeindex(MIPSInst_FUNC(ir))];
|
ieee754_csr.rm = ieee_rm[modeindex(MIPSInst_FUNC(ir))];
|
||||||
rv.w = ieee754dp_tint(fs);
|
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;
|
rfmt = w_fmt;
|
||||||
goto copcsr;
|
goto copcsr;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(__mips64)
|
|
||||||
case fcvtl_op:{
|
case fcvtl_op:{
|
||||||
union ieee754dp fs;
|
union ieee754dp fs;
|
||||||
|
|
||||||
|
if (!cpu_has_mips_3_4_5 && !cpu_has_mips64)
|
||||||
|
return SIGILL;
|
||||||
|
|
||||||
DPFROMREG(fs, MIPSInst_FS(ir));
|
DPFROMREG(fs, MIPSInst_FS(ir));
|
||||||
rv.l = ieee754dp_tlong(fs);
|
rv.l = ieee754dp_tlong(fs);
|
||||||
rfmt = l_fmt;
|
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;
|
unsigned int oldrm = ieee754_csr.rm;
|
||||||
union ieee754dp fs;
|
union ieee754dp fs;
|
||||||
|
|
||||||
|
if (!cpu_has_mips_3_4_5 && !cpu_has_mips64)
|
||||||
|
return SIGILL;
|
||||||
|
|
||||||
DPFROMREG(fs, MIPSInst_FS(ir));
|
DPFROMREG(fs, MIPSInst_FS(ir));
|
||||||
ieee754_csr.rm = ieee_rm[modeindex(MIPSInst_FUNC(ir))];
|
ieee754_csr.rm = ieee_rm[modeindex(MIPSInst_FUNC(ir))];
|
||||||
rv.l = ieee754dp_tlong(fs);
|
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;
|
rfmt = l_fmt;
|
||||||
goto copcsr;
|
goto copcsr;
|
||||||
}
|
}
|
||||||
#endif /* __mips >= 3 */
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (MIPSInst_FUNC(ir) >= fcmp_op) {
|
if (MIPSInst_FUNC(ir) >= fcmp_op) {
|
||||||
|
@ -1978,9 +2026,12 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(__mips64)
|
|
||||||
case l_fmt:{
|
case l_fmt:{
|
||||||
u64 bits;
|
u64 bits;
|
||||||
|
|
||||||
|
if (!cpu_has_mips_3_4_5 && !cpu_has_mips64)
|
||||||
|
return SIGILL;
|
||||||
|
|
||||||
DIFROMREG(bits, MIPSInst_FS(ir));
|
DIFROMREG(bits, MIPSInst_FS(ir));
|
||||||
|
|
||||||
switch (MIPSInst_FUNC(ir)) {
|
switch (MIPSInst_FUNC(ir)) {
|
||||||
|
@ -1999,7 +2050,6 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return SIGILL;
|
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.
|
* Now we can safely write the result back to the register file.
|
||||||
*/
|
*/
|
||||||
switch (rfmt) {
|
switch (rfmt) {
|
||||||
case -1:{
|
unsigned int cbit;
|
||||||
#if __mips >= 4
|
case -1:
|
||||||
cond = fpucondbit[MIPSInst_FD(ir) >> 2];
|
|
||||||
#else
|
if (cpu_has_mips_4_5_r)
|
||||||
cond = FPU_CSR_COND;
|
cbit = fpucondbit[MIPSInst_RT(ir) >> 2];
|
||||||
#endif
|
|
||||||
if (rv.w)
|
|
||||||
ctx->fcr31 |= cond;
|
|
||||||
else
|
else
|
||||||
ctx->fcr31 &= ~cond;
|
cbit = FPU_CSR_COND;
|
||||||
|
if (rv.w)
|
||||||
|
ctx->fcr31 |= cbit;
|
||||||
|
else
|
||||||
|
ctx->fcr31 &= ~cbit;
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
case d_fmt:
|
case d_fmt:
|
||||||
DPTOREG(rv.d, MIPSInst_FD(ir));
|
DPTOREG(rv.d, MIPSInst_FD(ir));
|
||||||
break;
|
break;
|
||||||
|
@ -2043,11 +2094,12 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
|
||||||
case w_fmt:
|
case w_fmt:
|
||||||
SITOREG(rv.w, MIPSInst_FD(ir));
|
SITOREG(rv.w, MIPSInst_FD(ir));
|
||||||
break;
|
break;
|
||||||
#if defined(__mips64)
|
|
||||||
case l_fmt:
|
case l_fmt:
|
||||||
|
if (!cpu_has_mips_3_4_5 && !cpu_has_mips64)
|
||||||
|
return SIGILL;
|
||||||
|
|
||||||
DITOREG(rv.l, MIPSInst_FD(ir));
|
DITOREG(rv.l, MIPSInst_FD(ir));
|
||||||
break;
|
break;
|
||||||
#endif
|
|
||||||
default:
|
default:
|
||||||
return SIGILL;
|
return SIGILL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,15 +45,14 @@
|
||||||
/* special constants
|
/* 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__
|
#ifdef __MIPSEB__
|
||||||
#define SPSTR(s, b, m) {s, b, m}
|
#define SPSTR(s, b, m) {s, b, m}
|
||||||
#define DPSTR(s, b, mh, ml) {s, b, mh, ml}
|
#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
|
#endif
|
||||||
|
|
||||||
const struct ieee754dp_const __ieee754dp_spcvals[] = {
|
const struct ieee754dp_const __ieee754dp_spcvals[] = {
|
||||||
|
|
Loading…
Reference in New Issue