Convert to linked list.

-----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQEcBAABAgAGBQJU3Y5ZAAoJEK0ScMxN0CebuvYH/iQa+ZA1yavKsOa2xtB4tq0K
 gwS0hwCmAtS7CV6iM8Wrte/3HJr4xtnQGeBQgatmM7PrDx6o6cjnxwga2mBx6EQv
 fIhWlNPlctAgd11ocuhXXUdGv2yL8TWf+WLTDcO6CS6zbdYp+42sOvrWGKL1UQbz
 RAJhiK5BZsDHv2DodqZBk7JZr9l4hAohARs627xG7uq/j6vggEHo6y/9Z6mETcRX
 fkIwx/qjUmDJbBlFgtgEPBYMX/AWDu7XbhU1kT+EjcrFwEjEd0mxi52NN8uEyGQ9
 xgAekmPvcNR0UpkVl5pIr64/wTkd+m2mBG8CVENG3ryDKePJk64jVth+I/8Z/Qo=
 =+mGW
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/rth/tags/pull-tcg-20150212' into staging

Convert to linked list.

# gpg: Signature made Fri 13 Feb 2015 05:40:41 GMT 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-20150212:
  tcg: Remove unused opcodes
  tcg: Implement insert_op_before
  tcg: Remove opcodes instead of noping them out
  tcg: Put opcodes in a linked list
  tcg: Introduce tcg_op_buf_count and tcg_op_buf_full
  tcg: Move emit of INDEX_op_end into gen_tb_end
  tcg: Reduce ifdefs in tcg-op.c
  tcg: Move some opcode generation functions out of line

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2015-02-13 11:44:49 +00:00
commit cd2d554127
27 changed files with 2736 additions and 2822 deletions

View file

@ -83,7 +83,7 @@ all: $(PROGS) stap
######################################################### #########################################################
# cpu emulator library # cpu emulator library
obj-y = exec.o translate-all.o cpu-exec.o obj-y = exec.o translate-all.o cpu-exec.o
obj-y += tcg/tcg.o tcg/optimize.o obj-y += tcg/tcg.o tcg/tcg-op.o tcg/optimize.o
obj-$(CONFIG_TCG_INTERPRETER) += tci.o obj-$(CONFIG_TCG_INTERPRETER) += tci.o
obj-$(CONFIG_TCG_INTERPRETER) += disas/tci.o obj-$(CONFIG_TCG_INTERPRETER) += disas/tci.o
obj-y += fpu/softfloat.o obj-y += fpu/softfloat.o

View file

@ -11,8 +11,8 @@ static int exitreq_label;
static inline void gen_tb_start(TranslationBlock *tb) static inline void gen_tb_start(TranslationBlock *tb)
{ {
TCGv_i32 count; TCGv_i32 count, flag, imm;
TCGv_i32 flag; int i;
exitreq_label = gen_new_label(); exitreq_label = gen_new_label();
flag = tcg_temp_new_i32(); flag = tcg_temp_new_i32();
@ -21,16 +21,25 @@ static inline void gen_tb_start(TranslationBlock *tb)
tcg_gen_brcondi_i32(TCG_COND_NE, flag, 0, exitreq_label); tcg_gen_brcondi_i32(TCG_COND_NE, flag, 0, exitreq_label);
tcg_temp_free_i32(flag); tcg_temp_free_i32(flag);
if (!(tb->cflags & CF_USE_ICOUNT)) if (!(tb->cflags & CF_USE_ICOUNT)) {
return; return;
}
icount_label = gen_new_label(); icount_label = gen_new_label();
count = tcg_temp_local_new_i32(); count = tcg_temp_local_new_i32();
tcg_gen_ld_i32(count, cpu_env, tcg_gen_ld_i32(count, cpu_env,
-ENV_OFFSET + offsetof(CPUState, icount_decr.u32)); -ENV_OFFSET + offsetof(CPUState, icount_decr.u32));
imm = tcg_temp_new_i32();
tcg_gen_movi_i32(imm, 0xdeadbeef);
/* This is a horrid hack to allow fixing up the value later. */ /* This is a horrid hack to allow fixing up the value later. */
icount_arg = tcg_ctx.gen_opparam_ptr + 1; i = tcg_ctx.gen_last_op_idx;
tcg_gen_subi_i32(count, count, 0xdeadbeef); i = tcg_ctx.gen_op_buf[i].args;
icount_arg = &tcg_ctx.gen_opparam_buf[i + 1];
tcg_gen_sub_i32(count, count, imm);
tcg_temp_free_i32(imm);
tcg_gen_brcondi_i32(TCG_COND_LT, count, 0, icount_label); tcg_gen_brcondi_i32(TCG_COND_LT, count, 0, icount_label);
tcg_gen_st16_i32(count, cpu_env, tcg_gen_st16_i32(count, cpu_env,
@ -48,6 +57,9 @@ static void gen_tb_end(TranslationBlock *tb, int num_insns)
gen_set_label(icount_label); gen_set_label(icount_label);
tcg_gen_exit_tb((uintptr_t)tb + TB_EXIT_ICOUNT_EXPIRED); tcg_gen_exit_tb((uintptr_t)tb + TB_EXIT_ICOUNT_EXPIRED);
} }
/* Terminate the linked list. */
tcg_ctx.gen_op_buf[tcg_ctx.gen_last_op_idx].next = -1;
} }
static inline void gen_io_start(void) static inline void gen_io_start(void)

View file

