[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 18/35] target/mips: Add nanoMIPS branch instructions
From: |
Yongbok Kim |
Subject: |
[Qemu-devel] [PATCH 18/35] target/mips: Add nanoMIPS branch instructions |
Date: |
Wed, 20 Jun 2018 13:06:03 +0100 |
Add nanoMIPS branch instructions
Signed-off-by: Yongbok Kim <address@hidden>
---
target/mips/translate.c | 277 ++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 277 insertions(+)
diff --git a/target/mips/translate.c b/target/mips/translate.c
index 08765a7..948d3d5 100644
--- a/target/mips/translate.c
+++ b/target/mips/translate.c
@@ -16597,6 +16597,168 @@ static void gen_pool32axf_nanomips_insn(CPUMIPSState
*env, DisasContext *ctx)
}
}
+/* Immediate Value Compact Branches */
+static void gen_compute_imm_branch(DisasContext *ctx, uint32_t opc,
+ int rt, int32_t imm, int32_t offset)
+{
+ int bcond_compute = 0;
+ TCGv t0 = tcg_temp_new();
+ TCGv t1 = tcg_temp_new();
+
+ if (ctx->hflags & MIPS_HFLAG_BMASK) {
+#ifdef MIPS_DEBUG_DISAS
+ LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
+ "\n", ctx->base.pc_next);
+#endif
+ generate_exception_end(ctx, EXCP_RI);
+ goto out;
+ }
+
+ gen_load_gpr(t0, rt);
+ tcg_gen_movi_tl(t1, imm);
+ ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
+
+ /* Load needed operands and calculate btarget */
+ switch (opc) {
+ case NM_BEQIC:
+ if (rt == 0 && imm == 0) {
+ /* Unconditional branch */
+ } else if (rt == 0 && imm != 0) {
+ /* Treat as NOP */
+ goto out;
+ } else {
+ bcond_compute = 1;
+ }
+ break;
+ case NM_BBEQZC:
+ case NM_BBNEZC:
+ if (imm >= 32 && !(ctx->hflags & MIPS_HFLAG_64)) {
+ generate_exception_end(ctx, EXCP_RI);
+ goto out;
+ } else if (rt == 0 && opc == NM_BBEQZC) {
+ /* Unconditional branch */
+ } else if (rt == 0 && opc == NM_BBNEZC) {
+ /* Treat as NOP */
+ goto out;
+ } else {
+ tcg_gen_shri_tl(t0, t0, imm);
+ tcg_gen_andi_tl(t0, t0, 1);
+ tcg_gen_movi_tl(t1, 0);
+ bcond_compute = 1;
+ }
+ break;
+ case NM_BNEIC:
+ if (rt == 0 && imm == 0) {
+ /* Treat as NOP */
+ goto out;
+ } else if (rt == 0 && imm != 0) {
+ /* Unconditional branch */
+ } else {
+ bcond_compute = 1;
+ }
+ break;
+ case NM_BGEIC:
+ if (rt == 0 && imm == 0) {
+ /* Unconditional branch */
+ } else {
+ bcond_compute = 1;
+ }
+ break;
+ case NM_BLTIC:
+ bcond_compute = 1;
+ break;
+ case NM_BGEIUC:
+ if (rt == 0 && imm == 0) {
+ /* Unconditional branch */
+ } else {
+ bcond_compute = 1;
+ }
+ break;
+ case NM_BLTIUC:
+ bcond_compute = 1;
+ break;
+ default:
+ MIPS_INVAL("Immediate Value Compact branch");
+ generate_exception_end(ctx, EXCP_RI);
+ goto out;
+ }
+
+ if (bcond_compute == 0) {
+ /* Uncoditional compact branch */
+ ctx->hflags |= MIPS_HFLAG_B;
+ /* Generating branch here as compact branches don't have delay slot */
+ gen_branch(ctx, 4);
+ } else {
+ /* Conditional compact branch */
+ TCGLabel *fs = gen_new_label();
+ save_cpu_state(ctx, 0);
+
+ switch (opc) {
+ case NM_BEQIC:
+ tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_EQ), t0, t1, fs);
+ break;
+ case NM_BBEQZC:
+ tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_EQ), t0, t1, fs);
+ break;
+ case NM_BNEIC:
+ tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_NE), t0, t1, fs);
+ break;
+ case NM_BBNEZC:
+ tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_NE), t0, t1, fs);
+ break;
+ case NM_BGEIC:
+ tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
+ break;
+ case NM_BLTIC:
+ tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
+ break;
+ case NM_BGEIUC:
+ tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
+ break;
+ case NM_BLTIUC:
+ tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
+ break;
+ }
+
+ /* Generating branch here as compact branches don't have delay slot */
+ gen_goto_tb(ctx, 1, ctx->btarget);
+ gen_set_label(fs);
+
+ ctx->hflags |= MIPS_HFLAG_FBNSLOT;
+ }
+
+out:
+ tcg_temp_free(t0);
+ tcg_temp_free(t1);
+}
+
+/* P.BALRSC type nanoMIPS R6 branches: BALRSC and BRSC */
+static void gen_compute_nanomips_pbalrsc_branch(DisasContext *ctx, int rs,
+ int rt)
+{
+ TCGv t0 = tcg_temp_new();
+ TCGv t1 = tcg_temp_new();
+
+ /* load rs */
+ gen_load_gpr(t0, rs);
+
+ /* link */
+ if (rt != 0) {
+ tcg_gen_movi_tl(cpu_gpr[rt], ctx->base.pc_next + 4);
+ }
+
+ /* calculate btarget */
+ tcg_gen_shli_tl(t0, t0, 1);
+ tcg_gen_movi_tl(t1, ctx->base.pc_next + 4);
+ gen_op_addr_add(ctx, btarget, t1, t0);
+
+ ctx->hflags |= MIPS_HFLAG_BR;
+ /* Generating branch here as compact branches don't have delay slot */
+ gen_branch(ctx, 4);
+
+ tcg_temp_free(t0);
+ tcg_temp_free(t1);
+}
static void gen_p_lsx(DisasContext *ctx, int rd, int rs, int rt)
{
@@ -17656,16 +17818,131 @@ static int decode_nanomips_32_48_opc(CPUMIPSState
*env, DisasContext *ctx)
}
break;
case NM_MOVE_BALC:
+ {
+ TCGv t0 = tcg_temp_new();
+ int32_t s = sextract32(ctx->opcode, 0, 1) << 21 |
+ extract32(ctx->opcode, 1, 20) << 1;
+ rd = ((ctx->opcode >> 24) & 1) == 0 ? 4 : 5;
+ rt = mmreg4z_nanomips(extract32(ctx->opcode, 25, 1) << 3 |
+ extract32(ctx->opcode, 21, 3));
+ gen_load_gpr(t0, rt);
+ tcg_gen_mov_tl(cpu_gpr[rd], t0);
+ gen_compute_branch(ctx, OPC_BGEZAL, 4, 0, 0, s, 0);
+ tcg_temp_free(t0);
+ }
break;
case NM_P_BAL:
+ {
+ int32_t s = sextract32(ctx->opcode, 0, 1) << 25 |
+ extract32(ctx->opcode, 1, 24) << 1;
+
+ if (((ctx->opcode >> 25) & 1) == 0) {
+ /* BC */
+ gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, s, 0);
+ } else {
+ /* BALC */
+ gen_compute_branch(ctx, OPC_BGEZAL, 4, 0, 0, s, 0);
+ }
+ }
break;
case NM_P_J:
+ switch ((ctx->opcode >> 12) & 0x0f) {
+ case NM_JALRC:
+ case NM_JALRC_HB:
+ gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 0);
+ break;
+ case NM_P_BALRSC:
+ gen_compute_nanomips_pbalrsc_branch(ctx, rs, rt);
+ break;
+ default:
+ generate_exception_end(ctx, EXCP_RI);
+ break;
+ }
break;
case NM_P_BR1:
+ {
+ int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
+ extract32(ctx->opcode, 1, 13) << 1;
+ switch ((ctx->opcode >> 14) & 0x03) {
+ case NM_BEQC:
+ gen_compute_branch(ctx, OPC_BEQ, 4, rs, rt, s, 0);
+ break;
+ case NM_P_BR3A:
+ {
+ int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
+ extract32(ctx->opcode, 1, 13) << 1;
+ check_cp1_enabled(ctx);
+ switch ((ctx->opcode >> 16) & 0x1f) {
+ case NM_BC1EQZC:
+ gen_compute_branch1_r6(ctx, OPC_BC1EQZ, rt, s, 0);
+ break;
+ case NM_BC1NEZC:
+ gen_compute_branch1_r6(ctx, OPC_BC1NEZ, rt, s, 0);
+ break;
+ default:
+ generate_exception_end(ctx, EXCP_RI);
+ break;
+ }
+ }
+ break;
+ case NM_BGEC:
+ if (rs == rt) {
+ gen_compute_compact_branch(ctx, OPC_BC, rs, rt, s);
+ } else {
+ gen_compute_compact_branch(ctx, OPC_BGEC, rs, rt, s);
+ }
+ break;
+ case NM_BGEUC:
+ if (rs == rt || rt == 0) {
+ gen_compute_compact_branch(ctx, OPC_BC, 0, 0, s);
+ } else if (rs == 0) {
+ gen_compute_compact_branch(ctx, OPC_BEQZC, rt, 0, s);
+ } else {
+ gen_compute_compact_branch(ctx, OPC_BGEUC, rs, rt, s);
+ }
+ break;
+ }
+ }
break;
case NM_P_BR2:
+ {
+ int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
+ extract32(ctx->opcode, 1, 13) << 1;
+ switch ((ctx->opcode >> 14) & 0x03) {
+ case NM_BNEC:
+ gen_compute_branch(ctx, OPC_BNE, 4, rs, rt, s, 0);
+ break;
+ case NM_BLTC:
+ if (rs != 0 && rt != 0 && rs == rt) {
+ /* NOP */
+ ctx->hflags |= MIPS_HFLAG_FBNSLOT;
+ } else {
+ gen_compute_compact_branch(ctx, OPC_BLTC, rs, rt, s);
+ }
+ break;
+ case NM_BLTUC:
+ if (rs == 0 || rs == rt) {
+ /* NOP */
+ ctx->hflags |= MIPS_HFLAG_FBNSLOT;
+ } else {
+ gen_compute_compact_branch(ctx, OPC_BLTUC, rs, rt, s);
+ }
+ break;
+ default:
+ generate_exception_end(ctx, EXCP_RI);
+ break;
+ }
+ }
break;
case NM_P_BRI:
+ {
+ int32_t s = sextract32(ctx->opcode, 0, 1) << 11 |
+ extract32(ctx->opcode, 1, 10) << 1;
+ uint32_t u = extract32(ctx->opcode, 11, 7);
+
+ gen_compute_imm_branch(ctx, extract32(ctx->opcode, 18, 3),
+ rt, u, s);
+ }
break;
default:
generate_exception_end(ctx, EXCP_RI);
--
1.9.1
- Re: [Qemu-devel] [PATCH 11/35] target/mips: Add nanoMIPS pool32a0 instructions, (continued)
- [Qemu-devel] [PATCH 12/35] target/mips: Add nanoMIPS pool32axf instructions, Yongbok Kim, 2018/06/20
- [Qemu-devel] [PATCH 13/35] target/mips: Update gen_flt_ldst(), Yongbok Kim, 2018/06/20
- [Qemu-devel] [PATCH 14/35] target/mips: Add nanoMIPS p_lsx instructions, Yongbok Kim, 2018/06/20
- [Qemu-devel] [PATCH 15/35] target/mips: Implement nanoMIPS EXTW instruction, Yongbok Kim, 2018/06/20
- [Qemu-devel] [PATCH 16/35] target/mips: Add has_isa_mode, Yongbok Kim, 2018/06/20
- [Qemu-devel] [PATCH 17/35] target/mips: Add nanoMIPS load store instructions, Yongbok Kim, 2018/06/20
- [Qemu-devel] [PATCH 18/35] target/mips: Add nanoMIPS branch instructions,
Yongbok Kim <=
- [Qemu-devel] [PATCH 19/35] target/mips: Implement nanoMIPS LLWP/SCWP pair, Yongbok Kim, 2018/06/20
- [Qemu-devel] [PATCH 20/35] target/mips: Fix not to update BadVAddr in Debug Mode, Yongbok Kim, 2018/06/20
- [Qemu-devel] [PATCH 21/35] target/mips: Add nanoMIPS rotx instruction, Yongbok Kim, 2018/06/20
- [Qemu-devel] [PATCH 22/35] target/mips: Fix data type for offset, Yongbok Kim, 2018/06/20