From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:37726) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Z3PY6-0003y2-Ow for qemu-devel@nongnu.org; Fri, 12 Jun 2015 10:03:15 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Z3PY3-0000wb-2f for qemu-devel@nongnu.org; Fri, 12 Jun 2015 10:03:10 -0400 Received: from mailapp01.imgtec.com ([195.59.15.196]:10940) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Z3PY2-0000wU-R1 for qemu-devel@nongnu.org; Fri, 12 Jun 2015 10:03:07 -0400 From: Yongbok Kim Date: Fri, 12 Jun 2015 15:02:17 +0100 Message-ID: <1434117743-53520-8-git-send-email-yongbok.kim@imgtec.com> In-Reply-To: <1434117743-53520-1-git-send-email-yongbok.kim@imgtec.com> References: <1434117743-53520-1-git-send-email-yongbok.kim@imgtec.com> MIME-Version: 1.0 Content-Type: text/plain Subject: [Qemu-devel] [PATCH 07/13] target-mips: microMIPS32 R6 branches and jumps List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: leon.alrae@imgtec.com, aurelien@aurel32.net add new microMIPS32 Release 6 branch and jump instructions. Signed-off-by: Yongbok Kim --- target-mips/translate.c | 209 ++++++++++++++++++++++++++++++++++++++++------ 1 files changed, 181 insertions(+), 28 deletions(-) diff --git a/target-mips/translate.c b/target-mips/translate.c index fa81448..0efaa02 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -8198,7 +8198,8 @@ static void gen_compute_branch1(DisasContext *ctx, uint32_t op, /* R6 CP1 Branches */ static void gen_compute_branch1_r6(DisasContext *ctx, uint32_t op, - int32_t ft, int32_t offset) + int32_t ft, int32_t offset, + int delayslot_size) { target_ulong btarget; const char *opn = "cp1 cond branch"; @@ -8241,7 +8242,15 @@ static void gen_compute_branch1_r6(DisasContext *ctx, uint32_t op, MIPS_DEBUG("%s: cond %02x target " TARGET_FMT_lx, opn, ctx->hflags, btarget); ctx->btarget = btarget; - ctx->hflags |= MIPS_HFLAG_BDS32; + + switch (delayslot_size) { + case 2: + ctx->hflags |= MIPS_HFLAG_BDS16; + break; + case 4: + ctx->hflags |= MIPS_HFLAG_BDS32; + break; + } out: tcg_temp_free_i64(t0); @@ -10766,7 +10775,8 @@ static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc, ctx->btarget = addr_add(ctx, ctx->pc + 4, offset); if (rs <= rt && rs == 0) { /* OPC_BEQZALC, OPC_BNEZALC */ - tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4); + tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4 + + !!(ctx->hflags & MIPS_HFLAG_M16)); } break; case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */ @@ -10781,7 +10791,8 @@ static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc, if (rs == 0 || rs == rt) { /* OPC_BLEZALC, OPC_BGEZALC */ /* OPC_BGTZALC, OPC_BLTZALC */ - tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4); + tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4 + + !!(ctx->hflags & MIPS_HFLAG_M16)); } gen_load_gpr(t0, rs); gen_load_gpr(t1, rt); @@ -10821,13 +10832,15 @@ static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc, /* Uncoditional compact branch */ switch (opc) { case OPC_JIALC: - tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4); + tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4 + + !!(ctx->hflags & MIPS_HFLAG_M16)); /* Fallthrough */ case OPC_JIC: ctx->hflags |= MIPS_HFLAG_BR; break; case OPC_BALC: - tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4); + tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4 + + !!(ctx->hflags & MIPS_HFLAG_M16)); /* Fallthrough */ case OPC_BC: ctx->hflags |= MIPS_HFLAG_B; @@ -13169,8 +13182,13 @@ static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs) switch (minor) { case JALR: case JALR_HB: - gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 4); - ctx->hflags |= MIPS_HFLAG_BDS_STRICT; + /* JALRC */ + if (ctx->insn_flags & ISA_MIPS32R6) { + gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 0); + } else { + gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 4); + ctx->hflags |= MIPS_HFLAG_BDS_STRICT; + } break; case JALRS: case JALRS_HB: @@ -14144,11 +14162,25 @@ static void decode_micromips32_opc (CPUMIPSState *env, DisasContext *ctx, /* Traps */ case TLTI: - mips32_op = OPC_TLTI; - goto do_trapi; + /* BC1EQZC */ + if (ctx->insn_flags & ISA_MIPS32R6) { + check_cp1_enabled(ctx); + gen_compute_branch1_r6(ctx, OPC_BC1EQZ, rs, imm << 1, 0); + } else { + mips32_op = OPC_TLTI; + goto do_trapi; + } + break; case TGEI: - mips32_op = OPC_TGEI; - goto do_trapi; + /* BC1NEZC */ + if (ctx->insn_flags & ISA_MIPS32R6) { + check_cp1_enabled(ctx); + gen_compute_branch1_r6(ctx, OPC_BC1NEZ, rs, imm << 1, 0); + } else { + mips32_op = OPC_TGEI; + goto do_trapi; + } + break; case TLTIU: check_insn_opc_removed(ctx, ISA_MIPS32R6); mips32_op = OPC_TLTIU; @@ -14351,26 +14383,75 @@ static void decode_micromips32_opc (CPUMIPSState *env, DisasContext *ctx, ctx->hflags |= MIPS_HFLAG_BDS_STRICT; break; case JALS32: - offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1; - gen_compute_branch(ctx, OPC_JAL, 4, rt, rs, offset, 2); - ctx->hflags |= MIPS_HFLAG_BDS_STRICT; + /* BOVC, BEQC, BEQZALC */ + if (ctx->insn_flags & ISA_MIPS32R6) { + if (rs >= rt) { + /* BOVC */ + mips32_op = OPC_BOVC; + } else if (rs < rt && rs == 0) { + /* BEQZALC */ + mips32_op = OPC_BEQZALC; + } else { + /* BEQC */ + mips32_op = OPC_BEQC; + } + gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1); + } else { + offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1; + gen_compute_branch(ctx, OPC_JAL, 4, rt, rs, offset, 2); + ctx->hflags |= MIPS_HFLAG_BDS_STRICT; + } break; case BEQ32: - gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1, 4); + /* BC */ + if (ctx->insn_flags & ISA_MIPS32R6) { + gen_compute_compact_branch(ctx, OPC_BC, 0, 0, + sextract32(ctx->opcode << 1, 0, 27)); + } else { + gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1, 4); + } break; case BNE32: - gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1, 4); + /* BALC */ + if (ctx->insn_flags & ISA_MIPS32R6) { + gen_compute_compact_branch(ctx, OPC_BALC, 0, 0, + sextract32(ctx->opcode << 1, 0, 27)); + } else { + gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1, 4); + } break; case J32: - check_insn_opc_removed(ctx, ISA_MIPS32R6); - gen_compute_branch(ctx, OPC_J, 4, rt, rs, - (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4); + /* BGTZC, BLTZC, BLTC */ + if (ctx->insn_flags & ISA_MIPS32R6) { + if (rs == 0 && rt != 0) { + mips32_op = OPC_BGTZC; + } else if (rs != 0 && rt != 0 && rs == rt) { + mips32_op = OPC_BLTZC; + } else { + mips32_op = OPC_BLTC; + } + gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1); + } else { + gen_compute_branch(ctx, OPC_J, 4, rt, rs, + (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4); + } break; case JAL32: - check_insn_opc_removed(ctx, ISA_MIPS32R6); - gen_compute_branch(ctx, OPC_JAL, 4, rt, rs, - (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4); - ctx->hflags |= MIPS_HFLAG_BDS_STRICT; + /* BLEZC, BGEZC, BGEC */ + if (ctx->insn_flags & ISA_MIPS32R6) { + if (rs == 0 && rt != 0) { + mips32_op = OPC_BLEZC; + } else if (rs != 0 && rt != 0 && rs == rt) { + mips32_op = OPC_BGEZC; + } else { + mips32_op = OPC_BGEC; + } + gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1); + } else { + gen_compute_branch(ctx, OPC_JAL, 4, rt, rs, + (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4); + ctx->hflags |= MIPS_HFLAG_BDS_STRICT; + } break; /* Floating point (COP1) */ case LWC132: @@ -14395,6 +14476,65 @@ static void decode_micromips32_opc (CPUMIPSState *env, DisasContext *ctx, gen_addiupc(ctx, reg, offset, 0, 0); } break; + case BNVC: + /* BNEC, BNEZALC */ + check_insn(ctx, ISA_MIPS32R6); + if (rs >= rt) { + /* BNVC */ + mips32_op = OPC_BNVC; + } else if (rs < rt && rs == 0) { + /* BNEZALC */ + mips32_op = OPC_BNEZALC; + } else { + /* BNEC */ + mips32_op = OPC_BNEC; + } + gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1); + break; + case R6_BNEZC: + /* JIALC */ + check_insn(ctx, ISA_MIPS32R6); + if (rt != 0) { + gen_compute_compact_branch(ctx, OPC_BNEZC, rt, 0, + sextract32(ctx->opcode << 1, 0, 22)); + } else { + gen_compute_compact_branch(ctx, OPC_JIALC, 0, rs, imm); + } + break; + case R6_BEQZC: + /* JIC */ + check_insn(ctx, ISA_MIPS32R6); + if (rt != 0) { + gen_compute_compact_branch(ctx, OPC_BEQZC, rt, 0, + sextract32(ctx->opcode << 1, 0, 22)); + } else { + gen_compute_compact_branch(ctx, OPC_JIC, 0, rs, imm); + } + break; + case BLEZALC: + /* BGEZALC, BGEUC */ + check_insn(ctx, ISA_MIPS32R6); + if (rs == 0 && rt != 0) { + mips32_op = OPC_BLEZALC; + } else if (rs != 0 && rt != 0 && rs == rt) { + mips32_op = OPC_BGEZALC; + } else { + mips32_op = OPC_BGEUC; + } + gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1); + break; + case BGTZALC: + /* BLTZALC, BLTUC */ + check_insn(ctx, ISA_MIPS32R6); + if (rs == 0 && rt != 0) { + mips32_op = OPC_BGTZALC; + } else if (rs != 0 && rt != 0 && rs == rt) { + mips32_op = OPC_BLTZALC; + } else { + mips32_op = OPC_BLTUC; + } + gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1); + break; /* Loads and stores */ case LB32: mips32_op = OPC_LB; @@ -14673,14 +14813,20 @@ static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx) } break; case B16: + /* BC16 */ gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, - SIMM(ctx->opcode, 0, 10) << 1, 4); + SIMM(ctx->opcode, 0, 10) << 1, + (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4); break; case BNEZ16: + /* BNEZC16 */ case BEQZ16: + /* BEQZC16 */ gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2, mmreg(uMIPS_RD(ctx->opcode)), - 0, SIMM(ctx->opcode, 0, 7) << 1, 4); + 0, SIMM(ctx->opcode, 0, 7) << 1, + (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4); + break; case LI16: { @@ -19047,7 +19193,7 @@ static void decode_opc(CPUMIPSState *env, DisasContext *ctx) if (ctx->insn_flags & ISA_MIPS32R6) { /* OPC_BC1EQZ */ gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode), - rt, imm << 2); + rt, imm << 2, 4); } else { /* OPC_BC1ANY2 */ check_cop1x(ctx); @@ -19060,7 +19206,7 @@ static void decode_opc(CPUMIPSState *env, DisasContext *ctx) check_cp1_enabled(ctx); check_insn(ctx, ISA_MIPS32R6); gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode), - rt, imm << 2); + rt, imm << 2, 4); break; case OPC_BC1ANY4: check_cp1_enabled(ctx); @@ -19451,6 +19597,13 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb, forbidden slot */ is_slot = 1; } + if ((ctx.hflags & MIPS_HFLAG_M16) && + (ctx.insn_flags & ISA_MIPS32R6) && + (ctx.hflags & MIPS_HFLAG_FBNSLOT)) { + /* Force to generate branch as microMIPS R6 doesn't restrict + branches in the forbidden slot. */ + is_slot = 1; + } } if (is_slot) { gen_branch(&ctx, insn_bytes); -- 1.7.5.4