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:
parent
622ed3605b
commit
6b9175478e
63
cpu-exec.c
63
cpu-exec.c
@ -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
56
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,
|
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, ¤t_pc, ¤t_cs_base,
|
||||||
current_flags = env->hflags;
|
¤t_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, ¤t_pc, ¤t_cs_base,
|
||||||
current_flags = env->hflags;
|
¤t_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);
|
||||||
|
@ -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__) */
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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 */
|
||||||
|
@ -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
|
||||||
|
@ -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__) */
|
||||||
|
@ -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__) */
|
||||||
|
@ -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 */
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user