commit 7d13299d07a9c3c42277207ae7a691f0501a70b2
Author: bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>
Date:   Thu Mar 6 23:23:54 2003 +0000

    added translation cache
    
    
    git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@25 c046a42c-6fe2-441c-8c8c-71466251a162

diff --git a/Makefile b/Makefile
index 57d2ba1..0f0b22d 100644
--- a/Makefile
+++ b/Makefile
@@ -1,43 +1,33 @@
-ARCH=i386
-#ARCH=ppc
-HOST_CC=gcc
+include config.mak
 
-ifeq ($(ARCH),i386)
-CFLAGS=-Wall -O2 -g -fomit-frame-pointer
+CFLAGS=-Wall -O2 -g
 LDFLAGS=-g
 LIBS=
-CC=gcc
 DEFINES=-DHAVE_BYTESWAP_H
+
+ifeq ($(ARCH),i386)
+CFLAGS+=-fomit-frame-pointer
 OP_CFLAGS=$(CFLAGS) -malign-functions=0 -mpreferred-stack-boundary=2
 endif
 
 ifeq ($(ARCH),ppc)
-GCC_LIBS_DIR=/usr/netgem/tools/lib/gcc-lib/powerpc-linux/2.95.2
-DIST=/home/fbe/nsv/dist/hw/n6-dtt
-CC=powerpc-linux-gcc -msoft-float 
-CFLAGS=-Wall -pipe -O2 -mcpu=405 -mbig -nostdinc -g -I$(GCC_LIBS_DIR)/include -I$(DIST)/include
-LIBS_DIR=$(DIST)/lib
-CRT1=$(LIBS_DIR)/crt1.o
-CRTI=$(LIBS_DIR)/crti.o
-CRTN=$(LIBS_DIR)/crtn.o
-CRTBEGIN=$(GCC_LIBS_DIR)/crtbegin.o
-CRTEND=$(GCC_LIBS_DIR)/crtend.o
-LDFLAGS=-static -g -nostdlib $(CRT1) $(CRTI) $(CRTBEGIN) 
-LIBS=-L$(LIBS_DIR) -ltinyc -lgcc $(CRTEND) $(CRTN)
-DEFINES=-Dsocklen_t=int
 OP_CFLAGS=$(CFLAGS)
 endif
 
 #########################################################
 
 DEFINES+=-D_GNU_SOURCE
-DEFINES+=-DCONFIG_PREFIX=\"/usr/local\"
 LDSCRIPT=$(ARCH).ld
 LIBS+=-ldl -lm
-VERSION=0.1
+
+# profiling code
+ifdef TARGET_GPROF
+LDFLAGS+=-p
+CFLAGS+=-p
+endif
 
 OBJS= elfload.o main.o thunk.o syscall.o
-OBJS+=translate-i386.o op-i386.o
+OBJS+=translate-i386.o op-i386.o exec-i386.o
 # NOTE: the disassembler code is only needed for debugging
 OBJS+=i386-dis.o dis-buf.o
 SRCS = $(OBJS:.o=.c)
@@ -66,8 +56,12 @@ op-i386.o: op-i386.c opreg_template.h ops_template.h
 	$(CC) $(CFLAGS) $(DEFINES) -c -o $@ $<
 
 clean:
+	$(MAKE) -C tests clean
 	rm -f *.o *~ gemu dyngen TAGS
 
+distclean: clean
+	rm -f config.mak config.h
+
 # various test targets
 test speed: gemu
 	make -C tests $@
@@ -82,7 +76,7 @@ TODO         elfload.c   main.c            signal.c        thunk.h\
 cpu-i386.h   gemu.h      op-i386.c         syscall-i386.h  translate-i386.c\
 dis-asm.h    gen-i386.h  op-i386.h         syscall.c\
 dis-buf.c    i386-dis.c  opreg_template.h  syscall_defs.h\
-i386.ld ppc.ld\
+i386.ld ppc.ld exec-i386.h exec-i386.c configure VERSION \
 tests/Makefile\
 tests/test-i386.c tests/test-i386-shift.h tests/test-i386.h\
 tests/test-i386-muldiv.h\
diff --git a/TODO b/TODO
index a12c384..3b04b7d 100644
--- a/TODO
+++ b/TODO
@@ -1,6 +1,8 @@
-- tests
+- optimize translated cache chaining (DLL PLT like system)
+- optimize inverse flags propagation (easy by generating intermediate
+  micro operation array).
 - signals
 - threads
-- fix printf for doubles (fp87.c bug ?)
 - make it self runnable (use same trick as ld.so : include its own relocator and libc)
 - fix FPU exceptions (in particular: gen_op_fpush not before mem load)
