From acede6f50caec3413f52cc18506b4e39a8e5ad4d Mon Sep 17 00:00:00 2001 From: Yongbok Kim Date: Tue, 13 Feb 2018 21:29:45 -0500 Subject: [PATCH] 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. Backports commit e29c962804c4dd3fabd44e703aa87eec555ed910 from qemu --- qemu/target-mips/translate.c | 81 ++++++++++++++++++++---------------- 1 file changed, 45 insertions(+), 36 deletions(-) diff --git a/qemu/target-mips/translate.c b/qemu/target-mips/translate.c index 57020f35..9d136620 100644 --- a/qemu/target-mips/translate.c +++ b/qemu/target-mips/translate.c @@ -1412,6 +1412,7 @@ typedef struct DisasContext { uint64_t PAMask; bool mvh; int CP0_LLAddr_shift; + bool ps; // Unicorn engine struct uc_struct *uc; } DisasContext; @@ -1827,6 +1828,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. */ @@ -1861,7 +1872,7 @@ static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \ TCGv_i##bits fp1 = tcg_temp_new_i##bits (tcg_ctx); \ switch (ifmt) { \ case FMT_PS: \ - check_cp1_64bitmode(ctx); \ + check_ps(ctx); \ break; \ case FMT_D: \ if (abs) { \ @@ -9085,7 +9096,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: { @@ -9578,8 +9588,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(tcg_ctx); TCGv_i32 fp32_0 = tcg_temp_new_i32(tcg_ctx); @@ -10196,8 +10205,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(tcg_ctx); @@ -10209,7 +10217,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(tcg_ctx); TCGv_i64 fp1 = tcg_temp_new_i64(tcg_ctx); @@ -10224,7 +10232,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(tcg_ctx); TCGv_i64 fp1 = tcg_temp_new_i64(tcg_ctx); @@ -10239,7 +10247,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(tcg_ctx); TCGv_i64 fp1 = tcg_temp_new_i64(tcg_ctx); @@ -10254,7 +10262,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(tcg_ctx); @@ -10266,7 +10274,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(tcg_ctx); @@ -10277,7 +10285,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(tcg_ctx); @@ -10289,12 +10297,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(tcg_ctx); TCGv_i64 fp0; @@ -10310,7 +10318,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(tcg_ctx); TCGv_i64 fp0; @@ -10327,7 +10335,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(tcg_ctx); TCGv_i64 fp1 = tcg_temp_new_i64(tcg_ctx); @@ -10342,7 +10350,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(tcg_ctx); TCGv_i64 fp1 = tcg_temp_new_i64(tcg_ctx); @@ -10357,7 +10365,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(tcg_ctx); TCGv_i64 fp1 = tcg_temp_new_i64(tcg_ctx); @@ -10372,7 +10380,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(tcg_ctx); @@ -10384,7 +10392,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(tcg_ctx); @@ -10396,7 +10404,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(tcg_ctx); TCGv_i64 fp1 = tcg_temp_new_i64(tcg_ctx); @@ -10423,7 +10431,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(tcg_ctx); @@ -10447,7 +10455,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(tcg_ctx); TCGv_i32 fp1 = tcg_temp_new_i32(tcg_ctx); @@ -10462,7 +10470,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(tcg_ctx); TCGv_i32 fp1 = tcg_temp_new_i32(tcg_ctx); @@ -10477,7 +10485,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(tcg_ctx); TCGv_i32 fp1 = tcg_temp_new_i32(tcg_ctx); @@ -10492,7 +10500,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(tcg_ctx); TCGv_i32 fp1 = tcg_temp_new_i32(tcg_ctx); @@ -10654,7 +10662,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(tcg_ctx); TCGv_i32 fp = tcg_temp_new_i32(tcg_ctx); @@ -10729,7 +10737,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(tcg_ctx); TCGv_i64 fp1 = tcg_temp_new_i64(tcg_ctx); @@ -10784,7 +10792,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(tcg_ctx); TCGv_i64 fp1 = tcg_temp_new_i64(tcg_ctx); @@ -10839,7 +10847,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(tcg_ctx); TCGv_i64 fp1 = tcg_temp_new_i64(tcg_ctx); @@ -10894,7 +10902,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(tcg_ctx); TCGv_i64 fp1 = tcg_temp_new_i64(tcg_ctx); @@ -14208,6 +14216,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: @@ -14223,6 +14232,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: @@ -14244,6 +14254,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: \ @@ -16633,7 +16644,6 @@ static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2, static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx) { - TCGContext *tcg_ctx = env->uc->tcg_ctx; int rs, rt, rd, sa; uint32_t op1, op2; @@ -17078,8 +17088,6 @@ static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx) static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx) { - TCGContext *tcg_ctx = env->uc->tcg_ctx; - TCGv **cpu_gpr = (TCGv **)tcg_ctx->cpu_gpr; int rs, rt, rd, sa; uint32_t op1, op2; int16_t imm; @@ -19305,8 +19313,7 @@ static void decode_opc(CPUMIPSState *env, DisasContext *ctx, bool *insn_need_pat (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: @@ -19615,6 +19622,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;