Commit 7d13299d07a9c3c42277207ae7a691f0501a70b2

Authored by bellard
1 parent 1017ebe9

added translation cache


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@25 c046a42c-6fe2-441c-8c8c-71466251a162
Makefile
1 -ARCH=i386  
2 -#ARCH=ppc  
3 -HOST_CC=gcc 1 +include config.mak
4 2
5 -ifeq ($(ARCH),i386)  
6 -CFLAGS=-Wall -O2 -g -fomit-frame-pointer 3 +CFLAGS=-Wall -O2 -g
7 LDFLAGS=-g 4 LDFLAGS=-g
8 LIBS= 5 LIBS=
9 -CC=gcc  
10 DEFINES=-DHAVE_BYTESWAP_H 6 DEFINES=-DHAVE_BYTESWAP_H
  7 +
  8 +ifeq ($(ARCH),i386)
  9 +CFLAGS+=-fomit-frame-pointer
11 OP_CFLAGS=$(CFLAGS) -malign-functions=0 -mpreferred-stack-boundary=2 10 OP_CFLAGS=$(CFLAGS) -malign-functions=0 -mpreferred-stack-boundary=2
12 endif 11 endif
13 12
14 ifeq ($(ARCH),ppc) 13 ifeq ($(ARCH),ppc)
15 -GCC_LIBS_DIR=/usr/netgem/tools/lib/gcc-lib/powerpc-linux/2.95.2  
16 -DIST=/home/fbe/nsv/dist/hw/n6-dtt  
17 -CC=powerpc-linux-gcc -msoft-float  
18 -CFLAGS=-Wall -pipe -O2 -mcpu=405 -mbig -nostdinc -g -I$(GCC_LIBS_DIR)/include -I$(DIST)/include  
19 -LIBS_DIR=$(DIST)/lib  
20 -CRT1=$(LIBS_DIR)/crt1.o  
21 -CRTI=$(LIBS_DIR)/crti.o  
22 -CRTN=$(LIBS_DIR)/crtn.o  
23 -CRTBEGIN=$(GCC_LIBS_DIR)/crtbegin.o  
24 -CRTEND=$(GCC_LIBS_DIR)/crtend.o  
25 -LDFLAGS=-static -g -nostdlib $(CRT1) $(CRTI) $(CRTBEGIN)  
26 -LIBS=-L$(LIBS_DIR) -ltinyc -lgcc $(CRTEND) $(CRTN)  
27 -DEFINES=-Dsocklen_t=int  
28 OP_CFLAGS=$(CFLAGS) 14 OP_CFLAGS=$(CFLAGS)
29 endif 15 endif
30 16
31 ######################################################### 17 #########################################################
32 18
33 DEFINES+=-D_GNU_SOURCE 19 DEFINES+=-D_GNU_SOURCE
34 -DEFINES+=-DCONFIG_PREFIX=\"/usr/local\"  
35 LDSCRIPT=$(ARCH).ld 20 LDSCRIPT=$(ARCH).ld
36 LIBS+=-ldl -lm 21 LIBS+=-ldl -lm
37 -VERSION=0.1 22 +
  23 +# profiling code
  24 +ifdef TARGET_GPROF
  25 +LDFLAGS+=-p
  26 +CFLAGS+=-p
  27 +endif
38 28
39 OBJS= elfload.o main.o thunk.o syscall.o 29 OBJS= elfload.o main.o thunk.o syscall.o
40 -OBJS+=translate-i386.o op-i386.o 30 +OBJS+=translate-i386.o op-i386.o exec-i386.o
41 # NOTE: the disassembler code is only needed for debugging 31 # NOTE: the disassembler code is only needed for debugging
42 OBJS+=i386-dis.o dis-buf.o 32 OBJS+=i386-dis.o dis-buf.o
43 SRCS = $(OBJS:.o=.c) 33 SRCS = $(OBJS:.o=.c)
@@ -66,8 +56,12 @@ op-i386.o: op-i386.c opreg_template.h ops_template.h @@ -66,8 +56,12 @@ op-i386.o: op-i386.c opreg_template.h ops_template.h
66 $(CC) $(CFLAGS) $(DEFINES) -c -o $@ $< 56 $(CC) $(CFLAGS) $(DEFINES) -c -o $@ $<
67 57
68 clean: 58 clean:
  59 + $(MAKE) -C tests clean
69 rm -f *.o *~ gemu dyngen TAGS 60 rm -f *.o *~ gemu dyngen TAGS
70 61
  62 +distclean: clean
  63 + rm -f config.mak config.h
  64 +
71 # various test targets 65 # various test targets
72 test speed: gemu 66 test speed: gemu
73 make -C tests $@ 67 make -C tests $@
@@ -82,7 +76,7 @@ TODO elfload.c main.c signal.c thunk.h\ @@ -82,7 +76,7 @@ TODO elfload.c main.c signal.c thunk.h\
82 cpu-i386.h gemu.h op-i386.c syscall-i386.h translate-i386.c\ 76 cpu-i386.h gemu.h op-i386.c syscall-i386.h translate-i386.c\
83 dis-asm.h gen-i386.h op-i386.h syscall.c\ 77 dis-asm.h gen-i386.h op-i386.h syscall.c\
84 dis-buf.c i386-dis.c opreg_template.h syscall_defs.h\ 78 dis-buf.c i386-dis.c opreg_template.h syscall_defs.h\
85 -i386.ld ppc.ld\ 79 +i386.ld ppc.ld exec-i386.h exec-i386.c configure VERSION \
86 tests/Makefile\ 80 tests/Makefile\
87 tests/test-i386.c tests/test-i386-shift.h tests/test-i386.h\ 81 tests/test-i386.c tests/test-i386-shift.h tests/test-i386.h\
88 tests/test-i386-muldiv.h\ 82 tests/test-i386-muldiv.h\
1 -- tests 1 +- optimize translated cache chaining (DLL PLT like system)
  2 +- optimize inverse flags propagation (easy by generating intermediate
  3 + micro operation array).
