From f1f36c9ba013607e3afe396c23894957770c6838 Mon Sep 17 00:00:00 2001 From: hap Date: Mon, 14 Mar 2022 22:07:33 +0100 Subject: sm590: added i/o ports --- src/devices/cpu/sm510/sm500.cpp | 8 +- src/devices/cpu/sm510/sm510base.cpp | 6 +- src/devices/cpu/sm510/sm510base.h | 37 +++++---- src/devices/cpu/sm510/sm510d.cpp | 17 ++-- src/devices/cpu/sm510/sm510d.h | 7 +- src/devices/cpu/sm510/sm510op.cpp | 2 +- src/devices/cpu/sm510/sm511.cpp | 8 +- src/devices/cpu/sm510/sm530.cpp | 8 +- src/devices/cpu/sm510/sm530.h | 5 +- src/devices/cpu/sm510/sm590.cpp | 127 +++++++++++++++++------------ src/devices/cpu/sm510/sm590.h | 112 +++++++++++--------------- src/devices/cpu/sm510/sm590op.cpp | 156 ++++++++++++++++++++---------------- src/devices/cpu/sm510/sm5a.cpp | 8 +- 13 files changed, 264 insertions(+), 237 deletions(-) diff --git a/src/devices/cpu/sm510/sm500.cpp b/src/devices/cpu/sm510/sm500.cpp index 347f17423dd..f8014ac1201 100644 --- a/src/devices/cpu/sm510/sm500.cpp +++ b/src/devices/cpu/sm510/sm500.cpp @@ -36,15 +36,15 @@ void sm500_device::data_4x10x4(address_map &map) // device definitions -sm500_device::sm500_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : - sm500_device(mconfig, SM500, tag, owner, clock, 1 /* stack levels */, 7 /* o group pins */, 11 /* prg width */, address_map_constructor(FUNC(sm500_device::program_1_2k), this), 6 /* data width */, address_map_constructor(FUNC(sm500_device::data_4x10x4), this)) -{ } - sm500_device::sm500_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, int stack_levels, int o_pins, int prgwidth, address_map_constructor program, int datawidth, address_map_constructor data) : sm510_base_device(mconfig, type, tag, owner, clock, stack_levels, prgwidth, program, datawidth, data), m_o_pins(o_pins) { } +sm500_device::sm500_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : + sm500_device(mconfig, SM500, tag, owner, clock, 1 /* stack levels */, 7 /* o group pins */, 11 /* prg width */, address_map_constructor(FUNC(sm500_device::program_1_2k), this), 6 /* data width */, address_map_constructor(FUNC(sm500_device::data_4x10x4), this)) +{ } + // disasm std::unique_ptr sm500_device::create_disassembler() diff --git a/src/devices/cpu/sm510/sm510base.cpp b/src/devices/cpu/sm510/sm510base.cpp index ec169a00e40..e4defb1f615 100644 --- a/src/devices/cpu/sm510/sm510base.cpp +++ b/src/devices/cpu/sm510/sm510base.cpp @@ -36,6 +36,7 @@ void sm510_base_device::device_start() m_data = &space(AS_DATA); m_prgmask = (1 << m_prgwidth) - 1; m_datamask = (1 << m_datawidth) - 1; + m_pagemask = 0x3f; // resolve callbacks m_read_k.resolve_safe(0); @@ -266,8 +267,9 @@ 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); + int msb = m_pagemask >> 1 ^ m_pagemask; + int feed = ((m_pc >> 1 ^ m_pc) & 1) ? 0 : msb; + m_pc = feed | (m_pc >> 1 & m_pagemask >> 1) | (m_pc & ~m_pagemask); } void sm510_base_device::execute_run() diff --git a/src/devices/cpu/sm510/sm510base.h b/src/devices/cpu/sm510/sm510base.h index f699c035b26..26ef77307cc 100644 --- a/src/devices/cpu/sm510/sm510base.h +++ b/src/devices/cpu/sm510/sm510base.h @@ -37,21 +37,24 @@ class sm510_base_device : public cpu_device { public: // construction/destruction - sm510_base_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) - : cpu_device(mconfig, type, tag, owner, clock) - , m_program_config("program", ENDIANNESS_LITTLE, 8, prgwidth, 0, program) - , m_data_config("data", ENDIANNESS_LITTLE, 8, datawidth, 0, data) - , m_prgwidth(prgwidth) - , m_datawidth(datawidth) - , m_stack_levels(stack_levels) - , m_r_mask_option(RMASK_DIRECT) - , m_lcd_ram_a(*this, "lcd_ram_a"), m_lcd_ram_b(*this, "lcd_ram_b"), m_lcd_ram_c(*this, "lcd_ram_c") - , m_write_segs(*this) - , m_melody_rom(*this, "melody") - , m_read_k(*this) - , m_read_ba(*this), m_read_b(*this) - , m_write_s(*this) - , m_write_r(*this) + sm510_base_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) : + cpu_device(mconfig, type, tag, owner, clock), + m_program_config("program", ENDIANNESS_LITTLE, 8, prgwidth, 0, program), + m_data_config("data", ENDIANNESS_LITTLE, 8, datawidth, 0, data), + m_prgwidth(prgwidth), + m_datawidth(datawidth), + m_stack_levels(stack_levels), + m_r_mask_option(RMASK_DIRECT), + m_lcd_ram_a(*this, "lcd_ram_a"), + m_lcd_ram_b(*this, "lcd_ram_b"), + m_lcd_ram_c(*this, "lcd_ram_c"), + m_write_segs(*this), + m_melody_rom(*this, "melody"), + m_read_k(*this), + m_read_ba(*this), + m_read_b(*this), + m_write_s(*this), + m_write_r(*this) { } // For SM510, SM500, SM5A, R port output is selected with a mask option, @@ -73,8 +76,9 @@ public: // 4/8-bit S strobe output port auto write_s() { return m_write_s.bind(); } - // 1/2/4-bit R (buzzer/melody) output port + // 1/2-bit R (buzzer/melody) output port // may also be called F(frequency?) or SO(sound out) + // SM590 has 4 R ports, don't use this one, see sm590.h auto write_r() { return m_write_r.bind(); } // LCD segment outputs, SM51x: H1-4 as offset(low), a/b/c 1-16 as data d0-d15, @@ -114,6 +118,7 @@ protected: int m_datawidth; int m_prgmask; int m_datamask; + int m_pagemask; u16 m_pc, m_prev_pc; u16 m_op, m_prev_op; diff --git a/src/devices/cpu/sm510/sm510d.cpp b/src/devices/cpu/sm510/sm510d.cpp index 0d1ff7924f4..dc6722dfc34 100644 --- a/src/devices/cpu/sm510/sm510d.cpp +++ b/src/devices/cpu/sm510/sm510d.cpp @@ -74,9 +74,8 @@ const char *const sm510_common_disassembler::s_mnemonics[] = "INIS", // SM590 - "NOP", "CCTRL", "INBL", "DEBL", "XBLA", "ADCS", "TR", - // " - "TAX", "LBLX", "MTR", "STR", "INBM", "DEBM", "RTA", "BLTA", "EXAX", "TBA", "ADS", "ADC", "LBMX", "TLS" + "TAX", "LBLX", "MTR", "STR", "INBM", "DEBM", "RTA", "BLTA", "EXAX", "TBA", "ADS", "ADC", "LBMX", "TLS", + "NOP", "CCTRL", "INBL", "DEBL", "XBLA", "ADCS", "TR" }; // number of bits per opcode parameter, 8 or larger means 2-byte opcode @@ -108,9 +107,8 @@ const u8 sm510_common_disassembler::s_bits[] = 0, // SM590 - 0, 0, 0, 0, 0, 0, 7, - // " - 4, 4, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 2, 2+8 + 4, 4, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 2, 2+8, + 0, 0, 0, 0, 0, 0, 7 }; const u32 sm510_common_disassembler::s_flags[] = @@ -141,9 +139,8 @@ const u32 sm510_common_disassembler::s_flags[] = 0, // SM590 - 0, 0, 0, 0, 0, 0, STEP_OVER, - // " - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, STEP_OVER + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, STEP_OVER, + 0, 0, 0, 0, 0, 0, STEP_OVER }; @@ -361,7 +358,7 @@ offs_t sm5a_disassembler::disassemble(std::ostream &stream, offs_t pc, const dat const u8 sm530_disassembler::sm530_mnemonic[0x100] = { /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ - mADX, mADX, mADX, mADX, mADX, mADX, mADX, mADX, mADX, mADX, mADX, mADX, mADX, mADX, mADX, mADX, // 0 - note: $00 has synonym SKIP + mSKIP, mADX, mADX, mADX, mADX, mADX, mADX, mADX, mADX, mADX, mADX, mADX, mADX, mADX, mADX, mADX, // 0 mLAX, mLAX, mLAX, mLAX, mLAX, mLAX, mLAX, mLAX, mLAX, mLAX, mLAX, mLAX, mLAX, mLAX, mLAX, mLAX, // 1 mLDA, mLDA, mLDA, mLDA, mEXC, mEXC, mEXC, mEXC, mEXCI, mEXCI, mEXCI, mEXCI, mEXCD, mEXCD, mEXCD, mEXCD, // 2 mLB, mLB, mLB, mLB, mLB, mLB, mLB, mLB, mLB, mLB, mLB, mLB, mLB, mLB, mLB, mLB, // 3 diff --git a/src/devices/cpu/sm510/sm510d.h b/src/devices/cpu/sm510/sm510d.h index b7d51786d4b..59257b73173 100644 --- a/src/devices/cpu/sm510/sm510d.h +++ b/src/devices/cpu/sm510/sm510d.h @@ -52,10 +52,9 @@ protected: mKETA, mATF, mSDS, mRDS, mINIS, - // SM590 aliases - mNOP, mCCTRL, mINBL, mDEBL, mXBLA, mADCS, mTR7, - // SM590 uniques - mTAX, mLBLX, mMTR, mSTR, mINBM, mDEBM, mRTA, mBLTA, mEXAX, mTBA2, mADS, mADC, mLBMX, mTLS + // SM590 common + mTAX, mLBLX, mMTR, mSTR, mINBM, mDEBM, mRTA, mBLTA, mEXAX, mTBA2, mADS, mADC, mLBMX, mTLS, + mNOP, mCCTRL, mINBL, mDEBL, mXBLA, mADCS, mTR7 // aliases }; static const char *const s_mnemonics[]; diff --git a/src/devices/cpu/sm510/sm510op.cpp b/src/devices/cpu/sm510/sm510op.cpp index 9c7aa24c85c..4d98c91ab36 100644 --- a/src/devices/cpu/sm510/sm510op.cpp +++ b/src/devices/cpu/sm510/sm510op.cpp @@ -118,7 +118,7 @@ void sm510_base_device::op_rtn1() void sm510_base_device::op_t() { // T xy: jump(transfer) within current page - m_pc = (m_pc & ~0x3f) | (m_op & 0x3f); + m_pc = (m_pc & ~m_pagemask) | (m_op & m_pagemask); } void sm510_base_device::op_tl() diff --git a/src/devices/cpu/sm510/sm511.cpp b/src/devices/cpu/sm510/sm511.cpp index 9ac8e36699e..c3a0e04d4c8 100644 --- a/src/devices/cpu/sm510/sm511.cpp +++ b/src/devices/cpu/sm510/sm511.cpp @@ -54,14 +54,14 @@ std::unique_ptr sm511_device::create_disassembler() // device definitions -sm511_device::sm511_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : - sm511_device(mconfig, SM511, tag, owner, clock, 2 /* stack levels */, 12 /* prg width */, address_map_constructor(FUNC(sm511_device::program_4k), this), 7 /* data width */, address_map_constructor(FUNC(sm511_device::data_96_32x4), this)) -{ } - sm511_device::sm511_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) : sm510_base_device(mconfig, type, tag, owner, clock, stack_levels, prgwidth, program, datawidth, data) { } +sm511_device::sm511_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : + sm511_device(mconfig, SM511, tag, owner, clock, 2 /* stack levels */, 12 /* prg width */, address_map_constructor(FUNC(sm511_device::program_4k), this), 7 /* data width */, address_map_constructor(FUNC(sm511_device::data_96_32x4), this)) +{ } + sm512_device::sm512_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : sm511_device(mconfig, SM512, tag, owner, clock, 2, 12, address_map_constructor(FUNC(sm512_device::program_4k), this), 7, address_map_constructor(FUNC(sm512_device::data_80_48x4), this)) { } diff --git a/src/devices/cpu/sm510/sm530.cpp b/src/devices/cpu/sm510/sm530.cpp index ddc2e24a368..8531e41f755 100644 --- a/src/devices/cpu/sm510/sm530.cpp +++ b/src/devices/cpu/sm510/sm530.cpp @@ -46,15 +46,15 @@ std::unique_ptr sm530_device::create_disassembler() // device definitions -sm530_device::sm530_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : - sm530_device(mconfig, SM530, tag, owner, clock, 1 /* stack levels */, 11 /* prg width */, address_map_constructor(FUNC(sm530_device::program_2k), this), 7 /* data width */, address_map_constructor(FUNC(sm530_device::data_64_24x4), this)) -{ } - sm530_device::sm530_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) : sm511_device(mconfig, type, tag, owner, clock, stack_levels, prgwidth, program, datawidth, data), m_write_f(*this) { } +sm530_device::sm530_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : + sm530_device(mconfig, SM530, tag, owner, clock, 1 /* stack levels */, 11 /* prg width */, address_map_constructor(FUNC(sm530_device::program_2k), this), 7 /* data width */, address_map_constructor(FUNC(sm530_device::data_64_24x4), this)) +{ } + //------------------------------------------------- // device_start - device-specific startup diff --git a/src/devices/cpu/sm510/sm530.h b/src/devices/cpu/sm510/sm530.h index a9ea769d679..654bcf2963e 100644 --- a/src/devices/cpu/sm510/sm530.h +++ b/src/devices/cpu/sm510/sm530.h @@ -89,8 +89,6 @@ protected: virtual void execute_one() override; virtual bool op_argument() override; - using sm510_base_device::do_branch; - virtual void do_branch(u8 pu, u8 pl); // does not have Pm virtual void reset_vector() override { do_branch(0xf, 0); } virtual void wakeup_vector() override { do_branch(0, 0); } @@ -109,6 +107,9 @@ protected: virtual u16 melody_step_mask() override { return 0xff; } // opcode handlers + using sm510_base_device::do_branch; + virtual void do_branch(u8 pu, u8 pl); // does not have Pm + virtual void op_incb() override; virtual void op_lb() override; virtual void op_sabl(); diff --git a/src/devices/cpu/sm510/sm590.cpp b/src/devices/cpu/sm510/sm590.cpp index 790e8578a54..70b7968eaa5 100644 --- a/src/devices/cpu/sm510/sm590.cpp +++ b/src/devices/cpu/sm510/sm590.cpp @@ -5,7 +5,8 @@ Sharp SM590 MCU core implementation TODO: - - finish SM590/SM595 emulation (NES/SNES CIC) + - if BL >= 4, are port accesses mirrored or ignored? (right now assuming mirrored) + - R port mask options */ @@ -17,39 +18,59 @@ // MCU types DEFINE_DEVICE_TYPE(SM590, sm590_device, "sm590", "Sharp SM590") // 512x8 ROM, 32x4 RAM -//DEFINE_DEVICE_TYPE(SM591, sm591_device, "sm591", "Sharp SM591") // 1kx8 ROM, 56x4 RAM -//DEFINE_DEVICE_TYPE(SM595, sm595_device, "sm595", "Sharp SM595") // 768x8 ROM, 32x4 RAM +DEFINE_DEVICE_TYPE(SM591, sm591_device, "sm591", "Sharp SM591") // 1kx8 ROM, 56x4 RAM +DEFINE_DEVICE_TYPE(SM595, sm595_device, "sm595", "Sharp SM595") // 768x8 ROM, 32x4 RAM + // internal memory maps -void sm590_device::program_1x128x4(address_map &map) +void sm590_device::program_512x8(address_map &map) { map(0x000, 0x1ff).rom(); } -void sm590_device::data_16x2x4(address_map &map) +void sm590_device::program_768x8(address_map &map) +{ + map(0x000, 0x2ff).rom(); +} + +void sm590_device::program_1kx8(address_map &map) { - map(0x00, 0x0f).ram(); - map(0x10, 0x1f).ram(); + map(0x000, 0x3ff).rom(); } +void sm590_device::data_32x4(address_map &map) +{ + map(0x00, 0x1f).ram(); +} + +void sm590_device::data_56x4(address_map &map) +{ + map(0x00, 0x2f).ram(); + map(0x30, 0x37).mirror(0x08).ram(); +} + + // device definitions -sm590_device::sm590_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : - sm590_device(mconfig, SM590, tag, owner, clock, 4 /* stack levels */, 9 /* prg width */, address_map_constructor(FUNC(sm590_device::program_1x128x4), this), 5 /* data width */, address_map_constructor(FUNC(sm590_device::data_16x2x4), this)) +sm590_device::sm590_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) : + sm510_base_device(mconfig, type, tag, owner, clock, stack_levels, prgwidth, program, datawidth, data), + m_write_rx(*this), + m_read_rx(*this) { } -//sm591_device::sm591_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : -// sm510_base_device(mconfig, SM591, tag, owner, clock, 4 /* stack levels */, 10 /* prg width */, address_map_constructor(FUNC(sm591_device::program_2x128x4), this), 6 /* data width */, address_map_constructor(FUNC(sm591_device::data_16x3.5x4), this)) -//{ } +sm590_device::sm590_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : + sm590_device(mconfig, SM590, tag, owner, clock, 4 /* stack levels */, 9 /* prg width */, address_map_constructor(FUNC(sm590_device::program_512x8), this), 5 /* data width */, address_map_constructor(FUNC(sm590_device::data_32x4), this)) +{ } -//sm595_device::sm595_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : -// sm510_base_device(mconfig, SM595, tag, owner, clock, 4 /* stack levels */, 10 /* prg width */, address_map_constructor(FUNC(sm595_device::program_1x128x4_1x128x2), this), 5 /* data width */, address_map_constructor(FUNC(sm595_device::data_16x2x4), this)) -//{ } +sm591_device::sm591_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : + sm590_device(mconfig, SM591, tag, owner, clock, 4, 10, address_map_constructor(FUNC(sm591_device::program_1kx8), this), 6, address_map_constructor(FUNC(sm591_device::data_56x4), this)) +{ } -sm590_device::sm590_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) : - sm510_base_device(mconfig, type, tag, owner, clock, stack_levels, prgwidth, program, datawidth, data) +sm595_device::sm595_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : + sm590_device(mconfig, SM595, tag, owner, clock, 4, 10, address_map_constructor(FUNC(sm595_device::program_768x8), this), 5, address_map_constructor(FUNC(sm595_device::data_32x4), this)) { } +// disasm std::unique_ptr sm590_device::create_disassembler() { return std::make_unique(); @@ -57,38 +78,46 @@ std::unique_ptr sm590_device::create_disassembler() //------------------------------------------------- -// device_reset - device-specific reset +// device_start - device-specific startup //------------------------------------------------- -void sm590_device::device_reset() +void sm590_device::device_start() { - // ACL - m_skip = false; - m_halt = false; - m_op = m_prev_op = 0; - reset_vector(); - m_prev_pc = m_pc; - - m_rports[0] = m_rports[1] = m_rports[2] = m_rports[3] = 0; - //m_write_r(0); // TODO: are the four ports zeroed on reset? + // common init + sm510_base_device::device_start(); + + // resolve callbacks + m_read_rx.resolve_all_safe(0); + m_write_rx.resolve_all_safe(); + + // init/register for savestates + m_pagemask = 0x7f; + save_item(NAME(m_rports)); } //------------------------------------------------- -// execute +// device_reset - device-specific reset //------------------------------------------------- -void sm590_device::increment_pc() +void sm590_device::device_reset() { - // PL(program counter low 7 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 : 0x40; - m_pc = feed | (m_pc >> 1 & 0x3f) | (m_pc & ~0x7f); + // common reset + sm510_base_device::device_reset(); + + // clear outputs + for (int i = 0; i < 4; i++) + port_w(i, 0); } + +//------------------------------------------------- +// execute +//------------------------------------------------- + void sm590_device::execute_one() { - switch (m_op & 0xf0) // opcodes with 4 bit params + switch (m_op & 0xf0) { case 0x00: op_adx(); break; case 0x10: op_tax(); break; @@ -96,20 +125,20 @@ void sm590_device::execute_one() case 0x30: op_lax(); break; case 0x80: case 0x90: case 0xa0: case 0xb0: case 0xc0: case 0xd0: case 0xe0: case 0xf0: - op_t(); break; // aka tr + op_t(); break; // TR - default: // opcodes with 2 bit params + default: switch (m_op & 0xfc) { - case 0x60: op_tmi(); break; // aka tm + case 0x60: op_tmi(); break; // TM case 0x64: op_tba(); break; case 0x68: op_rm(); break; case 0x6c: op_sm(); break; case 0x74: op_lbmx(); break; case 0x78: op_tl(); break; - case 0x7c: op_tml(); break; // aka tls + case 0x7c: op_tls(); break; - default: // everything else + default: switch (m_op) { case 0x40: op_lda(); break; @@ -123,27 +152,23 @@ void sm590_device::execute_one() case 0x48: op_rc(); break; case 0x49: op_sc(); break; case 0x4a: op_str(); break; - case 0x4b: op_cend(); break; // aka cctrl - case 0x4c: op_rtn0(); break; // aka rtn - case 0x4d: op_rtn1(); break; // aka rtns - // 4e, 4f illegal + case 0x4b: op_cend(); break; // CCTRL + case 0x4c: op_rtn0(); break; // RTN + case 0x4d: op_rtn1(); break; // RTNS case 0x50: op_inbm(); break; case 0x51: op_debm(); break; - case 0x52: op_incb(); break; // aka inbl - case 0x53: op_decb(); break; // aka debl + case 0x52: op_incb(); break; // INBL + case 0x53: op_decb(); break; // DEBL case 0x54: op_tc(); break; case 0x55: op_rta(); break; case 0x56: op_blta(); break; - case 0x57: op_exbla(); break; // aka xbla - // 58, 59, 5a, 5b illegal + case 0x57: op_exbla(); break; // XBLA case 0x5c: op_atx(); break; case 0x5d: op_exax(); break; - // 5e is illegal??? - // 5f is illegal case 0x70: op_add(); break; case 0x71: op_ads(); break; case 0x72: op_adc(); break; - case 0x73: op_add11(); break; // aka adcs + case 0x73: op_add11(); break; // ADCS default: op_illegal(); break; } diff --git a/src/devices/cpu/sm510/sm590.h b/src/devices/cpu/sm510/sm590.h index 93fedc460c1..7e4bb229e66 100644 --- a/src/devices/cpu/sm510/sm590.h +++ b/src/devices/cpu/sm510/sm590.h @@ -89,14 +89,23 @@ R3.3/CL2 => |_|6 15|_| <> R1.3 class sm590_device : public sm510_base_device { public: - sm590_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 32768); + sm590_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); + + // four 4-bit R I/O ports + using sm510_base_device::write_r; + template auto write_r() { return m_write_rx[Bit].bind(); } + template auto read_r() { return m_read_rx[Bit].bind(); } protected: sm590_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); - void program_1x128x4(address_map &map); - void data_16x2x4(address_map &map); + void program_512x8(address_map &map); + void program_768x8(address_map &map); + void program_1kx8(address_map &map); + void data_32x4(address_map &map); + void data_56x4(address_map &map); + virtual void device_start() override; virtual void device_reset() override; virtual std::unique_ptr create_disassembler() override; @@ -105,89 +114,62 @@ protected: virtual void init_divider() override { } // no divider timer virtual void init_lcd_driver() override { } // no lcd driver - virtual void increment_pc() override; virtual void execute_one() override; virtual bool op_argument() override; - virtual void do_branch(u8 pu, u8 pm, u8 pl) override; virtual void reset_vector() override { do_branch(0, 0, 0); } virtual void wakeup_vector() override { do_branch(0, 1, 0); } - // opcode handlers - // 00-3f - virtual void op_adx() override; - virtual void op_tax(); - virtual void op_lblx(); - // lax (same as sm510) + // R ports + devcb_write8::array<4> m_write_rx; + devcb_read8::array<4> m_read_rx; + u8 m_rports[4]; - // 40-43 - virtual void op_lda() override; - virtual void op_exc() override; - // exci (same as sm510) - // excd (same as sm510) + // opcode handlers + virtual void do_branch(u8 pu, u8 pm, u8 pl) override; + void port_w(offs_t offset, u8 data); - // 44-47 - // coma (same as sm510) - // tam (same as sm510) - virtual void op_atr() override; - virtual void op_mtr(); + virtual void op_tl() override; + virtual void op_tls(); - // 48-4b - // rc (same as sm510) - // sc (same as sm510) + virtual void op_lblx(); + virtual void op_lbmx(); virtual void op_str(); - // cctrl (same as sm510 cend) - - // 4c-4f - // rtn (same as sm510 rtn0) - // rtns (same as sm510 rtn1) - // 4e illegal - // 4f illegal + virtual void op_lda() override; + virtual void op_exc() override; + virtual void op_exax(); + virtual void op_blta(); - // 50-53 + virtual void op_adx() override; + virtual void op_ads(); + virtual void op_adc(); virtual void op_inbm(); virtual void op_debm(); - // inbl (same as sm510 incb) - // debl (same as sm510 decb) - // 54-57 - virtual void op_tc() override; - virtual void op_rta(); - virtual void op_blta(); - // xbla (same as sm510 exbla) - - // 58-5b are all illegal - - // 5c-5f - // atx (same as sm510) - virtual void op_exax(); - // 5e illegal??? - // 5f illegal - - // 60-6f - // tm (same as sm510 tmi) + virtual void op_tax(); virtual void op_tba(); - // rm (same as sm510) - // sm (same as sm510) - - // 70-73 - // add (same as sm510) - virtual void op_ads(); - virtual void op_adc(); - // adcs (same as sm510 add11) + virtual void op_tc() override; - // 74-7f - virtual void op_lbmx(); - virtual void op_tl() override; - virtual void op_tml() override; // aka TLS + virtual void op_atr() override; + virtual void op_mtr(); + virtual void op_rta(); +}; - // 80-ff - virtual void op_t() override; // aka TR +class sm591_device : public sm590_device +{ +public: + sm591_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); +}; - u8 m_rports[4]; +class sm595_device : public sm590_device +{ +public: + sm595_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); }; DECLARE_DEVICE_TYPE(SM590, sm590_device) +DECLARE_DEVICE_TYPE(SM591, sm591_device) +DECLARE_DEVICE_TYPE(SM595, sm595_device) #endif // MAME_CPU_SM510_SM590_H diff --git a/src/devices/cpu/sm510/sm590op.cpp b/src/devices/cpu/sm510/sm590op.cpp index 7a2c3f09ade..a539c4bd061 100644 --- a/src/devices/cpu/sm510/sm590op.cpp +++ b/src/devices/cpu/sm510/sm590op.cpp @@ -11,101 +11,130 @@ void sm590_device::do_branch(u8 pu, u8 pm, u8 pl) { - // set new PC(Pu/Pm/Pl) - m_pc = (((u16)pu << 9 & 0x200) | ((u16)pm << 7 & 0x180) | (pl & 0x07f)) & m_prgmask; + // set new PC(Pu/Pm/Pl) (Pu is not used on SM590) + m_pc = ((pu << 9 & 0x200) | (pm << 7 & 0x180) | (pl & 0x07f)) & m_prgmask; +} + +void sm590_device::port_w(offs_t offset, u8 data) +{ + offset &= 3; + data &= 0xf; + m_rports[offset] = data; + m_write_rx[offset](offset, data); } // instruction set -void sm590_device::op_adx() +// ROM address instructions + +void sm590_device::op_tl() { - // ADX x: add immediate value to ACC, skip next on carry - m_acc += (m_op & 0xf); - m_skip = bool(m_acc & 0x10); - m_acc &= 0xf; + // TL xyz: long jump + do_branch(BIT(m_op, 1), (m_op << 1 & 2) | BIT(m_param, 7), m_param & 0x7f); } -void sm590_device::op_tax() +void sm590_device::op_tls() { - // TAX: skip next if ACC equals 4-bit immediate value - m_skip = (m_acc == (m_op & 0xf)); + // TLS xyz: long call + push_stack(); + do_branch(BIT(m_op, 1), (m_op << 1 & 2) | BIT(m_param, 7), m_param & 0x7f); } + +// Data transfer instructions + void sm590_device::op_lblx() { // LBL x: load BL with 4-bit immediate value m_bl = (m_op & 0xf); } +void sm590_device::op_lbmx() +{ + // LBM x: load BM with 2-bit immediate value + m_bm = (m_op & 0x3); +} + +void sm590_device::op_str() +{ + // STR: store ACC to RAM + ram_w(m_acc); +} + void sm590_device::op_lda() { - // LDA: load ACC with RAM + // LDA: load ACC with RAM (no BM xor) m_acc = ram_r(); } void sm590_device::op_exc() { - // EXC: exchange ACC with RAM + // EXC: exchange ACC with RAM (no BM xor) u8 a = m_acc; m_acc = ram_r(); ram_w(a); } -void sm590_device::op_atr() +void sm590_device::op_exax() { - // ATR: output ACC to R(BL) - m_rports[m_bl & 0x3] = m_acc; // is the mask for BL correct here? if BL is >= 4, do the writes just go nowhere? + // EXAX: exchange X with ACC + u8 a = m_acc; + m_acc = m_x; + m_x = a; } -void sm590_device::op_mtr() +void sm590_device::op_blta() { - // MTR: output RAM to R(BL) - m_rports[m_bl & 0x3] = ram_r(); // is the mask for BL correct here? if BL is >= 4, do the writes just go nowhere? + // BLTA: load ACC with BL + m_acc = m_bl; } -void sm590_device::op_str() -{ - // STR: output ACC to RAM - ram_w(m_acc); -} -void sm590_device::op_inbm() +// Arithmetic instructions + +void sm590_device::op_adx() { - // INBM: increment BM - m_bm = (m_bm + 1) & 0x3; // is this mask correct? + // ADX x: add immediate value to ACC, skip next on carry + m_acc += (m_op & 0xf); + m_skip = bool(m_acc & 0x10); + m_acc &= 0xf; } -void sm590_device::op_debm() +void sm590_device::op_ads() { - // DEBM: decrement BM - m_bm = (m_bm - 1) & 0x3; // is this mask correct? + // ADS: add RAM to ACC, skip next on carry + m_acc += ram_r(); + m_skip = bool(m_acc & 0x10); + m_acc &= 0xf; } -void sm590_device::op_tc() +void sm590_device::op_adc() { - // TC: skip next if carry - m_skip = bool(m_c); + // ADC: add RAM and carry to ACC and carry + op_add11(); + m_skip = false; // no skip } -void sm590_device::op_rta() +void sm590_device::op_inbm() { - // RTA: load ACC with R(BL) - m_acc = m_rports[m_bl & 0x3]; // TODO: need a read function for this; is the mask for BL correct here? if BL is >= 4, do we always read 0 or F? + // INBM: increment BM + m_bm = (m_bm + 1) & m_datamask >> 4; } -void sm590_device::op_blta() +void sm590_device::op_debm() { - // BLTA: load ACC with BL - m_acc = m_bl; + // DEBM: decrement BM + m_bm = (m_bm - 1) & m_datamask >> 4; } -void sm590_device::op_exax() + +// Test instructions + +void sm590_device::op_tax() { - // EXAX: exchange X with ACC - u8 a = m_acc; - m_acc = m_x; - m_x = a; + // TAX: skip next if ACC equals 4-bit immediate value + m_skip = (m_acc == (m_op & 0xf)); } void sm590_device::op_tba() @@ -114,43 +143,30 @@ void sm590_device::op_tba() m_skip = ((m_acc & bitmask(m_op)) != 0); } -void sm590_device::op_ads() +void sm590_device::op_tc() { - // ADS: add RAM to ACC, skip next on carry - m_acc += ram_r(); - m_skip = bool(m_acc & 0x10); - m_acc &= 0xf; + // TC: skip next if carry + m_skip = bool(m_c); } -void sm590_device::op_adc() -{ - // ADC: add RAM and carry to ACC and carry - m_acc += ram_r() + m_c; - m_c = m_acc >> 4 & 1; - m_acc &= 0xf; -} -void sm590_device::op_lbmx() -{ - // LBM x: load BM with 2-bit immediate value - m_bm = (m_op & 0x3); -} +// I/O instructions -void sm590_device::op_tl() +void sm590_device::op_atr() { - // TL xyz: long jump (same as sm510 TL except m_op and m_param masks) - do_branch(BIT(m_op, 1), (m_op << 1 & 2) | BIT(m_param, 7), m_param & 0x7f); + // ATR: output ACC to R(BL) + port_w(m_bl, m_acc); } -void sm590_device::op_tml() // aka TLS +void sm590_device::op_mtr() { - // TLS xyz: long call (same as sm510 TML except m_param mask) - push_stack(); - do_branch(BIT(m_op, 1), (m_op << 1 & 2) | BIT(m_param, 7), m_param & 0x7f); + // MTR: output RAM to R(BL) + port_w(m_bl, ram_r()); } -void sm590_device::op_t() +void sm590_device::op_rta() { - // TR xy: jump(transfer) within current page (same as sm510 T except m_op/m_pc mask) - m_pc = (m_pc & ~0x7f) | (m_op & 0x7f); + // RTA: load ACC with R(BL) + u8 offset = m_bl & 3; + m_acc = (m_rports[offset] | m_read_rx[offset]()) & 0xf; } diff --git a/src/devices/cpu/sm510/sm5a.cpp b/src/devices/cpu/sm510/sm5a.cpp index 298cefe9b2f..fe705edbe58 100644 --- a/src/devices/cpu/sm510/sm5a.cpp +++ b/src/devices/cpu/sm510/sm5a.cpp @@ -40,14 +40,14 @@ void sm5a_device::data_5x13x4(address_map &map) // 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 */, 9 /* o group pins */, 11 /* prg width */, address_map_constructor(FUNC(sm5a_device::program_1_8k), this), 7 /* data width */, address_map_constructor(FUNC(sm5a_device::data_5x13x4), this)) -{ } - sm5a_device::sm5a_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, int stack_levels, int o_pins, int prgwidth, address_map_constructor program, int datawidth, address_map_constructor data) : sm500_device(mconfig, type, tag, owner, clock, stack_levels, o_pins, prgwidth, program, datawidth, data) { } +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 */, 9 /* o group pins */, 11 /* prg width */, address_map_constructor(FUNC(sm5a_device::program_1_8k), this), 7 /* data width */, address_map_constructor(FUNC(sm5a_device::data_5x13x4), this)) +{ } + sm5l_device::sm5l_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : sm5a_device(mconfig, SM5L, tag, owner, clock, 1, 9, 11, address_map_constructor(FUNC(sm5l_device::program_1_8k), this), 7, address_map_constructor(FUNC(sm5l_device::data_5x13x4), this)) { } -- cgit v1.2.3