diff options
Diffstat (limited to 'target/mips/translate.c')
| -rw-r--r-- | target/mips/translate.c | 88 |
1 files changed, 85 insertions, 3 deletions
diff --git a/target/mips/translate.c b/target/mips/translate.c index efe75e6be0..d745bd2803 100644 --- a/target/mips/translate.c +++ b/target/mips/translate.c @@ -388,6 +388,7 @@ enum { OPC_BSHFL = 0x20 | OPC_SPECIAL3, OPC_DBSHFL = 0x24 | OPC_SPECIAL3, OPC_RDHWR = 0x3B | OPC_SPECIAL3, + OPC_GINV = 0x3D | OPC_SPECIAL3, /* Loongson 2E */ OPC_MULT_G_2E = 0x18 | OPC_SPECIAL3, @@ -2547,6 +2548,8 @@ typedef struct DisasContext { bool nan2008; bool abs2008; bool saar; + bool mi; + int gi; } DisasContext; #define DISAS_STOP DISAS_TARGET_0 @@ -6783,6 +6786,25 @@ static void gen_mfhc0(DisasContext *ctx, TCGv arg, int reg, int sel) goto cp0_unimplemented; } break; + case CP0_REGISTER_19: + switch (sel) { + case CP0_REG19__WATCHHI0: + case CP0_REG19__WATCHHI1: + case CP0_REG19__WATCHHI2: + case CP0_REG19__WATCHHI3: + case CP0_REG19__WATCHHI4: + case CP0_REG19__WATCHHI5: + case CP0_REG19__WATCHHI6: + case CP0_REG19__WATCHHI7: + /* upper 32 bits are only available when Config5MI != 0 */ + CP0_CHECK(ctx->mi); + gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_WatchHi[sel]), 0); + register_name = "WatchHi"; + break; + default: + goto cp0_unimplemented; + } + break; case CP0_REGISTER_28: switch (sel) { case 0: @@ -6869,6 +6891,25 @@ static void gen_mthc0(DisasContext *ctx, TCGv arg, int reg, int sel) goto cp0_unimplemented; } break; + case CP0_REGISTER_19: + switch (sel) { + case CP0_REG19__WATCHHI0: + case CP0_REG19__WATCHHI1: + case CP0_REG19__WATCHHI2: + case CP0_REG19__WATCHHI3: + case CP0_REG19__WATCHHI4: + case CP0_REG19__WATCHHI5: + case CP0_REG19__WATCHHI6: + case CP0_REG19__WATCHHI7: + /* upper 32 bits are only available when Config5MI != 0 */ + CP0_CHECK(ctx->mi); + gen_helper_0e1i(mthc0_watchhi, arg, sel); + register_name = "WatchHi"; + break; + default: + goto cp0_unimplemented; + } + break; case CP0_REGISTER_28: switch (sel) { case 0: @@ -7092,6 +7133,11 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel) tcg_gen_ext32s_tl(arg, arg); register_name = "UserLocal"; break; + case CP0_REG04__MMID: + CP0_CHECK(ctx->mi); + gen_helper_mtc0_memorymapid(cpu_env, arg); + register_name = "MMID"; + break; default: goto cp0_unimplemented; } @@ -7832,6 +7878,11 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel) offsetof(CPUMIPSState, active_tc.CP0_UserLocal)); register_name = "UserLocal"; break; + case CP0_REG04__MMID: + CP0_CHECK(ctx->mi); + gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MemoryMapID)); + register_name = "MMID"; + break; default: goto cp0_unimplemented; } @@ -8590,6 +8641,11 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel) offsetof(CPUMIPSState, active_tc.CP0_UserLocal)); register_name = "UserLocal"; break; + case CP0_REG04__MMID: + CP0_CHECK(ctx->mi); + gen_helper_mtc0_memorymapid(cpu_env, arg); + register_name = "MMID"; + break; default: goto cp0_unimplemented; } @@ -8922,7 +8978,7 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel) case CP0_REG19__WATCHHI6: case CP0_REG19__WATCHHI7: CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR)); - gen_helper_1e0i(mfc0_watchhi, arg, sel); + gen_helper_1e0i(dmfc0_watchhi, arg, sel); register_name = "WatchHi"; break; default: @@ -9312,6 +9368,11 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel) offsetof(CPUMIPSState, active_tc.CP0_UserLocal)); register_name = "UserLocal"; break; + case CP0_REG04__MMID: + CP0_CHECK(ctx->mi); + gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MemoryMapID)); + register_name = "MMID"; + break; default: goto cp0_unimplemented; } @@ -27170,6 +27231,25 @@ static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx) } } break; +#ifndef CONFIG_USER_ONLY + case OPC_GINV: + if (unlikely(ctx->gi <= 1)) { + generate_exception_end(ctx, EXCP_RI); + } + check_cp0_enabled(ctx); + switch ((ctx->opcode >> 6) & 3) { + case 0: /* GINVI */ + /* Treat as NOP. */ + break; + case 2: /* GINVT */ + gen_helper_0e1i(ginvt, cpu_gpr[rs], extract32(ctx->opcode, 8, 2)); + break; + default: + generate_exception_end(ctx, EXCP_RI); + break; + } + break; +#endif #if defined(TARGET_MIPS64) case R6_OPC_SCD: gen_st_cond(ctx, rt, rs, imm, MO_TEQ, false); @@ -30727,6 +30807,8 @@ static void mips_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs) ctx->mrp = (env->CP0_Config5 >> CP0C5_MRP) & 1; ctx->nan2008 = (env->active_fpu.fcr31 >> FCR31_NAN2008) & 1; ctx->abs2008 = (env->active_fpu.fcr31 >> FCR31_ABS2008) & 1; + ctx->mi = (env->CP0_Config5 >> CP0C5_MI) & 1; + ctx->gi = (env->CP0_Config5 >> CP0C5_GI) & 3; restore_cpu_state(env, ctx); #ifdef CONFIG_USER_ONLY ctx->mem_idx = MIPS_HFLAG_UM; @@ -31187,8 +31269,8 @@ void cpu_state_reset(CPUMIPSState *env) if (env->CP0_Config3 & (1 << CP0C3_CMGCR)) { env->CP0_CMGCRBase = 0x1fbf8000 >> 4; } - env->CP0_EntryHi_ASID_mask = (env->CP0_Config4 & (1 << CP0C4_AE)) ? - 0x3ff : 0xff; + env->CP0_EntryHi_ASID_mask = (env->CP0_Config5 & (1 << CP0C5_MI)) ? + 0x0 : (env->CP0_Config4 & (1 << CP0C4_AE)) ? 0x3ff : 0xff; env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL); /* * Vectored interrupts not implemented, timer on int 7, |