src/emu/cpu/i386/i386.c
| r14598 | r14599 | |
| 1915 | 1915 | static void i386_protected_mode_retf(i386_state* cpustate, UINT8 count, UINT8 operand32) |
| 1916 | 1916 | { |
| 1917 | 1917 | UINT32 newCS, newEIP; |
| 1918 | | UINT32 newSS, newESP; // when changing privilege |
| 1919 | 1918 | I386_SREG desc; |
| 1920 | 1919 | UINT8 CPL, RPL, DPL; |
| 1921 | 1920 | |
| r14598 | r14599 | |
| 1925 | 1924 | { |
| 1926 | 1925 | newEIP = READ16(cpustate, ea) & 0xffff; |
| 1927 | 1926 | newCS = READ16(cpustate, ea+2) & 0xffff; |
| 1928 | | ea += count+4; |
| 1929 | | newESP = READ16(cpustate, ea) & 0xffff; |
| 1930 | | newSS = READ16(cpustate, ea+2) & 0xffff; |
| 1931 | 1927 | } |
| 1932 | 1928 | else |
| 1933 | 1929 | { |
| 1934 | 1930 | newEIP = READ32(cpustate, ea); |
| 1935 | 1931 | newCS = READ32(cpustate, ea+4) & 0xffff; |
| 1936 | | ea += count+8; |
| 1937 | | newESP = READ32(cpustate, ea); |
| 1938 | | newSS = READ32(cpustate, ea+4) & 0xffff; |
| 1939 | 1932 | } |
| 1940 | 1933 | |
| 1941 | 1934 | memset(&desc, 0, sizeof(desc)); |
| r14598 | r14599 | |
| 2031 | 2024 | } |
| 2032 | 2025 | else if(RPL > CPL) |
| 2033 | 2026 | { |
| 2027 | UINT32 newSS, newESP; // when changing privilege |
| 2034 | 2028 | /* outer privilege level */ |
| 2035 | 2029 | if(operand32 == 0) |
| 2036 | 2030 | { |
| r14598 | r14599 | |
| 2050 | 2044 | FAULT(FAULT_SS,0) |
| 2051 | 2045 | } |
| 2052 | 2046 | } |
| 2053 | | |
| 2054 | 2047 | /* Check CS selector and descriptor */ |
| 2055 | 2048 | if((newCS & ~0x03) == 0) |
| 2056 | 2049 | { |
| r14598 | r14599 | |
| 2104 | 2097 | logerror("RETF: EIP is past return CS segment limit.\n"); |
| 2105 | 2098 | FAULT(FAULT_GP,0) |
| 2106 | 2099 | } |
| 2100 | |
| 2101 | if(operand32 == 0) |
| 2102 | { |
| 2103 | ea += count+4; |
| 2104 | newESP = READ16(cpustate, ea) & 0xffff; |
| 2105 | newSS = READ16(cpustate, ea+2) & 0xffff; |
| 2106 | } |
| 2107 | else |
| 2108 | { |
| 2109 | ea += count+8; |
| 2110 | newESP = READ32(cpustate, ea); |
| 2111 | newSS = READ32(cpustate, ea+4) & 0xffff; |
| 2112 | } |
| 2113 | |
| 2107 | 2114 | /* Check SS selector and descriptor */ |
| 2108 | 2115 | desc.selector = newSS; |
| 2109 | 2116 | i386_load_protected_mode_segment(cpustate,&desc); |
| r14598 | r14599 | |
| 2191 | 2198 | newEIP = READ16(cpustate, ea) & 0xffff; |
| 2192 | 2199 | newCS = READ16(cpustate, ea+2) & 0xffff; |
| 2193 | 2200 | newflags = READ16(cpustate, ea+4) & 0xffff; |
| 2194 | | newESP = READ16(cpustate, ea+6) & 0xffff; |
| 2195 | | newSS = READ16(cpustate, ea+8) & 0xffff; |
| 2196 | 2201 | } |
| 2197 | 2202 | else |
| 2198 | 2203 | { |
| 2199 | 2204 | newEIP = READ32(cpustate, ea); |
| 2200 | 2205 | newCS = READ32(cpustate, ea+4) & 0xffff; |
| 2201 | 2206 | newflags = READ32(cpustate, ea+8); |
| 2202 | | newESP = READ32(cpustate, ea+12); |
| 2203 | | newSS = READ32(cpustate, ea+16) & 0xffff; |
| 2204 | 2207 | } |
| 2205 | 2208 | |
| 2206 | 2209 | if(V8086_MODE) |
| r14598 | r14599 | |
| 2271 | 2274 | if(newflags & 0x00020000) // if returning to virtual 8086 mode |
| 2272 | 2275 | { |
| 2273 | 2276 | // UINT8 SSRPL,SSDPL; |
| 2277 | if(operand32 == 0) |
| 2278 | { |
| 2279 | newESP = READ16(cpustate, ea+6) & 0xffff; |
| 2280 | newSS = READ16(cpustate, ea+8) & 0xffff; |
| 2281 | } |
| 2282 | else |
| 2283 | { |
| 2284 | newESP = READ32(cpustate, ea+12); |
| 2285 | newSS = READ32(cpustate, ea+16) & 0xffff; |
| 2286 | } |
| 2274 | 2287 | memset(&desc, 0, sizeof(desc)); |
| 2275 | 2288 | desc.selector = newCS; |
| 2276 | 2289 | i386_load_protected_mode_segment(cpustate,&desc); |
| r14598 | r14599 | |
| 2547 | 2560 | } |
| 2548 | 2561 | else if(RPL > CPL) |
| 2549 | 2562 | { |
| 2550 | | I386_SREG stack; |
| 2551 | 2563 | /* return to outer privilege level */ |
| 2552 | 2564 | memset(&desc, 0, sizeof(desc)); |
| 2553 | 2565 | desc.selector = newCS; |
| 2554 | 2566 | i386_load_protected_mode_segment(cpustate,&desc); |
| 2555 | 2567 | DPL = (desc.flags >> 5) & 0x03; // descriptor privilege level |
| 2556 | 2568 | RPL = newCS & 0x03; |
| 2557 | | memset(&stack, 0, sizeof(stack)); |
| 2558 | | stack.selector = newSS; |
| 2559 | | i386_load_protected_mode_segment(cpustate,&stack); |
| 2560 | 2569 | if(operand32 == 0) |
| 2561 | 2570 | { |
| 2562 | 2571 | UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP)); |
| r14598 | r14599 | |
| 2625 | 2634 | } |
| 2626 | 2635 | |
| 2627 | 2636 | /* Check SS selector and descriptor */ |
| 2637 | if(operand32 == 0) |
| 2638 | { |
| 2639 | newESP = READ16(cpustate, ea+6) & 0xffff; |
| 2640 | newSS = READ16(cpustate, ea+8) & 0xffff; |
| 2641 | } |
| 2642 | else |
| 2643 | { |
| 2644 | newESP = READ32(cpustate, ea+12); |
| 2645 | newSS = READ32(cpustate, ea+16) & 0xffff; |
| 2646 | } |
| 2647 | memset(&stack, 0, sizeof(stack)); |
| 2648 | stack.selector = newSS; |
| 2649 | i386_load_protected_mode_segment(cpustate,&stack); |
| 2628 | 2650 | DPL = (stack.flags >> 5) & 0x03; |
| 2629 | 2651 | if((newSS & ~0x03) == 0) |
| 2630 | 2652 | { |