2 - signals 4 - signals
3 - threads 5 - threads
4 -- fix printf for doubles (fp87.c bug ?)  
5 - make it self runnable (use same trick as ld.so : include its own relocator and libc) 6 - make it self runnable (use same trick as ld.so : include its own relocator and libc)
6 - fix FPU exceptions (in particular: gen_op_fpush not before mem load) 7 - fix FPU exceptions (in particular: gen_op_fpush not before mem load)
  8 +- tests
configure 0 โ†’ 100755
  1 +#!/bin/sh
  2 +#
  3 +# gemu configure script (c) 2003 Fabrice Bellard
  4 +#
  5 +# set temporary file name
  6 +if test ! -z "$TMPDIR" ; then
  7 + TMPDIR1="${TMPDIR}"
  8 +elif test ! -z "$TEMPDIR" ; then
  9 + TMPDIR1="${TEMPDIR}"
  10 +else
  11 + TMPDIR1="/tmp"
  12 +fi
  13 +
  14 +TMPC="${TMPDIR1}/qemacs-conf-${RANDOM}-$$-${RANDOM}.c"
  15 +TMPO="${TMPDIR1}/qemacs-conf-${RANDOM}-$$-${RANDOM}.o"
  16 +TMPS="${TMPDIR1}/qemacs-conf-${RANDOM}-$$-${RANDOM}.S"
  17 +TMPH="${TMPDIR1}/qemacs-conf-${RANDOM}-$$-${RANDOM}.h"
  18 +
  19 +# default parameters
  20 +prefix="/usr/local"
  21 +cross_prefix=""
  22 +cc="gcc"
  23 +host_cc="gcc"
  24 +ar="ar"
  25 +make="make"
  26 +strip="strip"
  27 +cpu=`uname -m`
  28 +case "$cpu" in
  29 + i386|i486|i586|i686|i86pc|BePC)
  30 + cpu="x86"
  31 + ;;
  32 + armv4l)
  33 + cpu="armv4l"
  34 + ;;
  35 + alpha)
  36 + cpu="alpha"
  37 + ;;
  38 + "Power Macintosh"|ppc)
  39 + cpu="powerpc"
  40 + ;;
  41 + mips)
  42 + cpu="mips"
  43 + ;;
  44 + *)
  45 + cpu="unknown"
  46 + ;;
  47 +esac
  48 +gprof="no"
  49 +bigendian="no"
  50 +
  51 +# OS specific
  52 +targetos=`uname -s`
  53 +case $targetos in
  54 +BeOS)
  55 +prefix="/boot/home/config"
  56 +# helps building libavcodec
  57 +CFLAGS="-O2 -DPIC"
  58 +# no need for libm, but the inet stuff
  59 +# Check for BONE
  60 +if (echo $BEINCLUDES|grep 'headers/be/bone' >/dev/null); then
  61 +extralibs="-lbind -lsocket"
  62 +else
  63 +echo "Not sure building for net_server will succeed... good luck."
  64 +extralibs="-lsocket"
  65 +fi ;;
  66 +BSD/OS)
  67 +extralibs="-lpoll -lgnugetopt -lm"
  68 +make="gmake"
  69 +;;
  70 +*) ;;
  71 +esac
  72 +
  73 +# find source path
  74 +# XXX: we assume an absolute path is given when launching configure,
  75 +# except in './configure' case.
  76 +source_path=${0%configure}
  77 +source_path=${source_path%/}
  78 +source_path_used="yes"
  79 +if test -z "$source_path" -o "$source_path" = "." ; then
  80 + source_path=`pwd`
  81 + source_path_used="no"
  82 +fi
  83 +
  84 +for opt do
  85 + case "$opt" in
  86 + --prefix=*) prefix=`echo $opt | cut -d '=' -f 2`
  87 + ;;
  88 + --source-path=*) source_path=`echo $opt | cut -d '=' -f 2`
  89 + ;;
  90 + --cross-prefix=*) cross_prefix=`echo $opt | cut -d '=' -f 2`
  91 + ;;
  92 + --cc=*) cc=`echo $opt | cut -d '=' -f 2`
  93 + ;;
  94 + --make=*) make=`echo $opt | cut -d '=' -f 2`
  95 + ;;
  96 + --extra-cflags=*) CFLAGS="${opt#--extra-cflags=}"
  97 + ;;
  98 + --extra-ldflags=*) LDFLAGS="${opt#--extra-ldflags=}"
  99 + ;;
  100 + --extra-libs=*) extralibs=${opt#--extra-libs=}
  101 + ;;
  102 + --cpu=*) cpu=`echo $opt | cut -d '=' -f 2`
  103 + ;;
  104 + --enable-gprof) gprof="yes"
  105 + ;;
  106 + esac
  107 +done
  108 +
  109 +# Checking for CFLAGS
  110 +if test -z "$CFLAGS"; then
  111 + CFLAGS="-O2"
  112 +fi
  113 +
  114 +cc="${cross_prefix}${cc}"
  115 +ar="${cross_prefix}${ar}"
  116 +strip="${cross_prefix}${strip}"
  117 +
  118 +if test -z "$cross_prefix" ; then
  119 +
  120 +# ---
  121 +# big/little endian test
  122 +cat > $TMPC << EOF
  123 +#include <inttypes.h>
  124 +int main(int argc, char ** argv){
  125 + volatile uint32_t i=0x01234567;
  126 + return (*((uint8_t*)(&i))) == 0x67;
  127 +}
  128 +EOF
  129 +
  130 +if $cc -o $TMPE $TMPC 2>/dev/null ; then
  131 +$TMPE && bigendian="yes"
  132 +else
  133 +echo big/little test failed
  134 +fi
  135 +
  136 +else
  137 +
  138 +# if cross compiling, cannot launch a program, so make a static guess
  139 +if test "$cpu" = "powerpc" -o "$cpu" = "mips" ; then
  140 + bigendian="yes"
  141 +fi
  142 +
  143 +fi
  144 +
  145 +if test x"$1" = x"-h" -o x"$1" = x"--help" ; then
  146 +cat << EOF
  147 +
  148 +Usage: configure [options]
  149 +Options: [defaults in brackets after descriptions]
  150 +
  151 +EOF
  152 +echo "Standard options:"
  153 +echo " --help print this message"
  154 +echo " --prefix=PREFIX install in PREFIX [$prefix]"
  155 +echo " for audio/video/image support"
  156 +echo ""
  157 +echo "Advanced options (experts only):"
  158 +echo " --source-path=PATH path of source code [$source_path]"
  159 +echo " --cross-prefix=PREFIX use PREFIX for compile tools [$cross_prefix]"
  160 +echo " --cc=CC use C compiler CC [$cc]"
  161 +echo " --make=MAKE use specified make [$make]"
  162 +echo ""
  163 +echo "NOTE: The object files are build at the place where configure is launched"
  164 +exit 1
  165 +fi
  166 +
  167 +echo "Install prefix $prefix"
  168 +echo "Source path $source_path"
  169 +echo "C compiler $cc"
  170 +echo "make $make"
  171 +echo "CPU $cpu"
  172 +echo "Big Endian $bigendian"
  173 +echo "gprof enabled $gprof"
  174 +
  175 +echo "Creating config.mak and config.h"
  176 +
  177 +echo "# Automatically generated by configure - do not modify" > config.mak
  178 +echo "/* Automatically generated by configure - do not modify */" > $TMPH
  179 +
  180 +echo "prefix=$prefix" >> config.mak
  181 +echo "#define CONFIG_GEMU_PREFIX \"$prefix\"" >> $TMPH
  182 +echo "MAKE=$make" >> config.mak
  183 +echo "CC=$cc" >> config.mak
  184 +echo "HOST_CC=$host_cc" >> config.mak
  185 +echo "AR=$ar" >> config.mak
  186 +echo "STRIP=$strip -s -R .comment -R .note" >> config.mak
  187 +echo "CFLAGS=$CFLAGS" >> config.mak
  188 +echo "LDFLAGS=$LDFLAGS" >> config.mak
  189 +if test "$cpu" = "x86" ; then
  190 + echo "ARCH=i386" >> config.mak
  191 +elif test "$cpu" = "armv4l" ; then
  192 + echo "ARCH=arm" >> config.mak
  193 +elif test "$cpu" = "powerpc" ; then
  194 + echo "ARCH=ppc" > config.mak
  195 +elif test "$cpu" = "mips" ; then
  196 + echo "ARCH=mips" > config.mak
  197 +else
  198 + echo "Unsupported CPU"
  199 + exit 1
  200 +fi
  201 +if test "$bigendian" = "yes" ; then
  202 + echo "WORDS_BIGENDIAN=yes" >> config.mak
  203 + echo "#define WORDS_BIGENDIAN 1" >> $TMPH
  204 +fi
  205 +if test "$gprof" = "yes" ; then
  206 + echo "TARGET_GPROF=yes" >> config.mak
  207 + echo "#define HAVE_GPROF 1" >> $TMPH
  208 +fi
  209 +echo -n "VERSION=" >>config.mak
  210 +head $source_path/VERSION >>config.mak
  211 +echo "" >>config.mak
  212 +echo -n "#define GEMU_VERSION \"" >> $TMPH
  213 +head $source_path/VERSION >> $TMPH
  214 +echo "\"" >> $TMPH
  215 +if test "$network" = "yes" ; then
  216 + echo "#define CONFIG_NETWORK 1" >> $TMPH
  217 + echo "CONFIG_NETWORK=yes" >> config.mak
  218 +fi
  219 +
  220 +# build tree in object directory if source path is different from current one
  221 +if test "$source_path_used" = "yes" ; then
  222 + DIRS="tests"
  223 + FILES="Makefile tests/Makefile"
  224 + for dir in $DIRS ; do
  225 + mkdir -p $dir
  226 + done
  227 + for f in $FILES ; do
  228 + ln -sf $source_path/$f $f
  229 + done
  230 +fi
  231 +echo "SRC_PATH=$source_path" >> config.mak
  232 +
  233 +diff $TMPH config.h >/dev/null 2>&1
  234 +if test $? -ne 0 ; then
  235 + mv -f $TMPH config.h
  236 +else
  237 + echo "config.h is unchanged"
  238 +fi
  239 +
  240 +rm -f $TMPH
