提交 0ecfa993 编写于 作者: B bellard

prints hello world


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@17 c046a42c-6fe2-441c-8c8c-71466251a162
上级 ba1c6e37
...@@ -30,16 +30,19 @@ endif ...@@ -30,16 +30,19 @@ endif
######################################################### #########################################################
DEFINES+=-D_GNU_SOURCE -DGEMU -DDOSEMU -DNO_TRACE_MSGS DEFINES+=-D_GNU_SOURCE
DEFINES+=-DCONFIG_PREFIX=\"/usr/local\" DEFINES+=-DCONFIG_PREFIX=\"/usr/local\"
LDSCRIPT=$(ARCH).ld LDSCRIPT=$(ARCH).ld
LIBS+=-ldl -lm LIBS+=-ldl -lm
OBJS= i386/fp87.o i386/interp_main.o i386/interp_modrm.o i386/interp_16_32.o \ #DEFINES+= -DGEMU -DDOSEMU -DNO_TRACE_MSGS
i386/interp_32_16.o i386/interp_32_32.o i386/emu-utils.o \ #OBJS= i386/fp87.o i386/interp_main.o i386/interp_modrm.o i386/interp_16_32.o \
i386/dis8086.o i386/emu-ldt.o # i386/interp_32_16.o i386/interp_32_32.o i386/emu-utils.o \
# i386/dis8086.o i386/emu-ldt.o
OBJS+=translate-i386.o op-i386.o OBJS+=translate-i386.o op-i386.o
OBJS+= elfload.o main.o thunk.o syscall.o OBJS+= elfload.o main.o thunk.o syscall.o
# NOTE: the disassembler code is only needed for debugging
OBJS+=i386-dis.o dis-buf.o
SRCS = $(OBJS:.o=.c) SRCS = $(OBJS:.o=.c)
all: gemu all: gemu
......
/* NOTE: this header is included in op-i386.c where global register
variable are used. Care must be used when including glibc headers.
*/
#ifndef CPU_I386_H #ifndef CPU_I386_H
#define CPU_I386_H #define CPU_I386_H
#include <setjmp.h>
#define R_EAX 0 #define R_EAX 0
#define R_ECX 1 #define R_ECX 1
#define R_EDX 2 #define R_EDX 2
...@@ -43,6 +48,27 @@ ...@@ -43,6 +48,27 @@
#define VM_FLAG 0x20000 #define VM_FLAG 0x20000
/* AC 0x40000 */ /* AC 0x40000 */
#define EXCP00_DIVZ 1
#define EXCP01_SSTP 2
#define EXCP02_NMI 3
#define EXCP03_INT3 4
#define EXCP04_INTO 5
#define EXCP05_BOUND 6
#define EXCP06_ILLOP 7
#define EXCP07_PREX 8
#define EXCP08_DBLE 9
#define EXCP09_XERR 10
#define EXCP0A_TSS 11
#define EXCP0B_NOSEG 12
#define EXCP0C_STACK 13
#define EXCP0D_GPF 14
#define EXCP0E_PAGE 15
#define EXCP10_COPR 17
#define EXCP11_ALGN 18
#define EXCP12_MCHK 19
#define EXCP_SIGNAL 256 /* async signal */
enum { enum {
CC_OP_DYNAMIC, /* must use dynamic code to get cc_op */ CC_OP_DYNAMIC, /* must use dynamic code to get cc_op */
CC_OP_EFLAGS, /* all cc are explicitely computed, CC_SRC = flags */ CC_OP_EFLAGS, /* all cc are explicitely computed, CC_SRC = flags */
...@@ -89,27 +115,34 @@ typedef struct CPUX86State { ...@@ -89,27 +115,34 @@ typedef struct CPUX86State {
/* standard registers */ /* standard registers */
uint32_t regs[8]; uint32_t regs[8];
uint32_t pc; /* cs_case + eip value */ uint32_t pc; /* cs_case + eip value */
/* eflags handling */
uint32_t eflags; uint32_t eflags;
/* emulator internal eflags handling */
uint32_t cc_src; uint32_t cc_src;
uint32_t cc_dst; uint32_t cc_dst;
uint32_t cc_op; uint32_t cc_op;
int32_t df; /* D flag : 1 if D = 0, -1 if D = 1 */ int32_t df; /* D flag : 1 if D = 0, -1 if D = 1 */
/* segments */ /* segments */
uint8_t *segs_base[6]; uint8_t *segs_base[6];
uint32_t segs[6];
/* FPU state */ /* FPU state */
CPU86_LDouble fpregs[8];
uint8_t fptags[8]; /* 0 = valid, 1 = empty */
unsigned int fpstt; /* top of stack index */ unsigned int fpstt; /* top of stack index */
unsigned int fpus; unsigned int fpus;
unsigned int fpuc; unsigned int fpuc;
uint8_t fptags[8]; /* 0 = valid, 1 = empty */
CPU86_LDouble fpregs[8];
/* segments */
uint32_t segs[6];
/* emulator internal variables */ /* emulator internal variables */
CPU86_LDouble ft0; CPU86_LDouble ft0;
/* exception handling */
jmp_buf jmp_env;
int exception_index;
} CPUX86State; } CPUX86State;
static inline int ldub(void *ptr) static inline int ldub(void *ptr)
......
...@@ -21,10 +21,11 @@ ...@@ -21,10 +21,11 @@
#include <stdio.h> #include <stdio.h>
#include <stdarg.h> #include <stdarg.h>
#include <errno.h> #include <errno.h>
#include <unistd.h>
#include "gemu.h" #include "gemu.h"
#include "i386/hsw_interp.h" #include "cpu-i386.h"
unsigned long x86_stack_size; unsigned long x86_stack_size;
unsigned long stktop; unsigned long stktop;
...@@ -38,160 +39,8 @@ void gemu_log(const char *fmt, ...) ...@@ -38,160 +39,8 @@ void gemu_log(const char *fmt, ...)
va_end(ap); va_end(ap);
} }
/* virtual x86 CPU stuff */
extern int invoke_code16(Interp_ENV *, int, int);
extern int invoke_code32(Interp_ENV *, int);
extern char *e_print_cpuemu_regs(ENVPARAMS, int is32);
extern char *e_emu_disasm(ENVPARAMS, unsigned char *org, int is32);
extern void init_npu(void);
Interp_ENV env_global;
Interp_ENV *envp_global;
QWORD EMUtime = 0;
int CEmuStat = 0;
long instr_count;
/* who will initialize this? */
unsigned long io_bitmap[IO_BITMAP_SIZE+1];
/* debug flag, 0=disable 1..9=level */
int d_emu = 0;
unsigned long CRs[5] =
{
0x00000013, /* valid bits: 0xe005003f */
0x00000000, /* invalid */
0x00000000,
0x00000000,
0x00000000
};
/*
* DR0-3 = linear address of breakpoint 0-3
* DR4=5 = reserved
* DR6 b0-b3 = BP active
* b13 = BD
* b14 = BS
* b15 = BT
* DR7 b0-b1 = G:L bp#0
* b2-b3 = G:L bp#1
* b4-b5 = G:L bp#2
* b6-b7 = G:L bp#3
* b8-b9 = GE:LE
* b13 = GD
* b16-19= LLRW bp#0 LL=00(1),01(2),11(4)
* b20-23= LLRW bp#1 RW=00(x),01(w),11(rw)
* b24-27= LLRW bp#2
* b28-31= LLRW bp#3
*/
unsigned long DRs[8] =
{
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0xffff1ff0,
0x00000400,
0xffff1ff0,
0x00000400
};
unsigned long TRs[2] =
{
0x00000000,
0x00000000
};
void FatalAppExit(UINT wAction, LPCSTR lpText)
{
fprintf(stderr, "Fatal error '%s' in CPU\n", lpText);
exit(1);
}
int e_debug_check(unsigned char *PC)
{
register unsigned long d7 = DRs[7];
if (d7&0x03) {
if (d7&0x30000) return 0; /* only execute(00) bkp */
if ((long)PC==DRs[0]) {
e_printf("DBRK: DR0 hit at %p\n",PC);
DRs[6] |= 1;
return 1;
}
}
if (d7&0x0c) {
if (d7&0x300000) return 0;
if ((long)PC==DRs[1]) {
e_printf("DBRK: DR1 hit at %p\n",PC);
DRs[6] |= 2;
return 1;
}
}
if (d7&0x30) {
if (d7&0x3000000) return 0;
if ((long)PC==DRs[2]) {
e_printf("DBRK: DR2 hit at %p\n",PC);
DRs[6] |= 4;
return 1;
}
}
if (d7&0xc0) {
if (d7&0x30000000) return 0;
if ((long)PC==DRs[3]) {
e_printf("DBRK: DR3 hit at %p\n",PC);
DRs[6] |= 8;
return 1;
}
}
return 0;
}
/* Debug stuff */
void logstr(unsigned long mask, const char *fmt,...)
{
va_list ap;
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
}
/* unconditional message into debug log and stderr */
#undef error
void error(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
exit(1);
}
int PortIO(DWORD port, DWORD value, UINT size, BOOL is_write)
{
fprintf(stderr, "IO: %s port=0x%lx value=0x%lx size=%d",
is_write ? "write" : "read", port, value, size);
return value;
}
void LogProcName(WORD wSel, WORD wOff, WORD wAction)
{
}
void INT_handler(int num, void *env)
{
fprintf(stderr, "EM86: int %d\n", num);
}
/***********************************************************/ /***********************************************************/
/* new CPU core */ /* CPUX86 core interface */
void cpu_x86_outb(int addr, int val) void cpu_x86_outb(int addr, int val)
{ {
...@@ -245,7 +94,7 @@ int main(int argc, char **argv) ...@@ -245,7 +94,7 @@ int main(int argc, char **argv)
const char *filename; const char *filename;
struct target_pt_regs regs1, *regs = &regs1; struct target_pt_regs regs1, *regs = &regs1;
struct image_info info1, *info = &info1; struct image_info info1, *info = &info1;
Interp_ENV *env; CPUX86State *env;
if (argc <= 1) if (argc <= 1)
usage(); usage();
...@@ -277,26 +126,25 @@ int main(int argc, char **argv) ...@@ -277,26 +126,25 @@ int main(int argc, char **argv)
target_set_brk((char *)info->brk); target_set_brk((char *)info->brk);
syscall_init(); syscall_init();
env = &env_global; env = cpu_x86_init();
envp_global = env;
memset(env, 0, sizeof(Interp_ENV)); env->regs[R_EAX] = regs->eax;
env->regs[R_EBX] = regs->ebx;
env->rax.e = regs->eax; env->regs[R_ECX] = regs->ecx;
env->rbx.e = regs->ebx; env->regs[R_EDX] = regs->edx;
env->rcx.e = regs->ecx; env->regs[R_ESI] = regs->esi;
env->rdx.e = regs->edx; env->regs[R_EDI] = regs->edi;
env->rsi.esi = regs->esi; env->regs[R_EBP] = regs->ebp;
env->rdi.edi = regs->edi; env->regs[R_ESP] = regs->esp;
env->rbp.ebp = regs->ebp; env->segs[R_CS] = __USER_CS;
env->rsp.esp = regs->esp; env->segs[R_DS] = __USER_DS;
env->cs.cs = __USER_CS; env->segs[R_ES] = __USER_DS;
env->ds.ds = __USER_DS; env->segs[R_SS] = __USER_DS;
env->es.es = __USER_DS; env->segs[R_FS] = __USER_DS;
env->ss.ss = __USER_DS; env->segs[R_GS] = __USER_DS;
env->fs.fs = __USER_DS; env->pc = regs->eip;
env->gs.gs = __USER_DS;
env->trans_addr = regs->eip;
#if 0
LDT[__USER_CS >> 3].w86Flags = DF_PRESENT | DF_PAGES | DF_32; LDT[__USER_CS >> 3].w86Flags = DF_PRESENT | DF_PAGES | DF_32;
LDT[__USER_CS >> 3].dwSelLimit = 0xfffff; LDT[__USER_CS >> 3].dwSelLimit = 0xfffff;
LDT[__USER_CS >> 3].lpSelBase = NULL; LDT[__USER_CS >> 3].lpSelBase = NULL;
...@@ -304,41 +152,34 @@ int main(int argc, char **argv) ...@@ -304,41 +152,34 @@ int main(int argc, char **argv)
LDT[__USER_DS >> 3].w86Flags = DF_PRESENT | DF_PAGES | DF_32; LDT[__USER_DS >> 3].w86Flags = DF_PRESENT | DF_PAGES | DF_32;
LDT[__USER_DS >> 3].dwSelLimit = 0xfffff; LDT[__USER_DS >> 3].dwSelLimit = 0xfffff;
LDT[__USER_DS >> 3].lpSelBase = NULL; LDT[__USER_DS >> 3].lpSelBase = NULL;
init_npu(); #endif
build_decode_tables();
for(;;) { for(;;) {
int err; int err;
uint8_t *pc; uint8_t *pc;
err = invoke_code32(env, -1); err = cpu_x86_exec(env);
env->trans_addr = env->return_addr;
pc = env->seg_regs[0] + env->trans_addr;
switch(err) { switch(err) {
case EXCP0D_GPF: case EXCP0D_GPF:
pc = (uint8_t *)env->pc;
if (pc[0] == 0xcd && pc[1] == 0x80) { if (pc[0] == 0xcd && pc[1] == 0x80) {
/* syscall */ /* syscall */
env->trans_addr += 2; env->pc += 2;
env->rax.e = do_syscall(env->rax.e, env->regs[R_EAX] = do_syscall(env->regs[R_EAX],
env->rbx.e, env->regs[R_EBX],
env->rcx.e, env->regs[R_ECX],
env->rdx.e, env->regs[R_EDX],
env->rsi.esi, env->regs[R_ESI],
env->rdi.edi, env->regs[R_EDI],
env->rbp.ebp); env->regs[R_EBP]);
} else { } else {
goto trap_error; goto trap_error;
} }
break; break;
default: default:
trap_error: trap_error:
fprintf(stderr, "GEMU: Unknown error %d, aborting\n", err); fprintf(stderr, "0x%08lx: Unknown exception %d, aborting\n",
#ifndef NO_TRACE_MSGS (long)env->pc, err);
d_emu = 9;
fprintf(stderr, "%s\n%s\n",
e_print_cpuemu_regs(env, 1),
e_emu_disasm(env,pc,1));
#endif
abort(); abort();
} }
} }
......
...@@ -10,11 +10,6 @@ typedef signed long long int64_t; ...@@ -10,11 +10,6 @@ typedef signed long long int64_t;
#define NULL 0 #define NULL 0
typedef struct FILE FILE;
extern FILE *stderr;
extern int fprintf(FILE *, const char *, ...);
#ifdef __i386__ #ifdef __i386__
register int T0 asm("esi"); register int T0 asm("esi");
register int T1 asm("ebx"); register int T1 asm("ebx");
...@@ -91,6 +86,7 @@ typedef struct CCTable { ...@@ -91,6 +86,7 @@ typedef struct CCTable {
int (*compute_c)(void); /* return the C flag */ int (*compute_c)(void); /* return the C flag */
} CCTable; } CCTable;
/* NOTE: data are not static to force relocation generation by GCC */
extern CCTable cc_table[]; extern CCTable cc_table[];
uint8_t parity_table[256] = { uint8_t parity_table[256] = {
...@@ -191,6 +187,14 @@ static inline int lshift(int x, int n) ...@@ -191,6 +187,14 @@ static inline int lshift(int x, int n)
return x >> (-n); return x >> (-n);
} }
/* exception support */
/* NOTE: not static to force relocation generation by GCC */
void raise_exception(int exception_index)
{
env->exception_index = exception_index;
longjmp(env->jmp_env, 1);
}
/* we define the various pieces of code used by the JIT */ /* we define the various pieces of code used by the JIT */
#define REG EAX #define REG EAX
...@@ -321,7 +325,6 @@ void OPPROTO op_decl_T0_cc(void) ...@@ -321,7 +325,6 @@ void OPPROTO op_decl_T0_cc(void)
void OPPROTO op_testl_T0_T1_cc(void) void OPPROTO op_testl_T0_T1_cc(void)
{ {
CC_SRC = T0;
CC_DST = T0 & T1; CC_DST = T0 & T1;
} }
...@@ -555,6 +558,7 @@ void OPPROTO op_stl_T0_A0(void) ...@@ -555,6 +558,7 @@ void OPPROTO op_stl_T0_A0(void)
/* jumps */ /* jumps */
/* indirect jump */ /* indirect jump */
void OPPROTO op_jmp_T0(void) void OPPROTO op_jmp_T0(void)
{ {
PC = T0; PC = T0;
...@@ -565,6 +569,30 @@ void OPPROTO op_jmp_im(void) ...@@ -565,6 +569,30 @@ void OPPROTO op_jmp_im(void)
PC = PARAM1; PC = PARAM1;
} }
void OPPROTO op_int_im(void)
{
PC = PARAM1;
raise_exception(EXCP0D_GPF);
}
void OPPROTO op_int3(void)
{
PC = PARAM1;
raise_exception(EXCP03_INT3);
}
void OPPROTO op_into(void)
{
int eflags;
eflags = cc_table[CC_OP].compute_all();
if (eflags & CC_O) {
PC = PARAM1;
raise_exception(EXCP04_INTO);
} else {
PC = PARAM2;
}
}
/* string ops */ /* string ops */
#define ldul ldl #define ldul ldl
...@@ -663,17 +691,19 @@ void OPPROTO op_jo_cc(void) ...@@ -663,17 +691,19 @@ void OPPROTO op_jo_cc(void)
int eflags; int eflags;
eflags = cc_table[CC_OP].compute_all(); eflags = cc_table[CC_OP].compute_all();
if (eflags & CC_O) if (eflags & CC_O)
PC += PARAM1; PC = PARAM1;
else else
PC += PARAM2; PC = PARAM2;
FORCE_RET();
} }
void OPPROTO op_jb_cc(void) void OPPROTO op_jb_cc(void)
{ {
if (cc_table[CC_OP].compute_c()) if (cc_table[CC_OP].compute_c())
PC += PARAM1; PC = PARAM1;
else else
PC += PARAM2; PC = PARAM2;
FORCE_RET();
} }
void OPPROTO op_jz_cc(void) void OPPROTO op_jz_cc(void)
...@@ -681,9 +711,10 @@ void OPPROTO op_jz_cc(void) ...@@ -681,9 +711,10 @@ void OPPROTO op_jz_cc(void)
int eflags; int eflags;
eflags = cc_table[CC_OP].compute_all(); eflags = cc_table[CC_OP].compute_all();
if (eflags & CC_Z) if (eflags & CC_Z)
PC += PARAM1; PC = PARAM1;
else else
PC += PARAM2; PC = PARAM2;
FORCE_RET();
} }
void OPPROTO op_jbe_cc(void) void OPPROTO op_jbe_cc(void)
...@@ -691,9 +722,10 @@ void OPPROTO op_jbe_cc(void) ...@@ -691,9 +722,10 @@ void OPPROTO op_jbe_cc(void)
int eflags; int eflags;
eflags = cc_table[CC_OP].compute_all(); eflags = cc_table[CC_OP].compute_all();
if (eflags & (CC_Z | CC_C)) if (eflags & (CC_Z | CC_C))
PC += PARAM1; PC = PARAM1;
else else
PC += PARAM2; PC = PARAM2;
FORCE_RET();
} }
void OPPROTO op_js_cc(void) void OPPROTO op_js_cc(void)
...@@ -701,9 +733,10 @@ void OPPROTO op_js_cc(void) ...@@ -701,9 +733,10 @@ void OPPROTO op_js_cc(void)
int eflags; int eflags;
eflags = cc_table[CC_OP].compute_all(); eflags = cc_table[CC_OP].compute_all();
if (eflags & CC_S) if (eflags & CC_S)
PC += PARAM1; PC = PARAM1;
else else
PC += PARAM2; PC = PARAM2;
FORCE_RET();
} }
void OPPROTO op_jp_cc(void) void OPPROTO op_jp_cc(void)
...@@ -711,9 +744,10 @@ void OPPROTO op_jp_cc(void) ...@@ -711,9 +744,10 @@ void OPPROTO op_jp_cc(void)
int eflags; int eflags;
eflags = cc_table[CC_OP].compute_all(); eflags = cc_table[CC_OP].compute_all();
if (eflags & CC_P) if (eflags & CC_P)
PC += PARAM1; PC = PARAM1;
else else
PC += PARAM2; PC = PARAM2;
FORCE_RET();
} }
void OPPROTO op_jl_cc(void) void OPPROTO op_jl_cc(void)
...@@ -721,9 +755,10 @@ void OPPROTO op_jl_cc(void) ...@@ -721,9 +755,10 @@ void OPPROTO op_jl_cc(void)
int eflags; int eflags;
eflags = cc_table[CC_OP].compute_all(); eflags = cc_table[CC_OP].compute_all();
if ((eflags ^ (eflags >> 4)) & 0x80) if ((eflags ^ (eflags >> 4)) & 0x80)
PC += PARAM1; PC = PARAM1;
else else
PC += PARAM2; PC = PARAM2;
FORCE_RET();
} }
void OPPROTO op_jle_cc(void) void OPPROTO op_jle_cc(void)
...@@ -731,9 +766,10 @@ void OPPROTO op_jle_cc(void) ...@@ -731,9 +766,10 @@ void OPPROTO op_jle_cc(void)
int eflags; int eflags;
eflags = cc_table[CC_OP].compute_all(); eflags = cc_table[CC_OP].compute_all();
if (((eflags ^ (eflags >> 4)) & 0x80) || (eflags & CC_Z)) if (((eflags ^ (eflags >> 4)) & 0x80) || (eflags & CC_Z))
PC += PARAM1; PC = PARAM1;
else else
PC += PARAM2; PC = PARAM2;
FORCE_RET();
} }
/* slow set cases (compute x86 flags) */ /* slow set cases (compute x86 flags) */
...@@ -1600,14 +1636,13 @@ void OPPROTO op_fcos(void) ...@@ -1600,14 +1636,13 @@ void OPPROTO op_fcos(void)
/* main execution loop */ /* main execution loop */
uint8_t code_gen_buffer[65536]; uint8_t code_gen_buffer[65536];
int cpu_x86_exec(CPUX86State *env1) int cpu_x86_exec(CPUX86State *env1)
{ {
int saved_T0, saved_T1, saved_A0; int saved_T0, saved_T1, saved_A0;
CPUX86State *saved_env; CPUX86State *saved_env;
int code_gen_size; int code_gen_size, ret;
void (*gen_func)(void); void (*gen_func)(void);
/* first we save global registers */ /* first we save global registers */
saved_T0 = T0; saved_T0 = T0;
saved_T1 = T1; saved_T1 = T1;
...@@ -1615,17 +1650,21 @@ int cpu_x86_exec(CPUX86State *env1) ...@@ -1615,17 +1650,21 @@ int cpu_x86_exec(CPUX86State *env1)
saved_env = env; saved_env = env;
env = env1; env = env1;
for(;;) { /* prepare setjmp context for exception handling */
cpu_x86_gen_code(code_gen_buffer, &code_gen_size, (uint8_t *)env->pc); if (setjmp(env->jmp_env) == 0) {
/* execute the generated code */ for(;;) {
gen_func = (void *)code_gen_buffer; cpu_x86_gen_code(code_gen_buffer, &code_gen_size, (uint8_t *)env->pc);
gen_func(); /* execute the generated code */
gen_func = (void *)code_gen_buffer;
gen_func();
}
} }
ret = env->exception_index;
/* restore global registers */ /* restore global registers */
T0 = saved_T0; T0 = saved_T0;
T1 = saved_T1; T1 = saved_T1;
A0 = saved_A0; A0 = saved_A0;
env = saved_env; env = saved_env;
return 0; return ret;
} }
...@@ -149,18 +149,18 @@ void OPPROTO glue(op_jb_sub, SUFFIX)(void) ...@@ -149,18 +149,18 @@ void OPPROTO glue(op_jb_sub, SUFFIX)(void)
src2 = CC_SRC - CC_DST; src2 = CC_SRC - CC_DST;
if ((DATA_TYPE)src1 < (DATA_TYPE)src2) if ((DATA_TYPE)src1 < (DATA_TYPE)src2)
PC += PARAM1; PC = PARAM1;
else else
PC += PARAM2; PC = PARAM2;
FORCE_RET(); FORCE_RET();
} }
void OPPROTO glue(op_jz_sub, SUFFIX)(void) void OPPROTO glue(op_jz_sub, SUFFIX)(void)
{ {
if ((DATA_TYPE)CC_DST != 0) if ((DATA_TYPE)CC_DST != 0)
PC += PARAM1; PC = PARAM1;
else else
PC += PARAM2; PC = PARAM2;
FORCE_RET(); FORCE_RET();
} }
...@@ -171,18 +171,18 @@ void OPPROTO glue(op_jbe_sub, SUFFIX)(void) ...@@ -171,18 +171,18 @@ void OPPROTO glue(op_jbe_sub, SUFFIX)(void)
src2 = CC_SRC - CC_DST; src2 = CC_SRC - CC_DST;
if ((DATA_TYPE)src1 <= (DATA_TYPE)src2) if ((DATA_TYPE)src1 <= (DATA_TYPE)src2)
PC += PARAM1; PC = PARAM1;
else else
PC += PARAM2; PC = PARAM2;
FORCE_RET(); FORCE_RET();
} }
void OPPROTO glue(op_js_sub, SUFFIX)(void) void OPPROTO glue(op_js_sub, SUFFIX)(void)
{ {
if (CC_DST & SIGN_MASK) if (CC_DST & SIGN_MASK)
PC += PARAM1; PC = PARAM1;
else else
PC += PARAM2; PC = PARAM2;
FORCE_RET(); FORCE_RET();
} }
...@@ -193,9 +193,9 @@ void OPPROTO glue(op_jl_sub, SUFFIX)(void) ...@@ -193,9 +193,9 @@ void OPPROTO glue(op_jl_sub, SUFFIX)(void)
src2 = CC_SRC - CC_DST; src2 = CC_SRC - CC_DST;
if ((DATA_STYPE)src1 < (DATA_STYPE)src2) if ((DATA_STYPE)src1 < (DATA_STYPE)src2)
PC += PARAM1; PC = PARAM1;
else else
PC += PARAM2; PC = PARAM2;
FORCE_RET(); FORCE_RET();
} }
...@@ -206,9 +206,9 @@ void OPPROTO glue(op_jle_sub, SUFFIX)(void) ...@@ -206,9 +206,9 @@ void OPPROTO glue(op_jle_sub, SUFFIX)(void)
src2 = CC_SRC - CC_DST; src2 = CC_SRC - CC_DST;
if ((DATA_STYPE)src1 <= (DATA_STYPE)src2) if ((DATA_STYPE)src1 <= (DATA_STYPE)src2)
PC += PARAM1; PC = PARAM1;
else else
PC += PARAM2; PC = PARAM2;
FORCE_RET(); FORCE_RET();
} }
......
...@@ -5,12 +5,24 @@ ...@@ -5,12 +5,24 @@
#include <inttypes.h> #include <inttypes.h>
#include <assert.h> #include <assert.h>
/* dump all code */
#define DEBUG_DISAS
#define DEBUG_LOGFILE "/tmp/gemu.log"
#ifdef DEBUG_DISAS
#include "dis-asm.h"
#endif
#define IN_OP_I386 #define IN_OP_I386
#include "cpu-i386.h" #include "cpu-i386.h"
static uint8_t *gen_code_ptr; static uint8_t *gen_code_ptr;
int __op_param1, __op_param2, __op_param3; int __op_param1, __op_param2, __op_param3;
#ifdef DEBUG_DISAS
static FILE *logfile = NULL;
#endif
/* supress that */ /* supress that */
static void error(const char *fmt, ...) static void error(const char *fmt, ...)
{ {
...@@ -704,6 +716,9 @@ static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_ ...@@ -704,6 +716,9 @@ static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_
int reg1, reg2, opreg; int reg1, reg2, opreg;
int mod, rm, code; int mod, rm, code;
#ifdef DEBUG_DISAS
fprintf(logfile, "modrm=0x%x\n", modrm);
#endif
mod = (modrm >> 6) & 3; mod = (modrm >> 6) & 3;
rm = modrm & 7; rm = modrm & 7;
...@@ -716,6 +731,9 @@ static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_ ...@@ -716,6 +731,9 @@ static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_
if (base == 4) { if (base == 4) {
havesib = 1; havesib = 1;
code = ldub(s->pc++); code = ldub(s->pc++);
#ifdef DEBUG_DISAS
fprintf(logfile, "sib=0x%x\n", code);
#endif
scale = (code >> 6) & 3; scale = (code >> 6) & 3;
index = (code >> 3) & 7; index = (code >> 3) & 7;
base = code & 7; base = code & 7;
...@@ -762,6 +780,7 @@ static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_ ...@@ -762,6 +780,7 @@ static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_
} else if (scale == 0 && disp == 0) { } else if (scale == 0 && disp == 0) {
gen_op_movl_A0_reg[reg1](); gen_op_movl_A0_reg[reg1]();
} else { } else {
gen_op_movl_A0_im(disp);
gen_op_addl_A0_reg_sN[scale][reg1](); gen_op_addl_A0_reg_sN[scale][reg1]();
} }
} else { } else {
...@@ -953,8 +972,10 @@ static void gen_setcc(DisasContext *s, int b) ...@@ -953,8 +972,10 @@ static void gen_setcc(DisasContext *s, int b)
} }
} }
/* return the size of the intruction. Return -1 if no insn found */ /* return the next pc address. Return -1 if no insn found. *is_jmp_ptr
int disas_insn(DisasContext *s, uint8_t *pc_start) is set to true if the instruction sets the PC (last instruction of
a basic block) */
long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr)
{ {
int b, prefixes, aflag, dflag; int b, prefixes, aflag, dflag;
int shift, ot; int shift, ot;
...@@ -967,6 +988,9 @@ int disas_insn(DisasContext *s, uint8_t *pc_start) ...@@ -967,6 +988,9 @@ int disas_insn(DisasContext *s, uint8_t *pc_start)
// cur_pc = s->pc; /* for insn generation */ // cur_pc = s->pc; /* for insn generation */
next_byte: next_byte:
b = ldub(s->pc); b = ldub(s->pc);
#ifdef DEBUG_DISAS
fprintf(logfile, "ib=0x%02x\n", b);
#endif
if (b < 0) if (b < 0)
return -1; return -1;
s->pc++; s->pc++;
...@@ -1195,6 +1219,7 @@ int disas_insn(DisasContext *s, uint8_t *pc_start) ...@@ -1195,6 +1219,7 @@ int disas_insn(DisasContext *s, uint8_t *pc_start)
gen_op_mull_EAX_T0(); gen_op_mull_EAX_T0();
break; break;
} }
s->cc_op = CC_OP_MUL;
break; break;
case 5: /* imul */ case 5: /* imul */
switch(ot) { switch(ot) {
...@@ -1209,6 +1234,7 @@ int disas_insn(DisasContext *s, uint8_t *pc_start) ...@@ -1209,6 +1234,7 @@ int disas_insn(DisasContext *s, uint8_t *pc_start)
gen_op_imull_EAX_T0(); gen_op_imull_EAX_T0();
break; break;
} }
s->cc_op = CC_OP_MUL;
break; break;
case 6: /* div */ case 6: /* div */
switch(ot) { switch(ot) {
...@@ -1281,9 +1307,11 @@ int disas_insn(DisasContext *s, uint8_t *pc_start) ...@@ -1281,9 +1307,11 @@ int disas_insn(DisasContext *s, uint8_t *pc_start)
gen_op_movl_T1_im((long)s->pc); gen_op_movl_T1_im((long)s->pc);
gen_op_pushl_T1(); gen_op_pushl_T1();
gen_op_jmp_T0(); gen_op_jmp_T0();
*is_jmp_ptr = 1;
break; break;
case 4: /* jmp Ev */ case 4: /* jmp Ev */
gen_op_jmp_T0(); gen_op_jmp_T0();
*is_jmp_ptr = 1;
break; break;
case 6: /* push Ev */ case 6: /* push Ev */
gen_op_pushl_T0(); gen_op_pushl_T0();
...@@ -1362,6 +1390,7 @@ int disas_insn(DisasContext *s, uint8_t *pc_start) ...@@ -1362,6 +1390,7 @@ int disas_insn(DisasContext *s, uint8_t *pc_start)
op_imulw_T0_T1(); op_imulw_T0_T1();
} }
gen_op_mov_reg_T0[ot][reg](); gen_op_mov_reg_T0[ot][reg]();
s->cc_op = CC_OP_MUL;
break; break;
/**************************/ /**************************/
...@@ -1418,10 +1447,14 @@ int disas_insn(DisasContext *s, uint8_t *pc_start) ...@@ -1418,10 +1447,14 @@ int disas_insn(DisasContext *s, uint8_t *pc_start)
ot = dflag ? OT_LONG : OT_WORD; ot = dflag ? OT_LONG : OT_WORD;
modrm = ldub(s->pc++); modrm = ldub(s->pc++);
mod = (modrm >> 6) & 3; mod = (modrm >> 6) & 3;
if (mod != 3)
gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
val = insn_get(s, ot); val = insn_get(s, ot);
gen_op_movl_T0_im(val); gen_op_movl_T0_im(val);
gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1); if (mod != 3)
gen_op_st_T0_A0[ot]();
else
gen_op_mov_reg_T0[ot][modrm & 7]();
break; break;
case 0x8a: case 0x8a:
case 0x8b: /* mov Ev, Gv */ case 0x8b: /* mov Ev, Gv */
...@@ -2068,10 +2101,12 @@ int disas_insn(DisasContext *s, uint8_t *pc_start) ...@@ -2068,10 +2101,12 @@ int disas_insn(DisasContext *s, uint8_t *pc_start)
gen_op_popl_T0(); gen_op_popl_T0();
gen_op_addl_ESP_im(val); gen_op_addl_ESP_im(val);
gen_op_jmp_T0(); gen_op_jmp_T0();
*is_jmp_ptr = 1;
break; break;
case 0xc3: /* ret */ case 0xc3: /* ret */
gen_op_popl_T0(); gen_op_popl_T0();
gen_op_jmp_T0(); gen_op_jmp_T0();
*is_jmp_ptr = 1;
break; break;
case 0xe8: /* call */ case 0xe8: /* call */
val = insn_get(s, OT_LONG); val = insn_get(s, OT_LONG);
...@@ -2079,16 +2114,19 @@ int disas_insn(DisasContext *s, uint8_t *pc_start) ...@@ -2079,16 +2114,19 @@ int disas_insn(DisasContext *s, uint8_t *pc_start)
gen_op_movl_T1_im((long)s->pc); gen_op_movl_T1_im((long)s->pc);
gen_op_pushl_T1(); gen_op_pushl_T1();
gen_op_jmp_im(val); gen_op_jmp_im(val);
*is_jmp_ptr = 1;
break; break;
case 0xe9: /* jmp */ case 0xe9: /* jmp */
val = insn_get(s, OT_LONG); val = insn_get(s, OT_LONG);
val += (long)s->pc; val += (long)s->pc;
gen_op_jmp_im(val); gen_op_jmp_im(val);
*is_jmp_ptr = 1;
break; break;
case 0xeb: /* jmp Jb */ case 0xeb: /* jmp Jb */
val = (int8_t)insn_get(s, OT_BYTE); val = (int8_t)insn_get(s, OT_BYTE);
val += (long)s->pc; val += (long)s->pc;
gen_op_jmp_im(val); gen_op_jmp_im(val);
*is_jmp_ptr = 1;
break; break;
case 0x70 ... 0x7f: /* jcc Jb */ case 0x70 ... 0x7f: /* jcc Jb */
val = (int8_t)insn_get(s, OT_BYTE); val = (int8_t)insn_get(s, OT_BYTE);
...@@ -2103,6 +2141,7 @@ int disas_insn(DisasContext *s, uint8_t *pc_start) ...@@ -2103,6 +2141,7 @@ int disas_insn(DisasContext *s, uint8_t *pc_start)
val += (long)s->pc; /* XXX: fix 16 bit wrap */ val += (long)s->pc; /* XXX: fix 16 bit wrap */
do_jcc: do_jcc:
gen_jcc(s, b, val); gen_jcc(s, b, val);
*is_jmp_ptr = 1;
break; break;
case 0x190 ... 0x19f: case 0x190 ... 0x19f:
...@@ -2164,8 +2203,23 @@ int disas_insn(DisasContext *s, uint8_t *pc_start) ...@@ -2164,8 +2203,23 @@ int disas_insn(DisasContext *s, uint8_t *pc_start)
/* misc */ /* misc */
case 0x90: /* nop */ case 0x90: /* nop */
break; break;
case 0xcc: /* int3 */
#if 0 gen_op_int3((long)pc_start);
*is_jmp_ptr = 1;
break;
case 0xcd: /* int N */
val = ldub(s->pc++);
/* XXX: currently we ignore the interrupt number */
gen_op_int_im((long)pc_start);
*is_jmp_ptr = 1;
break;
case 0xce: /* into */
if (s->cc_op != CC_OP_DYNAMIC)
gen_op_set_cc_op(s->cc_op);
gen_op_into((long)pc_start, (long)s->pc);
*is_jmp_ptr = 1;
break;
#if 0
case 0x1a2: /* cpuid */ case 0x1a2: /* cpuid */
gen_insn0(OP_ASM); gen_insn0(OP_ASM);
break; break;
...@@ -2182,16 +2236,78 @@ int cpu_x86_gen_code(uint8_t *gen_code_buf, int *gen_code_size_ptr, ...@@ -2182,16 +2236,78 @@ int cpu_x86_gen_code(uint8_t *gen_code_buf, int *gen_code_size_ptr,
uint8_t *pc_start) uint8_t *pc_start)
{ {
DisasContext dc1, *dc = &dc1; DisasContext dc1, *dc = &dc1;
int is_jmp;
long ret; long ret;
#ifdef DEBUG_DISAS
struct disassemble_info disasm_info;
#endif
dc->cc_op = CC_OP_DYNAMIC; dc->cc_op = CC_OP_DYNAMIC;
gen_code_ptr = gen_code_buf; gen_code_ptr = gen_code_buf;
gen_start(); gen_start();
ret = disas_insn(dc, pc_start);
#ifdef DEBUG_DISAS
if (!logfile) {
logfile = fopen(DEBUG_LOGFILE, "w");
if (!logfile) {
perror(DEBUG_LOGFILE);
exit(1);
}
setvbuf(logfile, NULL, _IOLBF, 0);
}
INIT_DISASSEMBLE_INFO(disasm_info, logfile, fprintf);
disasm_info.buffer = pc_start;
disasm_info.buffer_vma = (unsigned long)pc_start;
disasm_info.buffer_length = 15;
#if 0
disasm_info.flavour = bfd_get_flavour (abfd);
disasm_info.arch = bfd_get_arch (abfd);
disasm_info.mach = bfd_get_mach (abfd);
#endif
#ifdef WORDS_BIGENDIAN
disasm_info.endian = BFD_ENDIAN_BIG;
#else
disasm_info.endian = BFD_ENDIAN_LITTLE;
#endif
fprintf(logfile, "IN:\n");
fprintf(logfile, "0x%08lx: ", (long)pc_start);
print_insn_i386((unsigned long)pc_start, &disasm_info);
fprintf(logfile, "\n\n");
#endif
is_jmp = 0;
ret = disas_insn(dc, pc_start, &is_jmp);
if (ret == -1) if (ret == -1)
error("unknown instruction at PC=0x%x", pc_start); error("unknown instruction at PC=0x%x", pc_start);
/* we must store the eflags state if it is not already done */
if (dc->cc_op != CC_OP_DYNAMIC)
gen_op_set_cc_op(dc->cc_op);
if (!is_jmp) {
/* we add an additionnal jmp to update the simulated PC */
gen_op_jmp_im(ret);
}
gen_end(); gen_end();
*gen_code_size_ptr = gen_code_ptr - gen_code_buf; *gen_code_size_ptr = gen_code_ptr - gen_code_buf;
printf("0x%08lx: code_size = %d\n", (long)pc_start, *gen_code_size_ptr);
#ifdef DEBUG_DISAS
{
uint8_t *pc;
int count;
pc = gen_code_buf;
disasm_info.buffer = pc;
disasm_info.buffer_vma = (unsigned long)pc;
disasm_info.buffer_length = *gen_code_size_ptr;
fprintf(logfile, "OUT: [size=%d]\n", *gen_code_size_ptr);
while (pc < gen_code_ptr) {
fprintf(logfile, "0x%08lx: ", (long)pc);
count = print_insn_i386((unsigned long)pc, &disasm_info);
fprintf(logfile, "\n");
pc += count;
}
fprintf(logfile, "\n");
}
#endif
return 0; return 0;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册