mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge remote-tracking branch 'remotes/rth/tags/pull-tcg-20160512' into staging
queued 2.7 patches # gpg: Signature made Fri 13 May 2016 01:08:20 BST using RSA key ID 4DD0279B # gpg: Good signature from "Richard Henderson <rth7680@gmail.com>" # gpg: aka "Richard Henderson <rth@redhat.com>" # gpg: aka "Richard Henderson <rth@twiddle.net>" * remotes/rth/tags/pull-tcg-20160512: (39 commits) cpu-exec: Clean up 'interrupt_request' reloading in cpu_handle_interrupt() cpu-exec: Remove unused 'x86_cpu' and 'env' from cpu_exec() cpu-exec: Move TB execution stuff out of cpu_exec() cpu-exec: Move interrupt handling out of cpu_exec() cpu-exec: Move exception handling out of cpu_exec() cpu-exec: Move halt handling out of cpu_exec() cpu-exec: Remove relic orphaned comment tcg: Remove needless CPUState::current_tb cpu-exec: Move TB chaining into tb_find_fast() tcg: Rework tb_invalidated_flag tcg: Clean up from 'next_tb' cpu-exec: elide more icount code if CONFIG_USER_ONLY tcg: reorganize tb_find_physical loop tcg: code_bitmap and code_write_count are not used by user-mode emulation tcg: Allow goto_tb to any target PC in user mode tcg: Clean up direct block chaining safety checks tcg: Clean up tb_jmp_unlink() tcg: Extract removing of jumps to TB from tb_phys_invalidate() tcg: Rename tb_jmp_remove() to tb_remove_from_jmp_list() tcg: Clarify thread safety check in tb_add_jump() ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
@@ -68,7 +68,6 @@ void cpu_reloading_memory_map(void)
|
||||
|
||||
void cpu_loop_exit(CPUState *cpu)
|
||||
{
|
||||
cpu->current_tb = NULL;
|
||||
siglongjmp(cpu->jmp_env, 1);
|
||||
}
|
||||
|
||||
@@ -77,6 +76,5 @@ void cpu_loop_exit_restore(CPUState *cpu, uintptr_t pc)
|
||||
if (pc) {
|
||||
cpu_restore_state(cpu, pc);
|
||||
}
|
||||
cpu->current_tb = NULL;
|
||||
siglongjmp(cpu->jmp_env, 1);
|
||||
}
|
||||
|
||||
+279
-240
File diff suppressed because it is too large
Load Diff
@@ -76,10 +76,6 @@ void tlb_flush(CPUState *cpu, int flush_global)
|
||||
|
||||
tlb_debug("(%d)\n", flush_global);
|
||||
|
||||
/* must reset current TB so that interrupts cannot modify the
|
||||
links while we are modifying them */
|
||||
cpu->current_tb = NULL;
|
||||
|
||||
memset(env->tlb_table, -1, sizeof(env->tlb_table));
|
||||
memset(env->tlb_v_table, -1, sizeof(env->tlb_v_table));
|
||||
memset(cpu->tb_jmp_cache, 0, sizeof(cpu->tb_jmp_cache));
|
||||
@@ -95,9 +91,6 @@ static inline void v_tlb_flush_by_mmuidx(CPUState *cpu, va_list argp)
|
||||
CPUArchState *env = cpu->env_ptr;
|
||||
|
||||
tlb_debug("start\n");
|
||||
/* must reset current TB so that interrupts cannot modify the
|
||||
links while we are modifying them */
|
||||
cpu->current_tb = NULL;
|
||||
|
||||
for (;;) {
|
||||
int mmu_idx = va_arg(argp, int);
|
||||
@@ -152,9 +145,6 @@ void tlb_flush_page(CPUState *cpu, target_ulong addr)
|
||||
tlb_flush(cpu, 1);
|
||||
return;
|
||||
}
|
||||
/* must reset current TB so that interrupts cannot modify the
|
||||
links while we are modifying them */
|
||||
cpu->current_tb = NULL;
|
||||
|
||||
addr &= TARGET_PAGE_MASK;
|
||||
i = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
|
||||
@@ -193,9 +183,6 @@ void tlb_flush_page_by_mmuidx(CPUState *cpu, target_ulong addr, ...)
|
||||
va_end(argp);
|
||||
return;
|
||||
}
|
||||
/* must reset current TB so that interrupts cannot modify the
|
||||
links while we are modifying them */
|
||||
cpu->current_tb = NULL;
|
||||
|
||||
addr &= TARGET_PAGE_MASK;
|
||||
i = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
|
||||
|
||||
@@ -2087,7 +2087,7 @@ static void check_watchpoint(int offset, int len, MemTxAttrs attrs, int flags)
|
||||
target_ulong pc, cs_base;
|
||||
target_ulong vaddr;
|
||||
CPUWatchpoint *wp;
|
||||
int cpu_flags;
|
||||
uint32_t cpu_flags;
|
||||
|
||||
if (cpu->watchpoint_hit) {
|
||||
/* We re-entered the check after replacing the TB. Now raise
|
||||
|
||||
+1
-2
@@ -397,7 +397,7 @@ static void patch_instruction(VAPICROMState *s, X86CPU *cpu, target_ulong ip)
|
||||
uint32_t imm32;
|
||||
target_ulong current_pc = 0;
|
||||
target_ulong current_cs_base = 0;
|
||||
int current_flags = 0;
|
||||
uint32_t current_flags = 0;
|
||||
|
||||
if (smp_cpus == 1) {
|
||||
handlers = &s->rom_state.up;
|
||||
@@ -446,7 +446,6 @@ static void patch_instruction(VAPICROMState *s, X86CPU *cpu, target_ulong ip)
|
||||
resume_all_vcpus();
|
||||
|
||||
if (!kvm_enabled()) {
|
||||
cs->current_tb = NULL;
|
||||
tb_gen_code(cs, current_pc, current_cs_base, current_flags, 1);
|
||||
cpu_resume_from_signal(cs, NULL);
|
||||
}
|
||||
|
||||
+52
-56
@@ -76,7 +76,8 @@ bool cpu_restore_state(CPUState *cpu, uintptr_t searched_pc);
|
||||
void QEMU_NORETURN cpu_resume_from_signal(CPUState *cpu, void *puc);
|
||||
void QEMU_NORETURN cpu_io_recompile(CPUState *cpu, uintptr_t retaddr);
|
||||
TranslationBlock *tb_gen_code(CPUState *cpu,
|
||||
target_ulong pc, target_ulong cs_base, int flags,
|
||||
target_ulong pc, target_ulong cs_base,
|
||||
uint32_t flags,
|
||||
int cflags);
|
||||
void cpu_exec_init(CPUState *cpu, Error **errp);
|
||||
void QEMU_NORETURN cpu_loop_exit(CPUState *cpu);
|
||||
@@ -229,13 +230,14 @@ static inline void tlb_flush_by_mmuidx(CPUState *cpu, ...)
|
||||
|| defined(__sparc__) || defined(__aarch64__) \
|
||||
|| defined(__s390x__) || defined(__mips__) \
|
||||
|| defined(CONFIG_TCG_INTERPRETER)
|
||||
/* NOTE: Direct jump patching must be atomic to be thread-safe. */
|
||||
#define USE_DIRECT_JUMP
|
||||
#endif
|
||||
|
||||
struct TranslationBlock {
|
||||
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 */
|
||||
uint32_t flags; /* flags defining in which context the code was generated */
|
||||
uint16_t size; /* size of target code for this block (1 <=
|
||||
size <= TARGET_PAGE_SIZE) */
|
||||
uint16_t icount;
|
||||
@@ -257,20 +259,34 @@ struct TranslationBlock {
|
||||
struct TranslationBlock *page_next[2];
|
||||
tb_page_addr_t page_addr[2];
|
||||
|
||||
/* the following data are used to directly call another TB from
|
||||
the code of this one. */
|
||||
uint16_t tb_next_offset[2]; /* offset of original jump target */
|
||||
/* The following data are used to directly call another TB from
|
||||
* the code of this one. This can be done either by emitting direct or
|
||||
* indirect native jump instructions. These jumps are reset so that the TB
|
||||
* just continue its execution. The TB can be linked to another one by
|
||||
* setting one of the jump targets (or patching the jump instruction). Only
|
||||
* two of such jumps are supported.
|
||||
*/
|
||||
uint16_t jmp_reset_offset[2]; /* offset of original jump target */
|
||||
#define TB_JMP_RESET_OFFSET_INVALID 0xffff /* indicates no jump generated */
|
||||
#ifdef USE_DIRECT_JUMP
|
||||
uint16_t tb_jmp_offset[2]; /* offset of jump instruction */
|
||||
uint16_t jmp_insn_offset[2]; /* offset of native jump instruction */
|
||||
#else
|
||||
uintptr_t tb_next[2]; /* address of jump generated code */
|
||||
uintptr_t jmp_target_addr[2]; /* target address for indirect jump */
|
||||
#endif
|
||||
/* list of TBs jumping to this one. This is a circular list using
|
||||
the two least significant bits of the pointers to tell what is
|
||||
the next pointer: 0 = jmp_next[0], 1 = jmp_next[1], 2 =
|
||||
jmp_first */
|
||||
struct TranslationBlock *jmp_next[2];
|
||||
struct TranslationBlock *jmp_first;
|
||||
/* Each TB has an assosiated circular list of TBs jumping to this one.
|
||||
* jmp_list_first points to the first TB jumping to this one.
|
||||
* jmp_list_next is used to point to the next TB in a list.
|
||||
* Since each TB can have two jumps, it can participate in two lists.
|
||||
* jmp_list_first and jmp_list_next are 4-byte aligned pointers to a
|
||||
* TranslationBlock structure, but the two least significant bits of
|
||||
* them are used to encode which data field of the pointed TB should
|
||||
* be used to traverse the list further from that TB:
|
||||
* 0 => jmp_list_next[0], 1 => jmp_list_next[1], 2 => jmp_list_first.
|
||||
* In other words, 0/1 tells which jump is used in the pointed TB,
|
||||
* and 2 means that this is a pointer back to the target TB of this list.
|
||||
*/
|
||||
uintptr_t jmp_list_next[2];
|
||||
uintptr_t jmp_list_first;
|
||||
};
|
||||
|
||||
#include "qemu/thread.h"
|
||||
@@ -288,8 +304,6 @@ struct TBContext {
|
||||
/* statistics */
|
||||
int tb_flush_count;
|
||||
int tb_phys_invalidate_count;
|
||||
|
||||
int tb_invalidated_flag;
|
||||
};
|
||||
|
||||
void tb_free(TranslationBlock *tb);
|
||||
@@ -302,7 +316,7 @@ void tb_phys_invalidate(TranslationBlock *tb, tb_page_addr_t page_addr);
|
||||
static inline void tb_set_jmp_target1(uintptr_t jmp_addr, uintptr_t addr)
|
||||
{
|
||||
/* patch the branch destination */
|
||||
*(uint32_t *)jmp_addr = addr - (jmp_addr + 4);
|
||||
atomic_set((int32_t *)jmp_addr, addr - (jmp_addr + 4));
|
||||
/* no need to flush icache explicitly */
|
||||
}
|
||||
#elif defined(_ARCH_PPC)
|
||||
@@ -312,7 +326,7 @@ void ppc_tb_set_jmp_target(uintptr_t jmp_addr, uintptr_t addr);
|
||||
static inline void tb_set_jmp_target1(uintptr_t jmp_addr, uintptr_t addr)
|
||||
{
|
||||
/* patch the branch destination */
|
||||
stl_le_p((void*)jmp_addr, addr - (jmp_addr + 4));
|
||||
atomic_set((int32_t *)jmp_addr, addr - (jmp_addr + 4));
|
||||
/* no need to flush icache explicitly */
|
||||
}
|
||||
#elif defined(__s390x__)
|
||||
@@ -320,36 +334,15 @@ static inline void tb_set_jmp_target1(uintptr_t jmp_addr, uintptr_t addr)
|
||||
{
|
||||
/* patch the branch destination */
|
||||
intptr_t disp = addr - (jmp_addr - 2);
|
||||
stl_be_p((void*)jmp_addr, disp / 2);
|
||||
atomic_set((int32_t *)jmp_addr, disp / 2);
|
||||
/* no need to flush icache explicitly */
|
||||
}
|
||||
#elif defined(__aarch64__)
|
||||
void aarch64_tb_set_jmp_target(uintptr_t jmp_addr, uintptr_t addr);
|
||||
#define tb_set_jmp_target1 aarch64_tb_set_jmp_target
|
||||
#elif defined(__arm__)
|
||||
static inline void tb_set_jmp_target1(uintptr_t jmp_addr, uintptr_t addr)
|
||||
{
|
||||
#if !QEMU_GNUC_PREREQ(4, 1)
|
||||
register unsigned long _beg __asm ("a1");
|
||||
register unsigned long _end __asm ("a2");
|
||||
register unsigned long _flg __asm ("a3");
|
||||
#endif
|
||||
|
||||
/* we could use a ldr pc, [pc, #-4] kind of branch and avoid the flush */
|
||||
*(uint32_t *)jmp_addr =
|
||||
(*(uint32_t *)jmp_addr & ~0xffffff)
|
||||
| (((addr - (jmp_addr + 8)) >> 2) & 0xffffff);
|
||||
|
||||
#if QEMU_GNUC_PREREQ(4, 1)
|
||||
__builtin___clear_cache((char *) jmp_addr, (char *) jmp_addr + 4);
|
||||
#else
|
||||
/* flush icache */
|
||||
_beg = jmp_addr;
|
||||
_end = jmp_addr + 4;
|
||||
_flg = 0;
|
||||
__asm __volatile__ ("swi 0x9f0002" : : "r" (_beg), "r" (_end), "r" (_flg));
|
||||
#endif
|
||||
}
|
||||
void arm_tb_set_jmp_target(uintptr_t jmp_addr, uintptr_t addr);
|
||||
#define tb_set_jmp_target1 arm_tb_set_jmp_target
|
||||
#elif defined(__sparc__) || defined(__mips__)
|
||||
void tb_set_jmp_target1(uintptr_t jmp_addr, uintptr_t addr);
|
||||
#else
|
||||
@@ -359,7 +352,7 @@ void tb_set_jmp_target1(uintptr_t jmp_addr, uintptr_t addr);
|
||||
static inline void tb_set_jmp_target(TranslationBlock *tb,
|
||||
int n, uintptr_t addr)
|
||||
{
|
||||
uint16_t offset = tb->tb_jmp_offset[n];
|
||||
uint16_t offset = tb->jmp_insn_offset[n];
|
||||
tb_set_jmp_target1((uintptr_t)(tb->tc_ptr + offset), addr);
|
||||
}
|
||||
|
||||
@@ -369,7 +362,7 @@ static inline void tb_set_jmp_target(TranslationBlock *tb,
|
||||
static inline void tb_set_jmp_target(TranslationBlock *tb,
|
||||
int n, uintptr_t addr)
|
||||
{
|
||||
tb->tb_next[n] = addr;
|
||||
tb->jmp_target_addr[n] = addr;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -377,20 +370,23 @@ static inline void tb_set_jmp_target(TranslationBlock *tb,
|
||||
static inline void tb_add_jump(TranslationBlock *tb, int n,
|
||||
TranslationBlock *tb_next)
|
||||
{
|
||||
/* NOTE: this test is only needed for thread safety */
|
||||
if (!tb->jmp_next[n]) {
|
||||
qemu_log_mask_and_addr(CPU_LOG_EXEC, tb->pc,
|
||||
"Linking TBs %p [" TARGET_FMT_lx
|
||||
"] index %d -> %p [" TARGET_FMT_lx "]\n",
|
||||
tb->tc_ptr, tb->pc, n,
|
||||
tb_next->tc_ptr, tb_next->pc);
|
||||
/* patch the native jump address */
|
||||
tb_set_jmp_target(tb, n, (uintptr_t)tb_next->tc_ptr);
|
||||
|
||||
/* add in TB jmp circular list */
|
||||
tb->jmp_next[n] = tb_next->jmp_first;
|
||||
tb_next->jmp_first = (TranslationBlock *)((uintptr_t)(tb) | (n));
|
||||
if (tb->jmp_list_next[n]) {
|
||||
/* Another thread has already done this while we were
|
||||
* outside of the lock; nothing to do in this case */
|
||||
return;
|
||||
}
|
||||
qemu_log_mask_and_addr(CPU_LOG_EXEC, tb->pc,
|
||||
"Linking TBs %p [" TARGET_FMT_lx
|
||||
"] index %d -> %p [" TARGET_FMT_lx "]\n",
|
||||
tb->tc_ptr, tb->pc, n,
|
||||
tb_next->tc_ptr, tb_next->pc);
|
||||
|
||||
/* patch the native jump address */
|
||||
tb_set_jmp_target(tb, n, (uintptr_t)tb_next->tc_ptr);
|
||||
|
||||
/* add in TB jmp circular list */
|
||||
tb->jmp_list_next[n] = tb_next->jmp_list_first;
|
||||
tb_next->jmp_list_first = (uintptr_t)tb | n;
|
||||
}
|
||||
|
||||
/* GETRA is the true target of the return instruction that we'll execute,
|
||||
|
||||
@@ -158,6 +158,20 @@ extern int daemon(int, int);
|
||||
/* Round number up to multiple */
|
||||
#define QEMU_ALIGN_UP(n, m) QEMU_ALIGN_DOWN((n) + (m) - 1, (m))
|
||||
|
||||
/* Check if n is a multiple of m */
|
||||
#define QEMU_IS_ALIGNED(n, m) (((n) % (m)) == 0)
|
||||
|
||||
/* n-byte align pointer down */
|
||||
#define QEMU_ALIGN_PTR_DOWN(p, n) \
|
||||
((typeof(p))QEMU_ALIGN_DOWN((uintptr_t)(p), (n)))
|
||||
|
||||
/* n-byte align pointer up */
|
||||
#define QEMU_ALIGN_PTR_UP(p, n) \
|
||||
((typeof(p))QEMU_ALIGN_UP((uintptr_t)(p), (n)))
|
||||
|
||||
/* Check if pointer p is n-bytes aligned */
|
||||
#define QEMU_PTR_IS_ALIGNED(p, n) QEMU_IS_ALIGNED((uintptr_t)(p), (n))
|
||||
|
||||
#ifndef ROUND_UP
|
||||
#define ROUND_UP(n,d) (((n) + (d) - 1) & -(d))
|
||||
#endif
|
||||
|
||||
+2
-2
@@ -238,6 +238,7 @@ struct kvm_run;
|
||||
* @crash_occurred: Indicates the OS reported a crash (panic) for this CPU
|
||||
* @tcg_exit_req: Set to force TCG to stop executing linked TBs for this
|
||||
* CPU and return to its top level loop.
|
||||
* @tb_flushed: Indicates the translation buffer has been flushed.
|
||||
* @singlestep_enabled: Flags for single-stepping.
|
||||
* @icount_extra: Instructions until next timer event.
|
||||
* @icount_decr: Number of cycles left, with interrupt flag in high bit.
|
||||
@@ -252,7 +253,6 @@ struct kvm_run;
|
||||
* @as: Pointer to the first AddressSpace, for the convenience of targets which
|
||||
* only have a single AddressSpace
|
||||
* @env_ptr: Pointer to subclass-specific CPUArchState field.
|
||||
* @current_tb: Currently executing TB.
|
||||
* @gdb_regs: Additional GDB registers.
|
||||
* @gdb_num_regs: Number of total registers accessible to GDB.
|
||||
* @gdb_num_g_regs: Number of registers in GDB 'g' packets.
|
||||
@@ -289,6 +289,7 @@ struct CPUState {
|
||||
bool stopped;
|
||||
bool crash_occurred;
|
||||
bool exit_request;
|
||||
bool tb_flushed;
|
||||
uint32_t interrupt_request;
|
||||
int singlestep_enabled;
|
||||
int64_t icount_extra;
|
||||
@@ -303,7 +304,6 @@ struct CPUState {
|
||||
MemoryRegion *memory;
|
||||
|
||||
void *env_ptr; /* CPUArchState */
|
||||
struct TranslationBlock *current_tb;
|
||||
struct TranslationBlock *tb_jmp_cache[TB_JMP_CACHE_SIZE];
|
||||
struct GDBRegisterState *gdb_regs;
|
||||
int gdb_num_regs;
|
||||
|
||||
@@ -254,7 +254,6 @@ static void cpu_common_reset(CPUState *cpu)
|
||||
}
|
||||
|
||||
cpu->interrupt_request = 0;
|
||||
cpu->current_tb = NULL;
|
||||
cpu->halted = 0;
|
||||
cpu->mem_io_pc = 0;
|
||||
cpu->mem_io_vaddr = 0;
|
||||
|
||||
+1
-1
@@ -465,7 +465,7 @@ enum {
|
||||
};
|
||||
|
||||
static inline void cpu_get_tb_cpu_state(CPUAlphaState *env, target_ulong *pc,
|
||||
target_ulong *cs_base, int *pflags)
|
||||
target_ulong *cs_base, uint32_t *pflags)
|
||||
{
|
||||
int flags = 0;
|
||||
|
||||
|
||||
@@ -460,12 +460,16 @@ static bool use_goto_tb(DisasContext *ctx, uint64_t dest)
|
||||
|| ctx->singlestep_enabled || singlestep) {
|
||||
return false;
|
||||
}
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
/* If the destination is in the superpage, the page perms can't change. */
|
||||
if (in_superpage(ctx, dest)) {
|
||||
return true;
|
||||
}
|
||||
/* Check for the dest on the same page as the start of the TB. */
|
||||
return ((ctx->tb->pc ^ dest) & TARGET_PAGE_MASK) == 0;
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
static ExitStatus gen_bdirect(DisasContext *ctx, int ra, int32_t disp)
|
||||
|
||||
+1
-1
@@ -2117,7 +2117,7 @@ static inline bool arm_cpu_bswap_data(CPUARMState *env)
|
||||
#endif
|
||||
|
||||
static inline void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
|
||||
target_ulong *cs_base, int *flags)
|
||||
target_ulong *cs_base, uint32_t *flags)
|
||||
{
|
||||
if (is_a64(env)) {
|
||||
*pc = env->pc;
|
||||
|
||||
@@ -274,10 +274,12 @@ static inline bool use_goto_tb(DisasContext *s, int n, uint64_t dest)
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
/* Only link tbs from inside the same guest page */
|
||||
if ((s->tb->pc & TARGET_PAGE_MASK) != (dest & TARGET_PAGE_MASK)) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
+12
-5
@@ -4049,15 +4049,22 @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline bool use_goto_tb(DisasContext *s, target_ulong dest)
|
||||
{
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
return (s->tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) ||
|
||||
((s->pc - 1) & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void gen_goto_tb(DisasContext *s, int n, target_ulong dest)
|
||||
{
|
||||
TranslationBlock *tb;
|
||||
|
||||
tb = s->tb;
|
||||
if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
|
||||
if (use_goto_tb(s, dest)) {
|
||||
tcg_gen_goto_tb(n);
|
||||
gen_set_pc_im(s, dest);
|
||||
tcg_gen_exit_tb((uintptr_t)tb + n);
|
||||
tcg_gen_exit_tb((uintptr_t)s->tb + n);
|
||||
} else {
|
||||
gen_set_pc_im(s, dest);
|
||||
tcg_gen_exit_tb(0);
|
||||
|
||||
+1
-1
@@ -249,7 +249,7 @@ int cris_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int rw,
|
||||
#include "exec/cpu-all.h"
|
||||
|
||||
static inline void cpu_get_tb_cpu_state(CPUCRISState *env, target_ulong *pc,
|
||||
target_ulong *cs_base, int *flags)
|
||||
target_ulong *cs_base, uint32_t *flags)
|
||||
{
|
||||
*pc = env->pc;
|
||||
*cs_base = 0;
|
||||
|
||||
+12
-4
@@ -520,14 +520,22 @@ static void t_gen_cc_jmp(TCGv pc_true, TCGv pc_false)
|
||||
gen_set_label(l1);
|
||||
}
|
||||
|
||||
static inline bool use_goto_tb(DisasContext *dc, target_ulong dest)
|
||||
{
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
return (dc->tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) ||
|
||||
(dc->ppc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest)
|
||||
{
|
||||
TranslationBlock *tb;
|
||||
tb = dc->tb;
|
||||
if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
|
||||
if (use_goto_tb(dc, dest)) {
|
||||
tcg_gen_goto_tb(n);
|
||||
tcg_gen_movi_tl(env_pc, dest);
|
||||
tcg_gen_exit_tb((uintptr_t)tb + n);
|
||||
tcg_gen_exit_tb((uintptr_t)dc->tb + n);
|
||||
} else {
|
||||
tcg_gen_movi_tl(env_pc, dest);
|
||||
tcg_gen_exit_tb(0);
|
||||
|
||||
+1
-1
@@ -1269,7 +1269,7 @@ void tcg_x86_init(void);
|
||||
#include "exec/exec-all.h"
|
||||
|
||||
static inline void cpu_get_tb_cpu_state(CPUX86State *env, target_ulong *pc,
|
||||
target_ulong *cs_base, int *flags)
|
||||
target_ulong *cs_base, uint32_t *flags)
|
||||
{
|
||||
*cs_base = env->segs[R_CS].base;
|
||||
*pc = *cs_base + env->eip;
|
||||
|
||||
+14
-9
@@ -2085,20 +2085,25 @@ static inline int insn_const_size(TCGMemOp ot)
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool use_goto_tb(DisasContext *s, target_ulong pc)
|
||||
{
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
return (pc & TARGET_PAGE_MASK) == (s->tb->pc & TARGET_PAGE_MASK) ||
|
||||
(pc & TARGET_PAGE_MASK) == (s->pc_start & TARGET_PAGE_MASK);
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void gen_goto_tb(DisasContext *s, int tb_num, target_ulong eip)
|
||||
{
|
||||
TranslationBlock *tb;
|
||||
target_ulong pc;
|
||||
target_ulong pc = s->cs_base + eip;
|
||||
|
||||
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) ||
|
||||
(pc & TARGET_PAGE_MASK) == ((s->pc - 1) & TARGET_PAGE_MASK)) {
|
||||
if (use_goto_tb(s, pc)) {
|
||||
/* jump to same page: we can use a direct jump */
|
||||
tcg_gen_goto_tb(tb_num);
|
||||
gen_jmp_im(eip);
|
||||
tcg_gen_exit_tb((uintptr_t)tb + tb_num);
|
||||
tcg_gen_exit_tb((uintptr_t)s->tb + tb_num);
|
||||
} else {
|
||||
/* jump to another page: currently not optimized */
|
||||
gen_jmp_im(eip);
|
||||
@@ -8178,7 +8183,7 @@ void gen_intermediate_code(CPUX86State *env, TranslationBlock *tb)
|
||||
CPUState *cs = CPU(cpu);
|
||||
DisasContext dc1, *dc = &dc1;
|
||||
target_ulong pc_ptr;
|
||||
uint64_t flags;
|
||||
uint32_t flags;
|
||||
target_ulong pc_start;
|
||||
target_ulong cs_base;
|
||||
int num_insns;
|
||||
|
||||
+1
-1
@@ -226,7 +226,7 @@ int lm32_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int rw,
|
||||
#include "exec/cpu-all.h"
|
||||
|
||||
static inline void cpu_get_tb_cpu_state(CPULM32State *env, target_ulong *pc,
|
||||
target_ulong *cs_base, int *flags)
|
||||
target_ulong *cs_base, uint32_t *flags)
|
||||
{
|
||||
*pc = env->pc;
|
||||
*cs_base = 0;
|
||||
|
||||
+15
-6
@@ -133,16 +133,25 @@ static inline void t_gen_illegal_insn(DisasContext *dc)
|
||||
gen_helper_ill(cpu_env);
|
||||
}
|
||||
|
||||
static inline bool use_goto_tb(DisasContext *dc, target_ulong dest)
|
||||
{
|
||||
if (unlikely(dc->singlestep_enabled)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
return (dc->tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest)
|
||||
{
|
||||
TranslationBlock *tb;
|
||||
|
||||
tb = dc->tb;
|
||||
if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
|
||||
likely(!dc->singlestep_enabled)) {
|
||||
if (use_goto_tb(dc, dest)) {
|
||||
tcg_gen_goto_tb(n);
|
||||
tcg_gen_movi_tl(cpu_pc, dest);
|
||||
tcg_gen_exit_tb((uintptr_t)tb + n);
|
||||
tcg_gen_exit_tb((uintptr_t)dc->tb + n);
|
||||
} else {
|
||||
tcg_gen_movi_tl(cpu_pc, dest);
|
||||
if (dc->singlestep_enabled) {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user