summaryrefslogtreecommitdiffstatshomepage
path: root/src
diff options
context:
space:
mode:
author mamehaze <140764005+mamehaze@users.noreply.github.com>2024-06-29 14:59:13 +0100
committer GitHub <noreply@github.com>2024-06-29 09:59:13 -0400
commit9d66f71e34ed20f4e356fd31a12d68350c79a010 (patch)
tree3327dc6184852b823c9f12d417c1a4f774746e76 /src
parent48271af68061df7ce5715df59bc404cfdc350c32 (diff)
cpu/xa: New Philips XA disassembler (#12504)
* show size types on these for consistency with IDA output (manual indicates they're usually optional, but does show this syntax in places) * use the real CPU type (with internal map for internal ROM space) rather than 'XA' directly. --------- Co-authored-by: David Haywood <hazemamewip@hotmail.com>
Diffstat (limited to 'src')
-rw-r--r--src/devices/cpu/xa/xa.cpp96
-rw-r--r--src/devices/cpu/xa/xa.h53
-rw-r--r--src/devices/cpu/xa/xadasm.cpp1904
-rw-r--r--src/devices/cpu/xa/xadasm.h121
-rw-r--r--src/mame/igs/igs_fear.cpp9
-rw-r--r--src/mame/igs/igs_m027.cpp26
-rw-r--r--src/tools/unidasm.cpp2
7 files changed, 2203 insertions, 8 deletions
diff --git a/src/devices/cpu/xa/xa.cpp b/src/devices/cpu/xa/xa.cpp
new file mode 100644
index 00000000000..ab1ccf34dfb
--- /dev/null
+++ b/src/devices/cpu/xa/xa.cpp
@@ -0,0 +1,96 @@
+// license:BSD-3-Clause
+// copyright-holders:David Haywood
+
+/*
+ While advertised as a type of 80c51 (and even referred to as such by the test mode in some IGS titles)
+ this is a distinct architecture. The opcode set does extend on an 80c51, and tools were provided to
+ help convert 80c51 sources to run on the XA architecture, but the encoding is entirely different and
+ there is no binary compatibility.
+
+ https://www.ceibo.com/eng/datasheets/Philips-XA-User-Guide.pdf
+*/
+
+#include "emu.h"
+#include "xa.h"
+#include "xadasm.h"
+
+DEFINE_DEVICE_TYPE(XA, xa_cpu_device, "xa", "Philips 80c51 XA")
+DEFINE_DEVICE_TYPE(MX10EXA, mx10exa_cpu_device, "mx10exa", "Philips MX10EXA")
+
+
+
+
+xa_cpu_device::xa_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, address_map_constructor prg_map)
+ : cpu_device(mconfig, type, tag, owner, clock)
+ , m_program_config("data", ENDIANNESS_LITTLE, 16, 24, 0, prg_map)
+ , m_pc(0)
+ , m_program(nullptr)
+ , m_icount(0)
+{
+}
+
+xa_cpu_device::xa_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : xa_cpu_device(mconfig, XA, tag, owner, clock, address_map_constructor(FUNC(xa_cpu_device::internal_map), this))
+{
+}
+
+
+mx10exa_cpu_device::mx10exa_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : xa_cpu_device(mconfig, MX10EXA, tag, owner, clock, address_map_constructor(FUNC(mx10exa_cpu_device::mx10exa_internal_map), this))
+{
+}
+
+std::unique_ptr<util::disasm_interface> xa_cpu_device::create_disassembler()
+{
+ return std::make_unique<xa_dasm>();
+}
+
+/*****************************************************************************/
+
+void xa_cpu_device::internal_map(address_map &map)
+{
+}
+
+void mx10exa_cpu_device::mx10exa_internal_map(address_map &map)
+{
+ map(0x000000, 0x00ffff).rom();
+}
+
+
+device_memory_interface::space_config_vector xa_cpu_device::memory_space_config() const
+{
+ return space_config_vector {
+ std::make_pair(AS_PROGRAM, &m_program_config)
+ };
+}
+
+
+/*****************************************************************************/
+
+void xa_cpu_device::device_start()
+{
+ m_program = &space(AS_PROGRAM);
+
+ state_add(STATE_GENPC, "GENPC", m_pc).formatstr("%08X");
+ state_add(STATE_GENPCBASE, "CURPC", m_pc).callexport().noshow();
+
+ set_icountptr(m_icount);
+}
+
+void xa_cpu_device::device_reset()
+{
+ // temp, as there is code here on superkds
+ m_pc = m_program->read_word(2);
+}
+
+/*****************************************************************************/
+
+void xa_cpu_device::execute_run()
+{
+ while (m_icount > 0)
+ {
+ debugger_instruction_hook(m_pc);
+ m_pc++;
+ m_icount--;
+ }
+}
diff --git a/src/devices/cpu/xa/xa.h b/src/devices/cpu/xa/xa.h
new file mode 100644
index 00000000000..983fff36724
--- /dev/null
+++ b/src/devices/cpu/xa/xa.h
@@ -0,0 +1,53 @@
+// license:BSD-3-Clause
+// copyright-holders:David Haywood
+
+#ifndef MAME_CPU_XA_XA_H
+#define MAME_CPU_XA_XA_H
+
+#pragma once
+
+class xa_cpu_device : public cpu_device
+{
+public:
+ xa_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ xa_cpu_device(const machine_config& mconfig, device_type type, const char* tag, device_t* owner, uint32_t clock, address_map_constructor prg_map);
+
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ virtual uint32_t execute_min_cycles() const noexcept override { return 1; }
+ virtual uint32_t execute_max_cycles() const noexcept override { return 5; }
+ virtual uint32_t execute_input_lines() const noexcept override { return 0; }
+ virtual void execute_run() override;
+
+ virtual space_config_vector memory_space_config() const override;
+
+ virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
+
+private:
+ void internal_map(address_map &map);
+
+ address_space_config m_program_config;
+
+ uint32_t m_pc;
+
+ address_space *m_program;
+ int m_icount;
+};
+
+class mx10exa_cpu_device : public xa_cpu_device
+{
+public:
+ mx10exa_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+private:
+ void mx10exa_internal_map(address_map &map);
+};
+
+
+DECLARE_DEVICE_TYPE(XA, xa_cpu_device)
+DECLARE_DEVICE_TYPE(MX10EXA, mx10exa_cpu_device)
+
+#endif // MAME_CPU_XA_XA_H
diff --git a/src/devices/cpu/xa/xadasm.cpp b/src/devices/cpu/xa/xadasm.cpp
new file mode 100644
index 00000000000..c8eaf2d5e91
--- /dev/null
+++ b/src/devices/cpu/xa/xadasm.cpp
@@ -0,0 +1,1904 @@
+// license:BSD-3-Clause
+// copyright-holders:David Haywood
+
+#include "emu.h"
+#include "xadasm.h"
+
+const xa_dasm::op_func xa_dasm::s_instruction[256] =
+{
+// group 0
+&xa_dasm::d_nop, &xa_dasm::d_add, &xa_dasm::d_add, &xa_dasm::d_add, &xa_dasm::d_add, &xa_dasm::d_add, &xa_dasm::d_add, &xa_dasm::d_push_rlist,
+&xa_dasm::d_bitgroup, &xa_dasm::d_add, &xa_dasm::d_add, &xa_dasm::d_add, &xa_dasm::d_add, &xa_dasm::d_add, &xa_dasm::d_add, &xa_dasm::d_push_rlist,
+// group 1
+&xa_dasm::d_illegal, &xa_dasm::d_addc, &xa_dasm::d_addc, &xa_dasm::d_addc, &xa_dasm::d_addc, &xa_dasm::d_addc, &xa_dasm::d_addc, &xa_dasm::d_pushu_rlist,
+&xa_dasm::d_illegal, &xa_dasm::d_addc, &xa_dasm::d_addc, &xa_dasm::d_addc, &xa_dasm::d_addc, &xa_dasm::d_addc, &xa_dasm::d_addc, &xa_dasm::d_pushu_rlist,
+// group 2
+&xa_dasm::d_illegal, &xa_dasm::d_sub, &xa_dasm::d_sub, &xa_dasm::d_sub, &xa_dasm::d_sub, &xa_dasm::d_sub, &xa_dasm::d_sub, &xa_dasm::d_pop_rlist,
+&xa_dasm::d_illegal, &xa_dasm::d_sub, &xa_dasm::d_sub, &xa_dasm::d_sub, &xa_dasm::d_sub, &xa_dasm::d_sub, &xa_dasm::d_sub, &xa_dasm::d_pop_rlist,
+// group 3
+&xa_dasm::d_illegal, &xa_dasm::d_subb, &xa_dasm::d_subb, &xa_dasm::d_subb, &xa_dasm::d_subb, &xa_dasm::d_subb, &xa_dasm::d_subb, &xa_dasm::d_popu_rlist,
+&xa_dasm::d_illegal, &xa_dasm::d_subb, &xa_dasm::d_subb, &xa_dasm::d_subb, &xa_dasm::d_subb, &xa_dasm::d_subb, &xa_dasm::d_subb, &xa_dasm::d_popu_rlist,
+// group 4
+&xa_dasm::d_lea_offset8, &xa_dasm::d_cmp, &xa_dasm::d_cmp, &xa_dasm::d_cmp, &xa_dasm::d_cmp, &xa_dasm::d_cmp, &xa_dasm::d_cmp, &xa_dasm::d_push_rlist,
+&xa_dasm::d_lea_offset16, &xa_dasm::d_cmp, &xa_dasm::d_cmp, &xa_dasm::d_cmp, &xa_dasm::d_cmp, &xa_dasm::d_cmp, &xa_dasm::d_cmp, &xa_dasm::d_push_rlist,
+// group 5
+&xa_dasm::d_xch_type1, &xa_dasm::d_and, &xa_dasm::d_and, &xa_dasm::d_and, &xa_dasm::d_and, &xa_dasm::d_and, &xa_dasm::d_and, &xa_dasm::d_pushu_rlist,
+&xa_dasm::d_xch_type1, &xa_dasm::d_and, &xa_dasm::d_and, &xa_dasm::d_and, &xa_dasm::d_and, &xa_dasm::d_and, &xa_dasm::d_and, &xa_dasm::d_pushu_rlist,
+// group 6
+&xa_dasm::d_xch_type2, &xa_dasm::d_or, &xa_dasm::d_or, &xa_dasm::d_or, &xa_dasm::d_or, &xa_dasm::d_or, &xa_dasm::d_or, &xa_dasm::d_pop_rlist,
+&xa_dasm::d_xch_type2, &xa_dasm::d_or, &xa_dasm::d_or, &xa_dasm::d_or, &xa_dasm::d_or, &xa_dasm::d_or, &xa_dasm::d_or, &xa_dasm::d_pop_rlist,
+// group 7
+&xa_dasm::d_illegal, &xa_dasm::d_xor, &xa_dasm::d_xor, &xa_dasm::d_xor, &xa_dasm::d_xor, &xa_dasm::d_xor, &xa_dasm::d_xor, &xa_dasm::d_popu_rlist,
+&xa_dasm::d_illegal, &xa_dasm::d_xor, &xa_dasm::d_xor, &xa_dasm::d_xor, &xa_dasm::d_xor, &xa_dasm::d_xor, &xa_dasm::d_xor, &xa_dasm::d_popu_rlist,
+// group 8
+&xa_dasm::d_movc_rd_rsinc, &xa_dasm::d_mov, &xa_dasm::d_mov, &xa_dasm::d_mov, &xa_dasm::d_mov, &xa_dasm::d_mov, &xa_dasm::d_mov, &xa_dasm::d_pushpop_djnz_subgroup,
+&xa_dasm::d_movc_rd_rsinc, &xa_dasm::d_mov, &xa_dasm::d_mov, &xa_dasm::d_mov, &xa_dasm::d_mov, &xa_dasm::d_mov, &xa_dasm::d_mov, &xa_dasm::d_pushpop_djnz_subgroup,
+// group 9
+&xa_dasm::d_g9_subgroup, &xa_dasm::d_alu, &xa_dasm::d_alu, &xa_dasm::d_alu, &xa_dasm::d_alu, &xa_dasm::d_alu, &xa_dasm::d_alu, &xa_dasm::d_jb_mov_subgroup,
+&xa_dasm::d_g9_subgroup, &xa_dasm::d_alu, &xa_dasm::d_alu, &xa_dasm::d_alu, &xa_dasm::d_alu, &xa_dasm::d_alu, &xa_dasm::d_alu, &xa_dasm::d_jb_mov_subgroup,
+// group a
+&xa_dasm::d_movdir, &xa_dasm::d_adds, &xa_dasm::d_adds, &xa_dasm::d_adds, &xa_dasm::d_adds, &xa_dasm::d_adds, &xa_dasm::d_adds, &xa_dasm::d_movx_subgroup,
+&xa_dasm::d_movdir, &xa_dasm::d_adds, &xa_dasm::d_adds, &xa_dasm::d_adds, &xa_dasm::d_adds, &xa_dasm::d_adds, &xa_dasm::d_adds, &xa_dasm::d_movx_subgroup,
+// group b
+&xa_dasm::d_rr, &xa_dasm::d_movs, &xa_dasm::d_movs, &xa_dasm::d_movs, &xa_dasm::d_movs, &xa_dasm::d_movs, &xa_dasm::d_movs, &xa_dasm::d_rrc,
+&xa_dasm::d_rr, &xa_dasm::d_movs, &xa_dasm::d_movs, &xa_dasm::d_movs, &xa_dasm::d_movs, &xa_dasm::d_movs, &xa_dasm::d_movs, &xa_dasm::d_rrc,
+// group c
+&xa_dasm::d_lsr_fc, &xa_dasm::d_asl_c, &xa_dasm::d_asr_c, &xa_dasm::d_norm, &xa_dasm::d_lsr_fc, &xa_dasm::d_asl_c, &xa_dasm::d_asr_c, &xa_dasm::d_norm,
+&xa_dasm::d_lsr_fc, &xa_dasm::d_asl_c, &xa_dasm::d_asr_c, &xa_dasm::d_norm, &xa_dasm::d_lsr_fc, &xa_dasm::d_asl_c, &xa_dasm::d_asr_c, &xa_dasm::d_norm,
+// group d
+&xa_dasm::d_lsr_fj, &xa_dasm::d_asl_j, &xa_dasm::d_asr_j, &xa_dasm::d_rl, &xa_dasm::d_lsr_fj, &xa_dasm::d_asl_j, &xa_dasm::d_asr_j, &xa_dasm::d_rlc,
+&xa_dasm::d_lsr_fj, &xa_dasm::d_asl_j, &xa_dasm::d_asr_j, &xa_dasm::d_rl, &xa_dasm::d_lsr_fj, &xa_dasm::d_asl_j, &xa_dasm::d_asr_j, &xa_dasm::d_rlc,
+// group e
+&xa_dasm::d_mulu_b, &xa_dasm::d_divu_b, &xa_dasm::d_djnz_cjne, &xa_dasm::d_cjne_d8, &xa_dasm::d_mulu_w, &xa_dasm::d_divu_w, &xa_dasm::d_mul_w, &xa_dasm::d_div_w,
+&xa_dasm::d_div_data8, &xa_dasm::d_div_d16,&xa_dasm::d_djnz_cjne, &xa_dasm::d_cjne_d16, &xa_dasm::d_jz_rel8,&xa_dasm::d_divu_d, &xa_dasm::d_jnz_rel8, &xa_dasm::d_div_d,
+// group f
+&xa_dasm::d_branch, &xa_dasm::d_branch, &xa_dasm::d_branch, &xa_dasm::d_branch, &xa_dasm::d_branch, &xa_dasm::d_branch, &xa_dasm::d_branch, &xa_dasm::d_branch,
+&xa_dasm::d_branch, &xa_dasm::d_branch, &xa_dasm::d_branch, &xa_dasm::d_branch, &xa_dasm::d_branch, &xa_dasm::d_branch, &xa_dasm::d_branch, &xa_dasm::d_bkpt,
+};
+
+// SFR names
+const xa_dasm::mem_info xa_dasm::default_names[] = {
+ // the following are bit addressable
+ { 0x400, "PSWL" },
+ { 0x401, "PSWH" },
+ { 0x402, "PSW51" },
+ { 0x403, "SSEL" },
+ { 0x404, "PCON" },
+ { 0x410, "TCON" },
+ { 0x411, "TSTAT" },
+ { 0x418, "T2CON" },
+ { 0x419, "T2MOD" },
+ { 0x41F, "WDCON" },
+ { 0x420, "S0CON" },
+ { 0x421, "S0STAT" },
+ { 0x424, "S1CON" },
+ { 0x425, "S1STAT" },
+ { 0x426, "IEL" },
+ { 0x427, "IEH" },
+ { 0x42A, "SWR" },
+ { 0x430, "P0" },
+ { 0x431, "P1" },
+ { 0x432, "P2" },
+ { 0x433, "P3" },
+ { 0x440, "SCR" },
+ { 0x441, "DS" },
+ { 0x442, "ES" },
+ { 0x443, "CS" },
+ { 0x450, "TL0" },
+ { 0x451, "TH0" },
+ { 0x452, "TL1" },
+ { 0x453, "TH1" },
+ { 0x454, "RTL0" },
+ { 0x455, "RTH0" },
+ { 0x456, "RTL1" },
+ { 0x457, "RTH1" },
+ { 0x458, "TL2" },
+ { 0x459, "TH2" },
+ { 0x45A, "T2CAPL" },
+ { 0x45B, "T2CAPH" },
+ { 0x45C, "TMOD" },
+ { 0x45D, "WFEED1" },
+ { 0x45E, "WFEED2" },
+ { 0x45F, "WDL" },
+ { 0x460, "S0BUF" },
+ { 0x461, "S0ADDR" },
+ { 0x462, "S0ADEN" },
+ { 0x464, "S1BUF" },
+ { 0x465, "S1ADDR" },
+ { 0x466, "S1ADEN" },
+ { 0x468, "BTRL" },
+ { 0x469, "BTRH" },
+ { 0x46A, "BCR" },
+ { 0x470, "P0CFGA" },
+ { 0x471, "P1CFGA" },
+ { 0x472, "P2CFGA" },
+ { 0x473, "P3CFGA" },
+ { 0x47A, "SWE" },
+ { 0x4A0, "IPA0" },
+ { 0x4A1, "IPA1" },
+ { 0x4A2, "IPA2" },
+ { 0x4A3, "IPA3" },
+ { 0x4A4, "IPA4" },
+ { 0x4A5, "IPA5" },
+ { 0x4F0, "P0CFGB" },
+ { 0x4F1, "P1CFGB" },
+ { 0x4F2, "P2CFGB" },
+ { 0x4F3, "P3CFGB" },
+ { -1 }
+};
+
+void xa_dasm::add_names(const mem_info *info)
+{
+ for(unsigned int i=0; info[i].addr >= 0; i++)
+ m_names[info[i].addr] = info[i].name;
+}
+
+std::string xa_dasm::get_data_address(u16 arg) const
+{
+ auto i = m_names.find(arg);
+ if (i == m_names.end())
+ return util::string_format("unk_SFR_%03X", arg);
+ else
+ return i->second;
+}
+
+std::string xa_dasm::get_bittext(int bit)
+{
+ int position = bit & 7;
+
+ if (bit < 0x100)
+ {
+ int reg = ((bit & 0x1ff) >> 3);
+
+ if (reg < 16)
+ return util::string_format("%s.%d", m_regnames8[reg], position);
+ else
+ return util::string_format("ill_REG_%02x.%d", reg, position);
+ }
+ else if (bit < 0x200)
+ {
+ int addr = ((bit & 0x1ff) >> 3) + 0x20;
+ return util::string_format("$%02x.%d", addr, position);
+ }
+
+ int sfr = ((bit & 0x1ff) >> 3) + 0x400;
+ return util::string_format("%s.%d", get_data_address(sfr), position);
+}
+
+std::string xa_dasm::get_directtext(int direct)
+{
+ if (direct < 0x400)
+ {
+ return util::string_format("$%03x", direct);
+ }
+
+ return util::string_format("%s", get_data_address(direct));
+}
+
+int xa_dasm::d_illegal(XA_DASM_PARAMS)
+{
+ util::stream_format(stream, "illegal");
+ return 1;
+}
+
+int xa_dasm::handle_shift(XA_DASM_PARAMS, int shift_type)
+{
+ int size = op & 0x0c;
+ const u8 op2 = opcodes.r8(pc++);
+ u8 data, rd;
+ if (size == 0x0c)
+ {
+ data = op2 & 0x1f;
+ rd = (op2 & 0xe0) >> 4;
+ }
+ else
+ {
+ data = op2 & 0x0f;
+ rd = (op2 & 0xf0) >> 4;
+ }
+
+ if (size == 0x00)
+ {
+ util::stream_format(stream, "%s%s %s, %d", m_shifts[shift_type], m_dwparamsizes[size >> 2], m_regnames8[rd], data);
+ }
+ else
+ {
+ util::stream_format(stream, "%s%s %s, %d", m_shifts[shift_type], m_dwparamsizes[size >> 2], m_regnames16[rd], data);
+ }
+
+ return 2;
+}
+
+
+int xa_dasm::handle_alu_type0(XA_DASM_PARAMS, int alu_op)
+{
+ const int size = op & 0x08;
+ const u8 op2 = opcodes.r8(pc++);
+ const char** regnames = size ? m_regnames16 : m_regnames8;
+
+ switch (op & 0x07)
+ {
+ case 0x01:
+ {
+ const u8 rs = (op2 & 0x0f);
+ const u8 rd = (op2 & 0xf0) >> 4;
+ util::stream_format(stream, "%s%s %s, %s", m_aluops[alu_op], size ? ".w" : ".b", regnames[rd], regnames[rs] );
+ return 2;
+ }
+
+ case 0x02:
+ {
+ const int optype = op2 & 0x08;
+ if (!optype)
+ {
+ const u8 rs = (op2 & 0x07);
+ const u8 rd = (op2 & 0xf0) >> 4;
+ util::stream_format(stream, "%s%s %s, [%s]", m_aluops[alu_op], size ? ".w" : ".b", regnames[rd], m_regnames16[rs] );
+ }
+ else
+ {
+ const u8 rd = (op2 & 0x07);
+ const u8 rs = (op2 & 0xf0) >> 4;
+ util::stream_format(stream, "%s%s [%s], %s", m_aluops[alu_op], size ? ".w" : ".b", m_regnames16[rd], regnames[rs] );
+ }
+ return 2;
+ }
+
+ case 0x03:
+ {
+ const int optype = op2 & 0x08;
+ if (!optype)
+ {
+ const u8 rs = (op2 & 0x07);
+ const u8 rd = (op2 & 0xf0) >> 4;
+ util::stream_format(stream, "%s%s %s, [%s+]", m_aluops[alu_op], size ? ".w" : ".b", regnames[rd], m_regnames16[rs] );
+ }
+ else
+ {
+ const u8 rd = (op2 & 0x07);
+ const u8 rs = (op2 & 0xf0) >> 4;
+ util::stream_format(stream, "%s%s [%s+], %s", m_aluops[alu_op], size ? ".w" : ".b", m_regnames16[rd], regnames[rs] );
+ }
+ return 2;
+ }
+
+ case 0x04:
+ {
+ const int optype = op2 & 0x08;
+ const u8 op3 = opcodes.r8(pc++);
+ if (!optype)
+ {
+ const u8 rs = (op2 & 0x07);
+ const u8 rd = (op2 & 0xf0) >> 4;
+ util::stream_format(stream, "%s%s %s, [%s+#$%02x]", m_aluops[alu_op], size ? ".w" : ".b", regnames[rd], m_regnames16[rs], op3 );
+ }
+ else
+ {
+ const u8 rd = (op2 & 0x07);
+ const u8 rs = (op2 & 0xf0) >> 4;
+ util::stream_format(stream, "%s%s [%s+#$%02x], %s", m_aluops[alu_op], size ? ".w" : ".b", m_regnames16[rd], op3, regnames[rs] );
+ }
+ return 3;
+ }
+
+ case 0x05:
+ {
+ const int optype = op2 & 0x08;
+ const u8 op3 = opcodes.r8(pc++);
+ const u8 op4 = opcodes.r8(pc++);
+ const int offset16 = (op3 << 8) | op4;
+ if (!optype)
+ {
+ const u8 rs = (op2 & 0x07);
+ const u8 rd = (op2 & 0xf0) >> 4;
+ util::stream_format(stream, "%s%s %s, [%s+#$%04x]", m_aluops[alu_op], size ? ".w" : ".b", regnames[rd], m_regnames16[rs], offset16 );
+ }
+ else
+ {
+ const u8 rd = (op2 & 0x07);
+ const u8 rs = (op2 & 0xf0) >> 4;
+ util::stream_format(stream, "%s%s [%s+#$%04x], %s", m_aluops[alu_op], size ? ".w" : ".b", m_regnames16[rd], offset16, regnames[rs] );
+ }
+ return 4;
+ }
+
+ case 0x06:
+ {
+ const int optype = op2 & 0x08;
+ const u8 op3 = opcodes.r8(pc++);
+ const u16 direct = ((op2 & 0x07) << 8) | op3;
+ if (!optype)
+ {
+ const u8 rd = (op2 & 0xf0) >> 4;
+ util::stream_format(stream, "%s%s %s, %s", m_aluops[alu_op], size ? ".w" : ".b", regnames[rd], get_directtext(direct) );
+ }
+ else
+ {
+ const u8 rs = (op2 & 0xf0) >> 4;
+ util::stream_format(stream, "%s%s %s, %s", m_aluops[alu_op], size ? ".w" : ".b", get_directtext(direct), regnames[rs] );
+ }
+ return 3;
+ }
+
+ }
+
+ return 1;
+}
+
+
+
+int xa_dasm::handle_alu_type1(XA_DASM_PARAMS, uint8_t op2)
+{
+ int alu_op = op2 & 0x0f;
+ switch (op & 0x0f)
+ {
+ case 0x01:
+ {
+ const u8 op3 = opcodes.r8(pc++);
+ const u8 rd = (op2 & 0xf0) >> 4;
+ util::stream_format(stream, "%s.b %s, #$%02x", m_aluops[alu_op], m_regnames8[rd], op3 );
+ return 3;
+ }
+
+ case 0x02:
+ {
+ const u8 op3 = opcodes.r8(pc++);
+ const u8 rd = (op2 & 0xf0) >> 4;
+ util::stream_format(stream, "%s.b [%s], #$%02x", m_aluops[alu_op], m_regnames16[rd], op3 );
+ return 3;
+ }
+
+ case 0x03:
+ {
+ const u8 op3 = opcodes.r8(pc++);
+ const u8 rd = (op2 & 0xf0) >> 4;
+ util::stream_format(stream, "%s.b [%s+], #$%02x", m_aluops[alu_op], m_regnames16[rd], op3 );
+ return 3;
+ }
+
+ case 0x04:
+ {
+ const u8 op3 = opcodes.r8(pc++);
+ const u8 op4 = opcodes.r8(pc++);
+ const u8 rd = (op2 & 0xf0) >> 4;
+ util::stream_format(stream, "%s.b [%s+#$%02x], #$%02x", m_aluops[alu_op], m_regnames16[rd], op3, op4 );
+ return 4;
+ }
+
+ case 0x05:
+ {
+ const u8 op3 = opcodes.r8(pc++);
+ const u8 op4 = opcodes.r8(pc++);
+ const u8 op5 = opcodes.r8(pc++);
+ const u8 rd = (op2 & 0xf0) >> 4;
+ const u16 offset = (op3 << 8) | op4;
+ util::stream_format(stream, "%s.b [%s+#$%04x], #$%02d", m_aluops[alu_op], m_regnames16[rd], offset, op5 );
+ return 5;
+ }
+
+ case 0x06:
+ {
+ const u8 op3 = opcodes.r8(pc++);
+ const u8 op4 = opcodes.r8(pc++);
+ const u16 direct = ((op2 & 0xf0) << 4) | op3;
+ util::stream_format(stream, "%s.b %s, #$%02x", m_aluops[alu_op], get_directtext(direct), op4 );
+ return 4;
+ }
+
+ case 0x09:
+ {
+ const u8 op3 = opcodes.r8(pc++);
+ const u8 op4 = opcodes.r8(pc++);
+ const u8 rd = (op2 & 0xf0) >> 4;
+ const u16 data = (op3 << 8) | op4;
+ util::stream_format(stream, "%s.w %s, #$%04x", m_aluops[alu_op], m_regnames16[rd], data );
+ return 4;
+ }
+
+ case 0x0a:
+ {
+ const u8 op3 = opcodes.r8(pc++);
+ const u8 op4 = opcodes.r8(pc++);
+ const u8 rd = (op2 & 0xf0) >> 4;
+ const u16 data = (op3 << 8) | op4;
+ util::stream_format(stream, "%s.w [%s], #$%04x", m_aluops[alu_op], m_regnames16[rd], data );
+ return 4;
+ }
+
+ case 0x0b:
+ {
+ const u8 op3 = opcodes.r8(pc++);
+ const u8 op4 = opcodes.r8(pc++);
+ const u8 rd = (op2 & 0xf0) >> 4;
+ const u16 data = (op3 << 8) | op4;
+ util::stream_format(stream, "%s.w [%s+], #$%04x", m_aluops[alu_op], m_regnames16[rd], data );
+ return 4;
+ }
+
+ case 0x0c:
+ {
+ const u8 op3 = opcodes.r8(pc++);
+ const u8 op4 = opcodes.r8(pc++);
+ const u8 op5 = opcodes.r8(pc++);
+ const u8 rd = (op2 & 0xf0) >> 4;
+ const int offset = op3;
+ const u16 data = (op4 << 8) | op5;
+ util::stream_format(stream, "%s.w [%s+#$%02x], #$%04x", m_aluops[alu_op], m_regnames16[rd], offset, data );
+ return 5;
+ }
+
+ case 0x0d:
+ {
+ const u8 op3 = opcodes.r8(pc++);
+ const u8 op4 = opcodes.r8(pc++);
+ const u8 op5 = opcodes.r8(pc++);
+ const u8 op6 = opcodes.r8(pc++);
+ const u8 rd = (op2 & 0xf0) >> 4;
+ const int offset = (op3 << 8) | op4;
+ const u16 data = (op5 << 8) | op6;
+ util::stream_format(stream, "%s.w [%s+#$%04x], #$%04x", m_aluops[alu_op], m_regnames16[rd], offset, data );
+ return 6;
+ }
+
+ case 0x0e:
+ {
+ const u8 op3 = opcodes.r8(pc++);
+ const u8 op4 = opcodes.r8(pc++);
+ const u8 op5 = opcodes.r8(pc++);
+ const u16 direct =( (op2 & 0xf0) << 4) | op3;
+ const u16 data = (op4 << 8) | op5;
+ util::stream_format(stream, "%s.w %s, #$%04x", m_aluops[alu_op], get_directtext(direct), data );
+ return 5;
+ }
+ }
+ return 1;
+}
+
+std::string xa_dasm::show_expanded_data4(u16 data4, int size)
+{
+ u16 extended = util::sext(data4, 4);
+
+ if (!size)
+ {
+ extended &= 0xff;
+ return util::string_format("#$%02x", extended);
+ }
+
+ return util::string_format("#$%04x", extended);
+}
+
+int xa_dasm::handle_adds_movs(XA_DASM_PARAMS, int which)
+{
+ const u8 op2 = opcodes.r8(pc++);
+ int size = op & 0x08;
+
+ const u16 data4 = op2 & 0x0f;
+
+ switch (op & 0x07)
+ {
+ case 0x01:
+ {
+ int rd = (op2 & 0xf0) >> 4;
+ const char** regnames = size ? m_regnames16 : m_regnames8;
+ util::stream_format(stream, "%s%s %s, %s", m_addsmovs[which], size ? ".w" : ".b", regnames[rd], show_expanded_data4(data4, size)); // last is not m_regnames8
+ ;
+ return 2;
+ }
+
+ case 0x02:
+ {
+ int rd = (op2 & 0x70) >> 4;
+ util::stream_format(stream, "%s%s [%s], %s", m_addsmovs[which], size ? ".w" : ".b", m_regnames16[rd], show_expanded_data4(data4, size));
+ return 2;
+ }
+
+ case 0x03:
+ {
+ int rd = (op2 & 0x70) >> 4;
+ util::stream_format(stream, "%s%s [%s+], %s", m_addsmovs[which], size ? ".w" : ".b", m_regnames16[rd], show_expanded_data4(data4, size));
+ return 2;
+ }
+
+ case 0x04:
+ {
+ int rd = (op2 & 0x70) >> 4;
+ const u8 op3 = opcodes.r8(pc++);
+ util::stream_format(stream, "%s%s [%s+$%02x], %s", m_addsmovs[which], size ? ".w" : ".b", m_regnames16[rd], op3, show_expanded_data4(data4, size));
+ return 3;
+ }
+
+ case 0x05:
+ {
+ int rd = (op2 & 0x70) >> 4;
+ const u8 op3 = opcodes.r8(pc++);
+ const u8 op4 = opcodes.r8(pc++);
+ const int offset = (op3 << 8) | op4;
+ util::stream_format(stream, "%s%s [%s+$%04x], %s", m_addsmovs[which], size ? ".w" : ".b", m_regnames16[rd], offset, show_expanded_data4(data4, size));
+ return 4;
+ }
+ case 0x06:
+ {
+ const u8 op3 = opcodes.r8(pc++);
+ const u16 direct = ((op2 & 0xf0) << 4) | op3;
+ util::stream_format(stream, "%s%s %s, %s", m_addsmovs[which], size ? ".w" : ".b", get_directtext(direct), show_expanded_data4(data4, size));
+ return 3;
+ }
+ }
+
+ return 1;
+}
+
+
+int xa_dasm::handle_pushpop_rlist(XA_DASM_PARAMS, int type)
+{
+ const u8 h = op & 0x40;
+ const u8 size = op & 0x08;
+ const u8 op2 = opcodes.r8(pc++);
+
+ if (size)
+ {
+ // h is ignored?
+ util::stream_format(stream, "%s%s ", m_pushpull[type], size ? ".w" : ".b");
+
+ bool firstbit = true;
+ for (int i = 0; i < 8; i++)
+ {
+ int bit = (op2 & (1 << i));
+
+ if (bit)
+ {
+ util::stream_format(stream, "%s%s", firstbit ? "" : ",", m_regnames16[i]);
+ firstbit = false;
+ }
+ }
+ }
+ else
+ {
+ util::stream_format(stream, "%s%s ", m_pushpull[type], size ? ".w" : ".b");
+
+ bool firstbit = true;
+ for (int i = 0; i < 8; i++)
+ {
+ int bit = (op2 & (1 << i));
+
+ if (bit)
+ {
+ util::stream_format(stream, "%s%s", firstbit ? "" : ",", m_regnames8[i + h ? 8 : 0]);
+ firstbit = false;
+ }
+ }
+ }
+
+ return 2;
+}
+
+
+
+// -------------------------------------- Group 0 --------------------------------------
+
+/*
+NOP No operation 1 3 0000 0000
+*/
+int xa_dasm::d_nop(XA_DASM_PARAMS)
+{
+ util::stream_format(stream, "NOP");
+ return 1;
+}
+
+/*
+CLR bit Clear bit 3 4 0000 1000 0000 00bb bbbb bbbb
+SETB bit Sets the bit specified 3 4 0000 1000 0001 00bb bbbb bbbb
+MOV C, bit Move bit to the carry flag 3 4 0000 1000 0010 00bb bbbb bbbb
+MOV bit, C Move carry to bit 3 4 0000 1000 0011 00bb bbbb bbbb
+ANL C, bit Logical AND bit to carry 3 4 0000 1000 0100 00bb bbbb bbbb
+ANL C, /bit Logical AND complement of a bit to carry 3 4 0000 1000 0101 00bb bbbb bbbb
+ORL C, bit Logical OR a bit to carry 3 4 0000 1000 0110 00bb bbbb bbbb
+ORL C, /bit Logical OR complement of a bit to carry 3 4 0000 1000 0111 00bb bbbb bbbb
+*/
+
+int xa_dasm::d_bitgroup(XA_DASM_PARAMS)
+{
+ const u8 op2 = opcodes.r8(pc++);
+ const u8 op3 = opcodes.r8(pc++);
+
+ u16 bit = ((op2 & 0x03) << 8) | op3;
+
+ switch (op2 & 0xf0)
+ {
+ case 0x00: util::stream_format(stream, "CLR %s", get_bittext(bit) ); break;
+ case 0x10: util::stream_format(stream, "SETB %s", get_bittext(bit) ); break;
+ case 0x20: util::stream_format(stream, "MOV C, %s", get_bittext(bit) ); break;
+ case 0x30: util::stream_format(stream, "MOV %s, C", get_bittext(bit) ); break;
+ case 0x40: util::stream_format(stream, "ANL C, %s", get_bittext(bit) ); break;
+ case 0x50: util::stream_format(stream, "ANL C, /%s", get_bittext(bit) ); break;
+ case 0x60: util::stream_format(stream, "ORL C, %s", get_bittext(bit) ); break;
+ case 0x70: util::stream_format(stream, "ORL C, /%s", get_bittext(bit) ); break;
+ default: util::stream_format(stream, "illegal bit op %s", get_bittext(bit) ); break;
+ }
+ return 3;
+}
+
+/*
+ADD Rd, Rs Add regs direct 2 3 0000 S001 dddd ssss
+ADD Rd, [Rs] Add reg-ind to reg 2 4 0000 S010 dddd 0sss
+ADD [Rd], Rs Add reg to reg-ind 2 4 0000 S010 ssss 1ddd
+ADD Rd, [Rs+] Add reg-ind w/ autoinc to reg 2 5 0000 S011 dddd 0sss
+ADD [Rd+], Rs Add reg-ind w/ autoinc to reg 2 5 0000 S011 ssss 1ddd
+ADD Rd, [Rs+offset8] Add reg-ind w/ 8-bit offs to reg 3 6 0000 S100 dddd 0sss oooo oooo
+ADD [Rd+offset8], Rs Add reg to reg-ind w/ 8-bit offs 3 6 0000 S100 ssss 1ddd oooo oooo
+ADD Rd, [Rs+offset16] Add reg-ind w/ 16-bit offs to reg 4 6 0000 S101 dddd 0sss oooo oooo oooo oooo
+ADD [Rd+offset16], Rs Add reg to reg-ind w/ 16-bit offs 4 6 0000 S101 ssss 1ddd oooo oooo oooo oooo
+ADD direct, Rs Add reg to mem 3 4 0000 S110 ssss 1DDD DDDD DDDD
+ADD Rd, direct Add mem to reg 3 4 0000 S110 dddd 0DDD DDDD DDDD
+*/
+int xa_dasm::d_add(XA_DASM_PARAMS)
+{
+ return handle_alu_type0(XA_CALL_PARAMS, 0);
+}
+
+/*
+PUSH Rlist Push regs (b/w) onto the current stack 2 b* 0H00 S111 LLLL LLLL
+*/
+int xa_dasm::d_push_rlist(XA_DASM_PARAMS)
+{
+ return handle_pushpop_rlist(XA_CALL_PARAMS, 0);
+}
+
+// -------------------------------------- Group 1 --------------------------------------
+
+/*
+ADDC Rd, Rs Add regs direct w/ carry 2 3 0001 S001 dddd ssss
+ADDC Rd, [Rs] Add reg-ind to reg w/ carry 2 4 0001 S010 dddd 0sss
+ADDC [Rd], Rs Add reg to reg-ind w/ carry 2 4 0001 S010 ssss 1ddd
+ADDC Rd, [Rs+offset8] Add reg-ind w/ 8-bit offs to reg w/ carry 3 6 0001 S100 dddd 0sss oooo oooo
+ADDC [Rd+offset8], Rs Add reg to reg-ind w/ 8-bit offs w/ carry 3 6 0001 S100 ssss 1ddd oooo oooo
+ADDC Rd, [Rs+offset16] Add reg-ind w/ 16-bit offs to reg w/ carry 4 6 0001 S101 dddd 0sss oooo oooo oooo oooo
+ADDC [Rd+offset16], Rs Add reg to reg-ind w/ 16-bit offs w/ carry 4 6 0001 S101 ssss 1ddd oooo oooo oooo oooo
+ADDC Rd, [Rs+] Add reg-ind w/ autoinc to reg w/ carry 2 5 0001 S011 dddd 0sss
+ADDC [Rd+], Rs Add reg-ind w/ autoinc to reg w/ carry 2 5 0001 S011 ssss 1ddd
+ADDC direct, Rs Add reg to mem w/ carry 3 4 0001 S110 ssss 1DDD DDDD DDDD
+ADDC Rd, direct Add mem to reg w/ carry 3 4 0001 S110 dddd 0DDD DDDD DDDD
+*/
+
+int xa_dasm::d_addc(XA_DASM_PARAMS)
+{
+ return handle_alu_type0(XA_CALL_PARAMS, 1);
+}
+
+/*
+PUSHU Rlist Push regs (b/w) from the user stack 2 b* 0H01 S111 LLLL LLLL
+*/
+int xa_dasm::d_pushu_rlist(XA_DASM_PARAMS)
+{
+ return handle_pushpop_rlist(XA_CALL_PARAMS, 1);
+}
+
+
+// -------------------------------------- Group 2 --------------------------------------
+
+/*
+SUB Rd, Rs Subtract regs direct 2 3 0010 S001 dddd ssss
+SUB Rd, [Rs] Subtract reg-ind to reg 2 4 0010 S010 dddd 0sss
+SUB [Rd], Rs Subtract reg to reg-ind 2 4 0010 S010 ssss 1ddd
+SUB Rd, [Rs+offset8] Subtract reg-ind w/ 8-bit offs to reg 3 6 0010 S100 dddd 0sss oooo oooo
+SUB [Rd+offset8], Rs Subtract reg to reg-ind w/ 8-bit offs 3 6 0010 S100 ssss 1ddd oooo oooo
+SUB Rd, [Rs+offset16] Subtract reg-ind w/ 16-bit offs to reg 4 6 0010 S101 dddd 0sss oooo oooo oooo oooo
+SUB [Rd+offset16], Rs Subtract reg to reg-ind w/ 16-bit offs 4 6 0010 S101 ssss 1ddd oooo oooo oooo oooo
+SUB Rd, [Rs+] Subtract reg-ind w/ autoinc to reg 2 5 0010 S011 dddd 0sss
+SUB [Rd+], Rs Subtract reg-ind w/ autoinc to reg 2 5 0010 S011 ssss 1ddd
+SUB direct, Rs Subtract reg to mem 3 4 0010 S110 ssss 1DDD DDDD DDDD
+SUB Rd, direct Subtract mem to reg 3 4 0010 S110 dddd 0DDD DDDD DDDD
+*/
+int xa_dasm::d_sub(XA_DASM_PARAMS)
+{
+ return handle_alu_type0(XA_CALL_PARAMS, 2);
+}
+
+/*
+POP Rlist Pop regs (b/w) from the current stack 2 c* 0H10 S111 LLLL LLLL
+*/
+int xa_dasm::d_pop_rlist(XA_DASM_PARAMS)
+{
+ return handle_pushpop_rlist(XA_CALL_PARAMS, 2);
+}
+
+
+// -------------------------------------- Group 3 --------------------------------------
+
+/*
+SUBB Rd, Rs Subtract w/ borrow regs direct 2 3 0011 S001 dddd ssss
+SUBB Rd, [Rs] Subtract w/ borrow reg-ind to reg 2 4 0011 S010 dddd 0sss
+SUBB [Rd], Rs Subtract w/ borrow reg to reg-ind 2 4 0011 S010 ssss 1ddd
+SUBB Rd, [Rs+] Subtract w/ borrow reg-ind w/ autoinc to reg 2 5 0011 S011 dddd 0sss
+SUBB [Rd+], Rs Subtract w/ borrow reg-ind w/ autoinc to reg 2 5 0011 S011 ssss 1ddd
+SUBB Rd, [Rs+offset8] Subtract w/ borrow reg-ind w/ 8-bit offs to reg 3 6 0011 S100 dddd 0sss oooo oooo
+SUBB [Rd+offset8], Rs Subtract w/ borrow reg to reg-ind w/ 8-bit offs 3 6 0011 S100 ssss 1ddd oooo oooo
+SUBB Rd, [Rs+offset16] Subtract w/ borrow reg-ind w/ 16-bit offs to reg 4 6 0011 S101 dddd 0sss oooo oooo oooo oooo
+SUBB [Rd+offset16], Rs Subtract w/ borrow reg to reg-ind w/ 16-bit offs 4 6 0011 S101 ssss 1ddd oooo oooo oooo oooo
+SUBB direct, Rs Subtract w/ borrow reg to mem 3 4 0011 S110 ssss 1DDD DDDD DDDD
+SUBB Rd, direct Subtract w/ borrow mem to reg 3 4 0011 S110 dddd 0DDD DDDD DDDD
+*/
+int xa_dasm::d_subb(XA_DASM_PARAMS)
+{
+ return handle_alu_type0(XA_CALL_PARAMS, 3);
+}
+
+/*
+POPU Rlist Pop regs (b/w) from the user stack 2 c* 0H11 S111 LLLL LLLL
+*/
+int xa_dasm::d_popu_rlist(XA_DASM_PARAMS)
+{
+ return handle_pushpop_rlist(XA_CALL_PARAMS, 3);
+}
+
+
+// -------------------------------------- Group 4 --------------------------------------
+
+/*
+LEA Rd, Rs+offset8 Load 16-bit effective address w/ 8-bit offs to reg 3 3 0100 0000 0ddd 0sss oooo oooo
+*/
+int xa_dasm::d_lea_offset8(XA_DASM_PARAMS)
+{
+ const u8 op2 = opcodes.r8(pc++);
+ const u8 op3 = opcodes.r8(pc++);
+ const u8 rd = (op2 & 0x70) >> 4;
+ const u8 rs = (op2 & 0x07);
+ util::stream_format(stream, "LEA %s, %s+#$%02x", m_regnames16[rd], m_regnames16[rs], op3);
+ return 3;
+}
+
+/*
+LEA Rd, Rs+offset16 Load 16-bit effective address w/ 16-bit offs to reg 4 3 0100 1000 0ddd 0sss oooo oooo oooo oooo
+*/
+int xa_dasm::d_lea_offset16(XA_DASM_PARAMS)
+{
+ const u8 op2 = opcodes.r8(pc++);
+ const u8 op3 = opcodes.r8(pc++);
+ const u8 op4 = opcodes.r8(pc++);
+ const u8 rd = (op2 & 0x70) >> 4;
+ const u8 rs = (op2 & 0x07);
+ const u16 offset = (op3 << 8) | op4;
+
+ util::stream_format(stream, "LEA %s, %s+#$%04x ", m_regnames16[rd], m_regnames16[rs], offset);
+ return 4;
+}
+
+/*
+CMP Rd, Rs Compare dest and src regs 2 3 0100 S001 dddd ssss
+CMP Rd, [Rs] Compare reg-ind w/ reg 2 4 0100 S010 dddd 0sss
+CMP [Rd], Rs Compare reg w/ reg-ind 2 4 0100 S010 ssss 1ddd
+CMP Rd, [Rs+offset8] Compare reg-ind w/ 8-bit offs w/ reg 3 6 0100 S100 dddd 0sss oooo oooo
+CMP [Rd+offset8], Rs Compare reg w/ reg-ind w/ 8-bit offs 3 6 0100 S100 ssss 1ddd oooo oooo
+CMP Rd,[Rs+offset16] Compare reg-ind w/ 16-bit offs w/ reg 4 6 0100 S101 dddd 0sss oooo oooo oooo oooo
+CMP [Rd+offset16], Rs Compare reg w/ reg-ind w/ 16-bit offs 4 6 0100 S101 ssss 1ddd oooo oooo oooo oooo
+CMP Rd, [Rs+] Compare autoinc reg-ind w/ reg 2 5 0100 S011 dddd 0sss
+CMP [Rd+], Rs Compare reg w/ autoinc reg-ind 2 5 0100 S011 ssss 1ddd
+CMP direct, Rs Compare reg w/ mem 3 4 0100 S110 ssss 1DDD DDDD DDDD
+CMP Rd, direct Compare mem w/ reg 3 4 0100 S110 dddd 0DDD DDDD DDDD
+*/
+int xa_dasm::d_cmp(XA_DASM_PARAMS)
+{
+ return handle_alu_type0(XA_CALL_PARAMS, 4);
+}
+
+// -------------------------------------- Group 5 --------------------------------------
+
+/*
+XCH Rd, [Rs] Exchange contents of a reg-ind address w/ a reg 2 6 0101 S000 dddd 0sss
+*/
+int xa_dasm::d_xch_type1(XA_DASM_PARAMS)
+{
+ const u8 op2 = opcodes.r8(pc++);
+ int size = op & 0x08;
+ const char** regnames = size ? m_regnames16 : m_regnames8;
+ const u8 rd = (op2 & 0xf0) >> 4;
+ const u8 rs = (op2 & 0x07);
+ util::stream_format(stream, "XCH %s, [%s]", regnames[rd], m_regnames16[rs]);
+ return 2;
+}
+
+/*
+AND Rd, Rs Logical AND regs direct 2 3 0101 S001 dddd ssss
+AND Rd, [Rs] Logical AND reg-ind to reg 2 4 0101 S010 dddd 0sss
+AND [Rd], Rs Logical AND reg to reg-ind 2 4 0101 S010 ssss 1ddd
+AND Rd, [Rs+offset8] Logical AND reg-ind w/ 8-bit offs to reg 3 6 0101 S100 dddd 0sss oooo oooo
+AND [Rd+offset8], Rs Logical AND reg to reg-ind w/ 8-bit offs 3 6 0101 S100 ssss 1ddd oooo oooo
+AND Rd, [Rs+offset16] Logical AND reg-ind w/ 16-bit offs to reg 4 6 0101 S101 dddd 0sss oooo oooo oooo oooo
+AND [Rd+offset16], Rs Logical AND reg to reg-ind w/ 16-bit offs 4 6 0101 S101 ssss 1ddd oooo oooo oooo oooo
+AND Rd, [Rs+] Logical AND reg-ind w/ autoinc to reg 2 5 0101 S011 dddd 0sss
+AND [Rd+], Rs Logical AND reg-ind w/ autoinc to reg 2 5 0101 S011 ssss 1ddd
+AND direct, Rs Logical AND reg to mem 3 4 0101 S110 ssss 1DDD DDDD DDDD
+AND Rd, direct Logical AND mem to reg 3 4 0101 S110 dddd 0DDD DDDD DDDD
+*/
+int xa_dasm::d_and(XA_DASM_PARAMS)
+{
+ return handle_alu_type0(XA_CALL_PARAMS, 5);
+}
+
+// -------------------------------------- Group 6 --------------------------------------
+
+/*
+XCH Rd, Rs Exchange contents of two regs 2 5 0110 S000 dddd ssss
+*/
+int xa_dasm::d_xch_type2(XA_DASM_PARAMS)
+{
+ const u8 op2 = opcodes.r8(pc++);
+ int size = op & 0x08;
+ const char** regnames = size ? m_regnames16 : m_regnames8;
+ const u8 rd = (op2 & 0xf0) >> 4;
+ const u8 rs = (op2 & 0x0f);
+
+ util::stream_format(stream, "XCH %s, %s", regnames[rd], regnames[rs]);
+ return 2;
+}
+
+/*
+OR Rd, Rs Logical OR regs 2 3 0110 S001 dddd ssss
+OR Rd, [Rs] Logical OR reg-ind to reg 2 4 0110 S010 dddd 0sss
+OR [Rd], Rs Logical OR reg to reg-ind 2 4 0110 S010 ssss 1ddd
+OR Rd, [Rs+offset8] Logical OR reg-ind w/ 8-bit offs to reg 3 6 0110 S100 dddd 0sss oooo oooo
+OR [Rd+offset8], Rs Logical OR reg to reg-ind w/ 8-bit offs 3 6 0110 S100 ssss 1ddd oooo oooo
+OR Rd, [Rs+offset16] Logical OR reg-ind w/ 16-bit offs to reg 4 6 0110 S101 dddd 0sss oooo oooo oooo oooo
+OR [Rd+offset16], Rs Logical OR reg to reg-ind w/ 16-bit offs 4 6 0110 S101 ssss 1ddd oooo oooo oooo oooo
+OR Rd, [Rs+] Logical OR reg-ind w/ autoinc to reg 2 5 0110 S011 dddd 0sss
+OR [Rd+], Rs Logical OR reg-ind w/ autoinc to reg 2 5 0110 S011 ssss 1ddd
+OR direct, Rs Logical OR reg to mem 3 4 0110 S110 ssss 1DDD DDDD DDDD
+OR Rd, direct Logical OR mem to reg 3 4 0110 S110 dddd 0DDD DDDD DDDD
+*/
+int xa_dasm::d_or(XA_DASM_PARAMS)
+{
+ return handle_alu_type0(XA_CALL_PARAMS, 6);
+}
+
+// -------------------------------------- Group 7 --------------------------------------
+
+/*
+XOR Rd, Rs Logical XOR regs 2 3 0111 S001 dddd ssss
+XOR Rd, [Rs] Logical XOR reg-ind to reg 2 4 0111 S010 dddd 0sss
+XOR [Rd], Rs Logical XOR reg to reg-ind 2 4 0111 S010 ssss 1ddd
+XOR Rd, [Rs+offset8] Logical XOR reg-ind w/ 8-bit offs to reg 3 6 0111 S100 dddd 0sss oooo oooo
+XOR [Rd+offset8], Rs Logical XOR reg to reg-ind w/ 8-bit offs 3 6 0111 S100 ssss 1ddd oooo oooo
+XOR Rd, [Rs+offset16] Logical XOR reg-ind w/ 16-bit offs to reg 4 6 0111 S101 dddd 0sss oooo oooo oooo oooo
+XOR [Rd+offset16], Rs Logical XOR reg to reg-ind w/ 16-bit offs 4 6 0111 S101 ssss 1ddd oooo oooo oooo oooo
+XOR Rd, [Rs+] Logical XOR reg-ind w/ autoinc to reg 2 5 0111 S011 dddd 0sss
+XOR [Rd+], Rs Logical XOR reg-ind w/ autoinc to reg 2 5 0111 S011 ssss 1ddd
+XOR direct, Rs Logical XOR reg to mem 3 4 0111 S110 ssss 1DDD DDDD DDDD
+XOR Rd, direct Logical XOR mem to reg 3 4 0111 S110 dddd 0DDD DDDD DDDD
+*/
+int xa_dasm::d_xor(XA_DASM_PARAMS)
+{
+ return handle_alu_type0(XA_CALL_PARAMS, 7);
+}
+
+// -------------------------------------- Group 8 --------------------------------------
+
+/*
+MOVC Rd, [Rs+] Move data from WS:Rs address of code mem to reg w/ autoinc 2 4 1000 S000 dddd 0sss
+*/
+int xa_dasm::d_movc_rd_rsinc(XA_DASM_PARAMS)
+{
+ const u8 op2 = opcodes.r8(pc++);
+ int size = op & 0x08;
+
+ int rd = (op2 & 0xf0) >> 4;
+ int rs = (op2 & 0x07);
+ const char** regnames = size ? m_regnames16 : m_regnames8;
+
+ util::stream_format(stream, "MOVC%s %s, [%s+]", size ? ".w" : ".b", regnames[rd], m_regnames16[rs]);
+ return 2;
+}
+
+/*
+MOV Rd, Rs Move reg to reg 2 3 1000 S001 dddd ssss
+MOV Rd, [Rs] Move reg-ind to reg 2 3 1000 S010 dddd 0sss
+MOV [Rd], Rs Move reg to reg-ind 2 3 1000 S010 ssss 1ddd
+MOV Rd, [Rs+offset8] Move reg-ind w/ 8-bit offs to reg 3 5 1000 S100 dddd 0sss oooo oooo
+MOV [Rd+offset8], Rs Move reg to reg-ind w/ 8-bit offs 3 5 1000 S100 ssss 1ddd oooo oooo
+MOV Rd, [Rs+offset16] Move reg-ind w/ 16-bit offs to reg 4 5 1000 S101 dddd 0sss oooo oooo oooo oooo
+MOV [Rd+offset16], Rs Move reg to reg-ind w/ 16-bit offs 4 5 1000 S101 ssss 1ddd oooo oooo oooo oooo
+MOV Rd, [Rs+] Move reg-ind w/ autoinc to reg 2 4 1000 S011 dddd 0sss
+MOV [Rd+], Rs Move reg-ind w/ autoinc to reg 2 4 1000 S011 ssss 1ddd
+MOV direct, Rs Move reg to mem 3 4 1000 S110 ssss 1DDD DDDD DDDD
+MOV Rd, direct Move mem to reg 3 4 1000 S110 dddd 0DDD DDDD DDDD
+*/
+int xa_dasm::d_mov(XA_DASM_PARAMS)
+{
+ return handle_alu_type0(XA_CALL_PARAMS, 8);
+}
+
+/*
+POPU direct Pop the mem content (b/w) from the user stack 3 5 1000 S111 0000 0DDD DDDD DDDD
+POP direct Pop the mem content (b/w) from the current stack 3 5 1000 S111 0001 0DDD DDDD DDDD
+PUSHU direct Push the mem content (b/w) onto the user stack 3 5 1000 S111 0010 0DDD DDDD DDDD
+PUSH direct Push the mem content (b/w) onto the current stack 3 5 1000 S111 0011 0DDD DDDD DDDD
+DJNZ Rd,rel8 Decrement reg and jump if not zero 3 8t/5nt 1000 S111 dddd 1000 rrrr rrrr
+*/
+int xa_dasm::d_pushpop_djnz_subgroup(XA_DASM_PARAMS)
+{
+ const u8 op2 = opcodes.r8(pc++);
+ const u8 op3 = opcodes.r8(pc++);
+ int size = op & 0x08;
+
+
+ if (op2 & 0x08)
+ {
+ int address = pc + ((s8)op3)*2;
+ int rd = (op2 & 0xf0) >> 4;
+ address &= ~1; // must be word aligned
+ const char** regnames = size ? m_regnames16 : m_regnames8;
+ util::stream_format(stream, "DJNZ%s %s, $%04x", size ? ".w" : ".b", regnames[rd], address);
+ return 3;
+ }
+ else
+ {
+ const u16 direct = ((op2 & 0x07) << 8) | op3;
+
+ switch (op2 & 0xf0)
+ {
+ case 0x00:
+ util::stream_format(stream, "POPU%s %s", size ? ".w" : ".b", get_directtext(direct));
+ break;
+
+ case 0x10:
+ util::stream_format(stream, "POP%s %s", size ? ".w" : ".b", get_directtext(direct));
+ break;
+
+ case 0x20:
+ util::stream_format(stream, "PUSHU%s %s", size ? ".w" : ".b", get_directtext(direct));
+ break;
+
+ case 0x30:
+ util::stream_format(stream, "PUSH%s %s", size ? ".w" : ".b", get_directtext(direct));
+ break;
+
+ default:
+ util::stream_format(stream, "illegal");
+ break;
+ }
+ }
+ return 3;
+}
+
+
+
+// -------------------------------------- Group 9 --------------------------------------
+
+/*
+MOV [Rd+], [Rs+] Move reg-ind to reg-ind, both pointers autoinc 2 6 1001 S000 0ddd 0sss
+DA Rd Decimal Adjust byte reg 2 4 1001 0000 dddd 1000
+SEXT Rd Sign extend last operation to reg 2 3 1001 S000 dddd 1001
+CPL Rd Complement (ones complement) reg 2 3 1001 S000 dddd 1010
+NEG Rd Negate (twos complement) reg 2 3 1001 S000 dddd 1011
+MOVC A, [A+PC] Move data from code mem to the accumulator ind w/ PC 2 6 1001 0000 0100 1100
+MOVC A, [A+DPTR] Move data from code mem to the accumulator ind w/ DPTR 2 6 1001 0000 0100 1110
+MOV Rd, USP Move User Stack Pointer to reg (system mode only) 2 3 1001 0000 dddd 1111
+MOV USP, Rs Move reg to User Stack Pointer (system mode only) 2 3 1001 1000 ssss 1111
+*/
+int xa_dasm::d_g9_subgroup(XA_DASM_PARAMS)
+{
+ const u8 op2 = opcodes.r8(pc++);
+ int size = op & 0x08;
+ const char** regnames = size ? m_regnames16 : m_regnames8;
+
+ if ((op2 & 0x0f) < 0x08)
+ {
+ int rd = (op2 & 0x70) >> 4;
+ int rs = (op2 & 0x07);
+ util::stream_format(stream, "MOV%s [%s+], [%s+]", size ? ".w" : ".b", m_regnames16[rd], m_regnames16[rs]);
+ }
+ else
+ {
+ switch (op2 & 0x0f)
+ {
+ case 0x08:
+ {
+ int rd = (op2 & 0xf0) >> 4;
+ util::stream_format(stream, "DA %s", m_regnames8[rd]);
+ return 2;
+ }
+ case 0x09:
+ {
+ int rd = (op2 & 0xf0) >> 4;
+ util::stream_format(stream, "SEXT%s %s", size ? ".w" : ".b", regnames[rd]);
+ return 2;
+ }
+ case 0x0a:
+ {
+ int rd = (op2 & 0xf0) >> 4;
+ util::stream_format(stream, "CPL%s %s", size ? ".w" : ".b", regnames[rd]);
+ return 2;
+ }
+ case 0x0b:
+ {
+ int rd = (op2 & 0xf0) >> 4;
+ util::stream_format(stream, "NEG%s %sx", size ? ".w" : ".b", regnames[rd]);
+ return 2;
+ }
+ case 0x0c:
+ {
+ util::stream_format(stream, "MOVC A, [A+PC]");
+ return 2;
+ }
+ case 0x0e:
+ {
+ util::stream_format(stream, "MOVC A, [A+DPTR]");
+ return 2;
+ }
+ case 0x0f:
+ {
+ if (!size)
+ {
+ int rd = (op2 & 0xf0) >> 4;
+ util::stream_format(stream, "MOV %s, USP", m_regnames16[rd]);
+ }
+ else
+ {
+ int rs = (op2 & 0xf0) >> 4;
+ util::stream_format(stream, "MOV USP, %s", m_regnames16[rs]);
+ }
+ return 2;
+ }
+ default:
+ {
+ util::stream_format(stream, "illegal %02x", op2);
+ return 2;
+ }
+
+ }
+ }
+
+ return 2;
+}
+
+/*
+ADD Rd, #data8 Add 8-bit imm data to reg 3 3 1001 0001 dddd 0000 iiii iiii
+ADD [Rd], #data8 Add 8-bit imm data to reg-ind 3 4 1001 0010 0ddd 0000 iiii iiii
+ADD [Rd+], #data8 Add 8-bit imm data to reg-ind w/ autoinc 3 5 1001 0011 0ddd 0000 iiii iiii
+ADD [Rd+offset8], #data8 Add 8-bit imm data to reg-ind w/ 8-bit offs 4 6 1001 0100 0ddd 0000 oooo oooo iiii iiii
+ADD [Rd+offset16], #data8 Add 8-bit imm data to reg-ind w/ 16-bit offs 5 6 1001 0101 0ddd 0000 oooo oooo oooo oooo iiii iiii
+ADD direct, #data8 Add 8-bit imm data to mem 4 4 1001 0110 0DDD 0000 DDDD DDDD iiii iiii
+ADD Rd, #data16 Add 16-bit imm data to reg 4 3 1001 1001 dddd 0000 iiii iiii iiii iiii
+ADD [Rd], #data16 Add 16-bit imm data to reg-ind 4 4 1001 1010 0ddd 0000 iiii iiii iiii iiii
+ADD [Rd+], #data16 Add 16-bit imm data to reg-ind w/ autoinc 4 5 1001 1011 0ddd 0000 iiii iiii iiii iiii
+ADD [Rd+offset8], #data16 Add 16-bit imm data to reg-ind w/ 8-bit offs 5 6 1001 1100 0ddd 0000 oooo oooo iiii iiii iiii iiii
+ADD [Rd+offset16], #data16 Add 16-bit imm data to reg-ind w/ 16-bit offs 6 6 1001 1101 0ddd 0000 oooo oooo oooo oooo iiii iiii iiii iiii
+ADD direct, #data16 Add 16-bit imm data to mem 5 4 1001 1110 0DDD 0000 DDDD DDDD iiii iiii iiii iiii
+
+ADDC Rd, #data8 Add 8-bit imm data to reg w/ carry 3 3 1001 0001 dddd 0001 iiii iiii
+ADDC Rd, #data16 Add 16-bit imm data to reg w/ carry 4 3 1001 1001 dddd 0001 iiii iiii iiii iiii
+ADDC [Rd], #data8 Add 16-bit imm data to reg-ind w/ carry 3 4 1001 0010 0ddd 0001 iiii iiii
+ADDC [Rd], #data16 Add 16-bit imm data to reg-ind w/ carry 4 4 1001 1010 0ddd 0001 iiii iiii iiii iiii
+ADDC [Rd+], #data8 Add 8-bit imm data to reg-ind and autoinc w/ carry 3 5 1001 0011 0ddd 0001 iiii iiii
+ADDC [Rd+], #data16 Add 16-bit imm data to reg-ind and autoinc w/ carry 4 5 1001 1011 0ddd 0001 iiii iiii iiii iiii
+ADDC [Rd+offset8], #data8 Add 8-bit imm data to reg-ind w/ 8-bit offs and carry 4 6 1001 0100 0ddd 0001 oooo oooo iiii iiii
+ADDC [Rd+offset8], #data16 Add 16-bit imm data to reg-ind w/ 8-bit offs and carry 5 6 1001 1100 0ddd 0001 oooo oooo iiii iiii iiii iiii
+ADDC [Rd+offset16], #data8 Add 8-bit imm data to reg-ind w/ 16-bit offs and carry 5 6 1001 0101 0ddd 0001 oooo oooo oooo oooo iiii iiii
+ADDC [Rd+offset16], #data16 Add 16-bit imm data to reg-ind w/ 16-bit offs and carry 6 6 1001 1101 0ddd 0001 oooo oooo oooo oooo iiii iiii iiii iiii
+ADDC direct, #data8 Add 8-bit imm data to mem w/ carry 4 4 1001 0110 0DDD 0001 DDDD DDDD iiii iiii
+ADDC direct, #data16 Add 16-bit imm data to mem w/ carry 5 4 1001 1110 0DDD 0001 DDDD DDDD iiii iiii iiii iiii
+
+SUB Rd, #data8 Subtract 8-bit imm data to reg 3 3 1001 0001 dddd 0010 iiii iiii
+SUB Rd, #data16 Subtract 16-bit imm data to reg 4 3 1001 1001 dddd 0010 iiii iiii iiii iiii
+SUB [Rd], #data8 Subtract 8-bit imm data to reg-ind 3 4 1001 0010 0ddd 0010 iiii iiii
+SUB [Rd], #data16 Subtract 16-bit imm data to reg-ind 4 4 1001 1010 0ddd 0010 iiii iiii iiii iiii
+SUB [Rd+], #data8 Subtract 8-bit imm data to reg-ind w/ autoinc 3 5 1001 0011 0ddd 0010 iiii iiii
+SUB [Rd+], #data16 Subtract 16-bit imm data to reg-ind w/ autoinc 4 5 1001 1011 0ddd 0010 iiii iiii iiii iiii
+SUB [Rd+offset8], #data8 Subtract 8-bit imm data to reg-ind w/ 8-bit offs 4 6 1001 0100 0ddd 0010 oooo oooo iiii iiii
+SUB [Rd+offset8], #data16 Subtract 16-bit imm data to reg-ind w/ 8-bit offs 5 6 1001 1100 0ddd 0010 oooo oooo iiii iiii iiii iiii
+SUB [Rd+offset16], #data8 Subtract 8-bit imm data to reg-ind w/ 16-bit offs 5 6 1001 0101 0ddd 0010 oooo oooo oooo oooo iiii iiii
+SUB [Rd+offset16], #data16 Subtract 16-bit imm data to reg-ind w/ 16-bit offs 6 6 1001 1101 0ddd 0010 oooo oooo oooo oooo iiii iiii iiii iiii
+SUB direct, #data8 Subtract 8-bit imm data to mem 4 4 1001 0110 0DDD 0010 DDDD DDDD iiii iiii
+SUB direct, #data16 Subtract 16-bit imm data to mem 5 4 1001 1110 0DDD 0010 DDDD DDDD iiii iiii iiii iiii
+
+SUBB Rd, #data8 Subtract w/ borrow 8-bit imm data to reg 3 3 1001 0001 dddd 0011 iiii iiii
+SUBB Rd, #data16 Subtract w/ borrow 16-bit imm data to reg 4 3 1001 1001 dddd 0011 iiii iiii iiii iiii
+SUBB [Rd], #data8 Subtract w/ borrow 8-bit imm data to reg-ind 3 4 1001 0010 0ddd 0011 iiii iiii
+SUBB [Rd], #data16 Subtract w/ borrow 16-bit imm data to reg-ind 4 4 1001 1010 0ddd 0011 iiii iiii iiii iiii
+SUBB [Rd+], #data8 Subtract w/ borrow 8-bit imm data to reg-ind w/ autoinc 3 5 1001 0011 0ddd 0011 iiii iiii
+SUBB [Rd+], #data16 Subtract w/ borrow 16-bit imm data to reg-ind w/ autoinc 4 5 1001 1011 0ddd 0011 iiii iiii iiii iiii
+SUBB [Rd+offset8], #data8 Subtract w/ borrow 8-bit imm data to reg-ind w/ 8-bit offs 4 6 1001 0100 0ddd 0011 oooo oooo iiii iiii
+SUBB [Rd+offset8], #data16 Subtract w/ borrow 16-bit imm data to reg-ind w/ 8-bit offs 5 6 1001 1100 0ddd 0011 oooo oooo iiii iiii iiii iiii
+SUBB [Rd+offset16], #data8 Subtract w/ borrow 8-bit imm data to reg-ind w/ 16-bit offs 5 6 1001 0101 0ddd 0011 oooo oooo oooo oooo iiii iiii
+SUBB [Rd+offset16], #data16 Subtract w/ borrow 16-bit imm data to reg-ind w/ 16-bit offs 6 6 1001 1101 0ddd 0011 oooo oooo oooo oooo iiii iiii iiii iiii
+SUBB direct, #data8 Subtract w/ borrow 8-bit imm data to mem 4 4 1001 0110 0DDD 0011 DDDD DDDD iiii iiii
+SUBB direct, #data16 Subtract w/ borrow 16-bit imm data to mem 5 4 1001 1110 0DDD 0011 DDDD DDDD iiii iiii iiii iiii
+
+CMP Rd, #data8 Compare 8-bit imm data to reg 3 3 1001 0001 dddd 0100 iiii iiii
+CMP Rd, #data16 Compare 16-bit imm data to reg 4 3 1001 1001 dddd 0100 iiii iiii iiii iiii
+CMP [Rd], #data8 Compare 8-bit imm data to reg-ind 3 4 1001 0010 0ddd 0100 iiii iiii
+CMP [Rd], #data16 Compare 16-bit imm data to reg-ind 4 4 1001 1010 0ddd 0100 iiii iiii iiii iiii
+CMP [Rd+], #data8 Compare 8-bit imm data to reg-ind w/ autoinc 3 5 1001 0011 0ddd 0100 iiii iiii
+CMP [Rd+], #data16 Compare 16-bit imm data to reg-ind w/ autoinc 4 5 1001 1011 0ddd 0100 iiii iiii iiii iiii
+CMP [Rd+offset8], #data8 Compare 8-bit imm data to reg-ind w/ 8-bit offs 4 6 1001 0100 0ddd 0100 oooo oooo iiii iiii
+CMP [Rd+offset8], #data16 Compare 16-bit imm data to reg-ind w/ 8-bit offs 5 6 1001 1100 0ddd 0100 oooo oooo iiii iiii iiii iiii
+CMP [Rd+offset16], #data8 Compare 8-bit imm data to reg-ind w/ 16-bit offs 5 6 1001 0101 0ddd 0100 oooo oooo oooo oooo iiii iiii
+CMP [Rd+offset16], #data16 Compare 16-bit imm data to reg-ind w/ 16-bit offs 6 6 1001 1101 0ddd 0100 oooo oooo oooo oooo iiii iiii iiii iiii
+CMP direct, #data8 Compare 8-bit imm data to mem 4 4 1001 0110 0DDD 0100 DDDD DDDD iiii iiii
+CMP direct, #data16 Compare 16-bit imm data to mem 5 4 1001 1110 0DDD 0100 DDDD DDDD iiii iiii iiii iiii
+
+AND Rd, #data8 Logical AND 8-bit imm data to reg 3 3 1001 0001 dddd 0101 iiii iiii
+AND Rd, #data16 Logical AND 16-bit imm data to reg 4 3 1001 1001 dddd 0101 iiii iiii iiii iiii
+AND [Rd], #data8 Logical AND 8-bit imm data to reg-ind 3 4 1001 0010 0ddd 0101 iiii iiii
+AND [Rd], #data16 Logical AND 16-bit imm data to reg-ind 4 4 1001 1010 0ddd 0101 iiii iiii iiii iiii
+AND [Rd+], #data8 Logical AND 8-bit imm data to reg-ind and autoinc 3 5 1001 0011 0ddd 0101 iiii iiii
+AND [Rd+], #data16 Logical AND 16-bit imm data to reg-ind and autoinc 4 5 1001 1011 0ddd 0101 iiii iiii iiii iiii
+AND [Rd+offset8], #data8 Logical AND 8-bit imm data to reg-ind w/ 8-bit offs 4 6 1001 0100 0ddd 0101 oooo oooo iiii iiii
+AND [Rd+offset8], #data16 Logical AND 16-bit imm data to reg-ind w/ 8-bit offs 5 6 1001 1100 0ddd 0101 oooo oooo iiii iiii iiii iiii
+AND [Rd+offset16], #data8 Logical AND 8-bit imm data to reg-ind w/ 16-bit offs 5 6 1001 0101 0ddd 0101 oooo oooo oooo oooo iiii iiii
+AND [Rd+offset16], #data16 Logical AND 16-bit imm data to reg-ind w/ 16-bit offs 6 6 1001 1101 0ddd 0101 oooo oooo oooo oooo iiii iiii iiii iiii
+AND direct, #data8 Logical AND 8-bit imm data to mem 4 4 1001 0110 0DDD 0101 DDDD DDDD iiii iiii
+AND direct, #data16 Logical AND 16-bit imm data to mem 5 4 1001 1110 0DDD 0101 DDDD DDDD iiii iiii iiii iiii
+
+OR Rd, #data8 Logical OR 8-bit imm data to reg 3 3 1001 0001 dddd 0110 iiii iiii
+OR Rd, #data16 Logical OR 16-bit imm data to reg 4 3 1001 1001 dddd 0110 iiii iiii iiii iiii
+OR [Rd], #data8 Logical OR 8-bit imm data to reg-ind 3 4 1001 0010 0ddd 0110 iiii iiii
+OR [Rd], #data16 Logical OR 16-bit imm data to reg-ind 4 4 1001 1010 0ddd 0110 iiii iiii iiii iiii
+OR [Rd+], #data8 Logical OR 8-bit imm data to reg-ind w/ autoinc 3 5 1001 0011 0ddd 0110 iiii iiii
+OR [Rd+], #data16 Logical OR 16-bit imm data to reg-ind w/ autoinc 4 5 1001 1011 0ddd 0110 iiii iiii iiii iiii
+OR [Rd+offset8], #data8 Logical OR 8-bit imm data to reg-ind w/ 8-bit offs 4 6 1001 0100 0ddd 0110 oooo oooo iiii iiii
+OR [Rd+offset8], #data16 Logical OR 16-bit imm data to reg-ind w/ 8-bit offs 5 6 1001 1100 0ddd 0110 oooo oooo iiii iiii iiii iiii
+OR [Rd+offset16], #data8 Logical OR 8-bit imm data to reg-ind w/ 16-bit offs 5 6 1001 0101 0ddd 0110 oooo oooo oooo oooo iiii iiii
+OR [Rd+offset16], #data16 Logical OR 16-bit imm data to reg-ind w/ 16-bit offs 6 6 1001 1101 0ddd 0110 oooo oooo oooo oooo iiii iiii iiii iiii
+OR direct, #data8 Logical OR 8-bit imm data to mem 4 4 1001 0110 0DDD 0110 DDDD DDDD iiii iiii
+OR direct, #data16 Logical OR 16-bit imm data to mem 5 4 1001 1110 0DDD 0110 DDDD DDDD iiii iiii iiii iiii
+
+XOR Rd, #data8 Logical XOR 8-bit imm data to reg 3 3 1001 0001 dddd 0111 iiii iiii
+XOR Rd, #data16 Logical XOR 16-bit imm data to reg 4 3 1001 1001 dddd 0111 iiii iiii iiii iiii
+XOR [Rd], #data8 Logical XOR 8-bit imm data to reg-ind 3 4 1001 0010 0ddd 0111 iiii iiii
+XOR [Rd], #data16 Logical XOR 16-bit imm data to reg-ind 4 4 1001 1010 0ddd 0111 iiii iiii iiii iiii
+XOR [Rd+], #data8 Logical XOR 8-bit imm data to reg-ind w/ autoinc 3 5 1001 0011 0ddd 0111 iiii iiii
+XOR [Rd+], #data16 Logical XOR 16-bit imm data to reg-ind w/ autoinc 4 5 1001 1011 0ddd 0111 iiii iiii iiii iiii
+XOR [Rd+offset8], #data8 Logical XOR 8-bit imm data to reg-ind w/ 8-bit offs 4 6 1001 0100 0ddd 0111 oooo oooo iiii iiii
+XOR [Rd+offset8], #data16 Logical XOR 16-bit imm data to reg-ind w/ 8-bit offs 5 6 1001 1100 0ddd 0111 oooo oooo iiii iiii iiii iiii
+XOR [Rd+offset16], #data8 Logical XOR 8-bit imm data to reg-ind w/ 16-bit offs 5 6 1001 0101 0ddd 0111 oooo oooo oooo oooo iiii iiii
+XOR [Rd+offset16], #data16 Logical XOR 16-bit imm data to reg-ind w/ 16-bit offs 6 6 1001 1101 0ddd 0111 oooo oooo oooo oooo iiii iiii iiii iiii
+XOR direct, #data8 Logical XOR 8-bit imm data to mem 4 4 1001 0110 0DDD 0111 DDDD DDDD iiii iiii
+XOR direct, #data16 Logical XOR 16-bit imm data to mem 5 4 1001 1110 0DDD 0111 DDDD DDDD iiii iiii iiii iiii
+
+MOV Rd, #data8 Move 8-bit imm data to reg 3 3 1001 0001 dddd 1000 iiii iiii
+MOV Rd, #data16 Move 16-bit imm data to reg 4 3 1001 1001 dddd 1000 iiii iiii iiii iiii
+MOV [Rd], #data8 Move 16-bit imm data to reg-ind 3 3 1001 0010 0ddd 1000 iiii iiii
+MOV [Rd], #data16 Move 16-bit imm data to reg-ind 4 3 1001 1010 0ddd 1000 iiii iiii iiii iiii
+MOV [Rd+], #data8 Move 8-bit imm data to reg-ind w/ autoinc 3 4 1001 0011 0ddd 1000 iiii iiii
+MOV [Rd+], #data16 Move 16-bit imm data to reg-ind w/ autoinc 4 4 1001 1011 0ddd 1000 iiii iiii iiii iiii
+MOV [Rd+offset8], #data8 Move 8-bit imm data to reg-ind w/ 8-bit offs 4 5 1001 0100 0ddd 1000 oooo oooo iiii iiii
+MOV [Rd+offset8], #data16 Move 16-bit imm data to reg-ind w/ 8-bit offs 5 5 1001 1100 0ddd 1000 oooo oooo iiii iiii iiii iiii
+MOV [Rd+offset16], #data8 Move 8-bit imm data to reg-ind w/ 16-bit offs 5 5 1001 0101 0ddd 1000 oooo oooo oooo oooo iiii iiii
+MOV [Rd+offset16], #data16 Move 16-bit imm data to reg-ind w/ 16-bit offs 6 5 1001 1101 0ddd 1000 oooo oooo oooo oooo iiii iiii iiii iiii
+MOV direct, #data8 Move 8-bit imm data to mem 4 3 1001 0110 0DDD 1000 DDDD DDDD iiii iiii
+MOV direct, #data16 Move 16-bit imm data to mem 5 3 1001 1110 0DDD 1000 DDDD DDDD iiii iiii iiii iiii
+*/
+int xa_dasm::d_alu(XA_DASM_PARAMS)
+{
+ const u8 op2 = opcodes.r8(pc++);
+ return handle_alu_type1(XA_CALL_PARAMS, op2);
+}
+
+/*
+MOV direct, direct Move mem to mem 4 4 1001 S111 0DDD 0ddd DDDD DDDD dddd dddd
+JB bit,rel8 Jump if bit set 4 10t/6nt 1001 0111 1000 00bb bbbb bbbb rrrr rrrr
+JNB bit,rel8 Jump if bit not set 4 10t/6nt 1001 0111 1010 00bb bbbb bbbb rrrr rrrr
+JBC bit,rel8 Jump if bit set and then clear the bit 4 11t/7nt 1001 0111 1100 00bb bbbb bbbb rrrr rrrr
+*/
+int xa_dasm::d_jb_mov_subgroup(XA_DASM_PARAMS)
+{
+ const u8 op2 = opcodes.r8(pc++);
+ const u8 op3 = opcodes.r8(pc++);
+ const u8 op4 = opcodes.r8(pc++);
+
+ if (op2 & 0x80)
+ {
+ int address = pc + ((s8)op4)*2;
+ int bit = ((op2 & 0x03) << 8) | op3;
+ address &= ~1; // must be word aligned
+
+ switch (op2 & 0x70)
+ {
+ case 0x00: util::stream_format(stream, "JB %s, $%02x", get_bittext(bit), address ); break;
+ case 0x20: util::stream_format(stream, "JNB %s, $%02x", get_bittext(bit), address ); break;
+ case 0x40: util::stream_format(stream, "JBC %s, $%02x", get_bittext(bit), address ); break;
+ default: util::stream_format(stream, "illegal %s $%02x", get_bittext(bit), address ); break;
+ }
+ }
+ else
+ {
+ int direct_dst = ((op2 & 0x70) << 4) | op3;
+ int direct_src = ((op2 & 0x07) << 8) | op4;
+ util::stream_format(stream, "MOV %s, %s", get_directtext(direct_dst), get_directtext(direct_src));
+ }
+
+ return 4;
+}
+
+// -------------------------------------- Group a --------------------------------------
+
+/*
+XCH Rd, direct Exchange contents of mem w/ a reg 3 6 1010 S000 dddd 1DDD DDDD DDDD
+
+MOV direct, [Rs] Move reg-ind to mem 3 4 1010 S000 1sss 0DDD DDDD DDDD
+MOV [Rd], direct Move mem to reg-ind 3 4 1010 S000 0ddd 0DDD DDDD DDDD
+*/
+int xa_dasm::d_movdir(XA_DASM_PARAMS)
+{
+ const u8 op2 = opcodes.r8(pc++);
+ const u8 op3 = opcodes.r8(pc++);
+ int size = op & 0x08;
+ const u16 direct = ((op2 & 0x07) << 8) | op3;
+
+ if (op2 & 0x08)
+ {
+ const u8 rd = op2 & (0xf0) >> 4;
+ const char** regnames = size ? m_regnames16 : m_regnames8;
+ util::stream_format(stream, "XCH%s %s, %s", size ? ".w" : ".b", regnames[rd], get_directtext(direct) );
+ return 3;
+ }
+ else
+ {
+ if (op2 & 0x80)
+ {
+ const u8 rs = op2 & (0x70) >> 4;
+ util::stream_format(stream, "MOV%s %s, [%s]", size ? ".w" : ".b", get_directtext(direct), m_regnames16[rs]);
+ return 3;
+ }
+ else
+ {
+ const u8 rd = op2 & (0x70) >> 4;
+ util::stream_format(stream, "MOV%s [%s], %s", size ? ".w" : ".b", m_regnames16[rd], get_directtext(direct));
+ return 3;
+ }
+ }
+
+ return 3;
+}
+
+/*
+ADDS Rd, #data4 Add 4-bit signed imm data to reg 2 3 1010 S001 dddd iiii
+ADDS [Rd], #data4 Add 4-bit signed imm data to reg-ind 2 4 1010 S010 0ddd iiii
+ADDS [Rd+], #data4 Add 4-bit signed imm data to reg-ind w/ autoinc 2 5 1010 S011 0ddd iiii
+ADDS [Rd+offset8], #data4 Add reg-ind w/ 8-bit offs to 4-bit signed imm data 3 6 1010 S100 0ddd iiii oooo oooo
+ADDS [Rd+offset16], #data4 Add reg-ind w/ 16-bit offs to 4-bit signed imm data 4 6 1010 S101 0ddd iiii oooo oooo oooo oooo
+ADDS direct, #data4 Add 4-bit signed imm data to mem 3 4 1010 S110 0DDD iiii DDDD DDDD
+*/
+int xa_dasm::d_adds(XA_DASM_PARAMS)
+{
+ return handle_adds_movs(XA_CALL_PARAMS, 0);
+}
+
+/*
+MOVX [Rd], Rs Move external data from reg to mem 2 6 1010 S111 ssss 1ddd
+MOVX Rd, [Rs] Move external data from mem to reg 2 6 1010 S111 dddd 0sss
+*/
+int xa_dasm::d_movx_subgroup(XA_DASM_PARAMS)
+{
+ const u8 op2 = opcodes.r8(pc++);
+ int size = op & 0x08;
+ const char** regnames = size ? m_regnames16 : m_regnames8;
+
+ if (op2 & 0x08)
+ {
+ const u8 rs = (op2 & 0xf0) >> 4;
+ const u8 rd = (op2 & 0x07);
+ util::stream_format(stream, "MOVX%s [%s], %s", size ? ".w" : ".b", m_regnames16[rd], regnames[rs]);
+ }
+ else
+ {
+ const u8 rd = (op2 & 0xf0) >> 4;
+ const u8 rs = (op2 & 0x07);
+ util::stream_format(stream, "MOVX%s %s, [%s]", size ? ".w" : ".b", regnames[rd], m_regnames16[rs]);
+ }
+ return 2;
+}
+
+// -------------------------------------- Group b --------------------------------------
+
+/*
+RR Rd, #data4 Rotate right reg by the 4-bit imm value 2 a* 1011 S000 dddd iiii
+*/
+int xa_dasm::d_rr(XA_DASM_PARAMS)
+{
+ const u8 op2 = opcodes.r8(pc++);
+ int size = op & 0x08;
+ const char** regnames = size ? m_regnames16 : m_regnames8;
+ const u8 rd = (op2 & 0xf0) >> 4;
+ const u8 data = rd & 0x0f;
+ util::stream_format(stream, "RR%s %s, %d", size ? ".w" : ".b", regnames[rd], data);
+ return 2;
+}
+
+/*
+MOVS Rd, #data4 Move 4-bit sign-extended imm data to reg 2 3 1011 S001 dddd iiii
+MOVS [Rd], #data4 Move 4-bit sign-extended imm data to reg-ind 2 3 1011 S010 0ddd iiii
+MOVS [Rd+], #data4 Move 4-bit sign-extended imm data to reg-ind w/ autoinc 2 4 1011 S011 0ddd iiii
+MOVS [Rd+offset8], #data4 Move reg-ind w/ 8-bit offs to 4-bit sign-extended imm data 3 5 1011 S100 0ddd iiii oooo oooo
+MOVS [Rd+offset16], #data4 Move reg-ind w/ 16-bit offs to 4-bit sign-extended imm data 4 5 1011 S101 0ddd iiii oooo oooo oooo oooo
+MOVS direct, #data4 Move 4-bit sign-extended imm data to mem 3 3 1011 S110 0DDD iiii DDDD DDDD
+*/
+int xa_dasm::d_movs(XA_DASM_PARAMS)
+{
+ return handle_adds_movs(XA_CALL_PARAMS, 1);
+}
+
+/*
+RRC Rd, #data4 Rotate right reg though carry by the 4-bit imm value 2 a* 1011 S111 dddd iiii
+*/
+int xa_dasm::d_rrc(XA_DASM_PARAMS)
+{
+ const u8 op2 = opcodes.r8(pc++);
+ int size = op & 0x08;
+ const char** regnames = size ? m_regnames16 : m_regnames8;
+ const u8 rd = (op2 & 0xf0) >> 4;
+ const u8 data = rd & 0x0f;
+ util::stream_format(stream, "RRC%s %s, %d", size ? ".w" : ".b", regnames[rd], data);
+
+ return 2;
+}
+
+
+// -------------------------------------- Group c --------------------------------------
+
+/*
+LSR Rd, Rs Logical right shift dest reg by the value in the src reg 2 a* 1100 SS00 dddd ssss
+FCALL addr24 Far call (full 24-bit address space) 4 12/8(PZ) 1100 0100 aaaa aaaa AAAA AAAA AAAA AAAA
+*/
+int xa_dasm::d_lsr_fc(XA_DASM_PARAMS)
+{
+ int size = op & 0x0c;
+ if (size == 0x04)
+ {
+ const u8 op2 = opcodes.r8(pc++);
+ const u8 op3 = opcodes.r8(pc++);
+ const u8 op4 = opcodes.r8(pc++);
+
+ const u32 addr = (op2 << 8) | op3 | (op4 << 16);
+
+ util::stream_format(stream, "FCALL $%06x", addr);
+
+ return 4;
+ }
+ else
+ {
+ const u8 op2 = opcodes.r8(pc++);
+ const char** regnames = ((size != 0) ? m_regnames16 : m_regnames8);
+ const u8 rd = (op2 & 0xf0) >> 4;
+ const u8 rs = (op2 & 0x0f);
+ util::stream_format(stream, "LSR %s, %s", regnames[rd], m_regnames8[rs]); // m_regnames8 or regnames for last param?
+ return 2;
+ }
+
+ return 1;
+}
+
+/*
+ASL Rd, Rs Logical left shift dest reg by the value in the src reg 2 a* 1100 SS01 dddd ssss
+CALL rel16 Relative call (range +/- 64K) 3 7/4(PZ) 1100 0101 rrrr rrrr rrrr rrrr
+*/
+int xa_dasm::d_asl_c(XA_DASM_PARAMS)
+{
+ int size = op & 0x0c;
+ if (size == 0x04)
+ {
+ const u8 op2 = opcodes.r8(pc++);
+ const u8 op3 = opcodes.r8(pc++);
+ u16 offset = (op2 << 8) | op3;
+ int address = pc + ((s16)offset)*2;
+ address &= ~1; // must be word aligned
+ util::stream_format(stream, "CALL $%04x", address);
+ return 3;
+ }
+ else
+ {
+ const u8 op2 = opcodes.r8(pc++);
+ const char** regnames = ((size != 0) ? m_regnames16 : m_regnames8);
+ const u8 rd = (op2 & 0xf0) >> 4;
+ const u8 rs = (op2 & 0x0f);
+ util::stream_format(stream, "ASL %s, %s", regnames[rd], m_regnames8[rs]); // m_regnames8 or regnames for last param? (check 03D4 in superkds)
+ return 2;
+ }
+ return 1;
+}
+
+/*
+ASR Rd, Rs Arithmetic shift right dest reg by the count in the src 2 a* 1100 SS10 dddd ssss
+CALL [Rs] Subroutine call ind w/ a reg 2 8/5(PZ) 1100 0110 0000 0sss
+*/
+int xa_dasm::d_asr_c(XA_DASM_PARAMS)
+{
+ int size = op & 0x0c;
+ if (size == 0x04)
+ {
+ const u8 op2 = opcodes.r8(pc++);
+ const u8 rs = op2 & 0x07;
+ util::stream_format(stream, "CALL [%s]", m_regnames16[rs]);
+ return 2;
+ }
+ else
+ {
+ const u8 op2 = opcodes.r8(pc++);
+ const char** regnames = ((size != 0) ? m_regnames16 : m_regnames8);
+ const u8 rd = (op2 & 0xf0) >> 4;
+ const u8 rs = (op2 & 0x0f);
+ util::stream_format(stream, "ASR %s, %s", regnames[rd], m_regnames8[rs]); // m_regnames8 or regnames for last param?
+ return 2;
+ }
+ return 1;
+}
+
+/*
+NORM Rd, Rs Logical shift left dest reg by the value in the src reg until MSB set 2 a* 1100 SS11 dddd ssss
+*/
+int xa_dasm::d_norm(XA_DASM_PARAMS)
+{
+ int size = op & 0x0c;
+ if (size == 0x04)
+ {
+ const u8 op2 = opcodes.r8(pc++);
+ util::stream_format(stream, "illegal %02x", op2);
+ return 2;
+ }
+ else
+ {
+ const u8 op2 = opcodes.r8(pc++);
+ int rd = (op2 & 0xf0) >> 4;
+ int rs = (op2 & 0x0f);
+ const char** regnames = ((size != 0) ? m_regnames16 : m_regnames8);
+ // doesn't have a #data5 mode like the other shifts?
+ util::stream_format(stream, "NORM%s %s, %s", m_dwparamsizes[size >> 2], regnames[rd], m_regnames8[rs]); // m_regnames8 or regnames for last param?
+ return 2;
+ }
+ return 2;
+}
+
+// -------------------------------------- Group d --------------------------------------
+
+/*
+LSR Rd, #data4 Logical right shift reg by the 4-bit imm value 2 a* 1101 SS00 dddd iiii
+LSR Rd, #data5 Logical right shift reg by the 4-bit imm value 2 a* 1101 1100 dddi iiii
+FJMP addr24 Far jump (full 24-bit address space) 4 6 1101 0100 aaaa aaaa AAAA AAAA AAAA AAAA
+*/
+int xa_dasm::d_lsr_fj(XA_DASM_PARAMS)
+{
+ int size = op & 0x0c;
+ if (size == 0x04)
+ {
+ const u8 op2 = opcodes.r8(pc++);
+ const u8 op3 = opcodes.r8(pc++);
+ const u8 op4 = opcodes.r8(pc++);
+ const u32 addr = (op2 << 8) | op3 | (op4 << 16);
+ util::stream_format(stream, "FJMP $%06x", addr);
+ return 4;
+ }
+ else
+ {
+ return handle_shift(XA_CALL_PARAMS, 2);
+ }
+ return 1;
+}
+
+/*
+ASL Rd, #data4 Logical left shift reg by the 4-bit imm value 2 a* 1101 SS01 dddd iiii
+ASL Rd, #data5 Logical left shift reg by the 5-bit imm value 2 a* 1101 1101 dddi iiii
+JMP rel16 Long unconditional branch 3 6 1101 0101 rrrr rrrr rrrr rrrr
+*/
+int xa_dasm::d_asl_j(XA_DASM_PARAMS)
+{
+ int size = op & 0x0c;
+ if (size == 0x04)
+ {
+ const u8 op2 = opcodes.r8(pc++);
+ const u8 op3 = opcodes.r8(pc++);
+ u16 offset = (op2 << 8) | op3;
+ int address = pc + ((s16)offset)*2;
+ address &= ~1; // must be word aligned
+ util::stream_format(stream, "JMP $%04x", address);
+ return 3;
+ }
+ else
+ {
+ return handle_shift(XA_CALL_PARAMS, 0);
+ }
+ return 1;
+}
+
+/*
+ASR Rd, #data4 Arithmetic shift right reg by the 4-bit imm count 2 a* 1101 SS10 dddd iiii
+ASR Rd, #data5 Arithmetic shift right reg by the 5-bit imm count 2 a* 1101 1110 dddi iiii
+RESET Causes a hardware Reset (same as external Reset) 2 18 1101 0110 0001 0000
+TRAP #data4 Causes 1 of 16 hardware traps to be executed 2 23/19(PZ) 1101 0110 0011 tttt
+JMP [A+DPTR] Jump ind relative to the DPTR 2 5 1101 0110 0100 0110
+JMP [[Rs+]] Jump double-ind to the address (pointer to a pointer) 2 8 1101 0110 0110 0sss
+JMP [Rs] Jump ind to the address in the reg (64K) 2 7 1101 0110 0111 0sss
+RET Return from subroutine 2 8/6(PZ) 1101 0110 1000 0000
+RETI Return from interrupt 2 10/8(PZ) 1101 0110 1001 0000
+*/
+int xa_dasm::d_asr_j(XA_DASM_PARAMS)
+{
+ int size = op & 0x0c;
+ const u8 op2 = opcodes.r8(pc++);
+ if (size == 0x04)
+ {
+ switch (op2 & 0xf0)
+ {
+ case 0x10: util::stream_format(stream, "RESET"); break;
+ case 0x30: util::stream_format(stream, "TRAP %d", op2 & 0x0f); break;
+ case 0x40: util::stream_format(stream, "JMP [A+DPTR]"); break;
+ case 0x60: util::stream_format(stream, "JMP [[%s+]]", m_regnames16[op2 & 0x07]); break;
+ case 0x70: util::stream_format(stream, "JMP [%s]", m_regnames16[op2 & 0x07]); break;
+ case 0x80: util::stream_format(stream, "RET"); break;
+ case 0x90: util::stream_format(stream, "RTI"); break;
+ default: util::stream_format(stream, "illegal"); break;
+ }
+ }
+ else
+ {
+ return handle_shift(XA_CALL_PARAMS, 1);
+ }
+ return 2;
+}
+
+/*
+RL Rd, #data4 Rotate left reg by the 4-bit imm value 2 a* 1101 S011 dddd iiii
+*/
+int xa_dasm::d_rl(XA_DASM_PARAMS)
+{
+ int size = op & 0x08;
+ const u8 op2 = opcodes.r8(pc++);
+ const char** regnames = size ? m_regnames16 : m_regnames8;
+ const u8 rd = (op2 & 0xf0) >> 4;
+ const u8 data4 = (op2 & 0x0f);
+ util::stream_format(stream, "RL%s %d, %d", size ? ".w" : ".b", regnames[rd], data4);
+ return 2;
+}
+
+/*
+RLC Rd, #data4 Rotate left reg though carry by the 4-bit imm value 2 a* 1101 S111 dddd iiii
+*/
+int xa_dasm::d_rlc(XA_DASM_PARAMS)
+{
+ int size = op & 0x08;
+ const u8 op2 = opcodes.r8(pc++);
+ const char** regnames = size ? m_regnames16 : m_regnames8;
+ const u8 rd = (op2 & 0xf0) >> 4;
+ const u8 data4 = (op2 & 0x0f);
+ util::stream_format(stream, "RLC%s Rd, %d", size ? ".w" : ".b", regnames[rd], data4);
+ return 2;
+}
+
+// -------------------------------------- Group e --------------------------------------
+
+/*
+DJNZ direct,rel8 Decrement mem and jump if not zero 4 9t/5nt 1110 S010 0000 1DDD DDDD DDDD rrrr rrrr
+CJNE Rd,direct,rel8 Compare dir byte to reg and jump if not equal 4 10t/7nt 1110 S010 dddd 0DDD DDDD DDDD rrrr rrrr
+*/
+int xa_dasm::d_djnz_cjne(XA_DASM_PARAMS)
+{
+ const u8 op2 = opcodes.r8(pc++);
+ const u8 op3 = opcodes.r8(pc++);
+ const u8 op4 = opcodes.r8(pc++);
+ int address = pc + ((s8)op4)*2;
+ address &= ~1; // must be word aligned
+ const u16 direct = ((op2 & 0x07) << 8) | op3;
+ if (op2 & 0x08)
+ {
+ util::stream_format(stream, "DJNZ %s, $%04x", get_directtext(direct), address);
+ }
+ else
+ {
+ int rd = (op2 & 0xf0) >> 4;
+ util::stream_format(stream, "CJNE %s, %s, $%04x", m_regnames16[rd], get_directtext(direct), address);
+ }
+ return 4;
+}
+
+/*
+MULU.b Rd, Rs 8X8 unsigned multiply of reg contents 2 12 1110 0000 dddd ssss
+*/
+int xa_dasm::d_mulu_b(XA_DASM_PARAMS)
+{
+ const u8 op2 = opcodes.r8(pc++);
+ const u8 rd = (op2 & 0xf0) >> 4;
+ const u8 rs = (op2 & 0x0f);
+ util::stream_format(stream, "MULU.b %s, %s", m_regnames8[rd], m_regnames8[rs]);
+ return 2;
+}
+
+/*
+DIVU.b Rd, Rs 8x8 unsigned reg divide 2 12 1110 0001 dddd ssss
+*/
+int xa_dasm::d_divu_b(XA_DASM_PARAMS)
+{
+ const u8 op2 = opcodes.r8(pc++);
+ const u8 rd = (op2 & 0xf0) >> 4;
+ const u8 rs = (op2 & 0x0f);
+ util::stream_format(stream, "DIVU.b %s, %s", m_regnames8[rd], m_regnames8[rs]);
+ return 2;
+}
+
+/*
+MULU.w Rd, Rs 16X16 unsigned reg multiply 2 12 1110 0100 dddd ssss
+*/
+int xa_dasm::d_mulu_w(XA_DASM_PARAMS)
+{
+ const u8 op2 = opcodes.r8(pc++);
+ const u8 rd = (op2 & 0xf0) >> 4;
+ const u8 rs = (op2 & 0x0f);
+ util::stream_format(stream, "MULU.w %s, %s", m_regnames16[rd], m_regnames16[rs]);
+ return 2;
+}
+
+/*
+DIVU.w Rd, Rs 16X8 unsigned reg divide 2 12 1110 0101 dddd ssss
+*/
+int xa_dasm::d_divu_w(XA_DASM_PARAMS)
+{
+ const u8 op2 = opcodes.r8(pc++);
+ const u8 rd = (op2 & 0xf0) >> 4;
+ const u8 rs = (op2 & 0x0f);
+ util::stream_format(stream, "DIVU.w %s, %s", m_regnames16[rd], m_regnames16[rs]);
+ return 2;
+}
+
+/*
+MUL.w Rd, Rs 16X16 signed multiply of reg contents 2 12 1110 0110 dddd ssss
+*/
+int xa_dasm::d_mul_w(XA_DASM_PARAMS)
+{
+ const u8 op2 = opcodes.r8(pc++);
+ const u8 rd = (op2 & 0xf0) >> 4;
+ const u8 rs = (op2 & 0x0f);
+ util::stream_format(stream, "MUL.w %s, %s", m_regnames16[rd], m_regnames16[rs]);
+ return 2;
+}
+
+/*
+DIV.w Rd, Rs 16x8 signed reg divide 2 14 1110 0111 dddd ssss
+*/
+int xa_dasm::d_div_w(XA_DASM_PARAMS)
+{
+ const u8 op2 = opcodes.r8(pc++);
+ const u8 rd = (op2 & 0xf0) >> 4;
+ const u8 rs = (op2 & 0x0f);
+ util::stream_format(stream, "DIV.w %s, %s", m_regnames16[rd], m_regnames16[rs]);
+ return 2;
+}
+
+/*
+DIV.w Rd, #data8 16x8 signed divide reg w/ imm word 3 14 1110 1000 dddd 1011 iiii iiii
+DIVU.b Rd, #data8 8X8 unsigned reg divide w/ imm byte 3 12 1110 1000 dddd 0001 iiii iiii
+DIVU.w Rd, #data8 16X8 unsigned reg divide w/ imm byte 3 12 1110 1000 dddd 0011 iiii iiii
+MULU.b Rd, #data8 8X8 unsigned multiply of 8-bit imm data w/ reg 3 12 1110 1000 dddd 0000 iiii iiii
+*/
+int xa_dasm::d_div_data8(XA_DASM_PARAMS)
+{
+ const u8 op2 = opcodes.r8(pc++);
+ const u8 op3 = opcodes.r8(pc++);
+ const u8 rd = (op2 & 0xf0) >> 4;
+
+ switch (op2 & 0x0f)
+ {
+ case 0x00:
+ {
+ util::stream_format(stream, "MULU.b %s, #$%02x", m_regnames8[rd], op3);
+ break;
+ }
+ case 0x01:
+ {
+ util::stream_format(stream, "DIVU.b %s, #$%02x", m_regnames8[rd], op3);
+ break;
+ }
+ case 0x03:
+ {
+ util::stream_format(stream, "DIVU.w %s, #$%02x", m_regnames8[rd], op3);
+ break;
+ }
+ case 0x0b:
+ {
+ util::stream_format(stream, "DIV.w %s, #$%02x", m_regnames8[rd], op3);
+ break;
+ }
+ default:
+ {
+ util::stream_format(stream, "illegal %s #$%02x", m_regnames8[rd], op3);
+ break;
+ }
+ }
+ return 3;
+}
+
+/*
+MULU.w Rd, #data16 16X16 unsigned multiply 16-bit imm data w/ reg 4 12 1110 1001 dddd 0000 iiii iiii iiii iiii
+MUL.w Rd, #data16 16X16 signed multiply 16-bit imm data w/ reg 4 12 1110 1001 dddd 1000 iiii iiii iiii iiii
+DIVU.d Rd, #data16 32X16 unsigned double reg divide w/ imm word 4 22 1110 1001 ddd0 0001 iiii iiii iiii iiii
+DIV.d Rd, #data16 32x16 signed double reg divide w/ imm word 4 24 1110 1001 ddd0 1001 iiii iiii iiii iiii
+*/
+int xa_dasm::d_div_d16(XA_DASM_PARAMS)
+{
+ const u8 op2 = opcodes.r8(pc++);
+ const u8 op3 = opcodes.r8(pc++);
+ const u8 op4 = opcodes.r8(pc++);
+ const u16 data = (op3 << 8) | op4;
+ switch (op2 & 0x0f)
+ {
+ case 0x00:
+ {
+ const u8 rd = (op2 & 0xf0) >> 4;
+ util::stream_format(stream, "MULU.w %s, #$%04x", m_regnames16[rd], data);
+ break;
+ }
+ case 0x01:
+ {
+ const u8 rd = (op2 & 0xe0) >> 4;
+ util::stream_format(stream, "DIVU.d %s, #$%04x", m_regnames16[rd], data);
+ break;
+ }
+ case 0x08:
+ {
+ const u8 rd = (op2 & 0xf0) >> 4;
+ util::stream_format(stream, "MUL.w %s, #$%04x", m_regnames16[rd], data);
+ break;
+ }
+ case 0x09:
+ {
+ const u8 rd = (op2 & 0xe0) >> 4;
+ util::stream_format(stream, "DIV.d %s, #$%04x", m_regnames16[rd], data);
+ break;
+ }
+ default:
+ {
+ const u8 rd = (op2 & 0xf0) >> 4;
+ util::stream_format(stream, "illegal %s, #$%04x", m_regnames16[rd], data);
+ break;
+ }
+ }
+ return 4;
+}
+
+/*
+DIVU.d Rd, Rs 32X16 unsigned double reg divide 2 22 1110 1101 ddd0 ssss
+*/
+int xa_dasm::d_divu_d(XA_DASM_PARAMS)
+{
+ const u8 op2 = opcodes.r8(pc++);
+ const u8 rd = (op2 & 0xe0) >> 4;
+ const u8 rs = (op2 & 0x0f);
+ util::stream_format(stream, "DIVU.d %s, %s", m_regnames16[rd], m_regnames16[rs]);
+ return 2;
+}
+
+/*
+DIV.d Rd, Rs 32x16 signed double reg divide 2 24 1110 1111 ddd0 ssss
+*/
+int xa_dasm::d_div_d(XA_DASM_PARAMS)
+{
+ const u8 op2 = opcodes.r8(pc++);
+ const u8 rd = (op2 & 0xe0) >> 4;
+ const u8 rs = (op2 & 0x0f);
+ util::stream_format(stream, "DIV.d %s, %s", m_regnames16[rd], m_regnames16[rs]);
+ return 2;
+}
+
+/*
+CJNE [Rd],#data8,rel8 Compare imm word to reg-ind and jump if not equal 4 10t/7nt 1110 0011 0ddd 1000 rrrr rrrr iiii iiii
+CJNE Rd,#data8,rel8 Compare imm byte to reg and jump if not equal 4 9t/6nt 1110 0011 dddd 0000 rrrr rrrr iiii iiii
+*/
+int xa_dasm::d_cjne_d8(XA_DASM_PARAMS)
+{
+ const u8 op2 = opcodes.r8(pc++);
+ const u8 op3 = opcodes.r8(pc++);
+ const u8 op4 = opcodes.r8(pc++);
+ int address = pc + ((s8)op3)*2;
+ address &= ~1; // must be word aligned
+ if (op2 & 0x08)
+ {
+ const u8 rd = (op2 & 0x70) >> 4;
+ util::stream_format(stream, "CJNE [%d], #$%02x, $%04x", m_regnames16[rd], op4, address);
+ }
+ else
+ {
+ const u8 rd = (op2 & 0xf0) >> 4;
+ util::stream_format(stream, "CJNE %d, #$%02x, $%04x", m_regnames8[rd], op4, address);
+ }
+ return 4;
+}
+
+/*
+CJNE [Rd],#data16,rel8 Compare imm word to reg-ind and jump if not equal 5 10t/7nt 1110 1011 0ddd 1000 rrrr rrrr iiii iiii iiii iiii
+CJNE Rd,#data16,rel8 Compare imm word to reg and jump if not equal 5 9t/6nt 1110 1011 dddd 0000 rrrr rrrr iiii iiii iiii iiii
+*/
+int xa_dasm::d_cjne_d16(XA_DASM_PARAMS)
+{
+ const u8 op2 = opcodes.r8(pc++);
+ const u8 op3 = opcodes.r8(pc++);
+ const u8 op4 = opcodes.r8(pc++);
+ const u8 op5 = opcodes.r8(pc++);
+ const u16 data = (op4 << 8) | op5;
+ int address = pc + ((s8)op3)*2;
+ address &= ~1; // must be word aligned
+ if (op2 & 0x08)
+ {
+ const u8 rd = (op2 & 0x70) >> 4;
+ util::stream_format(stream, "CJNE [%s], #$%04x, $%04x", m_regnames16[rd], data, address);
+ }
+ else
+ {
+ const u8 rd = (op2 & 0xf0) >> 4;
+ util::stream_format(stream, "CJNE %s, #$%04x, $%04x", m_regnames8[rd], data, address);
+ }
+ return 5;
+}
+
+/*
+JZ rel8 Jump if accumulator equals zero 2 6t/3nt 1110 1100 rrrr rrrr
+*/
+int xa_dasm::d_jz_rel8(XA_DASM_PARAMS)
+{
+ const u8 op2 = opcodes.r8(pc++);
+ int address = pc + ((s8)op2)*2;
+ address &= ~1; // must be word aligned
+ util::stream_format(stream, "JZ $%04x", address);
+ return 2;
+}
+
+/*
+JNZ rel8 Jump if accumulator not equal zero 2 6t/3nt 1110 1110 rrrr rrrr
+*/
+int xa_dasm::d_jnz_rel8(XA_DASM_PARAMS)
+{
+ const u8 op2 = opcodes.r8(pc++);
+ int address = pc + ((s8)op2)*2;
+ address &= ~1; // must be word aligned
+ util::stream_format(stream, "JNZ $%04x", address);
+ return 2;
+}
+
+
+// -------------------------------------- Group f --------------------------------------
+
+/*
+BCC rel8 Branch if the carry flag is clear 2 6t/3nt 1111 0000 rrrr rrrr
+BCS rel8 Branch if the carry flag is set 2 6t/3nt 1111 0001 rrrr rrrr
+BNE rel8 Branch if the zero flag is not set 2 6t/3nt 1111 0010 rrrr rrrr
+BEQ rel8 Branch if the zero flag is set 2 6t/3nt 1111 0011 rrrr rrrr
+BNV rel8 Branch if overflow flag is clear 2 6t/3nt 1111 0100 rrrr rrrr
+BOV rel8 Branch if overflow flag is set 2 6t/3nt 1111 0101 rrrr rrrr
+BPL rel8 Branch if the negative flag is clear 2 6t/3nt 1111 0110 rrrr rrrr
+BMI rel8 Branch if the negative flag is set 2 6t/3nt 1111 0111 rrrr rrrr
+BG rel8 Branch if greater than (unsigned) 2 6t/3nt 1111 1000 rrrr rrrr
+BL rel8 Branch if less than or equal to (unsigned) 2 6t/3nt 1111 1001 rrrr rrrr
+BGE rel8 Branch if greater than or equal to (signed) 2 6t/3nt 1111 1010 rrrr rrrr
+BLT rel8 Branch if less than (signed) 2 6t/3nt 1111 1011 rrrr rrrr
+BGT rel8 Branch if greater than (signed) 2 6t/3nt 1111 1100 rrrr rrrr
+BLE rel8 Branch if less than or equal to (signed) 2 6t/3nt 1111 1101 rrrr rrrr
+BR rel8 Short unconditional branch 2 6 1111 1110 rrrr rrrr
+*/
+int xa_dasm::d_branch(XA_DASM_PARAMS)
+{
+ const u8 op2 = opcodes.r8(pc++);
+ int address = pc + ((s8)op2)*2;
+ address &= ~1; // must be word aligned
+ util::stream_format(stream, "%s $%04x", m_branches[op & 0xf], address);
+ return 2;
+}
+
+/*
+BKPT Cause the breakpoint trap to be executed. 1 23/19(PZ) 1111 1111
+*/
+int xa_dasm::d_bkpt(XA_DASM_PARAMS)
+{
+ util::stream_format(stream, "BKPT");
+ return 1;
+}
+
+u32 xa_dasm::opcode_alignment() const
+{
+ return 1;
+}
+
+offs_t xa_dasm::disassemble(std::ostream& stream, offs_t pc, const data_buffer& opcodes, const data_buffer& params)
+{
+ const u8 op = opcodes.r8(pc++);
+
+ int size = (this->*s_instruction[op])(XA_CALL_PARAMS);
+
+ return size;
+}
+
diff --git a/src/devices/cpu/xa/xadasm.h b/src/devices/cpu/xa/xadasm.h
new file mode 100644
index 00000000000..a2c211e10f5
--- /dev/null
+++ b/src/devices/cpu/xa/xadasm.h
@@ -0,0 +1,121 @@
+// license:BSD-3-Clause
+// copyright-holders:David Haywood
+
+#ifndef MAME_CPU_XA_XADASM_H
+#define MAME_CPU_XA_XADASM_H
+
+#pragma once
+
+#define XA_DASM_PARAMS uint8_t op, std::ostream& stream, offs_t pc, const data_buffer& opcodes, const data_buffer& params
+#define XA_CALL_PARAMS op, stream, pc, opcodes, params
+
+class xa_dasm : public util::disasm_interface
+{
+public:
+ xa_dasm()
+ {
+ add_names(default_names);
+ };
+
+ virtual ~xa_dasm() = default;
+
+private:
+
+ struct mem_info {
+ int addr;
+ const char *name;
+ };
+
+ static const mem_info default_names[];
+ void add_names(const mem_info *info);
+
+ std::string get_data_address(u16 arg) const;
+
+ 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;
+
+ typedef int (xa_dasm::*op_func) (XA_DASM_PARAMS);
+ static const op_func s_instruction[256];
+
+ const char* m_regnames16[16] = { "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7", "illegal", "illegal", "illegal", "illegal", "illegal", "illegal", "illegal", "illegal" };
+ const char* m_regnames8[16] = { "R0L", "R0H", "R1L", "R1H", "R2L", "R2H", "R3L", "R3H", "R4L", "R4H", "R5L", "R5H", "R6L", "R6H", "R7L", "R7H"};
+ const char* m_aluops[16] = { "ADD", "ADDC", "SUB", "SUBC", "CMP", "AND", "OR", "XOR", "MOV", "illegal ALU 0x09", "illegal ALU 0x0a", "illegal ALU 0x0b", "illegal ALU 0x0c", "illegal ALU 0x0d", "illegal ALU 0x0e", "illegal ALU 0x0f"};
+ const char* m_branches[15] = { "BCC", "BCS", "BNE", "BEQ", "BNV", "BOV", "BPL", "BMI", "BG", "BL", "BGE", "BLT", "BGT", "BLE", "BR" };
+ const char* m_addsmovs[2] = { "ADDS", "MOVS" };
+ const char* m_pushpull[4] = { "PUSH", "PUSHU", "POP", "POPU" };
+ const char* m_shifts[3] = { "ASL", "ASR", "LSR" };
+ const char* m_dwparamsizes[4] = { ".b", "invalid", ".w", ".dw" };
+
+ std::string get_bittext(int bit);
+ std::string get_directtext(int bit);
+ std::string show_expanded_data4(u16 data4, int size);
+
+ int handle_alu_type0(XA_DASM_PARAMS, int alu_op);
+ int handle_alu_type1(XA_DASM_PARAMS, uint8_t op2);
+ int handle_pushpop_rlist(XA_DASM_PARAMS, int type);
+ int handle_adds_movs(XA_DASM_PARAMS, int which);
+ int handle_shift(XA_DASM_PARAMS, int shift_type);
+
+ int d_illegal(XA_DASM_PARAMS);
+
+ int d_nop(XA_DASM_PARAMS);
+ int d_bitgroup(XA_DASM_PARAMS);
+ int d_add(XA_DASM_PARAMS);
+ int d_push_rlist(XA_DASM_PARAMS);
+ int d_addc(XA_DASM_PARAMS);
+ int d_pushu_rlist(XA_DASM_PARAMS);
+ int d_sub(XA_DASM_PARAMS);
+ int d_pop_rlist(XA_DASM_PARAMS);
+ int d_subb(XA_DASM_PARAMS);
+ int d_popu_rlist(XA_DASM_PARAMS);
+ int d_lea_offset8(XA_DASM_PARAMS);
+ int d_lea_offset16(XA_DASM_PARAMS);
+ int d_cmp(XA_DASM_PARAMS);
+ int d_xch_type1(XA_DASM_PARAMS);
+ int d_and(XA_DASM_PARAMS);
+ int d_xch_type2(XA_DASM_PARAMS);
+ int d_or(XA_DASM_PARAMS);
+ int d_xor(XA_DASM_PARAMS);
+ int d_movc_rd_rsinc(XA_DASM_PARAMS);
+ int d_mov(XA_DASM_PARAMS);
+ int d_pushpop_djnz_subgroup(XA_DASM_PARAMS);
+ int d_g9_subgroup(XA_DASM_PARAMS);
+ int d_alu(XA_DASM_PARAMS);
+ int d_jb_mov_subgroup(XA_DASM_PARAMS);
+ int d_movdir(XA_DASM_PARAMS);
+ int d_adds(XA_DASM_PARAMS);
+ int d_movx_subgroup(XA_DASM_PARAMS);
+ int d_rr(XA_DASM_PARAMS);
+ int d_movs(XA_DASM_PARAMS);
+ int d_rrc(XA_DASM_PARAMS);
+ int d_lsr_fc(XA_DASM_PARAMS);
+ int d_asl_c(XA_DASM_PARAMS);
+ int d_asr_c(XA_DASM_PARAMS);
+ int d_norm(XA_DASM_PARAMS);
+ int d_lsr_fj(XA_DASM_PARAMS);
+ int d_asl_j(XA_DASM_PARAMS);
+ int d_asr_j(XA_DASM_PARAMS);
+ int d_rl(XA_DASM_PARAMS);
+ int d_rlc(XA_DASM_PARAMS);
+ int d_djnz_cjne(XA_DASM_PARAMS);
+ int d_mulu_b(XA_DASM_PARAMS);
+ int d_divu_b(XA_DASM_PARAMS);
+ int d_mulu_w(XA_DASM_PARAMS);
+ int d_divu_w(XA_DASM_PARAMS);
+ int d_mul_w(XA_DASM_PARAMS);
+ int d_div_w(XA_DASM_PARAMS);
+ int d_div_data8(XA_DASM_PARAMS);
+ int d_div_d16(XA_DASM_PARAMS);
+ int d_divu_d(XA_DASM_PARAMS);
+ int d_div_d(XA_DASM_PARAMS);
+ int d_cjne_d8(XA_DASM_PARAMS);
+ int d_cjne_d16(XA_DASM_PARAMS);
+ int d_jz_rel8(XA_DASM_PARAMS);
+ int d_jnz_rel8(XA_DASM_PARAMS);
+ int d_branch(XA_DASM_PARAMS);
+ int d_bkpt(XA_DASM_PARAMS);
+
+ std::unordered_map<offs_t, const char *> m_names;
+};
+
+#endif // MAME_CPU_XA_XADASM_H
diff --git a/src/mame/igs/igs_fear.cpp b/src/mame/igs/igs_fear.cpp
index a5f3061be0f..3689010fcac 100644
--- a/src/mame/igs/igs_fear.cpp
+++ b/src/mame/igs/igs_fear.cpp
@@ -4,6 +4,7 @@
#include "emu.h"
#include "cpu/arm7/arm7.h"
#include "cpu/arm7/arm7core.h"
+#include "cpu/xa/xa.h"
#include "machine/nvram.h"
#include "pgmcrypt.h"
#include "sound/ics2115.h"
@@ -19,6 +20,7 @@ public:
igs_fear_state(const machine_config &mconfig, device_type type, const char *tag) :
driver_device(mconfig, type, tag),
m_maincpu(*this, "maincpu"),
+ m_xa(*this, "xa"),
m_videoram(*this, "videoram"),
m_palette(*this, "palette"),
m_gfxrom(*this, "gfx1")
@@ -34,6 +36,7 @@ protected:
private:
required_device<cpu_device> m_maincpu;
+ required_device<xa_cpu_device> m_xa;
required_shared_ptr<uint32_t> m_videoram;
required_device<palette_device> m_palette;
required_region_ptr<uint8_t> m_gfxrom;
@@ -132,7 +135,7 @@ void igs_fear_state::igs_fear(machine_config &config)
ARM7(config, m_maincpu, 50000000/2);
m_maincpu->set_addrmap(AS_PROGRAM, &igs_fear_state::main_map);
- // MX10EXAQC (Philips 80C51 XA)
+ MX10EXA(config, m_xa, 10000000); // MX10EXAQC (Philips 80C51 XA) unknown frequency
screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
screen.set_refresh_hz(60);
@@ -161,7 +164,7 @@ ROM_START( fearless )
ROM_REGION32_LE( 0x80000, "user1", 0 ) // external ARM data / prg
ROM_LOAD( "fearlessp_v-101us.u37", 0x000000, 0x80000, CRC(2522873c) SHA1(8db709877311b6d2796353fc9a44a820937e35c2) )
- ROM_REGION( 0x10000, "plcc", 0 ) // MX10EXAQC (80C51 XA based MCU) marked 07, not read protected
+ ROM_REGION( 0x10000, "xa", 0 ) // MX10EXAQC (80C51 XA based MCU) marked 07, not read protected
ROM_LOAD( "fearlessp_07.u33", 0x000000, 0x10000, CRC(7dae4900) SHA1(bbf7ba7c9e95ff2ffeb1dc0fc7ccedd4da274d01) )
ROM_REGION( 0x3000000, "gfx1", 0 ) // FIXED BITS (0xxxxxxx) (graphics are 7bpp)
@@ -184,7 +187,7 @@ ROM_START( superkds )
ROM_REGION32_LE( 0x80000, "user1", 0 ) // external ARM data / prg
ROM_LOAD( "superkids_s019cn.u37", 0x000000, 0x80000, CRC(1a7f17dd) SHA1(ba20c0f521bff2f5ae2103ea49bd413b0e6459ba) )
- ROM_REGION( 0x10000, "plcc", 0 ) // MX10EXAQC (80C51 XA based MCU) marked 07, not read protected
+ ROM_REGION( 0x10000, "xa", 0 ) // MX10EXAQC (80C51 XA based MCU) marked 07, not read protected
ROM_LOAD( "superkids_mx10exa.u33", 0x000000, 0x10000, CRC(8baf5ba2) SHA1(2f8c2c48e756264e593bce7c09260e50d5cac827) ) // sticker marked G6
ROM_REGION( 0x2000000, "gfx1", 0 ) // FIXED BITS (0xxxxxxx) (graphics are 7bpp)
diff --git a/src/mame/igs/igs_m027.cpp b/src/mame/igs/igs_m027.cpp
index fa56ea2e26c..b1f8c02d463 100644
--- a/src/mame/igs/igs_m027.cpp
+++ b/src/mame/igs/igs_m027.cpp
@@ -29,6 +29,8 @@
#include "cpu/arm7/arm7.h"
#include "cpu/arm7/arm7core.h"
+#include "cpu/xa/xa.h"
+
#include "machine/nvram.h"
#include "screen.h"
@@ -43,10 +45,12 @@ public:
driver_device(mconfig, type, tag),
m_igs_mainram(*this, "igs_mainram"),
m_maincpu(*this, "maincpu"),
+ m_xa(*this, "xa"),
m_igs017_igs031(*this, "igs017_igs031")
{ }
void igs_mahjong(machine_config &config);
+ void igs_mahjong_xa(machine_config &config);
void init_sdwx();
void init_chessc2();
@@ -73,6 +77,7 @@ protected:
private:
optional_shared_ptr<u32> m_igs_mainram;
required_device<cpu_device> m_maincpu;
+ optional_device<xa_cpu_device> m_xa;
required_device<igs017_igs031_device> m_igs017_igs031;
void vblank_irq(int state);
@@ -354,6 +359,13 @@ void igs_m027_state::igs_mahjong(machine_config &config)
// OK6295
}
+void igs_m027_state::igs_mahjong_xa(machine_config &config)
+{
+ igs_mahjong(config);
+
+ MX10EXA(config, m_xa, 10000000); // MX10EXAQC (Philips 80C51 XA) unknown frequency
+}
+
/***************************************************************************
@@ -907,7 +919,7 @@ ROM_START( haunthig ) // IGS PCB-0575-04-HU - Has IGS027A, MX10EXAQC, IGS031, Ok
ROM_REGION32_LE( 0x80000, "user1", 0 ) // external ARM data / prg
ROM_LOAD( "hauntedhouse_ver-101us.u34", 0x000000, 0x80000, CRC(4bf045d4) SHA1(78c848fd69961df8d9b75f92ad57c3534fbf08db) )
- ROM_REGION( 0x10000, "plcc", 0 )
+ ROM_REGION( 0x10000, "xa", 0 )
ROM_LOAD( "hauntedhouse.u17", 0x000000, 0x10000, CRC(3c76b157) SHA1(d8d3a434fd649577a30d5855e3fb34998041f4e5) ) // MX10EXAQC (80C51 XA based MCU) marked J9, not read protected?
ROM_REGION( 0x80000, "igs017_igs031:tilemaps", 0 )
@@ -918,7 +930,7 @@ ROM_START( haunthig ) // IGS PCB-0575-04-HU - Has IGS027A, MX10EXAQC, IGS031, Ok
ROM_LOAD( "haunted-h_cg.u32", 0x000000, 0x400000, CRC(e0ea10e6) SHA1(e81be78fea93e72d4b1f4c0b58560bda46cf7948) ) // FIXED BITS (xxxxxxx0xxxxxxxx)
ROM_LOAD( "haunted-h_ext.u12", 0x400000, 0x400000, CRC(662eb883) SHA1(831ebe29e1e7a8b2c2fff7fbc608975771c3486c) ) // FIXED BITS (xxxxxxxx0xxxxxxx)
- ROM_REGION( 0x200000, "samples", 0 ) // samples, but not OKI? possibly ICS? PCB only has an Oki M6295 though. Maybe scrambled ROM?
+ ROM_REGION( 0x200000, "samples", 0 ) // Oki M6295 samples, missing sample table, bad?
ROM_LOAD( "haunted-h_sp.u3", 0x00000, 0x200000, CRC(fe3fcddf) SHA1(ac57ab6d4e4883747c093bd19d0025cf6588cb2c) )
ROM_REGION( 0x500, "plds", ROMREGION_ERASE00 )
@@ -934,7 +946,7 @@ ROM_START( crzybugs ) // IGS PCB-0575-04-HU - Has IGS027A, MX10EXAQC, IGS031, Ok
ROM_REGION32_LE( 0x200000, "user1", 0 ) // external ARM data / prg
ROM_LOAD( "cray_bugs_v-103jp.u34", 0x000000, 0x200000, CRC(1e35ed79) SHA1(0e4f8b706cdfcaf2aacdc40eec422df9d865b311) )
- ROM_REGION( 0x10000, "plcc", 0 )
+ ROM_REGION( 0x10000, "xa", 0 )
ROM_LOAD( "e9.u17", 0x00000, 0x10000, CRC(3c76b157) SHA1(d8d3a434fd649577a30d5855e3fb34998041f4e5) ) // MX10EXAQC (80C51 XA based MCU) marked E9, same as haunthig
ROM_REGION( 0x80000, "igs017_igs031:tilemaps", 0 )
@@ -1236,8 +1248,12 @@ GAME( 200?, klxyj, 0, igs_mahjong, sdwx, igs_m027_state, init_klx
GAME( 2000, mgfx, 0, igs_mahjong, sdwx, igs_m027_state, init_mgfx, ROT0, "IGS", "Man Guan Fu Xing", MACHINE_IS_SKELETON )
GAME( 200?, gonefsh2, 0, igs_mahjong, sdwx, igs_m027_state, init_gonefsh2, ROT0, "IGS", "Gone Fishing 2", MACHINE_IS_SKELETON )
GAME( 2002, chessc2, 0, igs_mahjong, sdwx, igs_m027_state, init_chessc2, ROT0, "IGS", "Chess Challenge II", MACHINE_IS_SKELETON )
-GAME( 2006, haunthig, 0, igs_mahjong, sdwx, igs_m027_state, init_hauntedh, ROT0, "IGS", "Haunted House (IGS)", MACHINE_IS_SKELETON )
GAME( 200?, extradrw, 0, igs_mahjong, sdwx, igs_m027_state, init_qlgs, ROT0, "IGS", "Extra Draw", MACHINE_IS_SKELETON )
-GAME( 2007, crzybugs, 0, igs_mahjong, sdwx, igs_m027_state, init_crzybugs, ROT0, "IGS", "Crazy Bugs (V103JP)", MACHINE_IS_SKELETON )
GAME( 2003, mgzz, 0, igs_mahjong, sdwx, igs_m027_state, init_mgzz, ROT0, "IGS", "Man Guan Zhi Zun (V100CN)", MACHINE_IS_SKELETON )
GAME( 2007, mgcs3, 0, igs_mahjong, sdwx, igs_m027_state, init_mgcs3, ROT0, "IGS", "Man Guan Caishen 3 (V101CN)", MACHINE_IS_SKELETON )
+
+// These use the MX10EXAQC (80c51XA from Philips) and maybe don't belong in here
+// the PCBs are closer to igs_fear.cpp in terms of layout
+GAME( 2006, haunthig, 0, igs_mahjong_xa, sdwx, igs_m027_state, init_hauntedh, ROT0, "IGS", "Haunted House (IGS)", MACHINE_IS_SKELETON )
+GAME( 2007, crzybugs, 0, igs_mahjong_xa, sdwx, igs_m027_state, init_crzybugs, ROT0, "IGS", "Crazy Bugs (V103JP)", MACHINE_IS_SKELETON )
+
diff --git a/src/tools/unidasm.cpp b/src/tools/unidasm.cpp
index cf7b5c979e3..da562db857b 100644
--- a/src/tools/unidasm.cpp
+++ b/src/tools/unidasm.cpp
@@ -209,6 +209,7 @@ using util::BIT;
#include "cpu/vt50/vt50dasm.h"
#include "cpu/vt61/vt61dasm.h"
#include "cpu/we32000/we32100d.h"
+#include "cpu/xa/xadasm.h"
#include "cpu/xavix2/xavix2d.h"
#include "cpu/xtensa/xtensad.h"
#include "cpu/z180/z180dasm.h"
@@ -724,6 +725,7 @@ static const dasm_table_entry dasm_table[] =
{ "x86_16", le, 0, []() -> util::disasm_interface * { i386_unidasm.mode = 16; return new i386_disassembler(&i386_unidasm); } },
{ "x86_32", le, 0, []() -> util::disasm_interface * { i386_unidasm.mode = 32; return new i386_disassembler(&i386_unidasm); } },
{ "x86_64", le, 0, []() -> util::disasm_interface * { i386_unidasm.mode = 64; return new i386_disassembler(&i386_unidasm); } },
+ { "xa", le, 0, []() -> util::disasm_interface * { return new xa_dasm; } },
{ "xavix", le, 0, []() -> util::disasm_interface * { return new xavix_disassembler; } },
{ "xavix2000", le, 0, []() -> util::disasm_interface * { return new xavix2000_disassembler; } },
{ "xavix2", le, 0, []() -> util::disasm_interface * { return new xavix2_disassembler; } },