commit 4136f33c7e3c034b17bb0032fa5d4297ae2f317a
Author: bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>
Date:   Sun Nov 23 23:09:40 2003 +0000

    fixed eflags IF/IOPL update
    
    
    git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@476 c046a42c-6fe2-441c-8c8c-71466251a162

diff --git a/target-i386/exec.h b/target-i386/exec.h
index dd11a3a..f6c717e 100644
--- a/target-i386/exec.h
+++ b/target-i386/exec.h
@@ -512,11 +512,6 @@ static inline uint32_t compute_eflags(void)
     return env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
 }
 
-#define FL_UPDATE_MASK32 (TF_MASK | AC_MASK | ID_MASK)
-
-#define FL_UPDATE_CPL0_MASK (TF_MASK | IF_MASK | IOPL_MASK | NT_MASK | \
-                             RF_MASK | AC_MASK | ID_MASK)
-
 /* NOTE: CC_OP must be modified manually to CC_OP_EFLAGS */
 static inline void load_eflags(int eflags, int update_mask)
 {
diff --git a/target-i386/helper.c b/target-i386/helper.c
index 861266f..a743cfb 100644
--- a/target-i386/helper.c
+++ b/target-i386/helper.c
@@ -419,7 +419,8 @@ static void switch_tss(int tss_selector,
     /* load all registers without an exception, then reload them with
        possible exception */
     env->eip = new_eip;
-    eflags_mask = FL_UPDATE_CPL0_MASK;
+    eflags_mask = TF_MASK | AC_MASK | ID_MASK | 
+        IF_MASK | IOPL_MASK | VM_MASK | RF_MASK;
     if (!(type & 8))
         eflags_mask &= 0xffff;
     load_eflags(new_eflags, eflags_mask);
@@ -575,27 +576,6 @@ static void do_interrupt_protected(int intno, int is_int, int error_code,
     uint32_t e1, e2, offset, ss, esp, ss_e1, ss_e2;
     uint32_t old_eip;
 
-#ifdef DEBUG_PCALL
-    if (loglevel) {
-        static int count;
-        fprintf(logfile, "%d: interrupt: vector=%02x error_code=%04x int=%d CS:IP=%04x:%08x CPL=%d\n",
-                count, intno, error_code, is_int, env->segs[R_CS].selector, env->eip, env->hflags & 3);
-#if 0
-        {
-            int i;
-            uint8_t *ptr;
-            printf("       code=");
-            ptr = env->segs[R_CS].base + env->eip;
-            for(i = 0; i < 16; i++) {
-                printf(" %02x", ldub(ptr + i));
-            }
-            printf("\n");
-        }
-#endif
-        count++;
-    }
-#endif
-
     has_error_code = 0;
     if (!is_int && !is_hw) {
         switch(intno) {
@@ -775,7 +755,7 @@ static void do_interrupt_protected(int intno, int is_int, int error_code,
 
 /* real mode interrupt */
 static void do_interrupt_real(int intno, int is_int, int error_code,
-                                 unsigned int next_eip)
+                              unsigned int next_eip)
 {
     SegmentCache *dt;
     uint8_t *ptr, *ssp;
@@ -844,6 +824,27 @@ void do_interrupt_user(int intno, int is_int, int error_code,
 void do_interrupt(int intno, int is_int, int error_code, 
                   unsigned int next_eip, int is_hw)
 {
+#ifdef DEBUG_PCALL
+    if (loglevel) {
+        static int count;
+        fprintf(logfile, "%d: interrupt: vector=%02x error_code=%04x int=%d\n",
+                count, intno, error_code, is_int);
+        cpu_x86_dump_state(env, logfile, X86_DUMP_CCOP);
+#if 0
+        {
+            int i;
+            uint8_t *ptr;
+            printf("       code=");
+            ptr = env->segs[R_CS].base + env->eip;
+            for(i = 0; i < 16; i++) {
+                printf(" %02x", ldub(ptr + i));
+            }
+            printf("\n");
+        }
+#endif
+        count++;
+    }
+#endif
     if (env->cr[0] & CR0_PE_MASK) {
         do_interrupt_protected(intno, is_int, error_code, next_eip, is_hw);
     } else {
@@ -1293,6 +1294,7 @@ void helper_lcall_protected_T0_T1(int shift, int next_eip)
     if (loglevel) {
         fprintf(logfile, "lcall %04x:%08x\n",
                 new_cs, new_eip);
+        cpu_x86_dump_state(env, logfile, X86_DUMP_CCOP);
     }
 #endif
     if ((new_cs & 0xfffc) == 0)
@@ -1493,13 +1495,13 @@ void helper_iret_real(int shift)
         POPW(ssp, sp, sp_mask, new_cs);
         POPW(ssp, sp, sp_mask, new_eflags);
     }
-    ESP = (ESP & ~sp_mask) | (sp & 0xffff);
+    ESP = (ESP & ~sp_mask) | (sp & sp_mask);
     load_seg_vm(R_CS, new_cs);
     env->eip = new_eip;
     if (env->eflags & VM_MASK)
-        eflags_mask = FL_UPDATE_MASK32 | IF_MASK | RF_MASK;
+        eflags_mask = TF_MASK | AC_MASK | ID_MASK | IF_MASK | RF_MASK;
     else
-        eflags_mask = FL_UPDATE_CPL0_MASK;
+        eflags_mask = TF_MASK | AC_MASK | ID_MASK | IF_MASK | IOPL_MASK | RF_MASK;
     if (shift == 0)
         eflags_mask &= 0xffff;
     load_eflags(new_eflags, eflags_mask);
@@ -1511,7 +1513,7 @@ static inline void helper_ret_protected(int shift, int is_iret, int addend)
     uint32_t sp, new_cs, new_eip, new_eflags, new_esp, new_ss, sp_mask;
     uint32_t new_es, new_ds, new_fs, new_gs;
     uint32_t e1, e2, ss_e1, ss_e2;
-    int cpl, dpl, rpl, eflags_mask;
+    int cpl, dpl, rpl, eflags_mask, iopl;
     uint8_t *ssp;
     
     sp_mask = get_sp_mask(env->segs[R_SS].flags);
@@ -1536,8 +1538,9 @@ static inline void helper_ret_protected(int shift, int is_iret, int addend)
     }
 #ifdef DEBUG_PCALL
     if (loglevel) {
-        fprintf(logfile, "lret new %04x:%08x\n",
-                new_cs, new_eip);
+        fprintf(logfile, "lret new %04x:%08x addend=0x%x\n",
+                new_cs, new_eip, addend);
+        cpu_x86_dump_state(env, logfile, X86_DUMP_CCOP);
     }
 #endif
     if ((new_cs & 0xfffc) == 0)
@@ -1611,11 +1614,13 @@ static inline void helper_ret_protected(int shift, int is_iret, int addend)
     ESP = (ESP & ~sp_mask) | (sp & sp_mask);
     env->eip = new_eip;
     if (is_iret) {
-        /* NOTE: 'cpl' can be different from the current CPL */
+        /* NOTE: 'cpl' is the _old_ CPL */
+        eflags_mask = TF_MASK | AC_MASK | ID_MASK | RF_MASK;
         if (cpl == 0)
-            eflags_mask = FL_UPDATE_CPL0_MASK;
-        else
-            eflags_mask = FL_UPDATE_MASK32;
+            eflags_mask |= IOPL_MASK;
+        iopl = (env->eflags >> IOPL_SHIFT) & 3;
+        if (cpl <= iopl)
+            eflags_mask |= IF_MASK;
         if (shift == 0)
             eflags_mask &= 0xffff;
         load_eflags(new_eflags, eflags_mask);
@@ -1631,7 +1636,8 @@ static inline void helper_ret_protected(int shift, int is_iret, int addend)
     POPL(ssp, sp, sp_mask, new_gs);
     
     /* modify processor state */
-    load_eflags(new_eflags, FL_UPDATE_CPL0_MASK | VM_MASK | VIF_MASK | VIP_MASK);
+    load_eflags(new_eflags, TF_MASK | AC_MASK | ID_MASK | 
+                IF_MASK | IOPL_MASK | VM_MASK | VIF_MASK | VIP_MASK);
     load_seg_vm(R_CS, new_cs & 0xffff);
     cpu_x86_set_cpl(env, 3);
     load_seg_vm(R_SS, new_ss & 0xffff);
diff --git a/target-i386/op.c b/target-i386/op.c
index 04046fc..8988e06 100644
--- a/target-i386/op.c
+++ b/target-i386/op.c
@@ -1138,38 +1138,36 @@ void OPPROTO op_set_cc_op(void)
     CC_OP = PARAM1;
 }
 
-#define FL_UPDATE_MASK16 (FL_UPDATE_MASK32 & 0xffff)
+/* XXX: clear VIF/VIP in all ops ? */
 
 void OPPROTO op_movl_eflags_T0(void)
 {
-    int eflags;
-    eflags = T0;
-    CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
-    DF = 1 - (2 * ((eflags >> 10) & 1));
-    /* we also update some system flags as in user mode */
-    env->eflags = (env->eflags & ~FL_UPDATE_MASK32) | 
-        (eflags & FL_UPDATE_MASK32);
+    load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK));
 }
 
 void OPPROTO op_movw_eflags_T0(void)
 {
-    int eflags;
-    eflags = T0;
-    CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
-    DF = 1 - (2 * ((eflags >> 10) & 1));
-    /* we also update some system flags as in user mode */
-    env->eflags = (env->eflags & ~FL_UPDATE_MASK16) | 
-        (eflags & FL_UPDATE_MASK16);
+    load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK) & 0xffff);
+}
+
+void OPPROTO op_movl_eflags_T0_io(void)
+{
+    load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | IF_MASK));
+}
+
+void OPPROTO op_movw_eflags_T0_io(void)
+{
+    load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | IF_MASK) & 0xffff);
 }
 
 void OPPROTO op_movl_eflags_T0_cpl0(void)
 {
-    load_eflags(T0, FL_UPDATE_CPL0_MASK);
+    load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | IF_MASK | IOPL_MASK));
 }
 
 void OPPROTO op_movw_eflags_T0_cpl0(void)
 {
-    load_eflags(T0, FL_UPDATE_CPL0_MASK & 0xffff);
+    load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | IF_MASK | IOPL_MASK) & 0xffff);
 }
 
 #if 0
