Diff for /np2/i386c/ia32/ctrlxfer.c between versions 1.5 and 1.9

version 1.5, 2004/01/27 15:55:49 version 1.9, 2004/02/06 16:49:51
Line 98  JMPfar_pm(WORD selector, DWORD new_ip) Line 98  JMPfar_pm(WORD selector, DWORD new_ip)
                         break;                          break;
                 }                  }
         }          }
   
         VERBOSE(("JMPfar_pm: new EIP = %04x:%08x, ESP = %04x:%08x", CPU_CS, CPU_EIP, CPU_SS, CPU_ESP));          VERBOSE(("JMPfar_pm: new EIP = %04x:%08x, ESP = %04x:%08x", CPU_CS, CPU_EIP, CPU_SS, CPU_ESP));
 }  }
   
Line 152  static void Line 153  static void
 JMPfar_pm_call_gate(selector_t *callgate_sel)  JMPfar_pm_call_gate(selector_t *callgate_sel)
 {  {
         selector_t cs_sel;          selector_t cs_sel;
           DWORD new_ip;
         int rv;          int rv;
   
         VERBOSE(("JMPfar_pm: CALL-GATE"));          VERBOSE(("JMPfar_pm: CALL-GATE"));
Line 215  JMPfar_pm_call_gate(selector_t *callgate Line 217  JMPfar_pm_call_gate(selector_t *callgate
         }          }
   
         /* out of range */          /* out of range */
         if (callgate_sel->desc.u.gate.offset > cs_sel.desc.u.seg.limit) {          new_ip = callgate_sel->desc.u.gate.offset;
                 VERBOSE(("JMPfar_pm: new_ip is out of range. new_ip = %08x, limit = %08x", callgate_sel->desc.u.gate.offset, cs_sel.desc.u.seg.limit));          if (new_ip > cs_sel.desc.u.seg.limit) {
                   VERBOSE(("JMPfar_pm: new_ip is out of range. new_ip = %08x, limit = %08x", new_ip, cs_sel.desc.u.seg.limit));
                 EXCEPTION(GP_EXCEPTION, 0);                  EXCEPTION(GP_EXCEPTION, 0);
         }          }
   
         load_cs(cs_sel.selector, &cs_sel.desc, CPU_STAT_CPL);          load_cs(cs_sel.selector, &cs_sel.desc, CPU_STAT_CPL);
         SET_EIP(callgate_sel->desc.u.gate.offset);          SET_EIP(new_ip);
 }  }
   
 /*---  /*---
Line 560  static void Line 563  static void
 CALLfar_pm_call_gate_same_privilege(selector_t *callgate_sel, selector_t *cs_sel)  CALLfar_pm_call_gate_same_privilege(selector_t *callgate_sel, selector_t *cs_sel)
 {  {
         DWORD sp;          DWORD sp;
         DWORD old_eip;          DWORD new_ip;
         WORD old_cs;  
   
         VERBOSE(("CALLfar_pm: SAME-PRIVILEGE"));          VERBOSE(("CALLfar_pm: SAME-PRIVILEGE"));
   
         /* save register */  
         old_cs = CPU_CS;  
         old_eip = CPU_EIP;  
   
         if (CPU_STAT_SS32) {          if (CPU_STAT_SS32) {
                 sp = CPU_ESP;                  sp = CPU_ESP;
         } else {          } else {
                 sp = CPU_SP;                  sp = CPU_SP;
         }          }
           new_ip = callgate_sel->desc.u.gate.offset;
   
         if (callgate_sel->desc.type == CPU_SYSDESC_TYPE_CALL_32) {          if (callgate_sel->desc.type == CPU_SYSDESC_TYPE_CALL_32) {
                 CHECK_STACK_PUSH(&CPU_STAT_SREG(CPU_SS_INDEX), sp, 8);                  CHECK_STACK_PUSH(&CPU_STAT_SREG(CPU_SS_INDEX), sp, 8);
   
                 load_cs(cs_sel->selector, &cs_sel->desc, CPU_STAT_CPL);                  PUSH0_32(CPU_CS);
                 SET_EIP(callgate_sel->desc.u.gate.offset);                  PUSH0_32(CPU_EIP);
   
                 PUSH0_32(old_cs);                  load_cs(cs_sel->selector, &cs_sel->desc, CPU_STAT_CPL);
                 PUSH0_32(old_eip);                  SET_EIP(new_ip);
         } else {          } else {
                 CHECK_STACK_PUSH(&CPU_STAT_SREG(CPU_SS_INDEX), sp, 4);                  CHECK_STACK_PUSH(&CPU_STAT_SREG(CPU_SS_INDEX), sp, 4);
   
                 load_cs(cs_sel->selector, &cs_sel->desc, CPU_STAT_CPL);                  PUSH0_16(CPU_CS);
                 SET_EIP(callgate_sel->desc.u.gate.offset);                  PUSH0_16(CPU_IP);
   
                 PUSH0_16(old_cs);                  load_cs(cs_sel->selector, &cs_sel->desc, CPU_STAT_CPL);
                 PUSH0_16(old_eip);                  SET_EIP(new_ip);
         }          }
 }  }
   
