summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/arm7/arm7.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/arm7/arm7.cpp')
-rw-r--r--src/devices/cpu/arm7/arm7.cpp136
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> &params)
+void arm7_cpu_device::translate_insn_command(const std::vector<std::string_view> &params)
{
- translate_command(params, TRANSLATE_FETCH);
+ translate_command(params, TR_FETCH);
}
-void arm7_cpu_device::translate_data_command(const std::vector<std::string> &params)
+void arm7_cpu_device::translate_data_command(const std::vector<std::string_view> &params)
{
- translate_command(params, TRANSLATE_READ);
+ translate_command(params, TR_READ);
}
-void arm7_cpu_device::translate_command(const std::vector<std::string> &params, int intention)
+void arm7_cpu_device::translate_command(const std::vector<std::string_view> &params, 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
{