Refactor translation block CPU state handling (Jan Kiszka)

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").

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>



git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@5736 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
aliguori 2008-11-18 19:46:41 +00:00
parent 622ed3605b
commit 6b9175478e
11 changed files with 115 additions and 95 deletions

View File

@ -169,71 +169,12 @@ static inline TranslationBlock *tb_find_fast(void)
{ {
TranslationBlock *tb; TranslationBlock *tb;
target_ulong cs_base, pc; target_ulong cs_base, pc;
uint64_t flags; int flags;
/* we record a subset of the CPU state. It will /* we record a subset of the CPU state. It will
always be the same before a given translated block always be the same before a given translated block
is executed. */ is executed. */
#if defined(TARGET_I386) cpu_get_tb_cpu_state(env, &pc, &cs_base, &flags);
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
tb = env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)]; tb = env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)];
if (unlikely(!tb || tb->pc != pc || tb->cs_base != cs_base || if (unlikely(!tb || tb->pc != pc || tb->cs_base != cs_base ||
tb->flags != flags)) { tb->flags != flags)) {

56
exec.c
View File

@ -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, void tb_invalidate_phys_page_range(target_phys_addr_t start, target_phys_addr_t end,
int is_cpu_write_access) 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; CPUState *env = cpu_single_env;
PageDesc *p;
TranslationBlock *tb, *tb_next, *current_tb, *saved_tb;
target_ulong tb_start, tb_end; 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); p = page_find(start >> TARGET_PAGE_BITS);
if (!p) 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[ */ /* 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 */ /* 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; tb = p->first_tb;
while (tb != NULL) { while (tb != NULL) {
n = (long)tb & 3; 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; current_tb_modified = 1;
cpu_restore_state(current_tb, env, cpu_restore_state(current_tb, env,
env->mem_io_pc, NULL); env->mem_io_pc, NULL);
#if defined(TARGET_I386) cpu_get_tb_cpu_state(env, &current_pc, &current_cs_base,
current_flags = env->hflags; &current_flags);
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
} }
#endif /* TARGET_HAS_PRECISE_SMC */ #endif /* TARGET_HAS_PRECISE_SMC */
/* we need to do that to handle the case where a signal /* 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, static void tb_invalidate_phys_page(target_phys_addr_t addr,
unsigned long pc, void *puc) unsigned long pc, void *puc)
{ {
int n, current_flags, current_tb_modified; TranslationBlock *tb;
target_ulong current_pc, current_cs_base;
PageDesc *p; PageDesc *p;
TranslationBlock *tb, *current_tb; int n;
#ifdef TARGET_HAS_PRECISE_SMC #ifdef TARGET_HAS_PRECISE_SMC
TranslationBlock *current_tb = NULL;
CPUState *env = cpu_single_env; 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 #endif
addr &= TARGET_PAGE_MASK; addr &= TARGET_PAGE_MASK;
@ -1040,11 +1039,6 @@ static void tb_invalidate_phys_page(target_phys_addr_t addr,
if (!p) if (!p)
return; return;
tb = p->first_tb; 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 #ifdef TARGET_HAS_PRECISE_SMC
if (tb && pc != 0) { if (tb && pc != 0) {
current_tb = tb_find_pc(pc); 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; current_tb_modified = 1;
cpu_restore_state(current_tb, env, pc, puc); cpu_restore_state(current_tb, env, pc, puc);
#if defined(TARGET_I386) cpu_get_tb_cpu_state(env, &current_pc, &current_cs_base,
current_flags = env->hflags; &current_flags);
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
} }
#endif /* TARGET_HAS_PRECISE_SMC */ #endif /* TARGET_HAS_PRECISE_SMC */
tb_phys_invalidate(tb, addr); tb_phys_invalidate(tb, addr);

View File

@ -422,4 +422,12 @@ static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
env->pc = tb->pc; 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__) */ #endif /* !defined (__CPU_ALPHA_H__) */

View File

@ -423,4 +423,17 @@ static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
env->regs[15] = tb->pc; 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 #endif

View File

@ -245,4 +245,13 @@ static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
env->pc = tb->pc; 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 #endif

View File

@ -799,4 +799,12 @@ static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
env->eip = tb->pc - tb->cs_base; 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 */ #endif /* CPU_I386_H */

View File

@ -239,4 +239,14 @@ static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
env->pc = tb->pc; 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 #endif

View File

@ -571,4 +571,12 @@ static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
env->hflags |= tb->flags & MIPS_HFLAG_BMASK; 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__) */ #endif /* !defined (__MIPS_CPU_H__) */

View File

@ -1436,4 +1436,12 @@ static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
env->nip = tb->pc; 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__) */ #endif /* !defined (__CPU_PPC_H__) */

View File

@ -271,4 +271,15 @@ static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
env->flags = tb->flags; 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 */ #endif /* _CPU_SH4_H */

View File

@ -510,4 +510,20 @@ static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
env->npc = tb->cs_base; 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 #endif