summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--src/emu/cpu/melps4/m58846.c128
-rw-r--r--src/emu/cpu/melps4/m58846.h7
-rw-r--r--src/emu/cpu/melps4/melps4.c95
-rw-r--r--src/emu/cpu/melps4/melps4.h13
-rw-r--r--src/emu/cpu/melps4/melps4op.inc6
5 files changed, 216 insertions, 33 deletions
diff --git a/src/emu/cpu/melps4/m58846.c b/src/emu/cpu/melps4/m58846.c
index c2f68c6ecdf..dde2576906b 100644
--- a/src/emu/cpu/melps4/m58846.c
+++ b/src/emu/cpu/melps4/m58846.c
@@ -18,19 +18,19 @@ const device_type M58846 = &device_creator<m58846_device>;
// internal memory maps
-static ADDRESS_MAP_START(program_1k, AS_PROGRAM, 16, melps4_cpu_device)
- AM_RANGE(0x0000, 0x03ff) AM_ROM
+static ADDRESS_MAP_START(program_2kx9, AS_PROGRAM, 16, m58846_device)
+ AM_RANGE(0x0000, 0x07ff) AM_ROM
ADDRESS_MAP_END
-static ADDRESS_MAP_START(data_64x4, AS_DATA, 8, melps4_cpu_device)
- AM_RANGE(0x00, 0x3f) AM_RAM
+static ADDRESS_MAP_START(data_128x4, AS_DATA, 8, m58846_device)
+ AM_RANGE(0x00, 0x7f) AM_RAM
ADDRESS_MAP_END
// device definitions
m58846_device::m58846_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
- : melps4_cpu_device(mconfig, M58846, "M58846", tag, owner, clock, 10, ADDRESS_MAP_NAME(program_1k), 6, ADDRESS_MAP_NAME(data_64x4), "m58846", __FILE__)
+ : melps4_cpu_device(mconfig, M58846, "M58846", tag, owner, clock, 11, ADDRESS_MAP_NAME(program_2kx9), 7, ADDRESS_MAP_NAME(data_128x4), "m58846", __FILE__)
{ }
@@ -42,3 +42,121 @@ offs_t m58846_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *o
}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void m58846_device::device_start()
+{
+ melps4_cpu_device::device_start();
+}
+
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void m58846_device::device_reset()
+{
+ melps4_cpu_device::device_reset();
+}
+
+
+
+//-------------------------------------------------
+// execute
+//-------------------------------------------------
+
+void m58846_device::execute_one()
+{
+ // handle one opcode
+ switch (m_op & 0xf0)
+ {
+ case 0x30: op_sey(); break;
+ case 0x70: op_sp(); break;
+ case 0xa0: op_a(); break;
+ case 0xb0: op_la(); break;
+
+ case 0xc0: case 0xd0: case 0xe0: case 0xf0: op_lxy(); break;
+
+ default:
+ switch (m_op & 0xfc)
+ {
+ case 0x20: op_szb(); break;
+ case 0x4c: op_sb(); break;
+ case 0x58: op_szk(); break;
+ case 0x5c: op_rb(); break;
+ case 0x60: op_xam(); break;
+ case 0x64: op_tam(); break;
+ case 0x68: op_xamd(); break;
+ case 0x6c: op_xami(); break;
+
+ default:
+ switch (m_op)
+ {
+ case 0x06: case 0x07: op_su(); break;
+ case 0x40: case 0x41: op_lcps(); break;
+ case 0x4a: case 0x4b: op_lz(); break;
+ case 0x54: case 0x55: op_ias(); break;
+
+ case 0x00: op_nop(); break;
+ case 0x01: op_ba(); break;
+ case 0x02: op_iny(); break;
+ case 0x03: op_dey(); break;
+ case 0x04: op_di(); break;
+ case 0x05: op_ei(); break;
+ case 0x0a: op_am(); break;
+ case 0x0b: op_ose(); break;
+ case 0x0c: op_tya(); break;
+ case 0x0f: op_cma(); break;
+
+ case 0x10: op_cls(); break;
+ case 0x11: op_clds(); break;
+ case 0x13: op_cld(); break;
+ case 0x14: op_rd(); break;
+ case 0x15: op_sd(); break;
+ case 0x16: op_tepa(); break;
+ case 0x17: op_ospa(); break;
+ case 0x1a: op_teab(); break;
+ case 0x1b: op_osab(); break;
+ case 0x1c: op_tba(); break;
+ case 0x1d: op_tay(); break;
+ case 0x1e: op_tab(); break;
+
+ case 0x26: op_seam(); break;
+ case 0x2b: op_szd(); break;
+ case 0x2f: op_szc(); break;
+
+ case 0x43: op_amc(); break;
+ case 0x44: op_rt(); break;
+ case 0x45: op_rts(); break;
+ case 0x46: op_rti(); break;
+ case 0x48: op_rc(); break;
+ case 0x49: op_sc(); break;
+
+ case 0x53: op_amcs(); break;
+ case 0x57: op_iak(); break;
+
+ case 0x81: op_ofa(); break;
+ case 0x82: op_snz1(); break;
+ case 0x83: op_snz2(); break;
+ case 0x84: op_oga(); break;
+ case 0x85: op_t2ab(); break;
+ case 0x86: op_tva(); break;
+ case 0x8a: op_tab2(); break;
+ case 0x8c: op_iaf(); break;
+
+ default:
+ melps4_cpu_device::execute_one();
+ break;
+
+ }
+ break; // 0xff
+
+ }
+ break; // 0xfc
+
+ } // big switch
+}
diff --git a/src/emu/cpu/melps4/m58846.h b/src/emu/cpu/melps4/m58846.h
index 9209bb93cf0..cf37aeb5e8c 100644
--- a/src/emu/cpu/melps4/m58846.h
+++ b/src/emu/cpu/melps4/m58846.h
@@ -18,6 +18,13 @@ public:
m58846_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
protected:
+ // device-level overrides
+ virtual void device_start();
+ virtual void device_reset();
+
+ // device_execute_interface overrides
+ virtual void execute_one();
+
// device_disasm_interface overrides
virtual offs_t disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options);
};
diff --git a/src/emu/cpu/melps4/melps4.c b/src/emu/cpu/melps4/melps4.c
index 5549b4a564f..0bb1bf544cc 100644
--- a/src/emu/cpu/melps4/melps4.c
+++ b/src/emu/cpu/melps4/melps4.c
@@ -3,6 +3,22 @@
/*
Mitsubishi MELPS 4 MCU family cores
+
+ 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
+ *M58842: 64-pin DIL, external ROM(11-bit PC), rest is same as M58840
+ *M58843: 28-pin DIL, 1Kx9 ROM, 64x4 RAM, A/D converter
+ *M58844: almost same as M58843
+ *M58845: 42-pin DIL, 2Kx9 ROM, 128x4 RAM, A/D converter, 2 timers
+ M58846: 42-pin DIL, 2Kx9 ROM, 128x4 RAM, 2 timers(not same as M58845), extra I/O ports
+ *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
@@ -15,24 +31,17 @@
#include "melps4op.inc"
-
-// disasm
-void melps4_cpu_device::state_string_export(const device_state_entry &entry, std::string &str)
-{
- switch (entry.index())
- {
- case STATE_GENFLAGS:
- 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
+};
+
void melps4_cpu_device::device_start()
{
m_program = &space(AS_PROGRAM);
@@ -42,13 +51,49 @@ void melps4_cpu_device::device_start()
// zerofill
m_pc = 0;
+ m_prev_pc = 0;
+ memset(m_stack, 0, sizeof(m_stack));
+ m_op = 0;
+ m_cps = 0;
+ m_skip = false;
+
+ m_a = 0;
+ m_b = 0;
+ m_y = m_y2 = 0;
+ m_x = m_x2 = 0;
+ m_z = m_z2 = 0;
+ m_cy = m_cy2 = 0;
+ m_e = 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_cps));
+ save_item(NAME(m_skip));
+
+ save_item(NAME(m_a));
+ save_item(NAME(m_b));
+ 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));
// 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(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_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");
m_icountptr = &m_icount;
}
@@ -69,16 +114,28 @@ void melps4_cpu_device::device_reset()
// execute
//-------------------------------------------------
+void melps4_cpu_device::execute_one()
+{
+ // B is at $18x and BM is at $10x for all MCU types
+ if (m_op >= 0x180)
+ op_b();
+ else if (m_op >= 0x100)
+ op_bm();
+ else
+ op_illegal();
+}
+
void melps4_cpu_device::execute_run()
{
while (m_icount > 0)
{
- m_icount--;
-
// fetch next opcode
debugger_instruction_hook(this, m_pc);
+ m_icount--;
+ m_op = m_program->read_word(m_pc << 1) & 0x1ff;
+ m_pc = (m_pc & ~0x7f) | ((m_pc + 1) & 0x7f); // stays in the same page
- // handle opcode
-
+ // handle opcode if it's not skipped
+ execute_one();
}
}
diff --git a/src/emu/cpu/melps4/melps4.h b/src/emu/cpu/melps4/melps4.h
index 27bb8a75e20..ed206b293c1 100644
--- a/src/emu/cpu/melps4/melps4.h
+++ b/src/emu/cpu/melps4/melps4.h
@@ -34,8 +34,9 @@ protected:
virtual UINT64 execute_cycles_to_clocks(UINT64 cycles) const { return (cycles * 6); } // "
virtual UINT32 execute_min_cycles() const { return 1; }
virtual UINT32 execute_max_cycles() const { return 1; }
- virtual UINT32 execute_input_lines() const { return 1; }
+ virtual UINT32 execute_input_lines() const { return 3; } // up to 3 (some internal)
virtual void execute_run();
+ virtual void execute_one();
// device_memory_interface overrides
virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const { return(spacenum == AS_PROGRAM) ? &m_program_config : ((spacenum == AS_DATA) ? &m_data_config : NULL); }
@@ -43,7 +44,6 @@ 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;
@@ -57,10 +57,14 @@ protected:
int m_icount;
- UINT16 m_pc;
+ UINT16 m_pc; // program counter (11 or 10-bit)
UINT16 m_prev_pc;
+ UINT16 m_stack[3]; // callstack, 3 levels
UINT16 m_op;
+ UINT8 m_cps; // DP,CY or DP',CY' selected
+ bool m_skip; // skip next opcode
+
// registers (unless specified, each is 4-bit)
UINT8 m_a; // accumulator
UINT8 m_b; // generic
@@ -70,9 +74,6 @@ protected:
UINT8 m_cy, m_cy2; // carry flag(s)
UINT8 m_e; // 8-bit register, hold data for S output
- UINT8 m_cps; // DP,CY or DP',CY' selected
- bool m_skip;
-
// misc internal helpers
UINT8 ram_r();
void ram_w(UINT8 data);
diff --git a/src/emu/cpu/melps4/melps4op.inc b/src/emu/cpu/melps4/melps4op.inc
index 5542e0fbba9..9257ffd76e5 100644
--- a/src/emu/cpu/melps4/melps4op.inc
+++ b/src/emu/cpu/melps4/melps4op.inc
@@ -7,13 +7,13 @@
inline UINT8 melps4_cpu_device::ram_r()
{
- UINT8 address = (m_z << 5 | m_x << 4 | m_y) & m_datamask;
+ UINT8 address = (m_z << 6 | m_x << 4 | m_y) & m_datamask;
return m_data->read_byte(address) & 0xf;
}
inline void melps4_cpu_device::ram_w(UINT8 data)
{
- UINT8 address = (m_z << 5 | m_x << 4 | m_y) & m_datamask;
+ UINT8 address = (m_z << 6 | m_x << 4 | m_y) & m_datamask;
m_data->write_byte(address, data & 0xf);
}
@@ -170,7 +170,7 @@ void melps4_cpu_device::op_xami()
{
// XAMI j: XAM J, INY, skip next on Y=mask(default 0)
op_xam();
- op_iny();
+ op_dey();
op_illegal();
}