diff options
| author | 2017-09-05 17:45:17 +0700 | |
|---|---|---|
| committer | 2017-09-05 17:45:17 +0700 | |
| commit | 8a692c36281c3f2050d2ccb45bea843ef0b3ee77 (patch) | |
| tree | bd07c251c4d1f560634e3d78fd224356b6a441c2 /src | |
| parent | 67ddfe302cdc18b356839797d166f7bfda4ce2af (diff) | |
clipper: interrupt handling fixes
* improve interrupt vector handling
* fix C300 interrupt entry and stack frame
* fix pushw where source register is same as stack register
* switch to logmacro.h logging
Diffstat (limited to 'src')
| -rw-r--r-- | src/devices/cpu/clipper/clipper.cpp | 114 | ||||
| -rw-r--r-- | src/devices/cpu/clipper/clipper.h | 23 | ||||
| -rw-r--r-- | src/mame/drivers/interpro.cpp | 2 |
3 files changed, 98 insertions, 41 deletions
diff --git a/src/devices/cpu/clipper/clipper.cpp b/src/devices/cpu/clipper/clipper.cpp index 9282525205b..c2d057d8d35 100644 --- a/src/devices/cpu/clipper/clipper.cpp +++ b/src/devices/cpu/clipper/clipper.cpp @@ -21,8 +21,12 @@ #include "debugger.h" #include "clipper.h" -#define VERBOSE 0 -#define LOG_INTERRUPT(...) do { if (VERBOSE) logerror(__VA_ARGS__); } while (false) +#define LOG_GENERAL (1U << 0) +#define LOG_INTERRUPT (1U << 1) + +//#define VERBOSE (LOG_GENERAL | LOG_INTERRUPT) + +#include "logmacro.h" // convenience macros for frequently used instruction fields #define R1 (m_info.r1) @@ -109,7 +113,16 @@ void clipper_device::device_start() // set our instruction counter m_icountptr = &m_icount; - //save_item(NAME(m_pc)); + save_item(NAME(m_pc)); + save_item(NAME(m_psw)); + save_item(NAME(m_ssw)); + save_item(NAME(m_ru)); + save_item(NAME(m_rs)); + save_item(NAME(m_f)); + + save_item(NAME(m_nmi)); + save_item(NAME(m_irq)); + save_item(NAME(m_ivec)); state_add(STATE_GENPC, "GENPC", m_pc).noshow(); state_add(STATE_GENPCBASE, "CURPC", m_pc).noshow(); @@ -178,8 +191,9 @@ void clipper_device::device_reset() // FIXME: figure out how to branch to the boot code properly m_pc = 0x7f100000; - m_irq = 0; - m_nmi = 0; + m_irq = CLEAR_LINE; + m_nmi = CLEAR_LINE; + m_ivec = 0; } void clipper_device::state_string_export(const device_state_entry &entry, std::string &str) const @@ -206,23 +220,21 @@ void clipper_device::execute_run() // acknowledge non-maskable interrupt standard_irq_callback(INPUT_LINE_NMI); - LOG_INTERRUPT("non-maskable interrupt - current pc = 0x%08x\n", m_pc); + LOGMASKED(LOG_INTERRUPT, "non-maskable interrupt\n"); m_pc = intrap(EXCEPTION_INTERRUPT_BASE, m_pc); } else if (SSW(EI) && m_irq) { - // FIXME: sample interrupt vector from the bus without acknowledging the interrupt - u8 ivec = standard_irq_callback(-1); - LOG_INTERRUPT("received prioritised interrupt with vector 0x%04x\n", ivec); + LOGMASKED(LOG_INTERRUPT, "received prioritised interrupt ivec 0x%02x\n", m_ivec); // allow equal/higher priority interrupts - if ((ivec >> 4) <= SSW(IL)) + if ((m_ivec & IVEC_LEVEL) <= SSW(IL)) { // acknowledge interrupt standard_irq_callback(INPUT_LINE_IRQ0); - LOG_INTERRUPT("accepting interrupt vector 0x%04x - current pc = %08x\n", ivec, m_pc); - m_pc = intrap(EXCEPTION_INTERRUPT_BASE + ivec * 8, m_pc); + LOGMASKED(LOG_INTERRUPT, "transferring control to ivec 0x%02x\n", m_ivec); + m_pc = intrap(EXCEPTION_INTERRUPT_BASE + m_ivec * 8, m_pc); } } @@ -233,9 +245,10 @@ void clipper_device::execute_run() // fetch instruction word insn = m_insn->read_word(m_pc + 0); + // decode instruction decode_instruction(insn); - // decode and execute instruction, return next pc + // execute instruction, return next pc m_pc = execute_instruction(); // FIXME: some instructions take longer (significantly) than one cycle @@ -374,7 +387,7 @@ void clipper_device::decode_instruction (u16 insn) break; default: - logerror("illegal addressing mode pc = 0x%08x\n", m_pc); + LOG("illegal addressing mode pc 0x%08x\n", m_pc); machine().debug_break(); break; } @@ -444,16 +457,15 @@ int clipper_device::execute_instruction () break; case 0x14: // pushw: push word + m_data->write_dword(m_r[R1] - 4, m_r[R2]); m_r[R1] -= 4; - m_data->write_dword(m_r[R1], m_r[R2]); // TRAPS: A,P,W break; case 0x16: // popw: pop word - m_r[R2] = m_data->read_dword(m_r[R1]); - if (R1 != R2) - m_r[R1] += 4; + m_r[R1] += 4; + m_r[R2] = m_data->read_dword(m_r[R1] - 4); // TRAPS: C,U,A,P,R break; @@ -1217,7 +1229,7 @@ int clipper_device::execute_instruction () break; #endif default: - logerror("illegal unprivileged macro opcode at 0x%08x\n", m_pc); + LOG("illegal unprivileged macro opcode at 0x%08x\n", m_pc); next_pc = intrap(EXCEPTION_ILLEGAL_OPERATION, next_pc, CTS_ILLEGAL_OPERATION); machine().debug_break(); break; @@ -1263,7 +1275,7 @@ int clipper_device::execute_instruction () break; case 0x04: // reti: restore psw, ssw and pc from supervisor stack - LOG_INTERRUPT("reti r%d, ssp = %08x, pc = %08x, next_pc = %08x\n", + LOGMASKED(LOG_INTERRUPT, "reti r%d ssp 0x%08x pc 0x%08x next_pc 0x%08x\n", (m_info.macro >> 4) & 0xf, m_rs[(m_info.macro >> 4) & 0xf], m_pc, m_data->read_dword(m_rs[(m_info.macro >> 4) & 0xf] + 8)); m_psw = m_data->read_dword(m_rs[(m_info.macro >> 4) & 0xf] + 0); @@ -1288,7 +1300,7 @@ int clipper_device::execute_instruction () default: // illegal operation - logerror("illegal privileged macro opcode at 0x%08x\n", m_pc); + LOG("illegal privileged macro opcode at 0x%08x\n", m_pc); next_pc = intrap(EXCEPTION_ILLEGAL_OPERATION, next_pc, CTS_ILLEGAL_OPERATION); machine().debug_break(); break; @@ -1309,7 +1321,7 @@ int clipper_device::execute_instruction () #endif default: - logerror("illegal opcode at 0x%08x\n", m_pc); + LOG("illegal opcode at 0x%08x\n", m_pc); next_pc = intrap(EXCEPTION_ILLEGAL_OPERATION, next_pc, CTS_ILLEGAL_OPERATION); break; } @@ -1322,28 +1334,62 @@ int clipper_device::execute_instruction () */ u32 clipper_device::intrap(u32 vector, u32 pc, u32 cts, u32 mts) { - LOG_INTERRUPT("intrap - vector %x, pc = 0x%08x, next_pc = 0x%08x, ssp = 0x%08x\n", vector, pc, m_data->read_dword(vector + 4), m_rs[15]); + // fetch pc and ssw from interrupt vector + u32 next_pc = m_data->read_dword(vector + 0); + u32 next_ssw = m_data->read_dword(vector + 4); + + LOGMASKED(LOG_INTERRUPT, "intrap vector 0x%08x pc 0x%08x next_pc 0x%08x ssp 0x%08x\n", vector, pc, next_pc, m_rs[15]); // set cts and mts to indicate source of exception m_psw = (m_psw & ~(PSW_CTS | PSW_MTS)) | mts | cts; - // push pc, psw and ssw onto supervisor stack - m_data->write_dword(m_rs[15] - 4, pc); - m_data->write_dword(m_rs[15] - 12, m_psw); - m_data->write_dword(m_rs[15] - 8, m_ssw); + // push pc, ssw and psw onto supervisor stack + m_data->write_dword(m_rs[15] - 0x4, pc); + m_data->write_dword(m_rs[15] - 0x8, m_ssw); + m_data->write_dword(m_rs[15] - 0xc, m_psw); // decrement supervisor stack pointer + m_rs[15] -= 12; - // NOTE: while not explicitly stated anywhere, it seems the InterPro boot code has been + // load ssw from trap vector and set previous mode + set_ssw((next_ssw & ~(SSW(P))) | (SSW(U) << 1)); + + // clear psw + m_psw = 0; + + m_r = SSW(U) ? m_ru : m_rs; + + // return new pc from trap vector + return next_pc; +} + +u32 clipper_c400_device::intrap(u32 vector, u32 pc, u32 cts, u32 mts) +{ + // C400 reverses order of pc and ssw in interrupt vector + u32 next_pc = m_data->read_dword(vector + 4); + u32 next_ssw = m_data->read_dword(vector + 0); + + LOGMASKED(LOG_INTERRUPT, "intrap vector 0x%08x pc 0x%08x next_pc 0x%08x ssp 0x%08x\n", vector, pc, next_pc, m_rs[15]); + + // set cts and mts to indicate source of exception + m_psw = (m_psw & ~(PSW_CTS | PSW_MTS)) | mts | cts; + + // push pc, ssw and psw onto supervisor stack + m_data->write_dword(m_rs[15] - 0x4, pc); + m_data->write_dword(m_rs[15] - 0x8, m_ssw); + m_data->write_dword(m_rs[15] - 0xc, m_psw); + + // decrement supervisor stack pointer + + // NOTE: while not explicitly stated anywhere, it seems the InterPro C400 boot code has been // developed with the assumption that the SSP is decremented by 24 bytes during an exception, - // rather than the 12 bytes that might otherwise be expected. This means the exception handler + // rather than the 12 bytes for the InterPro C300 version. This means the exception handler // code must explicitly increment the SSP by 12 prior to executing the RETI instruction, - // as otherwise the SSP will not be pointing at a valid return frame. It's possible this - // behaviour might vary with some other version of the CPU, but this is all we know for now. + // as otherwise the SSP will not be pointing at a valid return frame. m_rs[15] -= 24; // load ssw from trap vector and set previous mode - set_ssw((m_data->read_dword(vector + 0) & ~(SSW(P))) | (SSW(U) << 1)); + set_ssw((next_ssw & ~(SSW(P))) | (SSW(U) << 1)); // clear psw m_psw = 0; @@ -1351,10 +1397,10 @@ u32 clipper_device::intrap(u32 vector, u32 pc, u32 cts, u32 mts) m_r = SSW(U) ? m_ru : m_rs; // return new pc from trap vector - return m_data->read_dword(vector + 4); + return next_pc; } -bool clipper_device::evaluate_branch () +bool clipper_device::evaluate_branch() const { switch (m_info.r2) { diff --git a/src/devices/cpu/clipper/clipper.h b/src/devices/cpu/clipper/clipper.h index 0a95c77aa5d..27624b4e05a 100644 --- a/src/devices/cpu/clipper/clipper.h +++ b/src/devices/cpu/clipper/clipper.h @@ -14,6 +14,10 @@ class clipper_device : public cpu_device { +public: + DECLARE_READ32_MEMBER(get_ssw) const { return m_ssw; } + DECLARE_WRITE8_MEMBER(set_ivec) { m_ivec = data; } + protected: enum registers { @@ -177,10 +181,12 @@ protected: MTS_WRITE_PROTECT_FAULT = 7 << 28, }; -public: - DECLARE_READ32_MEMBER(ssw) { return m_ssw; } + enum ivec_mask + { + IVEC_NUMBER = 0x0f, + IVEC_LEVEL = 0xf0 + }; -protected: clipper_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, const u32 cpuid); // device-level overrides @@ -224,17 +230,18 @@ protected: // floating registers double m_f[16]; -private: address_space_config m_insn_config; address_space_config m_data_config; address_space *m_insn; address_space *m_data; +private: int m_icount; int m_irq; int m_nmi; + u8 m_ivec; // decoded instruction information struct @@ -254,9 +261,10 @@ private: void decode_instruction(u16 insn); int execute_instruction(); - bool evaluate_branch(); + bool evaluate_branch() const; - uint32_t intrap(u32 vector, u32 pc, u32 cts = CTS_NO_CPU_TRAP, u32 mts = MTS_NO_MEMORY_TRAP); +protected: + virtual uint32_t intrap(u32 vector, u32 pc, u32 cts = CTS_NO_CPU_TRAP, u32 mts = MTS_NO_MEMORY_TRAP); }; class clipper_c100_device : public clipper_device @@ -275,6 +283,9 @@ class clipper_c400_device : public clipper_device { public: clipper_c400_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); + +protected: + virtual uint32_t intrap(u32 vector, u32 pc, u32 cts = CTS_NO_CPU_TRAP, u32 mts = MTS_NO_MEMORY_TRAP) override; }; DECLARE_DEVICE_TYPE(CLIPPER_C100, clipper_c100_device) diff --git a/src/mame/drivers/interpro.cpp b/src/mame/drivers/interpro.cpp index e3b8bd6c266..849d0a7d07e 100644 --- a/src/mame/drivers/interpro.cpp +++ b/src/mame/drivers/interpro.cpp @@ -415,7 +415,7 @@ static MACHINE_CONFIG_START(ip2800) MCFG_DEVICE_ADDRESS_MAP(0, interpro_main_map) MCFG_DEVICE_ADDRESS_MAP(1, interpro_io_map) MCFG_DEVICE_ADDRESS_MAP(2, interpro_boot_map) - MCFG_CAMMU_SSW_CB(DEVREAD32(INTERPRO_CPU_TAG, clipper_device, ssw)) + MCFG_CAMMU_SSW_CB(DEVREAD32(INTERPRO_CPU_TAG, clipper_device, get_ssw)) MCFG_RAM_ADD(RAM_TAG) MCFG_RAM_DEFAULT_SIZE("16M") |
