From aad19c92f57bf7b9c639441d3a51f237583dc652 Mon Sep 17 00:00:00 2001 From: Patrick Mackinlay Date: Tue, 7 Jan 2020 14:53:41 +0700 Subject: r4000: fix bad virtual address for [ls][dw][lr] exceptions (nw) * get rid of _t type name suffixes * improve logging --- src/devices/cpu/mips/r4000.cpp | 67 ++++++++++++++++++++++++------------------ src/devices/cpu/mips/r4000.h | 16 +++++----- 2 files changed, 46 insertions(+), 37 deletions(-) diff --git a/src/devices/cpu/mips/r4000.cpp b/src/devices/cpu/mips/r4000.cpp index 7b26493f61c..f490d7465cc 100644 --- a/src/devices/cpu/mips/r4000.cpp +++ b/src/devices/cpu/mips/r4000.cpp @@ -85,7 +85,7 @@ DEFINE_DEVICE_TYPE(R4000, r4000_device, "r4000", "MIPS R4000") DEFINE_DEVICE_TYPE(R4400, r4400_device, "r4400", "MIPS R4400") DEFINE_DEVICE_TYPE(R4600, r4600_device, "r4600", "QED R4600") -r4000_base_device::r4000_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u32 prid, u32 fcr, cache_size_t icache_size, cache_size_t dcache_size) +r4000_base_device::r4000_base_device(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock, u32 prid, u32 fcr, cache_size icache_size, cache_size dcache_size) : cpu_device(mconfig, type, tag, owner, clock) , m_program_config_le("program", ENDIANNESS_LITTLE, 64, 32) , m_program_config_be("program", ENDIANNESS_BIG, 64, 32) @@ -189,6 +189,7 @@ void r4000_base_device::device_reset() { m_branch_state = NONE; m_pc = s64(s32(0xbfc00000)); + m_r[0] = 0; m_cp0[CP0_Status] = SR_BEV | SR_ERL; m_cp0[CP0_Wired] = 0; @@ -240,7 +241,7 @@ bool r4000_base_device::memory_translate(int spacenum, int intention, offs_t &ad // FIXME: address truncation u64 placeholder = s32(address); - translate_t const t = translate(intention, placeholder); + translate_result const t = translate(intention, placeholder); if (t == ERROR || t == MISS) return false; @@ -1146,7 +1147,7 @@ void r4000_base_device::cpu_lwl(u32 const op) u64 const offset = ADDR(m_r[RSREG], s16(op)); unsigned const shift = ((offset & 3) ^ R4000_ENDIAN_LE_BE(3, 0)) << 3; - load(offset & ~3, + load(offset, [this, op, shift](u32 const data) { m_r[RTREG] = s32((m_r[RTREG] & ~u32(~u32(0) << shift)) | (data << shift)); @@ -1158,7 +1159,7 @@ void r4000_base_device::cpu_lwr(u32 const op) u64 const offset = ADDR(m_r[RSREG], s16(op)); unsigned const shift = ((offset & 0x3) ^ R4000_ENDIAN_LE_BE(0, 3)) << 3; - load(offset & ~3, + load(offset, [this, op, shift](u32 const data) { m_r[RTREG] = s32((m_r[RTREG] & ~u32(~u32(0) >> shift)) | (data >> shift)); @@ -1170,7 +1171,7 @@ void r4000_base_device::cpu_swl(u32 const op) u64 const offset = ADDR(m_r[RSREG], s16(op)); unsigned const shift = ((offset & 3) ^ R4000_ENDIAN_LE_BE(3, 0)) << 3; - store(offset & ~3, u32(m_r[RTREG]) >> shift, ~u32(0) >> shift); + store(offset, u32(m_r[RTREG]) >> shift, ~u32(0) >> shift); } void r4000_base_device::cpu_swr(u32 const op) @@ -1178,7 +1179,7 @@ void r4000_base_device::cpu_swr(u32 const op) u64 const offset = ADDR(m_r[RSREG], s16(op)); unsigned const shift = ((offset & 3) ^ R4000_ENDIAN_LE_BE(0, 3)) << 3; - store(offset & ~3, u32(m_r[RTREG]) << shift, ~u32(0) << shift); + store(offset, u32(m_r[RTREG]) << shift, ~u32(0) << shift); } void r4000_base_device::cpu_ldl(u32 const op) @@ -1186,7 +1187,7 @@ void r4000_base_device::cpu_ldl(u32 const op) u64 const offset = ADDR(m_r[RSREG], s16(op)); unsigned const shift = ((offset & 7) ^ R4000_ENDIAN_LE_BE(7, 0)) << 3; - load(offset & ~7, + load(offset, [this, op, shift](u64 const data) { m_r[RTREG] = (m_r[RTREG] & ~u64(~u64(0) << shift)) | (data << shift); @@ -1198,7 +1199,7 @@ void r4000_base_device::cpu_ldr(u32 const op) u64 const offset = ADDR(m_r[RSREG], s16(op)); unsigned const shift = ((offset & 7) ^ R4000_ENDIAN_LE_BE(0, 7)) << 3; - load(offset & ~7, + load(offset, [this, op, shift](u64 const data) { m_r[RTREG] = (m_r[RTREG] & ~u64(~u64(0) >> shift)) | (data >> shift); @@ -1210,7 +1211,7 @@ void r4000_base_device::cpu_sdl(u32 const op) u64 const offset = ADDR(m_r[RSREG], s16(op)); unsigned const shift = ((offset & 7) ^ R4000_ENDIAN_LE_BE(7, 0)) << 3; - store(offset & ~7, m_r[RTREG] >> shift, ~u64(0) >> shift); + store(offset, m_r[RTREG] >> shift, ~u64(0) >> shift); } void r4000_base_device::cpu_sdr(u32 const op) @@ -1218,7 +1219,7 @@ void r4000_base_device::cpu_sdr(u32 const op) u64 const offset = ADDR(m_r[RSREG], s16(op)); unsigned const shift = ((offset & 7) ^ R4000_ENDIAN_LE_BE(0, 7)) << 3; - store(offset & ~7, m_r[RTREG] << shift, ~u64(0) << shift); + store(offset, m_r[RTREG] << shift, ~u64(0) << shift); } void r4000_base_device::cp0_execute(u32 const op) @@ -1469,7 +1470,7 @@ void r4000_base_device::cp0_tlbr() if (index < ARRAY_LENGTH(m_tlb)) { - tlb_entry_t const &entry = m_tlb[index]; + tlb_entry const &entry = m_tlb[index]; m_cp0[CP0_PageMask] = entry.mask; m_cp0[CP0_EntryHi] = entry.vpn; @@ -1482,7 +1483,7 @@ void r4000_base_device::cp0_tlbwi(u8 const index) { if (index < ARRAY_LENGTH(m_tlb)) { - tlb_entry_t &entry = m_tlb[index]; + tlb_entry &entry = m_tlb[index]; entry.mask = m_cp0[CP0_PageMask]; entry.vpn = m_cp0[CP0_EntryHi] & EH_WM; @@ -1517,7 +1518,7 @@ void r4000_base_device::cp0_tlbp() m_cp0[CP0_Index] = 0x80000000; for (u8 index = 0; index < ARRAY_LENGTH(m_tlb); index++) { - tlb_entry_t const &entry = m_tlb[index]; + tlb_entry const &entry = m_tlb[index]; u64 const mask = (cp0_64() ? EH_R | (EH_VPN2_64 & ~entry.mask) : (EH_VPN2_32 & ~entry.mask)) | ((entry.vpn & EH_G) ? 0 : EH_ASID); @@ -1530,9 +1531,9 @@ void r4000_base_device::cp0_tlbp() } if (m_cp0[CP0_Index] == 0x80000000) - LOGMASKED(LOG_TLB, "tlbp miss 0x%08x\n", m_cp0[CP0_EntryHi]); + LOGMASKED(LOG_TLB, "tlbp miss 0x%08x (%s)\n", m_cp0[CP0_EntryHi], machine().describe_context()); else - LOGMASKED(LOG_TLB, "tlbp hit 0x%08x index %02d\n", m_cp0[CP0_EntryHi], m_cp0[CP0_Index]); + LOGMASKED(LOG_TLB, "tlbp hit 0x%08x index %02d (%s)\n", m_cp0[CP0_EntryHi], m_cp0[CP0_Index], machine().describe_context()); } void r4000_base_device::cp0_update_timer(bool start) @@ -2727,7 +2728,7 @@ void r4000_base_device::cp2_execute(u32 const op) } } -r4000_base_device::translate_t r4000_base_device::translate(int intention, u64 &address) +r4000_base_device::translate_result r4000_base_device::translate(int intention, u64 &address) { /* * Decode the program address into one of the following ranges depending on @@ -2890,7 +2891,7 @@ r4000_base_device::translate_t r4000_base_device::translate(int intention, u64 & for (unsigned i = 0; i < ARRAY_LENGTH(m_tlb); i++) { unsigned const index = mru[i]; - tlb_entry_t const &entry = m_tlb[index]; + tlb_entry const &entry = m_tlb[index]; // test vpn and asid u64 const mask = (extended ? EH_R | (EH_VPN2_64 & ~entry.mask) : (EH_VPN2_32 & ~entry.mask)) @@ -2934,13 +2935,13 @@ r4000_base_device::translate_t r4000_base_device::translate(int intention, u64 & { if (VERBOSE & LOG_TLB) { - char const mode[] = { 'r', 'w', 'x' }; + static char const mode[] = { 'r', 'w', 'x' }; if (modify) - LOGMASKED(LOG_TLB, "tlb modify asid %d address 0x%016x (%s)\n", - m_cp0[CP0_EntryHi] & EH_ASID, address, machine().describe_context()); + LOGMASKED(LOG_TLB, "tlb modify asid 0x%02x address 0x%016x (%s)\n", + m_cp0[CP0_EntryHi] & EH_ASID, address, machine().describe_context()); else - LOGMASKED(LOG_TLB, "tlb miss %c asid %d address 0x%016x (%s)\n", + LOGMASKED(LOG_TLB, "tlb miss %c asid 0x%02x address 0x%016x (%s)\n", mode[intention & TRANSLATE_TYPE_MASK], m_cp0[CP0_EntryHi] & EH_ASID, address, machine().describe_context()); } @@ -2976,16 +2977,16 @@ void r4000_base_device::address_error(int intention, u64 const address) } } -template std::enable_if_t>::value, bool> r4000_base_device::load(u64 address, U &&apply) +template std::enable_if_t>::value, bool> r4000_base_device::load(u64 address, U &&apply) { // alignment error - if (address & (sizeof(T) - 1)) + if (Aligned && (address & (sizeof(T) - 1))) { address_error(TRANSLATE_READ, address); return false; } - translate_t const t = translate(TRANSLATE_READ, address); + translate_result const t = translate(TRANSLATE_READ, address); // address error if (t == ERROR) @@ -3011,6 +3012,10 @@ template std::enable_if_t std::enable_if_t std::enable_if_t std::enable_if_t::value, bool> r4000_base_device::store(u64 address, U data, T mem_mask) +template std::enable_if_t::value, bool> r4000_base_device::store(u64 address, U data, T mem_mask) { // alignment error - if (address & (sizeof(T) - 1)) + if (Aligned && (address & (sizeof(T) - 1))) { address_error(TRANSLATE_WRITE, address); return false; } - translate_t const t = translate(TRANSLATE_WRITE, address); + translate_result const t = translate(TRANSLATE_WRITE, address); // address error if (t == ERROR) @@ -3114,6 +3119,10 @@ template std::enable_if_t::va } } + // align address for s[dw][lr] instructions + if (!Aligned) + address &= ~(sizeof(T) - 1); + // TODO: cache lookup switch (sizeof(T)) @@ -3139,7 +3148,7 @@ bool r4000_base_device::fetch(u64 address, std::function &&apply) return false; } - translate_t const t = translate(TRANSLATE_FETCH, address); + translate_result const t = translate(TRANSLATE_FETCH, address); // address error if (t == ERROR) diff --git a/src/devices/cpu/mips/r4000.h b/src/devices/cpu/mips/r4000.h index 80aac4ef56b..8c4906263ba 100644 --- a/src/devices/cpu/mips/r4000.h +++ b/src/devices/cpu/mips/r4000.h @@ -45,7 +45,7 @@ public: void bus_error() { m_bus_error = true; } protected: - enum cache_size_t + enum cache_size { CACHE_4K = 0, CACHE_8K = 1, @@ -56,7 +56,7 @@ protected: CACHE_256K = 6, CACHE_512K = 7, }; - r4000_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u32 prid, u32 fcr, cache_size_t icache_size, cache_size_t dcache_size); + r4000_base_device(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock, u32 prid, u32 fcr, cache_size icache_size, cache_size dcache_size); enum cp0_reg : int { @@ -361,13 +361,13 @@ protected: void cp2_execute(u32 const op); // address and memory handling - enum translate_t { ERROR, MISS, UNCACHED, CACHED }; - translate_t translate(int intention, u64 &address); + enum translate_result { ERROR, MISS, UNCACHED, CACHED }; + translate_result translate(int intention, u64 &address); void address_error(int intention, u64 const address); - template std::enable_if_t>::value, bool> load(u64 program_address, U &&apply); + template std::enable_if_t>::value, bool> load(u64 program_address, U &&apply); template std::enable_if_t>::value, bool> load_linked(u64 program_address, U &&apply); - template std::enable_if_t::value, bool> store(u64 program_address, U data, T mem_mask = ~T(0)); + template std::enable_if_t::value, bool> store(u64 program_address, U data, T mem_mask = ~T(0)); bool fetch(u64 address, std::function &&apply); // debugging helpers @@ -387,7 +387,7 @@ protected: u64 m_r[32]; u64 m_hi; u64 m_lo; - enum branch_state_t : unsigned + enum branch_state : unsigned { NONE = 0, DELAY = 1, // delay slot instruction active @@ -404,7 +404,7 @@ protected: emu_timer *m_cp0_timer; bool m_ll_active; bool m_bus_error; - struct tlb_entry_t + struct tlb_entry { u64 mask; u64 vpn; -- cgit v1.2.3