cpu-i386.h
@@ -244,5 +244,6 @@ void cpu_x86_close(CPUX86State *s); @@ -244,5 +244,6 @@ void cpu_x86_close(CPUX86State *s);
244 /* internal functions */ 244 /* internal functions */
245 int cpu_x86_gen_code(uint8_t *gen_code_buf, int max_code_size, 245 int cpu_x86_gen_code(uint8_t *gen_code_buf, int max_code_size,
246 int *gen_code_size_ptr, uint8_t *pc_start); 246 int *gen_code_size_ptr, uint8_t *pc_start);
  247 +void cpu_x86_tblocks_init(void);
247 248
248 #endif /* CPU_I386_H */ 249 #endif /* CPU_I386_H */
dyngen.c
  1 +/*
  2 + * Generic Dynamic compiler generator
  3 + *
  4 + * Copyright (c) 2003 Fabrice Bellard
  5 + *
  6 + * This program is free software; you can redistribute it and/or modify
  7 + * it under the terms of the GNU General Public License as published by
  8 + * the Free Software Foundation; either version 2 of the License, or
  9 + * (at your option) any later version.
  10 + *
  11 + * This program is distributed in the hope that it will be useful,
  12 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14 + * GNU General Public License for more details.
  15 + *
  16 + * You should have received a copy of the GNU General Public License
  17 + * along with this program; if not, write to the Free Software
  18 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19 + */
