summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/unsp/unsp.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/unsp/unsp.cpp')
-rw-r--r--src/devices/cpu/unsp/unsp.cpp1086
1 files changed, 539 insertions, 547 deletions
diff --git a/src/devices/cpu/unsp/unsp.cpp b/src/devices/cpu/unsp/unsp.cpp
index c8a4025f5cd..8d141637ecc 100644
--- a/src/devices/cpu/unsp/unsp.cpp
+++ b/src/devices/cpu/unsp/unsp.cpp
@@ -20,7 +20,16 @@ DEFINE_DEVICE_TYPE(UNSP, unsp_device, "unsp", "SunPlus u'nSP")
unsp_device::unsp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: cpu_device(mconfig, UNSP, tag, owner, clock)
, m_program_config("program", ENDIANNESS_BIG, 16, 23, -1)
- , m_irq(0), m_fiq(0), m_curirq(0), m_sirq(0), m_sb(0), m_saved_sb(0), m_program(nullptr), m_icount(0), m_debugger_temp(0)
+ , m_enable_irq(false)
+ , m_enable_fiq(false)
+ , m_irq(false)
+ , m_fiq(false)
+ , m_curirq(0)
+ , m_sirq(0)
+ , m_sb(0)
+ , m_program(nullptr)
+ , m_icount(0)
+ , m_debugger_temp(0)
{
}
@@ -57,54 +66,6 @@ std::unique_ptr<util::disasm_interface> unsp_device::create_disassembler()
#define UNSP_S 0x0080
#define UNSP_C 0x0040
-#define STANDARD_ALU_CASES \
- case 0: \
- lres = r0 + r1; \
- unsp_update_nzsc(lres, r0, r1); \
- break; \
- case 1: \
- lres = r0 + r1; \
- if(UNSP_REG(SR) & UNSP_C) lres++; \
- unsp_update_nzsc(lres, r0, r1); \
- break; \
- case 3: \
- lres = r0 + (~r1 & 0x0000ffff); \
- if(UNSP_REG(SR) & UNSP_C) lres++; \
- unsp_update_nzsc(lres, r0, r1); \
- break; \
- case 2: \
- case 4: \
- lres = r0 + (~r1 & 0x0000ffff) + 1; \
- unsp_update_nzsc(lres, r0, r1); \
- break; \
- case 6: \
- lres = -r1; \
- unsp_update_nz(lres); \
- break; \
- case 8: \
- lres = r0 ^ r1; \
- unsp_update_nz(lres); \
- break; \
- case 9: \
- lres = r1; \
- unsp_update_nz(lres); \
- break; \
- case 10: \
- lres = r0 | r1; \
- unsp_update_nz(lres); \
- break; \
- case 11: \
- case 12: \
- lres = r0 & r1; \
- unsp_update_nz(lres); \
- break
-
-#define WRITEBACK_OPA \
- if(OP0 != 4 && OP0 < 12) \
- { \
- UNSP_REG_I(OPA) = (uint16_t)lres; \
- }
-
/*****************************************************************************/
void unsp_device::unimplemented_opcode(uint16_t op)
@@ -114,12 +75,12 @@ void unsp_device::unimplemented_opcode(uint16_t op)
/*****************************************************************************/
-uint16_t unsp_device::READ16(uint32_t address)
+uint16_t unsp_device::read16(uint32_t address)
{
return m_program->read_word(address);
}
-void unsp_device::WRITE16(uint32_t address, uint16_t data)
+void unsp_device::write16(uint32_t address, uint16_t data)
{
m_program->write_word(address, data);
}
@@ -129,27 +90,31 @@ void unsp_device::WRITE16(uint32_t address, uint16_t data)
void unsp_device::device_start()
{
memset(m_r, 0, sizeof(uint16_t) * 16);
- m_irq = 0;
- m_fiq = 0;
+ m_enable_irq = false;
+ m_enable_fiq = false;
+ m_irq = false;
+ m_fiq = false;
m_curirq = 0;
m_sirq = 0;
m_sb = 0;
- m_saved_sb = 0;
+ memset(m_saved_sb, 0, sizeof(uint8_t) * 3);
m_debugger_temp = 0;
m_program = &space(AS_PROGRAM);
- state_add( UNSP_SP, "SP", UNSP_REG(SP)).formatstr("%04X");
- state_add( UNSP_R1, "R1", UNSP_REG(R1)).formatstr("%04X");
- state_add( UNSP_R2, "R2", UNSP_REG(R2)).formatstr("%04X");
- state_add( UNSP_R3, "R3", UNSP_REG(R3)).formatstr("%04X");
- state_add( UNSP_R4, "R4", UNSP_REG(R4)).formatstr("%04X");
- state_add( UNSP_BP, "BP", UNSP_REG(BP)).formatstr("%04X");
- state_add( UNSP_SR, "SR", UNSP_REG(SR)).formatstr("%04X");
- state_add( UNSP_PC, "PC", m_debugger_temp).callimport().callexport().formatstr("%06X");
- state_add( UNSP_IRQ, "IRQ", m_irq).formatstr("%1u");
- state_add( UNSP_FIQ, "FIQ", m_fiq).formatstr("%1u");
- state_add( UNSP_SB, "SB", m_sb).formatstr("%1u");
+ state_add( UNSP_SP, "SP", UNSP_REG(SP)).formatstr("%04X");
+ state_add( UNSP_R1, "R1", UNSP_REG(R1)).formatstr("%04X");
+ state_add( UNSP_R2, "R2", UNSP_REG(R2)).formatstr("%04X");
+ state_add( UNSP_R3, "R3", UNSP_REG(R3)).formatstr("%04X");
+ state_add( UNSP_R4, "R4", UNSP_REG(R4)).formatstr("%04X");
+ state_add( UNSP_BP, "BP", UNSP_REG(BP)).formatstr("%04X");
+ state_add( UNSP_SR, "SR", UNSP_REG(SR)).formatstr("%04X");
+ state_add( UNSP_PC, "PC", m_debugger_temp).callimport().callexport().formatstr("%06X");
+ state_add( UNSP_IRQ_EN, "IRQE", m_enable_irq).formatstr("%1u");
+ state_add( UNSP_FIQ_EN, "FIQE", m_enable_fiq).formatstr("%1u");
+ state_add( UNSP_IRQ, "IRQ", m_irq).formatstr("%1u");
+ state_add( UNSP_FIQ, "FIQ", m_fiq).formatstr("%1u");
+ state_add( UNSP_SB, "SB", m_sb).formatstr("%1u");
state_add(STATE_GENPC, "GENPC", m_debugger_temp).callexport().noshow();
state_add(STATE_GENPCBASE, "CURPC", m_debugger_temp).callexport().noshow();
@@ -184,14 +149,16 @@ void unsp_device::device_reset()
{
memset(m_r, 0, sizeof(uint16_t) * 16);
- UNSP_REG(PC) = READ16(0xfff7);
- m_irq = 0;
- m_fiq = 0;
+ UNSP_REG(PC) = read16(0xfff7);
+ m_enable_irq = false;
+ m_enable_fiq = false;
+ m_irq = false;
+ m_fiq = false;
}
/*****************************************************************************/
-void unsp_device::unsp_update_nz(uint32_t value)
+void unsp_device::update_nz(uint32_t value)
{
UNSP_REG(SR) &= ~(UNSP_N | UNSP_Z);
if(value & 0x8000)
@@ -204,10 +171,9 @@ void unsp_device::unsp_update_nz(uint32_t value)
}
}
-void unsp_device::unsp_update_nzsc(uint32_t value, uint16_t r0, uint16_t r1)
+void unsp_device::update_sc(uint32_t value, uint16_t r0, uint16_t r1)
{
UNSP_REG(SR) &= ~(UNSP_C | UNSP_S);
- unsp_update_nz(value);
if(value != (uint16_t)value)
{
UNSP_REG(SR) |= UNSP_C;
@@ -219,30 +185,91 @@ void unsp_device::unsp_update_nzsc(uint32_t value, uint16_t r0, uint16_t r1)
}
}
-void unsp_device::unsp_push(uint16_t value, uint16_t *reg)
+void unsp_device::push(uint16_t value, uint16_t *reg)
+{
+ write16((*reg)--, value);
+}
+
+uint16_t unsp_device::pop(uint16_t *reg)
{
- WRITE16((*reg)--, value);
+ return read16(++(*reg));
+}
+
+void unsp_device::trigger_fiq()
+{
+ if (!m_enable_fiq || m_fiq)
+ return;
+
+ m_fiq = true;
+
+ m_saved_sb[m_irq ? 1 : 0] = m_sb;
+ m_sb = m_saved_sb[2];
+
+ push(UNSP_REG(PC), &UNSP_REG(SP));
+ push(UNSP_REG(SR), &UNSP_REG(SP));
+ UNSP_REG(PC) = read16(0xfff6);
+ UNSP_REG(SR) = 0;
+}
+
+void unsp_device::trigger_irq(int line)
+{
+ if (!m_enable_irq || m_irq)
+ return;
+
+ m_irq = true;
+
+ m_saved_sb[0] = m_sb;
+ m_sb = m_saved_sb[1];
+
+ push(UNSP_REG(PC), &UNSP_REG(SP));
+ push(UNSP_REG(SR), &UNSP_REG(SP));
+ UNSP_REG(PC) = read16(0xfff8 + line);
+ UNSP_REG(SR) = 0;
}
-uint16_t unsp_device::unsp_pop(uint16_t *reg)
+void unsp_device::check_irqs()
{
- return READ16(++(*reg));
+ int highest_irq = -1;
+ for (int i = 0; i <= 8; i++)
+ {
+ if (BIT(m_sirq, i))
+ {
+ highest_irq = i;
+ break;
+ }
+ }
+
+ if (highest_irq < 0)
+ return;
+
+ if (highest_irq == UNSP_FIQ_LINE)
+ {
+ trigger_fiq();
+ }
+ else
+ {
+ trigger_irq(highest_irq);
+ }
}
void unsp_device::execute_run()
{
- uint32_t op;
- uint32_t lres;
- uint16_t r0, r1;
- lres = 0;
+ uint32_t lres = 0;
+ uint16_t r0 = 0;
+ uint16_t r1 = 0;
+ uint32_t r2 = 0;
while (m_icount > 0)
{
+ check_irqs();
+
debugger_instruction_hook(UNSP_LPC);
- op = READ16(UNSP_LPC);
+ const uint32_t op = read16(UNSP_LPC);
UNSP_REG(PC)++;
+ const uint8_t lower_op = (OP1 << 4) | OP0;
+
if(OP0 < 0xf && OPA == 0x7 && OP1 < 2)
{
switch(OP0)
@@ -250,560 +277,557 @@ void unsp_device::execute_run()
case 0: // JB
if(!(UNSP_REG(SR) & UNSP_C))
{
+ m_icount -= 4;
UNSP_REG(PC) += (OP1 == 0) ? OPIMM : (0 - OPIMM);
}
- break;
+ else
+ m_icount -= 2;
+ continue;
case 1: // JAE
if(UNSP_REG(SR) & UNSP_C)
{
+ m_icount -= 4;
UNSP_REG(PC) += (OP1 == 0) ? OPIMM : (0 - OPIMM);
}
- break;
+ else
+ m_icount -= 2;
+ continue;
case 2: // JGE
if(!(UNSP_REG(SR) & UNSP_S))
{
+ m_icount -= 4;
UNSP_REG(PC) += (OP1 == 0) ? OPIMM : (0 - OPIMM);
}
- break;
+ else
+ m_icount -= 2;
+ continue;
case 3: // JL
if(UNSP_REG(SR) & UNSP_S)
{
+ m_icount -= 4;
UNSP_REG(PC) += (OP1 == 0) ? OPIMM : (0 - OPIMM);
}
- break;
+ else
+ m_icount -= 2;
+ continue;
case 4: // JNE
if(!(UNSP_REG(SR) & UNSP_Z))
{
+ m_icount -= 4;
UNSP_REG(PC) += (OP1 == 0) ? OPIMM : (0 - OPIMM);
}
- break;
+ else
+ m_icount -= 2;
+ continue;
case 5: // JE
if(UNSP_REG(SR) & UNSP_Z)
{
+ m_icount -= 4;
UNSP_REG(PC) += (OP1 == 0) ? OPIMM : (0 - OPIMM);
}
- break;
+ else
+ m_icount -= 2;
+ continue;
case 6: // JPL
if(!(UNSP_REG(SR) & UNSP_N))
{
+ m_icount -= 4;
UNSP_REG(PC) += (OP1 == 0) ? OPIMM : (0 - OPIMM);
}
- break;
+ else
+ m_icount -= 2;
+ continue;
case 7: // JMI
if(UNSP_REG(SR) & UNSP_N)
{
+ m_icount -= 4;
UNSP_REG(PC) += (OP1 == 0) ? OPIMM : (0 - OPIMM);
}
- break;
+ else
+ m_icount -= 2;
+ continue;
case 8: // JBE
if((UNSP_REG(SR) & (UNSP_Z | UNSP_C)) != UNSP_C)
{
+ m_icount -= 4;
UNSP_REG(PC) += (OP1 == 0) ? OPIMM : (0 - OPIMM);
}
- break;
+ else
+ m_icount -= 2;
+ continue;
case 9: // JA
if((UNSP_REG(SR) & (UNSP_Z | UNSP_C)) == UNSP_C)
{
+ m_icount -= 4;
UNSP_REG(PC) += (OP1 == 0) ? OPIMM : (0 - OPIMM);
}
- break;
+ else
+ m_icount -= 2;
+ continue;
case 10: // JLE
if(UNSP_REG(SR) & (UNSP_Z | UNSP_S))
{
+ m_icount -= 4;
UNSP_REG(PC) += (OP1 == 0) ? OPIMM : (0 - OPIMM);
}
- break;
+ else
+ m_icount -= 2;
+ continue;
case 11: // JG
if(!(UNSP_REG(SR) & (UNSP_Z | UNSP_S)))
{
+ m_icount -= 4;
UNSP_REG(PC) += (OP1 == 0) ? OPIMM : (0 - OPIMM);
}
- break;
+ else
+ m_icount -= 2;
+ continue;
case 14: // JMP
UNSP_REG(PC) += (OP1 == 0) ? OPIMM : (0 - OPIMM);
- break;
+ m_icount -= 4;
+ continue;
+ default:
+ unimplemented_opcode(op);
+ continue;
}
}
- else
+ else if (lower_op == 0x2d) // Push
{
- switch((OP1 << 4) | OP0)
+ r0 = OPN;
+ r1 = OPA;
+ m_icount -= 4 + 2 * r0;
+
+ while (r0--)
{
- // r, [bp+imm6]
- case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x06: case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d:
- r0 = UNSP_REG_I(OPA);
- r1 = READ16(UNSP_REG(BP) + OPIMM);
- switch(OP0)
+ push(UNSP_REG_I(r1--), &UNSP_REG_I(OPB));
+ }
+ continue;
+ }
+ else if (lower_op == 0x29) // Pop
+ {
+ if (op == 0x9a98) // reti
+ {
+ m_icount -= 8;
+ UNSP_REG(SR) = pop(&UNSP_REG(SP));
+ UNSP_REG(PC) = pop(&UNSP_REG(SP));
+
+ if(m_fiq)
+ {
+ m_fiq = false;
+ m_saved_sb[2] = m_sb;
+ m_sb = m_saved_sb[m_irq ? 1 : 0];
+ }
+ else if(m_irq)
+ {
+ m_irq = false;
+ m_saved_sb[1] = m_sb;
+ m_sb = m_saved_sb[0];
+ }
+
+ check_irqs();
+ continue;
+ }
+ else
+ {
+ r0 = OPN;
+ r1 = OPA;
+ m_icount -= 4 + 2 * r0;
+
+ while (r0--)
+ {
+ UNSP_REG_I(++r1) = pop(&UNSP_REG_I(OPB));
+ }
+ continue;
+ }
+ }
+ else if (OP0 == 0xf)
+ {
+ switch (OP1)
+ {
+ case 0x00: // Multiply, Unsigned * Signed
+ if(OPN == 1 && OPA != 7)
{
- STANDARD_ALU_CASES;
- case 13: // store r, [bp+imm6]
- WRITE16(UNSP_REG(BP) + OPIMM, UNSP_REG_I(OPA));
- break;
- default:
- unimplemented_opcode(op);
- break;
+ m_icount -= 12;
+ lres = UNSP_REG_I(OPA) * UNSP_REG_I(OPB);
+ if(UNSP_REG_I(OPB) & 0x8000)
+ {
+ lres -= UNSP_REG_I(OPA) << 16;
+ }
+ UNSP_REG(R4) = lres >> 16;
+ UNSP_REG(R3) = (uint16_t)lres;
}
- WRITEBACK_OPA;
- break;
-
- // r, imm6
- case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x16: case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c:
- r0 = UNSP_REG_I(OPA);
- r1 = OPIMM;
- switch(OP0)
+ else
{
- STANDARD_ALU_CASES;
- default:
- unimplemented_opcode(op);
- break;
+ unimplemented_opcode(op);
}
- WRITEBACK_OPA;
- break;
+ continue;
- // Pop / Interrupt return
- case 0x29:
- if(op == 0x9a90) // retf
+ case 0x01: // Call
+ if(!(OPA & 1))
{
- UNSP_REG(SR) = unsp_pop(&UNSP_REG(SP));
- UNSP_REG(PC) = unsp_pop(&UNSP_REG(SP));
- break;
+ m_icount -= 9;
+ r1 = read16(UNSP_LPC);
+ UNSP_REG(PC)++;
+ push(UNSP_REG(PC), &UNSP_REG(SP));
+ push(UNSP_REG(SR), &UNSP_REG(SP));
+ UNSP_REG(PC) = r1;
+ UNSP_REG(SR) &= 0xffc0;
+ UNSP_REG(SR) |= OPIMM;
}
- else if(op == 0x9a98) // reti
+ else
{
- int i;
- UNSP_REG(SR) = unsp_pop(&UNSP_REG(SP));
- UNSP_REG(PC) = unsp_pop(&UNSP_REG(SP));
- if(m_fiq & 2)
- {
- m_fiq &= 1;
- }
- else if(m_irq & 2)
- {
- m_irq &= 1;
- }
- m_sirq &= ~(1 << m_curirq);
- for(i = 0; i < 9; i++)
+ unimplemented_opcode(op);
+ }
+ continue;
+
+ case 0x02: // Far Jump
+ if (OPA == 7)
+ {
+ m_icount -= 5;
+ UNSP_REG(PC) = read16(UNSP_LPC);
+ UNSP_REG(PC)++;
+ UNSP_REG(SR) &= 0xffc0;
+ UNSP_REG(SR) |= OPIMM;
+ }
+ else
+ {
+ unimplemented_opcode(op);
+ }
+ continue;
+
+ case 0x04: // Multiply, Signed * Signed
+ if(OPN == 1 && OPA != 7)
+ {
+ m_icount -= 12;
+ lres = UNSP_REG_I(OPA) * UNSP_REG_I(OPB);
+ if(UNSP_REG_I(OPB) & 0x8000)
{
- if((m_sirq & (1 << i)) != 0 && i != m_curirq)
- {
- m_sirq &= ~(1 << i);
- m_curirq = 0;
- execute_set_input(UNSP_IRQ0_LINE + i, 1);
- i = -1;
- break;
- }
+ lres -= UNSP_REG_I(OPA) << 16;
}
- if(i != -1)
+ if(UNSP_REG_I(OPA) & 0x8000)
{
- m_curirq = 0;
+ lres -= UNSP_REG_I(OPB) << 16;
}
- break;
+ UNSP_REG(R4) = lres >> 16;
+ UNSP_REG(R3) = (uint16_t)lres;
}
else
{
- r0 = OPN;
- r1 = OPA;
- while(r0--)
- {
- UNSP_REG_I(++r1) = unsp_pop(&UNSP_REG_I(OPB));
- }
+ unimplemented_opcode(op);
}
- break;
+ continue;
- // Push
- case 0x2d:
- r0 = OPN;
- r1 = OPA;
- while(r0--)
+ case 0x05: // Interrupt flags
+ m_icount -= 2;
+ switch(OPIMM)
{
- unsp_push(UNSP_REG_I(r1--), &UNSP_REG_I(OPB));
+ case 0:
+ m_enable_irq = false;
+ m_enable_fiq = false;
+ break;
+ case 1:
+ m_enable_irq = true;
+ m_enable_fiq = false;
+ break;
+ case 2:
+ m_enable_irq = false;
+ m_enable_fiq = true;
+ break;
+ case 3:
+ m_enable_irq = true;
+ m_enable_fiq = true;
+ break;
+ case 8: // irq off
+ m_enable_irq = false;
+ break;
+ case 9: // irq on
+ m_enable_irq = true;
+ break;
+ case 12: // fiq off
+ m_enable_fiq = false;
+ break;
+ case 14: // fiq on
+ m_enable_fiq = true;
+ break;
+ case 37: // nop
+ break;
+ default:
+ unimplemented_opcode(op);
+ break;
}
- break;
+ continue;
+
+ default:
+ unimplemented_opcode(op);
+ continue;
+ }
+ }
+
+ // At this point, we should be dealing solely with ALU ops.
- // ALU, Indirect
- case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x36: case 0x38: case 0x39: case 0x3a: case 0x3b: case 0x3c: case 0x3d:
- switch(OPN & 3)
+ r0 = UNSP_REG_I(OPA);
+
+ switch (OP1)
+ {
+ case 0x00: // r, [bp+imm6]
+ m_icount -= 6;
+
+ r2 = UNSP_REG(BP) + OPIMM;
+ if (OP0 != 0x0d)
+ r1 = read16(r2);
+ break;
+
+ case 0x01: // r, imm6
+ m_icount -= 2;
+
+ r1 = OPIMM;
+ break;
+
+ case 0x03: // Indirect
+ {
+ m_icount -= 6;
+ if (OPA == 7)
+ m_icount -= 1;
+
+ const uint8_t lsbits = OPN & 3;
+ const uint8_t opb = OPB;
+ if (OPN & 4)
+ {
+ switch (lsbits)
{
case 0: // r, [r]
- r0 = UNSP_REG_I(OPA);
- r1 = READ16((OPN & 4) ? UNSP_LREG_I(OPB) : UNSP_REG_I(OPB));
- switch(OP0)
- {
- STANDARD_ALU_CASES;
- case 13: // store r, [r]
- WRITE16((OPN & 4) ? UNSP_LREG_I(OPB) : UNSP_REG_I(OPB), UNSP_REG_I(OPA));
- break;
- default:
- unimplemented_opcode(op);
- break;
- }
- WRITEBACK_OPA;
+ r2 = UNSP_LREG_I(opb);
+ if (OP0 != 0x0d)
+ r1 = read16(r2);
break;
case 1: // r, [<ds:>r--]
- r0 = UNSP_REG_I(OPA);
- r1 = READ16((OPN & 4) ? UNSP_LREG_I(OPB) : UNSP_REG_I(OPB));
- switch(OP0)
- {
- STANDARD_ALU_CASES;
- case 13: // store r, [<ds:>r--]
- WRITE16((OPN & 4) ? UNSP_LREG_I(OPB) : UNSP_REG_I(OPB), UNSP_REG_I(OPA));
- break;
- default:
- unimplemented_opcode(op);
- break;
- }
- UNSP_REG_I(OPB)--;
- WRITEBACK_OPA;
+ r2 = UNSP_LREG_I(opb);
+ if (OP0 != 0x0d)
+ r1 = read16(r2);
+ UNSP_REG_I(opb)--;
break;
case 2: // r, [<ds:>r++]
- r0 = UNSP_REG_I(OPA);
- r1 = READ16((OPN & 4) ? UNSP_LREG_I(OPB) : UNSP_REG_I(OPB));
- switch(OP0)
- {
- STANDARD_ALU_CASES;
- case 13: // store r, [<ds:>r++]
- WRITE16((OPN & 4) ? UNSP_LREG_I(OPB) : UNSP_REG_I(OPB), UNSP_REG_I(OPA));
- break;
- default:
- unimplemented_opcode(op);
- break;
- }
- UNSP_REG_I(OPB)++;
- WRITEBACK_OPA;
+ r2 = UNSP_LREG_I(opb);
+ if (OP0 != 0x0d)
+ r1 = read16(r2);
+ UNSP_REG_I(opb)++;
break;
case 3: // r, [<ds:>++r]
- UNSP_REG_I(OPB)++;
- r0 = UNSP_REG_I(OPA);
- r1 = READ16((OPN & 4) ? UNSP_LREG_I(OPB) : UNSP_REG_I(OPB));
- switch(OP0)
- {
- STANDARD_ALU_CASES;
- default:
- unimplemented_opcode(op);
- break;
- }
- WRITEBACK_OPA;
+ UNSP_REG_I(opb)++;
+ r2 = UNSP_LREG_I(opb);
+ if (OP0 != 0x0d)
+ r1 = read16(r2);
+ break;
+ default:
break;
}
- break;
-
- // ALU, 16-bit ops
- case 0x40: case 0x41: case 0x42: case 0x43: case 0x44: case 0x46: case 0x48: case 0x49: case 0x4a: case 0x4b: case 0x4c:
- switch(OPN)
+ }
+ else
+ {
+ switch (lsbits)
{
- // r, r
- case 0:
- r0 = UNSP_REG_I(OPA);
- r1 = UNSP_REG_I(OPB);
- switch(OP0)
- {
- STANDARD_ALU_CASES;
- default:
- unimplemented_opcode(op);
- break;
- }
- WRITEBACK_OPA;
+ case 0: // r, [r]
+ r2 = UNSP_REG_I(opb);
+ if (OP0 != 0x0d)
+ r1 = read16(r2);
break;
-
- // ALU, 16-bit Immediate
- case 1: // r, r, imm16
- if(!((OP0 == 4 || OP0 == 6 || OP0 == 9 || OP0 == 12) && OPA != OPB))
- {
- r0 = UNSP_REG_I(OPB);
- r1 = READ16(UNSP_LPC);
- UNSP_REG(PC)++;
- switch(OP0)
- {
- STANDARD_ALU_CASES;
- default:
- unimplemented_opcode(op);
- break;
- }
- WRITEBACK_OPA;
- }
- else
- {
- unimplemented_opcode(op);
- }
+ case 1: // r, [<ds:>r--]
+ r2 = UNSP_REG_I(opb);
+ if (OP0 != 0x0d)
+ r1 = read16(r2);
+ UNSP_REG_I(opb)--;
break;
-
- // ALU, Direct 16
- case 2: // r, [imm16]
- r0 = UNSP_REG_I(OPB);
- r1 = READ16(READ16(UNSP_LPC));
- UNSP_REG(PC)++;
- switch(OP0)
- {
- STANDARD_ALU_CASES;
- default:
- unimplemented_opcode(op);
- break;
- }
- WRITEBACK_OPA;
+ case 2: // r, [<ds:>r++]
+ r2 = UNSP_REG_I(opb);
+ if (OP0 != 0x0d)
+ r1 = read16(r2);
+ UNSP_REG_I(opb)++;
break;
-
- // ALU, Direct 16
- case 3: // [imm16], r
- r0 = UNSP_REG_I(OPB);
- r1 = UNSP_REG_I(OPA);
- switch(OP0)
- {
- STANDARD_ALU_CASES;
- default:
- unimplemented_opcode(op);
- break;
- }
- if(OP0 != 4 && OP0 < 12)
- {
- WRITE16(READ16(UNSP_LPC), (uint16_t)lres);
- }
- UNSP_REG(PC)++;
+ case 3: // r, [<ds:>++r]
+ UNSP_REG_I(opb)++;
+ r2 = UNSP_REG_I(opb);
+ if (OP0 != 0x0d)
+ r1 = read16(r2);
break;
-
- // ALU, Shifted
default:
- {
- uint32_t shift = (UNSP_REG_I(OPB) << 4) | m_sb;
- if(shift & 0x80000)
- {
- shift |= 0xf00000;
- }
- shift >>= (OPN - 3);
- m_sb = shift & 0x0f;
- r1 = (shift >> 4) & 0x0000ffff;
-
- switch(OP0)
- {
- case 9: // load r, r asr n
- unsp_update_nz(r1);
- UNSP_REG_I(OPA) = r1;
- break;
- default:
- unimplemented_opcode(op);
- break;
- }
break;
- }
- }
- break;
-
- case 0x4d:
- if(OPN == 3)
- {
- if(OPA == OPB)
- {
- WRITE16(READ16(UNSP_LPC), UNSP_REG_I(OPB));
- UNSP_REG(PC)++;
- }
- else
- {
- unimplemented_opcode(op);
- }
- }
- else
- {
- unimplemented_opcode(op);
}
- break;
+ }
+ break;
+ }
- // ALU, Shifted
- case 0x50: case 0x51: case 0x52: case 0x53: case 0x54: case 0x56: case 0x58: case 0x59: case 0x5a: case 0x5b: case 0x5c:
- if(OPN & 4)
- {
- switch(OP0)
- {
- case 9: // load r, r >> imm2
- lres = ((UNSP_REG_I(OPB) << 4) | m_sb) >> (OPN - 3);
- m_sb = lres & 0x0f;
- unsp_update_nz((uint16_t)(lres >> 4));
- UNSP_REG_I(OPA) = (uint16_t)(lres >> 4);
- break;
- default:
- unimplemented_opcode(op);
- break;
- }
- }
- else
- {
- uint32_t shift = ((m_sb << 16) | UNSP_REG_I(OPB)) << (OPN + 1);
- m_sb = (shift >> 16) & 0x0f;
- r0 = UNSP_REG_I(OPA);
- r1 = shift & 0x0000ffff;
+ case 0x04: // 16-bit ops
+ switch (OPN)
+ {
+ case 0x00: // r
+ m_icount -= 3;
+ if (OPA == 7)
+ m_icount -= 2;
- switch(OP0)
- {
- case 0: // add r, r << imm2
- lres = r0 + r1;
- unsp_update_nzsc(lres, r0, r1);
- UNSP_REG_I(OPA) = (uint16_t)lres;
- break;
- case 9: // load r, r << imm2
- lres = r1;
- unsp_update_nz(lres);
- UNSP_REG_I(OPA) = (uint16_t)lres;
- break;
- case 10: // or r, r << imm2
- lres = r0 | r1;
- unsp_update_nz(lres);
- UNSP_REG_I(OPA) = (uint16_t)lres;
- break;
- default:
- unimplemented_opcode(op);
- break;
- }
- }
- break;
+ r1 = UNSP_REG_I(OPB);
+ break;
- // ALU, Rotated
- case 0x60: case 0x61: case 0x62: case 0x63: case 0x64: case 0x66: case 0x68: case 0x69: case 0x6a: case 0x6b: case 0x6c:
- if(OPN & 4) // ROR
- {
- lres = ((((m_sb << 16) | UNSP_REG_I(OPB)) << 4) | m_sb) >> (OPN - 3);
- m_sb = lres & 0x0f;
- r1 = (uint16_t)(lres >> 4);
- }
- else
- {
- lres = ((((m_sb << 16) | UNSP_REG_I(OPB)) << 4) | m_sb) << (OPN + 1);
- m_sb = (lres >> 20) & 0x0f;
- r1 = (uint16_t)(lres >> 4);
- }
+ case 0x01: // imm16
+ m_icount -= 4;
+ if (OPA == 7)
+ m_icount -= 1;
- switch(OP0)
- {
- case 9: // load r, r ror imm2
- unsp_update_nz(r1);
- UNSP_REG_I(OPA) = r1;
- break;
- default:
- unimplemented_opcode(op);
- break;
- }
- break;
+ r0 = UNSP_REG_I(OPB);
+ r1 = read16(UNSP_LPC);
+ UNSP_REG(PC)++;
+ break;
- // ALU, Direct 8
- case 0x70: case 0x71: case 0x72: case 0x73: case 0x74: case 0x76: case 0x78: case 0x79: case 0x7a: case 0x7b: case 0x7c:
- //print("%s %s, [%02x]", alu[OP0], reg[OPA], OPIMM);
- unimplemented_opcode(op);
- break;
+ case 0x02: // [imm16]
+ m_icount -= 7;
+ if (OPA == 7)
+ m_icount -= 1;
- // Call
- case 0x1f:
- if(OPA == 0)
- {
- r1 = READ16(UNSP_LPC);
+ r0 = UNSP_REG_I(OPB);
+ r2 = read16(UNSP_LPC);
UNSP_REG(PC)++;
- unsp_push(UNSP_REG(PC), &UNSP_REG(SP));
- unsp_push(UNSP_REG(SR), &UNSP_REG(SP));
- UNSP_REG(PC) = r1;
- UNSP_REG(SR) &= 0xffc0;
- UNSP_REG(SR) |= OPIMM;
- }
- else
- {
- unimplemented_opcode(op);
- }
- break;
- // Far Jump
- case 0x2f: case 0x3f: case 0x6f: case 0x7f:
- if (OPA == 7 && OP1 == 2)
- {
- UNSP_REG(PC) = READ16(UNSP_LPC);
- UNSP_REG(SR) &= 0xffc0;
- UNSP_REG(SR) |= OPIMM;
- }
- break;
-
- // Multiply, Unsigned * Signed
- case 0x0f:
- if(OPN == 1 && OPA != 7)
- {
- lres = UNSP_REG_I(OPA) * UNSP_REG_I(OPB);
- if(UNSP_REG_I(OPB) & 0x8000)
+ if (OP0 != 0x0d)
{
- lres -= UNSP_REG_I(OPA) << 16;
+ r1 = read16(r2);
}
- UNSP_REG(R4) = lres >> 16;
- UNSP_REG(R3) = (uint16_t)lres;
break;
- }
- else
- {
- unimplemented_opcode(op);
- }
- break;
- // Multiply, Signed * Signed
- case 0x4f:
- if(OPN == 1 && OPA != 7)
- {
- lres = UNSP_REG_I(OPA) * UNSP_REG_I(OPB);
- if(UNSP_REG_I(OPB) & 0x8000)
- {
- lres -= UNSP_REG_I(OPA) << 16;
- }
- if(UNSP_REG_I(OPA) & 0x8000)
- {
- lres -= UNSP_REG_I(OPB) << 16;
- }
- UNSP_REG(R4) = lres >> 16;
- UNSP_REG(R3) = (uint16_t)lres;
+ case 0x03: // store [imm16], r
+ m_icount -= 7;
+ if (OPA == 7)
+ m_icount -= 1;
+
+ r1 = r0;
+ r0 = UNSP_REG_I(OPB);
+ r2 = read16(UNSP_LPC);
+ UNSP_REG(PC)++;
break;
- }
- else
- {
- unimplemented_opcode(op);
- }
- break;
- // Interrupt flags
- case 0x5f:
- if(OPA == 0)
- {
- switch(OPIMM)
- {
- case 0:
- m_irq &= ~1;
- m_fiq &= ~1;
- break;
- case 1:
- m_irq |= 1;
- m_fiq &= ~1;
- break;
- case 2:
- m_irq &= ~1;
- m_fiq |= 1;
- break;
- case 3:
- m_irq |= 1;
- m_fiq |= 1;
- break;
- case 8: // irq off
- m_irq &= ~1;
- break;
- case 9: // irq on
- m_irq |= 1;
- break;
- case 12: // fiq off
- m_fiq &= ~1;
- break;
- case 13: // fiq on
- m_fiq |= 1;
- break;
- case 37: // nop
- break;
- }
- }
- else
+ default: // Shifted ops
{
- unimplemented_opcode(op);
+ m_icount -= 3;
+ if (OPA == 7)
+ m_icount -= 2;
+
+ uint32_t shift = (UNSP_REG_I(OPB) << 4) | m_sb;
+ if (shift & 0x80000)
+ shift |= 0xf00000;
+ shift >>= (OPN - 3);
+ m_sb = shift & 0x0f;
+ r1 = (uint16_t)(shift >> 4);
+ break;
}
- break;
+ }
+ break;
+
+ case 0x05: // More shifted ops
+ m_icount -= 3;
+ if (OPA == 7)
+ m_icount -= 2;
+
+ if (OPN & 4) // Shift right
+ {
+ const uint32_t shift = ((UNSP_REG_I(OPB) << 4) | m_sb) >> (OPN - 3);
+ m_sb = shift & 0x0f;
+ r1 = (uint16_t)(shift >> 4);
+ }
+ else // Shift left
+ {
+ const uint32_t shift = ((m_sb << 16) | UNSP_REG_I(OPB)) << (OPN + 1);
+ m_sb = (shift >> 16) & 0x0f;
+ r1 = (uint16_t)shift;
+ }
+ break;
+
+ case 0x06: // Rotated ops
+ {
+ m_icount -= 3;
+ if (OPA == 7)
+ m_icount -= 2;
+
+ uint32_t shift = (((m_sb << 16) | UNSP_REG_I(OPB)) << 4) | m_sb;
+ if (OPN & 4) // Rotate right
+ {
+ shift >>= (OPN - 3);
+ m_sb = shift & 0x0f;
+ }
+ else
+ {
+ shift <<= (OPN + 1);
+ m_sb = (shift >> 20) & 0x0f;
+ }
+ r1 = (uint16_t)(shift >> 4);
+ break;
}
+
+ case 0x07: // Direct 8
+ m_icount -= 5;
+ if (OPA == 7)
+ m_icount -= 1;
+
+ r1 = read16(OPIMM);
+ break;
+
+ default:
+ break;
}
- m_icount -= 5;
- m_icount = std::max(m_icount, 0);
+ switch (OP0)
+ {
+ case 0x00: // Add
+ lres = r0 + r1;
+ break;
+ case 0x01: // Add w/ carry
+ lres = r0 + r1;
+ if(UNSP_REG(SR) & UNSP_C)
+ lres++;
+ break;
+ case 0x02: // Subtract
+ case 0x04: // Compare
+ lres = r0 + (uint16_t)(~r1) + 1;
+ break;
+ case 0x03: // Subtract w/ carry
+ lres = r0 + (uint16_t)(~r1);
+ if(UNSP_REG(SR) & UNSP_C)
+ lres++;
+ break;
+ case 0x06: // Negate
+ lres = -r1;
+ break;
+ case 0x08: // XOR
+ lres = r0 ^ r1;
+ break;
+ case 0x09: // Load
+ lres = r1;
+ break;
+ case 0x0a: // OR
+ lres = r0 | r1;
+ break;
+ case 0x0b: // AND
+ case 0x0c: // Test
+ lres = r0 & r1;
+ break;
+ case 0x0d: // Store
+ write16(r2, r0);
+ continue;
+ default:
+ unimplemented_opcode(op);
+ continue;
+ }
+
+ if (OP0 != 0x0d && OPA != 0x07) // If not a store opcode and not updating the PC, update negative/zero flags.
+ update_nz(lres);
+
+ if (OP0 < 0x05 && OPA != 0x07) // If Add, Add w/ Carry, Subtract, Subtract w/ Carry, Compare, and not updating the PC, update sign/carry flags.
+ update_sc(lres, r0, r1);
+
+ if (OP0 == 0x04 || OP0 == 0x0c) // Compare and Test don't write back results.
+ continue;
+
+ if (OP1 == 0x04 && OPN == 0x03) // store [imm16], r
+ write16(r2, lres);
+ else
+ UNSP_REG_I(OPA) = lres;
}
}
@@ -812,8 +836,6 @@ void unsp_device::execute_run()
void unsp_device::execute_set_input(int irqline, int state)
{
- uint16_t irq_vector = 0;
-
m_sirq &= ~(1 << irqline);
if(!state)
@@ -831,40 +853,10 @@ void unsp_device::execute_set_input(int irqline, int state)
case UNSP_IRQ5_LINE:
case UNSP_IRQ6_LINE:
case UNSP_IRQ7_LINE:
- if(m_fiq & 2)
- {
- // FIQ is being serviced, ignore this IRQ trigger.
- m_sirq |= state << irqline;
- return;
- }
- if(m_irq != 1)
- {
- // IRQ is disabled, ignore this IRQ trigger.
- m_sirq |= state << irqline;
- return;
- }
- m_irq |= 2;
- m_curirq |= (1 << irqline);
- irq_vector = 0xfff8 + (irqline - UNSP_IRQ0_LINE);
- break;
case UNSP_FIQ_LINE:
- if(m_fiq != 1)
- {
- // FIQ is disabled, ignore this FIQ trigger.
- m_sirq |= state << irqline;
- return;
- }
- m_fiq |= 2;
- m_curirq |= (1 << irqline);
- irq_vector = 0xfff6;
+ m_sirq |= (1 << irqline);
break;
case UNSP_BRK_LINE:
break;
}
-
- m_saved_sb = m_sb;
- unsp_push(UNSP_REG(PC), &UNSP_REG(SP));
- unsp_push(UNSP_REG(SR), &UNSP_REG(SP));
- UNSP_REG(PC) = READ16(irq_vector);
- UNSP_REG(SR) = 0;
}