@ -2790,7 +2790,6 @@ static inline void gen_intermediate_code_internal(AlphaCPU *cpu,
target_ulong pc_start; target_ulong pc_start;
target_ulong pc_mask; target_ulong pc_mask;
uint32_t insn; uint32_t insn;
uint16_t *gen_opc_end;
CPUBreakpoint *bp; CPUBreakpoint *bp;
int j, lj = -1; int j, lj = -1;
ExitStatus ret; ExitStatus ret;
@ -2798,7 +2797,6 @@ static inline void gen_intermediate_code_internal(AlphaCPU *cpu,
int max_insns; int max_insns;
pc_start = tb->pc; pc_start = tb->pc;
gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
ctx.tb = tb; ctx.tb = tb;
ctx.pc = pc_start; ctx.pc = pc_start;
@ -2839,11 +2837,12 @@ static inline void gen_intermediate_code_internal(AlphaCPU *cpu,
} }
} }
if (search_pc) { if (search_pc) {
j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf; j = tcg_op_buf_count();
if (lj < j) { if (lj < j) {
lj++; lj++;
while (lj < j) while (lj < j) {
tcg_ctx.gen_opc_instr_start[lj++] = 0; tcg_ctx.gen_opc_instr_start[lj++] = 0;
}
} }
tcg_ctx.gen_opc_pc[lj] = ctx.pc; tcg_ctx.gen_opc_pc[lj] = ctx.pc;
tcg_ctx.gen_opc_instr_start[lj] = 1; tcg_ctx.gen_opc_instr_start[lj] = 1;
@ -2881,7 +2880,7 @@ static inline void gen_intermediate_code_internal(AlphaCPU *cpu,
or exhaust instruction count, stop generation. */ or exhaust instruction count, stop generation. */
if (ret == NO_EXIT if (ret == NO_EXIT
&& ((ctx.pc & pc_mask) == 0 && ((ctx.pc & pc_mask) == 0
|| tcg_ctx.gen_opc_ptr >= gen_opc_end || tcg_op_buf_full()
|| num_insns >= max_insns || num_insns >= max_insns
|| singlestep || singlestep
|| ctx.singlestep_enabled)) { || ctx.singlestep_enabled)) {
@ -2912,12 +2911,13 @@ static inline void gen_intermediate_code_internal(AlphaCPU *cpu,
} }
gen_tb_end(tb, num_insns); gen_tb_end(tb, num_insns);
*tcg_ctx.gen_opc_ptr = INDEX_op_end;
if (search_pc) { if (search_pc) {
j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf; j = tcg_op_buf_count();
lj++; lj++;
while (lj <= j) while (lj <= j) {
tcg_ctx.gen_opc_instr_start[lj++] = 0; tcg_ctx.gen_opc_instr_start[lj++] = 0;
}
} else { } else {
tb->size = ctx.pc - pc_start; tb->size = ctx.pc - pc_start;
tb->icount = num_insns; tb->icount = num_insns;

View file

@ -10920,7 +10920,6 @@ void gen_intermediate_code_internal_a64(ARMCPU *cpu,
CPUARMState *env = &cpu->env; CPUARMState *env = &cpu->env;
DisasContext dc1, *dc = &dc1; DisasContext dc1, *dc = &dc1;
CPUBreakpoint *bp; CPUBreakpoint *bp;
uint16_t *gen_opc_end;
int j, lj; int j, lj;
target_ulong pc_start; target_ulong pc_start;
target_ulong next_page_start; target_ulong next_page_start;
@ -10931,8 +10930,6 @@ void gen_intermediate_code_internal_a64(ARMCPU *cpu,
dc->tb = tb; dc->tb = tb;
gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
dc->is_jmp = DISAS_NEXT; dc->is_jmp = DISAS_NEXT;
dc->pc = pc_start; dc->pc = pc_start;
dc->singlestep_enabled = cs->singlestep_enabled; dc->singlestep_enabled = cs->singlestep_enabled;
@ -11002,7 +10999,7 @@ void gen_intermediate_code_internal_a64(ARMCPU *cpu,
} }
if (search_pc) { if (search_pc) {
j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf; j = tcg_op_buf_count();
if (lj < j) { if (lj < j) {
lj++; lj++;
while (lj < j) { while (lj < j) {
@ -11052,7 +11049,7 @@ void gen_intermediate_code_internal_a64(ARMCPU *cpu,
* ensures prefetch aborts occur at the right place. * ensures prefetch aborts occur at the right place.
*/ */
num_insns++; num_insns++;
} while (!dc->is_jmp && tcg_ctx.gen_opc_ptr < gen_opc_end && } while (!dc->is_jmp && !tcg_op_buf_full() &&
!cs->singlestep_enabled && !cs->singlestep_enabled &&
!singlestep && !singlestep &&
!dc->ss_active && !dc->ss_active &&
@ -11112,7 +11109,6 @@ void gen_intermediate_code_internal_a64(ARMCPU *cpu,
done_generating: done_generating:
gen_tb_end(tb, num_insns); gen_tb_end(tb, num_insns);
*tcg_ctx.gen_opc_ptr = INDEX_op_end;
#ifdef DEBUG_DISAS #ifdef DEBUG_DISAS
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) { if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
@ -11124,7 +11120,7 @@ done_generating:
} }
#endif #endif
if (search_pc) { if (search_pc) {
j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf; j = tcg_op_buf_count();
lj++; lj++;
while (lj <= j) { while (lj <= j) {
tcg_ctx.gen_opc_instr_start[lj++] = 0; tcg_ctx.gen_opc_instr_start[lj++] = 0;

View file

@ -11025,7 +11025,6 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu,
CPUARMState *env = &cpu->env; CPUARMState *env = &cpu->env;
DisasContext dc1, *dc = &dc1; DisasContext dc1, *dc = &dc1;
CPUBreakpoint *bp; CPUBreakpoint *bp;
uint16_t *gen_opc_end;
int j, lj; int j, lj;
target_ulong pc_start; target_ulong pc_start;
target_ulong next_page_start; target_ulong next_page_start;
@ -11046,8 +11045,6 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu,
dc->tb = tb; dc->tb = tb;
gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
dc->is_jmp = DISAS_NEXT; dc->is_jmp = DISAS_NEXT;
dc->pc = pc_start; dc->pc = pc_start;
dc->singlestep_enabled = cs->singlestep_enabled; dc->singlestep_enabled = cs->singlestep_enabled;
@ -11182,7 +11179,7 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu,
} }
} }
if (search_pc) { if (search_pc) {
j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf; j = tcg_op_buf_count();
if (lj < j) { if (lj < j) {
lj++; lj++;
while (lj < j) while (lj < j)
@ -11248,7 +11245,7 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu,
* Also stop translation when a page boundary is reached. This * Also stop translation when a page boundary is reached. This
* ensures prefetch aborts occur at the right place. */ * ensures prefetch aborts occur at the right place. */
num_insns ++; num_insns ++;
} while (!dc->is_jmp && tcg_ctx.gen_opc_ptr < gen_opc_end && } while (!dc->is_jmp && !tcg_op_buf_full() &&
!cs->singlestep_enabled && !cs->singlestep_enabled &&
!singlestep && !singlestep &&
!dc->ss_active && !dc->ss_active &&
@ -11357,7 +11354,6 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu,
done_generating: done_generating:
gen_tb_end(tb, num_insns); gen_tb_end(tb, num_insns);
*tcg_ctx.gen_opc_ptr = INDEX_op_end;
#ifdef DEBUG_DISAS #ifdef DEBUG_DISAS
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) { if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
@ -11369,7 +11365,7 @@ done_generating:
} }
#endif #endif
if (search_pc) { if (search_pc) {
j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf; j = tcg_op_buf_count();
lj++; lj++;
while (lj <= j) while (lj <= j)
tcg_ctx.gen_opc_instr_start[lj++] = 0; tcg_ctx.gen_opc_instr_start[lj++] = 0;

View file

@ -3116,7 +3116,6 @@ gen_intermediate_code_internal(CRISCPU *cpu, TranslationBlock *tb,
{ {
CPUState *cs = CPU(cpu); CPUState *cs = CPU(cpu);
CPUCRISState *env = &cpu->env; CPUCRISState *env = &cpu->env;
uint16_t *gen_opc_end;
uint32_t pc_start; uint32_t pc_start;
unsigned int insn_len; unsigned int insn_len;
int j, lj; int j, lj;
@ -3142,8 +3141,6 @@ gen_intermediate_code_internal(CRISCPU *cpu, TranslationBlock *tb,
dc->cpu = cpu; dc->cpu = cpu;
dc->tb = tb; dc->tb = tb;
gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
dc->is_jmp = DISAS_NEXT; dc->is_jmp = DISAS_NEXT;
dc->ppc = pc_start; dc->ppc = pc_start;
dc->pc = pc_start; dc->pc = pc_start;
@ -3207,7 +3204,7 @@ gen_intermediate_code_internal(CRISCPU *cpu, TranslationBlock *tb,
check_breakpoint(env, dc); check_breakpoint(env, dc);
if (search_pc) { if (search_pc) {
j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf; j = tcg_op_buf_count();
if (lj < j) { if (lj < j) {
lj++; lj++;
while (lj < j) { while (lj < j) {
@ -3291,7 +3288,7 @@ gen_intermediate_code_internal(CRISCPU *cpu, TranslationBlock *tb,
break; break;
} }
} while (!dc->is_jmp && !dc->cpustate_changed } while (!dc->is_jmp && !dc->cpustate_changed
&& tcg_ctx.gen_opc_ptr < gen_opc_end && !tcg_op_buf_full()
&& !singlestep && !singlestep
&& (dc->pc < next_page_start) && (dc->pc < next_page_start)
&& num_insns < max_insns); && num_insns < max_insns);
@ -3344,9 +3341,9 @@ gen_intermediate_code_internal(CRISCPU *cpu, TranslationBlock *tb,
} }
} }
gen_tb_end(tb, num_insns); gen_tb_end(tb, num_insns);
*tcg_ctx.gen_opc_ptr = INDEX_op_end;
if (search_pc) { if (search_pc) {
j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf; j = tcg_op_buf_count();
lj++; lj++;
while (lj <= j) { while (lj <= j) {
tcg_ctx.gen_opc_instr_start[lj++] = 0; tcg_ctx.gen_opc_instr_start[lj++] = 0;
@ -3361,8 +3358,8 @@ gen_intermediate_code_internal(CRISCPU *cpu, TranslationBlock *tb,
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) { if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
log_target_disas(env, pc_start, dc->pc - pc_start, log_target_disas(env, pc_start, dc->pc - pc_start,
env->pregs[PR_VR]); env->pregs[PR_VR]);
qemu_log("\nisize=%d osize=%td\n", qemu_log("\nisize=%d osize=%d\n",
dc->pc - pc_start, tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf); dc->pc - pc_start, tcg_op_buf_count());
} }
#endif #endif
#endif #endif

View file

@ -7913,7 +7913,6 @@ static inline void gen_intermediate_code_internal(X86CPU *cpu,
CPUX86State *env = &cpu->env; CPUX86State *env = &cpu->env;
DisasContext dc1, *dc = &dc1; DisasContext dc1, *dc = &dc1;
target_ulong pc_ptr; target_ulong pc_ptr;
uint16_t *gen_opc_end;
CPUBreakpoint *bp; CPUBreakpoint *bp;
int j, lj; int j, lj;
uint64_t flags; uint64_t flags;
@ -7993,8 +7992,6 @@ static inline void gen_intermediate_code_internal(X86CPU *cpu,
cpu_ptr1 = tcg_temp_new_ptr(); cpu_ptr1 = tcg_temp_new_ptr();
cpu_cc_srcT = tcg_temp_local_new(); cpu_cc_srcT = tcg_temp_local_new();
gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
dc->is_jmp = DISAS_NEXT; dc->is_jmp = DISAS_NEXT;
pc_ptr = pc_start; pc_ptr = pc_start;
lj = -1; lj = -1;
@ -8015,7 +8012,7 @@ static inline void gen_intermediate_code_internal(X86CPU *cpu,
} }
} }
if (search_pc) { if (search_pc) {
j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf; j = tcg_op_buf_count();
if (lj < j) { if (lj < j) {
lj++; lj++;
while (lj < j) while (lj < j)
@ -8060,7 +8057,7 @@ static inline void gen_intermediate_code_internal(X86CPU *cpu,
break; break;
} }
/* if too long translation, stop generation too */ /* if too long translation, stop generation too */
if (tcg_ctx.gen_opc_ptr >= gen_opc_end || if (tcg_op_buf_full() ||
(pc_ptr - pc_start) >= (TARGET_PAGE_SIZE - 32) || (pc_ptr - pc_start) >= (TARGET_PAGE_SIZE - 32) ||
num_insns >= max_insns) { num_insns >= max_insns) {
gen_jmp_im(pc_ptr - dc->cs_base); gen_jmp_im(pc_ptr - dc->cs_base);
@ -8077,10 +8074,10 @@ static inline void gen_intermediate_code_internal(X86CPU *cpu,
gen_io_end(); gen_io_end();
done_generating: done_generating:
gen_tb_end(tb, num_insns); gen_tb_end(tb, num_insns);
*tcg_ctx.gen_opc_ptr = INDEX_op_end;
/* we don't forget to fill the last values */ /* we don't forget to fill the last values */
if (search_pc) { if (search_pc) {
j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf; j = tcg_op_buf_count();
lj++; lj++;
while (lj <= j) while (lj <= j)
tcg_ctx.gen_opc_instr_start[lj++] = 0; tcg_ctx.gen_opc_instr_start[lj++] = 0;

View file

@ -1062,7 +1062,6 @@ void gen_intermediate_code_internal(LM32CPU *cpu,
CPUState *cs = CPU(cpu); CPUState *cs = CPU(cpu);
CPULM32State *env = &cpu->env; CPULM32State *env = &cpu->env;
struct DisasContext ctx, *dc = &ctx; struct DisasContext ctx, *dc = &ctx;
uint16_t *gen_opc_end;
uint32_t pc_start; uint32_t pc_start;
int j, lj; int j, lj;
uint32_t next_page_start; uint32_t next_page_start;
@ -1075,8 +1074,6 @@ void gen_intermediate_code_internal(LM32CPU *cpu,
dc->num_watchpoints = cpu->num_watchpoints; dc->num_watchpoints = cpu->num_watchpoints;
dc->tb = tb; dc->tb = tb;
gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
dc->is_jmp = DISAS_NEXT; dc->is_jmp = DISAS_NEXT;
dc->pc = pc_start; dc->pc = pc_start;
dc->singlestep_enabled = cs->singlestep_enabled; dc->singlestep_enabled = cs->singlestep_enabled;
@ -1100,7 +1097,7 @@ void gen_intermediate_code_internal(LM32CPU *cpu,
check_breakpoint(env, dc); check_breakpoint(env, dc);
if (search_pc) { if (search_pc) {
j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf; j = tcg_op_buf_count();
if (lj < j) { if (lj < j) {
lj++; lj++;
while (lj < j) { while (lj < j) {
@ -1124,7 +1121,7 @@ void gen_intermediate_code_internal(LM32CPU *cpu,
num_insns++; num_insns++;
} while (!dc->is_jmp } while (!dc->is_jmp
&& tcg_ctx.gen_opc_ptr < gen_opc_end && !tcg_op_buf_full()
&& !cs->singlestep_enabled && !cs->singlestep_enabled
&& !singlestep && !singlestep
&& (dc->pc < next_page_start) && (dc->pc < next_page_start)
@ -1158,9 +1155,9 @@ void gen_intermediate_code_internal(LM32CPU *cpu,
} }
gen_tb_end(tb, num_insns); gen_tb_end(tb, num_insns);
*tcg_ctx.gen_opc_ptr = INDEX_op_end;
if (search_pc) { if (search_pc) {
j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf; j = tcg_op_buf_count();
lj++; lj++;
while (lj <= j) { while (lj <= j) {
tcg_ctx.gen_opc_instr_start[lj++] = 0; tcg_ctx.gen_opc_instr_start[lj++] = 0;
@ -1174,9 +1171,8 @@ void gen_intermediate_code_internal(LM32CPU *cpu,
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) { if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
qemu_log("\n"); qemu_log("\n");
log_target_disas(env, pc_start, dc->pc - pc_start, 0); log_target_disas(env, pc_start, dc->pc - pc_start, 0);
qemu_log("\nisize=%d osize=%td\n", qemu_log("\nisize=%d osize=%d\n",
dc->pc - pc_start, tcg_ctx.gen_opc_ptr - dc->pc - pc_start, tcg_op_buf_count());
tcg_ctx.gen_opc_buf);
} }
#endif #endif
} }

View file

@ -2980,7 +2980,6 @@ gen_intermediate_code_internal(M68kCPU *cpu, TranslationBlock *tb,
CPUState *cs = CPU(cpu); CPUState *cs = CPU(cpu);
CPUM68KState *env = &cpu->env; CPUM68KState *env = &cpu->env;
DisasContext dc1, *dc = &dc1; DisasContext dc1, *dc = &dc1;
uint16_t *gen_opc_end;
CPUBreakpoint *bp; CPUBreakpoint *bp;
int j, lj; int j, lj;
target_ulong pc_start; target_ulong pc_start;
@ -2993,8 +2992,6 @@ gen_intermediate_code_internal(M68kCPU *cpu, TranslationBlock *tb,
dc->tb = tb; dc->tb = tb;
gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
dc->env = env; dc->env = env;
dc->is_jmp = DISAS_NEXT; dc->is_jmp = DISAS_NEXT;
dc->pc = pc_start; dc->pc = pc_start;
@ -3026,7 +3023,7 @@ gen_intermediate_code_internal(M68kCPU *cpu, TranslationBlock *tb,
break; break;
} }
if (search_pc) { if (search_pc) {
j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf; j = tcg_op_buf_count();
if (lj < j) { if (lj < j) {
lj++; lj++;
while (lj < j) while (lj < j)
@ -3041,7 +3038,7 @@ gen_intermediate_code_internal(M68kCPU *cpu, TranslationBlock *tb,
dc->insn_pc = dc->pc; dc->insn_pc = dc->pc;
disas_m68k_insn(env, dc); disas_m68k_insn(env, dc);
num_insns++; num_insns++;
} while (!dc->is_jmp && tcg_ctx.gen_opc_ptr < gen_opc_end && } while (!dc->is_jmp && !tcg_op_buf_full() &&
!cs->singlestep_enabled && !cs->singlestep_enabled &&
!singlestep && !singlestep &&
(pc_offset) < (TARGET_PAGE_SIZE - 32) && (pc_offset) < (TARGET_PAGE_SIZE - 32) &&
@ -3075,7 +3072,6 @@ gen_intermediate_code_internal(M68kCPU *cpu, TranslationBlock *tb,
} }
} }
gen_tb_end(tb, num_insns); gen_tb_end(tb, num_insns);
*tcg_ctx.gen_opc_ptr = INDEX_op_end;
#ifdef DEBUG_DISAS #ifdef DEBUG_DISAS
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) { if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
@ -3086,7 +3082,7 @@ gen_intermediate_code_internal(M68kCPU *cpu, TranslationBlock *tb,
} }
#endif #endif
if (search_pc) { if (search_pc) {
j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf; j = tcg_op_buf_count();
lj++; lj++;
while (lj <= j) while (lj <= j)
tcg_ctx.gen_opc_instr_start[lj++] = 0; tcg_ctx.gen_opc_instr_start[lj++] = 0;

View file

@ -1673,7 +1673,6 @@ gen_intermediate_code_internal(MicroBlazeCPU *cpu, TranslationBlock *tb,
{ {
CPUState *cs = CPU(cpu); CPUState *cs = CPU(cpu);
CPUMBState *env = &cpu->env; CPUMBState *env = &cpu->env;
uint16_t *gen_opc_end;
uint32_t pc_start; uint32_t pc_start;
int j, lj; int j, lj;
struct DisasContext ctx; struct DisasContext ctx;
@ -1688,8 +1687,6 @@ gen_intermediate_code_internal(MicroBlazeCPU *cpu, TranslationBlock *tb,
dc->tb = tb; dc->tb = tb;
org_flags = dc->synced_flags = dc->tb_flags = tb->flags; org_flags = dc->synced_flags = dc->tb_flags = tb->flags;
gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
dc->is_jmp = DISAS_NEXT; dc->is_jmp = DISAS_NEXT;
dc->jmp = 0; dc->jmp = 0;
dc->delayed_branch = !!(dc->tb_flags & D_FLAG); dc->delayed_branch = !!(dc->tb_flags & D_FLAG);
@ -1732,7 +1729,7 @@ gen_intermediate_code_internal(MicroBlazeCPU *cpu, TranslationBlock *tb,
check_breakpoint(env, dc); check_breakpoint(env, dc);
if (search_pc) { if (search_pc) {
j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf; j = tcg_op_buf_count();
if (lj < j) { if (lj < j) {
lj++; lj++;
while (lj < j) while (lj < j)
@ -1795,10 +1792,10 @@ gen_intermediate_code_internal(MicroBlazeCPU *cpu, TranslationBlock *tb,
break; break;
} }
} while (!dc->is_jmp && !dc->cpustate_changed } while (!dc->is_jmp && !dc->cpustate_changed
&& tcg_ctx.gen_opc_ptr < gen_opc_end && !tcg_op_buf_full()
&& !singlestep && !singlestep
&& (dc->pc < next_page_start) && (dc->pc < next_page_start)
&& num_insns < max_insns); && num_insns < max_insns);
npc = dc->pc; npc = dc->pc;
if (dc->jmp == JMP_DIRECT || dc->jmp == JMP_DIRECT_CC) { if (dc->jmp == JMP_DIRECT || dc->jmp == JMP_DIRECT_CC) {
@ -1846,9 +1843,9 @@ gen_intermediate_code_internal(MicroBlazeCPU *cpu, TranslationBlock *tb,
} }
} }
gen_tb_end(tb, num_insns); gen_tb_end(tb, num_insns);
*tcg_ctx.gen_opc_ptr = INDEX_op_end;
if (search_pc) { if (search_pc) {
j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf; j = tcg_op_buf_count();
lj++; lj++;
while (lj <= j) while (lj <= j)
tcg_ctx.gen_opc_instr_start[lj++] = 0; tcg_ctx.gen_opc_instr_start[lj++] = 0;
@ -1864,9 +1861,8 @@ gen_intermediate_code_internal(MicroBlazeCPU *cpu, TranslationBlock *tb,
#if DISAS_GNU #if DISAS_GNU
log_target_disas(env, pc_start, dc->pc - pc_start, 0); log_target_disas(env, pc_start, dc->pc - pc_start, 0);
#endif #endif
qemu_log("\nisize=%d osize=%td\n", qemu_log("\nisize=%d osize=%d\n",
dc->pc - pc_start, tcg_ctx.gen_opc_ptr - dc->pc - pc_start, tcg_op_buf_count());
tcg_ctx.gen_opc_buf);
} }
#endif #endif
#endif #endif

View file

@ -19095,7 +19095,6 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb,
CPUMIPSState *env = &cpu->env; CPUMIPSState *env = &cpu->env;
DisasContext ctx; DisasContext ctx;
target_ulong pc_start; target_ulong pc_start;
uint16_t *gen_opc_end;
CPUBreakpoint *bp; CPUBreakpoint *bp;
int j, lj = -1; int j, lj = -1;
int num_insns; int num_insns;
@ -19107,7 +19106,6 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb,
qemu_log("search pc %d\n", search_pc); qemu_log("search pc %d\n", search_pc);
pc_start = tb->pc; pc_start = tb->pc;
gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
ctx.pc = pc_start; ctx.pc = pc_start;
ctx.saved_pc = -1; ctx.saved_pc = -1;
ctx.singlestep_enabled = cs->singlestep_enabled; ctx.singlestep_enabled = cs->singlestep_enabled;
@ -19151,7 +19149,7 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb,
} }
if (search_pc) { if (search_pc) {
j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf; j = tcg_op_buf_count();
if (lj < j) { if (lj < j) {
lj++; lj++;
while (lj < j) while (lj < j)
@ -19209,7 +19207,7 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb,
if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0) if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
break; break;
if (tcg_ctx.gen_opc_ptr >= gen_opc_end) { if (tcg_op_buf_full()) {
break; break;
} }
@ -19244,9 +19242,9 @@ gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb,
} }
done_generating: done_generating:
gen_tb_end(tb, num_insns); gen_tb_end(tb, num_insns);
*tcg_ctx.gen_opc_ptr = INDEX_op_end;
if (search_pc) { if (search_pc) {
j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf; j = tcg_op_buf_count();
lj++; lj++;
while (lj <= j) while (lj <= j)
tcg_ctx.gen_opc_instr_start[lj++] = 0; tcg_ctx.gen_opc_instr_start[lj++] = 0;

View file

@ -827,14 +827,12 @@ gen_intermediate_code_internal(MoxieCPU *cpu, TranslationBlock *tb,
CPUState *cs = CPU(cpu); CPUState *cs = CPU(cpu);
DisasContext ctx; DisasContext ctx;
target_ulong pc_start; target_ulong pc_start;
uint16_t *gen_opc_end;
CPUBreakpoint *bp; CPUBreakpoint *bp;
int j, lj = -1; int j, lj = -1;
CPUMoxieState *env = &cpu->env; CPUMoxieState *env = &cpu->env;
int num_insns; int num_insns;
pc_start = tb->pc; pc_start = tb->pc;
gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
ctx.pc = pc_start; ctx.pc = pc_start;
ctx.saved_pc = -1; ctx.saved_pc = -1;
ctx.tb = tb; ctx.tb = tb;
@ -857,7 +855,7 @@ gen_intermediate_code_internal(MoxieCPU *cpu, TranslationBlock *tb,
} }
if (search_pc) { if (search_pc) {
j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf; j = tcg_op_buf_count();
if (lj < j) { if (lj < j) {
lj++; lj++;
while (lj < j) { while (lj < j) {
@ -879,7 +877,7 @@ gen_intermediate_code_internal(MoxieCPU *cpu, TranslationBlock *tb,
if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0) { if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0) {
break; break;
} }
} while (ctx.bstate == BS_NONE && tcg_ctx.gen_opc_ptr < gen_opc_end); } while (ctx.bstate == BS_NONE && !tcg_op_buf_full());
if (cs->singlestep_enabled) { if (cs->singlestep_enabled) {
tcg_gen_movi_tl(cpu_pc, ctx.pc); tcg_gen_movi_tl(cpu_pc, ctx.pc);
@ -900,9 +898,9 @@ gen_intermediate_code_internal(MoxieCPU *cpu, TranslationBlock *tb,
} }
done_generating: done_generating:
gen_tb_end(tb, num_insns); gen_tb_end(tb, num_insns);
*tcg_ctx.gen_opc_ptr = INDEX_op_end;
if (search_pc) { if (search_pc) {
j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf; j = tcg_op_buf_count();
lj++; lj++;
while (lj <= j) { while (lj <= j) {
tcg_ctx.gen_opc_instr_start[lj++] = 0; tcg_ctx.gen_opc_instr_start[lj++] = 0;

View file

@ -1642,7 +1642,6 @@ static inline void gen_intermediate_code_internal(OpenRISCCPU *cpu,
{ {
CPUState *cs = CPU(cpu); CPUState *cs = CPU(cpu);
struct DisasContext ctx, *dc = &ctx; struct DisasContext ctx, *dc = &ctx;
uint16_t *gen_opc_end;
uint32_t pc_start; uint32_t pc_start;
int j, k; int j, k;
uint32_t next_page_start; uint32_t next_page_start;
@ -1652,7 +1651,6 @@ static inline void gen_intermediate_code_internal(OpenRISCCPU *cpu,
pc_start = tb->pc; pc_start = tb->pc;
dc->tb = tb; dc->tb = tb;
gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
dc->is_jmp = DISAS_NEXT; dc->is_jmp = DISAS_NEXT;
dc->ppc = pc_start; dc->ppc = pc_start;
dc->pc = pc_start; dc->pc = pc_start;
@ -1680,7 +1678,7 @@ static inline void gen_intermediate_code_internal(OpenRISCCPU *cpu,
do { do {
check_breakpoint(cpu, dc); check_breakpoint(cpu, dc);
if (search_pc) { if (search_pc) {
j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf; j = tcg_op_buf_count();
if (k < j) { if (k < j) {
k++; k++;
while (k < j) { while (k < j) {
@ -1721,7 +1719,7 @@ static inline void gen_intermediate_code_internal(OpenRISCCPU *cpu,
} }
} }
} while (!dc->is_jmp } while (!dc->is_jmp
&& tcg_ctx.gen_opc_ptr < gen_opc_end && !tcg_op_buf_full()
&& !cs->singlestep_enabled && !cs->singlestep_enabled
&& !singlestep && !singlestep
&& (dc->pc < next_page_start) && (dc->pc < next_page_start)
@ -1759,9 +1757,9 @@ static inline void gen_intermediate_code_internal(OpenRISCCPU *cpu,
} }
gen_tb_end(tb, num_insns); gen_tb_end(tb, num_insns);
*tcg_ctx.gen_opc_ptr = INDEX_op_end;
if (search_pc) { if (search_pc) {
j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf; j = tcg_op_buf_count();
k++; k++;
while (k <= j) { while (k <= j) {
tcg_ctx.gen_opc_instr_start[k++] = 0; tcg_ctx.gen_opc_instr_start[k++] = 0;
@ -1775,9 +1773,8 @@ static inline void gen_intermediate_code_internal(OpenRISCCPU *cpu,
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) { if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
qemu_log("\n"); qemu_log("\n");
log_target_disas(&cpu->env, pc_start, dc->pc - pc_start, 0); log_target_disas(&cpu->env, pc_start, dc->pc - pc_start, 0);
qemu_log("\nisize=%d osize=%td\n", qemu_log("\nisize=%d osize=%d\n",
dc->pc - pc_start, tcg_ctx.gen_opc_ptr - dc->pc - pc_start, tcg_op_buf_count());
tcg_ctx.gen_opc_buf);
} }
#endif #endif
} }

View file

@ -11415,14 +11415,12 @@ static inline void gen_intermediate_code_internal(PowerPCCPU *cpu,
DisasContext ctx, *ctxp = &ctx; DisasContext ctx, *ctxp = &ctx;
opc_handler_t **table, *handler; opc_handler_t **table, *handler;
target_ulong pc_start; target_ulong pc_start;
uint16_t *gen_opc_end;
CPUBreakpoint *bp; CPUBreakpoint *bp;
int j, lj = -1; int j, lj = -1;
int num_insns; int num_insns;
int max_insns; int max_insns;
pc_start = tb->pc; pc_start = tb->pc;
gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
ctx.nip = pc_start; ctx.nip = pc_start;
ctx.tb = tb; ctx.tb = tb;
ctx.exception = POWERPC_EXCP_NONE; ctx.exception = POWERPC_EXCP_NONE;
@ -11481,8 +11479,7 @@ static inline void gen_intermediate_code_internal(PowerPCCPU *cpu,
gen_tb_start(tb); gen_tb_start(tb);
tcg_clear_temp_count(); tcg_clear_temp_count();
/* Set env in case of segfault during code fetch */ /* Set env in case of segfault during code fetch */
while (ctx.exception == POWERPC_EXCP_NONE while (ctx.exception == POWERPC_EXCP_NONE && !tcg_op_buf_full()) {
&& tcg_ctx.gen_opc_ptr < gen_opc_end) {
if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) { if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
QTAILQ_FOREACH(bp, &cs->breakpoints, entry) { QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
if (bp->pc == ctx.nip) { if (bp->pc == ctx.nip) {
@ -11492,7 +11489,7 @@ static inline void gen_intermediate_code_internal(PowerPCCPU *cpu,
} }
} }
if (unlikely(search_pc)) { if (unlikely(search_pc)) {
j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf; j = tcg_op_buf_count();
if (lj < j) { if (lj < j) {
lj++; lj++;
while (lj < j) while (lj < j)
@ -11598,9 +11595,9 @@ static inline void gen_intermediate_code_internal(PowerPCCPU *cpu,
tcg_gen_exit_tb(0); tcg_gen_exit_tb(0);
} }
gen_tb_end(tb, num_insns); gen_tb_end(tb, num_insns);
*tcg_ctx.gen_opc_ptr = INDEX_op_end;
if (unlikely(search_pc)) { if (unlikely(search_pc)) {
j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf; j = tcg_op_buf_count();
lj++; lj++;
while (lj <= j) while (lj <= j)
tcg_ctx.gen_opc_instr_start[lj++] = 0; tcg_ctx.gen_opc_instr_start[lj++] = 0;

View file

@ -4832,7 +4832,6 @@ static inline void gen_intermediate_code_internal(S390CPU *cpu,
DisasContext dc; DisasContext dc;
target_ulong pc_start; target_ulong pc_start;
uint64_t next_page_start; uint64_t next_page_start;
uint16_t *gen_opc_end;
int j, lj = -1; int j, lj = -1;
int num_insns, max_insns; int num_insns, max_insns;
CPUBreakpoint *bp; CPUBreakpoint *bp;
@ -4851,8 +4850,6 @@ static inline void gen_intermediate_code_internal(S390CPU *cpu,
dc.cc_op = CC_OP_DYNAMIC; dc.cc_op = CC_OP_DYNAMIC;
do_debug = dc.singlestep_enabled = cs->singlestep_enabled; do_debug = dc.singlestep_enabled = cs->singlestep_enabled;
gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE; next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
num_insns = 0; num_insns = 0;
@ -4865,7 +4862,7 @@ static inline void gen_intermediate_code_internal(S390CPU *cpu,
do { do {
if (search_pc) { if (search_pc) {
j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf; j = tcg_op_buf_count();
if (lj < j) { if (lj < j) {
lj++; lj++;
while (lj < j) { while (lj < j) {
@ -4903,7 +4900,7 @@ static inline void gen_intermediate_code_internal(S390CPU *cpu,
or exhaust instruction count, stop generation. */ or exhaust instruction count, stop generation. */
if (status == NO_EXIT if (status == NO_EXIT
&& (dc.pc >= next_page_start && (dc.pc >= next_page_start
|| tcg_ctx.gen_opc_ptr >= gen_opc_end || tcg_op_buf_full()
|| num_insns >= max_insns || num_insns >= max_insns
|| singlestep || singlestep
|| cs->singlestep_enabled)) { || cs->singlestep_enabled)) {
@ -4938,9 +4935,9 @@ static inline void gen_intermediate_code_internal(S390CPU *cpu,
} }
gen_tb_end(tb, num_insns); gen_tb_end(tb, num_insns);
*tcg_ctx.gen_opc_ptr = INDEX_op_end;
if (search_pc) { if (search_pc) {
j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf; j = tcg_op_buf_count();
lj++; lj++;
while (lj <= j) { while (lj <= j) {
tcg_ctx.gen_opc_instr_start[lj++] = 0; tcg_ctx.gen_opc_instr_start[lj++] = 0;

View file

@ -1865,14 +1865,12 @@ gen_intermediate_code_internal(SuperHCPU *cpu, TranslationBlock *tb,
CPUSH4State *env = &cpu->env; CPUSH4State *env = &cpu->env;
DisasContext ctx; DisasContext ctx;
target_ulong pc_start; target_ulong pc_start;
static uint16_t *gen_opc_end;
CPUBreakpoint *bp; CPUBreakpoint *bp;
int i, ii; int i, ii;
int num_insns; int num_insns;
int max_insns; int max_insns;
pc_start = tb->pc; pc_start = tb->pc;
gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
ctx.pc = pc_start; ctx.pc = pc_start;
ctx.flags = (uint32_t)tb->flags; ctx.flags = (uint32_t)tb->flags;
ctx.bstate = BS_NONE; ctx.bstate = BS_NONE;
@ -1891,7 +1889,7 @@ gen_intermediate_code_internal(SuperHCPU *cpu, TranslationBlock *tb,
if (max_insns == 0) if (max_insns == 0)
max_insns = CF_COUNT_MASK; max_insns = CF_COUNT_MASK;
gen_tb_start(tb); gen_tb_start(tb);
while (ctx.bstate == BS_NONE && tcg_ctx.gen_opc_ptr < gen_opc_end) { while (ctx.bstate == BS_NONE && !tcg_op_buf_full()) {
if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) { if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
QTAILQ_FOREACH(bp, &cs->breakpoints, entry) { QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
if (ctx.pc == bp->pc) { if (ctx.pc == bp->pc) {
@ -1904,7 +1902,7 @@ gen_intermediate_code_internal(SuperHCPU *cpu, TranslationBlock *tb,
} }
} }
if (search_pc) { if (search_pc) {
i = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf; i = tcg_op_buf_count();
if (ii < i) { if (ii < i) {
ii++; ii++;
while (ii < i) while (ii < i)
@ -1962,9 +1960,9 @@ gen_intermediate_code_internal(SuperHCPU *cpu, TranslationBlock *tb,
} }
gen_tb_end(tb, num_insns); gen_tb_end(tb, num_insns);
*tcg_ctx.gen_opc_ptr = INDEX_op_end;
if (search_pc) { if (search_pc) {
i = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf; i = tcg_op_buf_count();
ii++; ii++;
while (ii <= i) while (ii <= i)
tcg_ctx.gen_opc_instr_start[ii++] = 0; tcg_ctx.gen_opc_instr_start[ii++] = 0;

View file

@ -5223,7 +5223,6 @@ static inline void gen_intermediate_code_internal(SPARCCPU *cpu,
CPUState *cs = CPU(cpu); CPUState *cs = CPU(cpu);
CPUSPARCState *env = &cpu->env; CPUSPARCState *env = &cpu->env;
target_ulong pc_start, last_pc; target_ulong pc_start, last_pc;
uint16_t *gen_opc_end;
DisasContext dc1, *dc = &dc1; DisasContext dc1, *dc = &dc1;
CPUBreakpoint *bp; CPUBreakpoint *bp;
int j, lj = -1; int j, lj = -1;
@ -5243,7 +5242,6 @@ static inline void gen_intermediate_code_internal(SPARCCPU *cpu,
dc->fpu_enabled = tb_fpu_enabled(tb->flags); dc->fpu_enabled = tb_fpu_enabled(tb->flags);
dc->address_mask_32bit = tb_am_enabled(tb->flags); dc->address_mask_32bit = tb_am_enabled(tb->flags);
dc->singlestep = (cs->singlestep_enabled || singlestep); dc->singlestep = (cs->singlestep_enabled || singlestep);
gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
num_insns = 0; num_insns = 0;
max_insns = tb->cflags & CF_COUNT_MASK; max_insns = tb->cflags & CF_COUNT_MASK;
@ -5265,7 +5263,7 @@ static inline void gen_intermediate_code_internal(SPARCCPU *cpu,
} }
if (spc) { if (spc) {
qemu_log("Search PC...\n"); qemu_log("Search PC...\n");
j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf; j = tcg_op_buf_count();
if (lj < j) { if (lj < j) {
lj++; lj++;
while (lj < j) while (lj < j)
@ -5298,7 +5296,7 @@ static inline void gen_intermediate_code_internal(SPARCCPU *cpu,
if (dc->singlestep) { if (dc->singlestep) {
break; break;
} }
} while ((tcg_ctx.gen_opc_ptr < gen_opc_end) && } while (!tcg_op_buf_full() &&
(dc->pc - pc_start) < (TARGET_PAGE_SIZE - 32) && (dc->pc - pc_start) < (TARGET_PAGE_SIZE - 32) &&
num_insns < max_insns); num_insns < max_insns);
@ -5320,9 +5318,9 @@ static inline void gen_intermediate_code_internal(SPARCCPU *cpu,
} }
} }
gen_tb_end(tb, num_insns); gen_tb_end(tb, num_insns);
*tcg_ctx.gen_opc_ptr = INDEX_op_end;
if (spc) { if (spc) {
j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf; j = tcg_op_buf_count();
lj++; lj++;
while (lj <= j) while (lj <= j)
tcg_ctx.gen_opc_instr_start[lj++] = 0; tcg_ctx.gen_opc_instr_start[lj++] = 0;

View file

@ -5500,7 +5500,6 @@ gen_intermediate_code_internal(TriCoreCPU *cpu, struct TranslationBlock *tb,
DisasContext ctx; DisasContext ctx;
target_ulong pc_start; target_ulong pc_start;
int num_insns; int num_insns;
uint16_t *gen_opc_end;
if (search_pc) { if (search_pc) {
qemu_log("search pc %d\n", search_pc); qemu_log("search pc %d\n", search_pc);
@ -5508,7 +5507,6 @@ gen_intermediate_code_internal(TriCoreCPU *cpu, struct TranslationBlock *tb,
num_insns = 0; num_insns = 0;
pc_start = tb->pc; pc_start = tb->pc;
gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
ctx.pc = pc_start; ctx.pc = pc_start;
ctx.saved_pc = -1; ctx.saved_pc = -1;
ctx.tb = tb; ctx.tb = tb;
@ -5524,7 +5522,7 @@ gen_intermediate_code_internal(TriCoreCPU *cpu, struct TranslationBlock *tb,
num_insns++; num_insns++;
if (tcg_ctx.gen_opc_ptr >= gen_opc_end) { if (tcg_op_buf_full()) {
gen_save_pc(ctx.next_pc); gen_save_pc(ctx.next_pc);
tcg_gen_exit_tb(0); tcg_gen_exit_tb(0);
break; break;
@ -5538,7 +5536,6 @@ gen_intermediate_code_internal(TriCoreCPU *cpu, struct TranslationBlock *tb,
} }
gen_tb_end(tb, num_insns); gen_tb_end(tb, num_insns);
*tcg_ctx.gen_opc_ptr = INDEX_op_end;
if (search_pc) { if (search_pc) {
printf("done_generating search pc\n"); printf("done_generating search pc\n");
} else { } else {

View file

@ -1877,7 +1877,6 @@ static inline void gen_intermediate_code_internal(UniCore32CPU *cpu,
CPUUniCore32State *env = &cpu->env; CPUUniCore32State *env = &cpu->env;
DisasContext dc1, *dc = &dc1; DisasContext dc1, *dc = &dc1;
CPUBreakpoint *bp; CPUBreakpoint *bp;
uint16_t *gen_opc_end;
int j, lj; int j, lj;
target_ulong pc_start; target_ulong pc_start;
uint32_t next_page_start; uint32_t next_page_start;
@ -1891,8 +1890,6 @@ static inline void gen_intermediate_code_internal(UniCore32CPU *cpu,
dc->tb = tb; dc->tb = tb;
gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
dc->is_jmp = DISAS_NEXT; dc->is_jmp = DISAS_NEXT;
dc->pc = pc_start; dc->pc = pc_start;
dc->singlestep_enabled = cs->singlestep_enabled; dc->singlestep_enabled = cs->singlestep_enabled;
@ -1933,7 +1930,7 @@ static inline void gen_intermediate_code_internal(UniCore32CPU *cpu,
} }
} }
if (search_pc) { if (search_pc) {
j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf; j = tcg_op_buf_count();
if (lj < j) { if (lj < j) {
lj++; lj++;
while (lj < j) { while (lj < j) {
@ -1965,7 +1962,7 @@ static inline void gen_intermediate_code_internal(UniCore32CPU *cpu,
* Also stop translation when a page boundary is reached. This * Also stop translation when a page boundary is reached. This
* ensures prefetch aborts occur at the right place. */ * ensures prefetch aborts occur at the right place. */
num_insns++; num_insns++;
} while (!dc->is_jmp && tcg_ctx.gen_opc_ptr < gen_opc_end && } while (!dc->is_jmp && !tcg_op_buf_full() &&
!cs->singlestep_enabled && !cs->singlestep_enabled &&
!singlestep && !singlestep &&
dc->pc < next_page_start && dc->pc < next_page_start &&
@ -2037,7 +2034,6 @@ static inline void gen_intermediate_code_internal(UniCore32CPU *cpu,
done_generating: done_generating:
gen_tb_end(tb, num_insns); gen_tb_end(tb, num_insns);
*tcg_ctx.gen_opc_ptr = INDEX_op_end;
#ifdef DEBUG_DISAS #ifdef DEBUG_DISAS
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) { if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
@ -2048,7 +2044,7 @@ done_generating:
} }
#endif #endif
if (search_pc) { if (search_pc) {
j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf; j = tcg_op_buf_count();
lj++; lj++;
while (lj <= j) { while (lj <= j) {
tcg_ctx.gen_opc_instr_start[lj++] = 0; tcg_ctx.gen_opc_instr_start[lj++] = 0;

View file

@ -3021,7 +3021,6 @@ void gen_intermediate_code_internal(XtensaCPU *cpu,
DisasContext dc; DisasContext dc;
int insn_count = 0; int insn_count = 0;
int j, lj = -1; int j, lj = -1;
uint16_t *gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
int max_insns = tb->cflags & CF_COUNT_MASK; int max_insns = tb->cflags & CF_COUNT_MASK;
uint32_t pc_start = tb->pc; uint32_t pc_start = tb->pc;
uint32_t next_page_start = uint32_t next_page_start =
@ -3065,7 +3064,7 @@ void gen_intermediate_code_internal(XtensaCPU *cpu,
check_breakpoint(env, &dc); check_breakpoint(env, &dc);
if (search_pc) { if (search_pc) {
j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf; j = tcg_op_buf_count();
if (lj < j) { if (lj < j) {
lj++; lj++;
while (lj < j) { while (lj < j) {
@ -3117,7 +3116,7 @@ void gen_intermediate_code_internal(XtensaCPU *cpu,
insn_count < max_insns && insn_count < max_insns &&
dc.pc < next_page_start && dc.pc < next_page_start &&
dc.pc + xtensa_insn_len(env, &dc) <= next_page_start && dc.pc + xtensa_insn_len(env, &dc) <= next_page_start &&
tcg_ctx.gen_opc_ptr < gen_opc_end); !tcg_op_buf_full());
reset_litbase(&dc); reset_litbase(&dc);
reset_sar_tracker(&dc); reset_sar_tracker(&dc);
@ -3133,7 +3132,6 @@ void gen_intermediate_code_internal(XtensaCPU *cpu,
gen_jumpi(&dc, dc.pc, 0); gen_jumpi(&dc, dc.pc, 0);
} }
gen_tb_end(tb, insn_count); gen_tb_end(tb, insn_count);
*tcg_ctx.gen_opc_ptr = INDEX_op_end;
#ifdef DEBUG_DISAS #ifdef DEBUG_DISAS
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) { if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
@ -3144,7 +3142,7 @@ void gen_intermediate_code_internal(XtensaCPU *cpu,
} }
#endif #endif
if (search_pc) { if (search_pc) {
j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf; j = tcg_op_buf_count();
memset(tcg_ctx.gen_opc_instr_start + lj + 1, 0, memset(tcg_ctx.gen_opc_instr_start + lj + 1, 0,
(j - lj) * sizeof(tcg_ctx.gen_opc_instr_start[0])); (j - lj) * sizeof(tcg_ctx.gen_opc_instr_start[0]));
} else { } else {

View file

@ -67,6 +67,37 @@ static void reset_temp(TCGArg temp)
temps[temp].mask = -1; temps[temp].mask = -1;
} }
static TCGOp *insert_op_before(TCGContext *s, TCGOp *old_op,
TCGOpcode opc, int nargs)
{
int oi = s->gen_next_op_idx;
int pi = s->gen_next_parm_idx;
int prev = old_op->prev;
int next = old_op - s->gen_op_buf;
TCGOp *new_op;
tcg_debug_assert(oi < OPC_BUF_SIZE);
tcg_debug_assert(pi + nargs <= OPPARAM_BUF_SIZE);
s->gen_next_op_idx = oi + 1;
s->gen_next_parm_idx = pi + nargs;
new_op = &s->gen_op_buf[oi];
*new_op = (TCGOp){
.opc = opc,
.args = pi,
.prev = prev,
.next = next
};
if (prev >= 0) {
s->gen_op_buf[prev].next = oi;
} else {
s->gen_first_op_idx = oi;
}
old_op->prev = oi;
return new_op;
}
/* Reset all temporaries, given that there are NB_TEMPS of them. */ /* Reset all temporaries, given that there are NB_TEMPS of them. */
static void reset_all_temps(int nb_temps) static void reset_all_temps(int nb_temps)
{ {
@ -162,13 +193,13 @@ static bool temps_are_copies(TCGArg arg1, TCGArg arg2)
return false; return false;
} }
static void tcg_opt_gen_mov(TCGContext *s, int op_index, TCGArg *gen_args, static void tcg_opt_gen_mov(TCGContext *s, TCGOp *op, TCGArg *args,
TCGOpcode old_op, TCGArg dst, TCGArg src) TCGOpcode old_op, TCGArg dst, TCGArg src)
{ {
TCGOpcode new_op = op_to_mov(old_op); TCGOpcode new_op = op_to_mov(old_op);
tcg_target_ulong mask; tcg_target_ulong mask;
s->gen_opc_buf[op_index] = new_op; op->opc = new_op;
reset_temp(dst); reset_temp(dst);
mask = temps[src].mask; mask = temps[src].mask;
@ -193,17 +224,17 @@ static void tcg_opt_gen_mov(TCGContext *s, int op_index, TCGArg *gen_args,
temps[src].next_copy = dst; temps[src].next_copy = dst;
} }
gen_args[0] = dst; args[0] = dst;
gen_args[1] = src; args[1] = src;
} }
static void tcg_opt_gen_movi(TCGContext *s, int op_index, TCGArg *gen_args, static void tcg_opt_gen_movi(TCGContext *s, TCGOp *op, TCGArg *args,
TCGOpcode old_op, TCGArg dst, TCGArg val) TCGOpcode old_op, TCGArg dst, TCGArg val)
{ {
TCGOpcode new_op = op_to_movi(old_op); TCGOpcode new_op = op_to_movi(old_op);
tcg_target_ulong mask; tcg_target_ulong mask;
s->gen_opc_buf[op_index] = new_op; op->opc = new_op;
reset_temp(dst); reset_temp(dst);
temps[dst].state = TCG_TEMP_CONST; temps[dst].state = TCG_TEMP_CONST;
@ -215,8 +246,8 @@ static void tcg_opt_gen_movi(TCGContext *s, int op_index, TCGArg *gen_args,
} }
temps[dst].mask = mask; temps[dst].mask = mask;
gen_args[0] = dst; args[0] = dst;
gen_args[1] = val; args[1] = val;
} }
static TCGArg do_constant_folding_2(TCGOpcode op, TCGArg x, TCGArg y) static TCGArg do_constant_folding_2(TCGOpcode op, TCGArg x, TCGArg y)
@ -533,11 +564,9 @@ static bool swap_commutative2(TCGArg *p1, TCGArg *p2)
} }
/* Propagate constants and copies, fold constant expressions. */ /* Propagate constants and copies, fold constant expressions. */
static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, static void tcg_constant_folding(TCGContext *s)
TCGArg *args, TCGOpDef *tcg_op_defs)
{ {
int nb_ops, op_index, nb_temps, nb_globals; int oi, oi_next, nb_temps, nb_globals;
TCGArg *gen_args;
/* Array VALS has an element for each temp. /* Array VALS has an element for each temp.
If this temp holds a constant then its value is kept in VALS' element. If this temp holds a constant then its value is kept in VALS' element.
@ -548,24 +577,23 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
nb_globals = s->nb_globals; nb_globals = s->nb_globals;
reset_all_temps(nb_temps); reset_all_temps(nb_temps);
nb_ops = tcg_opc_ptr - s->gen_opc_buf; for (oi = s->gen_first_op_idx; oi >= 0; oi = oi_next) {
gen_args = args;
for (op_index = 0; op_index < nb_ops; op_index++) {
TCGOpcode op = s->gen_opc_buf[op_index];
const TCGOpDef *def = &tcg_op_defs[op];
tcg_target_ulong mask, partmask, affected; tcg_target_ulong mask, partmask, affected;
int nb_oargs, nb_iargs, nb_args, i; int nb_oargs, nb_iargs, i;
TCGArg tmp; TCGArg tmp;
if (op == INDEX_op_call) { TCGOp * const op = &s->gen_op_buf[oi];
*gen_args++ = tmp = *args++; TCGArg * const args = &s->gen_opparam_buf[op->args];
nb_oargs = tmp >> 16; TCGOpcode opc = op->opc;
nb_iargs = tmp & 0xffff; const TCGOpDef *def = &tcg_op_defs[opc];
nb_args = nb_oargs + nb_iargs + def->nb_cargs;
oi_next = op->next;
if (opc == INDEX_op_call) {
nb_oargs = op->callo;
nb_iargs = op->calli;
} else { } else {
nb_oargs = def->nb_oargs; nb_oargs = def->nb_oargs;
nb_iargs = def->nb_iargs; nb_iargs = def->nb_iargs;
nb_args = def->nb_args;
} }
/* Do copy propagation */ /* Do copy propagation */
@ -576,7 +604,7 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
} }
/* For commutative operations make constant second argument */ /* For commutative operations make constant second argument */
switch (op) { switch (opc) {
CASE_OP_32_64(add): CASE_OP_32_64(add):
CASE_OP_32_64(mul): CASE_OP_32_64(mul):
CASE_OP_32_64(and): CASE_OP_32_64(and):
@ -634,7 +662,7 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
/* Simplify expressions for "shift/rot r, 0, a => movi r, 0", /* Simplify expressions for "shift/rot r, 0, a => movi r, 0",
and "sub r, 0, a => neg r, a" case. */ and "sub r, 0, a => neg r, a" case. */
switch (op) { switch (opc) {
CASE_OP_32_64(shl): CASE_OP_32_64(shl):
CASE_OP_32_64(shr): CASE_OP_32_64(shr):
CASE_OP_32_64(sar): CASE_OP_32_64(sar):
@ -642,9 +670,7 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
CASE_OP_32_64(rotr): CASE_OP_32_64(rotr):
if (temps[args[1]].state == TCG_TEMP_CONST if (temps[args[1]].state == TCG_TEMP_CONST
&& temps[args[1]].val == 0) { && temps[args[1]].val == 0) {
tcg_opt_gen_movi(s, op_index, gen_args, op, args[0], 0); tcg_opt_gen_movi(s, op, args, opc, args[0], 0);
args += 3;
gen_args += 2;
continue; continue;
} }
break; break;
@ -657,7 +683,7 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
/* Proceed with possible constant folding. */ /* Proceed with possible constant folding. */
break; break;
} }
if (op == INDEX_op_sub_i32) { if (opc == INDEX_op_sub_i32) {
neg_op = INDEX_op_neg_i32; neg_op = INDEX_op_neg_i32;
have_neg = TCG_TARGET_HAS_neg_i32; have_neg = TCG_TARGET_HAS_neg_i32;
} else { } else {
@ -669,12 +695,9 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
} }
if (temps[args[1]].state == TCG_TEMP_CONST if (temps[args[1]].state == TCG_TEMP_CONST
&& temps[args[1]].val == 0) { && temps[args[1]].val == 0) {
s->gen_opc_buf[op_index] = neg_op; op->opc = neg_op;
reset_temp(args[0]); reset_temp(args[0]);
gen_args[0] = args[0]; args[1] = args[2];
gen_args[1] = args[2];
args += 3;
gen_args += 2;
continue; continue;
} }
} }
@ -728,12 +751,9 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
if (!have_not) { if (!have_not) {
break; break;
} }
s->gen_opc_buf[op_index] = not_op; op->opc = not_op;
reset_temp(args[0]); reset_temp(args[0]);
gen_args[0] = args[0]; args[1] = args[i];
gen_args[1] = args[i];
args += 3;
gen_args += 2;
continue; continue;
} }
default: default:
@ -741,7 +761,7 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
} }
/* Simplify expression for "op r, a, const => mov r, a" cases */ /* Simplify expression for "op r, a, const => mov r, a" cases */
switch (op) { switch (opc) {
CASE_OP_32_64(add): CASE_OP_32_64(add):
CASE_OP_32_64(sub): CASE_OP_32_64(sub):
CASE_OP_32_64(shl): CASE_OP_32_64(shl):
@ -769,12 +789,10 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
break; break;
do_mov3: do_mov3:
if (temps_are_copies(args[0], args[1])) { if (temps_are_copies(args[0], args[1])) {
s->gen_opc_buf[op_index] = INDEX_op_nop; tcg_op_remove(s, op);
} else { } else {
tcg_opt_gen_mov(s, op_index, gen_args, op, args[0], args[1]); tcg_opt_gen_mov(s, op, args, opc, args[0], args[1]);
gen_args += 2;
} }
args += 3;
continue; continue;
default: default:
break; break;
@ -784,7 +802,7 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
output argument is supported. */ output argument is supported. */
mask = -1; mask = -1;
affected = -1; affected = -1;
switch (op) { switch (opc) {
CASE_OP_32_64(ext8s): CASE_OP_32_64(ext8s):
if ((temps[args[1]].mask & 0x80) != 0) { if ((temps[args[1]].mask & 0x80) != 0) {
break; break;
@ -923,38 +941,31 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
if (partmask == 0) { if (partmask == 0) {
assert(nb_oargs == 1); assert(nb_oargs == 1);
tcg_opt_gen_movi(s, op_index, gen_args, op, args[0], 0); tcg_opt_gen_movi(s, op, args, opc, args[0], 0);
args += nb_args;
gen_args += 2;
continue; continue;
} }
if (affected == 0) { if (affected == 0) {
assert(nb_oargs == 1); assert(nb_oargs == 1);
if (temps_are_copies(args[0], args[1])) { if (temps_are_copies(args[0], args[1])) {
s->gen_opc_buf[op_index] = INDEX_op_nop; tcg_op_remove(s, op);
} else if (temps[args[1]].state != TCG_TEMP_CONST) { } else if (temps[args[1]].state != TCG_TEMP_CONST) {
tcg_opt_gen_mov(s, op_index, gen_args, op, args[0], args[1]); tcg_opt_gen_mov(s, op, args, opc, args[0], args[1]);
gen_args += 2;
} else { } else {
tcg_opt_gen_movi(s, op_index, gen_args, op, tcg_opt_gen_movi(s, op, args, opc,
args[0], temps[args[1]].val); args[0], temps[args[1]].val);
gen_args += 2;
} }
args += nb_args;
continue; continue;
} }
/* Simplify expression for "op r, a, 0 => movi r, 0" cases */ /* Simplify expression for "op r, a, 0 => movi r, 0" cases */
switch (op) { switch (opc) {
CASE_OP_32_64(and): CASE_OP_32_64(and):
CASE_OP_32_64(mul): CASE_OP_32_64(mul):
CASE_OP_32_64(muluh): CASE_OP_32_64(muluh):
CASE_OP_32_64(mulsh): CASE_OP_32_64(mulsh):
if ((temps[args[2]].state == TCG_TEMP_CONST if ((temps[args[2]].state == TCG_TEMP_CONST
&& temps[args[2]].val == 0)) { && temps[args[2]].val == 0)) {
tcg_opt_gen_movi(s, op_index, gen_args, op, args[0], 0); tcg_opt_gen_movi(s, op, args, opc, args[0], 0);
args += 3;
gen_args += 2;
continue; continue;
} }
break; break;
@ -963,18 +974,15 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
} }
/* Simplify expression for "op r, a, a => mov r, a" cases */ /* Simplify expression for "op r, a, a => mov r, a" cases */
switch (op) { switch (opc) {
CASE_OP_32_64(or): CASE_OP_32_64(or):
CASE_OP_32_64(and): CASE_OP_32_64(and):
if (temps_are_copies(args[1], args[2])) { if (temps_are_copies(args[1], args[2])) {
if (temps_are_copies(args[0], args[1])) { if (temps_are_copies(args[0], args[1])) {
s->gen_opc_buf[op_index] = INDEX_op_nop; tcg_op_remove(s, op);
} else { } else {
tcg_opt_gen_mov(s, op_index, gen_args, op, tcg_opt_gen_mov(s, op, args, opc, args[0], args[1]);
args[0], args[1]);
gen_args += 2;
} }
args += 3;
continue; continue;
} }
break; break;
@ -983,14 +991,12 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
} }
/* Simplify expression for "op r, a, a => movi r, 0" cases */ /* Simplify expression for "op r, a, a => movi r, 0" cases */
switch (op) { switch (opc) {
CASE_OP_32_64(andc): CASE_OP_32_64(andc):
CASE_OP_32_64(sub): CASE_OP_32_64(sub):
CASE_OP_32_64(xor): CASE_OP_32_64(xor):
if (temps_are_copies(args[1], args[2])) { if (temps_are_copies(args[1], args[2])) {
tcg_opt_gen_movi(s, op_index, gen_args, op, args[0], 0); tcg_opt_gen_movi(s, op, args, opc, args[0], 0);
gen_args += 2;
args += 3;
continue; continue;
} }
break; break;
@ -1001,17 +1007,14 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
/* Propagate constants through copy operations and do constant /* Propagate constants through copy operations and do constant
folding. Constants will be substituted to arguments by register folding. Constants will be substituted to arguments by register
allocator where needed and possible. Also detect copies. */ allocator where needed and possible. Also detect copies. */
switch (op) { switch (opc) {
CASE_OP_32_64(mov): CASE_OP_32_64(mov):
if (temps_are_copies(args[0], args[1])) { if (temps_are_copies(args[0], args[1])) {
args += 2; tcg_op_remove(s, op);
s->gen_opc_buf[op_index] = INDEX_op_nop;
break; break;
} }
if (temps[args[1]].state != TCG_TEMP_CONST) { if (temps[args[1]].state != TCG_TEMP_CONST) {
tcg_opt_gen_mov(s, op_index, gen_args, op, args[0], args[1]); tcg_opt_gen_mov(s, op, args, opc, args[0], args[1]);
gen_args += 2;
args += 2;
break; break;
} }
/* Source argument is constant. Rewrite the operation and /* Source argument is constant. Rewrite the operation and
@ -1019,9 +1022,7 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
args[1] = temps[args[1]].val; args[1] = temps[args[1]].val;
/* fallthrough */ /* fallthrough */
CASE_OP_32_64(movi): CASE_OP_32_64(movi):
tcg_opt_gen_movi(s, op_index, gen_args, op, args[0], args[1]); tcg_opt_gen_movi(s, op, args, opc, args[0], args[1]);
gen_args += 2;
args += 2;
break; break;
CASE_OP_32_64(not): CASE_OP_32_64(not):
@ -1033,20 +1034,16 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
case INDEX_op_ext32s_i64: case INDEX_op_ext32s_i64:
case INDEX_op_ext32u_i64: case INDEX_op_ext32u_i64:
if (temps[args[1]].state == TCG_TEMP_CONST) { if (temps[args[1]].state == TCG_TEMP_CONST) {
tmp = do_constant_folding(op, temps[args[1]].val, 0); tmp = do_constant_folding(opc, temps[args[1]].val, 0);
tcg_opt_gen_movi(s, op_index, gen_args, op, args[0], tmp); tcg_opt_gen_movi(s, op, args, opc, args[0], tmp);
gen_args += 2;
args += 2;
break; break;
} }
goto do_default; goto do_default;
case INDEX_op_trunc_shr_i32: case INDEX_op_trunc_shr_i32:
if (temps[args[1]].state == TCG_TEMP_CONST) { if (temps[args[1]].state == TCG_TEMP_CONST) {
tmp = do_constant_folding(op, temps[args[1]].val, args[2]); tmp = do_constant_folding(opc, temps[args[1]].val, args[2]);
tcg_opt_gen_movi(s, op_index, gen_args, op, args[0], tmp); tcg_opt_gen_movi(s, op, args, opc, args[0], tmp);
gen_args += 2;
args += 3;
break; break;
} }
goto do_default; goto do_default;
@ -1075,11 +1072,9 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
CASE_OP_32_64(remu): CASE_OP_32_64(remu):
if (temps[args[1]].state == TCG_TEMP_CONST if (temps[args[1]].state == TCG_TEMP_CONST
&& temps[args[2]].state == TCG_TEMP_CONST) { && temps[args[2]].state == TCG_TEMP_CONST) {
tmp = do_constant_folding(op, temps[args[1]].val, tmp = do_constant_folding(opc, temps[args[1]].val,
temps[args[2]].val); temps[args[2]].val);
tcg_opt_gen_movi(s, op_index, gen_args, op, args[0], tmp); tcg_opt_gen_movi(s, op, args, opc, args[0], tmp);
gen_args += 2;
args += 3;
break; break;
} }
goto do_default; goto do_default;
@ -1089,54 +1084,44 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
&& temps[args[2]].state == TCG_TEMP_CONST) { && temps[args[2]].state == TCG_TEMP_CONST) {
tmp = deposit64(temps[args[1]].val, args[3], args[4], tmp = deposit64(temps[args[1]].val, args[3], args[4],
temps[args[2]].val); temps[args[2]].val);
tcg_opt_gen_movi(s, op_index, gen_args, op, args[0], tmp); tcg_opt_gen_movi(s, op, args, opc, args[0], tmp);
gen_args += 2;
args += 5;
break; break;
} }
goto do_default; goto do_default;
CASE_OP_32_64(setcond): CASE_OP_32_64(setcond):
tmp = do_constant_folding_cond(op, args[1], args[2], args[3]); tmp = do_constant_folding_cond(opc, args[1], args[2], args[3]);
if (tmp != 2) { if (tmp != 2) {
tcg_opt_gen_movi(s, op_index, gen_args, op, args[0], tmp); tcg_opt_gen_movi(s, op, args, opc, args[0], tmp);
gen_args += 2;
args += 4;
break; break;
} }
goto do_default; goto do_default;
CASE_OP_32_64(brcond): CASE_OP_32_64(brcond):
tmp = do_constant_folding_cond(op, args[0], args[1], args[2]); tmp = do_constant_folding_cond(opc, args[0], args[1], args[2]);
if (tmp != 2) { if (tmp != 2) {
if (tmp) { if (tmp) {
reset_all_temps(nb_temps); reset_all_temps(nb_temps);
s->gen_opc_buf[op_index] = INDEX_op_br; op->opc = INDEX_op_br;
gen_args[0] = args[3]; args[0] = args[3];
gen_args += 1;
} else { } else {
s->gen_opc_buf[op_index] = INDEX_op_nop; tcg_op_remove(s, op);
} }
args += 4;
break; break;
} }
goto do_default; goto do_default;
CASE_OP_32_64(movcond): CASE_OP_32_64(movcond):
tmp = do_constant_folding_cond(op, args[1], args[2], args[5]); tmp = do_constant_folding_cond(opc, args[1], args[2], args[5]);
if (tmp != 2) { if (tmp != 2) {
if (temps_are_copies(args[0], args[4-tmp])) { if (temps_are_copies(args[0], args[4-tmp])) {
s->gen_opc_buf[op_index] = INDEX_op_nop; tcg_op_remove(s, op);
} else if (temps[args[4-tmp]].state == TCG_TEMP_CONST) { } else if (temps[args[4-tmp]].state == TCG_TEMP_CONST) {
tcg_opt_gen_movi(s, op_index, gen_args, op, tcg_opt_gen_movi(s, op, args, opc,
args[0], temps[args[4-tmp]].val); args[0], temps[args[4-tmp]].val);
gen_args += 2;
} else { } else {
tcg_opt_gen_mov(s, op_index, gen_args, op, tcg_opt_gen_mov(s, op, args, opc, args[0], args[4-tmp]);
args[0], args[4-tmp]);
gen_args += 2;
} }
args += 6;
break; break;
} }
goto do_default; goto do_default;
@ -1154,24 +1139,22 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
uint64_t a = ((uint64_t)ah << 32) | al; uint64_t a = ((uint64_t)ah << 32) | al;
uint64_t b = ((uint64_t)bh << 32) | bl; uint64_t b = ((uint64_t)bh << 32) | bl;
TCGArg rl, rh; TCGArg rl, rh;
TCGOp *op2 = insert_op_before(s, op, INDEX_op_movi_i32, 2);
TCGArg *args2 = &s->gen_opparam_buf[op2->args];
if (op == INDEX_op_add2_i32) { if (opc == INDEX_op_add2_i32) {
a += b; a += b;
} else { } else {
a -= b; a -= b;
} }
/* We emit the extra nop when we emit the add2/sub2. */
assert(s->gen_opc_buf[op_index + 1] == INDEX_op_nop);
rl = args[0]; rl = args[0];
rh = args[1]; rh = args[1];
tcg_opt_gen_movi(s, op_index, &gen_args[0], tcg_opt_gen_movi(s, op, args, opc, rl, (uint32_t)a);
op, rl, (uint32_t)a); tcg_opt_gen_movi(s, op2, args2, opc, rh, (uint32_t)(a >> 32));
tcg_opt_gen_movi(s, ++op_index, &gen_args[2],
op, rh, (uint32_t)(a >> 32)); /* We've done all we need to do with the movi. Skip it. */
gen_args += 4; oi_next = op2->next;
args += 6;
break; break;
} }
goto do_default; goto do_default;
@ -1183,18 +1166,16 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
uint32_t b = temps[args[3]].val; uint32_t b = temps[args[3]].val;
uint64_t r = (uint64_t)a * b; uint64_t r = (uint64_t)a * b;
TCGArg rl, rh; TCGArg rl, rh;
TCGOp *op2 = insert_op_before(s, op, INDEX_op_movi_i32, 2);
/* We emit the extra nop when we emit the mulu2. */ TCGArg *args2 = &s->gen_opparam_buf[op2->args];
assert(s->gen_opc_buf[op_index + 1] == INDEX_op_nop);
rl = args[0]; rl = args[0];
rh = args[1]; rh = args[1];
tcg_opt_gen_movi(s, op_index, &gen_args[0], tcg_opt_gen_movi(s, op, args, opc, rl, (uint32_t)r);
op, rl, (uint32_t)r); tcg_opt_gen_movi(s, op2, args2, opc, rh, (uint32_t)(r >> 32));
tcg_opt_gen_movi(s, ++op_index, &gen_args[2],
op, rh, (uint32_t)(r >> 32)); /* We've done all we need to do with the movi. Skip it. */
gen_args += 4; oi_next = op2->next;
args += 4;
break; break;
} }
goto do_default; goto do_default;
@ -1205,12 +1186,11 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
if (tmp) { if (tmp) {
do_brcond_true: do_brcond_true:
reset_all_temps(nb_temps); reset_all_temps(nb_temps);
s->gen_opc_buf[op_index] = INDEX_op_br; op->opc = INDEX_op_br;
gen_args[0] = args[5]; args[0] = args[5];
gen_args += 1;
} else { } else {
do_brcond_false: do_brcond_false:
s->gen_opc_buf[op_index] = INDEX_op_nop; tcg_op_remove(s, op);
} }
} else if ((args[4] == TCG_COND_LT || args[4] == TCG_COND_GE) } else if ((args[4] == TCG_COND_LT || args[4] == TCG_COND_GE)
&& temps[args[2]].state == TCG_TEMP_CONST && temps[args[2]].state == TCG_TEMP_CONST
@ -1221,12 +1201,11 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
vs the high word of the input. */ vs the high word of the input. */
do_brcond_high: do_brcond_high:
reset_all_temps(nb_temps); reset_all_temps(nb_temps);
s->gen_opc_buf[op_index] = INDEX_op_brcond_i32; op->opc = INDEX_op_brcond_i32;
gen_args[0] = args[1]; args[0] = args[1];
gen_args[1] = args[3]; args[1] = args[3];
gen_args[2] = args[4]; args[2] = args[4];
gen_args[3] = args[5]; args[3] = args[5];
gen_args += 4;
} else if (args[4] == TCG_COND_EQ) { } else if (args[4] == TCG_COND_EQ) {
/* Simplify EQ comparisons where one of the pairs /* Simplify EQ comparisons where one of the pairs
can be simplified. */ can be simplified. */
@ -1246,12 +1225,10 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
} }
do_brcond_low: do_brcond_low:
reset_all_temps(nb_temps); reset_all_temps(nb_temps);
s->gen_opc_buf[op_index] = INDEX_op_brcond_i32; op->opc = INDEX_op_brcond_i32;
gen_args[0] = args[0]; args[1] = args[2];
gen_args[1] = args[2]; args[2] = args[4];
gen_args[2] = args[4]; args[3] = args[5];
gen_args[3] = args[5];
gen_args += 4;
} else if (args[4] == TCG_COND_NE) { } else if (args[4] == TCG_COND_NE) {
/* Simplify NE comparisons where one of the pairs /* Simplify NE comparisons where one of the pairs
can be simplified. */ can be simplified. */
@ -1273,15 +1250,13 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
} else { } else {
goto do_default; goto do_default;
} }
args += 6;
break; break;
case INDEX_op_setcond2_i32: case INDEX_op_setcond2_i32:
tmp = do_constant_folding_cond2(&args[1], &args[3], args[5]); tmp = do_constant_folding_cond2(&args[1], &args[3], args[5]);
if (tmp != 2) { if (tmp != 2) {
do_setcond_const: do_setcond_const:
tcg_opt_gen_movi(s, op_index, gen_args, op, args[0], tmp); tcg_opt_gen_movi(s, op, args, opc, args[0], tmp);
gen_args += 2;
} else if ((args[5] == TCG_COND_LT || args[5] == TCG_COND_GE) } else if ((args[5] == TCG_COND_LT || args[5] == TCG_COND_GE)
&& temps[args[3]].state == TCG_TEMP_CONST && temps[args[3]].state == TCG_TEMP_CONST
&& temps[args[4]].state == TCG_TEMP_CONST && temps[args[4]].state == TCG_TEMP_CONST
@ -1290,14 +1265,12 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
/* Simplify LT/GE comparisons vs zero to a single compare /* Simplify LT/GE comparisons vs zero to a single compare
vs the high word of the input. */ vs the high word of the input. */
do_setcond_high: do_setcond_high:
s->gen_opc_buf[op_index] = INDEX_op_setcond_i32;
reset_temp(args[0]); reset_temp(args[0]);
temps[args[0]].mask = 1; temps[args[0]].mask = 1;
gen_args[0] = args[0]; op->opc = INDEX_op_setcond_i32;
gen_args[1] = args[2]; args[1] = args[2];
gen_args[2] = args[4]; args[2] = args[4];
gen_args[3] = args[5]; args[3] = args[5];
gen_args += 4;
} else if (args[5] == TCG_COND_EQ) { } else if (args[5] == TCG_COND_EQ) {
/* Simplify EQ comparisons where one of the pairs /* Simplify EQ comparisons where one of the pairs
can be simplified. */ can be simplified. */
@ -1318,12 +1291,9 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
do_setcond_low: do_setcond_low:
reset_temp(args[0]); reset_temp(args[0]);
temps[args[0]].mask = 1; temps[args[0]].mask = 1;
s->gen_opc_buf[op_index] = INDEX_op_setcond_i32; op->opc = INDEX_op_setcond_i32;
gen_args[0] = args[0]; args[2] = args[3];
gen_args[1] = args[1]; args[3] = args[5];
gen_args[2] = args[3];
gen_args[3] = args[5];
gen_args += 4;
} else if (args[5] == TCG_COND_NE) { } else if (args[5] == TCG_COND_NE) {
/* Simplify NE comparisons where one of the pairs /* Simplify NE comparisons where one of the pairs
can be simplified. */ can be simplified. */
@ -1345,7 +1315,6 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
} else { } else {
goto do_default; goto do_default;
} }
args += 6;
break; break;
case INDEX_op_call: case INDEX_op_call:
@ -1377,22 +1346,12 @@ static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
} }
} }
} }
for (i = 0; i < nb_args; i++) {
gen_args[i] = args[i];
}
args += nb_args;
gen_args += nb_args;
break; break;
} }
} }
return gen_args;
} }
TCGArg *tcg_optimize(TCGContext *s, uint16_t *tcg_opc_ptr, void tcg_optimize(TCGContext *s)
TCGArg *args, TCGOpDef *tcg_op_defs)
{ {
TCGArg *res; tcg_constant_folding(s);
res = tcg_constant_folding(s, tcg_opc_ptr, args, tcg_op_defs);
return res;
} }

1934
tcg/tcg-op.c Normal file

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -27,15 +27,6 @@
*/ */
/* predefined ops */ /* predefined ops */
DEF(end, 0, 0, 0, TCG_OPF_NOT_PRESENT) /* must be kept first */
DEF(nop, 0, 0, 0, TCG_OPF_NOT_PRESENT)
DEF(nop1, 0, 0, 1, TCG_OPF_NOT_PRESENT)
DEF(nop2, 0, 0, 2, TCG_OPF_NOT_PRESENT)
DEF(nop3, 0, 0, 3, TCG_OPF_NOT_PRESENT)
/* variable number of parameters */
DEF(nopn, 0, 0, 1, TCG_OPF_NOT_PRESENT)
DEF(discard, 1, 0, 0, TCG_OPF_NOT_PRESENT) DEF(discard, 1, 0, 0, TCG_OPF_NOT_PRESENT)
DEF(set_label, 0, 0, 1, TCG_OPF_BB_END | TCG_OPF_NOT_PRESENT) DEF(set_label, 0, 0, 1, TCG_OPF_BB_END | TCG_OPF_NOT_PRESENT)

536
tcg/tcg.c
View file

@ -407,7 +407,6 @@ void tcg_func_start(TCGContext *s)
/* No temps have been previously allocated for size or locality. */ /* No temps have been previously allocated for size or locality. */
memset(s->free_temps, 0, sizeof(s->free_temps)); memset(s->free_temps, 0, sizeof(s->free_temps));
s->labels = tcg_malloc(sizeof(TCGLabel) * TCG_MAX_LABELS);
s->nb_labels = 0; s->nb_labels = 0;
s->current_frame_offset = s->frame_start; s->current_frame_offset = s->frame_start;
@ -415,8 +414,10 @@ void tcg_func_start(TCGContext *s)
s->goto_tb_issue_mask = 0; s->goto_tb_issue_mask = 0;
#endif #endif
s->gen_opc_ptr = s->gen_opc_buf; s->gen_first_op_idx = 0;
s->gen_opparam_ptr = s->gen_opparam_buf; s->gen_last_op_idx = -1;
s->gen_next_op_idx = 0;
s->gen_next_parm_idx = 0;
s->be = tcg_malloc(sizeof(TCGBackendData)); s->be = tcg_malloc(sizeof(TCGBackendData));
} }
@ -703,9 +704,8 @@ int tcg_check_temp_count(void)
void tcg_gen_callN(TCGContext *s, void *func, TCGArg ret, void tcg_gen_callN(TCGContext *s, void *func, TCGArg ret,
int nargs, TCGArg *args) int nargs, TCGArg *args)
{ {
int i, real_args, nb_rets; int i, real_args, nb_rets, pi, pi_first;
unsigned sizemask, flags; unsigned sizemask, flags;
TCGArg *nparam;
TCGHelperInfo *info; TCGHelperInfo *info;
info = g_hash_table_lookup(s->helpers, (gpointer)func); info = g_hash_table_lookup(s->helpers, (gpointer)func);
@ -758,8 +758,7 @@ void tcg_gen_callN(TCGContext *s, void *func, TCGArg ret,
} }
#endif /* TCG_TARGET_EXTEND_ARGS */ #endif /* TCG_TARGET_EXTEND_ARGS */
*s->gen_opc_ptr++ = INDEX_op_call; pi_first = pi = s->gen_next_parm_idx;
nparam = s->gen_opparam_ptr++;
if (ret != TCG_CALL_DUMMY_ARG) { if (ret != TCG_CALL_DUMMY_ARG) {
#if defined(__sparc__) && !defined(__arch64__) \ #if defined(__sparc__) && !defined(__arch64__) \
&& !defined(CONFIG_TCG_INTERPRETER) && !defined(CONFIG_TCG_INTERPRETER)
@ -769,25 +768,25 @@ void tcg_gen_callN(TCGContext *s, void *func, TCGArg ret,
two return temporaries, and reassemble below. */ two return temporaries, and reassemble below. */
retl = tcg_temp_new_i64(); retl = tcg_temp_new_i64();
reth = tcg_temp_new_i64(); reth = tcg_temp_new_i64();
*s->gen_opparam_ptr++ = GET_TCGV_I64(reth); s->gen_opparam_buf[pi++] = GET_TCGV_I64(reth);
*s->gen_opparam_ptr++ = GET_TCGV_I64(retl); s->gen_opparam_buf[pi++] = GET_TCGV_I64(retl);
nb_rets = 2; nb_rets = 2;
} else { } else {
*s->gen_opparam_ptr++ = ret; s->gen_opparam_buf[pi++] = ret;
nb_rets = 1; nb_rets = 1;
} }
#else #else
if (TCG_TARGET_REG_BITS < 64 && (sizemask & 1)) { if (TCG_TARGET_REG_BITS < 64 && (sizemask & 1)) {
#ifdef HOST_WORDS_BIGENDIAN #ifdef HOST_WORDS_BIGENDIAN
*s->gen_opparam_ptr++ = ret + 1; s->gen_opparam_buf[pi++] = ret + 1;
*s->gen_opparam_ptr++ = ret; s->gen_opparam_buf[pi++] = ret;
#else #else
*s->gen_opparam_ptr++ = ret; s->gen_opparam_buf[pi++] = ret;
*s->gen_opparam_ptr++ = ret + 1; s->gen_opparam_buf[pi++] = ret + 1;
#endif #endif
nb_rets = 2; nb_rets = 2;
} else { } else {
*s->gen_opparam_ptr++ = ret; s->gen_opparam_buf[pi++] = ret;
nb_rets = 1; nb_rets = 1;
} }
#endif #endif
@ -801,7 +800,7 @@ void tcg_gen_callN(TCGContext *s, void *func, TCGArg ret,
#ifdef TCG_TARGET_CALL_ALIGN_ARGS #ifdef TCG_TARGET_CALL_ALIGN_ARGS
/* some targets want aligned 64 bit args */ /* some targets want aligned 64 bit args */
if (real_args & 1) { if (real_args & 1) {
*s->gen_opparam_ptr++ = TCG_CALL_DUMMY_ARG; s->gen_opparam_buf[pi++] = TCG_CALL_DUMMY_ARG;
real_args++; real_args++;
} }
#endif #endif
@ -816,26 +815,42 @@ void tcg_gen_callN(TCGContext *s, void *func, TCGArg ret,
have to get more complicated to differentiate between have to get more complicated to differentiate between
stack arguments and register arguments. */ stack arguments and register arguments. */
#if defined(HOST_WORDS_BIGENDIAN) != defined(TCG_TARGET_STACK_GROWSUP) #if defined(HOST_WORDS_BIGENDIAN) != defined(TCG_TARGET_STACK_GROWSUP)
*s->gen_opparam_ptr++ = args[i] + 1; s->gen_opparam_buf[pi++] = args[i] + 1;
*s->gen_opparam_ptr++ = args[i]; s->gen_opparam_buf[pi++] = args[i];
#else #else
*s->gen_opparam_ptr++ = args[i]; s->gen_opparam_buf[pi++] = args[i];
*s->gen_opparam_ptr++ = args[i] + 1; s->gen_opparam_buf[pi++] = args[i] + 1;
#endif #endif
real_args += 2; real_args += 2;
continue; continue;
} }
*s->gen_opparam_ptr++ = args[i]; s->gen_opparam_buf[pi++] = args[i];
real_args++; real_args++;
} }
*s->gen_opparam_ptr++ = (uintptr_t)func; s->gen_opparam_buf[pi++] = (uintptr_t)func;
*s->gen_opparam_ptr++ = flags; s->gen_opparam_buf[pi++] = flags;
*nparam = (nb_rets << 16) | real_args; i = s->gen_next_op_idx;
tcg_debug_assert(i < OPC_BUF_SIZE);
tcg_debug_assert(pi <= OPPARAM_BUF_SIZE);
/* total parameters, needed to go backward in the instruction stream */ /* Set links for sequential allocation during translation. */
*s->gen_opparam_ptr++ = 1 + nb_rets + real_args + 3; s->gen_op_buf[i] = (TCGOp){
.opc = INDEX_op_call,
.callo = nb_rets,
.calli = real_args,
.args = pi_first,
.prev = i - 1,
.next = i + 1
};
/* Make sure the calli field didn't overflow. */
tcg_debug_assert(s->gen_op_buf[i].calli == real_args);
s->gen_last_op_idx = i;
s->gen_next_op_idx = i + 1;
s->gen_next_parm_idx = pi;
#if defined(__sparc__) && !defined(__arch64__) \ #if defined(__sparc__) && !defined(__arch64__) \
&& !defined(CONFIG_TCG_INTERPRETER) && !defined(CONFIG_TCG_INTERPRETER)
@ -870,143 +885,6 @@ void tcg_gen_callN(TCGContext *s, void *func, TCGArg ret,
#endif /* TCG_TARGET_EXTEND_ARGS */ #endif /* TCG_TARGET_EXTEND_ARGS */
} }
#if TCG_TARGET_REG_BITS == 32
void tcg_gen_shifti_i64(TCGv_i64 ret, TCGv_i64 arg1,
int c, int right, int arith)
{
if (c == 0) {
tcg_gen_mov_i32(TCGV_LOW(ret), TCGV_LOW(arg1));
tcg_gen_mov_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1));
} else if (c >= 32) {
c -= 32;
if (right) {
if (arith) {
tcg_gen_sari_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c);
tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), 31);
} else {
tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_HIGH(arg1), c);
tcg_gen_movi_i32(TCGV_HIGH(ret), 0);
}
} else {
tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_LOW(arg1), c);
tcg_gen_movi_i32(TCGV_LOW(ret), 0);
}
} else {
TCGv_i32 t0, t1;
t0 = tcg_temp_new_i32();
t1 = tcg_temp_new_i32();
if (right) {
tcg_gen_shli_i32(t0, TCGV_HIGH(arg1), 32 - c);
if (arith)
tcg_gen_sari_i32(t1, TCGV_HIGH(arg1), c);
else
tcg_gen_shri_i32(t1, TCGV_HIGH(arg1), c);
tcg_gen_shri_i32(TCGV_LOW(ret), TCGV_LOW(arg1), c);
tcg_gen_or_i32(TCGV_LOW(ret), TCGV_LOW(ret), t0);
tcg_gen_mov_i32(TCGV_HIGH(ret), t1);
} else {
tcg_gen_shri_i32(t0, TCGV_LOW(arg1), 32 - c);
/* Note: ret can be the same as arg1, so we use t1 */
tcg_gen_shli_i32(t1, TCGV_LOW(arg1), c);
tcg_gen_shli_i32(TCGV_HIGH(ret), TCGV_HIGH(arg1), c);
tcg_gen_or_i32(TCGV_HIGH(ret), TCGV_HIGH(ret), t0);
tcg_gen_mov_i32(TCGV_LOW(ret), t1);
}
tcg_temp_free_i32(t0);
tcg_temp_free_i32(t1);
}
}
#endif
static inline TCGMemOp tcg_canonicalize_memop(TCGMemOp op, bool is64, bool st)
{
switch (op & MO_SIZE) {
case MO_8:
op &= ~MO_BSWAP;
break;
case MO_16:
break;
case MO_32:
if (!is64) {
op &= ~MO_SIGN;
}
break;
case MO_64:
if (!is64) {
tcg_abort();
}
break;
}
if (st) {
op &= ~MO_SIGN;
}
return op;
}
void tcg_gen_qemu_ld_i32(TCGv_i32 val, TCGv addr, TCGArg idx, TCGMemOp memop)
{
memop = tcg_canonicalize_memop(memop, 0, 0);
*tcg_ctx.gen_opc_ptr++ = INDEX_op_qemu_ld_i32;
tcg_add_param_i32(val);
tcg_add_param_tl(addr);
*tcg_ctx.gen_opparam_ptr++ = memop;
*tcg_ctx.gen_opparam_ptr++ = idx;
}
void tcg_gen_qemu_st_i32(TCGv_i32 val, TCGv addr, TCGArg idx, TCGMemOp memop)
{
memop = tcg_canonicalize_memop(memop, 0, 1);
*tcg_ctx.gen_opc_ptr++ = INDEX_op_qemu_st_i32;
tcg_add_param_i32(val);
tcg_add_param_tl(addr);
*tcg_ctx.gen_opparam_ptr++ = memop;
*tcg_ctx.gen_opparam_ptr++ = idx;
}
void tcg_gen_qemu_ld_i64(TCGv_i64 val, TCGv addr, TCGArg idx, TCGMemOp memop)
{
memop = tcg_canonicalize_memop(memop, 1, 0);
#if TCG_TARGET_REG_BITS == 32
if ((memop & MO_SIZE) < MO_64) {
tcg_gen_qemu_ld_i32(TCGV_LOW(val), addr, idx, memop);
if (memop & MO_SIGN) {
tcg_gen_sari_i32(TCGV_HIGH(val), TCGV_LOW(val), 31);
} else {
tcg_gen_movi_i32(TCGV_HIGH(val), 0);
}
return;
}
#endif
*tcg_ctx.gen_opc_ptr++ = INDEX_op_qemu_ld_i64;
tcg_add_param_i64(val);
tcg_add_param_tl(addr);
*tcg_ctx.gen_opparam_ptr++ = memop;
*tcg_ctx.gen_opparam_ptr++ = idx;
}
void tcg_gen_qemu_st_i64(TCGv_i64 val, TCGv addr, TCGArg idx, TCGMemOp memop)
{
memop = tcg_canonicalize_memop(memop, 1, 1);
#if TCG_TARGET_REG_BITS == 32
if ((memop & MO_SIZE) < MO_64) {
tcg_gen_qemu_st_i32(TCGV_LOW(val), addr, idx, memop);
return;
}
#endif
*tcg_ctx.gen_opc_ptr++ = INDEX_op_qemu_st_i64;
tcg_add_param_i64(val);
tcg_add_param_tl(addr);
*tcg_ctx.gen_opparam_ptr++ = memop;
*tcg_ctx.gen_opparam_ptr++ = idx;
}
static void tcg_reg_alloc_start(TCGContext *s) static void tcg_reg_alloc_start(TCGContext *s)
{ {
int i; int i;
@ -1109,20 +987,21 @@ static const char * const ldst_name[] =
void tcg_dump_ops(TCGContext *s) void tcg_dump_ops(TCGContext *s)
{ {
const uint16_t *opc_ptr;
const TCGArg *args;
TCGArg arg;
TCGOpcode c;
int i, k, nb_oargs, nb_iargs, nb_cargs, first_insn;
const TCGOpDef *def;
char buf[128]; char buf[128];
TCGOp *op;
int oi;
first_insn = 1; for (oi = s->gen_first_op_idx; oi >= 0; oi = op->next) {
opc_ptr = s->gen_opc_buf; int i, k, nb_oargs, nb_iargs, nb_cargs;
args = s->gen_opparam_buf; const TCGOpDef *def;
while (opc_ptr < s->gen_opc_ptr) { const TCGArg *args;
c = *opc_ptr++; TCGOpcode c;
op = &s->gen_op_buf[oi];
c = op->opc;
def = &tcg_op_defs[c]; def = &tcg_op_defs[c];
args = &s->gen_opparam_buf[op->args];
if (c == INDEX_op_debug_insn_start) { if (c == INDEX_op_debug_insn_start) {
uint64_t pc; uint64_t pc;
#if TARGET_LONG_BITS > TCG_TARGET_REG_BITS #if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
@ -1130,21 +1009,14 @@ void tcg_dump_ops(TCGContext *s)
#else #else
pc = args[0]; pc = args[0];
#endif #endif
if (!first_insn) { if (oi != s->gen_first_op_idx) {
qemu_log("\n"); qemu_log("\n");
} }
qemu_log(" ---- 0x%" PRIx64, pc); qemu_log(" ---- 0x%" PRIx64, pc);
first_insn = 0;
nb_oargs = def->nb_oargs;
nb_iargs = def->nb_iargs;
nb_cargs = def->nb_cargs;
} else if (c == INDEX_op_call) { } else if (c == INDEX_op_call) {
TCGArg arg;
/* variable number of arguments */ /* variable number of arguments */
arg = *args++; nb_oargs = op->callo;
nb_oargs = arg >> 16; nb_iargs = op->calli;
nb_iargs = arg & 0xffff;
nb_cargs = def->nb_cargs; nb_cargs = def->nb_cargs;
/* function name, flags, out args */ /* function name, flags, out args */
@ -1165,26 +1037,20 @@ void tcg_dump_ops(TCGContext *s)
} }
} else { } else {
qemu_log(" %s ", def->name); qemu_log(" %s ", def->name);
if (c == INDEX_op_nopn) {
/* variable number of arguments */ nb_oargs = def->nb_oargs;
nb_cargs = *args; nb_iargs = def->nb_iargs;
nb_oargs = 0; nb_cargs = def->nb_cargs;
nb_iargs = 0;
} else {
nb_oargs = def->nb_oargs;
nb_iargs = def->nb_iargs;
nb_cargs = def->nb_cargs;
}
k = 0; k = 0;
for(i = 0; i < nb_oargs; i++) { for (i = 0; i < nb_oargs; i++) {
if (k != 0) { if (k != 0) {
qemu_log(","); qemu_log(",");
} }
qemu_log("%s", tcg_get_arg_str_idx(s, buf, sizeof(buf), qemu_log("%s", tcg_get_arg_str_idx(s, buf, sizeof(buf),
args[k++])); args[k++]));
} }
for(i = 0; i < nb_iargs; i++) { for (i = 0; i < nb_iargs; i++) {
if (k != 0) { if (k != 0) {
qemu_log(","); qemu_log(",");
} }
@ -1222,16 +1088,14 @@ void tcg_dump_ops(TCGContext *s)
i = 0; i = 0;
break; break;
} }
for(; i < nb_cargs; i++) { for (; i < nb_cargs; i++) {
if (k != 0) { if (k != 0) {
qemu_log(","); qemu_log(",");
} }
arg = args[k++]; qemu_log("$0x%" TCG_PRIlx, args[k++]);
qemu_log("$0x%" TCG_PRIlx, arg);
} }
} }
qemu_log("\n"); qemu_log("\n");
args += nb_iargs + nb_oargs + nb_cargs;
} }
} }
@ -1380,21 +1244,30 @@ void tcg_add_target_add_op_defs(const TCGTargetOpDef *tdefs)
#endif #endif
} }
#ifdef USE_LIVENESS_ANALYSIS void tcg_op_remove(TCGContext *s, TCGOp *op)
/* set a nop for an operation using 'nb_args' */
static inline void tcg_set_nop(TCGContext *s, uint16_t *opc_ptr,
TCGArg *args, int nb_args)
{ {
if (nb_args == 0) { int next = op->next;
*opc_ptr = INDEX_op_nop; int prev = op->prev;
if (next >= 0) {
s->gen_op_buf[next].prev = prev;
} else { } else {
*opc_ptr = INDEX_op_nopn; s->gen_last_op_idx = prev;
args[0] = nb_args;
args[nb_args - 1] = nb_args;
} }
if (prev >= 0) {
s->gen_op_buf[prev].next = next;
} else {
s->gen_first_op_idx = next;
}
memset(op, -1, sizeof(*op));
#ifdef CONFIG_PROFILER
s->del_op_count++;
#endif
} }
#ifdef USE_LIVENESS_ANALYSIS
/* liveness analysis: end of function: all temps are dead, and globals /* liveness analysis: end of function: all temps are dead, and globals
should be in memory. */ should be in memory. */
static inline void tcg_la_func_end(TCGContext *s, uint8_t *dead_temps, static inline void tcg_la_func_end(TCGContext *s, uint8_t *dead_temps,
@ -1424,19 +1297,10 @@ static inline void tcg_la_bb_end(TCGContext *s, uint8_t *dead_temps,
temporaries are removed. */ temporaries are removed. */
static void tcg_liveness_analysis(TCGContext *s) static void tcg_liveness_analysis(TCGContext *s)
{ {
int i, op_index, nb_args, nb_iargs, nb_oargs, nb_ops;
TCGOpcode op, op_new, op_new2;
TCGArg *args, arg;
const TCGOpDef *def;
uint8_t *dead_temps, *mem_temps; uint8_t *dead_temps, *mem_temps;
uint16_t dead_args; int oi, oi_prev, nb_ops;
uint8_t sync_args;
bool have_op_new2;
s->gen_opc_ptr++; /* skip end */
nb_ops = s->gen_opc_ptr - s->gen_opc_buf;
nb_ops = s->gen_next_op_idx;
s->op_dead_args = tcg_malloc(nb_ops * sizeof(uint16_t)); s->op_dead_args = tcg_malloc(nb_ops * sizeof(uint16_t));
s->op_sync_args = tcg_malloc(nb_ops * sizeof(uint8_t)); s->op_sync_args = tcg_malloc(nb_ops * sizeof(uint8_t));
@ -1444,25 +1308,31 @@ static void tcg_liveness_analysis(TCGContext *s)
mem_temps = tcg_malloc(s->nb_temps); mem_temps = tcg_malloc(s->nb_temps);
tcg_la_func_end(s, dead_temps, mem_temps); tcg_la_func_end(s, dead_temps, mem_temps);
args = s->gen_opparam_ptr; for (oi = s->gen_last_op_idx; oi >= 0; oi = oi_prev) {
op_index = nb_ops - 1; int i, nb_iargs, nb_oargs;
while (op_index >= 0) { TCGOpcode opc_new, opc_new2;
op = s->gen_opc_buf[op_index]; bool have_opc_new2;
def = &tcg_op_defs[op]; uint16_t dead_args;
switch(op) { uint8_t sync_args;
TCGArg arg;
TCGOp * const op = &s->gen_op_buf[oi];
TCGArg * const args = &s->gen_opparam_buf[op->args];
TCGOpcode opc = op->opc;
const TCGOpDef *def = &tcg_op_defs[opc];
oi_prev = op->prev;
switch (opc) {
case INDEX_op_call: case INDEX_op_call:
{ {
int call_flags; int call_flags;
nb_args = args[-1]; nb_oargs = op->callo;
args -= nb_args; nb_iargs = op->calli;
arg = *args++;
nb_iargs = arg & 0xffff;
nb_oargs = arg >> 16;
call_flags = args[nb_oargs + nb_iargs + 1]; call_flags = args[nb_oargs + nb_iargs + 1];
/* pure functions can be removed if their result is not /* pure functions can be removed if their result is unused */
used */
if (call_flags & TCG_CALL_NO_SIDE_EFFECTS) { if (call_flags & TCG_CALL_NO_SIDE_EFFECTS) {
for (i = 0; i < nb_oargs; i++) { for (i = 0; i < nb_oargs; i++) {
arg = args[i]; arg = args[i];
@ -1470,8 +1340,7 @@ static void tcg_liveness_analysis(TCGContext *s)
goto do_not_remove_call; goto do_not_remove_call;
} }
} }
tcg_set_nop(s, s->gen_opc_buf + op_index, goto do_remove;
args - 1, nb_args);
} else { } else {
do_not_remove_call: do_not_remove_call:
@ -1510,41 +1379,31 @@ static void tcg_liveness_analysis(TCGContext *s)
dead_temps[arg] = 0; dead_temps[arg] = 0;
} }
} }
s->op_dead_args[op_index] = dead_args; s->op_dead_args[oi] = dead_args;
s->op_sync_args[op_index] = sync_args; s->op_sync_args[oi] = sync_args;
} }
args--;
} }
break; break;
case INDEX_op_debug_insn_start: case INDEX_op_debug_insn_start:
args -= def->nb_args;
break;
case INDEX_op_nopn:
nb_args = args[-1];
args -= nb_args;
break; break;
case INDEX_op_discard: case INDEX_op_discard:
args--;
/* mark the temporary as dead */ /* mark the temporary as dead */
dead_temps[args[0]] = 1; dead_temps[args[0]] = 1;
mem_temps[args[0]] = 0; mem_temps[args[0]] = 0;
break; break;
case INDEX_op_end:
break;
case INDEX_op_add2_i32: case INDEX_op_add2_i32:
op_new = INDEX_op_add_i32; opc_new = INDEX_op_add_i32;
goto do_addsub2; goto do_addsub2;
case INDEX_op_sub2_i32: case INDEX_op_sub2_i32:
op_new = INDEX_op_sub_i32; opc_new = INDEX_op_sub_i32;
goto do_addsub2; goto do_addsub2;
case INDEX_op_add2_i64: case INDEX_op_add2_i64:
op_new = INDEX_op_add_i64; opc_new = INDEX_op_add_i64;
goto do_addsub2; goto do_addsub2;
case INDEX_op_sub2_i64: case INDEX_op_sub2_i64:
op_new = INDEX_op_sub_i64; opc_new = INDEX_op_sub_i64;
do_addsub2: do_addsub2:
args -= 6;
nb_iargs = 4; nb_iargs = 4;
nb_oargs = 2; nb_oargs = 2;
/* Test if the high part of the operation is dead, but not /* Test if the high part of the operation is dead, but not
@ -1555,12 +1414,11 @@ static void tcg_liveness_analysis(TCGContext *s)
if (dead_temps[args[0]] && !mem_temps[args[0]]) { if (dead_temps[args[0]] && !mem_temps[args[0]]) {
goto do_remove; goto do_remove;
} }
/* Create the single operation plus nop. */ /* Replace the opcode and adjust the args in place,
s->gen_opc_buf[op_index] = op = op_new; leaving 3 unused args at the end. */
op->opc = opc = opc_new;
args[1] = args[2]; args[1] = args[2];
args[2] = args[4]; args[2] = args[4];
assert(s->gen_opc_buf[op_index + 1] == INDEX_op_nop);
tcg_set_nop(s, s->gen_opc_buf + op_index + 1, args + 3, 3);
/* Fall through and mark the single-word operation live. */ /* Fall through and mark the single-word operation live. */
nb_iargs = 2; nb_iargs = 2;
nb_oargs = 1; nb_oargs = 1;
@ -1568,27 +1426,26 @@ static void tcg_liveness_analysis(TCGContext *s)
goto do_not_remove; goto do_not_remove;
case INDEX_op_mulu2_i32: case INDEX_op_mulu2_i32:
op_new = INDEX_op_mul_i32; opc_new = INDEX_op_mul_i32;
op_new2 = INDEX_op_muluh_i32; opc_new2 = INDEX_op_muluh_i32;
have_op_new2 = TCG_TARGET_HAS_muluh_i32; have_opc_new2 = TCG_TARGET_HAS_muluh_i32;
goto do_mul2; goto do_mul2;
case INDEX_op_muls2_i32: case INDEX_op_muls2_i32:
op_new = INDEX_op_mul_i32; opc_new = INDEX_op_mul_i32;
op_new2 = INDEX_op_mulsh_i32; opc_new2 = INDEX_op_mulsh_i32;
have_op_new2 = TCG_TARGET_HAS_mulsh_i32; have_opc_new2 = TCG_TARGET_HAS_mulsh_i32;
goto do_mul2; goto do_mul2;
case INDEX_op_mulu2_i64: case INDEX_op_mulu2_i64:
op_new = INDEX_op_mul_i64; opc_new = INDEX_op_mul_i64;
op_new2 = INDEX_op_muluh_i64; opc_new2 = INDEX_op_muluh_i64;
have_op_new2 = TCG_TARGET_HAS_muluh_i64; have_opc_new2 = TCG_TARGET_HAS_muluh_i64;
goto do_mul2; goto do_mul2;
case INDEX_op_muls2_i64: case INDEX_op_muls2_i64:
op_new = INDEX_op_mul_i64; opc_new = INDEX_op_mul_i64;
op_new2 = INDEX_op_mulsh_i64; opc_new2 = INDEX_op_mulsh_i64;
have_op_new2 = TCG_TARGET_HAS_mulsh_i64; have_opc_new2 = TCG_TARGET_HAS_mulsh_i64;
goto do_mul2; goto do_mul2;
do_mul2: do_mul2:
args -= 4;
nb_iargs = 2; nb_iargs = 2;
nb_oargs = 2; nb_oargs = 2;
if (dead_temps[args[1]] && !mem_temps[args[1]]) { if (dead_temps[args[1]] && !mem_temps[args[1]]) {
@ -1597,28 +1454,25 @@ static void tcg_liveness_analysis(TCGContext *s)
goto do_remove; goto do_remove;
} }
/* The high part of the operation is dead; generate the low. */ /* The high part of the operation is dead; generate the low. */
s->gen_opc_buf[op_index] = op = op_new; op->opc = opc = opc_new;
args[1] = args[2]; args[1] = args[2];
args[2] = args[3]; args[2] = args[3];
} else if (have_op_new2 && dead_temps[args[0]] } else if (have_opc_new2 && dead_temps[args[0]]
&& !mem_temps[args[0]]) { && !mem_temps[args[0]]) {
/* The low part of the operation is dead; generate the high. */ /* The low part of the operation is dead; generate the high. */
s->gen_opc_buf[op_index] = op = op_new2; op->opc = opc = opc_new2;
args[0] = args[1]; args[0] = args[1];
args[1] = args[2]; args[1] = args[2];
args[2] = args[3]; args[2] = args[3];
} else { } else {
goto do_not_remove; goto do_not_remove;
} }
assert(s->gen_opc_buf[op_index + 1] == INDEX_op_nop);
tcg_set_nop(s, s->gen_opc_buf + op_index + 1, args + 3, 1);
/* Mark the single-word operation live. */ /* Mark the single-word operation live. */
nb_oargs = 1; nb_oargs = 1;
goto do_not_remove; goto do_not_remove;
default: default:
/* XXX: optimize by hardcoding common cases (e.g. triadic ops) */ /* XXX: optimize by hardcoding common cases (e.g. triadic ops) */
args -= def->nb_args;
nb_iargs = def->nb_iargs; nb_iargs = def->nb_iargs;
nb_oargs = def->nb_oargs; nb_oargs = def->nb_oargs;
@ -1626,24 +1480,20 @@ static void tcg_liveness_analysis(TCGContext *s)
its outputs are dead. We assume that nb_oargs == 0 its outputs are dead. We assume that nb_oargs == 0
implies side effects */ implies side effects */
if (!(def->flags & TCG_OPF_SIDE_EFFECTS) && nb_oargs != 0) { if (!(def->flags & TCG_OPF_SIDE_EFFECTS) && nb_oargs != 0) {
for(i = 0; i < nb_oargs; i++) { for (i = 0; i < nb_oargs; i++) {
arg = args[i]; arg = args[i];
if (!dead_temps[arg] || mem_temps[arg]) { if (!dead_temps[arg] || mem_temps[arg]) {
goto do_not_remove; goto do_not_remove;
} }
} }
do_remove: do_remove:
tcg_set_nop(s, s->gen_opc_buf + op_index, args, def->nb_args); tcg_op_remove(s, op);
#ifdef CONFIG_PROFILER
s->del_op_count++;
#endif
} else { } else {
do_not_remove: do_not_remove:
/* output args are dead */ /* output args are dead */
dead_args = 0; dead_args = 0;
sync_args = 0; sync_args = 0;
for(i = 0; i < nb_oargs; i++) { for (i = 0; i < nb_oargs; i++) {
arg = args[i]; arg = args[i];
if (dead_temps[arg]) { if (dead_temps[arg]) {
dead_args |= (1 << i); dead_args |= (1 << i);
@ -1664,23 +1514,18 @@ static void tcg_liveness_analysis(TCGContext *s)
} }
/* input args are live */ /* input args are live */
for(i = nb_oargs; i < nb_oargs + nb_iargs; i++) { for (i = nb_oargs; i < nb_oargs + nb_iargs; i++) {
arg = args[i]; arg = args[i];
if (dead_temps[arg]) { if (dead_temps[arg]) {
dead_args |= (1 << i); dead_args |= (1 << i);
} }
dead_temps[arg] = 0; dead_temps[arg] = 0;
} }
s->op_dead_args[op_index] = dead_args; s->op_dead_args[oi] = dead_args;
s->op_sync_args[op_index] = sync_args; s->op_sync_args[oi] = sync_args;
} }
break; break;
} }
op_index--;
}
if (args != s->gen_opparam_buf) {
tcg_abort();
} }
} }
#else #else
@ -2247,11 +2092,11 @@ static void tcg_reg_alloc_op(TCGContext *s,
#define STACK_DIR(x) (x) #define STACK_DIR(x) (x)
#endif #endif
static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def, static void tcg_reg_alloc_call(TCGContext *s, int nb_oargs, int nb_iargs,
TCGOpcode opc, const TCGArg *args, const TCGArg * const args, uint16_t dead_args,
uint16_t dead_args, uint8_t sync_args) uint8_t sync_args)
{ {
int nb_iargs, nb_oargs, flags, nb_regs, i, reg, nb_params; int flags, nb_regs, i, reg;
TCGArg arg; TCGArg arg;
TCGTemp *ts; TCGTemp *ts;
intptr_t stack_offset; intptr_t stack_offset;
@ -2260,22 +2105,16 @@ static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
int allocate_args; int allocate_args;
TCGRegSet allocated_regs; TCGRegSet allocated_regs;
arg = *args++;
nb_oargs = arg >> 16;
nb_iargs = arg & 0xffff;
nb_params = nb_iargs;
func_addr = (tcg_insn_unit *)(intptr_t)args[nb_oargs + nb_iargs]; func_addr = (tcg_insn_unit *)(intptr_t)args[nb_oargs + nb_iargs];
flags = args[nb_oargs + nb_iargs + 1]; flags = args[nb_oargs + nb_iargs + 1];
nb_regs = ARRAY_SIZE(tcg_target_call_iarg_regs); nb_regs = ARRAY_SIZE(tcg_target_call_iarg_regs);
if (nb_regs > nb_params) { if (nb_regs > nb_iargs) {
nb_regs = nb_params; nb_regs = nb_iargs;
} }
/* assign stack slots first */ /* assign stack slots first */
call_stack_size = (nb_params - nb_regs) * sizeof(tcg_target_long); call_stack_size = (nb_iargs - nb_regs) * sizeof(tcg_target_long);
call_stack_size = (call_stack_size + TCG_TARGET_STACK_ALIGN - 1) & call_stack_size = (call_stack_size + TCG_TARGET_STACK_ALIGN - 1) &
~(TCG_TARGET_STACK_ALIGN - 1); ~(TCG_TARGET_STACK_ALIGN - 1);
allocate_args = (call_stack_size > TCG_STATIC_CALL_ARGS_SIZE); allocate_args = (call_stack_size > TCG_STATIC_CALL_ARGS_SIZE);
@ -2286,7 +2125,7 @@ static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
} }
stack_offset = TCG_TARGET_CALL_STACK_OFFSET; stack_offset = TCG_TARGET_CALL_STACK_OFFSET;
for(i = nb_regs; i < nb_params; i++) { for(i = nb_regs; i < nb_iargs; i++) {
arg = args[nb_oargs + i]; arg = args[nb_oargs + i];
#ifdef TCG_TARGET_STACK_GROWSUP #ifdef TCG_TARGET_STACK_GROWSUP
stack_offset -= sizeof(tcg_target_long); stack_offset -= sizeof(tcg_target_long);
@ -2393,8 +2232,6 @@ static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
} }
} }
} }
return nb_iargs + nb_oargs + def->nb_cargs + 1;
} }
#ifdef CONFIG_PROFILER #ifdef CONFIG_PROFILER
@ -2405,7 +2242,7 @@ void tcg_dump_op_count(FILE *f, fprintf_function cpu_fprintf)
{ {
int i; int i;
for(i = INDEX_op_end; i < NB_OPS; i++) { for (i = 0; i < NB_OPS; i++) {
cpu_fprintf(f, "%s %" PRId64 "\n", tcg_op_defs[i].name, cpu_fprintf(f, "%s %" PRId64 "\n", tcg_op_defs[i].name,
tcg_table_op_count[i]); tcg_table_op_count[i]);
} }
@ -2422,10 +2259,7 @@ static inline int tcg_gen_code_common(TCGContext *s,
tcg_insn_unit *gen_code_buf, tcg_insn_unit *gen_code_buf,
long search_pc) long search_pc)
{ {
TCGOpcode opc; int oi, oi_next;
int op_index;
const TCGOpDef *def;
const TCGArg *args;
#ifdef DEBUG_DISAS #ifdef DEBUG_DISAS
if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) { if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) {
@ -2440,8 +2274,7 @@ static inline int tcg_gen_code_common(TCGContext *s,
#endif #endif
#ifdef USE_TCG_OPTIMIZATIONS #ifdef USE_TCG_OPTIMIZATIONS
s->gen_opparam_ptr = tcg_optimize(s);
tcg_optimize(s, s->gen_opc_ptr, s->gen_opparam_buf, tcg_op_defs);
#endif #endif
#ifdef CONFIG_PROFILER #ifdef CONFIG_PROFILER
@ -2470,42 +2303,30 @@ static inline int tcg_gen_code_common(TCGContext *s,
tcg_out_tb_init(s); tcg_out_tb_init(s);
args = s->gen_opparam_buf; for (oi = s->gen_first_op_idx; oi >= 0; oi = oi_next) {
op_index = 0; TCGOp * const op = &s->gen_op_buf[oi];
TCGArg * const args = &s->gen_opparam_buf[op->args];
TCGOpcode opc = op->opc;
const TCGOpDef *def = &tcg_op_defs[opc];
uint16_t dead_args = s->op_dead_args[oi];
uint8_t sync_args = s->op_sync_args[oi];
for(;;) { oi_next = op->next;
opc = s->gen_opc_buf[op_index];
#ifdef CONFIG_PROFILER #ifdef CONFIG_PROFILER
tcg_table_op_count[opc]++; tcg_table_op_count[opc]++;
#endif #endif
def = &tcg_op_defs[opc];
#if 0 switch (opc) {
printf("%s: %d %d %d\n", def->name,
def->nb_oargs, def->nb_iargs, def->nb_cargs);
// dump_regs(s);
#endif
switch(opc) {
case INDEX_op_mov_i32: case INDEX_op_mov_i32:
case INDEX_op_mov_i64: case INDEX_op_mov_i64:
tcg_reg_alloc_mov(s, def, args, s->op_dead_args[op_index], tcg_reg_alloc_mov(s, def, args, dead_args, sync_args);
s->op_sync_args[op_index]);
break; break;
case INDEX_op_movi_i32: case INDEX_op_movi_i32:
case INDEX_op_movi_i64: case INDEX_op_movi_i64:
tcg_reg_alloc_movi(s, args, s->op_dead_args[op_index], tcg_reg_alloc_movi(s, args, dead_args, sync_args);
s->op_sync_args[op_index]);
break; break;
case INDEX_op_debug_insn_start: case INDEX_op_debug_insn_start:
/* debug instruction */
break; break;
case INDEX_op_nop:
case INDEX_op_nop1:
case INDEX_op_nop2:
case INDEX_op_nop3:
break;
case INDEX_op_nopn:
args += args[0];
goto next;
case INDEX_op_discard: case INDEX_op_discard:
temp_dead(s, args[0]); temp_dead(s, args[0]);
break; break;
@ -2514,12 +2335,9 @@ static inline int tcg_gen_code_common(TCGContext *s,
tcg_out_label(s, args[0], s->code_ptr); tcg_out_label(s, args[0], s->code_ptr);
break; break;
case INDEX_op_call: case INDEX_op_call:
args += tcg_reg_alloc_call(s, def, opc, args, tcg_reg_alloc_call(s, op->callo, op->calli, args,
s->op_dead_args[op_index], dead_args, sync_args);
s->op_sync_args[op_index]); break;
goto next;
case INDEX_op_end:
goto the_end;
default: default:
/* Sanity check that we've not introduced any unhandled opcodes. */ /* Sanity check that we've not introduced any unhandled opcodes. */
if (def->flags & TCG_OPF_NOT_PRESENT) { if (def->flags & TCG_OPF_NOT_PRESENT) {
@ -2528,21 +2346,17 @@ static inline int tcg_gen_code_common(TCGContext *s,
/* Note: in order to speed up the code, it would be much /* Note: in order to speed up the code, it would be much
faster to have specialized register allocator functions for faster to have specialized register allocator functions for
some common argument patterns */ some common argument patterns */
tcg_reg_alloc_op(s, def, opc, args, s->op_dead_args[op_index], tcg_reg_alloc_op(s, def, opc, args, dead_args, sync_args);
s->op_sync_args[op_index]);
break; break;
} }
args += def->nb_args;
next:
if (search_pc >= 0 && search_pc < tcg_current_code_size(s)) { if (search_pc >= 0 && search_pc < tcg_current_code_size(s)) {
return op_index; return oi;
} }
op_index++;
#ifndef NDEBUG #ifndef NDEBUG
check_regs(s); check_regs(s);
#endif #endif
} }
the_end:
/* Generate TB finalization at the end of block */ /* Generate TB finalization at the end of block */
tcg_out_tb_finalize(s); tcg_out_tb_finalize(s);
return -1; return -1;
@ -2553,14 +2367,18 @@ int tcg_gen_code(TCGContext *s, tcg_insn_unit *gen_code_buf)
#ifdef CONFIG_PROFILER #ifdef CONFIG_PROFILER
{ {
int n; int n;
n = (s->gen_opc_ptr - s->gen_opc_buf);
s->op_count += n;
if (n > s->op_count_max)
s->op_count_max = n;
s->temp_count += s->nb_temps; n = s->gen_last_op_idx + 1;
if (s->nb_temps > s->temp_count_max) s->op_count += n;
s->temp_count_max = s->nb_temps; 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 #endif

View file

@ -448,10 +448,28 @@ typedef struct TCGTempSet {
unsigned long l[BITS_TO_LONGS(TCG_MAX_TEMPS)]; unsigned long l[BITS_TO_LONGS(TCG_MAX_TEMPS)];
} TCGTempSet; } TCGTempSet;
typedef struct TCGOp {
TCGOpcode opc : 8;
/* The number of out and in parameter for a call. */
unsigned callo : 2;
unsigned calli : 6;
/* Index of the arguments for this op, or -1 for zero-operand ops. */
signed args : 16;
/* Index of the prex/next op, or -1 for the end of the list. */
signed prev : 16;
signed next : 16;
} TCGOp;
QEMU_BUILD_BUG_ON(NB_OPS > 0xff);
QEMU_BUILD_BUG_ON(OPC_BUF_SIZE >= 0x7fff);
QEMU_BUILD_BUG_ON(OPPARAM_BUF_SIZE >= 0x7fff);
struct TCGContext { struct TCGContext {
uint8_t *pool_cur, *pool_end; uint8_t *pool_cur, *pool_end;
TCGPool *pool_first, *pool_current, *pool_first_large; TCGPool *pool_first, *pool_current, *pool_first_large;
TCGLabel *labels;
int nb_labels; int nb_labels;
int nb_globals; int nb_globals;
int nb_temps; int nb_temps;
@ -469,9 +487,6 @@ struct TCGContext {
corresponding output argument needs to be corresponding output argument needs to be
sync to memory. */ sync to memory. */
/* tells in which temporary a given register is. It does not take
into account fixed registers */
int reg_to_temp[TCG_TARGET_NB_REGS];
TCGRegSet reserved_regs; TCGRegSet reserved_regs;
intptr_t current_frame_offset; intptr_t current_frame_offset;
intptr_t frame_start; intptr_t frame_start;
@ -479,8 +494,6 @@ struct TCGContext {
int frame_reg; int frame_reg;
tcg_insn_unit *code_ptr; tcg_insn_unit *code_ptr;
TCGTemp temps[TCG_MAX_TEMPS]; /* globals first, temps after */
TCGTempSet free_temps[TCG_TYPE_COUNT * 2];
GHashTable *helpers; GHashTable *helpers;
@ -508,14 +521,10 @@ struct TCGContext {
int goto_tb_issue_mask; int goto_tb_issue_mask;
#endif #endif
uint16_t gen_opc_buf[OPC_BUF_SIZE]; int gen_first_op_idx;
TCGArg gen_opparam_buf[OPPARAM_BUF_SIZE]; int gen_last_op_idx;
int gen_next_op_idx;
uint16_t *gen_opc_ptr; int gen_next_parm_idx;
TCGArg *gen_opparam_ptr;
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];
/* Code generation. Note that we specifically do not use tcg_insn_unit /* Code generation. Note that we specifically do not use tcg_insn_unit
here, because there's too much arithmetic throughout that relies here, because there's too much arithmetic throughout that relies
@ -533,10 +542,38 @@ struct TCGContext {
/* The TCGBackendData structure is private to tcg-target.c. */ /* The TCGBackendData structure is private to tcg-target.c. */
struct TCGBackendData *be; struct TCGBackendData *be;
TCGTempSet free_temps[TCG_TYPE_COUNT * 2];
TCGTemp temps[TCG_MAX_TEMPS]; /* globals first, temps after */
/* tells in which temporary a given register is. It does not take
into account fixed registers */
int reg_to_temp[TCG_TARGET_NB_REGS];
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];
TCGLabel labels[TCG_MAX_LABELS];
}; };
extern TCGContext tcg_ctx; extern TCGContext tcg_ctx;
/* The number of opcodes emitted so far. */
static inline int tcg_op_buf_count(void)
{
return tcg_ctx.gen_next_op_idx;
}
/* Test for whether to terminate the TB for using too many opcodes. */
static inline bool tcg_op_buf_full(void)
{
return tcg_op_buf_count() >= OPC_MAX_SIZE;
}
/* pool based memory allocation */ /* pool based memory allocation */
void *tcg_malloc_internal(TCGContext *s, int size); void *tcg_malloc_internal(TCGContext *s, int size);
@ -706,11 +743,8 @@ void tcg_add_target_add_op_defs(const TCGTargetOpDef *tdefs);
void tcg_gen_callN(TCGContext *s, void *func, void tcg_gen_callN(TCGContext *s, void *func,
TCGArg ret, int nargs, TCGArg *args); TCGArg ret, int nargs, TCGArg *args);
void tcg_gen_shifti_i64(TCGv_i64 ret, TCGv_i64 arg1, void tcg_op_remove(TCGContext *s, TCGOp *op);
int c, int right, int arith); void tcg_optimize(TCGContext *s);
TCGArg *tcg_optimize(TCGContext *s, uint16_t *tcg_opc_ptr, TCGArg *args,
TCGOpDef *tcg_op_def);
/* only used for debugging purposes */ /* only used for debugging purposes */
void tcg_dump_ops(TCGContext *s); void tcg_dump_ops(TCGContext *s);

13
tci.c
View file

@ -506,19 +506,6 @@ uintptr_t tcg_qemu_tb_exec(CPUArchState *env, uint8_t *tb_ptr)
tb_ptr += 2; tb_ptr += 2;
switch (opc) { switch (opc) {
case INDEX_op_end:
case INDEX_op_nop:
break;
case INDEX_op_nop1:
case INDEX_op_nop2:
case INDEX_op_nop3:
case INDEX_op_nopn:
case INDEX_op_discard:
TODO();
break;
case INDEX_op_set_label:
TODO();
break;
case INDEX_op_call: case INDEX_op_call:
t0 = tci_read_ri(&tb_ptr); t0 = tci_read_ri(&tb_ptr);
#if TCG_TARGET_REG_BITS == 32 #if TCG_TARGET_REG_BITS == 32