+- tests
diff --git a/configure b/configure
new file mode 100755
index 0000000..16252c4
--- /dev/null
+++ b/configure
@@ -0,0 +1,240 @@
+#!/bin/sh
+#
+# gemu configure script (c) 2003 Fabrice Bellard
+#
+# set temporary file name
+if test ! -z "$TMPDIR" ; then
+    TMPDIR1="${TMPDIR}"
+elif test ! -z "$TEMPDIR" ; then
+    TMPDIR1="${TEMPDIR}"
+else
+    TMPDIR1="/tmp"
+fi
+
+TMPC="${TMPDIR1}/qemacs-conf-${RANDOM}-$$-${RANDOM}.c"
+TMPO="${TMPDIR1}/qemacs-conf-${RANDOM}-$$-${RANDOM}.o"
+TMPS="${TMPDIR1}/qemacs-conf-${RANDOM}-$$-${RANDOM}.S"
+TMPH="${TMPDIR1}/qemacs-conf-${RANDOM}-$$-${RANDOM}.h"
+
+# default parameters
+prefix="/usr/local"
+cross_prefix=""
+cc="gcc"
+host_cc="gcc"
+ar="ar"
+make="make"
+strip="strip"
+cpu=`uname -m`
+case "$cpu" in
+  i386|i486|i586|i686|i86pc|BePC)
+    cpu="x86"
+  ;;
+  armv4l)
+    cpu="armv4l"
+  ;;
+  alpha)
+    cpu="alpha"
+  ;;
+  "Power Macintosh"|ppc)
+    cpu="powerpc"
+  ;;
+  mips)
+    cpu="mips"
+  ;;
+  *)
+    cpu="unknown"
+  ;;
+esac
+gprof="no"
+bigendian="no"
+
+# OS specific
+targetos=`uname -s`
+case $targetos in
+BeOS)
+prefix="/boot/home/config"
+# helps building libavcodec
+CFLAGS="-O2 -DPIC"
+# no need for libm, but the inet stuff
+# Check for BONE
+if (echo $BEINCLUDES|grep 'headers/be/bone' >/dev/null); then
+extralibs="-lbind -lsocket"
+else
+echo "Not sure building for net_server will succeed... good luck."
+extralibs="-lsocket"
+fi ;;
+BSD/OS)
+extralibs="-lpoll -lgnugetopt -lm"
+make="gmake"
+;;
+*) ;;
+esac
+
+# find source path
+# XXX: we assume an absolute path is given when launching configure, 
+# except in './configure' case.
+source_path=${0%configure}
+source_path=${source_path%/}
+source_path_used="yes"
+if test -z "$source_path" -o "$source_path" = "." ; then
+    source_path=`pwd`
+    source_path_used="no"
+fi
+
+for opt do
+  case "$opt" in
+  --prefix=*) prefix=`echo $opt | cut -d '=' -f 2`
+  ;;
+  --source-path=*) source_path=`echo $opt | cut -d '=' -f 2`
+  ;;
+  --cross-prefix=*) cross_prefix=`echo $opt | cut -d '=' -f 2`
+  ;;
+  --cc=*) cc=`echo $opt | cut -d '=' -f 2`
+  ;;
+  --make=*) make=`echo $opt | cut -d '=' -f 2`
+  ;;
+  --extra-cflags=*) CFLAGS="${opt#--extra-cflags=}"
+  ;;
+  --extra-ldflags=*) LDFLAGS="${opt#--extra-ldflags=}"
+  ;;
+  --extra-libs=*) extralibs=${opt#--extra-libs=}
+  ;;
+  --cpu=*) cpu=`echo $opt | cut -d '=' -f 2`
+  ;;
+  --enable-gprof) gprof="yes"
+  ;;
+  esac
+done
+
+# Checking for CFLAGS
+if test -z "$CFLAGS"; then
+    CFLAGS="-O2"
+fi
+
+cc="${cross_prefix}${cc}"
+ar="${cross_prefix}${ar}"
+strip="${cross_prefix}${strip}"
+
+if test -z "$cross_prefix" ; then
+
+# ---
+# big/little endian test
+cat > $TMPC << EOF
+#include <inttypes.h>
+int main(int argc, char ** argv){
+	volatile uint32_t i=0x01234567;
+	return (*((uint8_t*)(&i))) == 0x67;
+}
+EOF
+
+if $cc -o $TMPE $TMPC 2>/dev/null ; then
+$TMPE && bigendian="yes"
+else
+echo big/little test failed
+fi
+
+else
+
+# if cross compiling, cannot launch a program, so make a static guess
+if test "$cpu" = "powerpc" -o "$cpu" = "mips" ; then
+    bigendian="yes"
+fi
+
+fi
+
+if test x"$1" = x"-h" -o x"$1" = x"--help" ; then
+cat << EOF
+
+Usage: configure [options]
+Options: [defaults in brackets after descriptions]
+
+EOF
+echo "Standard options:"
+echo "  --help                   print this message"
+echo "  --prefix=PREFIX          install in PREFIX [$prefix]"
+echo "                           for audio/video/image support"
+echo ""
+echo "Advanced options (experts only):"
+echo "  --source-path=PATH       path of source code [$source_path]"
+echo "  --cross-prefix=PREFIX    use PREFIX for compile tools [$cross_prefix]"
+echo "  --cc=CC                  use C compiler CC [$cc]"
+echo "  --make=MAKE              use specified make [$make]"
+echo ""
+echo "NOTE: The object files are build at the place where configure is launched"
+exit 1
+fi
+
+echo "Install prefix   $prefix"
+echo "Source path      $source_path"
+echo "C compiler       $cc"
+echo "make             $make"
+echo "CPU              $cpu"
+echo "Big Endian       $bigendian"
+echo "gprof enabled    $gprof"
+
+echo "Creating config.mak and config.h"
+
+echo "# Automatically generated by configure - do not modify" > config.mak
+echo "/* Automatically generated by configure - do not modify */" > $TMPH
+
+echo "prefix=$prefix" >> config.mak
+echo "#define CONFIG_GEMU_PREFIX \"$prefix\"" >> $TMPH
+echo "MAKE=$make" >> config.mak
+echo "CC=$cc" >> config.mak
+echo "HOST_CC=$host_cc" >> config.mak
+echo "AR=$ar" >> config.mak
+echo "STRIP=$strip -s -R .comment -R .note" >> config.mak
+echo "CFLAGS=$CFLAGS" >> config.mak
+echo "LDFLAGS=$LDFLAGS" >> config.mak
+if test "$cpu" = "x86" ; then
+  echo "ARCH=i386" >> config.mak
+elif test "$cpu" = "armv4l" ; then
+  echo "ARCH=arm" >> config.mak
+elif test "$cpu" = "powerpc" ; then
+  echo "ARCH=ppc" > config.mak
+elif test "$cpu" = "mips" ; then
+  echo "ARCH=mips" > config.mak
+else
+  echo "Unsupported CPU"
+  exit 1
+fi
+if test "$bigendian" = "yes" ; then
+  echo "WORDS_BIGENDIAN=yes" >> config.mak
+  echo "#define WORDS_BIGENDIAN 1" >> $TMPH
+fi
+if test "$gprof" = "yes" ; then
+  echo "TARGET_GPROF=yes" >> config.mak
+  echo "#define HAVE_GPROF 1" >> $TMPH
+fi
+echo -n "VERSION=" >>config.mak
+head $source_path/VERSION >>config.mak
+echo "" >>config.mak
+echo -n "#define GEMU_VERSION \"" >> $TMPH
+head $source_path/VERSION >> $TMPH
+echo "\"" >> $TMPH
+if test "$network" = "yes" ; then
+  echo "#define CONFIG_NETWORK 1" >> $TMPH
+  echo "CONFIG_NETWORK=yes" >> config.mak
+fi
+
+# build tree in object directory if source path is different from current one
+if test "$source_path_used" = "yes" ; then
+    DIRS="tests"
+    FILES="Makefile tests/Makefile"
+    for dir in $DIRS ; do
+            mkdir -p $dir
+    done
+    for f in $FILES ; do
+        ln -sf $source_path/$f $f
+    done
+fi
+echo "SRC_PATH=$source_path" >> config.mak
+
+diff $TMPH config.h >/dev/null 2>&1
+if test $? -ne 0 ; then
+	mv -f $TMPH config.h
+else
+	echo "config.h is unchanged"
+fi
+
+rm -f $TMPH
diff --git a/cpu-i386.h b/cpu-i386.h
index 4d06d92..a6464ef 100644
--- a/cpu-i386.h
+++ b/cpu-i386.h
@@ -244,5 +244,6 @@ void cpu_x86_close(CPUX86State *s);
 /* internal functions */
 int cpu_x86_gen_code(uint8_t *gen_code_buf, int max_code_size, 
                      int *gen_code_size_ptr, uint8_t *pc_start);
