diff --git a/target-i386/cpu.h b/target-i386/cpu.h index 99c6bb98c168cfe72d04fdc8117866b30dc2bf28..84b202659a5f4126d54d9161c241cafccc663735 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -115,6 +115,9 @@ /* copy of CR0.PE (protected mode) */ #define HF_PE_SHIFT 7 #define HF_TF_SHIFT 8 /* must be same as eflags */ +#define HF_MP_SHIFT 9 /* the order must be MP, EM, TS */ +#define HF_EM_SHIFT 10 +#define HF_TS_SHIFT 11 #define HF_IOPL_SHIFT 12 /* must be same as eflags */ #define HF_VM_SHIFT 17 /* must be same as eflags */ @@ -126,9 +129,15 @@ #define HF_ADDSEG_MASK (1 << HF_ADDSEG_SHIFT) #define HF_PE_MASK (1 << HF_PE_SHIFT) #define HF_TF_MASK (1 << HF_TF_SHIFT) +#define HF_MP_MASK (1 << HF_MP_SHIFT) +#define HF_EM_MASK (1 << HF_EM_SHIFT) +#define HF_TS_MASK (1 << HF_TS_SHIFT) #define CR0_PE_MASK (1 << 0) +#define CR0_MP_MASK (1 << 1) +#define CR0_EM_MASK (1 << 2) #define CR0_TS_MASK (1 << 3) +#define CR0_NE_MASK (1 << 5) #define CR0_WP_MASK (1 << 16) #define CR0_AM_MASK (1 << 18) #define CR0_PG_MASK (1 << 31) @@ -280,7 +289,7 @@ typedef struct CPUX86State { unsigned int fpus; unsigned int fpuc; uint8_t fptags[8]; /* 0 = valid, 1 = empty */ - CPU86_LDouble fpregs[8]; + CPU86_LDouble fpregs[8]; /* emulator internal variables */ CPU86_LDouble ft0; @@ -304,8 +313,11 @@ typedef struct CPUX86State { uint32_t sysenter_eip; /* temporary data for USE_CODE_COPY mode */ +#ifdef USE_CODE_COPY uint32_t tmp0; uint32_t saved_esp; + int native_fp_regs; /* if true, the FPU state is in the native CPU regs */ +#endif /* exception/interrupt handling */ jmp_buf jmp_env; diff --git a/target-i386/op.c b/target-i386/op.c index 1503134d1f7742d69f1f48a889cc741755bda593..f592b67a6af25ba316f027a0f0afac4cd1651082 100644 --- a/target-i386/op.c +++ b/target-i386/op.c @@ -998,6 +998,7 @@ void OPPROTO op_movl_env_T1(void) void OPPROTO op_clts(void) { env->cr[0] &= ~CR0_TS_MASK; + env->hflags &= ~HF_TS_MASK; } /* flags handling */ diff --git a/target-i386/translate.c b/target-i386/translate.c index 6e8d8116c7df20f7f63d09947e14c6a4897d97fe..f9823a49d19f15a36898a278e8e3f0f876846c35 100644 --- a/target-i386/translate.c +++ b/target-i386/translate.c @@ -63,6 +63,7 @@ typedef struct DisasContext { int singlestep_enabled; /* "hardware" single step enabled */ int jmp_opt; /* use direct block chaining for direct jumps */ int mem_index; /* select memory access functions */ + int flags; /* all execution flags */ struct TranslationBlock *tb; int popl_esp_hack; /* for correct popl with esp base handling */ } DisasContext; @@ -2814,6 +2815,12 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) /************************/ /* floats */ case 0xd8 ... 0xdf: + if (s->flags & (HF_EM_MASK | HF_TS_MASK)) { + /* if CR0.EM or CR0.TS are set, generate an FPU exception */ + /* XXX: what to do if illegal op ? */ + gen_exception(s, EXCP07_PREX, pc_start - s->cs_base); + break; + } modrm = ldub_code(s->pc++); mod = (modrm >> 6) & 3; rm = modrm & 7; @@ -3225,6 +3232,9 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) goto illegal_op; } } +#ifdef USE_CODE_COPY + s->tb->cflags |= CF_TB_FP_USED; +#endif break; /************************/ /* string ops */ @@ -3747,6 +3757,10 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) goto illegal_op; break; case 0x9b: /* fwait */ + if ((s->flags & (HF_MP_MASK | HF_TS_MASK)) == + (HF_MP_MASK | HF_TS_MASK)) { + gen_exception(s, EXCP07_PREX, pc_start - s->cs_base); + } break; case 0xcc: /* int3 */ gen_interrupt(s, EXCP03_INT3, pc_start - s->cs_base, s->pc - s->cs_base); @@ -4140,6 +4154,9 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); } else { gen_op_clts(); + /* abort block because static cpu state changed */ + gen_op_jmp_im(s->pc - s->cs_base); + gen_eob(s); } break; default: @@ -4504,6 +4521,7 @@ static inline int gen_intermediate_code_internal(CPUState *env, else dc->mem_index = 3; } + dc->flags = flags; dc->jmp_opt = !(dc->tf || env->singlestep_enabled || (flags & HF_INHIBIT_IRQ_MASK) #ifndef CONFIG_SOFTMMU