summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/st9
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/st9')
-rw-r--r--src/devices/cpu/st9/st905x.cpp238
-rw-r--r--src/devices/cpu/st9/st905x.h95
-rw-r--r--src/devices/cpu/st9/st9dasm.cpp1373
-rw-r--r--src/devices/cpu/st9/st9dasm.h90
4 files changed, 1796 insertions, 0 deletions
diff --git a/src/devices/cpu/st9/st905x.cpp b/src/devices/cpu/st9/st905x.cpp
new file mode 100644
index 00000000000..590c4d142d9
--- /dev/null
+++ b/src/devices/cpu/st9/st905x.cpp
@@ -0,0 +1,238 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/***************************************************************************
+
+ SGS-Thomson ST905x series
+
+ Currently this device is just a stub with no actual execution core.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "st905x.h"
+#include "st9dasm.h"
+
+// device type definitions
+DEFINE_DEVICE_TYPE(ST90R50, st90r50_device, "st90r50", "SGS-Thomson ST90R50")
+
+st9_device::st9_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, address_map_constructor regmap)
+ : cpu_device(mconfig, type, tag, owner, clock)
+ , m_program_config("program", ENDIANNESS_BIG, 8, 16, 0)
+ , m_data_config("data", ENDIANNESS_BIG, 8, 16, 0)
+ , m_register_config("register", ENDIANNESS_BIG, 8, 8, 0, regmap)
+ , m_pc(0)
+ , m_sspr(0)
+ , m_uspr(0)
+ , m_cicr(0)
+ , m_flagr(0)
+ , m_rpr{0, 0}
+ , m_ppr(0)
+ , m_moder(0)
+ , m_icount(0)
+{
+}
+
+st90r50_device::st90r50_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : st9_device(mconfig, ST90R50, tag, owner, clock, address_map_constructor(FUNC(st90r50_device::register_map), this))
+{
+}
+
+void st90r50_device::register_map(address_map &map)
+{
+ map(0x00, 0xdf).ram();
+ map(0xe6, 0xe6).rw(FUNC(st90r50_device::cicr_r), FUNC(st90r50_device::cicr_w));
+ map(0xe7, 0xe7).rw(FUNC(st90r50_device::flagr_r), FUNC(st90r50_device::flagr_w));
+ map(0xe8, 0xe9).rw(FUNC(st90r50_device::rpr_r), FUNC(st90r50_device::rpr_w));
+ map(0xea, 0xea).rw(FUNC(st90r50_device::ppr_r), FUNC(st90r50_device::ppr_w));
+ map(0xeb, 0xeb).rw(FUNC(st90r50_device::moder_r), FUNC(st90r50_device::moder_w));
+ map(0xec, 0xef).rw(FUNC(st90r50_device::spr_r), FUNC(st90r50_device::spr_w));
+}
+
+std::unique_ptr<util::disasm_interface> st9_device::create_disassembler()
+{
+ return std::make_unique<st9_disassembler>();
+}
+
+device_memory_interface::space_config_vector st9_device::memory_space_config() const
+{
+ if (has_configured_map(AS_DATA))
+ {
+ return space_config_vector {
+ std::make_pair(AS_PROGRAM, &m_program_config),
+ std::make_pair(AS_DATA, &m_data_config),
+ std::make_pair(AS_IO, &m_register_config)
+ };
+ }
+ else
+ {
+ return space_config_vector {
+ std::make_pair(AS_PROGRAM, &m_program_config),
+ std::make_pair(AS_IO, &m_register_config)
+ };
+ }
+}
+
+u8 st9_device::cicr_r()
+{
+ return m_cicr;
+}
+
+void st9_device::cicr_w(u8 data)
+{
+ m_cicr = data;
+}
+
+u8 st9_device::flagr_r()
+{
+ return m_flagr;
+}
+
+void st9_device::flagr_w(u8 data)
+{
+ m_flagr = data;
+}
+
+u8 st9_device::rpr_r(offs_t offset)
+{
+ return m_rpr[offset];
+}
+
+void st9_device::rpr_w(offs_t offset, u8 data)
+{
+ m_rpr[offset] = data & 0xfc;
+ if (BIT(data, 2))
+ m_rpr[offset ^ 1] |= 0x04;
+ else
+ m_rpr[offset ^ 1] &= 0xf8;
+}
+
+u8 st9_device::ppr_r()
+{
+ return m_ppr;
+}
+
+void st9_device::ppr_w(u8 data)
+{
+ m_ppr = data & 0xfc;
+}
+
+u8 st9_device::moder_r()
+{
+ return m_moder;
+}
+
+void st9_device::moder_w(u8 data)
+{
+ m_moder = data;
+}
+
+u8 st9_device::spr_r(offs_t offset)
+{
+ return BIT(BIT(offset, 1) ? m_sspr : m_uspr, BIT(offset, 0) ? 0 : 8, 8);
+}
+
+void st9_device::spr_w(offs_t offset, u8 data)
+{
+ u16 &spr = BIT(offset, 1) ? m_sspr : m_uspr;
+ if (BIT(offset, 0))
+ spr = (spr & 0xff00) | data;
+ else
+ spr = u16(data) << 8 | (spr & 0x00ff);
+}
+
+u8 st9_device::debug_register_r(int r)
+{
+ auto dis = machine().disable_side_effects();
+ return m_register.read_byte(BIT(m_rpr[0], 2) ? (m_rpr[BIT(r, 3)] & 0xf8) | (r & 7) : (m_rpr[0] & 0xf0) | r);
+}
+
+void st9_device::debug_register_w(int r, u8 data)
+{
+ auto dis = machine().disable_side_effects();
+ m_register.write_byte(BIT(m_rpr[0], 2) ? (m_rpr[BIT(r, 3)] & 0xf8) | (r & 7) : (m_rpr[0] & 0xf0) | r, data);
+}
+
+u16 st9_device::debug_rpair_r(int rr)
+{
+ auto dis = machine().disable_side_effects();
+ return m_register.read_word(BIT(m_rpr[0], 2) ? (m_rpr[BIT(rr, 3)] & 0xf8) | (rr & 6) : (m_rpr[0] & 0xf0) | rr);
+}
+
+void st9_device::debug_rpair_w(int rr, u16 data)
+{
+ auto dis = machine().disable_side_effects();
+ m_register.write_word(BIT(m_rpr[0], 2) ? (m_rpr[BIT(rr, 3)] & 0xf8) | (rr & 6) : (m_rpr[0] & 0xf0) | rr, data);
+}
+
+void st9_device::device_start()
+{
+ space(AS_PROGRAM).cache(m_cache);
+ space(AS_PROGRAM).specific(m_program);
+ space(has_space(AS_DATA) ? AS_DATA : AS_PROGRAM).specific(m_data);
+ space(AS_IO).specific(m_register);
+
+ set_icountptr(m_icount);
+
+ using namespace std::placeholders;
+ state_add(STATE_GENPC, "GENPC", m_pc).noshow();
+ state_add(STATE_GENPCBASE, "CURPC", m_pc).noshow();
+ state_add(STATE_GENFLAGS, "CURFLAGS", m_flagr).noshow().formatstr("%10s");
+ state_add(ST9_PC, "PC", m_pc);
+ state_add(ST9_SSPR, "SSPR", m_sspr);
+ state_add(ST9_USPR, "USPR", m_uspr);
+ state_add(ST9_CICR, "CICR", m_cicr);
+ state_add(ST9_FLAGR, "FLAGR", m_flagr);
+ state_add(ST9_RP0R, "RP0R", m_rpr[0], std::bind(&st9_device::rpr_w, this, 0, _1)).mask(0xfc);
+ state_add(ST9_RP1R, "RP1R", m_rpr[1], std::bind(&st9_device::rpr_w, this, 1, _1)).mask(0xfc);
+ state_add(ST9_PPR, "PPR", m_ppr).mask(0xfc);
+ state_add(ST9_MODER, "MODER", m_moder);
+ for (int i = 0; i < 16; i++)
+ state_add<u8>(ST9_R0 + i, util::string_format("r%d", i).c_str(),
+ std::bind(&st9_device::debug_register_r, this, i),
+ std::bind(&st9_device::debug_register_w, this, i, _1));
+ for (int i = 0; i < 16; i += 2)
+ state_add<u16>(ST9_RR0 + i / 2, util::string_format("rr%d", i).c_str(),
+ std::bind(&st9_device::debug_rpair_r, this, i),
+ std::bind(&st9_device::debug_rpair_w, this, i, _1)).noshow();
+
+ save_item(NAME(m_pc));
+ save_item(NAME(m_sspr));
+ save_item(NAME(m_uspr));
+ save_item(NAME(m_cicr));
+ save_item(NAME(m_flagr));
+ save_item(NAME(m_rpr));
+ save_item(NAME(m_ppr));
+ save_item(NAME(m_moder));
+}
+
+void st9_device::device_reset()
+{
+ m_cicr = 0x87;
+ m_moder = 0xe0;
+}
+
+void st9_device::execute_run()
+{
+ m_pc = m_cache.read_word(0x0000);
+ debugger_instruction_hook(m_pc);
+
+ m_icount = 0;
+}
+
+void st9_device::state_string_export(const device_state_entry &entry, std::string &str) const
+{
+ switch (entry.index())
+ {
+ case STATE_GENFLAGS:
+ str = util::string_format("%c%c%c%c%c%c%c %cM",
+ BIT(m_flagr, 7) ? 'C' : '.',
+ BIT(m_flagr, 6) ? 'Z' : '.',
+ BIT(m_flagr, 5) ? 'S' : '.',
+ BIT(m_flagr, 4) ? 'V' : '.',
+ BIT(m_flagr, 3) ? 'D' : '.',
+ BIT(m_flagr, 2) ? 'H' : '.',
+ BIT(m_flagr, 1) ? 'U' : '.',
+ BIT(m_flagr, 0) ? 'D' : 'P');
+ break;
+ }
+}
diff --git a/src/devices/cpu/st9/st905x.h b/src/devices/cpu/st9/st905x.h
new file mode 100644
index 00000000000..813251666f9
--- /dev/null
+++ b/src/devices/cpu/st9/st905x.h
@@ -0,0 +1,95 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+
+#ifndef MAME_CPU_ST9_ST905X_H
+#define MAME_CPU_ST9_ST905X_H
+
+#pragma once
+
+class st9_device : public cpu_device
+{
+public:
+ enum {
+ ST9_PC, ST9_SSPR, ST9_USPR,
+ ST9_CICR, ST9_FLAGR, ST9_RP0R, ST9_RP1R, ST9_PPR, ST9_MODER,
+ ST9_R0, ST9_R1, ST9_R2, ST9_R3, ST9_R4, ST9_R5, ST9_R6, ST9_R7,
+ ST9_R8, ST9_R9, ST9_R10, ST9_R11, ST9_R12, ST9_R13, ST9_R14, ST9_R15,
+ ST9_RR0, ST9_RR2, ST9_RR4, ST9_RR6, ST9_RR8, ST9_RR10, ST9_RR12, ST9_RR14
+ };
+
+protected:
+ // construction/destruction
+ st9_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, address_map_constructor regmap);
+
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // device_execute_interface overrides
+ virtual void execute_run() override;
+
+ // device_disasm_interface overrides
+ virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
+
+ // device_memory_interface overrides
+ virtual space_config_vector memory_space_config() const override;
+
+ // device_state_interface overrides
+ void state_string_export(const device_state_entry &entry, std::string &str) const override;
+
+ // internal register handlers
+ u8 cicr_r();
+ void cicr_w(u8 data);
+ u8 flagr_r();
+ void flagr_w(u8 data);
+ u8 rpr_r(offs_t offset);
+ void rpr_w(offs_t offset, u8 data);
+ u8 ppr_r();
+ void ppr_w(u8 data);
+ u8 moder_r();
+ void moder_w(u8 data);
+ u8 spr_r(offs_t offset);
+ void spr_w(offs_t offset, u8 data);
+
+private:
+ // debugging helpers
+ u8 debug_register_r(int r);
+ void debug_register_w(int r, u8 data);
+ u16 debug_rpair_r(int rr);
+ void debug_rpair_w(int rr, u16 data);
+
+ // address spaces
+ address_space_config m_program_config;
+ address_space_config m_data_config;
+ address_space_config m_register_config;
+ memory_access<16, 0, 0, ENDIANNESS_BIG>::cache m_cache;
+ memory_access<16, 0, 0, ENDIANNESS_BIG>::specific m_program;
+ memory_access<16, 0, 0, ENDIANNESS_BIG>::specific m_data;
+ memory_access<8, 0, 0, ENDIANNESS_BIG>::specific m_register;
+
+ // internal state
+ u16 m_pc;
+ u16 m_sspr;
+ u16 m_uspr;
+ u8 m_cicr;
+ u8 m_flagr;
+ u8 m_rpr[2];
+ u8 m_ppr;
+ u8 m_moder;
+ s32 m_icount;
+};
+
+class st90r50_device : public st9_device
+{
+public:
+ // device type constructor
+ st90r50_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+private:
+ void register_map(address_map &map) ATTR_COLD;
+};
+
+// device type declaration
+DECLARE_DEVICE_TYPE(ST90R50, st90r50_device)
+
+#endif // MAME_CPU_ST9_ST905X_H
diff --git a/src/devices/cpu/st9/st9dasm.cpp b/src/devices/cpu/st9/st9dasm.cpp
new file mode 100644
index 00000000000..dcce74300a0
--- /dev/null
+++ b/src/devices/cpu/st9/st9dasm.cpp
@@ -0,0 +1,1373 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/***************************************************************************
+
+ SGS-Thomson/STMicroelectronics ST9 Family disassembler
+
+ This architecture loosely resembles that of Zilog's Super8 and Z8, but
+ adds many 16-bit operations and indirect addressing modes. Instructions
+ listed as ALD and ALDW in opcode maps are actually mode prefixes
+ for common ALU instructions.
+
+ ST9+ extends the program space to 22 bits by using segmentation and
+ also adds several instructions to facilitate stack frame linkage.
+
+ ETRAP and ERET are listed in the ST9+ Opcode Map but are otherwise
+ undocumented. These instructions were likely reserved for special
+ debugging tools.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "st9dasm.h"
+
+st9_disassembler::st9_disassembler()
+ : util::disasm_interface()
+{
+}
+
+u32 st9_disassembler::opcode_alignment() const
+{
+ return 1;
+}
+
+u32 st9p_disassembler::interface_flags() const
+{
+ return PAGED;
+}
+
+u32 st9p_disassembler::page_address_bits() const
+{
+ return 16;
+}
+
+namespace {
+
+const char *const s_ald[16] =
+{
+ "or", "and",
+ "sbc", "adc",
+ "add", "sub",
+ "xor", nullptr,
+ "tcm", "cp",
+ "tm", nullptr,
+ nullptr, nullptr,
+ nullptr, "ld"
+};
+
+const char *const s_aldw[16] =
+{
+ "orw", "andw",
+ "sbcw", "adcw",
+ "addw", "subw",
+ "xorw", nullptr,
+ "tcmw", "cpw",
+ "tmw", nullptr,
+ nullptr, nullptr,
+ nullptr, "ldw"
+};
+
+const char *const s_unary_inst[16] =
+{
+ nullptr, nullptr,
+ "popu", "pushu",
+ "dec", "inc",
+ nullptr, "da",
+ "cpl", "clr",
+ "rol", "rlc",
+ "ror", "rrc",
+ "sra", "swap"
+};
+
+const char *const s_cc[16] =
+{
+ "f", "lt", "le", "ule", "ov", "mi", "eq", "c",
+ "", "ge", "gt", "ugt", "nov", "pl", "ne", "nc"
+};
+
+const char *const s_group_e[16] =
+{
+ "P0DR", "P1DR",
+ "P2DR", "P3DR",
+ "P4DR", "P5DR",
+ "CICR", "FLAGR",
+ "RP0R", "RP1R",
+ "PPR", "MODER",
+ "USPHR", "USPLR",
+ "SSPHR", "SSPLR"
+};
+
+} // anonymous namespace
+
+void st9_disassembler::format_dir(std::ostream &stream, u8 r) const
+{
+ if ((r & 0xf0) == 0xd0)
+ util::stream_format(stream, "r%d", r & 0x0f);
+ else if ((r & 0xf0) == 0xe0)
+ stream << s_group_e[r & 0x0f]; // R224-R239
+ else
+ util::stream_format(stream, "R%02X", r);
+}
+
+void st9_disassembler::format_dirw(std::ostream &stream, u8 rr) const
+{
+ if ((rr & 0xf0) == 0xd0)
+ util::stream_format(stream, "rr%d", rr & 0x0f);
+ else if (rr == 0xee)
+ stream << "SSPR"; // RR238
+ else if (rr == 0xec)
+ stream << "USPR"; // RR236
+ else if (rr == 0xe8)
+ stream << "RPR";
+ else
+ util::stream_format(stream, "RR%02X", rr);
+}
+
+void st9_disassembler::format_imm(std::ostream &stream, u8 n) const
+{
+ stream << '#';
+ if (n >= 0xa0)
+ stream << '0';
+ util::stream_format(stream, "%02Xh", n);
+}
+
+void st9_disassembler::format_immw(std::ostream &stream, u16 nn) const
+{
+ stream << '#';
+ if (nn >= 0xa000)
+ stream << '0';
+ util::stream_format(stream, "%04Xh", nn);
+}
+
+void st9_disassembler::format_disp(std::ostream &stream, s8 n) const
+{
+ util::stream_format(stream, "%d", n);
+}
+
+void st9_disassembler::format_dispw(std::ostream &stream, u16 nn) const
+{
+ if (nn >= 0xa000)
+ stream << '0';
+ util::stream_format(stream, "%04Xh", nn);
+}
+
+void st9_disassembler::format_label(std::ostream &stream, u16 nn) const
+{
+ if (nn >= 0xa000)
+ stream << '0';
+ util::stream_format(stream, "%04Xh", nn);
+}
+
+offs_t st9_disassembler::dasm_unknown(std::ostream &stream, u8 opc) const
+{
+ util::stream_format(stream, "%-8s", ".byte");
+ if (opc >= 0xa0)
+ stream << '0';
+ util::stream_format(stream, "%02Xh", opc);
+ return 1 | SUPPORTED;
+}
+
+offs_t st9_disassembler::dasm_06(std::ostream &stream, u8 byte1, offs_t pc, const st9_disassembler::data_buffer &opcodes) const
+{
+ const char *const aldw = s_aldw[byte1 >> 4];
+ if (aldw != nullptr)
+ {
+ util::stream_format(stream, "%-8s", aldw);
+ if (BIT(byte1, 0))
+ {
+ format_disp(stream, opcodes.r8(pc + 2));
+ util::stream_format(stream, "(rr%d)", byte1 & 0x0e);
+ stream << ',';
+ format_immw(stream, opcodes.r8(pc + 3));
+ return 5 | SUPPORTED;
+ }
+ else
+ {
+ format_dispw(stream, opcodes.r16(pc + 2));
+ util::stream_format(stream, "(rr%d)", byte1 & 0x0e);
+ stream << ',';
+ format_immw(stream, opcodes.r8(pc + 4));
+ return 6 | SUPPORTED;
+ }
+ }
+ else
+ return dasm_unknown(stream, 0x06);
+}
+
+offs_t st9_disassembler::dasm_0f(std::ostream &stream, u8 byte1, offs_t pc, const st9_disassembler::data_buffer &opcodes) const
+{
+ if (BIT(byte1, 4))
+ {
+ const u8 byte2 = opcodes.r8(pc + 2);
+ util::stream_format(stream, "%-8sr%d.%d,r%d.%s%d", "bor", byte1 & 0x0f, byte1 >> 5, byte2 & 0x0f, BIT(byte2, 4) ? "!" : "", byte2 >> 5);
+ return 3 | SUPPORTED;
+ }
+ else
+ {
+ util::stream_format(stream, "%-8sr%d.%d", "bset", byte1 & 0x0f, byte1 >> 5);
+ return 2 | SUPPORTED;
+ }
+}
+
+offs_t st9_disassembler::dasm_1f(std::ostream &stream, u8 byte1, offs_t pc, const st9_disassembler::data_buffer &opcodes) const
+{
+ if (BIT(byte1, 4))
+ {
+ const u8 byte2 = opcodes.r8(pc + 2);
+ util::stream_format(stream, "%-8sr%d.%d,r%d.%s%d", "band", byte1 & 0x0f, byte1 >> 5, byte2 & 0x0f, BIT(byte2, 4) ? "!" : "", byte2 >> 5);
+ return 3 | SUPPORTED;
+ }
+ else
+ {
+ util::stream_format(stream, "%-8sr%d.%d", "bres", byte1 & 0x0f, byte1 >> 5);
+ return 2 | SUPPORTED;
+ }
+}
+
+offs_t st9_disassembler::dasm_26(std::ostream &stream, u8 byte1, offs_t pc, const st9_disassembler::data_buffer &opcodes) const
+{
+ const char *const ald = s_ald[byte1 >> 4];
+ if (ald != nullptr)
+ {
+ util::stream_format(stream, "%-8s", ald);
+ if (BIT(byte1, 0))
+ {
+ format_disp(stream, opcodes.r8(pc + 2));
+ util::stream_format(stream, "(rr%d)", byte1 & 0x0e);
+ stream << ',';
+ format_dir(stream, opcodes.r8(pc + 3));
+ return 4 | SUPPORTED;
+ }
+ else
+ {
+ format_dispw(stream, opcodes.r16(pc + 2));
+ util::stream_format(stream, "(rr%d)", byte1 & 0x0e);
+ stream << ',';
+ format_dir(stream, opcodes.r8(pc + 4));
+ return 5 | SUPPORTED;
+ }
+ }
+ else
+ return dasm_unknown(stream, 0x26);
+}
+
+offs_t st9_disassembler::dasm_2f(std::ostream &stream, u8 byte1, offs_t pc, const st9_disassembler::data_buffer &opcodes) const
+{
+ if (!BIT(byte1, 0))
+ {
+ util::stream_format(stream, "%-8s", "sraw");
+ format_dirw(stream, byte1);
+ return 2 | SUPPORTED;
+ }
+ else if (s_ald[byte1 >> 4] != nullptr)
+ {
+ util::stream_format(stream, "%-8s", s_ald[byte1 >> 4]);
+ format_label(stream, opcodes.r16(pc + 3));
+ stream << ',';
+ format_imm(stream, opcodes.r8(pc + 2));
+ return 5 | SUPPORTED;
+ }
+ else
+ return dasm_unknown(stream, 0x2f);
+}
+
+offs_t st9_disassembler::dasm_36(std::ostream &stream, u8 byte1, offs_t pc, const st9_disassembler::data_buffer &opcodes) const
+{
+ if (!BIT(byte1, 0))
+ {
+ util::stream_format(stream, "%-8s", "rrcw");
+ format_dirw(stream, byte1);
+ return 2 | SUPPORTED;
+ }
+ else if (s_aldw[byte1 >> 4] != nullptr)
+ {
+ util::stream_format(stream, "%-8s", s_aldw[byte1 >> 4]);
+ format_label(stream, opcodes.r16(pc + 4));
+ stream << ',';
+ format_immw(stream, opcodes.r16(pc + 2));
+ return 6 | SUPPORTED;
+ }
+ else
+ return dasm_unknown(stream, 0x36);
+}
+
+offs_t st9_disassembler::dasm_3f(std::ostream &stream, offs_t pc, const st9_disassembler::data_buffer &opcodes) const
+{
+ return dasm_unknown(stream, 0x3f);
+}
+
+offs_t st9p_disassembler::dasm_3f(std::ostream &stream, offs_t pc, const st9_disassembler::data_buffer &opcodes) const
+{
+ const u8 byte1 = opcodes.r8(pc + 1);
+ if (BIT(byte1, 6))
+ {
+ util::stream_format(stream, "%-8s%02Xh,", BIT(byte1, 7) ? "jps" : "calls", byte1 & 0x3f);
+ format_label(stream, opcodes.r16(pc + 2));
+ return 4 | (BIT(byte1, 7) ? 0 : STEP_OVER) | SUPPORTED;
+ }
+ else
+ return dasm_unknown(stream, 0x3f);
+}
+
+offs_t st9_disassembler::dasm_60(std::ostream &stream, u8 byte1, u8 byte2) const
+{
+ const char *const ald = BIT(byte1, 4) ? s_ald[byte2 >> 4] : s_aldw[byte2 >> 4];
+ if (ald != nullptr)
+ {
+ util::stream_format(stream, "%-8s", ald);
+ if (BIT(byte1, 0))
+ util::stream_format(stream, "rr%d(rr%d),", (byte1 & 0xe0) >> 4, byte1 & 0x0e);
+ util::stream_format(stream, "%s%d", BIT(byte1, 4) ? "r" : "rr", byte2 & 0x0f);
+ if (!BIT(byte1, 0))
+ util::stream_format(stream, ",rr%d(rr%d)", (byte1 & 0xe0) >> 4, byte1 & 0x0e);
+ return 3 | SUPPORTED;
+ }
+ else
+ return dasm_unknown(stream, 0x60);
+}
+
+offs_t st9_disassembler::dasm_6f(std::ostream &stream, u8 byte1, offs_t pc, const st9_disassembler::data_buffer &opcodes) const
+{
+ if (BIT(byte1, 4))
+ {
+ const u8 byte2 = opcodes.r8(pc + 2);
+ util::stream_format(stream, "%-8sr%d.%d,r%d.%s%d", "bxor", byte1 & 0x0f, byte1 >> 5, byte2 & 0x0f, BIT(byte2, 4) ? "!" : "", byte2 >> 5);
+ return 3 | SUPPORTED;
+ }
+ else
+ {
+ util::stream_format(stream, "%-8sr%d.%d", "bcpl", byte1 & 0x0f, byte1 >> 5);
+ return 2 | SUPPORTED;
+ }
+}
+
+offs_t st9_disassembler::dasm_72(std::ostream &stream, u8 byte1, offs_t pc, const st9_disassembler::data_buffer &opcodes) const
+{
+ const char *const ald = s_ald[byte1 >> 4];
+ if (ald != nullptr)
+ {
+ util::stream_format(stream, "%-8s", ald);
+ if (!BIT(byte1, 0))
+ util::stream_format(stream, "(rr%d),", byte1 & 0x0e);
+ format_dir(stream, opcodes.r8(pc + 2));
+ if (BIT(byte1, 0))
+ util::stream_format(stream, ",(rr%d)", byte1 & 0x0e);
+ return 3 | SUPPORTED;
+ }
+ else
+ return dasm_unknown(stream, 0x72);
+}
+
+offs_t st9_disassembler::dasm_73(std::ostream &stream, u8 byte1, offs_t pc, const st9_disassembler::data_buffer &opcodes) const
+{
+ const char *const ald = s_ald[byte1 >> 4];
+ if (ald != nullptr && !BIT(byte1, 0))
+ {
+ util::stream_format(stream, "%-8s(", ald);
+ format_dirw(stream, opcodes.r8(pc + 2));
+ util::stream_format(stream, "),(rr%d)", byte1 & 0x0e);
+ return 3 | SUPPORTED;
+ }
+ else
+ return dasm_unknown(stream, 0x73);
+}
+
+offs_t st9p_disassembler::dasm_73(std::ostream &stream, u8 byte1, offs_t pc, const st9_disassembler::data_buffer &opcodes) const
+{
+ if ((byte1 & 0x71) == 0x41)
+ {
+ util::stream_format(stream, "%-8s(", BIT(byte1, 7) ? "jps" : "calls");
+ format_dirw(stream, opcodes.r8(pc + 2));
+ util::stream_format(stream, "),(rr%d)", byte1 & 0x0e);
+ return 3 | (BIT(byte1, 7) ? 0 : STEP_OVER) | SUPPORTED;
+ }
+ else
+ return st9_disassembler::dasm_73(stream, byte1, pc, opcodes);
+}
+
+offs_t st9_disassembler::dasm_74(std::ostream &stream, u8 byte1) const
+{
+ if (BIT(byte1, 0))
+ {
+ util::stream_format(stream, "%-8s(", "call");
+ format_dirw(stream, byte1 & 0xfe);
+ stream << ')';
+ return 2 | STEP_OVER | SUPPORTED;
+ }
+ else
+ {
+ util::stream_format(stream, "%-8s", "pushw");
+ format_dirw(stream, byte1);
+ return 2 | SUPPORTED;
+ }
+}
+
+offs_t st9_disassembler::dasm_75(std::ostream &stream, u8 byte1) const
+{
+ if (BIT(byte1, 0))
+ return dasm_unknown(stream, 0x75);
+ else
+ {
+ util::stream_format(stream, "%-8s", "popw");
+ format_dirw(stream, byte1);
+ return 2 | SUPPORTED;
+ }
+}
+
+offs_t st9p_disassembler::dasm_75(std::ostream &stream, u8 byte1) const
+{
+ if (BIT(byte1, 0))
+ {
+ util::stream_format(stream, "%-8s", "unlink");
+ format_dirw(stream, byte1 & 0xfe);
+ return 2 | SUPPORTED;
+ }
+ else
+ return st9_disassembler::dasm_75(stream, byte1);
+}
+
+offs_t st9_disassembler::dasm_7e(std::ostream &stream, u8 byte1, offs_t pc, const st9_disassembler::data_buffer &opcodes) const
+{
+ const char *const aldw = s_aldw[byte1 >> 4];
+ if (aldw != nullptr && !BIT(byte1, 0))
+ {
+ util::stream_format(stream, "%-8s", aldw);
+ format_dirw(stream, opcodes.r8(pc + 2));
+ util::stream_format(stream, ",(rr%d)", byte1 & 0x0e);
+ return 3 | SUPPORTED;
+ }
+ else
+ return dasm_unknown(stream, 0x7e);
+}
+
+offs_t st9_disassembler::dasm_7f(std::ostream &stream, u8 byte1, offs_t pc, const st9_disassembler::data_buffer &opcodes) const
+{
+ const char *const ald = s_ald[byte1 >> 4];
+ if (ald != nullptr)
+ {
+ util::stream_format(stream, "%-8s", ald);
+ if (BIT(byte1, 0))
+ {
+ format_dir(stream, opcodes.r8(pc + 3));
+ stream << ',';
+ format_disp(stream, opcodes.r8(pc + 2));
+ util::stream_format(stream, "(rr%d)", byte1 & 0x0e);
+ return 4 | SUPPORTED;
+ }
+ else
+ {
+ format_dir(stream, opcodes.r8(pc + 4));
+ stream << ',';
+ format_dispw(stream, opcodes.r16(pc + 2));
+ util::stream_format(stream, "(rr%d)", byte1 & 0x0e);
+ return 5 | SUPPORTED;
+ }
+ }
+ else
+ return dasm_unknown(stream, 0x7f);
+}
+
+offs_t st9_disassembler::dasm_86(std::ostream &stream, u8 byte1, offs_t pc, const st9_disassembler::data_buffer &opcodes) const
+{
+ const char *const aldw = s_aldw[byte1 >> 4];
+ if (aldw != nullptr)
+ {
+ util::stream_format(stream, "%-8s", aldw);
+ if (BIT(byte1, 0))
+ {
+ const u8 byte3 = opcodes.r8(pc + 3);
+ if (!BIT(byte3, 0))
+ {
+ format_dirw(stream, byte3);
+ stream << ',';
+ }
+ format_disp(stream, opcodes.r8(pc + 2));
+ util::stream_format(stream, "(rr%d)", byte1 & 0x0e);
+ if (BIT(byte3, 0))
+ {
+ stream << ',';
+ format_dirw(stream, byte3 & 0xfe);
+ }
+ return 4 | SUPPORTED;
+ }
+ else
+ {
+ const u8 byte4 = opcodes.r8(pc + 4);
+ if (!BIT(byte4, 0))
+ {
+ format_dirw(stream, byte4);
+ stream << ',';
+ }
+ format_dispw(stream, opcodes.r16(pc + 2));
+ util::stream_format(stream, "(rr%d)", byte1 & 0x0e);
+ if (BIT(byte4, 0))
+ {
+ stream << ',';
+ format_dirw(stream, byte4 & 0xfe);
+ }
+ return 5 | SUPPORTED;
+ }
+ }
+ else
+ return dasm_unknown(stream, 0x86);
+}
+
+offs_t st9_disassembler::dasm_8f(std::ostream &stream, u8 byte1, offs_t pc, const st9_disassembler::data_buffer &opcodes) const
+{
+ if (!BIT(byte1, 0))
+ {
+ util::stream_format(stream, "%-8s", "rlcw");
+ format_dirw(stream, byte1);
+ return 2 | SUPPORTED;
+ }
+ else switch (byte1)
+ {
+ case 0x01: case 0x03:
+ {
+ const u8 byte2 = opcodes.r8(pc + 2);
+ util::stream_format(stream, "%-8s", BIT(byte1, 1) ? "peau" : "pea");
+ if (BIT(byte2, 0))
+ format_dispw(stream, opcodes.r16(pc + 3));
+ else
+ format_disp(stream, opcodes.r8(pc + 3));
+ stream << '(';
+ format_dirw(stream, byte2 & 0xfe);
+ stream << ')';
+ return (BIT(byte2, 0) ? 5 : 4) | SUPPORTED;
+ }
+
+ case 0xc1: case 0xc3:
+ util::stream_format(stream, "%-8s", BIT(byte1, 1) ? "pushuw" : "pushw");
+ format_immw(stream, opcodes.r8(pc + 2));
+ return 4 | SUPPORTED;
+
+ case 0xf1: case 0xf3:
+ util::stream_format(stream, "%-8s", BIT(byte1, 1) ? "pushu" : "push");
+ format_imm(stream, opcodes.r8(pc + 2));
+ return 3 | SUPPORTED;
+
+ default:
+ return dasm_unknown(stream, 0x8f);
+ }
+}
+
+offs_t st9_disassembler::dasm_96(std::ostream &stream, u8 byte1, u8 byte2) const
+{
+ const char *const aldw = s_aldw[byte2 >> 4];
+ if (aldw != nullptr && !BIT(byte1, 0))
+ {
+ util::stream_format(stream, "%-8s(r%d),", aldw, byte2 & 0x0f);
+ format_dirw(stream, byte1);
+ return 3 | SUPPORTED;
+ }
+ else
+ return dasm_unknown(stream, 0x96);
+}
+
+offs_t st9_disassembler::dasm_a6(std::ostream &stream, u8 byte1, offs_t pc, const st9_disassembler::data_buffer &opcodes) const
+{
+ const char *const aldw = s_aldw[byte1 >> 4];
+ if (aldw != nullptr)
+ {
+ util::stream_format(stream, "%-8s", aldw);
+ format_dirw(stream, opcodes.r8(pc + 2));
+ util::stream_format(stream, ",(r%d)", byte1);
+ return 3 | SUPPORTED;
+ }
+ else
+ return dasm_unknown(stream, 0xa6);
+}
+
+offs_t st9_disassembler::dasm_b4(std::ostream &stream, u8 byte1, offs_t pc, const st9_disassembler::data_buffer &opcodes) const
+{
+ const char *const ald = s_ald[byte1 >> 4];
+ if (ald != nullptr)
+ {
+ util::stream_format(stream, "%-8s", ald);
+ if (!BIT(byte1, 0))
+ util::stream_format(stream, "(rr%d)+,", byte1 & 0x0e);
+ format_dir(stream, opcodes.r8(pc + 2));
+ if (BIT(byte1, 0))
+ util::stream_format(stream, ",(rr%d)+", byte1 & 0x0e);
+ return 3 | SUPPORTED;
+ }
+ else
+ return dasm_unknown(stream, 0xb4);
+}
+
+offs_t st9_disassembler::dasm_b6(std::ostream &stream, u8 opc, u8 byte1, offs_t pc, const st9_disassembler::data_buffer &opcodes) const
+{
+ if (BIT(byte1, 0))
+ return dasm_unknown(stream, opc);
+ else
+ {
+ util::stream_format(stream, "%-8s", BIT(opc, 0) ? "popuw" : "pushuw");
+ format_dirw(stream, byte1);
+ return 2 | SUPPORTED;
+ }
+}
+
+offs_t st9p_disassembler::dasm_b6(std::ostream &stream, u8 opc, u8 byte1, offs_t pc, const st9_disassembler::data_buffer &opcodes) const
+{
+ if (BIT(byte1, 0))
+ {
+ util::stream_format(stream, "%-8s", BIT(opc, 0) ? "unlinku" : "linku");
+ format_dirw(stream, byte1 & 0xfe);
+ if (BIT(opc, 0))
+ return 2 | SUPPORTED;
+ else
+ {
+ stream << ',';
+ format_imm(stream, opcodes.r8(pc + 2));
+ return 3 | SUPPORTED;
+ }
+ }
+ else
+ return st9_disassembler::dasm_b6(stream, opc, byte1, pc, opcodes);
+}
+
+offs_t st9_disassembler::dasm_be(std::ostream &stream, u8 byte1, offs_t pc, const st9_disassembler::data_buffer &opcodes) const
+{
+ const char *const aldw = s_aldw[byte1 >> 4];
+ if (aldw != nullptr)
+ {
+ util::stream_format(stream, "%-8s(rr%d),", aldw, byte1 & 0x0e);
+ if (BIT(byte1, 0))
+ {
+ format_dirw(stream, opcodes.r8(pc + 2));
+ return 3 | SUPPORTED;
+ }
+ else
+ {
+ format_immw(stream, opcodes.r16(pc + 2));
+ return 4 | SUPPORTED;
+ }
+ }
+ else
+ return dasm_unknown(stream, 0xbe);
+}
+
+offs_t st9_disassembler::dasm_bf(std::ostream &stream, u8 byte1, offs_t pc, const st9_disassembler::data_buffer &opcodes) const
+{
+ if (!BIT(byte1, 0))
+ {
+ util::stream_format(stream, "%-8s", "ldw");
+ format_dirw(stream, byte1);
+ stream << ',';
+ format_immw(stream, opcodes.r16(pc + 2));
+ return 4 | SUPPORTED;
+ }
+ else if (byte1 == 0x01)
+ {
+ stream << "halt";
+ return 2 | SUPPORTED;
+ }
+ else
+ return dasm_unknown(stream, 0xbf);
+}
+
+offs_t st9_disassembler::dasm_c2(std::ostream &stream, u8 opc, u8 byte1, offs_t pc, const st9_disassembler::data_buffer &opcodes) const
+{
+ const char *const ald = BIT(opc, 0) ? s_aldw[byte1 >> 4] : s_ald[byte1 >> 4];
+ if (ald != nullptr)
+ {
+ util::stream_format(stream, "%-8s", ald);
+ if (!BIT(byte1, 0))
+ util::stream_format(stream, "-(rr%d),", byte1 & 0x0e);
+ if (BIT(opc, 0))
+ format_dirw(stream, opcodes.r8(pc + 2));
+ else
+ format_dir(stream, opcodes.r8(pc + 2));
+ if (BIT(byte1, 0))
+ util::stream_format(stream, ",-(rr%d)", byte1 & 0x0e);
+ return 3 | SUPPORTED;
+ }
+ else
+ return dasm_unknown(stream, opc);
+}
+
+offs_t st9_disassembler::dasm_c4(std::ostream &stream, u8 opc, u8 byte1, offs_t pc, const st9_disassembler::data_buffer &opcodes) const
+{
+ const char *const ald = s_ald[byte1 >> 4];
+ if (ald != nullptr)
+ {
+ util::stream_format(stream, "%-8s", ald);
+ if (!BIT(opc, 0))
+ util::stream_format(stream, "r%d,", byte1 & 0x0f);
+ format_label(stream, opcodes.r16(pc + 2));
+ if (BIT(opc, 0))
+ util::stream_format(stream, ",r%d", byte1 & 0x0f);
+ return 4 | SUPPORTED;
+ }
+ else
+ return dasm_unknown(stream, opc);
+}
+
+offs_t st9_disassembler::dasm_c6(std::ostream &stream, u8 byte1, offs_t pc, const st9_disassembler::data_buffer &opcodes) const
+{
+ if (BIT(byte1, 0))
+ {
+ util::stream_format(stream, "%-8s", "ext");
+ format_dirw(stream, byte1 & 0xfe);
+ return 2 | SUPPORTED;
+ }
+ else
+ {
+ util::stream_format(stream, "%-8s", "dwjnz");
+ format_dirw(stream, byte1);
+ stream << ',';
+ format_label(stream, pc + 3 + s8(opcodes.r8(pc + 2)));
+ return 3 | STEP_COND | SUPPORTED;
+ }
+}
+
+offs_t st9_disassembler::dasm_c7(std::ostream &stream, u8 byte1, offs_t pc, const st9_disassembler::data_buffer &opcodes) const
+{
+ switch (byte1 & 0x07)
+ {
+ case 0:
+ util::stream_format(stream, "%-8s", "srp");
+ format_imm(stream, byte1 >> 3);
+ return 2 | SUPPORTED;
+
+ case 4:
+ util::stream_format(stream, "%-8s", "srp0");
+ format_imm(stream, byte1 >> 3);
+ return 2 | SUPPORTED;
+
+ case 5:
+ util::stream_format(stream, "%-8s", "srp1");
+ format_imm(stream, byte1 >> 3);
+ return 2 | SUPPORTED;
+
+ case 2: case 6:
+ util::stream_format(stream, "%-8s", "spp");
+ format_imm(stream, byte1 >> 2);
+ return 2 | SUPPORTED;
+
+ default:
+ return dasm_unknown(stream, 0xc7);
+ }
+}
+
+offs_t st9_disassembler::dasm_cf(std::ostream &stream, u8 opc, u8 byte1) const
+{
+ if (BIT(byte1, 0))
+ return dasm_unknown(stream, opc);
+ else
+ {
+ util::stream_format(stream, "%-8s", BIT(opc, 4) ? "incw" : "decw");
+ format_dirw(stream, byte1);
+ return 2 | SUPPORTED;
+ }
+}
+
+offs_t st9_disassembler::dasm_d4(std::ostream &stream, u8 byte1, offs_t pc, const st9_disassembler::data_buffer &opcodes) const
+{
+ if (BIT(byte1, 0))
+ return dasm_unknown(stream, 0xd4);
+ else
+ {
+ util::stream_format(stream, "%-8s(", "jp");
+ format_dirw(stream, byte1);
+ stream << ')';
+ return 2 | SUPPORTED;
+ }
+}
+
+offs_t st9p_disassembler::dasm_d4(std::ostream &stream, u8 byte1, offs_t pc, const st9_disassembler::data_buffer &opcodes) const
+{
+ if (BIT(byte1, 0))
+ {
+ util::stream_format(stream, "%-8s", "link");
+ format_dirw(stream, byte1 & 0xfe);
+ stream << ',';
+ format_imm(stream, opcodes.r8(pc + 2));
+ return 3 | SUPPORTED;
+ }
+ else
+ return st9_disassembler::dasm_d4(stream, byte1, pc, opcodes);
+}
+
+offs_t st9_disassembler::dasm_d5(std::ostream &stream, u8 byte1, offs_t pc, const st9_disassembler::data_buffer &opcodes) const
+{
+ const char *const aldw = s_aldw[byte1 >> 4];
+ if (aldw != nullptr)
+ {
+ util::stream_format(stream, "%-8s", aldw);
+ if (!BIT(byte1, 0))
+ util::stream_format(stream, "(rr%d)+,", byte1 & 0x0e);
+ format_dirw(stream, opcodes.r8(pc + 2));
+ if (BIT(byte1, 0))
+ util::stream_format(stream, ",(rr%d)+", byte1 & 0x0e);
+ return 3 | SUPPORTED;
+ }
+ else
+ return dasm_unknown(stream, 0xd5);
+}
+
+offs_t st9_disassembler::dasm_e2(std::ostream &stream, u8 byte1, offs_t pc, const st9_disassembler::data_buffer &opcodes) const
+{
+ const char *const aldw = s_aldw[byte1 >> 4];
+ if (aldw != nullptr)
+ {
+ util::stream_format(stream, "%-8s", aldw);
+ if (!BIT(byte1, 0))
+ util::stream_format(stream, "rr%d,", byte1 & 0x0e);
+ format_label(stream, opcodes.r16(pc + 2));
+ if (BIT(byte1, 0))
+ util::stream_format(stream, ",rr%d", byte1 & 0x0e);
+ return 4 | SUPPORTED;
+ }
+ else
+ return dasm_unknown(stream, 0xe2);
+}
+
+offs_t st9_disassembler::dasm_e6(std::ostream &stream, u8 byte1, u8 byte2) const
+{
+ const char *const ald = s_ald[byte2 >> 4];
+ if (ald != nullptr)
+ {
+ util::stream_format(stream, "%-8s(r%d),", ald, byte2 & 0x0f);
+ format_dir(stream, byte1);
+ return 3 | SUPPORTED;
+ }
+ else
+ return dasm_unknown(stream, 0xe6);
+}
+
+offs_t st9_disassembler::dasm_e7(std::ostream &stream, u8 byte1, offs_t pc, const st9_disassembler::data_buffer &opcodes) const
+{
+ const char *const ald = s_ald[byte1 >> 4];
+ if (ald != nullptr)
+ {
+ util::stream_format(stream, "%-8s", ald);
+ format_dir(stream, opcodes.r8(pc + 2));
+ util::stream_format(stream, ",(r%d)", byte1 & 0x0f);
+ return 3 | SUPPORTED;
+ }
+ else
+ return dasm_unknown(stream, 0xe7);
+}
+
+offs_t st9_disassembler::dasm_ef(std::ostream &stream, u8 byte1, offs_t pc, const st9_disassembler::data_buffer &opcodes) const
+{
+ if (BIT(byte1, 0))
+ {
+ if (byte1 == 0x01)
+ {
+ stream << "wfi";
+ return 2 | SUPPORTED;
+ }
+ else if (byte1 == 0x05)
+ {
+ stream << "eret";
+ return 2 | STEP_OUT | SUPPORTED;
+ }
+ else
+ return dasm_unknown(stream, 0xef);
+ }
+ else
+ {
+ util::stream_format(stream, "%-8s", "ldw");
+ format_dirw(stream, opcodes.r8(pc + 2));
+ stream << ',';
+ format_dirw(stream, byte1);
+ return 3 | SUPPORTED;
+ }
+}
+
+offs_t st9_disassembler::dasm_f2(std::ostream &stream, u8 byte1, offs_t pc, const st9_disassembler::data_buffer &opcodes) const
+{
+ if (BIT(byte1, 4))
+ {
+ const u8 byte2 = opcodes.r8(pc + 2);
+ util::stream_format(stream, "%-8sr%d.%d,r%d.%s%d", "bld", byte1 & 0x0f, byte1 >> 5, byte2 & 0x0f, BIT(byte2, 4) ? "!" : "", byte2 >> 5);
+ return 3 | SUPPORTED;
+ }
+ else
+ {
+ util::stream_format(stream, "%-8sr%d.%d", "btset", byte1 & 0x0f, byte1 >> 5);
+ return 2 | SUPPORTED;
+ }
+}
+
+offs_t st9_disassembler::dasm_f3(std::ostream &stream, u8 byte1, offs_t pc, const st9_disassembler::data_buffer &opcodes) const
+{
+ const char *const ald = s_ald[byte1 >> 4];
+ // Byte 1 for LD (rr),#N is documented as [XTN=F|dst,0], but actual code uses dst,1 instead
+ if (ald != nullptr /*&& !BIT(byte1, 0)*/)
+ {
+ util::stream_format(stream, "%-8s(rr%d),", ald, byte1 & 0x0e);
+ format_imm(stream, opcodes.r8(pc + 2));
+ return 3 | SUPPORTED;
+ }
+ else
+ return dasm_unknown(stream, 0xf3);
+}
+
+offs_t st9_disassembler::dasm_f6(std::ostream &stream, u8 byte1) const
+{
+ if (BIT(byte1, 0))
+ return dasm_unknown(stream, 0xf6);
+ else
+ {
+ util::stream_format(stream, "%-8s(rr%d).%d", "btset", byte1 & 0x0e, byte1 >> 5);
+ return 2 | SUPPORTED;
+ }
+}
+
+offs_t st9p_disassembler::dasm_f6(std::ostream &stream, u8 byte1) const
+{
+ if (byte1 == 0x01)
+ {
+ stream << "rets";
+ return 2 | STEP_OUT | SUPPORTED;
+ }
+ else
+ return st9_disassembler::dasm_f6(stream, byte1);
+}
+
+offs_t st9_disassembler::disassemble(std::ostream &stream, offs_t pc, const st9_disassembler::data_buffer &opcodes, const st9_disassembler::data_buffer &params)
+{
+ const u8 opc = opcodes.r8(pc);
+
+ switch (opc)
+ {
+ case 0x00:
+ stream << "ei";
+ return 1 | SUPPORTED;
+
+ case 0x01:
+ stream << "scf";
+ return 1 | SUPPORTED;
+
+ case 0x02: case 0x12: case 0x22: case 0x32: case 0x42: case 0x52: case 0x62: case 0x82: case 0x92: case 0xa2:
+ {
+ const u8 byte1 = opcodes.r8(pc + 1);
+ const char *const ald = s_ald[opc >> 4];
+ assert(ald != nullptr);
+ util::stream_format(stream, "%-8sr%d,r%d", ald, byte1 >> 4, byte1 & 0x0f);
+ return 2 | SUPPORTED;
+ }
+
+ case 0x03: case 0x13: case 0x23: case 0x33: case 0x43: case 0x53: case 0x63: case 0x83: case 0x93: case 0xa3:
+ {
+ const u8 byte1 = opcodes.r8(pc + 1);
+ const char *const ald = s_ald[opc >> 4];
+ assert(ald != nullptr);
+ util::stream_format(stream, "%-8sr%d,(r%d)", ald, byte1 >> 4, byte1 & 0x0f);
+ return 2 | SUPPORTED;
+ }
+
+ case 0x04: case 0x14: case 0x24: case 0x34: case 0x44: case 0x54: case 0x64: case 0x84: case 0x94: case 0xa4: case 0xf4:
+ {
+ const char *const ald = s_ald[opc >> 4];
+ assert(ald != nullptr);
+ util::stream_format(stream, "%-8s", ald);
+ format_dir(stream, opcodes.r8(pc + 2));
+ stream << ',';
+ format_dir(stream, opcodes.r8(pc + 1));
+ return 3 | SUPPORTED;
+ }
+
+ case 0x05: case 0x15: case 0x25: case 0x35: case 0x45: case 0x55: case 0x65: case 0x85: case 0x95: case 0xa5: case 0xf5:
+ {
+ const char *const ald = s_ald[opc >> 4];
+ assert(ald != nullptr);
+ util::stream_format(stream, "%-8s", ald);
+ format_dir(stream, opcodes.r8(pc + 1));
+ stream << ',';
+ format_imm(stream, opcodes.r8(pc + 2));
+ return 3 | SUPPORTED;
+ }
+
+ case 0x06:
+ return dasm_06(stream, opcodes.r8(pc + 1), pc, opcodes);
+
+ case 0x07: case 0x17: case 0x27: case 0x37: case 0x47: case 0x57: case 0x67: case 0x87: case 0x97: case 0xa7:
+ {
+ const u8 byte1 = opcodes.r8(pc + 1);
+ const char *const aldw = s_aldw[opc >> 4];
+ assert(aldw != nullptr);
+ util::stream_format(stream, "%-8s", aldw);
+ if (BIT(byte1, 0))
+ {
+ format_dirw(stream, byte1 & 0xfe);
+ stream << ',';
+ format_immw(stream, opcodes.r16(pc + 2));
+ return 4 | SUPPORTED;
+ }
+ else
+ {
+ format_dirw(stream, opcodes.r8(pc + 2));
+ stream << ',';
+ format_dirw(stream, byte1);
+ return 3 | SUPPORTED;
+ }
+ }
+
+ case 0x08: case 0x18: case 0x28: case 0x38: case 0x48: case 0x58: case 0x68: case 0x78:
+ case 0x88: case 0x98: case 0xa8: case 0xb8: case 0xc8: case 0xd8: case 0xe8: case 0xf8:
+ util::stream_format(stream, "%-8sr%d,", "ld", opc >> 4);
+ format_dir(stream, opcodes.r8(pc + 1));
+ return 2 | SUPPORTED;
+
+ case 0x09: case 0x19: case 0x29: case 0x39: case 0x49: case 0x59: case 0x69: case 0x79:
+ case 0x89: case 0x99: case 0xa9: case 0xb9: case 0xc9: case 0xd9: case 0xe9: case 0xf9:
+ util::stream_format(stream, "%-8s", "ld");
+ format_dir(stream, opcodes.r8(pc + 1));
+ util::stream_format(stream, ",r%d", opc >> 4);
+ return 2 | SUPPORTED;
+
+ case 0x0a: case 0x1a: case 0x2a: case 0x3a: case 0x4a: case 0x5a: case 0x6a: case 0x7a:
+ case 0x8a: case 0x9a: case 0xaa: case 0xba: case 0xca: case 0xda: case 0xea: case 0xfa:
+ util::stream_format(stream, "%-8sr%d,", "djnz", opc >> 4);
+ format_label(stream, pc + 2 + s8(opcodes.r8(pc + 1)));
+ return 2 | STEP_COND | SUPPORTED;
+
+ case 0x0b: case 0x1b: case 0x2b: case 0x3b: case 0x4b: case 0x5b: case 0x6b: case 0x7b:
+ case 0x8b: case 0x9b: case 0xab: case 0xbb: case 0xcb: case 0xdb: case 0xeb: case 0xfb:
+ util::stream_format(stream, "jr%-6s", s_cc[opc >> 4]);
+ format_label(stream, pc + 2 + s8(opcodes.r8(pc + 1)));
+ return 2 | ((opc & 0x70) != 0 ? STEP_COND : 0) | SUPPORTED;
+
+ case 0x0c: case 0x1c: case 0x2c: case 0x3c: case 0x4c: case 0x5c: case 0x6c: case 0x7c:
+ case 0x8c: case 0x9c: case 0xac: case 0xbc: case 0xcc: case 0xdc: case 0xec: case 0xfc:
+ util::stream_format(stream, "%-8sr%d,", "ld", opc >> 4);
+ format_imm(stream, opcodes.r8(pc + 1));
+ return 2 | SUPPORTED;
+
+ case 0x0d: case 0x1d: case 0x2d: case 0x3d: case 0x4d: case 0x5d: case 0x6d: case 0x7d:
+ case 0x8d: case 0x9d: case 0xad: case 0xbd: case 0xcd: case 0xdd: case 0xed: case 0xfd:
+ util::stream_format(stream, "jp%-6s", s_cc[opc >> 4]);
+ format_label(stream, opcodes.r16(pc + 1));
+ return 3 | ((opc & 0x70) != 0 ? STEP_COND : 0) | SUPPORTED;
+
+ case 0x0e: case 0x1e: case 0x2e: case 0x3e: case 0x4e: case 0x5e: case 0x6e: case 0x8e: case 0x9e: case 0xae:
+ {
+ const u8 byte1 = opcodes.r8(pc + 1);
+ const char *const aldw = s_aldw[opc >> 4];
+ assert(aldw != nullptr);
+ util::stream_format(stream, "%-8s", aldw);
+ if (BIT(byte1, 4))
+ stream << '(';
+ util::stream_format(stream, "rr%d", (byte1 & 0xe0) >> 4);
+ if (BIT(byte1, 4))
+ stream << ')';
+ stream << ',';
+ if (BIT(byte1, 0))
+ stream << '(';
+ util::stream_format(stream, "rr%d", byte1 & 0x0e);
+ if (BIT(byte1, 0))
+ stream << ')';
+ return 2 | SUPPORTED;
+ }
+
+ case 0x0f:
+ return dasm_0f(stream, opcodes.r8(pc + 1), pc, opcodes);
+
+ case 0x10:
+ stream << "di";
+ return 1 | SUPPORTED;
+
+ case 0x11:
+ stream << "rcf";
+ return 1 | SUPPORTED;
+
+ case 0x16:
+ util::stream_format(stream, "%-8s", "xch");
+ format_dir(stream, opcodes.r8(pc + 2));
+ stream << ',';
+ format_dir(stream, opcodes.r8(pc + 1));
+ return 3 | SUPPORTED;
+
+ case 0x1f:
+ return dasm_1f(stream, opcodes.r8(pc + 1), pc, opcodes);
+
+ case 0x20: case 0x30: case 0x40: case 0x50: case 0x70: case 0x80: case 0x90: case 0xa0: case 0xb0: case 0xc0: case 0xd0: case 0xe0: case 0xf0:
+ {
+ const char *const inst = s_unary_inst[opc >> 4];
+ assert(inst != nullptr);
+ util::stream_format(stream, "%-8s", inst);
+ format_dir(stream, opcodes.r8(pc + 1));
+ return 2 | SUPPORTED;
+ }
+
+ case 0x21: case 0x31: case 0x41: case 0x51: case 0x71: case 0x81: case 0x91: case 0xa1: case 0xb1: case 0xc1: case 0xd1: case 0xe1: case 0xf1:
+ {
+ const char *const inst = s_unary_inst[opc >> 4];
+ assert(inst != nullptr);
+ util::stream_format(stream, "%-8s(", inst);
+ format_dir(stream, opcodes.r8(pc + 1));
+ stream << ')';
+ return 2 | SUPPORTED;
+ }
+
+ case 0x26:
+ return dasm_26(stream, opcodes.r8(pc + 1), pc, opcodes);
+
+ case 0x2f:
+ return dasm_2f(stream, opcodes.r8(pc + 1), pc, opcodes);
+
+ case 0x36:
+ return dasm_36(stream, opcodes.r8(pc + 1), pc, opcodes);
+
+ case 0x3f:
+ return dasm_3f(stream, pc, opcodes);
+
+ case 0x46:
+ stream << "ret";
+ return 1 | STEP_OUT | SUPPORTED;
+
+ case 0x4f: case 0x5f:
+ {
+ const u8 byte1 = opcodes.r8(pc + 1);
+ util::stream_format(stream, "%-8srr%d,r%d", BIT(opc, 4) ? "div" : "mul", byte1 >> 4, byte1 & 0x0f);
+ return 2 | SUPPORTED;
+ }
+
+ case 0x56:
+ {
+ const u8 byte2 = opcodes.r8(pc + 2);
+ util::stream_format(stream, "%-8srr%d,rr%d,", "divws", byte2 >> 4, byte2 & 0x0f);
+ format_dirw(stream, opcodes.r8(pc + 1));
+ return 3 | SUPPORTED;
+ }
+
+ case 0x60:
+ return dasm_60(stream, opcodes.r8(pc + 1), opcodes.r8(pc + 2));
+
+ case 0x61:
+ stream << "ccf";
+ return 1 | SUPPORTED;
+
+ case 0x66: case 0x76:
+ util::stream_format(stream, "%-8s", BIT(opc, 4) ? "pop" : "push");
+ format_dir(stream, opcodes.r8(pc + 1));
+ return 2 | SUPPORTED;
+
+ case 0x6f:
+ return dasm_6f(stream, opcodes.r8(pc + 1), pc, opcodes);
+
+ case 0x72:
+ return dasm_72(stream, opcodes.r8(pc + 1), pc, opcodes);
+
+ case 0x73:
+ return dasm_73(stream, opcodes.r8(pc + 1), pc, opcodes);
+
+ case 0x74:
+ return dasm_74(stream, opcodes.r8(pc + 1));
+
+ case 0x75:
+ return dasm_75(stream, opcodes.r8(pc + 1));
+
+ case 0x77: case 0xf7:
+ util::stream_format(stream, "%-8s(", BIT(opc, 7) ? "push" : "pop");
+ format_dir(stream, opcodes.r8(pc + 1));
+ stream << ')';
+ return 2 | SUPPORTED;
+
+ case 0x7e:
+ return dasm_7e(stream, opcodes.r8(pc + 1), pc, opcodes);
+
+ case 0x7f:
+ return dasm_7f(stream, opcodes.r8(pc + 1), pc, opcodes);
+
+ case 0x86:
+ return dasm_86(stream, opcodes.r8(pc + 1), pc, opcodes);
+
+ case 0x8f:
+ return dasm_8f(stream, opcodes.r8(pc + 1), pc, opcodes);
+
+ case 0x96:
+ return dasm_96(stream, opcodes.r8(pc + 1), opcodes.r8(pc + 1));
+
+ case 0x9f:
+ {
+ const u8 byte1 = opcodes.r8(pc + 1);
+ util::stream_format(stream, "%-8sr%d,(rr%d),", BIT(byte1, 4) ? "cpjti" : "cpjfi", byte1 & 0x0f, (byte1 & 0xe0) >> 4);
+ format_label(stream, pc + 3 + s8(opcodes.r8(pc + 2)));
+ return 3 | STEP_COND | SUPPORTED;
+ }
+
+ case 0xa6:
+ return dasm_a6(stream, opcodes.r8(pc + 1), pc, opcodes);
+
+ case 0xaf:
+ {
+ const u8 byte1 = opcodes.r8(pc + 1);
+ util::stream_format(stream, "%-8sr%d.%d,", BIT(byte1, 4) ? "btjf" : "btjt", byte1 & 0x0f, byte1 >> 5);
+ format_label(stream, pc + 3 + s8(opcodes.r8(pc + 2)));
+ return 3 | STEP_COND | SUPPORTED;
+ }
+
+ case 0xb2: case 0xb3:
+ {
+ const u8 byte1 = opcodes.r8(pc + 1);
+ util::stream_format(stream, "%-8s", "ld");
+ if (BIT(opc, 0))
+ util::stream_format(stream, "r%d,", byte1 >> 4);
+ format_disp(stream, opcodes.r8(pc + 2));
+ util::stream_format(stream, "(r%d)", byte1 & 0x0f);
+ if (!BIT(opc, 0))
+ util::stream_format(stream, ",r%d", byte1 >> 4);
+ return 3 | SUPPORTED;
+ }
+
+ case 0xb4:
+ return dasm_b4(stream, opcodes.r8(pc + 1), pc, opcodes);
+
+ case 0xb5:
+ {
+ const u8 byte1 = opcodes.r8(pc + 1);
+ if (BIT(byte1, 0))
+ util::stream_format(stream, "%-8s(rr%d),r%d", "ld", byte1 & 0x0e, byte1 >> 4);
+ else
+ util::stream_format(stream, "%-8sr%d,(rr%d)", "ld", byte1 >> 4, byte1 & 0x0e);
+ return 2 | SUPPORTED;
+ }
+
+ case 0xb6: case 0xb7:
+ return dasm_b6(stream, opc, opcodes.r8(pc + 1), pc, opcodes);
+
+ case 0xbe:
+ return dasm_be(stream, opcodes.r8(pc + 1), pc, opcodes);
+
+ case 0xbf:
+ return dasm_bf(stream, opcodes.r8(pc + 1), pc, opcodes);
+
+ case 0xc2: case 0xc3:
+ return dasm_c2(stream, opc, opcodes.r8(pc + 1), pc, opcodes);
+
+ case 0xc4: case 0xc5:
+ return dasm_c4(stream, opc, opcodes.r8(pc + 1), pc, opcodes);
+
+ case 0xc6:
+ return dasm_c6(stream, opcodes.r8(pc + 1), pc, opcodes);
+
+ case 0xc7:
+ return dasm_c7(stream, opcodes.r8(pc + 1), pc, opcodes);
+
+ case 0xce:
+ stream << "etrap";
+ return 1 | STEP_OVER | SUPPORTED;
+
+ case 0xcf: case 0xdf:
+ return dasm_cf(stream, opc, opcodes.r8(pc + 1));
+
+ case 0xd2:
+ util::stream_format(stream, "%-8s", "call");
+ format_label(stream, opcodes.r16(pc + 1));
+ return 3 | STEP_OVER | SUPPORTED;
+
+ case 0xd3:
+ stream << "iret";
+ return 1 | STEP_OUT | SUPPORTED;
+
+ case 0xd4:
+ return dasm_d4(stream, opcodes.r8(pc + 1), pc, opcodes);
+
+ case 0xd5:
+ return dasm_d5(stream, opcodes.r8(pc + 1), pc, opcodes);
+
+ case 0xd6:
+ {
+ const u8 byte1 = opcodes.r8(pc + 1);
+ util::stream_format(stream, "ld%c%-5c(rr%d)+,(rr%d)+", "pd"[BIT(byte1, 4)], "pd"[BIT(byte1, 0)], (byte1 & 0xe0) >> 4, byte1 & 0x0e);
+ return 2 | SUPPORTED;
+ }
+
+ case 0xd7:
+ {
+ const u8 byte1 = opcodes.r8(pc + 1);
+ util::stream_format(stream, "%-8s", "ld");
+ if (BIT(byte1, 0))
+ util::stream_format(stream, "(r%d)+,(rr%d)+", byte1 >> 4, byte1 & 0x0e);
+ else
+ util::stream_format(stream, "(rr%d)+,(r%d)+", byte1 & 0x0e, byte1 >> 4);
+ return 2 | SUPPORTED;
+ }
+
+ case 0xde:
+ {
+ const u8 byte1 = opcodes.r8(pc + 1);
+ util::stream_format(stream, "%-8s", "ldw");
+ if (!BIT(byte1, 4))
+ util::stream_format(stream, "rr%d,", byte1 >> 4);
+ format_disp(stream, opcodes.r8(pc + 2));
+ util::stream_format(stream, "(r%d)", byte1 & 0x0f);
+ if (BIT(byte1, 4))
+ util::stream_format(stream, ",rr%d", (byte1 & 0xe0) >> 4);
+ return 3 | SUPPORTED;
+ }
+
+ case 0xe2:
+ return dasm_e2(stream, opcodes.r8(pc + 1), pc, opcodes);
+
+ case 0xe3:
+ {
+ const u8 byte1 = opcodes.r8(pc + 1);
+ util::stream_format(stream, "%-8s", "ldw");
+ if (BIT(byte1, 4))
+ stream << '(';
+ util::stream_format(stream, "rr%d", (byte1 & 0xe0) >> 4);
+ if (BIT(byte1, 4))
+ stream << ')';
+ stream << ',';
+ if (BIT(byte1, 0))
+ stream << '(';
+ util::stream_format(stream, "rr%d", byte1 & 0x0e);
+ if (BIT(byte1, 0))
+ stream << ')';
+ return 2 | SUPPORTED;
+ }
+
+ case 0xe4:
+ {
+ const u8 byte1 = opcodes.r8(pc + 1);
+ util::stream_format(stream, "%-8sr%d,(r%d)", "ld", byte1 >> 4, byte1 & 0x0f);
+ return 2 | SUPPORTED;
+ }
+
+ case 0xe5:
+ {
+ const u8 byte1 = opcodes.r8(pc + 1);
+ util::stream_format(stream, "%-8s(r%d),r%d", "ld", byte1 >> 4, byte1 & 0x0f);
+ return 2 | SUPPORTED;
+ }
+
+ case 0xe6:
+ return dasm_e6(stream, opcodes.r8(pc + 1), opcodes.r8(pc + 2));
+
+ case 0xe7:
+ return dasm_e7(stream, opcodes.r8(pc + 1), pc, opcodes);
+
+ case 0xee:
+ stream << "spm";
+ return 1 | SUPPORTED;
+
+ case 0xef:
+ return dasm_ef(stream, opcodes.r8(pc + 1), pc, opcodes);
+
+ case 0xf2:
+ return dasm_f2(stream, opcodes.r8(pc + 1), pc, opcodes);
+
+ case 0xf3:
+ return dasm_f3(stream, opcodes.r8(pc + 1), pc, opcodes);
+
+ case 0xf6:
+ return dasm_f6(stream, opcodes.r8(pc + 1));
+
+ case 0xfe:
+ stream << "sdm";
+ return 1 | SUPPORTED;
+
+ case 0xff:
+ stream << "nop";
+ return 1 | SUPPORTED;
+
+ default:
+ return dasm_unknown(stream, opc);
+ }
+}
diff --git a/src/devices/cpu/st9/st9dasm.h b/src/devices/cpu/st9/st9dasm.h
new file mode 100644
index 00000000000..95a7169ee98
--- /dev/null
+++ b/src/devices/cpu/st9/st9dasm.h
@@ -0,0 +1,90 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+
+#ifndef MAME_CPU_ST9_ST9DASM_H
+#define MAME_CPU_ST9_ST9DASM_H
+
+#pragma once
+
+class st9_disassembler : public util::disasm_interface
+{
+public:
+ // construction/destruction
+ st9_disassembler();
+
+protected:
+ // util::disasm_interface overrides
+ 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;
+
+ // formatting helpers
+ void format_dir(std::ostream &stream, u8 r) const;
+ void format_dirw(std::ostream &stream, u8 rr) const;
+ void format_imm(std::ostream &stream, u8 n) const;
+ void format_immw(std::ostream &stream, u16 n) const;
+ void format_disp(std::ostream &stream, s8 n) const;
+ void format_dispw(std::ostream &stream, u16 nn) const;
+ void format_label(std::ostream &stream, u16 nn) const;
+
+ // disassembly helpers
+ offs_t dasm_unknown(std::ostream &stream, u8 opc) const;
+ offs_t dasm_06(std::ostream &stream, u8 byte1, offs_t pc, const data_buffer &opcodes) const;
+ offs_t dasm_0f(std::ostream &stream, u8 byte1, offs_t pc, const data_buffer &opcodes) const;
+ offs_t dasm_1f(std::ostream &stream, u8 byte1, offs_t pc, const data_buffer &opcodes) const;
+ offs_t dasm_26(std::ostream &stream, u8 byte1, offs_t pc, const data_buffer &opcodes) const;
+ offs_t dasm_2f(std::ostream &stream, u8 byte1, offs_t pc, const data_buffer &opcodes) const;
+ offs_t dasm_36(std::ostream &stream, u8 byte1, offs_t pc, const data_buffer &opcodes) const;
+ virtual offs_t dasm_3f(std::ostream &stream, offs_t pc, const data_buffer &opcodes) const;
+ offs_t dasm_60(std::ostream &stream, u8 byte1, u8 byte2) const;
+ offs_t dasm_6f(std::ostream &stream, u8 byte1, offs_t pc, const data_buffer &opcodes) const;
+ offs_t dasm_72(std::ostream &stream, u8 byte1, offs_t pc, const data_buffer &opcodes) const;
+ virtual offs_t dasm_73(std::ostream &stream, u8 byte1, offs_t pc, const data_buffer &opcodes) const;
+ offs_t dasm_74(std::ostream &stream, u8 byte1) const;
+ virtual offs_t dasm_75(std::ostream &stream, u8 byte1) const;
+ offs_t dasm_7e(std::ostream &stream, u8 byte1, offs_t pc, const data_buffer &opcodes) const;
+ offs_t dasm_7f(std::ostream &stream, u8 byte1, offs_t pc, const data_buffer &opcodes) const;
+ offs_t dasm_86(std::ostream &stream, u8 byte1, offs_t pc, const data_buffer &opcodes) const;
+ offs_t dasm_8f(std::ostream &stream, u8 byte1, offs_t pc, const data_buffer &opcodes) const;
+ offs_t dasm_96(std::ostream &stream, u8 byte1, u8 byte2) const;
+ offs_t dasm_a6(std::ostream &stream, u8 byte1, offs_t pc, const data_buffer &opcodes) const;
+ offs_t dasm_b4(std::ostream &stream, u8 byte1, offs_t pc, const data_buffer &opcodes) const;
+ virtual offs_t dasm_b6(std::ostream &stream, u8 opc, u8 byte1, offs_t pc, const data_buffer &opcodes) const;
+ offs_t dasm_be(std::ostream &stream, u8 byte1, offs_t pc, const data_buffer &opcodes) const;
+ offs_t dasm_bf(std::ostream &stream, u8 byte1, offs_t pc, const data_buffer &opcodes) const;
+ offs_t dasm_c2(std::ostream &stream, u8 opc, u8 byte1, offs_t pc, const data_buffer &opcodes) const;
+ offs_t dasm_c4(std::ostream &stream, u8 opc, u8 byte1, offs_t pc, const data_buffer &opcodes) const;
+ offs_t dasm_c6(std::ostream &stream, u8 byte1, offs_t pc, const data_buffer &opcodes) const;
+ offs_t dasm_c7(std::ostream &stream, u8 byte1, offs_t pc, const data_buffer &opcodes) const;
+ offs_t dasm_cf(std::ostream &stream, u8 opc, u8 byte1) const;
+ virtual offs_t dasm_d4(std::ostream &stream, u8 byte1, offs_t pc, const data_buffer &opcodes) const;
+ offs_t dasm_d5(std::ostream &stream, u8 byte1, offs_t pc, const data_buffer &opcodes) const;
+ offs_t dasm_e2(std::ostream &stream, u8 byte1, offs_t pc, const data_buffer &opcodes) const;
+ offs_t dasm_e6(std::ostream &stream, u8 byte1, u8 byte2) const;
+ offs_t dasm_e7(std::ostream &stream, u8 byte1, offs_t pc, const data_buffer &opcodes) const;
+ offs_t dasm_ef(std::ostream &stream, u8 byte1, offs_t pc, const data_buffer &opcodes) const;
+ offs_t dasm_f2(std::ostream &stream, u8 byte1, offs_t pc, const data_buffer &opcodes) const;
+ offs_t dasm_f3(std::ostream &stream, u8 byte1, offs_t pc, const data_buffer &opcodes) const;
+ virtual offs_t dasm_f6(std::ostream &stream, u8 byte1) const;
+};
+
+class st9p_disassembler : public st9_disassembler
+{
+public:
+ // construction/destruction
+ using st9_disassembler::st9_disassembler;
+
+protected:
+ // util::disasm_interface overrides
+ virtual u32 interface_flags() const override;
+ virtual u32 page_address_bits() const override;
+
+ // st9_disassembler overrides
+ virtual offs_t dasm_3f(std::ostream &stream, offs_t pc, const data_buffer &opcodes) const override;
+ virtual offs_t dasm_73(std::ostream &stream, u8 byte1, offs_t pc, const data_buffer &opcodes) const override;
+ virtual offs_t dasm_75(std::ostream &stream, u8 byte1) const override;
+ virtual offs_t dasm_b6(std::ostream &stream, u8 opc, u8 byte1, offs_t pc, const data_buffer &opcodes) const override;
+ virtual offs_t dasm_d4(std::ostream &stream, u8 byte1, offs_t pc, const data_buffer &opcodes) const override;
+ virtual offs_t dasm_f6(std::ostream &stream, u8 byte1) const override;
+};
+
+#endif // MAME_CPU_ST9_ST9DASM_H