mirror of
https://github.com/holub/mame
synced 2025-04-22 16:31:49 +03:00
Merge branch 'master' of https://github.com/mamedev/mame into magnet_args
This commit is contained in:
commit
1b6322e1e1
@ -2159,6 +2159,11 @@ if (CPUS["UNSP"]~=null) then
|
||||
files {
|
||||
MAME_DIR .. "src/devices/cpu/unsp/unsp.cpp",
|
||||
MAME_DIR .. "src/devices/cpu/unsp/unsp.h",
|
||||
MAME_DIR .. "src/devices/cpu/unsp/unsp_extended.cpp",
|
||||
MAME_DIR .. "src/devices/cpu/unsp/unsp_jumps.cpp",
|
||||
MAME_DIR .. "src/devices/cpu/unsp/unsp_exxx.cpp",
|
||||
MAME_DIR .. "src/devices/cpu/unsp/unsp_fxxx.cpp",
|
||||
MAME_DIR .. "src/devices/cpu/unsp/unsp_other.cpp",
|
||||
MAME_DIR .. "src/devices/cpu/unsp/unspdefs.h",
|
||||
MAME_DIR .. "src/devices/cpu/unsp/unspdrc.cpp",
|
||||
MAME_DIR .. "src/devices/cpu/unsp/unspfe.cpp",
|
||||
@ -2169,6 +2174,11 @@ end
|
||||
if (CPUS["UNSP"]~=null or _OPTIONS["with-tools"]) then
|
||||
table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/unsp/unspdasm.cpp")
|
||||
table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/unsp/unspdasm.h")
|
||||
table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/unsp/unspdasm_extended.cpp")
|
||||
table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/unsp/unspdasm_jumps.cpp")
|
||||
table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/unsp/unspdasm_exxx.cpp")
|
||||
table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/unsp/unspdasm_fxxx.cpp")
|
||||
table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/unsp/unspdasm_other.cpp")
|
||||
end
|
||||
|
||||
--------------------------------------------------
|
||||
|
@ -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_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_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_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_newer_disassembler>();
|
||||
return std::make_unique<unsp_12_disassembler>();
|
||||
}
|
||||
|
||||
std::unique_ptr<util::disasm_interface> unsp_20_device::create_disassembler()
|
||||
{
|
||||
return std::make_unique<unsp_12_disassembler>();
|
||||
}
|
||||
|
||||
void unsp_device::unimplemented_opcode(uint16_t op)
|
||||
@ -86,22 +154,16 @@ 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)
|
||||
{
|
||||
#if UNSP_LOG_REGS
|
||||
log_write(address, data);
|
||||
#endif
|
||||
m_program->write_word(address, data);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
void unsp_device::unimplemented_opcode(uint16_t op, uint16_t ximm, uint16_t ximm_2)
|
||||
{
|
||||
fatalerror("UNSP: unknown opcode %04x %04x %04x at %04x\n", op, ximm, ximm_2, UNSP_LPC);
|
||||
}
|
||||
|
||||
void unsp_device::device_start()
|
||||
{
|
||||
@ -109,7 +171,7 @@ void unsp_device::device_start()
|
||||
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 (op0 == 0xe)
|
||||
return execute_exxx_group(op);
|
||||
|
||||
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;
|
||||
|
||||
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()
|
||||
|
@ -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_newer_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||
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_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
|
||||
|
206
src/devices/cpu/unsp/unsp_extended.cpp
Normal file
206
src/devices/cpu/unsp/unsp_extended.cpp
Normal file
@ -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;
|
||||
}
|
161
src/devices/cpu/unsp/unsp_exxx.cpp
Normal file
161
src/devices/cpu/unsp/unsp_exxx.cpp
Normal file
@ -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;
|
||||
}
|
431
src/devices/cpu/unsp/unsp_fxxx.cpp
Normal file
431
src/devices/cpu/unsp/unsp_fxxx.cpp
Normal file
@ -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;
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
160
src/devices/cpu/unsp/unsp_jumps.cpp
Normal file
160
src/devices/cpu/unsp/unsp_jumps.cpp
Normal file
@ -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;
|
||||
}
|
||||
}
|
347
src/devices/cpu/unsp/unsp_other.cpp
Normal file
347
src/devices/cpu/unsp/unsp_other.cpp
Normal file
@ -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;
|
||||
}
|
@ -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)
|
||||
|
||||
|
||||
offs_t unsp_disassembler::disassemble_code(std::ostream &stream, offs_t pc, uint16_t op, uint16_t ximm, const data_buffer &opcodes)
|
||||
{
|
||||
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)
|
||||
{
|
||||
// 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;
|
||||
}
|
||||
uint8_t op0 = (op >> 12);
|
||||
|
||||
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;
|
||||
if (op0 == 0xf)
|
||||
return disassemble_fxxx_group(stream, pc, op, ximm, opcodes);
|
||||
|
||||
uint8_t opA = (op >> 9) & 7;
|
||||
uint8_t op1 = (op >> 6) & 7;
|
||||
|
||||
// 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;
|
||||
if (op0 < 15 && opA == 7 && op1 < 2)
|
||||
return disassemble_jumps(stream, pc, op);
|
||||
|
||||
if (op0 == 0xe)
|
||||
return disassemble_exxx_group(stream, pc, op, ximm);
|
||||
|
||||
// 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;
|
||||
|
||||
|
||||
// alu, direct memory
|
||||
case 0x70: case 0x71: case 0x72: case 0x73:
|
||||
case 0x74: case 0x76: case 0x78: case 0x79:
|
||||
case 0x7a: case 0x7b: case 0x7c:
|
||||
print_alu_op_start(stream, op0, opA);
|
||||
util::stream_format(stream, "[%02x]", opimm);
|
||||
print_alu_op_end(stream, op0);
|
||||
return UNSP_DASM_OK;
|
||||
case 0x7d:
|
||||
util::stream_format(stream, "[%02x] = %s", opimm, regs[opA]);
|
||||
return UNSP_DASM_OK;
|
||||
|
||||
|
||||
case 0x1f:
|
||||
if (opA == 0)
|
||||
{
|
||||
util::stream_format(stream, "call %04x", (opimm << 16) | ximm);
|
||||
return UNSP_DASM_OK;
|
||||
}
|
||||
util::stream_format(stream, "<DUNNO>");
|
||||
return UNSP_DASM_OK;
|
||||
|
||||
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;
|
||||
|
||||
|
||||
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;
|
||||
return disassemble_remaining(stream, pc, op, ximm, opcodes);
|
||||
}
|
||||
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
|
@ -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_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_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_extended_group(std::ostream& stream, offs_t pc, uint16_t op, uint16_t ximm, const data_buffer& opcodes) override;
|
||||
|
||||
};
|
||||
|
||||
|
193
src/devices/cpu/unsp/unspdasm_extended.cpp
Normal file
193
src/devices/cpu/unsp/unspdasm_extended.cpp
Normal file
@ -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;
|
||||
}
|
117
src/devices/cpu/unsp/unspdasm_exxx.cpp
Normal file
117
src/devices/cpu/unsp/unspdasm_exxx.cpp
Normal file
@ -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;
|
||||
}
|
371
src/devices/cpu/unsp/unspdasm_fxxx.cpp
Normal file
371
src/devices/cpu/unsp/unspdasm_fxxx.cpp
Normal file
@ -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;
|
||||
}
|
41
src/devices/cpu/unsp/unspdasm_jumps.cpp
Normal file
41
src/devices/cpu/unsp/unspdasm_jumps.cpp
Normal file
@ -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;
|
||||
}
|
235
src/devices/cpu/unsp/unspdasm_other.cpp
Normal file
235
src/devices/cpu/unsp/unspdasm_other.cpp
Normal file
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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:
|
||||
|
||||
|
@ -218,7 +218,7 @@ void flkatck_state::machine_reset()
|
||||
void flkatck_state::flkatck(machine_config &config)
|
||||
{
|
||||
/* basic machine hardware */
|
||||
HD6309E(config, m_maincpu, 24_MHz_XTAL / 8); /* HD63C09EP, 3MHz (24MHz/8)*/
|
||||
HD6309E(config, m_maincpu, 24_MHz_XTAL / 8); /* HD63C09EP, 3MHz (24MHz/8) */
|
||||
m_maincpu->set_addrmap(AS_PROGRAM, &flkatck_state::flkatck_map);
|
||||
m_maincpu->set_vblank_int("screen", FUNC(flkatck_state::flkatck_interrupt));
|
||||
|
||||
|
@ -195,12 +195,13 @@ CRT-351
|
||||
| |=============J2=============||=============J1===============||
|
||||
+----------------------------------------------------------------------------+
|
||||
|
||||
J1 80-pin connector to J1 connector on the CRT-350 mainboard
|
||||
J1 80-pin connector to J1 connector on the CRT-350 mainboard
|
||||
J2 80-pin connector to J2 connector on the CRT-350 mainboard
|
||||
J3 65-pin single row connector for wire harness
|
||||
J4 40-pin dual row connector for printer
|
||||
J5 16-pin dual row connector for unknown
|
||||
J7 17-pin single row connector for unknown (some kind of jumper block)
|
||||
J6 17-pin single row connector for unknown (some kind of jumper block)
|
||||
J7 6-pin single row connector for hopper
|
||||
JPR3 is a 3 pin jumper: Pins 1&2 = Printer, pins 2&3= Hopper
|
||||
|
||||
|
||||
@ -352,12 +353,13 @@ CRT-351
|
||||
| |=============J2=============||=============J1===============||
|
||||
+----------------------------------------------------------------------------+
|
||||
|
||||
J1 80-pin connector to J1 connector on the CRT-350 mainboard
|
||||
J1 80-pin connector to J1 connector on the CRT-350 mainboard
|
||||
J2 80-pin connector to J2 connector on the CRT-350 mainboard
|
||||
J3 65-pin single row connector for wire harness
|
||||
J4 40-pin dual row connector for printer
|
||||
J5 16-pin dual row connector for unknown
|
||||
J7 17-pin single row connector for unknown (some kind of jumper block)
|
||||
J6 17-pin single row connector for unknown (some kind of jumper block)
|
||||
J7 6-pin single row connector for hopper
|
||||
JPR3 is a 3 pin jumper: Pins 1&2 = Printer, pins 2&3= Hopper
|
||||
|
||||
|
||||
|
@ -6794,7 +6794,29 @@ PayTable 2P 3K STR FL FH 4K SF RF 5K RF (Bonus)
|
||||
ROM_LOAD( "cap740.u50", 0x0000, 0x0100, CRC(6fe619c4) SHA1(49e43dafd010ce0fe9b2a63b96a4ddedcb933c6d) )
|
||||
ROM_END
|
||||
|
||||
ROM_START( pepp0550a ) /* Normal board : Joker Poker (Two Pair or Better) (PP0550) */
|
||||
ROM_START( pepp0550a ) /* Normal board : Joker Poker (Two Pair or Better) (PP0550) - PSR Verified */
|
||||
/*
|
||||
w/J w/oJ
|
||||
PayTable 2P 3K STR FL FH 4K SF RF 5K RF (Bonus)
|
||||
-----------------------------------------------------------
|
||||
NA 1 2 4 5 8 16 100 100 400 100 800
|
||||
% Range: 93.2-95.2% Optimum: 97.2% Hit Frequency: 30.1%
|
||||
Programs Available: PP0550, X000550P
|
||||
*/
|
||||
ROM_REGION( 0x10000, "maincpu", 0 )
|
||||
ROM_LOAD( "pp0550_a1h-a36.u68", 0x00000, 0x10000, CRC(639ca5bc) SHA1(a7e12a3a89c57890fbb948333ced20e701a08cad) ) /* Game Version: A1H, Library Version: A36 - 10/04/94 */
|
||||
|
||||
ROM_REGION( 0x020000, "gfx1", 0 )
|
||||
ROM_LOAD( "mro-cg2004.u72", 0x00000, 0x8000, CRC(e5e40ea5) SHA1(e0d9e50b30cc0c25c932b2bf444990df1fb2c38c) ) /* 08/31/94 @ IGT L95-0146 */
|
||||
ROM_LOAD( "mgo-cg2004.u73", 0x08000, 0x8000, CRC(12607f1e) SHA1(248e1ecee4e735f5943c50f8c350ca95b81509a7) )
|
||||
ROM_LOAD( "mbo-cg2004.u74", 0x10000, 0x8000, CRC(78c3fb9f) SHA1(2b9847c511888de507a008dec981778ca4dbcd6c) )
|
||||
ROM_LOAD( "mxo-cg2004.u75", 0x18000, 0x8000, CRC(5aaa4480) SHA1(353c4ce566c944406fce21f2c5045c856ef7a609) )
|
||||
|
||||
ROM_REGION( 0x100, "proms", 0 )
|
||||
ROM_LOAD( "cap740.u50", 0x0000, 0x0100, CRC(6fe619c4) SHA1(49e43dafd010ce0fe9b2a63b96a4ddedcb933c6d) )
|
||||
ROM_END
|
||||
|
||||
ROM_START( pepp0550b ) /* Normal board : Joker Poker (Two Pair or Better) (PP0550) */
|
||||
/*
|
||||
w/J w/oJ
|
||||
PayTable 2P 3K STR FL FH 4K SF RF 5K RF (Bonus)
|
||||
@ -9909,7 +9931,7 @@ PayTable Js+ 2PR 3K STR FL FH 4K 4K 4A SF RF (Bonus)
|
||||
------------------------------------------------------------------
|
||||
P101A 1 2 3 4 5 6 25 40 80 50 250 800
|
||||
% Range: 92.5-94.5% Optimum: 96.9% Hit Frequency: 45.5%
|
||||
Programs Available: PP0265, X000265P, PP0403 & PP0410 - Non Double-up Only
|
||||
Programs Available: PP0265, X000265P, PP0403, X000403P & PP0410 - Non Double-up Only
|
||||
*/
|
||||
ROM_REGION( 0x10000, "maincpu", 0 )
|
||||
ROM_LOAD( "xp000038.u67", 0x00000, 0x10000, CRC(8707ab9e) SHA1(3e00a2ad8017e1495c6d6fe900d0efa68a1772b8) ) /* 09/05/95 @ IGT L95-2452 */
|
||||
@ -9952,6 +9974,31 @@ PayTable 3K STR FL FH 4K SF 5K RF 4D RF (Bonus)
|
||||
ROM_LOAD( "capx1321.u43", 0x0000, 0x0200, CRC(4b57569f) SHA1(fa29c0f627e7ce79951ec6dadec114864144f37d) )
|
||||
ROM_END
|
||||
|
||||
ROM_START( pex0403p ) /* Superboard : 4 of a Kind Bonus Poker (X000403P+XP000013) */
|
||||
/*
|
||||
5-K 2-4
|
||||
PayTable Js+ 2PR 3K STR FL FH 4K 4K 4A SF RF (Bonus)
|
||||
------------------------------------------------------------------
|
||||
P101A 1 2 3 4 5 6 25 40 80 50 250 800
|
||||
% Range: 92.5-94.5% Optimum: 96.9% Hit Frequency: 45.5%
|
||||
Programs Available: PP0265, X000265P, PP0403, X000403P & PP0410 - Non Double-up Only
|
||||
*/
|
||||
ROM_REGION( 0x10000, "maincpu", 0 )
|
||||
ROM_LOAD( "xp000013.u67", 0x00000, 0x10000, CRC(ed5a63a9) SHA1(8aa9bb37ab90b3b64a26087b3d4844f6481c8856) ) /* 05/19/95 */
|
||||
|
||||
ROM_REGION( 0x10000, "user1", 0 )
|
||||
ROM_LOAD( "x000403p.u66", 0x00000, 0x10000, CRC(430cc468) SHA1(e8ac25792ef564b390b05838d1fcf69b4db38867) ) /* 4 of a Kind Bonus Poker - 11/29/94 */
|
||||
|
||||
ROM_REGION( 0x020000, "gfx1", 0 )
|
||||
ROM_LOAD( "mro-cg2119.u77", 0x00000, 0x8000, CRC(1e671f88) SHA1(23c667ffb6d6f6e63f92aa8916bc4f862e924d87) )
|
||||
ROM_LOAD( "mgo-cg2119.u78", 0x08000, 0x8000, CRC(3c65b8ef) SHA1(a26433ed0b0040b8bb8fa59802715cdb185f39ff) )
|
||||
ROM_LOAD( "mbo-cg2119.u79", 0x10000, 0x8000, CRC(958d1b42) SHA1(3e8a1589b9a0c17237247e573d14a75fd09c2a88) )
|
||||
ROM_LOAD( "mxo-cg2119.u80", 0x18000, 0x8000, CRC(f82f27a5) SHA1(81e7f8c0f31a8e8aeca8c0456ff59f9d2ec7d184) )
|
||||
|
||||
ROM_REGION( 0x200, "proms", 0 )
|
||||
ROM_LOAD( "capx1321.u43", 0x0000, 0x0200, CRC(4b57569f) SHA1(fa29c0f627e7ce79951ec6dadec114864144f37d) )
|
||||
ROM_END
|
||||
|
||||
ROM_START( pex0417p ) /* Superboard : Deuces Wild Poker (X000417P+XP000053) - PSR Verified */
|
||||
/*
|
||||
w/D w/oD
|
||||
@ -14581,6 +14628,7 @@ GAMEL( 1987, pepp0542a, pepp0542, peplus, peplus_poker, peplus_state, init_pepl
|
||||
GAMEL( 1987, pepp0542b, pepp0542, peplus, peplus_poker, peplus_state, init_peplus, ROT0, "IGT - International Game Technology", "Player's Edge Plus (PP0542) One Eyed Jacks Wild Poker (CG1199)", MACHINE_SUPPORTS_SAVE, layout_pe_poker )
|
||||
GAMEL( 1987, pepp0550, pepp0048, peplus, peplus_poker, peplus_state, init_peplus, ROT0, "IGT - International Game Technology", "Player's Edge Plus (PP0550) Joker Poker (Two Pair or Better, set 1)", MACHINE_SUPPORTS_SAVE, layout_pe_poker )
|
||||
GAMEL( 1987, pepp0550a, pepp0048, peplus, peplus_poker, peplus_state, init_peplus, ROT0, "IGT - International Game Technology", "Player's Edge Plus (PP0550) Joker Poker (Two Pair or Better, set 2)", MACHINE_SUPPORTS_SAVE, layout_pe_poker )
|
||||
GAMEL( 1987, pepp0550b, pepp0048, peplus, peplus_poker, peplus_state, init_peplus, ROT0, "IGT - International Game Technology", "Player's Edge Plus (PP0550) Joker Poker (Two Pair or Better, set 3)", MACHINE_SUPPORTS_SAVE, layout_pe_poker )
|
||||
GAMEL( 1987, pepp0555, pepp0001, peplus, peplus_poker, peplus_state, init_peplus, ROT0, "IGT - International Game Technology", "Player's Edge Plus (PP0555) Standard Draw Poker", MACHINE_SUPPORTS_SAVE, layout_pe_poker )
|
||||
GAMEL( 1987, pepp0559, pepp0048, peplus, peplus_poker, peplus_state, init_peplus, ROT0, "IGT - International Game Technology", "Player's Edge Plus (PP0559) Joker Poker (Aces or Better)", MACHINE_SUPPORTS_SAVE, layout_pe_poker )
|
||||
GAMEL( 1987, pepp0562, pepp0001, peplus, peplus_poker, peplus_state, init_peplus, ROT0, "IGT - International Game Technology", "Player's Edge Plus (PP0562) 10's or Better", MACHINE_SUPPORTS_SAVE, layout_pe_poker )
|
||||
@ -14737,6 +14785,7 @@ GAMEL( 1995, pex0225p, 0, peplus, peplus_poker, peplus_state, init_pepl
|
||||
GAMEL( 1995, pex0242p, 0, peplus, peplus_poker, peplus_state, init_peplussb, ROT0, "IGT - International Game Technology", "Player's Edge Plus (X000242P+XP000038) Deuces Wild Poker", MACHINE_SUPPORTS_SAVE, layout_pe_poker )
|
||||
GAMEL( 1995, pex0265p, 0, peplus, peplus_poker, peplus_state, init_peplussb, ROT0, "IGT - International Game Technology", "Player's Edge Plus (X000265P+XP000038) 4 of a Kind Bonus Poker", MACHINE_SUPPORTS_SAVE, layout_pe_poker )
|
||||
GAMEL( 1995, pex0291p, 0, peplus, peplus_poker, peplus_state, init_peplussb, ROT0, "IGT - International Game Technology", "Player's Edge Plus (X000291P+XP000038) Deuces Wild Poker", MACHINE_SUPPORTS_SAVE, layout_pe_poker )
|
||||
GAMEL( 1995, pex0403p, 0, peplus, peplus_poker, peplus_state, init_peplussb, ROT0, "IGT - International Game Technology", "Player's Edge Plus (X000403P+XP000013) 4 of a Kind Bonus Poker", MACHINE_SUPPORTS_SAVE, layout_pe_poker )
|
||||
GAMEL( 1995, pex0417p, 0, peplus, peplus_poker, peplus_state, init_peplussb, ROT0, "IGT - International Game Technology", "Player's Edge Plus (X000417P+XP000038) Deuces Wild Poker", MACHINE_SUPPORTS_SAVE, layout_pe_poker )
|
||||
GAMEL( 1995, pex0426p, 0, peplus, peplus_poker, peplus_state, init_peplussb, ROT0, "IGT - International Game Technology", "Player's Edge Plus (X000426P+XP000038) Joker Poker", MACHINE_SUPPORTS_SAVE, layout_pe_poker )
|
||||
GAMEL( 1995, pex0430p, 0, peplus, peplus_poker, peplus_state, init_peplussb, ROT0, "IGT - International Game Technology", "Player's Edge Plus (X000430P+XP000079) Dueces Joker Wild Poker", MACHINE_SUPPORTS_SAVE, layout_pe_poker )
|
||||
|
@ -1154,10 +1154,10 @@ ROM_END
|
||||
//
|
||||
ROM_START( hangon2 )
|
||||
ROM_REGION( 0x40000, "maincpu", 0 ) // 68000 code
|
||||
ROM_LOAD16_BYTE( "epr-6851a__,needs_verification.ic22", 0x000000, 0x8000, CRC(1e4d2217) SHA1(197d8939b7c9eea0496aecac55cce3dec51be042) ) // as per the manual
|
||||
ROM_LOAD16_BYTE( "epr-6849a__,needs_verification.ic8", 0x000001, 0x8000, CRC(3793e50e) SHA1(ffcad02696ca6d67f6bd5001a0d4aa41e23e21bd) ) // as per the manual
|
||||
ROM_LOAD16_BYTE( "epr-6850a__,needs_verification.ic20", 0x010000, 0x8000, CRC(5d715e3b) SHA1(88554d05e157b1276ba56b80d808fddedc9d71c5) ) // as per the manual
|
||||
ROM_LOAD16_BYTE( "epr-6848a__,needs_verification.ic6", 0x010001, 0x8000, CRC(f1439a30) SHA1(5d496f80c2fda29eb71c29a050f17ecef4543052) ) // as per the manual
|
||||
ROM_LOAD16_BYTE( "epr-6851a.ic22", 0x000000, 0x8000, CRC(1e4d2217) SHA1(197d8939b7c9eea0496aecac55cce3dec51be042) )
|
||||
ROM_LOAD16_BYTE( "epr-6849a.ic8", 0x000001, 0x8000, CRC(3793e50e) SHA1(ffcad02696ca6d67f6bd5001a0d4aa41e23e21bd) )
|
||||
ROM_LOAD16_BYTE( "epr-6850a.ic20", 0x010000, 0x8000, CRC(5d715e3b) SHA1(88554d05e157b1276ba56b80d808fddedc9d71c5) )
|
||||
ROM_LOAD16_BYTE( "epr-6848a.ic6", 0x010001, 0x8000, CRC(f1439a30) SHA1(5d496f80c2fda29eb71c29a050f17ecef4543052) )
|
||||
|
||||
ROM_REGION( 0x40000, "subcpu", 0 ) // second 68000 CPU
|
||||
ROM_LOAD16_BYTE( "epr-6838.ic63", 0x0000, 0x8000, CRC(2747b794) SHA1(06d296837f03f5dfb2d9d7e3001070b81391247f) )
|
||||
|
@ -675,9 +675,7 @@ void sun2_state::sun2vme(machine_config &config)
|
||||
|
||||
screen_device &bwtwo(SCREEN(config, "bwtwo", SCREEN_TYPE_RASTER));
|
||||
bwtwo.set_screen_update(FUNC(sun2_state::bw2_update));
|
||||
bwtwo.set_size(1152,900);
|
||||
bwtwo.set_visarea(0, 1152-1, 0, 900-1);
|
||||
bwtwo.set_refresh_hz(72);
|
||||
bwtwo.set_raw(100_MHz_XTAL, 1600, 0, 1152, 937, 0, 900);
|
||||
|
||||
I82586(config, m_edlc, 16_MHz_XTAL / 2);
|
||||
m_edlc->set_addrmap(0, &sun2_state::sun2_mem);
|
||||
@ -732,9 +730,8 @@ void sun2_state::sun2mbus(machine_config &config)
|
||||
|
||||
screen_device &bwtwo(SCREEN(config, "bwtwo", SCREEN_TYPE_RASTER));
|
||||
bwtwo.set_screen_update(FUNC(sun2_state::bw2_update));
|
||||
bwtwo.set_size(1152,900);
|
||||
bwtwo.set_visarea(0, 1152-1, 0, 900-1);
|
||||
bwtwo.set_refresh_hz(72);
|
||||
bwtwo.set_raw(100_MHz_XTAL, 1600, 0, 1152, 937, 0, 900);
|
||||
//bwtwo.set_raw(100_MHz_XTAL, 1600, 0, 1024, 1061, 0, 1024);
|
||||
|
||||
am9513a_device &timer(AM9513A(config, "timer", 39.3216_MHz_XTAL / 8));
|
||||
timer.fout_cb().set("timer", FUNC(am9513_device::gate1_w));
|
||||
|
@ -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 )
|
||||
|
@ -159,8 +159,12 @@ uint16_t ti68k_state::reset_overlay_r(offs_t offset)
|
||||
if (offset == 3 && !machine().side_effects_disabled())
|
||||
m_ram_enabled = true;
|
||||
|
||||
// FIXME: this reset vector happens to work for all Flash systems, but may not be loaded
|
||||
// first. It is algorithmically located by the preceding initialization code which looks
|
||||
// for the string of four CC bytes preceding it. This code has not been enabled since it
|
||||
// also contains a "Certificate Memory" self-test which fails.
|
||||
if (m_flash.found())
|
||||
return m_flash->read(offset + 0x12088/2); // why this offset?
|
||||
return m_flash->read(offset + 0x12088/2);
|
||||
else
|
||||
return m_rom_base[offset];
|
||||
}
|
||||
|
@ -31762,6 +31762,7 @@ pepp0542a // (c) 1987 IGT - International Game Technology
|
||||
pepp0542b // (c) 1987 IGT - International Game Technology
|
||||
pepp0550 // (c) 1987 IGT - International Game Technology
|
||||
pepp0550a // (c) 1987 IGT - International Game Technology
|
||||
pepp0550b // (c) 1987 IGT - International Game Technology
|
||||
pepp0555 // (c) 1987 IGT - International Game Technology
|
||||
pepp0559 // (c) 1987 IGT - International Game Technology
|
||||
pepp0562 // (c) 1987 IGT - International Game Technology
|
||||
@ -31880,6 +31881,7 @@ pex0225p // (c) 1995 IGT - International Game Technology
|
||||
pex0242p // (c) 1995 IGT - International Game Technology
|
||||
pex0265p // (c) 1995 IGT - International Game Technology
|
||||
pex0291p // (c) 1995 IGT - International Game Technology
|
||||
pex0403p // (c) 1995 IGT - International Game Technology
|
||||
pex0417p // (c) 1995 IGT - International Game Technology
|
||||
pex0426p // (c) 1995 IGT - International Game Technology
|
||||
pex0430p // (c) 1995 IGT - International Game Technology
|
||||
|
Loading…
Reference in New Issue
Block a user