Add translator_use_goto_tb.
Cleanups in prep of breakpoint fixes. Misc fixes. -----BEGIN PGP SIGNATURE----- iQFRBAABCgA7FiEEekgeeIaLTbaoWgXAZN846K9+IV8FAmDpvModHHJpY2hhcmQu aGVuZGVyc29uQGxpbmFyby5vcmcACgkQZN846K9+IV/1jgf+J1JMsPfxlSCwbbdc WEuWEcuKdcDFqhsePa6LaPYHTKuEEwavTG0kPbLIVZW2f6BTBeSYxAC6EWhq7pWo MGMhIOZM3fF0Yj+azuoybu9qxQ/K/aLM3GYt/OU00mvzturBezz+ka8MvWCrUwta XlhxhwnKsSP7lDWPBBjcdIIGiFJyxIRoU43giWaXrsvsc8ORJbmy7rgZfTKAit+w AvtQlc7TBi5nImz6f/KmEoy8mHEOhMf7czzo+v0u97lTiNK717/AHEwMfX9J585O GjlA9XmUUsNAciuLy48F1rHkgJxYAwo0G2shklpqPaOP5FctKm1reCSb8VEfAGaX Xq3UVA== =E9i/ -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/rth-gitlab/tags/pull-tcg-20210710' into staging Add translator_use_goto_tb. Cleanups in prep of breakpoint fixes. Misc fixes. # gpg: Signature made Sat 10 Jul 2021 16:29:14 BST # gpg: using RSA key 7A481E78868B4DB6A85A05C064DF38E8AF7E215F # gpg: issuer "richard.henderson@linaro.org" # gpg: Good signature from "Richard Henderson <richard.henderson@linaro.org>" [full] # Primary key fingerprint: 7A48 1E78 868B 4DB6 A85A 05C0 64DF 38E8 AF7E 215F * remotes/rth-gitlab/tags/pull-tcg-20210710: (41 commits) cpu: Add breakpoint tracepoints tcg: Remove TCG_TARGET_HAS_goto_ptr accel/tcg: Log tb->cflags with -d exec accel/tcg: Split out log_cpu_exec accel/tcg: Move tb_lookup to cpu-exec.c accel/tcg: Move helper_lookup_tb_ptr to cpu-exec.c target/i386: Use cpu_breakpoint_test in breakpoint_handler tcg: Fix prologue disassembly target/xtensa: Use translator_use_goto_tb target/tricore: Use tcg_gen_lookup_and_goto_ptr target/tricore: Use translator_use_goto_tb target/sparc: Use translator_use_goto_tb target/sh4: Use translator_use_goto_tb target/s390x: Remove use_exit_tb target/s390x: Use translator_use_goto_tb target/rx: Use translator_use_goto_tb target/riscv: Use translator_use_goto_tb target/ppc: Use translator_use_goto_tb target/openrisc: Use translator_use_goto_tb target/nios2: Use translator_use_goto_tb ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
bd38ae26ce
@ -38,8 +38,8 @@
|
||||
#include "exec/cpu-all.h"
|
||||
#include "sysemu/cpu-timers.h"
|
||||
#include "sysemu/replay.h"
|
||||
#include "exec/helper-proto.h"
|
||||
#include "tb-hash.h"
|
||||
#include "tb-lookup.h"
|
||||
#include "tb-context.h"
|
||||
#include "internal.h"
|
||||
|
||||
@ -145,6 +145,93 @@ static void init_delay_params(SyncClocks *sc, const CPUState *cpu)
|
||||
}
|
||||
#endif /* CONFIG USER ONLY */
|
||||
|
||||
/* Might cause an exception, so have a longjmp destination ready */
|
||||
static inline TranslationBlock *tb_lookup(CPUState *cpu, target_ulong pc,
|
||||
target_ulong cs_base,
|
||||
uint32_t flags, uint32_t cflags)
|
||||
{
|
||||
TranslationBlock *tb;
|
||||
uint32_t hash;
|
||||
|
||||
/* we should never be trying to look up an INVALID tb */
|
||||
tcg_debug_assert(!(cflags & CF_INVALID));
|
||||
|
||||
hash = tb_jmp_cache_hash_func(pc);
|
||||
tb = qatomic_rcu_read(&cpu->tb_jmp_cache[hash]);
|
||||
|
||||
if (likely(tb &&
|
||||
tb->pc == pc &&
|
||||
tb->cs_base == cs_base &&
|
||||
tb->flags == flags &&
|
||||
tb->trace_vcpu_dstate == *cpu->trace_dstate &&
|
||||
tb_cflags(tb) == cflags)) {
|
||||
return tb;
|
||||
}
|
||||
tb = tb_htable_lookup(cpu, pc, cs_base, flags, cflags);
|
||||
if (tb == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
qatomic_set(&cpu->tb_jmp_cache[hash], tb);
|
||||
return tb;
|
||||
}
|
||||
|
||||
static inline void log_cpu_exec(target_ulong pc, CPUState *cpu,
|
||||
const TranslationBlock *tb)
|
||||
{
|
||||
if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_CPU | CPU_LOG_EXEC))
|
||||
&& qemu_log_in_addr_range(pc)) {
|
||||
|
||||
qemu_log_mask(CPU_LOG_EXEC,
|
||||
"Trace %d: %p [" TARGET_FMT_lx
|
||||
"/" TARGET_FMT_lx "/%08x/%08x] %s\n",
|
||||
cpu->cpu_index, tb->tc.ptr, tb->cs_base, pc,
|
||||
tb->flags, tb->cflags, lookup_symbol(pc));
|
||||
|
||||
#if defined(DEBUG_DISAS)
|
||||
if (qemu_loglevel_mask(CPU_LOG_TB_CPU)) {
|
||||
FILE *logfile = qemu_log_lock();
|
||||
int flags = 0;
|
||||
|
||||
if (qemu_loglevel_mask(CPU_LOG_TB_FPU)) {
|
||||
flags |= CPU_DUMP_FPU;
|
||||
}
|
||||
#if defined(TARGET_I386)
|
||||
flags |= CPU_DUMP_CCOP;
|
||||
#endif
|
||||
log_cpu_state(cpu, flags);
|
||||
qemu_log_unlock(logfile);
|
||||
}
|
||||
#endif /* DEBUG_DISAS */
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* helper_lookup_tb_ptr: quick check for next tb
|
||||
* @env: current cpu state
|
||||
*
|
||||
* Look for an existing TB matching the current cpu state.
|
||||
* If found, return the code pointer. If not found, return
|
||||
* the tcg epilogue so that we return into cpu_tb_exec.
|
||||
*/
|
||||
const void *HELPER(lookup_tb_ptr)(CPUArchState *env)
|
||||
{
|
||||
CPUState *cpu = env_cpu(env);
|
||||
TranslationBlock *tb;
|
||||
target_ulong cs_base, pc;
|
||||
uint32_t flags;
|
||||
|
||||
cpu_get_tb_cpu_state(env, &pc, &cs_base, &flags);
|
||||
|
||||
tb = tb_lookup(cpu, pc, cs_base, flags, curr_cflags(cpu));
|
||||
if (tb == NULL) {
|
||||
return tcg_code_gen_epilogue;
|
||||
}
|
||||
|
||||
log_cpu_exec(pc, cpu, tb);
|
||||
|
||||
return tb->tc.ptr;
|
||||
}
|
||||
|
||||
/* Execute a TB, and fix up the CPU state afterwards if necessary */
|
||||
/*
|
||||
* Disable CFI checks.
|
||||
@ -163,28 +250,7 @@ cpu_tb_exec(CPUState *cpu, TranslationBlock *itb, int *tb_exit)
|
||||
TranslationBlock *last_tb;
|
||||
const void *tb_ptr = itb->tc.ptr;
|
||||
|
||||
qemu_log_mask_and_addr(CPU_LOG_EXEC, itb->pc,
|
||||
"Trace %d: %p ["
|
||||
TARGET_FMT_lx "/" TARGET_FMT_lx "/%#x] %s\n",
|
||||
cpu->cpu_index, itb->tc.ptr,
|
||||
itb->cs_base, itb->pc, itb->flags,
|
||||
lookup_symbol(itb->pc));
|
||||
|
||||
#if defined(DEBUG_DISAS)
|
||||
if (qemu_loglevel_mask(CPU_LOG_TB_CPU)
|
||||
&& qemu_log_in_addr_range(itb->pc)) {
|
||||
FILE *logfile = qemu_log_lock();
|
||||
int flags = 0;
|
||||
if (qemu_loglevel_mask(CPU_LOG_TB_FPU)) {
|
||||
flags |= CPU_DUMP_FPU;
|
||||
}
|
||||
#if defined(TARGET_I386)
|
||||
flags |= CPU_DUMP_CCOP;
|
||||
#endif
|
||||
log_cpu_state(cpu, flags);
|
||||
qemu_log_unlock(logfile);
|
||||
}
|
||||
#endif /* DEBUG_DISAS */
|
||||
log_cpu_exec(itb->pc, cpu, itb);
|
||||
|
||||
qemu_thread_jit_execute();
|
||||
ret = tcg_qemu_tb_exec(env, tb_ptr);
|
||||
|
@ -34,6 +34,7 @@ struct TBContext {
|
||||
|
||||
/* statistics */
|
||||
unsigned tb_flush_count;
|
||||
unsigned tb_phys_invalidate_count;
|
||||
};
|
||||
|
||||
extern TBContext tb_ctx;
|
||||
|
@ -1,49 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017, Emilio G. Cota <cota@braap.org>
|
||||
*
|
||||
* License: GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
#ifndef EXEC_TB_LOOKUP_H
|
||||
#define EXEC_TB_LOOKUP_H
|
||||
|
||||
#ifdef NEED_CPU_H
|
||||
#include "cpu.h"
|
||||
#else
|
||||
#include "exec/poison.h"
|
||||
#endif
|
||||
|
||||
#include "exec/exec-all.h"
|
||||
#include "tb-hash.h"
|
||||
|
||||
/* Might cause an exception, so have a longjmp destination ready */
|
||||
static inline TranslationBlock *tb_lookup(CPUState *cpu, target_ulong pc,
|
||||
target_ulong cs_base,
|
||||
uint32_t flags, uint32_t cflags)
|
||||
{
|
||||
TranslationBlock *tb;
|
||||
uint32_t hash;
|
||||
|
||||
/* we should never be trying to look up an INVALID tb */
|
||||
tcg_debug_assert(!(cflags & CF_INVALID));
|
||||
|
||||
hash = tb_jmp_cache_hash_func(pc);
|
||||
tb = qatomic_rcu_read(&cpu->tb_jmp_cache[hash]);
|
||||
|
||||
if (likely(tb &&
|
||||
tb->pc == pc &&
|
||||
tb->cs_base == cs_base &&
|
||||
tb->flags == flags &&
|
||||
tb->trace_vcpu_dstate == *cpu->trace_dstate &&
|
||||
tb_cflags(tb) == cflags)) {
|
||||
return tb;
|
||||
}
|
||||
tb = tb_htable_lookup(cpu, pc, cs_base, flags, cflags);
|
||||
if (tb == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
qatomic_set(&cpu->tb_jmp_cache[hash], tb);
|
||||
return tb;
|
||||
}
|
||||
|
||||
#endif /* EXEC_TB_LOOKUP_H */
|
@ -30,7 +30,6 @@
|
||||
#include "disas/disas.h"
|
||||
#include "exec/log.h"
|
||||
#include "tcg/tcg.h"
|
||||
#include "tb-lookup.h"
|
||||
|
||||
/* 32-bit helpers */
|
||||
|
||||
@ -145,27 +144,6 @@ uint64_t HELPER(ctpop_i64)(uint64_t arg)
|
||||
return ctpop64(arg);
|
||||
}
|
||||
|
||||
const void *HELPER(lookup_tb_ptr)(CPUArchState *env)
|
||||
{
|
||||
CPUState *cpu = env_cpu(env);
|
||||
TranslationBlock *tb;
|
||||
target_ulong cs_base, pc;
|
||||
uint32_t flags;
|
||||
|
||||
cpu_get_tb_cpu_state(env, &pc, &cs_base, &flags);
|
||||
|
||||
tb = tb_lookup(cpu, pc, cs_base, flags, curr_cflags(cpu));
|
||||
if (tb == NULL) {
|
||||
return tcg_code_gen_epilogue;
|
||||
}
|
||||
qemu_log_mask_and_addr(CPU_LOG_EXEC, pc,
|
||||
"Chain %d: %p ["
|
||||
TARGET_FMT_lx "/" TARGET_FMT_lx "/%#x] %s\n",
|
||||
cpu->cpu_index, tb->tc.ptr, cs_base, pc, flags,
|
||||
lookup_symbol(pc));
|
||||
return tb->tc.ptr;
|
||||
}
|
||||
|
||||
void HELPER(exit_atomic)(CPUArchState *env)
|
||||
{
|
||||
cpu_loop_exit_atomic(env_cpu(env), GETPC());
|
||||
|
@ -378,11 +378,6 @@ static int cpu_restore_state_from_tb(CPUState *cpu, TranslationBlock *tb,
|
||||
return 0;
|
||||
}
|
||||
|
||||
void tb_destroy(TranslationBlock *tb)
|
||||
{
|
||||
qemu_spin_destroy(&tb->jmp_lock);
|
||||
}
|
||||
|
||||
bool cpu_restore_state(CPUState *cpu, uintptr_t host_pc, bool will_exit)
|
||||
{
|
||||
/*
|
||||
@ -1224,8 +1219,8 @@ static void do_tb_phys_invalidate(TranslationBlock *tb, bool rm_from_page_list)
|
||||
/* suppress any remaining jumps to this TB */
|
||||
tb_jmp_unlink(tb);
|
||||
|
||||
qatomic_set(&tcg_ctx->tb_phys_invalidate_count,
|
||||
tcg_ctx->tb_phys_invalidate_count + 1);
|
||||
qatomic_set(&tb_ctx.tb_phys_invalidate_count,
|
||||
tb_ctx.tb_phys_invalidate_count + 1);
|
||||
}
|
||||
|
||||
static void tb_phys_invalidate__locked(TranslationBlock *tb)
|
||||
@ -1657,6 +1652,13 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
|
||||
return tb;
|
||||
}
|
||||
|
||||
/*
|
||||
* Insert TB into the corresponding region tree before publishing it
|
||||
* through QHT. Otherwise rewinding happened in the TB might fail to
|
||||
* lookup itself using host PC.
|
||||
*/
|
||||
tcg_tb_insert(tb);
|
||||
|
||||
/* check next page if needed */
|
||||
virt_page2 = (pc + tb->size - 1) & TARGET_PAGE_MASK;
|
||||
phys_page2 = -1;
|
||||
@ -1674,10 +1676,9 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
|
||||
|
||||
orig_aligned -= ROUND_UP(sizeof(*tb), qemu_icache_linesize);
|
||||
qatomic_set(&tcg_ctx->code_gen_ptr, (void *)orig_aligned);
|
||||
tb_destroy(tb);
|
||||
tcg_tb_remove(tb);
|
||||
return existing_tb;
|
||||
}
|
||||
tcg_tb_insert(tb);
|
||||
return tb;
|
||||
}
|
||||
|
||||
@ -2127,8 +2128,8 @@ void dump_exec_info(void)
|
||||
qemu_printf("\nStatistics:\n");
|
||||
qemu_printf("TB flush count %u\n",
|
||||
qatomic_read(&tb_ctx.tb_flush_count));
|
||||
qemu_printf("TB invalidate count %zu\n",
|
||||
tcg_tb_phys_invalidate_count());
|
||||
qemu_printf("TB invalidate count %u\n",
|
||||
qatomic_read(&tb_ctx.tb_phys_invalidate_count));
|
||||
|
||||
tlb_flush_counts(&flush_full, &flush_part, &flush_elide);
|
||||
qemu_printf("TLB full flushes %zu\n", flush_full);
|
||||
|
@ -31,6 +31,17 @@ void translator_loop_temp_check(DisasContextBase *db)
|
||||
}
|
||||
}
|
||||
|
||||
bool translator_use_goto_tb(DisasContextBase *db, target_ulong dest)
|
||||
{
|
||||
/* Suppress goto_tb in the case of single-steping. */
|
||||
if (db->singlestep_enabled || singlestep) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Check for the dest on the same page as the start of the TB. */
|
||||
return ((db->pc_first ^ dest) & TARGET_PAGE_MASK) == 0;
|
||||
}
|
||||
|
||||
void translator_loop(const TranslatorOps *ops, DisasContextBase *db,
|
||||
CPUState *cpu, TranslationBlock *tb, int max_insns)
|
||||
{
|
||||
|
13
cpu.c
13
cpu.c
@ -38,6 +38,7 @@
|
||||
#include "exec/translate-all.h"
|
||||
#include "exec/log.h"
|
||||
#include "hw/core/accel-cpu.h"
|
||||
#include "trace/trace-root.h"
|
||||
|
||||
uintptr_t qemu_host_page_size;
|
||||
intptr_t qemu_host_page_mask;
|
||||
@ -285,6 +286,8 @@ int cpu_breakpoint_insert(CPUState *cpu, vaddr pc, int flags,
|
||||
if (breakpoint) {
|
||||
*breakpoint = bp;
|
||||
}
|
||||
|
||||
trace_breakpoint_insert(cpu->cpu_index, pc, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -303,13 +306,14 @@ int cpu_breakpoint_remove(CPUState *cpu, vaddr pc, int flags)
|
||||
}
|
||||
|
||||
/* Remove a specific breakpoint by reference. */
|
||||
void cpu_breakpoint_remove_by_ref(CPUState *cpu, CPUBreakpoint *breakpoint)
|
||||
void cpu_breakpoint_remove_by_ref(CPUState *cpu, CPUBreakpoint *bp)
|
||||
{
|
||||
QTAILQ_REMOVE(&cpu->breakpoints, breakpoint, entry);
|
||||
QTAILQ_REMOVE(&cpu->breakpoints, bp, entry);
|
||||
|
||||
breakpoint_invalidate(cpu, breakpoint->pc);
|
||||
breakpoint_invalidate(cpu, bp->pc);
|
||||
|
||||
g_free(breakpoint);
|
||||
trace_breakpoint_remove(cpu->cpu_index, bp->pc, bp->flags);
|
||||
g_free(bp);
|
||||
}
|
||||
|
||||
/* Remove all matching breakpoints. */
|
||||
@ -337,6 +341,7 @@ void cpu_single_step(CPUState *cpu, int enabled)
|
||||
/* XXX: only flush what is necessary */
|
||||
tb_flush(cpu);
|
||||
}
|
||||
trace_breakpoint_singlestep(cpu->cpu_index, enabled);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -145,6 +145,16 @@ void translator_loop(const TranslatorOps *ops, DisasContextBase *db,
|
||||
|
||||
void translator_loop_temp_check(DisasContextBase *db);
|
||||
|
||||
/**
|
||||
* translator_use_goto_tb
|
||||
* @db: Disassembly context
|
||||
* @dest: target pc of the goto
|
||||
*
|
||||
* Return true if goto_tb is allowed between the current TB
|
||||
* and the destination PC.
|
||||
*/
|
||||
bool translator_use_goto_tb(DisasContextBase *db, target_ulong dest);
|
||||
|
||||
/*
|
||||
* Translator Load Functions
|
||||
*
|
||||
|
@ -194,8 +194,7 @@ DEF(insn_start, 0, 0, TLADDR_ARGS * TARGET_INSN_START_WORDS,
|
||||
TCG_OPF_NOT_PRESENT)
|
||||
DEF(exit_tb, 0, 0, 1, TCG_OPF_BB_EXIT | TCG_OPF_BB_END)
|
||||
DEF(goto_tb, 0, 0, 1, TCG_OPF_BB_EXIT | TCG_OPF_BB_END)
|
||||
DEF(goto_ptr, 0, 1, 0,
|
||||
TCG_OPF_BB_EXIT | TCG_OPF_BB_END | IMPL(TCG_TARGET_HAS_goto_ptr))
|
||||
DEF(goto_ptr, 0, 1, 0, TCG_OPF_BB_EXIT | TCG_OPF_BB_END)
|
||||
|
||||
DEF(plugin_cb_start, 0, 0, 3, TCG_OPF_NOT_PRESENT)
|
||||
DEF(plugin_cb_end, 0, 0, 0, TCG_OPF_NOT_PRESENT)
|
||||
|
@ -579,8 +579,6 @@ struct TCGContext {
|
||||
/* Threshold to flush the translated code buffer. */
|
||||
void *code_gen_highwater;
|
||||
|
||||
size_t tb_phys_invalidate_count;
|
||||
|
||||
/* Track which vCPU triggers events */
|
||||
CPUState *cpu; /* *_trans */
|
||||
|
||||
@ -808,7 +806,6 @@ void *tcg_malloc_internal(TCGContext *s, int size);
|
||||
void tcg_pool_reset(TCGContext *s);
|
||||
TranslationBlock *tcg_tb_alloc(TCGContext *s);
|
||||
|
||||
void tb_destroy(TranslationBlock *tb);
|
||||
void tcg_region_reset_all(void);
|
||||
|
||||
size_t tcg_code_size(void);
|
||||
@ -816,7 +813,6 @@ size_t tcg_code_capacity(void);
|
||||
|
||||
void tcg_tb_insert(TranslationBlock *tb);
|
||||
void tcg_tb_remove(TranslationBlock *tb);
|
||||
size_t tcg_tb_phys_invalidate_count(void);
|
||||
TranslationBlock *tcg_tb_lookup(uintptr_t tc_ptr);
|
||||
void tcg_tb_foreach(GTraverseFunc func, gpointer user_data);
|
||||
size_t tcg_nb_tbs(void);
|
||||
|
@ -28,7 +28,6 @@
|
||||
#include "exec/cpu_ldst.h"
|
||||
#include "exec/helper-proto.h"
|
||||
#include "exec/helper-gen.h"
|
||||
#include "trace-tcg.h"
|
||||
#include "exec/translator.h"
|
||||
#include "exec/log.h"
|
||||
|
||||
@ -439,40 +438,9 @@ static DisasJumpType gen_store_conditional(DisasContext *ctx, int ra, int rb,
|
||||
return DISAS_NEXT;
|
||||
}
|
||||
|
||||
static bool in_superpage(DisasContext *ctx, int64_t addr)
|
||||
{
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
return ((ctx->tbflags & ENV_FLAG_PS_USER) == 0
|
||||
&& addr >> TARGET_VIRT_ADDR_SPACE_BITS == -1
|
||||
&& ((addr >> 41) & 3) == 2);
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool use_exit_tb(DisasContext *ctx)
|
||||
{
|
||||
return ((tb_cflags(ctx->base.tb) & CF_LAST_IO)
|
||||
|| ctx->base.singlestep_enabled
|
||||
|| singlestep);
|
||||
}
|
||||
|
||||
static bool use_goto_tb(DisasContext *ctx, uint64_t dest)
|
||||
{
|
||||
/* Suppress goto_tb in the case of single-steping and IO. */
|
||||
if (unlikely(use_exit_tb(ctx))) {
|
||||
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->base.tb->pc ^ dest) & TARGET_PAGE_MASK) == 0;
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
return translator_use_goto_tb(&ctx->base, dest);
|
||||
}
|
||||
|
||||
static DisasJumpType gen_bdirect(DisasContext *ctx, int ra, int32_t disp)
|
||||
@ -1271,7 +1239,7 @@ static DisasJumpType gen_call_pal(DisasContext *ctx, int palcode)
|
||||
need the page permissions check. We'll see the existence of
|
||||
the page when we create the TB, and we'll flush all TBs if
|
||||
we change the PAL base register. */
|
||||
if (!use_exit_tb(ctx)) {
|
||||
if (!ctx->base.singlestep_enabled) {
|
||||
tcg_gen_goto_tb(0);
|
||||
tcg_gen_movi_i64(cpu_pc, entry);
|
||||
tcg_gen_exit_tb(ctx->base.tb, 0);
|
||||
@ -3002,7 +2970,7 @@ static void alpha_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cpu)
|
||||
{
|
||||
DisasContext *ctx = container_of(dcbase, DisasContext, base);
|
||||
CPUAlphaState *env = cpu->env_ptr;
|
||||
int64_t bound, mask;
|
||||
int64_t bound;
|
||||
|
||||
ctx->tbflags = ctx->base.tb->flags;
|
||||
ctx->mem_idx = cpu_mmu_index(env, false);
|
||||
@ -3031,12 +2999,7 @@ static void alpha_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cpu)
|
||||
ctx->lit = NULL;
|
||||
|
||||
/* Bound the number of insns to execute to those left on the page. */
|
||||
if (in_superpage(ctx, ctx->base.pc_first)) {
|
||||
mask = -1ULL << 41;
|
||||
} else {
|
||||
mask = TARGET_PAGE_MASK;
|
||||
}
|
||||
bound = -(ctx->base.pc_first | mask) / 4;
|
||||
bound = -(ctx->base.pc_first | TARGET_PAGE_MASK) / 4;
|
||||
ctx->base.max_insns = MIN(ctx->base.max_insns, bound);
|
||||
}
|
||||
|
||||
@ -3095,7 +3058,7 @@ static void alpha_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
|
||||
tcg_gen_movi_i64(cpu_pc, ctx->base.pc_next);
|
||||
/* FALLTHRU */
|
||||
case DISAS_PC_UPDATED:
|
||||
if (!use_exit_tb(ctx)) {
|
||||
if (!ctx->base.singlestep_enabled) {
|
||||
tcg_gen_lookup_and_goto_ptr();
|
||||
break;
|
||||
}
|
||||
|
@ -35,7 +35,6 @@
|
||||
#include "exec/helper-gen.h"
|
||||
#include "exec/log.h"
|
||||
|
||||
#include "trace-tcg.h"
|
||||
#include "translate-a64.h"
|
||||
#include "qemu/atomic128.h"
|
||||
|
||||
@ -386,35 +385,20 @@ static void gen_step_complete_exception(DisasContext *s)
|
||||
s->base.is_jmp = DISAS_NORETURN;
|
||||
}
|
||||
|
||||
static inline bool use_goto_tb(DisasContext *s, int n, uint64_t dest)
|
||||
static inline bool use_goto_tb(DisasContext *s, uint64_t dest)
|
||||
{
|
||||
/* No direct tb linking with singlestep (either QEMU's or the ARM
|
||||
* debug architecture kind) or deterministic io
|
||||
*/
|
||||
if (s->base.singlestep_enabled || s->ss_active ||
|
||||
(tb_cflags(s->base.tb) & CF_LAST_IO)) {
|
||||
if (s->ss_active) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
/* Only link tbs from inside the same guest page */
|
||||
if ((s->base.tb->pc & TARGET_PAGE_MASK) != (dest & TARGET_PAGE_MASK)) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
return translator_use_goto_tb(&s->base, dest);
|
||||
}
|
||||
|
||||
static inline void gen_goto_tb(DisasContext *s, int n, uint64_t dest)
|
||||
{
|
||||
const TranslationBlock *tb;
|
||||
|
||||
tb = s->base.tb;
|
||||
if (use_goto_tb(s, n, dest)) {
|
||||
if (use_goto_tb(s, dest)) {
|
||||
tcg_gen_goto_tb(n);
|
||||
gen_a64_set_pc_im(dest);
|
||||
tcg_gen_exit_tb(tb, n);
|
||||
tcg_gen_exit_tb(s->base.tb, n);
|
||||
s->base.is_jmp = DISAS_NORETURN;
|
||||
} else {
|
||||
gen_a64_set_pc_im(dest);
|
||||
|
@ -30,7 +30,6 @@
|
||||
#include "exec/helper-proto.h"
|
||||
#include "exec/helper-gen.h"
|
||||
#include "exec/log.h"
|
||||
#include "trace-tcg.h"
|
||||
#include "translate-a64.h"
|
||||
#include "fpu/softfloat.h"
|
||||
|
||||
|
@ -34,7 +34,6 @@
|
||||
#include "exec/helper-proto.h"
|
||||
#include "exec/helper-gen.h"
|
||||
|
||||
#include "trace-tcg.h"
|
||||
#include "exec/log.h"
|
||||
|
||||
|
||||
@ -2579,16 +2578,6 @@ static int disas_dsp_insn(DisasContext *s, uint32_t insn)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline bool use_goto_tb(DisasContext *s, target_ulong dest)
|
||||
{
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
return (s->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) ||
|
||||
((s->base.pc_next - 1) & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void gen_goto_ptr(void)
|
||||
{
|
||||
tcg_gen_lookup_and_goto_ptr();
|
||||
@ -2600,7 +2589,7 @@ static void gen_goto_ptr(void)
|
||||
*/
|
||||
static void gen_goto_tb(DisasContext *s, int n, target_ulong dest)
|
||||
{
|
||||
if (use_goto_tb(s, dest)) {
|
||||
if (translator_use_goto_tb(&s->base, dest)) {
|
||||
tcg_gen_goto_tb(n);
|
||||
gen_set_pc_im(s, dest);
|
||||
tcg_gen_exit_tb(s->base.tb, n);
|
||||
@ -8905,7 +8894,7 @@ static bool trans_ISB(DisasContext *s, arg_ISB *a)
|
||||
* self-modifying code correctly and also to take
|
||||
* any pending interrupts immediately.
|
||||
*/
|
||||
gen_goto_tb(s, 0, s->base.pc_next);
|
||||
s->base.is_jmp = DISAS_TOO_MANY;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -8919,7 +8908,7 @@ static bool trans_SB(DisasContext *s, arg_SB *a)
|
||||
* for TCG; MB and end the TB instead.
|
||||
*/
|
||||
tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
|
||||
gen_goto_tb(s, 0, s->base.pc_next);
|
||||
s->base.is_jmp = DISAS_TOO_MANY;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -19,10 +19,10 @@
|
||||
*/
|
||||
|
||||
DEF_HELPER_1(wdr, void, env)
|
||||
DEF_HELPER_1(debug, void, env)
|
||||
DEF_HELPER_1(break, void, env)
|
||||
DEF_HELPER_1(sleep, void, env)
|
||||
DEF_HELPER_1(unsupported, void, env)
|
||||
DEF_HELPER_1(debug, noreturn, env)
|
||||
DEF_HELPER_1(break, noreturn, env)
|
||||
DEF_HELPER_1(sleep, noreturn, env)
|
||||
DEF_HELPER_1(unsupported, noreturn, env)
|
||||
DEF_HELPER_3(outb, void, env, i32, i32)
|
||||
DEF_HELPER_2(inb, tl, env, i32)
|
||||
DEF_HELPER_3(fullwr, void, env, i32, i32)
|
||||
|
@ -1083,14 +1083,17 @@ static void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
|
||||
{
|
||||
const TranslationBlock *tb = ctx->base.tb;
|
||||
|
||||
if (!ctx->base.singlestep_enabled) {
|
||||
if (translator_use_goto_tb(&ctx->base, dest)) {
|
||||
tcg_gen_goto_tb(n);
|
||||
tcg_gen_movi_i32(cpu_pc, dest);
|
||||
tcg_gen_exit_tb(tb, n);
|
||||
} else {
|
||||
tcg_gen_movi_i32(cpu_pc, dest);
|
||||
if (ctx->base.singlestep_enabled) {
|
||||
gen_helper_debug(cpu_env);
|
||||
tcg_gen_exit_tb(NULL, 0);
|
||||
} else {
|
||||
tcg_gen_lookup_and_goto_ptr();
|
||||
}
|
||||
}
|
||||
ctx->base.is_jmp = DISAS_NORETURN;
|
||||
}
|
||||
|
@ -37,7 +37,6 @@
|
||||
|
||||
#include "exec/helper-gen.h"
|
||||
|
||||
#include "trace-tcg.h"
|
||||
#include "exec/log.h"
|
||||
|
||||
|
||||
@ -482,7 +481,7 @@ static void t_gen_swapr(TCGv d, TCGv s)
|
||||
|
||||
static bool use_goto_tb(DisasContext *dc, target_ulong dest)
|
||||
{
|
||||
return ((dest ^ dc->base.pc_first) & TARGET_PAGE_MASK) == 0;
|
||||
return translator_use_goto_tb(&dc->base, dest);
|
||||
}
|
||||
|
||||
static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest)
|
||||
@ -3235,8 +3234,7 @@ static void cris_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
|
||||
* Use a conditional branch if either taken or not-taken path
|
||||
* can use goto_tb. If neither can, then treat it as indirect.
|
||||
*/
|
||||
if (likely(!dc->base.singlestep_enabled)
|
||||
&& likely(!dc->cpustate_changed)
|
||||
if (likely(!dc->cpustate_changed)
|
||||
&& (use_goto_tb(dc, dc->jmp_pc) || use_goto_tb(dc, npc))) {
|
||||
TCGLabel *not_taken = gen_new_label();
|
||||
|
||||
|
@ -27,7 +27,6 @@
|
||||
#include "exec/helper-proto.h"
|
||||
#include "exec/helper-gen.h"
|
||||
#include "exec/translator.h"
|
||||
#include "trace-tcg.h"
|
||||
#include "exec/log.h"
|
||||
|
||||
/* Since we have a distinction between register size and address size,
|
||||
@ -817,10 +816,7 @@ static bool gen_illegal(DisasContext *ctx)
|
||||
|
||||
static bool use_goto_tb(DisasContext *ctx, target_ureg dest)
|
||||
{
|
||||
/* Suppress goto_tb for page crossing, IO, or single-steping. */
|
||||
return !(((ctx->base.pc_first ^ dest) & TARGET_PAGE_MASK)
|
||||
|| (tb_cflags(ctx->base.tb) & CF_LAST_IO)
|
||||
|| ctx->base.singlestep_enabled);
|
||||
return translator_use_goto_tb(&ctx->base, dest);
|
||||
}
|
||||
|
||||
/* If the next insn is to be nullified, and it's on the same page,
|
||||
|
@ -210,7 +210,6 @@ void breakpoint_handler(CPUState *cs)
|
||||
{
|
||||
X86CPU *cpu = X86_CPU(cs);
|
||||
CPUX86State *env = &cpu->env;
|
||||
CPUBreakpoint *bp;
|
||||
|
||||
if (cs->watchpoint_hit) {
|
||||
if (cs->watchpoint_hit->flags & BP_CPU) {
|
||||
@ -222,15 +221,10 @@ void breakpoint_handler(CPUState *cs)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
|
||||
if (bp->pc == env->eip) {
|
||||
if (bp->flags & BP_CPU) {
|
||||
if (cpu_breakpoint_test(cs, env->eip, BP_CPU)) {
|
||||
check_hw_breakpoints(env, true);
|
||||
raise_exception(env, EXCP01_DB);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -30,7 +30,6 @@
|
||||
#include "exec/helper-gen.h"
|
||||
#include "helper-tcg.h"
|
||||
|
||||
#include "trace-tcg.h"
|
||||
#include "exec/log.h"
|
||||
|
||||
#define PREFIX_REPZ 0x01
|
||||
@ -2315,21 +2314,11 @@ static inline int insn_const_size(MemOp ot)
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool use_goto_tb(DisasContext *s, target_ulong pc)
|
||||
{
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
return (pc & TARGET_PAGE_MASK) == (s->base.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)
|
||||
static void gen_goto_tb(DisasContext *s, int tb_num, target_ulong eip)
|
||||
{
|
||||
target_ulong pc = s->cs_base + eip;
|
||||
|
||||
if (use_goto_tb(s, pc)) {
|
||||
if (translator_use_goto_tb(&s->base, pc)) {
|
||||
/* jump to same page: we can use a direct jump */
|
||||
tcg_gen_goto_tb(tb_num);
|
||||
gen_jmp_im(s, eip);
|
||||
|
@ -31,7 +31,6 @@
|
||||
#include "exec/helper-proto.h"
|
||||
#include "exec/helper-gen.h"
|
||||
|
||||
#include "trace-tcg.h"
|
||||
#include "exec/log.h"
|
||||
#include "fpu/softfloat.h"
|
||||
|
||||
@ -1520,16 +1519,6 @@ static void gen_exit_tb(DisasContext *s)
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
static inline bool use_goto_tb(DisasContext *s, uint32_t dest)
|
||||
{
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
return (s->base.pc_first & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)
|
||||
|| (s->base.pc_next & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Generate a jump to an immediate address. */
|
||||
static void gen_jmp_tb(DisasContext *s, int n, uint32_t dest)
|
||||
{
|
||||
@ -1537,7 +1526,7 @@ static void gen_jmp_tb(DisasContext *s, int n, uint32_t dest)
|
||||
update_cc_op(s);
|
||||
tcg_gen_movi_i32(QREG_PC, dest);
|
||||
gen_singlestep_exception(s);
|
||||
} else if (use_goto_tb(s, dest)) {
|
||||
} else if (translator_use_goto_tb(&s->base, dest)) {
|
||||
tcg_gen_goto_tb(n);
|
||||
tcg_gen_movi_i32(QREG_PC, dest);
|
||||
tcg_gen_exit_tb(s->base.tb, n);
|
||||
|
@ -29,7 +29,6 @@
|
||||
#include "exec/translator.h"
|
||||
#include "qemu/qemu-print.h"
|
||||
|
||||
#include "trace-tcg.h"
|
||||
#include "exec/log.h"
|
||||
|
||||
#define EXTRACT_FIELD(src, start, end) \
|
||||
@ -125,15 +124,6 @@ static void gen_raise_hw_excp(DisasContext *dc, uint32_t esr_ec)
|
||||
gen_raise_exception_sync(dc, EXCP_HW_EXCP);
|
||||
}
|
||||
|
||||
static inline bool use_goto_tb(DisasContext *dc, target_ulong dest)
|
||||
{
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
return (dc->base.pc_first & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest)
|
||||
{
|
||||
if (dc->base.singlestep_enabled) {
|
||||
@ -141,7 +131,7 @@ static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest)
|
||||
tcg_gen_movi_i32(cpu_pc, dest);
|
||||
gen_helper_raise_exception(cpu_env, tmp);
|
||||
tcg_temp_free_i32(tmp);
|
||||
} else if (use_goto_tb(dc, dest)) {
|
||||
} else if (translator_use_goto_tb(&dc->base, dest)) {
|
||||
tcg_gen_goto_tb(n);
|
||||
tcg_gen_movi_i32(cpu_pc, dest);
|
||||
tcg_gen_exit_tb(dc->base.tb, n);
|
||||
|
@ -32,7 +32,6 @@
|
||||
#include "semihosting/semihost.h"
|
||||
|
||||
#include "trace.h"
|
||||
#include "trace-tcg.h"
|
||||
#include "exec/translator.h"
|
||||
#include "exec/log.h"
|
||||
#include "qemu/qemu-print.h"
|
||||
@ -4948,22 +4947,9 @@ static void gen_trap(DisasContext *ctx, uint32_t opc,
|
||||
tcg_temp_free(t1);
|
||||
}
|
||||
|
||||
static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest)
|
||||
static void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
|
||||
{
|
||||
if (unlikely(ctx->base.singlestep_enabled)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
return (ctx->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
|
||||
{
|
||||
if (use_goto_tb(ctx, dest)) {
|
||||
if (translator_use_goto_tb(&ctx->base, dest)) {
|
||||
tcg_gen_goto_tb(n);
|
||||
gen_save_pc(dest);
|
||||
tcg_gen_exit_tb(ctx->base.tb, n);
|
||||
@ -4972,9 +4958,10 @@ static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
|
||||
if (ctx->base.singlestep_enabled) {
|
||||
save_cpu_state(ctx, 0);
|
||||
gen_helper_raise_exception_debug(cpu_env);
|
||||
}
|
||||
} else {
|
||||
tcg_gen_lookup_and_goto_ptr();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Branches (before delay slot) */
|
||||
|
@ -150,24 +150,11 @@ static void t_gen_helper_raise_exception(DisasContext *dc,
|
||||
dc->base.is_jmp = DISAS_NORETURN;
|
||||
}
|
||||
|
||||
static bool use_goto_tb(DisasContext *dc, uint32_t dest)
|
||||
{
|
||||
if (unlikely(dc->base.singlestep_enabled)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
return (dc->base.pc_first & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void gen_goto_tb(DisasContext *dc, int n, uint32_t dest)
|
||||
{
|
||||
const TranslationBlock *tb = dc->base.tb;
|
||||
|
||||
if (use_goto_tb(dc, dest)) {
|
||||
if (translator_use_goto_tb(&dc->base, dest)) {
|
||||
tcg_gen_goto_tb(n);
|
||||
tcg_gen_movi_tl(cpu_R[R_PC], dest);
|
||||
tcg_gen_exit_tb(tb, n);
|
||||
|
@ -33,7 +33,6 @@
|
||||
#include "exec/helper-gen.h"
|
||||
#include "exec/gen-icount.h"
|
||||
|
||||
#include "trace-tcg.h"
|
||||
#include "exec/log.h"
|
||||
|
||||
/* is_jmp field values */
|
||||
@ -1720,16 +1719,17 @@ static void openrisc_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
|
||||
/* fallthru */
|
||||
|
||||
case DISAS_TOO_MANY:
|
||||
if (unlikely(dc->base.singlestep_enabled)) {
|
||||
tcg_gen_movi_tl(cpu_pc, jmp_dest);
|
||||
gen_exception(dc, EXCP_DEBUG);
|
||||
} else if ((dc->base.pc_first ^ jmp_dest) & TARGET_PAGE_MASK) {
|
||||
tcg_gen_movi_tl(cpu_pc, jmp_dest);
|
||||
tcg_gen_lookup_and_goto_ptr();
|
||||
} else {
|
||||
if (translator_use_goto_tb(&dc->base, jmp_dest)) {
|
||||
tcg_gen_goto_tb(0);
|
||||
tcg_gen_movi_tl(cpu_pc, jmp_dest);
|
||||
tcg_gen_exit_tb(dc->base.tb, 0);
|
||||
break;
|
||||
}
|
||||
tcg_gen_movi_tl(cpu_pc, jmp_dest);
|
||||
if (unlikely(dc->base.singlestep_enabled)) {
|
||||
gen_exception(dc, EXCP_DEBUG);
|
||||
} else {
|
||||
tcg_gen_lookup_and_goto_ptr();
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -32,7 +32,6 @@
|
||||
#include "exec/helper-proto.h"
|
||||
#include "exec/helper-gen.h"
|
||||
|
||||
#include "trace-tcg.h"
|
||||
#include "exec/translator.h"
|
||||
#include "exec/log.h"
|
||||
#include "qemu/atomic128.h"
|
||||
@ -4302,15 +4301,7 @@ static inline void gen_update_cfar(DisasContext *ctx, target_ulong nip)
|
||||
|
||||
static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest)
|
||||
{
|
||||
if (unlikely(ctx->singlestep_enabled)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
return (ctx->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
return translator_use_goto_tb(&ctx->base, dest);
|
||||
}
|
||||
|
||||
static void gen_lookup_and_goto_ptr(DisasContext *ctx)
|
||||
|
@ -168,29 +168,11 @@ static void gen_exception_inst_addr_mis(DisasContext *ctx)
|
||||
generate_exception_mtval(ctx, RISCV_EXCP_INST_ADDR_MIS);
|
||||
}
|
||||
|
||||
static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest)
|
||||
{
|
||||
if (unlikely(ctx->base.singlestep_enabled)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
return (ctx->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
|
||||
{
|
||||
if (use_goto_tb(ctx, dest)) {
|
||||
/* chaining is only allowed when the jump is to the same page */
|
||||
if (translator_use_goto_tb(&ctx->base, dest)) {
|
||||
tcg_gen_goto_tb(n);
|
||||
tcg_gen_movi_tl(cpu_pc, dest);
|
||||
|
||||
/* No need to check for single stepping here as use_goto_tb() will
|
||||
* return false in case of single stepping.
|
||||
*/
|
||||
tcg_gen_exit_tb(ctx->base.tb, n);
|
||||
} else {
|
||||
tcg_gen_movi_tl(cpu_pc, dest);
|
||||
|
@ -26,7 +26,6 @@
|
||||
#include "exec/helper-proto.h"
|
||||
#include "exec/helper-gen.h"
|
||||
#include "exec/translator.h"
|
||||
#include "trace-tcg.h"
|
||||
#include "exec/log.h"
|
||||
|
||||
typedef struct DisasContext {
|
||||
@ -143,18 +142,9 @@ void rx_cpu_dump_state(CPUState *cs, FILE *f, int flags)
|
||||
}
|
||||
}
|
||||
|
||||
static bool use_goto_tb(DisasContext *dc, target_ulong dest)
|
||||
{
|
||||
if (unlikely(dc->base.singlestep_enabled)) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest)
|
||||
{
|
||||
if (use_goto_tb(dc, dest)) {
|
||||
if (translator_use_goto_tb(&dc->base, dest)) {
|
||||
tcg_gen_goto_tb(n);
|
||||
tcg_gen_movi_i32(cpu_pc, dest);
|
||||
tcg_gen_exit_tb(dc->base.tb, n);
|
||||
|
@ -42,7 +42,6 @@
|
||||
#include "exec/helper-proto.h"
|
||||
#include "exec/helper-gen.h"
|
||||
|
||||
#include "trace-tcg.h"
|
||||
#include "exec/translator.h"
|
||||
#include "exec/log.h"
|
||||
#include "qemu/atomic128.h"
|
||||
@ -685,24 +684,12 @@ static void gen_op_calc_cc(DisasContext *s)
|
||||
set_cc_static(s);
|
||||
}
|
||||
|
||||
static bool use_exit_tb(DisasContext *s)
|
||||
{
|
||||
return s->base.singlestep_enabled ||
|
||||
(tb_cflags(s->base.tb) & CF_LAST_IO) ||
|
||||
(s->base.tb->flags & FLAG_MASK_PER);
|
||||
}
|
||||
|
||||
static bool use_goto_tb(DisasContext *s, uint64_t dest)
|
||||
{
|
||||
if (unlikely(use_exit_tb(s))) {
|
||||
if (unlikely(s->base.tb->flags & FLAG_MASK_PER)) {
|
||||
return false;
|
||||
}
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
return (dest & TARGET_PAGE_MASK) == (s->base.tb->pc & TARGET_PAGE_MASK) ||
|
||||
(dest & TARGET_PAGE_MASK) == (s->base.pc_next & TARGET_PAGE_MASK);
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
return translator_use_goto_tb(&s->base, dest);
|
||||
}
|
||||
|
||||
static void account_noninline_branch(DisasContext *s, int cc_op)
|
||||
@ -6641,7 +6628,7 @@ static void s390x_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
|
||||
/* Exit the TB, either by raising a debug exception or by return. */
|
||||
if (dc->do_debug) {
|
||||
gen_exception(EXCP_DEBUG);
|
||||
} else if (use_exit_tb(dc) ||
|
||||
} else if ((dc->base.tb->flags & FLAG_MASK_PER) ||
|
||||
dc->base.is_jmp == DISAS_PC_STALE_NOCHAIN) {
|
||||
tcg_gen_exit_tb(NULL, 0);
|
||||
} else {
|
||||
|
@ -28,7 +28,6 @@
|
||||
#include "exec/helper-proto.h"
|
||||
#include "exec/helper-gen.h"
|
||||
#include "exec/translator.h"
|
||||
#include "trace-tcg.h"
|
||||
#include "exec/log.h"
|
||||
#include "qemu/qemu-print.h"
|
||||
|
||||
@ -225,17 +224,12 @@ static inline bool use_exit_tb(DisasContext *ctx)
|
||||
return (ctx->tbflags & GUSA_EXCLUSIVE) != 0;
|
||||
}
|
||||
|
||||
static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest)
|
||||
static bool use_goto_tb(DisasContext *ctx, target_ulong dest)
|
||||
{
|
||||
/* Use a direct jump if in same page and singlestep not enabled */
|
||||
if (unlikely(ctx->base.singlestep_enabled || use_exit_tb(ctx))) {
|
||||
if (use_exit_tb(ctx)) {
|
||||
return false;
|
||||
}
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
return (ctx->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
return translator_use_goto_tb(&ctx->base, dest);
|
||||
}
|
||||
|
||||
static void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
|
||||
|
@ -29,7 +29,6 @@
|
||||
|
||||
#include "exec/helper-gen.h"
|
||||
|
||||
#include "trace-tcg.h"
|
||||
#include "exec/translator.h"
|
||||
#include "exec/log.h"
|
||||
#include "asi.h"
|
||||
@ -339,22 +338,13 @@ static inline TCGv gen_dest_gpr(DisasContext *dc, int reg)
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool use_goto_tb(DisasContext *s, target_ulong pc,
|
||||
target_ulong npc)
|
||||
static bool use_goto_tb(DisasContext *s, target_ulong pc, target_ulong npc)
|
||||
{
|
||||
if (unlikely(s->base.singlestep_enabled || singlestep)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
return (pc & TARGET_PAGE_MASK) == (s->base.tb->pc & TARGET_PAGE_MASK) &&
|
||||
(npc & TARGET_PAGE_MASK) == (s->base.tb->pc & TARGET_PAGE_MASK);
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
return translator_use_goto_tb(&s->base, pc) &&
|
||||
translator_use_goto_tb(&s->base, npc);
|
||||
}
|
||||
|
||||
static inline void gen_goto_tb(DisasContext *s, int tb_num,
|
||||
static void gen_goto_tb(DisasContext *s, int tb_num,
|
||||
target_ulong pc, target_ulong npc)
|
||||
{
|
||||
if (use_goto_tb(s, pc, npc)) {
|
||||
|
@ -3225,19 +3225,6 @@ static inline void gen_save_pc(target_ulong pc)
|
||||
tcg_gen_movi_tl(cpu_PC, pc);
|
||||
}
|
||||
|
||||
static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest)
|
||||
{
|
||||
if (unlikely(ctx->base.singlestep_enabled)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
return (ctx->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void generate_qemu_excp(DisasContext *ctx, int excp)
|
||||
{
|
||||
TCGv_i32 tmp = tcg_const_i32(excp);
|
||||
@ -3246,9 +3233,9 @@ static void generate_qemu_excp(DisasContext *ctx, int excp)
|
||||
tcg_temp_free(tmp);
|
||||
}
|
||||
|
||||
static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
|
||||
static void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
|
||||
{
|
||||
if (use_goto_tb(ctx, dest)) {
|
||||
if (translator_use_goto_tb(&ctx->base, dest)) {
|
||||
tcg_gen_goto_tb(n);
|
||||
gen_save_pc(dest);
|
||||
tcg_gen_exit_tb(ctx->base.tb, n);
|
||||
@ -3256,8 +3243,9 @@ static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
|
||||
gen_save_pc(dest);
|
||||
if (ctx->base.singlestep_enabled) {
|
||||
generate_qemu_excp(ctx, EXCP_DEBUG);
|
||||
} else {
|
||||
tcg_gen_lookup_and_goto_ptr();
|
||||
}
|
||||
tcg_gen_exit_tb(NULL, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -43,7 +43,6 @@
|
||||
#include "exec/helper-proto.h"
|
||||
#include "exec/helper-gen.h"
|
||||
|
||||
#include "trace-tcg.h"
|
||||
#include "exec/log.h"
|
||||
|
||||
|
||||
@ -406,11 +405,7 @@ static void gen_jump(DisasContext *dc, TCGv dest)
|
||||
|
||||
static int adjust_jump_slot(DisasContext *dc, uint32_t dest, int slot)
|
||||
{
|
||||
if (((dc->base.pc_first ^ dest) & TARGET_PAGE_MASK) != 0) {
|
||||
return -1;
|
||||
} else {
|
||||
return slot;
|
||||
}
|
||||
return translator_use_goto_tb(&dc->base, dest) ? slot : -1;
|
||||
}
|
||||
|
||||
static void gen_jumpi(DisasContext *dc, uint32_t dest, int slot)
|
||||
|
@ -88,7 +88,6 @@ typedef enum {
|
||||
#define TCG_TARGET_HAS_mulsh_i32 0
|
||||
#define TCG_TARGET_HAS_extrl_i64_i32 0
|
||||
#define TCG_TARGET_HAS_extrh_i64_i32 0
|
||||
#define TCG_TARGET_HAS_goto_ptr 1
|
||||
#define TCG_TARGET_HAS_qemu_st8_i32 0
|
||||
|
||||
#define TCG_TARGET_HAS_div_i64 1
|
||||
|
@ -148,7 +148,6 @@ extern bool use_neon_instructions;
|
||||
#define TCG_TARGET_HAS_mulsh_i32 0
|
||||
#define TCG_TARGET_HAS_div_i32 use_idiv_instructions
|
||||
#define TCG_TARGET_HAS_rem_i32 0
|
||||
#define TCG_TARGET_HAS_goto_ptr 1
|
||||
#define TCG_TARGET_HAS_direct_jump 0
|
||||
#define TCG_TARGET_HAS_qemu_st8_i32 0
|
||||
|
||||
|
@ -135,7 +135,6 @@ extern bool have_movbe;
|
||||
#define TCG_TARGET_HAS_muls2_i32 1
|
||||
#define TCG_TARGET_HAS_muluh_i32 0
|
||||
#define TCG_TARGET_HAS_mulsh_i32 0
|
||||
#define TCG_TARGET_HAS_goto_ptr 1
|
||||
#define TCG_TARGET_HAS_direct_jump 1
|
||||
|
||||
#if TCG_TARGET_REG_BITS == 64
|
||||
|
@ -136,7 +136,6 @@ extern bool use_mips32r2_instructions;
|
||||
#define TCG_TARGET_HAS_muluh_i32 1
|
||||
#define TCG_TARGET_HAS_mulsh_i32 1
|
||||
#define TCG_TARGET_HAS_bswap32_i32 1
|
||||
#define TCG_TARGET_HAS_goto_ptr 1
|
||||
#define TCG_TARGET_HAS_direct_jump 1
|
||||
|
||||
#if TCG_TARGET_REG_BITS == 64
|
||||
|
@ -108,7 +108,6 @@ extern bool have_vsx;
|
||||
#define TCG_TARGET_HAS_muls2_i32 0
|
||||
#define TCG_TARGET_HAS_muluh_i32 1
|
||||
#define TCG_TARGET_HAS_mulsh_i32 1
|
||||
#define TCG_TARGET_HAS_goto_ptr 1
|
||||
#define TCG_TARGET_HAS_direct_jump 1
|
||||
#define TCG_TARGET_HAS_qemu_st8_i32 0
|
||||
|
||||
|
33
tcg/region.c
33
tcg/region.c
@ -112,7 +112,7 @@ static int ptr_cmp_tb_tc(const void *ptr, const struct tb_tc *s)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static gint tb_tc_cmp(gconstpointer ap, gconstpointer bp)
|
||||
static gint tb_tc_cmp(gconstpointer ap, gconstpointer bp, gpointer userdata)
|
||||
{
|
||||
const struct tb_tc *a = ap;
|
||||
const struct tb_tc *b = bp;
|
||||
@ -143,6 +143,12 @@ static gint tb_tc_cmp(gconstpointer ap, gconstpointer bp)
|
||||
return ptr_cmp_tb_tc(b->ptr, a);
|
||||
}
|
||||
|
||||
static void tb_destroy(gpointer value)
|
||||
{
|
||||
TranslationBlock *tb = value;
|
||||
qemu_spin_destroy(&tb->jmp_lock);
|
||||
}
|
||||
|
||||
static void tcg_region_trees_init(void)
|
||||
{
|
||||
size_t i;
|
||||
@ -153,7 +159,7 @@ static void tcg_region_trees_init(void)
|
||||
struct tcg_region_tree *rt = region_trees + i * tree_size;
|
||||
|
||||
qemu_mutex_init(&rt->lock);
|
||||
rt->tree = g_tree_new(tb_tc_cmp);
|
||||
rt->tree = g_tree_new_full(tb_tc_cmp, NULL, NULL, tb_destroy);
|
||||
}
|
||||
}
|
||||
|
||||
@ -277,14 +283,6 @@ size_t tcg_nb_tbs(void)
|
||||
return nb_tbs;
|
||||
}
|
||||
|
||||
static gboolean tcg_region_tree_traverse(gpointer k, gpointer v, gpointer data)
|
||||
{
|
||||
TranslationBlock *tb = v;
|
||||
|
||||
tb_destroy(tb);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void tcg_region_tree_reset_all(void)
|
||||
{
|
||||
size_t i;
|
||||
@ -293,7 +291,6 @@ static void tcg_region_tree_reset_all(void)
|
||||
for (i = 0; i < region.n; i++) {
|
||||
struct tcg_region_tree *rt = region_trees + i * tree_size;
|
||||
|
||||
g_tree_foreach(rt->tree, tcg_region_tree_traverse, NULL);
|
||||
/* Increment the refcount first so that destroy acts as a reset */
|
||||
g_tree_ref(rt->tree);
|
||||
g_tree_destroy(rt->tree);
|
||||
@ -983,17 +980,3 @@ size_t tcg_code_capacity(void)
|
||||
|
||||
return capacity;
|
||||
}
|
||||
|
||||
size_t tcg_tb_phys_invalidate_count(void)
|
||||
{
|
||||
unsigned int n_ctxs = qatomic_read(&tcg_cur_ctxs);
|
||||
unsigned int i;
|
||||
size_t total = 0;
|
||||
|
||||
for (i = 0; i < n_ctxs; i++) {
|
||||
const TCGContext *s = qatomic_read(&tcg_ctxs[i]);
|
||||
|
||||
total += qatomic_read(&s->tb_phys_invalidate_count);
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
@ -85,7 +85,6 @@ typedef enum {
|
||||
#define TCG_TARGET_CALL_STACK_OFFSET 0
|
||||
|
||||
/* optional instructions */
|
||||
#define TCG_TARGET_HAS_goto_ptr 1
|
||||
#define TCG_TARGET_HAS_movcond_i32 0
|
||||
#define TCG_TARGET_HAS_div_i32 1
|
||||
#define TCG_TARGET_HAS_rem_i32 1
|
||||
|
@ -98,7 +98,6 @@ extern uint64_t s390_facilities;
|
||||
#define TCG_TARGET_HAS_mulsh_i32 0
|
||||
#define TCG_TARGET_HAS_extrl_i64_i32 0
|
||||
#define TCG_TARGET_HAS_extrh_i64_i32 0
|
||||
#define TCG_TARGET_HAS_goto_ptr 1
|
||||
#define TCG_TARGET_HAS_direct_jump (s390_facilities & FACILITY_GEN_INST_EXT)
|
||||
#define TCG_TARGET_HAS_qemu_st8_i32 0
|
||||
|
||||
|
@ -121,7 +121,6 @@ extern bool use_vis3_instructions;
|
||||
#define TCG_TARGET_HAS_muls2_i32 1
|
||||
#define TCG_TARGET_HAS_muluh_i32 0
|
||||
#define TCG_TARGET_HAS_mulsh_i32 0
|
||||
#define TCG_TARGET_HAS_goto_ptr 1
|
||||
#define TCG_TARGET_HAS_direct_jump 1
|
||||
#define TCG_TARGET_HAS_qemu_st8_i32 0
|
||||
|
||||
|
@ -2754,7 +2754,7 @@ void tcg_gen_goto_tb(unsigned idx)
|
||||
|
||||
void tcg_gen_lookup_and_goto_ptr(void)
|
||||
{
|
||||
if (TCG_TARGET_HAS_goto_ptr && !qemu_loglevel_mask(CPU_LOG_TB_NOCHAIN)) {
|
||||
if (!qemu_loglevel_mask(CPU_LOG_TB_NOCHAIN)) {
|
||||
TCGv_ptr ptr;
|
||||
|
||||
plugin_gen_disable_mem_helpers();
|
||||
|
12
tcg/tcg.c
12
tcg/tcg.c
@ -752,8 +752,6 @@ void tcg_prologue_init(TCGContext *s)
|
||||
(uintptr_t)s->code_buf, prologue_size);
|
||||
#endif
|
||||
|
||||
tcg_region_prologue_set(s);
|
||||
|
||||
#ifdef DEBUG_DISAS
|
||||
if (qemu_loglevel_mask(CPU_LOG_TB_OUT_ASM)) {
|
||||
FILE *logfile = qemu_log_lock();
|
||||
@ -791,10 +789,10 @@ void tcg_prologue_init(TCGContext *s)
|
||||
* For tci, we use NULL as the signal to return from the interpreter,
|
||||
* so skip this check.
|
||||
*/
|
||||
if (TCG_TARGET_HAS_goto_ptr) {
|
||||
tcg_debug_assert(tcg_code_gen_epilogue != NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
tcg_region_prologue_set(s);
|
||||
}
|
||||
|
||||
void tcg_func_start(TCGContext *s)
|
||||
@ -1176,6 +1174,7 @@ bool tcg_op_supported(TCGOpcode op)
|
||||
case INDEX_op_insn_start:
|
||||
case INDEX_op_exit_tb:
|
||||
case INDEX_op_goto_tb:
|
||||
case INDEX_op_goto_ptr:
|
||||
case INDEX_op_qemu_ld_i32:
|
||||
case INDEX_op_qemu_st_i32:
|
||||
case INDEX_op_qemu_ld_i64:
|
||||
@ -1185,9 +1184,6 @@ bool tcg_op_supported(TCGOpcode op)
|
||||
case INDEX_op_qemu_st8_i32:
|
||||
return TCG_TARGET_HAS_qemu_st8_i32;
|
||||
|
||||
case INDEX_op_goto_ptr:
|
||||
return TCG_TARGET_HAS_goto_ptr;
|
||||
|
||||
case INDEX_op_mov_i32:
|
||||
case INDEX_op_setcond_i32:
|
||||
case INDEX_op_brcond_i32:
|
||||
@ -1849,7 +1845,7 @@ static void tcg_dump_ops(TCGContext *s, bool have_prefs)
|
||||
col += qemu_log("plugin(%p)", func);
|
||||
}
|
||||
|
||||
col += qemu_log("$0x%x,$%d", info->flags, nb_oargs);
|
||||
col += qemu_log(",$0x%x,$%d", info->flags, nb_oargs);
|
||||
for (i = 0; i < nb_oargs; i++) {
|
||||
col += qemu_log(",%s", tcg_get_arg_str(s, buf, sizeof(buf),
|
||||
op->args[i]));
|
||||
|
@ -87,7 +87,6 @@
|
||||
#define TCG_TARGET_HAS_muls2_i32 1
|
||||
#define TCG_TARGET_HAS_muluh_i32 0
|
||||
#define TCG_TARGET_HAS_mulsh_i32 0
|
||||
#define TCG_TARGET_HAS_goto_ptr 1
|
||||
#define TCG_TARGET_HAS_direct_jump 0
|
||||
#define TCG_TARGET_HAS_qemu_st8_i32 0
|
||||
|
||||
|
@ -25,6 +25,11 @@
|
||||
#
|
||||
# The <format-string> should be a sprintf()-compatible format string.
|
||||
|
||||
# cpu.c
|
||||
breakpoint_insert(int cpu_index, uint64_t pc, int flags) "cpu=%d pc=0x%" PRIx64 " flags=0x%x"
|
||||
breakpoint_remove(int cpu_index, uint64_t pc, int flags) "cpu=%d pc=0x%" PRIx64 " flags=0x%x"
|
||||
breakpoint_singlestep(int cpu_index, int enabled) "cpu=%d enable=%d"
|
||||
|
||||
# dma-helpers.c
|
||||
dma_blk_io(void *dbs, void *bs, int64_t offset, bool to_dev) "dbs=%p bs=%p offset=%" PRId64 " to_dev=%d"
|
||||
dma_aio_cancel(void *dbs) "dbs=%p"
|
||||
|
Loading…
Reference in New Issue
Block a user