use the TCG code generator

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3944 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
bellard 2008-02-01 10:50:11 +00:00
parent c896fe29d6
commit 57fec1fee9
35 changed files with 1098 additions and 2364 deletions

View File

@ -10,6 +10,9 @@ In particular, the QEMU virtual CPU core library (libqemu.a) is
released under the GNU Lesser General Public License. Many hardware released under the GNU Lesser General Public License. Many hardware
device emulation sources are released under the BSD license. device emulation sources are released under the BSD license.
3) QEMU is a trademark of Fabrice Bellard. 3) The Tiny Code Generator (TCG) is released under the BSD license
(see license headers in files).
4) QEMU is a trademark of Fabrice Bellard.
Fabrice Bellard. Fabrice Bellard.

View File

@ -172,8 +172,11 @@ all: $(PROGS)
######################################################### #########################################################
# cpu emulator library # cpu emulator library
LIBOBJS=exec.o kqemu.o translate-op.o translate-all.o cpu-exec.o\ LIBOBJS=exec.o kqemu.o translate-all.o cpu-exec.o\
translate.o op.o host-utils.o translate.o op.o host-utils.o
# TCG code generator
LIBOBJS+= tcg/tcg.o tcg/tcg-dyngen.o tcg/tcg-runtime.o
CPPFLAGS+=-I$(SRC_PATH)/tcg -I$(SRC_PATH)/tcg/$(ARCH)
ifdef CONFIG_SOFTFLOAT ifdef CONFIG_SOFTFLOAT
LIBOBJS+=fpu/softfloat.o LIBOBJS+=fpu/softfloat.o
else else
@ -268,16 +271,16 @@ libqemu.a: $(LIBOBJS)
rm -f $@ rm -f $@
$(AR) rcs $@ $(LIBOBJS) $(AR) rcs $@ $(LIBOBJS)
translate.o: translate.c gen-op.h opc.h cpu.h translate.o: translate.c gen-op.h dyngen-opc.h cpu.h
translate-all.o: translate-all.c opc.h cpu.h translate-all.o: translate-all.c dyngen-opc.h cpu.h
translate-op.o: translate-all.c op.h opc.h cpu.h tcg/tcg.o: op.h dyngen-opc.h cpu.h
op.h: op.o $(DYNGEN) op.h: op.o $(DYNGEN)
$(DYNGEN) -o $@ $< $(DYNGEN) -o $@ $<
opc.h: op.o $(DYNGEN) dyngen-opc.h: op.o $(DYNGEN)
$(DYNGEN) -c -o $@ $< $(DYNGEN) -c -o $@ $<
gen-op.h: op.o $(DYNGEN) gen-op.h: op.o $(DYNGEN)
@ -648,8 +651,8 @@ endif # !CONFIG_USER_ONLY
$(CC) $(CPPFLAGS) -c -o $@ $< $(CC) $(CPPFLAGS) -c -o $@ $<
clean: clean:
rm -f *.o *.a *~ $(PROGS) gen-op.h opc.h op.h nwfpe/*.o fpu/*.o rm -f *.o *.a *~ $(PROGS) gen-op.h dyngen-opc.h op.h nwfpe/*.o fpu/*.o
rm -f *.d */*.d rm -f *.d */*.d tcg/*.o
install: all install: all
ifneq ($(PROGS),) ifneq ($(PROGS),)

1
configure vendored
View File

@ -1051,6 +1051,7 @@ test -f $config_h && mv $config_h ${config_h}~
mkdir -p $target_dir mkdir -p $target_dir
mkdir -p $target_dir/fpu mkdir -p $target_dir/fpu
mkdir -p $target_dir/tcg
if test "$target" = "arm-linux-user" -o "$target" = "armeb-linux-user" ; then if test "$target" = "arm-linux-user" -o "$target" = "armeb-linux-user" ; then
mkdir -p $target_dir/nwfpe mkdir -p $target_dir/nwfpe
fi fi

View File

@ -1048,6 +1048,18 @@ extern int64_t kqemu_ret_int_count;
extern int64_t kqemu_ret_excp_count; extern int64_t kqemu_ret_excp_count;
extern int64_t kqemu_ret_intr_count; extern int64_t kqemu_ret_intr_count;
extern int64_t dyngen_tb_count1;
extern int64_t dyngen_tb_count;
extern int64_t dyngen_op_count;
extern int64_t dyngen_old_op_count;
extern int64_t dyngen_tcg_del_op_count;
extern int dyngen_op_count_max;
extern int64_t dyngen_code_in_len;
extern int64_t dyngen_code_out_len;
extern int64_t dyngen_interm_time;
extern int64_t dyngen_code_time;
extern int64_t dyngen_restore_count;
extern int64_t dyngen_restore_time;
#endif #endif
#endif /* CPU_ALL_H */ #endif /* CPU_ALL_H */

View File

@ -145,6 +145,7 @@ typedef struct CPUTLBEntry {
/* The meaning of the MMU modes is defined in the target code. */ \ /* The meaning of the MMU modes is defined in the target code. */ \
CPUTLBEntry tlb_table[NB_MMU_MODES][CPU_TLB_SIZE]; \ CPUTLBEntry tlb_table[NB_MMU_MODES][CPU_TLB_SIZE]; \
struct TranslationBlock *tb_jmp_cache[TB_JMP_CACHE_SIZE]; \ struct TranslationBlock *tb_jmp_cache[TB_JMP_CACHE_SIZE]; \
long temp_buf[128]; /* buffer for temporaries in the code generator */ \
\ \
/* from this point: preserved by CPU reset */ \ /* from this point: preserved by CPU reset */ \
/* ice debug support */ \ /* ice debug support */ \

View File

@ -354,7 +354,7 @@ int cpu_exec(CPUState *env1)
#endif #endif
#endif #endif
int ret, interrupt_request; int ret, interrupt_request;
void (*gen_func)(void); long (*gen_func)(void);
TranslationBlock *tb; TranslationBlock *tb;
uint8_t *tc_ptr; uint8_t *tc_ptr;
@ -736,7 +736,7 @@ int cpu_exec(CPUState *env1)
fp.gp = code_gen_buffer + 2 * (1 << 20); fp.gp = code_gen_buffer + 2 * (1 << 20);
(*(void (*)(void)) &fp)(); (*(void (*)(void)) &fp)();
#else #else
gen_func(); T0 = gen_func();
#endif #endif
env->current_tb = NULL; env->current_tb = NULL;
/* reset soft MMU for next block (it can currently /* reset soft MMU for next block (it can currently

View File

@ -1,9 +0,0 @@
static inline int gen_new_label(void)
{
return nb_gen_labels++;
}
static inline void gen_set_label(int n)
{
gen_labels[n] = gen_opc_ptr - gen_opc_buf;
}

170
dyngen.c
View File

@ -1212,14 +1212,16 @@ int load_object(const char *filename)
#endif /* CONFIG_FORMAT_MACH */ #endif /* CONFIG_FORMAT_MACH */
void get_reloc_expr(char *name, int name_size, const char *sym_name) /* return true if the expression is a label reference */
int get_reloc_expr(char *name, int name_size, const char *sym_name)
{ {
const char *p; const char *p;
if (strstart(sym_name, "__op_param", &p)) { if (strstart(sym_name, "__op_param", &p)) {
snprintf(name, name_size, "param%s", p); snprintf(name, name_size, "param%s", p);
} else if (strstart(sym_name, "__op_gen_label", &p)) { } else if (strstart(sym_name, "__op_gen_label", &p)) {
snprintf(name, name_size, "gen_labels[param%s]", p); snprintf(name, name_size, "param%s", p);
return 1;
} else { } else {
#ifdef HOST_SPARC #ifdef HOST_SPARC
if (sym_name[0] == '.') if (sym_name[0] == '.')
@ -1230,6 +1232,7 @@ void get_reloc_expr(char *name, int name_size, const char *sym_name)
#endif #endif
snprintf(name, name_size, "(long)(&%s)", sym_name); snprintf(name, name_size, "(long)(&%s)", sym_name);
} }
return 0;
} }
#ifdef HOST_IA64 #ifdef HOST_IA64
@ -1846,7 +1849,7 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
#if defined(HOST_I386) #if defined(HOST_I386)
{ {
char relname[256]; char relname[256];
int type; int type, is_label;
int addend; int addend;
int reloc_offset; int reloc_offset;
for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
@ -1868,21 +1871,33 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
continue; continue;
} }
get_reloc_expr(relname, sizeof(relname), sym_name); is_label = get_reloc_expr(relname, sizeof(relname), sym_name);
addend = get32((uint32_t *)(text + rel->r_offset)); addend = get32((uint32_t *)(text + rel->r_offset));
#ifdef CONFIG_FORMAT_ELF #ifdef CONFIG_FORMAT_ELF
type = ELF32_R_TYPE(rel->r_info); type = ELF32_R_TYPE(rel->r_info);
switch(type) { if (is_label) {
case R_386_32: switch(type) {
fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n", case R_386_32:
reloc_offset, relname, addend); case R_386_PC32:
break; fprintf(outfile, " tcg_out_reloc(s, gen_code_ptr + %d, %d, %s, %d);\n",
case R_386_PC32: reloc_offset, type, relname, addend);
fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d;\n", break;
reloc_offset, relname, reloc_offset, addend); default:
break; error("unsupported i386 relocation (%d)", type);
default: }
error("unsupported i386 relocation (%d)", type); } else {
switch(type) {
case R_386_32:
fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
reloc_offset, relname, addend);
break;
case R_386_PC32:
fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d;\n",
reloc_offset, relname, reloc_offset, addend);
break;
default:
error("unsupported i386 relocation (%d)", type);
}
} }
#elif defined(CONFIG_FORMAT_COFF) #elif defined(CONFIG_FORMAT_COFF)
{ {
@ -1920,32 +1935,45 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
#elif defined(HOST_X86_64) #elif defined(HOST_X86_64)
{ {
char relname[256]; char relname[256];
int type; int type, is_label;
int addend; int addend;
int reloc_offset; int reloc_offset;
for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
if (rel->r_offset >= start_offset && if (rel->r_offset >= start_offset &&
rel->r_offset < start_offset + copy_size) { rel->r_offset < start_offset + copy_size) {
sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name; sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
get_reloc_expr(relname, sizeof(relname), sym_name); is_label = get_reloc_expr(relname, sizeof(relname), sym_name);
type = ELF32_R_TYPE(rel->r_info); type = ELF32_R_TYPE(rel->r_info);
addend = rel->r_addend; addend = rel->r_addend;
reloc_offset = rel->r_offset - start_offset; reloc_offset = rel->r_offset - start_offset;
switch(type) { if (is_label) {
case R_X86_64_32: switch(type) {
fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = (uint32_t)%s + %d;\n", case R_X86_64_32:
reloc_offset, relname, addend); case R_X86_64_32S:
break; case R_X86_64_PC32:
case R_X86_64_32S: fprintf(outfile, " tcg_out_reloc(s, gen_code_ptr + %d, %d, %s, %d);\n",
fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = (int32_t)%s + %d;\n", reloc_offset, type, relname, addend);
reloc_offset, relname, addend); break;
break; default:
case R_X86_64_PC32: error("unsupported X86_64 relocation (%d)", type);
fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d;\n", }
reloc_offset, relname, reloc_offset, addend); } else {
break; switch(type) {
default: case R_X86_64_32:
error("unsupported X86_64 relocation (%d)", type); fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = (uint32_t)%s + %d;\n",
reloc_offset, relname, addend);
break;
case R_X86_64_32S:
fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = (int32_t)%s + %d;\n",
reloc_offset, relname, addend);
break;
case R_X86_64_PC32:
fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d;\n",
reloc_offset, relname, reloc_offset, addend);
break;
default:
error("unsupported X86_64 relocation (%d)", type);
}
} }
} }
} }
@ -2639,11 +2667,6 @@ int gen_file(FILE *outfile, int out_type)
EXE_SYM *sym; EXE_SYM *sym;
if (out_type == OUT_INDEX_OP) { if (out_type == OUT_INDEX_OP) {
fprintf(outfile, "DEF(end, 0, 0)\n");
fprintf(outfile, "DEF(nop, 0, 0)\n");
fprintf(outfile, "DEF(nop1, 1, 0)\n");
fprintf(outfile, "DEF(nop2, 2, 0)\n");
fprintf(outfile, "DEF(nop3, 3, 0)\n");
for(i = 0, sym = symtab; i < nb_syms; i++, sym++) { for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
const char *name; const char *name;
name = get_sym_name(sym); name = get_sym_name(sym);
@ -2653,7 +2676,6 @@ int gen_file(FILE *outfile, int out_type)
} }
} else if (out_type == OUT_GEN_OP) { } else if (out_type == OUT_GEN_OP) {
/* generate gen_xxx functions */ /* generate gen_xxx functions */
fprintf(outfile, "#include \"dyngen-op.h\"\n");
for(i = 0, sym = symtab; i < nb_syms; i++, sym++) { for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
const char *name; const char *name;
name = get_sym_name(sym); name = get_sym_name(sym);
@ -2670,6 +2692,7 @@ int gen_file(FILE *outfile, int out_type)
/* generate big code generation switch */ /* generate big code generation switch */
#ifdef HOST_ARM #ifdef HOST_ARM
#error broken
/* We need to know the size of all the ops so we can figure out when /* We need to know the size of all the ops so we can figure out when
to emit constant pools. This must be consistent with opc.h. */ to emit constant pools. This must be consistent with opc.h. */
fprintf(outfile, fprintf(outfile,
@ -2690,16 +2713,8 @@ fprintf(outfile,
"};\n"); "};\n");
#endif #endif
fprintf(outfile,
"int dyngen_code(uint8_t *gen_code_buf,\n"
" uint16_t *label_offsets, uint16_t *jmp_offsets,\n"
" const uint16_t *opc_buf, const uint32_t *opparam_buf, const long *gen_labels)\n"
"{\n"
" uint8_t *gen_code_ptr;\n"
" const uint16_t *opc_ptr;\n"
" const uint32_t *opparam_ptr;\n");
#ifdef HOST_ARM #ifdef HOST_ARM
#error broken
/* Arm is tricky because it uses constant pools for loading immediate values. /* Arm is tricky because it uses constant pools for loading immediate values.
We assume (and require) each function is code followed by a constant pool. We assume (and require) each function is code followed by a constant pool.
All the ops are small so this should be ok. For each op we figure All the ops are small so this should be ok. For each op we figure
@ -2732,6 +2747,7 @@ fprintf(outfile,
" uint8_t *arm_pool_ptr = gen_code_buf + 0x1000000;\n"); " uint8_t *arm_pool_ptr = gen_code_buf + 0x1000000;\n");
#endif #endif
#ifdef HOST_IA64 #ifdef HOST_IA64
#error broken
{ {
long addend, not_first = 0; long addend, not_first = 0;
unsigned long sym_idx; unsigned long sym_idx;
@ -2789,18 +2805,8 @@ fprintf(outfile,
} }
#endif #endif
fprintf(outfile,
"\n"
" gen_code_ptr = gen_code_buf;\n"
" opc_ptr = opc_buf;\n"
" opparam_ptr = opparam_buf;\n");
/* Generate prologue, if needed. */
fprintf(outfile,
" for(;;) {\n");
#ifdef HOST_ARM #ifdef HOST_ARM
#error broken
/* Generate constant pool if needed */ /* Generate constant pool if needed */
fprintf(outfile, fprintf(outfile,
" if (gen_code_ptr + arm_opc_size[*opc_ptr] >= arm_pool_ptr) {\n" " if (gen_code_ptr + arm_opc_size[*opc_ptr] >= arm_pool_ptr) {\n"
@ -2813,9 +2819,6 @@ fprintf(outfile,
" }\n"); " }\n");
#endif #endif
fprintf(outfile,
" switch(*opc_ptr++) {\n");
for(i = 0, sym = symtab; i < nb_syms; i++, sym++) { for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
const char *name; const char *name;
name = get_sym_name(sym); name = get_sym_name(sym);
@ -2831,51 +2834,6 @@ fprintf(outfile,
gen_code(name, sym->st_value, sym->st_size, outfile, 1); gen_code(name, sym->st_value, sym->st_size, outfile, 1);
} }
} }
fprintf(outfile,
" case INDEX_op_nop:\n"
" break;\n"
" case INDEX_op_nop1:\n"
" opparam_ptr++;\n"
" break;\n"
" case INDEX_op_nop2:\n"
" opparam_ptr += 2;\n"
" break;\n"
" case INDEX_op_nop3:\n"
" opparam_ptr += 3;\n"
" break;\n"
" default:\n"
" goto the_end;\n"
" }\n");
fprintf(outfile,
" }\n"
" the_end:\n"
);
#ifdef HOST_IA64
fprintf(outfile,
" {\n"
" extern char code_gen_buffer[];\n"
" ia64_apply_fixes(&gen_code_ptr, ltoff_fixes, "
"(uint64_t) code_gen_buffer + 2*(1<<20), plt_fixes,\n\t\t\t"
"sizeof(plt_target)/sizeof(plt_target[0]),\n\t\t\t"
"plt_target, plt_offset);\n }\n");
#endif
/* generate some code patching */
#ifdef HOST_ARM
fprintf(outfile,
"if (arm_data_ptr != arm_data_table + ARM_LDR_TABLE_SIZE)\n"
" gen_code_ptr = arm_flush_ldr(gen_code_ptr, arm_ldr_table, "
"arm_ldr_ptr, arm_data_ptr, arm_data_table + ARM_LDR_TABLE_SIZE, 0);\n");
#endif
/* flush instruction cache */
fprintf(outfile, "flush_icache_range((unsigned long)gen_code_buf, (unsigned long)gen_code_ptr);\n");
fprintf(outfile, "return gen_code_ptr - gen_code_buf;\n");
fprintf(outfile, "}\n\n");
} }
return 0; return 0;

