summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/minx/minx.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/minx/minx.c')
-rw-r--r--src/devices/cpu/minx/minx.c234
1 files changed, 234 insertions, 0 deletions
diff --git a/src/devices/cpu/minx/minx.c b/src/devices/cpu/minx/minx.c
new file mode 100644
index 00000000000..e822fbd9ecc
--- /dev/null
+++ b/src/devices/cpu/minx/minx.c
@@ -0,0 +1,234 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+/*
+ Implementation for the Nintendo Minx CPU.
+
+ Registers (mindX13.txt):
+ 8bit: A B H L FLAGS N U V
+ 16bit: BA
+ 24bit: HL, X1, X2, NN, SP
+
+
+ "sunlab":
+ 16bit:
+ V:PC if high bit set, extended to 23 bits, upper 8 bits V
+ SP
+ BA
+ I:HL
+ (XI:)X
+ (YI:)Y
+
+ 8bit:
+ A, B, H, L
+ U - delayed jump bank. When a jump occurs, V is set to this value
+ V
+ F - flags IDLBSOCZ
+ I - Interrupt branch
+ D - Interrupt disable
+ L - low mask mode enable
+ B - bcd decimal mode enable
+ S - sign flag
+ O - overflow flag
+ C - carry flag
+ Z - zero flag
+ E - exception register
+ I
+ N
+ XI - index/extension
+ YI - index/extension
+
+TODO:
+- Add support for O and C flags in NEG8 instruction
+- Verify MUL (CE D8) and DIV (CE D9)
+- Doublecheck behaviour of CMPN instructions ( CF 60 .. CF 63 )
+
+*/
+
+#include "emu.h"
+#include "debugger.h"
+#include "minx.h"
+
+#define FLAG_I 0x80
+#define FLAG_D 0x40
+#define FLAG_L 0x20
+#define FLAG_B 0x10
+#define FLAG_S 0x08
+#define FLAG_O 0x04
+#define FLAG_C 0x02
+#define FLAG_Z 0x01
+
+#define EXEC_X0 0x80
+#define EXEC_X1 0x40
+#define EXEC_X2 0x20
+#define EXEC_DZ 0x10
+#define EXEC_EN 0x08
+#define EXEC_04 0x04
+#define EXEC_02 0x02
+#define EXEC_01 0x01
+
+
+#define RD(offset) m_program->read_byte( offset )
+#define WR(offset,data) m_program->write_byte( offset, data )
+#define GET_MINX_PC ( ( m_PC & 0x8000 ) ? ( m_V << 15 ) | (m_PC & 0x7FFF ) : m_PC )
+
+
+const device_type MINX = &device_creator<minx_cpu_device>;
+
+
+minx_cpu_device::minx_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : cpu_device(mconfig, MINX, "Nintendo Minx", tag, owner, clock, "minx", __FILE__)
+ , m_program_config("program", ENDIANNESS_BIG, 8, 24, 0)
+{
+}
+
+
+UINT16 minx_cpu_device::rd16( UINT32 offset )
+{
+ return RD( offset ) | ( RD( offset + 1 ) << 8 );
+}
+
+
+void minx_cpu_device::wr16( UINT32 offset, UINT16 data )
+{
+ WR( offset, ( data & 0x00FF ) );
+ WR( offset + 1, ( data >> 8 ) );
+}
+
+
+void minx_cpu_device::device_start()
+{
+ m_program = &space(AS_PROGRAM);
+
+ state_add( MINX_PC, "PC", m_PC ).formatstr("%04X");
+ state_add( MINX_SP, "SP", m_SP ).formatstr("%04X");
+ state_add( MINX_BA, "BA", m_BA ).formatstr("%04X");
+ state_add( MINX_HL, "HL", m_HL ).formatstr("%04X");
+ state_add( MINX_X, "X", m_X ).formatstr("%04X");
+ state_add( MINX_Y, "Y", m_Y ).formatstr("%04X");
+ state_add( MINX_U, "U", m_U ).formatstr("%02X");
+ state_add( MINX_V, "V", m_V ).formatstr("%02X");
+ state_add( MINX_F, "F", m_F ).formatstr("%02X");
+ state_add( MINX_E, "E", m_E ).formatstr("%02X");
+ state_add( MINX_N, "N", m_N ).formatstr("%02X");
+ state_add( MINX_I, "I", m_I ).formatstr("%02X");
+ state_add( MINX_XI, "XI", m_XI ).formatstr("%02X");
+ state_add( MINX_YI, "YI", m_YI ).formatstr("%02X");
+
+ state_add(STATE_GENPC, "curpc", m_curpc).formatstr("%06X").noshow();
+ state_add(STATE_GENFLAGS, "GENFLAGS", m_flags).formatstr("%14s").noshow();
+
+ m_icountptr = &m_icount;
+}
+
+
+void minx_cpu_device::state_string_export(const device_state_entry &entry, std::string &str)
+{
+ switch (entry.index())
+ {
+ case STATE_GENFLAGS:
+ strprintf(str, "%c%c%c%c%c%c%c%c-%c%c%c%c%c",
+ m_F & FLAG_I ? 'I' : '.',
+ m_F & FLAG_D ? 'D' : '.',
+ m_F & FLAG_L ? 'L' : '.',
+ m_F & FLAG_B ? 'B' : '.',
+ m_F & FLAG_S ? 'S' : '.',
+ m_F & FLAG_O ? 'O' : '.',
+ m_F & FLAG_C ? 'C' : '.',
+ m_F & FLAG_Z ? 'Z' : '.',
+ m_E & EXEC_X0 ? '0' : '.',
+ m_E & EXEC_X1 ? '1' : '.',
+ m_E & EXEC_X2 ? '2' : '.',
+ m_E & EXEC_DZ ? 'z' : '.',
+ m_E & EXEC_EN ? 'E' : '.' );
+ break;
+ }
+}
+
+
+void minx_cpu_device::device_reset()
+{
+ m_SP = m_BA = m_HL = m_X = m_Y = 0;
+ m_U = m_V = m_F = m_E = m_I = m_XI = m_YI = 0;
+ m_halted = m_interrupt_pending = 0;
+
+ m_PC = rd16( 0 );
+}
+
+
+UINT8 minx_cpu_device::rdop()
+{
+ UINT8 op = RD( GET_MINX_PC );
+ m_PC++;
+ return op;
+}
+
+
+UINT16 minx_cpu_device::rdop16()
+{
+ UINT16 op = rdop();
+ op = op | ( rdop() << 8 );
+ return op;
+}
+
+
+#include "minxfunc.h"
+#include "minxopce.h"
+#include "minxopcf.h"
+#include "minxops.h"
+
+
+void minx_cpu_device::execute_run()
+{
+ do
+ {
+ m_curpc = GET_MINX_PC;
+ debugger_instruction_hook(this, m_curpc);
+
+ if ( m_interrupt_pending )
+ {
+ m_halted = 0;
+ if ( ! ( m_F & 0xc0 ) && m_U == m_V )
+ {
+ //logerror("minx_execute(): taking IRQ\n");
+ PUSH8( m_V );
+ PUSH16( m_PC );
+ PUSH8( m_F );
+
+ /* Set Interrupt Branch flag */
+ m_F |= 0x80;
+ m_V = 0;
+ m_PC = rd16( standard_irq_callback( 0 ) << 1 );
+ m_icount -= 28; /* This cycle count is a guess */
+ }
+ }
+
+ if ( m_halted )
+ {
+ m_icount -= insnminx_cycles_CE[0xAE];
+ }
+ else
+ {
+ execute_one();
+ }
+ } while ( m_icount > 0 );
+}
+
+
+void minx_cpu_device::execute_set_input(int inputnum, int state)
+{
+ if ( state == ASSERT_LINE )
+ {
+ m_interrupt_pending = 1;
+ }
+ else
+ {
+ m_interrupt_pending = 0;
+ }
+}
+
+
+offs_t minx_cpu_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options)
+{
+ extern CPU_DISASSEMBLE( minx );
+ return CPU_DISASSEMBLE_NAME(minx)(this, buffer, pc, oprom, opram, options);
+}