Diff for /np2/i386c/ia32/exception.c between versions 1.7 and 1.17

version 1.7, 2004/02/04 13:24:35 version 1.17, 2004/03/23 22:39:40
Line 72  exception(int num, int error_code) Line 72  exception(int num, int error_code)
   
         __ASSERT((unsigned int)num < EXCEPTION_NUM);          __ASSERT((unsigned int)num < EXCEPTION_NUM);
   
           VERBOSE(("exception: -------------------------------------------------------------- start"));
         VERBOSE(("exception: %s, error_code = %x at %04x:%08x", exception_str[num], error_code, CPU_CS, CPU_PREV_EIP));          VERBOSE(("exception: %s, error_code = %x at %04x:%08x", exception_str[num], error_code, CPU_CS, CPU_PREV_EIP));
         VERBOSE(("exception:------------------------------------------------"));  
         VERBOSE(("%s", cpu_reg2str()));          VERBOSE(("%s", cpu_reg2str()));
         VERBOSE(("exception:------------------------------------------------"));  
   
         CPU_STAT_NERROR++;          CPU_STAT_EXCEPTION_COUNTER_INC();
         if ((CPU_STAT_NERROR >= 3)           if ((CPU_STAT_EXCEPTION_COUNTER >= 3) 
          || (CPU_STAT_NERROR == 2 && CPU_STAT_PREV_EXCEPTION == DF_EXCEPTION)) {           || (CPU_STAT_EXCEPTION_COUNTER == 2 && CPU_STAT_PREV_EXCEPTION == DF_EXCEPTION)) {
                 /* Triple fault */                  /* Triple fault */
                 ia32_panic("exception: catch triple fault!");                  ia32_panic("exception: catch triple fault!");
         }          }
   
         switch (num) {          switch (num) {
         case DE_EXCEPTION:      /* (F) 除算エラー */          case DE_EXCEPTION:      /* (F) 除算エラー */
           case DB_EXCEPTION:      /* (F/T) デバッグ */
         case BR_EXCEPTION:      /* (F) BOUND の範囲外 */          case BR_EXCEPTION:      /* (F) BOUND の範囲外 */
         case UD_EXCEPTION:      /* (F) 無効オペコード */          case UD_EXCEPTION:      /* (F) 無効オペコード */
         case NM_EXCEPTION:      /* (F) デバイス使用不可 (FPU が無い) */          case NM_EXCEPTION:      /* (F) デバイス使用不可 (FPU が無い) */
           case MF_EXCEPTION:      /* (F) 浮動小数点エラー */
   #if CPU_FAMILY >= 5
           case MC_EXCEPTION:      /* (A) マシンチェック */
   #endif
   #if CPU_FAMILY >= 6
           case XF_EXCEPTION:      /* (F) ストリーミング SIMD 拡張命令 */
   #endif
                 CPU_EIP = CPU_PREV_EIP;                  CPU_EIP = CPU_PREV_EIP;
                 /*FALLTHROUGH*/                  /*FALLTHROUGH*/
         case DB_EXCEPTION:      /* (F/T) デバッグ */  
         case NMI_EXCEPTION:     /* (I) NMI 割り込み */          case NMI_EXCEPTION:     /* (I) NMI 割り込み */
         case BP_EXCEPTION:      /* (T) ブレークポイント */          case BP_EXCEPTION:      /* (T) ブレークポイント */
         case OF_EXCEPTION:      /* (T) オーバーフロー */          case OF_EXCEPTION:      /* (T) オーバーフロー */
Line 117  exception(int num, int error_code) Line 123  exception(int num, int error_code)
                 errorp = 1;                  errorp = 1;
                 break;                  break;
   
         case MF_EXCEPTION:      /* (F) 浮動小数点エラー */  
                 CPU_EIP = CPU_PREV_EIP;  
                 errorp = 0;  
                 break;  
   
 #if CPU_FAMILY >= 5  
         case MC_EXCEPTION:      /* (A) マシンチェック */  
                 CPU_EIP = CPU_PREV_EIP;  
                 errorp = 0;  
                 break;  
 #endif  
   
 #if CPU_FAMILY >= 6  
         case XF_EXCEPTION:      /* (F) ストリーミング SIMD 拡張命令 */  
                 CPU_EIP = CPU_PREV_EIP;  
                 errorp = 0;  
                 break;  
 #endif  
   
         default:          default:
                 ia32_panic("exception: unknown exception (%d)", num);                  ia32_panic("exception: unknown exception (%d)", num);
                 break;                  break;
         }          }
   
         if (CPU_STAT_NERROR >= 2) {          if (CPU_STAT_EXCEPTION_COUNTER >= 2) {
                 if (dftable[exctype[CPU_STAT_PREV_EXCEPTION]][exctype[num]]) {                  if (dftable[exctype[CPU_STAT_PREV_EXCEPTION]][exctype[num]]) {
                         num = DF_EXCEPTION;                          num = DF_EXCEPTION;
                           errorp = 1;
                           error_code = 0;
                 }                  }
         }          }
         CPU_STAT_PREV_EXCEPTION = num;          CPU_STAT_PREV_EXCEPTION = num;
   
         INTERRUPT(num, FALSE, errorp, error_code);          VERBOSE(("exception: ---------------------------------------------------------------- end"));
   
           INTERRUPT(num, 0, errorp, error_code);
   #if defined(IA32_SUPPORT_DEBUG_REGISTER)
           if (num != BP_EXCEPTION) {
                   if (CPU_INST_OP32) {
   #if defined(IA32_DONT_USE_SET_EFLAGS_FUNCTION)
                           CPU_EFLAG |= RF_FLAG;
   #else
                           set_eflags(REAL_EFLAGREG|RF_FLAG, RF_FLAG);
   #endif
                   }
           }
   #endif
           CPU_STAT_EXCEPTION_COUNTER_CLEAR();
         siglongjmp(exec_1step_jmpbuf, 1);          siglongjmp(exec_1step_jmpbuf, 1);
 }  }
   
