]> git.proxmox.com Git - qemu.git/commitdiff
fixed 16 bit segment optimisations
authorbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>
Sun, 13 Jun 2004 13:26:14 +0000 (13:26 +0000)
committerbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>
Sun, 13 Jun 2004 13:26:14 +0000 (13:26 +0000)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@922 c046a42c-6fe2-441c-8c8c-71466251a162

target-i386/cpu.h
target-i386/translate.c

index 9f16a487f074e0c034490f450a07882923f40f10..94f621cd109a1e207500d64d003fc0884d04a9e1 100644 (file)
 /* 16 or 32 segments */
 #define HF_CS32_SHIFT        4
 #define HF_SS32_SHIFT        5
-/* zero base for DS, ES and SS */
+/* zero base for DS, ES and SS : can be '0' only in 32 bit CS segment */
 #define HF_ADDSEG_SHIFT      6
 /* copy of CR0.PE (protected mode) */
 #define HF_PE_SHIFT          7
@@ -398,7 +398,9 @@ static inline void cpu_x86_load_seg_cache(CPUX86State *env,
         >> (DESC_B_SHIFT - HF_CS32_SHIFT);
     new_hflags |= (env->segs[R_SS].flags & DESC_B_MASK)
         >> (DESC_B_SHIFT - HF_SS32_SHIFT);
-    if (!(env->cr[0] & CR0_PE_MASK) || (env->eflags & VM_MASK)) {
+    if (!(env->cr[0] & CR0_PE_MASK) || 
+        (env->eflags & VM_MASK) ||
+        !(new_hflags & HF_CS32_MASK)) {
         /* XXX: try to avoid this test. The problem comes from the
            fact that is real mode or vm86 mode we only modify the
            'base' and 'selector' fields of the segment cache to go
index 811356bafc0947060a499f88157b3c9ebaa76c76..13840bbf92fa6bac39ecc188e437bfd79c4ebb8b 100644 (file)
@@ -1538,15 +1538,17 @@ static void gen_movl_seg_T0(DisasContext *s, int seg_reg, unsigned int cur_eip)
             gen_op_set_cc_op(s->cc_op);
         gen_op_jmp_im(cur_eip);
         gen_op_movl_seg_T0(seg_reg);
+        /* abort translation because the addseg value may change or
+           because ss32 may change. For R_SS, translation must always
+           stop as a special handling must be done to disable hardware
+           interrupts for the next instruction */
+        if (seg_reg == R_SS || (s->code32 && seg_reg < R_FS))
+            s->is_jmp = 3;
     } else {
         gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[seg_reg]));
+        if (seg_reg == R_SS)
+            s->is_jmp = 3;
     }
-    /* abort translation because the register may have a non zero base
-       or because ss32 may change. For R_SS, translation must always
-       stop as a special handling must be done to disable hardware
-       interrupts for the next instruction */
-    if (seg_reg == R_SS || (!s->addseg && seg_reg < R_FS))
-        s->is_jmp = 3;
 }
 
 static inline void gen_stack_update(DisasContext *s, int addend)
@@ -4572,7 +4574,7 @@ static inline int gen_intermediate_code_internal(CPUState *env,
                     );
 #if 0
     /* check addseg logic */
-    if (!dc->addseg && (dc->vm86 || !dc->pe))
+    if (!dc->addseg && (dc->vm86 || !dc->pe || !dc->code32))
         printf("ERROR addseg\n");
 #endif