added MELPS 4 skeleton

This commit is contained in:
hap 2015-05-19 23:34:20 +02:00
parent 5fb7f7e82a
commit 4587bb0369
10 changed files with 983 additions and 3 deletions

View File

@ -1051,6 +1051,24 @@ if (CPUS["PSX"]~=null or _OPTIONS["with-tools"]) then
table.insert(disasm_files , MAME_DIR .. "src/emu/cpu/psx/psxdasm.c")
end
--------------------------------------------------
-- Mitsubishi MELPS 4 series
---@src/emu/cpu/melps4/melps4.h,CPUS += MELPS4
--------------------------------------------------
if (CPUS["MELPS4"]~=null) then
files {
MAME_DIR .. "src/emu/cpu/melps4/melps4.c",
MAME_DIR .. "src/emu/cpu/melps4/melps4.h",
MAME_DIR .. "src/emu/cpu/melps4/m58846.c",
MAME_DIR .. "src/emu/cpu/melps4/m58846.h",
}
end
if (CPUS["MELPS4"]~=null or _OPTIONS["with-tools"]) then
table.insert(disasm_files , MAME_DIR .. "src/emu/cpu/melps4/melps4d.c")
end
--------------------------------------------------
-- Mitsubishi M37702 and M37710 (based on 65C816)
---@src/emu/cpu/m37710/m37710.h,CPUS += M37710

View File

@ -127,6 +127,7 @@ CPUS["ARCOMPACT"] = true
--CPUS["UCOM4"] = true
CPUS["HMCS40"] = true
--CPUS["E0C6200"] = true
--CPUS["MELPS4"] = true
--------------------------------------------------
-- specify available sound cores

View File

@ -127,6 +127,7 @@ CPUS["AMIS2000"] = true
CPUS["UCOM4"] = true
CPUS["HMCS40"] = true
CPUS["E0C6200"] = true
CPUS["MELPS4"] = true
--------------------------------------------------
-- specify available sound cores; some of these are

View File

@ -0,0 +1,44 @@
// license:BSD-3-Clause
// copyright-holders:hap
/*
Mitsubishi M58846 MCU
TODO:
- o hai
*/
#include "m58846.h"
#include "debugger.h"
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
ADDRESS_MAP_END
static ADDRESS_MAP_START(data_64x4, AS_DATA, 8, melps4_cpu_device)
AM_RANGE(0x00, 0x3f) 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__)
{ }
// disasm
offs_t m58846_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options)
{
extern CPU_DISASSEMBLE(m58846);
return CPU_DISASSEMBLE_NAME(m58846)(this, buffer, pc, oprom, opram, options);
}

View File

@ -0,0 +1,30 @@
// license:BSD-3-Clause
// copyright-holders:hap
/*
Mitsubishi M58846 MCU
*/
#ifndef _M58846_H_
#define _M58846_H_
#include "melps4.h"
class m58846_device : public melps4_cpu_device
{
public:
m58846_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
protected:
// device_disasm_interface overrides
virtual offs_t disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options);
};
extern const device_type M58846;
#endif /* _M58846_H_ */

View File

@ -0,0 +1,84 @@
// license:BSD-3-Clause
// copyright-holders:hap
/*
Mitsubishi MELPS 4 MCU family cores
References:
- 1982 Mitsubishi LSI Data Book
*/
#include "melps4.h"
#include "debugger.h"
#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
//-------------------------------------------------
void melps4_cpu_device::device_start()
{
m_program = &space(AS_PROGRAM);
m_data = &space(AS_DATA);
m_prgmask = (1 << m_prgwidth) - 1;
m_datamask = (1 << m_datawidth) - 1;
// zerofill
m_pc = 0;
// register for savestates
save_item(NAME(m_pc));
// register state for debugger
state_add(STATE_GENPC, "curpc", m_pc).formatstr("%04X").noshow();
m_icountptr = &m_icount;
}
//-------------------------------------------------
// device_reset - device-specific reset
//-------------------------------------------------
void melps4_cpu_device::device_reset()
{
}
//-------------------------------------------------
// execute
//-------------------------------------------------
void melps4_cpu_device::execute_run()
{
while (m_icount > 0)
{
m_icount--;
// fetch next opcode
debugger_instruction_hook(this, m_pc);
// handle opcode
}
}

