diff options
author | 2019-05-01 00:04:54 +0100 | |
---|---|---|
committer | 2019-04-30 19:04:53 -0400 | |
commit | f8656d9246057c3d266f1a898169e9cd700f4746 (patch) | |
tree | 0b64e0af5bcea886251e2c87678a696a5a359d0e /src | |
parent | dcfacd8df665ced82c57f7ac83a4e0fe54752c8b (diff) |
TV Game Work (progress towards smartfp and wrlshunt) (#4956)
* unsp refactoring / tv game work (nw)
* unsp refactoring / tv game work (nw)
* srcclean (nw)
* more ops (nw)
* (nw)
* (nw)
* guesses (nw)
* more guesses (nw)
* (nw)
Diffstat (limited to 'src')
-rw-r--r-- | src/devices/cpu/unsp/unsp.cpp | 726 | ||||
-rw-r--r-- | src/devices/cpu/unsp/unsp.h | 127 | ||||
-rw-r--r-- | src/devices/cpu/unsp/unsp_extended.cpp | 206 | ||||
-rw-r--r-- | src/devices/cpu/unsp/unsp_exxx.cpp | 161 | ||||
-rw-r--r-- | src/devices/cpu/unsp/unsp_fxxx.cpp | 431 | ||||
-rw-r--r-- | src/devices/cpu/unsp/unsp_jumps.cpp | 160 | ||||
-rw-r--r-- | src/devices/cpu/unsp/unsp_other.cpp | 347 | ||||
-rw-r--r-- | src/devices/cpu/unsp/unspdasm.cpp | 452 | ||||
-rw-r--r-- | src/devices/cpu/unsp/unspdasm.h | 67 | ||||
-rw-r--r-- | src/devices/cpu/unsp/unspdasm_extended.cpp | 193 | ||||
-rw-r--r-- | src/devices/cpu/unsp/unspdasm_exxx.cpp | 117 | ||||
-rw-r--r-- | src/devices/cpu/unsp/unspdasm_fxxx.cpp | 371 | ||||
-rw-r--r-- | src/devices/cpu/unsp/unspdasm_jumps.cpp | 41 | ||||
-rw-r--r-- | src/devices/cpu/unsp/unspdasm_other.cpp | 235 | ||||
-rw-r--r-- | src/devices/cpu/unsp/unspdrc.cpp | 15 | ||||
-rw-r--r-- | src/devices/machine/sunplus_gcm394.cpp | 61 | ||||
-rw-r--r-- | src/devices/machine/sunplus_gcm394.h | 3 | ||||
-rw-r--r-- | src/mame/drivers/clickstart.cpp | 4 | ||||
-rw-r--r-- | src/mame/drivers/sunplus_gcm394.cpp | 7 |
19 files changed, 2653 insertions, 1071 deletions
diff --git a/src/devices/cpu/unsp/unsp.cpp b/src/devices/cpu/unsp/unsp.cpp index bec95cafe71..410d8b60396 100644 --- a/src/devices/cpu/unsp/unsp.cpp +++ b/src/devices/cpu/unsp/unsp.cpp @@ -1,5 +1,5 @@ // license:GPL-2.0+ -// copyright-holders:Segher Boessenkool,Ryan Holtz +// copyright-holders:Segher Boessenkool, Ryan Holtz, David Haywood /***************************************************************************** SunPlus µ'nSP emulator @@ -10,6 +10,10 @@ Ported to MAME framework by Ryan Holtz + Notes: + + R3 and R4 together are 'MR' with R4 being the upper part of the 32-bit reg + *****************************************************************************/ #include "emu.h" @@ -18,11 +22,12 @@ #include "debugger.h" -#include "unspdefs.h" #include "unspdasm.h" -DEFINE_DEVICE_TYPE(UNSP, unsp_device, "unsp", "SunPlus u'nSP") -DEFINE_DEVICE_TYPE(UNSP_NEWER, unsp_newer_device, "unsp_newer", "SunPlus u'nSP (newer)") // found on GCM394 die, has extra instructions +DEFINE_DEVICE_TYPE(UNSP, unsp_device, "unsp", "SunPlus u'nSP (ISA 1.0)") +DEFINE_DEVICE_TYPE(UNSP_11, unsp_11_device, "unsp_11", "SunPlus u'nSP (ISA 1.1)") +DEFINE_DEVICE_TYPE(UNSP_12, unsp_12_device, "unsp_12", "SunPlus u'nSP (ISA 1.2)") // found on GCM394 die, has extra instructions +DEFINE_DEVICE_TYPE(UNSP_20, unsp_20_device, "unsp_20", "SunPlus u'nSP (ISA 2.0)") /* size of the execution code cache */ #define CACHE_SIZE (64 * 1024 * 1024) @@ -56,13 +61,71 @@ unsp_device::unsp_device(const machine_config& mconfig, device_type type, const unsp_device::unsp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : unsp_device(mconfig, UNSP, tag, owner, clock) { + m_iso = 10; +} + +unsp_11_device::unsp_11_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : unsp_device(mconfig, UNSP_11, tag, owner, clock) +{ + m_iso = 11; +} + +unsp_11_device::unsp_11_device(const machine_config& mconfig, device_type type, const char* tag, device_t* owner, uint32_t clock) + : unsp_device(mconfig, type, tag, owner, clock) +{ + m_iso = 11; +} + + +unsp_12_device::unsp_12_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : unsp_11_device(mconfig, UNSP_12, tag, owner, clock) +{ + m_iso = 12; +} + +unsp_12_device::unsp_12_device(const machine_config& mconfig, device_type type, const char* tag, device_t* owner, uint32_t clock) + : unsp_11_device(mconfig, type, tag, owner, clock) +{ + m_iso = 12; } -unsp_newer_device::unsp_newer_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : unsp_device(mconfig, UNSP_NEWER, tag, owner, clock) +unsp_20_device::unsp_20_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : unsp_12_device(mconfig, UNSP_20, tag, owner, clock) { + m_iso = 20; } +// these are just for logging, can be removed once all ops are implemented +char const* const unsp_device::regs[] = +{ + "sp", "r1", "r2", "r3", "r4", "bp", "sr", "pc" +}; + +char const* const unsp_device::bitops[] = +{ + "tstb", "setb", "clrb", "invb" +}; + +char const* const unsp_device::lsft[] = +{ + "asr", "asror", "lsl", "lslor", "lsr", "lsror", "rol", "ror" +}; + +char const* const unsp_device::extregs[] = +{ + "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15" +}; + +char const* const unsp_device::aluops[] = +{ + "add","adc","sub","sbc","cmp","(invalid)","neg","--","xor","load","or","and","test","store","(invalid)","(invalid)" +}; + +char const* const unsp_device::forms[] = +{ + "[%s]", "[%s--]", "[%s++]", "[++%s]" +}; + device_memory_interface::space_config_vector unsp_device::memory_space_config() const { @@ -76,9 +139,14 @@ std::unique_ptr<util::disasm_interface> unsp_device::create_disassembler() return std::make_unique<unsp_disassembler>(); } -std::unique_ptr<util::disasm_interface> unsp_newer_device::create_disassembler() +std::unique_ptr<util::disasm_interface> unsp_12_device::create_disassembler() +{ + return std::make_unique<unsp_12_disassembler>(); +} + +std::unique_ptr<util::disasm_interface> unsp_20_device::create_disassembler() { - return std::make_unique<unsp_newer_disassembler>(); + return std::make_unique<unsp_12_disassembler>(); } void unsp_device::unimplemented_opcode(uint16_t op) @@ -86,30 +154,24 @@ void unsp_device::unimplemented_opcode(uint16_t op) fatalerror("UNSP: unknown opcode %04x at %04x\n", op, UNSP_LPC); } -/*****************************************************************************/ - -uint16_t unsp_device::read16(uint32_t address) +void unsp_device::unimplemented_opcode(uint16_t op, uint16_t ximm) { - return m_program->read_word(address); + fatalerror("UNSP: unknown opcode %04x %04x at %04x\n", op, ximm, UNSP_LPC); } -void unsp_device::write16(uint32_t address, uint16_t data) + +void unsp_device::unimplemented_opcode(uint16_t op, uint16_t ximm, uint16_t ximm_2) { -#if UNSP_LOG_REGS - log_write(address, data); -#endif - m_program->write_word(address, data); + fatalerror("UNSP: unknown opcode %04x %04x %04x at %04x\n", op, ximm, ximm_2, UNSP_LPC); } -/*****************************************************************************/ - void unsp_device::device_start() { 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(); + m_enable_drc = allow_drc() && (m_iso < 12); #else m_enable_drc = false; #endif @@ -306,7 +368,7 @@ uint16_t unsp_device::pop(uint32_t *reg) return (uint16_t)read16(*reg); } -void unsp_device::trigger_fiq() +inline void unsp_device::trigger_fiq() { if (!m_core->m_enable_fiq || m_core->m_fiq || m_core->m_irq) { @@ -324,7 +386,7 @@ void unsp_device::trigger_fiq() m_core->m_r[REG_SR] = 0; } -void unsp_device::trigger_irq(int line) +inline void unsp_device::trigger_irq(int line) { if (!m_core->m_enable_irq || m_core->m_irq || m_core->m_fiq) return; @@ -361,631 +423,23 @@ void unsp_device::check_irqs() trigger_irq(highest_irq - 1); } -void unsp_device::add_lpc(const int32_t offset) -{ - const uint32_t new_lpc = UNSP_LPC + offset; - 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; -} - -void unsp_device::execute_f_group(const uint16_t op) -{ - unimplemented_opcode(op); -} - -void unsp_newer_device::execute_f_group(const uint16_t op) -{ - logerror("UNSP: unknown extended opcode %04x at %04x\n", op, UNSP_LPC); -} - 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; - 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) + return execute_fxxx_group(op); if(op0 < 0xf && opa == 0x7 && op1 < 2) - { - const uint32_t opimm = op & 0x3f; - switch(op0) - { - case 0: // JB - if(!(m_core->m_r[REG_SR] & UNSP_C)) - { - m_core->m_icount -= 4; - add_lpc((op1 == 0) ? opimm : (0 - opimm)); - } - else - { - m_core->m_icount -= 2; - } - return; - case 1: // JAE - if(m_core->m_r[REG_SR] & UNSP_C) - { - m_core->m_icount -= 4; - add_lpc((op1 == 0) ? opimm : (0 - opimm)); - } - else - { - m_core->m_icount -= 2; - } - return; - case 2: // JGE - if(!(m_core->m_r[REG_SR] & UNSP_S)) - { - m_core->m_icount -= 4; - add_lpc((op1 == 0) ? opimm : (0 - opimm)); - } - else - { - m_core->m_icount -= 2; - } - return; - case 3: // JL - if(m_core->m_r[REG_SR] & UNSP_S) - { - m_core->m_icount -= 4; - add_lpc((op1 == 0) ? opimm : (0 - opimm)); - } - else - { - m_core->m_icount -= 2; - } - return; - case 4: // JNE - if(!(m_core->m_r[REG_SR] & UNSP_Z)) - { - m_core->m_icount -= 4; - add_lpc((op1 == 0) ? opimm : (0 - opimm)); - } - else - { - m_core->m_icount -= 2; - } - return; - case 5: // JE - if(m_core->m_r[REG_SR] & UNSP_Z) - { - m_core->m_icount -= 4; - add_lpc((op1 == 0) ? opimm : (0 - opimm)); - } - else - { - m_core->m_icount -= 2; - } - return; - case 6: // JPL - if(!(m_core->m_r[REG_SR] & UNSP_N)) - { - m_core->m_icount -= 4; - add_lpc((op1 == 0) ? opimm : (0 - opimm)); - } - else - { - m_core->m_icount -= 2; - } - return; - case 7: // JMI - if(m_core->m_r[REG_SR] & UNSP_N) - { - m_core->m_icount -= 4; - add_lpc((op1 == 0) ? opimm : (0 - opimm)); - } - else - { - m_core->m_icount -= 2; - } - return; - case 8: // JBE - if((m_core->m_r[REG_SR] & (UNSP_Z | UNSP_C)) != UNSP_C) // branch if (!UNSP_Z && !UNSP_C) || UNSP_Z - { - m_core->m_icount -= 4; - add_lpc((op1 == 0) ? opimm : (0 - opimm)); - } - else - { - m_core->m_icount -= 2; - } - return; - case 9: // JA - if((m_core->m_r[REG_SR] & (UNSP_Z | UNSP_C)) == UNSP_C) // branch if !UNSP_Z && UNSP_C - { - m_core->m_icount -= 4; - add_lpc((op1 == 0) ? opimm : (0 - opimm)); - } - else - { - m_core->m_icount -= 2; - } - return; - case 10: // JLE - if(m_core->m_r[REG_SR] & (UNSP_Z | UNSP_S)) - { - m_core->m_icount -= 4; - add_lpc((op1 == 0) ? opimm : (0 - opimm)); - } - else - { - m_core->m_icount -= 2; - } - return; - case 11: // JG - if(!(m_core->m_r[REG_SR] & (UNSP_Z | UNSP_S))) - { - m_core->m_icount -= 4; - add_lpc((op1 == 0) ? opimm : (0 - opimm)); - } - else - { - m_core->m_icount -= 2; - } - return; - case 14: // JMP - add_lpc((op1 == 0) ? opimm : (0 - opimm)); - m_core->m_icount -= 4; - return; - default: - unimplemented_opcode(op); - return; - } - } - else if (lower_op == 0x2d) // Push - { - r0 = opn; - r1 = opa; - m_core->m_icount -= 4 + 2 * r0; + return execute_jumps(op); - while (r0--) - { - push(m_core->m_r[r1--], &m_core->m_r[opb]); - } - return; - } - else if (lower_op == 0x29) - { - if (op == 0x9a98) // reti - { - 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_core->m_fiq) - { - m_core->m_fiq = 0; - m_core->m_saved_sb[2] = m_core->m_sb; - m_core->m_sb = m_core->m_saved_sb[m_core->m_irq ? 1 : 0]; - } - else if(m_core->m_irq) - { - m_core->m_irq = 0; - m_core->m_saved_sb[1] = m_core->m_sb; - m_core->m_sb = m_core->m_saved_sb[0]; - } - m_core->m_curirq = 0; - check_irqs(); - return; - } - else // pop - { - r0 = opn; - r1 = opa; - m_core->m_icount -= 4 + 2 * r0; - - while (r0--) - { - m_core->m_r[++r1] = pop(&m_core->m_r[opb]); - } - return; - } - } - else if (op0 == 0xf) - { - switch (op1) - { - case 0x00: // Multiply, Unsigned * Signed - if(opn == 1 && opa != 7) - { - m_core->m_icount -= 12; - lres = m_core->m_r[opa] * m_core->m_r[opb]; - if(m_core->m_r[opb] & 0x8000) - { - lres -= m_core->m_r[opa] << 16; - } - m_core->m_r[REG_R4] = lres >> 16; - m_core->m_r[REG_R3] = (uint16_t)lres; - } - else - { - unimplemented_opcode(op); - } - return; - - case 0x01: // Call - if(!(opa & 1)) - { - m_core->m_icount -= 9; - r1 = read16(UNSP_LPC); - add_lpc(1); - 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 - { - unimplemented_opcode(op); - } - return; - - case 0x02: // Far Jump - if (opa == 7) - { - 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 - { - unimplemented_opcode(op); - } - return; - - case 0x04: // Multiply, Signed * Signed - if(opn == 1 && opa != 7) - { - m_core->m_icount -= 12; - lres = m_core->m_r[opa] * m_core->m_r[opb]; - if(m_core->m_r[opb] & 0x8000) - { - lres -= m_core->m_r[opa] << 16; - } - if(m_core->m_r[opa] & 0x8000) - { - lres -= m_core->m_r[opb] << 16; - } - m_core->m_r[REG_R4] = lres >> 16; - m_core->m_r[REG_R3] = (uint16_t)lres; - } - else - { - unimplemented_opcode(op); - } - return; - - case 0x05: // Interrupt flags - m_core->m_icount -= 2; - switch(op & 0x3f) - { - case 0: - m_core->m_enable_irq = 0; - m_core->m_enable_fiq = 0; - break; - case 1: - m_core->m_enable_irq = 1; - m_core->m_enable_fiq = 0; - break; - case 2: - m_core->m_enable_irq = 0; - m_core->m_enable_fiq = 1; - break; - case 3: - m_core->m_enable_irq = 1; - m_core->m_enable_fiq = 1; - break; - case 8: // irq off - m_core->m_enable_irq = 0; - break; - case 9: // irq on - m_core->m_enable_irq = 1; - break; - case 12: // fiq off - m_core->m_enable_fiq = 0; - break; - case 14: // fiq on - m_core->m_enable_fiq = 1; - break; - case 37: // nop - break; - default: - unimplemented_opcode(op); - break; - } - return; - - default: - unimplemented_opcode(op); - return; - } - } - - // At this point, we should be dealing solely with ALU ops. - - r0 = m_core->m_r[opa]; - - switch (op1) - { - case 0x00: // r, [bp+imm6] - m_core->m_icount -= 6; + if (op0 == 0xe) + return execute_exxx_group(op); - r2 = (uint16_t)(m_core->m_r[REG_BP] + (op & 0x3f)); - if (op0 != 0x0d) - r1 = read16(r2); - break; - - case 0x01: // r, imm6 - m_core->m_icount -= 2; - - r1 = op & 0x3f; - break; - - case 0x03: // Indirect - { - m_core->m_icount -= (opa == 7 ? 7 : 6); - - const uint8_t lsbits = opn & 3; - if (opn & 4) - { - switch (lsbits) - { - case 0: // r, [<ds:>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); - 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) - r1 = read16(r2); - 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] - 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) - r1 = read16(r2); - break; - default: - break; - } - } - else - { - switch (lsbits) - { - case 0: // r, [r] - r2 = m_core->m_r[opb]; - if (op0 != 0x0d) - r1 = read16(r2); - break; - case 1: // r, [r--] - r2 = m_core->m_r[opb]; - if (op0 != 0x0d) - r1 = read16(r2); - m_core->m_r[opb] = (uint16_t)(m_core->m_r[opb] - 1); - break; - case 2: // r, [r++] - r2 = m_core->m_r[opb]; - if (op0 != 0x0d) - r1 = read16(r2); - m_core->m_r[opb] = (uint16_t)(m_core->m_r[opb] + 1); - break; - case 3: // r, [++r] - 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: - break; - } - } - break; - } - - case 0x04: // 16-bit ops - switch (opn) - { - case 0x00: // r - m_core->m_icount -= (opa == 7 ? 5 : 3); - r1 = m_core->m_r[opb]; - break; - - case 0x01: // imm16 - 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_core->m_icount -= (opa == 7 ? 8 : 7); - r0 = m_core->m_r[opb]; - r2 = read16(UNSP_LPC); - add_lpc(1); - - if (op0 != 0x0d) - { - r1 = read16(r2); - } - break; - - case 0x03: // store [imm16], r - m_core->m_icount -= (opa == 7 ? 8 : 7); - r1 = r0; - r0 = m_core->m_r[opb]; - r2 = read16(UNSP_LPC); - add_lpc(1); - break; - - default: // Shifted ops - { - 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_core->m_sb = shift & 0x0f; - r1 = (uint16_t)(shift >> 4); - break; - } - } - break; - - case 0x05: // More shifted ops - m_core->m_icount -= (opa == 7 ? 5 : 3); - - if (opn & 4) // Shift right - { - 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_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_core->m_icount -= (opa == 7 ? 5 : 3); - - 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_core->m_sb = shift & 0x0f; - } - else - { - shift <<= (opn + 1); - m_core->m_sb = (shift >> 20) & 0x0f; - } - r1 = (uint16_t)(shift >> 4); - break; - } - - case 0x07: // Direct 8 - m_core->m_icount -= (opa == 7 ? 6 : 5); - r2 = op & 0x3f; - r1 = read16(r2); - break; - - default: - break; - } - - switch (op0) - { - case 0x00: // Add - { - lres = r0 + r1; - if (opa != 7) - update_nzsc(lres, r0, r1); - break; - } - case 0x01: // Add w/ carry - { - 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 - lres = r0 + (uint16_t)(~r1) + uint32_t(1); - if (opa != 7) - update_nzsc(lres, r0, ~r1); - break; - case 0x03: // Subtract w/ carry - { - uint32_t c = (m_core->m_r[REG_SR] & UNSP_C) ? 1 : 0; - lres = r0 + (uint16_t)(~r1) + c; - if (opa != 7) - 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 - 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; - - case 0x0f: // extended opcodes - execute_f_group(op); - return; - - default: - unimplemented_opcode(op); - return; - } - - if (op1 == 0x04 && opn == 0x03) // store [imm16], r - write16(r2, lres); - else - m_core->m_r[opa] = (uint16_t)lres; + execute_remaining(op); } void unsp_device::execute_run() diff --git a/src/devices/cpu/unsp/unsp.h b/src/devices/cpu/unsp/unsp.h index 5bbc92d35b5..0a9583e8fa4 100644 --- a/src/devices/cpu/unsp/unsp.h +++ b/src/devices/cpu/unsp/unsp.h @@ -1,5 +1,5 @@ // license:GPL-2.0+ -// copyright-holders:Segher Boessenkool,Ryan Holtz +// copyright-holders:Segher Boessenkool, Ryan Holtz, David Haywood /***************************************************************************** SunPlus µ'nSP emulator @@ -20,6 +20,7 @@ #include "cpu/drcfe.h" #include "cpu/drcuml.h" #include "cpu/drcumlsh.h" +#include "unspdefs.h" /*************************************************************************** CONSTANTS @@ -91,7 +92,7 @@ class unsp_device : public cpu_device public: // construction/destruction - unsp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + unsp_device(const machine_config& mconfig, const char* tag, device_t* owner, uint32_t clock); unsp_device(const machine_config& mconfig, device_type type, const char* tag, device_t* owner, uint32_t clock); // HACK: IRQ line state can only be modified directly by hardware on-board the SPG SoC itself. @@ -132,9 +133,9 @@ protected: virtual space_config_vector memory_space_config() const override; // device_state_interface overrides - virtual void state_import(const device_state_entry &entry) override; - virtual void state_export(const device_state_entry &entry) override; - virtual void state_string_export(const device_state_entry &entry, std::string &str) const override; + virtual void state_import(const device_state_entry& entry) override; + virtual void state_export(const device_state_entry& entry) override; + virtual void state_string_export(const device_state_entry& entry, std::string& str) const override; // device_disasm_interface overrides virtual std::unique_ptr<util::disasm_interface> create_disassembler() override; @@ -154,8 +155,8 @@ protected: /* internal compiler state */ struct compiler_state { - compiler_state(compiler_state const &) = delete; - compiler_state &operator=(compiler_state const &) = delete; + compiler_state(compiler_state const&) = delete; + compiler_state& operator=(compiler_state const&) = delete; uint32_t m_cycles; /* accumulated cycles */ uml::code_label m_labelnum; /* index for local labels */ @@ -181,7 +182,53 @@ protected: }; /* core state */ - internal_unsp_state *m_core; + internal_unsp_state* m_core; + +protected: + uint16_t read16(uint32_t address) { return m_program->read_word(address); } + + void write16(uint32_t address, uint16_t data) + { + #if UNSP_LOG_REGS + log_write(address, data); + #endif + m_program->write_word(address, data); + } + + void add_lpc(const int32_t offset) + { + const uint32_t new_lpc = UNSP_LPC + offset; + 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; + } + + void execute_fxxx_000_group(uint16_t op); + void execute_fxxx_001_group(uint16_t op); + void execute_fxxx_010_group(uint16_t op); + void execute_fxxx_011_group(uint16_t op); + virtual void execute_fxxx_101_group(uint16_t op); + void execute_fxxx_110_group(uint16_t op); + void execute_fxxx_111_group(uint16_t op); + void execute_fxxx_group(uint16_t op);; + void execute_fxxx_100_group(uint16_t op); + virtual void execute_extended_group(uint16_t op); + virtual void execute_exxx_group(uint16_t op); + void unimplemented_opcode(uint16_t op); + void unimplemented_opcode(uint16_t op, uint16_t ximm); + void unimplemented_opcode(uint16_t op, uint16_t ximm, uint16_t ximm_2); + + int m_iso; + + static char const *const regs[]; + static char const *const extregs[]; + static char const *const bitops[]; + static char const *const lsft[]; + static char const *const aluops[]; + static char const *const forms[]; + + void push(uint32_t value, uint32_t *reg); + uint16_t pop(uint32_t *reg); private: // compilation boundaries -- how far back/forward does the analysis extend? @@ -202,10 +249,12 @@ private: EXECUTE_RESET_CACHE = 3 }; - void add_lpc(const int32_t offset); - virtual void execute_f_group(const uint16_t op); - inline void execute_one(const uint16_t op); + void execute_jumps(const uint16_t op); + void execute_remaining(const uint16_t op); + void execute_one(const uint16_t op); + + address_space_config m_program_config; address_space *m_program; @@ -217,16 +266,11 @@ private: uint32_t m_log_ops; #endif - void unimplemented_opcode(uint16_t op); - inline uint16_t read16(uint32_t address); - inline void write16(uint32_t address, uint16_t data); - inline void update_nz(uint32_t value); - inline void update_nzsc(uint32_t value, uint16_t r0, uint16_t r1); - inline void push(uint32_t value, uint32_t *reg); - inline uint16_t pop(uint32_t *reg); + void update_nz(uint32_t value); + void update_nzsc(uint32_t value, uint16_t r0, uint16_t r1); inline void trigger_fiq(); inline void trigger_irq(int line); - inline void check_irqs(); + void check_irqs(); drc_cache m_cache; std::unique_ptr<drcuml_state> m_drcuml; @@ -247,8 +291,6 @@ private: bool m_enable_drc; - - void execute_run_drc(); void flush_drc_cache(); void code_flush_cache(); @@ -272,7 +314,6 @@ private: void generate_update_nzsc(drcuml_block &block); void generate_update_nz(drcuml_block &block); void log_add_disasm_comment(drcuml_block &block, uint32_t pc, uint32_t op); - virtual bool generate_f_group_opcode(drcuml_block& block, compiler_state& compiler, const opcode_desc* desc); bool generate_opcode(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc); #if UNSP_LOG_REGS @@ -280,20 +321,50 @@ private: #endif }; -class unsp_newer_device : public unsp_device + +class unsp_11_device : public unsp_device +{ +public: + // construction/destruction + unsp_11_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + unsp_11_device(const machine_config& mconfig, device_type type, const char* tag, device_t* owner, uint32_t clock); + +private: +}; + +class unsp_12_device : public unsp_11_device +{ +public: + // construction/destruction + unsp_12_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + unsp_12_device(const machine_config& mconfig, device_type type, const char* tag, device_t* owner, uint32_t clock); + +private: + virtual void execute_fxxx_101_group(uint16_t op) override; + virtual void execute_exxx_group(uint16_t op) override; + + virtual std::unique_ptr<util::disasm_interface> create_disassembler() override; +}; + +class unsp_20_device : public unsp_12_device { public: // construction/destruction - unsp_newer_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + unsp_20_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); private: virtual std::unique_ptr<util::disasm_interface> create_disassembler() override; - virtual void execute_f_group(const uint16_t op) override; - virtual bool generate_f_group_opcode(drcuml_block& block, compiler_state& compiler, const opcode_desc* desc) override; + virtual void execute_extended_group(uint16_t op) override; + +private: }; -DECLARE_DEVICE_TYPE(UNSP, unsp_device) -DECLARE_DEVICE_TYPE(UNSP_NEWER, unsp_newer_device) + +DECLARE_DEVICE_TYPE(UNSP, unsp_device) +DECLARE_DEVICE_TYPE(UNSP_11, unsp_11_device) +DECLARE_DEVICE_TYPE(UNSP_12, unsp_12_device) +DECLARE_DEVICE_TYPE(UNSP_20, unsp_20_device) + #endif // MAME_CPU_UNSP_UNSP_H diff --git a/src/devices/cpu/unsp/unsp_extended.cpp b/src/devices/cpu/unsp/unsp_extended.cpp new file mode 100644 index 00000000000..fa9c3d5a713 --- /dev/null +++ b/src/devices/cpu/unsp/unsp_extended.cpp @@ -0,0 +1,206 @@ +// license:GPL-2.0+ +// copyright-holders:Segher Boessenkool, Ryan Holtz, David Haywood + +#include "emu.h" +#include "unsp.h" +#include "unspfe.h" + +#include "debugger.h" + +#include "unspdasm.h" + +void unsp_device::execute_extended_group(uint16_t op) +{ + // shouldn't get here anyway + logerror("<UNKNOWN EXTENDED>\n"); + unimplemented_opcode(op); + return; +} + +void unsp_20_device::execute_extended_group(uint16_t op) +{ + uint16_t ximm = read16(UNSP_LPC); + add_lpc(1); + + switch ((ximm & 0x01f0) >> 4) + { + case 0x00: case 0x10: + { + // Ext Register Ra = Ra op Rb + uint8_t aluop = (op & 0xf000) >> 12; + uint8_t rb = (op & 0x000f) >> 0; + uint8_t ra = (op & 0x0e00) >> 9; + ra |= (op & 0x0100) >> 5; + + logerror("(Ext) %s = %s %s %s\n", (ra & 0x8) ? extregs[ra & 0x7] : regs[ra & 0x7] + , (ra & 0x8) ? extregs[ra & 0x7] : regs[ra & 0x7] + , aluops[aluop] + , (rb & 0x8) ? extregs[rb & 0x7] : regs[rb & 0x7]); + + unimplemented_opcode(op, ximm); + return; + } + case 0x02: + { + // Ext Push/Pop + if (op & 0x8000) + { + uint8_t rb = (op & 0x000f) >> 0; + uint8_t size = (op & 0x7000) >> 12; + uint8_t rx = (op & 0x0e00) >> 9; + + if (rx+1 >= size && rx < size+7) + logerror("(Ext) push %s, %s to [%s]\n", + extregs[rx+1-size], extregs[rx], (rb & 0x8) ? extregs[rb & 0x7] : regs[rb & 0x7]); + else + logerror("(Ext) push <BAD>\n"); + + unimplemented_opcode(op, ximm); + } + else + { + uint8_t rb = (op & 0x000f) >> 0; + uint8_t size = (op & 0x7000) >> 12; + uint8_t rx = (op & 0x0e00) >> 9; + + if (rx+1 < 8 && rx+size < 8) + logerror("(Ext) pop %s, %s from [%s]\n", + extregs[rx+1], extregs[rx+size], (rb & 0x8) ? extregs[rb & 0x7] : regs[rb & 0x7]); + else + logerror("(Ext) pop <BAD>\n"); + + unimplemented_opcode(op, ximm); + } + return; + } + case 0x04: case 0x14: + { + uint16_t ximm_2 = read16(UNSP_LPC); + add_lpc(1); + + // Ra=Rb op IMM16 + uint8_t aluop = (op & 0xf000) >> 12; + uint8_t rb = (op & 0x000f) >> 0; + uint8_t ra = (op & 0x0e00) >> 9; + ra |= (op & 0x0100) >> 5; + + logerror("(Ext) %s = %s %s %04x\n", (ra & 0x8) ? extregs[ra & 0x7] : regs[ra & 0x7] + , (rb & 0x8) ? extregs[rb & 0x7] : regs[rb & 0x7] + , aluops[aluop] + , ximm_2); + + unimplemented_opcode(op, ximm, ximm_2); + return; + } + + case 0x06: + case 0x16: + { + uint16_t ximm_2 = read16(UNSP_LPC); + add_lpc(1); + + // Ra=Rb op [A16] + uint8_t aluop = (op & 0xf000) >> 12; + uint8_t rb = (op & 0x000f) >> 0; + uint8_t ra = (op & 0x0e00) >> 9; + ra |= (op & 0x0100) >> 5; + + logerror("(Ext) %s = %s %s [%04x]\n", (ra & 0x8) ? extregs[ra & 0x7] : regs[ra & 0x7] + , (rb & 0x8) ? extregs[rb & 0x7] : regs[rb & 0x7] + , aluops[aluop] + , ximm_2); + + unimplemented_opcode(op, ximm, ximm_2); + return; + } + + case 0x07: + case 0x17: + { + uint16_t ximm_2 = read16(UNSP_LPC); + add_lpc(1); + + //[A16] = Ra op Rb + uint8_t aluop = (op & 0xf000) >> 12; + uint8_t rb = (op & 0x000f) >> 0; + uint8_t ra = (op & 0x0e00) >> 9; + ra |= (op & 0x0100) >> 5; + + logerror("(Ext) [0x4x] = %s %s %s\n", ximm_2 + , (ra & 0x8) ? extregs[ra & 0x7] : regs[ra & 0x7] + , aluops[aluop] + , (rb & 0x8) ? extregs[rb & 0x7] : regs[rb & 0x7]); + + unimplemented_opcode(op, ximm, ximm_2); + return; + } + + case 0x08: case 0x09: + { + // Ext Indirect Rx=Rx op [Ry@] + uint8_t aluop = (op & 0xf000) >> 12; + uint8_t ry = (op & 0x0007) >> 0; + uint8_t form = (op & 0x0018) >> 3; + uint8_t rx = (op & 0x0e00) >> 9; + + logerror("(Ext) %s=%s %s", extregs[rx], extregs[rx], aluops[aluop]); + logerror(forms[form], extregs[ry]); + logerror("\n"); + unimplemented_opcode(op, ximm); + return; + } + case 0x0a: case 0x0b: + { + // Ext DS_Indirect Rx=Rx op ds:[Ry@] + uint8_t aluop = (op & 0xf000) >> 12; + uint8_t ry = (op & 0x0007) >> 0; + uint8_t form = (op & 0x0018) >> 3; + uint8_t rx = (op & 0x0e00) >> 9; + + logerror("(Ext) %s=%s %s ds:", extregs[rx], extregs[rx], aluops[aluop]); + logerror(forms[form], extregs[ry]); + logerror("\n"); + unimplemented_opcode(op, ximm); + return; + } + case 0x18: case 0x19: case 0x1a: case 0x1b: + { + // Ext IM6 Rx=Rx op IM6 + uint8_t aluop = (op & 0xf000) >> 12; + uint8_t rx = (op & 0x0e00) >> 9; + uint8_t imm6 = (op & 0x003f) >> 0; + + logerror("(Ext) %s=%s %s %02x\n", extregs[rx], extregs[rx], aluops[aluop], imm6 ); + unimplemented_opcode(op, ximm); + return; + } + + case 0x0c: case 0x0d: case 0x0e: case 0x0f: + { + // Ext Base+Disp6 Rx=Rx op [BP+IM6] + uint8_t aluop = (op & 0xf000) >> 12; + uint8_t rx = (op & 0x0e00) >> 9; + uint8_t imm6 = (op & 0x003f) >> 0; + + logerror("(Ext) %s=%s %s [BP+%02x]\n", extregs[rx], extregs[rx], aluops[aluop], imm6 ); + unimplemented_opcode(op, ximm); + return; + } + + case 0x1c: case 0x1d: case 0x1e: case 0x1f: + { + // Ext A6 Rx=Rx op [A6] + uint8_t aluop = (op & 0xf000) >> 12; + uint8_t rx = (op & 0x0e00) >> 9; + uint8_t a6 = (op & 0x003f) >> 0; + + logerror("(Ext) %s=%s %s [%02x]\n", extregs[rx], extregs[rx], aluops[aluop], a6 ); + unimplemented_opcode(op, ximm); + return; + } + } + + // illegal? + unimplemented_opcode(op, ximm); + return; +} diff --git a/src/devices/cpu/unsp/unsp_exxx.cpp b/src/devices/cpu/unsp/unsp_exxx.cpp new file mode 100644 index 00000000000..ddbc32bc570 --- /dev/null +++ b/src/devices/cpu/unsp/unsp_exxx.cpp @@ -0,0 +1,161 @@ +// license:GPL-2.0+ +// copyright-holders:Segher Boessenkool, Ryan Holtz, David Haywood + +#include "emu.h" +#include "unsp.h" +#include "unspfe.h" + +#include "debugger.h" + +#include "unspdasm.h" + +void unsp_device::execute_exxx_group(uint16_t op) +{ + // several exxx opcodes have already been decoded as jumps by the time we get here + //logerror("<DUNNO>\n"); + unimplemented_opcode(op); + return; +} + +void unsp_12_device::execute_exxx_group(uint16_t op) +{ + // several exxx opcodes have already been decoded as jumps by the time we get here + + // Register BITOP BITOP Rd,Rs 1 1 1 0 r r r 0 0 0 b b 0 r r r + // Register BITOP BITOP Rd,offset 1 1 1 0 r r r 0 0 1 b b o o o o + // Memory BITOP BITOP [Rd], offset 1 1 1 0 r r r 1 1 0 b b o o o o + // Memory BITOP BITOP ds:[Rd], offset 1 1 1 0 r r r 1 1 1 b b o o o o + // Memory BITOP BITOP [Rd], Rs 1 1 1 0 r r r 1 0 0 b b 0 r r r + // Memory BITOP BITOP ds:[Rd], Rs 1 1 1 0 r r r 1 0 1 b b 0 r r r + + if (((op & 0xf1c8) == 0xe000)) + { + // Register BITOP BITOP Rd,Rs + uint8_t bitop = (op & 0x0030) >> 4; + uint8_t rd = (op & 0x0e00) >> 9; + uint8_t rs = (op & 0x0007) >> 0; + logerror("%s %s,%s\n", bitops[bitop], regs[rd], regs[rs]); + unimplemented_opcode(op); + return; + } + else if (((op & 0xf1c0) == 0xe040)) + { + // Register BITOP BITOP Rd,offset + uint8_t bitop = (op & 0x0030) >> 4; + uint8_t rd = (op & 0x0e00) >> 9; + uint8_t offset = (op & 0x000f) >> 0; + + switch (bitop) + { + case 0x00: + fatalerror("UNSP: unknown opcode tstb Rd,offset (%04x) at %04x\n", op, UNSP_LPC); + return; + + case 0x01: // setb + m_core->m_r[rd] |= (1 << offset); + return; + + case 0x02: // clrb + m_core->m_r[rd] &= ~(1 << offset); + return; + + case 0x03: + fatalerror("UNSP: unknown opcode invb Rd,offset (%04x) at %04x\n", op, UNSP_LPC); + return; + } + return; + } + else if (((op & 0xf1c0) == 0xe180)) + { + // Memory BITOP BITOP [Rd], offset + uint8_t bitop = (op & 0x0030) >> 4; + uint8_t rd = (op & 0x0e00) >> 9; + uint8_t offset = (op & 0x000f) >> 0; + logerror("%s [%s],%d\n", bitops[bitop], regs[rd], offset); + unimplemented_opcode(op); + return; + } + else if (((op & 0xf1c0) == 0xe1c0)) + { + // Memory BITOP BITOP ds:[Rd], offset + uint8_t bitop = (op & 0x0030) >> 4; + uint8_t rd = (op & 0x0e00) >> 9; + uint8_t offset = (op & 0x000f) >> 0; + logerror("%s ds:[%s],%d\n", bitops[bitop], regs[rd], offset); + unimplemented_opcode(op); + return; + } + else if (((op & 0xf1c8) == 0xe100)) + { + // Memory BITOP BITOP [Rd], Rs + uint8_t bitop = (op & 0x0030) >> 4; + uint8_t rd = (op & 0x0e00) >> 9; + uint8_t rs = (op & 0x0007) >> 0; + logerror("%s [%s],%s\n", bitops[bitop], regs[rd], regs[rs]); + unimplemented_opcode(op); + return; + } + else if (((op & 0xf1c8) == 0xe140)) + { + // Memory BITOP BITOP ds:[Rd], Rs + uint8_t bitop = (op & 0x0030) >> 4; + uint8_t rd = (op & 0x0e00) >> 9; + uint8_t rs = (op & 0x0007) >> 0; + logerror("%s ds:[%s],%s\n", bitops[bitop], regs[rd], regs[rs]); + unimplemented_opcode(op); + return; + } + else if (((op & 0xf0f8) == 0xe008)) + { + // MUL operations + // MUL 1 1 1 0* r r r S* 0 0 0 0 1 r r r (* = sign bit, fixed here) + /* + print_mul(stream, op); // MUL uu or MUL su (invalid?) + */ + + if (op & 0x0100) + { + logerror("MUL su\n"); + fatalerror("UNSP: unknown opcode MUL su (invalid?) (%04x) at %04x\n", op, UNSP_LPC); + return; + } + else + { + uint32_t lres = 0; + const uint16_t opa = (op >> 9) & 7; + const uint16_t opb = op & 7; + + m_core->m_icount -= 12; // unknown + lres = m_core->m_r[opa] * m_core->m_r[opb]; + m_core->m_r[REG_R4] = lres >> 16; + m_core->m_r[REG_R3] = (uint16_t)lres; + return; + } + return; + } + else if (((op & 0xf080) == 0xe080)) + { + // MULS 1 1 1 0* r r r S* 1 s s s s r r r (* = sign bit, fixed here) + /* + // MULS uu or MULS su (invalid?) + print_muls(stream, op); + */ + logerror("MULS uu or su\n"); + unimplemented_opcode(op); + return; + } + else if (((op & 0xf188) == 0xe108)) + { + // 16 bit Shift 1 1 1 0 r r r 1 0 l l l 1 r r r + uint8_t rd = (op & 0x0e00) >> 9; + uint8_t shift = (op & 0x0070) >> 4; + uint8_t rs = (op & 0x0007) >> 0; + logerror("%s = %s %s %s\n", regs[rd], regs[rd], lsft[shift], regs[rs]); + unimplemented_opcode(op); + return; + } + + logerror("<DUNNO>\n"); + unimplemented_opcode(op); + return; +} diff --git a/src/devices/cpu/unsp/unsp_fxxx.cpp b/src/devices/cpu/unsp/unsp_fxxx.cpp new file mode 100644 index 00000000000..c63b02c4ad0 --- /dev/null +++ b/src/devices/cpu/unsp/unsp_fxxx.cpp @@ -0,0 +1,431 @@ +// license:GPL-2.0+ +// copyright-holders:Segher Boessenkool, Ryan Holtz, David Haywood + +#include "emu.h" +#include "unsp.h" +#include "unspfe.h" + +#include "debugger.h" + +#include "unspdasm.h" + +inline void unsp_device::execute_fxxx_000_group(uint16_t op) +{ + // | | | + // DS16 1 1 1 1 1 1 1 0 0 0 i i i i i i + // DS Reg 1 1 1 1 - - - 0 0 0 1 0 w r r r + // FR Reg 1 1 1 1 - - - 0 0 0 1 1 w r r r + + if (((op & 0xffc0) == 0xfe00) && m_iso >= 12) + { + // ds = imm6 + int imm = op & 0x003f; + set_ds(imm); + return; + } + else if (((op & 0xf1f8) == 0xf020) && m_iso >= 12) + { + // rx = ds + int r = op & 0x7; + m_core->m_r[r] = get_ds(); + return; + } + else if (((op & 0xf1f8) == 0xf028) && m_iso >= 12) + { + // ds = rx + int r = op & 0x7; + set_ds(m_core->m_r[r]); + return; + } + else if (((op & 0xf1f8) == 0xf030) && m_iso >= 12) + { + int r = op & 0x7; + logerror("%s = fr\n", regs[r]); + unimplemented_opcode(op); + return; + } + else if (((op & 0xf1f8) == 0xf038) && m_iso >= 12) + { + int r = op & 0x7; + logerror("fr = %s\n", regs[r]); + unimplemented_opcode(op); + return; + } + + // everything else falls through to the multiply + + // signed * unsigned + // MUL 1 1 1 1* r r r 0* 0 0 0 0 1 r r r (** = sign bits, fixed here) + const uint16_t opa = (op >> 9) & 7; + const uint16_t opb = op & 7; + m_core->m_icount -= 12; + uint32_t lres = m_core->m_r[opa] * m_core->m_r[opb]; + if (m_core->m_r[opb] & 0x8000) + { + lres -= m_core->m_r[opa] << 16; + } + m_core->m_r[REG_R4] = lres >> 16; + m_core->m_r[REG_R3] = (uint16_t)lres; + + return; +} + +inline void unsp_device::execute_fxxx_001_group(uint16_t op) +{ + // | | | + // CALL16 1 1 1 1 - - 0 0 0 1 a a a a a a (+imm16) + + if ((op & 0xf3c0) == 0xf040) + { + m_core->m_icount -= 9; + uint16_t r1 = read16(UNSP_LPC); + add_lpc(1); + 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; + return; + } + // MEM bitop 1 1 1 1 - D 1 0 0 1 b b o o o o (+imm16) ( BITOP {ds:}[A16],offset ) + else if (((op & 0xf3c0) == 0xf240) && m_iso >= 20) + { + uint8_t bitop = (op & 0x0030) >> 4; + uint8_t offset = (op & 0x000f) >> 0; + uint8_t d = (op & 0x0400) >> 10; + + if (d) + { + logerror("%s ds:[$04x],%d\n", bitops[bitop], offset); + unimplemented_opcode(op); + } + else + { + logerror("%s [$04x],%d\n", bitops[bitop], offset); + unimplemented_opcode(op); + } + + return; + } + + logerror("<DUNNO>\n"); + unimplemented_opcode(op); + return; +} + +inline void unsp_device::execute_fxxx_010_group(uint16_t op) +{ + // | | | + // JMPF 1 1 1 1 1 1 1 0 1 0 a a a a a a (+imm16) + + if ((op & 0xffc0) == 0xfe80) // apparently 1.2 and above, but jak_capb needs it and otherwise seems 1.0 / 1.1? + { + 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; + return; + } + + // signed * unsigned (size 16,1,2,3,4,5,6,7) + // MULS 1 1 1 1* r r r 0* 1 0*s s s r r r (1* = sign bit, 0* = sign bit 0* = upper size bit) + + // MULS us with upper size bit not set + logerror("MULS us\n"); + unimplemented_opcode(op); + return; +} + +inline void unsp_device::execute_fxxx_011_group(uint16_t op) +{ + // | | | + // JMPR 1 1 1 1 1 1 1 0 1 1 - - - - - - + if (((op & 0xffc0) == 0xfec0) && m_iso >= 12) + { + logerror("goto mr\n"); + unimplemented_opcode(op); + return; + } + + // signed * unsigned (size 8,9,10,11,12,13,14,15) + // MULS 1 1 1 1* r r r 0* 1 1*s s s r r r (1* = sign bit, 0* = sign bit 1* = upper size bit) + + // MULS us with upper size bit set + logerror("MULS us\n"); + unimplemented_opcode(op); + + return; +} + +inline void unsp_device::execute_fxxx_100_group(uint16_t op) +{ + // | | | + // signed * signed + // MUL 1 1 1 1* r r r 1* 0 0 0 0 1 r r r (** = sign bits, fixed here) + + if ((op & 0xf1f8) == 0xf108) + { + uint32_t lres = 0; + + const uint16_t opa = (op >> 9) & 7; + const uint16_t opb = op & 7; + + m_core->m_icount -= 12; + lres = m_core->m_r[opa] * m_core->m_r[opb]; + if (m_core->m_r[opb] & 0x8000) + { + lres -= m_core->m_r[opa] << 16; + } + if (m_core->m_r[opa] & 0x8000) + { + lres -= m_core->m_r[opb] << 16; + } + m_core->m_r[REG_R4] = lres >> 16; + m_core->m_r[REG_R3] = (uint16_t)lres; + return; + } + + logerror("<DUNNO>\n"); + unimplemented_opcode(op); + return; +} + + +inline void unsp_12_device::execute_fxxx_101_group(uint16_t op) +{ + // FIR_MOV 1 1 1 1 - - - 1 0 1 0 0 0 1 0 f + // Fraction 1 1 1 1 - - - 1 0 1 0 0 0 1 1 f + // SECBANK 1 1 1 1 - - - 1 0 1 0 0 1 0 1 S + // NESTMODE 1 1 1 1 - - - 1 0 1 0 0 1 1 N 1 + // CALLR 1 1 1 1 - - - 1 0 1 1 - - 0 0 1 + // DIVS 1 1 1 1 - - - 1 0 1 1 - - 0 1 0 + // DIVQ 1 1 1 1 - - - 1 0 1 1 - - 0 1 1 + // EXP 1 1 1 1 - - - 1 0 1 1 - - 1 0 0 + + switch (op) + { + case 0xf146: case 0xf346: case 0xf546: case 0xf746: case 0xf946: case 0xfb46: case 0xfd46: case 0xff46: + logerror("fraction off\n"); + unimplemented_opcode(op); + return; + + case 0xf147: case 0xf347: case 0xf547: case 0xf747: case 0xf947: case 0xfb47: case 0xfd47: case 0xff47: + logerror("fraction on\n"); + unimplemented_opcode(op); + return; + + case 0xf14a: case 0xf34a: case 0xf54a: case 0xf74a: case 0xf94a: case 0xfb4a: case 0xfd4a: case 0xff4a: + logerror("secbank off\n"); + unimplemented_opcode(op); + return; + + case 0xf14b: case 0xf34b: case 0xf54b: case 0xf74b: case 0xf94b: case 0xfb4b: case 0xfd4b: case 0xff4b: + logerror("secbank on\n"); + unimplemented_opcode(op); + return; + + case 0xf14d: case 0xf34d: case 0xf54d: case 0xf74d: case 0xf94d: case 0xfb4d: case 0xfd4d: case 0xff4d: + logerror("irqnest off\n"); + unimplemented_opcode(op); + return; + + case 0xf14f: case 0xf34f: case 0xf54f: case 0xf74f: case 0xf94f: case 0xfb4f: case 0xfd4f: case 0xff4f: + logerror("irqnest on\n"); + unimplemented_opcode(op); + return; + + case 0xf144: case 0xf344: case 0xf544: case 0xf744: case 0xf944: case 0xfb44: case 0xfd44: case 0xff44: + logerror("fir_mov on\n"); + unimplemented_opcode(op); + return; + + case 0xf145: case 0xf345: case 0xf545: case 0xf745: case 0xf945: case 0xfb45: case 0xfd45: case 0xff45: + logerror("fir_mov off\n"); + unimplemented_opcode(op); + return; + + case 0xf161: case 0xf361: case 0xf561: case 0xf761: case 0xf961: case 0xfb61: case 0xfd61: case 0xff61: + case 0xf169: case 0xf369: case 0xf569: case 0xf769: case 0xf969: case 0xfb69: case 0xfd69: case 0xff69: + case 0xf171: case 0xf371: case 0xf571: case 0xf771: case 0xf971: case 0xfb71: case 0xfd71: case 0xff71: + case 0xf179: case 0xf379: case 0xf579: case 0xf779: case 0xf979: case 0xfb79: case 0xfd79: case 0xff79: + { + m_core->m_icount -= 1; // unknown count + uint32_t addr = m_core->m_r[REG_R3] | ((m_core->m_r[REG_R4] & 0x3f) << 16); + add_lpc(1); + 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] = addr & 0x0000ffff; + m_core->m_r[REG_SR] &= 0xffc0; + m_core->m_r[REG_SR] |= ((addr & 0x003f0000) >> 16); + return; + } + + case 0xf162: case 0xf362: case 0xf562: case 0xf762: case 0xf962: case 0xfb62: case 0xfd62: case 0xff62: + case 0xf16a: case 0xf36a: case 0xf56a: case 0xf76a: case 0xf96a: case 0xfb6a: case 0xfd6a: case 0xff6a: + case 0xf172: case 0xf372: case 0xf572: case 0xf772: case 0xf972: case 0xfb72: case 0xfd72: case 0xff72: + case 0xf17a: case 0xf37a: case 0xf57a: case 0xf77a: case 0xf97a: case 0xfb7a: case 0xfd7a: case 0xff7a: + logerror("divs mr, r2\n"); + unimplemented_opcode(op); + return; + + case 0xf163: case 0xf363: case 0xf563: case 0xf763: case 0xf963: case 0xfb63: case 0xfd63: case 0xff63: + case 0xf16b: case 0xf36b: case 0xf56b: case 0xf76b: case 0xf96b: case 0xfb6b: case 0xfd6b: case 0xff6b: + case 0xf173: case 0xf373: case 0xf573: case 0xf773: case 0xf973: case 0xfb73: case 0xfd73: case 0xff73: + case 0xf17b: case 0xf37b: case 0xf57b: case 0xf77b: case 0xf97b: case 0xfb7b: case 0xfd7b: case 0xff7b: + logerror("divq mr, r2\n"); + unimplemented_opcode(op); + return; + + case 0xf164: case 0xf364: case 0xf564: case 0xf764: case 0xf964: case 0xfb64: case 0xfd64: case 0xff64: + case 0xf16c: case 0xf36c: case 0xf56c: case 0xf76c: case 0xf96c: case 0xfb6c: case 0xfd6c: case 0xff6c: + case 0xf174: case 0xf374: case 0xf574: case 0xf774: case 0xf974: case 0xfb74: case 0xfd74: case 0xff74: + case 0xf17c: case 0xf37c: case 0xf57c: case 0xf77c: case 0xf97c: case 0xfb7c: case 0xfd7c: case 0xff7c: + //unimplemented_opcode(op); + // what is this, sign extend / sign expand / zero expand? it doesn't seem to be exponent + logerror("r2 = exp r4 (with r2 = %04x r4 = %04x)\n", m_core->m_r[REG_R2], m_core->m_r[REG_R4]); + m_core->m_r[REG_R2] = 0x0001; // WRONG!! + return; + + + default: + return unsp_device::execute_fxxx_101_group(op); + } +} + + +inline void unsp_device::execute_fxxx_101_group(uint16_t op) +{ + // | | | + // INT SET 1 1 1 1 - - - 1 0 1 0 0 0 0 F I + // BREAK 1 1 1 1 - - - 1 0 1 1 - - 0 0 0 + // NOP 1 1 1 1 - - - 1 0 1 1 - - 1 0 1 + + // IRQ 1 1 1 1 - - - 1 0 1 0 0 1 0 0 I + // FIRQ 1 1 1 1 - - - 1 0 1 0 0 1 1 F 0 + + m_core->m_icount -= 2; + + switch (op) + { + case 0xf140: case 0xf340: case 0xf540: case 0xf740: case 0xf940: case 0xfb40: case 0xfd40: case 0xff40: + m_core->m_enable_irq = 0; + m_core->m_enable_fiq = 0; + return; + + case 0xf141: case 0xf341: case 0xf541: case 0xf741: case 0xf941: case 0xfb41: case 0xfd41: case 0xff41: + m_core->m_enable_irq = 1; + m_core->m_enable_fiq = 0; + return; + + case 0xf142: case 0xf342: case 0xf542: case 0xf742: case 0xf942: case 0xfb42: case 0xfd42: case 0xff42: + m_core->m_enable_irq = 0; + m_core->m_enable_fiq = 1; + return; + + case 0xf143: case 0xf343: case 0xf543: case 0xf743: case 0xf943: case 0xfb43: case 0xfd43: case 0xff43: + m_core->m_enable_irq = 1; + m_core->m_enable_fiq = 1; + return; + + case 0xf160: case 0xf360: case 0xf560: case 0xf760: case 0xf960: case 0xfb60: case 0xfd60: case 0xff60: + case 0xf168: case 0xf368: case 0xf568: case 0xf768: case 0xf968: case 0xfb68: case 0xfd68: case 0xff68: + case 0xf170: case 0xf370: case 0xf570: case 0xf770: case 0xf970: case 0xfb70: case 0xfd70: case 0xff70: + case 0xf178: case 0xf378: case 0xf578: case 0xf778: case 0xf978: case 0xfb78: case 0xfd78: case 0xff78: + unimplemented_opcode(op); + return; + + case 0xf165: case 0xf365: case 0xf565: case 0xf765: case 0xf965: case 0xfb65: case 0xfd65: case 0xff65: + case 0xf16d: case 0xf36d: case 0xf56d: case 0xf76d: case 0xf96d: case 0xfb6d: case 0xfd6d: case 0xff6d: + case 0xf175: case 0xf375: case 0xf575: case 0xf775: case 0xf975: case 0xfb75: case 0xfd75: case 0xff75: + case 0xf17d: case 0xf37d: case 0xf57d: case 0xf77d: case 0xf97d: case 0xfb7d: case 0xfd7d: case 0xff7d: + // nothing + return; + + // these are in code that otherwise seems like ISA1.0 / 1.1 (jak_disf for example) but spec says it's only in ISA 1.2? + case 0xf148: case 0xf348: case 0xf548: case 0xf748: case 0xf948: case 0xfb48: case 0xfd48: case 0xff48: + m_core->m_enable_irq = 0; + return; + + case 0xf149: case 0xf349: case 0xf549: case 0xf749: case 0xf949: case 0xfb49: case 0xfd49: case 0xff49: + m_core->m_enable_irq = 1; + return; + + case 0xf14c: case 0xf34c: case 0xf54c: case 0xf74c: case 0xf94c: case 0xfb4c: case 0xfd4c: case 0xff4c: + m_core->m_enable_fiq = 0; + return; + + case 0xf14e: case 0xf34e: case 0xf54e: case 0xf74e: case 0xf94e: case 0xfb4e: case 0xfd4e: case 0xff4e: + m_core->m_enable_fiq = 1; + return; + + default: + unimplemented_opcode(op); + return; + } + + return; +} + + +inline void unsp_device::execute_fxxx_110_group(uint16_t op) +{ + //uint32_t len = 1; + // | | | + // signed * signed (size 16,1,2,3,4,5,6,7) + // MULS 1 1 1 1* r r r 1* 1 0*s s s r r r (1* = sign bit, 1* = sign bit 0* = upper size bit) + + // MULS ss with upper size bit not set + unimplemented_opcode(op); + //return; +} + +inline void unsp_device::execute_fxxx_111_group(uint16_t op) +{ + //uint32_t len = 1; + // | | | + // EXTOP 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 (+16 bit imm) + if ((op == 0xffc0) && m_iso >= 20) + { + return execute_extended_group(op); + } + + // signed * signed (size 8,9,10,11,12,13,14,15) + // MULS 1 1 1 1* r r r 1* 1 1*s s s r r r (1* = sign bit, 1* = sign bit 1* = upper size bit) + + // MULS ss with upper size bit set. + unimplemented_opcode(op); + //return; +} + +void unsp_device::execute_fxxx_group(uint16_t op) +{ + switch ((op & 0x01c0) >> 6) + { + case 0x0: + return execute_fxxx_000_group(op); + + case 0x1: + return execute_fxxx_001_group(op); + + case 0x2: + return execute_fxxx_010_group(op); + + case 0x3: + return execute_fxxx_011_group(op); + + case 0x4: + return execute_fxxx_100_group(op); + + case 0x5: + return execute_fxxx_101_group(op); + + case 0x6: + return execute_fxxx_110_group(op); + + case 0x7: + return execute_fxxx_111_group(op); + + } + + return; +} diff --git a/src/devices/cpu/unsp/unsp_jumps.cpp b/src/devices/cpu/unsp/unsp_jumps.cpp new file mode 100644 index 00000000000..aa32f934ca5 --- /dev/null +++ b/src/devices/cpu/unsp/unsp_jumps.cpp @@ -0,0 +1,160 @@ +// license:GPL-2.0+ +// copyright-holders:Segher Boessenkool, Ryan Holtz, David Haywood + +#include "emu.h" +#include "unsp.h" +#include "unspfe.h" + +#include "debugger.h" + +#include "unspdasm.h" + +void unsp_device::execute_jumps(const uint16_t op) +{ + const uint16_t op0 = (op >> 12) & 15; + const uint16_t op1 = (op >> 6) & 7; + const uint32_t opimm = op & 0x3f; + + switch (op0) + { + case 0: // JB + if (!(m_core->m_r[REG_SR] & UNSP_C)) + { + m_core->m_icount -= 4; + add_lpc((op1 == 0) ? opimm : (0 - opimm)); + } + else + { + m_core->m_icount -= 2; + } + return; + case 1: // JAE + if (m_core->m_r[REG_SR] & UNSP_C) + { + m_core->m_icount -= 4; + add_lpc((op1 == 0) ? opimm : (0 - opimm)); + } + else + { + m_core->m_icount -= 2; + } + return; + case 2: // JGE + if (!(m_core->m_r[REG_SR] & UNSP_S)) + { + m_core->m_icount -= 4; + add_lpc((op1 == 0) ? opimm : (0 - opimm)); + } + else + { + m_core->m_icount -= 2; + } + return; + case 3: // JL + if (m_core->m_r[REG_SR] & UNSP_S) + { + m_core->m_icount -= 4; + add_lpc((op1 == 0) ? opimm : (0 - opimm)); + } + else + { + m_core->m_icount -= 2; + } + return; + case 4: // JNE + if (!(m_core->m_r[REG_SR] & UNSP_Z)) + { + m_core->m_icount -= 4; + add_lpc((op1 == 0) ? opimm : (0 - opimm)); + } + else + { + m_core->m_icount -= 2; + } + return; + case 5: // JE + if (m_core->m_r[REG_SR] & UNSP_Z) + { + m_core->m_icount -= 4; + add_lpc((op1 == 0) ? opimm : (0 - opimm)); + } + else + { + m_core->m_icount -= 2; + } + return; + case 6: // JPL + if (!(m_core->m_r[REG_SR] & UNSP_N)) + { + m_core->m_icount -= 4; + add_lpc((op1 == 0) ? opimm : (0 - opimm)); + } + else + { + m_core->m_icount -= 2; + } + return; + case 7: // JMI + if (m_core->m_r[REG_SR] & UNSP_N) + { + m_core->m_icount -= 4; + add_lpc((op1 == 0) ? opimm : (0 - opimm)); + } + else + { + m_core->m_icount -= 2; + } + return; + case 8: // JBE + if ((m_core->m_r[REG_SR] & (UNSP_Z | UNSP_C)) != UNSP_C) // branch if (!UNSP_Z && !UNSP_C) || UNSP_Z + { + m_core->m_icount -= 4; + add_lpc((op1 == 0) ? opimm : (0 - opimm)); + } + else + { + m_core->m_icount -= 2; + } + return; + case 9: // JA + if ((m_core->m_r[REG_SR] & (UNSP_Z | UNSP_C)) == UNSP_C) // branch if !UNSP_Z && UNSP_C + { + m_core->m_icount -= 4; + add_lpc((op1 == 0) ? opimm : (0 - opimm)); + } + else + { + m_core->m_icount -= 2; + } + return; + case 10: // JLE + if (m_core->m_r[REG_SR] & (UNSP_Z | UNSP_S)) + { + m_core->m_icount -= 4; + add_lpc((op1 == 0) ? opimm : (0 - opimm)); + } + else + { + m_core->m_icount -= 2; + } + return; + case 11: // JG + if (!(m_core->m_r[REG_SR] & (UNSP_Z | UNSP_S))) + { + m_core->m_icount -= 4; + add_lpc((op1 == 0) ? opimm : (0 - opimm)); + } + else + { + m_core->m_icount -= 2; + } + return; + case 14: // JMP + add_lpc((op1 == 0) ? opimm : (0 - opimm)); + m_core->m_icount -= 4; + return; + default: + unimplemented_opcode(op); + return; + } +} diff --git a/src/devices/cpu/unsp/unsp_other.cpp b/src/devices/cpu/unsp/unsp_other.cpp new file mode 100644 index 00000000000..9e9fb984cb4 --- /dev/null +++ b/src/devices/cpu/unsp/unsp_other.cpp @@ -0,0 +1,347 @@ +// license:GPL-2.0+ +// copyright-holders:Segher Boessenkool, Ryan Holtz, David Haywood + +#include "emu.h" +#include "unsp.h" +#include "unspfe.h" + +#include "debugger.h" + +#include "unspdasm.h" + +void unsp_device::execute_remaining(const uint16_t op) +{ + uint32_t lres = 0; + uint16_t r0 = 0; + uint16_t r1 = 0; + uint32_t r2 = 0; + + 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 (lower_op == 0x2d) // Push + { + r0 = opn; + r1 = opa; + m_core->m_icount -= 4 + 2 * r0; + + while (r0--) + { + push(m_core->m_r[r1--], &m_core->m_r[opb]); + } + return; + } + else if (lower_op == 0x29) + { + if (op == 0x9a98) // reti + { + 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_core->m_fiq) + { + m_core->m_fiq = 0; + m_core->m_saved_sb[2] = m_core->m_sb; + m_core->m_sb = m_core->m_saved_sb[m_core->m_irq ? 1 : 0]; + } + else if (m_core->m_irq) + { + m_core->m_irq = 0; + m_core->m_saved_sb[1] = m_core->m_sb; + m_core->m_sb = m_core->m_saved_sb[0]; + } + m_core->m_curirq = 0; + check_irqs(); + return; + } + else // pop + { + r0 = opn; + r1 = opa; + m_core->m_icount -= 4 + 2 * r0; + + while (r0--) + { + m_core->m_r[++r1] = pop(&m_core->m_r[opb]); + } + return; + } + } + + // At this point, we should be dealing solely with ALU ops. + + r0 = m_core->m_r[opa]; + + switch (op1) + { + case 0x00: // r, [bp+imm6] + m_core->m_icount -= 6; + + r2 = (uint16_t)(m_core->m_r[REG_BP] + (op & 0x3f)); + if (op0 != 0x0d) + r1 = read16(r2); + break; + + case 0x01: // r, imm6 + m_core->m_icount -= 2; + + r1 = op & 0x3f; + break; + + case 0x03: // Indirect + { + m_core->m_icount -= (opa == 7 ? 7 : 6); + + const uint8_t lsbits = opn & 3; + if (opn & 4) + { + switch (lsbits) + { + case 0: // r, [<ds:>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); + 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) + r1 = read16(r2); + 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] + 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) + r1 = read16(r2); + break; + default: + break; + } + } + else + { + switch (lsbits) + { + case 0: // r, [r] + r2 = m_core->m_r[opb]; + if (op0 != 0x0d) + r1 = read16(r2); + break; + case 1: // r, [r--] + r2 = m_core->m_r[opb]; + if (op0 != 0x0d) + r1 = read16(r2); + m_core->m_r[opb] = (uint16_t)(m_core->m_r[opb] - 1); + break; + case 2: // r, [r++] + r2 = m_core->m_r[opb]; + if (op0 != 0x0d) + r1 = read16(r2); + m_core->m_r[opb] = (uint16_t)(m_core->m_r[opb] + 1); + break; + case 3: // r, [++r] + 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: + break; + } + } + break; + } + + case 0x04: // 16-bit ops + switch (opn) + { + case 0x00: // r + m_core->m_icount -= (opa == 7 ? 5 : 3); + r1 = m_core->m_r[opb]; + break; + + case 0x01: // imm16 + 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_core->m_icount -= (opa == 7 ? 8 : 7); + r0 = m_core->m_r[opb]; + r2 = read16(UNSP_LPC); + add_lpc(1); + + if (op0 != 0x0d) + { + r1 = read16(r2); + } + break; + + case 0x03: // store [imm16], r + m_core->m_icount -= (opa == 7 ? 8 : 7); + r1 = r0; + r0 = m_core->m_r[opb]; + r2 = read16(UNSP_LPC); + add_lpc(1); + break; + + default: // Shifted ops + { + 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_core->m_sb = shift & 0x0f; + r1 = (uint16_t)(shift >> 4); + break; + } + } + break; + + case 0x05: // More shifted ops + m_core->m_icount -= (opa == 7 ? 5 : 3); + + if (opn & 4) // Shift right + { + 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_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_core->m_icount -= (opa == 7 ? 5 : 3); + + 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_core->m_sb = shift & 0x0f; + } + else + { + shift <<= (opn + 1); + m_core->m_sb = (shift >> 20) & 0x0f; + } + r1 = (uint16_t)(shift >> 4); + break; + } + + case 0x07: // Direct 8 + m_core->m_icount -= (opa == 7 ? 6 : 5); + r2 = op & 0x3f; + r1 = read16(r2); + break; + + default: + break; + } + + switch (op0) + { + case 0x00: // Add + { + lres = r0 + r1; + if (opa != 7) + update_nzsc(lres, r0, r1); + break; + } + case 0x01: // Add w/ carry + { + 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 + lres = r0 + (uint16_t)(~r1) + uint32_t(1); + if (opa != 7) + update_nzsc(lres, r0, ~r1); + break; + case 0x03: // Subtract w/ carry + { + uint32_t c = (m_core->m_r[REG_SR] & UNSP_C) ? 1 : 0; + lres = r0 + (uint16_t)(~r1) + c; + if (opa != 7) + 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 + 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; + + default: + unimplemented_opcode(op); + return; + } + + if (op1 == 0x04 && opn == 0x03) // store [imm16], r + write16(r2, lres); + else + m_core->m_r[opa] = (uint16_t)lres; +} diff --git a/src/devices/cpu/unsp/unspdasm.cpp b/src/devices/cpu/unsp/unspdasm.cpp index a69379b555b..3b52b519af3 100644 --- a/src/devices/cpu/unsp/unspdasm.cpp +++ b/src/devices/cpu/unsp/unspdasm.cpp @@ -1,5 +1,5 @@ // license:GPL-2.0+ -// copyright-holders:Segher Boessenkool +// copyright-holders:Segher Boessenkool, David Haywood /***************************************************************************** SunPlus µ'nSP disassembler @@ -13,18 +13,42 @@ #include "emu.h" #include "unspdasm.h" -char const *const unsp_disassembler::regs[] = +char const* const unsp_disassembler::regs[] = { "sp", "r1", "r2", "r3", "r4", "bp", "sr", "pc" }; -char const *const unsp_disassembler::jumps[] = +char const* const unsp_disassembler::bitops[] = { - "jb", "jae", "jge", "jl", "jne", "je", "jpl", "jmi", - "jbe", "ja", "jle", "jg", "jvc", "jvs", "jmp", "<inv>" + "tstb", "setb", "clrb", "invb" }; -#define UNSP_DASM_OK (len | SUPPORTED) +char const* const unsp_disassembler::signmodes[] = +{ + "uu", "us", "su?", "ss" // su? might be invalid +}; + +char const* const unsp_disassembler::lsft[] = +{ + "asr", "asror", "lsl", "lslor", "lsr", "lsror", "rol", "ror" +}; + +char const* const unsp_disassembler::extregs[] = +{ + "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15" +}; + + +// TODO: use alu_op_start-like formatting +char const* const unsp_disassembler::aluops[] = +{ + "add","adc","sub","sbc","cmp","(invalid)","neg","--","xor","load","or","and","test","store","(invalid)","(invalid)" +}; + +char const* const unsp_disassembler::forms[] = +{ + "[%s]", "[%s--]", "[%s++]", "[++%s]" +}; u32 unsp_disassembler::opcode_alignment() const { @@ -57,6 +81,38 @@ void unsp_disassembler::print_alu_op3(std::ostream &stream, uint8_t op0, uint8_t util::stream_format(stream, alu_op3[op0], regs[opB]); } +void unsp_disassembler::print_mul(std::ostream& stream, uint16_t op) +{ + int rs = (op & 0x0007) >> 0; + // (op & 0x0078) >> 3; fixed 0001 + // (op & 0x0080) >> 7; fixed 0 + int srd = (op & 0x0100) >> 8; + int rd = (op & 0x0e00) >> 9; + int srs = (op & 0x1000) >> 12; + // (op & 0xe000) >> 13; fixed 111 + + int sign = (srs << 1) | srd; + + util::stream_format(stream, "MR = %s*%s, %s", regs[rd], regs[rs], signmodes[sign] ); +} + +void unsp_disassembler::print_muls(std::ostream& stream, uint16_t op) +{ + int rs = (op & 0x0007) >> 0; + int size = (op & 0x0078) >> 3; + // (op & 0x0080) >> 7; fixed 1 + int srd = (op & 0x0100) >> 8; + int rd = (op & 0x0e00) >> 9; + int srs = (op & 0x1000) >> 12; + // (op & 0xe000) >> 13; fixed 111 + + int sign = (srs << 1) | srd; + if (size == 0) size = 16; + + util::stream_format(stream, "MR = [%s]*[%s], %s, %d", regs[rd], regs[rs], signmodes[sign], size ); +} + + void unsp_disassembler::print_alu_op_end(std::ostream &stream, uint8_t op0) { if (op0 == 1 || op0 == 3) @@ -65,78 +121,16 @@ void unsp_disassembler::print_alu_op_end(std::ostream &stream, uint8_t op0) void unsp_disassembler::print_indirect_op(std::ostream &stream, uint8_t opN, uint8_t opB) { - 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_f_group(std::ostream& stream, offs_t pc, uint16_t op, uint16_t ximm, uint8_t opN, uint8_t opA, uint8_t opB, uint32_t len) -{ - switch (opN) - { - case 1: - if (opA == 7) - { - util::stream_format(stream, "<DUNNO f group>"); - 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 f group>"); - return UNSP_DASM_OK; - } -} - -offs_t unsp_newer_disassembler::disassemble_f_group(std::ostream& stream, offs_t pc, uint16_t op, uint16_t ximm, uint8_t opN, uint8_t opA, uint8_t opB, uint32_t len) -{ - // these are new opcodes on the later core - - switch (opN) - { - case 1: - if (opA == 7) - { - util::stream_format(stream, "<EXTENDED f group>"); - 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, "<EXTENDED f group>"); - return UNSP_DASM_OK; - } -} - -offs_t unsp_disassembler::disassemble(std::ostream &stream, offs_t pc, uint16_t op, uint16_t ximm) +offs_t unsp_disassembler::disassemble_code(std::ostream &stream, offs_t pc, uint16_t op, uint16_t ximm, const data_buffer &opcodes) { - // 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))) - { - len = 2; - } // all-zero and all-one are invalid insns: if (op == 0 || op == 0xffff) @@ -145,325 +139,29 @@ offs_t unsp_disassembler::disassemble(std::ostream &stream, offs_t pc, uint16_t return UNSP_DASM_OK; } - // first, check for the conditional branch insns - if (op0 < 15 && opA == 7 && op1 == 0) - { - 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; - - - 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; - - // alu, 16-bit immediate - case 1: - if ((op0 == 4 || op0 == 12 || op0 == 6 || op0 == 9) && opA != opB) - { - util::stream_format(stream, "<BAD>"); - return UNSP_DASM_OK; - } - 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, "<BAD>"); - return UNSP_DASM_OK; - } - 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 3: - if (op0 == 4 || op0 == 12) - { - util::stream_format(stream, "<BAD>"); - return UNSP_DASM_OK; - } - if ((op0 == 6 || op0 == 9) && opA != opB) - { - 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, 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) - { - util::stream_format(stream, "<BAD>"); - return UNSP_DASM_OK; - } - util::stream_format(stream, "[%04x] = %s", ximm, regs[opB]); - return UNSP_DASM_OK; - 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, 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; - + uint8_t op0 = (op >> 12); - // 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; + if (op0 == 0xf) + return disassemble_fxxx_group(stream, pc, op, ximm, opcodes); + uint8_t opA = (op >> 9) & 7; + uint8_t op1 = (op >> 6) & 7; - 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; + if (op0 < 15 && opA == 7 && op1 < 2) + return disassemble_jumps(stream, pc, op); - 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; + if (op0 == 0xe) + return disassemble_exxx_group(stream, pc, op, ximm); + return disassemble_remaining(stream, pc, op, ximm, opcodes); +} - case 0x0f: - return disassemble_f_group(stream, pc, op, ximm, opN, opA, opB, len); - - case 0x4f: - switch (opN) - { - case 1: - if (opA == 7) - { - util::stream_format(stream, "<DUNNO>"); - return UNSP_DASM_OK; - } - 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; - } - return UNSP_DASM_OK; -} offs_t unsp_disassembler::disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer ¶ms) { uint16_t op = opcodes.r16(pc); uint16_t imm16 = opcodes.r16(pc+1); - return disassemble(stream, pc, op, imm16); + return disassemble_code(stream, pc, op, imm16, opcodes); } diff --git a/src/devices/cpu/unsp/unspdasm.h b/src/devices/cpu/unsp/unspdasm.h index cd896b03ea7..32d73605b76 100644 --- a/src/devices/cpu/unsp/unspdasm.h +++ b/src/devices/cpu/unsp/unspdasm.h @@ -1,5 +1,5 @@ // license:GPL-2.0 -// copyright-holders:Segher Boessenkool +// copyright-holders:Segher Boessenkool, David Haywood /***************************************************************************** SunPlus µ'nSP disassembler @@ -15,39 +15,88 @@ #pragma once +#define UNSP_DASM_OK (len | SUPPORTED) + class unsp_disassembler : public util::disasm_interface { public: - unsp_disassembler() = default; + unsp_disassembler() + { + m_iso = 10; + } + virtual ~unsp_disassembler() = default; virtual u32 opcode_alignment() const override; virtual offs_t disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer ¶ms) override; - offs_t disassemble(std::ostream &stream, offs_t pc, uint16_t op, uint16_t imm16); + offs_t disassemble_code(std::ostream &stream, offs_t pc, uint16_t op, uint16_t imm16, const data_buffer& opcodes); protected: - virtual offs_t disassemble_f_group(std::ostream& stream, offs_t pc, uint16_t op, uint16_t ximm, uint8_t opN, uint8_t opA, uint8_t opB, uint32_t len); + offs_t disassemble_fxxx_group(std::ostream& stream, offs_t pc, uint16_t op, uint16_t ximm, const data_buffer& opcodes); + offs_t disassemble_jumps(std::ostream& stream, offs_t pc, const uint16_t op); + offs_t disassemble_remaining(std::ostream& stream, offs_t pc, uint16_t op, uint16_t ximm, const data_buffer& opcodes); + + offs_t disassemble_fxxx_000_group(std::ostream& stream, offs_t pc, uint16_t op, uint16_t ximm); + offs_t disassemble_fxxx_001_group(std::ostream& stream, offs_t pc, uint16_t op, uint16_t ximm); + offs_t disassemble_fxxx_010_group(std::ostream& stream, offs_t pc, uint16_t op, uint16_t ximm); + offs_t disassemble_fxxx_011_group(std::ostream& stream, offs_t pc, uint16_t op, uint16_t ximm); + offs_t disassemble_fxxx_100_group(std::ostream& stream, offs_t pc, uint16_t op, uint16_t ximm); + virtual offs_t disassemble_fxxx_101_group(std::ostream& stream, offs_t pc, uint16_t op, uint16_t ximm); + offs_t disassemble_fxxx_110_group(std::ostream& stream, offs_t pc, uint16_t op, uint16_t ximm); + offs_t disassemble_fxxx_111_group(std::ostream& stream, offs_t pc, uint16_t op, uint16_t ximm, const data_buffer& opcodes); + + virtual offs_t disassemble_exxx_group(std::ostream& stream, offs_t pc, uint16_t op, uint16_t ximm); + virtual offs_t disassemble_extended_group(std::ostream& stream, offs_t pc, uint16_t op, uint16_t ximm, const data_buffer& opcodes); static char const *const regs[]; + static char const *const extregs[]; static char const *const jumps[]; + static char const *const bitops[]; + static char const *const signmodes[]; + static char const *const lsft[]; + static char const *const aluops[]; + static char const *const forms[]; -private: + int m_iso; + +protected: 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); + void print_muls(std::ostream& stream, uint16_t op); + void print_mul(std::ostream& stream, uint16_t op); }; -class unsp_newer_disassembler : public unsp_disassembler +class unsp_12_disassembler : public unsp_disassembler { public: - unsp_newer_disassembler() = default; - virtual ~unsp_newer_disassembler() = default; + unsp_12_disassembler() + { + m_iso = 12; + } + + virtual ~unsp_12_disassembler() = default; + +private: + virtual offs_t disassemble_fxxx_101_group(std::ostream& stream, offs_t pc, uint16_t op, uint16_t ximm) override; + virtual offs_t disassemble_exxx_group(std::ostream& stream, offs_t pc, uint16_t op, uint16_t ximm) override; +}; + +class unsp_20_disassembler : public unsp_12_disassembler +{ +public: + unsp_20_disassembler() + { + m_iso = 20; + } + + virtual ~unsp_20_disassembler() = default; private: - virtual offs_t disassemble_f_group(std::ostream& stream, offs_t pc, uint16_t op, uint16_t ximm, uint8_t opN, uint8_t opA, uint8_t opB, uint32_t len) override; + virtual offs_t disassemble_extended_group(std::ostream& stream, offs_t pc, uint16_t op, uint16_t ximm, const data_buffer& opcodes) override; }; diff --git a/src/devices/cpu/unsp/unspdasm_extended.cpp b/src/devices/cpu/unsp/unspdasm_extended.cpp new file mode 100644 index 00000000000..a64f726c332 --- /dev/null +++ b/src/devices/cpu/unsp/unspdasm_extended.cpp @@ -0,0 +1,193 @@ +// license:GPL-2.0+ +// copyright-holders:Segher Boessenkool, David Haywood +/***************************************************************************** + + SunPlus µ'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" + +offs_t unsp_disassembler::disassemble_extended_group(std::ostream& stream, offs_t pc, uint16_t op, uint16_t ximm, const data_buffer& opcodes) +{ + // shouldn't get here anyway + int len = 1; + util::stream_format(stream, "<UNKNOWN EXTENDED>"); + return UNSP_DASM_OK; +} + +offs_t unsp_20_disassembler::disassemble_extended_group(std::ostream& stream, offs_t pc, uint16_t op, uint16_t ximm,const data_buffer &opcodes) +{ + uint32_t len = 2; + + switch ((ximm & 0x01f0) >> 4) + { + case 0x00: case 0x10: + { + // Ext Register Ra = Ra op Rb + uint8_t aluop = (op & 0xf000) >> 12; + uint8_t rb = (op & 0x000f) >> 0; + uint8_t ra = (op & 0x0e00) >> 9; + ra |= (op & 0x0100) >> 5; + + util::stream_format(stream, "(Ext) %s = %s %s %s", (ra & 0x8) ? extregs[ra & 0x7] : regs[ra & 0x7] + , (ra & 0x8) ? extregs[ra & 0x7] : regs[ra & 0x7] + , aluops[aluop] + , (rb & 0x8) ? extregs[rb & 0x7] : regs[rb & 0x7]); + return UNSP_DASM_OK; + } + case 0x02: + { + // Ext Push/Pop + if (op & 0x8000) + { + uint8_t rb = (op & 0x000f) >> 0; + uint8_t size = (op & 0x7000) >> 12; + uint8_t rx = (op & 0x0e00) >> 9; + + if (rx+1 >= size && rx < size+7) + util::stream_format(stream, "(Ext) push %s, %s to [%s]", + extregs[rx+1-size], extregs[rx], (rb & 0x8) ? extregs[rb & 0x7] : regs[rb & 0x7]); + else + util::stream_format(stream, "(Ext) push <BAD>"); + } + else + { + uint8_t rb = (op & 0x000f) >> 0; + uint8_t size = (op & 0x7000) >> 12; + uint8_t rx = (op & 0x0e00) >> 9; + + if (rx+1 < 8 && rx+size < 8) + util::stream_format(stream, "(Ext) pop %s, %s from [%s]", + extregs[rx+1], extregs[rx+size], (rb & 0x8) ? extregs[rb & 0x7] : regs[rb & 0x7]); + else + util::stream_format(stream, "(Ext) pop <BAD>"); + } + return UNSP_DASM_OK; + } + case 0x04: case 0x14: + { + // Ra=Rb op IMM16 + len = 3; + uint16_t imm16_2 = opcodes.r16(pc + 2); + uint8_t aluop = (op & 0xf000) >> 12; + uint8_t rb = (op & 0x000f) >> 0; + uint8_t ra = (op & 0x0e00) >> 9; + ra |= (op & 0x0100) >> 5; + + util::stream_format(stream, "(Ext) %s = %s %s %04x", (ra & 0x8) ? extregs[ra & 0x7] : regs[ra & 0x7] + , (rb & 0x8) ? extregs[rb & 0x7] : regs[rb & 0x7] + , aluops[aluop] + , imm16_2); + return UNSP_DASM_OK; + } + + case 0x06: + case 0x16: + { + // Ra=Rb op [A16] + len = 3; + uint16_t imm16_2 = opcodes.r16(pc + 2); + uint8_t aluop = (op & 0xf000) >> 12; + uint8_t rb = (op & 0x000f) >> 0; + uint8_t ra = (op & 0x0e00) >> 9; + ra |= (op & 0x0100) >> 5; + + util::stream_format(stream, "(Ext) %s = %s %s [%04x]", (ra & 0x8) ? extregs[ra & 0x7] : regs[ra & 0x7] + , (rb & 0x8) ? extregs[rb & 0x7] : regs[rb & 0x7] + , aluops[aluop] + , imm16_2); + return UNSP_DASM_OK; + } + + case 0x07: + case 0x17: + { + //[A16] = Ra op Rb + len = 3; + uint16_t imm16_2 = opcodes.r16(pc + 2); + uint8_t aluop = (op & 0xf000) >> 12; + uint8_t rb = (op & 0x000f) >> 0; + uint8_t ra = (op & 0x0e00) >> 9; + ra |= (op & 0x0100) >> 5; + + util::stream_format(stream, "(Ext) [0x4x] = %s %s %s", imm16_2 + , (ra & 0x8) ? extregs[ra & 0x7] : regs[ra & 0x7] + , aluops[aluop] + , (rb & 0x8) ? extregs[rb & 0x7] : regs[rb & 0x7]); + return UNSP_DASM_OK; + } + + case 0x08: case 0x09: + { + // Ext Indirect Rx=Rx op [Ry@] + + uint8_t aluop = (op & 0xf000) >> 12; + uint8_t ry = (op & 0x0007) >> 0; + uint8_t form = (op & 0x0018) >> 3; + uint8_t rx = (op & 0x0e00) >> 9; + + util::stream_format(stream, "(Ext) %s=%s %s", extregs[rx], extregs[rx], aluops[aluop]); + util::stream_format(stream, forms[form], extregs[ry]); + + return UNSP_DASM_OK; + } + case 0x0a: case 0x0b: + { + // Ext DS_Indirect Rx=Rx op ds:[Ry@] + + uint8_t aluop = (op & 0xf000) >> 12; + uint8_t ry = (op & 0x0007) >> 0; + uint8_t form = (op & 0x0018) >> 3; + uint8_t rx = (op & 0x0e00) >> 9; + + util::stream_format(stream, "(Ext) %s=%s %s ds:", extregs[rx], extregs[rx], aluops[aluop]); + util::stream_format(stream, forms[form], extregs[ry]); + + return UNSP_DASM_OK; + } + case 0x18: case 0x19: case 0x1a: case 0x1b: + { + // Ext IM6 Rx=Rx op IM6 + + uint8_t aluop = (op & 0xf000) >> 12; + uint8_t rx = (op & 0x0e00) >> 9; + uint8_t imm6 = (op & 0x003f) >> 0; + + util::stream_format(stream, "(Ext) %s=%s %s %02x", extregs[rx], extregs[rx], aluops[aluop], imm6 ); + return UNSP_DASM_OK; + } + + case 0x0c: case 0x0d: case 0x0e: case 0x0f: + { + // Ext Base+Disp6 Rx=Rx op [BP+IM6] + + uint8_t aluop = (op & 0xf000) >> 12; + uint8_t rx = (op & 0x0e00) >> 9; + uint8_t imm6 = (op & 0x003f) >> 0; + + util::stream_format(stream, "(Ext) %s=%s %s [BP+%02x]", extregs[rx], extregs[rx], aluops[aluop], imm6 ); + return UNSP_DASM_OK; + } + + case 0x1c: case 0x1d: case 0x1e: case 0x1f: + { + // Ext A6 Rx=Rx op [A6] + + uint8_t aluop = (op & 0xf000) >> 12; + uint8_t rx = (op & 0x0e00) >> 9; + uint8_t a6 = (op & 0x003f) >> 0; + + util::stream_format(stream, "(Ext) %s=%s %s [%02x]", extregs[rx], extregs[rx], aluops[aluop], a6 ); + return UNSP_DASM_OK; + } + } + + util::stream_format(stream, "<UNKNOWN EXTENDED>"); + return UNSP_DASM_OK; +} diff --git a/src/devices/cpu/unsp/unspdasm_exxx.cpp b/src/devices/cpu/unsp/unspdasm_exxx.cpp new file mode 100644 index 00000000000..43c494cc0a5 --- /dev/null +++ b/src/devices/cpu/unsp/unspdasm_exxx.cpp @@ -0,0 +1,117 @@ +// license:GPL-2.0+ +// copyright-holders:Segher Boessenkool, David Haywood +/***************************************************************************** + + SunPlus µ'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" + +offs_t unsp_disassembler::disassemble_exxx_group(std::ostream& stream, offs_t pc, uint16_t op, uint16_t ximm) +{ + uint32_t len = 1; + // several exxx opcodes have already been decoded as jumps by the time we get here + util::stream_format(stream, "<DUNNO>"); + return UNSP_DASM_OK; +} + +offs_t unsp_12_disassembler::disassemble_exxx_group(std::ostream& stream, offs_t pc, uint16_t op, uint16_t ximm) +{ + uint32_t len = 1; + // several exxx opcodes have already been decoded as jumps by the time we get here + + // Register BITOP BITOP Rd,Rs 1 1 1 0 r r r 0 0 0 b b 0 r r r + // Register BITOP BITOP Rd,offset 1 1 1 0 r r r 0 0 1 b b o o o o + // Memory BITOP BITOP [Rd], offset 1 1 1 0 r r r 1 1 0 b b o o o o + // Memory BITOP BITOP ds:[Rd], offset 1 1 1 0 r r r 1 1 1 b b o o o o + // Memory BITOP BITOP [Rd], Rs 1 1 1 0 r r r 1 0 0 b b 0 r r r + // Memory BITOP BITOP ds:[Rd], Rs 1 1 1 0 r r r 1 0 1 b b 0 r r r + + if (((op & 0xf1c8) == 0xe000)) + { + // Register BITOP BITOP Rd,Rs + uint8_t bitop = (op & 0x0030) >> 4; + uint8_t rd = (op & 0x0e00) >> 9; + uint8_t rs = (op & 0x0007) >> 0; + util::stream_format(stream, "%s %s,%s", bitops[bitop], regs[rd], regs[rs]); + return UNSP_DASM_OK; + } + else if (((op & 0xf1c0) == 0xe040)) + { + // Register BITOP BITOP Rd,offset + uint8_t bitop = (op & 0x0030) >> 4; + uint8_t rd = (op & 0x0e00) >> 9; + uint8_t offset = (op & 0x000f) >> 0; + util::stream_format(stream, "%s %s,%d", bitops[bitop], regs[rd], offset); + return UNSP_DASM_OK; + } + else if (((op & 0xf1c0) == 0xe180)) + { + // Memory BITOP BITOP [Rd], offset + uint8_t bitop = (op & 0x0030) >> 4; + uint8_t rd = (op & 0x0e00) >> 9; + uint8_t offset = (op & 0x000f) >> 0; + util::stream_format(stream, "%s [%s],%d", bitops[bitop], regs[rd], offset); + return UNSP_DASM_OK; + } + else if (((op & 0xf1c0) == 0xe1c0)) + { + // Memory BITOP BITOP ds:[Rd], offset + uint8_t bitop = (op & 0x0030) >> 4; + uint8_t rd = (op & 0x0e00) >> 9; + uint8_t offset = (op & 0x000f) >> 0; + util::stream_format(stream, "%s ds:[%s],%d", bitops[bitop], regs[rd], offset); + return UNSP_DASM_OK; + } + else if (((op & 0xf1c8) == 0xe100)) + { + // Memory BITOP BITOP [Rd], Rs + uint8_t bitop = (op & 0x0030) >> 4; + uint8_t rd = (op & 0x0e00) >> 9; + uint8_t rs = (op & 0x0007) >> 0; + util::stream_format(stream, "%s [%s],%s", bitops[bitop], regs[rd], regs[rs]); + return UNSP_DASM_OK; + } + else if (((op & 0xf1c8) == 0xe140)) + { + // Memory BITOP BITOP ds:[Rd], Rs + uint8_t bitop = (op & 0x0030) >> 4; + uint8_t rd = (op & 0x0e00) >> 9; + uint8_t rs = (op & 0x0007) >> 0; + util::stream_format(stream, "%s ds:[%s],%s", bitops[bitop], regs[rd], regs[rs]); + return UNSP_DASM_OK; + } + else if (((op & 0xf0f8) == 0xe008)) + { + // MUL operations + // MUL 1 1 1 0* r r r S* 0 0 0 0 1 r r r (* = sign bit, fixed here) + print_mul(stream, op); // MUL uu or MUL su (invalid?) + return UNSP_DASM_OK; + } + else if (((op & 0xf080) == 0xe080)) + { + // MULS 1 1 1 0* r r r S* 1 s s s s r r r (* = sign bit, fixed here) + + // MULS uu or MULS su (invalid?) + print_muls(stream, op); + return UNSP_DASM_OK; + } + else if (((op & 0xf188) == 0xe108)) + { + // 16 bit Shift 1 1 1 0 r r r 1 0 l l l 1 r r r + uint8_t rd = (op & 0x0e00) >> 9; + uint8_t shift = (op & 0x0070) >> 4; + uint8_t rs = (op & 0x0007) >> 0; + util::stream_format(stream, "%s = %s %s %s", regs[rd], regs[rd], lsft[shift], regs[rs]); + return UNSP_DASM_OK; + } + + util::stream_format(stream, "<DUNNO>"); + return UNSP_DASM_OK; +} diff --git a/src/devices/cpu/unsp/unspdasm_fxxx.cpp b/src/devices/cpu/unsp/unspdasm_fxxx.cpp new file mode 100644 index 00000000000..55ace86f178 --- /dev/null +++ b/src/devices/cpu/unsp/unspdasm_fxxx.cpp @@ -0,0 +1,371 @@ +// license:GPL-2.0+ +// copyright-holders:Segher Boessenkool, David Haywood +/***************************************************************************** + + SunPlus µ'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" + +offs_t unsp_disassembler::disassemble_fxxx_000_group(std::ostream& stream, offs_t pc, uint16_t op, uint16_t ximm) +{ + // | | | + // DS16 1 1 1 1 1 1 1 0 0 0 i i i i i i + // DS Reg 1 1 1 1 - - - 0 0 0 1 0 w r r r + // FR Reg 1 1 1 1 - - - 0 0 0 1 1 w r r r + uint32_t len = 1; + + if (((op & 0xffc0) == 0xfe00) && m_iso >= 12) + { + int imm = op & 0x003f; + util::stream_format(stream, "ds = %02x", imm); + return UNSP_DASM_OK; + } + else if (((op & 0xf1f8) == 0xf020) && m_iso >= 12) + { + int r = op & 0x7; + util::stream_format(stream, "%s = ds", regs[r]); + return UNSP_DASM_OK; + } + else if (((op & 0xf1f8) == 0xf028) && m_iso >= 12) + { + int r = op & 0x7; + util::stream_format(stream, "ds = %s", regs[r]); + return UNSP_DASM_OK; + } + else if (((op & 0xf1f8) == 0xf030) && m_iso >= 12) + { + int r = op & 0x7; + util::stream_format(stream, "%s = fr", regs[r]); + return UNSP_DASM_OK; + } + else if (((op & 0xf1f8) == 0xf038) && m_iso >= 12) + { + int r = op & 0x7; + util::stream_format(stream, "fr = %s", regs[r]); + return UNSP_DASM_OK; + } + + // everything else falls through to the multiply + + // signed * unsigned + // MUL 1 1 1 1* r r r 0* 0 0 0 0 1 r r r (** = sign bits, fixed here) + print_mul(stream, op); // MUL us + return UNSP_DASM_OK; +} + +offs_t unsp_disassembler::disassemble_fxxx_001_group(std::ostream& stream, offs_t pc, uint16_t op, uint16_t ximm) +{ + // | | | + // CALL16 1 1 1 1 - - 0 0 0 1 a a a a a a (+imm16) + + uint32_t len = 1; + + if ((op & 0xf3c0) == 0xf040) + { + len = 2; + uint8_t opimm = op & 0x3f; + util::stream_format(stream, "call %06x", (opimm << 16) | ximm); + return UNSP_DASM_OK; + } + // MEM bitop 1 1 1 1 - D 1 0 0 1 b b o o o o (+imm16) ( BITOP {ds:}[A16],offset ) + else if (((op & 0xf3c0) == 0xf240) && m_iso >= 20) + { + len = 2; + uint8_t bitop = (op & 0x0030) >> 4; + uint8_t offset = (op & 0x000f) >> 0; + uint8_t d = (op & 0x0400) >> 10; + + if (d) + util::stream_format(stream, "%s ds:[$04x],%d", bitops[bitop], offset); + else + util::stream_format(stream, "%s [$04x],%d", bitops[bitop], offset); + + return UNSP_DASM_OK; + } + + util::stream_format(stream, "<DUNNO>"); + return UNSP_DASM_OK; +} + +offs_t unsp_disassembler::disassemble_fxxx_010_group(std::ostream& stream, offs_t pc, uint16_t op, uint16_t ximm) +{ + uint32_t len = 1; + // | | | + // JMPF 1 1 1 1 1 1 1 0 1 0 a a a a a a (+imm16) + + if ((op & 0xffc0) == 0xfe80) // apparently 1.2 and above, but jak_capb needs it and otherwise seems 1.0 / 1.1? + { + len = 2; + uint8_t opimm = op & 0x3f; + util::stream_format(stream, "goto %06x", (opimm << 16) | ximm); + return UNSP_DASM_OK; + } + + // signed * unsigned (size 16,1,2,3,4,5,6,7) + // MULS 1 1 1 1* r r r 0* 1 0*s s s r r r (1* = sign bit, 0* = sign bit 0* = upper size bit) + + // MULS us with upper size bit not set + print_muls(stream, op); + return UNSP_DASM_OK; +} + +offs_t unsp_disassembler::disassemble_fxxx_011_group(std::ostream& stream, offs_t pc, uint16_t op, uint16_t ximm) +{ + uint32_t len = 1; + // | | | + // JMPR 1 1 1 1 1 1 1 0 1 1 - - - - - - + if (((op & 0xffc0) == 0xfec0) && m_iso >= 12) + { + util::stream_format(stream, "goto mr"); + return UNSP_DASM_OK; + } + + // signed * unsigned (size 8,9,10,11,12,13,14,15) + // MULS 1 1 1 1* r r r 0* 1 1*s s s r r r (1* = sign bit, 0* = sign bit 1* = upper size bit) + + // MULS us with upper size bit set + print_muls(stream, op); + + return UNSP_DASM_OK; +} + +offs_t unsp_disassembler::disassemble_fxxx_100_group(std::ostream& stream, offs_t pc, uint16_t op, uint16_t ximm) +{ + uint32_t len = 1; + // | | | + // signed * signed + // MUL 1 1 1 1* r r r 1* 0 0 0 0 1 r r r (** = sign bits, fixed here) + + if ((op & 0xf1f8) == 0xf108) + { + print_mul(stream, op); // MUL ss + return UNSP_DASM_OK; + } + + util::stream_format(stream, "<DUNNO>"); + return UNSP_DASM_OK; +} + + +offs_t unsp_12_disassembler::disassemble_fxxx_101_group(std::ostream& stream, offs_t pc, uint16_t op, uint16_t ximm) +{ + // IRQ 1 1 1 1 - - - 1 0 1 0 0 1 0 0 I + // FIRQ 1 1 1 1 - - - 1 0 1 0 0 1 1 F 0 + // FIR_MOV 1 1 1 1 - - - 1 0 1 0 0 0 1 0 f + // Fraction 1 1 1 1 - - - 1 0 1 0 0 0 1 1 f + // SECBANK 1 1 1 1 - - - 1 0 1 0 0 1 0 1 S + // NESTMODE 1 1 1 1 - - - 1 0 1 0 0 1 1 N 1 + // CALLR 1 1 1 1 - - - 1 0 1 1 - - 0 0 1 + // DIVS 1 1 1 1 - - - 1 0 1 1 - - 0 1 0 + // DIVQ 1 1 1 1 - - - 1 0 1 1 - - 0 1 1 + // EXP 1 1 1 1 - - - 1 0 1 1 - - 1 0 0 + + uint32_t len = 1; + + switch (op) + { + case 0xf146: case 0xf346: case 0xf546: case 0xf746: case 0xf946: case 0xfb46: case 0xfd46: case 0xff46: + util::stream_format(stream, "fraction off"); + return UNSP_DASM_OK; + + case 0xf147: case 0xf347: case 0xf547: case 0xf747: case 0xf947: case 0xfb47: case 0xfd47: case 0xff47: + util::stream_format(stream, "fraction on"); + return UNSP_DASM_OK; + + case 0xf14a: case 0xf34a: case 0xf54a: case 0xf74a: case 0xf94a: case 0xfb4a: case 0xfd4a: case 0xff4a: + util::stream_format(stream, "secbank off"); + return UNSP_DASM_OK; + + case 0xf14b: case 0xf34b: case 0xf54b: case 0xf74b: case 0xf94b: case 0xfb4b: case 0xfd4b: case 0xff4b: + util::stream_format(stream, "secbank on"); + return UNSP_DASM_OK; + + case 0xf14d: case 0xf34d: case 0xf54d: case 0xf74d: case 0xf94d: case 0xfb4d: case 0xfd4d: case 0xff4d: + util::stream_format(stream, "irqnest off"); + return UNSP_DASM_OK; + + case 0xf14f: case 0xf34f: case 0xf54f: case 0xf74f: case 0xf94f: case 0xfb4f: case 0xfd4f: case 0xff4f: + util::stream_format(stream, "irqnest on"); + return UNSP_DASM_OK; + + case 0xf144: case 0xf344: case 0xf544: case 0xf744: case 0xf944: case 0xfb44: case 0xfd44: case 0xff44: + util::stream_format(stream, "fir_mov on"); + return UNSP_DASM_OK; + + case 0xf145: case 0xf345: case 0xf545: case 0xf745: case 0xf945: case 0xfb45: case 0xfd45: case 0xff45: + util::stream_format(stream, "fir_mov off"); + return UNSP_DASM_OK; + + case 0xf161: case 0xf361: case 0xf561: case 0xf761: case 0xf961: case 0xfb61: case 0xfd61: case 0xff61: + case 0xf169: case 0xf369: case 0xf569: case 0xf769: case 0xf969: case 0xfb69: case 0xfd69: case 0xff69: + case 0xf171: case 0xf371: case 0xf571: case 0xf771: case 0xf971: case 0xfb71: case 0xfd71: case 0xff71: + case 0xf179: case 0xf379: case 0xf579: case 0xf779: case 0xf979: case 0xfb79: case 0xfd79: case 0xff79: + util::stream_format(stream, "call mr"); + return UNSP_DASM_OK; + + case 0xf162: case 0xf362: case 0xf562: case 0xf762: case 0xf962: case 0xfb62: case 0xfd62: case 0xff62: + case 0xf16a: case 0xf36a: case 0xf56a: case 0xf76a: case 0xf96a: case 0xfb6a: case 0xfd6a: case 0xff6a: + case 0xf172: case 0xf372: case 0xf572: case 0xf772: case 0xf972: case 0xfb72: case 0xfd72: case 0xff72: + case 0xf17a: case 0xf37a: case 0xf57a: case 0xf77a: case 0xf97a: case 0xfb7a: case 0xfd7a: case 0xff7a: + util::stream_format(stream, "divs mr, r2"); + return UNSP_DASM_OK; + + case 0xf163: case 0xf363: case 0xf563: case 0xf763: case 0xf963: case 0xfb63: case 0xfd63: case 0xff63: + case 0xf16b: case 0xf36b: case 0xf56b: case 0xf76b: case 0xf96b: case 0xfb6b: case 0xfd6b: case 0xff6b: + case 0xf173: case 0xf373: case 0xf573: case 0xf773: case 0xf973: case 0xfb73: case 0xfd73: case 0xff73: + case 0xf17b: case 0xf37b: case 0xf57b: case 0xf77b: case 0xf97b: case 0xfb7b: case 0xfd7b: case 0xff7b: + util::stream_format(stream, "divq mr, r2"); + return UNSP_DASM_OK; + + case 0xf164: case 0xf364: case 0xf564: case 0xf764: case 0xf964: case 0xfb64: case 0xfd64: case 0xff64: + case 0xf16c: case 0xf36c: case 0xf56c: case 0xf76c: case 0xf96c: case 0xfb6c: case 0xfd6c: case 0xff6c: + case 0xf174: case 0xf374: case 0xf574: case 0xf774: case 0xf974: case 0xfb74: case 0xfd74: case 0xff74: + case 0xf17c: case 0xf37c: case 0xf57c: case 0xf77c: case 0xf97c: case 0xfb7c: case 0xfd7c: case 0xff7c: + util::stream_format(stream, "r2 = exp r4"); + return UNSP_DASM_OK; + + + default: + return unsp_disassembler::disassemble_fxxx_101_group(stream, pc, op, ximm); + } +} + + +offs_t unsp_disassembler::disassemble_fxxx_101_group(std::ostream& stream, offs_t pc, uint16_t op, uint16_t ximm) +{ + // | | | + // INT SET 1 1 1 1 - - - 1 0 1 0 0 0 0 F I + // BREAK 1 1 1 1 - - - 1 0 1 1 - - 0 0 0 + // NOP 1 1 1 1 - - - 1 0 1 1 - - 1 0 1 + + uint32_t len = 1; + + switch (op) + { + case 0xf140: case 0xf340: case 0xf540: case 0xf740: case 0xf940: case 0xfb40: case 0xfd40: case 0xff40: + util::stream_format(stream, "int off"); + return UNSP_DASM_OK; + + case 0xf141: case 0xf341: case 0xf541: case 0xf741: case 0xf941: case 0xfb41: case 0xfd41: case 0xff41: + util::stream_format(stream, "int irq"); + return UNSP_DASM_OK; + + case 0xf142: case 0xf342: case 0xf542: case 0xf742: case 0xf942: case 0xfb42: case 0xfd42: case 0xff42: + util::stream_format(stream, "int fiq"); + return UNSP_DASM_OK; + + case 0xf143: case 0xf343: case 0xf543: case 0xf743: case 0xf943: case 0xfb43: case 0xfd43: case 0xff43: + util::stream_format(stream, "int fiq,irq"); + return UNSP_DASM_OK; + + case 0xf160: case 0xf360: case 0xf560: case 0xf760: case 0xf960: case 0xfb60: case 0xfd60: case 0xff60: + case 0xf168: case 0xf368: case 0xf568: case 0xf768: case 0xf968: case 0xfb68: case 0xfd68: case 0xff68: + case 0xf170: case 0xf370: case 0xf570: case 0xf770: case 0xf970: case 0xfb70: case 0xfd70: case 0xff70: + case 0xf178: case 0xf378: case 0xf578: case 0xf778: case 0xf978: case 0xfb78: case 0xfd78: case 0xff78: + util::stream_format(stream, "break"); + return UNSP_DASM_OK; + + case 0xf165: case 0xf365: case 0xf565: case 0xf765: case 0xf965: case 0xfb65: case 0xfd65: case 0xff65: + case 0xf16d: case 0xf36d: case 0xf56d: case 0xf76d: case 0xf96d: case 0xfb6d: case 0xfd6d: case 0xff6d: + case 0xf175: case 0xf375: case 0xf575: case 0xf775: case 0xf975: case 0xfb75: case 0xfd75: case 0xff75: + case 0xf17d: case 0xf37d: case 0xf57d: case 0xf77d: case 0xf97d: case 0xfb7d: case 0xfd7d: case 0xff7d: + util::stream_format(stream, "nop"); + return UNSP_DASM_OK; + + // these are in code that otherwise seems like ISA1.0 / 1.1 (jak_disf for example) but spec says it's only in ISA 1.2? + case 0xf148: case 0xf348: case 0xf548: case 0xf748: case 0xf948: case 0xfb48: case 0xfd48: case 0xff48: + util::stream_format(stream, "irq off"); + return UNSP_DASM_OK; + + case 0xf149: case 0xf349: case 0xf549: case 0xf749: case 0xf949: case 0xfb49: case 0xfd49: case 0xff49: + util::stream_format(stream, "irq on"); + return UNSP_DASM_OK; + + case 0xf14c: case 0xf34c: case 0xf54c: case 0xf74c: case 0xf94c: case 0xfb4c: case 0xfd4c: case 0xff4c: + util::stream_format(stream, "fiq off"); + return UNSP_DASM_OK; + + case 0xf14e: case 0xf34e: case 0xf54e: case 0xf74e: case 0xf94e: case 0xfb4e: case 0xfd4e: case 0xff4e: + util::stream_format(stream, "fiq on"); + return UNSP_DASM_OK; + + default: + util::stream_format(stream, "<UNDEFINED>"); + return UNSP_DASM_OK; + } + + return UNSP_DASM_OK; +} + +offs_t unsp_disassembler::disassemble_fxxx_110_group(std::ostream& stream, offs_t pc, uint16_t op, uint16_t ximm) +{ + uint32_t len = 1; + // | | | + // signed * signed (size 16,1,2,3,4,5,6,7) + // MULS 1 1 1 1* r r r 1* 1 0*s s s r r r (1* = sign bit, 1* = sign bit 0* = upper size bit) + + // MULS ss with upper size bit not set + print_muls(stream, op); + return UNSP_DASM_OK; +} + +offs_t unsp_disassembler::disassemble_fxxx_111_group(std::ostream& stream, offs_t pc, uint16_t op, uint16_t ximm,const data_buffer &opcodes) +{ + uint32_t len = 1; + // | | | + // EXTOP 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 (+16 bit imm) + if ((op == 0xffc0) && m_iso >= 20) + { + return disassemble_extended_group(stream, pc, op, ximm, opcodes); + } + + // signed * signed (size 8,9,10,11,12,13,14,15) + // MULS 1 1 1 1* r r r 1* 1 1*s s s r r r (1* = sign bit, 1* = sign bit 1* = upper size bit) + + // MULS ss with upper size bit set. + print_muls(stream, op); + return UNSP_DASM_OK; +} + + +offs_t unsp_disassembler::disassemble_fxxx_group(std::ostream &stream, offs_t pc, uint16_t op, uint16_t ximm,const data_buffer &opcodes) +{ + uint32_t len = 1; + + switch ((op & 0x01c0) >> 6) + { + case 0x0: + return disassemble_fxxx_000_group(stream, pc, op, ximm); + + case 0x1: + return disassemble_fxxx_001_group(stream, pc, op, ximm); + + case 0x2: + return disassemble_fxxx_010_group(stream, pc, op, ximm); + + case 0x3: + return disassemble_fxxx_011_group(stream, pc, op, ximm); + + case 0x4: + return disassemble_fxxx_100_group(stream, pc, op, ximm); + + case 0x5: + return disassemble_fxxx_101_group(stream, pc, op, ximm); + + case 0x6: + return disassemble_fxxx_110_group(stream, pc, op, ximm); + + case 0x7: + return disassemble_fxxx_111_group(stream, pc, op, ximm, opcodes); + + } + + return UNSP_DASM_OK; +} diff --git a/src/devices/cpu/unsp/unspdasm_jumps.cpp b/src/devices/cpu/unsp/unspdasm_jumps.cpp new file mode 100644 index 00000000000..09c96692285 --- /dev/null +++ b/src/devices/cpu/unsp/unspdasm_jumps.cpp @@ -0,0 +1,41 @@ +// license:GPL-2.0+ +// copyright-holders:Segher Boessenkool, David Haywood +/***************************************************************************** + + SunPlus µ'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::jumps[] = +{ + "jb", "jae", "jge", "jl", "jne", "je", "jpl", "jmi", + "jbe", "ja", "jle", "jg", "jvc", "jvs", "jmp", "<inv>" +}; + +offs_t unsp_disassembler::disassemble_jumps(std::ostream &stream, offs_t pc, const uint16_t op) +{ + uint32_t len = 1; + const uint16_t op0 = (op >> 12) & 15; + const uint16_t op1 = (op >> 6) & 7; + const uint32_t opimm = op & 0x3f; + + if (op1 == 0) + { + util::stream_format(stream, "%s %04x", jumps[op0], pc + 1 + opimm); + return UNSP_DASM_OK; + } + else if (op1 == 1) + { + util::stream_format(stream, "%s %04x", jumps[op0], pc + 1 - opimm); + return UNSP_DASM_OK; + } + + return UNSP_DASM_OK; +} diff --git a/src/devices/cpu/unsp/unspdasm_other.cpp b/src/devices/cpu/unsp/unspdasm_other.cpp new file mode 100644 index 00000000000..b639b97e25c --- /dev/null +++ b/src/devices/cpu/unsp/unspdasm_other.cpp @@ -0,0 +1,235 @@ +// license:GPL-2.0+ +// copyright-holders:Segher Boessenkool, David Haywood +/***************************************************************************** + + SunPlus µ'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" + +offs_t unsp_disassembler::disassemble_remaining(std::ostream& stream, offs_t pc, uint16_t op, uint16_t ximm, const data_buffer& opcodes) +{ + uint32_t len = 1; + uint8_t op0 = (op >> 12); + uint8_t opA = (op >> 9) & 7; + uint8_t op1 = (op >> 6) & 7; + uint8_t opN = (op >> 3) & 7; + uint8_t opB = op & 7; + uint8_t opimm = op & 63; + + 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; + + + 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; + + // alu, 16-bit immediate + case 1: + if ((op0 == 4 || op0 == 12 || op0 == 6 || op0 == 9) && opA != opB) + { + util::stream_format(stream, "<BAD>"); + return UNSP_DASM_OK; + } + if (op0 != 4 && op0 != 12) + util::stream_format(stream, "%s = ", regs[opA]); + print_alu_op3(stream, op0, opB); + len = 2; + 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, "<BAD>"); + return UNSP_DASM_OK; + } + if (op0 != 4 && op0 != 12) + util::stream_format(stream, "%s = ", regs[opA]); + print_alu_op3(stream, op0, opB); + len = 2; + util::stream_format(stream, "[%04x]", ximm); + print_alu_op_end(stream, op0); + return UNSP_DASM_OK; + + // alu, direct memory + case 3: + if (op0 == 4 || op0 == 12) + { + util::stream_format(stream, "<BAD>"); + return UNSP_DASM_OK; + } + if ((op0 == 6 || op0 == 9) && opA != opB) + { + util::stream_format(stream, "<BAD>"); + return UNSP_DASM_OK; + } + len = 2; + 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, 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) + { + util::stream_format(stream, "<BAD>"); + return UNSP_DASM_OK; + } + len = 2; + util::stream_format(stream, "[%04x] = %s", ximm, regs[opB]); + return UNSP_DASM_OK; + 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, 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; + + + // 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; + + default: + util::stream_format(stream, "<UNHANDLED>"); + return UNSP_DASM_OK; + } +} diff --git a/src/devices/cpu/unsp/unspdrc.cpp b/src/devices/cpu/unsp/unspdrc.cpp index f2f8f409ee8..a34d20f8a7e 100644 --- a/src/devices/cpu/unsp/unspdrc.cpp +++ b/src/devices/cpu/unsp/unspdrc.cpp @@ -677,18 +677,6 @@ void unsp_device::generate_update_nz(drcuml_block &block) single opcode ------------------------------------------------------------------*/ -bool unsp_device::generate_f_group_opcode(drcuml_block& block, compiler_state& compiler, const opcode_desc* desc) -{ - return false; -} - -bool unsp_newer_device::generate_f_group_opcode(drcuml_block& block, compiler_state& compiler, const opcode_desc* desc) -{ - // TODO: handle the extended opcodes - return true; -} - - bool unsp_device::generate_opcode(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc) { uint32_t op = (uint32_t)desc->opptr.w[0]; @@ -1310,9 +1298,6 @@ bool unsp_device::generate_opcode(drcuml_block &block, compiler_state &compiler, UML_CALLH(block, *m_mem_write); return true; - case 0x0f: // Extended - return generate_f_group_opcode(block, compiler, desc); - default: return false; } diff --git a/src/devices/machine/sunplus_gcm394.cpp b/src/devices/machine/sunplus_gcm394.cpp index 74b5774bf13..d73ac892aa1 100644 --- a/src/devices/machine/sunplus_gcm394.cpp +++ b/src/devices/machine/sunplus_gcm394.cpp @@ -18,19 +18,70 @@ sunplus_gcm394_device::sunplus_gcm394_device(const machine_config &mconfig, cons READ16_MEMBER(sunplus_gcm394_base_device::unk_r) { + switch (offset) + { + + case 0x80f: + logerror("%s:sunplus_gcm394_base_device::unk_r @ 0x%04x\n", machine().describe_context(), offset + 0x7000); + return 0x0002; + + case 0x8fb: + logerror("%s:sunplus_gcm394_base_device::unk_r @ 0x%04x\n", machine().describe_context(), offset + 0x7000); + m_78fb ^= 0x0100; // status flag for something? + return m_78fb; + + case 0xabf: + logerror("%s:sunplus_gcm394_base_device::unk_r @ 0x%04x\n", machine().describe_context(), offset + 0x7000); + return 0x0001; + + } + logerror("%s:sunplus_gcm394_base_device::unk_r @ 0x%04x\n", machine().describe_context(), offset + 0x7000); - return 0x00; + return 0x0000; } WRITE16_MEMBER(sunplus_gcm394_base_device::unk_w) { - logerror("%s:sunplus_gcm394_base_device::unk_w @ 0x%04x (data 0x%04x)\n", machine().describe_context(), offset + 0x7000, data); + + switch (offset) + { + + case 0xa80: + case 0xa81: + case 0xa82: + case 0xa83: + case 0xa84: + case 0xa85: + case 0xa86: + m_dma_params[offset - 0xa80] = data; + break; + + case 0xabf: + logerror("%s:possible DMA operation @ 0x%04x (trigger %04x) with params unk:%04x unk:%04x source:%04x length:%04x unk:%04x unk:%04x unk:%04x\n", machine().describe_context(), offset + 0x7000, data, m_dma_params[0], m_dma_params[1], m_dma_params[2], m_dma_params[3], m_dma_params[4], m_dma_params[5], m_dma_params[6]); + break; + + default: + logerror("%s:sunplus_gcm394_base_device::unk_w @ 0x%04x (data 0x%04x)\n", machine().describe_context(), offset + 0x7000, data); + break; + } } void sunplus_gcm394_base_device::map(address_map &map) { map(0x000000, 0x006fff).ram(); map(0x007000, 0x007fff).rw(FUNC(sunplus_gcm394_base_device::unk_r), FUNC(sunplus_gcm394_base_device::unk_w)); + + map(0x007300, 0x0073ff).ram(); + map(0x007400, 0x0074ff).ram(); + map(0x007500, 0x0075ff).ram(); + map(0x007600, 0x0076ff).ram(); + map(0x007700, 0x0077ff).ram(); + + map(0x007c00, 0x007cff).ram(); + map(0x007d00, 0x007dff).ram(); + map(0x007e00, 0x007eff).ram(); + map(0x007f00, 0x007fff).ram(); + } void sunplus_gcm394_base_device::device_start() @@ -39,6 +90,12 @@ void sunplus_gcm394_base_device::device_start() void sunplus_gcm394_base_device::device_reset() { + m_78fb = 0x0000; + + for (int i = 0; i < 7; i++) + { + m_dma_params[i] = 0x0000; + } } void sunplus_gcm394_device::device_add_mconfig(machine_config &config) diff --git a/src/devices/machine/sunplus_gcm394.h b/src/devices/machine/sunplus_gcm394.h index 9da9db77a5e..8aee6d07847 100644 --- a/src/devices/machine/sunplus_gcm394.h +++ b/src/devices/machine/sunplus_gcm394.h @@ -38,6 +38,9 @@ protected: required_device<unsp_device> m_cpu; required_device<screen_device> m_screen; + uint16_t m_78fb; + uint16_t m_dma_params[7]; + private: DECLARE_READ16_MEMBER(unk_r); DECLARE_WRITE16_MEMBER(unk_w); diff --git a/src/mame/drivers/clickstart.cpp b/src/mame/drivers/clickstart.cpp index d880e901af7..bc2e948d9dc 100644 --- a/src/mame/drivers/clickstart.cpp +++ b/src/mame/drivers/clickstart.cpp @@ -5,8 +5,8 @@ Leapfrog Clickstart Emulation Die markings show "SunPlus QL8041C" ( known as Sunplus SPG2?? ) - The keyboard has a "SunPlus PU6583" MCU under a glob, and the - mouse optical sensor is a N2163, probably from Agilent. + The keyboard has a "SunPlus PU6583" MCU under a glob, and the + mouse optical sensor is a N2163, probably from Agilent. Status: diff --git a/src/mame/drivers/sunplus_gcm394.cpp b/src/mame/drivers/sunplus_gcm394.cpp index e8d9ac2e788..4bfafc3225a 100644 --- a/src/mame/drivers/sunplus_gcm394.cpp +++ b/src/mame/drivers/sunplus_gcm394.cpp @@ -57,7 +57,7 @@ void gcm394_game_state::base(machine_config &config) { GCM394(config, m_spg, XTAL(27'000'000), m_maincpu, m_screen); - UNSP_NEWER(config, m_maincpu, XTAL(27'000'000)); + UNSP_12(config, m_maincpu, XTAL(27'000'000)); m_maincpu->set_addrmap(AS_PROGRAM, &gcm394_game_state::mem_map_4m); SCREEN(config, m_screen, SCREEN_TYPE_RASTER); @@ -99,8 +99,11 @@ void gcm394_game_state::machine_reset() void gcm394_game_state::mem_map_4m(address_map &map) { - map(0x000000, 0x3fffff).bankr("cartbank"); + map(0x000000, 0x01ffff).bankr("cartbank"); map(0x000000, 0x007fff).m(m_spg, FUNC(sunplus_gcm394_device::map)); + + // smartfp really expects the ROM at 0 to map here, so maybe this is how the newer SoC works + map(0x020000, 0x3fffff).bankr("cartbank"); } static INPUT_PORTS_START( gcm394 ) |