diff options
Diffstat (limited to 'src/devices/cpu/z80')
-rw-r--r-- | src/devices/cpu/z80/z80.cpp | 89 | ||||
-rw-r--r-- | src/devices/cpu/z80/z80.h | 13 | ||||
-rw-r--r-- | src/devices/cpu/z80/z80daisy_generic.cpp | 117 | ||||
-rw-r--r-- | src/devices/cpu/z80/z80daisy_generic.h | 71 | ||||
-rw-r--r-- | src/devices/cpu/z80/z80dasm.cpp | 164 | ||||
-rw-r--r-- | src/devices/cpu/z80/z80dasm.h | 56 |
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 ¶ms) +{ + 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 ¶ms) 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 |