449
dyngen.h
View File

@ -1,449 +0,0 @@
/*
* dyngen helpers
*
* Copyright (c) 2003 Fabrice Bellard
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
int __op_param1, __op_param2, __op_param3;
#if defined(__sparc__) || defined(__arm__)
void __op_gen_label1(){}
void __op_gen_label2(){}
void __op_gen_label3(){}
#else
int __op_gen_label1, __op_gen_label2, __op_gen_label3;
#endif
int __op_jmp0, __op_jmp1, __op_jmp2, __op_jmp3;
#if defined(__i386__) || defined(__x86_64__) || defined(__s390__)
static inline void flush_icache_range(unsigned long start, unsigned long stop)
{
}
#elif defined(__ia64__)
static inline void flush_icache_range(unsigned long start, unsigned long stop)
{
while (start < stop) {
asm volatile ("fc %0" :: "r"(start));
start += 32;
}
asm volatile (";;sync.i;;srlz.i;;");
}
#elif defined(__powerpc__)
#define MIN_CACHE_LINE_SIZE 8 /* conservative value */
static inline void flush_icache_range(unsigned long start, unsigned long stop)
{
unsigned long p;
start &= ~(MIN_CACHE_LINE_SIZE - 1);
stop = (stop + MIN_CACHE_LINE_SIZE - 1) & ~(MIN_CACHE_LINE_SIZE - 1);
for (p = start; p < stop; p += MIN_CACHE_LINE_SIZE) {
asm volatile ("dcbst 0,%0" : : "r"(p) : "memory");
}
asm volatile ("sync" : : : "memory");
for (p = start; p < stop; p += MIN_CACHE_LINE_SIZE) {
asm volatile ("icbi 0,%0" : : "r"(p) : "memory");
}
asm volatile ("sync" : : : "memory");
asm volatile ("isync" : : : "memory");
}
#elif defined(__alpha__)
static inline void flush_icache_range(unsigned long start, unsigned long stop)
{
asm ("imb");
}
#elif defined(__sparc__)
static inline void flush_icache_range(unsigned long start, unsigned long stop)
{
unsigned long p;
p = start & ~(8UL - 1UL);
stop = (stop + (8UL - 1UL)) & ~(8UL - 1UL);
for (; p < stop; p += 8)
__asm__ __volatile__("flush\t%0" : : "r" (p));
}
#elif defined(__arm__)
static inline void flush_icache_range(unsigned long start, unsigned long stop)
{
register unsigned long _beg __asm ("a1") = start;
register unsigned long _end __asm ("a2") = stop;
register unsigned long _flg __asm ("a3") = 0;
__asm __volatile__ ("swi 0x9f0002" : : "r" (_beg), "r" (_end), "r" (_flg));
}
#elif defined(__mc68000)
# include <asm/cachectl.h>
static inline void flush_icache_range(unsigned long start, unsigned long stop)
{
cacheflush(start,FLUSH_SCOPE_LINE,FLUSH_CACHE_BOTH,stop-start+16);
}
#elif defined(__mips__)
#include <sys/cachectl.h>
static inline void flush_icache_range(unsigned long start, unsigned long stop)
{
_flush_cache ((void *)start, stop - start, BCACHE);
}
#else
#error unsupported CPU
#endif
#ifdef __alpha__
register int gp asm("$29");
static inline void immediate_ldah(void *p, int val) {
uint32_t *dest = p;
long high = ((val >> 16) + ((val >> 15) & 1)) & 0xffff;
*dest &= ~0xffff;
*dest |= high;
*dest |= 31 << 16;
}
static inline void immediate_lda(void *dest, int val) {
*(uint16_t *) dest = val;
}
void fix_bsr(void *p, int offset) {
uint32_t *dest = p;
*dest &= ~((1 << 21) - 1);
*dest |= (offset >> 2) & ((1 << 21) - 1);
}
#endif /* __alpha__ */
#ifdef __arm__
#define ARM_LDR_TABLE_SIZE 1024
typedef struct LDREntry {
uint8_t *ptr;
uint32_t *data_ptr;
unsigned type:2;
} LDREntry;
static LDREntry arm_ldr_table[1024];
static uint32_t arm_data_table[ARM_LDR_TABLE_SIZE];
extern char exec_loop;
static inline void arm_reloc_pc24(uint32_t *ptr, uint32_t insn, int val)
{
*ptr = (insn & ~0xffffff) | ((insn + ((val - (int)ptr) >> 2)) & 0xffffff);
}
static uint8_t *arm_flush_ldr(uint8_t *gen_code_ptr,
LDREntry *ldr_start, LDREntry *ldr_end,
uint32_t *data_start, uint32_t *data_end,
int gen_jmp)
{
LDREntry *le;
uint32_t *ptr;
int offset, data_size, target;
uint8_t *data_ptr;
uint32_t insn;
uint32_t mask;
data_size = (data_end - data_start) << 2;
if (gen_jmp) {
/* generate branch to skip the data */
if (data_size == 0)
return gen_code_ptr;
target = (long)gen_code_ptr + data_size + 4;
arm_reloc_pc24((uint32_t *)gen_code_ptr, 0xeafffffe, target);
gen_code_ptr += 4;
}
/* copy the data */
data_ptr = gen_code_ptr;
memcpy(gen_code_ptr, data_start, data_size);
gen_code_ptr += data_size;
/* patch the ldr to point to the data */
for(le = ldr_start; le < ldr_end; le++) {
ptr = (uint32_t *)le->ptr;
offset = ((unsigned long)(le->data_ptr) - (unsigned long)data_start) +
(unsigned long)data_ptr -
(unsigned long)ptr - 8;
if (offset < 0) {
fprintf(stderr, "Negative constant pool offset\n");
abort();
}
switch (le->type) {
case 0: /* ldr */
mask = ~0x00800fff;
if (offset >= 4096) {
fprintf(stderr, "Bad ldr offset\n");
abort();
}
break;
case 1: /* ldc */
mask = ~0x008000ff;
if (offset >= 1024 ) {
fprintf(stderr, "Bad ldc offset\n");
abort();
}
break;
case 2: /* add */
mask = ~0xfff;
if (offset >= 1024 ) {
fprintf(stderr, "Bad add offset\n");
abort();
}
break;
default:
fprintf(stderr, "Bad pc relative fixup\n");
abort();
}
insn = *ptr & mask;
switch (le->type) {
case 0: /* ldr */
insn |= offset | 0x00800000;
break;
case 1: /* ldc */
insn |= (offset >> 2) | 0x00800000;
break;
case 2: /* add */
insn |= (offset >> 2) | 0xf00;
break;
}
*ptr = insn;
}
return gen_code_ptr;
}
#endif /* __arm__ */
#ifdef __ia64
/* Patch instruction with "val" where "mask" has 1 bits. */
static inline void ia64_patch (uint64_t insn_addr, uint64_t mask, uint64_t val)
{
uint64_t m0, m1, v0, v1, b0, b1, *b = (uint64_t *) (insn_addr & -16);
# define insn_mask ((1UL << 41) - 1)
unsigned long shift;
b0 = b[0]; b1 = b[1];
shift = 5 + 41 * (insn_addr % 16); /* 5 template, 3 x 41-bit insns */
if (shift >= 64) {
m1 = mask << (shift - 64);
v1 = val << (shift - 64);
} else {
m0 = mask << shift; m1 = mask >> (64 - shift);
v0 = val << shift; v1 = val >> (64 - shift);
b[0] = (b0 & ~m0) | (v0 & m0);
}
b[1] = (b1 & ~m1) | (v1 & m1);
}
static inline void ia64_patch_imm60 (uint64_t insn_addr, uint64_t val)
{
ia64_patch(insn_addr,
0x011ffffe000UL,
( ((val & 0x0800000000000000UL) >> 23) /* bit 59 -> 36 */
| ((val & 0x00000000000fffffUL) << 13) /* bit 0 -> 13 */));
ia64_patch(insn_addr - 1, 0x1fffffffffcUL, val >> 18);
}
static inline void ia64_imm64 (void *insn, uint64_t val)
{
/* Ignore the slot number of the relocation; GCC and Intel
toolchains differed for some time on whether IMM64 relocs are
against slot 1 (Intel) or slot 2 (GCC). */
uint64_t insn_addr = (uint64_t) insn & ~3UL;
ia64_patch(insn_addr + 2,
0x01fffefe000UL,
( ((val & 0x8000000000000000UL) >> 27) /* bit 63 -> 36 */
| ((val & 0x0000000000200000UL) << 0) /* bit 21 -> 21 */
| ((val & 0x00000000001f0000UL) << 6) /* bit 16 -> 22 */
| ((val & 0x000000000000ff80UL) << 20) /* bit 7 -> 27 */
| ((val & 0x000000000000007fUL) << 13) /* bit 0 -> 13 */)
);
ia64_patch(insn_addr + 1, 0x1ffffffffffUL, val >> 22);
}
static inline void ia64_imm60b (void *insn, uint64_t val)
{
/* Ignore the slot number of the relocation; GCC and Intel
toolchains differed for some time on whether IMM64 relocs are
against slot 1 (Intel) or slot 2 (GCC). */
uint64_t insn_addr = (uint64_t) insn & ~3UL;
if (val + ((uint64_t) 1 << 59) >= (1UL << 60))
fprintf(stderr, "%s: value %ld out of IMM60 range\n",
__FUNCTION__, (int64_t) val);
ia64_patch_imm60(insn_addr + 2, val);
}
static inline void ia64_imm22 (void *insn, uint64_t val)
{
if (val + (1 << 21) >= (1 << 22))
fprintf(stderr, "%s: value %li out of IMM22 range\n",
__FUNCTION__, (int64_t)val);
ia64_patch((uint64_t) insn, 0x01fffcfe000UL,
( ((val & 0x200000UL) << 15) /* bit 21 -> 36 */
| ((val & 0x1f0000UL) << 6) /* bit 16 -> 22 */
| ((val & 0x00ff80UL) << 20) /* bit 7 -> 27 */
| ((val & 0x00007fUL) << 13) /* bit 0 -> 13 */));
}
/* Like ia64_imm22(), but also clear bits 20-21. For addl, this has
the effect of turning "addl rX=imm22,rY" into "addl
rX=imm22,r0". */
static inline void ia64_imm22_r0 (void *insn, uint64_t val)
{
if (val + (1 << 21) >= (1 << 22))
fprintf(stderr, "%s: value %li out of IMM22 range\n",
__FUNCTION__, (int64_t)val);
ia64_patch((uint64_t) insn, 0x01fffcfe000UL | (0x3UL << 20),
( ((val & 0x200000UL) << 15) /* bit 21 -> 36 */
| ((val & 0x1f0000UL) << 6) /* bit 16 -> 22 */
| ((val & 0x00ff80UL) << 20) /* bit 7 -> 27 */
| ((val & 0x00007fUL) << 13) /* bit 0 -> 13 */));
}
static inline void ia64_imm21b (void *insn, uint64_t val)
{
if (val + (1 << 20) >= (1 << 21))
fprintf(stderr, "%s: value %li out of IMM21b range\n",
__FUNCTION__, (int64_t)val);
ia64_patch((uint64_t) insn, 0x11ffffe000UL,
( ((val & 0x100000UL) << 16) /* bit 20 -> 36 */
| ((val & 0x0fffffUL) << 13) /* bit 0 -> 13 */));
}
static inline void ia64_nop_b (void *insn)
{
ia64_patch((uint64_t) insn, (1UL << 41) - 1, 2UL << 37);
}
static inline void ia64_ldxmov(void *insn, uint64_t val)
{
if (val + (1 << 21) < (1 << 22))
ia64_patch((uint64_t) insn, 0x1fff80fe000UL, 8UL << 37);
}
static inline int ia64_patch_ltoff(void *insn, uint64_t val,
int relaxable)
{
if (relaxable && (val + (1 << 21) < (1 << 22))) {
ia64_imm22_r0(insn, val);
return 0;
}
return 1;
}
struct ia64_fixup {
struct ia64_fixup *next;
void *addr; /* address that needs to be patched */
long value;
};
#define IA64_PLT(insn, plt_index) \
do { \
struct ia64_fixup *fixup = alloca(sizeof(*fixup)); \
fixup->next = plt_fixes; \
plt_fixes = fixup; \
fixup->addr = (insn); \
fixup->value = (plt_index); \
plt_offset[(plt_index)] = 1; \
} while (0)
#define IA64_LTOFF(insn, val, relaxable) \
do { \
if (ia64_patch_ltoff(insn, val, relaxable)) { \
struct ia64_fixup *fixup = alloca(sizeof(*fixup)); \
fixup->next = ltoff_fixes; \
ltoff_fixes = fixup; \
fixup->addr = (insn); \
fixup->value = (val); \
} \
} while (0)
static inline void ia64_apply_fixes (uint8_t **gen_code_pp,
struct ia64_fixup *ltoff_fixes,
uint64_t gp,
struct ia64_fixup *plt_fixes,
int num_plts,
unsigned long *plt_target,
unsigned int *plt_offset)
{
static const uint8_t plt_bundle[] = {
0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, /* nop 0; movl r1=GP */
0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x60,
0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, /* nop 0; brl IP */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0
};
uint8_t *gen_code_ptr = *gen_code_pp, *plt_start, *got_start;
uint64_t *vp;
struct ia64_fixup *fixup;
unsigned int offset = 0;
struct fdesc {
long ip;
long gp;
} *fdesc;
int i;
if (plt_fixes) {
plt_start = gen_code_ptr;
for (i = 0; i < num_plts; ++i) {
if (plt_offset[i]) {
plt_offset[i] = offset;
offset += sizeof(plt_bundle);
fdesc = (struct fdesc *) plt_target[i];
memcpy(gen_code_ptr, plt_bundle, sizeof(plt_bundle));
ia64_imm64 (gen_code_ptr + 0x02, fdesc->gp);
ia64_imm60b(gen_code_ptr + 0x12,
(fdesc->ip - (long) (gen_code_ptr + 0x10)) >> 4);
gen_code_ptr += sizeof(plt_bundle);
}
}
for (fixup = plt_fixes; fixup; fixup = fixup->next)
ia64_imm21b(fixup->addr,
((long) plt_start + plt_offset[fixup->value]
- ((long) fixup->addr & ~0xf)) >> 4);
}
got_start = gen_code_ptr;
/* First, create the GOT: */
for (fixup = ltoff_fixes; fixup; fixup = fixup->next) {
/* first check if we already have this value in the GOT: */
for (vp = (uint64_t *) got_start; vp < (uint64_t *) gen_code_ptr; ++vp)
if (*vp == fixup->value)
break;
if (vp == (uint64_t *) gen_code_ptr) {
/* Nope, we need to put the value in the GOT: */
*vp = fixup->value;
gen_code_ptr += 8;
}
ia64_imm22(fixup->addr, (long) vp - gp);
}
/* Keep code ptr aligned. */
if ((long) gen_code_ptr & 15)
gen_code_ptr += 8;
*gen_code_pp = gen_code_ptr;
}
#endif

