From bca24133da2a7b5e8dd326bfebc94d5b4cef2f60 Mon Sep 17 00:00:00 2001 From: hap Date: Fri, 23 Jun 2017 00:33:49 +0200 Subject: sm510: made KB1013VK12 device a clone of SM5A (nw) --- scripts/src/cpu.lua | 6 +- src/devices/cpu/sm510/kb1013vk1-2.h | 38 ---- src/devices/cpu/sm510/kb1013vk1-2core.cpp | 137 ------------- src/devices/cpu/sm510/kb1013vk1-2op.cpp | 22 -- src/devices/cpu/sm510/sm500.h | 61 +++++- src/devices/cpu/sm510/sm500op.cpp | 16 +- src/devices/cpu/sm510/sm510.cpp | 330 ------------------------------ src/devices/cpu/sm510/sm510base.cpp | 328 +++++++++++++++++++++++++++++ src/devices/cpu/sm510/sm510d.cpp | 94 ++++----- src/devices/cpu/sm510/sm510op.cpp | 2 +- src/devices/cpu/sm510/sm5acore.cpp | 156 ++++++++++++++ src/mame/drivers/hh_sm500.cpp | 2 +- src/tools/unidasm.cpp | 4 +- 13 files changed, 597 insertions(+), 599 deletions(-) delete mode 100644 src/devices/cpu/sm510/kb1013vk1-2.h delete mode 100644 src/devices/cpu/sm510/kb1013vk1-2core.cpp delete mode 100644 src/devices/cpu/sm510/kb1013vk1-2op.cpp delete mode 100644 src/devices/cpu/sm510/sm510.cpp create mode 100644 src/devices/cpu/sm510/sm510base.cpp create mode 100644 src/devices/cpu/sm510/sm5acore.cpp diff --git a/scripts/src/cpu.lua b/scripts/src/cpu.lua index aeec05b0982..2684a186546 100644 --- a/scripts/src/cpu.lua +++ b/scripts/src/cpu.lua @@ -1765,7 +1765,7 @@ end if (CPUS["SM510"]~=null) then files { - MAME_DIR .. "src/devices/cpu/sm510/sm510.cpp", + MAME_DIR .. "src/devices/cpu/sm510/sm510base.cpp", MAME_DIR .. "src/devices/cpu/sm510/sm510.h", MAME_DIR .. "src/devices/cpu/sm510/sm510op.cpp", MAME_DIR .. "src/devices/cpu/sm510/sm510core.cpp", @@ -1773,9 +1773,7 @@ if (CPUS["SM510"]~=null) then MAME_DIR .. "src/devices/cpu/sm510/sm500.h", MAME_DIR .. "src/devices/cpu/sm510/sm500op.cpp", MAME_DIR .. "src/devices/cpu/sm510/sm500core.cpp", - MAME_DIR .. "src/devices/cpu/sm510/kb1013vk1-2.h", - MAME_DIR .. "src/devices/cpu/sm510/kb1013vk1-2op.cpp", - MAME_DIR .. "src/devices/cpu/sm510/kb1013vk1-2core.cpp", + MAME_DIR .. "src/devices/cpu/sm510/sm5acore.cpp", MAME_DIR .. "src/devices/cpu/sm510/sm590.h", MAME_DIR .. "src/devices/cpu/sm510/sm590op.cpp", MAME_DIR .. "src/devices/cpu/sm510/sm590core.cpp", diff --git a/src/devices/cpu/sm510/kb1013vk1-2.h b/src/devices/cpu/sm510/kb1013vk1-2.h deleted file mode 100644 index ce51feb36a1..00000000000 --- a/src/devices/cpu/sm510/kb1013vk1-2.h +++ /dev/null @@ -1,38 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:hap, Igor -/* - - KB1013VK1-2 - -*/ - -#ifndef MAME_CPU_SM510_KB1013VK1_2_H -#define MAME_CPU_SM510_KB1013VK1_2_H - -#pragma once - -#include "sm500.h" - - -// I/O ports setup - -// .. - -class kb1013vk12_device : public sm500_device -{ -public: - kb1013vk12_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); - -protected: - virtual offs_t disasm_disassemble(std::ostream &stream, offs_t pc, const u8 *oprom, const u8 *opram, u32 options) override; - virtual void execute_one() override; - - // opcode handlers - virtual void op_bs0(); - virtual void op_bs1(); -}; - - -DECLARE_DEVICE_TYPE(KB1013VK12, kb1013vk12_device) - -#endif // MAME_CPU_SM510_KB1013VK1_2_H diff --git a/src/devices/cpu/sm510/kb1013vk1-2core.cpp b/src/devices/cpu/sm510/kb1013vk1-2core.cpp deleted file mode 100644 index 2ba55cb33f6..00000000000 --- a/src/devices/cpu/sm510/kb1013vk1-2core.cpp +++ /dev/null @@ -1,137 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:hap, Igor -/* - - KB1013VK1-2 MCU core implementation - -*/ - -#include "emu.h" -#include "kb1013vk1-2.h" -#include "debugger.h" - -// MCU types -DEFINE_DEVICE_TYPE(KB1013VK12, kb1013vk12_device, "kb1013vk1_2", "KB1013VK1-2") - - -// internal memory maps -static ADDRESS_MAP_START(program_1_8k, AS_PROGRAM, 8, sm510_base_device) - AM_RANGE(0x000, 0x6ff) AM_ROM - AM_RANGE(0x700, 0x73f) AM_MIRROR(0x0c0) AM_ROM -ADDRESS_MAP_END - -static ADDRESS_MAP_START(data_5x13x4, AS_DATA, 8, sm510_base_device) - AM_RANGE(0x00, 0x0c) AM_RAM - AM_RANGE(0x10, 0x1c) AM_RAM - AM_RANGE(0x20, 0x2c) AM_RAM - AM_RANGE(0x30, 0x3c) AM_RAM - AM_RANGE(0x40, 0x4c) AM_RAM -ADDRESS_MAP_END - -// device definitions -kb1013vk12_device::kb1013vk12_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) - : sm500_device(mconfig, KB1013VK12, tag, owner, clock, 1 /* stack levels */, 11 /* prg width */, ADDRESS_MAP_NAME(program_1_8k), 7 /* data width */, ADDRESS_MAP_NAME(data_5x13x4)) -{ -} - - -// disasm -offs_t kb1013vk12_device::disasm_disassemble(std::ostream &stream, offs_t pc, const u8 *oprom, const u8 *opram, u32 options) -{ - extern CPU_DISASSEMBLE(kb1013vk12); - return CPU_DISASSEMBLE_NAME(kb1013vk12)(this, stream, pc, oprom, opram, options); -} - - - -//------------------------------------------------- -// execute -//------------------------------------------------- - -void kb1013vk12_device::execute_one() -{ - switch (m_op & 0xf0) - { - case 0x20: op_lax(); break; // LC - case 0x30: op_adx(); break; // AS/A10 - case 0x40: op_lb(); break; // LAS - case 0x70: op_ssr(); break; // LP - - case 0x80: case 0x90: case 0xa0: case 0xb0: - op_t(); break; // BR (LP+this=JMP) - case 0xc0: case 0xd0: case 0xe0: case 0xf0: - op_trs(); break; // CBR/CZP (LP+this=CAL) - - default: - switch (m_op & 0xfc) - { - case 0x04: op_rm(); break; // BM0 - case 0x0c: op_sm(); break; // BM1 - case 0x10: op_exc(); break; // XM/XE - case 0x14: op_exci(); break; // XI/XEI - case 0x18: op_lda(); break; // LE - case 0x1c: op_excd(); break; // XD/XED - case 0x54: op_tmi(); break; // SM1 - - default: - switch (m_op) - { - case 0x00: op_skip(); break; // NOP - case 0x01: op_atr(); break; // OAR - case 0x02: op_bs1(); break; // *BS1 - case 0x03: op_atbp(); break; - case 0x08: op_add(); break; // AM - case 0x09: op_add11(); break; // AC - case 0x0a: op_coma(); break; // COM - case 0x0b: op_exbla(); break; // XL - - case 0x50: op_tal(); break; // SI1 - case 0x51: op_tb(); break; // SI0 - case 0x52: op_tc(); break; // SCO - case 0x53: op_tam(); break; // SAM - case 0x58: op_tis(); break; // TIM - case 0x59: op_ptw(); break; - case 0x5a: op_ta0(); break; // SAO - case 0x5b: op_tabl(); break; // SAL - case 0x5c: op_tw(); break; - case 0x5d: op_dtw(); break; - case 0x5f: op_lbl(); break; // LAF - - case 0x60: op_comcn(); break; - case 0x61: op_pdtw(); break; - case 0x62: op_wr(); break; - case 0x63: op_ws(); break; - case 0x64: op_incb(); break; // INC - case 0x65: op_idiv(); break; // SYN - case 0x66: op_rc(); break; // CLC - case 0x67: op_sc(); break; // STC - case 0x68: op_rmf(); break; // CLL - case 0x69: op_smf(); break; // LD0 - case 0x6a: op_kta(); break; // ICD - case 0x6b: op_bs0(); break; // *BS0 - case 0x6c: op_decb(); break; // DEC - case 0x6d: op_comcb(); break; // CMS - case 0x6e: op_rtn0(); break; // RT - case 0x6f: op_rtn1(); break; // RTS - - // extended opcodes - case 0x5e: - m_op = m_op << 8 | m_param; - switch (m_param) - { - case 0x00: op_cend(); break; // HLT - case 0x04: op_dta(); break; // LDF - - default: op_illegal(); break; - } - break; // 0x5e - - default: op_illegal(); break; - } - break; // 0xff - - } - break; // 0xfc - - } // big switch -} diff --git a/src/devices/cpu/sm510/kb1013vk1-2op.cpp b/src/devices/cpu/sm510/kb1013vk1-2op.cpp deleted file mode 100644 index 377739190be..00000000000 --- a/src/devices/cpu/sm510/kb1013vk1-2op.cpp +++ /dev/null @@ -1,22 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:hap, Igor - -// KB1013VK1-2 opcode handlers - -#include "emu.h" -#include "kb1013vk1-2.h" - - -// instruction set - -void kb1013vk12_device::op_bs0() -{ - // BS0: reset RAM address high bit - m_bm &= ~4; -} - -void kb1013vk12_device::op_bs1() -{ - // BS1: set RAM address high bit - m_bm |= 4; -} diff --git a/src/devices/cpu/sm510/sm500.h b/src/devices/cpu/sm510/sm500.h index b6cc948c71f..ec52202ae3a 100644 --- a/src/devices/cpu/sm510/sm500.h +++ b/src/devices/cpu/sm510/sm500.h @@ -32,17 +32,42 @@ O13 38 | | 23 OS3 O44 39 | | 22 OS4 O34 40 | | 21 H1 O24 41 | | 20 H2 -O14 42 | SM500 | 19 VM +O14 42 | SM500 | 19 Vm O45 43 | | 18 OSCin O35 44 | | 17 OSCout -O25 45 | | 16 VDD +O25 45 | | 16 Vdd O15 46 | | 15 K4 O46 47 | | 14 K3 O36 48 | * | 13 K2 |________________________________________________/ - 1 2 3 4 5 6 7 8 9 10 11 12 + 1 2 3 4 5 6 7 8 9 10 11 12 O26 O16 R4 R3 R2 R1 GND _T bt al ACL K1 note: bt = beta symbol, al = alpha symbol + + + OS2 OS3 OS4 K4 K3 K2 K1 GND al bt ACL _R1 _Tp NC NC note: on SM5L, pin 31=V1, 32=V2, 33=NC + 45 44 43 42 41 40 39 38 37 36 35 34 33 32 31 + ____________________________________________________________ + | | +OS1 46 | | 30 H1 +O41 47 | | 29 H2 +O31 48 | | 28 Vm +O21 49 | | 27 Vdd +O11 50 | | 26 _R2 +O42 51 | | 25 _R3 +O32 52 | SM5A | 24 _R4 +O22 53 | SM5L | 23 OSCin +O12 54 | | 22 OSCout +O43 55 | | 21 _T2 +O33 56 | | 20 _T1 +O23 57 | | 19 O18 +O13 58 | | 18 O28 +O44 59 | | 17 O38 +O34 60 | * | 16 O48 + |____________________________________________________________/ + + 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 + O24 O14 O45 O35 O25 O15 O46 GND O36 O26 O16 O47 O37 O27 O17 */ class sm500_device : public sm510_base_device @@ -60,6 +85,8 @@ protected: // opcode handlers virtual void op_lb() override; virtual void op_incb() override; + virtual void op_sbm() override; + virtual void op_rbm(); virtual void op_comcb(); virtual void op_ssr(); @@ -79,6 +106,34 @@ protected: }; +class sm5a_device : public sm500_device +{ +public: + sm5a_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); + +protected: + sm5a_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, int stack_levels, int prgwidth, address_map_constructor program, int datawidth, address_map_constructor data); + + virtual offs_t disasm_disassemble(std::ostream &stream, offs_t pc, const u8 *oprom, const u8 *opram, u32 options) override; + virtual void execute_one() override; +}; + +class sm5l_device : public sm5a_device +{ +public: + sm5l_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); +}; + +class kb1013vk12_device : public sm5a_device +{ +public: + kb1013vk12_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); +}; + + DECLARE_DEVICE_TYPE(SM500, sm500_device) +DECLARE_DEVICE_TYPE(SM5A, sm5a_device) +DECLARE_DEVICE_TYPE(SM5L, sm5l_device) +DECLARE_DEVICE_TYPE(KB1013VK12, kb1013vk12_device) #endif // MAME_CPU_SM510_SM500_H diff --git a/src/devices/cpu/sm510/sm500op.cpp b/src/devices/cpu/sm510/sm500op.cpp index 2fd8089e39d..44ed43952ff 100644 --- a/src/devices/cpu/sm510/sm500op.cpp +++ b/src/devices/cpu/sm510/sm500op.cpp @@ -1,7 +1,7 @@ // license:BSD-3-Clause -// copyright-holders:hap +// copyright-holders:hap, Igor -// SM500 opcode handlers +// SM500 shared opcode handlers #include "emu.h" #include "sm500.h" @@ -26,6 +26,18 @@ void sm500_device::op_incb() m_skip = (m_bl == 8); } +void sm500_device::op_sbm() +{ + // SBM: set RAM address high bit + m_bm |= 4; +} + +void sm500_device::op_rbm() +{ + // RBM: reset RAM address high bit + m_bm &= ~4; +} + // ROM address instructions diff --git a/src/devices/cpu/sm510/sm510.cpp b/src/devices/cpu/sm510/sm510.cpp deleted file mode 100644 index 3d88f9ad59f..00000000000 --- a/src/devices/cpu/sm510/sm510.cpp +++ /dev/null @@ -1,330 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:hap -/* - - Known chips: (* means not emulated yet) - - Sharp SM510 MCU family: - - SM510: 2.7Kx8 ROM, 128x4 RAM(32x4 for LCD) - - SM511: 4Kx8 ROM, 128x4 RAM(32x4 for LCD), melody controller - - SM512: 4Kx8 ROM, 128x4 RAM(48x4 for LCD), melody controller - - *KB1013VK4-2: Soviet-era clone of SM510, minor differences - - Sharp SM500 MCU family: - - *SM500: x - - *SM4A: x - - *SM530: x - - *SM531: x - - *KB1013VK1-2: Soviet-era clone of SM500, minor differences - - Sharp SM590 MCU family: - - *SM590: 512x8 ROM, 32x4 RAM - - *SM591: 1kx8 ROM, 56x4 RAM - - *SM595: 768x8 ROM, 32x4 RAM - - References: - - 1990 Sharp Microcomputers Data Book - - 1996 Sharp Microcomputer Databook - - KB1013VK1-2/KB1013VK4-2 manual - - TODO: - - finish SM500 emulation (gen.1 Game & Watch) - - finish SM590/SM595 emulation (NES/SNES CIC) - - proper support for LFSR program counter in debugger - - callback for lcd screen as MAME bitmap (when needed) - - LCD bs pin blink mode via Y register (0.5s off, 0.5s on) - - wake up after CEND doesn't work right - - SM510 buzzer control divider bit is mask-programmable? - - SM511 undocumented/guessed opcodes: - * $01 is guessed as DIV to ACC transfer, unknown which bits - * $5d is certainly CEND - * $65 is certainly divider reset, but not sure if it behaves same as on SM510 - * $6036 and $6037 may be instruction timing? (16kHz and 8kHz), mnemonics unknown - -*/ - -#include "emu.h" -#include "sm510.h" -#include "debugger.h" - - -//------------------------------------------------- -// device_start - device-specific startup -//------------------------------------------------- - -enum -{ - SM510_PC=1, SM510_ACC, SM510_X, SM510_BL, SM510_BM, - SM510_C, SM510_W -}; - -void sm510_base_device::device_start() -{ - m_program = &space(AS_PROGRAM); - m_data = &space(AS_DATA); - m_prgmask = (1 << m_prgwidth) - 1; - m_datamask = (1 << m_datawidth) - 1; - - // resolve callbacks - m_read_k.resolve_safe(0); - m_read_ba.resolve_safe(1); - m_read_b.resolve_safe(1); - m_write_s.resolve_safe(); - m_write_r.resolve_safe(); - - m_write_sega.resolve_safe(); - m_write_segb.resolve_safe(); - m_write_segbs.resolve_safe(); - m_write_segc.resolve_safe(); - - // init/zerofill - memset(m_stack, 0, sizeof(m_stack)); - m_pc = 0; - m_prev_pc = 0; - m_op = 0; - m_prev_op = 0; - m_param = 0; - m_acc = 0; - m_bl = 0; - m_bm = 0; - m_sbm = false; - m_c = 0; - m_skip = false; - m_w = 0; - m_r = 0; - m_r_out = 0; - m_div = 0; - m_1s = false; - m_k_active = false; - m_l = 0; - m_x = 0; - m_y = 0; - m_bp = false; - m_bc = false; - m_halt = false; - m_melody_rd = 0; - m_melody_step_count = 0; - m_melody_duty_count = 0; - m_melody_duty_index = 0; - m_melody_address = 0; - m_clk_div = 2; // 16kHz - - // register for savestates - save_item(NAME(m_stack)); - save_item(NAME(m_pc)); - save_item(NAME(m_prev_pc)); - save_item(NAME(m_op)); - save_item(NAME(m_prev_op)); - save_item(NAME(m_param)); - save_item(NAME(m_acc)); - save_item(NAME(m_bl)); - save_item(NAME(m_bm)); - save_item(NAME(m_sbm)); - save_item(NAME(m_c)); - save_item(NAME(m_skip)); - save_item(NAME(m_w)); - save_item(NAME(m_r)); - save_item(NAME(m_r_out)); - save_item(NAME(m_div)); - save_item(NAME(m_1s)); - save_item(NAME(m_k_active)); - save_item(NAME(m_l)); - save_item(NAME(m_x)); - save_item(NAME(m_y)); - save_item(NAME(m_bp)); - save_item(NAME(m_bc)); - save_item(NAME(m_halt)); - save_item(NAME(m_melody_rd)); - save_item(NAME(m_melody_step_count)); - save_item(NAME(m_melody_duty_count)); - save_item(NAME(m_melody_duty_index)); - save_item(NAME(m_melody_address)); - save_item(NAME(m_clk_div)); - - // register state for debugger - state_add(SM510_PC, "PC", m_pc).formatstr("%04X"); - state_add(SM510_ACC, "ACC", m_acc).formatstr("%01X"); - state_add(SM510_X, "X", m_x).formatstr("%01X"); - state_add(SM510_BL, "BL", m_bl).formatstr("%01X"); - state_add(SM510_BM, "BM", m_bm).formatstr("%01X"); - state_add(SM510_C, "C", m_c).formatstr("%01X"); - state_add(SM510_W, "W", m_w).formatstr("%02X"); - - state_add(STATE_GENPC, "GENPC", m_pc).formatstr("%04X").noshow(); - state_add(STATE_GENPCBASE, "CURPC", m_pc).formatstr("%04X").noshow(); - state_add(STATE_GENFLAGS, "GENFLAGS", m_c).formatstr("%1s").noshow(); - - m_icountptr = &m_icount; - - // init peripherals - init_divider(); - init_lcd_driver(); - init_melody(); -} - - - -//------------------------------------------------- -// device_reset - device-specific reset -//------------------------------------------------- - -void sm510_base_device::device_reset() -{ - // ACL - m_skip = false; - m_halt = false; - m_sbm = false; - m_op = m_prev_op = 0; - do_branch(3, 7, 0); - m_prev_pc = m_pc; - - // lcd is on (Bp on, BC off, bs(y) off) - m_bp = true; - m_bc = false; - m_y = 0; - - m_r = m_r_out = 0; - m_write_r(0, 0, 0xff); -} - - - -//------------------------------------------------- -// lcd driver -//------------------------------------------------- - -inline u16 sm510_base_device::get_lcd_row(int column, u8* ram) -{ - // output 0 if lcd blackpate/bleeder is off, or in case row doesn't exist - if (ram == nullptr || m_bc || !m_bp) - return 0; - - u16 rowdata = 0; - for (int i = 0; i < 0x10; i++) - rowdata |= (ram[i] >> column & 1) << i; - - return rowdata; -} - -TIMER_CALLBACK_MEMBER(sm510_base_device::lcd_timer_cb) -{ - // 4 columns - for (int h = 0; h < 4; h++) - { - // 16 segments per row from upper part of RAM - m_write_sega(h | SM510_PORT_SEGA, get_lcd_row(h, m_lcd_ram_a), 0xffff); - m_write_segb(h | SM510_PORT_SEGB, get_lcd_row(h, m_lcd_ram_b), 0xffff); - m_write_segc(h | SM510_PORT_SEGC, get_lcd_row(h, m_lcd_ram_c), 0xffff); - - // bs output from L/X and Y regs - u8 bs = (m_l >> h & 1) | ((m_x*2) >> h & 2); - m_write_segbs(h | SM510_PORT_SEGBS, (m_bc || !m_bp) ? 0 : bs, 0xffff); - } - - // schedule next timeout - m_lcd_timer->adjust(attotime::from_ticks(0x200, unscaled_clock())); -} - -void sm510_base_device::init_lcd_driver() -{ - // note: in reality, this timer runs at high frequency off the main divider, strobing one segment at a time - m_lcd_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(sm510_base_device::lcd_timer_cb), this)); - m_lcd_timer->adjust(attotime::from_ticks(0x200, unscaled_clock())); // 64hz default -} - - - -//------------------------------------------------- -// interrupt/divider -//------------------------------------------------- - -bool sm510_base_device::wake_me_up() -{ - // in halt mode, wake up after 1S signal or K input - if (m_k_active || m_1s) - { - // note: official doc warns that Bl/Bm and the stack are undefined - // after waking up, but we leave it unchanged - m_halt = false; - do_branch(1, 0, 0); - - standard_irq_callback(0); - return true; - } - else - return false; -} - -void sm510_base_device::execute_set_input(int line, int state) -{ - if (line != SM510_INPUT_LINE_K) - return; - - // set K input lines active state - m_k_active = (state != 0); -} - -TIMER_CALLBACK_MEMBER(sm510_base_device::div_timer_cb) -{ - m_div = (m_div + 1) & 0x7fff; - - // 1S signal on overflow(falling edge of F1) - if (m_div == 0) - m_1s = true; - - clock_melody(); -} - -void sm510_base_device::init_divider() -{ - m_div_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(sm510_base_device::div_timer_cb), this)); - m_div_timer->adjust(attotime::from_ticks(1, unscaled_clock()), 0, attotime::from_ticks(1, unscaled_clock())); -} - - - -//------------------------------------------------- -// execute -//------------------------------------------------- - -void sm510_base_device::increment_pc() -{ - // PL(program counter low 6 bits) is a simple LFSR: newbit = (bit0==bit1) - // PU,PM(high bits) specify page, PL specifies steps within page - int feed = ((m_pc >> 1 ^ m_pc) & 1) ? 0 : 0x20; - m_pc = feed | (m_pc >> 1 & 0x1f) | (m_pc & ~0x3f); -} - -void sm510_base_device::execute_run() -{ - while (m_icount > 0) - { - m_icount--; - - if (m_halt && !wake_me_up()) - { - // got nothing to do - m_icount = 0; - return; - } - - // remember previous state - m_prev_op = m_op; - m_prev_pc = m_pc; - - // fetch next opcode - debugger_instruction_hook(this, m_pc); - m_op = m_program->read_byte(m_pc); - increment_pc(); - get_opcode_param(); - - // handle opcode if it's not skipped - if (m_skip) - { - m_skip = false; - m_op = 0; // fake nop - } - else - execute_one(); - } -} diff --git a/src/devices/cpu/sm510/sm510base.cpp b/src/devices/cpu/sm510/sm510base.cpp new file mode 100644 index 00000000000..f77bfeb451d --- /dev/null +++ b/src/devices/cpu/sm510/sm510base.cpp @@ -0,0 +1,328 @@ +// license:BSD-3-Clause +// copyright-holders:hap +/* + + Supported chips: (* means not finished emulated yet) + + Sharp SM510 MCU family: + - SM510: 2.7Kx8 ROM, 128x4 RAM(32x4 for LCD) + - SM511: 4Kx8 ROM, 128x4 RAM(32x4 for LCD), melody controller + - SM512: 4Kx8 ROM, 128x4 RAM(48x4 for LCD), melody controller + + Sharp SM500 MCU family: + - *SM500: x + - *SM5A: x + - *SM5L: low-power version of SM5A + - *KB1013VK1-2: Soviet-era clone of SM5A + + Sharp SM590 MCU family: + - *SM590: 512x8 ROM, 32x4 RAM + - *SM591: 1kx8 ROM, 56x4 RAM + - *SM595: 768x8 ROM, 32x4 RAM + + References: + - 1990 Sharp Microcomputers Data Book + - 1996 Sharp Microcomputer Databook + - KB1013VK1-2/KB1013VK4-2 manual + + TODO: + - finish SM500 emulation (gen.1 Game & Watch) + - finish SM590/SM595 emulation (NES/SNES CIC) + - proper support for LFSR program counter in debugger + - callback for lcd screen as MAME bitmap (when needed) + - LCD bs pin blink mode via Y register (0.5s off, 0.5s on) + - wake up after CEND doesn't work right + - SM510 buzzer control divider bit is mask-programmable? + - SM511 undocumented/guessed opcodes: + * $01 is guessed as DIV to ACC transfer, unknown which bits + * $5d is certainly CEND + * $65 is certainly divider reset, but not sure if it behaves same as on SM510 + * $6036 and $6037 may be instruction timing? (16kHz and 8kHz), mnemonics unknown + +*/ + +#include "emu.h" +#include "sm510.h" +#include "debugger.h" + + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +enum +{ + SM510_PC=1, SM510_ACC, SM510_X, SM510_BL, SM510_BM, + SM510_C, SM510_W +}; + +void sm510_base_device::device_start() +{ + m_program = &space(AS_PROGRAM); + m_data = &space(AS_DATA); + m_prgmask = (1 << m_prgwidth) - 1; + m_datamask = (1 << m_datawidth) - 1; + + // resolve callbacks + m_read_k.resolve_safe(0); + m_read_ba.resolve_safe(1); + m_read_b.resolve_safe(1); + m_write_s.resolve_safe(); + m_write_r.resolve_safe(); + + m_write_sega.resolve_safe(); + m_write_segb.resolve_safe(); + m_write_segbs.resolve_safe(); + m_write_segc.resolve_safe(); + + // init/zerofill + memset(m_stack, 0, sizeof(m_stack)); + m_pc = 0; + m_prev_pc = 0; + m_op = 0; + m_prev_op = 0; + m_param = 0; + m_acc = 0; + m_bl = 0; + m_bm = 0; + m_sbm = false; + m_c = 0; + m_skip = false; + m_w = 0; + m_r = 0; + m_r_out = 0; + m_div = 0; + m_1s = false; + m_k_active = false; + m_l = 0; + m_x = 0; + m_y = 0; + m_bp = false; + m_bc = false; + m_halt = false; + m_melody_rd = 0; + m_melody_step_count = 0; + m_melody_duty_count = 0; + m_melody_duty_index = 0; + m_melody_address = 0; + m_clk_div = 2; // 16kHz + + // register for savestates + save_item(NAME(m_stack)); + save_item(NAME(m_pc)); + save_item(NAME(m_prev_pc)); + save_item(NAME(m_op)); + save_item(NAME(m_prev_op)); + save_item(NAME(m_param)); + save_item(NAME(m_acc)); + save_item(NAME(m_bl)); + save_item(NAME(m_bm)); + save_item(NAME(m_sbm)); + save_item(NAME(m_c)); + save_item(NAME(m_skip)); + save_item(NAME(m_w)); + save_item(NAME(m_r)); + save_item(NAME(m_r_out)); + save_item(NAME(m_div)); + save_item(NAME(m_1s)); + save_item(NAME(m_k_active)); + save_item(NAME(m_l)); + save_item(NAME(m_x)); + save_item(NAME(m_y)); + save_item(NAME(m_bp)); + save_item(NAME(m_bc)); + save_item(NAME(m_halt)); + save_item(NAME(m_melody_rd)); + save_item(NAME(m_melody_step_count)); + save_item(NAME(m_melody_duty_count)); + save_item(NAME(m_melody_duty_index)); + save_item(NAME(m_melody_address)); + save_item(NAME(m_clk_div)); + + // register state for debugger + state_add(SM510_PC, "PC", m_pc).formatstr("%04X"); + state_add(SM510_ACC, "ACC", m_acc).formatstr("%01X"); + state_add(SM510_X, "X", m_x).formatstr("%01X"); + state_add(SM510_BL, "BL", m_bl).formatstr("%01X"); + state_add(SM510_BM, "BM", m_bm).formatstr("%01X"); + state_add(SM510_C, "C", m_c).formatstr("%01X"); + state_add(SM510_W, "W", m_w).formatstr("%02X"); + + state_add(STATE_GENPC, "GENPC", m_pc).formatstr("%04X").noshow(); + state_add(STATE_GENPCBASE, "CURPC", m_pc).formatstr("%04X").noshow(); + state_add(STATE_GENFLAGS, "GENFLAGS", m_c).formatstr("%1s").noshow(); + + m_icountptr = &m_icount; + + // init peripherals + init_divider(); + init_lcd_driver(); + init_melody(); +} + + + +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + +void sm510_base_device::device_reset() +{ + // ACL + m_skip = false; + m_halt = false; + m_sbm = false; + m_op = m_prev_op = 0; + do_branch(3, 7, 0); + m_prev_pc = m_pc; + + // lcd is on (Bp on, BC off, bs(y) off) + m_bp = true; + m_bc = false; + m_y = 0; + + m_r = m_r_out = 0; + m_write_r(0, 0, 0xff); +} + + + +//------------------------------------------------- +// lcd driver +//------------------------------------------------- + +inline u16 sm510_base_device::get_lcd_row(int column, u8* ram) +{ + // output 0 if lcd blackpate/bleeder is off, or in case row doesn't exist + if (ram == nullptr || m_bc || !m_bp) + return 0; + + u16 rowdata = 0; + for (int i = 0; i < 0x10; i++) + rowdata |= (ram[i] >> column & 1) << i; + + return rowdata; +} + +TIMER_CALLBACK_MEMBER(sm510_base_device::lcd_timer_cb) +{ + // 4 columns + for (int h = 0; h < 4; h++) + { + // 16 segments per row from upper part of RAM + m_write_sega(h | SM510_PORT_SEGA, get_lcd_row(h, m_lcd_ram_a), 0xffff); + m_write_segb(h | SM510_PORT_SEGB, get_lcd_row(h, m_lcd_ram_b), 0xffff); + m_write_segc(h | SM510_PORT_SEGC, get_lcd_row(h, m_lcd_ram_c), 0xffff); + + // bs output from L/X and Y regs + u8 bs = (m_l >> h & 1) | ((m_x*2) >> h & 2); + m_write_segbs(h | SM510_PORT_SEGBS, (m_bc || !m_bp) ? 0 : bs, 0xffff); + } + + // schedule next timeout + m_lcd_timer->adjust(attotime::from_ticks(0x200, unscaled_clock())); +} + +void sm510_base_device::init_lcd_driver() +{ + // note: in reality, this timer runs at high frequency off the main divider, strobing one segment at a time + m_lcd_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(sm510_base_device::lcd_timer_cb), this)); + m_lcd_timer->adjust(attotime::from_ticks(0x200, unscaled_clock())); // 64hz default +} + + + +//------------------------------------------------- +// interrupt/divider +//------------------------------------------------- + +bool sm510_base_device::wake_me_up() +{ + // in halt mode, wake up after 1S signal or K input + if (m_k_active || m_1s) + { + // note: official doc warns that Bl/Bm and the stack are undefined + // after waking up, but we leave it unchanged + m_halt = false; + do_branch(1, 0, 0); + + standard_irq_callback(0); + return true; + } + else + return false; +} + +void sm510_base_device::execute_set_input(int line, int state) +{ + if (line != SM510_INPUT_LINE_K) + return; + + // set K input lines active state + m_k_active = (state != 0); +} + +TIMER_CALLBACK_MEMBER(sm510_base_device::div_timer_cb) +{ + m_div = (m_div + 1) & 0x7fff; + + // 1S signal on overflow(falling edge of F1) + if (m_div == 0) + m_1s = true; + + clock_melody(); +} + +void sm510_base_device::init_divider() +{ + m_div_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(sm510_base_device::div_timer_cb), this)); + m_div_timer->adjust(attotime::from_ticks(1, unscaled_clock()), 0, attotime::from_ticks(1, unscaled_clock())); +} + + + +//------------------------------------------------- +// execute +//------------------------------------------------- + +void sm510_base_device::increment_pc() +{ + // PL(program counter low 6 bits) is a simple LFSR: newbit = (bit0==bit1) + // PU,PM(high bits) specify page, PL specifies steps within page + int feed = ((m_pc >> 1 ^ m_pc) & 1) ? 0 : 0x20; + m_pc = feed | (m_pc >> 1 & 0x1f) | (m_pc & ~0x3f); +} + +void sm510_base_device::execute_run() +{ + while (m_icount > 0) + { + m_icount--; + + if (m_halt && !wake_me_up()) + { + // got nothing to do + m_icount = 0; + return; + } + + // remember previous state + m_prev_op = m_op; + m_prev_pc = m_pc; + + // fetch next opcode + debugger_instruction_hook(this, m_pc); + m_op = m_program->read_byte(m_pc); + increment_pc(); + get_opcode_param(); + + // handle opcode if it's not skipped + if (m_skip) + { + m_skip = false; + m_op = 0; // fake nop + } + else + execute_one(); + } +} diff --git a/src/devices/cpu/sm510/sm510d.cpp b/src/devices/cpu/sm510/sm510d.cpp index bc671cb5fca..78ec0d180eb 100644 --- a/src/devices/cpu/sm510/sm510d.cpp +++ b/src/devices/cpu/sm510/sm510d.cpp @@ -27,21 +27,15 @@ enum e_mnemonics mPRE, mSME, mRME, mTMEL, mSKIP, mCEND, mIDIV, mDR, mDTA, mCLKLO, mCLKHI, - // SM500-specific - mCOMCB, mRTN, mRTNS, mSSR, mTR, mTRS, + // SM500 common + mCOMCB, mRTN, mRTNS, mSSR, mTR, mTRS, mRBM, mADDC, mPDTW, mTW, mDTW, mATS, mEXKSA, mEXKFA, mRMF, mSMF, mCOMCN, mTA, mTM2, mTG, - // KB1013VK1-2 aliases - mLC, mLM, mLE, mLAF, mLAS, mLDF, mBS0, mBS1, mXL, mXM, mXI, mXEI, mXD, mXED, mXE, mBM0, mBM1, mSM1, - mAM, mAC, mA10, mAS, mCLL, mCOM, mCLC, mSTC, mSCO, mSAO, mINC, mDEC, mSAM, mSAL, mNOP, - mICD, mOAR, mOA0, mOA1, mDAF, mDAS, mABS, mABF, mCTB, mLD0, mEN, - mBR, mLP, mCBR, mCMS, mRT, mRTS, mSI1, mSI0, mSYN, mTIM, mHLT, - // SM590 aliases - mCCTRL, mINBL, mDEBL, mXBLA, mADCS, mTR7, + mNOP, mCCTRL, mINBL, mDEBL, mXBLA, mADCS, mTR7, // SM590 uniques mTAX, mLBLX, mMTR, mSTR, mINBM, mDEBM, mRTA, mBLTA, mEXAX, mTBA, mADS, mADC, mLBMX, mTLS }; @@ -60,20 +54,14 @@ static const char *const s_mnemonics[] = "SKIP", "CEND", "IDIV", "DR", "DTA", "CLKLO", "CLKHI", // - "COMCB", "RTN", "RTNS", "SSR", "TR", "TRS", + "COMCB", "RTN", "RTNS", "SSR", "TR", "TRS", "RBM", "ADDC", "PDTW", "TW", "DTW", "ATS", "EXKSA", "EXKFA", "RMF", "SMF", "COMCN", "TA", "TM", "TG", // - "LC", "LM", "LE", "LAF", "LAS", "LDF", "BS0", "BS1", "XL", "XM", "XI", "XEI", "XD", "XED", "XE", "BM0", "BM1", "SM1", - "AM", "AC", "A10", "AS", "CLL", "COM", "CLC", "STC", "SCO", "SAO", "INC", "DEC", "SAM", "SAL", "NOP", - "ICD", "OAR", "OA0", "OA1", "DAF", "DAS", "ABS", "ABF", "CTB", "LD0", "EN", - "BR", "LP", "CBR", "CMS", "RT", "RTS", "SI1", "SI0", "SYN", "TIM", "HLT", - - // - "CCTRL", "INBL", "DEBL", "XBLA", "ADCS", "TR", + "NOP", "CCTRL", "INBL", "DEBL", "XBLA", "ADCS", "TR", // "TAX", "LBLX", "MTR", "STR", "INBM", "DEBM", "RTA", "BLTA", "EXAX", "TBA", "ADS", "ADC", "LBMX", "TLS" }; @@ -93,20 +81,14 @@ static const u8 s_bits[] = 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 4, 6, 6, + 0, 0, 0, 4, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, // - 4, 0, 2, 8, 4, 0, 0, 0, 0, 0, 0, 2, 0, 2, 2, 2, 2, 2, - 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 6, 4, 6, 0, 0, 0, 0, 0, 0, 0, 0, - - // - 0, 0, 0, 0, 0, 7, + 0, 0, 0, 0, 0, 0, 7, // 4, 4, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 2, 2+8 }; @@ -128,20 +110,14 @@ static const u32 s_flags[] = 0, _OVER, 0, 0, 0, 0, 0, // - 0, _OUT, _OUT, 0, 0, _OVER, + 0, _OUT, _OUT, 0, 0, _OVER, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, _OVER, 0, _OUT, _OUT, 0, 0, 0, 0, _OVER, - - // - 0, 0, 0, 0, 0, _OVER, + 0, 0, 0, 0, 0, 0, _OVER, // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, _OVER }; @@ -342,45 +318,45 @@ CPU_DISASSEMBLE(sm500) } -// KB1013VK1-2 disasm +// SM5A disasm -static const u8 kb1013vk12_mnemonic[0x100] = +static const u8 sm5a_mnemonic[0x100] = { /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ - mNOP, mOAR, mBS1, mEN, mBM0, mBM0, mBM0, mBM0, mAM, mAC, mCOM, mXL, mBM1, mBM1, mBM1, mBM1, // 0 - mXM, mXE, mXE, mXE, mXI, mXEI, mXEI, mXEI, mLE, mLE, mLE, mLDA, mXD, mXED, mXED, mXED, // 1 - mLC, mLC, mLC, mLC, mLC, mLC, mLC, mLC, mLC, mLC, mLC, mLC, mLC, mLC, mLC, mLC, // 2 - mAS, mAS, mAS, mAS, mAS, mAS, mAS, mAS, mAS, mAS, mA10, mAS, mAS, mAS, mAS, mAS, // 3 - - mLAS, mLAS, mLAS, mLAS, mLAS, mLAS, mLAS, mLAS, mLAS, mLAS, mLAS, mLAS, mLAS, mLAS, mLAS, mLAS, // 4 - mSI1, mSI0, mSCO, mSAM, mSM1, mSM1, mSM1, mSM1, mTIM, mABS, mSAO, mSAL, mABF, mDAF, mEXT, mLAF, // 5 - mCTB, mDAS, mOA1, mOA0, mINC, mSYN, mCLC, mSTC, mCLL, mLD0, mICD, mBS0, mDEC, mCMS, mRT, mRTS, // 6 - mLP, mLP, mLP, mLP, mLP, mLP, mLP, mLP, mLP, mLP, mLP, mLP, mLP, mLP, mLP, mLP, // 7 - - mBR, mBR, mBR, mBR, mBR, mBR, mBR, mBR, mBR, mBR, mBR, mBR, mBR, mBR, mBR, mBR, // 8 - mBR, mBR, mBR, mBR, mBR, mBR, mBR, mBR, mBR, mBR, mBR, mBR, mBR, mBR, mBR, mBR, // 9 - mBR, mBR, mBR, mBR, mBR, mBR, mBR, mBR, mBR, mBR, mBR, mBR, mBR, mBR, mBR, mBR, // A - mBR, mBR, mBR, mBR, mBR, mBR, mBR, mBR, mBR, mBR, mBR, mBR, mBR, mBR, mBR, mBR, // B - - mCBR, mCBR, mCBR, mCBR, mCBR, mCBR, mCBR, mCBR, mCBR, mCBR, mCBR, mCBR, mCBR, mCBR, mCBR, mCBR, // C - mCBR, mCBR, mCBR, mCBR, mCBR, mCBR, mCBR, mCBR, mCBR, mCBR, mCBR, mCBR, mCBR, mCBR, mCBR, mCBR, // D - mCBR, mCBR, mCBR, mCBR, mCBR, mCBR, mCBR, mCBR, mCBR, mCBR, mCBR, mCBR, mCBR, mCBR, mCBR, mCBR, // E - mCBR, mCBR, mCBR, mCBR, mCBR, mCBR, mCBR, mCBR, mCBR, mCBR, mCBR, mCBR, mCBR, mCBR, mCBR, mCBR // F + mSKIP, mATR, mSBM, mATBP, mRM, mRM, mRM, mRM, mADD, mADDC, mCOMA, mEXBLA,mSM, mSM, mSM, mSM, // 0 + mEXC, mEXC, mEXC, mEXC, mEXCI, mEXCI, mEXCI, mEXCI, mLDA, mLDA, mLDA, mLDA, mEXCD, mEXCD, mEXCD, mEXCD, // 1 + mLAX, mLAX, mLAX, mLAX, mLAX, mLAX, mLAX, mLAX, mLAX, mLAX, mLAX, mLAX, mLAX, mLAX, mLAX, mLAX, // 2 + mADX, mADX, mADX, mADX, mADX, mADX, mADX, mADX, mADX, mADX, mADX, mADX, mADX, mADX, mADX, mADX, // 3 + + mLB, mLB, mLB, mLB, mLB, mLB, mLB, mLB, mLB, mLB, mLB, mLB, mLB, mLB, mLB, mLB, // 4 + mTA, mTB, mTC, mTAM, mTM2, mTM2, mTM2, mTM2, mTG, mPTW, mTA0, mTABL, mTW, mDTW, mEXT, mLBL, // 5 + mCOMCN,mPDTW, mWR, mWS, mINCB, mIDIV, mRC, mSC, mRMF, mSMF, mKTA, mRBM, mDECB, mCOMCB,mRTN, mRTNS, // 6 + mSSR, mSSR, mSSR, mSSR, mSSR, mSSR, mSSR, mSSR, mSSR, mSSR, mSSR, mSSR, mSSR, mSSR, mSSR, mSSR, // 7 + + mTR, mTR, mTR, mTR, mTR, mTR, mTR, mTR, mTR, mTR, mTR, mTR, mTR, mTR, mTR, mTR, // 8 + mTR, mTR, mTR, mTR, mTR, mTR, mTR, mTR, mTR, mTR, mTR, mTR, mTR, mTR, mTR, mTR, // 9 + mTR, mTR, mTR, mTR, mTR, mTR, mTR, mTR, mTR, mTR, mTR, mTR, mTR, mTR, mTR, mTR, // A + mTR, mTR, mTR, mTR, mTR, mTR, mTR, mTR, mTR, mTR, mTR, mTR, mTR, mTR, mTR, mTR, // B + + mTRS, mTRS, mTRS, mTRS, mTRS, mTRS, mTRS, mTRS, mTRS, mTRS, mTRS, mTRS, mTRS, mTRS, mTRS, mTRS, // C + mTRS, mTRS, mTRS, mTRS, mTRS, mTRS, mTRS, mTRS, mTRS, mTRS, mTRS, mTRS, mTRS, mTRS, mTRS, mTRS, // D + mTRS, mTRS, mTRS, mTRS, mTRS, mTRS, mTRS, mTRS, mTRS, mTRS, mTRS, mTRS, mTRS, mTRS, mTRS, mTRS, // E + mTRS, mTRS, mTRS, mTRS, mTRS, mTRS, mTRS, mTRS, mTRS, mTRS, mTRS, mTRS, mTRS, mTRS, mTRS, mTRS // F }; -static const u8 kb1013vk12_extended[0x10] = +static const u8 sm5a_extended[0x10] = { - mHLT, 0, 0, 0, mLDF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // 5E 0 + mCEND, 0, 0, 0, mDTA, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // 5E 0 }; -CPU_DISASSEMBLE(kb1013vk12) +CPU_DISASSEMBLE(sm5a) { // create extended opcode table u8 ext[0x100]; memset(ext, 0, 0x100); - memcpy(ext + 0x00, kb1013vk12_extended, 0x10); + memcpy(ext + 0x00, sm5a_extended, 0x10); - return sm510_common_disasm(kb1013vk12_mnemonic, ext, stream, pc, oprom, opram, 6); + return sm510_common_disasm(sm5a_mnemonic, ext, stream, pc, oprom, opram, 6); } diff --git a/src/devices/cpu/sm510/sm510op.cpp b/src/devices/cpu/sm510/sm510op.cpp index 5a14a7f2e12..5847cbf68f4 100644 --- a/src/devices/cpu/sm510/sm510op.cpp +++ b/src/devices/cpu/sm510/sm510op.cpp @@ -1,7 +1,7 @@ // license:BSD-3-Clause // copyright-holders:hap -// shared opcode handlers +// SM510 shared opcode handlers #include "emu.h" #include "sm510.h" diff --git a/src/devices/cpu/sm510/sm5acore.cpp b/src/devices/cpu/sm510/sm5acore.cpp new file mode 100644 index 00000000000..d4192b6a534 --- /dev/null +++ b/src/devices/cpu/sm510/sm5acore.cpp @@ -0,0 +1,156 @@ +// license:BSD-3-Clause +// copyright-holders:hap, Igor +/* + + Sharp SM5A MCU core implementation + +*/ + +#include "emu.h" +#include "sm500.h" +#include "debugger.h" + + +// MCU types +DEFINE_DEVICE_TYPE(SM5A, sm5a_device, "sm5a", "SM5A") +DEFINE_DEVICE_TYPE(SM5L, sm5l_device, "sm5l", "SM5L") +DEFINE_DEVICE_TYPE(KB1013VK12, kb1013vk12_device, "kb1013vk1_2", "KB1013VK1-2") + + +// internal memory maps +static ADDRESS_MAP_START(program_1_8k, AS_PROGRAM, 8, sm510_base_device) + AM_RANGE(0x000, 0x6ff) AM_ROM + AM_RANGE(0x700, 0x73f) AM_MIRROR(0x0c0) AM_ROM +ADDRESS_MAP_END + +static ADDRESS_MAP_START(data_5x13x4, AS_DATA, 8, sm510_base_device) + AM_RANGE(0x00, 0x0c) AM_RAM + AM_RANGE(0x10, 0x1c) AM_RAM + AM_RANGE(0x20, 0x2c) AM_RAM + AM_RANGE(0x30, 0x3c) AM_RAM + AM_RANGE(0x40, 0x4c) AM_RAM +ADDRESS_MAP_END + + +// device definitions +sm5a_device::sm5a_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : sm5a_device(mconfig, SM5A, tag, owner, clock, 1 /* stack levels */, 11 /* prg width */, ADDRESS_MAP_NAME(program_1_8k), 7 /* data width */, ADDRESS_MAP_NAME(data_5x13x4)) +{ +} + +sm5a_device::sm5a_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, int stack_levels, int prgwidth, address_map_constructor program, int datawidth, address_map_constructor data) + : sm500_device(mconfig, type, tag, owner, clock, stack_levels, prgwidth, program, datawidth, data) +{ +} + +sm5l_device::sm5l_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : sm5a_device(mconfig, SM5L, tag, owner, clock, 1, 11, ADDRESS_MAP_NAME(program_1_8k), 7, ADDRESS_MAP_NAME(data_5x13x4)) +{ +} + +kb1013vk12_device::kb1013vk12_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : sm5a_device(mconfig, SM5L, tag, owner, clock, 1, 11, ADDRESS_MAP_NAME(program_1_8k), 7, ADDRESS_MAP_NAME(data_5x13x4)) +{ +} + + +// disasm +offs_t sm5a_device::disasm_disassemble(std::ostream &stream, offs_t pc, const u8 *oprom, const u8 *opram, u32 options) +{ + extern CPU_DISASSEMBLE(sm5a); + return CPU_DISASSEMBLE_NAME(sm5a)(this, stream, pc, oprom, opram, options); +} + + + +//------------------------------------------------- +// execute +//------------------------------------------------- + +void sm5a_device::execute_one() +{ + switch (m_op & 0xf0) + { + case 0x20: op_lax(); break; // LC + case 0x30: op_adx(); break; // AS/A10 + case 0x40: op_lb(); break; // LAS + case 0x70: op_ssr(); break; // LP + + case 0x80: case 0x90: case 0xa0: case 0xb0: + op_t(); break; // BR (LP+this=JMP) + case 0xc0: case 0xd0: case 0xe0: case 0xf0: + op_trs(); break; // CBR/CZP (LP+this=CAL) + + default: + switch (m_op & 0xfc) + { + case 0x04: op_rm(); break; // BM0 + case 0x0c: op_sm(); break; // BM1 + case 0x10: op_exc(); break; // XM/XE + case 0x14: op_exci(); break; // XI/XEI + case 0x18: op_lda(); break; // LE + case 0x1c: op_excd(); break; // XD/XED + case 0x54: op_tmi(); break; // SM1 + + default: + switch (m_op) + { + case 0x00: op_skip(); break; // NOP + case 0x01: op_atr(); break; // OAR + case 0x02: op_sbm(); break; // *BS1 + case 0x03: op_atbp(); break; + case 0x08: op_add(); break; // AM + case 0x09: op_add11(); break; // AC + case 0x0a: op_coma(); break; // COM + case 0x0b: op_exbla(); break; // XL + + case 0x50: op_tal(); break; // SI1 + case 0x51: op_tb(); break; // SI0 + case 0x52: op_tc(); break; // SCO + case 0x53: op_tam(); break; // SAM + case 0x58: op_tis(); break; // TIM + case 0x59: op_ptw(); break; + case 0x5a: op_ta0(); break; // SAO + case 0x5b: op_tabl(); break; // SAL + case 0x5c: op_tw(); break; + case 0x5d: op_dtw(); break; + case 0x5f: op_lbl(); break; // LAF + + case 0x60: op_comcn(); break; + case 0x61: op_pdtw(); break; + case 0x62: op_wr(); break; + case 0x63: op_ws(); break; + case 0x64: op_incb(); break; // INC + case 0x65: op_idiv(); break; // SYN + case 0x66: op_rc(); break; // CLC + case 0x67: op_sc(); break; // STC + case 0x68: op_rmf(); break; // CLL + case 0x69: op_smf(); break; // LD0 + case 0x6a: op_kta(); break; // ICD + case 0x6b: op_rbm(); break; // *BS0 + case 0x6c: op_decb(); break; // DEC + case 0x6d: op_comcb(); break; // CMS + case 0x6e: op_rtn0(); break; // RT + case 0x6f: op_rtn1(); break; // RTS + + // extended opcodes + case 0x5e: + m_op = m_op << 8 | m_param; + switch (m_param) + { + case 0x00: op_cend(); break; // HLT + case 0x04: op_dta(); break; // LDF + + default: op_illegal(); break; + } + break; // 0x5e + + default: op_illegal(); break; + } + break; // 0xff + + } + break; // 0xfc + + } // big switch +} diff --git a/src/mame/drivers/hh_sm500.cpp b/src/mame/drivers/hh_sm500.cpp index af9091652f4..d9e7327cbf3 100644 --- a/src/mame/drivers/hh_sm500.cpp +++ b/src/mame/drivers/hh_sm500.cpp @@ -11,7 +11,7 @@ #include "emu.h" -#include "cpu/sm510/kb1013vk1-2.h" +#include "cpu/sm510/sm500.h" #include "sound/spkrdev.h" #include "screen.h" diff --git a/src/tools/unidasm.cpp b/src/tools/unidasm.cpp index 5ae5df132c2..6a53776ab17 100644 --- a/src/tools/unidasm.cpp +++ b/src/tools/unidasm.cpp @@ -122,7 +122,6 @@ CPU_DISASSEMBLE( i960 ); CPU_DISASSEMBLE( ie15 ); CPU_DISASSEMBLE( jaguardsp ); CPU_DISASSEMBLE( jaguargpu ); -CPU_DISASSEMBLE( kb1013vk12 ); CPU_DISASSEMBLE( konami ); CPU_DISASSEMBLE( lh5801 ); CPU_DISASSEMBLE( lr35902 ); @@ -177,6 +176,7 @@ CPU_DISASSEMBLE( sharc ); CPU_DISASSEMBLE( sm500 ); CPU_DISASSEMBLE( sm510 ); CPU_DISASSEMBLE( sm511 ); +CPU_DISASSEMBLE( sm5a ); CPU_DISASSEMBLE( sm8500 ); CPU_DISASSEMBLE( spc700 ); CPU_DISASSEMBLE( ssem ); @@ -296,7 +296,6 @@ static const dasm_table_entry dasm_table[] = { "ie15", _8bit, 0, CPU_DISASSEMBLE_NAME(ie15) }, { "jaguardsp", _16be, 0, CPU_DISASSEMBLE_NAME(jaguardsp) }, { "jaguargpu", _16be, 0, CPU_DISASSEMBLE_NAME(jaguargpu) }, - { "kb1013vk12", _8bit, 0, CPU_DISASSEMBLE_NAME(kb1013vk12) }, { "konami", _8bit, 0, CPU_DISASSEMBLE_NAME(konami) }, { "lh5801", _8bit, 0, CPU_DISASSEMBLE_NAME(lh5801) }, { "lr35902", _8bit, 0, CPU_DISASSEMBLE_NAME(lr35902) }, @@ -351,6 +350,7 @@ static const dasm_table_entry dasm_table[] = { "sm500", _8bit, 0, CPU_DISASSEMBLE_NAME(sm500) }, { "sm510", _8bit, 0, CPU_DISASSEMBLE_NAME(sm510) }, { "sm511", _8bit, 0, CPU_DISASSEMBLE_NAME(sm511) }, + { "sm5a", _8bit, 0, CPU_DISASSEMBLE_NAME(sm5a) }, { "sm8500", _8bit, 0, CPU_DISASSEMBLE_NAME(sm8500) }, { "sparcv7", _32be, 0, CPU_DISASSEMBLE_NAME(sparcv7) }, { "sparcv8", _32be, 0, CPU_DISASSEMBLE_NAME(sparcv8) }, -- cgit v1.2.3