qemu-devel
[Top][All Lists]
Advanced

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

[Qemu-devel] [PATCH 2/2] tcg: Fix allocation of indirect_base registers


From: Richard Henderson
Subject: [Qemu-devel] [PATCH 2/2] tcg: Fix allocation of indirect_base registers
Date: Fri, 17 Jun 2016 22:03:27 -0700

When the number of available registers is low, we need to be
prepared for TS to overlap MEM_BASE.

This fixes the Sparc64 OpenBIOS boot on i686.

Signed-off-by: Richard Henderson <address@hidden>
---
 tcg/tcg.c | 68 +++++++++++++++++++++++++++++++++++++++++++--------------------
 1 file changed, 47 insertions(+), 21 deletions(-)

diff --git a/tcg/tcg.c b/tcg/tcg.c
index 154ffe8..6c26ee4 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -1743,32 +1743,71 @@ static TCGReg tcg_reg_alloc(TCGContext *s, TCGRegSet 
desired_regs,
     tcg_abort();
 }
 
+/* Mark a temporary as dead.  */
+static void temp_dead(TCGContext *s, TCGTemp *ts)
+{
+    if (ts->fixed_reg) {
+        return;
+    }
+    if (ts->val_type == TEMP_VAL_REG) {
+        s->reg_to_temp[ts->reg] = NULL;
+    }
+    ts->val_type = (temp_idx(s, ts) < s->nb_globals || ts->temp_local
+                    ? TEMP_VAL_MEM : TEMP_VAL_DEAD);
+}
+
 /* Make sure the temporary is in a register.  If needed, allocate the register
    from DESIRED while avoiding ALLOCATED.  */
 static void temp_load(TCGContext *s, TCGTemp *ts, TCGRegSet desired_regs,
                       TCGRegSet allocated_regs)
 {
-    TCGReg reg;
+    TCGReg reg, base_reg;
+    TCGTemp *base;
 
     switch (ts->val_type) {
     case TEMP_VAL_REG:
         return;
+
     case TEMP_VAL_CONST:
         reg = tcg_reg_alloc(s, desired_regs, allocated_regs, 
ts->indirect_base);
         tcg_out_movi(s, ts->type, reg, ts->val);
         ts->mem_coherent = 0;
         break;
+
     case TEMP_VAL_MEM:
-        reg = tcg_reg_alloc(s, desired_regs, allocated_regs, 
ts->indirect_base);
-        if (ts->indirect_reg) {
-            tcg_regset_set_reg(allocated_regs, reg);
-            temp_load(s, ts->mem_base,
-                      tcg_target_available_regs[TCG_TYPE_PTR],
-                      allocated_regs);
+        base = ts->mem_base;
+        base_reg = base->reg;
+        if (ts->indirect_reg && base->val_type != TEMP_VAL_REG) {
+            TCGRegSet reg_avail = desired_regs & ~allocated_regs;
+            TCGRegSet base_avail = (tcg_target_available_regs[TCG_TYPE_PTR]
+                                    & ~allocated_regs);
+            if (is_power_of_2(reg_avail)) {
+                /* There is only one register available for TS.  If there are
+                   other available registers for BASE, make sure we pick one
+                   of them.  Otherwise BASE and TS will share a reg.  */
+                TCGRegSet avail = base_avail & ~reg_avail;
+                if (avail) {
+                    base_avail = avail;
+                }
+                temp_load(s, base, base_avail, allocated_regs);
+                base_reg = base->reg;
+            } else {
+                temp_load(s, base, base_avail, allocated_regs);
+                base_reg = base->reg;
+                tcg_regset_reset_reg(allocated_regs, base_reg);
+            }
         }
-        tcg_out_ld(s, ts->type, reg, ts->mem_base->reg, ts->mem_offset);
+
+        reg = tcg_reg_alloc(s, desired_regs, allocated_regs, 
ts->indirect_base);
+        tcg_out_ld(s, ts->type, reg, base_reg, ts->mem_offset);
         ts->mem_coherent = 1;
+
+        /* If the registers overlap, zap the info from BASE.  */
+        if (reg == base_reg) {
+            temp_dead(s, base);
+        }
         break;
+
     case TEMP_VAL_DEAD:
     default:
         tcg_abort();
@@ -1778,19 +1817,6 @@ static void temp_load(TCGContext *s, TCGTemp *ts, 
TCGRegSet desired_regs,
     s->reg_to_temp[reg] = ts;
 }
 
-/* mark a temporary as dead. */
-static inline void temp_dead(TCGContext *s, TCGTemp *ts)
-{
-    if (ts->fixed_reg) {
-        return;
-    }
-    if (ts->val_type == TEMP_VAL_REG) {
-        s->reg_to_temp[ts->reg] = NULL;
-    }
-    ts->val_type = (temp_idx(s, ts) < s->nb_globals || ts->temp_local
-                    ? TEMP_VAL_MEM : TEMP_VAL_DEAD);
-}
-
 /* sync a temporary to memory. 'allocated_regs' is used in case a
    temporary registers needs to be allocated to store a constant. */
 static void temp_sync(TCGContext *s, TCGTemp *ts, TCGRegSet allocated_regs)
-- 
2.5.5




reply via email to

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