Commit dc196a57e3e2e00e0c5f887390b1191787990193
1 parent
2a282056
fixed 16 bit segment optimisations
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@922 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
2 changed files
with
13 additions
and
9 deletions
target-i386/cpu.h
... | ... | @@ -116,7 +116,7 @@ |
116 | 116 | /* 16 or 32 segments */ |
117 | 117 | #define HF_CS32_SHIFT 4 |
118 | 118 | #define HF_SS32_SHIFT 5 |
119 | -/* zero base for DS, ES and SS */ | |
119 | +/* zero base for DS, ES and SS : can be '0' only in 32 bit CS segment */ | |
120 | 120 | #define HF_ADDSEG_SHIFT 6 |
121 | 121 | /* copy of CR0.PE (protected mode) */ |
122 | 122 | #define HF_PE_SHIFT 7 |
... | ... | @@ -398,7 +398,9 @@ static inline void cpu_x86_load_seg_cache(CPUX86State *env, |
398 | 398 | >> (DESC_B_SHIFT - HF_CS32_SHIFT); |
399 | 399 | new_hflags |= (env->segs[R_SS].flags & DESC_B_MASK) |
400 | 400 | >> (DESC_B_SHIFT - HF_SS32_SHIFT); |
401 | - if (!(env->cr[0] & CR0_PE_MASK) || (env->eflags & VM_MASK)) { | |
401 | + if (!(env->cr[0] & CR0_PE_MASK) || | |
402 | + (env->eflags & VM_MASK) || | |
403 | + !(new_hflags & HF_CS32_MASK)) { | |
402 | 404 | /* XXX: try to avoid this test. The problem comes from the |
403 | 405 | fact that is real mode or vm86 mode we only modify the |
404 | 406 | 'base' and 'selector' fields of the segment cache to go | ... | ... |
target-i386/translate.c
... | ... | @@ -1538,15 +1538,17 @@ static void gen_movl_seg_T0(DisasContext *s, int seg_reg, unsigned int cur_eip) |
1538 | 1538 | gen_op_set_cc_op(s->cc_op); |
1539 | 1539 | gen_op_jmp_im(cur_eip); |
1540 | 1540 | gen_op_movl_seg_T0(seg_reg); |
1541 | + /* abort translation because the addseg value may change or | |
1542 | + because ss32 may change. For R_SS, translation must always | |
1543 | + stop as a special handling must be done to disable hardware | |
1544 | + interrupts for the next instruction */ | |
1545 | + if (seg_reg == R_SS || (s->code32 && seg_reg < R_FS)) | |
1546 | + s->is_jmp = 3; | |
1541 | 1547 | } else { |
1542 | 1548 | gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[seg_reg])); |
1549 | + if (seg_reg == R_SS) | |
1550 | + s->is_jmp = 3; | |
1543 | 1551 | } |
1544 | - /* abort translation because the register may have a non zero base | |
1545 | - or because ss32 may change. For R_SS, translation must always | |
1546 | - stop as a special handling must be done to disable hardware | |
1547 | - interrupts for the next instruction */ | |
1548 | - if (seg_reg == R_SS || (!s->addseg && seg_reg < R_FS)) | |
1549 | - s->is_jmp = 3; | |
1550 | 1552 | } |
1551 | 1553 | |
1552 | 1554 | static inline void gen_stack_update(DisasContext *s, int addend) |
... | ... | @@ -4572,7 +4574,7 @@ static inline int gen_intermediate_code_internal(CPUState *env, |
4572 | 4574 | ); |
4573 | 4575 | #if 0 |
4574 | 4576 | /* check addseg logic */ |
4575 | - if (!dc->addseg && (dc->vm86 || !dc->pe)) | |
4577 | + if (!dc->addseg && (dc->vm86 || !dc->pe || !dc->code32)) | |
4576 | 4578 | printf("ERROR addseg\n"); |
4577 | 4579 | #endif |
4578 | 4580 | ... | ... |