Line 208  exception(int num, int error_code) Line 211  exception(int num, int error_code)
  * D          : ゲートのサイズ.0 = 16 bit, 1 = 32 bit   * D          : ゲートのサイズ.0 = 16 bit, 1 = 32 bit
  */   */
   
 static void interrupt_task(descriptor_t *gdp, int softintp, int errorp, int error_code);  static void interrupt_task_gate(const descriptor_t *gd, int softintp, int errorp, int error_code);
 static void interrupt_intr_or_trap(descriptor_t *gdp, int softintp, int errorp, int error_code);  static void interrupt_intr_or_trap(const descriptor_t *gd, int softintp, int errorp, int error_code);
   
 void  void
 interrupt(int num, int softintp, int errorp, int error_code)  interrupt(int num, int softintp, int errorp, int error_code)
 {  {
         descriptor_t gd;          descriptor_t gd;
         DWORD idt_idx;          UINT idt_idx;
         DWORD new_ip;          UINT32 new_ip;
         WORD new_cs;          UINT16 new_cs;
   
         VERBOSE(("interrupt: num = 0x%02x, softintp = %s, errorp = %s, error_code = %02x", num, softintp ? "on" : "off", errorp ? "on" : "off", error_code));          VERBOSE(("interrupt: num = 0x%02x, softintp = %s, errorp = %s, error_code = %08x", num, softintp ? "on" : "off", errorp ? "on" : "off", error_code));
   
         if (!CPU_STAT_PM) {          if (!CPU_STAT_PM) {
                 /* real mode */                  /* real mode */
                 idt_idx = num * 4;                  idt_idx = num * 4;
                 if (idt_idx + 3 > CPU_IDTR_LIMIT) {                  if (idt_idx + 3 > CPU_IDTR_LIMIT) {
                         VERBOSE(("interrupt: real-mode IDTR limit check failure (idx = 0x%04x, limit = 0x%08x", idt_idx, CPU_IDTR_LIMIT));                          VERBOSE(("interrupt: real-mode IDTR limit check failure (idx = 0x%04x, limit = 0x%08x", idt_idx, CPU_IDTR_LIMIT));
                         EXCEPTION(GP_EXCEPTION, num * 4 | 2);                          EXCEPTION(GP_EXCEPTION, idt_idx + 2);
                 }                  }
   
                 if (!softintp) {                  if (!softintp && CPU_STAT_HLT) {
                         BYTE op = cpu_codefetch(CPU_IP);                          CPU_EIP++;
                         if (op == 0xf4) {       /* hlt */                          CPU_STAT_HLT = FALSE;
                                 CPU_EIP++;  
                         }  
                 }                  }
   
                 REGPUSH0(REAL_FLAGREG);                  REGPUSH0(REAL_FLAGREG);
Line 243  interrupt(int num, int softintp, int err Line 244  interrupt(int num, int softintp, int err
                 CPU_EFLAG &= ~(T_FLAG | I_FLAG | AC_FLAG | RF_FLAG);                  CPU_EFLAG &= ~(T_FLAG | I_FLAG | AC_FLAG | RF_FLAG);
                 CPU_TRAP = 0;                  CPU_TRAP = 0;
   
                 new_ip = cpu_memoryread_w(CPU_IDTR_BASE + num * 4);                  new_ip = cpu_memoryread_w(CPU_IDTR_BASE + idt_idx);
                 new_cs = cpu_memoryread_w(CPU_IDTR_BASE + num * 4 + 2);                  new_cs = cpu_memoryread_w(CPU_IDTR_BASE + idt_idx + 2);
                 CPU_SET_SEGREG(CPU_CS_INDEX, new_cs);                  CPU_SET_SEGREG(CPU_CS_INDEX, new_cs);
                 SET_EIP(new_ip);                  SET_EIP(new_ip);
                 CPU_WORKCLOCK(20);                  CPU_WORKCLOCK(20);
         } else {          } else {
                 /* protected mode */                  /* protected mode */
                   VERBOSE(("interrupt: -------------------------------------------------------------- start"));
   
                   VERBOSE(("interrupt: old EIP = %04x:%08x, ESP = %04x:%08x", CPU_CS, CPU_EIP, CPU_SS, CPU_ESP));
   
   #if defined(DEBUG)
                   if (num == 0x80) {
                           /* Linux, FreeBSD, NetBSD, OpenBSD system call */
                           VERBOSE(("interrupt: syscall no = %d\n%s", CPU_EAX, cpu_reg2str()));
                   }
   #endif
   
                 /* VM86 && IOPL < 3 && interrupt cause == INTn */                  /* VM86 && IOPL < 3 && interrupt cause == INTn */
                 if (CPU_STAT_VM86 && (CPU_STAT_IOPL < CPU_IOPL3) && (softintp == -1)) {                  if (CPU_STAT_VM86 && (CPU_STAT_IOPL < CPU_IOPL3) && (softintp == -1)) {
Line 260  interrupt(int num, int softintp, int err Line 271  interrupt(int num, int softintp, int err
                 idt_idx = num * 8;                  idt_idx = num * 8;
                 if (idt_idx + 7 > CPU_IDTR_LIMIT) {                  if (idt_idx + 7 > CPU_IDTR_LIMIT) {
                         VERBOSE(("interrupt: IDTR limit check failure (idx = 0x%04x, limit = 0x%08x", idt_idx, CPU_IDTR_LIMIT));                          VERBOSE(("interrupt: IDTR limit check failure (idx = 0x%04x, limit = 0x%08x", idt_idx, CPU_IDTR_LIMIT));
                         EXCEPTION(GP_EXCEPTION, num * 8 | 2 | !softintp);                          EXCEPTION(GP_EXCEPTION, idt_idx + 2 + !softintp);
                 }                  }
   
                 memset(&gd, 0, sizeof(gd));                  memset(&gd, 0, sizeof(gd));
                 CPU_SET_GATEDESC(&gd, CPU_IDTR_BASE + idt_idx, CPU_MODE_SUPERVISER);                  load_descriptor(&gd, CPU_IDTR_BASE + idt_idx);
                 if (!gd.valid || !gd.p) {                  if (!gd.valid || !gd.p) {
                         VERBOSE(("interrupt: gate descripter is invalid."));                          VERBOSE(("interrupt: gate descripter is invalid."));
                         EXCEPTION(GP_EXCEPTION, num * 8 | 2 | !softintp);                          EXCEPTION(GP_EXCEPTION, idt_idx + 2 + !softintp);
                 }                  }
   
                 switch (gd.type) {                  switch (gd.type) {
Line 280  interrupt(int num, int softintp, int err Line 291  interrupt(int num, int softintp, int err
   
                 default:                  default:
                         VERBOSE(("interrupt: invalid gate type (%d)", gd.type));                          VERBOSE(("interrupt: invalid gate type (%d)", gd.type));
                         EXCEPTION(GP_EXCEPTION, num * 8 | 2 | !softintp);                          EXCEPTION(GP_EXCEPTION, idt_idx + 2 + !softintp);
                         break;                          break;
                 }                  }
   
                 /* 5.10.1.1. 例外/割り込みハンドラ・プロシージャの保護 */                  /* 5.10.1.1. 例外/割り込みハンドラ・プロシージャの保護 */
                 if (softintp && (gd.dpl < CPU_STAT_CPL)) {                  if (softintp && (gd.dpl < CPU_STAT_CPL)) {
                         VERBOSE(("interrupt: softintp && DPL(%d) < CPL(%d)", gd.dpl, CPU_STAT_CPL));                          VERBOSE(("interrupt: softintp && DPL(%d) < CPL(%d)", gd.dpl, CPU_STAT_CPL));
                         EXCEPTION(GP_EXCEPTION, num * 8 | 2);                          EXCEPTION(GP_EXCEPTION, idt_idx + 2);
                   }
   
                   if (!softintp && CPU_STAT_HLT) {
                           CPU_EIP++;
                           CPU_STAT_HLT = FALSE;
                 }                  }
   
                 switch (gd.type) {                  switch (gd.type) {
                 case CPU_SYSDESC_TYPE_TASK:                  case CPU_SYSDESC_TYPE_TASK:
                         interrupt_task(&gd, softintp, errorp, error_code);                          interrupt_task_gate(&gd, softintp, errorp, error_code);
                         break;                          break;
   
                 case CPU_SYSDESC_TYPE_INTR_16:                  case CPU_SYSDESC_TYPE_INTR_16:
Line 303  interrupt(int num, int softintp, int err Line 319  interrupt(int num, int softintp, int err
                         break;                          break;
   
                 default:                  default:
                         EXCEPTION(GP_EXCEPTION, num * 8 | 2 | !softintp);                          EXCEPTION(GP_EXCEPTION, idt_idx + 2 + !softintp);
                         break;                          break;
                 }                  }
   
                   VERBOSE(("interrupt: ---------------------------------------------------------------- end"));
         }          }
 }  }
   
 static void  static void
 interrupt_task(descriptor_t *gdp, int softintp, int errorp, int error_code)  interrupt_task_gate(const descriptor_t *gd, int softintp, int errorp, int error_code)
 {  {
         selector_t task_sel;          selector_t task_sel;
         int rv;          int rv;
Line 319  interrupt_task(descriptor_t *gdp, int so Line 337  interrupt_task(descriptor_t *gdp, int so
   
         (void)softintp;          (void)softintp;
   
         rv = parse_selector_sv(&task_sel, gdp->u.gate.selector);          rv = parse_selector(&task_sel, gd->u.gate.selector);
         if (rv < 0 || task_sel.ldt) {          if (rv < 0 || task_sel.ldt) {
                 VERBOSE(("interrupt: parse_selector (selector = %04x, rv = %d, %cDT)", gdp->u.gate.selector, rv, task_sel.ldt ? 'L' : 'G'));                  VERBOSE(("interrupt: parse_selector (selector = %04x, rv = %d, %cDT)", gd->u.gate.selector, rv, task_sel.ldt ? 'L' : 'G'));
                 EXCEPTION(TS_EXCEPTION, task_sel.idx);                  EXCEPTION(TS_EXCEPTION, task_sel.idx);
         }          }
   
Line 355  interrupt_task(descriptor_t *gdp, int so Line 373  interrupt_task(descriptor_t *gdp, int so
 }  }
   
 static void  static void
 interrupt_intr_or_trap(descriptor_t *gdp, int softintp, int errorp, int error_code)  interrupt_intr_or_trap(const descriptor_t *gd, int softintp, int errorp, int error_code)
 {  {
         selector_t intr_sel, ss_sel;          selector_t cs_sel, ss_sel;
         DWORD old_flags = REAL_EFLAGREG;          UINT stacksize;
         DWORD flags = REAL_EFLAGREG;          UINT32 old_flags;
         DWORD mask = 0;          UINT32 new_flags;
         DWORD stacksize;          UINT32 mask;
         DWORD new_ip, new_sp;          UINT32 sp;
         DWORD old_ip, old_sp;          UINT32 new_ip, new_sp;
         WORD old_cs, old_ss, new_ss;          UINT32 old_ip, old_sp;
           UINT16 old_cs, old_ss, new_ss;
         int rv;           int rv; 
   
         VERBOSE(("interrupt: old EIP = %04x:%08x, ESP = %04x:%08x", CPU_CS, CPU_PREV_EIP, CPU_SS, CPU_ESP));          new_ip = gd->u.gate.offset;
   
         new_ip = gdp->u.gate.offset;  
         old_ss = CPU_SS;          old_ss = CPU_SS;
         old_cs = CPU_CS;          old_cs = CPU_CS;
         old_ip = CPU_EIP;          old_ip = CPU_EIP;
         old_sp = CPU_ESP;          old_sp = CPU_ESP;
           old_flags = REAL_EFLAGREG;
           new_flags = REAL_EFLAGREG & ~(T_FLAG|RF_FLAG|NT_FLAG|VM_FLAG);
           mask = T_FLAG|RF_FLAG|NT_FLAG|VM_FLAG;
   
         switch (gdp->type) {          switch (gd->type) {
         case CPU_SYSDESC_TYPE_INTR_16:          case CPU_SYSDESC_TYPE_INTR_16:
                 old_ip &= 0xffff;  
                 old_sp &= 0xffff;  
                 /*FALLTHROUGH*/  
         case CPU_SYSDESC_TYPE_INTR_32:          case CPU_SYSDESC_TYPE_INTR_32:
                 VERBOSE(("interrupt: INTERRUPT-GATE"));                  VERBOSE(("interrupt: INTERRUPT-GATE"));
                 flags &= ~I_FLAG;                  new_flags &= ~I_FLAG;
                 mask |= I_FLAG;                  mask |= I_FLAG;
                 break;                  break;
   
         case CPU_SYSDESC_TYPE_TRAP_16:          case CPU_SYSDESC_TYPE_TRAP_16:
                 old_ip &= 0xffff;  
                 old_sp &= 0xffff;  
                 /*FALLTHROUGH*/  
         case CPU_SYSDESC_TYPE_TRAP_32:          case CPU_SYSDESC_TYPE_TRAP_32:
                 VERBOSE(("interrupt: TRAP-GATE"));                  VERBOSE(("interrupt: TRAP-GATE"));
                 break;                  break;
   
           default:
                   ia32_panic("interrupt: gate descriptor type is invalid (type = %d)", gd->type);
                   break;
         }          }
         flags &= ~(T_FLAG|RF_FLAG|NT_FLAG|VM_FLAG);  
         mask |= T_FLAG|RF_FLAG|NT_FLAG|VM_FLAG;  
   
         rv = parse_selector_sv(&intr_sel, gdp->u.gate.selector);          rv = parse_selector(&cs_sel, gd->u.gate.selector);
         if (rv < 0) {          if (rv < 0) {
                 VERBOSE(("interrupt: parse_selector (selector = %04x, rv = %d)", gdp->u.gate.selector, rv));                  VERBOSE(("interrupt: parse_selector (selector = %04x, rv = %d)", gd->u.gate.selector, rv));
                 EXCEPTION(GP_EXCEPTION, intr_sel.idx | !softintp);                  EXCEPTION(GP_EXCEPTION, cs_sel.idx + !softintp);
         }          }
   
         /* check segment type */          /* check segment type */
         if (!intr_sel.desc.s) {          if (!cs_sel.desc.s) {
                 VERBOSE(("interrupt: code segment is system segment"));                  VERBOSE(("interrupt: code segment is system segment"));
                 EXCEPTION(GP_EXCEPTION, intr_sel.idx | !softintp);                  EXCEPTION(GP_EXCEPTION, cs_sel.idx + !softintp);
         }          }
         if (!intr_sel.desc.u.seg.c) {          if (!cs_sel.desc.u.seg.c) {
                 VERBOSE(("interrupt: code segment is data segment"));                  VERBOSE(("interrupt: code segment is data segment"));
                 EXCEPTION(GP_EXCEPTION, intr_sel.idx | !softintp);                  EXCEPTION(GP_EXCEPTION, cs_sel.idx + !softintp);
         }          }
   
         /* check privilege level */          /* check privilege level */
         if (intr_sel.desc.dpl > CPU_STAT_CPL) {          if (cs_sel.desc.dpl > CPU_STAT_CPL) {
                 VERBOSE(("interrupt: DPL(%d) > CPL(%d)", intr_sel.desc.dpl, CPU_STAT_CPL));                  VERBOSE(("interrupt: DPL(%d) > CPL(%d)", cs_sel.desc.dpl, CPU_STAT_CPL));
                 EXCEPTION(GP_EXCEPTION, intr_sel.idx | !softintp);                  EXCEPTION(GP_EXCEPTION, cs_sel.idx + !softintp);
         }          }
   
         /* not present */          /* not present */
         if (selector_is_not_present(&intr_sel)) {          if (selector_is_not_present(&cs_sel)) {
                 VERBOSE(("interrupt: selector is not present"));                  VERBOSE(("interrupt: selector is not present"));
                 EXCEPTION(NP_EXCEPTION, intr_sel.idx | !softintp);                  EXCEPTION(NP_EXCEPTION, cs_sel.idx + !softintp);
         }          }
   
         if (!intr_sel.desc.u.seg.ec          if (!cs_sel.desc.u.seg.ec
          && (intr_sel.desc.dpl < CPU_STAT_CPL)) {           && (cs_sel.desc.dpl < CPU_STAT_CPL)) {
                 if (!CPU_STAT_VM86) {                  if (!CPU_STAT_VM86) {
                         VERBOSE(("interrupt: INTER-PRIVILEGE-LEVEL-INTERRUPT"));                          VERBOSE(("interrupt: INTER-PRIVILEGE-LEVEL-INTERRUPT"));
                         stacksize = errorp ? 12 : 10;                          stacksize = errorp ? 12 : 10;
                 } else {                  } else {
                         /* VM86 */                          /* VM86 */
                         if (intr_sel.desc.dpl != 0) {                          if (cs_sel.desc.dpl != 0) {
                                 /* 16.3.1.1 */                                  /* 16.3.1.1 */
                                 VERBOSE(("interrupt: DPL[CS](%d) != 0", intr_sel.desc.dpl));                                  VERBOSE(("interrupt: DPL[CS](%d) != 0", cs_sel.desc.dpl));
                                 EXCEPTION(GP_EXCEPTION, intr_sel.idx);                                  EXCEPTION(GP_EXCEPTION, cs_sel.idx);
                         }                          }
                         VERBOSE(("interrupt: INTERRUPT-FROM-VIRTUAL-8086-MODE"));                          VERBOSE(("interrupt: INTERRUPT-FROM-VIRTUAL-8086-MODE"));
                         stacksize = errorp ? 20 : 18;                          stacksize = errorp ? 20 : 18;
                 }                  }
                 switch (gdp->type) {                  switch (gd->type) {
                 case CPU_SYSDESC_TYPE_INTR_32:                  case CPU_SYSDESC_TYPE_INTR_32:
                 case CPU_SYSDESC_TYPE_TRAP_32:                  case CPU_SYSDESC_TYPE_TRAP_32:
                         stacksize *= 2;                          stacksize *= 2;
                         break;                          break;
                 }                  }
   
                 get_stack_from_tss(intr_sel.desc.dpl, &new_ss, &new_sp);                  get_stack_pointer_from_tss(cs_sel.desc.dpl, &new_ss, &new_sp);
   
                 rv = parse_selector_sv(&ss_sel, new_ss);                  rv = parse_selector(&ss_sel, new_ss);
                 if (rv < 0) {                  if (rv < 0) {
                         VERBOSE(("interrupt: parse_selector (selector = %04x, rv = %d)", new_ss, rv));                          VERBOSE(("interrupt: parse_selector (selector = %04x, rv = %d)", new_ss, rv));
                         EXCEPTION(TS_EXCEPTION, ss_sel.idx | !softintp);                          EXCEPTION(TS_EXCEPTION, ss_sel.idx + !softintp);
                 }                  }
   
                 /* check privilege level */                  /* check privilege level */
                 if (ss_sel.rpl != intr_sel.desc.dpl) {                  if (ss_sel.rpl != cs_sel.desc.dpl) {
                         VERBOSE(("interrupt: RPL[SS](%d) != DPL[CS](%d)", ss_sel.rpl, intr_sel.desc.dpl));                          VERBOSE(("interrupt: RPL[SS](%d) != DPL[CS](%d)", ss_sel.rpl, cs_sel.desc.dpl));
                         EXCEPTION(TS_EXCEPTION, ss_sel.idx | !softintp);                          EXCEPTION(TS_EXCEPTION, ss_sel.idx + !softintp);
                 }                  }
                 if (ss_sel.desc.dpl != intr_sel.desc.dpl) {                  if (ss_sel.desc.dpl != cs_sel.desc.dpl) {
                         VERBOSE(("interrupt: DPL[SS](%d) != DPL[CS](%d)", ss_sel.desc.dpl, intr_sel.desc.dpl));                          VERBOSE(("interrupt: DPL[SS](%d) != DPL[CS](%d)", ss_sel.desc.dpl, cs_sel.desc.dpl));
                         EXCEPTION(TS_EXCEPTION, ss_sel.idx | !softintp);                          EXCEPTION(TS_EXCEPTION, ss_sel.idx + !softintp);
                 }                  }
   
                 /* check segment type */                  /* check segment type */
                 if (!ss_sel.desc.s) {                  if (!ss_sel.desc.s) {
                         VERBOSE(("interrupt: stack segment is system segment"));                          VERBOSE(("interrupt: stack segment is system segment"));
                         EXCEPTION(TS_EXCEPTION, ss_sel.idx | !softintp);                          EXCEPTION(TS_EXCEPTION, ss_sel.idx + !softintp);
                 }                  }
                 if (ss_sel.desc.u.seg.c) {                  if (ss_sel.desc.u.seg.c) {
                         VERBOSE(("interrupt: stack segment is code segment"));                          VERBOSE(("interrupt: stack segment is code segment"));
                         EXCEPTION(TS_EXCEPTION, ss_sel.idx | !softintp);                          EXCEPTION(TS_EXCEPTION, ss_sel.idx + !softintp);
                 }                  }
                 if (!ss_sel.desc.u.seg.wr) {                  if (!ss_sel.desc.u.seg.wr) {
                         VERBOSE(("interrupt: stack segment is read-only data segment"));                          VERBOSE(("interrupt: stack segment is read-only data segment"));
                         EXCEPTION(TS_EXCEPTION, ss_sel.idx | !softintp);                          EXCEPTION(TS_EXCEPTION, ss_sel.idx + !softintp);
                 }                  }
   
                 /* not present */                  /* not present */
                 if (selector_is_not_present(&ss_sel)) {                  if (selector_is_not_present(&ss_sel)) {
                         VERBOSE(("interrupt: selector is not present"));                          VERBOSE(("interrupt: selector is not present"));
                         EXCEPTION(SS_EXCEPTION, ss_sel.idx | !softintp);                          EXCEPTION(SS_EXCEPTION, ss_sel.idx + !softintp);
                 }                  }
   
                 /* check stack room size */                  /* check stack room size */
                 CHECK_STACK_PUSH(&ss_sel.desc, new_sp, stacksize);                  STACK_PUSH_CHECK(ss_sel.idx, &ss_sel.desc, new_sp, stacksize);
   
                 /* out of range */                  /* out of range */
                 if (new_ip > intr_sel.desc.u.seg.limit) {                  if (new_ip > cs_sel.desc.u.seg.limit) {
                         VERBOSE(("interrupt: new_ip is out of range. new_ip = %08x, limit = %08x", new_ip, intr_sel.desc.u.seg.limit));                          VERBOSE(("interrupt: 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_ss(ss_sel.selector, &ss_sel.desc, intr_sel.desc.dpl);                  load_ss(ss_sel.selector, &ss_sel.desc, cs_sel.desc.dpl);
                 CPU_ESP = new_sp;                  CPU_ESP = new_sp;
   
                 load_cs(intr_sel.selector, &intr_sel.desc, intr_sel.desc.dpl);                  load_cs(cs_sel.selector, &cs_sel.desc, cs_sel.desc.dpl);
                 SET_EIP(new_ip);                  SET_EIP(new_ip);
   
                 if (CPU_STAT_VM86) {                  switch (gd->type) {
                         switch (gdp->type) {                  case CPU_SYSDESC_TYPE_INTR_32:
                         case CPU_SYSDESC_TYPE_INTR_32:                  case CPU_SYSDESC_TYPE_TRAP_32:
                         case CPU_SYSDESC_TYPE_TRAP_32:                          if (CPU_STAT_VM86) {
                                 PUSH0_32(CPU_GS);                                  PUSH0_32(CPU_GS);
                                 PUSH0_32(CPU_FS);                                  PUSH0_32(CPU_FS);
                                 PUSH0_32(CPU_DS);                                  PUSH0_32(CPU_DS);
                                 PUSH0_32(CPU_ES);                                  PUSH0_32(CPU_ES);
                                 break;  
   
                         case CPU_SYSDESC_TYPE_INTR_16:                                  CPU_SET_SEGREG(CPU_GS_INDEX, 0);
                         case CPU_SYSDESC_TYPE_TRAP_16:                                  CPU_STAT_SREG(CPU_GS_INDEX).valid = 0;
                                 ia32_panic("interrupt: 16bit gate");                                  CPU_SET_SEGREG(CPU_FS_INDEX, 0);
                                 break;                                  CPU_STAT_SREG(CPU_FS_INDEX).valid = 0;
                                   CPU_SET_SEGREG(CPU_DS_INDEX, 0);
                                   CPU_STAT_SREG(CPU_DS_INDEX).valid = 0;
                                   CPU_SET_SEGREG(CPU_ES_INDEX, 0);
                                   CPU_STAT_SREG(CPU_ES_INDEX).valid = 0;
                         }                          }
   
                         CPU_SET_SEGREG(CPU_GS_INDEX, 0);  
                         CPU_SET_SEGREG(CPU_FS_INDEX, 0);  
                         CPU_SET_SEGREG(CPU_DS_INDEX, 0);  
                         CPU_SET_SEGREG(CPU_ES_INDEX, 0);  
                 }  
   
                 switch (gdp->type) {  
                 case CPU_SYSDESC_TYPE_INTR_32:  
                 case CPU_SYSDESC_TYPE_TRAP_32:  
                         PUSH0_32(old_ss);                          PUSH0_32(old_ss);
                         PUSH0_32(old_sp);                          PUSH0_32(old_sp);
                         PUSH0_32(old_flags);                          PUSH0_32(old_flags);
Line 537  interrupt_intr_or_trap(descriptor_t *gdp Line 546  interrupt_intr_or_trap(descriptor_t *gdp
   
                 case CPU_SYSDESC_TYPE_INTR_16:                  case CPU_SYSDESC_TYPE_INTR_16:
                 case CPU_SYSDESC_TYPE_TRAP_16:                  case CPU_SYSDESC_TYPE_TRAP_16:
                           if (CPU_STAT_VM86) {
                                   ia32_panic("interrupt: 16bit gate && VM86");
                           }
                         PUSH0_16(old_ss);                          PUSH0_16(old_ss);
                         PUSH0_16(old_sp);                          PUSH0_16(old_sp);
                         PUSH0_16(old_flags);                          PUSH0_16(old_flags);
Line 547  interrupt_intr_or_trap(descriptor_t *gdp Line 559  interrupt_intr_or_trap(descriptor_t *gdp
                         }                          }
                         break;                          break;
                 }                  }
   
                 set_eflags(flags, mask);  
         } else {          } else {
                 if (CPU_STAT_VM86) {                  if (CPU_STAT_VM86) {
                         VERBOSE(("interrupt: VM86"));                          VERBOSE(("interrupt: VM86"));
                         EXCEPTION(GP_EXCEPTION, intr_sel.idx);                          EXCEPTION(GP_EXCEPTION, cs_sel.idx + !softintp);
                 }                  }
                 if (!intr_sel.desc.u.seg.ec && (intr_sel.desc.dpl != CPU_STAT_CPL)) {                  if (!cs_sel.desc.u.seg.ec && (cs_sel.desc.dpl != CPU_STAT_CPL)) {
                         VERBOSE(("interrupt: NON-CONFORMING-CODE-SEGMENT(%s) and DPL[CS](%d) != CPL", intr_sel.desc.u.seg.ec ? "false" : "true", intr_sel.desc.dpl, CPU_STAT_CPL));                          VERBOSE(("interrupt: NON-CONFORMING-CODE-SEGMENT(%s) and DPL[CS](%d) != CPL", cs_sel.desc.u.seg.ec ? "false" : "true", cs_sel.desc.dpl, CPU_STAT_CPL));
                         EXCEPTION(GP_EXCEPTION, intr_sel.idx);                          EXCEPTION(GP_EXCEPTION, cs_sel.idx + !softintp);
                 }                  }
                 VERBOSE(("interrupt: INTRA-PRIVILEGE-LEVEL-INTERRUPT"));                  VERBOSE(("interrupt: INTRA-PRIVILEGE-LEVEL-INTERRUPT"));
   
                 if (CPU_STAT_SS32) {  
                         new_sp = CPU_ESP;  
                 } else {  
                         new_sp = CPU_SP;  
                 }  
   
                 stacksize = errorp ? 8 : 6;                  stacksize = errorp ? 8 : 6;
                 switch (gdp->type) {                  switch (gd->type) {
                 case CPU_SYSDESC_TYPE_INTR_32:                  case CPU_SYSDESC_TYPE_INTR_32:
                 case CPU_SYSDESC_TYPE_TRAP_32:                  case CPU_SYSDESC_TYPE_TRAP_32:
                         stacksize *= 2;                          stacksize *= 2;
                         break;                          break;
                 }                  }
                 CHECK_STACK_PUSH(&CPU_STAT_SREG(CPU_SS_INDEX), new_sp, stacksize);  
                   if (CPU_STAT_SS32) {
                           sp = CPU_ESP;
                   } else {
                           sp = CPU_SP;
                   }
                   STACK_PUSH_CHECK(CPU_REGS_SREG(CPU_SS_INDEX), &CPU_STAT_SREG(CPU_SS_INDEX), sp, stacksize);
   
                 /* out of range */                  /* out of range */
                 if (new_ip > intr_sel.desc.u.seg.limit) {                  if (new_ip > cs_sel.desc.u.seg.limit) {
                         VERBOSE(("interrupt: new_ip is out of range. new_ip = %08x, limit = %08x", new_ip, intr_sel.desc.u.seg.limit));                          VERBOSE(("interrupt: 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);
                 }                  }
   
                 switch (gdp->type) {                  load_cs(cs_sel.selector, &cs_sel.desc, CPU_STAT_CPL);
                   SET_EIP(new_ip);
   
                   switch (gd->type) {
                 case CPU_SYSDESC_TYPE_INTR_32:                  case CPU_SYSDESC_TYPE_INTR_32:
                 case CPU_SYSDESC_TYPE_TRAP_32:                  case CPU_SYSDESC_TYPE_TRAP_32:
                         PUSH0_32(REAL_EFLAGREG);                          PUSH0_32(old_flags);
                         PUSH0_32(CPU_CS);                          PUSH0_32(old_cs);
                         PUSH0_32(CPU_EIP);                          PUSH0_32(old_ip);
                         if (errorp) {                          if (errorp) {
                                 PUSH0_32(error_code);                                  PUSH0_32(error_code);
                         }                          }
Line 594  interrupt_intr_or_trap(descriptor_t *gdp Line 607  interrupt_intr_or_trap(descriptor_t *gdp
   
                 case CPU_SYSDESC_TYPE_INTR_16:                  case CPU_SYSDESC_TYPE_INTR_16:
                 case CPU_SYSDESC_TYPE_TRAP_16:                  case CPU_SYSDESC_TYPE_TRAP_16:
                         PUSH0_16(REAL_FLAGREG);                          PUSH0_16(old_flags);
                         PUSH0_16(CPU_CS);                          PUSH0_16(old_cs);
                         PUSH0_16(CPU_IP);                          PUSH0_16(old_ip);
                         if (errorp) {                          if (errorp) {
                                 PUSH0_16(error_code);                                  PUSH0_16(error_code);
                         }                          }
                         break;                          break;
                 }                  }
   
                 load_cs(intr_sel.selector, &intr_sel.desc, CPU_STAT_CPL);  
                 SET_EIP(new_ip);  
   
                 set_eflags(flags, mask);  
         }          }
   #if defined(IA32_DONT_USE_SET_EFLAGS_FUNCTION)
           CPU_EFLAG = new_flags;
           CPU_OV = CPU_FLAG & O_FLAG;
           CPU_TRAP = (CPU_FLAG & (I_FLAG|T_FLAG)) == (I_FLAG|T_FLAG);
           if ((old_flags ^ CPU_EFLAG) & VM_FLAG) {
                   if (CPU_EFLAG & VM_FLAG) {
                           change_vm(1);
                   } else {
                           change_vm(0);
                   }
           }
   #else
           set_eflags(new_flags, mask);
   #endif
   
         VERBOSE(("interrupt: new EIP = %04x:%08x, new ESP = %04x:%08x", CPU_CS, CPU_EIP, CPU_SS, CPU_ESP));          VERBOSE(("interrupt: new EIP = %04x:%08x, ESP = %04x:%08x", CPU_CS, CPU_EIP, CPU_SS, CPU_ESP));
 }  }

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


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