On Mon, Aug 20, 2018 at 8:17 PM Aleksandar Markovic <aleksandar.marko...@rt-rk.com> wrote: > > From: Stefan Markovic <smarko...@wavecomp.com> > > Add emulation of nanoMIPS 16-bit branch instructions. > > Reviewed-by: Richard Henderson <richard.hender...@linaro.org> > Signed-off-by: Yongbok Kim <yongbok....@mips.com> > Signed-off-by: Aleksandar Markovic <amarko...@wavecomp.com> > Signed-off-by: Stefan Markovic <smarko...@wavecomp.com> > --- > target/mips/translate.c | 158 > ++++++++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 158 insertions(+) > > diff --git a/target/mips/translate.c b/target/mips/translate.c > index 261680e..b0bbf4c 100644 > --- a/target/mips/translate.c > +++ b/target/mips/translate.c > @@ -4564,6 +4564,128 @@ static void gen_compute_branch (DisasContext *ctx, > uint32_t opc, > tcg_temp_free(t1); > } > > + > +/* nanoMIPS Branches */ > +static void gen_compute_branch_nm(DisasContext *ctx, uint32_t opc, > + int insn_bytes, > + int rs, int rt, int32_t offset) > +{ > + target_ulong btgt = -1; > + int bcond_compute = 0; > + TCGv t0 = tcg_temp_new(); > + TCGv t1 = tcg_temp_new(); > + > + /* Load needed operands */ > + switch (opc) { > + case OPC_BEQ: > + case OPC_BNE: > + /* Compare two registers */ > + if (rs != rt) { > + gen_load_gpr(t0, rs); > + gen_load_gpr(t1, rt); > + bcond_compute = 1; > + } > + btgt = ctx->base.pc_next + insn_bytes + offset; > + break; > + case OPC_BGEZAL: > + /* Compare to zero */ > + if (rs != 0) { > + gen_load_gpr(t0, rs); > + bcond_compute = 1; > + } > + btgt = ctx->base.pc_next + insn_bytes + offset; > + break; > + case OPC_BPOSGE32: > + tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F); > + bcond_compute = 1; > + btgt = ctx->base.pc_next + insn_bytes + offset; > + break; > + case OPC_JR: > + case OPC_JALR: > + /* Jump to register */ > + if (offset != 0 && offset != 16) { > + /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the > + others are reserved. */ > + MIPS_INVAL("jump hint"); > + generate_exception_end(ctx, EXCP_RI); > + goto out; > + } > + gen_load_gpr(btarget, rs); > + break; > + default: > + MIPS_INVAL("branch/jump"); > + generate_exception_end(ctx, EXCP_RI); > + goto out; > + } > + if (bcond_compute == 0) { > + /* No condition to be computed */ > + switch (opc) { > + case OPC_BEQ: /* rx == rx */ > + /* Always take */ > + ctx->hflags |= MIPS_HFLAG_B; > + break; > + case OPC_BGEZAL: /* 0 >= 0 */ > + /* Always take and link */ > + tcg_gen_movi_tl(cpu_gpr[31], > + ctx->base.pc_next + insn_bytes); > + ctx->hflags |= MIPS_HFLAG_B; > + break; > + case OPC_BNE: /* rx != rx */ > + tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8); > + /* Skip the instruction in the delay slot */ > + ctx->base.pc_next += 4; > + goto out; > + case OPC_JR: > + ctx->hflags |= MIPS_HFLAG_BR; > + break; > + case OPC_JALR: > + if (rt > 0) { > + tcg_gen_movi_tl(cpu_gpr[rt], > + ctx->base.pc_next + insn_bytes); > + } > + ctx->hflags |= MIPS_HFLAG_BR; > + break; > + default: > + MIPS_INVAL("branch/jump"); > + generate_exception_end(ctx, EXCP_RI); > + goto out; > + } > + } else { > + switch (opc) { > + case OPC_BEQ: > + tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1); > + goto not_likely; > + case OPC_BNE: > + tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1); > + goto not_likely; > + case OPC_BGEZAL: > + tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0); > + tcg_gen_movi_tl(cpu_gpr[31], > + ctx->base.pc_next + insn_bytes); > + goto not_likely; > + case OPC_BPOSGE32: > + tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
This opcode implementation seems incomplete, per the ISA manual: If a control transfer instruction (CTI) is executed in the forbidden slot of a branch or jump, Release 6 implementations are required to signal a Reserved Instruction Exception. A CTI is considered to be one of the following instructions: branch, jump, NAL (Release 6), ERET, ERETNC (Release 5), DERET, WAIT, or PAUSE (Release 2). An instruction is in the forbidden slot if it is the instruction following the branch. > + not_likely: > + ctx->hflags |= MIPS_HFLAG_BC; > + break; > + default: > + MIPS_INVAL("conditional branch/jump"); > + generate_exception_end(ctx, EXCP_RI); > + goto out; > + } > + } > + > + ctx->btarget = btgt; > + > + out: > + if (insn_bytes == 2) { > + ctx->hflags |= MIPS_HFLAG_B16; > + } > + tcg_temp_free(t0); > + tcg_temp_free(t1); > +}