diff options
-rw-r--r-- | disas/mips.c | 1 | ||||
-rw-r--r-- | target-mips/cpu.h | 1 | ||||
-rw-r--r-- | target-mips/helper.h | 1 | ||||
-rw-r--r-- | target-mips/op_helper.c | 12 | ||||
-rw-r--r-- | target-mips/translate.c | 20 | ||||
-rw-r--r-- | target-mips/translate_init.c | 3 |
6 files changed, 31 insertions, 7 deletions
diff --git a/disas/mips.c b/disas/mips.c index 1afe0c5511..832468c0a7 100644 --- a/disas/mips.c +++ b/disas/mips.c @@ -2407,6 +2407,7 @@ const struct mips_opcode mips_builtin_opcodes[] = {"emt", "", 0x41600be1, 0xffffffff, TRAP, 0, MT32 }, {"emt", "t", 0x41600be1, 0xffe0ffff, TRAP|WR_t, 0, MT32 }, {"eret", "", 0x42000018, 0xffffffff, 0, 0, I3|I32 }, +{"eretnc", "", 0x42000058, 0xffffffff, 0, 0, I33}, {"evpe", "", 0x41600021, 0xffffffff, TRAP, 0, MT32 }, {"evpe", "t", 0x41600021, 0xffe0ffff, TRAP|WR_t, 0, MT32 }, {"ext", "t,r,+A,+C", 0x7c000000, 0xfc00003f, WR_t|RD_s, 0, I33 }, diff --git a/target-mips/cpu.h b/target-mips/cpu.h index 03eb888361..2c68782763 100644 --- a/target-mips/cpu.h +++ b/target-mips/cpu.h @@ -466,6 +466,7 @@ struct CPUMIPSState { #define CP0C5_UFE 9 #define CP0C5_FRE 8 #define CP0C5_SBRI 6 +#define CP0C5_LLB 4 #define CP0C5_UFR 2 #define CP0C5_NFExists 0 int32_t CP0_Config6; diff --git a/target-mips/helper.h b/target-mips/helper.h index bdd5ba5e92..8df98c71b8 100644 --- a/target-mips/helper.h +++ b/target-mips/helper.h @@ -348,6 +348,7 @@ DEF_HELPER_1(tlbinvf, void, env) DEF_HELPER_1(di, tl, env) DEF_HELPER_1(ei, tl, env) DEF_HELPER_1(eret, void, env) +DEF_HELPER_1(eretnc, void, env) DEF_HELPER_1(deret, void, env) #endif /* !CONFIG_USER_ONLY */ DEF_HELPER_1(rdhwr_cpunum, tl, env) diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c index 2fe862a4cf..b412f94f82 100644 --- a/target-mips/op_helper.c +++ b/target-mips/op_helper.c @@ -2099,7 +2099,7 @@ static void set_pc(CPUMIPSState *env, target_ulong error_pc) } } -void helper_eret(CPUMIPSState *env) +static inline void exception_return(CPUMIPSState *env) { debug_pre_eret(env); if (env->CP0_Status & (1 << CP0St_ERL)) { @@ -2111,9 +2111,19 @@ void helper_eret(CPUMIPSState *env) } compute_hflags(env); debug_post_eret(env); +} + +void helper_eret(CPUMIPSState *env) +{ + exception_return(env); env->lladdr = 1; } +void helper_eretnc(CPUMIPSState *env) +{ + exception_return(env); +} + void helper_deret(CPUMIPSState *env) { debug_pre_eret(env); diff --git a/target-mips/translate.c b/target-mips/translate.c index fe6bc16b18..f6ae0d3aec 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -7917,16 +7917,26 @@ static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt, goto die; gen_helper_tlbr(cpu_env); break; - case OPC_ERET: - opn = "eret"; - check_insn(ctx, ISA_MIPS2); + case OPC_ERET: /* OPC_ERETNC */ if ((ctx->insn_flags & ISA_MIPS32R6) && (ctx->hflags & MIPS_HFLAG_BMASK)) { MIPS_DEBUG("CTI in delay / forbidden slot"); goto die; + } else { + int bit_shift = (ctx->hflags & MIPS_HFLAG_M16) ? 16 : 6; + if (ctx->opcode & (1 << bit_shift)) { + /* OPC_ERETNC */ + opn = "eretnc"; + check_insn(ctx, ISA_MIPS32R5); + gen_helper_eretnc(cpu_env); + } else { + /* OPC_ERET */ + opn = "eret"; + check_insn(ctx, ISA_MIPS2); + gen_helper_eret(cpu_env); + } + ctx->bstate = BS_EXCP; } - gen_helper_eret(cpu_env); - ctx->bstate = BS_EXCP; break; case OPC_DERET: opn = "deret"; diff --git a/target-mips/translate_init.c b/target-mips/translate_init.c index 00369f1b01..51e7c986e4 100644 --- a/target-mips/translate_init.c +++ b/target-mips/translate_init.c @@ -403,7 +403,7 @@ static const mips_def_t mips_defs[] = .CP0_Config3 = MIPS_CONFIG3 | (1U << CP0C3_M) | (1 << CP0C3_MSAP), .CP0_Config4 = MIPS_CONFIG4 | (1U << CP0C4_M), .CP0_Config4_rw_bitmask = 0, - .CP0_Config5 = MIPS_CONFIG5 | (1 << CP0C5_UFR), + .CP0_Config5 = MIPS_CONFIG5 | (1 << CP0C5_UFR) | (1 << CP0C5_LLB), .CP0_Config5_rw_bitmask = (0 << CP0C5_M) | (1 << CP0C5_K) | (1 << CP0C5_CV) | (0 << CP0C5_EVA) | (1 << CP0C5_MSAEn) | (1 << CP0C5_UFR) | @@ -622,6 +622,7 @@ static const mips_def_t mips_defs[] = (1 << CP0C3_BI) | (1 << CP0C3_ULRI) | (1U << CP0C3_M), .CP0_Config4 = MIPS_CONFIG4 | (0xfc << CP0C4_KScrExist) | (3 << CP0C4_IE) | (1 << CP0C4_M), + .CP0_Config5 = MIPS_CONFIG5 | (1 << CP0C5_LLB), .CP0_Config5_rw_bitmask = (1 << CP0C5_SBRI) | (1 << CP0C5_FRE) | (1 << CP0C5_UFE), .CP0_LLAddr_rw_bitmask = 0, |