diff --git a/src/emu/cpu/sm510/sm510.c b/src/emu/cpu/sm510/sm510.c index ce84fba789c..c91f152fa77 100644 --- a/src/emu/cpu/sm510/sm510.c +++ b/src/emu/cpu/sm510/sm510.c @@ -47,23 +47,6 @@ sm510_device::sm510_device(const machine_config &mconfig, const char *tag, devic // disasm -void sm510_base_device::state_string_export(const device_state_entry &entry, std::string &str) -{ - #if 0 - switch (entry.index()) - { - case STATE_GENFLAGS: - strprintf(str, "%c%c", - m_c ? 'C':'c', - m_s ? 'S':'s' - ); - break; - - default: break; - } - #endif -} - offs_t sm510_base_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options) { extern CPU_DISASSEMBLE(sm510); @@ -124,7 +107,7 @@ void sm510_base_device::device_start() state_add(SM510_BM, "BM", m_bm).formatstr("%01X"); state_add(STATE_GENPC, "curpc", m_pc).formatstr("%04X").noshow(); - state_add(STATE_GENFLAGS, "GENFLAGS", m_pc).formatstr("%2s").noshow(); + state_add(STATE_GENFLAGS, "GENFLAGS", m_c).formatstr("%1s").noshow(); m_icountptr = &m_icount; } @@ -137,7 +120,10 @@ void sm510_base_device::device_start() void sm510_base_device::device_reset() { - m_pc = 0x37 << 6; + m_skip = false; + m_op = m_prev_op = 0; + do_branch(3, 7, 0); + m_prev_pc = m_pc; } @@ -156,10 +142,10 @@ inline void sm510_base_device::increment_pc() void sm510_base_device::get_opcode_param() { - // LBL, TL, TML, TM opcodes are 2 bytes - if (m_op == 0x5f || (m_op & 0xf0) == 0x70 || m_op >= 0xc0) + // LBL, TL, TML opcodes are 2 bytes + if (m_op == 0x5f || (m_op & 0xf0) == 0x70) { - m_icount -= 2; // guessed + m_icount--; m_param = m_program->read_byte(m_pc); increment_pc(); } @@ -175,12 +161,19 @@ void sm510_base_device::execute_run() // fetch next opcode debugger_instruction_hook(this, m_pc); - m_icount -= 2; // 61us typical + m_icount--; m_op = m_program->read_byte(m_pc); increment_pc(); get_opcode_param(); - // handle opcode + // handle opcode if it's not skipped + if (m_skip) + { + m_skip = false; + m_op = 0; // fake nop + } + else //execute_one(); + switch (m_op & 0xf0) { case 0x20: op_lax(); break; diff --git a/src/emu/cpu/sm510/sm510.h b/src/emu/cpu/sm510/sm510.h index ffb7e3561a1..379bc13c314 100644 --- a/src/emu/cpu/sm510/sm510.h +++ b/src/emu/cpu/sm510/sm510.h @@ -42,6 +42,8 @@ protected: virtual void device_reset(); // device_execute_interface overrides + virtual UINT64 execute_clocks_to_cycles(UINT64 clocks) const { return (clocks + 2 - 1) / 2; } // default 2 cycles per machine cycle + virtual UINT64 execute_cycles_to_clocks(UINT64 cycles) const { return (cycles * 2); } // " virtual UINT32 execute_min_cycles() const { return 1; } virtual UINT32 execute_max_cycles() const { return 2; } virtual UINT32 execute_input_lines() const { return 1; } @@ -55,7 +57,6 @@ protected: virtual UINT32 disasm_min_opcode_bytes() const { return 1; } virtual UINT32 disasm_max_opcode_bytes() const { return 2; } virtual offs_t disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options); - void state_string_export(const device_state_entry &entry, std::string &str); address_space_config m_program_config; address_space_config m_data_config; @@ -93,6 +94,8 @@ protected: void ram_w(UINT8 data); void pop_stack(); void push_stack(); + void do_branch(UINT8 pu, UINT8 pm, UINT8 pl); + UINT8 bitmask(UINT8 param); // opcode handlers void op_lb(); diff --git a/src/emu/cpu/sm510/sm510d.c b/src/emu/cpu/sm510/sm510d.c index 71d32fa332d..dffd5e1530c 100644 --- a/src/emu/cpu/sm510/sm510d.c +++ b/src/emu/cpu/sm510/sm510d.c @@ -40,7 +40,7 @@ static const UINT8 s_bits[] = { 0, 4, 8, 0, 0, 0, 0, - 0, 0, 0, 4+8, 2+8, 6+8, 6, + 0, 0, 0, 4+8, 2+8, 6, 6, 2, 0, 2, 2, 2, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, @@ -133,15 +133,11 @@ CPU_DISASSEMBLE(sm510) { dst += sprintf(dst, "$%02X", param); } - else if (instr == mTL || instr == mTML) + else { - UINT16 address = (param << 4 & 0xc00) | (mask << 6 & 0x3c0) | (param & 0x3f); + UINT16 address = (param << 4 & 0xc00) | (mask << 6 & 0x3c0) | (param & 0x03f); dst += sprintf(dst, "$%03X", address); } - else if (instr == mTM) - { - //todo - } } return len | s_flags[instr] | DASMFLAG_SUPPORTED; diff --git a/src/emu/cpu/sm510/sm510op.inc b/src/emu/cpu/sm510/sm510op.inc index d8e4368c4c2..b9583694849 100644 --- a/src/emu/cpu/sm510/sm510op.inc +++ b/src/emu/cpu/sm510/sm510op.inc @@ -7,13 +7,15 @@ inline UINT8 sm510_base_device::ram_r() { - UINT8 address = (m_bm << 4 | m_bl) & m_datamask; + int bmh = (m_prev_op == 0x02) ? (1 << (m_datawidth-1)) : 0; // from SBM + UINT8 address = (bmh | m_bm << 4 | m_bl) & m_datamask; return m_data->read_byte(address) & 0xf; } inline void sm510_base_device::ram_w(UINT8 data) { - UINT8 address = (m_bm << 4 | m_bl) & m_datamask; + int bmh = (m_prev_op == 0x02) ? (1 << (m_datawidth-1)) : 0; // from SBM + UINT8 address = (bmh | m_bm << 4 | m_bl) & m_datamask; m_data->write_byte(address, data & 0xf); } @@ -31,6 +33,18 @@ void sm510_base_device::push_stack() m_stack[0] = m_pc; } +inline void sm510_base_device::do_branch(UINT8 pu, UINT8 pm, UINT8 pl) +{ + // set new PC(Pu/Pm/Pl) + m_pc = ((pu << 10 & 0xc00) | (pm << 6 & 0x3c0) | (pl & 0x03f)) & m_prgmask; +} + +inline UINT8 sm510_base_device::bitmask(UINT8 param) +{ + // bitmask from immediate opcode param + return 1 << (param & 3); +} + // instruction set @@ -46,13 +60,14 @@ void sm510_base_device::op_lb() void sm510_base_device::op_lbl() { // LBL xy: load BM/BL with 8-bit immediate value - op_illegal(); + m_bl = m_param & 0xf; + m_bm = (m_param & m_datamask) >> 4; } void sm510_base_device::op_sbm() { - // SBM: set BM high bit for next opcode - op_illegal(); + // SBM: set BM high bit for next opcode - handled in ram_r/w + assert(m_op == 0x02); } void sm510_base_device::op_exbla() @@ -82,7 +97,7 @@ void sm510_base_device::op_decb() void sm510_base_device::op_atpl() { - // ATPL: load PC low bits with ACC + // ATPL: load Pl(PC low bits) with ACC m_pc = (m_pc & ~0xf) | m_acc; } @@ -99,29 +114,34 @@ void sm510_base_device::op_rtn1() m_skip = true; } +void sm510_base_device::op_t() +{ + // T xy: jump(transfer) within current page + m_pc = (m_pc & ~0x3f) | (m_op & 0x3f); +} + void sm510_base_device::op_tl() { - // TL xyz: longjump - op_illegal(); + // TL xyz: long jump + do_branch(m_param >> 6 & 3, m_op & 0xf, m_param & 0x3f); } void sm510_base_device::op_tml() { - // TML xyz: x - op_illegal(); + // TML xyz: long call + push_stack(); + do_branch(m_param >> 6 & 3, m_op & 3, m_param & 0x3f); } void sm510_base_device::op_tm() { - // TM xyz: x - op_illegal(); + // TM x: indirect subroutine call, pointers(IDX) are in page 0 + m_icount--; + push_stack(); + UINT8 idx = m_program->read_byte(m_op & 0x3f); + do_branch(idx >> 6 & 3, 4, idx & 0x3f); } -void sm510_base_device::op_t() -{ - // T xy: jump within current page - m_pc = (m_pc & ~0x3f) | (m_op & 0x3f); -} // Data transfer instructions @@ -236,7 +256,7 @@ void sm510_base_device::op_adx() { // ADX x: add immediate value to ACC, skip next on carry m_acc += (m_op & 0xf); - m_skip = (m_acc & 0x10) ? true : false; + m_skip = ((m_acc & 0x10) != 0); m_acc &= 0xf; } @@ -248,10 +268,10 @@ void sm510_base_device::op_coma() void sm510_base_device::op_rot() { - // ROT: rotate ACC left through carry - m_acc = m_acc << 1 | m_c; - m_c = m_acc >> 4 & 1; - m_acc &= 0xf; + // ROT: rotate ACC right through carry + UINT8 c = m_acc & 1; + m_acc = m_acc >> 1 | m_c << 3; + m_c = c; } void sm510_base_device::op_rc() @@ -290,7 +310,7 @@ void sm510_base_device::op_tam() void sm510_base_device::op_tmi() { // TMI x: skip next if RAM bit is set - m_skip = (ram_r() & 1 << (m_op & 3)) ? true : false; + m_skip = ((ram_r() & bitmask(m_op)) != 0); } void sm510_base_device::op_ta0() @@ -335,13 +355,13 @@ void sm510_base_device::op_tf4() void sm510_base_device::op_rm() { // RM x: reset RAM bit - ram_w(ram_r() & ~(1 << (m_op & 3))); + ram_w(ram_r() & ~bitmask(m_op)); } void sm510_base_device::op_sm() { // SM x: set RAM bit - ram_w(ram_r() | (1 << (m_op & 3))); + ram_w(ram_r() | bitmask(m_op)); }