qemu-devel
[Top][All Lists]
Advanced

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

[Qemu-devel] [PATCH v5 02/18] Refactor translation block CPU state handl


From: Jan Kiszka
Subject: [Qemu-devel] [PATCH v5 02/18] Refactor translation block CPU state handling
Date: Mon, 17 Nov 2008 17:18:58 +0100
User-agent: StGIT/0.14.2

This patch refactors the way the CPU state is handled that is associated
with a TB. The basic motivation is to move more arch specific code out
of generic files. Specifically the long #ifdef clutter in tb_find_fast()
has to be overcome in order to avoid duplicating it for the gdb
watchpoint fixes (patch "Restore pc on watchpoint hits").

The approach taken here is to encapsulate the relevant CPU state in a
new structure called TBCPUState which is kept inside TranslationBlock
but also passed around when setting up new TBs. To fill a TBCPUState
based on the current CPUState, each arch has to provide
cpu_get_tb_cpu_state(CPUState *, TBCPUState *).

At this chance, the patch also converts the not really beautiful macro
CPU_PC_FROM_TB into a clean static inline function.

Signed-off-by: Jan Kiszka <address@hidden>
---

 cpu-exec.c         |   63 ++--------------------------------------------------
 exec.c             |   56 ++++++++++++++++++----------------------------
 target-alpha/cpu.h |    8 +++++++
 target-arm/cpu.h   |   13 +++++++++++
 target-cris/cpu.h  |    9 +++++++
 target-i386/cpu.h  |    8 +++++++
 target-m68k/cpu.h  |   10 ++++++++
 target-mips/cpu.h  |    8 +++++++
 target-ppc/cpu.h   |    8 +++++++
 target-sh4/cpu.h   |   11 +++++++++
 target-sparc/cpu.h |   16 +++++++++++++
 11 files changed, 115 insertions(+), 95 deletions(-)

