target-mips: raise RI exceptions when FIR.PS = 0
64-bit paired-single (PS) floating point data type is optional in the pre-Release 6. It has to raise RI exception when PS type is not implemented. (FIR.PS = 0) (The PS data type is removed in the Release 6.) Loongson-2E and Loongson-2F don't have any implementation field in FCSR0(FIR) but do support PS data format, therefore for these cores RI will not be signalled regardless of PS bit. Signed-off-by: Yongbok Kim <yongbok.kim@imgtec.com> Reviewed-by: Leon Alrae <leon.alrae@imgtec.com> Reviewed-by: Aurelien Jarno <aurelien@aurel32.net> Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
This commit is contained in:
parent
6893f07466
commit
e29c962804
@ -1430,6 +1430,7 @@ typedef struct DisasContext {
|
||||
uint64_t PAMask;
|
||||
bool mvh;
|
||||
int CP0_LLAddr_shift;
|
||||
bool ps;
|
||||
} DisasContext;
|
||||
|
||||
enum {
|
||||
@ -1826,6 +1827,16 @@ static inline void check_insn_opc_removed(DisasContext *ctx, int flags)
|
||||
}
|
||||
}
|
||||
|
||||
/* This code generates a "reserved instruction" exception if the
|
||||
CPU does not support 64-bit paired-single (PS) floating point data type */
|
||||
static inline void check_ps(DisasContext *ctx)
|
||||
{
|
||||
if (unlikely(!ctx->ps)) {
|
||||
generate_exception(ctx, EXCP_RI);
|
||||
}
|
||||
check_cp1_64bitmode(ctx);
|
||||
}
|
||||
|
||||
#ifdef TARGET_MIPS64
|
||||
/* This code generates a "reserved instruction" exception if 64-bit
|
||||
instructions are not enabled. */
|
||||
@ -1859,7 +1870,7 @@ static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \
|
||||
TCGv_i##bits fp1 = tcg_temp_new_i##bits (); \
|
||||
switch (ifmt) { \
|
||||
case FMT_PS: \
|
||||
check_cp1_64bitmode(ctx); \
|
||||
check_ps(ctx); \
|
||||
break; \
|
||||
case FMT_D: \
|
||||
if (abs) { \
|
||||
@ -8999,7 +9010,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1,
|
||||
};
|
||||
enum { BINOP, CMPOP, OTHEROP } optype = OTHEROP;
|
||||
uint32_t func = ctx->opcode & 0x3f;
|
||||
|
||||
switch (op1) {
|
||||
case OPC_ADD_S:
|
||||
{
|
||||
@ -9492,8 +9502,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1,
|
||||
opn = "cvt.l.s";
|
||||
break;
|
||||
case OPC_CVT_PS_S:
|
||||
check_insn_opc_removed(ctx, ISA_MIPS32R6);
|
||||
check_cp1_64bitmode(ctx);
|
||||
check_ps(ctx);
|
||||
{
|
||||
TCGv_i64 fp64 = tcg_temp_new_i64();
|
||||
TCGv_i32 fp32_0 = tcg_temp_new_i32();
|
||||
@ -10110,8 +10119,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1,
|
||||
opn = "cvt.d.l";
|
||||
break;
|
||||
case OPC_CVT_PS_PW:
|
||||
check_insn_opc_removed(ctx, ISA_MIPS32R6);
|
||||
check_cp1_64bitmode(ctx);
|
||||
check_ps(ctx);
|
||||
{
|
||||
TCGv_i64 fp0 = tcg_temp_new_i64();
|
||||
|
||||
@ -10123,7 +10131,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1,
|
||||
opn = "cvt.ps.pw";
|
||||
break;
|
||||
case OPC_ADD_PS:
|
||||
check_cp1_64bitmode(ctx);
|
||||
check_ps(ctx);
|
||||
{
|
||||
TCGv_i64 fp0 = tcg_temp_new_i64();
|
||||
TCGv_i64 fp1 = tcg_temp_new_i64();
|
||||
@ -10138,7 +10146,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1,
|
||||
opn = "add.ps";
|
||||
break;
|
||||
case OPC_SUB_PS:
|
||||
check_cp1_64bitmode(ctx);
|
||||
check_ps(ctx);
|
||||
{
|
||||
TCGv_i64 fp0 = tcg_temp_new_i64();
|
||||
TCGv_i64 fp1 = tcg_temp_new_i64();
|
||||
@ -10153,7 +10161,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1,
|
||||
opn = "sub.ps";
|
||||
break;
|
||||
case OPC_MUL_PS:
|
||||
check_cp1_64bitmode(ctx);
|
||||
check_ps(ctx);
|
||||
{
|
||||
TCGv_i64 fp0 = tcg_temp_new_i64();
|
||||
TCGv_i64 fp1 = tcg_temp_new_i64();
|
||||
@ -10168,7 +10176,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1,
|
||||
opn = "mul.ps";
|
||||
break;
|
||||
case OPC_ABS_PS:
|
||||
check_cp1_64bitmode(ctx);
|
||||
check_ps(ctx);
|
||||
{
|
||||
TCGv_i64 fp0 = tcg_temp_new_i64();
|
||||
|
||||
@ -10180,7 +10188,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1,
|
||||
opn = "abs.ps";
|
||||
break;
|
||||
case OPC_MOV_PS:
|
||||
check_cp1_64bitmode(ctx);
|
||||
check_ps(ctx);
|
||||
{
|
||||
TCGv_i64 fp0 = tcg_temp_new_i64();
|
||||
|
||||
@ -10191,7 +10199,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1,
|
||||
opn = "mov.ps";
|
||||
break;
|
||||
case OPC_NEG_PS:
|
||||
check_cp1_64bitmode(ctx);
|
||||
check_ps(ctx);
|
||||
{
|
||||
TCGv_i64 fp0 = tcg_temp_new_i64();
|
||||
|
||||
@ -10203,12 +10211,12 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1,
|
||||
opn = "neg.ps";
|
||||
break;
|
||||
case OPC_MOVCF_PS:
|
||||
check_cp1_64bitmode(ctx);
|
||||
check_ps(ctx);
|
||||
gen_movcf_ps(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
|
||||
opn = "movcf.ps";
|
||||
break;
|
||||
case OPC_MOVZ_PS:
|
||||
check_cp1_64bitmode(ctx);
|
||||
check_ps(ctx);
|
||||
{
|
||||
TCGLabel *l1 = gen_new_label();
|
||||
TCGv_i64 fp0;
|
||||
@ -10224,7 +10232,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1,
|
||||
opn = "movz.ps";
|
||||
break;
|
||||
case OPC_MOVN_PS:
|
||||
check_cp1_64bitmode(ctx);
|
||||
check_ps(ctx);
|
||||
{
|
||||
TCGLabel *l1 = gen_new_label();
|
||||
TCGv_i64 fp0;
|
||||
@ -10241,7 +10249,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1,
|
||||
opn = "movn.ps";
|
||||
break;
|
||||
case OPC_ADDR_PS:
|
||||
check_cp1_64bitmode(ctx);
|
||||
check_ps(ctx);
|
||||
{
|
||||
TCGv_i64 fp0 = tcg_temp_new_i64();
|
||||
TCGv_i64 fp1 = tcg_temp_new_i64();
|
||||
@ -10256,7 +10264,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1,
|
||||
opn = "addr.ps";
|
||||
break;
|
||||
case OPC_MULR_PS:
|
||||
check_cp1_64bitmode(ctx);
|
||||
check_ps(ctx);
|
||||
{
|
||||
TCGv_i64 fp0 = tcg_temp_new_i64();
|
||||
TCGv_i64 fp1 = tcg_temp_new_i64();
|
||||
@ -10271,7 +10279,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1,
|
||||
opn = "mulr.ps";
|
||||
break;
|
||||
case OPC_RECIP2_PS:
|
||||
check_cp1_64bitmode(ctx);
|
||||
check_ps(ctx);
|
||||
{
|
||||
TCGv_i64 fp0 = tcg_temp_new_i64();
|
||||
TCGv_i64 fp1 = tcg_temp_new_i64();
|
||||
@ -10286,7 +10294,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1,
|
||||
opn = "recip2.ps";
|
||||
break;
|
||||
case OPC_RECIP1_PS:
|
||||
check_cp1_64bitmode(ctx);
|
||||
check_ps(ctx);
|
||||
{
|
||||
TCGv_i64 fp0 = tcg_temp_new_i64();
|
||||
|
||||
@ -10298,7 +10306,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1,
|
||||
opn = "recip1.ps";
|
||||
break;
|
||||
case OPC_RSQRT1_PS:
|
||||
check_cp1_64bitmode(ctx);
|
||||
check_ps(ctx);
|
||||
{
|
||||
TCGv_i64 fp0 = tcg_temp_new_i64();
|
||||
|
||||
@ -10310,7 +10318,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1,
|
||||
opn = "rsqrt1.ps";
|
||||
break;
|
||||
case OPC_RSQRT2_PS:
|
||||
check_cp1_64bitmode(ctx);
|
||||
check_ps(ctx);
|
||||
{
|
||||
TCGv_i64 fp0 = tcg_temp_new_i64();
|
||||
TCGv_i64 fp1 = tcg_temp_new_i64();
|
||||
@ -10337,7 +10345,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1,
|
||||
opn = "cvt.s.pu";
|
||||
break;
|
||||
case OPC_CVT_PW_PS:
|
||||
check_cp1_64bitmode(ctx);
|
||||
check_ps(ctx);
|
||||
{
|
||||
TCGv_i64 fp0 = tcg_temp_new_i64();
|
||||
|
||||
@ -10361,7 +10369,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1,
|
||||
opn = "cvt.s.pl";
|
||||
break;
|
||||
case OPC_PLL_PS:
|
||||
check_cp1_64bitmode(ctx);
|
||||
check_ps(ctx);
|
||||
{
|
||||
TCGv_i32 fp0 = tcg_temp_new_i32();
|
||||
TCGv_i32 fp1 = tcg_temp_new_i32();
|
||||
@ -10376,7 +10384,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1,
|
||||
opn = "pll.ps";
|
||||
break;
|
||||
case OPC_PLU_PS:
|
||||
check_cp1_64bitmode(ctx);
|
||||
check_ps(ctx);
|
||||
{
|
||||
TCGv_i32 fp0 = tcg_temp_new_i32();
|
||||
TCGv_i32 fp1 = tcg_temp_new_i32();
|
||||
@ -10391,7 +10399,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1,
|
||||
opn = "plu.ps";
|
||||
break;
|
||||
case OPC_PUL_PS:
|
||||
check_cp1_64bitmode(ctx);
|
||||
check_ps(ctx);
|
||||
{
|
||||
TCGv_i32 fp0 = tcg_temp_new_i32();
|
||||
TCGv_i32 fp1 = tcg_temp_new_i32();
|
||||
@ -10406,7 +10414,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1,
|
||||
opn = "pul.ps";
|
||||
break;
|
||||
case OPC_PUU_PS:
|
||||
check_cp1_64bitmode(ctx);
|
||||
check_ps(ctx);
|
||||
{
|
||||
TCGv_i32 fp0 = tcg_temp_new_i32();
|
||||
TCGv_i32 fp1 = tcg_temp_new_i32();
|
||||
@ -10565,7 +10573,7 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
|
||||
|
||||
switch (opc) {
|
||||
case OPC_ALNV_PS:
|
||||
check_cp1_64bitmode(ctx);
|
||||
check_ps(ctx);
|
||||
{
|
||||
TCGv t0 = tcg_temp_local_new();
|
||||
TCGv_i32 fp = tcg_temp_new_i32();
|
||||
@ -10640,7 +10648,7 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
|
||||
opn = "madd.d";
|
||||
break;
|
||||
case OPC_MADD_PS:
|
||||
check_cp1_64bitmode(ctx);
|
||||
check_ps(ctx);
|
||||
{
|
||||
TCGv_i64 fp0 = tcg_temp_new_i64();
|
||||
TCGv_i64 fp1 = tcg_temp_new_i64();
|
||||
@ -10695,7 +10703,7 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
|
||||
opn = "msub.d";
|
||||
break;
|
||||
case OPC_MSUB_PS:
|
||||
check_cp1_64bitmode(ctx);
|
||||
check_ps(ctx);
|
||||
{
|
||||
TCGv_i64 fp0 = tcg_temp_new_i64();
|
||||
TCGv_i64 fp1 = tcg_temp_new_i64();
|
||||
@ -10750,7 +10758,7 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
|
||||
opn = "nmadd.d";
|
||||
break;
|
||||
case OPC_NMADD_PS:
|
||||
check_cp1_64bitmode(ctx);
|
||||
check_ps(ctx);
|
||||
{
|
||||
TCGv_i64 fp0 = tcg_temp_new_i64();
|
||||
TCGv_i64 fp1 = tcg_temp_new_i64();
|
||||
@ -10805,7 +10813,7 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
|
||||
opn = "nmsub.d";
|
||||
break;
|
||||
case OPC_NMSUB_PS:
|
||||
check_cp1_64bitmode(ctx);
|
||||
check_ps(ctx);
|
||||
{
|
||||
TCGv_i64 fp0 = tcg_temp_new_i64();
|
||||
TCGv_i64 fp1 = tcg_temp_new_i64();
|
||||
@ -14118,6 +14126,7 @@ static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx)
|
||||
gen_movcf_d(ctx, rs, rt, cc, 0);
|
||||
break;
|
||||
case FMT_SDPS_PS:
|
||||
check_ps(ctx);
|
||||
gen_movcf_ps(ctx, rs, rt, cc, 0);
|
||||
break;
|
||||
default:
|
||||
@ -14133,6 +14142,7 @@ static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx)
|
||||
gen_movcf_d(ctx, rs, rt, cc, 1);
|
||||
break;
|
||||
case FMT_SDPS_PS:
|
||||
check_ps(ctx);
|
||||
gen_movcf_ps(ctx, rs, rt, cc, 1);
|
||||
break;
|
||||
default:
|
||||
@ -14154,6 +14164,7 @@ static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx)
|
||||
mips32_op = OPC_##prfx##_D; \
|
||||
goto do_fpop; \
|
||||
case FMT_SDPS_PS: \
|
||||
check_ps(ctx); \
|
||||
mips32_op = OPC_##prfx##_PS; \
|
||||
goto do_fpop; \
|
||||
default: \
|
||||
@ -19162,8 +19173,7 @@ static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
|
||||
(rt >> 2) & 0x7, imm << 2);
|
||||
break;
|
||||
case OPC_PS_FMT:
|
||||
check_cp1_enabled(ctx);
|
||||
check_insn_opc_removed(ctx, ISA_MIPS32R6);
|
||||
check_ps(ctx);
|
||||
/* fall through */
|
||||
case OPC_S_FMT:
|
||||
case OPC_D_FMT:
|
||||
@ -19472,6 +19482,8 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb,
|
||||
/* Restore delay slot state from the tb context. */
|
||||
ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */
|
||||
ctx.ulri = (env->CP0_Config3 >> CP0C3_ULRI) & 1;
|
||||
ctx.ps = ((env->active_fpu.fcr0 >> FCR0_PS) & 1) ||
|
||||
(env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F));
|
||||
restore_cpu_state(env, &ctx);
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
ctx.mem_idx = MIPS_HFLAG_UM;
|
||||
|
Loading…
Reference in New Issue
Block a user