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 | |