Commit dc196a57e3e2e00e0c5f887390b1191787990193

Authored by bellard
1 parent 2a282056

fixed 16 bit segment optimisations


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@922 c046a42c-6fe2-441c-8c8c-71466251a162
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  
... ...