165
src/emu/cpu/melps4/melps4.h Normal file
View File

@ -0,0 +1,165 @@
// license:BSD-3-Clause
// copyright-holders:hap
/*
Mitsubishi MELPS 4 MCU family cores
*/
#ifndef _MELPS4_H_
#define _MELPS4_H_
#include "emu.h"
class melps4_cpu_device : public cpu_device
{
public:
// construction/destruction
melps4_cpu_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, int prgwidth, address_map_constructor program, int datawidth, address_map_constructor data, const char *shortname, const char *source)
: cpu_device(mconfig, type, name, tag, owner, clock, shortname, source)
, m_program_config("program", ENDIANNESS_LITTLE, 16, prgwidth, -1, program)
, m_data_config("data", ENDIANNESS_LITTLE, 8, datawidth, 0, data)
, m_prgwidth(prgwidth)
, m_datawidth(datawidth)
{ }
protected:
// device-level overrides
virtual void device_start();
virtual void device_reset();
// device_execute_interface overrides
virtual UINT64 execute_clocks_to_cycles(UINT64 clocks) const { return (clocks + 6 - 1) / 6; } // 6 t-states per machine cycle
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 void execute_run();
// 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); }
// 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;
UINT16 m_pc;
UINT16 m_prev_pc;
UINT16 m_op;
// opcode handlers
void op_tab();
void op_tba();
void op_tay();
void op_tya();
void op_teab();
void op_tepa();
void op_txa();
void op_tax();
void op_lxy();
void op_lz();
void op_iny();
void op_dey();
void op_lcps();
void op_sadr();
void op_tam();
void op_xam();
void op_xamd();
void op_xami();
void op_la();
void op_am();
void op_amc();
void op_amcs();
void op_a();
void op_sc();
void op_rc();
void op_szc();
void op_cma();
void op_sb();
void op_rb();
void op_szb();
void op_seam();
void op_sey();
void op_tla();
void op_tha();
void op_taj();
void op_xal();
void op_xah();
void op_lc7();
void op_dec();
void op_shl();
void op_rhl();
void op_cpa();
void op_cpas();
void op_cpae();
void op_szj();
void op_t1ab();
void op_trab();
void op_t2ab();
void op_tab1();
void op_tabr();
void op_tab2();
void op_tva();
void op_twa();
void op_snz1();
void op_snz2();
void op_ba();
void op_sp();
void op_b();
void op_bm();
void op_rt();
void op_rts();
void op_rti();
void op_cld();
void op_cls();
void op_clds();
void op_sd();
void op_rd();
void op_szd();
void op_osab();
void op_ospa();
void op_ose();
void op_ias();
void op_ofa();
void op_iaf();
void op_oga();
void op_iak();
void op_szk();
void op_su();
void op_ei();
void op_di();
void op_inth();
void op_intl();
void op_nop();
void op_illegal();
};
#endif /* _MELPS4_H_ */

View File

