diff options
Diffstat (limited to 'src/devices/cpu/unsp/unsp_other.cpp')
-rw-r--r-- | src/devices/cpu/unsp/unsp_other.cpp | 69 |
1 files changed, 40 insertions, 29 deletions
diff --git a/src/devices/cpu/unsp/unsp_other.cpp b/src/devices/cpu/unsp/unsp_other.cpp index 9e9fb984cb4..efbf27d1278 100644 --- a/src/devices/cpu/unsp/unsp_other.cpp +++ b/src/devices/cpu/unsp/unsp_other.cpp @@ -5,8 +5,6 @@ #include "unsp.h" #include "unspfe.h" -#include "debugger.h" - #include "unspdasm.h" void unsp_device::execute_remaining(const uint16_t op) @@ -41,23 +39,22 @@ void unsp_device::execute_remaining(const uint16_t op) if (op == 0x9a98) // reti { m_core->m_icount -= 8; + if (m_core->m_ine) + { + set_fr(pop(&m_core->m_r[REG_SP])); + } + m_core->m_r[REG_SR] = pop(&m_core->m_r[REG_SP]); m_core->m_r[REG_PC] = pop(&m_core->m_r[REG_SP]); if (m_core->m_fiq) { m_core->m_fiq = 0; - m_core->m_saved_sb[2] = m_core->m_sb; - m_core->m_sb = m_core->m_saved_sb[m_core->m_irq ? 1 : 0]; } else if (m_core->m_irq) { m_core->m_irq = 0; - m_core->m_saved_sb[1] = m_core->m_sb; - m_core->m_sb = m_core->m_saved_sb[0]; } - m_core->m_curirq = 0; - check_irqs(); return; } else // pop @@ -204,6 +201,7 @@ void unsp_device::execute_remaining(const uint16_t op) r0 = m_core->m_r[opb]; r2 = read16(UNSP_LPC); add_lpc(1); + // additional special case 'if (op1 == 0x04 && opn == 0x03)' write logic below break; default: // Shifted ops @@ -256,7 +254,7 @@ void unsp_device::execute_remaining(const uint16_t op) break; } - case 0x07: // Direct 8 + case 0x07: // Direct 6 m_core->m_icount -= (opa == 7 ? 6 : 5); r2 = op & 0x3f; r1 = read16(r2); @@ -266,12 +264,26 @@ void unsp_device::execute_remaining(const uint16_t op) break; } + bool write = do_basic_alu_ops(op0, lres, r0, r1, r2, (opa != 7) ? true : false); + + if (write) + { + if (op1 == 0x04 && opn == 0x03) // store [imm16], r + write16(r2, lres); + else + m_core->m_r[opa] = (uint16_t)lres; + } +} + + +bool unsp_device::do_basic_alu_ops(const uint16_t &op0, uint32_t &lres, uint16_t &r0, uint16_t &r1, uint32_t &r2, bool update_flags) +{ switch (op0) { case 0x00: // Add { lres = r0 + r1; - if (opa != 7) + if (update_flags) update_nzsc(lres, r0, r1); break; } @@ -279,69 +291,68 @@ void unsp_device::execute_remaining(const uint16_t op) { uint32_t c = (m_core->m_r[REG_SR] & UNSP_C) ? 1 : 0; lres = r0 + r1 + c; - if (opa != 7) + if (update_flags) update_nzsc(lres, r0, r1); break; } case 0x02: // Subtract lres = r0 + (uint16_t)(~r1) + uint32_t(1); - if (opa != 7) + if (update_flags) update_nzsc(lres, r0, ~r1); break; case 0x03: // Subtract w/ carry { uint32_t c = (m_core->m_r[REG_SR] & UNSP_C) ? 1 : 0; lres = r0 + (uint16_t)(~r1) + c; - if (opa != 7) + if (update_flags) update_nzsc(lres, r0, ~r1); break; } case 0x04: // Compare lres = r0 + (uint16_t)(~r1) + uint32_t(1); - if (opa != 7) + if (update_flags) update_nzsc(lres, r0, ~r1); - return; + return false; case 0x06: // Negate lres = -r1; - if (opa != 7) + if (update_flags) update_nz(lres); break; case 0x08: // XOR lres = r0 ^ r1; - if (opa != 7) + if (update_flags) update_nz(lres); break; case 0x09: // Load lres = r1; - if (opa != 7) + if (update_flags) update_nz(lres); break; case 0x0a: // OR lres = r0 | r1; - if (opa != 7) + if (update_flags) update_nz(lres); break; case 0x0b: // AND lres = r0 & r1; - if (opa != 7) + if (update_flags) update_nz(lres); break; case 0x0c: // Test lres = r0 & r1; - if (opa != 7) + if (update_flags) update_nz(lres); - return; + return false; case 0x0d: // Store write16(r2, r0); - return; + return false; default: - unimplemented_opcode(op); - return; + // pcp87xx 'Elevator Action' explicitly jumps into the middle of an earlier opcode (off-by-one error in the code) + // It looks like the illegal op should have no meaningful effect so just log rather than fatalerroring + logerror("UNSP: illegal ALU optype %02x at %04x\n", op0, UNSP_LPC); + return false; } - if (op1 == 0x04 && opn == 0x03) // store [imm16], r - write16(r2, lres); - else - m_core->m_r[opa] = (uint16_t)lres; + return true; } |