+void cpu_x86_tblocks_init(void);
 
 #endif /* CPU_I386_H */
diff --git a/dyngen.c b/dyngen.c
index f6b102f..40a7fc6 100644
--- a/dyngen.c
+++ b/dyngen.c
@@ -1,3 +1,22 @@
+/*
+ *  Generic Dynamic compiler generator
+ * 
+ *  Copyright (c) 2003 Fabrice Bellard
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program 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 General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
 #include <stdlib.h>
 #include <stdio.h>
 #include <stdarg.h>
diff --git a/exec-i386.c b/exec-i386.c
new file mode 100644
index 0000000..c067685
--- /dev/null
+++ b/exec-i386.c
@@ -0,0 +1,213 @@
+/*
+ *  i386 emulator main execution loop
+ * 
+ *  Copyright (c) 2003 Fabrice Bellard
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program 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 General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "exec-i386.h"
+
+#define DEBUG_EXEC
+#define DEBUG_FLUSH
+
+/* main execution loop */
+
+/* maximum total translate dcode allocated */
+#define CODE_GEN_BUFFER_SIZE     (2048 * 1024)
+//#define CODE_GEN_BUFFER_SIZE     (128 * 1024)
+#define CODE_GEN_MAX_SIZE        65536
+#define CODE_GEN_ALIGN           16 /* must be >= of the size of a icache line */
+
+/* threshold to flush the translated code buffer */
+#define CODE_GEN_BUFFER_MAX_SIZE (CODE_GEN_BUFFER_SIZE - CODE_GEN_MAX_SIZE)
+
+#define CODE_GEN_MAX_BLOCKS    (CODE_GEN_BUFFER_SIZE / 64)
+#define CODE_GEN_HASH_BITS     15
+#define CODE_GEN_HASH_SIZE     (1 << CODE_GEN_HASH_BITS)
+typedef struct TranslationBlock {
+    unsigned long pc;   /* simulated PC corresponding to this block */
+    uint8_t *tc_ptr;    /* pointer to the translated code */
+    struct TranslationBlock *hash_next; /* next matching block */
+} TranslationBlock;
+
+TranslationBlock tbs[CODE_GEN_MAX_BLOCKS];
+TranslationBlock *tb_hash[CODE_GEN_HASH_SIZE];
+int nb_tbs;
+
+uint8_t code_gen_buffer[CODE_GEN_BUFFER_SIZE];
+uint8_t *code_gen_ptr;
+
+#ifdef DEBUG_EXEC
+static const char *cc_op_str[] = {
+    "DYNAMIC",
+    "EFLAGS",
+    "MUL",
+    "ADDB",
+    "ADDW",
+    "ADDL",
+    "ADCB",
+    "ADCW",
+    "ADCL",
+    "SUBB",
+    "SUBW",
+    "SUBL",
+    "SBBB",
+    "SBBW",
+    "SBBL",
+    "LOGICB",
+    "LOGICW",
+    "LOGICL",
+    "INCB",
+    "INCW",
+    "INCL",
+    "DECB",
+    "DECW",
+    "DECL",
+    "SHLB",
+    "SHLW",
+    "SHLL",
+    "SARB",
+    "SARW",
+    "SARL",
+};
+
+static void cpu_x86_dump_state(void)
+{
+    int eflags;
+    eflags = cc_table[CC_OP].compute_all();
+    eflags |= (DF & DIRECTION_FLAG);
+    fprintf(logfile, 
+            "EAX=%08x EBX=%08X ECX=%08x EDX=%08x\n"
+            "ESI=%08x EDI=%08X EBP=%08x ESP=%08x\n"
+            "CCS=%08x CCD=%08x CCO=%-8s EFL=%c%c%c%c%c%c%c\n",
+            env->regs[R_EAX], env->regs[R_EBX], env->regs[R_ECX], env->regs[R_EDX], 
+            env->regs[R_ESI], env->regs[R_EDI], env->regs[R_EBP], env->regs[R_ESP], 
+            env->cc_src, env->cc_dst, cc_op_str[env->cc_op],
+            eflags & DIRECTION_FLAG ? 'D' : '-',
+            eflags & CC_O ? 'O' : '-',
+            eflags & CC_S ? 'S' : '-',
+            eflags & CC_Z ? 'Z' : '-',
+            eflags & CC_A ? 'A' : '-',
+            eflags & CC_P ? 'P' : '-',
+            eflags & CC_C ? 'C' : '-'
+            );
+#if 1
+    fprintf(logfile, "ST0=%f ST1=%f ST2=%f ST3=%f\n", 
+            (double)ST0, (double)ST1, (double)ST(2), (double)ST(3));
+#endif
+}
+
+#endif
+
+void cpu_x86_tblocks_init(void)
+{
+    if (!code_gen_ptr) {
+        code_gen_ptr = code_gen_buffer;
+    }
+}
+
+/* flush all the translation blocks */
+static void tb_flush(void)
+{
+    int i;
+#ifdef DEBUG_FLUSH
+    printf("gemu: flush code_size=%d nb_tbs=%d avg_tb_size=%d\n", 
+           code_gen_ptr - code_gen_buffer, 
+           nb_tbs, 
+           (code_gen_ptr - code_gen_buffer) / nb_tbs);
+#endif
+    nb_tbs = 0;
+    for(i = 0;i < CODE_GEN_HASH_SIZE; i++)
+        tb_hash[i] = NULL;
+    code_gen_ptr = code_gen_buffer;
+    /* XXX: flush processor icache at this point */
+}
+
+/* find a translation block in the translation cache. If not found,
+   allocate a new one */
+static inline TranslationBlock *tb_find_and_alloc(unsigned long pc)
+{
+    TranslationBlock **ptb, *tb;
+    unsigned int h;
+ 
+    h = pc & (CODE_GEN_HASH_SIZE - 1);
+    ptb = &tb_hash[h];
+    for(;;) {
+        tb = *ptb;
+        if (!tb)
+            break;
+        if (tb->pc == pc)
+            return tb;
+        ptb = &tb->hash_next;
+    }
+    if (nb_tbs >= CODE_GEN_MAX_BLOCKS || 
+        (code_gen_ptr - code_gen_buffer) >= CODE_GEN_BUFFER_MAX_SIZE)
+        tb_flush();
+    tb = &tbs[nb_tbs++];
+    *ptb = tb;
+    tb->pc = pc;
+    tb->tc_ptr = NULL;
+    tb->hash_next = NULL;
+    return tb;
+}
+
+int cpu_x86_exec(CPUX86State *env1)
+{
+    int saved_T0, saved_T1, saved_A0;
+    CPUX86State *saved_env;
+    int code_gen_size, ret;
+    void (*gen_func)(void);
+    TranslationBlock *tb;
+    uint8_t *tc_ptr;
+    
+    /* first we save global registers */
+    saved_T0 = T0;
+    saved_T1 = T1;
+    saved_A0 = A0;
+    saved_env = env;
+    env = env1;
+    
+    /* prepare setjmp context for exception handling */
+    if (setjmp(env->jmp_env) == 0) {
+        for(;;) {
+#ifdef DEBUG_EXEC
+            if (loglevel) {
+                cpu_x86_dump_state();
+            }
+#endif
+            tb = tb_find_and_alloc((unsigned long)env->pc);
+            tc_ptr = tb->tc_ptr;
+            if (!tb->tc_ptr) {
+                /* if no translated code available, then translate it now */
+                tc_ptr = code_gen_ptr;
+                cpu_x86_gen_code(code_gen_ptr, CODE_GEN_MAX_SIZE, 
+                                 &code_gen_size, (uint8_t *)env->pc);
+                tb->tc_ptr = tc_ptr;
+                code_gen_ptr = (void *)(((unsigned long)code_gen_ptr + code_gen_size + CODE_GEN_ALIGN - 1) & ~(CODE_GEN_ALIGN - 1));
+            }
+            /* execute the generated code */
+            gen_func = (void *)tc_ptr;
+            gen_func();
+        }
+    }
+    ret = env->exception_index;
+
+    /* restore global registers */
+    T0 = saved_T0;
+    T1 = saved_T1;
+    A0 = saved_A0;
+    env = saved_env;
+    return ret;
+}
diff --git a/exec-i386.h b/exec-i386.h
new file mode 100644
index 0000000..62f681b
--- /dev/null
+++ b/exec-i386.h
@@ -0,0 +1,105 @@
+/* i386 execution defines */
+
+typedef unsigned char uint8_t;
+typedef unsigned short uint16_t;
+typedef unsigned int uint32_t;
+typedef unsigned long long uint64_t;
+
+typedef signed char int8_t;
+typedef signed short int16_t;
+typedef signed int int32_t;
+typedef signed long long int64_t;
+
+#define bswap32(x) \
+({ \
+	uint32_t __x = (x); \
+	((uint32_t)( \
+		(((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \
+		(((uint32_t)(__x) & (uint32_t)0x0000ff00UL) <<  8) | \
+		(((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >>  8) | \
+		(((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) )); \
+})
+
+#define NULL 0
+#include <fenv.h>
+
+typedef struct FILE FILE;
+extern FILE *logfile;
+extern int loglevel;
+extern int fprintf(FILE *, const char *, ...);
+
+#ifdef __i386__
+register unsigned int T0 asm("ebx");
+register unsigned int T1 asm("esi");
+register unsigned int A0 asm("edi");
+register struct CPUX86State *env asm("ebp");
+#endif
+#ifdef __powerpc__
+register unsigned int T0 asm("r24");
+register unsigned int T1 asm("r25");
+register unsigned int A0 asm("r26");
+register struct CPUX86State *env asm("r27");
+#endif
+#ifdef __arm__
+register unsigned int T0 asm("r4");
+register unsigned int T1 asm("r5");
+register unsigned int A0 asm("r6");
+register struct CPUX86State *env asm("r7");
+#endif
+#ifdef __mips__
+register unsigned int T0 asm("s0");
+register unsigned int T1 asm("s1");
+register unsigned int A0 asm("s2");
+register struct CPUX86State *env asm("s3");
+#endif
+#ifdef __sparc__
+register unsigned int T0 asm("l0");
+register unsigned int T1 asm("l1");
+register unsigned int A0 asm("l2");
+register struct CPUX86State *env asm("l3");
+#endif
+
+/* force GCC to generate only one epilog at the end of the function */
+#define FORCE_RET() asm volatile ("");
+
+#ifndef OPPROTO
+#define OPPROTO
+#endif
+
+#define xglue(x, y) x ## y
+#define glue(x, y) xglue(x, y)
+
+#define EAX (env->regs[R_EAX])
+#define ECX (env->regs[R_ECX])
+#define EDX (env->regs[R_EDX])
+#define EBX (env->regs[R_EBX])
+#define ESP (env->regs[R_ESP])
+#define EBP (env->regs[R_EBP])
+#define ESI (env->regs[R_ESI])
+#define EDI (env->regs[R_EDI])
+#define PC  (env->pc)
+#define DF  (env->df)
+
+#define CC_SRC (env->cc_src)
+#define CC_DST (env->cc_dst)
+#define CC_OP  (env->cc_op)
+
+/* float macros */
+#define FT0    (env->ft0)
+#define ST0    (env->fpregs[env->fpstt])
+#define ST(n)  (env->fpregs[(env->fpstt + (n)) & 7])
+#define ST1    ST(1)
+
+extern int __op_param1, __op_param2, __op_param3;
+#define PARAM1 ((long)(&__op_param1))
+#define PARAM2 ((long)(&__op_param2))
+#define PARAM3 ((long)(&__op_param3))
+
+#include "cpu-i386.h"
+
+typedef struct CCTable {
+    int (*compute_all)(void); /* return all the flags */
+    int (*compute_c)(void);  /* return the C flag */
+} CCTable;
+
+extern CCTable cc_table[];
diff --git a/linux-user/main.c b/linux-user/main.c
index 356d980..9927b82 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -87,7 +87,7 @@ int cpu_x86_inl(int addr)
 
 void usage(void)
 {
-    printf("gemu version 0.1, Copyright (c) 2003 Fabrice Bellard\n"
+    printf("gemu version" GEMU_VERSION ", Copyright (c) 2003 Fabrice Bellard\n"
            "usage: gemu [-d] program [arguments...]\n"
            "Linux x86 emulator\n"
            );
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index f800fa2..ac40cf1 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -628,6 +628,9 @@ long do_syscall(int num, long arg1, long arg2, long arg3,
 #endif
     switch(num) {
     case TARGET_NR_exit:
+#ifdef HAVE_GPROF
+        _mcleanup();
+#endif
         _exit(arg1);
         ret = 0; /* avoid warning */
         break;
diff --git a/op-i386.c b/op-i386.c
index 2cca6a6..6bd9de0 100644
--- a/op-i386.c
+++ b/op-i386.c
@@ -1,109 +1,25 @@
-#define DEBUG_EXEC
-
-typedef unsigned char uint8_t;
-typedef unsigned short uint16_t;
-typedef unsigned int uint32_t;
-typedef unsigned long long uint64_t;
-
-typedef signed char int8_t;
-typedef signed short int16_t;
-typedef signed int int32_t;
-typedef signed long long int64_t;
-
-#define bswap32(x) \
-({ \
-	uint32_t __x = (x); \
-	((uint32_t)( \
-		(((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \
-		(((uint32_t)(__x) & (uint32_t)0x0000ff00UL) <<  8) | \
-		(((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >>  8) | \
-		(((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) )); \
-})
-
-#define NULL 0
-#include <fenv.h>
-
-typedef struct FILE FILE;
-extern FILE *logfile;
-extern int loglevel;
-extern int fprintf(FILE *, const char *, ...);
-
-#ifdef __i386__
-register unsigned int T0 asm("ebx");
-register unsigned int T1 asm("esi");
-register unsigned int A0 asm("edi");
-register struct CPUX86State *env asm("ebp");
-#endif
-#ifdef __powerpc__
-register unsigned int T0 asm("r24");
-register unsigned int T1 asm("r25");
-register unsigned int A0 asm("r26");
-register struct CPUX86State *env asm("r27");
-#endif
-#ifdef __arm__
-register unsigned int T0 asm("r4");
-register unsigned int T1 asm("r5");
-register unsigned int A0 asm("r6");
-register struct CPUX86State *env asm("r7");
-#endif
-#ifdef __mips__
-register unsigned int T0 asm("s0");
-register unsigned int T1 asm("s1");
-register unsigned int A0 asm("s2");
-register struct CPUX86State *env asm("s3");
-#endif
-#ifdef __sparc__
-register unsigned int T0 asm("l0");
-register unsigned int T1 asm("l1");
-register unsigned int A0 asm("l2");
-register struct CPUX86State *env asm("l3");
-#endif
-
-/* force GCC to generate only one epilog at the end of the function */
-#define FORCE_RET() asm volatile ("");
-
-#ifndef OPPROTO
-#define OPPROTO
-#endif
-
-#define xglue(x, y) x ## y
-#define glue(x, y) xglue(x, y)
-
-#define EAX (env->regs[R_EAX])
-#define ECX (env->regs[R_ECX])
-#define EDX (env->regs[R_EDX])
-#define EBX (env->regs[R_EBX])
-#define ESP (env->regs[R_ESP])
-#define EBP (env->regs[R_EBP])
-#define ESI (env->regs[R_ESI])
-#define EDI (env->regs[R_EDI])
-#define PC  (env->pc)
-#define DF  (env->df)
-
-#define CC_SRC (env->cc_src)
-#define CC_DST (env->cc_dst)
-#define CC_OP  (env->cc_op)
-
-/* float macros */
-#define FT0    (env->ft0)
-#define ST0    (env->fpregs[env->fpstt])
-#define ST(n)  (env->fpregs[(env->fpstt + (n)) & 7])
-#define ST1    ST(1)
-
-extern int __op_param1, __op_param2, __op_param3;
-#define PARAM1 ((long)(&__op_param1))
-#define PARAM2 ((long)(&__op_param2))
-#define PARAM3 ((long)(&__op_param3))
-
-#include "cpu-i386.h"
-
-typedef struct CCTable {
-    int (*compute_all)(void); /* return all the flags */
-    int (*compute_c)(void);  /* return the C flag */
-} CCTable;
+/*
+ *  i386 micro operations
+ * 
+ *  Copyright (c) 2003 Fabrice Bellard
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program 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 General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include "exec-i386.h"
 
 /* NOTE: data are not static to force relocation generation by GCC */
-extern CCTable cc_table[];
 
 uint8_t parity_table[256] = {
     CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
@@ -1878,100 +1794,3 @@ void OPPROTO op_fldcw_A0(void)
     fesetround(rnd_type);
 }
 
-/* main execution loop */
-uint8_t code_gen_buffer[65536];
-
-#ifdef DEBUG_EXEC
-static const char *cc_op_str[] = {
-    "DYNAMIC",
-    "EFLAGS",
-    "MUL",
-    "ADDB",
-    "ADDW",
-    "ADDL",
-    "ADCB",
-    "ADCW",
-    "ADCL",
-    "SUBB",
-    "SUBW",
-    "SUBL",
-    "SBBB",
-    "SBBW",
-    "SBBL",
-    "LOGICB",
-    "LOGICW",
-    "LOGICL",
-    "INCB",
-    "INCW",
-    "INCL",
-    "DECB",
-    "DECW",
-    "DECL",
-    "SHLB",
-    "SHLW",
-    "SHLL",
-    "SARB",
-    "SARW",
-    "SARL",
-};
-#endif
-
-int cpu_x86_exec(CPUX86State *env1)
-{
-    int saved_T0, saved_T1, saved_A0;
-    CPUX86State *saved_env;
-    int code_gen_size, ret;
-    void (*gen_func)(void);
-
-    /* first we save global registers */
-    saved_T0 = T0;
-    saved_T1 = T1;
-    saved_A0 = A0;
-    saved_env = env;
-    env = env1;
-    
-    /* prepare setjmp context for exception handling */
-    if (setjmp(env->jmp_env) == 0) {
-        for(;;) {
-#ifdef DEBUG_EXEC
-            if (loglevel) {
-                int eflags;
-                eflags = cc_table[CC_OP].compute_all();
-                eflags |= (DF & DIRECTION_FLAG);
-                fprintf(logfile, 
-                        "EAX=%08x EBX=%08X ECX=%08x EDX=%08x\n"
-                        "ESI=%08x EDI=%08X EBP=%08x ESP=%08x\n"
-                        "CCS=%08x CCD=%08x CCO=%-8s EFL=%c%c%c%c%c%c%c\n",
-                        env->regs[R_EAX], env->regs[R_EBX], env->regs[R_ECX], env->regs[R_EDX], 
-                        env->regs[R_ESI], env->regs[R_EDI], env->regs[R_EBP], env->regs[R_ESP], 
-                        env->cc_src, env->cc_dst, cc_op_str[env->cc_op],
-                        eflags & DIRECTION_FLAG ? 'D' : '-',
-                        eflags & CC_O ? 'O' : '-',
-                        eflags & CC_S ? 'S' : '-',
-                        eflags & CC_Z ? 'Z' : '-',
-                        eflags & CC_A ? 'A' : '-',
-                        eflags & CC_P ? 'P' : '-',
-                        eflags & CC_C ? 'C' : '-'
-                        );
-#if 1
-                fprintf(logfile, "ST0=%f ST1=%f ST2=%f ST3=%f\n", 
-                        (double)ST0, (double)ST1, (double)ST(2), (double)ST(3));
-#endif
-            }
-#endif
-            cpu_x86_gen_code(code_gen_buffer, sizeof(code_gen_buffer), 
-                             &code_gen_size, (uint8_t *)env->pc);
-            /* execute the generated code */
-            gen_func = (void *)code_gen_buffer;
-            gen_func();
-        }
-    }
-    ret = env->exception_index;
-
-    /* restore global registers */
-    T0 = saved_T0;
-    T1 = saved_T1;
-    A0 = saved_A0;
-    env = saved_env;
-    return ret;
-}
diff --git a/tests/Makefile b/tests/Makefile
index 5fc813c..c7d1154 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -1,9 +1,11 @@
-CC=gcc
+include ../config.mak
+
 CFLAGS=-Wall -O2 -g
 LDFLAGS=
 
+ifeq ($(ARCH),i386)
 TESTS=hello test2 sha1 test-i386
-TESTS+=op-i386.o #op-i386.o op-ppc.o op-arm.o op-mips.o op-sparc.o
+endif
 
 GEMU=../gemu
 
@@ -24,22 +26,6 @@ test: test-i386
 	$(GEMU) test-i386 > test-i386.out
 	@if diff -u test-i386.ref test-i386.out ; then echo "Auto Test OK"; fi
 
-# dyngen tests
-op-i386.o: op.c
-	gcc $(CFLAGS) -c -o $@ $<
-
-op-ppc.o: op.c
-	powerpc-linux-gcc $(CFLAGS) -c -o $@ $<
-
-op-arm.o: op.c
-	arm-linux-gcc $(CFLAGS) -c -o $@ $<
-
-op-mips.o: op.c
-	mips-linux-gcc $(CFLAGS) -mno-abicalls -c -o $@ $<
-
-op-sparc.o: op.c
-	sparc-linux-gcc $(CFLAGS) -mflat -c -o $@ $<
-
 # speed test
 sha1: sha1.c
 	$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $<
@@ -48,6 +34,5 @@ speed: sha1
 	time ./sha1
 	time $(GEMU) sha1
 
-# interpreter test
-interp: interp.c interploop.c
-	$(CC) $(CFLAGS) -fomit-frame-pointer $(LDFLAGS) -o $@ $^
+clean:
+	rm -f *~ *.o $(TESTS)
diff --git a/thunk.h b/thunk.h
index 5e5d9dd..a7338ad 100644
--- a/thunk.h
+++ b/thunk.h
@@ -2,7 +2,7 @@
 #define THUNK_H
 
 #include <inttypes.h>
-#include <endian.h>
+#include "config.h"
 
 #ifdef HAVE_BYTESWAP_H
 #include <byteswap.h>
@@ -42,11 +42,6 @@
 
 #endif
 
-#undef WORDS_BIGENDIAN
-#if __BYTE_ORDER == __BIG_ENDIAN
-#define WORDS_BIGENDIAN
-#endif
-
 #ifdef WORDS_BIGENDIAN
 #define BSWAP_NEEDED
 #endif
diff --git a/translate-i386.c b/translate-i386.c
index d13d5d7..ad46e13 100644
--- a/translate-i386.c
+++ b/translate-i386.c
@@ -1,3 +1,22 @@
+/*
+ *  i386 translation
+ * 
+ *  Copyright (c) 2003 Fabrice Bellard
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program 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 General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
 #include <stdarg.h>
 #include <stdlib.h>
 #include <stdio.h>
@@ -2591,6 +2610,8 @@ CPUX86State *cpu_x86_init(void)
     CPUX86State *env;
     int i;
 
+    cpu_x86_tblocks_init();
+
     env = malloc(sizeof(CPUX86State));
     if (!env)
         return NULL;
