aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeon Alrae <leon.alrae@imgtec.com>2015-01-19 11:35:11 +0100
committerMiodrag Dinic <miodrag.dinic@imgtec.com>2015-02-05 11:21:14 +0100
commitb211ef108da1d434d434b04ffc3a5f60a14328f3 (patch)
tree4c22ceae88a850d08f360cc0af9d451b5ceb7a9a
parentf521bd2470294784df3bfed9704661583ce40573 (diff)
downloadqemu-android-b211ef108da1d434d434b04ffc3a5f60a14328f3.tar.gz
target-mips: add ERETNC instruction
ERETNC is identical to ERET except that an ERETNC will not clear the LLbit that is set by execution of an LL instruction, and thus when placed between an LL and SC sequence, will never cause the SC to fail. Software can detect the presence of ERETNC by reading Config5.LLB Change-Id: Ifbd263b8cbd974d97c9f9f29488618117a16b460
-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.c16
-rw-r--r--target-mips/translate_init.c7
6 files changed, 30 insertions, 8 deletions
diff --git a/disas/mips.c b/disas/mips.c
index 2614c52a4b..66a5275738 100644
--- a/disas/mips.c
+++ b/disas/mips.c
@@ -2406,6 +2406,7 @@ const struct mips_opcode mips_builtin_opcodes[] =
{"ei", "t", 0x41606020, 0xffe0ffff, WR_t|WR_C0, 0, I33 },
{"emt", "", 0x41600be1, 0xffffffff, TRAP, 0, MT32 },
{"emt", "t", 0x41600be1, 0xffe0ffff, TRAP|WR_t, 0, MT32 },
+{"eretnc", "", 0x42000058, 0xffffffff, 0, 0, I33 },
{"eret", "", 0x42000018, 0xffffffff, 0, 0, I3|I32 },
{"evpe", "", 0x41600021, 0xffffffff, TRAP, 0, MT32 },
{"evpe", "t", 0x41600021, 0xffe0ffff, TRAP|WR_t, 0, MT32 },
diff --git a/target-mips/cpu.h b/target-mips/cpu.h
index c01bbdac2d..9963cffc72 100644
--- a/target-mips/cpu.h
+++ b/target-mips/cpu.h
@@ -464,6 +464,7 @@ struct CPUMIPSState {
#define CP0C5_EVA 28
#define CP0C5_MSAEn 27
#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 9d0275891c..3687df4969 100644
--- a/target-mips/helper.h
+++ b/target-mips/helper.h
@@ -347,6 +347,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 638c9f9dfb..8630d44275 100644
--- a/target-mips/op_helper.c
+++ b/target-mips/op_helper.c
@@ -2160,7 +2160,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)) {
@@ -2172,9 +2172,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 f0b8e6ffe4..2682c13294 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -7886,15 +7886,23 @@ 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;
}
- gen_helper_eret(cpu_env);
+ if (ctx->opcode & (1 << 6)) {
+ /* 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;
break;
case OPC_DERET:
diff --git a/target-mips/translate_init.c b/target-mips/translate_init.c
index 148b394cf0..4b70ccaac9 100644
--- a/target-mips/translate_init.c
+++ b/target-mips/translate_init.c
@@ -362,7 +362,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) |
@@ -528,14 +528,15 @@ static const mips_def_t mips_defs[] =
.CP0_Config0 = MIPS_CONFIG0 | (0x2 << CP0C0_AR) | (0x2 << CP0C0_AT) |
(MMU_TYPE_R4000 << CP0C0_MT),
.CP0_Config1 = MIPS_CONFIG1 | (1 << CP0C1_FP) | (63 << CP0C1_MMU) |
- (2 << CP0C1_IS) | (4 << CP0C1_IL) | (3 << CP0C1_IA) |
- (2 << CP0C1_DS) | (4 << CP0C1_DL) | (3 << CP0C1_DA) |
+ (2 << CP0C1_IS) | (3 << CP0C1_IL) | (3 << CP0C1_IA) |
+ (2 << CP0C1_DS) | (3 << CP0C1_DL) | (3 << CP0C1_DA) |
(0 << CP0C1_PC) | (1 << CP0C1_WR) | (1 << CP0C1_EP),
.CP0_Config2 = MIPS_CONFIG2,
.CP0_Config3 = MIPS_CONFIG3 | (1 << CP0C3_RXI) | (1 << CP0C3_BP) |
(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),
.CP0_LLAddr_rw_bitmask = 0,
.CP0_LLAddr_shift = 0,