View File

@ -36,10 +36,6 @@ struct TranslationBlock;
#define OPPARAM_BUF_SIZE (OPC_BUF_SIZE * 3) #define OPPARAM_BUF_SIZE (OPC_BUF_SIZE * 3)
extern uint16_t gen_opc_buf[OPC_BUF_SIZE];
extern uint32_t gen_opparam_buf[OPPARAM_BUF_SIZE];
extern long gen_labels[OPC_BUF_SIZE];
extern int nb_gen_labels;
extern target_ulong gen_opc_pc[OPC_BUF_SIZE]; extern target_ulong gen_opc_pc[OPC_BUF_SIZE];
extern target_ulong gen_opc_npc[OPC_BUF_SIZE]; extern target_ulong gen_opc_npc[OPC_BUF_SIZE];
extern uint8_t gen_opc_cc_op[OPC_BUF_SIZE]; extern uint8_t gen_opc_cc_op[OPC_BUF_SIZE];
@ -63,8 +59,8 @@ extern int loglevel;
int gen_intermediate_code(CPUState *env, struct TranslationBlock *tb); int gen_intermediate_code(CPUState *env, struct TranslationBlock *tb);
int gen_intermediate_code_pc(CPUState *env, struct TranslationBlock *tb); int gen_intermediate_code_pc(CPUState *env, struct TranslationBlock *tb);
void dump_ops(const uint16_t *opc_buf, const uint32_t *opparam_buf);
unsigned long code_gen_max_block_size(void); unsigned long code_gen_max_block_size(void);
void cpu_gen_init(void);
int cpu_gen_code(CPUState *env, struct TranslationBlock *tb, int cpu_gen_code(CPUState *env, struct TranslationBlock *tb,
int *gen_code_size_ptr); int *gen_code_size_ptr);
int cpu_restore_state(struct TranslationBlock *tb, int cpu_restore_state(struct TranslationBlock *tb,
@ -120,6 +116,7 @@ static inline int tlb_set_page(CPUState *env, target_ulong vaddr,
#elif defined(__powerpc__) #elif defined(__powerpc__)
#define CODE_GEN_BUFFER_SIZE (6 * 1024 * 1024) #define CODE_GEN_BUFFER_SIZE (6 * 1024 * 1024)
#else #else
/* XXX: make it dynamic on x86 */
#define CODE_GEN_BUFFER_SIZE (16 * 1024 * 1024) #define CODE_GEN_BUFFER_SIZE (16 * 1024 * 1024)
#endif #endif
@ -136,7 +133,7 @@ static inline int tlb_set_page(CPUState *env, target_ulong vaddr,
#define CODE_GEN_MAX_BLOCKS (CODE_GEN_BUFFER_SIZE / CODE_GEN_AVG_BLOCK_SIZE) #define CODE_GEN_MAX_BLOCKS (CODE_GEN_BUFFER_SIZE / CODE_GEN_AVG_BLOCK_SIZE)
#if defined(__powerpc__) #if defined(__powerpc__) || defined(__x86_64__)
#define USE_DIRECT_JUMP #define USE_DIRECT_JUMP
#endif #endif
#if defined(__i386__) && !defined(_WIN32) #if defined(__i386__) && !defined(_WIN32)
@ -169,7 +166,7 @@ typedef struct TranslationBlock {
#ifdef USE_DIRECT_JUMP #ifdef USE_DIRECT_JUMP
uint16_t tb_jmp_offset[4]; /* offset of jump instruction */ uint16_t tb_jmp_offset[4]; /* offset of jump instruction */
#else #else
uint32_t tb_next[2]; /* address of jump generated code */ unsigned long tb_next[2]; /* address of jump generated code */
#endif #endif
/* list of TBs jumping to this one. This is a circular list using /* list of TBs jumping to this one. This is a circular list using
the two least significant bits of the pointers to tell what is the two least significant bits of the pointers to tell what is
@ -228,7 +225,7 @@ static inline void tb_set_jmp_target1(unsigned long jmp_addr, unsigned long addr
asm volatile ("sync" : : : "memory"); asm volatile ("sync" : : : "memory");
asm volatile ("isync" : : : "memory"); asm volatile ("isync" : : : "memory");
} }
#elif defined(__i386__) #elif defined(__i386__) || defined(__x86_64__)
static inline void tb_set_jmp_target1(unsigned long jmp_addr, unsigned long addr) static inline void tb_set_jmp_target1(unsigned long jmp_addr, unsigned long addr)
{ {
/* patch the branch destination */ /* patch the branch destination */
@ -294,48 +291,6 @@ TranslationBlock *tb_find_pc(unsigned long pc_ptr);
#define ASM_OP_LABEL_NAME(n, opname) \ #define ASM_OP_LABEL_NAME(n, opname) \
ASM_NAME(__op_label) #n "." ASM_NAME(opname) ASM_NAME(__op_label) #n "." ASM_NAME(opname)
#if defined(__powerpc__)
/* we patch the jump instruction directly */
#define GOTO_TB(opname, tbparam, n)\
do {\
asm volatile (ASM_DATA_SECTION\
ASM_OP_LABEL_NAME(n, opname) ":\n"\
".long 1f\n"\
ASM_PREVIOUS_SECTION \
"b " ASM_NAME(__op_jmp) #n "\n"\
"1:\n");\
} while (0)
#elif defined(__i386__) && defined(USE_DIRECT_JUMP)
/* we patch the jump instruction directly */
#define GOTO_TB(opname, tbparam, n)\
do {\
asm volatile (".section .data\n"\
ASM_OP_LABEL_NAME(n, opname) ":\n"\
".long 1f\n"\
ASM_PREVIOUS_SECTION \
"jmp " ASM_NAME(__op_jmp) #n "\n"\
"1:\n");\
} while (0)
#else
/* jump to next block operations (more portable code, does not need
cache flushing, but slower because of indirect jump) */
#define GOTO_TB(opname, tbparam, n)\
do {\
static void __attribute__((used)) *dummy ## n = &&dummy_label ## n;\
static void __attribute__((used)) *__op_label ## n \
__asm__(ASM_OP_LABEL_NAME(n, opname)) = &&label ## n;\
goto *(void *)(((TranslationBlock *)tbparam)->tb_next[n]);\
label ## n: ;\
dummy_label ## n: ;\
} while (0)
#endif
extern CPUWriteMemoryFunc *io_mem_write[IO_MEM_NB_ENTRIES][4]; extern CPUWriteMemoryFunc *io_mem_write[IO_MEM_NB_ENTRIES][4];
extern CPUReadMemoryFunc *io_mem_read[IO_MEM_NB_ENTRIES][4]; extern CPUReadMemoryFunc *io_mem_read[IO_MEM_NB_ENTRIES][4];
extern void *io_mem_opaque[IO_MEM_NB_ENTRIES]; extern void *io_mem_opaque[IO_MEM_NB_ENTRIES];

46
exec.c
View File

@ -312,6 +312,7 @@ void cpu_exec_init(CPUState *env)
int cpu_index; int cpu_index;
if (!code_gen_ptr) { if (!code_gen_ptr) {
cpu_gen_init();
code_gen_ptr = code_gen_buffer; code_gen_ptr = code_gen_buffer;
page_init(); page_init();
io_mem_init(); io_mem_init();
@ -1238,10 +1239,10 @@ CPULogItem cpu_log_items[] = {
{ CPU_LOG_TB_IN_ASM, "in_asm", { CPU_LOG_TB_IN_ASM, "in_asm",
"show target assembly code for each compiled TB" }, "show target assembly code for each compiled TB" },
{ CPU_LOG_TB_OP, "op", { CPU_LOG_TB_OP, "op",
"show micro ops for each compiled TB (only usable if 'in_asm' used)" }, "show micro ops for each compiled TB" },
#ifdef TARGET_I386 #ifdef TARGET_I386
{ CPU_LOG_TB_OP_OPT, "op_opt", { CPU_LOG_TB_OP_OPT, "op_opt",
"show micro ops after optimization for each compiled TB" }, "show micro ops before eflags optimization" },
#endif #endif
{ CPU_LOG_INT, "int", { CPU_LOG_INT, "int",
"show interrupts/exceptions in short format" }, "show interrupts/exceptions in short format" },
@ -2935,6 +2936,7 @@ void dump_exec_info(FILE *f,
} }
} }
/* XXX: avoid using doubles ? */ /* XXX: avoid using doubles ? */
cpu_fprintf(f, "Translation buffer state:\n");
cpu_fprintf(f, "TB count %d\n", nb_tbs); cpu_fprintf(f, "TB count %d\n", nb_tbs);
cpu_fprintf(f, "TB avg target size %d max=%d bytes\n", cpu_fprintf(f, "TB avg target size %d max=%d bytes\n",
nb_tbs ? target_code_size / nb_tbs : 0, nb_tbs ? target_code_size / nb_tbs : 0,
@ -2950,9 +2952,49 @@ void dump_exec_info(FILE *f,
nb_tbs ? (direct_jmp_count * 100) / nb_tbs : 0, nb_tbs ? (direct_jmp_count * 100) / nb_tbs : 0,
direct_jmp2_count, direct_jmp2_count,
nb_tbs ? (direct_jmp2_count * 100) / nb_tbs : 0); nb_tbs ? (direct_jmp2_count * 100) / nb_tbs : 0);
cpu_fprintf(f, "\nStatistics:\n");
cpu_fprintf(f, "TB flush count %d\n", tb_flush_count); cpu_fprintf(f, "TB flush count %d\n", tb_flush_count);
cpu_fprintf(f, "TB invalidate count %d\n", tb_phys_invalidate_count); cpu_fprintf(f, "TB invalidate count %d\n", tb_phys_invalidate_count);
cpu_fprintf(f, "TLB flush count %d\n", tlb_flush_count); cpu_fprintf(f, "TLB flush count %d\n", tlb_flush_count);
#ifdef CONFIG_PROFILER
{
int64_t tot;
tot = dyngen_interm_time + dyngen_code_time;
cpu_fprintf(f, "JIT cycles %" PRId64 " (%0.3f s at 2.4 GHz)\n",
tot, tot / 2.4e9);
cpu_fprintf(f, "translated TBs %" PRId64 " (aborted=%" PRId64 " %0.1f%%)\n",
dyngen_tb_count,
dyngen_tb_count1 - dyngen_tb_count,
dyngen_tb_count1 ? (double)(dyngen_tb_count1 - dyngen_tb_count) / dyngen_tb_count1 * 100.0 : 0);
cpu_fprintf(f, "avg ops/TB %0.1f max=%d\n",
dyngen_tb_count ? (double)dyngen_op_count / dyngen_tb_count : 0, dyngen_op_count_max);
cpu_fprintf(f, "old ops/total ops %0.1f%%\n",
dyngen_op_count ? (double)dyngen_old_op_count / dyngen_op_count * 100.0 : 0);
cpu_fprintf(f, "deleted ops/TB %0.2f\n",
dyngen_tb_count ?
(double)dyngen_tcg_del_op_count / dyngen_tb_count : 0);
cpu_fprintf(f, "cycles/op %0.1f\n",
dyngen_op_count ? (double)tot / dyngen_op_count : 0);
cpu_fprintf(f, "cycles/in byte %0.1f\n",
dyngen_code_in_len ? (double)tot / dyngen_code_in_len : 0);
cpu_fprintf(f, "cycles/out byte %0.1f\n",
dyngen_code_out_len ? (double)tot / dyngen_code_out_len : 0);
if (tot == 0)
tot = 1;
cpu_fprintf(f, " gen_interm time %0.1f%%\n",
(double)dyngen_interm_time / tot * 100.0);
cpu_fprintf(f, " gen_code time %0.1f%%\n",
(double)dyngen_code_time / tot * 100.0);
cpu_fprintf(f, "cpu_restore count %" PRId64 "\n",
dyngen_restore_count);
cpu_fprintf(f, " avg cycles %0.1f\n",
dyngen_restore_count ? (double)dyngen_restore_time / dyngen_restore_count : 0);
{
extern void dump_op_count(void);
dump_op_count();
}
}
#endif
} }
#if !defined(CONFIG_USER_ONLY) #if !defined(CONFIG_USER_ONLY)

View File

@ -216,11 +216,6 @@ void OPPROTO op_clear_irf (void)
RETURN(); RETURN();
} }
void OPPROTO op_exit_tb (void)
{
EXIT_TB();
}
/* Arithmetic */ /* Arithmetic */
void OPPROTO op_addq (void) void OPPROTO op_addq (void)
{ {

View File

@ -25,6 +25,7 @@
#include "cpu.h" #include "cpu.h"
#include "exec-all.h" #include "exec-all.h"
#include "disas.h" #include "disas.h"
#include "tcg-op.h"
#define DO_SINGLE_STEP #define DO_SINGLE_STEP
#define GENERATE_NOP #define GENERATE_NOP
@ -41,24 +42,6 @@ struct DisasContext {
uint32_t amask; uint32_t amask;
}; };
#ifdef USE_DIRECT_JUMP
#define TBPARAM(x)
#else
#define TBPARAM(x) (long)(x)
#endif
enum {
#define DEF(s, n, copy_size) INDEX_op_ ## s,
#include "opc.h"
#undef DEF
NB_OPS,
};
static uint16_t *gen_opc_ptr;
static uint32_t *gen_opparam_ptr;
#include "gen-op.h"
static always_inline void gen_op_nop (void) static always_inline void gen_op_nop (void)
{ {
#if defined(GENERATE_NOP) #if defined(GENERATE_NOP)
@ -1988,10 +1971,7 @@ static always_inline int gen_intermediate_code_internal (CPUState *env,
int ret; int ret;
pc_start = tb->pc; pc_start = tb->pc;
gen_opc_ptr = gen_opc_buf;
gen_opc_end = gen_opc_buf + OPC_MAX_SIZE; gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
gen_opparam_ptr = gen_opparam_buf;
nb_gen_labels = 0;
ctx.pc = pc_start; ctx.pc = pc_start;
ctx.amask = env->amask; ctx.amask = env->amask;
#if defined (CONFIG_USER_ONLY) #if defined (CONFIG_USER_ONLY)
@ -2051,12 +2031,11 @@ static always_inline int gen_intermediate_code_internal (CPUState *env,
if (ret != 1 && ret != 3) { if (ret != 1 && ret != 3) {
gen_update_pc(&ctx); gen_update_pc(&ctx);
} }
gen_op_reset_T0();
#if defined (DO_TB_FLUSH) #if defined (DO_TB_FLUSH)
gen_op_tb_flush(); gen_op_tb_flush();
#endif #endif
/* Generate the return instruction */ /* Generate the return instruction */
gen_op_exit_tb(); tcg_gen_exit_tb(0);
*gen_opc_ptr = INDEX_op_end; *gen_opc_ptr = INDEX_op_end;
if (search_pc) { if (search_pc) {
j = gen_opc_ptr - gen_opc_buf; j = gen_opc_ptr - gen_opc_buf;
@ -2075,11 +2054,6 @@ static always_inline int gen_intermediate_code_internal (CPUState *env,
target_disas(logfile, pc_start, ctx.pc - pc_start, 1); target_disas(logfile, pc_start, ctx.pc - pc_start, 1);
fprintf(logfile, "\n"); fprintf(logfile, "\n");
} }
if (loglevel & CPU_LOG_TB_OP) {
fprintf(logfile, "OP:\n");
dump_ops(gen_opc_buf, gen_opparam_buf);
fprintf(logfile, "\n");
}
#endif #endif
return 0; return 0;

View File

@ -364,21 +364,6 @@ void OPPROTO op_testn_T0(void)
FORCE_RET(); FORCE_RET();
} }
void OPPROTO op_goto_tb0(void)
{
GOTO_TB(op_goto_tb0, PARAM1, 0);
}
void OPPROTO op_goto_tb1(void)
{
GOTO_TB(op_goto_tb1, PARAM1, 1);
}
void OPPROTO op_exit_tb(void)
{
EXIT_TB();
}
void OPPROTO op_movl_T0_cpsr(void) void OPPROTO op_movl_T0_cpsr(void)
{ {
/* Execution state bits always read as zero. */ /* Execution state bits always read as zero. */

View File

@ -28,6 +28,7 @@
#include "cpu.h" #include "cpu.h"
#include "exec-all.h" #include "exec-all.h"
#include "disas.h" #include "disas.h"
#include "tcg-op.h"
#define ENABLE_ARCH_5J 0 #define ENABLE_ARCH_5J 0
#define ENABLE_ARCH_6 arm_feature(env, ARM_FEATURE_V6) #define ENABLE_ARCH_6 arm_feature(env, ARM_FEATURE_V6)
@ -68,27 +69,10 @@ typedef struct DisasContext {
#define DISAS_WFI 4 #define DISAS_WFI 4
#define DISAS_SWI 5 #define DISAS_SWI 5
#ifdef USE_DIRECT_JUMP
#define TBPARAM(x)
#else
#define TBPARAM(x) (long)(x)
#endif
/* XXX: move that elsewhere */ /* XXX: move that elsewhere */
static uint16_t *gen_opc_ptr;
static uint32_t *gen_opparam_ptr;
extern FILE *logfile; extern FILE *logfile;
extern int loglevel; extern int loglevel;
enum {
#define DEF(s, n, copy_size) INDEX_op_ ## s,
#include "opc.h"
#undef DEF
NB_OPS,
};
#include "gen-op.h"
#define PAS_OP(pfx) { \ #define PAS_OP(pfx) { \
gen_op_ ## pfx ## add16_T0_T1, \ gen_op_ ## pfx ## add16_T0_T1, \
gen_op_ ## pfx ## addsubx_T0_T1, \ gen_op_ ## pfx ## addsubx_T0_T1, \
@ -2432,19 +2416,14 @@ static inline void gen_goto_tb(DisasContext *s, int n, uint32_t dest)
tb = s->tb; tb = s->tb;
if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) { if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
if (n == 0) tcg_gen_goto_tb(n);
gen_op_goto_tb0(TBPARAM(tb));
else
gen_op_goto_tb1(TBPARAM(tb));
gen_op_movl_T0_im(dest); gen_op_movl_T0_im(dest);
gen_op_movl_r15_T0(); gen_op_movl_r15_T0();
gen_op_movl_T0_im((long)tb + n); tcg_gen_exit_tb((long)tb + n);
gen_op_exit_tb();
} else { } else {
gen_op_movl_T0_im(dest); gen_op_movl_T0_im(dest);
gen_op_movl_r15_T0(); gen_op_movl_r15_T0();
gen_op_movl_T0_0(); tcg_gen_exit_tb(0);
gen_op_exit_tb();
} }
} }
@ -7486,9 +7465,7 @@ static inline int gen_intermediate_code_internal(CPUState *env,
dc->tb = tb; dc->tb = tb;
gen_opc_ptr = gen_opc_buf;
gen_opc_end = gen_opc_buf + OPC_MAX_SIZE; gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
gen_opparam_ptr = gen_opparam_buf;
dc->is_jmp = DISAS_NEXT; dc->is_jmp = DISAS_NEXT;
dc->pc = pc_start; dc->pc = pc_start;
@ -7506,7 +7483,6 @@ static inline int gen_intermediate_code_internal(CPUState *env,
} }
#endif #endif
next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE; next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
nb_gen_labels = 0;
lj = -1; lj = -1;
/* Reset the conditional execution bits immediately. This avoids /* Reset the conditional execution bits immediately. This avoids
complications trying to do it at the end of the block. */ complications trying to do it at the end of the block. */
@ -7625,8 +7601,7 @@ static inline int gen_intermediate_code_internal(CPUState *env,
case DISAS_JUMP: case DISAS_JUMP:
case DISAS_UPDATE: case DISAS_UPDATE:
/* indicate that the hash table must be used to find the next TB */ /* indicate that the hash table must be used to find the next TB */
gen_op_movl_T0_0(); tcg_gen_exit_tb(0);
gen_op_exit_tb();
break; break;
case DISAS_TB_JUMP: case DISAS_TB_JUMP:
/* nothing more to generate */ /* nothing more to generate */
@ -7654,11 +7629,6 @@ done_generating:
fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start)); fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
target_disas(logfile, pc_start, dc->pc - pc_start, env->thumb); target_disas(logfile, pc_start, dc->pc - pc_start, env->thumb);
fprintf(logfile, "\n"); fprintf(logfile, "\n");
if (loglevel & (CPU_LOG_TB_OP)) {
fprintf(logfile, "OP:\n");
dump_ops(gen_opc_buf, gen_opparam_buf);
fprintf(logfile, "\n");
}
} }
#endif #endif
if (search_pc) { if (search_pc) {

View File

@ -151,23 +151,6 @@
/* Microcode. */ /* Microcode. */
void OPPROTO op_exit_tb (void)
{
EXIT_TB();
}
void OPPROTO op_goto_tb0 (void)
{
GOTO_TB(op_goto_tb0, PARAM1, 0);
RETURN();
}
void OPPROTO op_goto_tb1 (void)
{
GOTO_TB(op_goto_tb1, PARAM1, 1);
RETURN();
}
void OPPROTO op_break_im(void) void OPPROTO op_break_im(void)
{ {
env->trapnr = PARAM1; env->trapnr = PARAM1;
@ -1268,7 +1251,7 @@ void OPPROTO op_movl_btarget_T0 (void)
RETURN(); RETURN();
} }
void OPPROTO op_jmp (void) void OPPROTO op_jmp1 (void)
{ {
env->pc = env->btarget; env->pc = env->btarget;
RETURN(); RETURN();

View File

@ -51,6 +51,7 @@
#include "cpu.h" #include "cpu.h"
#include "exec-all.h" #include "exec-all.h"
#include "disas.h" #include "disas.h"
#include "tcg-op.h"
#include "crisv32-decode.h" #include "crisv32-decode.h"
#define CRIS_STATS 0 #define CRIS_STATS 0
@ -67,12 +68,6 @@
#define DIS(x) #define DIS(x)
#endif #endif
#ifdef USE_DIRECT_JUMP
#define TBPARAM(x)
#else
#define TBPARAM(x) (long)(x)
#endif
#define BUG() (gen_BUG(dc, __FILE__, __LINE__)) #define BUG() (gen_BUG(dc, __FILE__, __LINE__))
#define BUG_ON(x) ({if (x) BUG();}) #define BUG_ON(x) ({if (x) BUG();})
@ -85,17 +80,6 @@
#define CC_MASK_NZVC 0xf #define CC_MASK_NZVC 0xf
#define CC_MASK_RNZV 0x10e #define CC_MASK_RNZV 0x10e
static uint16_t *gen_opc_ptr;
static uint32_t *gen_opparam_ptr;
enum {
#define DEF(s, n, copy_size) INDEX_op_ ## s,
#include "opc.h"
#undef DEF
NB_OPS,
};
#include "gen-op.h"
/* This is the state at translation time. */ /* This is the state at translation time. */
typedef struct DisasContext { typedef struct DisasContext {
CPUState *env; CPUState *env;
@ -264,15 +248,14 @@ static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest)
TranslationBlock *tb; TranslationBlock *tb;
tb = dc->tb; tb = dc->tb;
if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) { if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
if (n == 0) #if 0
gen_op_goto_tb0(TBPARAM(tb)); /* XXX: this code is not finished */
else tcg_gen_goto_tb(n);
gen_op_goto_tb1(TBPARAM(tb)); #endif
gen_op_movl_T0_0(); tcg_gen_exit_tb(0);
} else { } else {
gen_op_movl_T0_0(); tcg_gen_exit_tb(0);
} }
gen_op_exit_tb();
} }
/* Sign extend at translation time. */ /* Sign extend at translation time. */
@ -2325,9 +2308,7 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb,
dc->env = env; dc->env = env;
dc->tb = tb; dc->tb = tb;
gen_opc_ptr = gen_opc_buf;
gen_opc_end = gen_opc_buf + OPC_MAX_SIZE; gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
gen_opparam_ptr = gen_opparam_buf;
dc->is_jmp = DISAS_NEXT; dc->is_jmp = DISAS_NEXT;
dc->pc = pc_start; dc->pc = pc_start;
@ -2374,7 +2355,7 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb,
if (dc->delayed_branch == 0) if (dc->delayed_branch == 0)
{ {
if (dc->bcc == CC_A) { if (dc->bcc == CC_A) {
gen_op_jmp (); gen_op_jmp1 ();
dc->is_jmp = DISAS_UPDATE; dc->is_jmp = DISAS_UPDATE;
} }
else { else {
@ -2409,9 +2390,7 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb,
case DISAS_UPDATE: case DISAS_UPDATE:
/* indicate that the hash table must be used /* indicate that the hash table must be used
to find the next TB */ to find the next TB */
/* T0 is used to index the jmp tables. */ tcg_gen_exit_tb(0);
gen_op_movl_T0_0();
gen_op_exit_tb();
break; break;
case DISAS_TB_JUMP: case DISAS_TB_JUMP:
/* nothing more to generate */ /* nothing more to generate */
@ -2434,11 +2413,6 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb,
fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start)); fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
target_disas(logfile, pc_start, dc->pc + 4 - pc_start, 0); target_disas(logfile, pc_start, dc->pc + 4 - pc_start, 0);
fprintf(logfile, "\n"); fprintf(logfile, "\n");
if (loglevel & CPU_LOG_TB_OP) {
fprintf(logfile, "OP:\n");
dump_ops(gen_opc_buf, gen_opparam_buf);
fprintf(logfile, "\n");
}
} }
#endif #endif
return 0; return 0;

View File

@ -181,8 +181,9 @@ void __hidden cpu_loop_exit(void);
void OPPROTO op_movl_eflags_T0(void); void OPPROTO op_movl_eflags_T0(void);
void OPPROTO op_movl_T0_eflags(void); void OPPROTO op_movl_T0_eflags(void);
void helper_divl_EAX_T0(void);
void helper_idivl_EAX_T0(void); #include "helper.h"
void helper_mulq_EAX_T0(void); void helper_mulq_EAX_T0(void);
void helper_imulq_EAX_T0(void); void helper_imulq_EAX_T0(void);
void helper_imulq_T0_T1(void); void helper_imulq_T0_T1(void);

View File

@ -1608,13 +1608,13 @@ int32_t idiv32(int64_t *q_ptr, int64_t num, int32_t den)
} }
#endif #endif
void helper_divl_EAX_T0(void) void helper_divl_EAX_T0(target_ulong t0)
{ {
unsigned int den, r; unsigned int den, r;
uint64_t num, q; uint64_t num, q;
num = ((uint32_t)EAX) | ((uint64_t)((uint32_t)EDX) << 32); num = ((uint32_t)EAX) | ((uint64_t)((uint32_t)EDX) << 32);
den = T0; den = t0;
if (den == 0) { if (den == 0) {
raise_exception(EXCP00_DIVZ); raise_exception(EXCP00_DIVZ);
} }
@ -1630,13 +1630,13 @@ void helper_divl_EAX_T0(void)
EDX = (uint32_t)r; EDX = (uint32_t)r;
} }
void helper_idivl_EAX_T0(void) void helper_idivl_EAX_T0(target_ulong t0)
{ {
int den, r; int den, r;
int64_t num, q; int64_t num, q;
num = ((uint32_t)EAX) | ((uint64_t)((uint32_t)EDX) << 32); num = ((uint32_t)EAX) | ((uint64_t)((uint32_t)EDX) << 32);
den = T0; den = t0;
if (den == 0) { if (den == 0) {
raise_exception(EXCP00_DIVZ); raise_exception(EXCP00_DIVZ);
} }

4
target-i386/helper.h Normal file
View File

@ -0,0 +1,4 @@
#define TCG_HELPER_PROTO
void TCG_HELPER_PROTO helper_divl_EAX_T0(target_ulong t0);
void TCG_HELPER_PROTO helper_idivl_EAX_T0(target_ulong t0);

View File

@ -172,31 +172,6 @@ void OPPROTO op_testl_T0_T1_cc(void)
/* operations without flags */ /* operations without flags */
void OPPROTO op_addl_T0_T1(void)
{
T0 += T1;
}
void OPPROTO op_orl_T0_T1(void)
{
T0 |= T1;
}
void OPPROTO op_andl_T0_T1(void)
{
T0 &= T1;
}
void OPPROTO op_subl_T0_T1(void)
{
T0 -= T1;
}
void OPPROTO op_xorl_T0_T1(void)
{
T0 ^= T1;
}
void OPPROTO op_negl_T0(void) void OPPROTO op_negl_T0(void)
{ {
T0 = -T0; T0 = -T0;
@ -217,18 +192,6 @@ void OPPROTO op_notl_T0(void)
T0 = ~T0; T0 = ~T0;
} }
void OPPROTO op_bswapl_T0(void)
{
T0 = bswap32(T0);
}
#ifdef TARGET_X86_64
void OPPROTO op_bswapq_T0(void)
{
helper_bswapq_T0();
}
#endif
/* multiply/divide */ /* multiply/divide */
/* XXX: add eflags optimizations */ /* XXX: add eflags optimizations */
@ -399,16 +362,6 @@ void OPPROTO op_idivw_AX_T0(void)
EDX = (EDX & ~0xffff) | r; EDX = (EDX & ~0xffff) | r;
} }
void OPPROTO op_divl_EAX_T0(void)
{
helper_divl_EAX_T0();
}
void OPPROTO op_idivl_EAX_T0(void)
{
helper_idivl_EAX_T0();
}
#ifdef TARGET_X86_64 #ifdef TARGET_X86_64
void OPPROTO op_divq_EAX_T0(void) void OPPROTO op_divq_EAX_T0(void)
{ {
@ -424,46 +377,6 @@ void OPPROTO op_idivq_EAX_T0(void)
/* constant load & misc op */ /* constant load & misc op */
/* XXX: consistent names */ /* XXX: consistent names */
void OPPROTO op_movl_T0_imu(void)
{
T0 = (uint32_t)PARAM1;
}
void OPPROTO op_movl_T0_im(void)
{
T0 = (int32_t)PARAM1;
}
void OPPROTO op_addl_T0_im(void)
{
T0 += PARAM1;
}
void OPPROTO op_andl_T0_ffff(void)
{
T0 = T0 & 0xffff;
}
void OPPROTO op_andl_T0_im(void)
{
T0 = T0 & PARAM1;
}
void OPPROTO op_movl_T0_T1(void)
{
T0 = T1;
}
void OPPROTO op_movl_T1_imu(void)
{
T1 = (uint32_t)PARAM1;
}
void OPPROTO op_movl_T1_im(void)
{
T1 = (int32_t)PARAM1;
}
void OPPROTO op_addl_T1_im(void) void OPPROTO op_addl_T1_im(void)
{ {
T1 += PARAM1; T1 += PARAM1;
@ -474,26 +387,6 @@ void OPPROTO op_movl_T1_A0(void)
T1 = A0; T1 = A0;
} }
void OPPROTO op_movl_A0_im(void)
{
A0 = (uint32_t)PARAM1;
}
void OPPROTO op_addl_A0_im(void)
{
A0 = (uint32_t)(A0 + PARAM1);
}
void OPPROTO op_movl_A0_seg(void)
{
A0 = (uint32_t)*(target_ulong *)((char *)env + PARAM1);
}
void OPPROTO op_addl_A0_seg(void)
{
A0 = (uint32_t)(A0 + *(target_ulong *)((char *)env + PARAM1));
}
void OPPROTO op_addl_A0_AL(void) void OPPROTO op_addl_A0_AL(void)
{ {
A0 = (uint32_t)(A0 + (EAX & 0xff)); A0 = (uint32_t)(A0 + (EAX & 0xff));
@ -523,46 +416,6 @@ typedef union UREG64 {
#ifdef TARGET_X86_64 #ifdef TARGET_X86_64
void OPPROTO op_movq_T0_im64(void)
{
T0 = PARAMQ1;
}
void OPPROTO op_movq_T1_im64(void)
{
T1 = PARAMQ1;
}
void OPPROTO op_movq_A0_im(void)
{
A0 = (int32_t)PARAM1;
}
void OPPROTO op_movq_A0_im64(void)
{
A0 = PARAMQ1;
}
void OPPROTO op_addq_A0_im(void)
{
A0 = (A0 + (int32_t)PARAM1);
}
void OPPROTO op_addq_A0_im64(void)
{
A0 = (A0 + PARAMQ1);
}
void OPPROTO op_movq_A0_seg(void)
{
A0 = *(target_ulong *)((char *)env + PARAM1);
}
void OPPROTO op_addq_A0_seg(void)
{
A0 += *(target_ulong *)((char *)env + PARAM1);
}
void OPPROTO op_addq_A0_AL(void) void OPPROTO op_addq_A0_AL(void)
{ {
A0 = (A0 + (EAX & 0xff)); A0 = (A0 + (EAX & 0xff));
@ -570,11 +423,6 @@ void OPPROTO op_addq_A0_AL(void)
#endif #endif
void OPPROTO op_andl_A0_ffff(void)
{
A0 = A0 & 0xffff;
}
/* memory access */ /* memory access */
#define MEMSUFFIX _raw #define MEMSUFFIX _raw
@ -588,30 +436,6 @@ void OPPROTO op_andl_A0_ffff(void)
#include "ops_mem.h" #include "ops_mem.h"
#endif #endif
/* indirect jump */
void OPPROTO op_jmp_T0(void)
{
EIP = T0;
}
void OPPROTO op_movl_eip_im(void)
{
EIP = (uint32_t)PARAM1;
}
#ifdef TARGET_X86_64
void OPPROTO op_movq_eip_im(void)
{
EIP = (int32_t)PARAM1;
}
void OPPROTO op_movq_eip_im64(void)
{
EIP = PARAMQ1;
}
#endif
void OPPROTO op_hlt(void) void OPPROTO op_hlt(void)
{ {
helper_hlt(); helper_hlt();
@ -735,16 +559,6 @@ void OPPROTO op_single_step(void)
helper_single_step(); helper_single_step();
} }
void OPPROTO op_movl_T0_0(void)
{
T0 = 0;
}
void OPPROTO op_exit_tb(void)
{
EXIT_TB();
}
/* multiple size ops */ /* multiple size ops */
#define ldul ldl #define ldul ldl
@ -879,75 +693,6 @@ void OPPROTO op_decq_ECX(void)
} }
#endif #endif
/* push/pop utils */
void op_addl_A0_SS(void)
{
A0 = (uint32_t)(A0 + env->segs[R_SS].base);
}
void op_subl_A0_2(void)
{
A0 = (uint32_t)(A0 - 2);
}
void op_subl_A0_4(void)
{
A0 = (uint32_t)(A0 - 4);
}
void op_addl_ESP_4(void)
{
ESP = (uint32_t)(ESP + 4);
}
void op_addl_ESP_2(void)
{
ESP = (uint32_t)(ESP + 2);
}
void op_addw_ESP_4(void)
{
ESP = (ESP & ~0xffff) | ((ESP + 4) & 0xffff);
}
void op_addw_ESP_2(void)
{
ESP = (ESP & ~0xffff) | ((ESP + 2) & 0xffff);
}
void op_addl_ESP_im(void)
{
ESP = (uint32_t)(ESP + PARAM1);
}
void op_addw_ESP_im(void)
{
ESP = (ESP & ~0xffff) | ((ESP + PARAM1) & 0xffff);
}
#ifdef TARGET_X86_64
void op_subq_A0_2(void)
{
A0 -= 2;
}
void op_subq_A0_8(void)
{
A0 -= 8;
}
void op_addq_ESP_8(void)
{
ESP += 8;
}
void op_addq_ESP_im(void)
{
ESP += PARAM1;
}
#endif
void OPPROTO op_rdtsc(void) void OPPROTO op_rdtsc(void)
{ {
helper_rdtsc(); helper_rdtsc();
@ -1362,16 +1107,6 @@ void OPPROTO op_clts(void)
/* flags handling */ /* flags handling */
void OPPROTO op_goto_tb0(void)
{
GOTO_TB(op_goto_tb0, PARAM1, 0);
}
void OPPROTO op_goto_tb1(void)
{
GOTO_TB(op_goto_tb1, PARAM1, 1);
}
void OPPROTO op_jmp_label(void) void OPPROTO op_jmp_label(void)
{ {
GOTO_LABEL_PARAM(1); GOTO_LABEL_PARAM(1);
@ -1451,11 +1186,6 @@ void OPPROTO op_xor_T0_1(void)
T0 ^= 1; T0 ^= 1;
} }
void OPPROTO op_set_cc_op(void)
{
CC_OP = PARAM1;
}
void OPPROTO op_mov_T0_cc(void) void OPPROTO op_mov_T0_cc(void)
{ {
T0 = cc_table[CC_OP].compute_all(); T0 = cc_table[CC_OP].compute_all();

View File

@ -18,110 +18,6 @@
* License along with this library; if not, write to the Free Software * License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
void OPPROTO glue(op_movl_A0,REGNAME)(void)
{
A0 = (uint32_t)REG;
}
void OPPROTO glue(op_addl_A0,REGNAME)(void)
{
A0 = (uint32_t)(A0 + REG);
}
void OPPROTO glue(glue(op_addl_A0,REGNAME),_s1)(void)
{
A0 = (uint32_t)(A0 + (REG << 1));
}
void OPPROTO glue(glue(op_addl_A0,REGNAME),_s2)(void)
{
A0 = (uint32_t)(A0 + (REG << 2));
}
void OPPROTO glue(glue(op_addl_A0,REGNAME),_s3)(void)
{
A0 = (uint32_t)(A0 + (REG << 3));
}
#ifdef TARGET_X86_64
void OPPROTO glue(op_movq_A0,REGNAME)(void)
{
A0 = REG;
}
void OPPROTO glue(op_addq_A0,REGNAME)(void)
{
A0 = (A0 + REG);
}
void OPPROTO glue(glue(op_addq_A0,REGNAME),_s1)(void)
{
A0 = (A0 + (REG << 1));
}
void OPPROTO glue(glue(op_addq_A0,REGNAME),_s2)(void)
{
A0 = (A0 + (REG << 2));
}
void OPPROTO glue(glue(op_addq_A0,REGNAME),_s3)(void)
{
A0 = (A0 + (REG << 3));
}
#endif
void OPPROTO glue(op_movl_T0,REGNAME)(void)
{
T0 = REG;
}
void OPPROTO glue(op_movl_T1,REGNAME)(void)
{
T1 = REG;
}
void OPPROTO glue(op_movh_T0,REGNAME)(void)
{
T0 = REG >> 8;
}
void OPPROTO glue(op_movh_T1,REGNAME)(void)
{
T1 = REG >> 8;
}
void OPPROTO glue(glue(op_movl,REGNAME),_T0)(void)
{
REG = (uint32_t)T0;
}
void OPPROTO glue(glue(op_movl,REGNAME),_T1)(void)
{
REG = (uint32_t)T1;
}
void OPPROTO glue(glue(op_movl,REGNAME),_A0)(void)
{
REG = (uint32_t)A0;
}
#ifdef TARGET_X86_64
void OPPROTO glue(glue(op_movq,REGNAME),_T0)(void)
{
REG = T0;
}
void OPPROTO glue(glue(op_movq,REGNAME),_T1)(void)
{
REG = T1;
}
void OPPROTO glue(glue(op_movq,REGNAME),_A0)(void)
{
REG = A0;
}
#endif
/* mov T1 to REG if T0 is true */ /* mov T1 to REG if T0 is true */
void OPPROTO glue(glue(op_cmovw,REGNAME),_T1_T0)(void) void OPPROTO glue(glue(op_cmovw,REGNAME),_T1_T0)(void)
{ {
@ -132,8 +28,15 @@ void OPPROTO glue(glue(op_cmovw,REGNAME),_T1_T0)(void)
void OPPROTO glue(glue(op_cmovl,REGNAME),_T1_T0)(void) void OPPROTO glue(glue(op_cmovl,REGNAME),_T1_T0)(void)
{ {
#ifdef TARGET_X86_64
if (T0) if (T0)
REG = (uint32_t)T1; REG = (uint32_t)T1;
else
REG = (uint32_t)REG;
#else
if (T0)
REG = (uint32_t)T1;
#endif
FORCE_RET(); FORCE_RET();
} }
@ -145,46 +48,3 @@ void OPPROTO glue(glue(op_cmovq,REGNAME),_T1_T0)(void)
FORCE_RET(); FORCE_RET();
} }
#endif #endif
/* NOTE: T0 high order bits are ignored */
void OPPROTO glue(glue(op_movw,REGNAME),_T0)(void)
{
REG = (REG & ~0xffff) | (T0 & 0xffff);
}
/* NOTE: T0 high order bits are ignored */
void OPPROTO glue(glue(op_movw,REGNAME),_T1)(void)
{
REG = (REG & ~0xffff) | (T1 & 0xffff);
}
/* NOTE: A0 high order bits are ignored */
void OPPROTO glue(glue(op_movw,REGNAME),_A0)(void)
{
REG = (REG & ~0xffff) | (A0 & 0xffff);
}
/* NOTE: T0 high order bits are ignored */
void OPPROTO glue(glue(op_movb,REGNAME),_T0)(void)
{
REG = (REG & ~0xff) | (T0 & 0xff);
}
/* NOTE: T0 high order bits are ignored */
void OPPROTO glue(glue(op_movh,REGNAME),_T0)(void)
{
REG = (REG & ~0xff00) | ((T0 & 0xff) << 8);
}
/* NOTE: T1 high order bits are ignored */
void OPPROTO glue(glue(op_movb,REGNAME),_T1)(void)
{
REG = (REG & ~0xff) | (T1 & 0xff);
}
/* NOTE: T1 high order bits are ignored */
void OPPROTO glue(glue(op_movh,REGNAME),_T1)(void)
{
REG = (REG & ~0xff00) | ((T1 & 0xff) << 8);
}

File diff suppressed because it is too large Load Diff

View File

@ -482,7 +482,7 @@ OP(set_sr)
FORCE_RET(); FORCE_RET();
} }
OP(jmp) OP(jmp_im)
{ {
GOTO_LABEL_PARAM(1); GOTO_LABEL_PARAM(1);
} }
@ -522,22 +522,6 @@ OP(jmp_T0)
FORCE_RET(); FORCE_RET();
} }
void OPPROTO op_goto_tb0(void)
{
GOTO_TB(op_goto_tb0, PARAM1, 0);
}
void OPPROTO op_goto_tb1(void)
{
GOTO_TB(op_goto_tb1, PARAM1, 1);
}
OP(exit_tb)
{
EXIT_TB();
}
/* Floating point. */ /* Floating point. */
OP(f64_to_i32) OP(f64_to_i32)
{ {

View File

@ -28,6 +28,7 @@
#include "cpu.h" #include "cpu.h"
#include "exec-all.h" #include "exec-all.h"
#include "disas.h" #include "disas.h"
#include "tcg-op.h"
#include "m68k-qreg.h" #include "m68k-qreg.h"
//#define DEBUG_DISPATCH 1 //#define DEBUG_DISPATCH 1
@ -67,20 +68,9 @@ typedef struct DisasContext {
static void *gen_throws_exception; static void *gen_throws_exception;
#define gen_last_qop NULL #define gen_last_qop NULL
static uint16_t *gen_opc_ptr;
static uint32_t *gen_opparam_ptr;
extern FILE *logfile; extern FILE *logfile;
extern int loglevel; extern int loglevel;
enum {
#define DEF(s, n, copy_size) INDEX_op_ ## s,
#include "opc.h"
#undef DEF
NB_OPS,
};
#include "gen-op.h"
#if defined(CONFIG_USER_ONLY) #if defined(CONFIG_USER_ONLY)
#define gen_st(s, name, addr, val) gen_op_st##name##_raw(addr, val) #define gen_st(s, name, addr, val) gen_op_st##name##_raw(addr, val)
#define gen_ld(s, name, val, addr) gen_op_ld##name##_raw(val, addr) #define gen_ld(s, name, val, addr) gen_op_ld##name##_raw(val, addr)
@ -622,7 +612,7 @@ static void gen_jmpcc(DisasContext *s, int cond, int l1)
gen_flush_flags(s); gen_flush_flags(s);
switch (cond) { switch (cond) {
case 0: /* T */ case 0: /* T */
gen_op_jmp(l1); gen_op_jmp_im(l1);
break; break;
case 1: /* F */ case 1: /* F */
break; break;
@ -702,7 +692,7 @@ static void gen_jmpcc(DisasContext *s, int cond, int l1)
gen_op_xor32(tmp, tmp, QREG_CC_DEST); gen_op_xor32(tmp, tmp, QREG_CC_DEST);
gen_op_and32(tmp, tmp, gen_im32(CCF_V)); gen_op_and32(tmp, tmp, gen_im32(CCF_V));
gen_op_jmp_nz32(tmp, l2); gen_op_jmp_nz32(tmp, l2);
gen_op_jmp(l1); gen_op_jmp_im(l1);
gen_set_label(l2); gen_set_label(l2);
} }
break; break;
@ -791,14 +781,12 @@ static void gen_jmp_tb(DisasContext *s, int n, uint32_t dest)
gen_exception(s, dest, EXCP_DEBUG); gen_exception(s, dest, EXCP_DEBUG);
} else if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) || } else if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) ||
(s->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) { (s->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
gen_op_goto_tb(0, n, (long)tb); tcg_gen_goto_tb(n);
gen_op_mov32(QREG_PC, gen_im32(dest)); gen_op_mov32(QREG_PC, gen_im32(dest));
gen_op_mov32(QREG_T0, gen_im32((long)tb + n)); tcg_gen_exit_tb((long)tb + n);
gen_op_exit_tb();
} else { } else {
gen_jmp(s, gen_im32(dest)); gen_jmp(s, gen_im32(dest));
gen_op_mov32(QREG_T0, gen_im32(0)); tcg_gen_exit_tb(0);
gen_op_exit_tb();
} }
s->is_jmp = DISAS_TB_JUMP; s->is_jmp = DISAS_TB_JUMP;
} }
@ -3073,7 +3061,7 @@ static void expand_op_addx_cc(qOP *qop)
gen_op_add32(arg0, arg0, gen_im32(1)); gen_op_add32(arg0, arg0, gen_im32(1));
gen_op_mov32(QREG_CC_OP, gen_im32(CC_OP_ADDX)); gen_op_mov32(QREG_CC_OP, gen_im32(CC_OP_ADDX));
gen_op_set_leu32(QREG_CC_X, arg0, arg1); gen_op_set_leu32(QREG_CC_X, arg0, arg1);
gen_op_jmp(l2); gen_op_jmp_im(l2);
gen_set_label(l1); gen_set_label(l1);
gen_op_mov32(QREG_CC_OP, gen_im32(CC_OP_ADD)); gen_op_mov32(QREG_CC_OP, gen_im32(CC_OP_ADD));
gen_op_set_ltu32(QREG_CC_X, arg0, arg1); gen_op_set_ltu32(QREG_CC_X, arg0, arg1);
@ -3093,7 +3081,7 @@ static void expand_op_subx_cc(qOP *qop)
gen_op_set_leu32(QREG_CC_X, arg0, arg1); gen_op_set_leu32(QREG_CC_X, arg0, arg1);
gen_op_sub32(arg0, arg0, gen_im32(1)); gen_op_sub32(arg0, arg0, gen_im32(1));
gen_op_mov32(QREG_CC_OP, gen_im32(CC_OP_SUBX)); gen_op_mov32(QREG_CC_OP, gen_im32(CC_OP_SUBX));
gen_op_jmp(l2); gen_op_jmp_im(l2);
gen_set_label(l1); gen_set_label(l1);
gen_op_set_ltu32(QREG_CC_X, arg0, arg1); gen_op_set_ltu32(QREG_CC_X, arg0, arg1);
gen_op_mov32(QREG_CC_OP, gen_im32(CC_OP_SUB)); gen_op_mov32(QREG_CC_OP, gen_im32(CC_OP_SUB));
@ -3162,9 +3150,7 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb,
dc->tb = tb; dc->tb = tb;
gen_opc_ptr = gen_opc_buf;
gen_opc_end = gen_opc_buf + OPC_MAX_SIZE; gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
gen_opparam_ptr = gen_opparam_buf;
dc->env = env; dc->env = env;
dc->is_jmp = DISAS_NEXT; dc->is_jmp = DISAS_NEXT;
@ -3174,7 +3160,6 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb,
dc->fpcr = env->fpcr; dc->fpcr = env->fpcr;
dc->user = (env->sr & SR_S) == 0; dc->user = (env->sr & SR_S) == 0;
dc->is_mem = 0; dc->is_mem = 0;
nb_gen_labels = 0;
lj = -1; lj = -1;
do { do {
free_qreg = 0; free_qreg = 0;
@ -3232,8 +3217,7 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb,
case DISAS_UPDATE: case DISAS_UPDATE:
gen_flush_cc_op(dc); gen_flush_cc_op(dc);
/* indicate that the hash table must be used to find the next TB */ /* indicate that the hash table must be used to find the next TB */
gen_op_mov32(QREG_T0, gen_im32(0)); tcg_gen_exit_tb(0);
gen_op_exit_tb();
break; break;
case DISAS_TB_JUMP: case DISAS_TB_JUMP:
/* nothing more to generate */ /* nothing more to generate */
@ -3248,11 +3232,6 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb,
fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start)); fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
target_disas(logfile, pc_start, dc->pc - pc_start, 0); target_disas(logfile, pc_start, dc->pc - pc_start, 0);
fprintf(logfile, "\n"); fprintf(logfile, "\n");
if (loglevel & (CPU_LOG_TB_OP)) {
fprintf(logfile, "OP:\n");
dump_ops(gen_opc_buf, gen_opparam_buf);
fprintf(logfile, "\n");
}
} }
#endif #endif
if (search_pc) { if (search_pc) {

View File

@ -1093,18 +1093,6 @@ OP_COND(lez, (target_long)T0 <= 0);
OP_COND(ltz, (target_long)T0 < 0); OP_COND(ltz, (target_long)T0 < 0);
/* Branches */ /* Branches */
void OPPROTO op_goto_tb0(void)
{
GOTO_TB(op_goto_tb0, PARAM1, 0);
FORCE_RET();
}
void OPPROTO op_goto_tb1(void)
{
GOTO_TB(op_goto_tb1, PARAM1, 1);
FORCE_RET();
}
/* Branch to register */ /* Branch to register */
void op_save_breg_target (void) void op_save_breg_target (void)
{ {
@ -3252,12 +3240,6 @@ void op_raise_exception_err (void)
FORCE_RET(); FORCE_RET();
} }
void op_exit_tb (void)
{
EXIT_TB();
FORCE_RET();
}
void op_wait (void) void op_wait (void)
{ {
env->halted = 1; env->halted = 1;

View File

@ -29,29 +29,12 @@
#include "cpu.h" #include "cpu.h"
#include "exec-all.h" #include "exec-all.h"
#include "disas.h" #include "disas.h"
#include "tcg-op.h"
//#define MIPS_DEBUG_DISAS //#define MIPS_DEBUG_DISAS
//#define MIPS_DEBUG_SIGN_EXTENSIONS //#define MIPS_DEBUG_SIGN_EXTENSIONS
//#define MIPS_SINGLE_STEP //#define MIPS_SINGLE_STEP
#ifdef USE_DIRECT_JUMP
#define TBPARAM(x)
#else
#define TBPARAM(x) (long)(x)
#endif
enum {
#define DEF(s, n, copy_size) INDEX_op_ ## s,
#include "opc.h"
#undef DEF
NB_OPS,
};
static uint16_t *gen_opc_ptr;
static uint32_t *gen_opparam_ptr;
#include "gen-op.h"
/* MIPS major opcodes */ /* MIPS major opcodes */
#define MASK_OP_MAJOR(op) (op & (0x3F << 26)) #define MASK_OP_MAJOR(op) (op & (0x3F << 26))
@ -1777,17 +1760,13 @@ static always_inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong des
TranslationBlock *tb; TranslationBlock *tb;
tb = ctx->tb; tb = ctx->tb;
if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) { if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
if (n == 0) tcg_gen_goto_tb(n);
gen_op_goto_tb0(TBPARAM(tb));
else
gen_op_goto_tb1(TBPARAM(tb));
gen_save_pc(dest); gen_save_pc(dest);
gen_op_set_T0((long)tb + n); tcg_gen_exit_tb((long)tb + n);
} else { } else {
gen_save_pc(dest); gen_save_pc(dest);
gen_op_reset_T0(); tcg_gen_exit_tb(0);
} }
gen_op_exit_tb();
} }
/* Branches (before delay slot) */ /* Branches (before delay slot) */
@ -6642,8 +6621,7 @@ static void decode_opc (CPUState *env, DisasContext *ctx)
/* unconditional branch to register */ /* unconditional branch to register */
MIPS_DEBUG("branch to register"); MIPS_DEBUG("branch to register");
gen_op_breg(); gen_op_breg();
gen_op_reset_T0(); tcg_gen_exit_tb(0);
gen_op_exit_tb();
break; break;
default: default:
MIPS_DEBUG("unknown branch"); MIPS_DEBUG("unknown branch");
@ -6665,10 +6643,7 @@ gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
fprintf (logfile, "search pc %d\n", search_pc); fprintf (logfile, "search pc %d\n", search_pc);
pc_start = tb->pc; pc_start = tb->pc;
gen_opc_ptr = gen_opc_buf;
gen_opc_end = gen_opc_buf + OPC_MAX_SIZE; gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
gen_opparam_ptr = gen_opparam_buf;
nb_gen_labels = 0;
ctx.pc = pc_start; ctx.pc = pc_start;
ctx.saved_pc = -1; ctx.saved_pc = -1;
ctx.tb = tb; ctx.tb = tb;
@ -6748,8 +6723,7 @@ gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
break; break;
case BS_EXCP: case BS_EXCP:
gen_op_interrupt_restart(); gen_op_interrupt_restart();
gen_op_reset_T0(); tcg_gen_exit_tb(0);
gen_op_exit_tb();
break; break;
case BS_BRANCH: case BS_BRANCH:
default: default:
@ -6777,11 +6751,6 @@ done_generating:
target_disas(logfile, pc_start, ctx.pc - pc_start, 0); target_disas(logfile, pc_start, ctx.pc - pc_start, 0);
fprintf(logfile, "\n"); fprintf(logfile, "\n");
} }
if (loglevel & CPU_LOG_TB_OP) {
fprintf(logfile, "OP:\n");
dump_ops(gen_opc_buf, gen_opparam_buf);
fprintf(logfile, "\n");
}
if (loglevel & CPU_LOG_TB_CPU) { if (loglevel & CPU_LOG_TB_CPU) {
fprintf(logfile, "---------------- %d %08x\n", ctx.bstate, ctx.hflags); fprintf(logfile, "---------------- %d %08x\n", ctx.bstate, ctx.hflags);
} }

