]> git.ipfire.org Git - thirdparty/qemu.git/commitdiff
prints hello world
authorbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>
Mon, 3 Mar 2003 14:32:43 +0000 (14:32 +0000)
committerbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>
Mon, 3 Mar 2003 14:32:43 +0000 (14:32 +0000)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@17 c046a42c-6fe2-441c-8c8c-71466251a162

Makefile
cpu-i386.h
linux-user/main.c
op-i386.c
ops_template.h
translate-i386.c

index a61ab4a76abbca868dbe4b8d52355c5ec05f930f..b007f40dde9b99d01cd1ae02beb9d4131a99aba0 100644 (file)
--- 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
index 4eac51fb50a77136420d5a585302488c01ccf330..9add4175d3d8dc738a0af9c805cb2fc59e9ad834 100644 (file)
@@ -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
 #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)
index 552ce006c770b9cbc660b6e6ff864e23c1a0c0a2..68858daf4c9a56d0268867a2be7d9f5042fd45ec 100644 (file)
 #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();
         }
     }
index 9443e172c758fb7ef6a59354680e419562db15fc..451318af72f000abc114ce87a8a29b4b24f646f4 100644 (file)
--- 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;
 }
index 18b2ffb4920fc83370246dfa714126622738b940..c67fe0fd41e1273d26dcadfc5448069848d96758 100644 (file)
@@ -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();
 }
 
index 9ebc81e2ce6fbc514e0443e445e88b3e147b52fe..eb621c3e7287b6b7050ad72cb5db2473ff90aa77 100644 (file)
@@ -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;
 }