Skip to content

Commit 339cd2a

Browse files
author
Leon Alrae
committed
target-mips: implement forbidden slot
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 <leon.alrae@imgtec.com> Reviewed-by: Yongbok Kim <yongbok.kim@imgtec.com>
1 parent faf1f68 commit 339cd2a

File tree

2 files changed

+76
-36
lines changed

2 files changed

+76
-36
lines changed

target-mips/cpu.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -488,7 +488,7 @@ struct CPUMIPSState {
488488
* the delay slot, record what type of branch it is so that we can
489489
* resume translation properly. It might be possible to reduce
490490
* this from three bits to two. */
491-
#define MIPS_HFLAG_BMASK_BASE 0x03800
491+
#define MIPS_HFLAG_BMASK_BASE 0x803800
492492
#define MIPS_HFLAG_B 0x00800 /* Unconditional branch */
493493
#define MIPS_HFLAG_BC 0x01000 /* Conditional branch */
494494
#define MIPS_HFLAG_BL 0x01800 /* Likely branch */
@@ -507,6 +507,7 @@ struct CPUMIPSState {
507507
/* Extra flag about HWREna register. */
508508
#define MIPS_HFLAG_HWRENA_ULR 0x200000 /* ULR bit from HWREna is set. */
509509
#define MIPS_HFLAG_SBRI 0x400000 /* R6 SDBBP causes RI excpt. in user mode */
510+
#define MIPS_HFLAG_FBNSLOT 0x800000 /* Forbidden slot */
510511
target_ulong btarget; /* Jump / branch target */
511512
target_ulong bcond; /* Branch condition (if needed) */
512513

target-mips/translate.c

Lines changed: 74 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -4136,7 +4136,8 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
41364136

41374137
if (ctx->hflags & MIPS_HFLAG_BMASK) {
41384138
#ifdef MIPS_DEBUG_DISAS
4139-
LOG_DISAS("Branch in delay slot at PC 0x" TARGET_FMT_lx "\n", ctx->pc);
4139+
LOG_DISAS("Branch in delay / forbidden slot at PC 0x"
4140+
TARGET_FMT_lx "\n", ctx->pc);
41404141
#endif
41414142
generate_exception(ctx, EXCP_RI);
41424143
goto out;
@@ -7638,12 +7639,22 @@ static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt,
76387639
case OPC_ERET:
76397640
opn = "eret";
76407641
check_insn(ctx, ISA_MIPS2);
7642+
if ((ctx->insn_flags & ISA_MIPS32R6) &&
7643+
(ctx->hflags & MIPS_HFLAG_BMASK)) {
7644+
MIPS_DEBUG("CTI in delay / forbidden slot");
7645+
goto die;
7646+
}
76417647
gen_helper_eret(cpu_env);
76427648
ctx->bstate = BS_EXCP;
76437649
break;
76447650
case OPC_DERET:
76457651
opn = "deret";
76467652
check_insn(ctx, ISA_MIPS32);
7653+
if ((ctx->insn_flags & ISA_MIPS32R6) &&
7654+
(ctx->hflags & MIPS_HFLAG_BMASK)) {
7655+
MIPS_DEBUG("CTI in delay / forbidden slot");
7656+
goto die;
7657+
}
76477658
if (!(ctx->hflags & MIPS_HFLAG_DM)) {
76487659
MIPS_INVAL(opn);
76497660
generate_exception(ctx, EXCP_RI);
@@ -7655,6 +7666,11 @@ static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt,
76557666
case OPC_WAIT:
76567667
opn = "wait";
76577668
check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
7669+
if ((ctx->insn_flags & ISA_MIPS32R6) &&
7670+
(ctx->hflags & MIPS_HFLAG_BMASK)) {
7671+
MIPS_DEBUG("CTI in delay / forbidden slot");
7672+
goto die;
7673+
}
76587674
/* If we get an exception, we want to restart at next instruction */
76597675
ctx->pc += 4;
76607676
save_cpu_state(ctx, 1);
@@ -7681,6 +7697,12 @@ static void gen_compute_branch1(DisasContext *ctx, uint32_t op,
76817697
const char *opn = "cp1 cond branch";
76827698
TCGv_i32 t0 = tcg_temp_new_i32();
76837699

7700+
if ((ctx->insn_flags & ISA_MIPS32R6) && (ctx->hflags & MIPS_HFLAG_BMASK)) {
7701+
MIPS_DEBUG("CTI in delay / forbidden slot");
7702+
generate_exception(ctx, EXCP_RI);
7703+
goto out;
7704+
}
7705+
76847706
if (cc != 0)
76857707
check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
76867708

@@ -7797,7 +7819,8 @@ static void gen_compute_branch1_r6(DisasContext *ctx, uint32_t op,
77977819

77987820
if (ctx->hflags & MIPS_HFLAG_BMASK) {
77997821
#ifdef MIPS_DEBUG_DISAS
7800-
LOG_DISAS("Branch in delay slot at PC 0x" TARGET_FMT_lx "\n", ctx->pc);
7822+
LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
7823+
"\n", ctx->pc);
78017824
#endif
78027825
generate_exception(ctx, EXCP_RI);
78037826
goto out;
@@ -10251,6 +10274,10 @@ static void gen_branch(DisasContext *ctx, int insn_bytes)
1025110274
save_cpu_state(ctx, 0);
1025210275
/* FIXME: Need to clear can_do_io. */
1025310276
switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
10277+
case MIPS_HFLAG_FBNSLOT:
10278+
MIPS_DEBUG("forbidden slot");
10279+
gen_goto_tb(ctx, 0, ctx->pc + insn_bytes);
10280+
break;
1025410281
case MIPS_HFLAG_B:
1025510282
/* unconditional branch */
1025610283
MIPS_DEBUG("unconditional branch");
@@ -15533,7 +15560,8 @@ static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
1553315560

1553415561
if (ctx->hflags & MIPS_HFLAG_BMASK) {
1553515562
#ifdef MIPS_DEBUG_DISAS
15536-
LOG_DISAS("Branch in delay slot at PC 0x" TARGET_FMT_lx "\n", ctx->pc);
15563+
LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
15564+
"\n", ctx->pc);
1553715565
#endif
1553815566
generate_exception(ctx, EXCP_RI);
1553915567
goto out;
@@ -15626,56 +15654,56 @@ static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
1562615654
gen_branch(ctx, 4);
1562715655
} else {
1562815656
/* Conditional compact branch */
15629-
int l1 = gen_new_label();
15657+
int fs = gen_new_label();
1563015658
save_cpu_state(ctx, 0);
1563115659

1563215660
switch (opc) {
1563315661
case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
1563415662
if (rs == 0 && rt != 0) {
1563515663
/* OPC_BLEZALC */
15636-
tcg_gen_brcondi_tl(TCG_COND_LE, t1, 0, l1);
15664+
tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
1563715665
} else if (rs != 0 && rt != 0 && rs == rt) {
1563815666
/* OPC_BGEZALC */
15639-
tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
15667+
tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
1564015668
} else {
1564115669
/* OPC_BGEUC */
15642-
tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
15670+
tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
1564315671
}
1564415672
break;
1564515673
case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
1564615674
if (rs == 0 && rt != 0) {
1564715675
/* OPC_BGTZALC */
15648-
tcg_gen_brcondi_tl(TCG_COND_GT, t1, 0, l1);
15676+
tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
1564915677
} else if (rs != 0 && rt != 0 && rs == rt) {
1565015678
/* OPC_BLTZALC */
15651-
tcg_gen_brcondi_tl(TCG_COND_LT, t1, 0, l1);
15679+
tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
1565215680
} else {
1565315681
/* OPC_BLTUC */
15654-
tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
15682+
tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
1565515683
}
1565615684
break;
1565715685
case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
1565815686
if (rs == 0 && rt != 0) {
1565915687
/* OPC_BLEZC */
15660-
tcg_gen_brcondi_tl(TCG_COND_LE, t1, 0, l1);
15688+
tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
1566115689
} else if (rs != 0 && rt != 0 && rs == rt) {
1566215690
/* OPC_BGEZC */
15663-
tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
15691+
tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
1566415692
} else {
1566515693
/* OPC_BGEC */
15666-
tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
15694+
tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
1566715695
}
1566815696
break;
1566915697
case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
1567015698
if (rs == 0 && rt != 0) {
1567115699
/* OPC_BGTZC */
15672-
tcg_gen_brcondi_tl(TCG_COND_GT, t1, 0, l1);
15700+
tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
1567315701
} else if (rs != 0 && rt != 0 && rs == rt) {
1567415702
/* OPC_BLTZC */
15675-
tcg_gen_brcondi_tl(TCG_COND_LT, t1, 0, l1);
15703+
tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
1567615704
} else {
1567715705
/* OPC_BLTC */
15678-
tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
15706+
tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
1567915707
}
1568015708
break;
1568115709
case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
@@ -15704,10 +15732,10 @@ static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
1570415732
tcg_gen_or_tl(t4, t4, input_overflow);
1570515733
if (opc == OPC_BOVC) {
1570615734
/* OPC_BOVC */
15707-
tcg_gen_brcondi_tl(TCG_COND_NE, t4, 0, l1);
15735+
tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t4, 0, fs);
1570815736
} else {
1570915737
/* OPC_BNVC */
15710-
tcg_gen_brcondi_tl(TCG_COND_EQ, t4, 0, l1);
15738+
tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t4, 0, fs);
1571115739
}
1571215740
tcg_temp_free(input_overflow);
1571315741
tcg_temp_free(t4);
@@ -15717,27 +15745,27 @@ static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
1571715745
/* OPC_BEQZALC, OPC_BNEZALC */
1571815746
if (opc == OPC_BEQZALC) {
1571915747
/* OPC_BEQZALC */
15720-
tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
15748+
tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t1, 0, fs);
1572115749
} else {
1572215750
/* OPC_BNEZALC */
15723-
tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
15751+
tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t1, 0, fs);
1572415752
}
1572515753
} else {
1572615754
/* OPC_BEQC, OPC_BNEC */
1572715755
if (opc == OPC_BEQC) {
1572815756
/* OPC_BEQC */
15729-
tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
15757+
tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_EQ), t0, t1, fs);
1573015758
} else {
1573115759
/* OPC_BNEC */
15732-
tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
15760+
tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_NE), t0, t1, fs);
1573315761
}
1573415762
}
1573515763
break;
1573615764
case OPC_BEQZC:
15737-
tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
15765+
tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
1573815766
break;
1573915767
case OPC_BNEZC:
15740-
tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
15768+
tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t0, 0, fs);
1574115769
break;
1574215770
default:
1574315771
MIPS_INVAL("Compact conditional branch/jump");
@@ -15746,12 +15774,11 @@ static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
1574615774
}
1574715775

