summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author mooglyguy <therealmogminer@gmail.com>2018-10-21 21:11:09 +0200
committer mooglyguy <therealmogminer@gmail.com>2018-10-21 21:29:13 +0200
commitaf515310d71f7f8529c3d52c1380e732d27492ca (patch)
treea067064c2a3867c05289e520f7804f204fa286a4
parent5e85036f34456506b03b98d5cdbf5afcb6a14302 (diff)
vsmile: Fixed erroneous cartridge ROM mirroring. Gets V.Smile games to boot. Needs cleanup. [Ryan Holtz]
-rw-r--r--src/devices/cpu/unsp/unsp.cpp1311
-rw-r--r--src/devices/cpu/unsp/unsp.h34
-rw-r--r--src/devices/cpu/unsp/unspdasm.cpp550
-rw-r--r--src/devices/cpu/unsp/unspdasm.h18
-rw-r--r--src/devices/machine/spg2xx.cpp107
-rw-r--r--src/devices/machine/spg2xx.h13
-rw-r--r--src/mame/drivers/vii.cpp80
7 files changed, 1287 insertions, 826 deletions
diff --git a/src/devices/cpu/unsp/unsp.cpp b/src/devices/cpu/unsp/unsp.cpp
index ca8b149fe5d..48e48ae16b0 100644
--- a/src/devices/cpu/unsp/unsp.cpp
+++ b/src/devices/cpu/unsp/unsp.cpp
@@ -1,10 +1,14 @@
-// license:BSD-3-Clause
-// copyright-holders:Ryan Holtz
+// license:GPL-2.0+
+// copyright-holders:Segher Boessenkool,Ryan Holtz
/*****************************************************************************
- SunPlus micro'nSP core
+ SunPlus micro'nSP emulator
- based primarily on Unununium, by segher
+ Copyright 2008-2017 Segher Boessenkool <segher@kernel.crashing.org>
+ Licensed under the terms of the GNU GPL, version 2
+ http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
+
+ Ported to MAME framework by Ryan Holtz
*****************************************************************************/
@@ -173,6 +177,20 @@ void unsp_device::state_import(const device_state_entry &entry)
}
}
+static struct unsp_timer timer_tmb1 = {
+ .time = 0,
+ .interval = 27000000/8,
+ .index = 0,
+ .next = nullptr
+};
+
+static struct unsp_timer timer_tmb2 = {
+ .time = 0,
+ .interval = 27000000/128,
+ .index = 1,
+ .next = nullptr
+};
+
void unsp_device::device_reset()
{
memset(m_r, 0, sizeof(uint16_t) * 16);
@@ -182,6 +200,10 @@ void unsp_device::device_reset()
m_enable_fiq = false;
m_irq = false;
m_fiq = false;
+
+ timers = nullptr;
+ timer_add(&timer_tmb1);
+ timer_add(&timer_tmb2);
}
/*****************************************************************************/
@@ -260,20 +282,60 @@ void unsp_device::trigger_irq(int line)
UNSP_REG(SR) = 0;
}
+int unsp_device::get_irq()
+{
+ if (!m_enable_irq || m_irq)
+ return -1;
+
+ // video
+ if (read16(0x2862) & read16(0x2863))
+ return UNSP_IRQ0_LINE;
+
+ const uint16_t enable = read16(0x3d21);
+ const uint16_t status = read16(0x3d22);
+
+ // timerA, timerB
+ if (enable & status & 0x0c00)
+ return UNSP_IRQ2_LINE;
+
+ // UART, ADC XXX: also SPI
+ if (enable & status & 0x2100)
+ return UNSP_IRQ3_LINE;
+
+ // XXX audio, IRQ4
+
+ // extint1, extint2
+ if (enable & status & 0x1200)
+ return UNSP_IRQ5_LINE;
+
+ // 1024Hz, 2048HZ, 4096HZ
+ if (enable & status & 0x0070)
+ return UNSP_IRQ6_LINE;
+
+ // TMB1, TMB2, 4Hz, key change
+ if (enable & status & 0x008b)
+ return UNSP_IRQ7_LINE;
+
+ return -1;
+}
+
void unsp_device::check_irqs()
{
- if (!m_sirq)
- return;
+ //if (!m_sirq)
+ //return;
- int highest_irq = -1;
- for (int i = 0; i <= 8; i++)
+ int highest_irq = get_irq();
+ /*if (highest_irq == -1)
{
- if (BIT(m_sirq, i))
+ for (int i = 0; i <= 8; i++)
{
- highest_irq = i;
- break;
+ if (BIT(m_sirq, i))
+ {
+ highest_irq = i;
+ break;
+ }
}
- }
+ }*/
if (highest_irq < 0)
return;
@@ -285,606 +347,761 @@ void unsp_device::check_irqs()
}
else
{
- //logerror("Trying to trigger IRQ\n");
+ //printf("Trying to trigger IRQ%d\n", highest_irq - 1);
trigger_irq(highest_irq - 1);
}
}
-void unsp_device::execute_run()
+void unsp_device::add_lpc(const int32_t offset)
{
-#if UNSP_LOG_OPCODES
- unsp_disassembler dasm;
-#endif
+ const uint32_t new_lpc = UNSP_LPC + offset;
+ UNSP_REG(PC) = (uint16_t)new_lpc;
+ UNSP_REG(SR) &= 0xffc0;
+ UNSP_REG(SR) |= (new_lpc >> 16) & 0x3f;
+}
+static const int32_t cycles_per_line = 1728;
+static uint32_t cycle_count = 0;
+static int32_t lines_per_frame = 312;
+static int32_t line_count = 0;
+
+inline void unsp_device::execute_one(const uint16_t op)
+{
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);
- const uint32_t op = read16(UNSP_LPC);
+ const uint8_t lower_op = (OP1 << 4) | OP0;
-#if UNSP_LOG_OPCODES
- if (m_log_ops)
+ if(OP0 < 0xf && OPA == 0x7 && OP1 < 2)
+ {
+ switch(OP0)
{
- std::stringstream strbuffer;
- dasm.disassemble(strbuffer, UNSP_LPC, op, read16(UNSP_LPC+1));
- logerror("%06x: %s\n", UNSP_LPC, strbuffer.str().c_str());
+ case 0: // JB
+ if(!(UNSP_REG(SR) & UNSP_C))
+ {
+ m_icount -= 4;
+ cycle_count += 4;
+ add_lpc((OP1 == 0) ? OPIMM : (0 - OPIMM));
+ }
+ else
+ {
+ m_icount -= 2;
+ cycle_count += 2;
+ }
+ return;
+ case 1: // JAE
+ if(UNSP_REG(SR) & UNSP_C)
+ {
+ m_icount -= 4;
+ cycle_count += 4;
+ add_lpc((OP1 == 0) ? OPIMM : (0 - OPIMM));
+ }
+ else
+ {
+ m_icount -= 2;
+ cycle_count += 2;
+ }
+ return;
+ case 2: // JGE
+ if(!(UNSP_REG(SR) & UNSP_S))
+ {
+ m_icount -= 4;
+ cycle_count += 4;
+ add_lpc((OP1 == 0) ? OPIMM : (0 - OPIMM));
+ }
+ else
+ {
+ m_icount -= 2;
+ cycle_count += 2;
+ }
+ return;
+ case 3: // JL
+ if(UNSP_REG(SR) & UNSP_S)
+ {
+ m_icount -= 4;
+ cycle_count += 4;
+ add_lpc((OP1 == 0) ? OPIMM : (0 - OPIMM));
+ }
+ else
+ {
+ m_icount -= 2;
+ cycle_count += 2;
+ }
+ return;
+ case 4: // JNE
+ if(!(UNSP_REG(SR) & UNSP_Z))
+ {
+ m_icount -= 4;
+ cycle_count += 4;
+ add_lpc((OP1 == 0) ? OPIMM : (0 - OPIMM));
+ }
+ else
+ {
+ m_icount -= 2;
+ cycle_count += 2;
+ }
+ return;
+ case 5: // JE
+ if(UNSP_REG(SR) & UNSP_Z)
+ {
+ m_icount -= 4;
+ cycle_count += 4;
+ add_lpc((OP1 == 0) ? OPIMM : (0 - OPIMM));
+ }
+ else
+ {
+ m_icount -= 2;
+ cycle_count += 2;
+ }
+ return;
+ case 6: // JPL
+ if(!(UNSP_REG(SR) & UNSP_N))
+ {
+ m_icount -= 4;
+ cycle_count += 4;
+ add_lpc((OP1 == 0) ? OPIMM : (0 - OPIMM));
+ }
+ else
+ {
+ m_icount -= 2;
+ cycle_count += 2;
+ }
+ return;
+ case 7: // JMI
+ if(UNSP_REG(SR) & UNSP_N)
+ {
+ m_icount -= 4;
+ cycle_count += 4;
+ add_lpc((OP1 == 0) ? OPIMM : (0 - OPIMM));
+ }
+ else
+ {
+ m_icount -= 2;
+ cycle_count += 2;
+ }
+ return;
+ case 8: // JBE
+ if((UNSP_REG(SR) & (UNSP_Z | UNSP_C)) != UNSP_C)
+ {
+ m_icount -= 4;
+ cycle_count += 4;
+ add_lpc((OP1 == 0) ? OPIMM : (0 - OPIMM));
+ }
+ else
+ {
+ m_icount -= 2;
+ cycle_count += 2;
+ }
+ return;
+ case 9: // JA
+ if((UNSP_REG(SR) & (UNSP_Z | UNSP_C)) == UNSP_C)
+ {
+ m_icount -= 4;
+ cycle_count += 4;
+ add_lpc((OP1 == 0) ? OPIMM : (0 - OPIMM));
+ }
+ else
+ {
+ m_icount -= 2;
+ cycle_count += 2;
+ }
+ return;
+ case 10: // JLE
+ if(UNSP_REG(SR) & (UNSP_Z | UNSP_S))
+ {
+ m_icount -= 4;
+ cycle_count += 4;
+ add_lpc((OP1 == 0) ? OPIMM : (0 - OPIMM));
+ }
+ else
+ {
+ m_icount -= 2;
+ cycle_count += 2;
+ }
+ return;
+ case 11: // JG
+ if(!(UNSP_REG(SR) & (UNSP_Z | UNSP_S)))
+ {
+ m_icount -= 4;
+ cycle_count += 4;
+ add_lpc((OP1 == 0) ? OPIMM : (0 - OPIMM));
+ }
+ else
+ {
+ m_icount -= 2;
+ cycle_count += 2;
+ }
+ return;
+ case 14: // JMP
+ add_lpc((OP1 == 0) ? OPIMM : (0 - OPIMM));
+ m_icount -= 4;
+ cycle_count += 4;
+ return;
+ default:
+ unimplemented_opcode(op);
+ return;
}
-#endif
-
- UNSP_REG(PC)++;
-
- const uint8_t lower_op = (OP1 << 4) | OP0;
+ }
+ else if (lower_op == 0x2d) // Push
+ {
+ r0 = OPN;
+ r1 = OPA;
+ m_icount -= 4 + 2 * r0;
+ cycle_count += 4 + 2 * r0;
- if(OP0 < 0xf && OPA == 0x7 && OP1 < 2)
+ while (r0--)
{
- switch(OP0)
+ push(UNSP_REG_I(r1--), &UNSP_REG_I(OPB));
+ }
+ return;
+ }
+ else if (lower_op == 0x29) // Pop
+ {
+ if (op == 0x9a98) // reti
+ {
+ m_icount -= 8;
+ cycle_count += 8;
+ UNSP_REG(SR) = pop(&UNSP_REG(SP));
+ UNSP_REG(PC) = pop(&UNSP_REG(SP));
+
+ if(m_fiq)
{
- case 0: // JB
- if(!(UNSP_REG(SR) & UNSP_C))
- {
- m_icount -= 4;
- UNSP_REG(PC) += (OP1 == 0) ? OPIMM : (0 - OPIMM);
- }
- 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);
- }
- 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);
- }
- 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);
- }
- 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);
- }
- 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);
- }
- 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);
- }
- 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);
- }
- 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);
- }
- 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);
- }
- 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);
- }
- 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);
- }
- else
- m_icount -= 2;
- continue;
- case 14: // JMP
- UNSP_REG(PC) += (OP1 == 0) ? OPIMM : (0 - OPIMM);
- m_icount -= 4;
- continue;
- default:
- unimplemented_opcode(op);
- continue;
+ 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];
+ }
+ m_curirq = 0;
+
+ check_irqs();
+ return;
}
- else if (lower_op == 0x2d) // Push
+ else
{
r0 = OPN;
r1 = OPA;
m_icount -= 4 + 2 * r0;
+ cycle_count += 4 + 2 * r0;
while (r0--)
{
- push(UNSP_REG_I(r1--), &UNSP_REG_I(OPB));
+ UNSP_REG_I(++r1) = pop(&UNSP_REG_I(OPB));
}
- continue;
+ return;
}
- else if (lower_op == 0x29) // Pop
+ }
+ else if (OP0 == 0xf)
+ {
+ switch (OP1)
{
- if (op == 0x9a98) // reti
- {
- m_icount -= 8;
- UNSP_REG(SR) = pop(&UNSP_REG(SP));
- UNSP_REG(PC) = pop(&UNSP_REG(SP));
-
- if(m_fiq)
+ case 0x00: // Multiply, Unsigned * Signed
+ if(OPN == 1 && OPA != 7)
{
- m_fiq = false;
- m_saved_sb[2] = m_sb;
- m_sb = m_saved_sb[m_irq ? 1 : 0];
+ m_icount -= 12;
+ cycle_count += 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;
}
- else if(m_irq)
+ else
{
- m_irq = false;
- m_saved_sb[1] = m_sb;
- m_sb = m_saved_sb[0];
+ unimplemented_opcode(op);
}
- m_curirq = 0;
+ return;
- check_irqs();
- continue;
- }
- else
- {
- r0 = OPN;
- r1 = OPA;
- m_icount -= 4 + 2 * r0;
-
- while (r0--)
+ case 0x01: // Call
+ if(!(OPA & 1))
{
- UNSP_REG_I(++r1) = pop(&UNSP_REG_I(OPB));
+ m_icount -= 9;
+ cycle_count += 9;
+ r1 = read16(UNSP_LPC);
+ add_lpc(1);
+ 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;
}
- continue;
- }
- }
- else if (OP0 == 0xf)
- {
- switch (OP1)
- {
- case 0x00: // Multiply, Unsigned * Signed
- if(OPN == 1 && OPA != 7)
- {
- 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;
- }
- else
- {
- unimplemented_opcode(op);
- }
- continue;
+ else
+ {
+ unimplemented_opcode(op);
+ }
+ return;
- case 0x01: // Call
- if(!(OPA & 1))
- {
- 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
- {
- unimplemented_opcode(op);
- }
- continue;
+ case 0x02: // Far Jump
+ if (OPA == 7)
+ {
+ m_icount -= 5;
+ cycle_count += 5;
+ UNSP_REG(PC) = read16(UNSP_LPC);
+ UNSP_REG(SR) &= 0xffc0;
+ UNSP_REG(SR) |= OPIMM;
+ }
+ else
+ {
+ unimplemented_opcode(op);
+ }
+ return;
- case 0x02: // Far Jump
- if (OPA == 7)
+ case 0x04: // Multiply, Signed * Signed
+ if(OPN == 1 && OPA != 7)
+ {
+ m_icount -= 12;
+ cycle_count += 12;
+ lres = UNSP_REG_I(OPA) * UNSP_REG_I(OPB);
+ if(UNSP_REG_I(OPB) & 0x8000)
{
- m_icount -= 5;
- UNSP_REG(PC) = read16(UNSP_LPC);
- UNSP_REG(SR) &= 0xffc0;
- UNSP_REG(SR) |= OPIMM;
+ lres -= UNSP_REG_I(OPA) << 16;
}
- else
+ if(UNSP_REG_I(OPA) & 0x8000)
{
- unimplemented_opcode(op);
+ lres -= UNSP_REG_I(OPB) << 16;
}
- continue;
+ UNSP_REG(R4) = lres >> 16;
+ UNSP_REG(R3) = (uint16_t)lres;
+ }
+ else
+ {
+ unimplemented_opcode(op);
+ }
+ return;
- 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)
- {
- 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;
- }
- else
- {
+ case 0x05: // Interrupt flags
+ m_icount -= 2;
+ cycle_count += 2;
+ switch(OPIMM)
+ {
+ 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);
- }
- continue;
-
- case 0x05: // Interrupt flags
- m_icount -= 2;
- switch(OPIMM)
- {
- 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;
- }
- continue;
+ break;
+ }
+ return;
- default:
- unimplemented_opcode(op);
- continue;
- }
+ default:
+ unimplemented_opcode(op);
+ return;
}
+ }
- // At this point, we should be dealing solely with ALU ops.
+ // At this point, we should be dealing solely with ALU ops.
- r0 = UNSP_REG_I(OPA);
+ r0 = UNSP_REG_I(OPA);
- switch (OP1)
- {
- case 0x00: // r, [bp+imm6]
- m_icount -= 6;
+ switch (OP1)
+ {
+ case 0x00: // r, [bp+imm6]
+ m_icount -= 6;
+ cycle_count += 6;
- r2 = (uint16_t)(UNSP_REG(BP) + OPIMM);
- if (OP0 != 0x0d)
- r1 = read16(r2);
- break;
+ r2 = (uint16_t)(UNSP_REG(BP) + OPIMM);
+ if (OP0 != 0x0d)
+ r1 = read16(r2);
+ break;
- case 0x01: // r, imm6
- m_icount -= 2;
+ case 0x01: // r, imm6
+ m_icount -= 2;
+ cycle_count += 2;
- r1 = OPIMM;
- break;
+ r1 = OPIMM;
+ break;
- case 0x03: // Indirect
+ case 0x03: // Indirect
+ {
+ m_icount -= 6;
+ cycle_count += 6;
+ if (OPA == 7)
{
- m_icount -= 6;
- if (OPA == 7)
- m_icount -= 1;
+ m_icount -= 1;
+ cycle_count += 1;
+ }
- const uint8_t lsbits = OPN & 3;
- const uint8_t opb = OPB;
- if (OPN & 4)
- {
- switch (lsbits)
- {
- case 0: // r, [r]
- r2 = UNSP_LREG_I(opb);
- if (OP0 != 0x0d)
- r1 = read16(r2);
- break;
- case 1: // r, [<ds:>r--]
- r2 = UNSP_LREG_I(opb);
- if (OP0 != 0x0d)
- r1 = read16(r2);
- UNSP_REG_I(opb)--;
- if (UNSP_REG_I(opb) == 0xffff)
- UNSP_REG(SR) -= 0x0400;
- break;
- case 2: // r, [<ds:>r++]
- r2 = UNSP_LREG_I(opb);
- if (OP0 != 0x0d)
- r1 = read16(r2);
- UNSP_REG_I(opb)++;
- if (UNSP_REG_I(opb) == 0x0000)
- UNSP_REG(SR) += 0x0400;
- break;
- case 3: // r, [<ds:>++r]
- UNSP_REG_I(opb)++;
- if (UNSP_REG_I(opb) == 0x0000)
- UNSP_REG(SR) += 0x0400;
- r2 = UNSP_LREG_I(opb);
- if (OP0 != 0x0d)
- r1 = read16(r2);
- break;
- default:
- break;
- }
- }
- else
+ const uint8_t lsbits = OPN & 3;
+ const uint8_t opb = OPB;
+ if (OPN & 4)
+ {
+ switch (lsbits)
{
- switch (lsbits)
- {
- case 0: // r, [r]
- r2 = UNSP_REG_I(opb);
- if (OP0 != 0x0d)
- r1 = read16(r2);
- break;
- case 1: // r, [r--]
- r2 = UNSP_REG_I(opb);
- if (OP0 != 0x0d)
- r1 = read16(r2);
- UNSP_REG_I(opb)--;
- break;
- case 2: // r, [r++]
- r2 = UNSP_REG_I(opb);
- if (OP0 != 0x0d)
- r1 = read16(r2);
- UNSP_REG_I(opb)++;
- break;
- case 3: // r, [++r]
- UNSP_REG_I(opb)++;
- r2 = UNSP_REG_I(opb);
- if (OP0 != 0x0d)
- r1 = read16(r2);
- break;
- default:
- break;
- }
+ case 0: // r, [r]
+ r2 = UNSP_LREG_I(opb);
+ if (OP0 != 0x0d)
+ r1 = read16(r2);
+ break;
+ case 1: // r, [<ds:>r--]
+ r2 = UNSP_LREG_I(opb);
+ if (OP0 != 0x0d)
+ r1 = read16(r2);
+ UNSP_REG_I(opb)--;
+ if (UNSP_REG_I(opb) == 0xffff)
+ UNSP_REG(SR) -= 0x0400;
+ break;
+ case 2: // r, [<ds:>r++]
+ r2 = UNSP_LREG_I(opb);
+ if (OP0 != 0x0d)
+ r1 = read16(r2);
+ UNSP_REG_I(opb)++;
+ if (UNSP_REG_I(opb) == 0x0000)
+ UNSP_REG(SR) += 0x0400;
+ break;
+ case 3: // r, [<ds:>++r]
+ UNSP_REG_I(opb)++;
+ if (UNSP_REG_I(opb) == 0x0000)
+ UNSP_REG(SR) += 0x0400;
+ r2 = UNSP_LREG_I(opb);
+ if (OP0 != 0x0d)
+ r1 = read16(r2);
+ break;
+ default:
+ break;
}
- break;
}
-
- case 0x04: // 16-bit ops
- switch (OPN)
+ else
+ {
+ switch (lsbits)
{
- case 0x00: // r
- m_icount -= 3;
- if (OPA == 7)
- m_icount -= 2;
-
- r1 = UNSP_REG_I(OPB);
+ case 0: // r, [r]
+ r2 = UNSP_REG_I(opb);
+ if (OP0 != 0x0d)
+ r1 = read16(r2);
+ break;
+ case 1: // r, [r--]
+ r2 = UNSP_REG_I(opb);
+ if (OP0 != 0x0d)
+ r1 = read16(r2);
+ UNSP_REG_I(opb)--;
+ break;
+ case 2: // r, [r++]
+ r2 = UNSP_REG_I(opb);
+ if (OP0 != 0x0d)
+ r1 = read16(r2);
+ UNSP_REG_I(opb)++;
+ break;
+ case 3: // r, [++r]
+ UNSP_REG_I(opb)++;
+ r2 = UNSP_REG_I(opb);
+ if (OP0 != 0x0d)
+ r1 = read16(r2);
break;
+ default:
+ break;
+ }
+ }
+ break;
+ }
- case 0x01: // imm16
- m_icount -= 4;
- if (OPA == 7)
- m_icount -= 1;
+ case 0x04: // 16-bit ops
+ switch (OPN)
+ {
+ case 0x00: // r
+ m_icount -= 3;
+ cycle_count += 3;
+ if (OPA == 7)
+ {
+ m_icount -= 2;
+ cycle_count += 2;
+ }
- r0 = UNSP_REG_I(OPB);
- r1 = read16(UNSP_LPC);
- UNSP_REG(PC)++;
- break;
+ r1 = UNSP_REG_I(OPB);
+ break;
- case 0x02: // [imm16]
- m_icount -= 7;
- if (OPA == 7)
- m_icount -= 1;
+ case 0x01: // imm16
+ m_icount -= 4;
+ cycle_count += 4;
+ if (OPA == 7)
+ {
+ m_icount -= 1;
+ cycle_count += 1;
+ }
- r0 = UNSP_REG_I(OPB);
- r2 = read16(UNSP_LPC);
- UNSP_REG(PC)++;
+ r0 = UNSP_REG_I(OPB);
+ r1 = read16(UNSP_LPC);
+ add_lpc(1);
+ break;
- if (OP0 != 0x0d)
- {
- r1 = read16(r2);
- }
- break;
+ case 0x02: // [imm16]
+ m_icount -= 7;
+ cycle_count += 7;
+ if (OPA == 7)
+ {
+ m_icount -= 1;
+ cycle_count += 1;
+ }
- case 0x03: // store [imm16], r
- m_icount -= 7;
- if (OPA == 7)
- m_icount -= 1;
+ r0 = UNSP_REG_I(OPB);
+ r2 = read16(UNSP_LPC);
+ add_lpc(1);
- r1 = r0;
- r0 = UNSP_REG_I(OPB);
- r2 = read16(UNSP_LPC);
- UNSP_REG(PC)++;
- break;
+ if (OP0 != 0x0d)
+ {
+ r1 = read16(r2);
+ }
+ break;
- default: // Shifted ops
+ case 0x03: // store [imm16], r
+ m_icount -= 7;
+ cycle_count += 7;
+ if (OPA == 7)
{
- 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;
+ m_icount -= 1;
+ cycle_count += 1;
}
- }
- break;
- case 0x05: // More shifted ops
- m_icount -= 3;
- if (OPA == 7)
- m_icount -= 2;
+ r1 = r0;
+ r0 = UNSP_REG_I(OPB);
+ r2 = read16(UNSP_LPC);
+ add_lpc(1);
+ break;
- if (OPN & 4) // Shift right
+ default: // Shifted ops
{
- const uint32_t shift = ((UNSP_REG_I(OPB) << 4) | m_sb) >> (OPN - 3);
+ m_icount -= 3;
+ cycle_count += 3;
+ if (OPA == 7)
+ {
+ m_icount -= 2;
+ cycle_count += 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;
}
- 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;
+ }
+ break;
- case 0x06: // Rotated ops
+ case 0x05: // More shifted ops
+ m_icount -= 3;
+ cycle_count += 3;
+ if (OPA == 7)
{
- m_icount -= 3;
- if (OPA == 7)
- m_icount -= 2;
+ m_icount -= 2;
+ cycle_count += 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;
- }
+ 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);
- break;
}
+ 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 0x07: // Direct 8
- m_icount -= 5;
- if (OPA == 7)
- m_icount -= 1;
-
- r1 = read16(OPIMM);
- break;
+ case 0x06: // Rotated ops
+ {
+ m_icount -= 3;
+ cycle_count += 3;
+ if (OPA == 7)
+ {
+ m_icount -= 2;
+ cycle_count += 2;
+ }
- default:
- break;
+ 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;
}
- switch (OP0)
+ case 0x07: // Direct 8
+ m_icount -= 5;
+ cycle_count += 5;
+ if (OPA == 7)
+ {
+ m_icount -= 1;
+ cycle_count += 1;
+ }
+
+ r2 = OPIMM;
+ r1 = read16(OPIMM);
+ break;
+
+ default:
+ break;
+ }
+
+ 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);
+ return;
+ default:
+ unimplemented_opcode(op);
+ return;
+ }
+
+ if (OP0 != 0x0d && OPA != 7) // If not a store opcode and not updating the PC, update negative/zero flags.
+ {
+ update_nz(lres);
+ }
+
+ if (OP0 < 0x05 && OPA != 7) // 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.
+ return;
+
+ if (OP1 == 0x04 && OPN == 0x03) // store [imm16], r
+ write16(r2, lres);
+ else
+ UNSP_REG_I(OPA) = lres;
+}
+
+void unsp_device::execute_run()
+{
+#if UNSP_LOG_OPCODES
+ unsp_disassembler dasm;
+#endif
+
+ while (m_icount > 0)
+ {
+ debugger_instruction_hook(UNSP_LPC);
+ const uint32_t op = read16(UNSP_LPC);
+
+#if UNSP_LOG_OPCODES
+ if (m_log_ops)
{
- 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;
+ std::stringstream strbuffer;
+ dasm.disassemble(strbuffer, UNSP_LPC, op, read16(UNSP_LPC+1));
+ uint32_t len = 1;
+ if ((OP0 < 14 && OP1 == 4 && (OPN == 1 || OPN == 2 || OPN == 3)) || (OP0 == 15 && (OP1 == 1 || OP1 == 2)))
+ {
+ len = 2;
+ }
+ if (len == 1)
+ {
+ logerror("%04x %04x %04x %04x %04x %04x %04x %04x %02x %x%x%x%x %02x %x %x %d %x: %04x %x %x %x %x %x %s\n",
+ m_r[0], m_r[1], m_r[2], m_r[3], m_r[4], m_r[5], m_r[6], m_r[7],
+ m_r[6] & 0x3f, BIT(m_r[6], 9), BIT(m_r[6], 8), BIT(m_r[6], 7), BIT(m_r[6], 6), (m_r[6] >> 10) & 0x3f,
+ m_sb, m_enable_irq ? 1 : 0, cycle_count, UNSP_LPC, op, OP0, OPA, OP1, OPN, OPB, strbuffer.str().c_str());
+ }
+ else
+ {
+ logerror("%04x %04x %04x %04x %04x %04x %04x %04x %02x %x%x%x%x %02x %x %x %d %x: %04x %04x %x %x %x %x %x %s\n",
+ m_r[0], m_r[1], m_r[2], m_r[3], m_r[4], m_r[5], m_r[6], m_r[7],
+ m_r[6] & 0x3f, BIT(m_r[6], 9), BIT(m_r[6], 8), BIT(m_r[6], 7), BIT(m_r[6], 6), (m_r[6] >> 10) & 0x3f,
+ m_sb, m_enable_irq ? 1 : 0, cycle_count, UNSP_LPC, op, read16(UNSP_LPC+1), OP0, OPA, OP1, OPN, OPB, strbuffer.str().c_str());
+ }
+ //logerror("%x: %s\n", UNSP_LPC, strbuffer.str().c_str());
+ //logerror("%x%04x: %d\n", UNSP_REG(SR) & 0x3f, UNSP_REG(PC), cycle_count);
}
+#endif
- if (OP0 != 0x0d && OPA != 7) // If not a store opcode and not updating the PC, update negative/zero flags.
- update_nz(lres);
+ add_lpc(1);
- if (OP0 < 0x05 && OPA != 7) // If Add, Add w/ Carry, Subtract, Subtract w/ Carry, Compare, and not updating the PC, update sign/carry flags.
- update_sc(lres, r0, r1);
+ execute_one(op);
- if (OP0 == 0x04 || OP0 == 0x0c) // Compare and Test don't write back results.
- continue;
+ if (cycle_count >= cycles_per_line)
+ {
+ cycle_count -= cycles_per_line;
- if (OP1 == 0x04 && OPN == 0x03) // store [imm16], r
- write16(r2, lres);
- else
- UNSP_REG_I(OPA) = lres;
+ timer_run(cycles_per_line);
+
+ if (line_count == 240)
+ write16(0x3d61, 1); // trigger vblank IRQ
+ if (line_count == read16(0x2836))
+ write16(0x3d61, 2); // trigger vpos IRQ
+
+ check_irqs();
+
+ line_count++;
+ if (line_count == lines_per_frame)
+ {
+ line_count = 0;
+ write16(0x3d60, 0x0100);
+ }
+ }
}
}
@@ -917,3 +1134,55 @@ void unsp_device::execute_set_input(int irqline, int state)
break;
}
}
+
+void unsp_device::set_timer_interval(int timer, uint32_t interval)
+{
+ if (timer == 0)
+ timer_tmb1.interval = interval;
+ else if (timer == 1)
+ timer_tmb2.interval = interval;
+}
+
+void unsp_device::timer_add(struct unsp_timer *timer)
+{
+ if (timer->time == 0)
+ timer->time = timer->interval;
+
+ uint32_t time = timer->time;
+ struct unsp_timer **p = &timers;
+
+ while (*p && (*p)->time <= time) {
+ time -= (*p)->time;
+ p = &(*p)->next;
+ }
+
+ timer->next = *p;
+ *p = timer;
+ timer->time = time;
+ if (timer->next)
+ timer->next->time -= time;
+}
+
+void unsp_device::timer_run(uint32_t ticks)
+{
+ struct unsp_timer *timer;
+ while ((timer = timers) && timer->time <= ticks) {
+ timers = timer->next;
+ ticks -= timer->time;
+
+ write16(0x3d62, 1 << timer->index);
+
+ if (timer->interval) {
+ timer->time = timer->interval;
+ timer_add(timer);
+ }
+ }
+
+ if (timer)
+ timer->time -= ticks;
+}
+
+uint16_t unsp_device::get_video_line()
+{
+ return line_count;
+}
diff --git a/src/devices/cpu/unsp/unsp.h b/src/devices/cpu/unsp/unsp.h
index cd939aeb25e..2ff18871a8f 100644
--- a/src/devices/cpu/unsp/unsp.h
+++ b/src/devices/cpu/unsp/unsp.h
@@ -1,10 +1,14 @@
-// license:BSD-3-Clause
-// copyright-holders:Ryan Holtz
+// license:GPL-2.0+
+// copyright-holders:Segher Boessenkool,Ryan Holtz
/*****************************************************************************
- SunPlus micro'nSP core
+ SunPlus micro'nSP emulator
- based primarily on Unununium, by segher
+ Copyright 2008-2017 Segher Boessenkool <segher@kernel.crashing.org>
+ Licensed under the terms of the GNU GPL, version 2
+ http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
+
+ Ported to MAME framework by Ryan Holtz
*****************************************************************************/
@@ -13,7 +17,7 @@
#pragma once
-#define UNSP_LOG_OPCODES (0)
+#define UNSP_LOG_OPCODES (1)
enum
{
@@ -56,6 +60,13 @@ enum
UNSP_NUM_LINES
};
+struct unsp_timer
+{
+ uint32_t time;
+ uint32_t interval;
+ int index;
+ struct unsp_timer *next;
+};
class unsp_device : public cpu_device
{
@@ -63,6 +74,10 @@ public:
// construction/destruction
unsp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ void set_timer_interval(int timer, uint32_t interval);
+
+ uint16_t get_video_line();
+
protected:
// device-level overrides
virtual void device_start() override;
@@ -87,8 +102,15 @@ protected:
virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
private:
+ void add_lpc(const int32_t offset);
+
+ inline void execute_one(const uint16_t op);
+
address_space_config m_program_config;
+ void timer_add(struct unsp_timer *timer);
+ void timer_run(uint32_t ticks);
+
uint16_t m_r[16];
bool m_enable_irq;
bool m_enable_fiq;
@@ -98,6 +120,7 @@ private:
uint16_t m_sirq;
uint8_t m_sb;
uint8_t m_saved_sb[3];
+ struct unsp_timer *timers;
address_space *m_program;
int m_icount;
@@ -117,6 +140,7 @@ private:
inline void trigger_fiq();
inline void trigger_irq(int line);
inline void check_irqs();
+ inline int get_irq();
};
diff --git a/src/devices/cpu/unsp/unspdasm.cpp b/src/devices/cpu/unsp/unspdasm.cpp
index 14996cbbf2a..ad67ce9d17e 100644
--- a/src/devices/cpu/unsp/unspdasm.cpp
+++ b/src/devices/cpu/unsp/unspdasm.cpp
@@ -1,257 +1,435 @@
-// license:BSD-3-Clause
-// copyright-holders:Ryan Holtz
+// license:GPL-2.0+
+// copyright-holders:Segher Boessenkool
/*****************************************************************************
SunPlus micro'nSP disassembler
+ Copyright 2008-2017 Segher Boessenkool <segher@kernel.crashing.org>
+ Licensed under the terms of the GNU GPL, version 2
+ http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
+
*****************************************************************************/
#include "emu.h"
#include "unspdasm.h"
-char const *const unsp_disassembler::reg[] =
+char const *const unsp_disassembler::regs[] =
{
"sp", "r1", "r2", "r3", "r4", "bp", "sr", "pc"
};
-char const *const unsp_disassembler::jmp[] =
+char const *const unsp_disassembler::jumps[] =
{
"jb", "jae", "jge", "jl", "jne", "je", "jpl", "jmi",
"jbe", "ja", "jle", "jg", "jvc", "jvs", "jmp", "<inv>"
};
-char const *const unsp_disassembler::alu[] =
+#define UNSP_DASM_OK (len | SUPPORTED)
+
+u32 unsp_disassembler::opcode_alignment() const
{
- "add", "adc", "sub", "sbc",
- "cmp", "<inv>", "neg", "<inv>",
- "xor", "load", "or", "and",
- "test", "store", "<inv>", "<inv>"
-};
+ return 1;
+}
-/*****************************************************************************/
+void unsp_disassembler::print_alu_op_start(std::ostream &stream, uint8_t op0, uint8_t opA)
+{
+ static const char* const alu_op_start[] =
+ {
+ "%s += ", "%s += ", "%s -= ", "%s -= ",
+ "cmp %s, ", "<BAD>", "%s =- ", "<BAD>",
+ "%s ^= ", "%s = ", "%s |= ", "%s &= ",
+ "test %s, "
+ };
-#define OP0 (op >> 12)
-#define OPA ((op >> 9) & 7)
-#define OP1 ((op >> 6) & 7)
-#define OPN ((op >> 3) & 7)
-#define OPB (op & 7)
-#define OPIMM (op & 0x3f)
-#define OP2X ((OP0 < 14 && OP1 == 4 && (OPN >= 1 && OPN <= 3)) || (OP0 == 15 && (OP1 == 1 || OP1 == 2)))
+ util::stream_format(stream, alu_op_start[op0], regs[opA]);
+}
-/*****************************************************************************/
+void unsp_disassembler::print_alu_op3(std::ostream &stream, uint8_t op0, uint8_t opB)
+{
+ static const char* const alu_op3[] =
+ {
+ "%s + ", "%s + ", "%s - ", "%s - ",
+ "cmp %s, ", "<BAD>", "-", "<BAD>",
+ "%s ^ ", "", "%s | ", "%s & ",
+ "test %s, "
+ };
-#define UNSP_DASM_OK ((OP2X ? 2 : 1) | SUPPORTED)
+ util::stream_format(stream, alu_op3[op0], regs[opB]);
+}
-u32 unsp_disassembler::opcode_alignment() const
+void unsp_disassembler::print_alu_op_end(std::ostream &stream, uint8_t op0)
{
- return 1;
+ if (op0 == 1 || op0 == 3)
+ util::stream_format(stream, ", carry");
}
-offs_t unsp_disassembler::disassemble(std::ostream &stream, offs_t pc, uint16_t op, uint16_t imm16)
+void unsp_disassembler::print_indirect_op(std::ostream &stream, uint8_t opN, uint8_t opB)
{
- if(OP0 < 0xf && OPA == 0x7 && OP1 < 2)
+ static const char* const forms[] = { "[%s]", "[%s--]", "[%s++]", "[++%s]" };
+
+ if (opN & 4)
+ util::stream_format(stream, "ds:");
+ util::stream_format(stream, forms[opN & 3], regs[opB]);
+}
+
+offs_t unsp_disassembler::disassemble(std::ostream &stream, offs_t pc, uint16_t op, uint16_t ximm)
+{
+ // the top four bits are the alu op or the branch condition, or E or F
+ uint8_t op0 = (op >> 12);
+
+ // the next three are usually the destination register
+ uint8_t opA = (op >> 9) & 7;
+
+ // and the next three the addressing mode
+ uint8_t op1 = (op >> 6) & 7;
+
+ // the next three can be anything
+ uint8_t opN = (op >> 3) & 7;
+
+ // and the last three usually the second register (source register)
+ uint8_t opB = op & 7;
+
+ // the last six sometimes are a single immediate number
+ uint8_t opimm = op & 63;
+
+ uint32_t len = 1;
+ if ((op0 < 14 && op1 == 4 && (opN == 1 || opN == 2 || opN == 3)) || (op0 == 15 && (op1 == 1 || op1 == 2)))
{
- util::stream_format(stream, "%s %04x", jmp[OP0], OP1 ? (pc - OPIMM + 1) : (pc + OPIMM + 1));
+ len = 2;
+ }
+
+ // all-zero and all-one are invalid insns:
+ if (op == 0 || op == 0xffff)
+ {
+ util::stream_format(stream, "--");
return UNSP_DASM_OK;
}
- switch((OP1 << 4) | OP0)
+ // first, check for the conditional branch insns
+ if (op0 < 15 && opA == 7 && op1 == 0)
{
- // ALU, Indexed
- case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x06: case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d:
- util::stream_format(stream, "%s %s, [bp+%02x]", alu[OP0], reg[OPA], OPIMM);
- return UNSP_DASM_OK;
+ util::stream_format(stream, "%s %04x", jumps[op0], pc+1+opimm);
+ return UNSP_DASM_OK;
+ }
+ if (op0 < 15 && opA == 7 && op1 == 1)
+ {
+ util::stream_format(stream, "%s %04x", jumps[op0], pc+1-opimm);
+ return UNSP_DASM_OK;
+ }
+
+ switch ((op1 << 4) | op0)
+ {
+ case 0x05: case 0x15: case 0x25: case 0x35:
+ case 0x45: case 0x55: case 0x65: case 0x75:
+ case 0x85: case 0x95: case 0xa5: case 0xb5:
+ case 0xc5: case 0xd5:
+ case 0x07: case 0x17: case 0x27: case 0x37:
+ case 0x47: case 0x57: case 0x67: case 0x77:
+ case 0x87: case 0x97: case 0xa7: case 0xb7:
+ case 0xc7: case 0xd7:
+ case 0x1d: case 0x5d: case 0x6d:
+ case 0x20: case 0x21: case 0x22: case 0x23:
+ case 0x24: case 0x26: case 0x28: case 0x2a:
+ case 0x2b: case 0x2c:
+ util::stream_format(stream, "<BAD>");
+ return UNSP_DASM_OK;
+
+
+ // alu, base+displacement
+ case 0x00: case 0x01: case 0x02: case 0x03:
+ case 0x04: case 0x06: case 0x08: case 0x09:
+ case 0x0a: case 0x0b: case 0x0c:
+ print_alu_op_start(stream, op0, opA);
+ util::stream_format(stream, "[bp+%02x]", opimm);
+ print_alu_op_end(stream, op0);
+ return UNSP_DASM_OK;
+ case 0x0d:
+ util::stream_format(stream, "[bp+%02x] = %s", opimm, regs[opA]);
+ return UNSP_DASM_OK;
+
+
+ // alu, 6-bit immediate
+ case 0x10: case 0x11: case 0x12: case 0x13:
+ case 0x14: case 0x16: case 0x18: case 0x19:
+ case 0x1a: case 0x1b: case 0x1c:
+ print_alu_op_start(stream, op0, opA);
+ util::stream_format(stream, "%02x", opimm);
+ print_alu_op_end(stream, op0);
+ return UNSP_DASM_OK;
+
+
+ // pop insns
+ case 0x29:
+ if (op == 0x9a90)
+ util::stream_format(stream, "retf");
+ else if (op == 0x9a98)
+ util::stream_format(stream, "reti");
+ else if (opA+1 < 8 && opA+opN < 8)
+ util::stream_format(stream, "pop %s, %s from [%s]",
+ regs[opA+1], regs[opA+opN], regs[opB]);
+ else
+ util::stream_format(stream, "<BAD>");
+ return UNSP_DASM_OK;
+
+
+ // push insns
+ case 0x2d:
+ if (opA+1 >= opN && opA < opN+7)
+ util::stream_format(stream, "push %s, %s to [%s]",
+ regs[opA+1-opN], regs[opA], regs[opB]);
+ else
+ util::stream_format(stream, "<BAD>");
+ return UNSP_DASM_OK;
+
+
+ // alu, indirect memory
+ case 0x30: case 0x31: case 0x32: case 0x33:
+ case 0x34: case 0x36: case 0x38: case 0x39:
+ case 0x3a: case 0x3b: case 0x3c:
+ print_alu_op_start(stream, op0, opA);
+ print_indirect_op(stream, opN, opB);
+ print_alu_op_end(stream, op0);
+ return UNSP_DASM_OK;
+ case 0x3d:
+ print_indirect_op(stream, opN, opB);
+ util::stream_format(stream, " = %s", regs[opA]);
+ return UNSP_DASM_OK;
- // ALU, Immediate
- case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x16: case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c:
- util::stream_format(stream, "%s %s, %02x", alu[OP0], reg[OPA], OPIMM);
+
+ case 0x40: case 0x41: case 0x42: case 0x43:
+ case 0x44: case 0x46: case 0x48: case 0x49:
+ case 0x4a: case 0x4b: case 0x4c:
+ switch (opN)
+ {
+ // alu, register
+ case 0:
+ print_alu_op_start(stream, op0, opA);
+ util::stream_format(stream, "%s", regs[opB]);
+ print_alu_op_end(stream, op0);
return UNSP_DASM_OK;
- // Pop / Interrupt return
- case 0x29:
- if(op == 0x9a90)
+ // alu, 16-bit immediate
+ case 1:
+ if ((op0 == 4 || op0 == 12 || op0 == 6 || op0 == 9) && opA != opB)
{
- util::stream_format(stream, "retf");
+ util::stream_format(stream, "<BAD>");
return UNSP_DASM_OK;
}
- else if(op == 0x9a98)
- {
- util::stream_format(stream, "reti");
- return UNSP_DASM_OK;
- }
- else if((OPA + 1) < 8 && ((OPA + OPN) < 8))
+ if (op0 != 4 && op0 != 12)
+ util::stream_format(stream, "%s = ", regs[opA]);
+ print_alu_op3(stream, op0, opB);
+ util::stream_format(stream, "%04x", ximm);
+ print_alu_op_end(stream, op0);
+ return UNSP_DASM_OK;
+
+ // alu, direct memory
+ case 2:
+ if ((op0 == 4 || op0 == 12 || op0 == 6 || op0 == 9) && opA != opB)
{
- util::stream_format(stream, "pop %s, %s [%s]", reg[OPA+1], reg[OPA+OPN], reg[OPB]);
+ util::stream_format(stream, "<BAD>");
return UNSP_DASM_OK;
}
- break;
+ if (op0 != 4 && op0 != 12)
+ util::stream_format(stream, "%s = ", regs[opA]);
+ print_alu_op3(stream, op0, opB);
+ util::stream_format(stream, "[%04x]", ximm);
+ print_alu_op_end(stream, op0);
+ return UNSP_DASM_OK;
- // Push
- case 0x2d:
- if((OPA + 1) >= OPN && OPA < (OPN + 7))
+ // alu, direct memory
+ case 3:
+ if (op0 == 4 || op0 == 12)
{
- util::stream_format(stream, "push %s, %s [%s]", reg[(OPA+1)-OPN], reg[OPA], reg[OPB]);
+ util::stream_format(stream, "<BAD>");
return UNSP_DASM_OK;
}
- break;
-
- // 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)
+ if ((op0 == 6 || op0 == 9) && opA != opB)
{
- case 0:
- util::stream_format(stream, "%s %s, [%s%s]", alu[OP0], reg[OPA], (OPN & 4) ? "ds:" : "", reg[OPB]);
- return UNSP_DASM_OK;
- case 1:
- util::stream_format(stream, "%s %s, [%s%s--]", alu[OP0], reg[OPA], (OPN & 4) ? "ds:" : "", reg[OPB]);
- return UNSP_DASM_OK;
- case 2:
- util::stream_format(stream, "%s %s, [%s%s++]", alu[OP0], reg[OPA], (OPN & 4) ? "ds:" : "", reg[OPB]);
- return UNSP_DASM_OK;
- case 3:
- util::stream_format(stream, "%s %s, [%s++%s]", alu[OP0], reg[OPA], (OPN & 4) ? "ds:" : "", reg[OPB]);
- return UNSP_DASM_OK;
+ util::stream_format(stream, "<BAD>");
+ return UNSP_DASM_OK;
}
+ util::stream_format(stream, "[%04x] = ", ximm);
+ print_alu_op3(stream, op0, opB);
+ util::stream_format(stream, "%s", regs[opA]);
+ print_alu_op_end(stream, op0);
return UNSP_DASM_OK;
- // 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)
+ // alu, with shift
+ default:
+ print_alu_op_start(stream, op0, opA);
+ util::stream_format(stream, "%s asr %x", regs[opB], (opN & 3) + 1);
+ print_alu_op_end(stream, op0);
+ return UNSP_DASM_OK;
+ }
+
+ case 0x4d:
+ switch (opN)
+ {
+ // alu, direct memory
+ case 3:
+ if (opA != opB)
{
- // ALU, Register
- case 0:
- util::stream_format(stream, "%s %s, %s", alu[OP0], reg[OPA], reg[OPB]);
- return UNSP_DASM_OK;
-
- // ALU, 16-bit Immediate
- case 1:
- if(!((OP0 == 4 || OP0 == 6 || OP0 == 9 || OP0 == 12) && OPA != OPB))
- {
- if(OP0 != 4 && OP0 != 12)
- {
- util::stream_format(stream, "%s %s, %s, %04x", alu[OP0], reg[OPA], reg[OPB], imm16);
- return UNSP_DASM_OK;
- }
- else
- {
- util::stream_format(stream, "%s %s, %04x", alu[OP0], reg[OPB], imm16);
- return UNSP_DASM_OK;
- }
- }
- break;
-
- // ALU, Direct 16
- case 2:
- util::stream_format(stream, "%s %s, [%04x]", alu[OP0], reg[OPA], imm16);
- return UNSP_DASM_OK;
-
- // ALU, Direct 16
- case 3:
- util::stream_format(stream, "%s [%04x], %s, %s", alu[OP0], imm16, reg[OPA], reg[OPB]);
- return UNSP_DASM_OK;
-
- // ALU, Shifted
- default:
- util::stream_format(stream, "%s %s, %s asr %d", alu[OP0], reg[OPA], reg[OPB], (OPN & 3) + 1);
- return UNSP_DASM_OK;
+ util::stream_format(stream, "<BAD>");
+ return UNSP_DASM_OK;
}
- case 0x4d:
- if((OPN == 3) && (OPA == OPB))
- util::stream_format(stream, "store [%04x], %s", imm16, reg[OPB]);
- else
- util::stream_format(stream, "<inv>");
+ util::stream_format(stream, "[%04x] = %s", ximm, regs[opB]);
return UNSP_DASM_OK;
-
- // ALU, Shifted
- case 0x50: case 0x51: case 0x52: case 0x53: case 0x54: case 0x56: case 0x58: case 0x59: case 0x5a: case 0x5b: case 0x5c:
- util::stream_format(stream, "%s %s, %s %s %d", alu[OP0], reg[OPA], reg[OPB], (OPN & 4) ? ">>" : "<<", (OPN & 3) + 1);
+ default:
+ util::stream_format(stream, "<BAD>");
return UNSP_DASM_OK;
+ }
+
+
+ // alu, with shift
+ case 0x50: case 0x51: case 0x52: case 0x53:
+ case 0x54: case 0x56: case 0x58: case 0x59:
+ case 0x5a: case 0x5b: case 0x5c:
+ print_alu_op_start(stream, op0, opA);
+ if ((opN & 4) == 0)
+ util::stream_format(stream, "%s lsl %x", regs[opB], (opN & 3) + 1);
+ else
+ util::stream_format(stream, "%s lsr %x", regs[opB], (opN & 3) + 1);
+ print_alu_op_end(stream, op0);
+ return UNSP_DASM_OK;
- // ALU, Rotated
- case 0x60: case 0x61: case 0x62: case 0x63: case 0x64: case 0x66: case 0x68: case 0x69: case 0x6a: case 0x6b: case 0x6c:
- util::stream_format(stream, "%s %s, %s %s %d", alu[OP0], reg[OPA], reg[OPB], (OPN & 4) ? "ror" : "rol", (OPN & 3) + 1);
- return UNSP_DASM_OK;
- // 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:
- util::stream_format(stream, "%s %s, [%02x]", alu[OP0], reg[OPA], OPIMM);
- return UNSP_DASM_OK;
+ // alu, with shift
+ case 0x60: case 0x61: case 0x62: case 0x63:
+ case 0x64: case 0x66: case 0x68: case 0x69:
+ case 0x6a: case 0x6b: case 0x6c:
+ print_alu_op_start(stream, op0, opA);
+ if ((opN & 4) == 0)
+ util::stream_format(stream, "%s rol %x", regs[opB], (opN & 3) + 1);
+ else
+ util::stream_format(stream, "%s ror %x", regs[opB], (opN & 3) + 1);
+ print_alu_op_end(stream, op0);
+ return UNSP_DASM_OK;
- // Call
- case 0x1f:
- if(OPA == 0)
- util::stream_format(stream, "call %06x", (OPIMM << 16) | imm16);
- else
- util::stream_format(stream, "<inv>");
- return UNSP_DASM_OK;
- // Far Jump
- case 0x2f: case 0x3f: case 0x6f: case 0x7f:
- if (OPA == 7 && OP1 == 2)
- util::stream_format(stream, "goto %06x", (OPIMM << 16) | imm16);
- else
- util::stream_format(stream, "<inv>");
+ // alu, direct memory
+ case 0x70: case 0x71: case 0x72: case 0x73:
+ case 0x74: case 0x76: case 0x78: case 0x79:
+ case 0x7a: case 0x7b: case 0x7c:
+ print_alu_op_start(stream, op0, opA);
+ util::stream_format(stream, "[%02x]", opimm);
+ print_alu_op_end(stream, op0);
+ return UNSP_DASM_OK;
+ case 0x7d:
+ util::stream_format(stream, "[%02x] = %s", opimm, regs[opA]);
+ return UNSP_DASM_OK;
+
+
+ case 0x1f:
+ if (opA == 0)
+ {
+ util::stream_format(stream, "call %04x", (opimm << 16) | ximm);
return UNSP_DASM_OK;
+ }
+ util::stream_format(stream, "<DUNNO>");
+ return UNSP_DASM_OK;
- // Multiply, Unsigned * Signed
- case 0x0f:
- if(OPN == 1 && OPA != 7)
- util::stream_format(stream, "mulus %s, %s", reg[OPA], reg[OPB]);
- else
- util::stream_format(stream, "<inv>");
+ case 0x2f: case 0x3f: case 0x6f: case 0x7f:
+ if (opA == 7 && op1 == 2)
+ {
+ util::stream_format(stream, "goto %04x", (opimm << 16) | ximm);
+ return UNSP_DASM_OK;
+ }
+ if (opA == 7 && op1 == 3)
+ {
+ util::stream_format(stream, "<DUNNO>");
return UNSP_DASM_OK;
+ }
+ util::stream_format(stream, "<DUNNO>");
+ return UNSP_DASM_OK;
- // Multiply, Signed * Signed
- case 0x4f:
- if(OPN == 1 && OPA != 7)
- util::stream_format(stream, "mulss %s, %s", reg[OPA], reg[OPB]);
- else
- util::stream_format(stream, "<inv>");
+
+ case 0x0f:
+ switch (opN)
+ {
+ case 1:
+ if (opA == 7)
+ {
+ util::stream_format(stream, "<DUNNO>");
+ return UNSP_DASM_OK;
+ }
+ util::stream_format(stream, "mr = %s*%s, us", regs[opA], regs[opB]);
return UNSP_DASM_OK;
+ default:
+ util::stream_format(stream, "<DUNNO>");
+ return UNSP_DASM_OK;
+ }
- // Interrupt flags
- case 0x5f:
- if(OPA == 0)
+ case 0x4f:
+ switch (opN)
+ {
+ case 1:
+ if (opA == 7)
{
- switch(OPIMM)
- {
- case 0:
- util::stream_format(stream, "int off");
- break;
- case 1:
- util::stream_format(stream, "int irq");
- break;
- case 2:
- util::stream_format(stream, "int fiq");
- break;
- case 3:
- util::stream_format(stream, "int irq,fiq");
- break;
- case 8:
- util::stream_format(stream, "irq off");
- break;
- case 9:
- util::stream_format(stream, "irq on");
- break;
- case 12:
- util::stream_format(stream, "fiq off");
- break;
- case 14:
- util::stream_format(stream, "fiq on");
- break;
- case 37:
- util::stream_format(stream, "nop");
- break;
- default:
- util::stream_format(stream, "<inv>");
- break;
- }
+ util::stream_format(stream, "<DUNNO>");
+ return UNSP_DASM_OK;
}
- else
- util::stream_format(stream, "<inv>");
+ util::stream_format(stream, "mr = %s*%s", regs[opA], regs[opB]);
+ return UNSP_DASM_OK;
+ default:
+ util::stream_format(stream, "<DUNNO>");
+ return UNSP_DASM_OK;
+ }
+
+ case 0x5f:
+ if (opA != 0)
+ {
+ util::stream_format(stream, "<DUNNO>");
+ return UNSP_DASM_OK;
+ }
+ switch (opimm)
+ {
+ case 0x00:
+ util::stream_format(stream, "int off");
+ return UNSP_DASM_OK;
+ case 0x01:
+ util::stream_format(stream, "int irq");
+ return UNSP_DASM_OK;
+ case 0x02:
+ util::stream_format(stream, "int fiq");
+ return UNSP_DASM_OK;
+ case 0x03:
+ util::stream_format(stream, "int fiq,irq");
return UNSP_DASM_OK;
+ case 0x04:
+ util::stream_format(stream, "fir_mov on");
+ return UNSP_DASM_OK;
+ case 0x05:
+ util::stream_format(stream, "fir_mov off");
+ return UNSP_DASM_OK;
+ case 0x08:
+ util::stream_format(stream, "irq off");
+ return UNSP_DASM_OK;
+ case 0x09:
+ util::stream_format(stream, "irq on");
+ return UNSP_DASM_OK;
+ case 0x0c:
+ util::stream_format(stream, "fiq off");
+ return UNSP_DASM_OK;
+ case 0x0e:
+ util::stream_format(stream, "fiq on");
+ return UNSP_DASM_OK;
+ case 0x25:
+ util::stream_format(stream, "nop");
+ return UNSP_DASM_OK;
+ default:
+ util::stream_format(stream, "<DUNNO>");
+ return UNSP_DASM_OK;
+ }
+
+ case 0x0e: case 0x1e: case 0x2e: case 0x3e:
+ case 0x4e: case 0x5e: case 0x6e: case 0x7e:
+ util::stream_format(stream, "<DUNNO>");
+ return UNSP_DASM_OK;
+
+ default:
+ util::stream_format(stream, "<UNHANDLED>");
+ return UNSP_DASM_OK;
}
- util::stream_format(stream, "<inv>");
return UNSP_DASM_OK;
}
diff --git a/src/devices/cpu/unsp/unspdasm.h b/src/devices/cpu/unsp/unspdasm.h
index 94bfdeece7c..eb921b22346 100644
--- a/src/devices/cpu/unsp/unspdasm.h
+++ b/src/devices/cpu/unsp/unspdasm.h
@@ -1,9 +1,13 @@
-// license:BSD-3-Clause
-// copyright-holders:Ryan Holtz
+// license:GPL-2.0
+// copyright-holders:Segher Boessenkool
/*****************************************************************************
SunPlus micro'nSP disassembler
+ Copyright 2008-2017 Segher Boessenkool <segher@kernel.crashing.org>
+ Licensed under the terms of the GNU GPL, version 2
+ http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
+
*****************************************************************************/
#ifndef MAME_CPU_UNSP_UNSPDASM_H
@@ -22,9 +26,13 @@ public:
offs_t disassemble(std::ostream &stream, offs_t pc, uint16_t op, uint16_t imm16);
private:
- static char const *const reg[];
- static char const *const jmp[];
- static char const *const alu[];
+ void print_alu_op_start(std::ostream &stream, uint8_t op0, uint8_t opA);
+ void print_alu_op3(std::ostream &stream, uint8_t op0, uint8_t opB);
+ void print_alu_op_end(std::ostream &stream, uint8_t op0);
+ void print_indirect_op(std::ostream &stream, uint8_t opN, uint8_t opB);
+
+ static char const *const regs[];
+ static char const *const jumps[];
};
#endif
diff --git a/src/devices/machine/spg2xx.cpp b/src/devices/machine/spg2xx.cpp
index 7be6477f5f9..2da5385b0c3 100644
--- a/src/devices/machine/spg2xx.cpp
+++ b/src/devices/machine/spg2xx.cpp
@@ -167,7 +167,8 @@ void spg2xx_device::device_reset()
memset(m_video_regs, 0, 0x100 * sizeof(uint16_t));
memset(m_io_regs, 0, 0x200 * sizeof(uint16_t));
- m_io_regs[0x23] = 0x0028;
+ //m_io_regs[0x23] = 0x0028;
+ m_uart_rx_available = false;
m_video_regs[0x36] = 0xffff;
m_video_regs[0x37] = 0xffff;
@@ -830,7 +831,7 @@ WRITE_LINE_MEMBER(spg2xx_device::vblank)
#endif
const uint16_t old = VIDEO_IRQ_ENABLE & VIDEO_IRQ_STATUS;
- VIDEO_IRQ_STATUS |= 1;
+ //VIDEO_IRQ_STATUS |= 1;
LOGMASKED(LOG_IRQS, "Setting video IRQ status to %04x\n", VIDEO_IRQ_STATUS);
const uint16_t changed = old ^ (VIDEO_IRQ_ENABLE & VIDEO_IRQ_STATUS);
if (changed)
@@ -849,18 +850,16 @@ void spg2xx_device::check_video_irq()
void spg2xx_device::uart_rx(uint8_t data)
{
- if (m_uart_rx_index < 8)
+ if (!m_uart_rx_available)
{
- m_uart_rx_fifo[m_uart_rx_index] = data;
- m_uart_rx_index++;
- m_io_regs[0x31] |= 1;
- if (m_uart_rx_index > (m_io_regs[0x37] & 7))
+ if (BIT(m_io_regs[0x30], 6))
{
- const uint16_t old = IO_IRQ_STATUS;
- IO_IRQ_STATUS |= 0x0100;
- const uint16_t changed = old ^ IO_IRQ_STATUS;
- if (changed & IO_IRQ_ENABLE)
+ m_io_regs[0x36] = data;
+ if (BIT(m_io_regs[0x30], 0))
+ {
+ IO_IRQ_STATUS |= 0x0100;
check_irqs(0x0100);
+ }
}
}
else
@@ -947,32 +946,26 @@ READ16_MEMBER(spg2xx_device::io_r)
break;
case 0x31: // UART Status
- val = 0x0002 | (m_uart_rx_index ? 1 : 0) | (m_uart_rx_index == 8 ? 0x80 : 0);
+ val |= 0x81;//(m_uart_rx_available ? 0x81 : 0);
LOGMASKED(LOG_UART, "io_r: UART Status = %04x\n", val);
break;
case 0x36: // UART RX Data
- if (m_uart_rx_index)
+ if (m_uart_rx_available)
{
- val = m_uart_rx_fifo[0];
- m_uart_rx_fifo[0] = 0;
- m_uart_rx_index--;
- for (uint8_t i = 0; i < m_uart_rx_index; i++)
- {
- m_uart_rx_fifo[i] = m_uart_rx_fifo[i + 1];
- }
+ m_uart_rx_available = false;
+ m_io_regs[0x36] = 0;
}
else
{
m_io_regs[0x37] |= 0x2000;
- val = 0;
}
LOGMASKED(LOG_UART, "io_r: UART Rx Data = %04x\n", val);
break;
case 0x37: // UART Rx FIFO Control
val &= ~0x0070;
- val |= (m_uart_rx_index > 7 ? 7 : m_uart_rx_index) << 4;
+ val |= (m_uart_rx_available ? 7 : 0) << 4;
LOGMASKED(LOG_UART, "io_r: UART Rx FIFO Control = %04x\n", val);
break;
@@ -1147,12 +1140,14 @@ WRITE16_MEMBER(spg2xx_device::io_w)
if (changed & 0x0013)
{
const uint32_t freq = s_tmb1_freq[hifreq][data & 3];
- m_tmb1->adjust(attotime::from_hz(freq), 0, attotime::from_hz(freq));
+ m_cpu->set_timer_interval(0, 27000000 / freq);
+ //m_tmb1->adjust(attotime::from_hz(freq), 0, attotime::from_hz(freq));
}
if (changed & 0x001c)
{
const uint32_t freq = s_tmb2_freq[hifreq][(data >> 2) & 3];
- m_tmb2->adjust(attotime::from_hz(freq), 0, attotime::from_hz(freq));
+ m_cpu->set_timer_interval(1, 27000000 / freq);
+ //m_tmb2->adjust(attotime::from_hz(freq), 0, attotime::from_hz(freq));
}
}
break;
@@ -1238,16 +1233,16 @@ WRITE16_MEMBER(spg2xx_device::io_w)
case 0x25: // ADC Control
{
LOGMASKED(LOG_IO_WRITES, "io_w: ADC Control = %04x\n", data);
- const uint16_t changed = m_io_regs[offset] ^ data;
+ //const uint16_t changed = m_io_regs[offset] ^ data;
m_io_regs[offset] = data;
- if (BIT(changed, 12) && BIT(data, 12) && !BIT(m_io_regs[offset], 1))
+ //if (BIT(changed, 12) && BIT(data, 12) && !BIT(m_io_regs[offset], 1))
{
- m_io_regs[0x27] = 0x80ff;
- const uint16_t old = IO_IRQ_STATUS;
- IO_IRQ_STATUS |= 0x2000;
- const uint16_t changed = IO_IRQ_STATUS ^ old;
- if (changed)
- check_irqs(changed);
+ //m_io_regs[0x27] = 0x80ff;
+ //const uint16_t old = IO_IRQ_STATUS;
+ //IO_IRQ_STATUS |= 0x2000;
+ //const uint16_t changed = IO_IRQ_STATUS ^ old;
+ //if (changed)
+ //check_irqs(changed);
}
break;
}
@@ -1306,23 +1301,23 @@ WRITE16_MEMBER(spg2xx_device::io_w)
static const char* const s_9th_bit[4] = { "0", "1", "Odd", "Even" };
LOGMASKED(LOG_UART, "io_w: UART Control = %04x (TxEn:%d, RxEn:%d, Bits:%d, MultiProc:%d, 9thBit:%s, TxIntEn:%d, RxIntEn:%d\n", data
, BIT(data, 7), BIT(data, 6), BIT(data, 5) ? 9 : 8, BIT(data, 4), s_9th_bit[(data >> 2) & 3], BIT(data, 1), BIT(data, 0));
- const uint16_t changed = m_io_regs[offset] ^ data;
+ //const uint16_t changed = m_io_regs[offset] ^ data;
m_io_regs[offset] = data;
if (!BIT(data, 6))
{
- m_uart_rx_index = 0;
- memset(m_uart_rx_fifo, 0, 8);
- }
- if (BIT(changed, 7) && BIT(data, 7))
- {
- m_io_regs[0x31] |= 0x0002;
+ m_uart_rx_available = false;
+ m_io_regs[0x36] = 0;
}
+ //if (BIT(changed, 7) && BIT(data, 7))
+ //{
+ // m_io_regs[0x31] |= 0x0002;
+ //}
break;
}
case 0x31: // UART Status
LOGMASKED(LOG_UART, "io_w: UART Status = %04x\n", data);
- //m_io_regs[offset] &= ~data;
+ m_io_regs[offset] &= ~data;
break;
case 0x33: // UART Baud Rate
@@ -1333,6 +1328,7 @@ WRITE16_MEMBER(spg2xx_device::io_w)
case 0x35: // UART TX Data
LOGMASKED(LOG_UART, "io_w: UART Tx Data = %02x\n", data & 0x00ff);
m_io_regs[offset] = data;
+ m_io_regs[0x31] |= 2;
m_uart_tx((uint8_t)data);
break;
@@ -1345,8 +1341,8 @@ WRITE16_MEMBER(spg2xx_device::io_w)
, BIT(data, 15), BIT(data, 14), BIT(data, 13), (data >> 4) & 7, data & 7);
if (data & 0x8000)
{
- m_uart_rx_index = 0;
- memset(m_uart_rx_fifo, 0, 8);
+ m_uart_rx_available = false;
+ m_io_regs[0x36] = 0;
}
m_io_regs[offset] &= ~data & 0x6000;
m_io_regs[offset] &= ~0x0007;
@@ -1394,6 +1390,18 @@ WRITE16_MEMBER(spg2xx_device::io_w)
m_io_regs[offset] = data;
break;
+ case 0x60: // SPECIAL INTERRUPT HAX - REMOVE BEFORE CHECKIN
+ m_io_regs[0x22] |= data;
+ break;
+
+ case 0x61: // SPECIAL INTERRUPT HAX - REMOVE BEFORE CHECKIN
+ m_video_regs[0x63] |= data;
+ break;
+
+ case 0x62: // SPECIAL INTERRUPT HAX - REMOVE BEFORE CHECKIN
+ m_io_regs[0x22] |= data;
+ break;
+
case 0x100: // DMA Source (lo)
LOGMASKED(LOG_DMA, "io_w: DMA Source (lo) = %04x\n", data);
m_io_regs[offset] = data;
@@ -1427,17 +1435,17 @@ void spg2xx_device::device_timer(emu_timer &timer, device_timer_id id, int param
{
case TIMER_TMB1:
{
- LOGMASKED(LOG_TIMERS, "TMB1 elapsed, setting IRQ Status bit 0 (old:%04x, new:%04x, enable:%04x)\n", IO_IRQ_STATUS, IO_IRQ_STATUS | 1, IO_IRQ_ENABLE);
- IO_IRQ_STATUS |= 1;
- check_irqs(0x0001);
+ //LOGMASKED(LOG_TIMERS, "TMB1 elapsed, setting IRQ Status bit 0 (old:%04x, new:%04x, enable:%04x)\n", IO_IRQ_STATUS, IO_IRQ_STATUS | 1, IO_IRQ_ENABLE);
+ //IO_IRQ_STATUS |= 1;
+ //check_irqs(0x0001);
break;
}
case TIMER_TMB2:
{
- LOGMASKED(LOG_TIMERS, "TMB2 elapsed, setting IRQ Status bit 1 (old:%04x, new:%04x, enable:%04x)\n", IO_IRQ_STATUS, IO_IRQ_STATUS | 2, IO_IRQ_ENABLE);
- IO_IRQ_STATUS |= 2;
- check_irqs(0x0002);
+ //LOGMASKED(LOG_TIMERS, "TMB2 elapsed, setting IRQ Status bit 1 (old:%04x, new:%04x, enable:%04x)\n", IO_IRQ_STATUS, IO_IRQ_STATUS | 2, IO_IRQ_ENABLE);
+ //IO_IRQ_STATUS |= 2;
+ //check_irqs(0x0002);
break;
}
@@ -1468,6 +1476,9 @@ void spg2xx_device::check_irqs(const uint16_t changed)
// m_cpu->set_input_line(UNSP_IRQ1_LINE, ASSERT_LINE);
// }
+ if (true)
+ return;
+
if (changed & 0x0c00) // Timer A, Timer B IRQ
{
m_cpu->set_input_line(UNSP_IRQ2_LINE, (IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x0c00) ? ASSERT_LINE : CLEAR_LINE);
diff --git a/src/devices/machine/spg2xx.h b/src/devices/machine/spg2xx.h
index 7a993251ece..b6ea28025ae 100644
--- a/src/devices/machine/spg2xx.h
+++ b/src/devices/machine/spg2xx.h
@@ -225,16 +225,16 @@ protected:
AUDIO_ADPCM36_MASK = 0x8000,
AUDIO_PHASE_HIGH = 0x200,
- AUDIO_PHASE_HIGH_MASK = 0x0007,
+ AUDIO_PHASE_HIGH_MASK = 0xffff,
AUDIO_PHASE_ACCUM_HIGH = 0x201,
- AUDIO_PHASE_ACCUM_HIGH_MASK = 0x0007,
+ AUDIO_PHASE_ACCUM_HIGH_MASK = 0xffff,
AUDIO_TARGET_PHASE_HIGH = 0x202,
- AUDIO_TARGET_PHASE_HIGH_MASK= 0x0007,
+ AUDIO_TARGET_PHASE_HIGH_MASK= 0xffff,
AUDIO_RAMP_DOWN_CLOCK = 0x203,
- AUDIO_RAMP_DOWN_CLOCK_MASK = 0x0007,
+ AUDIO_RAMP_DOWN_CLOCK_MASK = 0xffff,
AUDIO_PHASE = 0x204,
AUDIO_PHASE_ACCUM = 0x205,
@@ -439,8 +439,7 @@ protected:
uint16_t m_audio_curr_beat_base_count;
uint16_t m_io_regs[0x200];
- uint8_t m_uart_rx_fifo[8];
- uint8_t m_uart_rx_index;
+ bool m_uart_rx_available;
uint16_t m_video_regs[0x100];
size_t m_sprite_limit;
@@ -468,7 +467,7 @@ protected:
sound_stream *m_stream;
oki_adpcm_state m_adpcm[16];
- required_device<cpu_device> m_cpu;
+ required_device<unsp_device> m_cpu;
required_device<screen_device> m_screen;
required_shared_ptr<uint16_t> m_scrollram;
required_shared_ptr<uint16_t> m_paletteram;
diff --git a/src/mame/drivers/vii.cpp b/src/mame/drivers/vii.cpp
index dcd25d3466f..a7ffd7d4ef5 100644
--- a/src/mame/drivers/vii.cpp
+++ b/src/mame/drivers/vii.cpp
@@ -186,7 +186,7 @@ public:
: spg2xx_game_state(mconfig, type, tag)
, m_cart(*this, "cartslot")
, m_bankdev(*this, "bank")
- , m_cart_banks(*this, "cartbank%u", 0U)
+ , m_system_region(*this, "maincpu")
{ }
void vsmile(machine_config &config);
@@ -218,9 +218,9 @@ private:
DECLARE_READ16_MEMBER(bank2_r);
DECLARE_READ16_MEMBER(bank3_r);
optional_device<generic_slot_device> m_cart;
- memory_region *m_cart_rom;
required_device<address_map_bank_device> m_bankdev;
- optional_memory_bank_array<4> m_cart_banks;
+ memory_region *m_cart_region;
+ required_memory_region m_system_region;
emu_timer *m_pad_timer;
uint8_t m_pad_counter;
@@ -248,7 +248,7 @@ private:
virtual void machine_reset() override;
optional_device<generic_slot_device> m_cart;
- memory_region *m_cart_rom;
+ memory_region *m_cart_region;
};
#define VERBOSE_LEVEL (4)
@@ -340,7 +340,7 @@ void vsmile_state::device_timer(emu_timer &timer, device_timer_id id, int param,
if (m_pad_counter >= 100)
{
m_pad_counter = 0;
- m_spg->uart_rx(0x55);
+ //m_spg->uart_rx(0x55);
}
}
}
@@ -362,59 +362,55 @@ void vsmile_state::device_timer(emu_timer &timer, device_timer_id id, int param,
READ16_MEMBER(vsmile_state::bank0_r)
{
- const uint16_t data = ((uint16_t*)m_cart_rom->base())[offset];
- //printf("bank0_r: %06x: %04x\n", offset, data);
- return data;
+ return ((uint16_t*)m_cart_region->base())[offset];
}
READ16_MEMBER(vsmile_state::bank1_r)
{
- const uint16_t data = ((uint16_t*)m_cart_rom->base())[offset + 0x100000];
- //printf("bank1_r: %06x: %04x\n", offset + 0x100000, data);
- return data;
+ return ((uint16_t*)m_cart_region->base())[offset + 0x100000];
}
READ16_MEMBER(vsmile_state::bank2_r)
{
- const uint16_t data = ((uint16_t*)m_cart_rom->base())[offset + 0x200000];
- //printf("bank2_r: %06x: %04x\n", offset + 0x200000, data);
- return data;
+ return ((uint16_t*)m_cart_region->base())[offset + 0x200000];
}
READ16_MEMBER(vsmile_state::bank3_r)
{
- const uint16_t data = ((uint16_t*)memregion("maincpu")->base())[offset];
- //printf("bank3_r: %06x: %04x\n", offset + 0x300000, data);
- return data;
+ return ((uint16_t*)m_system_region->base())[offset];
}
READ16_MEMBER(vsmile_state::portb_r)
{
//const uint8_t inputs = m_io_p2->read();
//const uint16_t input_bits = BIT(inputs, 0) ? VSMILE_PORTB_ON_SW : 0;
- const uint16_t data = VSMILE_PORTB_ON_SW | (m_cart && m_cart->exists() ? VSMILE_PORTB_CART : 0);
+ //const uint16_t data = VSMILE_PORTB_ON_SW | VSMILE_PORTB_OFF_SW | (m_cart && m_cart->exists() ? VSMILE_PORTB_CART : 0);
//logerror("V.Smile Port B read %04x, mask %04x\n", data, mem_mask);
//printf("V.Smile Port B read %04x, mask %04x\n", data, mem_mask);
- return data;
+ return m_portb_data;// | data;
}
READ16_MEMBER(vsmile_state::portc_r)
{
- const uint16_t data = VSMILE_PORTC_LOGO | 0x0004;
+ uint16_t data = 0x0004;
+ if (m_portc_data & 0x0100)
+ data |= 0x0400;
+ if (m_portc_data & 0x0200)
+ data |= 0x1000;
//logerror("V.Smile Port C read %04x, mask %04x\n", data, mem_mask);
- return data;
+ return (m_portc_data & ~0x000f) | data;
}
WRITE16_MEMBER(vsmile_state::portb_w)
{
- m_portb_data = data & mem_mask;
+ m_portb_data = data;//(m_portb_data &~ mem_mask) | (data & mem_mask);
//logerror("V.Smile Port B write %04x, mask %04x\n", m_portb_data, mem_mask);
//printf("V.Smile Port B write %04x, mask %04x\n", m_portb_data, mem_mask);
}
WRITE16_MEMBER(vsmile_state::portc_w)
{
- m_portc_data = data & mem_mask;
+ m_portc_data = data;//(m_portc_data &~ mem_mask) | (data & mem_mask);
//logerror("V.Smile Port C write %04x, mask %04x\n", m_portc_data, mem_mask);
//printf("V.Smile Port C write %04x, mask %04x\n", m_portc_data, mem_mask);
//printf("%02x ", data >> 8);
@@ -422,26 +418,22 @@ WRITE16_MEMBER(vsmile_state::portc_w)
WRITE8_MEMBER(vsmile_state::uart_tx)
{
- //logerror("UART Tx: %02x\n", data);
+ logerror("UART Tx: %02x\n", data);
}
WRITE8_MEMBER(vsmile_state::chip_sel_w)
{
- //logerror("Chip select mode: %d\n", data);
const uint16_t cart_offset = m_cart && m_cart->exists() ? 4 : 0;
switch (data)
{
case 0:
- //logerror("Setting bank %d\n", cart_offset);
m_bankdev->set_bank(cart_offset);
break;
case 1:
- //logerror("Setting bank %d\n", 1 + cart_offset);
m_bankdev->set_bank(1 + cart_offset);
break;
case 2:
case 3:
- //logerror("Setting bank %d\n", 2 + cart_offset);
m_bankdev->set_bank(2 + cart_offset);
break;
}
@@ -499,15 +491,10 @@ void vsmile_state::banked_map(address_map &map)
map(0x0a00000, 0x0afffff).rom().region("maincpu", 0);
map(0x0b00000, 0x0bfffff).rom().region("maincpu", 0);
- map(0x1000000, 0x10fffff).bankr("cartbank0");
- map(0x1100000, 0x11fffff).bankr("cartbank0");
- map(0x1200000, 0x12fffff).bankr("cartbank0");
- map(0x1300000, 0x13fffff).bankr("cartbank0");
+ map(0x1000000, 0x13fffff).r(FUNC(vsmile_state::bank0_r));
- map(0x1400000, 0x14fffff).bankr("cartbank0");
- map(0x1500000, 0x15fffff).bankr("cartbank0");
- map(0x1600000, 0x16fffff).bankr("cartbank1");
- map(0x1700000, 0x17fffff).bankr("cartbank1");
+ map(0x1400000, 0x15fffff).r(FUNC(vsmile_state::bank0_r));
+ map(0x1600000, 0x17fffff).r(FUNC(vsmile_state::bank1_r));
map(0x1800000, 0x18fffff).r(FUNC(vsmile_state::bank0_r));
map(0x1900000, 0x19fffff).r(FUNC(vsmile_state::bank1_r));
@@ -759,8 +746,8 @@ void spg2xx_cart_state::machine_start()
if (m_cart && m_cart->exists())
{
std::string region_tag;
- m_cart_rom = memregion(region_tag.assign(m_cart->tag()).append(GENERIC_ROM_REGION_TAG).c_str());
- m_bank->configure_entries(0, ceilf((float)m_cart_rom->bytes() / 0x800000), m_cart_rom->base(), 0x800000);
+ m_cart_region = memregion(region_tag.assign(m_cart->tag()).append(GENERIC_ROM_REGION_TAG).c_str());
+ m_bank->configure_entries(0, ceilf((float)m_cart_region->bytes() / 0x800000), m_cart_region->base(), 0x800000);
m_bank->set_entry(0);
}
}
@@ -771,22 +758,7 @@ void vsmile_state::machine_start()
if (m_cart && m_cart->exists())
{
std::string region_tag;
- m_cart_rom = memregion(region_tag.assign(m_cart->tag()).append(GENERIC_ROM_REGION_TAG).c_str());
- const uint32_t banks = (m_cart_rom->bytes() + 0x1fffff) / 0x200000;
- for (uint32_t i = 0; i < 2; i++)
- {
- m_cart_banks[i]->configure_entries(0, banks, m_cart_rom->base(), 0x200000);
- m_cart_banks[i]->set_entry(i % banks);
- }
- }
- else
- {
- for (uint32_t i = 0; i < 2; i++)
- {
- m_cart_rom = memregion("maincpu");
- m_cart_banks[i]->configure_entries(0, (m_cart_rom->bytes() + 0x1fffff) / 0x200000, m_cart_rom->base(), 0x200000);
- m_cart_banks[i]->set_entry(0);
- }
+ m_cart_region = memregion(region_tag.assign(m_cart->tag()).append(GENERIC_ROM_REGION_TAG).c_str());
}
m_bankdev->set_bank(m_cart && m_cart->exists() ? 4 : 0);