diff --git a/target-i386/translate.c b/target-i386/translate.c
index b09f1b7..9c5c52e 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -3540,10 +3540,18 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
                     gen_op_movw_eflags_T0_cpl0();
                 }
             } else {
-                if (s->dflag) {
-                    gen_op_movl_eflags_T0();
+                if (s->cpl <= s->iopl) {
+                    if (s->dflag) {
+                        gen_op_movl_eflags_T0_io();
+                    } else {
+                        gen_op_movw_eflags_T0_io();
+                    }
                 } else {
-                    gen_op_movw_eflags_T0();
+                    if (s->dflag) {
+                        gen_op_movl_eflags_T0();
+                    } else {
+                        gen_op_movw_eflags_T0();
+                    }
                 }
             }
             gen_pop_update(s);
@@ -4265,6 +4273,10 @@ static uint16_t opc_write_flags[NB_OPS] = {
     [INDEX_op_movb_eflags_T0] = CC_S | CC_Z | CC_A | CC_P | CC_C,
     [INDEX_op_movw_eflags_T0] = CC_OSZAPC,
     [INDEX_op_movl_eflags_T0] = CC_OSZAPC,
+    [INDEX_op_movw_eflags_T0_io] = CC_OSZAPC,
+    [INDEX_op_movl_eflags_T0_io] = CC_OSZAPC,
+    [INDEX_op_movw_eflags_T0_cpl0] = CC_OSZAPC,
+    [INDEX_op_movl_eflags_T0_cpl0] = CC_OSZAPC,
     [INDEX_op_clc] = CC_C,
     [INDEX_op_stc] = CC_C,
     [INDEX_op_cmc] = CC_C,
