diff options
author | 2020-05-20 00:02:14 +0200 | |
---|---|---|
committer | 2020-05-20 00:02:43 +0200 | |
commit | 0ec3865b9990c96341160a967fb2013c324a5cf2 (patch) | |
tree | 92ca4c1dacb0402daa97b4b8427626f360b3f913 | |
parent | cec2fd71bc414c1f51fbadb772d845240819c1a7 (diff) |
-sun4: Make use of multiple address spaces in the SPARC core rather than having the MMU handle it all. [Ryan Holtz]
-rw-r--r-- | src/devices/cpu/m68000/m68kmake.exe | bin | 0 -> 415010 bytes | |||
-rw-r--r-- | src/devices/cpu/m68000/m68kmake.o | bin | 0 -> 26355 bytes | |||
-rw-r--r-- | src/devices/cpu/sparc/sparc.cpp | 111 | ||||
-rw-r--r-- | src/devices/cpu/sparc/sparc.h | 8 | ||||
-rw-r--r-- | src/devices/cpu/sparc/sparc_intf.h | 2 | ||||
-rw-r--r-- | src/devices/machine/sun4c_mmu.cpp | 382 | ||||
-rw-r--r-- | src/devices/machine/sun4c_mmu.h | 59 | ||||
-rw-r--r-- | src/mame/drivers/sun4.cpp | 121 |
8 files changed, 358 insertions, 325 deletions
diff --git a/src/devices/cpu/m68000/m68kmake.exe b/src/devices/cpu/m68000/m68kmake.exe Binary files differnew file mode 100644 index 00000000000..7b2a36e5413 --- /dev/null +++ b/src/devices/cpu/m68000/m68kmake.exe diff --git a/src/devices/cpu/m68000/m68kmake.o b/src/devices/cpu/m68000/m68kmake.o Binary files differnew file mode 100644 index 00000000000..b4621ccc99a --- /dev/null +++ b/src/devices/cpu/m68000/m68kmake.o diff --git a/src/devices/cpu/sparc/sparc.cpp b/src/devices/cpu/sparc/sparc.cpp index 07765a7ef19..f24a4f6a93c 100644 --- a/src/devices/cpu/sparc/sparc.cpp +++ b/src/devices/cpu/sparc/sparc.cpp @@ -45,7 +45,13 @@ sparc_base_device::sparc_base_device(const machine_config &mconfig, device_type : cpu_device(mconfig, type, tag, owner, clock) , m_mmu(*this, finder_base::DUMMY_TAG) { - m_default_config = address_space_config("program", ENDIANNESS_BIG, 32, 32); + char asi_buf[10]; + m_debugger_config = address_space_config("debug", ENDIANNESS_BIG, 32, 32); + for (int i = 0; i < 0x10; i++) + { + snprintf(asi_buf, ARRAY_LENGTH(asi_buf), "asi%X", i); + m_asi_config[i] = address_space_config(asi_buf, ENDIANNESS_BIG, 32, 32); + } } @@ -162,6 +168,15 @@ void sparc_base_device::device_start() m_bp_irl = 0; m_irq_state = 0; + for (int i = 0; i < 0x20; i++) + { + if (i > 0 && i < 0x10) + { + continue; + } + m_asi[i] = &space(i); + } + memset(m_dbgregs, 0, 24 * sizeof(uint32_t)); memset(m_illegal_instruction_asr, 0, 32 * sizeof(bool)); @@ -522,38 +537,24 @@ void sparc_base_device::device_post_load() device_memory_interface::space_config_vector sparc_base_device::memory_space_config() const { space_config_vector config_vector; - config_vector.push_back(std::make_pair(AS_PROGRAM, &m_default_config)); + config_vector.push_back(std::make_pair(0, &m_debugger_config)); + for (int i = 0; i < 0x10; i++) + { + config_vector.push_back(std::make_pair(0x10 + i, &m_asi_config[i])); + } return config_vector; } - -//------------------------------------------------- -// read_sized_word - read a value from a given -// address space and address, shifting the data -// that is read into the appropriate location of -// a 32-bit word in a big-endian system. -//------------------------------------------------- - -uint32_t sparc_base_device::read_sized_word(const uint8_t asi, const uint32_t address, const uint32_t mem_mask) +inline uint32_t sparc_base_device::read_word(const uint8_t asi, const uint32_t address, const uint32_t mem_mask) { - assert(asi < 0x20); // We do not currently support ASIs outside the range used by actual Sun machines. - return m_mmu->read_asi(asi, address >> 2, mem_mask); + assert(asi < 0x10); // We do not currently support ASIs outside the range used by actual Sun machines. + return m_asi[asi | 0x10]->read_dword(address, mem_mask); } - -//------------------------------------------------- -// write_sized_word - write a value to a given -// address space and address, shifting the data -// that is written into the least significant -// bits as appropriate in order to write the -// value to a memory system with separate data -// size handlers -//------------------------------------------------- - -void sparc_base_device::write_sized_word(const uint8_t asi, const uint32_t address, const uint32_t data, const uint32_t mem_mask) +inline void sparc_base_device::write_word(const uint8_t asi, const uint32_t address, const uint32_t data, const uint32_t mem_mask) { - assert(asi < 0x20); // We do not currently support ASIs outside the range used by actual Sun machines. - m_mmu->write_asi(asi, address >> 2, data, mem_mask); + assert(asi < 0x10); // We do not currently support ASIs outside the range used by actual Sun machines. + return m_asi[asi | 0x10]->write_dword(address, data, mem_mask); } @@ -2165,7 +2166,7 @@ void sparc_base_device::execute_store(uint32_t op) static const uint32_t mask16[4] = { 0xffff0000, 0x00000000, 0x0000ffff, 0x00000000 }; static const uint32_t mask8[4] = { 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff }; - m_mmu->write_asi(addr_space, address >> 2, data0, (ST || STA || STD || STDA || STF || STDF || STDFQ || STFSR || STC || STDC || STDCQ || STCSR) ? 0xffffffff : ((STH || STHA) ? mask16[address & 2] : mask8[address & 3])); + write_word(addr_space, address, data0, (ST || STA || STD || STDA || STF || STDF || STDFQ || STFSR || STC || STDC || STDCQ || STCSR) ? 0xffffffff : ((STH || STHA) ? mask16[address & 2] : mask8[address & 3])); if (MAE) { m_trap = 1; @@ -2177,7 +2178,7 @@ void sparc_base_device::execute_store(uint32_t op) if (STD || STDA || STDF || STDC || STDFQ || STDCQ) { - m_mmu->write_asi(addr_space, (address + 4) >> 2, data1, 0xffffffff); + write_word(addr_space, address + 4, data1); if (MAE) { m_trap = 1; @@ -2304,7 +2305,7 @@ inline void sparc_base_device::execute_ldd(uint32_t op) m_icount = 0; } - const uint32_t data = m_mmu->read_asi(m_data_space, address >> 2, 0xffffffff); + const uint32_t data = read_word(m_data_space, address); if (MAE) { @@ -2318,7 +2319,7 @@ inline void sparc_base_device::execute_ldd(uint32_t op) if (RDBITS) RDREG = data; - const uint32_t word1 = m_mmu->read_asi(m_data_space, (address + 4) >> 2, 0xffffffff); + const uint32_t word1 = read_word(m_data_space, address + 4); if (MAE) { m_trap = 1; @@ -2347,7 +2348,7 @@ inline void sparc_base_device::execute_ld(uint32_t op) return; } - const uint32_t data = m_mmu->read_asi(m_data_space, address >> 2, 0xffffffff); + const uint32_t data = read_word(m_data_space, address); if (m_mae) { @@ -2379,7 +2380,7 @@ inline void sparc_base_device::execute_ldsh(uint32_t op) } static const uint32_t mask16[4] = { 0xffff0000, 0x00000000, 0x0000ffff, 0x00000000 }; - const uint32_t data = m_mmu->read_asi(m_data_space, address >> 2, mask16[address & 2]); + const uint32_t data = read_word(m_data_space, address, mask16[address & 2]); if (m_mae) { @@ -2414,7 +2415,7 @@ inline void sparc_base_device::execute_lduh(uint32_t op) } static const uint32_t mask16[4] = { 0xffff0000, 0x00000000, 0x0000ffff, 0x00000000 }; - const uint32_t data = m_mmu->read_asi(m_data_space, address >> 2, mask16[address & 2]); + const uint32_t data = read_word(m_data_space, address, mask16[address & 2]); if (m_mae) { @@ -2440,7 +2441,7 @@ inline void sparc_base_device::execute_ldsb(uint32_t op) const uint32_t address = RS1REG + (USEIMM ? SIMM13 : RS2REG); static const uint32_t mask8[4] = { 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff }; - const uint32_t data = m_mmu->read_asi(m_data_space, address >> 2, mask8[address & 3]); + const uint32_t data = read_word(m_data_space, address, mask8[address & 3]); if (m_mae) { @@ -2469,7 +2470,7 @@ inline void sparc_base_device::execute_ldub(uint32_t op) static const uint32_t mask8[4] = { 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff }; const uint32_t byte_idx = address & 3; - const uint32_t data = m_mmu->read_asi(m_data_space, address >> 2, mask8[byte_idx]); + const uint32_t data = read_word(m_data_space, address, mask8[byte_idx]); if (m_mae) { @@ -2512,7 +2513,7 @@ inline void sparc_base_device::execute_lddfpr(uint32_t op) return; } - const uint32_t data = m_mmu->read_asi(m_data_space, address >> 2, 0xffffffff); + const uint32_t data = read_word(m_data_space, address); if (m_mae) { @@ -2528,7 +2529,7 @@ inline void sparc_base_device::execute_lddfpr(uint32_t op) return; } - const uint32_t word1 = m_mmu->read_asi(m_data_space, (address + 4) >> 2, 0xffffffff); + const uint32_t word1 = read_word(m_data_space, address + 4); if (MAE) { m_trap = 1; @@ -2572,7 +2573,7 @@ inline void sparc_base_device::execute_ldfpr(uint32_t op) return; } - const uint32_t data = m_mmu->read_asi(m_data_space, address >> 2, 0xffffffff); + const uint32_t data = read_word(m_data_space, address); if (m_mae) { @@ -2616,7 +2617,7 @@ inline void sparc_base_device::execute_ldfsr(uint32_t op) return; } - const uint32_t data = m_mmu->read_asi(m_data_space, address >> 2, 0xffffffff); + const uint32_t data = read_word(m_data_space, address); if (m_mae) { @@ -2673,7 +2674,7 @@ inline void sparc_base_device::execute_lddcpr(uint32_t op) return; } - m_mmu->read_asi(m_data_space, address >> 2, 0xffffffff); + read_word(m_data_space, address); if (MAE) { m_trap = 1; @@ -2685,7 +2686,7 @@ inline void sparc_base_device::execute_lddcpr(uint32_t op) // implementation-dependent actions - m_mmu->read_asi(m_data_space, (address + 4) >> 2, 0xffffffff); + read_word(m_data_space, address + 4); if (MAE) { m_trap = 1; @@ -2733,7 +2734,7 @@ inline void sparc_base_device::execute_ldcpr(uint32_t op) return; } - m_mmu->read_asi(m_data_space, address >> 2, 0xffffffff); + read_word(m_data_space, address); if (MAE) { @@ -2782,7 +2783,7 @@ inline void sparc_base_device::execute_ldcsr(uint32_t op) return; } - m_mmu->read_asi(m_data_space, address >> 2, 0xffffffff); + read_word(m_data_space, address); if (MAE) { @@ -2830,7 +2831,7 @@ inline void sparc_base_device::execute_ldda(uint32_t op) return; } - const uint32_t data = m_mmu->read_asi(addr_space, address >> 2, 0xffffffff); + const uint32_t data = read_word(addr_space, address); if (m_mae) { @@ -2844,7 +2845,7 @@ inline void sparc_base_device::execute_ldda(uint32_t op) if (RDBITS) RDREG = data; - uint32_t word1 = m_mmu->read_asi(addr_space, (address + 4) >> 2, 0xffffffff); + uint32_t word1 = read_word(addr_space, address + 4); if (MAE) { m_trap = 1; @@ -2890,7 +2891,7 @@ inline void sparc_base_device::execute_lda(uint32_t op) return; } - const uint32_t data = m_mmu->read_asi(ASI, address >> 2, 0xffffffff); + const uint32_t data = read_word(ASI, address); if (m_mae) { @@ -2939,7 +2940,7 @@ inline void sparc_base_device::execute_ldsha(uint32_t op) } static const uint32_t mask16[4] = { 0xffff0000, 0x00000000, 0x0000ffff, 0x00000000 }; - const uint32_t data = m_mmu->read_asi(ASI, address >> 2, mask16[address & 2]); + const uint32_t data = read_word(ASI, address, mask16[address & 2]); if (m_mae) { @@ -2990,7 +2991,7 @@ inline void sparc_base_device::execute_lduha(uint32_t op) } static const uint32_t mask16[4] = { 0xffff0000, 0x00000000, 0x0000ffff, 0x00000000 }; - const uint32_t data = m_mmu->read_asi(ASI, address >> 2, mask16[address & 2]); + const uint32_t data = read_word(ASI, address, mask16[address & 2]); if (m_mae) { @@ -3032,7 +3033,7 @@ inline void sparc_base_device::execute_ldsba(uint32_t op) static const uint32_t mask8[4] = { 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff }; const uint32_t address = RS1REG + RS2REG; - const uint32_t data = m_mmu->read_asi(ASI, address >> 2, mask8[address & 3]); + const uint32_t data = read_word(ASI, address, mask8[address & 3]); if (m_mae) { @@ -3076,7 +3077,7 @@ inline void sparc_base_device::execute_lduba(uint32_t op) static const uint32_t mask8[4] = { 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff }; const uint32_t address = RS1REG + RS2REG; - const uint32_t data = m_mmu->read_asi(ASI, address >> 2, mask8[address & 3]); + const uint32_t data = read_word(ASI, address, mask8[address & 3]); if (m_mae) { @@ -3210,7 +3211,7 @@ void sparc_base_device::execute_ldstub(uint32_t op) m_pb_block_ldst_byte = 1; static const uint32_t mask8[4] = { 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff }; - data = m_mmu->read_asi(addr_space, address >> 2, mask8[address & 3]); + data = read_word(addr_space, address, mask8[address & 3]); if (MAE) { @@ -3221,7 +3222,7 @@ void sparc_base_device::execute_ldstub(uint32_t op) return; } - m_mmu->write_asi(addr_space, address >> 2, 0xffffffff, mask8[address & 3]); + write_word(addr_space, address, 0xffffffff, mask8[address & 3]); m_pb_block_ldst_byte = 0; @@ -4555,7 +4556,7 @@ void sparcv8_device::execute_swap(uint32_t op) m_pb_block_ldst_word = 1; - word = read_sized_word(addr_space, address, 4); + word = read_word(addr_space, address); if (MAE) { @@ -4565,7 +4566,7 @@ void sparcv8_device::execute_swap(uint32_t op) } if (!m_trap) { - write_sized_word(addr_space, address, temp, 4); + write_word(addr_space, address, temp); m_pb_block_ldst_word = 0; if (MAE) @@ -4807,7 +4808,7 @@ inline void sparc_base_device::execute_step() // write-state-register delay not yet implemented - const uint32_t op = m_mmu->fetch_insn(m_s, PC >> 2); + const uint32_t op = read_word(8 + (IS_SUPERVISOR ? 1 : 0), PC); #if LOG_FCODES //if (m_log_fcodes) diff --git a/src/devices/cpu/sparc/sparc.h b/src/devices/cpu/sparc/sparc.h index 8e16c8bc3f5..de7fa3d3797 100644 --- a/src/devices/cpu/sparc/sparc.h +++ b/src/devices/cpu/sparc/sparc.h @@ -155,11 +155,13 @@ protected: required_device<sparc_mmu_interface> m_mmu; // address spaces - address_space_config m_default_config; + address_space_config m_debugger_config; + address_space_config m_asi_config[0x10]; + address_space *m_asi[0x20]; // memory access - uint32_t read_sized_word(const uint8_t asi, const uint32_t address, const uint32_t mem_mask); - void write_sized_word(const uint8_t asi, const uint32_t address, const uint32_t data, const uint32_t mem_mask); + inline uint32_t read_word(const uint8_t asi, const uint32_t address, const uint32_t mem_mask = 0xffffffff); + inline void write_word(const uint8_t asi, const uint32_t address, const uint32_t data, const uint32_t mem_mask = 0xffffffff); // helpers for the disassembler virtual uint64_t get_reg_r(unsigned index) const override; diff --git a/src/devices/cpu/sparc/sparc_intf.h b/src/devices/cpu/sparc/sparc_intf.h index b1fad3ad9a9..f84219be8fd 100644 --- a/src/devices/cpu/sparc/sparc_intf.h +++ b/src/devices/cpu/sparc/sparc_intf.h @@ -23,8 +23,6 @@ class sparc_mmu_interface public: virtual ~sparc_mmu_interface() { } virtual uint32_t fetch_insn(const bool supervisor, const uint32_t offset) = 0; - virtual uint32_t read_asi(uint8_t asi, uint32_t offset, uint32_t mem_mask) = 0; - virtual void write_asi(uint8_t asi, uint32_t offset, uint32_t data, uint32_t mem_mask) = 0; virtual void set_host(sparc_mmu_host_interface *host) = 0; }; diff --git a/src/devices/machine/sun4c_mmu.cpp b/src/devices/machine/sun4c_mmu.cpp index 8e55308adbd..7cc673cb9d1 100644 --- a/src/devices/machine/sun4c_mmu.cpp +++ b/src/devices/machine/sun4c_mmu.cpp @@ -230,107 +230,45 @@ void sun4_mmu_base_device::device_timer(emu_timer &timer, device_timer_id id, in } } -uint32_t sun4_mmu_base_device::fetch_insn(const bool supervisor, const uint32_t offset) +uint32_t sun4_mmu_base_device::fetch_insn(const bool supervisor, uint32_t offset) { if (supervisor) - return insn_data_r<SUPER_INSN, SUPER_MODE>(offset, 0xffffffff); + return insn_data_r<SUPER_INSN>(offset, 0xffffffff); else - return insn_data_r<USER_INSN, USER_MODE>(offset, 0xffffffff); + return insn_data_r<USER_INSN>(offset, 0xffffffff); } -uint32_t sun4_mmu_base_device::read_asi(uint8_t asi, uint32_t offset, uint32_t mem_mask) +void sun4_mmu_base_device::hw_segment_flush_w(uint32_t offset, uint32_t data, uint32_t mem_mask) { - LOGMASKED(LOG_ALL_ASI, "read_asi %d: %08x & %08x\n", asi, offset << 2, mem_mask); - switch (asi) + for (uint32_t i = 0x0000; i < (0x1000 >> (m_cache_tag_shift + 2)); i++) { - case 2: - return system_r(offset, mem_mask); - case 3: - return segment_map_r(offset, mem_mask); - case 4: - return page_map_r(offset, mem_mask); - case 8: - return insn_data_r<USER_INSN, USER_MODE>(offset, mem_mask); - case 9: - return insn_data_r<SUPER_INSN, SUPER_MODE>(offset, mem_mask); - case 10: - return insn_data_r<USER_DATA, USER_MODE>(offset, mem_mask); - case 11: - return insn_data_r<SUPER_DATA, SUPER_MODE>(offset, mem_mask); - case 12: - case 13: - case 14: - return 0; - default: - LOGMASKED(LOG_UNKNOWN_ASI, "Unknown ASI read: %d, %08x & %08x\n", asi, offset << 2, mem_mask); - return ~0; + segment_flush_w(offset | (i << m_cache_tag_shift), data, mem_mask); } } -void sun4_mmu_base_device::write_asi(uint8_t asi, uint32_t offset, uint32_t data, uint32_t mem_mask) +void sun4_mmu_base_device::hw_page_flush_w(uint32_t offset, uint32_t data, uint32_t mem_mask) { - LOGMASKED(LOG_ALL_ASI, "write_asi %d: %08x = %08x & %08x\n", asi, offset << 2, data, mem_mask); - switch (asi) + for (uint32_t i = 0x0000; i < (0x1000 >> (m_cache_tag_shift + 2)); i++) { - case 2: - system_w(offset, data, mem_mask); - return; - case 3: - segment_map_w(offset, data, mem_mask); - return; - case 4: - page_map_w(offset, data, mem_mask); - return; - case 5: - for (uint32_t i = 0x0000; i < (0x1000 >> (m_cache_tag_shift + 2)); i++) - { - segment_flush_w(offset | (i << m_cache_tag_shift)); - } - break; - case 6: - for (uint32_t i = 0x0000; i < (0x1000 >> (m_cache_tag_shift + 2)); i++) - { - page_flush_w(offset | (i << m_cache_tag_shift)); - } - break; - case 7: - for (uint32_t i = 0x0000; i < (0x1000 >> (m_cache_tag_shift + 2)); i++) - { - context_flush_w(offset | (i << m_cache_tag_shift)); - } - break; - case 8: - insn_data_w<USER_INSN, USER_MODE>(offset, data, mem_mask); - return; - case 9: - insn_data_w<SUPER_INSN, SUPER_MODE>(offset, data, mem_mask); - return; - case 10: - insn_data_w<USER_DATA, USER_MODE>(offset, data, mem_mask); - return; - case 11: - insn_data_w<SUPER_DATA, SUPER_MODE>(offset, data, mem_mask); - return; - case 12: - segment_flush_w(offset); - break; - case 13: - page_flush_w(offset); - break; - case 14: - context_flush_w(offset); - return; - case 15: - for (uint32_t i = 0x0000; i < (0x1000 >> (m_cache_tag_shift + 2)); i++) - { - const uint32_t vaddr = offset | (i << m_cache_tag_shift); - const uint32_t tag_addr = vaddr_to_cache_line(vaddr); - m_cachetags[tag_addr] &= ~(1 << 19); - } - break; - default: - LOGMASKED(LOG_UNKNOWN_ASI, "Unknown ASI write: %d, %08x = %08x & %08x\n", asi, offset << 2, data, mem_mask); - return; + page_flush_w(offset | (i << m_cache_tag_shift), data, mem_mask); + } +} + +void sun4_mmu_base_device::hw_context_flush_w(uint32_t offset, uint32_t data, uint32_t mem_mask) +{ + for (uint32_t i = 0x0000; i < (0x1000 >> (m_cache_tag_shift + 2)); i++) + { + context_flush_w(offset | (i << m_cache_tag_shift), data, mem_mask); + } +} + +void sun4_mmu_base_device::hw_flush_all_w(uint32_t offset, uint32_t data, uint32_t mem_mask) +{ + for (uint32_t i = 0x0000; i < (0x1000 >> (m_cache_tag_shift + 2)); i++) + { + const uint32_t vaddr = offset | (i << m_cache_tag_shift); + const uint32_t tag_addr = vaddr_to_cache_line(vaddr); + m_cachetags[tag_addr] &= ~(1 << 19); } } @@ -365,7 +303,7 @@ void sun4_mmu_base_device::parity_w(uint32_t offset, uint32_t data, uint32_t mem } } -void sun4_mmu_base_device::segment_flush_w(const uint32_t vaddr) +void sun4_mmu_base_device::segment_flush_w(uint32_t vaddr, uint32_t data, uint32_t mem_mask) { LOGMASKED(LOG_SEGMENT_FLUSH, "%s: segment_flush_w %08x\n", machine().describe_context(), vaddr); const uint32_t tag_addr = vaddr_to_cache_line(vaddr); @@ -393,7 +331,7 @@ void sun4_mmu_base_device::segment_flush_w(const uint32_t vaddr) } } -void sun4_mmu_base_device::context_flush_w(const uint32_t vaddr) +void sun4_mmu_base_device::context_flush_w(uint32_t vaddr, uint32_t data, uint32_t mem_mask) { LOGMASKED(LOG_CONTEXT_FLUSH, "%s: context_flush_w %08x\n", machine().describe_context(), vaddr << 2); const uint32_t tag_addr = vaddr_to_cache_line(vaddr); @@ -413,7 +351,7 @@ void sun4_mmu_base_device::context_flush_w(const uint32_t vaddr) } } -void sun4_mmu_base_device::page_flush_w(const uint32_t vaddr) +void sun4_mmu_base_device::page_flush_w(uint32_t vaddr, uint32_t data, uint32_t mem_mask) { LOGMASKED(LOG_PAGE_FLUSH, "%s: page_flush_w %08x\n", machine().describe_context(), vaddr << 2); const uint32_t tag_addr = vaddr_to_cache_line(vaddr); @@ -443,133 +381,115 @@ void sun4_mmu_base_device::page_flush_w(const uint32_t vaddr) } } -uint32_t sun4_mmu_base_device::system_r(const uint32_t offset, const uint32_t mem_mask) +uint32_t sun4_mmu_base_device::context_reg_r(uint32_t offset, uint32_t mem_mask) { - LOGMASKED(LOG_SYSTEM, "%s: system_r: %08x & %08x\n", machine().describe_context(), offset << 2, mem_mask); - switch (offset >> 26) + if (mem_mask == 0x00ff0000) { - case 3: // context reg - { - if (mem_mask == 0x00ff0000) - { - LOGMASKED(LOG_CONTEXT, "sun4c_mmu: read context %08x & %08x = %08x\n", offset << 2, mem_mask, m_context<<16); - return m_context<<16; - } - LOGMASKED(LOG_CONTEXT, "sun4c_mmu: read context %08x & %08x = %08x\n", offset << 2, mem_mask, m_context<<24); - return m_context<<24; - } - - case 4: // system enable reg - LOGMASKED(LOG_SYSTEM_ENABLE, "sun4c_mmu: read system enable %08x & %08x = %08x\n", offset << 2, mem_mask, m_system_enable<<24); - return m_system_enable<<24; - - case 6: // bus error register - { - const uint32_t ret = m_buserr[offset & 0xf]; - LOGMASKED(LOG_BUSERROR, "sun4c_mmu: read buserror %08x & %08x = %08x, PC=%x\n", 0x60000000 | (offset << 2), mem_mask, ret, m_cpu->pc()); - m_buserr[offset & 0xf] = 0; // clear on reading - return ret; - } + LOGMASKED(LOG_CONTEXT, "sun4c_mmu: read context %08x & %08x = %08x\n", offset << 2, mem_mask, m_context<<16); + return m_context<<16; + } + LOGMASKED(LOG_CONTEXT, "sun4c_mmu: read context %08x & %08x = %08x\n", offset << 2, mem_mask, m_context<<24); + return m_context<<24; +} - case 8: // (d-)cache tags - LOGMASKED(LOG_CACHE_TAGS, "%s: sun4c_mmu: read dcache tags @ %x, %08x\n", machine().describe_context(), offset << 2, m_cachetags[vaddr_to_cache_line(offset)]); - return m_cachetags[vaddr_to_cache_line(offset)]; +uint32_t sun4_mmu_base_device::system_enable_r(uint32_t offset, uint32_t mem_mask) +{ + LOGMASKED(LOG_SYSTEM_ENABLE, "sun4c_mmu: read system enable %08x & %08x = %08x\n", offset << 2, mem_mask, m_system_enable<<24); + return m_system_enable<<24; +} - case 9: // (d-)cache data - LOGMASKED(LOG_CACHE_DATA, "%s: sun4c_mmu: read dcache data @ %x, PC = %x\n", machine().describe_context(), offset << 2, m_cpu->pc()); - return m_cachedata[offset & 0x3fff]; +uint32_t sun4_mmu_base_device::bus_error_r(uint32_t offset, uint32_t mem_mask) +{ + const uint32_t ret = m_buserr[offset & 0xf]; + LOGMASKED(LOG_BUSERROR, "sun4c_mmu: read buserror %08x & %08x = %08x, PC=%x\n", 0x60000000 | (offset << 2), mem_mask, ret, m_cpu->pc()); + m_buserr[offset & 0xf] = 0; // clear on reading + return ret; +} - case 0xf: // UART bypass - switch (offset & 3) - { - case 0: if (mem_mask == 0xff000000) return m_scc->cb_r(0)<<24; else return m_scc->db_r(0)<<8; break; - case 1: if (mem_mask == 0xff000000) return m_scc->ca_r(0)<<24; else return m_scc->da_r(0)<<8; break; - } - return 0xffffffff; +uint32_t sun4_mmu_base_device::cache_tag_r(uint32_t offset, uint32_t mem_mask) +{ + LOGMASKED(LOG_CACHE_TAGS, "%s: sun4c_mmu: read dcache tags @ %x, %08x\n", machine().describe_context(), offset << 2, m_cachetags[vaddr_to_cache_line(offset)]); + return m_cachetags[vaddr_to_cache_line(offset)]; +} - case 0: // IDPROM - SPARCstation-1 does not have an ID prom and a timeout should occur. - default: - LOGMASKED(LOG_UNKNOWN_SYSTEM, "read unhandled ASI 2 space %08x & %08x\n", offset << 2, mem_mask); - return 0; - } +uint32_t sun4_mmu_base_device::cache_data_r(uint32_t offset, uint32_t mem_mask) +{ + LOGMASKED(LOG_CACHE_DATA, "%s: sun4c_mmu: read dcache data @ %x, PC = %x\n", machine().describe_context(), offset << 2, m_cpu->pc()); + return m_cachedata[offset & 0x3fff]; } -void sun4_mmu_base_device::system_w(const uint32_t offset, const uint32_t data, const uint32_t mem_mask) +uint32_t sun4_mmu_base_device::uart_r(uint32_t offset, uint32_t mem_mask) { - LOGMASKED(LOG_SYSTEM, "system_w: %08x = %08x & %08x\n", offset << 2, data, mem_mask); - switch (offset >> 26) + switch (offset & 3) { - case 3: // context reg - LOGMASKED(LOG_CONTEXT, "write context = %08x & %08x\n", data, mem_mask); - m_context = data >> 24; - m_context_masked = m_context & m_ctx_mask; - m_cache_context = m_context & m_ctx_mask; - m_curr_segmap = &m_segmap[m_context_masked][0]; - m_curr_segmap_masked = &m_segmap_masked[m_context_masked][0]; - return; + case 0: if (mem_mask == 0xff000000) return m_scc->cb_r(0)<<24; else return m_scc->db_r(0)<<8; break; + case 1: if (mem_mask == 0xff000000) return m_scc->ca_r(0)<<24; else return m_scc->da_r(0)<<8; break; + } + return 0xffffffff; +} - case 4: // system enable reg - { - LOGMASKED(LOG_SYSTEM_ENABLE, "write system enable = %08x & %08x\n", data, mem_mask); - m_system_enable = data >> 24; - m_fetch_bootrom = !(m_system_enable & ENA_NOTBOOT); +void sun4_mmu_base_device::context_reg_w(uint32_t offset, uint32_t data, uint32_t mem_mask) +{ + LOGMASKED(LOG_CONTEXT, "write context = %08x & %08x\n", data, mem_mask); + m_context = data >> 24; + m_context_masked = m_context & m_ctx_mask; + m_cache_context = m_context & m_ctx_mask; + m_curr_segmap = &m_segmap[m_context_masked][0]; + m_curr_segmap_masked = &m_segmap_masked[m_context_masked][0]; +} - if (m_system_enable & ENA_RESET) - { - m_reset_timer->adjust(attotime::from_usec(1)); - m_cpu->set_input_line(SPARC_RESET, ASSERT_LINE); - } - if (m_system_enable & ENA_RESET) - { - m_system_enable = 0; - m_cpu->set_input_line(INPUT_LINE_RESET, ASSERT_LINE); - m_cpu->set_input_line(INPUT_LINE_RESET, CLEAR_LINE); - } - return; - } +void sun4_mmu_base_device::system_enable_w(uint32_t offset, uint32_t data, uint32_t mem_mask) +{ + LOGMASKED(LOG_SYSTEM_ENABLE, "write system enable = %08x & %08x\n", data, mem_mask); + m_system_enable = data >> 24; + m_fetch_bootrom = !(m_system_enable & ENA_NOTBOOT); - case 6: // bus error - { - const uint32_t masked_offset = offset & 0xf; - LOGMASKED(LOG_BUSERROR, "write bus error %08x = %08x & %08x\n", offset << 2, data, mem_mask); - if (masked_offset == 0) - m_buserr[0] = (data & 0x000000ff) | 0x00008000; - else - m_buserr[masked_offset] = data; - return; - } + if (m_system_enable & ENA_RESET) + { + m_reset_timer->adjust(attotime::from_usec(1)); + m_cpu->set_input_line(SPARC_RESET, ASSERT_LINE); + } + if (m_system_enable & ENA_RESET) + { + m_system_enable = 0; + m_cpu->set_input_line(INPUT_LINE_RESET, ASSERT_LINE); + m_cpu->set_input_line(INPUT_LINE_RESET, CLEAR_LINE); + } +} - case 8: // cache tags - LOGMASKED(LOG_CACHE_TAGS, "%s: write dcache tags %08x = %08x & %08x\n", machine().describe_context(), offset << 2, data, mem_mask); - m_cachetags[vaddr_to_cache_line(offset)] = data & 0x03f8fffc; - /*if (m_cpu->pc() == 0xFFE8B4F8) - { - m_log_mem = true; - }*/ - return; +void sun4_mmu_base_device::bus_error_w(uint32_t offset, uint32_t data, uint32_t mem_mask) +{ + const uint32_t masked_offset = offset & 0xf; + LOGMASKED(LOG_BUSERROR, "write bus error %08x = %08x & %08x\n", offset << 2, data, mem_mask); + if (masked_offset == 0) + m_buserr[0] = (data & 0x000000ff) | 0x00008000; + else + m_buserr[masked_offset] = data; +} - case 9: // cache data - LOGMASKED(LOG_CACHE_DATA, "write cache data %08x = %08x & %08x\n", offset << 2, data, mem_mask); - COMBINE_DATA(&m_cachedata[offset & 0x3fff]); - m_cachetags[vaddr_to_cache_line(offset)] &= ~(1 << 19); - return; +void sun4_mmu_base_device::cache_tag_w(uint32_t offset, uint32_t data, uint32_t mem_mask) +{ + LOGMASKED(LOG_CACHE_TAGS, "%s: write dcache tags %08x = %08x & %08x\n", machine().describe_context(), offset << 2, data, mem_mask); + m_cachetags[vaddr_to_cache_line(offset)] = data & 0x03f8fffc; +} - case 0xf: // UART bypass - switch (offset & 3) - { - case 0: if (mem_mask == 0xff000000) m_scc->cb_w(0, data>>24); else m_scc->db_w(0, data>>8); break; - case 1: if (mem_mask == 0xff000000) m_scc->ca_w(0, data>>24); else { m_scc->da_w(0, data>>8); logerror("%c\n", data>>8); printf("%c", data>>8); } break; - } - return; +void sun4_mmu_base_device::cache_data_w(uint32_t offset, uint32_t data, uint32_t mem_mask) +{ + LOGMASKED(LOG_CACHE_DATA, "write cache data %08x = %08x & %08x\n", offset << 2, data, mem_mask); + COMBINE_DATA(&m_cachedata[offset & 0x3fff]); + m_cachetags[vaddr_to_cache_line(offset)] &= ~(1 << 19); +} - case 0: // IDPROM - default: - LOGMASKED(LOG_UNKNOWN_SYSTEM, "write unhandled ASI 2 space %08x = %08x & %08x, PC=%08x\n", offset << 2, data, mem_mask, m_cpu->pc()); - return; +void sun4_mmu_base_device::uart_w(uint32_t offset, uint32_t data, uint32_t mem_mask) +{ + switch (offset & 3) + { + case 0: if (mem_mask == 0xff000000) m_scc->cb_w(0, data>>24); else m_scc->db_w(0, data>>8); break; + case 1: if (mem_mask == 0xff000000) m_scc->ca_w(0, data>>24); else { m_scc->da_w(0, data>>8); logerror("%c\n", data>>8); printf("%c", data>>8); } break; } } -uint32_t sun4_mmu_base_device::segment_map_r(const uint32_t offset, const uint32_t mem_mask) +uint32_t sun4_mmu_base_device::segment_map_r(uint32_t offset, uint32_t mem_mask) { uint32_t ret = 0; if (mem_mask == 0xffff0000) @@ -584,7 +504,7 @@ uint32_t sun4_mmu_base_device::segment_map_r(const uint32_t offset, const uint32 return ret; } -void sun4_mmu_base_device::segment_map_w(const uint32_t offset, const uint32_t data, const uint32_t mem_mask) +void sun4_mmu_base_device::segment_map_w(uint32_t offset, uint32_t data, uint32_t mem_mask) { LOGMASKED(LOG_SEGMENT_MAP, "write segment map %08x = %08x & %08x\n", offset << 2, data, mem_mask); @@ -599,7 +519,7 @@ void sun4_mmu_base_device::segment_map_w(const uint32_t offset, const uint32_t d m_curr_segmap_masked[seg] = (segdata & m_pmeg_mask) << 6; } -uint32_t sun4_mmu_base_device::page_map_r(const uint32_t offset, const uint32_t mem_mask) +uint32_t sun4_mmu_base_device::page_map_r(uint32_t offset, uint32_t mem_mask) { const uint32_t page = m_curr_segmap_masked[(offset >> 16) & 0xfff] | ((offset >> m_seg_entry_shift) & m_seg_entry_mask); const uint32_t ret = page_entry_to_uint(page); @@ -607,7 +527,7 @@ uint32_t sun4_mmu_base_device::page_map_r(const uint32_t offset, const uint32_t return ret; } -void sun4_mmu_base_device::page_map_w(const uint32_t offset, const uint32_t data, const uint32_t mem_mask) +void sun4_mmu_base_device::page_map_w(uint32_t offset, uint32_t data, uint32_t mem_mask) { uint32_t page = m_curr_segmap_masked[(offset >> 16) & 0xfff] | ((offset >> m_seg_entry_shift) & m_seg_entry_mask); LOGMASKED(LOG_PAGE_MAP, "write page map %08x (%x) = %08x & %08x\n", offset << 2, page, data, mem_mask); @@ -615,7 +535,7 @@ void sun4_mmu_base_device::page_map_w(const uint32_t offset, const uint32_t data m_page_valid[page] = m_pagemap[page].valid; } -void sun4_mmu_base_device::type0_timeout_r(const uint32_t offset) +void sun4_mmu_base_device::type0_timeout_r(uint32_t offset) { LOGMASKED(LOG_TYPE0_TIMEOUT, "type 0 read timeout %08x, PC=%08x\n", offset << 2, m_cpu->pc()); m_buserr[0] = 0x20; // read timeout @@ -623,7 +543,7 @@ void sun4_mmu_base_device::type0_timeout_r(const uint32_t offset) m_host->set_mae(); } -void sun4_mmu_base_device::type0_timeout_w(const uint32_t offset) +void sun4_mmu_base_device::type0_timeout_w(uint32_t offset) { LOGMASKED(LOG_TYPE0_TIMEOUT, "type 0 write timeout %08x, PC=%08x\n", offset << 2, m_cpu->pc()); m_buserr[0] = 0x8020; // write timeout @@ -703,10 +623,12 @@ void sun4_mmu_base_device::cache_fill(page_entry &entry, uint32_t vaddr, uint32_ } } -template bool sun4_mmu_base_device::cache_fetch<sun4_mmu_base_device::USER_MODE>(page_entry &entry, uint32_t vaddr, uint32_t paddr, uint32_t &cached_data, uint32_t entry_index); -template bool sun4_mmu_base_device::cache_fetch<sun4_mmu_base_device::SUPER_MODE>(page_entry &entry, uint32_t vaddr, uint32_t paddr, uint32_t &cached_data, uint32_t entry_index); +template bool sun4_mmu_base_device::cache_fetch<sun4_mmu_base_device::USER_INSN>(page_entry &entry, uint32_t vaddr, uint32_t paddr, uint32_t &cached_data, uint32_t entry_index); +template bool sun4_mmu_base_device::cache_fetch<sun4_mmu_base_device::USER_DATA>(page_entry &entry, uint32_t vaddr, uint32_t paddr, uint32_t &cached_data, uint32_t entry_index); +template bool sun4_mmu_base_device::cache_fetch<sun4_mmu_base_device::SUPER_INSN>(page_entry &entry, uint32_t vaddr, uint32_t paddr, uint32_t &cached_data, uint32_t entry_index); +template bool sun4_mmu_base_device::cache_fetch<sun4_mmu_base_device::SUPER_DATA>(page_entry &entry, uint32_t vaddr, uint32_t paddr, uint32_t &cached_data, uint32_t entry_index); -template <sun4_mmu_base_device::perm_mode PERM_MODE> +template <sun4_mmu_base_device::insn_data_mode MODE> bool sun4_mmu_base_device::cache_fetch(page_entry &entry, uint32_t vaddr, uint32_t paddr, uint32_t &cached_data, uint32_t entry_index) { const uint32_t cache_line = vaddr_to_cache_line(vaddr); @@ -725,7 +647,7 @@ bool sun4_mmu_base_device::cache_fetch(page_entry &entry, uint32_t vaddr, uint32 else if ((tag & m_cache_tag_id_mask) == ((vaddr >> m_cache_tag_id_shift) & m_cache_tag_id_mask)) { // If the current tag is valid and the tag IDs match, fetch from the cache - if (PERM_MODE == USER_MODE) + if ((MODE >> 1) == USER_MODE) { // If we're in user mode and the context does not match, this is a miss if (((tag >> 22) & m_ctx_mask) != m_context_masked && (tag & (1 << 20))) @@ -750,17 +672,13 @@ bool sun4_mmu_base_device::cache_fetch(page_entry &entry, uint32_t vaddr, uint32 } } -template uint32_t sun4_mmu_base_device::insn_data_r<sun4_mmu_base_device::USER_INSN, sun4_mmu_base_device::USER_MODE>(const uint32_t, const uint32_t); -template uint32_t sun4_mmu_base_device::insn_data_r<sun4_mmu_base_device::SUPER_INSN, sun4_mmu_base_device::USER_MODE>(const uint32_t, const uint32_t); -template uint32_t sun4_mmu_base_device::insn_data_r<sun4_mmu_base_device::USER_DATA, sun4_mmu_base_device::USER_MODE>(const uint32_t, const uint32_t); -template uint32_t sun4_mmu_base_device::insn_data_r<sun4_mmu_base_device::SUPER_DATA, sun4_mmu_base_device::USER_MODE>(const uint32_t, const uint32_t); -template uint32_t sun4_mmu_base_device::insn_data_r<sun4_mmu_base_device::USER_INSN, sun4_mmu_base_device::SUPER_MODE>(const uint32_t, const uint32_t); -template uint32_t sun4_mmu_base_device::insn_data_r<sun4_mmu_base_device::SUPER_INSN, sun4_mmu_base_device::SUPER_MODE>(const uint32_t, const uint32_t); -template uint32_t sun4_mmu_base_device::insn_data_r<sun4_mmu_base_device::USER_DATA, sun4_mmu_base_device::SUPER_MODE>(const uint32_t, const uint32_t); -template uint32_t sun4_mmu_base_device::insn_data_r<sun4_mmu_base_device::SUPER_DATA, sun4_mmu_base_device::SUPER_MODE>(const uint32_t, const uint32_t); - -template <sun4_mmu_base_device::insn_data_mode MODE, sun4_mmu_base_device::perm_mode PERM_MODE> -uint32_t sun4_mmu_base_device::insn_data_r(const uint32_t offset, const uint32_t mem_mask) +template uint32_t sun4_mmu_base_device::insn_data_r<sun4_mmu_base_device::USER_INSN>(const uint32_t, const uint32_t); +template uint32_t sun4_mmu_base_device::insn_data_r<sun4_mmu_base_device::SUPER_INSN>(const uint32_t, const uint32_t); +template uint32_t sun4_mmu_base_device::insn_data_r<sun4_mmu_base_device::USER_DATA>(const uint32_t, const uint32_t); +template uint32_t sun4_mmu_base_device::insn_data_r<sun4_mmu_base_device::SUPER_DATA>(const uint32_t, const uint32_t); + +template <sun4_mmu_base_device::insn_data_mode MODE> +uint32_t sun4_mmu_base_device::insn_data_r(uint32_t offset, uint32_t mem_mask) { // supervisor program fetches in boot state are special if (MODE == SUPER_INSN && m_fetch_bootrom) @@ -785,7 +703,7 @@ uint32_t sun4_mmu_base_device::insn_data_r(const uint32_t offset, const uint32_t { uint32_t tag_entry = vaddr_to_cache_line(offset); uint32_t tag = m_cachetags[tag_entry]; - bool user_mode = (PERM_MODE == USER_MODE); + bool user_mode = ((MODE >> 1) == USER_MODE); bool cache_hit = (tag & m_cache_tag_id_mask) == ((offset >> m_cache_tag_id_shift) & m_cache_tag_id_mask); bool cacheable = entry.type == 0 && !entry.uncached; bool check_cache = cacheable && cache_hit && (m_system_enable & ENA_CACHE); @@ -845,7 +763,7 @@ uint32_t sun4_mmu_base_device::insn_data_r(const uint32_t offset, const uint32_t const uint32_t masked_addr = m_ram_set_base[set] + (paddr & addr_mask); if (!entry.uncached && (m_system_enable & ENA_CACHE)) { - if (cache_fetch<PERM_MODE>(entry, offset, masked_addr, cached_data, entry_index)) + if (cache_fetch<MODE>(entry, offset, masked_addr, cached_data, entry_index)) { #if SUN4CMMU_LOG_MEM_ACCESSES uint32_t value = masked_addr | 0x80000000; @@ -886,7 +804,7 @@ uint32_t sun4_mmu_base_device::insn_data_r(const uint32_t offset, const uint32_t { if (!machine().side_effects_disabled()) { - if ((m_system_enable & ENA_CACHE) && cache_fetch<PERM_MODE>(entry, offset, 0, cached_data, entry_index)) + if ((m_system_enable & ENA_CACHE) && cache_fetch<MODE>(entry, offset, 0, cached_data, entry_index)) { return cached_data; } @@ -915,17 +833,13 @@ uint32_t sun4_mmu_base_device::insn_data_r(const uint32_t offset, const uint32_t } } -template void sun4_mmu_base_device::insn_data_w<sun4_mmu_base_device::USER_INSN, sun4_mmu_base_device::USER_MODE>(const uint32_t, const uint32_t, const uint32_t); -template void sun4_mmu_base_device::insn_data_w<sun4_mmu_base_device::SUPER_INSN, sun4_mmu_base_device::USER_MODE>(const uint32_t, const uint32_t, const uint32_t); -template void sun4_mmu_base_device::insn_data_w<sun4_mmu_base_device::USER_DATA, sun4_mmu_base_device::USER_MODE>(const uint32_t, const uint32_t, const uint32_t); -template void sun4_mmu_base_device::insn_data_w<sun4_mmu_base_device::SUPER_DATA, sun4_mmu_base_device::USER_MODE>(const uint32_t, const uint32_t, const uint32_t); -template void sun4_mmu_base_device::insn_data_w<sun4_mmu_base_device::USER_INSN, sun4_mmu_base_device::SUPER_MODE>(const uint32_t, const uint32_t, const uint32_t); -template void sun4_mmu_base_device::insn_data_w<sun4_mmu_base_device::SUPER_INSN, sun4_mmu_base_device::SUPER_MODE>(const uint32_t, const uint32_t, const uint32_t); -template void sun4_mmu_base_device::insn_data_w<sun4_mmu_base_device::USER_DATA, sun4_mmu_base_device::SUPER_MODE>(const uint32_t, const uint32_t, const uint32_t); -template void sun4_mmu_base_device::insn_data_w<sun4_mmu_base_device::SUPER_DATA, sun4_mmu_base_device::SUPER_MODE>(const uint32_t, const uint32_t, const uint32_t); - -template <sun4_mmu_base_device::insn_data_mode MODE, sun4_mmu_base_device::perm_mode PERM_MODE> -void sun4_mmu_base_device::insn_data_w(const uint32_t offset, const uint32_t data, const uint32_t mem_mask) +template void sun4_mmu_base_device::insn_data_w<sun4_mmu_base_device::USER_INSN>(const uint32_t, const uint32_t, const uint32_t); +template void sun4_mmu_base_device::insn_data_w<sun4_mmu_base_device::SUPER_INSN>(const uint32_t, const uint32_t, const uint32_t); +template void sun4_mmu_base_device::insn_data_w<sun4_mmu_base_device::USER_DATA>(const uint32_t, const uint32_t, const uint32_t); +template void sun4_mmu_base_device::insn_data_w<sun4_mmu_base_device::SUPER_DATA>(const uint32_t, const uint32_t, const uint32_t); + +template <sun4_mmu_base_device::insn_data_mode MODE> +void sun4_mmu_base_device::insn_data_w(uint32_t offset, uint32_t data, uint32_t mem_mask) { // it's translation time const uint32_t pmeg = m_curr_segmap_masked[(offset >> 16) & 0xfff];// & m_pmeg_mask; @@ -939,7 +853,7 @@ void sun4_mmu_base_device::insn_data_w(const uint32_t offset, const uint32_t dat { uint32_t tag_entry = vaddr_to_cache_line(offset); uint32_t tag = m_cachetags[tag_entry]; - bool user_mode = PERM_MODE == USER_MODE; + bool user_mode = (MODE >> 1) == USER_MODE; bool cacheable = entry.type == 0 && !entry.uncached; bool check_cache = cacheable && (m_system_enable & ENA_CACHE); bool cache_valid = BIT(tag, 19); diff --git a/src/devices/machine/sun4c_mmu.h b/src/devices/machine/sun4c_mmu.h index 32623a36769..7ab00c8798a 100644 --- a/src/devices/machine/sun4c_mmu.h +++ b/src/devices/machine/sun4c_mmu.h @@ -52,22 +52,22 @@ public: void set_page_entry_mask(uint32_t page_entry_mask) { m_page_entry_mask = page_entry_mask; } void set_cache_mask(uint32_t cache_mask) { m_cache_mask = cache_mask; } + enum perm_mode + { + USER_MODE, + SUPER_MODE + }; + enum insn_data_mode { USER_INSN, - SUPER_INSN, USER_DATA, + SUPER_INSN, SUPER_DATA }; - enum perm_mode - { - USER_MODE, - SUPER_MODE - }; - - template <insn_data_mode MODE, perm_mode PERM_MODE> uint32_t insn_data_r(const uint32_t offset, const uint32_t mem_mask); - template <insn_data_mode MODE, perm_mode PERM_MODE> void insn_data_w(const uint32_t offset, const uint32_t data, const uint32_t mem_mask); + template <insn_data_mode MODE> uint32_t insn_data_r(uint32_t offset, uint32_t mem_mask); + template <insn_data_mode MODE> void insn_data_w(uint32_t offset, uint32_t data, uint32_t mem_mask); uint32_t type1_timeout_r(uint32_t offset); void type1_timeout_w(uint32_t offset, uint32_t data); @@ -75,11 +75,35 @@ public: void parity_w(uint32_t offset, uint32_t data, uint32_t mem_mask); // sparc_mmu_device overrides - uint32_t fetch_insn(const bool supervisor, const uint32_t offset) override; - uint32_t read_asi(uint8_t asi, uint32_t offset, uint32_t mem_mask) override; - void write_asi(uint8_t asi, uint32_t offset, uint32_t data, uint32_t mem_mask) override; + uint32_t fetch_insn(const bool supervisor, uint32_t offset) override; void set_host(sparc_mmu_host_interface *host) override { m_host = host; } + uint32_t context_reg_r(uint32_t offset, uint32_t mem_mask); + void context_reg_w(uint32_t offset, uint32_t data, uint32_t mem_mask); + uint32_t system_enable_r(uint32_t offset, uint32_t mem_mask); + void system_enable_w(uint32_t offset, uint32_t data, uint32_t mem_mask); + uint32_t bus_error_r(uint32_t offset, uint32_t mem_mask); + void bus_error_w(uint32_t offset, uint32_t data, uint32_t mem_mask); + uint32_t cache_tag_r(uint32_t offset, uint32_t mem_mask); + void cache_tag_w(uint32_t offset, uint32_t data, uint32_t mem_mask); + uint32_t cache_data_r(uint32_t offset, uint32_t mem_mask); + void cache_data_w(uint32_t offset, uint32_t data, uint32_t mem_mask); + uint32_t uart_r(uint32_t offset, uint32_t mem_mask); + void uart_w(uint32_t offset, uint32_t data, uint32_t mem_mask); + uint32_t segment_map_r(uint32_t offset, uint32_t mem_mask); + void segment_map_w(uint32_t offset, uint32_t data, uint32_t mem_mask); + uint32_t page_map_r(uint32_t offset, uint32_t mem_mask); + void page_map_w(uint32_t offset, uint32_t data, uint32_t mem_mask); + + void segment_flush_w(uint32_t offset, uint32_t data, uint32_t mem_mask); + void page_flush_w(uint32_t offset, uint32_t data, uint32_t mem_mask); + void context_flush_w(uint32_t offset, uint32_t data, uint32_t mem_mask); + + void hw_segment_flush_w(uint32_t offset, uint32_t data, uint32_t mem_mask); + void hw_page_flush_w(uint32_t offset, uint32_t data, uint32_t mem_mask); + void hw_context_flush_w(uint32_t offset, uint32_t data, uint32_t mem_mask); + void hw_flush_all_w(uint32_t offset, uint32_t data, uint32_t mem_mask); + protected: sun4_mmu_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); @@ -108,18 +132,9 @@ protected: uint32_t page_entry_to_uint(uint32_t index); void merge_page_entry(uint32_t index, uint32_t data, uint32_t mem_mask); - template <perm_mode MODE> bool cache_fetch(page_entry &entry, uint32_t vaddr, uint32_t paddr, uint32_t &cached_data, uint32_t entry_index); + template <insn_data_mode MODE> bool cache_fetch(page_entry &entry, uint32_t vaddr, uint32_t paddr, uint32_t &cached_data, uint32_t entry_index); void cache_fill(page_entry &entry, uint32_t vaddr, uint32_t paddr, uint32_t entry_index); - void segment_flush_w(const uint32_t vaddr); - void context_flush_w(const uint32_t vaddr); - void page_flush_w(const uint32_t vaddr); - uint32_t system_r(const uint32_t offset, const uint32_t mem_mask); - void system_w(const uint32_t offset, const uint32_t data, const uint32_t mem_mask); - uint32_t segment_map_r(const uint32_t offset, const uint32_t mem_mask); - void segment_map_w(const uint32_t offset, const uint32_t data, const uint32_t mem_mask); - uint32_t page_map_r(const uint32_t offset, const uint32_t mem_mask); - void page_map_w(const uint32_t offset, const uint32_t data, const uint32_t mem_mask); void type0_timeout_r(const uint32_t offset); void type0_timeout_w(const uint32_t offset); bool translate(uint32_t &addr); diff --git a/src/mame/drivers/sun4.cpp b/src/mame/drivers/sun4.cpp index 1089cc9d8ec..45a53f5ead9 100644 --- a/src/mame/drivers/sun4.cpp +++ b/src/mame/drivers/sun4.cpp @@ -580,6 +580,20 @@ protected: void ncr53c90a(device_t *device); void debugger_map(address_map &map); + void system_asi_map(address_map &map); + void segment_asi_map(address_map &map); + void page_asi_map(address_map &map); + void hw_segment_flush_asi_map(address_map &map); + void hw_page_flush_asi_map(address_map &map); + void hw_context_flush_asi_map(address_map &map); + void user_insn_asi_map(address_map &map); + void super_insn_asi_map(address_map &map); + void user_data_asi_map(address_map &map); + void super_data_asi_map(address_map &map); + void sw_segment_flush_asi_map(address_map &map); + void sw_page_flush_asi_map(address_map &map); + void sw_context_flush_asi_map(address_map &map); + void hw_flush_all_asi_map(address_map &map); void type1space_base_map(address_map &map); @@ -673,12 +687,12 @@ private: READ32_MEMBER( sun4_base_state::debugger_r ) { - return m_mmu->insn_data_r<sun4_mmu_base_device::SUPER_INSN, sun4_mmu_base_device::SUPER_MODE>(offset, mem_mask); + return m_mmu->insn_data_r<sun4_mmu_base_device::SUPER_INSN>(offset, mem_mask); } WRITE32_MEMBER( sun4_base_state::debugger_w ) { - m_mmu->insn_data_w<sun4_mmu_base_device::SUPER_INSN, sun4_mmu_base_device::SUPER_MODE>(offset, data, mem_mask); + m_mmu->insn_data_w<sun4_mmu_base_device::SUPER_INSN>(offset, data, mem_mask); } void sun4_base_state::fcodes_command(int ref, const std::vector<std::string> ¶ms) @@ -738,6 +752,81 @@ void sun4_state::type1space_map(address_map &map) type1space_base_map(map); } +void sun4_base_state::system_asi_map(address_map &map) +{ + map(0x30000000, 0x3fffffff).rw(m_mmu, FUNC(sun4_mmu_base_device::context_reg_r), FUNC(sun4_mmu_base_device::context_reg_w)); + map(0x40000000, 0x4fffffff).rw(m_mmu, FUNC(sun4_mmu_base_device::system_enable_r), FUNC(sun4_mmu_base_device::system_enable_w)); + map(0x60000000, 0x6fffffff).rw(m_mmu, FUNC(sun4_mmu_base_device::bus_error_r), FUNC(sun4_mmu_base_device::bus_error_w)); + map(0x80000000, 0x8fffffff).rw(m_mmu, FUNC(sun4_mmu_base_device::cache_tag_r), FUNC(sun4_mmu_base_device::cache_tag_w)); + map(0x90000000, 0x9fffffff).rw(m_mmu, FUNC(sun4_mmu_base_device::cache_data_r), FUNC(sun4_mmu_base_device::cache_data_w)); + map(0xf0000000, 0xffffffff).rw(m_mmu, FUNC(sun4_mmu_base_device::uart_r), FUNC(sun4_mmu_base_device::uart_w)); +} + +void sun4_base_state::segment_asi_map(address_map &map) +{ + map(0x00000000, 0xffffffff).rw(m_mmu, FUNC(sun4_mmu_base_device::segment_map_r), FUNC(sun4_mmu_base_device::segment_map_w)); +} + +void sun4_base_state::page_asi_map(address_map &map) +{ + map(0x00000000, 0xffffffff).rw(m_mmu, FUNC(sun4_mmu_base_device::page_map_r), FUNC(sun4_mmu_base_device::page_map_w)); +} + +void sun4_base_state::hw_segment_flush_asi_map(address_map &map) +{ + map(0x00000000, 0xffffffff).w(m_mmu, FUNC(sun4_mmu_base_device::hw_segment_flush_w)); +} + +void sun4_base_state::hw_page_flush_asi_map(address_map &map) +{ + map(0x00000000, 0xffffffff).w(m_mmu, FUNC(sun4_mmu_base_device::hw_page_flush_w)); +} + +void sun4_base_state::hw_context_flush_asi_map(address_map &map) +{ + map(0x00000000, 0xffffffff).w(m_mmu, FUNC(sun4_mmu_base_device::hw_context_flush_w)); +} + +void sun4_base_state::user_insn_asi_map(address_map &map) +{ + map(0x00000000, 0xffffffff).rw(m_mmu, FUNC(sun4_mmu_base_device::insn_data_r<sun4_mmu_base_device::USER_INSN>), FUNC(sun4_mmu_base_device::insn_data_w<sun4_mmu_base_device::USER_INSN>)); +} + +void sun4_base_state::super_insn_asi_map(address_map &map) +{ + map(0x00000000, 0xffffffff).rw(m_mmu, FUNC(sun4_mmu_base_device::insn_data_r<sun4_mmu_base_device::SUPER_INSN>), FUNC(sun4_mmu_base_device::insn_data_w<sun4_mmu_base_device::SUPER_INSN>)); +} + +void sun4_base_state::user_data_asi_map(address_map &map) +{ + map(0x00000000, 0xffffffff).rw(m_mmu, FUNC(sun4_mmu_base_device::insn_data_r<sun4_mmu_base_device::USER_DATA>), FUNC(sun4_mmu_base_device::insn_data_w<sun4_mmu_base_device::USER_DATA>)); +} + +void sun4_base_state::super_data_asi_map(address_map &map) +{ + map(0x00000000, 0xffffffff).rw(m_mmu, FUNC(sun4_mmu_base_device::insn_data_r<sun4_mmu_base_device::SUPER_DATA>), FUNC(sun4_mmu_base_device::insn_data_w<sun4_mmu_base_device::SUPER_DATA>)); +} + +void sun4_base_state::sw_segment_flush_asi_map(address_map &map) +{ + map(0x00000000, 0xffffffff).w(m_mmu, FUNC(sun4_mmu_base_device::segment_flush_w)); +} + +void sun4_base_state::sw_page_flush_asi_map(address_map &map) +{ + map(0x00000000, 0xffffffff).w(m_mmu, FUNC(sun4_mmu_base_device::page_flush_w)); +} + +void sun4_base_state::sw_context_flush_asi_map(address_map &map) +{ + map(0x00000000, 0xffffffff).w(m_mmu, FUNC(sun4_mmu_base_device::context_flush_w)); +} + +void sun4_base_state::hw_flush_all_asi_map(address_map &map) +{ + map(0x00000000, 0xffffffff).w(m_mmu, FUNC(sun4_mmu_base_device::hw_flush_all_w)); +} + /* Input ports */ static INPUT_PORTS_START( sun4 ) INPUT_PORTS_END @@ -1078,7 +1167,7 @@ void sun4_base_state::dma_transfer_write() pack_cnt++; if (pack_cnt == 4) { - m_mmu->insn_data_w<sun4c_mmu_device::SUPER_DATA, sun4_mmu_base_device::SUPER_MODE>(m_dma[DMA_ADDR] >> 2, m_dma_pack_register, ~0); + m_mmu->insn_data_w<sun4c_mmu_device::SUPER_DATA>(m_dma[DMA_ADDR] >> 2, m_dma_pack_register, ~0); pack_cnt = 0; m_dma_pack_register = 0; m_dma[DMA_ADDR] += 4; @@ -1099,7 +1188,7 @@ void sun4_base_state::dma_transfer_read() { if (!word_cached) { - current_word = m_mmu->insn_data_r<sun4c_mmu_device::SUPER_DATA, sun4_mmu_base_device::SUPER_MODE>(m_dma[DMA_ADDR] >> 2, ~0); + current_word = m_mmu->insn_data_r<sun4c_mmu_device::SUPER_DATA>(m_dma[DMA_ADDR] >> 2, ~0); word_cached = true; //logerror("Current word: %08x\n", current_word); } @@ -1176,7 +1265,7 @@ WRITE32_MEMBER( sun4_base_state::dma_w ) const uint32_t bit_index = (3 - i) * 8; //const uint32_t value = m_dma_pack_register & (0xff << bit_index); //logerror("dma_w: draining %02x to RAM address %08x & %08x\n", value >> bit_index, m_dma[DMA_ADDR], 0xff << (24 - bit_index)); - m_mmu->insn_data_w<sun4c_mmu_device::SUPER_DATA, sun4_mmu_base_device::SUPER_MODE>(m_dma[DMA_ADDR] >> 2, m_dma_pack_register, 0xff << bit_index); + m_mmu->insn_data_w<sun4c_mmu_device::SUPER_DATA>(m_dma[DMA_ADDR] >> 2, m_dma_pack_register, 0xff << bit_index); m_dma[DMA_ADDR]++; } m_dma_pack_register = 0; @@ -1301,16 +1390,16 @@ void sun4_base_state::sun4_base(machine_config &config) AM79C90(config, m_lance); m_lance->dma_in().set([this](offs_t offset) { - u32 const data = m_mmu->insn_data_r<sun4c_mmu_device::SUPER_DATA, sun4_mmu_base_device::SUPER_MODE>((0xff000000U | offset) >> 2, 0xffffffffU); + u32 const data = m_mmu->insn_data_r<sun4c_mmu_device::SUPER_DATA>((0xff000000U | offset) >> 2, 0xffffffffU); return (offset & 2) ? u16(data) : u16(data >> 16); }); m_lance->dma_out().set([this](offs_t offset, u16 data, u16 mem_mask) { if (offset & 2) - m_mmu->insn_data_w<sun4c_mmu_device::SUPER_DATA, sun4_mmu_base_device::SUPER_MODE>((0xff000000U | offset) >> 2, data, mem_mask); + m_mmu->insn_data_w<sun4c_mmu_device::SUPER_DATA>((0xff000000U | offset) >> 2, data, mem_mask); else - m_mmu->insn_data_w<sun4c_mmu_device::SUPER_DATA, sun4_mmu_base_device::SUPER_MODE>((0xff000000U | offset) >> 2, u32(data) << 16, u32(mem_mask) << 16); + m_mmu->insn_data_w<sun4c_mmu_device::SUPER_DATA>((0xff000000U | offset) >> 2, u32(data) << 16, u32(mem_mask) << 16); }); // Keyboard/mouse @@ -1376,7 +1465,21 @@ void sun4c_state::sun4c(machine_config &config) /* basic machine hardware */ SPARCV7(config, m_maincpu, 20'000'000); m_maincpu->add_asi_desc([](sparc_disassembler *dasm) { dasm->add_asi_desc(sun4c_asi_desc); }); - m_maincpu->set_addrmap(0, &sun4c_state::debugger_map); + m_maincpu->set_addrmap(0x00, &sun4c_state::debugger_map); + m_maincpu->set_addrmap(0x12, &sun4c_state::system_asi_map); + m_maincpu->set_addrmap(0x13, &sun4c_state::segment_asi_map); + m_maincpu->set_addrmap(0x14, &sun4c_state::page_asi_map); + m_maincpu->set_addrmap(0x15, &sun4c_state::hw_segment_flush_asi_map); + m_maincpu->set_addrmap(0x16, &sun4c_state::hw_page_flush_asi_map); + m_maincpu->set_addrmap(0x17, &sun4c_state::hw_context_flush_asi_map); + m_maincpu->set_addrmap(0x18, &sun4c_state::user_insn_asi_map); + m_maincpu->set_addrmap(0x19, &sun4c_state::super_insn_asi_map); + m_maincpu->set_addrmap(0x1a, &sun4c_state::user_data_asi_map); + m_maincpu->set_addrmap(0x1b, &sun4c_state::super_data_asi_map); + m_maincpu->set_addrmap(0x1c, &sun4c_state::sw_segment_flush_asi_map); + m_maincpu->set_addrmap(0x1d, &sun4c_state::sw_page_flush_asi_map); + m_maincpu->set_addrmap(0x1e, &sun4c_state::sw_context_flush_asi_map); + m_maincpu->set_addrmap(0x1f, &sun4c_state::hw_flush_all_asi_map); sun4_base(config); |