added translation cache
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@25 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
1017ebe9cb
commit
7d13299d07
40
Makefile
40
Makefile
@ -1,43 +1,33 @@
|
|||||||
ARCH=i386
|
include config.mak
|
||||||
#ARCH=ppc
|
|
||||||
HOST_CC=gcc
|
|
||||||
|
|
||||||
ifeq ($(ARCH),i386)
|
CFLAGS=-Wall -O2 -g
|
||||||
CFLAGS=-Wall -O2 -g -fomit-frame-pointer
|
|
||||||
LDFLAGS=-g
|
LDFLAGS=-g
|
||||||
LIBS=
|
LIBS=
|
||||||
CC=gcc
|
|
||||||
DEFINES=-DHAVE_BYTESWAP_H
|
DEFINES=-DHAVE_BYTESWAP_H
|
||||||
|
|
||||||
|
ifeq ($(ARCH),i386)
|
||||||
|
CFLAGS+=-fomit-frame-pointer
|
||||||
OP_CFLAGS=$(CFLAGS) -malign-functions=0 -mpreferred-stack-boundary=2
|
OP_CFLAGS=$(CFLAGS) -malign-functions=0 -mpreferred-stack-boundary=2
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(ARCH),ppc)
|
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)
|
OP_CFLAGS=$(CFLAGS)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
#########################################################
|
#########################################################
|
||||||
|
|
||||||
DEFINES+=-D_GNU_SOURCE
|
DEFINES+=-D_GNU_SOURCE
|
||||||
DEFINES+=-DCONFIG_PREFIX=\"/usr/local\"
|
|
||||||
LDSCRIPT=$(ARCH).ld
|
LDSCRIPT=$(ARCH).ld
|
||||||
LIBS+=-ldl -lm
|
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= 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
|
# NOTE: the disassembler code is only needed for debugging
|
||||||
OBJS+=i386-dis.o dis-buf.o
|
OBJS+=i386-dis.o dis-buf.o
|
||||||
SRCS = $(OBJS:.o=.c)
|
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 $@ $<
|
$(CC) $(CFLAGS) $(DEFINES) -c -o $@ $<
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
|
$(MAKE) -C tests clean
|
||||||
rm -f *.o *~ gemu dyngen TAGS
|
rm -f *.o *~ gemu dyngen TAGS
|
||||||
|
|
||||||
|
distclean: clean
|
||||||
|
rm -f config.mak config.h
|
||||||
|
|
||||||
# various test targets
|
# various test targets
|
||||||
test speed: gemu
|
test speed: gemu
|
||||||
make -C tests $@
|
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\
|
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-asm.h gen-i386.h op-i386.h syscall.c\
|
||||||
dis-buf.c i386-dis.c opreg_template.h syscall_defs.h\
|
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/Makefile\
|
||||||
tests/test-i386.c tests/test-i386-shift.h tests/test-i386.h\
|
tests/test-i386.c tests/test-i386-shift.h tests/test-i386.h\
|
||||||
tests/test-i386-muldiv.h\
|
tests/test-i386-muldiv.h\
|
||||||
|
6
TODO
6
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
|
- signals
|
||||||
- threads
|
- threads
|
||||||
- fix printf for doubles (fp87.c bug ?)
|
|
||||||
- make it self runnable (use same trick as ld.so : include its own relocator and libc)
|
- 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)
|
- fix FPU exceptions (in particular: gen_op_fpush not before mem load)
|
||||||
|
- tests
|
||||||
|
240
configure
vendored
Executable file
240
configure
vendored
Executable file
@ -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
|
@ -244,5 +244,6 @@ void cpu_x86_close(CPUX86State *s);
|
|||||||
/* internal functions */
|
/* internal functions */
|
||||||
int cpu_x86_gen_code(uint8_t *gen_code_buf, int max_code_size,
|
int cpu_x86_gen_code(uint8_t *gen_code_buf, int max_code_size,
|
||||||
int *gen_code_size_ptr, uint8_t *pc_start);
|
int *gen_code_size_ptr, uint8_t *pc_start);
|
||||||
|
void cpu_x86_tblocks_init(void);
|
||||||
|
|
||||||
#endif /* CPU_I386_H */
|
#endif /* CPU_I386_H */
|
||||||
|
19
dyngen.c
19
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 <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
213
exec-i386.c
Normal file
213
exec-i386.c
Normal file
@ -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;
|
||||||
|
}
|
105
exec-i386.h
Normal file
105
exec-i386.h
Normal file
@ -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[];
|
@ -87,7 +87,7 @@ int cpu_x86_inl(int addr)
|
|||||||
|
|
||||||
void usage(void)
|
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"
|
"usage: gemu [-d] program [arguments...]\n"
|
||||||
"Linux x86 emulator\n"
|
"Linux x86 emulator\n"
|
||||||
);
|
);
|
||||||
|
@ -628,6 +628,9 @@ long do_syscall(int num, long arg1, long arg2, long arg3,
|
|||||||
#endif
|
#endif
|
||||||
switch(num) {
|
switch(num) {
|
||||||
case TARGET_NR_exit:
|
case TARGET_NR_exit:
|
||||||
|
#ifdef HAVE_GPROF
|
||||||
|
_mcleanup();
|
||||||
|
#endif
|
||||||
_exit(arg1);
|
_exit(arg1);
|
||||||
ret = 0; /* avoid warning */
|
ret = 0; /* avoid warning */
|
||||||
break;
|
break;
|
||||||
|
221
op-i386.c
221
op-i386.c
@ -1,109 +1,25 @@
|
|||||||
#define DEBUG_EXEC
|
/*
|
||||||
|
* i386 micro operations
|
||||||
typedef unsigned char uint8_t;
|
*
|
||||||
typedef unsigned short uint16_t;
|
* Copyright (c) 2003 Fabrice Bellard
|
||||||
typedef unsigned int uint32_t;
|
*
|
||||||
typedef unsigned long long uint64_t;
|
* 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
|
||||||
typedef signed char int8_t;
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
typedef signed short int16_t;
|
* (at your option) any later version.
|
||||||
typedef signed int int32_t;
|
*
|
||||||
typedef signed long long int64_t;
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
#define bswap32(x) \
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
({ \
|
* GNU General Public License for more details.
|
||||||
uint32_t __x = (x); \
|
*
|
||||||
((uint32_t)( \
|
* You should have received a copy of the GNU General Public License
|
||||||
(((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \
|
* along with this program; if not, write to the Free Software
|
||||||
(((uint32_t)(__x) & (uint32_t)0x0000ff00UL) << 8) | \
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
(((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >> 8) | \
|
*/
|
||||||
(((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) )); \
|
#include "exec-i386.h"
|
||||||
})
|
|
||||||
|
|
||||||
#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;
|
|
||||||
|
|
||||||
/* NOTE: data are not static to force relocation generation by GCC */
|
/* NOTE: data are not static to force relocation generation by GCC */
|
||||||
extern CCTable cc_table[];
|
|
||||||
|
|
||||||
uint8_t parity_table[256] = {
|
uint8_t parity_table[256] = {
|
||||||
CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
|
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);
|
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;
|
|
||||||
}
|
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
CC=gcc
|
include ../config.mak
|
||||||
|
|
||||||
CFLAGS=-Wall -O2 -g
|
CFLAGS=-Wall -O2 -g
|
||||||
LDFLAGS=
|
LDFLAGS=
|
||||||
|
|
||||||
|
ifeq ($(ARCH),i386)
|
||||||
TESTS=hello test2 sha1 test-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
|
GEMU=../gemu
|
||||||
|
|
||||||
@ -24,22 +26,6 @@ test: test-i386
|
|||||||
$(GEMU) test-i386 > test-i386.out
|
$(GEMU) test-i386 > test-i386.out
|
||||||
@if diff -u test-i386.ref test-i386.out ; then echo "Auto Test OK"; fi
|
@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
|
# speed test
|
||||||
sha1: sha1.c
|
sha1: sha1.c
|
||||||
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $<
|
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $<
|
||||||
@ -48,6 +34,5 @@ speed: sha1
|
|||||||
time ./sha1
|
time ./sha1
|
||||||
time $(GEMU) sha1
|
time $(GEMU) sha1
|
||||||
|
|
||||||
# interpreter test
|
clean:
|
||||||
interp: interp.c interploop.c
|
rm -f *~ *.o $(TESTS)
|
||||||
$(CC) $(CFLAGS) -fomit-frame-pointer $(LDFLAGS) -o $@ $^
|
|
||||||
|
7
thunk.h
7
thunk.h
@ -2,7 +2,7 @@
|
|||||||
#define THUNK_H
|
#define THUNK_H
|
||||||
|
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <endian.h>
|
#include "config.h"
|
||||||
|
|
||||||
#ifdef HAVE_BYTESWAP_H
|
#ifdef HAVE_BYTESWAP_H
|
||||||
#include <byteswap.h>
|
#include <byteswap.h>
|
||||||
@ -42,11 +42,6 @@
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#undef WORDS_BIGENDIAN
|
|
||||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
|
||||||
#define WORDS_BIGENDIAN
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef WORDS_BIGENDIAN
|
#ifdef WORDS_BIGENDIAN
|
||||||
#define BSWAP_NEEDED
|
#define BSWAP_NEEDED
|
||||||
#endif
|
#endif
|
||||||
|
@ -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 <stdarg.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@ -2591,6 +2610,8 @@ CPUX86State *cpu_x86_init(void)
|
|||||||
CPUX86State *env;
|
CPUX86State *env;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
cpu_x86_tblocks_init();
|
||||||
|
|
||||||
env = malloc(sizeof(CPUX86State));
|
env = malloc(sizeof(CPUX86State));
|
||||||
if (!env)
|
if (!env)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
Loading…
Reference in New Issue
Block a user