aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2015-10-08 15:33:56 +0100
committerPeter Maydell <peter.maydell@linaro.org>2015-10-08 15:33:56 +0100
commit31c9bd164ddb653915b9029ba0edd40cd57530d9 (patch)
treea89ce755264cd0d9f97dcf4c8aae5df524034fd3
parentca4e4b82848982311a40d0937c1de9db1108fdb0 (diff)
parent126d89e8cdfa3be15d51f76906eaccbcd0023f98 (diff)
downloadqemu-arm-31c9bd164ddb653915b9029ba0edd40cd57530d9.tar.gz
Merge remote-tracking branch 'remotes/rth/tags/pull-tcg-20151007' into staging
Do away with TB retranslation # gpg: Signature made Wed 07 Oct 2015 10:42:08 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-20151007: (26 commits) tcg: Adjust CODE_GEN_AVG_BLOCK_SIZE tcg: Check for overflow via highwater mark tcg: Allocate a guard page after code_gen_buffer tcg: Emit prologue to the beginning of code_gen_buffer tcg: Remove tcg_gen_code_search_pc tcg: Remove gen_intermediate_code_pc tcg: Save insn data and use it in cpu_restore_state_from_tb tcg: Pass data argument to restore_state_to_opc tcg: Add TCG_MAX_INSNS target-*: Drop cpu_gen_code define tcg: Merge cpu_gen_code into tb_gen_code target-sparc: Add npc state to insn_start target-sparc: Remove gen_opc_jump_pc target-sparc: Split out gen_branch_n target-sparc: Tidy gen_branch_a interface target-cris: Mirror gen_opc_pc into insn_start target-sh4: Add flags state to insn_start target-s390x: Add cc_op state to insn_start target-mips: Add delayed branch state to insn_start target-i386: Add cc_op state to insn_start ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r--include/exec/exec-all.h23
-rw-r--r--include/qom/cpu.h16
-rw-r--r--target-alpha/cpu.h1
-rw-r--r--target-alpha/translate.c70
-rw-r--r--target-arm/cpu.h2
-rw-r--r--target-arm/translate-a64.c48
-rw-r--r--target-arm/translate.c83
-rw-r--r--target-arm/translate.h8
-rw-r--r--target-cris/cpu.h1
-rw-r--r--target-cris/translate.c93
-rw-r--r--target-cris/translate_v10.c3
-rw-r--r--target-i386/cpu.h2
-rw-r--r--target-i386/translate.c106
-rw-r--r--target-lm32/cpu.h1
-rw-r--r--target-lm32/translate.c83
-rw-r--r--target-m68k/cpu.h1
-rw-r--r--target-m68k/translate.c82
-rw-r--r--target-microblaze/cpu.h1
-rw-r--r--target-microblaze/translate.c83
-rw-r--r--target-mips/cpu.h2
-rw-r--r--target-mips/translate.c98
-rw-r--r--target-moxie/cpu.h1
-rw-r--r--target-moxie/translate.c82
-rw-r--r--target-openrisc/cpu.h1
-rw-r--r--target-openrisc/translate.c78
-rw-r--r--target-ppc/cpu.h1
-rw-r--r--target-ppc/translate.c72
-rw-r--r--target-s390x/cpu.h2
-rw-r--r--target-s390x/translate.c78
-rw-r--r--target-sh4/cpu.h2
-rw-r--r--target-sh4/translate.c91
-rw-r--r--target-sparc/cpu.h2
-rw-r--r--target-sparc/translate.c185
-rw-r--r--target-tilegx/cpu.h1
-rw-r--r--target-tilegx/translate.c58
-rw-r--r--target-tricore/translate.c59
-rw-r--r--target-unicore32/translate.c83
-rw-r--r--target-xtensa/cpu.h1
-rw-r--r--target-xtensa/translate.c79
-rw-r--r--tcg/tcg-op.h52
-rw-r--r--tcg/tcg-opc.h4
-rw-r--r--tcg/tcg.c168
-rw-r--r--tcg/tcg.h20
-rw-r--r--tci.c9
-rw-r--r--translate-all.c520
45 files changed, 964 insertions, 1492 deletions
diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
index a3719b7f0d..a63fd6015e 100644
--- a/include/exec/exec-all.h
+++ b/include/exec/exec-all.h
@@ -62,24 +62,15 @@ typedef struct TranslationBlock TranslationBlock;
#define OPC_BUF_SIZE 640
#define OPC_MAX_SIZE (OPC_BUF_SIZE - MAX_OP_PER_INSTR)
-/* Maximum size a TCG op can expand to. This is complicated because a
- single op may require several host instructions and register reloads.
- For now take a wild guess at 192 bytes, which should allow at least
- a couple of fixup instructions per argument. */
-#define TCG_MAX_OP_SIZE 192
-
#define OPPARAM_BUF_SIZE (OPC_BUF_SIZE * MAX_OPC_PARAM)
#include "qemu/log.h"
void gen_intermediate_code(CPUArchState *env, struct TranslationBlock *tb);
-void gen_intermediate_code_pc(CPUArchState *env, struct TranslationBlock *tb);
void restore_state_to_opc(CPUArchState *env, struct TranslationBlock *tb,
- int pc_pos);
+ target_ulong *data);
void cpu_gen_init(void);
-int cpu_gen_code(CPUArchState *env, struct TranslationBlock *tb,
- int *gen_code_size_ptr);
bool cpu_restore_state(CPUState *cpu, uintptr_t searched_pc);
void page_size_init(void);
@@ -170,13 +161,14 @@ static inline void tlb_flush_by_mmuidx(CPUState *cpu, ...)
#define CODE_GEN_PHYS_HASH_BITS 15
#define CODE_GEN_PHYS_HASH_SIZE (1 << CODE_GEN_PHYS_HASH_BITS)
-/* estimated block size for TB allocation */
-/* XXX: use a per code average code fragment size and modulate it
- according to the host CPU */
+/* Estimated block size for TB allocation. */
+/* ??? The following is based on a 2015 survey of x86_64 host output.
+ Better would seem to be some sort of dynamically sized TB array,
+ adapting to the block sizes actually being produced. */
#if defined(CONFIG_SOFTMMU)
-#define CODE_GEN_AVG_BLOCK_SIZE 128
+#define CODE_GEN_AVG_BLOCK_SIZE 400
#else
-#define CODE_GEN_AVG_BLOCK_SIZE 64
+#define CODE_GEN_AVG_BLOCK_SIZE 150
#endif
#if defined(__arm__) || defined(_ARCH_PPC) \
@@ -201,6 +193,7 @@ struct TranslationBlock {
#define CF_USE_ICOUNT 0x20000
void *tc_ptr; /* pointer to the translated code */
+ uint8_t *tc_search; /* pointer to search data */
/* next matching tb for physical address. */
struct TranslationBlock *phys_hash_next;
/* original tb when cflags has CF_NOCACHE */
diff --git a/include/qom/cpu.h b/include/qom/cpu.h
index 9405554a2b..b613ff0329 100644
--- a/include/qom/cpu.h
+++ b/include/qom/cpu.h
@@ -721,6 +721,7 @@ void cpu_single_step(CPUState *cpu, int enabled);
/* 0x08 currently unused */
#define BP_GDB 0x10
#define BP_CPU 0x20
+#define BP_ANY (BP_GDB | BP_CPU)
#define BP_WATCHPOINT_HIT_READ 0x40
#define BP_WATCHPOINT_HIT_WRITE 0x80
#define BP_WATCHPOINT_HIT (BP_WATCHPOINT_HIT_READ | BP_WATCHPOINT_HIT_WRITE)
@@ -731,6 +732,21 @@ int cpu_breakpoint_remove(CPUState *cpu, vaddr pc, int flags);
void cpu_breakpoint_remove_by_ref(CPUState *cpu, CPUBreakpoint *breakpoint);
void cpu_breakpoint_remove_all(CPUState *cpu, int mask);
+/* Return true if PC matches an installed breakpoint. */
+static inline bool cpu_breakpoint_test(CPUState *cpu, vaddr pc, int mask)
+{
+ CPUBreakpoint *bp;
+
+ if (unlikely(!QTAILQ_EMPTY(&cpu->breakpoints))) {
+ QTAILQ_FOREACH(bp, &cpu->breakpoints, entry) {
+ if (bp->pc == pc && (bp->flags & mask)) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
int cpu_watchpoint_insert(CPUState *cpu, vaddr addr, vaddr len,
int flags, CPUWatchpoint **watchpoint);
int cpu_watchpoint_remove(CPUState *cpu, vaddr addr,
diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h
index 097637eb4e..bcd8076abb 100644
--- a/target-alpha/cpu.h
+++ b/target-alpha/cpu.h
@@ -287,7 +287,6 @@ struct CPUAlphaState {
#define cpu_list alpha_cpu_list
#define cpu_exec cpu_alpha_exec
-#define cpu_gen_code cpu_alpha_gen_code
#define cpu_signal_handler cpu_alpha_signal_handler
#include "exec/cpu-all.h"
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index 2ba5fb80ae..f936d1b5b9 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -2858,18 +2858,14 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
return ret;
}
-static inline void gen_intermediate_code_internal(AlphaCPU *cpu,
- TranslationBlock *tb,
- bool search_pc)
+void gen_intermediate_code(CPUAlphaState *env, struct TranslationBlock *tb)
{
+ AlphaCPU *cpu = alpha_env_get_cpu(env);
CPUState *cs = CPU(cpu);
- CPUAlphaState *env = &cpu->env;
DisasContext ctx, *ctxp = &ctx;
target_ulong pc_start;
target_ulong pc_mask;
uint32_t insn;
- CPUBreakpoint *bp;
- int j, lj = -1;
ExitStatus ret;
int num_insns;
int max_insns;
@@ -2904,6 +2900,9 @@ static inline void gen_intermediate_code_internal(AlphaCPU *cpu,
if (max_insns == 0) {
max_insns = CF_COUNT_MASK;
}
+ if (max_insns > TCG_MAX_INSNS) {
+ max_insns = TCG_MAX_INSNS;
+ }
if (in_superpage(&ctx, pc_start)) {
pc_mask = (1ULL << 41) - 1;
@@ -2913,35 +2912,17 @@ static inline void gen_intermediate_code_internal(AlphaCPU *cpu,
gen_tb_start(tb);
do {
- if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
- QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
- if (bp->pc == ctx.pc) {
- gen_excp(&ctx, EXCP_DEBUG, 0);
- break;
- }
- }
- }
- if (search_pc) {
- j = tcg_op_buf_count();
- if (lj < j) {
- lj++;
- while (lj < j) {
- tcg_ctx.gen_opc_instr_start[lj++] = 0;
- }
- }
- tcg_ctx.gen_opc_pc[lj] = ctx.pc;
- tcg_ctx.gen_opc_instr_start[lj] = 1;
- tcg_ctx.gen_opc_icount[lj] = num_insns;
+ tcg_gen_insn_start(ctx.pc);
+ num_insns++;
+
+ if (unlikely(cpu_breakpoint_test(cs, ctx.pc, BP_ANY))) {
+ gen_excp(&ctx, EXCP_DEBUG, 0);
+ break;
}
- if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) {
+ if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
gen_io_start();
}
insn = cpu_ldl_code(env, ctx.pc);
- num_insns++;
-
- if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
- tcg_gen_debug_insn_start(ctx.pc);
- }
TCGV_UNUSED_I64(ctx.zero);
TCGV_UNUSED_I64(ctx.sink);
@@ -2997,16 +2978,8 @@ static inline void gen_intermediate_code_internal(AlphaCPU *cpu,
gen_tb_end(tb, num_insns);
- if (search_pc) {
- j = tcg_op_buf_count();
- lj++;
- while (lj <= j) {
- tcg_ctx.gen_opc_instr_start[lj++] = 0;
- }
- } else {
- tb->size = ctx.pc - pc_start;
- tb->icount = num_insns;
- }
+ tb->size = ctx.pc - pc_start;
+ tb->icount = num_insns;
#ifdef DEBUG_DISAS
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
@@ -3017,17 +2990,8 @@ static inline void gen_intermediate_code_internal(AlphaCPU *cpu,
#endif
}
-void gen_intermediate_code (CPUAlphaState *env, struct TranslationBlock *tb)
-{
- gen_intermediate_code_internal(alpha_env_get_cpu(env), tb, false);
-}
-
-void gen_intermediate_code_pc (CPUAlphaState *env, struct TranslationBlock *tb)
-{
- gen_intermediate_code_internal(alpha_env_get_cpu(env), tb, true);
-}
-
-void restore_state_to_opc(CPUAlphaState *env, TranslationBlock *tb, int pc_pos)
+void restore_state_to_opc(CPUAlphaState *env, TranslationBlock *tb,
+ target_ulong *data)
{
- env->pc = tcg_ctx.gen_opc_pc[pc_pos];
+ env->pc = data[0];
}
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index cc1578c9e8..493f9d02a9 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -95,6 +95,7 @@
struct arm_boot_info;
#define NB_MMU_MODES 7
+#define TARGET_INSN_START_EXTRA_WORDS 1
/* We currently assume float and double are IEEE single and double
precision respectively.
@@ -1600,7 +1601,6 @@ static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx,
#define cpu_init(cpu_model) CPU(cpu_arm_init(cpu_model))
#define cpu_exec cpu_arm_exec
-#define cpu_gen_code cpu_arm_gen_code
#define cpu_signal_handler cpu_arm_signal_handler
#define cpu_list arm_cpu_list
diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c
index ec0936cf97..e65e309535 100644
--- a/target-arm/translate-a64.c
+++ b/target-arm/translate-a64.c
@@ -11000,15 +11000,11 @@ static void disas_a64_insn(CPUARMState *env, DisasContext *s)
free_tmp_a64(s);
}
-void gen_intermediate_code_internal_a64(ARMCPU *cpu,
- TranslationBlock *tb,
- bool search_pc)
+void gen_intermediate_code_a64(ARMCPU *cpu, TranslationBlock *tb)
{
CPUState *cs = CPU(cpu);
CPUARMState *env = &cpu->env;
DisasContext dc1, *dc = &dc1;
- CPUBreakpoint *bp;
- int j, lj;
target_ulong pc_start;
target_ulong next_page_start;
int num_insns;
@@ -11067,19 +11063,25 @@ void gen_intermediate_code_internal_a64(ARMCPU *cpu,
init_tmp_a64_array(dc);
next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
- lj = -1;
num_insns = 0;
max_insns = tb->cflags & CF_COUNT_MASK;
if (max_insns == 0) {
max_insns = CF_COUNT_MASK;
}
+ if (max_insns > TCG_MAX_INSNS) {
+ max_insns = TCG_MAX_INSNS;
+ }
gen_tb_start(tb);
tcg_clear_temp_count();
do {
+ tcg_gen_insn_start(dc->pc, 0);
+ num_insns++;
+
if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
+ CPUBreakpoint *bp;
QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
if (bp->pc == dc->pc) {
gen_exception_internal_insn(dc, 0, EXCP_DEBUG);
@@ -11091,27 +11093,10 @@ void gen_intermediate_code_internal_a64(ARMCPU *cpu,
}
}
- if (search_pc) {
- j = tcg_op_buf_count();
- if (lj < j) {
- lj++;
- while (lj < j) {
- tcg_ctx.gen_opc_instr_start[lj++] = 0;
- }
- }
- tcg_ctx.gen_opc_pc[lj] = dc->pc;
- tcg_ctx.gen_opc_instr_start[lj] = 1;
- tcg_ctx.gen_opc_icount[lj] = num_insns;
- }
-
- if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) {
+ if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
gen_io_start();
}
- if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
- tcg_gen_debug_insn_start(dc->pc);
- }
-
if (dc->ss_active && !dc->pstate_ss) {
/* Singlestep state is Active-pending.
* If we're in this state at the start of a TB then either
@@ -11123,7 +11108,7 @@ void gen_intermediate_code_internal_a64(ARMCPU *cpu,
* "did not step an insn" case, and so the syndrome ISV and EX
* bits should be zero.
*/
- assert(num_insns == 0);
+ assert(num_insns == 1);
gen_exception(EXCP_UDEF, syn_swstep(dc->ss_same_el, 0, 0),
default_exception_el(dc));
dc->is_jmp = DISAS_EXC;
@@ -11142,7 +11127,6 @@ void gen_intermediate_code_internal_a64(ARMCPU *cpu,
* Also stop translation when a page boundary is reached. This
* ensures prefetch aborts occur at the right place.
*/
- num_insns++;
} while (!dc->is_jmp && !tcg_op_buf_full() &&
!cs->singlestep_enabled &&
!singlestep &&
@@ -11221,14 +11205,6 @@ done_generating:
qemu_log("\n");
}
#endif
- if (search_pc) {
- j = tcg_op_buf_count();
- lj++;
- while (lj <= j) {
- tcg_ctx.gen_opc_instr_start[lj++] = 0;
- }
- } else {
- tb->size = dc->pc - pc_start;
- tb->icount = num_insns;
- }
+ tb->size = dc->pc - pc_start;
+ tb->icount = num_insns;
}
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 84a21ace54..22c35877e5 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -52,7 +52,6 @@
#define ARCH(x) do { if (!ENABLE_ARCH_##x) goto illegal_op; } while(0)
#include "translate.h"
-static uint32_t gen_opc_condexec_bits[OPC_BUF_SIZE];
#if defined(CONFIG_USER_ONLY)
#define IS_USER(s) 1
@@ -11168,17 +11167,12 @@ undef:
}
/* generate intermediate code in gen_opc_buf and gen_opparam_buf for
- basic block 'tb'. If search_pc is TRUE, also generate PC
- information for each intermediate instruction. */
-static inline void gen_intermediate_code_internal(ARMCPU *cpu,
- TranslationBlock *tb,
- bool search_pc)
+ basic block 'tb'. */
+void gen_intermediate_code(CPUARMState *env, TranslationBlock *tb)
{
+ ARMCPU *cpu = arm_env_get_cpu(env);
CPUState *cs = CPU(cpu);
- CPUARMState *env = &cpu->env;
DisasContext dc1, *dc = &dc1;
- CPUBreakpoint *bp;
- int j, lj;
target_ulong pc_start;
target_ulong next_page_start;
int num_insns;
@@ -11190,7 +11184,7 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu,
* the A32/T32 complexity to do with conditional execution/IT blocks/etc.
*/
if (ARM_TBFLAG_AARCH64_STATE(tb->flags)) {
- gen_intermediate_code_internal_a64(cpu, tb, search_pc);
+ gen_intermediate_code_a64(cpu, tb);
return;
}
@@ -11256,11 +11250,14 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu,
/* FIXME: cpu_M0 can probably be the same as cpu_V0. */
cpu_M0 = tcg_temp_new_i64();
next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
- lj = -1;
num_insns = 0;
max_insns = tb->cflags & CF_COUNT_MASK;
- if (max_insns == 0)
+ if (max_insns == 0) {
max_insns = CF_COUNT_MASK;
+ }
+ if (max_insns > TCG_MAX_INSNS) {
+ max_insns = TCG_MAX_INSNS;
+ }
gen_tb_start(tb);
@@ -11286,10 +11283,9 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu,
* (3) if we leave the TB unexpectedly (eg a data abort on a load)
* then the CPUARMState will be wrong and we need to reset it.
* This is handled in the same way as restoration of the
- * PC in these situations: we will be called again with search_pc=1
- * and generate a mapping of the condexec bits for each PC in
- * gen_opc_condexec_bits[]. restore_state_to_opc() then uses
- * this to restore the condexec bits.
+ * PC in these situations; we save the value of the condexec bits
+ * for each PC via tcg_gen_insn_start(), and restore_state_to_opc()
+ * then uses this to restore them after an exception.
*
* Note that there are no instructions which can read the condexec
* bits, and none which can write non-static values to them, so
@@ -11306,6 +11302,10 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu,
store_cpu_field(tmp, condexec_bits);
}
do {
+ tcg_gen_insn_start(dc->pc,
+ (dc->condexec_cond << 4) | (dc->condexec_mask >> 1));
+ num_insns++;
+
#ifdef CONFIG_USER_ONLY
/* Intercept jump to the magic kernel page. */
if (dc->pc >= 0xffff0000) {
@@ -11326,6 +11326,7 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu,
#endif
if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
+ CPUBreakpoint *bp;
QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
if (bp->pc == dc->pc) {
gen_exception_internal_insn(dc, 0, EXCP_DEBUG);
@@ -11336,24 +11337,9 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu,
}
}
}
- if (search_pc) {
- j = tcg_op_buf_count();
- if (lj < j) {
- lj++;
- while (lj < j)
- tcg_ctx.gen_opc_instr_start[lj++] = 0;
- }
- tcg_ctx.gen_opc_pc[lj] = dc->pc;
- gen_opc_condexec_bits[lj] = (dc->condexec_cond << 4) | (dc->condexec_mask >> 1);
- tcg_ctx.gen_opc_instr_start[lj] = 1;
- tcg_ctx.gen_opc_icount[lj] = num_insns;
- }
- if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
+ if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
gen_io_start();
-
- if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
- tcg_gen_debug_insn_start(dc->pc);
}
if (dc->ss_active && !dc->pstate_ss) {
@@ -11367,7 +11353,7 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu,
* "did not step an insn" case, and so the syndrome ISV and EX
* bits should be zero.
*/
- assert(num_insns == 0);
+ assert(num_insns == 1);
gen_exception(EXCP_UDEF, syn_swstep(dc->ss_same_el, 0, 0),
default_exception_el(dc));
goto done_generating;
@@ -11403,7 +11389,6 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu,
* Otherwise the subsequent code could get translated several times.
* Also stop translation when a page boundary is reached. This
* ensures prefetch aborts occur at the right place. */
- num_insns ++;
} while (!dc->is_jmp && !tcg_op_buf_full() &&
!cs->singlestep_enabled &&
!singlestep &&
@@ -11533,25 +11518,8 @@ done_generating:
qemu_log("\n");
}
#endif
- if (search_pc) {
- j = tcg_op_buf_count();
- lj++;
- while (lj <= j)
- tcg_ctx.gen_opc_instr_start[lj++] = 0;
- } else {
- tb->size = dc->pc - pc_start;
- tb->icount = num_insns;
- }
-}
-
-void gen_intermediate_code(CPUARMState *env, TranslationBlock *tb)
-{
- gen_intermediate_code_internal(arm_env_get_cpu(env), tb, false);
-}
-
-void gen_intermediate_code_pc(CPUARMState *env, TranslationBlock *tb)
-{
- gen_intermediate_code_internal(arm_env_get_cpu(env), tb, true);
+ tb->size = dc->pc - pc_start;
+ tb->icount = num_insns;
}
static const char *cpu_mode_names[16] = {
@@ -11608,13 +11576,14 @@ void arm_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
}
}
-void restore_state_to_opc(CPUARMState *env, TranslationBlock *tb, int pc_pos)
+void restore_state_to_opc(CPUARMState *env, TranslationBlock *tb,
+ target_ulong *data)
{
if (is_a64(env)) {
- env->pc = tcg_ctx.gen_opc_pc[pc_pos];
+ env->pc = data[0];
env->condexec_bits = 0;
} else {
- env->regs[15] = tcg_ctx.gen_opc_pc[pc_pos];
- env->condexec_bits = gen_opc_condexec_bits[pc_pos];
+ env->regs[15] = data[0];
+ env->condexec_bits = data[1];
}
}
diff --git a/target-arm/translate.h b/target-arm/translate.h
index b8fe37a0a7..53ef971058 100644
--- a/target-arm/translate.h
+++ b/target-arm/translate.h
@@ -122,9 +122,7 @@ static inline int default_exception_el(DisasContext *s)
#ifdef TARGET_AARCH64
void a64_translate_init(void);
-void gen_intermediate_code_internal_a64(ARMCPU *cpu,
- TranslationBlock *tb,
- bool search_pc);
+void gen_intermediate_code_a64(ARMCPU *cpu, TranslationBlock *tb);
void gen_a64_set_pc_im(uint64_t val);
void aarch64_cpu_dump_state(CPUState *cs, FILE *f,
fprintf_function cpu_fprintf, int flags);
@@ -133,9 +131,7 @@ static inline void a64_translate_init(void)
{
}
-static inline void gen_intermediate_code_internal_a64(ARMCPU *cpu,
- TranslationBlock *tb,
- bool search_pc)
+static inline void gen_intermediate_code_a64(ARMCPU *cpu, TranslationBlock *tb)
{
}
diff --git a/target-cris/cpu.h b/target-cris/cpu.h
index d47fad466b..32204607ca 100644
--- a/target-cris/cpu.h
+++ b/target-cris/cpu.h
@@ -223,7 +223,6 @@ enum {
#define cpu_init(cpu_model) CPU(cpu_cris_init(cpu_model))
#define cpu_exec cpu_cris_exec
-#define cpu_gen_code cpu_cris_gen_code
#define cpu_signal_handler cpu_cris_signal_handler
/* MMU modes definitions */
diff --git a/target-cris/translate.c b/target-cris/translate.c
index d5b54e1ad4..964845c461 100644
--- a/target-cris/translate.c
+++ b/target-cris/translate.c
@@ -2994,10 +2994,6 @@ static unsigned int crisv32_decoder(CPUCRISState *env, DisasContext *dc)
int insn_len = 2;
int i;
- if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
- tcg_gen_debug_insn_start(dc->pc);
- }
-
/* Load a halfword onto the instruction register. */
dc->ir = cris_fetch(env, dc, dc->pc, 2, 0);
@@ -3034,23 +3030,6 @@ static unsigned int crisv32_decoder(CPUCRISState *env, DisasContext *dc)
return insn_len;
}
-static void check_breakpoint(CPUCRISState *env, DisasContext *dc)
-{
- CPUState *cs = CPU(cris_env_get_cpu(env));
- CPUBreakpoint *bp;
-
- if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
- QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
- if (bp->pc == dc->pc) {
- cris_evaluate_flags(dc);
- tcg_gen_movi_tl(env_pc, dc->pc);
- t_gen_raise_exception(EXCP_DEBUG);
- dc->is_jmp = DISAS_UPDATE;
- }
- }
- }
-}
-
#include "translate_v10.c"
/*
@@ -3088,15 +3067,12 @@ static void check_breakpoint(CPUCRISState *env, DisasContext *dc)
*/
/* generate intermediate code for basic block 'tb'. */
-static inline void
-gen_intermediate_code_internal(CRISCPU *cpu, TranslationBlock *tb,
- bool search_pc)
+void gen_intermediate_code(CPUCRISState *env, struct TranslationBlock *tb)
{
+ CRISCPU *cpu = cris_env_get_cpu(env);
CPUState *cs = CPU(cpu);
- CPUCRISState *env = &cpu->env;
uint32_t pc_start;
unsigned int insn_len;
- int j, lj;
struct DisasContext ctx;
struct DisasContext *dc = &ctx;
uint32_t next_page_start;
@@ -3148,13 +3124,13 @@ gen_intermediate_code_internal(CRISCPU *cpu, TranslationBlock *tb,
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
qemu_log(
- "srch=%d pc=%x %x flg=%" PRIx64 " bt=%x ds=%u ccs=%x\n"
+ "pc=%x %x flg=%" PRIx64 " bt=%x ds=%u ccs=%x\n"
"pid=%x usp=%x\n"
"%x.%x.%x.%x\n"
"%x.%x.%x.%x\n"
"%x.%x.%x.%x\n"
"%x.%x.%x.%x\n",
- search_pc, dc->pc, dc->ppc,
+ dc->pc, dc->ppc,
(uint64_t)tb->flags,
env->btarget, (unsigned)tb->flags & 7,
env->pregs[PR_CCS],
@@ -3170,38 +3146,33 @@ gen_intermediate_code_internal(CRISCPU *cpu, TranslationBlock *tb,
}
next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
- lj = -1;
num_insns = 0;
max_insns = tb->cflags & CF_COUNT_MASK;
if (max_insns == 0) {
max_insns = CF_COUNT_MASK;
}
+ if (max_insns > TCG_MAX_INSNS) {
+ max_insns = TCG_MAX_INSNS;
+ }
gen_tb_start(tb);
do {
- check_breakpoint(env, dc);
-
- if (search_pc) {
- j = tcg_op_buf_count();
- if (lj < j) {
- lj++;
- while (lj < j) {
- tcg_ctx.gen_opc_instr_start[lj++] = 0;
- }
- }
- if (dc->delayed_branch == 1) {
- tcg_ctx.gen_opc_pc[lj] = dc->ppc | 1;
- } else {
- tcg_ctx.gen_opc_pc[lj] = dc->pc;
- }
- tcg_ctx.gen_opc_instr_start[lj] = 1;
- tcg_ctx.gen_opc_icount[lj] = num_insns;
+ tcg_gen_insn_start(dc->delayed_branch == 1
+ ? dc->ppc | 1 : dc->pc);
+ num_insns++;
+
+ if (unlikely(cpu_breakpoint_test(cs, dc->pc, BP_ANY))) {
+ cris_evaluate_flags(dc);
+ tcg_gen_movi_tl(env_pc, dc->pc);
+ t_gen_raise_exception(EXCP_DEBUG);
+ dc->is_jmp = DISAS_UPDATE;
+ break;
}
/* Pretty disas. */
LOG_DIS("%8.8x:\t", dc->pc);
- if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) {
+ if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
gen_io_start();
}
dc->clear_x = 1;
@@ -3213,7 +3184,6 @@ gen_intermediate_code_internal(CRISCPU *cpu, TranslationBlock *tb,
cris_clear_x_flag(dc);
}
- num_insns++;
/* Check for delayed branches here. If we do it before
actually generating any host code, the simulator will just
loop doing nothing for on this program location. */
@@ -3318,16 +3288,8 @@ gen_intermediate_code_internal(CRISCPU *cpu, TranslationBlock *tb,
}
gen_tb_end(tb, num_insns);
- if (search_pc) {
- j = tcg_op_buf_count();
- lj++;
- while (lj <= j) {
- tcg_ctx.gen_opc_instr_start[lj++] = 0;
- }
- } else {
- tb->size = dc->pc - pc_start;
- tb->icount = num_insns;
- }
+ tb->size = dc->pc - pc_start;
+ tb->icount = num_insns;
#ifdef DEBUG_DISAS
#if !DISAS_CRIS
@@ -3341,16 +3303,6 @@ gen_intermediate_code_internal(CRISCPU *cpu, TranslationBlock *tb,
#endif
}
-void gen_intermediate_code (CPUCRISState *env, struct TranslationBlock *tb)
-{
- gen_intermediate_code_internal(cris_env_get_cpu(env), tb, false);
-}
-
-void gen_intermediate_code_pc (CPUCRISState *env, struct TranslationBlock *tb)
-{
- gen_intermediate_code_internal(cris_env_get_cpu(env), tb, true);
-}
-
void cris_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
int flags)
{
@@ -3443,7 +3395,8 @@ void cris_initialize_tcg(void)
}
}
-void restore_state_to_opc(CPUCRISState *env, TranslationBlock *tb, int pc_pos)
+void restore_state_to_opc(CPUCRISState *env, TranslationBlock *tb,
+ target_ulong *data)
{
- env->pc = tcg_ctx.gen_opc_pc[pc_pos];
+ env->pc = data[0];
}
diff --git a/target-cris/translate_v10.c b/target-cris/translate_v10.c
index da0b2caf85..3ab1c398e0 100644
--- a/target-cris/translate_v10.c
+++ b/target-cris/translate_v10.c
@@ -1199,9 +1199,6 @@ static unsigned int crisv10_decoder(CPUCRISState *env, DisasContext *dc)
{
unsigned int insn_len = 2;
- if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP)))
- tcg_gen_debug_insn_start(dc->pc);
-
/* Load a halfword onto the instruction register. */
dc->ir = cpu_lduw_code(env, dc->pc);
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index 8926780e85..54d9d50140 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -794,6 +794,7 @@ typedef struct {
#define MAX_GP_COUNTERS (MSR_IA32_PERF_STATUS - MSR_P6_EVNTSEL0)
#define NB_MMU_MODES 3
+#define TARGET_INSN_START_EXTRA_WORDS 1
#define NB_OPMASK_REGS 8
@@ -1188,7 +1189,6 @@ uint64_t cpu_get_tsc(CPUX86State *env);
#define cpu_init(cpu_model) CPU(cpu_x86_init(cpu_model))
#define cpu_exec cpu_x86_exec
-#define cpu_gen_code cpu_x86_gen_code
#define cpu_signal_handler cpu_x86_signal_handler
#define cpu_list x86_cpu_list
#define cpudef_setup x86_cpudef_setup
diff --git a/target-i386/translate.c b/target-i386/translate.c
index 8b35de1a1a..ef10e685cc 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -75,8 +75,6 @@ static TCGv_ptr cpu_ptr0, cpu_ptr1;
static TCGv_i32 cpu_tmp2_i32, cpu_tmp3_i32;
static TCGv_i64 cpu_tmp1_i64;
-static uint8_t gen_opc_cc_op[OPC_BUF_SIZE];
-
#include "exec/gen-icount.h"
#ifdef TARGET_X86_64
@@ -4401,9 +4399,6 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
target_ulong next_eip, tval;
int rex_w, rex_r;
- if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
- tcg_gen_debug_insn_start(pc_start);
- }
s->pc = pc_start;
prefixes = 0;
s->override = -1;
@@ -7842,18 +7837,13 @@ void optimize_flags_init(void)
}
/* generate intermediate code in gen_opc_buf and gen_opparam_buf for
- basic block 'tb'. If search_pc is TRUE, also generate PC
- information for each intermediate instruction. */
-static inline void gen_intermediate_code_internal(X86CPU *cpu,
- TranslationBlock *tb,
- bool search_pc)
+ basic block 'tb'. */
+void gen_intermediate_code(CPUX86State *env, TranslationBlock *tb)
{
+ X86CPU *cpu = x86_env_get_cpu(env);
CPUState *cs = CPU(cpu);
- CPUX86State *env = &cpu->env;
DisasContext dc1, *dc = &dc1;
target_ulong pc_ptr;
- CPUBreakpoint *bp;
- int j, lj;
uint64_t flags;
target_ulong pc_start;
target_ulong cs_base;
@@ -7933,40 +7923,32 @@ static inline void gen_intermediate_code_internal(X86CPU *cpu,
dc->is_jmp = DISAS_NEXT;
pc_ptr = pc_start;
- lj = -1;
num_insns = 0;
max_insns = tb->cflags & CF_COUNT_MASK;
- if (max_insns == 0)
+ if (max_insns == 0) {
max_insns = CF_COUNT_MASK;
+ }
+ if (max_insns > TCG_MAX_INSNS) {
+ max_insns = TCG_MAX_INSNS;
+ }
gen_tb_start(tb);
for(;;) {
- if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
- QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
- if (bp->pc == pc_ptr &&
- !((bp->flags & BP_CPU) && (tb->flags & HF_RF_MASK))) {
- gen_debug(dc, pc_ptr - dc->cs_base);
- goto done_generating;
- }
- }
- }
- if (search_pc) {
- j = tcg_op_buf_count();
- if (lj < j) {
- lj++;
- while (lj < j)
- tcg_ctx.gen_opc_instr_start[lj++] = 0;
- }
- tcg_ctx.gen_opc_pc[lj] = pc_ptr;
- gen_opc_cc_op[lj] = dc->cc_op;
- tcg_ctx.gen_opc_instr_start[lj] = 1;
- tcg_ctx.gen_opc_icount[lj] = num_insns;
+ tcg_gen_insn_start(pc_ptr, dc->cc_op);
+ num_insns++;
+
+ /* If RF is set, suppress an internally generated breakpoint. */
+ if (unlikely(cpu_breakpoint_test(cs, pc_ptr,
+ tb->flags & HF_RF_MASK
+ ? BP_GDB : BP_ANY))) {
+ gen_debug(dc, pc_ptr - dc->cs_base);
+ goto done_generating;
}
- if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
+ if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
gen_io_start();
+ }
pc_ptr = disas_insn(env, dc, pc_ptr);
- num_insns++;
/* stop translation if indicated */
if (dc->is_jmp)
break;
@@ -8014,14 +7996,6 @@ static inline void gen_intermediate_code_internal(X86CPU *cpu,
done_generating:
gen_tb_end(tb, num_insns);
- /* we don't forget to fill the last values */
- if (search_pc) {
- j = tcg_op_buf_count();
- lj++;
- while (lj <= j)
- tcg_ctx.gen_opc_instr_start[lj++] = 0;
- }
-
#ifdef DEBUG_DISAS
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
int disas_flags;
@@ -8038,42 +8012,16 @@ done_generating:
}
#endif
- if (!search_pc) {
- tb->size = pc_ptr - pc_start;
- tb->icount = num_insns;
- }
+ tb->size = pc_ptr - pc_start;
+ tb->icount = num_insns;
}
-void gen_intermediate_code(CPUX86State *env, TranslationBlock *tb)
+void restore_state_to_opc(CPUX86State *env, TranslationBlock *tb,
+ target_ulong *data)
{
- gen_intermediate_code_internal(x86_env_get_cpu(env), tb, false);
-}
-
-void gen_intermediate_code_pc(CPUX86State *env, TranslationBlock *tb)
-{
- gen_intermediate_code_internal(x86_env_get_cpu(env), tb, true);
-}
-
-void restore_state_to_opc(CPUX86State *env, TranslationBlock *tb, int pc_pos)
-{
- int cc_op;
-#ifdef DEBUG_DISAS
- if (qemu_loglevel_mask(CPU_LOG_TB_OP)) {
- int i;
- qemu_log("RESTORE:\n");
- for(i = 0;i <= pc_pos; i++) {
- if (tcg_ctx.gen_opc_instr_start[i]) {
- qemu_log("0x%04x: " TARGET_FMT_lx "\n", i,
- tcg_ctx.gen_opc_pc[i]);
- }
- }
- qemu_log("pc_pos=0x%x eip=" TARGET_FMT_lx " cs_base=%x\n",
- pc_pos, tcg_ctx.gen_opc_pc[pc_pos] - tb->cs_base,
- (uint32_t)tb->cs_base);
- }
-#endif
- env->eip = tcg_ctx.gen_opc_pc[pc_pos] - tb->cs_base;
- cc_op = gen_opc_cc_op[pc_pos];
- if (cc_op != CC_OP_DYNAMIC)
+ int cc_op = data[1];
+ env->eip = data[0] - tb->cs_base;
+ if (cc_op != CC_OP_DYNAMIC) {
env->cc_op = cc_op;
+ }
}
diff --git a/target-lm32/cpu.h b/target-lm32/cpu.h
index 3f874d5111..2b7620c7da 100644
--- a/target-lm32/cpu.h
+++ b/target-lm32/cpu.h
@@ -219,7 +219,6 @@ bool lm32_cpu_do_semihosting(CPUState *cs);
#define cpu_list lm32_cpu_list
#define cpu_exec cpu_lm32_exec
-#define cpu_gen_code cpu_lm32_gen_code
#define cpu_signal_handler cpu_lm32_signal_handler
int lm32_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int rw,
diff --git a/target-lm32/translate.c b/target-lm32/translate.c
index cf7042e3e0..c61ad0f9ab 100644
--- a/target-lm32/translate.c
+++ b/target-lm32/translate.c
@@ -1005,10 +1005,6 @@ static const DecoderInfo decinfo[] = {
static inline void decode(DisasContext *dc, uint32_t ir)
{
- if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
- tcg_gen_debug_insn_start(dc->pc);
- }
-
dc->ir = ir;
LOG_DIS("%8.8x\t", dc->ir);
@@ -1036,32 +1032,13 @@ static inline void decode(DisasContext *dc, uint32_t ir)
decinfo[dc->opcode](dc);
}
-static void check_breakpoint(CPULM32State *env, DisasContext *dc)
-{
- CPUState *cs = CPU(lm32_env_get_cpu(env));
- CPUBreakpoint *bp;
-
- if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
- QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
- if (bp->pc == dc->pc) {
- tcg_gen_movi_tl(cpu_pc, dc->pc);
- t_gen_raise_exception(dc, EXCP_DEBUG);
- dc->is_jmp = DISAS_UPDATE;
- }
- }
- }
-}
-
/* generate intermediate code for basic block 'tb'. */
-static inline
-void gen_intermediate_code_internal(LM32CPU *cpu,
- TranslationBlock *tb, bool search_pc)
+void gen_intermediate_code(CPULM32State *env, struct TranslationBlock *tb)
{
+ LM32CPU *cpu = lm32_env_get_cpu(env);
CPUState *cs = CPU(cpu);
- CPULM32State *env = &cpu->env;
struct DisasContext ctx, *dc = &ctx;
uint32_t pc_start;
- int j, lj;
uint32_t next_page_start;
int num_insns;
int max_insns;
@@ -1083,41 +1060,36 @@ void gen_intermediate_code_internal(LM32CPU *cpu,
}
next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
- lj = -1;
num_insns = 0;
max_insns = tb->cflags & CF_COUNT_MASK;
if (max_insns == 0) {
max_insns = CF_COUNT_MASK;
}
+ if (max_insns > TCG_MAX_INSNS) {
+ max_insns = TCG_MAX_INSNS;
+ }
gen_tb_start(tb);
do {
- check_breakpoint(env, dc);
-
- if (search_pc) {
- j = tcg_op_buf_count();
- if (lj < j) {
- lj++;
- while (lj < j) {
- tcg_ctx.gen_opc_instr_start[lj++] = 0;
- }
- }
- tcg_ctx.gen_opc_pc[lj] = dc->pc;
- tcg_ctx.gen_opc_instr_start[lj] = 1;
- tcg_ctx.gen_opc_icount[lj] = num_insns;
+ tcg_gen_insn_start(dc->pc);
+ num_insns++;
+
+ if (unlikely(cpu_breakpoint_test(cs, dc->pc, BP_ANY))) {
+ tcg_gen_movi_tl(cpu_pc, dc->pc);
+ t_gen_raise_exception(dc, EXCP_DEBUG);
+ dc->is_jmp = DISAS_UPDATE;
+ break;
}
/* Pretty disas. */
LOG_DIS("%8.8x:\t", dc->pc);
- if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) {
+ if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
gen_io_start();
}
decode(dc, cpu_ldl_code(env, dc->pc));
dc->pc += 4;
- num_insns++;
-
} while (!dc->is_jmp
&& !tcg_op_buf_full()
&& !cs->singlestep_enabled
@@ -1154,16 +1126,8 @@ void gen_intermediate_code_internal(LM32CPU *cpu,
gen_tb_end(tb, num_insns);
- if (search_pc) {
- j = tcg_op_buf_count();
- lj++;
- while (lj <= j) {
- tcg_ctx.gen_opc_instr_start[lj++] = 0;
- }
- } else {
- tb->size = dc->pc - pc_start;
- tb->icount = num_insns;
- }
+ tb->size = dc->pc - pc_start;
+ tb->icount = num_insns;
#ifdef DEBUG_DISAS
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
@@ -1175,16 +1139,6 @@ void gen_intermediate_code_internal(LM32CPU *cpu,
#endif
}
-void gen_intermediate_code(CPULM32State *env, struct TranslationBlock *tb)
-{
- gen_intermediate_code_internal(lm32_env_get_cpu(env), tb, false);
-}
-
-void gen_intermediate_code_pc(CPULM32State *env, struct TranslationBlock *tb)
-{
- gen_intermediate_code_internal(lm32_env_get_cpu(env), tb, true);
-}
-
void lm32_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
int flags)
{
@@ -1219,9 +1173,10 @@ void lm32_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
cpu_fprintf(f, "\n\n");
}
-void restore_state_to_opc(CPULM32State *env, TranslationBlock *tb, int pc_pos)
+void restore_state_to_opc(CPULM32State *env, TranslationBlock *tb,
+ target_ulong *data)
{
- env->pc = tcg_ctx.gen_opc_pc[pc_pos];
+ env->pc = data[0];
}
void lm32_translate_init(void)
diff --git a/target-m68k/cpu.h b/target-m68k/cpu.h
index d1957063b4..224c16967c 100644
--- a/target-m68k/cpu.h
+++ b/target-m68k/cpu.h
@@ -213,7 +213,6 @@ void register_m68k_insns (CPUM68KState *env);
#define cpu_init(cpu_model) CPU(cpu_m68k_init(cpu_model))
#define cpu_exec cpu_m68k_exec
-#define cpu_gen_code cpu_m68k_gen_code
#define cpu_signal_handler cpu_m68k_signal_handler
#define cpu_list m68k_cpu_list
diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index 3cdf6652aa..5995ccea92 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -2955,10 +2955,6 @@ static void disas_m68k_insn(CPUM68KState * env, DisasContext *s)
{
uint16_t insn;
- if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
- tcg_gen_debug_insn_start(s->pc);
- }
-
insn = cpu_lduw_code(env, s->pc);
s->pc += 2;
@@ -2966,15 +2962,11 @@ static void disas_m68k_insn(CPUM68KState * env, DisasContext *s)
}
/* generate intermediate code for basic block 'tb'. */
-static inline void
-gen_intermediate_code_internal(M68kCPU *cpu, TranslationBlock *tb,
- bool search_pc)
+void gen_intermediate_code(CPUM68KState *env, TranslationBlock *tb)
{
+ M68kCPU *cpu = m68k_env_get_cpu(env);
CPUState *cs = CPU(cpu);
- CPUM68KState *env = &cpu->env;
DisasContext dc1, *dc = &dc1;
- CPUBreakpoint *bp;
- int j, lj;
target_ulong pc_start;
int pc_offset;
int num_insns;
@@ -2993,43 +2985,34 @@ gen_intermediate_code_internal(M68kCPU *cpu, TranslationBlock *tb,
dc->fpcr = env->fpcr;
dc->user = (env->sr & SR_S) == 0;
dc->done_mac = 0;
- lj = -1;
num_insns = 0;
max_insns = tb->cflags & CF_COUNT_MASK;
- if (max_insns == 0)
+ if (max_insns == 0) {
max_insns = CF_COUNT_MASK;
+ }
+ if (max_insns > TCG_MAX_INSNS) {
+ max_insns = TCG_MAX_INSNS;
+ }
gen_tb_start(tb);
do {
pc_offset = dc->pc - pc_start;
gen_throws_exception = NULL;
- if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
- QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
- if (bp->pc == dc->pc) {
- gen_exception(dc, dc->pc, EXCP_DEBUG);
- dc->is_jmp = DISAS_JUMP;
- break;
- }
- }
- if (dc->is_jmp)
- break;
- }
- if (search_pc) {
- j = tcg_op_buf_count();
- if (lj < j) {
- lj++;
- while (lj < j)
- tcg_ctx.gen_opc_instr_start[lj++] = 0;
- }
- tcg_ctx.gen_opc_pc[lj] = dc->pc;
- tcg_ctx.gen_opc_instr_start[lj] = 1;
- tcg_ctx.gen_opc_icount[lj] = num_insns;
+ tcg_gen_insn_start(dc->pc);
+ num_insns++;
+
+ if (unlikely(cpu_breakpoint_test(cs, dc->pc, BP_ANY))) {
+ gen_exception(dc, dc->pc, EXCP_DEBUG);
+ dc->is_jmp = DISAS_JUMP;
+ break;
}
- if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
+
+ if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
gen_io_start();
+ }
+
dc->insn_pc = dc->pc;
disas_m68k_insn(env, dc);
- num_insns++;
} while (!dc->is_jmp && !tcg_op_buf_full() &&
!cs->singlestep_enabled &&
!singlestep &&
@@ -3073,28 +3056,8 @@ gen_intermediate_code_internal(M68kCPU *cpu, TranslationBlock *tb,
qemu_log("\n");
}
#endif
- if (search_pc) {
- j = tcg_op_buf_count();
- lj++;
- while (lj <= j)
- tcg_ctx.gen_opc_instr_start[lj++] = 0;
- } else {
- tb->size = dc->pc - pc_start;
- tb->icount = num_insns;
- }
-
- //optimize_flags();
- //expand_target_qops();
-}
-
-void gen_intermediate_code(CPUM68KState *env, TranslationBlock *tb)
-{
- gen_intermediate_code_internal(m68k_env_get_cpu(env), tb, false);
-}
-
-void gen_intermediate_code_pc(CPUM68KState *env, TranslationBlock *tb)
-{
- gen_intermediate_code_internal(m68k_env_get_cpu(env), tb, true);
+ tb->size = dc->pc - pc_start;
+ tb->icount = num_insns;
}
void m68k_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
@@ -3120,7 +3083,8 @@ void m68k_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
cpu_fprintf (f, "FPRESULT = %12g\n", *(double *)&env->fp_result);
}
-void restore_state_to_opc(CPUM68KState *env, TranslationBlock *tb, int pc_pos)
+void restore_state_to_opc(CPUM68KState *env, TranslationBlock *tb,
+ target_ulong *data)
{
- env->pc = tcg_ctx.gen_opc_pc[pc_pos];
+ env->pc = data[0];
}
diff --git a/target-microblaze/cpu.h b/target-microblaze/cpu.h
index b707c71367..6b212ab7f0 100644
--- a/target-microblaze/cpu.h
+++ b/target-microblaze/cpu.h
@@ -295,7 +295,6 @@ int cpu_mb_signal_handler(int host_signum, void *pinfo,
#define cpu_init(cpu_model) CPU(cpu_mb_init(cpu_model))
#define cpu_exec cpu_mb_exec
-#define cpu_gen_code cpu_mb_gen_code
#define cpu_signal_handler cpu_mb_signal_handler
/* MMU modes definitions */
diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c
index 3de89440a6..a9c501099c 100644
--- a/target-microblaze/translate.c
+++ b/target-microblaze/translate.c
@@ -1588,10 +1588,6 @@ static inline void decode(DisasContext *dc, uint32_t ir)
{
int i;
- if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
- tcg_gen_debug_insn_start(dc->pc);
- }
-
dc->ir = ir;
LOG_DIS("%8.8x\t", dc->ir);
@@ -1630,30 +1626,12 @@ static inline void decode(DisasContext *dc, uint32_t ir)
}
}
-static void check_breakpoint(CPUMBState *env, DisasContext *dc)
-{
- CPUState *cs = CPU(mb_env_get_cpu(env));
- CPUBreakpoint *bp;
-
- if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
- QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
- if (bp->pc == dc->pc) {
- t_gen_raise_exception(dc, EXCP_DEBUG);
- dc->is_jmp = DISAS_UPDATE;
- }
- }
- }
-}
-
/* generate intermediate code for basic block 'tb'. */
-static inline void
-gen_intermediate_code_internal(MicroBlazeCPU *cpu, TranslationBlock *tb,
- bool search_pc)
+void gen_intermediate_code(CPUMBState *env, struct TranslationBlock *tb)
{
+ MicroBlazeCPU *cpu = mb_env_get_cpu(env);
CPUState *cs = CPU(cpu);
- CPUMBState *env = &cpu->env;
uint32_t pc_start;
- int j, lj;
struct DisasContext ctx;
struct DisasContext *dc = &ctx;
uint32_t next_page_start, org_flags;
@@ -1690,47 +1668,46 @@ gen_intermediate_code_internal(MicroBlazeCPU *cpu, TranslationBlock *tb,
}
next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
- lj = -1;
num_insns = 0;
max_insns = tb->cflags & CF_COUNT_MASK;
- if (max_insns == 0)
+ if (max_insns == 0) {
max_insns = CF_COUNT_MASK;
+ }
+ if (max_insns > TCG_MAX_INSNS) {
+ max_insns = TCG_MAX_INSNS;
+ }
gen_tb_start(tb);
do
{
+ tcg_gen_insn_start(dc->pc);
+ num_insns++;
+
#if SIM_COMPAT
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
tcg_gen_movi_tl(cpu_SR[SR_PC], dc->pc);
gen_helper_debug();
}
#endif
- check_breakpoint(env, dc);
-
- if (search_pc) {
- j = tcg_op_buf_count();
- if (lj < j) {
- lj++;
- while (lj < j)
- tcg_ctx.gen_opc_instr_start[lj++] = 0;
- }
- tcg_ctx.gen_opc_pc[lj] = dc->pc;
- tcg_ctx.gen_opc_instr_start[lj] = 1;
- tcg_ctx.gen_opc_icount[lj] = num_insns;
+
+ if (unlikely(cpu_breakpoint_test(cs, dc->pc, BP_ANY))) {
+ t_gen_raise_exception(dc, EXCP_DEBUG);
+ dc->is_jmp = DISAS_UPDATE;
+ break;
}
/* Pretty disas. */
LOG_DIS("%8.8x:\t", dc->pc);
- if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
+ if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
gen_io_start();
+ }
dc->clear_imm = 1;
decode(dc, cpu_ldl_code(env, dc->pc));
if (dc->clear_imm)
dc->tb_flags &= ~IMM_FLAG;
dc->pc += 4;
- num_insns++;
if (dc->delayed_branch) {
dc->delayed_branch--;
@@ -1821,15 +1798,8 @@ gen_intermediate_code_internal(MicroBlazeCPU *cpu, TranslationBlock *tb,
}
gen_tb_end(tb, num_insns);
- if (search_pc) {
- j = tcg_op_buf_count();
- lj++;
- while (lj <= j)
- tcg_ctx.gen_opc_instr_start[lj++] = 0;
- } else {
- tb->size = dc->pc - pc_start;
- tb->icount = num_insns;
- }
+ tb->size = dc->pc - pc_start;
+ tb->icount = num_insns;
#ifdef DEBUG_DISAS
#if !SIM_COMPAT
@@ -1846,16 +1816,6 @@ gen_intermediate_code_internal(MicroBlazeCPU *cpu, TranslationBlock *tb,
assert(!dc->abort_at_next_insn);
}
-void gen_intermediate_code (CPUMBState *env, struct TranslationBlock *tb)
-{
- gen_intermediate_code_internal(mb_env_get_cpu(env), tb, false);
-}
-
-void gen_intermediate_code_pc (CPUMBState *env, struct TranslationBlock *tb)
-{
- gen_intermediate_code_internal(mb_env_get_cpu(env), tb, true);
-}
-
void mb_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
int flags)
{
@@ -1936,7 +1896,8 @@ void mb_tcg_init(void)
}
}
-void restore_state_to_opc(CPUMBState *env, TranslationBlock *tb, int pc_pos)
+void restore_state_to_opc(CPUMBState *env, TranslationBlock *tb,
+ target_ulong *data)
{
- env->sregs[SR_PC] = tcg_ctx.gen_opc_pc[pc_pos];
+ env->sregs[SR_PC] = data[0];
}
diff --git a/target-mips/cpu.h b/target-mips/cpu.h
index ec5f991dfb..f32a0fd737 100644
--- a/target-mips/cpu.h
+++ b/target-mips/cpu.h
@@ -130,6 +130,7 @@ struct CPUMIPSFPUContext {
};
#define NB_MMU_MODES 3
+#define TARGET_INSN_START_EXTRA_WORDS 2
typedef struct CPUMIPSMVPContext CPUMIPSMVPContext;
struct CPUMIPSMVPContext {
@@ -619,7 +620,6 @@ void mips_cpu_unassigned_access(CPUState *cpu, hwaddr addr,
void mips_cpu_list (FILE *f, fprintf_function cpu_fprintf);
#define cpu_exec cpu_mips_exec
-#define cpu_gen_code cpu_mips_gen_code
#define cpu_signal_handler cpu_mips_signal_handler
#define cpu_list mips_cpu_list
diff --git a/target-mips/translate.c b/target-mips/translate.c
index 87d495975a..897839ced9 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -1359,9 +1359,6 @@ static TCGv_i32 fpu_fcr0, fpu_fcr31;
static TCGv_i64 fpu_f64[32];
static TCGv_i64 msa_wr_d[64];
-static uint32_t gen_opc_hflags[OPC_BUF_SIZE];
-static target_ulong gen_opc_btarget[OPC_BUF_SIZE];
-
#include "exec/gen-icount.h"
#define gen_helper_0e0i(name, arg) do { \
@@ -18904,10 +18901,6 @@ static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
gen_set_label(l1);
}
- if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
- tcg_gen_debug_insn_start(ctx->pc);
- }
-
op = MASK_OP_MAJOR(ctx->opcode);
rs = (ctx->opcode >> 21) & 0x1f;
rt = (ctx->opcode >> 16) & 0x1f;
@@ -19539,25 +19532,18 @@ static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
}
}
-static inline void
-gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb,
- bool search_pc)
+void gen_intermediate_code(CPUMIPSState *env, struct TranslationBlock *tb)
{
+ MIPSCPU *cpu = mips_env_get_cpu(env);
CPUState *cs = CPU(cpu);
- CPUMIPSState *env = &cpu->env;
DisasContext ctx;
target_ulong pc_start;
target_ulong next_page_start;
- CPUBreakpoint *bp;
- int j, lj = -1;
int num_insns;
int max_insns;
int insn_bytes;
int is_slot;
- if (search_pc)
- qemu_log("search pc %d\n", search_pc);
-
pc_start = tb->pc;
next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
ctx.pc = pc_start;
@@ -19567,6 +19553,7 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb,
ctx.CP0_Config1 = env->CP0_Config1;
ctx.tb = tb;
ctx.bstate = BS_NONE;
+ ctx.btarget = 0;
ctx.kscrexist = (env->CP0_Config4 >> CP0C4_KScrExist) & 0xff;
ctx.rxi = (env->CP0_Config3 >> CP0C3_RXI) & 1;
ctx.ie = (env->CP0_Config4 >> CP0C4_IE) & 3;
@@ -19590,40 +19577,32 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb,
MO_UNALN : MO_ALIGN;
num_insns = 0;
max_insns = tb->cflags & CF_COUNT_MASK;
- if (max_insns == 0)
+ if (max_insns == 0) {
max_insns = CF_COUNT_MASK;
+ }
+ if (max_insns > TCG_MAX_INSNS) {
+ max_insns = TCG_MAX_INSNS;
+ }
+
LOG_DISAS("\ntb %p idx %d hflags %04x\n", tb, ctx.mem_idx, ctx.hflags);
gen_tb_start(tb);
while (ctx.bstate == BS_NONE) {
- if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
- QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
- if (bp->pc == ctx.pc) {
- save_cpu_state(&ctx, 1);
- ctx.bstate = BS_BRANCH;
- gen_helper_raise_exception_debug(cpu_env);
- /* Include the breakpoint location or the tb won't
- * be flushed when it must be. */
- ctx.pc += 4;
- goto done_generating;
- }
- }
- }
+ tcg_gen_insn_start(ctx.pc, ctx.hflags & MIPS_HFLAG_BMASK, ctx.btarget);
+ num_insns++;
- if (search_pc) {
- j = tcg_op_buf_count();
- if (lj < j) {
- lj++;
- while (lj < j)
- tcg_ctx.gen_opc_instr_start[lj++] = 0;
- }
- tcg_ctx.gen_opc_pc[lj] = ctx.pc;
- gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK;
- gen_opc_btarget[lj] = ctx.btarget;
- tcg_ctx.gen_opc_instr_start[lj] = 1;
- tcg_ctx.gen_opc_icount[lj] = num_insns;
+ if (unlikely(cpu_breakpoint_test(cs, ctx.pc, BP_ANY))) {
+ save_cpu_state(&ctx, 1);
+ ctx.bstate = BS_BRANCH;
+ gen_helper_raise_exception_debug(cpu_env);
+ /* Include the breakpoint location or the tb won't
+ * be flushed when it must be. */
+ ctx.pc += 4;
+ goto done_generating;
}
- if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
+
+ if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
gen_io_start();
+ }
is_slot = ctx.hflags & MIPS_HFLAG_BMASK;
if (!(ctx.hflags & MIPS_HFLAG_M16)) {
@@ -19660,8 +19639,6 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb,
}
ctx.pc += insn_bytes;
- num_insns++;
-
/* Execute a branch and its delay slot as a single instruction.
This is what GDB expects and is consistent with what the
hardware does (e.g. if a delay slot instruction faults, the
@@ -19710,15 +19687,9 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb,
done_generating:
gen_tb_end(tb, num_insns);
- if (search_pc) {
- j = tcg_op_buf_count();
- lj++;
- while (lj <= j)
- tcg_ctx.gen_opc_instr_start[lj++] = 0;
- } else {
- tb->size = ctx.pc - pc_start;
- tb->icount = num_insns;
- }
+ tb->size = ctx.pc - pc_start;
+ tb->icount = num_insns;
+
#ifdef DEBUG_DISAS
LOG_DISAS("\n");
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
@@ -19729,16 +19700,6 @@ done_generating:
#endif
}
-void gen_intermediate_code (CPUMIPSState *env, struct TranslationBlock *tb)
-{
- gen_intermediate_code_internal(mips_env_get_cpu(env), tb, false);
-}
-
-void gen_intermediate_code_pc (CPUMIPSState *env, struct TranslationBlock *tb)
-{
- gen_intermediate_code_internal(mips_env_get_cpu(env), tb, true);
-}
-
static void fpu_dump_state(CPUMIPSState *env, FILE *f, fprintf_function fpu_fprintf,
int flags)
{
@@ -20062,18 +20023,19 @@ void cpu_state_reset(CPUMIPSState *env)
}
}
-void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb, int pc_pos)
+void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb,
+ target_ulong *data)
{
- env->active_tc.PC = tcg_ctx.gen_opc_pc[pc_pos];
+ env->active_tc.PC = data[0];
env->hflags &= ~MIPS_HFLAG_BMASK;
- env->hflags |= gen_opc_hflags[pc_pos];
+ env->hflags |= data[1];
switch (env->hflags & MIPS_HFLAG_BMASK_BASE) {
case MIPS_HFLAG_BR:
break;
case MIPS_HFLAG_BC:
case MIPS_HFLAG_BL:
case MIPS_HFLAG_B:
- env->btarget = gen_opc_btarget[pc_pos];
+ env->btarget = data[2];
break;
}
}
diff --git a/target-moxie/cpu.h b/target-moxie/cpu.h
index 2bac15bf60..a612744011 100644
--- a/target-moxie/cpu.h
+++ b/target-moxie/cpu.h
@@ -122,7 +122,6 @@ int cpu_moxie_signal_handler(int host_signum, void *pinfo,
#define cpu_init(cpu_model) CPU(cpu_moxie_init(cpu_model))
#define cpu_exec cpu_moxie_exec
-#define cpu_gen_code cpu_moxie_gen_code
#define cpu_signal_handler cpu_moxie_signal_handler
static inline int cpu_mmu_index(CPUMoxieState *env, bool ifetch)
diff --git a/target-moxie/translate.c b/target-moxie/translate.c
index cc77366ee7..f84841efe2 100644
--- a/target-moxie/translate.c
+++ b/target-moxie/translate.c
@@ -153,10 +153,6 @@ static int decode_opc(MoxieCPU *cpu, DisasContext *ctx)
/* Set the default instruction length. */
int length = 2;
- if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
- tcg_gen_debug_insn_start(ctx->pc);
- }
-
/* Examine the 16-bit opcode. */
opcode = ctx->opcode;
@@ -819,17 +815,13 @@ static int decode_opc(MoxieCPU *cpu, DisasContext *ctx)
}
/* generate intermediate code for basic block 'tb'. */
-static inline void
-gen_intermediate_code_internal(MoxieCPU *cpu, TranslationBlock *tb,
- bool search_pc)
+void gen_intermediate_code(CPUMoxieState *env, struct TranslationBlock *tb)
{
+ MoxieCPU *cpu = moxie_env_get_cpu(env);
CPUState *cs = CPU(cpu);
DisasContext ctx;
target_ulong pc_start;
- CPUBreakpoint *bp;
- int j, lj = -1;
- CPUMoxieState *env = &cpu->env;
- int num_insns;
+ int num_insns, max_insns;
pc_start = tb->pc;
ctx.pc = pc_start;
@@ -839,40 +831,35 @@ gen_intermediate_code_internal(MoxieCPU *cpu, TranslationBlock *tb,
ctx.singlestep_enabled = 0;
ctx.bstate = BS_NONE;
num_insns = 0;
+ max_insns = tb->cflags & CF_COUNT_MASK;
+ if (max_insns == 0) {
+ max_insns = CF_COUNT_MASK;
+ }
+ if (max_insns > TCG_MAX_INSNS) {
+ max_insns = TCG_MAX_INSNS;
+ }
gen_tb_start(tb);
do {
- if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
- QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
- if (ctx.pc == bp->pc) {
- tcg_gen_movi_i32(cpu_pc, ctx.pc);
- gen_helper_debug(cpu_env);
- ctx.bstate = BS_EXCP;
- goto done_generating;
- }
- }
- }
+ tcg_gen_insn_start(ctx.pc);
+ num_insns++;
- if (search_pc) {
- j = tcg_op_buf_count();
- if (lj < j) {
- lj++;
- while (lj < j) {
- tcg_ctx.gen_opc_instr_start[lj++] = 0;
- }
- }
- tcg_ctx.gen_opc_pc[lj] = ctx.pc;
- tcg_ctx.gen_opc_instr_start[lj] = 1;
- tcg_ctx.gen_opc_icount[lj] = num_insns;
+ if (unlikely(cpu_breakpoint_test(cs, ctx.pc, BP_ANY))) {
+ tcg_gen_movi_i32(cpu_pc, ctx.pc);
+ gen_helper_debug(cpu_env);
+ ctx.bstate = BS_EXCP;
+ goto done_generating;
}
+
ctx.opcode = cpu_lduw_code(env, ctx.pc);
ctx.pc += decode_opc(cpu, &ctx);
- num_insns++;
+ if (num_insns >= max_insns) {
+ break;
+ }
if (cs->singlestep_enabled) {
break;
}
-
if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0) {
break;
}
@@ -898,29 +885,12 @@ gen_intermediate_code_internal(MoxieCPU *cpu, TranslationBlock *tb,
done_generating:
gen_tb_end(tb, num_insns);
- if (search_pc) {
- j = tcg_op_buf_count();
- lj++;
- while (lj <= j) {
- tcg_ctx.gen_opc_instr_start[lj++] = 0;
- }
- } else {
- tb->size = ctx.pc - pc_start;
- tb->icount = num_insns;
- }
-}
-
-void gen_intermediate_code(CPUMoxieState *env, struct TranslationBlock *tb)
-{
- gen_intermediate_code_internal(moxie_env_get_cpu(env), tb, false);
-}
-
-void gen_intermediate_code_pc(CPUMoxieState *env, struct TranslationBlock *tb)
-{
- gen_intermediate_code_internal(moxie_env_get_cpu(env), tb, true);
+ tb->size = ctx.pc - pc_start;
+ tb->icount = num_insns;
}
-void restore_state_to_opc(CPUMoxieState *env, TranslationBlock *tb, int pc_pos)
+void restore_state_to_opc(CPUMoxieState *env, TranslationBlock *tb,
+ target_ulong *data)
{
- env->pc = tcg_ctx.gen_opc_pc[pc_pos];
+ env->pc = data[0];
}
diff --git a/target-openrisc/cpu.h b/target-openrisc/cpu.h
index 1ff1c9ec2a..eb71607395 100644
--- a/target-openrisc/cpu.h
+++ b/target-openrisc/cpu.h
@@ -360,7 +360,6 @@ int cpu_openrisc_signal_handler(int host_signum, void *pinfo, void *puc);
#define cpu_list cpu_openrisc_list
#define cpu_exec cpu_openrisc_exec
-#define cpu_gen_code cpu_openrisc_gen_code
#define cpu_signal_handler cpu_openrisc_signal_handler
#ifndef CONFIG_USER_ONLY
diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c
index 473556e14a..b66fde18fe 100644
--- a/target-openrisc/translate.c
+++ b/target-openrisc/translate.c
@@ -1618,30 +1618,12 @@ static void disas_openrisc_insn(DisasContext *dc, OpenRISCCPU *cpu)
}
}
-static void check_breakpoint(OpenRISCCPU *cpu, DisasContext *dc)
-{
- CPUState *cs = CPU(cpu);
- CPUBreakpoint *bp;
-
- if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
- QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
- if (bp->pc == dc->pc) {
- tcg_gen_movi_tl(cpu_pc, dc->pc);
- gen_exception(dc, EXCP_DEBUG);
- dc->is_jmp = DISAS_UPDATE;
- }
- }
- }
-}
-
-static inline void gen_intermediate_code_internal(OpenRISCCPU *cpu,
- TranslationBlock *tb,
- int search_pc)
+void gen_intermediate_code(CPUOpenRISCState *env, struct TranslationBlock *tb)
{
+ OpenRISCCPU *cpu = openrisc_env_get_cpu(env);
CPUState *cs = CPU(cpu);
struct DisasContext ctx, *dc = &ctx;
uint32_t pc_start;
- int j, k;
uint32_t next_page_start;
int num_insns;
int max_insns;
@@ -1663,36 +1645,30 @@ static inline void gen_intermediate_code_internal(OpenRISCCPU *cpu,
}
next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
- k = -1;
num_insns = 0;
max_insns = tb->cflags & CF_COUNT_MASK;
if (max_insns == 0) {
max_insns = CF_COUNT_MASK;
}
+ if (max_insns > TCG_MAX_INSNS) {
+ max_insns = TCG_MAX_INSNS;
+ }
gen_tb_start(tb);
do {
- check_breakpoint(cpu, dc);
- if (search_pc) {
- j = tcg_op_buf_count();
- if (k < j) {
- k++;
- while (k < j) {
- tcg_ctx.gen_opc_instr_start[k++] = 0;
- }
- }
- tcg_ctx.gen_opc_pc[k] = dc->pc;
- tcg_ctx.gen_opc_instr_start[k] = 1;
- tcg_ctx.gen_opc_icount[k] = num_insns;
- }
+ tcg_gen_insn_start(dc->pc);
+ num_insns++;
- if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
- tcg_gen_debug_insn_start(dc->pc);
+ if (unlikely(cpu_breakpoint_test(cs, dc->pc, BP_ANY))) {
+ tcg_gen_movi_tl(cpu_pc, dc->pc);
+ gen_exception(dc, EXCP_DEBUG);
+ dc->is_jmp = DISAS_UPDATE;
+ break;
}
- if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) {
+ if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
gen_io_start();
}
dc->ppc = dc->pc - 4;
@@ -1701,7 +1677,6 @@ static inline void gen_intermediate_code_internal(OpenRISCCPU *cpu,
tcg_gen_movi_tl(cpu_npc, dc->npc);
disas_openrisc_insn(dc, cpu);
dc->pc = dc->npc;
- num_insns++;
/* delay slot */
if (dc->delayed_branch) {
dc->delayed_branch--;
@@ -1756,16 +1731,8 @@ static inline void gen_intermediate_code_internal(OpenRISCCPU *cpu,
gen_tb_end(tb, num_insns);
- if (search_pc) {
- j = tcg_op_buf_count();
- k++;
- while (k <= j) {
- tcg_ctx.gen_opc_instr_start[k++] = 0;
- }
- } else {
- tb->size = dc->pc - pc_start;
- tb->icount = num_insns;
- }
+ tb->size = dc->pc - pc_start;
+ tb->icount = num_insns;
#ifdef DEBUG_DISAS
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
@@ -1777,17 +1744,6 @@ static inline void gen_intermediate_code_internal(OpenRISCCPU *cpu,
#endif
}
-void gen_intermediate_code(CPUOpenRISCState *env, struct TranslationBlock *tb)
-{
- gen_intermediate_code_internal(openrisc_env_get_cpu(env), tb, 0);
-}
-
-void gen_intermediate_code_pc(CPUOpenRISCState *env,
- struct TranslationBlock *tb)
-{
- gen_intermediate_code_internal(openrisc_env_get_cpu(env), tb, 1);
-}
-
void openrisc_cpu_dump_state(CPUState *cs, FILE *f,
fprintf_function cpu_fprintf,
int flags)
@@ -1804,7 +1760,7 @@ void openrisc_cpu_dump_state(CPUState *cs, FILE *f,
}
void restore_state_to_opc(CPUOpenRISCState *env, TranslationBlock *tb,
- int pc_pos)
+ target_ulong *data)
{
- env->pc = tcg_ctx.gen_opc_pc[pc_pos];
+ env->pc = data[0];
}
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index c6dbb38fea..98ce5a7ab0 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -1241,7 +1241,6 @@ int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, uint32_t val);
#define cpu_init(cpu_model) CPU(cpu_ppc_init(cpu_model))
#define cpu_exec cpu_ppc_exec
-#define cpu_gen_code cpu_ppc_gen_code
#define cpu_signal_handler cpu_ppc_signal_handler
#define cpu_list ppc_cpu_list
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index c0eed13f98..c2bc1a7ec6 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -11409,17 +11409,13 @@ void ppc_cpu_dump_statistics(CPUState *cs, FILE*f,
}
/*****************************************************************************/
-static inline void gen_intermediate_code_internal(PowerPCCPU *cpu,
- TranslationBlock *tb,
- bool search_pc)
+void gen_intermediate_code(CPUPPCState *env, struct TranslationBlock *tb)
{
+ PowerPCCPU *cpu = ppc_env_get_cpu(env);
CPUState *cs = CPU(cpu);
- CPUPPCState *env = &cpu->env;
DisasContext ctx, *ctxp = &ctx;
opc_handler_t **table, *handler;
target_ulong pc_start;
- CPUBreakpoint *bp;
- int j, lj = -1;
int num_insns;
int max_insns;
@@ -11476,36 +11472,29 @@ static inline void gen_intermediate_code_internal(PowerPCCPU *cpu,
#endif
num_insns = 0;
max_insns = tb->cflags & CF_COUNT_MASK;
- if (max_insns == 0)
+ if (max_insns == 0) {
max_insns = CF_COUNT_MASK;
+ }
+ if (max_insns > TCG_MAX_INSNS) {
+ max_insns = TCG_MAX_INSNS;
+ }
gen_tb_start(tb);
tcg_clear_temp_count();
/* Set env in case of segfault during code fetch */
while (ctx.exception == POWERPC_EXCP_NONE && !tcg_op_buf_full()) {
- if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
- QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
- if (bp->pc == ctx.nip) {
- gen_debug_exception(ctxp);
- break;
- }
- }
- }
- if (unlikely(search_pc)) {
- j = tcg_op_buf_count();
- if (lj < j) {
- lj++;
- while (lj < j)
- tcg_ctx.gen_opc_instr_start[lj++] = 0;
- }
- tcg_ctx.gen_opc_pc[lj] = ctx.nip;
- tcg_ctx.gen_opc_instr_start[lj] = 1;
- tcg_ctx.gen_opc_icount[lj] = num_insns;
+ tcg_gen_insn_start(ctx.nip);
+ num_insns++;
+
+ if (unlikely(cpu_breakpoint_test(cs, ctx.nip, BP_ANY))) {
+ gen_debug_exception(ctxp);
+ break;
}
+
LOG_DISAS("----------------\n");
LOG_DISAS("nip=" TARGET_FMT_lx " super=%d ir=%d\n",
ctx.nip, ctx.mem_idx, (int)msr_ir);
- if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
+ if (num_insns == max_insns && (tb->cflags & CF_LAST_IO))
gen_io_start();
if (unlikely(need_byteswap(&ctx))) {
ctx.opcode = bswap32(cpu_ldl_code(env, ctx.nip));
@@ -11515,12 +11504,8 @@ static inline void gen_intermediate_code_internal(PowerPCCPU *cpu,
LOG_DISAS("translate opcode %08x (%02x %02x %02x) (%s)\n",
ctx.opcode, opc1(ctx.opcode), opc2(ctx.opcode),
opc3(ctx.opcode), ctx.le_mode ? "little" : "big");
- if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
- tcg_gen_debug_insn_start(ctx.nip);
- }
ctx.nip += 4;
table = env->opcodes;
- num_insns++;
handler = table[opc1(ctx.opcode)];
if (is_indirect_opcode(handler)) {
table = ind_table(handler);
@@ -11599,15 +11584,9 @@ static inline void gen_intermediate_code_internal(PowerPCCPU *cpu,
}
gen_tb_end(tb, num_insns);
- if (unlikely(search_pc)) {
- j = tcg_op_buf_count();
- lj++;
- while (lj <= j)
- tcg_ctx.gen_opc_instr_start[lj++] = 0;
- } else {
- tb->size = ctx.nip - pc_start;
- tb->icount = num_insns;
- }
+ tb->size = ctx.nip - pc_start;
+ tb->icount = num_insns;
+
#if defined(DEBUG_DISAS)
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
int flags;
@@ -11620,17 +11599,8 @@ static inline void gen_intermediate_code_internal(PowerPCCPU *cpu,
#endif
}
-void gen_intermediate_code (CPUPPCState *env, struct TranslationBlock *tb)
-{
- gen_intermediate_code_internal(ppc_env_get_cpu(env), tb, false);
-}
-
-void gen_intermediate_code_pc (CPUPPCState *env, struct TranslationBlock *tb)
-{
- gen_intermediate_code_internal(ppc_env_get_cpu(env), tb, true);
-}
-
-void restore_state_to_opc(CPUPPCState *env, TranslationBlock *tb, int pc_pos)
+void restore_state_to_opc(CPUPPCState *env, TranslationBlock *tb,
+ target_ulong *data)
{
- env->nip = tcg_ctx.gen_opc_pc[pc_pos];
+ env->nip = data[0];
}
diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
index 843904bc12..e4de8632f3 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -42,6 +42,7 @@
#include "fpu/softfloat.h"
#define NB_MMU_MODES 3
+#define TARGET_INSN_START_EXTRA_WORDS 1
#define MMU_MODE0_SUFFIX _primary
#define MMU_MODE1_SUFFIX _secondary
@@ -597,7 +598,6 @@ bool css_present(uint8_t cssid);
#define cpu_init(model) CPU(cpu_s390x_init(model))
#define cpu_exec cpu_s390x_exec
-#define cpu_gen_code cpu_s390x_gen_code
#define cpu_signal_handler cpu_s390x_signal_handler
void s390_cpu_list(FILE *f, fprintf_function cpu_fprintf);
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 1151515fa4..05d51fe84a 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -161,8 +161,6 @@ static char cpu_reg_names[32][4];
static TCGv_i64 regs[16];
static TCGv_i64 fregs[16];
-static uint8_t gen_opc_cc_op[OPC_BUF_SIZE];
-
void s390x_translate_init(void)
{
int i;
@@ -5319,18 +5317,14 @@ static ExitStatus translate_one(CPUS390XState *env, DisasContext *s)
return ret;
}
-static inline void gen_intermediate_code_internal(S390CPU *cpu,
- TranslationBlock *tb,
- bool search_pc)
+void gen_intermediate_code(CPUS390XState *env, struct TranslationBlock *tb)
{
+ S390CPU *cpu = s390_env_get_cpu(env);
CPUState *cs = CPU(cpu);
- CPUS390XState *env = &cpu->env;
DisasContext dc;
target_ulong pc_start;
uint64_t next_page_start;
- int j, lj = -1;
int num_insns, max_insns;
- CPUBreakpoint *bp;
ExitStatus status;
bool do_debug;
@@ -5353,41 +5347,27 @@ static inline void gen_intermediate_code_internal(S390CPU *cpu,
if (max_insns == 0) {
max_insns = CF_COUNT_MASK;
}
+ if (max_insns > TCG_MAX_INSNS) {
+ max_insns = TCG_MAX_INSNS;
+ }
gen_tb_start(tb);
do {
- if (search_pc) {
- j = tcg_op_buf_count();
- if (lj < j) {
- lj++;
- while (lj < j) {
- tcg_ctx.gen_opc_instr_start[lj++] = 0;
- }
- }
- tcg_ctx.gen_opc_pc[lj] = dc.pc;
- gen_opc_cc_op[lj] = dc.cc_op;
- tcg_ctx.gen_opc_instr_start[lj] = 1;
- tcg_ctx.gen_opc_icount[lj] = num_insns;
- }
- if (++num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
- gen_io_start();
+ tcg_gen_insn_start(dc.pc, dc.cc_op);
+ num_insns++;
+
+ if (unlikely(cpu_breakpoint_test(cs, dc.pc, BP_ANY))) {
+ status = EXIT_PC_STALE;
+ do_debug = true;
+ break;
}
- if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
- tcg_gen_debug_insn_start(dc.pc);
+ if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
+ gen_io_start();
}
status = NO_EXIT;
- if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
- QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
- if (bp->pc == dc.pc) {
- status = EXIT_PC_STALE;
- do_debug = true;
- break;
- }
- }
- }
if (status == NO_EXIT) {
status = translate_one(env, &dc);
}
@@ -5432,16 +5412,8 @@ static inline void gen_intermediate_code_internal(S390CPU *cpu,
gen_tb_end(tb, num_insns);
- if (search_pc) {
- j = tcg_op_buf_count();
- lj++;
- while (lj <= j) {
- tcg_ctx.gen_opc_instr_start[lj++] = 0;
- }
- } else {
- tb->size = dc.pc - pc_start;
- tb->icount = num_insns;
- }
+ tb->size = dc.pc - pc_start;
+ tb->icount = num_insns;
#if defined(S390X_DEBUG_DISAS)
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
@@ -5452,21 +5424,11 @@ static inline void gen_intermediate_code_internal(S390CPU *cpu,
#endif
}
-void gen_intermediate_code (CPUS390XState *env, struct TranslationBlock *tb)
-{
- gen_intermediate_code_internal(s390_env_get_cpu(env), tb, false);
-}
-
-void gen_intermediate_code_pc (CPUS390XState *env, struct TranslationBlock *tb)
-{
- gen_intermediate_code_internal(s390_env_get_cpu(env), tb, true);
-}
-
-void restore_state_to_opc(CPUS390XState *env, TranslationBlock *tb, int pc_pos)
+void restore_state_to_opc(CPUS390XState *env, TranslationBlock *tb,
+ target_ulong *data)
{
- int cc_op;
- env->psw.addr = tcg_ctx.gen_opc_pc[pc_pos];
- cc_op = gen_opc_cc_op[pc_pos];
+ int cc_op = data[1];
+ env->psw.addr = data[0];
if ((cc_op != CC_OP_DYNAMIC) && (cc_op != CC_OP_STATIC)) {
env->cc_op = cc_op;
}
diff --git a/target-sh4/cpu.h b/target-sh4/cpu.h
index 6fb63215ef..5b022c5973 100644
--- a/target-sh4/cpu.h
+++ b/target-sh4/cpu.h
@@ -120,6 +120,7 @@ typedef struct tlb_t {
#define ITLB_SIZE 4
#define NB_MMU_MODES 2
+#define TARGET_INSN_START_EXTRA_WORDS 1
enum sh_features {
SH_FEATURE_SH4A = 1,
@@ -225,7 +226,6 @@ void cpu_load_tlb(CPUSH4State * env);
#define cpu_init(cpu_model) CPU(cpu_sh4_init(cpu_model))
#define cpu_exec cpu_sh4_exec
-#define cpu_gen_code cpu_sh4_gen_code
#define cpu_signal_handler cpu_sh4_signal_handler
#define cpu_list sh4_cpu_list
diff --git a/target-sh4/translate.c b/target-sh4/translate.c
index 724c0e7106..f764bc2539 100644
--- a/target-sh4/translate.c
+++ b/target-sh4/translate.c
@@ -70,8 +70,6 @@ static TCGv cpu_fregs[32];
/* internal register indexes */
static TCGv cpu_flags, cpu_delayed_pc;
-static uint32_t gen_opc_hflags[OPC_BUF_SIZE];
-
#include "exec/gen-icount.h"
void sh4_translate_init(void)
@@ -1790,10 +1788,6 @@ static void decode_opc(DisasContext * ctx)
{
uint32_t old_flags = ctx->flags;
- if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
- tcg_gen_debug_insn_start(ctx->pc);
- }
-
_decode_opc(ctx);
if (old_flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) {
@@ -1820,16 +1814,12 @@ static void decode_opc(DisasContext * ctx)
gen_store_flags(ctx->flags);
}
-static inline void
-gen_intermediate_code_internal(SuperHCPU *cpu, TranslationBlock *tb,
- bool search_pc)
+void gen_intermediate_code(CPUSH4State * env, struct TranslationBlock *tb)
{
+ SuperHCPU *cpu = sh_env_get_cpu(env);
CPUState *cs = CPU(cpu);
- CPUSH4State *env = &cpu->env;
DisasContext ctx;
target_ulong pc_start;
- CPUBreakpoint *bp;
- int i, ii;
int num_insns;
int max_insns;
@@ -1846,45 +1836,34 @@ gen_intermediate_code_internal(SuperHCPU *cpu, TranslationBlock *tb,
ctx.features = env->features;
ctx.has_movcal = (ctx.flags & TB_FLAG_PENDING_MOVCA);
- ii = -1;
num_insns = 0;
max_insns = tb->cflags & CF_COUNT_MASK;
- if (max_insns == 0)
+ if (max_insns == 0) {
max_insns = CF_COUNT_MASK;
+ }
+ if (max_insns > TCG_MAX_INSNS) {
+ max_insns = TCG_MAX_INSNS;
+ }
+
gen_tb_start(tb);
while (ctx.bstate == BS_NONE && !tcg_op_buf_full()) {
- if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
- QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
- if (ctx.pc == bp->pc) {
- /* We have hit a breakpoint - make sure PC is up-to-date */
- tcg_gen_movi_i32(cpu_pc, ctx.pc);
- gen_helper_debug(cpu_env);
- ctx.bstate = BS_BRANCH;
- break;
- }
- }
- }
- if (search_pc) {
- i = tcg_op_buf_count();
- if (ii < i) {
- ii++;
- while (ii < i)
- tcg_ctx.gen_opc_instr_start[ii++] = 0;
- }
- tcg_ctx.gen_opc_pc[ii] = ctx.pc;
- gen_opc_hflags[ii] = ctx.flags;
- tcg_ctx.gen_opc_instr_start[ii] = 1;
- tcg_ctx.gen_opc_icount[ii] = num_insns;
+ tcg_gen_insn_start(ctx.pc, ctx.flags);
+ num_insns++;
+
+ if (unlikely(cpu_breakpoint_test(cs, ctx.pc, BP_ANY))) {
+ /* We have hit a breakpoint - make sure PC is up-to-date */
+ tcg_gen_movi_i32(cpu_pc, ctx.pc);
+ gen_helper_debug(cpu_env);
+ ctx.bstate = BS_BRANCH;
+ break;
}
- if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
+
+ if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
gen_io_start();
-#if 0
- fprintf(stderr, "Loading opcode at address 0x%08x\n", ctx.pc);
- fflush(stderr);
-#endif
+ }
+
ctx.opcode = cpu_lduw_code(env, ctx.pc);
decode_opc(&ctx);
- num_insns++;
ctx.pc += 2;
if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
break;
@@ -1924,15 +1903,8 @@ gen_intermediate_code_internal(SuperHCPU *cpu, TranslationBlock *tb,
gen_tb_end(tb, num_insns);
- if (search_pc) {
- i = tcg_op_buf_count();
- ii++;
- while (ii <= i)
- tcg_ctx.gen_opc_instr_start[ii++] = 0;
- } else {
- tb->size = ctx.pc - pc_start;
- tb->icount = num_insns;
- }
+ tb->size = ctx.pc - pc_start;
+ tb->icount = num_insns;
#ifdef DEBUG_DISAS
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
@@ -1943,18 +1915,9 @@ gen_intermediate_code_internal(SuperHCPU *cpu, TranslationBlock *tb,
#endif
}
-void gen_intermediate_code(CPUSH4State * env, struct TranslationBlock *tb)
-{
- gen_intermediate_code_internal(sh_env_get_cpu(env), tb, false);
-}
-
-void gen_intermediate_code_pc(CPUSH4State * env, struct TranslationBlock *tb)
-{
- gen_intermediate_code_internal(sh_env_get_cpu(env), tb, true);
-}
-
-void restore_state_to_opc(CPUSH4State *env, TranslationBlock *tb, int pc_pos)
+void restore_state_to_opc(CPUSH4State *env, TranslationBlock *tb,
+ target_ulong *data)
{
- env->pc = tcg_ctx.gen_opc_pc[pc_pos];
- env->flags = gen_opc_hflags[pc_pos];
+ env->pc = data[0];
+ env->flags = data[1];
}
diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h
index 053edd5ed1..9fa770b144 100644
--- a/target-sparc/cpu.h
+++ b/target-sparc/cpu.h
@@ -230,6 +230,7 @@ typedef struct trap_state {
uint32_t tt;
} trap_state;
#endif
+#define TARGET_INSN_START_EXTRA_WORDS 1
typedef struct sparc_def_t {
const char *name;
@@ -592,7 +593,6 @@ int cpu_sparc_signal_handler(int host_signum, void *pinfo, void *puc);
#endif
#define cpu_exec cpu_sparc_exec
-#define cpu_gen_code cpu_sparc_gen_code
#define cpu_signal_handler cpu_sparc_signal_handler
#define cpu_list sparc_cpu_list
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index 4690b4699a..b59742ad2e 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -64,9 +64,6 @@ static TCGv cpu_wim;
/* Floating point registers */
static TCGv_i64 cpu_fpr[TARGET_DPREGS];
-static target_ulong gen_opc_npc[OPC_BUF_SIZE];
-static target_ulong gen_opc_jump_pc[2];
-
#include "exec/gen-icount.h"
typedef struct DisasContext {
@@ -955,17 +952,44 @@ static inline void gen_branch2(DisasContext *dc, target_ulong pc1,
gen_goto_tb(dc, 1, pc2, pc2 + 4);
}
-static inline void gen_branch_a(DisasContext *dc, target_ulong pc1,
- target_ulong pc2, TCGv r_cond)
+static void gen_branch_a(DisasContext *dc, target_ulong pc1)
{
TCGLabel *l1 = gen_new_label();
+ target_ulong npc = dc->npc;
- tcg_gen_brcondi_tl(TCG_COND_EQ, r_cond, 0, l1);
+ tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_cond, 0, l1);
- gen_goto_tb(dc, 0, pc2, pc1);
+ gen_goto_tb(dc, 0, npc, pc1);
gen_set_label(l1);
- gen_goto_tb(dc, 1, pc2 + 4, pc2 + 8);
+ gen_goto_tb(dc, 1, npc + 4, npc + 8);
+
+ dc->is_br = 1;
+}
+
+static void gen_branch_n(DisasContext *dc, target_ulong pc1)
+{
+ target_ulong npc = dc->npc;
+
+ if (likely(npc != DYNAMIC_PC)) {
+ dc->pc = npc;
+ dc->jump_pc[0] = pc1;
+ dc->jump_pc[1] = npc + 4;
+ dc->npc = JUMP_PC;
+ } else {
+ TCGv t, z;
+
+ tcg_gen_mov_tl(cpu_pc, cpu_npc);
+
+ tcg_gen_addi_tl(cpu_npc, cpu_npc, 4);
+ t = tcg_const_tl(pc1);
+ z = tcg_const_tl(0);
+ tcg_gen_movcond_tl(TCG_COND_NE, cpu_npc, cpu_cond, z, t, cpu_npc);
+ tcg_temp_free(t);
+ tcg_temp_free(z);
+
+ dc->pc = DYNAMIC_PC;
+ }
}
static inline void gen_generic_branch(DisasContext *dc)
@@ -1398,18 +1422,9 @@ static void do_branch(DisasContext *dc, int32_t offset, uint32_t insn, int cc)
flush_cond(dc);
gen_cond(cpu_cond, cc, cond, dc);
if (a) {
- gen_branch_a(dc, target, dc->npc, cpu_cond);
- dc->is_br = 1;
+ gen_branch_a(dc, target);
} else {
- dc->pc = dc->npc;
- dc->jump_pc[0] = target;
- if (unlikely(dc->npc == DYNAMIC_PC)) {
- dc->jump_pc[1] = DYNAMIC_PC;
- tcg_gen_addi_tl(cpu_pc, cpu_npc, 4);
- } else {
- dc->jump_pc[1] = dc->npc + 4;
- dc->npc = JUMP_PC;
- }
+ gen_branch_n(dc, target);
}
}
}
@@ -1447,18 +1462,9 @@ static void do_fbranch(DisasContext *dc, int32_t offset, uint32_t insn, int cc)
flush_cond(dc);
gen_fcond(cpu_cond, cc, cond);
if (a) {
- gen_branch_a(dc, target, dc->npc, cpu_cond);
- dc->is_br = 1;
+ gen_branch_a(dc, target);
} else {
- dc->pc = dc->npc;
- dc->jump_pc[0] = target;
- if (unlikely(dc->npc == DYNAMIC_PC)) {
- dc->jump_pc[1] = DYNAMIC_PC;
- tcg_gen_addi_tl(cpu_pc, cpu_npc, 4);
- } else {
- dc->jump_pc[1] = dc->npc + 4;
- dc->npc = JUMP_PC;
- }
+ gen_branch_n(dc, target);
}
}
}
@@ -1476,18 +1482,9 @@ static void do_branch_reg(DisasContext *dc, int32_t offset, uint32_t insn,
flush_cond(dc);
gen_cond_reg(cpu_cond, cond, r_reg);
if (a) {
- gen_branch_a(dc, target, dc->npc, cpu_cond);
- dc->is_br = 1;
+ gen_branch_a(dc, target);
} else {
- dc->pc = dc->npc;
- dc->jump_pc[0] = target;
- if (unlikely(dc->npc == DYNAMIC_PC)) {
- dc->jump_pc[1] = DYNAMIC_PC;
- tcg_gen_addi_tl(cpu_pc, cpu_npc, 4);
- } else {
- dc->jump_pc[1] = dc->npc + 4;
- dc->npc = JUMP_PC;
- }
+ gen_branch_n(dc, target);
}
}
@@ -2482,10 +2479,6 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
TCGv_i64 cpu_src1_64, cpu_src2_64, cpu_dst_64;
target_long simm;
- if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
- tcg_gen_debug_insn_start(dc->pc);
- }
-
opc = GET_FIELD(insn, 0, 1);
rd = GET_FIELD(insn, 2, 6);
@@ -5213,16 +5206,12 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
}
}
-static inline void gen_intermediate_code_internal(SPARCCPU *cpu,
- TranslationBlock *tb,
- bool spc)
+void gen_intermediate_code(CPUSPARCState * env, TranslationBlock * tb)
{
+ SPARCCPU *cpu = sparc_env_get_cpu(env);
CPUState *cs = CPU(cpu);
- CPUSPARCState *env = &cpu->env;
target_ulong pc_start, last_pc;
DisasContext dc1, *dc = &dc1;
- CPUBreakpoint *bp;
- int j, lj = -1;
int num_insns;
int max_insns;
unsigned int insn;
@@ -5242,42 +5231,41 @@ static inline void gen_intermediate_code_internal(SPARCCPU *cpu,
num_insns = 0;
max_insns = tb->cflags & CF_COUNT_MASK;
- if (max_insns == 0)
+ if (max_insns == 0) {
max_insns = CF_COUNT_MASK;
+ }
+ if (max_insns > TCG_MAX_INSNS) {
+ max_insns = TCG_MAX_INSNS;
+ }
+
gen_tb_start(tb);
do {
- if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
- QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
- if (bp->pc == dc->pc) {
- if (dc->pc != pc_start)
- save_state(dc);
- gen_helper_debug(cpu_env);
- tcg_gen_exit_tb(0);
- dc->is_br = 1;
- goto exit_gen_loop;
- }
- }
+ if (dc->npc & JUMP_PC) {
+ assert(dc->jump_pc[1] == dc->pc + 4);
+ tcg_gen_insn_start(dc->pc, dc->jump_pc[0] | JUMP_PC);
+ } else {
+ tcg_gen_insn_start(dc->pc, dc->npc);
}
- if (spc) {
- qemu_log("Search PC...\n");
- j = tcg_op_buf_count();
- if (lj < j) {
- lj++;
- while (lj < j)
- tcg_ctx.gen_opc_instr_start[lj++] = 0;
- tcg_ctx.gen_opc_pc[lj] = dc->pc;
- gen_opc_npc[lj] = dc->npc;
- tcg_ctx.gen_opc_instr_start[lj] = 1;
- tcg_ctx.gen_opc_icount[lj] = num_insns;
+ num_insns++;
+
+ if (unlikely(cpu_breakpoint_test(cs, dc->pc, BP_ANY))) {
+ if (dc->pc != pc_start) {
+ save_state(dc);
}
+ gen_helper_debug(cpu_env);
+ tcg_gen_exit_tb(0);
+ dc->is_br = 1;
+ goto exit_gen_loop;
}
- if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
+
+ if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
gen_io_start();
+ }
+
last_pc = dc->pc;
insn = cpu_ldl_code(env, dc->pc);
disas_sparc_insn(dc, insn);
- num_insns++;
if (dc->is_br)
break;
@@ -5316,20 +5304,9 @@ static inline void gen_intermediate_code_internal(SPARCCPU *cpu,
}
gen_tb_end(tb, num_insns);
- if (spc) {
- j = tcg_op_buf_count();
- lj++;
- while (lj <= j)
- tcg_ctx.gen_opc_instr_start[lj++] = 0;
-#if 0
- log_page_dump();
-#endif
- gen_opc_jump_pc[0] = dc->jump_pc[0];
- gen_opc_jump_pc[1] = dc->jump_pc[1];
- } else {
- tb->size = last_pc + 4 - pc_start;
- tb->icount = num_insns;
- }
+ tb->size = last_pc + 4 - pc_start;
+ tb->icount = num_insns;
+
#ifdef DEBUG_DISAS
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
qemu_log("--------------\n");
@@ -5340,16 +5317,6 @@ static inline void gen_intermediate_code_internal(SPARCCPU *cpu,
#endif
}
-void gen_intermediate_code(CPUSPARCState * env, TranslationBlock * tb)
-{
- gen_intermediate_code_internal(sparc_env_get_cpu(env), tb, false);
-}
-
-void gen_intermediate_code_pc(CPUSPARCState * env, TranslationBlock * tb)
-{
- gen_intermediate_code_internal(sparc_env_get_cpu(env), tb, true);
-}
-
void gen_intermediate_code_init(CPUSPARCState *env)
{
unsigned int i;
@@ -5451,19 +5418,21 @@ void gen_intermediate_code_init(CPUSPARCState *env)
}
}
-void restore_state_to_opc(CPUSPARCState *env, TranslationBlock *tb, int pc_pos)
+void restore_state_to_opc(CPUSPARCState *env, TranslationBlock *tb,
+ target_ulong *data)
{
- target_ulong npc;
- env->pc = tcg_ctx.gen_opc_pc[pc_pos];
- npc = gen_opc_npc[pc_pos];
- if (npc == 1) {
+ target_ulong pc = data[0];
+ target_ulong npc = data[1];
+
+ env->pc = pc;
+ if (npc == DYNAMIC_PC) {
/* dynamic NPC: already stored */
- } else if (npc == 2) {
+ } else if (npc & JUMP_PC) {
/* jump PC: use 'cond' and the jump targets of the translation */
if (env->cond) {
- env->npc = gen_opc_jump_pc[0];
+ env->npc = npc & ~3;
} else {
- env->npc = gen_opc_jump_pc[1];
+ env->npc = pc + 4;
}
} else {
env->npc = npc;
diff --git a/target-tilegx/cpu.h b/target-tilegx/cpu.h
index 6c0fd5365d..03df107a67 100644
--- a/target-tilegx/cpu.h
+++ b/target-tilegx/cpu.h
@@ -167,7 +167,6 @@ TileGXCPU *cpu_tilegx_init(const char *cpu_model);
#define cpu_init(cpu_model) CPU(cpu_tilegx_init(cpu_model))
#define cpu_exec cpu_tilegx_exec
-#define cpu_gen_code cpu_tilegx_gen_code
#define cpu_signal_handler cpu_tilegx_signal_handler
static inline void cpu_get_tb_cpu_state(CPUTLGState *env, target_ulong *pc,
diff --git a/target-tilegx/translate.c b/target-tilegx/translate.c
index acb9ec480c..34d45f87b9 100644
--- a/target-tilegx/translate.c
+++ b/target-tilegx/translate.c
@@ -2320,10 +2320,6 @@ static void translate_one_bundle(DisasContext *dc, uint64_t bundle)
}
dc->num_wb = 0;
- if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
- tcg_gen_debug_insn_start(dc->pc);
- }
-
qemu_log_mask(CPU_LOG_TB_IN_ASM, " %" PRIx64 ": { ", dc->pc);
if (get_Mode(bundle)) {
notice_excp(dc, bundle, "y0", decode_y0(dc, bundle));
@@ -2365,17 +2361,14 @@ static void translate_one_bundle(DisasContext *dc, uint64_t bundle)
}
}
-static inline void gen_intermediate_code_internal(TileGXCPU *cpu,
- TranslationBlock *tb,
- bool search_pc)
+void gen_intermediate_code(CPUTLGState *env, struct TranslationBlock *tb)
{
+ TileGXCPU *cpu = tilegx_env_get_cpu(env);
DisasContext ctx;
DisasContext *dc = &ctx;
CPUState *cs = CPU(cpu);
- CPUTLGState *env = &cpu->env;
uint64_t pc_start = tb->pc;
uint64_t next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
- int j, lj = -1;
int num_insns = 0;
int max_insns = tb->cflags & CF_COUNT_MASK;
@@ -2397,21 +2390,15 @@ static inline void gen_intermediate_code_internal(TileGXCPU *cpu,
if (cs->singlestep_enabled || singlestep) {
max_insns = 1;
}
+ if (max_insns > TCG_MAX_INSNS) {
+ max_insns = TCG_MAX_INSNS;
+ }
gen_tb_start(tb);
while (1) {
- if (search_pc) {
- j = tcg_op_buf_count();
- if (lj < j) {
- lj++;
- while (lj < j) {
- tcg_ctx.gen_opc_instr_start[lj++] = 0;
- }
- }
- tcg_ctx.gen_opc_pc[lj] = dc->pc;
- tcg_ctx.gen_opc_instr_start[lj] = 1;
- tcg_ctx.gen_opc_icount[lj] = num_insns;
- }
+ tcg_gen_insn_start(dc->pc);
+ num_insns++;
+
translate_one_bundle(dc, cpu_ldq_data(env, dc->pc));
if (dc->exit_tb) {
@@ -2419,7 +2406,7 @@ static inline void gen_intermediate_code_internal(TileGXCPU *cpu,
break;
}
dc->pc += TILEGX_BUNDLE_SIZE_IN_BYTES;
- if (++num_insns >= max_insns
+ if (num_insns >= max_insns
|| dc->pc >= next_page_start
|| tcg_op_buf_full()) {
/* Ending the TB due to TB size or page boundary. Set PC. */
@@ -2430,33 +2417,16 @@ static inline void gen_intermediate_code_internal(TileGXCPU *cpu,
}
gen_tb_end(tb, num_insns);
- if (search_pc) {
- j = tcg_op_buf_count();
- lj++;
- while (lj <= j) {
- tcg_ctx.gen_opc_instr_start[lj++] = 0;
- }
- } else {
- tb->size = dc->pc - pc_start;
- tb->icount = num_insns;
- }
+ tb->size = dc->pc - pc_start;
+ tb->icount = num_insns;
qemu_log_mask(CPU_LOG_TB_IN_ASM, "\n");
}
-void gen_intermediate_code(CPUTLGState *env, struct TranslationBlock *tb)
-{
- gen_intermediate_code_internal(tilegx_env_get_cpu(env), tb, false);
-}
-
-void gen_intermediate_code_pc(CPUTLGState *env, struct TranslationBlock *tb)
-{
- gen_intermediate_code_internal(tilegx_env_get_cpu(env), tb, true);
-}
-
-void restore_state_to_opc(CPUTLGState *env, TranslationBlock *tb, int pc_pos)
+void restore_state_to_opc(CPUTLGState *env, TranslationBlock *tb,
+ target_ulong *data)
{
- env->pc = tcg_ctx.gen_opc_pc[pc_pos];
+ env->pc = data[0];
}
void tilegx_tcg_init(void)
diff --git a/target-tricore/translate.c b/target-tricore/translate.c
index 440f30a843..135c58347a 100644
--- a/target-tricore/translate.c
+++ b/target-tricore/translate.c
@@ -8266,21 +8266,26 @@ static void decode_opc(CPUTriCoreState *env, DisasContext *ctx, int *is_branch)
}
}
-static inline void
-gen_intermediate_code_internal(TriCoreCPU *cpu, struct TranslationBlock *tb,
- int search_pc)
+void gen_intermediate_code(CPUTriCoreState *env, struct TranslationBlock *tb)
{
+ TriCoreCPU *cpu = tricore_env_get_cpu(env);
CPUState *cs = CPU(cpu);
- CPUTriCoreState *env = &cpu->env;
DisasContext ctx;
target_ulong pc_start;
- int num_insns;
+ int num_insns, max_insns;
- if (search_pc) {
- qemu_log("search pc %d\n", search_pc);
+ num_insns = 0;
+ max_insns = tb->cflags & CF_COUNT_MASK;
+ if (max_insns == 0) {
+ max_insns = CF_COUNT_MASK;
+ }
+ if (singlestep) {
+ max_insns = 1;
+ }
+ if (max_insns > TCG_MAX_INSNS) {
+ max_insns = TCG_MAX_INSNS;
}
- num_insns = 0;
pc_start = tb->pc;
ctx.pc = pc_start;
ctx.saved_pc = -1;
@@ -8292,17 +8297,13 @@ gen_intermediate_code_internal(TriCoreCPU *cpu, struct TranslationBlock *tb,
tcg_clear_temp_count();
gen_tb_start(tb);
while (ctx.bstate == BS_NONE) {
+ tcg_gen_insn_start(ctx.pc);
+ num_insns++;
+
ctx.opcode = cpu_ldl_code(env, ctx.pc);
decode_opc(env, &ctx, 0);
- num_insns++;
-
- if (tcg_op_buf_full()) {
- gen_save_pc(ctx.next_pc);
- tcg_gen_exit_tb(0);
- break;
- }
- if (singlestep) {
+ if (num_insns >= max_insns || tcg_op_buf_full()) {
gen_save_pc(ctx.next_pc);
tcg_gen_exit_tb(0);
break;
@@ -8311,12 +8312,9 @@ gen_intermediate_code_internal(TriCoreCPU *cpu, struct TranslationBlock *tb,
}
gen_tb_end(tb, num_insns);
- if (search_pc) {
- printf("done_generating search pc\n");
- } else {
- tb->size = ctx.pc - pc_start;
- tb->icount = num_insns;
- }
+ tb->size = ctx.pc - pc_start;
+ tb->icount = num_insns;
+
if (tcg_check_temp_count()) {
printf("LEAK at %08x\n", env->PC);
}
@@ -8331,21 +8329,10 @@ gen_intermediate_code_internal(TriCoreCPU *cpu, struct TranslationBlock *tb,
}
void
-gen_intermediate_code(CPUTriCoreState *env, struct TranslationBlock *tb)
-{
- gen_intermediate_code_internal(tricore_env_get_cpu(env), tb, false);
-}
-
-void
-gen_intermediate_code_pc(CPUTriCoreState *env, struct TranslationBlock *tb)
-{
- gen_intermediate_code_internal(tricore_env_get_cpu(env), tb, true);
-}
-
-void
-restore_state_to_opc(CPUTriCoreState *env, TranslationBlock *tb, int pc_pos)
+restore_state_to_opc(CPUTriCoreState *env, TranslationBlock *tb,
+ target_ulong *data)
{
- env->PC = tcg_ctx.gen_opc_pc[pc_pos];
+ env->PC = data[0];
}
/*
*
diff --git a/target-unicore32/translate.c b/target-unicore32/translate.c
index 2fc78e6f3e..48f89fb1c5 100644
--- a/target-unicore32/translate.c
+++ b/target-unicore32/translate.c
@@ -1794,10 +1794,6 @@ static void disas_uc32_insn(CPUUniCore32State *env, DisasContext *s)
UniCore32CPU *cpu = uc32_env_get_cpu(env);
unsigned int insn;
- if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
- tcg_gen_debug_insn_start(s->pc);
- }
-
insn = cpu_ldl_code(env, s->pc);
s->pc += 4;
@@ -1868,16 +1864,12 @@ static void disas_uc32_insn(CPUUniCore32State *env, DisasContext *s)
}
/* generate intermediate code in gen_opc_buf and gen_opparam_buf for
- basic block 'tb'. If search_pc is TRUE, also generate PC
- information for each intermediate instruction. */
-static inline void gen_intermediate_code_internal(UniCore32CPU *cpu,
- TranslationBlock *tb, bool search_pc)
+ basic block 'tb'. */
+void gen_intermediate_code(CPUUniCore32State *env, TranslationBlock *tb)
{
+ UniCore32CPU *cpu = uc32_env_get_cpu(env);
CPUState *cs = CPU(cpu);
- CPUUniCore32State *env = &cpu->env;
DisasContext dc1, *dc = &dc1;
- CPUBreakpoint *bp;
- int j, lj;
target_ulong pc_start;
uint32_t next_page_start;
int num_insns;
@@ -1899,12 +1891,14 @@ static inline void gen_intermediate_code_internal(UniCore32CPU *cpu,
cpu_F0d = tcg_temp_new_i64();
cpu_F1d = tcg_temp_new_i64();
next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
- lj = -1;
num_insns = 0;
max_insns = tb->cflags & CF_COUNT_MASK;
if (max_insns == 0) {
max_insns = CF_COUNT_MASK;
}
+ if (max_insns > TCG_MAX_INSNS) {
+ max_insns = TCG_MAX_INSNS;
+ }
#ifndef CONFIG_USER_ONLY
if ((env->uncached_asr & ASR_M) == ASR_MODE_USER) {
@@ -1916,33 +1910,20 @@ static inline void gen_intermediate_code_internal(UniCore32CPU *cpu,
gen_tb_start(tb);
do {
- if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
- QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
- if (bp->pc == dc->pc) {
- gen_set_pc_im(dc->pc);
- gen_exception(EXCP_DEBUG);
- dc->is_jmp = DISAS_JUMP;
- /* Advance PC so that clearing the breakpoint will
- invalidate this TB. */
- dc->pc += 2; /* FIXME */
- goto done_generating;
- }
- }
- }
- if (search_pc) {
- j = tcg_op_buf_count();
- if (lj < j) {
- lj++;
- while (lj < j) {
- tcg_ctx.gen_opc_instr_start[lj++] = 0;
- }
- }
- tcg_ctx.gen_opc_pc[lj] = dc->pc;
- tcg_ctx.gen_opc_instr_start[lj] = 1;
- tcg_ctx.gen_opc_icount[lj] = num_insns;
+ tcg_gen_insn_start(dc->pc);
+ num_insns++;
+
+ if (unlikely(cpu_breakpoint_test(cs, dc->pc, BP_ANY))) {
+ gen_set_pc_im(dc->pc);
+ gen_exception(EXCP_DEBUG);
+ dc->is_jmp = DISAS_JUMP;
+ /* Advance PC so that clearing the breakpoint will
+ invalidate this TB. */
+ dc->pc += 2; /* FIXME */
+ goto done_generating;
}
- if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) {
+ if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
gen_io_start();
}
@@ -1961,7 +1942,6 @@ static inline void gen_intermediate_code_internal(UniCore32CPU *cpu,
* Otherwise the subsequent code could get translated several times.
* Also stop translation when a page boundary is reached. This
* ensures prefetch aborts occur at the right place. */
- num_insns++;
} while (!dc->is_jmp && !tcg_op_buf_full() &&
!cs->singlestep_enabled &&
!singlestep &&
@@ -2043,26 +2023,8 @@ done_generating:
qemu_log("\n");
}
#endif
- if (search_pc) {
- j = tcg_op_buf_count();
- lj++;
- while (lj <= j) {
- tcg_ctx.gen_opc_instr_start[lj++] = 0;
- }
- } else {
- tb->size = dc->pc - pc_start;
- tb->icount = num_insns;
- }
-}
-
-void gen_intermediate_code(CPUUniCore32State *env, TranslationBlock *tb)
-{
- gen_intermediate_code_internal(uc32_env_get_cpu(env), tb, false);
-}
-
-void gen_intermediate_code_pc(CPUUniCore32State *env, TranslationBlock *tb)
-{
- gen_intermediate_code_internal(uc32_env_get_cpu(env), tb, true);
+ tb->size = dc->pc - pc_start;
+ tb->icount = num_insns;
}
static const char *cpu_mode_names[16] = {
@@ -2133,7 +2095,8 @@ void uc32_cpu_dump_state(CPUState *cs, FILE *f,
cpu_dump_state_ucf64(env, f, cpu_fprintf, flags);
}
-void restore_state_to_opc(CPUUniCore32State *env, TranslationBlock *tb, int pc_pos)
+void restore_state_to_opc(CPUUniCore32State *env, TranslationBlock *tb,
+ target_ulong *data)
{
- env->regs[31] = tcg_ctx.gen_opc_pc[pc_pos];
+ env->regs[31] = data[0];
}
diff --git a/target-xtensa/cpu.h b/target-xtensa/cpu.h
index 148a0f8d92..006bcb78b8 100644
--- a/target-xtensa/cpu.h
+++ b/target-xtensa/cpu.h
@@ -382,7 +382,6 @@ typedef struct CPUXtensaState {
#include "cpu-qom.h"
#define cpu_exec cpu_xtensa_exec
-#define cpu_gen_code cpu_xtensa_gen_code
#define cpu_signal_handler cpu_xtensa_signal_handler
#define cpu_list xtensa_cpu_list
diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index a29b3e61bc..fda91b7e5d 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -2984,22 +2984,6 @@ static inline unsigned xtensa_insn_len(CPUXtensaState *env, DisasContext *dc)
return xtensa_op0_insn_len(OP0);
}
-static void check_breakpoint(CPUXtensaState *env, DisasContext *dc)
-{
- CPUState *cs = CPU(xtensa_env_get_cpu(env));
- CPUBreakpoint *bp;
-
- if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
- QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
- if (bp->pc == dc->pc) {
- tcg_gen_movi_i32(cpu_pc, dc->pc);
- gen_exception(dc, EXCP_DEBUG);
- dc->is_jmp = DISAS_UPDATE;
- }
- }
- }
-}
-
static void gen_ibreak_check(CPUXtensaState *env, DisasContext *dc)
{
unsigned i;
@@ -3013,15 +2997,12 @@ static void gen_ibreak_check(CPUXtensaState *env, DisasContext *dc)
}
}
-static inline
-void gen_intermediate_code_internal(XtensaCPU *cpu,
- TranslationBlock *tb, bool search_pc)
+void gen_intermediate_code(CPUXtensaState *env, TranslationBlock *tb)
{
+ XtensaCPU *cpu = xtensa_env_get_cpu(env);
CPUState *cs = CPU(cpu);
- CPUXtensaState *env = &cpu->env;
DisasContext dc;
int insn_count = 0;
- int j, lj = -1;
int max_insns = tb->cflags & CF_COUNT_MASK;
uint32_t pc_start = tb->pc;
uint32_t next_page_start =
@@ -3030,6 +3011,9 @@ void gen_intermediate_code_internal(XtensaCPU *cpu,
if (max_insns == 0) {
max_insns = CF_COUNT_MASK;
}
+ if (max_insns > TCG_MAX_INSNS) {
+ max_insns = TCG_MAX_INSNS;
+ }
dc.config = env->config;
dc.singlestep_enabled = cs->singlestep_enabled;
@@ -3062,28 +3046,19 @@ void gen_intermediate_code_internal(XtensaCPU *cpu,
}
do {
- check_breakpoint(env, &dc);
+ tcg_gen_insn_start(dc.pc);
+ ++insn_count;
- if (search_pc) {
- j = tcg_op_buf_count();
- if (lj < j) {
- lj++;
- while (lj < j) {
- tcg_ctx.gen_opc_instr_start[lj++] = 0;
- }
- }
- tcg_ctx.gen_opc_pc[lj] = dc.pc;
- tcg_ctx.gen_opc_instr_start[lj] = 1;
- tcg_ctx.gen_opc_icount[lj] = insn_count;
- }
+ ++dc.ccount_delta;
- if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
- tcg_gen_debug_insn_start(dc.pc);
+ if (unlikely(cpu_breakpoint_test(cs, dc.pc, BP_ANY))) {
+ tcg_gen_movi_i32(cpu_pc, dc.pc);
+ gen_exception(&dc, EXCP_DEBUG);
+ dc.is_jmp = DISAS_UPDATE;
+ break;
}
- ++dc.ccount_delta;
-
- if (insn_count + 1 == max_insns && (tb->cflags & CF_LAST_IO)) {
+ if (insn_count == max_insns && (tb->cflags & CF_LAST_IO)) {
gen_io_start();
}
@@ -3104,7 +3079,6 @@ void gen_intermediate_code_internal(XtensaCPU *cpu,
}
disas_xtensa_insn(env, &dc);
- ++insn_count;
if (dc.icount) {
tcg_gen_mov_i32(cpu_SR[ICOUNT], dc.next_icount);
}
@@ -3142,24 +3116,8 @@ void gen_intermediate_code_internal(XtensaCPU *cpu,
qemu_log("\n");
}
#endif
- if (search_pc) {
- j = tcg_op_buf_count();
- memset(tcg_ctx.gen_opc_instr_start + lj + 1, 0,
- (j - lj) * sizeof(tcg_ctx.gen_opc_instr_start[0]));
- } else {
- tb->size = dc.pc - pc_start;
- tb->icount = insn_count;
- }
-}
-
-void gen_intermediate_code(CPUXtensaState *env, TranslationBlock *tb)
-{
- gen_intermediate_code_internal(xtensa_env_get_cpu(env), tb, false);
-}
-
-void gen_intermediate_code_pc(CPUXtensaState *env, TranslationBlock *tb)
-{
- gen_intermediate_code_internal(xtensa_env_get_cpu(env), tb, true);
+ tb->size = dc.pc - pc_start;
+ tb->icount = insn_count;
}
void xtensa_cpu_dump_state(CPUState *cs, FILE *f,
@@ -3213,7 +3171,8 @@ void xtensa_cpu_dump_state(CPUState *cs, FILE *f,
}
}
-void restore_state_to_opc(CPUXtensaState *env, TranslationBlock *tb, int pc_pos)
+void restore_state_to_opc(CPUXtensaState *env, TranslationBlock *tb,
+ target_ulong *data)
{
- env->pc = tcg_ctx.gen_opc_pc[pc_pos];
+ env->pc = data[0];
}
diff --git a/tcg/tcg-op.h b/tcg/tcg-op.h
index 6da083a1e9..4e20dc1a6b 100644
--- a/tcg/tcg-op.h
+++ b/tcg/tcg-op.h
@@ -700,17 +700,53 @@ static inline void tcg_gen_concat32_i64(TCGv_i64 ret, TCGv_i64 lo, TCGv_i64 hi)
#error must include QEMU headers
#endif
-/* debug info: write the PC of the corresponding QEMU CPU instruction */
-static inline void tcg_gen_debug_insn_start(uint64_t pc)
+#if TARGET_INSN_START_WORDS == 1
+# if TARGET_LONG_BITS <= TCG_TARGET_REG_BITS
+static inline void tcg_gen_insn_start(target_ulong pc)
{
- /* XXX: must really use a 32 bit size for TCGArg in all cases */
-#if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
- tcg_gen_op2ii(INDEX_op_debug_insn_start,
- (uint32_t)(pc), (uint32_t)(pc >> 32));
+ tcg_gen_op1(&tcg_ctx, INDEX_op_insn_start, pc);
+}
+# else
+static inline void tcg_gen_insn_start(target_ulong pc)
+{
+ tcg_gen_op2(&tcg_ctx, INDEX_op_insn_start,
+ (uint32_t)pc, (uint32_t)(pc >> 32));
+}
+# endif
+#elif TARGET_INSN_START_WORDS == 2
+# if TARGET_LONG_BITS <= TCG_TARGET_REG_BITS
+static inline void tcg_gen_insn_start(target_ulong pc, target_ulong a1)
+{
+ tcg_gen_op2(&tcg_ctx, INDEX_op_insn_start, pc, a1);
+}
+# else
+static inline void tcg_gen_insn_start(target_ulong pc, target_ulong a1)
+{
+ tcg_gen_op4(&tcg_ctx, INDEX_op_insn_start,
+ (uint32_t)pc, (uint32_t)(pc >> 32),
+ (uint32_t)a1, (uint32_t)(a1 >> 32));
+}
+# endif
+#elif TARGET_INSN_START_WORDS == 3
+# if TARGET_LONG_BITS <= TCG_TARGET_REG_BITS
+static inline void tcg_gen_insn_start(target_ulong pc, target_ulong a1,
+ target_ulong a2)
+{
+ tcg_gen_op3(&tcg_ctx, INDEX_op_insn_start, pc, a1, a2);
+}
+# else
+static inline void tcg_gen_insn_start(target_ulong pc, target_ulong a1,
+ target_ulong a2)
+{
+ tcg_gen_op6(&tcg_ctx, INDEX_op_insn_start,
+ (uint32_t)pc, (uint32_t)(pc >> 32),
+ (uint32_t)a1, (uint32_t)(a1 >> 32),
+ (uint32_t)a2, (uint32_t)(a2 >> 32));
+}
+# endif
#else
- tcg_gen_op1i(INDEX_op_debug_insn_start, pc);
+# error "Unhandled number of operands to insn_start"
#endif
-}
static inline void tcg_gen_exit_tb(uintptr_t val)
{
diff --git a/tcg/tcg-opc.h b/tcg/tcg-opc.h
index 02bbf30387..c6f95703eb 100644
--- a/tcg/tcg-opc.h
+++ b/tcg/tcg-opc.h
@@ -175,9 +175,9 @@ DEF(mulsh_i64, 1, 2, 0, IMPL(TCG_TARGET_HAS_mulsh_i64))
/* QEMU specific */
#if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
-DEF(debug_insn_start, 0, 0, 2, TCG_OPF_NOT_PRESENT)
+DEF(insn_start, 0, 0, 2 * TARGET_INSN_START_WORDS, TCG_OPF_NOT_PRESENT)
#else
-DEF(debug_insn_start, 0, 0, 1, TCG_OPF_NOT_PRESENT)
+DEF(insn_start, 0, 0, TARGET_INSN_START_WORDS, TCG_OPF_NOT_PRESENT)
#endif
DEF(exit_tb, 0, 0, 1, TCG_OPF_BB_END)
DEF(goto_tb, 0, 0, 1, TCG_OPF_BB_END)
diff --git a/tcg/tcg.c b/tcg/tcg.c
index a2cb027a14..682af8a7c6 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -363,17 +363,39 @@ void tcg_context_init(TCGContext *s)
void tcg_prologue_init(TCGContext *s)
{
- /* init global prologue and epilogue */
- s->code_buf = s->code_gen_prologue;
- s->code_ptr = s->code_buf;
+ size_t prologue_size, total_size;
+ void *buf0, *buf1;
+
+ /* Put the prologue at the beginning of code_gen_buffer. */
+ buf0 = s->code_gen_buffer;
+ s->code_ptr = buf0;
+ s->code_buf = buf0;
+ s->code_gen_prologue = buf0;
+
+ /* Generate the prologue. */
tcg_target_qemu_prologue(s);
- flush_icache_range((uintptr_t)s->code_buf, (uintptr_t)s->code_ptr);
+ buf1 = s->code_ptr;
+ flush_icache_range((uintptr_t)buf0, (uintptr_t)buf1);
+
+ /* Deduct the prologue from the buffer. */
+ prologue_size = tcg_current_code_size(s);
+ s->code_gen_ptr = buf1;
+ s->code_gen_buffer = buf1;
+ s->code_buf = buf1;
+ total_size = s->code_gen_buffer_size - prologue_size;
+ s->code_gen_buffer_size = total_size;
+
+ /* Compute a high-water mark, at which we voluntarily flush the buffer
+ and start over. The size here is arbitrary, significantly larger
+ than we expect the code generation for any one opcode to require. */
+ s->code_gen_highwater = s->code_gen_buffer + (total_size - 1024);
+
+ tcg_register_jit(s->code_gen_buffer, total_size);
#ifdef DEBUG_DISAS
if (qemu_loglevel_mask(CPU_LOG_TB_OUT_ASM)) {
- size_t size = tcg_current_code_size(s);
- qemu_log("PROLOGUE: [size=%zu]\n", size);
- log_disas(s->code_buf, size);
+ qemu_log("PROLOGUE: [size=%zu]\n", prologue_size);
+ log_disas(buf0, prologue_size);
qemu_log("\n");
qemu_log_flush();
}
@@ -990,17 +1012,18 @@ void tcg_dump_ops(TCGContext *s)
def = &tcg_op_defs[c];
args = &s->gen_opparam_buf[op->args];
- if (c == INDEX_op_debug_insn_start) {
- uint64_t pc;
+ if (c == INDEX_op_insn_start) {
+ qemu_log("%s ----", oi != s->gen_first_op_idx ? "\n" : "");
+
+ for (i = 0; i < TARGET_INSN_START_WORDS; ++i) {
+ target_ulong a;
#if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
- pc = ((uint64_t)args[1] << 32) | args[0];
+ a = ((target_ulong)args[i * 2 + 1] << 32) | args[i * 2];
#else
- pc = args[0];
+ a = args[i];
#endif
- if (oi != s->gen_first_op_idx) {
- qemu_log("\n");
+ qemu_log(" " TARGET_FMT_lx, a);
}
- qemu_log(" ---- 0x%" PRIx64, pc);
} else if (c == INDEX_op_call) {
/* variable number of arguments */
nb_oargs = op->callo;
@@ -1400,7 +1423,7 @@ static void tcg_liveness_analysis(TCGContext *s)
}
}
break;
- case INDEX_op_debug_insn_start:
+ case INDEX_op_insn_start:
break;
case INDEX_op_discard:
/* mark the temporary as dead */
@@ -2289,11 +2312,27 @@ void tcg_dump_op_count(FILE *f, fprintf_function cpu_fprintf)
#endif
-static inline int tcg_gen_code_common(TCGContext *s,
- tcg_insn_unit *gen_code_buf,
- long search_pc)
+int tcg_gen_code(TCGContext *s, tcg_insn_unit *gen_code_buf)
{
- int oi, oi_next;
+ int i, oi, oi_next, num_insns;
+
+#ifdef CONFIG_PROFILER
+ {
+ int n;
+
+ n = s->gen_last_op_idx + 1;
+ s->op_count += n;
+ if (n > s->op_count_max) {
+ s->op_count_max = n;
+ }
+
+ n = s->nb_temps;
+ s->temp_count += n;
+ if (n > s->temp_count_max) {
+ s->temp_count_max = n;
+ }
+ }
+#endif
#ifdef DEBUG_DISAS
if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) {
@@ -2337,6 +2376,7 @@ static inline int tcg_gen_code_common(TCGContext *s,
tcg_out_tb_init(s);
+ num_insns = -1;
for (oi = s->gen_first_op_idx; oi >= 0; oi = oi_next) {
TCGOp * const op = &s->gen_op_buf[oi];
TCGArg * const args = &s->gen_opparam_buf[op->args];
@@ -2359,7 +2399,20 @@ static inline int tcg_gen_code_common(TCGContext *s,
case INDEX_op_movi_i64:
tcg_reg_alloc_movi(s, args, dead_args, sync_args);
break;
- case INDEX_op_debug_insn_start:
+ case INDEX_op_insn_start:
+ if (num_insns >= 0) {
+ s->gen_insn_end_off[num_insns] = tcg_current_code_size(s);
+ }
+ num_insns++;
+ for (i = 0; i < TARGET_INSN_START_WORDS; ++i) {
+ target_ulong a;
+#if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
+ a = ((target_ulong)args[i * 2 + 1] << 32) | args[i * 2];
+#else
+ a = args[i];
+#endif
+ s->gen_insn_data[num_insns][i] = a;
+ }
break;
case INDEX_op_discard:
temp_dead(s, args[0]);
@@ -2383,40 +2436,22 @@ static inline int tcg_gen_code_common(TCGContext *s,
tcg_reg_alloc_op(s, def, opc, args, dead_args, sync_args);
break;
}
- if (search_pc >= 0 && search_pc < tcg_current_code_size(s)) {
- return oi;
- }
#ifndef NDEBUG
check_regs(s);
#endif
+ /* Test for (pending) buffer overflow. The assumption is that any
+ one operation beginning below the high water mark cannot overrun
+ the buffer completely. Thus we can test for overflow after
+ generating code without having to check during generation. */
+ if (unlikely(s->code_gen_ptr > s->code_gen_highwater)) {
+ return -1;
+ }
}
+ tcg_debug_assert(num_insns >= 0);
+ s->gen_insn_end_off[num_insns] = tcg_current_code_size(s);
/* Generate TB finalization at the end of block */
tcg_out_tb_finalize(s);
- return -1;
-}
-
-int tcg_gen_code(TCGContext *s, tcg_insn_unit *gen_code_buf)
-{
-#ifdef CONFIG_PROFILER
- {
- int n;
-
- n = s->gen_last_op_idx + 1;
- s->op_count += n;
- if (n > s->op_count_max) {
- s->op_count_max = n;
- }
-
- n = s->nb_temps;
- s->temp_count += n;
- if (n > s->temp_count_max) {
- s->temp_count_max = n;
- }
- }
-#endif
-
- tcg_gen_code_common(s, gen_code_buf, -1);
/* flush instruction cache */
flush_icache_range((uintptr_t)s->code_buf, (uintptr_t)s->code_ptr);
@@ -2424,38 +2459,30 @@ int tcg_gen_code(TCGContext *s, tcg_insn_unit *gen_code_buf)
return tcg_current_code_size(s);
}
-/* Return the index of the micro operation such as the pc after is <
- offset bytes from the start of the TB. The contents of gen_code_buf must
- not be changed, though writing the same values is ok.
- Return -1 if not found. */
-int tcg_gen_code_search_pc(TCGContext *s, tcg_insn_unit *gen_code_buf,
- long offset)
-{
- return tcg_gen_code_common(s, gen_code_buf, offset);
-}
-
#ifdef CONFIG_PROFILER
void tcg_dump_info(FILE *f, fprintf_function cpu_fprintf)
{
TCGContext *s = &tcg_ctx;
- int64_t tot;
+ int64_t tb_count = s->tb_count;
+ int64_t tb_div_count = tb_count ? tb_count : 1;
+ int64_t tot = s->interm_time + s->code_time;
- tot = s->interm_time + s->code_time;
cpu_fprintf(f, "JIT cycles %" PRId64 " (%0.3f s at 2.4 GHz)\n",
tot, tot / 2.4e9);
cpu_fprintf(f, "translated TBs %" PRId64 " (aborted=%" PRId64 " %0.1f%%)\n",
- s->tb_count,
- s->tb_count1 - s->tb_count,
- s->tb_count1 ? (double)(s->tb_count1 - s->tb_count) / s->tb_count1 * 100.0 : 0);
+ tb_count, s->tb_count1 - tb_count,
+ (double)(s->tb_count1 - s->tb_count)
+ / (s->tb_count1 ? s->tb_count1 : 1) * 100.0);
cpu_fprintf(f, "avg ops/TB %0.1f max=%d\n",
- s->tb_count ? (double)s->op_count / s->tb_count : 0, s->op_count_max);
+ (double)s->op_count / tb_div_count, s->op_count_max);
cpu_fprintf(f, "deleted ops/TB %0.2f\n",
- s->tb_count ?
- (double)s->del_op_count / s->tb_count : 0);
+ (double)s->del_op_count / tb_div_count);
cpu_fprintf(f, "avg temps/TB %0.2f max=%d\n",
- s->tb_count ?
- (double)s->temp_count / s->tb_count : 0,
- s->temp_count_max);
+ (double)s->temp_count / tb_div_count, s->temp_count_max);
+ cpu_fprintf(f, "avg host code/TB %0.1f\n",
+ (double)s->code_out_len / tb_div_count);
+ cpu_fprintf(f, "avg search data/TB %0.1f\n",
+ (double)s->search_out_len / tb_div_count);
cpu_fprintf(f, "cycles/op %0.1f\n",
s->op_count ? (double)tot / s->op_count : 0);
@@ -2463,8 +2490,11 @@ void tcg_dump_info(FILE *f, fprintf_function cpu_fprintf)
s->code_in_len ? (double)tot / s->code_in_len : 0);
cpu_fprintf(f, "cycles/out byte %0.1f\n",
s->code_out_len ? (double)tot / s->code_out_len : 0);
- if (tot == 0)
+ cpu_fprintf(f, "cycles/search byte %0.1f\n",
+ s->search_out_len ? (double)tot / s->search_out_len : 0);
+ if (tot == 0) {
tot = 1;
+ }
cpu_fprintf(f, " gen_interm time %0.1f%%\n",
(double)s->interm_time / tot * 100.0);
cpu_fprintf(f, " gen_code time %0.1f%%\n",
diff --git a/tcg/tcg.h b/tcg/tcg.h
index 879a665012..a696922420 100644
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -129,6 +129,12 @@ typedef uint64_t TCGRegSet;
# error "Missing unsigned widening multiply"
#endif
+#ifndef TARGET_INSN_START_EXTRA_WORDS
+# define TARGET_INSN_START_WORDS 1
+#else
+# define TARGET_INSN_START_WORDS (1 + TARGET_INSN_START_EXTRA_WORDS)
+#endif
+
typedef enum TCGOpcode {
#define DEF(name, oargs, iargs, cargs, flags) INDEX_op_ ## name,
#include "tcg-opc.h"
@@ -188,6 +194,7 @@ typedef struct TCGPool {
#define TCG_POOL_CHUNK_SIZE 32768
#define TCG_MAX_TEMPS 512
+#define TCG_MAX_INSNS 512
/* when the size of the arguments of a called function is smaller than
this value, they are statically allocated in the TB stack frame */
@@ -525,6 +532,7 @@ struct TCGContext {
int64_t del_op_count;
int64_t code_in_len;
int64_t code_out_len;
+ int64_t search_out_len;
int64_t interm_time;
int64_t code_time;
int64_t la_time;
@@ -551,10 +559,11 @@ struct TCGContext {
void *code_gen_prologue;
void *code_gen_buffer;
size_t code_gen_buffer_size;
- /* threshold to flush the translated code buffer */
- size_t code_gen_buffer_max_size;
void *code_gen_ptr;
+ /* Threshold to flush the translated code buffer. */
+ void *code_gen_highwater;
+
TBContext tb_ctx;
/* The TCGBackendData structure is private to tcg-target.c. */
@@ -570,9 +579,8 @@ struct TCGContext {
TCGOp gen_op_buf[OPC_BUF_SIZE];
TCGArg gen_opparam_buf[OPPARAM_BUF_SIZE];
- target_ulong gen_opc_pc[OPC_BUF_SIZE];
- uint16_t gen_opc_icount[OPC_BUF_SIZE];
- uint8_t gen_opc_instr_start[OPC_BUF_SIZE];
+ uint16_t gen_insn_end_off[TCG_MAX_INSNS];
+ target_ulong gen_insn_data[TCG_MAX_INSNS][TARGET_INSN_START_WORDS];
};
extern TCGContext tcg_ctx;
@@ -619,8 +627,6 @@ void tcg_prologue_init(TCGContext *s);
void tcg_func_start(TCGContext *s);
int tcg_gen_code(TCGContext *s, tcg_insn_unit *gen_code_buf);
-int tcg_gen_code_search_pc(TCGContext *s, tcg_insn_unit *gen_code_buf,
- long offset);
void tcg_set_frame(TCGContext *s, int reg, intptr_t start, intptr_t size);
diff --git a/tci.c b/tci.c
index 70eaab25eb..b5ed7b1f7a 100644
--- a/tci.c
+++ b/tci.c
@@ -1081,15 +1081,6 @@ uintptr_t tcg_qemu_tb_exec(CPUArchState *env, uint8_t *tb_ptr)
/* QEMU specific operations. */
-#if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
- case INDEX_op_debug_insn_start:
- TODO();
- break;
-#else
- case INDEX_op_debug_insn_start:
- TODO();
- break;
-#endif
case INDEX_op_exit_tb:
next_tb = *(uint64_t *)tb_ptr;
goto exit;
diff --git a/translate-all.c b/translate-all.c
index 4a9ee33dac..333eba4f5d 100644
--- a/translate-all.c
+++ b/translate-all.c
@@ -168,127 +168,137 @@ void cpu_gen_init(void)
tcg_context_init(&tcg_ctx);
}
-/* return non zero if the very first instruction is invalid so that
- * the virtual CPU can trigger an exception.
- *
- * '*gen_code_size_ptr' contains the size of the generated code (host
- * code).
- *
- * Called with mmap_lock held for user-mode emulation.
- */
-int cpu_gen_code(CPUArchState *env, TranslationBlock *tb, int *gen_code_size_ptr)
+/* Encode VAL as a signed leb128 sequence at P.
+ Return P incremented past the encoded value. */
+static uint8_t *encode_sleb128(uint8_t *p, target_long val)
{
- TCGContext *s = &tcg_ctx;
- tcg_insn_unit *gen_code_buf;
- int gen_code_size;
-#ifdef CONFIG_PROFILER
- int64_t ti;
-#endif
+ int more, byte;
+
+ do {
+ byte = val & 0x7f;
+ val >>= 7;
+ more = !((val == 0 && (byte & 0x40) == 0)
+ || (val == -1 && (byte & 0x40) != 0));
+ if (more) {
+ byte |= 0x80;
+ }
+ *p++ = byte;
+ } while (more);
-#ifdef CONFIG_PROFILER
- s->tb_count1++; /* includes aborted translations because of
- exceptions */
- ti = profile_getclock();
-#endif
- tcg_func_start(s);
+ return p;
+}
- gen_intermediate_code(env, tb);
+/* Decode a signed leb128 sequence at *PP; increment *PP past the
+ decoded value. Return the decoded value. */
+static target_long decode_sleb128(uint8_t **pp)
+{
+ uint8_t *p = *pp;
+ target_long val = 0;
+ int byte, shift = 0;
- trace_translate_block(tb, tb->pc, tb->tc_ptr);
+ do {
+ byte = *p++;
+ val |= (target_ulong)(byte & 0x7f) << shift;
+ shift += 7;
+ } while (byte & 0x80);
+ if (shift < TARGET_LONG_BITS && (byte & 0x40)) {
+ val |= -(target_ulong)1 << shift;
+ }
- /* generate machine code */
- gen_code_buf = tb->tc_ptr;
- tb->tb_next_offset[0] = 0xffff;
- tb->tb_next_offset[1] = 0xffff;
- s->tb_next_offset = tb->tb_next_offset;
-#ifdef USE_DIRECT_JUMP
- s->tb_jmp_offset = tb->tb_jmp_offset;
- s->tb_next = NULL;
-#else
- s->tb_jmp_offset = NULL;
- s->tb_next = tb->tb_next;
-#endif
+ *pp = p;
+ return val;
+}
-#ifdef CONFIG_PROFILER
- s->tb_count++;
- s->interm_time += profile_getclock() - ti;
- s->code_time -= profile_getclock();
-#endif
- gen_code_size = tcg_gen_code(s, gen_code_buf);
- *gen_code_size_ptr = gen_code_size;
-#ifdef CONFIG_PROFILER
- s->code_time += profile_getclock();
- s->code_in_len += tb->size;
- s->code_out_len += gen_code_size;
-#endif
+/* Encode the data collected about the instructions while compiling TB.
+ Place the data at BLOCK, and return the number of bytes consumed.
-#ifdef DEBUG_DISAS
- if (qemu_loglevel_mask(CPU_LOG_TB_OUT_ASM)) {
- qemu_log("OUT: [size=%d]\n", gen_code_size);
- log_disas(tb->tc_ptr, gen_code_size);
- qemu_log("\n");
- qemu_log_flush();
+ The logical table consisits of TARGET_INSN_START_WORDS target_ulong's,
+ which come from the target's insn_start data, followed by a uintptr_t
+ which comes from the host pc of the end of the code implementing the insn.
+
+ Each line of the table is encoded as sleb128 deltas from the previous
+ line. The seed for the first line is { tb->pc, 0..., tb->tc_ptr }.
+ That is, the first column is seeded with the guest pc, the last column
+ with the host pc, and the middle columns with zeros. */
+
+static int encode_search(TranslationBlock *tb, uint8_t *block)
+{
+ uint8_t *highwater = tcg_ctx.code_gen_highwater;
+ uint8_t *p = block;
+ int i, j, n;
+
+ tb->tc_search = block;
+
+ for (i = 0, n = tb->icount; i < n; ++i) {
+ target_ulong prev;
+
+ for (j = 0; j < TARGET_INSN_START_WORDS; ++j) {
+ if (i == 0) {
+ prev = (j == 0 ? tb->pc : 0);
+ } else {
+ prev = tcg_ctx.gen_insn_data[i - 1][j];
+ }
+ p = encode_sleb128(p, tcg_ctx.gen_insn_data[i][j] - prev);
+ }
+ prev = (i == 0 ? 0 : tcg_ctx.gen_insn_end_off[i - 1]);
+ p = encode_sleb128(p, tcg_ctx.gen_insn_end_off[i] - prev);
+
+ /* Test for (pending) buffer overflow. The assumption is that any
+ one row beginning below the high water mark cannot overrun
+ the buffer completely. Thus we can test for overflow after
+ encoding a row without having to check during encoding. */
+ if (unlikely(p > highwater)) {
+ return -1;
+ }
}
-#endif
- return 0;
+
+ return p - block;
}
-/* The cpu state corresponding to 'searched_pc' is restored.
- */
+/* The cpu state corresponding to 'searched_pc' is restored. */
static int cpu_restore_state_from_tb(CPUState *cpu, TranslationBlock *tb,
uintptr_t searched_pc)
{
+ target_ulong data[TARGET_INSN_START_WORDS] = { tb->pc };
+ uintptr_t host_pc = (uintptr_t)tb->tc_ptr;
CPUArchState *env = cpu->env_ptr;
- TCGContext *s = &tcg_ctx;
- int j;
- uintptr_t tc_ptr;
+ uint8_t *p = tb->tc_search;
+ int i, j, num_insns = tb->icount;
#ifdef CONFIG_PROFILER
- int64_t ti;
+ int64_t ti = profile_getclock();
#endif
-#ifdef CONFIG_PROFILER
- ti = profile_getclock();
-#endif
- tcg_func_start(s);
+ if (searched_pc < host_pc) {
+ return -1;
+ }
- gen_intermediate_code_pc(env, tb);
+ /* Reconstruct the stored insn data while looking for the point at
+ which the end of the insn exceeds the searched_pc. */
+ for (i = 0; i < num_insns; ++i) {
+ for (j = 0; j < TARGET_INSN_START_WORDS; ++j) {
+ data[j] += decode_sleb128(&p);
+ }
+ host_pc += decode_sleb128(&p);
+ if (host_pc > searched_pc) {
+ goto found;
+ }
+ }
+ return -1;
+ found:
if (tb->cflags & CF_USE_ICOUNT) {
assert(use_icount);
/* Reset the cycle counter to the start of the block. */
- cpu->icount_decr.u16.low += tb->icount;
+ cpu->icount_decr.u16.low += num_insns;
/* Clear the IO flag. */
cpu->can_do_io = 0;
}
-
- /* find opc index corresponding to search_pc */
- tc_ptr = (uintptr_t)tb->tc_ptr;
- if (searched_pc < tc_ptr)
- return -1;
-
- s->tb_next_offset = tb->tb_next_offset;
-#ifdef USE_DIRECT_JUMP
- s->tb_jmp_offset = tb->tb_jmp_offset;
- s->tb_next = NULL;
-#else
- s->tb_jmp_offset = NULL;
- s->tb_next = tb->tb_next;
-#endif
- j = tcg_gen_code_search_pc(s, (tcg_insn_unit *)tc_ptr,
- searched_pc - tc_ptr);
- if (j < 0)
- return -1;
- /* now find start of instruction before */
- while (s->gen_opc_instr_start[j] == 0) {
- j--;
- }
- cpu->icount_decr.u16.low -= s->gen_opc_icount[j];
-
- restore_state_to_opc(env, tb, j);
+ cpu->icount_decr.u16.low -= i;
+ restore_state_to_opc(env, tb, data);
#ifdef CONFIG_PROFILER
- s->restore_time += profile_getclock() - ti;
- s->restore_count++;
+ tcg_ctx.restore_time += profile_getclock() - ti;
+ tcg_ctx.restore_count++;
#endif
return 0;
}
@@ -311,31 +321,6 @@ bool cpu_restore_state(CPUState *cpu, uintptr_t retaddr)
return false;
}
-#ifdef _WIN32
-static __attribute__((unused)) void map_exec(void *addr, long size)
-{
- DWORD old_protect;
- VirtualProtect(addr, size,
- PAGE_EXECUTE_READWRITE, &old_protect);
-}
-#else
-static __attribute__((unused)) void map_exec(void *addr, long size)
-{
- unsigned long start, end, page_size;
-
- page_size = getpagesize();
- start = (unsigned long)addr;
- start &= ~(page_size - 1);
-
- end = (unsigned long)addr + size;
- end += page_size - 1;
- end &= ~(page_size - 1);
-
- mprotect((void *)start, end - start,
- PROT_READ | PROT_WRITE | PROT_EXEC);
-}
-#endif
-
void page_size_init(void)
{
/* NOTE: we can always suppose that qemu_host_page_size >=
@@ -472,14 +457,6 @@ static inline PageDesc *page_find(tb_page_addr_t index)
#define USE_STATIC_CODE_GEN_BUFFER
#endif
-/* ??? Should configure for this, not list operating systems here. */
-#if (defined(__linux__) \
- || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) \
- || defined(__DragonFly__) || defined(__OpenBSD__) \
- || defined(__NetBSD__))
-# define USE_MMAP
-#endif
-
/* Minimum size of the code gen buffer. This number is randomly chosen,
but not so small that we can't have a fair number of TB's live. */
#define MIN_CODE_GEN_BUFFER_SIZE (1024u * 1024)
@@ -567,22 +544,102 @@ static inline void *split_cross_256mb(void *buf1, size_t size1)
static uint8_t static_code_gen_buffer[DEFAULT_CODE_GEN_BUFFER_SIZE]
__attribute__((aligned(CODE_GEN_ALIGN)));
+# ifdef _WIN32
+static inline void do_protect(void *addr, long size, int prot)
+{
+ DWORD old_protect;
+ VirtualProtect(addr, size, prot, &old_protect);
+}
+
+static inline void map_exec(void *addr, long size)
+{
+ do_protect(addr, size, PAGE_EXECUTE_READWRITE);
+}
+
+static inline void map_none(void *addr, long size)
+{
+ do_protect(addr, size, PAGE_NOACCESS);
+}
+# else
+static inline void do_protect(void *addr, long size, int prot)
+{
+ uintptr_t start, end;
+
+ start = (uintptr_t)addr;
+ start &= qemu_real_host_page_mask;
+
+ end = (uintptr_t)addr + size;
+ end = ROUND_UP(end, qemu_real_host_page_size);
+
+ mprotect((void *)start, end - start, prot);
+}
+
+static inline void map_exec(void *addr, long size)
+{
+ do_protect(addr, size, PROT_READ | PROT_WRITE | PROT_EXEC);
+}
+
+static inline void map_none(void *addr, long size)
+{
+ do_protect(addr, size, PROT_NONE);
+}
+# endif /* WIN32 */
+
static inline void *alloc_code_gen_buffer(void)
{
void *buf = static_code_gen_buffer;
+ size_t full_size, size;
+
+ /* The size of the buffer, rounded down to end on a page boundary. */
+ full_size = (((uintptr_t)buf + sizeof(static_code_gen_buffer))
+ & qemu_real_host_page_mask) - (uintptr_t)buf;
+
+ /* Reserve a guard page. */
+ size = full_size - qemu_real_host_page_size;
+
+ /* Honor a command-line option limiting the size of the buffer. */
+ if (size > tcg_ctx.code_gen_buffer_size) {
+ size = (((uintptr_t)buf + tcg_ctx.code_gen_buffer_size)
+ & qemu_real_host_page_mask) - (uintptr_t)buf;
+ }
+ tcg_ctx.code_gen_buffer_size = size;
+
#ifdef __mips__
- if (cross_256mb(buf, tcg_ctx.code_gen_buffer_size)) {
- buf = split_cross_256mb(buf, tcg_ctx.code_gen_buffer_size);
+ if (cross_256mb(buf, size)) {
+ buf = split_cross_256mb(buf, size);
+ size = tcg_ctx.code_gen_buffer_size;
}
#endif
- map_exec(buf, tcg_ctx.code_gen_buffer_size);
+
+ map_exec(buf, size);
+ map_none(buf + size, qemu_real_host_page_size);
+ qemu_madvise(buf, size, QEMU_MADV_HUGEPAGE);
+
return buf;
}
-#elif defined(USE_MMAP)
+#elif defined(_WIN32)
+static inline void *alloc_code_gen_buffer(void)
+{
+ size_t size = tcg_ctx.code_gen_buffer_size;
+ void *buf1, *buf2;
+
+ /* Perform the allocation in two steps, so that the guard page
+ is reserved but uncommitted. */
+ buf1 = VirtualAlloc(NULL, size + qemu_real_host_page_size,
+ MEM_RESERVE, PAGE_NOACCESS);
+ if (buf1 != NULL) {
+ buf2 = VirtualAlloc(buf1, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
+ assert(buf1 == buf2);
+ }
+
+ return buf1;
+}
+#else
static inline void *alloc_code_gen_buffer(void)
{
int flags = MAP_PRIVATE | MAP_ANONYMOUS;
uintptr_t start = 0;
+ size_t size = tcg_ctx.code_gen_buffer_size;
void *buf;
/* Constrain the position of the buffer based on the host cpu.
@@ -598,86 +655,70 @@ static inline void *alloc_code_gen_buffer(void)
Leave the choice of exact location with the kernel. */
flags |= MAP_32BIT;
/* Cannot expect to map more than 800MB in low memory. */
- if (tcg_ctx.code_gen_buffer_size > 800u * 1024 * 1024) {
- tcg_ctx.code_gen_buffer_size = 800u * 1024 * 1024;
+ if (size > 800u * 1024 * 1024) {
+ tcg_ctx.code_gen_buffer_size = size = 800u * 1024 * 1024;
}
# elif defined(__sparc__)
start = 0x40000000ul;
# elif defined(__s390x__)
start = 0x90000000ul;
# elif defined(__mips__)
- /* ??? We ought to more explicitly manage layout for softmmu too. */
-# ifdef CONFIG_USER_ONLY
- start = 0x68000000ul;
-# elif _MIPS_SIM == _ABI64
+# if _MIPS_SIM == _ABI64
start = 0x128000000ul;
# else
start = 0x08000000ul;
# endif
# endif
- buf = mmap((void *)start, tcg_ctx.code_gen_buffer_size,
- PROT_WRITE | PROT_READ | PROT_EXEC, flags, -1, 0);
+ buf = mmap((void *)start, size + qemu_real_host_page_size,
+ PROT_NONE, flags, -1, 0);
if (buf == MAP_FAILED) {
return NULL;
}
#ifdef __mips__
- if (cross_256mb(buf, tcg_ctx.code_gen_buffer_size)) {
+ if (cross_256mb(buf, size)) {
/* Try again, with the original still mapped, to avoid re-acquiring
that 256mb crossing. This time don't specify an address. */
- size_t size2, size1 = tcg_ctx.code_gen_buffer_size;
- void *buf2 = mmap(NULL, size1, PROT_WRITE | PROT_READ | PROT_EXEC,
- flags, -1, 0);
- if (buf2 != MAP_FAILED) {
- if (!cross_256mb(buf2, size1)) {
+ size_t size2;
+ void *buf2 = mmap(NULL, size + qemu_real_host_page_size,
+ PROT_NONE, flags, -1, 0);
+ switch (buf2 != MAP_FAILED) {
+ case 1:
+ if (!cross_256mb(buf2, size)) {
/* Success! Use the new buffer. */
- munmap(buf, size1);
- return buf2;
+ munmap(buf, size);
+ break;
}
/* Failure. Work with what we had. */
- munmap(buf2, size1);
+ munmap(buf2, size);
+ /* fallthru */
+ default:
+ /* Split the original buffer. Free the smaller half. */
+ buf2 = split_cross_256mb(buf, size);
+ size2 = tcg_ctx.code_gen_buffer_size;
+ if (buf == buf2) {
+ munmap(buf + size2 + qemu_real_host_page_size, size - size2);
+ } else {
+ munmap(buf, size - size2);
+ }
+ size = size2;
+ break;
}
-
- /* Split the original buffer. Free the smaller half. */
- buf2 = split_cross_256mb(buf, size1);
- size2 = tcg_ctx.code_gen_buffer_size;
- munmap(buf + (buf == buf2 ? size2 : 0), size1 - size2);
- return buf2;
+ buf = buf2;
}
#endif
- return buf;
-}
-#else
-static inline void *alloc_code_gen_buffer(void)
-{
- void *buf = g_try_malloc(tcg_ctx.code_gen_buffer_size);
+ /* Make the final buffer accessible. The guard page at the end
+ will remain inaccessible with PROT_NONE. */
+ mprotect(buf, size, PROT_WRITE | PROT_READ | PROT_EXEC);
- if (buf == NULL) {
- return NULL;
- }
+ /* Request large pages for the buffer. */
+ qemu_madvise(buf, size, QEMU_MADV_HUGEPAGE);
-#ifdef __mips__
- if (cross_256mb(buf, tcg_ctx.code_gen_buffer_size)) {
- void *buf2 = g_malloc(tcg_ctx.code_gen_buffer_size);
- if (buf2 != NULL && !cross_256mb(buf2, size1)) {
- /* Success! Use the new buffer. */
- free(buf);
- buf = buf2;
- } else {
- /* Failure. Work with what we had. Since this is malloc
- and not mmap, we can't free the other half. */
- free(buf2);
- buf = split_cross_256mb(buf, tcg_ctx.code_gen_buffer_size);
- }
- }
-#endif
-
- map_exec(buf, tcg_ctx.code_gen_buffer_size);
return buf;
}
-#endif /* USE_STATIC_CODE_GEN_BUFFER, USE_MMAP */
+#endif /* USE_STATIC_CODE_GEN_BUFFER, WIN32, POSIX */
static inline void code_gen_alloc(size_t tb_size)
{
@@ -688,24 +729,13 @@ static inline void code_gen_alloc(size_t tb_size)
exit(1);
}
- qemu_madvise(tcg_ctx.code_gen_buffer, tcg_ctx.code_gen_buffer_size,
- QEMU_MADV_HUGEPAGE);
-
- /* Steal room for the prologue at the end of the buffer. This ensures
- (via the MAX_CODE_GEN_BUFFER_SIZE limits above) that direct branches
- from TB's to the prologue are going to be in range. It also means
- that we don't need to mark (additional) portions of the data segment
- as executable. */
- tcg_ctx.code_gen_prologue = tcg_ctx.code_gen_buffer +
- tcg_ctx.code_gen_buffer_size - 1024;
- tcg_ctx.code_gen_buffer_size -= 1024;
-
- tcg_ctx.code_gen_buffer_max_size = tcg_ctx.code_gen_buffer_size -
- (TCG_MAX_OP_SIZE * OPC_BUF_SIZE);
- tcg_ctx.code_gen_max_blocks = tcg_ctx.code_gen_buffer_size /
- CODE_GEN_AVG_BLOCK_SIZE;
- tcg_ctx.tb_ctx.tbs =
- g_malloc(tcg_ctx.code_gen_max_blocks * sizeof(TranslationBlock));
+ /* Estimate a good size for the number of TBs we can support. We
+ still haven't deducted the prologue from the buffer size here,
+ but that's minimal and won't affect the estimate much. */
+ tcg_ctx.code_gen_max_blocks
+ = tcg_ctx.code_gen_buffer_size / CODE_GEN_AVG_BLOCK_SIZE;
+ tcg_ctx.tb_ctx.tbs = g_new(TranslationBlock, tcg_ctx.code_gen_max_blocks);
+
qemu_mutex_init(&tcg_ctx.tb_ctx.tb_lock);
}
@@ -715,10 +745,8 @@ static inline void code_gen_alloc(size_t tb_size)
void tcg_exec_init(unsigned long tb_size)
{
cpu_gen_init();
- code_gen_alloc(tb_size);
- tcg_ctx.code_gen_ptr = tcg_ctx.code_gen_buffer;
- tcg_register_jit(tcg_ctx.code_gen_buffer, tcg_ctx.code_gen_buffer_size);
page_init();
+ code_gen_alloc(tb_size);
#if defined(CONFIG_SOFTMMU)
/* There's no guest base to take into account, so go ahead and
initialize the prologue now. */
@@ -737,9 +765,7 @@ static TranslationBlock *tb_alloc(target_ulong pc)
{
TranslationBlock *tb;
- if (tcg_ctx.tb_ctx.nb_tbs >= tcg_ctx.code_gen_max_blocks ||
- (tcg_ctx.code_gen_ptr - tcg_ctx.code_gen_buffer) >=
- tcg_ctx.code_gen_buffer_max_size) {
+ if (tcg_ctx.tb_ctx.nb_tbs >= tcg_ctx.code_gen_max_blocks) {
return NULL;
}
tb = &tcg_ctx.tb_ctx.tbs[tcg_ctx.tb_ctx.nb_tbs++];
@@ -1034,28 +1060,98 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
TranslationBlock *tb;
tb_page_addr_t phys_pc, phys_page2;
target_ulong virt_page2;
- int code_gen_size;
+ tcg_insn_unit *gen_code_buf;
+ int gen_code_size, search_size;
+#ifdef CONFIG_PROFILER
+ int64_t ti;
+#endif
phys_pc = get_page_addr_code(env, pc);
if (use_icount) {
cflags |= CF_USE_ICOUNT;
}
+
tb = tb_alloc(pc);
- if (!tb) {
+ if (unlikely(!tb)) {
+ buffer_overflow:
/* flush must be done */
tb_flush(cpu);
/* cannot fail at this point */
tb = tb_alloc(pc);
+ assert(tb != NULL);
/* Don't forget to invalidate previous TB info. */
tcg_ctx.tb_ctx.tb_invalidated_flag = 1;
}
- tb->tc_ptr = tcg_ctx.code_gen_ptr;
+
+ gen_code_buf = tcg_ctx.code_gen_ptr;
+ tb->tc_ptr = gen_code_buf;
tb->cs_base = cs_base;
tb->flags = flags;
tb->cflags = cflags;
- cpu_gen_code(env, tb, &code_gen_size);
- tcg_ctx.code_gen_ptr = (void *)(((uintptr_t)tcg_ctx.code_gen_ptr +
- code_gen_size + CODE_GEN_ALIGN - 1) & ~(CODE_GEN_ALIGN - 1));
+
+#ifdef CONFIG_PROFILER
+ tcg_ctx.tb_count1++; /* includes aborted translations because of
+ exceptions */
+ ti = profile_getclock();
+#endif
+
+ tcg_func_start(&tcg_ctx);
+
+ gen_intermediate_code(env, tb);
+
+ trace_translate_block(tb, tb->pc, tb->tc_ptr);
+
+ /* generate machine code */
+ tb->tb_next_offset[0] = 0xffff;
+ tb->tb_next_offset[1] = 0xffff;
+ tcg_ctx.tb_next_offset = tb->tb_next_offset;
+#ifdef USE_DIRECT_JUMP
+ tcg_ctx.tb_jmp_offset = tb->tb_jmp_offset;
+ tcg_ctx.tb_next = NULL;
+#else
+ tcg_ctx.tb_jmp_offset = NULL;
+ tcg_ctx.tb_next = tb->tb_next;
+#endif
+
+#ifdef CONFIG_PROFILER
+ tcg_ctx.tb_count++;
+ tcg_ctx.interm_time += profile_getclock() - ti;
+ tcg_ctx.code_time -= profile_getclock();
+#endif
+
+ /* ??? Overflow could be handled better here. In particular, we
+ don't need to re-do gen_intermediate_code, nor should we re-do
+ the tcg optimization currently hidden inside tcg_gen_code. All
+ that should be required is to flush the TBs, allocate a new TB,
+ re-initialize it per above, and re-do the actual code generation. */
+ gen_code_size = tcg_gen_code(&tcg_ctx, gen_code_buf);
+ if (unlikely(gen_code_size < 0)) {
+ goto buffer_overflow;
+ }
+ search_size = encode_search(tb, (void *)gen_code_buf + gen_code_size);
+ if (unlikely(search_size < 0)) {
+ goto buffer_overflow;
+ }
+
+#ifdef CONFIG_PROFILER
+ tcg_ctx.code_time += profile_getclock();
+ tcg_ctx.code_in_len += tb->size;
+ tcg_ctx.code_out_len += gen_code_size;
+ tcg_ctx.search_out_len += search_size;
+#endif
+
+#ifdef DEBUG_DISAS
+ if (qemu_loglevel_mask(CPU_LOG_TB_OUT_ASM)) {
+ qemu_log("OUT: [size=%d]\n", gen_code_size);
+ log_disas(tb->tc_ptr, gen_code_size);
+ qemu_log("\n");
+ qemu_log_flush();
+ }
+#endif
+
+ tcg_ctx.code_gen_ptr = (void *)
+ ROUND_UP((uintptr_t)gen_code_buf + gen_code_size + search_size,
+ CODE_GEN_ALIGN);
/* check next page if needed */
virt_page2 = (pc + tb->size - 1) & TARGET_PAGE_MASK;
@@ -1606,7 +1702,7 @@ void dump_exec_info(FILE *f, fprintf_function cpu_fprintf)
cpu_fprintf(f, "Translation buffer state:\n");
cpu_fprintf(f, "gen code size %td/%zd\n",
tcg_ctx.code_gen_ptr - tcg_ctx.code_gen_buffer,
- tcg_ctx.code_gen_buffer_max_size);
+ tcg_ctx.code_gen_highwater - tcg_ctx.code_gen_buffer);
cpu_fprintf(f, "TB count %d/%d\n",
tcg_ctx.tb_ctx.nb_tbs, tcg_ctx.code_gen_max_blocks);
cpu_fprintf(f, "TB avg target size %d max=%d bytes\n",