@@ -4136,7 +4136,8 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
4136
4136
4137
4137
if (ctx->hflags & MIPS_HFLAG_BMASK) {
4138
4138
#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);
4140
4141
#endif
4141
4142
generate_exception(ctx, EXCP_RI);
4142
4143
goto out;
@@ -7638,12 +7639,22 @@ static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt,
7638
7639
case OPC_ERET:
7639
7640
opn = "eret";
7640
7641
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
+ }
7641
7647
gen_helper_eret(cpu_env);
7642
7648
ctx->bstate = BS_EXCP;
7643
7649
break;
7644
7650
case OPC_DERET:
7645
7651
opn = "deret";
7646
7652
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
+ }
7647
7658
if (!(ctx->hflags & MIPS_HFLAG_DM)) {
7648
7659
MIPS_INVAL(opn);
7649
7660
generate_exception(ctx, EXCP_RI);
@@ -7655,6 +7666,11 @@ static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt,
7655
7666
case OPC_WAIT:
7656
7667
opn = "wait";
7657
7668
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
+ }
7658
7674
/* If we get an exception, we want to restart at next instruction */
7659
7675
ctx->pc += 4;
7660
7676
save_cpu_state(ctx, 1);
@@ -7681,6 +7697,12 @@ static void gen_compute_branch1(DisasContext *ctx, uint32_t op,
7681
7697
const char *opn = "cp1 cond branch";
7682
7698
TCGv_i32 t0 = tcg_temp_new_i32();
7683
7699
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
+
7684
7706
if (cc != 0)
7685
7707
check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
7686
7708
@@ -7797,7 +7819,8 @@ static void gen_compute_branch1_r6(DisasContext *ctx, uint32_t op,
7797
7819
7798
7820
if (ctx->hflags & MIPS_HFLAG_BMASK) {
7799
7821
#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);
7801
7824
#endif
7802
7825
generate_exception(ctx, EXCP_RI);
7803
7826
goto out;
@@ -10251,6 +10274,10 @@ static void gen_branch(DisasContext *ctx, int insn_bytes)
10251
10274
save_cpu_state(ctx, 0);
10252
10275
/* FIXME: Need to clear can_do_io. */
10253
10276
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;
10254
10281
case MIPS_HFLAG_B:
10255
10282
/* unconditional branch */
10256
10283
MIPS_DEBUG("unconditional branch");
@@ -15533,7 +15560,8 @@ static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
15533
15560
15534
15561
if (ctx->hflags & MIPS_HFLAG_BMASK) {
15535
15562
#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);
15537
15565
#endif
15538
15566
generate_exception(ctx, EXCP_RI);
15539
15567
goto out;
@@ -15626,56 +15654,56 @@ static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
15626
15654
gen_branch(ctx, 4);
15627
15655
} else {
15628
15656
/* Conditional compact branch */
15629
- int l1 = gen_new_label();
15657
+ int fs = gen_new_label();
15630
15658
save_cpu_state(ctx, 0);
15631
15659
15632
15660
switch (opc) {
15633
15661
case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
15634
15662
if (rs == 0 && rt != 0) {
15635
15663
/* 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 );
15637
15665
} else if (rs != 0 && rt != 0 && rs == rt) {
15638
15666
/* 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 );
15640
15668
} else {
15641
15669
/* 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 );
15643
15671
}
15644
15672
break;
15645
15673
case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
15646
15674
if (rs == 0 && rt != 0) {
15647
15675
/* 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 );
15649
15677
} else if (rs != 0 && rt != 0 && rs == rt) {
15650
15678
/* 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 );
15652
15680
} else {
15653
15681
/* 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 );
15655
15683
}
15656
15684
break;
15657
15685
case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
15658
15686
if (rs == 0 && rt != 0) {
15659
15687
/* 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 );
15661
15689
} else if (rs != 0 && rt != 0 && rs == rt) {
15662
15690
/* 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 );
15664
15692
} else {
15665
15693
/* 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 );
15667
15695
}
15668
15696
break;
15669
15697
case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
15670
15698
if (rs == 0 && rt != 0) {
15671
15699
/* 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 );
15673
15701
} else if (rs != 0 && rt != 0 && rs == rt) {
15674
15702
/* 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 );
15676
15704
} else {
15677
15705
/* 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 );
15679
15707
}
15680
15708
break;
15681
15709
case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
@@ -15704,10 +15732,10 @@ static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
15704
15732
tcg_gen_or_tl(t4, t4, input_overflow);
15705
15733
if (opc == OPC_BOVC) {
15706
15734
/* 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 );
15708
15736
} else {
15709
15737
/* 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 );
15711
15739
}
15712
15740
tcg_temp_free(input_overflow);
15713
15741
tcg_temp_free(t4);
@@ -15717,27 +15745,27 @@ static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
15717
15745
/* OPC_BEQZALC, OPC_BNEZALC */
15718
15746
if (opc == OPC_BEQZALC) {
15719
15747
/* 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 );
15721
15749
} else {
15722
15750
/* 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 );
15724
15752
}
15725
15753
} else {
15726
15754
/* OPC_BEQC, OPC_BNEC */
15727
15755
if (opc == OPC_BEQC) {
15728
15756
/* 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 );
15730
15758
} else {
15731
15759
/* 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 );
15733
15761
}
15734
15762
}
15735
15763
break;
15736
15764
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 );
15738
15766
break;
15739
15767
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 );
15741
15769
break;
15742
15770
default:
15743
15771
MIPS_INVAL("Compact conditional branch/jump");
@@ -15746,12 +15774,11 @@ static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
15746
15774
}
15747
15775
15748
15776
/* 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 ;
15753
15781
MIPS_DEBUG("Compact conditional branch");
15754
- ctx->bstate = BS_BRANCH;
15755
15782
}
15756
15783
15757
15784
out:
@@ -15969,6 +15996,16 @@ static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
15969
15996
op1 = MASK_SPECIAL(ctx->opcode);
15970
15997
switch (op1) {
15971
15998
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 */
15972
16009
case OPC_SRA:
15973
16010
gen_shift_imm(ctx, op1, rd, rt, sa);
15974
16011
break;
@@ -17567,7 +17604,7 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb,
17567
17604
int num_insns;
17568
17605
int max_insns;
17569
17606
int insn_bytes;
17570
- int is_delay ;
17607
+ int is_slot ;
17571
17608
17572
17609
if (search_pc)
17573
17610
qemu_log("search pc %d\n", search_pc);
@@ -17632,7 +17669,7 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb,
17632
17669
if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
17633
17670
gen_io_start();
17634
17671
17635
- is_delay = ctx.hflags & MIPS_HFLAG_BMASK;
17672
+ is_slot = ctx.hflags & MIPS_HFLAG_BMASK;
17636
17673
if (!(ctx.hflags & MIPS_HFLAG_M16)) {
17637
17674
ctx.opcode = cpu_ldl_code(env, ctx.pc);
17638
17675
insn_bytes = 4;
@@ -17650,12 +17687,14 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb,
17650
17687
}
17651
17688
17652
17689
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;
17656
17695
}
17657
17696
}
17658
- if (is_delay ) {
17697
+ if (is_slot ) {
17659
17698
gen_branch(&ctx, insn_bytes);
17660
17699
}
17661
17700
ctx.pc += insn_bytes;
0 commit comments