Previous 199869 Revisions Next

r22009 Thursday 21st March, 2013 at 21:54:31 UTC by Carl
i386: fix up the stack if a page fault occurs in a far call and clear the top of esp when loading a tss stack (nw)
[src/emu/cpu/i386]i386.c

trunk/src/emu/cpu/i386/i386.c
r22008r22009
848848            cpustate->sreg[SS].selector = stack.selector;
849849            i386_load_protected_mode_segment(cpustate,&cpustate->sreg[SS],NULL);
850850            i386_set_descriptor_accessed(cpustate, stack.selector);
851            if(flags & 0x0008)
852               REG32(ESP) = i386_get_stack_ptr(cpustate,DPL);
853            else
854               REG16(SP) = i386_get_stack_ptr(cpustate,DPL);
851            REG32(ESP) = newESP;
855852            if(V8086_MODE)
856853            {
857854               //logerror("IRQ (%08x): Interrupt during V8086 task\n",cpustate->pc);
r22008r22009
928925            }
929926         }
930927      }
931
932      if(type != 0x0e && type != 0x0f)  // if not 386 interrupt or trap gate
928      UINT32 tempSP = REG32(ESP);
929      try
933930      {
934         PUSH16(cpustate, oldflags & 0xffff );
935         PUSH16(cpustate, cpustate->sreg[CS].selector );
936         if(irq == 3 || irq == 4 || irq == 9 || irq_gate == 1)
937            PUSH16(cpustate, cpustate->eip );
931         // this is ugly but the alternative is worse
932         if(type != 0x0e && type != 0x0f)  // if not 386 interrupt or trap gate
933         {
934            PUSH16(cpustate, oldflags & 0xffff );
935            PUSH16(cpustate, cpustate->sreg[CS].selector );
936            if(irq == 3 || irq == 4 || irq == 9 || irq_gate == 1)
937               PUSH16(cpustate, cpustate->eip );
938            else
939               PUSH16(cpustate, cpustate->prev_eip );
940         }
938941         else
939            PUSH16(cpustate, cpustate->prev_eip );
942         {
943            PUSH32(cpustate, oldflags & 0x00ffffff );
944            PUSH32(cpustate, cpustate->sreg[CS].selector );
945            if(irq == 3 || irq == 4 || irq == 9 || irq_gate == 1)
946               PUSH32(cpustate, cpustate->eip );
947            else
948               PUSH32(cpustate, cpustate->prev_eip );
949         }
940950      }
941      else
951      catch(UINT64 e)
942952      {
943         PUSH32(cpustate, oldflags & 0x00ffffff );
944         PUSH32(cpustate, cpustate->sreg[CS].selector );
945         if(irq == 3 || irq == 4 || irq == 9 || irq_gate == 1)
946            PUSH32(cpustate, cpustate->eip );
947         else
948            PUSH32(cpustate, cpustate->prev_eip );
953         REG32(ESP) = tempSP;
954         throw e;
949955      }
950956      if(SetRPL != 0)
951957         segment = (segment & ~0x03) | cpustate->CPL;
r22008r22009
17801786               offset = gate.offset;
17811787
17821788               cpustate->CPL = (stack.flags >> 5) & 0x03;
1783               /* check for page fault at new stack TODO: check if stack frame crosses page boundary */
1789               /* check for page fault at new stack */
17841790               WRITE_TEST(cpustate, stack.base+newESP-1);
17851791               /* switch to new stack */
17861792               oldSS = cpustate->sreg[SS].selector;
r22008r22009
17941800                  oldESP = REG16(SP);
17951801               }
17961802               i386_load_segment_descriptor(cpustate, SS );
1797               if(operand32 != 0)
1798                  REG32(ESP) = i386_get_stack_ptr(cpustate,gate.selector & 0x03);
1799               else
1800                  REG16(SP) = i386_get_stack_ptr(cpustate,gate.selector & 0x03) & 0x0000ffff;
1803               REG32(ESP) = newESP;
18011804
18021805               if(operand32 != 0)
18031806               {
r22008r22009
19171920
19181921   if(SetRPL != 0)
19191922      selector = (selector & ~0x03) | cpustate->CPL;
1920   if(operand32 == 0)
1923
1924   UINT32 tempSP = REG32(ESP);
1925   try
19211926   {
1922      /* 16-bit operand size */
1923      PUSH16(cpustate, cpustate->sreg[CS].selector );
1924      PUSH16(cpustate, cpustate->eip & 0x0000ffff );
1925      cpustate->sreg[CS].selector = selector;
1926      cpustate->performed_intersegment_jump = 1;
1927      cpustate->eip = offset;
1928      i386_load_segment_descriptor(cpustate,CS);
1927      // this is ugly but the alternative is worse
1928      if(operand32 == 0)
1929      {
1930         /* 16-bit operand size */
1931         PUSH16(cpustate, cpustate->sreg[CS].selector );
1932         PUSH16(cpustate, cpustate->eip & 0x0000ffff );
1933         cpustate->sreg[CS].selector = selector;
1934         cpustate->performed_intersegment_jump = 1;
1935         cpustate->eip = offset;
1936         i386_load_segment_descriptor(cpustate,CS);
1937      }
1938      else
1939      {
1940         /* 32-bit operand size */
1941         PUSH32(cpustate, cpustate->sreg[CS].selector );
1942         PUSH32(cpustate, cpustate->eip );
1943         cpustate->sreg[CS].selector = selector;
1944         cpustate->performed_intersegment_jump = 1;
1945         cpustate->eip = offset;
1946         i386_load_segment_descriptor(cpustate, CS );
1947      }
19291948   }
1930   else
1949   catch(UINT64 e)
19311950   {
1932      /* 32-bit operand size */
1933      PUSH32(cpustate, cpustate->sreg[CS].selector );
1934      PUSH32(cpustate, cpustate->eip );
1935      cpustate->sreg[CS].selector = selector;
1936      cpustate->performed_intersegment_jump = 1;
1937      cpustate->eip = offset;
1938      i386_load_segment_descriptor(cpustate, CS );
1951      REG32(ESP) = tempSP;
1952      throw e;
19391953   }
1954
19401955   CHANGE_PC(cpustate,cpustate->eip);
19411956}
19421957

Previous 199869 Revisions Next


© 1997-2024 The MAME Team