Revision 7d13299d

b/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 4
LDFLAGS=-g
8 5
LIBS=
9
CC=gcc
10 6
DEFINES=-DHAVE_BYTESWAP_H
7

  
8
ifeq ($(ARCH),i386)
9
CFLAGS+=-fomit-frame-pointer
11 10
OP_CFLAGS=$(CFLAGS) -malign-functions=0 -mpreferred-stack-boundary=2
12 11
endif
13 12

  
14 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 14
OP_CFLAGS=$(CFLAGS)
29 15
endif
30 16

  
31 17
#########################################################
32 18

  
33 19
DEFINES+=-D_GNU_SOURCE
34
DEFINES+=-DCONFIG_PREFIX=\"/usr/local\"
35 20
LDSCRIPT=$(ARCH).ld
36 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 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 31
# NOTE: the disassembler code is only needed for debugging
42 32
OBJS+=i386-dis.o dis-buf.o
43 33
SRCS = $(OBJS:.o=.c)
......
66 56
	$(CC) $(CFLAGS) $(DEFINES) -c -o $@ $<
67 57

  
68 58
clean:
59
	$(MAKE) -C tests clean
69 60
	rm -f *.o *~ gemu dyngen TAGS
70 61

  
62
distclean: clean
63
	rm -f config.mak config.h
64

  
71 65
# various test targets
72 66
test speed: gemu
73 67
	make -C tests $@
......
82 76
cpu-i386.h   gemu.h      op-i386.c         syscall-i386.h  translate-i386.c\
83 77
dis-asm.h    gen-i386.h  op-i386.h         syscall.c\
84 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 80
tests/Makefile\
87 81
tests/test-i386.c tests/test-i386-shift.h tests/test-i386.h\
88 82
tests/test-i386-muldiv.h\
b/TODO
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 4
- signals
3 5
- threads
4
- fix printf for doubles (fp87.c bug ?)
5 6
- make it self runnable (use same trick as ld.so : include its own relocator and libc)
6 7
- fix FPU exceptions (in particular: gen_op_fpush not before mem load)
8
- tests
b/configure
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
b/cpu-i386.h
244 244
/* internal functions */
245 245
int cpu_x86_gen_code(uint8_t *gen_code_buf, int max_code_size, 
246 246
                     int *gen_code_size_ptr, uint8_t *pc_start);
247
void cpu_x86_tblocks_init(void);
247 248

  
248 249
#endif /* CPU_I386_H */
b/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 20
#include <stdlib.h>
2 21
#include <stdio.h>
3 22
#include <stdarg.h>
b/exec-i386.c
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
}
b/exec-i386.h
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[];
b/linux-user/main.c
87 87

  
88 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 91
           "usage: gemu [-d] program [arguments...]\n"
92 92
           "Linux x86 emulator\n"
93 93
           );
b/linux-user/syscall.c
628 628
#endif
629 629
    switch(num) {
630 630
    case TARGET_NR_exit:
631
#ifdef HAVE_GPROF
632
        _mcleanup();
633
#endif
631 634
        _exit(arg1);
632 635
        ret = 0; /* avoid warning */
633 636
        break;
b/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 22
/* NOTE: data are not static to force relocation generation by GCC */
106
extern CCTable cc_table[];
107 23

  
108 24
uint8_t parity_table[256] = {
109 25
    CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
......
1878 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
}
b/tests/Makefile
1
CC=gcc
1
include ../config.mak
2

  
2 3
CFLAGS=-Wall -O2 -g
3 4
LDFLAGS=
4 5

  
6
ifeq ($(ARCH),i386)
5 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 10
GEMU=../gemu
9 11

  
......
24 26
	$(GEMU) test-i386 > test-i386.out
25 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 29
# speed test
44 30
sha1: sha1.c
45 31
	$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $<
......
48 34
	time ./sha1
49 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)
b/thunk.h
2 2
#define THUNK_H
3 3

  
4 4
#include <inttypes.h>
5
#include <endian.h>
5
#include "config.h"
6 6

  
7 7
#ifdef HAVE_BYTESWAP_H
8 8
#include <byteswap.h>
......
42 42

  
43 43
#endif
44 44

  
45
#undef WORDS_BIGENDIAN
46
#if __BYTE_ORDER == __BIG_ENDIAN
47
#define WORDS_BIGENDIAN
48
#endif
49

  
50 45
#ifdef WORDS_BIGENDIAN
51 46
#define BSWAP_NEEDED
52 47
#endif
b/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 20
#include <stdarg.h>
2 21
#include <stdlib.h>
3 22
#include <stdio.h>
......
2591 2610
    CPUX86State *env;
2592 2611
    int i;
2593 2612

  
2613
    cpu_x86_tblocks_init();
2614

  
2594 2615
    env = malloc(sizeof(CPUX86State));
2595 2616
    if (!env)
2596 2617
        return NULL;

Also available in: Unified diff