From faf1f68ba11c919191dd7a5f32cfd0b6401c4827 Mon Sep 17 00:00:00 2001 From: Leon Alrae Date: Fri, 11 Jul 2014 16:11:33 +0100 Subject: [PATCH] target-mips: add Config5.SBRI SDBBP instruction Reserved Instruction control. The purpose of this field is to restrict availability of SDBBP to kernel mode operation. If the bit is set then SDBBP instruction can only be executed in kernel mode. User execution of SDBBP will cause a Reserved Instruction exception. Additionally add missing Config4 and Config5 cases for dm{f,t}c0. Signed-off-by: Leon Alrae Reviewed-by: Yongbok Kim --- target-mips/cpu.h | 11 +++++++++-- target-mips/translate.c | 24 +++++++++++++++++++++++- 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/target-mips/cpu.h b/target-mips/cpu.h index c66a725f70..ce9a7a28f0 100644 --- a/target-mips/cpu.h +++ b/target-mips/cpu.h @@ -410,6 +410,7 @@ struct CPUMIPSState { #define CP0C5_CV 29 #define CP0C5_EVA 28 #define CP0C5_MSAEn 27 +#define CP0C5_SBRI 6 #define CP0C5_UFR 2 #define CP0C5_NFExists 0 int32_t CP0_Config6; @@ -461,7 +462,7 @@ struct CPUMIPSState { #define EXCP_INST_NOTAVAIL 0x2 /* No valid instruction word for BadInstr */ uint32_t hflags; /* CPU State */ /* TMASK defines different execution modes */ -#define MIPS_HFLAG_TMASK 0x1807FF +#define MIPS_HFLAG_TMASK 0x5807FF #define MIPS_HFLAG_MODE 0x00007 /* execution modes */ /* The KSU flags must be the lowest bits in hflags. The flag order must be the same as defined for CP0 Status. This allows to use @@ -505,6 +506,7 @@ struct CPUMIPSState { #define MIPS_HFLAG_DSPR2 0x100000 /* Enable access to MIPS DSPR2 resources. */ /* Extra flag about HWREna register. */ #define MIPS_HFLAG_HWRENA_ULR 0x200000 /* ULR bit from HWREna is set. */ +#define MIPS_HFLAG_SBRI 0x400000 /* R6 SDBBP causes RI excpt. in user mode */ target_ulong btarget; /* Jump / branch target */ target_ulong bcond; /* Branch condition (if needed) */ @@ -760,7 +762,8 @@ static inline void compute_hflags(CPUMIPSState *env) { env->hflags &= ~(MIPS_HFLAG_COP1X | MIPS_HFLAG_64 | MIPS_HFLAG_CP0 | MIPS_HFLAG_F64 | MIPS_HFLAG_FPU | MIPS_HFLAG_KSU | - MIPS_HFLAG_AWRAP | MIPS_HFLAG_DSP | MIPS_HFLAG_DSPR2); + MIPS_HFLAG_AWRAP | MIPS_HFLAG_DSP | MIPS_HFLAG_DSPR2 | + MIPS_HFLAG_SBRI); if (!(env->CP0_Status & (1 << CP0St_EXL)) && !(env->CP0_Status & (1 << CP0St_ERL)) && !(env->hflags & MIPS_HFLAG_DM)) { @@ -796,6 +799,10 @@ static inline void compute_hflags(CPUMIPSState *env) if (env->CP0_Status & (1 << CP0St_FR)) { env->hflags |= MIPS_HFLAG_F64; } + if (((env->hflags & MIPS_HFLAG_KSU) != MIPS_HFLAG_KM) && + (env->CP0_Config5 & (1 << CP0C5_SBRI))) { + env->hflags |= MIPS_HFLAG_SBRI; + } if (env->insn_flags & ASE_DSPR2) { /* Enables access MIPS DSP resources, now our cpu is DSP ASER2, so enable to access DSPR2 resources. */ diff --git a/target-mips/translate.c b/target-mips/translate.c index 3e6e99026a..c7a8bbc0d3 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -6225,6 +6225,14 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel) gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3)); rn = "Config3"; break; + case 4: + gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4)); + rn = "Config4"; + break; + case 5: + gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5)); + rn = "Config5"; + break; /* 6,7 are implementation dependent */ case 6: gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6)); @@ -6843,6 +6851,16 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel) /* ignored */ rn = "Config3"; break; + case 4: + /* currently ignored */ + rn = "Config4"; + break; + case 5: + gen_helper_mtc0_config5(cpu_env, arg); + rn = "Config5"; + /* Stop translation as we may have switched the execution mode */ + ctx->bstate = BS_STOP; + break; /* 6,7 are implementation dependent */ default: rn = "Invalid config selector"; @@ -15801,7 +15819,11 @@ static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx) } break; case R6_OPC_SDBBP: - generate_exception(ctx, EXCP_DBp); + if (ctx->hflags & MIPS_HFLAG_SBRI) { + generate_exception(ctx, EXCP_RI); + } else { + generate_exception(ctx, EXCP_DBp); + } break; #if defined(TARGET_MIPS64) case OPC_DLSA: