diff options
35 files changed, 1087 insertions, 2353 deletions
@@ -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 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.
\ No newline at end of file diff --git a/Makefile.target b/Makefile.target index 8a94ad806d..fca219201c 100644 --- a/Makefile.target +++ b/Makefile.target @@ -172,8 +172,11 @@ all: $(PROGS) ######################################################### # 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 +# 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 LIBOBJS+=fpu/softfloat.o else @@ -268,16 +271,16 @@ libqemu.a: $(LIBOBJS) rm -f $@ $(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) $(DYNGEN) -o $@ $< -opc.h: op.o $(DYNGEN) +dyngen-opc.h: op.o $(DYNGEN) $(DYNGEN) -c -o $@ $< gen-op.h: op.o $(DYNGEN) @@ -648,8 +651,8 @@ endif # !CONFIG_USER_ONLY $(CC) $(CPPFLAGS) -c -o $@ $< clean: - rm -f *.o *.a *~ $(PROGS) gen-op.h opc.h op.h nwfpe/*.o fpu/*.o - rm -f *.d */*.d + rm -f *.o *.a *~ $(PROGS) gen-op.h dyngen-opc.h op.h nwfpe/*.o fpu/*.o + rm -f *.d */*.d tcg/*.o install: all ifneq ($(PROGS),) @@ -1051,6 +1051,7 @@ test -f $config_h && mv $config_h ${config_h}~ mkdir -p $target_dir mkdir -p $target_dir/fpu +mkdir -p $target_dir/tcg if test "$target" = "arm-linux-user" -o "$target" = "armeb-linux-user" ; then mkdir -p $target_dir/nwfpe fi @@ -1048,6 +1048,18 @@ extern int64_t kqemu_ret_int_count; extern int64_t kqemu_ret_excp_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 /* CPU_ALL_H */ diff --git a/cpu-defs.h b/cpu-defs.h index b581d949f2..6979c1145f 100644 --- a/cpu-defs.h +++ b/cpu-defs.h @@ -145,6 +145,7 @@ typedef struct CPUTLBEntry { /* The meaning of the MMU modes is defined in the target code. */ \ CPUTLBEntry tlb_table[NB_MMU_MODES][CPU_TLB_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 */ \ /* ice debug support */ \ diff --git a/cpu-exec.c b/cpu-exec.c index af5c58f8a7..003d6e2545 100644 --- a/cpu-exec.c +++ b/cpu-exec.c @@ -354,7 +354,7 @@ int cpu_exec(CPUState *env1) #endif #endif int ret, interrupt_request; - void (*gen_func)(void); + long (*gen_func)(void); TranslationBlock *tb; uint8_t *tc_ptr; @@ -736,7 +736,7 @@ int cpu_exec(CPUState *env1) fp.gp = code_gen_buffer + 2 * (1 << 20); (*(void (*)(void)) &fp)(); #else - gen_func(); + T0 = gen_func(); #endif env->current_tb = NULL; /* reset soft MMU for next block (it can currently diff --git a/dyngen-op.h b/dyngen-op.h deleted file mode 100644 index f77a4756f7..0000000000 --- a/dyngen-op.h +++ /dev/null @@ -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; -} @@ -1212,14 +1212,16 @@ int load_object(const char *filename) #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; if (strstart(sym_name, "__op_param", &p)) { snprintf(name, name_size, "param%s", 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 { #ifdef HOST_SPARC if (sym_name[0] == '.') @@ -1230,6 +1232,7 @@ void get_reloc_expr(char *name, int name_size, const char *sym_name) #endif snprintf(name, name_size, "(long)(&%s)", sym_name); } + return 0; } #ifdef HOST_IA64 @@ -1846,7 +1849,7 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, #if defined(HOST_I386) { char relname[256]; - int type; + int type, is_label; int addend; int reloc_offset; 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; } - 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)); #ifdef CONFIG_FORMAT_ELF type = ELF32_R_TYPE(rel->r_info); - 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); + if (is_label) { + switch(type) { + case R_386_32: + case R_386_PC32: + fprintf(outfile, " tcg_out_reloc(s, gen_code_ptr + %d, %d, %s, %d);\n", + reloc_offset, type, relname, addend); + break; + 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) { @@ -1920,32 +1935,45 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, #elif defined(HOST_X86_64) { char relname[256]; - int type; + int type, is_label; int addend; int reloc_offset; for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { if (rel->r_offset >= start_offset && rel->r_offset < start_offset + copy_size) { 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); addend = rel->r_addend; reloc_offset = rel->r_offset - start_offset; - switch(type) { - case R_X86_64_32: - 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); + if (is_label) { + switch(type) { + case R_X86_64_32: + case R_X86_64_32S: + case R_X86_64_PC32: + fprintf(outfile, " tcg_out_reloc(s, gen_code_ptr + %d, %d, %s, %d);\n", + reloc_offset, type, relname, addend); + break; + default: + error("unsupported X86_64 relocation (%d)", type); + } + } else { + switch(type) { + case R_X86_64_32: + 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; 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++) { const char *name; name = get_sym_name(sym); @@ -2653,7 +2676,6 @@ int gen_file(FILE *outfile, int out_type) } } else if (out_type == OUT_GEN_OP) { /* generate gen_xxx functions */ - fprintf(outfile, "#include \"dyngen-op.h\"\n"); for(i = 0, sym = symtab; i < nb_syms; i++, sym++) { const char *name; name = get_sym_name(sym); @@ -2670,6 +2692,7 @@ int gen_file(FILE *outfile, int out_type) /* generate big code generation switch */ #ifdef HOST_ARM +#error broken /* 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. */ fprintf(outfile, @@ -2690,16 +2713,8 @@ fprintf(outfile, "};\n"); #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 +#error broken /* 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. 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"); #endif #ifdef HOST_IA64 +#error broken { long addend, not_first = 0; unsigned long sym_idx; @@ -2789,18 +2805,8 @@ fprintf(outfile, } #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 +#error broken /* Generate constant pool if needed */ fprintf(outfile, " if (gen_code_ptr + arm_opc_size[*opc_ptr] >= arm_pool_ptr) {\n" @@ -2813,9 +2819,6 @@ fprintf(outfile, " }\n"); #endif -fprintf(outfile, -" switch(*opc_ptr++) {\n"); - for(i = 0, sym = symtab; i < nb_syms; i++, sym++) { const char *name; name = get_sym_name(sym); @@ -2831,51 +2834,6 @@ fprintf(outfile, 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; diff --git a/dyngen.h b/dyngen.h deleted file mode 100644 index 4451d54358..0000000000 --- a/dyngen.h +++ /dev/null @@ -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 diff --git a/exec-all.h b/exec-all.h index e7c4806010..cf723994eb 100644 --- a/exec-all.h +++ b/exec-all.h @@ -36,10 +36,6 @@ struct TranslationBlock; #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_npc[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_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); +void cpu_gen_init(void); int cpu_gen_code(CPUState *env, struct TranslationBlock *tb, int *gen_code_size_ptr); 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__) #define CODE_GEN_BUFFER_SIZE (6 * 1024 * 1024) #else +/* XXX: make it dynamic on x86 */ #define CODE_GEN_BUFFER_SIZE (16 * 1024 * 1024) #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) -#if defined(__powerpc__) +#if defined(__powerpc__) || defined(__x86_64__) #define USE_DIRECT_JUMP #endif #if defined(__i386__) && !defined(_WIN32) @@ -169,7 +166,7 @@ typedef struct TranslationBlock { #ifdef USE_DIRECT_JUMP uint16_t tb_jmp_offset[4]; /* offset of jump instruction */ #else - uint32_t tb_next[2]; /* address of jump generated code */ + unsigned long tb_next[2]; /* address of jump generated code */ #endif /* 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 @@ -228,7 +225,7 @@ static inline void tb_set_jmp_target1(unsigned long jmp_addr, unsigned long addr asm volatile ("sync" : : : "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) { /* patch the branch destination */ @@ -294,48 +291,6 @@ TranslationBlock *tb_find_pc(unsigned long pc_ptr); #define ASM_OP_LABEL_NAME(n, 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 CPUReadMemoryFunc *io_mem_read[IO_MEM_NB_ENTRIES][4]; extern void *io_mem_opaque[IO_MEM_NB_ENTRIES]; @@ -312,6 +312,7 @@ void cpu_exec_init(CPUState *env) int cpu_index; if (!code_gen_ptr) { + cpu_gen_init(); code_gen_ptr = code_gen_buffer; page_init(); io_mem_init(); @@ -1238,10 +1239,10 @@ CPULogItem cpu_log_items[] = { { CPU_LOG_TB_IN_ASM, "in_asm", "show target assembly code for each compiled TB" }, { 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 { CPU_LOG_TB_OP_OPT, "op_opt", - "show micro ops after optimization for each compiled TB" }, + "show micro ops before eflags optimization" }, #endif { CPU_LOG_INT, "int", "show interrupts/exceptions in short format" }, @@ -2935,6 +2936,7 @@ void dump_exec_info(FILE *f, } } /* XXX: avoid using doubles ? */ + cpu_fprintf(f, "Translation buffer state:\n"); cpu_fprintf(f, "TB count %d\n", nb_tbs); cpu_fprintf(f, "TB avg target size %d max=%d bytes\n", 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, direct_jmp2_count, 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 invalidate count %d\n", tb_phys_invalidate_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) diff --git a/target-alpha/op.c b/target-alpha/op.c index da93e7cdfb..957c651605 100644 --- a/target-alpha/op.c +++ b/target-alpha/op.c @@ -216,11 +216,6 @@ void OPPROTO op_clear_irf (void) RETURN(); } -void OPPROTO op_exit_tb (void) -{ - EXIT_TB(); -} - /* Arithmetic */ void OPPROTO op_addq (void) { diff --git a/target-alpha/translate.c b/target-alpha/translate.c index 01e6ded123..1c8587db99 100644 --- a/target-alpha/translate.c +++ b/target-alpha/translate.c @@ -25,6 +25,7 @@ #include "cpu.h" #include "exec-all.h" #include "disas.h" +#include "tcg-op.h" #define DO_SINGLE_STEP #define GENERATE_NOP @@ -41,24 +42,6 @@ struct DisasContext { 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) { #if defined(GENERATE_NOP) @@ -1988,10 +1971,7 @@ static always_inline int gen_intermediate_code_internal (CPUState *env, int ret; pc_start = tb->pc; - gen_opc_ptr = gen_opc_buf; gen_opc_end = gen_opc_buf + OPC_MAX_SIZE; - gen_opparam_ptr = gen_opparam_buf; - nb_gen_labels = 0; ctx.pc = pc_start; ctx.amask = env->amask; #if defined (CONFIG_USER_ONLY) @@ -2051,12 +2031,11 @@ static always_inline int gen_intermediate_code_internal (CPUState *env, if (ret != 1 && ret != 3) { gen_update_pc(&ctx); } - gen_op_reset_T0(); #if defined (DO_TB_FLUSH) gen_op_tb_flush(); #endif /* Generate the return instruction */ - gen_op_exit_tb(); + tcg_gen_exit_tb(0); *gen_opc_ptr = INDEX_op_end; if (search_pc) { 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); 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 return 0; diff --git a/target-arm/op.c b/target-arm/op.c index 216944af59..c2d33ca328 100644 --- a/target-arm/op.c +++ b/target-arm/op.c @@ -364,21 +364,6 @@ void OPPROTO op_testn_T0(void) 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) { /* Execution state bits always read as zero. */ diff --git a/target-arm/translate.c b/target-arm/translate.c index 513b179872..6de78f8caa 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -28,6 +28,7 @@ #include "cpu.h" #include "exec-all.h" #include "disas.h" +#include "tcg-op.h" #define ENABLE_ARCH_5J 0 #define ENABLE_ARCH_6 arm_feature(env, ARM_FEATURE_V6) @@ -68,27 +69,10 @@ typedef struct DisasContext { #define DISAS_WFI 4 #define DISAS_SWI 5 -#ifdef USE_DIRECT_JUMP -#define TBPARAM(x) -#else -#define TBPARAM(x) (long)(x) -#endif - /* XXX: move that elsewhere */ -static uint16_t *gen_opc_ptr; -static uint32_t *gen_opparam_ptr; extern FILE *logfile; 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) { \ gen_op_ ## pfx ## add16_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; if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) { - if (n == 0) - gen_op_goto_tb0(TBPARAM(tb)); - else - gen_op_goto_tb1(TBPARAM(tb)); + tcg_gen_goto_tb(n); gen_op_movl_T0_im(dest); gen_op_movl_r15_T0(); - gen_op_movl_T0_im((long)tb + n); - gen_op_exit_tb(); + tcg_gen_exit_tb((long)tb + n); } else { gen_op_movl_T0_im(dest); gen_op_movl_r15_T0(); - gen_op_movl_T0_0(); - gen_op_exit_tb(); + tcg_gen_exit_tb(0); } } @@ -7486,9 +7465,7 @@ static inline int gen_intermediate_code_internal(CPUState *env, dc->tb = tb; - gen_opc_ptr = gen_opc_buf; gen_opc_end = gen_opc_buf + OPC_MAX_SIZE; - gen_opparam_ptr = gen_opparam_buf; dc->is_jmp = DISAS_NEXT; dc->pc = pc_start; @@ -7506,7 +7483,6 @@ static inline int gen_intermediate_code_internal(CPUState *env, } #endif next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE; - nb_gen_labels = 0; lj = -1; /* Reset the conditional execution bits immediately. This avoids 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_UPDATE: /* indicate that the hash table must be used to find the next TB */ - gen_op_movl_T0_0(); - gen_op_exit_tb(); + tcg_gen_exit_tb(0); break; case DISAS_TB_JUMP: /* nothing more to generate */ @@ -7654,11 +7629,6 @@ done_generating: fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start)); target_disas(logfile, pc_start, dc->pc - pc_start, env->thumb); 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 if (search_pc) { diff --git a/target-cris/op.c b/target-cris/op.c index 3c50574e76..c7243b15a0 100644 --- a/target-cris/op.c +++ b/target-cris/op.c @@ -151,23 +151,6 @@ /* 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) { env->trapnr = PARAM1; @@ -1268,7 +1251,7 @@ void OPPROTO op_movl_btarget_T0 (void) RETURN(); } -void OPPROTO op_jmp (void) +void OPPROTO op_jmp1 (void) { env->pc = env->btarget; RETURN(); diff --git a/target-cris/translate.c b/target-cris/translate.c index a05d139ee2..3a5e5eb1ba 100644 --- a/target-cris/translate.c +++ b/target-cris/translate.c @@ -51,6 +51,7 @@ #include "cpu.h" #include "exec-all.h" #include "disas.h" +#include "tcg-op.h" #include "crisv32-decode.h" #define CRIS_STATS 0 @@ -67,12 +68,6 @@ #define DIS(x) #endif -#ifdef USE_DIRECT_JUMP -#define TBPARAM(x) -#else -#define TBPARAM(x) (long)(x) -#endif - #define BUG() (gen_BUG(dc, __FILE__, __LINE__)) #define BUG_ON(x) ({if (x) BUG();}) @@ -85,17 +80,6 @@ #define CC_MASK_NZVC 0xf #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. */ typedef struct DisasContext { CPUState *env; @@ -264,15 +248,14 @@ static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest) TranslationBlock *tb; tb = dc->tb; if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) { - if (n == 0) - gen_op_goto_tb0(TBPARAM(tb)); - else - gen_op_goto_tb1(TBPARAM(tb)); - gen_op_movl_T0_0(); +#if 0 + /* XXX: this code is not finished */ + tcg_gen_goto_tb(n); +#endif + tcg_gen_exit_tb(0); } else { - gen_op_movl_T0_0(); + tcg_gen_exit_tb(0); } - gen_op_exit_tb(); } /* Sign extend at translation time. */ @@ -2325,9 +2308,7 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb, dc->env = env; dc->tb = tb; - gen_opc_ptr = gen_opc_buf; gen_opc_end = gen_opc_buf + OPC_MAX_SIZE; - gen_opparam_ptr = gen_opparam_buf; dc->is_jmp = DISAS_NEXT; dc->pc = pc_start; @@ -2374,7 +2355,7 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb, if (dc->delayed_branch == 0) { if (dc->bcc == CC_A) { - gen_op_jmp (); + gen_op_jmp1 (); dc->is_jmp = DISAS_UPDATE; } else { @@ -2409,9 +2390,7 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb, case DISAS_UPDATE: /* indicate that the hash table must be used to find the next TB */ - /* T0 is used to index the jmp tables. */ - gen_op_movl_T0_0(); - gen_op_exit_tb(); + tcg_gen_exit_tb(0); break; case DISAS_TB_JUMP: /* 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)); target_disas(logfile, pc_start, dc->pc + 4 - pc_start, 0); 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 return 0; diff --git a/target-i386/exec.h b/target-i386/exec.h index 20153f7279..37fcdc01b7 100644 --- a/target-i386/exec.h +++ b/target-i386/exec.h @@ -181,8 +181,9 @@ void __hidden cpu_loop_exit(void); void OPPROTO op_movl_eflags_T0(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_imulq_EAX_T0(void); void helper_imulq_T0_T1(void); diff --git a/target-i386/helper.c b/target-i386/helper.c index 3c7424f887..f5268093fb 100644 --- a/target-i386/helper.c +++ b/target-i386/helper.c @@ -1608,13 +1608,13 @@ int32_t idiv32(int64_t *q_ptr, int64_t num, int32_t den) } #endif -void helper_divl_EAX_T0(void) +void helper_divl_EAX_T0(target_ulong t0) { unsigned int den, r; uint64_t num, q; num = ((uint32_t)EAX) | ((uint64_t)((uint32_t)EDX) << 32); - den = T0; + den = t0; if (den == 0) { raise_exception(EXCP00_DIVZ); } @@ -1630,13 +1630,13 @@ void helper_divl_EAX_T0(void) EDX = (uint32_t)r; } -void helper_idivl_EAX_T0(void) +void helper_idivl_EAX_T0(target_ulong t0) { int den, r; int64_t num, q; num = ((uint32_t)EAX) | ((uint64_t)((uint32_t)EDX) << 32); - den = T0; + den = t0; if (den == 0) { raise_exception(EXCP00_DIVZ); } diff --git a/target-i386/helper.h b/target-i386/helper.h new file mode 100644 index 0000000000..1b247dbf5b --- /dev/null +++ b/target-i386/helper.h @@ -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); diff --git a/target-i386/op.c b/target-i386/op.c index 77930db125..eb292fe38f 100644 --- a/target-i386/op.c +++ b/target-i386/op.c @@ -172,31 +172,6 @@ void OPPROTO op_testl_T0_T1_cc(void) /* 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) { T0 = -T0; @@ -217,18 +192,6 @@ void OPPROTO op_notl_T0(void) 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 */ /* XXX: add eflags optimizations */ @@ -399,16 +362,6 @@ void OPPROTO op_idivw_AX_T0(void) 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 void OPPROTO op_divq_EAX_T0(void) { @@ -424,46 +377,6 @@ void OPPROTO op_idivq_EAX_T0(void) /* constant load & misc op */ /* 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) { T1 += PARAM1; @@ -474,26 +387,6 @@ void OPPROTO op_movl_T1_A0(void) 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) { A0 = (uint32_t)(A0 + (EAX & 0xff)); @@ -523,46 +416,6 @@ typedef union UREG64 { #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) { A0 = (A0 + (EAX & 0xff)); @@ -570,11 +423,6 @@ void OPPROTO op_addq_A0_AL(void) #endif -void OPPROTO op_andl_A0_ffff(void) -{ - A0 = A0 & 0xffff; -} - /* memory access */ #define MEMSUFFIX _raw @@ -588,30 +436,6 @@ void OPPROTO op_andl_A0_ffff(void) #include "ops_mem.h" #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) { helper_hlt(); @@ -735,16 +559,6 @@ void OPPROTO op_single_step(void) helper_single_step(); } -void OPPROTO op_movl_T0_0(void) -{ - T0 = 0; -} - -void OPPROTO op_exit_tb(void) -{ - EXIT_TB(); -} - /* multiple size ops */ #define ldul ldl @@ -879,75 +693,6 @@ void OPPROTO op_decq_ECX(void) } #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) { helper_rdtsc(); @@ -1362,16 +1107,6 @@ void OPPROTO op_clts(void) /* 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) { GOTO_LABEL_PARAM(1); @@ -1451,11 +1186,6 @@ void OPPROTO op_xor_T0_1(void) T0 ^= 1; } -void OPPROTO op_set_cc_op(void) -{ - CC_OP = PARAM1; -} - void OPPROTO op_mov_T0_cc(void) { T0 = cc_table[CC_OP].compute_all(); diff --git a/target-i386/opreg_template.h b/target-i386/opreg_template.h index eae4139d10..67bee8804a 100644 --- a/target-i386/opreg_template.h +++ b/target-i386/opreg_template.h @@ -18,110 +18,6 @@ * License along with this library; if not, write to the Free Software * 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 */ 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) { +#ifdef TARGET_X86_64 if (T0) REG = (uint32_t)T1; + else + REG = (uint32_t)REG; +#else + if (T0) + REG = (uint32_t)T1; +#endif FORCE_RET(); } @@ -145,46 +48,3 @@ void OPPROTO glue(glue(op_cmovq,REGNAME),_T1_T0)(void) FORCE_RET(); } #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); -} - diff --git a/target-i386/translate.c b/target-i386/translate.c index 9723e76092..aa397f6d06 100644 --- a/target-i386/translate.c +++ b/target-i386/translate.c @@ -28,10 +28,8 @@ #include "cpu.h" #include "exec-all.h" #include "disas.h" - -/* XXX: move that elsewhere */ -static uint16_t *gen_opc_ptr; -static uint32_t *gen_opparam_ptr; +#include "helper.h" +#include "tcg-op.h" #define PREFIX_REPZ 0x01 #define PREFIX_REPNZ 0x02 @@ -57,14 +55,79 @@ static uint32_t *gen_opparam_ptr; #define REX_B(s) 0 #endif +//#define MACRO_TEST 1 + #ifdef TARGET_X86_64 -static int x86_64_hregs; +#define TCG_TYPE_TL TCG_TYPE_I64 +#define tcg_gen_movi_tl tcg_gen_movi_i64 +#define tcg_gen_mov_tl tcg_gen_mov_i64 +#define tcg_gen_ld8u_tl tcg_gen_ld8u_i64 +#define tcg_gen_ld8s_tl tcg_gen_ld8s_i64 +#define tcg_gen_ld16u_tl tcg_gen_ld16u_i64 +#define tcg_gen_ld16s_tl tcg_gen_ld16s_i64 +#define tcg_gen_ld32u_tl tcg_gen_ld32u_i64 +#define tcg_gen_ld32s_tl tcg_gen_ld32s_i64 +#define tcg_gen_ld_tl tcg_gen_ld_i64 +#define tcg_gen_st8_tl tcg_gen_st8_i64 +#define tcg_gen_st16_tl tcg_gen_st16_i64 +#define tcg_gen_st32_tl tcg_gen_st32_i64 +#define tcg_gen_st_tl tcg_gen_st_i64 +#define tcg_gen_add_tl tcg_gen_add_i64 +#define tcg_gen_addi_tl tcg_gen_addi_i64 +#define tcg_gen_sub_tl tcg_gen_sub_i64 +#define tcg_gen_subi_tl tcg_gen_subi_i64 +#define tcg_gen_and_tl tcg_gen_and_i64 +#define tcg_gen_andi_tl tcg_gen_andi_i64 +#define tcg_gen_or_tl tcg_gen_or_i64 +#define tcg_gen_ori_tl tcg_gen_ori_i64 +#define tcg_gen_xor_tl tcg_gen_xor_i64 +#define tcg_gen_xori_tl tcg_gen_xori_i64 +#define tcg_gen_shl_tl tcg_gen_shl_i64 +#define tcg_gen_shli_tl tcg_gen_shli_i64 +#define tcg_gen_shr_tl tcg_gen_shr_i64 +#define tcg_gen_shri_tl tcg_gen_shri_i64 +#define tcg_gen_sar_tl tcg_gen_sar_i64 +#define tcg_gen_sari_tl tcg_gen_sari_i64 +#else +#define TCG_TYPE_TL TCG_TYPE_I32 +#define tcg_gen_movi_tl tcg_gen_movi_i32 +#define tcg_gen_mov_tl tcg_gen_mov_i32 +#define tcg_gen_ld8u_tl tcg_gen_ld8u_i32 +#define tcg_gen_ld8s_tl tcg_gen_ld8s_i32 +#define tcg_gen_ld16u_tl tcg_gen_ld16u_i32 +#define tcg_gen_ld16s_tl tcg_gen_ld16s_i32 +#define tcg_gen_ld32u_tl tcg_gen_ld_i32 +#define tcg_gen_ld32s_tl tcg_gen_ld_i32 +#define tcg_gen_ld_tl tcg_gen_ld_i32 +#define tcg_gen_st8_tl tcg_gen_st8_i32 +#define tcg_gen_st16_tl tcg_gen_st16_i32 +#define tcg_gen_st32_tl tcg_gen_st_i32 +#define tcg_gen_st_tl tcg_gen_st_i32 +#define tcg_gen_add_tl tcg_gen_add_i32 +#define tcg_gen_addi_tl tcg_gen_addi_i32 +#define tcg_gen_sub_tl tcg_gen_sub_i32 +#define tcg_gen_subi_tl tcg_gen_subi_i32 +#define tcg_gen_and_tl tcg_gen_and_i32 +#define tcg_gen_andi_tl tcg_gen_andi_i32 +#define tcg_gen_or_tl tcg_gen_or_i32 +#define tcg_gen_ori_tl tcg_gen_ori_i32 +#define tcg_gen_xor_tl tcg_gen_xor_i32 +#define tcg_gen_xori_tl tcg_gen_xori_i32 +#define tcg_gen_shl_tl tcg_gen_shl_i32 +#define tcg_gen_shli_tl tcg_gen_shli_i32 +#define tcg_gen_shr_tl tcg_gen_shr_i32 +#define tcg_gen_shri_tl tcg_gen_shri_i32 +#define tcg_gen_sar_tl tcg_gen_sar_i32 +#define tcg_gen_sari_tl tcg_gen_sari_i32 #endif -#ifdef USE_DIRECT_JUMP -#define TBPARAM(x) -#else -#define TBPARAM(x) (long)(x) +/* global register indexes */ +static int cpu_env, cpu_T[2], cpu_A0; +/* local register indexes (only used inside old micro ops) */ +static int cpu_tmp0; + +#ifdef TARGET_X86_64 +static int x86_64_hregs; #endif typedef struct DisasContext { @@ -131,15 +194,6 @@ enum { OP_SAR = 7, }; -enum { -#define DEF(s, n, copy_size) INDEX_op_ ## s, -#include "opc.h" -#undef DEF - NB_OPS, -}; - -#include "gen-op.h" - /* operand size */ enum { OT_BYTE = 0, @@ -164,6 +218,73 @@ enum { OR_A0, /* temporary register used when doing address evaluation */ }; +static inline void gen_op_movl_T0_0(void) +{ + tcg_gen_movi_tl(cpu_T[0], 0); +} + +static inline void gen_op_movl_T0_im(int32_t val) +{ + tcg_gen_movi_tl(cpu_T[0], val); +} + +static inline void gen_op_movl_T0_imu(uint32_t val) +{ + tcg_gen_movi_tl(cpu_T[0], val); +} + +static inline void gen_op_movl_T1_im(int32_t val) +{ + tcg_gen_movi_tl(cpu_T[1], val); +} + +static inline void gen_op_movl_T1_imu(uint32_t val) +{ + tcg_gen_movi_tl(cpu_T[1], val); +} + +static inline void gen_op_movl_A0_im(uint32_t val) +{ + tcg_gen_movi_tl(cpu_A0, val); +} + +#ifdef TARGET_X86_64 +static inline void gen_op_movq_A0_im(int64_t val) +{ + tcg_gen_movi_tl(cpu_A0, val); +} +#endif + +static inline void gen_movtl_T0_im(target_ulong val) +{ + tcg_gen_movi_tl(cpu_T[0], val); +} + +static inline void gen_movtl_T1_im(target_ulong val) +{ + tcg_gen_movi_tl(cpu_T[1], val); +} + +static inline void gen_op_andl_T0_ffff(void) +{ + tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0xffff); +} + +static inline void gen_op_andl_T0_im(uint32_t val) +{ + tcg_gen_andi_tl(cpu_T[0], cpu_T[0], val); +} + +static inline void gen_op_movl_T0_T1(void) +{ + tcg_gen_mov_tl(cpu_T[0], cpu_T[1]); +} + +static inline void gen_op_andl_A0_ffff(void) +{ + tcg_gen_andi_tl(cpu_A0, cpu_A0, 0xffff); +} + #ifdef TARGET_X86_64 #define NB_OP_SIZES 4 @@ -186,45 +307,6 @@ enum { prefix ## R14 ## suffix,\ prefix ## R15 ## suffix, -#define DEF_BREGS(prefixb, prefixh, suffix) \ - \ -static void prefixb ## ESP ## suffix ## _wrapper(void) \ -{ \ - if (x86_64_hregs) \ - prefixb ## ESP ## suffix (); \ - else \ - prefixh ## EAX ## suffix (); \ -} \ - \ -static void prefixb ## EBP ## suffix ## _wrapper(void) \ -{ \ - if (x86_64_hregs) \ - prefixb ## EBP ## suffix (); \ - else \ - prefixh ## ECX ## suffix (); \ -} \ - \ -static void prefixb ## ESI ## suffix ## _wrapper(void) \ -{ \ - if (x86_64_hregs) \ - prefixb ## ESI ## suffix (); \ - else \ - prefixh ## EDX ## suffix (); \ -} \ - \ -static void prefixb ## EDI ## suffix ## _wrapper(void) \ -{ \ - if (x86_64_hregs) \ - prefixb ## EDI ## suffix (); \ - else \ - prefixh ## EBX ## suffix (); \ -} - -DEF_BREGS(gen_op_movb_, gen_op_movh_, _T0) -DEF_BREGS(gen_op_movb_, gen_op_movh_, _T1) -DEF_BREGS(gen_op_movl_T0_, gen_op_movh_T0_, ) -DEF_BREGS(gen_op_movl_T1_, gen_op_movh_T1_, ) - #else /* !TARGET_X86_64 */ #define NB_OP_SIZES 3 @@ -241,218 +323,227 @@ DEF_BREGS(gen_op_movl_T1_, gen_op_movh_T1_, ) #endif /* !TARGET_X86_64 */ -static GenOpFunc *gen_op_mov_reg_T0[NB_OP_SIZES][CPU_NB_REGS] = { - [OT_BYTE] = { - gen_op_movb_EAX_T0, - gen_op_movb_ECX_T0, - gen_op_movb_EDX_T0, - gen_op_movb_EBX_T0, -#ifdef TARGET_X86_64 - gen_op_movb_ESP_T0_wrapper, - gen_op_movb_EBP_T0_wrapper, - gen_op_movb_ESI_T0_wrapper, - gen_op_movb_EDI_T0_wrapper, - gen_op_movb_R8_T0, - gen_op_movb_R9_T0, - gen_op_movb_R10_T0, - gen_op_movb_R11_T0, - gen_op_movb_R12_T0, - gen_op_movb_R13_T0, - gen_op_movb_R14_T0, - gen_op_movb_R15_T0, +#if defined(WORDS_BIGENDIAN) +#define REG_B_OFFSET (sizeof(target_ulong) - 1) +#define REG_H_OFFSET (sizeof(target_ulong) - 2) +#define REG_W_OFFSET (sizeof(target_ulong) - 2) +#define REG_L_OFFSET (sizeof(target_ulong) - 4) +#define REG_LH_OFFSET (sizeof(target_ulong) - 8) #else - gen_op_movh_EAX_T0, - gen_op_movh_ECX_T0, - gen_op_movh_EDX_T0, - gen_op_movh_EBX_T0, +#define REG_B_OFFSET 0 +#define REG_H_OFFSET 1 +#define REG_W_OFFSET 0 +#define REG_L_OFFSET 0 +#define REG_LH_OFFSET 4 #endif - }, - [OT_WORD] = { - DEF_REGS(gen_op_movw_, _T0) - }, - [OT_LONG] = { - DEF_REGS(gen_op_movl_, _T0) - }, + +static inline void gen_op_mov_reg_TN(int ot, int t_index, int reg) +{ + switch(ot) { + case OT_BYTE: + if (reg < 4 X86_64_DEF( || reg >= 8 || x86_64_hregs)) { + tcg_gen_st8_tl(cpu_T[t_index], cpu_env, offsetof(CPUState, regs[reg]) + REG_B_OFFSET); + } else { + tcg_gen_st8_tl(cpu_T[t_index], cpu_env, offsetof(CPUState, regs[reg - 4]) + REG_H_OFFSET); + } + break; + case OT_WORD: + tcg_gen_st16_tl(cpu_T[t_index], cpu_env, offsetof(CPUState, regs[reg]) + REG_W_OFFSET); + break; #ifdef TARGET_X86_64 - [OT_QUAD] = { - DEF_REGS(gen_op_movq_, _T0) - }, + case OT_LONG: + tcg_gen_st32_tl(cpu_T[t_index], cpu_env, offsetof(CPUState, regs[reg]) + REG_L_OFFSET); + /* high part of register set to zero */ + tcg_gen_movi_tl(cpu_tmp0, 0); + tcg_gen_st32_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg]) + REG_LH_OFFSET); + break; + default: + case OT_QUAD: + tcg_gen_st_tl(cpu_T[t_index], cpu_env, offsetof(CPUState, regs[reg])); + break; +#else + default: + case OT_LONG: + tcg_gen_st32_tl(cpu_T[t_index], cpu_env, offsetof(CPUState, regs[reg]) + REG_L_OFFSET); + break; #endif -}; + } +} -static GenOpFunc *gen_op_mov_reg_T1[NB_OP_SIZES][CPU_NB_REGS] = { - [OT_BYTE] = { - gen_op_movb_EAX_T1, - gen_op_movb_ECX_T1, - gen_op_movb_EDX_T1, - gen_op_movb_EBX_T1, +static inline void gen_op_mov_reg_T0(int ot, int reg) +{ + gen_op_mov_reg_TN(ot, 0, reg); +} + +static inline void gen_op_mov_reg_T1(int ot, int reg) +{ + gen_op_mov_reg_TN(ot, 1, reg); +} + +static inline void gen_op_mov_reg_A0(int size, int reg) +{ + switch(size) { + case 0: + tcg_gen_st16_tl(cpu_A0, cpu_env, offsetof(CPUState, regs[reg]) + REG_W_OFFSET); + break; #ifdef TARGET_X86_64 - gen_op_movb_ESP_T1_wrapper, - gen_op_movb_EBP_T1_wrapper, - gen_op_movb_ESI_T1_wrapper, - gen_op_movb_EDI_T1_wrapper, - gen_op_movb_R8_T1, - gen_op_movb_R9_T1, - gen_op_movb_R10_T1, - gen_op_movb_R11_T1, - gen_op_movb_R12_T1, - gen_op_movb_R13_T1, - gen_op_movb_R14_T1, - gen_op_movb_R15_T1, + case 1: + tcg_gen_st32_tl(cpu_A0, cpu_env, offsetof(CPUState, regs[reg]) + REG_L_OFFSET); + /* high part of register set to zero */ + tcg_gen_movi_tl(cpu_tmp0, 0); + tcg_gen_st32_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg]) + REG_LH_OFFSET); + break; + default: + case 2: + tcg_gen_st_tl(cpu_A0, cpu_env, offsetof(CPUState, regs[reg])); + break; #else - gen_op_movh_EAX_T1, - gen_op_movh_ECX_T1, - gen_op_movh_EDX_T1, - gen_op_movh_EBX_T1, + default: + case 1: + tcg_gen_st32_tl(cpu_A0, cpu_env, offsetof(CPUState, regs[reg]) + REG_L_OFFSET); + break; #endif - }, - [OT_WORD] = { - DEF_REGS(gen_op_movw_, _T1) - }, - [OT_LONG] = { - DEF_REGS(gen_op_movl_, _T1) - }, + } +} + +static inline void gen_op_mov_TN_reg(int ot, int t_index, int reg) +{ + switch(ot) { + case OT_BYTE: + if (reg < 4 X86_64_DEF( || reg >= 8 || x86_64_hregs)) { + goto std_case; + } else { + tcg_gen_ld8u_tl(cpu_T[t_index], cpu_env, offsetof(CPUState, regs[reg - 4]) + REG_H_OFFSET); + } + break; + default: + std_case: + tcg_gen_ld_tl(cpu_T[t_index], cpu_env, offsetof(CPUState, regs[reg])); + break; + } +} + +static inline void gen_op_movl_A0_reg(int reg) +{ + tcg_gen_ld32u_tl(cpu_A0, cpu_env, offsetof(CPUState, regs[reg]) + REG_L_OFFSET); +} + +static inline void gen_op_addl_A0_im(int32_t val) +{ + tcg_gen_addi_tl(cpu_A0, cpu_A0, val); #ifdef TARGET_X86_64 - [OT_QUAD] = { - DEF_REGS(gen_op_movq_, _T1) - }, + tcg_gen_andi_tl(cpu_A0, cpu_A0, 0xffffffff); #endif -}; +} -static GenOpFunc *gen_op_mov_reg_A0[NB_OP_SIZES - 1][CPU_NB_REGS] = { - [0] = { - DEF_REGS(gen_op_movw_, _A0) - }, - [1] = { - DEF_REGS(gen_op_movl_, _A0) - }, #ifdef TARGET_X86_64 - [2] = { - DEF_REGS(gen_op_movq_, _A0) - }, +static inline void gen_op_addq_A0_im(int64_t val) +{ + tcg_gen_addi_tl(cpu_A0, cpu_A0, val); +} #endif -}; + +static void gen_add_A0_im(DisasContext *s, int val) +{ +#ifdef TARGET_X86_64 + if (CODE64(s)) + gen_op_addq_A0_im(val); + else +#endif + gen_op_addl_A0_im(val); +} -static GenOpFunc *gen_op_mov_TN_reg[NB_OP_SIZES][2][CPU_NB_REGS] = +static inline void gen_op_addl_T0_T1(void) { - [OT_BYTE] = { - { - gen_op_movl_T0_EAX, - gen_op_movl_T0_ECX, - gen_op_movl_T0_EDX, - gen_op_movl_T0_EBX, + tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_T[1]); +} + +static inline void gen_op_jmp_T0(void) +{ + tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUState, eip)); +} + +static inline void gen_op_addw_ESP_im(int32_t val) +{ + tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[R_ESP])); + tcg_gen_addi_tl(cpu_tmp0, cpu_tmp0, val); + tcg_gen_st16_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[R_ESP]) + REG_W_OFFSET); +} + +static inline void gen_op_addl_ESP_im(int32_t val) +{ + tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[R_ESP])); + tcg_gen_addi_tl(cpu_tmp0, cpu_tmp0, val); #ifdef TARGET_X86_64 - gen_op_movl_T0_ESP_wrapper, - gen_op_movl_T0_EBP_wrapper, - gen_op_movl_T0_ESI_wrapper, - gen_op_movl_T0_EDI_wrapper, - gen_op_movl_T0_R8, - gen_op_movl_T0_R9, - gen_op_movl_T0_R10, - gen_op_movl_T0_R11, - gen_op_movl_T0_R12, - gen_op_movl_T0_R13, - gen_op_movl_T0_R14, - gen_op_movl_T0_R15, -#else - gen_op_movh_T0_EAX, - gen_op_movh_T0_ECX, - gen_op_movh_T0_EDX, - gen_op_movh_T0_EBX, + tcg_gen_andi_tl(cpu_tmp0, cpu_tmp0, 0xffffffff); #endif - }, - { - gen_op_movl_T1_EAX, - gen_op_movl_T1_ECX, - gen_op_movl_T1_EDX, - gen_op_movl_T1_EBX, + tcg_gen_st_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[R_ESP])); +} + #ifdef TARGET_X86_64 - gen_op_movl_T1_ESP_wrapper, - gen_op_movl_T1_EBP_wrapper, - gen_op_movl_T1_ESI_wrapper, - gen_op_movl_T1_EDI_wrapper, - gen_op_movl_T1_R8, - gen_op_movl_T1_R9, - gen_op_movl_T1_R10, - gen_op_movl_T1_R11, - gen_op_movl_T1_R12, - gen_op_movl_T1_R13, - gen_op_movl_T1_R14, - gen_op_movl_T1_R15, -#else - gen_op_movh_T1_EAX, - gen_op_movh_T1_ECX, - gen_op_movh_T1_EDX, - gen_op_movh_T1_EBX, +static inline void gen_op_addq_ESP_im(int32_t val) +{ + tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[R_ESP])); + tcg_gen_addi_tl(cpu_tmp0, cpu_tmp0, val); + tcg_gen_st_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[R_ESP])); +} #endif - }, - }, - [OT_WORD] = { - { - DEF_REGS(gen_op_movl_T0_, ) - }, - { - DEF_REGS(gen_op_movl_T1_, ) - }, - }, - [OT_LONG] = { - { - DEF_REGS(gen_op_movl_T0_, ) - }, - { - DEF_REGS(gen_op_movl_T1_, ) - }, - }, + +static inline void gen_op_set_cc_op(int32_t val) +{ + tcg_gen_movi_tl(cpu_tmp0, val); + tcg_gen_st32_tl(cpu_tmp0, cpu_env, offsetof(CPUState, cc_op)); +} + +static inline void gen_op_addl_A0_reg_sN(int shift, int reg) +{ + tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg])); + if (shift != 0) + tcg_gen_shli_tl(cpu_tmp0, cpu_tmp0, shift); + tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0); #ifdef TARGET_X86_64 - [OT_QUAD] = { - { - DEF_REGS(gen_op_movl_T0_, ) - }, - { - DEF_REGS(gen_op_movl_T1_, ) - }, - }, + tcg_gen_andi_tl(cpu_A0, cpu_A0, 0xffffffff); #endif -}; +} -static GenOpFunc *gen_op_movl_A0_reg[CPU_NB_REGS] = { - DEF_REGS(gen_op_movl_A0_, ) -}; +static inline void gen_op_movl_A0_seg(int reg) +{ + tcg_gen_ld32u_tl(cpu_A0, cpu_env, offsetof(CPUState, segs[reg].base) + REG_L_OFFSET); +} -static GenOpFunc *gen_op_addl_A0_reg_sN[4][CPU_NB_REGS] = { - [0] = { - DEF_REGS(gen_op_addl_A0_, ) - }, - [1] = { - DEF_REGS(gen_op_addl_A0_, _s1) - }, - [2] = { - DEF_REGS(gen_op_addl_A0_, _s2) - }, - [3] = { - DEF_REGS(gen_op_addl_A0_, _s3) - }, -}; +static inline void gen_op_addl_A0_seg(int reg) +{ + tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUState, segs[reg].base)); + tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0); +#ifdef TARGET_X86_64 + tcg_gen_andi_tl(cpu_A0, cpu_A0, 0xffffffff); +#endif +} #ifdef TARGET_X86_64 -static GenOpFunc *gen_op_movq_A0_reg[CPU_NB_REGS] = { - DEF_REGS(gen_op_movq_A0_, ) -}; +static inline void gen_op_movq_A0_seg(int reg) +{ + tcg_gen_ld_tl(cpu_A0, cpu_env, offsetof(CPUState, segs[reg].base)); +} -static GenOpFunc *gen_op_addq_A0_reg_sN[4][CPU_NB_REGS] = { - [0] = { - DEF_REGS(gen_op_addq_A0_, ) - }, - [1] = { - DEF_REGS(gen_op_addq_A0_, _s1) - }, - [2] = { - DEF_REGS(gen_op_addq_A0_, _s2) - }, - [3] = { - DEF_REGS(gen_op_addq_A0_, _s3) - }, -}; +static inline void gen_op_addq_A0_seg(int reg) +{ + tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUState, segs[reg].base)); + tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0); +} + +static inline void gen_op_movq_A0_reg(int reg) +{ + tcg_gen_ld_tl(cpu_A0, cpu_env, offsetof(CPUState, regs[reg])); +} + +static inline void gen_op_addq_A0_reg_sN(int shift, int reg) +{ + tcg_gen_ld_tl(cpu_tmp0, cpu_env, offsetof(CPUState, regs[reg])); + if (shift != 0) + tcg_gen_shli_tl(cpu_tmp0, cpu_tmp0, shift); + tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0); +} #endif static GenOpFunc *gen_op_cmov_reg_T1_T0[NB_OP_SIZES - 1][CPU_NB_REGS] = { @@ -469,17 +560,6 @@ static GenOpFunc *gen_op_cmov_reg_T1_T0[NB_OP_SIZES - 1][CPU_NB_REGS] = { #endif }; -static GenOpFunc *gen_op_arith_T0_T1_cc[8] = { - NULL, - gen_op_orl_T0_T1, - NULL, - NULL, - gen_op_andl_T0_T1, - NULL, - gen_op_xorl_T0_T1, - NULL, -}; - #define DEF_ARITHC(SUFFIX)\ {\ gen_op_adcb ## SUFFIX ## _T0_T1_cc,\ @@ -681,133 +761,113 @@ static GenOpFunc *gen_op_bsx_T0_cc[3][2] = { #endif }; -static GenOpFunc *gen_op_lds_T0_A0[3 * 4] = { - gen_op_ldsb_raw_T0_A0, - gen_op_ldsw_raw_T0_A0, - X86_64_ONLY(gen_op_ldsl_raw_T0_A0), - NULL, -#ifndef CONFIG_USER_ONLY - gen_op_ldsb_kernel_T0_A0, - gen_op_ldsw_kernel_T0_A0, - X86_64_ONLY(gen_op_ldsl_kernel_T0_A0), - NULL, - - gen_op_ldsb_user_T0_A0, - gen_op_ldsw_user_T0_A0, - X86_64_ONLY(gen_op_ldsl_user_T0_A0), - NULL, -#endif -}; - -static GenOpFunc *gen_op_ldu_T0_A0[3 * 4] = { - gen_op_ldub_raw_T0_A0, - gen_op_lduw_raw_T0_A0, - NULL, - NULL, - -#ifndef CONFIG_USER_ONLY - gen_op_ldub_kernel_T0_A0, - gen_op_lduw_kernel_T0_A0, - NULL, - NULL, - - gen_op_ldub_user_T0_A0, - gen_op_lduw_user_T0_A0, - NULL, - NULL, -#endif -}; +static inline void gen_op_lds_T0_A0(int idx) +{ + int mem_index = (idx >> 2) - 1; + switch(idx & 3) { + case 0: + tcg_gen_qemu_ld8s(cpu_T[0], cpu_A0, mem_index); + break; + case 1: + tcg_gen_qemu_ld16s(cpu_T[0], cpu_A0, mem_index); + break; + default: + case 2: + tcg_gen_qemu_ld32s(cpu_T[0], cpu_A0, mem_index); + break; + } +} /* sign does not matter, except for lidt/lgdt call (TODO: fix it) */ -static GenOpFunc *gen_op_ld_T0_A0[3 * 4] = { - gen_op_ldub_raw_T0_A0, - gen_op_lduw_raw_T0_A0, - gen_op_ldl_raw_T0_A0, - X86_64_ONLY(gen_op_ldq_raw_T0_A0), - -#ifndef CONFIG_USER_ONLY - gen_op_ldub_kernel_T0_A0, - gen_op_lduw_kernel_T0_A0, - gen_op_ldl_kernel_T0_A0, - X86_64_ONLY(gen_op_ldq_kernel_T0_A0), - - gen_op_ldub_user_T0_A0, - gen_op_lduw_user_T0_A0, - gen_op_ldl_user_T0_A0, - X86_64_ONLY(gen_op_ldq_user_T0_A0), -#endif -}; - -static GenOpFunc *gen_op_ld_T1_A0[3 * 4] = { - gen_op_ldub_raw_T1_A0, - gen_op_lduw_raw_T1_A0, - gen_op_ldl_raw_T1_A0, - X86_64_ONLY(gen_op_ldq_raw_T1_A0), - -#ifndef CONFIG_USER_ONLY - gen_op_ldub_kernel_T1_A0, - gen_op_lduw_kernel_T1_A0, - gen_op_ldl_kernel_T1_A0, - X86_64_ONLY(gen_op_ldq_kernel_T1_A0), - - gen_op_ldub_user_T1_A0, - gen_op_lduw_user_T1_A0, - gen_op_ldl_user_T1_A0, - X86_64_ONLY(gen_op_ldq_user_T1_A0), -#endif -}; - -static GenOpFunc *gen_op_st_T0_A0[3 * 4] = { - gen_op_stb_raw_T0_A0, - gen_op_stw_raw_T0_A0, - gen_op_stl_raw_T0_A0, - X86_64_ONLY(gen_op_stq_raw_T0_A0), +static inline void gen_op_ld_T0_A0(int idx) +{ + int mem_index = (idx >> 2) - 1; + switch(idx & 3) { + case 0: + tcg_gen_qemu_ld8u(cpu_T[0], cpu_A0, mem_index); + break; + case 1: + tcg_gen_qemu_ld16u(cpu_T[0], cpu_A0, mem_index); + break; + case 2: + tcg_gen_qemu_ld32u(cpu_T[0], cpu_A0, mem_index); + break; + default: + case 3: + tcg_gen_qemu_ld64(cpu_T[0], cpu_A0, mem_index); + break; + } +} -#ifndef CONFIG_USER_ONLY - gen_op_stb_kernel_T0_A0, - gen_op_stw_kernel_T0_A0, - gen_op_stl_kernel_T0_A0, - X86_64_ONLY(gen_op_stq_kernel_T0_A0), - - gen_op_stb_user_T0_A0, - gen_op_stw_user_T0_A0, - gen_op_stl_user_T0_A0, - X86_64_ONLY(gen_op_stq_user_T0_A0), -#endif -}; +static inline void gen_op_ldu_T0_A0(int idx) +{ + gen_op_ld_T0_A0(idx); +} -static GenOpFunc *gen_op_st_T1_A0[3 * 4] = { - NULL, - gen_op_stw_raw_T1_A0, - gen_op_stl_raw_T1_A0, - X86_64_ONLY(gen_op_stq_raw_T1_A0), +static inline void gen_op_ld_T1_A0(int idx) +{ + int mem_index = (idx >> 2) - 1; + switch(idx & 3) { + case 0: + tcg_gen_qemu_ld8u(cpu_T[1], cpu_A0, mem_index); + break; + case 1: + tcg_gen_qemu_ld16u(cpu_T[1], cpu_A0, mem_index); + break; + case 2: + tcg_gen_qemu_ld32u(cpu_T[1], cpu_A0, mem_index); + break; + default: + case 3: + tcg_gen_qemu_ld64(cpu_T[1], cpu_A0, mem_index); + break; + } +} -#ifndef CONFIG_USER_ONLY - NULL, - gen_op_stw_kernel_T1_A0, - gen_op_stl_kernel_T1_A0, - X86_64_ONLY(gen_op_stq_kernel_T1_A0), +static inline void gen_op_st_T0_A0(int idx) +{ + int mem_index = (idx >> 2) - 1; + switch(idx & 3) { + case 0: + tcg_gen_qemu_st8(cpu_T[0], cpu_A0, mem_index); + break; + case 1: + tcg_gen_qemu_st16(cpu_T[0], cpu_A0, mem_index); + break; + case 2: + tcg_gen_qemu_st32(cpu_T[0], cpu_A0, mem_index); + break; + default: + case 3: + tcg_gen_qemu_st64(cpu_T[0], cpu_A0, mem_index); + break; + } +} - NULL, - gen_op_stw_user_T1_A0, - gen_op_stl_user_T1_A0, - X86_64_ONLY(gen_op_stq_user_T1_A0), -#endif -}; +static inline void gen_op_st_T1_A0(int idx) +{ + int mem_index = (idx >> 2) - 1; + switch(idx & 3) { + case 0: + tcg_gen_qemu_st8(cpu_T[1], cpu_A0, mem_index); + break; + case 1: + tcg_gen_qemu_st16(cpu_T[1], cpu_A0, mem_index); + break; + case 2: + tcg_gen_qemu_st32(cpu_T[1], cpu_A0, mem_index); + break; + default: + case 3: + tcg_gen_qemu_st64(cpu_T[1], cpu_A0, mem_index); + break; + } +} static inline void gen_jmp_im(target_ulong pc) { -#ifdef TARGET_X86_64 - if (pc == (uint32_t)pc) { - gen_op_movl_eip_im(pc); - } else if (pc == (int32_t)pc) { - gen_op_movq_eip_im(pc); - } else { - gen_op_movq_eip_im64(pc >> 32, pc); - } -#else - gen_op_movl_eip_im(pc); -#endif + tcg_gen_movi_tl(cpu_tmp0, pc); + tcg_gen_st_tl(cpu_tmp0, cpu_env, offsetof(CPUState, eip)); } static inline void gen_string_movl_A0_ESI(DisasContext *s) @@ -818,10 +878,10 @@ static inline void gen_string_movl_A0_ESI(DisasContext *s) #ifdef TARGET_X86_64 if (s->aflag == 2) { if (override >= 0) { - gen_op_movq_A0_seg(offsetof(CPUX86State,segs[override].base)); - gen_op_addq_A0_reg_sN[0][R_ESI](); + gen_op_movq_A0_seg(override); + gen_op_addq_A0_reg_sN(0, R_ESI); } else { - gen_op_movq_A0_reg[R_ESI](); + gen_op_movq_A0_reg(R_ESI); } } else #endif @@ -830,18 +890,18 @@ static inline void gen_string_movl_A0_ESI(DisasContext *s) if (s->addseg && override < 0) override = R_DS; if (override >= 0) { - gen_op_movl_A0_seg(offsetof(CPUX86State,segs[override].base)); - gen_op_addl_A0_reg_sN[0][R_ESI](); + gen_op_movl_A0_seg(override); + gen_op_addl_A0_reg_sN(0, R_ESI); } else { - gen_op_movl_A0_reg[R_ESI](); + gen_op_movl_A0_reg(R_ESI); } } else { /* 16 address, always override */ if (override < 0) override = R_DS; - gen_op_movl_A0_reg[R_ESI](); + gen_op_movl_A0_reg(R_ESI); gen_op_andl_A0_ffff(); - gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base)); + gen_op_addl_A0_seg(override); } } @@ -849,20 +909,20 @@ static inline void gen_string_movl_A0_EDI(DisasContext *s) { #ifdef TARGET_X86_64 if (s->aflag == 2) { - gen_op_movq_A0_reg[R_EDI](); + gen_op_movq_A0_reg(R_EDI); } else #endif if (s->aflag) { if (s->addseg) { - gen_op_movl_A0_seg(offsetof(CPUX86State,segs[R_ES].base)); - gen_op_addl_A0_reg_sN[0][R_EDI](); + gen_op_movl_A0_seg(R_ES); + gen_op_addl_A0_reg_sN(0, R_EDI); } else { - gen_op_movl_A0_reg[R_EDI](); + gen_op_movl_A0_reg(R_EDI); } } else { - gen_op_movl_A0_reg[R_EDI](); + gen_op_movl_A0_reg(R_EDI); gen_op_andl_A0_ffff(); - gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_ES].base)); + gen_op_addl_A0_seg(R_ES); } } @@ -958,9 +1018,9 @@ static void gen_check_io(DisasContext *s, int ot, int use_dx, target_ulong cur_e static inline void gen_movs(DisasContext *s, int ot) { gen_string_movl_A0_ESI(s); - gen_op_ld_T0_A0[ot + s->mem_index](); + gen_op_ld_T0_A0(ot + s->mem_index); gen_string_movl_A0_EDI(s); - gen_op_st_T0_A0[ot + s->mem_index](); + gen_op_st_T0_A0(ot + s->mem_index); gen_op_movl_T0_Dshift[ot](); #ifdef TARGET_X86_64 if (s->aflag == 2) { @@ -1002,9 +1062,9 @@ static int gen_jz_ecx_string(DisasContext *s, target_ulong next_eip) static inline void gen_stos(DisasContext *s, int ot) { - gen_op_mov_TN_reg[OT_LONG][0][R_EAX](); + gen_op_mov_TN_reg(OT_LONG, 0, R_EAX); gen_string_movl_A0_EDI(s); - gen_op_st_T0_A0[ot + s->mem_index](); + gen_op_st_T0_A0(ot + s->mem_index); gen_op_movl_T0_Dshift[ot](); #ifdef TARGET_X86_64 if (s->aflag == 2) { @@ -1021,8 +1081,8 @@ static inline void gen_stos(DisasContext *s, int ot) static inline void gen_lods(DisasContext *s, int ot) { gen_string_movl_A0_ESI(s); - gen_op_ld_T0_A0[ot + s->mem_index](); - gen_op_mov_reg_T0[ot][R_EAX](); + gen_op_ld_T0_A0(ot + s->mem_index); + gen_op_mov_reg_T0(ot, R_EAX); gen_op_movl_T0_Dshift[ot](); #ifdef TARGET_X86_64 if (s->aflag == 2) { @@ -1038,9 +1098,9 @@ static inline void gen_lods(DisasContext *s, int ot) static inline void gen_scas(DisasContext *s, int ot) { - gen_op_mov_TN_reg[OT_LONG][0][R_EAX](); + gen_op_mov_TN_reg(OT_LONG, 0, R_EAX); gen_string_movl_A0_EDI(s); - gen_op_ld_T1_A0[ot + s->mem_index](); + gen_op_ld_T1_A0(ot + s->mem_index); gen_op_cmpl_T0_T1_cc(); gen_op_movl_T0_Dshift[ot](); #ifdef TARGET_X86_64 @@ -1058,9 +1118,9 @@ static inline void gen_scas(DisasContext *s, int ot) static inline void gen_cmps(DisasContext *s, int ot) { gen_string_movl_A0_ESI(s); - gen_op_ld_T0_A0[ot + s->mem_index](); + gen_op_ld_T0_A0(ot + s->mem_index); gen_string_movl_A0_EDI(s); - gen_op_ld_T1_A0[ot + s->mem_index](); + gen_op_ld_T1_A0(ot + s->mem_index); gen_op_cmpl_T0_T1_cc(); gen_op_movl_T0_Dshift[ot](); #ifdef TARGET_X86_64 @@ -1082,9 +1142,9 @@ static inline void gen_ins(DisasContext *s, int ot) { gen_string_movl_A0_EDI(s); gen_op_movl_T0_0(); - gen_op_st_T0_A0[ot + s->mem_index](); + gen_op_st_T0_A0(ot + s->mem_index); gen_op_in_DX_T0[ot](); - gen_op_st_T0_A0[ot + s->mem_index](); + gen_op_st_T0_A0(ot + s->mem_index); gen_op_movl_T0_Dshift[ot](); #ifdef TARGET_X86_64 if (s->aflag == 2) { @@ -1101,7 +1161,7 @@ static inline void gen_ins(DisasContext *s, int ot) static inline void gen_outs(DisasContext *s, int ot) { gen_string_movl_A0_ESI(s); - gen_op_ld_T0_A0[ot + s->mem_index](); + gen_op_ld_T0_A0(ot + s->mem_index); gen_op_out_DX_T0[ot](); gen_op_movl_T0_Dshift[ot](); #ifdef TARGET_X86_64 @@ -1320,9 +1380,9 @@ static void gen_op(DisasContext *s1, int op, int ot, int d) GenOpFunc *gen_update_cc; if (d != OR_TMP0) { - gen_op_mov_TN_reg[ot][0][d](); + gen_op_mov_TN_reg(ot, 0, d); } else { - gen_op_ld_T0_A0[ot + s1->mem_index](); + gen_op_ld_T0_A0(ot + s1->mem_index); } switch(op) { case OP_ADCL: @@ -1331,7 +1391,7 @@ static void gen_op(DisasContext *s1, int op, int ot, int d) gen_op_set_cc_op(s1->cc_op); if (d != OR_TMP0) { gen_op_arithc_T0_T1_cc[ot][op - OP_ADCL](); - gen_op_mov_reg_T0[ot][d](); + gen_op_mov_reg_T0(ot, d); } else { gen_op_arithc_mem_T0_T1_cc[ot + s1->mem_index][op - OP_ADCL](); } @@ -1343,15 +1403,23 @@ static void gen_op(DisasContext *s1, int op, int ot, int d) gen_update_cc = gen_op_update2_cc; break; case OP_SUBL: - gen_op_subl_T0_T1(); + tcg_gen_sub_tl(cpu_T[0], cpu_T[0], cpu_T[1]); s1->cc_op = CC_OP_SUBB + ot; gen_update_cc = gen_op_update2_cc; break; default: case OP_ANDL: + tcg_gen_and_tl(cpu_T[0], cpu_T[0], cpu_T[1]); + s1->cc_op = CC_OP_LOGICB + ot; + gen_update_cc = gen_op_update1_cc; + break; case OP_ORL: + tcg_gen_or_tl(cpu_T[0], cpu_T[0], cpu_T[1]); + s1->cc_op = CC_OP_LOGICB + ot; + gen_update_cc = gen_op_update1_cc; + break; case OP_XORL: - gen_op_arith_T0_T1_cc[op](); + tcg_gen_xor_tl(cpu_T[0], cpu_T[0], cpu_T[1]); s1->cc_op = CC_OP_LOGICB + ot; gen_update_cc = gen_op_update1_cc; break; @@ -1363,9 +1431,9 @@ static void gen_op(DisasContext *s1, int op, int ot, int d) } if (op != OP_CMPL) { if (d != OR_TMP0) - gen_op_mov_reg_T0[ot][d](); + gen_op_mov_reg_T0(ot, d); else - gen_op_st_T0_A0[ot + s1->mem_index](); + gen_op_st_T0_A0(ot + s1->mem_index); } /* the flags update must happen after the memory write (precise exception support) */ @@ -1378,9 +1446,9 @@ static void gen_op(DisasContext *s1, int op, int ot, int d) static void gen_inc(DisasContext *s1, int ot, int d, int c) { if (d != OR_TMP0) - gen_op_mov_TN_reg[ot][0][d](); + gen_op_mov_TN_reg(ot, 0, d); else - gen_op_ld_T0_A0[ot + s1->mem_index](); + gen_op_ld_T0_A0(ot + s1->mem_index); if (s1->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s1->cc_op); if (c > 0) { @@ -1391,20 +1459,20 @@ static void gen_inc(DisasContext *s1, int ot, int d, int c) s1->cc_op = CC_OP_DECB + ot; } if (d != OR_TMP0) - gen_op_mov_reg_T0[ot][d](); + gen_op_mov_reg_T0(ot, d); else - gen_op_st_T0_A0[ot + s1->mem_index](); + gen_op_st_T0_A0(ot + s1->mem_index); gen_op_update_inc_cc(); } static void gen_shift(DisasContext *s1, int op, int ot, int d, int s) { if (d != OR_TMP0) - gen_op_mov_TN_reg[ot][0][d](); + gen_op_mov_TN_reg(ot, 0, d); else - gen_op_ld_T0_A0[ot + s1->mem_index](); + gen_op_ld_T0_A0(ot + s1->mem_index); if (s != OR_TMP1) - gen_op_mov_TN_reg[ot][1][s](); + gen_op_mov_TN_reg(ot, 1, s); /* for zero counts, flags are not updated, so must do it dynamically */ if (s1->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s1->cc_op); @@ -1414,7 +1482,7 @@ static void gen_shift(DisasContext *s1, int op, int ot, int d, int s) else gen_op_shift_mem_T0_T1_cc[ot + s1->mem_index][op](); if (d != OR_TMP0) - gen_op_mov_reg_T0[ot][d](); + gen_op_mov_reg_T0(ot, d); s1->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */ } @@ -1487,27 +1555,21 @@ static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_ disp += s->popl_esp_hack; #ifdef TARGET_X86_64 if (s->aflag == 2) { - gen_op_movq_A0_reg[base](); + gen_op_movq_A0_reg(base); if (disp != 0) { - if ((int32_t)disp == disp) - gen_op_addq_A0_im(disp); - else - gen_op_addq_A0_im64(disp >> 32, disp); + gen_op_addq_A0_im(disp); } } else #endif { - gen_op_movl_A0_reg[base](); + gen_op_movl_A0_reg(base); if (disp != 0) gen_op_addl_A0_im(disp); } } else { #ifdef TARGET_X86_64 if (s->aflag == 2) { - if ((int32_t)disp == disp) - gen_op_movq_A0_im(disp); - else - gen_op_movq_A0_im64(disp >> 32, disp); + gen_op_movq_A0_im(disp); } else #endif { @@ -1518,11 +1580,11 @@ static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_ if (havesib && (index != 4 || scale != 0)) { #ifdef TARGET_X86_64 if (s->aflag == 2) { - gen_op_addq_A0_reg_sN[scale][index](); + gen_op_addq_A0_reg_sN(scale, index); } else #endif { - gen_op_addl_A0_reg_sN[scale][index](); + gen_op_addl_A0_reg_sN(scale, index); } } if (must_add_seg) { @@ -1534,11 +1596,11 @@ static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_ } #ifdef TARGET_X86_64 if (s->aflag == 2) { - gen_op_addq_A0_seg(offsetof(CPUX86State,segs[override].base)); + gen_op_addq_A0_seg(override); } else #endif { - gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base)); + gen_op_addl_A0_seg(override); } } } else { @@ -1565,33 +1627,33 @@ static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_ } switch(rm) { case 0: - gen_op_movl_A0_reg[R_EBX](); - gen_op_addl_A0_reg_sN[0][R_ESI](); + gen_op_movl_A0_reg(R_EBX); + gen_op_addl_A0_reg_sN(0, R_ESI); break; case 1: - gen_op_movl_A0_reg[R_EBX](); - gen_op_addl_A0_reg_sN[0][R_EDI](); + gen_op_movl_A0_reg(R_EBX); + gen_op_addl_A0_reg_sN(0, R_EDI); break; case 2: - gen_op_movl_A0_reg[R_EBP](); - gen_op_addl_A0_reg_sN[0][R_ESI](); + gen_op_movl_A0_reg(R_EBP); + gen_op_addl_A0_reg_sN(0, R_ESI); break; case 3: - gen_op_movl_A0_reg[R_EBP](); - gen_op_addl_A0_reg_sN[0][R_EDI](); + gen_op_movl_A0_reg(R_EBP); + gen_op_addl_A0_reg_sN(0, R_EDI); break; case 4: - gen_op_movl_A0_reg[R_ESI](); + gen_op_movl_A0_reg(R_ESI); break; case 5: - gen_op_movl_A0_reg[R_EDI](); + gen_op_movl_A0_reg(R_EDI); break; case 6: - gen_op_movl_A0_reg[R_EBP](); + gen_op_movl_A0_reg(R_EBP); break; default: case 7: - gen_op_movl_A0_reg[R_EBX](); + gen_op_movl_A0_reg(R_EBX); break; } if (disp != 0) @@ -1605,7 +1667,7 @@ static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_ else override = R_DS; } - gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base)); + gen_op_addl_A0_seg(override); } } @@ -1680,11 +1742,11 @@ static void gen_add_A0_ds_seg(DisasContext *s) if (must_add_seg) { #ifdef TARGET_X86_64 if (CODE64(s)) { - gen_op_addq_A0_seg(offsetof(CPUX86State,segs[override].base)); + gen_op_addq_A0_seg(override); } else #endif { - gen_op_addl_A0_seg(offsetof(CPUX86State,segs[override].base)); + gen_op_addl_A0_seg(override); } } } @@ -1700,23 +1762,23 @@ static void gen_ldst_modrm(DisasContext *s, int modrm, int ot, int reg, int is_s if (mod == 3) { if (is_store) { if (reg != OR_TMP0) - gen_op_mov_TN_reg[ot][0][reg](); - gen_op_mov_reg_T0[ot][rm](); + gen_op_mov_TN_reg(ot, 0, reg); + gen_op_mov_reg_T0(ot, rm); } else { - gen_op_mov_TN_reg[ot][0][rm](); + gen_op_mov_TN_reg(ot, 0, rm); if (reg != OR_TMP0) - gen_op_mov_reg_T0[ot][reg](); + gen_op_mov_reg_T0(ot, reg); } } else { gen_lea_modrm(s, modrm, &opreg, &disp); if (is_store) { if (reg != OR_TMP0) - gen_op_mov_TN_reg[ot][0][reg](); - gen_op_st_T0_A0[ot + s->mem_index](); + gen_op_mov_TN_reg(ot, 0, reg); + gen_op_st_T0_A0(ot + s->mem_index); } else { - gen_op_ld_T0_A0[ot + s->mem_index](); + gen_op_ld_T0_A0(ot + s->mem_index); if (reg != OR_TMP0) - gen_op_mov_reg_T0[ot][reg](); + gen_op_mov_reg_T0(ot, reg); } } } @@ -1762,13 +1824,9 @@ static inline void gen_goto_tb(DisasContext *s, int tb_num, target_ulong eip) if ((pc & TARGET_PAGE_MASK) == (tb->pc & TARGET_PAGE_MASK) || (pc & TARGET_PAGE_MASK) == ((s->pc - 1) & TARGET_PAGE_MASK)) { /* jump to same page: we can use a direct jump */ - if (tb_num == 0) - gen_op_goto_tb0(TBPARAM(tb)); - else - gen_op_goto_tb1(TBPARAM(tb)); + tcg_gen_goto_tb(tb_num); gen_jmp_im(eip); - gen_op_movl_T0_im((long)tb + tb_num); - gen_op_exit_tb(); + tcg_gen_exit_tb((long)tb + tb_num); } else { /* jump to another page: currently not optimized */ gen_jmp_im(eip); @@ -1995,11 +2053,7 @@ static void gen_movl_seg_T0(DisasContext *s, int seg_reg, target_ulong cur_eip) } } -#ifdef TARGET_X86_64 -#define SVM_movq_T1_im(x) gen_op_movq_T1_im64((x) >> 32, x) -#else -#define SVM_movq_T1_im(x) gen_op_movl_T1_im(x) -#endif +#define SVM_movq_T1_im(x) gen_movtl_T1_im(x) static inline int gen_svm_check_io(DisasContext *s, target_ulong pc_start, uint64_t type) @@ -2091,26 +2145,13 @@ static inline void gen_stack_update(DisasContext *s, int addend) { #ifdef TARGET_X86_64 if (CODE64(s)) { - if (addend == 8) - gen_op_addq_ESP_8(); - else - gen_op_addq_ESP_im(addend); + gen_op_addq_ESP_im(addend); } else #endif if (s->ss32) { - if (addend == 2) - gen_op_addl_ESP_2(); - else if (addend == 4) - gen_op_addl_ESP_4(); - else - gen_op_addl_ESP_im(addend); + gen_op_addl_ESP_im(addend); } else { - if (addend == 2) - gen_op_addw_ESP_2(); - else if (addend == 4) - gen_op_addw_ESP_4(); - else - gen_op_addw_ESP_im(addend); + gen_op_addw_ESP_im(addend); } } @@ -2119,38 +2160,38 @@ static void gen_push_T0(DisasContext *s) { #ifdef TARGET_X86_64 if (CODE64(s)) { - gen_op_movq_A0_reg[R_ESP](); + gen_op_movq_A0_reg(R_ESP); if (s->dflag) { - gen_op_subq_A0_8(); - gen_op_st_T0_A0[OT_QUAD + s->mem_index](); + gen_op_addq_A0_im(-8); + gen_op_st_T0_A0(OT_QUAD + s->mem_index); } else { - gen_op_subq_A0_2(); - gen_op_st_T0_A0[OT_WORD + s->mem_index](); + gen_op_addq_A0_im(-2); + gen_op_st_T0_A0(OT_WORD + s->mem_index); } - gen_op_movq_ESP_A0(); + gen_op_mov_reg_A0(2, R_ESP); } else #endif { - gen_op_movl_A0_reg[R_ESP](); + gen_op_movl_A0_reg(R_ESP); if (!s->dflag) - gen_op_subl_A0_2(); + gen_op_addl_A0_im(-2); else - gen_op_subl_A0_4(); + gen_op_addl_A0_im(-4); if (s->ss32) { if (s->addseg) { gen_op_movl_T1_A0(); - gen_op_addl_A0_SS(); + gen_op_addl_A0_seg(R_SS); } } else { gen_op_andl_A0_ffff(); gen_op_movl_T1_A0(); - gen_op_addl_A0_SS(); + gen_op_addl_A0_seg(R_SS); } - gen_op_st_T0_A0[s->dflag + 1 + s->mem_index](); + gen_op_st_T0_A0(s->dflag + 1 + s->mem_index); if (s->ss32 && !s->addseg) - gen_op_movl_ESP_A0(); + gen_op_mov_reg_A0(1, R_ESP); else - gen_op_mov_reg_T1[s->ss32 + 1][R_ESP](); + gen_op_mov_reg_T1(s->ss32 + 1, R_ESP); } } @@ -2160,35 +2201,35 @@ static void gen_push_T1(DisasContext *s) { #ifdef TARGET_X86_64 if (CODE64(s)) { - gen_op_movq_A0_reg[R_ESP](); + gen_op_movq_A0_reg(R_ESP); if (s->dflag) { - gen_op_subq_A0_8(); - gen_op_st_T1_A0[OT_QUAD + s->mem_index](); + gen_op_addq_A0_im(-8); + gen_op_st_T1_A0(OT_QUAD + s->mem_index); } else { - gen_op_subq_A0_2(); - gen_op_st_T0_A0[OT_WORD + s->mem_index](); + gen_op_addq_A0_im(-2); + gen_op_st_T0_A0(OT_WORD + s->mem_index); } - gen_op_movq_ESP_A0(); + gen_op_mov_reg_A0(2, R_ESP); } else #endif { - gen_op_movl_A0_reg[R_ESP](); + gen_op_movl_A0_reg(R_ESP); if (!s->dflag) - gen_op_subl_A0_2(); + gen_op_addl_A0_im(-2); else - gen_op_subl_A0_4(); + gen_op_addl_A0_im(-4); if (s->ss32) { if (s->addseg) { - gen_op_addl_A0_SS(); + gen_op_addl_A0_seg(R_SS); } } else { gen_op_andl_A0_ffff(); - gen_op_addl_A0_SS(); + gen_op_addl_A0_seg(R_SS); } - gen_op_st_T1_A0[s->dflag + 1 + s->mem_index](); + gen_op_st_T1_A0(s->dflag + 1 + s->mem_index); if (s->ss32 && !s->addseg) - gen_op_movl_ESP_A0(); + gen_op_mov_reg_A0(1, R_ESP); else gen_stack_update(s, (-2) << s->dflag); } @@ -2199,20 +2240,20 @@ static void gen_pop_T0(DisasContext *s) { #ifdef TARGET_X86_64 if (CODE64(s)) { - gen_op_movq_A0_reg[R_ESP](); - gen_op_ld_T0_A0[(s->dflag ? OT_QUAD : OT_WORD) + s->mem_index](); + gen_op_movq_A0_reg(R_ESP); + gen_op_ld_T0_A0((s->dflag ? OT_QUAD : OT_WORD) + s->mem_index); } else #endif { - gen_op_movl_A0_reg[R_ESP](); + gen_op_movl_A0_reg(R_ESP); if (s->ss32) { if (s->addseg) - gen_op_addl_A0_SS(); + gen_op_addl_A0_seg(R_SS); } else { gen_op_andl_A0_ffff(); - gen_op_addl_A0_SS(); + gen_op_addl_A0_seg(R_SS); } - gen_op_ld_T0_A0[s->dflag + 1 + s->mem_index](); + gen_op_ld_T0_A0(s->dflag + 1 + s->mem_index); } } @@ -2230,53 +2271,53 @@ static void gen_pop_update(DisasContext *s) static void gen_stack_A0(DisasContext *s) { - gen_op_movl_A0_ESP(); + gen_op_movl_A0_reg(R_ESP); if (!s->ss32) gen_op_andl_A0_ffff(); gen_op_movl_T1_A0(); if (s->addseg) - gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base)); + gen_op_addl_A0_seg(R_SS); } /* NOTE: wrap around in 16 bit not fully handled */ static void gen_pusha(DisasContext *s) { int i; - gen_op_movl_A0_ESP(); + gen_op_movl_A0_reg(R_ESP); gen_op_addl_A0_im(-16 << s->dflag); if (!s->ss32) gen_op_andl_A0_ffff(); gen_op_movl_T1_A0(); if (s->addseg) - gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base)); + gen_op_addl_A0_seg(R_SS); for(i = 0;i < 8; i++) { - gen_op_mov_TN_reg[OT_LONG][0][7 - i](); - gen_op_st_T0_A0[OT_WORD + s->dflag + s->mem_index](); + gen_op_mov_TN_reg(OT_LONG, 0, 7 - i); + gen_op_st_T0_A0(OT_WORD + s->dflag + s->mem_index); gen_op_addl_A0_im(2 << s->dflag); } - gen_op_mov_reg_T1[OT_WORD + s->ss32][R_ESP](); + gen_op_mov_reg_T1(OT_WORD + s->ss32, R_ESP); } /* NOTE: wrap around in 16 bit not fully handled */ static void gen_popa(DisasContext *s) { int i; - gen_op_movl_A0_ESP(); + gen_op_movl_A0_reg(R_ESP); if (!s->ss32) gen_op_andl_A0_ffff(); gen_op_movl_T1_A0(); gen_op_addl_T1_im(16 << s->dflag); if (s->addseg) - gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base)); + gen_op_addl_A0_seg(R_SS); for(i = 0;i < 8; i++) { /* ESP is not reloaded */ if (i != 3) { - gen_op_ld_T0_A0[OT_WORD + s->dflag + s->mem_index](); - gen_op_mov_reg_T0[OT_WORD + s->dflag][7 - i](); + gen_op_ld_T0_A0(OT_WORD + s->dflag + s->mem_index); + gen_op_mov_reg_T0(OT_WORD + s->dflag, 7 - i); } gen_op_addl_A0_im(2 << s->dflag); } - gen_op_mov_reg_T1[OT_WORD + s->ss32][R_ESP](); + gen_op_mov_reg_T1(OT_WORD + s->ss32, R_ESP); } static void gen_enter(DisasContext *s, int esp_addend, int level) @@ -2289,41 +2330,41 @@ static void gen_enter(DisasContext *s, int esp_addend, int level) ot = s->dflag ? OT_QUAD : OT_WORD; opsize = 1 << ot; - gen_op_movl_A0_ESP(); + gen_op_movl_A0_reg(R_ESP); gen_op_addq_A0_im(-opsize); gen_op_movl_T1_A0(); /* push bp */ - gen_op_mov_TN_reg[OT_LONG][0][R_EBP](); - gen_op_st_T0_A0[ot + s->mem_index](); + gen_op_mov_TN_reg(OT_LONG, 0, R_EBP); + gen_op_st_T0_A0(ot + s->mem_index); if (level) { gen_op_enter64_level(level, (ot == OT_QUAD)); } - gen_op_mov_reg_T1[ot][R_EBP](); + gen_op_mov_reg_T1(ot, R_EBP); gen_op_addl_T1_im( -esp_addend + (-opsize * level) ); - gen_op_mov_reg_T1[OT_QUAD][R_ESP](); + gen_op_mov_reg_T1(OT_QUAD, R_ESP); } else #endif { ot = s->dflag + OT_WORD; opsize = 2 << s->dflag; - gen_op_movl_A0_ESP(); + gen_op_movl_A0_reg(R_ESP); gen_op_addl_A0_im(-opsize); if (!s->ss32) gen_op_andl_A0_ffff(); gen_op_movl_T1_A0(); if (s->addseg) - gen_op_addl_A0_seg(offsetof(CPUX86State,segs[R_SS].base)); + gen_op_addl_A0_seg(R_SS); /* push bp */ - gen_op_mov_TN_reg[OT_LONG][0][R_EBP](); - gen_op_st_T0_A0[ot + s->mem_index](); + gen_op_mov_TN_reg(OT_LONG, 0, R_EBP); + gen_op_st_T0_A0(ot + s->mem_index); if (level) { gen_op_enter_level(level, s->dflag); } - gen_op_mov_reg_T1[ot][R_EBP](); + gen_op_mov_reg_T1(ot, R_EBP); gen_op_addl_T1_im( -esp_addend + (-opsize * level) ); - gen_op_mov_reg_T1[OT_WORD + s->ss32][R_ESP](); + gen_op_mov_reg_T1(OT_WORD + s->ss32, R_ESP); } } @@ -2371,8 +2412,7 @@ static void gen_eob(DisasContext *s) } else if (s->tf) { gen_op_single_step(); } else { - gen_op_movl_T0_0(); - gen_op_exit_tb(); + tcg_gen_exit_tb(0); } s->is_jmp = 3; } @@ -2399,42 +2439,6 @@ static void gen_jmp(DisasContext *s, target_ulong eip) gen_jmp_tb(s, eip, 0); } -static void gen_movtl_T0_im(target_ulong val) -{ -#ifdef TARGET_X86_64 - if ((int32_t)val == val) { - gen_op_movl_T0_im(val); - } else { - gen_op_movq_T0_im64(val >> 32, val); - } -#else - gen_op_movl_T0_im(val); -#endif -} - -static void gen_movtl_T1_im(target_ulong val) -{ -#ifdef TARGET_X86_64 - if ((int32_t)val == val) { - gen_op_movl_T1_im(val); - } else { - gen_op_movq_T1_im64(val >> 32, val); - } -#else - gen_op_movl_T1_im(val); -#endif -} - -static void gen_add_A0_im(DisasContext *s, int val) -{ -#ifdef TARGET_X86_64 - if (CODE64(s)) - gen_op_addq_A0_im(val); - else -#endif - gen_op_addl_A0_im(val); -} - static GenOpFunc1 *gen_ldq_env_A0[3] = { gen_op_ldq_raw_env_A0, #ifndef CONFIG_USER_ONLY @@ -2764,7 +2768,7 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r) case 0x210: /* movss xmm, ea */ if (mod != 3) { gen_lea_modrm(s, modrm, ®_addr, &offset_addr); - gen_op_ld_T0_A0[OT_LONG + s->mem_index](); + gen_op_ld_T0_A0(OT_LONG + s->mem_index); gen_op_movl_env_T0(offsetof(CPUX86State,xmm_regs[reg].XMM_L(0))); gen_op_movl_T0_0(); gen_op_movl_env_T0(offsetof(CPUX86State,xmm_regs[reg].XMM_L(1))); @@ -2921,7 +2925,7 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r) if (mod != 3) { gen_lea_modrm(s, modrm, ®_addr, &offset_addr); gen_op_movl_T0_env(offsetof(CPUX86State,xmm_regs[reg].XMM_L(0))); - gen_op_st_T0_A0[OT_LONG + s->mem_index](); + gen_op_st_T0_A0(OT_LONG + s->mem_index); } else { rm = (modrm & 7) | REX_B(s); gen_op_movl(offsetof(CPUX86State,xmm_regs[rm].XMM_L(0)), @@ -2991,12 +2995,12 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r) case 0x050: /* movmskps */ rm = (modrm & 7) | REX_B(s); gen_op_movmskps(offsetof(CPUX86State,xmm_regs[rm])); - gen_op_mov_reg_T0[OT_LONG][reg](); + gen_op_mov_reg_T0(OT_LONG, reg); break; case 0x150: /* movmskpd */ rm = (modrm & 7) | REX_B(s); gen_op_movmskpd(offsetof(CPUX86State,xmm_regs[rm])); - gen_op_mov_reg_T0[OT_LONG][reg](); + gen_op_mov_reg_T0(OT_LONG, reg); break; case 0x02a: /* cvtpi2ps */ case 0x12a: /* cvtpi2pd */ @@ -3066,7 +3070,7 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r) if ((b >> 8) & 1) { gen_ldq_env_A0[s->mem_index >> 2](offsetof(CPUX86State,xmm_t0.XMM_Q(0))); } else { - gen_op_ld_T0_A0[OT_LONG + s->mem_index](); + gen_op_ld_T0_A0(OT_LONG + s->mem_index); gen_op_movl_env_T0(offsetof(CPUX86State,xmm_t0.XMM_L(0))); } op2_offset = offsetof(CPUX86State,xmm_t0); @@ -3076,7 +3080,7 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r) } sse_op_table3[(s->dflag == 2) * 2 + ((b >> 8) - 2) + 4 + (b & 1) * 4](op2_offset); - gen_op_mov_reg_T0[ot][reg](); + gen_op_mov_reg_T0(ot, reg); break; case 0xc4: /* pinsrw */ case 0x1c4: @@ -3106,7 +3110,7 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r) gen_op_pextrw_mmx(offsetof(CPUX86State,fpregs[rm].mmx), val); } reg = ((modrm >> 3) & 7) | rex_r; - gen_op_mov_reg_T0[OT_LONG][reg](); + gen_op_mov_reg_T0(OT_LONG, reg); break; case 0x1d6: /* movq ea, xmm */ if (mod != 3) { @@ -3144,7 +3148,7 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r) gen_op_pmovmskb_mmx(offsetof(CPUX86State,fpregs[rm].mmx)); } reg = ((modrm >> 3) & 7) | rex_r; - gen_op_mov_reg_T0[OT_LONG][reg](); + gen_op_mov_reg_T0(OT_LONG, reg); break; default: goto illegal_op; @@ -3158,11 +3162,11 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r) goto illegal_op; #ifdef TARGET_X86_64 if (s->aflag == 2) { - gen_op_movq_A0_reg[R_EDI](); + gen_op_movq_A0_reg(R_EDI); } else #endif { - gen_op_movl_A0_reg[R_EDI](); + gen_op_movl_A0_reg(R_EDI); if (s->aflag == 0) gen_op_andl_A0_ffff(); } @@ -3186,7 +3190,7 @@ static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r) /* specific case for SSE single instructions */ if (b1 == 2) { /* 32 bit access */ - gen_op_ld_T0_A0[OT_LONG + s->mem_index](); + gen_op_ld_T0_A0(OT_LONG + s->mem_index); gen_op_movl_env_T0(offsetof(CPUX86State,xmm_t0.XMM_L(0))); } else { /* 64 bit access */ @@ -3412,13 +3416,13 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) /* xor reg, reg optimisation */ gen_op_movl_T0_0(); s->cc_op = CC_OP_LOGICB + ot; - gen_op_mov_reg_T0[ot][reg](); + gen_op_mov_reg_T0(ot, reg); gen_op_update1_cc(); break; } else { opreg = rm; } - gen_op_mov_TN_reg[ot][1][reg](); + gen_op_mov_TN_reg(ot, 1, reg); gen_op(s, op, ot, opreg); break; case 1: /* OP Gv, Ev */ @@ -3428,11 +3432,11 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) rm = (modrm & 7) | REX_B(s); if (mod != 3) { gen_lea_modrm(s, modrm, ®_addr, &offset_addr); - gen_op_ld_T1_A0[ot + s->mem_index](); + gen_op_ld_T1_A0(ot + s->mem_index); } else if (op == OP_XORL && rm == reg) { goto xor_zero; } else { - gen_op_mov_TN_reg[ot][1][rm](); + gen_op_mov_TN_reg(ot, 1, rm); } gen_op(s, op, ot, reg); break; @@ -3514,9 +3518,9 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) if (op == 0) s->rip_offset = insn_const_size(ot); gen_lea_modrm(s, modrm, ®_addr, &offset_addr); - gen_op_ld_T0_A0[ot + s->mem_index](); + gen_op_ld_T0_A0(ot + s->mem_index); } else { - gen_op_mov_TN_reg[ot][0][rm](); + gen_op_mov_TN_reg(ot, 0, rm); } switch(op) { @@ -3529,17 +3533,17 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) case 2: /* not */ gen_op_notl_T0(); if (mod != 3) { - gen_op_st_T0_A0[ot + s->mem_index](); + gen_op_st_T0_A0(ot + s->mem_index); } else { - gen_op_mov_reg_T0[ot][rm](); + gen_op_mov_reg_T0(ot, rm); } break; case 3: /* neg */ gen_op_negl_T0(); if (mod != 3) { - gen_op_st_T0_A0[ot + s->mem_index](); + gen_op_st_T0_A0(ot + s->mem_index); } else { - gen_op_mov_reg_T0[ot][rm](); + gen_op_mov_reg_T0(ot, rm); } gen_op_update_neg_cc(); s->cc_op = CC_OP_SUBB + ot; @@ -3603,7 +3607,12 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) default: case OT_LONG: gen_jmp_im(pc_start - s->cs_base); - gen_op_divl_EAX_T0(); +#ifdef MACRO_TEST + /* XXX: this is just a test */ + tcg_gen_macro_2(cpu_T[0], cpu_T[0], MACRO_TEST); +#else + tcg_gen_helper_0_1(helper_divl_EAX_T0, cpu_T[0]); +#endif break; #ifdef TARGET_X86_64 case OT_QUAD: @@ -3626,7 +3635,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) default: case OT_LONG: gen_jmp_im(pc_start - s->cs_base); - gen_op_idivl_EAX_T0(); + tcg_gen_helper_0_1(helper_idivl_EAX_T0, cpu_T[0]); break; #ifdef TARGET_X86_64 case OT_QUAD: @@ -3671,9 +3680,9 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) if (mod != 3) { gen_lea_modrm(s, modrm, ®_addr, &offset_addr); if (op >= 2 && op != 3 && op != 5) - gen_op_ld_T0_A0[ot + s->mem_index](); + gen_op_ld_T0_A0(ot + s->mem_index); } else { - gen_op_mov_TN_reg[ot][0][rm](); + gen_op_mov_TN_reg(ot, 0, rm); } switch(op) { @@ -3702,9 +3711,9 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) gen_eob(s); break; case 3: /* lcall Ev */ - gen_op_ld_T1_A0[ot + s->mem_index](); + gen_op_ld_T1_A0(ot + s->mem_index); gen_add_A0_im(s, 1 << (ot - OT_WORD + 1)); - gen_op_ldu_T0_A0[OT_WORD + s->mem_index](); + gen_op_ldu_T0_A0(OT_WORD + s->mem_index); do_lcall: if (s->pe && !s->vm86) { if (s->cc_op != CC_OP_DYNAMIC) @@ -3723,9 +3732,9 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) gen_eob(s); break; case 5: /* ljmp Ev */ - gen_op_ld_T1_A0[ot + s->mem_index](); + gen_op_ld_T1_A0(ot + s->mem_index); gen_add_A0_im(s, 1 << (ot - OT_WORD + 1)); - gen_op_ldu_T0_A0[OT_WORD + s->mem_index](); + gen_op_ldu_T0_A0(OT_WORD + s->mem_index); do_ljmp: if (s->pe && !s->vm86) { if (s->cc_op != CC_OP_DYNAMIC) @@ -3760,7 +3769,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) reg = ((modrm >> 3) & 7) | rex_r; gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0); - gen_op_mov_TN_reg[ot][1][reg](); + gen_op_mov_TN_reg(ot, 1, reg); gen_op_testl_T0_T1_cc(); s->cc_op = CC_OP_LOGICB + ot; break; @@ -3773,7 +3782,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) ot = dflag + OT_WORD; val = insn_get(s, ot); - gen_op_mov_TN_reg[ot][0][OR_EAX](); + gen_op_mov_TN_reg(ot, 0, OR_EAX); gen_op_movl_T1_im(val); gen_op_testl_T0_T1_cc(); s->cc_op = CC_OP_LOGICB + ot; @@ -3819,7 +3828,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) val = (int8_t)insn_get(s, OT_BYTE); gen_op_movl_T1_im(val); } else { - gen_op_mov_TN_reg[ot][1][reg](); + gen_op_mov_TN_reg(ot, 1, reg); } #ifdef TARGET_X86_64 @@ -3832,7 +3841,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) } else { gen_op_imulw_T0_T1(); } - gen_op_mov_reg_T0[ot][reg](); + gen_op_mov_reg_T0(ot, reg); s->cc_op = CC_OP_MULB + ot; break; case 0x1c0: @@ -3846,18 +3855,18 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) mod = (modrm >> 6) & 3; if (mod == 3) { rm = (modrm & 7) | REX_B(s); - gen_op_mov_TN_reg[ot][0][reg](); - gen_op_mov_TN_reg[ot][1][rm](); + gen_op_mov_TN_reg(ot, 0, reg); + gen_op_mov_TN_reg(ot, 1, rm); gen_op_addl_T0_T1(); - gen_op_mov_reg_T1[ot][reg](); - gen_op_mov_reg_T0[ot][rm](); + gen_op_mov_reg_T1(ot, reg); + gen_op_mov_reg_T0(ot, rm); } else { gen_lea_modrm(s, modrm, ®_addr, &offset_addr); - gen_op_mov_TN_reg[ot][0][reg](); - gen_op_ld_T1_A0[ot + s->mem_index](); + gen_op_mov_TN_reg(ot, 0, reg); + gen_op_ld_T1_A0(ot + s->mem_index); gen_op_addl_T0_T1(); - gen_op_st_T0_A0[ot + s->mem_index](); - gen_op_mov_reg_T1[ot][reg](); + gen_op_st_T0_A0(ot + s->mem_index); + gen_op_mov_reg_T1(ot, reg); } gen_op_update2_cc(); s->cc_op = CC_OP_ADDB + ot; @@ -3871,15 +3880,15 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) modrm = ldub_code(s->pc++); reg = ((modrm >> 3) & 7) | rex_r; mod = (modrm >> 6) & 3; - gen_op_mov_TN_reg[ot][1][reg](); + gen_op_mov_TN_reg(ot, 1, reg); if (mod == 3) { rm = (modrm & 7) | REX_B(s); - gen_op_mov_TN_reg[ot][0][rm](); + gen_op_mov_TN_reg(ot, 0, rm); gen_op_cmpxchg_T0_T1_EAX_cc[ot](); - gen_op_mov_reg_T0[ot][rm](); + gen_op_mov_reg_T0(ot, rm); } else { gen_lea_modrm(s, modrm, ®_addr, &offset_addr); - gen_op_ld_T0_A0[ot + s->mem_index](); + gen_op_ld_T0_A0(ot + s->mem_index); gen_op_cmpxchg_mem_T0_T1_EAX_cc[ot + s->mem_index](); } s->cc_op = CC_OP_SUBB + ot; @@ -3900,7 +3909,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) /**************************/ /* push/pop */ case 0x50 ... 0x57: /* push */ - gen_op_mov_TN_reg[OT_LONG][0][(b & 7) | REX_B(s)](); + gen_op_mov_TN_reg(OT_LONG, 0, (b & 7) | REX_B(s)); gen_push_T0(s); break; case 0x58 ... 0x5f: /* pop */ @@ -3912,7 +3921,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) gen_pop_T0(s); /* NOTE: order is important for pop %sp */ gen_pop_update(s); - gen_op_mov_reg_T0[ot][(b & 7) | REX_B(s)](); + gen_op_mov_reg_T0(ot, (b & 7) | REX_B(s)); break; case 0x60: /* pusha */ if (CODE64(s)) @@ -3951,7 +3960,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) /* NOTE: order is important for pop %sp */ gen_pop_update(s); rm = (modrm & 7) | REX_B(s); - gen_op_mov_reg_T0[ot][rm](); + gen_op_mov_reg_T0(ot, rm); } else { /* NOTE: order is important too for MMU exceptions */ s->popl_esp_hack = 1 << ot; @@ -3972,14 +3981,14 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) case 0xc9: /* leave */ /* XXX: exception not precise (ESP is updated before potential exception) */ if (CODE64(s)) { - gen_op_mov_TN_reg[OT_QUAD][0][R_EBP](); - gen_op_mov_reg_T0[OT_QUAD][R_ESP](); + gen_op_mov_TN_reg(OT_QUAD, 0, R_EBP); + gen_op_mov_reg_T0(OT_QUAD, R_ESP); } else if (s->ss32) { - gen_op_mov_TN_reg[OT_LONG][0][R_EBP](); - gen_op_mov_reg_T0[OT_LONG][R_ESP](); + gen_op_mov_TN_reg(OT_LONG, 0, R_EBP); + gen_op_mov_reg_T0(OT_LONG, R_ESP); } else { - gen_op_mov_TN_reg[OT_WORD][0][R_EBP](); - gen_op_mov_reg_T0[OT_WORD][R_ESP](); + gen_op_mov_TN_reg(OT_WORD, 0, R_EBP); + gen_op_mov_reg_T0(OT_WORD, R_ESP); } gen_pop_T0(s); if (CODE64(s)) { @@ -3987,7 +3996,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) } else { ot = dflag + OT_WORD; } - gen_op_mov_reg_T0[ot][R_EBP](); + gen_op_mov_reg_T0(ot, R_EBP); gen_pop_update(s); break; case 0x06: /* push es */ @@ -4066,9 +4075,9 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) val = insn_get(s, ot); gen_op_movl_T0_im(val); if (mod != 3) - gen_op_st_T0_A0[ot + s->mem_index](); + gen_op_st_T0_A0(ot + s->mem_index); else - gen_op_mov_reg_T0[ot][(modrm & 7) | REX_B(s)](); + gen_op_mov_reg_T0(ot, (modrm & 7) | REX_B(s)); break; case 0x8a: case 0x8b: /* mov Ev, Gv */ @@ -4080,7 +4089,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) reg = ((modrm >> 3) & 7) | rex_r; gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0); - gen_op_mov_reg_T0[ot][reg](); + gen_op_mov_reg_T0(ot, reg); break; case 0x8e: /* mov seg, Gv */ modrm = ldub_code(s->pc++); @@ -4132,7 +4141,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) rm = (modrm & 7) | REX_B(s); if (mod == 3) { - gen_op_mov_TN_reg[ot][0][rm](); + gen_op_mov_TN_reg(ot, 0, rm); switch(ot | (b & 8)) { case OT_BYTE: gen_op_movzbl_T0_T0(); @@ -4148,15 +4157,15 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) gen_op_movswl_T0_T0(); break; } - gen_op_mov_reg_T0[d_ot][reg](); + gen_op_mov_reg_T0(d_ot, reg); } else { gen_lea_modrm(s, modrm, ®_addr, &offset_addr); if (b & 8) { - gen_op_lds_T0_A0[ot + s->mem_index](); + gen_op_lds_T0_A0(ot + s->mem_index); } else { - gen_op_ldu_T0_A0[ot + s->mem_index](); + gen_op_ldu_T0_A0(ot + s->mem_index); } - gen_op_mov_reg_T0[d_ot][reg](); + gen_op_mov_reg_T0(d_ot, reg); } } break; @@ -4174,7 +4183,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) s->addseg = 0; gen_lea_modrm(s, modrm, ®_addr, &offset_addr); s->addseg = val; - gen_op_mov_reg_A0[ot - OT_WORD][reg](); + gen_op_mov_reg_A0(ot - OT_WORD, reg); break; case 0xa0: /* mov EAX, Ov */ @@ -4192,10 +4201,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) if (s->aflag == 2) { offset_addr = ldq_code(s->pc); s->pc += 8; - if (offset_addr == (int32_t)offset_addr) - gen_op_movq_A0_im(offset_addr); - else - gen_op_movq_A0_im64(offset_addr >> 32, offset_addr); + gen_op_movq_A0_im(offset_addr); } else #endif { @@ -4208,35 +4214,35 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) } gen_add_A0_ds_seg(s); if ((b & 2) == 0) { - gen_op_ld_T0_A0[ot + s->mem_index](); - gen_op_mov_reg_T0[ot][R_EAX](); + gen_op_ld_T0_A0(ot + s->mem_index); + gen_op_mov_reg_T0(ot, R_EAX); } else { - gen_op_mov_TN_reg[ot][0][R_EAX](); - gen_op_st_T0_A0[ot + s->mem_index](); + gen_op_mov_TN_reg(ot, 0, R_EAX); + gen_op_st_T0_A0(ot + s->mem_index); } } break; case 0xd7: /* xlat */ #ifdef TARGET_X86_64 if (s->aflag == 2) { - gen_op_movq_A0_reg[R_EBX](); + gen_op_movq_A0_reg(R_EBX); gen_op_addq_A0_AL(); } else #endif { - gen_op_movl_A0_reg[R_EBX](); + gen_op_movl_A0_reg(R_EBX); gen_op_addl_A0_AL(); if (s->aflag == 0) gen_op_andl_A0_ffff(); } gen_add_A0_ds_seg(s); - gen_op_ldu_T0_A0[OT_BYTE + s->mem_index](); - gen_op_mov_reg_T0[OT_BYTE][R_EAX](); + gen_op_ldu_T0_A0(OT_BYTE + s->mem_index); + gen_op_mov_reg_T0(OT_BYTE, R_EAX); break; case 0xb0 ... 0xb7: /* mov R, Ib */ val = insn_get(s, OT_BYTE); gen_op_movl_T0_im(val); - gen_op_mov_reg_T0[OT_BYTE][(b & 7) | REX_B(s)](); + gen_op_mov_reg_T0(OT_BYTE, (b & 7) | REX_B(s)); break; case 0xb8 ... 0xbf: /* mov R, Iv */ #ifdef TARGET_X86_64 @@ -4247,7 +4253,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) s->pc += 8; reg = (b & 7) | REX_B(s); gen_movtl_T0_im(tmp); - gen_op_mov_reg_T0[OT_QUAD][reg](); + gen_op_mov_reg_T0(OT_QUAD, reg); } else #endif { @@ -4255,7 +4261,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) val = insn_get(s, ot); reg = (b & 7) | REX_B(s); gen_op_movl_T0_im(val); - gen_op_mov_reg_T0[ot][reg](); + gen_op_mov_reg_T0(ot, reg); } break; @@ -4276,21 +4282,21 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) if (mod == 3) { rm = (modrm & 7) | REX_B(s); do_xchg_reg: - gen_op_mov_TN_reg[ot][0][reg](); - gen_op_mov_TN_reg[ot][1][rm](); - gen_op_mov_reg_T0[ot][rm](); - gen_op_mov_reg_T1[ot][reg](); + gen_op_mov_TN_reg(ot, 0, reg); + gen_op_mov_TN_reg(ot, 1, rm); + gen_op_mov_reg_T0(ot, rm); + gen_op_mov_reg_T1(ot, reg); } else { gen_lea_modrm(s, modrm, ®_addr, &offset_addr); - gen_op_mov_TN_reg[ot][0][reg](); + gen_op_mov_TN_reg(ot, 0, reg); /* for xchg, lock is implicit */ if (!(prefixes & PREFIX_LOCK)) gen_op_lock(); - gen_op_ld_T1_A0[ot + s->mem_index](); - gen_op_st_T0_A0[ot + s->mem_index](); + gen_op_ld_T1_A0(ot + s->mem_index); + gen_op_st_T0_A0(ot + s->mem_index); if (!(prefixes & PREFIX_LOCK)) gen_op_unlock(); - gen_op_mov_reg_T1[ot][reg](); + gen_op_mov_reg_T1(ot, reg); } break; case 0xc4: /* les Gv */ @@ -4319,13 +4325,13 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) if (mod == 3) goto illegal_op; gen_lea_modrm(s, modrm, ®_addr, &offset_addr); - gen_op_ld_T1_A0[ot + s->mem_index](); + gen_op_ld_T1_A0(ot + s->mem_index); gen_add_A0_im(s, 1 << (ot - OT_WORD + 1)); /* load the segment first to handle exceptions properly */ - gen_op_ldu_T0_A0[OT_WORD + s->mem_index](); + gen_op_ldu_T0_A0(OT_WORD + s->mem_index); gen_movl_seg_T0(s, op, pc_start - s->cs_base); /* then put the data */ - gen_op_mov_reg_T1[ot][reg](); + gen_op_mov_reg_T1(ot, reg); if (s->is_jmp) { gen_jmp_im(s->pc - s->cs_base); gen_eob(s); @@ -4405,11 +4411,11 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) if (mod != 3) { gen_lea_modrm(s, modrm, ®_addr, &offset_addr); - gen_op_ld_T0_A0[ot + s->mem_index](); + gen_op_ld_T0_A0(ot + s->mem_index); } else { - gen_op_mov_TN_reg[ot][0][rm](); + gen_op_mov_TN_reg(ot, 0, rm); } - gen_op_mov_TN_reg[ot][1][reg](); + gen_op_mov_TN_reg(ot, 1, reg); if (shift) { val = ldub_code(s->pc++); @@ -4437,7 +4443,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */ } if (mod == 3) { - gen_op_mov_reg_T0[ot][rm](); + gen_op_mov_reg_T0(ot, rm); } break; @@ -4969,7 +4975,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) else ot = dflag ? OT_LONG : OT_WORD; gen_check_io(s, ot, 1, pc_start - s->cs_base); - gen_op_mov_TN_reg[OT_WORD][0][R_EDX](); + gen_op_mov_TN_reg(OT_WORD, 0, R_EDX); gen_op_andl_T0_ffff(); if (gen_svm_check_io(s, pc_start, SVM_IOIO_TYPE_MASK | (1 << (4+ot)) | @@ -4988,7 +4994,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) else ot = dflag ? OT_LONG : OT_WORD; gen_check_io(s, ot, 1, pc_start - s->cs_base); - gen_op_mov_TN_reg[OT_WORD][0][R_EDX](); + gen_op_mov_TN_reg(OT_WORD, 0, R_EDX); gen_op_andl_T0_ffff(); if (gen_svm_check_io(s, pc_start, (1 << (4+ot)) | svm_is_rep(prefixes) | @@ -5018,7 +5024,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) (1 << (4+ot)))) break; gen_op_in[ot](); - gen_op_mov_reg_T1[ot][R_EAX](); + gen_op_mov_reg_T1(ot, R_EAX); break; case 0xe6: case 0xe7: @@ -5032,7 +5038,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) if (gen_svm_check_io(s, pc_start, svm_is_rep(prefixes) | (1 << (4+ot)))) break; - gen_op_mov_TN_reg[ot][1][R_EAX](); + gen_op_mov_TN_reg(ot, 1, R_EAX); gen_op_out[ot](); break; case 0xec: @@ -5041,7 +5047,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) ot = OT_BYTE; else ot = dflag ? OT_LONG : OT_WORD; - gen_op_mov_TN_reg[OT_WORD][0][R_EDX](); + gen_op_mov_TN_reg(OT_WORD, 0, R_EDX); gen_op_andl_T0_ffff(); gen_check_io(s, ot, 0, pc_start - s->cs_base); if (gen_svm_check_io(s, pc_start, @@ -5049,7 +5055,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) (1 << (4+ot)))) break; gen_op_in[ot](); - gen_op_mov_reg_T1[ot][R_EAX](); + gen_op_mov_reg_T1(ot, R_EAX); break; case 0xee: case 0xef: @@ -5057,13 +5063,13 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) ot = OT_BYTE; else ot = dflag ? OT_LONG : OT_WORD; - gen_op_mov_TN_reg[OT_WORD][0][R_EDX](); + gen_op_mov_TN_reg(OT_WORD, 0, R_EDX); gen_op_andl_T0_ffff(); gen_check_io(s, ot, 0, pc_start - s->cs_base); if (gen_svm_check_io(s, pc_start, svm_is_rep(prefixes) | (1 << (4+ot)))) break; - gen_op_mov_TN_reg[ot][1][R_EAX](); + gen_op_mov_TN_reg(ot, 1, R_EAX); gen_op_out[ot](); break; @@ -5101,7 +5107,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) } else { gen_stack_A0(s); /* pop offset */ - gen_op_ld_T0_A0[1 + s->dflag + s->mem_index](); + gen_op_ld_T0_A0(1 + s->dflag + s->mem_index); if (s->dflag == 0) gen_op_andl_T0_ffff(); /* NOTE: keeping EIP updated is not a problem in case of @@ -5109,7 +5115,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) gen_op_jmp_T0(); /* pop selector */ gen_op_addl_A0_im(2 << s->dflag); - gen_op_ld_T0_A0[1 + s->dflag + s->mem_index](); + gen_op_ld_T0_A0(1 + s->dflag + s->mem_index); gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[R_CS])); /* add stack offset */ gen_stack_update(s, val + (4 << s->dflag)); @@ -5232,10 +5238,10 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) gen_setcc(s, b); if (mod != 3) { gen_lea_modrm(s, modrm, ®_addr, &offset_addr); - gen_op_ld_T1_A0[ot + s->mem_index](); + gen_op_ld_T1_A0(ot + s->mem_index); } else { rm = (modrm & 7) | REX_B(s); - gen_op_mov_TN_reg[ot][1][rm](); + gen_op_mov_TN_reg(ot, 1, rm); } gen_op_cmov_reg_T1_T0[ot - OT_WORD][reg](); break; @@ -5292,7 +5298,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) case 0x9e: /* sahf */ if (CODE64(s)) goto illegal_op; - gen_op_mov_TN_reg[OT_BYTE][0][R_AH](); + gen_op_mov_TN_reg(OT_BYTE, 0, R_AH); if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); gen_op_movb_eflags_T0(); @@ -5304,7 +5310,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); gen_op_movl_T0_eflags(); - gen_op_mov_reg_T0[OT_BYTE][R_AH](); + gen_op_mov_reg_T0(OT_BYTE, R_AH); break; case 0xf5: /* cmc */ if (s->cc_op != CC_OP_DYNAMIC) @@ -5342,9 +5348,9 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) if (mod != 3) { s->rip_offset = 1; gen_lea_modrm(s, modrm, ®_addr, &offset_addr); - gen_op_ld_T0_A0[ot + s->mem_index](); + gen_op_ld_T0_A0(ot + s->mem_index); } else { - gen_op_mov_TN_reg[ot][0][rm](); + gen_op_mov_TN_reg(ot, 0, rm); } /* load shift */ val = ldub_code(s->pc++); @@ -5356,9 +5362,9 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) s->cc_op = CC_OP_SARB + ot; if (op != 0) { if (mod != 3) - gen_op_st_T0_A0[ot + s->mem_index](); + gen_op_st_T0_A0(ot + s->mem_index); else - gen_op_mov_reg_T0[ot][rm](); + gen_op_mov_reg_T0(ot, rm); gen_op_update_bt_cc(); } break; @@ -5379,22 +5385,22 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) reg = ((modrm >> 3) & 7) | rex_r; mod = (modrm >> 6) & 3; rm = (modrm & 7) | REX_B(s); - gen_op_mov_TN_reg[OT_LONG][1][reg](); + gen_op_mov_TN_reg(OT_LONG, 1, reg); if (mod != 3) { gen_lea_modrm(s, modrm, ®_addr, &offset_addr); /* specific case: we need to add a displacement */ gen_op_add_bit_A0_T1[ot - OT_WORD](); - gen_op_ld_T0_A0[ot + s->mem_index](); + gen_op_ld_T0_A0(ot + s->mem_index); } else { - gen_op_mov_TN_reg[ot][0][rm](); + gen_op_mov_TN_reg(ot, 0, rm); } gen_op_btx_T0_T1_cc[ot - OT_WORD][op](); s->cc_op = CC_OP_SARB + ot; if (op != 0) { if (mod != 3) - gen_op_st_T0_A0[ot + s->mem_index](); + gen_op_st_T0_A0(ot + s->mem_index); else - gen_op_mov_reg_T0[ot][rm](); + gen_op_mov_reg_T0(ot, rm); gen_op_update_bt_cc(); } break; @@ -5406,9 +5412,9 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0); /* NOTE: in order to handle the 0 case, we must load the result. It could be optimized with a generated jump */ - gen_op_mov_TN_reg[ot][1][reg](); + gen_op_mov_TN_reg(ot, 1, reg); gen_op_bsx_T0_cc[ot - OT_WORD][b & 1](); - gen_op_mov_reg_T1[ot][reg](); + gen_op_mov_reg_T1(ot, reg); s->cc_op = CC_OP_LOGICB + ot; break; /************************/ @@ -5569,7 +5575,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) mod = (modrm >> 6) & 3; if (mod == 3) goto illegal_op; - gen_op_mov_TN_reg[ot][0][reg](); + gen_op_mov_TN_reg(ot, 0, reg); gen_lea_modrm(s, modrm, ®_addr, &offset_addr); gen_jmp_im(pc_start - s->cs_base); if (ot == OT_WORD) @@ -5581,16 +5587,27 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) reg = (b & 7) | REX_B(s); #ifdef TARGET_X86_64 if (dflag == 2) { - gen_op_mov_TN_reg[OT_QUAD][0][reg](); - gen_op_bswapq_T0(); - gen_op_mov_reg_T0[OT_QUAD][reg](); + gen_op_mov_TN_reg(OT_QUAD, 0, reg); + tcg_gen_bswap_i64(cpu_T[0], cpu_T[0]); + gen_op_mov_reg_T0(OT_QUAD, reg); } else -#endif { - gen_op_mov_TN_reg[OT_LONG][0][reg](); - gen_op_bswapl_T0(); - gen_op_mov_reg_T0[OT_LONG][reg](); + int tmp0; + gen_op_mov_TN_reg(OT_LONG, 0, reg); + + tmp0 = tcg_temp_new(TCG_TYPE_I32); + tcg_gen_trunc_i64_i32(tmp0, cpu_T[0]); + tcg_gen_bswap_i32(tmp0, tmp0); + tcg_gen_extu_i32_i64(cpu_T[0], tmp0); + gen_op_mov_reg_T0(OT_LONG, reg); + } +#else + { + gen_op_mov_TN_reg(OT_LONG, 0, reg); + tcg_gen_bswap_i32(cpu_T[0], cpu_T[0]); + gen_op_mov_reg_T0(OT_LONG, reg); } +#endif break; case 0xd6: /* salc */ if (CODE64(s)) @@ -5821,12 +5838,12 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) break; gen_lea_modrm(s, modrm, ®_addr, &offset_addr); gen_op_movl_T0_env(offsetof(CPUX86State, gdt.limit)); - gen_op_st_T0_A0[OT_WORD + s->mem_index](); + gen_op_st_T0_A0(OT_WORD + s->mem_index); gen_add_A0_im(s, 2); gen_op_movtl_T0_env(offsetof(CPUX86State, gdt.base)); if (!s->dflag) gen_op_andl_T0_im(0xffffff); - gen_op_st_T0_A0[CODE64(s) + OT_LONG + s->mem_index](); + gen_op_st_T0_A0(CODE64(s) + OT_LONG + s->mem_index); break; case 1: if (mod == 3) { @@ -5840,12 +5857,12 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) gen_jmp_im(pc_start - s->cs_base); #ifdef TARGET_X86_64 if (s->aflag == 2) { - gen_op_movq_A0_reg[R_EBX](); + gen_op_movq_A0_reg(R_EBX); gen_op_addq_A0_AL(); } else #endif { - gen_op_movl_A0_reg[R_EBX](); + gen_op_movl_A0_reg(R_EBX); gen_op_addl_A0_AL(); if (s->aflag == 0) gen_op_andl_A0_ffff(); @@ -5875,12 +5892,12 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) break; gen_lea_modrm(s, modrm, ®_addr, &offset_addr); gen_op_movl_T0_env(offsetof(CPUX86State, idt.limit)); - gen_op_st_T0_A0[OT_WORD + s->mem_index](); + gen_op_st_T0_A0(OT_WORD + s->mem_index); gen_add_A0_im(s, 2); gen_op_movtl_T0_env(offsetof(CPUX86State, idt.base)); if (!s->dflag) gen_op_andl_T0_im(0xffffff); - gen_op_st_T0_A0[CODE64(s) + OT_LONG + s->mem_index](); + gen_op_st_T0_A0(CODE64(s) + OT_LONG + s->mem_index); } break; case 2: /* lgdt */ @@ -5943,9 +5960,9 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) op==2 ? SVM_EXIT_GDTR_WRITE : SVM_EXIT_IDTR_WRITE)) break; gen_lea_modrm(s, modrm, ®_addr, &offset_addr); - gen_op_ld_T1_A0[OT_WORD + s->mem_index](); + gen_op_ld_T1_A0(OT_WORD + s->mem_index); gen_add_A0_im(s, 2); - gen_op_ld_T0_A0[CODE64(s) + OT_LONG + s->mem_index](); + gen_op_ld_T0_A0(CODE64(s) + OT_LONG + s->mem_index); if (!s->dflag) gen_op_andl_T0_im(0xffffff); if (op == 2) { @@ -6029,19 +6046,19 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) rm = (modrm & 7) | REX_B(s); if (mod == 3) { - gen_op_mov_TN_reg[OT_LONG][0][rm](); + gen_op_mov_TN_reg(OT_LONG, 0, rm); /* sign extend */ if (d_ot == OT_QUAD) gen_op_movslq_T0_T0(); - gen_op_mov_reg_T0[d_ot][reg](); + gen_op_mov_reg_T0(d_ot, reg); } else { gen_lea_modrm(s, modrm, ®_addr, &offset_addr); if (d_ot == OT_QUAD) { - gen_op_lds_T0_A0[OT_LONG + s->mem_index](); + gen_op_lds_T0_A0(OT_LONG + s->mem_index); } else { - gen_op_ld_T0_A0[OT_LONG + s->mem_index](); + gen_op_ld_T0_A0(OT_LONG + s->mem_index); } - gen_op_mov_reg_T0[d_ot][reg](); + gen_op_mov_reg_T0(d_ot, reg); } } else #endif @@ -6055,18 +6072,18 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) rm = modrm & 7; if (mod != 3) { gen_lea_modrm(s, modrm, ®_addr, &offset_addr); - gen_op_ld_T0_A0[ot + s->mem_index](); + gen_op_ld_T0_A0(ot + s->mem_index); } else { - gen_op_mov_TN_reg[ot][0][rm](); + gen_op_mov_TN_reg(ot, 0, rm); } if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); gen_op_arpl(); s->cc_op = CC_OP_EFLAGS; if (mod != 3) { - gen_op_st_T0_A0[ot + s->mem_index](); + gen_op_st_T0_A0(ot + s->mem_index); } else { - gen_op_mov_reg_T0[ot][rm](); + gen_op_mov_reg_T0(ot, rm); } gen_op_arpl_update(); } @@ -6079,7 +6096,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) modrm = ldub_code(s->pc++); reg = ((modrm >> 3) & 7) | rex_r; gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0); - gen_op_mov_TN_reg[ot][1][reg](); + gen_op_mov_TN_reg(ot, 1, reg); if (s->cc_op != CC_OP_DYNAMIC) gen_op_set_cc_op(s->cc_op); if (b == 0x102) @@ -6087,7 +6104,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) else gen_op_lsl(); s->cc_op = CC_OP_EFLAGS; - gen_op_mov_reg_T1[ot][reg](); + gen_op_mov_reg_T1(ot, reg); break; case 0x118: modrm = ldub_code(s->pc++); @@ -6134,7 +6151,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) case 8: if (b & 2) { gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_CR0 + reg); - gen_op_mov_TN_reg[ot][0][rm](); + gen_op_mov_TN_reg(ot, 0, rm); gen_op_movl_crN_T0(reg); gen_jmp_im(s->pc - s->cs_base); gen_eob(s); @@ -6146,7 +6163,7 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) else #endif gen_op_movtl_T0_env(offsetof(CPUX86State,cr[reg])); - gen_op_mov_reg_T0[ot][rm](); + gen_op_mov_reg_T0(ot, rm); } break; default: @@ -6173,14 +6190,14 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) goto illegal_op; if (b & 2) { gen_svm_check_intercept(s, pc_start, SVM_EXIT_WRITE_DR0 + reg); - gen_op_mov_TN_reg[ot][0][rm](); + gen_op_mov_TN_reg(ot, 0, rm); gen_op_movl_drN_T0(reg); gen_jmp_im(s->pc - s->cs_base); gen_eob(s); } else { gen_svm_check_intercept(s, pc_start, SVM_EXIT_READ_DR0 + reg); gen_op_movtl_T0_env(offsetof(CPUX86State,dr[reg])); - gen_op_mov_reg_T0[ot][rm](); + gen_op_mov_reg_T0(ot, rm); } } break; @@ -6246,11 +6263,11 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) goto illegal_op; gen_lea_modrm(s, modrm, ®_addr, &offset_addr); if (op == 2) { - gen_op_ld_T0_A0[OT_LONG + s->mem_index](); + gen_op_ld_T0_A0(OT_LONG + s->mem_index); gen_op_movl_env_T0(offsetof(CPUX86State, mxcsr)); } else { gen_op_movl_T0_env(offsetof(CPUX86State, mxcsr)); - gen_op_st_T0_A0[OT_LONG + s->mem_index](); + gen_op_st_T0_A0(OT_LONG + s->mem_index); } break; case 5: /* lfence */ @@ -6647,6 +6664,17 @@ static uint16_t opc_simpler[NB_OPS] = { #endif }; +static void tcg_macro_func(TCGContext *s, int macro_id, const int *dead_args) +{ + switch(macro_id) { +#ifdef MACRO_TEST + case MACRO_TEST: + tcg_gen_helper_0_1(helper_divl_EAX_T0, cpu_T[0]); + break; +#endif + } +} + void optimize_flags_init(void) { int i; @@ -6655,6 +6683,25 @@ void optimize_flags_init(void) if (opc_simpler[i] == 0) opc_simpler[i] = i; } + + tcg_set_macro_func(&tcg_ctx, tcg_macro_func); + + cpu_env = tcg_global_reg_new(TCG_TYPE_PTR, TCG_AREG0, "env"); +#if TARGET_LONG_BITS > HOST_LONG_BITS + cpu_T[0] = tcg_global_mem_new(TCG_TYPE_TL, + TCG_AREG0, offsetof(CPUState, t0), "T0"); + cpu_T[1] = tcg_global_mem_new(TCG_TYPE_TL, + TCG_AREG0, offsetof(CPUState, t1), "T1"); + cpu_A0 = tcg_global_mem_new(TCG_TYPE_TL, + TCG_AREG0, offsetof(CPUState, t2), "A0"); +#else + cpu_T[0] = tcg_global_reg_new(TCG_TYPE_TL, TCG_AREG1, "T0"); + cpu_T[1] = tcg_global_reg_new(TCG_TYPE_TL, TCG_AREG2, "T1"); + cpu_A0 = tcg_global_reg_new(TCG_TYPE_TL, TCG_AREG3, "A0"); +#endif + /* the helpers are only registered to print debug info */ + TCG_HELPER(helper_divl_EAX_T0); + TCG_HELPER(helper_idivl_EAX_T0); } /* CPU flags computation optimization: we move backward thru the @@ -6746,10 +6793,9 @@ static inline int gen_intermediate_code_internal(CPUState *env, printf("ERROR addseg\n"); #endif - gen_opc_ptr = gen_opc_buf; + cpu_tmp0 = tcg_temp_new(TCG_TYPE_TL); + gen_opc_end = gen_opc_buf + OPC_MAX_SIZE; - gen_opparam_ptr = gen_opparam_buf; - nb_gen_labels = 0; dc->is_jmp = DISAS_NEXT; pc_ptr = pc_start; @@ -6824,9 +6870,9 @@ static inline int gen_intermediate_code_internal(CPUState *env, disas_flags = !dc->code32; target_disas(logfile, pc_start, pc_ptr - pc_start, disas_flags); fprintf(logfile, "\n"); - if (loglevel & CPU_LOG_TB_OP) { - fprintf(logfile, "OP:\n"); - dump_ops(gen_opc_buf, gen_opparam_buf); + if (loglevel & CPU_LOG_TB_OP_OPT) { + fprintf(logfile, "OP before opt:\n"); + tcg_dump_ops(&tcg_ctx, logfile); fprintf(logfile, "\n"); } } @@ -6835,13 +6881,6 @@ static inline int gen_intermediate_code_internal(CPUState *env, /* optimize flag computations */ optimize_flags(gen_opc_buf, gen_opc_ptr - gen_opc_buf); -#ifdef DEBUG_DISAS - if (loglevel & CPU_LOG_TB_OP_OPT) { - fprintf(logfile, "AFTER FLAGS OPT:\n"); - dump_ops(gen_opc_buf, gen_opparam_buf); - fprintf(logfile, "\n"); - } -#endif if (!search_pc) tb->size = pc_ptr - pc_start; return 0; diff --git a/target-m68k/op.c b/target-m68k/op.c index 140c71d890..b9412d8fcb 100644 --- a/target-m68k/op.c +++ b/target-m68k/op.c @@ -482,7 +482,7 @@ OP(set_sr) FORCE_RET(); } -OP(jmp) +OP(jmp_im) { GOTO_LABEL_PARAM(1); } @@ -522,22 +522,6 @@ OP(jmp_T0) 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. */ OP(f64_to_i32) { diff --git a/target-m68k/translate.c b/target-m68k/translate.c index 68f39aab75..39816f4b2a 100644 --- a/target-m68k/translate.c +++ b/target-m68k/translate.c @@ -28,6 +28,7 @@ #include "cpu.h" #include "exec-all.h" #include "disas.h" +#include "tcg-op.h" #include "m68k-qreg.h" //#define DEBUG_DISPATCH 1 @@ -67,20 +68,9 @@ typedef struct DisasContext { static void *gen_throws_exception; #define gen_last_qop NULL -static uint16_t *gen_opc_ptr; -static uint32_t *gen_opparam_ptr; extern FILE *logfile; 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) #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) @@ -622,7 +612,7 @@ static void gen_jmpcc(DisasContext *s, int cond, int l1) gen_flush_flags(s); switch (cond) { case 0: /* T */ - gen_op_jmp(l1); + gen_op_jmp_im(l1); break; case 1: /* F */ 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_and32(tmp, tmp, gen_im32(CCF_V)); gen_op_jmp_nz32(tmp, l2); - gen_op_jmp(l1); + gen_op_jmp_im(l1); gen_set_label(l2); } break; @@ -791,14 +781,12 @@ static void gen_jmp_tb(DisasContext *s, int n, uint32_t dest) gen_exception(s, dest, EXCP_DEBUG); } else if ((tb->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_T0, gen_im32((long)tb + n)); - gen_op_exit_tb(); + tcg_gen_exit_tb((long)tb + n); } else { gen_jmp(s, gen_im32(dest)); - gen_op_mov32(QREG_T0, gen_im32(0)); - gen_op_exit_tb(); + tcg_gen_exit_tb(0); } 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_mov32(QREG_CC_OP, gen_im32(CC_OP_ADDX)); gen_op_set_leu32(QREG_CC_X, arg0, arg1); - gen_op_jmp(l2); + gen_op_jmp_im(l2); gen_set_label(l1); gen_op_mov32(QREG_CC_OP, gen_im32(CC_OP_ADD)); 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_sub32(arg0, arg0, gen_im32(1)); 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_op_set_ltu32(QREG_CC_X, arg0, arg1); 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; - gen_opc_ptr = gen_opc_buf; gen_opc_end = gen_opc_buf + OPC_MAX_SIZE; - gen_opparam_ptr = gen_opparam_buf; dc->env = env; dc->is_jmp = DISAS_NEXT; @@ -3174,7 +3160,6 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb, dc->fpcr = env->fpcr; dc->user = (env->sr & SR_S) == 0; dc->is_mem = 0; - nb_gen_labels = 0; lj = -1; do { free_qreg = 0; @@ -3232,8 +3217,7 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb, case DISAS_UPDATE: gen_flush_cc_op(dc); /* indicate that the hash table must be used to find the next TB */ - gen_op_mov32(QREG_T0, gen_im32(0)); - gen_op_exit_tb(); + tcg_gen_exit_tb(0); break; case DISAS_TB_JUMP: /* 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)); target_disas(logfile, pc_start, dc->pc - pc_start, 0); 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 if (search_pc) { diff --git a/target-mips/op.c b/target-mips/op.c index cf965fa874..cece7f1f23 100644 --- a/target-mips/op.c +++ b/target-mips/op.c @@ -1093,18 +1093,6 @@ OP_COND(lez, (target_long)T0 <= 0); OP_COND(ltz, (target_long)T0 < 0); /* 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 */ void op_save_breg_target (void) { @@ -3252,12 +3240,6 @@ void op_raise_exception_err (void) FORCE_RET(); } -void op_exit_tb (void) -{ - EXIT_TB(); - FORCE_RET(); -} - void op_wait (void) { env->halted = 1; diff --git a/target-mips/translate.c b/target-mips/translate.c index 719af3ae8f..1231c00cd3 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -29,29 +29,12 @@ #include "cpu.h" #include "exec-all.h" #include "disas.h" +#include "tcg-op.h" //#define MIPS_DEBUG_DISAS //#define MIPS_DEBUG_SIGN_EXTENSIONS //#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 */ #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; tb = ctx->tb; if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) { - if (n == 0) - gen_op_goto_tb0(TBPARAM(tb)); - else - gen_op_goto_tb1(TBPARAM(tb)); + tcg_gen_goto_tb(n); gen_save_pc(dest); - gen_op_set_T0((long)tb + n); + tcg_gen_exit_tb((long)tb + n); } else { gen_save_pc(dest); - gen_op_reset_T0(); + tcg_gen_exit_tb(0); } - gen_op_exit_tb(); } /* Branches (before delay slot) */ @@ -6642,8 +6621,7 @@ static void decode_opc (CPUState *env, DisasContext *ctx) /* unconditional branch to register */ MIPS_DEBUG("branch to register"); gen_op_breg(); - gen_op_reset_T0(); - gen_op_exit_tb(); + tcg_gen_exit_tb(0); break; default: MIPS_DEBUG("unknown branch"); @@ -6665,10 +6643,7 @@ gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb, fprintf (logfile, "search pc %d\n", search_pc); pc_start = tb->pc; - gen_opc_ptr = gen_opc_buf; gen_opc_end = gen_opc_buf + OPC_MAX_SIZE; - gen_opparam_ptr = gen_opparam_buf; - nb_gen_labels = 0; ctx.pc = pc_start; ctx.saved_pc = -1; ctx.tb = tb; @@ -6748,8 +6723,7 @@ gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb, break; case BS_EXCP: gen_op_interrupt_restart(); - gen_op_reset_T0(); - gen_op_exit_tb(); + tcg_gen_exit_tb(0); break; case BS_BRANCH: default: @@ -6777,11 +6751,6 @@ done_generating: target_disas(logfile, pc_start, ctx.pc - pc_start, 0); 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) { fprintf(logfile, "---------------- %d %08x\n", ctx.bstate, ctx.hflags); } diff --git a/target-ppc/op.c b/target-ppc/op.c index c950579a1b..6cda0f0f64 100644 --- a/target-ppc/op.c +++ b/target-ppc/op.c @@ -222,11 +222,6 @@ void OPPROTO op_debug (void) do_raise_exception(EXCP_DEBUG); } -void OPPROTO op_exit_tb (void) -{ - EXIT_TB(); -} - /* Load/store special registers */ void OPPROTO op_load_cr (void) { @@ -674,16 +669,6 @@ void OPPROTO op_setlr_64 (void) } #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) { env->nip = (uint32_t)(T1 & ~3); diff --git a/target-ppc/translate.c b/target-ppc/translate.c index 1313a77362..c9530eb17e 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -26,6 +26,7 @@ #include "cpu.h" #include "exec-all.h" #include "disas.h" +#include "tcg-op.h" /* Include definitions for instructions classes and implementations flags */ //#define DO_SINGLE_STEP @@ -36,28 +37,12 @@ /*****************************************************************************/ /* 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) static uint16_t *gen_fprf_buf[OPC_BUF_SIZE]; static uint16_t **gen_fprf_ptr; #endif -#include "gen-op.h" - static always_inline void gen_set_T0 (target_ulong val) { #if defined(TARGET_PPC64) @@ -2798,11 +2783,9 @@ static always_inline void gen_goto_tb (DisasContext *ctx, int n, { TranslationBlock *tb; tb = ctx->tb; - if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) { - if (n == 0) - gen_op_goto_tb0(TBPARAM(tb)); - else - gen_op_goto_tb1(TBPARAM(tb)); + if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) && + !ctx->singlestep_enabled) { + tcg_gen_goto_tb(n); gen_set_T1(dest); #if defined(TARGET_PPC64) if (ctx->sf_mode) @@ -2810,10 +2793,7 @@ static always_inline void gen_goto_tb (DisasContext *ctx, int n, else #endif gen_op_b_T1(); - gen_op_set_T0((long)tb + n); - if (ctx->singlestep_enabled) - gen_op_debug(); - gen_op_exit_tb(); + tcg_gen_exit_tb((long)tb + n); } else { gen_set_T1(dest); #if defined(TARGET_PPC64) @@ -2822,10 +2802,9 @@ static always_inline void gen_goto_tb (DisasContext *ctx, int n, else #endif gen_op_b_T1(); - gen_op_reset_T0(); if (ctx->singlestep_enabled) 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 #endif gen_op_b_T1(); - gen_op_reset_T0(); goto no_test; } break; @@ -3005,11 +2983,10 @@ static always_inline void gen_bcond (DisasContext *ctx, int type) else #endif gen_op_btest_T1(ctx->nip); - gen_op_reset_T0(); no_test: if (ctx->singlestep_enabled) gen_op_debug(); - gen_op_exit_tb(); + tcg_gen_exit_tb(0); } out: ctx->exception = POWERPC_EXCP_BRANCH; @@ -6176,13 +6153,10 @@ static always_inline int gen_intermediate_code_internal (CPUState *env, int j, lj = -1; pc_start = tb->pc; - gen_opc_ptr = gen_opc_buf; gen_opc_end = gen_opc_buf + OPC_MAX_SIZE; - gen_opparam_ptr = gen_opparam_buf; #if defined(OPTIMIZE_FPRF_UPDATE) gen_fprf_ptr = gen_fprf_buf; #endif - nb_gen_labels = 0; ctx.nip = pc_start; ctx.tb = tb; 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) { gen_goto_tb(&ctx, 0, ctx.nip); } else if (ctx.exception != POWERPC_EXCP_BRANCH) { - gen_op_reset_T0(); /* Generate the return instruction */ - gen_op_exit_tb(); + tcg_gen_exit_tb(0); } *gen_opc_ptr = INDEX_op_end; 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); 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 return 0; } diff --git a/target-sh4/op.c b/target-sh4/op.c index 1004ef4c70..955610a90a 100644 --- a/target-sh4/op.c +++ b/target-sh4/op.c @@ -161,12 +161,6 @@ void OPPROTO op_rts(void) RETURN(); } -void OPPROTO op_exit_tb(void) -{ - EXIT_TB(); - RETURN(); -} - void OPPROTO op_addl_imm_T0(void) { T0 += PARAM1; @@ -947,18 +941,6 @@ void OPPROTO op_movl_FT0_fpul(void) 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) { env->pc = PARAM1; diff --git a/target-sh4/translate.c b/target-sh4/translate.c index 802f926ca2..0c66e0bf53 100644 --- a/target-sh4/translate.c +++ b/target-sh4/translate.c @@ -31,24 +31,7 @@ #include "cpu.h" #include "exec-all.h" #include "disas.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" +#include "tcg-op.h" typedef struct DisasContext { 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) && !ctx->singlestep_enabled) { /* Use a direct jump if in same page and singlestep not enabled */ - if (n == 0) - gen_op_goto_tb0(TBPARAM(tb)); - else - gen_op_goto_tb1(TBPARAM(tb)); - gen_op_movl_imm_T0((long) tb + n); + tcg_gen_goto_tb(n); + gen_op_movl_imm_PC(dest); + tcg_gen_exit_tb((long) tb + n); } 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) @@ -192,10 +172,9 @@ static void gen_jump(DisasContext * ctx) /* Target is not statically known, it comes necessarily from a delayed jump as immediate jump are conditinal jumps */ gen_op_movl_delayed_pc_PC(); - gen_op_movl_imm_T0(0); if (ctx->singlestep_enabled) gen_op_debug(); - gen_op_exit_tb(); + tcg_gen_exit_tb(0); } else { gen_goto_tb(ctx, 0, ctx->delayed_pc); } @@ -1176,9 +1155,7 @@ gen_intermediate_code_internal(CPUState * env, TranslationBlock * tb, int i, ii; pc_start = tb->pc; - gen_opc_ptr = gen_opc_buf; gen_opc_end = gen_opc_buf + OPC_MAX_SIZE; - gen_opparam_ptr = gen_opparam_buf; ctx.pc = pc_start; ctx.flags = (uint32_t)tb->flags; 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.tb = tb; ctx.singlestep_enabled = env->singlestep_enabled; - nb_gen_labels = 0; #ifdef DEBUG_DISAS if (loglevel & CPU_LOG_TB_CPU) { @@ -1254,8 +1230,7 @@ gen_intermediate_code_internal(CPUState * env, TranslationBlock * tb, break; case BS_EXCP: /* gen_op_interrupt_restart(); */ - gen_op_movl_imm_T0(0); - gen_op_exit_tb(); + tcg_gen_exit_tb(0); break; case BS_BRANCH: default: @@ -1283,11 +1258,6 @@ gen_intermediate_code_internal(CPUState * env, TranslationBlock * tb, target_disas(logfile, pc_start, ctx.pc - pc_start, 0); 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 return 0; } diff --git a/target-sparc/op.c b/target-sparc/op.c index 52b824cc7b..1b5b21b760 100644 --- a/target-sparc/op.c +++ b/target-sparc/op.c @@ -1277,11 +1277,6 @@ void OPPROTO op_debug(void) helper_debug(); } -void OPPROTO op_exit_tb(void) -{ - EXIT_TB(); -} - void OPPROTO op_eval_ba(void) { T2 = 1; @@ -1542,16 +1537,6 @@ void OPPROTO op_next_insn(void) 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) { GOTO_LABEL_PARAM(1); diff --git a/target-sparc/translate.c b/target-sparc/translate.c index ecec372723..8286c428df 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -36,6 +36,7 @@ #include "cpu.h" #include "exec-all.h" #include "disas.h" +#include "tcg-op.h" #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 uint16_t *gen_opc_ptr; -static uint32_t *gen_opparam_ptr; extern FILE *logfile; 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 #define GET_FIELD(X, FROM, TO) \ ((X) >> (31 - (TO)) & ((1 << ((TO) - (FROM) + 1)) - 1)) @@ -98,12 +88,6 @@ enum { #define QFPREG(r) (r & 0x1c) #endif -#ifdef USE_DIRECT_JUMP -#define TBPARAM(x) -#else -#define TBPARAM(x) (long)(x) -#endif - static int sign_extend(int x, int 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) && (npc & TARGET_PAGE_MASK) == (tb->pc & TARGET_PAGE_MASK)) { /* jump to same page: we can use a direct jump */ - if (tb_num == 0) - gen_op_goto_tb0(TBPARAM(tb)); - else - gen_op_goto_tb1(TBPARAM(tb)); + tcg_gen_goto_tb(tb_num); gen_jmp_im(pc); gen_movl_npc_im(npc); - gen_op_movl_T0_im((long)tb + tb_num); - gen_op_exit_tb(); + tcg_gen_exit_tb((long)tb + tb_num); } else { /* jump to another page: currently not optimized */ gen_jmp_im(pc); gen_movl_npc_im(npc); - gen_op_movl_T0_0(); - gen_op_exit_tb(); + tcg_gen_exit_tb(0); } } @@ -1281,8 +1260,7 @@ static void disas_sparc_insn(DisasContext * dc) gen_op_trapcc_T0(); } gen_op_next_insn(); - gen_op_movl_T0_0(); - gen_op_exit_tb(); + tcg_gen_exit_tb(0); dc->is_br = 1; goto jmp_insn; } else if (xop == 0x28) { @@ -2341,8 +2319,7 @@ static void disas_sparc_insn(DisasContext * dc) gen_op_movl_env_T0(offsetof(CPUSPARCState, fprs)); save_state(dc); gen_op_next_insn(); - gen_op_movl_T0_0(); - gen_op_exit_tb(); + tcg_gen_exit_tb(0); dc->is_br = 1; break; case 0xf: /* V9 sir, nop if user */ @@ -2422,8 +2399,7 @@ static void disas_sparc_insn(DisasContext * dc) gen_op_wrpsr(); save_state(dc); gen_op_next_insn(); - gen_op_movl_T0_0(); - gen_op_exit_tb(); + tcg_gen_exit_tb(0); dc->is_br = 1; #endif } @@ -2457,8 +2433,7 @@ static void disas_sparc_insn(DisasContext * dc) gen_op_wrpstate(); save_state(dc); gen_op_next_insn(); - gen_op_movl_T0_0(); - gen_op_exit_tb(); + tcg_gen_exit_tb(0); dc->is_br = 1; break; case 7: // tl @@ -2517,8 +2492,7 @@ static void disas_sparc_insn(DisasContext * dc) // XXX gen_op_wrhpstate(); save_state(dc); gen_op_next_insn(); - gen_op_movl_T0_0(); - gen_op_exit_tb(); + tcg_gen_exit_tb(0); dc->is_br = 1; break; case 1: // htstate @@ -3635,10 +3609,7 @@ static inline int gen_intermediate_code_internal(TranslationBlock * tb, dc->npc = (target_ulong) tb->cs_base; dc->mem_idx = cpu_mmu_index(env); dc->fpu_enabled = cpu_fpu_enabled(env); - gen_opc_ptr = gen_opc_buf; gen_opc_end = gen_opc_buf + OPC_MAX_SIZE; - gen_opparam_ptr = gen_opparam_buf; - nb_gen_labels = 0; do { if (env->nb_breakpoints > 0) { @@ -3647,8 +3618,7 @@ static inline int gen_intermediate_code_internal(TranslationBlock * tb, if (dc->pc != pc_start) save_state(dc); gen_op_debug(); - gen_op_movl_T0_0(); - gen_op_exit_tb(); + tcg_gen_exit_tb(0); dc->is_br = 1; goto exit_gen_loop; } @@ -3683,8 +3653,7 @@ static inline int gen_intermediate_code_internal(TranslationBlock * tb, generate an exception */ if (env->singlestep_enabled) { gen_jmp_im(dc->pc); - gen_op_movl_T0_0(); - gen_op_exit_tb(); + tcg_gen_exit_tb(0); break; } } 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) gen_jmp_im(dc->pc); save_npc(dc); - gen_op_movl_T0_0(); - gen_op_exit_tb(); + tcg_gen_exit_tb(0); } } *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)); target_disas(logfile, pc_start, last_pc + 4 - pc_start, 0); 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 return 0; @@ -3746,8 +3709,6 @@ int gen_intermediate_code_pc(CPUSPARCState * env, TranslationBlock * tb) return gen_intermediate_code_internal(tb, 1, env); } -extern int ram_size; - void cpu_reset(CPUSPARCState *env) { tlb_flush(env, 1); diff --git a/translate-all.c b/translate-all.c index d8b91023e6..9639612eb7 100644 --- a/translate-all.c +++ b/translate-all.c @@ -29,22 +29,13 @@ #include "cpu.h" #include "exec-all.h" #include "disas.h" +#include "tcg.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); - -enum { -#define DEF(s, n, copy_size) INDEX_op_ ## s, -#include "opc.h" -#undef DEF - NB_OPS, -}; +/* code generation context */ +TCGContext tcg_ctx; uint16_t gen_opc_buf[OPC_BUF_SIZE]; -uint32_t gen_opparam_buf[OPPARAM_BUF_SIZE]; -long gen_labels[OPC_BUF_SIZE]; -int nb_gen_labels; +TCGArg gen_opparam_buf[OPPARAM_BUF_SIZE]; target_ulong gen_opc_pc[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; -#ifdef DEBUG_DISAS -static const char *op_str[] = { -#define DEF(s, n, copy_size) #s, -#include "opc.h" -#undef DEF -}; - -static uint8_t op_nb_args[] = { -#define DEF(s, n, copy_size) n, -#include "opc.h" -#undef DEF -}; - -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; - } -} - +#ifdef CONFIG_PROFILER +int64_t dyngen_tb_count1; +int64_t dyngen_tb_count; +int64_t dyngen_op_count; +int64_t dyngen_old_op_count; +int64_t dyngen_tcg_del_op_count; +int dyngen_op_count_max; +int64_t dyngen_code_in_len; +int64_t dyngen_code_out_len; +int64_t dyngen_interm_time; +int64_t dyngen_code_time; +int64_t dyngen_restore_count; +int64_t dyngen_restore_time; #endif -/* compute label info */ -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]]; - } -} - +/* XXX: suppress that */ unsigned long code_gen_max_block_size(void) { static unsigned long max; if (max == 0) { #define DEF(s, n, copy_size) max = copy_size > max? copy_size : max; -#include "opc.h" +#include "tcg-opc.h" #undef DEF max *= OPC_MAX_SIZE; } @@ -146,6 +80,13 @@ unsigned long code_gen_max_block_size(void) 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 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) { + TCGContext *s = &tcg_ctx; uint8_t *gen_code_buf; 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) return -1; /* generate machine code */ + gen_code_buf = tb->tc_ptr; tb->tb_next_offset[0] = 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 + s->tb_jmp_offset = tb->tb_jmp_offset; + s->tb_next = NULL; /* the following two entries are optional (only used for string ops) */ + /* XXX: not used ? */ tb->tb_jmp_offset[2] = 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 - NULL, + s->tb_jmp_offset = NULL; + s->tb_next = tb->tb_next; #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; +#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 if (loglevel & CPU_LOG_TB_OUT_ASM) { 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, void *puc) { - int j, c; + TCGContext *s = &tcg_ctx; + int j; 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) return -1; @@ -207,18 +178,19 @@ int cpu_restore_state(TranslationBlock *tb, tc_ptr = (unsigned long)tb->tc_ptr; if (searched_pc < tc_ptr) return -1; - j = 0; - opc_ptr = gen_opc_buf; - for(;;) { - c = *opc_ptr; - if (c == INDEX_op_end) - return -1; - tc_ptr += opc_copy_size[c]; - if (searched_pc < tc_ptr) - break; - opc_ptr++; - } - j = opc_ptr - gen_opc_buf; + + s->tb_next_offset = tb->tb_next_offset; +#ifdef USE_DIRECT_JUMP + s->tb_jmp_offset = tb->tb_jmp_offset; + s->tb_next = NULL; +#else + s->tb_jmp_offset = NULL; + s->tb_next = tb->tb_next; +#endif + j = dyngen_code_search_pc(s, (uint8_t *)tc_ptr, + (void *)searched_pc); + if (j < 0) + return -1; /* now find start of instruction before */ while (gen_opc_instr_start[j] == 0) j--; @@ -266,10 +238,11 @@ int cpu_restore_state(TranslationBlock *tb, } #elif defined(TARGET_PPC) { - int type; + int type, c; /* for PPC, we need to look at the micro operation to get the access type */ env->nip = gen_opc_pc[j]; + c = gen_opc_buf[j]; switch(c) { #if defined(CONFIG_USER_ONLY) #define CASE3(op)\ @@ -315,5 +288,10 @@ int cpu_restore_state(TranslationBlock *tb, env->pc = gen_opc_pc[j]; env->flags = gen_opc_hflags[j]; #endif + +#ifdef CONFIG_PROFILER + dyngen_restore_time += profile_getclock() - ti; + dyngen_restore_count++; +#endif return 0; } diff --git a/translate-op.c b/translate-op.c deleted file mode 100644 index 8104e86f22..0000000000 --- a/translate-op.c +++ /dev/null @@ -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" - |