diff --git a/cpu-exec.c b/cpu-exec.c
index 322af0d..1955d24 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -169,71 +169,12 @@ static inline TranslationBlock *tb_find_fast(void)
 {
     TranslationBlock *tb;
     target_ulong cs_base, pc;
-    uint64_t flags;
+    int flags;
 
     /* we record a subset of the CPU state. It will
        always be the same before a given translated block
        is executed. */
-#if defined(TARGET_I386)
-    flags = env->hflags;
-    flags |= (env->eflags & (IOPL_MASK | TF_MASK | VM_MASK));
-    cs_base = env->segs[R_CS].base;
-    pc = cs_base + env->eip;
-#elif defined(TARGET_ARM)
-    flags = env->thumb | (env->vfp.vec_len << 1)
-            | (env->vfp.vec_stride << 4);
-    if ((env->uncached_cpsr & CPSR_M) != ARM_CPU_MODE_USR)
-        flags |= (1 << 6);
-    if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30))
-        flags |= (1 << 7);
-    flags |= (env->condexec_bits << 8);
-    cs_base = 0;
-    pc = env->regs[15];
-#elif defined(TARGET_SPARC)
-#ifdef TARGET_SPARC64
-    // AM . Combined FPU enable bits . PRIV . DMMU enabled . IMMU enabled
-    flags = ((env->pstate & PS_AM) << 2)
-        | (((env->pstate & PS_PEF) >> 1) | ((env->fprs & FPRS_FEF) << 2))
-        | (env->pstate & PS_PRIV) | ((env->lsu & (DMMU_E | IMMU_E)) >> 2);
-#else
-    // FPU enable . Supervisor
-    flags = (env->psref << 4) | env->psrs;
-#endif
-    cs_base = env->npc;
-    pc = env->pc;
-#elif defined(TARGET_PPC)
-    flags = env->hflags;
-    cs_base = 0;
-    pc = env->nip;
-#elif defined(TARGET_MIPS)
-    flags = env->hflags & (MIPS_HFLAG_TMASK | MIPS_HFLAG_BMASK);
-    cs_base = 0;
-    pc = env->active_tc.PC;
-#elif defined(TARGET_M68K)
-    flags = (env->fpcr & M68K_FPCR_PREC)  /* Bit  6 */
-            | (env->sr & SR_S)            /* Bit  13 */
-            | ((env->macsr >> 4) & 0xf);  /* Bits 0-3 */
-    cs_base = 0;
-    pc = env->pc;
-#elif defined(TARGET_SH4)
-    flags = (env->flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL
-                    | DELAY_SLOT_TRUE | DELAY_SLOT_CLEARME))   /* Bits  0- 3 */
-            | (env->fpscr & (FPSCR_FR | FPSCR_SZ | FPSCR_PR))  /* Bits 19-21 */
-            | (env->sr & (SR_MD | SR_RB));                     /* Bits 29-30 */
-    cs_base = 0;
-    pc = env->pc;
-#elif defined(TARGET_ALPHA)
-    flags = env->ps;
-    cs_base = 0;
-    pc = env->pc;
-#elif defined(TARGET_CRIS)
-    flags = env->pregs[PR_CCS] & (S_FLAG | P_FLAG | U_FLAG | X_FLAG);
-    flags |= env->dslot;
-    cs_base = 0;
-    pc = env->pc;
-#else
-#error unsupported CPU
-#endif
+    cpu_get_tb_cpu_state(env, &pc, &cs_base, &flags);
     tb = env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)];
     if (unlikely(!tb || tb->pc != pc || tb->cs_base != cs_base ||
                  tb->flags != flags)) {
diff --git a/exec.c b/exec.c
index 1edc737..772b1c1 100644
--- a/exec.c
+++ b/exec.c
@@ -886,12 +886,19 @@ TranslationBlock *tb_gen_code(CPUState *env,
 void tb_invalidate_phys_page_range(target_phys_addr_t start, 
target_phys_addr_t end,
                                    int is_cpu_write_access)
 {
-    int n, current_tb_modified, current_tb_not_found, current_flags;
+    TranslationBlock *tb, *tb_next, *saved_tb;
     CPUState *env = cpu_single_env;
-    PageDesc *p;
-    TranslationBlock *tb, *tb_next, *current_tb, *saved_tb;
     target_ulong tb_start, tb_end;
-    target_ulong current_pc, current_cs_base;
+    PageDesc *p;
+    int n;
+#ifdef TARGET_HAS_PRECISE_SMC
+    int current_tb_not_found = is_cpu_write_access;
+    TranslationBlock *current_tb = NULL;
+    int current_tb_modified = 0;
+    target_ulong current_pc = 0;
+    target_ulong current_cs_base = 0;
+    int current_flags = 0;
+#endif /* TARGET_HAS_PRECISE_SMC */
 
     p = page_find(start >> TARGET_PAGE_BITS);
     if (!p)
@@ -905,12 +912,6 @@ void tb_invalidate_phys_page_range(target_phys_addr_t 
start, target_phys_addr_t
 
     /* we remove all the TBs in the range [start, end[ */
     /* XXX: see if in some cases it could be faster to invalidate all the code 
*/
-    current_tb_not_found = is_cpu_write_access;
-    current_tb_modified = 0;
-    current_tb = NULL; /* avoid warning */
-    current_pc = 0; /* avoid warning */
-    current_cs_base = 0; /* avoid warning */
-    current_flags = 0; /* avoid warning */
     tb = p->first_tb;
     while (tb != NULL) {
         n = (long)tb & 3;
@@ -947,14 +948,8 @@ void tb_invalidate_phys_page_range(target_phys_addr_t 
start, target_phys_addr_t
                 current_tb_modified = 1;
                 cpu_restore_state(current_tb, env,
                                   env->mem_io_pc, NULL);
-#if defined(TARGET_I386)
-                current_flags = env->hflags;
-                current_flags |= (env->eflags & (IOPL_MASK | TF_MASK | 
VM_MASK));
-                current_cs_base = (target_ulong)env->segs[R_CS].base;
-                current_pc = current_cs_base + env->eip;
-#else
-#error unsupported CPU
-#endif
+                cpu_get_tb_cpu_state(env, &current_pc, &current_cs_base,
+                                     &current_flags);
             }
 #endif /* TARGET_HAS_PRECISE_SMC */
             /* we need to do that to handle the case where a signal
@@ -1027,12 +1022,16 @@ static inline void 
tb_invalidate_phys_page_fast(target_phys_addr_t start, int le
 static void tb_invalidate_phys_page(target_phys_addr_t addr,
                                     unsigned long pc, void *puc)
 {
-    int n, current_flags, current_tb_modified;
-    target_ulong current_pc, current_cs_base;
+    TranslationBlock *tb;
     PageDesc *p;
-    TranslationBlock *tb, *current_tb;
+    int n;
 #ifdef TARGET_HAS_PRECISE_SMC
+    TranslationBlock *current_tb = NULL;
     CPUState *env = cpu_single_env;
+    int current_tb_modified = 0;
+    target_ulong current_pc = 0;
+    target_ulong current_cs_base = 0;
+    int current_flags = 0;
 #endif
 
     addr &= TARGET_PAGE_MASK;
@@ -1040,11 +1039,6 @@ static void tb_invalidate_phys_page(target_phys_addr_t 
addr,
     if (!p)
         return;
     tb = p->first_tb;
-    current_tb_modified = 0;
-    current_tb = NULL;
-    current_pc = 0; /* avoid warning */
-    current_cs_base = 0; /* avoid warning */
-    current_flags = 0; /* avoid warning */
 #ifdef TARGET_HAS_PRECISE_SMC
     if (tb && pc != 0) {
         current_tb = tb_find_pc(pc);
@@ -1064,14 +1058,8 @@ static void tb_invalidate_phys_page(target_phys_addr_t 
addr,
 
             current_tb_modified = 1;
             cpu_restore_state(current_tb, env, pc, puc);
-#if defined(TARGET_I386)
-            current_flags = env->hflags;
-            current_flags |= (env->eflags & (IOPL_MASK | TF_MASK | VM_MASK));
-            current_cs_base = (target_ulong)env->segs[R_CS].base;
-            current_pc = current_cs_base + env->eip;
-#else
-#error unsupported CPU
-#endif
+            cpu_get_tb_cpu_state(env, &current_pc, &current_cs_base,
+                                 &current_flags);
         }
 #endif /* TARGET_HAS_PRECISE_SMC */
         tb_phys_invalidate(tb, addr);
diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h
index f606fac..122e2c2 100644
--- a/target-alpha/cpu.h
+++ b/target-alpha/cpu.h
@@ -422,4 +422,12 @@ static inline void cpu_pc_from_tb(CPUState *env, 
TranslationBlock *tb)
     env->pc = tb->pc;
 }
 
+static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
+                                        target_ulong *cs_base, int *flags)
+{
+    *pc = env->pc;
+    *cs_base = 0;
+    *flags = env->ps;
+}
+
 #endif /* !defined (__CPU_ALPHA_H__) */
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 79e51ac..d6cb116 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -423,4 +423,17 @@ static inline void cpu_pc_from_tb(CPUState *env, 
TranslationBlock *tb)
     env->regs[15] = tb->pc;
 }
 
+static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
+                                        target_ulong *cs_base, int *flags)
+{
+    *pc = env->regs[15];
+    *cs_base = 0;
+    *flags = env->thumb | (env->vfp.vec_len << 1)
+            | (env->vfp.vec_stride << 4) | (env->condexec_bits << 8);
+    if ((env->uncached_cpsr & CPSR_M) != ARM_CPU_MODE_USR)
+        *flags |= (1 << 6);
+    if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30))
+        *flags |= (1 << 7);
+}
+
 #endif
