[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 01/12] Refactor translation block CPU state handling
From: |
Jan Kiszka |
Subject: |
[Qemu-devel] [PATCH 01/12] Refactor translation block CPU state handling |
Date: |
Mon, 03 Nov 2008 11:35:59 +0100 |
User-agent: |
quilt/0.46_cvs20080326-19.1 |
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 | 96 ++++++++---------------------------------------
exec-all.h | 11 +++--
exec.c | 89 ++++++++++++++++---------------------------
target-alpha/cpu.h | 14 +++++-
target-alpha/translate.c | 2
target-arm/cpu.h | 19 ++++++++-
target-arm/translate.c | 4 -
target-cris/cpu.h | 16 ++++++-
target-cris/translate.c | 22 +++++-----
target-i386/cpu.h | 16 ++++++-
target-i386/translate.c | 22 +++++-----
target-m68k/cpu.h | 16 ++++++-
target-m68k/translate.c | 5 +-
target-mips/cpu.h | 18 ++++++--
target-mips/translate.c | 6 +-
target-ppc/cpu.h | 14 +++++-
target-ppc/translate.c | 4 -
target-sh4/cpu.h | 21 +++++++---
target-sh4/translate.c | 6 +-
target-sparc/cpu.h | 26 ++++++++++--
target-sparc/translate.c | 8 +--
21 files changed, 232 insertions(+), 203 deletions(-)
Index: b/cpu-exec.c
===================================================================
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -39,6 +39,8 @@
#endif
#endif
+#include <string.h>
+
#if defined(__sparc__) && !defined(HOST_SOLARIS)
// Work around ugly bugs in glibc that mangle global register contents
#undef env
@@ -100,8 +102,7 @@ static void cpu_exec_nocache(int max_cyc
if (max_cycles > CF_COUNT_MASK)
max_cycles = CF_COUNT_MASK;
- tb = tb_gen_code(env, orig_tb->pc, orig_tb->cs_base, orig_tb->flags,
- max_cycles);
+ tb = tb_gen_code(env, &orig_tb->cpu_state, max_cycles);
env->current_tb = tb;
/* execute the generated code */
next_tb = tcg_qemu_tb_exec(tb->tc_ptr);
@@ -109,20 +110,19 @@ static void cpu_exec_nocache(int max_cyc
if ((next_tb & 3) == 2) {
/* Restore PC. This may happen if async event occurs before
the TB starts executing. */
- CPU_PC_FROM_TB(env, tb);
+ cpu_pc_from_tb(env, tb);
}
tb_phys_invalidate(tb, -1);
tb_free(tb);
}
-static TranslationBlock *tb_find_slow(target_ulong pc,
- target_ulong cs_base,
- uint64_t flags)
+static TranslationBlock *tb_find_slow(TBCPUState *cpu_state)
{
TranslationBlock *tb, **ptb1;
unsigned int h;
- target_ulong phys_pc, phys_page1, phys_page2, virt_page2;
+ target_ulong pc, phys_pc, phys_page1, phys_page2, virt_page2;
+ pc = cpu_state->pc;
tb_invalidated_flag = 0;
regs_to_env(); /* XXX: do it just before cpu_gen_code() */
@@ -137,10 +137,10 @@ static TranslationBlock *tb_find_slow(ta
tb = *ptb1;
if (!tb)
goto not_found;
- if (tb->pc == pc &&
+ if (tb->cpu_state.pc == pc &&
tb->page_addr[0] == phys_page1 &&
- tb->cs_base == cs_base &&
- tb->flags == flags) {
+ tb->cpu_state.cs_base == cpu_state->cs_base &&
+ tb->cpu_state.flags == cpu_state->flags) {
/* check next page if needed */
if (tb->page_addr[1] != -1) {
virt_page2 = (pc & TARGET_PAGE_MASK) +
@@ -156,7 +156,7 @@ static TranslationBlock *tb_find_slow(ta
}
not_found:
/* if no translated code available, then translate it now */
- tb = tb_gen_code(env, pc, cs_base, flags, 0);
+ tb = tb_gen_code(env, cpu_state, 0);
found:
/* we add the TB in the virtual pc hash table */
@@ -167,76 +167,16 @@ static TranslationBlock *tb_find_slow(ta
static inline TranslationBlock *tb_find_fast(void)
{
TranslationBlock *tb;
- target_ulong cs_base, pc;
- uint64_t flags;
+ TBCPUState cpu_state;
/* 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
- 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)) {
- tb = tb_find_slow(pc, cs_base, flags);
+ cpu_get_tb_cpu_state(env, &cpu_state);
+ tb = env->tb_jmp_cache[tb_jmp_cache_hash_func(cpu_state.pc)];
+ if (unlikely(!tb ||
+ memcmp(&tb->cpu_state, &cpu_state, sizeof(cpu_state)))) {
+ tb = tb_find_slow(&cpu_state);
}
return tb;
}
@@ -634,7 +574,7 @@ int cpu_exec(CPUState *env1)
int insns_left;
tb = (TranslationBlock *)(long)(next_tb & ~3);
/* Restore PC. */
- CPU_PC_FROM_TB(env, tb);
+ cpu_pc_from_tb(env, tb);
insns_left = env->icount_decr.u32;
if (env->icount_extra && insns_left >= 0) {
/* Refill decrementer and continue execution. */
Index: b/exec-all.h
===================================================================
--- a/exec-all.h
+++ b/exec-all.h
@@ -29,6 +29,7 @@
#define DISAS_UPDATE 2 /* cpu state was modified dynamically */
#define DISAS_TB_JUMP 3 /* only pc was modified statically */
+typedef struct TBCPUState TBCPUState;
typedef struct TranslationBlock TranslationBlock;
/* XXX: make safe guess about sizes */
@@ -78,9 +79,7 @@ int cpu_restore_state_copy(struct Transl
void *puc);
void cpu_resume_from_signal(CPUState *env1, void *puc);
void cpu_io_recompile(CPUState *env, void *retaddr);
-TranslationBlock *tb_gen_code(CPUState *env,
- target_ulong pc, target_ulong cs_base, int flags,
- int cflags);
+TranslationBlock *tb_gen_code(CPUState *env, TBCPUState *cpu_state, int
cflags);
void cpu_exec_init(CPUState *env);
int page_unprotect(target_ulong address, unsigned long pc, void *puc);
void tb_invalidate_phys_page_range(target_phys_addr_t start,
target_phys_addr_t end,
@@ -123,10 +122,14 @@ static inline int tlb_set_page(CPUState
#define USE_DIRECT_JUMP
#endif
-struct TranslationBlock {
+struct TBCPUState {
target_ulong pc; /* simulated PC corresponding to this block (EIP + CS
base) */
target_ulong cs_base; /* CS base for this block */
uint64_t flags; /* flags defining in which context the code was generated
*/
+};
+
+struct TranslationBlock {
+ TBCPUState cpu_state;
uint16_t size; /* size of target code for this block (1 <=
size <= TARGET_PAGE_SIZE) */
uint16_t cflags; /* compile flags */
Index: b/exec.c
===================================================================
--- a/exec.c
+++ b/exec.c
@@ -737,7 +737,7 @@ void tb_phys_invalidate(TranslationBlock
TranslationBlock *tb1, *tb2;
/* remove the TB from the hash list */
- phys_pc = tb->page_addr[0] + (tb->pc & ~TARGET_PAGE_MASK);
+ phys_pc = tb->page_addr[0] + (tb->cpu_state.pc & ~TARGET_PAGE_MASK);
h = tb_phys_hash_func(phys_pc);
tb_remove(&tb_phys_hash[h], tb,
offsetof(TranslationBlock, phys_hash_next));
@@ -757,7 +757,7 @@ void tb_phys_invalidate(TranslationBlock
tb_invalidated_flag = 1;
/* remove the TB from the hash list */
- h = tb_jmp_cache_hash_func(tb->pc);
+ h = tb_jmp_cache_hash_func(tb->cpu_state.pc);
for(env = first_cpu; env != NULL; env = env->next_cpu) {
if (env->tb_jmp_cache[h] == tb)
env->tb_jmp_cache[h] = NULL;
@@ -828,28 +828,27 @@ static void build_page_bitmap(PageDesc *
if (n == 0) {
/* NOTE: tb_end may be after the end of the page, but
it is not a problem */
- tb_start = tb->pc & ~TARGET_PAGE_MASK;
+ tb_start = tb->cpu_state.pc & ~TARGET_PAGE_MASK;
tb_end = tb_start + tb->size;
if (tb_end > TARGET_PAGE_SIZE)
tb_end = TARGET_PAGE_SIZE;
} else {
tb_start = 0;
- tb_end = ((tb->pc + tb->size) & ~TARGET_PAGE_MASK);
+ tb_end = ((tb->cpu_state.pc + tb->size) & ~TARGET_PAGE_MASK);
}
set_bits(p->code_bitmap, tb_start, tb_end - tb_start);
tb = tb->page_next[n];
}
}
-TranslationBlock *tb_gen_code(CPUState *env,
- target_ulong pc, target_ulong cs_base,
- int flags, int cflags)
+TranslationBlock *tb_gen_code(CPUState *env, TBCPUState *cpu_state, int cflags)
{
TranslationBlock *tb;
uint8_t *tc_ptr;
- target_ulong phys_pc, phys_page2, virt_page2;
+ target_ulong pc, phys_pc, phys_page2, virt_page2;
int code_gen_size;
+ pc = cpu_state->pc;
phys_pc = get_phys_addr_code(env, pc);
tb = tb_alloc(pc);
if (!tb) {
@@ -862,8 +861,7 @@ TranslationBlock *tb_gen_code(CPUState *
}
tc_ptr = code_gen_ptr;
tb->tc_ptr = tc_ptr;
- tb->cs_base = cs_base;
- tb->flags = flags;
+ tb->cpu_state = *cpu_state;
tb->cflags = cflags;
cpu_gen_code(env, tb, &code_gen_size);
code_gen_ptr = (void *)(((unsigned long)code_gen_ptr + code_gen_size +
CODE_GEN_ALIGN - 1) & ~(CODE_GEN_ALIGN - 1));
@@ -886,12 +884,17 @@ TranslationBlock *tb_gen_code(CPUState *
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;
+ TBCPUState cpu_state;
+#endif /* TARGET_HAS_PRECISE_SMC */
p = page_find(start >> TARGET_PAGE_BITS);
if (!p)
@@ -905,12 +908,6 @@ void tb_invalidate_phys_page_range(targe
/* 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;
@@ -920,11 +917,13 @@ void tb_invalidate_phys_page_range(targe
if (n == 0) {
/* NOTE: tb_end may be after the end of the page, but
it is not a problem */
- tb_start = tb->page_addr[0] + (tb->pc & ~TARGET_PAGE_MASK);
+ tb_start = tb->page_addr[0] +
+ (tb->cpu_state.pc & ~TARGET_PAGE_MASK);
tb_end = tb_start + tb->size;
} else {
tb_start = tb->page_addr[1];
- tb_end = tb_start + ((tb->pc + tb->size) & ~TARGET_PAGE_MASK);
+ tb_end = tb_start +
+ ((tb->cpu_state.pc + tb->size) & ~TARGET_PAGE_MASK);
}
if (!(tb_end <= start || tb_start >= end)) {
#ifdef TARGET_HAS_PRECISE_SMC
@@ -947,14 +946,7 @@ void tb_invalidate_phys_page_range(targe
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, &cpu_state);
}
#endif /* TARGET_HAS_PRECISE_SMC */
/* we need to do that to handle the case where a signal
@@ -988,7 +980,7 @@ void tb_invalidate_phys_page_range(targe
modifying the memory. It will ensure that it cannot modify
itself */
env->current_tb = NULL;
- tb_gen_code(env, current_pc, current_cs_base, current_flags, 1);
+ tb_gen_code(env, &cpu_state, 1);
cpu_resume_from_signal(env, NULL);
}
#endif
@@ -1027,12 +1019,14 @@ static inline void tb_invalidate_phys_pa
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;
+ TBCPUState cpu_state;
#endif
addr &= TARGET_PAGE_MASK;
@@ -1040,11 +1034,6 @@ static void tb_invalidate_phys_page(targ
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 +1053,7 @@ static void tb_invalidate_phys_page(targ
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, &cpu_state);
}
#endif /* TARGET_HAS_PRECISE_SMC */
tb_phys_invalidate(tb, addr);
@@ -1084,7 +1066,7 @@ static void tb_invalidate_phys_page(targ
modifying the memory. It will ensure that it cannot modify
itself */
env->current_tb = NULL;
- tb_gen_code(env, current_pc, current_cs_base, current_flags, 1);
+ tb_gen_code(env, &cpu_state, 1);
cpu_resume_from_signal(env, puc);
}
#endif
@@ -1156,7 +1138,7 @@ TranslationBlock *tb_alloc(target_ulong
(code_gen_ptr - code_gen_buffer) >= code_gen_buffer_max_size)
return NULL;
tb = &tbs[nb_tbs++];
- tb->pc = pc;
+ tb->cpu_state.pc = pc;
tb->cflags = 0;
return tb;
}
@@ -3150,9 +3132,8 @@ int cpu_memory_rw_debug(CPUState *env, t
void cpu_io_recompile(CPUState *env, void *retaddr)
{
TranslationBlock *tb;
+ TBCPUState cpu_state;
uint32_t n, cflags;
- target_ulong pc, cs_base;
- uint64_t flags;
tb = tb_find_pc((unsigned long)retaddr);
if (!tb) {
@@ -3189,13 +3170,11 @@ void cpu_io_recompile(CPUState *env, voi
cpu_abort(env, "TB too big during recompile");
cflags = n | CF_LAST_IO;
- pc = tb->pc;
- cs_base = tb->cs_base;
- flags = tb->flags;
+ cpu_state = tb->cpu_state;
tb_phys_invalidate(tb, -1);
/* FIXME: In theory this could raise an exception. In practice
we have already translated the block once so it's probably ok. */
- tb_gen_code(env, pc, cs_base, flags, cflags);
+ tb_gen_code(env, &cpu_state, cflags);
/* TODO: If env->pc != tb->pc (i.e. the faulting instruction was not
the first in the TB) then we end up generating a whole new TB and
repeating the fault, which is horribly inefficient.
Index: b/target-alpha/cpu.h
===================================================================
--- a/target-alpha/cpu.h
+++ b/target-alpha/cpu.h
@@ -318,6 +318,7 @@ static inline void cpu_clone_regs(CPUSta
#endif
#include "cpu-all.h"
+#include "exec-all.h"
enum {
FEATURE_ASN = 0x00000001,
@@ -416,6 +417,15 @@ void call_pal (CPUState *env);
void call_pal (CPUState *env, int palcode);
#endif
-#define CPU_PC_FROM_TB(env, tb) env->pc = tb->pc
-
+static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
+{
+ env->pc = tb->cpu_state.pc;
+}
+
+static inline void cpu_get_tb_cpu_state(CPUState *env, TBCPUState *cpu_state)
+{
+ cpu_state->pc = env->pc;
+ cpu_state->cs_base = 0;
+ cpu_state->flags = env->ps;
+}
#endif /* !defined (__CPU_ALPHA_H__) */
Index: b/target-alpha/translate.c
===================================================================
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -2245,7 +2245,7 @@ static always_inline void gen_intermedia
int num_insns;
int max_insns;
- pc_start = tb->pc;
+ pc_start = tb->cpu_state.pc;
gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
ctx.pc = pc_start;
ctx.amask = env->amask;
Index: b/target-arm/cpu.h
===================================================================
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -415,8 +415,23 @@ static inline void cpu_clone_regs(CPUSta
}
#endif
-#define CPU_PC_FROM_TB(env, tb) env->regs[15] = tb->pc
-
#include "cpu-all.h"
+#include "exec-all.h"
+
+static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
+{
+ env->regs[15] = tb->cpu_state.pc;
+}
+static inline void cpu_get_tb_cpu_state(CPUState *env, TBCPUState *cpu_state)
+{
+ cpu_state->pc = env->regs[15];
+ cpu_state->cs_base = 0;
+ cpu_state->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)
+ cpu_state->flags |= (1 << 6);
+ if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30))
+ cpu_state->flags |= (1 << 7);
+}
#endif
Index: b/target-arm/translate.c
===================================================================
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -3375,7 +3375,7 @@ static inline void gen_goto_tb(DisasCont
TranslationBlock *tb;
tb = s->tb;
- if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
+ if ((tb->cpu_state.pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
tcg_gen_goto_tb(n);
gen_set_pc_im(dest);
tcg_gen_exit_tb((long)tb + n);
@@ -8597,7 +8597,7 @@ static inline void gen_intermediate_code
num_temps = 0;
memset(temps, 0, sizeof(temps));
- pc_start = tb->pc;
+ pc_start = tb->cpu_state.pc;
dc->tb = tb;
Index: b/target-cris/cpu.h
===================================================================
--- a/target-cris/cpu.h
+++ b/target-cris/cpu.h
@@ -237,7 +237,19 @@ static inline void cpu_clone_regs(CPUSta
#define SFR_RW_MM_TLB_LO env->pregs[PR_SRS]][5
#define SFR_RW_MM_TLB_HI env->pregs[PR_SRS]][6
-#define CPU_PC_FROM_TB(env, tb) env->pc = tb->pc
-
#include "cpu-all.h"
+#include "exec-all.h"
+
+static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
+{
+ env->pc = tb->cpu_state.pc;
+}
+
+static inline void cpu_get_tb_cpu_state(CPUState *env, TBCPUState *cpu_state)
+{
+ cpu_state->pc = env->pc;
+ cpu_state->cs_base = 0;
+ cpu_state->flags = env->dslot |
+ (env->pregs[PR_CCS] & (S_FLAG | P_FLAG | U_FLAG | X_FLAG));
+}
#endif
Index: b/target-cris/translate.c
===================================================================
--- a/target-cris/translate.c
+++ b/target-cris/translate.c
@@ -642,7 +642,8 @@ static void gen_goto_tb(DisasContext *dc
{
TranslationBlock *tb;
tb = dc->tb;
- if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
+ if ((tb->cpu_state.pc & TARGET_PAGE_MASK) ==
+ (dest & TARGET_PAGE_MASK)) {
tcg_gen_goto_tb(n);
tcg_gen_movi_tl(env_pc, dest);
tcg_gen_exit_tb((long)tb + n);
@@ -3241,7 +3242,7 @@ gen_intermediate_code_internal(CPUState
/* Odd PC indicates that branch is rexecuting due to exception in the
* delayslot, like in real hw.
*/
- pc_start = tb->pc & ~1;
+ pc_start = tb->cpu_state.pc & ~1;
dc->env = env;
dc->tb = tb;
@@ -3253,7 +3254,7 @@ gen_intermediate_code_internal(CPUState
dc->singlestep_enabled = env->singlestep_enabled;
dc->flags_uptodate = 1;
dc->flagx_known = 1;
- dc->flags_x = tb->flags & X_FLAG;
+ dc->flags_x = tb->cpu_state.flags & X_FLAG;
dc->cc_x_uptodate = 0;
dc->cc_mask = 0;
dc->update_cc = 0;
@@ -3262,8 +3263,9 @@ gen_intermediate_code_internal(CPUState
dc->cc_size_uptodate = -1;
/* Decode TB flags. */
- dc->tb_flags = tb->flags & (S_FLAG | P_FLAG | U_FLAG | X_FLAG);
- dc->delayed_branch = !!(tb->flags & 7);
+ dc->tb_flags =
+ tb->cpu_state.flags & (S_FLAG | P_FLAG | U_FLAG | X_FLAG);
+ dc->delayed_branch = !!(tb->cpu_state.flags & 7);
if (dc->delayed_branch)
dc->jmp = JMP_INDIRECT;
else
@@ -3280,8 +3282,8 @@ gen_intermediate_code_internal(CPUState
"%x.%x.%x.%x\n"
"%x.%x.%x.%x\n",
search_pc, dc->pc, dc->ppc,
- (unsigned long long)tb->flags,
- env->btarget, (unsigned)tb->flags & 7,
+ (unsigned long long)tb->cpu_state.flags,
+ env->btarget, (unsigned)tb->cpu_state.flags & 7,
env->pregs[PR_CCS],
env->pregs[PR_PID], env->pregs[PR_USP],
env->regs[0], env->regs[1], env->regs[2], env->regs[3],
@@ -3342,7 +3344,7 @@ gen_intermediate_code_internal(CPUState
dc->delayed_branch--;
if (dc->delayed_branch == 0)
{
- if (tb->flags & 7)
+ if (tb->cpu_state.flags & 7)
t_gen_mov_env_TN(dslot,
tcg_const_tl(0));
if (dc->jmp == JMP_DIRECT) {
@@ -3358,7 +3360,7 @@ gen_intermediate_code_internal(CPUState
/* If we are rexecuting a branch due to exceptions on
delay slots dont break. */
- if (!(tb->pc & 1) && env->singlestep_enabled)
+ if (!(tb->cpu_state.pc & 1) && env->singlestep_enabled)
break;
} while (!dc->is_jmp && !dc->cpustate_changed
&& gen_opc_ptr < gen_opc_end
@@ -3374,7 +3376,7 @@ gen_intermediate_code_internal(CPUState
/* Force an update if the per-tb cpu state has changed. */
if (dc->is_jmp == DISAS_NEXT
&& (dc->cpustate_changed || !dc->flagx_known
- || (dc->flags_x != (tb->flags & X_FLAG)))) {
+ || (dc->flags_x != (tb->cpu_state.flags & X_FLAG)))) {
dc->is_jmp = DISAS_UPDATE;
tcg_gen_movi_tl(env_pc, npc);
}
Index: b/target-i386/cpu.h
===================================================================
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -774,10 +774,20 @@ static inline void cpu_clone_regs(CPUSta
}
#endif
-#define CPU_PC_FROM_TB(env, tb) env->eip = tb->pc - tb->cs_base
-
#include "cpu-all.h"
-
+#include "exec-all.h"
#include "svm.h"
+static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
+{
+ env->eip = tb->cpu_state.pc - tb->cpu_state.cs_base;
+}
+
+static inline void cpu_get_tb_cpu_state(CPUState *env, TBCPUState *cpu_state)
+{
+ cpu_state->cs_base = env->segs[R_CS].base;
+ cpu_state->pc = cpu_state->cs_base + env->eip;
+ cpu_state->flags =
+ env->hflags | (env->eflags & (IOPL_MASK | TF_MASK | VM_MASK));
+}
#endif /* CPU_I386_H */
Index: b/target-i386/translate.c
===================================================================
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -2210,7 +2210,7 @@ static inline void gen_goto_tb(DisasCont
pc = s->cs_base + eip;
tb = s->tb;
/* NOTE: we handle the case where the TB spans two pages here */
- if ((pc & TARGET_PAGE_MASK) == (tb->pc & TARGET_PAGE_MASK) ||
+ if ((pc & TARGET_PAGE_MASK) == (tb->cpu_state.pc & TARGET_PAGE_MASK) ||
(pc & TARGET_PAGE_MASK) == ((s->pc - 1) & TARGET_PAGE_MASK)) {
/* jump to same page: we can use a direct jump */
tcg_gen_goto_tb(tb_num);
@@ -2625,7 +2625,7 @@ static void gen_eob(DisasContext *s)
{
if (s->cc_op != CC_OP_DYNAMIC)
gen_op_set_cc_op(s->cc_op);
- if (s->tb->flags & HF_INHIBIT_IRQ_MASK) {
+ if (s->tb->cpu_state.flags & HF_INHIBIT_IRQ_MASK) {
tcg_gen_helper_0_0(helper_reset_inhibit_irq);
}
if (s->singlestep_enabled) {
@@ -4921,7 +4921,7 @@ static target_ulong disas_insn(DisasCont
/* if reg == SS, inhibit interrupts/trace. */
/* If several instructions disable interrupts, only the
_first_ does it */
- if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK))
+ if (!(s->tb->cpu_state.flags & HF_INHIBIT_IRQ_MASK))
tcg_gen_helper_0_0(helper_set_inhibit_irq);
s->tf = 0;
}
@@ -4997,7 +4997,7 @@ static target_ulong disas_insn(DisasCont
/* if reg == SS, inhibit interrupts/trace */
/* If several instructions disable interrupts, only the
_first_ does it */
- if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK))
+ if (!(s->tb->cpu_state.flags & HF_INHIBIT_IRQ_MASK))
tcg_gen_helper_0_0(helper_set_inhibit_irq);
s->tf = 0;
}
@@ -6597,7 +6597,7 @@ static target_ulong disas_insn(DisasCont
/* interruptions are enabled only the first insn after sti */
/* If several instructions disable interrupts, only the
_first_ does it */
- if (!(s->tb->flags & HF_INHIBIT_IRQ_MASK))
+ if (!(s->tb->cpu_state.flags & HF_INHIBIT_IRQ_MASK))
tcg_gen_helper_0_0(helper_set_inhibit_irq);
/* give a chance to handle pending irqs */
gen_jmp_im(s->pc - s->cs_base);
@@ -7541,9 +7541,9 @@ static inline void gen_intermediate_code
int max_insns;
/* generate intermediate code */
- pc_start = tb->pc;
- cs_base = tb->cs_base;
- flags = tb->flags;
+ pc_start = tb->cpu_state.pc;
+ cs_base = tb->cpu_state.cs_base;
+ flags = tb->cpu_state.flags;
cflags = tb->cflags;
dc->pe = (flags >> HF_PE_SHIFT) & 1;
@@ -7725,11 +7725,11 @@ void gen_pc_load(CPUState *env, Translat
}
}
fprintf(logfile, "spc=0x%08lx pc_pos=0x%x eip=" TARGET_FMT_lx "
cs_base=%x\n",
- searched_pc, pc_pos, gen_opc_pc[pc_pos] - tb->cs_base,
- (uint32_t)tb->cs_base);
+ searched_pc, pc_pos, gen_opc_pc[pc_pos] -
tb->cpu_state.cs_base,
+ (uint32_t)tb->cpu_state.cs_base);
}
#endif
- env->eip = gen_opc_pc[pc_pos] - tb->cs_base;
+ env->eip = gen_opc_pc[pc_pos] - tb->cpu_state.cs_base;
cc_op = gen_opc_cc_op[pc_pos];
if (cc_op != CC_OP_DYNAMIC)
env->cc_op = cc_op;
Index: b/target-m68k/cpu.h
===================================================================
--- a/target-m68k/cpu.h
+++ b/target-m68k/cpu.h
@@ -231,8 +231,20 @@ static inline void cpu_clone_regs(CPUSta
}
#endif
-#define CPU_PC_FROM_TB(env, tb) env->pc = tb->pc
-
#include "cpu-all.h"
+#include "exec-all.h"
+
+static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
+{
+ env->pc = tb->cpu_state.pc;
+}
+static inline void cpu_get_tb_cpu_state(CPUState *env, TBCPUState *cpu_state)
+{
+ cpu_state->pc = env->pc;
+ cpu_state->cs_base = 0;
+ cpu_state->flags = (env->fpcr & M68K_FPCR_PREC) /* Bit 6 */
+ | (env->sr & SR_S) /* Bit 13 */
+ | ((env->macsr >> 4) & 0xf); /* Bits 0-3 */
+}
#endif
Index: b/target-m68k/translate.c
===================================================================
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -874,7 +874,8 @@ static void gen_jmp_tb(DisasContext *s,
tb = s->tb;
if (unlikely(s->singlestep_enabled)) {
gen_exception(s, dest, EXCP_DEBUG);
- } else if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) ||
+ } else if ((tb->cpu_state.pc & TARGET_PAGE_MASK) ==
+ (dest & TARGET_PAGE_MASK) ||
(s->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
tcg_gen_goto_tb(n);
tcg_gen_movi_i32(QREG_PC, dest);
@@ -2924,7 +2925,7 @@ gen_intermediate_code_internal(CPUState
int max_insns;
/* generate intermediate code */
- pc_start = tb->pc;
+ pc_start = tb->cpu_state.pc;
dc->tb = tb;
Index: b/target-mips/cpu.h
===================================================================
--- a/target-mips/cpu.h
+++ b/target-mips/cpu.h
@@ -501,6 +501,7 @@ static inline void cpu_clone_regs(CPUSta
}
#include "cpu-all.h"
+#include "exec-all.h"
/* Memory access type :
* may be needed for precise access rights control and precise exceptions.
@@ -562,10 +563,17 @@ CPUMIPSState *cpu_mips_init(const char *
uint32_t cpu_mips_get_clock (void);
int cpu_mips_signal_handler(int host_signum, void *pinfo, void *puc);
-#define CPU_PC_FROM_TB(env, tb) do { \
- env->active_tc.PC = tb->pc; \
- env->hflags &= ~MIPS_HFLAG_BMASK; \
- env->hflags |= tb->flags & MIPS_HFLAG_BMASK; \
- } while (0)
+static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
+{
+ env->active_tc.PC = tb->cpu_state.pc;
+ env->hflags &= ~MIPS_HFLAG_BMASK;
+ env->hflags |= tb->cpu_state.flags & MIPS_HFLAG_BMASK;
+}
+static inline void cpu_get_tb_cpu_state(CPUState *env, TBCPUState *cpu_state)
+{
+ cpu_state->pc = env->active_tc.PC;
+ cpu_state->cs_base = 0;
+ cpu_state->flags = env->hflags & (MIPS_HFLAG_TMASK | MIPS_HFLAG_BMASK);
+}
#endif /* !defined (__MIPS_CPU_H__) */
Index: b/target-mips/translate.c
===================================================================
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -2475,7 +2475,7 @@ static inline void gen_goto_tb(DisasCont
{
TranslationBlock *tb;
tb = ctx->tb;
- if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
+ if ((tb->cpu_state.pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
tcg_gen_goto_tb(n);
gen_save_pc(dest);
tcg_gen_exit_tb((long)tb + n);
@@ -8449,7 +8449,7 @@ gen_intermediate_code_internal (CPUState
if (search_pc && loglevel)
fprintf (logfile, "search pc %d\n", search_pc);
- pc_start = tb->pc;
+ pc_start = tb->cpu_state.pc;
/* Leave some spare opc slots for branch handling. */
gen_opc_end = gen_opc_buf + OPC_MAX_SIZE - 16;
ctx.pc = pc_start;
@@ -8457,7 +8457,7 @@ gen_intermediate_code_internal (CPUState
ctx.tb = tb;
ctx.bstate = BS_NONE;
/* Restore delay slot state from the tb context. */
- ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */
+ ctx.hflags = (uint32_t)tb->cpu_state.flags; /* FIXME: maybe use 64 bits
here? */
restore_cpu_state(env, &ctx);
if (env->user_mode_only)
ctx.mem_idx = MIPS_HFLAG_UM;
Index: b/target-ppc/cpu.h
===================================================================
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -822,9 +822,8 @@ static inline void cpu_clone_regs(CPUSta
}
#endif
-#define CPU_PC_FROM_TB(env, tb) env->nip = tb->pc
-
#include "cpu-all.h"
+#include "exec-all.h"
/*****************************************************************************/
/* CRF definitions */
@@ -1424,4 +1423,15 @@ enum {
/*****************************************************************************/
+static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
+{
+ env->nip = tb->cpu_state.pc;
+}
+
+static inline void cpu_get_tb_cpu_state(CPUState *env, TBCPUState *cpu_state)
+{
+ cpu_state->pc = env->nip;
+ cpu_state->cs_base = 0;
+ cpu_state->flags = env->hflags;
+}
#endif /* !defined (__CPU_PPC_H__) */
Index: b/target-ppc/translate.c
===================================================================
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -3470,7 +3470,7 @@ static always_inline void gen_goto_tb (D
if (!ctx->sf_mode)
dest = (uint32_t) dest;
#endif
- if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
+ if ((tb->cpu_state.pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
likely(!ctx->singlestep_enabled)) {
tcg_gen_goto_tb(n);
tcg_gen_movi_tl(cpu_nip, dest & ~3);
@@ -6783,7 +6783,7 @@ static always_inline void gen_intermedia
int num_insns;
int max_insns;
- pc_start = tb->pc;
+ pc_start = tb->cpu_state.pc;
gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
#if defined(OPTIMIZE_FPRF_UPDATE)
gen_fprf_ptr = gen_fprf_buf;
Index: b/target-sh4/cpu.h
===================================================================
--- a/target-sh4/cpu.h
+++ b/target-sh4/cpu.h
@@ -173,12 +173,8 @@ static inline void cpu_clone_regs(CPUSta
}
#endif
-#define CPU_PC_FROM_TB(env, tb) do { \
- env->pc = tb->pc; \
- env->flags = tb->flags; \
- } while (0)
-
#include "cpu-all.h"
+#include "exec-all.h"
/* Memory access type */
enum {
@@ -269,4 +265,19 @@ static inline int cpu_ptel_pr (uint32_t
#define PTEA_TC (1 << 3)
#define cpu_ptea_tc(ptea) (((ptea) & PTEA_TC) >> 3)
+static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
+{
+ env->pc = tb->cpu_state.pc;
+ env->flags = tb->cpu_state.flags;
+}
+
+static inline void cpu_get_tb_cpu_state(CPUState *env, TBCPUState *cpu_state)
+{
+ cpu_state->pc = env->pc;
+ cpu_state->cs_base = 0;
+ cpu_state->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 */
Index: b/target-sh4/translate.c
===================================================================
--- a/target-sh4/translate.c
+++ b/target-sh4/translate.c
@@ -261,7 +261,7 @@ static void gen_goto_tb(DisasContext * c
TranslationBlock *tb;
tb = ctx->tb;
- if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
+ if ((tb->cpu_state.pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
!ctx->singlestep_enabled) {
/* Use a direct jump if in same page and singlestep not enabled */
tcg_gen_goto_tb(n);
@@ -1803,10 +1803,10 @@ gen_intermediate_code_internal(CPUState
int num_insns;
int max_insns;
- pc_start = tb->pc;
+ pc_start = tb->cpu_state.pc;
gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
ctx.pc = pc_start;
- ctx.flags = (uint32_t)tb->flags;
+ ctx.flags = (uint32_t)tb->cpu_state.flags;
ctx.bstate = BS_NONE;
ctx.sr = env->sr;
ctx.fpscr = env->fpscr;
Index: b/target-sparc/cpu.h
===================================================================
--- a/target-sparc/cpu.h
+++ b/target-sparc/cpu.h
@@ -491,12 +491,8 @@ static inline void cpu_clone_regs(CPUSta
}
#endif
-#define CPU_PC_FROM_TB(env, tb) do { \
- env->pc = tb->pc; \
- env->npc = tb->cs_base; \
- } while(0)
-
#include "cpu-all.h"
+#include "exec-all.h"
/* sum4m.c, sun4u.c */
void cpu_check_irqs(CPUSPARCState *env);
@@ -508,4 +504,24 @@ uint64_t cpu_tick_get_count(void *opaque
void cpu_tick_set_limit(void *opaque, uint64_t limit);
#endif
+static inline void cpu_pc_from_tb(CPUState *env, TranslationBlock *tb)
+{
+ env->pc = tb->cpu_state.pc;
+ env->npc = tb->cpu_state.cs_base;
+}
+
+static inline void cpu_get_tb_cpu_state(CPUState *env, TBCPUState *cpu_state)
+{
+ cpu_state->pc = env->pc;
+ cpu_state->cs_base = env->npc;
+#ifdef TARGET_SPARC64
+ // AM . Combined FPU enable bits . PRIV . DMMU enabled . IMMU enabled
+ cpu_state->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
+ cpu_state->flags = (env->psref << 4) | env->psrs;
+#endif
+}
#endif
Index: b/target-sparc/translate.c
===================================================================
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -223,8 +223,8 @@ static inline void gen_goto_tb(DisasCont
TranslationBlock *tb;
tb = s->tb;
- if ((pc & TARGET_PAGE_MASK) == (tb->pc & TARGET_PAGE_MASK) &&
- (npc & TARGET_PAGE_MASK) == (tb->pc & TARGET_PAGE_MASK)) {
+ if ((pc & TARGET_PAGE_MASK) == (tb->cpu_state.pc & TARGET_PAGE_MASK) &&
+ (npc & TARGET_PAGE_MASK) == (tb->cpu_state.pc & TARGET_PAGE_MASK)) {
/* jump to same page: we can use a direct jump */
tcg_gen_goto_tb(tb_num);
tcg_gen_movi_tl(cpu_pc, pc);
@@ -4783,10 +4783,10 @@ static inline void gen_intermediate_code
memset(dc, 0, sizeof(DisasContext));
dc->tb = tb;
- pc_start = tb->pc;
+ pc_start = tb->cpu_state.pc;
dc->pc = pc_start;
last_pc = dc->pc;
- dc->npc = (target_ulong) tb->cs_base;
+ dc->npc = (target_ulong) tb->cpu_state.cs_base;
dc->mem_idx = cpu_mmu_index(env);
dc->def = env->def;
if ((dc->def->features & CPU_FEATURE_FLOAT))
- Re: [Qemu-devel] [PATCH 03/12] Refactor and enhance break/watchpoint API, (continued)
[Qemu-devel] [PATCH 04/12] Set mem_io_vaddr on io_read, Jan Kiszka, 2008/11/03
[Qemu-devel] [PATCH 06/12] Restore pc on watchpoint hits, Jan Kiszka, 2008/11/03
[Qemu-devel] [PATCH 11/12] Introduce BP_CPU as a breakpoint type, Jan Kiszka, 2008/11/03
[Qemu-devel] [PATCH 08/12] qemu: gdbstub: manage CPUs as threads, Jan Kiszka, 2008/11/03
[Qemu-devel] [PATCH 09/12] Introduce BP_WATCHPOINT_HIT flag, Jan Kiszka, 2008/11/03
[Qemu-devel] [PATCH 07/12] Remove premature memop TB terminations, Jan Kiszka, 2008/11/03
[Qemu-devel] [PATCH 01/12] Refactor translation block CPU state handling,
Jan Kiszka <=
[Qemu-devel] [PATCH 12/12] x86: Debug register emulation, Jan Kiszka, 2008/11/03
[Qemu-devel] [PATCH 05/12] Respect length of watchpoints, Jan Kiszka, 2008/11/03
Re: [Qemu-devel] [PATCH 00/12] Enhance debugging support - 4th take, Anthony Liguori, 2008/11/13
Re: [Qemu-devel] [PATCH 00/12] Enhance debugging support - 4th take, Fabrice Bellard, 2008/11/13