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() void m58846_device::device_start()
{ {
melps4_cpu_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 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 *M58840: 42-pin DIL, 2Kx9 ROM, 128x4 RAM, A/D converter
*M58841: almost same as M58840 *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) *M58847: 40-pin DIL, 2Kx9 ROM, 128x4 RAM, extra I/O ports(not same as M58846)
MELPS 41/42 subfamily: MELPS 41/42 subfamily:
*M58494: 72-pin QFP CMOS, 4Kx10 ROM, 32x4 internal + 4Kx4 external RAM, 2 timers *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 *M58496: 72-pin QFP CMOS, 2Kx10 ROM, 128x4 internal + 256x4 external RAM, 1 timer, low-power
*M58497: almost same as M58496 *M58497: almost same as M58496
References: References:
- 1982 Mitsubishi LSI Data Book - 1982 Mitsubishi LSI Data Book
@ -31,15 +34,35 @@
#include "melps4op.inc" #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 // device_start - device-specific startup
//------------------------------------------------- //-------------------------------------------------
enum enum
{ {
MELPS4_PC=1, MELPS4_A, MELPS4_B, MELPS4_PC=1, MELPS4_A, MELPS4_B, MELPS4_E,
MELPS4_Y, MELPS4_X, MELPS4_Z, MELPS4_CY, MELPS4_CPS, MELPS4_Y, MELPS4_X, MELPS4_Z,
MELPS4_E MELPS4_H, MELPS4_L, MELPS4_C, MELPS4_V, MELPS4_W
}; };
void melps4_cpu_device::device_start() void melps4_cpu_device::device_start()
@ -54,46 +77,70 @@ void melps4_cpu_device::device_start()
m_prev_pc = 0; m_prev_pc = 0;
memset(m_stack, 0, sizeof(m_stack)); memset(m_stack, 0, sizeof(m_stack));
m_op = 0; m_op = 0;
m_prev_op = 0;
m_cps = 0; m_cps = 0;
m_skip = false; m_skip = false;
m_inte = 0;
m_intp = 1;
m_a = 0; m_a = 0;
m_b = 0; m_b = 0;
m_e = 0;
m_y = m_y2 = 0; m_y = m_y2 = 0;
m_x = m_x2 = 0; m_x = m_x2 = 0;
m_z = m_z2 = 0; m_z = m_z2 = 0;
m_cy = m_cy2 = 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 // register for savestates
save_item(NAME(m_pc)); save_item(NAME(m_pc));
save_item(NAME(m_prev_pc)); save_item(NAME(m_prev_pc));
save_item(NAME(m_stack)); save_item(NAME(m_stack));
save_item(NAME(m_op)); save_item(NAME(m_op));
save_item(NAME(m_prev_op));
save_item(NAME(m_cps)); save_item(NAME(m_cps));
save_item(NAME(m_skip)); save_item(NAME(m_skip));
save_item(NAME(m_inte));
save_item(NAME(m_intp));
save_item(NAME(m_a)); save_item(NAME(m_a));
save_item(NAME(m_b)); save_item(NAME(m_b));
save_item(NAME(m_e));
save_item(NAME(m_y)); save_item(NAME(m_y2)); save_item(NAME(m_y)); save_item(NAME(m_y2));
save_item(NAME(m_x)); save_item(NAME(m_x2)); save_item(NAME(m_x)); save_item(NAME(m_x2));
save_item(NAME(m_z)); save_item(NAME(m_z2)); save_item(NAME(m_z)); save_item(NAME(m_z2));
save_item(NAME(m_cy)); save_item(NAME(m_cy2)); 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 // register state for debugger
state_add(STATE_GENPC, "curpc", m_pc).formatstr("%04X").noshow(); 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_PC, "PC", m_pc).formatstr("%04X");
state_add(MELPS4_A, "A", m_a).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_B, "B", m_b).formatstr("%2d"); // "
state_add(MELPS4_CPS, "CPS", m_cps).formatstr("%1d"); state_add(MELPS4_E, "E", m_e).formatstr("%02X");
state_add(MELPS4_Y, "Y", m_y).formatstr("%2d"); state_add(MELPS4_Y, "Y", m_y).formatstr("%1X");
state_add(MELPS4_X, "X", m_x).formatstr("%1d"); state_add(MELPS4_X, "X", m_x).formatstr("%1d");
state_add(MELPS4_Z, "Z", m_z).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; m_icountptr = &m_icount;
} }
@ -106,6 +153,14 @@ void melps4_cpu_device::device_start()
void melps4_cpu_device::device_reset() 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) while (m_icount > 0)
{ {
// remember previous state
m_prev_op = m_op;
m_prev_pc = m_pc;
// fetch next opcode // fetch next opcode
debugger_instruction_hook(this, m_pc); debugger_instruction_hook(this, m_pc);
m_icount--; m_icount--;

View File

@ -22,6 +22,10 @@ public:
, m_data_config("data", ENDIANNESS_LITTLE, 8, datawidth, 0, data) , m_data_config("data", ENDIANNESS_LITTLE, 8, datawidth, 0, data)
, m_prgwidth(prgwidth) , m_prgwidth(prgwidth)
, m_datawidth(datawidth) , m_datawidth(datawidth)
, m_stack_levels(3)
, m_bm_page(14)
, m_int_page(12)
, m_xami_mask(0)
{ } { }
protected: protected:
@ -44,35 +48,52 @@ protected:
// device_disasm_interface overrides // device_disasm_interface overrides
virtual UINT32 disasm_min_opcode_bytes() const { return 2; } virtual UINT32 disasm_min_opcode_bytes() const { return 2; }
virtual UINT32 disasm_max_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_program_config;
address_space_config m_data_config; address_space_config m_data_config;
address_space *m_program; address_space *m_program;
address_space *m_data; address_space *m_data;
int m_prgwidth;
int m_datawidth;
int m_prgmask;
int m_datamask;
int m_icount; 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_pc; // program counter (11 or 10-bit)
UINT16 m_prev_pc; UINT16 m_prev_pc;
UINT16 m_stack[3]; // callstack, 3 levels UINT16 m_stack[12]; // callstack
UINT16 m_op; UINT16 m_op;
UINT16 m_prev_op;
UINT8 m_cps; // DP,CY or DP',CY' selected UINT8 m_cps; // DP,CY or DP',CY' selected
bool m_skip; // skip next opcode 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_a; // accumulator
UINT8 m_b; // generic 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_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_x, m_x2; // RAM index X, X', 2-bit
UINT8 m_z, m_z2; // RAM index Z, Z', 1-bit, optional UINT8 m_z, m_z2; // RAM index Z, Z', 1-bit, optional
UINT8 m_cy, m_cy2; // carry flag(s) 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 // misc internal helpers
UINT8 ram_r(); UINT8 ram_r();

View File

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