mirror of
https://github.com/holub/mame
synced 2025-04-21 07:52:35 +03:00
Add preliminary Sharp SM590 CPU core [Lord Nightmare, hap]
This commit is contained in:
parent
790c23ff29
commit
3d18cb2faa
@ -1769,6 +1769,9 @@ if (CPUS["SM510"]~=null) then
|
||||
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/sm590.h",
|
||||
MAME_DIR .. "src/devices/cpu/sm510/sm590op.cpp",
|
||||
MAME_DIR .. "src/devices/cpu/sm510/sm590core.cpp",
|
||||
}
|
||||
end
|
||||
|
||||
|
@ -18,9 +18,9 @@
|
||||
- *KB1013VK1-2: Soviet-era clone of SM500, minor differences
|
||||
|
||||
Sharp SM590 MCU family:
|
||||
- *SM590: x
|
||||
- *SM591: x
|
||||
- *SM595: x
|
||||
- *SM590: 512x8 ROM, 32x4 RAM
|
||||
- *SM591: 1kx8 ROM, 56x4 RAM
|
||||
- *SM595: 768x8 ROM, 32x4 RAM
|
||||
|
||||
References:
|
||||
- 1990 Sharp Microcomputers Data Book
|
||||
@ -54,7 +54,7 @@
|
||||
|
||||
enum
|
||||
{
|
||||
SM510_PC=1, SM510_ACC, SM510_BL, SM510_BM,
|
||||
SM510_PC=1, SM510_ACC, SM510_X, SM510_BL, SM510_BM,
|
||||
SM510_C, SM510_W
|
||||
};
|
||||
|
||||
@ -144,6 +144,7 @@ void sm510_base_device::device_start()
|
||||
// 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");
|
||||
|
@ -220,7 +220,7 @@ protected:
|
||||
devcb_write8 m_write_r;
|
||||
|
||||
// misc internal helpers
|
||||
void increment_pc();
|
||||
virtual void increment_pc();
|
||||
virtual void get_opcode_param() { }
|
||||
virtual void update_w_latch() { }
|
||||
|
||||
@ -228,7 +228,7 @@ protected:
|
||||
void ram_w(u8 data);
|
||||
void pop_stack();
|
||||
void push_stack();
|
||||
void do_branch(u8 pu, u8 pm, u8 pl);
|
||||
virtual void do_branch(u8 pu, u8 pm, u8 pl);
|
||||
u8 bitmask(u16 param);
|
||||
|
||||
// opcode handlers
|
||||
|
@ -1,5 +1,5 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:hap
|
||||
// copyright-holders:hap, Jonathan Gevaryahu
|
||||
/*
|
||||
|
||||
Sharp SM510/SM500 MCU family disassembler
|
||||
@ -38,7 +38,12 @@ enum e_mnemonics
|
||||
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
|
||||
mBR, mLP, mCBR, mCMS, mRT, mRTS, mSI1, mSI0, mSYN, mTIM, mHLT,
|
||||
|
||||
// SM590 aliases
|
||||
mCCTRL, mINBL, mDEBL, mXBLA, mADCS, mTR7,
|
||||
// SM590 uniques
|
||||
mTAX, mLBLX, mMTR, mSTR, mINBM, mDEBM, mRTA, mBLTA, mEXAX, mTBA, mADS, mADC, mLBMX, mTLS
|
||||
};
|
||||
|
||||
static const char *const s_mnemonics[] =
|
||||
@ -65,7 +70,12 @@ static const char *const s_mnemonics[] =
|
||||
"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"
|
||||
"BR", "LP", "CBR", "CMS", "RT", "RTS", "SI1", "SI0", "SYN", "TIM", "HLT",
|
||||
|
||||
//
|
||||
"CCTRL", "INBL", "DEBL", "XBLA", "ADCS", "TR",
|
||||
//
|
||||
"TAX", "LBLX", "MTR", "STR", "INBM", "DEBM", "RTA", "BLTA", "EXAX", "TBA", "ADS", "ADC", "LBMX", "TLS"
|
||||
};
|
||||
|
||||
// number of bits per opcode parameter, 8 or larger means 2-byte opcode
|
||||
@ -93,7 +103,12 @@ static const u8 s_bits[] =
|
||||
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
|
||||
6, 4, 6, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
|
||||
//
|
||||
0, 0, 0, 0, 0, 7,
|
||||
//
|
||||
4, 4, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 2, 2+8
|
||||
};
|
||||
|
||||
#define _OVER DASMFLAG_STEP_OVER
|
||||
@ -123,11 +138,16 @@ static const u32 s_flags[] =
|
||||
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, _OVER, 0, _OUT, _OUT, 0, 0, 0, 0, _OVER,
|
||||
|
||||
//
|
||||
0, 0, 0, 0, 0, _OVER,
|
||||
//
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, _OVER
|
||||
};
|
||||
|
||||
// next program counter in sequence (relative)
|
||||
static const s8 s_next_pc[0x40] =
|
||||
static const s8 s_next_pc_6[0x40] =
|
||||
{
|
||||
32, -1 /* rollback */, -1, 30, 30, -3, -3, 28, 28, -5, -5, 26, 26, -7, -7, 24,
|
||||
24, -9, -9, 22, 22, -11, -11, 20, 20, -13, -13, 18, 18, -15, -15, 16,
|
||||
@ -135,15 +155,27 @@ static const s8 s_next_pc[0x40] =
|
||||
8, -25, -25, 6, 6, -27, -27, 4, 4, -29, -29, 2, 2, -31, -31, 0 /* gets stuck here */
|
||||
};
|
||||
|
||||
static const s8 s_next_pc_7[0x80] =
|
||||
{
|
||||
64, -1 /* rollback */, -1, 62, 62, -3, -3, 60, 60, -5, -5, 58, 58, -7, -7, 56,
|
||||
56, -9, -9, 54, 54, -11, -11, 52, 52, -13, -13, 50, 50, -15, -15, 48,
|
||||
48, -17, -17, 46, 46, -19, -19, 44, 44, -21, -21, 42, 42, -23, -23, 40,
|
||||
40, -25, -25, 38, 38, -27, -27, 36, 36, -29, -29, 34, 34, -31, -31, 32,
|
||||
32, -33, -33, 30, 30, -35, -35, 28, 28, -37, -37, 26, 26, -39, -39, 24,
|
||||
24, -41, -41, 22, 22, -43, -43, 20, 20, -45, -45, 18, 18, -47, -47, 16,
|
||||
16, -49, -49, 14, 14, -51, -51, 12, 12, -53, -53, 10, 10, -55, -55, 8,
|
||||
8, -57, -57, 6, 6, -59, -59, 4, 4, -61, -61, 2, 2, -63, -63, 0 /* gets stuck here */
|
||||
};
|
||||
|
||||
|
||||
// common disasm
|
||||
|
||||
static offs_t sm510_common_disasm(const u8 *lut_mnemonic, const u8 *lut_extended, std::ostream &stream, offs_t pc, const u8 *oprom, const u8 *opram)
|
||||
static offs_t sm510_common_disasm(const u8 *lut_mnemonic, const u8 *lut_extended, std::ostream &stream, offs_t pc, const u8 *oprom, const u8 *opram, const u8 pclen)
|
||||
{
|
||||
// get raw opcode
|
||||
u8 op = oprom[0];
|
||||
u8 instr = lut_mnemonic[op];
|
||||
s8 s_next_pc = ((pclen==6)?s_next_pc_6[pc & 0x3f]:s_next_pc_7[pc & 0x7f]);
|
||||
int len = 1;
|
||||
|
||||
int bits = s_bits[instr];
|
||||
@ -153,7 +185,7 @@ static offs_t sm510_common_disasm(const u8 *lut_mnemonic, const u8 *lut_extended
|
||||
{
|
||||
// note: disasm view shows correct parameter, but raw view does not
|
||||
// note2: oprom array negative index doesn't work either :(
|
||||
param = oprom[s_next_pc[pc & 0x3f]];
|
||||
param = oprom[s_next_pc];
|
||||
len++;
|
||||
}
|
||||
|
||||
@ -186,7 +218,7 @@ static offs_t sm510_common_disasm(const u8 *lut_mnemonic, const u8 *lut_extended
|
||||
|
||||
// show param offset
|
||||
if (bits >= 8)
|
||||
util::stream_format(stream, " [$%03X]", pc + s_next_pc[pc & 0x3f]);
|
||||
util::stream_format(stream, " [$%03X]", pc + s_next_pc);
|
||||
}
|
||||
|
||||
return len | s_flags[instr] | DASMFLAG_SUPPORTED;
|
||||
@ -221,7 +253,7 @@ static const u8 sm510_mnemonic[0x100] =
|
||||
|
||||
CPU_DISASSEMBLE(sm510)
|
||||
{
|
||||
return sm510_common_disasm(sm510_mnemonic, nullptr, stream, pc, oprom, opram);
|
||||
return sm510_common_disasm(sm510_mnemonic, nullptr, stream, pc, oprom, opram, 6);
|
||||
}
|
||||
|
||||
|
||||
@ -263,7 +295,7 @@ CPU_DISASSEMBLE(sm511)
|
||||
memset(ext, 0, 0x100);
|
||||
memcpy(ext + 0x30, sm511_extended, 0x10);
|
||||
|
||||
return sm510_common_disasm(sm511_mnemonic, ext, stream, pc, oprom, opram);
|
||||
return sm510_common_disasm(sm511_mnemonic, ext, stream, pc, oprom, opram, 6);
|
||||
}
|
||||
|
||||
|
||||
@ -305,7 +337,7 @@ CPU_DISASSEMBLE(sm500)
|
||||
memset(ext, 0, 0x100);
|
||||
memcpy(ext + 0x00, sm500_extended, 0x10);
|
||||
|
||||
return sm510_common_disasm(sm500_mnemonic, ext, stream, pc, oprom, opram);
|
||||
return sm510_common_disasm(sm500_mnemonic, ext, stream, pc, oprom, opram, 6);
|
||||
}
|
||||
|
||||
|
||||
@ -347,5 +379,38 @@ CPU_DISASSEMBLE(kb1013vk12)
|
||||
memset(ext, 0, 0x100);
|
||||
memcpy(ext + 0x00, kb1013vk12_extended, 0x10);
|
||||
|
||||
return sm510_common_disasm(kb1013vk12_mnemonic, ext, stream, pc, oprom, opram);
|
||||
return sm510_common_disasm(kb1013vk12_mnemonic, ext, stream, pc, oprom, opram, 6);
|
||||
}
|
||||
|
||||
|
||||
// SM590 disasm
|
||||
|
||||
static const u8 sm590_mnemonic[0x100] =
|
||||
{
|
||||
/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
|
||||
mNOP, mADX, mADX, mADX, mADX, mADX, mADX, mADX, mADX, mADX, mADX, mADX, mADX, mADX, mADX, mADX, // 0
|
||||
mTAX, mTAX, mTAX, mTAX, mTAX, mTAX, mTAX, mTAX, mTAX, mTAX, mTAX, mTAX, mTAX, mTAX, mTAX, mTAX, // 1
|
||||
mLBLX, mLBLX, mLBLX, mLBLX, mLBLX, mLBLX, mLBLX, mLBLX, mLBLX, mLBLX, mLBLX, mLBLX, mLBLX, mLBLX, mLBLX, mLBLX, // 2
|
||||
mLAX, mLAX, mLAX, mLAX, mLAX, mLAX, mLAX, mLAX, mLAX, mLAX, mLAX, mLAX, mLAX, mLAX, mLAX, mLAX, // 3
|
||||
|
||||
mLDA, mEXC, mEXCI, mEXCD, mCOMA, mTAM, mATR, mMTR, mRC, mSC, mSTR, mCCTRL,mRTN, mRTNS, 0, 0, // 4
|
||||
mINBM, mDEBM, mINBL, mDEBL, mTC, mRTA, mBLTA, mXBLA, 0, 0, 0, 0, mATX, mEXAX, 0, 0, // 5
|
||||
mTMI, mTMI, mTMI, mTMI, mTBA, mTBA, mTBA, mTBA, mRM, mRM, mRM, mRM, mSM, mSM, mSM, mSM, // 6
|
||||
mADD, mADS, mADC, mADCS, mLBMX, mLBMX, mLBMX, mLBMX, mTL, mTL, mTL, mTL, mTLS, mTLS, mTLS, mTLS, // 7
|
||||
|
||||
mTR7, mTR7, mTR7, mTR7, mTR7, mTR7, mTR7, mTR7, mTR7, mTR7, mTR7, mTR7, mTR7, mTR7, mTR7, mTR7, // 8
|
||||
mTR7, mTR7, mTR7, mTR7, mTR7, mTR7, mTR7, mTR7, mTR7, mTR7, mTR7, mTR7, mTR7, mTR7, mTR7, mTR7, // 9
|
||||
mTR7, mTR7, mTR7, mTR7, mTR7, mTR7, mTR7, mTR7, mTR7, mTR7, mTR7, mTR7, mTR7, mTR7, mTR7, mTR7, // A
|
||||
mTR7, mTR7, mTR7, mTR7, mTR7, mTR7, mTR7, mTR7, mTR7, mTR7, mTR7, mTR7, mTR7, mTR7, mTR7, mTR7, // B
|
||||
|
||||
mTR7, mTR7, mTR7, mTR7, mTR7, mTR7, mTR7, mTR7, mTR7, mTR7, mTR7, mTR7, mTR7, mTR7, mTR7, mTR7, // C
|
||||
mTR7, mTR7, mTR7, mTR7, mTR7, mTR7, mTR7, mTR7, mTR7, mTR7, mTR7, mTR7, mTR7, mTR7, mTR7, mTR7, // D
|
||||
mTR7, mTR7, mTR7, mTR7, mTR7, mTR7, mTR7, mTR7, mTR7, mTR7, mTR7, mTR7, mTR7, mTR7, mTR7, mTR7, // E
|
||||
mTR7, mTR7, mTR7, mTR7, mTR7, mTR7, mTR7, mTR7, mTR7, mTR7, mTR7, mTR7, mTR7, mTR7, mTR7, mTR7 // F
|
||||
};
|
||||
|
||||
|
||||
CPU_DISASSEMBLE(sm590)
|
||||
{
|
||||
return sm510_common_disasm(sm590_mnemonic, nullptr, stream, pc, oprom, opram, 7);
|
||||
}
|
@ -9,14 +9,14 @@
|
||||
|
||||
// internal helpers
|
||||
|
||||
inline u8 sm510_base_device::ram_r()
|
||||
u8 sm510_base_device::ram_r()
|
||||
{
|
||||
int bmh = (m_sbm) ? (1 << (m_datawidth-1)) : 0; // from SBM
|
||||
u8 address = (bmh | m_bm << 4 | m_bl) & m_datamask;
|
||||
return m_data->read_byte(address) & 0xf;
|
||||
}
|
||||
|
||||
inline void sm510_base_device::ram_w(u8 data)
|
||||
void sm510_base_device::ram_w(u8 data)
|
||||
{
|
||||
int bmh = (m_sbm) ? (1 << (m_datawidth-1)) : 0; // from SBM
|
||||
u8 address = (bmh | m_bm << 4 | m_bl) & m_datamask;
|
||||
@ -43,7 +43,7 @@ void sm510_base_device::do_branch(u8 pu, u8 pm, u8 pl)
|
||||
m_pc = ((pu << 10 & 0xc00) | (pm << 6 & 0x3c0) | (pl & 0x03f)) & m_prgmask;
|
||||
}
|
||||
|
||||
inline u8 sm510_base_device::bitmask(u16 param)
|
||||
u8 sm510_base_device::bitmask(u16 param)
|
||||
{
|
||||
// bitmask from immediate opcode param
|
||||
return 1 << (param & 3);
|
||||
|
187
src/devices/cpu/sm510/sm590.h
Normal file
187
src/devices/cpu/sm510/sm590.h
Normal file
@ -0,0 +1,187 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:hap, Jonathan Gevaryahu
|
||||
/*
|
||||
|
||||
Sharp SM590 MCU family cores
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _SM590_H_
|
||||
#define _SM590_H_
|
||||
|
||||
#include "sm510.h"
|
||||
|
||||
|
||||
// I/O ports setup
|
||||
|
||||
// ..
|
||||
|
||||
|
||||
// pinout reference
|
||||
|
||||
/*
|
||||
|
||||
16-pin DIP SM590/591/595:
|
||||
____ ____
|
||||
_|* \__/ |_
|
||||
R0.0 <> |_|1 16|_| -- VDD(5v)
|
||||
_| |_
|
||||
R0.1 <> |_|2 15|_| <> R2.2
|
||||
_| |_
|
||||
R0.2 <> |_|3 14|_| <> R2.1
|
||||
_| |_
|
||||
R0.3 <> |_|4 13|_| <> R2.0
|
||||
_| |_
|
||||
R3.3/CL2 => |_|5 12|_| <> R1.3
|
||||
_| |_
|
||||
CL1 == |_|6 11|_| <> R1.2
|
||||
_| |_
|
||||
ACL -> |_|7 10|_| <> R1.1
|
||||
_| |_
|
||||
GND -- |_|8 9|_| <> R1.0
|
||||
|____________|
|
||||
|
||||
|
||||
18-pin DIP SM590/591/595:
|
||||
____ ____
|
||||
_|* \__/ |_
|
||||
R0.0 <> |_|1 18|_| -- VDD(5v)
|
||||
_| |_
|
||||
R0.1 <> |_|2 17|_| <> R2.2
|
||||
_| |_
|
||||
R2.3 <> |_|3 16|_| <> R3.0
|
||||
_| |_
|
||||
R0.2 <> |_|4 15|_| <> R2.1
|
||||
_| |_
|
||||
R0.3 <> |_|5 14|_| <> R2.0
|
||||
_| |_
|
||||
R3.3/CL2 => |_|6 13|_| <> R1.3
|
||||
_| |_
|
||||
CL1 == |_|7 12|_| <> R1.2
|
||||
_| |_
|
||||
ACL -> |_|8 11|_| <> R1.1
|
||||
_| |_
|
||||
GND -- |_|9 10|_| <> R1.0
|
||||
|____________|
|
||||
|
||||
|
||||
20-pin DIP SM590/591/595:
|
||||
____ ____
|
||||
_|* \__/ |_
|
||||
R0.0 <> |_|1 20|_| -- VDD(5v)
|
||||
_| |_
|
||||
R0.1 <> |_|2 19|_| <> R2.2
|
||||
_| |_
|
||||
R2.3 <> |_|3 18|_| <> R3.0
|
||||
_| |_
|
||||
R0.2 <> |_|4 17|_| <> R2.1
|
||||
_| |_
|
||||
R0.3 <> |_|5 16|_| <> R2.0
|
||||
_| |_
|
||||
R3.3/CL2 => |_|6 15|_| <> R1.3
|
||||
_| |_
|
||||
CL1 == |_|7 14|_| <> R1.2
|
||||
_| |_
|
||||
R3.2 <> |_|8 13|_| <> R3.1
|
||||
_| |_
|
||||
ACL -> |_|9 12|_| <> R1.1
|
||||
_| |_
|
||||
GND -- |_|10 11|_| <> R1.0
|
||||
|____________|
|
||||
|
||||
|
||||
*/
|
||||
|
||||
class sm590_device : public sm510_base_device
|
||||
{
|
||||
public:
|
||||
sm590_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
|
||||
sm590_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, u32 clock, int stack_levels, int prgwidth, address_map_constructor program, int datawidth, address_map_constructor data, const char *shortname, const char *source);
|
||||
|
||||
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 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;
|
||||
|
||||
// opcode handlers
|
||||
// 00-3f
|
||||
// adx (same as sm510)
|
||||
virtual void op_tax();
|
||||
virtual void op_lblx();
|
||||
// lax (same as sm510)
|
||||
|
||||
// 40-43
|
||||
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
|
||||
|
||||
// 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_ads();
|
||||
virtual void op_adc();
|
||||
// adcs (same as sm510 add11)
|
||||
|
||||
// 74-7f
|
||||
virtual void op_lbmx();
|
||||
virtual void op_tl() override;
|
||||
virtual void op_tml() override; // aka TLS
|
||||
|
||||
// 80-ff
|
||||
virtual void op_t() override; // aka TR
|
||||
|
||||
u8 m_rports[4];
|
||||
};
|
||||
|
||||
|
||||
extern const device_type SM590;
|
||||
|
||||
|
||||
#endif /* _SM590_H_ */
|
190
src/devices/cpu/sm510/sm590core.cpp
Normal file
190
src/devices/cpu/sm510/sm590core.cpp
Normal file
@ -0,0 +1,190 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:hap, Jonathan Gevaryahu
|
||||
/*
|
||||
|
||||
Sharp SM590 MCU core implementation
|
||||
|
||||
*/
|
||||
|
||||
#include "emu.h"
|
||||
#include "sm590.h"
|
||||
#include "debugger.h"
|
||||
|
||||
|
||||
// MCU types
|
||||
const device_type SM590 = device_creator<sm590_device>;
|
||||
//const device_type SM591 = device_creator<sm591_device>;
|
||||
//const device_type SM595 = device_creator<sm595_device>;
|
||||
|
||||
// internal memory maps
|
||||
static ADDRESS_MAP_START(program_1x128x4, AS_PROGRAM, 8, sm510_base_device)
|
||||
AM_RANGE(0x000, 0x200) AM_ROM
|
||||
ADDRESS_MAP_END
|
||||
|
||||
/*static ADDRESS_MAP_START(program_2x128x4, AS_PROGRAM, 8, sm510_base_device)
|
||||
AM_RANGE(0x000, 0x400) AM_ROM
|
||||
ADDRESS_MAP_END
|
||||
|
||||
static ADDRESS_MAP_START(program_1x128x4_1x128x2, AS_PROGRAM, 8, sm510_base_device)
|
||||
AM_RANGE(0x000, 0x300) AM_ROM
|
||||
ADDRESS_MAP_END*/
|
||||
|
||||
static ADDRESS_MAP_START(data_16x2x4, AS_DATA, 8, sm510_base_device)
|
||||
AM_RANGE(0x00, 0x0f) AM_RAM
|
||||
AM_RANGE(0x10, 0x1f) AM_RAM
|
||||
ADDRESS_MAP_END
|
||||
|
||||
/*
|
||||
static ADDRESS_MAP_START(data_16x3.5x4, AS_DATA, 8, sm510_base_device)
|
||||
AM_RANGE(0x00, 0x0f) AM_RAM
|
||||
AM_RANGE(0x10, 0x1f) AM_RAM
|
||||
AM_RANGE(0x20, 0x2f) AM_RAM
|
||||
AM_RANGE(0x30, 0x37) AM_RAM
|
||||
ADDRESS_MAP_END
|
||||
*/
|
||||
|
||||
// device definitions
|
||||
sm590_device::sm590_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
|
||||
: sm510_base_device(mconfig, SM590, "SM590", tag, owner, clock, 4 /* stack levels */, 10 /* prg width */, ADDRESS_MAP_NAME(program_1x128x4), 5 /* data width */, ADDRESS_MAP_NAME(data_16x2x4), "sm590", __FILE__)
|
||||
{ }
|
||||
|
||||
//sm590_device::sm591_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
|
||||
// : sm510_base_device(mconfig, SM591, "SM591", tag, owner, clock, 4 /* stack levels */, 10 /* prg width */, ADDRESS_MAP_NAME(program_2x128x4), 6 /* data width */, ADDRESS_MAP_NAME(data_16x3.5x4), "sm591", __FILE__)
|
||||
//{ }
|
||||
|
||||
//sm590_device::sm595_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
|
||||
// : sm510_base_device(mconfig, SM595, "SM595", tag, owner, clock, 4 /* stack levels */, 10 /* prg width */, ADDRESS_MAP_NAME(program_1x128x4_1x128x2), 5 /* data width */, ADDRESS_MAP_NAME(data_16x2x4), "sm595", __FILE__)
|
||||
//{ }
|
||||
|
||||
sm590_device::sm590_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, u32 clock, int stack_levels, int prgwidth, address_map_constructor program, int datawidth, address_map_constructor data, const char *shortname, const char *source)
|
||||
: sm510_base_device(mconfig, type, name, tag, owner, clock, stack_levels, prgwidth, program, datawidth, data, shortname, source)
|
||||
{ }
|
||||
|
||||
|
||||
// disasm
|
||||
offs_t sm590_device::disasm_disassemble(std::ostream &stream, offs_t pc, const u8 *oprom, const u8 *opram, u32 options)
|
||||
{
|
||||
extern CPU_DISASSEMBLE(sm590);
|
||||
return CPU_DISASSEMBLE_NAME(sm590)(this, stream, pc, oprom, opram, options);
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_reset - device-specific reset
|
||||
//-------------------------------------------------
|
||||
void sm590_device::device_reset()
|
||||
{
|
||||
// ACL
|
||||
m_skip = false;
|
||||
m_halt = false;
|
||||
m_sbm = false;
|
||||
m_op = m_prev_op = 0;
|
||||
do_branch(0, 0, 0);
|
||||
m_prev_pc = m_pc;
|
||||
|
||||
m_rports[0] = m_rports[1] = m_rports[2] = m_rports[3] = 0;
|
||||
//m_write_r(0, 0, 0xff);
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// 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::get_opcode_param()
|
||||
{
|
||||
// TL, TLS(TML) opcodes are 2 bytes
|
||||
if ((m_op & 0xf8) == 0x78)
|
||||
{
|
||||
m_icount--;
|
||||
m_param = m_program->read_byte(m_pc);
|
||||
increment_pc();
|
||||
}
|
||||
}
|
||||
|
||||
void sm590_device::execute_one()
|
||||
{
|
||||
switch (m_op & 0xf0) // opcodes with 4 bit params
|
||||
{
|
||||
case 0x00: op_adx(); break;
|
||||
case 0x10: op_tax(); break;
|
||||
case 0x20: op_lblx(); break;
|
||||
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
|
||||
|
||||
default: // opcodes with 2 bit params
|
||||
switch (m_op & 0xfc)
|
||||
{
|
||||
case 0x60: op_tmi(); break; // aka 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
|
||||
|
||||
default: // everything else
|
||||
switch (m_op)
|
||||
{
|
||||
case 0x40: op_lda(); break;
|
||||
case 0x41: op_exc(); break;
|
||||
case 0x42: op_exci(); break;
|
||||
case 0x43: op_excd(); break;
|
||||
case 0x44: op_coma(); break;
|
||||
case 0x45: op_tam(); break;
|
||||
case 0x46: op_atr(); break;
|
||||
case 0x47: op_mtr(); break;
|
||||
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 0x50: op_inbm(); break;
|
||||
case 0x51: op_debm(); break;
|
||||
case 0x52: op_incb(); break; // aka inbl
|
||||
case 0x53: op_decb(); break; // aka debl
|
||||
case 0x54: op_tc(); break; // check this?
|
||||
case 0x55: op_rta(); break;
|
||||
case 0x56: op_blta(); break;
|
||||
case 0x57: op_exbla(); break; // aka xbla
|
||||
// 58, 59, 5a, 5b illegal
|
||||
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
|
||||
|
||||
/*// extended opcodes
|
||||
case 0x5e:
|
||||
m_op = m_op << 8 | m_param;
|
||||
switch (m_param)
|
||||
{
|
||||
case 0x00: op_cend(); break;
|
||||
case 0x04: op_dta(); break;
|
||||
|
||||
default: op_illegal(); break;
|
||||
}
|
||||
break; // 0x5e*/
|
||||
|
||||
default: op_illegal(); break;
|
||||
}
|
||||
break; // 0xff
|
||||
|
||||
}
|
||||
break; // 0xfc
|
||||
|
||||
} // big switch
|
||||
}
|
146
src/devices/cpu/sm510/sm590op.cpp
Normal file
146
src/devices/cpu/sm510/sm590op.cpp
Normal file
@ -0,0 +1,146 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:hap, Jonathan Gevaryahu
|
||||
|
||||
// SM590 opcode handlers
|
||||
|
||||
#include "emu.h"
|
||||
#include "sm590.h"
|
||||
|
||||
|
||||
// internal helpers
|
||||
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;
|
||||
}
|
||||
|
||||
// instruction set
|
||||
|
||||
void sm590_device::op_lblx()
|
||||
{
|
||||
// LBL x: load BL with 4-bit immediate value
|
||||
m_bl = (m_op & 0xf);
|
||||
}
|
||||
|
||||
void sm590_device::op_tax()
|
||||
{
|
||||
// TAX: skip next if ACC equals 4-bit immediate value
|
||||
m_skip = (m_acc == (m_op & 0xf));
|
||||
}
|
||||
|
||||
void sm590_device::op_lda()
|
||||
{
|
||||
// LDA: load ACC with RAM
|
||||
m_acc = ram_r();
|
||||
}
|
||||
|
||||
void sm590_device::op_exc()
|
||||
{
|
||||
// EXC: exchange ACC with RAM
|
||||
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 = 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
|
||||
u8 a = m_acc;
|
||||
m_acc = m_x;
|
||||
m_x = a;
|
||||
}
|
||||
|
||||
void sm590_device::op_tba()
|
||||
{
|
||||
// TBA x: skip next if ACC bit is set
|
||||
m_skip = ((m_acc & bitmask(m_op)) != 0);
|
||||
}
|
||||
|
||||
void sm590_device::op_ads()
|
||||
{
|
||||
// ADS: add RAM to ACC, skip next on carry
|
||||
m_acc += ram_r();
|
||||
m_skip = (m_c == 1);
|
||||
m_acc &= 0xf;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void sm590_device::op_tl()
|
||||
{
|
||||
// TL xyz: long jump (same as sm510 TL except m_op and m_param masks)
|
||||
do_branch((m_op & 2)>>1, (((m_op & 1)<<1)|((m_param&0x80)?1:0)), m_param & 0x7f);
|
||||
}
|
||||
|
||||
void sm590_device::op_tml() // aka TLS
|
||||
{
|
||||
// TLS xyz: long call (same as sm510 TML except m_param mask)
|
||||
push_stack();
|
||||
do_branch((m_op & 2)>>1, (((m_op & 1)<<1)|((m_param&0x80)?1:0)), m_param & 0x7f);
|
||||
}
|
||||
|
||||
void sm590_device::op_t()
|
||||
{
|
||||
// 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);
|
||||
}
|
Loading…
Reference in New Issue
Block a user