@ -0,0 +1,92 @@
// license:BSD-3-Clause
// copyright-holders:hap
/*
Mitsubishi MELPS 4 MCU family disassembler
Not counting the extra opcodes for peripherals (eg. timers, A/D),
each MCU in the series has small differences in the opcode map.
*/
#include "emu.h"
#include "debugger.h"
#include "melps4.h"
// opcode mnemonics
enum e_mnemonics
{
em_TAB, em_TBA, em_TAY, em_TYA, em_TEAB, em_TEPA, em_TXA, em_TAX,
em_LXY, em_LZ, em_INY, em_DEY, em_LCPS, em_SADR,
em_TAM, em_XAM, em_XAMD, em_XAMI,
em_LA, em_AM, em_AMC, em_AMCS, em_A, em_SC, em_RC, em_SZC, em_CMA,
em_SB, em_RB, em_SZB, em_SEAM, em_SEY,
em_TLA, em_THA, em_TAJ, em_XAL, em_XAH, em_LC7, em_DEC, em_SHL, em_RHL, em_CPA, em_CPAS, em_CPAE, em_SZJ,
em_T1AB, em_TRAB, em_TAB1, em_TABR, em_TAB2, em_TVA, em_TWA, em_SNZ1, em_SNZ2,
em_BA, em_SP, em_B, em_BM, em_RT, em_RTS, em_RTI,
em_CLD, em_CLS, em_CLDS, em_SD, em_RD, em_SZD, em_OSAB, em_OSPA, em_OSE, em_IAS, em_OFA, em_IAF, em_OGA, em_IAK, em_SZK, em_SU, em_RU,
em_EI, em_DI, em_INTH, em_INTL,
em_NOP, em_ILL
};
static const char *const em_name[] =
{
"TAB", "TBA", "TAY", "TYA", "TEAB", "TEPA", "TXA", "TAX",
"LXY", "LZ", "INY", "DEY", "LCPS", "SADR",
"TAM", "XAM", "XAMD", "XAMI",
"LA", "AM", "AMC", "AMCS", "A", "SC", "RC", "SZC", "CMA",
"SB", "RB", "SZB", "SEAM", "SEY",
"TLA", "THA", "TAJ", "XAL", "XAH", "LC7", "DEC", "SHL", "RHL", "CPA", "CPAS", "CPAE", "SZJ",
"T1AB", "TRAB", "TAB1", "TABR", "TAB2", "TVA", "TWA", "SNZ1", "SNZ2",
"BA", "SP", "B", "BM", "RT", "RTS", "RTI",
"CLD", "CLS", "CLDS", "SD", "RD", "SZD", "OSAB", "OSPA", "OSE", "IAS", "OFA", "IAF", "OGA", "IAK", "SZK", "SU", "RU",
"EI", "DI", "INTH", "INTL",
"NOP", "?"
};
// number of bits per opcode parameter
static const UINT8 s_bits[] =
{
0, 0, 0, 0, 0, 0, 0, 0,
6, 1, 0, 0, 1, 2,
2, 2, 2, 2,
4, 0, 0, 0, 4, 0, 0, 0, 0,
2, 2, 2, 0, 4,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 4, 7, 7, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 2, 0, 0,
0, 0, 0, 0,
0, 0
};
#define _OVER DASMFLAG_STEP_OVER
#define _OUT DASMFLAG_STEP_OUT
static const UINT32 em_flags[] =
{
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, _OVER, _OUT, _OUT, _OUT,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0,
0, 0
};
CPU_DISASSEMBLE(m58846)
{
return 1;
}

View File