1 #include <stdlib.h> 20 #include <stdlib.h>
2 #include <stdio.h> 21 #include <stdio.h>
3 #include <stdarg.h> 22 #include <stdarg.h>
exec-i386.c 0 โ†’ 100644
  1 +/*
  2 + * i386 emulator main execution loop
  3 + *
  4 + * Copyright (c) 2003 Fabrice Bellard
  5 + *
  6 + * This program is free software; you can redistribute it and/or modify
  7 + * it under the terms of the GNU General Public License as published by
  8 + * the Free Software Foundation; either version 2 of the License, or
  9 + * (at your option) any later version.
  10 + *
  11 + * This program is distributed in the hope that it will be useful,
  12 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14 + * GNU General Public License for more details.
  15 + *
  16 + * You should have received a copy of the GNU General Public License
  17 + * along with this program; if not, write to the Free Software
  18 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19 + */
  20 +#include "exec-i386.h"
  21 +
  22 +#define DEBUG_EXEC
  23 +#define DEBUG_FLUSH
  24 +
  25 +/* main execution loop */
  26 +
  27 +/* maximum total translate dcode allocated */
  28 +#define CODE_GEN_BUFFER_SIZE (2048 * 1024)
  29 +//#define CODE_GEN_BUFFER_SIZE (128 * 1024)
  30 +#define CODE_GEN_MAX_SIZE 65536
  31 +#define CODE_GEN_ALIGN 16 /* must be >= of the size of a icache line */
  32 +
  33 +/* threshold to flush the translated code buffer */
  34 +#define CODE_GEN_BUFFER_MAX_SIZE (CODE_GEN_BUFFER_SIZE - CODE_GEN_MAX_SIZE)
  35 +
  36 +#define CODE_GEN_MAX_BLOCKS (CODE_GEN_BUFFER_SIZE / 64)
  37 +#define CODE_GEN_HASH_BITS 15
  38 +#define CODE_GEN_HASH_SIZE (1 << CODE_GEN_HASH_BITS)
  39 +typedef struct TranslationBlock {
  40 + unsigned long pc; /* simulated PC corresponding to this block */
  41 + uint8_t *tc_ptr; /* pointer to the translated code */
  42 + struct TranslationBlock *hash_next; /* next matching block */
  43 +} TranslationBlock;
  44 +
  45 +TranslationBlock tbs[CODE_GEN_MAX_BLOCKS];
  46 +TranslationBlock *tb_hash[CODE_GEN_HASH_SIZE];
  47 +int nb_tbs;
  48 +
  49 +uint8_t code_gen_buffer[CODE_GEN_BUFFER_SIZE];
  50 +uint8_t *code_gen_ptr;
  51 +
  52 +#ifdef DEBUG_EXEC
  53 +static const char *cc_op_str[] = {
  54 + "DYNAMIC",
  55 + "EFLAGS",
  56 + "MUL",
  57 + "ADDB",
  58 + "ADDW",
  59 + "ADDL",
  60 + "ADCB",
  61 + "ADCW",
  62 + "ADCL",
  63 + "SUBB",
  64 + "SUBW",
  65 + "SUBL",
  66 + "SBBB",
  67 + "SBBW",
  68 + "SBBL",
  69 + "LOGICB",
  70 + "LOGICW",
  71 + "LOGICL",
  72 + "INCB",
  73 + "INCW",
  74 + "INCL",
  75 + "DECB",
  76 + "DECW",
  77 + "DECL",
  78 + "SHLB",
  79 + "SHLW",
  80 + "SHLL",
  81 + "SARB",
  82 + "SARW",
  83 + "SARL",
  84 +};
  85 +
  86 +static void cpu_x86_dump_state(void)
  87 +{
  88 + int eflags;
  89 + eflags = cc_table[CC_OP].compute_all();
  90 + eflags |= (DF & DIRECTION_FLAG);
  91 + fprintf(logfile,
  92 + "EAX=%08x EBX=%08X ECX=%08x EDX=%08x\n"
  93 + "ESI=%08x EDI=%08X EBP=%08x ESP=%08x\n"
  94 + "CCS=%08x CCD=%08x CCO=%-8s EFL=%c%c%c%c%c%c%c\n",
  95 + env->regs[R_EAX], env->regs[R_EBX], env->regs[R_ECX], env->regs[R_EDX],
  96 + env->regs[R_ESI], env->regs[R_EDI], env->regs[R_EBP], env->regs[R_ESP],
  97 + env->cc_src, env->cc_dst, cc_op_str[env->cc_op],
  98 + eflags & DIRECTION_FLAG ? 'D' : '-',
  99 + eflags & CC_O ? 'O' : '-',
  100 + eflags & CC_S ? 'S' : '-',
  101 + eflags & CC_Z ? 'Z' : '-',
  102 + eflags & CC_A ? 'A' : '-',
  103 + eflags & CC_P ? 'P' : '-',
  104 + eflags & CC_C ? 'C' : '-'
  105 + );
  106 +#if 1
  107 + fprintf(logfile, "ST0=%f ST1=%f ST2=%f ST3=%f\n",
  108 + (double)ST0, (double)ST1, (double)ST(2), (double)ST(3));
  109 +#endif
  110 +}
  111 +
  112 +#endif
  113 +
  114 +void cpu_x86_tblocks_init(void)
  115 +{
  116 + if (!code_gen_ptr) {
  117 + code_gen_ptr = code_gen_buffer;
  118 + }
  119 +}
  120 +
  121 +/* flush all the translation blocks */
  122 +static void tb_flush(void)
  123 +{
  124 + int i;
  125 +#ifdef DEBUG_FLUSH
  126 + printf("gemu: flush code_size=%d nb_tbs=%d avg_tb_size=%d\n",
  127 + code_gen_ptr - code_gen_buffer,
  128 + nb_tbs,
  129 + (code_gen_ptr - code_gen_buffer) / nb_tbs);
  130 +#endif
  131 + nb_tbs = 0;
  132 + for(i = 0;i < CODE_GEN_HASH_SIZE; i++)
  133 + tb_hash[i] = NULL;
  134 + code_gen_ptr = code_gen_buffer;
  135 + /* XXX: flush processor icache at this point */
  136 +}
  137 +
  138 +/* find a translation block in the translation cache. If not found,
  139 + allocate a new one */
  140 +static inline TranslationBlock *tb_find_and_alloc(unsigned long pc)
  141 +{
  142 + TranslationBlock **ptb, *tb;
  143 + unsigned int h;
  144 +
  145 + h = pc & (CODE_GEN_HASH_SIZE - 1);
  146 + ptb = &tb_hash[h];
  147 + for(;;) {
  148 + tb = *ptb;
  149 + if (!tb)
  150 + break;
  151 + if (tb->pc == pc)
  152 + return tb;
  153 + ptb = &tb->hash_next;
  154 + }
  155 + if (nb_tbs >= CODE_GEN_MAX_BLOCKS ||
  156 + (code_gen_ptr - code_gen_buffer) >= CODE_GEN_BUFFER_MAX_SIZE)
  157 + tb_flush();
  158 + tb = &tbs[nb_tbs++];
  159 + *ptb = tb;
  160 + tb->pc = pc;
  161 + tb->tc_ptr = NULL;
  162 + tb->hash_next = NULL;
  163 + return tb;
  164 +}
  165 +
  166 +int cpu_x86_exec(CPUX86State *env1)
  167 +{
  168 + int saved_T0, saved_T1, saved_A0;
  169 + CPUX86State *saved_env;
  170 + int code_gen_size, ret;
  171 + void (*gen_func)(void);
  172 + TranslationBlock *tb;
  173 + uint8_t *tc_ptr;
  174 +
  175 + /* first we save global registers */
  176 + saved_T0 = T0;
  177 + saved_T1 = T1;
  178 + saved_A0 = A0;
  179 + saved_env = env;
  180 + env = env1;
  181 +
  182 + /* prepare setjmp context for exception handling */
  183 + if (setjmp(env->jmp_env) == 0) {
  184 + for(;;) {
  185 +#ifdef DEBUG_EXEC
  186 + if (loglevel) {
  187 + cpu_x86_dump_state();
  188 + }
  189 +#endif
  190 + tb = tb_find_and_alloc((unsigned long)env->pc);
  191 + tc_ptr = tb->tc_ptr;
  192 + if (!tb->tc_ptr) {
  193 + /* if no translated code available, then translate it now */
  194 + tc_ptr = code_gen_ptr;
  195 + cpu_x86_gen_code(code_gen_ptr, CODE_GEN_MAX_SIZE,
  196 + &code_gen_size, (uint8_t *)env->pc);
  197 + tb->tc_ptr = tc_ptr;
  198 + code_gen_ptr = (void *)(((unsigned long)code_gen_ptr + code_gen_size + CODE_GEN_ALIGN - 1) & ~(CODE_GEN_ALIGN - 1));
  199 + }
  200 + /* execute the generated code */
  201 + gen_func = (void *)tc_ptr;
  202 + gen_func();
  203 + }
  204 + }
  205 + ret = env->exception_index;
  206 +
  207 + /* restore global registers */
  208 + T0 = saved_T0;
  209 + T1 = saved_T1;
  210 + A0 = saved_A0;
  211 + env = saved_env;
  212 + return ret;
  213 +}
