Commit 7eee2a509a9a777aafd0c2efb14b837b83a8df9c
1 parent
42c3c0cc
CR0.MP/EM/TS support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@642 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
3 changed files
with
32 additions
and
1 deletions
target-i386/cpu.h
| @@ -115,6 +115,9 @@ | @@ -115,6 +115,9 @@ | ||
| 115 | /* copy of CR0.PE (protected mode) */ | 115 | /* copy of CR0.PE (protected mode) */ |
| 116 | #define HF_PE_SHIFT 7 | 116 | #define HF_PE_SHIFT 7 |
| 117 | #define HF_TF_SHIFT 8 /* must be same as eflags */ | 117 | #define HF_TF_SHIFT 8 /* must be same as eflags */ |
| 118 | +#define HF_MP_SHIFT 9 /* the order must be MP, EM, TS */ | ||
| 119 | +#define HF_EM_SHIFT 10 | ||
| 120 | +#define HF_TS_SHIFT 11 | ||
| 118 | #define HF_IOPL_SHIFT 12 /* must be same as eflags */ | 121 | #define HF_IOPL_SHIFT 12 /* must be same as eflags */ |
| 119 | #define HF_VM_SHIFT 17 /* must be same as eflags */ | 122 | #define HF_VM_SHIFT 17 /* must be same as eflags */ |
| 120 | 123 | ||
| @@ -126,9 +129,15 @@ | @@ -126,9 +129,15 @@ | ||
| 126 | #define HF_ADDSEG_MASK (1 << HF_ADDSEG_SHIFT) | 129 | #define HF_ADDSEG_MASK (1 << HF_ADDSEG_SHIFT) |
| 127 | #define HF_PE_MASK (1 << HF_PE_SHIFT) | 130 | #define HF_PE_MASK (1 << HF_PE_SHIFT) |
| 128 | #define HF_TF_MASK (1 << HF_TF_SHIFT) | 131 | #define HF_TF_MASK (1 << HF_TF_SHIFT) |
| 132 | +#define HF_MP_MASK (1 << HF_MP_SHIFT) | ||
| 133 | +#define HF_EM_MASK (1 << HF_EM_SHIFT) | ||
| 134 | +#define HF_TS_MASK (1 << HF_TS_SHIFT) | ||
| 129 | 135 | ||
| 130 | #define CR0_PE_MASK (1 << 0) | 136 | #define CR0_PE_MASK (1 << 0) |
| 137 | +#define CR0_MP_MASK (1 << 1) | ||
| 138 | +#define CR0_EM_MASK (1 << 2) | ||
| 131 | #define CR0_TS_MASK (1 << 3) | 139 | #define CR0_TS_MASK (1 << 3) |
| 140 | +#define CR0_NE_MASK (1 << 5) | ||
| 132 | #define CR0_WP_MASK (1 << 16) | 141 | #define CR0_WP_MASK (1 << 16) |
| 133 | #define CR0_AM_MASK (1 << 18) | 142 | #define CR0_AM_MASK (1 << 18) |
| 134 | #define CR0_PG_MASK (1 << 31) | 143 | #define CR0_PG_MASK (1 << 31) |
| @@ -280,7 +289,7 @@ typedef struct CPUX86State { | @@ -280,7 +289,7 @@ typedef struct CPUX86State { | ||
| 280 | unsigned int fpus; | 289 | unsigned int fpus; |
| 281 | unsigned int fpuc; | 290 | unsigned int fpuc; |
| 282 | uint8_t fptags[8]; /* 0 = valid, 1 = empty */ | 291 | uint8_t fptags[8]; /* 0 = valid, 1 = empty */ |
| 283 | - CPU86_LDouble fpregs[8]; | 292 | + CPU86_LDouble fpregs[8]; |
| 284 | 293 | ||
| 285 | /* emulator internal variables */ | 294 | /* emulator internal variables */ |
| 286 | CPU86_LDouble ft0; | 295 | CPU86_LDouble ft0; |
| @@ -304,8 +313,11 @@ typedef struct CPUX86State { | @@ -304,8 +313,11 @@ typedef struct CPUX86State { | ||
| 304 | uint32_t sysenter_eip; | 313 | uint32_t sysenter_eip; |
| 305 | 314 | ||
| 306 | /* temporary data for USE_CODE_COPY mode */ | 315 | /* temporary data for USE_CODE_COPY mode */ |
| 316 | +#ifdef USE_CODE_COPY | ||
| 307 | uint32_t tmp0; | 317 | uint32_t tmp0; |
| 308 | uint32_t saved_esp; | 318 | uint32_t saved_esp; |
| 319 | + int native_fp_regs; /* if true, the FPU state is in the native CPU regs */ | ||
| 320 | +#endif | ||
| 309 | 321 | ||
| 310 | /* exception/interrupt handling */ | 322 | /* exception/interrupt handling */ |
| 311 | jmp_buf jmp_env; | 323 | jmp_buf jmp_env; |
target-i386/op.c
| @@ -998,6 +998,7 @@ void OPPROTO op_movl_env_T1(void) | @@ -998,6 +998,7 @@ void OPPROTO op_movl_env_T1(void) | ||
| 998 | void OPPROTO op_clts(void) | 998 | void OPPROTO op_clts(void) |
| 999 | { | 999 | { |
| 1000 | env->cr[0] &= ~CR0_TS_MASK; | 1000 | env->cr[0] &= ~CR0_TS_MASK; |
| 1001 | + env->hflags &= ~HF_TS_MASK; | ||
| 1001 | } | 1002 | } |
| 1002 | 1003 | ||
| 1003 | /* flags handling */ | 1004 | /* flags handling */ |
target-i386/translate.c
| @@ -63,6 +63,7 @@ typedef struct DisasContext { | @@ -63,6 +63,7 @@ typedef struct DisasContext { | ||
| 63 | int singlestep_enabled; /* "hardware" single step enabled */ | 63 | int singlestep_enabled; /* "hardware" single step enabled */ |
| 64 | int jmp_opt; /* use direct block chaining for direct jumps */ | 64 | int jmp_opt; /* use direct block chaining for direct jumps */ |
| 65 | int mem_index; /* select memory access functions */ | 65 | int mem_index; /* select memory access functions */ |
| 66 | + int flags; /* all execution flags */ | ||
| 66 | struct TranslationBlock *tb; | 67 | struct TranslationBlock *tb; |
| 67 | int popl_esp_hack; /* for correct popl with esp base handling */ | 68 | int popl_esp_hack; /* for correct popl with esp base handling */ |
| 68 | } DisasContext; | 69 | } DisasContext; |
| @@ -2814,6 +2815,12 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -2814,6 +2815,12 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) | ||
| 2814 | /************************/ | 2815 | /************************/ |
| 2815 | /* floats */ | 2816 | /* floats */ |
| 2816 | case 0xd8 ... 0xdf: | 2817 | case 0xd8 ... 0xdf: |
| 2818 | + if (s->flags & (HF_EM_MASK | HF_TS_MASK)) { | ||
| 2819 | + /* if CR0.EM or CR0.TS are set, generate an FPU exception */ | ||
| 2820 | + /* XXX: what to do if illegal op ? */ | ||
| 2821 | + gen_exception(s, EXCP07_PREX, pc_start - s->cs_base); | ||
| 2822 | + break; | ||
| 2823 | + } | ||
| 2817 | modrm = ldub_code(s->pc++); | 2824 | modrm = ldub_code(s->pc++); |
| 2818 | mod = (modrm >> 6) & 3; | 2825 | mod = (modrm >> 6) & 3; |
| 2819 | rm = modrm & 7; | 2826 | rm = modrm & 7; |
| @@ -3225,6 +3232,9 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -3225,6 +3232,9 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) | ||
| 3225 | goto illegal_op; | 3232 | goto illegal_op; |
| 3226 | } | 3233 | } |
| 3227 | } | 3234 | } |
| 3235 | +#ifdef USE_CODE_COPY | ||
| 3236 | + s->tb->cflags |= CF_TB_FP_USED; | ||
| 3237 | +#endif | ||
| 3228 | break; | 3238 | break; |
| 3229 | /************************/ | 3239 | /************************/ |
| 3230 | /* string ops */ | 3240 | /* string ops */ |
| @@ -3747,6 +3757,10 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -3747,6 +3757,10 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) | ||
| 3747 | goto illegal_op; | 3757 | goto illegal_op; |
| 3748 | break; | 3758 | break; |
| 3749 | case 0x9b: /* fwait */ | 3759 | case 0x9b: /* fwait */ |
| 3760 | + if ((s->flags & (HF_MP_MASK | HF_TS_MASK)) == | ||
| 3761 | + (HF_MP_MASK | HF_TS_MASK)) { | ||
| 3762 | + gen_exception(s, EXCP07_PREX, pc_start - s->cs_base); | ||
| 3763 | + } | ||
| 3750 | break; | 3764 | break; |
| 3751 | case 0xcc: /* int3 */ | 3765 | case 0xcc: /* int3 */ |
| 3752 | gen_interrupt(s, EXCP03_INT3, pc_start - s->cs_base, s->pc - s->cs_base); | 3766 | 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) | @@ -4140,6 +4154,9 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) | ||
| 4140 | gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); | 4154 | gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
| 4141 | } else { | 4155 | } else { |
| 4142 | gen_op_clts(); | 4156 | gen_op_clts(); |
| 4157 | + /* abort block because static cpu state changed */ | ||
| 4158 | + gen_op_jmp_im(s->pc - s->cs_base); | ||
| 4159 | + gen_eob(s); | ||
| 4143 | } | 4160 | } |
| 4144 | break; | 4161 | break; |
| 4145 | default: | 4162 | default: |
| @@ -4504,6 +4521,7 @@ static inline int gen_intermediate_code_internal(CPUState *env, | @@ -4504,6 +4521,7 @@ static inline int gen_intermediate_code_internal(CPUState *env, | ||
| 4504 | else | 4521 | else |
| 4505 | dc->mem_index = 3; | 4522 | dc->mem_index = 3; |
| 4506 | } | 4523 | } |
| 4524 | + dc->flags = flags; | ||
| 4507 | dc->jmp_opt = !(dc->tf || env->singlestep_enabled || | 4525 | dc->jmp_opt = !(dc->tf || env->singlestep_enabled || |
| 4508 | (flags & HF_INHIBIT_IRQ_MASK) | 4526 | (flags & HF_INHIBIT_IRQ_MASK) |
| 4509 | #ifndef CONFIG_SOFTMMU | 4527 | #ifndef CONFIG_SOFTMMU |