1574815776
/* Generating branch here as compact branches don't have delay slot */
15749-
/* TODO: implement forbidden slot */
15750-
gen_goto_tb(ctx, 1, ctx->pc + 4);
15751-
gen_set_label(l1);
15752-
gen_goto_tb(ctx, 0, ctx->btarget);
15777+
gen_goto_tb(ctx, 1, ctx->btarget);
15778+
gen_set_label(fs);
15779+
15780+
ctx->hflags |= MIPS_HFLAG_FBNSLOT;
1575315781
MIPS_DEBUG("Compact conditional branch");
15754-
ctx->bstate = BS_BRANCH;
1575515782
}
1575615783

1575715784
out:
@@ -15969,6 +15996,16 @@ static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
1596915996
op1 = MASK_SPECIAL(ctx->opcode);
1597015997
switch (op1) {
1597115998
case OPC_SLL: /* Shift with immediate */
15999+
if (sa == 5 && rd == 0 &&
16000+
rs == 0 && rt == 0) { /* PAUSE */
16001+
if ((ctx->insn_flags & ISA_MIPS32R6) &&
16002+
(ctx->hflags & MIPS_HFLAG_BMASK)) {
16003+
MIPS_DEBUG("CTI in delay / forbidden slot");
16004+
generate_exception(ctx, EXCP_RI);
16005+
break;
16006+
}
16007+
}
16008+
/* Fallthrough */
1597216009
case OPC_SRA:
1597316010
gen_shift_imm(ctx, op1, rd, rt, sa);
1597416011
break;
@@ -17567,7 +17604,7 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb,
1756717604
int num_insns;
1756817605
int max_insns;
1756917606
int insn_bytes;
17570-
int is_delay;
17607+
int is_slot;
1757117608

1757217609
if (search_pc)
1757317610
qemu_log("search pc %d\n", search_pc);
@@ -17632,7 +17669,7 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb,
1763217669
if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
1763317670
gen_io_start();
1763417671

17635-
is_delay = ctx.hflags & MIPS_HFLAG_BMASK;
17672+
is_slot = ctx.hflags & MIPS_HFLAG_BMASK;
1763617673
if (!(ctx.hflags & MIPS_HFLAG_M16)) {
1763717674
ctx.opcode = cpu_ldl_code(env, ctx.pc);
1763817675
insn_bytes = 4;
@@ -17650,12 +17687,14 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb,
1765017687
}
1765117688

1765217689
if (ctx.hflags & MIPS_HFLAG_BMASK) {
17653-
if (!(ctx.hflags & (MIPS_HFLAG_BDS16 | MIPS_HFLAG_BDS32))) {
17654-
is_delay = 1;
17655-
/* force to generate branch as no delay slot is required */
17690+
if (!(ctx.hflags & (MIPS_HFLAG_BDS16 | MIPS_HFLAG_BDS32 |
17691+
MIPS_HFLAG_FBNSLOT))) {
17692+
/* force to generate branch as there is neither delay nor
17693+
forbidden slot */
17694+
is_slot = 1;
1765617695
}
1765717696
}
17658-
if (is_delay) {
17697+
if (is_slot) {
1765917698
gen_branch(&ctx, insn_bytes);
1766017699
}
1766117700
ctx.pc += insn_bytes;

0 commit comments

Comments
 (0)