[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH v4 09/15] target-mips: microMIPS32 R6 branches and j
From: |
Yongbok Kim |
Subject: |
[Qemu-devel] [PATCH v4 09/15] target-mips: microMIPS32 R6 branches and jumps |
Date: |
Thu, 25 Jun 2015 00:24:21 +0100 |
Add new microMIPS32 Release 6 branch and jump instructions.
Signed-off-by: Yongbok Kim <address@hidden>
Reviewed-by: Leon Alrae <address@hidden>
Reviewed-by: Aurelien Jarno <address@hidden>
---
target-mips/translate.c | 242 +++++++++++++++++++++++++++++++++++++++--------
1 files changed, 202 insertions(+), 40 deletions(-)
diff --git a/target-mips/translate.c b/target-mips/translate.c
index 0aaf5e0..0f5b407 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -8441,7 +8441,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";
@@ -8484,7 +8485,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);
@@ -10985,6 +10994,7 @@ static void gen_compute_compact_branch(DisasContext
*ctx, uint32_t opc,
int bcond_compute = 0;
TCGv t0 = tcg_temp_new();
TCGv t1 = tcg_temp_new();
+ int m16_lowbit = (ctx->hflags & MIPS_HFLAG_M16) != 0;
if (ctx->hflags & MIPS_HFLAG_BMASK) {
#ifdef MIPS_DEBUG_DISAS
@@ -11006,7 +11016,7 @@ 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 + m16_lowbit);
}
break;
case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
@@ -11021,7 +11031,7 @@ 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 + m16_lowbit);
}
gen_load_gpr(t0, rs);
gen_load_gpr(t1, rt);
@@ -11061,13 +11071,13 @@ 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 + m16_lowbit);
/* 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 + m16_lowbit);
/* Fallthrough */
case OPC_BC:
ctx->hflags |= MIPS_HFLAG_B;
@@ -13403,10 +13413,16 @@ static void gen_pool32axf (CPUMIPSState *env,
DisasContext *ctx, int rt, int rs)
break;
case 0x3c:
switch (minor) {
- case JALR:
- case JALR_HB:
- gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 4);
- ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
+ case JALR: /* JALRC */
+ case JALR_HB: /* JALRC_HB */
+ if (ctx->insn_flags & ISA_MIPS32R6) {
+ /* JALRC, JALRC_HB */
+ gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 0);
+ } else {
+ /* JALR, JALR_HB */
+ gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 4);
+ ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
+ }
break;
case JALRS:
case JALRS_HB:
@@ -14381,12 +14397,28 @@ static void decode_micromips32_opc(CPUMIPSState *env,
DisasContext *ctx)
break;
/* Traps */
- case TLTI:
- mips32_op = OPC_TLTI;
- goto do_trapi;
- case TGEI:
- mips32_op = OPC_TGEI;
- goto do_trapi;
+ case TLTI: /* BC1EQZC */
+ if (ctx->insn_flags & ISA_MIPS32R6) {
+ /* BC1EQZC */
+ check_cp1_enabled(ctx);
+ gen_compute_branch1_r6(ctx, OPC_BC1EQZ, rs, imm << 1, 0);
+ } else {
+ /* TLTI */
+ mips32_op = OPC_TLTI;
+ goto do_trapi;
+ }
+ break;
+ case TGEI: /* BC1NEZC */
+ if (ctx->insn_flags & ISA_MIPS32R6) {
+ /* BC1NEZC */
+ check_cp1_enabled(ctx);
+ gen_compute_branch1_r6(ctx, OPC_BC1NEZ, rs, imm << 1, 0);
+ } else {
+ /* TGEI */
+ mips32_op = OPC_TGEI;
+ goto do_trapi;
+ }
+ break;
case TLTIU:
check_insn_opc_removed(ctx, ISA_MIPS32R6);
mips32_op = OPC_TLTIU;
@@ -14588,27 +14620,84 @@ static void decode_micromips32_opc(CPUMIPSState *env,
DisasContext *ctx)
gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset, 4);
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;
+ case JALS32: /* 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 {
+ /* 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;
+ }
break;
- case BEQ32:
- gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1, 4);
+ case BEQ32: /* BC */
+ if (ctx->insn_flags & ISA_MIPS32R6) {
+ /* BC */
+ gen_compute_compact_branch(ctx, OPC_BC, 0, 0,
+ sextract32(ctx->opcode << 1, 0, 27));
+ } else {
+ /* BEQ32 */
+ 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);
+ case BNE32: /* BALC */
+ if (ctx->insn_flags & ISA_MIPS32R6) {
+ /* BALC */
+ gen_compute_compact_branch(ctx, OPC_BALC, 0, 0,
+ sextract32(ctx->opcode << 1, 0, 27));
+ } else {
+ /* BNE32 */
+ 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);
+ case J32: /* BGTZC, BLTZC, BLTC */
+ if (ctx->insn_flags & ISA_MIPS32R6) {
+ if (rs == 0 && rt != 0) {
+ /* BGTZC */
+ mips32_op = OPC_BGTZC;
+ } else if (rs != 0 && rt != 0 && rs == rt) {
+ /* BLTZC */
+ mips32_op = OPC_BLTZC;
+ } else {
+ /* BLTC */
+ mips32_op = OPC_BLTC;
+ }
+ gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
+ } else {
+ /* J32 */
+ 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;
+ case JAL32: /* BLEZC, BGEZC, BGEC */
+ if (ctx->insn_flags & ISA_MIPS32R6) {
+ if (rs == 0 && rt != 0) {
+ /* BLEZC */
+ mips32_op = OPC_BLEZC;
+ } else if (rs != 0 && rt != 0 && rs == rt) {
+ /* BGEZC */
+ mips32_op = OPC_BGEZC;
+ } else {
+ /* BGEC */
+ mips32_op = OPC_BGEC;
+ }
+ gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
+ } else {
+ /* JAL32 */
+ 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:
@@ -14633,6 +14722,70 @@ 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) {
+ /* BNEZC */
+ gen_compute_compact_branch(ctx, OPC_BNEZC, rt, 0,
+ sextract32(ctx->opcode << 1, 0, 22));
+ } else {
+ /* JIALC */
+ gen_compute_compact_branch(ctx, OPC_JIALC, 0, rs, imm);
+ }
+ break;
+ case R6_BEQZC: /* JIC */
+ check_insn(ctx, ISA_MIPS32R6);
+ if (rt != 0) {
+ /* BEQZC */
+ gen_compute_compact_branch(ctx, OPC_BEQZC, rt, 0,
+ sextract32(ctx->opcode << 1, 0, 22));
+ } else {
+ /* JIC */
+ 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) {
+ /* BLEZALC */
+ mips32_op = OPC_BLEZALC;
+ } else if (rs != 0 && rt != 0 && rs == rt) {
+ /* BGEZALC */
+ mips32_op = OPC_BGEZALC;
+ } else {
+ /* BGEUC */
+ 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) {
+ /* BGTZALC */
+ mips32_op = OPC_BGTZALC;
+ } else if (rs != 0 && rt != 0 && rs == rt) {
+ /* BLTZALC */
+ mips32_op = OPC_BLTZALC;
+ } else {
+ /* BLTUC */
+ 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;
@@ -14910,15 +15063,18 @@ static int decode_micromips_opc (CPUMIPSState *env,
DisasContext *ctx)
break;
}
break;
- case B16:
+ case B16: /* BC16 */
gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
- SIMM(ctx->opcode, 0, 10) << 1, 4);
+ sextract32(ctx->opcode, 0, 10) << 1,
+ (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
break;
- case BNEZ16:
- case BEQZ16:
+ 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, sextract32(ctx->opcode, 0, 7) << 1,
+ (ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
+
break;
case LI16:
{
@@ -19287,7 +19443,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);
@@ -19300,7 +19456,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);
@@ -19695,6 +19851,12 @@ gen_intermediate_code_internal(MIPSCPU *cpu,
TranslationBlock *tb,
forbidden slot */
is_slot = 1;
}
+ if ((ctx.hflags & MIPS_HFLAG_M16) &&
+ (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
- [Qemu-devel] [PATCH v4 04/15] target-mips: refactor {D}LSA, {D}ALIGN, {D}BITSWAP, (continued)
- [Qemu-devel] [PATCH v4 04/15] target-mips: refactor {D}LSA, {D}ALIGN, {D}BITSWAP, Yongbok Kim, 2015/06/24
- [Qemu-devel] [PATCH v4 08/15] target-mips: add microMIPS32 R6 opcode enum, Yongbok Kim, 2015/06/24
- [Qemu-devel] [PATCH v4 10/15] target-mips: microMIPS32 R6 POOL32A{XF} instructions, Yongbok Kim, 2015/06/24
- [Qemu-devel] [PATCH v4 05/15] target-mips: rearrange gen_compute_compact_branch, Yongbok Kim, 2015/06/24
- [Qemu-devel] [PATCH v4 12/15] target-mips: microMIPS32 R6 POOL32{I, C} instructions, Yongbok Kim, 2015/06/24
- [Qemu-devel] [PATCH v4 13/15] target-mips: microMIPS32 R6 Major instructions, Yongbok Kim, 2015/06/24
- [Qemu-devel] [PATCH v4 06/15] target-mips: raise RI exceptions when FIR.PS = 0, Yongbok Kim, 2015/06/24
- [Qemu-devel] [PATCH v4 11/15] target-mips: microMIPS32 R6 POOL32F instructions, Yongbok Kim, 2015/06/24
- [Qemu-devel] [PATCH v4 15/15] target-mips: add mips32r6-generic CPU definition, Yongbok Kim, 2015/06/24
- [Qemu-devel] [PATCH v4 09/15] target-mips: microMIPS32 R6 branches and jumps,
Yongbok Kim <=
- [Qemu-devel] [PATCH v4 07/15] target-mips: signal RI for removed instructions in microMIPS R6, Yongbok Kim, 2015/06/24
- [Qemu-devel] [PATCH v4 14/15] target-mips: microMIPS32 R6 POOL16{A, C} instructions, Yongbok Kim, 2015/06/24