mirror of
https://github.com/holub/mame
synced 2025-04-16 21:44:32 +03:00
ns32082: new device
This commit is contained in:
parent
644d85fbe9
commit
80fb62cce5
@ -4734,3 +4734,14 @@ if (MACHINES["NS32202"]~=null) then
|
|||||||
MAME_DIR .. "src/devices/machine/ns32202.h",
|
MAME_DIR .. "src/devices/machine/ns32202.h",
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---------------------------------------------------
|
||||||
|
--
|
||||||
|
--@src/devices/machine/ns32082.h,MACHINES["NS32082"] = true
|
||||||
|
---------------------------------------------------
|
||||||
|
if (MACHINES["NS32082"]~=null) then
|
||||||
|
files {
|
||||||
|
MAME_DIR .. "src/devices/machine/ns32082.cpp",
|
||||||
|
MAME_DIR .. "src/devices/machine/ns32082.h",
|
||||||
|
}
|
||||||
|
end
|
||||||
|
@ -814,6 +814,7 @@ MACHINES["CXD1185"] = true
|
|||||||
MACHINES["BL_HANDHELDS_MENUCONTROL"] = true
|
MACHINES["BL_HANDHELDS_MENUCONTROL"] = true
|
||||||
MACHINES["NS32081"] = true
|
MACHINES["NS32081"] = true
|
||||||
MACHINES["NS32202"] = true
|
MACHINES["NS32202"] = true
|
||||||
|
MACHINES["NS32082"] = true
|
||||||
|
|
||||||
--------------------------------------------------
|
--------------------------------------------------
|
||||||
-- specify available bus cores
|
-- specify available bus cores
|
||||||
|
492
src/devices/machine/ns32082.cpp
Normal file
492
src/devices/machine/ns32082.cpp
Normal file
@ -0,0 +1,492 @@
|
|||||||
|
// license:BSD-3-Clause
|
||||||
|
// copyright-holders:Patrick Mackinlay
|
||||||
|
|
||||||
|
/*
|
||||||
|
* National Semiconductor 32082 Memory Management Unit.
|
||||||
|
*
|
||||||
|
* Sources:
|
||||||
|
* - http://bitsavers.org/components/national/_dataBooks/1988_National_Series_32000_Microprocessors_Databook.pdf
|
||||||
|
*
|
||||||
|
* TODO:
|
||||||
|
* - 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")
|
||||||
|
|
||||||
|
enum state : unsigned
|
||||||
|
{
|
||||||
|
IDLE = 0,
|
||||||
|
OPERATION = 1, // awaiting operation word
|
||||||
|
OPERAND = 2, // awaiting operands
|
||||||
|
RDVAL = 3, // rdval pending
|
||||||
|
WRVAL = 4, // wrval pending
|
||||||
|
STATUS = 5, // status word available
|
||||||
|
RESULT = 6, // result word available
|
||||||
|
};
|
||||||
|
|
||||||
|
enum idbyte : u8
|
||||||
|
{
|
||||||
|
FORMAT_14 = 0x1e,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum reg_mask : unsigned
|
||||||
|
{
|
||||||
|
BPR0 = 0x0, // breakpoint register 0
|
||||||
|
BPR1 = 0x1, // breakpoint register 1
|
||||||
|
MSR = 0xa, // memory management status register
|
||||||
|
BCNT = 0xb, // breakpoint counter register
|
||||||
|
PTB0 = 0xc, // page table base register 0
|
||||||
|
PTB1 = 0xd, // page table base register 1
|
||||||
|
EIA = 0xf, // error/invalidate address register
|
||||||
|
};
|
||||||
|
|
||||||
|
enum msr_mask : u32
|
||||||
|
{
|
||||||
|
MSR_TE = 0x00000001, // translation error
|
||||||
|
MSR_R = 0x00000002, // reset
|
||||||
|
MSR_B = 0x00000004, // break
|
||||||
|
MSR_TET = 0x00000038, // translation error type
|
||||||
|
MSR_BN = 0x00000040, // breakpoint number
|
||||||
|
MSR_ED = 0x00000100, // error direction
|
||||||
|
MSR_BD = 0x00000200, // break direction
|
||||||
|
MSR_EST = 0x00001c00, // error status
|
||||||
|
MSR_BST = 0x0000e000, // breakpoint status
|
||||||
|
MSR_TU = 0x00010000, // translate user-mode addresses
|
||||||
|
MSR_TS = 0x00020000, // translate supervisor-mode addresses
|
||||||
|
MSR_DS = 0x00040000, // dual-space translation
|
||||||
|
MSR_AO = 0x00080000, // access level override
|
||||||
|
MSR_BEN = 0x00100000, // breakpoint enable
|
||||||
|
MSR_UB = 0x00200000, // user-only breakpointing
|
||||||
|
MSR_AI = 0x00400000, // abort/interrupt
|
||||||
|
|
||||||
|
MSR_ERC = 0x00000007,
|
||||||
|
MSR_WM = 0x007f0000,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum msr_tet_mask : u32
|
||||||
|
{
|
||||||
|
TET_PL = 0x00000008,
|
||||||
|
TET_IL1 = 0x00000010,
|
||||||
|
TET_IL2 = 0x00000020,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ptb_mask : u32
|
||||||
|
{
|
||||||
|
PTB_AB = 0x00fffc00, // address bits
|
||||||
|
PTB_MS = 0x80000000, // memory system
|
||||||
|
};
|
||||||
|
|
||||||
|
enum va_mask : u32
|
||||||
|
{
|
||||||
|
VA_INDEX1 = 0x00ff0000,
|
||||||
|
VA_INDEX2 = 0x0000fe00,
|
||||||
|
VA_OFFSET = 0x000001ff,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum pte_mask : u32
|
||||||
|
{
|
||||||
|
PTE_V = 0x00000001, // valid
|
||||||
|
PTE_PL = 0x00000006, // protection level
|
||||||
|
PTE_R = 0x00000008, // referenced
|
||||||
|
PTE_M = 0x00000010, // modified
|
||||||
|
PTE_NSC = 0x00000060, // reserved
|
||||||
|
PTE_USR = 0x00000180, // user bits
|
||||||
|
PTE_PFN = 0x00fffe00, // page frame number
|
||||||
|
PTE_MS = 0x80000000, // memory system
|
||||||
|
};
|
||||||
|
|
||||||
|
enum pte_pl_mask : u32
|
||||||
|
{
|
||||||
|
PL_SRO = 0x00000000, // supervisor read only
|
||||||
|
PL_SRW = 0x00000002, // supervisor read write
|
||||||
|
PL_URO = 0x00000004, // user read only
|
||||||
|
PL_URW = 0x00000006, // user read write
|
||||||
|
};
|
||||||
|
|
||||||
|
enum eia_mask : u32
|
||||||
|
{
|
||||||
|
EIA_VA = 0x00ffffff, // virtual address
|
||||||
|
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)
|
||||||
|
, m_bpr{}
|
||||||
|
, m_msr(0)
|
||||||
|
, m_bcnt(0)
|
||||||
|
, m_ptb{}
|
||||||
|
, m_eia(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void ns32082_device::device_start()
|
||||||
|
{
|
||||||
|
save_item(NAME(m_bpr));
|
||||||
|
save_item(NAME(m_msr));
|
||||||
|
save_item(NAME(m_bcnt));
|
||||||
|
save_item(NAME(m_ptb));
|
||||||
|
save_item(NAME(m_eia));
|
||||||
|
|
||||||
|
save_item(NAME(m_idbyte));
|
||||||
|
save_item(NAME(m_opword));
|
||||||
|
save_item(STRUCT_MEMBER(m_op, expected));
|
||||||
|
save_item(STRUCT_MEMBER(m_op, issued));
|
||||||
|
save_item(STRUCT_MEMBER(m_op, value));
|
||||||
|
save_item(NAME(m_status));
|
||||||
|
|
||||||
|
save_item(NAME(m_state));
|
||||||
|
save_item(NAME(m_tcy));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ns32082_device::device_reset()
|
||||||
|
{
|
||||||
|
m_msr = 0;
|
||||||
|
|
||||||
|
m_state = IDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ns32082_device::state_add(device_state_interface &parent, int &index)
|
||||||
|
{
|
||||||
|
parent.state_add(index++, "MSR", m_msr).formatstr("%08X");
|
||||||
|
}
|
||||||
|
|
||||||
|
u16 ns32082_device::read_st(int *icount)
|
||||||
|
{
|
||||||
|
if (m_state == STATUS)
|
||||||
|
{
|
||||||
|
m_state = (m_op[2].issued == m_op[2].expected) ? IDLE : RESULT;
|
||||||
|
|
||||||
|
if (icount)
|
||||||
|
*icount -= m_tcy;
|
||||||
|
|
||||||
|
LOG("read_st 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());
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
u16 ns32082_device::read_op()
|
||||||
|
{
|
||||||
|
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());
|
||||||
|
|
||||||
|
m_op[2].issued += 2;
|
||||||
|
|
||||||
|
if (m_op[2].issued == m_op[2].expected)
|
||||||
|
{
|
||||||
|
LOG("read_op last result word issued\n");
|
||||||
|
m_state = IDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
logerror("read_op protocol error reading result word (%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)
|
||||||
|
{
|
||||||
|
switch (m_state)
|
||||||
|
{
|
||||||
|
case OPERATION:
|
||||||
|
m_opword = swapendian_int16(data);
|
||||||
|
LOG("write_op opword 0x%04x (%s)\n", m_opword, machine().describe_context());
|
||||||
|
|
||||||
|
m_tcy = 0;
|
||||||
|
|
||||||
|
// initialize operands
|
||||||
|
for (operand &op : m_op)
|
||||||
|
{
|
||||||
|
op.expected = 0;
|
||||||
|
op.issued = 0;
|
||||||
|
op.value = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// decode operands
|
||||||
|
if (m_idbyte == FORMAT_14)
|
||||||
|
{
|
||||||
|
// format 14: xxxx xsss s0oo ooii 0001 1110
|
||||||
|
unsigned const size = m_opword & 3;
|
||||||
|
|
||||||
|
switch ((m_opword >> 2) & 15)
|
||||||
|
{
|
||||||
|
case 0: // rdval
|
||||||
|
break;
|
||||||
|
case 1: // wrval
|
||||||
|
break;
|
||||||
|
case 2: // lmr
|
||||||
|
m_op[0].expected = size + 1;
|
||||||
|
break;
|
||||||
|
case 3: // smr
|
||||||
|
m_op[2].expected = size + 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_state = OPERAND;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OPERAND:
|
||||||
|
// check awaiting operand word
|
||||||
|
if (m_op[0].issued < m_op[0].expected || m_op[1].issued < m_op[1].expected)
|
||||||
|
{
|
||||||
|
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());
|
||||||
|
|
||||||
|
// 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());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// start execution when all operands are available
|
||||||
|
if (m_state == OPERAND && m_op[0].issued >= m_op[0].expected && m_op[1].issued >= m_op[1].expected)
|
||||||
|
execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ns32082_device::execute()
|
||||||
|
{
|
||||||
|
m_status = 0;
|
||||||
|
|
||||||
|
switch (m_idbyte)
|
||||||
|
{
|
||||||
|
case FORMAT_14:
|
||||||
|
// format 14: xxxx xsss s0oo ooii 0001 1110
|
||||||
|
{
|
||||||
|
unsigned const quick = BIT(m_opword, 7, 4);
|
||||||
|
|
||||||
|
switch (BIT(m_opword, 2, 4))
|
||||||
|
{
|
||||||
|
case 0: // rdval
|
||||||
|
m_tcy = 21;
|
||||||
|
m_state = RDVAL;
|
||||||
|
break;
|
||||||
|
case 1: // wrval
|
||||||
|
m_tcy = 21;
|
||||||
|
m_state = WRVAL;
|
||||||
|
break;
|
||||||
|
case 2: // lmr
|
||||||
|
switch (quick)
|
||||||
|
{
|
||||||
|
case BPR0: m_bpr[0] = m_op[0].value & u32(0xfcffffff); break;
|
||||||
|
case BPR1: m_bpr[1] = m_op[0].value & u32(0xf8ffffff); break;
|
||||||
|
case MSR: set_msr(m_op[0].value); break;
|
||||||
|
case BCNT: m_bcnt = m_op[0].value & u32(0x00ffffff); break;
|
||||||
|
case PTB0: m_ptb[0] = m_op[0].value & u32(0xfffffc00); break;
|
||||||
|
case PTB1: m_ptb[1] = m_op[0].value & u32(0xfffffc00); break;
|
||||||
|
case EIA: set_eia(m_op[0].value); break;
|
||||||
|
default:
|
||||||
|
logerror("lmr unknown register %d (%s)\n", quick, machine().describe_context());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
m_tcy = 30;
|
||||||
|
break;
|
||||||
|
case 3: // smr
|
||||||
|
switch (quick)
|
||||||
|
{
|
||||||
|
case BPR0: m_op[2].value = m_bpr[0]; break;
|
||||||
|
case BPR1: m_op[2].value = m_bpr[1]; break;
|
||||||
|
case MSR: m_op[2].value = m_msr; break;
|
||||||
|
case BCNT: m_op[2].value = m_bcnt; break;
|
||||||
|
case PTB0: m_op[2].value = m_ptb[0]; break;
|
||||||
|
case PTB1: m_op[2].value = m_ptb[1]; break;
|
||||||
|
case EIA: m_op[2].value = m_eia; break;
|
||||||
|
default:
|
||||||
|
logerror("smr unknown register %d (%s)\n", quick, machine().describe_context());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
m_tcy = 25;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// exceptions suppress result issue
|
||||||
|
if (m_status & SLAVE_Q)
|
||||||
|
m_op[2].expected = 0;
|
||||||
|
|
||||||
|
if (m_state == OPERAND)
|
||||||
|
m_state = STATUS;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ns32082_device::set_msr(u32 data)
|
||||||
|
{
|
||||||
|
if (data & MSR_R)
|
||||||
|
m_msr &= ~(MSR_TE | MSR_B | MSR_TET | MSR_ED | MSR_BD | MSR_EST | MSR_BST);
|
||||||
|
|
||||||
|
if ((m_msr ^ data) & (MSR_TS | MSR_TU))
|
||||||
|
LOG("supervisor translation %s user translation %s (%s)\n",
|
||||||
|
data & MSR_TS ? "enabled" : "disabled",
|
||||||
|
data & MSR_TU ? "enabled" : "disabled", machine().describe_context());
|
||||||
|
|
||||||
|
m_msr = (m_msr & ~MSR_WM) | (data & MSR_WM);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* FIXME: RDVAL/WRVAL don't trigger abort on protection failures, but it's not
|
||||||
|
* clear if the memory access is cancelled on a protection failure or invalid
|
||||||
|
* level 2 page table entry. Also not clear if MSR/EIA are updated.
|
||||||
|
*/
|
||||||
|
ns32082_device::translate_result ns32082_device::translate(address_space &space, unsigned st, u32 &address, bool user, bool write, bool debug)
|
||||||
|
{
|
||||||
|
// check translation required
|
||||||
|
if ((!(m_msr & MSR_TU) && user) || (!(m_msr & MSR_TS) && !user))
|
||||||
|
return COMPLETE;
|
||||||
|
|
||||||
|
// treat WRVAL as write
|
||||||
|
write |= m_state == WRVAL;
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
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);
|
||||||
|
LOGMASKED(LOG_TRANSLATE, "translate level 1 page table address 0x%06x entry 0x%08x\n", pte1_address, pte1);
|
||||||
|
|
||||||
|
if (access_level > (pte1 & PTE_PL) || !(pte1 & PTE_V))
|
||||||
|
{
|
||||||
|
if (m_state == IDLE && !debug)
|
||||||
|
{
|
||||||
|
m_msr |= (write ? 0 : MSR_ED) | ((st & 7) << 10) | MSR_TE;
|
||||||
|
if (access_level > (pte1 & PTE_PL))
|
||||||
|
m_msr |= TET_PL;
|
||||||
|
if (!(pte1 & PTE_V))
|
||||||
|
m_msr |= TET_IL1;
|
||||||
|
|
||||||
|
m_eia = (address_space ? EIA_AS : 0) | (address & EIA_VA);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_state == RDVAL || m_state == WRVAL)
|
||||||
|
{
|
||||||
|
if (pte1 & PTE_V)
|
||||||
|
{
|
||||||
|
m_state = STATUS;
|
||||||
|
m_status |= SLAVE_F;
|
||||||
|
|
||||||
|
return CANCEL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
m_state = IDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGMASKED(LOG_TRANSLATE, "translate level 1 abort eia 0x%08x\n", m_eia);
|
||||||
|
return ABORT;
|
||||||
|
}
|
||||||
|
|
||||||
|
// set referenced
|
||||||
|
if (!(pte1 & PTE_R) && !debug)
|
||||||
|
space.write_word(pte1_address, u16(pte1 | PTE_R));
|
||||||
|
|
||||||
|
// read level 2 page table entry
|
||||||
|
u32 const pte2_address = ((pte1 & PTE_MS) >> 7) | (pte1 & PTE_PFN) | ((address & VA_INDEX2) >> 7);
|
||||||
|
u32 const pte2 = space.read_dword(pte2_address);
|
||||||
|
LOGMASKED(LOG_TRANSLATE, "translate level 2 page table address 0x%06x entry 0x%08x\n", pte2_address, pte2);
|
||||||
|
|
||||||
|
if (access_level > (pte2 & PTE_PL) || !(pte2 & PTE_V))
|
||||||
|
{
|
||||||
|
if (m_state == IDLE && !debug)
|
||||||
|
{
|
||||||
|
m_msr |= (write ? 0 : MSR_ED) | ((st & 7) << 10) | MSR_TE;
|
||||||
|
if (access_level > (pte2 & PTE_PL))
|
||||||
|
m_msr |= TET_PL;
|
||||||
|
if (!(pte2 & PTE_V))
|
||||||
|
m_msr |= TET_IL2;
|
||||||
|
|
||||||
|
m_eia = (address_space ? EIA_AS : 0) | (address & EIA_VA);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_state == RDVAL || m_state == WRVAL)
|
||||||
|
{
|
||||||
|
m_state = STATUS;
|
||||||
|
if (pte1 & PTE_V)
|
||||||
|
m_status |= SLAVE_F;
|
||||||
|
|
||||||
|
return CANCEL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOGMASKED(LOG_TRANSLATE, "translate level 2 abort eia 0x%08x\n", m_eia);
|
||||||
|
return ABORT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// set modified and referenced
|
||||||
|
if ((!(pte2 & PTE_R) || (write && !(pte2 & PTE_M))) && !debug)
|
||||||
|
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);
|
||||||
|
|
||||||
|
return COMPLETE;
|
||||||
|
}
|
65
src/devices/machine/ns32082.h
Normal file
65
src/devices/machine/ns32082.h
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
// license:BSD-3-Clause
|
||||||
|
// copyright-holders:Patrick Mackinlay
|
||||||
|
|
||||||
|
#ifndef MAME_MACHINE_NS32082_H
|
||||||
|
#define MAME_MACHINE_NS32082_H
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "cpu/ns32000/slave.h"
|
||||||
|
|
||||||
|
class ns32082_device
|
||||||
|
: public device_t
|
||||||
|
, public ns32000_mmu_interface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ns32082_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
|
||||||
|
|
||||||
|
virtual void state_add(device_state_interface &parent, int &index) override;
|
||||||
|
|
||||||
|
virtual u16 read_st(int *icount = nullptr) override;
|
||||||
|
virtual u16 read_op() override;
|
||||||
|
|
||||||
|
virtual void write_id(u16 data) override;
|
||||||
|
virtual void write_op(u16 data) override;
|
||||||
|
|
||||||
|
virtual translate_result translate(address_space &space, unsigned st, u32 &address, bool user, bool write, bool debug = false) override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// device_t overrides
|
||||||
|
virtual void device_start() override;
|
||||||
|
virtual void device_reset() override;
|
||||||
|
|
||||||
|
void execute();
|
||||||
|
|
||||||
|
void set_msr(u32 data);
|
||||||
|
void set_eia(u32 data) {}
|
||||||
|
|
||||||
|
private:
|
||||||
|
// registers
|
||||||
|
u32 m_bpr[2];
|
||||||
|
u32 m_msr;
|
||||||
|
u32 m_bcnt;
|
||||||
|
u32 m_ptb[2];
|
||||||
|
u32 m_eia;
|
||||||
|
|
||||||
|
// operating state
|
||||||
|
u8 m_idbyte;
|
||||||
|
u16 m_opword;
|
||||||
|
struct operand
|
||||||
|
{
|
||||||
|
unsigned expected;
|
||||||
|
unsigned issued;
|
||||||
|
u64 value;
|
||||||
|
}
|
||||||
|
m_op[3];
|
||||||
|
u16 m_status;
|
||||||
|
|
||||||
|
// implementation state
|
||||||
|
unsigned m_state;
|
||||||
|
unsigned m_tcy;
|
||||||
|
};
|
||||||
|
|
||||||
|
DECLARE_DEVICE_TYPE(NS32082, ns32082_device)
|
||||||
|
|
||||||
|
#endif // MAME_MACHINE_NS32082_H
|
@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
// various hardware
|
// various hardware
|
||||||
#include "machine/ns32081.h"
|
#include "machine/ns32081.h"
|
||||||
//#include "machine/ns32082.h"
|
#include "machine/ns32082.h"
|
||||||
#include "machine/ns32202.h"
|
#include "machine/ns32202.h"
|
||||||
#include "machine/am79c90.h"
|
#include "machine/am79c90.h"
|
||||||
//#include "machine/am9516.h"
|
//#include "machine/am9516.h"
|
||||||
@ -53,6 +53,7 @@ public:
|
|||||||
: driver_device(mconfig, type, tag)
|
: driver_device(mconfig, type, tag)
|
||||||
, m_cpu(*this, "cpu")
|
, m_cpu(*this, "cpu")
|
||||||
, m_fpu(*this, "fpu")
|
, m_fpu(*this, "fpu")
|
||||||
|
, m_mmu(*this, "mmu")
|
||||||
, m_icu(*this, "icu")
|
, m_icu(*this, "icu")
|
||||||
, m_ram(*this, "ram")
|
, m_ram(*this, "ram")
|
||||||
, m_sram(*this, "sram")
|
, m_sram(*this, "sram")
|
||||||
@ -96,6 +97,7 @@ private:
|
|||||||
// devices
|
// devices
|
||||||
required_device<ns32016_device> m_cpu;
|
required_device<ns32016_device> m_cpu;
|
||||||
required_device<ns32081_device> m_fpu;
|
required_device<ns32081_device> m_fpu;
|
||||||
|
required_device<ns32082_device> m_mmu;
|
||||||
required_device<ns32202_device> m_icu;
|
required_device<ns32202_device> m_icu;
|
||||||
required_device<ram_device> m_ram;
|
required_device<ram_device> m_ram;
|
||||||
required_device<nvram_device> m_sram;
|
required_device<nvram_device> m_sram;
|
||||||
@ -293,9 +295,12 @@ void mg1_state::mg1(machine_config &config)
|
|||||||
m_cpu->set_addrmap(0, &mg1_state::cpu_map<0>);
|
m_cpu->set_addrmap(0, &mg1_state::cpu_map<0>);
|
||||||
m_cpu->set_addrmap(6, &mg1_state::cpu_map<6>);
|
m_cpu->set_addrmap(6, &mg1_state::cpu_map<6>);
|
||||||
m_cpu->set_fpu(m_fpu);
|
m_cpu->set_fpu(m_fpu);
|
||||||
|
m_cpu->set_mmu(m_mmu);
|
||||||
|
|
||||||
NS32081(config, m_fpu, 16_MHz_XTAL / 2);
|
NS32081(config, m_fpu, 16_MHz_XTAL / 2);
|
||||||
|
|
||||||
|
NS32082(config, m_mmu, 16_MHz_XTAL / 2);
|
||||||
|
|
||||||
NS32202(config, m_icu, 5_MHz_XTAL);
|
NS32202(config, m_icu, 5_MHz_XTAL);
|
||||||
m_icu->out_int().set_inputline(m_cpu, INPUT_LINE_IRQ0);
|
m_icu->out_int().set_inputline(m_cpu, INPUT_LINE_IRQ0);
|
||||||
/*
|
/*
|
||||||
|
Loading…
Reference in New Issue
Block a user