aboutsummaryrefslogtreecommitdiff
path: root/accel/tcg/cpu-exec.c
diff options
context:
space:
mode:
Diffstat (limited to 'accel/tcg/cpu-exec.c')
-rw-r--r--accel/tcg/cpu-exec.c112
1 files changed, 89 insertions, 23 deletions
diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c
index ad1279d2ed..e22bcb99f7 100644
--- a/accel/tcg/cpu-exec.c
+++ b/accel/tcg/cpu-exec.c
@@ -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);