@ -0,0 +1,546 @@
// license:BSD-3-Clause
// copyright-holders:hap
// MELPS 4 opcode handlers
// Register-to-register transfers
void melps4_cpu_device::op_tab()
{
// TAB: transfer B to A
op_illegal();
}
void melps4_cpu_device::op_tba()
{
// TBA: transfer A to B
op_illegal();
}
void melps4_cpu_device::op_tay()
{
// TAY: transfer Y to A
op_illegal();
}
void melps4_cpu_device::op_tya()
{
// TYA: transfer A to Y
op_illegal();
}
void melps4_cpu_device::op_teab()
{
// TEAB: transfer A and B to E
op_illegal();
}
void melps4_cpu_device::op_tepa()
{
// TEPA: decode A by PLA and transfer to E
op_illegal();
}
void melps4_cpu_device::op_txa()
{
// TXA: transfer bits 0,1 of A to X, inverted bit 2 to Z, inverted bit 3 to carry
op_illegal();
}
void melps4_cpu_device::op_tax()
{
// TAX: transfer X to bits 0,1 of A, inverted Z to bit 2, inverted carry to bit 3
op_illegal();
}
// RAM addresses
void melps4_cpu_device::op_lxy()
{
// LXY x,y: load immediate into X,Y, skip any next LXY
op_illegal();
}
void melps4_cpu_device::op_lz()
{
// LZ z: load immediate into Z
op_illegal();
}
void melps4_cpu_device::op_iny()
{
// INY: increment Y, skip next on overflow
op_illegal();
}
void melps4_cpu_device::op_dey()
{
// DEY: decrement Y, skip next on overflow
op_illegal();
}
void melps4_cpu_device::op_lcps()
{
// LCPS i: choose active DP,CY or DP',CY'
op_illegal();
}
void melps4_cpu_device::op_sadr()
{
// SADR j: ..
op_illegal();
}
// RAM-accumulator transfers
void melps4_cpu_device::op_tam()
{
// TAM j: transfer RAM to A, xor X with j
op_illegal();
}
void melps4_cpu_device::op_xam()
{
// XAM j: exchange RAM with A, xor X with j
op_illegal();
}
void melps4_cpu_device::op_xamd()
{
// XAMD j: XAM J, DEY
op_illegal();
}
void melps4_cpu_device::op_xami()
{
// XAMI j: XAM J, increment Y, skip next on Y=mask(default 0)
op_illegal();
}
// Arithmetic Operations
void melps4_cpu_device::op_la()
{
// LA n: load immediate into A, skip any next LA
op_illegal();
}
void melps4_cpu_device::op_am()
{
// AM: add RAM to A
op_illegal();
}
void melps4_cpu_device::op_amc()
{
// AMC: add RAM+CY to A and CY
op_illegal();
}
void melps4_cpu_device::op_amcs()
{
// AMCS: AMC, skip next on carry
op_illegal();
}
void melps4_cpu_device::op_a()
{
// A n: add immediate to A, skip next on no carry (except when n=6)
op_illegal();
}
void melps4_cpu_device::op_sc()
{
// SC: set carry
op_illegal();
}
void melps4_cpu_device::op_rc()
{
// RC: reset carry
op_illegal();
}
void melps4_cpu_device::op_szc()
{
// SZC: skip next on no carry
op_illegal();
}
void melps4_cpu_device::op_cma()
{
// CMA: complement A
op_illegal();
}
// Bit operations
void melps4_cpu_device::op_sb()
{
// SB j: set RAM bit
op_illegal();
}
void melps4_cpu_device::op_rb()
{
// RB j: reset RAM bit
op_illegal();
}
void melps4_cpu_device::op_szb()
{
// SZB j: skip next if RAM bit is reset
op_illegal();
}
// Compares
void melps4_cpu_device::op_seam()
{
// SEAM: skip next if A equals RAM
op_illegal();
}
void melps4_cpu_device::op_sey()
{
// SEY y: skip next if Y equals immediate
op_illegal();
}
// A/D converter operations
void melps4_cpu_device::op_tla()
{
// TLA: transfer A to L
op_illegal();
}
void melps4_cpu_device::op_tha()
{
// THA: transfer A to H
op_illegal();
}
void melps4_cpu_device::op_taj()
{
// TAJ: transfer J to A
op_illegal();
}
void melps4_cpu_device::op_xal()
{
// XAL: exchange A with L
op_illegal();
}
void melps4_cpu_device::op_xah()
{
// XAH: exchange A with H
op_illegal();
}
void melps4_cpu_device::op_lc7()
{
// LC7: load 7 into C
op_illegal();
}
void melps4_cpu_device::op_dec()
{
// DEC: decrement C, skip next on overflow
op_illegal();
}
void melps4_cpu_device::op_shl()
{
// SHL: set bit in L or H designated by C
op_illegal();
}
void melps4_cpu_device::op_rhl()
{
// RHL: reset bit in L or H designated by C
op_illegal();
}
void melps4_cpu_device::op_cpa()
{
// CPA: ..
op_illegal();
}
void melps4_cpu_device::op_cpas()
{
// CPAS: ..
op_illegal();
}
void melps4_cpu_device::op_cpae()
{
// CPAE: ..
op_illegal();
}
void melps4_cpu_device::op_szj()
{
// SZJ: ..
op_illegal();
}
// Timer instruction
void melps4_cpu_device::op_t1ab()
{
// T1AB: transfer A and B to timer 1
op_illegal();
}
void melps4_cpu_device::op_trab()
{
// TRAB: transfer A and B to timer 2 reload
op_illegal();
}
void melps4_cpu_device::op_t2ab()
{
// T2AB: transfer A and B to timer 2 and timer 2 reload
op_illegal();
}
void melps4_cpu_device::op_tab1()
{
// TAB1: transfer timer 1 to A and B
op_illegal();
}
void melps4_cpu_device::op_tabr()
{
// TABR: transfer timer 2 reload to A and B
op_illegal();
}
void melps4_cpu_device::op_tab2()
{
// TAB2: transfer timer 2 to A and B
op_illegal();
}
void melps4_cpu_device::op_tva()
{
// TVA: transfer A to timer control V
op_illegal();
}
void melps4_cpu_device::op_twa()
{
// TWA: transfer A to timer control W
op_illegal();
}
void melps4_cpu_device::op_snz1()
{
// SNZ1: skip next on flag 1F
op_illegal();
}
void melps4_cpu_device::op_snz2()
{
// SNZ2: skip next on flag 2F
op_illegal();
}
// Jumps
void melps4_cpu_device::op_ba()
{
// BA: x
op_illegal();
}
void melps4_cpu_device::op_sp()
{
// SP: set page
op_illegal();
}
void melps4_cpu_device::op_b()
{
// B xy: branch in current page
op_illegal();
}
void melps4_cpu_device::op_bm()
{
// BM xy call subroutine on page 14
op_illegal();
}
// Program returns
void melps4_cpu_device::op_rt()
{
// RT: return from subroutine
op_illegal();
}
void melps4_cpu_device::op_rts()
{
// RTS: RT, skip next
op_illegal();
}
void melps4_cpu_device::op_rti()
{
// RTI: return from interrupt routine
op_illegal();
}
// Input/Output
void melps4_cpu_device::op_cld()
{
// CLD: clear port D
op_illegal();
}
void melps4_cpu_device::op_cls()
{
// CLS: clear port S
op_illegal();
}
void melps4_cpu_device::op_clds()
{
// CLDS: CLD, CLS
op_illegal();
}
void melps4_cpu_device::op_sd()
{
// SD: set port D bit designated by Y
op_illegal();
}
void melps4_cpu_device::op_rd()
{
// RD: reset port D bit designated by Y
op_illegal();
}
void melps4_cpu_device::op_szd()
{
// SZD: skip next if port D bit designated by Y is 0
op_illegal();
}
void melps4_cpu_device::op_osab()
{
// OSAB: output A and B to port S
op_illegal();
}
void melps4_cpu_device::op_ospa()
{
// OSPA: decode A by PLA and output to port S
op_illegal();
}
void melps4_cpu_device::op_ose()
{
// OSE: output E to port S
op_illegal();
}
void melps4_cpu_device::op_ias()
{
// IAS i: transfer port S(hi/lo) to A
op_illegal();
}
void melps4_cpu_device::op_ofa()
{
// OFA: output A to port F
op_illegal();
}
void melps4_cpu_device::op_iaf()
{
// IAF: input port F to A
op_illegal();
}
void melps4_cpu_device::op_oga()
{
// OGA: output A to port G
op_illegal();
}
void melps4_cpu_device::op_iak()
{
// IAK: input port K to A
op_illegal();
}
void melps4_cpu_device::op_szk()
{
// SZK j: skip next if port K bit is reset
op_illegal();
}
void melps4_cpu_device::op_su()
{
// SU/RU: set/reset port U
op_illegal();
}
// Interrupts
void melps4_cpu_device::op_ei()
{
// EI: enable interrupt flag
op_illegal();
}
void melps4_cpu_device::op_di()
{
// DI: disable interrupt flag
op_illegal();
}
void melps4_cpu_device::op_inth()
{
// INTH: set interrupt polarity high
op_illegal();
}
void melps4_cpu_device::op_intl()
{
// INTL: set interrupt polarity low
op_illegal();
}
// Misc
void melps4_cpu_device::op_nop()
{
// NOP: no operation
}
void melps4_cpu_device::op_illegal()
{
logerror("%s unknown opcode $%03X at $%04X\n", tag(), m_op, m_prev_pc);
}

View File

@ -8,8 +8,7 @@
***************************************************************************/
#include "emu.h"
//#include "cpu/melps4/melps4.h"
#include "cpu/ucom4/ucom4.h"
#include "cpu/melps4/m58846.h"
#include "sound/speaker.h"
#include "hh_melps4_test.lh" // common test-layout - use external artwork
@ -240,7 +239,7 @@ INPUT_PORTS_END
static MACHINE_CONFIG_START( cfrogger, cfrogger_state )
/* basic machine hardware */
MCFG_CPU_ADD("maincpu", NEC_D552, XTAL_600kHz)
MCFG_CPU_ADD("maincpu", M58846, XTAL_600kHz)
MCFG_TIMER_DRIVER_ADD_PERIODIC("display_decay", hh_melps4_state, display_decay_tick, attotime::from_msec(1))
MCFG_DEFAULT_LAYOUT(layout_hh_melps4_test)