diff options
Diffstat (limited to 'target-mips/translate.c')
-rw-r--r-- | target-mips/translate.c | 55 |
1 files changed, 52 insertions, 3 deletions
diff --git a/target-mips/translate.c b/target-mips/translate.c index d95ab9e..1b2bf7f 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -1072,6 +1072,7 @@ typedef struct DisasContext { uint32_t hflags, saved_hflags; int bstate; target_ulong btarget; + bool ulri; } DisasContext; enum { @@ -4215,7 +4216,18 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel) case 1: // gen_helper_mfc0_contextconfig(arg); /* SmartMIPS ASE */ rn = "ContextConfig"; + goto die; // break; + case 2: + if (ctx->ulri) { + tcg_gen_ld32s_tl(arg, cpu_env, + offsetof(CPUMIPSState, + active_tc.CP0_UserLocal)); + rn = "UserLocal"; + } else { + tcg_gen_movi_tl(arg, 0); + } + break; default: goto die; } @@ -4802,7 +4814,15 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel) case 1: // gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */ rn = "ContextConfig"; + goto die; // break; + case 2: + if (ctx->ulri) { + tcg_gen_st_tl(arg, cpu_env, + offsetof(CPUMIPSState, active_tc.CP0_UserLocal)); + rn = "UserLocal"; + } + break; default: goto die; } @@ -4862,6 +4882,7 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel) case 0: check_insn(ctx, ISA_MIPS32R2); gen_helper_mtc0_hwrena(cpu_env, arg); + ctx->bstate = BS_STOP; rn = "HWREna"; break; default: @@ -5406,7 +5427,17 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel) case 1: // gen_helper_dmfc0_contextconfig(arg); /* SmartMIPS ASE */ rn = "ContextConfig"; + goto die; // break; + case 2: + if (ctx->ulri) { + tcg_gen_ld_tl(arg, cpu_env, + offsetof(CPUMIPSState, active_tc.CP0_UserLocal)); + rn = "UserLocal"; + } else { + tcg_gen_movi_tl(arg, 0); + } + break; default: goto die; } @@ -5978,7 +6009,15 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel) case 1: // gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */ rn = "ContextConfig"; + goto die; // break; + case 2: + if (ctx->ulri) { + tcg_gen_st_tl(arg, cpu_env, + offsetof(CPUMIPSState, active_tc.CP0_UserLocal)); + rn = "UserLocal"; + } + break; default: goto die; } @@ -6038,6 +6077,7 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel) case 0: check_insn(ctx, ISA_MIPS32R2); gen_helper_mtc0_hwrena(cpu_env, arg); + ctx->bstate = BS_STOP; rn = "HWREna"; break; default: @@ -9060,12 +9100,20 @@ static void gen_rdhwr(DisasContext *ctx, int rt, int rd) break; case 29: #if defined(CONFIG_USER_ONLY) - tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUMIPSState, tls_value)); + tcg_gen_ld_tl(t0, cpu_env, + offsetof(CPUMIPSState, active_tc.CP0_UserLocal)); gen_store_gpr(t0, rt); break; #else - /* XXX: Some CPUs implement this in hardware. - Not supported yet. */ + if ((ctx->hflags & MIPS_HFLAG_CP0) || + (ctx->hflags & MIPS_HFLAG_HWRENA_ULR)) { + tcg_gen_ld_tl(t0, cpu_env, + offsetof(CPUMIPSState, active_tc.CP0_UserLocal)); + gen_store_gpr(t0, rt); + } else { + generate_exception(ctx, EXCP_RI); + } + break; #endif default: /* Invalid */ MIPS_INVAL("rdhwr"); @@ -15609,6 +15657,7 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb, ctx.bstate = BS_NONE; /* 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 & (1 << CP0C3_ULRI); restore_cpu_state(env, &ctx); #ifdef CONFIG_USER_ONLY ctx.mem_idx = MIPS_HFLAG_UM; |