diff --git a/src/devices/cpu/olms66k/msm665xx.cpp b/src/devices/cpu/olms66k/msm665xx.cpp index 27c21cc2db2..1ac4fa02abf 100644 --- a/src/devices/cpu/olms66k/msm665xx.cpp +++ b/src/devices/cpu/olms66k/msm665xx.cpp @@ -4,8 +4,6 @@ Oki MSM665xx 16-bit microcontroller family (nX-8/500S core) - Currently this is just one stub device with no actual execution core. - ****************************************************************************/ #include "emu.h" @@ -15,6 +13,8 @@ // device type definition DEFINE_DEVICE_TYPE(MSM66573, msm66573_device, "msm66573", "Oki MSM66573") +ALLOW_SAVE_TYPE(msm665xx_device::inst_state) + msm665xx_device::msm665xx_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, address_map_constructor mem_map, address_map_constructor data_map) : cpu_device(mconfig, type, tag, owner, clock) @@ -31,6 +31,11 @@ msm665xx_device::msm665xx_device(const machine_config &mconfig, device_type type , m_tsr(0) , m_romwin(0x30) , m_memscon(0) + , m_inst(0) + , m_fetch_byte(0) + , m_adr(0) + , m_seg(0) + , m_tmp{0, 0} , m_icount(0) { } @@ -84,7 +89,8 @@ void msm665xx_device::device_start() // debug state state_add(MSM665XX_ACC, "ACC", m_acc); - state_add(MSM665XX_PC, "PC", m_pc); + state_add(MSM665XX_CSR, "CSR", m_csr).mask(0x0f); + state_add(MSM665XX_PC, "PC", m_pc, [this](u16 data) { m_pc = data; prefetch(); next_inst(); }); state_add(STATE_GENPC, "GENPC", [this]() { return u32(m_csr) << 16 | m_pc; }, [this](u32 data) { m_csr = (data >> 16) & 0x0f; m_pc = data & 0xffff; m_ppc = data & 0xfffff; } @@ -114,7 +120,6 @@ void msm665xx_device::device_start() [this, fixed, n]() { return util::little_endian_cast(fixed)[(m_lrb & 0x00ff) << 3 | n]; }, [this, fixed, n](u8 data) { util::little_endian_cast(fixed)[(m_lrb & 0x00ff) << 3 | n] = data; } ).noshow(); - state_add(MSM665XX_CSR, "CSR", m_csr).mask(0x0f); state_add(MSM665XX_DSR, "DSR", m_dsr).mask(0x0f); state_add(MSM665XX_TSR, "TSR", m_tsr).mask(0x0f); state_add(MSM665XX_ROMWIN, "ROMWIN", m_romwin); @@ -131,18 +136,402 @@ void msm665xx_device::device_start() save_item(NAME(m_dsr)); save_item(NAME(m_tsr)); save_item(NAME(m_romwin)); + save_item(NAME(m_state)); + save_item(NAME(m_inst)); + save_item(NAME(m_fetch_byte)); + save_item(NAME(m_adr)); + save_item(NAME(m_seg)); + save_item(NAME(m_tmp)); } -void msm665xx_device::device_reset() +u16 msm665xx_device::do_add(u16 n1, u16 n2, bool c) noexcept { - // PC will be initialized from vector following reset; LRB and ROMWIN are undefined at reset - m_acc = 0; - m_psw = 0; - m_ssp = 0xffff; - m_csr = 0; - m_dsr = 0; - m_tsr = 0; - m_memscon = 0; + s32 sum = s16(n1) + (s16(n2) + s32(c)); + if (u32(n1) + c > u16(~n2)) + m_psw |= 0x8000; + else + m_psw &= 0x7fff; + if ((sum & 0xffff) == 0) + m_psw |= 0x4000; + else + m_psw &= 0xbfff; + if (BIT(sum, 15)) + m_psw |= 0x0800; + else + m_psw &= 0xf7ff; + if (sum >= 0x8000 || sum < s32(-0x8000)) + m_psw |= 0x0200; + else + m_psw &= 0xfdff; + if ((n1 & 0x000f) + c > (~n2 & 0x000f)) + m_psw |= 0x2000; + else + m_psw &= 0xdfff; + return sum & 0xffff; +} + +u8 msm665xx_device::do_addb(u8 n1, u8 n2, bool c) noexcept +{ + s16 sum = s8(n1) + s16(c) + s8(n2); + if (u16(n1) + c > u8(~n2)) + m_psw |= 0x8000; + else + m_psw &= 0x7fff; + if ((sum & 0xff) == 0) + m_psw |= 0x4000; + else + m_psw &= 0xbfff; + if (BIT(sum, 7)) + m_psw |= 0x0800; + else + m_psw &= 0xf7ff; + if (sum >= 0x80 || sum < s16(-0x80)) + m_psw |= 0x0200; + else + m_psw &= 0xfdff; + if ((n1 & 0x0f) + c > (~n2 & 0x0f)) + m_psw |= 0x2000; + else + m_psw &= 0xdfff; + return sum & 0xff; +} + +u16 msm665xx_device::do_sub(u16 n1, u16 n2, bool c) noexcept +{ + s32 diff = s16(n1) - s32(c) - s16(n2); + if (n1 < n2 + u32(c)) + m_psw |= 0x8000; + else + m_psw &= 0x7fff; + if ((diff & 0xffff) == 0) + m_psw |= 0x4000; + else + m_psw &= 0xbfff; + if (BIT(diff, 15)) + m_psw |= 0x0800; + else + m_psw &= 0xf7ff; + if (diff >= 0x8000 || diff < s32(-0x8000)) + m_psw |= 0x0200; + else + m_psw &= 0xfdff; + if ((n1 & 0x000f) < (n2 & 0x000f) + c) + m_psw |= 0x2000; + else + m_psw &= 0xdfff; + return diff & 0xffff; +} + +u8 msm665xx_device::do_subb(u8 n1, u8 n2, bool c) noexcept +{ + s16 diff = s8(n1) - s16(c) - s8(n2); + if (n1 < n2 + u16(c)) + m_psw |= 0x8000; + else + m_psw &= 0x7fff; + if ((diff & 0xff) == 0) + m_psw |= 0x4000; + else + m_psw &= 0xbfff; + if (BIT(diff, 7)) + m_psw |= 0x0800; + else + m_psw &= 0xf7ff; + if (diff >= 0x80 || diff < s16(-0x80)) + m_psw |= 0x0200; + else + m_psw &= 0xfdff; + if ((n1 & 0x0f) < (n2 & 0x0f) + c) + m_psw |= 0x2000; + else + m_psw &= 0xdfff; + return diff & 0xff; +} + +u16 msm665xx_device::do_aluop_word(u16 n1, u16 n2) noexcept +{ + u16 result; + switch (BIT(m_inst, 4, 3)) + { + default: // (what even are bitfields?) + case 0: // SUB + return do_sub(n1, n2); + + case 1: // CMP + (void)do_sub(n1, n2); + return n1; + + case 2: // ADD + return do_add(n1, n2); + + case 3: // AND + result = n1 & n2; + setzs_word(result); + return result; + + case 4: // OR + result = n1 | n2; + setzs_word(result); + return result; + + case 5: // XOR + result = n1 ^ n2; + setzs_word(result); + return result; + + case 6: // ADC + return do_add(n1, n2, BIT(m_psw, 15)); + + case 7: // SBC + return do_sub(n1, n2, BIT(m_psw, 15)); + } +} + +u8 msm665xx_device::do_aluop_byte(u8 n1, u8 n2) noexcept +{ + u8 result; + switch (BIT(m_inst, 4, 3)) + { + default: // (what even are bitfields?) + case 0: // SUB + return do_subb(n1, n2); + + case 1: // CMP + (void)do_subb(n1, n2); + return n1; + + case 2: // ADD + return do_addb(n1, n2); + + case 3: // AND + result = n1 & n2; + setzs_byte(result); + return result; + + case 4: // OR + result = n1 | n2; + setzs_byte(result); + return result; + + case 5: // XOR + result = n1 ^ n2; + setzs_byte(result); + return result; + + case 6: // ADC + return do_addb(n1, n2, BIT(m_psw, 15)); + + case 7: // SBC + return do_subb(n1, n2, BIT(m_psw, 15)); + } +} + +u16 msm665xx_device::do_inc(u16 n) noexcept +{ + u16 result = n + 1; + if (result == 0) + m_psw |= 0x4000; + else + m_psw &= 0xbfff; + if (BIT(result, 15)) + m_psw |= 0x0800; + else + m_psw &= 0xf7ff; + if (result == 0x8000) + m_psw |= 0x0200; + else + m_psw &= 0xfdff; + if ((result & 0x000f) == 0) + m_psw |= 0x2000; + else + m_psw &= 0xdfff; + return result; +} + +u8 msm665xx_device::do_incb(u8 n) noexcept +{ + u8 result = n + 1; + if (result == 0) + m_psw |= 0x4000; + else + m_psw &= 0xbfff; + if (BIT(result, 7)) + m_psw |= 0x0800; + else + m_psw &= 0xf7ff; + if (result == 0x80) + m_psw |= 0x0200; + else + m_psw &= 0xfdff; + if ((result & 0x0f) == 0) + m_psw |= 0x2000; + else + m_psw &= 0xdfff; + return result; +} + +u16 msm665xx_device::do_dec(u16 n) noexcept +{ + u16 result = n - 1; + if (result == 0) + m_psw |= 0x4000; + else + m_psw &= 0xbfff; + if (BIT(result, 15)) + m_psw |= 0x0800; + else + m_psw &= 0xf7ff; + if (n == 0x8000) + m_psw |= 0x0200; + else + m_psw &= 0xfdff; + if ((n & 0x000f) == 0) + m_psw |= 0x2000; + else + m_psw &= 0xdfff; + return result; +} + +u8 msm665xx_device::do_decb(u8 n) noexcept +{ + u8 result = n - 1; + if (result == 0) + m_psw |= 0x4000; + else + m_psw &= 0xbfff; + if (BIT(result, 7)) + m_psw |= 0x0800; + else + m_psw &= 0xf7ff; + if (n == 0x80) + m_psw |= 0x0200; + else + m_psw &= 0xfdff; + if ((n & 0x0f) == 0) + m_psw |= 0x2000; + else + m_psw &= 0xdfff; + return result; +} + +u16 msm665xx_device::do_rol(u16 n) noexcept +{ + bool c = BIT(m_psw, 15); + if (BIT(n, 15)) + m_psw |= 0x8000; + else + m_psw &= 0x7fff; + return n << 1 | (c ? 1 : 0); +} + +u8 msm665xx_device::do_rolb(u8 n) noexcept +{ + bool c = BIT(m_psw, 15); + if (BIT(n, 7)) + m_psw |= 0x8000; + else + m_psw &= 0x7fff; + return n << 1 | (c ? 1 : 0); +} + +u16 msm665xx_device::do_ror(u16 n) noexcept +{ + bool c = BIT(m_psw, 15); + if (BIT(n, 0)) + m_psw |= 0x8000; + else + m_psw &= 0x7fff; + return n >> 1 | (c ? 0x8000 : 0); +} + +u8 msm665xx_device::do_rorb(u8 n) noexcept +{ + bool c = BIT(m_psw, 15); + if (BIT(n, 0)) + m_psw |= 0x8000; + else + m_psw &= 0x7fff; + return n >> 1 | (c ? 0x80 : 0); +} + +void msm665xx_device::do_mul(u16 data) noexcept +{ + u32 prod = m_acc * u32(data); + if (prod == 0) + m_psw |= 0x4000; + else + m_psw &= 0xbfff; + + // Store 32-bit product + m_acc = prod >> 16; + m_data_cache.write_word(addr_er(0), prod & 0xffff); +} + +void msm665xx_device::do_div(u16 data) noexcept +{ + if (data == 0) + { + m_psw |= 0x8000; + return; + } + m_psw &= 0x7fff; + + u32 div = u32(m_acc) << 16 | m_data_cache.read_word(addr_er(0)); + u32 quot = div / data; + if (quot == 0) + m_psw |= 0x4000; + else + m_psw &= 0xbfff; + + // Store 32-bit quotient and 16-bit remainder + m_acc = quot >> 16; + m_data_cache.write_word(addr_er(0), quot & 0xffff); + m_data_cache.write_word(addr_er(1), div % data); +} + +void msm665xx_device::do_divb(u8 data) noexcept +{ + if (data == 0) + { + m_psw |= 0x8000; + return; + } + m_psw &= 0x7fff; + + u16 quot = m_acc / data; + if (quot == 0) + m_psw |= 0x4000; + else + m_psw &= 0xbfff; + + // Store 16-bit quotient and 8-bit remainder + m_data_cache.write_byte(addr_lr(1), m_acc % data); + m_acc = quot; +} + +void msm665xx_device::do_divq(u16 data) noexcept +{ + if (data == 0) + { + m_psw |= 0x8000; + return; + } + m_psw &= 0x7fff; + + u32 div = u32(m_acc) << 16 | m_data_cache.read_word(addr_er(0)); + u32 quot = div / data; + if (quot >= 0x10000) + m_psw |= 0x0200; + else + m_psw &= 0xfdff; + if ((quot & 0xffff) == 0) + m_psw |= 0x4000; + else + m_psw &= 0xbfff; + + // Store 16-bit quotient and 16-bit remainder + m_acc = quot & 0xffff; + m_data_cache.write_word(addr_er(1), div % data); } @@ -237,15 +626,2636 @@ void msm665xx_device::memscon_w(u8 data) m_memscon = data & 0x03; } +u16 msm665xx_device::get_seg(u16 addr) const noexcept +{ + // Common area from 0 to 03FFH, 1FFFH, 3FFFH, 7FFFH is always segment 0 + if (m_dsr == 0 || addr < (BIT(m_psw, 4, 2) == 0 ? 0x0400 : 0x1000 << BIT(m_psw, 4, 2))) + { + if (addr >= 0x1200 && (m_romwin & 0x0f) != 0 && (addr >> 12) >= (m_romwin & 0x0f) && (addr >> 12) <= (m_romwin >> 4)) + return 0x8000 | m_tsr; + else + return 0; + } + else + { + if ((m_romwin & 0x0f) != 0 && (addr >> 12) >= (m_romwin & 0x0f) && (addr >> 12) <= (m_romwin >> 4)) + return 0x8000 | m_tsr; + else + return m_dsr; + } +} + + +enum class msm665xx_device::inst_state : u8 +{ + NOP, no_jump, store_byte, store_word, + RT, RTI, J_Cadr, J_Cadr_2, + SJ, DJNZ_Rn, prefix_stackop, FCAL, FCAL_2, FCAL_3, FRT, PUSHS_A, + op16_A_ERn_PRn, op8_A_Rn, + MOVB_Rn_N8, + MOV_PRn_ERn_N16, MOV_PRn_ERn_N16_2, + ST_A_ind_PRn, ST_A_ind_DP_post, STB_A_ind_PRn, STB_A_ind_DP_post, + ST_A_fix8, ST_A_off8, ST_A_sfr8, ST_A_dir, ST_A_dir_2, + STB_A_fix8, STB_A_off8, STB_A_sfr8, STB_A_dir, STB_A_dir_2, + ST_A_ERn_PRn, STB_A_Rn, + INC_DEC_PRn, ACAL, prefix_sbaoff6, prefix_sbafix6, + prefix_PRn_ERn, prefix_Rn, + L_A_PRn_ERn, LB_A_Rn, + L_A_ind_PRn, L_A_ind_DP_post, + L_A_fix8, L_A_off8, L_A_sfr8, L_A_dir, L_A_dir_2, L_A_obj, + L_A_D16_X1, L_A_D16_X1_2, L_A_n7_ind_PR, prefix_PSW, prefix_n7_ind_PR, + op16_A_fix8, op16_A_off8, op16_A_N16, op16_A_N16_2, op16_A_N16_3, SLL_A, + op8_A_fix8, op8_A_off8, op8_A_N8, op8_A_N8_2, SLLB_A, + LB_A_ind_PRn, LB_A_ind_DP_post, + LB_A_obj, + SRL_A, + SRLB_A, + prefix_ind8_PRn, prefix_ind16_PRn, prefix_ind_DP_post, + prefix_fix8, prefix_off8, prefix_sfr8, prefix_dir, prefix_dir_2, + prefix_D16_PRn, prefix_D16_PRn_2, prefix_ind8_X1_A, prefix_ind16_X1_A, prefix_ind8_X1_R0, prefix_ind16_X1_R0, + prefix_obj8, prefix_obj16, + ROL_A, + ROLB_A, + prefix_A16, prefix_A8, + ROR_A, + RORB_A, + INCB_DECB_Rn, + CMP_fix8_N16, CMP_off8_N16, + MOV_sfr8_N16, MOV_off8_N16, + ST_A_D16_X1, ST_A_D16_X1_2, ST_A_n7_ind_PR, + STB_A_D16_X1, STB_A_D16_X1_2, STB_A_n7_ind_PR, + RC_SC, + INC_A, NEG_A, + INCB_A, NEGB_A, + CMPB_fix8_N8, CMPB_off8_N8, + MOVB_sfr8_N8, MOVB_off8_N8, + RDD_SDD, + DI_EI, + DEC_A, SWAP, + DECB_A, + VCAL, + JGT_JLE, JZ_JNZ, JCY_JNC, JNS_JPS, + L_A_N16, L_A_N16_2, L_A_N16_3, LB_A_N8, LB_A_N8_2, CLR_A, CLRB_A, + EXTND, CPL_C, CAL_Cadr, CAL_Cadr_2, BRK, + + RB_SB_obj_bit, + MB_C_obj_bit, MB_obj_bit_C, + JBR_JBS_obj_bit, + JBRS_JBSR_obj_bit, + BAND_C_obj_bit, + BOR_C_obj_bit, + BXOR_C_obj_bit, + MOV_ERn_PRn_obj, MOVB_Rn_obj, + op16_obj_fix8, op8_obj_fix8, + op16_obj_off8, op8_obj_off8, + op16_obj_sfr8, op8_obj_sfr8, + op16_obj1_obj2, op8_obj1_obj2, + op16_obj_N16, op16_obj_N16_2, op16_obj_N16_3, + op8_obj_N8, op8_obj_N8_2, + op16_obj_A, op8_obj_A, + op16_A_obj, op8_A_obj, + MOV_fix8_obj, MOV_off8_obj, + MOVB_fix8_obj, MOVB_off8_obj, + MOV_ind_PRn_obj, MOV_ind_DP_post_obj, + MOVB_ind_PRn_obj, MOVB_ind_DP_post_obj, + SLL_obj, SLLB_obj, + CMP_obj1_obj2, CMPB_obj1_obj2, + CMP_obj_N16, CMP_obj_N16_2, CMP_obj_N16_3, + CMPB_obj_N8, CMPB_obj_N8_2, + CMP_obj_A, CMPB_obj_A, + MOV_sfr8_obj, MOV_A_obj, + MOVB_sfr8_obj, MOVB_A_obj, + MOV_D16_PRn_obj, MOV_D16_PRn_obj_2, MOVB_D16_PRn_obj, MOVB_D16_PRn_obj_2, + MOV_n7_ind_PR_obj, MOVB_n7_ind_PR_obj, + MOV_dir_obj, MOV_dir_obj_2, MOVB_dir_obj, MOVB_dir_obj_2, + SRL_obj, SRLB_obj, + TJNZ_TJZ, TJNZB_TJZB, + DIV_obj, DIVB_obj, + MUL_obj, MULB_obj, + MOV_obj_A, MOV_obj_N16, MOV_obj_N16_2, + MOVB_obj_A, MOVB_obj_N8, + ROL_ROR_obj, ROLB_RORB_obj, + CMPC_LC_A_Tadr, CMPC_LC_A_Tadr_2, CMPCB_LCB_A_Tadr, CMPCB_LCB_A_Tadr_2, + SBR_RBR_obj, MBR_C_obj, MBR_obj_C, + INC_DEC_obj, CLR_FILL_obj, XCHG_A_obj, + INCB_DECB_obj, CLRB_FILLB_obj, XCHGB_A_obj, + TBR_obj, + J_ind_obj, + CMPC_LC_A_ind_obj, CMPCB_LCB_A_ind_obj, + CMPC_LC_A_T16_obj, CMPC_LC_A_T16_obj_2, CMPC_A_obj_3, CMPCB_A_obj_3, LC_A_obj_3, LCB_A_obj_3, + DJNZ_obj, + CAL_ind_obj, + SRA_obj, SRAB_obj, + MOV_obj_ind_X1_A, MOV_obj_ind_X1_R0, MOVB_obj_ind_X1_A, MOVB_obj_ind_X1_R0, + FJ, FJ_2, FJ_3, + DIVQ_obj, + JLTS_JGES, JLES_JGTS, + illegal +}; + +const msm665xx_device::inst_state msm665xx_device::s_inst_decode[2][0x100] = +{ + { + // 00-0F (DD = 0) + inst_state::NOP, inst_state::RT, inst_state::RTI, inst_state::J_Cadr, + inst_state::SJ, inst_state::DJNZ_Rn, inst_state::prefix_stackop, inst_state::PUSHS_A, + inst_state::op8_A_Rn, inst_state::op8_A_Rn, inst_state::op8_A_Rn, inst_state::op8_A_Rn, + inst_state::op8_A_Rn, inst_state::op8_A_Rn, inst_state::op8_A_Rn, inst_state::op8_A_Rn, + + // 10-1F (DD = 0) + inst_state::MOVB_Rn_N8, inst_state::MOVB_Rn_N8, inst_state::MOVB_Rn_N8, inst_state::MOVB_Rn_N8, + inst_state::MOVB_Rn_N8, inst_state::MOVB_Rn_N8, inst_state::MOVB_Rn_N8, inst_state::MOVB_Rn_N8, + inst_state::op8_A_Rn, inst_state::op8_A_Rn, inst_state::op8_A_Rn, inst_state::op8_A_Rn, + inst_state::op8_A_Rn, inst_state::op8_A_Rn, inst_state::op8_A_Rn, inst_state::op8_A_Rn, + + // 20-2F (DD = 0) + inst_state::MOV_PRn_ERn_N16, inst_state::MOV_PRn_ERn_N16, inst_state::MOV_PRn_ERn_N16, inst_state::MOV_PRn_ERn_N16, + inst_state::MOV_PRn_ERn_N16, inst_state::MOV_PRn_ERn_N16, inst_state::MOV_PRn_ERn_N16, inst_state::MOV_PRn_ERn_N16, + inst_state::op8_A_Rn, inst_state::op8_A_Rn, inst_state::op8_A_Rn, inst_state::op8_A_Rn, + inst_state::op8_A_Rn, inst_state::op8_A_Rn, inst_state::op8_A_Rn, inst_state::op8_A_Rn, + + // 30-3F (DD = 0) + inst_state::STB_A_ind_PRn, inst_state::STB_A_ind_DP_post, inst_state::STB_A_ind_PRn, inst_state::STB_A_ind_DP_post, + inst_state::STB_A_fix8, inst_state::STB_A_off8, inst_state::STB_A_sfr8, inst_state::STB_A_dir, + inst_state::STB_A_Rn, inst_state::STB_A_Rn, inst_state::STB_A_Rn, inst_state::STB_A_Rn, + inst_state::STB_A_Rn, inst_state::STB_A_Rn, inst_state::STB_A_Rn, inst_state::STB_A_Rn, + + // 40-4F + inst_state::INC_DEC_PRn, inst_state::INC_DEC_PRn, inst_state::INC_DEC_PRn, inst_state::INC_DEC_PRn, + inst_state::ACAL, inst_state::ACAL, inst_state::ACAL, inst_state::ACAL, + inst_state::prefix_sbaoff6, inst_state::prefix_sbaoff6, inst_state::prefix_sbaoff6, inst_state::prefix_sbaoff6, + inst_state::prefix_sbaoff6, inst_state::prefix_sbaoff6, inst_state::prefix_sbaoff6, inst_state::prefix_sbaoff6, + + // 50-5F + inst_state::INC_DEC_PRn, inst_state::INC_DEC_PRn, inst_state::INC_DEC_PRn, inst_state::INC_DEC_PRn, + inst_state::ACAL, inst_state::ACAL, inst_state::ACAL, inst_state::ACAL, + inst_state::prefix_sbafix6, inst_state::prefix_sbafix6, inst_state::prefix_sbafix6, inst_state::prefix_sbafix6, + inst_state::prefix_sbafix6, inst_state::prefix_sbafix6, inst_state::prefix_sbafix6, inst_state::prefix_sbafix6, + + // 60-6F + inst_state::prefix_PRn_ERn, inst_state::prefix_PRn_ERn, inst_state::prefix_PRn_ERn, inst_state::prefix_PRn_ERn, + inst_state::prefix_PRn_ERn, inst_state::prefix_PRn_ERn, inst_state::prefix_PRn_ERn, inst_state::prefix_PRn_ERn, + inst_state::prefix_Rn, inst_state::prefix_Rn, inst_state::prefix_Rn, inst_state::prefix_Rn, + inst_state::prefix_Rn, inst_state::prefix_Rn, inst_state::prefix_Rn, inst_state::prefix_Rn, + + // 70-7F + inst_state::L_A_PRn_ERn, inst_state::L_A_PRn_ERn, inst_state::L_A_PRn_ERn, inst_state::L_A_PRn_ERn, + inst_state::L_A_PRn_ERn, inst_state::L_A_PRn_ERn, inst_state::L_A_PRn_ERn, inst_state::L_A_PRn_ERn, + inst_state::LB_A_Rn, inst_state::LB_A_Rn, inst_state::LB_A_Rn, inst_state::LB_A_Rn, + inst_state::LB_A_Rn, inst_state::LB_A_Rn, inst_state::LB_A_Rn, inst_state::LB_A_Rn, + + // 80-8F (DD = 0) + inst_state::L_A_ind_PRn, inst_state::L_A_ind_DP_post, inst_state::L_A_ind_PRn, inst_state::L_A_ind_DP_post, + inst_state::L_A_fix8, inst_state::L_A_off8, inst_state::L_A_sfr8, inst_state::L_A_dir, + inst_state::L_A_D16_X1, inst_state::L_A_n7_ind_PR, inst_state::prefix_PSW, inst_state::prefix_n7_ind_PR, + inst_state::op8_A_fix8, inst_state::op8_A_off8, inst_state::op8_A_N8, inst_state::SLLB_A, + + // 90-9F (DD = 0) + inst_state::LB_A_ind_PRn, inst_state::LB_A_ind_DP_post, inst_state::LB_A_ind_PRn, inst_state::LB_A_ind_DP_post, + inst_state::L_A_fix8, inst_state::L_A_off8, inst_state::L_A_sfr8, inst_state::L_A_dir, + inst_state::L_A_D16_X1, inst_state::L_A_n7_ind_PR, inst_state::prefix_PSW, inst_state::prefix_n7_ind_PR, + inst_state::op8_A_fix8, inst_state::op8_A_off8, inst_state::op8_A_N8, inst_state::SRLB_A, + + // A0-AF (DD = 0) + inst_state::prefix_ind8_PRn, inst_state::prefix_ind_DP_post, inst_state::prefix_ind8_PRn, inst_state::prefix_ind_DP_post, + inst_state::prefix_fix8, inst_state::prefix_off8, inst_state::prefix_sfr8, inst_state::prefix_dir, + inst_state::prefix_D16_PRn, inst_state::prefix_D16_PRn, inst_state::prefix_ind8_X1_A, inst_state::prefix_ind8_X1_R0, + inst_state::op8_A_fix8, inst_state::op8_A_off8, inst_state::op8_A_N8, inst_state::ROLB_A, + + // B0-BF (DD = 0) + inst_state::prefix_ind8_PRn, inst_state::prefix_ind_DP_post, inst_state::prefix_ind8_PRn, inst_state::prefix_ind_DP_post, + inst_state::prefix_fix8, inst_state::prefix_off8, inst_state::prefix_sfr8, inst_state::prefix_dir, + inst_state::prefix_D16_PRn, inst_state::prefix_D16_PRn, inst_state::prefix_ind8_X1_A, inst_state::prefix_ind8_X1_R0, + inst_state::prefix_A8, inst_state::op8_A_off8, inst_state::op8_A_N8, inst_state::RORB_A, + + // C0-CF (DD = 0) + inst_state::INCB_DECB_Rn, inst_state::INCB_DECB_Rn, inst_state::INCB_DECB_Rn, inst_state::INCB_DECB_Rn, + inst_state::CMP_fix8_N16, inst_state::CMP_off8_N16, inst_state::MOV_sfr8_N16, inst_state::MOV_off8_N16, + inst_state::STB_A_D16_X1, inst_state::STB_A_n7_ind_PR, inst_state::RC_SC, inst_state::RC_SC, + inst_state::INCB_A, inst_state::op8_A_off8, inst_state::op8_A_N8, inst_state::NEGB_A, + + // D0-DF (DD = 0) + inst_state::INCB_DECB_Rn, inst_state::INCB_DECB_Rn, inst_state::INCB_DECB_Rn, inst_state::INCB_DECB_Rn, + inst_state::CMPB_fix8_N8, inst_state::CMPB_off8_N8, inst_state::MOVB_sfr8_N8, inst_state::MOVB_off8_N8, + inst_state::RDD_SDD, inst_state::RDD_SDD, inst_state::DI_EI, inst_state::DI_EI, + inst_state::DECB_A, inst_state::op8_A_off8, inst_state::op8_A_N8, inst_state::SWAP, + + // E0-EF + inst_state::VCAL, inst_state::VCAL, inst_state::VCAL, inst_state::VCAL, + inst_state::VCAL, inst_state::VCAL, inst_state::VCAL, inst_state::VCAL, + inst_state::VCAL, inst_state::VCAL, inst_state::VCAL, inst_state::VCAL, + inst_state::VCAL, inst_state::VCAL, inst_state::VCAL, inst_state::VCAL, + + // F0-FF + inst_state::JGT_JLE, inst_state::JZ_JNZ, inst_state::JCY_JNC, inst_state::JNS_JPS, + inst_state::JNS_JPS, inst_state::JCY_JNC, inst_state::JZ_JNZ, inst_state::JGT_JLE, + inst_state::L_A_N16, inst_state::LB_A_N8, inst_state::CLR_A, inst_state::CLRB_A, + inst_state::EXTND, inst_state::CPL_C, inst_state::CAL_Cadr, inst_state::BRK + }, + + { + // 00-0F (DD = 1) + inst_state::NOP, inst_state::RT, inst_state::RTI, inst_state::J_Cadr, + inst_state::SJ, inst_state::DJNZ_Rn, inst_state::prefix_stackop, inst_state::PUSHS_A, + inst_state::op16_A_ERn_PRn, inst_state::op16_A_ERn_PRn, inst_state::op16_A_ERn_PRn, inst_state::op16_A_ERn_PRn, + inst_state::op16_A_ERn_PRn, inst_state::op16_A_ERn_PRn, inst_state::op16_A_ERn_PRn, inst_state::op16_A_ERn_PRn, + + // 10-1F (DD = 1) + inst_state::MOVB_Rn_N8, inst_state::MOVB_Rn_N8, inst_state::MOVB_Rn_N8, inst_state::MOVB_Rn_N8, + inst_state::MOVB_Rn_N8, inst_state::MOVB_Rn_N8, inst_state::MOVB_Rn_N8, inst_state::MOVB_Rn_N8, + inst_state::op16_A_ERn_PRn, inst_state::op16_A_ERn_PRn, inst_state::op16_A_ERn_PRn, inst_state::op16_A_ERn_PRn, + inst_state::op16_A_ERn_PRn, inst_state::op16_A_ERn_PRn, inst_state::op16_A_ERn_PRn, inst_state::op16_A_ERn_PRn, + + // 20-2F (DD = 1) + inst_state::MOV_PRn_ERn_N16, inst_state::MOV_PRn_ERn_N16, inst_state::MOV_PRn_ERn_N16, inst_state::MOV_PRn_ERn_N16, + inst_state::MOV_PRn_ERn_N16, inst_state::MOV_PRn_ERn_N16, inst_state::MOV_PRn_ERn_N16, inst_state::MOV_PRn_ERn_N16, + inst_state::op16_A_ERn_PRn, inst_state::op16_A_ERn_PRn, inst_state::op16_A_ERn_PRn, inst_state::op16_A_ERn_PRn, + inst_state::op16_A_ERn_PRn, inst_state::op16_A_ERn_PRn, inst_state::op16_A_ERn_PRn, inst_state::op16_A_ERn_PRn, + + // 30-3F (DD = 1) + inst_state::ST_A_ind_PRn, inst_state::ST_A_ind_DP_post, inst_state::ST_A_ind_PRn, inst_state::ST_A_ind_DP_post, + inst_state::ST_A_fix8, inst_state::ST_A_off8, inst_state::ST_A_sfr8, inst_state::ST_A_dir, + inst_state::ST_A_ERn_PRn, inst_state::ST_A_ERn_PRn, inst_state::ST_A_ERn_PRn, inst_state::ST_A_ERn_PRn, + inst_state::ST_A_ERn_PRn, inst_state::ST_A_ERn_PRn, inst_state::ST_A_ERn_PRn, inst_state::ST_A_ERn_PRn, + + // 40-4F + inst_state::INC_DEC_PRn, inst_state::INC_DEC_PRn, inst_state::INC_DEC_PRn, inst_state::INC_DEC_PRn, + inst_state::ACAL, inst_state::ACAL, inst_state::ACAL, inst_state::ACAL, + inst_state::prefix_sbaoff6, inst_state::prefix_sbaoff6, inst_state::prefix_sbaoff6, inst_state::prefix_sbaoff6, + inst_state::prefix_sbaoff6, inst_state::prefix_sbaoff6, inst_state::prefix_sbaoff6, inst_state::prefix_sbaoff6, + + // 50-5F + inst_state::INC_DEC_PRn, inst_state::INC_DEC_PRn, inst_state::INC_DEC_PRn, inst_state::INC_DEC_PRn, + inst_state::ACAL, inst_state::ACAL, inst_state::ACAL, inst_state::ACAL, + inst_state::prefix_sbafix6, inst_state::prefix_sbafix6, inst_state::prefix_sbafix6, inst_state::prefix_sbafix6, + inst_state::prefix_sbafix6, inst_state::prefix_sbafix6, inst_state::prefix_sbafix6, inst_state::prefix_sbafix6, + + // 60-6F + inst_state::prefix_PRn_ERn, inst_state::prefix_PRn_ERn, inst_state::prefix_PRn_ERn, inst_state::prefix_PRn_ERn, + inst_state::prefix_PRn_ERn, inst_state::prefix_PRn_ERn, inst_state::prefix_PRn_ERn, inst_state::prefix_PRn_ERn, + inst_state::prefix_Rn, inst_state::prefix_Rn, inst_state::prefix_Rn, inst_state::prefix_Rn, + inst_state::prefix_Rn, inst_state::prefix_Rn, inst_state::prefix_Rn, inst_state::prefix_Rn, + + // 70-7F + inst_state::L_A_PRn_ERn, inst_state::L_A_PRn_ERn, inst_state::L_A_PRn_ERn, inst_state::L_A_PRn_ERn, + inst_state::L_A_PRn_ERn, inst_state::L_A_PRn_ERn, inst_state::L_A_PRn_ERn, inst_state::L_A_PRn_ERn, + inst_state::LB_A_Rn, inst_state::LB_A_Rn, inst_state::LB_A_Rn, inst_state::LB_A_Rn, + inst_state::LB_A_Rn, inst_state::LB_A_Rn, inst_state::LB_A_Rn, inst_state::LB_A_Rn, + + // 80-8F (DD = 1) + inst_state::L_A_ind_PRn, inst_state::L_A_ind_DP_post, inst_state::L_A_ind_PRn, inst_state::L_A_ind_DP_post, + inst_state::L_A_fix8, inst_state::L_A_off8, inst_state::L_A_sfr8, inst_state::L_A_dir, + inst_state::L_A_D16_X1, inst_state::L_A_n7_ind_PR, inst_state::prefix_PSW, inst_state::prefix_n7_ind_PR, + inst_state::op16_A_fix8, inst_state::op16_A_off8, inst_state::op16_A_N16, inst_state::SLL_A, + + // 90-9F (DD = 1) + inst_state::LB_A_ind_PRn, inst_state::LB_A_ind_DP_post, inst_state::LB_A_ind_PRn, inst_state::LB_A_ind_DP_post, + inst_state::L_A_fix8, inst_state::L_A_off8, inst_state::L_A_sfr8, inst_state::L_A_dir, + inst_state::L_A_D16_X1, inst_state::L_A_n7_ind_PR, inst_state::prefix_PSW, inst_state::prefix_n7_ind_PR, + inst_state::op16_A_fix8, inst_state::op16_A_off8, inst_state::op16_A_N16, inst_state::SRL_A, + + // A0-AF (DD = 1) + inst_state::prefix_ind16_PRn, inst_state::prefix_ind_DP_post, inst_state::prefix_ind16_PRn, inst_state::prefix_ind_DP_post, + inst_state::prefix_fix8, inst_state::prefix_off8, inst_state::prefix_sfr8, inst_state::prefix_dir, + inst_state::prefix_D16_PRn, inst_state::prefix_D16_PRn, inst_state::prefix_ind16_X1_A, inst_state::prefix_ind16_X1_R0, + inst_state::op16_A_fix8, inst_state::op16_A_off8, inst_state::op16_A_N16, inst_state::ROL_A, + + // B0-BF (DD = 1) + inst_state::prefix_ind16_PRn, inst_state::prefix_ind_DP_post, inst_state::prefix_ind16_PRn, inst_state::prefix_ind_DP_post, + inst_state::prefix_fix8, inst_state::prefix_off8, inst_state::prefix_sfr8, inst_state::prefix_dir, + inst_state::prefix_D16_PRn, inst_state::prefix_D16_PRn, inst_state::prefix_ind16_X1_A, inst_state::prefix_ind16_X1_R0, + inst_state::prefix_A16, inst_state::op16_A_off8, inst_state::op16_A_N16, inst_state::ROR_A, + + // C0-CF (DD = 1) + inst_state::INCB_DECB_Rn, inst_state::INCB_DECB_Rn, inst_state::INCB_DECB_Rn, inst_state::INCB_DECB_Rn, + inst_state::CMP_fix8_N16, inst_state::CMP_off8_N16, inst_state::MOV_sfr8_N16, inst_state::MOV_off8_N16, + inst_state::ST_A_D16_X1, inst_state::ST_A_n7_ind_PR, inst_state::RC_SC, inst_state::RC_SC, + inst_state::INC_A, inst_state::op16_A_off8, inst_state::op16_A_N16, inst_state::NEG_A, + + // D0-DF (DD = 1) + inst_state::INCB_DECB_Rn, inst_state::INCB_DECB_Rn, inst_state::INCB_DECB_Rn, inst_state::INCB_DECB_Rn, + inst_state::CMPB_fix8_N8, inst_state::CMPB_off8_N8, inst_state::MOVB_sfr8_N8, inst_state::MOVB_off8_N8, + inst_state::RDD_SDD, inst_state::RDD_SDD, inst_state::DI_EI, inst_state::DI_EI, + inst_state::DEC_A, inst_state::op16_A_off8, inst_state::op16_A_N16, inst_state::SWAP, + + // E0-EF + inst_state::VCAL, inst_state::VCAL, inst_state::VCAL, inst_state::VCAL, + inst_state::VCAL, inst_state::VCAL, inst_state::VCAL, inst_state::VCAL, + inst_state::VCAL, inst_state::VCAL, inst_state::VCAL, inst_state::VCAL, + inst_state::VCAL, inst_state::VCAL, inst_state::VCAL, inst_state::VCAL, + + // F0-FF + inst_state::JGT_JLE, inst_state::JZ_JNZ, inst_state::JCY_JNC, inst_state::JNS_JPS, + inst_state::JNS_JPS, inst_state::JCY_JNC, inst_state::JZ_JNZ, inst_state::JGT_JLE, + inst_state::L_A_N16, inst_state::LB_A_N8, inst_state::CLR_A, inst_state::CLRB_A, + inst_state::EXTND, inst_state::CPL_C, inst_state::CAL_Cadr, inst_state::BRK + } +}; + +const msm665xx_device::inst_state msm665xx_device::s_prefixed_inst_decode[2][0x100] = +{ + { + // 00-0F (byte mode) + inst_state::RB_SB_obj_bit, inst_state::RB_SB_obj_bit, inst_state::RB_SB_obj_bit, inst_state::RB_SB_obj_bit, + inst_state::RB_SB_obj_bit, inst_state::RB_SB_obj_bit, inst_state::RB_SB_obj_bit, inst_state::RB_SB_obj_bit, + inst_state::RB_SB_obj_bit, inst_state::RB_SB_obj_bit, inst_state::RB_SB_obj_bit, inst_state::RB_SB_obj_bit, + inst_state::RB_SB_obj_bit, inst_state::RB_SB_obj_bit, inst_state::RB_SB_obj_bit, inst_state::RB_SB_obj_bit, + + // 10-1F (byte mode) + inst_state::MB_C_obj_bit, inst_state::MB_C_obj_bit, inst_state::MB_C_obj_bit, inst_state::MB_C_obj_bit, + inst_state::MB_C_obj_bit, inst_state::MB_C_obj_bit, inst_state::MB_C_obj_bit, inst_state::MB_C_obj_bit, + inst_state::MB_obj_bit_C, inst_state::MB_obj_bit_C, inst_state::MB_obj_bit_C, inst_state::MB_obj_bit_C, + inst_state::MB_obj_bit_C, inst_state::MB_obj_bit_C, inst_state::MB_obj_bit_C, inst_state::MB_obj_bit_C, + + // 20-2F (byte mode) + inst_state::JBR_JBS_obj_bit, inst_state::JBR_JBS_obj_bit, inst_state::JBR_JBS_obj_bit, inst_state::JBR_JBS_obj_bit, + inst_state::JBR_JBS_obj_bit, inst_state::JBR_JBS_obj_bit, inst_state::JBR_JBS_obj_bit, inst_state::JBR_JBS_obj_bit, + inst_state::JBR_JBS_obj_bit, inst_state::JBR_JBS_obj_bit, inst_state::JBR_JBS_obj_bit, inst_state::JBR_JBS_obj_bit, + inst_state::JBR_JBS_obj_bit, inst_state::JBR_JBS_obj_bit, inst_state::JBR_JBS_obj_bit, inst_state::JBR_JBS_obj_bit, + + // 30-3F (byte mode) + inst_state::JBRS_JBSR_obj_bit, inst_state::JBRS_JBSR_obj_bit, inst_state::JBRS_JBSR_obj_bit, inst_state::JBRS_JBSR_obj_bit, + inst_state::JBRS_JBSR_obj_bit, inst_state::JBRS_JBSR_obj_bit, inst_state::JBRS_JBSR_obj_bit, inst_state::JBRS_JBSR_obj_bit, + inst_state::JBRS_JBSR_obj_bit, inst_state::JBRS_JBSR_obj_bit, inst_state::JBRS_JBSR_obj_bit, inst_state::JBRS_JBSR_obj_bit, + inst_state::JBRS_JBSR_obj_bit, inst_state::JBRS_JBSR_obj_bit, inst_state::JBRS_JBSR_obj_bit, inst_state::JBRS_JBSR_obj_bit, + + // 40-4F (byte mode) + inst_state::BAND_C_obj_bit, inst_state::BAND_C_obj_bit, inst_state::BAND_C_obj_bit, inst_state::BAND_C_obj_bit, + inst_state::BAND_C_obj_bit, inst_state::BAND_C_obj_bit, inst_state::BAND_C_obj_bit, inst_state::BAND_C_obj_bit, + inst_state::BAND_C_obj_bit, inst_state::BAND_C_obj_bit, inst_state::BAND_C_obj_bit, inst_state::BAND_C_obj_bit, + inst_state::BAND_C_obj_bit, inst_state::BAND_C_obj_bit, inst_state::BAND_C_obj_bit, inst_state::BAND_C_obj_bit, + + // 50-5F (byte mode) + inst_state::BOR_C_obj_bit, inst_state::BOR_C_obj_bit, inst_state::BOR_C_obj_bit, inst_state::BOR_C_obj_bit, + inst_state::BOR_C_obj_bit, inst_state::BOR_C_obj_bit, inst_state::BOR_C_obj_bit, inst_state::BOR_C_obj_bit, + inst_state::BOR_C_obj_bit, inst_state::BOR_C_obj_bit, inst_state::BOR_C_obj_bit, inst_state::BOR_C_obj_bit, + inst_state::BOR_C_obj_bit, inst_state::BOR_C_obj_bit, inst_state::BOR_C_obj_bit, inst_state::BOR_C_obj_bit, + + // 60-6F (byte mode) + inst_state::BXOR_C_obj_bit, inst_state::BXOR_C_obj_bit, inst_state::BXOR_C_obj_bit, inst_state::BXOR_C_obj_bit, + inst_state::BXOR_C_obj_bit, inst_state::BXOR_C_obj_bit, inst_state::BXOR_C_obj_bit, inst_state::BXOR_C_obj_bit, + inst_state::illegal, inst_state::illegal, inst_state::illegal, inst_state::illegal, + inst_state::illegal, inst_state::illegal, inst_state::illegal, inst_state::illegal, + + // 70-7F (byte mode) + inst_state::MOVB_Rn_obj, inst_state::MOVB_Rn_obj, inst_state::MOVB_Rn_obj, inst_state::MOVB_Rn_obj, + inst_state::MOVB_Rn_obj, inst_state::MOVB_Rn_obj, inst_state::MOVB_Rn_obj, inst_state::MOVB_Rn_obj, + inst_state::illegal, inst_state::illegal, inst_state::illegal, inst_state::illegal, + inst_state::illegal, inst_state::illegal, inst_state::illegal, inst_state::illegal, + + // 80-8F (byte mode) + inst_state::op8_obj_fix8, inst_state::op8_obj_off8, inst_state::op8_obj_sfr8, inst_state::op8_obj_N8, + inst_state::op8_obj_A, inst_state::op8_A_obj, inst_state::MOVB_fix8_obj, inst_state::MOVB_off8_obj, + inst_state::MOVB_ind_PRn_obj, inst_state::MOVB_ind_DP_post_obj, inst_state::MOVB_ind_PRn_obj, inst_state::MOVB_ind_DP_post_obj, + inst_state::SLLB_obj, inst_state::SLLB_obj, inst_state::SLLB_obj, inst_state::SLLB_obj, + + // 90-9F (byte mode) + inst_state::op8_obj_fix8, inst_state::op8_obj_off8, inst_state::op8_obj_sfr8, inst_state::CMPB_obj_N8, + inst_state::CMPB_obj_A, inst_state::op8_A_obj, inst_state::MOVB_sfr8_obj, inst_state::MOVB_A_obj, + inst_state::MOVB_D16_PRn_obj, inst_state::MOVB_D16_PRn_obj, inst_state::MOVB_n7_ind_PR_obj, inst_state::MOVB_dir_obj, + inst_state::SRLB_obj, inst_state::SRLB_obj, inst_state::SRLB_obj, inst_state::SRLB_obj, + + // A0-AF (byte mode) + inst_state::op8_obj_fix8, inst_state::op8_obj_off8, inst_state::op8_obj_sfr8, inst_state::op8_obj_N8, + inst_state::op8_obj_A, inst_state::op8_A_obj, inst_state::TJNZB_TJZB, inst_state::TJNZB_TJZB, + inst_state::DIVB_obj, inst_state::MULB_obj, inst_state::MOVB_obj_A, inst_state::MOVB_obj_N8, + inst_state::ROLB_RORB_obj, inst_state::illegal, inst_state::illegal, inst_state::illegal, + + // B0-BF (byte mode) + inst_state::op8_obj_fix8, inst_state::op8_obj_off8, inst_state::op8_obj_sfr8, inst_state::op8_obj_N8, + inst_state::op8_obj_A, inst_state::op8_A_obj, inst_state::CMPCB_LCB_A_Tadr, inst_state::CMPCB_LCB_A_Tadr, + inst_state::SBR_RBR_obj, inst_state::SBR_RBR_obj, inst_state::MBR_C_obj, inst_state::MBR_obj_C, + inst_state::ROLB_RORB_obj, inst_state::illegal, inst_state::illegal, inst_state::illegal, + + // C0-CF (byte mode) + inst_state::op8_obj_fix8, inst_state::op8_obj_off8, inst_state::op8_obj_sfr8, inst_state::op8_obj_N8, + inst_state::op8_obj_A, inst_state::op8_A_obj, inst_state::INCB_DECB_obj, inst_state::CLRB_FILLB_obj, + inst_state::XCHGB_A_obj, inst_state::illegal, inst_state::TBR_obj, inst_state::illegal, + inst_state::illegal, inst_state::illegal, inst_state::illegal, inst_state::illegal, + + // D0-DF (byte mode) + inst_state::op8_obj_fix8, inst_state::op8_obj_off8, inst_state::op8_obj_sfr8, inst_state::op8_obj_N8, + inst_state::op8_obj_A, inst_state::op8_A_obj, inst_state::INCB_DECB_obj, inst_state::CLRB_FILLB_obj, + inst_state::illegal, inst_state::illegal, inst_state::illegal, inst_state::illegal, + inst_state::illegal, inst_state::illegal, inst_state::illegal, inst_state::illegal, + + // E0-EF (byte mode) + inst_state::op8_obj_fix8, inst_state::op8_obj_off8, inst_state::op8_obj_sfr8, inst_state::op8_obj_N8, + inst_state::op8_obj_A, inst_state::op8_A_obj, inst_state::illegal, inst_state::illegal, + inst_state::illegal, inst_state::illegal, inst_state::DJNZ_obj, inst_state::illegal, + inst_state::SRAB_obj, inst_state::SRAB_obj, inst_state::SRAB_obj, inst_state::SRAB_obj, + + // F0-FF (byte mode) + inst_state::op8_obj_fix8, inst_state::op8_obj_off8, inst_state::op8_obj_sfr8, inst_state::op8_obj_N8, + inst_state::op8_obj_A, inst_state::op8_A_obj, inst_state::illegal, inst_state::illegal, + inst_state::MOVB_obj_ind_X1_A, inst_state::MOVB_obj_ind_X1_R0, inst_state::illegal, inst_state::illegal, + inst_state::JLTS_JGES, inst_state::JLES_JGTS, inst_state::JLES_JGTS, inst_state::JLTS_JGES + }, + + { + // 00-0F (word mode) + inst_state::illegal, inst_state::illegal, inst_state::illegal, inst_state::illegal, + inst_state::illegal, inst_state::illegal, inst_state::illegal, inst_state::illegal, + inst_state::illegal, inst_state::illegal, inst_state::illegal, inst_state::illegal, + inst_state::illegal, inst_state::illegal, inst_state::illegal, inst_state::illegal, + + // 10-1F (word mode) + inst_state::illegal, inst_state::illegal, inst_state::illegal, inst_state::illegal, + inst_state::illegal, inst_state::illegal, inst_state::illegal, inst_state::illegal, + inst_state::illegal, inst_state::illegal, inst_state::illegal, inst_state::illegal, + inst_state::illegal, inst_state::illegal, inst_state::illegal, inst_state::illegal, + + // 20-2F (word mode) + inst_state::illegal, inst_state::illegal, inst_state::illegal, inst_state::illegal, + inst_state::illegal, inst_state::illegal, inst_state::illegal, inst_state::illegal, + inst_state::illegal, inst_state::illegal, inst_state::illegal, inst_state::illegal, + inst_state::illegal, inst_state::illegal, inst_state::illegal, inst_state::illegal, + + // 30-3F (word mode) + inst_state::illegal, inst_state::illegal, inst_state::illegal, inst_state::illegal, + inst_state::illegal, inst_state::illegal, inst_state::illegal, inst_state::illegal, + inst_state::illegal, inst_state::illegal, inst_state::illegal, inst_state::illegal, + inst_state::illegal, inst_state::illegal, inst_state::illegal, inst_state::illegal, + + // 40-4F (word mode) + inst_state::illegal, inst_state::illegal, inst_state::illegal, inst_state::illegal, + inst_state::illegal, inst_state::illegal, inst_state::illegal, inst_state::illegal, + inst_state::illegal, inst_state::illegal, inst_state::illegal, inst_state::illegal, + inst_state::illegal, inst_state::illegal, inst_state::illegal, inst_state::illegal, + + // 50-5F (word mode) + inst_state::illegal, inst_state::illegal, inst_state::illegal, inst_state::illegal, + inst_state::illegal, inst_state::illegal, inst_state::illegal, inst_state::illegal, + inst_state::illegal, inst_state::illegal, inst_state::illegal, inst_state::illegal, + inst_state::illegal, inst_state::illegal, inst_state::illegal, inst_state::illegal, + + // 60-6F (word mode) + inst_state::illegal, inst_state::illegal, inst_state::illegal, inst_state::illegal, + inst_state::illegal, inst_state::illegal, inst_state::illegal, inst_state::illegal, + inst_state::illegal, inst_state::illegal, inst_state::illegal, inst_state::illegal, + inst_state::illegal, inst_state::illegal, inst_state::illegal, inst_state::illegal, + + // 70-7F (word mode) + inst_state::MOV_ERn_PRn_obj, inst_state::MOV_ERn_PRn_obj, inst_state::MOV_ERn_PRn_obj, inst_state::MOV_ERn_PRn_obj, + inst_state::MOV_ERn_PRn_obj, inst_state::MOV_ERn_PRn_obj, inst_state::MOV_ERn_PRn_obj, inst_state::MOV_ERn_PRn_obj, + inst_state::illegal, inst_state::illegal, inst_state::illegal, inst_state::illegal, + inst_state::illegal, inst_state::illegal, inst_state::illegal, inst_state::illegal, + + // 80-8F (word mode) + inst_state::op16_obj_fix8, inst_state::op16_obj_off8, inst_state::op16_obj_sfr8, inst_state::op16_obj_N16, + inst_state::op16_obj_A, inst_state::op16_A_obj, inst_state::MOV_fix8_obj, inst_state::MOV_off8_obj, + inst_state::MOV_ind_PRn_obj, inst_state::MOV_ind_DP_post_obj, inst_state::MOV_ind_PRn_obj, inst_state::MOV_ind_DP_post_obj, + inst_state::SLL_obj, inst_state::SLL_obj, inst_state::SLL_obj, inst_state::SLL_obj, + + // 90-9F (word mode) + inst_state::op16_obj_fix8, inst_state::op16_obj_off8, inst_state::op16_obj_sfr8, inst_state::CMP_obj_N16, + inst_state::CMP_obj_A, inst_state::op16_A_obj, inst_state::MOV_sfr8_obj, inst_state::MOV_A_obj, + inst_state::MOV_D16_PRn_obj, inst_state::MOV_D16_PRn_obj, inst_state::MOV_n7_ind_PR_obj, inst_state::MOV_dir_obj, + inst_state::SRL_obj, inst_state::SRL_obj, inst_state::SRL_obj, inst_state::SRL_obj, + + // A0-AF (word mode) + inst_state::op16_obj_fix8, inst_state::op16_obj_off8, inst_state::op16_obj_sfr8, inst_state::op16_obj_N16, + inst_state::op16_obj_A, inst_state::op16_A_obj, inst_state::TJNZ_TJZ, inst_state::TJNZ_TJZ, + inst_state::DIV_obj, inst_state::MUL_obj, inst_state::MOV_obj_A, inst_state::MOV_obj_N16, + inst_state::ROL_ROR_obj, inst_state::illegal, inst_state::illegal, inst_state::illegal, + + // B0-BF (word mode) + inst_state::op16_obj_fix8, inst_state::op16_obj_off8, inst_state::op16_obj_sfr8, inst_state::op16_obj_N16, + inst_state::op16_obj_A, inst_state::op16_A_obj, inst_state::CMPC_LC_A_Tadr, inst_state::CMPC_LC_A_Tadr, + inst_state::illegal, inst_state::illegal, inst_state::illegal, inst_state::illegal, + inst_state::ROL_ROR_obj, inst_state::illegal, inst_state::illegal, inst_state::illegal, + + // C0-CF (word mode) + inst_state::op16_obj_fix8, inst_state::op16_obj_off8, inst_state::op16_obj_sfr8, inst_state::op16_obj_N16, + inst_state::op16_obj_A, inst_state::op16_A_obj, inst_state::INC_DEC_obj, inst_state::CLR_FILL_obj, + inst_state::XCHG_A_obj, inst_state::J_ind_obj, inst_state::illegal, inst_state::illegal, + inst_state::illegal, inst_state::illegal, inst_state::illegal, inst_state::illegal, + + // D0-DF (word mode) + inst_state::op16_obj_fix8, inst_state::op16_obj_off8, inst_state::op16_obj_sfr8, inst_state::op16_obj_N16, + inst_state::op16_obj_A, inst_state::op16_A_obj, inst_state::INC_DEC_obj, inst_state::CLR_FILL_obj, + inst_state::CMPC_LC_A_ind_obj, inst_state::CMPCB_LCB_A_ind_obj, inst_state::CMPC_LC_A_ind_obj, inst_state::CMPCB_LCB_A_ind_obj, + inst_state::illegal, inst_state::illegal, inst_state::illegal, inst_state::illegal, + + // E0-EF (word mode) + inst_state::op16_obj_fix8, inst_state::op16_obj_off8, inst_state::op16_obj_sfr8, inst_state::op16_obj_N16, + inst_state::op16_obj_A, inst_state::op16_A_obj, inst_state::CMPC_LC_A_T16_obj, inst_state::CMPC_LC_A_T16_obj, + inst_state::illegal, inst_state::illegal, inst_state::DJNZ_obj, inst_state::CAL_ind_obj, + inst_state::SRA_obj, inst_state::SRA_obj, inst_state::SRA_obj, inst_state::SRA_obj, + + // F0-FF (word mode) + inst_state::op16_obj_fix8, inst_state::op16_obj_off8, inst_state::op16_obj_sfr8, inst_state::op16_obj_N16, + inst_state::op16_obj_A, inst_state::op16_A_obj, inst_state::CMPC_LC_A_T16_obj, inst_state::CMPC_LC_A_T16_obj, + inst_state::MOV_obj_ind_X1_A, inst_state::MOV_obj_ind_X1_R0, inst_state::FJ, inst_state::DIVQ_obj, + inst_state::illegal, inst_state::illegal, inst_state::illegal, inst_state::illegal + } +}; + + +void msm665xx_device::device_reset() +{ + // PC will be initialized from vector following reset; LRB and ROMWIN are undefined at reset + m_acc = 0; + m_psw = 0; + m_ssp = 0xffff; + m_csr = 0; + m_dsr = 0; + m_tsr = 0; + m_memscon = 0; + m_state = inst_state::J_Cadr; +} void msm665xx_device::execute_run() { - m_pc = m_program_cache.read_word(0); - m_ppc = m_pc; - debugger_instruction_hook(m_pc); + do + { + prefetch(); + switch (m_state) + { + case inst_state::NOP: + m_icount -= 2; + next_inst(); + break; - // TODO - m_icount = 0; + case inst_state::no_jump: + m_icount -= 2; + m_state = inst_state::NOP; + break; + + case inst_state::store_byte: + m_icount -= 2; + next_inst_and_store_byte(m_tmp[0]); + break; + + case inst_state::store_word: + m_icount -= 2; + next_inst_and_store_word(m_tmp[0]); + break; + + case inst_state::RT: + m_ssp += 2; + m_pc = data_read_word(0, m_ssp); + m_icount -= 4; + m_state = inst_state::NOP; + break; + + case inst_state::RTI: + m_adr = m_ssp + 2; + m_psw = data_read_word(0, m_adr); + m_adr += 2; + m_lrb = data_read_word(0, m_adr); + m_adr += 2; + m_acc = data_read_word(0, m_adr); + if (BIT(m_memscon, 1)) + { + m_adr += 2; + m_csr = data_read_word(0, m_adr) & 0x000f; + } + m_adr += 2; + m_pc = data_read_word(0, m_adr); + m_ssp = m_adr; + m_icount -= BIT(m_memscon, 1) ? 12 : 10; + m_state = inst_state::NOP; + break; + + case inst_state::J_Cadr: + m_tmp[0] = m_fetch_byte; + m_icount -= 2; + m_state = inst_state::J_Cadr_2; + break; + + case inst_state::J_Cadr_2: + m_pc = m_fetch_byte << 8 | m_tmp[0]; + m_icount -= 3; + m_state = inst_state::NOP; + break; + + case inst_state::SJ: + m_pc += s8(m_fetch_byte); + m_icount -= 4; + m_state = inst_state::NOP; + break; + + case inst_state::DJNZ_Rn: + m_adr = addr_lr(BIT(m_fetch_byte, 7) ? 5 : 4); + m_tmp[0] = m_data_cache.read_byte(m_adr) - 1; + m_data_cache.write_byte(m_adr, m_tmp[0]); + if (m_tmp[0] != 0) + { + m_pc += s8(m_fetch_byte | 0x80); + m_icount -= 10 - 2; + m_state = inst_state::NOP; + } + else + { + m_icount -= 7; + next_inst(); + } + break; + + case inst_state::prefix_stackop: + m_inst = m_fetch_byte; + if ((m_inst & 0x30) != 0x30) + { + if (BIT(m_inst, 6)) + { + m_adr = m_data_cache.read_word(addr_pr(3)); + m_seg = get_seg(m_adr); + } + else + { + m_adr = m_ssp; + m_seg = 0; + } + m_tmp[1] = BIT(m_inst, 5) ? 0 : BIT(m_inst, 4) ? addr_pr(0) : addr_er(0); + if (BIT(m_inst, 7)) + { + // POPS/POPU + for (int n = 0; n < 4; n++) + { + if (BIT(m_inst, n)) + { + m_adr += 2; + if (BIT(m_inst, 6)) + m_seg = get_seg(m_adr); + m_tmp[0] = data_read_word(m_seg, m_adr); + data_write_word(0, m_tmp[1] + n * 2, m_tmp[0]); + m_icount -= 4; + } + } + } + else + { + // PUSHS/PUSHU + for (int n = 3; n >= 0; n--) + { + if (BIT(m_inst, n)) + { + m_tmp[0] = data_read_word(0, m_tmp[1] + n * 2); + data_write_word(m_seg, m_adr, m_tmp[0]); + m_adr -= 2; + if (BIT(m_inst, 6)) + m_seg = get_seg(m_adr); + m_icount -= 4; + } + } + } + if (BIT(m_inst, 6)) + m_data_cache.write_word(addr_pr(3), m_adr); + else + m_ssp = m_adr; + m_icount -= 3; + m_state = inst_state::NOP; + break; + } + else if (m_inst == 0x38 && BIT(m_memscon, 1)) + { + m_state = inst_state::FCAL; + m_icount -= 2; + } + else if (m_inst == 0x39 && BIT(m_memscon, 1)) + { + m_state = inst_state::FRT; + m_icount -= 2; + } + else + m_state = inst_state::illegal; + break; + + case inst_state::FCAL: + m_tmp[0] = m_fetch_byte; + m_state = inst_state::FCAL_2; + m_icount -= 2; + break; + + case inst_state::FCAL_2: + m_tmp[0] |= m_fetch_byte << 8; + m_adr = m_ssp; + m_seg = 0; + m_state = inst_state::FCAL_3; + m_icount -= 2; + break; + + case inst_state::FCAL_3: + data_write_word(0, m_adr, m_pc); + m_adr -= 2; + data_write_word(0, m_adr, m_csr); + m_ssp = m_adr - 2; + m_pc = m_tmp[0]; + m_csr = m_fetch_byte; + m_state = inst_state::NOP; + m_icount -= 5; + break; + + case inst_state::FRT: + m_adr = m_ssp + 2; + m_csr = data_read_word(0, m_adr) & 0x000f; + m_adr += 2; + m_pc = data_read_word(0, m_adr); + m_ssp = m_adr; + m_state = inst_state::NOP; + m_icount -= 9 - (2 * 2); + break; + + case inst_state::PUSHS_A: + data_write_word(0, m_ssp, m_acc); + m_ssp -= 2; + m_icount -= 3; + next_inst(); + break; + + case inst_state::op16_A_ERn_PRn: + m_adr = BIT(m_inst, 2) ? addr_pr(m_inst) : addr_er(m_inst); + m_acc = do_aluop_word(m_acc, m_data_cache.read_word(m_adr)); + m_icount -= 3; + next_inst(); + break; + + case inst_state::op8_A_Rn: + m_adr = addr_lr(m_inst); + m_acc = (m_acc & 0xff00) | do_aluop_byte(m_acc & 0x00ff, m_data_cache.read_byte(m_adr)); + m_icount -= 3; + next_inst(); + break; + + case inst_state::MOVB_Rn_N8: + m_adr = addr_lr(m_inst); + m_seg = 0; + m_tmp[0] = m_fetch_byte; + m_icount -= 2; + m_state = inst_state::store_byte; + break; + + case inst_state::MOV_PRn_ERn_N16: + m_adr = BIT(m_inst, 2) ? addr_er(m_inst) : addr_pr(m_inst); + m_seg = 0; + m_tmp[0] = m_fetch_byte; + m_state = inst_state::MOV_PRn_ERn_N16_2; + m_icount -= 2; + break; + + case inst_state::MOV_PRn_ERn_N16_2: + m_tmp[0] |= m_fetch_byte << 8; + m_state = inst_state::store_word; + m_icount -= 2; + break; + + case inst_state::ST_A_ind_PRn: + m_adr = m_data_cache.read_word(addr_pr(m_inst)); + m_seg = get_seg(m_adr); + m_icount -= 4; + next_inst_and_store_word(m_acc); + break; + + case inst_state::ST_A_ind_DP_post: + m_tmp[1] = addr_pr(2); + m_adr = m_data_cache.read_word(m_tmp[1]); + m_seg = get_seg(m_adr); + m_data_cache.write_word(m_tmp[1], m_adr + (BIT(m_inst, 1) ? 2 : -2)); + m_icount -= 5; + next_inst_and_store_word(m_acc); + break; + + case inst_state::STB_A_ind_PRn: + m_adr = m_data_cache.read_word(addr_pr(m_inst)); + m_seg = get_seg(m_adr); + m_icount -= 4; + next_inst_and_store_byte(m_acc & 0x00ff); + break; + + case inst_state::STB_A_ind_DP_post: + m_tmp[1] = addr_pr(2); + m_adr = m_data_cache.read_word(m_tmp[1]); + m_seg = get_seg(m_adr); + m_data_cache.write_word(m_tmp[1], m_adr + (BIT(m_inst, 1) ? 1 : -1)); + m_icount -= 5; + next_inst_and_store_byte(m_acc & 0x00ff); + break; + + case inst_state::ST_A_fix8: + set_adr_fix8(m_fetch_byte); + m_icount -= 2; + m_state = inst_state::MOV_obj_A; + break; + + case inst_state::ST_A_off8: + set_adr_off8(m_fetch_byte); + m_icount -= 2; + m_state = inst_state::MOV_obj_A; + break; + + case inst_state::ST_A_sfr8: + set_adr_sfr8(m_fetch_byte); + m_icount -= 2; + m_state = inst_state::MOV_obj_A; + break; + + case inst_state::ST_A_dir: + m_tmp[0] = m_fetch_byte; + m_state = inst_state::ST_A_dir_2; + m_icount -= 2; + break; + + case inst_state::ST_A_dir_2: + m_adr = m_fetch_byte << 8 | m_tmp[0]; + m_seg = get_seg(m_adr); + m_tmp[0] = m_acc; + m_state = inst_state::store_word; + m_icount -= 2; + break; + + case inst_state::STB_A_fix8: + set_adr_fix8(m_fetch_byte); + m_icount -= 2; + m_state = inst_state::MOVB_obj_A; + break; + + case inst_state::STB_A_off8: + set_adr_off8(m_fetch_byte); + m_icount -= 2; + m_state = inst_state::MOVB_obj_A; + break; + + case inst_state::STB_A_sfr8: + set_adr_sfr8(m_fetch_byte); + m_icount -= 2; + m_state = inst_state::MOVB_obj_A; + break; + + case inst_state::STB_A_dir: + m_tmp[0] = m_fetch_byte; + m_icount -= 2; + m_state = inst_state::STB_A_dir_2; + break; + + case inst_state::STB_A_dir_2: + m_adr = m_fetch_byte << 8 | m_tmp[0]; + m_seg = get_seg(m_adr); + m_icount -= 2; + m_state = inst_state::MOVB_obj_A; + break; + + case inst_state::ST_A_ERn_PRn: + m_adr = BIT(m_inst, 2) ? addr_pr(m_inst) : addr_er(m_inst); + m_data_cache.write_word(m_adr, m_acc); + m_icount -= 2; + next_inst(); + break; + + case inst_state::STB_A_Rn: + m_adr = addr_lr(m_inst); + m_data_cache.write_byte(m_adr, m_acc & 0x00ff); + m_icount -= 2; + next_inst(); + break; + + case inst_state::INC_DEC_PRn: + m_adr = addr_pr(m_inst); + m_tmp[0] = m_data_cache.read_word(m_adr); + if (BIT(m_inst, 4)) + m_tmp[0] = do_dec(m_tmp[0]); + else + m_tmp[0] = do_inc(m_tmp[0]); + m_data_cache.write_word(m_adr, m_tmp[0]); + m_icount -= 3; + next_inst(); + break; + + case inst_state::ACAL: + m_tmp[0] = (BIT(m_inst, 4) ? 0x1400 : 0x1000) | u16(m_inst & 0x03) << 8 | m_fetch_byte; + data_write_word(0, m_ssp, m_pc); + m_ssp -= 2; + m_pc = m_tmp[0]; + m_icount -= 7; + m_state = inst_state::NOP; + break; + + case inst_state::prefix_sbaoff6: + set_adr_off8(0xc0 | m_fetch_byte); + m_tmp[0] = data_read_byte(m_seg, m_adr); + if (BIT(m_fetch_byte, 7)) + { + if (BIT(m_fetch_byte, 6) != BIT(m_tmp[0], m_inst & 0x07)) + { + m_state = inst_state::SJ; + m_icount -= 9 - 6; + } + else + { + m_state = inst_state::no_jump; + m_icount -= 6 - 4; + } + } + else + { + if (BIT(m_fetch_byte, 6)) + m_tmp[0] &= ~(1 << (m_inst & 0x07)); + else + m_tmp[0] |= 1 << (m_inst & 0x07); + m_state = inst_state::store_byte; + m_icount -= 4 - 2; + } + break; + + case inst_state::prefix_sbafix6: + set_adr_fix8(0xc0 | m_fetch_byte); + m_tmp[0] = m_data_cache.read_byte(m_adr); + if (BIT(m_fetch_byte, 7)) + { + if (BIT(m_fetch_byte, 6) != BIT(m_tmp[0], m_inst & 0x07)) + { + m_state = inst_state::SJ; + m_icount -= 9 - 6; + } + else + { + m_state = inst_state::no_jump; + m_icount -= 6 - 4; + } + } + else + { + if (BIT(m_fetch_byte, 6)) + m_tmp[0] &= ~(1 << (m_inst & 0x07)); + else + m_tmp[0] |= 1 << (m_inst & 0x07); + m_state = inst_state::store_byte; + m_icount -= 4 - 2; + } + break; + + case inst_state::prefix_PRn_ERn: + m_adr = BIT(m_inst, 2) ? addr_er(m_inst) : addr_pr(m_inst); + m_seg = 0; + m_inst = m_fetch_byte; + m_icount -= 2; + m_state = s_prefixed_inst_decode[1][m_inst]; + break; + + case inst_state::prefix_Rn: + m_adr = addr_lr(m_inst); + m_seg = 0; + m_inst = m_fetch_byte; + m_icount -= 2; + m_state = s_prefixed_inst_decode[0][m_inst]; + break; + + case inst_state::L_A_PRn_ERn: + m_adr = BIT(m_inst, 2) ? addr_er(m_inst) : addr_pr(m_inst); + acc_load_word(m_data_cache.read_word(m_adr)); + m_icount -= 2; + next_inst(); + break; + + case inst_state::LB_A_Rn: + m_adr = addr_lr(m_inst); + acc_load_byte(m_data_cache.read_byte(m_adr)); + m_icount -= 2; + next_inst(); + break; + + case inst_state::L_A_ind_PRn: + m_adr = m_data_cache.read_word(addr_pr(m_inst)); + m_seg = get_seg(m_adr); + acc_load_word(data_read_word(m_seg, m_adr)); + m_icount -= 4; + next_inst(); + break; + + case inst_state::L_A_ind_DP_post: + m_tmp[1] = addr_pr(2); + m_adr = m_data_cache.read_word(m_tmp[1]); + m_seg = get_seg(m_adr); + m_data_cache.write_word(m_tmp[1], m_adr + (BIT(m_inst, 1) ? 2 : -2)); + acc_load_word(data_read_word(m_seg, m_adr)); + m_icount -= 5; + next_inst(); + break; + + case inst_state::L_A_fix8: + set_adr_fix8(m_fetch_byte); + m_state = BIT(m_inst, 4) ? inst_state::LB_A_obj : inst_state::L_A_obj; + m_icount -= 2; + break; + + case inst_state::L_A_off8: + set_adr_off8(m_fetch_byte); + m_icount -= 2; + m_state = BIT(m_inst, 4) ? inst_state::LB_A_obj : inst_state::L_A_obj; + break; + + case inst_state::L_A_sfr8: + set_adr_sfr8(m_fetch_byte); + m_icount -= 2; + m_state = BIT(m_inst, 4) ? inst_state::LB_A_obj : inst_state::L_A_obj; + break; + + case inst_state::L_A_dir: + m_tmp[0] = m_fetch_byte; + m_icount -= 2; + m_state = inst_state::L_A_dir_2; + break; + + case inst_state::L_A_dir_2: + m_adr = m_fetch_byte << 8 | m_tmp[0]; + m_seg = get_seg(m_adr); + m_icount -= 2; + m_state = BIT(m_inst, 4) ? inst_state::LB_A_obj : inst_state::L_A_obj; + break; + + case inst_state::L_A_obj: + acc_load_word(data_read_word(m_seg, m_adr)); + m_icount -= 2; + next_inst(); + break; + + case inst_state::L_A_D16_X1: + m_tmp[0] = m_fetch_byte; + m_tmp[1] = m_data_cache.read_word(addr_pr(0)); + m_icount -= 2; + m_state = inst_state::L_A_D16_X1_2; + break; + + case inst_state::L_A_D16_X1_2: + m_adr = (m_fetch_byte << 8 | m_tmp[0]) + m_tmp[1]; + m_seg = get_seg(m_adr); + m_icount -= 2; + m_state = BIT(m_inst, 4) ? inst_state::LB_A_obj : inst_state::L_A_obj; + break; + + case inst_state::L_A_n7_ind_PR: + m_adr = m_data_cache.read_word(addr_pr(2 + BIT(m_fetch_byte, 7))) + util::sext(m_fetch_byte, 7); + m_seg = get_seg(m_adr); + m_icount -= 4; + m_state = BIT(m_inst, 4) ? inst_state::LB_A_obj : inst_state::L_A_obj; + break; + + case inst_state::prefix_PSW: + set_adr_sfr8(0x04 + BIT(m_inst, 4)); + m_inst = m_fetch_byte; + m_icount -= 2; + m_state = s_prefixed_inst_decode[0][m_inst]; + break; + + case inst_state::prefix_n7_ind_PR: + m_adr = m_data_cache.read_word(addr_pr(2 + BIT(m_fetch_byte, 7))) + util::sext(m_fetch_byte, 7); + m_seg = get_seg(m_adr); + m_state = BIT(m_inst, 4) ? inst_state::prefix_obj8 : inst_state::prefix_obj16; + m_icount -= 6 - 2; + break; + + case inst_state::op16_A_fix8: + set_adr_fix8(m_fetch_byte); + m_icount -= 2; + m_state = inst_state::op16_A_obj; + break; + + case inst_state::op16_A_off8: + set_adr_off8(m_fetch_byte); + m_icount -= 2; + m_state = inst_state::op16_A_obj; + break; + + case inst_state::op16_A_N16: + m_tmp[0] = m_fetch_byte; + m_icount -= 2; + m_state = inst_state::op16_A_N16_2; + break; + + case inst_state::op16_A_N16_2: + m_tmp[0] |= m_fetch_byte << 8; + m_icount -= 2; + m_state = inst_state::op16_A_N16_3; + break; + + case inst_state::op16_A_N16_3: + m_acc = do_aluop_word(m_acc, m_tmp[0]); + m_icount -= 2; + next_inst(); + break; + + case inst_state::op8_A_fix8: + set_adr_fix8(m_fetch_byte); + m_icount -= 2; + m_state = inst_state::op8_A_obj; + break; + + case inst_state::op8_A_off8: + set_adr_off8(m_fetch_byte); + m_icount -= 2; + m_state = inst_state::op8_A_obj; + break; + + case inst_state::op8_A_N8: + m_tmp[0] = m_fetch_byte; + m_icount -= 2; + m_state = inst_state::op8_A_N8_2; + break; + + case inst_state::op8_A_N8_2: + m_acc = (m_acc & 0xff00) | do_aluop_byte(m_acc & 0x00ff, m_tmp[0]); + m_icount -= 2; + next_inst(); + break; + + case inst_state::LB_A_ind_PRn: + m_adr = m_data_cache.read_word(addr_pr(m_inst)); + m_seg = get_seg(m_adr); + acc_load_byte(data_read_byte(m_seg, m_adr)); + m_icount -= 4; + next_inst(); + break; + + case inst_state::LB_A_ind_DP_post: + m_tmp[1] = addr_pr(2); + m_adr = m_data_cache.read_word(m_tmp[1]); + m_seg = get_seg(m_adr); + m_data_cache.write_word(m_tmp[1], m_adr + (BIT(m_inst, 1) ? 1 : -1)); + acc_load_byte(data_read_byte(m_seg, m_adr)); + m_icount -= 5; + next_inst(); + break; + + case inst_state::LB_A_obj: + acc_load_byte(data_read_byte(m_seg, m_adr)); + m_icount -= 2; + next_inst(); + break; + + case inst_state::SLL_A: + if (BIT(m_acc, 15)) + m_psw |= 0x8000; + else + m_psw &= 0x7fff; + m_acc <<= 1; + m_icount -= 2; + next_inst(); + break; + + case inst_state::SLLB_A: + if (BIT(m_acc, 7)) + m_psw |= 0x8000; + else + m_psw &= 0x7fff; + m_acc = (m_acc & 0xff00) | ((m_acc << 1) & 0x00ff); + m_icount -= 2; + next_inst(); + break; + + case inst_state::SRL_A: + if (BIT(m_acc, 0)) + m_psw |= 0x8000; + else + m_psw &= 0x7fff; + m_acc >>= 1; + m_icount -= 2; + next_inst(); + break; + + case inst_state::SRLB_A: + if (BIT(m_acc, 0)) + m_psw |= 0x8000; + else + m_psw &= 0x7fff; + m_acc = (m_acc & 0xff00) | (m_acc & 0x00ff) >> 1; + m_icount -= 2; + next_inst(); + break; + + case inst_state::prefix_ind8_PRn: + m_adr = m_data_cache.read_word(addr_pr(m_inst)); + m_seg = get_seg(m_adr); + m_inst = m_fetch_byte; + m_icount -= 4; + m_state = s_prefixed_inst_decode[0][m_inst]; + break; + + case inst_state::prefix_ind16_PRn: + m_adr = m_data_cache.read_word(addr_pr(m_inst)); + m_seg = get_seg(m_adr); + m_inst = m_fetch_byte; + m_icount -= 4; + m_state = s_prefixed_inst_decode[1][m_inst]; + break; + + case inst_state::prefix_ind_DP_post: + m_tmp[1] = addr_pr(2); + m_adr = m_data_cache.read_word(m_tmp[1]); + m_seg = get_seg(m_adr); + if (BIT(m_inst, 4)) + m_data_cache.write_word(m_tmp[1], m_adr + (BIT(m_inst, 1) ? 1 : -1)); + else + m_data_cache.write_word(m_tmp[1], m_adr + (BIT(m_inst, 1) ? 2 : -2)); + m_icount -= 3; + m_state = BIT(m_inst, 4) ? inst_state::prefix_obj8 : inst_state::prefix_obj16; + break; + + case inst_state::prefix_fix8: + set_adr_fix8(m_fetch_byte); + m_icount -= 2; + m_state = BIT(m_inst, 4) ? inst_state::prefix_obj8 : inst_state::prefix_obj16; + break; + + case inst_state::prefix_off8: + set_adr_off8(m_fetch_byte); + m_icount -= 2; + m_state = BIT(m_inst, 4) ? inst_state::prefix_obj8 : inst_state::prefix_obj16; + break; + + case inst_state::prefix_sfr8: + set_adr_sfr8(m_fetch_byte); + m_icount -= 2; + m_state = BIT(m_inst, 4) ? inst_state::prefix_obj8 : inst_state::prefix_obj16; + break; + + case inst_state::prefix_dir: + m_tmp[0] = m_fetch_byte; + m_icount -= 2; + m_state = inst_state::prefix_dir_2; + break; + + case inst_state::prefix_dir_2: + m_adr = m_fetch_byte << 8 | m_tmp[0]; + m_seg = get_seg(m_adr); + m_icount -= 2; + m_state = BIT(m_inst, 4) ? inst_state::prefix_obj8 : inst_state::prefix_obj16; + break; + + case inst_state::prefix_D16_PRn: + m_tmp[0] = m_fetch_byte; + m_tmp[1] = m_data_cache.read_word(addr_pr(m_inst)); + m_icount -= 2; + m_state = inst_state::prefix_D16_PRn_2; + break; + + case inst_state::prefix_D16_PRn_2: + m_adr = (m_fetch_byte << 8 | m_tmp[0]) + m_tmp[1]; + m_seg = get_seg(m_adr); + m_icount -= 2; + m_state = BIT(m_inst, 4) ? inst_state::prefix_obj8 : inst_state::prefix_obj16; + break; + + case inst_state::prefix_obj8: + m_inst = m_fetch_byte; + m_icount -= 2; + m_state = s_prefixed_inst_decode[0][m_inst]; + break; + + case inst_state::prefix_obj16: + m_inst = m_fetch_byte; + m_icount -= 2; + m_state = s_prefixed_inst_decode[1][m_inst]; + break; + + case inst_state::prefix_ind8_X1_A: + m_tmp[0] = m_data_cache.read_word(addr_pr(0)); + m_adr = m_tmp[0] + (m_acc & 0x00ff); + m_seg = get_seg(m_adr); + m_inst = m_fetch_byte; + m_icount -= 6; + m_state = s_prefixed_inst_decode[0][m_inst]; + break; + + case inst_state::prefix_ind16_X1_A: + m_tmp[0] = m_data_cache.read_word(addr_pr(0)); + m_adr = m_tmp[0] + (m_acc & 0x00ff); + m_seg = get_seg(m_adr); + m_inst = m_fetch_byte; + m_icount -= 6; + m_state = s_prefixed_inst_decode[1][m_inst]; + break; + + case inst_state::prefix_ind8_X1_R0: + m_tmp[0] = m_data_cache.read_word(addr_pr(0)); + m_adr = m_tmp[0] + m_data_cache.read_byte(addr_lr(0)); + m_seg = get_seg(m_adr); + m_inst = m_fetch_byte; + m_icount -= 6; + m_state = s_prefixed_inst_decode[0][m_inst]; + break; + + case inst_state::prefix_ind16_X1_R0: + m_tmp[0] = m_data_cache.read_word(addr_pr(0)); + m_adr = m_tmp[0] + m_data_cache.read_byte(addr_lr(0)); + m_seg = get_seg(m_adr); + m_inst = m_fetch_byte; + m_icount -= 6; + m_state = s_prefixed_inst_decode[1][m_inst]; + break; + + case inst_state::ROL_A: + m_acc = do_rol(m_acc); + m_icount -= 2; + next_inst(); + break; + + case inst_state::ROLB_A: + m_acc = (m_acc & 0xff00) | do_rolb(m_acc & 0x00ff); + m_icount -= 2; + next_inst(); + break; + + case inst_state::prefix_A16: + set_adr_sfr8(0x06); + m_inst = m_fetch_byte; + m_icount -= 2; + m_state = s_prefixed_inst_decode[m_inst >= 0x70][m_inst]; + break; + + case inst_state::prefix_A8: + set_adr_sfr8(0x06); + m_inst = m_fetch_byte; + m_icount -= 2; + m_state = s_prefixed_inst_decode[0][m_inst]; + break; + + case inst_state::ROR_A: + m_acc = do_ror(m_acc); + m_icount -= 2; + next_inst(); + break; + + case inst_state::RORB_A: + m_acc = (m_acc & 0xff00) | do_rorb(m_acc & 0x00ff); + m_icount -= 2; + next_inst(); + break; + + case inst_state::INCB_DECB_Rn: + m_adr = addr_lr(m_inst); + m_tmp[0] = m_data_cache.read_byte(m_adr); + if (BIT(m_inst, 4)) + m_tmp[0] = do_decb(m_tmp[0]); + else + m_tmp[0] = do_incb(m_tmp[0]); + m_data_cache.write_byte(m_adr, m_tmp[0]); + m_icount -= 3; + next_inst(); + break; + + case inst_state::CMP_fix8_N16: + set_adr_fix8(m_fetch_byte); + m_icount -= 2; + m_state = inst_state::CMP_obj_N16; + break; + + case inst_state::CMP_off8_N16: + set_adr_off8(m_fetch_byte); + m_icount -= 2; + m_state = inst_state::CMP_obj_N16; + break; + + case inst_state::MOV_sfr8_N16: + set_adr_sfr8(m_fetch_byte); + m_icount -= 2; + m_state = inst_state::MOV_obj_N16; + break; + + case inst_state::MOV_off8_N16: + set_adr_off8(m_fetch_byte); + m_icount -= 2; + m_state = inst_state::MOV_obj_N16; + break; + + case inst_state::ST_A_D16_X1: + m_tmp[0] = m_data_cache.read_word(addr_pr(0)); + m_tmp[1] = m_fetch_byte; + m_icount -= 2; + m_state = inst_state::ST_A_D16_X1_2; + break; + + case inst_state::ST_A_D16_X1_2: + m_adr = m_tmp[0] + (m_fetch_byte << 8 | m_tmp[1]); + m_seg = get_seg(m_adr); + m_tmp[0] = m_acc; + m_icount -= 2; + m_state = inst_state::store_word; + break; + + case inst_state::ST_A_n7_ind_PR: + m_adr = m_data_cache.read_word(addr_pr(2 + BIT(m_fetch_byte, 7))) + util::sext(m_fetch_byte, 7); + m_seg = get_seg(m_adr); + m_tmp[0] = m_acc; + m_icount -= 4; + m_state = inst_state::store_word; + break; + + case inst_state::STB_A_D16_X1: + m_tmp[0] = m_data_cache.read_word(addr_pr(0)); + m_tmp[1] = m_fetch_byte; + m_icount -= 2; + m_state = inst_state::STB_A_D16_X1_2; + break; + + case inst_state::STB_A_D16_X1_2: + m_adr = m_tmp[0] + (m_fetch_byte << 8 | m_tmp[1]); + m_seg = get_seg(m_adr); + m_tmp[0] = m_acc & 0x00ff; + m_icount -= 2; + m_state = inst_state::store_byte; + break; + + case inst_state::STB_A_n7_ind_PR: + m_adr = m_data_cache.read_word(addr_pr(2 + BIT(m_fetch_byte, 7))) + util::sext(m_fetch_byte, 7); + m_seg = get_seg(m_adr); + m_tmp[0] = m_acc; + m_icount -= 4; + m_state = inst_state::store_byte; + break; + + case inst_state::RC_SC: + if (BIT(m_inst, 0)) + m_psw |= 0x8000; + else + m_psw &= 0x7fff; + m_icount -= 2; + next_inst(); + break; + + case inst_state::INC_A: + m_acc = do_inc(m_acc); + m_icount -= 2; + next_inst(); + break; + + case inst_state::NEG_A: + m_acc = do_sub(0, m_acc); + m_icount -= 3; + next_inst(); + break; + + case inst_state::INCB_A: + m_acc = (m_acc & 0xff00) | do_incb(m_acc & 0x00ff); + m_icount -= 2; + next_inst(); + break; + + case inst_state::NEGB_A: + m_acc = (m_acc & 0xff00) | do_subb(0, m_acc & 0x00ff); + m_icount -= 3; + next_inst(); + break; + + case inst_state::CMPB_fix8_N8: + set_adr_fix8(m_fetch_byte); + m_icount -= 2; + m_state = inst_state::CMPB_obj_N8; + break; + + case inst_state::CMPB_off8_N8: + set_adr_off8(m_fetch_byte); + m_icount -= 2; + m_state = inst_state::CMPB_obj_N8; + break; + + case inst_state::MOVB_sfr8_N8: + set_adr_sfr8(m_fetch_byte); + m_icount -= 2; + m_state = inst_state::MOVB_obj_N8; + break; + + case inst_state::MOVB_off8_N8: + set_adr_off8(m_fetch_byte); + m_icount -= 2; + m_state = inst_state::MOVB_obj_N8; + break; + + case inst_state::RDD_SDD: + if (BIT(m_inst, 0)) + m_psw |= 0x1000; + else + m_psw &= 0xefff; + m_icount -= 2; + next_inst(); + break; + + case inst_state::DI_EI: + if (BIT(m_inst, 0)) + m_psw |= 0x0100; + else + m_psw &= 0xfeff; + m_icount -= 2; + next_inst(); + break; + + case inst_state::DEC_A: + m_acc = do_dec(m_acc); + m_icount -= 2; + next_inst(); + break; + + case inst_state::SWAP: + m_acc = swapendian_int16(m_acc); + m_icount -= 2; + next_inst(); + break; + + case inst_state::DECB_A: + m_acc = (m_acc & 0xff00) | do_decb(m_acc & 0x00ff); + m_icount -= 2; + next_inst(); + break; + + case inst_state::VCAL: + m_adr = m_ssp; + data_write_word(0, m_adr, m_pc - 1); + if (BIT(m_memscon, 1)) + { + m_adr -= 2; + data_write_word(0, m_adr, m_csr); + } + m_ssp = m_adr - 2; + m_csr = 0; + m_pc = 0x004a + (m_inst & 0x0f) * 2; + m_state = inst_state::J_Cadr; // hack + m_icount -= 3; + break; + + case inst_state::JGT_JLE: + if ((BIT(m_psw, 14) || BIT(m_psw, 15)) == BIT(m_inst, 2)) + { + m_pc += s8(m_fetch_byte); + m_icount -= 4; + } + else + m_icount -= 2; + m_state = inst_state::NOP; + break; + + case inst_state::JZ_JNZ: + if (BIT(m_psw, 14) != BIT(m_inst, 2)) + { + m_pc += s8(m_fetch_byte); + m_icount -= 4; + } + else + m_icount -= 2; + m_state = inst_state::NOP; + break; + + case inst_state::JCY_JNC: + if (BIT(m_psw, 15) != BIT(m_inst, 2)) + { + m_pc += s8(m_fetch_byte); + m_icount -= 4; + } + else + m_icount -= 2; + m_state = inst_state::NOP; + break; + + case inst_state::JNS_JPS: + if (BIT(m_psw, 11) != BIT(m_inst, 2)) + { + m_pc += s8(m_fetch_byte); + m_icount -= 4; + } + else + m_icount -= 2; + m_state = inst_state::NOP; + break; + + case inst_state::L_A_N16: + m_tmp[0] = m_fetch_byte; + m_icount -= 2; + m_state = inst_state::L_A_N16_2; + break; + + case inst_state::L_A_N16_2: + m_tmp[0] |= m_fetch_byte << 8; + m_icount -= 2; + m_state = inst_state::L_A_N16_3; + break; + + case inst_state::L_A_N16_3: + acc_load_word(m_tmp[0]); + m_icount -= 2; + next_inst(); + break; + + case inst_state::LB_A_N8: + m_tmp[0] = m_fetch_byte; + m_icount -= 2; + m_state = inst_state::LB_A_N8_2; + break; + + case inst_state::LB_A_N8_2: + acc_load_byte(m_tmp[0]); + m_icount -= 2; + next_inst(); + break; + + case inst_state::CLR_A: + acc_load_word(0); + m_icount -= 2; + next_inst(); + break; + + case inst_state::CLRB_A: + acc_load_byte(0); + m_icount -= 2; + next_inst(); + break; + + case inst_state::EXTND: + if (BIT(m_acc, 7)) + { + m_acc |= 0xff00; + m_psw |= 0x2000; + } + else + { + m_acc &= 0x00ff; + m_psw &= 0xdfff; + } + m_psw |= 0x1000; + m_icount -= 2; + next_inst(); + break; + + case inst_state::CPL_C: + m_psw ^= 0x8000; + m_icount -= 2; + next_inst(); + break; + + case inst_state::CAL_Cadr: + m_tmp[0] = m_fetch_byte; + m_icount -= 2; + m_state = inst_state::CAL_Cadr_2; + break; + + case inst_state::CAL_Cadr_2: + m_tmp[0] |= m_fetch_byte << 8; + m_adr = m_ssp; + m_seg = 0; + m_ssp -= 2; + std::swap(m_pc, m_tmp[0]); + m_icount -= 5; + m_state = inst_state::store_word; + break; + + case inst_state::BRK: + reset(); // hacky method of performing a "software system reset" + m_pc = 0x0002; + m_icount -= 2; + m_state = inst_state::J_Cadr; + break; + + case inst_state::RB_SB_obj_bit: + m_tmp[0] = data_read_byte(m_seg, m_adr); + if (BIT(m_tmp[0], m_inst & 0x07)) + m_psw &= 0xbfff; + else + m_psw |= 0x4000; + if (BIT(m_inst, 3)) + m_tmp[0] |= 1 << (m_inst & 0x07); + else + m_tmp[0] &= ~(1 << (m_inst & 0x07)); + m_icount -= 3; + next_inst_and_store_byte(m_tmp[0]); + break; + + case inst_state::MB_C_obj_bit: + m_tmp[0] = data_read_byte(m_seg, m_adr); + if (BIT(m_tmp[0], m_inst & 0x07)) + m_psw |= 0x8000; + else + m_psw &= 0x7fff; + m_icount -= 3; + next_inst(); + break; + + case inst_state::MB_obj_bit_C: + m_tmp[0] = data_read_byte(m_seg, m_adr); + if (BIT(m_psw, 15)) + m_tmp[0] |= 1 << (m_inst & 0x07); + else + m_tmp[0] &= ~(1 << (m_inst & 0x07)); + m_icount -= 3; + next_inst_and_store_byte(m_tmp[0]); + break; + + case inst_state::JBR_JBS_obj_bit: + m_tmp[0] = data_read_byte(m_seg, m_adr); + if (BIT(m_tmp[0], m_inst & 0x07) == BIT(m_inst, 3)) + { + m_pc += s8(m_fetch_byte); + m_icount -= 6; + } + else + m_icount -= 2; + m_state = inst_state::NOP; + break; + + case inst_state::JBRS_JBSR_obj_bit: + m_tmp[0] = data_read_byte(m_seg, m_adr); + if (BIT(m_tmp[0], m_inst & 0x07) == BIT(m_inst, 3)) + { + m_tmp[0] ^= 1 << (m_inst & 0x07); + m_pc += s8(m_fetch_byte); + m_icount -= 8; + m_state = inst_state::store_byte; + } + else + { + m_icount -= 2; + m_state = inst_state::NOP; + } + break; + + case inst_state::BAND_C_obj_bit: + m_tmp[0] = data_read_byte(m_seg, m_adr); + if (BIT(m_tmp[0], m_inst & 0x07) == BIT(m_inst, 3)) + m_psw &= 0x7fff; + m_icount -= 3; + next_inst(); + break; + + case inst_state::BOR_C_obj_bit: + m_tmp[0] = data_read_byte(m_seg, m_adr); + if (BIT(m_tmp[0], m_inst & 0x07) != BIT(m_inst, 3)) + m_psw |= 0x8000; + m_icount -= 3; + next_inst(); + break; + + case inst_state::BXOR_C_obj_bit: + m_tmp[0] = data_read_byte(m_seg, m_adr); + if (BIT(m_tmp[0], m_inst & 0x07)) + m_psw ^= 0x8000; + m_icount -= 3; + next_inst(); + break; + + case inst_state::MOV_ERn_PRn_obj: + m_tmp[0] = data_read_word(m_seg, m_adr); + m_data_cache.write_word(BIT(m_inst, 2) ? addr_pr(m_inst) : addr_er(m_inst), m_tmp[0]); + m_icount -= 2; + next_inst(); + break; + + case inst_state::MOVB_Rn_obj: + m_tmp[0] = data_read_byte(m_seg, m_adr); + m_data_cache.write_byte(addr_lr(m_inst), m_tmp[0]); + m_icount -= 2; + next_inst(); + break; + + case inst_state::op16_obj_fix8: + m_tmp[1] = m_data_cache.read_word(0x0200 | m_fetch_byte); + m_icount -= 2; + m_state = (m_inst & 0x90) == 0x90 ? inst_state::CMP_obj1_obj2 : inst_state::op16_obj1_obj2; + break; + + case inst_state::op8_obj_fix8: + m_tmp[1] = m_data_cache.read_byte(0x0200 | m_fetch_byte); + m_icount -= 2; + m_state = (m_inst & 0x90) == 0x90 ? inst_state::CMPB_obj1_obj2 : inst_state::op8_obj1_obj2; + break; + + case inst_state::op16_obj_off8: + m_tmp[1] = data_read_word(get_seg((m_lrb & 0xff00) | m_fetch_byte), (m_lrb & 0xff00) | m_fetch_byte); + m_icount -= 2; + m_state = (m_inst & 0x90) == 0x90 ? inst_state::CMP_obj1_obj2 : inst_state::op16_obj1_obj2; + break; + + case inst_state::op8_obj_off8: + m_tmp[1] = data_read_byte(get_seg((m_lrb & 0xff00) | m_fetch_byte), (m_lrb & 0xff00) | m_fetch_byte); + m_icount -= 2; + m_state = (m_inst & 0x90) == 0x90 ? inst_state::CMPB_obj1_obj2 : inst_state::op8_obj1_obj2; + break; + + case inst_state::op16_obj_sfr8: + m_tmp[1] = data_read_word(0, m_fetch_byte); + m_icount -= 2; + m_state = (m_inst & 0x90) == 0x90 ? inst_state::CMP_obj1_obj2 : inst_state::op16_obj1_obj2; + break; + + case inst_state::op8_obj_sfr8: + m_tmp[1] = data_read_byte(0, m_fetch_byte); + m_icount -= 2; + m_state = (m_inst & 0x90) == 0x90 ? inst_state::CMPB_obj1_obj2 : inst_state::op8_obj1_obj2; + break; + + case inst_state::op16_obj1_obj2: + m_tmp[0] = data_read_word(m_seg, m_adr); + m_tmp[0] = do_aluop_word(m_tmp[0], m_tmp[1]); + m_icount -= 3; + next_inst_and_store_word(m_tmp[0]); + break; + + case inst_state::op8_obj1_obj2: + m_tmp[0] = data_read_byte(m_seg, m_adr); + m_tmp[0] = do_aluop_byte(m_tmp[0], m_tmp[1]); + m_icount -= 3; + next_inst_and_store_byte(m_tmp[0]); + break; + + case inst_state::op16_obj_N16: + m_tmp[0] = data_read_word(m_seg, m_adr); + m_tmp[1] = m_fetch_byte; + m_icount -= 2; + m_state = inst_state::op16_obj_N16_2; + break; + + case inst_state::op16_obj_N16_2: + m_tmp[1] |= m_fetch_byte << 8; + m_icount -= 2; + m_state = inst_state::op16_obj_N16_3; + break; + + case inst_state::op16_obj_N16_3: + m_tmp[0] = do_aluop_word(m_tmp[0], m_tmp[1]); + m_icount -= 2; + next_inst_and_store_word(m_tmp[0]); + break; + + case inst_state::op8_obj_N8: + m_tmp[0] = data_read_byte(m_seg, m_adr); + m_tmp[1] = m_fetch_byte; + m_icount -= 2; + m_state = inst_state::op8_obj_N8_2; + break; + + case inst_state::op8_obj_N8_2: + m_tmp[0] = do_aluop_byte(m_tmp[0], m_tmp[1]); + m_icount -= 2; + next_inst_and_store_byte(m_tmp[0]); + break; + + case inst_state::op16_obj_A: + m_tmp[0] = data_read_word(m_seg, m_adr); + m_tmp[0] = do_aluop_word(m_tmp[0], m_acc); + m_icount -= 2; + next_inst_and_store_word(m_tmp[0]); + break; + + case inst_state::op8_obj_A: + m_tmp[0] = data_read_byte(m_seg, m_adr); + m_tmp[0] = do_aluop_byte(m_tmp[0], m_acc & 0x00ff); + m_icount -= 2; + next_inst_and_store_byte(m_tmp[0]); + break; + + case inst_state::op16_A_obj: + m_acc = do_aluop_word(m_acc, data_read_word(m_seg, m_adr)); + m_icount -= 2; + next_inst(); + break; + + case inst_state::op8_A_obj: + m_acc = (m_acc & 0xff00) | do_aluop_byte(m_acc & 0x00ff, data_read_byte(m_seg, m_adr)); + m_icount -= 2; + next_inst(); + break; + + case inst_state::MOV_fix8_obj: + m_tmp[0] = data_read_word(m_seg, m_adr); + set_adr_fix8(m_fetch_byte); + m_icount -= 2; + m_state = inst_state::store_word; + break; + + case inst_state::MOV_off8_obj: + m_tmp[0] = data_read_word(m_seg, m_adr); + set_adr_off8(m_fetch_byte); + m_icount -= 2; + m_state = inst_state::store_word; + break; + + case inst_state::MOVB_fix8_obj: + m_tmp[0] = data_read_byte(m_seg, m_adr); + set_adr_fix8(m_fetch_byte); + m_icount -= 2; + m_state = inst_state::store_byte; + break; + + case inst_state::MOVB_off8_obj: + m_tmp[0] = data_read_byte(m_seg, m_adr); + set_adr_off8(m_fetch_byte); + m_icount -= 2; + m_state = inst_state::store_byte; + break; + + case inst_state::MOV_ind_PRn_obj: + m_tmp[0] = data_read_word(m_seg, m_adr); + m_adr = m_data_cache.read_word(addr_pr(m_inst)); + m_seg = get_seg(m_adr); + m_icount -= 4; + next_inst_and_store_word(m_tmp[0]); + break; + + case inst_state::MOV_ind_DP_post_obj: + m_tmp[0] = data_read_word(m_seg, m_adr); + m_tmp[1] = addr_pr(2); + m_adr = m_data_cache.read_word(m_tmp[1]); + m_seg = get_seg(m_adr); + m_data_cache.write_word(m_tmp[1], m_tmp[0] + (BIT(m_inst, 1) ? 2 : -2)); + m_icount -= 5; + next_inst_and_store_word(m_tmp[0]); + break; + + case inst_state::MOVB_ind_PRn_obj: + m_tmp[0] = data_read_byte(m_seg, m_adr); + m_adr = m_data_cache.read_word(addr_pr(m_inst)); + m_seg = get_seg(m_adr); + m_icount -= 4; + next_inst_and_store_byte(m_tmp[0]); + break; + + case inst_state::MOVB_ind_DP_post_obj: + m_tmp[0] = data_read_word(m_seg, m_adr); + m_tmp[1] = addr_pr(2); + m_adr = m_data_cache.read_word(m_tmp[1]); + m_seg = get_seg(m_adr); + m_data_cache.write_word(m_tmp[1], m_adr + (BIT(m_inst, 1) ? 1 : -1)); + m_icount -= 5; + next_inst_and_store_byte(m_tmp[0]); + break; + + case inst_state::SLL_obj: + m_tmp[0] = data_read_word(m_seg, m_adr); + m_psw &= 0x7fff; + for (int n = m_inst & 0x03; n >= 0; n--) + { + if (BIT(m_tmp[0], 15)) + m_psw |= 0x8000; + m_tmp[0] <<= 1; + --m_icount; + } + m_icount -= 2; + next_inst_and_store_word(m_tmp[0]); + break; + + case inst_state::SLLB_obj: + m_tmp[0] = data_read_byte(m_seg, m_adr); + m_psw &= 0x7fff; + for (int n = m_inst & 0x03; n >= 0; n--) + { + if (BIT(m_tmp[0], 7)) + m_psw |= 0x8000; + m_tmp[0] <<= 1; + --m_icount; + } + m_icount -= 2; + next_inst_and_store_byte(m_tmp[0]); + break; + + case inst_state::CMP_obj1_obj2: + m_tmp[0] = data_read_word(m_seg, m_adr); + (void)do_sub(m_tmp[0], m_tmp[1]); + m_icount -= 2; + next_inst(); + break; + + case inst_state::CMPB_obj1_obj2: + m_tmp[0] = data_read_byte(m_seg, m_adr); + (void)do_subb(m_tmp[0], m_tmp[1]); + m_icount -= 2; + next_inst(); + break; + + case inst_state::CMP_obj_N16: + m_tmp[0] = data_read_word(m_seg, m_adr); + m_tmp[1] = m_fetch_byte; + m_icount -= 2; + m_state = inst_state::CMP_obj_N16_2; + break; + + case inst_state::CMP_obj_N16_2: + m_tmp[1] |= m_fetch_byte << 8; + m_icount -= 2; + m_state = inst_state::CMP_obj_N16_3; + break; + + case inst_state::CMP_obj_N16_3: + (void)do_sub(m_tmp[0], m_tmp[1]); + m_icount -= 2; + next_inst(); + break; + + case inst_state::CMPB_obj_N8: + m_tmp[0] = data_read_byte(m_seg, m_adr); + m_tmp[1] = m_fetch_byte; + m_icount -= 2; + m_state = inst_state::CMPB_obj_N8_2; + break; + + case inst_state::CMPB_obj_N8_2: + (void)do_subb(m_tmp[0], m_tmp[1]); + m_icount -= 2; + next_inst(); + break; + + case inst_state::CMP_obj_A: + m_tmp[0] = data_read_word(m_seg, m_adr); + (void)do_sub(m_tmp[0], m_acc); + m_icount -= 2; + next_inst(); + break; + + case inst_state::CMPB_obj_A: + m_tmp[0] = data_read_byte(m_seg, m_adr); + (void)do_subb(m_tmp[0], m_acc & 0x00ff); + m_icount -= 2; + next_inst(); + break; + + case inst_state::MOV_sfr8_obj: + m_tmp[0] = data_read_word(m_seg, m_adr); + set_adr_sfr8(m_fetch_byte); + m_icount -= 2; + m_state = inst_state::store_word; + break; + + case inst_state::MOV_A_obj: + m_acc = data_read_word(m_seg, m_adr); + m_icount -= 2; + next_inst(); + break; + + case inst_state::MOVB_sfr8_obj: + m_tmp[0] = data_read_byte(m_seg, m_adr); + set_adr_sfr8(m_fetch_byte); + m_icount -= 2; + m_state = inst_state::store_byte; + break; + + case inst_state::MOVB_A_obj: + m_acc = (m_acc & 0xff00) | data_read_byte(m_seg, m_adr); + m_icount -= 2; + next_inst(); + break; + + case inst_state::MOV_D16_PRn_obj: + m_tmp[0] = data_read_word(m_seg, m_adr); + m_tmp[1] = m_fetch_byte; + m_icount -= 2; + m_state = inst_state::MOV_dir_obj_2; + break; + + case inst_state::MOV_D16_PRn_obj_2: + m_adr = (m_fetch_byte << 8 | m_tmp[1]) + m_data_cache.read_word(addr_pr(m_inst)); + m_seg = get_seg(m_adr); + m_icount -= 2; + m_state = inst_state::store_word; + break; + + case inst_state::MOVB_D16_PRn_obj: + m_tmp[0] = data_read_byte(m_seg, m_adr); + m_tmp[1] = m_fetch_byte; + m_icount -= 2; + m_state = inst_state::MOV_dir_obj_2; + break; + + case inst_state::MOVB_D16_PRn_obj_2: + m_adr = (m_fetch_byte << 8 | m_tmp[1]) + m_data_cache.read_word(addr_pr(m_inst)); + m_seg = get_seg(m_adr); + m_icount -= 2; + m_state = inst_state::store_byte; + break; + + case inst_state::MOV_n7_ind_PR_obj: + m_tmp[0] = data_read_word(m_seg, m_adr); + m_adr = m_data_cache.read_word(addr_pr(2 + BIT(m_fetch_byte, 7))) + util::sext(m_fetch_byte, 7); + m_seg = get_seg(m_adr); + m_icount -= 4; + m_state = inst_state::store_word; + break; + + case inst_state::MOVB_n7_ind_PR_obj: + m_tmp[0] = data_read_byte(m_seg, m_adr); + m_adr = m_data_cache.read_word(addr_pr(2 + BIT(m_fetch_byte, 7))) + util::sext(m_fetch_byte, 7); + m_seg = get_seg(m_adr); + m_icount -= 4; + m_state = inst_state::store_byte; + break; + + case inst_state::MOV_dir_obj: + m_tmp[0] = data_read_word(m_seg, m_adr); + m_tmp[1] = m_fetch_byte; + m_icount -= 2; + m_state = inst_state::MOV_dir_obj_2; + break; + + case inst_state::MOV_dir_obj_2: + m_adr = m_fetch_byte << 8 | m_tmp[1]; + m_seg = get_seg(m_adr); + m_icount -= 2; + m_state = inst_state::store_word; + break; + + case inst_state::MOVB_dir_obj: + m_tmp[0] = data_read_byte(m_seg, m_adr); + m_tmp[1] = m_fetch_byte; + m_icount -= 2; + m_state = inst_state::MOVB_dir_obj_2; + break; + + case inst_state::MOVB_dir_obj_2: + m_adr = m_fetch_byte << 8 | m_tmp[1]; + m_seg = get_seg(m_adr); + m_icount -= 2; + m_state = inst_state::store_byte; + break; + + case inst_state::SRL_obj: + m_tmp[0] = data_read_word(m_seg, m_adr); + for (int n = m_inst & 0x03; n >= 0; n--) + { + if (BIT(m_tmp[0], 0)) + m_psw |= 0x8000; + else + m_psw &= 0x7fff; + m_tmp[0] >>= 1; + --m_icount; + } + m_icount -= 2; + next_inst_and_store_word(m_tmp[0]); + break; + + case inst_state::SRLB_obj: + m_tmp[0] = data_read_byte(m_seg, m_adr); + for (int n = m_inst & 0x03; n >= 0; n--) + { + if (BIT(m_tmp[0], 0)) + m_psw |= 0x8000; + else + m_psw &= 0x7fff; + m_tmp[0] >>= 1; + --m_icount; + } + m_icount -= 2; + next_inst_and_store_byte(m_tmp[0]); + break; + + case inst_state::TJNZ_TJZ: + m_tmp[0] = data_read_word(m_seg, m_adr); + if (BIT(m_inst, 0) ? m_tmp[0] == 0 : m_tmp[0] != 0) + { + m_pc += s8(m_fetch_byte); + m_icount -= 4; + } + else + m_icount -= 2; + m_state = inst_state::NOP; + break; + + case inst_state::TJNZB_TJZB: + m_tmp[0] = data_read_byte(m_seg, m_adr); + if (BIT(m_inst, 0) ? m_tmp[0] == 0 : m_tmp[0] != 0) + { + m_pc += s8(m_fetch_byte); + m_icount -= 4; + } + else + m_icount -= 2; + m_state = inst_state::NOP; + break; + + case inst_state::DIV_obj: + m_tmp[0] = data_read_word(m_seg, m_adr); + do_div(m_tmp[0]); + m_icount -= 42; + next_inst(); + break; + + case inst_state::DIVB_obj: + m_tmp[0] = data_read_byte(m_seg, m_adr); + do_divb(m_tmp[0]); + m_icount -= 22; + next_inst(); + break; + + case inst_state::MUL_obj: + m_tmp[0] = data_read_word(m_seg, m_adr); + do_mul(m_tmp[0]); + m_icount -= 21; // TODO: 3 if high-speed multiplier provided + next_inst(); + break; + + case inst_state::MULB_obj: + m_tmp[0] = data_read_byte(m_seg, m_adr); + m_acc = (m_acc & 0x00ff) * m_tmp[0]; + if (m_acc == 0) + m_psw |= 0x4000; + else + m_psw &= 0xbfff; + m_icount -= 12; // TODO: 2 if high-speed multiplier provided + next_inst(); + break; + + case inst_state::MOV_obj_A: + m_icount -= 2; + next_inst_and_store_word(m_acc); + break; + + case inst_state::MOV_obj_N16: + m_tmp[0] = m_fetch_byte; + m_icount -= 2; + m_state = inst_state::MOV_obj_N16_2; + break; + + case inst_state::MOV_obj_N16_2: + m_tmp[0] |= m_fetch_byte << 8; + m_icount -= 2; + m_state = inst_state::store_word; + break; + + case inst_state::MOVB_obj_A: + m_icount -= 2; + next_inst_and_store_byte(m_acc & 0x00ff); + break; + + case inst_state::MOVB_obj_N8: + m_tmp[0] = m_fetch_byte; + m_icount -= 2; + m_state = inst_state::store_byte; + break; + + case inst_state::ROL_ROR_obj: + m_tmp[0] = data_read_word(m_seg, m_adr); + for (int n = m_inst & 0x03; n >= 0; n--) + { + m_tmp[0] = BIT(m_inst, 4) ? do_ror(m_tmp[0]) : do_rol(m_tmp[0]); + --m_icount; + } + m_icount -= 2; + next_inst_and_store_word(m_tmp[0]); + break; + + case inst_state::ROLB_RORB_obj: + m_tmp[0] = data_read_byte(m_seg, m_adr); + for (int n = m_inst & 0x03; n >= 0; n--) + { + m_tmp[0] = BIT(m_inst, 4) ? do_rorb(m_tmp[0]) : do_rolb(m_tmp[0]); + --m_icount; + } + m_icount -= 2; + next_inst_and_store_byte(m_tmp[0]); + break; + + case inst_state::CMPC_LC_A_Tadr: + m_tmp[0] = m_fetch_byte; + m_icount -= 2; + m_state = inst_state::CMPC_LC_A_Tadr_2; + break; + + case inst_state::CMPC_LC_A_Tadr_2: + m_tmp[0] |= m_fetch_byte << 8; + m_icount -= 2; + m_state = BIT(m_inst, 0) ? inst_state::LC_A_obj_3 : inst_state::CMPC_A_obj_3; + break; + + case inst_state::CMPCB_LCB_A_Tadr: + m_tmp[0] = m_fetch_byte; + m_icount -= 2; + m_state = inst_state::CMPCB_LCB_A_Tadr_2; + break; + + case inst_state::CMPCB_LCB_A_Tadr_2: + m_tmp[0] |= m_fetch_byte << 8; + m_icount -= 2; + m_state = BIT(m_inst, 0) ? inst_state::LCB_A_obj_3 : inst_state::CMPCB_A_obj_3; + break; + + case inst_state::SBR_RBR_obj: + m_adr += (m_acc & 0x00f8) >> 3; + m_tmp[0] = data_read_byte(m_seg, m_adr); + if (BIT(m_tmp[0], m_acc & 0x0007)) + m_psw &= 0xbfff; + else + m_psw |= 0x4000; + if (BIT(m_inst, 0)) + m_tmp[0] &= ~(1 << (m_acc & 0x0007)); + else + m_tmp[0] |= 1 << (m_acc & 0x0007); + m_icount -= 5; + next_inst_and_store_byte(m_tmp[0]); + break; + + case inst_state::MBR_C_obj: + m_adr += (m_acc & 0x00f8) >> 3; + m_tmp[0] = data_read_byte(m_seg, m_adr); + if (BIT(m_tmp[0], m_acc & 0x0007)) + m_psw |= 0x8000; + else + m_psw &= 0x7fff; + m_icount -= 6; + next_inst(); + break; + + case inst_state::MBR_obj_C: + m_adr += (m_acc & 0x00f8) >> 3; + m_tmp[0] = data_read_byte(m_seg, m_adr); + if (BIT(m_psw, 15)) + m_tmp[0] |= 1 << (m_acc & 0x0007); + else + m_tmp[0] &= ~(1 << (m_acc & 0x0007)); + m_icount -= 5; + next_inst_and_store_byte(m_tmp[0]); + break; + + case inst_state::INC_DEC_obj: + m_tmp[0] = data_read_word(m_seg, m_adr); + if (BIT(m_inst, 4)) + m_tmp[0] = do_dec(m_tmp[0]); + else + m_tmp[0] = do_inc(m_tmp[0]); + m_icount -= 2; + next_inst_and_store_word(m_tmp[0]); + break; + + case inst_state::CLR_FILL_obj: + m_tmp[0] = BIT(m_inst, 4) ? 0xffff : 0; + m_icount -= 2; + next_inst_and_store_word(m_tmp[0]); + break; + + case inst_state::XCHG_A_obj: + m_tmp[1] = data_read_word(m_seg, m_adr); + m_tmp[0] = m_acc; + m_acc = m_tmp[1]; + m_icount -= 3; + next_inst_and_store_word(m_tmp[0]); + break; + + case inst_state::TBR_obj: + m_adr += (m_acc & 0x00f8) >> 3; + m_tmp[0] = data_read_byte(m_seg, m_adr); + if (BIT(m_tmp[0], m_acc & 0x0007)) + m_psw &= 0xbfff; + else + m_psw |= 0x4000; + m_icount -= 5; + next_inst(); + break; + + case inst_state::J_ind_obj: + m_pc = data_read_word(m_seg, m_adr); + m_icount -= 2; + m_state = inst_state::NOP; + break; + + case inst_state::CMPC_LC_A_ind_obj: + m_tmp[0] = data_read_word(m_seg, m_adr); + m_tmp[1] = data_read_word(0x8000 | m_tsr, m_tmp[0]); + if (BIT(m_inst, 1)) + { + m_acc = m_tmp[1]; + if (m_tmp[1] == 0) + m_psw |= 0x4000; + else + m_psw &= 0xbfff; + } + else + (void)do_sub(m_acc, m_tmp[1]); + m_icount -= 9; + next_inst(); + break; + + case inst_state::CMPCB_LCB_A_ind_obj: + m_tmp[0] = data_read_word(m_seg, m_adr); + m_tmp[1] = data_read_byte(0x8000 | m_tsr, m_tmp[0]); + m_acc = (m_acc & 0xff00) | m_tmp[1]; + if (BIT(m_inst, 1)) + { + if (m_tmp[1] == 0) + m_psw |= 0x4000; + else + m_psw &= 0xbfff; + } + else + (void)do_subb(m_acc & 0x00ff, m_tmp[1]); + m_icount -= 6; + next_inst(); + break; + + case inst_state::CMPC_LC_A_T16_obj: + m_tmp[0] = data_read_word(m_seg, m_adr); + m_tmp[1] = m_fetch_byte; + m_icount -= 2; + m_state = inst_state::CMPC_LC_A_T16_obj_2; + break; + + case inst_state::CMPC_LC_A_T16_obj_2: + m_tmp[0] += m_fetch_byte << 8 | m_tmp[1]; + m_icount -= 2; + if (BIT(m_inst, 4)) + m_state = BIT(m_inst, 1) ? inst_state::LCB_A_obj_3 : inst_state::CMPCB_A_obj_3; + else + m_state = BIT(m_inst, 1) ? inst_state::LC_A_obj_3 : inst_state::CMPC_A_obj_3; + break; + + case inst_state::CMPC_A_obj_3: + m_tmp[1] = data_read_word(0x8000 | m_tsr, m_tmp[0]); + (void)do_sub(m_acc, m_tmp[1]); + m_icount -= 9; + next_inst(); + break; + + case inst_state::CMPCB_A_obj_3: + m_tmp[1] = data_read_byte(0x8000 | m_tsr, m_tmp[0]); + (void)do_subb(m_acc & 0x00ff, m_tmp[1]); + m_icount -= 6; + next_inst(); + break; + + case inst_state::LC_A_obj_3: + m_tmp[1] = data_read_word(0x8000 | m_tsr, m_tmp[0]); + m_acc = m_tmp[1]; + if (m_tmp[1] == 0) + m_psw |= 0x4000; + else + m_psw &= 0xbfff; + m_icount -= 9; + next_inst(); + break; + + case inst_state::LCB_A_obj_3: + m_tmp[1] = data_read_byte(0x8000 | m_tsr, m_tmp[0]); + m_acc = (m_acc & 0xff00) | m_tmp[1]; + if (m_tmp[1] == 0) + m_psw |= 0x4000; + else + m_psw &= 0xbfff; + m_icount -= 6; + next_inst(); + break; + + case inst_state::INCB_DECB_obj: + m_tmp[0] = data_read_byte(m_seg, m_adr); + if (BIT(m_inst, 4)) + m_tmp[0] = do_decb(m_tmp[0]); + else + m_tmp[0] = do_incb(m_tmp[0]); + m_icount -= 2; + next_inst_and_store_byte(m_tmp[0]); + break; + + case inst_state::CLRB_FILLB_obj: + m_tmp[0] = BIT(m_inst, 4) ? 0xff : 0; + m_icount -= 2; + next_inst_and_store_byte(m_tmp[0]); + break; + + case inst_state::XCHGB_A_obj: + m_tmp[1] = data_read_byte(m_seg, m_adr); + m_tmp[0] = m_acc & 0x00ff; + m_acc = (m_acc & 0xff00) | m_tmp[1]; + m_icount -= 3; + next_inst_and_store_byte(m_tmp[0]); + break; + + case inst_state::DJNZ_obj: + m_tmp[0] = data_read_byte(m_seg, m_adr); + --m_tmp[0]; + if (m_tmp[0] != 0) + { + m_pc += s8(m_fetch_byte); + m_icount -= 6; + } + else + m_icount -= 3; + m_state = inst_state::store_byte; + break; + + case inst_state::CAL_ind_obj: + m_tmp[0] = m_pc - 1; + m_pc = data_read_word(m_seg, m_adr); + m_adr = m_ssp; + m_seg = 0; + m_ssp -= 2; + m_icount -= 3; + m_state = inst_state::store_word; + break; + + case inst_state::SRA_obj: + m_tmp[0] = data_read_word(m_seg, m_adr); + for (int n = m_inst & 0x03; n >= 0; n--) + { + if (BIT(m_tmp[0], 0)) + m_psw |= 0x8000; + else + m_psw &= 0x7fff; + m_tmp[0] = (m_tmp[0] & 0x8000) | m_tmp[0] >> 1; + --m_icount; + } + m_icount -= 2; + next_inst_and_store_word(m_tmp[0]); + break; + + case inst_state::SRAB_obj: + m_tmp[0] = data_read_byte(m_seg, m_adr); + for (int n = m_inst & 0x03; n >= 0; n--) + { + if (BIT(m_tmp[0], 0)) + m_psw |= 0x8000; + else + m_psw &= 0x7fff; + m_tmp[0] = (m_tmp[0] & 0x80) | m_tmp[0] >> 1; + --m_icount; + } + m_icount -= 2; + next_inst_and_store_byte(m_tmp[0]); + break; + + case inst_state::MOV_obj_ind_X1_A: + m_tmp[1] = m_data_cache.read_word(addr_pr(0)); + m_tmp[1] += m_acc & 0x00ff; + m_tmp[0] = data_read_word(get_seg(m_tmp[1]), m_tmp[1]); + m_icount -= 6; + next_inst_and_store_word(m_tmp[0]); + break; + + case inst_state::MOV_obj_ind_X1_R0: + m_tmp[1] = m_data_cache.read_word(addr_pr(0)); + m_tmp[1] += m_data_cache.read_byte(addr_lr(0)); + m_tmp[0] = data_read_word(get_seg(m_tmp[1]), m_tmp[1]); + m_icount -= 6; + next_inst_and_store_byte(m_tmp[0]); + break; + + case inst_state::MOVB_obj_ind_X1_A: + m_tmp[1] = m_data_cache.read_word(addr_pr(0)); + m_tmp[1] += m_acc & 0x00ff; + m_tmp[0] = data_read_word(get_seg(m_tmp[1]), m_tmp[1]); + m_icount -= 6; + next_inst_and_store_word(m_tmp[0]); + break; + + case inst_state::MOVB_obj_ind_X1_R0: + m_tmp[1] = m_data_cache.read_word(addr_pr(0)); + m_tmp[1] += m_data_cache.read_byte(addr_lr(0)); + m_tmp[0] = data_read_byte(get_seg(m_tmp[1]), m_tmp[1]); + m_icount -= 6; + next_inst_and_store_byte(m_tmp[0]); + break; + + case inst_state::FJ: + if (!BIT(m_memscon, 1)) + { + m_state = inst_state::illegal; + break; + } + m_tmp[0] = m_fetch_byte; + m_icount -= 2; + m_state = inst_state::FJ_2; + break; + + case inst_state::FJ_2: + m_tmp[0] |= m_fetch_byte << 8; + m_icount -= 2; + m_state = inst_state::FJ_3; + break; + + case inst_state::FJ_3: + m_csr = m_fetch_byte & 0x0f; + m_pc = m_tmp[0]; + m_icount -= 3; + m_state = inst_state::NOP; + break; + + case inst_state::DIVQ_obj: + m_tmp[0] = data_read_word(m_seg, m_adr); + do_divq(m_tmp[0]); + m_icount -= 42; + next_inst(); + break; + + case inst_state::JLTS_JGES: + if ((BIT(m_psw, 9) != BIT(m_psw, 11)) != BIT(m_inst, 1)) + { + m_pc += s8(m_fetch_byte); + m_icount -= 6; + } + else + m_icount -= 2; + m_state = inst_state::NOP; + break; + + case inst_state::JLES_JGTS: + if (((BIT(m_psw, 9) != BIT(m_psw, 11)) || BIT(m_psw, 14)) != BIT(m_inst, 1)) + { + m_pc += s8(m_fetch_byte); + m_icount -= 6; + } + else + m_icount -= 2; + m_state = inst_state::NOP; + break; + + case inst_state::illegal: + logerror("%06X: Illegal prefixed opcode %02X encountered\n", m_ppc, m_inst); + reset(); + m_pc = 0x0006; + m_icount -= 2; + m_state = inst_state::J_Cadr; + break; + } + } + while (m_icount > 0); } @@ -258,7 +3268,7 @@ void msm665xx_device::state_string_export(const device_state_entry &entry, std:: BIT(m_psw, 15) ? 'C' : '.', BIT(m_psw, 14) ? 'Z' : '.', BIT(m_psw, 13) ? 'H' : '.', - BIT(m_psw, 12) ? 'D' : '.', + BIT(m_psw, 12) ? 'D' : 'd', BIT(m_psw, 11) ? 'S' : '.', BIT(m_psw, 10) ? 'P' : '.', BIT(m_psw, 9) ? 'V' : '.', diff --git a/src/devices/cpu/olms66k/msm665xx.h b/src/devices/cpu/olms66k/msm665xx.h index 5ca435e6385..a4132aea6fb 100644 --- a/src/devices/cpu/olms66k/msm665xx.h +++ b/src/devices/cpu/olms66k/msm665xx.h @@ -39,6 +39,8 @@ protected: virtual std::unique_ptr create_disassembler() override; virtual void execute_run() override; + virtual u32 execute_min_cycles() const noexcept override { return 2; } + virtual u32 execute_max_cycles() const noexcept override { return 42; } virtual space_config_vector memory_space_config() const override; @@ -63,6 +65,93 @@ protected: void memscon_w(u8 data); private: + u16 addr_lr(u8 n) const noexcept { return 0x0200 + (n & 7) + (m_lrb & 0x00ff) * 8; } + u16 addr_er(u8 n) const noexcept { return 0x0200 + (n & 3) * 2 + (m_lrb & 0x00ff) * 8; } + u16 addr_pr(u8 n) const noexcept { return 0x0200 + (n & 3) * 2 + (m_psw & 0x0007) * 8; } + + void set_adr_fix8(u8 fix8) noexcept { m_adr = 0x0200 | fix8; m_seg = 0; } + void set_adr_off8(u8 off8) noexcept { m_adr = (m_lrb & 0xff00) | off8; m_seg = get_seg(m_adr); } + void set_adr_sfr8(u8 sfr8) noexcept { m_adr = sfr8; m_seg = 0; } + + u16 get_seg(u16 addr) const noexcept; + + u8 data_read_byte(u16 seg, u16 adr) { return s16(seg) < 0 ? m_program_space.read_byte(u32(seg) << 16 | adr) : m_data_space.read_byte(u32(seg) << 16 | adr); } + u16 data_read_word(u16 seg, u16 adr) { return s16(seg) < 0 ? m_program_space.read_word_unaligned(u32(seg) << 16 | adr) : m_data_space.read_word(u32(seg) << 16 | adr); } + void data_write_byte(u16 seg, u16 adr, u8 data) { m_data_space.write_byte(u32(seg) << 16 | adr, data); } + void data_write_word(u16 seg, u16 adr, u16 data) { m_data_space.write_word(u32(seg) << 16 | adr, data); } + + void next_inst() { m_inst = m_fetch_byte; m_state = s_inst_decode[BIT(m_psw, 12)][m_inst]; m_ppc = u32(m_csr) << 16 | u16(m_pc - 1); debugger_instruction_hook(m_ppc); } + void next_inst_and_store_byte(u8 data) { m_inst = m_fetch_byte; m_state = s_inst_decode[BIT(m_psw, 12)][m_inst]; data_write_byte(m_seg, m_adr, data); m_ppc = u32(m_csr) << 16 | u16(m_pc - 1); debugger_instruction_hook(m_ppc); } + void next_inst_and_store_word(u16 data) { m_inst = m_fetch_byte; m_state = s_inst_decode[BIT(m_psw, 12)][m_inst]; data_write_word(m_seg, m_adr, data); m_ppc = u32(m_csr) << 16 | u16(m_pc - 1); debugger_instruction_hook(m_ppc); } + void prefetch() { m_fetch_byte = m_program_cache.read_byte(u32(m_csr) << 16 | m_pc); ++m_pc; } + + void acc_load_byte(u8 data) noexcept + { + m_acc = (m_acc & 0xff00) | data; + if (data == 0) + m_psw |= 0x4000; + else + m_psw &= 0xbfff; + m_psw &= 0xefff; + } + + void acc_load_word(u16 data) noexcept + { + m_acc = data; + if (data == 0) + m_psw |= 0x4000; + else + m_psw &= 0xbfff; + m_psw |= 0x1000; + } + + void setzs_byte(u8 data) noexcept + { + if (data == 0) + m_psw |= 0x4000; + else + m_psw &= 0xbfff; + if (s8(data) < 0) + m_psw |= 0x0800; + else + m_psw &= 0xf7ff; + } + + void setzs_word(u16 data) noexcept + { + if (data == 0) + m_psw |= 0x4000; + else + m_psw &= 0xbfff; + if (s16(data) < 0) + m_psw |= 0x0800; + else + m_psw &= 0xf7ff; + } + + u16 do_add(u16 n1, u16 n2, bool c = false) noexcept; + u8 do_addb(u8 n1, u8 n2, bool c = false) noexcept; + u16 do_sub(u16 n1, u16 n2, bool c = false) noexcept; + u8 do_subb(u8 n1, u8 n2, bool c = false) noexcept; + u16 do_aluop_word(u16 n1, u16 n2) noexcept; + u8 do_aluop_byte(u8 n1, u8 n2) noexcept; + u16 do_inc(u16 n) noexcept; + u8 do_incb(u8 n) noexcept; + u16 do_dec(u16 n) noexcept; + u8 do_decb(u8 n) noexcept; + u16 do_rol(u16 n) noexcept; + u8 do_rolb(u8 n) noexcept; + u16 do_ror(u16 n) noexcept; + u8 do_rorb(u8 n) noexcept; + void do_mul(u16 n) noexcept; + void do_div(u16 n) noexcept; + void do_divb(u8 n) noexcept; + void do_divq(u16 n) noexcept; + + enum class inst_state : u8; + static const inst_state s_inst_decode[2][0x100]; + static const inst_state s_prefixed_inst_decode[2][0x100]; + address_space_config m_program_config; address_space_config m_data_config; memory_access<20, 0, 0, ENDIANNESS_LITTLE>::cache m_program_cache; @@ -81,6 +170,13 @@ private: u8 m_tsr; u8 m_romwin; u8 m_memscon; + + inst_state m_state; + u8 m_inst; + u8 m_fetch_byte; + u16 m_adr; + u16 m_seg; + u16 m_tmp[2]; s32 m_icount; };