From 57f57a9de4ff6632216da8255a76bed35d995b33 Mon Sep 17 00:00:00 2001 From: Leon Alrae Date: Tue, 13 Feb 2018 13:31:16 -0500 Subject: [PATCH] target-mips: add ERETNC instruction and Config5.LLB bit 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. Presence of ERETNC is denoted by the Config5.LLB. Backports commit ce9782f40ac16660ea9437bfaa2c9c34d5ed8110 from qemu --- qemu/header_gen.py | 1 + qemu/mips.h | 1 + qemu/mips64.h | 1 + qemu/mips64el.h | 1 + qemu/mipsel.h | 1 + qemu/target-mips/cpu.h | 1 + qemu/target-mips/helper.h | 1 + qemu/target-mips/op_helper.c | 12 +++++++++++- qemu/target-mips/translate.c | 18 +++++++++++++++--- 9 files changed, 33 insertions(+), 4 deletions(-) diff --git a/qemu/header_gen.py b/qemu/header_gen.py index 9c16df12..20ae68d8 100644 --- a/qemu/header_gen.py +++ b/qemu/header_gen.py @@ -3683,6 +3683,7 @@ mips_symbols = ( 'helper_di', 'helper_ei', 'helper_eret', + 'helper_eretnc', 'helper_deret', 'helper_rdhwr_cpunum', 'helper_rdhwr_synci_step', diff --git a/qemu/mips.h b/qemu/mips.h index 5df97be5..9d61af1b 100644 --- a/qemu/mips.h +++ b/qemu/mips.h @@ -3630,6 +3630,7 @@ #define helper_di helper_di_mips #define helper_ei helper_ei_mips #define helper_eret helper_eret_mips +#define helper_eretnc helper_eretnc_mips #define helper_deret helper_deret_mips #define helper_rdhwr_cpunum helper_rdhwr_cpunum_mips #define helper_rdhwr_synci_step helper_rdhwr_synci_step_mips diff --git a/qemu/mips64.h b/qemu/mips64.h index 8a748a6a..06302324 100644 --- a/qemu/mips64.h +++ b/qemu/mips64.h @@ -3630,6 +3630,7 @@ #define helper_di helper_di_mips64 #define helper_ei helper_ei_mips64 #define helper_eret helper_eret_mips64 +#define helper_eretnc helper_eretnc_mips64 #define helper_deret helper_deret_mips64 #define helper_rdhwr_cpunum helper_rdhwr_cpunum_mips64 #define helper_rdhwr_synci_step helper_rdhwr_synci_step_mips64 diff --git a/qemu/mips64el.h b/qemu/mips64el.h index 2f091005..ce53005c 100644 --- a/qemu/mips64el.h +++ b/qemu/mips64el.h @@ -3630,6 +3630,7 @@ #define helper_di helper_di_mips64el #define helper_ei helper_ei_mips64el #define helper_eret helper_eret_mips64el +#define helper_eretnc helper_eretnc_mips64el #define helper_deret helper_deret_mips64el #define helper_rdhwr_cpunum helper_rdhwr_cpunum_mips64el #define helper_rdhwr_synci_step helper_rdhwr_synci_step_mips64el diff --git a/qemu/mipsel.h b/qemu/mipsel.h index 9302c264..0b9dac0c 100644 --- a/qemu/mipsel.h +++ b/qemu/mipsel.h @@ -3630,6 +3630,7 @@ #define helper_di helper_di_mipsel #define helper_ei helper_ei_mipsel #define helper_eret helper_eret_mipsel +#define helper_eretnc helper_eretnc_mipsel #define helper_deret helper_deret_mipsel #define helper_rdhwr_cpunum helper_rdhwr_cpunum_mipsel #define helper_rdhwr_synci_step helper_rdhwr_synci_step_mipsel diff --git a/qemu/target-mips/cpu.h b/qemu/target-mips/cpu.h index 78858521..e267456b 100644 --- a/qemu/target-mips/cpu.h +++ b/qemu/target-mips/cpu.h @@ -467,6 +467,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/qemu/target-mips/helper.h b/qemu/target-mips/helper.h index c5e5def5..24809cce 100644 --- a/qemu/target-mips/helper.h +++ b/qemu/target-mips/helper.h @@ -350,6 +350,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/qemu/target-mips/op_helper.c b/qemu/target-mips/op_helper.c index b8ba7b86..e8ce2d54 100644 --- a/qemu/target-mips/op_helper.c +++ b/qemu/target-mips/op_helper.c @@ -2106,7 +2106,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)) { @@ -2118,9 +2118,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/qemu/target-mips/translate.c b/qemu/target-mips/translate.c index c163228c..8be9951c 100644 --- a/qemu/target-mips/translate.c +++ b/qemu/target-mips/translate.c @@ -7985,16 +7985,28 @@ static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt, goto die; gen_helper_tlbr(tcg_ctx, tcg_ctx->cpu_env); break; - case OPC_ERET: + case OPC_ERET: /* OPC_ERETNC */ opn = "eret"; check_insn(ctx, ISA_MIPS2); 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(tcg_ctx, tcg_ctx->cpu_env); + } else { + /* OPC_ERET */ + opn = "eret"; + check_insn(ctx, ISA_MIPS2); + gen_helper_eret(tcg_ctx, tcg_ctx->cpu_env); + } + ctx->bstate = BS_EXCP; } - gen_helper_eret(tcg_ctx, tcg_ctx->cpu_env); - ctx->bstate = BS_EXCP; break; case OPC_DERET: opn = "deret";