diff options
-rw-r--r-- | src/emu/cpu/melps4/m58846.c | 128 | ||||
-rw-r--r-- | src/emu/cpu/melps4/m58846.h | 7 | ||||
-rw-r--r-- | src/emu/cpu/melps4/melps4.c | 95 | ||||
-rw-r--r-- | src/emu/cpu/melps4/melps4.h | 13 | ||||
-rw-r--r-- | src/emu/cpu/melps4/melps4op.inc | 6 |
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(); } |