trunk/src/emu/cpu/i386/i386.c
| r22008 | r22009 | |
| 848 | 848 | cpustate->sreg[SS].selector = stack.selector; |
| 849 | 849 | i386_load_protected_mode_segment(cpustate,&cpustate->sreg[SS],NULL); |
| 850 | 850 | 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; |
| 855 | 852 | if(V8086_MODE) |
| 856 | 853 | { |
| 857 | 854 | //logerror("IRQ (%08x): Interrupt during V8086 task\n",cpustate->pc); |
| r22008 | r22009 | |
| 928 | 925 | } |
| 929 | 926 | } |
| 930 | 927 | } |
| 931 | | |
| 932 | | if(type != 0x0e && type != 0x0f) // if not 386 interrupt or trap gate |
| 928 | UINT32 tempSP = REG32(ESP); |
| 929 | try |
| 933 | 930 | { |
| 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 | } |
| 938 | 941 | 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 | } |
| 940 | 950 | } |
| 941 | | else |
| 951 | catch(UINT64 e) |
| 942 | 952 | { |
| 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; |
| 949 | 955 | } |
| 950 | 956 | if(SetRPL != 0) |
| 951 | 957 | segment = (segment & ~0x03) | cpustate->CPL; |
| r22008 | r22009 | |
| 1780 | 1786 | offset = gate.offset; |
| 1781 | 1787 | |
| 1782 | 1788 | 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 */ |
| 1784 | 1790 | WRITE_TEST(cpustate, stack.base+newESP-1); |
| 1785 | 1791 | /* switch to new stack */ |
| 1786 | 1792 | oldSS = cpustate->sreg[SS].selector; |
| r22008 | r22009 | |
| 1794 | 1800 | oldESP = REG16(SP); |
| 1795 | 1801 | } |
| 1796 | 1802 | 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; |
| 1801 | 1804 | |
| 1802 | 1805 | if(operand32 != 0) |
| 1803 | 1806 | { |
| r22008 | r22009 | |
| 1917 | 1920 | |
| 1918 | 1921 | if(SetRPL != 0) |
| 1919 | 1922 | selector = (selector & ~0x03) | cpustate->CPL; |
| 1920 | | if(operand32 == 0) |
| 1923 | |
| 1924 | UINT32 tempSP = REG32(ESP); |
| 1925 | try |
| 1921 | 1926 | { |
| 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 | } |
| 1929 | 1948 | } |
| 1930 | | else |
| 1949 | catch(UINT64 e) |
| 1931 | 1950 | { |
| 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; |
| 1939 | 1953 | } |
| 1954 | |
| 1940 | 1955 | CHANGE_PC(cpustate,cpustate->eip); |
| 1941 | 1956 | } |
| 1942 | 1957 | |