diff --git a/target-cris/cpu.h b/target-cris/cpu.h
index 19cb209..44a98e4 100644
--- a/target-cris/cpu.h
+++ b/target-cris/cpu.h
@@ -245,4 +245,13 @@ static inline void cpu_pc_from_tb(CPUState *env, 
TranslationBlock *tb)
     env->pc = tb->pc;
 }
 
+static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
+                                        target_ulong *cs_base, int *flags)
+{
+    *pc = env->pc;
+    *cs_base = 0;
+    *flags = env->dslot |
+            (env->pregs[PR_CCS] & (S_FLAG | P_FLAG | U_FLAG | X_FLAG));
+}
+
 #endif
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index ead073c..ebbf1b1 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -799,4 +799,12 @@ static inline void cpu_pc_from_tb(CPUState *env, 
TranslationBlock *tb)
     env->eip = tb->pc - tb->cs_base;
 }
 
+static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
+                                        target_ulong *cs_base, int *flags)
+{
+    *cs_base = env->segs[R_CS].base;
+    *pc = *cs_base + env->eip;
+    *flags = env->hflags | (env->eflags & (IOPL_MASK | TF_MASK | VM_MASK));
+}
+
 #endif /* CPU_I386_H */
diff --git a/target-m68k/cpu.h b/target-m68k/cpu.h
index 48c752c..bdef9b8 100644
--- a/target-m68k/cpu.h
+++ b/target-m68k/cpu.h
@@ -239,4 +239,14 @@ static inline void cpu_pc_from_tb(CPUState *env, 
TranslationBlock *tb)
     env->pc = tb->pc;
 }
 
