diff options
Diffstat (limited to 'src/devices/cpu/arm7/arm7.cpp')
-rw-r--r-- | src/devices/cpu/arm7/arm7.cpp | 136 |
1 files changed, 97 insertions, 39 deletions
diff --git a/src/devices/cpu/arm7/arm7.cpp b/src/devices/cpu/arm7/arm7.cpp index 6151e712186..7f479a668d4 100644 --- a/src/devices/cpu/arm7/arm7.cpp +++ b/src/devices/cpu/arm7/arm7.cpp @@ -29,21 +29,23 @@ TODO: - Fix and finish the DRC code, or remove it entirely *****************************************************************************/ + #include "emu.h" #include "debug/debugcon.h" -#include "debug/debugcmd.h" #include "debugger.h" #include "arm7.h" #include "arm7core.h" //include arm7 core #include "arm7help.h" -#define LOG_MMU (1 << 0) -#define LOG_DSP (1 << 1) -#define LOG_COPRO_READS (1 << 2) -#define LOG_COPRO_WRITES (1 << 3) -#define LOG_COPRO_UNKNOWN (1 << 4) -#define LOG_COPRO_RESERVED (1 << 5) -#define LOG_TLB (1 << 6) +#define LOG_MMU (1U << 1) +#define LOG_DSP (1U << 2) +#define LOG_COPRO_READS (1U << 3) +#define LOG_COPRO_WRITES (1U << 4) +#define LOG_COPRO_UNKNOWN (1U << 5) +#define LOG_COPRO_RESERVED (1U << 6) +#define LOG_TLB (1U << 7) +#define LOG_TLB_MISS (1U << 8) +#define LOG_PREFETCH (1U << 9) #define VERBOSE (0) // (LOG_COPRO_READS | LOG_COPRO_WRITES | LOG_COPRO_UNKNOWN | LOG_COPRO_RESERVED) #include "logmacro.h" @@ -297,6 +299,7 @@ void arm7_cpu_device::update_reg_ptr() void arm7_cpu_device::set_cpsr(uint32_t val) { uint8_t old_mode = GET_CPSR & MODE_FLAG; + bool call_hook = false; if (m_archFlags & ARCHFLAG_MODE26) { if ((val & 0x10) != (m_r[eCPSR] & 0x10)) @@ -312,6 +315,7 @@ void arm7_cpu_device::set_cpsr(uint32_t val) // 32 -> 26 m_r[eR15] = (m_r[eR15] & 0x03FFFFFC) /* PC */ | (val & 0xF0000000) /* N Z C V */ | ((val & 0x000000C0) << (26 - 6)) /* I F */ | (val & 0x00000003) /* M1 M0 */; } + call_hook = true; } else { @@ -326,11 +330,17 @@ void arm7_cpu_device::set_cpsr(uint32_t val) { val |= 0x10; // force valid mode } + if ((val & T_MASK) != (m_r[eCPSR] & T_MASK)) + call_hook = true; m_r[eCPSR] = val; if ((GET_CPSR & MODE_FLAG) != old_mode) { + if ((GET_CPSR & MODE_FLAG) == eARM7_MODE_USER || old_mode == eARM7_MODE_USER) + call_hook = true; update_reg_ptr(); } + if (call_hook) + debugger_privilege_hook(); } @@ -700,9 +710,12 @@ bool arm7_cpu_device::page_table_translate(offs_t &vaddr, const int flags) const uint32_t lvl1_addr = m_tlb_base_mask | ((vaddr & COPRO_TLB_VADDR_FLTI_MASK) >> COPRO_TLB_VADDR_FLTI_MASK_SHIFT); const uint32_t lvl1_desc = m_program->read_dword(lvl1_addr); + LOGMASKED(LOG_MMU, "ARM7: Translating page table entry for %08x, lvl1_addr %08x, lvl1_desc %08x\n", vaddr, lvl1_addr, lvl1_desc); + switch (lvl1_desc & 3) { case 0: // Unmapped + LOGMASKED(LOG_MMU, "ARM7: Translating page table entry for %08x, Unmapped, lvl1a %08x, lvl1d %08x\n", vaddr, lvl1_addr, lvl1_desc); if (flags & ARM7_TLB_ABORT_D) { LOGMASKED(LOG_MMU, "ARM7: Page Table Translation failed (D), PC %08x, lvl1 unmapped, vaddr = %08x, lvl1A = %08x, lvl1D = %08x\n", m_r[eR15], vaddr, lvl1_addr, lvl1_desc); @@ -722,6 +735,8 @@ bool arm7_cpu_device::page_table_translate(offs_t &vaddr, const int flags) const uint32_t lvl2_addr = (lvl1_desc & COPRO_TLB_CFLD_ADDR_MASK) | ((vaddr & COPRO_TLB_VADDR_CSLTI_MASK) >> COPRO_TLB_VADDR_CSLTI_MASK_SHIFT); const uint32_t lvl2_desc = m_program->read_dword(lvl2_addr); + LOGMASKED(LOG_MMU, "ARM7: Translating page table entry for %08x, Coarse, lvl1a %08x, lvl1d %08x, lvl2a %08x, lvl2d %08x\n", vaddr, lvl1_addr, lvl1_desc, lvl2_addr, lvl2_desc); + switch (lvl2_desc & 3) { case 0: // Unmapped @@ -753,6 +768,7 @@ bool arm7_cpu_device::page_table_translate(offs_t &vaddr, const int flags) } case 2: // Section Descriptor + LOGMASKED(LOG_MMU, "ARM7: Translating page table entry for %08x, Section, lvl1a %08x, lvl1d %08x\n", vaddr, lvl1_addr, lvl1_desc); return page_table_finish_translation(vaddr, COPRO_TLB_TYPE_SECTION, lvl1_desc, lvl1_desc, flags, lvl1_addr, lvl1_addr); case 3: // Fine Table @@ -760,6 +776,8 @@ bool arm7_cpu_device::page_table_translate(offs_t &vaddr, const int flags) const uint32_t lvl2_addr = (lvl1_desc & COPRO_TLB_FPTB_ADDR_MASK) | ((vaddr & COPRO_TLB_VADDR_FSLTI_MASK) >> COPRO_TLB_VADDR_FSLTI_MASK_SHIFT); const uint32_t lvl2_desc = m_program->read_dword(lvl2_addr); + LOGMASKED(LOG_MMU, "ARM7: Translating page table entry for %08x, Fine, lvl1a %08x, lvl1d %08x, lvl2a %08x, lvl2d %08x\n", vaddr, lvl1_addr, lvl1_desc, lvl2_addr, lvl2_desc); + switch (lvl2_desc & 3) { case 0: // Unmapped @@ -837,44 +855,46 @@ bool arm7_cpu_device::translate_vaddr_to_paddr(offs_t &vaddr, const int flags) } else { + if (m_tlb_log) + LOGMASKED(LOG_MMU, "No TLB entry for %08x yet, running page_table_translate\n", vaddr); return page_table_translate(vaddr, flags); } } -void arm7_cpu_device::translate_insn_command(const std::vector<std::string> ¶ms) +void arm7_cpu_device::translate_insn_command(const std::vector<std::string_view> ¶ms) { - translate_command(params, TRANSLATE_FETCH); + translate_command(params, TR_FETCH); } -void arm7_cpu_device::translate_data_command(const std::vector<std::string> ¶ms) +void arm7_cpu_device::translate_data_command(const std::vector<std::string_view> ¶ms) { - translate_command(params, TRANSLATE_READ); + translate_command(params, TR_READ); } -void arm7_cpu_device::translate_command(const std::vector<std::string> ¶ms, int intention) +void arm7_cpu_device::translate_command(const std::vector<std::string_view> ¶ms, int intention) { uint64_t vaddr; - if (!machine().debugger().commands().validate_number_parameter(params[0], vaddr)) return; + if (!machine().debugger().console().validate_number_parameter(params[0], vaddr)) return; vaddr &= 0xffffffff; offs_t paddr = (offs_t)vaddr; - bool can_translate = memory_translate(AS_PROGRAM, intention, paddr); + address_space *space = nullptr; + bool can_translate = memory_translate(AS_PROGRAM, intention, paddr, space); if (can_translate) - machine().debugger().console().printf("%s vaddr %08x => phys %08x\n", intention == TRANSLATE_FETCH ? "instruction" : "data", (uint32_t)vaddr, paddr); + machine().debugger().console().printf("%s vaddr %08x => phys %08x\n", intention == TR_FETCH ? "instruction" : "data", (uint32_t)vaddr, paddr); else - machine().debugger().console().printf("%s vaddr %08x => unmapped\n", intention == TRANSLATE_FETCH ? "instruction" : "data"); + machine().debugger().console().printf("%s vaddr %08x => unmapped\n", intention == TR_FETCH ? "instruction" : "data"); } -bool arm7_cpu_device::memory_translate(int spacenum, int intention, offs_t &address) +bool arm7_cpu_device::memory_translate(int spacenum, int intention, offs_t &address, address_space *&target_space) { + target_space = &space(spacenum); /* only applies to the program address space and only does something if the MMU's enabled */ if (spacenum == AS_PROGRAM && (m_control & COPRO_CTRL_MMU_EN)) { - int intention_type = intention & TRANSLATE_TYPE_MASK; - - const int flags = (intention_type & TRANSLATE_FETCH) ? ARM7_TLB_ABORT_P : ARM7_TLB_ABORT_D; + const int flags = intention == TR_FETCH ? ARM7_TLB_ABORT_P : ARM7_TLB_ABORT_D; if (address < 0x2000000) address += m_pid_offset; @@ -1143,29 +1163,37 @@ void arm7_cpu_device::update_insn_prefetch(uint32_t curr_pc) curr_pc &= ~3; if (m_insn_prefetch_address[m_insn_prefetch_index] != curr_pc) { + LOGMASKED(LOG_PREFETCH, "Prefetch addr %08x doesn't match curr_pc %08x, flushing prefetch buffer\n", m_insn_prefetch_address[m_insn_prefetch_index], curr_pc); m_insn_prefetch_count = 0; m_insn_prefetch_index = 0; } if (m_insn_prefetch_count == m_insn_prefetch_depth) + { + LOGMASKED(LOG_PREFETCH, "We have prefetched up to the max depth, bailing\n"); return; + } const uint32_t to_fetch = m_insn_prefetch_depth - m_insn_prefetch_count; const uint32_t start_index = (m_insn_prefetch_depth + (m_insn_prefetch_index - to_fetch)) % m_insn_prefetch_depth; //printf("need to prefetch %d instructions starting at index %d\n", to_fetch, start_index); + LOGMASKED(LOG_PREFETCH, "Need to fetch %d entries starting from index %d\n", to_fetch, start_index); uint32_t pc = curr_pc + m_insn_prefetch_count * 4; for (uint32_t i = 0; i < to_fetch; i++) { uint32_t index = (i + start_index) % m_insn_prefetch_depth; + LOGMASKED(LOG_PREFETCH, "About to get prefetch index %d from addr %08x\n", index, pc); m_insn_prefetch_valid[index] = true; offs_t physical_pc = pc; if ((m_control & COPRO_CTRL_MMU_EN) && !translate_vaddr_to_paddr(physical_pc, ARM7_TLB_ABORT_P | ARM7_TLB_READ)) { + LOGMASKED(LOG_PREFETCH, "Unable to fetch, bailing\n"); m_insn_prefetch_valid[index] = false; break; } uint32_t op = m_pr32(physical_pc); + LOGMASKED(LOG_PREFETCH, "Got op %08x\n", op); //printf("ipb[%d] <- %08x(%08x)\n", index, op, pc); m_insn_prefetch_buffer[index] = op; m_insn_prefetch_address[index] = pc; @@ -1193,6 +1221,7 @@ bool arm7_cpu_device::insn_fetch_arm(uint32_t pc, uint32_t &out_insn) //printf("ipb[%d] = %08x\n", m_insn_prefetch_index, m_insn_prefetch_buffer[m_insn_prefetch_index]); out_insn = m_insn_prefetch_buffer[m_insn_prefetch_index]; bool valid = m_insn_prefetch_valid[m_insn_prefetch_index]; + LOGMASKED(LOG_PREFETCH, "Fetched op %08x for PC %08x with %s entry from %08x\n", out_insn, pc, valid ? "valid" : "invalid", m_insn_prefetch_address[m_insn_prefetch_index]); m_insn_prefetch_index = (m_insn_prefetch_index + 1) % m_insn_prefetch_depth; m_insn_prefetch_count--; return valid; @@ -1797,7 +1826,7 @@ void arm7_cpu_device::arm7_rt_w_callback(offs_t offset, uint32_t data) // LOGMASKED(LOG_COPRO_WRITES, "arm7_rt_w_callback Cache Ops = %08x (%d) (%d)\n", data, op2, op3); break; case 8: // TLB Operations - LOGMASKED(LOG_COPRO_WRITES, "arm7_rt_w_callback TLB Ops = %08x (%d) (%d), PC = %08x\n", data, op2, op3, m_r[eR15]); + LOGMASKED(LOG_COPRO_WRITES, "%s: arm7_rt_w_callback TLB Ops = %08x (%d) (%d), PC = %08x\n", machine().describe_context(), data, op2, op3, m_r[eR15]); switch (op2) { case 0: @@ -1831,18 +1860,51 @@ void arm7_cpu_device::arm7_rt_w_callback(offs_t offset, uint32_t data) } break; case 1: - if (op3 == 6) + switch (op3) { - // Flush D single entry - tlb_entry *entry = tlb_map_entry(m_r[op3], ARM7_TLB_ABORT_D); - if (entry) + case 5: { - entry->valid = false; + // Flush I single entry + tlb_entry *entry = tlb_probe(data, ARM7_TLB_ABORT_P); + if (entry) + { + LOGMASKED(LOG_COPRO_WRITES, "arm7_rt_w_callback TLB Ops: Successfully flushed I entry for %08x\n", data); + entry->valid = false; + } + break; } - } - else - { - LOGMASKED(LOG_COPRO_WRITES, "arm7_rt_w_callback Unsupported TLB Op\n"); + + case 6: + { + // Flush D single entry + tlb_entry *entry = tlb_probe(data, ARM7_TLB_ABORT_D); + if (entry) + { + LOGMASKED(LOG_COPRO_WRITES, "arm7_rt_w_callback TLB Ops: Successfully flushed D entry for %08x\n", data); + entry->valid = false; + } + break; + } + case 7: + { + // Flush unified single entry + tlb_entry *entry = tlb_probe(data, ARM7_TLB_ABORT_D); + if (entry) + { + LOGMASKED(LOG_COPRO_WRITES, "arm7_rt_w_callback TLB Ops: Successfully flushed D entry for %08x\n", data); + entry->valid = false; + } + entry = tlb_probe(data, ARM7_TLB_ABORT_P); + if (entry) + { + LOGMASKED(LOG_COPRO_WRITES, "arm7_rt_w_callback TLB Ops: Successfully flushed I entry for %08x\n", data); + entry->valid = false; + } + break; + } + default: + LOGMASKED(LOG_COPRO_WRITES, "arm7_rt_w_callback Unsupported TLB Op\n"); + break; } break; } @@ -2069,8 +2131,7 @@ uint32_t arm946es_cpu_device::arm7_cpu_read32(uint32_t addr) if (addr & 3) { uint32_t *wp = (uint32_t *)&ITCM[(addr & ~3)&0x7fff]; - result = *wp; - result = (result >> (8 * (addr & 3))) | (result << (32 - (8 * (addr & 3)))); + result = rotr_32(*wp, 8 * (addr & 3)); } else { @@ -2083,8 +2144,7 @@ uint32_t arm946es_cpu_device::arm7_cpu_read32(uint32_t addr) if (addr & 3) { uint32_t *wp = (uint32_t *)&DTCM[(addr & ~3)&0x3fff]; - result = *wp; - result = (result >> (8 * (addr & 3))) | (result << (32 - (8 * (addr & 3)))); + result = rotr_32(*wp, 8 * (addr & 3)); } else { @@ -2096,8 +2156,7 @@ uint32_t arm946es_cpu_device::arm7_cpu_read32(uint32_t addr) { if (addr & 3) { - result = m_program->read_dword(addr & ~3); - result = (result >> (8 * (addr & 3))) | (result << (32 - (8 * (addr & 3)))); + result = rotr_32(m_program->read_dword(addr & ~3), 8 * (addr & 3)); } else { @@ -2267,8 +2326,7 @@ uint32_t arm7_cpu_device::arm7_cpu_read32(uint32_t addr) if (addr & 3) { - result = m_program->read_dword(addr & ~3); - result = (result >> (8 * (addr & 3))) | (result << (32 - (8 * (addr & 3)))); + result = rotr_32(m_program->read_dword(addr & ~3), 8 * (addr & 3)); } else { |