mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2024-12-23 17:35:33 +00:00
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
This commit is contained in:
parent
90848d778a
commit
acede6f50c
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue