summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--disas/mips.c1
-rw-r--r--target-mips/cpu.h1
-rw-r--r--target-mips/helper.h1
-rw-r--r--target-mips/op_helper.c12
-rw-r--r--target-mips/translate.c20
-rw-r--r--target-mips/translate_init.c3
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,