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
This commit is contained in:
Leon Alrae 2018-02-13 13:31:16 -05:00 committed by Lioncash
parent 922d30c448
commit 57f57a9de4
No known key found for this signature in database
GPG key ID: 4E3C3CC1031BA9C7
9 changed files with 33 additions and 4 deletions

View file

@ -3683,6 +3683,7 @@ mips_symbols = (
'helper_di',
'helper_ei',
'helper_eret',
'helper_eretnc',
'helper_deret',
'helper_rdhwr_cpunum',
'helper_rdhwr_synci_step',

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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;

View file

@ -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)

View file

@ -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);

View file

@ -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";