summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/z80
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/z80')
-rw-r--r--src/devices/cpu/z80/z80.cpp89
-rw-r--r--src/devices/cpu/z80/z80.h13
-rw-r--r--src/devices/cpu/z80/z80daisy_generic.cpp117
-rw-r--r--src/devices/cpu/z80/z80daisy_generic.h71
-rw-r--r--src/devices/cpu/z80/z80dasm.cpp164
-rw-r--r--src/devices/cpu/z80/z80dasm.h56
6 files changed, 373 insertions, 137 deletions
diff --git a/src/devices/cpu/z80/z80.cpp b/src/devices/cpu/z80/z80.cpp
index 3dbf3f506d9..3b2fcd99761 100644
--- a/src/devices/cpu/z80/z80.cpp
+++ b/src/devices/cpu/z80/z80.cpp
@@ -110,6 +110,7 @@
#include "emu.h"
#include "debugger.h"
#include "z80.h"
+#include "z80dasm.h"
#define VERBOSE 0
@@ -208,7 +209,7 @@ static const uint8_t cc_op[0x100] = {
5,10,10,10,10,11, 7,11, 5,10,10, 0,10,17, 7,11, /* cb -> cc_cb */
5,10,10,11,10,11, 7,11, 5, 4,10,11,10, 0, 7,11, /* dd -> cc_xy */
5,10,10,19,10,11, 7,11, 5, 4,10, 4,10, 0, 7,11, /* ed -> cc_ed */
- 5,10,10, 4,10,11, 7,11, 5, 6,10, 4,10, 0, 7,11 /* fd -> cc_xy */
+ 5,10,10, 4,10,11, 7,11, 5, 6,10, 4,10, 0, 7,11 /* fd -> cc_xy */
};
static const uint8_t cc_cb[0x100] = {
@@ -235,14 +236,14 @@ static const uint8_t cc_ed[0x100] = {
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
-12,12,15,20, 8,14, 8, 9,12,12,15,20, 8,14, 8, 9,
-12,12,15,20, 8,14, 8, 9,12,12,15,20, 8,14, 8, 9,
-12,12,15,20, 8,14, 8,18,12,12,15,20, 8,14, 8,18,
-12,12,15,20, 8,14, 8, 8,12,12,15,20, 8,14, 8, 8,
+ 12,12,15,20,8,14, 8, 9,12,12,15,20, 8,14, 8, 9,
+ 12,12,15,20,8,14, 8, 9,12,12,15,20, 8,14, 8, 9,
+ 12,12,15,20,8,14, 8,18,12,12,15,20, 8,14, 8,18,
+ 12,12,15,20,8,14, 8, 8,12,12,15,20, 8,14, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
-16,16,16,16, 8, 8, 8, 8,16,16,16,16, 8, 8, 8, 8,
-16,16,16,16, 8, 8, 8, 8,16,16,16,16, 8, 8, 8, 8,
+ 16,16,16,16,8, 8, 8, 8,16,16,16,16, 8, 8, 8, 8,
+ 16,16,16,16,8, 8, 8, 8,16,16,16,16, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
@@ -258,7 +259,7 @@ static const uint8_t cc_xy[0x100] = {
4+4, 4+4, 4+4, 4+4, 4+4, 4+4,19 , 4+4, 4+4, 4+4, 4+4, 4+4, 4+4, 4+4,19 , 4+4,
4+4, 4+4, 4+4, 4+4, 4+4, 4+4,19 , 4+4, 4+4, 4+4, 4+4, 4+4, 4+4, 4+4,19 , 4+4,
4+4, 4+4, 4+4, 4+4, 4+4, 4+4,19 , 4+4, 4+4, 4+4, 4+4, 4+4, 4+4, 4+4,19 , 4+4,
-19 ,19 ,19 ,19 ,19 ,19 , 4+4,19 , 4+4, 4+4, 4+4, 4+4, 4+4, 4+4,19 , 4+4,
+ 19 ,19 ,19 ,19 ,19 ,19 , 4+4,19 , 4+4, 4+4, 4+4, 4+4, 4+4, 4+4,19 , 4+4,
4+4, 4+4, 4+4, 4+4, 4+4, 4+4,19 , 4+4, 4+4, 4+4, 4+4, 4+4, 4+4, 4+4,19 , 4+4,
4+4, 4+4, 4+4, 4+4, 4+4, 4+4,19 , 4+4, 4+4, 4+4, 4+4, 4+4, 4+4, 4+4,19 , 4+4,
4+4, 4+4, 4+4, 4+4, 4+4, 4+4,19 , 4+4, 4+4, 4+4, 4+4, 4+4, 4+4, 4+4,19 , 4+4,
@@ -266,26 +267,26 @@ static const uint8_t cc_xy[0x100] = {
5+4,10+4,10+4,10+4,10+4,11+4, 7+4,11+4, 5+4,10+4,10+4, 0 ,10+4,17+4, 7+4,11+4, /* cb -> cc_xycb */
5+4,10+4,10+4,11+4,10+4,11+4, 7+4,11+4, 5+4, 4+4,10+4,11+4,10+4, 4 , 7+4,11+4, /* dd -> cc_xy again */
5+4,10+4,10+4,19+4,10+4,11+4, 7+4,11+4, 5+4, 4+4,10+4, 4+4,10+4, 4 , 7+4,11+4, /* ed -> cc_ed */
- 5+4,10+4,10+4, 4+4,10+4,11+4, 7+4,11+4, 5+4, 6+4,10+4, 4+4,10+4, 4 , 7+4,11+4 /* fd -> cc_xy again */
+ 5+4,10+4,10+4, 4+4,10+4,11+4, 7+4,11+4, 5+4, 6+4,10+4, 4+4,10+4, 4 , 7+4,11+4 /* fd -> cc_xy again */
};
static const uint8_t cc_xycb[0x100] = {
-23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,
-23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,
-23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,
-23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,
-20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
-20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
-20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
-20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
-23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,
-23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,
-23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,
-23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,
-23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,
-23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,
-23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,
-23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23
+ 23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,
+ 23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,
+ 23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,
+ 23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,
+ 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
+ 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
+ 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
+ 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,
+ 23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,
+ 23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,
+ 23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,
+ 23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,
+ 23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,
+ 23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,
+ 23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,
+ 23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23
};
/* extra cycles if jr/jp/call taken and 'interrupt latency' on rst 0-7 */
@@ -394,22 +395,27 @@ static const uint8_t cc_ex[0x100] = {
} while (0)
/***************************************************************
- * Enter halt state; write 1 to fake port on first execution
+ * Enter halt state; write 1 to callback on first execution
***************************************************************/
inline void z80_device::halt()
{
PC--;
- m_halt = 1;
+ if (!m_halt)
+ {
+ m_halt = 1;
+ m_halt_cb(1);
+ }
}
/***************************************************************
- * Leave halt state; write 0 to fake port
+ * Leave halt state; write 0 to callback
***************************************************************/
inline void z80_device::leave_halt()
{
if( m_halt )
{
m_halt = 0;
+ m_halt_cb(0);
PC++;
}
}
@@ -564,8 +570,8 @@ inline void z80_device::jp_cond(bool cond)
***************************************************************/
inline void z80_device::jr()
{
- int8_t a = (int8_t)arg(); /* arg() also increments PC */
- PC += a; /* so don't do PC += arg() */
+ int8_t a = (int8_t)arg(); /* arg() also increments PC */
+ PC += a; /* so don't do PC += arg() */
WZ = PC;
}
@@ -609,7 +615,7 @@ inline void z80_device::call_cond(bool cond, uint8_t opcode)
}
else
{
- WZ = arg16(); /* implicit call PC+=2; */
+ WZ = arg16(); /* implicit call PC+=2; */
}
}
@@ -655,7 +661,7 @@ inline void z80_device::reti()
inline void z80_device::ld_r_a()
{
m_r = A;
- m_r2 = A & 0x80; /* keep bit 7 of r */
+ m_r2 = A & 0x80; /* keep bit 7 of r */
}
/***************************************************************
@@ -3401,12 +3407,12 @@ void z80_device::device_start()
m_program = &space(AS_PROGRAM);
m_decrypted_opcodes = has_space(AS_OPCODES) ? &space(AS_OPCODES) : m_program;
- m_direct = &m_program->direct();
- m_decrypted_opcodes_direct = &m_decrypted_opcodes->direct();
+ m_direct = m_program->direct<0>();
+ m_decrypted_opcodes_direct = m_decrypted_opcodes->direct<0>();
m_io = &space(AS_IO);
IX = IY = 0xffff; /* IX and IY are FFFF after a reset! */
- F = ZF; /* Zero flag is set */
+ F = ZF; /* Zero flag is set */
/* set up the state table */
state_add(STATE_GENPC, "PC", m_pc.w.l).callimport();
@@ -3452,6 +3458,7 @@ void z80_device::device_start()
m_irqack_cb.resolve_safe();
m_refresh_cb.resolve_safe();
+ m_halt_cb.resolve_safe();
}
void nsc800_device::device_start()
@@ -3465,6 +3472,8 @@ void nsc800_device::device_start()
****************************************************************************/
void z80_device::device_reset()
{
+ leave_halt();
+
PC = 0x0000;
m_i = 0;
m_r = 0;
@@ -3659,14 +3668,13 @@ void z80_device::state_string_export(const device_state_entry &entry, std::strin
}
//-------------------------------------------------
-// disasm_disassemble - call the disassembly
+// disassemble - call the disassembly
// helper function
//-------------------------------------------------
-offs_t z80_device::disasm_disassemble( std::ostream &stream, offs_t pc, const uint8_t *oprom, const uint8_t *opram, uint32_t options )
+util::disasm_interface *z80_device::create_disassembler()
{
- extern CPU_DISASSEMBLE( z80 );
- return CPU_DISASSEMBLE_NAME(z80)(this, stream, pc, oprom, opram, options);
+ return new z80_disassembler;
}
@@ -3697,7 +3705,8 @@ z80_device::z80_device(const machine_config &mconfig, device_type type, const ch
m_decrypted_opcodes_config("decrypted_opcodes", ENDIANNESS_LITTLE, 8, 16, 0),
m_io_config("io", ENDIANNESS_LITTLE, 8, 16, 0),
m_irqack_cb(*this),
- m_refresh_cb(*this)
+ m_refresh_cb(*this),
+ m_halt_cb(*this)
{
}
diff --git a/src/devices/cpu/z80/z80.h b/src/devices/cpu/z80/z80.h
index cf244e24d3c..732e425fd86 100644
--- a/src/devices/cpu/z80/z80.h
+++ b/src/devices/cpu/z80/z80.h
@@ -13,6 +13,9 @@
#define MCFG_Z80_SET_REFRESH_CALLBACK(_devcb) \
devcb = &z80_device::set_refresh_cb(*device, DEVCB_##_devcb);
+#define MCFG_Z80_SET_HALT_CALLBACK(_devcb) \
+ devcb = &z80_device::set_halt_cb(*device, DEVCB_##_devcb);
+
enum
{
NSC800_RSTA = INPUT_LINE_IRQ0 + 1,
@@ -41,6 +44,7 @@ public:
void z80_set_cycle_tables(const uint8_t *op, const uint8_t *cb, const uint8_t *ed, const uint8_t *xy, const uint8_t *xycb, const uint8_t *ex);
template<class _Object> static devcb_base &set_irqack_cb(device_t &device, _Object object) { return downcast<z80_device &>(device).m_irqack_cb.set_callback(object); }
template<class _Object> static devcb_base &set_refresh_cb(device_t &device, _Object object) { return downcast<z80_device &>(device).m_refresh_cb.set_callback(object); }
+ template<class _Object> static devcb_base &set_halt_cb(device_t &device, _Object object) { return downcast<z80_device &>(device).m_halt_cb.set_callback(object); }
protected:
z80_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
@@ -66,9 +70,7 @@ protected:
virtual void state_string_export(const device_state_entry &entry, std::string &str) const override;
// device_disasm_interface overrides
- virtual uint32_t disasm_min_opcode_bytes() const override { return 1; }
- virtual uint32_t disasm_max_opcode_bytes() const override { return 4; }
- virtual offs_t disasm_disassemble(std::ostream &stream, offs_t pc, const uint8_t *oprom, const uint8_t *opram, uint32_t options) override;
+ virtual util::disasm_interface *create_disassembler() override;
#undef PROTOTYPES
#define PROTOTYPES(prefix) \
@@ -242,10 +244,11 @@ protected:
address_space *m_program;
address_space *m_decrypted_opcodes;
address_space *m_io;
- direct_read_data *m_direct;
- direct_read_data *m_decrypted_opcodes_direct;
+ direct_read_data<0> *m_direct;
+ direct_read_data<0> *m_decrypted_opcodes_direct;
devcb_write_line m_irqack_cb;
devcb_write16 m_refresh_cb;
+ devcb_write_line m_halt_cb;
PAIR m_prvpc;
PAIR m_pc;
diff --git a/src/devices/cpu/z80/z80daisy_generic.cpp b/src/devices/cpu/z80/z80daisy_generic.cpp
new file mode 100644
index 00000000000..57d08c13066
--- /dev/null
+++ b/src/devices/cpu/z80/z80daisy_generic.cpp
@@ -0,0 +1,117 @@
+// license: BSD-3-Clause
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ Generic Z80 daisy chain device
+
+***************************************************************************/
+
+#include "emu.h"
+#include "z80daisy_generic.h"
+
+
+//**************************************************************************
+// DEVICE DEFINITIONS
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(Z80DAISY_GENERIC, z80daisy_generic_device, "z80daisy_generic", "Generic Z80 daisy chain device")
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// z80daisy_generic_device - constructor
+//-------------------------------------------------
+
+z80daisy_generic_device::z80daisy_generic_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, Z80DAISY_GENERIC, tag, owner, clock),
+ device_z80daisy_interface(mconfig, *this),
+ m_int_handler(*this),
+ m_int(0), m_mask(0), m_vector(0xff)
+{
+}
+
+//-------------------------------------------------
+// static_set_vector - static configuration
+//-------------------------------------------------
+
+void z80daisy_generic_device::static_set_vector(device_t &device, uint8_t vector)
+{
+ z80daisy_generic_device &dev = downcast<z80daisy_generic_device &>(device);
+ dev.m_vector = vector;
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void z80daisy_generic_device::device_start()
+{
+ // resolve callbacks
+ m_int_handler.resolve_safe();
+
+ // register for save states
+ save_item(NAME(m_int));
+ save_item(NAME(m_mask));
+ save_item(NAME(m_vector));
+}
+
+//-------------------------------------------------
+// z80daisy_irq_state - return the overall IRQ
+// state for this device
+//-------------------------------------------------
+
+int z80daisy_generic_device::z80daisy_irq_state()
+{
+ if (m_int & ~m_mask)
+ return Z80_DAISY_INT;
+
+ return 0;
+}
+
+//-------------------------------------------------
+// z80daisy_irq_ack - acknowledge an IRQ and
+// return the appropriate vector
+//-------------------------------------------------
+
+int z80daisy_generic_device::z80daisy_irq_ack()
+{
+ return m_vector;
+}
+
+//-------------------------------------------------
+// z80daisy_irq_reti - clear the interrupt
+// pending state to allow other interrupts through
+//-------------------------------------------------
+
+void z80daisy_generic_device::z80daisy_irq_reti()
+{
+}
+
+//-------------------------------------------------
+// update_interrupt() - check interrupt status
+//-------------------------------------------------
+
+void z80daisy_generic_device::update_interrupt()
+{
+ m_int_handler(m_int & ~m_mask ? ASSERT_LINE : CLEAR_LINE);
+}
+
+
+//**************************************************************************
+// INTERFACE
+//**************************************************************************
+
+WRITE_LINE_MEMBER( z80daisy_generic_device::int_w )
+{
+ m_int = state;
+ update_interrupt();
+}
+
+WRITE_LINE_MEMBER( z80daisy_generic_device::mask_w )
+{
+ m_mask = state;
+ update_interrupt();
+}
diff --git a/src/devices/cpu/z80/z80daisy_generic.h b/src/devices/cpu/z80/z80daisy_generic.h
new file mode 100644
index 00000000000..389c5eda43f
--- /dev/null
+++ b/src/devices/cpu/z80/z80daisy_generic.h
@@ -0,0 +1,71 @@
+// license: BSD-3-Clause
+// copyright-holders: Dirk Best
+/***************************************************************************
+
+ Generic Z80 daisy chain device
+
+***************************************************************************/
+
+#ifndef MAME_DEVICES_CPU_Z80_Z80DAISY_GENERIC_H
+#define MAME_DEVICES_CPU_Z80_Z80DAISY_GENERIC_H
+
+#pragma once
+
+#include "z80daisy.h"
+
+
+//**************************************************************************
+// INTERFACE CONFIGURATION MACROS
+//**************************************************************************
+
+#define MCFG_Z80DAISY_GENERIC_ADD(_tag, _vector) \
+ MCFG_DEVICE_ADD(_tag, Z80DAISY_GENERIC, 0) \
+ z80daisy_generic_device::static_set_vector(*device, _vector); \
+
+#define MCFG_Z80DAISY_GENERIC_INT_CB(_devcb) \
+ devcb = &z80daisy_generic_device::set_int_handler(*device, DEVCB_##_devcb);
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class z80daisy_generic_device : public device_t, public device_z80daisy_interface
+{
+public:
+ // construction/destruction
+ z80daisy_generic_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ // callbacks
+ template <class Object> static devcb_base &set_int_handler(device_t &device, Object &&cb)
+ { return downcast<z80daisy_generic_device &>(device).m_int_handler.set_callback(std::forward<Object>(cb)); }
+
+ // configuration
+ static void static_set_vector(device_t &device, uint8_t vector);
+
+ DECLARE_WRITE_LINE_MEMBER(int_w);
+ DECLARE_WRITE_LINE_MEMBER(mask_w);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+
+ // z80daisy_interface overrides
+ virtual int z80daisy_irq_state() override;
+ virtual int z80daisy_irq_ack() override;
+ virtual void z80daisy_irq_reti() override;
+
+private:
+ void update_interrupt();
+
+ devcb_write_line m_int_handler;
+
+ int m_int;
+ int m_mask;
+ int m_vector;
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(Z80DAISY_GENERIC, z80daisy_generic_device)
+
+#endif // MAME_DEVICES_CPU_Z80_Z80DAISY_GENERIC_H
diff --git a/src/devices/cpu/z80/z80dasm.cpp b/src/devices/cpu/z80/z80dasm.cpp
index 2af88954943..b59b3a38eb6 100644
--- a/src/devices/cpu/z80/z80dasm.cpp
+++ b/src/devices/cpu/z80/z80dasm.cpp
@@ -9,20 +9,8 @@
#include "emu.h"
#include "debugger.h"
-#include "z80.h"
+#include "z80dasm.h"
-enum e_mnemonics
-{
- zADC ,zADD ,zAND ,zBIT ,zCALL ,zCCF ,zCP ,zCPD ,
- zCPDR ,zCPI ,zCPIR ,zCPL ,zDAA ,zDB ,zDEC ,zDI ,
- zDJNZ ,zEI ,zEX ,zEXX ,zHLT ,zIM ,zIN ,zINC ,
- zIND ,zINDR ,zINI ,zINIR ,zJP ,zJR ,zLD ,zLDD ,
- zLDDR ,zLDI ,zLDIR ,zNEG ,zNOP ,zOR ,zOTDR ,zOTIR ,
- zOUT ,zOUTD ,zOUTI ,zPOP ,zPUSH ,zRES ,zRET ,zRETI ,
- zRETN ,zRL ,zRLA ,zRLC ,zRLCA ,zRLD ,zRR ,zRRA ,
- zRRC ,zRRCA ,zRRD ,zRST ,zSBC ,zSCF ,zSET ,zSLA ,
- zSLL ,zSRA ,zSRL ,zSUB ,zXOR
-};
static const char *const s_mnemonic[] =
{
@@ -37,29 +25,20 @@ static const char *const s_mnemonic[] =
"sll" ,"sra" ,"srl" ,"sub" ,"xor "
};
-#define _OVER DASMFLAG_STEP_OVER
-#define _OUT DASMFLAG_STEP_OUT
-
-static const uint32_t s_flags[] =
-{
- 0 ,0 ,0 ,0 ,_OVER,0 ,0 ,0 ,
- _OVER,0 ,_OVER,0 ,0 ,0 ,0 ,0 ,
- _OVER,0 ,0 ,0 ,_OVER,0 ,0 ,0 ,
- 0 ,_OVER,0 ,_OVER,0 ,0 ,0 ,0 ,
- _OVER,0 ,_OVER,0 ,0 ,0 ,_OVER,_OVER,
- 0 ,0 ,0 ,0 ,0 ,0 ,_OUT ,_OUT ,
- _OUT ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
- 0 ,0 ,0 ,_OVER,0 ,0 ,0 ,0 ,
- 0 ,0 ,0 ,0 ,0
-};
-
-struct z80dasm
+const u32 z80_disassembler::s_flags[] =
{
- uint8_t mnemonic;
- const char *arguments;
+ 0 ,0 ,0 ,0 ,STEP_OVER,0 ,0 ,0 ,
+ STEP_OVER,0 ,STEP_OVER,0 ,0 ,0 ,0 ,0 ,
+ STEP_OVER,0 ,0 ,0 ,STEP_OVER,0 ,0 ,0 ,
+ 0 ,STEP_OVER,0 ,STEP_OVER,0 ,0 ,0 ,0 ,
+ STEP_OVER,0 ,STEP_OVER,0 ,0 ,0 ,STEP_OVER,STEP_OVER,
+ 0 ,0 ,0 ,0 ,0 ,0 ,STEP_OUT ,STEP_OUT ,
+ STEP_OUT ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
+ 0 ,0 ,0 ,STEP_OVER,0 ,0 ,0 ,0 ,
+ 0 ,0 ,0 ,0 ,0
};
-static const z80dasm mnemonic_xx_cb[256] =
+const z80_disassembler::z80dasm z80_disassembler::mnemonic_xx_cb[256] =
{
{zRLC,"b=Y"}, {zRLC,"c=Y"}, {zRLC,"d=Y"}, {zRLC,"e=Y"},
{zRLC,"h=Y"}, {zRLC,"l=Y"}, {zRLC,"Y"}, {zRLC,"a=Y"},
@@ -127,7 +106,7 @@ static const z80dasm mnemonic_xx_cb[256] =
{zSET,"h=7,Y"}, {zSET,"l=7,Y"}, {zSET,"7,Y"}, {zSET,"a=7,Y"}
};
-static const z80dasm mnemonic_cb[256] =
+const z80_disassembler::z80dasm z80_disassembler::mnemonic_cb[256] =
{
{zRLC,"b"}, {zRLC,"c"}, {zRLC,"d"}, {zRLC,"e"},
{zRLC,"h"}, {zRLC,"l"}, {zRLC,"(hl)"}, {zRLC,"a"},
@@ -195,7 +174,7 @@ static const z80dasm mnemonic_cb[256] =
{zSET,"7,h"}, {zSET,"7,l"}, {zSET,"7,(hl)"},{zSET,"7,a"}
};
-static const z80dasm mnemonic_ed[256] =
+const z80_disassembler::z80dasm z80_disassembler::mnemonic_ed[256] =
{
{zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
{zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
@@ -214,21 +193,21 @@ static const z80dasm mnemonic_ed[256] =
{zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
{zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
{zIN,"b,(c)"}, {zOUT,"(c),b"}, {zSBC,"hl,bc"}, {zLD,"(W),bc"},
- {zNEG,nullptr}, {zRETN,nullptr}, {zIM,"0"}, {zLD,"i,a"},
+ {zNEG,nullptr}, {zRETN,nullptr},{zIM,"0"}, {zLD,"i,a"},
{zIN,"c,(c)"}, {zOUT,"(c),c"}, {zADC,"hl,bc"}, {zLD,"bc,(W)"},
- {zNEG,"*"}, {zRETI,nullptr}, {zIM,"0"}, {zLD,"r,a"},
+ {zNEG,"*"}, {zRETI,nullptr},{zIM,"0"}, {zLD,"r,a"},
{zIN,"d,(c)"}, {zOUT,"(c),d"}, {zSBC,"hl,de"}, {zLD,"(W),de"},
- {zNEG,"*"}, {zRETN,nullptr}, {zIM,"1"}, {zLD,"a,i"},
+ {zNEG,"*"}, {zRETN,nullptr},{zIM,"1"}, {zLD,"a,i"},
{zIN,"e,(c)"}, {zOUT,"(c),e"}, {zADC,"hl,de"}, {zLD,"de,(W)"},
- {zNEG,"*"}, {zRETI,nullptr}, {zIM,"2"}, {zLD,"a,r"},
+ {zNEG,"*"}, {zRETI,nullptr},{zIM,"2"}, {zLD,"a,r"},
{zIN,"h,(c)"}, {zOUT,"(c),h"}, {zSBC,"hl,hl"}, {zLD,"(W),hl"},
- {zNEG,"*"}, {zRETN,nullptr}, {zIM,"0"}, {zRRD,"(hl)"},
+ {zNEG,"*"}, {zRETN,nullptr},{zIM,"0"}, {zRRD,"(hl)"},
{zIN,"l,(c)"}, {zOUT,"(c),l"}, {zADC,"hl,hl"}, {zLD,"hl,(W)"},
- {zNEG,"*"}, {zRETI,nullptr}, {zIM,"0"}, {zRLD,"(hl)"},
+ {zNEG,"*"}, {zRETI,nullptr},{zIM,"0"}, {zRLD,"(hl)"},
{zIN,"0,(c)"}, {zOUT,"(c),0"}, {zSBC,"hl,sp"}, {zLD,"(W),sp"},
- {zNEG,"*"}, {zRETN,nullptr}, {zIM,"1"}, {zDB,"?"},
+ {zNEG,"*"}, {zRETN,nullptr},{zIM,"1"}, {zDB,"?"},
{zIN,"a,(c)"}, {zOUT,"(c),a"}, {zADC,"hl,sp"}, {zLD,"sp,(W)"},
- {zNEG,"*"}, {zRETI,nullptr}, {zIM,"2"}, {zDB,"?"},
+ {zNEG,"*"}, {zRETI,nullptr},{zIM,"2"}, {zDB,"?"},
{zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
{zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
{zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
@@ -263,7 +242,7 @@ static const z80dasm mnemonic_ed[256] =
{zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"}
};
-static const z80dasm mnemonic_xx[256] =
+const z80_disassembler::z80dasm z80_disassembler::mnemonic_xx[256] =
{
{zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
{zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"},
@@ -331,9 +310,9 @@ static const z80dasm mnemonic_xx[256] =
{zDB,"?"}, {zDB,"?"}, {zDB,"?"}, {zDB,"?"}
};
-static const z80dasm mnemonic_main[256] =
+const z80_disassembler::z80dasm z80_disassembler::mnemonic_main[256] =
{
- {zNOP,nullptr}, {zLD,"bc,N"}, {zLD,"(bc),a"}, {zINC,"bc"},
+ {zNOP,nullptr}, {zLD,"bc,N"}, {zLD,"(bc),a"}, {zINC,"bc"},
{zINC,"b"}, {zDEC,"b"}, {zLD,"b,B"}, {zRLCA,nullptr},
{zEX,"af,af'"}, {zADD,"hl,bc"}, {zLD,"a,(bc)"}, {zDEC,"bc"},
{zINC,"c"}, {zDEC,"c"}, {zLD,"c,B"}, {zRRCA,nullptr},
@@ -383,11 +362,11 @@ static const z80dasm mnemonic_main[256] =
{zCP,"h"}, {zCP,"l"}, {zCP,"(hl)"}, {zCP,"a"},
{zRET,"nz"}, {zPOP,"bc"}, {zJP,"nz,A"}, {zJP,"A"},
{zCALL,"nz,A"}, {zPUSH,"bc"}, {zADD,"a,B"}, {zRST,"V"},
- {zRET,"z"}, {zRET,nullptr}, {zJP,"z,A"}, {zDB,"cb"},
+ {zRET,"z"}, {zRET,nullptr}, {zJP,"z,A"}, {zDB,"cb"},
{zCALL,"z,A"}, {zCALL,"A"}, {zADC,"a,B"}, {zRST,"V"},
{zRET,"nc"}, {zPOP,"de"}, {zJP,"nc,A"}, {zOUT,"(P),a"},
{zCALL,"nc,A"}, {zPUSH,"de"}, {zSUB,"B"}, {zRST,"V"},
- {zRET,"c"}, {zEXX,nullptr}, {zJP,"c,A"}, {zIN,"a,(P)"},
+ {zRET,"c"}, {zEXX,nullptr}, {zJP,"c,A"}, {zIN,"a,(P)"},
{zCALL,"c,A"}, {zDB,"dd"}, {zSBC,"a,B"}, {zRST,"V"},
{zRET,"po"}, {zPOP,"hl"}, {zJP,"po,A"}, {zEX,"(sp),hl"},
{zCALL,"po,A"}, {zPUSH,"hl"}, {zAND,"B"}, {zRST,"V"},
@@ -399,65 +378,73 @@ static const z80dasm mnemonic_main[256] =
{zCALL,"m,A"}, {zDB,"fd"}, {zCP,"B"}, {zRST,"V"}
};
-static char sign(int8_t offset)
+char z80_disassembler::sign(s8 offset)
{
return (offset < 0)? '-':'+';
}
-static int offs(int8_t offset)
+u32 z80_disassembler::offs(s8 offset)
{
- if (offset < 0) return -offset;
+ if (offset < 0)
+ return -offset;
return offset;
}
-/****************************************************************************
- * Disassemble opcode at PC and return number of bytes it takes
- ****************************************************************************/
-CPU_DISASSEMBLE(z80)
+z80_disassembler::z80_disassembler()
{
- const z80dasm *d;
- const char *src, *ixy;
- int8_t offset = 0;
- uint8_t op, op1 = 0;
- uint16_t ea;
- int pos = 0;
+}
- ixy = "oops!!";
+u32 z80_disassembler::opcode_alignment() const
+{
+ return 1;
+}
+
+offs_t z80_disassembler::disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer &params)
+{
+ s8 offset = 0;
- op = oprom[pos++];
+ offs_t pos = pc;
+ std::string ixy = "oops!!";
+ const z80dasm *d = nullptr;
+ u8 op = opcodes.r8(pos++);
switch (op)
{
case 0xcb:
- op = oprom[pos++];
+ op = opcodes.r8(pos++);
d = &mnemonic_cb[op];
break;
case 0xed:
- op1 = oprom[pos++];
- d = &mnemonic_ed[op1];
+ d = &mnemonic_ed[opcodes.r8(pos++)];
break;
case 0xdd:
+ {
ixy = "ix";
- op1 = oprom[pos++];
+ u8 op1 = opcodes.r8(pos++);
if( op1 == 0xcb )
{
- offset = (int8_t) opram[pos++];
- op1 = opram[pos++]; /* fourth byte from opbase.ram! */
+ offset = params.r8(pos++);
+ op1 = params.r8(pos++);
d = &mnemonic_xx_cb[op1];
}
- else d = &mnemonic_xx[op1];
+ else
+ d = &mnemonic_xx[op1];
break;
+ }
case 0xfd:
+ {
ixy = "iy";
- op1 = oprom[pos++];
+ u8 op1 = opcodes.r8(pos++);
if( op1 == 0xcb )
{
- offset = (int8_t) opram[pos++];
- op1 = opram[pos++]; /* fourth byte from opbase.ram! */
+ offset = params.r8(pos++);
+ op1 = params.r8(pos++);
d = &mnemonic_xx_cb[op1];
}
- else d = &mnemonic_xx[op1];
+ else
+ d = &mnemonic_xx[op1];
break;
+ }
default:
d = &mnemonic_main[op];
break;
@@ -466,47 +453,40 @@ CPU_DISASSEMBLE(z80)
if( d->arguments )
{
util::stream_format(stream, "%-4s ", s_mnemonic[d->mnemonic]);
- src = d->arguments;
+ const char *src = d->arguments;
while( *src )
{
switch( *src )
{
case '?': /* illegal opcode */
- util::stream_format(stream, "$%02x,$%02x", op, op1 );
+ util::stream_format(stream, "$%02x", op );
break;
case 'A':
- ea = opram[pos+0] + ( opram[pos+1] << 8 );
+ util::stream_format(stream, "$%04X", params.r16(pos) );
pos += 2;
- util::stream_format(stream, "$%04X", ea );
break;
case 'B': /* Byte op arg */
- ea = opram[pos++];
- util::stream_format(stream, "$%02X", ea );
+ util::stream_format(stream, "$%02X", params.r8(pos++) );
break;
case 'N': /* Immediate 16 bit */
- ea = opram[pos+0] + ( opram[pos+1] << 8 );
+ util::stream_format(stream, "$%04X", params.r16(pos) );
pos += 2;
- util::stream_format(stream, "$%04X", ea );
break;
case 'O': /* Offset relative to PC */
- offset = (int8_t) opram[pos++];
- util::stream_format(stream, "$%04X", (pc + offset + 2) & 0xffff);
+ util::stream_format(stream, "$%04X", (pc + s8(params.r8(pos++)) + 2) & 0xffff);
break;
case 'P': /* Port number */
- ea = opram[pos++];
- util::stream_format(stream, "$%02X", ea );
+ util::stream_format(stream, "$%02X", params.r8(pos++) );
break;
case 'V': /* Restart vector */
- ea = op & 0x38;
- util::stream_format(stream, "$%02X", ea );
+ util::stream_format(stream, "$%02X", op & 0x38 );
break;
case 'W': /* Memory address word */
- ea = opram[pos+0] + ( opram[pos+1] << 8 );
+ util::stream_format(stream, "$%04X", params.r16(pos) );
pos += 2;
- util::stream_format(stream, "$%04X", ea );
break;
case 'X':
- offset = (int8_t) opram[pos++];
+ offset = params.r8(pos++);
/* fall through */
case 'Y':
util::stream_format(stream,"(%s%c$%02x)", ixy, sign(offset), offs(offset) );
@@ -525,5 +505,5 @@ CPU_DISASSEMBLE(z80)
util::stream_format(stream, "%s", s_mnemonic[d->mnemonic]);
}
- return pos | s_flags[d->mnemonic] | DASMFLAG_SUPPORTED;
+ return (pos - pc) | s_flags[d->mnemonic] | SUPPORTED;
}
diff --git a/src/devices/cpu/z80/z80dasm.h b/src/devices/cpu/z80/z80dasm.h
new file mode 100644
index 00000000000..774f4df89a8
--- /dev/null
+++ b/src/devices/cpu/z80/z80dasm.h
@@ -0,0 +1,56 @@
+// license:BSD-3-Clause
+// copyright-holders:Juergen Buchmueller
+/*****************************************************************************
+ *
+ * z80dasm.h
+ * Portable Z80 disassembler
+ *
+ *****************************************************************************/
+
+#ifndef MAME_CPU_Z80_Z80DASM_H
+#define MAME_CPU_Z80_Z80DASM_H
+
+#pragma once
+
+class z80_disassembler : public util::disasm_interface
+{
+public:
+ z80_disassembler();
+ virtual ~z80_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 &params) override;
+
+protected:
+ struct z80dasm
+ {
+ u8 mnemonic;
+ const char *arguments;
+ };
+
+ enum e_mnemonics
+ {
+ zADC ,zADD ,zAND ,zBIT ,zCALL ,zCCF ,zCP ,zCPD ,
+ zCPDR ,zCPI ,zCPIR ,zCPL ,zDAA ,zDB ,zDEC ,zDI ,
+ zDJNZ ,zEI ,zEX ,zEXX ,zHLT ,zIM ,zIN ,zINC ,
+ zIND ,zINDR ,zINI ,zINIR ,zJP ,zJR ,zLD ,zLDD ,
+ zLDDR ,zLDI ,zLDIR ,zNEG ,zNOP ,zOR ,zOTDR ,zOTIR ,
+ zOUT ,zOUTD ,zOUTI ,zPOP ,zPUSH ,zRES ,zRET ,zRETI ,
+ zRETN ,zRL ,zRLA ,zRLC ,zRLCA ,zRLD ,zRR ,zRRA ,
+ zRRC ,zRRCA ,zRRD ,zRST ,zSBC ,zSCF ,zSET ,zSLA ,
+ zSLL ,zSRA ,zSRL ,zSUB ,zXOR
+ };
+
+ static inline char sign(s8 offset);
+ static inline u32 offs(s8 offset);
+
+ static const u32 s_flags[];
+ static const z80dasm mnemonic_xx_cb[256];
+ static const z80dasm mnemonic_cb[256];
+ static const z80dasm mnemonic_ed[256];
+ static const z80dasm mnemonic_xx[256];
+ static const z80dasm mnemonic_main[256];
+
+};
+
+#endif