checkpoint

This commit is contained in:
hap 2015-05-20 22:44:43 +02:00
parent 7b3fe379b4
commit c2e31774dc
4 changed files with 147 additions and 50 deletions

View File

@ -50,6 +50,10 @@ offs_t m58846_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *o
void m58846_device::device_start()
{
melps4_cpu_device::device_start();
// set fixed state
m_bm_page = 2;
m_int_page = 1;
}

View File

@ -4,7 +4,8 @@
Mitsubishi MELPS 4 MCU family cores
Known types and their features: (* means not emulated yet)
Known types and their features:
(* means not emulated yet)
*M58840: 42-pin DIL, 2Kx9 ROM, 128x4 RAM, A/D converter
*M58841: almost same as M58840
@ -16,10 +17,12 @@
*M58847: 40-pin DIL, 2Kx9 ROM, 128x4 RAM, extra I/O ports(not same as M58846)
MELPS 41/42 subfamily:
*M58494: 72-pin QFP CMOS, 4Kx10 ROM, 32x4 internal + 4Kx4 external RAM, 2 timers
*M58496: 72-pin QFP CMOS, 2Kx10 ROM, 128x4 internal + 256x4 external RAM, 1 timer, low-power
*M58497: almost same as M58496
References:
- 1982 Mitsubishi LSI Data Book
@ -31,15 +34,35 @@
#include "melps4op.inc"
// disasm
void melps4_cpu_device::state_string_export(const device_state_entry &entry, std::string &str)
{
switch (entry.index())
{
// obviously not from a single flags register, letters are made up
case STATE_GENFLAGS:
strprintf(str, "%c%c%c%c",
m_intp ? 'P':'p',
m_inte ? 'I':'i',
m_cps ? 'D':'d',
m_cy ? 'C':'c'
);
break;
default: break;
}
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
enum
{
MELPS4_PC=1, MELPS4_A, MELPS4_B,
MELPS4_Y, MELPS4_X, MELPS4_Z, MELPS4_CY, MELPS4_CPS,
MELPS4_E
MELPS4_PC=1, MELPS4_A, MELPS4_B, MELPS4_E,
MELPS4_Y, MELPS4_X, MELPS4_Z,
MELPS4_H, MELPS4_L, MELPS4_C, MELPS4_V, MELPS4_W
};
void melps4_cpu_device::device_start()
@ -48,52 +71,76 @@ void melps4_cpu_device::device_start()
m_data = &space(AS_DATA);
m_prgmask = (1 << m_prgwidth) - 1;
m_datamask = (1 << m_datawidth) - 1;
// zerofill
m_pc = 0;
m_prev_pc = 0;
memset(m_stack, 0, sizeof(m_stack));
m_op = 0;
m_prev_op = 0;
m_cps = 0;
m_skip = false;
m_inte = 0;
m_intp = 1;
m_a = 0;
m_b = 0;
m_e = 0;
m_y = m_y2 = 0;
m_x = m_x2 = 0;
m_z = m_z2 = 0;
m_cy = m_cy2 = 0;
m_e = 0;
m_h = 0;
m_l = 0;
m_c = 7;
m_v = 0;
m_w = 0;
// register for savestates
save_item(NAME(m_pc));
save_item(NAME(m_prev_pc));
save_item(NAME(m_stack));
save_item(NAME(m_op));
save_item(NAME(m_prev_op));
save_item(NAME(m_cps));
save_item(NAME(m_skip));
save_item(NAME(m_inte));
save_item(NAME(m_intp));
save_item(NAME(m_a));
save_item(NAME(m_b));
save_item(NAME(m_e));
save_item(NAME(m_y)); save_item(NAME(m_y2));
save_item(NAME(m_x)); save_item(NAME(m_x2));
save_item(NAME(m_z)); save_item(NAME(m_z2));
save_item(NAME(m_cy)); save_item(NAME(m_cy2));
save_item(NAME(m_e));
save_item(NAME(m_h));
save_item(NAME(m_l));
save_item(NAME(m_c));
save_item(NAME(m_v));
save_item(NAME(m_w));
// register state for debugger
state_add(STATE_GENPC, "curpc", m_pc).formatstr("%04X").noshow();
state_add(STATE_GENFLAGS, "GENFLAGS", m_cy).formatstr("%1s").noshow();
state_add(STATE_GENFLAGS, "GENFLAGS", m_cy).formatstr("%4s").noshow();
state_add(MELPS4_PC, "PC", m_pc).formatstr("%04X");
state_add(MELPS4_A, "A", m_a).formatstr("%2d");
state_add(MELPS4_B, "B", m_b).formatstr("%2d");
state_add(MELPS4_CPS, "CPS", m_cps).formatstr("%1d");
state_add(MELPS4_Y, "Y", m_y).formatstr("%2d");
state_add(MELPS4_A, "A", m_a).formatstr("%2d"); // show in decimal
state_add(MELPS4_B, "B", m_b).formatstr("%2d"); // "
state_add(MELPS4_E, "E", m_e).formatstr("%02X");
state_add(MELPS4_Y, "Y", m_y).formatstr("%1X");
state_add(MELPS4_X, "X", m_x).formatstr("%1d");
state_add(MELPS4_Z, "Z", m_z).formatstr("%1d");
state_add(MELPS4_CY, "CY", m_cy).formatstr("%1d");
state_add(MELPS4_E, "E", m_e).formatstr("%02X");
state_add(MELPS4_H, "H", m_h).formatstr("%1X");
state_add(MELPS4_L, "L", m_l).formatstr("%1X");
state_add(MELPS4_C, "C", m_c).formatstr("%1X");
state_add(MELPS4_V, "V", m_v).formatstr("%1X");
state_add(MELPS4_W, "W", m_w).formatstr("%1X");
m_icountptr = &m_icount;
}
@ -106,6 +153,14 @@ void melps4_cpu_device::device_start()
void melps4_cpu_device::device_reset()
{
m_op = m_prev_op = 0;
m_pc = m_prev_pc = 0;
m_inte = 0;
m_intp = 1;
op_lcps(); // CPS=0
m_v = 0;
m_w = 0;
}
@ -129,6 +184,10 @@ void melps4_cpu_device::execute_run()
{
while (m_icount > 0)
{
// remember previous state
m_prev_op = m_op;
m_prev_pc = m_pc;
// fetch next opcode
debugger_instruction_hook(this, m_pc);
m_icount--;

View File

@ -22,6 +22,10 @@ public:
, m_data_config("data", ENDIANNESS_LITTLE, 8, datawidth, 0, data)
, m_prgwidth(prgwidth)
, m_datawidth(datawidth)
, m_stack_levels(3)
, m_bm_page(14)
, m_int_page(12)
, m_xami_mask(0)
{ }
protected:
@ -44,35 +48,52 @@ protected:
// device_disasm_interface overrides
virtual UINT32 disasm_min_opcode_bytes() const { return 2; }
virtual UINT32 disasm_max_opcode_bytes() const { return 2; }
virtual void state_string_export(const device_state_entry &entry, std::string &str);
address_space_config m_program_config;
address_space_config m_data_config;
address_space *m_program;
address_space *m_data;
int m_prgwidth;
int m_datawidth;
int m_prgmask;
int m_datamask;
int m_icount;
// fixed settings or mask options
int m_prgwidth; // number of bits and bitmask for ROM/RAM size
int m_datawidth; // "
int m_prgmask; // "
int m_datamask; // "
UINT8 m_stack_levels; // 3 levels on MELPS 4, 12 levels on MELPS 41/42
UINT8 m_bm_page; // short BM default page: 14 on '40 to '44, 2 on '45,'46, 0 on '47
UINT8 m_int_page; // interrupt routine page: 12 on '40 to '44, 1 on '45,'46, 2 on '47
UINT8 m_xami_mask; // mask option for XAMI opcode on '40,'41,'45 (0 for others)
// internal state, misc regs
UINT16 m_pc; // program counter (11 or 10-bit)
UINT16 m_prev_pc;
UINT16 m_stack[3]; // callstack, 3 levels
UINT16 m_stack[12]; // callstack
UINT16 m_op;
UINT16 m_prev_op;
UINT8 m_cps; // DP,CY or DP',CY' selected
bool m_skip; // skip next opcode
UINT8 m_inte; // interrupt enable flag
UINT8 m_intp; // external interrupt polarity ('40 to '44)
// registers (unless specified, each is 4-bit)
// work registers (unless specified, each is 4-bit)
UINT8 m_a; // accumulator
UINT8 m_b; // generic
UINT8 m_e; // 8-bit register, hold data for S output
UINT8 m_y, m_y2; // RAM index Y, Y' (Z.XX.YYYY is DP aka Data Pointer)
UINT8 m_x, m_x2; // RAM index X, X', 2-bit
UINT8 m_z, m_z2; // RAM index Z, Z', 1-bit, optional
UINT8 m_cy, m_cy2; // carry flag(s)
UINT8 m_e; // 8-bit register, hold data for S output
UINT8 m_h; // A/D converter H or generic
UINT8 m_l; // A/D converter L or generic
UINT8 m_c; // A/D converter counter
UINT8 m_v; // timer control V
UINT8 m_w; // timer control W
// misc internal helpers
UINT8 ram_r();

View File

@ -82,10 +82,11 @@ void melps4_cpu_device::op_tax()
void melps4_cpu_device::op_lxy()
{
// LXY x,y: load immediate into X,Y, skip any next LXY
m_x = m_op >> 4 & 3;
m_y = m_op & 0xf;
op_illegal();
if ((m_op & ~0x3f) != (m_prev_op & ~0x3f))
{
m_x = m_op >> 4 & 3;
m_y = m_op & 0xf;
}
}
void melps4_cpu_device::op_lz()
@ -170,9 +171,8 @@ void melps4_cpu_device::op_xami()
{
// XAMI j: XAM J, INY, skip next on Y=mask(default 0)
op_xam();
op_dey();
op_illegal();
op_iny();
m_skip = (m_y == m_xami_mask);
}
@ -181,9 +181,8 @@ void melps4_cpu_device::op_xami()
void melps4_cpu_device::op_la()
{
// LA n: load immediate into A, skip any next LA
m_a = m_op & 0xf;
op_illegal();
if ((m_op & ~0xf) != (m_prev_op & ~0xf))
m_a = m_op & 0xf;
}
void melps4_cpu_device::op_am()
@ -259,7 +258,7 @@ void melps4_cpu_device::op_rb()
void melps4_cpu_device::op_szb()
{
// SZB j: skip next if RAM bit is reset
// SZB j: skip next if RAM bit is 0
UINT8 mask = 1 << (m_op & 3);
m_skip = !(ram_r() & mask);
}
@ -285,55 +284,68 @@ void melps4_cpu_device::op_sey()
void melps4_cpu_device::op_tla()
{
// TLA: transfer A to L
op_illegal();
m_l = m_a;
}
void melps4_cpu_device::op_tha()
{
// THA: transfer A to H
op_illegal();
m_h = m_a;
}
void melps4_cpu_device::op_taj()
{
// TAJ: transfer J to A
// TAJ: transfer J(hi/lo) to A designated by Y
op_illegal();
}
void melps4_cpu_device::op_xal()
{
// XAL: exchange A with L
op_illegal();
UINT8 a = m_a;
m_a = m_l;
m_l = a;
}
void melps4_cpu_device::op_xah()
{
// XAH: exchange A with H
op_illegal();
UINT8 a = m_a;
m_a = m_h;
m_h = a;
}
void melps4_cpu_device::op_lc7()
{
// LC7: load 7 into C
op_illegal();
m_c = 7;
}
void melps4_cpu_device::op_dec()
{
// DEC: decrement C, skip next on overflow
op_illegal();
m_c = (m_c - 1) & 7;
m_skip = (m_c == 7);
}
void melps4_cpu_device::op_shl()
{
// SHL: set bit in L or H designated by C
op_illegal();
UINT8 mask = 1 << (m_c & 3);
if (m_c & 4)
m_h |= mask;
else
m_l |= mask;
}
void melps4_cpu_device::op_rhl()
{
// RHL: reset bit in L or H designated by C
op_illegal();
UINT8 mask = 1 << (m_c & 3);
if (m_c & 4)
m_h &= ~mask;
else
m_l &= ~mask;
}
void melps4_cpu_device::op_cpa()
@ -356,7 +368,7 @@ void melps4_cpu_device::op_cpae()
void melps4_cpu_device::op_szj()
{
// SZJ: ..
// SZJ: skip next if J bit designated by Y is 0
op_illegal();
}
@ -462,7 +474,8 @@ void melps4_cpu_device::op_rt()
void melps4_cpu_device::op_rts()
{
// RTS: RT, skip next
op_illegal();
op_rt();
m_skip = true;
}
void melps4_cpu_device::op_rti()
@ -576,25 +589,25 @@ void melps4_cpu_device::op_su()
void melps4_cpu_device::op_ei()
{
// EI: enable interrupt flag
op_illegal();
m_inte = 1;
}
void melps4_cpu_device::op_di()
{
// DI: disable interrupt flag
op_illegal();
m_inte = 0;
}
void melps4_cpu_device::op_inth()
{
// INTH: set interrupt polarity high
op_illegal();
// INTH: set external interrupt polarity high (rising edge)
m_intp = 1;
}
void melps4_cpu_device::op_intl()
{
// INTL: set interrupt polarity low
op_illegal();
// INTL: set external interrupt polarity low (falling edge)
m_intp = 0;
}