mirror of
https://github.com/holub/mame
synced 2025-04-23 00:39:36 +03:00
checkpoint
This commit is contained in:
parent
7b3fe379b4
commit
c2e31774dc
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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--;
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user