Diff for /np2/i386c/ia32/ctrlxfer.c between versions 1.4 and 1.7

version 1.4, 2004/01/26 15:23:21 version 1.7, 2004/02/04 13:24:35
Line 34 Line 34
 #include "ctrlxfer.h"  #include "ctrlxfer.h"
   
   
 static void check_segreg(void);  
   
 /*------------------------------------------------------------------------------  /*------------------------------------------------------------------------------
  * JMPfar_pm   * JMPfar_pm
  */   */
Line 53  JMPfar_pm(WORD selector, DWORD new_ip) Line 51  JMPfar_pm(WORD selector, DWORD new_ip)
         VERBOSE(("JMPfar_pm: old EIP = %04x:%08x, ESP = %04x:%08x", CPU_CS, CPU_PREV_EIP, CPU_SS, CPU_ESP));          VERBOSE(("JMPfar_pm: old EIP = %04x:%08x, ESP = %04x:%08x", CPU_CS, CPU_PREV_EIP, CPU_SS, CPU_ESP));
         VERBOSE(("JMPfar_pm: selector = 0x%04x, new_ip = 0x%08x", selector, new_ip));          VERBOSE(("JMPfar_pm: selector = 0x%04x, new_ip = 0x%08x", selector, new_ip));
   
         rv = parse_selector(&jmp_sel, selector);          rv = parse_selector(&jmp_sel, selector, CPU_IS_USER_MODE());
         if (rv < 0) {          if (rv < 0) {
                 VERBOSE(("JMPfar_pm: parse_selector (selector = %04x, rv = %d)", selector, rv));                  VERBOSE(("JMPfar_pm: parse_selector (selector = %04x, rv = %d)", selector, rv));
                 EXCEPTION(GP_EXCEPTION, jmp_sel.idx);                  EXCEPTION(GP_EXCEPTION, jmp_sel.idx);
Line 175  JMPfar_pm_call_gate(selector_t *callgate Line 173  JMPfar_pm_call_gate(selector_t *callgate
         }          }
   
         /* parse code segment selector */          /* parse code segment selector */
         rv = parse_selector(&cs_sel, callgate_sel->desc.u.gate.selector);          rv = parse_selector(&cs_sel, callgate_sel->desc.u.gate.selector, CPU_IS_USER_MODE());
         if (rv < 0) {          if (rv < 0) {
                 VERBOSE(("JMPfar_pm: parse_selector (selector = %04x, rv = %d)", callgate_sel->desc.u.gate.selector, rv));                  VERBOSE(("JMPfar_pm: parse_selector (selector = %04x, rv = %d)", callgate_sel->desc.u.gate.selector, rv));
                 EXCEPTION(GP_EXCEPTION, cs_sel.idx);                  EXCEPTION(GP_EXCEPTION, cs_sel.idx);
Line 268  JMPfar_pm_task_gate(selector_t *taskgate Line 266  JMPfar_pm_task_gate(selector_t *taskgate
         }          }
   
         /* parse tss selector */          /* parse tss selector */
         rv = parse_selector(&tss_sel, taskgate_sel->desc.u.gate.selector);          rv = parse_selector(&tss_sel, taskgate_sel->desc.u.gate.selector, CPU_IS_USER_MODE());
         if (rv < 0 || tss_sel.ldt) {          if (rv < 0 || tss_sel.ldt) {
                 VERBOSE(("JMPfar_pm: parse_selector (selector = %04x, rv = %d, %cDT)", taskgate_sel->desc.u.gate.selector, rv, tss_sel.ldt ? 'L' : 'G'));                  VERBOSE(("JMPfar_pm: parse_selector (selector = %04x, rv = %d, %cDT)", taskgate_sel->desc.u.gate.selector, rv, tss_sel.ldt ? 'L' : 'G'));
                 EXCEPTION(GP_EXCEPTION, tss_sel.idx);                  EXCEPTION(GP_EXCEPTION, tss_sel.idx);
Line 364  CALLfar_pm(WORD selector, DWORD new_ip) Line 362  CALLfar_pm(WORD selector, DWORD new_ip)
         VERBOSE(("CALLfar_pm: old EIP = %04x:%08x, ESP = %04x:%08x", CPU_CS, CPU_PREV_EIP, CPU_SS, CPU_ESP));          VERBOSE(("CALLfar_pm: old EIP = %04x:%08x, ESP = %04x:%08x", CPU_CS, CPU_PREV_EIP, CPU_SS, CPU_ESP));
         VERBOSE(("CALLfar_pm: selector = 0x%04x, new_ip = 0x%08x", selector, new_ip));          VERBOSE(("CALLfar_pm: selector = 0x%04x, new_ip = 0x%08x", selector, new_ip));
   
         rv = parse_selector(&call_sel, selector);          rv = parse_selector(&call_sel, selector, CPU_IS_USER_MODE());
         if (rv < 0) {          if (rv < 0) {
                 VERBOSE(("CALLfar_pm: parse_selector (selector = %04x, rv = %d)", selector, rv));                  VERBOSE(("CALLfar_pm: parse_selector (selector = %04x, rv = %d)", selector, rv));
                 EXCEPTION(GP_EXCEPTION, call_sel.idx);                  EXCEPTION(GP_EXCEPTION, call_sel.idx);
Line 514  CALLfar_pm_call_gate(selector_t *callgat Line 512  CALLfar_pm_call_gate(selector_t *callgat
         }          }
   
         /* parse code segment descriptor */          /* parse code segment descriptor */
         rv = parse_selector(&cs_sel, callgate_sel->desc.u.gate.selector);          rv = parse_selector(&cs_sel, callgate_sel->desc.u.gate.selector, CPU_IS_USER_MODE());
         if (rv < 0) {          if (rv < 0) {
                 VERBOSE(("CALLfar_pm: parse_selector (selector = %04x, rv = %d)", callgate_sel->desc.u.gate.selector, rv));                  VERBOSE(("CALLfar_pm: parse_selector (selector = %04x, rv = %d)", callgate_sel->desc.u.gate.selector, rv));
                 EXCEPTION(GP_EXCEPTION, cs_sel.idx);                  EXCEPTION(GP_EXCEPTION, cs_sel.idx);
Line 631  CALLfar_pm_call_gate_more_privilege(sele Line 629  CALLfar_pm_call_gate_more_privilege(sele
         get_stack_from_tss(cs_sel->desc.dpl, &tss_ss, &tss_esp);          get_stack_from_tss(cs_sel->desc.dpl, &tss_ss, &tss_esp);
   
         /* parse stack segment descriptor */          /* parse stack segment descriptor */
         rv = parse_selector(&ss_sel, tss_ss);          rv = parse_selector(&ss_sel, tss_ss, CPU_IS_USER_MODE());
         if (rv < 0) {          if (rv < 0) {
                 VERBOSE(("CALLfar_pm: parse_selector (selector = %04x, rv = %d)", tss_ss, rv));                  VERBOSE(("CALLfar_pm: parse_selector (selector = %04x, rv = %d)", tss_ss, rv));
                 EXCEPTION(TS_EXCEPTION, ss_sel.idx);                  EXCEPTION(TS_EXCEPTION, ss_sel.idx);
Line 753  CALLfar_pm_task_gate(selector_t *taskgat Line 751  CALLfar_pm_task_gate(selector_t *taskgat
         }          }
   
         /* tss descriptor */          /* tss descriptor */
         rv = parse_selector(&tss_sel, taskgate_sel->desc.u.gate.selector);          rv = parse_selector(&tss_sel, taskgate_sel->desc.u.gate.selector, CPU_IS_USER_MODE());
         if (rv < 0 || tss_sel.ldt) {          if (rv < 0 || tss_sel.ldt) {
                 VERBOSE(("CALLfar_pm: parse_selector (selector = %04x, rv = %d, %s)", tss_sel.selector, rv, tss_sel.ldt ? "LDT" : "GDT"));                  VERBOSE(("CALLfar_pm: parse_selector (selector = %04x, rv = %d, %s)", tss_sel.selector, rv, tss_sel.ldt ? "LDT" : "GDT"));
                 EXCEPTION(GP_EXCEPTION, tss_sel.idx);                  EXCEPTION(GP_EXCEPTION, tss_sel.idx);
Line 840  CALLfar_pm_tss(selector_t *tss_sel) Line 838  CALLfar_pm_tss(selector_t *tss_sel)
 void  void
 RETfar_pm(DWORD nbytes)  RETfar_pm(DWORD nbytes)
 {  {
         selector_t ret_sel, ss_sel;          selector_t ret_sel, ss_sel, temp_sel;
         DWORD sp;          DWORD sp;
         DWORD new_ip, new_sp;          DWORD new_ip, new_sp;
         WORD new_cs, new_ss;          WORD new_cs, new_ss;
         int rv;          int rv;
           int i;
   
         VERBOSE(("RETfar_pm: old EIP = %04x:%08x, ESP = %04x:%08x, nbytes = %d", CPU_CS, CPU_PREV_EIP, CPU_SS, CPU_ESP, nbytes));          VERBOSE(("RETfar_pm: old EIP = %04x:%08x, ESP = %04x:%08x, nbytes = %d", CPU_CS, CPU_PREV_EIP, CPU_SS, CPU_ESP, nbytes));
   
Line 863  RETfar_pm(DWORD nbytes) Line 862  RETfar_pm(DWORD nbytes)
                 new_cs = cpu_vmemoryread_w(CPU_SS_INDEX, sp + 2);                  new_cs = cpu_vmemoryread_w(CPU_SS_INDEX, sp + 2);
         }          }
   
         rv = parse_selector(&ret_sel, new_cs);          rv = parse_selector(&ret_sel, new_cs, CPU_IS_USER_MODE());
         if (rv < 0) {          if (rv < 0) {
                 VERBOSE(("RETfar_pm: parse_selector (selector = %04x, rv = %d, %s)", ret_sel.selector, rv));                  VERBOSE(("RETfar_pm: parse_selector (selector = %04x, rv = %d, %s)", ret_sel.selector, rv));
                 EXCEPTION(GP_EXCEPTION, ret_sel.idx);                  EXCEPTION(GP_EXCEPTION, ret_sel.idx);
Line 932  RETfar_pm(DWORD nbytes) Line 931  RETfar_pm(DWORD nbytes)
                         new_ss = cpu_vmemoryread_w(CPU_SS_INDEX, sp + 4 + nbytes + 2);                          new_ss = cpu_vmemoryread_w(CPU_SS_INDEX, sp + 4 + nbytes + 2);
                 }                  }
   
                 rv = parse_selector(&ss_sel, new_ss);                  rv = parse_selector(&ss_sel, new_ss, CPU_IS_USER_MODE());
                 if (rv < 0) {                  if (rv < 0) {
                         VERBOSE(("RETfar_pm: parse_selector (selector = %04x, rv = %d, %s)", ss_sel.selector, rv));                          VERBOSE(("RETfar_pm: parse_selector (selector = %04x, rv = %d, %s)", ss_sel.selector, rv));
                         EXCEPTION(GP_EXCEPTION, ss_sel.idx);                          EXCEPTION(GP_EXCEPTION, ss_sel.idx);
Line 984  RETfar_pm(DWORD nbytes) Line 983  RETfar_pm(DWORD nbytes)
                 CPU_ESP = new_sp + nbytes;                  CPU_ESP = new_sp + nbytes;
   
                 /* check segment register */                  /* check segment register */
                 check_segreg();                  for (i = 0; i < CPU_SEGREG_NUM; i++) {
                           descriptor_t *dp;
                           BOOL valid;
   
                           dp = &CPU_STAT_SREG(i);
                           if ((!dp->u.seg.c || !dp->u.seg.ec)
                            && (CPU_STAT_SREG(i).dpl < CPU_STAT_CPL)) {
                                   /* segment register is invalid */
                                   CPU_REGS_SREG(i) = 0;
                                   CPU_STAT_SREG_CLEAR(i);
                                   continue;
                           }
   
                           rv = parse_selector(&temp_sel, CPU_REGS_SREG(i), CPU_IS_USER_MODE());
                           if (rv < 0) {
                                   /* segment register is invalid */
                                   CPU_REGS_SREG(i) = 0;
                                   CPU_STAT_SREG_CLEAR(i);
                                   continue;
                           }
   
                           valid = TRUE;
                           if (!temp_sel.desc.s) {
                                   /* system segment */
                                   valid = FALSE;
                           }
                           if (temp_sel.desc.u.seg.c && !temp_sel.desc.u.seg.wr) {
                                   /* execute-only code segment */
                                   valid = FALSE;
                           }
                           if (!temp_sel.desc.u.seg.c || !temp_sel.desc.u.seg.ec) {
                                   if (CPU_STAT_CPL > temp_sel.desc.dpl) {
                                           valid = FALSE;
                                   }
                           }
   
                           if (!valid) {
                                   /* segment register is invalid */
                                   CPU_REGS_SREG(i) = 0;
                                   CPU_STAT_SREG(i).valid = 0;
                           }
                   }
         }          }
   
         VERBOSE(("RETfar_pm: new EIP = %04x:%08x, ESP = %04x:%08x", CPU_CS, CPU_EIP, CPU_SS, CPU_ESP));          VERBOSE(("RETfar_pm: new EIP = %04x:%08x, ESP = %04x:%08x", CPU_CS, CPU_EIP, CPU_SS, CPU_ESP));
Line 994  RETfar_pm(DWORD nbytes) Line 1034  RETfar_pm(DWORD nbytes)
 /*------------------------------------------------------------------------------  /*------------------------------------------------------------------------------
  * IRET_pm   * IRET_pm
  */   */
   
 #undef  IA32_RETURN_FROM_VM86  
   
 static void IRET_pm_nested_task(void);  static void IRET_pm_nested_task(void);
 static void IRET_pm_return_to_vm86(DWORD new_ip, DWORD new_cs, DWORD new_flags);  static void IRET_pm_return_to_vm86(DWORD new_ip, DWORD new_cs, DWORD new_flags);
 #if defined(IA32_RETURN_FROM_VM86)  
 static void IRET_pm_return_from_vm86(DWORD new_ip, DWORD new_cs, DWORD new_flags);  static void IRET_pm_return_from_vm86(DWORD new_ip, DWORD new_cs, DWORD new_flags);
 #endif  /* IA32_RETURN_FROM_VM86 */  
   
 void  void
 IRET_pm(void)  IRET_pm(void)
 {  {
         selector_t iret_sel, ss_sel;          selector_t iret_sel, ss_sel;
           descriptor_t *dp;
         DWORD sp;          DWORD sp;
         DWORD stacksize;        /* for RETURN-TO-SAME-PRIVILEGE-LEVEL */          DWORD stacksize;        /* for RETURN-TO-SAME-PRIVILEGE-LEVEL */
         DWORD mask = 0;          DWORD mask = 0;
Line 1014  IRET_pm(void) Line 1050  IRET_pm(void)
         WORD new_cs, new_ss;          WORD new_cs, new_ss;
         int old_cpl;          int old_cpl;
         int rv;          int rv;
           int i;
   
         VERBOSE(("IRET_pm: old EIP = %04x:%08x, old ESP = %04x:%08x", CPU_CS, CPU_PREV_EIP, CPU_SS, CPU_ESP));          VERBOSE(("IRET_pm: old EIP = %04x:%08x, old ESP = %04x:%08x", CPU_CS, CPU_PREV_EIP, CPU_SS, CPU_ESP));
   
         if (CPU_EFLAG & NT_FLAG) {          if (!(CPU_EFLAG & VM_FLAG) && (CPU_EFLAG & NT_FLAG)) {
                 /* TASK-RETURN: PE=1, VM=0, NT=1 */                  /* TASK-RETURN: PE=1, VM=0, NT=1 */
                 IRET_pm_nested_task();                  IRET_pm_nested_task();
                 VERBOSE(("IRET_pm: new EIP = %04x:%08x, new ESP = %04x:%08x", CPU_CS, CPU_EIP, CPU_SS, CPU_ESP));                  VERBOSE(("IRET_pm: new EIP = %04x:%08x, new ESP = %04x:%08x", CPU_CS, CPU_EIP, CPU_SS, CPU_ESP));
Line 1043  IRET_pm(void) Line 1080  IRET_pm(void)
         }          }
         VERBOSE(("IRET_pm: new_ip = %08x, new_cs = %04x, new_eflags = %08x", new_ip, new_cs, new_flags));          VERBOSE(("IRET_pm: new_ip = %08x, new_cs = %04x, new_eflags = %08x", new_ip, new_cs, new_flags));
   
 #ifdef  IA32_RETURN_FROM_VM86  
         if (CPU_EFLAG & VM_FLAG) {          if (CPU_EFLAG & VM_FLAG) {
                 /* RETURN-FROM-VIRTUAL-8086-MODE */                  /* RETURN-FROM-VIRTUAL-8086-MODE */
                 IRET_pm_return_from_vm86(new_ip, new_cs, new_flags);                  IRET_pm_return_from_vm86(new_ip, new_cs, new_flags);
Line 1051  IRET_pm(void) Line 1087  IRET_pm(void)
                 CPU_STAT_NERROR = 0;                  CPU_STAT_NERROR = 0;
                 return;                  return;
         }          }
 #endif  /* IA32_RETURN_FROM_VM86 */  
   
         if (new_flags & VM_FLAG) {          if (new_flags & VM_FLAG) {
                 /* RETURN-TO-VIRTUAL-8086-MODE */                  /* RETURN-TO-VIRTUAL-8086-MODE */
Line 1064  IRET_pm(void) Line 1099  IRET_pm(void)
         /* PROTECTED-MODE-RETURN */          /* PROTECTED-MODE-RETURN */
         VERBOSE(("IRET_pm: PE=1, VM=0 in flags image"));          VERBOSE(("IRET_pm: PE=1, VM=0 in flags image"));
   
         rv = parse_selector(&iret_sel, new_cs);          rv = parse_selector(&iret_sel, new_cs, CPU_IS_USER_MODE());
         if (rv < 0) {          if (rv < 0) {
                 VERBOSE(("IRET_pm: parse_selector (selector = %04x, rv = %d)", iret_sel.selector, rv));                  VERBOSE(("IRET_pm: parse_selector (selector = %04x, rv = %d)", iret_sel.selector, rv));
                 EXCEPTION(GP_EXCEPTION, iret_sel.idx);                  EXCEPTION(GP_EXCEPTION, iret_sel.idx);
Line 1110  IRET_pm(void) Line 1145  IRET_pm(void)
                 }                  }
                 VERBOSE(("IRET_pm: new_sp = 0x%08x, new_ss = 0x%04x", new_sp, new_ss));                  VERBOSE(("IRET_pm: new_sp = 0x%08x, new_ss = 0x%04x", new_sp, new_ss));
   
                 rv = parse_selector(&ss_sel, new_ss);                  rv = parse_selector(&ss_sel, new_ss, CPU_IS_USER_MODE());
                 if (rv < 0) {                  if (rv < 0) {
                         VERBOSE(("IRET_pm: parse_selector (selector = %04x, rv = %d)", ss_sel.selector, rv));                          VERBOSE(("IRET_pm: parse_selector (selector = %04x, rv = %d)", ss_sel.selector, rv));
                         EXCEPTION(GP_EXCEPTION, ss_sel.idx);                          EXCEPTION(GP_EXCEPTION, ss_sel.idx);
Line 1189  IRET_pm(void) Line 1224  IRET_pm(void)
   
         if (iret_sel.rpl > old_cpl) {          if (iret_sel.rpl > old_cpl) {
                 /* RETURN-OUTER-PRIVILEGE-LEVEL */                  /* RETURN-OUTER-PRIVILEGE-LEVEL */
   
                 load_ss(ss_sel.selector, &ss_sel.desc, iret_sel.rpl);                  load_ss(ss_sel.selector, &ss_sel.desc, iret_sel.rpl);
                 CPU_ESP = new_sp;                  CPU_ESP = new_sp;
   
                 /* check segment register */                  /* check segment register */
                 check_segreg();                  for (i = 0; i < CPU_SEGREG_NUM; i++) {
                           if ((i != CPU_CS_INDEX) && (i != CPU_SS_INDEX)) {
                                   dp = &CPU_STAT_SREG(i);
                                   if ((!dp->u.seg.c || !dp->u.seg.ec)
                                    && (CPU_STAT_SREG(i).dpl < CPU_STAT_CPL)) {
                                           /* segment register is invalid */
                                           CPU_REGS_SREG(i) = 0;
                                           CPU_STAT_SREG_CLEAR(i);
                                           continue;
                                   }
                           }
                   }
         } else {          } else {
                 /* RETURN-TO-SAME-PRIVILEGE-LEVEL */                  /* RETURN-TO-SAME-PRIVILEGE-LEVEL */
                 if (CPU_STAT_SS32) {                  if (CPU_STAT_SS32) {
Line 1219  IRET_pm_nested_task(void) Line 1266  IRET_pm_nested_task(void)
   
         VERBOSE(("IRET_pm: TASK-RETURN: PE=1, VM=0, NT=1"));          VERBOSE(("IRET_pm: TASK-RETURN: PE=1, VM=0, NT=1"));
   
         if (CPU_STAT_VM86) {  
                 ia32_panic("IRET_pm: VM86");  
         }  
   
         new_cs = get_link_selector_from_tss();          new_cs = get_link_selector_from_tss();
         rv = parse_selector(&iret_sel, new_cs);          rv = parse_selector(&iret_sel, new_cs, CPU_IS_USER_MODE());
         if (rv < 0 || iret_sel.ldt) {          if (rv < 0 || iret_sel.ldt) {
                 VERBOSE(("IRET_pm: parse_selector (selector = %04x, rv = %d)", iret_sel.selector, rv));                  VERBOSE(("IRET_pm: parse_selector (selector = %04x, rv = %d)", iret_sel.selector, rv));
                 EXCEPTION(GP_EXCEPTION, iret_sel.idx);                  EXCEPTION(GP_EXCEPTION, iret_sel.idx);
Line 1305  IRET_pm_return_to_vm86(DWORD new_ip, DWO Line 1348  IRET_pm_return_to_vm86(DWORD new_ip, DWO
         SET_EIP(new_ip);          SET_EIP(new_ip);
 }  }
   
 #ifdef  IA32_RETURN_FROM_VM86  
 /*---  /*---
  * IRET_pm: VM_FLAG   * IRET_pm: VM_FLAG
  */   */
Line 1338  IRET_pm_return_from_vm86(DWORD new_ip, D Line 1380  IRET_pm_return_from_vm86(DWORD new_ip, D
         VERBOSE(("IRET_pm: trap to virtual-8086 monitor: VM=1, IOPL<3"));          VERBOSE(("IRET_pm: trap to virtual-8086 monitor: VM=1, IOPL<3"));
         EXCEPTION(GP_EXCEPTION, 0);          EXCEPTION(GP_EXCEPTION, 0);
 }  }
 #endif  /* IA32_RETURN_FROM_VM86 */  
   
   
 /*-----  
  * Misc.  
  */  
 static void  
 check_segreg(void)  
 {  
         selector_t temp_sel;  
         BOOL valid;  
         int rv;  
         int i;  
   
         /* check segment register */  
         for (i = 0; i < CPU_SEGREG_NUM; i++) {  
                 if (i == CPU_CS_INDEX || i == CPU_SS_INDEX)  
                         continue;  
   
                 rv = parse_selector(&temp_sel, CPU_REGS_SREG(i));  
                 if (rv < 0) {  
                         /* segment register is invalid */  
                         CPU_REGS_SREG(i) = 0;  
                         CPU_STAT_SREG(i).valid = 0;  
                         continue;  
                 }  
   
                 valid = TRUE;  
                 if (!temp_sel.desc.s) {  
                         /* system segment */  
                         valid = FALSE;  
                 }  
                 if (temp_sel.desc.u.seg.c && !temp_sel.desc.u.seg.wr) {  
                         /* execute-only code segment */  
                         valid = FALSE;  
                 }  
                 if (!temp_sel.desc.u.seg.c || !temp_sel.desc.u.seg.ec) {  
                         if (CPU_STAT_CPL > temp_sel.desc.dpl) {  
                                 valid = FALSE;  
                         }  
                 }  
   
                 if (!valid) {  
                         /* segment register is invalid */  
                         CPU_REGS_SREG(i) = 0;  
                         CPU_STAT_SREG(i).valid = 0;  
                 }  
         }  
 }  

Removed from v.1.4  
changed lines
  Added in v.1.7


RetroPC.NET-CVS <cvs@retropc.net>