qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 62/77] target/microblaze: Try to keep imm and delay slot together


From: Richard Henderson
Subject: [PATCH 62/77] target/microblaze: Try to keep imm and delay slot together
Date: Tue, 25 Aug 2020 13:59:35 -0700

If the last insn on a page is imm, or a branch with delay slot,
then end a tb early if this has not begun the tb.  If it has
begun the tb, then we can allow the tb to span two pages as if
the imm plus its consumer, or branch plus delay, or imm plus
branch plus delay, are a single insn.

If the insn in the delay slot faults, then the exception handler
will have reset the PC to the beginning of this sequence anyway,
via the stored D_FLAG and BIMM_FLAG bits.

Disable all of this when single-stepping.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/microblaze/translate.c | 65 ++++++++++++++++++++++++++++++-----
 1 file changed, 56 insertions(+), 9 deletions(-)

diff --git a/target/microblaze/translate.c b/target/microblaze/translate.c
index 4675326083..fcfc1ac184 100644
--- a/target/microblaze/translate.c
+++ b/target/microblaze/translate.c
@@ -530,11 +530,50 @@ static void gen_idivu(TCGv_i32 out, TCGv_i32 ina, 
TCGv_i32 inb)
 DO_TYPEA_CFG(idiv, use_div, true, gen_idiv)
 DO_TYPEA_CFG(idivu, use_div, true, gen_idivu)
 
+/*
+ * Try to keep the current instruction with the one following.
+ * So if this insn is the last in the TB, and is not the first
+ * in the TB, and we are not singlestepping, then back up and
+ * exit the current TB.
+ */
+static bool wait_for_next_tb(DisasContext *dc)
+{
+    if (dc->base.num_insns >= dc->base.max_insns
+        && !dc->base.singlestep_enabled) {
+        /* Also consider if this insn (e.g. brid) itself uses an imm. */
+        int ninsns = (dc->tb_flags & IMM_FLAG ? 2 : 1);
+
+        /*
+         * If this is not the first insn in the TB, back up and
+         * start again with a new TB.
+         */
+        if (dc->base.num_insns > ninsns) {
+            dc->base.pc_next -= ninsns * 4;
+            dc->base.num_insns -= ninsns;
+            dc->base.is_jmp = DISAS_TOO_MANY;
+            return true;
+        }
+
+        /*
+         * Correspondingly, if this is the first insn of the TB,
+         * then extend the TB as necessary to keep it with the
+         * next insn.  Do this by *reducing* the number of insns
+         * processed by this TB so that icount does fail an assertion.
+         */
+        if (dc->base.num_insns == ninsns) {
+            dc->base.num_insns = 0;
+        }
+    }
+    return false;
+}
+
 static bool trans_imm(DisasContext *dc, arg_imm *arg)
 {
-    dc->ext_imm = arg->imm << 16;
-    tcg_gen_movi_i32(cpu_imm, dc->ext_imm);
-    dc->tb_flags_to_set = IMM_FLAG;
+    if (!wait_for_next_tb(dc)) {
+        dc->ext_imm = arg->imm << 16;
+        tcg_gen_movi_i32(cpu_imm, dc->ext_imm);
+        dc->tb_flags_to_set = IMM_FLAG;
+    }
     return true;
 }
 
@@ -1311,12 +1350,17 @@ static void eval_cond_jmp(DisasContext *dc, TCGv_i32 
pc_true, TCGv_i32 pc_false)
     tcg_temp_free_i32(zero);
 }
 
-static void dec_setup_dslot(DisasContext *dc)
+static bool dec_setup_dslot(DisasContext *dc)
 {
+    if (wait_for_next_tb(dc)) {
+        return true;
+    }
+
     dc->tb_flags_to_set |= D_FLAG;
     if (dc->type_b && (dc->tb_flags & IMM_FLAG)) {
         dc->tb_flags_to_set |= BIMM_FLAG;
     }
+    return false;
 }
 
 static void dec_bcc(DisasContext *dc)
@@ -1327,8 +1371,8 @@ static void dec_bcc(DisasContext *dc)
     cc = EXTRACT_FIELD(dc->ir, 21, 23);
     dslot = dc->ir & (1 << 25);
 
-    if (dslot) {
-        dec_setup_dslot(dc);
+    if (dslot && dec_setup_dslot(dc)) {
+        return;
     }
 
     if (dc->type_b) {
@@ -1402,9 +1446,10 @@ static void dec_br(DisasContext *dc)
         }
     }
 
-    if (dslot) {
-        dec_setup_dslot(dc);
+    if (dslot && dec_setup_dslot(dc)) {
+        return;
     }
+
     if (link && dc->rd) {
         tcg_gen_movi_i32(cpu_R[dc->rd], dc->base.pc_next);
     }
@@ -1513,7 +1558,9 @@ static void dec_rts(DisasContext *dc)
         return;
     }
 
-    dec_setup_dslot(dc);
+    if (dec_setup_dslot(dc)) {
+        return;
+    }
 
     if (i_bit) {
         dc->tb_flags |= DRTI_FLAG;
-- 
2.25.1




reply via email to

[Prev in Thread] Current Thread [Next in Thread]