Use the standard ASE check for MIPS-3D and MT.
[qemu] / target-i386 / translate-copy.c
index 340864a..d687643 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  i386 on i386 translation
- * 
+ *
  *  Copyright (c) 2003 Fabrice Bellard
  *
  * This library is free software; you can redistribute it and/or
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
+#include "config.h"
+
 #include <stdarg.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
 #include <inttypes.h>
-#include <signal.h>
 #include <assert.h>
-#include <sys/mman.h>
-#include <sys/ucontext.h>
 
 #include "cpu.h"
 #include "exec-all.h"
 #include "disas.h"
 
+#ifdef USE_CODE_COPY
+
+#include <signal.h>
+#include <sys/mman.h>
+#include <sys/ucontext.h>
+
 extern char exec_loop;
 
 /* operand size */
 enum {
     OT_BYTE = 0,
     OT_WORD,
-    OT_LONG, 
+    OT_LONG,
     OT_QUAD,
 };
 
@@ -52,21 +57,22 @@ typedef struct DisasContext {
     int override; /* -1 if no override */
     int prefix;
     int aflag, dflag;
-    uint8_t *pc; /* pc = eip + cs_base */
+    target_ulong pc; /* pc = eip + cs_base */
     int is_jmp; /* 1 = means jump (stop translation), 2 means CPU
                    static state change (stop translation) */
     /* code output */
     uint8_t *gen_code_ptr;
     uint8_t *gen_code_start;
-    
+
     /* current block context */
-    uint8_t *cs_base; /* base of CS segment */
+    target_ulong cs_base; /* base of CS segment */
     int pe;     /* protected mode */
     int code32; /* 32 bit code segment */
     int f_st;   /* currently unused */
     int vm86;   /* vm86 mode */
     int cpl;
     int iopl;
+    int flags;
     struct TranslationBlock *tb;
 } DisasContext;
 
@@ -99,22 +105,22 @@ static inline void gjmp(DisasContext *s, long val)
     gl(s, val - (long)(s->gen_code_ptr + 4));
 }
 