exec-i386.h 0 โ†’ 100644
  1 +/* i386 execution defines */
  2 +
  3 +typedef unsigned char uint8_t;
  4 +typedef unsigned short uint16_t;
  5 +typedef unsigned int uint32_t;
  6 +typedef unsigned long long uint64_t;
  7 +
  8 +typedef signed char int8_t;
  9 +typedef signed short int16_t;
  10 +typedef signed int int32_t;
  11 +typedef signed long long int64_t;
  12 +
  13 +#define bswap32(x) \
  14 +({ \
  15 + uint32_t __x = (x); \
  16 + ((uint32_t)( \
  17 + (((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \
  18 + (((uint32_t)(__x) & (uint32_t)0x0000ff00UL) << 8) | \
  19 + (((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >> 8) | \
  20 + (((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) )); \
  21 +})
  22 +
  23 +#define NULL 0
  24 +#include <fenv.h>
  25 +
  26 +typedef struct FILE FILE;
  27 +extern FILE *logfile;
  28 +extern int loglevel;
  29 +extern int fprintf(FILE *, const char *, ...);
  30 +
  31 +#ifdef __i386__
  32 +register unsigned int T0 asm("ebx");
  33 +register unsigned int T1 asm("esi");
  34 +register unsigned int A0 asm("edi");
  35 +register struct CPUX86State *env asm("ebp");
  36 +#endif
  37 +#ifdef __powerpc__
  38 +register unsigned int T0 asm("r24");
  39 +register unsigned int T1 asm("r25");
  40 +register unsigned int A0 asm("r26");
  41 +register struct CPUX86State *env asm("r27");
  42 +#endif
  43 +#ifdef __arm__
  44 +register unsigned int T0 asm("r4");
  45 +register unsigned int T1 asm("r5");
  46 +register unsigned int A0 asm("r6");
  47 +register struct CPUX86State *env asm("r7");
  48 +#endif
  49 +#ifdef __mips__
  50 +register unsigned int T0 asm("s0");
  51 +register unsigned int T1 asm("s1");
  52 +register unsigned int A0 asm("s2");
  53 +register struct CPUX86State *env asm("s3");
  54 +#endif
  55 +#ifdef __sparc__
  56 +register unsigned int T0 asm("l0");
  57 +register unsigned int T1 asm("l1");
  58 +register unsigned int A0 asm("l2");
  59 +register struct CPUX86State *env asm("l3");
  60 +#endif
  61 +
  62 +/* force GCC to generate only one epilog at the end of the function */
  63 +#define FORCE_RET() asm volatile ("");
  64 +
  65 +#ifndef OPPROTO
  66 +#define OPPROTO
  67 +#endif
  68 +
  69 +#define xglue(x, y) x ## y
  70 +#define glue(x, y) xglue(x, y)
  71 +
  72 +#define EAX (env->regs[R_EAX])
  73 +#define ECX (env->regs[R_ECX])
  74 +#define EDX (env->regs[R_EDX])
  75 +#define EBX (env->regs[R_EBX])
  76 +#define ESP (env->regs[R_ESP])
  77 +#define EBP (env->regs[R_EBP])
  78 +#define ESI (env->regs[R_ESI])
  79 +#define EDI (env->regs[R_EDI])
  80 +#define PC (env->pc)
  81 +#define DF (env->df)
  82 +
  83 +#define CC_SRC (env->cc_src)
  84 +#define CC_DST (env->cc_dst)
  85 +#define CC_OP (env->cc_op)
  86 +
  87 +/* float macros */
  88 +#define FT0 (env->ft0)
  89 +#define ST0 (env->fpregs[env->fpstt])
  90 +#define ST(n) (env->fpregs[(env->fpstt + (n)) & 7])
  91 +#define ST1 ST(1)
  92 +
  93 +extern int __op_param1, __op_param2, __op_param3;
  94 +#define PARAM1 ((long)(&__op_param1))
  95 +#define PARAM2 ((long)(&__op_param2))
  96 +#define PARAM3 ((long)(&__op_param3))
  97 +
  98 +#include "cpu-i386.h"
  99 +
  100 +typedef struct CCTable {
  101 + int (*compute_all)(void); /* return all the flags */
  102 + int (*compute_c)(void); /* return the C flag */
  103 +} CCTable;
  104 +
  105 +extern CCTable cc_table[];
linux-user/main.c
@@ -87,7 +87,7 @@ int cpu_x86_inl(int addr) @@ -87,7 +87,7 @@ int cpu_x86_inl(int addr)
87 87
88 void usage(void) 88 void usage(void)
89 { 89 {
90 - printf("gemu version 0.1, Copyright (c) 2003 Fabrice Bellard\n" 90 + printf("gemu version" GEMU_VERSION ", Copyright (c) 2003 Fabrice Bellard\n"
91 "usage: gemu [-d] program [arguments...]\n" 91 "usage: gemu [-d] program [arguments...]\n"
92 "Linux x86 emulator\n" 92 "Linux x86 emulator\n"
93 ); 93 );
linux-user/syscall.c
@@ -628,6 +628,9 @@ long do_syscall(int num, long arg1, long arg2, long arg3, @@ -628,6 +628,9 @@ long do_syscall(int num, long arg1, long arg2, long arg3,
628 #endif 628 #endif
629 switch(num) { 629 switch(num) {
630 case TARGET_NR_exit: 630 case TARGET_NR_exit:
  631 +#ifdef HAVE_GPROF
  632 + _mcleanup();
  633 +#endif
631 _exit(arg1); 634 _exit(arg1);
632 ret = 0; /* avoid warning */ 635 ret = 0; /* avoid warning */
633 break; 636 break;
op-i386.c
1 -#define DEBUG_EXEC  
2 -  
3 -typedef unsigned char uint8_t;  
4 -typedef unsigned short uint16_t;  
5 -typedef unsigned int uint32_t;  
6 -typedef unsigned long long uint64_t;  
7 -  
8 -typedef signed char int8_t;  
9 -typedef signed short int16_t;  
10 -typedef signed int int32_t;  
11 -typedef signed long long int64_t;  
12 -  
13 -#define bswap32(x) \  
14 -({ \  
15 - uint32_t __x = (x); \  
16 - ((uint32_t)( \  
17 - (((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \  
18 - (((uint32_t)(__x) & (uint32_t)0x0000ff00UL) << 8) | \  
19 - (((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >> 8) | \  
20 - (((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) )); \  
21 -})  
22 -  
23 -#define NULL 0  
24 -#include <fenv.h>  
25 -  
26 -typedef struct FILE FILE;  
27 -extern FILE *logfile;  
28 -extern int loglevel;  
29 -extern int fprintf(FILE *, const char *, ...);  
30 -  
31 -#ifdef __i386__  
32 -register unsigned int T0 asm("ebx");  
33 -register unsigned int T1 asm("esi");  
34 -register unsigned int A0 asm("edi");  
35 -register struct CPUX86State *env asm("ebp");  
36 -#endif  
37 -#ifdef __powerpc__  
38 -register unsigned int T0 asm("r24");  
39 -register unsigned int T1 asm("r25");  
40 -register unsigned int A0 asm("r26");  
41 -register struct CPUX86State *env asm("r27");  
42 -#endif  
43 -#ifdef __arm__  
44 -register unsigned int T0 asm("r4");  
45 -register unsigned int T1 asm("r5");  
46 -register unsigned int A0 asm("r6");  
47 -register struct CPUX86State *env asm("r7");  
48 -#endif  
49 -#ifdef __mips__  
50 -register unsigned int T0 asm("s0");  
51 -register unsigned int T1 asm("s1");  
52 -register unsigned int A0 asm("s2");  
53 -register struct CPUX86State *env asm("s3");  
54 -#endif  
55 -#ifdef __sparc__  
56 -register unsigned int T0 asm("l0");  
57 -register unsigned int T1 asm("l1");  
58 -register unsigned int A0 asm("l2");  
59 -register struct CPUX86State *env asm("l3");  
60 -#endif  
61 -  
62 -/* force GCC to generate only one epilog at the end of the function */  
63 -#define FORCE_RET() asm volatile ("");  
64 -  
65 -#ifndef OPPROTO  
66 -#define OPPROTO  
67 -#endif  
68 -  
69 -#define xglue(x, y) x ## y  
70 -#define glue(x, y) xglue(x, y)  
71 -  
72 -#define EAX (env->regs[R_EAX])  
73 -#define ECX (env->regs[R_ECX])  
74 -#define EDX (env->regs[R_EDX])  
75 -#define EBX (env->regs[R_EBX])  
76 -#define ESP (env->regs[R_ESP])  
77 -#define EBP (env->regs[R_EBP])  
78 -#define ESI (env->regs[R_ESI])  
79 -#define EDI (env->regs[R_EDI])  
80 -#define PC (env->pc)  
81 -#define DF (env->df)  
82 -  
83 -#define CC_SRC (env->cc_src)  
84 -#define CC_DST (env->cc_dst)  
85 -#define CC_OP (env->cc_op)  
86 -  
87 -/* float macros */  
88 -#define FT0 (env->ft0)  
89 -#define ST0 (env->fpregs[env->fpstt])  
90 -#define ST(n) (env->fpregs[(env->fpstt + (n)) & 7])  
91 -#define ST1 ST(1)  
92 -  
93 -extern int __op_param1, __op_param2, __op_param3;  
94 -#define PARAM1 ((long)(&__op_param1))  
95 -#define PARAM2 ((long)(&__op_param2))  
96 -#define PARAM3 ((long)(&__op_param3))  
97 -  
98 -#include "cpu-i386.h"  
99 -  
100 -typedef struct CCTable {  
101 - int (*compute_all)(void); /* return all the flags */  
102 - int (*compute_c)(void); /* return the C flag */  
103 -} CCTable; 1 +/*
  2 + * i386 micro operations
  3 + *
  4 + * Copyright (c) 2003 Fabrice Bellard
  5 + *
  6 + * This program is free software; you can redistribute it and/or modify
  7 + * it under the terms of the GNU General Public License as published by
  8 + * the Free Software Foundation; either version 2 of the License, or
  9 + * (at your option) any later version.
  10 + *
  11 + * This program is distributed in the hope that it will be useful,
  12 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14 + * GNU General Public License for more details.
  15 + *
  16 + * You should have received a copy of the GNU General Public License
  17 + * along with this program; if not, write to the Free Software
  18 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19 + */
  20 +#include "exec-i386.h"
104 21
105 /* NOTE: data are not static to force relocation generation by GCC */ 22 /* NOTE: data are not static to force relocation generation by GCC */
106 -extern CCTable cc_table[];  
107 23
108 uint8_t parity_table[256] = { 24 uint8_t parity_table[256] = {
109 CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, 25 CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
@@ -1878,100 +1794,3 @@ void OPPROTO op_fldcw_A0(void) @@ -1878,100 +1794,3 @@ void OPPROTO op_fldcw_A0(void)
1878 fesetround(rnd_type); 1794 fesetround(rnd_type);
1879 } 1795 }
1880 1796
1881 -/* main execution loop */  
1882 -uint8_t code_gen_buffer[65536];  
1883 -  
1884 -#ifdef DEBUG_EXEC  
1885 -static const char *cc_op_str[] = {  
1886 - "DYNAMIC",  
1887 - "EFLAGS",  
1888 - "MUL",  
1889 - "ADDB",  
1890 - "ADDW",  
1891 - "ADDL",  
1892 - "ADCB",  
1893 - "ADCW",  
1894 - "ADCL",  
1895 - "SUBB",  
1896 - "SUBW",  
1897 - "SUBL",  
1898 - "SBBB",  
1899 - "SBBW",  
1900 - "SBBL",  
1901 - "LOGICB",  
1902 - "LOGICW",  
1903 - "LOGICL",  
1904 - "INCB",  
1905 - "INCW",  
1906 - "INCL",  
1907 - "DECB",  
1908 - "DECW",  
1909 - "DECL",  
1910 - "SHLB",  
1911 - "SHLW",  
1912 - "SHLL",  
1913 - "SARB",  
1914 - "SARW",  
1915 - "SARL",  
1916 -};  
1917 -#endif  
1918 -  
1919 -int cpu_x86_exec(CPUX86State *env1)  
1920 -{  
1921 - int saved_T0, saved_T1, saved_A0;  
1922 - CPUX86State *saved_env;  
1923 - int code_gen_size, ret;  
1924 - void (*gen_func)(void);  
1925 -  
1926 - /* first we save global registers */  
1927 - saved_T0 = T0;  
1928 - saved_T1 = T1;  
1929 - saved_A0 = A0;  
1930 - saved_env = env;  
1931 - env = env1;  
1932 -  
1933 - /* prepare setjmp context for exception handling */  
1934 - if (setjmp(env->jmp_env) == 0) {  
1935 - for(;;) {  
1936 -#ifdef DEBUG_EXEC  
1937 - if (loglevel) {  
1938 - int eflags;  
1939 - eflags = cc_table[CC_OP].compute_all();  
1940 - eflags |= (DF & DIRECTION_FLAG);  
1941 - fprintf(logfile,  
1942 - "EAX=%08x EBX=%08X ECX=%08x EDX=%08x\n"  
1943 - "ESI=%08x EDI=%08X EBP=%08x ESP=%08x\n"  
1944 - "CCS=%08x CCD=%08x CCO=%-8s EFL=%c%c%c%c%c%c%c\n",  
1945 - env->regs[R_EAX], env->regs[R_EBX], env->regs[R_ECX], env->regs[R_EDX],  
1946 - env->regs[R_ESI], env->regs[R_EDI], env->regs[R_EBP], env->regs[R_ESP],  
1947 - env->cc_src, env->cc_dst, cc_op_str[env->cc_op],  
1948 - eflags & DIRECTION_FLAG ? 'D' : '-',  
1949 - eflags & CC_O ? 'O' : '-',  
1950 - eflags & CC_S ? 'S' : '-',  
1951 - eflags & CC_Z ? 'Z' : '-',  
1952 - eflags & CC_A ? 'A' : '-',  
1953 - eflags & CC_P ? 'P' : '-',  
1954 - eflags & CC_C ? 'C' : '-'  
1955 - );  
1956 -#if 1  
1957 - fprintf(logfile, "ST0=%f ST1=%f ST2=%f ST3=%f\n",  
1958 - (double)ST0, (double)ST1, (double)ST(2), (double)ST(3));  
1959 -#endif  
1960 - }  
1961 -#endif  
1962 - cpu_x86_gen_code(code_gen_buffer, sizeof(code_gen_buffer),  
1963 - &code_gen_size, (uint8_t *)env->pc);  
1964 - /* execute the generated code */  
1965 - gen_func = (void *)code_gen_buffer;  
1966 - gen_func();  
1967 - }  
1968 - }  
1969 - ret = env->exception_index;  
1970 -  
1971 - /* restore global registers */  
1972 - T0 = saved_T0;  
1973 - T1 = saved_T1;  
1974 - A0 = saved_A0;  
1975 - env = saved_env;  
1976 - return ret;  
1977 -}  
tests/Makefile
1 -CC=gcc 1 +include ../config.mak
  2 +
2 CFLAGS=-Wall -O2 -g 3 CFLAGS=-Wall -O2 -g
3 LDFLAGS= 4 LDFLAGS=
4 5
  6 +ifeq ($(ARCH),i386)
5 TESTS=hello test2 sha1 test-i386 7 TESTS=hello test2 sha1 test-i386
6 -TESTS+=op-i386.o #op-i386.o op-ppc.o op-arm.o op-mips.o op-sparc.o 8 +endif
7 9
8 GEMU=../gemu 10 GEMU=../gemu
9 11
@@ -24,22 +26,6 @@ test: test-i386 @@ -24,22 +26,6 @@ test: test-i386
24 $(GEMU) test-i386 > test-i386.out 26 $(GEMU) test-i386 > test-i386.out
25 @if diff -u test-i386.ref test-i386.out ; then echo "Auto Test OK"; fi 27 @if diff -u test-i386.ref test-i386.out ; then echo "Auto Test OK"; fi
26 28
27 -# dyngen tests  
28 -op-i386.o: op.c  
29 - gcc $(CFLAGS) -c -o $@ $<  
30 -  
31 -op-ppc.o: op.c  
32 - powerpc-linux-gcc $(CFLAGS) -c -o $@ $<  
33 -  
34 -op-arm.o: op.c  
35 - arm-linux-gcc $(CFLAGS) -c -o $@ $<  
36 -  
37 -op-mips.o: op.c  
38 - mips-linux-gcc $(CFLAGS) -mno-abicalls -c -o $@ $<  
39 -  
40 -op-sparc.o: op.c  
41 - sparc-linux-gcc $(CFLAGS) -mflat -c -o $@ $<  
42 -  
43 # speed test 29 # speed test
44 sha1: sha1.c 30 sha1: sha1.c
45 $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< 31 $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $<
@@ -48,6 +34,5 @@ speed: sha1 @@ -48,6 +34,5 @@ speed: sha1
48 time ./sha1 34 time ./sha1
49 time $(GEMU) sha1 35 time $(GEMU) sha1
50 36
51 -# interpreter test  
52 -interp: interp.c interploop.c  
53 - $(CC) $(CFLAGS) -fomit-frame-pointer $(LDFLAGS) -o $@ $^ 37 +clean:
  38 + rm -f *~ *.o $(TESTS)
@@ -2,7 +2,7 @@ @@ -2,7 +2,7 @@
2 #define THUNK_H 2 #define THUNK_H
3 3
4 #include <inttypes.h> 4 #include <inttypes.h>
5 -#include <endian.h> 5 +#include "config.h"
6 6
7 #ifdef HAVE_BYTESWAP_H 7 #ifdef HAVE_BYTESWAP_H
8 #include <byteswap.h> 8 #include <byteswap.h>
@@ -42,11 +42,6 @@ @@ -42,11 +42,6 @@
42 42
43 #endif 43 #endif
44 44
45 -#undef WORDS_BIGENDIAN  
46 -#if __BYTE_ORDER == __BIG_ENDIAN  
47 -#define WORDS_BIGENDIAN  
48 -#endif  
49 -  
50 #ifdef WORDS_BIGENDIAN 45 #ifdef WORDS_BIGENDIAN
51 #define BSWAP_NEEDED 46 #define BSWAP_NEEDED
52 #endif 47 #endif
translate-i386.c
  1 +/*
  2 + * i386 translation
  3 + *
  4 + * Copyright (c) 2003 Fabrice Bellard
  5 + *
  6 + * This program is free software; you can redistribute it and/or modify
  7 + * it under the terms of the GNU General Public License as published by
  8 + * the Free Software Foundation; either version 2 of the License, or
  9 + * (at your option) any later version.
  10 + *
  11 + * This program is distributed in the hope that it will be useful,
  12 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14 + * GNU General Public License for more details.
  15 + *
  16 + * You should have received a copy of the GNU General Public License
  17 + * along with this program; if not, write to the Free Software
  18 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19 + */
1 #include <stdarg.h> 20 #include <stdarg.h>
2 #include <stdlib.h> 21 #include <stdlib.h>
3 #include <stdio.h> 22 #include <stdio.h>
@@ -2591,6 +2610,8 @@ CPUX86State *cpu_x86_init(void) @@ -2591,6 +2610,8 @@ CPUX86State *cpu_x86_init(void)
2591 CPUX86State *env; 2610 CPUX86State *env;
2592 int i; 2611 int i;
2593 2612
  2613 + cpu_x86_tblocks_init();
  2614 +
2594 env = malloc(sizeof(CPUX86State)); 2615 env = malloc(sizeof(CPUX86State));
2595 if (!env) 2616 if (!env)
2596 return NULL; 2617 return NULL;