+static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
+                                        target_ulong *cs_base, int *flags)
+{
+    *pc = env->pc;
+    *cs_base = 0;
+    *flags = (env->fpcr & M68K_FPCR_PREC)       /* Bit  6 */
+            | (env->sr & SR_S)                  /* Bit  13 */
+            | ((env->macsr >> 4) & 0xf);        /* Bits 0-3 */
+}
+
 #endif
diff --git a/target-mips/cpu.h b/target-mips/cpu.h
index a2544b1..86a7680 100644
--- a/target-mips/cpu.h
+++ b/target-mips/cpu.h
@@ -571,4 +571,12 @@ static inline void cpu_pc_from_tb(CPUState *env, 
TranslationBlock *tb)
     env->hflags |= tb->flags & MIPS_HFLAG_BMASK;
 }
 
+static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
+                                        target_ulong *cs_base, int *flags)
+{
+    *pc = env->active_tc.PC;
+    *cs_base = 0;
+    *flags = env->hflags & (MIPS_HFLAG_TMASK | MIPS_HFLAG_BMASK);
+}
+
 #endif /* !defined (__MIPS_CPU_H__) */
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index 1ffbc30..35c824a 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -1436,4 +1436,12 @@ static inline void cpu_pc_from_tb(CPUState *env, 
TranslationBlock *tb)
     env->nip = tb->pc;
 }
 
+static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
+                                        target_ulong *cs_base, int *flags)
+{
+    *pc = env->nip;
+    *cs_base = 0;
+    *flags = env->hflags;
+}
+
 #endif /* !defined (__CPU_PPC_H__) */
diff --git a/target-sh4/cpu.h b/target-sh4/cpu.h
index ed7c105..23ecded 100644
--- a/target-sh4/cpu.h
+++ b/target-sh4/cpu.h
@@ -271,4 +271,15 @@ static inline void cpu_pc_from_tb(CPUState *env, 
TranslationBlock *tb)
     env->flags = tb->flags;
 }
 
+static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
+                                        target_ulong *cs_base, int *flags)
+{
+    *pc = env->pc;
+    *cs_base = 0;
+    *flags = (env->flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL
+                    | DELAY_SLOT_TRUE | DELAY_SLOT_CLEARME))   /* Bits  0- 3 */
+            | (env->fpscr & (FPSCR_FR | FPSCR_SZ | FPSCR_PR))  /* Bits 19-21 */
+            | (env->sr & (SR_MD | SR_RB));                     /* Bits 29-30 */
+}
+
 #endif                         /* _CPU_SH4_H */
diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h
index 4779e34..93c1be5 100644
--- a/target-sparc/cpu.h
+++ b/target-sparc/cpu.h
@@ -510,4 +510,20 @@ static inline void cpu_pc_from_tb(CPUState *env, 
TranslationBlock *tb)
     env->npc = tb->cs_base;
 }
 
+static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
+                                        target_ulong *cs_base, int *flags)
+{
+    *pc = env->pc;
+    *cs_base = env->npc;
+#ifdef TARGET_SPARC64
+    // AM . Combined FPU enable bits . PRIV . DMMU enabled . IMMU enabled
+    *flags = ((env->pstate & PS_AM) << 2)
+        | (((env->pstate & PS_PEF) >> 1) | ((env->fprs & FPRS_FEF) << 2))
+        | (env->pstate & PS_PRIV) | ((env->lsu & (DMMU_E | IMMU_E)) >> 2);
+#else
+    // FPU enable . Supervisor
+    *flags = (env->psref << 4) | env->psrs;
+#endif
+}
+
 #endif





reply via email to

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