View File

@ -222,11 +222,6 @@ void OPPROTO op_debug (void)
do_raise_exception(EXCP_DEBUG); do_raise_exception(EXCP_DEBUG);
} }
void OPPROTO op_exit_tb (void)
{
EXIT_TB();
}
/* Load/store special registers */ /* Load/store special registers */
void OPPROTO op_load_cr (void) void OPPROTO op_load_cr (void)
{ {
@ -674,16 +669,6 @@ void OPPROTO op_setlr_64 (void)
} }
#endif #endif
void OPPROTO op_goto_tb0 (void)
{
GOTO_TB(op_goto_tb0, PARAM1, 0);
}
void OPPROTO op_goto_tb1 (void)
{
GOTO_TB(op_goto_tb1, PARAM1, 1);
}
void OPPROTO op_b_T1 (void) void OPPROTO op_b_T1 (void)
{ {
env->nip = (uint32_t)(T1 & ~3); env->nip = (uint32_t)(T1 & ~3);

View File

@ -26,6 +26,7 @@
#include "cpu.h" #include "cpu.h"
#include "exec-all.h" #include "exec-all.h"
#include "disas.h" #include "disas.h"
#include "tcg-op.h"
/* Include definitions for instructions classes and implementations flags */ /* Include definitions for instructions classes and implementations flags */
//#define DO_SINGLE_STEP //#define DO_SINGLE_STEP
@ -36,28 +37,12 @@
/*****************************************************************************/ /*****************************************************************************/
/* Code translation helpers */ /* Code translation helpers */
#if defined(USE_DIRECT_JUMP)
#define TBPARAM(x)
#else
#define TBPARAM(x) (long)(x)
#endif
enum {
#define DEF(s, n, copy_size) INDEX_op_ ## s,
#include "opc.h"
#undef DEF
NB_OPS,
};
static uint16_t *gen_opc_ptr;
static uint32_t *gen_opparam_ptr;
#if defined(OPTIMIZE_FPRF_UPDATE) #if defined(OPTIMIZE_FPRF_UPDATE)
static uint16_t *gen_fprf_buf[OPC_BUF_SIZE]; static uint16_t *gen_fprf_buf[OPC_BUF_SIZE];
static uint16_t **gen_fprf_ptr; static uint16_t **gen_fprf_ptr;
#endif #endif
#include "gen-op.h"
static always_inline void gen_set_T0 (target_ulong val) static always_inline void gen_set_T0 (target_ulong val)
{ {
#if defined(TARGET_PPC64) #if defined(TARGET_PPC64)
@ -2798,11 +2783,9 @@ static always_inline void gen_goto_tb (DisasContext *ctx, int n,
{ {
TranslationBlock *tb; TranslationBlock *tb;
tb = ctx->tb; tb = ctx->tb;
if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) { if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
if (n == 0) !ctx->singlestep_enabled) {
gen_op_goto_tb0(TBPARAM(tb)); tcg_gen_goto_tb(n);
else
gen_op_goto_tb1(TBPARAM(tb));
gen_set_T1(dest); gen_set_T1(dest);
#if defined(TARGET_PPC64) #if defined(TARGET_PPC64)
if (ctx->sf_mode) if (ctx->sf_mode)
@ -2810,10 +2793,7 @@ static always_inline void gen_goto_tb (DisasContext *ctx, int n,
else else
#endif #endif
gen_op_b_T1(); gen_op_b_T1();
gen_op_set_T0((long)tb + n); tcg_gen_exit_tb((long)tb + n);
if (ctx->singlestep_enabled)
gen_op_debug();
gen_op_exit_tb();
} else { } else {
gen_set_T1(dest); gen_set_T1(dest);
#if defined(TARGET_PPC64) #if defined(TARGET_PPC64)
@ -2822,10 +2802,9 @@ static always_inline void gen_goto_tb (DisasContext *ctx, int n,
else else
#endif #endif
gen_op_b_T1(); gen_op_b_T1();
gen_op_reset_T0();
if (ctx->singlestep_enabled) if (ctx->singlestep_enabled)
gen_op_debug(); gen_op_debug();
gen_op_exit_tb(); tcg_gen_exit_tb(0);
} }
} }
@ -2934,7 +2913,6 @@ static always_inline void gen_bcond (DisasContext *ctx, int type)
else else
#endif #endif
gen_op_b_T1(); gen_op_b_T1();
gen_op_reset_T0();
goto no_test; goto no_test;
} }
break; break;
@ -3005,11 +2983,10 @@ static always_inline void gen_bcond (DisasContext *ctx, int type)
else else
#endif #endif
gen_op_btest_T1(ctx->nip); gen_op_btest_T1(ctx->nip);
gen_op_reset_T0();
no_test: no_test:
if (ctx->singlestep_enabled) if (ctx->singlestep_enabled)
gen_op_debug(); gen_op_debug();
gen_op_exit_tb(); tcg_gen_exit_tb(0);
} }
out: out:
ctx->exception = POWERPC_EXCP_BRANCH; ctx->exception = POWERPC_EXCP_BRANCH;
@ -6176,13 +6153,10 @@ static always_inline int gen_intermediate_code_internal (CPUState *env,
int j, lj = -1; int j, lj = -1;
pc_start = tb->pc; pc_start = tb->pc;
gen_opc_ptr = gen_opc_buf;
gen_opc_end = gen_opc_buf + OPC_MAX_SIZE; gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
gen_opparam_ptr = gen_opparam_buf;
#if defined(OPTIMIZE_FPRF_UPDATE) #if defined(OPTIMIZE_FPRF_UPDATE)
gen_fprf_ptr = gen_fprf_buf; gen_fprf_ptr = gen_fprf_buf;
#endif #endif
nb_gen_labels = 0;
ctx.nip = pc_start; ctx.nip = pc_start;
ctx.tb = tb; ctx.tb = tb;
ctx.exception = POWERPC_EXCP_NONE; ctx.exception = POWERPC_EXCP_NONE;
@ -6332,9 +6306,8 @@ static always_inline int gen_intermediate_code_internal (CPUState *env,
if (ctx.exception == POWERPC_EXCP_NONE) { if (ctx.exception == POWERPC_EXCP_NONE) {
gen_goto_tb(&ctx, 0, ctx.nip); gen_goto_tb(&ctx, 0, ctx.nip);
} else if (ctx.exception != POWERPC_EXCP_BRANCH) { } else if (ctx.exception != POWERPC_EXCP_BRANCH) {
gen_op_reset_T0();
/* Generate the return instruction */ /* Generate the return instruction */
gen_op_exit_tb(); tcg_gen_exit_tb(0);
} }
*gen_opc_ptr = INDEX_op_end; *gen_opc_ptr = INDEX_op_end;
if (unlikely(search_pc)) { if (unlikely(search_pc)) {
@ -6358,11 +6331,6 @@ static always_inline int gen_intermediate_code_internal (CPUState *env,
target_disas(logfile, pc_start, ctx.nip - pc_start, flags); target_disas(logfile, pc_start, ctx.nip - pc_start, flags);
fprintf(logfile, "\n"); fprintf(logfile, "\n");
} }
if (loglevel & CPU_LOG_TB_OP) {
fprintf(logfile, "OP:\n");
dump_ops(gen_opc_buf, gen_opparam_buf);
fprintf(logfile, "\n");
}
#endif #endif
return 0; return 0;
} }

View File

@ -161,12 +161,6 @@ void OPPROTO op_rts(void)
RETURN(); RETURN();
} }
void OPPROTO op_exit_tb(void)
{
EXIT_TB();
RETURN();
}
void OPPROTO op_addl_imm_T0(void) void OPPROTO op_addl_imm_T0(void)
{ {
T0 += PARAM1; T0 += PARAM1;
@ -947,18 +941,6 @@ void OPPROTO op_movl_FT0_fpul(void)
RETURN(); RETURN();
} }
void OPPROTO op_goto_tb0(void)
{
GOTO_TB(op_goto_tb0, PARAM1, 0);
RETURN();
}
void OPPROTO op_goto_tb1(void)
{
GOTO_TB(op_goto_tb1, PARAM1, 1);
RETURN();
}
void OPPROTO op_movl_imm_PC(void) void OPPROTO op_movl_imm_PC(void)
{ {
env->pc = PARAM1; env->pc = PARAM1;

View File

@ -31,24 +31,7 @@
#include "cpu.h" #include "cpu.h"
#include "exec-all.h" #include "exec-all.h"
#include "disas.h" #include "disas.h"
#include "tcg-op.h"
enum {
#define DEF(s, n, copy_size) INDEX_op_ ## s,
#include "opc.h"
#undef DEF
NB_OPS,
};
#ifdef USE_DIRECT_JUMP
#define TBPARAM(x)
#else
#define TBPARAM(x) ((long)(x))
#endif
static uint16_t *gen_opc_ptr;
static uint32_t *gen_opparam_ptr;
#include "gen-op.h"
typedef struct DisasContext { typedef struct DisasContext {
struct TranslationBlock *tb; struct TranslationBlock *tb;
@ -172,18 +155,15 @@ static void gen_goto_tb(DisasContext * ctx, int n, target_ulong dest)
if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) && if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
!ctx->singlestep_enabled) { !ctx->singlestep_enabled) {
/* Use a direct jump if in same page and singlestep not enabled */ /* Use a direct jump if in same page and singlestep not enabled */
if (n == 0) tcg_gen_goto_tb(n);
gen_op_goto_tb0(TBPARAM(tb)); gen_op_movl_imm_PC(dest);
else tcg_gen_exit_tb((long) tb + n);
gen_op_goto_tb1(TBPARAM(tb));
gen_op_movl_imm_T0((long) tb + n);
} else { } else {
gen_op_movl_imm_T0(0); gen_op_movl_imm_PC(dest);
if (ctx->singlestep_enabled)
gen_op_debug();
tcg_gen_exit_tb(0);
} }
gen_op_movl_imm_PC(dest);
if (ctx->singlestep_enabled)
gen_op_debug();
gen_op_exit_tb();
} }
static void gen_jump(DisasContext * ctx) static void gen_jump(DisasContext * ctx)
@ -192,10 +172,9 @@ static void gen_jump(DisasContext * ctx)
/* Target is not statically known, it comes necessarily from a /* Target is not statically known, it comes necessarily from a
delayed jump as immediate jump are conditinal jumps */ delayed jump as immediate jump are conditinal jumps */
gen_op_movl_delayed_pc_PC(); gen_op_movl_delayed_pc_PC();
gen_op_movl_imm_T0(0);
if (ctx->singlestep_enabled) if (ctx->singlestep_enabled)
gen_op_debug(); gen_op_debug();
gen_op_exit_tb(); tcg_gen_exit_tb(0);
} else { } else {
gen_goto_tb(ctx, 0, ctx->delayed_pc); gen_goto_tb(ctx, 0, ctx->delayed_pc);
} }
@ -1176,9 +1155,7 @@ gen_intermediate_code_internal(CPUState * env, TranslationBlock * tb,
int i, ii; int i, ii;
pc_start = tb->pc; pc_start = tb->pc;
gen_opc_ptr = gen_opc_buf;
gen_opc_end = gen_opc_buf + OPC_MAX_SIZE; gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
gen_opparam_ptr = gen_opparam_buf;
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;
@ -1190,7 +1167,6 @@ gen_intermediate_code_internal(CPUState * env, TranslationBlock * tb,
ctx.delayed_pc = -1; /* use delayed pc from env pointer */ ctx.delayed_pc = -1; /* use delayed pc from env pointer */
ctx.tb = tb; ctx.tb = tb;
ctx.singlestep_enabled = env->singlestep_enabled; ctx.singlestep_enabled = env->singlestep_enabled;
nb_gen_labels = 0;
#ifdef DEBUG_DISAS #ifdef DEBUG_DISAS
if (loglevel & CPU_LOG_TB_CPU) { if (loglevel & CPU_LOG_TB_CPU) {
@ -1254,8 +1230,7 @@ gen_intermediate_code_internal(CPUState * env, TranslationBlock * tb,
break; break;
case BS_EXCP: case BS_EXCP:
/* gen_op_interrupt_restart(); */ /* gen_op_interrupt_restart(); */
gen_op_movl_imm_T0(0); tcg_gen_exit_tb(0);
gen_op_exit_tb();
break; break;
case BS_BRANCH: case BS_BRANCH:
default: default:
@ -1283,11 +1258,6 @@ gen_intermediate_code_internal(CPUState * env, TranslationBlock * tb,
target_disas(logfile, pc_start, ctx.pc - pc_start, 0); target_disas(logfile, pc_start, ctx.pc - pc_start, 0);
fprintf(logfile, "\n"); fprintf(logfile, "\n");
} }
if (loglevel & CPU_LOG_TB_OP) {
fprintf(logfile, "OP:\n");
dump_ops(gen_opc_buf, gen_opparam_buf);
fprintf(logfile, "\n");
}
#endif #endif
return 0; return 0;
} }

View File

@ -1277,11 +1277,6 @@ void OPPROTO op_debug(void)
helper_debug(); helper_debug();
} }
void OPPROTO op_exit_tb(void)
{
EXIT_TB();
}
void OPPROTO op_eval_ba(void) void OPPROTO op_eval_ba(void)
{ {
T2 = 1; T2 = 1;
@ -1542,16 +1537,6 @@ void OPPROTO op_next_insn(void)
env->npc = env->npc + 4; env->npc = env->npc + 4;
} }
void OPPROTO op_goto_tb0(void)
{
GOTO_TB(op_goto_tb0, PARAM1, 0);
}
void OPPROTO op_goto_tb1(void)
{
GOTO_TB(op_goto_tb1, PARAM1, 1);
}
void OPPROTO op_jmp_label(void) void OPPROTO op_jmp_label(void)
{ {
GOTO_LABEL_PARAM(1); GOTO_LABEL_PARAM(1);

View File

@ -36,6 +36,7 @@
#include "cpu.h" #include "cpu.h"
#include "exec-all.h" #include "exec-all.h"
#include "disas.h" #include "disas.h"
#include "tcg-op.h"
#define DEBUG_DISAS #define DEBUG_DISAS
@ -65,20 +66,9 @@ struct sparc_def_t {
static const sparc_def_t *cpu_sparc_find_by_name(const unsigned char *name); static const sparc_def_t *cpu_sparc_find_by_name(const unsigned char *name);
static uint16_t *gen_opc_ptr;
static uint32_t *gen_opparam_ptr;
extern FILE *logfile; extern FILE *logfile;
extern int loglevel; extern int loglevel;
enum {
#define DEF(s,n,copy_size) INDEX_op_ ## s,
#include "opc.h"
#undef DEF
NB_OPS
};
#include "gen-op.h"
// This function uses non-native bit order // This function uses non-native bit order
#define GET_FIELD(X, FROM, TO) \ #define GET_FIELD(X, FROM, TO) \
((X) >> (31 - (TO)) & ((1 << ((TO) - (FROM) + 1)) - 1)) ((X) >> (31 - (TO)) & ((1 << ((TO) - (FROM) + 1)) - 1))
@ -98,12 +88,6 @@ enum {
#define QFPREG(r) (r & 0x1c) #define QFPREG(r) (r & 0x1c)
#endif #endif
#ifdef USE_DIRECT_JUMP
#define TBPARAM(x)
#else
#define TBPARAM(x) (long)(x)
#endif
static int sign_extend(int x, int len) static int sign_extend(int x, int len)
{ {
len = 32 - len; len = 32 - len;
@ -699,20 +683,15 @@ static inline void gen_goto_tb(DisasContext *s, int tb_num,
if ((pc & TARGET_PAGE_MASK) == (tb->pc & TARGET_PAGE_MASK) && if ((pc & TARGET_PAGE_MASK) == (tb->pc & TARGET_PAGE_MASK) &&
(npc & TARGET_PAGE_MASK) == (tb->pc & TARGET_PAGE_MASK)) { (npc & TARGET_PAGE_MASK) == (tb->pc & TARGET_PAGE_MASK)) {
/* jump to same page: we can use a direct jump */ /* jump to same page: we can use a direct jump */
if (tb_num == 0) tcg_gen_goto_tb(tb_num);
gen_op_goto_tb0(TBPARAM(tb));
else
gen_op_goto_tb1(TBPARAM(tb));
gen_jmp_im(pc); gen_jmp_im(pc);
gen_movl_npc_im(npc); gen_movl_npc_im(npc);
gen_op_movl_T0_im((long)tb + tb_num); tcg_gen_exit_tb((long)tb + tb_num);
gen_op_exit_tb();
} else { } else {
/* jump to another page: currently not optimized */ /* jump to another page: currently not optimized */
gen_jmp_im(pc); gen_jmp_im(pc);
gen_movl_npc_im(npc); gen_movl_npc_im(npc);
gen_op_movl_T0_0(); tcg_gen_exit_tb(0);
gen_op_exit_tb();
} }
} }
@ -1281,8 +1260,7 @@ static void disas_sparc_insn(DisasContext * dc)
gen_op_trapcc_T0(); gen_op_trapcc_T0();
} }
gen_op_next_insn(); gen_op_next_insn();
gen_op_movl_T0_0(); tcg_gen_exit_tb(0);
gen_op_exit_tb();
dc->is_br = 1; dc->is_br = 1;
goto jmp_insn; goto jmp_insn;
} else if (xop == 0x28) { } else if (xop == 0x28) {
@ -2341,8 +2319,7 @@ static void disas_sparc_insn(DisasContext * dc)
gen_op_movl_env_T0(offsetof(CPUSPARCState, fprs)); gen_op_movl_env_T0(offsetof(CPUSPARCState, fprs));
save_state(dc); save_state(dc);
gen_op_next_insn(); gen_op_next_insn();
gen_op_movl_T0_0(); tcg_gen_exit_tb(0);
gen_op_exit_tb();
dc->is_br = 1; dc->is_br = 1;
break; break;
case 0xf: /* V9 sir, nop if user */ case 0xf: /* V9 sir, nop if user */
@ -2422,8 +2399,7 @@ static void disas_sparc_insn(DisasContext * dc)
gen_op_wrpsr(); gen_op_wrpsr();
save_state(dc); save_state(dc);
gen_op_next_insn(); gen_op_next_insn();
gen_op_movl_T0_0(); tcg_gen_exit_tb(0);
gen_op_exit_tb();
dc->is_br = 1; dc->is_br = 1;
#endif #endif
} }
@ -2457,8 +2433,7 @@ static void disas_sparc_insn(DisasContext * dc)
gen_op_wrpstate(); gen_op_wrpstate();
save_state(dc); save_state(dc);
gen_op_next_insn(); gen_op_next_insn();
gen_op_movl_T0_0(); tcg_gen_exit_tb(0);
gen_op_exit_tb();
dc->is_br = 1; dc->is_br = 1;
break; break;
case 7: // tl case 7: // tl
@ -2517,8 +2492,7 @@ static void disas_sparc_insn(DisasContext * dc)
// XXX gen_op_wrhpstate(); // XXX gen_op_wrhpstate();
save_state(dc); save_state(dc);
gen_op_next_insn(); gen_op_next_insn();
gen_op_movl_T0_0(); tcg_gen_exit_tb(0);
gen_op_exit_tb();
dc->is_br = 1; dc->is_br = 1;
break; break;
case 1: // htstate case 1: // htstate
@ -3635,10 +3609,7 @@ static inline int gen_intermediate_code_internal(TranslationBlock * tb,
dc->npc = (target_ulong) tb->cs_base; dc->npc = (target_ulong) tb->cs_base;
dc->mem_idx = cpu_mmu_index(env); dc->mem_idx = cpu_mmu_index(env);
dc->fpu_enabled = cpu_fpu_enabled(env); dc->fpu_enabled = cpu_fpu_enabled(env);
gen_opc_ptr = gen_opc_buf;
gen_opc_end = gen_opc_buf + OPC_MAX_SIZE; gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
gen_opparam_ptr = gen_opparam_buf;
nb_gen_labels = 0;
do { do {
if (env->nb_breakpoints > 0) { if (env->nb_breakpoints > 0) {
@ -3647,8 +3618,7 @@ static inline int gen_intermediate_code_internal(TranslationBlock * tb,
if (dc->pc != pc_start) if (dc->pc != pc_start)
save_state(dc); save_state(dc);
gen_op_debug(); gen_op_debug();
gen_op_movl_T0_0(); tcg_gen_exit_tb(0);
gen_op_exit_tb();
dc->is_br = 1; dc->is_br = 1;
goto exit_gen_loop; goto exit_gen_loop;
} }
@ -3683,8 +3653,7 @@ static inline int gen_intermediate_code_internal(TranslationBlock * tb,
generate an exception */ generate an exception */
if (env->singlestep_enabled) { if (env->singlestep_enabled) {
gen_jmp_im(dc->pc); gen_jmp_im(dc->pc);
gen_op_movl_T0_0(); tcg_gen_exit_tb(0);
gen_op_exit_tb();
break; break;
} }
} while ((gen_opc_ptr < gen_opc_end) && } while ((gen_opc_ptr < gen_opc_end) &&
@ -3700,8 +3669,7 @@ static inline int gen_intermediate_code_internal(TranslationBlock * tb,
if (dc->pc != DYNAMIC_PC) if (dc->pc != DYNAMIC_PC)
gen_jmp_im(dc->pc); gen_jmp_im(dc->pc);
save_npc(dc); save_npc(dc);
gen_op_movl_T0_0(); tcg_gen_exit_tb(0);
gen_op_exit_tb();
} }
} }
*gen_opc_ptr = INDEX_op_end; *gen_opc_ptr = INDEX_op_end;
@ -3726,11 +3694,6 @@ static inline int gen_intermediate_code_internal(TranslationBlock * tb,
fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start)); fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
target_disas(logfile, pc_start, last_pc + 4 - pc_start, 0); target_disas(logfile, pc_start, last_pc + 4 - pc_start, 0);
fprintf(logfile, "\n"); fprintf(logfile, "\n");
if (loglevel & CPU_LOG_TB_OP) {
fprintf(logfile, "OP:\n");
dump_ops(gen_opc_buf, gen_opparam_buf);
fprintf(logfile, "\n");
}
} }
#endif #endif
return 0; return 0;
@ -3746,8 +3709,6 @@ int gen_intermediate_code_pc(CPUSPARCState * env, TranslationBlock * tb)
return gen_intermediate_code_internal(tb, 1, env); return gen_intermediate_code_internal(tb, 1, env);
} }
extern int ram_size;
void cpu_reset(CPUSPARCState *env) void cpu_reset(CPUSPARCState *env)
{ {
tlb_flush(env, 1); tlb_flush(env, 1);

View File

@ -29,22 +29,13 @@
#include "cpu.h" #include "cpu.h"
#include "exec-all.h" #include "exec-all.h"
#include "disas.h" #include "disas.h"
#include "tcg.h"
extern int dyngen_code(uint8_t *gen_code_buf, /* code generation context */
uint16_t *label_offsets, uint16_t *jmp_offsets, TCGContext tcg_ctx;
const uint16_t *opc_buf, const uint32_t *opparam_buf, const long *gen_labels);
enum {
#define DEF(s, n, copy_size) INDEX_op_ ## s,
#include "opc.h"
#undef DEF
NB_OPS,
};
uint16_t gen_opc_buf[OPC_BUF_SIZE]; uint16_t gen_opc_buf[OPC_BUF_SIZE];
uint32_t gen_opparam_buf[OPPARAM_BUF_SIZE]; TCGArg gen_opparam_buf[OPPARAM_BUF_SIZE];
long gen_labels[OPC_BUF_SIZE];
int nb_gen_labels;
target_ulong gen_opc_pc[OPC_BUF_SIZE]; target_ulong gen_opc_pc[OPC_BUF_SIZE];
uint8_t gen_opc_instr_start[OPC_BUF_SIZE]; uint8_t gen_opc_instr_start[OPC_BUF_SIZE];
@ -59,86 +50,29 @@ uint32_t gen_opc_hflags[OPC_BUF_SIZE];
int code_copy_enabled = 1; int code_copy_enabled = 1;
#ifdef DEBUG_DISAS #ifdef CONFIG_PROFILER
static const char *op_str[] = { int64_t dyngen_tb_count1;
#define DEF(s, n, copy_size) #s, int64_t dyngen_tb_count;
#include "opc.h" int64_t dyngen_op_count;
#undef DEF int64_t dyngen_old_op_count;
}; int64_t dyngen_tcg_del_op_count;
int dyngen_op_count_max;
static uint8_t op_nb_args[] = { int64_t dyngen_code_in_len;
#define DEF(s, n, copy_size) n, int64_t dyngen_code_out_len;
#include "opc.h" int64_t dyngen_interm_time;
#undef DEF int64_t dyngen_code_time;
}; int64_t dyngen_restore_count;
int64_t dyngen_restore_time;
static const unsigned short opc_copy_size[] = {
#define DEF(s, n, copy_size) copy_size,
#include "opc.h"
#undef DEF
};
void dump_ops(const uint16_t *opc_buf, const uint32_t *opparam_buf)
{
const uint16_t *opc_ptr;
const uint32_t *opparam_ptr;
int c, n, i;
opc_ptr = opc_buf;
opparam_ptr = opparam_buf;
for(;;) {
c = *opc_ptr++;
n = op_nb_args[c];
fprintf(logfile, "0x%04x: %s",
(int)(opc_ptr - opc_buf - 1), op_str[c]);
for(i = 0; i < n; i++) {
fprintf(logfile, " 0x%x", opparam_ptr[i]);
}
fprintf(logfile, "\n");
if (c == INDEX_op_end)
break;
opparam_ptr += n;
}
}
#endif #endif
/* compute label info */ /* XXX: suppress that */
static void dyngen_labels(long *gen_labels, int nb_gen_labels,
uint8_t *gen_code_buf, const uint16_t *opc_buf)
{
uint8_t *gen_code_ptr;
int c, i;
unsigned long gen_code_addr[OPC_BUF_SIZE];
if (nb_gen_labels == 0)
return;
/* compute the address of each op code */
gen_code_ptr = gen_code_buf;
i = 0;
for(;;) {
c = opc_buf[i];
gen_code_addr[i] =(unsigned long)gen_code_ptr;
if (c == INDEX_op_end)
break;
gen_code_ptr += opc_copy_size[c];
i++;
}
/* compute the address of each label */
for(i = 0; i < nb_gen_labels; i++) {
gen_labels[i] = gen_code_addr[gen_labels[i]];
}
}
unsigned long code_gen_max_block_size(void) unsigned long code_gen_max_block_size(void)
{ {
static unsigned long max; static unsigned long max;
if (max == 0) { if (max == 0) {
#define DEF(s, n, copy_size) max = copy_size > max? copy_size : max; #define DEF(s, n, copy_size) max = copy_size > max? copy_size : max;
#include "opc.h" #include "tcg-opc.h"
#undef DEF #undef DEF
max *= OPC_MAX_SIZE; max *= OPC_MAX_SIZE;
} }
@ -146,6 +80,13 @@ unsigned long code_gen_max_block_size(void)
return max; return max;
} }
void cpu_gen_init(void)
{
tcg_context_init(&tcg_ctx);
tcg_set_frame(&tcg_ctx, TCG_AREG0, offsetof(CPUState, temp_buf),
128 * sizeof(long));
}
/* return non zero if the very first instruction is invalid so that /* return non zero if the very first instruction is invalid so that
the virtual CPU can trigger an exception. the virtual CPU can trigger an exception.
@ -154,31 +95,53 @@ unsigned long code_gen_max_block_size(void)
*/ */
int cpu_gen_code(CPUState *env, TranslationBlock *tb, int *gen_code_size_ptr) int cpu_gen_code(CPUState *env, TranslationBlock *tb, int *gen_code_size_ptr)
{ {
TCGContext *s = &tcg_ctx;
uint8_t *gen_code_buf; uint8_t *gen_code_buf;
int gen_code_size; int gen_code_size;
#ifdef CONFIG_PROFILER
int64_t ti;
#endif
#ifdef CONFIG_PROFILER
dyngen_tb_count1++; /* includes aborted translations because of
exceptions */
ti = profile_getclock();
#endif
tcg_func_start(s);
if (gen_intermediate_code(env, tb) < 0) if (gen_intermediate_code(env, tb) < 0)
return -1; return -1;
/* generate machine code */ /* generate machine code */
gen_code_buf = tb->tc_ptr;
tb->tb_next_offset[0] = 0xffff; tb->tb_next_offset[0] = 0xffff;
tb->tb_next_offset[1] = 0xffff; tb->tb_next_offset[1] = 0xffff;
gen_code_buf = tb->tc_ptr; s->tb_next_offset = tb->tb_next_offset;
#ifdef USE_DIRECT_JUMP #ifdef USE_DIRECT_JUMP
s->tb_jmp_offset = tb->tb_jmp_offset;
s->tb_next = NULL;
/* the following two entries are optional (only used for string ops) */ /* the following two entries are optional (only used for string ops) */
/* XXX: not used ? */
tb->tb_jmp_offset[2] = 0xffff; tb->tb_jmp_offset[2] = 0xffff;
tb->tb_jmp_offset[3] = 0xffff; tb->tb_jmp_offset[3] = 0xffff;
#endif
dyngen_labels(gen_labels, nb_gen_labels, gen_code_buf, gen_opc_buf);
gen_code_size = dyngen_code(gen_code_buf, tb->tb_next_offset,
#ifdef USE_DIRECT_JUMP
tb->tb_jmp_offset,
#else #else
NULL, s->tb_jmp_offset = NULL;
s->tb_next = tb->tb_next;
#endif #endif
gen_opc_buf, gen_opparam_buf, gen_labels);
#ifdef CONFIG_PROFILER
dyngen_tb_count++;
dyngen_interm_time += profile_getclock() - ti;
dyngen_code_time -= profile_getclock();
#endif
gen_code_size = dyngen_code(s, gen_code_buf);
*gen_code_size_ptr = gen_code_size; *gen_code_size_ptr = gen_code_size;
#ifdef CONFIG_PROFILER
dyngen_code_time += profile_getclock();
dyngen_code_in_len += tb->size;
dyngen_code_out_len += gen_code_size;
#endif
#ifdef DEBUG_DISAS #ifdef DEBUG_DISAS
if (loglevel & CPU_LOG_TB_OUT_ASM) { if (loglevel & CPU_LOG_TB_OUT_ASM) {
fprintf(logfile, "OUT: [size=%d]\n", *gen_code_size_ptr); fprintf(logfile, "OUT: [size=%d]\n", *gen_code_size_ptr);
@ -196,9 +159,17 @@ int cpu_restore_state(TranslationBlock *tb,
CPUState *env, unsigned long searched_pc, CPUState *env, unsigned long searched_pc,
void *puc) void *puc)
{ {
int j, c; TCGContext *s = &tcg_ctx;
int j;
unsigned long tc_ptr; unsigned long tc_ptr;
uint16_t *opc_ptr; #ifdef CONFIG_PROFILER
int64_t ti;
#endif
#ifdef CONFIG_PROFILER
ti = profile_getclock();
#endif
tcg_func_start(s);
if (gen_intermediate_code_pc(env, tb) < 0) if (gen_intermediate_code_pc(env, tb) < 0)
return -1; return -1;
@ -207,18 +178,19 @@ int cpu_restore_state(TranslationBlock *tb,
tc_ptr = (unsigned long)tb->tc_ptr; tc_ptr = (unsigned long)tb->tc_ptr;
if (searched_pc < tc_ptr) if (searched_pc < tc_ptr)
return -1; return -1;
j = 0;
opc_ptr = gen_opc_buf; s->tb_next_offset = tb->tb_next_offset;
for(;;) { #ifdef USE_DIRECT_JUMP
c = *opc_ptr; s->tb_jmp_offset = tb->tb_jmp_offset;
if (c == INDEX_op_end) s->tb_next = NULL;
return -1; #else
tc_ptr += opc_copy_size[c]; s->tb_jmp_offset = NULL;
if (searched_pc < tc_ptr) s->tb_next = tb->tb_next;
break; #endif
opc_ptr++; j = dyngen_code_search_pc(s, (uint8_t *)tc_ptr,
} (void *)searched_pc);
j = opc_ptr - gen_opc_buf; if (j < 0)
return -1;
/* now find start of instruction before */ /* now find start of instruction before */
while (gen_opc_instr_start[j] == 0) while (gen_opc_instr_start[j] == 0)
j--; j--;
@ -266,10 +238,11 @@ int cpu_restore_state(TranslationBlock *tb,
} }
#elif defined(TARGET_PPC) #elif defined(TARGET_PPC)
{ {
int type; int type, c;
/* for PPC, we need to look at the micro operation to get the /* for PPC, we need to look at the micro operation to get the
access type */ access type */
env->nip = gen_opc_pc[j]; env->nip = gen_opc_pc[j];
c = gen_opc_buf[j];
switch(c) { switch(c) {
#if defined(CONFIG_USER_ONLY) #if defined(CONFIG_USER_ONLY)
#define CASE3(op)\ #define CASE3(op)\
@ -315,5 +288,10 @@ int cpu_restore_state(TranslationBlock *tb,
env->pc = gen_opc_pc[j]; env->pc = gen_opc_pc[j];
env->flags = gen_opc_hflags[j]; env->flags = gen_opc_hflags[j];
#endif #endif
#ifdef CONFIG_PROFILER
dyngen_restore_time += profile_getclock() - ti;
dyngen_restore_count++;
#endif
return 0; return 0;
} }

View File

@ -1,41 +0,0 @@
/*
* Host code generation
*
* Copyright (c) 2003 Fabrice Bellard
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#include "config.h"
#include "osdep.h"
enum {
#define DEF(s, n, copy_size) INDEX_op_ ## s,
#include "opc.h"
#undef DEF
NB_OPS,
};
#include "dyngen.h"
extern int dyngen_code(uint8_t *gen_code_buf,
uint16_t *label_offsets, uint16_t *jmp_offsets,
const uint16_t *opc_buf, const uint32_t *opparam_buf, const long *gen_labels);
#include "op.h"