-static inline void gen_movl_addr_im(DisasContext *s, 
+static inline void gen_movl_addr_im(DisasContext *s,
                                     uint32_t addr, uint32_t val)
 {
     gb(s, CPU_SEG); /* seg movl im, addr */
-    gb(s, 0xc7); 
+    gb(s, 0xc7);
     gb(s, 0x05);
     gl(s, addr);
     gl(s, val);
 }
 
-static inline void gen_movw_addr_im(DisasContext *s, 
+static inline void gen_movw_addr_im(DisasContext *s,
                                     uint32_t addr, uint32_t val)
 {
     gb(s, CPU_SEG); /* seg movl im, addr */
-    gb(s, 0x66); 
-    gb(s, 0xc7); 
+    gb(s, 0x66);
+    gb(s, 0xc7);
     gb(s, 0x05);
     gl(s, addr);
     gw(s, val);
@@ -149,7 +155,7 @@ static void gen_jcc(DisasContext *s, int op,
     gb(s, 0xe9); /* jmp */
     tb->tb_jmp_offset[1] = s->gen_code_ptr - s->gen_code_start;
     gl(s, 0);
-    
+
     tb->tb_next_offset[0] = s->gen_code_ptr - s->gen_code_start;
     gen_movl_addr_im(s, CPU_FIELD_OFFSET(eip), target_eip);
     gen_movl_addr_im(s, CPU_FIELD_OFFSET(tmp0), (uint32_t)tb);
@@ -188,7 +194,7 @@ static inline void gen_lea_modrm(DisasContext *s, int modrm)
         base = rm;
         index = 0;
         scale = 0;
-        
+
         if (base == 4) {
             havesib = 1;
             code = ldub_code(s->pc++);
@@ -216,7 +222,7 @@ static inline void gen_lea_modrm(DisasContext *s, int modrm)
             s->pc += 4;
             break;
         }
-        
+
     } else {
         switch (mod) {
         case 0:
@@ -242,7 +248,7 @@ static inline void gen_lea_modrm(DisasContext *s, int modrm)
 static inline void parse_modrm(DisasContext *s, int modrm)
 {
     if ((modrm & 0xc0) != 0xc0)
-        gen_lea_modrm(s, modrm);        
+        gen_lea_modrm(s, modrm);
 }
 
 static inline uint32_t insn_get(DisasContext *s, int ot)
@@ -271,10 +277,10 @@ static inline uint32_t insn_get(DisasContext *s, int ot)
    be stopped.  */
 static int disas_insn(DisasContext *s)
 {
-    uint8_t *pc_start, *pc_tmp, *pc_start_insn;
+    target_ulong pc_start, pc_tmp, pc_start_insn;
     int b, prefixes, aflag, dflag, next_eip, val;
     int ot;
-    int modrm, mod, op;
+    int modrm, mod, op, rm;
 
     pc_start = s->pc;
     prefixes = 0;
@@ -345,7 +351,7 @@ static int disas_insn(DisasContext *s)
         /* extended op code */
         b = ldub_code(s->pc++) | 0x100;
         goto reswitch;
-        
+
         /**************************/
         /* arith & logic */
     case 0x00 ... 0x05:
@@ -364,7 +370,7 @@ static int disas_insn(DisasContext *s)
                 ot = OT_BYTE;
             else
                 ot = dflag ? OT_LONG : OT_WORD;
-            
+
             switch(f) {
             case 0: /* OP Ev, Gv */
                 modrm = ldub_code(s->pc++);
@@ -383,13 +389,14 @@ static int disas_insn(DisasContext *s)
 
     case 0x80: /* GRP1 */
     case 0x81:
+    case 0x82:
     case 0x83:
         {
             if ((b & 1) == 0)
                 ot = OT_BYTE;
             else
                 ot = dflag ? OT_LONG : OT_WORD;
-            
+
             modrm = ldub_code(s->pc++);
             parse_modrm(s, modrm);
 
@@ -397,6 +404,7 @@ static int disas_insn(DisasContext *s)
             default:
             case 0x80:
             case 0x81:
+            case 0x82:
                 insn_get(s, ot);
                 break;
             case 0x83:
@@ -467,8 +475,8 @@ static int disas_insn(DisasContext *s)
             break;
         case 2: /* call Ev */
             /* XXX: optimize and handle MEM exceptions specifically
-               fs movl %eax, regs[0] 
-               movl Ev, %eax 
+               fs movl %eax, regs[0]
+               movl Ev, %eax
                pushl next_eip
                fs movl %eax, eip
             */
@@ -477,8 +485,8 @@ static int disas_insn(DisasContext *s)
             goto unsupported_op;
         case 4: /* jmp Ev */
             /* XXX: optimize and handle MEM exceptions specifically
-               fs movl %eax, regs[0] 
-               movl Ev, %eax 
+               fs movl %eax, regs[0]
+               movl Ev, %eax
                fs movl %eax, eip
             */
             goto unsupported_op;
@@ -498,7 +506,7 @@ static int disas_insn(DisasContext *s)
             ot = dflag ? OT_LONG : OT_WORD;
         insn_get(s, ot);
         break;
-        
+
     case 0x98: /* CWDE/CBW */
         break;
     case 0x99: /* CDQ/CWD */
@@ -518,8 +526,8 @@ static int disas_insn(DisasContext *s)
         break;
 
     case 0x84: /* test Ev, Gv */
-    case 0x85: 
-        
+    case 0x85:
+
     case 0x1c0:
     case 0x1c1: /* xadd Ev, Gv */
 
@@ -575,7 +583,7 @@ static int disas_insn(DisasContext *s)
             goto illegal_op;
         parse_modrm(s, modrm);
         break;
-        
+
         /**************************/
         /* push/pop */
     case 0x50 ... 0x57: /* push */
@@ -644,48 +652,37 @@ static int disas_insn(DisasContext *s)
         op = R_GS;
     do_lxx:
         goto unsupported_op;
-#if 0
         /************************/
         /* floats */
-    case 0xd8 ... 0xdf: 
+    case 0xd8 ... 0xdf:
+#if 1
+        /* currently not stable enough */
+        goto unsupported_op;
+#else
+        if (s->flags & (HF_EM_MASK | HF_TS_MASK))
+            goto unsupported_op;
+#endif
+#if 0
+        /* for testing FPU context switch */
+        {
+            static int count;
+            count = (count + 1) % 3;
+            if (count != 0)
+                goto unsupported_op;
+        }
+#endif
         modrm = ldub_code(s->pc++);
         mod = (modrm >> 6) & 3;
         rm = modrm & 7;
         op = ((b & 7) << 3) | ((modrm >> 3) & 7);
         if (mod != 3) {
             /* memory op */
-            gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
+            parse_modrm(s, modrm);
             switch(op) {
             case 0x00 ... 0x07: /* fxxxs */
             case 0x10 ... 0x17: /* fixxxl */
             case 0x20 ... 0x27: /* fxxxl */
             case 0x30 ... 0x37: /* fixxx */
-                {
-                    int op1;
-                    op1 = op & 7;
-
-                    switch(op >> 4) {
-                    case 0:
-                        gen_op_flds_FT0_A0();
-                        break;
-                    case 1:
-                        gen_op_fildl_FT0_A0();
-                        break;
-                    case 2:
-                        gen_op_fldl_FT0_A0();
-                        break;
-                    case 3:
-                    default:
-                        gen_op_fild_FT0_A0();
-                        break;
-                    }
-                    
-                    gen_op_fp_arith_ST0_FT0[op1]();
-                    if (op1 == 3) {
-                        /* fcomp needs pop */
-                        gen_op_fpop();
-                    }
-                }
                 break;
             case 0x08: /* flds */
             case 0x0a: /* fsts */
@@ -699,102 +696,28 @@ static int disas_insn(DisasContext *s)
             case 0x38: /* filds */
             case 0x3a: /* fists */
             case 0x3b: /* fistps */
-                
-                switch(op & 7) {
-                case 0:
-                    switch(op >> 4) {
-                    case 0:
-                        gen_op_flds_ST0_A0();
-                        break;
-                    case 1:
-                        gen_op_fildl_ST0_A0();
-                        break;
-                    case 2:
-                        gen_op_fldl_ST0_A0();
-                        break;
-                    case 3:
-                    default:
-                        gen_op_fild_ST0_A0();
-                        break;
-                    }
-                    break;
-                default:
-                    switch(op >> 4) {
-                    case 0:
-                        gen_op_fsts_ST0_A0();
-                        break;
-                    case 1:
-                        gen_op_fistl_ST0_A0();
-                        break;
-                    case 2:
-                        gen_op_fstl_ST0_A0();
-                        break;
-                    case 3:
-                    default:
-                        gen_op_fist_ST0_A0();
-                        break;
-                    }
-                    if ((op & 7) == 3)
-                        gen_op_fpop();
-                    break;
-                }
-                break;
             case 0x0c: /* fldenv mem */
-                gen_op_fldenv_A0(s->dflag);
-                break;
             case 0x0d: /* fldcw mem */
-                gen_op_fldcw_A0();
-                break;
             case 0x0e: /* fnstenv mem */
-                gen_op_fnstenv_A0(s->dflag);
-                break;
             case 0x0f: /* fnstcw mem */
-                gen_op_fnstcw_A0();
-                break;
             case 0x1d: /* fldt mem */
-                gen_op_fldt_ST0_A0();
-                break;
             case 0x1f: /* fstpt mem */
-                gen_op_fstt_ST0_A0();
-                gen_op_fpop();
-                break;
             case 0x2c: /* frstor mem */
-                gen_op_frstor_A0(s->dflag);
-                break;
             case 0x2e: /* fnsave mem */
-                gen_op_fnsave_A0(s->dflag);
-                break;
             case 0x2f: /* fnstsw mem */
-                gen_op_fnstsw_A0();
-                break;
             case 0x3c: /* fbld */
-                gen_op_fbld_ST0_A0();
-                break;
             case 0x3e: /* fbstp */
-                gen_op_fbst_ST0_A0();
-                gen_op_fpop();
-                break;
             case 0x3d: /* fildll */
-                gen_op_fildll_ST0_A0();
-                break;
             case 0x3f: /* fistpll */
-                gen_op_fistll_ST0_A0();
-                gen_op_fpop();
                 break;
             default:
                 goto illegal_op;
             }
         } else {
             /* register float ops */
-            opreg = rm;
-
             switch(op) {
             case 0x08: /* fld sti */
-                gen_op_fpush();
-                gen_op_fmov_ST0_STN((opreg + 1) & 7);
-                break;
             case 0x09: /* fxchg sti */
-                gen_op_fxchg_ST0_STN(opreg);
                 break;
             case 0x0a: /* grp d9/2 */
                 switch(rm) {
@@ -807,149 +730,43 @@ static int disas_insn(DisasContext *s)
             case 0x0c: /* grp d9/4 */
                 switch(rm) {
                 case 0: /* fchs */
-                    gen_op_fchs_ST0();
-                    break;
                 case 1: /* fabs */
-                    gen_op_fabs_ST0();
-                    break;
                 case 4: /* ftst */
-                    gen_op_fldz_FT0();
-                    gen_op_fcom_ST0_FT0();
-                    break;
                 case 5: /* fxam */
-                    gen_op_fxam_ST0();
                     break;
                 default:
                     goto illegal_op;
                 }
                 break;
             case 0x0d: /* grp d9/5 */
-                {
-                    switch(rm) {
-                    case 0:
-                        gen_op_fpush();
-                        gen_op_fld1_ST0();
-                        break;
-                    case 1:
-                        gen_op_fpush();
-                        gen_op_fldl2t_ST0();
-                        break;
-                    case 2:
-                        gen_op_fpush();
-                        gen_op_fldl2e_ST0();
-                        break;
-                    case 3:
-                        gen_op_fpush();
-                        gen_op_fldpi_ST0();
-                        break;
-                    case 4:
-                        gen_op_fpush();
-                        gen_op_fldlg2_ST0();
-                        break;
-                    case 5:
-                        gen_op_fpush();
-                        gen_op_fldln2_ST0();
-                        break;
-                    case 6:
-                        gen_op_fpush();
-                        gen_op_fldz_ST0();
-                        break;
-                    default:
-                        goto illegal_op;
-                    }
-                }
-                break;
-            case 0x0e: /* grp d9/6 */
                 switch(rm) {
-                case 0: /* f2xm1 */
-                    gen_op_f2xm1();
-                    break;
-                case 1: /* fyl2x */
-                    gen_op_fyl2x();
-                    break;
-                case 2: /* fptan */
-                    gen_op_fptan();
-                    break;
-                case 3: /* fpatan */
-                    gen_op_fpatan();
-                    break;
-                case 4: /* fxtract */
-                    gen_op_fxtract();
-                    break;
-                case 5: /* fprem1 */
-                    gen_op_fprem1();
-                    break;
-                case 6: /* fdecstp */
-                    gen_op_fdecstp();
+                case 0:
+                case 1:
+                case 2:
+                case 3:
+                case 4:
+                case 5:
+                case 6:
                     break;
                 default:
-                case 7: /* fincstp */
-                    gen_op_fincstp();
-                    break;
+                    goto illegal_op;
                 }
                 break;
+            case 0x0e: /* grp d9/6 */
+                break;
             case 0x0f: /* grp d9/7 */
-                switch(rm) {
-                case 0: /* fprem */
-                    gen_op_fprem();
-                    break;
-                case 1: /* fyl2xp1 */
-                    gen_op_fyl2xp1();
-                    break;
-                case 2: /* fsqrt */
-                    gen_op_fsqrt();
-                    break;
-                case 3: /* fsincos */
-                    gen_op_fsincos();
-                    break;
-                case 5: /* fscale */
-                    gen_op_fscale();
-                    break;
-                case 4: /* frndint */
-                    gen_op_frndint();
-                    break;
-                case 6: /* fsin */
-                    gen_op_fsin();
-                    break;
-                default:
-                case 7: /* fcos */
-                    gen_op_fcos();
-                    break;
-                }
                 break;
             case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */
             case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */
             case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */
-                {
-                    int op1;
-                    
-                    op1 = op & 7;
-                    if (op >= 0x20) {
-                        gen_op_fp_arith_STN_ST0[op1](opreg);
-                        if (op >= 0x30)
-                            gen_op_fpop();
-                    } else {
-                        gen_op_fmov_FT0_STN(opreg);
-                        gen_op_fp_arith_ST0_FT0[op1]();
-                    }
-                }
                 break;
             case 0x02: /* fcom */
-                gen_op_fmov_FT0_STN(opreg);
-                gen_op_fcom_ST0_FT0();
                 break;
             case 0x03: /* fcomp */
-                gen_op_fmov_FT0_STN(opreg);
-                gen_op_fcom_ST0_FT0();
-                gen_op_fpop();
                 break;
             case 0x15: /* da/5 */
                 switch(rm) {
                 case 1: /* fucompp */
-                    gen_op_fmov_FT0_STN(1);
-                    gen_op_fucom_ST0_FT0();
-                    gen_op_fpop();
-                    gen_op_fpop();
                     break;
                 default:
                     goto illegal_op;
@@ -958,15 +775,10 @@ static int disas_insn(DisasContext *s)
             case 0x1c:
                 switch(rm) {
                 case 0: /* feni (287 only, just do nop here) */
-                    break;
                 case 1: /* fdisi (287 only, just do nop here) */
-                    break;
+                    goto unsupported_op;
                 case 2: /* fclex */
-                    gen_op_fclex();
-                    break;
                 case 3: /* fninit */
-                    gen_op_fninit();
-                    break;
                 case 4: /* fsetpm (287 only, just do nop here) */
                     break;
                 default:
@@ -974,42 +786,22 @@ static int disas_insn(DisasContext *s)
                 }
                 break;
             case 0x1d: /* fucomi */
-                if (s->cc_op != CC_OP_DYNAMIC)
-                    gen_op_set_cc_op(s->cc_op);
-                gen_op_fmov_FT0_STN(opreg);
-                gen_op_fucomi_ST0_FT0();
-                s->cc_op = CC_OP_EFLAGS;
                 break;
             case 0x1e: /* fcomi */
-                if (s->cc_op != CC_OP_DYNAMIC)
-                    gen_op_set_cc_op(s->cc_op);
-                gen_op_fmov_FT0_STN(opreg);
-                gen_op_fcomi_ST0_FT0();
-                s->cc_op = CC_OP_EFLAGS;
+                break;
+            case 0x28: /* ffree sti */
                 break;
             case 0x2a: /* fst sti */
-                gen_op_fmov_STN_ST0(opreg);
                 break;
             case 0x2b: /* fstp sti */
-                gen_op_fmov_STN_ST0(opreg);
-                gen_op_fpop();
                 break;
             case 0x2c: /* fucom st(i) */
-                gen_op_fmov_FT0_STN(opreg);
-                gen_op_fucom_ST0_FT0();
                 break;
             case 0x2d: /* fucomp st(i) */
-                gen_op_fmov_FT0_STN(opreg);
-                gen_op_fucom_ST0_FT0();
-                gen_op_fpop();
                 break;
             case 0x33: /* de/3 */
                 switch(rm) {
                 case 1: /* fcompp */
-                    gen_op_fmov_FT0_STN(1);
-                    gen_op_fcom_ST0_FT0();
-                    gen_op_fpop();
-                    gen_op_fpop();
                     break;
                 default:
                     goto illegal_op;
@@ -1018,49 +810,25 @@ static int disas_insn(DisasContext *s)
             case 0x3c: /* df/4 */
                 switch(rm) {
                 case 0:
-                    gen_op_fnstsw_EAX();
                     break;
                 default:
                     goto illegal_op;
                 }
                 break;
             case 0x3d: /* fucomip */
-                if (s->cc_op != CC_OP_DYNAMIC)
-                    gen_op_set_cc_op(s->cc_op);
-                gen_op_fmov_FT0_STN(opreg);
-                gen_op_fucomi_ST0_FT0();
-                gen_op_fpop();
-                s->cc_op = CC_OP_EFLAGS;
                 break;
             case 0x3e: /* fcomip */
-                if (s->cc_op != CC_OP_DYNAMIC)
-                    gen_op_set_cc_op(s->cc_op);
-                gen_op_fmov_FT0_STN(opreg);
-                gen_op_fcomi_ST0_FT0();
-                gen_op_fpop();
-                s->cc_op = CC_OP_EFLAGS;
                 break;
             case 0x10 ... 0x13: /* fcmovxx */
             case 0x18 ... 0x1b:
-                {
-                    int op1;
-                    const static uint8_t fcmov_cc[8] = {
-                        (JCC_B << 1),
-                        (JCC_Z << 1),
-                        (JCC_BE << 1),
-                        (JCC_P << 1),
-                    };
-                    op1 = fcmov_cc[op & 3] | ((op >> 3) & 1);
-                    gen_setcc(s, op1);
-                    gen_op_fcmov_ST0_STN_T0(opreg);
-                }
                 break;
             default:
                 goto illegal_op;
             }
         }
+        s->tb->cflags |= CF_TB_FP_USED;
         break;
-#endif
+
         /**************************/
         /* mov */
     case 0xc6:
@@ -1082,7 +850,7 @@ static int disas_insn(DisasContext *s)
             goto illegal_op;
         parse_modrm(s, modrm);
         break;
-        
+
     case 0xa0: /* mov EAX, Ov */
     case 0xa1:
     case 0xa2: /* mov Ov, EAX */
@@ -1120,14 +888,14 @@ static int disas_insn(DisasContext *s)
         parse_modrm(s, modrm);
         ldub_code(s->pc++);
         break;
-        
+
         /************************/
         /* string ops */
 
     case 0xa4: /* movsS */
     case 0xa5:
         break;
-        
+
     case 0xaa: /* stosS */
     case 0xab:
         break;
@@ -1187,7 +955,7 @@ static int disas_insn(DisasContext *s)
 
     case 0xc3: /* ret */
         gb(s, CPU_SEG);
-        if (!s->dflag)  
+        if (!s->dflag)
             gb(s, 0x66); /* d16 */
         gb(s, 0x8f); /* pop addr */
         gb(s, 0x05);
@@ -1243,7 +1011,7 @@ static int disas_insn(DisasContext *s)
         if (dflag) {
             val = insn_get(s, OT_LONG);
         } else {
-            val = (int16_t)insn_get(s, OT_WORD); 
+            val = (int16_t)insn_get(s, OT_WORD);
         }
     do_jcc:
         next_eip = s->pc - s->cs_base;
@@ -1303,6 +1071,10 @@ static int disas_insn(DisasContext *s)
     case 0x90: /* nop */
         break;
     case 0x9b: /* fwait */
+        if ((s->flags & (HF_MP_MASK | HF_TS_MASK)) ==
+            (HF_MP_MASK | HF_TS_MASK)) {
+            goto unsupported_op;
+        }
         break;
     case 0xcc: /* int3 */
         goto unsupported_op;
@@ -1399,34 +1171,36 @@ static int disas_insn(DisasContext *s)
 #define GEN_CODE_MAX_INSN_SIZE 512
 
 static inline int gen_intermediate_code_internal(CPUState *env,
-                                                 TranslationBlock *tb, 
+                                                 TranslationBlock *tb,
                                                  uint8_t *gen_code_ptr,
                                                  int *gen_code_size_ptr,
                                                  int search_pc,
                                                  uint8_t *tc_ptr)
 {
     DisasContext dc1, *dc = &dc1;
-    uint8_t *pc_insn, *pc_start, *gen_code_end;
+    target_ulong pc_insn, pc_start, cs_base;
+    uint8_t *gen_code_end;
     int flags, ret;
-    uint8_t *cs_base;
 
     if (env->nb_breakpoints > 0 ||
         env->singlestep_enabled)
         return -1;
     flags = tb->flags;
-    if (flags & (HF_TF_MASK | HF_ADDSEG_MASK | 
+    if (flags & (HF_TF_MASK | HF_ADDSEG_MASK |
                  HF_SOFTMMU_MASK | HF_INHIBIT_IRQ_MASK))
         return -1;
     if (!(flags & HF_SS32_MASK))
         return -1;
-    gen_code_end = gen_code_ptr + 
+    if (tb->cflags & CF_SINGLE_INSN)
+        return -1;
+    gen_code_end = gen_code_ptr +
         GEN_CODE_MAX_SIZE - GEN_CODE_MAX_INSN_SIZE;
     dc->gen_code_ptr = gen_code_ptr;
     dc->gen_code_start = gen_code_ptr;
 
     /* generate intermediate code */
-    pc_start = (uint8_t *)tb->pc;
-    cs_base = (uint8_t *)tb->cs_base;
+    pc_start = tb->pc;
+    cs_base = tb->cs_base;
     dc->pc = pc_start;
     dc->cs_base = cs_base;
     dc->pe = (flags >> HF_PE_SHIFT) & 1;
@@ -1436,7 +1210,8 @@ static inline int gen_intermediate_code_internal(CPUState *env,
     dc->cpl = (flags >> HF_CPL_SHIFT) & 3;
     dc->iopl = (flags >> IOPL_SHIFT) & 3;
     dc->tb = tb;
-    
+    dc->flags = flags;
+
     dc->is_jmp = 0;
 
     for(;;) {
@@ -1469,12 +1244,14 @@ static inline int gen_intermediate_code_internal(CPUState *env,
             break;
         }
     }
-    
+
 #ifdef DEBUG_DISAS
-    if (loglevel) {
+    if (loglevel & CPU_LOG_TB_IN_ASM) {
         fprintf(logfile, "----------------\n");
-        fprintf(logfile, "IN: COPY: %s\n", lookup_symbol(pc_start));
-       disas(logfile, pc_start, dc->pc - pc_start, 0, !dc->code32);
+        fprintf(logfile, "IN: COPY: %s fpu=%d\n",
+                lookup_symbol(pc_start),
+                tb->cflags & CF_TB_FP_USED ? 1 : 0);
+       target_disas(logfile, pc_start, dc->pc - pc_start, !dc->code32);
         fprintf(logfile, "\n");
     }
 #endif
@@ -1482,7 +1259,7 @@ static inline int gen_intermediate_code_internal(CPUState *env,
     if (!search_pc) {
         *gen_code_size_ptr = dc->gen_code_ptr - dc->gen_code_start;
         tb->size = dc->pc - pc_start;
-        tb->cflags = CF_CODE_COPY;
+        tb->cflags |= CF_CODE_COPY;
         return 0;
     } else {
         return -1;
@@ -1502,14 +1279,14 @@ int cpu_gen_code_copy(CPUState *env, TranslationBlock *tb,
     tb->tb_jmp_offset[2] = 0xffff;
     tb->tb_jmp_offset[3] = 0xffff;
 #endif
-    return gen_intermediate_code_internal(env, tb, 
+    return gen_intermediate_code_internal(env, tb,
                                           tb->tc_ptr, gen_code_size_ptr,
                                           0, NULL);
 }
 
 static uint8_t dummy_gen_code_buf[GEN_CODE_MAX_SIZE];
 
-int cpu_restore_state_copy(TranslationBlock *tb, 
+int cpu_restore_state_copy(TranslationBlock *tb,
                            CPUState *env, unsigned long searched_pc,
                            void *puc)
 {
@@ -1520,14 +1297,14 @@ int cpu_restore_state_copy(TranslationBlock *tb,
     if (searched_pc < (unsigned long)tb->tc_ptr)
         return -1;
     searched_pc = searched_pc - (long)tb->tc_ptr + (long)dummy_gen_code_buf;
-    ret = gen_intermediate_code_internal(env, tb, 
+    ret = gen_intermediate_code_internal(env, tb,
                                          dummy_gen_code_buf, NULL,
                                          1, (uint8_t *)searched_pc);
     if (ret < 0)
         return ret;
     /* restore all the CPU state from the CPU context from the
-       signal */
-    
+       signal. The FPU context stays in the host CPU. */
+
     env->regs[R_EAX] = uc->uc_mcontext.gregs[REG_EAX];
     env->regs[R_ECX] = uc->uc_mcontext.gregs[REG_ECX];
     env->regs[R_EDX] = uc->uc_mcontext.gregs[REG_EDX];
@@ -1542,3 +1319,5 @@ int cpu_restore_state_copy(TranslationBlock *tb,
     env->cc_op = CC_OP_EFLAGS;
     return 0;
 }
+
+#endif /* USE_CODE_COPY */