sm590: added i/o ports

This commit is contained in:
hap 2022-03-14 22:07:33 +01:00
parent ca467d4cdb
commit f1f36c9ba0
13 changed files with 277 additions and 250 deletions

View File

@ -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<util::disasm_interface> sm500_device::create_disassembler()

View File

@ -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()

View File

@ -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;

View File

@ -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

View File

@ -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[];

View File

@ -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()

View File

@ -54,14 +54,14 @@ std::unique_ptr<util::disasm_interface> 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))
{ }

View File

@ -46,15 +46,15 @@ std::unique_ptr<util::disasm_interface> 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

View File

@ -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();

View File

@ -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,60 +18,96 @@
// 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(0x00, 0x0f).ram();
map(0x10, 0x1f).ram();
map(0x000, 0x2ff).rom();
}
void sm590_device::program_1kx8(address_map &map)
{
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))
{ }
//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))
//{ }
//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))
//{ }
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)
sm510_base_device(mconfig, type, tag, owner, clock, stack_levels, prgwidth, program, datawidth, data),
m_write_rx(*this),
m_read_rx(*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))
{ }
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))
{ }
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<util::disasm_interface> sm590_device::create_disassembler()
{
return std::make_unique<sm590_disassembler>();
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void sm590_device::device_start()
{
// 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));
}
//-------------------------------------------------
// device_reset - device-specific reset
//-------------------------------------------------
void sm590_device::device_reset()
{
// ACL
m_skip = false;
m_halt = false;
m_op = m_prev_op = 0;
reset_vector();
m_prev_pc = m_pc;
// common reset
sm510_base_device::device_reset();
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?
// clear outputs
for (int i = 0; i < 4; i++)
port_w(i, 0);
}
@ -78,17 +115,9 @@ void sm590_device::device_reset()
// execute
//-------------------------------------------------
void sm590_device::increment_pc()
{
// 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);
}
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;
}

View File

@ -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 <std::size_t Bit> auto write_r() { return m_write_rx[Bit].bind(); }
template <std::size_t Bit> 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<util::disasm_interface> 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
// opcode handlers
virtual void do_branch(u8 pu, u8 pm, u8 pl) override;
void port_w(offs_t offset, u8 data);
virtual void op_tl() override;
virtual void op_tls();
virtual void op_lblx();
virtual void op_lbmx();
virtual void op_str();
virtual void op_lda() override;
virtual void op_exc() override;
// exci (same as sm510)
// excd (same as sm510)
// 44-47
// coma (same as sm510)
// tam (same as sm510)
virtual void op_atr() override;
virtual void op_mtr();
// 48-4b
// rc (same as sm510)
// sc (same as sm510)
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
// 50-53
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
virtual void op_blta();
// 60-6f
// tm (same as sm510 tmi)
virtual void op_tba();
// rm (same as sm510)
// sm (same as sm510)
// 70-73
// add (same as sm510)
virtual void op_adx() override;
virtual void op_ads();
virtual void op_adc();
// adcs (same as sm510 add11)
virtual void op_inbm();
virtual void op_debm();
// 74-7f
virtual void op_lbmx();
virtual void op_tl() override;
virtual void op_tml() override; // aka TLS
virtual void op_tax();
virtual void op_tba();
virtual void op_tc() override;
// 80-ff
virtual void op_t() override; // aka TR
virtual void op_atr() override;
virtual void op_mtr();
virtual void op_rta();
};
u8 m_rports[4];
class sm591_device : public sm590_device
{
public:
sm591_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
};
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

View File

@ -11,95 +11,71 @@
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()
{
// 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?
}
void sm590_device::op_mtr()
{
// 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?
}
void sm590_device::op_str()
{
// STR: output ACC to RAM
ram_w(m_acc);
}
void sm590_device::op_inbm()
{
// INBM: increment BM
m_bm = (m_bm + 1) & 0x3; // is this mask correct?
}
void sm590_device::op_debm()
{
// DEBM: decrement BM
m_bm = (m_bm - 1) & 0x3; // is this mask correct?
}
void sm590_device::op_tc()
{
// TC: skip next if carry
m_skip = bool(m_c);
}
void sm590_device::op_rta()
{
// 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?
}
void sm590_device::op_blta()
{
// BLTA: load ACC with BL
m_acc = m_bl;
}
void sm590_device::op_exax()
{
// EXAX: exchange X with ACC
@ -108,10 +84,21 @@ void sm590_device::op_exax()
m_x = a;
}
void sm590_device::op_tba()
void sm590_device::op_blta()
{
// TBA x: skip next if ACC bit is set
m_skip = ((m_acc & bitmask(m_op)) != 0);
// BLTA: load ACC with BL
m_acc = m_bl;
}
// Arithmetic instructions
void sm590_device::op_adx()
{
// 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_ads()
@ -125,32 +112,61 @@ void sm590_device::op_ads()
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;
op_add11();
m_skip = false; // no skip
}
void sm590_device::op_lbmx()
void sm590_device::op_inbm()
{
// LBM x: load BM with 2-bit immediate value
m_bm = (m_op & 0x3);
// INBM: increment BM
m_bm = (m_bm + 1) & m_datamask >> 4;
}
void sm590_device::op_tl()
void sm590_device::op_debm()
{
// 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);
// DEBM: decrement BM
m_bm = (m_bm - 1) & m_datamask >> 4;
}
void sm590_device::op_tml() // aka TLS
// Test instructions
void sm590_device::op_tax()
{
// 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);
// TAX: skip next if ACC equals 4-bit immediate value
m_skip = (m_acc == (m_op & 0xf));
}
void sm590_device::op_t()
void sm590_device::op_tba()
{
// 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);
// TBA x: skip next if ACC bit is set
m_skip = ((m_acc & bitmask(m_op)) != 0);
}
void sm590_device::op_tc()
{
// TC: skip next if carry
m_skip = bool(m_c);
}
// I/O instructions
void sm590_device::op_atr()
{
// ATR: output ACC to R(BL)
port_w(m_bl, m_acc);
}
void sm590_device::op_mtr()
{
// MTR: output RAM to R(BL)
port_w(m_bl, ram_r());
}
void sm590_device::op_rta()
{
// RTA: load ACC with R(BL)
u8 offset = m_bl & 3;
m_acc = (m_rports[offset] | m_read_rx[offset]()) & 0xf;
}

View File

@ -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))
{ }