diff options
Diffstat (limited to 'src/mame/machine/cammu.cpp')
-rw-r--r-- | src/mame/machine/cammu.cpp | 548 |
1 files changed, 315 insertions, 233 deletions
diff --git a/src/mame/machine/cammu.cpp b/src/mame/machine/cammu.cpp index 4e1d86b2076..5686cfa7d2e 100644 --- a/src/mame/machine/cammu.cpp +++ b/src/mame/machine/cammu.cpp @@ -2,28 +2,43 @@ // copyright-holders:Patrick Mackinlay /* - * An implementation of the Fairchild/Intergraph Cache and Memory Management Unit (CAMMU) designed for use with the CLIPPER CPU family. + * An implementation of the Fairchild/Intergraph Cache and Memory Management + * Unit (CAMMU) designed for use with the CLIPPER CPU family. * - * Primary reference: http://bitsavers.trailing-edge.com/pdf/fairchild/clipper/CLIPPER%20C300%2032-Bit%20Compute%20Engine.pdf - * Another reference: http://www.eecs.berkeley.edu/Pubs/TechRpts/1986/CSD-86-289.pdf + * The C100 and C300 designs used a pair of identical CAMMU devices, each + * containing a cache, TLB and dynamic translation unit. One device was + * configured and used for instruction memory, the other for data. It is + * possible to write to multiple CAMMU devices sharing a common system bus by + * using "global" register addresses. + * + * C400 designs initially implemented the memory management and cache functions + * using discrete logic, later using a more highly integrated memory management + * implementation, but still using discrete cache memory. In these systems, the + * mmu is consolidated into a single logical unit handling both instruction and + * data memory, with distinctly different program-visible architectures on the + * C4I and C4E/T devices. Almost no documentation for these has been located. * - * This implementation is currently at a very early stage, and is only sufficient to handle the bare minimum of boot/diagnostic code. + * Primary reference: http://bitsavers.org/pdf/fairchild/clipper/CLIPPER%20C300%2032-Bit%20Compute%20Engine.pdf + * Another reference: http://www.eecs.berkeley.edu/Pubs/TechRpts/1986/CSD-86-289.pdf * * TODO - * - almost everything - * - refactor hardware tlb - * - faults - * - tlb + * - fault register values + * - alignment faults + * - c3 protection faults + * - hard-wired and dynamic tlb * - cache * - bus errors */ #include "emu.h" +#include "cammu.h" -#define VERBOSE 0 -#define DTU 1 // enable preliminary/incomplete address translation +#define LOG_GENERAL (1U << 0) +#define LOG_ACCESS (1U << 1) +#define LOG_DTU (1U << 2) -#include "cammu.h" +//#define VERBOSE (LOG_GENERAL | LOG_ACCESS | LOG_DTU) +#include "logmacro.h" // each variant of the cammu has different registers and a different addressing map DEVICE_ADDRESS_MAP_START(map, 32, cammu_c4t_device) @@ -75,28 +90,21 @@ DEVICE_ADDRESS_MAP_START(map, 32, cammu_c4i_device) ADDRESS_MAP_END DEVICE_ADDRESS_MAP_START(map, 32, cammu_c3_device) - // the first AM_NOP in each range is in fact the TLB in the C3 CAMMU - - AM_RANGE(0x800, 0x8ff) AM_NOP - AM_RANGE(0x904, 0x907) AM_READWRITE(d_s_pdo_r, d_s_pdo_w) - AM_RANGE(0x908, 0x90b) AM_READWRITE(d_u_pdo_r, d_u_pdo_w) - AM_RANGE(0x910, 0x913) AM_READWRITE(d_fault_r, d_fault_w) - AM_RANGE(0x940, 0x943) AM_READWRITE(d_control_r, d_control_w) - AM_RANGE(0x980, 0x983) AM_READWRITE(d_reset_r, d_reset_w) - - AM_RANGE(0xa00, 0xaff) AM_NOP - AM_RANGE(0xb04, 0xb07) AM_READWRITE(i_s_pdo_r, i_s_pdo_w) - AM_RANGE(0xb08, 0xb0b) AM_READWRITE(i_u_pdo_r, i_u_pdo_w) - AM_RANGE(0xb10, 0xb13) AM_READWRITE(i_fault_r, i_fault_w) - AM_RANGE(0xb40, 0xb43) AM_READWRITE(i_control_r, i_control_w) - AM_RANGE(0xb80, 0xb83) AM_READWRITE(i_reset_r, i_reset_w) - - AM_RANGE(0xc00, 0xcff) AM_NOP - AM_RANGE(0xd04, 0xd07) AM_WRITE(g_s_pdo_w) - AM_RANGE(0xd08, 0xd0b) AM_WRITE(g_u_pdo_w) - AM_RANGE(0xd10, 0xd13) AM_WRITE(g_fault_w) - AM_RANGE(0xd40, 0xd43) AM_WRITE(g_control_w) - AM_RANGE(0xd80, 0xd83) AM_WRITE(g_reset_w) + AM_RANGE(0x000, 0x0ff) AM_NOP // tlb + AM_RANGE(0x104, 0x107) AM_READWRITE(s_pdo_r, s_pdo_w) + AM_RANGE(0x108, 0x10b) AM_READWRITE(u_pdo_r, u_pdo_w) + AM_RANGE(0x110, 0x113) AM_READWRITE(fault_r, fault_w) + AM_RANGE(0x140, 0x143) AM_READWRITE(control_r, control_w) + AM_RANGE(0x180, 0x183) AM_READWRITE(reset_r, reset_w) +ADDRESS_MAP_END + +DEVICE_ADDRESS_MAP_START(map_global, 32, cammu_c3_device) + AM_RANGE(0x000, 0x0ff) AM_NOP // global tlb + AM_RANGE(0x104, 0x107) AM_WRITE(g_s_pdo_w) + AM_RANGE(0x108, 0x10b) AM_WRITE(g_u_pdo_w) + AM_RANGE(0x110, 0x113) AM_WRITE(g_fault_w) + AM_RANGE(0x140, 0x143) AM_WRITE(g_control_w) + AM_RANGE(0x180, 0x183) AM_WRITE(g_reset_w) ADDRESS_MAP_END DEFINE_DEVICE_TYPE(CAMMU_C4T, cammu_c4t_device, "c4t", "C4E/C4T CAMMU") @@ -104,41 +112,62 @@ DEFINE_DEVICE_TYPE(CAMMU_C4I, cammu_c4i_device, "c4i", "C4I CAMMU") DEFINE_DEVICE_TYPE(CAMMU_C3, cammu_c3_device, "c3", "C1/C3 CAMMU") cammu_c4t_device::cammu_c4t_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : cammu_c4_device(mconfig, CAMMU_C4T, tag, owner, clock) + : cammu_c4_device(mconfig, CAMMU_C4T, tag, owner, clock, CID_C4T) { } cammu_c4i_device::cammu_c4i_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : cammu_c4_device(mconfig, CAMMU_C4I, tag, owner, clock) + : cammu_c4_device(mconfig, CAMMU_C4I, tag, owner, clock, CID_C4I) { } -cammu_c4_device::cammu_c4_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) +cammu_c4_device::cammu_c4_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, u32 cammu_id) : cammu_device(mconfig, type, tag, owner, clock) + , m_control(cammu_id) { } cammu_c3_device::cammu_c3_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : cammu_device(mconfig, CAMMU_C3, tag, owner, clock) + , m_control(CID_C3) + , m_linked{ this } { } cammu_device::cammu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) : device_t(mconfig, type, tag, owner, clock) - , device_memory_interface(mconfig, *this), - m_main_space_config("main", ENDIANNESS_LITTLE, 32, 32, 0), - m_io_space_config("io", ENDIANNESS_LITTLE, 32, 32, 0), - m_boot_space_config("boot", ENDIANNESS_LITTLE, 32, 32, 0), - m_main_space(nullptr), - m_io_space(nullptr), - m_boot_space(nullptr), - m_ssw_func(*this) + , device_memory_interface(mconfig, *this) + , m_main_space_config("main", ENDIANNESS_LITTLE, 32, 32, 0) + , m_io_space_config("io", ENDIANNESS_LITTLE, 32, 32, 0) + , m_boot_space_config("boot", ENDIANNESS_LITTLE, 32, 32, 0) + , m_main_space(nullptr) + , m_io_space(nullptr) + , m_boot_space(nullptr) + , m_ssw_func(*this) + , m_exception_func(*this) +{ +} + +device_memory_interface::space_config_vector cammu_device::memory_space_config() const { + return space_config_vector { + std::make_pair(0, &m_main_space_config), + std::make_pair(1, &m_io_space_config), + std::make_pair(2, &m_boot_space_config) + }; +} + +void cammu_c3_device::static_add_linked(device_t &device, const char *const tag) +{ + cammu_c3_device &parent = downcast<cammu_c3_device &>(device); + + parent.m_linked.push_back(downcast<cammu_c3_device *>(parent.siblingdevice(tag))); } void cammu_device::device_start() { m_ssw_func.resolve(); + m_exception_func.resolve(); m_main_space = &space(0); m_io_space = &space(1); @@ -149,268 +178,321 @@ void cammu_device::device_reset() { } -device_memory_interface::space_config_vector cammu_device::memory_space_config() const +void cammu_c4_device::device_start() { - return space_config_vector { - std::make_pair(0, &m_main_space_config), - std::make_pair(1, &m_io_space_config), - std::make_pair(2, &m_boot_space_config) - }; + cammu_device::device_start(); + + save_item(NAME(m_s_pdo)); + save_item(NAME(m_u_pdo)); + save_item(NAME(m_control)); + + save_item(NAME(m_i_fault)); + save_item(NAME(m_fault_address_1)); + save_item(NAME(m_fault_address_2)); + save_item(NAME(m_fault_data_1_lo)); + save_item(NAME(m_fault_data_1_hi)); + save_item(NAME(m_fault_data_2_lo)); + save_item(NAME(m_fault_data_2_hi)); } -READ32_MEMBER(cammu_device::insn_r) +void cammu_c4i_device::device_start() { - u32 ssw = m_ssw_func(); - u32 va = offset << 2; + cammu_c4_device::device_start(); + + save_item(NAME(m_reset)); + save_item(NAME(m_clr_s_data_tlb)); + save_item(NAME(m_clr_u_data_tlb)); + save_item(NAME(m_clr_s_insn_tlb)); + save_item(NAME(m_clr_u_insn_tlb)); + save_item(NAME(m_test_data)); + save_item(NAME(m_test_address)); +} - // in supervisor mode, the first 8 pages are always mapped via the hard-wired tlb - if ((ssw & 0x40000000) == 0 && (va & ~0x7fff) == 0) - { - switch (va & 0xf000) - { - case 0x0000: - case 0x1000: - case 0x2000: - case 0x3000: - // pages 0-3: main space pages 0-3 - return m_main_space->read_dword(va, mem_mask); +void cammu_c4t_device::device_start() +{ + cammu_c4_device::device_start(); + + save_item(NAME(m_ram_line)); + save_item(NAME(m_htlb_offset)); + save_item(NAME(m_c4_bus_poll)); + save_item(NAME(m_bio_control)); + save_item(NAME(m_bio_address_tag)); + + save_item(NAME(m_cache_data_lo)); + save_item(NAME(m_cache_data_hi)); + save_item(NAME(m_cache_cpu_tag)); + save_item(NAME(m_cache_system_tag_valid)); + save_item(NAME(m_cache_system_tag)); + save_item(NAME(m_tlb_va_line)); + save_item(NAME(m_tlb_ra_line)); +} - case 0x4000: - case 0x5000: - // pages 4-5: i/o space pages 0-1 - return m_io_space->read_dword(va & 0x1fff, mem_mask); +void cammu_c3_device::device_start() +{ + cammu_device::device_start(); - case 0x6000: - case 0x7000: - // pages 6-7: boot space pages 0-1 - return m_boot_space->read_dword(va & 0x1fff, mem_mask); - } - } + save_item(NAME(m_s_pdo)); + save_item(NAME(m_u_pdo)); + save_item(NAME(m_fault)); + save_item(NAME(m_control)); + save_item(NAME(m_reset)); +} - // if not in mapped mode, default to main memory space - if ((ssw & 0x04000000) == 0) - return m_main_space->read_dword(va); +void cammu_c3_device::device_reset() +{ + cammu_device::device_reset(); -#if DTU - // get the page table entry - u32 pte = get_pte(va, ssw & 0x40000000, false); + m_control = (m_control & CNTL_CID) | (CNTL_ATE | UST_3 | CNTL_EWIR | CNTL_EWIW | CNTL_EWCW | CNTL_EP); + m_reset = 0; +} - // translate the address - u32 ra = (pte & 0xfffff000) | (va & 0xfff); +READ32_MEMBER(cammu_device::read) +{ + const u32 virtual_address = (offset << 2) | ( + (mem_mask & 0x00ffffff) == 0 ? 0x3 : + (mem_mask & 0x0000ffff) == 0 ? 0x2 : + (mem_mask & 0x000000ff) == 0 ? 0x1 : 0x0); + offs_t physical_address; - // execute the read based on the system tag - switch ((pte & 0xe00) >> 9) - { - case 0: - case 1: - case 2: - case 3: - return m_main_space->read_dword(ra, mem_mask); + LOGMASKED(LOG_ACCESS, "%s read address 0x%08x mem_mask 0x%08x (%s)\n", + space.name(), virtual_address, mem_mask, machine().describe_context()); - case 4: - return m_io_space->read_dword(ra, mem_mask); + address_space *physical_space = translate_address(virtual_address, space.spacenum() == AS_PROGRAM ? ACCESS_X : ACCESS_R, &physical_address); - case 5: - return m_boot_space->read_dword(ra, mem_mask); + if (physical_space != nullptr) + return physical_space->read_dword(physical_address, mem_mask); + else + return space.unmap(); +} - case 6: // cache purge - case 7: // main memory, slave mode - fatalerror("system tag %d not supported %s\n", (pte & 0xe00) >> 9, machine().describe_context().c_str()); - } +WRITE32_MEMBER(cammu_device::write) +{ + const u32 virtual_address = (offset << 2) | ( + (mem_mask & 0x00ffffff) == 0 ? 0x3 : + (mem_mask & 0x0000ffff) == 0 ? 0x2 : + (mem_mask & 0x000000ff) == 0 ? 0x1 : 0x0); + offs_t physical_address; - return 0; -#else - // FIXME: currently maps addresses with upper bits 0x00 or 0x7f1 to main memory and everything else to I/O - if ((va & 0xff000000) == 0x00000000 || (va & 0xfff00000) == 0x7f100000) - return m_main_space->read_dword(va, mem_mask); - else - return m_io_space->read_dword(va, mem_mask); -#endif + LOGMASKED(LOG_ACCESS, "%s write address 0x%08x data 0x%08x mem_mask 0x%08x (%s)\n", + space.name(), virtual_address, data, mem_mask, machine().describe_context()); + + address_space *physical_space = translate_address(virtual_address, ACCESS_W, &physical_address); + + if (physical_space != nullptr) + physical_space->write_dword(physical_address, data, mem_mask); } -READ32_MEMBER(cammu_device::data_r) +address_space *cammu_device::translate_address(const offs_t virtual_address, const access_t mode, offs_t *physical_address) { - u32 ssw = m_ssw_func(); - u32 va = offset << 2; + // get ssw and user/supervisor mode + const u32 ssw = m_ssw_func(); + const bool user = mode == ACCESS_X ? ssw & SSW_U : ssw & (SSW_U | SSW_UU); + + // TODO: check for alignment faults - // in supervisor mode (and not user data mode), the first 8 pages are always mapped via the hard-wired tlb - if (((ssw & 0x50000000) == 0) && ((va & ~0x7fff) == 0)) + // in supervisor mode, the first 8 pages are always mapped via the hard-wired tlb + if (!user && (virtual_address & ~0x7fff) == 0) { - switch (va & 0xf000) + switch (virtual_address & 0x7000) { case 0x0000: case 0x1000: case 0x2000: case 0x3000: // pages 0-3: main space pages 0-3 - return m_main_space->read_dword(va, mem_mask); + *physical_address = virtual_address & 0x3fff; + return m_main_space; case 0x4000: case 0x5000: // pages 4-5: i/o space pages 0-1 - return m_io_space->read_dword(va & 0x1fff, mem_mask); + *physical_address = virtual_address & 0x1fff; + return m_io_space; case 0x6000: case 0x7000: // pages 6-7: boot space pages 0-1 - return m_boot_space->read_dword(va & 0x1fff, mem_mask); + *physical_address = virtual_address & 0x1fff; + return m_boot_space; } } - // if not in mapped mode, default to main memory space - if ((ssw & 0x04000000) == 0) - return m_main_space->read_dword(va); + // if not in mapped mode, use unmapped system tag + if ((ssw & SSW_M) == 0) + { + *physical_address = virtual_address; + + return get_ust_space(); + } -#if DTU // get the page table entry - u32 pte = get_pte(va, ssw & 0x50000000, space.spacenum() == AS_DATA); + const u32 pte = get_pte(virtual_address, user); - // translate the address - u32 ra = (pte & 0xfffff000) | (va & 0xfff); + // check for page faults + if (pte & PTE_F) + { + if (!machine().side_effect_disabled()) + { + LOG("%s page fault address 0x%08x ssw 0x%08x pte 0x%08x (%s)\n", + mode == ACCESS_X ? "instruction" : "data", + virtual_address, ssw, pte, machine().describe_context()); + + set_fault_address(virtual_address); + m_exception_func(mode == ACCESS_X ? EXCEPTION_I_PAGE_FAULT : EXCEPTION_D_PAGE_FAULT); + } + + return nullptr; + } - // execute the read based on the system tag - switch ((pte & 0xe00) >> 9) + // check for protection level faults + if (!machine().side_effect_disabled() && !get_access(mode, pte, ssw)) { - case 0: - case 1: - case 2: - case 3: - return m_main_space->read_dword(ra, mem_mask); + LOG("%s protection fault address 0x%08x ssw 0x%08x pte 0x%08x (%s)\n", + mode == ACCESS_X ? "execute" : mode == ACCESS_R ? "read" : "write", + virtual_address, ssw, pte, machine().describe_context()); + + set_fault_address(virtual_address); + m_exception_func( + mode == ACCESS_X ? EXCEPTION_I_EXECUTE_PROTECT_FAULT : + mode == ACCESS_R ? EXCEPTION_D_READ_PROTECT_FAULT : + EXCEPTION_D_WRITE_PROTECT_FAULT); - case 4: - return m_io_space->read_dword(ra, mem_mask); + return nullptr; + } - case 5: - return m_boot_space->read_dword(ra, mem_mask); + // translate the address + *physical_address = (pte & ~CAMMU_PAGE_MASK) | (virtual_address & CAMMU_PAGE_MASK); + LOGMASKED(LOG_DTU, "%s address translated 0x%08x\n", mode == ACCESS_X ? "instruction" : "data", *physical_address); - case 6: // cache purge - case 7: // main memory, slave mode - fatalerror("data_r: system tag %d not supported at %s\n", (pte & 0xe00) >> 9, machine().describe_context().c_str()); + // return the physical space based on the system tag + switch (pte & PTE_ST) + { + case ST_0: + case ST_1: + case ST_2: + case ST_3: + // main memory space + return m_main_space; + + case ST_4: + // i/o space + return m_io_space; + + case ST_5: + // boot space + return m_boot_space; + + case ST_6: + // cache purge + case ST_7: + // main memory, slave mode + if (!machine().side_effect_disabled()) + fatalerror("%s page table entry system tag %d not supported\n", + mode == ACCESS_X ? "instruction" : "data", (pte & PTE_ST) >> 9); + break; } - return 0; -#else - // FIXME: currently maps addresses with upper bits 0x00 or 0x7f1 to main memory and everything else to I/O - if ((va & 0xff000000) == 0x00000000 || (va & 0xfff00000) == 0x7f100000) - return m_main_space->read_dword(va, mem_mask); - else - return m_io_space->read_dword(va, mem_mask); -#endif + return nullptr; } -WRITE32_MEMBER(cammu_device::data_w) +// return the page table entry for a given virtual address +u32 cammu_device::get_pte(const u32 va, const bool user) { - u32 ssw = m_ssw_func(); - u32 va = offset << 2; - - // in supervisor mode (and not user data mode), the first 8 pages are always mapped via the hard-wired tlb - if (((ssw & 0x50000000) == 0) && ((va & ~0x7fff) == 0)) + const u32 tlb_index = user ? 1 : 0; + if ((va & ~CAMMU_PAGE_MASK) != m_tlb[tlb_index].va) { - switch (va & 0xf000) - { - case 0x0000: - case 0x1000: - case 0x2000: - case 0x3000: - // pages 0-3: main space pages 0-3 - m_main_space->write_dword(va, data, mem_mask); - return; + // get page table directory origin from user or supervisor pdo register + const u32 pdo = get_pdo(user); - case 0x4000: - case 0x5000: - // pages 4-5: i/o space pages 0-1 - m_io_space->write_dword(va & 0x1fff, data, mem_mask); - return; + // get page table directory index from top 12 bits of virtual address + const u32 ptdi = (va & VA_PTDI) >> 20; - case 0x6000: - case 0x7000: - // pages 6-7: boot space pages 0-1 - m_boot_space->write_dword(va & 0x1fff, data, mem_mask); - return; - } - } + // fetch page table directory entry + const u32 ptde = m_main_space->read_dword(pdo | ptdi); - // if not in mapped mode, default to main memory space - if ((ssw & 0x04000000) == 0) - { - m_main_space->write_dword(va, data, mem_mask); - return; - } + LOGMASKED(LOG_DTU, "get_pte pdo 0x%08x ptdi 0x%08x ptde 0x%08x\n", pdo, ptdi, ptde); -#if DTU - // get the page table entry - u32 pte = get_pte(va, ssw & 0x50000000, space.spacenum() == AS_DATA); + // check for page table directory entry fault + if (ptde & PTDE_F) + return PTE_F; - // translate the address - u32 ra = (pte & 0xfffff000) | (va & 0xfff); + // get the page table origin from the page table directory entry + const u32 pto = ptde & PTDE_PTO; - // execute the read based on the system tag - switch ((pte & 0xe00) >> 9) - { - case 0: - case 1: - case 2: - case 3: - m_main_space->write_dword(ra, data, mem_mask); - break; + // get the page table index from the middle 12 bits of the virtual address + const u32 pti = (va & VA_PTI) >> 10; - case 4: - m_io_space->write_dword(ra, data, mem_mask); - break; + // fetch page table entry + const u32 pte = m_main_space->read_dword(pto | pti); - case 5: - m_boot_space->write_dword(ra, data, mem_mask); - break; + LOGMASKED(LOG_DTU, "get_pte pto 0x%08x pti 0x%08x pte 0x%08x\n", pto, pti, pte); - case 6: // cache purge - case 7: // main memory, slave mode - fatalerror("data_w: system tag %d not supported at %s\n", (pte & 0xe00) >> 9, machine().describe_context().c_str()); - break; + // check for page table entry fault + if (pte & PTE_F) + return PTE_F; + + // add the pte to the tlb + m_tlb[tlb_index].va = va & ~CAMMU_PAGE_MASK; + m_tlb[tlb_index].pte = pte; + + LOGMASKED(LOG_DTU, "get_pte address 0x%08x pte 0x%08x (%s)\n", va, pte, machine().describe_context()); } -#else - // FIXME: currently maps addresses with upper bits 0x00 or 0x7f1 to main memory and everything else to I/O - if ((va & 0xff000000) == 0x00000000 || (va & 0xfff00000) == 0x7f100000) - m_main_space->write_dword(va, data, mem_mask); - else - m_io_space->write_dword(va, data, mem_mask); -#endif + + return m_tlb[tlb_index].pte; } -u32 cammu_c4_device::get_pte(u32 va, int user, bool data) +address_space *cammu_c4i_device::get_ust_space() const { - u32 tlb_index = (user ? 2 : 0) + (data ? 1 : 0); - if ((va & 0xfffff000) != m_tlb[tlb_index].va) + switch (m_control & CNTL_UMM) { - // return the page table entry for a given virtual address - u32 pdo = user ? m_u_pdo : m_s_pdo; - - u32 pto = m_main_space->read_dword(pdo | (va & 0xffc00000) >> 20); - if (pto & 0x1) - fatalerror("can't deal with pto faults va 0x%08x %s\n", va, machine().describe_context().c_str()); + case UMM_MM: return m_main_space; + case UMM_MMRIO: return m_main_space; // FIXME: what determines main or i/o? + case UMM_IO: return m_io_space; + } - u32 pte = m_main_space->read_dword((pto & 0xfffff000) | (va & 0x003ff000) >> 10); - if (pte & 0x1) - fatalerror("can't deal with pte faults va 0x%08x %s\n", va, machine().describe_context().c_str()); + return m_main_space; +} - m_tlb[tlb_index].va = va & 0xfffff000; - m_tlb[tlb_index].pte = pte; +bool cammu_c4_device::get_access(const access_t mode, const u32 pte, const u32 ssw) const +{ + switch (mode) + { + case ACCESS_R: return pte & 0x20; + case ACCESS_W: return pte & 0x10; + case ACCESS_X: return pte & 0x08; } - return m_tlb[tlb_index].pte; + return false; } -u32 cammu_c3_device::get_pte(u32 va, int user, bool data) +bool cammu_c3_device::get_access(const access_t mode, const u32 pte, const u32 ssw) const { - // return the page table entry for a given virtual address - u32 pdo = user ? (data ? m_d_u_pdo : m_i_u_pdo) : (data ? m_d_s_pdo : m_i_s_pdo); + // FIXME: logic is not correct yet + return true; - u32 pto = m_main_space->read_dword(pdo | (va & 0xffc00000) >> 20); - if (pto & 0x1) - fatalerror("can't deal with pto faults va 0x%08x %s\n", va, machine().describe_context().c_str()); + const u8 column = (mode == ACCESS_X ? i_cammu_column : d_cammu_column)[(ssw & SSW_PL) >> 9]; + const u8 access = cammu_matrix[column][(pte & PTE_PL) >> 3]; - u32 pte = m_main_space->read_dword((pto & 0xfffff000) | (va & 0x003ff000) >> 10); - if (pte & 0x1) - fatalerror("can't deal with pte faults va 0x%08x %s\n", va, machine().describe_context().c_str()); + switch (mode) + { + case ACCESS_R: return access & R; + case ACCESS_W: return access & W; + case ACCESS_X: return access & E; + } - return pte; + return false; } + +// C100/C300 CAMMU protection level matrix +const u8 cammu_c3_device::i_cammu_column[] = { 1, 1, 0, 0, 1, 1, 0, 0, 3, 3, 2, 2, 3, 3, 2, 2 }; +const u8 cammu_c3_device::d_cammu_column[] = { 1, 1, 0, 0, 3, 2, 3, 2, 3, 3, 2, 2, 3, 3, 2, 2 }; + +const cammu_c3_device::c3_access_t cammu_c3_device::cammu_matrix[][16] = +{ + { RW, RW, RW, RW, RW, RW, RW, RWE, RE, R, R, R, N, N, N, N }, + { N, RW, RW, RW, RW, RW, R, RWE, N, RE, R, R, RE, N, N, N }, + { N, N, RW, RW, RW, R, R, RWE, N, N, RE, RE, N, RE, N, N }, + { N, N, N, RW, R, R, R, RWE, N, N, N, RE, RE, N, RE, N } +}; + + |