From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:48852) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XgArV-0005I4-L0 for qemu-devel@nongnu.org; Mon, 20 Oct 2014 07:10:59 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1XgArN-0007UO-NP for qemu-devel@nongnu.org; Mon, 20 Oct 2014 07:10:53 -0400 Received: from mailapp01.imgtec.com ([195.59.15.196]:52256) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XgArN-0007U9-78 for qemu-devel@nongnu.org; Mon, 20 Oct 2014 07:10:45 -0400 Message-ID: <5444EDB1.5090607@imgtec.com> Date: Mon, 20 Oct 2014 12:10:41 +0100 From: Yongbok Kim MIME-Version: 1.0 References: <1405354795-25884-1-git-send-email-leon.alrae@imgtec.com> <1405354795-25884-3-git-send-email-leon.alrae@imgtec.com> In-Reply-To: <1405354795-25884-3-git-send-email-leon.alrae@imgtec.com> Content-Type: text/plain; charset="windows-1252"; format=flowed Content-Transfer-Encoding: 7bit Subject: Re: [Qemu-devel] [PATCH 2/6] target-mips: implement forbidden slot List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: Leon Alrae , qemu-devel@nongnu.org Cc: aurelien@aurel32.net On 14/07/2014 17:19, Leon Alrae wrote: > When conditional compact branch is encountered decode one more instruction in > current translation block - that will be forbidden slot. Instruction in > forbidden slot will be executed only if conditional compact branch is not taken. > > Any control transfer instruction (CTI) which are branches, jumps, ERET, > DERET, WAIT and PAUSE will generate RI exception if executed in forbidden or > delay slot. > > Signed-off-by: Leon Alrae > --- > target-mips/cpu.h | 5 ++- > target-mips/translate.c | 89 +++++++++++++++++++++++++++++++--------------- > 2 files changed, 63 insertions(+), 31 deletions(-) > > diff --git a/target-mips/cpu.h b/target-mips/cpu.h > index 2a762d2..a35ab9d 100644 > --- a/target-mips/cpu.h > +++ b/target-mips/cpu.h > @@ -462,7 +462,7 @@ struct CPUMIPSState { > #define EXCP_INST_NOTAVAIL 0x2 /* No valid instruction word for BadInstr */ > uint32_t hflags; /* CPU State */ > /* TMASK defines different execution modes */ > -#define MIPS_HFLAG_TMASK 0x2C07FF > +#define MIPS_HFLAG_TMASK 0x6C07FF > #define MIPS_HFLAG_MODE 0x00007 /* execution modes */ > /* The KSU flags must be the lowest bits in hflags. The flag order > must be the same as defined for CP0 Status. This allows to use > @@ -488,7 +488,7 @@ struct CPUMIPSState { > * the delay slot, record what type of branch it is so that we can > * resume translation properly. It might be possible to reduce > * this from three bits to two. */ > -#define MIPS_HFLAG_BMASK_BASE 0x03800 > +#define MIPS_HFLAG_BMASK_BASE 0x403800 > #define MIPS_HFLAG_B 0x00800 /* Unconditional branch */ > #define MIPS_HFLAG_BC 0x01000 /* Conditional branch */ > #define MIPS_HFLAG_BL 0x01800 /* Likely branch */ > @@ -506,6 +506,7 @@ struct CPUMIPSState { > /* Extra flag about HWREna register. */ > #define MIPS_HFLAG_HWRENA_ULR 0x100000 /* ULR bit from HWREna is set. */ > #define MIPS_HFLAG_SBRI 0x200000 /* R6 SDBBP causes RI excpt. in user mode */ > +#define MIPS_HFLAG_FBNSLOT 0x400000 /* Forbidden slot */ > target_ulong btarget; /* Jump / branch target */ > target_ulong bcond; /* Branch condition (if needed) */ > > diff --git a/target-mips/translate.c b/target-mips/translate.c > index d0f695a..4ed81fe 100644 > --- a/target-mips/translate.c > +++ b/target-mips/translate.c > @@ -7686,12 +7686,20 @@ static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt, > case OPC_ERET: > 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; > + } > gen_helper_eret(cpu_env); > ctx->bstate = BS_EXCP; > break; > case OPC_DERET: > opn = "deret"; > check_insn(ctx, ISA_MIPS32); > + if (ctx->insn_flags & ISA_MIPS32R6 && ctx->hflags & MIPS_HFLAG_BMASK) { > + MIPS_DEBUG("CTI in delay / forbidden slot"); > + goto die; > + } > if (!(ctx->hflags & MIPS_HFLAG_DM)) { > MIPS_INVAL(opn); > generate_exception(ctx, EXCP_RI); > @@ -7703,6 +7711,10 @@ static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt, > case OPC_WAIT: > opn = "wait"; > check_insn(ctx, ISA_MIPS3 | ISA_MIPS32); > + if (ctx->insn_flags & ISA_MIPS32R6 && ctx->hflags & MIPS_HFLAG_BMASK) { > + MIPS_DEBUG("CTI in delay / forbidden slot"); > + goto die; > + } > /* If we get an exception, we want to restart at next instruction */ > ctx->pc += 4; > save_cpu_state(ctx, 1); > @@ -7729,6 +7741,12 @@ static void gen_compute_branch1(DisasContext *ctx, uint32_t op, > const char *opn = "cp1 cond branch"; > TCGv_i32 t0 = tcg_temp_new_i32(); > > + if (ctx->insn_flags & ISA_MIPS32R6 && ctx->hflags & MIPS_HFLAG_BMASK) { > + MIPS_DEBUG("CTI in delay / forbidden slot"); > + generate_exception(ctx, EXCP_RI); > + goto out; > + } > + > if (cc != 0) > check_insn(ctx, ISA_MIPS4 | ISA_MIPS32); > > @@ -10299,6 +10317,10 @@ static void gen_branch(DisasContext *ctx, int insn_bytes) > save_cpu_state(ctx, 0); > /* FIXME: Need to clear can_do_io. */ > switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) { > + case MIPS_HFLAG_FBNSLOT: > + MIPS_DEBUG("forbidden slot"); > + gen_goto_tb(ctx, 0, ctx->pc + insn_bytes); > + break; > case MIPS_HFLAG_B: > /* unconditional branch */ > MIPS_DEBUG("unconditional branch"); > @@ -15711,56 +15733,56 @@ static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc, > gen_branch(ctx, 4); > } else { > /* Conditional compact branch */ > - int l1 = gen_new_label(); > + int fs = gen_new_label(); > save_cpu_state(ctx, 0); > > switch (opc) { > case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */ > if (rs == 0 && rt != 0) { > /* OPC_BLEZALC */ > - tcg_gen_brcondi_tl(TCG_COND_LE, t1, 0, l1); > + tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs); > } else if (rs != 0 && rt != 0 && rs == rt) { > /* OPC_BGEZALC */ > - tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1); > + tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs); > } else { > /* OPC_BGEUC */ > - tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1); > + tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs); > } > break; > case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */ > if (rs == 0 && rt != 0) { > /* OPC_BGTZALC */ > - tcg_gen_brcondi_tl(TCG_COND_GT, t1, 0, l1); > + tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs); > } else if (rs != 0 && rt != 0 && rs == rt) { > /* OPC_BLTZALC */ > - tcg_gen_brcondi_tl(TCG_COND_LT, t1, 0, l1); > + tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs); > } else { > /* OPC_BLTUC */ > - tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1); > + tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs); > } > break; > case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */ > if (rs == 0 && rt != 0) { > /* OPC_BLEZC */ > - tcg_gen_brcondi_tl(TCG_COND_LE, t1, 0, l1); > + tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs); > } else if (rs != 0 && rt != 0 && rs == rt) { > /* OPC_BGEZC */ > - tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1); > + tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs); > } else { > /* OPC_BGEC */ > - tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1); > + tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs); > } > break; > case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */ > if (rs == 0 && rt != 0) { > /* OPC_BGTZC */ > - tcg_gen_brcondi_tl(TCG_COND_GT, t1, 0, l1); > + tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs); > } else if (rs != 0 && rt != 0 && rs == rt) { > /* OPC_BLTZC */ > - tcg_gen_brcondi_tl(TCG_COND_LT, t1, 0, l1); > + tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs); > } else { > /* OPC_BLTC */ > - tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1); > + tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs); > } > break; > case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */ > @@ -15789,10 +15811,10 @@ static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc, > tcg_gen_or_tl(t4, t4, input_overflow); > if (opc == OPC_BOVC) { > /* OPC_BOVC */ > - tcg_gen_brcondi_tl(TCG_COND_NE, t4, 0, l1); > + tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t4, 0, fs); > } else { > /* OPC_BNVC */ > - tcg_gen_brcondi_tl(TCG_COND_EQ, t4, 0, l1); > + tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t4, 0, fs); > } > tcg_temp_free(input_overflow); > tcg_temp_free(t4); > @@ -15802,27 +15824,27 @@ static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc, > /* OPC_BEQZALC, OPC_BNEZALC */ > if (opc == OPC_BEQZALC) { > /* OPC_BEQZALC */ > - tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1); > + tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t1, 0, fs); > } else { > /* OPC_BNEZALC */ > - tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1); > + tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t1, 0, fs); > } > } else { > /* OPC_BEQC, OPC_BNEC */ > if (opc == OPC_BEQC) { > /* OPC_BEQC */ > - tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1); > + tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_EQ), t0, t1, fs); > } else { > /* OPC_BNEC */ > - tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1); > + tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_NE), t0, t1, fs); > } > } > break; > case OPC_BEQZC: > - tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); > + tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs); > break; > case OPC_BNEZC: > - tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1); > + tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t0, 0, fs); > break; > default: > MIPS_INVAL("Compact conditional branch/jump"); > @@ -15831,12 +15853,11 @@ static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc, > } > > /* Generating branch here as compact branches don't have delay slot */ > - /* TODO: implement forbidden slot */ > - gen_goto_tb(ctx, 1, ctx->pc + 4); > - gen_set_label(l1); > - gen_goto_tb(ctx, 0, ctx->btarget); > + gen_goto_tb(ctx, 1, ctx->btarget); > + gen_set_label(fs); > + > + ctx->hflags |= MIPS_HFLAG_FBNSLOT; > MIPS_DEBUG("Compact conditional branch"); > - ctx->bstate = BS_BRANCH; > } > > out: > @@ -16054,6 +16075,16 @@ static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx) > op1 = MASK_SPECIAL(ctx->opcode); > switch (op1) { > case OPC_SLL: /* Shift with immediate */ > + if (sa == 5 && rd == 0 && > + rs == 0 && rt == 0) { /* PAUSE */ > + if (ctx->insn_flags & ISA_MIPS32R6 && > + ctx->hflags & MIPS_HFLAG_BMASK) { > + MIPS_DEBUG("CTI in delay / forbidden slot"); > + generate_exception(ctx, EXCP_RI); > + break; > + } > + } > + /* Fallthrough */ > case OPC_SRA: > gen_shift_imm(ctx, op1, rd, rt, sa); > break; > @@ -17647,7 +17678,7 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb, > int num_insns; > int max_insns; > int insn_bytes; > - int is_delay; > + int is_slot; > > if (search_pc) > qemu_log("search pc %d\n", search_pc); > @@ -17712,7 +17743,7 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb, > if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) > gen_io_start(); > > - is_delay = ctx.hflags & MIPS_HFLAG_BMASK; > + is_slot = ctx.hflags & MIPS_HFLAG_BMASK; > if (!(ctx.hflags & MIPS_HFLAG_M16)) { > ctx.opcode = cpu_ldl_code(env, ctx.pc); > insn_bytes = 4; > @@ -17729,7 +17760,7 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb, > break; > } > > - if (is_delay) { > + if (is_slot) { > gen_branch(&ctx, insn_bytes); > } > ctx.pc += insn_bytes; Comments on 4155 , 7839 and 15616 are also required changes to indicate it might be delay or forbidden slot. Otherwise, Reviewed-by: Yongbok Kim Regards, Yongbok