diff options
Diffstat (limited to 'src/devices/machine/ns32082.cpp')
-rw-r--r-- | src/devices/machine/ns32082.cpp | 120 |
1 files changed, 50 insertions, 70 deletions
diff --git a/src/devices/machine/ns32082.cpp b/src/devices/machine/ns32082.cpp index e5835401745..ffe2f645274 100644 --- a/src/devices/machine/ns32082.cpp +++ b/src/devices/machine/ns32082.cpp @@ -2,27 +2,26 @@ // copyright-holders:Patrick Mackinlay /* - * National Semiconductor 32082 Memory Management Unit. + * National Semiconductor NS32082 Memory Management Unit. * * Sources: - * - http://bitsavers.org/components/national/_dataBooks/1988_National_Series_32000_Microprocessors_Databook.pdf + * - Microprocessor Databook, Series 32000, NSC800, 1989 Edition, National Semiconductor * * TODO: - * - tlb - * - breakpoints + * - tlb + * - breakpoints */ #include "emu.h" #include "ns32082.h" -#define LOG_GENERAL (1U << 0) #define LOG_TRANSLATE (1U << 1) //#define VERBOSE (LOG_GENERAL|LOG_TRANSLATE) #include "logmacro.h" -DEFINE_DEVICE_TYPE(NS32082, ns32082_device, "ns32082", "National Semiconductor 32082 Memory Management Unit") +DEFINE_DEVICE_TYPE(NS32082, ns32082_device, "ns32082", "National Semiconductor NS32082 Memory Management Unit") enum state : unsigned { @@ -35,11 +34,6 @@ enum state : unsigned RESULT = 6, // result word available }; -enum idbyte : u8 -{ - FORMAT_14 = 0x1e, -}; - enum reg_mask : unsigned { BPR0 = 0x0, // breakpoint register 0 @@ -126,28 +120,10 @@ enum eia_mask : u32 EIA_AS = 0x80000000, // address space }; -enum st_mask : unsigned -{ - ST_ICI = 0x0, // bus idle (CPU busy) - ST_ICW = 0x1, // bus idle (CPU wait) - ST_ISE = 0x3, // bus idle (slave execution) - ST_IAM = 0x4, // interrupt acknowledge, master - ST_IAC = 0x5, // interrupt acknowledge, cascaded - ST_EIM = 0x6, // end of interrupt, master - ST_EIC = 0x7, // end of interrupt, cascaded - ST_SIF = 0x8, // sequential instruction fetch - ST_NIF = 0x9, // non-sequential instruction fetch - ST_ODT = 0xa, // operand data transfer - ST_RMW = 0xb, // read RMW operand - ST_EAR = 0xc, // effective address read - ST_SOP = 0xd, // slave operand - ST_SST = 0xe, // slave status - ST_SID = 0xf, // slave ID -}; - ns32082_device::ns32082_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) : device_t(mconfig, NS32082, tag, owner, clock) , ns32000_mmu_interface(mconfig, *this) + , ns32000_slow_slave_interface(mconfig, *this) , m_bpr{} , m_pf{} , m_sc(0) @@ -189,9 +165,12 @@ void ns32082_device::device_reset() void ns32082_device::state_add(device_state_interface &parent, int &index) { parent.state_add(index++, "MSR", m_msr).formatstr("%08X"); + parent.state_add(index++, "PTB0", m_ptb[0]).formatstr("%08X"); + parent.state_add(index++, "PTB1", m_ptb[1]).formatstr("%08X"); + parent.state_add(index++, "EIA", m_eia).formatstr("%08X"); } -u16 ns32082_device::read_st(int *icount) +u16 ns32082_device::slow_status(int *icount) { if (m_state == STATUS) { @@ -200,63 +179,54 @@ u16 ns32082_device::read_st(int *icount) if (icount) *icount -= m_tcy; - LOG("read_st status 0x%04x tcy %d %s (%s)\n", m_status, m_tcy, + LOG("status 0x%04x tcy %d %s (%s)\n", m_status, m_tcy, (m_state == RESULT ? "results pending" : "complete"), machine().describe_context()); return m_status; } - logerror("read_st protocol error reading status word (%s)\n", machine().describe_context()); + logerror("status protocol error (%s)\n", machine().describe_context()); return 0; } -u16 ns32082_device::read_op() +u16 ns32082_device::slow_read() { if (m_state == RESULT && m_op[2].issued < m_op[2].expected) { u16 const data = u16(m_op[2].value >> (m_op[2].issued * 8)); - LOG("read_op word %d data 0x%04x (%s)\n", m_op[2].issued >> 1, data, machine().describe_context()); + LOG("read %d data 0x%04x (%s)\n", m_op[2].issued >> 1, data, machine().describe_context()); m_op[2].issued += 2; if (m_op[2].issued == m_op[2].expected) { - LOG("read_op last result word issued\n"); + LOG("read complete\n"); m_state = IDLE; } return data; } - logerror("read_op protocol error reading result word (%s)\n", machine().describe_context()); + logerror("read protocol error (%s)\n", machine().describe_context()); return 0; } -void ns32082_device::write_id(u16 data) -{ - bool const match = (data == FORMAT_14); - - if (match) - { - LOG("write_id match 0x%04x (%s)\n", data, machine().describe_context()); - m_state = OPERATION; - } - else - { - LOG("write_id ignore 0x%04x (%s)\n", data, machine().describe_context()); - m_state = IDLE; - } - - m_idbyte = u8(data); -} - -void ns32082_device::write_op(u16 data) +void ns32082_device::slow_write(u16 data) { switch (m_state) { + case IDLE: + LOG("write idbyte 0x%04x (%s)\n", data, machine().describe_context()); + if (data == FORMAT_14) + { + m_idbyte = u8(data); + m_state = OPERATION; + } + break; + case OPERATION: m_opword = swapendian_int16(data); - LOG("write_op opword 0x%04x (%s)\n", m_opword, machine().describe_context()); + LOG("write opword 0x%04x (%s)\n", m_opword, machine().describe_context()); m_tcy = 0; @@ -277,8 +247,10 @@ void ns32082_device::write_op(u16 data) switch ((m_opword >> 2) & 15) { case 0: // rdval + m_op[0].expected = size + 1; break; case 1: // wrval + m_op[0].expected = size + 1; break; case 2: // lmr m_op[0].expected = size + 1; @@ -299,14 +271,16 @@ void ns32082_device::write_op(u16 data) unsigned const n = (m_op[0].issued < m_op[0].expected) ? 0 : 1; operand &op = m_op[n]; - LOG("write_op op%d data 0x%04x (%s)\n", n, data, machine().describe_context()); + LOG("write operand %d data 0x%04x (%s)\n", + n, data, machine().describe_context()); // insert word into operand value op.value |= u64(data) << (op.issued * 8); op.issued += 2; } else - logerror("write_op protocol error unexpected operand word 0x%04x (%s)\n", data, machine().describe_context()); + logerror("write protocol error unexpected operand data 0x%04x (%s)\n", + data, machine().describe_context()); break; } @@ -400,12 +374,12 @@ void ns32082_device::set_msr(u32 data) m_msr = (m_msr & ~MSR_WM) | (data & MSR_WM); } -ns32082_device::translate_result ns32082_device::translate(address_space &space, unsigned st, u32 &address, bool user, bool write, bool pfs, bool debug) +ns32082_device::translate_result ns32082_device::translate(address_space &space, unsigned st, u32 &address, bool user, bool write, bool pfs, bool suppress) { // update program flow trace state if (pfs && (m_msr & MSR_FT)) { - if (st == ST_NIF) + if (st == ns32000::ST_NIF) { m_pf[1] = m_pf[0]; m_pf[0] = address; @@ -425,15 +399,12 @@ ns32082_device::translate_result ns32082_device::translate(address_space &space, bool const address_space = (m_msr & MSR_DS) && user; unsigned const access_level = (user && !(m_msr & MSR_AO)) - ? ((write || st == ST_RMW) ? PL_URW : PL_URO) : ((write || st == ST_RMW) ? PL_SRW : PL_SRO); + ? ((write || st == ns32000::ST_RMW) ? PL_URW : PL_URO) : ((write || st == ns32000::ST_RMW) ? PL_SRW : PL_SRO); u32 const ptb = ((m_ptb[address_space] & PTB_MS) >> 7) | (m_ptb[address_space] & PTB_AB); LOGMASKED(LOG_TRANSLATE, "translate address_space %d access_level %d page table 0x%08x address 0x%08x\n", address_space, access_level, ptb, address); - if (m_state == IDLE && !debug) - m_msr &= ~(MSR_EST | MSR_ED | MSR_TET | MSR_TE); - // read level 1 page table entry u32 const pte1_address = ptb | ((address & VA_INDEX1) >> 14); u32 const pte1 = space.read_dword(pte1_address); @@ -441,8 +412,11 @@ ns32082_device::translate_result ns32082_device::translate(address_space &space, if (access_level > (pte1 & PTE_PL) || !(pte1 & PTE_V)) { - if (m_state == IDLE && !debug) + if (m_state == IDLE && !suppress) { + // reset error status + m_msr &= ~(MSR_EST | MSR_ED | MSR_TET | MSR_TE); + m_msr |= (write ? 0 : MSR_ED) | ((st & 7) << 10) | MSR_TE; if (access_level > (pte1 & PTE_PL)) m_msr |= TET_PL; @@ -470,7 +444,7 @@ ns32082_device::translate_result ns32082_device::translate(address_space &space, } // set referenced - if (!(pte1 & PTE_R) && !debug) + if (!(pte1 & PTE_R) && !suppress) space.write_word(pte1_address, u16(pte1 | PTE_R)); // read level 2 page table entry @@ -480,8 +454,11 @@ ns32082_device::translate_result ns32082_device::translate(address_space &space, if (access_level > (pte2 & PTE_PL) || !(pte2 & PTE_V)) { - if (m_state == IDLE && !debug) + if (m_state == IDLE && !suppress) { + // reset error status + m_msr &= ~(MSR_EST | MSR_ED | MSR_TET | MSR_TE); + m_msr |= (write ? 0 : MSR_ED) | ((st & 7) << 10) | MSR_TE; if (access_level > (pte2 & PTE_PL)) m_msr |= TET_PL; @@ -494,7 +471,7 @@ ns32082_device::translate_result ns32082_device::translate(address_space &space, if (m_state == RDVAL || m_state == WRVAL) { m_state = STATUS; - if (pte1 & PTE_V) + if (pte2 & PTE_V) m_status |= SLAVE_F; return CANCEL; @@ -507,11 +484,14 @@ ns32082_device::translate_result ns32082_device::translate(address_space &space, } // set modified and referenced - if ((!(pte2 & PTE_R) || (write && !(pte2 & PTE_M))) && !debug) + if ((!(pte2 & PTE_R) || (write && !(pte2 & PTE_M))) && !suppress) space.write_word(pte2_address, u16(pte2 | (write ? PTE_M : 0) | PTE_R)); address = ((pte1 & PTE_MS) >> 7) | (pte2 & PTE_PFN) | (address & VA_OFFSET); LOGMASKED(LOG_TRANSLATE, "translate complete 0x%08x\n", address); + if (m_state == RDVAL || m_state == WRVAL) + m_state = STATUS; + return COMPLETE; } |