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.cpp840
1 files changed, 457 insertions, 383 deletions
diff --git a/src/devices/cpu/unsp/unsp.cpp b/src/devices/cpu/unsp/unsp.cpp
index af964f713f9..7d1359896af 100644
--- a/src/devices/cpu/unsp/unsp.cpp
+++ b/src/devices/cpu/unsp/unsp.cpp
@@ -14,28 +14,41 @@
#include "emu.h"
#include "unsp.h"
-#include "unspdasm.h"
+#include "unspfe.h"
+
#include "debugger.h"
+#include "unspdefs.h"
+#include "unspdasm.h"
+
DEFINE_DEVICE_TYPE(UNSP, unsp_device, "unsp", "SunPlus u'nSP")
+/* size of the execution code cache */
+#define CACHE_SIZE (64 * 1024 * 1024)
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_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_core(nullptr)
, m_debugger_temp(0)
-#if UNSP_LOG_OPCODES
+#if UNSP_LOG_OPCODES || UNSP_LOG_REGS
, m_log_ops(0)
#endif
+ , m_cache(CACHE_SIZE + sizeof(unsp_device))
+ , m_drcuml(nullptr)
+ , m_drcfe(nullptr)
+ , m_drcoptions(0)
+ , m_cache_dirty(0)
+ , m_entry(nullptr)
+ , m_nocode(nullptr)
+ , m_out_of_cycles(nullptr)
+ , m_check_interrupts(nullptr)
+ , m_trigger_fiq(nullptr)
+ , m_trigger_irq(nullptr)
+ , m_mem_read(nullptr)
+ , m_mem_write(nullptr)
+ , m_enable_drc(false)
{
}
@@ -51,29 +64,6 @@ std::unique_ptr<util::disasm_interface> unsp_device::create_disassembler()
return std::make_unique<unsp_disassembler>();
}
-
-/*****************************************************************************/
-
-#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 UNSP_LPC (((UNSP_REG(SR) & 0x3f) << 16) | UNSP_REG(PC))
-
-#define UNSP_REG(reg) m_r[UNSP_##reg - 1]
-#define UNSP_REG_I(reg) m_r[reg]
-#define UNSP_LREG_I(reg) (((UNSP_REG(SR) << 6) & 0x3f0000) | UNSP_REG_I(reg))
-
-#define UNSP_N 0x0200
-#define UNSP_Z 0x0100
-#define UNSP_S 0x0080
-#define UNSP_C 0x0040
-
-/*****************************************************************************/
-
void unsp_device::unimplemented_opcode(uint16_t op)
{
fatalerror("UNSP: unknown opcode %04x at %04x\n", op, UNSP_LPC);
@@ -88,6 +78,9 @@ uint16_t unsp_device::read16(uint32_t address)
void unsp_device::write16(uint32_t address, uint16_t data)
{
+#if UNSP_LOG_REGS
+ log_write(address, data);
+#endif
m_program->write_word(address, data);
}
@@ -95,60 +88,141 @@ void unsp_device::write16(uint32_t address, uint16_t data)
void unsp_device::device_start()
{
- memset(m_r, 0, sizeof(uint16_t) * 16);
- m_enable_irq = false;
- m_enable_fiq = false;
- m_irq = false;
- m_fiq = false;
- m_curirq = 0;
- m_sirq = 0;
- m_sb = 0;
- memset(m_saved_sb, 0, sizeof(uint8_t) * 3);
+ m_core = (internal_unsp_state *)m_cache.alloc_near(sizeof(internal_unsp_state));
+ memset(m_core, 0, sizeof(internal_unsp_state));
+
+#if ENABLE_UNSP_DRC
+ m_enable_drc = allow_drc();
+#else
+ m_enable_drc = false;
+#endif
+
+#if UNSP_LOG_REGS
+ if (m_enable_drc)
+ m_log_file = fopen("unsp_drc.bin", "wb");
+ else
+ m_log_file = fopen("unsp_interp.bin", "wb");
+#endif
+
m_debugger_temp = 0;
m_program = &space(AS_PROGRAM);
-
- state_add(STATE_GENFLAGS, "GENFLAGS", UNSP_REG(SR)).callimport().callexport().formatstr("%4s").noshow();
- 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");
+ auto cache = m_program->cache<1, -1, ENDIANNESS_BIG>();
+ m_pr16 = [cache](offs_t address) -> u16 { return cache->read_word(address); };
+ m_prptr = [cache](offs_t address) -> const void * { return cache->read_ptr(address); };
+
+ uint32_t umlflags = 0;
+ m_drcuml = std::make_unique<drcuml_state>(*this, m_cache, umlflags, 1, 23, 0);
+
+ // add UML symbols-
+ m_drcuml->symbol_add(&m_core->m_r[REG_SP], sizeof(uint32_t), "SP");
+ m_drcuml->symbol_add(&m_core->m_r[REG_R1], sizeof(uint32_t), "R1");
+ m_drcuml->symbol_add(&m_core->m_r[REG_R2], sizeof(uint32_t), "R2");
+ m_drcuml->symbol_add(&m_core->m_r[REG_R3], sizeof(uint32_t), "R3");
+ m_drcuml->symbol_add(&m_core->m_r[REG_R4], sizeof(uint32_t), "R4");
+ m_drcuml->symbol_add(&m_core->m_r[REG_BP], sizeof(uint32_t), "BP");
+ m_drcuml->symbol_add(&m_core->m_r[REG_SR], sizeof(uint32_t), "SR");
+ m_drcuml->symbol_add(&m_core->m_r[REG_PC], sizeof(uint32_t), "PC");
+ m_drcuml->symbol_add(&m_core->m_enable_irq, sizeof(uint32_t), "IRQE");
+ m_drcuml->symbol_add(&m_core->m_enable_fiq, sizeof(uint32_t), "FIQE");
+ m_drcuml->symbol_add(&m_core->m_irq, sizeof(uint32_t), "IRQ");
+ m_drcuml->symbol_add(&m_core->m_fiq, sizeof(uint32_t), "FIQ");
+ m_drcuml->symbol_add(&m_core->m_sb, sizeof(uint32_t), "SB");
+ m_drcuml->symbol_add(&m_core->m_icount, sizeof(m_core->m_icount), "icount");
+
+ /* initialize the front-end helper */
+ m_drcfe = std::make_unique<unsp_frontend>(this, COMPILE_BACKWARDS_BYTES, COMPILE_FORWARDS_BYTES, SINGLE_INSTRUCTION_MODE ? 1 : COMPILE_MAX_SEQUENCE);
+
+ /* mark the cache dirty so it is updated on next execute */
+ m_cache_dirty = true;
+
+ // register our state for the debugger
+ state_add(STATE_GENFLAGS, "GENFLAGS", m_core->m_r[REG_SR]).callimport().callexport().formatstr("%4s").noshow();
+ state_add(UNSP_SP, "SP", m_core->m_r[REG_SP]).formatstr("%04X");
+ state_add(UNSP_R1, "R1", m_core->m_r[REG_R1]).formatstr("%04X");
+ state_add(UNSP_R2, "R2", m_core->m_r[REG_R2]).formatstr("%04X");
+ state_add(UNSP_R3, "R3", m_core->m_r[REG_R3]).formatstr("%04X");
+ state_add(UNSP_R4, "R4", m_core->m_r[REG_R4]).formatstr("%04X");
+ state_add(UNSP_BP, "BP", m_core->m_r[REG_BP]).formatstr("%04X");
+ state_add(UNSP_SR, "SR", m_core->m_r[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");
-#if UNSP_LOG_OPCODES
+ state_add(UNSP_IRQ_EN, "IRQE", m_core->m_enable_irq).formatstr("%1u");
+ state_add(UNSP_FIQ_EN, "FIQE", m_core->m_enable_fiq).formatstr("%1u");
+ state_add(UNSP_IRQ, "IRQ", m_core->m_irq).formatstr("%1u");
+ state_add(UNSP_FIQ, "FIQ", m_core->m_fiq).formatstr("%1u");
+ state_add(UNSP_SB, "SB", m_core->m_sb).formatstr("%1u");
+#if UNSP_LOG_OPCODES || UNSP_LOG_REGS
state_add(UNSP_LOG_OPS,"LOG", m_log_ops).formatstr("%1u");
#endif
state_add(STATE_GENPC, "GENPC", m_debugger_temp).callexport().noshow();
state_add(STATE_GENPCBASE, "CURPC", m_debugger_temp).callexport().noshow();
- set_icountptr(m_icount);
-
- save_item(NAME(m_r));
- save_item(NAME(m_enable_irq));
- save_item(NAME(m_enable_fiq));
- save_item(NAME(m_irq));
- save_item(NAME(m_fiq));
- save_item(NAME(m_curirq));
- save_item(NAME(m_sirq));
- save_item(NAME(m_sb));
- save_item(NAME(m_saved_sb));
+ save_item(NAME(m_core->m_r));
+ save_item(NAME(m_core->m_enable_irq));
+ save_item(NAME(m_core->m_enable_fiq));
+ save_item(NAME(m_core->m_irq));
+ save_item(NAME(m_core->m_fiq));
+ save_item(NAME(m_core->m_curirq));
+ save_item(NAME(m_core->m_sirq));
+ save_item(NAME(m_core->m_sb));
+ save_item(NAME(m_core->m_saved_sb));
+
+ set_icountptr(m_core->m_icount);
+}
+
+void unsp_device::device_reset()
+{
+ memset(m_core->m_r, 0, sizeof(uint32_t) * 8);
+
+ m_core->m_r[REG_PC] = read16(0xfff7);
+ m_core->m_enable_irq = 0;
+ m_core->m_enable_fiq = 0;
+ m_core->m_irq = 0;
+ m_core->m_fiq = 0;
}
+void unsp_device::device_stop()
+{
+ if (m_drcfe != nullptr)
+ {
+ m_drcfe = nullptr;
+ }
+ if (m_drcuml != nullptr)
+ {
+ m_drcuml = nullptr;
+ }
+#if UNSP_LOG_REGS
+ fclose(m_log_file);
+#endif
+}
+
+#if UNSP_LOG_REGS
+void unsp_device::log_regs()
+{
+ if (m_log_ops == 0)
+ return;
+ fwrite(m_core->m_r, sizeof(uint32_t), 8, m_log_file);
+ fwrite(&m_core->m_sb, sizeof(uint32_t), 1, m_log_file);
+ fwrite(&m_core->m_icount, sizeof(uint32_t), 1, m_log_file);
+}
+
+void unsp_device::log_write(uint32_t addr, uint32_t data)
+{
+ addr |= 0x80000000;
+ fwrite(&addr, sizeof(uint32_t), 1, m_log_file);
+ fwrite(&data, sizeof(uint32_t), 1, m_log_file);
+}
+
+#endif
+
void unsp_device::state_string_export(const device_state_entry &entry, std::string &str) const
{
switch (entry.index())
{
case STATE_GENFLAGS:
{
- const uint16_t sr = UNSP_REG(SR);
+ const uint16_t sr = m_core->m_r[REG_SR];
str = string_format("%c%c%c%c", (sr & UNSP_N) ? 'N' : ' ', (sr & UNSP_Z) ? 'Z' : ' ', (sr & UNSP_S) ? 'S' : ' ', (sr & UNSP_C) ? 'C' : ' ');
}
}
@@ -171,105 +245,91 @@ void unsp_device::state_import(const device_state_entry &entry)
switch (entry.index())
{
case UNSP_PC:
- UNSP_REG(PC) = m_debugger_temp & 0x0000ffff;
- UNSP_REG(SR) = (UNSP_REG(SR) & 0xffc0) | ((m_debugger_temp & 0x003f0000) >> 16);
+ m_core->m_r[REG_PC] = m_debugger_temp & 0x0000ffff;
+ m_core->m_r[REG_SR] = (m_core->m_r[REG_SR] & 0xffc0) | ((m_debugger_temp & 0x003f0000) >> 16);
break;
}
}
-void unsp_device::device_reset()
-{
- memset(m_r, 0, sizeof(uint16_t) * 16);
-
- UNSP_REG(PC) = read16(0xfff7);
- m_enable_irq = false;
- m_enable_fiq = false;
- m_irq = false;
- m_fiq = false;
-}
-
/*****************************************************************************/
-void unsp_device::update_nz(uint32_t value)
+void unsp_device::update_nzsc(uint32_t value, uint16_t r0, uint16_t r1)
{
- UNSP_REG(SR) &= ~(UNSP_N | UNSP_Z);
- if(value & 0x8000)
- {
- UNSP_REG(SR) |= UNSP_N;
- }
+ m_core->m_r[REG_SR] &= ~(UNSP_N | UNSP_Z | UNSP_S | UNSP_C);
+ if (int16_t(r0) < int16_t(~r1))
+ m_core->m_r[REG_SR] |= UNSP_S;
+ if (BIT(value, 15))
+ m_core->m_r[REG_SR] |= UNSP_N;
if((uint16_t)value == 0)
- {
- UNSP_REG(SR) |= UNSP_Z;
- }
+ m_core->m_r[REG_SR] |= UNSP_Z;
+ if (BIT(value, 16))
+ m_core->m_r[REG_SR] |= UNSP_C;
}
-void unsp_device::update_sc(uint32_t value, uint16_t r0, uint16_t r1)
+void unsp_device::update_nz(uint32_t value)
{
- UNSP_REG(SR) &= ~(UNSP_C | UNSP_S);
- if(value != (uint16_t)value)
- {
- UNSP_REG(SR) |= UNSP_C;
- }
-
- if((int16_t)r0 < (int16_t)r1)
- {
- UNSP_REG(SR) |= UNSP_S;
- }
+ m_core->m_r[REG_SR] &= ~(UNSP_N | UNSP_Z);
+ if(value & 0x8000)
+ m_core->m_r[REG_SR] |= UNSP_N;
+ if((uint16_t)value == 0)
+ m_core->m_r[REG_SR] |= UNSP_Z;
}
-void unsp_device::push(uint16_t value, uint16_t *reg)
+void unsp_device::push(uint32_t value, uint32_t *reg)
{
- write16((*reg)--, value);
+ write16(*reg, (uint16_t)value);
+ *reg = (uint16_t)(*reg - 1);
}
-uint16_t unsp_device::pop(uint16_t *reg)
+uint16_t unsp_device::pop(uint32_t *reg)
{
- return read16(++(*reg));
+ *reg = (uint16_t)(*reg + 1);
+ return (uint16_t)read16(*reg);
}
void unsp_device::trigger_fiq()
{
- if (!m_enable_fiq || m_fiq || m_irq)
+ if (!m_core->m_enable_fiq || m_core->m_fiq || m_core->m_irq)
{
return;
}
- m_fiq = true;
+ m_core->m_fiq = 1;
- m_saved_sb[m_irq ? 1 : 0] = m_sb;
- m_sb = m_saved_sb[2];
+ m_core->m_saved_sb[m_core->m_irq ? 1 : 0] = m_core->m_sb;
+ m_core->m_sb = m_core->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;
+ push(m_core->m_r[REG_PC], &m_core->m_r[REG_SP]);
+ push(m_core->m_r[REG_SR], &m_core->m_r[REG_SP]);
+ m_core->m_r[REG_PC] = read16(0xfff6);
+ m_core->m_r[REG_SR] = 0;
}
void unsp_device::trigger_irq(int line)
{
- if (!m_enable_irq || m_irq || m_fiq)
+ if (!m_core->m_enable_irq || m_core->m_irq || m_core->m_fiq)
return;
- m_irq = true;
+ m_core->m_irq = 1;
- m_saved_sb[0] = m_sb;
- m_sb = m_saved_sb[1];
+ m_core->m_saved_sb[0] = m_core->m_sb;
+ m_core->m_sb = m_core->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;
+ push(m_core->m_r[REG_PC], &m_core->m_r[REG_SP]);
+ push(m_core->m_r[REG_SR], &m_core->m_r[REG_SP]);
+ m_core->m_r[REG_PC] = read16(0xfff8 + line);
+ m_core->m_r[REG_SR] = 0;
}
void unsp_device::check_irqs()
{
- if (!m_sirq)
+ if (!m_core->m_sirq)
return;
int highest_irq = -1;
for (int i = 0; i <= 8; i++)
{
- if (BIT(m_sirq, i))
+ if (BIT(m_core->m_sirq, i))
{
highest_irq = i;
break;
@@ -285,9 +345,9 @@ void unsp_device::check_irqs()
void unsp_device::add_lpc(const int32_t offset)
{
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;
+ m_core->m_r[REG_PC] = (uint16_t)new_lpc;
+ m_core->m_r[REG_SR] &= 0xffc0;
+ m_core->m_r[REG_SR] |= (new_lpc >> 16) & 0x3f;
}
inline void unsp_device::execute_one(const uint16_t op)
@@ -297,147 +357,154 @@ inline void unsp_device::execute_one(const uint16_t op)
uint16_t r1 = 0;
uint32_t r2 = 0;
- const uint8_t lower_op = (OP1 << 4) | OP0;
+ const uint16_t op0 = (op >> 12) & 15;
+ const uint16_t opa = (op >> 9) & 7;
+ const uint16_t op1 = (op >> 6) & 7;
+ const uint16_t opn = (op >> 3) & 7;
+ const uint16_t opb = op & 7;
+
+ const uint8_t lower_op = (op1 << 4) | op0;
- if(OP0 < 0xf && OPA == 0x7 && OP1 < 2)
+ if(op0 < 0xf && opa == 0x7 && op1 < 2)
{
- switch(OP0)
+ const uint32_t opimm = op & 0x3f;
+ switch(op0)
{
case 0: // JB
- if(!(UNSP_REG(SR) & UNSP_C))
+ if(!(m_core->m_r[REG_SR] & UNSP_C))
{
- m_icount -= 4;
- add_lpc((OP1 == 0) ? OPIMM : (0 - OPIMM));
+ m_core->m_icount -= 4;
+ add_lpc((op1 == 0) ? opimm : (0 - opimm));
}
else
{
- m_icount -= 2;
+ m_core->m_icount -= 2;
}
return;
case 1: // JAE
- if(UNSP_REG(SR) & UNSP_C)
+ if(m_core->m_r[REG_SR] & UNSP_C)
{
- m_icount -= 4;
- add_lpc((OP1 == 0) ? OPIMM : (0 - OPIMM));
+ m_core->m_icount -= 4;
+ add_lpc((op1 == 0) ? opimm : (0 - opimm));
}
else
{
- m_icount -= 2;
+ m_core->m_icount -= 2;
}
return;
case 2: // JGE
- if(!(UNSP_REG(SR) & UNSP_S))
+ if(!(m_core->m_r[REG_SR] & UNSP_S))
{
- m_icount -= 4;
- add_lpc((OP1 == 0) ? OPIMM : (0 - OPIMM));
+ m_core->m_icount -= 4;
+ add_lpc((op1 == 0) ? opimm : (0 - opimm));
}
else
{
- m_icount -= 2;
+ m_core->m_icount -= 2;
}
return;
case 3: // JL
- if(UNSP_REG(SR) & UNSP_S)
+ if(m_core->m_r[REG_SR] & UNSP_S)
{
- m_icount -= 4;
- add_lpc((OP1 == 0) ? OPIMM : (0 - OPIMM));
+ m_core->m_icount -= 4;
+ add_lpc((op1 == 0) ? opimm : (0 - opimm));
}
else
{
- m_icount -= 2;
+ m_core->m_icount -= 2;
}
return;
case 4: // JNE
- if(!(UNSP_REG(SR) & UNSP_Z))
+ if(!(m_core->m_r[REG_SR] & UNSP_Z))
{
- m_icount -= 4;
- add_lpc((OP1 == 0) ? OPIMM : (0 - OPIMM));
+ m_core->m_icount -= 4;
+ add_lpc((op1 == 0) ? opimm : (0 - opimm));
}
else
{
- m_icount -= 2;
+ m_core->m_icount -= 2;
}
return;
case 5: // JE
- if(UNSP_REG(SR) & UNSP_Z)
+ if(m_core->m_r[REG_SR] & UNSP_Z)
{
- m_icount -= 4;
- add_lpc((OP1 == 0) ? OPIMM : (0 - OPIMM));
+ m_core->m_icount -= 4;
+ add_lpc((op1 == 0) ? opimm : (0 - opimm));
}
else
{
- m_icount -= 2;
+ m_core->m_icount -= 2;
}
return;
case 6: // JPL
- if(!(UNSP_REG(SR) & UNSP_N))
+ if(!(m_core->m_r[REG_SR] & UNSP_N))
{
- m_icount -= 4;
- add_lpc((OP1 == 0) ? OPIMM : (0 - OPIMM));
+ m_core->m_icount -= 4;
+ add_lpc((op1 == 0) ? opimm : (0 - opimm));
}
else
{
- m_icount -= 2;
+ m_core->m_icount -= 2;
}
return;
case 7: // JMI
- if(UNSP_REG(SR) & UNSP_N)
+ if(m_core->m_r[REG_SR] & UNSP_N)
{
- m_icount -= 4;
- add_lpc((OP1 == 0) ? OPIMM : (0 - OPIMM));
+ m_core->m_icount -= 4;
+ add_lpc((op1 == 0) ? opimm : (0 - opimm));
}
else
{
- m_icount -= 2;
+ m_core->m_icount -= 2;
}
return;
case 8: // JBE
- if((UNSP_REG(SR) & (UNSP_Z | UNSP_C)) != UNSP_C)
+ if((m_core->m_r[REG_SR] & (UNSP_Z | UNSP_C)) != UNSP_C) // branch if (!UNSP_Z && !UNSP_C) || UNSP_Z
{
- m_icount -= 4;
- add_lpc((OP1 == 0) ? OPIMM : (0 - OPIMM));
+ m_core->m_icount -= 4;
+ add_lpc((op1 == 0) ? opimm : (0 - opimm));
}
else
{
- m_icount -= 2;
+ m_core->m_icount -= 2;
}
return;
case 9: // JA
- if((UNSP_REG(SR) & (UNSP_Z | UNSP_C)) == UNSP_C)
+ if((m_core->m_r[REG_SR] & (UNSP_Z | UNSP_C)) == UNSP_C) // branch if !UNSP_Z && UNSP_C
{
- m_icount -= 4;
- add_lpc((OP1 == 0) ? OPIMM : (0 - OPIMM));
+ m_core->m_icount -= 4;
+ add_lpc((op1 == 0) ? opimm : (0 - opimm));
}
else
{
- m_icount -= 2;
+ m_core->m_icount -= 2;
}
return;
case 10: // JLE
- if(UNSP_REG(SR) & (UNSP_Z | UNSP_S))
+ if(m_core->m_r[REG_SR] & (UNSP_Z | UNSP_S))
{
- m_icount -= 4;
- add_lpc((OP1 == 0) ? OPIMM : (0 - OPIMM));
+ m_core->m_icount -= 4;
+ add_lpc((op1 == 0) ? opimm : (0 - opimm));
}
else
{
- m_icount -= 2;
+ m_core->m_icount -= 2;
}
return;
case 11: // JG
- if(!(UNSP_REG(SR) & (UNSP_Z | UNSP_S)))
+ if(!(m_core->m_r[REG_SR] & (UNSP_Z | UNSP_S)))
{
- m_icount -= 4;
- add_lpc((OP1 == 0) ? OPIMM : (0 - OPIMM));
+ m_core->m_icount -= 4;
+ add_lpc((op1 == 0) ? opimm : (0 - opimm));
}
else
{
- m_icount -= 2;
+ m_core->m_icount -= 2;
}
return;
case 14: // JMP
- add_lpc((OP1 == 0) ? OPIMM : (0 - OPIMM));
- m_icount -= 4;
+ add_lpc((op1 == 0) ? opimm : (0 - opimm));
+ m_core->m_icount -= 4;
return;
default:
unimplemented_opcode(op);
@@ -446,69 +513,68 @@ inline void unsp_device::execute_one(const uint16_t op)
}
else if (lower_op == 0x2d) // Push
{
- r0 = OPN;
- r1 = OPA;
- m_icount -= 4 + 2 * r0;
+ r0 = opn;
+ r1 = opa;
+ m_core->m_icount -= 4 + 2 * r0;
while (r0--)
{
- push(UNSP_REG_I(r1--), &UNSP_REG_I(OPB));
+ push(m_core->m_r[r1--], &m_core->m_r[opb]);
}
return;
}
- else if (lower_op == 0x29) // Pop
+ else if (lower_op == 0x29)
{
if (op == 0x9a98) // reti
{
- m_icount -= 8;
- UNSP_REG(SR) = pop(&UNSP_REG(SP));
- UNSP_REG(PC) = pop(&UNSP_REG(SP));
+ m_core->m_icount -= 8;
+ 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_fiq)
+ if(m_core->m_fiq)
{
- m_fiq = false;
- m_saved_sb[2] = m_sb;
- m_sb = m_saved_sb[m_irq ? 1 : 0];
+ 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_irq)
+ else if(m_core->m_irq)
{
- m_irq = false;
- m_saved_sb[1] = m_sb;
- m_sb = m_saved_sb[0];
+ 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_curirq = 0;
-
+ m_core->m_curirq = 0;
check_irqs();
return;
}
- else
+ else // pop
{
- r0 = OPN;
- r1 = OPA;
- m_icount -= 4 + 2 * r0;
+ r0 = opn;
+ r1 = opa;
+ m_core->m_icount -= 4 + 2 * r0;
while (r0--)
{
- UNSP_REG_I(++r1) = pop(&UNSP_REG_I(OPB));
+ m_core->m_r[++r1] = pop(&m_core->m_r[opb]);
}
return;
}
}
- else if (OP0 == 0xf)
+ else if (op0 == 0xf)
{
- switch (OP1)
+ switch (op1)
{
case 0x00: // Multiply, Unsigned * Signed
- if(OPN == 1 && OPA != 7)
+ if(opn == 1 && opa != 7)
{
- m_icount -= 12;
- lres = UNSP_REG_I(OPA) * UNSP_REG_I(OPB);
- if(UNSP_REG_I(OPB) & 0x8000)
+ m_core->m_icount -= 12;
+ lres = m_core->m_r[opa] * m_core->m_r[opb];
+ if(m_core->m_r[opb] & 0x8000)
{
- lres -= UNSP_REG_I(OPA) << 16;
+ lres -= m_core->m_r[opa] << 16;
}
- UNSP_REG(R4) = lres >> 16;
- UNSP_REG(R3) = (uint16_t)lres;
+ m_core->m_r[REG_R4] = lres >> 16;
+ m_core->m_r[REG_R3] = (uint16_t)lres;
}
else
{
@@ -517,16 +583,16 @@ inline void unsp_device::execute_one(const uint16_t op)
return;
case 0x01: // Call
- if(!(OPA & 1))
+ if(!(opa & 1))
{
- m_icount -= 9;
+ m_core->m_icount -= 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;
+ push(m_core->m_r[REG_PC], &m_core->m_r[REG_SP]);
+ push(m_core->m_r[REG_SR], &m_core->m_r[REG_SP]);
+ m_core->m_r[REG_PC] = r1;
+ m_core->m_r[REG_SR] &= 0xffc0;
+ m_core->m_r[REG_SR] |= op & 0x3f;
}
else
{
@@ -535,12 +601,12 @@ inline void unsp_device::execute_one(const uint16_t op)
return;
case 0x02: // Far Jump
- if (OPA == 7)
+ if (opa == 7)
{
- m_icount -= 5;
- UNSP_REG(PC) = read16(UNSP_LPC);
- UNSP_REG(SR) &= 0xffc0;
- UNSP_REG(SR) |= OPIMM;
+ m_core->m_icount -= 5;
+ m_core->m_r[REG_PC] = read16(UNSP_LPC);
+ m_core->m_r[REG_SR] &= 0xffc0;
+ m_core->m_r[REG_SR] |= op & 0x3f;
}
else
{
@@ -549,20 +615,20 @@ inline void unsp_device::execute_one(const uint16_t op)
return;
case 0x04: // Multiply, Signed * Signed
- if(OPN == 1 && OPA != 7)
+ if(opn == 1 && opa != 7)
{
- m_icount -= 12;
- lres = UNSP_REG_I(OPA) * UNSP_REG_I(OPB);
- if(UNSP_REG_I(OPB) & 0x8000)
+ m_core->m_icount -= 12;
+ lres = m_core->m_r[opa] * m_core->m_r[opb];
+ if(m_core->m_r[opb] & 0x8000)
{
- lres -= UNSP_REG_I(OPA) << 16;
+ lres -= m_core->m_r[opa] << 16;
}
- if(UNSP_REG_I(OPA) & 0x8000)
+ if(m_core->m_r[opa] & 0x8000)
{
- lres -= UNSP_REG_I(OPB) << 16;
+ lres -= m_core->m_r[opb] << 16;
}
- UNSP_REG(R4) = lres >> 16;
- UNSP_REG(R3) = (uint16_t)lres;
+ m_core->m_r[REG_R4] = lres >> 16;
+ m_core->m_r[REG_R3] = (uint16_t)lres;
}
else
{
@@ -571,36 +637,36 @@ inline void unsp_device::execute_one(const uint16_t op)
return;
case 0x05: // Interrupt flags
- m_icount -= 2;
- switch(OPIMM)
+ m_core->m_icount -= 2;
+ switch(op & 0x3f)
{
case 0:
- m_enable_irq = false;
- m_enable_fiq = false;
+ m_core->m_enable_irq = 0;
+ m_core->m_enable_fiq = 0;
break;
case 1:
- m_enable_irq = true;
- m_enable_fiq = false;
+ m_core->m_enable_irq = 1;
+ m_core->m_enable_fiq = 0;
break;
case 2:
- m_enable_irq = false;
- m_enable_fiq = true;
+ m_core->m_enable_irq = 0;
+ m_core->m_enable_fiq = 1;
break;
case 3:
- m_enable_irq = true;
- m_enable_fiq = true;
+ m_core->m_enable_irq = 1;
+ m_core->m_enable_fiq = 1;
break;
case 8: // irq off
- m_enable_irq = false;
+ m_core->m_enable_irq = 0;
break;
case 9: // irq on
- m_enable_irq = true;
+ m_core->m_enable_irq = 1;
break;
case 12: // fiq off
- m_enable_fiq = false;
+ m_core->m_enable_fiq = 0;
break;
case 14: // fiq on
- m_enable_fiq = true;
+ m_core->m_enable_fiq = 1;
break;
case 37: // nop
break;
@@ -618,65 +684,61 @@ inline void unsp_device::execute_one(const uint16_t op)
// At this point, we should be dealing solely with ALU ops.
- r0 = UNSP_REG_I(OPA);
+ r0 = m_core->m_r[opa];
- switch (OP1)
+ switch (op1)
{
case 0x00: // r, [bp+imm6]
- m_icount -= 6;
+ m_core->m_icount -= 6;
- r2 = (uint16_t)(UNSP_REG(BP) + OPIMM);
- if (OP0 != 0x0d)
+ r2 = (uint16_t)(m_core->m_r[REG_BP] + (op & 0x3f));
+ if (op0 != 0x0d)
r1 = read16(r2);
break;
case 0x01: // r, imm6
- m_icount -= 2;
+ m_core->m_icount -= 2;
- r1 = OPIMM;
+ r1 = op & 0x3f;
break;
case 0x03: // Indirect
{
- m_icount -= 6;
- if (OPA == 7)
- {
- m_icount -= 1;
- }
+ m_core->m_icount -= (opa == 7 ? 7 : 6);
- const uint8_t lsbits = OPN & 3;
- const uint8_t opb = OPB;
- if (OPN & 4)
+ const uint8_t lsbits = opn & 3;
+ if (opn & 4)
{
switch (lsbits)
{
- case 0: // r, [r]
+ case 0: // r, [<ds:>r]
r2 = UNSP_LREG_I(opb);
- if (OP0 != 0x0d)
+ if (op0 != 0x0d)
r1 = read16(r2);
break;
+
case 1: // r, [<ds:>r--]
r2 = UNSP_LREG_I(opb);
- if (OP0 != 0x0d)
+ if (op0 != 0x0d)
r1 = read16(r2);
- UNSP_REG_I(opb)--;
- if (UNSP_REG_I(opb) == 0xffff)
- UNSP_REG(SR) -= 0x0400;
+ m_core->m_r[opb] = (uint16_t)(m_core->m_r[opb] - 1);
+ if (m_core->m_r[opb] == 0xffff)
+ m_core->m_r[REG_SR] -= 0x0400;
break;
case 2: // r, [<ds:>r++]
r2 = UNSP_LREG_I(opb);
- if (OP0 != 0x0d)
+ if (op0 != 0x0d)
r1 = read16(r2);
- UNSP_REG_I(opb)++;
- if (UNSP_REG_I(opb) == 0x0000)
- UNSP_REG(SR) += 0x0400;
+ m_core->m_r[opb] = (uint16_t)(m_core->m_r[opb] + 1);
+ if (m_core->m_r[opb] == 0x0000)
+ m_core->m_r[REG_SR] += 0x0400;
break;
case 3: // r, [<ds:>++r]
- UNSP_REG_I(opb)++;
- if (UNSP_REG_I(opb) == 0x0000)
- UNSP_REG(SR) += 0x0400;
+ m_core->m_r[opb] = (uint16_t)(m_core->m_r[opb] + 1);
+ if (m_core->m_r[opb] == 0x0000)
+ m_core->m_r[REG_SR] += 0x0400;
r2 = UNSP_LREG_I(opb);
- if (OP0 != 0x0d)
+ if (op0 != 0x0d)
r1 = read16(r2);
break;
default:
@@ -688,26 +750,26 @@ inline void unsp_device::execute_one(const uint16_t op)
switch (lsbits)
{
case 0: // r, [r]
- r2 = UNSP_REG_I(opb);
- if (OP0 != 0x0d)
+ r2 = m_core->m_r[opb];
+ if (op0 != 0x0d)
r1 = read16(r2);
break;
case 1: // r, [r--]
- r2 = UNSP_REG_I(opb);
- if (OP0 != 0x0d)
+ r2 = m_core->m_r[opb];
+ if (op0 != 0x0d)
r1 = read16(r2);
- UNSP_REG_I(opb)--;
+ m_core->m_r[opb] = (uint16_t)(m_core->m_r[opb] - 1);
break;
case 2: // r, [r++]
- r2 = UNSP_REG_I(opb);
- if (OP0 != 0x0d)
+ r2 = m_core->m_r[opb];
+ if (op0 != 0x0d)
r1 = read16(r2);
- UNSP_REG_I(opb)++;
+ m_core->m_r[opb] = (uint16_t)(m_core->m_r[opb] + 1);
break;
case 3: // r, [++r]
- UNSP_REG_I(opb)++;
- r2 = UNSP_REG_I(opb);
- if (OP0 != 0x0d)
+ m_core->m_r[opb] = (uint16_t)(m_core->m_r[opb] + 1);
+ r2 = m_core->m_r[opb];
+ if (op0 != 0x0d)
r1 = read16(r2);
break;
default:
@@ -718,73 +780,48 @@ inline void unsp_device::execute_one(const uint16_t op)
}
case 0x04: // 16-bit ops
- switch (OPN)
+ switch (opn)
{
case 0x00: // r
- m_icount -= 3;
- if (OPA == 7)
- {
- m_icount -= 2;
- }
-
- r1 = UNSP_REG_I(OPB);
+ m_core->m_icount -= (opa == 7 ? 5 : 3);
+ r1 = m_core->m_r[opb];
break;
case 0x01: // imm16
- m_icount -= 4;
- if (OPA == 7)
- {
- m_icount -= 1;
- }
-
- r0 = UNSP_REG_I(OPB);
+ m_core->m_icount -= (opa == 7 ? 5 : 4);
+ r0 = m_core->m_r[opb];
r1 = read16(UNSP_LPC);
add_lpc(1);
break;
case 0x02: // [imm16]
- m_icount -= 7;
- if (OPA == 7)
- {
- m_icount -= 1;
- }
-
- r0 = UNSP_REG_I(OPB);
+ m_core->m_icount -= (opa == 7 ? 8 : 7);
+ r0 = m_core->m_r[opb];
r2 = read16(UNSP_LPC);
add_lpc(1);
- if (OP0 != 0x0d)
+ if (op0 != 0x0d)
{
r1 = read16(r2);
}
break;
case 0x03: // store [imm16], r
- m_icount -= 7;
- if (OPA == 7)
- {
- m_icount -= 1;
- }
-
+ m_core->m_icount -= (opa == 7 ? 8 : 7);
r1 = r0;
- r0 = UNSP_REG_I(OPB);
+ r0 = m_core->m_r[opb];
r2 = read16(UNSP_LPC);
add_lpc(1);
break;
default: // Shifted ops
{
- m_icount -= 3;
- if (OPA == 7)
- {
- m_icount -= 2;
- }
-
- uint32_t shift = (UNSP_REG_I(OPB) << 4) | m_sb;
+ m_core->m_icount -= (opa == 7 ? 5 : 3);
+ uint32_t shift = (m_core->m_r[opb] << 4) | m_core->m_sb;
if (shift & 0x80000)
shift |= 0xf00000;
- shift >>= (OPN - 3);
- m_sb = shift & 0x0f;
+ shift >>= (opn - 3);
+ m_core->m_sb = shift & 0x0f;
r1 = (uint16_t)(shift >> 4);
break;
}
@@ -792,99 +829,116 @@ inline void unsp_device::execute_one(const uint16_t op)
break;
case 0x05: // More shifted ops
- m_icount -= 3;
- if (OPA == 7)
- {
- m_icount -= 2;
- }
+ m_core->m_icount -= (opa == 7 ? 5 : 3);
- if (OPN & 4) // Shift right
+ if (opn & 4) // Shift right
{
- const uint32_t shift = ((UNSP_REG_I(OPB) << 4) | m_sb) >> (OPN - 3);
- m_sb = shift & 0x0f;
+ const uint32_t shift = ((m_core->m_r[opb] << 4) | m_core->m_sb) >> (opn - 3);
+ m_core->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;
+ const uint32_t shift = ((m_core->m_sb << 16) | m_core->m_r[opb]) << (opn + 1);
+ m_core->m_sb = (shift >> 16) & 0x0f;
r1 = (uint16_t)shift;
}
break;
case 0x06: // Rotated ops
{
- m_icount -= 3;
- if (OPA == 7)
- {
- m_icount -= 2;
- }
+ m_core->m_icount -= (opa == 7 ? 5 : 3);
- uint32_t shift = (((m_sb << 16) | UNSP_REG_I(OPB)) << 4) | m_sb;
- if (OPN & 4) // Rotate right
+ uint32_t shift = (((m_core->m_sb << 16) | m_core->m_r[opb]) << 4) | m_core->m_sb;
+ if (opn & 4) // Rotate right
{
- shift >>= (OPN - 3);
- m_sb = shift & 0x0f;
+ shift >>= (opn - 3);
+ m_core->m_sb = shift & 0x0f;
}
else
{
- shift <<= (OPN + 1);
- m_sb = (shift >> 20) & 0x0f;
+ shift <<= (opn + 1);
+ m_core->m_sb = (shift >> 20) & 0x0f;
}
r1 = (uint16_t)(shift >> 4);
break;
}
case 0x07: // Direct 8
- m_icount -= 5;
- if (OPA == 7)
- {
- m_icount -= 1;
- }
-
- r2 = OPIMM;
- r1 = read16(OPIMM);
+ m_core->m_icount -= (opa == 7 ? 6 : 5);
+ r2 = op & 0x3f;
+ r1 = read16(r2);
break;
default:
break;
}
- switch (OP0)
+ switch (op0)
{
case 0x00: // Add
+ {
lres = r0 + r1;
+ if (opa != 7)
+ update_nzsc(lres, r0, r1);
break;
+ }
case 0x01: // Add w/ carry
- lres = r0 + r1;
- if(UNSP_REG(SR) & UNSP_C)
- lres++;
+ {
+ uint32_t c = (m_core->m_r[REG_SR] & UNSP_C) ? 1 : 0;
+ lres = r0 + r1 + c;
+ if (opa != 7)
+ update_nzsc(lres, r0, r1);
break;
+ }
case 0x02: // Subtract
- case 0x04: // Compare
- lres = r0 + (uint16_t)(~r1) + 1;
+ lres = r0 + (uint16_t)(~r1) + uint32_t(1);
+ if (opa != 7)
+ update_nzsc(lres, r0, ~r1);
break;
case 0x03: // Subtract w/ carry
- lres = r0 + (uint16_t)(~r1);
- if(UNSP_REG(SR) & UNSP_C)
- lres++;
+ {
+ uint32_t c = (m_core->m_r[REG_SR] & UNSP_C) ? 1 : 0;
+ lres = r0 + (uint16_t)(~r1) + c;
+ if (opa != 7)
+ update_nzsc(lres, r0, ~r1);
break;
+ }
+ case 0x04: // Compare
+ lres = r0 + (uint16_t)(~r1) + uint32_t(1);
+ if (opa != 7)
+ update_nzsc(lres, r0, ~r1);
+ return;
case 0x06: // Negate
lres = -r1;
+ if (opa != 7)
+ update_nz(lres);
break;
case 0x08: // XOR
lres = r0 ^ r1;
+ if (opa != 7)
+ update_nz(lres);
break;
case 0x09: // Load
lres = r1;
+ if (opa != 7)
+ update_nz(lres);
break;
case 0x0a: // OR
lres = r0 | r1;
+ if (opa != 7)
+ update_nz(lres);
break;
case 0x0b: // AND
- case 0x0c: // Test
lres = r0 & r1;
+ if (opa != 7)
+ update_nz(lres);
break;
+ case 0x0c: // Test
+ lres = r0 & r1;
+ if (opa != 7)
+ update_nz(lres);
+ return;
case 0x0d: // Store
write16(r2, r0);
return;
@@ -893,34 +947,33 @@ inline void unsp_device::execute_one(const uint16_t 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
+ if (op1 == 0x04 && opn == 0x03) // store [imm16], r
write16(r2, lres);
else
- UNSP_REG_I(OPA) = lres;
+ m_core->m_r[opa] = (uint16_t)lres;
}
void unsp_device::execute_run()
{
+ if (m_enable_drc)
+ {
+ execute_run_drc();
+ return;
+ }
+
#if UNSP_LOG_OPCODES
unsp_disassembler dasm;
#endif
- while (m_icount > 0)
+ while (m_core->m_icount >= 0)
{
debugger_instruction_hook(UNSP_LPC);
const uint32_t op = read16(UNSP_LPC);
+#if UNSP_LOG_REGS
+ log_regs();
+#endif
+
#if UNSP_LOG_OPCODES
if (m_log_ops)
{
@@ -941,16 +994,26 @@ void unsp_device::execute_run()
/*****************************************************************************/
-void unsp_device::execute_set_input(int irqline, int state)
+void unsp_device::execute_set_input(int inputnum, int state)
+{
+ set_state_unsynced(inputnum, state);
+}
+
+uint8_t unsp_device::get_csb()
+{
+ return 1 << ((UNSP_LPC >> 20) & 3);
+}
+
+void unsp_device::set_state_unsynced(int inputnum, int state)
{
- m_sirq &= ~(1 << irqline);
+ m_core->m_sirq &= ~(1 << inputnum);
if(!state)
{
return;
}
- switch (irqline)
+ switch (inputnum)
{
case UNSP_IRQ0_LINE:
case UNSP_IRQ1_LINE:
@@ -961,9 +1024,20 @@ void unsp_device::execute_set_input(int irqline, int state)
case UNSP_IRQ6_LINE:
case UNSP_IRQ7_LINE:
case UNSP_FIQ_LINE:
- m_sirq |= (1 << irqline);
+ m_core->m_sirq |= (1 << inputnum);
break;
case UNSP_BRK_LINE:
break;
}
}
+
+uint16_t unsp_device::get_ds()
+{
+ return (m_core->m_r[REG_SR] >> 10) & 0x3f;
+}
+
+void unsp_device::set_ds(uint16_t ds)
+{
+ m_core->m_r[REG_SR] &= 0x03ff;
+ m_core->m_r[REG_SR] |= (ds & 0x3f) << 10;
+}