Line 604  CALLfar_pm_call_gate_more_privilege(sele Line 603  CALLfar_pm_call_gate_more_privilege(sele
         selector_t ss_sel;          selector_t ss_sel;
         DWORD sp;          DWORD sp;
         DWORD old_eip, old_esp;          DWORD old_eip, old_esp;
         DWORD tss_esp;          DWORD new_esp;
         WORD old_cs, old_ss;          WORD old_cs, old_ss;
         WORD tss_ss;          WORD new_ss;
         int param_count;          int param_count;
         int i;          int i;
         int rv;          int rv;
Line 626  CALLfar_pm_call_gate_more_privilege(sele Line 625  CALLfar_pm_call_gate_more_privilege(sele
         }          }
   
         /* get stack pointer from TSS */          /* get stack pointer from TSS */
         get_stack_from_tss(cs_sel->desc.dpl, &tss_ss, &tss_esp);          get_stack_from_tss(cs_sel->desc.dpl, &new_ss, &new_esp);
   
         /* parse stack segment descriptor */          /* parse stack segment descriptor */
         rv = parse_selector(&ss_sel, tss_ss);          rv = parse_selector(&ss_sel, new_ss);
         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)", new_ss, rv));
                 EXCEPTION(TS_EXCEPTION, ss_sel.idx);                  EXCEPTION(TS_EXCEPTION, ss_sel.idx);
         }          }
   
