summaryrefslogtreecommitdiffstatshomepage
path: root/src
diff options
context:
space:
mode:
author R. Belmont <rb6502@users.noreply.github.com>2017-09-05 14:42:59 -0400
committer GitHub <noreply@github.com>2017-09-05 14:42:59 -0400
commit6523a1566ebd28c4e01ab52af9744b7f9badc972 (patch)
treec95b896a55e4956b45f955f29d7be66e979f8885 /src
parent1908ac9eeec3d33b23743057beaac4f2213d0eb7 (diff)
parent8a692c36281c3f2050d2ccb45bea843ef0b3ee77 (diff)
Merge pull request #2633 from pmackinlay/clipper
clipper: interrupt handling fixes
Diffstat (limited to 'src')
-rw-r--r--src/devices/cpu/clipper/clipper.cpp114
-rw-r--r--src/devices/cpu/clipper/clipper.h23
-rw-r--r--src/mame/drivers/interpro.cpp2
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")