Skip to content

Commit

Permalink
Merge remote-tracking branch 'remotes/rth/tags/pull-tcg-20151007' int…
Browse files Browse the repository at this point in the history
…o 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>
  • Loading branch information
pm215 committed Oct 8, 2015
2 parents ca4e4b8 + 126d89e commit 31c9bd1
Show file tree
Hide file tree
Showing 45 changed files with 964 additions and 1,492 deletions.
23 changes: 8 additions & 15 deletions include/exec/exec-all.h
Expand Up @@ -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);

Expand Down Expand Up @@ -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) \
Expand All @@ -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 */
Expand Down
16 changes: 16 additions & 0 deletions include/qom/cpu.h
Expand Up @@ -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)
Expand All @@ -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,
Expand Down
1 change: 0 additions & 1 deletion target-alpha/cpu.h
Expand Up @@ -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"
Expand Down
70 changes: 17 additions & 53 deletions target-alpha/translate.c
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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);
Expand Down Expand Up @@ -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)) {
Expand All @@ -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];
}
2 changes: 1 addition & 1 deletion target-arm/cpu.h
Expand Up @@ -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.
Expand Down Expand Up @@ -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

Expand Down
48 changes: 12 additions & 36 deletions target-arm/translate-a64.c
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand All @@ -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
Expand All @@ -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;
Expand All @@ -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 &&
Expand Down Expand Up @@ -11221,14 +11205,6 @@ void gen_intermediate_code_internal_a64(ARMCPU *cpu,
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;
}

0 comments on commit 31c9bd1

Please sign in to comment.