Commit 57fec1fe authored by bellard's avatar bellard

use the TCG code generator


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3944 c046a42c-6fe2-441c-8c8c-71466251a162
parent c896fe29
......@@ -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
......@@ -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 */
......@@ -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 */ \
......
......@@ -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
......
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;
}
This diff is collapsed.
This diff is collapsed.
......@@ -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)
......
......@@ -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)
{
......
......@@ -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;
......
......@@ -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. */
......
......@@ -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) {
......
......@@ -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();
......
......@@ -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;
......
......@@ -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);
......
......@@ -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);
}
......
#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);
......@@ -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();
}