Line 669  CALLfar_pm_call_gate_more_privilege(sele Line 668  CALLfar_pm_call_gate_more_privilege(sele
         VERBOSE(("CALLfar_pm: param_count = %d", param_count));          VERBOSE(("CALLfar_pm: param_count = %d", param_count));
   
         if (callgate_sel->desc.type == CPU_SYSDESC_TYPE_CALL_32) {          if (callgate_sel->desc.type == CPU_SYSDESC_TYPE_CALL_32) {
                 CHECK_STACK_PUSH(&ss_sel.desc, tss_esp, 16 + param_count * 4);                  CHECK_STACK_PUSH(&ss_sel.desc, new_esp, 16 + param_count * 4);
   
                 /* dump param */                  /* dump param */
                 for (i = 0; i < param_count; i++) {                  for (i = 0; i < param_count; i++) {
Line 678  CALLfar_pm_call_gate_more_privilege(sele Line 677  CALLfar_pm_call_gate_more_privilege(sele
                 }                  }
   
                 load_ss(ss_sel.selector, &ss_sel.desc, ss_sel.desc.dpl);                  load_ss(ss_sel.selector, &ss_sel.desc, ss_sel.desc.dpl);
                 CPU_ESP = tss_esp;                  if (CPU_STAT_SS32) {
                           CPU_ESP = new_esp;
                   } else {
                           CPU_SP = new_esp;
                   }
   
                 load_cs(cs_sel->selector, &cs_sel->desc, cs_sel->desc.dpl);                  load_cs(cs_sel->selector, &cs_sel->desc, cs_sel->desc.dpl);
                 SET_EIP(callgate_sel->desc.u.gate.offset);                  SET_EIP(callgate_sel->desc.u.gate.offset);
Line 695  CALLfar_pm_call_gate_more_privilege(sele Line 698  CALLfar_pm_call_gate_more_privilege(sele
                 PUSH0_32(old_cs);                  PUSH0_32(old_cs);
                 PUSH0_32(old_eip);                  PUSH0_32(old_eip);
         } else {          } else {
                 CHECK_STACK_PUSH(&ss_sel.desc, tss_esp, 8 + param_count * 2);                  CHECK_STACK_PUSH(&ss_sel.desc, new_esp, 8 + param_count * 2);
   
                 /* dump param */                  /* dump param */
                 for (i = 0; i < param_count; i++) {                  for (i = 0; i < param_count; i++) {
Line 704  CALLfar_pm_call_gate_more_privilege(sele Line 707  CALLfar_pm_call_gate_more_privilege(sele
                 }                  }
   
                 load_ss(ss_sel.selector, &ss_sel.desc, ss_sel.desc.dpl);                  load_ss(ss_sel.selector, &ss_sel.desc, ss_sel.desc.dpl);
                 CPU_ESP = tss_esp;                  if (CPU_STAT_SS32) {
                           CPU_ESP = new_esp;
                   } else {
                           CPU_SP = new_esp;
                   }
   
                 load_cs(cs_sel->selector, &cs_sel->desc, cs_sel->desc.dpl);                  load_cs(cs_sel->selector, &cs_sel->desc, cs_sel->desc.dpl);
                 SET_EIP(callgate_sel->desc.u.gate.offset);                  SET_EIP(callgate_sel->desc.u.gate.offset);
Line 753  CALLfar_pm_task_gate(selector_t *taskgat Line 760  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);
         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, %cDT)", tss_sel.selector, rv, tss_sel.ldt ? 'L' : 'G'));
                 EXCEPTION(GP_EXCEPTION, tss_sel.idx);                  EXCEPTION(GP_EXCEPTION, tss_sel.idx);
         }          }
   
Line 855  RETfar_pm(DWORD nbytes) Line 862  RETfar_pm(DWORD nbytes)
         if (CPU_INST_OP32) {          if (CPU_INST_OP32) {
                 CHECK_STACK_POP(&CPU_STAT_SREG(CPU_SS_INDEX), sp, nbytes + 8);                  CHECK_STACK_POP(&CPU_STAT_SREG(CPU_SS_INDEX), sp, nbytes + 8);
                 new_ip = cpu_vmemoryread_d(CPU_SS_INDEX, sp);                  new_ip = cpu_vmemoryread_d(CPU_SS_INDEX, sp);
                 new_cs = cpu_vmemoryread_d(CPU_SS_INDEX, sp + 4);                  new_cs = cpu_vmemoryread_w(CPU_SS_INDEX, sp + 4);
         } else {          } else {
                 CHECK_STACK_POP(&CPU_STAT_SREG(CPU_SS_INDEX), sp, nbytes + 4);                  CHECK_STACK_POP(&CPU_STAT_SREG(CPU_SS_INDEX), sp, nbytes + 4);
                 new_ip = cpu_vmemoryread_w(CPU_SS_INDEX, sp);                  new_ip = cpu_vmemoryread_w(CPU_SS_INDEX, sp);
Line 980  RETfar_pm(DWORD nbytes) Line 987  RETfar_pm(DWORD nbytes)
                 SET_EIP(new_ip);                  SET_EIP(new_ip);
   
                 load_ss(ss_sel.selector, &ss_sel.desc, ret_sel.rpl);                  load_ss(ss_sel.selector, &ss_sel.desc, ret_sel.rpl);
                 CPU_ESP = new_sp + nbytes;                  if (CPU_STAT_SS32) {
                           CPU_ESP = new_sp + nbytes;
                   } else {
                           CPU_SP = new_sp + nbytes;
                   }
   
                 /* check segment register */                  /* check segment register */
                 for (i = 0; i < CPU_SEGREG_NUM; i++) {                  for (i = 0; i < CPU_SEGREG_NUM; i++) {
Line 1034  RETfar_pm(DWORD nbytes) Line 1045  RETfar_pm(DWORD nbytes)
 /*------------------------------------------------------------------------------  /*------------------------------------------------------------------------------
  * IRET_pm   * IRET_pm
  */   */
   
 #define 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 cs_sel, ss_sel;
         descriptor_t *dp;          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;
         DWORD new_ip, new_sp, new_flags;          DWORD new_ip, new_sp, new_flags;
         WORD new_cs, new_ss;          WORD new_cs, new_ss;
         int old_cpl;          int op32;
         int rv;          int rv;
         int i;          int i;
   
Line 1083  IRET_pm(void) Line 1089  IRET_pm(void)
                 new_cs = cpu_vmemoryread_w(CPU_SS_INDEX, sp + 2);                  new_cs = cpu_vmemoryread_w(CPU_SS_INDEX, sp + 2);
                 new_flags = cpu_vmemoryread_w(CPU_SS_INDEX, sp + 4);                  new_flags = cpu_vmemoryread_w(CPU_SS_INDEX, sp + 4);
         }          }
           op32 = CPU_INST_OP32;
   
         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 1093  IRET_pm(void) Line 1100  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 1106  IRET_pm(void) Line 1112  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(&cs_sel, new_cs);
         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)", cs_sel.selector, rv));
                 EXCEPTION(GP_EXCEPTION, iret_sel.idx);                  EXCEPTION(GP_EXCEPTION, cs_sel.idx);
         }          }
   
         /* check code segment descriptor */          /* check code segment descriptor */
         if (!iret_sel.desc.s) {          if (!cs_sel.desc.s) {
                 VERBOSE(("IRET_pm: return code segment is system segment"));                  VERBOSE(("IRET_pm: return code segment is system segment"));
                 EXCEPTION(GP_EXCEPTION, iret_sel.idx);                  EXCEPTION(GP_EXCEPTION, cs_sel.idx);
         }          }
         if (!iret_sel.desc.u.seg.c) {          if (!cs_sel.desc.u.seg.c) {
                 VERBOSE(("IRET_pm: return code segment is data segment"));                  VERBOSE(("IRET_pm: return code segment is data segment"));
                 EXCEPTION(GP_EXCEPTION, iret_sel.idx);                  EXCEPTION(GP_EXCEPTION, cs_sel.idx);
         }          }
   
         /* check privilege level */          /* check privilege level */
         if (iret_sel.rpl < CPU_STAT_CPL) {          if (cs_sel.rpl < CPU_STAT_CPL) {
                 VERBOSE(("IRET_pm: RPL(%d) < CPL(%d)", iret_sel.rpl, CPU_STAT_CPL));                  VERBOSE(("IRET_pm: RPL(%d) < CPL(%d)", cs_sel.rpl, CPU_STAT_CPL));
                 EXCEPTION(GP_EXCEPTION, iret_sel.idx);                  EXCEPTION(GP_EXCEPTION, cs_sel.idx);
         }          }
         if (iret_sel.desc.u.seg.ec && (iret_sel.desc.dpl > iret_sel.rpl)) {          if (cs_sel.desc.u.seg.ec && (cs_sel.desc.dpl > cs_sel.rpl)) {
                 VERBOSE(("IRET_pm: CONFORMING-CODE-SEGMENT and DPL(%d) != RPL(%d)", iret_sel.desc.dpl, iret_sel.rpl));                  VERBOSE(("IRET_pm: CONFORMING-CODE-SEGMENT and DPL(%d) != RPL(%d)", cs_sel.desc.dpl, cs_sel.rpl));
                 EXCEPTION(GP_EXCEPTION, iret_sel.idx);                  EXCEPTION(GP_EXCEPTION, cs_sel.idx);
         }          }
   
         /* not present */          /* not present */
         if (selector_is_not_present(&iret_sel)) {          if (selector_is_not_present(&cs_sel)) {
                 VERBOSE(("IRET_pm: code segment is not present"));                  VERBOSE(("IRET_pm: code segment is not present"));
                 EXCEPTION(NP_EXCEPTION, iret_sel.idx);                  EXCEPTION(NP_EXCEPTION, cs_sel.idx);
         }          }
   
         if (iret_sel.rpl > CPU_STAT_CPL) {          if (cs_sel.rpl > CPU_STAT_CPL) {
                 VERBOSE(("IRET_pm: RETURN-OUTER-PRIVILEGE-LEVEL"));                  VERBOSE(("IRET_pm: RETURN-OUTER-PRIVILEGE-LEVEL"));
   
                 if (CPU_INST_OP32) {                  if (CPU_INST_OP32) {
Line 1159  IRET_pm(void) Line 1165  IRET_pm(void)
                 }                  }
   
                 /* check privilege level */                  /* check privilege level */
                 if (ss_sel.rpl != iret_sel.rpl) {                  if (ss_sel.rpl != cs_sel.rpl) {
                         VERBOSE(("IRET_pm: RPL[SS](%d) != RPL[CS](%d)", ss_sel.rpl, iret_sel.rpl));                          VERBOSE(("IRET_pm: RPL[SS](%d) != RPL[CS](%d)", ss_sel.rpl, cs_sel.rpl));
                         EXCEPTION(GP_EXCEPTION, ss_sel.idx);                          EXCEPTION(GP_EXCEPTION, ss_sel.idx);
                 }                  }
                 if (ss_sel.desc.dpl != iret_sel.rpl) {                  if (ss_sel.desc.dpl != cs_sel.rpl) {
                         VERBOSE(("IRET_pm: DPL[SS](%d) != RPL[CS](%d)", ss_sel.desc.dpl, iret_sel.rpl));                          VERBOSE(("IRET_pm: DPL[SS](%d) != RPL[CS](%d)", ss_sel.desc.dpl, cs_sel.rpl));
                         EXCEPTION(GP_EXCEPTION, ss_sel.idx);                          EXCEPTION(GP_EXCEPTION, ss_sel.idx);
                 }                  }
   
Line 1188  IRET_pm(void) Line 1194  IRET_pm(void)
                         EXCEPTION(SS_EXCEPTION, ss_sel.idx);                          EXCEPTION(SS_EXCEPTION, ss_sel.idx);
                 }                  }
   
                 /* compiler happy :-) */                  /* check code segment limit */
                 stacksize = 0;                  if (new_ip > cs_sel.desc.u.seg.limit) {
         } else {                          VERBOSE(("IRET_pm: new_ip is out of range. new_ip = %08x, limit = %08x", new_ip, cs_sel.desc.u.seg.limit));
                 VERBOSE(("IRET_pm: RETURN-TO-SAME-PRIVILEGE-LEVEL"));                          EXCEPTION(GP_EXCEPTION, 0);
   
                 if (CPU_INST_OP32) {  
                         stacksize = 12;  
                 } else {  
                         stacksize = 6;  
                 }                  }
   
                 /* compiler happy :-) */                  mask = 0;
                 new_sp = 0;                  if (CPU_INST_OP32)
                 new_ss = 0;                          mask |= RF_FLAG;
         }                  if (CPU_STAT_CPL <= CPU_STAT_IOPL)
                           mask |= I_FLAG;
         /* check code segment limit */                  if (CPU_STAT_CPL == 0) {
         if (new_ip > iret_sel.desc.u.seg.limit) {                          mask |= IOPL_FLAG;
                 VERBOSE(("IRET_pm: new_ip is out of range. new_ip = %08x, limit = %08x", new_ip, iret_sel.desc.u.seg.limit));                          if (CPU_INST_OP32) {
                 EXCEPTION(GP_EXCEPTION, 0);                                  mask |= VM_FLAG|VIF_FLAG|VIP_FLAG;
         }                          }
                   }
   
         /* set new register */                  /* set new register */
         old_cpl = CPU_STAT_CPL;                  load_cs(cs_sel.selector, &cs_sel.desc, cs_sel.rpl);
         load_cs(iret_sel.selector, &iret_sel.desc, iret_sel.rpl);                  SET_EIP(new_ip);
         SET_EIP(new_ip);  
   
         /* set new eflags */                  if (op32) {
         mask = 0;                          set_eflags(new_flags, mask);
         if (CPU_INST_OP32)                  } else {
                 mask |= RF_FLAG;                          set_flags(new_flags, mask);
         if (CPU_STAT_CPL <= CPU_STAT_IOPL)  
                 mask |= I_FLAG;  
         if (CPU_STAT_CPL == 0) {  
                 mask |= IOPL_FLAG;  
                 if (CPU_INST_OP32) {  
                         mask |= VM_FLAG|VIF_FLAG|VIP_FLAG;  
                 }                  }
         }  
         set_eflags(new_flags, mask);  
   
         if (iret_sel.rpl > old_cpl) {                  load_ss(ss_sel.selector, &ss_sel.desc, cs_sel.rpl);
                 /* RETURN-OUTER-PRIVILEGE-LEVEL */                  if (CPU_STAT_SS32) {
                           CPU_ESP = new_sp;
                 load_ss(ss_sel.selector, &ss_sel.desc, iret_sel.rpl);                  } else {
                 CPU_ESP = new_sp;                          CPU_SP = new_sp;
                   }
   
                 /* check segment register */                  /* check segment register */
                 for (i = 0; i < CPU_SEGREG_NUM; i++) {                  for (i = 0; i < CPU_SEGREG_NUM; i++) {
Line 1249  IRET_pm(void) Line 1243  IRET_pm(void)
                         }                          }
                 }                  }
         } else {          } else {
                 /* RETURN-TO-SAME-PRIVILEGE-LEVEL */                  VERBOSE(("IRET_pm: RETURN-TO-SAME-PRIVILEGE-LEVEL"));
   
                   /* check code segment limit */
                   if (new_ip > cs_sel.desc.u.seg.limit) {
                           VERBOSE(("IRET_pm: new_ip is out of range. new_ip = %08x, limit = %08x", new_ip, cs_sel.desc.u.seg.limit));
                           EXCEPTION(GP_EXCEPTION, 0);
                   }
   
                   mask = 0;
                   if (CPU_INST_OP32)
                           mask |= RF_FLAG;
                   if (CPU_STAT_CPL <= CPU_STAT_IOPL)
                           mask |= I_FLAG;
                   if (CPU_STAT_CPL == 0) {
                           mask |= IOPL_FLAG;
                           if (CPU_INST_OP32) {
                                   mask |= VM_FLAG|VIF_FLAG|VIP_FLAG;
                           }
                   }
   
                   /* set new register */
                   load_cs(cs_sel.selector, &cs_sel.desc, CPU_STAT_CPL);
                   SET_EIP(new_ip);
   
                   if (op32) {
                           set_eflags(new_flags, mask);
                   } else {
                           set_flags(new_flags, mask);
                   }
   
                   if (CPU_INST_OP32) {
                           stacksize = 12;
                   } else {
                           stacksize = 6;
                   }
                 if (CPU_STAT_SS32) {                  if (CPU_STAT_SS32) {
                         CPU_ESP += stacksize;                          CPU_ESP += stacksize;
                 } else {                  } else {
Line 1267  IRET_pm(void) Line 1295  IRET_pm(void)
 static void  static void
 IRET_pm_nested_task(void)  IRET_pm_nested_task(void)
 {  {
         selector_t iret_sel;          selector_t tss_sel;
         int rv;          int rv;
         WORD new_cs;          WORD new_tss;
   
         VERBOSE(("IRET_pm: TASK-RETURN: PE=1, VM=0, NT=1"));          VERBOSE(("IRET_pm: TASK-RETURN: PE=1, VM=0, NT=1"));
   
         new_cs = get_link_selector_from_tss();          new_tss = get_link_selector_from_tss();
         rv = parse_selector(&iret_sel, new_cs);  
         if (rv < 0 || iret_sel.ldt) {          rv = parse_selector(&tss_sel, new_tss);
                 VERBOSE(("IRET_pm: parse_selector (selector = %04x, rv = %d)", iret_sel.selector, rv));          if (rv < 0 || tss_sel.ldt) {
                 EXCEPTION(GP_EXCEPTION, iret_sel.idx);                  VERBOSE(("IRET_pm: parse_selector (selector = %04x, rv = %d, %cDT)", tss_sel.selector, rv, tss_sel.ldt ? 'L' : 'G'));
                   EXCEPTION(GP_EXCEPTION, tss_sel.idx);
         }          }
   
         /* check system segment */          /* check system segment */
         if (iret_sel.desc.s) {          if (tss_sel.desc.s) {
                 VERBOSE(("IRET_pm: task segment is %d segment", iret_sel.desc.u.seg.c ? "code" : "data"));                  VERBOSE(("IRET_pm: task segment is %d segment", tss_sel.desc.u.seg.c ? "code" : "data"));
                 EXCEPTION(GP_EXCEPTION, iret_sel.idx);                  EXCEPTION(GP_EXCEPTION, tss_sel.idx);
         }          }
   
         switch (iret_sel.desc.type) {          switch (tss_sel.desc.type) {
         case CPU_SYSDESC_TYPE_TSS_BUSY_16:          case CPU_SYSDESC_TYPE_TSS_BUSY_16:
         case CPU_SYSDESC_TYPE_TSS_BUSY_32:          case CPU_SYSDESC_TYPE_TSS_BUSY_32:
                 break;                  break;
Line 1296  IRET_pm_nested_task(void) Line 1325  IRET_pm_nested_task(void)
                 VERBOSE(("IRET_pm: task is not busy"));                  VERBOSE(("IRET_pm: task is not busy"));
                 /*FALLTHROUGH*/                  /*FALLTHROUGH*/
         default:          default:
                 VERBOSE(("IRET_pm: invalid descriptor type (type = %d)", iret_sel.desc.type));                  VERBOSE(("IRET_pm: invalid descriptor type (type = %d)", tss_sel.desc.type));
                 EXCEPTION(GP_EXCEPTION, iret_sel.idx);                  EXCEPTION(GP_EXCEPTION, tss_sel.idx);
                 break;                  break;
         }          }
   
         /* not present */          /* not present */
         if (selector_is_not_present(&iret_sel)) {          if (selector_is_not_present(&tss_sel)) {
                 VERBOSE(("IRET_pm: tss segment is not present"));                  VERBOSE(("IRET_pm: tss segment is not present"));
                 EXCEPTION(NP_EXCEPTION, iret_sel.idx);                  EXCEPTION(NP_EXCEPTION, tss_sel.idx);
         }          }
   
         task_switch(&iret_sel, TASK_SWITCH_IRET);          task_switch(&tss_sel, TASK_SWITCH_IRET);
 }  }
   
 /*---  /*---
Line 1327  IRET_pm_return_to_vm86(DWORD new_ip, DWO Line 1356  IRET_pm_return_to_vm86(DWORD new_ip, DWO
                 ia32_panic("IRET_pm: CPL != 0");                  ia32_panic("IRET_pm: CPL != 0");
         }          }
   
           if (!CPU_INST_OP32) {
                   ia32_panic("IRET_pm: 16bit mode");
           }
   
         if (CPU_STAT_SS32) {          if (CPU_STAT_SS32) {
                 sp = CPU_ESP;                  sp = CPU_ESP;
         } else {          } else {
                 sp = CPU_SP;                  sp = CPU_SP;
         }          }
         if (!CPU_INST_OP32) {  
                 ia32_panic("IRET_pm: 16bit mode");  
         }  
   
         CHECK_STACK_POP(&CPU_STAT_SREG(CPU_SS_INDEX), sp, 36);          CHECK_STACK_POP(&CPU_STAT_SREG(CPU_SS_INDEX), sp, 36);
         new_sp = cpu_vmemoryread_d(CPU_SS_INDEX, sp + 12);          new_sp = cpu_vmemoryread_d(CPU_SS_INDEX, sp + 12);
         segsel[CPU_SS_INDEX] = cpu_vmemoryread_w(CPU_SS_INDEX, sp + 16);          segsel[CPU_SS_INDEX] = cpu_vmemoryread_w(CPU_SS_INDEX, sp + 16);
Line 1347  IRET_pm_return_to_vm86(DWORD new_ip, DWO Line 1376  IRET_pm_return_to_vm86(DWORD new_ip, DWO
   
         for (i = 0; i < CPU_SEGREG_NUM; i++) {          for (i = 0; i < CPU_SEGREG_NUM; i++) {
                 CPU_REGS_SREG(i) = segsel[i];                  CPU_REGS_SREG(i) = segsel[i];
                   CPU_STAT_SREG_INIT(i);
         }          }
   
           /* to VM86 mode */
         set_eflags(new_flags, IOPL_FLAG|I_FLAG|VM_FLAG|RF_FLAG);          set_eflags(new_flags, IOPL_FLAG|I_FLAG|VM_FLAG|RF_FLAG);
   
         CPU_ESP = new_sp;          CPU_ESP = new_sp;
           new_ip &= 0xffff;
         SET_EIP(new_ip);          SET_EIP(new_ip);
 }  }
   
 #ifdef  IA32_RETURN_FROM_VM86  
 /*---  /*---
  * IRET_pm: VM_FLAG   * IRET_pm: VM_FLAG
  */   */
Line 1379  IRET_pm_return_from_vm86(DWORD new_ip, D Line 1410  IRET_pm_return_from_vm86(DWORD new_ip, D
                         CPU_SP += stacksize;                          CPU_SP += stacksize;
                 }                  }
   
                 set_eflags(new_flags, I_FLAG|RF_FLAG);                  if (CPU_INST_OP32) {
                           set_eflags(new_flags, I_FLAG|RF_FLAG);
                   } else {
                           set_flags(new_flags, I_FLAG|RF_FLAG);
                   }
   
                 CPU_SET_SEGREG(CPU_CS_INDEX, new_cs);                  CPU_SET_SEGREG(CPU_CS_INDEX, new_cs);
                 SET_EIP(new_ip);                  SET_EIP(new_ip);
Line 1388  IRET_pm_return_from_vm86(DWORD new_ip, D Line 1423  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 */  

Removed from v.1.5  
changed lines
  Added in v.1.9


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