diff options
Diffstat (limited to 'src/devices/cpu/i386/i386.cpp')
-rw-r--r-- | src/devices/cpu/i386/i386.cpp | 342 |
1 files changed, 205 insertions, 137 deletions
diff --git a/src/devices/cpu/i386/i386.cpp b/src/devices/cpu/i386/i386.cpp index 9f6eaafc83c..bd99c7f456b 100644 --- a/src/devices/cpu/i386/i386.cpp +++ b/src/devices/cpu/i386/i386.cpp @@ -25,8 +25,23 @@ #include "cycles.h" #include "i386ops.h" -#include "debugger.h" #include "debug/debugcpu.h" +#include "debug/express.h" + +#define LOG_MSR (1U << 1) +#define LOG_INVALID_OPCODE (1U << 2) +#define LOG_LIMIT_CHECK (1U << 3) +#define LOG_UNEMULATED (1U << 4) +#define LOG_PM_EVENTS (1U << 5) +#define LOG_PM_FAULT_GP (1U << 6) +#define LOG_PM_FAULT_SS (1U << 7) +#define LOG_PM_FAULT_NP (1U << 8) +#define LOG_PM_FAULT_TS (1U << 9) +#define LOG_PM_FAULT_DF (1U << 10) +#define LOG_PM_FAULT_UD (1U << 11) + +//#define VERBOSE (LOG_PM_FAULT_GP) +#include "logmacro.h" /* seems to be defined on mingw-gcc */ #undef i386 @@ -55,7 +70,6 @@ i386_device::i386_device(const machine_config &mconfig, device_type type, const , device_vtlb_interface(mconfig, *this, AS_PROGRAM) , m_program_config("program", ENDIANNESS_LITTLE, program_data_width, program_addr_width, 0, 32, 12) , m_io_config("io", ENDIANNESS_LITTLE, io_data_width, 16, 0) - , m_dr_breakpoints{nullptr, nullptr, nullptr, nullptr} , m_smiact(*this) , m_ferr_handler(*this) { @@ -151,14 +165,14 @@ MODRM_TABLE i386_MODRM_table[256]; /*************************************************************************/ -uint32_t i386_device::i386_translate(int segment, uint32_t ip, int rwn) +uint32_t i386_device::i386_translate(int segment, uint32_t ip, int rwn, int size) { // TODO: segment limit access size, execution permission, handle exception thrown from exception handler if (PROTECTED_MODE && !V8086_MODE && (rwn != -1)) { if (!(m_sreg[segment].valid)) FAULT_THROW((segment == SS) ? FAULT_SS : FAULT_GP, 0); - if (i386_limit_check(segment, ip)) + if (i386_limit_check(segment, ip, size)) FAULT_THROW((segment == SS) ? FAULT_SS : FAULT_GP, 0); if ((rwn == 0) && ((m_sreg[segment].flags & 8) && !(m_sreg[segment].flags & 2))) FAULT_THROW(FAULT_GP, 0); @@ -168,17 +182,17 @@ uint32_t i386_device::i386_translate(int segment, uint32_t ip, int rwn) return m_sreg[segment].base + ip; } -vtlb_entry i386_device::get_permissions(uint32_t pte, int wp) +device_vtlb_interface::vtlb_entry i386_device::get_permissions(uint32_t pte, int wp) { - vtlb_entry ret = VTLB_READ_ALLOWED | ((pte & 4) ? VTLB_USER_READ_ALLOWED : 0); + vtlb_entry ret = READ_ALLOWED | ((pte & 4) ? USER_READ_ALLOWED : 0); if (!wp) - ret |= VTLB_WRITE_ALLOWED; + ret |= WRITE_ALLOWED; if (pte & 2) - ret |= VTLB_WRITE_ALLOWED | ((pte & 4) ? VTLB_USER_WRITE_ALLOWED : 0); + ret |= WRITE_ALLOWED | ((pte & 4) ? USER_WRITE_ALLOWED : 0); return ret; } -bool i386_device::i386_translate_address(int intention, offs_t *address, vtlb_entry *entry) +bool i386_device::i386_translate_address(int intention, bool debug, offs_t *address, vtlb_entry *entry) { uint32_t a = *address; uint32_t pdbr = m_cr[3] & 0xfffff000; @@ -186,11 +200,10 @@ bool i386_device::i386_translate_address(int intention, offs_t *address, vtlb_en uint32_t table = (a >> 12) & 0x3ff; vtlb_entry perm = 0; bool ret; - bool user = (intention & TRANSLATE_USER_MASK) ? true : false; - bool write = (intention & TRANSLATE_WRITE) ? true : false; - bool debug = (intention & TRANSLATE_DEBUG_MASK) ? true : false; + bool user = (intention & TR_USER) ? true : false; + bool write = (intention & TR_WRITE) ? true : false; - if (!(m_cr[0] & 0x80000000)) + if (!(m_cr[0] & CR0_PG)) { if (entry) *entry = 0x77; @@ -200,7 +213,7 @@ bool i386_device::i386_translate_address(int intention, offs_t *address, vtlb_en uint32_t page_dir = m_program->read_dword(pdbr + directory * 4); if (page_dir & 1) { - if ((page_dir & 0x80) && (m_cr[4] & 0x10)) + if ((page_dir & 0x80) && (m_cr[4] & CR4_PSE)) { a = (page_dir & 0xffc00000) | (a & 0x003fffff); if (debug) @@ -209,14 +222,14 @@ bool i386_device::i386_translate_address(int intention, offs_t *address, vtlb_en return true; } perm = get_permissions(page_dir, WP); - if (write && (!(perm & VTLB_WRITE_ALLOWED) || (user && !(perm & VTLB_USER_WRITE_ALLOWED)))) + if (write && (!(perm & WRITE_ALLOWED) || (user && !(perm & USER_WRITE_ALLOWED)))) ret = false; - else if (user && !(perm & VTLB_USER_READ_ALLOWED)) + else if (user && !(perm & USER_READ_ALLOWED)) ret = false; else { if (write) - perm |= VTLB_FLAG_DIRTY; + perm |= FLAG_DIRTY; if (!(page_dir & 0x40) && write) m_program->write_dword(pdbr + directory * 4, page_dir | 0x60); else if (!(page_dir & 0x20)) @@ -238,14 +251,14 @@ bool i386_device::i386_translate_address(int intention, offs_t *address, vtlb_en return true; } perm = get_permissions(page_entry, WP); - if (write && (!(perm & VTLB_WRITE_ALLOWED) || (user && !(perm & VTLB_USER_WRITE_ALLOWED)))) + if (write && (!(perm & WRITE_ALLOWED) || (user && !(perm & USER_WRITE_ALLOWED)))) ret = false; - else if (user && !(perm & VTLB_USER_READ_ALLOWED)) + else if (user && !(perm & USER_READ_ALLOWED)) ret = false; else { if (write) - perm |= VTLB_FLAG_DIRTY; + perm |= FLAG_DIRTY; if (!(page_dir & 0x20)) m_program->write_dword(pdbr + directory * 4, page_dir | 0x20); if (!(page_entry & 0x40) && write) @@ -270,25 +283,25 @@ bool i386_device::i386_translate_address(int intention, offs_t *address, vtlb_en bool i386_device::translate_address(int pl, int type, uint32_t *address, uint32_t *error) { - if (!(m_cr[0] & 0x80000000)) // Some (very few) old OS's won't work with this + if (!(m_cr[0] & CR0_PG)) // Some (very few) old OS's won't work with this return true; const vtlb_entry *table = vtlb_table(); uint32_t index = *address >> 12; vtlb_entry entry = table[index]; - if (type == TRANSLATE_FETCH) - type = TRANSLATE_READ; + if (type == TR_FETCH) + type = TR_READ; if (pl == 3) - type |= TRANSLATE_USER_MASK; + type |= TR_USER; #ifdef TEST_TLB uint32_t test_addr = *address; #endif - if (!(entry & VTLB_FLAG_VALID) || ((type & TRANSLATE_WRITE) && !(entry & VTLB_FLAG_DIRTY))) + if (!(entry & FLAG_VALID) || ((type & TR_WRITE) && !(entry & FLAG_DIRTY))) { - if (!i386_translate_address(type, address, &entry)) + if (!i386_translate_address(type, false, address, &entry)) { - *error = ((type & TRANSLATE_WRITE) ? 2 : 0) | ((m_CPL == 3) ? 4 : 0); + *error = ((type & TR_WRITE) ? 2 : 0) | ((m_CPL == 3) ? 4 : 0); if (entry) *error |= 1; return false; @@ -298,12 +311,12 @@ bool i386_device::translate_address(int pl, int type, uint32_t *address, uint32_ } if (!(entry & (1 << type))) { - *error = ((type & TRANSLATE_WRITE) ? 2 : 0) | ((m_CPL == 3) ? 4 : 0) | 1; + *error = ((type & TR_WRITE) ? 2 : 0) | ((m_CPL == 3) ? 4 : 0) | 1; return false; } *address = (entry & 0xfffff000) | (*address & 0xfff); #ifdef TEST_TLB - int test_ret = i386_translate_address(type | TRANSLATE_DEBUG_MASK, &test_addr, nullptr); + int test_ret = i386_translate_address(type, true, &test_addr, nullptr); if (!test_ret || (test_addr != *address)) logerror("TLB-PTE mismatch! %06X %06X %06x\n", *address, test_addr, m_pc); #endif @@ -329,7 +342,7 @@ uint8_t i386_device::FETCH() uint8_t value; uint32_t address = m_pc, error; - if(!translate_address(m_CPL,TRANSLATE_FETCH,&address,&error)) + if(!translate_address(m_CPL,TR_FETCH,&address,&error)) PF_THROW(error); value = mem_pr8(address & m_a20_mask); @@ -350,7 +363,7 @@ uint16_t i386_device::FETCH16() value = (FETCH() << 0); value |= (FETCH() << 8); } else { - if(!translate_address(m_CPL,TRANSLATE_FETCH,&address,&error)) + if(!translate_address(m_CPL,TR_FETCH,&address,&error)) PF_THROW(error); address &= m_a20_mask; value = mem_pr16(address); @@ -370,7 +383,7 @@ uint32_t i386_device::FETCH32() value |= (FETCH() << 16); value |= (FETCH() << 24); } else { - if(!translate_address(m_CPL,TRANSLATE_FETCH,&address,&error)) + if(!translate_address(m_CPL,TR_FETCH,&address,&error)) PF_THROW(error); address &= m_a20_mask; @@ -385,7 +398,7 @@ uint8_t i386_device::READ8PL(uint32_t ea, uint8_t privilege) { uint32_t address = ea, error; - if(!translate_address(privilege,TRANSLATE_READ,&address,&error)) + if(!translate_address(privilege,TR_READ,&address,&error)) PF_THROW(error); address &= m_a20_mask; @@ -402,7 +415,7 @@ uint16_t i386_device::READ16PL(uint32_t ea, uint8_t privilege) case 0: case 2: default: - if(!translate_address(privilege,TRANSLATE_READ,&address,&error)) + if(!translate_address(privilege,TR_READ,&address,&error)) PF_THROW(error); address &= m_a20_mask; @@ -410,7 +423,7 @@ uint16_t i386_device::READ16PL(uint32_t ea, uint8_t privilege) break; case 1: - if(!translate_address(privilege,TRANSLATE_READ,&address,&error)) + if(!translate_address(privilege,TR_READ,&address,&error)) PF_THROW(error); address &= m_a20_mask; @@ -435,7 +448,7 @@ uint32_t i386_device::READ32PL(uint32_t ea, uint8_t privilege) { case 0: default: - if(!translate_address(privilege,TRANSLATE_READ,&address,&error)) + if(!translate_address(privilege,TR_READ,&address,&error)) PF_THROW(error); address &= m_a20_mask; @@ -443,7 +456,7 @@ uint32_t i386_device::READ32PL(uint32_t ea, uint8_t privilege) break; case 1: - if(!translate_address(privilege,TRANSLATE_READ,&address,&error)) + if(!translate_address(privilege,TR_READ,&address,&error)) PF_THROW(error); address &= m_a20_mask; @@ -460,7 +473,7 @@ uint32_t i386_device::READ32PL(uint32_t ea, uint8_t privilege) value = READ8PL(ea, privilege); address = ea + 1; - if(!translate_address(privilege,TRANSLATE_READ,&address,&error)) + if(!translate_address(privilege,TR_READ,&address,&error)) PF_THROW(error); address &= m_a20_mask; @@ -481,11 +494,11 @@ uint64_t i386_device::READ64PL(uint32_t ea, uint8_t privilege) case 0: default: value = READ32PL(ea, privilege); - value |= uint64_t(READ32PL(ea + 2, privilege)) << 32; + value |= uint64_t(READ32PL(ea + 4, privilege)) << 32; break; case 1: - if(!translate_address(privilege,TRANSLATE_READ,&address,&error)) + if(!translate_address(privilege,TR_READ,&address,&error)) PF_THROW(error); address &= m_a20_mask; @@ -505,7 +518,7 @@ uint64_t i386_device::READ64PL(uint32_t ea, uint8_t privilege) value |= uint64_t(READ32PL(ea + 1, privilege)) << 8; address = ea + 5; - if(!translate_address(privilege,TRANSLATE_READ,&address,&error)) + if(!translate_address(privilege,TR_READ,&address,&error)) PF_THROW(error); address &= m_a20_mask; @@ -523,7 +536,7 @@ uint16_t i386sx_device::READ16PL(uint32_t ea, uint8_t privilege) if (WORD_ALIGNED(ea)) { - if(!translate_address(privilege,TRANSLATE_READ,&address,&error)) + if(!translate_address(privilege,TR_READ,&address,&error)) PF_THROW(error); address &= m_a20_mask; @@ -583,14 +596,14 @@ uint64_t i386sx_device::READ64PL(uint32_t ea, uint8_t privilege) void i386_device::WRITE_TEST(uint32_t ea) { uint32_t address = ea, error; - if(!translate_address(m_CPL,TRANSLATE_WRITE,&address,&error)) + if(!translate_address(m_CPL,TR_WRITE,&address,&error)) PF_THROW(error); } void i386_device::WRITE8PL(uint32_t ea, uint8_t privilege, uint8_t value) { uint32_t address = ea, error; - if(!translate_address(privilege,TRANSLATE_WRITE,&address,&error)) + if(!translate_address(privilege,TR_WRITE,&address,&error)) PF_THROW(error); address &= m_a20_mask; @@ -605,7 +618,7 @@ void i386_device::WRITE16PL(uint32_t ea, uint8_t privilege, uint16_t value) { case 0: case 2: - if(!translate_address(privilege,TRANSLATE_WRITE,&address,&error)) + if(!translate_address(privilege,TR_WRITE,&address,&error)) PF_THROW(error); address &= m_a20_mask; @@ -613,7 +626,7 @@ void i386_device::WRITE16PL(uint32_t ea, uint8_t privilege, uint16_t value) break; case 1: - if(!translate_address(privilege,TRANSLATE_WRITE,&address,&error)) + if(!translate_address(privilege,TR_WRITE,&address,&error)) PF_THROW(error); address &= m_a20_mask; @@ -634,7 +647,7 @@ void i386_device::WRITE32PL(uint32_t ea, uint8_t privilege, uint32_t value) switch(ea & 3) { case 0: - if(!translate_address(privilege,TRANSLATE_WRITE,&address,&error)) + if(!translate_address(privilege,TR_WRITE,&address,&error)) PF_THROW(error); address &= m_a20_mask; @@ -642,7 +655,7 @@ void i386_device::WRITE32PL(uint32_t ea, uint8_t privilege, uint32_t value) break; case 1: - if(!translate_address(privilege,TRANSLATE_WRITE,&address,&error)) + if(!translate_address(privilege,TR_WRITE,&address,&error)) PF_THROW(error); address &= m_a20_mask; @@ -659,7 +672,7 @@ void i386_device::WRITE32PL(uint32_t ea, uint8_t privilege, uint32_t value) WRITE8PL(ea, privilege, value & 0xff); address = ea + 1; - if(!translate_address(privilege,TRANSLATE_WRITE,&address,&error)) + if(!translate_address(privilege,TR_WRITE,&address,&error)) PF_THROW(error); address &= m_a20_mask; @@ -676,11 +689,11 @@ void i386_device::WRITE64PL(uint32_t ea, uint8_t privilege, uint64_t value) { case 0: WRITE32PL(ea, privilege, value & 0xffffffff); - WRITE32PL(ea + 2, privilege, (value >> 32) & 0xffffffff); + WRITE32PL(ea + 4, privilege, (value >> 32) & 0xffffffff); break; case 1: - if(!translate_address(privilege,TRANSLATE_WRITE,&address,&error)) + if(!translate_address(privilege,TR_WRITE,&address,&error)) PF_THROW(error); address &= m_a20_mask; @@ -700,7 +713,7 @@ void i386_device::WRITE64PL(uint32_t ea, uint8_t privilege, uint64_t value) WRITE32PL(ea + 1, privilege, (value >> 8) & 0xffffffff); address = ea + 5; - if(!translate_address(privilege,TRANSLATE_WRITE,&address,&error)) + if(!translate_address(privilege,TR_WRITE,&address,&error)) PF_THROW(error); address &= m_a20_mask; @@ -715,7 +728,7 @@ void i386sx_device::WRITE16PL(uint32_t ea, uint8_t privilege, uint16_t value) if (WORD_ALIGNED(ea)) { - if(!translate_address(privilege,TRANSLATE_WRITE,&address,&error)) + if(!translate_address(privilege,TR_WRITE,&address,&error)) PF_THROW(error); address &= m_a20_mask; @@ -1530,7 +1543,7 @@ void i386_device::i386_check_irq_line() if ( (m_irq_state) && m_IF ) { m_cycles -= 2; - i386_trap(standard_irq_callback(0), 1, 0); + i386_trap(standard_irq_callback(0, m_pc), 1, 0); } } @@ -1554,24 +1567,30 @@ void i386_device::build_cycle_table() void i386_device::report_invalid_opcode() { #ifndef DEBUG_MISSING_OPCODE - logerror("i386: Invalid opcode %02X at %08X %s\n", m_opcode, m_pc - 1, m_lock ? "with lock" : ""); + LOGMASKED(LOG_INVALID_OPCODE, "i386: Invalid opcode %02X at %08X %s\n", m_opcode, m_pc - 1, m_lock ? "with lock" : ""); #else - logerror("i386: Invalid opcode"); + logerror("Invalid opcode"); for (int a = 0; a < m_opcode_bytes_length; a++) logerror(" %02X", m_opcode_bytes[a]); - logerror(" at %08X\n", m_opcode_pc); + logerror(" at %08X %s\n", m_opcode_pc, m_lock ? "with lock" : ""); + logerror("Backtrace:\n"); + for (uint32_t i = 1; i < 16; i++) + logerror(" %08X\n", m_opcode_addrs[(m_opcode_addrs_index - i) & 15]); #endif } void i386_device::report_invalid_modrm(const char* opcode, uint8_t modrm) { #ifndef DEBUG_MISSING_OPCODE - logerror("i386: Invalid %s modrm %01X at %08X\n", opcode, modrm, m_pc - 2); + LOGMASKED(LOG_INVALID_OPCODE, "i386: Invalid %s modrm %01X at %08X\n", opcode, modrm, m_pc - 2); #else - logerror("i386: Invalid %s modrm %01X", opcode, modrm); + logerror("Invalid %s modrm %01X", opcode, modrm); for (int a = 0; a < m_opcode_bytes_length; a++) logerror(" %02X", m_opcode_bytes[a]); - logerror(" at %08X\n", m_opcode_pc); + logerror(" at %08X %s\n", m_opcode_pc, m_lock ? "with lock" : ""); + logerror("Backtrace:\n"); + for (uint32_t i = 1; i < 16; i++) + logerror(" %08X\n", m_opcode_addrs[(m_opcode_addrs_index - i) & 15]); #endif i386_trap(6, 0, 0); } @@ -1723,7 +1742,7 @@ uint8_t i386_device::read8_debug(uint32_t ea, uint8_t *data) { uint32_t address = ea; - if(!i386_translate_address(TRANSLATE_DEBUG_MASK,&address,nullptr)) + if(!i386_translate_address(TR_READ, true, &address,nullptr)) return 0; address &= m_a20_mask; @@ -1777,7 +1796,7 @@ uint32_t i386_device::i386_get_debug_desc(I386_SREG *seg) return seg->valid; } -uint64_t i386_device::debug_segbase(symbol_table &table, int params, const uint64_t *param) +uint64_t i386_device::debug_segbase(int params, const uint64_t *param) { uint32_t result; I386_SREG seg; @@ -1800,7 +1819,7 @@ uint64_t i386_device::debug_segbase(symbol_table &table, int params, const uint6 return result; } -uint64_t i386_device::debug_seglimit(symbol_table &table, int params, const uint64_t *param) +uint64_t i386_device::debug_seglimit(int params, const uint64_t *param) { uint32_t result = 0; I386_SREG seg; @@ -1816,7 +1835,7 @@ uint64_t i386_device::debug_seglimit(symbol_table &table, int params, const uint return result; } -uint64_t i386_device::debug_segofftovirt(symbol_table &table, int params, const uint64_t *param) +uint64_t i386_device::debug_segofftovirt(int params, const uint64_t *param) { uint32_t result; I386_SREG seg; @@ -1854,16 +1873,16 @@ uint64_t i386_device::debug_segofftovirt(symbol_table &table, int params, const return result; } -uint64_t i386_device::debug_virttophys(symbol_table &table, int params, const uint64_t *param) +uint64_t i386_device::debug_virttophys(int params, const uint64_t *param) { uint32_t result = param[0]; - if(!i386_translate_address(TRANSLATE_DEBUG_MASK,&result,nullptr)) + if(!i386_translate_address(TR_READ,true,&result,nullptr)) return 0; return result; } -uint64_t i386_device::debug_cacheflush(symbol_table &table, int params, const uint64_t *param) +uint64_t i386_device::debug_cacheflush(int params, const uint64_t *param) { uint32_t option; bool invalidate; @@ -1886,11 +1905,11 @@ uint64_t i386_device::debug_cacheflush(symbol_table &table, int params, const ui void i386_device::device_debug_setup() { using namespace std::placeholders; - debug()->symtable().add("segbase", 1, 1, std::bind(&i386_device::debug_segbase, this, _1, _2, _3)); - debug()->symtable().add("seglimit", 1, 1, std::bind(&i386_device::debug_seglimit, this, _1, _2, _3)); - debug()->symtable().add("segofftovirt", 2, 2, std::bind(&i386_device::debug_segofftovirt, this, _1, _2, _3)); - debug()->symtable().add("virttophys", 1, 1, std::bind(&i386_device::debug_virttophys, this, _1, _2, _3)); - debug()->symtable().add("cacheflush", 0, 1, std::bind(&i386_device::debug_cacheflush, this, _1, _2, _3)); + debug()->symtable().add("segbase", 1, 1, std::bind(&i386_device::debug_segbase, this, _1, _2)); + debug()->symtable().add("seglimit", 1, 1, std::bind(&i386_device::debug_seglimit, this, _1, _2)); + debug()->symtable().add("segofftovirt", 2, 2, std::bind(&i386_device::debug_segofftovirt, this, _1, _2)); + debug()->symtable().add("virttophys", 1, 1, std::bind(&i386_device::debug_virttophys, this, _1, _2)); + debug()->symtable().add("cacheflush", 0, 1, std::bind(&i386_device::debug_cacheflush, this, _1, _2)); } /*************************************************************************/ @@ -1936,9 +1955,9 @@ void i386_device::i386_common_init() m_program = &space(AS_PROGRAM); if(m_program->data_width() == 16) { // for the 386sx - macache16 = m_program->cache<1, 0, ENDIANNESS_LITTLE>(); + m_program->cache(macache16); } else { - macache32 = m_program->cache<2, 0, ENDIANNESS_LITTLE>(); + m_program->cache(macache32); } m_io = &space(AS_IO); @@ -1949,36 +1968,11 @@ void i386_device::i386_common_init() zero_state(); save_item(NAME(m_reg.d)); - save_item(NAME(m_sreg[ES].selector)); - save_item(NAME(m_sreg[ES].base)); - save_item(NAME(m_sreg[ES].limit)); - save_item(NAME(m_sreg[ES].flags)); - save_item(NAME(m_sreg[ES].d)); - save_item(NAME(m_sreg[CS].selector)); - save_item(NAME(m_sreg[CS].base)); - save_item(NAME(m_sreg[CS].limit)); - save_item(NAME(m_sreg[CS].flags)); - save_item(NAME(m_sreg[CS].d)); - save_item(NAME(m_sreg[SS].selector)); - save_item(NAME(m_sreg[SS].base)); - save_item(NAME(m_sreg[SS].limit)); - save_item(NAME(m_sreg[SS].flags)); - save_item(NAME(m_sreg[SS].d)); - save_item(NAME(m_sreg[DS].selector)); - save_item(NAME(m_sreg[DS].base)); - save_item(NAME(m_sreg[DS].limit)); - save_item(NAME(m_sreg[DS].flags)); - save_item(NAME(m_sreg[DS].d)); - save_item(NAME(m_sreg[FS].selector)); - save_item(NAME(m_sreg[FS].base)); - save_item(NAME(m_sreg[FS].limit)); - save_item(NAME(m_sreg[FS].flags)); - save_item(NAME(m_sreg[FS].d)); - save_item(NAME(m_sreg[GS].selector)); - save_item(NAME(m_sreg[GS].base)); - save_item(NAME(m_sreg[GS].limit)); - save_item(NAME(m_sreg[GS].flags)); - save_item(NAME(m_sreg[GS].d)); + save_item(STRUCT_MEMBER(m_sreg, selector)); + save_item(STRUCT_MEMBER(m_sreg, base)); + save_item(STRUCT_MEMBER(m_sreg, limit)); + save_item(STRUCT_MEMBER(m_sreg, flags)); + save_item(STRUCT_MEMBER(m_sreg, d)); save_item(NAME(m_eip)); save_item(NAME(m_prev_eip)); @@ -2037,17 +2031,22 @@ void i386_device::i386_common_init() save_item(NAME(m_nmi_latched)); save_item(NAME(m_smbase)); save_item(NAME(m_lock)); + + save_item(NAME(m_x87_cw)); + save_item(NAME(m_x87_tw)); + save_item(NAME(m_x87_sw)); + save_item(NAME(m_x87_cs)); + save_item(NAME(m_x87_ds)); + save_item(NAME(m_x87_inst_ptr)); + save_item(NAME(m_x87_data_ptr)); + save_item(NAME(m_x87_opcode)); + machine().save().register_postload(save_prepost_delegate(FUNC(i386_device::i386_postload), this)); - m_smiact.resolve_safe(); - m_ferr_handler.resolve_safe(); m_ferr_handler(0); set_icountptr(m_cycles); - m_notifier = m_program->add_change_notifier([this](read_or_write mode) - { - dri_changed(); - }); + m_notifier = m_program->add_change_notifier([this] (read_or_write mode) { dri_changed(); }); } void i386_device::device_start() @@ -2146,25 +2145,24 @@ void i386_device::register_state_i386() state_add( STATE_GENPC, "GENPC", m_pc).noshow(); state_add( STATE_GENPCBASE, "CURPC", m_pc).noshow(); - state_add( STATE_GENFLAGS, "GENFLAGS", m_debugger_temp).formatstr("%8s").noshow(); - state_add( STATE_GENSP, "GENSP", REG32(ESP)).noshow(); + state_add( STATE_GENFLAGS, "GENFLAGS", m_debugger_temp).formatstr("%32s").noshow(); } void i386_device::register_state_i386_x87() { register_state_i386(); - state_add( X87_CTRL, "x87_CW", m_x87_cw).formatstr("%04X"); - state_add( X87_STATUS, "x87_SW", m_x87_sw).formatstr("%04X"); - state_add( X87_TAG, "x87_TAG", m_x87_tw).formatstr("%04X"); - state_add( X87_ST0, "ST0", m_debugger_temp ).formatstr("%15s"); - state_add( X87_ST1, "ST1", m_debugger_temp ).formatstr("%15s"); - state_add( X87_ST2, "ST2", m_debugger_temp ).formatstr("%15s"); - state_add( X87_ST3, "ST3", m_debugger_temp ).formatstr("%15s"); - state_add( X87_ST4, "ST4", m_debugger_temp ).formatstr("%15s"); - state_add( X87_ST5, "ST5", m_debugger_temp ).formatstr("%15s"); - state_add( X87_ST6, "ST6", m_debugger_temp ).formatstr("%15s"); - state_add( X87_ST7, "ST7", m_debugger_temp ).formatstr("%15s"); + state_add(X87_CTRL, "x87_CW", m_x87_cw).formatstr("%04X"); + state_add(X87_STATUS,"x87_SW", m_x87_sw).formatstr("%04X"); + state_add(X87_TAG, "x87_TAG", m_x87_tw).formatstr("%04X"); + state_add( X87_ST0, "ST0", m_debugger_temp ).callexport().formatstr("%15s"); + state_add( X87_ST1, "ST1", m_debugger_temp ).callexport().formatstr("%15s"); + state_add( X87_ST2, "ST2", m_debugger_temp ).callexport().formatstr("%15s"); + state_add( X87_ST3, "ST3", m_debugger_temp ).callexport().formatstr("%15s"); + state_add( X87_ST4, "ST4", m_debugger_temp ).callexport().formatstr("%15s"); + state_add( X87_ST5, "ST5", m_debugger_temp ).callexport().formatstr("%15s"); + state_add( X87_ST6, "ST6", m_debugger_temp ).callexport().formatstr("%15s"); + state_add( X87_ST7, "ST7", m_debugger_temp ).callexport().formatstr("%15s"); } void i386_device::register_state_i386_x87_xmm() @@ -2221,6 +2219,30 @@ void i386_device::state_export(const device_state_entry &entry) case I386_IP: m_debugger_temp = m_eip & 0xffff; break; + case X87_ST0: + m_debugger_temp = floatx80_to_float64(ST(0)); + break; + case X87_ST1: + m_debugger_temp = floatx80_to_float64(ST(1)); + break; + case X87_ST2: + m_debugger_temp = floatx80_to_float64(ST(2)); + break; + case X87_ST3: + m_debugger_temp = floatx80_to_float64(ST(3)); + break; + case X87_ST4: + m_debugger_temp = floatx80_to_float64(ST(4)); + break; + case X87_ST5: + m_debugger_temp = floatx80_to_float64(ST(5)); + break; + case X87_ST6: + m_debugger_temp = floatx80_to_float64(ST(6)); + break; + case X87_ST7: + m_debugger_temp = floatx80_to_float64(ST(7)); + break; } } @@ -2229,7 +2251,20 @@ void i386_device::state_string_export(const device_state_entry &entry, std::stri switch (entry.index()) { case STATE_GENFLAGS: - str = string_format("%08X", get_flags()); + str = string_format("%08X %s%s%d%s%s%s%s%s%s%s%s%s", + get_flags(), + m_RF ? "R" : "r", + m_NT ? " N " : " n ", + m_IOP2 << 1 | m_IOP1, + m_OF ? " O" : " o", + m_DF ? " D" : " d", + m_IF ? " I" : " i", + m_TF ? " T" : " t", + m_SF ? " S" : " s", + m_ZF ? " Z" : " z", + m_AF ? " A" : " a", + m_PF ? " P" : " p", + m_CF ? " C" : " c"); break; case X87_ST0: str = string_format("%f", fx80_to_double(ST(0))); @@ -2453,6 +2488,9 @@ void i386_device::zero_state() memset( m_opcode_bytes, 0, sizeof(m_opcode_bytes) ); m_opcode_pc = 0; m_opcode_bytes_length = 0; + memset(m_opcode_addrs, 0, sizeof(m_opcode_addrs)); + m_opcode_addrs_index = 0; + m_dri_changed_active = false; } void i386_device::device_reset() @@ -2507,8 +2545,7 @@ void i386_device::enter_smm() m_cr[0] &= ~(0x8000000d); set_flags(2); - if(!m_smiact.isnull()) - m_smiact(true); + m_smiact(true); m_smm = true; m_smi_latched = false; @@ -2659,8 +2696,7 @@ void i386_device::leave_smm() m_sreg[i].valid = true; } - if (!m_smiact.isnull()) - m_smiact(false); + m_smiact(false); m_smm = false; CHANGE_PC(m_eip); @@ -2742,6 +2778,7 @@ void i386_device::execute_run() if (m_halted) { + debugger_wait_hook(); m_tsc += cycles; m_cycles = 0; return; @@ -2764,10 +2801,10 @@ void i386_device::execute_run() { uint32_t phys_addr = 0; uint32_t error; - phys_addr = (m_cr[0] & (1 << 31)) ? translate_address(m_CPL, TRANSLATE_FETCH, &m_dr[i], &error) : m_dr[i]; + phys_addr = (m_cr[0] & CR0_PG) ? translate_address(m_CPL, TR_FETCH, &m_dr[i], &error) : m_dr[i]; if(breakpoint_length != 0) // Not one byte in length? logerror it, I have no idea how this works on real processors. { - logerror("i386: Breakpoint length not 1 byte on an instruction breakpoint\n"); + LOGMASKED(LOG_INVALID_OPCODE, "i386: Breakpoint length not 1 byte on an instruction breakpoint\n"); } if(m_pc == phys_addr) { @@ -2802,6 +2839,8 @@ void i386_device::execute_run() #ifdef DEBUG_MISSING_OPCODE m_opcode_bytes_length = 0; m_opcode_pc = m_pc; + m_opcode_addrs[m_opcode_addrs_index] = m_opcode_pc; + m_opcode_addrs_index = (m_opcode_addrs_index + 1) & 15; #endif try { @@ -2829,11 +2868,12 @@ void i386_device::execute_run() /*************************************************************************/ -bool i386_device::memory_translate(int spacenum, int intention, offs_t &address) +bool i386_device::memory_translate(int spacenum, int intention, offs_t &address, address_space *&target_space) { + target_space = &space(spacenum); bool ret = true; if(spacenum == AS_PROGRAM) - ret = i386_translate_address(intention, &address, nullptr); + ret = i386_translate_address(intention, true, &address, nullptr); address &= m_a20_mask; return ret; } @@ -2850,20 +2890,20 @@ std::unique_ptr<util::disasm_interface> i386_device::create_disassembler() void i386_device::opcode_cpuid() { - logerror("CPUID called with unsupported EAX=%08x at %08x!\n", REG32(EAX), m_eip); + LOGMASKED(LOG_MSR, "CPUID called with unsupported EAX=%08x at %08x!\n", REG32(EAX), m_eip); } uint64_t i386_device::opcode_rdmsr(bool &valid_msr) { valid_msr = false; - logerror("RDMSR called with unsupported ECX=%08x at %08x!\n", REG32(ECX), m_eip); + LOGMASKED(LOG_MSR, "RDMSR called with unsupported ECX=%08x at %08x!\n", REG32(ECX), m_eip); return -1; } void i386_device::opcode_wrmsr(uint64_t data, bool &valid_msr) { valid_msr = false; - logerror("WRMSR called with unsupported ECX=%08x (%08x%08x) at %08x!\n", REG32(ECX), (uint32_t)(data >> 32), (uint32_t)data, m_eip); + LOGMASKED(LOG_MSR, "WRMSR called with unsupported ECX=%08x (%08x%08x) at %08x!\n", REG32(ECX), (uint32_t)(data >> 32), (uint32_t)data, m_eip); } /*****************************************************************************/ @@ -3339,12 +3379,38 @@ void pentium3_device::device_reset() // [ 0:0] FPU on chip // [ 4:4] Time Stamp Counter + // [ 8:8] CMPXCHG8B instruction // [ D:D] PTE Global Bit - m_feature_flags = 0x00002011; // TODO: enable relevant flags here + // [15:15] CMOV and FCMOV + // [18:18] PSN (Processor Serial Number, P3 only) + m_feature_flags = 0x0004a111; // TODO: enable relevant flags here CHANGE_PC(m_eip); } +void pentium3_device::opcode_cpuid() +{ + switch (REG32(EAX)) + { + case 0x00000003: + { + // TODO: lower part of 96 bits s/n for Pentium III processors only (ditched in 4) + // (upper 32-bits part is in EAX=1 EAX return) + // NB: if this is triggered from an Arcade system then there's a very good chance + // that is trying to tie the serial as a form of copy protection cfr. gamecstl + LOGMASKED(LOG_MSR, "CPUID with EAX=00000003 (Pentium III PSN?) at %08x!\n", m_eip); + REG32(EAX) = 0x00000000; + REG32(EBX) = 0x00000000; + REG32(ECX) = 0x01234567; + REG32(EDX) = 0x89abcdef; + CYCLES(CYCLES_CPUID); + break; + } + default: + pentium_pro_device::opcode_cpuid(); + } +} + /*****************************************************************************/ /* Intel Pentium 4 */ @@ -3408,7 +3474,9 @@ void pentium4_device::device_reset() m_cpu_version = REG32(EDX); // [ 0:0] FPU on chip - m_feature_flags = 0x00000001; // TODO: enable relevant flags here + // [ 8:8] CMPXCHG8B instruction + // [15:15] CMOV and FCMOV + m_feature_flags = 0x00008101; // TODO: enable relevant flags here CHANGE_PC(m_eip); } |