summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author hap <happppp@users.noreply.github.com>2017-06-24 16:21:24 +0200
committer hap <happppp@users.noreply.github.com>2017-06-24 16:21:53 +0200
commitc7301ced32518749d1b550cf40eb4fc4abf01fff (patch)
tree3d0594be11ce2d25db7ab32866628bfb2bf659a7
parent9814aba49eef1c6a810eac4349d2ed4763abdc0f (diff)
sm5*: update notes (nw)
-rw-r--r--src/devices/cpu/sm510/sm500.h16
-rw-r--r--src/devices/cpu/sm510/sm500core.cpp17
-rw-r--r--src/devices/cpu/sm510/sm500op.cpp4
-rw-r--r--src/devices/cpu/sm510/sm510.h6
-rw-r--r--src/devices/cpu/sm510/sm510base.cpp46
-rw-r--r--src/devices/cpu/sm510/sm510core.cpp5
-rw-r--r--src/devices/cpu/sm510/sm511core.cpp11
-rw-r--r--src/devices/cpu/sm510/sm590.h9
-rw-r--r--src/devices/cpu/sm510/sm590core.cpp18
-rw-r--r--src/devices/cpu/sm510/sm5acore.cpp95
10 files changed, 118 insertions, 109 deletions
diff --git a/src/devices/cpu/sm510/sm500.h b/src/devices/cpu/sm510/sm500.h
index 57b89202c3b..e09ef52147d 100644
--- a/src/devices/cpu/sm510/sm500.h
+++ b/src/devices/cpu/sm510/sm500.h
@@ -16,7 +16,7 @@
// I/O ports setup
-// ..
+// see sm510.h for ACL, K, R, alpha, beta
// pinout reference
@@ -81,14 +81,18 @@ 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;
virtual void get_opcode_param() override;
+
+ virtual void reset_vector() override { do_branch(0, 0xf, 0); }
+ virtual void wakeup_vector() override { do_branch(0, 0, 0); }
int m_o_mask; // number of 4-bit O pins minus 1
u8 m_ox[9]; // W' latch, max 9
- u8 m_o[9]; // W latch(O outputs)
- u8 m_cn; // CN(digit select)
- u8 m_mx; // m'(digit DP select)
- u8 m_cb; // CB(PC high bit buffer)
- bool m_rsub; // R(in subroutine)
+ u8 m_o[9]; // W latch
+ u8 m_cn;
+ u8 m_mx;
+ u8 m_cb;
+ u8 m_s;
+ bool m_rsub;
void shift_w();
u8 get_digit();
diff --git a/src/devices/cpu/sm510/sm500core.cpp b/src/devices/cpu/sm510/sm500core.cpp
index 1df14d4d147..f09fc515f5c 100644
--- a/src/devices/cpu/sm510/sm500core.cpp
+++ b/src/devices/cpu/sm510/sm500core.cpp
@@ -3,6 +3,9 @@
/*
Sharp SM500 MCU core implementation
+
+ TODO:
+ - EXKSA, EXKFA opcodes
*/
@@ -12,7 +15,7 @@
// MCU types
-DEFINE_DEVICE_TYPE(SM500, sm500_device, "sm500", "SM500")
+DEFINE_DEVICE_TYPE(SM500, sm500_device, "sm500", "SM500") // 1.2K ROM, 4x10x4 RAM, shift registers for LCD
// internal memory maps
@@ -91,7 +94,7 @@ void sm500_device::execute_one()
case 0x14: op_exci(); break;
case 0x18: op_lda(); break;
case 0x1c: op_excd(); break;
- case 0x54: op_tmi(); break; // aka tm
+ case 0x54: op_tmi(); break; // TM
default:
switch (m_op)
@@ -101,15 +104,15 @@ void sm500_device::execute_one()
case 0x02: op_exksa(); break;
case 0x03: op_atbp(); break;
case 0x08: op_add(); break;
- case 0x09: op_add11(); break; // aka addc
+ case 0x09: op_add11(); break; // ADDC
case 0x0a: op_coma(); break;
case 0x0b: op_exbla(); break;
- case 0x50: op_tal(); break; // aka ta: test alpha
+ case 0x50: op_tal(); break; // TA
case 0x51: op_tb(); break;
case 0x52: op_tc(); break;
case 0x53: op_tam(); break;
- case 0x58: op_tis(); break; // aka tg: test gamma
+ case 0x58: op_tis(); break; // TG
case 0x59: op_ptw(); break;
case 0x5a: op_ta0(); break;
case 0x5b: op_tabl(); break;
@@ -131,8 +134,8 @@ void sm500_device::execute_one()
case 0x6b: op_exkfa(); break;
case 0x6c: op_decb(); break;
case 0x6d: op_comcb(); break;
- case 0x6e: op_rtn0(); break; // aka rtn
- case 0x6f: op_rtn1(); break; // aka rtns
+ case 0x6e: op_rtn0(); break; // RTN
+ case 0x6f: op_rtn1(); break; // RTNS
// extended opcodes
case 0x5e:
diff --git a/src/devices/cpu/sm510/sm500op.cpp b/src/devices/cpu/sm510/sm500op.cpp
index fc18e279894..acb2864cec2 100644
--- a/src/devices/cpu/sm510/sm500op.cpp
+++ b/src/devices/cpu/sm510/sm500op.cpp
@@ -166,14 +166,18 @@ void sm500_device::op_ws()
void sm500_device::op_ats()
{
+ // ATS: transfer ACC to S
+ m_s = m_acc;
}
void sm500_device::op_exksa()
{
+ // EXKSA: x
}
void sm500_device::op_exkfa()
{
+ // EXKFA: x
}
diff --git a/src/devices/cpu/sm510/sm510.h b/src/devices/cpu/sm510/sm510.h
index 0fecde8e447..63c9b21d498 100644
--- a/src/devices/cpu/sm510/sm510.h
+++ b/src/devices/cpu/sm510/sm510.h
@@ -32,7 +32,7 @@
#define MCFG_SM510_WRITE_S_CB(_devcb) \
devcb = &sm510_base_device::set_write_s_callback(*device, DEVCB_##_devcb);
-// 2-bit R melody output port
+// 2/4-bit R (melody) output port
#define MCFG_SM510_WRITE_R_CB(_devcb) \
devcb = &sm510_base_device::set_write_r_callback(*device, DEVCB_##_devcb);
@@ -155,6 +155,9 @@ protected:
address_space_config m_data_config;
address_space *m_program;
address_space *m_data;
+
+ virtual void reset_vector() { do_branch(3, 7, 0); }
+ virtual void wakeup_vector() { do_branch(1, 0, 0); } // after halt
int m_prgwidth;
int m_datawidth;
@@ -190,6 +193,7 @@ protected:
bool m_bc;
u16 get_lcd_row(int column, u8* ram);
+ virtual void lcd_update();
TIMER_CALLBACK_MEMBER(lcd_timer_cb);
virtual void init_lcd_driver();
diff --git a/src/devices/cpu/sm510/sm510base.cpp b/src/devices/cpu/sm510/sm510base.cpp
index f77bfeb451d..07bda795f71 100644
--- a/src/devices/cpu/sm510/sm510base.cpp
+++ b/src/devices/cpu/sm510/sm510base.cpp
@@ -2,42 +2,21 @@
// 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
+ Sharp SM5xx family, using SM510 as parent device
References:
+ - 1986 Sharp Semiconductor Data Book
- 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)
+ - source organiziation between files is a mess
- 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
+
+ for more, see the *core.cpp file notes
*/
@@ -173,7 +152,7 @@ void sm510_base_device::device_reset()
m_halt = false;
m_sbm = false;
m_op = m_prev_op = 0;
- do_branch(3, 7, 0);
+ reset_vector();
m_prev_pc = m_pc;
// lcd is on (Bp on, BC off, bs(y) off)
@@ -204,7 +183,7 @@ inline u16 sm510_base_device::get_lcd_row(int column, u8* ram)
return rowdata;
}
-TIMER_CALLBACK_MEMBER(sm510_base_device::lcd_timer_cb)
+void sm510_base_device::lcd_update()
{
// 4 columns
for (int h = 0; h < 4; h++)
@@ -218,16 +197,19 @@ TIMER_CALLBACK_MEMBER(sm510_base_device::lcd_timer_cb)
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()));
+TIMER_CALLBACK_MEMBER(sm510_base_device::lcd_timer_cb)
+{
+ lcd_update();
}
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
+ attotime period = attotime::from_ticks(0x200, unscaled_clock()); // 64hz default
+ m_lcd_timer->adjust(period, 0, period);
}
@@ -244,7 +226,7 @@ bool sm510_base_device::wake_me_up()
// 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);
+ wakeup_vector();
standard_irq_callback(0);
return true;
diff --git a/src/devices/cpu/sm510/sm510core.cpp b/src/devices/cpu/sm510/sm510core.cpp
index 6dd60abccd8..e9bb5c5b089 100644
--- a/src/devices/cpu/sm510/sm510core.cpp
+++ b/src/devices/cpu/sm510/sm510core.cpp
@@ -4,6 +4,9 @@
Sharp SM510 MCU core implementation
+ TODO:
+ - buzzer control divider bit is mask-programmable?
+
*/
#include "emu.h"
@@ -12,7 +15,7 @@
// MCU types
-DEFINE_DEVICE_TYPE(SM510, sm510_device, "sm510", "SM510")
+DEFINE_DEVICE_TYPE(SM510, sm510_device, "sm510", "SM510") // 2.7Kx8 ROM, 128x4 RAM(32x4 for LCD)
// internal memory maps
diff --git a/src/devices/cpu/sm510/sm511core.cpp b/src/devices/cpu/sm510/sm511core.cpp
index d2e911b02dd..04f3cdfee24 100644
--- a/src/devices/cpu/sm510/sm511core.cpp
+++ b/src/devices/cpu/sm510/sm511core.cpp
@@ -3,6 +3,13 @@
/*
Sharp SM511 MCU core implementation
+
+ TODO:
+ - 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
*/
@@ -12,8 +19,8 @@
// MCU types
-DEFINE_DEVICE_TYPE(SM511, sm511_device, "sm511", "SM511")
-DEFINE_DEVICE_TYPE(SM512, sm512_device, "sm512", "SM512")
+DEFINE_DEVICE_TYPE(SM511, sm511_device, "sm511", "SM511") // 4Kx8 ROM, 128x4 RAM(32x4 for LCD), melody controller
+DEFINE_DEVICE_TYPE(SM512, sm512_device, "sm512", "SM512") // 4Kx8 ROM, 128x4 RAM(48x4 for LCD), melody controller
// internal memory maps
diff --git a/src/devices/cpu/sm510/sm590.h b/src/devices/cpu/sm510/sm590.h
index 517aebe37f6..42cdb879cec 100644
--- a/src/devices/cpu/sm510/sm590.h
+++ b/src/devices/cpu/sm510/sm590.h
@@ -102,14 +102,17 @@ protected:
virtual void device_reset() override;
virtual offs_t disasm_disassemble(std::ostream &stream, offs_t pc, const u8 *oprom, const u8 *opram, u32 options) override;
- virtual void init_divider() override;
- virtual void init_lcd_driver() override;
- virtual void init_melody() override;
+ virtual void init_divider() override { }
+ virtual void init_lcd_driver() override { }
+ virtual void init_melody() override { }
virtual void increment_pc() override;
virtual void execute_one() override;
virtual void get_opcode_param() 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;
diff --git a/src/devices/cpu/sm510/sm590core.cpp b/src/devices/cpu/sm510/sm590core.cpp
index 4abe76a2d80..a44f7c83296 100644
--- a/src/devices/cpu/sm510/sm590core.cpp
+++ b/src/devices/cpu/sm510/sm590core.cpp
@@ -3,6 +3,9 @@
/*
Sharp SM590 MCU core implementation
+
+ TODO:
+ - finish SM590/SM595 emulation (NES/SNES CIC)
*/
@@ -12,9 +15,9 @@
// MCU types
-DEFINE_DEVICE_TYPE(SM590, sm590_device, "sm590", "SM590")
-//DEFINE_DEVICE_TYPE(SM591, sm591_device, "sm591", "SM591")
-//DEFINE_DEVICE_TYPE(SM595, sm595_device, "sm595", "SM595")
+DEFINE_DEVICE_TYPE(SM590, sm590_device, "sm590", "SM590") // 512x8 ROM, 32x4 RAM
+//DEFINE_DEVICE_TYPE(SM591, sm591_device, "sm591", "SM591") // 1kx8 ROM, 56x4 RAM
+//DEFINE_DEVICE_TYPE(SM595, sm595_device, "sm595", "SM595") // 768x8 ROM, 32x4 RAM
// internal memory maps
static ADDRESS_MAP_START(program_1x128x4, AS_PROGRAM, 8, sm510_base_device)
@@ -83,7 +86,7 @@ void sm590_device::device_reset()
m_halt = false;
m_sbm = false; // needed?
m_op = m_prev_op = 0;
- do_branch(0, 0, 0);
+ reset_vector();
m_prev_pc = m_pc;
m_rports[0] = m_rports[1] = m_rports[2] = m_rports[3] = 0;
@@ -91,13 +94,6 @@ void sm590_device::device_reset()
}
//-------------------------------------------------
-// init overrides
-//-------------------------------------------------
-void sm590_device::init_divider() {} // doesn't have it
-void sm590_device::init_lcd_driver() {} // doesn't have it
-void sm590_device::init_melody() {} // doesn't have it
-
-//-------------------------------------------------
// execute
//-------------------------------------------------
void sm590_device::increment_pc()
diff --git a/src/devices/cpu/sm510/sm5acore.cpp b/src/devices/cpu/sm510/sm5acore.cpp
index ab402e535ba..04989bef418 100644
--- a/src/devices/cpu/sm510/sm5acore.cpp
+++ b/src/devices/cpu/sm510/sm5acore.cpp
@@ -3,6 +3,9 @@
/*
Sharp SM5A MCU core implementation
+
+ TODO:
+ - confirm SM5A mnemonics
*/
@@ -12,9 +15,9 @@
// 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")
+DEFINE_DEVICE_TYPE(SM5A, sm5a_device, "sm5a", "SM5A") // 1.8K ROM, 5x13x4 RAM, shift registers for LCD
+DEFINE_DEVICE_TYPE(SM5L, sm5l_device, "sm5l", "SM5L") // low-power version of SM5A
+DEFINE_DEVICE_TYPE(KB1013VK12, kb1013vk12_device, "kb1013vk1_2", "KB1013VK1-2") // Soviet-era clone of SM5A
// internal memory maps
@@ -71,75 +74,75 @@ 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 0x20: op_lax(); break;
+ case 0x30: op_adx(); break;
+ case 0x40: op_lb(); break;
+ case 0x70: op_ssr(); break;
case 0x80: case 0x90: case 0xa0: case 0xb0:
- op_tr(); break; // BR (LP+this=JMP)
+ op_tr(); break;
case 0xc0: case 0xd0: case 0xe0: case 0xf0:
- op_trs(); break; // CBR/CZP (LP+this=CAL)
+ op_trs(); break;
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
+ case 0x04: op_rm(); break;
+ case 0x0c: op_sm(); break;
+ case 0x10: op_exc(); break;
+ case 0x14: op_exci(); break;
+ case 0x18: op_lda(); break;
+ case 0x1c: op_excd(); break;
+ case 0x54: op_tmi(); break;
default:
switch (m_op)
{
- case 0x00: op_skip(); break; // NOP
- case 0x01: op_atr(); break; // OAR
- case 0x02: op_sbm(); break; // *BS1
+ case 0x00: op_skip(); break;
+ case 0x01: op_atr(); break;
+ case 0x02: op_sbm(); break;
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 0x08: op_add(); break;
+ case 0x09: op_add11(); break;
+ case 0x0a: op_coma(); break;
+ case 0x0b: op_exbla(); break;
+
+ case 0x50: op_tal(); break;
+ case 0x51: op_tb(); break;
+ case 0x52: op_tc(); break;
+ case 0x53: op_tam(); break;
+ case 0x58: op_tis(); break;
case 0x59: op_ptw(); break;
- case 0x5a: op_ta0(); break; // SAO
- case 0x5b: op_tabl(); break; // SAL
+ case 0x5a: op_ta0(); break;
+ case 0x5b: op_tabl(); break;
case 0x5c: op_tw(); break;
case 0x5d: op_dtw(); break;
- case 0x5f: op_lbl(); break; // LAF
+ case 0x5f: op_lbl(); break;
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
+ case 0x64: op_incb(); break;
+ case 0x65: op_idiv(); break;
+ case 0x66: op_rc(); break;
+ case 0x67: op_sc(); break;
+ case 0x68: op_rmf(); break;
+ case 0x69: op_smf(); break;
+ case 0x6a: op_kta(); break;
+ case 0x6b: op_rbm(); break;
+ case 0x6c: op_decb(); break;
+ case 0x6d: op_comcb(); break;
+ case 0x6e: op_rtn0(); break;
+ case 0x6f: op_rtn1(); break;
// 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
+ case 0x00: op_cend(); break;
+ case 0x04: op_dta(); break;
default: op_illegal(); break;
}