aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>2003-03-03 14:32:43 +0000
committerbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>2003-03-03 14:32:43 +0000
commit0ecfa9930c7615503ba629a61f7b94a0c3305af5 (patch)
treee9b87ad13ee9b77cb7c5b5082ad61d877232db7e
parentba1c6e37fc5efc0f3d1e50d0760f9f4a1061187b (diff)
prints hello world
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@17 c046a42c-6fe2-441c-8c8c-71466251a162
-rw-r--r--Makefile11
-rw-r--r--cpu-i386.h45
-rw-r--r--linux-user/main.c231
-rw-r--r--op-i386.c103
-rw-r--r--ops_template.h24
-rw-r--r--translate-i386.c132
6 files changed, 289 insertions, 257 deletions
diff --git a/Makefile b/Makefile
index a61ab4a76a..b007f40dde 100644
--- a/Makefile
+++ b/Makefile
@@ -30,16 +30,19 @@ endif
#########################################################
-DEFINES+=-D_GNU_SOURCE -DGEMU -DDOSEMU -DNO_TRACE_MSGS
+DEFINES+=-D_GNU_SOURCE
DEFINES+=-DCONFIG_PREFIX=\"/usr/local\"
LDSCRIPT=$(ARCH).ld
LIBS+=-ldl -lm
-OBJS= i386/fp87.o i386/interp_main.o i386/interp_modrm.o i386/interp_16_32.o \
- i386/interp_32_16.o i386/interp_32_32.o i386/emu-utils.o \
- i386/dis8086.o i386/emu-ldt.o
+#DEFINES+= -DGEMU -DDOSEMU -DNO_TRACE_MSGS
+#OBJS= i386/fp87.o i386/interp_main.o i386/interp_modrm.o i386/interp_16_32.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+= 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)
all: gemu
diff --git a/cpu-i386.h b/cpu-i386.h
index 4eac51fb50..9add4175d3 100644
--- a/cpu-i386.h
+++ b/cpu-i386.h
@@ -1,6 +1,11 @@
+/* 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
#define CPU_I386_H
+#include <setjmp.h>
+
#define R_EAX 0
#define R_ECX 1
#define R_EDX 2
@@ -43,6 +48,27 @@
#define VM_FLAG 0x20000
/* 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 {
CC_OP_DYNAMIC, /* must use dynamic code to get cc_op */
CC_OP_EFLAGS, /* all cc are explicitely computed, CC_SRC = flags */
@@ -89,27 +115,34 @@ typedef struct CPUX86State {
/* standard registers */
uint32_t regs[8];
uint32_t pc; /* cs_case + eip value */
-
- /* eflags handling */
uint32_t eflags;
+
+ /* emulator internal eflags handling */
uint32_t cc_src;
uint32_t cc_dst;
uint32_t cc_op;
int32_t df; /* D flag : 1 if D = 0, -1 if D = 1 */
-
+
/* segments */
uint8_t *segs_base[6];
- uint32_t segs[6];
/* FPU state */
- CPU86_LDouble fpregs[8];
- uint8_t fptags[8]; /* 0 = valid, 1 = empty */
unsigned int fpstt; /* top of stack index */
unsigned int fpus;
unsigned int fpuc;
+ uint8_t fptags[8]; /* 0 = valid, 1 = empty */
+ CPU86_LDouble fpregs[8];
+
+ /* segments */
+ uint32_t segs[6];
/* emulator internal variables */
+
CPU86_LDouble ft0;
+
+ /* exception handling */
+ jmp_buf jmp_env;
+ int exception_index;
} CPUX86State;
static inline int ldub(void *ptr)
diff --git a/linux-user/main.c b/linux-user/main.c
index 552ce006c7..68858daf4c 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -21,10 +21,11 @@
#include <stdio.h>
#include <stdarg.h>
#include <errno.h>
+#include <unistd.h>
#include "gemu.h"
-#include "i386/hsw_interp.h"
+#include "cpu-i386.h"
unsigned long x86_stack_size;
unsigned long stktop;
@@ -38,160 +39,8 @@ void gemu_log(const char *fmt, ...)
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)
{
@@ -245,7 +94,7 @@ int main(int argc, char **argv)
const char *filename;
struct target_pt_regs regs1, *regs = &regs1;
struct image_info info1, *info = &info1;
- Interp_ENV *env;
+ CPUX86State *env;
if (argc <= 1)
usage();
@@ -277,26 +126,25 @@ int main(int argc, char **argv)
target_set_brk((char *)info->brk);
syscall_init();
- env = &env_global;
- envp_global = env;
- memset(env, 0, sizeof(Interp_ENV));
-
- env->rax.e = regs->eax;
- env->rbx.e = regs->ebx;
- env->rcx.e = regs->ecx;
- env->rdx.e = regs->edx;
- env->rsi.esi = regs->esi;
- env->rdi.edi = regs->edi;
- env->rbp.ebp = regs->ebp;
- env->rsp.esp = regs->esp;
- env->cs.cs = __USER_CS;
- env->ds.ds = __USER_DS;
- env->es.es = __USER_DS;
- env->ss.ss = __USER_DS;
- env->fs.fs = __USER_DS;
- env->gs.gs = __USER_DS;
- env->trans_addr = regs->eip;
+ env = cpu_x86_init();
+
+ env->regs[R_EAX] = regs->eax;
+ env->regs[R_EBX] = regs->ebx;
+ env->regs[R_ECX] = regs->ecx;
+ env->regs[R_EDX] = regs->edx;
+ env->regs[R_ESI] = regs->esi;
+ env->regs[R_EDI] = regs->edi;
+ env->regs[R_EBP] = regs->ebp;
+ env->regs[R_ESP] = regs->esp;
+ env->segs[R_CS] = __USER_CS;
+ env->segs[R_DS] = __USER_DS;
+ env->segs[R_ES] = __USER_DS;
+ env->segs[R_SS] = __USER_DS;
+ env->segs[R_FS] = __USER_DS;
+ env->segs[R_GS] = __USER_DS;
+ env->pc = regs->eip;
+#if 0
LDT[__USER_CS >> 3].w86Flags = DF_PRESENT | DF_PAGES | DF_32;
LDT[__USER_CS >> 3].dwSelLimit = 0xfffff;
LDT[__USER_CS >> 3].lpSelBase = NULL;
@@ -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].dwSelLimit = 0xfffff;
LDT[__USER_DS >> 3].lpSelBase = NULL;
- init_npu();
- build_decode_tables();
+#endif
for(;;) {
int err;
uint8_t *pc;
-
- err = invoke_code32(env, -1);
- env->trans_addr = env->return_addr;
- pc = env->seg_regs[0] + env->trans_addr;
+
+ err = cpu_x86_exec(env);
switch(err) {
case EXCP0D_GPF:
+ pc = (uint8_t *)env->pc;
if (pc[0] == 0xcd && pc[1] == 0x80) {
/* syscall */
- env->trans_addr += 2;
- env->rax.e = do_syscall(env->rax.e,
- env->rbx.e,
- env->rcx.e,
- env->rdx.e,
- env->rsi.esi,
- env->rdi.edi,
- env->rbp.ebp);
+ env->pc += 2;
+ env->regs[R_EAX] = do_syscall(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]);
} else {
goto trap_error;
}
break;
default:
trap_error:
- fprintf(stderr, "GEMU: Unknown error %d, aborting\n", err);
-#ifndef NO_TRACE_MSGS
- d_emu = 9;
- fprintf(stderr, "%s\n%s\n",
- e_print_cpuemu_regs(env, 1),
- e_emu_disasm(env,pc,1));
-#endif
+ fprintf(stderr, "0x%08lx: Unknown exception %d, aborting\n",
+ (long)env->pc, err);
abort();
}
}
diff --git a/op-i386.c b/op-i386.c
index 9443e172c7..451318af72 100644
--- a/op-i386.c
+++ b/op-i386.c
@@ -10,11 +10,6 @@ typedef signed long long int64_t;
#define NULL 0
-typedef struct FILE FILE;
-
-extern FILE *stderr;
-extern int fprintf(FILE *, const char *, ...);
-
#ifdef __i386__
register int T0 asm("esi");
register int T1 asm("ebx");
@@ -91,6 +86,7 @@ typedef struct CCTable {
int (*compute_c)(void); /* return the C flag */
} CCTable;
+/* NOTE: data are not static to force relocation generation by GCC */
extern CCTable cc_table[];
uint8_t parity_table[256] = {
@@ -191,6 +187,14 @@ static inline int lshift(int x, int 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 */
#define REG EAX
@@ -321,7 +325,6 @@ void OPPROTO op_decl_T0_cc(void)
void OPPROTO op_testl_T0_T1_cc(void)
{
- CC_SRC = T0;
CC_DST = T0 & T1;
}
@@ -555,6 +558,7 @@ void OPPROTO op_stl_T0_A0(void)
/* jumps */
/* indirect jump */
+
void OPPROTO op_jmp_T0(void)
{
PC = T0;
@@ -565,6 +569,30 @@ void OPPROTO op_jmp_im(void)
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 */
#define ldul ldl
@@ -663,17 +691,19 @@ void OPPROTO op_jo_cc(void)
int eflags;
eflags = cc_table[CC_OP].compute_all();
if (eflags & CC_O)
- PC += PARAM1;
+ PC = PARAM1;
else
- PC += PARAM2;
+ PC = PARAM2;
+ FORCE_RET();
}
void OPPROTO op_jb_cc(void)
{
if (cc_table[CC_OP].compute_c())
- PC += PARAM1;
+ PC = PARAM1;
else
- PC += PARAM2;
+ PC = PARAM2;
+ FORCE_RET();
}
void OPPROTO op_jz_cc(void)
@@ -681,9 +711,10 @@ void OPPROTO op_jz_cc(void)
int eflags;
eflags = cc_table[CC_OP].compute_all();
if (eflags & CC_Z)
- PC += PARAM1;
+ PC = PARAM1;
else
- PC += PARAM2;
+ PC = PARAM2;
+ FORCE_RET();
}
void OPPROTO op_jbe_cc(void)
@@ -691,9 +722,10 @@ void OPPROTO op_jbe_cc(void)
int eflags;
eflags = cc_table[CC_OP].compute_all();
if (eflags & (CC_Z | CC_C))
- PC += PARAM1;
+ PC = PARAM1;
else
- PC += PARAM2;
+ PC = PARAM2;
+ FORCE_RET();
}
void OPPROTO op_js_cc(void)
@@ -701,9 +733,10 @@ void OPPROTO op_js_cc(void)
int eflags;
eflags = cc_table[CC_OP].compute_all();
if (eflags & CC_S)
- PC += PARAM1;
+ PC = PARAM1;
else
- PC += PARAM2;
+ PC = PARAM2;
+ FORCE_RET();
}
void OPPROTO op_jp_cc(void)
@@ -711,9 +744,10 @@ void OPPROTO op_jp_cc(void)
int eflags;
eflags = cc_table[CC_OP].compute_all();
if (eflags & CC_P)
- PC += PARAM1;
+ PC = PARAM1;
else
- PC += PARAM2;
+ PC = PARAM2;
+ FORCE_RET();
}
void OPPROTO op_jl_cc(void)
@@ -721,9 +755,10 @@ void OPPROTO op_jl_cc(void)
int eflags;
eflags = cc_table[CC_OP].compute_all();
if ((eflags ^ (eflags >> 4)) & 0x80)
- PC += PARAM1;
+ PC = PARAM1;
else
- PC += PARAM2;
+ PC = PARAM2;
+ FORCE_RET();
}
void OPPROTO op_jle_cc(void)
@@ -731,9 +766,10 @@ void OPPROTO op_jle_cc(void)
int eflags;
eflags = cc_table[CC_OP].compute_all();
if (((eflags ^ (eflags >> 4)) & 0x80) || (eflags & CC_Z))
- PC += PARAM1;
+ PC = PARAM1;
else
- PC += PARAM2;
+ PC = PARAM2;
+ FORCE_RET();
}
/* slow set cases (compute x86 flags) */
@@ -1600,14 +1636,13 @@ void OPPROTO op_fcos(void)
/* main execution loop */
uint8_t code_gen_buffer[65536];
-
int cpu_x86_exec(CPUX86State *env1)
{
int saved_T0, saved_T1, saved_A0;
CPUX86State *saved_env;
- int code_gen_size;
+ int code_gen_size, ret;
void (*gen_func)(void);
-
+
/* first we save global registers */
saved_T0 = T0;
saved_T1 = T1;
@@ -1615,17 +1650,21 @@ int cpu_x86_exec(CPUX86State *env1)
saved_env = env;
env = env1;
- for(;;) {
- cpu_x86_gen_code(code_gen_buffer, &code_gen_size, (uint8_t *)env->pc);
- /* execute the generated code */
- gen_func = (void *)code_gen_buffer;
- gen_func();
+ /* prepare setjmp context for exception handling */
+ if (setjmp(env->jmp_env) == 0) {
+ for(;;) {
+ cpu_x86_gen_code(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 0;
+ return ret;
}
diff --git a/ops_template.h b/ops_template.h
index 18b2ffb492..c67fe0fd41 100644
--- a/ops_template.h
+++ b/ops_template.h
@@ -149,18 +149,18 @@ void OPPROTO glue(op_jb_sub, SUFFIX)(void)
src2 = CC_SRC - CC_DST;
if ((DATA_TYPE)src1 < (DATA_TYPE)src2)
- PC += PARAM1;
+ PC = PARAM1;
else
- PC += PARAM2;
+ PC = PARAM2;
FORCE_RET();
}
void OPPROTO glue(op_jz_sub, SUFFIX)(void)
{
if ((DATA_TYPE)CC_DST != 0)
- PC += PARAM1;
+ PC = PARAM1;
else
- PC += PARAM2;
+ PC = PARAM2;
FORCE_RET();
}
@@ -171,18 +171,18 @@ void OPPROTO glue(op_jbe_sub, SUFFIX)(void)
src2 = CC_SRC - CC_DST;
if ((DATA_TYPE)src1 <= (DATA_TYPE)src2)
- PC += PARAM1;
+ PC = PARAM1;
else
- PC += PARAM2;
+ PC = PARAM2;
FORCE_RET();
}
void OPPROTO glue(op_js_sub, SUFFIX)(void)
{
if (CC_DST & SIGN_MASK)
- PC += PARAM1;
+ PC = PARAM1;
else
- PC += PARAM2;
+ PC = PARAM2;
FORCE_RET();
}
@@ -193,9 +193,9 @@ void OPPROTO glue(op_jl_sub, SUFFIX)(void)
src2 = CC_SRC - CC_DST;
if ((DATA_STYPE)src1 < (DATA_STYPE)src2)
- PC += PARAM1;
+ PC = PARAM1;
else
- PC += PARAM2;
+ PC = PARAM2;
FORCE_RET();
}
@@ -206,9 +206,9 @@ void OPPROTO glue(op_jle_sub, SUFFIX)(void)
src2 = CC_SRC - CC_DST;
if ((DATA_STYPE)src1 <= (DATA_STYPE)src2)
- PC += PARAM1;
+ PC = PARAM1;
else
- PC += PARAM2;
+ PC = PARAM2;
FORCE_RET();
}
diff --git a/translate-i386.c b/translate-i386.c
index 9ebc81e2ce..eb621c3e72 100644
--- a/translate-i386.c
+++ b/translate-i386.c
@@ -5,12 +5,24 @@
#include <inttypes.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
#include "cpu-i386.h"
static uint8_t *gen_code_ptr;
int __op_param1, __op_param2, __op_param3;
+#ifdef DEBUG_DISAS
+static FILE *logfile = NULL;
+#endif
+
/* supress that */
static void error(const char *fmt, ...)
{
@@ -704,6 +716,9 @@ static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_
int reg1, reg2, opreg;
int mod, rm, code;
+#ifdef DEBUG_DISAS
+ fprintf(logfile, "modrm=0x%x\n", modrm);
+#endif
mod = (modrm >> 6) & 3;
rm = modrm & 7;
@@ -716,6 +731,9 @@ static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_
if (base == 4) {
havesib = 1;
code = ldub(s->pc++);
+#ifdef DEBUG_DISAS
+ fprintf(logfile, "sib=0x%x\n", code);
+#endif
scale = (code >> 6) & 3;
index = (code >> 3) & 7;
base = code & 7;
@@ -762,6 +780,7 @@ static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_
} else if (scale == 0 && disp == 0) {
gen_op_movl_A0_reg[reg1]();
} else {
+ gen_op_movl_A0_im(disp);
gen_op_addl_A0_reg_sN[scale][reg1]();
}
} else {
@@ -953,8 +972,10 @@ static void gen_setcc(DisasContext *s, int b)
}
}
-/* return the size of the intruction. Return -1 if no insn found */
-int disas_insn(DisasContext *s, uint8_t *pc_start)
+/* return the next pc address. Return -1 if no insn found. *is_jmp_ptr
+ 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 shift, ot;
@@ -967,6 +988,9 @@ int disas_insn(DisasContext *s, uint8_t *pc_start)
// cur_pc = s->pc; /* for insn generation */
next_byte:
b = ldub(s->pc);
+#ifdef DEBUG_DISAS
+ fprintf(logfile, "ib=0x%02x\n", b);
+#endif
if (b < 0)
return -1;
s->pc++;
@@ -1195,6 +1219,7 @@ int disas_insn(DisasContext *s, uint8_t *pc_start)
gen_op_mull_EAX_T0();
break;
}
+ s->cc_op = CC_OP_MUL;
break;
case 5: /* imul */
switch(ot) {
@@ -1209,6 +1234,7 @@ int disas_insn(DisasContext *s, uint8_t *pc_start)
gen_op_imull_EAX_T0();
break;
}
+ s->cc_op = CC_OP_MUL;
break;
case 6: /* div */
switch(ot) {
@@ -1281,9 +1307,11 @@ int disas_insn(DisasContext *s, uint8_t *pc_start)
gen_op_movl_T1_im((long)s->pc);
gen_op_pushl_T1();
gen_op_jmp_T0();
+ *is_jmp_ptr = 1;
break;
case 4: /* jmp Ev */
gen_op_jmp_T0();
+ *is_jmp_ptr = 1;
break;
case 6: /* push Ev */
gen_op_pushl_T0();
@@ -1362,6 +1390,7 @@ int disas_insn(DisasContext *s, uint8_t *pc_start)
op_imulw_T0_T1();
}
gen_op_mov_reg_T0[ot][reg]();
+ s->cc_op = CC_OP_MUL;
break;
/**************************/
@@ -1418,10 +1447,14 @@ int disas_insn(DisasContext *s, uint8_t *pc_start)
ot = dflag ? OT_LONG : OT_WORD;
modrm = ldub(s->pc++);
mod = (modrm >> 6) & 3;
-
+ if (mod != 3)
+ gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
val = insn_get(s, ot);
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;
case 0x8a:
case 0x8b: /* mov Ev, Gv */
@@ -2068,10 +2101,12 @@ int disas_insn(DisasContext *s, uint8_t *pc_start)
gen_op_popl_T0();
gen_op_addl_ESP_im(val);
gen_op_jmp_T0();
+ *is_jmp_ptr = 1;
break;
case 0xc3: /* ret */
gen_op_popl_T0();
gen_op_jmp_T0();
+ *is_jmp_ptr = 1;
break;
case 0xe8: /* call */
val = insn_get(s, OT_LONG);
@@ -2079,16 +2114,19 @@ int disas_insn(DisasContext *s, uint8_t *pc_start)
gen_op_movl_T1_im((long)s->pc);
gen_op_pushl_T1();
gen_op_jmp_im(val);
+ *is_jmp_ptr = 1;
break;
case 0xe9: /* jmp */
val = insn_get(s, OT_LONG);
val += (long)s->pc;
gen_op_jmp_im(val);
+ *is_jmp_ptr = 1;
break;
case 0xeb: /* jmp Jb */
val = (int8_t)insn_get(s, OT_BYTE);
val += (long)s->pc;
gen_op_jmp_im(val);
+ *is_jmp_ptr = 1;
break;
case 0x70 ... 0x7f: /* jcc Jb */
val = (int8_t)insn_get(s, OT_BYTE);
@@ -2103,6 +2141,7 @@ int disas_insn(DisasContext *s, uint8_t *pc_start)
val += (long)s->pc; /* XXX: fix 16 bit wrap */
do_jcc:
gen_jcc(s, b, val);
+ *is_jmp_ptr = 1;
break;
case 0x190 ... 0x19f:
@@ -2164,8 +2203,23 @@ int disas_insn(DisasContext *s, uint8_t *pc_start)
/* misc */
case 0x90: /* nop */
break;
-
-#if 0
+ case 0xcc: /* int3 */
+ 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 */
gen_insn0(OP_ASM);
break;
@@ -2182,16 +2236,78 @@ int cpu_x86_gen_code(uint8_t *gen_code_buf, int *gen_code_size_ptr,
uint8_t *pc_start)
{
DisasContext dc1, *dc = &dc1;
+ int is_jmp;
long ret;
+#ifdef DEBUG_DISAS
+ struct disassemble_info disasm_info;
+#endif
+
dc->cc_op = CC_OP_DYNAMIC;
gen_code_ptr = gen_code_buf;
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)
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_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;
}