From a1b2974ec91402e5e55d2f179abc850da8b49178 Mon Sep 17 00:00:00 2001 From: mamehaze <140764005+mamehaze@users.noreply.github.com> Date: Fri, 26 Jul 2024 13:09:30 +0100 Subject: cpu/xa: CPU core work for fearless/superkds - adds sound, promotes to working (#12617) * This adds basic execution to XA core. It emulates enough of the XA to give fearless and superkds working sound. * only the exact forms of the opcodes used so far have been implemented * no optimizations have been done, use of const, inline use, templates etc. are planned for a future update; code is still primed for debugging and development * overall structure, code style are not 100% final (see above) and will be adjusted as the CPU is better understood * peripherals, interrupts etc. are not yet fully implemented, nor is anything outside of the page zero mode used here due to lack of test cases Machines Promoted to WORKING ---------------------------------- Super Kids (S019CN) [David Haywood, XingXing] Fearless Pinocchio (V101US) [David Haywood, XingXing, Peter Wilhelmsen, rtw] --------- Co-authored-by: David Haywood --- scripts/src/cpu.lua | 1 + src/devices/cpu/xa/xa.cpp | 2608 ++++++++++++++++++++++++++++++++++++++++- src/devices/cpu/xa/xa.h | 926 ++++++++++++++- src/devices/cpu/xa/xa_ops.cpp | 1893 ++++++++++++++++++++++++++++++ src/devices/cpu/xa/xadasm.cpp | 164 +-- src/devices/cpu/xa/xadasm.h | 6 +- src/devices/sound/ics2115.cpp | 10 +- src/mame/igs/igs_fear.cpp | 304 ++++- src/mame/igs/igs_m027.cpp | 2 +- 9 files changed, 5763 insertions(+), 151 deletions(-) create mode 100644 src/devices/cpu/xa/xa_ops.cpp diff --git a/scripts/src/cpu.lua b/scripts/src/cpu.lua index e88a2c94716..85de8acd3c8 100644 --- a/scripts/src/cpu.lua +++ b/scripts/src/cpu.lua @@ -1209,6 +1209,7 @@ end if CPUS["XA"] then files { MAME_DIR .. "src/devices/cpu/xa/xa.cpp", + MAME_DIR .. "src/devices/cpu/xa/xa_ops.cpp", MAME_DIR .. "src/devices/cpu/xa/xa.h", } end diff --git a/src/devices/cpu/xa/xa.cpp b/src/devices/cpu/xa/xa.cpp index ab1ccf34dfb..e02344e4ac1 100644 --- a/src/devices/cpu/xa/xa.cpp +++ b/src/devices/cpu/xa/xa.cpp @@ -14,40 +14,262 @@ #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") - - +#define LOG_DEBUG (1U << 1) +#define VERBOSE (0) +#include "logmacro.h" +DEFINE_DEVICE_TYPE(XA, xa_cpu, "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) +xa_cpu::xa_cpu(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, address_map_constructor prg_map, address_map_constructor dat_map) : cpu_device(mconfig, type, tag, owner, clock) - , m_program_config("data", ENDIANNESS_LITTLE, 16, 24, 0, prg_map) + , m_program_config("program", ENDIANNESS_LITTLE, 16, 24, 0, prg_map) + , m_data_config("data", ENDIANNESS_LITTLE, 16, 24, 0, dat_map) + , m_sfr_config("sfr", ENDIANNESS_LITTLE, 8, 11, 0, address_map_constructor(FUNC(xa_cpu::sfr_map), this)) , m_pc(0) , m_program(nullptr) + , m_data(nullptr) + , m_sfr(nullptr) , m_icount(0) + , m_port_in_cb(*this, 0xff) + , m_port_out_cb(*this) { + add_names(default_names); } -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)) +xa_cpu::xa_cpu(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : xa_cpu(mconfig, XA, tag, owner, clock, address_map_constructor(FUNC(xa_cpu::internal_map), this), address_map_constructor(FUNC(xa_cpu::internal_data_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)) + : xa_cpu(mconfig, MX10EXA, tag, owner, clock, address_map_constructor(FUNC(mx10exa_cpu_device::mx10exa_internal_map), this), address_map_constructor(FUNC(mx10exa_cpu_device::mx10exa_internal_data_map), this)) { } -std::unique_ptr xa_cpu_device::create_disassembler() +std::unique_ptr xa_cpu::create_disassembler() { return std::make_unique(); } /*****************************************************************************/ -void xa_cpu_device::internal_map(address_map &map) +u8 xa_cpu::sfr_port_r(offs_t offset) +{ + return m_port_in_cb[offset](); +} + +void xa_cpu::sfr_port_w(offs_t offset, u8 data) +{ + m_port_out_cb[offset](data); +} + +u8 xa_cpu::sfr_PxCFGA_r(offs_t offset) +{ + return m_PxCFGA[offset]; +} + +void xa_cpu::sfr_PxCFGA_w(offs_t offset, u8 data) +{ + LOGMASKED(LOG_DEBUG, "P%d CFGA - Port Configuration A write %02x\n", offset, data); + m_PxCFGA[offset] = data; +} + +u8 xa_cpu::sfr_PxCFGB_r(offs_t offset) +{ + return m_PxCFGB[offset]; +} + +void xa_cpu::sfr_PxCFGB_w(offs_t offset, u8 data) +{ + LOGMASKED(LOG_DEBUG, "P%d CFGB - Port Configuration B write %02x\n", offset, data); + m_PxCFGB[offset] = data; +} + + + +void xa_cpu::set_pc_in_current_page(u16 addr) +{ + m_pc = addr; +} + +u8 xa_cpu::sfr_WDCON_r() +{ + return m_WDCON; +} + +// PSWL C AC - - - V N Z +u8 xa_cpu::sfr_PSWL_r() +{ + u8 ret = m_PSWL & 0x38; + if (get_z_flag()) ret |= 0x01; + if (get_n_flag()) ret |= 0x02; + if (get_v_flag()) ret |= 0x04; + if (get_ac_flag()) ret |= 0x40; + if (get_c_flag()) ret |= 0x80; + LOGMASKED(LOG_DEBUG, "read %02x from PSWL\n", ret); + return ret; +} + +void xa_cpu::sfr_PSWL_w(u8 data) +{ + LOGMASKED(LOG_DEBUG, "write %02x to PSWL\n", data); + m_PSWL = data; + if (data & 0x01) set_z_flag(); else clear_z_flag(); + if (data & 0x02) set_n_flag(); else clear_n_flag(); + if (data & 0x04) set_v_flag(); else clear_v_flag(); + if (data & 0x40) set_ac_flag(); else clear_ac_flag(); + if (data & 0x80) set_c_flag(); else clear_c_flag(); +} + +u8 xa_cpu::sfr_PSWH_r() +{ + u8 ret = m_PSWH; + LOGMASKED(LOG_DEBUG, "read %02x from PSWH\n", ret); + return m_PSWH; +} + +void xa_cpu::sfr_PSWH_w(u8 data) +{ + // PSWH SM TM RS1 RS0 IM3 IM2 IM1 IM0 + LOGMASKED(LOG_DEBUG, "write %02x to PSWH\n", data); + m_PSWH = data; + + if (m_PSWH & 0x80) + m_usermode = false; + else + m_usermode = true; + + m_regbank = (m_PSWH & 0x30) >> 4; + +} + +void xa_cpu::sfr_PSW51_w(u8 data) +{ + // PSW51 C AC F0 RS1 RS0 OV F1 P + +} + +u8 xa_cpu::sfr_IEL_r() +{ + return m_IEL; +} + +void xa_cpu::sfr_IEL_w(u8 data) +{ + m_IEL = data; + LOGMASKED(LOG_DEBUG, "write to m_IEL %02x\n", data); +} + +void xa_cpu::sfr_SCR_w(u8 data) +{ + /* System Configuration Register (SCR) + + ---- PPCZ + + PP = PT0/1: Peripheral timer multiplier + C = CM: 80c51 Compatibility Mode (registers appear in data memory, indirect addressing behavior changed) + Z = Page Zero / Small Memory mode (only 16-bits of address are pushed / pulled from stack, faster timing on those ops) + + */ + + LOGMASKED(LOG_DEBUG, "write %02x to SCR\n", data); + m_SCR = data; + m_pagezeromode = (data & 1); +} + +void xa_cpu::sfr_WFEED1_w(u8 data) +{ + LOGMASKED(LOG_DEBUG, "write %02x to WFEED1\n", data); +} + +void xa_cpu::sfr_WFEED2_w(u8 data) +{ + LOGMASKED(LOG_DEBUG, "write %02x to WFEED2\n", data); +} + +/*****************************************************************************/ + +void xa_cpu::data_map(address_map &map) +{ +} + +void xa_cpu::sfr_map(address_map &map) +{ + map(0x000, 0x000).rw(FUNC(xa_cpu::sfr_PSWL_r), FUNC(xa_cpu::sfr_PSWL_w)); + map(0x001, 0x001).rw(FUNC(xa_cpu::sfr_PSWH_r), FUNC(xa_cpu::sfr_PSWH_w)); + map(0x002, 0x002).w(FUNC(xa_cpu::sfr_PSW51_w)); + + //0x003, "SSEL" + //0x004, "PCON" + //0x010, "TCON" + //0x011, "TSTAT" + //0x018, "T2CON" + //0x019, "T2MOD" + + map(0x01f, 0x01f).r(FUNC(xa_cpu::sfr_WDCON_r)); + + //0x020, "S0CON" + //0x021, "S0STAT" + //0x024, "S1CON" + //0x025, "S1STAT" + + map(0x026, 0x026).rw(FUNC(xa_cpu::sfr_IEL_r), FUNC(xa_cpu::sfr_IEL_w)); + + //0x027, "IEH" + //0x02A, "SWR" + + map(0x030, 0x033).rw(FUNC(xa_cpu::sfr_port_r), FUNC(xa_cpu::sfr_port_w)); + + map(0x040, 0x040).w(FUNC(xa_cpu::sfr_SCR_w)); + + //0x041, "DS" + //0x042, "ES" + //0x043, "CS" + + //0x050, "TL0" + //0x051, "TH0" + //0x052, "TL1" + //0x053, "TH1" + //0x054, "RTL0" + //0x055, "RTH0" + //0x056, "RTL1" + //0x057, "RTH1" + //0x058, "TL2" + //0x059, "TH2" + //0x05A, "T2CAPL" + //0x05B, "T2CAPH" + //0x05C, "TMOD" + + map(0x05d, 0x05d).w(FUNC(xa_cpu::sfr_WFEED1_w)); + map(0x05e, 0x05e).w(FUNC(xa_cpu::sfr_WFEED2_w)); + + //0x05F, "WDL" + //0x060, "S0BUF" + //0x061, "S0ADDR" + //0x062, "S0ADEN" + //0x064, "S1BUF" + //0x065, "S1ADDR" + //0x066, "S1ADEN" + //0x068, "BTRL" + //0x069, "BTRH" + //0x06A, "BCR" + + map(0x070, 0x073).rw(FUNC(xa_cpu::sfr_PxCFGA_r), FUNC(xa_cpu::sfr_PxCFGA_w)); + + //0x07A, "SWE" + //0x0A0, "IPA0" + //0x0A1, "IPA1" + //0x0A2, "IPA2" + //0x0A3, "IPA3" + //0x0A4, "IPA4" + //0x0A5, "IPA5" + + map(0x0f0, 0x0f3).rw(FUNC(xa_cpu::sfr_PxCFGB_r), FUNC(xa_cpu::sfr_PxCFGB_w)); +} + +void xa_cpu::internal_map(address_map &map) { } @@ -56,41 +278,2373 @@ void mx10exa_cpu_device::mx10exa_internal_map(address_map &map) map(0x000000, 0x00ffff).rom(); } +void xa_cpu::internal_data_map(address_map &map) +{ +} + +void mx10exa_cpu_device::mx10exa_internal_data_map(address_map &map) +{ + map(0x000000, 0x0007ff).ram(); +} + -device_memory_interface::space_config_vector xa_cpu_device::memory_space_config() const + +device_memory_interface::space_config_vector xa_cpu::memory_space_config() const { return space_config_vector { - std::make_pair(AS_PROGRAM, &m_program_config) + std::make_pair(AS_PROGRAM, &m_program_config), + std::make_pair(AS_DATA, &m_data_config), + std::make_pair(AS_IO, &m_sfr_config) }; } - /*****************************************************************************/ -void xa_cpu_device::device_start() +const xa_cpu::op_func xa_cpu::s_instruction[256] = { - m_program = &space(AS_PROGRAM); +// group 0 +&xa_cpu::e_nop, &xa_cpu::e_add, &xa_cpu::e_add, &xa_cpu::e_add, &xa_cpu::e_add, &xa_cpu::e_add, &xa_cpu::e_add, &xa_cpu::e_push_rlist, +&xa_cpu::e_bitgroup, &xa_cpu::e_add, &xa_cpu::e_add, &xa_cpu::e_add, &xa_cpu::e_add, &xa_cpu::e_add, &xa_cpu::e_add, &xa_cpu::e_push_rlist, +// group 1 +&xa_cpu::e_illegal, &xa_cpu::e_addc, &xa_cpu::e_addc, &xa_cpu::e_addc, &xa_cpu::e_addc, &xa_cpu::e_addc, &xa_cpu::e_addc, &xa_cpu::e_pushu_rlist, +&xa_cpu::e_illegal, &xa_cpu::e_addc, &xa_cpu::e_addc, &xa_cpu::e_addc, &xa_cpu::e_addc, &xa_cpu::e_addc, &xa_cpu::e_addc, &xa_cpu::e_pushu_rlist, +// group 2 +&xa_cpu::e_illegal, &xa_cpu::e_sub, &xa_cpu::e_sub, &xa_cpu::e_sub, &xa_cpu::e_sub, &xa_cpu::e_sub, &xa_cpu::e_sub, &xa_cpu::e_pop_rlist, +&xa_cpu::e_illegal, &xa_cpu::e_sub, &xa_cpu::e_sub, &xa_cpu::e_sub, &xa_cpu::e_sub, &xa_cpu::e_sub, &xa_cpu::e_sub, &xa_cpu::e_pop_rlist, +// group 3 +&xa_cpu::e_illegal, &xa_cpu::e_subb, &xa_cpu::e_subb, &xa_cpu::e_subb, &xa_cpu::e_subb, &xa_cpu::e_subb, &xa_cpu::e_subb, &xa_cpu::e_popu_rlist, +&xa_cpu::e_illegal, &xa_cpu::e_subb, &xa_cpu::e_subb, &xa_cpu::e_subb, &xa_cpu::e_subb, &xa_cpu::e_subb, &xa_cpu::e_subb, &xa_cpu::e_popu_rlist, +// group 4 +&xa_cpu::e_lea_offset8, &xa_cpu::e_cmp, &xa_cpu::e_cmp, &xa_cpu::e_cmp, &xa_cpu::e_cmp, &xa_cpu::e_cmp, &xa_cpu::e_cmp, &xa_cpu::e_push_rlist, +&xa_cpu::e_lea_offset16, &xa_cpu::e_cmp, &xa_cpu::e_cmp, &xa_cpu::e_cmp, &xa_cpu::e_cmp, &xa_cpu::e_cmp, &xa_cpu::e_cmp, &xa_cpu::e_push_rlist, +// group 5 +&xa_cpu::e_xch_type1, &xa_cpu::e_and, &xa_cpu::e_and, &xa_cpu::e_and, &xa_cpu::e_and, &xa_cpu::e_and, &xa_cpu::e_and, &xa_cpu::e_pushu_rlist, +&xa_cpu::e_xch_type1, &xa_cpu::e_and, &xa_cpu::e_and, &xa_cpu::e_and, &xa_cpu::e_and, &xa_cpu::e_and, &xa_cpu::e_and, &xa_cpu::e_pushu_rlist, +// group 6 +&xa_cpu::e_xch_type2, &xa_cpu::e_or, &xa_cpu::e_or, &xa_cpu::e_or, &xa_cpu::e_or, &xa_cpu::e_or, &xa_cpu::e_or, &xa_cpu::e_pop_rlist, +&xa_cpu::e_xch_type2, &xa_cpu::e_or, &xa_cpu::e_or, &xa_cpu::e_or, &xa_cpu::e_or, &xa_cpu::e_or, &xa_cpu::e_or, &xa_cpu::e_pop_rlist, +// group 7 +&xa_cpu::e_illegal, &xa_cpu::e_xor, &xa_cpu::e_xor, &xa_cpu::e_xor, &xa_cpu::e_xor, &xa_cpu::e_xor, &xa_cpu::e_xor, &xa_cpu::e_popu_rlist, +&xa_cpu::e_illegal, &xa_cpu::e_xor, &xa_cpu::e_xor, &xa_cpu::e_xor, &xa_cpu::e_xor, &xa_cpu::e_xor, &xa_cpu::e_xor, &xa_cpu::e_popu_rlist, +// group 8 +&xa_cpu::e_movc_rd_rsinc,&xa_cpu::e_mov, &xa_cpu::e_mov, &xa_cpu::e_mov, &xa_cpu::e_mov, &xa_cpu::e_mov, &xa_cpu::e_mov, &xa_cpu::e_pushpop_djnz_subgroup, +&xa_cpu::e_movc_rd_rsinc,&xa_cpu::e_mov, &xa_cpu::e_mov, &xa_cpu::e_mov, &xa_cpu::e_mov, &xa_cpu::e_mov, &xa_cpu::e_mov, &xa_cpu::e_pushpop_djnz_subgroup, +// group 9 +&xa_cpu::e_g9_subgroup, &xa_cpu::e_alu, &xa_cpu::e_alu, &xa_cpu::e_alu, &xa_cpu::e_alu, &xa_cpu::e_alu, &xa_cpu::e_alu, &xa_cpu::e_jb_mov_subgroup, +&xa_cpu::e_g9_subgroup, &xa_cpu::e_alu, &xa_cpu::e_alu, &xa_cpu::e_alu, &xa_cpu::e_alu, &xa_cpu::e_alu, &xa_cpu::e_alu, &xa_cpu::e_jb_mov_subgroup, +// group a +&xa_cpu::e_movdir, &xa_cpu::e_adds, &xa_cpu::e_adds, &xa_cpu::e_adds, &xa_cpu::e_adds, &xa_cpu::e_adds, &xa_cpu::e_adds, &xa_cpu::e_movx_subgroup, +&xa_cpu::e_movdir, &xa_cpu::e_adds, &xa_cpu::e_adds, &xa_cpu::e_adds, &xa_cpu::e_adds, &xa_cpu::e_adds, &xa_cpu::e_adds, &xa_cpu::e_movx_subgroup, +// group b +&xa_cpu::e_rr, &xa_cpu::e_movs, &xa_cpu::e_movs, &xa_cpu::e_movs, &xa_cpu::e_movs, &xa_cpu::e_movs, &xa_cpu::e_movs, &xa_cpu::e_rrc, +&xa_cpu::e_rr, &xa_cpu::e_movs, &xa_cpu::e_movs, &xa_cpu::e_movs, &xa_cpu::e_movs, &xa_cpu::e_movs, &xa_cpu::e_movs, &xa_cpu::e_rrc, +// group c +&xa_cpu::e_lsr_fc, &xa_cpu::e_asl_c, &xa_cpu::e_asr_c, &xa_cpu::e_norm, &xa_cpu::e_lsr_fc, &xa_cpu::e_asl_c, &xa_cpu::e_asr_c, &xa_cpu::e_norm, +&xa_cpu::e_lsr_fc, &xa_cpu::e_asl_c, &xa_cpu::e_asr_c, &xa_cpu::e_norm, &xa_cpu::e_lsr_fc, &xa_cpu::e_asl_c, &xa_cpu::e_asr_c, &xa_cpu::e_norm, +// group d +&xa_cpu::e_lsr_fj, &xa_cpu::e_asl_j, &xa_cpu::e_asr_j, &xa_cpu::e_rl, &xa_cpu::e_lsr_fj, &xa_cpu::e_asl_j, &xa_cpu::e_asr_j, &xa_cpu::e_rlc, +&xa_cpu::e_lsr_fj, &xa_cpu::e_asl_j, &xa_cpu::e_asr_j, &xa_cpu::e_rl, &xa_cpu::e_lsr_fj, &xa_cpu::e_asl_j, &xa_cpu::e_asr_j, &xa_cpu::e_rlc, +// group e +&xa_cpu::e_mulu_b, &xa_cpu::e_divu_b, &xa_cpu::e_djnz_cjne, &xa_cpu::e_cjne_d8, &xa_cpu::e_mulu_w, &xa_cpu::e_divu_w, &xa_cpu::e_mul_w, &xa_cpu::e_div_w, +&xa_cpu::e_div_data8, &xa_cpu::e_div_d16, &xa_cpu::e_djnz_cjne, &xa_cpu::e_cjne_d16, &xa_cpu::e_jz_rel8, &xa_cpu::e_divu_d, &xa_cpu::e_jnz_rel8, &xa_cpu::e_div_d, +// group f +&xa_cpu::e_branch, &xa_cpu::e_branch, &xa_cpu::e_branch, &xa_cpu::e_branch, &xa_cpu::e_branch, &xa_cpu::e_branch, &xa_cpu::e_branch, &xa_cpu::e_branch, +&xa_cpu::e_branch, &xa_cpu::e_branch, &xa_cpu::e_branch, &xa_cpu::e_branch, &xa_cpu::e_branch, &xa_cpu::e_branch, &xa_cpu::e_branch, &xa_cpu::e_bkpt, +}; - state_add(STATE_GENPC, "GENPC", m_pc).formatstr("%08X"); - state_add(STATE_GENPCBASE, "CURPC", m_pc).callexport().noshow(); +// SFR names +const xa_cpu::mem_info xa_cpu::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 } +}; - set_icountptr(m_icount); +void xa_cpu::add_names(const mem_info *info) +{ + for(unsigned int i=0; info[i].addr >= 0; i++) + m_names[info[i].addr] = info[i].name; } -void xa_cpu_device::device_reset() +u16 xa_cpu::expand_rel16(u16 rel16) { - // temp, as there is code here on superkds - m_pc = m_program->read_word(2); + int address = m_pc + ((s16)rel16) * 2; + address &= ~1; // must be word aligned + return address; +} + +u16 xa_cpu::expand_rel8(u8 rel8) +{ + int address = m_pc + ((s8)rel8) * 2; + address &= ~1; // must be word aligned + return address; } -/*****************************************************************************/ -void xa_cpu_device::execute_run() +void xa_cpu::do_nz_flags_16(u16 data) { - while (m_icount > 0) + if (data & 0x8000) + set_n_flag(); + else + clear_n_flag(); + + if (data == 0x0000) + set_z_flag(); + else + clear_z_flag(); +} + + +void xa_cpu::do_nz_flags_8(u8 data) +{ + if (data & 0x80) + set_n_flag(); + else + clear_n_flag(); + + if (data == 0x00) + set_z_flag(); + else + clear_z_flag(); +} + +void xa_cpu::push_word_to_user_stack(u16 data) +{ + // should use the segment register as well! + m_USP -= 2; + m_data->write_word(m_USP, data); +} + +void xa_cpu::push_word_to_system_stack(u16 data) +{ + m_SSP -= 2; + m_data->write_word(m_SSP, data); +} + +void xa_cpu::push_word_to_stack(u16 data) +{ + if (m_usermode) + { + push_word_to_user_stack(data); + } + else + { + push_word_to_system_stack(data); + } +} + +u16 xa_cpu::pull_word_from_user_stack() +{ + // should use the segment register as well! + u16 data = m_data->read_word(m_USP); + m_USP += 2; + return data; +} + +u16 xa_cpu::pull_word_from_system_stack() +{ + u16 data = m_data->read_word(m_SSP); + m_SSP += 2; + return data; +} + + +u16 xa_cpu::pull_word_from_stack() +{ + if (m_usermode) + { + return pull_word_from_user_stack(); + } + else + { + return pull_word_from_system_stack(); + } +} + +void xa_cpu::push_byte_to_user_stack(u8 data) +{ + // should use the segment register as well! + m_USP -= 2; + m_data->write_byte(m_USP, data); +} + +void xa_cpu::push_byte_to_system_stack(u8 data) +{ + m_SSP -= 2; + m_data->write_byte(m_SSP, data); +} + +void xa_cpu::push_byte_to_stack(u16 data) +{ + if (m_usermode) + { + push_byte_to_user_stack(data); + } + else + { + push_byte_to_system_stack(data); + } +} + +u8 xa_cpu::pull_byte_from_user_stack() +{ + // should use the segment register as well! + u8 data = m_data->read_byte(m_USP); + m_USP += 2; + return data; +} + +u8 xa_cpu::pull_byte_from_system_stack() +{ + u8 data = m_data->read_byte(m_SSP); + m_SSP += 2; + return data; +} + +u8 xa_cpu::pull_byte_from_stack() +{ + if (m_usermode) + { + return pull_byte_from_user_stack(); + } + else + { + return pull_byte_from_system_stack(); + } +} + + +u8 xa_cpu::gr8(int reg) +{ + int high = reg & 1; + + reg >>= 1; + + if (reg < 4) + { + // banked regs + int regbank = m_regbank; + + if (high) + return (m_regs[(regbank * 4) + reg] & 0xff00) >> 8; + else + return (m_regs[(regbank * 4) + reg] & 0x00ff) >> 0; + } + else + { + if (reg == 7) + { + fatalerror("gr8 on register R7\n"); + return 0; + } + + reg -= 4; + if (high) + return (m_regs[(4 * 4) + reg] & 0xff00) >> 8; + else + return (m_regs[(4 * 4) + reg] & 0x00ff) >> 0; + } +} + +void xa_cpu::sr8(int reg, u8 data) +{ + int high = reg & 1; + + reg >>= 1; + + if (reg < 4) + { + // banked regs + int regbank = m_regbank; + + if (high) + m_regs[(regbank * 4) + reg] = (m_regs[(regbank * 4) + reg] & 0x00ff) | (data << 8); + else + m_regs[(regbank * 4) + reg] = (m_regs[(regbank * 4) + reg] & 0xff00) | (data << 0); + } + else + { + if (reg == 7) + { + fatalerror("sr8 on register R7\n"); + } + + reg -= 4; + if (high) + m_regs[(4 * 4) + reg] = (m_regs[(4 * 4) + reg] & 0x00ff) | (data << 8); + else + m_regs[(4 * 4) + reg] = (m_regs[(4 * 4) + reg] & 0xff00) | (data << 0); + } +} + + +void xa_cpu::sr16(int reg, u16 data) +{ + if (reg < 4) + { + // banked regs + int regbank = m_regbank; + m_regs[(regbank * 4) + reg] = data; + + } + else if (reg < 8) + { + if (reg == 7) + { + // R7 is the stack pointer, which switches between USP and SSP depending on mode + if (m_usermode) + m_USP = data; + else + m_SSP = data; + + return; + } + + // do we need to calculate parity bit (in PSW51) on all R4 writes (as R4 as backwards compatibility with accumulator) + // or only when the backwards compatible instructions are used? (for now, simply ignore it) + reg -= 4; + m_regs[(4 * 4) + reg] = data; + } + else + { + fatalerror("sr16 with reg %d val = %04x\n", reg, data); + } +} + +u16 xa_cpu::gr16(int reg) +{ + if (reg < 4) + { + // banked regs + int regbank = m_regbank; + return m_regs[(regbank * 4) + reg]; + + } + else if (reg < 8) + { + if (reg == 7) + { + // R7 is the stack pointer, which switches between USP and SSP depending on mode + if (m_usermode) + return m_USP; + else + return m_SSP; + } + + // do we need to calculate parity bit (in PSW51) on all R4 writes (as R4 as backwards compatibility with accumulator) + // or only when the backwards compatible instructions are used? (for now, simply ignore it) + reg -= 4; + return m_regs[(4 * 4) + reg]; + } + else + { + fatalerror("gr16 with reg %d\n", reg); + return 0; + } +} + +void xa_cpu::wdat8(int address, u8 data) +{ + m_data->write_byte(address, data); +} + +void xa_cpu::wdat16(int address, u16 data) +{ + if (address & 1) + fatalerror("unaligned in wdat16\n"); + + m_data->write_word(address, data); +} + + +u8 xa_cpu::rdat8(int address) +{ + return m_data->read_byte(address); +} + +u16 xa_cpu::rdat16(int address) +{ + if (address & 1) + fatalerror("unaligned in rdat16\n"); + + return m_data->read_word(address); +} + + + +void xa_cpu::write_direct16(u16 addr, u16 data) +{ + if (addr < 0x400) + { + if (addr & 1) + fatalerror("write_direct16 (odd address) %04x %04x\n", addr, data); + + m_data->write_word(addr, data); + } + else + { + fatalerror("write_direct16 (SFR) %04x %04x\n", addr, data); + } +} + +void xa_cpu::write_direct8(u16 addr, u8 data) +{ + if (addr < 0x400) + { + m_data->write_byte(addr, data); + } + else + { + m_sfr->write_byte(addr - 0x400, data); + } +} + +u16 xa_cpu::read_direct16(u16 addr) +{ + if (addr < 0x400) + { + return m_data->read_word(addr); + } + else { + fatalerror("read_direct16 on sfr %03x\n", addr); + return 0; + } + return 0; +} + +u8 xa_cpu::read_direct8(u16 addr) +{ + if (addr < 0x400) + { + return m_data->read_byte(addr); + } + else + { + return m_sfr->read_byte(addr - 0x400); + } + return 0; +} + +std::string xa_cpu::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_cpu::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_cpu::get_directtext(int direct) +{ + if (direct < 0x400) + { + return util::string_format("$%03x", direct); + } + + return util::string_format("%s", get_data_address(direct)); +} + +void xa_cpu::e_illegal(u8 op) +{ + fatalerror( "illegal"); +} + +void xa_cpu::handle_shift(u8 op, int shift_type) +{ + int size = (op & 0x0c) >> 2; + const u8 op2 = m_program->read_byte(m_pc++); + u8 data, rd; + if (size == 0x03) + { + data = op2 & 0x1f; + rd = (op2 & 0xe0) >> 4; + } + else + { + data = op2 & 0x0f; + rd = (op2 & 0xf0) >> 4; + } + + // size == 1 has already been filtered out by the time we get here + switch (shift_type) + { + case 0x0: + { + if (size == 0) asl_byte_rd_imm4(rd, data); + else if (size == 2) asl_word_rd_imm4(rd, data); + else if (size == 3) asl_dword_rd_imm5(rd, data); + break; + } + case 0x1: + { + if (size == 0) asr_byte_rd_imm4(rd, data); + else if (size == 2) asr_word_rd_imm4(rd, data); + else if (size == 3) asr_dword_rd_imm5(rd, data); + break; + } + case 0x2: + { + if (size == 0) lsr_byte_rd_imm4(rd, data); + else if (size == 2) lsr_word_rd_imm4(rd, data); + else if (size == 3) lsr_dword_rd_imm5(rd, data); + break; + } + } +} + + +void xa_cpu::handle_alu_type0(u8 op, int alu_op) +{ + const int size = op & 0x08; + const u8 op2 = m_program->read_byte(m_pc++); + + switch (op & 0x07) + { + case 0x01: + { + const u8 rs = (op2 & 0x0f); + const u8 rd = (op2 & 0xf0) >> 4; + if (size) { aluop_word_rd_rs(alu_op, rd, rs); } else { aluop_byte_rd_rs(alu_op, rd, rs); } + break; + } + + case 0x02: + { + const int optype = op2 & 0x08; + if (!optype) + { + const u8 rs = (op2 & 0x07); + const u8 rd = (op2 & 0xf0) >> 4; + if (size) { aluop_word_rd_indrs(alu_op, rd, rs); } else { aluop_byte_rd_indrs(alu_op, rd, rs); } + } + else + { + const u8 rd = (op2 & 0x07); + const u8 rs = (op2 & 0xf0) >> 4; + if (size) { aluop_word_indrd_rs(alu_op, rd, rs); } else { aluop_byte_indrd_rs(alu_op, rd, rs); } + } + break; + } + + case 0x03: + { + const int optype = op2 & 0x08; + if (!optype) + { + const u8 rs = (op2 & 0x07); + const u8 rd = (op2 & 0xf0) >> 4; + if (size) { aluop_word_rd_indrsinc(alu_op, rd, rs); } else { aluop_byte_rd_indrsinc(alu_op, rd, rs); } + } + else + { + const u8 rd = (op2 & 0x07); + const u8 rs = (op2 & 0xf0) >> 4; + if (size) { aluop_word_indrdinc_rs(alu_op, rd, rs); } else { aluop_byte_indrdinc_rs(alu_op, rd, rs); } + } + break; + } + + case 0x04: + { + const int optype = op2 & 0x08; + const u8 offset8 = m_program->read_byte(m_pc++); + if (!optype) + { + const u8 rs = (op2 & 0x07); + const u8 rd = (op2 & 0xf0) >> 4; + if (size) { aluop_word_rd_rsoff8(alu_op, rd, rs, offset8); } else { aluop_byte_rd_rsoff8(alu_op, rd, rs, offset8); } + } + else + { + const u8 rd = (op2 & 0x07); + const u8 rs = (op2 & 0xf0) >> 4; + if (size) { aluop_word_rdoff8_rs(alu_op, rd, offset8, rs); } else { aluop_byte_rdoff8_rs(alu_op, rd, offset8, rs); } + } + break; + } + + case 0x05: + { + const int optype = op2 & 0x08; + const u8 op3 = m_program->read_byte(m_pc++); + const u8 op4 = m_program->read_byte(m_pc++); + const int offset16 = (op3 << 8) | op4; + if (!optype) + { + const u8 rs = (op2 & 0x07); + const u8 rd = (op2 & 0xf0) >> 4; + if (size) { aluop_word_rsoff16(alu_op, rd, rs, offset16); } else { aluop_byte_rsoff16(alu_op, rd, rs, offset16); } + } + else + { + const u8 rd = (op2 & 0x07); + const u8 rs = (op2 & 0xf0) >> 4; + if (size) { aluop_word_rdoff16_rs(alu_op, rd, offset16, rs); } else { aluop_byte_rdoff16_rs(alu_op, rd, offset16, rs); } + } + break; + } + + case 0x06: + { + const int optype = op2 & 0x08; + const u8 op3 = m_program->read_byte(m_pc++); + const u16 direct = ((op2 & 0x07) << 8) | op3; + if (!optype) + { + const u8 rd = (op2 & 0xf0) >> 4; + if (size) { aluop_word_rd_direct(alu_op, rd, direct); } else { aluop_byte_rd_direct(alu_op, rd, direct); } + } + else + { + const u8 rs = (op2 & 0xf0) >> 4; + if (size) { aluop_word_direct_rs(alu_op, direct, rs); } else { aluop_byte_direct_rs(alu_op, direct, rs); } + } + break; + } + + } +} + + + +void xa_cpu::handle_alu_type1(u8 op, u8 op2) +{ + int alu_op = op2 & 0x0f; + switch (op & 0x0f) + { + case 0x01: // ALUOP.b Rd, data8 + { + const u8 data8 = m_program->read_byte(m_pc++); + const u8 rd = (op2 & 0xf0) >> 4; + aluop_byte_rd_data8(alu_op, rd, data8); + break; + } + + case 0x02: // ALUOP.b [Rd], data8 + { + const u8 data8 = m_program->read_byte(m_pc++); + const u8 rd = (op2 & 0xf0) >> 4; + aluop_byte_indrd_data8(alu_op, rd, data8); + break; + } + + case 0x03: // ALUOP.b [Rd+], data8 + { + const u8 data8 = m_program->read_byte(m_pc++); + const u8 rd = (op2 & 0xf0) >> 4; + aluop_byte_indrdinc_data8(alu_op, rd, data8); + break; + } + + case 0x04: // ALUOP.b [Rd+offs8], data8 + { + const u8 offset8 = m_program->read_byte(m_pc++); + const u8 data8 = m_program->read_byte(m_pc++); + const u8 rd = (op2 & 0xf0) >> 4; + aluop_byte_rdoff8_data8(alu_op, rd, offset8, data8); + break; + } + + case 0x05: // ALUOP.b [Rd+offs16], data8 + { + const u8 op3 = m_program->read_byte(m_pc++); + const u8 op4 = m_program->read_byte(m_pc++); + const u8 data8 = m_program->read_byte(m_pc++); + const u8 rd = (op2 & 0xf0) >> 4; + const u16 offset16 = (op3 << 8) | op4; + aluop_byte_rdoff16_data8(alu_op, rd, offset16, data8); + break; + } + + case 0x06: // ALUOP.b DIRECT, data8 + { + const u8 op3 = m_program->read_byte(m_pc++); + const u8 data8 = m_program->read_byte(m_pc++); + const u16 direct = ((op2 & 0xf0) << 4) | op3; + aluop_byte_direct_data8(alu_op, direct, data8); + break; + } + + case 0x09: // ALUOP.w Rd, data16 + { + const u8 op3 = m_program->read_byte(m_pc++); + const u8 op4 = m_program->read_byte(m_pc++); + const u8 rd = (op2 & 0xf0) >> 4; + const u16 data16 = (op3 << 8) | op4; + aluop_byte_rd_data16(alu_op, rd, data16); + break; + } + + case 0x0a: // ALUOP.w [Rd], data16 + { + const u8 op3 = m_program->read_byte(m_pc++); + const u8 op4 = m_program->read_byte(m_pc++); + const u8 rd = (op2 & 0xf0) >> 4; + const u16 data16 = (op3 << 8) | op4; + aluop_byte_indrd_data16(alu_op, rd, data16); + break; + } + + case 0x0b: // ALUOP.w [Rd+], data16 + { + const u8 op3 = m_program->read_byte(m_pc++); + const u8 op4 = m_program->read_byte(m_pc++); + const u8 rd = (op2 & 0xf0) >> 4; + const u16 data16 = (op3 << 8) | op4; + aluop_byte_indrdinc_data16(alu_op, rd, data16); + break; + } + + case 0x0c: // ALPOP.w [Rd+offs8], data16 + { + const u8 op3 = m_program->read_byte(m_pc++); + const u8 op4 = m_program->read_byte(m_pc++); + const u8 op5 = m_program->read_byte(m_pc++); + const u8 rd = (op2 & 0xf0) >> 4; + const int offset8 = op3; + const u16 data16 = (op4 << 8) | op5; + aluop_byte_rdoff8_data16(alu_op, rd, offset8, data16); + break; + } + + case 0x0d: // ALUOP.w [Rd+offs16], data16 + { + const u8 op3 = m_program->read_byte(m_pc++); + const u8 op4 = m_program->read_byte(m_pc++); + const u8 op5 = m_program->read_byte(m_pc++); + const u8 op6 = m_program->read_byte(m_pc++); + const u8 rd = (op2 & 0xf0) >> 4; + const int offset16= (op3 << 8) | op4; + const u16 data16 = (op5 << 8) | op6; + aluop_byte_rdoff16_data16(alu_op, rd, offset16, data16); + break; + } + + case 0x0e: // ALUOP.w DIRECT, data16 + { + const u8 op3 = m_program->read_byte(m_pc++); + const u8 op4 = m_program->read_byte(m_pc++); + const u8 op5 = m_program->read_byte(m_pc++); + const u16 direct =( (op2 & 0xf0) << 4) | op3; + const u16 data16 = (op4 << 8) | op5; + aluop_byte_direct_data16(alu_op, direct, data16); + break; + } + } +} + +std::string xa_cpu::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); +} + +void xa_cpu::handle_adds_movs(u8 op, int which) +{ + const u8 op2 = m_program->read_byte(m_pc++); + int size = op & 0x08; + const u16 data4 = op2 & 0x0f; + + switch (op & 0x07) + { + case 0x01: + { + int rd = (op2 & 0xf0) >> 4; + if (which) { if (size) { movs_word_rd_data4(rd, data4); } else { movs_byte_rd_data4(rd, data4); } } + else { if (size) { adds_word_rd_data4(rd, data4); } else { adds_byte_rd_data4(rd, data4); } } + break; + } + case 0x02: + { + int rd = (op2 & 0x70) >> 4; + if (which == 1) { if (size) { movs_word_indrd_data4(rd, data4); } else { movs_byte_indrd_data4(rd, data4); } } + else { if (size) { adds_word_indrd_data4(rd, data4); } else { adds_byte_indrd_data4(rd, data4); } } + break; + } + case 0x03: + { + int rd = (op2 & 0x70) >> 4; + if (which) { if (size) { movs_word_indrdinc_data4(rd, data4); } else { movs_byte_indrdinc_data4(rd, data4); } } + else { if (size) { adds_word_indrdinc_data4(rd, data4); } else { adds_byte_indrdinc_data4(rd, data4); } } + break; + } + case 0x04: + { + int rd = (op2 & 0x70) >> 4; + const u8 off8 = m_program->read_byte(m_pc++); + if (which == 1) { if (size) { movs_word_indrdoff8_data4(rd, off8, data4); } else { movs_byte_indrdoff8_data4(rd, off8, data4); } } + else { if (size) { adds_word_indrdoff8_data4(rd, off8, data4); } else { adds_byte_indrdoff8_data4(rd, off8, data4); } } + break; + } + case 0x05: + { + int rd = (op2 & 0x70) >> 4; + const u8 op3 = m_program->read_byte(m_pc++); + const u8 op4 = m_program->read_byte(m_pc++); + const int off16 = (op3 << 8) | op4; + if (which == 1) { if (size) { movs_word_indrdoff16_data4(rd, off16, data4); } else { movs_byte_indrdoff16_data4(rd, off16, data4); } } + else { if (size) { adds_word_indrdoff16_data4(rd, off16, data4); } else { adds_byte_indrdoff16_data4(rd, off16, data4); } } + break; + } + case 0x06: + { + const u8 op3 = m_program->read_byte(m_pc++); + const u16 direct = ((op2 & 0xf0) << 4) | op3; + if (which == 1) { if (size) { movs_word_direct_data4(direct, data4); } else { movs_byte_direct_data4(direct, data4); } } + else { if (size) { adds_word_direct_data4(direct, data4); } else { adds_byte_direct_data4(direct, data4); } } + break; + } + } +} + +std::string xa_cpu::get_word_reglist(u8 op2) +{ + std::string temp; + + bool firstbit = true; + for (int i = 0; i < 8; i++) + { + int bit = (op2 & (1 << i)); + + if (bit) + { + temp += util::string_format("%s%s", firstbit ? "" : ",", m_regnames16[i]); + firstbit = false; + } + } + return temp; +} + +std::string xa_cpu::get_byte_reglist(u8 op2, int h) +{ + std::string temp; + + bool firstbit = true; + for (int i = 0; i < 8; i++) + { + int bit = (op2 & (1 << i)); + + if (bit) + { + temp += util::string_format("%s%s", firstbit ? "" : ",", m_regnames8[i + (h ? 8 : 0)]); + firstbit = false; + } + } + return temp; +} + +void xa_cpu::push_byte_reglist(u8 op2, int h, bool force_user) +{ + for (int i = 7; i >= 0; i--) + { + int bit = (op2 & (1 << i)); + if (bit) + { + u8 regval = gr8(i + (h ? 8 : 0)); + if (force_user) + push_byte_to_user_stack(regval); + else + push_byte_to_stack(regval); + cy(2); + } + } +} + +void xa_cpu::push_word_reglist(u8 op2, int h, bool force_user) +{ + // h is unused for word ops? + for (int i = 7; i >= 0; i--) + { + int bit = (op2 & (1 << i)); + if (bit) + { + u16 regval = gr16(i); + if (force_user) + push_word_to_user_stack(regval); + else + push_word_to_stack(regval); + cy(2); + } + } +} + +void xa_cpu::pull_byte_reglist(u8 op2, int h, bool force_user) +{ + for (int i = 0; i < 8; i++) + { + int bit = (op2 & (1 << i)); + if (bit) + { + u8 stackval; + if (force_user) + stackval = pull_byte_from_user_stack(); + else + stackval = pull_byte_from_stack(); + + sr8(i + (h ? 8 : 0), stackval); + cy(2); + } + } +} + +void xa_cpu::pull_word_reglist(u8 op2, int h, bool force_user) +{ + // h is unused for word ops? + for (int i = 0; i < 8; i++) + { + int bit = (op2 & (1 << i)); + if (bit) + { + u16 stackval; + if (force_user) + stackval = pull_word_from_user_stack(); + else + stackval = pull_word_from_stack(); + + sr16(i, stackval); + cy(2); + } + } +} + + +void xa_cpu::handle_push_rlist(u8 op) +{ + const u8 h = op & 0x40; + const u8 size = op & 0x08; + const u8 op2 = m_program->read_byte(m_pc++); + if (size) { push_word_rlist(op2, h); } else { push_byte_rlist(op2, h); } +} + +void xa_cpu::handle_pushu_rlist(u8 op) +{ + const u8 h = op & 0x40; + const u8 size = op & 0x08; + const u8 op2 = m_program->read_byte(m_pc++); + if (size) { pushu_word_rlist(op2, h); } else { pushu_byte_rlist(op2, h); } +} + +void xa_cpu::handle_pop_rlist(u8 op) +{ + const u8 h = op & 0x40; + const u8 size = op & 0x08; + const u8 op2 = m_program->read_byte(m_pc++); + if (size) { pop_word_rlist(op2, h); } else { pop_byte_rlist(op2, h); } +} + +void xa_cpu::handle_popu_rlist(u8 op) +{ + const u8 h = op & 0x40; + const u8 size = op & 0x08; + const u8 op2 = m_program->read_byte(m_pc++); + if (size) { popu_word_rlist(op2, h); } else { popu_byte_rlist(op2, h); } +} + +// -------------------------------------- Group 0 -------------------------------------- + +/* +NOP No operation 1 3 0000 0000 +*/ +void xa_cpu::e_nop(u8 op) +{ + do_nop(); +} + +/* +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 +*/ + +void xa_cpu::e_bitgroup(u8 op) +{ + const u8 op2 = m_program->read_byte(m_pc++); + const u8 op3 = m_program->read_byte(m_pc++); + + u16 bit = ((op2 & 0x03) << 8) | op3; + + switch (op2 & 0xf0) + { + case 0x00: clr_bit(bit); break; + case 0x10: setb_bit(bit); break; + case 0x20: mov_c_bit(bit); break; + case 0x30: mov_bit_c(bit); break; + case 0x40: anl_c_bit(bit); break; + case 0x50: anl_c_notbit(bit); break; + case 0x60: orl_c_bit(bit); break; + case 0x70: orl_c_notbit(bit); break; + default: LOGMASKED(LOG_DEBUG, "illegal bit op %s", get_bittext(bit) ); do_nop(); break; + } + return; +} + +/* +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 +*/ +void xa_cpu::e_add(u8 op) +{ + handle_alu_type0(op, 0); +} + +/* +PUSH Rlist Push regs (b/w) onto the current stack 2 b* 0H00 S111 LLLL LLLL +*/ +void xa_cpu::e_push_rlist(u8 op) +{ + // PUSH + handle_push_rlist(op); +} + +// -------------------------------------- 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 +*/ + +void xa_cpu::e_addc(u8 op) +{ + handle_alu_type0(op, 1); +} + +/* +PUSHU Rlist Push regs (b/w) from the user stack 2 b* 0H01 S111 LLLL LLLL +*/ +void xa_cpu::e_pushu_rlist(u8 op) +{ + // PUSHU + handle_pushu_rlist(op); +} + + +// -------------------------------------- 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 +*/ +void xa_cpu::e_sub(u8 op) +{ + handle_alu_type0(op, 2); +} + +/* +POP Rlist Pop regs (b/w) from the current stack 2 c* 0H10 S111 LLLL LLLL +*/ +void xa_cpu::e_pop_rlist(u8 op) +{ + // POP + handle_pop_rlist(op); +} + + +// -------------------------------------- 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 +*/ +void xa_cpu::e_subb(u8 op) +{ + handle_alu_type0(op, 3); +} + +/* +POPU Rlist Pop regs (b/w) from the user stack 2 c* 0H11 S111 LLLL LLLL +*/ +void xa_cpu::e_popu_rlist(u8 op) +{ + // POPU + handle_popu_rlist(op); +} + + +// -------------------------------------- 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 +*/ +void xa_cpu::e_lea_offset8(u8 op) +{ + const u8 op2 = m_program->read_byte(m_pc++); + const u8 offs8 = m_program->read_byte(m_pc++); + const u8 rd = (op2 & 0x70) >> 4; + const u8 rs = (op2 & 0x07); + lea_word_rd_rs_off8(rd, rs, offs8); +} + +/* +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 +*/ +void xa_cpu::e_lea_offset16(u8 op) +{ + const u8 op2 = m_program->read_byte(m_pc++); + const u8 op3 = m_program->read_byte(m_pc++); + const u8 op4 = m_program->read_byte(m_pc++); + const u8 rd = (op2 & 0x70) >> 4; + const u8 rs = (op2 & 0x07); + const u16 offs16 = (op3 << 8) | op4; + lea_word_rd_rs_off16(rd, rs, offs16); +} + +/* +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 +*/ +void xa_cpu::e_cmp(u8 op) +{ + handle_alu_type0(op, 4); +} + +// -------------------------------------- Group 5 -------------------------------------- + +/* +XCH Rd, [Rs] Exchange contents of a reg-ind address w/ a reg 2 6 0101 S000 dddd 0sss +*/ +void xa_cpu::e_xch_type1(u8 op) +{ + const u8 op2 = m_program->read_byte(m_pc++); + int size = op & 0x08; + const u8 rd = (op2 & 0xf0) >> 4; + const u8 rs = (op2 & 0x07); + + if (size) { xch_word_rd_indrs(rd, rs); } else { xch_byte_rd_indrs(rd, rs); } +} + +/* +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 +*/ +void xa_cpu::e_and(u8 op) +{ + handle_alu_type0(op, 5); +} + +// -------------------------------------- Group 6 -------------------------------------- + +/* +XCH Rd, Rs Exchange contents of two regs 2 5 0110 S000 dddd ssss +*/ +void xa_cpu::e_xch_type2(u8 op) +{ + const u8 op2 = m_program->read_byte(m_pc++); + int size = op & 0x08; + const u8 rd = (op2 & 0xf0) >> 4; + const u8 rs = (op2 & 0x0f); + if (size) { xch_word_rd_rs(rd, rs); } else { xch_byte_rd_rs(rd, rs); } +} + +/* +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 +*/ +void xa_cpu::e_or(u8 op) +{ + handle_alu_type0(op, 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 +*/ +void xa_cpu::e_xor(u8 op) +{ + handle_alu_type0(op, 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 +*/ +void xa_cpu::e_movc_rd_rsinc(u8 op) +{ + const u8 op2 = m_program->read_byte(m_pc++); + int size = op & 0x08; + int rd = (op2 & 0xf0) >> 4; + int rs = (op2 & 0x07); + if (size) { movc_word_rd_indrsinc(rd, rs); } else { movc_byte_rd_indrsinc(rd, rs); } +} + +/* +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 +*/ +void xa_cpu::e_mov(u8 op) +{ + handle_alu_type0(op, 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 +*/ +void xa_cpu::e_pushpop_djnz_subgroup(u8 op) +{ + const u8 op2 = m_program->read_byte(m_pc++); + int size = op & 0x08; + if (op2 & 0x08) + { + const u8 rel8 = m_program->read_byte(m_pc++); + int rd = (op2 & 0xf0) >> 4; + if (size) { djnz_word_rd_rel8(rd, rel8); } else { djnz_byte_rd_rel8(rd, rel8); } + } + else + { + const u8 op3 = m_program->read_byte(m_pc++); + const u16 direct = ((op2 & 0x07) << 8) | op3; + switch (op2 & 0xf0) + { + case 0x00: { if (size) { popu_word_direct(direct); } else { popu_byte_direct(direct); } break; } + case 0x10: { if (size) { pop_word_direct(direct); } else { pop_byte_direct(direct); } break; } + case 0x20: { if (size) { pushu_word_direct(direct); } else { pushu_byte_direct(direct); } break; } + case 0x30: { if (size) { push_word_direct(direct); } else { push_byte_direct(direct); } break; } + default: LOGMASKED(LOG_DEBUG, "illegal push/pop"); do_nop(); break; + } + } +} + + + +// -------------------------------------- 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 +*/ +void xa_cpu::e_g9_subgroup(u8 op) +{ + const u8 op2 = m_program->read_byte(m_pc++); + int size = op & 0x08; + if ((op2 & 0x0f) < 0x08) + { + int rd = (op2 & 0x70) >> 4; + int rs = (op2 & 0x07); + if (size) { mov_word_indrdinc_indrsinc(rd, rs); } else { mov_byte_indrdinc_indrsinc(rd, rs); } + } + else + { + switch (op2 & 0x0f) + { + case 0x08: { int rd = (op2 & 0xf0) >> 4; da_rd(rd); break; } + case 0x09: { int rd = (op2 & 0xf0) >> 4; if (size) { sext_word_rd(rd); } else { sext_byte_rd(rd); } break; } + case 0x0a: { int rd = (op2 & 0xf0) >> 4; if (size) { cpl_word_rd(rd); } else { cpl_byte_rd(rd); } break; } + case 0x0b: { int rd = (op2 & 0xf0) >> 4; if (size) { neg_word_rd(rd); } else { neg_byte_rd(rd); } break; } + case 0x0c: { movc_a_apc(); break; } + case 0x0e: { movc_a_adptr(); break; } + case 0x0f: { int reg = (op2 & 0xf0) >> 4; if (!size) { mov_rd_usp(reg); } else { mov_usp_rs(reg); } break; } + default: { LOGMASKED(LOG_DEBUG, "illegal %02x", op2); do_nop(); break; } + } + } +} + +/* +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 +*/ +void xa_cpu::e_alu(u8 op) +{ + const u8 op2 = m_program->read_byte(m_pc++); + handle_alu_type1(op, 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 +*/ +void xa_cpu::e_jb_mov_subgroup(u8 op) +{ + const u8 op2 = m_program->read_byte(m_pc++); + const u8 op3 = m_program->read_byte(m_pc++); + const u8 op4 = m_program->read_byte(m_pc++); + + if (op2 & 0x80) + { + int bit = ((op2 & 0x03) << 8) | op3; + switch (op2 & 0x70) + { + case 0x00: jb_bit_rel8(bit, op4); break; + case 0x20: jnb_bit_rel8(bit, op4); break; + case 0x40: jbc_bit_rel8(bit, op4); break; + default: LOGMASKED(LOG_DEBUG, "illegal conditional jump %s $%02x", get_bittext(bit), expand_rel8(op4) ); break; + } + } + else + { + int direct_dst = ((op2 & 0x70) << 4) | op3; + int direct_src = ((op2 & 0x07) << 8) | op4; + int size = op & 0x08; + if (size) { mov_word_direct_direct(direct_dst, direct_src); } else { mov_byte_direct_direct(direct_dst, direct_src); } + } +} + +// -------------------------------------- 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 +*/ +void xa_cpu::e_movdir(u8 op) +{ + const u8 op2 = m_program->read_byte(m_pc++); + const u8 op3 = m_program->read_byte(m_pc++); + int size = op & 0x08; + const u16 direct = ((op2 & 0x07) << 8) | op3; + + if (op2 & 0x08) + { + const u8 rd = op2 & (0xf0) >> 4; + if (size) { xch_word_rd_direct(rd, direct); } else { xch_byte_rd_direct(rd, direct); } + } + else + { + if (op2 & 0x80) + { + const u8 rs = op2 & (0x70) >> 4; + if (size) { mov_word_direct_indrs(direct, rs); } else { mov_byte_direct_indrs(direct, rs); } + } + else + { + const u8 rd = op2 & (0x70) >> 4; + if (size) { mov_word_indrd_direct(rd, direct); } else { mov_byte_indrd_direct(rd, direct); } + } + } +} + +/* +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 +*/ +void xa_cpu::e_adds(u8 op) +{ + handle_adds_movs(op, 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 +*/ +void xa_cpu::e_movx_subgroup(u8 op) +{ + const u8 op2 = m_program->read_byte(m_pc++); + int size = op & 0x08; + if (op2 & 0x08) + { + const u8 rs = (op2 & 0xf0) >> 4; + const u8 rd = (op2 & 0x07); + if (size) { movx_word_indrd_rs(rd, rs); } else { movx_byte_indrd_rs(rd, rs); } + } + else + { + const u8 rd = (op2 & 0xf0) >> 4; + const u8 rs = (op2 & 0x07); + if (size) { movx_word_rd_indrs(rd, rs); } else { movx_byte_rd_indrs(rd, rs); } + } +} + +// -------------------------------------- Group b -------------------------------------- + +/* +RR Rd, #data4 Rotate right reg by the 4-bit imm value 2 a* 1011 S000 dddd iiii +*/ +void xa_cpu::e_rr(u8 op) +{ + const u8 op2 = m_program->read_byte(m_pc++); + int size = op & 0x08; + const u8 rd = (op2 & 0xf0) >> 4; + const u8 data = rd & 0x0f; + if (size) { rr_word_rd_data4(rd, data); } else { rr_byte_rd_data4(rd, data); } +} + +/* +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 +*/ +void xa_cpu::e_movs(u8 op) +{ + handle_adds_movs(op, 1); +} + +/* +RRC Rd, #data4 Rotate right reg though carry by the 4-bit imm value 2 a* 1011 S111 dddd iiii +*/ +void xa_cpu::e_rrc(u8 op) +{ + const u8 op2 = m_program->read_byte(m_pc++); + int size = op & 0x08; + const u8 rd = (op2 & 0xf0) >> 4; + const u8 data = rd & 0x0f; + if (size) { rrc_word_rd_data4(rd, data); } else { rrc_byte_rd_data4(rd, data); } +} + + +// -------------------------------------- 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 +*/ +void xa_cpu::e_lsr_fc(u8 op) +{ + int size = (op & 0x0c) >> 2; + if (size == 0x01) + { + const u8 op2 = m_program->read_byte(m_pc++); + const u8 op3 = m_program->read_byte(m_pc++); + const u8 op4 = m_program->read_byte(m_pc++); + const u32 addr = (op2 << 8) | op3 | (op4 << 16); + fcall_addr24(addr); + } + else + { + const u8 op2 = m_program->read_byte(m_pc++); + const u8 rd = (op2 & 0xf0) >> 4; + const u8 rs = (op2 & 0x0f); + if (size == 0) lsr_byte_rd_rs(rd, rs); + else if (size == 2) lsr_word_rd_rs(rd, rs); + else if (size == 3) lsr_dword_rd_rs(rd, rs); + } +} + +/* +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 +*/ +void xa_cpu::e_asl_c(u8 op) +{ + int size = (op & 0x0c) >> 2; + if (size == 0x01) + { + const u8 op2 = m_program->read_byte(m_pc++); + const u8 op3 = m_program->read_byte(m_pc++); + u16 rel16 = (op2 << 8) | op3; + call_rel16(rel16); + } + else + { + const u8 op2 = m_program->read_byte(m_pc++); + const u8 rd = (op2 & 0xf0) >> 4; + const u8 rs = (op2 & 0x0f); + if (size == 0) asl_byte_rd_rs(rd, rs); + else if (size == 2) asl_word_rd_rs(rd, rs); + else if (size == 3) asl_dword_rd_rs(rd, rs); + } +} + +/* +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 +*/ +void xa_cpu::e_asr_c(u8 op) +{ + int size = (op & 0x0c) >> 2; + if (size == 0x01) + { + const u8 op2 = m_program->read_byte(m_pc++); + const u8 rs = op2 & 0x07; + call_indrs(rs); + } + else + { + const u8 op2 = m_program->read_byte(m_pc++); + const u8 rd = (op2 & 0xf0) >> 4; + const u8 rs = (op2 & 0x0f); + if (size == 0) asr_byte_rd_rs(rd, rs); + else if (size == 2) asr_word_rd_rs(rd, rs); + else if (size == 3) asr_dword_rd_rs(rd, rs); + } +} + +/* +NORM Rd, Rs Logical shift left dest reg by the value in the src reg until MSB set 2 a* 1100 SS11 dddd ssss +*/ +void xa_cpu::e_norm(u8 op) +{ + int size = (op & 0x0c) >> 2; + if (size == 0x01) + { + const u8 op2 = m_program->read_byte(m_pc++); + LOGMASKED(LOG_DEBUG, "illegal %02x", op2); do_nop(); + } + else + { + const u8 op2 = m_program->read_byte(m_pc++); + int rd = (op2 & 0xf0) >> 4; + int rs = (op2 & 0x0f); + if (size == 0) norm_byte_rd_rs(rd, rs); + else if (size == 2) norm_word_rd_rs(rd, rs); + else if (size == 3) norm_dword_rd_rs(rd, rs); + } +} + +// -------------------------------------- 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 +*/ +void xa_cpu::e_lsr_fj(u8 op) +{ + int size = (op & 0x0c) >> 2; + if (size == 0x01) + { + const u8 op2 = m_program->read_byte(m_pc++); + const u8 op3 = m_program->read_byte(m_pc++); + const u8 op4 = m_program->read_byte(m_pc++); + const u32 addr = (op2 << 8) | op3 | (op4 << 16); + fjmp_addr24(addr); + } + else + { + handle_shift(op, 2); + } +} + +/* +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 +*/ +void xa_cpu::e_asl_j(u8 op) +{ + int size = (op & 0x0c) >> 2; + if (size == 0x01) + { + const u8 op2 = m_program->read_byte(m_pc++); + const u8 op3 = m_program->read_byte(m_pc++); + u16 offset = (op2 << 8) | op3; + jmp_rel16(offset); + } + else + { + handle_shift(op, 0); + } +} + +/* +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 +*/ +void xa_cpu::e_asr_j(u8 op) +{ + int size = (op & 0x0c) >> 2; + const u8 op2 = m_program->read_byte(m_pc++); + if (size == 0x01) + { + switch (op2 & 0xf0) + { + case 0x10: reset(); break; + case 0x30: trap_data4(op2 & 0x0f); break; + case 0x40: jmp_ind_adptr(); break; + case 0x60: jmp_dblindrs(op2 & 0x07); break; + case 0x70: jmp_indrs(op2 & 0x07); break; + case 0x80: ret(); break; + case 0x90: reti(); break; + default: LOGMASKED(LOG_DEBUG, "illegal"); do_nop(); break; + } + } + else + { + handle_shift(op, 1); + } +} + +/* +RL Rd, #data4 Rotate left reg by the 4-bit imm value 2 a* 1101 S011 dddd iiii +*/ +void xa_cpu::e_rl(u8 op) +{ + int size = op & 0x08; + const u8 op2 = m_program->read_byte(m_pc++); + const u8 rd = (op2 & 0xf0) >> 4; + const u8 data4 = (op2 & 0x0f); + if (size) { rl_word_rd_data4(rd, data4); } else { rl_byte_rd_data4(rd, data4); } +} + +/* +RLC Rd, #data4 Rotate left reg though carry by the 4-bit imm value 2 a* 1101 S111 dddd iiii +*/ +void xa_cpu::e_rlc(u8 op) +{ + int size = op & 0x08; + const u8 op2 = m_program->read_byte(m_pc++); + const u8 rd = (op2 & 0xf0) >> 4; + const u8 data4 = (op2 & 0x0f); + if (size) { rlc_word_rd_data4(rd, data4); } else { rlc_byte_rd_data4(rd, data4); } +} + +// -------------------------------------- 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 +*/ +void xa_cpu::e_djnz_cjne(u8 op) +{ + const u8 op2 = m_program->read_byte(m_pc++); + const u8 op3 = m_program->read_byte(m_pc++); + const u8 op4 = m_program->read_byte(m_pc++); + int size = op & 0x08; + + const u16 direct = ((op2 & 0x07) << 8) | op3; + if (op2 & 0x08) + { + if (size) { djnz_word_direct_rel8(direct, op4); } else { djnz_byte_direct_rel8(direct, op4); } + } + else + { + int rd = (op2 & 0xf0) >> 4; + if (size) { cjne_word_rd_direct_rel8(rd, direct, op4); } else { cjne_byte_rd_direct_rel8(rd, direct, op4); } + } +} + +/* +MULU.b Rd, Rs 8X8 unsigned multiply of reg contents 2 12 1110 0000 dddd ssss +*/ +void xa_cpu::e_mulu_b(u8 op) +{ + const u8 op2 = m_program->read_byte(m_pc++); + const u8 rd = (op2 & 0xf0) >> 4; + const u8 rs = (op2 & 0x0f); + mulu_byte_rd_rs(rd, rs); +} + +/* +DIVU.b Rd, Rs 8x8 unsigned reg divide 2 12 1110 0001 dddd ssss +*/ +void xa_cpu::e_divu_b(u8 op) +{ + const u8 op2 = m_program->read_byte(m_pc++); + const u8 rd = (op2 & 0xf0) >> 4; + const u8 rs = (op2 & 0x0f); + divu_byte_rd_rs(rd, rs); +} + +/* +MULU.w Rd, Rs 16X16 unsigned reg multiply 2 12 1110 0100 dddd ssss +*/ +void xa_cpu::e_mulu_w(u8 op) +{ + const u8 op2 = m_program->read_byte(m_pc++); + const u8 rd = (op2 & 0xf0) >> 4; + const u8 rs = (op2 & 0x0f); + mulu_word_rd_rs(rd, rs); +} + +/* +DIVU.w Rd, Rs 16X8 unsigned reg divide 2 12 1110 0101 dddd ssss +*/ +void xa_cpu::e_divu_w(u8 op) +{ + const u8 op2 = m_program->read_byte(m_pc++); + const u8 rd = (op2 & 0xf0) >> 4; + const u8 rs = (op2 & 0x0f); + divu_word_rd_rs(rd, rs); +} + +/* +MUL.w Rd, Rs 16X16 signed multiply of reg contents 2 12 1110 0110 dddd ssss +*/ +void xa_cpu::e_mul_w(u8 op) +{ + const u8 op2 = m_program->read_byte(m_pc++); + const u8 rd = (op2 & 0xf0) >> 4; + const u8 rs = (op2 & 0x0f); + mul_word_rd_rs(rd, rs); +} + +/* +DIV.w Rd, Rs 16x8 signed reg divide 2 14 1110 0111 dddd ssss +*/ +void xa_cpu::e_div_w(u8 op) +{ + const u8 op2 = m_program->read_byte(m_pc++); + const u8 rd = (op2 & 0xf0) >> 4; + const u8 rs = (op2 & 0x0f); + div_word_rd_rs(rd, rs); +} + +/* +MULU.b Rd, #data8 8X8 unsigned multiply of 8-bit imm data w/ reg 3 12 1110 1000 dddd 0000 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 +DIV.w Rd, #data8 16x8 signed divide reg w/ imm word 3 14 1110 1000 dddd 1011 iiii iiii + +*/ +void xa_cpu::e_div_data8(u8 op) +{ + const u8 op2 = m_program->read_byte(m_pc++); + const u8 data8 = m_program->read_byte(m_pc++); + const u8 rd = (op2 & 0xf0) >> 4; + + switch (op2 & 0x0f) + { + case 0x00: { mulu_byte_rd_data8(rd, data8); break; } + case 0x01: { divu_byte_rd_data8(rd, data8); break; } + case 0x03: { divu_word_rd_data8(rd, data8); break; } + case 0x0b: { div_word_rd_data8(rd, data8);break; } + default: { LOGMASKED(LOG_DEBUG, "illegal mul/div data8 %s #$%02x", m_regnames8[rd], data8); do_nop(); break; } + } +} + +/* +MULU.w Rd, #data16 16X16 unsigned multiply 16-bit imm data w/ reg 4 12 1110 1001 dddd 0000 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 +MUL.w Rd, #data16 16X16 signed multiply 16-bit imm data w/ reg 4 12 1110 1001 dddd 1000 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 +*/ +void xa_cpu::e_div_d16(u8 op) +{ + const u8 op2 = m_program->read_byte(m_pc++); + const u8 op3 = m_program->read_byte(m_pc++); + const u8 op4 = m_program->read_byte(m_pc++); + const u16 data16 = (op3 << 8) | op4; + switch (op2 & 0x0f) + { + case 0x00: { const u8 rd = (op2 & 0xf0) >> 4; mulu_word_rd_data16(rd, data16); break; } + case 0x01: { const u8 rd = (op2 & 0xe0) >> 4; divu_dword_rd_data16(rd, data16); break; } + case 0x08: { const u8 rd = (op2 & 0xf0) >> 4; mul_word_rd_data16(rd, data16); break; } + case 0x09: { const u8 rd = (op2 & 0xe0) >> 4; div_dword_rd_data16(rd, data16); break; } + default: { const u8 rd = (op2 & 0xf0) >> 4; LOGMASKED(LOG_DEBUG, "illegal mul/div data16 %s, #$%04x", m_regnames16[rd], data16); do_nop(); break; } + } +} + +/* +DIVU.d Rd, Rs 32X16 unsigned double reg divide 2 22 1110 1101 ddd0 ssss +*/ +void xa_cpu::e_divu_d(u8 op) +{ + const u8 op2 = m_program->read_byte(m_pc++); + const u8 rd = (op2 & 0xe0) >> 4; + const u8 rs = (op2 & 0x0f); + divu_dword_rd_rs(rd, rs); +} + +/* +DIV.d Rd, Rs 32x16 signed double reg divide 2 24 1110 1111 ddd0 ssss +*/ +void xa_cpu::e_div_d(u8 op) +{ + const u8 op2 = m_program->read_byte(m_pc++); + const u8 rd = (op2 & 0xe0) >> 4; + const u8 rs = (op2 & 0x0f); + div_dword_rd_rs(rd, rs); +} + +/* +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 +*/ +void xa_cpu::e_cjne_d8(u8 op) +{ + const u8 op2 = m_program->read_byte(m_pc++); + const u8 op3 = m_program->read_byte(m_pc++); + const u8 op4 = m_program->read_byte(m_pc++); + if (op2 & 0x08) + { + const u8 rd = (op2 & 0x70) >> 4; + cjne_indrd_data8_rel8(rd, op4, op3); + } + else + { + const u8 rd = (op2 & 0xf0) >> 4; + cjne_rd_data8_rel8(rd, op4, op3); + } +} + +/* +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 +*/ +void xa_cpu::e_cjne_d16(u8 op) +{ + const u8 op2 = m_program->read_byte(m_pc++); + const u8 op3 = m_program->read_byte(m_pc++); + const u8 op4 = m_program->read_byte(m_pc++); + const u8 op5 = m_program->read_byte(m_pc++); + const u16 data = (op4 << 8) | op5; + if (op2 & 0x08) + { + const u8 rd = (op2 & 0x70) >> 4; + cjne_indrd_data16_rel8(rd, data, op3); + } + else + { + const u8 rd = (op2 & 0xf0) >> 4; + cjne_rd_data16_rel8(rd, data, op3); + } +} + +/* +JZ rel8 Jump if accumulator equals zero 2 6t/3nt 1110 1100 rrrr rrrr +*/ +void xa_cpu::e_jz_rel8(u8 op) +{ + const u8 op2 = m_program->read_byte(m_pc++); + jz_rel8(op2); +} + +/* +JNZ rel8 Jump if accumulator not equal zero 2 6t/3nt 1110 1110 rrrr rrrr +*/ +void xa_cpu::e_jnz_rel8(u8 op) +{ + const u8 op2 = m_program->read_byte(m_pc++); + jnz_rel8(op2); +} + + +// -------------------------------------- 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 +*/ + +void xa_cpu::e_branch(u8 op) +{ + const u8 rel8 = m_program->read_byte(m_pc++); + switch (op & 0x0f) + { + case 0x00: bcc_rel8(rel8); break; + case 0x01: bcs_rel8(rel8); break; + case 0x02: bne_rel8(rel8); break; + case 0x03: beq_rel8(rel8); break; + case 0x04: bnv_rel8(rel8); break; + case 0x05: bov_rel8(rel8); break; + case 0x06: bpl_rel8(rel8); break; + case 0x07: bmi_rel8(rel8); break; + case 0x08: bg_rel8(rel8); break; + case 0x09: bl_rel8(rel8); break; + case 0x0a: bge_rel8(rel8); break; + case 0x0b: blt_rel8(rel8); break; + case 0x0c: bgt_rel8(rel8); break; + case 0x0d: ble_rel8(rel8); break; + case 0x0e: br_rel8(rel8); break; + case 0x0f: LOGMASKED(LOG_DEBUG, "Illegal branch type"); do_nop(); break; // probably acts as 'branch never' + } +} + +/* +BKPT Cause the breakpoint trap to be executed. 1 23/19(PZ) 1111 1111 +*/ +void xa_cpu::e_bkpt(u8 op) +{ + fatalerror( "BKPT"); +} + + +/*****************************************************************************/ + +void xa_cpu::device_start() +{ + m_program = &space(AS_PROGRAM); + m_data = &space(AS_DATA); + m_sfr = &space(AS_IO); + + state_add(STATE_GENPC, "GENPC", m_pc).formatstr("%08X"); + state_add(STATE_GENPCBASE, "CURPC", m_pc).callexport().noshow(); + + state_add(XA_BANK0_R0, "BANK0_R0", m_regs[0]); + state_add(XA_BANK0_R1, "BANK0_R1", m_regs[1]); + state_add(XA_BANK0_R2, "BANK0_R2", m_regs[2]); + state_add(XA_BANK0_R3, "BANK0_R3", m_regs[3]); + + state_add(XA_BANK1_R0, "BANK1_R0", m_regs[4]); + state_add(XA_BANK1_R1, "BANK1_R1", m_regs[5]); + state_add(XA_BANK1_R2, "BANK1_R2", m_regs[6]); + state_add(XA_BANK1_R3, "BANK1_R3", m_regs[7]); + + state_add(XA_BANK2_R0, "BANK2_R0", m_regs[8]); + state_add(XA_BANK2_R1, "BANK2_R1", m_regs[9]); + state_add(XA_BANK2_R2, "BANK2_R2", m_regs[10]); + state_add(XA_BANK2_R3, "BANK2_R3", m_regs[11]); + + state_add(XA_BANK3_R0, "BANK3_R0", m_regs[12]); + state_add(XA_BANK3_R1, "BANK3_R1", m_regs[13]); + state_add(XA_BANK3_R2, "BANK3_R2", m_regs[14]); + state_add(XA_BANK3_R3, "BANK3_R3", m_regs[15]); + + state_add(XA_R4, "R4", m_regs[16]); + state_add(XA_R5, "R5", m_regs[17]); + state_add(XA_R6, "R6", m_regs[18]); +// state_add(XA_R7, "R7", m_usermode ? m_USP : m_SSP); + + state_add(XA_USP, "R7 USP", m_USP); + state_add(XA_SSP, "R7 SSP", m_SSP); + + set_icountptr(m_icount); + + save_item(NAME(m_im)); + save_item(NAME(m_rs)); + save_item(NAME(m_zflag)); + save_item(NAME(m_nflag)); + save_item(NAME(m_vflag)); + save_item(NAME(m_cflag)); + save_item(NAME(m_acflag)); + save_item(NAME(m_sm_flag)); + save_item(NAME(m_tm_flag)); + save_item(NAME(m_p_flag)); + save_item(NAME(m_f0_flag)); + save_item(NAME(m_f1_flag)); + save_item(NAME(m_pc)); + save_item(NAME(m_usermode)); + save_item(NAME(m_pagezeromode)); + save_item(NAME(m_USP)); + save_item(NAME(m_SSP)); + save_item(NAME(m_WDCON)); + save_item(NAME(m_SCR)); + save_item(NAME(m_IEL)); + save_item(NAME(m_regs)); + save_item(NAME(m_PSWL)); + save_item(NAME(m_PSWH)); + save_item(NAME(m_regbank)); + + save_item(NAME(m_PxCFGA)); + save_item(NAME(m_PxCFGB)); + + save_item(NAME(m_in_interrupt)); + save_item(NAME(m_irq_pending)); + +} + +void xa_cpu::device_reset() +{ + u16 temppsw = m_program->read_word(0); + sfr_PSWL_w(temppsw & 0xff); + sfr_PSWH_w((temppsw >> 8) & 0xff); + m_pc = m_program->read_word(2); + + m_WDCON = 0x00; + m_SCR = 0x00; + m_IEL = 0x00; + + m_USP = 0x0100; + m_SSP = 0x0100; + + for (int i = 0; i < 4 * 4 + 4; i++) + { + m_regs[i] = 0x0000; + } + + m_nflag = 0; + m_zflag = 0; + m_cflag = 0; + m_vflag = 0; + m_acflag = 0; + + m_pagezeromode = 1; + + m_in_interrupt = 0; + m_irq_pending = 0; + + for (int i = 0; i < 4; i++) + { + m_PxCFGA[i] = 0; + m_PxCFGB[i] = 0; + } +} + +/*****************************************************************************/ + +void xa_cpu::check_external_irq_level(int level) +{ + if (m_IEL & 0x80) + { + if (m_IEL & (1 << level)) + { + if (m_irq_pending & (1 << level)) + { + LOGMASKED(LOG_DEBUG, "testing irq %d\n", level); + int vector = 0x20 + level; + push_word_to_system_stack(sfr_PSWH_r()); + push_word_to_system_stack(sfr_PSWL_r()); + push_word_to_system_stack(m_pc); + + u16 temppsw = m_program->read_word(vector*4); + sfr_PSWL_w(temppsw & 0xff); + sfr_PSWH_w((temppsw >> 8) & 0xff); + m_pc = m_program->read_word((vector*4)+2); + m_in_interrupt = 1; + m_irq_pending &= ~(1 << level); + standard_irq_callback(level, m_pc); + } + } + } +} + +void xa_cpu::check_interrupts() +{ + if (m_irq_pending) + { + if (!m_in_interrupt) + { + for (int i = 0; i < 4; i++) + check_external_irq_level(i); + } + } + +} + +void xa_cpu::execute_set_input(int inputnum, int state) +{ + // This is not accurate, just test code for fearless/superkds + m_irq_pending |= 1 << inputnum; + check_interrupts(); +} + +void xa_cpu::execute_run() +{ + while (m_icount > 0) + { + check_interrupts(); + debugger_instruction_hook(m_pc); - m_pc++; - m_icount--; + u32 oldpc = m_pc; + u8 op = m_program->read_byte(m_pc++); + int old_icount = m_icount; + (this->*s_instruction[op])(op); + if (m_icount == old_icount) + fatalerror("op at %06x took no cycles\n", oldpc); } } diff --git a/src/devices/cpu/xa/xa.h b/src/devices/cpu/xa/xa.h index 983fff36724..3fbf7a3cb92 100644 --- a/src/devices/cpu/xa/xa.h +++ b/src/devices/cpu/xa/xa.h @@ -6,13 +6,54 @@ #pragma once -class xa_cpu_device : public cpu_device +enum { + XA_EXT_IRQ0, + XA_EXT_IRQ1, + XA_EXT_IRQ2, + XA_EXT_IRQ3, +}; + +enum { + XA_BANK0_R0, + XA_BANK0_R1, + XA_BANK0_R2, + XA_BANK0_R3, + + XA_BANK1_R0, + XA_BANK1_R1, + XA_BANK1_R2, + XA_BANK1_R3, + + XA_BANK2_R0, + XA_BANK2_R1, + XA_BANK2_R2, + XA_BANK2_R3, + + XA_BANK3_R0, + XA_BANK3_R1, + XA_BANK3_R2, + XA_BANK3_R3, + + XA_R4, + XA_R5, + XA_R6, + XA_R7, + + XA_USP, + XA_SSP, +}; + + +class xa_cpu : public cpu_device { public: - xa_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + xa_cpu(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + template auto port_in_cb() { return m_port_in_cb[N].bind(); } + template auto port_out_cb() { return m_port_out_cb[N].bind(); } 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); + xa_cpu(const machine_config& mconfig, device_type type, const char* tag, device_t* owner, uint32_t clock, address_map_constructor prg_map, address_map_constructor dat_map); virtual void device_start() override; virtual void device_reset() override; @@ -21,6 +62,7 @@ protected: 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 void execute_set_input(int inputnum, int state) override; virtual space_config_vector memory_space_config() const override; @@ -28,26 +70,900 @@ protected: private: void internal_map(address_map &map); + void internal_data_map(address_map &map); + void data_map(address_map &map); + void sfr_map(address_map &map); address_space_config m_program_config; + address_space_config m_data_config; + address_space_config m_sfr_config; + + 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; + + typedef void (xa_cpu::*op_func) (u8 op); + 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"}; + + std::string get_bittext(int bit); + std::string get_directtext(int bit); + std::string show_expanded_data4(u16 data4, int size); + std::string get_word_reglist(u8 op2); + std::string get_byte_reglist(u8 op2, int h); + + void check_external_irq_level(int level); + void check_interrupts(); + + u16 expand_rel16(u16 rel16); + u16 expand_rel8(u8 rel8); + + void cy(u8 cycles) + { + m_icount -= cycles; + } + + void do_nz_flags_16(u16 data); + void do_nz_flags_8(u8 data); + + u8 get_n_flag() { return m_nflag; } + void set_n_flag() { m_nflag = 1; } + void clear_n_flag() { m_nflag = 0; } + + u8 get_z_flag() { return m_zflag; } + void set_z_flag() { m_zflag = 1; } + void clear_z_flag() { m_zflag = 0; } + + u8 get_c_flag() { return m_cflag; } + void set_c_flag() { m_cflag = 1; } + void clear_c_flag() { m_cflag = 0; } + + u8 get_v_flag() { return m_vflag; } + void set_v_flag() { m_vflag = 1; } + void clear_v_flag() { m_vflag = 0; } + + u8 get_ac_flag() { return m_acflag; } + void set_ac_flag() { m_acflag = 1; } + void clear_ac_flag() { m_acflag = 0; } + + + u8 gr8(int reg); + void sr8(int reg, u8 data); + + u16 gr16(int reg); + void sr16(int reg, u16 data); + + u32 gr32(int reg); + void sr32(int reg, u32 data); + + void set_pc_in_current_page(u16 addr); + + void push_word_reglist(u8 op2, int h, bool force_user); + void pull_word_reglist(u8 op2, int h, bool force_user); + void push_byte_reglist(u8 op2, int h, bool force_user); + void pull_byte_reglist(u8 op2, int h, bool force_user); + + void push_word_to_user_stack(u16 data); + void push_word_to_system_stack(u16 data); + void push_word_to_stack(u16 data); + + u16 pull_word_from_user_stack(); + u16 pull_word_from_system_stack(); + u16 pull_word_from_stack(); + + void push_byte_to_user_stack(u8 data); + void push_byte_to_system_stack(u8 data); + void push_byte_to_stack(u16 data); + + u8 pull_byte_from_user_stack(); + u8 pull_byte_from_system_stack(); + u8 pull_byte_from_stack(); + + void wdat8(int address, u8 data); + void wdat16(int address, u16 data); + + u8 rdat8(int address); + u16 rdat16(int address); + + u8 sfr_WDCON_r(); + + u8 sfr_PSWL_r(); + void sfr_PSWL_w(u8 data); + + u8 sfr_PSWH_r(); + void sfr_PSWH_w(u8 data); + void sfr_PSW51_w(u8 data); + + void sfr_SCR_w(u8 data); + void sfr_WFEED1_w(u8 data); + void sfr_WFEED2_w(u8 data); + + u8 sfr_IEL_r(); + void sfr_IEL_w(u8 data); + + u8 sfr_port_r(offs_t offset); + void sfr_port_w(offs_t offset, u8 data); + + u8 sfr_PxCFGA_r(offs_t offset); + void sfr_PxCFGA_w(offs_t offset, u8 data); + + u8 sfr_PxCFGB_r(offs_t offset); + void sfr_PxCFGB_w(offs_t offset, u8 data); + + void set_bit_8_helper(u16 bit, u8 val); + + u32 asl32_helper(u32 fullreg, u8 amount); + u32 lsr32_helper(u32 fullreg, u8 amount); + u16 lsr16_helper(u16 fullreg, u8 amount); + + u8 read_direct8(u16 addr); + u16 read_direct16(u16 addr); + + void write_direct8(u16 addr, u8 data); + void write_direct16(u16 addr, u16 data); + + u16 do_subb_16(u16 val1, u16 val2); + u16 do_sub_16(u16 val1, u16 val2); + u16 do_sub_16_helper(u16 val1, u16 val2, u8 c); + + u16 do_addc_16(u16 val1, u16 val2); + u16 do_add_16(u16 val1, u16 val2); + u16 do_add_16_helper(u16 val1, u16 val2, u8 c); + + u16 do_xor_16(u16 val1, u16 val2); + u16 do_or_16(u16 val1, u16 val2); + u16 do_and_16(u16 val1, u16 val2); + + u8 do_sub_8(u8 val1, u8 val2); + u8 do_subb_8(u8 val1, u8 val2); + u8 do_sub_8_helper(u8 val1, u8 val2, u8 c); + + u8 do_add_8(u8 val1, u8 val2); + u8 do_addc_8(u8 val1, u8 val2); + u8 do_add_8_helper(u8 val1, u8 val2, u8 c); + + u8 do_xor_8(u8 val1, u8 val2); + u8 do_or_8(u8 val1, u8 val2); + u8 do_and_8(u8 val1, u8 val2); + + u8 do_cjne_8_helper(u8 val1, u8 val2); + + void handle_alu_type0(u8 op, int alu_op); + void handle_alu_type1(u8 op, u8 op2); + void handle_push_rlist(u8 op); + void handle_pushu_rlist(u8 op); + void handle_pop_rlist(u8 op); + void handle_popu_rlist(u8 op); + void handle_adds_movs(u8 op, int which); + void handle_shift(u8 op, int shift_type); + + void e_illegal(u8 op); + + void e_nop(u8 op); + void e_bitgroup(u8 op); + void e_add(u8 op); + void e_push_rlist(u8 op); + void e_addc(u8 op); + void e_pushu_rlist(u8 op); + void e_sub(u8 op); + void e_pop_rlist(u8 op); + void e_subb(u8 op); + void e_popu_rlist(u8 op); + void e_lea_offset8(u8 op); + void e_lea_offset16(u8 op); + void e_cmp(u8 op); + void e_xch_type1(u8 op); + void e_and(u8 op); + void e_xch_type2(u8 op); + void e_or(u8 op); + void e_xor(u8 op); + void e_movc_rd_rsinc(u8 op); + void e_mov(u8 op); + void e_pushpop_djnz_subgroup(u8 op); + void e_g9_subgroup(u8 op); + void e_alu(u8 op); + void e_jb_mov_subgroup(u8 op); + void e_movdir(u8 op); + void e_adds(u8 op); + void e_movx_subgroup(u8 op); + void e_rr(u8 op); + void e_movs(u8 op); + void e_rrc(u8 op); + void e_lsr_fc(u8 op); + void e_asl_c(u8 op); + void e_asr_c(u8 op); + void e_norm(u8 op); + void e_lsr_fj(u8 op); + void e_asl_j(u8 op); + void e_asr_j(u8 op); + void e_rl(u8 op); + void e_rlc(u8 op); + void e_djnz_cjne(u8 op); + void e_mulu_b(u8 op); + void e_divu_b(u8 op); + void e_mulu_w(u8 op); + void e_divu_w(u8 op); + void e_mul_w(u8 op); + void e_div_w(u8 op); + void e_div_data8(u8 op); + void e_div_d16(u8 op); + void e_divu_d(u8 op); + void e_div_d(u8 op); + void e_cjne_d8(u8 op); + void e_cjne_d16(u8 op); + void e_jz_rel8(u8 op); + void e_jnz_rel8(u8 op); + void e_branch(u8 op); + void e_bkpt(u8 op); + + void do_nop(); + + void add_byte_rd_data8(u8 rd, u8 data8); + void addc_byte_rd_data8(u8 rd, u8 data8); + void sub_byte_rd_data8(u8 rd, u8 data8); + void subb_byte_rd_data8(u8 rd, u8 data8); + void cmp_byte_rd_data8(u8 rd, u8 data8); + void and_byte_rd_data8(u8 rd, u8 data8); + void or_byte_rd_data8(u8 rd, u8 data8); + void xor_byte_rd_data8(u8 rd, u8 data8); + void mov_byte_rd_data8(u8 rd, u8 data8); + + void add_byte_indrd_data8(u8 rd, u8 data8); + void addc_byte_indrd_data8(u8 rd, u8 data8); + void sub_byte_indrd_data8(u8 rd, u8 data8); + void subb_byte_indrd_data8(u8 rd, u8 data8); + void cmp_byte_indrd_data8(u8 rd, u8 data8); + void and_byte_indrd_data8(u8 rd, u8 data8); + void or_byte_indrd_data8(u8 rd, u8 data8); + void xor_byte_indrd_data8(u8 rd, u8 data8); + void mov_byte_indrd_data8(u8 rd, u8 data8); + + void add_byte_indrdinc_data8(u8 rd, u8 data8); + void addc_byte_indrdinc_data8(u8 rd, u8 data8); + void sub_byte_indrdinc_data8(u8 rd, u8 data8); + void subb_byte_indrdinc_data8(u8 rd, u8 data8); + void cmp_byte_indrdinc_data8(u8 rd, u8 data8); + void and_byte_indrdinc_data8(u8 rd, u8 data8); + void or_byte_indrdinc_data8(u8 rd, u8 data8); + void xor_byte_indrdinc_data8(u8 rd, u8 data8); + void mov_byte_indrdinc_data8(u8 rd, u8 data8); + + void add_byte_indrdoff8_data8(u8 rd, u8 offset8, u8 data8); + void addc_byte_indrdoff8_data8(u8 rd, u8 offset8, u8 data8); + void sub_byte_indrdoff8_data8(u8 rd, u8 offset8, u8 data8); + void subb_byte_indrdoff8_data8(u8 rd, u8 offset8, u8 data8); + void cmp_byte_indrdoff8_data8(u8 rd, u8 offset8, u8 data8); + void and_byte_indrdoff8_data8(u8 rd, u8 offset8, u8 data8); + void or_byte_indrdoff8_data8(u8 rd, u8 offset8, u8 data8); + void xor_byte_indrdoff8_data8(u8 rd, u8 offset8, u8 data8); + void mov_byte_indrdoff8_data8(u8 rd, u8 offset8, u8 data8); + + void add_byte_indrdoff16_data8(u8 rd, u16 offset16, u8 data8); + void addc_byte_indrdoff16_data8(u8 rd, u16 offset16, u8 data8); + void sub_byte_indrdoff16_data8(u8 rd, u16 offset16, u8 data8); + void subb_byte_indrdoff16_data8(u8 rd, u16 offset16, u8 data8); + void cmp_byte_indrdoff16_data8(u8 rd, u16 offset16, u8 data8); + void and_byte_indrdoff16_data8(u8 rd, u16 offset16, u8 data8); + void or_byte_indrdoff16_data8(u8 rd, u16 offset16, u8 data8); + void xor_byte_indrdoff16_data8(u8 rd, u16 offset16, u8 data8); + void mov_byte_indrdoff16_data8(u8 rd, u16 offset16, u8 data8); + + void add_byte_direct_data8(u16 direct, u8 data8); + void addc_byte_direct_data8(u16 direct, u8 data8); + void sub_byte_direct_data8(u16 direct, u8 data8); + void subb_byte_direct_data8(u16 direct, u8 data8); + void cmp_byte_direct_data8(u16 direct, u8 data8); + void and_byte_direct_data8(u16 direct, u8 data8); + void or_byte_direct_data8(u16 direct, u8 data8); + void xor_byte_direct_data8(u16 direct, u8 data8); + void mov_byte_direct_data8(u16 direct, u8 data8); + + void add_word_rd_data16(u8 rd, u16 data16); + void addc_word_rd_data16(u8 rd, u16 data16); + void sub_word_rd_data16(u8 rd, u16 data16); + void subb_word_rd_data16(u8 rd, u16 data16); + void cmp_word_rd_data16(u8 rd, u16 data16); + void and_word_rd_data16(u8 rd, u16 data16); + void or_word_rd_data16(u8 rd, u16 data16); + void xor_word_rd_data16(u8 rd, u16 data16); + void mov_word_rd_data16(u8 rd, u16 data16); + + void add_word_indrd_data16(u8 rd, u16 data16); + void addc_word_indrd_data16(u8 rd, u16 data16); + void sub_word_indrd_data16(u8 rd, u16 data16); + void subb_word_indrd_data16(u8 rd, u16 data16); + void cmp_word_indrd_data16(u8 rd, u16 data16); + void and_word_indrd_data16(u8 rd, u16 data16); + void or_word_indrd_data16(u8 rd, u16 data16); + void xor_word_indrd_data16(u8 rd, u16 data16); + void mov_word_indrd_data16(u8 rd, u16 data16); + + void add_word_indrdinc_data16(u8 rd, u16 data16); + void addc_word_indrdinc_data16(u8 rd, u16 data16); + void sub_word_indrdinc_data16(u8 rd, u16 data16); + void subb_word_indrdinc_data16(u8 rd, u16 data16); + void cmp_word_indrdinc_data16(u8 rd, u16 data16); + void and_word_indrdinc_data16(u8 rd, u16 data16); + void or_word_indrdinc_data16(u8 rd, u16 data16); + void xor_word_indrdinc_data16(u8 rd, u16 data16); + void mov_word_indrdinc_data16(u8 rd, u16 data16); + + void add_word_indrdoff8_data16(u8 rd, u8 offset8, u16 data16); + void addc_word_indrdoff8_data16(u8 rd, u8 offset8, u16 data16); + void sub_word_indrdoff8_data16(u8 rd, u8 offset8, u16 data16); + void subb_word_indrdoff8_data16(u8 rd, u8 offset8, u16 data16); + void cmp_word_indrdoff8_data16(u8 rd, u8 offset8, u16 data16); + void and_word_indrdoff8_data16(u8 rd, u8 offset8, u16 data16); + void or_word_indrdoff8_data16(u8 rd, u8 offset8, u16 data16); + void xor_word_indrdoff8_data16(u8 rd, u8 offset8, u16 data16); + void mov_word_indrdoff8_data16(u8 rd, u8 offset8, u16 data16); + + void add_word_indrdoff16_data16(u8 rd, u16 offset16, u16 data16); + void addc_word_indrdoff16_data16(u8 rd, u16 offset16, u16 data16); + void sub_word_indrdoff16_data16(u8 rd, u16 offset16, u16 data16); + void subb_word_indrdoff16_data16(u8 rd, u16 offset16, u16 data16); + void cmp_word_indrdoff16_data16(u8 rd, u16 offset16, u16 data16); + void and_word_indrdoff16_data16(u8 rd, u16 offset16, u16 data16); + void or_word_indrdoff16_data16(u8 rd, u16 offset16, u16 data16); + void xor_word_indrdoff16_data16(u8 rd, u16 offset16, u16 data16); + void mov_word_indrdoff16_data16(u8 rd, u16 offset16, u16 data16); + + void add_word_direct_data16(u16 direct, u16 data16); + void addc_word_direct_data16(u16 direct, u16 data16); + void sub_word_direct_data16(u16 direct, u16 data16); + void subb_word_direct_data16(u16 direct, u16 data16); + void cmp_word_direct_data16(u16 direct, u16 data16); + void and_word_direct_data16(u16 direct, u16 data16); + void or_word_direct_data16(u16 direct, u16 data16); + void xor_word_direct_data16(u16 direct, u16 data16); + void mov_word_direct_data16(u16 direct, u16 data16); + + void aluop_word_rd_rs(int alu_op, u8 rd, u8 rs); + void aluop_byte_rd_rs(int alu_op, u8 rd, u8 rs); + void aluop_word_rd_indrs(int alu_op, u8 rd, u8 rs); + void aluop_byte_rd_indrs(int alu_op, u8 rd, u8 rs); + void aluop_word_indrd_rs(int alu_op, u8 rd, u8 rs); + void aluop_byte_indrd_rs(int alu_op, u8 rd, u8 rs); + void aluop_word_rd_indrsinc(int alu_op, u8 rd, u8 rs); + void aluop_byte_rd_indrsinc(int alu_op, u8 rd, u8 rs); + void aluop_word_indrdinc_rs(int alu_op, u8 rd, u8 rs); + void aluop_byte_indrdinc_rs(int alu_op, u8 rd, u8 rs); + void aluop_word_rd_rsoff8(int alu_op, u8 rd, u8 rs, u8 offset8); + void aluop_byte_rd_rsoff8(int alu_op, u8 rd, u8 rs, u8 offset8); + void aluop_word_rdoff8_rs(int alu_op, u8 rd, u8 offset8, u8 rs); + void aluop_byte_rdoff8_rs(int alu_op, u8 rd, u8 offset8, u8 rs); + void aluop_word_rsoff16(int alu_op, u8 rd, u8 rs, u16 offset16); + void aluop_byte_rsoff16(int alu_op, u8 rd, u8 rs, u16 offset16); + void aluop_word_rdoff16_rs(int alu_op, u8 rd, u16 offset16, u8 rs); + void aluop_byte_rdoff16_rs(int alu_op, u8 rd, u16 offset16, u8 rs); + void aluop_word_rd_direct(int alu_op, u8 rd, u16 direct); + void aluop_byte_rd_direct(int alu_op, u8 rd, u16 direct); + void aluop_word_direct_rs(int alu_op, u16 direct, u8 rs); + void aluop_byte_direct_rs(int alu_op, u16 direct, u8 rs); + + void aluop_byte_rd_data8(int alu_op, u8 rd, u8 data8); + void aluop_byte_indrd_data8(int alu_op, u8 rd, u8 data8); + void aluop_byte_indrdinc_data8(int alu_op, u8 rd, u8 data8); + void aluop_byte_rdoff8_data8(int alu_op, u8 rd, u8 offset8, u8 data8); + void aluop_byte_rdoff16_data8(int alu_op, u8 rd, u16 offset16, u8 data8); + void aluop_byte_direct_data8(int alu_op, u16 direct, u8 data8); + void aluop_byte_rd_data16(int alu_op, u8 rd, u16 data16); + void aluop_byte_indrd_data16(int alu_op, u8 rd, u16 data16); + void aluop_byte_indrdinc_data16(int alu_op, u8 rd, u16 data16); + void aluop_byte_rdoff8_data16(int alu_op, u8 rd, u8 offset8, u16 data16); + void aluop_byte_rdoff16_data16(int alu_op, u8 rd, u16 offset16, u16 data16); + void aluop_byte_direct_data16(int alu_op, u16 direct, u16 data16); + + void add_word_rd_rs(u8 rd, u8 rs); + void addc_word_rd_rs(u8 rd, u8 rs); + void sub_word_rd_rs(u8 rd, u8 rs); + void subb_word_rd_rs(u8 rd, u8 rs); + void cmp_word_rd_rs(u8 rd, u8 rs); + void and_word_rd_rs(u8 rd, u8 rs); + void or_word_rd_rs(u8 rd, u8 rs); + void xor_word_rd_rs(u8 rd, u8 rs); + void mov_word_rd_rs(u8 rd, u8 rs); + + void add_byte_rd_rs(u8 rd, u8 rs); + void addc_byte_rd_rs(u8 rd, u8 rs); + void sub_byte_rd_rs(u8 rd, u8 rs); + void subb_byte_rd_rs(u8 rd, u8 rs); + void cmp_byte_rd_rs(u8 rd, u8 rs); + void and_byte_rd_rs(u8 rd, u8 rs); + void or_byte_rd_rs(u8 rd, u8 rs); + void xor_byte_rd_rs(u8 rd, u8 rs); + void mov_byte_rd_rs(u8 rd, u8 rs); + + void add_word_rd_indrs(u8 rd, u8 rs); + void addc_word_rd_indrs(u8 rd, u8 rs); + void sub_word_rd_indrs(u8 rd, u8 rs); + void subb_word_rd_indrs(u8 rd, u8 rs); + void cmp_word_rd_indrs(u8 rd, u8 rs); + void and_word_rd_indrs(u8 rd, u8 rs); + void or_word_rd_indrs(u8 rd, u8 rs); + void xor_word_rd_indrs(u8 rd, u8 rs); + void mov_word_rd_indrs(u8 rd, u8 rs); + + void add_byte_rd_indrs(u8 rd, u8 rs); + void addc_byte_rd_indrs(u8 rd, u8 rs); + void sub_byte_rd_indrs(u8 rd, u8 rs); + void subb_byte_rd_indrs(u8 rd, u8 rs); + void cmp_byte_rd_indrs(u8 rd, u8 rs); + void and_byte_rd_indrs(u8 rd, u8 rs); + void or_byte_rd_indrs(u8 rd, u8 rs); + void xor_byte_rd_indrs(u8 rd, u8 rs); + void mov_byte_rd_indrs(u8 rd, u8 rs); + + void add_word_indrd_rs(u8 rd, u8 rs); + void addc_word_indrd_rs(u8 rd, u8 rs); + void sub_word_indrd_rs(u8 rd, u8 rs); + void subb_word_indrd_rs(u8 rd, u8 rs); + void cmp_word_indrd_rs(u8 rd, u8 rs); + void and_word_indrd_rs(u8 rd, u8 rs); + void or_word_indrd_rs(u8 rd, u8 rs); + void xor_word_indrd_rs(u8 rd, u8 rs); + void mov_word_indrd_rs(u8 rd, u8 rs); + + void add_byte_indrd_rs(u8 rd, u8 rs); + void addc_byte_indrd_rs(u8 rd, u8 rs); + void sub_byte_indrd_rs(u8 rd, u8 rs); + void subb_byte_indrd_rs(u8 rd, u8 rs); + void cmp_byte_indrd_rs(u8 rd, u8 rs); + void and_byte_indrd_rs(u8 rd, u8 rs); + void or_byte_indrd_rs(u8 rd, u8 rs); + void xor_byte_indrd_rs(u8 rd, u8 rs); + void mov_byte_indrd_rs(u8 rd, u8 rs); + + void add_word_rd_indrsinc(u8 rd, u8 rs); + void addc_word_rd_indrsinc(u8 rd, u8 rs); + void sub_word_rd_indrsinc(u8 rd, u8 rs); + void subb_word_rd_indrsinc(u8 rd, u8 rs); + void cmp_word_rd_indrsinc(u8 rd, u8 rs); + void and_word_rd_indrsinc(u8 rd, u8 rs); + void or_word_rd_indrsinc(u8 rd, u8 rs); + void xor_word_rd_indrsinc(u8 rd, u8 rs); + void mov_word_rd_indrsinc(u8 rd, u8 rs); + + void add_byte_rd_indrsinc(u8 rd, u8 rs); + void addc_byte_rd_indrsinc(u8 rd, u8 rs); + void sub_byte_rd_indrsinc(u8 rd, u8 rs); + void subb_byte_rd_indrsinc(u8 rd, u8 rs); + void cmp_byte_rd_indrsinc(u8 rd, u8 rs); + void and_byte_rd_indrsinc(u8 rd, u8 rs); + void or_byte_rd_indrsinc(u8 rd, u8 rs); + void xor_byte_rd_indrsinc(u8 rd, u8 rs); + void mov_byte_rd_indrsinc(u8 rd, u8 rs); + + void add_word_indrdinc_rs(u8 rd, u8 rs); + void addc_word_indrdinc_rs(u8 rd, u8 rs); + void sub_word_indrdinc_rs(u8 rd, u8 rs); + void subb_word_indrdinc_rs(u8 rd, u8 rs); + void cmp_word_indrdinc_rs(u8 rd, u8 rs); + void and_word_indrdinc_rs(u8 rd, u8 rs); + void or_word_indrdinc_rs(u8 rd, u8 rs); + void xor_word_indrdinc_rs(u8 rd, u8 rs); + void mov_word_indrdinc_rs(u8 rd, u8 rs); + + void add_byte_indrdinc_rs(u8 rd, u8 rs); + void addc_byte_indrdinc_rs(u8 rd, u8 rs); + void sub_byte_indrdinc_rs(u8 rd, u8 rs); + void subb_byte_indrdinc_rs(u8 rd, u8 rs); + void cmp_byte_indrdinc_rs(u8 rd, u8 rs); + void and_byte_indrdinc_rs(u8 rd, u8 rs); + void or_byte_indrdinc_rs(u8 rd, u8 rs); + void xor_byte_indrdinc_rs(u8 rd, u8 rs); + void mov_byte_indrdinc_rs(u8 rd, u8 rs); + + void add_word_rd_rsoff8(u8 rd, u8 rs, u8 offset8); + void addc_word_rd_rsoff8(u8 rd, u8 rs, u8 offset8); + void sub_word_rd_rsoff8(u8 rd, u8 rs, u8 offset8); + void subb_word_rd_rsoff8(u8 rd, u8 rs, u8 offset8); + void cmp_word_rd_rsoff8(u8 rd, u8 rs, u8 offset8); + void and_word_rd_rsoff8(u8 rd, u8 rs, u8 offset8); + void or_word_rd_rsoff8(u8 rd, u8 rs, u8 offset8); + void xor_word_rd_rsoff8(u8 rd, u8 rs, u8 offset8); + void mov_word_rd_rsoff8(u8 rd, u8 rs, u8 offset8); + + void add_byte_rd_rsoff8(u8 rd, u8 rs, u8 offset8); + void addc_byte_rd_rsoff8(u8 rd, u8 rs, u8 offset8); + void sub_byte_rd_rsoff8(u8 rd, u8 rs, u8 offset8); + void subb_byte_rd_rsoff8(u8 rd, u8 rs, u8 offset8); + void cmp_byte_rd_rsoff8(u8 rd, u8 rs, u8 offset8); + void and_byte_rd_rsoff8(u8 rd, u8 rs, u8 offset8); + void or_byte_rd_rsoff8(u8 rd, u8 rs, u8 offset8); + void xor_byte_rd_rsoff8(u8 rd, u8 rs, u8 offset8); + void mov_byte_rd_rsoff8(u8 rd, u8 rs, u8 offset8); + + void add_word_rdoff8_rs(u8 rd, u8 offset8, u8 rs); + void addc_word_rdoff8_rs(u8 rd, u8 offset8, u8 rs); + void sub_word_rdoff8_rs(u8 rd, u8 offset8, u8 rs); + void subb_word_rdoff8_rs(u8 rd, u8 offset8, u8 rs); + void cmp_word_rdoff8_rs(u8 rd, u8 offset8, u8 rs); + void and_word_rdoff8_rs(u8 rd, u8 offset8, u8 rs); + void or_word_rdoff8_rs(u8 rd, u8 offset8, u8 rs); + void xor_word_rdoff8_rs(u8 rd, u8 offset8, u8 rs); + void mov_word_rdoff8_rs(u8 rd, u8 offset8, u8 rs); + + void add_byte_rdoff8_rs(u8 rd, u8 offset8, u8 rs); + void addc_byte_rdoff8_rs(u8 rd, u8 offset8, u8 rs); + void sub_byte_rdoff8_rs(u8 rd, u8 offset8, u8 rs); + void subb_byte_rdoff8_rs(u8 rd, u8 offset8, u8 rs); + void cmp_byte_rdoff8_rs(u8 rd, u8 offset8, u8 rs); + void and_byte_rdoff8_rs(u8 rd, u8 offset8, u8 rs); + void or_byte_rdoff8_rs(u8 rd, u8 offset8, u8 rs); + void xor_byte_rdoff8_rs(u8 rd, u8 offset8, u8 rs); + void mov_byte_rdoff8_rs(u8 rd, u8 offset8, u8 rs); + + void add_word_rd_rsoff16(u8 rd, u8 rs, u16 offset16); + void addc_word_rd_rsoff16(u8 rd, u8 rs, u16 offset16); + void sub_word_rd_rsoff16(u8 rd, u8 rs, u16 offset16); + void subb_word_rd_rsoff16(u8 rd, u8 rs, u16 offset16); + void cmp_word_rd_rsoff16(u8 rd, u8 rs, u16 offset16); + void and_word_rd_rsoff16(u8 rd, u8 rs, u16 offset16); + void or_word_rd_rsoff16(u8 rd, u8 rs, u16 offset16); + void xor_word_rd_rsoff16(u8 rd, u8 rs, u16 offset16); + void mov_word_rd_rsoff16(u8 rd, u8 rs, u16 offset16); + + void add_byte_rd_rsoff16(u8 rd, u8 rs, u16 offset16); + void addc_byte_rd_rsoff16(u8 rd, u8 rs, u16 offset16); + void sub_byte_rd_rsoff16(u8 rd, u8 rs, u16 offset16); + void subb_byte_rd_rsoff16(u8 rd, u8 rs, u16 offset16); + void cmp_byte_rd_rsoff16(u8 rd, u8 rs, u16 offset16); + void and_byte_rd_rsoff16(u8 rd, u8 rs, u16 offset16); + void or_byte_rd_rsoff16(u8 rd, u8 rs, u16 offset16); + void xor_byte_rd_rsoff16(u8 rd, u8 rs, u16 offset16); + void mov_byte_rd_rsoff16(u8 rd, u8 rs, u16 offset16); + + void add_word_rdoff16_rs(u8 rd, u16 offset16, u8 rs); + void addc_word_rdoff16_rs(u8 rd, u16 offset16, u8 rs); + void sub_word_rdoff16_rs(u8 rd, u16 offset16, u8 rs); + void subb_word_rdoff16_rs(u8 rd, u16 offset16, u8 rs); + void cmp_word_rdoff16_rs(u8 rd, u16 offset16, u8 rs); + void and_word_rdoff16_rs(u8 rd, u16 offset16, u8 rs); + void or_word_rdoff16_rs(u8 rd, u16 offset16, u8 rs); + void xor_word_rdoff16_rs(u8 rd, u16 offset16, u8 rs); + void mov_word_rdoff16_rs(u8 rd, u16 offset16, u8 rs); + + void add_byte_rdoff16_rs(u8 rd, u16 offset16, u8 rs); + void addc_byte_rdoff16_rs(u8 rd, u16 offset16, u8 rs); + void sub_byte_rdoff16_rs(u8 rd, u16 offset16, u8 rs); + void subb_byte_rdoff16_rs(u8 rd, u16 offset16, u8 rs); + void cmp_byte_rdoff16_rs(u8 rd, u16 offset16, u8 rs); + void and_byte_rdoff16_rs(u8 rd, u16 offset16, u8 rs); + void or_byte_rdoff16_rs(u8 rd, u16 offset16, u8 rs); + void xor_byte_rdoff16_rs(u8 rd, u16 offset16, u8 rs); + void mov_byte_rdoff16_rs(u8 rd, u16 offset16, u8 rs); + + void add_word_rd_direct(u8 rd, u16 direct); + void addc_word_rd_direct(u8 rd, u16 direct); + void sub_word_rd_direct(u8 rd, u16 direct); + void subb_word_rd_direct(u8 rd, u16 direct); + void cmp_word_rd_direct(u8 rd, u16 direct); + void and_word_rd_direct(u8 rd, u16 direct); + void or_word_rd_direct(u8 rd, u16 direct); + void xor_word_rd_direct(u8 rd, u16 direct); + void mov_word_rd_direct(u8 rd, u16 direct); + + void add_byte_rd_direct(u8 rd, u16 direct); + void addc_byte_rd_direct(u8 rd, u16 direct); + void sub_byte_rd_direct(u8 rd, u16 direct); + void subb_byte_rd_direct(u8 rd, u16 direct); + void cmp_byte_rd_direct(u8 rd, u16 direct); + void and_byte_rd_direct(u8 rd, u16 direct); + void or_byte_rd_direct(u8 rd, u16 direct); + void xor_byte_rd_direct(u8 rd, u16 direct); + void mov_byte_rd_direct(u8 rd, u16 direct); + + void add_word_direct_rs(u16 direct, u8 rs); + void addc_word_direct_rs(u16 direct, u8 rs); + void sub_word_direct_rs(u16 direct, u8 rs); + void subb_word_direct_rs(u16 direct, u8 rs); + void cmp_word_direct_rs(u16 direct, u8 rs); + void and_word_direct_rs(u16 direct, u8 rs); + void or_word_direct_rs(u16 direct, u8 rs); + void xor_word_direct_rs(u16 direct, u8 rs); + void mov_word_direct_rs(u16 direct, u8 rs); + + void add_byte_direct_rs(u16 direct, u8 rs); + void addc_byte_direct_rs(u16 direct, u8 rs); + void sub_byte_direct_rs(u16 direct, u8 rs); + void subb_byte_direct_rs(u16 direct, u8 rs); + void cmp_byte_direct_rs(u16 direct, u8 rs); + void and_byte_direct_rs(u16 direct, u8 rs); + void or_byte_direct_rs(u16 direct, u8 rs); + void xor_byte_direct_rs(u16 direct, u8 rs); + void mov_byte_direct_rs(u16 direct, u8 rs); + + void movs_word_rd_data4(u8 rd, u8 data4); + void movs_byte_rd_data4(u8 rd, u8 data4); + void adds_word_rd_data4(u8 rd, u8 data4); + void adds_byte_rd_data4(u8 rd, u8 data4); + + void movs_word_indrd_data4(u8 rd, u8 data4); + void movs_byte_indrd_data4(u8 rd, u8 data4); + void adds_word_indrd_data4(u8 rd, u8 data4); + void adds_byte_indrd_data4(u8 rd, u8 data4); + + void movs_word_indrdinc_data4(u8 rd, u8 data4); + void movs_byte_indrdinc_data4(u8 rd, u8 data4); + void adds_word_indrdinc_data4(u8 rd, u8 data4); + void adds_byte_indrdinc_data4(u8 rd, u8 data4); + + void movs_word_indrdoff8_data4(u8 rd, u8 off8, u8 data4); + void movs_byte_indrdoff8_data4(u8 rd, u8 off8, u8 data4); + void adds_word_indrdoff8_data4(u8 rd, u8 off8, u8 data4); + void adds_byte_indrdoff8_data4(u8 rd, u8 off8, u8 data4); + + void movs_word_indrdoff16_data4(u8 rd, u16 off16, u8 data4); + void movs_byte_indrdoff16_data4(u8 rd, u16 off16, u8 data4); + void adds_word_indrdoff16_data4(u8 rd, u16 off16, u8 data4); + void adds_byte_indrdoff16_data4(u8 rd, u16 off16, u8 data4); + + void movs_word_direct_data4(u16 direct, u8 data4); + void movs_byte_direct_data4(u16 direct, u8 data4); + void adds_word_direct_data4(u16 direct, u8 data4); + void adds_byte_direct_data4(u16 direct, u8 data4); + + void call_rel16(u16 rel16); + + void bcc_rel8(u8 rel8); + void bcs_rel8(u8 rel8); + void bne_rel8(u8 rel8); + void beq_rel8(u8 rel8); + void bnv_rel8(u8 rel8); + void bov_rel8(u8 rel8); + void bpl_rel8(u8 rel8); + void bmi_rel8(u8 rel8); + void bg_rel8(u8 rel8); + void bl_rel8(u8 rel8); + void bge_rel8(u8 rel8); + void blt_rel8(u8 rel8); + void bgt_rel8(u8 rel8); + void ble_rel8(u8 rel8); + void br_rel8(u8 rel8); + + void asl_byte_rd_imm4(u8 rd, u8 amount); + void asl_word_rd_imm4(u8 rd, u8 amount); + void asl_dword_rd_imm5(u8 rd, u8 amount); + + void asr_byte_rd_imm4(u8 rd, u8 amount); + void asr_word_rd_imm4(u8 rd, u8 amount); + void asr_dword_rd_imm5(u8 rd, u8 amount); + + void lsr_byte_rd_imm4(u8 rd, u8 amount); + void lsr_word_rd_imm4(u8 rd, u8 amount); + void lsr_dword_rd_imm5(u8 rd, u8 amount); + + void asl_byte_rd_rs(u8 rd, u8 rs); + void asl_word_rd_rs(u8 rd, u8 rs); + void asl_dword_rd_rs(u8 rd, u8 rs); + + void asr_byte_rd_rs(u8 rd, u8 rs); + void asr_word_rd_rs(u8 rd, u8 rs); + void asr_dword_rd_rs(u8 rd, u8 rs); + + void lsr_byte_rd_rs(u8 rd, u8 rs); + void lsr_word_rd_rs(u8 rd, u8 rs); + void lsr_dword_rd_rs(u8 rd, u8 rs); + + void norm_byte_rd_rs(u8 rd, u8 rs); + void norm_word_rd_rs(u8 rd, u8 rs); + void norm_dword_rd_rs(u8 rd, u8 rs); + + void mulu_byte_rd_rs(u8 rd, u8 rs); + void divu_byte_rd_rs(u8 rd, u8 rs); + void mulu_word_rd_rs(u8 rd, u8 rs); + void divu_word_rd_rs(u8 rd, u8 rs); + void mul_word_rd_rs(u8 rd, u8 rs); + void div_word_rd_rs(u8 rd, u8 rs); + void div_word_rd_data8(u8 rd, u8 data8); + void divu_byte_rd_data8(u8 rd, u8 data8); + void divu_word_rd_data8(u8 rd, u8 data8); + void mulu_byte_rd_data8(u8 rd, u8 data8); + void mulu_word_rd_data16(u8 rd, u16 data16); + void mul_word_rd_data16(u8 rd, u16 data16); + void divu_dword_rd_data16(u8 rd, u16 data16); + void div_dword_rd_data16(u8 rd, u16 data16); + void divu_dword_rd_rs(u8 rd, u8 rs); + void div_dword_rd_rs(u8 rd, u8 rs); + + void clr_bit(u16 bit); + void setb_bit(u16 bit); + void mov_c_bit(u16 bit); + void mov_bit_c(u16 bit); + void anl_c_bit(u16 bit); + void anl_c_notbit(u16 bit); + void orl_c_bit(u16 bit); + void orl_c_notbit(u16 bit); + + void lea_word_rd_rs_off8(u8 rd, u8 rs, u8 offs8); + void lea_word_rd_rs_off16(u8 rd, u8 rs, u16 offs16); + + void xch_word_rd_indrs(u8 rd, u8 rs); + void xch_byte_rd_indrs(u8 rd, u8 rs); + void xch_word_rd_rs(u8 rd, u8 rs); + void xch_byte_rd_rs(u8 rd, u8 rs); + + void movc_word_rd_indrsinc(u8 rd, u8 rs); + void movc_byte_rd_indrsinc(u8 rd, u8 rs); + + void djnz_word_rd_rel8(u8 rd, u8 rel8); + void djnz_byte_rd_rel8(u8 rd, u8 rel8); + + void popu_word_direct(u16 direct); + void popu_byte_direct(u16 direct); + void pop_word_direct(u16 direct); + void pop_byte_direct(u16 direct); + void pushu_word_direct(u16 direct); + void pushu_byte_direct(u16 direct); + void push_word_direct(u16 direct); + void push_byte_direct(u16 direct); + + void mov_word_indrdinc_indrsinc(u8 rd, u8 rs); + void mov_byte_indrdinc_indrsinc(u8 rd, u8 rs); + + void da_rd(u8 rd); + void sext_word_rd(u8 rd); + void sext_byte_rd(u8 rd); + void cpl_word_rd(u8 rd); + void cpl_byte_rd(u8 rd); + void neg_word_rd(u8 rd); + void neg_byte_rd(u8 rd); + void movc_a_apc(); + void movc_a_adptr(); + void mov_rd_usp(u8 rd); + void mov_usp_rs(u8 rs); + + void jb_bit_rel8(u16 bit, u8 rel8); + void jnb_bit_rel8(u16 bit, u8 rel8); + void jbc_bit_rel8(u16 bit, u8 rel8); + + void mov_word_direct_direct(u16 direct1, u16 direct2); + void mov_byte_direct_direct(u16 direct1, u16 direct2); + + void xch_word_rd_direct(u8 rd, u16 direct); + void xch_byte_rd_direct(u8 rd, u16 direct); + + void mov_word_direct_indrs(u16 direct, u8 rs); + void mov_byte_direct_indrs(u16 direct, u8 rs); + + void mov_word_indrd_direct(u8 rd, u16 direct); + void mov_byte_indrd_direct(u8 rd, u16 direct); + + void movx_word_indrd_rs(u8 rd, u8 rs); + void movx_byte_indrd_rs(u8 rd, u8 rs); + + void movx_word_rd_indrs(u8 rd, u8 rs); + void movx_byte_rd_indrs(u8 rd, u8 rs); + + void rr_word_rd_data4(u8 rd, u8 data4); + void rr_byte_rd_data4(u8 rd, u8 data4); + + void rrc_word_rd_data4(u8 rd, u8 data4); + void rrc_byte_rd_data4(u8 rd, u8 data4); + + void rl_word_rd_data4(u8 rd, u8 data4); + void rl_byte_rd_data4(u8 rd, u8 data4); + + void rlc_word_rd_data4(u8 rd, u8 data4); + void rlc_byte_rd_data4(u8 rd, u8 data4); + + void fcall_addr24(u32 addr24); + void call_indrs(u8 rs); + void fjmp_addr24(u32 addr24); + void jmp_rel16(u16 rel16); + + void djnz_word_direct_rel8(u16 direct, u8 rel8); + void djnz_byte_direct_rel8(u16 direct, u8 rel8); + + void cjne_word_rd_direct_rel8(u8 rd, u16 direct, u8 rel8); + void cjne_byte_rd_direct_rel8(u8 rd, u16 direct, u8 rel8); + + void cjne_indrd_data8_rel8(u8 rd, u8 data8, u8 rel8); + void cjne_rd_data8_rel8(u8 rd, u8 data8, u8 rel8); + + void cjne_indrd_data16_rel8(u8 rd, u16 data16, u8 rel8); + void cjne_rd_data16_rel8(u8 rd, u16 data16, u8 rel8); + + void reset(); + void trap_data4(u8 data4); + void jmp_ind_adptr(); + void jmp_dblindrs(u8 rs); + void jmp_indrs(u8 rs); + void ret(); + void reti(); + + void jz_rel8(u8 rel8); + void jnz_rel8(u8 rel8); + + void push_word_rlist(u8 bitfield, int h); + void push_byte_rlist(u8 bitfield, int h); + + void pushu_word_rlist(u8 bitfield, int h); + void pushu_byte_rlist(u8 bitfield, int h); + + void pop_word_rlist(u8 bitfield, int h); + void pop_byte_rlist(u8 bitfield, int h); + + void popu_word_rlist(u8 bitfield, int h); + void popu_byte_rlist(u8 bitfield, int h); + + std::unordered_map m_names; + + u8 m_im; + u8 m_rs; + u8 m_zflag; + u8 m_nflag; + u8 m_vflag; + u8 m_cflag; + u8 m_acflag; + u8 m_sm_flag; + u8 m_tm_flag; + u8 m_p_flag; + u8 m_f0_flag; + u8 m_f1_flag; uint32_t m_pc; + bool m_usermode; + u8 m_pagezeromode; + + u16 m_USP; // user stack pointer + u16 m_SSP; // system stack pointer + + u8 m_WDCON; + u8 m_SCR; + u8 m_IEL; + u8 m_PSWL; + u8 m_PSWH; + + u8 m_regbank; + + u8 m_PxCFGA[4]; + u8 m_PxCFGB[4]; + + // hacks for IRQ testing + u8 m_in_interrupt; + u8 m_irq_pending; + + + // 16-bit regs R0-R3 can have 4 selectable banks, R4-R7 are global + // for 8-bit use each register can be seen as High and Low parts + // R4 when split is R4H and R4L, R4L acts as ACC from i8051 for compatibility, R4H acts as B + // R6H is DPH, R6L is DPL + u16 m_regs[(4 * 4) + 4]; + address_space *m_program; + address_space *m_data; + address_space *m_sfr; int m_icount; + + devcb_read8::array<4> m_port_in_cb; + devcb_write8::array<4> m_port_out_cb; }; -class mx10exa_cpu_device : public xa_cpu_device +class mx10exa_cpu_device : public xa_cpu { 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); + void mx10exa_internal_data_map(address_map &map); + }; -DECLARE_DEVICE_TYPE(XA, xa_cpu_device) +DECLARE_DEVICE_TYPE(XA, xa_cpu) DECLARE_DEVICE_TYPE(MX10EXA, mx10exa_cpu_device) #endif // MAME_CPU_XA_XA_H diff --git a/src/devices/cpu/xa/xa_ops.cpp b/src/devices/cpu/xa/xa_ops.cpp new file mode 100644 index 00000000000..ae803581380 --- /dev/null +++ b/src/devices/cpu/xa/xa_ops.cpp @@ -0,0 +1,1893 @@ +// license:BSD-3-Clause +// copyright-holders:David Haywood + +#include "emu.h" +#include "xa.h" +#include "xadasm.h" + +#define get_addr gr16 +#define set_addr sr16 + +u32 xa_cpu::gr32(int reg) +{ + if (reg & 1) + fatalerror("gr32 with low bit set\n"); + + u16 reg1 = gr16(reg); + u16 reg2 = gr16(reg + 1); + + return (reg2 << 16) | reg1; +} + +void xa_cpu::sr32(int reg, u32 data) +{ + if (reg & 1) + fatalerror("sr32 with low bit set\n"); + + sr16(reg, data & 0xffff); + sr16(reg + 1, (data >> 16) & 0xffff); +} + +u16 xa_cpu::do_subb_16(u16 val1, u16 val2) +{ + return do_sub_16_helper(val1, val2, get_c_flag()); +} + +u16 xa_cpu::do_sub_16(u16 val1, u16 val2) +{ + return do_sub_16_helper(val1, val2, 0); +} + +u16 xa_cpu::do_sub_16_helper(u16 val1, u16 val2, u8 c) +{ + u32 result = val1 - (val2 + c); + s32 result1 = (s16)val1 - (s16)(val2 + c); + u32 result3 = (val1 & 0x0fff) - ((val2 & 0x0fff) + c); + + if (result & 0x10000) set_c_flag(); else clear_c_flag(); + if (result3 & 0x1000) set_ac_flag(); else clear_ac_flag(); + if ((result1 < -32768 || result1 > 32767)) set_v_flag(); else clear_v_flag(); + + do_nz_flags_16((u16)result); + return (u16)result; +} + + +u16 xa_cpu::do_addc_16(u16 val1, u16 val2) +{ + return do_add_16_helper(val1, val2, get_c_flag()); +} + +u16 xa_cpu::do_add_16(u16 val1, u16 val2) +{ + return do_add_16_helper(val1, val2, 0); +} + + +u16 xa_cpu::do_add_16_helper(u16 val1, u16 val2, u8 c) +{ + u32 result = val1 + val2 + c; + s32 result1 = (s16)val1 + (s16)val2 + c; + u32 result3 = (val1 & 0x0fff) + (val2 & 0x0fff) + c; + if (result & 0x10000) set_c_flag(); else clear_c_flag(); + if (result3 & 0x1000) set_ac_flag(); else clear_ac_flag(); + if ((result1 < -32768 || result1 > 32767)) set_v_flag(); else clear_v_flag(); + + do_nz_flags_16((u16)result); + return (u16)result; +} + + +u16 xa_cpu::do_xor_16(u16 val1, u16 val2) +{ + u16 result = val1 ^ val2; + do_nz_flags_16(result); + return result; +} + +u16 xa_cpu::do_or_16(u16 val1, u16 val2) +{ + u16 result = val1 | val2; + do_nz_flags_16(result); + return result; +} + +u16 xa_cpu::do_and_16(u16 val1, u16 val2) +{ + u16 result = val1 & val2; + do_nz_flags_16(result); + return result; +} + +u32 xa_cpu::asl32_helper(u32 fullreg, u8 amount) +{ + cy(6 + (amount >> 1)); + + int lastbit = 0; + + u32 topbit = fullreg & 0x8000000; + + while (amount) + { + lastbit = fullreg & 0x8000000; + fullreg = fullreg << 1; + amount--; + } + + if (lastbit) + set_c_flag(); + else + clear_c_flag(); + + if (fullreg == 0) + set_z_flag(); + else + clear_z_flag(); + + if (fullreg & 0x8000000) + set_n_flag(); + else + clear_n_flag(); + + if (topbit != (fullreg & 0x8000000)) + set_v_flag(); + else + clear_v_flag(); + + return fullreg; +} + +u32 xa_cpu::lsr32_helper(u32 fullreg, u8 amount) +{ + cy(6 + (amount >> 1)); + + int lastbit = 0; + + while (amount) + { + lastbit = fullreg & 0x0000001; + fullreg = fullreg >> 1; + amount--; + } + + if (lastbit) + set_c_flag(); + else + clear_c_flag(); + + if (fullreg == 0) + set_z_flag(); + else + clear_z_flag(); + + if (fullreg & 0x8000000) + set_n_flag(); + else + clear_n_flag(); + + return fullreg; +} + +u16 xa_cpu::lsr16_helper(u16 fullreg, u8 amount) +{ + cy(6 + (amount >> 1)); + + int lastbit = 0; + + while (amount) + { + lastbit = fullreg & 0x0001; + fullreg = fullreg >> 1; + amount--; + } + + if (lastbit) + set_c_flag(); + else + clear_c_flag(); + + if (fullreg == 0) + set_z_flag(); + else + clear_z_flag(); + + if (fullreg & 0x8000) + set_n_flag(); + else + clear_n_flag(); + + return fullreg; +} + + +u8 xa_cpu::do_subb_8(u8 val1, u8 val2) +{ + return do_sub_8_helper(val1, val2, get_c_flag()); +} + +u8 xa_cpu::do_sub_8(u8 val1, u8 val2) +{ + return do_sub_8_helper(val1, val2, 0); +} + +u8 xa_cpu::do_sub_8_helper(u8 val1, u8 val2, u8 c) +{ + u16 result = val1 - (val2 + c); + s16 result1 = (s8)val1 - (s8)(val2 + c); + u16 result3 = (val1 & 0x0f) - ((val2 & 0x0f) + c); + if (result & 0x100) set_c_flag(); else clear_c_flag(); + if (result3 & 0x10) set_ac_flag(); else clear_ac_flag(); + if ((result1 < -128 || result1 > 127)) set_v_flag(); else clear_v_flag(); + + do_nz_flags_8((u8)result); + return (u8)result; +} + +u8 xa_cpu::do_addc_8(u8 val1, u8 val2) +{ + return do_add_8_helper(val1, val2, get_c_flag()); +} + +u8 xa_cpu::do_add_8(u8 val1, u8 val2) +{ + return do_add_8_helper(val1, val2, 0); +} + + +u8 xa_cpu::do_add_8_helper(u8 val1, u8 val2, u8 c) +{ + u16 result = val1 + val2 + c; + s16 result1 = (s8)val1 + (s8)val2 + c; + u16 result3 = (val1 & 0x0f) + (val2 & 0x0f) + c; + if (result & 0x100) set_c_flag(); else clear_c_flag(); + if (result3 & 0x10) set_ac_flag(); else clear_ac_flag(); + if ((result1 < -128 || result1 > 127)) set_v_flag(); else clear_v_flag(); + + do_nz_flags_8((u8)result); + return (u8)result; +} + +u8 xa_cpu::do_xor_8(u8 val1, u8 val2) +{ + u8 result = val1 ^ val2; + do_nz_flags_8(result); + return result; +} + +u8 xa_cpu::do_or_8(u8 val1, u8 val2) +{ + u8 result = val1 | val2; + do_nz_flags_8(result); + return result; +} + +u8 xa_cpu::do_and_8(u8 val1, u8 val2) +{ + u8 result = val1 & val2; + do_nz_flags_8(result); + return result; +} + + + +u8 xa_cpu::do_cjne_8_helper(u8 val1, u8 val2) +{ + u16 result = val1 - val2; + do_nz_flags_8((u8)result); + if (result & 0x100) set_c_flag(); else clear_c_flag(); + return (u8)result; +} + + +void xa_cpu::set_bit_8_helper(u16 bit, u8 val) +{ + int position = bit & 7; + + if (bit < 0x100) + { + int reg = ((bit & 0x1ff) >> 3); + + if (reg < 16) + fatalerror("set_bit_helper %s.%d", m_regnames8[reg], position); + else + fatalerror("set_bit_helper ill_REG_%02x.%d", reg, position); + } + else if (bit < 0x200) + { + int addr = ((bit & 0x1ff) >> 3) + 0x20; + fatalerror("set_bit_helper $%02x.%d", addr, position); + } + + int sfr = ((bit & 0x1ff) >> 3); + u8 mask = (1 << position) ^ 0xff; + + u8 sfr_val = m_sfr->read_byte(sfr) & mask; + sfr_val |= (val << position); + m_sfr->write_byte(sfr, sfr_val); +} + +// NOP No operation 1 3 0000 0000 +void xa_cpu::do_nop() { cy(3); } + +// ALUOP.b Rd, data8 +// ADD Rd, #data8 Add 8-bit imm data to reg 3 3 1001 0001 dddd 0000 iiii iiii +// ADDC Rd, #data8 Add 8-bit imm data to reg w/ carry 3 3 1001 0001 dddd 0001 iiii iiii +// SUB Rd, #data8 Subtract 8-bit imm data to reg 3 3 1001 0001 dddd 0010 iiii iiii +// SUBB Rd, #data8 Subtract w/ borrow 8-bit imm data to reg 3 3 1001 0001 dddd 0011 iiii iiii +// CMP Rd, #data8 Compare 8-bit imm data to reg 3 3 1001 0001 dddd 0100 iiii iiii +// AND Rd, #data8 Logical AND 8-bit imm data to reg 3 3 1001 0001 dddd 0101 iiii iiii +// OR Rd, #data8 Logical OR 8-bit imm data to reg 3 3 1001 0001 dddd 0110 iiii iiii +// XOR Rd, #data8 Logical XOR 8-bit imm data to reg 3 3 1001 0001 dddd 0111 iiii iiii +// MOV Rd, #data8 Move 8-bit imm data to reg 3 3 1001 0001 dddd 1000 iiii iiii +void xa_cpu::aluop_byte_rd_data8(int alu_op, u8 rd, u8 data8) +{ + switch (alu_op) + { + case 0x0: add_byte_rd_data8(rd, data8); break; + case 0x1: addc_byte_rd_data8(rd, data8); break; + case 0x2: sub_byte_rd_data8(rd, data8); break; + case 0x3: subb_byte_rd_data8(rd, data8); break; + case 0x4: cmp_byte_rd_data8(rd, data8); break; + case 0x5: and_byte_rd_data8(rd, data8); break; + case 0x6: or_byte_rd_data8(rd, data8); break; + case 0x7: xor_byte_rd_data8(rd, data8); break; + case 0x8: mov_byte_rd_data8(rd, data8); break; + default: logerror("UNK_ALUOP.b %s, #$%02x", m_regnames8[rd], data8); do_nop(); break; + } +} + +void xa_cpu::add_byte_rd_data8(u8 rd, u8 data8) { u8 rdval = gr8(rd); u8 result = do_add_8(rdval, data8); sr8(rd, result); cy(3); } +void xa_cpu::addc_byte_rd_data8(u8 rd, u8 data8){ u8 rdval = gr8(rd); u8 result = do_addc_8(rdval, data8); sr8(rd, result); cy(3); } +void xa_cpu::sub_byte_rd_data8(u8 rd, u8 data8) { u8 rdval = gr8(rd); u8 result = do_sub_8(rdval, data8); sr8(rd, result); cy(3); } +void xa_cpu::subb_byte_rd_data8(u8 rd, u8 data8){ u8 rdval = gr8(rd); u8 result = do_subb_8(rdval, data8); sr8(rd, result); cy(3); } +void xa_cpu::cmp_byte_rd_data8(u8 rd, u8 data8) { u8 rdval = gr8(rd); do_sub_8(rdval, data8); cy(3); } +void xa_cpu::and_byte_rd_data8(u8 rd, u8 data8) { u8 rdval = gr8(rd); u8 result = do_and_8(rdval, data8); sr8(rd, result); cy(3); } +void xa_cpu::or_byte_rd_data8(u8 rd, u8 data8) { u8 rdval = gr8(rd); u8 result = do_or_8(rdval, data8); sr8(rd, result); cy(3); } +void xa_cpu::xor_byte_rd_data8(u8 rd, u8 data8) { u8 rdval = gr8(rd); u8 result = do_xor_8(rdval, data8); sr8(rd, result); cy(3); } +void xa_cpu::mov_byte_rd_data8(u8 rd, u8 data8) { u8 result = data8; do_nz_flags_8(result); sr8(rd, result); cy(3); } + +// ------------------------------------------ + +// ALUOP.b [Rd], data8 +// ADD [Rd], #data8 Add 8-bit imm data to reg-ind 3 4 1001 0010 0ddd 0000 iiii iiii +// ADDC [Rd], #data8 Add 16-bit imm data to reg-ind w/ carry 3 4 1001 0010 0ddd 0001 iiii iiii +// SUB [Rd], #data8 Subtract 8-bit imm data to reg-ind 3 4 1001 0010 0ddd 0010 iiii iiii +// SUBB [Rd], #data8 Subtract w/ borrow 8-bit imm data to reg-ind 3 4 1001 0010 0ddd 0011 iiii iiii +// CMP [Rd], #data8 Compare 8-bit imm data to reg-ind 3 4 1001 0010 0ddd 0100 iiii iiii +// AND [Rd], #data8 Logical AND 8-bit imm data to reg-ind 3 4 1001 0010 0ddd 0101 iiii iiii +// OR [Rd], #data8 Logical OR 8-bit imm data to reg-ind 3 4 1001 0010 0ddd 0110 iiii iiii +// XOR [Rd], #data8 Logical XOR 8-bit imm data to reg-ind 3 4 1001 0010 0ddd 0111 iiii iiii +// MOV [Rd], #data8 Move 16-bit imm data to reg-ind 3 3 1001 0010 0ddd 1000 iiii iiii +void xa_cpu::aluop_byte_indrd_data8(int alu_op, u8 rd, u8 data8) +{ + switch (alu_op) + { + case 0x0: add_byte_indrd_data8(rd, data8); break; + case 0x1: addc_byte_indrd_data8(rd, data8); break; + case 0x2: sub_byte_indrd_data8(rd, data8); break; + case 0x3: subb_byte_indrd_data8(rd, data8); break; + case 0x4: cmp_byte_indrd_data8(rd, data8); break; + case 0x5: and_byte_indrd_data8(rd, data8); break; + case 0x6: or_byte_indrd_data8(rd, data8); break; + case 0x7: xor_byte_indrd_data8(rd, data8); break; + case 0x8: mov_byte_indrd_data8(rd, data8); break; + default: logerror("UNK_ALUOP.b [%s], #$%02x", m_regnames16[rd], data8); do_nop(); break; + } +} +void xa_cpu::add_byte_indrd_data8(u8 rd, u8 data8) { fatalerror( "ADD.b [%s], #$%02x ([RD], DATA8)", m_regnames16[rd], data8 ); } +void xa_cpu::addc_byte_indrd_data8(u8 rd, u8 data8){ fatalerror( "ADDC.b [%s], #$%02x ([RD], DATA8)", m_regnames16[rd], data8 ); } +void xa_cpu::sub_byte_indrd_data8(u8 rd, u8 data8) { fatalerror( "SUB.b [%s], #$%02x ([RD], DATA8)", m_regnames16[rd], data8 ); } +void xa_cpu::subb_byte_indrd_data8(u8 rd, u8 data8){ fatalerror( "SUBB.b [%s], #$%02x ([RD], DATA8)", m_regnames16[rd], data8 ); } +void xa_cpu::cmp_byte_indrd_data8(u8 rd, u8 data8) { u16 address = get_addr(rd); u8 rdval = rdat8(address); do_sub_8(rdval, data8); cy(3); } +void xa_cpu::and_byte_indrd_data8(u8 rd, u8 data8) { u16 address = get_addr(rd); u8 rdval = rdat8(address); u8 result = do_and_8(rdval, data8); wdat8(address, result); cy(3); } +void xa_cpu::or_byte_indrd_data8(u8 rd, u8 data8) { fatalerror( "OR.b [%s], #$%02x ([RD], DATA8)", m_regnames16[rd], data8 ); } +void xa_cpu::xor_byte_indrd_data8(u8 rd, u8 data8) { fatalerror( "XOR.b [%s], #$%02x ([RD], DATA8)", m_regnames16[rd], data8 ); } +void xa_cpu::mov_byte_indrd_data8(u8 rd, u8 data8) { fatalerror( "MOV.b [%s], #$%02x ([RD], DATA8)", m_regnames16[rd], data8 ); } + +// ------------------------------------------ +// ALUOP.b [Rd+], data8 +// ADD [Rd+], #data8 Add 8-bit imm data to reg-ind w/ autoinc 3 5 1001 0011 0ddd 0000 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 +// SUB [Rd+], #data8 Subtract 8-bit imm data to reg-ind w/ autoinc 3 5 1001 0011 0ddd 0010 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 +// CMP [Rd+], #data8 Compare 8-bit imm data to reg-ind w/ autoinc 3 5 1001 0011 0ddd 0100 iiii iiii +// AND [Rd+], #data8 Logical AND 8-bit imm data to reg-ind and autoinc 3 5 1001 0011 0ddd 0101 iiii iiii +// OR [Rd+], #data8 Logical OR 8-bit imm data to reg-ind w/ autoinc 3 5 1001 0011 0ddd 0110 iiii iiii +// XOR [Rd+], #data8 Logical XOR 8-bit imm data to reg-ind w/ autoinc 3 5 1001 0011 0ddd 0111 iiii iiii +// MOV [Rd+], #data8 Move 8-bit imm data to reg-ind w/ autoinc 3 4 1001 0011 0ddd 1000 iiii iiii +void xa_cpu::aluop_byte_indrdinc_data8(int alu_op, u8 rd, u8 data8) +{ + switch (alu_op) + { + case 0x0: add_byte_indrdinc_data8(rd, data8); break; + case 0x1: addc_byte_indrdinc_data8(rd, data8); break; + case 0x2: sub_byte_indrdinc_data8(rd, data8); break; + case 0x3: subb_byte_indrdinc_data8(rd, data8); break; + case 0x4: cmp_byte_indrdinc_data8(rd, data8); break; + case 0x5: and_byte_indrdinc_data8(rd, data8); break; + case 0x6: or_byte_indrdinc_data8(rd, data8); break; + case 0x7: xor_byte_indrdinc_data8(rd, data8); break; + case 0x8: mov_byte_indrdinc_data8(rd, data8); break; + default: logerror("UNK_ALUOP.b [%s+], #$%02x", m_regnames16[rd], data8); do_nop(); break; + } +} +void xa_cpu::add_byte_indrdinc_data8(u8 rd, u8 data8) { fatalerror( "ADD.b [%s+], #$%02x ([RD+], DATA8)", m_regnames16[rd], data8 ); } +void xa_cpu::addc_byte_indrdinc_data8(u8 rd, u8 data8){ fatalerror( "ADDC.b [%s+], #$%02x ([RD+], DATA8)", m_regnames16[rd], data8 ); } +void xa_cpu::sub_byte_indrdinc_data8(u8 rd, u8 data8) { fatalerror( "SUB.b [%s+], #$%02x ([RD+], DATA8)", m_regnames16[rd], data8 ); } +void xa_cpu::subb_byte_indrdinc_data8(u8 rd, u8 data8){ fatalerror( "SUBB.b [%s+], #$%02x ([RD+], DATA8)", m_regnames16[rd], data8 ); } +void xa_cpu::cmp_byte_indrdinc_data8(u8 rd, u8 data8) { fatalerror( "CMP.b [%s+], #$%02x ([RD+], DATA8)", m_regnames16[rd], data8 ); } +void xa_cpu::and_byte_indrdinc_data8(u8 rd, u8 data8) { fatalerror( "AND.b [%s+], #$%02x ([RD+], DATA8)", m_regnames16[rd], data8 ); } +void xa_cpu::or_byte_indrdinc_data8(u8 rd, u8 data8) { fatalerror( "OR.b [%s+], #$%02x ([RD+], DATA8)", m_regnames16[rd], data8 ); } +void xa_cpu::xor_byte_indrdinc_data8(u8 rd, u8 data8) { fatalerror( "XOR.b [%s+], #$%02x ([RD+], DATA8)", m_regnames16[rd], data8 ); } +void xa_cpu::mov_byte_indrdinc_data8(u8 rd, u8 data8) { fatalerror( "MOV.b [%s+], #$%02x ([RD+], DATA8)", m_regnames16[rd], data8 ); } + +// ------------------------------------------ +// ALUOP.b [Rd+offs8], data8 +// 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 +// 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 +// 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 +// 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 +// 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 +// 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 +// 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 +// 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 +// 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 +void xa_cpu::aluop_byte_rdoff8_data8(int alu_op, u8 rd, u8 offset8, u8 data8) +{ + switch (alu_op) + { + case 0x0: add_byte_indrdoff8_data8(rd, offset8, data8); break; + case 0x1: addc_byte_indrdoff8_data8(rd, offset8, data8); break; + case 0x2: sub_byte_indrdoff8_data8(rd, offset8, data8); break; + case 0x3: subb_byte_indrdoff8_data8(rd, offset8, data8); break; + case 0x4: cmp_byte_indrdoff8_data8(rd, offset8, data8); break; + case 0x5: and_byte_indrdoff8_data8(rd, offset8, data8); break; + case 0x6: or_byte_indrdoff8_data8(rd, offset8, data8); break; + case 0x7: xor_byte_indrdoff8_data8(rd, offset8, data8); break; + case 0x8: mov_byte_indrdoff8_data8(rd, offset8, data8); break; + default: logerror("UNK_ALUOP.b [%s+#$%02x], #$%02x", m_regnames16[rd], offset8, data8); do_nop(); break; + } +} +void xa_cpu::add_byte_indrdoff8_data8(u8 rd, u8 offset8, u8 data8) { u16 fulloffset = util::sext(offset8, 8); u16 address = get_addr(rd) + fulloffset; u8 val = rdat8(address); u8 result = do_add_8(val, data8); wdat8(address, result); cy(6); } +void xa_cpu::addc_byte_indrdoff8_data8(u8 rd, u8 offset8, u8 data8){ u16 fulloffset = util::sext(offset8, 8); u16 address = get_addr(rd) + fulloffset; u8 val = rdat8(address); u8 result = do_addc_8(val, data8); wdat8(address, result); cy(6); } +void xa_cpu::sub_byte_indrdoff8_data8(u8 rd, u8 offset8, u8 data8) { u16 fulloffset = util::sext(offset8, 8); u16 address = get_addr(rd) + fulloffset; u8 val = rdat8(address); u8 result = do_sub_8(val, data8); wdat8(address, result); cy(6); } +void xa_cpu::subb_byte_indrdoff8_data8(u8 rd, u8 offset8, u8 data8){ u16 fulloffset = util::sext(offset8, 8); u16 address = get_addr(rd) + fulloffset; u8 val = rdat8(address); u8 result = do_subb_8(val, data8); wdat8(address, result); cy(6); } +void xa_cpu::cmp_byte_indrdoff8_data8(u8 rd, u8 offset8, u8 data8) { u16 fulloffset = util::sext(offset8, 8); u16 address = get_addr(rd) + fulloffset; u8 val = rdat8(address); do_sub_8(val, data8); cy(6); } +void xa_cpu::and_byte_indrdoff8_data8(u8 rd, u8 offset8, u8 data8) { u16 fulloffset = util::sext(offset8, 8); u16 address = get_addr(rd) + fulloffset; u8 val = rdat8(address); u8 result = do_and_8(val, data8); wdat8(address, result); cy(6); } +void xa_cpu::or_byte_indrdoff8_data8(u8 rd, u8 offset8, u8 data8) { u16 fulloffset = util::sext(offset8, 8); u16 address = get_addr(rd) + fulloffset; u8 val = rdat8(address); u8 result = do_or_8(val, data8); wdat8(address, result); cy(6); } +void xa_cpu::xor_byte_indrdoff8_data8(u8 rd, u8 offset8, u8 data8) { u16 fulloffset = util::sext(offset8, 8); u16 address = get_addr(rd) + fulloffset; u8 val = rdat8(address); u8 result = do_xor_8(val, data8); wdat8(address, result); cy(6); } +void xa_cpu::mov_byte_indrdoff8_data8(u8 rd, u8 offset8, u8 data8) { u16 fulloffset = util::sext(offset8, 8); u16 address = get_addr(rd) + fulloffset; do_nz_flags_8(data8); wdat8(address, data8); cy(5); } + +// ------------------------------------------ +// ALUOP.b [Rd+offs16], data8 +// 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 +// 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 +// 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 +// 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 +// 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 +// 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 +// 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 +// 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 +// 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 +void xa_cpu::aluop_byte_rdoff16_data8(int alu_op, u8 rd, u16 offset16, u8 data8) +{ + switch (alu_op) + { + case 0x0: add_byte_indrdoff16_data8(rd, offset16, data8); break; + case 0x1: addc_byte_indrdoff16_data8(rd, offset16, data8); break; + case 0x2: sub_byte_indrdoff16_data8(rd, offset16, data8); break; + case 0x3: subb_byte_indrdoff16_data8(rd, offset16, data8); break; + case 0x4: cmp_byte_indrdoff16_data8(rd, offset16, data8); break; + case 0x5: and_byte_indrdoff16_data8(rd, offset16, data8); break; + case 0x6: or_byte_indrdoff16_data8(rd, offset16, data8); break; + case 0x7: xor_byte_indrdoff16_data8(rd, offset16, data8); break; + case 0x8: mov_byte_indrdoff16_data8(rd, offset16, data8); break; + default: logerror("UNK_ALUOP.b [%s+#$%04x], #$%02d", m_regnames16[rd], offset16, data8); do_nop(); break; + } +} +void xa_cpu::add_byte_indrdoff16_data8(u8 rd, u16 offset16, u8 data8) { u16 fulloffset = offset16; u16 address = get_addr(rd) + fulloffset; u8 val = rdat8(address); u8 result = do_add_8(val, data8); wdat8(address, result); cy(6); } +void xa_cpu::addc_byte_indrdoff16_data8(u8 rd, u16 offset16, u8 data8){ u16 fulloffset = offset16; u16 address = get_addr(rd) + fulloffset; u8 val = rdat8(address); u8 result = do_addc_8(val, data8); wdat8(address, result); cy(6); } +void xa_cpu::sub_byte_indrdoff16_data8(u8 rd, u16 offset16, u8 data8) { u16 fulloffset = offset16; u16 address = get_addr(rd) + fulloffset; u8 val = rdat8(address); u8 result = do_sub_8(val, data8); wdat8(address, result); cy(6); } +void xa_cpu::subb_byte_indrdoff16_data8(u8 rd, u16 offset16, u8 data8){ u16 fulloffset = offset16; u16 address = get_addr(rd) + fulloffset; u8 val = rdat8(address); u8 result = do_subb_8(val, data8); wdat8(address, result); cy(6); } +void xa_cpu::cmp_byte_indrdoff16_data8(u8 rd, u16 offset16, u8 data8) { u16 fulloffset = offset16; u16 address = get_addr(rd) + fulloffset; u8 val = rdat8(address); do_sub_8(val, data8); cy(6); } +void xa_cpu::and_byte_indrdoff16_data8(u8 rd, u16 offset16, u8 data8) { u16 fulloffset = offset16; u16 address = get_addr(rd) + fulloffset; u8 val = rdat8(address); u8 result = do_and_8(val, data8); wdat8(address, result); cy(6); } +void xa_cpu::or_byte_indrdoff16_data8(u8 rd, u16 offset16, u8 data8) { u16 fulloffset = offset16; u16 address = get_addr(rd) + fulloffset; u8 val = rdat8(address); u8 result = do_or_8(val, data8); wdat8(address, result); cy(6); } +void xa_cpu::xor_byte_indrdoff16_data8(u8 rd, u16 offset16, u8 data8) { u16 fulloffset = offset16; u16 address = get_addr(rd) + fulloffset; u8 val = rdat8(address); u8 result = do_xor_8(val, data8); wdat8(address, result); cy(6); } +void xa_cpu::mov_byte_indrdoff16_data8(u8 rd, u16 offset16, u8 data8) { u16 fulloffset = offset16; u16 address = get_addr(rd) + fulloffset; do_nz_flags_8(data8); wdat8(address, data8); cy(5); } + +// ------------------------------------------ +// ADD direct, #data8 Add 8-bit imm data to mem 4 4 1001 0110 0DDD 0000 DDDD DDDD iiii iiii +// ADDC direct, #data8 Add 8-bit imm data to mem w/ carry 4 4 1001 0110 0DDD 0001 DDDD DDDD iiii iiii +// SUB direct, #data8 Subtract 8-bit imm data to mem 4 4 1001 0110 0DDD 0010 DDDD DDDD iiii iiii +// SUBB direct, #data8 Subtract w/ borrow 8-bit imm data to mem 4 4 1001 0110 0DDD 0011 DDDD DDDD iiii iiii +// CMP direct, #data8 Compare 8-bit imm data to mem 4 4 1001 0110 0DDD 0100 DDDD DDDD iiii iiii +// AND direct, #data8 Logical AND 8-bit imm data to mem 4 4 1001 0110 0DDD 0101 DDDD DDDD iiii iiii +// OR direct, #data8 Logical OR 8-bit imm data to mem 4 4 1001 0110 0DDD 0110 DDDD DDDD iiii iiii +// XOR direct, #data8 Logical XOR 8-bit imm data to mem 4 4 1001 0110 0DDD 0111 DDDD DDDD iiii iiii +// MOV direct, #data8 Move 8-bit imm data to mem 4 3 1001 0110 0DDD 1000 DDDD DDDD iiii iiii +void xa_cpu::aluop_byte_direct_data8(int alu_op, u16 direct, u8 data8) +{ + switch (alu_op) + { + case 0x0: add_byte_direct_data8(direct, data8); break; + case 0x1: addc_byte_direct_data8(direct, data8); break; + case 0x2: sub_byte_direct_data8(direct, data8); break; + case 0x3: subb_byte_direct_data8(direct, data8); break; + case 0x4: cmp_byte_direct_data8(direct, data8); break; + case 0x5: and_byte_direct_data8(direct, data8); break; + case 0x6: or_byte_direct_data8(direct, data8); break; + case 0x7: xor_byte_direct_data8(direct, data8); break; + case 0x8: mov_byte_direct_data8(direct, data8); break; + default: logerror("UNK_ALUOP.b %s, #$%02x (DIRECT, DATA8)", get_directtext(direct), data8); do_nop(); break; + } +} +void xa_cpu::add_byte_direct_data8(u16 direct, u8 data8) { u8 val = read_direct8(direct); u8 result = do_add_8(val, data8); write_direct8(direct, result); cy(4); } +void xa_cpu::addc_byte_direct_data8(u16 direct, u8 data8){ u8 val = read_direct8(direct); u8 result = do_addc_8(val, data8); write_direct8(direct, result); cy(4);} +void xa_cpu::sub_byte_direct_data8(u16 direct, u8 data8) { u8 val = read_direct8(direct); u8 result = do_sub_8(val, data8); write_direct8(direct, result); cy(4); } +void xa_cpu::subb_byte_direct_data8(u16 direct, u8 data8){ u8 val = read_direct8(direct); u8 result = do_subb_8(val, data8); write_direct8(direct, result); cy(4);} +void xa_cpu::cmp_byte_direct_data8(u16 direct, u8 data8) { u8 val = read_direct8(direct); do_sub_8(val, data8); cy(4); } +void xa_cpu::and_byte_direct_data8(u16 direct, u8 data8) { u8 val = read_direct8(direct); u8 result = do_and_8(val, data8); write_direct8(direct, result); cy(4); } +void xa_cpu::or_byte_direct_data8(u16 direct, u8 data8) { u8 val = read_direct8(direct); u8 result = do_or_8(val, data8); write_direct8(direct, result); cy(4); } +void xa_cpu::xor_byte_direct_data8(u16 direct, u8 data8) { u8 val = read_direct8(direct); u8 result = do_xor_8(val, data8); write_direct8(direct, result); cy(4); } +void xa_cpu::mov_byte_direct_data8(u16 direct, u8 data8) { u8 result = data8; do_nz_flags_8(result); write_direct8(direct, result); cy(3); } + +// ----------------------------------------------- +// ALUOP.w Rd, data16 +// ADD Rd, #data16 Add 16-bit imm data to reg 4 3 1001 1001 dddd 0000 iiii iiii iiii iiii +// ADDC Rd, #data16 Add 16-bit imm data to reg w/ carry 4 3 1001 1001 dddd 0001 iiii iiii iiii iiii +// SUB Rd, #data16 Subtract 16-bit imm data to reg 4 3 1001 1001 dddd 0010 iiii iiii iiii iiii +// SUBB Rd, #data16 Subtract w/ borrow 16-bit imm data to reg 4 3 1001 1001 dddd 0011 iiii iiii iiii iiii +// CMP Rd, #data16 Compare 16-bit imm data to reg 4 3 1001 1001 dddd 0100 iiii iiii iiii iiii +// AND Rd, #data16 Logical AND 16-bit imm data to reg 4 3 1001 1001 dddd 0101 iiii iiii iiii iiii +// OR Rd, #data16 Logical OR 16-bit imm data to reg 4 3 1001 1001 dddd 0110 iiii iiii iiii iiii +// XOR Rd, #data16 Logical XOR 16-bit imm data to reg 4 3 1001 1001 dddd 0111 iiii iiii iiii iiii +// MOV Rd, #data16 Move 16-bit imm data to reg 4 3 1001 1001 dddd 1000 iiii iiii iiii iiii +void xa_cpu::aluop_byte_rd_data16(int alu_op, u8 rd, u16 data16) +{ + switch (alu_op) + { + case 0x0: add_word_rd_data16(rd, data16); break; + case 0x1: addc_word_rd_data16(rd, data16); break; + case 0x2: sub_word_rd_data16(rd, data16); break; + case 0x3: subb_word_rd_data16(rd, data16); break; + case 0x4: cmp_word_rd_data16(rd, data16); break; + case 0x5: and_word_rd_data16(rd, data16); break; + case 0x6: or_word_rd_data16(rd, data16); break; + case 0x7: xor_word_rd_data16(rd, data16); break; + case 0x8: mov_word_rd_data16(rd, data16); break; + default: logerror("UNK_ALUOP.w %s, #$%04x (RD, DATA16)", m_regnames16[rd], data16); do_nop(); break; + } +} +void xa_cpu::add_word_rd_data16(u8 rd, u16 data16) { u16 rdval = gr16(rd); u16 result = do_add_16(rdval, data16); sr16(rd, result); cy(3); } +void xa_cpu::addc_word_rd_data16(u8 rd, u16 data16){ u16 rdval = gr16(rd); u16 result = do_addc_16(rdval, data16); sr16(rd, result); cy(3); } +void xa_cpu::sub_word_rd_data16(u8 rd, u16 data16) { u16 rdval = gr16(rd); u16 result = do_sub_16(rdval, data16); sr16(rd, result); cy(3); } +void xa_cpu::subb_word_rd_data16(u8 rd, u16 data16){ u16 rdval = gr16(rd); u16 result = do_subb_16(rdval, data16); sr16(rd, result); cy(3); } +void xa_cpu::cmp_word_rd_data16(u8 rd, u16 data16) { u16 rdval = gr16(rd); do_sub_16(rdval, data16); cy(3); } +void xa_cpu::and_word_rd_data16(u8 rd, u16 data16) { u16 rdval = gr16(rd); u16 result = do_and_16(rdval, data16); sr16(rd, result); cy(3); } +void xa_cpu::or_word_rd_data16(u8 rd, u16 data16) { u16 rdval = gr16(rd); u16 result = do_or_16(rdval, data16); sr16(rd, result); cy(3); } +void xa_cpu::xor_word_rd_data16(u8 rd, u16 data16) { u16 rdval = gr16(rd); u16 result = do_xor_16(rdval, data16); sr16(rd, result); cy(3); } +void xa_cpu::mov_word_rd_data16(u8 rd, u16 data16) { u16 result = data16; do_nz_flags_16(result); sr16(rd, result); cy(3); } + +// ----------------------------------------------- +// ALUOP.w [Rd], data16 +// ADD [Rd], #data16 Add 16-bit imm data to reg-ind 4 4 1001 1010 0ddd 0000 iiii iiii 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 +// SUB [Rd], #data16 Subtract 16-bit imm data to reg-ind 4 4 1001 1010 0ddd 0010 iiii iiii 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 +// CMP [Rd], #data16 Compare 16-bit imm data to reg-ind 4 4 1001 1010 0ddd 0100 iiii iiii iiii iiii +// AND [Rd], #data16 Logical AND 16-bit imm data to reg-ind 4 4 1001 1010 0ddd 0101 iiii iiii iiii iiii +// OR [Rd], #data16 Logical OR 16-bit imm data to reg-ind 4 4 1001 1010 0ddd 0110 iiii iiii iiii iiii +// XOR [Rd], #data16 Logical XOR 16-bit imm data to reg-ind 4 4 1001 1010 0ddd 0111 iiii iiii iiii iiii +// MOV [Rd], #data16 Move 16-bit imm data to reg-ind 4 3 1001 1010 0ddd 1000 iiii iiii iiii iiii +void xa_cpu::aluop_byte_indrd_data16(int alu_op, u8 rd, u16 data16) +{ + switch (alu_op) + { + case 0x0: add_word_indrd_data16(rd, data16); break; + case 0x1: addc_word_indrd_data16(rd, data16); break; + case 0x2: sub_word_indrd_data16(rd, data16); break; + case 0x3: subb_word_indrd_data16(rd, data16); break; + case 0x4: cmp_word_indrd_data16(rd, data16); break; + case 0x5: and_word_indrd_data16(rd, data16); break; + case 0x6: or_word_indrd_data16(rd, data16); break; + case 0x7: xor_word_indrd_data16(rd, data16); break; + case 0x8: mov_word_indrd_data16(rd, data16); break; + default: logerror("UNK_ALUOP.w [%s], #$%04x", m_regnames16[rd], data16); do_nop(); break; + } +} +void xa_cpu::add_word_indrd_data16(u8 rd, u16 data16) { u16 address = get_addr(rd); u16 val = rdat16(address); u16 result = do_add_16(val, data16); wdat16(address, result); cy(4); } +void xa_cpu::addc_word_indrd_data16(u8 rd, u16 data16){ u16 address = get_addr(rd); u16 val = rdat16(address); u16 result = do_addc_16(val, data16); wdat16(address, result); cy(4); } +void xa_cpu::sub_word_indrd_data16(u8 rd, u16 data16) { u16 address = get_addr(rd); u16 val = rdat16(address); u16 result = do_sub_16(val, data16); wdat16(address, result); cy(4); } +void xa_cpu::subb_word_indrd_data16(u8 rd, u16 data16){ u16 address = get_addr(rd); u16 val = rdat16(address); u16 result = do_subb_16(val, data16); wdat16(address, result); cy(4); } +void xa_cpu::cmp_word_indrd_data16(u8 rd, u16 data16) { u16 address = get_addr(rd); u16 val = rdat16(address); do_sub_16(val, data16); cy(4); } +void xa_cpu::and_word_indrd_data16(u8 rd, u16 data16) { u16 address = get_addr(rd); u16 val = rdat16(address); u16 result = do_and_16(val, data16); wdat16(address, result); cy(4); } +void xa_cpu::or_word_indrd_data16(u8 rd, u16 data16) { u16 address = get_addr(rd); u16 val = rdat16(address); u16 result = do_or_16(val, data16); wdat16(address, result); cy(4); } +void xa_cpu::xor_word_indrd_data16(u8 rd, u16 data16) { u16 address = get_addr(rd); u16 val = rdat16(address); u16 result = do_xor_16(val, data16); wdat16(address, result); cy(4); } +void xa_cpu::mov_word_indrd_data16(u8 rd, u16 data16) { u16 address = get_addr(rd); do_nz_flags_16(data16); wdat16(address, data16); cy(3); } + +// ALUOP.w [Rd+], data16 +// ADD [Rd+], #data16 Add 16-bit imm data to reg-ind w/ autoinc 4 5 1001 1011 0ddd 0000 iiii iiii 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 +// SUB [Rd+], #data16 Subtract 16-bit imm data to reg-ind w/ autoinc 4 5 1001 1011 0ddd 0010 iiii iiii 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 +// CMP [Rd+], #data16 Compare 16-bit imm data to reg-ind w/ autoinc 4 5 1001 1011 0ddd 0100 iiii iiii 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 +// OR [Rd+], #data16 Logical OR 16-bit imm data to reg-ind w/ autoinc 4 5 1001 1011 0ddd 0110 iiii iiii 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 +// MOV [Rd+], #data16 Move 16-bit imm data to reg-ind w/ autoinc 4 4 1001 1011 0ddd 1000 iiii iiii iiii iiii +void xa_cpu::aluop_byte_indrdinc_data16(int alu_op, u8 rd, u16 data16) +{ + switch (alu_op) + { + case 0x0: add_word_indrdinc_data16(rd, data16); break; + case 0x1: addc_word_indrdinc_data16(rd, data16); break; + case 0x2: sub_word_indrdinc_data16(rd, data16); break; + case 0x3: subb_word_indrdinc_data16(rd, data16); break; + case 0x4: cmp_word_indrdinc_data16(rd, data16); break; + case 0x5: and_word_indrdinc_data16(rd, data16); break; + case 0x6: or_word_indrdinc_data16(rd, data16); break; + case 0x7: xor_word_indrdinc_data16(rd, data16); break; + case 0x8: mov_word_indrdinc_data16(rd, data16); break; + default: logerror("UNK_ALUOP.w [%s+], #$%04x", m_regnames16[rd], data16); do_nop(); break; + } +} +void xa_cpu::add_word_indrdinc_data16(u8 rd, u16 data16) { fatalerror( "ADD.w [%s+], #$%04x ([RD+], DATA16)", m_regnames16[rd], data16); } +void xa_cpu::addc_word_indrdinc_data16(u8 rd, u16 data16){ fatalerror( "ADDC.w [%s+], #$%04x ([RD+], DATA16)", m_regnames16[rd], data16); } +void xa_cpu::sub_word_indrdinc_data16(u8 rd, u16 data16) { fatalerror( "SUB.w [%s+], #$%04x ([RD+], DATA16)", m_regnames16[rd], data16); } +void xa_cpu::subb_word_indrdinc_data16(u8 rd, u16 data16){ fatalerror( "SUBB.w [%s+], #$%04x ([RD+], DATA16)", m_regnames16[rd], data16); } +void xa_cpu::cmp_word_indrdinc_data16(u8 rd, u16 data16) { fatalerror( "CMP.w [%s+], #$%04x ([RD+], DATA16)", m_regnames16[rd], data16); } +void xa_cpu::and_word_indrdinc_data16(u8 rd, u16 data16) { fatalerror( "AND.w [%s+], #$%04x ([RD+], DATA16)", m_regnames16[rd], data16); } +void xa_cpu::or_word_indrdinc_data16(u8 rd, u16 data16) { fatalerror( "OR.w [%s+], #$%04x ([RD+], DATA16)", m_regnames16[rd], data16); } +void xa_cpu::xor_word_indrdinc_data16(u8 rd, u16 data16) { fatalerror( "XOR.w [%s+], #$%04x ([RD+], DATA16)", m_regnames16[rd], data16); } +void xa_cpu::mov_word_indrdinc_data16(u8 rd, u16 data16) { fatalerror( "MOV.w [%s+], #$%04x ([RD+], DATA16)", m_regnames16[rd], data16); } + +// ALPOP.w [Rd+offs8], data16 +// 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 +// 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 +// 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 +// 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 +// 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 +// 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 +// 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 +// 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 +// 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 +void xa_cpu::aluop_byte_rdoff8_data16(int alu_op, u8 rd, u8 offset8, u16 data16) +{ + switch (alu_op) + { + case 0x0: add_word_indrdoff8_data16(rd, offset8, data16); break; + case 0x1: addc_word_indrdoff8_data16(rd, offset8, data16); break; + case 0x2: sub_word_indrdoff8_data16(rd, offset8, data16); break; + case 0x3: subb_word_indrdoff8_data16(rd, offset8, data16); break; + case 0x4: cmp_word_indrdoff8_data16(rd, offset8, data16); break; + case 0x5: and_word_indrdoff8_data16(rd, offset8, data16); break; + case 0x6: or_word_indrdoff8_data16(rd, offset8, data16); break; + case 0x7: xor_word_indrdoff8_data16(rd, offset8, data16); break; + case 0x8: mov_word_indrdoff8_data16(rd, offset8, data16); break; + default: logerror("UNK_ALUOP.w [%s+#$%02x], #$%04x", m_regnames16[rd], offset8, data16); do_nop(); break; + } +} + + +void xa_cpu::add_word_indrdoff8_data16(u8 rd, u8 offset8, u16 data16) { u16 fulloffset = util::sext(offset8, 8); u16 address = get_addr(rd) + fulloffset; u16 val = rdat16(address); u16 result = do_add_16(val, data16); wdat16(address, result); cy(6); } +void xa_cpu::addc_word_indrdoff8_data16(u8 rd, u8 offset8, u16 data16){ u16 fulloffset = util::sext(offset8, 8); u16 address = get_addr(rd) + fulloffset; u16 val = rdat16(address); u16 result = do_addc_16(val, data16); wdat16(address, result); cy(6); } +void xa_cpu::sub_word_indrdoff8_data16(u8 rd, u8 offset8, u16 data16) { u16 fulloffset = util::sext(offset8, 8); u16 address = get_addr(rd) + fulloffset; u16 val = rdat16(address); u16 result = do_sub_16(val, data16); wdat16(address, result); cy(6); } +void xa_cpu::subb_word_indrdoff8_data16(u8 rd, u8 offset8, u16 data16){ u16 fulloffset = util::sext(offset8, 8); u16 address = get_addr(rd) + fulloffset; u16 val = rdat16(address); u16 result = do_subb_16(val, data16); wdat16(address, result); cy(6); } +void xa_cpu::cmp_word_indrdoff8_data16(u8 rd, u8 offset8, u16 data16) { u16 fulloffset = util::sext(offset8, 8); u16 address = get_addr(rd) + fulloffset; u16 val = rdat16(address); do_sub_16(val, data16); cy(6); } +void xa_cpu::and_word_indrdoff8_data16(u8 rd, u8 offset8, u16 data16) { u16 fulloffset = util::sext(offset8, 8); u16 address = get_addr(rd) + fulloffset; u16 val = rdat16(address); u16 result = do_and_16(val, data16); wdat16(address, result); cy(6); } +void xa_cpu::or_word_indrdoff8_data16(u8 rd, u8 offset8, u16 data16) { u16 fulloffset = util::sext(offset8, 8); u16 address = get_addr(rd) + fulloffset; u16 val = rdat16(address); u16 result = do_or_16(val, data16); wdat16(address, result); cy(6); } +void xa_cpu::xor_word_indrdoff8_data16(u8 rd, u8 offset8, u16 data16) { u16 fulloffset = util::sext(offset8, 8); u16 address = get_addr(rd) + fulloffset; u16 val = rdat16(address); u16 result = do_xor_16(val, data16); wdat16(address, result); cy(6); } +void xa_cpu::mov_word_indrdoff8_data16(u8 rd, u8 offset8, u16 data16) { u16 fulloffset = util::sext(offset8, 8); u16 address = get_addr(rd) + fulloffset; do_nz_flags_16(data16); wdat16(address, data16); cy(5); } + +// ALUOP.w [Rd+offs16], data16 +// 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 +// 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 +// 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 +// 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 +// 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 +// 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 +// 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 +// 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 +// 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 +void xa_cpu::aluop_byte_rdoff16_data16(int alu_op, u8 rd, u16 offset16, u16 data16) +{ + switch (alu_op) + { + case 0x0: add_word_indrdoff16_data16(rd, offset16, data16); break; + case 0x1: addc_word_indrdoff16_data16(rd, offset16, data16); break; + case 0x2: sub_word_indrdoff16_data16(rd, offset16, data16); break; + case 0x3: subb_word_indrdoff16_data16(rd, offset16, data16); break; + case 0x4: cmp_word_indrdoff16_data16(rd, offset16, data16); break; + case 0x5: and_word_indrdoff16_data16(rd, offset16, data16); break; + case 0x6: or_word_indrdoff16_data16(rd, offset16, data16); break; + case 0x7: xor_word_indrdoff16_data16(rd, offset16, data16); break; + case 0x8: mov_word_indrdoff16_data16(rd, offset16, data16); break; + default: logerror("UNK_ALUOP.w [%s+#$%04x], #$%04x", m_regnames16[rd], offset16, data16); do_nop(); break; + } +} + +void xa_cpu::add_word_indrdoff16_data16(u8 rd, u16 offset16, u16 data16) { u16 fulloffset = offset16; u16 address = get_addr(rd) + fulloffset; u16 val = rdat16(address); u16 result = do_add_16(val, data16); wdat16(address, result); cy(6); } +void xa_cpu::addc_word_indrdoff16_data16(u8 rd, u16 offset16, u16 data16){ u16 fulloffset = offset16; u16 address = get_addr(rd) + fulloffset; u16 val = rdat16(address); u16 result = do_addc_16(val, data16); wdat16(address, result); cy(6); } +void xa_cpu::sub_word_indrdoff16_data16(u8 rd, u16 offset16, u16 data16) { u16 fulloffset = offset16; u16 address = get_addr(rd) + fulloffset; u16 val = rdat16(address); u16 result = do_sub_16(val, data16); wdat16(address, result); cy(6); } +void xa_cpu::subb_word_indrdoff16_data16(u8 rd, u16 offset16, u16 data16){ u16 fulloffset = offset16; u16 address = get_addr(rd) + fulloffset; u16 val = rdat16(address); u16 result = do_subb_16(val, data16); wdat16(address, result); cy(6); } +void xa_cpu::cmp_word_indrdoff16_data16(u8 rd, u16 offset16, u16 data16) { u16 fulloffset = offset16; u16 address = get_addr(rd) + fulloffset; u16 val = rdat16(address); do_sub_16(val, data16); cy(6); } +void xa_cpu::and_word_indrdoff16_data16(u8 rd, u16 offset16, u16 data16) { u16 fulloffset = offset16; u16 address = get_addr(rd) + fulloffset; u16 val = rdat16(address); u16 result = do_and_16(val, data16); wdat16(address, result); cy(6); } +void xa_cpu::or_word_indrdoff16_data16(u8 rd, u16 offset16, u16 data16) { u16 fulloffset = offset16; u16 address = get_addr(rd) + fulloffset; u16 val = rdat16(address); u16 result = do_or_16(val, data16); wdat16(address, result); cy(6); } +void xa_cpu::xor_word_indrdoff16_data16(u8 rd, u16 offset16, u16 data16) { u16 fulloffset = offset16; u16 address = get_addr(rd) + fulloffset; u16 val = rdat16(address); u16 result = do_xor_16(val, data16); wdat16(address, result); cy(6); } +void xa_cpu::mov_word_indrdoff16_data16(u8 rd, u16 offset16, u16 data16) { u16 fulloffset = offset16; u16 address = get_addr(rd) + fulloffset; do_nz_flags_16(data16); wdat16(address, data16); cy(5); } + +// ALUOP.w DIRECT, data16 +// ADD direct, #data16 Add 16-bit imm data to mem 5 4 1001 1110 0DDD 0000 DDDD DDDD iiii iiii 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 direct, #data16 Subtract 16-bit imm data to mem 5 4 1001 1110 0DDD 0010 DDDD DDDD iiii iiii 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 direct, #data16 Compare 16-bit imm data to mem 5 4 1001 1110 0DDD 0100 DDDD DDDD iiii iiii 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 direct, #data16 Logical OR 16-bit imm data to mem 5 4 1001 1110 0DDD 0110 DDDD DDDD iiii iiii 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 direct, #data16 Move 16-bit imm data to mem 5 3 1001 1110 0DDD 1000 DDDD DDDD iiii iiii iiii iiii +void xa_cpu::aluop_byte_direct_data16(int alu_op, u16 direct, u16 data16) +{ + switch (alu_op) + { + case 0x0: add_word_direct_data16(direct, data16); break; + case 0x1: addc_word_direct_data16(direct, data16); break; + case 0x2: sub_word_direct_data16(direct, data16); break; + case 0x3: subb_word_direct_data16(direct, data16); break; + case 0x4: cmp_word_direct_data16(direct, data16); break; + case 0x5: and_word_direct_data16(direct, data16); break; + case 0x6: or_word_direct_data16(direct, data16); break; + case 0x7: xor_word_direct_data16(direct, data16); break; + case 0x8: mov_word_direct_data16(direct, data16); break; + default: logerror("UNK_ALUOP.w %s, #$%04x", get_directtext(direct), data16); do_nop(); break; + } +} +void xa_cpu::add_word_direct_data16(u16 direct, u16 data16) { u16 val = read_direct16(direct); u16 result = do_add_16(val, data16); write_direct16(direct, result); cy(4); } +void xa_cpu::addc_word_direct_data16(u16 direct, u16 data16){ u16 val = read_direct16(direct); u16 result = do_addc_16(val, data16); write_direct16(direct, result); cy(4);} +void xa_cpu::sub_word_direct_data16(u16 direct, u16 data16) { u16 val = read_direct16(direct); u16 result = do_sub_16(val, data16); write_direct16(direct, result); cy(4); } +void xa_cpu::subb_word_direct_data16(u16 direct, u16 data16){ u16 val = read_direct16(direct); u16 result = do_subb_16(val, data16); write_direct16(direct, result); cy(4);} +void xa_cpu::cmp_word_direct_data16(u16 direct, u16 data16) { u16 val = read_direct16(direct); do_sub_16(val, data16); cy(4); } +void xa_cpu::and_word_direct_data16(u16 direct, u16 data16) { u16 val = read_direct16(direct); u16 result = do_and_16(val, data16); write_direct16(direct, result); cy(4); } +void xa_cpu::or_word_direct_data16(u16 direct, u16 data16) { u16 val = read_direct16(direct); u16 result = do_or_16(val, data16); write_direct16(direct, result); cy(4); } +void xa_cpu::xor_word_direct_data16(u16 direct, u16 data16) { u16 val = read_direct16(direct); u16 result = do_xor_16(val, data16); write_direct16(direct, result); cy(4); } +void xa_cpu::mov_word_direct_data16(u16 direct, u16 data16) { u16 result = data16; do_nz_flags_16(result); write_direct16(direct, result); cy(3); } + +// ------------------------------------------ +// ------------------------------------------ +// ------------------------------------------ + + +// ALUOP.w Rd, Rs +// ALUOP.b Rd, Rs +// ADD Rd, Rs Add regs direct 2 3 0000 S001 dddd ssss +// ADDC Rd, Rs Add regs direct w/ carry 2 3 0001 S001 dddd ssss +// SUB Rd, Rs Subtract regs direct 2 3 0010 S001 dddd ssss +// SUBB Rd, Rs Subtract w/ borrow regs direct 2 3 0011 S001 dddd ssss +// CMP Rd, Rs Compare dest and src regs 2 3 0100 S001 dddd ssss +// AND Rd, Rs Logical AND regs direct 2 3 0101 S001 dddd ssss +// OR Rd, Rs Logical OR regs 2 3 0110 S001 dddd ssss +// XOR Rd, Rs Logical XOR regs 2 3 0111 S001 dddd ssss +// MOV Rd, Rs Move reg to reg 2 3 1000 S001 dddd ssss +void xa_cpu::aluop_word_rd_rs(int alu_op, u8 rd, u8 rs) +{ + switch (alu_op) + { + case 0x0: add_word_rd_rs(rd, rs); break; + case 0x1: addc_word_rd_rs(rd, rs); break; + case 0x2: sub_word_rd_rs(rd, rs); break; + case 0x3: subb_word_rd_rs(rd, rs); break; + case 0x4: cmp_word_rd_rs(rd, rs); break; + case 0x5: and_word_rd_rs(rd, rs); break; + case 0x6: or_word_rd_rs(rd, rs); break; + case 0x7: xor_word_rd_rs(rd, rs); break; + case 0x8: mov_word_rd_rs(rd, rs); break; + default: fatalerror("UNK_ALUOP.w %s, %s", m_regnames16[rd], m_regnames16[rs]); // ALUOP.w Rd, Rs + } +} +void xa_cpu::aluop_byte_rd_rs(int alu_op, u8 rd, u8 rs) +{ + switch (alu_op) + { + case 0x0: add_byte_rd_rs(rd, rs); break; + case 0x1: addc_byte_rd_rs(rd, rs); break; + case 0x2: sub_byte_rd_rs(rd, rs); break; + case 0x3: subb_byte_rd_rs(rd, rs); break; + case 0x4: cmp_byte_rd_rs(rd, rs); break; + case 0x5: and_byte_rd_rs(rd, rs); break; + case 0x6: or_byte_rd_rs(rd, rs); break; + case 0x7: xor_byte_rd_rs(rd, rs); break; + case 0x8: mov_byte_rd_rs(rd, rs); break; + default: fatalerror("UNK_ALUOP.b %s, %s", m_regnames8[rd], m_regnames8[rs]); // ALUOP.b Rd, Rs + } +} + +void xa_cpu::add_word_rd_rs(u8 rd, u8 rs) { u16 rdval = gr16(rd); u16 rsval = gr16(rs); u16 result = do_add_16(rdval, rsval); sr16(rd, result); cy(3);} +void xa_cpu::addc_word_rd_rs(u8 rd, u8 rs){ u16 rdval = gr16(rd); u16 rsval = gr16(rs); u16 result = do_addc_16(rdval, rsval); sr16(rd, result); cy(3);} +void xa_cpu::sub_word_rd_rs(u8 rd, u8 rs) { u16 rdval = gr16(rd); u16 rsval = gr16(rs); u16 result = do_sub_16(rdval, rsval); sr16(rd, result); cy(3);} +void xa_cpu::subb_word_rd_rs(u8 rd, u8 rs){ u16 rdval = gr16(rd); u16 rsval = gr16(rs); u16 result = do_subb_16(rdval, rsval); sr16(rd, result); cy(3);} +void xa_cpu::cmp_word_rd_rs(u8 rd, u8 rs) { u16 rdval = gr16(rd); u16 rsval = gr16(rs); do_sub_16(rdval, rsval); cy(3); } +void xa_cpu::and_word_rd_rs(u8 rd, u8 rs) { u16 rdval = gr16(rd); u16 rsval = gr16(rs); u16 result = do_and_16(rdval, rsval); sr16(rd, result); cy(3); } +void xa_cpu::or_word_rd_rs(u8 rd, u8 rs) { u16 rdval = gr16(rd); u16 rsval = gr16(rs); u16 result = do_or_16(rdval, rsval); sr16(rd, result); cy(3); } +void xa_cpu::xor_word_rd_rs(u8 rd, u8 rs) { u16 rdval = gr16(rd); u16 rsval = gr16(rs); u16 result = do_xor_16(rdval, rsval); sr16(rd, result); cy(3);} +void xa_cpu::mov_word_rd_rs(u8 rd, u8 rs) { u16 val = gr16(rs); do_nz_flags_16(val); sr16(rd, val); cy(3); } + +void xa_cpu::add_byte_rd_rs(u8 rd, u8 rs) { u8 rdval = gr8(rd); u8 rsval = gr8(rs); u8 result = do_add_8(rdval, rsval); sr8(rd, result); cy(3); } +void xa_cpu::addc_byte_rd_rs(u8 rd, u8 rs){ u8 rdval = gr8(rd); u8 rsval = gr8(rs); u8 result = do_addc_8(rdval, rsval); sr8(rd, result); cy(3); } +void xa_cpu::sub_byte_rd_rs(u8 rd, u8 rs) { u8 rdval = gr8(rd); u8 rsval = gr8(rs); u8 result = do_sub_8(rdval, rsval); sr8(rd, result); cy(3); } +void xa_cpu::subb_byte_rd_rs(u8 rd, u8 rs){ u8 rdval = gr8(rd); u8 rsval = gr8(rs); u8 result = do_subb_8(rdval, rsval); sr8(rd, result); cy(3); } +void xa_cpu::cmp_byte_rd_rs(u8 rd, u8 rs) { u8 rdval = gr8(rd); u8 rsval = gr8(rs); do_sub_8(rdval, rsval); cy(3);} +void xa_cpu::and_byte_rd_rs(u8 rd, u8 rs) { u8 rdval = gr8(rd); u8 rsval = gr8(rs); u8 result = do_and_8(rdval, rsval); sr8(rd, result); cy(3); } +void xa_cpu::or_byte_rd_rs(u8 rd, u8 rs) { u8 rdval = gr8(rd); u8 rsval = gr8(rs); u8 result = do_or_8(rdval, rsval); sr8(rd, result); cy(3); } +void xa_cpu::xor_byte_rd_rs(u8 rd, u8 rs) { u8 rdval = gr8(rd); u8 rsval = gr8(rs); u8 result = do_xor_8(rdval, rsval); sr8(rd, result); cy(3); } +void xa_cpu::mov_byte_rd_rs(u8 rd, u8 rs) { u8 val = gr8(rs); do_nz_flags_8(val); sr8(rd, val); cy(3);} + +// ALUOP.w Rd, [Rs] +// ALUOP.b Rd, [Rs] +// ADD Rd, [Rs] Add reg-ind to reg 2 4 0000 S010 dddd 0sss +// ADDC Rd, [Rs] Add reg-ind to reg w/ carry 2 4 0001 S010 dddd 0sss +// SUB Rd, [Rs] Subtract reg-ind to reg 2 4 0010 S010 dddd 0sss +// SUBB Rd, [Rs] Subtract w/ borrow reg-ind to reg 2 4 0011 S010 dddd 0sss +// CMP Rd, [Rs] Compare reg-ind w/ reg 2 4 0100 S010 dddd 0sss +// AND Rd, [Rs] Logical AND reg-ind to reg 2 4 0101 S010 dddd 0sss +// OR Rd, [Rs] Logical OR reg-ind to reg 2 4 0110 S010 dddd 0sss +// XOR Rd, [Rs] Logical XOR reg-ind to reg 2 4 0111 S010 dddd 0sss +// MOV Rd, [Rs] Move reg-ind to reg 2 3 1000 S010 dddd 0sss +void xa_cpu::aluop_word_rd_indrs(int alu_op, u8 rd, u8 rs) +{ + switch (alu_op) + { + case 0x0: add_word_rd_indrs(rd, rs); break; + case 0x1: addc_word_rd_indrs(rd, rs); break; + case 0x2: sub_word_rd_indrs(rd, rs); break; + case 0x3: subb_word_rd_indrs(rd, rs); break; + case 0x4: cmp_word_rd_indrs(rd, rs); break; + case 0x5: and_word_rd_indrs(rd, rs); break; + case 0x6: or_word_rd_indrs(rd, rs); break; + case 0x7: xor_word_rd_indrs(rd, rs); break; + case 0x8: mov_word_rd_indrs(rd, rs); break; + default: fatalerror("UNK_ALUOP.w %s, [%s]", m_regnames16[rd], m_regnames16[rs]); // ALUOP.w Rd, [Rs] + } +} +void xa_cpu::aluop_byte_rd_indrs(int alu_op, u8 rd, u8 rs) +{ + switch (alu_op) + { + case 0x0: add_byte_rd_indrs(rd, rs); break; + case 0x1: addc_byte_rd_indrs(rd, rs); break; + case 0x2: sub_byte_rd_indrs(rd, rs); break; + case 0x3: subb_byte_rd_indrs(rd, rs); break; + case 0x4: cmp_byte_rd_indrs(rd, rs); break; + case 0x5: and_byte_rd_indrs(rd, rs); break; + case 0x6: or_byte_rd_indrs(rd, rs); break; + case 0x7: xor_byte_rd_indrs(rd, rs); break; + case 0x8: mov_byte_rd_indrs(rd, rs); break; + default: fatalerror("UNK_ALUOP.b %s, [%s]", m_regnames8[rd], m_regnames16[rs]); // ALUOP.b Rd, [Rs] + } +} +void xa_cpu::add_word_rd_indrs(u8 rd, u8 rs) { fatalerror("ADD.w %s, [%s]", m_regnames16[rd], m_regnames16[rs]);} +void xa_cpu::addc_word_rd_indrs(u8 rd, u8 rs){ fatalerror("ADDC.w %s, [%s]", m_regnames16[rd], m_regnames16[rs]);} +void xa_cpu::sub_word_rd_indrs(u8 rd, u8 rs) { fatalerror("SUB.w %s, [%s]", m_regnames16[rd], m_regnames16[rs]);} +void xa_cpu::subb_word_rd_indrs(u8 rd, u8 rs){ fatalerror("SUBB.w %s, [%s]", m_regnames16[rd], m_regnames16[rs]);} +void xa_cpu::cmp_word_rd_indrs(u8 rd, u8 rs) { fatalerror("CMP.w %s, [%s]", m_regnames16[rd], m_regnames16[rs]);} +void xa_cpu::and_word_rd_indrs(u8 rd, u8 rs) { fatalerror("AND.w %s, [%s]", m_regnames16[rd], m_regnames16[rs]);} +void xa_cpu::or_word_rd_indrs(u8 rd, u8 rs) { fatalerror("OR.w %s, [%s]", m_regnames16[rd], m_regnames16[rs]);} +void xa_cpu::xor_word_rd_indrs(u8 rd, u8 rs) { fatalerror("XOR.w %s, [%s]", m_regnames16[rd], m_regnames16[rs]);} +void xa_cpu::mov_word_rd_indrs(u8 rd, u8 rs) { u16 address = get_addr(rs); u16 val = rdat16(address); do_nz_flags_16(val); sr16(rd, val); cy(3); } + +void xa_cpu::add_byte_rd_indrs(u8 rd, u8 rs) { fatalerror("ADD.b %s, [%s]", m_regnames8[rd], m_regnames16[rs]);} +void xa_cpu::addc_byte_rd_indrs(u8 rd, u8 rs){ fatalerror("ADDC.b %s, [%s]", m_regnames8[rd], m_regnames16[rs]);} +void xa_cpu::sub_byte_rd_indrs(u8 rd, u8 rs) { fatalerror("SUB.b %s, [%s]", m_regnames8[rd], m_regnames16[rs]);} +void xa_cpu::subb_byte_rd_indrs(u8 rd, u8 rs){ fatalerror("SUBB.b %s, [%s]", m_regnames8[rd], m_regnames16[rs]);} +void xa_cpu::cmp_byte_rd_indrs(u8 rd, u8 rs) { fatalerror("CMP.b %s, [%s]", m_regnames8[rd], m_regnames16[rs]);} +void xa_cpu::and_byte_rd_indrs(u8 rd, u8 rs) { fatalerror("AND.b %s, [%s]", m_regnames8[rd], m_regnames16[rs]);} +void xa_cpu::or_byte_rd_indrs(u8 rd, u8 rs) { fatalerror("OR.b %s, [%s]", m_regnames8[rd], m_regnames16[rs]);} +void xa_cpu::xor_byte_rd_indrs(u8 rd, u8 rs) { fatalerror("XOR.b %s, [%s]", m_regnames8[rd], m_regnames16[rs]);} +void xa_cpu::mov_byte_rd_indrs(u8 rd, u8 rs) { u16 address = get_addr(rs); u8 val = rdat8(address); do_nz_flags_8(val); sr8(rd, val); cy(3); } + + +// ALUOP.w [Rd], Rs +// ALUOP.b [Rd], Rs +// ADD [Rd], Rs Add reg to reg-ind 2 4 0000 S010 ssss 1ddd +// ADDC [Rd], Rs Add reg to reg-ind w/ carry 2 4 0001 S010 ssss 1ddd +// SUB [Rd], Rs Subtract reg to reg-ind 2 4 0010 S010 ssss 1ddd +// SUBB [Rd], Rs Subtract w/ borrow reg to reg-ind 2 4 0011 S010 ssss 1ddd +// CMP [Rd], Rs Compare reg w/ reg-ind 2 4 0100 S010 ssss 1ddd +// AND [Rd], Rs Logical AND reg to reg-ind 2 4 0101 S010 ssss 1ddd +// OR [Rd], Rs Logical OR reg to reg-ind 2 4 0110 S010 ssss 1ddd +// XOR [Rd], Rs Logical XOR reg to reg-ind 2 4 0111 S010 ssss 1ddd +// MOV [Rd], Rs Move reg to reg-ind 2 3 1000 S010 ssss 1ddd +void xa_cpu::aluop_word_indrd_rs(int alu_op, u8 rd, u8 rs) +{ + switch (alu_op) + { + case 0x0: add_word_indrd_rs(rd, rs); break; + case 0x1: addc_word_indrd_rs(rd, rs); break; + case 0x2: sub_word_indrd_rs(rd, rs); break; + case 0x3: subb_word_indrd_rs(rd, rs); break; + case 0x4: cmp_word_indrd_rs(rd, rs); break; + case 0x5: and_word_indrd_rs(rd, rs); break; + case 0x6: or_word_indrd_rs(rd, rs); break; + case 0x7: xor_word_indrd_rs(rd, rs); break; + case 0x8: mov_word_indrd_rs(rd, rs); break; + default: logerror("UNK_ALUOP.w [%s], %s", m_regnames16[rd], m_regnames16[rs]); do_nop(); break; + } +} + +void xa_cpu::aluop_byte_indrd_rs(int alu_op, u8 rd, u8 rs) +{ + switch (alu_op) + { + case 0x0: add_byte_indrd_rs(rd, rs); break; + case 0x1: addc_byte_indrd_rs(rd, rs); break; + case 0x2: sub_byte_indrd_rs(rd, rs); break; + case 0x3: subb_byte_indrd_rs(rd, rs); break; + case 0x4: cmp_byte_indrd_rs(rd, rs); break; + case 0x5: and_byte_indrd_rs(rd, rs); break; + case 0x6: or_byte_indrd_rs(rd, rs); break; + case 0x7: xor_byte_indrd_rs(rd, rs); break; + case 0x8: mov_byte_indrd_rs(rd, rs); break; + default: logerror("UNK_ALUOP.b [%s], %s", m_regnames16[rd], m_regnames8[rs]); do_nop(); break; + } +} + +void xa_cpu::add_word_indrd_rs(u8 rd, u8 rs) { fatalerror("ADD.w [%s], %s", m_regnames16[rd], m_regnames16[rs]);} +void xa_cpu::addc_word_indrd_rs(u8 rd, u8 rs){ fatalerror("ADDC.w [%s], %s", m_regnames16[rd], m_regnames16[rs]);} +void xa_cpu::sub_word_indrd_rs(u8 rd, u8 rs) { fatalerror("SUB.w [%s], %s", m_regnames16[rd], m_regnames16[rs]);} +void xa_cpu::subb_word_indrd_rs(u8 rd, u8 rs){ fatalerror("SUBB.w [%s], %s", m_regnames16[rd], m_regnames16[rs]);} +void xa_cpu::cmp_word_indrd_rs(u8 rd, u8 rs) { fatalerror("CMP.w [%s], %s", m_regnames16[rd], m_regnames16[rs]);} +void xa_cpu::and_word_indrd_rs(u8 rd, u8 rs) { fatalerror("AND.w [%s], %s", m_regnames16[rd], m_regnames16[rs]);} +void xa_cpu::or_word_indrd_rs(u8 rd, u8 rs) { fatalerror("OR.w [%s], %s", m_regnames16[rd], m_regnames16[rs]);} +void xa_cpu::xor_word_indrd_rs(u8 rd, u8 rs) { fatalerror("XOR.w [%s], %s", m_regnames16[rd], m_regnames16[rs]);} +void xa_cpu::mov_word_indrd_rs(u8 rd, u8 rs) { u16 val = gr16(rs); do_nz_flags_16(val); u16 addr = get_addr(rd); wdat16(addr, val); cy(3); } + +void xa_cpu::add_byte_indrd_rs(u8 rd, u8 rs) { fatalerror("ADD.b [%s], %s", m_regnames16[rd], m_regnames8[rs]);} +void xa_cpu::addc_byte_indrd_rs(u8 rd, u8 rs){ fatalerror("ADDC.b [%s], %s", m_regnames16[rd], m_regnames8[rs]);} +void xa_cpu::sub_byte_indrd_rs(u8 rd, u8 rs) { fatalerror("SUB.b [%s], %s", m_regnames16[rd], m_regnames8[rs]);} +void xa_cpu::subb_byte_indrd_rs(u8 rd, u8 rs){ fatalerror("SUBB.b [%s], %s", m_regnames16[rd], m_regnames8[rs]);} +void xa_cpu::cmp_byte_indrd_rs(u8 rd, u8 rs) { fatalerror("CMP.b [%s], %s", m_regnames16[rd], m_regnames8[rs]);} +void xa_cpu::and_byte_indrd_rs(u8 rd, u8 rs) { fatalerror("AND.b [%s], %s", m_regnames16[rd], m_regnames8[rs]);} +void xa_cpu::or_byte_indrd_rs(u8 rd, u8 rs) { fatalerror("OR.b [%s], %s", m_regnames16[rd], m_regnames8[rs]);} +void xa_cpu::xor_byte_indrd_rs(u8 rd, u8 rs) { fatalerror("XOR.b [%s], %s", m_regnames16[rd], m_regnames8[rs]);} +void xa_cpu::mov_byte_indrd_rs(u8 rd, u8 rs) { u8 val = gr8(rs); do_nz_flags_8(val); u16 addr = get_addr(rd); wdat8(addr, val); cy(3); } + +// ALUOP.w Rd, [Rs+] +// ALUOP.b Rd, [Rs+] +// ADD Rd, [Rs+] Add reg-ind w/ autoinc to reg 2 5 0000 S011 dddd 0sss +// ADDC Rd, [Rs+] Add reg-ind w/ autoinc to reg w/ carry 2 5 0001 S011 dddd 0sss +// SUB Rd, [Rs+] Subtract reg-ind w/ autoinc to reg 2 5 0010 S011 dddd 0sss +// SUBB Rd, [Rs+] Subtract w/ borrow reg-ind w/ autoinc to reg 2 5 0011 S011 dddd 0sss +// CMP Rd, [Rs+] Compare autoinc reg-ind w/ reg 2 5 0100 S011 dddd 0sss +// AND Rd, [Rs+] Logical AND reg-ind w/ autoinc to reg 2 5 0101 S011 dddd 0sss +// OR Rd, [Rs+] Logical OR reg-ind w/ autoinc to reg 2 5 0110 S011 dddd 0sss +// XOR Rd, [Rs+] Logical XOR reg-ind w/ autoinc to reg 2 5 0111 S011 dddd 0sss +// MOV Rd, [Rs+] Move reg-ind w/ autoinc to reg 2 4 1000 S011 dddd 0sss +void xa_cpu::aluop_word_rd_indrsinc(int alu_op, u8 rd, u8 rs) +{ + switch (alu_op) + { + case 0x0: add_word_rd_indrsinc(rd, rs); break; + case 0x1: addc_word_rd_indrsinc(rd, rs); break; + case 0x2: sub_word_rd_indrsinc(rd, rs); break; + case 0x3: subb_word_rd_indrsinc(rd, rs); break; + case 0x4: cmp_word_rd_indrsinc(rd, rs); break; + case 0x5: and_word_rd_indrsinc(rd, rs); break; + case 0x6: or_word_rd_indrsinc(rd, rs); break; + case 0x7: xor_word_rd_indrsinc(rd, rs); break; + case 0x8: mov_word_rd_indrsinc(rd, rs); break; + default: logerror("UNK_ALUOP.w %s, [%s+]", m_regnames16[rd], m_regnames16[rs]); do_nop(); break; + } +} +void xa_cpu::aluop_byte_rd_indrsinc(int alu_op, u8 rd, u8 rs) +{ + switch (alu_op) + { + case 0x0: add_byte_rd_indrsinc(rd, rs); break; + case 0x1: addc_byte_rd_indrsinc(rd, rs); break; + case 0x2: sub_byte_rd_indrsinc(rd, rs); break; + case 0x3: subb_byte_rd_indrsinc(rd, rs); break; + case 0x4: cmp_byte_rd_indrsinc(rd, rs); break; + case 0x5: and_byte_rd_indrsinc(rd, rs); break; + case 0x6: or_byte_rd_indrsinc(rd, rs); break; + case 0x7: xor_byte_rd_indrsinc(rd, rs); break; + case 0x8: mov_byte_rd_indrsinc(rd, rs); break; + default: logerror("UNK_ALUOP.b %s, [%s+]", m_regnames8[rd], m_regnames16[rs]); do_nop(); break; + } +} +void xa_cpu::add_word_rd_indrsinc(u8 rd, u8 rs) { fatalerror("ADD.w %s, [%s+]", m_regnames16[rd], m_regnames16[rs]);} +void xa_cpu::addc_word_rd_indrsinc(u8 rd, u8 rs){ fatalerror("ADDC.w %s, [%s+]", m_regnames16[rd], m_regnames16[rs]);} +void xa_cpu::sub_word_rd_indrsinc(u8 rd, u8 rs) { fatalerror("SUB.w %s, [%s+]", m_regnames16[rd], m_regnames16[rs]);} +void xa_cpu::subb_word_rd_indrsinc(u8 rd, u8 rs){ fatalerror("SUBB.w %s, [%s+]", m_regnames16[rd], m_regnames16[rs]);} +void xa_cpu::cmp_word_rd_indrsinc(u8 rd, u8 rs) { fatalerror("CMP.w %s, [%s+]", m_regnames16[rd], m_regnames16[rs]);} +void xa_cpu::and_word_rd_indrsinc(u8 rd, u8 rs) { fatalerror("AND.w %s, [%s+]", m_regnames16[rd], m_regnames16[rs]);} +void xa_cpu::or_word_rd_indrsinc(u8 rd, u8 rs) { fatalerror("OR.w %s, [%s+]", m_regnames16[rd], m_regnames16[rs]);} +void xa_cpu::xor_word_rd_indrsinc(u8 rd, u8 rs) { fatalerror("XOR.w %s, [%s+]", m_regnames16[rd], m_regnames16[rs]);} +void xa_cpu::mov_word_rd_indrsinc(u8 rd, u8 rs) { fatalerror("MOV.w %s, [%s+]", m_regnames16[rd], m_regnames16[rs]);} + +void xa_cpu::add_byte_rd_indrsinc(u8 rd, u8 rs) { fatalerror("ADD.b %s, [%s+]", m_regnames8[rd], m_regnames16[rs]);} +void xa_cpu::addc_byte_rd_indrsinc(u8 rd, u8 rs){ fatalerror("ADDC.b %s, [%s+]", m_regnames8[rd], m_regnames16[rs]);} +void xa_cpu::sub_byte_rd_indrsinc(u8 rd, u8 rs) { fatalerror("SUB.b %s, [%s+]", m_regnames8[rd], m_regnames16[rs]);} +void xa_cpu::subb_byte_rd_indrsinc(u8 rd, u8 rs){ fatalerror("SUBB.b %s, [%s+]", m_regnames8[rd], m_regnames16[rs]);} +void xa_cpu::cmp_byte_rd_indrsinc(u8 rd, u8 rs) { fatalerror("CMP.b %s, [%s+]", m_regnames8[rd], m_regnames16[rs]);} +void xa_cpu::and_byte_rd_indrsinc(u8 rd, u8 rs) { fatalerror("AND.b %s, [%s+]", m_regnames8[rd], m_regnames16[rs]);} +void xa_cpu::or_byte_rd_indrsinc(u8 rd, u8 rs) { fatalerror("OR.b %s, [%s+]", m_regnames8[rd], m_regnames16[rs]);} +void xa_cpu::xor_byte_rd_indrsinc(u8 rd, u8 rs) { fatalerror("XOR.b %s, [%s+]", m_regnames8[rd], m_regnames16[rs]);} +void xa_cpu::mov_byte_rd_indrsinc(u8 rd, u8 rs) { fatalerror("MOV.b %s, [%s+]", m_regnames8[rd], m_regnames16[rs]);} + +// ALUOP.w [Rd+], Rs +// ALUOP.b [Rd+], Rs +// ADD [Rd+], Rs Add reg-ind w/ autoinc to reg 2 5 0000 S011 ssss 1ddd +// ADDC [Rd+], Rs Add reg-ind w/ autoinc to reg w/ carry 2 5 0001 S011 ssss 1ddd +// SUB [Rd+], Rs Subtract reg-ind w/ autoinc to reg 2 5 0010 S011 ssss 1ddd +// SUBB [Rd+], Rs Subtract w/ borrow reg-ind w/ autoinc to reg 2 5 0011 S011 ssss 1ddd +// CMP [Rd+], Rs Compare reg w/ autoinc reg-ind 2 5 0100 S011 ssss 1ddd +// AND [Rd+], Rs Logical AND reg-ind w/ autoinc to reg 2 5 0101 S011 ssss 1ddd +// OR [Rd+], Rs Logical OR reg-ind w/ autoinc to reg 2 5 0110 S011 ssss 1ddd +// XOR [Rd+], Rs Logical XOR reg-ind w/ autoinc to reg 2 5 0111 S011 ssss 1ddd +// MOV [Rd+], Rs Move reg-ind w/ autoinc to reg 2 4 1000 S011 ssss 1ddd +void xa_cpu::aluop_word_indrdinc_rs(int alu_op, u8 rd, u8 rs) +{ + switch (alu_op) + { + case 0x0: add_word_indrdinc_rs(rd, rs); break; + case 0x1: addc_word_indrdinc_rs(rd, rs); break; + case 0x2: sub_word_indrdinc_rs(rd, rs); break; + case 0x3: subb_word_indrdinc_rs(rd, rs); break; + case 0x4: cmp_word_indrdinc_rs(rd, rs); break; + case 0x5: and_word_indrdinc_rs(rd, rs); break; + case 0x6: or_word_indrdinc_rs(rd, rs); break; + case 0x7: xor_word_indrdinc_rs(rd, rs); break; + case 0x8: mov_word_indrdinc_rs(rd, rs); break; + default: logerror("UNK_ALUOP.w [%s+], %s", m_regnames16[rd], m_regnames16[rs]); do_nop(); break; + } +} + +void xa_cpu::aluop_byte_indrdinc_rs(int alu_op, u8 rd, u8 rs) +{ + switch (alu_op) + { + case 0x0: add_byte_indrdinc_rs(rd, rs); break; + case 0x1: addc_byte_indrdinc_rs(rd, rs); break; + case 0x2: sub_byte_indrdinc_rs(rd, rs); break; + case 0x3: subb_byte_indrdinc_rs(rd, rs); break; + case 0x4: cmp_byte_indrdinc_rs(rd, rs); break; + case 0x5: and_byte_indrdinc_rs(rd, rs); break; + case 0x6: or_byte_indrdinc_rs(rd, rs); break; + case 0x7: xor_byte_indrdinc_rs(rd, rs); break; + case 0x8: mov_byte_indrdinc_rs(rd, rs); break; + default: logerror("UNK_ALUOP.b [%s+], %s", m_regnames16[rd], m_regnames8[rs]); do_nop(); break; + } +} + +void xa_cpu::add_word_indrdinc_rs(u8 rd, u8 rs) { fatalerror("ADD.w [%s+], %s", m_regnames16[rd], m_regnames16[rs]);} +void xa_cpu::addc_word_indrdinc_rs(u8 rd, u8 rs){ fatalerror("ADDC.w [%s+], %s", m_regnames16[rd], m_regnames16[rs]);} +void xa_cpu::sub_word_indrdinc_rs(u8 rd, u8 rs) { fatalerror("SUB.w [%s+], %s", m_regnames16[rd], m_regnames16[rs]);} +void xa_cpu::subb_word_indrdinc_rs(u8 rd, u8 rs){ fatalerror("SUBB.w [%s+], %s", m_regnames16[rd], m_regnames16[rs]);} +void xa_cpu::cmp_word_indrdinc_rs(u8 rd, u8 rs) { fatalerror("CMP.w [%s+], %s", m_regnames16[rd], m_regnames16[rs]);} +void xa_cpu::and_word_indrdinc_rs(u8 rd, u8 rs) { fatalerror("AND.w [%s+], %s", m_regnames16[rd], m_regnames16[rs]);} +void xa_cpu::or_word_indrdinc_rs(u8 rd, u8 rs) { fatalerror("OR.w [%s+], %s", m_regnames16[rd], m_regnames16[rs]);} +void xa_cpu::xor_word_indrdinc_rs(u8 rd, u8 rs) { fatalerror("XOR.w [%s+], %s", m_regnames16[rd], m_regnames16[rs]);} +void xa_cpu::mov_word_indrdinc_rs(u8 rd, u8 rs) { fatalerror("MOV.w [%s+], %s", m_regnames16[rd], m_regnames16[rs]);} + +void xa_cpu::add_byte_indrdinc_rs(u8 rd, u8 rs) { fatalerror("ADD.b [%s+], %s", m_regnames16[rd], m_regnames8[rs]);} +void xa_cpu::addc_byte_indrdinc_rs(u8 rd, u8 rs){ fatalerror("ADDC.b [%s+], %s", m_regnames16[rd], m_regnames8[rs]);} +void xa_cpu::sub_byte_indrdinc_rs(u8 rd, u8 rs) { fatalerror("SUB.b [%s+], %s", m_regnames16[rd], m_regnames8[rs]);} +void xa_cpu::subb_byte_indrdinc_rs(u8 rd, u8 rs){ fatalerror("SUBB.b [%s+], %s", m_regnames16[rd], m_regnames8[rs]);} +void xa_cpu::cmp_byte_indrdinc_rs(u8 rd, u8 rs) { fatalerror("CMP.b [%s+], %s", m_regnames16[rd], m_regnames8[rs]);} +void xa_cpu::and_byte_indrdinc_rs(u8 rd, u8 rs) { fatalerror("AND.b [%s+], %s", m_regnames16[rd], m_regnames8[rs]);} +void xa_cpu::or_byte_indrdinc_rs(u8 rd, u8 rs) { fatalerror("OR.b [%s+], %s", m_regnames16[rd], m_regnames8[rs]);} +void xa_cpu::xor_byte_indrdinc_rs(u8 rd, u8 rs) { fatalerror("XOR.b [%s+], %s", m_regnames16[rd], m_regnames8[rs]);} +void xa_cpu::mov_byte_indrdinc_rs(u8 rd, u8 rs) { u16 address = get_addr(rd); u8 result = gr8(rs); wdat8(address, result); address++; do_nz_flags_8(result); set_addr(rd, address); cy(4); } + + +// ALUOP.w Rd, [Rs+off8] +// ALUOP.b Rd, [Rs+off8] +// ADD Rd, [Rs+offset8] Add reg-ind w/ 8-bit offs to reg 3 6 0000 S100 dddd 0sss oooo oooo +// ADDC Rd, [Rs+offset8] Add reg-ind w/ 8-bit offs to reg w/ carry 3 6 0001 S100 dddd 0sss oooo oooo +// SUB Rd, [Rs+offset8] Subtract reg-ind w/ 8-bit offs to reg 3 6 0010 S100 dddd 0sss oooo oooo +// SUBB Rd, [Rs+offset8] Subtract w/ borrow reg-ind w/ 8-bit offs to reg 3 6 0011 S100 dddd 0sss oooo oooo +// CMP Rd, [Rs+offset8] Compare reg-ind w/ 8-bit offs w/ reg 3 6 0100 S100 dddd 0sss oooo oooo +// AND Rd, [Rs+offset8] Logical AND reg-ind w/ 8-bit offs to reg 3 6 0101 S100 dddd 0sss oooo oooo +// OR Rd, [Rs+offset8] Logical OR reg-ind w/ 8-bit offs to reg 3 6 0110 S100 dddd 0sss oooo oooo +// XOR Rd, [Rs+offset8] Logical XOR reg-ind w/ 8-bit offs to reg 3 6 0111 S100 dddd 0sss oooo oooo +// MOV Rd, [Rs+offset8] Move reg-ind w/ 8-bit offs to reg 3 5 1000 S100 dddd 0sss oooo oooo +void xa_cpu::aluop_word_rd_rsoff8(int alu_op, u8 rd, u8 rs, u8 offset8) +{ + switch (alu_op) + { + case 0x0: add_word_rd_rsoff8(rd, rs, offset8); break; + case 0x1: addc_word_rd_rsoff8(rd, rs, offset8); break; + case 0x2: sub_word_rd_rsoff8(rd, rs, offset8); break; + case 0x3: subb_word_rd_rsoff8(rd, rs, offset8); break; + case 0x4: cmp_word_rd_rsoff8(rd, rs, offset8); break; + case 0x5: and_word_rd_rsoff8(rd, rs, offset8); break; + case 0x6: or_word_rd_rsoff8(rd, rs, offset8); break; + case 0x7: xor_word_rd_rsoff8(rd, rs, offset8); break; + case 0x8: mov_word_rd_rsoff8(rd, rs, offset8); break; + default: logerror("UNK_ALUOP.w %s, [%s+#$%02x]", m_regnames16[rd], m_regnames16[rs], offset8); do_nop(); break; + } +} +void xa_cpu::aluop_byte_rd_rsoff8(int alu_op, u8 rd, u8 rs, u8 offset8) +{ + switch (alu_op) + { + case 0x0: add_byte_rd_rsoff8(rd, rs, offset8); break; + case 0x1: addc_byte_rd_rsoff8(rd, rs, offset8); break; + case 0x2: sub_byte_rd_rsoff8(rd, rs, offset8); break; + case 0x3: subb_byte_rd_rsoff8(rd, rs, offset8); break; + case 0x4: cmp_byte_rd_rsoff8(rd, rs, offset8); break; + case 0x5: and_byte_rd_rsoff8(rd, rs, offset8); break; + case 0x6: or_byte_rd_rsoff8(rd, rs, offset8); break; + case 0x7: xor_byte_rd_rsoff8(rd, rs, offset8); break; + case 0x8: mov_byte_rd_rsoff8(rd, rs, offset8); break; + default: logerror("UNK_ALUOP.b %s, [%s+#$%02x]", m_regnames8[rd], m_regnames16[rs], offset8); do_nop(); break; + } +} + +void xa_cpu::add_word_rd_rsoff8(u8 rd, u8 rs, u8 offset8) { fatalerror("ADD.w %s, [%s+#$%02x]", m_regnames16[rd], m_regnames16[rs], offset8);} +void xa_cpu::addc_word_rd_rsoff8(u8 rd, u8 rs, u8 offset8){ fatalerror("ADDC.w %s, [%s+#$%02x]", m_regnames16[rd], m_regnames16[rs], offset8);} +void xa_cpu::sub_word_rd_rsoff8(u8 rd, u8 rs, u8 offset8) { fatalerror("SUB.w %s, [%s+#$%02x]", m_regnames16[rd], m_regnames16[rs], offset8);} +void xa_cpu::subb_word_rd_rsoff8(u8 rd, u8 rs, u8 offset8){ fatalerror("SUBB.w %s, [%s+#$%02x]", m_regnames16[rd], m_regnames16[rs], offset8);} +void xa_cpu::cmp_word_rd_rsoff8(u8 rd, u8 rs, u8 offset8) { fatalerror("CMP.w %s, [%s+#$%02x]", m_regnames16[rd], m_regnames16[rs], offset8);} +void xa_cpu::and_word_rd_rsoff8(u8 rd, u8 rs, u8 offset8) { fatalerror("AND.w %s, [%s+#$%02x]", m_regnames16[rd], m_regnames16[rs], offset8);} +void xa_cpu::or_word_rd_rsoff8(u8 rd, u8 rs, u8 offset8) { fatalerror("OR.w %s, [%s+#$%02x]", m_regnames16[rd], m_regnames16[rs], offset8);} +void xa_cpu::xor_word_rd_rsoff8(u8 rd, u8 rs, u8 offset8) { fatalerror("XOR.w %s, [%s+#$%02x]", m_regnames16[rd], m_regnames16[rs], offset8);} +void xa_cpu::mov_word_rd_rsoff8(u8 rd, u8 rs, u8 offset8) { u16 fulloffset = util::sext(offset8, 8); u16 address = get_addr(rs) + fulloffset; u16 val = rdat16(address); do_nz_flags_16(val); sr16(rd, val); cy(5); } + +void xa_cpu::add_byte_rd_rsoff8(u8 rd, u8 rs, u8 offset8) { fatalerror("ADD.b %s, [%s+#$%02x]", m_regnames8[rd], m_regnames16[rs], offset8);} +void xa_cpu::addc_byte_rd_rsoff8(u8 rd, u8 rs, u8 offset8){ fatalerror("ADDC.b %s, [%s+#$%02x]", m_regnames8[rd], m_regnames16[rs], offset8);} +void xa_cpu::sub_byte_rd_rsoff8(u8 rd, u8 rs, u8 offset8) { fatalerror("SUB.b %s, [%s+#$%02x]", m_regnames8[rd], m_regnames16[rs], offset8);} +void xa_cpu::subb_byte_rd_rsoff8(u8 rd, u8 rs, u8 offset8){ fatalerror("SUBB.b %s, [%s+#$%02x]", m_regnames8[rd], m_regnames16[rs], offset8);} +void xa_cpu::cmp_byte_rd_rsoff8(u8 rd, u8 rs, u8 offset8) { fatalerror("CMP.b %s, [%s+#$%02x]", m_regnames8[rd], m_regnames16[rs], offset8);} +void xa_cpu::and_byte_rd_rsoff8(u8 rd, u8 rs, u8 offset8) { fatalerror("AND.b %s, [%s+#$%02x]", m_regnames8[rd], m_regnames16[rs], offset8);} +void xa_cpu::or_byte_rd_rsoff8(u8 rd, u8 rs, u8 offset8) { fatalerror("OR.b %s, [%s+#$%02x]", m_regnames8[rd], m_regnames16[rs], offset8);} +void xa_cpu::xor_byte_rd_rsoff8(u8 rd, u8 rs, u8 offset8) { fatalerror("XOR.b %s, [%s+#$%02x]", m_regnames8[rd], m_regnames16[rs], offset8);} +void xa_cpu::mov_byte_rd_rsoff8(u8 rd, u8 rs, u8 offset8) { u16 fulloffset = util::sext(offset8, 8); u16 address = get_addr(rs) + fulloffset; u8 val = rdat8(address); do_nz_flags_8(val); sr8(rd, val); cy(5); } + +// ALUOP.w [Rd+off8], Rs +// ALUOP.b [Rd+off8], Rs +// ADD [Rd+offset8], Rs Add reg to reg-ind w/ 8-bit offs 3 6 0000 S100 ssss 1ddd 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 +// SUB [Rd+offset8], Rs Subtract reg to reg-ind w/ 8-bit offs 3 6 0010 S100 ssss 1ddd 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 +// CMP [Rd+offset8], Rs Compare reg w/ reg-ind w/ 8-bit offs 3 6 0100 S100 ssss 1ddd oooo oooo +// AND [Rd+offset8], Rs Logical AND reg to reg-ind w/ 8-bit offs 3 6 0101 S100 ssss 1ddd oooo oooo +// OR [Rd+offset8], Rs Logical OR reg to reg-ind w/ 8-bit offs 3 6 0110 S100 ssss 1ddd oooo oooo +// XOR [Rd+offset8], Rs Logical XOR reg to reg-ind w/ 8-bit offs 3 6 0111 S100 ssss 1ddd oooo oooo +// MOV [Rd+offset8], Rs Move reg to reg-ind w/ 8-bit offs 3 5 1000 S100 ssss 1ddd oooo oooo +void xa_cpu::aluop_word_rdoff8_rs(int alu_op, u8 rd, u8 offset8, u8 rs) +{ + switch (alu_op) + { + case 0x0: add_word_rdoff8_rs(rd, offset8, rs); break; + case 0x1: addc_word_rdoff8_rs(rd, offset8, rs); break; + case 0x2: sub_word_rdoff8_rs(rd, offset8, rs); break; + case 0x3: subb_word_rdoff8_rs(rd, offset8, rs); break; + case 0x4: cmp_word_rdoff8_rs(rd, offset8, rs); break; + case 0x5: and_word_rdoff8_rs(rd, offset8, rs); break; + case 0x6: or_word_rdoff8_rs(rd, offset8, rs); break; + case 0x7: xor_word_rdoff8_rs(rd, offset8, rs); break; + case 0x8: mov_word_rdoff8_rs(rd, offset8, rs); break; + default: logerror("UNK_ALUOP.w [%s+#$%02x], %s", m_regnames16[rd], offset8, m_regnames16[rs]); do_nop(); break; + } +} +void xa_cpu::aluop_byte_rdoff8_rs(int alu_op, u8 rd, u8 offset8, u8 rs) +{ + switch (alu_op) + { + case 0x0: add_byte_rdoff8_rs(rd, offset8, rs); break; + case 0x1: addc_byte_rdoff8_rs(rd, offset8, rs); break; + case 0x2: sub_byte_rdoff8_rs(rd, offset8, rs); break; + case 0x3: subb_byte_rdoff8_rs(rd, offset8, rs); break; + case 0x4: cmp_byte_rdoff8_rs(rd, offset8, rs); break; + case 0x5: and_byte_rdoff8_rs(rd, offset8, rs); break; + case 0x6: or_byte_rdoff8_rs(rd, offset8, rs); break; + case 0x7: xor_byte_rdoff8_rs(rd, offset8, rs); break; + case 0x8: mov_byte_rdoff8_rs(rd, offset8, rs); break; + default: logerror("UNK_ALUOP.b [%s+#$%02x], %s", m_regnames16[rd], offset8, m_regnames8[rs]); do_nop(); break; + } +} + +void xa_cpu::add_word_rdoff8_rs(u8 rd, u8 offset8, u8 rs) { fatalerror("ADD.w [%s+#$%02x], %s", m_regnames16[rd], offset8, m_regnames16[rs]);} +void xa_cpu::addc_word_rdoff8_rs(u8 rd, u8 offset8, u8 rs){ fatalerror("ADDC.w [%s+#$%02x], %s", m_regnames16[rd], offset8, m_regnames16[rs]);} +void xa_cpu::sub_word_rdoff8_rs(u8 rd, u8 offset8, u8 rs) { fatalerror("SUB.w [%s+#$%02x], %s", m_regnames16[rd], offset8, m_regnames16[rs]);} +void xa_cpu::subb_word_rdoff8_rs(u8 rd, u8 offset8, u8 rs){ fatalerror("SUBB.w [%s+#$%02x], %s", m_regnames16[rd], offset8, m_regnames16[rs]);} +void xa_cpu::cmp_word_rdoff8_rs(u8 rd, u8 offset8, u8 rs) { fatalerror("CMP.w [%s+#$%02x], %s", m_regnames16[rd], offset8, m_regnames16[rs]);} +void xa_cpu::and_word_rdoff8_rs(u8 rd, u8 offset8, u8 rs) { fatalerror("AND.w [%s+#$%02x], %s", m_regnames16[rd], offset8, m_regnames16[rs]);} +void xa_cpu::or_word_rdoff8_rs(u8 rd, u8 offset8, u8 rs) { fatalerror("OR.w [%s+#$%02x], %s", m_regnames16[rd], offset8, m_regnames16[rs]);} +void xa_cpu::xor_word_rdoff8_rs(u8 rd, u8 offset8, u8 rs) { fatalerror("XOR.w [%s+#$%02x], %s", m_regnames16[rd], offset8, m_regnames16[rs]);} +void xa_cpu::mov_word_rdoff8_rs(u8 rd, u8 offset8, u8 rs) { u16 val = gr16(rs); u16 fulloffset = util::sext(offset8, 8); u16 address = get_addr(rd) + fulloffset; do_nz_flags_16(val); wdat16(address, val); cy(5); } + +void xa_cpu::add_byte_rdoff8_rs(u8 rd, u8 offset8, u8 rs) { fatalerror("ADD.b [%s+#$%02x], %s", m_regnames16[rd], offset8, m_regnames8[rs]);} +void xa_cpu::addc_byte_rdoff8_rs(u8 rd, u8 offset8, u8 rs){ fatalerror("ADDC.b [%s+#$%02x], %s", m_regnames16[rd], offset8, m_regnames8[rs]);} +void xa_cpu::sub_byte_rdoff8_rs(u8 rd, u8 offset8, u8 rs) { fatalerror("SUB.b [%s+#$%02x], %s", m_regnames16[rd], offset8, m_regnames8[rs]);} +void xa_cpu::subb_byte_rdoff8_rs(u8 rd, u8 offset8, u8 rs){ fatalerror("SUBB.b [%s+#$%02x], %s", m_regnames16[rd], offset8, m_regnames8[rs]);} +void xa_cpu::cmp_byte_rdoff8_rs(u8 rd, u8 offset8, u8 rs) { fatalerror("CMP.b [%s+#$%02x], %s", m_regnames16[rd], offset8, m_regnames8[rs]);} +void xa_cpu::and_byte_rdoff8_rs(u8 rd, u8 offset8, u8 rs) { fatalerror("AND.b [%s+#$%02x], %s", m_regnames16[rd], offset8, m_regnames8[rs]);} +void xa_cpu::or_byte_rdoff8_rs(u8 rd, u8 offset8, u8 rs) { fatalerror("OR.b [%s+#$%02x], %s", m_regnames16[rd], offset8, m_regnames8[rs]);} +void xa_cpu::xor_byte_rdoff8_rs(u8 rd, u8 offset8, u8 rs) { fatalerror("XOR.b [%s+#$%02x], %s", m_regnames16[rd], offset8, m_regnames8[rs]);} +void xa_cpu::mov_byte_rdoff8_rs(u8 rd, u8 offset8, u8 rs) { u8 val = gr8(rs); u16 fulloffset = util::sext(offset8, 8); u16 address = get_addr(rd) + fulloffset; do_nz_flags_8(val); wdat8(address, val); cy(5); } + + +// ALUOP.w Rd, [Rs+off16] +// ALUOP.b Rd, [Rs+off16] +// ADD Rd, [Rs+offset16] Add reg-ind w/ 16-bit offs to reg 4 6 0000 S101 dddd 0sss oooo oooo 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 +// SUB Rd, [Rs+offset16] Subtract reg-ind w/ 16-bit offs to reg 4 6 0010 S101 dddd 0sss oooo oooo 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 +// CMP Rd, [Rs+offset16] Compare reg-ind w/ 16-bit offs w/ reg 4 6 0100 S101 dddd 0sss oooo oooo 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 +// OR Rd, [Rs+offset16] Logical OR reg-ind w/ 16-bit offs to reg 4 6 0110 S101 dddd 0sss oooo oooo 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 +// MOV Rd, [Rs+offset16] Move reg-ind w/ 16-bit offs to reg 4 5 1000 S101 dddd 0sss oooo oooo oooo oooo +void xa_cpu::aluop_word_rsoff16(int alu_op, u8 rd, u8 rs, u16 offset16) +{ + switch (alu_op) + { + case 0x0: add_word_rd_rsoff16(rd, rs, offset16); break; + case 0x1: addc_word_rd_rsoff16(rd, rs, offset16); break; + case 0x2: sub_word_rd_rsoff16(rd, rs, offset16); break; + case 0x3: subb_word_rd_rsoff16(rd, rs, offset16); break; + case 0x4: cmp_word_rd_rsoff16(rd, rs, offset16); break; + case 0x5: and_word_rd_rsoff16(rd, rs, offset16); break; + case 0x6: or_word_rd_rsoff16(rd, rs, offset16); break; + case 0x7: xor_word_rd_rsoff16(rd, rs, offset16); break; + case 0x8: mov_word_rd_rsoff16(rd, rs, offset16); break; + default: logerror("UNK_ALUOP.w %s, [%s+#$%04x]", m_regnames16[rd], m_regnames16[rs], offset16); do_nop(); break; + } +} +void xa_cpu::aluop_byte_rsoff16(int alu_op, u8 rd, u8 rs, u16 offset16) +{ + switch (alu_op) + { + case 0x0: add_byte_rd_rsoff16(rd, rs, offset16); break; + case 0x1: addc_byte_rd_rsoff16(rd, rs, offset16); break; + case 0x2: sub_byte_rd_rsoff16(rd, rs, offset16); break; + case 0x3: subb_byte_rd_rsoff16(rd, rs, offset16); break; + case 0x4: cmp_byte_rd_rsoff16(rd, rs, offset16); break; + case 0x5: and_byte_rd_rsoff16(rd, rs, offset16); break; + case 0x6: or_byte_rd_rsoff16(rd, rs, offset16); break; + case 0x7: xor_byte_rd_rsoff16(rd, rs, offset16); break; + case 0x8: mov_byte_rd_rsoff16(rd, rs, offset16); break; + default: logerror("UNK_ALUOP.b %s, [%s+#$%04x]", m_regnames8[rd], m_regnames16[rs], offset16); do_nop(); break; + } +} + +void xa_cpu::add_word_rd_rsoff16(u8 rd, u8 rs, u16 offset16) { fatalerror("ADD.w %s, [%s+#$%04x]", m_regnames16[rd], m_regnames16[rs], offset16);} +void xa_cpu::addc_word_rd_rsoff16(u8 rd, u8 rs, u16 offset16){ fatalerror("ADDC.w %s, [%s+#$%04x]", m_regnames16[rd], m_regnames16[rs], offset16);} +void xa_cpu::sub_word_rd_rsoff16(u8 rd, u8 rs, u16 offset16) { fatalerror("SUB.w %s, [%s+#$%04x]", m_regnames16[rd], m_regnames16[rs], offset16);} +void xa_cpu::subb_word_rd_rsoff16(u8 rd, u8 rs, u16 offset16){ fatalerror("SUBB.w %s, [%s+#$%04x]", m_regnames16[rd], m_regnames16[rs], offset16);} +void xa_cpu::cmp_word_rd_rsoff16(u8 rd, u8 rs, u16 offset16) { fatalerror("CMP.w %s, [%s+#$%04x]", m_regnames16[rd], m_regnames16[rs], offset16);} +void xa_cpu::and_word_rd_rsoff16(u8 rd, u8 rs, u16 offset16) { fatalerror("AND.w %s, [%s+#$%04x]", m_regnames16[rd], m_regnames16[rs], offset16);} +void xa_cpu::or_word_rd_rsoff16(u8 rd, u8 rs, u16 offset16) { fatalerror("OR.w %s, [%s+#$%04x]", m_regnames16[rd], m_regnames16[rs], offset16);} +void xa_cpu::xor_word_rd_rsoff16(u8 rd, u8 rs, u16 offset16) { fatalerror("XOR.w %s, [%s+#$%04x]", m_regnames16[rd], m_regnames16[rs], offset16);} +void xa_cpu::mov_word_rd_rsoff16(u8 rd, u8 rs, u16 offset16) { fatalerror("MOV.w %s, [%s+#$%04x]", m_regnames16[rd], m_regnames16[rs], offset16);} + +void xa_cpu::add_byte_rd_rsoff16(u8 rd, u8 rs, u16 offset16) { fatalerror("ADD.b %s, [%s+#$%04x]", m_regnames8[rd], m_regnames16[rs], offset16);} +void xa_cpu::addc_byte_rd_rsoff16(u8 rd, u8 rs, u16 offset16){ fatalerror("ADDC.b %s, [%s+#$%04x]", m_regnames8[rd], m_regnames16[rs], offset16);} +void xa_cpu::sub_byte_rd_rsoff16(u8 rd, u8 rs, u16 offset16) { fatalerror("SUB.b %s, [%s+#$%04x]", m_regnames8[rd], m_regnames16[rs], offset16);} +void xa_cpu::subb_byte_rd_rsoff16(u8 rd, u8 rs, u16 offset16){ fatalerror("SUBB.b %s, [%s+#$%04x]", m_regnames8[rd], m_regnames16[rs], offset16);} +void xa_cpu::cmp_byte_rd_rsoff16(u8 rd, u8 rs, u16 offset16) { fatalerror("CMP.b %s, [%s+#$%04x]", m_regnames8[rd], m_regnames16[rs], offset16);} +void xa_cpu::and_byte_rd_rsoff16(u8 rd, u8 rs, u16 offset16) { fatalerror("AND.b %s, [%s+#$%04x]", m_regnames8[rd], m_regnames16[rs], offset16);} +void xa_cpu::or_byte_rd_rsoff16(u8 rd, u8 rs, u16 offset16) { fatalerror("OR.b %s, [%s+#$%04x]", m_regnames8[rd], m_regnames16[rs], offset16);} +void xa_cpu::xor_byte_rd_rsoff16(u8 rd, u8 rs, u16 offset16) { fatalerror("XOR.b %s, [%s+#$%04x]", m_regnames8[rd], m_regnames16[rs], offset16);} +void xa_cpu::mov_byte_rd_rsoff16(u8 rd, u8 rs, u16 offset16) { fatalerror("MOV.b %s, [%s+#$%04x]", m_regnames8[rd], m_regnames16[rs], offset16);} + +// ALUOP.w [Rd+off16], Rs +// ALUOP.b [Rd+off16], Rs +// ADD [Rd+offset16], Rs Add reg to reg-ind w/ 16-bit offs 4 6 0000 S101 ssss 1ddd 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 +// SUB [Rd+offset16], Rs Subtract reg to reg-ind w/ 16-bit offs 4 6 0010 S101 ssss 1ddd 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 +// CMP [Rd+offset16], Rs Compare reg w/ reg-ind w/ 16-bit offs 4 6 0100 S101 ssss 1ddd 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 +// OR [Rd+offset16], Rs Logical OR reg to reg-ind w/ 16-bit offs 4 6 0110 S101 ssss 1ddd 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 +// MOV [Rd+offset16], Rs Move reg to reg-ind w/ 16-bit offs 4 5 1000 S101 ssss 1ddd oooo oooo oooo oooo +void xa_cpu::aluop_word_rdoff16_rs(int alu_op, u8 rd, u16 offset16, u8 rs) +{ + switch (alu_op) + { + case 0x0: add_word_rdoff16_rs(rd, offset16, rs); break; + case 0x1: addc_word_rdoff16_rs(rd, offset16, rs); break; + case 0x2: sub_word_rdoff16_rs(rd, offset16, rs); break; + case 0x3: subb_word_rdoff16_rs(rd, offset16, rs); break; + case 0x4: cmp_word_rdoff16_rs(rd, offset16, rs); break; + case 0x5: and_word_rdoff16_rs(rd, offset16, rs); break; + case 0x6: or_word_rdoff16_rs(rd, offset16, rs); break; + case 0x7: xor_word_rdoff16_rs(rd, offset16, rs); break; + case 0x8: mov_word_rdoff16_rs(rd, offset16, rs); break; + default: logerror("UNK_ALUOP.w [%s+#$%04x], %s", m_regnames16[rd], offset16, m_regnames16[rs]); do_nop(); break; + } +} +void xa_cpu::aluop_byte_rdoff16_rs(int alu_op, u8 rd, u16 offset16, u8 rs) +{ + switch (alu_op) + { + case 0x0: add_byte_rdoff16_rs(rd, offset16, rs); break; + case 0x1: addc_byte_rdoff16_rs(rd, offset16, rs); break; + case 0x2: sub_byte_rdoff16_rs(rd, offset16, rs); break; + case 0x3: subb_byte_rdoff16_rs(rd, offset16, rs); break; + case 0x4: cmp_byte_rdoff16_rs(rd, offset16, rs); break; + case 0x5: and_byte_rdoff16_rs(rd, offset16, rs); break; + case 0x6: or_byte_rdoff16_rs(rd, offset16, rs); break; + case 0x7: xor_byte_rdoff16_rs(rd, offset16, rs); break; + case 0x8: mov_byte_rdoff16_rs(rd, offset16, rs); break; + default: logerror("UNK_ALUOP.b [%s+#$%04x], %s", m_regnames16[rd], offset16, m_regnames8[rs]); do_nop(); break; + } +} + +void xa_cpu::add_word_rdoff16_rs(u8 rd, u16 offset16, u8 rs) { fatalerror("ADD.w [%s+#$%04x], %s", m_regnames16[rd], offset16, m_regnames16[rs]);} +void xa_cpu::addc_word_rdoff16_rs(u8 rd, u16 offset16, u8 rs){ fatalerror("ADDC.w [%s+#$%04x], %s", m_regnames16[rd], offset16, m_regnames16[rs]);} +void xa_cpu::sub_word_rdoff16_rs(u8 rd, u16 offset16, u8 rs) { fatalerror("SUB.w [%s+#$%04x], %s", m_regnames16[rd], offset16, m_regnames16[rs]);} +void xa_cpu::subb_word_rdoff16_rs(u8 rd, u16 offset16, u8 rs){ fatalerror("SUBB.w [%s+#$%04x], %s", m_regnames16[rd], offset16, m_regnames16[rs]);} +void xa_cpu::cmp_word_rdoff16_rs(u8 rd, u16 offset16, u8 rs) { fatalerror("CMP.w [%s+#$%04x], %s", m_regnames16[rd], offset16, m_regnames16[rs]);} +void xa_cpu::and_word_rdoff16_rs(u8 rd, u16 offset16, u8 rs) { fatalerror("AND.w [%s+#$%04x], %s", m_regnames16[rd], offset16, m_regnames16[rs]);} +void xa_cpu::or_word_rdoff16_rs(u8 rd, u16 offset16, u8 rs) { fatalerror("OR.w [%s+#$%04x], %s", m_regnames16[rd], offset16, m_regnames16[rs]);} +void xa_cpu::xor_word_rdoff16_rs(u8 rd, u16 offset16, u8 rs) { fatalerror("XOR.w [%s+#$%04x], %s", m_regnames16[rd], offset16, m_regnames16[rs]);} +void xa_cpu::mov_word_rdoff16_rs(u8 rd, u16 offset16, u8 rs) { u16 val = gr16(rs); u16 fulloffset = offset16; u16 address = get_addr(rd) + fulloffset; do_nz_flags_16(val); wdat16(address, val); cy(5); } + +void xa_cpu::add_byte_rdoff16_rs(u8 rd, u16 offset16, u8 rs) { fatalerror("ADD.b [%s+#$%04x], %s", m_regnames16[rd], offset16, m_regnames8[rs]);} +void xa_cpu::addc_byte_rdoff16_rs(u8 rd, u16 offset16, u8 rs){ fatalerror("ADDC.b [%s+#$%04x], %s", m_regnames16[rd], offset16, m_regnames8[rs]);} +void xa_cpu::sub_byte_rdoff16_rs(u8 rd, u16 offset16, u8 rs) { fatalerror("SUB.b [%s+#$%04x], %s", m_regnames16[rd], offset16, m_regnames8[rs]);} +void xa_cpu::subb_byte_rdoff16_rs(u8 rd, u16 offset16, u8 rs){ fatalerror("SUBB.b [%s+#$%04x], %s", m_regnames16[rd], offset16, m_regnames8[rs]);} +void xa_cpu::cmp_byte_rdoff16_rs(u8 rd, u16 offset16, u8 rs) { fatalerror("CMP.b [%s+#$%04x], %s", m_regnames16[rd], offset16, m_regnames8[rs]);} +void xa_cpu::and_byte_rdoff16_rs(u8 rd, u16 offset16, u8 rs) { fatalerror("AND.b [%s+#$%04x], %s", m_regnames16[rd], offset16, m_regnames8[rs]);} +void xa_cpu::or_byte_rdoff16_rs(u8 rd, u16 offset16, u8 rs) { fatalerror("OR.b [%s+#$%04x], %s", m_regnames16[rd], offset16, m_regnames8[rs]);} +void xa_cpu::xor_byte_rdoff16_rs(u8 rd, u16 offset16, u8 rs) { fatalerror("XOR.b [%s+#$%04x], %s", m_regnames16[rd], offset16, m_regnames8[rs]);} +void xa_cpu::mov_byte_rdoff16_rs(u8 rd, u16 offset16, u8 rs) { u8 val = gr16(rs); u16 fulloffset = offset16; u16 address = get_addr(rd) + fulloffset; do_nz_flags_8(val); wdat8(address, val); cy(5); } + +// ALUOP.w Rd, Direct +// ALUOP.b Rd, Direct +// ADD Rd, direct Add mem to reg 3 4 0000 S110 dddd 0DDD DDDD DDDD +// ADDC Rd, direct Add mem to reg w/ carry 3 4 0001 S110 dddd 0DDD DDDD DDDD +// SUB Rd, direct Subtract mem to reg 3 4 0010 S110 dddd 0DDD DDDD DDDD +// SUBB Rd, direct Subtract w/ borrow mem to reg 3 4 0011 S110 dddd 0DDD DDDD DDDD +// CMP Rd, direct Compare mem w/ reg 3 4 0100 S110 dddd 0DDD DDDD DDDD +// AND Rd, direct Logical AND mem to reg 3 4 0101 S110 dddd 0DDD DDDD DDDD +// OR Rd, direct Logical OR mem to reg 3 4 0110 S110 dddd 0DDD DDDD DDDD +// XOR Rd, direct Logical XOR mem to reg 3 4 0111 S110 dddd 0DDD DDDD DDDD +// MOV Rd, direct Move mem to reg 3 4 1000 S110 dddd 0DDD DDDD DDDD +void xa_cpu::aluop_word_rd_direct(int alu_op, u8 rd, u16 direct) +{ + switch (alu_op) + { + case 0x0: add_word_rd_direct(rd, direct); break; + case 0x1: addc_word_rd_direct(rd, direct); break; + case 0x2: sub_word_rd_direct(rd, direct); break; + case 0x3: subb_word_rd_direct(rd, direct); break; + case 0x4: cmp_word_rd_direct(rd, direct); break; + case 0x5: and_word_rd_direct(rd, direct); break; + case 0x6: or_word_rd_direct(rd, direct); break; + case 0x7: xor_word_rd_direct(rd, direct); break; + case 0x8: mov_word_rd_direct(rd, direct); break; + default: logerror("UNK_ALUOP.w %s, %s", m_regnames16[rd], get_directtext(direct)); do_nop(); break; + } +} + +void xa_cpu::aluop_byte_rd_direct(int alu_op, u8 rd, u16 direct) +{ + switch (alu_op) + { + case 0x0: add_byte_rd_direct(rd, direct); break; + case 0x1: addc_byte_rd_direct(rd, direct); break; + case 0x2: sub_byte_rd_direct(rd, direct); break; + case 0x3: subb_byte_rd_direct(rd, direct); break; + case 0x4: cmp_byte_rd_direct(rd, direct); break; + case 0x5: and_byte_rd_direct(rd, direct); break; + case 0x6: or_byte_rd_direct(rd, direct); break; + case 0x7: xor_byte_rd_direct(rd, direct); break; + case 0x8: mov_byte_rd_direct(rd, direct); break; + default: logerror("UNK_ALUOP.b %s, %s", m_regnames8[rd], get_directtext(direct)); do_nop(); break; + } +} + +void xa_cpu::add_word_rd_direct(u8 rd, u16 direct) { u16 rdval = gr16(rd); u16 val = read_direct16(direct); u16 result = do_add_16(rdval, val); sr16(rd, result); cy(4); } +void xa_cpu::addc_word_rd_direct(u8 rd, u16 direct){ u16 rdval = gr16(rd); u16 val = read_direct16(direct); u16 result = do_addc_16(rdval, val); sr16(rd, result); cy(4);} +void xa_cpu::sub_word_rd_direct(u8 rd, u16 direct) { u16 rdval = gr16(rd); u16 val = read_direct16(direct); u16 result = do_sub_16(rdval, val); sr16(rd, result); cy(4); } +void xa_cpu::subb_word_rd_direct(u8 rd, u16 direct){ u16 rdval = gr16(rd); u16 val = read_direct16(direct); u16 result = do_subb_16(rdval, val); sr16(rd, result); cy(4); } +void xa_cpu::cmp_word_rd_direct(u8 rd, u16 direct) { u16 rdval = gr16(rd); u16 val = read_direct16(direct); do_sub_16(rdval, val); cy(4); } +void xa_cpu::and_word_rd_direct(u8 rd, u16 direct) { u16 rdval = gr16(rd); u16 val = read_direct16(direct); u16 result = do_and_16(rdval, val); sr16(rd, result); cy(4); } +void xa_cpu::or_word_rd_direct(u8 rd, u16 direct) { u16 rdval = gr16(rd); u16 val = read_direct16(direct); u16 result = do_or_16(rdval, val); sr16(rd, result); cy(4); } +void xa_cpu::xor_word_rd_direct(u8 rd, u16 direct) { u16 rdval = gr16(rd); u16 val = read_direct16(direct); u16 result = do_xor_16(rdval, val); sr16(rd, result); cy(4); } +void xa_cpu::mov_word_rd_direct(u8 rd, u16 direct) { u16 val = read_direct16(direct); do_nz_flags_16(val); sr16(rd, val); cy(4);} + +void xa_cpu::add_byte_rd_direct(u8 rd, u16 direct) { fatalerror("ADD.b %s, %s", m_regnames8[rd], get_directtext(direct));} +void xa_cpu::addc_byte_rd_direct(u8 rd, u16 direct){ fatalerror("ADDC.b %s, %s", m_regnames8[rd], get_directtext(direct));} +void xa_cpu::sub_byte_rd_direct(u8 rd, u16 direct) { fatalerror("SUB.b %s, %s", m_regnames8[rd], get_directtext(direct));} +void xa_cpu::subb_byte_rd_direct(u8 rd, u16 direct){ fatalerror("SUBB.b %s, %s", m_regnames8[rd], get_directtext(direct));} +void xa_cpu::cmp_byte_rd_direct(u8 rd, u16 direct) { u8 rdval = gr8(rd); u8 val = read_direct8(direct); do_sub_8(rdval, val); cy(4); } +void xa_cpu::and_byte_rd_direct(u8 rd, u16 direct) { fatalerror("AND.b %s, %s", m_regnames8[rd], get_directtext(direct));} +void xa_cpu::or_byte_rd_direct(u8 rd, u16 direct) { fatalerror("OR.b %s, %s", m_regnames8[rd], get_directtext(direct));} +void xa_cpu::xor_byte_rd_direct(u8 rd, u16 direct) { fatalerror("XOR.b %s, %s", m_regnames8[rd], get_directtext(direct));} +void xa_cpu::mov_byte_rd_direct(u8 rd, u16 direct) { u8 val = read_direct8(direct); do_nz_flags_8(val); sr8(rd, val); cy(4); } + +// ALUOP.w Direct, Rs +// ALUOP.b Direct, Rs +// ADD direct, Rs Add reg to mem 3 4 0000 S110 ssss 1DDD DDDD DDDD +// ADDC direct, Rs Add reg to mem w/ carry 3 4 0001 S110 ssss 1DDD DDDD DDDD +// SUB direct, Rs Subtract reg to mem 3 4 0010 S110 ssss 1DDD DDDD DDDD +// SUBB direct, Rs Subtract w/ borrow reg to mem 3 4 0011 S110 ssss 1DDD DDDD DDDD +// CMP direct, Rs Compare reg w/ mem 3 4 0100 S110 ssss 1DDD DDDD DDDD +// AND direct, Rs Logical AND reg to mem 3 4 0101 S110 ssss 1DDD DDDD DDDD +// OR direct, Rs Logical OR reg to mem 3 4 0110 S110 ssss 1DDD DDDD DDDD +// XOR direct, Rs Logical XOR reg to mem 3 4 0111 S110 ssss 1DDD DDDD DDDD +// MOV direct, Rs Move reg to mem 3 4 1000 S110 ssss 1DDD DDDD DDDD + +void xa_cpu::aluop_word_direct_rs(int alu_op, u16 direct, u8 rs) +{ + switch (alu_op) + { + case 0x0: add_word_direct_rs(direct, rs); break; + case 0x1: addc_word_direct_rs(direct, rs); break; + case 0x2: sub_word_direct_rs(direct, rs); break; + case 0x3: subb_word_direct_rs(direct, rs); break; + case 0x4: cmp_word_direct_rs(direct, rs); break; + case 0x5: and_word_direct_rs(direct, rs); break; + case 0x6: or_word_direct_rs(direct, rs); break; + case 0x7: xor_word_direct_rs(direct, rs); break; + case 0x8: mov_word_direct_rs(direct, rs); break; + default: logerror("UNK_ALUOP.w %s, %s", get_directtext(direct), m_regnames16[rs]); do_nop(); break; + } +} + +void xa_cpu::aluop_byte_direct_rs(int alu_op, u16 direct, u8 rs) +{ + switch (alu_op) + { + case 0x0: add_byte_direct_rs(direct, rs); break; + case 0x1: addc_byte_direct_rs(direct, rs); break; + case 0x2: sub_byte_direct_rs(direct, rs); break; + case 0x3: subb_byte_direct_rs(direct, rs); break; + case 0x4: cmp_byte_direct_rs(direct, rs); break; + case 0x5: and_byte_direct_rs(direct, rs); break; + case 0x6: or_byte_direct_rs(direct, rs); break; + case 0x7: xor_byte_direct_rs(direct, rs); break; + case 0x8: mov_byte_direct_rs(direct, rs); break; + default: logerror("UNK_ALUOP.b %s, %s", get_directtext(direct), m_regnames8[rs]); do_nop(); break; + } +} + +void xa_cpu::add_word_direct_rs(u16 direct, u8 rs) { u16 directval = read_direct16(direct); u16 val = gr16(rs); u16 result = do_add_16(directval, val); write_direct16(direct, result); cy(4); } +void xa_cpu::addc_word_direct_rs(u16 direct, u8 rs){ u16 directval = read_direct16(direct); u16 val = gr16(rs); u16 result = do_addc_16(directval, val); write_direct16(direct, result); cy(4); } +void xa_cpu::sub_word_direct_rs(u16 direct, u8 rs) { u16 directval = read_direct16(direct); u16 val = gr16(rs); u16 result = do_sub_16(directval, val); write_direct16(direct, result); cy(4); } +void xa_cpu::subb_word_direct_rs(u16 direct, u8 rs){ u16 directval = read_direct16(direct); u16 val = gr16(rs); u16 result = do_subb_16(directval, val); write_direct16(direct, result); cy(4) ; } +void xa_cpu::cmp_word_direct_rs(u16 direct, u8 rs) { u16 directval = read_direct16(direct); u16 val = gr16(rs); do_sub_16(directval, val); cy(4); } +void xa_cpu::and_word_direct_rs(u16 direct, u8 rs) { u16 directval = read_direct16(direct); u16 val = gr16(rs); u16 result = do_and_16(directval, val); write_direct16(direct, result); cy(4); } +void xa_cpu::or_word_direct_rs(u16 direct, u8 rs) { u16 directval = read_direct16(direct); u16 val = gr16(rs); u16 result = do_or_16(directval, val); write_direct16(direct, result); cy(4); } +void xa_cpu::xor_word_direct_rs(u16 direct, u8 rs) { u16 directval = read_direct16(direct); u16 val = gr16(rs); u16 result = do_xor_16(directval, val); write_direct16(direct, result); cy(4); } +void xa_cpu::mov_word_direct_rs(u16 direct, u8 rs) { u16 val = gr16(rs); do_nz_flags_16(val); write_direct16(direct, val); cy(4); } + +void xa_cpu::add_byte_direct_rs(u16 direct, u8 rs) { fatalerror("ADD.b %s, %s", get_directtext(direct), m_regnames8[rs]);} +void xa_cpu::addc_byte_direct_rs(u16 direct, u8 rs){ fatalerror("ADDC.b %s, %s", get_directtext(direct), m_regnames8[rs]);} +void xa_cpu::sub_byte_direct_rs(u16 direct, u8 rs) { fatalerror("SUB.b %s, %s", get_directtext(direct), m_regnames8[rs]);} +void xa_cpu::subb_byte_direct_rs(u16 direct, u8 rs){ fatalerror("SUBB.b %s, %s", get_directtext(direct), m_regnames8[rs]);} +void xa_cpu::cmp_byte_direct_rs(u16 direct, u8 rs) { u8 directval = read_direct8(direct); u8 val = gr8(rs); do_sub_8(directval, val); cy(4); } +void xa_cpu::and_byte_direct_rs(u16 direct, u8 rs) { fatalerror("AND.b %s, %s", get_directtext(direct), m_regnames8[rs]);} +void xa_cpu::or_byte_direct_rs(u16 direct, u8 rs) { fatalerror("OR.b %s, %s", get_directtext(direct), m_regnames8[rs]);} +void xa_cpu::xor_byte_direct_rs(u16 direct, u8 rs) { fatalerror("XOR.b %s, %s", get_directtext(direct), m_regnames8[rs]);} +void xa_cpu::mov_byte_direct_rs(u16 direct, u8 rs) { u8 val = gr8(rs); do_nz_flags_8(val); write_direct8(direct, val); cy(4); } + +/////////////////////////////////////////////////////// + +// MOVS Rd, #data4 Move 4-bit sign-extended imm data to reg 2 3 1011 S001 dddd iiii +void xa_cpu::movs_word_rd_data4(u8 rd, u8 data4) { u16 data = util::sext(data4, 4); sr16(rd, data); do_nz_flags_16(data); cy(3); } +void xa_cpu::movs_byte_rd_data4(u8 rd, u8 data4) { u8 data = util::sext(data4, 4); sr8(rd, data); do_nz_flags_8(data); cy(3); } +// ADDS Rd, #data4 Add 4-bit signed imm data to reg 2 3 1010 S001 dddd iiii +void xa_cpu::adds_word_rd_data4(u8 rd, u8 data4) { u16 data = util::sext(data4, 4); u16 regval = gr16(rd); regval += data; do_nz_flags_16(regval); sr16(rd, regval); cy(3); } +void xa_cpu::adds_byte_rd_data4(u8 rd, u8 data4) { u8 data = util::sext(data4, 4); u8 regval = gr8(rd); regval += data; do_nz_flags_8(regval); sr8(rd, regval); cy(3); } + +// MOVS [Rd], #data4 Move 4-bit sign-extended imm data to reg-ind 2 3 1011 S010 0ddd iiii +void xa_cpu::movs_word_indrd_data4(u8 rd, u8 data4){ u16 data = util::sext(data4, 4); u16 address = get_addr(rd); wdat16(address, data); do_nz_flags_16(data); cy(3); } +void xa_cpu::movs_byte_indrd_data4(u8 rd, u8 data4){ u8 data = util::sext(data4, 4); u16 address = get_addr(rd); wdat8(address, data); do_nz_flags_8(data); cy(3); } +// ADDS [Rd], #data4 Add 4-bit signed imm data to reg-ind 2 4 1010 S010 0ddd iiii +void xa_cpu::adds_word_indrd_data4(u8 rd, u8 data4){ u16 data = util::sext(data4, 4); u16 address = get_addr(rd); u16 rdval = rdat16(address); u16 result = do_add_16(rdval, data); wdat16(address, result); cy(4); } +void xa_cpu::adds_byte_indrd_data4(u8 rd, u8 data4){ u8 data = util::sext(data4, 4); u16 address = get_addr(rd); u8 rdval = rdat8(address); u8 result = do_add_8(rdval, data); wdat8(address, result); cy(4); } + +// MOVS [Rd+], #data4 Move 4-bit sign-extended imm data to reg-ind w/ autoinc 2 4 1011 S011 0ddd iiii +void xa_cpu::movs_word_indrdinc_data4(u8 rd, u8 data4) { u16 data = util::sext(data4, 4); u16 address = get_addr(rd); wdat16(address, data); address += 2; do_nz_flags_16(data); set_addr(rd, address); cy(4); } +void xa_cpu::movs_byte_indrdinc_data4(u8 rd, u8 data4) { u8 data = util::sext(data4, 4); u16 address = get_addr(rd); wdat8(address, data); address++; do_nz_flags_8(data); set_addr(rd, address); cy(4); } +// ADDS [Rd+], #data4 Add 4-bit signed imm data to reg-ind w/ autoinc 2 5 1010 S011 0ddd iiii +void xa_cpu::adds_word_indrdinc_data4(u8 rd, u8 data4){ fatalerror("ADDS.w [%s+], %s", m_regnames16[rd], show_expanded_data4(data4, 1)); } +void xa_cpu::adds_byte_indrdinc_data4(u8 rd, u8 data4){ fatalerror("ADDS.b [%s+], %s", m_regnames16[rd], show_expanded_data4(data4, 0)); } + +// 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 +void xa_cpu::movs_word_indrdoff8_data4(u8 rd, u8 off8, u8 data4) { u16 data = util::sext(data4, 4); u16 fulloffset = util::sext(off8, 8); u16 address = get_addr(rd) + fulloffset; wdat16(address, data); do_nz_flags_16(data); cy(5); } +void xa_cpu::movs_byte_indrdoff8_data4(u8 rd, u8 off8, u8 data4){ u8 data = util::sext(data4, 4); u16 fulloffset = util::sext(off8, 8); u16 address = get_addr(rd) + fulloffset; wdat8(address, data); do_nz_flags_8(data); cy(5); } +// 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 +void xa_cpu::adds_word_indrdoff8_data4(u8 rd, u8 off8, u8 data4){ u16 data = util::sext(data4, 4); u16 fulloffset = util::sext(off8, 8); u16 address = get_addr(rd) + fulloffset; u16 rdval = rdat16(address); u16 result = do_add_16(rdval, data); wdat16(address, result); cy(4); } +void xa_cpu::adds_byte_indrdoff8_data4(u8 rd, u8 off8, u8 data4){ u8 data = util::sext(data4, 4); u16 fulloffset = util::sext(off8, 8); u16 address = get_addr(rd) + fulloffset; u8 rdval = rdat8(address); u8 result = do_add_8(rdval, data); wdat8(address, result); cy(4); } + +// 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 +void xa_cpu::movs_word_indrdoff16_data4(u8 rd, u16 off16, u8 data4){ fatalerror("MOVS.w [%s+$%04x], %s", m_regnames16[rd], off16, show_expanded_data4(data4, 1)); } +void xa_cpu::movs_byte_indrdoff16_data4(u8 rd, u16 off16, u8 data4){ fatalerror("MOVS.b [%s+$%04x], %s", m_regnames16[rd], off16, show_expanded_data4(data4, 0)); } +// 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 +void xa_cpu::adds_word_indrdoff16_data4(u8 rd, u16 off16, u8 data4){ fatalerror("ADDS.w [%s+$%04x], %s", m_regnames16[rd], off16, show_expanded_data4(data4, 1)); } +void xa_cpu::adds_byte_indrdoff16_data4(u8 rd, u16 off16, u8 data4){ fatalerror("ADDS.b [%s+$%04x], %s", m_regnames16[rd], off16, show_expanded_data4(data4, 0)); } + +// MOVS direct, #data4 Move 4-bit sign-extended imm data to mem 3 3 1011 S110 0DDD iiii DDDD DDDD +void xa_cpu::movs_word_direct_data4(u16 direct, u8 data4) { u16 data = util::sext(data4, 4); do_nz_flags_16(data); write_direct16(direct, data); cy(3); } +void xa_cpu::movs_byte_direct_data4(u16 direct, u8 data4) { u8 data = util::sext(data4, 4); do_nz_flags_8(data); write_direct8(direct, data); cy(3); } +// ADDS direct, #data4 Add 4-bit signed imm data to mem 3 4 1010 S110 0DDD iiii DDDD DDDD +void xa_cpu::adds_word_direct_data4(u16 direct, u8 data4){ fatalerror("ADDS.w %s, %s\n", get_directtext(direct), show_expanded_data4(data4, 0)); } +void xa_cpu::adds_byte_direct_data4(u16 direct, u8 data4){ u8 directval = read_direct8(direct); u8 data = util::sext(data4, 4); directval += data; do_nz_flags_8(directval); write_direct8(direct, directval); cy(4); } + +// CALL rel16 Relative call (range +/- 64K) 3 7/4(PZ) 1100 0101 rrrr rrrr rrrr rrrr +void xa_cpu::call_rel16(u16 rel16) { if (m_pagezeromode) { push_word_to_stack(m_pc); set_pc_in_current_page(expand_rel16(rel16)); cy(4); } else { cy(7); fatalerror("CALL rel16 not in pagezero mode"); } } + +// BCC rel8 Branch if the carry flag is clear 2 6t/3nt 1111 0000 rrrr rrrr +void xa_cpu::bcc_rel8(u8 rel8) { if (get_c_flag() == 0) { set_pc_in_current_page(expand_rel8(rel8)); cy(6); } else { cy(3); } } +// BCS rel8 Branch if the carry flag is set 2 6t/3nt 1111 0001 rrrr rrrr +void xa_cpu::bcs_rel8(u8 rel8) { if (get_c_flag()) { set_pc_in_current_page(expand_rel8(rel8)); cy(6); } else { cy(3); } } +// BNE rel8 Branch if the zero flag is not set 2 6t/3nt 1111 0010 rrrr rrrr +void xa_cpu::bne_rel8(u8 rel8) { if (get_z_flag() == 0) { set_pc_in_current_page(expand_rel8(rel8)); cy(6); } else { cy(3); } } +// BEQ rel8 Branch if the zero flag is set 2 6t/3nt 1111 0011 rrrr rrrr +void xa_cpu::beq_rel8(u8 rel8) { if (get_z_flag()) { set_pc_in_current_page(expand_rel8(rel8)); cy(6); } else { cy(3); } } +// BNV rel8 Branch if overflow flag is clear 2 6t/3nt 1111 0100 rrrr rrrr +void xa_cpu::bnv_rel8(u8 rel8) { fatalerror("BNV %04x\n", expand_rel8(rel8)); } +// BOV rel8 Branch if overflow flag is set 2 6t/3nt 1111 0101 rrrr rrrr +void xa_cpu::bov_rel8(u8 rel8) { fatalerror("BOV %04x\n", expand_rel8(rel8)); } +// BPL rel8 Branch if the negative flag is clear 2 6t/3nt 1111 0110 rrrr rrrr +void xa_cpu::bpl_rel8(u8 rel8) { fatalerror("BPL %04x\n", expand_rel8(rel8)); } +// BMI rel8 Branch if the negative flag is set 2 6t/3nt 1111 0111 rrrr rrrr +void xa_cpu::bmi_rel8(u8 rel8) { fatalerror("BMI %04x\n", expand_rel8(rel8)); } +// BG rel8 Branch if greater than (unsigned) 2 6t/3nt 1111 1000 rrrr rrrr +void xa_cpu::bg_rel8(u8 rel8) { fatalerror("BG %04x\n", expand_rel8(rel8)); } +// BL rel8 Branch if less than or equal to (unsigned) 2 6t/3nt 1111 1001 rrrr rrrr +void xa_cpu::bl_rel8(u8 rel8) { fatalerror("BL %04x\n", expand_rel8(rel8)); } +// BGE rel8 Branch if greater than or equal to (signed) 2 6t/3nt 1111 1010 rrrr rrrr +void xa_cpu::bge_rel8(u8 rel8) { fatalerror("BGE %04x\n", expand_rel8(rel8)); } +// BLT rel8 Branch if less than (signed) 2 6t/3nt 1111 1011 rrrr rrrr +void xa_cpu::blt_rel8(u8 rel8) { if (get_n_flag() ^ get_v_flag()) { set_pc_in_current_page(expand_rel8(rel8)); cy(6); } else { cy(3); } } +// BGT rel8 Branch if greater than (signed) 2 6t/3nt 1111 1100 rrrr rrrr +void xa_cpu::bgt_rel8(u8 rel8) { if ((get_z_flag() | get_n_flag()) ^ get_v_flag()) { set_pc_in_current_page(expand_rel8(rel8)); cy(6); } else { cy(3); } } +// BLE rel8 Branch if less than or equal to (signed) 2 6t/3nt 1111 1101 rrrr rrrr +void xa_cpu::ble_rel8(u8 rel8) { fatalerror("BLE %04x\n", expand_rel8(rel8)); } +// BR rel8 Short unconditional branch 2 6 1111 1110 rrrr rrrr +void xa_cpu::br_rel8(u8 rel8) { set_pc_in_current_page(expand_rel8(rel8)); cy(6); } + +// immediate shifts + +// ASL Rd, #data4 Logical left shift reg by the 4-bit imm value 2 a* 1101 SS01 dddd iiii +void xa_cpu::asl_byte_rd_imm4(u8 rd, u8 amount) { fatalerror("ASL.b %s, %d", m_regnames8[rd], amount); } +void xa_cpu::asl_word_rd_imm4(u8 rd, u8 amount) { u16 fullreg = gr16(rd); fullreg = asl32_helper(fullreg, amount); sr16(rd, fullreg); } +// ASL Rd, #data5 Logical left shift reg by the 5-bit imm value 2 a* 1101 1101 dddi iiii +void xa_cpu::asl_dword_rd_imm5(u8 rd, u8 amount) { u32 fullreg = gr32(rd); fullreg = asl32_helper(fullreg, amount); sr32(rd, fullreg); } + +// ASR Rd, #data4 Arithmetic shift right reg by the 4-bit imm count 2 a* 1101 SS10 dddd iiii +void xa_cpu::asr_byte_rd_imm4(u8 rd, u8 amount) { fatalerror("ASR.b %s, %d", m_regnames8[rd], amount); } +void xa_cpu::asr_word_rd_imm4(u8 rd, u8 amount) { fatalerror("ASR.w %s, %d", m_regnames16[rd], amount); } +// ASR Rd, #data5 Arithmetic shift right reg by the 5-bit imm count 2 a* 1101 1110 dddi iiii +void xa_cpu::asr_dword_rd_imm5(u8 rd, u8 amount) { fatalerror("ASR.dw %s, %d", m_regnames16[rd], amount); } + +// LSR Rd, #data4 Logical right shift reg by the 4-bit imm value 2 a* 1101 SS00 dddd iiii +void xa_cpu::lsr_byte_rd_imm4(u8 rd, u8 amount) { fatalerror("LSR.b %s, %d", m_regnames8[rd], amount); } +void xa_cpu::lsr_word_rd_imm4(u8 rd, u8 amount) { u16 fullreg = gr16(rd); fullreg = lsr32_helper(fullreg, amount); sr16(rd, fullreg); } +// LSR Rd, #data5 Logical right shift reg by the 4-bit imm value 2 a* 1101 1100 dddi iiii +void xa_cpu::lsr_dword_rd_imm5(u8 rd, u8 amount) { u32 fullreg = gr32(rd); fullreg = lsr32_helper(fullreg, amount); sr32(rd, fullreg); } + +// register form shifts + +//ASL Rd, Rs Logical left shift dest reg by the value in the src reg 2 a* 1100 SS01 dddd ssss +void xa_cpu::asl_byte_rd_rs(u8 rd, u8 rs) { fatalerror("ASL.b %s, %d", m_regnames8[rd], m_regnames8[rs]); } +void xa_cpu::asl_word_rd_rs(u8 rd, u8 rs) { fatalerror("ASL.w %s, %d", m_regnames16[rd], m_regnames8[rs]); } +void xa_cpu::asl_dword_rd_rs(u8 rd, u8 rs) { u32 fullreg = gr32(rd); u8 amount = gr8(rs); fullreg = lsr32_helper(fullreg, amount); sr32(rd, fullreg); cy(7); } + +// ASR Rd, Rs Arithmetic shift right dest reg by the count in the src 2 a* 1100 SS10 dddd ssss +void xa_cpu::asr_byte_rd_rs(u8 rd, u8 rs) { fatalerror("ASR.b %s, %d", m_regnames8[rd], m_regnames8[rs]); } +void xa_cpu::asr_word_rd_rs(u8 rd, u8 rs) { fatalerror("ASR.w %s, %d", m_regnames16[rd], m_regnames8[rs]); } +void xa_cpu::asr_dword_rd_rs(u8 rd, u8 rs) { fatalerror("ASR.dw %s, %d", m_regnames16[rd], m_regnames8[rs]); } + +// LSR Rd, Rs Logical right shift dest reg by the value in the src reg 2 a* 1100 SS00 dddd ssss +void xa_cpu::lsr_byte_rd_rs(u8 rd, u8 rs) { fatalerror("LSR.b %s, %d", m_regnames8[rd], m_regnames8[rs]); } +void xa_cpu::lsr_word_rd_rs(u8 rd, u8 rs) { fatalerror("LSR.w %s, %d", m_regnames16[rd], m_regnames8[rs]); } +void xa_cpu::lsr_dword_rd_rs(u8 rd, u8 rs) { fatalerror("LSR.dw %s, %d", m_regnames16[rd], m_regnames8[rs]); } + +// NORM Rd, Rs Logical shift left dest reg by the value in the src reg until MSB set 2 a* 1100 SS11 dddd ssss +void xa_cpu::norm_byte_rd_rs(u8 rd, u8 rs) { fatalerror("NORM.b %s, %d", m_regnames8[rd], m_regnames8[rs]); } +void xa_cpu::norm_word_rd_rs(u8 rd, u8 rs) { fatalerror("NORM.w %s, %d", m_regnames16[rd], m_regnames8[rs]); } +void xa_cpu::norm_dword_rd_rs(u8 rd, u8 rs) { fatalerror("NORM.dw %s, %d", m_regnames16[rd], m_regnames8[rs]); } + + +//MULU.b Rd, Rs +void xa_cpu::mulu_byte_rd_rs(u8 rd, u8 rs) { fatalerror( "MULU.b %s, %s", m_regnames8[rd], m_regnames8[rs]); } +//DIVU.b Rd, Rs +void xa_cpu::divu_byte_rd_rs(u8 rd, u8 rs) { fatalerror( "DIVU.b %s, %s", m_regnames8[rd], m_regnames8[rs]); } +//MULU.w Rd, Rs +void xa_cpu::mulu_word_rd_rs(u8 rd, u8 rs) { fatalerror( "MULU.w %s, %s", m_regnames16[rd], m_regnames16[rs]); } +//DIVU.w Rd, Rs +void xa_cpu::divu_word_rd_rs(u8 rd, u8 rs) { fatalerror( "DIVU.w %s, %s", m_regnames16[rd], m_regnames16[rs]); } +// MUL.w Rd, Rs +void xa_cpu::mul_word_rd_rs(u8 rd, u8 rs) { fatalerror( "MUL.w %s, %s", m_regnames16[rd], m_regnames16[rs]); } +// DIV.w Rd, Rs +void xa_cpu::div_word_rd_rs(u8 rd, u8 rs) { fatalerror( "DIV.w %s, %s", m_regnames16[rd], m_regnames16[rs]); } + +//DIV.w Rd, #data8 +void xa_cpu::div_word_rd_data8(u8 rd, u8 data8) { fatalerror( "DIV.w %s, #$%02x", m_regnames8[rd], data8); } +//DIVU.b Rd, #data8 +void xa_cpu::divu_byte_rd_data8(u8 rd, u8 data8) { fatalerror( "DIVU.b %s, #$%02x", m_regnames8[rd], data8); } +//DIVU.w Rd, #data8 +void xa_cpu::divu_word_rd_data8(u8 rd, u8 data8) { fatalerror( "DIVU.w %s, #$%02x", m_regnames8[rd], data8); } +//MULU.b Rd, #data8 +void xa_cpu::mulu_byte_rd_data8(u8 rd, u8 data8) { fatalerror( "MULU.b %s, #$%02x", m_regnames8[rd], data8); } + +//MULU.w Rd, #data16 +void xa_cpu::mulu_word_rd_data16(u8 rd, u16 data16) { fatalerror( "MULU.w %s, #$%04x", m_regnames16[rd], data16); } +// DIVU.d Rd, #data16 32X16 unsigned double reg divide w/ imm word 4 22 1110 1001 ddd0 0001 iiii iiii iiii iiii +void xa_cpu::divu_dword_rd_data16(u8 rd, u16 data16) { fatalerror( "DIVU.d %s, #$%04x", m_regnames16[rd], data16); } +//MUL.w Rd, #data16 +void xa_cpu::mul_word_rd_data16(u8 rd, u16 data16) { fatalerror( "MUL.w %s, #$%04x", m_regnames16[rd], data16); } +//DIV.d Rd, #data16 +void xa_cpu::div_dword_rd_data16(u8 rd, u16 data16) { fatalerror( "DIV.d %s, #$%04x", m_regnames16[rd], data16); } + +// DIVU.d Rd, Rs 32X16 unsigned double reg divide 2 22 1110 1101 ddd0 ssss +void xa_cpu::divu_dword_rd_rs(u8 rd, u8 rs) +{ + u32 fullval = gr32(rd); + u16 rsval = gr16(rs); + + if (rsval) + { + u32 result = fullval / rsval; + u32 remainder = fullval % rsval; + + if (result & 0xffff0000) + set_v_flag(); + else + clear_v_flag(); + + // are z and n based on the 32-bit result, or 16 bit result? + result &= 0xffff; + + if (result == 0x0000) + set_z_flag(); + else + clear_n_flag(); + + if (result & 0x8000) + set_n_flag(); + else + clear_n_flag(); + + sr16(rd, result); + sr16(rd + 1, remainder); + } + else + { + set_v_flag(); + logerror("%s divide by zero\n", machine().describe_context()); + } + + clear_c_flag(); + + cy(22); +} +//DIV.d Rd, Rs +void xa_cpu::div_dword_rd_rs(u8 rd, u8 rs) { fatalerror( "DIV.d %s, %s", m_regnames16[rd], m_regnames16[rs]); } + +// CLR bit Clear bit 3 4 0000 1000 0000 00bb bbbb bbbb +void xa_cpu::clr_bit(u16 bit) { set_bit_8_helper(bit, 0); cy(4); } +// SETB bit Sets the bit specified 3 4 0000 1000 0001 00bb bbbb bbbb +void xa_cpu::setb_bit(u16 bit) { set_bit_8_helper(bit, 1); cy(4); } +// MOV C, bit Move bit to the carry flag 3 4 0000 1000 0010 00bb bbbb bbbb +void xa_cpu::mov_c_bit(u16 bit) { fatalerror( "MOV C, %s", get_bittext(bit) ); } +// MOV bit, C Move carry to bit 3 4 0000 1000 0011 00bb bbbb bbbb +void xa_cpu::mov_bit_c(u16 bit) { fatalerror( "MOV %s, C", get_bittext(bit) ); } +// ANL C, bit Logical AND bit to carry 3 4 0000 1000 0100 00bb bbbb bbbb +void xa_cpu::anl_c_bit(u16 bit) { fatalerror( "ANL C, %s", get_bittext(bit) ); } +// ANL C, /bit Logical AND complement of a bit to carry 3 4 0000 1000 0101 00bb bbbb bbbb +void xa_cpu::anl_c_notbit(u16 bit) { fatalerror( "ANL C, /%s", get_bittext(bit) ); } +// ORL C, bit Logical OR a bit to carry 3 4 0000 1000 0110 00bb bbbb bbbb +void xa_cpu::orl_c_bit(u16 bit) { fatalerror( "ORL C, %s", get_bittext(bit) ); } +// ORL C, /bit Logical OR complement of a bit to carry 3 4 0000 1000 0111 00bb bbbb bbbb +void xa_cpu::orl_c_notbit(u16 bit) { fatalerror( "ORL C, /%s", get_bittext(bit) ); } + +// LEA Rd, Rs+offset8 Load 16-bit effective address w/ 8-bit offs to reg 3 3 0100 0000 0ddd 0sss oooo oooo +void xa_cpu::lea_word_rd_rs_off8(u8 rd, u8 rs, u8 offs8) { fatalerror("LEA %s, %s+#$%02x", m_regnames16[rd], m_regnames16[rs], offs8); } + +// 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 +void xa_cpu::lea_word_rd_rs_off16(u8 rd, u8 rs, u16 offs16) { fatalerror( "LEA %s, %s+#$%04x", m_regnames16[rd], m_regnames16[rs], offs16); } + +// XCH Rd, [Rs] Exchange contents of a reg-ind address w/ a reg 2 6 0101 S000 dddd 0sss +void xa_cpu::xch_word_rd_indrs(u8 rd, u8 rs) { fatalerror("XCH.w %s, [%s]", m_regnames16[rd], m_regnames16[rs]); } +void xa_cpu::xch_byte_rd_indrs(u8 rd, u8 rs) { fatalerror("XCH.b %s, [%s]", m_regnames8[rd], m_regnames16[rs]); } + +// XCH Rd, Rs Exchange contents of two regs 2 5 0110 S000 dddd ssss +void xa_cpu::xch_word_rd_rs(u8 rd, u8 rs) { u16 rdval = gr16(rd); u16 rsval = gr16(rs); sr16(rd, rsval); sr16(rs, rdval); cy(5); } +void xa_cpu::xch_byte_rd_rs(u8 rd, u8 rs) { fatalerror("XCH.b %s, %s", m_regnames8[rd], m_regnames8[rs]); } + +// MOVC Rd, [Rs+] Move data from WS:Rs address of code mem to reg w/ autoinc 2 4 1000 S000 dddd 0sss +void xa_cpu::movc_word_rd_indrsinc(u8 rd, u8 rs) { u16 address = get_addr(rs); u16 data = m_program->read_word(address); address+=2; set_addr(rs, address); do_nz_flags_16(data); sr16(rd, data); cy(4); } +void xa_cpu::movc_byte_rd_indrsinc(u8 rd, u8 rs) { u16 address = get_addr(rs); u8 data = m_program->read_byte(address); address++; set_addr(rs, address); do_nz_flags_8(data); sr8(rd, data); cy(4); } + +// DJNZ Rd,rel8 Decrement reg and jump if not zero 3 8t/5nt 1000 S111 dddd 1000 rrrr rrrr +void xa_cpu::djnz_word_rd_rel8(u8 rd, u8 rel8) { u16 regval = gr16(rd); regval--; do_nz_flags_16(regval); sr16(rd, regval); if (get_z_flag() == 0) { set_pc_in_current_page(expand_rel8(rel8)); cy(8); } else { cy(5); } } +void xa_cpu::djnz_byte_rd_rel8(u8 rd, u8 rel8) { fatalerror("DJNZ.b %s, $%04x", m_regnames8[rd], expand_rel8(rel8)); } + +// POPU direct Pop the mem content (b/w) from the user stack 3 5 1000 S111 0000 0DDD DDDD DDDD +void xa_cpu::popu_word_direct(u16 direct) { fatalerror("POPU.w %s", get_directtext(direct)); } +void xa_cpu::popu_byte_direct(u16 direct) { fatalerror("POPU.b %s", get_directtext(direct)); } +// POP direct Pop the mem content (b/w) from the current stack 3 5 1000 S111 0001 0DDD DDDD DDDD +void xa_cpu::pop_word_direct(u16 direct) { fatalerror("POP.w %s", get_directtext(direct)); } +void xa_cpu::pop_byte_direct(u16 direct) { fatalerror("POP.b %s", get_directtext(direct)); } +// PUSHU direct Push the mem content (b/w) onto the user stack 3 5 1000 S111 0010 0DDD DDDD DDDD +void xa_cpu::pushu_word_direct(u16 direct) { fatalerror("PUSHU.w %s", get_directtext(direct)); } +void xa_cpu::pushu_byte_direct(u16 direct) { fatalerror("PUSHU.b %s", get_directtext(direct)); } +// PUSH direct Push the mem content (b/w) onto the current stack 3 5 1000 S111 0011 0DDD DDDD DDDD +void xa_cpu::push_word_direct(u16 direct) { fatalerror("PUSH.w %s", get_directtext(direct)); } +void xa_cpu::push_byte_direct(u16 direct) { fatalerror("PUSH.b %s", get_directtext(direct)); } + +// MOV [Rd+], [Rs+] Move reg-ind to reg-ind, both pointers autoinc 2 6 1001 S000 0ddd 0sss +void xa_cpu::mov_word_indrdinc_indrsinc(u8 rd, u8 rs) { fatalerror("MOV.w [%s+], [%s+]", m_regnames16[rd], m_regnames16[rs]); } +void xa_cpu::mov_byte_indrdinc_indrsinc(u8 rd, u8 rs) { fatalerror("MOV.b [%s+], [%s+]", m_regnames16[rd], m_regnames16[rs]); } + +// DA Rd Decimal Adjust byte reg 2 4 1001 0000 dddd 1000 +void xa_cpu::da_rd(u8 rd) { fatalerror( "DA %s", m_regnames8[rd]); } +// SEXT Rd Sign extend last operation to reg 2 3 1001 S000 dddd 1001 +void xa_cpu::sext_word_rd(u8 rd) { if(m_nflag) sr16(rd, 0xffff); else sr16(rd, 0); cy(2); } +void xa_cpu::sext_byte_rd(u8 rd) { if(m_nflag) sr8(rd, 0xff); else sr8(rd, 0); cy(2); } +// CPL Rd Complement (ones complement) reg 2 3 1001 S000 dddd 1010 +void xa_cpu::cpl_word_rd(u8 rd) { u16 rdval = gr16(rd); u16 result = rdval ^ 0xffff; do_nz_flags_16(result); sr16(rd, result); cy(3); } +void xa_cpu::cpl_byte_rd(u8 rd) { fatalerror("CPL.b %s", m_regnames8[rd]); } +// NEG Rd Negate (twos complement) reg 2 3 1001 S000 dddd 1011 +void xa_cpu::neg_word_rd(u8 rd) { fatalerror("NEG.w %sx", m_regnames16[rd]); } +void xa_cpu::neg_byte_rd(u8 rd) { fatalerror("NEG.b %sx", m_regnames8[rd]); } +// MOVC A, [A+PC] Move data from code mem to the accumulator ind w/ PC 2 6 1001 0000 0100 1100 +void xa_cpu::movc_a_apc() { fatalerror( "MOVC A, [A+PC]"); } +// MOVC A, [A+DPTR] Move data from code mem to the accumulator ind w/ DPTR 2 6 1001 0000 0100 1110 +void xa_cpu::movc_a_adptr() { fatalerror( "MOVC A, [A+DPTR]"); } +// MOV Rd, USP Move User Stack Pointer to reg (system mode only) 2 3 1001 0000 dddd 1111 +void xa_cpu::mov_rd_usp(u8 rd) { fatalerror( "MOV %s, USP", m_regnames16[rd]); } +// MOV USP, Rs Move reg to User Stack Pointer (system mode only) 2 3 1001 1000 ssss 1111 +void xa_cpu::mov_usp_rs(u8 rs) { fatalerror( "MOV USP, %s", m_regnames16[rs]); } + +//JB bit,rel8 Jump if bit set 4 10t/6nt 1001 0111 1000 00bb bbbb bbbb rrrr rrrr +void xa_cpu::jb_bit_rel8(u16 bit, u8 rel8) { fatalerror( "JB %s, $%02x", get_bittext(bit), expand_rel8(rel8) ); } +//JNB bit,rel8 Jump if bit not set 4 10t/6nt 1001 0111 1010 00bb bbbb bbbb rrrr rrrr +void xa_cpu::jnb_bit_rel8(u16 bit, u8 rel8) { fatalerror( "JNB %s, $%02x", get_bittext(bit), expand_rel8(rel8) ); } +//JBC bit,rel8 Jump if bit set and then clear the bit 4 11t/7nt 1001 0111 1100 00bb bbbb bbbb rrrr rrrr +void xa_cpu::jbc_bit_rel8(u16 bit, u8 rel8) { fatalerror( "JBC %s, $%02x", get_bittext(bit), expand_rel8(rel8) ); } + +// MOV direct, direct Move mem to mem 4 4 1001 S111 0DDD 0ddd DDDD DDDD dddd dddd +void xa_cpu::mov_word_direct_direct(u16 direct_d, u16 direct_s) { fatalerror("MOV.w %s, %s", get_directtext(direct_d), get_directtext(direct_s)); } +void xa_cpu::mov_byte_direct_direct(u16 direct_d, u16 direct_s) { u8 val = read_direct8(direct_s); do_nz_flags_8(val); write_direct8(direct_d, val); cy(4); } + +// XCH Rd, direct Exchange contents of mem w/ a reg 3 6 1010 S000 dddd 1DDD DDDD DDDD +void xa_cpu::xch_word_rd_direct(u8 rd, u16 direct) { fatalerror("XCH.w %s, %s", m_regnames16[rd], get_directtext(direct)); } +void xa_cpu::xch_byte_rd_direct(u8 rd, u16 direct) { fatalerror("XCH.b %s, %s", m_regnames8[rd], get_directtext(direct)); } + +// MOV direct, [Rs] Move reg-ind to mem 3 4 1010 S000 1sss 0DDD DDDD DDDD +void xa_cpu::mov_word_direct_indrs(u16 direct, u8 rs) { fatalerror("MOV.w %s, [%s]", get_directtext(direct), m_regnames16[rs]); } +void xa_cpu::mov_byte_direct_indrs(u16 direct, u8 rs) { fatalerror("MOV.b %s, [%s]", get_directtext(direct), m_regnames16[rs]); } + +// MOV [Rd], direct Move mem to reg-ind 3 4 1010 S000 0ddd 0DDD DDDD DDDD +void xa_cpu::mov_word_indrd_direct(u8 rd, u16 direct) { fatalerror("MOV.w [%s], %s", m_regnames16[rd], get_directtext(direct)); } +void xa_cpu::mov_byte_indrd_direct(u8 rd, u16 direct) { fatalerror("MOV.b [%s], %s", m_regnames16[rd], get_directtext(direct)); } + +// MOVX [Rd], Rs Move external data from reg to mem 2 6 1010 S111 ssss 1ddd +void xa_cpu::movx_word_indrd_rs(u8 rd, u8 rs) { fatalerror("MOVX.w [%s], %s", m_regnames16[rd], m_regnames16[rs]); } +void xa_cpu::movx_byte_indrd_rs(u8 rd, u8 rs) { fatalerror("MOVX.b [%s], %s", m_regnames16[rd], m_regnames8[rs]); } + +// MOVX Rd, [Rs] Move external data from mem to reg 2 6 1010 S111 dddd 0sss +void xa_cpu::movx_word_rd_indrs(u8 rd, u8 rs) { fatalerror("MOVX.w %s, [%s]", m_regnames16[rd], m_regnames16[rs]); } +void xa_cpu::movx_byte_rd_indrs(u8 rd, u8 rs) { fatalerror("MOVX.b %s, [%s]", m_regnames8[rd], m_regnames16[rs]); } + +// RR Rd, #data4 Rotate right reg by the 4-bit imm value 2 a* 1011 S000 dddd iiii +void xa_cpu::rr_word_rd_data4(u8 rd, u8 data4) { fatalerror("RR.w %s, %d", m_regnames16[rd], data4); } +void xa_cpu::rr_byte_rd_data4(u8 rd, u8 data4) { fatalerror("RR.b %s, %d", m_regnames8[rd], data4); } + +// RRC Rd, #data4 Rotate right reg though carry by the 4-bit imm value 2 a* 1011 S111 dddd iiii +void xa_cpu::rrc_word_rd_data4(u8 rd, u8 data4) { fatalerror("RRC.w %s, %d", m_regnames16[rd], data4); } +void xa_cpu::rrc_byte_rd_data4(u8 rd, u8 data4) { fatalerror("RRC.b %s, %d", m_regnames8[rd], data4); } + +// RL Rd, #data4 Rotate left reg by the 4-bit imm value 2 a* 1101 S011 dddd iiii +void xa_cpu::rl_word_rd_data4(u8 rd, u8 data4) { fatalerror("RL.w %d, %d", m_regnames16[rd], data4); } +void xa_cpu::rl_byte_rd_data4(u8 rd, u8 data4) { fatalerror("RL.b %d, %d", m_regnames8[rd], data4); } + +// RLC Rd, #data4 Rotate left reg though carry by the 4-bit imm value 2 a* 1101 S111 dddd iiii +void xa_cpu::rlc_word_rd_data4(u8 rd, u8 data4) { fatalerror( "RLC.w Rd, %d", m_regnames16[rd], data4); } +void xa_cpu::rlc_byte_rd_data4(u8 rd, u8 data4) { fatalerror( "RLC.b Rd, %d", m_regnames8[rd], data4); } + +// FCALL addr24 Far call (full 24-bit address space) 4 12/8(PZ) 1100 0100 aaaa aaaa AAAA AAAA AAAA AAAA +void xa_cpu::fcall_addr24(u32 addr24) { fatalerror("FCALL $%06x", addr24); } + +// CALL [Rs] Subroutine call ind w/ a reg 2 8/5(PZ) 1100 0110 0000 0sss +void xa_cpu::call_indrs(u8 rs) { fatalerror("CALL [%s]", m_regnames16[rs]); } + +// FJMP addr24 Far jump (full 24-bit address space) 4 6 1101 0100 aaaa aaaa AAAA AAAA AAAA AAAA +void xa_cpu::fjmp_addr24(u32 addr24) { fatalerror( "FJMP $%06x", addr24); } + +// JMP rel16 Long unconditional branch 3 6 1101 0101 rrrr rrrr rrrr rrrr +void xa_cpu::jmp_rel16(u16 rel16) { m_pc = expand_rel16(rel16); cy(6); } + +// DJNZ direct,rel8 Decrement mem and jump if not zero 4 9t/5nt 1110 S010 0000 1DDD DDDD DDDD rrrr rrrr +void xa_cpu::djnz_word_direct_rel8(u16 direct, u8 rel8) { fatalerror("DJNZ.w %s, $%04x", get_directtext(direct), expand_rel8(rel8)); } +void xa_cpu::djnz_byte_direct_rel8(u16 direct, u8 rel8) { fatalerror("DJNZ.b %s, $%04x", get_directtext(direct), expand_rel8(rel8)); } + +// 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 +void xa_cpu::cjne_word_rd_direct_rel8(u8 rd, u16 direct, u8 rel8) { fatalerror("CJNE.w %s, %s, $%04x", m_regnames16[rd], get_directtext(direct), expand_rel8(rel8)); } +void xa_cpu::cjne_byte_rd_direct_rel8(u8 rd, u16 direct, u8 rel8) { fatalerror("CJNE.b %s, %s, $%04x", m_regnames8[rd], get_directtext(direct), expand_rel8(rel8)); } + +// 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 +void xa_cpu::cjne_indrd_data8_rel8(u8 rd, u8 data8, u8 rel8) { fatalerror( "CJNE [%s], #$%02x, $%04x", m_regnames16[rd], data8, expand_rel8(rel8));} + +// 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 +void xa_cpu::cjne_rd_data8_rel8(u8 rd, u8 data8, u8 rel8) { u8 regval = gr8(rd); do_cjne_8_helper(regval, data8); if (!get_z_flag()) { set_pc_in_current_page(expand_rel8(rel8)); cy(9); } else { cy(6); } } + +// 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 +void xa_cpu::cjne_indrd_data16_rel8(u8 rd, u16 data16, u8 rel8) { fatalerror( "CJNE [%s], #$%04x, $%04x", m_regnames16[rd], data16, expand_rel8(rel8));} + +// 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 +void xa_cpu::cjne_rd_data16_rel8(u8 rd, u16 data16, u8 rel8) { fatalerror( "CJNE %s, #$%04x, $%04x", m_regnames8[rd], data16, expand_rel8(rel8)); } + +// RESET Causes a hardware Reset (same as external Reset) 2 18 1101 0110 0001 0000 +void xa_cpu::reset() { fatalerror( "RESET"); } + +// TRAP #data4 Causes 1 of 16 hardware traps to be executed 2 23/19(PZ) 1101 0110 0011 tttt +void xa_cpu::trap_data4(u8 data4) { fatalerror( "TRAP %d", data4); } + +// JMP [A+DPTR] Jump ind relative to the DPTR 2 5 1101 0110 0100 0110 +void xa_cpu::jmp_ind_adptr() { fatalerror( "JMP [A+DPTR]"); } + +// JMP [[Rs+]] Jump double-ind to the address (pointer to a pointer) 2 8 1101 0110 0110 0sss +void xa_cpu::jmp_dblindrs(u8 rs) { fatalerror( "JMP [[%s+]]", m_regnames16[rs]); } + +// JMP [Rs] Jump ind to the address in the reg (64K) 2 7 1101 0110 0111 0sss +void xa_cpu::jmp_indrs(u8 rs) { fatalerror( "JMP [%s]", m_regnames16[rs]); } + +// RET Return from subroutine 2 8/6(PZ) 1101 0110 1000 0000 +void xa_cpu::ret() { + if (m_pagezeromode) + { + u16 addr = pull_word_from_stack(); + set_pc_in_current_page(addr); + cy(6); + } + else + { + cy(8); + fatalerror("RET not in pagezero mode"); + } +} + +// RETI Return from interrupt 2 10/8(PZ) 1101 0110 1001 0000 +void xa_cpu::reti() +{ + if (m_pagezeromode) + { + // probably wrong order + m_pc = pull_word_from_system_stack(); + m_PSWL = pull_word_from_system_stack(); + m_PSWH = pull_word_from_system_stack(); + sfr_PSWL_w(m_PSWL); + sfr_PSWH_w(m_PSWH); + cy(8); + m_in_interrupt = 0; + + } + else + { + fatalerror("RETI when not in page zero mode\n"); + } +} + +// JZ rel8 Jump if accumulator equals zero 2 6t/3nt 1110 1100 rrrr rrrr +void xa_cpu::jz_rel8(u8 rel8) { fatalerror( "JZ $%04x", expand_rel8(rel8)); } + +// JNZ rel8 Jump if accumulator not equal zero 2 6t/3nt 1110 1110 rrrr rrrr +void xa_cpu::jnz_rel8(u8 rel8) { fatalerror( "JNZ $%04x", expand_rel8(rel8)); } + +// PUSH Rlist Push regs (b/w) onto the current stack 2 b* 0H00 S111 LLLL LLLL +void xa_cpu::push_word_rlist(u8 bitfield, int h) { cy(2); push_word_reglist(bitfield, h, false); } +void xa_cpu::push_byte_rlist(u8 bitfield, int h) { cy(2); push_byte_reglist(bitfield, h, false); } + +// PUSHU Rlist Push regs (b/w) from the user stack 2 b* 0H01 S111 LLLL LLLL +void xa_cpu::pushu_word_rlist(u8 bitfield, int h) { fatalerror("PUSHU.w %s", get_word_reglist(bitfield)); } +void xa_cpu::pushu_byte_rlist(u8 bitfield, int h) { push_byte_reglist(bitfield, h, true); } + +// POP Rlist Pop regs (b/w) from the current stack 2 c* 0H10 S111 LLLL LLLL +void xa_cpu::pop_word_rlist(u8 bitfield, int h) { cy(2); pull_word_reglist(bitfield, h, false); } +void xa_cpu::pop_byte_rlist(u8 bitfield, int h) { cy(2); pull_byte_reglist(bitfield, h, false); } + +// POPU Rlist Pop regs (b/w) from the user stack 2 c* 0H11 S111 LLLL LLLL +void xa_cpu::popu_word_rlist(u8 bitfield, int h) { fatalerror("POPU.w %s", get_word_reglist(bitfield)); } +void xa_cpu::popu_byte_rlist(u8 bitfield, int h) { cy(2); pull_byte_reglist(bitfield, h, true); } diff --git a/src/devices/cpu/xa/xadasm.cpp b/src/devices/cpu/xa/xadasm.cpp index c8eaf2d5e91..96bb39d2350 100644 --- a/src/devices/cpu/xa/xadasm.cpp +++ b/src/devices/cpu/xa/xadasm.cpp @@ -6,54 +6,54 @@ 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 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, +&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, +&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, +&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, +&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, +&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, +&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, +&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, +&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, +&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, +&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, +&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, +&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, +&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, +&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, +&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 @@ -68,13 +68,13 @@ const xa_dasm::mem_info xa_dasm::default_names[] = { { 0x411, "TSTAT" }, { 0x418, "T2CON" }, { 0x419, "T2MOD" }, - { 0x41F, "WDCON" }, - { 0x420, "S0CON" }, - { 0x421, "S0STAT" }, + { 0x41F, "WDCON" }, + { 0x420, "S0CON" }, + { 0x421, "S0STAT" }, { 0x424, "S1CON" }, - { 0x425, "S1STAT" }, + { 0x425, "S1STAT" }, { 0x426, "IEL" }, - { 0x427, "IEH" }, + { 0x427, "IEH" }, { 0x42A, "SWR" }, { 0x430, "P0" }, { 0x431, "P1" }, @@ -105,22 +105,22 @@ const xa_dasm::mem_info xa_dasm::default_names[] = { { 0x462, "S0ADEN" }, { 0x464, "S1BUF" }, { 0x465, "S1ADDR" }, - { 0x466, "S1ADEN" }, + { 0x466, "S1ADEN" }, { 0x468, "BTRL" }, { 0x469, "BTRH" }, { 0x46A, "BCR" }, { 0x470, "P0CFGA" }, { 0x471, "P1CFGA" }, { 0x472, "P2CFGA" }, - { 0x473, "P3CFGA" }, + { 0x473, "P3CFGA" }, { 0x47A, "SWE" }, { 0x4A0, "IPA0" }, { 0x4A1, "IPA1" }, - { 0x4A2, "IPA2" }, + { 0x4A2, "IPA2" }, { 0x4A3, "IPA3" }, { 0x4A4, "IPA4" }, - { 0x4A5, "IPA5" }, - { 0x4F0, "P0CFGB" }, + { 0x4A5, "IPA5" }, + { 0x4F0, "P0CFGB" }, { 0x4F1, "P1CFGB" }, { 0x4F2, "P2CFGB" }, { 0x4F3, "P3CFGB" }, @@ -183,10 +183,10 @@ int xa_dasm::d_illegal(XA_DASM_PARAMS) int xa_dasm::handle_shift(XA_DASM_PARAMS, int shift_type) { - int size = op & 0x0c; + int size = (op & 0x0c) >> 2; const u8 op2 = opcodes.r8(pc++); u8 data, rd; - if (size == 0x0c) + if (size == 0x03) { data = op2 & 0x1f; rd = (op2 & 0xe0) >> 4; @@ -199,11 +199,11 @@ int xa_dasm::handle_shift(XA_DASM_PARAMS, int shift_type) if (size == 0x00) { - util::stream_format(stream, "%s%s %s, %d", m_shifts[shift_type], m_dwparamsizes[size >> 2], m_regnames8[rd], data); + util::stream_format(stream, "%s%s %s, %d", m_shifts[shift_type], m_dwparamsizes[size], 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); + util::stream_format(stream, "%s%s %s, %d", m_shifts[shift_type], m_dwparamsizes[size], m_regnames16[rd], data); } return 2; @@ -327,7 +327,7 @@ int xa_dasm::handle_alu_type0(XA_DASM_PARAMS, int alu_op) -int xa_dasm::handle_alu_type1(XA_DASM_PARAMS, uint8_t op2) +int xa_dasm::handle_alu_type1(XA_DASM_PARAMS, u8 op2) { int alu_op = op2 & 0x0f; switch (op & 0x0f) @@ -563,7 +563,7 @@ int xa_dasm::handle_pushpop_rlist(XA_DASM_PARAMS, int type) if (bit) { - util::stream_format(stream, "%s%s", firstbit ? "" : ",", m_regnames8[i + h ? 8 : 0]); + util::stream_format(stream, "%s%s", firstbit ? "" : ",", m_regnames8[i + (h ? 8 : 0)]); firstbit = false; } } @@ -605,15 +605,15 @@ int xa_dasm::d_bitgroup(XA_DASM_PARAMS) switch (op2 & 0xf0) { - case 0x00: util::stream_format(stream, "CLR %s", get_bittext(bit) ); break; + 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 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; + default: util::stream_format(stream, "illegal bit op %s", get_bittext(bit) ); break; } return 3; } @@ -793,7 +793,7 @@ int xa_dasm::d_xch_type1(XA_DASM_PARAMS) 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]); + util::stream_format(stream, "XCH%s %s, [%s]", size ? ".w" : ".b", regnames[rd], m_regnames16[rs]); return 2; } @@ -809,7 +809,7 @@ AND Rd, [Rs+] Logical AND reg-ind w/ autoinc to reg 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); @@ -828,7 +828,7 @@ int xa_dasm::d_xch_type2(XA_DASM_PARAMS) const u8 rd = (op2 & 0xf0) >> 4; const u8 rs = (op2 & 0x0f); - util::stream_format(stream, "XCH %s, %s", regnames[rd], regnames[rs]); + util::stream_format(stream, "XCH%s %s, %s", size ? ".w" : ".b", regnames[rd], regnames[rs]); return 2; } @@ -1029,12 +1029,12 @@ int xa_dasm::d_g9_subgroup(XA_DASM_PARAMS) if (!size) { int rd = (op2 & 0xf0) >> 4; - util::stream_format(stream, "MOV %s, USP", m_regnames16[rd]); + 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]); + util::stream_format(stream, "MOV USP, %s", m_regnames16[rs]); } return 2; } @@ -1204,7 +1204,9 @@ int xa_dasm::d_jb_mov_subgroup(XA_DASM_PARAMS) { 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)); + int size = op & 0x08; + + util::stream_format(stream, "MOV%s %s, %s", size ? ".w" : ".b", get_directtext(direct_dst), get_directtext(direct_src)); } return 4; @@ -1244,7 +1246,7 @@ int xa_dasm::d_movdir(XA_DASM_PARAMS) { 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; } } @@ -1293,7 +1295,7 @@ int xa_dasm::d_movx_subgroup(XA_DASM_PARAMS) /* 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++); @@ -1374,8 +1376,8 @@ CALL rel16 Relative call (range +/- 64K) */ int xa_dasm::d_asl_c(XA_DASM_PARAMS) { - int size = op & 0x0c; - if (size == 0x04) + int size = (op & 0x0c) >> 2; + if (size == 0x01) { const u8 op2 = opcodes.r8(pc++); const u8 op3 = opcodes.r8(pc++); @@ -1391,7 +1393,7 @@ int xa_dasm::d_asl_c(XA_DASM_PARAMS) 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) + util::stream_format(stream, "ASL%s %s, %s", m_dwparamsizes[size], regnames[rd], m_regnames8[rs]); // m_regnames8 or regnames for last param? (check 03D4 in superkds) return 2; } return 1; @@ -1400,11 +1402,11 @@ int xa_dasm::d_asl_c(XA_DASM_PARAMS) /* 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) + int size = (op & 0x0c) >> 2; + if (size == 0x01) { const u8 op2 = opcodes.r8(pc++); const u8 rs = op2 & 0x07; @@ -1417,7 +1419,7 @@ int xa_dasm::d_asr_c(XA_DASM_PARAMS) 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? + util::stream_format(stream, "ASR%s %s, %s", m_dwparamsizes[size], regnames[rd], m_regnames8[rs]); // m_regnames8 or regnames for last param? return 2; } return 1; @@ -1428,8 +1430,8 @@ NORM Rd, Rs Logical shift left dest reg by the value in the src */ int xa_dasm::d_norm(XA_DASM_PARAMS) { - int size = op & 0x0c; - if (size == 0x04) + int size = (op & 0x0c) >> 2; + if (size == 0x01) { const u8 op2 = opcodes.r8(pc++); util::stream_format(stream, "illegal %02x", op2); @@ -1441,8 +1443,7 @@ int xa_dasm::d_norm(XA_DASM_PARAMS) 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? + util::stream_format(stream, "NORM%s %s, %s", m_dwparamsizes[size], regnames[rd], m_regnames8[rs]); // m_regnames8 or regnames for last param? return 2; } return 2; @@ -1457,8 +1458,8 @@ FJMP addr24 Far jump (full 24-bit address space) */ int xa_dasm::d_lsr_fj(XA_DASM_PARAMS) { - int size = op & 0x0c; - if (size == 0x04) + int size = (op & 0x0c) >> 2; + if (size == 0x01) { const u8 op2 = opcodes.r8(pc++); const u8 op3 = opcodes.r8(pc++); @@ -1574,17 +1575,20 @@ 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 size = op & 0x08; + 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); + util::stream_format(stream, "DJNZ%s %s, $%04x", size ? ".w" : ".b", 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); + const char** regnames = size ? m_regnames16 : m_regnames8; + util::stream_format(stream, "CJNE%s %s, %s, $%04x", size ? ".w" : ".b", regnames[rd], get_directtext(direct), address); } return 4; } @@ -1662,10 +1666,10 @@ int xa_dasm::d_div_w(XA_DASM_PARAMS) } /* -DIV.w Rd, #data8 16x8 signed divide reg w/ imm word 3 14 1110 1000 dddd 1011 iiii iiii +MULU.b Rd, #data8 8X8 unsigned multiply of 8-bit imm data w/ reg 3 12 1110 1000 dddd 0000 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 +DIV.w Rd, #data8 16x8 signed divide reg w/ imm word 3 14 1110 1000 dddd 1011 iiii iiii */ int xa_dasm::d_div_data8(XA_DASM_PARAMS) { @@ -1706,8 +1710,8 @@ int xa_dasm::d_div_data8(XA_DASM_PARAMS) /* 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 +MUL.w Rd, #data16 16X16 signed multiply 16-bit imm data w/ reg 4 12 1110 1001 dddd 1000 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) @@ -1790,12 +1794,12 @@ int xa_dasm::d_cjne_d8(XA_DASM_PARAMS) if (op2 & 0x08) { const u8 rd = (op2 & 0x70) >> 4; - util::stream_format(stream, "CJNE [%d], #$%02x, $%04x", m_regnames16[rd], op4, address); + util::stream_format(stream, "CJNE [%s], #$%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); + util::stream_format(stream, "CJNE %s, #$%02x, $%04x", m_regnames8[rd], op4, address); } return 4; } diff --git a/src/devices/cpu/xa/xadasm.h b/src/devices/cpu/xa/xadasm.h index a2c211e10f5..7cb8380c086 100644 --- a/src/devices/cpu/xa/xadasm.h +++ b/src/devices/cpu/xa/xadasm.h @@ -6,7 +6,7 @@ #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_DASM_PARAMS u8 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 @@ -39,7 +39,7 @@ private: 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_aluops[16] = { "ADD", "ADDC", "SUB", "SUBB", "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" }; @@ -51,7 +51,7 @@ private: 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_alu_type1(XA_DASM_PARAMS, u8 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); diff --git a/src/devices/sound/ics2115.cpp b/src/devices/sound/ics2115.cpp index f38b31e6c86..2e93ab5b1da 100644 --- a/src/devices/sound/ics2115.cpp +++ b/src/devices/sound/ics2115.cpp @@ -533,6 +533,14 @@ u16 ics2115_device::reg_read() { case 0x00: // [osc] Oscillator Configuration ret = voice.osc_conf.value; + if (voice.state.on) + { + ret |= 8; + } + else + { + ret &= ~8; + } ret <<= 8; break; @@ -1078,7 +1086,7 @@ void ics2115_device::recalc_irq() //Suspect bool irq = (m_irq_pending & m_irq_enabled); for (int i = 0; (!irq) && (i < 32); i++) - irq |= m_voice[i].vol_ctrl.bitflags.irq_pending && m_voice[i].osc_conf.bitflags.irq_pending; + irq |= m_voice[i].vol_ctrl.bitflags.irq_pending || m_voice[i].osc_conf.bitflags.irq_pending; m_irq_on = irq; m_irq_cb(irq ? ASSERT_LINE : CLEAR_LINE); } diff --git a/src/mame/igs/igs_fear.cpp b/src/mame/igs/igs_fear.cpp index 9b9abc8c4b8..b5012567715 100644 --- a/src/mame/igs/igs_fear.cpp +++ b/src/mame/igs/igs_fear.cpp @@ -17,6 +17,9 @@ #include "screen.h" #include "speaker.h" +#define LOG_DEBUG (1U << 1) +#define VERBOSE (0) +#include "logmacro.h" namespace { @@ -27,6 +30,8 @@ public: driver_device(mconfig, type, tag), m_maincpu(*this, "maincpu"), m_xa(*this, "xa"), + m_ics(*this, "ics"), + m_screen(*this, "screen"), m_videoram(*this, "videoram"), m_palette(*this, "palette"), m_gfxrom(*this, "gfx1"), @@ -44,6 +49,9 @@ public: protected: virtual void video_start() override; + virtual void machine_start() override; + virtual void machine_reset() override; + private: void main_map(address_map &map); @@ -54,7 +62,7 @@ private: u32 screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); - u32 igs027_gpio_r(offs_t offset); + u32 igs027_gpio_r(offs_t offset, u32 mem_mask); void igs027_gpio_w(offs_t offset, u32 data, u32 mem_mask); TIMER_CALLBACK_MEMBER(igs027_timer0); @@ -62,26 +70,52 @@ private: void igs027_periph_init(void); void igs027_trigger_irq(int num); - u32 igs027_periph_r(offs_t offset); + u32 igs027_periph_r(offs_t offset, u32 mem_mask); void igs027_periph_w(offs_t offset, u32 data, u32 mem_mask); - u32 xa_r(offs_t offset); + u32 xa_r(offs_t offset, u32 mem_mask); void xa_w(offs_t offset, u32 data, u32 mem_mask); void cpld_w(offs_t offset, u32 data, u32 mem_mask); + u8 mcu_p0_r(); + u8 mcu_p1_r(); + u8 mcu_p2_r(); + u8 mcu_p3_r(); + void mcu_p0_w(uint8_t data); + void mcu_p1_w(uint8_t data); + void mcu_p2_w(uint8_t data); + void mcu_p3_w(uint8_t data); + + u16 xa_wait_r(offs_t offset); + + u8 m_port2_latch; + u8 m_port0_latch; + u32 m_gpio_o; u32 m_irq_enable; u32 m_irq_pending; - emu_timer *m_timer0; - emu_timer *m_timer1; u32 m_xa_cmd; + u32 m_xa_ret0; + u32 m_xa_ret1; + u8 m_num_params; + + u8 m_port0_dat; + u8 m_port1_dat; + u8 m_port2_dat; + u8 m_port3_dat; + int m_trackball_cnt; int m_trackball_axis[2], m_trackball_axis_pre[2], m_trackball_axis_diff[2]; + emu_timer *m_timer0; + emu_timer *m_timer1; + // devices required_device m_maincpu; - required_device m_xa; + required_device m_xa; + required_device m_ics; + required_device m_screen; required_shared_ptr m_videoram; required_device m_palette; required_region_ptr m_gfxrom; @@ -97,11 +131,52 @@ void igs_fear_state::video_start() igs027_periph_init(); } +void igs_fear_state::machine_start() +{ + save_item(NAME(m_port2_latch)); + save_item(NAME(m_port0_latch)); + + save_item(NAME(m_gpio_o)); + save_item(NAME(m_irq_enable)); + save_item(NAME(m_irq_pending)); + + save_item(NAME(m_xa_cmd)); + save_item(NAME(m_xa_ret0)); + save_item(NAME(m_xa_ret1)); + save_item(NAME(m_num_params)); + + save_item(NAME(m_port0_dat)); + save_item(NAME(m_port1_dat)); + save_item(NAME(m_port2_dat)); + save_item(NAME(m_port3_dat)); +} + +void igs_fear_state::machine_reset() +{ + m_port2_latch = 0; + m_port0_latch = 0; + + m_gpio_o = 0; + m_irq_enable = 0; + m_irq_pending = 0; + + m_xa_cmd = 0; + m_xa_ret0 = 0; + m_xa_ret1 = 0; + m_num_params = 0; + + m_port0_dat = 0; + m_port1_dat = 0; + m_port2_dat = 0; + m_port3_dat = 0; + +} + void igs_fear_state::draw_sprite(bitmap_ind16 &bitmap, const rectangle &cliprect, int xpos, int ypos, int height, int width, int palette, int flipx, int romoffset) { if ((romoffset != 0) && (romoffset != 0xffffffff)) { - //logerror("x=%d, y=%d, w=%d pix, h=%d pix, c=0x%02x, romoffset=0x%08x\n", xpos, ypos, width, height, palette, romoffset << 2); + //LOGMASKED(LOG_DEBUG, "x=%d, y=%d, w=%d pix, h=%d pix, c=0x%02x, romoffset=0x%08x\n", xpos, ypos, width, height, palette, romoffset << 2); const u8 *gfxrom = &m_gfxrom[romoffset << 2]; const int x_base = flipx ? (xpos + width - 1) : xpos; const int x_inc = flipx ? (-1) : 1; @@ -235,11 +310,11 @@ INPUT_PORTS_START( superkds ) PORT_INCLUDE ( fear ) PORT_MODIFY("DSW1") - PORT_DIPNAME( 0x03, 0x00, "Scene" ) PORT_DIPLOCATION("SW1:1,2") + PORT_DIPNAME( 0x03, 0x01, "Scene" ) PORT_DIPLOCATION("SW1:1,2") PORT_DIPSETTING( 0x03, "Volcano" ) PORT_DIPSETTING( 0x02, "Jungle" ) PORT_DIPSETTING( 0x01, "Ice Field" ) - PORT_DIPSETTING( 0x00, "Ice Field" ) + PORT_DIPSETTING( 0x00, "Ice Field (duplicate)" ) PORT_DIPNAME( 0x04, 0x00, "Ticket" ) PORT_DIPLOCATION("SW1:3") PORT_DIPSETTING( 0x04, DEF_STR( On ) ) PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) @@ -278,7 +353,7 @@ INPUT_PORTS_START( superkds ) PORT_DIPSETTING( 0x00, "Table32" ) PORT_MODIFY("DSW2") - PORT_DIPNAME( 0x01, 0x00, "Free Play" ) PORT_DIPLOCATION("SW2:1") + PORT_DIPNAME( 0x01, 0x01, "Free Play" ) PORT_DIPLOCATION("SW2:1") PORT_DIPSETTING( 0x01, DEF_STR( Off ) ) PORT_DIPSETTING( 0x00, DEF_STR( On ) ) PORT_DIPNAME( 0x06, 0x06, "Coin/Credit" ) PORT_DIPLOCATION("SW2:2,3") @@ -305,15 +380,19 @@ INPUT_PORTS_END void igs_fear_state::sound_irq(int state) { + LOGMASKED(LOG_DEBUG, "sound irq\n"); + if (state) + m_xa->set_input_line(XA_EXT_IRQ2, ASSERT_LINE); } void igs_fear_state::vblank_irq(int state) { if (state) - m_maincpu->pulse_input_line(ARM7_FIRQ_LINE, m_maincpu->minimum_quantum_time()); + if (m_screen->frame_number() & 1) + m_maincpu->pulse_input_line(ARM7_FIRQ_LINE, m_maincpu->minimum_quantum_time()); } -u32 igs_fear_state::igs027_gpio_r(offs_t offset) +u32 igs_fear_state::igs027_gpio_r(offs_t offset, u32 mem_mask) { u32 data = ~u32(0); switch (offset * 4) @@ -326,7 +405,12 @@ u32 igs_fear_state::igs027_gpio_r(offs_t offset) data = 0x2000 | (u32(ret) << 3); } break; + + default: + LOGMASKED(LOG_DEBUG, "%s: unhandled igs027_gpio_r %04x (%08x)\n", machine().describe_context(), offset * 4, mem_mask); + break; } + return data; } @@ -337,6 +421,10 @@ void igs_fear_state::igs027_gpio_w(offs_t offset, u32 data, u32 mem_mask) case 0x18: m_gpio_o = data; break; + + default: + LOGMASKED(LOG_DEBUG, "%s: unhandled igs027_gpio_w %04x %08x (%08x)\n", machine().describe_context(), offset * 4, data, mem_mask); + break; } } @@ -373,20 +461,24 @@ void igs_fear_state::igs027_periph_w(offs_t offset, u32 data, u32 mem_mask) { case 0x100: // TODO: verify the timer interval - m_timer0->adjust(attotime::from_hz(data), 0, attotime::from_hz(data)); + m_timer0->adjust(attotime::from_hz(data / 2), 0, attotime::from_hz(data / 2)); break; case 0x104: - m_timer1->adjust(attotime::from_hz(data), 0, attotime::from_hz(data)); + m_timer1->adjust(attotime::from_hz(data / 2), 0, attotime::from_hz(data / 2)); break; case 0x200: m_irq_enable = data; break; + + default: + LOGMASKED(LOG_DEBUG, "%s: unhandled igs027_periph_w %04x %08x (%08x)\n", machine().describe_context(), offset * 4, data, mem_mask); + break; } } -u32 igs_fear_state::igs027_periph_r(offs_t offset) +u32 igs_fear_state::igs027_periph_r(offs_t offset, u32 mem_mask) { u32 data = ~u32(0); switch (offset * 4) @@ -395,12 +487,17 @@ u32 igs_fear_state::igs027_periph_r(offs_t offset) data = m_irq_pending; m_irq_pending = 0xff; break; + + default: + LOGMASKED(LOG_DEBUG, "%s: unhandled igs027_periph_r %04x (%08x)\n", machine().describe_context(), offset * 4, mem_mask); + break; + } return data; } -// TODO: ICS2115 & trackball support in XA -u32 igs_fear_state::xa_r(offs_t offset) +// TODO: trackball support in XA +u32 igs_fear_state::xa_r(offs_t offset, u32 mem_mask) { u32 data = ~u32(0); @@ -408,6 +505,8 @@ u32 igs_fear_state::xa_r(offs_t offset) { case 0: { + data = m_xa_ret0; + // TODO: This should be remove when we implement serial trackball support in XA if (m_xa_cmd == 0xa301) { switch (m_trackball_cnt++) @@ -444,7 +543,7 @@ u32 igs_fear_state::xa_r(offs_t offset) break; } case 0x80: - data = 0; + data = m_xa_ret1 << 16; break; } return data; @@ -452,10 +551,26 @@ u32 igs_fear_state::xa_r(offs_t offset) void igs_fear_state::xa_w(offs_t offset, u32 data, u32 mem_mask) { + m_xa_cmd = data; + if (offset == 0) { - m_xa_cmd = data; - igs027_trigger_irq(3); + m_num_params--; + + if (m_num_params <= 0) + { + LOGMASKED(LOG_DEBUG, "---------------m_xa_cmd is %02x size %02x\n", (data & 0xff00)>>8, data & 0xff); + m_num_params = data & 0xff; + } + else + { + LOGMASKED(LOG_DEBUG, "-------------------------- param %04x\n", data & 0xffff); + } + m_xa->set_input_line(XA_EXT_IRQ0, ASSERT_LINE); + } + else + { + LOGMASKED(LOG_DEBUG, "%s: unhandled xa_w %04x %08x (%08x)\n", machine().describe_context(), offset * 4, data, mem_mask); } } @@ -466,6 +581,116 @@ void igs_fear_state::cpld_w(offs_t offset, u32 data, u32 mem_mask) case 0x8: m_ticket->motor_w(BIT(data, 7)); break; + + default: + LOGMASKED(LOG_DEBUG, "%s: unhandled cpld_w %04x %08x (%08x)\n", machine().describe_context(), offset * 4, data, mem_mask); + break; + } +} + +u8 igs_fear_state::mcu_p0_r() +{ + u8 ret = m_port0_latch; + LOGMASKED(LOG_DEBUG, "%s: COMMAND READ LOWER mcu_p0_r() returning %02x with port3 as %02x\n", machine().describe_context(), ret, m_port3_dat); + return ret; +} + +u8 igs_fear_state::mcu_p1_r() +{ + LOGMASKED(LOG_DEBUG, "%s: mcu_p1_r()\n", machine().describe_context()); + return m_port1_dat; // superkds XA will end up failing returning port1 dat for now, but not attempt to play any sounds otherwise? +} + +u8 igs_fear_state::mcu_p2_r() +{ + u8 ret = m_port2_latch; + LOGMASKED(LOG_DEBUG, "%s: COMMAND READ mcu_p2_r() returning %02x with port3 as %02x\n", machine().describe_context(), ret, m_port3_dat); + return m_port2_latch; +} + +u8 igs_fear_state::mcu_p3_r() +{ + LOGMASKED(LOG_DEBUG, "%s: mcu_p3_r()\n", machine().describe_context()); + return m_port3_dat; +} + +static int posedge(uint32_t oldval, uint32_t val, int bit) +{ + return (!BIT(oldval, bit)) && (BIT(val, bit)); +} + +static int negedge(uint32_t oldval, uint32_t val, int bit) +{ + return (BIT(oldval, bit)) && (!BIT(val, bit)); +} + +void igs_fear_state::mcu_p0_w(uint8_t data) +{ + LOGMASKED(LOG_DEBUG, "%s: mcu_p0_w() %02x with port 3 as %02x and port 1 as %02x\n", machine().describe_context(), data, m_port3_dat, m_port1_dat); + m_port0_dat = data; +} + +void igs_fear_state::mcu_p1_w(uint8_t data) +{ + u8 olddata = m_port1_dat; + LOGMASKED(LOG_DEBUG, "%s: mcu_p1_w() %02x\n", machine().describe_context(), data); + m_port1_dat = data; + + if (posedge(olddata, m_port1_dat, 3)) + { + igs027_trigger_irq(3); + } +} + +void igs_fear_state::mcu_p2_w(uint8_t data) +{ + m_port2_dat = data; + LOGMASKED(LOG_DEBUG, "%s: mcu_p2_w() %02x with port 3 as %02x\n", machine().describe_context(), data, m_port3_dat); +} + +void igs_fear_state::mcu_p3_w(uint8_t data) +{ + u8 oldport3 = m_port3_dat; + m_port3_dat = data; + LOGMASKED(LOG_DEBUG, "%s: mcu_p3_w() %02x - do latches oldport3 %02x newport3 %02x\n", machine().describe_context(), data, oldport3, m_port3_dat); + + // high->low transition on bit 0x80 must read into latches! + if (negedge(oldport3, m_port3_dat, 7)) + { + if (!BIT(m_port3_dat, 4)) + { + m_port0_latch = m_ics->read(m_port1_dat & 7); + LOGMASKED(LOG_DEBUG, "read from ics [%d] = [%02x]\n", m_port1_dat & 7, m_port0_latch); + } + else if (!BIT(m_port3_dat, 5)) + { + LOGMASKED(LOG_DEBUG, "read command [%d] = [%04x]\n", m_port1_dat & 7, m_xa_cmd); + m_port2_latch = (m_xa_cmd & 0xff00) >> 8; + m_port0_latch = m_xa_cmd & 0x00ff; + } + } + + if (negedge(oldport3, m_port3_dat, 6)) + { + if (!BIT(m_port3_dat, 4)) + { + LOGMASKED(LOG_DEBUG, "write to ics [%d] = [%02x]\n", m_port1_dat & 7, m_port0_dat); + m_ics->write(m_port1_dat & 7, m_port0_dat); + } + else if (!BIT(m_port3_dat, 5)) + { + uint32_t dat = (m_port2_dat << 8) | m_port0_dat; + LOGMASKED(LOG_DEBUG, "write command [%d] = [%04x]\n", m_port1_dat & 7, dat); + switch (m_port1_dat & 7) + { + case 1: + m_xa_ret1 = dat; + break; + case 2: + m_xa_ret0 = dat; + break; + } + } } } @@ -475,15 +700,25 @@ void igs_fear_state::igs_fear(machine_config &config) m_maincpu->set_addrmap(AS_PROGRAM, &igs_fear_state::main_map); MX10EXA(config, m_xa, 50000000/3); // MX10EXAQC (Philips 80C51 XA) - - screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER)); - screen.set_refresh_hz(60); - screen.set_vblank_time(ATTOSECONDS_IN_USEC(0)); - screen.set_size(640, 480); - screen.set_visarea(0, 640-1, 0, 480-1); - screen.set_screen_update(FUNC(igs_fear_state::screen_update)); - screen.screen_vblank().set(FUNC(igs_fear_state::vblank_irq)); - screen.set_palette(m_palette); + m_xa->port_in_cb<0>().set(FUNC(igs_fear_state::mcu_p0_r)); + m_xa->port_in_cb<1>().set(FUNC(igs_fear_state::mcu_p1_r)); + m_xa->port_in_cb<2>().set(FUNC(igs_fear_state::mcu_p2_r)); + m_xa->port_in_cb<3>().set(FUNC(igs_fear_state::mcu_p3_r)); + m_xa->port_out_cb<0>().set(FUNC(igs_fear_state::mcu_p0_w)); + m_xa->port_out_cb<1>().set(FUNC(igs_fear_state::mcu_p1_w)); + m_xa->port_out_cb<2>().set(FUNC(igs_fear_state::mcu_p2_w)); + m_xa->port_out_cb<3>().set(FUNC(igs_fear_state::mcu_p3_w)); + + config.set_maximum_quantum(attotime::from_hz(600)); + + SCREEN(config, m_screen, SCREEN_TYPE_RASTER); + m_screen->set_refresh_hz(60); + m_screen->set_vblank_time(ATTOSECONDS_IN_USEC(0)); + m_screen->set_size(640, 480); + m_screen->set_visarea(0, 640-1, 0, 480-1); + m_screen->set_screen_update(FUNC(igs_fear_state::screen_update)); + m_screen->screen_vblank().set(FUNC(igs_fear_state::vblank_irq)); + m_screen->set_palette(m_palette); PALETTE(config, m_palette, palette_device::BLACK).set_format(palette_device::xBGR_555, 0x4000/2); @@ -493,9 +728,10 @@ void igs_fear_state::igs_fear(machine_config &config) /* sound hardware */ SPEAKER(config, "mono").front_center(); - ics2115_device &ics(ICS2115(config, "ics", 33.8688_MHz_XTAL)); // TODO : Correct? - ics.irq().set(FUNC(igs_fear_state::sound_irq)); - ics.add_route(ALL_OUTPUTS, "mono", 5.0); + + ICS2115(config, m_ics, 33.8688_MHz_XTAL); // TODO : Correct? + m_ics->irq().set(FUNC(igs_fear_state::sound_irq)); + m_ics->add_route(ALL_OUTPUTS, "mono", 5.0); } @@ -583,6 +819,6 @@ void igs_fear_state::init_igs_icescape() } // anonymous namespace -GAME( 2005, superkds, 0, igs_fear, superkds, igs_fear_state, init_igs_superkds, ROT0, "IGS", "Super Kids (S019CN)", MACHINE_IS_SKELETON ) -GAME( 2006, fearless, 0, igs_fear, fear, igs_fear_state, init_igs_fear, ROT0, "IGS", "Fearless Pinocchio (V101US)", MACHINE_IS_SKELETON ) +GAME( 2005, superkds, 0, igs_fear, superkds, igs_fear_state, init_igs_superkds, ROT0, "IGS", "Super Kids (S019CN)", 0 ) +GAME( 2006, fearless, 0, igs_fear, fear, igs_fear_state, init_igs_fear, ROT0, "IGS", "Fearless Pinocchio (V101US)", 0 ) GAME( 2006, icescape, 0, igs_fear, fear, igs_fear_state, init_igs_icescape, ROT0, "IGS", "Icescape (V104FA)", MACHINE_IS_SKELETON ) // IGS FOR V104FA 2006-11-02 diff --git a/src/mame/igs/igs_m027.cpp b/src/mame/igs/igs_m027.cpp index 405bee82849..551685c51c1 100644 --- a/src/mame/igs/igs_m027.cpp +++ b/src/mame/igs/igs_m027.cpp @@ -85,7 +85,7 @@ protected: private: optional_shared_ptr m_igs_mainram; required_device m_maincpu; - optional_device m_xa; + optional_device m_xa; required_device m_igs017_igs031; void vblank_irq(int state); -- cgit v1.2.3