ns32082: implement program flow trace support

This commit is contained in:
Patrick Mackinlay 2021-07-28 17:48:19 +07:00
parent e16435f2ab
commit 90d694c29b
6 changed files with 42 additions and 10 deletions

View File

@ -240,11 +240,11 @@ template <int Width> void ns32000_device<Width>::state_string_export(device_stat
*
* Underlying handlers further subdivide accesses by device bus width.
*/
template <int Width> template<typename T> T ns32000_device<Width>::mem_read(unsigned st, u32 address, bool user)
template <int Width> template<typename T> T ns32000_device<Width>::mem_read(unsigned st, u32 address, bool user, bool pfs)
{
u32 physical = address;
ns32000_mmu_interface::translate_result tr = m_mmu ?
m_mmu->translate(m_bus[st].space(), st, physical, (m_psr & PSR_U) || user, false) : ns32000_mmu_interface::COMPLETE;
m_mmu->translate(m_bus[st].space(), st, physical, (m_psr & PSR_U) || user, false, pfs) : ns32000_mmu_interface::COMPLETE;
if (tr == ns32000_mmu_interface::COMPLETE)
{
@ -404,7 +404,7 @@ template <int Width> template<typename T> void ns32000_device<Width>::mem_write(
*/
template <int Width> template<typename T> T ns32000_device<Width>::fetch(unsigned &bytes)
{
T const data = mem_read<T>(m_sequential ? ST_SIF : ST_NIF, m_pc + bytes);
T const data = mem_read<T>(m_sequential ? ST_SIF : ST_NIF, m_pc + bytes, false, bytes == 0);
bytes += sizeof(T);
m_sequential = true;
@ -3341,7 +3341,7 @@ template <int Width> device_memory_interface::space_config_vector ns32000_device
template <int Width> bool ns32000_device<Width>::memory_translate(int spacenum, int intention, offs_t &address)
{
return !m_mmu || m_mmu->translate(space(spacenum), spacenum, address, intention & TRANSLATE_USER_MASK, intention & TRANSLATE_WRITE, intention & TRANSLATE_DEBUG_MASK) == ns32000_mmu_interface::COMPLETE;
return !m_mmu || m_mmu->translate(space(spacenum), spacenum, address, intention & TRANSLATE_USER_MASK, intention & TRANSLATE_WRITE, false, intention & TRANSLATE_DEBUG_MASK) == ns32000_mmu_interface::COMPLETE;
}
template <int Width> std::unique_ptr<util::disasm_interface> ns32000_device<Width>::create_disassembler()

View File

@ -119,7 +119,7 @@ protected:
};
// memory accessors
template <typename T> T mem_read(unsigned st, u32 address, bool user = false);
template <typename T> T mem_read(unsigned st, u32 address, bool user = false, bool pfs = false);
template <typename T> void mem_write(unsigned st, u32 address, T data, bool user = false);
// instruction fetch/decode helpers

View File

@ -543,7 +543,7 @@ offs_t ns32000_disassembler::disassemble(std::ostream &stream, offs_t pc, data_b
case 0x1e:
// format 14: xxxx xsss s0oo ooii 0001 1110
{
char const *const mmureg[] = { "BPR0", "BPR1", "", "", "", "", "", "", "", "", "MSR", "BCNT", "PTB0", "PTB1", "", "EIA" };
char const *const mmureg[] = { "BPR0", "BPR1", "", "", "PF0", "PF1", "", "", "SC", "", "MSR", "BCNT", "PTB0", "PTB1", "", "EIA" };
u16 const opword = opcodes.r16(pc + bytes); bytes += 2;

View File

@ -57,7 +57,7 @@ public:
}
enum translate_result : unsigned { COMPLETE, CANCEL, ABORT };
virtual translate_result translate(address_space &space, unsigned st, u32 &address, bool user, bool write, bool debug = false) = 0;
virtual translate_result translate(address_space &space, unsigned st, u32 &address, bool user, bool write, bool pfs = false, bool debug = false) = 0;
};
#endif // MAME_CPU_NS32000_SLAVE_H

View File

@ -44,6 +44,9 @@ enum reg_mask : unsigned
{
BPR0 = 0x0, // breakpoint register 0
BPR1 = 0x1, // breakpoint register 1
PF0 = 0x4, // program flow register 0 (removed at rev L)
PF1 = 0x5, // program flow register 1 (removed at rev L)
SC = 0x8, // sequential count register (removed at rev L)
MSR = 0xa, // memory management status register
BCNT = 0xb, // breakpoint counter register
PTB0 = 0xc, // page table base register 0
@ -69,9 +72,12 @@ enum msr_mask : u32
MSR_BEN = 0x00100000, // breakpoint enable
MSR_UB = 0x00200000, // user-only breakpointing
MSR_AI = 0x00400000, // abort/interrupt
MSR_FT = 0x00800000, // flow trace (removed at rev L)
MSR_UT = 0x01000000, // user trace (removed at rev L)
MSR_NT = 0x02000000, // nonsequential trace (removed at rev L)
MSR_ERC = 0x00000007,
MSR_WM = 0x007f0000,
MSR_WM = 0x03ff0000,
};
enum msr_tet_mask : u32
@ -143,6 +149,8 @@ ns32082_device::ns32082_device(machine_config const &mconfig, char const *tag, d
: device_t(mconfig, NS32082, tag, owner, clock)
, ns32000_mmu_interface(mconfig, *this)
, m_bpr{}
, m_pf{}
, m_sc(0)
, m_msr(0)
, m_bcnt(0)
, m_ptb{}
@ -153,6 +161,8 @@ ns32082_device::ns32082_device(machine_config const &mconfig, char const *tag, d
void ns32082_device::device_start()
{
save_item(NAME(m_bpr));
save_item(NAME(m_pf));
save_item(NAME(m_sc));
save_item(NAME(m_msr));
save_item(NAME(m_bcnt));
save_item(NAME(m_ptb));
@ -331,6 +341,9 @@ void ns32082_device::execute()
{
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 PF0: m_pf[0] = m_op[0].value & u32(0x00ffffff); break;
case PF1: m_pf[1] = m_op[0].value & u32(0x00ffffff); break;
case SC: m_sc = m_op[0].value; 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;
@ -347,6 +360,9 @@ void ns32082_device::execute()
{
case BPR0: m_op[2].value = m_bpr[0]; break;
case BPR1: m_op[2].value = m_bpr[1]; break;
case PF0: m_op[2].value = m_pf[0]; break;
case PF1: m_op[2].value = m_pf[1]; break;
case SC: m_op[2].value = m_sc; 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;
@ -384,8 +400,22 @@ 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 debug)
ns32082_device::translate_result ns32082_device::translate(address_space &space, unsigned st, u32 &address, bool user, bool write, bool pfs, bool debug)
{
// update program flow trace state
if (pfs && (m_msr & MSR_FT))
{
if (st == ST_NIF)
{
m_pf[1] = m_pf[0];
m_pf[0] = address;
m_sc = m_sc << 16;
}
m_sc++;
}
// check translation required
if ((!(m_msr & MSR_TU) && user) || (!(m_msr & MSR_TS) && !user))
return COMPLETE;

View File

@ -23,7 +23,7 @@ public:
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;
virtual translate_result translate(address_space &space, unsigned st, u32 &address, bool user, bool write, bool pfs = false, bool debug = false) override;
protected:
// device_t overrides
@ -38,6 +38,8 @@ protected:
private:
// registers
u32 m_bpr[2];
u32 m_pf[2];
u32 m_sc;
u32 m_msr;
u32 m_bcnt;
u32 m_ptb[2];