Revision 586314f2
b/Makefile | ||
---|---|---|
34 | 34 |
DEFINES+=-DCONFIG_PREFIX=\"/usr/local\" |
35 | 35 |
LDSCRIPT=$(ARCH).ld |
36 | 36 |
LIBS+=-ldl -lm |
37 |
VERSION=0.1 |
|
37 | 38 |
|
38 |
#DEFINES+= -DGEMU -DDOSEMU -DNO_TRACE_MSGS |
|
39 |
#OBJS= i386/fp87.o i386/interp_main.o i386/interp_modrm.o i386/interp_16_32.o \ |
|
40 |
# i386/interp_32_16.o i386/interp_32_32.o i386/emu-utils.o \ |
|
41 |
# i386/dis8086.o i386/emu-ldt.o |
|
39 |
OBJS= elfload.o main.o thunk.o syscall.o |
|
42 | 40 |
OBJS+=translate-i386.o op-i386.o |
43 |
OBJS+= elfload.o main.o thunk.o syscall.o |
|
44 | 41 |
# NOTE: the disassembler code is only needed for debugging |
45 | 42 |
OBJS+=i386-dis.o dis-buf.o |
46 | 43 |
SRCS = $(OBJS:.o=.c) |
... | ... | |
53 | 50 |
depend: $(SRCS) |
54 | 51 |
$(CC) -MM $(CFLAGS) $^ 1>.depend |
55 | 52 |
|
56 |
# old i386 emulator |
|
57 |
i386/interp_32_32.o: i386/interp_32_32.c i386/interp_gen.h |
|
58 |
|
|
59 |
i386/interp_gen.h: i386/gencode |
|
60 |
./i386/gencode > $@ |
|
61 |
|
|
62 |
i386/gencode: i386/gencode.c |
|
63 |
$(CC) -O2 -Wall -g $< -o $@ |
|
64 |
|
|
65 | 53 |
# new i386 emulator |
66 | 54 |
dyngen: dyngen.c |
67 | 55 |
$(HOST_CC) -O2 -Wall -g $< -o $@ |
... | ... | |
78 | 66 |
$(CC) $(CFLAGS) $(DEFINES) -c -o $@ $< |
79 | 67 |
|
80 | 68 |
clean: |
81 |
rm -f *.o *~ i386/*.o i386/*~ gemu TAGS
|
|
69 |
rm -f *.o *~ gemu dyngen TAGS
|
|
82 | 70 |
|
83 | 71 |
# various test targets |
84 | 72 |
test speed: gemu |
... | ... | |
87 | 75 |
TAGS: |
88 | 76 |
etags *.[ch] i386/*.[ch] |
89 | 77 |
|
78 |
FILES= \ |
|
79 |
COPYING.LIB dyngen.c ioctls.h ops_template.h syscall_types.h\ |
|
80 |
Makefile elf.h linux_bin.h segment.h thunk.c\ |
|
81 |
TODO elfload.c main.c signal.c thunk.h\ |
|
82 |
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\ |
|
84 |
dis-buf.c i386-dis.c opreg_template.h syscall_defs.h\ |
|
85 |
i386.ld ppc.ld\ |
|
86 |
tests/test-i386.c tests/test-i386-shift.h tests/test-i386.h\ |
|
87 |
tests/test2.c tests/hello.c tests/sha1.c tests/test1.c |
|
88 |
|
|
89 |
FILE=gemu-$(VERSION) |
|
90 |
|
|
91 |
tar: |
|
92 |
rm -rf /tmp/$(FILE) |
|
93 |
mkdir -p /tmp/$(FILE) |
|
94 |
cp -P $(FILES) /tmp/$(FILE) |
|
95 |
( cd /tmp ; tar zcvf ~/$(FILE).tar.gz $(FILE) ) |
|
96 |
rm -rf /tmp/$(FILE) |
|
97 |
|
|
90 | 98 |
ifneq ($(wildcard .depend),) |
91 | 99 |
include .depend |
92 | 100 |
endif |
b/linux-user/main.c | ||
---|---|---|
27 | 27 |
|
28 | 28 |
#include "cpu-i386.h" |
29 | 29 |
|
30 |
#define DEBUG_LOGFILE "/tmp/gemu.log" |
|
31 |
|
|
32 |
FILE *logfile = NULL; |
|
33 |
int loglevel; |
|
34 |
|
|
30 | 35 |
unsigned long x86_stack_size; |
31 | 36 |
unsigned long stktop; |
32 | 37 |
|
... | ... | |
83 | 88 |
void usage(void) |
84 | 89 |
{ |
85 | 90 |
printf("gemu version 0.1, Copyright (c) 2003 Fabrice Bellard\n" |
86 |
"usage: gemu program [arguments...]\n" |
|
91 |
"usage: gemu [-d] program [arguments...]\n"
|
|
87 | 92 |
"Linux x86 emulator\n" |
88 | 93 |
); |
89 | 94 |
exit(1); |
... | ... | |
95 | 100 |
struct target_pt_regs regs1, *regs = ®s1; |
96 | 101 |
struct image_info info1, *info = &info1; |
97 | 102 |
CPUX86State *env; |
103 |
int optind; |
|
98 | 104 |
|
99 | 105 |
if (argc <= 1) |
100 | 106 |
usage(); |
101 |
|
|
102 |
filename = argv[1]; |
|
107 |
loglevel = 0; |
|
108 |
optind = 1; |
|
109 |
if (argv[optind] && !strcmp(argv[optind], "-d")) { |
|
110 |
loglevel = 1; |
|
111 |
optind++; |
|
112 |
} |
|
113 |
filename = argv[optind]; |
|
114 |
|
|
115 |
/* init debug */ |
|
116 |
if (loglevel) { |
|
117 |
logfile = fopen(DEBUG_LOGFILE, "w"); |
|
118 |
if (!logfile) { |
|
119 |
perror(DEBUG_LOGFILE); |
|
120 |
exit(1); |
|
121 |
} |
|
122 |
setvbuf(logfile, NULL, _IOLBF, 0); |
|
123 |
} |
|
103 | 124 |
|
104 | 125 |
/* Zero out regs */ |
105 | 126 |
memset(regs, 0, sizeof(struct target_pt_regs)); |
b/op-i386.c | ||
---|---|---|
1 |
#define DEBUG_EXEC |
|
2 |
|
|
1 | 3 |
typedef unsigned char uint8_t; |
2 | 4 |
typedef unsigned short uint16_t; |
3 | 5 |
typedef unsigned int uint32_t; |
... | ... | |
10 | 12 |
|
11 | 13 |
#define NULL 0 |
12 | 14 |
|
15 |
typedef struct FILE FILE; |
|
16 |
extern FILE *logfile; |
|
17 |
extern int loglevel; |
|
18 |
extern int fprintf(FILE *, const char *, ...); |
|
19 |
|
|
13 | 20 |
#ifdef __i386__ |
14 | 21 |
register int T0 asm("esi"); |
15 | 22 |
register int T1 asm("ebx"); |
... | ... | |
1636 | 1643 |
/* main execution loop */ |
1637 | 1644 |
uint8_t code_gen_buffer[65536]; |
1638 | 1645 |
|
1646 |
#ifdef DEBUG_EXEC |
|
1647 |
static const char *cc_op_str[] = { |
|
1648 |
"DYNAMIC", |
|
1649 |
"EFLAGS", |
|
1650 |
"MUL", |
|
1651 |
"ADDB", |
|
1652 |
"ADDW", |
|
1653 |
"ADDL", |
|
1654 |
"SUBB", |
|
1655 |
"SUBW", |
|
1656 |
"SUBL", |
|
1657 |
"LOGICB", |
|
1658 |
"LOGICW", |
|
1659 |
"LOGICL", |
|
1660 |
"INCB", |
|
1661 |
"INCW", |
|
1662 |
"INCL", |
|
1663 |
"DECB", |
|
1664 |
"DECW", |
|
1665 |
"DECL", |
|
1666 |
"SHLB", |
|
1667 |
"SHLW", |
|
1668 |
"SHLL", |
|
1669 |
}; |
|
1670 |
#endif |
|
1671 |
|
|
1639 | 1672 |
int cpu_x86_exec(CPUX86State *env1) |
1640 | 1673 |
{ |
1641 | 1674 |
int saved_T0, saved_T1, saved_A0; |
... | ... | |
1653 | 1686 |
/* prepare setjmp context for exception handling */ |
1654 | 1687 |
if (setjmp(env->jmp_env) == 0) { |
1655 | 1688 |
for(;;) { |
1689 |
#ifdef DEBUG_EXEC |
|
1690 |
if (loglevel) { |
|
1691 |
fprintf(logfile, |
|
1692 |
"EAX=%08x EBX=%08X ECX=%08x EDX=%08x\n" |
|
1693 |
"ESI=%08x ESI=%08X EBP=%08x ESP=%08x\n" |
|
1694 |
"CCS=%08x CCD=%08x CCOP=%s\n", |
|
1695 |
env->regs[R_EAX], env->regs[R_EBX], env->regs[R_ECX], env->regs[R_EDX], |
|
1696 |
env->regs[R_ESI], env->regs[R_EDI], env->regs[R_EBP], env->regs[R_ESP], |
|
1697 |
env->cc_src, env->cc_dst, cc_op_str[env->cc_op]); |
|
1698 |
} |
|
1699 |
#endif |
|
1656 | 1700 |
cpu_x86_gen_code(code_gen_buffer, &code_gen_size, (uint8_t *)env->pc); |
1657 | 1701 |
/* execute the generated code */ |
1658 | 1702 |
gen_func = (void *)code_gen_buffer; |
b/translate-i386.c | ||
---|---|---|
5 | 5 |
#include <inttypes.h> |
6 | 6 |
#include <assert.h> |
7 | 7 |
|
8 |
/* dump all code */ |
|
9 | 8 |
#define DEBUG_DISAS |
10 |
#define DEBUG_LOGFILE "/tmp/gemu.log" |
|
11 | 9 |
|
10 |
#define IN_OP_I386 |
|
11 |
#include "cpu-i386.h" |
|
12 |
|
|
13 |
/* dump all code */ |
|
12 | 14 |
#ifdef DEBUG_DISAS |
13 | 15 |
#include "dis-asm.h" |
14 | 16 |
#endif |
15 | 17 |
|
16 |
#define IN_OP_I386 |
|
17 |
#include "cpu-i386.h" |
|
18 |
|
|
19 | 18 |
static uint8_t *gen_code_ptr; |
20 | 19 |
int __op_param1, __op_param2, __op_param3; |
21 | 20 |
|
22 |
#ifdef DEBUG_DISAS |
|
23 |
static FILE *logfile = NULL; |
|
24 |
#endif |
|
21 |
extern FILE *logfile; |
|
22 |
extern int loglevel; |
|
25 | 23 |
|
26 | 24 |
/* supress that */ |
27 | 25 |
static void error(const char *fmt, ...) |
... | ... | |
716 | 714 |
int reg1, reg2, opreg; |
717 | 715 |
int mod, rm, code; |
718 | 716 |
|
719 |
#ifdef DEBUG_DISAS |
|
720 |
fprintf(logfile, "modrm=0x%x\n", modrm); |
|
721 |
#endif |
|
722 | 717 |
mod = (modrm >> 6) & 3; |
723 | 718 |
rm = modrm & 7; |
724 | 719 |
|
... | ... | |
731 | 726 |
if (base == 4) { |
732 | 727 |
havesib = 1; |
733 | 728 |
code = ldub(s->pc++); |
734 |
#ifdef DEBUG_DISAS |
|
735 |
fprintf(logfile, "sib=0x%x\n", code); |
|
736 |
#endif |
|
737 | 729 |
scale = (code >> 6) & 3; |
738 | 730 |
index = (code >> 3) & 7; |
739 | 731 |
base = code & 7; |
... | ... | |
988 | 980 |
// cur_pc = s->pc; /* for insn generation */ |
989 | 981 |
next_byte: |
990 | 982 |
b = ldub(s->pc); |
991 |
#ifdef DEBUG_DISAS |
|
992 |
fprintf(logfile, "ib=0x%02x\n", b); |
|
993 |
#endif |
|
994 |
if (b < 0) |
|
995 |
return -1; |
|
996 | 983 |
s->pc++; |
997 | 984 |
/* check prefixes */ |
998 | 985 |
switch (b) { |
... | ... | |
2247 | 2234 |
gen_start(); |
2248 | 2235 |
|
2249 | 2236 |
#ifdef DEBUG_DISAS |
2250 |
if (!logfile) { |
|
2251 |
logfile = fopen(DEBUG_LOGFILE, "w"); |
|
2252 |
if (!logfile) { |
|
2253 |
perror(DEBUG_LOGFILE); |
|
2254 |
exit(1); |
|
2255 |
} |
|
2256 |
setvbuf(logfile, NULL, _IOLBF, 0); |
|
2257 |
} |
|
2258 |
|
|
2259 |
INIT_DISASSEMBLE_INFO(disasm_info, logfile, fprintf); |
|
2260 |
disasm_info.buffer = pc_start; |
|
2261 |
disasm_info.buffer_vma = (unsigned long)pc_start; |
|
2262 |
disasm_info.buffer_length = 15; |
|
2237 |
if (loglevel) { |
|
2238 |
INIT_DISASSEMBLE_INFO(disasm_info, logfile, fprintf); |
|
2239 |
disasm_info.buffer = pc_start; |
|
2240 |
disasm_info.buffer_vma = (unsigned long)pc_start; |
|
2241 |
disasm_info.buffer_length = 15; |
|
2263 | 2242 |
#if 0 |
2264 |
disasm_info.flavour = bfd_get_flavour (abfd); |
|
2265 |
disasm_info.arch = bfd_get_arch (abfd); |
|
2266 |
disasm_info.mach = bfd_get_mach (abfd); |
|
2243 |
disasm_info.flavour = bfd_get_flavour (abfd);
|
|
2244 |
disasm_info.arch = bfd_get_arch (abfd);
|
|
2245 |
disasm_info.mach = bfd_get_mach (abfd);
|
|
2267 | 2246 |
#endif |
2268 | 2247 |
#ifdef WORDS_BIGENDIAN |
2269 |
disasm_info.endian = BFD_ENDIAN_BIG; |
|
2248 |
disasm_info.endian = BFD_ENDIAN_BIG;
|
|
2270 | 2249 |
#else |
2271 |
disasm_info.endian = BFD_ENDIAN_LITTLE; |
|
2250 |
disasm_info.endian = BFD_ENDIAN_LITTLE;
|
|
2272 | 2251 |
#endif |
2273 |
fprintf(logfile, "IN:\n"); |
|
2274 |
fprintf(logfile, "0x%08lx: ", (long)pc_start); |
|
2275 |
print_insn_i386((unsigned long)pc_start, &disasm_info); |
|
2276 |
fprintf(logfile, "\n\n"); |
|
2252 |
fprintf(logfile, "IN:\n"); |
|
2253 |
fprintf(logfile, "0x%08lx: ", (long)pc_start); |
|
2254 |
print_insn_i386((unsigned long)pc_start, &disasm_info); |
|
2255 |
fprintf(logfile, "\n\n"); |
|
2256 |
} |
|
2277 | 2257 |
#endif |
2278 | 2258 |
is_jmp = 0; |
2279 | 2259 |
ret = disas_insn(dc, pc_start, &is_jmp); |
... | ... | |
2290 | 2270 |
*gen_code_size_ptr = gen_code_ptr - gen_code_buf; |
2291 | 2271 |
|
2292 | 2272 |
#ifdef DEBUG_DISAS |
2293 |
{ |
|
2273 |
if (loglevel) {
|
|
2294 | 2274 |
uint8_t *pc; |
2295 | 2275 |
int count; |
2296 | 2276 |
|
Also available in: Unified diff