src/emu/cpu/i386/i386op16.c
| r14729 | r14730 | |
| 61 | 61 | switch( (modrm >> 3) & 0x7 ) |
| 62 | 62 | { |
| 63 | 63 | case 0: /* ROL rm16, i8 */ |
| 64 | if(!(shift & 15)) |
| 65 | { |
| 66 | if(shift & 16) |
| 67 | { |
| 68 | cpustate->CF = src & 1; |
| 69 | cpustate->OF = (src & 1) ^ ((src >> 15) & 1); |
| 70 | } |
| 71 | break; |
| 72 | } |
| 73 | shift &= 15; |
| 64 | 74 | dst = ((src & ((UINT16)0xffff >> shift)) << shift) | |
| 65 | 75 | ((src & ((UINT16)0xffff << (16-shift))) >> (16-shift)); |
| 66 | | cpustate->CF = (src >> (16-shift)) & 0x1; |
| 76 | cpustate->CF = dst & 0x1; |
| 77 | cpustate->OF = (dst & 1) ^ (dst >> 15); |
| 67 | 78 | CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); |
| 68 | 79 | break; |
| 69 | 80 | case 1: /* ROR rm16, i8 */ |
| 81 | if(!(shift & 15)) |
| 82 | { |
| 83 | if(shift & 16) |
| 84 | { |
| 85 | cpustate->CF = (src >> 15) & 1; |
| 86 | cpustate->OF = ((src >> 15) & 1) ^ ((src >> 14) & 1); |
| 87 | } |
| 88 | break; |
| 89 | } |
| 90 | shift &= 15; |
| 70 | 91 | dst = ((src & ((UINT16)0xffff << shift)) >> shift) | |
| 71 | 92 | ((src & ((UINT16)0xffff >> (16-shift))) << (16-shift)); |
| 72 | | cpustate->CF = (src >> (shift-1)) & 0x1; |
| 93 | cpustate->CF = (dst >> 15) & 1; |
| 94 | cpustate->OF = ((dst >> 15) ^ (dst >> 14)) & 1; |
| 73 | 95 | CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); |
| 74 | 96 | break; |
| 75 | 97 | case 2: /* RCL rm16, i8 */ |
| 98 | shift %= 17; |
| 76 | 99 | dst = ((src & ((UINT16)0xffff >> shift)) << shift) | |
| 77 | 100 | ((src & ((UINT16)0xffff << (17-shift))) >> (17-shift)) | |
| 78 | 101 | (cpustate->CF << (shift-1)); |
| 79 | | cpustate->CF = (src >> (16-shift)) & 0x1; |
| 102 | if(shift) cpustate->CF = (src >> (16-shift)) & 0x1; |
| 103 | cpustate->OF = cpustate->CF ^ ((dst >> 15) & 1); |
| 80 | 104 | CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM); |
| 81 | 105 | break; |
| 82 | 106 | case 3: /* RCR rm16, i8 */ |
| 107 | shift %= 17; |
| 83 | 108 | dst = ((src & ((UINT16)0xffff << shift)) >> shift) | |
| 84 | 109 | ((src & ((UINT16)0xffff >> (16-shift))) << (17-shift)) | |
| 85 | 110 | (cpustate->CF << (16-shift)); |
| 86 | | cpustate->CF = (src >> (shift-1)) & 0x1; |
| 111 | if(shift) cpustate->CF = (src >> (shift-1)) & 0x1; |
| 112 | cpustate->OF = ((dst >> 15) ^ (dst >> 14)) & 1; |
| 87 | 113 | CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM); |
| 88 | 114 | break; |
| 89 | 115 | case 4: /* SHL/SAL rm16, i8 */ |
| 90 | 116 | case 6: |
| 117 | shift &= 31; |
| 91 | 118 | dst = src << shift; |
| 92 | 119 | cpustate->CF = (src & (1 << (16-shift))) ? 1 : 0; |
| 93 | 120 | SetSZPF16(dst); |
| 94 | 121 | CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); |
| 95 | 122 | break; |
| 96 | 123 | case 5: /* SHR rm16, i8 */ |
| 124 | shift &= 31; |
| 97 | 125 | dst = src >> shift; |
| 98 | 126 | cpustate->CF = (src & (1 << (shift-1))) ? 1 : 0; |
| 99 | 127 | SetSZPF16(dst); |
| 100 | 128 | CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); |
| 101 | 129 | break; |
| 102 | 130 | case 7: /* SAR rm16, i8 */ |
| 131 | shift &= 31; |
| 103 | 132 | dst = (INT16)src >> shift; |
| 104 | 133 | cpustate->CF = (src & (1 << (shift-1))) ? 1 : 0; |
| 105 | 134 | SetSZPF16(dst); |
| r14729 | r14730 | |
| 329 | 358 | UINT16 dst = LOAD_RM16(modrm); |
| 330 | 359 | UINT16 bit = LOAD_REG16(modrm); |
| 331 | 360 | |
| 332 | | if( dst & (1 << bit) ) |
| 361 | if( dst & (1 << (bit & 0xf)) ) |
| 333 | 362 | cpustate->CF = 1; |
| 334 | 363 | else |
| 335 | 364 | cpustate->CF = 0; |
| r14729 | r14730 | |
| 339 | 368 | UINT32 ea = GetEA(cpustate,modrm,0); |
| 340 | 369 | UINT16 bit = LOAD_REG16(modrm); |
| 341 | 370 | ea += 2*(bit/16); |
| 371 | ea = (cpustate->address_size)?ea:(ea&0xffff); |
| 342 | 372 | bit %= 16; |
| 343 | 373 | UINT16 dst = READ16(cpustate,ea); |
| 344 | 374 | |
| r14729 | r14730 | |
| 358 | 388 | UINT16 dst = LOAD_RM16(modrm); |
| 359 | 389 | UINT16 bit = LOAD_REG16(modrm); |
| 360 | 390 | |
| 361 | | if( dst & (1 << bit) ) |
| 391 | if( dst & (1 << (bit & 0xf)) ) |
| 362 | 392 | cpustate->CF = 1; |
| 363 | 393 | else |
| 364 | 394 | cpustate->CF = 0; |
| 365 | | dst ^= (1 << bit); |
| 395 | dst ^= (1 << (bit & 0xf)); |
| 366 | 396 | |
| 367 | 397 | STORE_RM16(modrm, dst); |
| 368 | 398 | CYCLES(cpustate,CYCLES_BTC_REG_REG); |
| r14729 | r14730 | |
| 370 | 400 | UINT32 ea = GetEA(cpustate,modrm,1); |
| 371 | 401 | UINT16 bit = LOAD_REG16(modrm); |
| 372 | 402 | ea += 2*(bit/16); |
| 403 | ea = (cpustate->address_size)?ea:(ea&0xffff); |
| 373 | 404 | bit %= 16; |
| 374 | 405 | UINT16 dst = READ16(cpustate,ea); |
| 375 | 406 | |
| r14729 | r14730 | |
| 391 | 422 | UINT16 dst = LOAD_RM16(modrm); |
| 392 | 423 | UINT16 bit = LOAD_REG16(modrm); |
| 393 | 424 | |
| 394 | | if( dst & (1 << bit) ) |
| 425 | if( dst & (1 << (bit & 0xf)) ) |
| 395 | 426 | cpustate->CF = 1; |
| 396 | 427 | else |
| 397 | 428 | cpustate->CF = 0; |
| 398 | | dst &= ~(1 << bit); |
| 429 | dst &= ~(1 << (bit & 0xf)); |
| 399 | 430 | |
| 400 | 431 | STORE_RM16(modrm, dst); |
| 401 | 432 | CYCLES(cpustate,CYCLES_BTR_REG_REG); |
| r14729 | r14730 | |
| 403 | 434 | UINT32 ea = GetEA(cpustate,modrm,1); |
| 404 | 435 | UINT16 bit = LOAD_REG16(modrm); |
| 405 | 436 | ea += 2*(bit/16); |
| 437 | ea = (cpustate->address_size)?ea:(ea&0xffff); |
| 406 | 438 | bit %= 16; |
| 407 | 439 | UINT16 dst = READ16(cpustate,ea); |
| 408 | 440 | |
| r14729 | r14730 | |
| 424 | 456 | UINT16 dst = LOAD_RM16(modrm); |
| 425 | 457 | UINT16 bit = LOAD_REG16(modrm); |
| 426 | 458 | |
| 427 | | if( dst & (1 << bit) ) |
| 459 | if( dst & (1 << (bit & 0xf)) ) |
| 428 | 460 | cpustate->CF = 1; |
| 429 | 461 | else |
| 430 | 462 | cpustate->CF = 0; |
| 431 | | dst |= (1 << bit); |
| 463 | dst |= (1 << (bit & 0xf)); |
| 432 | 464 | |
| 433 | 465 | STORE_RM16(modrm, dst); |
| 434 | 466 | CYCLES(cpustate,CYCLES_BTS_REG_REG); |
| r14729 | r14730 | |
| 436 | 468 | UINT32 ea = GetEA(cpustate,modrm,1); |
| 437 | 469 | UINT16 bit = LOAD_REG16(modrm); |
| 438 | 470 | ea += 2*(bit/16); |
| 471 | ea = (cpustate->address_size)?ea:(ea&0xffff); |
| 439 | 472 | bit %= 16; |
| 440 | 473 | UINT16 dst = READ16(cpustate,ea); |
| 441 | 474 | |
| r14729 | r14730 | |
| 1994 | 2027 | |
| 1995 | 2028 | static void I386OP(shld16_i8)(i386_state *cpustate) // Opcode 0x0f a4 |
| 1996 | 2029 | { |
| 1997 | | /* TODO: Correct flags */ |
| 1998 | 2030 | UINT8 modrm = FETCH(cpustate); |
| 1999 | 2031 | if( modrm >= 0xc0 ) { |
| 2000 | 2032 | UINT16 dst = LOAD_RM16(modrm); |
| 2001 | 2033 | UINT16 upper = LOAD_REG16(modrm); |
| 2002 | 2034 | UINT8 shift = FETCH(cpustate); |
| 2003 | | if( shift > 31 || shift == 0 ) { |
| 2035 | shift &= 31; |
| 2036 | if( shift == 0 ) { |
| 2004 | 2037 | |
| 2005 | 2038 | } else if( shift > 15 ) { |
| 2006 | | cpustate->CF = (dst & (1 << (16-shift))) ? 1 : 0; |
| 2039 | cpustate->CF = (upper & (1 << (16-shift))) ? 1 : 0; |
| 2040 | // ppro and above should be (dst >> (32-shift)) |
| 2007 | 2041 | dst = (upper << (shift-16)) | (upper >> (32-shift)); |
| 2042 | cpustate->OF = cpustate->CF ^ (dst >> 15); |
| 2008 | 2043 | SetSZPF16(dst); |
| 2009 | 2044 | } else { |
| 2010 | 2045 | cpustate->CF = (dst & (1 << (16-shift))) ? 1 : 0; |
| 2011 | 2046 | dst = (dst << shift) | (upper >> (16-shift)); |
| 2047 | cpustate->OF = cpustate->CF ^ (dst >> 15); |
| 2012 | 2048 | SetSZPF16(dst); |
| 2013 | 2049 | } |
| 2014 | 2050 | STORE_RM16(modrm, dst); |
| r14729 | r14730 | |
| 2018 | 2054 | UINT16 dst = READ16(cpustate,ea); |
| 2019 | 2055 | UINT16 upper = LOAD_REG16(modrm); |
| 2020 | 2056 | UINT8 shift = FETCH(cpustate); |
| 2021 | | if( shift > 31 || shift == 0 ) { |
| 2057 | shift &= 31; |
| 2058 | if( shift == 0 ) { |
| 2022 | 2059 | |
| 2023 | 2060 | } else if( shift > 15 ) { |
| 2024 | | cpustate->CF = (dst & (1 << (16-shift))) ? 1 : 0; |
| 2061 | cpustate->CF = (upper & (1 << (16-shift))) ? 1 : 0; |
| 2025 | 2062 | dst = (upper << (shift-16)) | (upper >> (32-shift)); |
| 2063 | cpustate->OF = cpustate->CF ^ (dst >> 15); |
| 2026 | 2064 | SetSZPF16(dst); |
| 2027 | 2065 | } else { |
| 2028 | 2066 | cpustate->CF = (dst & (1 << (16-shift))) ? 1 : 0; |
| 2029 | 2067 | dst = (dst << shift) | (upper >> (16-shift)); |
| 2068 | cpustate->OF = cpustate->CF ^ (dst >> 15); |
| 2030 | 2069 | SetSZPF16(dst); |
| 2031 | 2070 | } |
| 2032 | 2071 | WRITE16(cpustate,ea, dst); |
| r14729 | r14730 | |
| 2036 | 2075 | |
| 2037 | 2076 | static void I386OP(shld16_cl)(i386_state *cpustate) // Opcode 0x0f a5 |
| 2038 | 2077 | { |
| 2039 | | /* TODO: Correct flags */ |
| 2040 | 2078 | UINT8 modrm = FETCH(cpustate); |
| 2041 | 2079 | if( modrm >= 0xc0 ) { |
| 2042 | 2080 | UINT16 dst = LOAD_RM16(modrm); |
| 2043 | 2081 | UINT16 upper = LOAD_REG16(modrm); |
| 2044 | 2082 | UINT8 shift = REG8(CL); |
| 2045 | | if( shift > 31 || shift == 0 ) { |
| 2083 | shift &= 31; |
| 2084 | if( shift == 0 ) { |
| 2046 | 2085 | |
| 2047 | 2086 | } else if( shift > 15 ) { |
| 2048 | | cpustate->CF = (dst & (1 << (16-shift))) ? 1 : 0; |
| 2087 | cpustate->CF = (upper & (1 << (16-shift))) ? 1 : 0; |
| 2049 | 2088 | dst = (upper << (shift-16)) | (upper >> (32-shift)); |
| 2089 | cpustate->OF = cpustate->CF ^ (dst >> 15); |
| 2050 | 2090 | SetSZPF16(dst); |
| 2051 | 2091 | } else { |
| 2052 | 2092 | cpustate->CF = (dst & (1 << (16-shift))) ? 1 : 0; |
| 2053 | 2093 | dst = (dst << shift) | (upper >> (16-shift)); |
| 2094 | cpustate->OF = cpustate->CF ^ (dst >> 15); |
| 2054 | 2095 | SetSZPF16(dst); |
| 2055 | 2096 | } |
| 2056 | 2097 | STORE_RM16(modrm, dst); |
| r14729 | r14730 | |
| 2060 | 2101 | UINT16 dst = READ16(cpustate,ea); |
| 2061 | 2102 | UINT16 upper = LOAD_REG16(modrm); |
| 2062 | 2103 | UINT8 shift = REG8(CL); |
| 2063 | | if( shift > 31 || shift == 0 ) { |
| 2104 | shift &= 31; |
| 2105 | if( shift == 0 ) { |
| 2064 | 2106 | |
| 2065 | 2107 | } else if( shift > 15 ) { |
| 2066 | | cpustate->CF = (dst & (1 << (16-shift))) ? 1 : 0; |
| 2108 | cpustate->CF = (upper & (1 << (16-shift))) ? 1 : 0; |
| 2067 | 2109 | dst = (upper << (shift-16)) | (upper >> (32-shift)); |
| 2110 | cpustate->OF = cpustate->CF ^ (dst >> 15); |
| 2068 | 2111 | SetSZPF16(dst); |
| 2069 | 2112 | } else { |
| 2070 | 2113 | cpustate->CF = (dst & (1 << (16-shift))) ? 1 : 0; |
| 2071 | 2114 | dst = (dst << shift) | (upper >> (16-shift)); |
| 2115 | cpustate->OF = cpustate->CF ^ (dst >> 15); |
| 2072 | 2116 | SetSZPF16(dst); |
| 2073 | 2117 | } |
| 2074 | 2118 | WRITE16(cpustate,ea, dst); |
| r14729 | r14730 | |
| 2078 | 2122 | |
| 2079 | 2123 | static void I386OP(shrd16_i8)(i386_state *cpustate) // Opcode 0x0f ac |
| 2080 | 2124 | { |
| 2081 | | /* TODO: Correct flags */ |
| 2082 | 2125 | UINT8 modrm = FETCH(cpustate); |
| 2083 | 2126 | if( modrm >= 0xc0 ) { |
| 2084 | 2127 | UINT16 dst = LOAD_RM16(modrm); |
| 2085 | 2128 | UINT16 upper = LOAD_REG16(modrm); |
| 2086 | 2129 | UINT8 shift = FETCH(cpustate); |
| 2087 | | if( shift > 15 || shift == 0) { |
| 2130 | shift &= 31; |
| 2131 | if( shift == 0) { |
| 2088 | 2132 | |
| 2133 | } else if( shift > 15 ) { |
| 2134 | cpustate->CF = (upper & (1 << (shift-1))) ? 1 : 0; |
| 2135 | dst = (upper >> (shift-16)) | (upper << (32-shift)); |
| 2136 | cpustate->OF = ((dst >> 15) ^ (dst >> 14)) & 1; |
| 2137 | SetSZPF16(dst); |
| 2089 | 2138 | } else { |
| 2090 | 2139 | cpustate->CF = (dst & (1 << (shift-1))) ? 1 : 0; |
| 2091 | 2140 | dst = (dst >> shift) | (upper << (16-shift)); |
| 2141 | cpustate->OF = ((dst >> 15) ^ (dst >> 14)) & 1; |
| 2092 | 2142 | SetSZPF16(dst); |
| 2093 | 2143 | } |
| 2094 | 2144 | STORE_RM16(modrm, dst); |
| r14729 | r14730 | |
| 2098 | 2148 | UINT16 dst = READ16(cpustate,ea); |
| 2099 | 2149 | UINT16 upper = LOAD_REG16(modrm); |
| 2100 | 2150 | UINT8 shift = FETCH(cpustate); |
| 2101 | | if( shift > 15 || shift == 0) { |
| 2151 | shift &= 31; |
| 2152 | if( shift == 0) { |
| 2102 | 2153 | |
| 2154 | } else if( shift > 15 ) { |
| 2155 | cpustate->CF = (upper & (1 << (shift-1))) ? 1 : 0; |
| 2156 | dst = (upper >> (shift-16)) | (upper << (32-shift)); |
| 2157 | cpustate->OF = ((dst >> 15) ^ (dst >> 14)) & 1; |
| 2158 | SetSZPF16(dst); |
| 2103 | 2159 | } else { |
| 2104 | 2160 | cpustate->CF = (dst & (1 << (shift-1))) ? 1 : 0; |
| 2105 | 2161 | dst = (dst >> shift) | (upper << (16-shift)); |
| 2162 | cpustate->OF = ((dst >> 15) ^ (dst >> 14)) & 1; |
| 2106 | 2163 | SetSZPF16(dst); |
| 2107 | 2164 | } |
| 2108 | 2165 | WRITE16(cpustate,ea, dst); |
| r14729 | r14730 | |
| 2112 | 2169 | |
| 2113 | 2170 | static void I386OP(shrd16_cl)(i386_state *cpustate) // Opcode 0x0f ad |
| 2114 | 2171 | { |
| 2115 | | /* TODO: Correct flags */ |
| 2116 | 2172 | UINT8 modrm = FETCH(cpustate); |
| 2117 | 2173 | if( modrm >= 0xc0 ) { |
| 2118 | 2174 | UINT16 dst = LOAD_RM16(modrm); |
| 2119 | 2175 | UINT16 upper = LOAD_REG16(modrm); |
| 2120 | 2176 | UINT8 shift = REG8(CL); |
| 2121 | | if( shift > 15 || shift == 0) { |
| 2177 | shift &= 31; |
| 2178 | if( shift == 0) { |
| 2122 | 2179 | |
| 2180 | } else if( shift > 15 ) { |
| 2181 | cpustate->CF = (upper & (1 << (shift-1))) ? 1 : 0; |
| 2182 | dst = (upper >> (shift-16)) | (upper << (32-shift)); |
| 2183 | cpustate->OF = ((dst >> 15) ^ (dst >> 14)) & 1; |
| 2184 | SetSZPF16(dst); |
| 2123 | 2185 | } else { |
| 2124 | 2186 | cpustate->CF = (dst & (1 << (shift-1))) ? 1 : 0; |
| 2125 | 2187 | dst = (dst >> shift) | (upper << (16-shift)); |
| 2188 | cpustate->OF = ((dst >> 15) ^ (dst >> 14)) & 1; |
| 2126 | 2189 | SetSZPF16(dst); |
| 2127 | 2190 | } |
| 2128 | 2191 | STORE_RM16(modrm, dst); |
| r14729 | r14730 | |
| 2132 | 2195 | UINT16 dst = READ16(cpustate,ea); |
| 2133 | 2196 | UINT16 upper = LOAD_REG16(modrm); |
| 2134 | 2197 | UINT8 shift = REG8(CL); |
| 2135 | | if( shift > 15 || shift == 0) { |
| 2198 | shift &= 31; |
| 2199 | if( shift == 0) { |
| 2136 | 2200 | |
| 2201 | } else if( shift > 15 ) { |
| 2202 | cpustate->CF = (upper & (1 << (shift-1))) ? 1 : 0; |
| 2203 | dst = (upper >> (shift-16)) | (upper << (32-shift)); |
| 2204 | cpustate->OF = ((dst >> 15) ^ (dst >> 14)) & 1; |
| 2205 | SetSZPF16(dst); |
| 2137 | 2206 | } else { |
| 2138 | 2207 | cpustate->CF = (dst & (1 << (shift-1))) ? 1 : 0; |
| 2139 | 2208 | dst = (dst >> shift) | (upper << (16-shift)); |
| 2209 | cpustate->OF = ((dst >> 15) ^ (dst >> 14)) & 1; |
| 2140 | 2210 | SetSZPF16(dst); |
| 2141 | 2211 | } |
| 2142 | 2212 | WRITE16(cpustate,ea, dst); |
| r14729 | r14730 | |
| 2823 | 2893 | cpustate->CF = 1; |
| 2824 | 2894 | } |
| 2825 | 2895 | } else { |
| 2826 | | cpustate->ext = 0; |
| 2827 | 2896 | i386_trap(cpustate, 0, 0, 0); |
| 2828 | | cpustate->ext = 1; |
| 2829 | 2897 | } |
| 2830 | 2898 | } |
| 2831 | 2899 | break; |
| r14729 | r14730 | |
| 2857 | 2925 | cpustate->CF = 1; |
| 2858 | 2926 | } |
| 2859 | 2927 | } else { |
| 2860 | | cpustate->ext = 0; |
| 2861 | 2928 | i386_trap(cpustate, 0, 0, 0); |
| 2862 | | cpustate->ext = 1; |
| 2863 | 2929 | } |
| 2864 | 2930 | } |
| 2865 | 2931 | break; |
| r14729 | r14730 | |
| 3072 | 3138 | } |
| 3073 | 3139 | memset(&seg, 0, sizeof(seg)); |
| 3074 | 3140 | seg.selector = cpustate->ldtr.segment; |
| 3075 | | i386_load_protected_mode_segment(cpustate,&seg); |
| 3141 | i386_load_protected_mode_segment(cpustate,&seg,NULL); |
| 3076 | 3142 | cpustate->ldtr.limit = seg.limit; |
| 3077 | 3143 | cpustate->ldtr.base = seg.base; |
| 3078 | 3144 | cpustate->ldtr.flags = seg.flags; |
| r14729 | r14730 | |
| 3099 | 3165 | } |
| 3100 | 3166 | memset(&seg, 0, sizeof(seg)); |
| 3101 | 3167 | seg.selector = cpustate->task.segment; |
| 3102 | | i386_load_protected_mode_segment(cpustate,&seg); |
| 3168 | i386_load_protected_mode_segment(cpustate,&seg,NULL); |
| 3103 | 3169 | cpustate->task.limit = seg.limit; |
| 3104 | 3170 | cpustate->task.base = seg.base; |
| 3105 | 3171 | cpustate->task.flags = seg.flags; |
| r14729 | r14730 | |
| 3124 | 3190 | } |
| 3125 | 3191 | memset(&seg, 0, sizeof(seg)); |
| 3126 | 3192 | seg.selector = address; |
| 3127 | | i386_load_protected_mode_segment(cpustate,&seg); |
| 3128 | | // check if the segment is within the bounds of the GDT or LDT |
| 3129 | | if(seg.selector & 0x04) |
| 3130 | | { // LDT |
| 3131 | | if((seg.selector & 0xf8) > cpustate->ldtr.limit) |
| 3132 | | { |
| 3133 | | result = 0; |
| 3134 | | } |
| 3135 | | } |
| 3136 | | else |
| 3137 | | { // GDT |
| 3138 | | if((seg.selector & 0xf8) > cpustate->gdtr.limit) |
| 3139 | | { |
| 3140 | | result = 0; |
| 3141 | | } |
| 3142 | | } |
| 3193 | result = i386_load_protected_mode_segment(cpustate,&seg,NULL); |
| 3143 | 3194 | // check if the segment is a code or data segment (not a special segment type, like a TSS, gate, LDT...) |
| 3144 | 3195 | if(!(seg.flags & 0x10)) |
| 3145 | 3196 | result = 0; |
| r14729 | r14730 | |
| 3187 | 3238 | } |
| 3188 | 3239 | memset(&seg, 0, sizeof(seg)); |
| 3189 | 3240 | seg.selector = address; |
| 3190 | | i386_load_protected_mode_segment(cpustate,&seg); |
| 3191 | | // check if the segment is within the bounds of the GDT or LDT |
| 3192 | | if(seg.selector & 0x04) |
| 3193 | | { // LDT |
| 3194 | | if((seg.selector & 0xf8) > cpustate->ldtr.limit) |
| 3195 | | { |
| 3196 | | result = 0; |
| 3197 | | } |
| 3198 | | } |
| 3199 | | else |
| 3200 | | { // GDT |
| 3201 | | if((seg.selector & 0xf8) > cpustate->gdtr.limit) |
| 3202 | | { |
| 3203 | | result = 0; |
| 3204 | | } |
| 3205 | | } |
| 3241 | result = i386_load_protected_mode_segment(cpustate,&seg,NULL); |
| 3206 | 3242 | // check if the segment is a code or data segment (not a special segment type, like a TSS, gate, LDT...) |
| 3207 | 3243 | if(!(seg.flags & 0x10)) |
| 3208 | 3244 | result = 0; |
| r14729 | r14730 | |
| 3488 | 3524 | } |
| 3489 | 3525 | else |
| 3490 | 3526 | { |
| 3491 | | i386_load_protected_mode_segment(cpustate,&seg); |
| 3527 | if(!i386_load_protected_mode_segment(cpustate,&seg,NULL)) |
| 3528 | { |
| 3529 | SetZF(0); |
| 3530 | return; |
| 3531 | } |
| 3532 | if(((seg.flags >> 5) & 3) < cpustate->CPL) |
| 3533 | { |
| 3534 | SetZF(0); |
| 3535 | return; |
| 3536 | } |
| 3492 | 3537 | if(!(seg.flags & 0x10)) // special segment |
| 3493 | 3538 | { |
| 3494 | 3539 | // check for invalid segment types |
| r14729 | r14730 | |
| 3499 | 3544 | } |
| 3500 | 3545 | else |
| 3501 | 3546 | { |
| 3502 | | // TODO: check current privilege level |
| 3503 | 3547 | STORE_REG16(modrm,(seg.flags << 8) & 0xff00); |
| 3504 | 3548 | SetZF(1); |
| 3505 | 3549 | } |
| 3506 | 3550 | } |
| 3507 | 3551 | else |
| 3508 | 3552 | { // data or code segment (both are valid for LAR) |
| 3509 | | // TODO: check current privilege level |
| 3510 | 3553 | STORE_REG16(modrm,(seg.flags << 8) & 0xff00); |
| 3511 | 3554 | SetZF(1); |
| 3512 | 3555 | } |
| r14729 | r14730 | |
| 3544 | 3587 | } |
| 3545 | 3588 | else |
| 3546 | 3589 | { |
| 3547 | | // TODO: check segment type |
| 3548 | | i386_load_protected_mode_segment(cpustate,&seg); |
| 3549 | | limit = seg.limit; |
| 3550 | | STORE_REG16(modrm,limit & 0x0000ffff); |
| 3551 | | SetZF(1); |
| 3590 | UINT8 type; |
| 3591 | if(!i386_load_protected_mode_segment(cpustate,&seg,NULL)) |
| 3592 | { |
| 3593 | SetZF(0); |
| 3594 | return; |
| 3595 | } |
| 3596 | if(((seg.flags >> 5) & 3) < cpustate->CPL) |
| 3597 | { |
| 3598 | SetZF(0); |
| 3599 | return; |
| 3600 | } |
| 3601 | type = seg.flags & 0x1f; |
| 3602 | switch(type) |
| 3603 | { |
| 3604 | case 0: |
| 3605 | case 4: |
| 3606 | case 5: |
| 3607 | case 6: |
| 3608 | case 7: |
| 3609 | case 8: |
| 3610 | case 10: |
| 3611 | case 12: |
| 3612 | case 13: |
| 3613 | case 14: |
| 3614 | case 15: |
| 3615 | SetZF(0); |
| 3616 | return; |
| 3617 | default: |
| 3618 | limit = seg.limit; |
| 3619 | STORE_REG16(modrm,limit & 0x0000ffff); |
| 3620 | SetZF(1); |
| 3621 | } |
| 3552 | 3622 | } |
| 3553 | 3623 | } |
| 3554 | 3624 | else |
src/emu/cpu/i386/x87ops.c
| r14729 | r14730 | |
| 292 | 292 | |
| 293 | 293 | if ((cpustate->x87_sw & ~cpustate->x87_cw) & 0x3f) |
| 294 | 294 | { |
| 295 | | // TODO |
| 296 | | fatalerror("Unimplemented: unmasked x87 exception (CW:%.4x, SW:%.4x)", cpustate->x87_cw, cpustate->x87_sw); |
| 295 | // device_set_input_line(cpustate->device, INPUT_LINE_FERR, RAISE_LINE); |
| 296 | logerror("Unmasked x87 exception (CW:%.4x, SW:%.4x)\n", cpustate->x87_cw, cpustate->x87_sw); |
| 297 | if (cpustate->cr[0] & 0x20) // FIXME: 486 and up only |
| 298 | { |
| 299 | cpustate->ext = 1; |
| 300 | i386_trap(cpustate, FAULT_MF, 0, 0); |
| 301 | } |
| 297 | 302 | return 0; |
| 298 | 303 | } |
| 299 | 304 | |
| r14729 | r14730 | |
| 465 | 470 | { |
| 466 | 471 | floatx80 result; |
| 467 | 472 | |
| 473 | UINT32 ea = GetEA(cpustate, modrm, 0); |
| 468 | 474 | if (X87_IS_ST_EMPTY(0)) |
| 469 | 475 | { |
| 470 | 476 | x87_set_stack_underflow(cpustate); |
| r14729 | r14730 | |
| 472 | 478 | } |
| 473 | 479 | else |
| 474 | 480 | { |
| 475 | | UINT32 ea = GetEA(cpustate, modrm, 0); |
| 476 | 481 | UINT32 m32real = READ32(cpustate, ea); |
| 477 | 482 | |
| 478 | 483 | floatx80 a = ST(0); |
| r14729 | r14730 | |
| 500 | 505 | { |
| 501 | 506 | floatx80 result; |
| 502 | 507 | |
| 508 | UINT32 ea = GetEA(cpustate, modrm, 0); |
| 503 | 509 | if (X87_IS_ST_EMPTY(0)) |
| 504 | 510 | { |
| 505 | 511 | x87_set_stack_underflow(cpustate); |
| r14729 | r14730 | |
| 507 | 513 | } |
| 508 | 514 | else |
| 509 | 515 | { |
| 510 | | UINT32 ea = GetEA(cpustate, modrm, 0); |
| 511 | 516 | UINT64 m64real = READ64(cpustate, ea); |
| 512 | 517 | |
| 513 | 518 | floatx80 a = ST(0); |
| r14729 | r14730 | |
| 637 | 642 | { |
| 638 | 643 | floatx80 result; |
| 639 | 644 | |
| 645 | UINT32 ea = GetEA(cpustate, modrm, 0); |
| 640 | 646 | if (X87_IS_ST_EMPTY(0)) |
| 641 | 647 | { |
| 642 | 648 | x87_set_stack_underflow(cpustate); |
| r14729 | r14730 | |
| 644 | 650 | } |
| 645 | 651 | else |
| 646 | 652 | { |
| 647 | | UINT32 ea = GetEA(cpustate, modrm, 0); |
| 648 | 653 | INT32 m32int = READ32(cpustate, ea); |
| 649 | 654 | |
| 650 | 655 | floatx80 a = ST(0); |
| r14729 | r14730 | |
| 672 | 677 | { |
| 673 | 678 | floatx80 result; |
| 674 | 679 | |
| 680 | UINT32 ea = GetEA(cpustate, modrm, 0); |
| 675 | 681 | if (X87_IS_ST_EMPTY(0)) |
| 676 | 682 | { |
| 677 | 683 | x87_set_stack_underflow(cpustate); |
| r14729 | r14730 | |
| 679 | 685 | } |
| 680 | 686 | else |
| 681 | 687 | { |
| 682 | | UINT32 ea = GetEA(cpustate, modrm, 0); |
| 683 | 688 | INT16 m16int = READ16(cpustate, ea); |
| 684 | 689 | |
| 685 | 690 | floatx80 a = ST(0); |
| r14729 | r14730 | |
| 714 | 719 | { |
| 715 | 720 | floatx80 result; |
| 716 | 721 | |
| 722 | UINT32 ea = GetEA(cpustate, modrm, 0); |
| 717 | 723 | if (X87_IS_ST_EMPTY(0)) |
| 718 | 724 | { |
| 719 | 725 | x87_set_stack_underflow(cpustate); |
| r14729 | r14730 | |
| 721 | 727 | } |
| 722 | 728 | else |
| 723 | 729 | { |
| 724 | | UINT32 ea = GetEA(cpustate, modrm, 0); |
| 725 | 730 | UINT32 m32real = READ32(cpustate, ea); |
| 726 | 731 | |
| 727 | 732 | floatx80 a = ST(0); |
| r14729 | r14730 | |
| 749 | 754 | { |
| 750 | 755 | floatx80 result; |
| 751 | 756 | |
| 757 | UINT32 ea = GetEA(cpustate, modrm, 0); |
| 752 | 758 | if (X87_IS_ST_EMPTY(0)) |
| 753 | 759 | { |
| 754 | 760 | x87_set_stack_underflow(cpustate); |
| r14729 | r14730 | |
| 756 | 762 | } |
| 757 | 763 | else |
| 758 | 764 | { |
| 759 | | UINT32 ea = GetEA(cpustate, modrm, 0); |
| 760 | 765 | UINT64 m64real = READ64(cpustate, ea); |
| 761 | 766 | |
| 762 | 767 | floatx80 a = ST(0); |
| r14729 | r14730 | |
| 886 | 891 | { |
| 887 | 892 | floatx80 result; |
| 888 | 893 | |
| 894 | UINT32 ea = GetEA(cpustate, modrm, 0); |
| 889 | 895 | if (X87_IS_ST_EMPTY(0)) |
| 890 | 896 | { |
| 891 | 897 | x87_set_stack_underflow(cpustate); |
| r14729 | r14730 | |
| 893 | 899 | } |
| 894 | 900 | else |
| 895 | 901 | { |
| 896 | | UINT32 ea = GetEA(cpustate, modrm, 0); |
| 897 | 902 | INT32 m32int = READ32(cpustate, ea); |
| 898 | 903 | |
| 899 | 904 | floatx80 a = ST(0); |
| r14729 | r14730 | |
| 921 | 926 | { |
| 922 | 927 | floatx80 result; |
| 923 | 928 | |
| 929 | UINT32 ea = GetEA(cpustate, modrm, 0); |
| 924 | 930 | if (X87_IS_ST_EMPTY(0)) |
| 925 | 931 | { |
| 926 | 932 | x87_set_stack_underflow(cpustate); |
| r14729 | r14730 | |
| 928 | 934 | } |
| 929 | 935 | else |
| 930 | 936 | { |
| 931 | | UINT32 ea = GetEA(cpustate, modrm, 0); |
| 932 | 937 | INT16 m16int = READ16(cpustate, ea); |
| 933 | 938 | |
| 934 | 939 | floatx80 a = ST(0); |
| r14729 | r14730 | |
| 963 | 968 | { |
| 964 | 969 | floatx80 result; |
| 965 | 970 | |
| 971 | UINT32 ea = GetEA(cpustate, modrm, 0); |
| 966 | 972 | if (X87_IS_ST_EMPTY(0)) |
| 967 | 973 | { |
| 968 | 974 | x87_set_stack_underflow(cpustate); |
| r14729 | r14730 | |
| 970 | 976 | } |
| 971 | 977 | else |
| 972 | 978 | { |
| 973 | | UINT32 ea = GetEA(cpustate, modrm, 0); |
| 974 | 979 | UINT32 m32real = READ32(cpustate, ea); |
| 975 | 980 | |
| 976 | 981 | floatx80 a = float32_to_floatx80(m32real); |
| r14729 | r14730 | |
| 998 | 1003 | { |
| 999 | 1004 | floatx80 result; |
| 1000 | 1005 | |
| 1006 | UINT32 ea = GetEA(cpustate, modrm, 0); |
| 1001 | 1007 | if (X87_IS_ST_EMPTY(0)) |
| 1002 | 1008 | { |
| 1003 | 1009 | x87_set_stack_underflow(cpustate); |
| r14729 | r14730 | |
| 1005 | 1011 | } |
| 1006 | 1012 | else |
| 1007 | 1013 | { |
| 1008 | | UINT32 ea = GetEA(cpustate, modrm, 0); |
| 1009 | 1014 | UINT64 m64real = READ64(cpustate, ea); |
| 1010 | 1015 | |
| 1011 | 1016 | floatx80 a = float64_to_floatx80(m64real); |
| r14729 | r14730 | |
| 1135 | 1140 | { |
| 1136 | 1141 | floatx80 result; |
| 1137 | 1142 | |
| 1143 | UINT32 ea = GetEA(cpustate, modrm, 0); |
| 1138 | 1144 | if (X87_IS_ST_EMPTY(0)) |
| 1139 | 1145 | { |
| 1140 | 1146 | x87_set_stack_underflow(cpustate); |
| r14729 | r14730 | |
| 1142 | 1148 | } |
| 1143 | 1149 | else |
| 1144 | 1150 | { |
| 1145 | | UINT32 ea = GetEA(cpustate, modrm, 0); |
| 1146 | 1151 | INT32 m32int = READ32(cpustate, ea); |
| 1147 | 1152 | |
| 1148 | 1153 | floatx80 a = int32_to_floatx80(m32int); |
| r14729 | r14730 | |
| 1170 | 1175 | { |
| 1171 | 1176 | floatx80 result; |
| 1172 | 1177 | |
| 1178 | UINT32 ea = GetEA(cpustate, modrm, 0); |
| 1173 | 1179 | if (X87_IS_ST_EMPTY(0)) |
| 1174 | 1180 | { |
| 1175 | 1181 | x87_set_stack_underflow(cpustate); |
| r14729 | r14730 | |
| 1177 | 1183 | } |
| 1178 | 1184 | else |
| 1179 | 1185 | { |
| 1180 | | UINT32 ea = GetEA(cpustate, modrm, 0); |
| 1181 | 1186 | INT16 m16int = READ16(cpustate, ea); |
| 1182 | 1187 | |
| 1183 | 1188 | floatx80 a = int32_to_floatx80(m16int); |
| r14729 | r14730 | |
| 1212 | 1217 | { |
| 1213 | 1218 | floatx80 result; |
| 1214 | 1219 | |
| 1220 | UINT32 ea = GetEA(cpustate, modrm, 0); |
| 1215 | 1221 | if (X87_IS_ST_EMPTY(0)) |
| 1216 | 1222 | { |
| 1217 | 1223 | x87_set_stack_underflow(cpustate); |
| r14729 | r14730 | |
| 1219 | 1225 | } |
| 1220 | 1226 | else |
| 1221 | 1227 | { |
| 1222 | | UINT32 ea = GetEA(cpustate, modrm, 0); |
| 1223 | 1228 | UINT32 m32real = READ32(cpustate, ea); |
| 1224 | 1229 | |
| 1225 | 1230 | floatx80 a = ST(0); |
| r14729 | r14730 | |
| 1247 | 1252 | { |
| 1248 | 1253 | floatx80 result; |
| 1249 | 1254 | |
| 1255 | UINT32 ea = GetEA(cpustate, modrm, 0); |
| 1250 | 1256 | if (X87_IS_ST_EMPTY(0)) |
| 1251 | 1257 | { |
| 1252 | 1258 | x87_set_stack_underflow(cpustate); |
| r14729 | r14730 | |
| 1254 | 1260 | } |
| 1255 | 1261 | else |
| 1256 | 1262 | { |
| 1257 | | UINT32 ea = GetEA(cpustate, modrm, 0); |
| 1258 | 1263 | UINT64 m64real = READ64(cpustate, ea); |
| 1259 | 1264 | |
| 1260 | 1265 | floatx80 a = ST(0); |
| r14729 | r14730 | |
| 1388 | 1393 | { |
| 1389 | 1394 | floatx80 result; |
| 1390 | 1395 | |
| 1396 | UINT32 ea = GetEA(cpustate, modrm, 0); |
| 1391 | 1397 | if (X87_IS_ST_EMPTY(0)) |
| 1392 | 1398 | { |
| 1393 | 1399 | x87_set_stack_underflow(cpustate); |
| r14729 | r14730 | |
| 1395 | 1401 | } |
| 1396 | 1402 | else |
| 1397 | 1403 | { |
| 1398 | | UINT32 ea = GetEA(cpustate, modrm, 0); |
| 1399 | 1404 | INT32 m32int = READ32(cpustate, ea); |
| 1400 | 1405 | |
| 1401 | 1406 | floatx80 a = ST(0); |
| r14729 | r14730 | |
| 1423 | 1428 | { |
| 1424 | 1429 | floatx80 result; |
| 1425 | 1430 | |
| 1431 | UINT32 ea = GetEA(cpustate, modrm, 0); |
| 1426 | 1432 | if (X87_IS_ST_EMPTY(0)) |
| 1427 | 1433 | { |
| 1428 | 1434 | x87_set_stack_underflow(cpustate); |
| r14729 | r14730 | |
| 1430 | 1436 | } |
| 1431 | 1437 | else |
| 1432 | 1438 | { |
| 1433 | | UINT32 ea = GetEA(cpustate, modrm, 0); |
| 1434 | 1439 | INT16 m16int = READ32(cpustate, ea); |
| 1435 | 1440 | |
| 1436 | 1441 | floatx80 a = ST(0); |
| r14729 | r14730 | |
| 1465 | 1470 | { |
| 1466 | 1471 | floatx80 result; |
| 1467 | 1472 | |
| 1473 | UINT32 ea = GetEA(cpustate, modrm, 0); |
| 1468 | 1474 | if (X87_IS_ST_EMPTY(0)) |
| 1469 | 1475 | { |
| 1470 | 1476 | x87_set_stack_underflow(cpustate); |
| r14729 | r14730 | |
| 1472 | 1478 | } |
| 1473 | 1479 | else |
| 1474 | 1480 | { |
| 1475 | | UINT32 ea = GetEA(cpustate, modrm, 0); |
| 1476 | 1481 | UINT32 m32real = READ32(cpustate, ea); |
| 1477 | 1482 | |
| 1478 | 1483 | floatx80 a = float32_to_floatx80(m32real); |
| r14729 | r14730 | |
| 1500 | 1505 | { |
| 1501 | 1506 | floatx80 result; |
| 1502 | 1507 | |
| 1508 | UINT32 ea = GetEA(cpustate, modrm, 0); |
| 1503 | 1509 | if (X87_IS_ST_EMPTY(0)) |
| 1504 | 1510 | { |
| 1505 | 1511 | x87_set_stack_underflow(cpustate); |
| r14729 | r14730 | |
| 1507 | 1513 | } |
| 1508 | 1514 | else |
| 1509 | 1515 | { |
| 1510 | | UINT32 ea = GetEA(cpustate, modrm, 0); |
| 1511 | 1516 | UINT64 m64real = READ64(cpustate, ea); |
| 1512 | 1517 | |
| 1513 | 1518 | floatx80 a = float64_to_floatx80(m64real); |
| r14729 | r14730 | |
| 1642 | 1647 | { |
| 1643 | 1648 | floatx80 result; |
| 1644 | 1649 | |
| 1650 | UINT32 ea = GetEA(cpustate, modrm, 0); |
| 1645 | 1651 | if (X87_IS_ST_EMPTY(0)) |
| 1646 | 1652 | { |
| 1647 | 1653 | x87_set_stack_underflow(cpustate); |
| r14729 | r14730 | |
| 1649 | 1655 | } |
| 1650 | 1656 | else |
| 1651 | 1657 | { |
| 1652 | | UINT32 ea = GetEA(cpustate, modrm, 0); |
| 1653 | 1658 | INT32 m32int = READ32(cpustate, ea); |
| 1654 | 1659 | |
| 1655 | 1660 | floatx80 a = int32_to_floatx80(m32int); |
| r14729 | r14730 | |
| 1677 | 1682 | { |
| 1678 | 1683 | floatx80 result; |
| 1679 | 1684 | |
| 1685 | UINT32 ea = GetEA(cpustate, modrm, 0); |
| 1680 | 1686 | if (X87_IS_ST_EMPTY(0)) |
| 1681 | 1687 | { |
| 1682 | 1688 | x87_set_stack_underflow(cpustate); |
| r14729 | r14730 | |
| 1684 | 1690 | } |
| 1685 | 1691 | else |
| 1686 | 1692 | { |
| 1687 | | UINT32 ea = GetEA(cpustate, modrm, 0); |
| 1688 | 1693 | INT16 m16int = READ32(cpustate, ea); |
| 1689 | 1694 | |
| 1690 | 1695 | floatx80 a = int32_to_floatx80(m16int); |
| r14729 | r14730 | |
| 1719 | 1724 | { |
| 1720 | 1725 | floatx80 result; |
| 1721 | 1726 | |
| 1727 | UINT32 ea = GetEA(cpustate, modrm, 0); |
| 1722 | 1728 | if (X87_IS_ST_EMPTY(0)) |
| 1723 | 1729 | { |
| 1724 | 1730 | x87_set_stack_underflow(cpustate); |
| r14729 | r14730 | |
| 1726 | 1732 | } |
| 1727 | 1733 | else |
| 1728 | 1734 | { |
| 1729 | | UINT32 ea = GetEA(cpustate, modrm, 0); |
| 1730 | 1735 | UINT32 m32real = READ32(cpustate, ea); |
| 1731 | 1736 | |
| 1732 | 1737 | floatx80 a = ST(0); |
| r14729 | r14730 | |
| 1753 | 1758 | { |
| 1754 | 1759 | floatx80 result; |
| 1755 | 1760 | |
| 1761 | UINT32 ea = GetEA(cpustate, modrm, 0); |
| 1756 | 1762 | if (X87_IS_ST_EMPTY(0)) |
| 1757 | 1763 | { |
| 1758 | 1764 | x87_set_stack_underflow(cpustate); |
| r14729 | r14730 | |
| 1760 | 1766 | } |
| 1761 | 1767 | else |
| 1762 | 1768 | { |
| 1763 | | UINT32 ea = GetEA(cpustate, modrm, 0); |
| 1764 | 1769 | UINT64 m64real = READ64(cpustate, ea); |
| 1765 | 1770 | |
| 1766 | 1771 | floatx80 a = ST(0); |
| r14729 | r14730 | |
| 1886 | 1891 | { |
| 1887 | 1892 | floatx80 result; |
| 1888 | 1893 | |
| 1894 | UINT32 ea = GetEA(cpustate, modrm, 0); |
| 1889 | 1895 | if (X87_IS_ST_EMPTY(0)) |
| 1890 | 1896 | { |
| 1891 | 1897 | x87_set_stack_underflow(cpustate); |
| r14729 | r14730 | |
| 1893 | 1899 | } |
| 1894 | 1900 | else |
| 1895 | 1901 | { |
| 1896 | | UINT32 ea = GetEA(cpustate, modrm, 0); |
| 1897 | 1902 | INT32 m32int = READ32(cpustate, ea); |
| 1898 | 1903 | |
| 1899 | 1904 | floatx80 a = ST(0); |
| r14729 | r14730 | |
| 1920 | 1925 | { |
| 1921 | 1926 | floatx80 result; |
| 1922 | 1927 | |
| 1928 | UINT32 ea = GetEA(cpustate, modrm, 0); |
| 1923 | 1929 | if (X87_IS_ST_EMPTY(0)) |
| 1924 | 1930 | { |
| 1925 | 1931 | x87_set_stack_underflow(cpustate); |
| r14729 | r14730 | |
| 1927 | 1933 | } |
| 1928 | 1934 | else |
| 1929 | 1935 | { |
| 1930 | | UINT32 ea = GetEA(cpustate, modrm, 0); |
| 1931 | 1936 | INT16 m16int = READ16(cpustate, ea); |
| 1932 | 1937 | |
| 1933 | 1938 | floatx80 a = ST(0); |
| r14729 | r14730 | |
| 2332 | 2337 | { |
| 2333 | 2338 | floatx80 value; |
| 2334 | 2339 | |
| 2340 | UINT32 ea = GetEA(cpustate, modrm, 0); |
| 2335 | 2341 | if (x87_dec_stack(cpustate)) |
| 2336 | 2342 | { |
| 2337 | | UINT32 ea = GetEA(cpustate, modrm, 0); |
| 2338 | 2343 | UINT32 m32real = READ32(cpustate, ea); |
| 2339 | 2344 | |
| 2340 | 2345 | value = float32_to_floatx80(m32real); |
| r14729 | r14730 | |
| 2362 | 2367 | { |
| 2363 | 2368 | floatx80 value; |
| 2364 | 2369 | |
| 2370 | UINT32 ea = GetEA(cpustate, modrm, 0); |
| 2365 | 2371 | if (x87_dec_stack(cpustate)) |
| 2366 | 2372 | { |
| 2367 | | UINT32 ea = GetEA(cpustate, modrm, 0); |
| 2368 | 2373 | UINT64 m64real = READ64(cpustate, ea); |
| 2369 | 2374 | |
| 2370 | 2375 | value = float64_to_floatx80(m64real); |
| r14729 | r14730 | |
| 2392 | 2397 | { |
| 2393 | 2398 | floatx80 value; |
| 2394 | 2399 | |
| 2400 | UINT32 ea = GetEA(cpustate, modrm, 0); |
| 2395 | 2401 | if (x87_dec_stack(cpustate)) |
| 2396 | 2402 | { |
| 2397 | 2403 | cpustate->x87_sw &= ~X87_SW_C1; |
| 2398 | | UINT32 ea = GetEA(cpustate, modrm, 0); |
| 2399 | 2404 | value = READ80(cpustate, ea); |
| 2400 | 2405 | } |
| 2401 | 2406 | else |
| r14729 | r14730 | |
| 2433 | 2438 | { |
| 2434 | 2439 | floatx80 value; |
| 2435 | 2440 | |
| 2441 | UINT32 ea = GetEA(cpustate, modrm, 0); |
| 2436 | 2442 | if (!x87_dec_stack(cpustate)) |
| 2437 | 2443 | { |
| 2438 | 2444 | value = fx80_inan; |
| r14729 | r14730 | |
| 2441 | 2447 | { |
| 2442 | 2448 | cpustate->x87_sw &= ~X87_SW_C1; |
| 2443 | 2449 | |
| 2444 | | UINT32 ea = GetEA(cpustate, modrm, 0); |
| 2445 | 2450 | INT16 m16int = READ16(cpustate, ea); |
| 2446 | 2451 | value = int32_to_floatx80(m16int); |
| 2447 | 2452 | } |
| r14729 | r14730 | |
| 2456 | 2461 | { |
| 2457 | 2462 | floatx80 value; |
| 2458 | 2463 | |
| 2464 | UINT32 ea = GetEA(cpustate, modrm, 0); |
| 2459 | 2465 | if (!x87_dec_stack(cpustate)) |
| 2460 | 2466 | { |
| 2461 | 2467 | value = fx80_inan; |
| r14729 | r14730 | |
| 2464 | 2470 | { |
| 2465 | 2471 | cpustate->x87_sw &= ~X87_SW_C1; |
| 2466 | 2472 | |
| 2467 | | UINT32 ea = GetEA(cpustate, modrm, 0); |
| 2468 | 2473 | INT32 m32int = READ32(cpustate, ea); |
| 2469 | 2474 | value = int32_to_floatx80(m32int); |
| 2470 | 2475 | } |
| r14729 | r14730 | |
| 2479 | 2484 | { |
| 2480 | 2485 | floatx80 value; |
| 2481 | 2486 | |
| 2487 | UINT32 ea = GetEA(cpustate, modrm, 0); |
| 2482 | 2488 | if (!x87_dec_stack(cpustate)) |
| 2483 | 2489 | { |
| 2484 | 2490 | value = fx80_inan; |
| r14729 | r14730 | |
| 2487 | 2493 | { |
| 2488 | 2494 | cpustate->x87_sw &= ~X87_SW_C1; |
| 2489 | 2495 | |
| 2490 | | UINT32 ea = GetEA(cpustate, modrm, 0); |
| 2491 | 2496 | INT64 m64int = READ64(cpustate, ea); |
| 2492 | 2497 | value = int64_to_floatx80(m64int); |
| 2493 | 2498 | } |
| r14729 | r14730 | |
| 2502 | 2507 | { |
| 2503 | 2508 | floatx80 value; |
| 2504 | 2509 | |
| 2510 | UINT32 ea = GetEA(cpustate, modrm, 0); |
| 2505 | 2511 | if (!x87_dec_stack(cpustate)) |
| 2506 | 2512 | { |
| 2507 | 2513 | value = fx80_inan; |
| r14729 | r14730 | |
| 2510 | 2516 | { |
| 2511 | 2517 | cpustate->x87_sw &= ~X87_SW_C1; |
| 2512 | 2518 | |
| 2513 | | UINT32 ea = GetEA(cpustate, modrm, 0); |
| 2514 | 2519 | UINT64 m64val = 0; |
| 2515 | 2520 | UINT16 sign; |
| 2516 | 2521 | |
| r14729 | r14730 | |
| 2547 | 2552 | { |
| 2548 | 2553 | floatx80 value; |
| 2549 | 2554 | |
| 2555 | UINT32 ea = GetEA(cpustate, modrm, 1); |
| 2550 | 2556 | if (X87_IS_ST_EMPTY(0)) |
| 2551 | 2557 | { |
| 2552 | 2558 | x87_set_stack_underflow(cpustate); |
| r14729 | r14730 | |
| 2561 | 2567 | if (x87_check_exceptions(cpustate)) |
| 2562 | 2568 | { |
| 2563 | 2569 | UINT32 m32real = floatx80_to_float32(value); |
| 2564 | | UINT32 ea = GetEA(cpustate, modrm, 1); |
| 2565 | 2570 | WRITE32(cpustate, ea, m32real); |
| 2566 | 2571 | } |
| 2567 | 2572 | |
| r14729 | r14730 | |
| 2572 | 2577 | { |
| 2573 | 2578 | floatx80 value; |
| 2574 | 2579 | |
| 2580 | UINT32 ea = GetEA(cpustate, modrm, 1); |
| 2575 | 2581 | if (X87_IS_ST_EMPTY(0)) |
| 2576 | 2582 | { |
| 2577 | 2583 | x87_set_stack_underflow(cpustate); |
| r14729 | r14730 | |
| 2586 | 2592 | if (x87_check_exceptions(cpustate)) |
| 2587 | 2593 | { |
| 2588 | 2594 | UINT64 m64real = floatx80_to_float64(value); |
| 2589 | | UINT32 ea = GetEA(cpustate, modrm, 1); |
| 2590 | 2595 | WRITE64(cpustate, ea, m64real); |
| 2591 | 2596 | } |
| 2592 | 2597 | |
| r14729 | r14730 | |
| 2619 | 2624 | { |
| 2620 | 2625 | floatx80 value; |
| 2621 | 2626 | |
| 2627 | UINT32 ea = GetEA(cpustate, modrm, 1); |
| 2622 | 2628 | if (X87_IS_ST_EMPTY(0)) |
| 2623 | 2629 | { |
| 2624 | 2630 | x87_set_stack_underflow(cpustate); |
| r14729 | r14730 | |
| 2633 | 2639 | if (x87_check_exceptions(cpustate)) |
| 2634 | 2640 | { |
| 2635 | 2641 | UINT32 m32real = floatx80_to_float32(value); |
| 2636 | | UINT32 ea = GetEA(cpustate, modrm, 1); |
| 2637 | 2642 | WRITE32(cpustate, ea, m32real); |
| 2638 | 2643 | x87_inc_stack(cpustate); |
| 2639 | 2644 | } |
| r14729 | r14730 | |
| 2657 | 2662 | } |
| 2658 | 2663 | |
| 2659 | 2664 | |
| 2665 | UINT32 ea = GetEA(cpustate, modrm, 1); |
| 2660 | 2666 | if (x87_check_exceptions(cpustate)) |
| 2661 | 2667 | { |
| 2662 | 2668 | UINT64 m64real = floatx80_to_float64(value); |
| 2663 | | UINT32 ea = GetEA(cpustate, modrm, 1); |
| 2664 | 2669 | WRITE64(cpustate, ea, m64real); |
| 2665 | 2670 | x87_inc_stack(cpustate); |
| 2666 | 2671 | } |
| r14729 | r14730 | |
| 2683 | 2688 | value = ST(0); |
| 2684 | 2689 | } |
| 2685 | 2690 | |
| 2691 | UINT32 ea = GetEA(cpustate, modrm, 1); |
| 2686 | 2692 | if (x87_check_exceptions(cpustate)) |
| 2687 | 2693 | { |
| 2688 | | UINT32 ea = GetEA(cpustate, modrm, 1); |
| 2689 | 2694 | WRITE80(cpustate, ea, value); |
| 2690 | 2695 | x87_inc_stack(cpustate); |
| 2691 | 2696 | } |
| r14729 | r14730 | |
| 2742 | 2747 | m16int = -32768; |
| 2743 | 2748 | } |
| 2744 | 2749 | |
| 2750 | UINT32 ea = GetEA(cpustate, modrm, 1); |
| 2745 | 2751 | if (x87_check_exceptions(cpustate)) |
| 2746 | 2752 | { |
| 2747 | | UINT32 ea = GetEA(cpustate, modrm, 1); |
| 2748 | 2753 | WRITE16(cpustate, ea, m16int); |
| 2749 | 2754 | } |
| 2750 | 2755 | |
| r14729 | r14730 | |
| 2775 | 2780 | m32int = 0x80000000; |
| 2776 | 2781 | } |
| 2777 | 2782 | |
| 2783 | UINT32 ea = GetEA(cpustate, modrm, 1); |
| 2778 | 2784 | if (x87_check_exceptions(cpustate)) |
| 2779 | 2785 | { |
| 2780 | | UINT32 ea = GetEA(cpustate, modrm, 1); |
| 2781 | 2786 | WRITE32(cpustate, ea, m32int); |
| 2782 | 2787 | } |
| 2783 | 2788 | |
| r14729 | r14730 | |
| 2808 | 2813 | m16int = (UINT16)0x8000; |
| 2809 | 2814 | } |
| 2810 | 2815 | |
| 2816 | UINT32 ea = GetEA(cpustate, modrm, 1); |
| 2811 | 2817 | if (x87_check_exceptions(cpustate)) |
| 2812 | 2818 | { |
| 2813 | | UINT32 ea = GetEA(cpustate, modrm, 1); |
| 2814 | 2819 | WRITE16(cpustate, ea, m16int); |
| 2815 | 2820 | x87_inc_stack(cpustate); |
| 2816 | 2821 | } |
| r14729 | r14730 | |
| 2842 | 2847 | m32int = 0x80000000; |
| 2843 | 2848 | } |
| 2844 | 2849 | |
| 2850 | UINT32 ea = GetEA(cpustate, modrm, 1); |
| 2845 | 2851 | if (x87_check_exceptions(cpustate)) |
| 2846 | 2852 | { |
| 2847 | | UINT32 ea = GetEA(cpustate, modrm, 1); |
| 2848 | 2853 | WRITE32(cpustate, ea, m32int); |
| 2849 | 2854 | x87_inc_stack(cpustate); |
| 2850 | 2855 | } |
| r14729 | r14730 | |
| 2876 | 2881 | m64int = U64(0x8000000000000000); |
| 2877 | 2882 | } |
| 2878 | 2883 | |
| 2884 | UINT32 ea = GetEA(cpustate, modrm, 1); |
| 2879 | 2885 | if (x87_check_exceptions(cpustate)) |
| 2880 | 2886 | { |
| 2881 | | UINT32 ea = GetEA(cpustate, modrm, 1); |
| 2882 | 2887 | WRITE64(cpustate, ea, m64int); |
| 2883 | 2888 | x87_inc_stack(cpustate); |
| 2884 | 2889 | } |
| r14729 | r14730 | |
| 2911 | 2916 | result.high |= ST(0).high & 0x8000; |
| 2912 | 2917 | } |
| 2913 | 2918 | |
| 2919 | UINT32 ea = GetEA(cpustate, modrm, 1); |
| 2914 | 2920 | if (x87_check_exceptions(cpustate)) |
| 2915 | 2921 | { |
| 2916 | | UINT32 ea = GetEA(cpustate, modrm, 1); |
| 2917 | 2922 | WRITE80(cpustate, ea, result); |
| 2918 | 2923 | x87_inc_stack(cpustate); |
| 2919 | 2924 | } |
| r14729 | r14730 | |
| 3385 | 3390 | |
| 3386 | 3391 | void x87_ficom_m16int(i386_state *cpustate, UINT8 modrm) |
| 3387 | 3392 | { |
| 3393 | UINT32 ea = GetEA(cpustate, modrm, 0); |
| 3388 | 3394 | if (X87_IS_ST_EMPTY(0)) |
| 3389 | 3395 | { |
| 3390 | 3396 | x87_set_stack_underflow(cpustate); |
| r14729 | r14730 | |
| 3394 | 3400 | { |
| 3395 | 3401 | cpustate->x87_sw &= ~(X87_SW_C3 | X87_SW_C2 | X87_SW_C1 | X87_SW_C0); |
| 3396 | 3402 | |
| 3397 | | UINT32 ea = GetEA(cpustate, modrm, 0); |
| 3398 | 3403 | INT16 m16int = READ16(cpustate, ea); |
| 3399 | 3404 | |
| 3400 | 3405 | floatx80 a = ST(0); |
| r14729 | r14730 | |
| 3422 | 3427 | |
| 3423 | 3428 | void x87_ficom_m32int(i386_state *cpustate, UINT8 modrm) |
| 3424 | 3429 | { |
| 3430 | UINT32 ea = GetEA(cpustate, modrm, 0); |
| 3425 | 3431 | if (X87_IS_ST_EMPTY(0)) |
| 3426 | 3432 | { |
| 3427 | 3433 | x87_set_stack_underflow(cpustate); |
| r14729 | r14730 | |
| 3431 | 3437 | { |
| 3432 | 3438 | cpustate->x87_sw &= ~(X87_SW_C3 | X87_SW_C2 | X87_SW_C1 | X87_SW_C0); |
| 3433 | 3439 | |
| 3434 | | UINT32 ea = GetEA(cpustate, modrm, 0); |
| 3435 | 3440 | INT32 m32int = READ32(cpustate, ea); |
| 3436 | 3441 | |
| 3437 | 3442 | floatx80 a = ST(0); |
| r14729 | r14730 | |
| 3459 | 3464 | |
| 3460 | 3465 | void x87_ficomp_m16int(i386_state *cpustate, UINT8 modrm) |
| 3461 | 3466 | { |
| 3467 | UINT32 ea = GetEA(cpustate, modrm, 0); |
| 3462 | 3468 | if (X87_IS_ST_EMPTY(0)) |
| 3463 | 3469 | { |
| 3464 | 3470 | x87_set_stack_underflow(cpustate); |
| r14729 | r14730 | |
| 3468 | 3474 | { |
| 3469 | 3475 | cpustate->x87_sw &= ~(X87_SW_C3 | X87_SW_C2 | X87_SW_C1 | X87_SW_C0); |
| 3470 | 3476 | |
| 3471 | | UINT32 ea = GetEA(cpustate, modrm, 0); |
| 3472 | 3477 | INT16 m16int = READ16(cpustate, ea); |
| 3473 | 3478 | |
| 3474 | 3479 | floatx80 a = ST(0); |
| r14729 | r14730 | |
| 3497 | 3502 | |
| 3498 | 3503 | void x87_ficomp_m32int(i386_state *cpustate, UINT8 modrm) |
| 3499 | 3504 | { |
| 3505 | UINT32 ea = GetEA(cpustate, modrm, 0); |
| 3500 | 3506 | if (X87_IS_ST_EMPTY(0)) |
| 3501 | 3507 | { |
| 3502 | 3508 | x87_set_stack_underflow(cpustate); |
| r14729 | r14730 | |
| 3506 | 3512 | { |
| 3507 | 3513 | cpustate->x87_sw &= ~(X87_SW_C3 | X87_SW_C2 | X87_SW_C1 | X87_SW_C0); |
| 3508 | 3514 | |
| 3509 | | UINT32 ea = GetEA(cpustate, modrm, 0); |
| 3510 | 3515 | INT32 m32int = READ32(cpustate, ea); |
| 3511 | 3516 | |
| 3512 | 3517 | floatx80 a = ST(0); |
| r14729 | r14730 | |
| 3536 | 3541 | |
| 3537 | 3542 | void x87_fcom_m32real(i386_state *cpustate, UINT8 modrm) |
| 3538 | 3543 | { |
| 3544 | UINT32 ea = GetEA(cpustate, modrm, 0); |
| 3539 | 3545 | if (X87_IS_ST_EMPTY(0)) |
| 3540 | 3546 | { |
| 3541 | 3547 | x87_set_stack_underflow(cpustate); |
| r14729 | r14730 | |
| 3545 | 3551 | { |
| 3546 | 3552 | cpustate->x87_sw &= ~(X87_SW_C3 | X87_SW_C2 | X87_SW_C1 | X87_SW_C0); |
| 3547 | 3553 | |
| 3548 | | UINT32 ea = GetEA(cpustate, modrm, 0); |
| 3549 | 3554 | UINT32 m32real = READ32(cpustate, ea); |
| 3550 | 3555 | |
| 3551 | 3556 | floatx80 a = ST(0); |
| r14729 | r14730 | |
| 3573 | 3578 | |
| 3574 | 3579 | void x87_fcom_m64real(i386_state *cpustate, UINT8 modrm) |
| 3575 | 3580 | { |
| 3581 | UINT32 ea = GetEA(cpustate, modrm, 0); |
| 3576 | 3582 | if (X87_IS_ST_EMPTY(0)) |
| 3577 | 3583 | { |
| 3578 | 3584 | x87_set_stack_underflow(cpustate); |
| r14729 | r14730 | |
| 3582 | 3588 | { |
| 3583 | 3589 | cpustate->x87_sw &= ~(X87_SW_C3 | X87_SW_C2 | X87_SW_C1 | X87_SW_C0); |
| 3584 | 3590 | |
| 3585 | | UINT32 ea = GetEA(cpustate, modrm, 0); |
| 3586 | 3591 | UINT64 m64real = READ64(cpustate, ea); |
| 3587 | 3592 | |
| 3588 | 3593 | floatx80 a = ST(0); |
| r14729 | r14730 | |
| 3646 | 3651 | |
| 3647 | 3652 | void x87_fcomp_m32real(i386_state *cpustate, UINT8 modrm) |
| 3648 | 3653 | { |
| 3654 | UINT32 ea = GetEA(cpustate, modrm, 0); |
| 3649 | 3655 | if (X87_IS_ST_EMPTY(0)) |
| 3650 | 3656 | { |
| 3651 | 3657 | x87_set_stack_underflow(cpustate); |
| r14729 | r14730 | |
| 3655 | 3661 | { |
| 3656 | 3662 | cpustate->x87_sw &= ~(X87_SW_C3 | X87_SW_C2 | X87_SW_C1 | X87_SW_C0); |
| 3657 | 3663 | |
| 3658 | | UINT32 ea = GetEA(cpustate, modrm, 0); |
| 3659 | 3664 | UINT32 m32real = READ32(cpustate, ea); |
| 3660 | 3665 | |
| 3661 | 3666 | floatx80 a = ST(0); |
| r14729 | r14730 | |
| 3684 | 3689 | |
| 3685 | 3690 | void x87_fcomp_m64real(i386_state *cpustate, UINT8 modrm) |
| 3686 | 3691 | { |
| 3692 | UINT32 ea = GetEA(cpustate, modrm, 0); |
| 3687 | 3693 | if (X87_IS_ST_EMPTY(0)) |
| 3688 | 3694 | { |
| 3689 | 3695 | x87_set_stack_underflow(cpustate); |
| r14729 | r14730 | |
| 3693 | 3699 | { |
| 3694 | 3700 | cpustate->x87_sw &= ~(X87_SW_C3 | X87_SW_C2 | X87_SW_C1 | X87_SW_C0); |
| 3695 | 3701 | |
| 3696 | | UINT32 ea = GetEA(cpustate, modrm, 0); |
| 3697 | 3702 | UINT64 m64real = READ64(cpustate, ea); |
| 3698 | 3703 | |
| 3699 | 3704 | floatx80 a = ST(0); |
src/emu/cpu/i386/i386.c
| r14729 | r14730 | |
| 34 | 34 | |
| 35 | 35 | #define INT_DEBUG 1 |
| 36 | 36 | |
| 37 | | static void i386_load_protected_mode_segment(i386_state *cpustate, I386_SREG *seg ) |
| 37 | static UINT32 i386_load_protected_mode_segment(i386_state *cpustate, I386_SREG *seg, UINT64 *desc ) |
| 38 | 38 | { |
| 39 | 39 | UINT32 v1,v2; |
| 40 | 40 | UINT32 base, limit; |
| r14729 | r14730 | |
| 51 | 51 | |
| 52 | 52 | entry = seg->selector & ~0x7; |
| 53 | 53 | if (limit == 0 || entry + 7 > limit) |
| 54 | | return; |
| 54 | return 0; |
| 55 | 55 | |
| 56 | 56 | v1 = READ32(cpustate, base + entry ); |
| 57 | 57 | v2 = READ32(cpustate, base + entry + 4 ); |
| r14729 | r14730 | |
| 63 | 63 | seg->limit = (seg->limit << 12) | 0xfff; |
| 64 | 64 | seg->d = (seg->flags & 0x4000) ? 1 : 0; |
| 65 | 65 | seg->valid = (seg->selector & ~3)?(true):(false); |
| 66 | |
| 67 | if(desc) |
| 68 | *desc = ((UINT64)v2<<32)|v1; |
| 69 | return 1; |
| 66 | 70 | } |
| 67 | 71 | |
| 68 | 72 | static void i386_load_call_gate(i386_state* cpustate, I386_CALL_GATE *gate) |
| r14729 | r14730 | |
| 101 | 105 | if (PROTECTED_MODE) |
| 102 | 106 | { |
| 103 | 107 | if (!V8086_MODE) |
| 104 | | i386_load_protected_mode_segment(cpustate, &cpustate->sreg[segment] ); |
| 108 | i386_load_protected_mode_segment(cpustate, &cpustate->sreg[segment], NULL ); |
| 105 | 109 | else |
| 106 | 110 | { |
| 107 | 111 | cpustate->sreg[segment].base = cpustate->sreg[segment].selector << 4; |
| r14729 | r14730 | |
| 358 | 362 | |
| 359 | 363 | memset(&desc, 0, sizeof(desc)); |
| 360 | 364 | desc.selector = selector; |
| 361 | | i386_load_protected_mode_segment(cpustate,&desc); |
| 365 | i386_load_protected_mode_segment(cpustate,&desc,NULL); |
| 362 | 366 | DPL = (desc.flags >> 5) & 0x03; // descriptor privilege level |
| 363 | 367 | RPL = selector & 0x03; |
| 364 | 368 | |
| r14729 | r14730 | |
| 401 | 405 | { |
| 402 | 406 | if((cpustate->sreg[seg].flags & 0x0018) == 0x0010 && cpustate->sreg[seg].flags & 0x0004) // if expand-down data segment |
| 403 | 407 | { |
| 404 | | if(offset <= cpustate->sreg[seg].limit) |
| 408 | // compare if greater then 0xffffffff when we're passed the access size |
| 409 | if((offset <= cpustate->sreg[seg].limit) || ((cpustate->sreg[seg].d)?0:(offset > 0xffff))) |
| 405 | 410 | { |
| 406 | 411 | logerror("Limit check at 0x%08x failed. Segment %04x, limit %08x, offset %08x (expand-down)\n",cpustate->pc,cpustate->sreg[seg].selector,cpustate->sreg[seg].limit,offset); |
| 407 | 412 | return 1; |
| r14729 | r14730 | |
| 433 | 438 | |
| 434 | 439 | memset(&stack, 0, sizeof(stack)); |
| 435 | 440 | stack.selector = selector; |
| 436 | | i386_load_protected_mode_segment(cpustate,&stack); |
| 441 | i386_load_protected_mode_segment(cpustate,&stack,NULL); |
| 437 | 442 | DPL = (stack.flags >> 5) & 0x03; |
| 438 | 443 | |
| 439 | 444 | if((selector & ~0x0003) == 0) |
| r14729 | r14730 | |
| 491 | 496 | |
| 492 | 497 | memset(&desc, 0, sizeof(desc)); |
| 493 | 498 | desc.selector = selector; |
| 494 | | i386_load_protected_mode_segment(cpustate,&desc); |
| 499 | i386_load_protected_mode_segment(cpustate,&desc,NULL); |
| 495 | 500 | DPL = (desc.flags >> 5) & 0x03; |
| 496 | 501 | |
| 497 | 502 | if(selector & 0x0004) // LDT |
| r14729 | r14730 | |
| 692 | 697 | /* Task gate */ |
| 693 | 698 | memset(&desc, 0, sizeof(desc)); |
| 694 | 699 | desc.selector = segment; |
| 695 | | i386_load_protected_mode_segment(cpustate,&desc); |
| 700 | i386_load_protected_mode_segment(cpustate,&desc,NULL); |
| 696 | 701 | if(segment & 0x04) |
| 697 | 702 | { |
| 698 | 703 | logerror("IRQ: Task gate: TSS is not in the GDT.\n"); |
| r14729 | r14730 | |
| 729 | 734 | /* Interrupt or Trap gate */ |
| 730 | 735 | memset(&desc, 0, sizeof(desc)); |
| 731 | 736 | desc.selector = segment; |
| 732 | | i386_load_protected_mode_segment(cpustate,&desc); |
| 737 | i386_load_protected_mode_segment(cpustate,&desc,NULL); |
| 733 | 738 | CPL = cpustate->CPL; // current privilege level |
| 734 | 739 | DPL = (desc.flags >> 5) & 0x03; // descriptor privilege level |
| 735 | 740 | // RPL = segment & 0x03; // requested privilege level |
| r14729 | r14730 | |
| 777 | 782 | stack.selector = i386_get_stack_segment(cpustate,DPL); |
| 778 | 783 | else |
| 779 | 784 | stack.selector = i286_get_stack_segment(cpustate,DPL); |
| 780 | | i386_load_protected_mode_segment(cpustate,&stack); |
| 785 | i386_load_protected_mode_segment(cpustate,&stack,NULL); |
| 781 | 786 | oldSS = cpustate->sreg[SS].selector; |
| 782 | 787 | if(flags & 0x0008) |
| 783 | 788 | oldESP = REG32(ESP); |
| r14729 | r14730 | |
| 1011 | 1016 | cpustate->task.segment = selector; |
| 1012 | 1017 | memset(&seg, 0, sizeof(seg)); |
| 1013 | 1018 | seg.selector = cpustate->task.segment; |
| 1014 | | i386_load_protected_mode_segment(cpustate,&seg); |
| 1019 | i386_load_protected_mode_segment(cpustate,&seg,NULL); |
| 1015 | 1020 | cpustate->task.limit = seg.limit; |
| 1016 | 1021 | cpustate->task.base = seg.base; |
| 1017 | 1022 | cpustate->task.flags = seg.flags; |
| r14729 | r14730 | |
| 1023 | 1028 | tss = cpustate->task.base; |
| 1024 | 1029 | cpustate->ldtr.segment = READ16(cpustate,tss+0x2a) & 0xffff; |
| 1025 | 1030 | seg.selector = cpustate->ldtr.segment; |
| 1026 | | i386_load_protected_mode_segment(cpustate,&seg); |
| 1031 | i386_load_protected_mode_segment(cpustate,&seg,NULL); |
| 1027 | 1032 | cpustate->ldtr.limit = seg.limit; |
| 1028 | 1033 | cpustate->ldtr.base = seg.base; |
| 1029 | 1034 | cpustate->ldtr.flags = seg.flags; |
| r14729 | r14730 | |
| 1121 | 1126 | cpustate->task.segment = selector; |
| 1122 | 1127 | memset(&seg, 0, sizeof(seg)); |
| 1123 | 1128 | seg.selector = cpustate->task.segment; |
| 1124 | | i386_load_protected_mode_segment(cpustate,&seg); |
| 1129 | i386_load_protected_mode_segment(cpustate,&seg,NULL); |
| 1125 | 1130 | cpustate->task.limit = seg.limit; |
| 1126 | 1131 | cpustate->task.base = seg.base; |
| 1127 | 1132 | cpustate->task.flags = seg.flags; |
| r14729 | r14730 | |
| 1133 | 1138 | tss = cpustate->task.base; |
| 1134 | 1139 | cpustate->ldtr.segment = READ32(cpustate,tss+0x60) & 0xffff; |
| 1135 | 1140 | seg.selector = cpustate->ldtr.segment; |
| 1136 | | i386_load_protected_mode_segment(cpustate,&seg); |
| 1141 | i386_load_protected_mode_segment(cpustate,&seg,NULL); |
| 1137 | 1142 | cpustate->ldtr.limit = seg.limit; |
| 1138 | 1143 | cpustate->ldtr.base = seg.base; |
| 1139 | 1144 | cpustate->ldtr.flags = seg.flags; |
| r14729 | r14730 | |
| 1233 | 1238 | /* Determine segment type */ |
| 1234 | 1239 | memset(&desc, 0, sizeof(desc)); |
| 1235 | 1240 | desc.selector = segment; |
| 1236 | | i386_load_protected_mode_segment(cpustate,&desc); |
| 1241 | i386_load_protected_mode_segment(cpustate,&desc,NULL); |
| 1237 | 1242 | CPL = cpustate->CPL; // current privilege level |
| 1238 | 1243 | DPL = (desc.flags >> 5) & 0x03; // descriptor privilege level |
| 1239 | 1244 | RPL = segment & 0x03; // requested privilege level |
| r14729 | r14730 | |
| 1291 | 1296 | logerror("JMP: Available 386 TSS at %08x\n",cpustate->pc); |
| 1292 | 1297 | memset(&desc, 0, sizeof(desc)); |
| 1293 | 1298 | desc.selector = segment; |
| 1294 | | i386_load_protected_mode_segment(cpustate,&desc); |
| 1299 | i386_load_protected_mode_segment(cpustate,&desc,NULL); |
| 1295 | 1300 | DPL = (desc.flags >> 5) & 0x03; // descriptor privilege level |
| 1296 | 1301 | if(DPL < CPL) |
| 1297 | 1302 | { |
| r14729 | r14730 | |
| 1362 | 1367 | } |
| 1363 | 1368 | } |
| 1364 | 1369 | desc.selector = call_gate.selector; |
| 1365 | | i386_load_protected_mode_segment(cpustate,&desc); |
| 1370 | i386_load_protected_mode_segment(cpustate,&desc,NULL); |
| 1366 | 1371 | DPL = (desc.flags >> 5) & 0x03; |
| 1367 | 1372 | if((desc.flags & 0x0018) != 0x18) |
| 1368 | 1373 | { |
| r14729 | r14730 | |
| 1421 | 1426 | } |
| 1422 | 1427 | /* Check the TSS that the task gate points to */ |
| 1423 | 1428 | desc.selector = call_gate.selector; |
| 1424 | | i386_load_protected_mode_segment(cpustate,&desc); |
| 1429 | i386_load_protected_mode_segment(cpustate,&desc,NULL); |
| 1425 | 1430 | DPL = (desc.flags >> 5) & 0x03; // descriptor privilege level |
| 1426 | 1431 | RPL = call_gate.selector & 0x03; // requested privilege level |
| 1427 | 1432 | if(call_gate.selector & 0x04) |
| r14729 | r14730 | |
| 1507 | 1512 | /* Determine segment type */ |
| 1508 | 1513 | memset(&desc, 0, sizeof(desc)); |
| 1509 | 1514 | desc.selector = selector; |
| 1510 | | i386_load_protected_mode_segment(cpustate,&desc); |
| 1515 | i386_load_protected_mode_segment(cpustate,&desc,NULL); |
| 1511 | 1516 | CPL = cpustate->CPL; // current privilege level |
| 1512 | 1517 | DPL = (desc.flags >> 5) & 0x03; // descriptor privilege level |
| 1513 | 1518 | RPL = selector & 0x03; // requested privilege level |
| r14729 | r14730 | |
| 1653 | 1658 | FAULT(FAULT_GP,desc.selector & ~0x03) // #GP(selector) |
| 1654 | 1659 | } |
| 1655 | 1660 | } |
| 1656 | | i386_load_protected_mode_segment(cpustate,&desc); |
| 1661 | i386_load_protected_mode_segment(cpustate,&desc,NULL); |
| 1657 | 1662 | if((desc.flags & 0x0018) != 0x18) |
| 1658 | 1663 | { |
| 1659 | 1664 | logerror("CALL: Call gate: Segment is not a code segment.\n"); |
| r14729 | r14730 | |
| 1682 | 1687 | stack.selector = i386_get_stack_segment(cpustate,DPL); |
| 1683 | 1688 | else |
| 1684 | 1689 | stack.selector = i286_get_stack_segment(cpustate,DPL); |
| 1685 | | i386_load_protected_mode_segment(cpustate,&stack); |
| 1690 | i386_load_protected_mode_segment(cpustate,&stack,NULL); |
| 1686 | 1691 | if((stack.selector & ~0x07) == 0) |
| 1687 | 1692 | { |
| 1688 | 1693 | logerror("CALL: Call gate: TSS selector is null\n"); |
| r14729 | r14730 | |
| 1786 | 1791 | |
| 1787 | 1792 | memset(&temp, 0, sizeof(temp)); |
| 1788 | 1793 | temp.selector = oldSS; |
| 1789 | | i386_load_protected_mode_segment(cpustate,&temp); |
| 1794 | i386_load_protected_mode_segment(cpustate,&temp,NULL); |
| 1790 | 1795 | /* copy parameters from old stack to new stack */ |
| 1791 | 1796 | for(x=(gate.dword_count & 0x1f)-1;x>=0;x--) |
| 1792 | 1797 | { |
| r14729 | r14730 | |
| 1850 | 1855 | } |
| 1851 | 1856 | /* Check the TSS that the task gate points to */ |
| 1852 | 1857 | desc.selector = gate.selector; |
| 1853 | | i386_load_protected_mode_segment(cpustate,&desc); |
| 1858 | i386_load_protected_mode_segment(cpustate,&desc,NULL); |
| 1854 | 1859 | if(gate.selector & 0x04) |
| 1855 | 1860 | { |
| 1856 | 1861 | logerror("CALL: Task Gate: TSS is not global.\n"); |
| r14729 | r14730 | |
| 1933 | 1938 | |
| 1934 | 1939 | memset(&desc, 0, sizeof(desc)); |
| 1935 | 1940 | desc.selector = newCS; |
| 1936 | | i386_load_protected_mode_segment(cpustate,&desc); |
| 1941 | i386_load_protected_mode_segment(cpustate,&desc,NULL); |
| 1937 | 1942 | CPL = cpustate->CPL; // current privilege level |
| 1938 | 1943 | DPL = (desc.flags >> 5) & 0x03; // descriptor privilege level |
| 1939 | 1944 | RPL = newCS & 0x03; |
| r14729 | r14730 | |
| 2113 | 2118 | |
| 2114 | 2119 | /* Check SS selector and descriptor */ |
| 2115 | 2120 | desc.selector = newSS; |
| 2116 | | i386_load_protected_mode_segment(cpustate,&desc); |
| 2121 | i386_load_protected_mode_segment(cpustate,&desc,NULL); |
| 2117 | 2122 | DPL = (desc.flags >> 5) & 0x03; // descriptor privilege level |
| 2118 | 2123 | if((newSS & ~0x07) == 0) |
| 2119 | 2124 | { |
| r14729 | r14730 | |
| 2252 | 2257 | } |
| 2253 | 2258 | memset(&desc, 0, sizeof(desc)); |
| 2254 | 2259 | desc.selector = task; |
| 2255 | | i386_load_protected_mode_segment(cpustate,&desc); |
| 2260 | i386_load_protected_mode_segment(cpustate,&desc,NULL); |
| 2256 | 2261 | if((desc.flags & 0x001f) != 0x000b) |
| 2257 | 2262 | { |
| 2258 | 2263 | logerror("IRET (%08x): Task return: Back-linked TSS is not a busy TSS.\n",cpustate->pc); |
| r14729 | r14730 | |
| 2286 | 2291 | } |
| 2287 | 2292 | memset(&desc, 0, sizeof(desc)); |
| 2288 | 2293 | desc.selector = newCS; |
| 2289 | | i386_load_protected_mode_segment(cpustate,&desc); |
| 2294 | i386_load_protected_mode_segment(cpustate,&desc,NULL); |
| 2290 | 2295 | DPL = (desc.flags >> 5) & 0x03; // descriptor privilege level |
| 2291 | 2296 | RPL = newCS & 0x03; |
| 2292 | 2297 | memset(&stack, 0, sizeof(stack)); |
| 2293 | 2298 | stack.selector = newSS; |
| 2294 | | i386_load_protected_mode_segment(cpustate,&stack); |
| 2299 | i386_load_protected_mode_segment(cpustate,&stack,NULL); |
| 2295 | 2300 | //SSRPL = newSS & 0x03; |
| 2296 | 2301 | //SSDPL = (stack.flags >> 5) & 0x03; |
| 2297 | 2302 | |
| r14729 | r14730 | |
| 2502 | 2507 | } |
| 2503 | 2508 | memset(&desc, 0, sizeof(desc)); |
| 2504 | 2509 | desc.selector = newCS; |
| 2505 | | i386_load_protected_mode_segment(cpustate,&desc); |
| 2510 | i386_load_protected_mode_segment(cpustate,&desc,NULL); |
| 2506 | 2511 | DPL = (desc.flags >> 5) & 0x03; // descriptor privilege level |
| 2507 | 2512 | RPL = newCS & 0x03; |
| 2508 | 2513 | if((desc.flags & 0x0018) != 0x0018) |
| r14729 | r14730 | |
| 2563 | 2568 | /* return to outer privilege level */ |
| 2564 | 2569 | memset(&desc, 0, sizeof(desc)); |
| 2565 | 2570 | desc.selector = newCS; |
| 2566 | | i386_load_protected_mode_segment(cpustate,&desc); |
| 2571 | i386_load_protected_mode_segment(cpustate,&desc,NULL); |
| 2567 | 2572 | DPL = (desc.flags >> 5) & 0x03; // descriptor privilege level |
| 2568 | 2573 | RPL = newCS & 0x03; |
| 2569 | 2574 | if(operand32 == 0) |
| r14729 | r14730 | |
| 2646 | 2651 | } |
| 2647 | 2652 | memset(&stack, 0, sizeof(stack)); |
| 2648 | 2653 | stack.selector = newSS; |
| 2649 | | i386_load_protected_mode_segment(cpustate,&stack); |
| 2654 | i386_load_protected_mode_segment(cpustate,&stack,NULL); |
| 2650 | 2655 | DPL = (stack.flags >> 5) & 0x03; |
| 2651 | 2656 | if((newSS & ~0x03) == 0) |
| 2652 | 2657 | { |
| r14729 | r14730 | |
| 2852 | 2857 | { |
| 2853 | 2858 | memset(&seg, 0, sizeof(seg)); |
| 2854 | 2859 | seg.selector = (UINT16) param[0]; |
| 2855 | | i386_load_protected_mode_segment(cpustate,&seg); |
| 2860 | i386_load_protected_mode_segment(cpustate,&seg,NULL); |
| 2856 | 2861 | result = seg.base; |
| 2857 | 2862 | } |
| 2858 | 2863 | else |
| r14729 | r14730 | |
| 2873 | 2878 | { |
| 2874 | 2879 | memset(&seg, 0, sizeof(seg)); |
| 2875 | 2880 | seg.selector = (UINT16) param[0]; |
| 2876 | | i386_load_protected_mode_segment(cpustate,&seg); |
| 2881 | i386_load_protected_mode_segment(cpustate,&seg,NULL); |
| 2877 | 2882 | result = seg.limit; |
| 2878 | 2883 | } |
| 2879 | 2884 | return result; |
| r14729 | r14730 | |
| 3139 | 3144 | if(cpustate->TF && cpustate->old_tf) |
| 3140 | 3145 | { |
| 3141 | 3146 | cpustate->prev_eip = cpustate->eip; |
| 3142 | | cpustate->ext = 0; |
| 3147 | cpustate->ext = 1; |
| 3143 | 3148 | i386_trap(cpustate,1,0,0); |
| 3144 | 3149 | } |
| 3145 | 3150 | |
src/emu/cpu/i386/i386op32.c
| r14729 | r14730 | |
| 59 | 59 | } |
| 60 | 60 | |
| 61 | 61 | } else { |
| 62 | | |
| 62 | shift &= 31; |
| 63 | 63 | switch( (modrm >> 3) & 0x7 ) |
| 64 | 64 | { |
| 65 | 65 | case 0: /* ROL rm32, i8 */ |
| 66 | 66 | dst = ((src & ((UINT32)0xffffffff >> shift)) << shift) | |
| 67 | 67 | ((src & ((UINT32)0xffffffff << (32-shift))) >> (32-shift)); |
| 68 | | cpustate->CF = (src >> (32-shift)) & 0x1; |
| 68 | cpustate->CF = dst & 0x1; |
| 69 | cpustate->OF = (dst & 1) ^ (dst >> 31); |
| 69 | 70 | CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); |
| 70 | 71 | break; |
| 71 | 72 | case 1: /* ROR rm32, i8 */ |
| 72 | 73 | dst = ((src & ((UINT32)0xffffffff << shift)) >> shift) | |
| 73 | 74 | ((src & ((UINT32)0xffffffff >> (32-shift))) << (32-shift)); |
| 74 | | cpustate->CF = (src >> (shift-1)) & 0x1; |
| 75 | cpustate->CF = (dst >> 31) & 0x1; |
| 76 | cpustate->OF = ((dst >> 31) ^ (dst >> 30)) & 1; |
| 75 | 77 | CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM); |
| 76 | 78 | break; |
| 77 | 79 | case 2: /* RCL rm32, i8 */ |
| r14729 | r14730 | |
| 79 | 81 | ((src & ((UINT32)0xffffffff << (33-shift))) >> (33-shift)) | |
| 80 | 82 | (cpustate->CF << (shift-1)); |
| 81 | 83 | cpustate->CF = (src >> (32-shift)) & 0x1; |
| 84 | cpustate->OF = cpustate->CF ^ ((dst >> 31) & 1); |
| 82 | 85 | CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM); |
| 83 | 86 | break; |
| 84 | 87 | case 3: /* RCR rm32, i8 */ |
| r14729 | r14730 | |
| 86 | 89 | ((src & ((UINT32)0xffffffff >> (32-shift))) << (33-shift)) | |
| 87 | 90 | (cpustate->CF << (32-shift)); |
| 88 | 91 | cpustate->CF = (src >> (shift-1)) & 0x1; |
| 92 | cpustate->OF = ((dst >> 31) ^ (dst >> 30)) & 1; |
| 89 | 93 | CYCLES_RM(cpustate,modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM); |
| 90 | 94 | break; |
| 91 | 95 | case 4: /* SHL/SAL rm32, i8 */ |
| r14729 | r14730 | |
| 340 | 344 | UINT32 ea = GetEA(cpustate,modrm,0); |
| 341 | 345 | UINT32 bit = LOAD_REG32(modrm); |
| 342 | 346 | ea += 4*(bit/32); |
| 347 | ea = (cpustate->address_size)?ea:(ea&0xffff); |
| 343 | 348 | bit %= 32; |
| 344 | 349 | UINT32 dst = READ32(cpustate,ea); |
| 345 | 350 | |
| r14729 | r14730 | |
| 371 | 376 | UINT32 ea = GetEA(cpustate,modrm,1); |
| 372 | 377 | UINT32 bit = LOAD_REG32(modrm); |
| 373 | 378 | ea += 4*(bit/32); |
| 379 | ea = (cpustate->address_size)?ea:(ea&0xffff); |
| 374 | 380 | bit %= 32; |
| 375 | 381 | UINT32 dst = READ32(cpustate,ea); |
| 376 | 382 | |
| r14729 | r14730 | |
| 404 | 410 | UINT32 ea = GetEA(cpustate,modrm,1); |
| 405 | 411 | UINT32 bit = LOAD_REG32(modrm); |
| 406 | 412 | ea += 4*(bit/32); |
| 413 | ea = (cpustate->address_size)?ea:(ea&0xffff); |
| 407 | 414 | bit %= 32; |
| 408 | 415 | UINT32 dst = READ32(cpustate,ea); |
| 409 | 416 | |
| r14729 | r14730 | |
| 437 | 444 | UINT32 ea = GetEA(cpustate,modrm,1); |
| 438 | 445 | UINT32 bit = LOAD_REG32(modrm); |
| 439 | 446 | ea += 4*(bit/32); |
| 447 | ea = (cpustate->address_size)?ea:(ea&0xffff); |
| 440 | 448 | bit %= 32; |
| 441 | 449 | UINT32 dst = READ32(cpustate,ea); |
| 442 | 450 | |
| r14729 | r14730 | |
| 1867 | 1875 | |
| 1868 | 1876 | static void I386OP(shld32_i8)(i386_state *cpustate) // Opcode 0x0f a4 |
| 1869 | 1877 | { |
| 1870 | | /* TODO: Correct flags */ |
| 1871 | 1878 | UINT8 modrm = FETCH(cpustate); |
| 1872 | 1879 | if( modrm >= 0xc0 ) { |
| 1873 | 1880 | UINT32 dst = LOAD_RM32(modrm); |
| 1874 | 1881 | UINT32 upper = LOAD_REG32(modrm); |
| 1875 | 1882 | UINT8 shift = FETCH(cpustate); |
| 1876 | | if( shift > 31 || shift == 0 ) { |
| 1883 | shift &= 31; |
| 1884 | if( shift == 0 ) { |
| 1877 | 1885 | |
| 1878 | 1886 | } else { |
| 1879 | 1887 | cpustate->CF = (dst & (1 << (32-shift))) ? 1 : 0; |
| 1880 | 1888 | dst = (dst << shift) | (upper >> (32-shift)); |
| 1889 | cpustate->OF = cpustate->CF ^ (dst >> 31); |
| 1881 | 1890 | SetSZPF32(dst); |
| 1882 | 1891 | } |
| 1883 | 1892 | STORE_RM32(modrm, dst); |
| r14729 | r14730 | |
| 1887 | 1896 | UINT32 dst = READ32(cpustate,ea); |
| 1888 | 1897 | UINT32 upper = LOAD_REG32(modrm); |
| 1889 | 1898 | UINT8 shift = FETCH(cpustate); |
| 1890 | | if( shift > 31 || shift == 0 ) { |
| 1899 | shift &= 31; |
| 1900 | if( shift == 0 ) { |
| 1891 | 1901 | |
| 1892 | 1902 | } else { |
| 1893 | 1903 | cpustate->CF = (dst & (1 << (32-shift))) ? 1 : 0; |
| 1894 | 1904 | dst = (dst << shift) | (upper >> (32-shift)); |
| 1905 | cpustate->OF = cpustate->CF ^ (dst >> 31); |
| 1895 | 1906 | SetSZPF32(dst); |
| 1896 | 1907 | } |
| 1897 | 1908 | WRITE32(cpustate,ea, dst); |
| r14729 | r14730 | |
| 1901 | 1912 | |
| 1902 | 1913 | static void I386OP(shld32_cl)(i386_state *cpustate) // Opcode 0x0f a5 |
| 1903 | 1914 | { |
| 1904 | | /* TODO: Correct flags */ |
| 1905 | 1915 | UINT8 modrm = FETCH(cpustate); |
| 1906 | 1916 | if( modrm >= 0xc0 ) { |
| 1907 | 1917 | UINT32 dst = LOAD_RM32(modrm); |
| 1908 | 1918 | UINT32 upper = LOAD_REG32(modrm); |
| 1909 | 1919 | UINT8 shift = REG8(CL); |
| 1910 | | if( shift > 31 || shift == 0 ) { |
| 1920 | shift &= 31; |
| 1921 | if( shift == 0 ) { |
| 1911 | 1922 | |
| 1912 | 1923 | } else { |
| 1913 | 1924 | cpustate->CF = (dst & (1 << (32-shift))) ? 1 : 0; |
| 1914 | 1925 | dst = (dst << shift) | (upper >> (32-shift)); |
| 1926 | cpustate->OF = cpustate->CF ^ (dst >> 31); |
| 1915 | 1927 | SetSZPF32(dst); |
| 1916 | 1928 | } |
| 1917 | 1929 | STORE_RM32(modrm, dst); |
| r14729 | r14730 | |
| 1921 | 1933 | UINT32 dst = READ32(cpustate,ea); |
| 1922 | 1934 | UINT32 upper = LOAD_REG32(modrm); |
| 1923 | 1935 | UINT8 shift = REG8(CL); |
| 1924 | | if( shift > 31 || shift == 0 ) { |
| 1936 | shift &= 31; |
| 1937 | if( shift == 0 ) { |
| 1925 | 1938 | |
| 1926 | 1939 | } else { |
| 1927 | 1940 | cpustate->CF = (dst & (1 << (32-shift))) ? 1 : 0; |
| 1928 | 1941 | dst = (dst << shift) | (upper >> (32-shift)); |
| 1942 | cpustate->OF = cpustate->CF ^ (dst >> 31); |
| 1929 | 1943 | SetSZPF32(dst); |
| 1930 | 1944 | } |
| 1931 | 1945 | WRITE32(cpustate,ea, dst); |
| r14729 | r14730 | |
| 1935 | 1949 | |
| 1936 | 1950 | static void I386OP(shrd32_i8)(i386_state *cpustate) // Opcode 0x0f ac |
| 1937 | 1951 | { |
| 1938 | | /* TODO: Correct flags */ |
| 1939 | 1952 | UINT8 modrm = FETCH(cpustate); |
| 1940 | 1953 | if( modrm >= 0xc0 ) { |
| 1941 | 1954 | UINT32 dst = LOAD_RM32(modrm); |
| 1942 | 1955 | UINT32 upper = LOAD_REG32(modrm); |
| 1943 | 1956 | UINT8 shift = FETCH(cpustate); |
| 1944 | | if( shift > 31 || shift == 0 ) { |
| 1957 | shift &= 31; |
| 1958 | if( shift == 0 ) { |
| 1945 | 1959 | |
| 1946 | 1960 | } else { |
| 1947 | 1961 | cpustate->CF = (dst & (1 << (shift-1))) ? 1 : 0; |
| 1948 | 1962 | dst = (dst >> shift) | (upper << (32-shift)); |
| 1963 | cpustate->OF = ((dst >> 31) ^ (dst >> 30)) & 1; |
| 1949 | 1964 | SetSZPF32(dst); |
| 1950 | 1965 | } |
| 1951 | 1966 | STORE_RM32(modrm, dst); |
| r14729 | r14730 | |
| 1955 | 1970 | UINT32 dst = READ32(cpustate,ea); |
| 1956 | 1971 | UINT32 upper = LOAD_REG32(modrm); |
| 1957 | 1972 | UINT8 shift = FETCH(cpustate); |
| 1958 | | if( shift > 31 || shift == 0 ) { |
| 1973 | shift &= 31; |
| 1974 | if( shift == 0 ) { |
| 1959 | 1975 | |
| 1960 | 1976 | } else { |
| 1961 | 1977 | cpustate->CF = (dst & (1 << (shift-1))) ? 1 : 0; |
| 1962 | 1978 | dst = (dst >> shift) | (upper << (32-shift)); |
| 1979 | cpustate->OF = ((dst >> 31) ^ (dst >> 30)) & 1; |
| 1963 | 1980 | SetSZPF32(dst); |
| 1964 | 1981 | } |
| 1965 | 1982 | WRITE32(cpustate,ea, dst); |
| r14729 | r14730 | |
| 1969 | 1986 | |
| 1970 | 1987 | static void I386OP(shrd32_cl)(i386_state *cpustate) // Opcode 0x0f ad |
| 1971 | 1988 | { |
| 1972 | | /* TODO: Correct flags */ |
| 1973 | 1989 | UINT8 modrm = FETCH(cpustate); |
| 1974 | 1990 | if( modrm >= 0xc0 ) { |
| 1975 | 1991 | UINT32 dst = LOAD_RM32(modrm); |
| 1976 | 1992 | UINT32 upper = LOAD_REG32(modrm); |
| 1977 | 1993 | UINT8 shift = REG8(CL); |
| 1978 | | if( shift > 31 || shift == 0 ) { |
| 1994 | shift &= 31; |
| 1995 | if( shift == 0 ) { |
| 1979 | 1996 | |
| 1980 | 1997 | } else { |
| 1981 | 1998 | cpustate->CF = (dst & (1 << (shift-1))) ? 1 : 0; |
| 1982 | 1999 | dst = (dst >> shift) | (upper << (32-shift)); |
| 2000 | cpustate->OF = ((dst >> 31) ^ (dst >> 30)) & 1; |
| 1983 | 2001 | SetSZPF32(dst); |
| 1984 | 2002 | } |
| 1985 | 2003 | STORE_RM32(modrm, dst); |
| r14729 | r14730 | |
| 1989 | 2007 | UINT32 dst = READ32(cpustate,ea); |
| 1990 | 2008 | UINT32 upper = LOAD_REG32(modrm); |
| 1991 | 2009 | UINT8 shift = REG8(CL); |
| 1992 | | if( shift > 31 || shift == 0 ) { |
| 2010 | shift &= 31; |
| 2011 | if( shift == 0 ) { |
| 1993 | 2012 | |
| 1994 | 2013 | } else { |
| 1995 | 2014 | cpustate->CF = (dst & (1 << (shift-1))) ? 1 : 0; |
| 1996 | 2015 | dst = (dst >> shift) | (upper << (32-shift)); |
| 2016 | cpustate->OF = ((dst >> 31) ^ (dst >> 30)) & 1; |
| 1997 | 2017 | SetSZPF32(dst); |
| 1998 | 2018 | } |
| 1999 | 2019 | WRITE32(cpustate,ea, dst); |
| r14729 | r14730 | |
| 2675 | 2695 | REG32(EAX) = (UINT32)result; |
| 2676 | 2696 | } |
| 2677 | 2697 | } else { |
| 2678 | | cpustate->ext = 0; |
| 2679 | 2698 | i386_trap(cpustate, 0, 0, 0); |
| 2680 | | cpustate->ext = 1; |
| 2681 | 2699 | } |
| 2682 | 2700 | } |
| 2683 | 2701 | break; |
| r14729 | r14730 | |
| 2705 | 2723 | REG32(EAX) = (UINT32)result; |
| 2706 | 2724 | } |
| 2707 | 2725 | } else { |
| 2708 | | cpustate->ext = 0; |
| 2709 | 2726 | i386_trap(cpustate, 0, 0, 0); |
| 2710 | | cpustate->ext = 1; |
| 2711 | 2727 | } |
| 2712 | 2728 | } |
| 2713 | 2729 | break; |
| r14729 | r14730 | |
| 2919 | 2935 | } |
| 2920 | 2936 | memset(&seg, 0, sizeof(seg)); |
| 2921 | 2937 | seg.selector = cpustate->ldtr.segment; |
| 2922 | | i386_load_protected_mode_segment(cpustate,&seg); |
| 2938 | i386_load_protected_mode_segment(cpustate,&seg,NULL); |
| 2923 | 2939 | cpustate->ldtr.limit = seg.limit; |
| 2924 | 2940 | cpustate->ldtr.base = seg.base; |
| 2925 | 2941 | cpustate->ldtr.flags = seg.flags; |
| r14729 | r14730 | |
| 2946 | 2962 | } |
| 2947 | 2963 | memset(&seg, 0, sizeof(seg)); |
| 2948 | 2964 | seg.selector = cpustate->task.segment; |
| 2949 | | i386_load_protected_mode_segment(cpustate,&seg); |
| 2965 | i386_load_protected_mode_segment(cpustate,&seg,NULL); |
| 2950 | 2966 | cpustate->task.limit = seg.limit; |
| 2951 | 2967 | cpustate->task.base = seg.base; |
| 2952 | 2968 | cpustate->task.flags = seg.flags; |
| r14729 | r14730 | |
| 2960 | 2976 | case 4: /* VERR */ |
| 2961 | 2977 | if ( PROTECTED_MODE && !V8086_MODE ) |
| 2962 | 2978 | { |
| 2963 | | result = 1; |
| 2964 | 2979 | if( modrm >= 0xc0 ) { |
| 2965 | 2980 | address = LOAD_RM32(modrm); |
| 2966 | 2981 | CYCLES(cpustate,CYCLES_VERR_REG); |
| r14729 | r14730 | |
| 2971 | 2986 | } |
| 2972 | 2987 | memset(&seg, 0, sizeof(seg)); |
| 2973 | 2988 | seg.selector = address; |
| 2974 | | i386_load_protected_mode_segment(cpustate,&seg); |
| 2975 | | // check if the segment is within the bounds of the GDT or LDT |
| 2976 | | if(seg.selector & 0x04) |
| 2977 | | { // LDT |
| 2978 | | if((seg.selector & 0xf8) > cpustate->ldtr.limit) |
| 2979 | | { |
| 2980 | | result = 0; |
| 2981 | | } |
| 2982 | | } |
| 2983 | | else |
| 2984 | | { // GDT |
| 2985 | | if((seg.selector & 0xf8) > cpustate->gdtr.limit) |
| 2986 | | { |
| 2987 | | result = 0; |
| 2988 | | } |
| 2989 | | } |
| 2989 | result = i386_load_protected_mode_segment(cpustate,&seg,NULL); |
| 2990 | 2990 | // check if the segment is a code or data segment (not a special segment type, like a TSS, gate, LDT...) |
| 2991 | 2991 | if(!(seg.flags & 0x10)) |
| 2992 | 2992 | result = 0; |
| r14729 | r14730 | |
| 3023 | 3023 | case 5: /* VERW */ |
| 3024 | 3024 | if ( PROTECTED_MODE && !V8086_MODE ) |
| 3025 | 3025 | { |
| 3026 | | result = 1; |
| 3027 | 3026 | if( modrm >= 0xc0 ) { |
| 3028 | 3027 | address = LOAD_RM16(modrm); |
| 3029 | 3028 | CYCLES(cpustate,CYCLES_VERW_REG); |
| r14729 | r14730 | |
| 3034 | 3033 | } |
| 3035 | 3034 | memset(&seg, 0, sizeof(seg)); |
| 3036 | 3035 | seg.selector = address; |
| 3037 | | i386_load_protected_mode_segment(cpustate,&seg); |
| 3038 | | // check if the segment is within the bounds of the GDT or LDT |
| 3039 | | if(seg.selector & 0x04) |
| 3040 | | { // LDT |
| 3041 | | if((seg.selector & 0xf8) > cpustate->ldtr.limit) |
| 3042 | | { |
| 3043 | | result = 0; |
| 3044 | | } |
| 3045 | | } |
| 3046 | | else |
| 3047 | | { // GDT |
| 3048 | | if((seg.selector & 0xf8) > cpustate->gdtr.limit) |
| 3049 | | { |
| 3050 | | result = 0; |
| 3051 | | } |
| 3052 | | } |
| 3036 | result = i386_load_protected_mode_segment(cpustate,&seg,NULL); |
| 3053 | 3037 | // check if the segment is a code or data segment (not a special segment type, like a TSS, gate, LDT...) |
| 3054 | 3038 | if(!(seg.flags & 0x10)) |
| 3055 | 3039 | result = 0; |
| r14729 | r14730 | |
| 3334 | 3318 | } |
| 3335 | 3319 | else |
| 3336 | 3320 | { |
| 3337 | | i386_load_protected_mode_segment(cpustate,&seg); |
| 3321 | UINT64 desc; |
| 3322 | if(!i386_load_protected_mode_segment(cpustate,&seg,&desc)) |
| 3323 | { |
| 3324 | SetZF(0); |
| 3325 | return; |
| 3326 | } |
| 3327 | if(((seg.flags >> 5) & 3) < cpustate->CPL) |
| 3328 | { |
| 3329 | SetZF(0); |
| 3330 | return; |
| 3331 | } |
| 3338 | 3332 | if(!(seg.flags & 0x10)) // special segment |
| 3339 | 3333 | { |
| 3340 | 3334 | // check for invalid segment types |
| r14729 | r14730 | |
| 3345 | 3339 | } |
| 3346 | 3340 | else |
| 3347 | 3341 | { |
| 3348 | | // TODO: check current privilege level |
| 3349 | | STORE_REG32(modrm,(seg.flags << 8) & 0x00ffff00); |
| 3342 | STORE_REG32(modrm,(desc>>32) & 0x00ffff00); |
| 3350 | 3343 | SetZF(1); |
| 3351 | 3344 | } |
| 3352 | 3345 | } |
| 3353 | 3346 | else |
| 3354 | 3347 | { |
| 3355 | | // TODO: check current privilege level |
| 3356 | | STORE_REG32(modrm,(seg.flags << 8) & 0x00ffff00); |
| 3348 | STORE_REG32(modrm,(desc>>32) & 0x00ffff00); |
| 3357 | 3349 | SetZF(1); |
| 3358 | 3350 | } |
| 3359 | 3351 | } |
| r14729 | r14730 | |
| 3390 | 3382 | } |
| 3391 | 3383 | else |
| 3392 | 3384 | { |
| 3393 | | // TODO: check segment type |
| 3394 | | i386_load_protected_mode_segment(cpustate,&seg); |
| 3395 | | limit = seg.limit; |
| 3396 | | STORE_REG32(modrm,limit); |
| 3397 | | SetZF(1); |
| 3385 | UINT8 type; |
| 3386 | if(!i386_load_protected_mode_segment(cpustate,&seg,NULL)) |
| 3387 | { |
| 3388 | SetZF(0); |
| 3389 | return; |
| 3390 | } |
| 3391 | if(((seg.flags >> 5) & 3) < cpustate->CPL) |
| 3392 | { |
| 3393 | SetZF(0); |
| 3394 | return; |
| 3395 | } |
| 3396 | type = seg.flags & 0x1f; |
| 3397 | switch(type) |
| 3398 | { |
| 3399 | case 0: |
| 3400 | case 4: |
| 3401 | case 5: |
| 3402 | case 6: |
| 3403 | case 7: |
| 3404 | case 8: |
| 3405 | case 10: |
| 3406 | case 12: |
| 3407 | case 13: |
| 3408 | case 14: |
| 3409 | case 15: |
| 3410 | SetZF(0); |
| 3411 | return; |
| 3412 | default: |
| 3413 | limit = seg.limit; |
| 3414 | STORE_REG32(modrm,limit); |
| 3415 | SetZF(1); |
| 3416 | } |
| 3398 | 3417 | } |
| 3399 | 3418 | } |
| 3400 | 3419 | else |