summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices')
-rw-r--r--src/devices/machine/sun4c_mmu.cpp132
-rw-r--r--src/devices/machine/sun4c_mmu.h10
2 files changed, 134 insertions, 8 deletions
diff --git a/src/devices/machine/sun4c_mmu.cpp b/src/devices/machine/sun4c_mmu.cpp
index 1ff3e9da52f..c0a93267db1 100644
--- a/src/devices/machine/sun4c_mmu.cpp
+++ b/src/devices/machine/sun4c_mmu.cpp
@@ -30,11 +30,13 @@ DEFINE_DEVICE_TYPE(SUN4C_MMU, sun4c_mmu_device, "sun4c_mmu", "Sun 4c MMU")
#define LOG_UNKNOWN_SYSTEM (1U << 9)
#define LOG_UNKNOWN_SEGMENT (1U << 10)
#define LOG_TYPE0_TIMEOUT (1U << 11)
-#define LOG_UNKNOWN_SPACE (1U << 12)
-#define LOG_WRITE_PROTECT (1U << 13)
-#define LOG_ALL_ASI (1U << 14) // WARNING: Heavy!
+#define LOG_TYPE1_TIMEOUT (1U << 12)
+#define LOG_UNKNOWN_SPACE (1U << 13)
+#define LOG_WRITE_PROTECT (1U << 14)
+#define LOG_PARITY (1U << 15)
+#define LOG_ALL_ASI (1U << 16) // WARNING: Heavy!
-#define VERBOSE (0)
+#define VERBOSE (LOG_CACHE_TAGS)
#include "logmacro.h"
sun4_mmu_base_device::sun4_mmu_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
@@ -108,6 +110,7 @@ void sun4_mmu_base_device::device_start()
save_item(NAME(m_system_enable));
save_item(NAME(m_fetch_bootrom));
save_item(NAME(m_buserr));
+ save_item(NAME(m_type1_offset));
save_item(NAME(m_ctx_mask));
save_item(NAME(m_pmeg_mask));
save_item(NAME(m_page_mask));
@@ -118,6 +121,9 @@ void sun4_mmu_base_device::device_start()
save_item(NAME(m_ram_set_mask));
save_item(NAME(m_ram_set_base));
save_item(NAME(m_populated_ram_words));
+ save_item(NAME(m_parity_err_reg));
+ save_item(NAME(m_memory_err_reg));
+ save_item(NAME(m_parity_err));
if (machine().debug_flags & DEBUG_FLAG_ENABLED)
{
@@ -128,6 +134,7 @@ void sun4_mmu_base_device::device_start()
void sun4_mmu_base_device::device_reset()
{
+ m_log_mem = false;
m_rom_ptr = (uint32_t *)m_rom->base();
m_ram_ptr = (uint32_t *)m_ram->pointer();
m_ram_size = m_ram->size();
@@ -163,7 +170,7 @@ void sun4_mmu_base_device::device_reset()
m_system_enable = 0;
m_fetch_bootrom = true;
- memset(m_buserr, 0, sizeof(uint32_t) * 4);
+ memset(m_buserr, 0, sizeof(uint32_t) * 8);
for (int i = 0; i < 16; i++)
{
memset(&m_segmap[i][0], 0, 4096);
@@ -255,6 +262,37 @@ void sun4_mmu_base_device::write_asi(uint8_t asi, uint32_t offset, uint32_t data
}
}
+uint32_t sun4_mmu_base_device::parity_r(uint32_t offset, uint32_t mem_mask)
+{
+ if (offset == 0)
+ {
+ const uint32_t data = m_parity_err_reg;
+ logerror("%s: parity_err_reg read: %08x & %08x\n", machine().describe_context(), m_parity_err_reg, mem_mask);
+ m_parity_err_reg &= ~0xcf;
+ return data;
+ }
+ else if (offset == 1)
+ {
+ logerror("%s: memory_err_reg read: %08x & %08x\n", machine().describe_context(), m_memory_err_reg, mem_mask);
+ return m_memory_err_reg;
+ }
+ return 0;
+}
+
+void sun4_mmu_base_device::parity_w(uint32_t offset, uint32_t data, uint32_t mem_mask)
+{
+ if (offset == 0)
+ {
+ logerror("%s: parity_err_reg write: %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ COMBINE_DATA(&m_parity_err_reg);
+ }
+ else
+ {
+ logerror("%s: memory_err_reg write: %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ COMBINE_DATA(&m_memory_err_reg);
+ }
+}
+
uint32_t sun4_mmu_base_device::cache_flush_r()
{
// Do nothing for now
@@ -363,8 +401,12 @@ void sun4_mmu_base_device::system_w(const uint32_t offset, const uint32_t data,
}
case 8: // cache tags
- LOGMASKED(LOG_CACHE_TAGS, "write cache tags %08x = %08x & %08x\n", offset << 2, data, mem_mask);
+ LOGMASKED(LOG_CACHE_TAGS, "%s: write cache tags %08x = %08x & %08x\n", machine().describe_context(), offset << 2, data, mem_mask);
m_cachetags[offset & m_cache_mask] = data & 0x03f8fffc;
+ if (m_cpu->pc() == 0xFFE8B940)
+ {
+ m_log_mem = true;
+ }
return;
case 9: // cache data
@@ -376,7 +418,7 @@ void sun4_mmu_base_device::system_w(const uint32_t offset, const uint32_t data,
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); printf("%c", 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;
@@ -449,6 +491,21 @@ void sun4_mmu_base_device::type0_timeout_w(const uint32_t offset)
m_host->set_mae();
}
+uint32_t sun4_mmu_base_device::type1_timeout_r(uint32_t offset)
+{
+ LOGMASKED(LOG_TYPE1_TIMEOUT, "type 1 read timeout %08x, PC=%08x\n", offset << 2, m_cpu->pc());
+ m_buserr[2] = 0x20; // read timeout
+ m_buserr[3] = m_type1_offset << 2;
+ return 0;
+}
+
+void sun4_mmu_base_device::type1_timeout_w(uint32_t offset, uint32_t data)
+{
+ LOGMASKED(LOG_TYPE1_TIMEOUT, "type 1 write timeout %08x = %08x, PC=%08x\n", offset << 2, data, m_cpu->pc());
+ m_buserr[2] = 0x120; // write timeout
+ m_buserr[3] = m_type1_offset << 2;
+}
+
uint32_t sun4_mmu_base_device::page_entry_to_uint(uint32_t index)
{
const page_entry &pe = m_pagemap[index];
@@ -463,6 +520,12 @@ void sun4_mmu_base_device::merge_page_entry(uint32_t index, uint32_t data, uint3
pe.writable = new_value & PM_WRITEMASK;
pe.supervisor = new_value & PM_SYSMASK;
pe.uncached = new_value & PM_CACHE;
+
+ if (pe.uncached)
+ logerror("page entry %05x is uncached\n", index);
+ else
+ logerror("page entry %05x is cached\n", index);
+
pe.type = (new_value & PM_TYPEMASK) >> 26;
pe.accessed = new_value & PM_ACCESSED;
pe.modified = new_value & PM_MODIFIED;
@@ -480,7 +543,8 @@ uint32_t sun4_mmu_base_device::insn_data_r(const uint32_t offset, const uint32_t
// supervisor program fetches in boot state are special
if (MODE == SUPER_INSN && m_fetch_bootrom)
{
- m_cpu->eat_cycles(50);
+ if (!machine().side_effects_disabled())
+ m_cpu->eat_cycles(50); // !?
return m_rom_ptr[offset & 0x1ffff];
}
@@ -500,9 +564,44 @@ uint32_t sun4_mmu_base_device::insn_data_r(const uint32_t offset, const uint32_t
case 0: // type 0 space
if (tmp < m_populated_ram_words)
{
+ if (BIT(m_parity_err_reg, 4) && m_parity_err)
+ {
+ logerror("%s: ram read with parity %08x: %08x & %08x\n", machine().describe_context(), m_parity_err_reg, offset, mem_mask);
+ m_parity_err_reg |= m_parity_err;
+ if (BIT(m_parity_err_reg, 7))
+ {
+ m_parity_err_reg |= (1 << 6);
+ }
+ uint8_t boffs = 0;
+
+ if (ACCESSING_BITS_24_31)
+ boffs = 0;
+ else if (ACCESSING_BITS_16_23)
+ boffs = 1;
+ else if (ACCESSING_BITS_8_15)
+ boffs = 2;
+ else if (ACCESSING_BITS_0_7)
+ boffs = 3;
+
+ m_parity_err_reg |= (1 << 7);
+ m_parity_err = 0;
+ m_buserr[0] = 0x8; // Read cycle, memory error
+ m_buserr[1] = (offset << 2) | boffs;
+ m_host->set_mae();
+ }
+ if (!entry.uncached)
+ {
+ const uint32_t cache_entry = (offset >> 2) & 0xfff;
+ m_cachetags[cache_entry] |= (1 << 19);
+ m_cachetags[cache_entry] &= ~(3 << 20);
+ m_cachetags[cache_entry] |= entry.supervisor ? (1 << 20) : (0 << 20);
+ m_cachetags[cache_entry] |= entry.writable ? (1 << 21) : (0 << 21);
+ }
const uint32_t set = (tmp >> 22) & 3;
const uint32_t addr_mask = m_ram_set_mask[set];
const uint32_t masked_addr = m_ram_set_base[set] + (tmp & addr_mask);
+ //if (m_log_mem)
+ //logerror("RAM read: %08x (%08x)\n", offset << 2, tmp << 2);
return m_ram_ptr[masked_addr];
}
else if (tmp >= 0x4000000 >> 2 && tmp < 0x10000000 >> 2)
@@ -512,6 +611,7 @@ uint32_t sun4_mmu_base_device::insn_data_r(const uint32_t offset, const uint32_t
return ~0;
case 1: // type 1 space
+ m_type1_offset = offset;
return m_type1_r(tmp, mem_mask);
default:
@@ -585,10 +685,25 @@ void sun4_mmu_base_device::insn_data_w(const uint32_t offset, const uint32_t dat
case 0: // type 0
if (tmp < m_populated_ram_words)
{
+ if (BIT(m_parity_err_reg, 5))
+ {
+ logerror("%s: ram write with parity %08x: %08x = %08x & %08x\n", machine().describe_context(), m_parity_err_reg, offset, data, mem_mask);
+ if (ACCESSING_BITS_24_31)
+ m_parity_err |= (1 << 0);
+ if (ACCESSING_BITS_16_23)
+ m_parity_err |= (1 << 1);
+ if (ACCESSING_BITS_8_15)
+ m_parity_err |= (1 << 2);
+ if (ACCESSING_BITS_0_7)
+ m_parity_err |= (1 << 3);
+ }
+ m_cachetags[(offset >> 4) & m_cache_mask] |= (1 << 19);
const uint32_t set = (tmp >> 22) & 3;
const uint32_t addr_mask = m_ram_set_mask[set];
const uint32_t masked_addr = m_ram_set_base[set] + (tmp & addr_mask);
COMBINE_DATA((m_ram_ptr + masked_addr));
+ //if (m_log_mem)
+ //logerror("RAM write: %08x (%08x) = %08x\n", offset << 2, tmp << 2, data);
}
else if (tmp >= 0x4000000 >> 2 && tmp < 0x10000000 >> 2)
{
@@ -597,6 +712,7 @@ void sun4_mmu_base_device::insn_data_w(const uint32_t offset, const uint32_t dat
return;
case 1: // type 1
+ m_type1_offset = offset;
m_type1_w(tmp, data, mem_mask);
return;
diff --git a/src/devices/machine/sun4c_mmu.h b/src/devices/machine/sun4c_mmu.h
index 1386867a7ce..51bf57c4aa3 100644
--- a/src/devices/machine/sun4c_mmu.h
+++ b/src/devices/machine/sun4c_mmu.h
@@ -59,6 +59,11 @@ public:
template <insn_data_mode MODE> uint32_t insn_data_r(const uint32_t offset, const uint32_t mem_mask);
template <insn_data_mode MODE> void insn_data_w(const uint32_t offset, const uint32_t data, const uint32_t mem_mask);
+ uint32_t type1_timeout_r(uint32_t offset);
+ void type1_timeout_w(uint32_t offset, uint32_t data);
+ uint32_t parity_r(uint32_t offset, uint32_t mem_mask);
+ 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;
@@ -148,6 +153,10 @@ protected:
uint8_t m_system_enable;
bool m_fetch_bootrom;
uint32_t m_buserr[16];
+ uint32_t m_type1_offset;
+ uint32_t m_parity_err_reg;
+ uint32_t m_memory_err_reg;
+ uint32_t m_parity_err;
// Pre-computed data for optimization purposes
std::unique_ptr<std::unique_ptr<uint32_t[]>[]> m_segmap_masked;
@@ -167,6 +176,7 @@ protected:
uint32_t m_ram_set_base[4];
uint32_t m_populated_ram_words;
emu_timer *m_reset_timer;
+ bool m_log_mem;
};
class sun4_mmu_device : public sun4_mmu_base_device