added MM76 disassembler and preliminary PPS-4/1 MCU core [hap]

New machines marked as NOT_WORKING
----------------------------------
Electronic Master Mind (Invicta) [hap, Sean Riddle]
This commit is contained in:
hap 2021-02-26 18:24:44 +01:00
parent 1a0b950985
commit 2f02c96baf
38 changed files with 1100 additions and 156 deletions

View File

@ -452,7 +452,7 @@ if (CPUS["COSMAC"]~=null or _OPTIONS["with-tools"]) then
end
--------------------------------------------------
-- National Semiconductor COPS1 family
-- National Semiconductor COPS(MM57) family
--@src/devices/cpu/cops1/mm5799.h,CPUS["COPS1"] = true
--------------------------------------------------
@ -460,9 +460,9 @@ if (CPUS["COPS1"]~=null) then
files {
MAME_DIR .. "src/devices/cpu/cops1/cops1base.cpp",
MAME_DIR .. "src/devices/cpu/cops1/cops1base.h",
MAME_DIR .. "src/devices/cpu/cops1/cops1op.cpp",
MAME_DIR .. "src/devices/cpu/cops1/mm5799.cpp",
MAME_DIR .. "src/devices/cpu/cops1/mm5799.h",
MAME_DIR .. "src/devices/cpu/cops1/mm5799op.cpp",
}
end
@ -472,7 +472,7 @@ if (CPUS["COPS1"]~=null or _OPTIONS["with-tools"]) then
end
--------------------------------------------------
-- National Semiconductor COP400 family
-- National Semiconductor COPS(COP400) family
--@src/devices/cpu/cop400/cop400.h,CPUS["COP400"] = true
--------------------------------------------------
@ -2178,7 +2178,7 @@ end
--------------------------------------------------
-- Panasonic MN1880
--@src/devices/cpu/mn1800/mn1880.h,CPUS["MN1880"] = true
--@src/devices/cpu/mn1880/mn1880.h,CPUS["MN1880"] = true
--------------------------------------------------
if (CPUS["MN1880"]~=null) then
@ -2870,6 +2870,26 @@ if (CPUS["PPS4"]~=null or _OPTIONS["with-tools"]) then
table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/pps4/pps4dasm.h")
end
--------------------------------------------------
-- Rockwell PPS-4/1
--@src/devices/cpu/pps41/mm76.h,CPUS["PPS41"] = true
--------------------------------------------------
if (CPUS["PPS41"]~=null) then
files {
MAME_DIR .. "src/devices/cpu/pps41/pps41base.cpp",
MAME_DIR .. "src/devices/cpu/pps41/pps41base.h",
MAME_DIR .. "src/devices/cpu/pps41/mm76.cpp",
MAME_DIR .. "src/devices/cpu/pps41/mm76.h",
MAME_DIR .. "src/devices/cpu/pps41/mm76op.cpp",
}
end
if (CPUS["PPS41"]~=null or _OPTIONS["with-tools"]) then
table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/pps41/pps41d.cpp")
table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/pps41/pps41d.h")
end
--------------------------------------------------
-- Hitachi HD61700
--@src/devices/cpu/hd61700/hd61700.h,CPUS["HD61700"] = true

View File

@ -119,6 +119,7 @@ CPUS["COSMAC"] = true
CPUS["UNSP"] = true
CPUS["HCD62121"] = true
CPUS["PPS4"] = true
--CPUS["PPS41"] = true
CPUS["UPD7725"] = true
CPUS["HD61700"] = true
CPUS["LC8670"] = true

View File

@ -121,6 +121,7 @@ CPUS["COSMAC"] = true
CPUS["UNSP"] = true
CPUS["HCD62121"] = true
CPUS["PPS4"] = true
CPUS["PPS41"] = true
CPUS["UPD7725"] = true
CPUS["HD61700"] = true
CPUS["LC8670"] = true
@ -3456,6 +3457,7 @@ files {
MAME_DIR .. "src/mame/includes/aim65.h",
MAME_DIR .. "src/mame/machine/aim65.cpp",
MAME_DIR .. "src/mame/drivers/aim65_40.cpp",
MAME_DIR .. "src/mame/drivers/hh_pps41.cpp",
}
createMESSProjects(_target, _subtarget, "rtpc")

View File

@ -250,7 +250,9 @@ void amis2000_base_device::execute_run()
// remember previous opcode
m_prev_op = m_op;
debugger_instruction_hook(m_pc);
// fetch next opcode
if (!m_skip)
debugger_instruction_hook(m_pc);
m_op = m_program->read_byte(m_pc);
m_pc = (m_pc + 1) & 0x1fff;

View File

@ -205,7 +205,7 @@ void amis2000_base_device::op_inp()
void amis2000_base_device::op_out()
{
// OUT: pulse output ACC and RAM to D-pins
logerror("%s unknown opcode $%02X at $%04X\n", tag(), m_op, m_pc);
logerror("unknown opcode $%02X at $%04X\n", m_op, m_pc);
}
void amis2000_base_device::op_disb()
@ -359,7 +359,7 @@ void amis2000_base_device::op_nop()
void amis2000_base_device::op_halt()
{
// HALT: debugger breakpoint for devkit-use
logerror("%s unknown opcode $%02X at $%04X\n", tag(), m_op, m_pc);
logerror("unknown opcode $%02X at $%04X\n", m_op, m_pc);
}
@ -405,7 +405,7 @@ void amis2000_base_device::op_sam()
void amis2000_base_device::op_sos()
{
// SOS: skip next on SF(timer output), clear SF
logerror("%s unknown opcode $%02X at $%04X\n", tag(), m_op, m_pc);
logerror("unknown opcode $%02X at $%04X\n", m_op, m_pc);
}
void amis2000_base_device::op_tf1()

View File

@ -2,7 +2,7 @@
// copyright-holders:hap
/*
National Semiconductor COPS(MM57 MCU family) cores
National Semiconductor COPS(MM57 MCU family) cores
This is the first "COPS" series (Controller Oriented Processor Systems),
4-bit MCUs with internal RAM and most of them internal ROM too.
@ -36,7 +36,7 @@ TODO:
#include "debugger.h"
cops1_base_device::cops1_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, int prgwidth, address_map_constructor program, int datawidth, address_map_constructor data) :
cops1_base_device::cops1_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, int prgwidth, address_map_constructor program, int datawidth, address_map_constructor data) :
cpu_device(mconfig, type, tag, owner, clock),
m_program_config("program", ENDIANNESS_LITTLE, 8, prgwidth, 0, program),
m_data_config("data", ENDIANNESS_LITTLE, 8, datawidth, 0, data),
@ -192,8 +192,9 @@ void cops1_base_device::cycle()
void cops1_base_device::increment_pc()
{
// low part is LFSR
u8 feed = (m_pc & 0x3f) == 0 || ((m_pc >> 1 ^ m_pc) & 1) ? 0x20 : 0;
m_pc = (m_pc & ~0x3f) | (m_pc >> 1 & 0x1f) | feed;
int feed = ((m_pc & 0x3e) == 0) ? 1 : 0;
feed ^= (m_pc >> 1 ^ m_pc) & 1;
m_pc = (m_pc & ~0x3f) | (m_pc >> 1 & 0x1f) | (feed << 5);
}
void cops1_base_device::execute_run()
@ -209,7 +210,8 @@ void cops1_base_device::execute_run()
m_write_blk(0);
// fetch next opcode
debugger_instruction_hook(m_pc);
if (!m_skip)
debugger_instruction_hook(m_pc);
m_op = m_program->read_byte(m_pc);
increment_pc();
cycle();

View File

@ -64,7 +64,7 @@ public:
protected:
// construction/destruction
cops1_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, int prgwidth, address_map_constructor program, int datawidth, address_map_constructor data);
cops1_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, int prgwidth, address_map_constructor program, int datawidth, address_map_constructor data);
// device-level overrides
virtual void device_start() override;
@ -72,10 +72,10 @@ protected:
virtual void device_add_mconfig(machine_config &config) override;
// device_execute_interface overrides
virtual uint64_t execute_clocks_to_cycles(uint64_t clocks) const noexcept override { return (clocks + 4 - 1) / 4; }
virtual uint64_t execute_cycles_to_clocks(uint64_t cycles) const noexcept override { return (cycles * 4); }
virtual uint32_t execute_min_cycles() const noexcept override { return 1; }
virtual uint32_t execute_max_cycles() const noexcept override { return 2; }
virtual u64 execute_clocks_to_cycles(u64 clocks) const noexcept override { return (clocks + 4 - 1) / 4; }
virtual u64 execute_cycles_to_clocks(u64 cycles) const noexcept override { return (cycles * 4); }
virtual u32 execute_min_cycles() const noexcept override { return 1; }
virtual u32 execute_max_cycles() const noexcept override { return 2; }
virtual void execute_run() override;
virtual void execute_one() = 0;
virtual bool op_argument() = 0;
@ -138,59 +138,6 @@ protected:
// misc handlers
void cycle();
void increment_pc();
u8 ram_r();
void ram_w(u8 data);
void pop_pc();
void push_pc();
// opcode handlers
void op_ad();
void op_add();
void op_sub();
void op_comp();
void op_0ta();
void op_adx();
void op_hxa();
void op_tam();
void op_sc();
void op_rsc();
void op_tc();
void op_tin();
void op_tf();
void op_tkb();
void op_tir();
void op_btd();
void op_dspa();
void op_dsps();
void op_axo();
void op_ldf();
void op_read();
void op_go();
void op_call();
void op_ret();
void op_rets();
void op_lg();
void op_nop();
void op_exc();
void op_excm();
void op_excp();
void op_mta();
void op_lm();
void op_sm();
void op_rsm();
void op_tm();
void op_lb();
void op_lbl();
void op_atb();
void op_bta();
void op_hxbr();
};

View File

@ -24,8 +24,9 @@ cops1_common_disassembler::cops1_common_disassembler()
offs_t cops1_common_disassembler::increment_pc(offs_t pc)
{
u8 feed = (pc & 0x3f) == 0 || ((pc >> 1 ^ pc) & 1) ? 0x20 : 0;
return (pc & ~0x3f) | (pc >> 1 & 0x1f) | feed;
int feed = ((pc & 0x3e) == 0) ? 1 : 0;
feed ^= (pc >> 1 ^ pc) & 1;
return (pc & ~0x3f) | (pc >> 1 & 0x1f) | (feed << 5);
}

View File

@ -39,8 +39,8 @@ protected:
};
static const char *const s_name[];
static const uint8_t s_bits[];
static const uint32_t s_flags[];
static const u8 s_bits[];
static const u32 s_flags[];
u8 m_l2r[0x40];
u8 m_r2l[0x40];

View File

@ -42,7 +42,7 @@ void mm5799_device::data_map(address_map &map)
// device definitions
mm5799_device::mm5799_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
mm5799_device::mm5799_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
cops1_base_device(mconfig, MM5799, tag, owner, clock, 11, address_map_constructor(FUNC(mm5799_device::program_map), this), 7, address_map_constructor(FUNC(mm5799_device::data_map), this))
{ }

View File

@ -37,7 +37,7 @@
class mm5799_device : public cops1_base_device
{
public:
mm5799_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
mm5799_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
protected:
// device-level overrides
@ -53,6 +53,60 @@ protected:
void data_map(address_map &map);
void program_map(address_map &map);
// opcode helpers
u8 ram_r();
void ram_w(u8 data);
void pop_pc();
void push_pc();
// opcode handlers
void op_ad();
void op_add();
void op_sub();
void op_comp();
void op_0ta();
void op_adx();
void op_hxa();
void op_tam();
void op_sc();
void op_rsc();
void op_tc();
void op_tin();
void op_tf();
void op_tkb();
void op_tir();
void op_btd();
void op_dspa();
void op_dsps();
void op_axo();
void op_ldf();
void op_read();
void op_go();
void op_call();
void op_ret();
void op_rets();
void op_lg();
void op_nop();
void op_exc();
void op_excm();
void op_excp();
void op_mta();
void op_lm();
void op_sm();
void op_rsm();
void op_tm();
void op_lb();
void op_lbl();
void op_atb();
void op_bta();
void op_hxbr();
};

View File

@ -1,31 +1,31 @@
// license:BSD-3-Clause
// copyright-holders:hap
// COPS opcode handlers
// MM5799 opcode handlers
#include "emu.h"
#include "cops1base.h"
#include "mm5799.h"
// internal helpers
inline u8 cops1_base_device::ram_r()
inline u8 mm5799_device::ram_r()
{
return m_data->read_byte(m_b) & 0xf;
}
inline void cops1_base_device::ram_w(u8 data)
inline void mm5799_device::ram_w(u8 data)
{
m_data->write_byte(m_b, data & 0xf);
}
void cops1_base_device::pop_pc()
void mm5799_device::pop_pc()
{
m_pc = m_sa;
m_sa = m_sb;
}
void cops1_base_device::push_pc()
void mm5799_device::push_pc()
{
m_sb = m_sa;
m_sa = m_pc;
@ -36,13 +36,13 @@ void cops1_base_device::push_pc()
// arithmetic operations
void cops1_base_device::op_ad()
void mm5799_device::op_ad()
{
// add M to A
m_a = (m_a + ram_r()) & 0xf;
}
void cops1_base_device::op_add()
void mm5799_device::op_add()
{
// ADD: add M+carry to A
m_a = m_a + ram_r() + m_c;
@ -51,7 +51,7 @@ void cops1_base_device::op_add()
m_skip = !bool(m_c);
}
void cops1_base_device::op_sub()
void mm5799_device::op_sub()
{
// SUB: subtract A+carry from M
m_a = (m_a ^ 0xf) + ram_r() + m_c;
@ -60,19 +60,19 @@ void cops1_base_device::op_sub()
m_skip = bool(m_c);
}
void cops1_base_device::op_comp()
void mm5799_device::op_comp()
{
// COMP: complement A
m_a ^= 0xf;
}
void cops1_base_device::op_0ta()
void mm5799_device::op_0ta()
{
// 0TA: clear A
m_a = 0;
}
void cops1_base_device::op_adx()
void mm5799_device::op_adx()
{
// ADX x: add constant to A
u8 x = m_op & 0xf;
@ -81,7 +81,7 @@ void cops1_base_device::op_adx()
m_a &= 0xf;
}
void cops1_base_device::op_hxa()
void mm5799_device::op_hxa()
{
// HXA: exchange A with H
u8 h = m_h;
@ -89,25 +89,25 @@ void cops1_base_device::op_hxa()
m_a = h;
}
void cops1_base_device::op_tam()
void mm5799_device::op_tam()
{
// TAM: compare A with M
m_skip = m_a == ram_r();
}
void cops1_base_device::op_sc()
void mm5799_device::op_sc()
{
// SC: set carry
m_c = 1;
}
void cops1_base_device::op_rsc()
void mm5799_device::op_rsc()
{
// RSC: reset carry
m_c = 0;
}
void cops1_base_device::op_tc()
void mm5799_device::op_tc()
{
// TC: test carry
m_skip = !m_c;
@ -116,28 +116,28 @@ void cops1_base_device::op_tc()
// input test
void cops1_base_device::op_tin()
void mm5799_device::op_tin()
{
// TIN: test INB pin
bool t = !bool(m_read_inb() & 1);
m_skip = m_option_inb_active_high ? t : !t;
}
void cops1_base_device::op_tf()
void mm5799_device::op_tf()
{
// TF x: test F pin
u8 f = m_read_f.isnull() ? m_f : m_read_f();
m_skip = !BIT(f, m_op >> 4 & 3);
}
void cops1_base_device::op_tkb()
void mm5799_device::op_tkb()
{
// TKB: test K pins
bool t = bool(m_read_k() & 0xf);
m_skip = m_option_k_active_high ? t : !t;
}
void cops1_base_device::op_tir()
void mm5799_device::op_tir()
{
// TIR: test DO3 pin
int d = m_read_do3.isnull() ? (m_do >> 2) : m_read_do3();
@ -147,28 +147,28 @@ void cops1_base_device::op_tir()
// input/output
void cops1_base_device::op_btd()
void mm5799_device::op_btd()
{
// BTD: transfer B(d) to digit output latches
m_do = ~m_b & 0xf;
m_write_do(m_do);
}
void cops1_base_device::op_dspa()
void mm5799_device::op_dspa()
{
// DSPA: transfer A+H+C to segment output latches, direct
u8 segs = bitswap<7>(m_h << 4 | m_a, 4,5,6,0,1,2,3);
m_write_s((m_c << 7 ^ 0x80) | segs);
}
void cops1_base_device::op_dsps()
void mm5799_device::op_dsps()
{
// DSPS: transfer A+C to segment output latches, via PLA
u8 segs = ~m_opla->read((m_a + 1) & 0xf) & 0x7f;
m_write_s((m_c << 7 ^ 0x80) | segs);
}
void cops1_base_device::op_axo()
void mm5799_device::op_axo()
{
// AXO: exchange A with serial
u8 s = m_serial;
@ -180,7 +180,7 @@ void cops1_base_device::op_axo()
m_a = (m_a & 7) | (m_read_si() << 3 & 8);
}
void cops1_base_device::op_ldf()
void mm5799_device::op_ldf()
{
// LDF x: load F pin(s)
u8 mask = bitswap<4>(~m_arg, 7,5,3,1);
@ -189,7 +189,7 @@ void cops1_base_device::op_ldf()
m_write_f(m_f);
}
void cops1_base_device::op_read()
void mm5799_device::op_read()
{
// READ: read K pins to A
m_a = m_read_k() & 0xf;
@ -198,7 +198,7 @@ void cops1_base_device::op_read()
// control functions
void cops1_base_device::op_go()
void mm5799_device::op_go()
{
// GO x: jump to address in page
@ -209,7 +209,7 @@ void cops1_base_device::op_go()
m_pc = (m_pc & ~0x3f) | (m_op & 0x3f);
}
void cops1_base_device::op_call()
void mm5799_device::op_call()
{
// CALL x: call subroutine
@ -220,20 +220,20 @@ void cops1_base_device::op_call()
m_pc = (m_op & 0x3f) | 0x7c0;
}
void cops1_base_device::op_ret()
void mm5799_device::op_ret()
{
// RET: return from subroutine
pop_pc();
}
void cops1_base_device::op_rets()
void mm5799_device::op_rets()
{
// RET: return from subroutine, skip next
op_ret();
m_skip = true;
}
void cops1_base_device::op_lg()
void mm5799_device::op_lg()
{
// LG x: long go / long call
if (~m_arg & 0x40)
@ -242,7 +242,7 @@ void cops1_base_device::op_lg()
m_pc = (~m_op << 7 & 0x780) | (m_arg >> 1 & 0x40) | (m_arg & 0x3f);
}
void cops1_base_device::op_nop()
void mm5799_device::op_nop()
{
// NOP: no operation
}
@ -250,7 +250,7 @@ void cops1_base_device::op_nop()
// memory digit operations
void cops1_base_device::op_exc()
void mm5799_device::op_exc()
{
// EXC x: exchange A with M, XOR B(r) with x
u8 a = m_a;
@ -259,7 +259,7 @@ void cops1_base_device::op_exc()
m_b ^= m_op & 0x30;
}
void cops1_base_device::op_excm()
void mm5799_device::op_excm()
{
// EXC- x: EXC + decrement B(d)
op_exc();
@ -267,7 +267,7 @@ void cops1_base_device::op_excm()
m_skip = (m_b & 0xf) == 0xf;
}
void cops1_base_device::op_excp()
void mm5799_device::op_excp()
{
// EXC+ x: EXC + increment B(d)
op_exc();
@ -279,14 +279,14 @@ void cops1_base_device::op_excp()
m_skip = true;
}
void cops1_base_device::op_mta()
void mm5799_device::op_mta()
{
// MTA x: load A with M, XOR B(r) with x
m_a = ram_r();
m_b ^= m_op & 0x30;
}
void cops1_base_device::op_lm()
void mm5799_device::op_lm()
{
// LM x: load M with constant, increment B(d)
ram_w(m_op & 0xf);
@ -296,7 +296,7 @@ void cops1_base_device::op_lm()
// memory bit operations
void cops1_base_device::op_sm()
void mm5799_device::op_sm()
{
// SM x: set memory bit
u8 x = 0;
@ -312,7 +312,7 @@ void cops1_base_device::op_sm()
ram_w(ram_r() | x);
}
void cops1_base_device::op_rsm()
void mm5799_device::op_rsm()
{
// RSM x: reset memory bit
u8 x = 0;
@ -328,7 +328,7 @@ void cops1_base_device::op_rsm()
ram_w(ram_r() & ~x);
}
void cops1_base_device::op_tm()
void mm5799_device::op_tm()
{
// TM x: test memory bit
m_skip = !BIT(ram_r(), m_op & 3);
@ -337,7 +337,7 @@ void cops1_base_device::op_tm()
// memory address operations
void cops1_base_device::op_lb()
void mm5799_device::op_lb()
{
// LB x: load B (successive LB are ignored)
if ((m_prev_op & 0xc0) == 0x00 && (m_prev_op & 0xf) >= 0xa)
@ -351,25 +351,25 @@ void cops1_base_device::op_lb()
m_b = ((m_op & 0x30) | x) & m_datamask;
}
void cops1_base_device::op_lbl()
void mm5799_device::op_lbl()
{
// LBL x: load B fully
m_b = m_arg & m_datamask;
}
void cops1_base_device::op_atb()
void mm5799_device::op_atb()
{
// ATB: transfer A to B(d)
m_b = (m_b & ~0xf) | m_a;
}
void cops1_base_device::op_bta()
void mm5799_device::op_bta()
{
// BTA: transfer B(d) to A
m_a = m_b & 0xf;
}
void cops1_base_device::op_hxbr()
void mm5799_device::op_hxbr()
{
// HXBR: exchange H with B(r)
u8 h = m_h;

View File

@ -839,7 +839,7 @@ void e0c6200_cpu_device::execute_one()
// illegal opcode
default:
logerror("%s unknown opcode $%03X at $%04X\n", tag(), m_op, m_prev_pc);
logerror("unknown opcode $%03X at $%04X\n", m_op, m_prev_pc);
break;
} // 0xff0

View File

@ -390,7 +390,7 @@ void e0c6s46_device::clock_watchdog()
// initial reset after 3 to 4 seconds
if (++m_watchdog_count == 4)
{
logerror("%s watchdog reset\n", tag());
logerror("watchdog reset\n");
m_watchdog_count = 0;
device_reset();
}
@ -690,7 +690,7 @@ u8 e0c6s46_device::io_r(offs_t offset)
default:
if (!machine().side_effects_disabled())
logerror("%s unknown io_r from $0F%02X at $%04X\n", tag(), offset, m_prev_pc);
logerror("unknown io_r from $0F%02X at $%04X\n", offset, m_prev_pc);
break;
}
@ -758,7 +758,7 @@ void e0c6s46_device::io_w(offs_t offset, u8 data)
// d2: OSC3 on (high freq)
// d3: clock source OSC1 or OSC3
if (data & 8)
logerror("%s io_w selected OSC3! PC=$%04X\n", tag(), m_prev_pc);
logerror("io_w selected OSC3! PC=$%04X\n", m_prev_pc);
m_osc = data;
break;
@ -861,7 +861,7 @@ void e0c6s46_device::io_w(offs_t offset, u8 data)
// d2: reset envelope
// d3: trigger one-shot buzzer
if (data & 1)
logerror("%s io_w enabled envelope, PC=$%04X\n", tag(), m_prev_pc);
logerror("io_w enabled envelope, PC=$%04X\n", m_prev_pc);
m_bz_envelope = data & 3;
m_bz_1shot_on |= data & 8;
break;
@ -874,7 +874,7 @@ void e0c6s46_device::io_w(offs_t offset, u8 data)
default:
if (machine().phase() > machine_phase::RESET)
logerror("%s unknown io_w $%X to $0F%02X at $%04X\n", tag(), data, offset, m_prev_pc);
logerror("unknown io_w $%X to $0F%02X at $%04X\n", data, offset, m_prev_pc);
break;
}
}

View File

@ -376,7 +376,7 @@ u8 hmcs43_cpu_device::read_r(int index)
index &= 7;
if (index >= 2)
logerror("%s read from %s port R%d at $%04X\n", tag(), (index >= 4) ? "unknown" : "output", index, m_prev_pc);
logerror("read from %s port R%d at $%04X\n", (index >= 4) ? "unknown" : "output", index, m_prev_pc);
return hmcs40_cpu_device::read_r(index);
}
@ -388,7 +388,7 @@ void hmcs43_cpu_device::write_r(int index, u8 data)
if (index != 0 && index < 4)
hmcs40_cpu_device::write_r(index, data);
else
logerror("%s ineffective write to port R%d = $%X at $%04X\n", tag(), index, data & 0xf, m_prev_pc);
logerror("ineffective write to port R%d = $%X at $%04X\n", index, data & 0xf, m_prev_pc);
}
int hmcs43_cpu_device::read_d(int index)
@ -396,7 +396,7 @@ int hmcs43_cpu_device::read_d(int index)
index &= 15;
if (index >= 4)
logerror("%s read from output pin D%d at $%04X\n", tag(), index, m_prev_pc);
logerror("read from output pin D%d at $%04X\n", index, m_prev_pc);
return hmcs40_cpu_device::read_d(index);
}
@ -410,7 +410,7 @@ u8 hmcs44_cpu_device::read_r(int index)
index &= 7;
if (index >= 6)
logerror("%s read from unknown port R%d at $%04X\n", tag(), index, m_prev_pc);
logerror("read from unknown port R%d at $%04X\n", index, m_prev_pc);
return hmcs40_cpu_device::read_r(index);
}
@ -422,7 +422,7 @@ void hmcs44_cpu_device::write_r(int index, u8 data)
if (index < 6)
hmcs40_cpu_device::write_r(index, data);
else
logerror("%s ineffective write to port R%d = $%X at $%04X\n", tag(), index, data & 0xf, m_prev_pc);
logerror("ineffective write to port R%d = $%X at $%04X\n", index, data & 0xf, m_prev_pc);
}
// HMCS45:
@ -434,7 +434,7 @@ u8 hmcs45_cpu_device::read_r(int index)
index &= 7;
if (index >= 6)
logerror("%s read from %s port R%d at $%04X\n", tag(), (index == 7) ? "unknown" : "output", index, m_prev_pc);
logerror("read from %s port R%d at $%04X\n", (index == 7) ? "unknown" : "output", index, m_prev_pc);
return hmcs40_cpu_device::read_r(index);
}
@ -446,7 +446,7 @@ void hmcs45_cpu_device::write_r(int index, u8 data)
if (index != 7)
hmcs40_cpu_device::write_r(index, data);
else
logerror("%s ineffective write to port R%d = $%X at $%04X\n", tag(), index, data & 0xf, m_prev_pc);
logerror("ineffective write to port R%d = $%X at $%04X\n", index, data & 0xf, m_prev_pc);
}

View File

@ -49,7 +49,7 @@ void hmcs40_cpu_device::push_stack()
void hmcs40_cpu_device::op_illegal()
{
logerror("%s unknown opcode $%03X at $%04X\n", tag(), m_op, m_prev_pc);
logerror("unknown opcode $%03X at $%04X\n", m_op, m_prev_pc);
}

View File

@ -452,7 +452,8 @@ void melps4_cpu_device::execute_run()
m_prohibit_irq = false;
// fetch next opcode
debugger_instruction_hook(m_pc);
if (!m_skip)
debugger_instruction_hook(m_pc);
m_icount--;
m_op = m_program->read_word(m_pc) & 0x1ff;
m_bitmask = 1 << (m_op & 3);

View File

@ -696,5 +696,5 @@ void melps4_cpu_device::op_nop()
void melps4_cpu_device::op_illegal()
{
logerror("%s unknown opcode $%03X at $%04X\n", tag(), m_op, m_prev_pc);
logerror("unknown opcode $%03X at $%04X\n", m_op, m_prev_pc);
}

View File

@ -0,0 +1,71 @@
// license:BSD-3-Clause
// copyright-holders:hap
/*
Rockwell MM76 MCU
*/
#include "emu.h"
#include "mm76.h"
#include "pps41d.h"
DEFINE_DEVICE_TYPE(MM76, mm76_device, "mm76", "Rockwell MM76")
// internal memory maps
void mm76_device::program_map(address_map &map)
{
map(0x0000, 0x01ff).rom();
map(0x0380, 0x03ff).rom();
}
void mm76_device::data_map(address_map &map)
{
map(0x00, 0x02f).ram();
}
// device definitions
mm76_device::mm76_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
pps41_base_device(mconfig, MM76, tag, owner, clock, 10, address_map_constructor(FUNC(mm76_device::program_map), this), 6, address_map_constructor(FUNC(mm76_device::data_map), this))
{ }
// machine config
void mm76_device::device_add_mconfig(machine_config &config)
{
PLA(config, "opla", 5, 8, 17).set_format(pla_device::FMT::BERKELEY);
}
// disasm
std::unique_ptr<util::disasm_interface> mm76_device::create_disassembler()
{
return std::make_unique<mm76_disassembler>();
}
// initialize
void mm76_device::device_start()
{
pps41_base_device::device_start();
m_stack_levels = 1;
}
void mm76_device::device_reset()
{
pps41_base_device::device_reset();
}
//-------------------------------------------------
// execute
//-------------------------------------------------
void mm76_device::execute_one()
{
op_nop();
}

View File

@ -0,0 +1,59 @@
// license:BSD-3-Clause
// copyright-holders:hap
/*
Rockwell MM76 MCU
*/
#ifndef MAME_CPU_PPS41_MM76_H
#define MAME_CPU_PPS41_MM76_H
#pragma once
#include "pps41base.h"
// pinout reference
/*
...
*/
class mm76_device : public pps41_base_device
{
public:
mm76_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
protected:
// device-level overrides
virtual void device_start() override;
virtual void device_reset() override;
virtual void device_add_mconfig(machine_config &config) override;
// device_disasm_interface overrides
virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
// device_execute_interface overrides
virtual void execute_one() override;
void data_map(address_map &map);
void program_map(address_map &map);
// opcode helpers
u8 ram_r();
void ram_w(u8 data);
void pop_pc();
void push_pc();
void op_illegal();
virtual bool op_is_prefix(u8 op) override { return (op & 0xf0) == 0x30; };
// opcode handlers
void op_nop();
};
DECLARE_DEVICE_TYPE(MM76, mm76_device)
#endif // MAME_CPU_PPS41_MM76_H

View File

@ -0,0 +1,46 @@
// license:BSD-3-Clause
// copyright-holders:hap
// MM76 opcode handlers
#include "emu.h"
#include "mm76.h"
// internal helpers
inline u8 mm76_device::ram_r()
{
return m_data->read_byte(m_b & m_datamask) & 0xf;
}
inline void mm76_device::ram_w(u8 data)
{
m_data->write_byte(m_b & m_datamask, data & 0xf);
}
void mm76_device::pop_pc()
{
m_pc = m_stack[0] & m_prgmask;
for (int i = 0; i < m_stack_levels-1; i++)
m_stack[i] = m_stack[i+1];
}
void mm76_device::push_pc()
{
for (int i = m_stack_levels-1; i >= 1; i--)
m_stack[i] = m_stack[i-1];
m_stack[0] = m_pc;
}
void mm76_device::op_illegal()
{
logerror("unknown opcode $%02X at $%03X\n", m_op, m_prev_pc);
}
// opcodes
void mm76_device::op_nop()
{
}

View File

@ -0,0 +1,230 @@
// license:BSD-3-Clause
// copyright-holders:hap
/*
Rockwell PPS-4/1 MCU cores
This is the single-chip evolution of Rockwell's older PPS-4 CPU. It is similar,
but a lot of things were simplified, the ALU instructions are less diverse.
Part numbers:
- A75xx = MM75 - 28 pin dip
- A76xx = MM76 - 42 pin spider
- A77xx = MM77 - 42 pin spider
- A78xx = MM78 - 42 pin spider
- A79xx = MM76C - 52 pin spider
- A86xx = MM76E - 42 pin spider
- B76xx = MM76L - 40 pin dip
- B77xx = MM77L - 40 pin dip
- B78xx = MM78L - 40 pin dip
- B86xx = MM76EL - 40 pin dip
- B90xx = MM78LA - 42 pin spider
"spider" = 2 rows of pins on each side, just like standard PPS-4 CPUs.
"L" only difference is low-power
References:
- Series MM76 Product Description
- Series MM77 Product Description
- MM76 Microcomputer Programming Manual
- MM77 Microcomputer Programming Manual
TODO:
- add extended opcodes to disasm? it's easy to add there, but the emulation goes
through prefixes 1 cycle at the time which means the live disasm gets messy
- WIP
*/
#include "emu.h"
#include "pps41base.h"
#include "debugger.h"
pps41_base_device::pps41_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, int prgwidth, address_map_constructor program, int datawidth, address_map_constructor data) :
cpu_device(mconfig, type, tag, owner, clock),
m_program_config("program", ENDIANNESS_LITTLE, 8, prgwidth, 0, program),
m_data_config("data", ENDIANNESS_LITTLE, 8, datawidth, 0, data),
m_prgwidth(prgwidth),
m_datawidth(datawidth),
m_opla(*this, "opla")
{ }
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
enum
{
PPS41_PC=1, PPS41_A, PPS41_C, PPS41_B
};
void pps41_base_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;
// resolve callbacks
//..
// zerofill
m_pc = 0;
m_prev_pc = 0;
m_op = 0;
m_prev_op = 0;
m_prev2_op = 0;
memset(m_stack, 0, sizeof(m_stack));
m_a = 0;
m_b = 0;
m_prev_b = 0;
m_prev2_b = 0;
m_ram_addr = 0;
m_ram_delay = false;
m_sag = false;
m_c = 0;
m_prev_c = 0;
m_c_in = 0;
m_c_delay = false;
m_skip = false;
m_skip_count = 0;
// register for savestates
save_item(NAME(m_pc));
save_item(NAME(m_prev_pc));
save_item(NAME(m_op));
save_item(NAME(m_prev_op));
save_item(NAME(m_prev2_op));
save_item(NAME(m_stack));
save_item(NAME(m_a));
save_item(NAME(m_b));
save_item(NAME(m_prev_b));
save_item(NAME(m_prev2_b));
save_item(NAME(m_ram_addr));
save_item(NAME(m_ram_delay));
save_item(NAME(m_sag));
save_item(NAME(m_c));
save_item(NAME(m_prev_c));
save_item(NAME(m_c_in));
save_item(NAME(m_c_delay));
save_item(NAME(m_skip));
save_item(NAME(m_skip_count));
// register state for debugger
state_add(STATE_GENPC, "GENPC", m_pc).formatstr("%03X").noshow();
state_add(STATE_GENPCBASE, "CURPC", m_prev_pc).formatstr("%03X").noshow();
state_add(PPS41_PC, "PC", m_pc).formatstr("%03X");
state_add(PPS41_A, "A", m_a).formatstr("%01X");
state_add(PPS41_C, "C", m_c_in).formatstr("%01X");
state_add(PPS41_B, "B", m_b).formatstr("%02X");
set_icountptr(m_icount);
}
device_memory_interface::space_config_vector pps41_base_device::memory_space_config() const
{
return space_config_vector {
std::make_pair(AS_PROGRAM, &m_program_config),
std::make_pair(AS_DATA, &m_data_config)
};
}
//-------------------------------------------------
// device_reset - device-specific reset
//-------------------------------------------------
void pps41_base_device::device_reset()
{
m_op = m_prev_op = 0;
m_pc = m_prgmask >> 1 & ~0x3f;
m_skip = false;
m_skip_count = 0;
// clear outputs
//..
}
//-------------------------------------------------
// execute
//-------------------------------------------------
void pps41_base_device::cycle()
{
m_icount--;
}
void pps41_base_device::increment_pc()
{
// low part is LFSR
int feed = ((m_pc & 0x3e) == 0) ? 1 : 0;
feed ^= (m_pc >> 1 ^ m_pc) & 1;
m_pc = (m_pc & ~0x3f) | (m_pc >> 1 & 0x1f) | (feed << 5);
}
void pps41_base_device::execute_run()
{
while (m_icount > 0)
{
// remember previous state
m_prev2_op = m_prev_op;
m_prev_op = m_op;
m_prev_pc = m_pc;
m_prev2_b = m_prev_b;
m_prev_b = m_b;
m_prev_c = m_c;
// fetch next opcode
if (!m_skip && !m_skip_count)
debugger_instruction_hook(m_pc);
m_op = m_program->read_byte(m_pc);
increment_pc();
cycle();
// handle opcode if it's not skipped
if (m_skip)
{
// still skip through prefix(es)
m_skip = op_is_prefix(m_op);
m_op = 0; // fake nop
}
else if (m_skip_count)
{
m_skip_count--;
// restore opcode state
m_op = m_prev_op;
m_prev_op = m_prev2_op;
}
else
execute_one();
// some opcodes delay RAM address(Bl part) adjustment for 1 cycle
m_ram_addr = m_b;
if (m_ram_delay)
{
m_ram_addr = (m_ram_addr & ~0xf) | (m_prev_b & 0xf);
m_ram_delay = false;
}
// SAG sets RAM address(Bu part) to 3 for the next cycle
if (m_sag)
{
m_ram_addr = (m_ram_addr & 0xf) | 0x30;
m_sag = false;
}
// and some opcodes delay carry adjustment for 1 cycle
m_c_in = m_c_delay ? m_prev_c : m_c;
m_c_delay = false;
}
}

View File

@ -0,0 +1,94 @@
// license:BSD-3-Clause
// copyright-holders:hap
/*
Rockwell PPS-4/1 MCU cores
*/
#ifndef MAME_CPU_PPS41_PPS41BASE_H
#define MAME_CPU_PPS41_PPS41BASE_H
#pragma once
#include "machine/pla.h"
class pps41_base_device : public cpu_device
{
public:
// configuration helpers
// I/O ports:
//..
// set MCU mask options:
//..
protected:
// construction/destruction
pps41_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, int prgwidth, address_map_constructor program, int datawidth, address_map_constructor data);
// device-level overrides
virtual void device_start() override;
virtual void device_reset() override;
// device_execute_interface overrides
virtual u32 execute_min_cycles() const noexcept override { return 1; }
virtual u32 execute_max_cycles() const noexcept override { return 2; }
virtual void execute_run() override;
virtual void execute_one() = 0;
// device_memory_interface overrides
virtual space_config_vector memory_space_config() const override;
address_space_config m_program_config;
address_space_config m_data_config;
address_space *m_program;
address_space *m_data;
int m_icount;
// fixed settings or mask options
int m_prgwidth; // ROM/RAM address size
int m_datawidth; // "
u16 m_prgmask; // "
u16 m_datamask; // "
optional_device<pla_device> m_opla; // segment output PLA
// i/o handlers
//..
// internal state, regs
u16 m_pc;
u16 m_prev_pc;
u8 m_op;
u8 m_prev_op;
u8 m_prev2_op;
int m_stack_levels;
u16 m_stack[2]; // max 2
u8 m_a;
u8 m_b;
u8 m_prev_b;
u8 m_prev2_b;
u8 m_ram_addr;
bool m_ram_delay;
bool m_sag;
int m_c;
int m_prev_c;
int m_c_in;
bool m_c_delay;
bool m_skip;
int m_skip_count;
// misc handlers
virtual bool op_is_prefix(u8 op) = 0;
void cycle();
void increment_pc();
};
#endif // MAME_CPU_PPS41_PPS41BASE_H

View File

@ -0,0 +1,141 @@
// license:BSD-3-Clause
// copyright-holders:hap
/*
Rockwell PPS-4/1 disassembler
*/
#include "emu.h"
#include "pps41d.h"
// constructor
pps41_common_disassembler::pps41_common_disassembler()
{
// init lfsr pc lut
for (u32 i = 0, pc = 0; i < 0x40; i++)
{
m_l2r[i] = pc;
m_r2l[pc] = i;
pc = increment_pc(pc);
}
}
offs_t pps41_common_disassembler::increment_pc(offs_t pc)
{
int feed = ((pc & 0x3e) == 0) ? 1 : 0;
feed ^= (pc >> 1 ^ pc) & 1;
return (pc & ~0x3f) | (pc >> 1 & 0x1f) | (feed << 5);
}
// common lookup tables
const char *const pps41_common_disassembler::s_name[] =
{
"?",
"XAB", "LBA", "LB", "EOB",
"SB", "RB", "SKBF",
"XAS", "LSA",
"L", "X", "XDSK", "XNSK",
"A", "AC", "ACSK", "ASK", "COM", "RC", "SC", "SKNC", "LAI", "AISK",
"RT", "RTSK", "T", "NOP", "TL", "TM", "TML", "TR",
"SKMEA", "SKBEI", "SKAEI",
"SOS", "ROS", "SKISL", "IBM", "OB", "IAM", "OA", "IOS", "I1", "I2C", "INT1H", "DIN1", "INT0L", "DIN0", "SEG1", "SEG2"
};
// number of bits per opcode parameter
// note: d4 means hex, d5 means inverted, d6 means extended
const u8 pps41_common_disassembler::s_bits[] =
{
0,
0, 0, 4, 2,
2, 2, 2,
0, 0,
2, 2, 2, 2,
0, 0, 0, 0, 0, 0, 0, 0, 4, 4,
0, 0, 0x36, 0, 0x76, 0x36, 0x76, 0x34,
0, 0x40, 0x60,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};
const u32 pps41_common_disassembler::s_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,
STEP_OUT, STEP_OUT, 0, 0, 0, STEP_OVER, STEP_OVER, 0,
0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};
// common disasm
offs_t pps41_common_disassembler::common_disasm(const u8 *lut_opmap, std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer &params)
{
// get raw opcode
u8 op = opcodes.r8(pc);
u8 instr = lut_opmap[op];
// get parameter
u8 bits = s_bits[instr];
u16 mask = (1 << (bits & 0xf)) - 1;
bits &= 0xf0;
u16 param = op & mask;
if (bits & 0x20)
param ^= mask;
// memory bit opcodes are 1,2,3,4
if (instr == em_SB || instr == em_RB || instr == em_SKBF)
param++;
// disassemble it
util::stream_format(stream, "%-6s ", s_name[instr]);
if (mask > 0)
{
if (bits & 0x10)
util::stream_format(stream, (mask & ~0xf) ? "$%02X" : "$%X", param);
else
util::stream_format(stream, "%d", param);
}
return 1 | s_flags[instr] | SUPPORTED;
}
// MM76 disasm
const u8 mm76_disassembler::mm76_opmap[0x100] =
{
/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
em_NOP, em_SKNC, em_RT, em_RTSK, em_INT0L,em_INT1H,em_DIN1, em_DIN0, em_SKBF, em_SKBF, em_SKBF, em_SKBF, em_SC, em_RC, em_SEG1, em_SEG2, // 0
em_SB, em_SB, em_SB, em_SB, em_RB, em_RB, em_RB, em_RB, em_OA, em_OB, em_IAM, em_IBM, em_EOB, em_EOB, em_EOB, em_EOB, // 1
em_LB, em_LB, em_LB, em_LB, em_LB, em_LB, em_LB, em_LB, em_LB, em_LB, em_LB, em_LB, em_LB, em_LB, em_LB, em_LB, // 2
em_TR, em_TR, em_TR, em_TR, em_TR, em_TR, em_TR, em_TR, em_TR, em_TR, em_TR, em_TR, em_TR, em_TR, em_TR, em_TR, // 3
em_AC, em_ACSK, em_A, em_ASK, em_LBA, em_COM, em_XAB, em_SKMEA,em_ILL, em_ILL, em_I1, em_I2C, em_LSA, em_IOS, em_XAS, em_ILL, // 4
em_L, em_L, em_L, em_L, em_XNSK, em_XNSK, em_XNSK, em_XNSK, em_X, em_X, em_X, em_X, em_XDSK, em_XDSK, em_XDSK, em_XDSK, // 5
em_AISK, em_AISK, em_AISK, em_AISK, em_AISK, em_AISK, em_AISK, em_AISK, em_AISK, em_AISK, em_AISK, em_AISK, em_AISK, em_AISK, em_AISK, em_AISK, // 6
em_LAI, em_LAI, em_LAI, em_LAI, em_LAI, em_LAI, em_LAI, em_LAI, em_LAI, em_LAI, em_LAI, em_LAI, em_LAI, em_LAI, em_LAI, em_LAI, // 7
em_TM, em_TM, em_TM, em_TM, em_TM, em_TM, em_TM, em_TM, em_TM, em_TM, em_TM, em_TM, em_TM, em_TM, em_TM, em_TM, // 8
em_TM, em_TM, em_TM, em_TM, em_TM, em_TM, em_TM, em_TM, em_TM, em_TM, em_TM, em_TM, em_TM, em_TM, em_TM, em_TM, // 9
em_TM, em_TM, em_TM, em_TM, em_TM, em_TM, em_TM, em_TM, em_TM, em_TM, em_TM, em_TM, em_TM, em_TM, em_TM, em_TM, // A
em_TM, em_TM, em_TM, em_TM, em_TM, em_TM, em_TM, em_TM, em_TM, em_TM, em_TM, em_TM, em_TM, em_TM, em_TM, em_TM, // B
em_T, em_T, em_T, em_T, em_T, em_T, em_T, em_T, em_T, em_T, em_T, em_T, em_T, em_T, em_T, em_T, // C
em_T, em_T, em_T, em_T, em_T, em_T, em_T, em_T, em_T, em_T, em_T, em_T, em_T, em_T, em_T, em_T, // D
em_T, em_T, em_T, em_T, em_T, em_T, em_T, em_T, em_T, em_T, em_T, em_T, em_T, em_T, em_T, em_T, // E
em_T, em_T, em_T, em_T, em_T, em_T, em_T, em_T, em_T, em_T, em_T, em_T, em_T, em_T, em_T, em_T // F
};
offs_t mm76_disassembler::disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer &params)
{
return common_disasm(mm76_opmap, stream, pc, opcodes, params);
}

View File

@ -0,0 +1,66 @@
// license:BSD-3-Clause
// copyright-holders:hap
/*
Rockwell PPS-4/1 disassembler
*/
#ifndef MAME_CPU_PPS41_PPS41D_H
#define MAME_CPU_PPS41_PPS41D_H
#pragma once
class pps41_common_disassembler : public util::disasm_interface
{
public:
pps41_common_disassembler();
virtual ~pps41_common_disassembler() = default;
virtual u32 opcode_alignment() const override { return 1; }
virtual u32 interface_flags() const override { return NONLINEAR_PC | PAGED; }
virtual u32 page_address_bits() const override { return 6; }
virtual offs_t pc_linear_to_real(offs_t pc) const override { return (pc & ~0x3f) | m_l2r[pc & 0x3f]; }
virtual offs_t pc_real_to_linear(offs_t pc) const override { return (pc & ~0x3f) | m_r2l[pc & 0x3f]; }
protected:
// opcode mnemonics
enum e_mnemonics
{
em_ILL,
em_XAB, em_LBA, em_LB, em_EOB,
em_SB, em_RB, em_SKBF,
em_XAS, em_LSA,
em_L, em_X, em_XDSK, em_XNSK,
em_A, em_AC, em_ACSK, em_ASK, em_COM, em_RC, em_SC, em_SKNC, em_LAI, em_AISK,
em_RT, em_RTSK, em_T, em_NOP, em_TL, em_TM, em_TML, em_TR,
em_SKMEA, em_SKBEI, em_SKAEI,
em_SOS, em_ROS, em_SKISL, em_IBM, em_OB, em_IAM, em_OA, em_IOS, em_I1, em_I2C, em_INT1H, em_DIN1, em_INT0L, em_DIN0, em_SEG1, em_SEG2,
};
static const char *const s_name[];
static const u8 s_bits[];
static const u32 s_flags[];
u8 m_l2r[0x40];
u8 m_r2l[0x40];
offs_t increment_pc(offs_t pc);
offs_t common_disasm(const u8 *lut_opmap, std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer &params);
};
class mm76_disassembler : public pps41_common_disassembler
{
public:
mm76_disassembler() = default;
virtual ~mm76_disassembler() = default;
virtual offs_t disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer &params) override;
private:
static const u8 mm76_opmap[0x100];
};
#endif // MAME_CPU_PPS41_PPS41D_H

View File

@ -302,7 +302,8 @@ void sm510_base_device::execute_run()
m_prev_pc = m_pc;
// fetch next opcode
debugger_instruction_hook(m_pc);
if (!m_skip)
debugger_instruction_hook(m_pc);
m_op = m_program->read_byte(m_pc);
increment_pc();
get_opcode_param();

View File

@ -468,5 +468,5 @@ void sm510_base_device::op_clkhi()
void sm510_base_device::op_illegal()
{
logerror("%s unknown opcode $%02X at $%04X\n", tag(), m_op, m_prev_pc);
logerror("unknown opcode $%02X at $%04X\n", m_op, m_prev_pc);
}

View File

@ -153,7 +153,7 @@ void sm511_device::init_melody()
{
u8 data = m_melody_rom[i];
if (data & 0xc0 || (data & 0x0f) > 13)
logerror("%s unknown melody ROM data $%02X at $%02X\n", tag(), data, i);
logerror("unknown melody ROM data $%02X at $%02X\n", data, i);
}
}

View File

@ -277,7 +277,7 @@ u8 ucom4_cpu_device::input_r(int index)
case PORTD: inp = m_read_d(index, 0xff) | m_port_out[index]; break;
default:
logerror("%s read from unknown port %c at $%03X\n", tag(), 'A' + index, m_prev_pc);
logerror("read from unknown port %c at $%03X\n", 'A' + index, m_prev_pc);
break;
}
@ -300,7 +300,7 @@ void ucom4_cpu_device::output_w(int index, u8 data)
case PORTI: m_write_i(index, data & 7, 0xff); break;
default:
logerror("%s write to unknown port %c = $%X at $%03X\n", tag(), 'A' + index, data, m_prev_pc);
logerror("write to unknown port %c = $%X at $%03X\n", 'A' + index, data, m_prev_pc);
break;
}
@ -315,7 +315,7 @@ u8 upd557l_cpu_device::input_r(int index)
index &= 0xf;
if (index == PORTB)
logerror("%s read from unknown port %c at $%03X\n", tag(), 'A' + index, m_prev_pc);
logerror("read from unknown port %c at $%03X\n", 'A' + index, m_prev_pc);
else
return ucom4_cpu_device::input_r(index);
@ -328,7 +328,7 @@ void upd557l_cpu_device::output_w(int index, u8 data)
data &= 0xf;
if (index == PORTH || index == PORTI)
logerror("%s write to unknown port %c = $%X at $%03X\n", tag(), 'A' + index, data, m_prev_pc);
logerror("write to unknown port %c = $%X at $%03X\n", 'A' + index, data, m_prev_pc);
else
{
// only G0 for port G
@ -409,7 +409,8 @@ void ucom4_cpu_device::execute_run()
m_prev_pc = m_pc;
// fetch next opcode
debugger_instruction_hook(m_pc);
if (!m_skip)
debugger_instruction_hook(m_pc);
m_icount--;
m_op = m_program->read_byte(m_pc);
m_bitmask = 1 << (m_op & 0x03);

View File

@ -41,7 +41,7 @@ void ucom4_cpu_device::push_stack()
void ucom4_cpu_device::op_illegal()
{
logerror("%s unknown opcode $%02X at $%03X\n", tag(), m_op, m_prev_pc);
logerror("unknown opcode $%02X at $%03X\n", m_op, m_prev_pc);
}
@ -337,7 +337,7 @@ void ucom4_cpu_device::op_ci()
m_skip = (m_acc == (m_arg & 0x0f));
if ((m_arg & 0xf0) != 0xc0)
logerror("%s CI opcode unexpected upper arg $%02X at $%03X\n", tag(), m_arg & 0xf0, m_prev_pc);
logerror("CI opcode unexpected upper arg $%02X at $%03X\n", m_arg & 0xf0, m_prev_pc);
}
void ucom4_cpu_device::op_cm()
@ -364,7 +364,7 @@ void ucom4_cpu_device::op_cli()
m_skip = (m_dpl == (m_arg & 0x0f));
if ((m_arg & 0xf0) != 0xe0)
logerror("%s CLI opcode unexpected upper arg $%02X at $%03X\n", tag(), m_arg & 0xf0, m_prev_pc);
logerror("CLI opcode unexpected upper arg $%02X at $%03X\n", m_arg & 0xf0, m_prev_pc);
}
void ucom4_cpu_device::op_tmb()
@ -447,7 +447,7 @@ inline bool ucom4_cpu_device::check_op_43()
{
// these opcodes are officially only supported on uCOM-43
if (m_family != NEC_UCOM43)
logerror("%s using uCOM-43 opcode $%02X at $%03X\n", tag(), m_op, m_prev_pc);
logerror("using uCOM-43 opcode $%02X at $%03X\n", m_op, m_prev_pc);
return (m_family == NEC_UCOM43);
}
@ -689,7 +689,7 @@ void ucom4_cpu_device::op_stm()
m_timer->adjust(base * ((m_arg & 0x3f) + 1));
if ((m_arg & 0xc0) != 0x80)
logerror("%s STM opcode unexpected upper arg $%02X at $%03X\n", tag(), m_arg & 0xc0, m_prev_pc);
logerror("STM opcode unexpected upper arg $%02X at $%03X\n", m_arg & 0xc0, m_prev_pc);
}
void ucom4_cpu_device::op_ttm()

View File

@ -0,0 +1,162 @@
// license:BSD-3-Clause
// copyright-holders:hap
// thanks-to:Sean Riddle, Kevin Horton
/***************************************************************************
Rockwell PPS-4/1 MCU series handhelds
TODO:
- WIP
***************************************************************************/
#include "emu.h"
#include "cpu/pps41/mm76.h"
#include "video/pwm.h"
#include "sound/spkrdev.h"
#include "speaker.h"
// internal artwork
//#include "mastmind.lh"
//#include "hh_pps41_test.lh" // common test-layout - use external artwork
class hh_pps41_state : public driver_device
{
public:
hh_pps41_state(const machine_config &mconfig, device_type type, const char *tag) :
driver_device(mconfig, type, tag),
m_maincpu(*this, "maincpu"),
m_display(*this, "display"),
m_speaker(*this, "speaker"),
m_inputs(*this, "IN.%u", 0)
{ }
// devices
required_device<pps41_base_device> m_maincpu;
optional_device<pwm_display_device> m_display;
optional_device<speaker_sound_device> m_speaker;
optional_ioport_array<8> m_inputs; // max 8
u16 m_inp_mux = 0;
// MCU output pin state
//..
u8 read_inputs(int columns);
protected:
virtual void machine_start() override;
virtual void machine_reset() override;
};
// machine start/reset
void hh_pps41_state::machine_start()
{
// register for savestates
save_item(NAME(m_inp_mux));
}
void hh_pps41_state::machine_reset()
{
}
/***************************************************************************
Helper Functions
***************************************************************************/
// generic input handlers
u8 hh_pps41_state::read_inputs(int columns)
{
u8 ret = 0;
// read selected input rows
for (int i = 0; i < columns; i++)
if (m_inp_mux >> i & 1)
ret |= m_inputs[i]->read();
return ret;
}
/***************************************************************************
Minidrivers (subclass, I/O, Inputs, Machine Config, ROM Defs)
***************************************************************************/
namespace {
/***************************************************************************
Invicta Electronic Master Mind
* x
Invicta is the owner of the Mastermind game rights. The back of the unit
says (C) 1977, but this electronic handheld version came out in 1979.
***************************************************************************/
class mastmind_state : public hh_pps41_state
{
public:
mastmind_state(const machine_config &mconfig, device_type type, const char *tag) :
hh_pps41_state(mconfig, type, tag)
{ }
void mastmind(machine_config &config);
};
// handlers
// config
static INPUT_PORTS_START( mastmind )
INPUT_PORTS_END
void mastmind_state::mastmind(machine_config &config)
{
/* basic machine hardware */
MM76(config, m_maincpu, 100000); // approximation
/* video hardware */
PWM_DISPLAY(config, m_display).set_size(4, 8);
m_display->set_segmask(3, 0xff);
//config.set_default_layout(layout_mastmind);
/* no sound! */
}
// roms
ROM_START( mastmind )
ROM_REGION( 0x0400, "maincpu", ROMREGION_ERASE00 )
ROM_LOAD( "mm75_a7525-11", 0x0000, 0x0200, BAD_DUMP CRC(d144ee6b) SHA1(1e0b521b1e79f94377780470a52e22ee2deaf1d4) ) // wrong byte/bit ordering
ROM_CONTINUE( 0x0380, 0x0080 )
ROM_REGION( 100, "maincpu:opla", 0 )
ROM_LOAD( "mm76_mastmind_output.pla", 0, 100, NO_DUMP ) // that's a lie
ROM_END
} // anonymous namespace
/***************************************************************************
Game driver(s)
***************************************************************************/
// YEAR NAME PARENT CMP MACHINE INPUT CLASS INIT COMPANY, FULLNAME, FLAGS
CONS( 1979, mastmind, 0, 0, mastmind, mastmind, mastmind_state, empty_init, "Invicta Plastics", "Electronic Master Mind (Invicta)", MACHINE_SUPPORTS_SAVE | MACHINE_NO_SOUND_HW | MACHINE_NOT_WORKING )

View File

@ -227,8 +227,8 @@ namespace {
This is Bambino's first game, it is not known if ET-01 exists. Emix Corp.
wasn't initially a toy company, the first release was through Tomy. Emix
created the Bambino brand afterwards. It is claimed to be the first
computerized VFD game (true, unless TI Speak & Spell(1978), or even Invicta
Electronic Mastermind(1977) are considered games)
computerized VFD game (true, unless TI Speak & Spell or M.E.M. Memoquiz
from 1978 are considered VFD games)
known releases:
- Japan: "Missile Guerilla Warfare Maneuvers", published by Tomy

View File

@ -10,7 +10,7 @@ license:CC0
<element name="led" defstate="0">
<disk state="0"><color red="0.0" green="0.0" blue="0.0" /></disk>
<disk state="1"><color red="1.0" green="0.5" blue="0.3" /></disk>
<disk state="1"><color red="0.5" green="1.0" blue="1.0" /></disk>
</element>

View File

@ -0,0 +1,37 @@
<?xml version="1.0"?>
<!--
license:CC0
-->
<mamelayout version="2">
<!-- define elements -->
<element name="static_black"><rect><color red="0.0" green="0.0" blue="0.0" /></rect></element>
<element name="led" defstate="0">
<disk state="0"><color red="0.0" green="0.0" blue="0.0" /></disk>
<disk state="1"><color red="0.5" green="1.0" blue="1.0" /></disk>
</element>
<!-- build screen -->
<view name="Test Layout">
<bounds left="0" right="32" top="0" bottom="16" />
<element ref="static_black">
<bounds left="0" right="32" top="0" bottom="16" />
</element>
<!-- max 16*32 matrix -->
<repeat count="16">
<param name="y" start="0" increment="1" />
<repeat count="32">
<param name="x" start="0" increment="1" />
<element name="~y~.~x~" ref="led"><bounds x="~x~" y="~y~" width="0.5" height="0.5" /></element>
</repeat>
</repeat>
</view>
</mamelayout>

View File

@ -10,7 +10,7 @@ license:CC0
<element name="led" defstate="0">
<disk state="0"><color red="0.0" green="0.0" blue="0.0" /></disk>
<disk state="1"><color red="0.3" green="1.0" blue="0.3" /></disk>
<disk state="1"><color red="0.5" green="1.0" blue="1.0" /></disk>
</element>

View File

@ -16162,6 +16162,9 @@ ttfballa // Toytronic
us2pfball // US Games
uspbball // US Games
@source:hh_pps41.cpp
mastmind // Invicta
@source:hh_sm510.cpp
auslalom // Elektronika
bassmate // Telko

View File

@ -390,6 +390,7 @@ hh_cops1.cpp
hh_hmcs40.cpp
hh_melps4.cpp
hh_pic16.cpp
hh_pps41.cpp
hh_sm510.cpp
hh_tms1k.cpp
hh_ucom4.cpp

View File

@ -131,6 +131,7 @@ using util::BIT;
#include "cpu/pic17/pic17d.h"
#include "cpu/powerpc/ppc_dasm.h"
#include "cpu/pps4/pps4dasm.h"
#include "cpu/pps41/pps41d.h"
#include "cpu/psx/psxdasm.h"
#include "cpu/rii/riidasm.h"
#include "cpu/romp/rompdasm.h"
@ -498,6 +499,7 @@ static const dasm_table_entry dasm_table[] =
{ "mips3be", be, 0, []() -> util::disasm_interface * { return new mips3_disassembler; } },
{ "mips3le", le, 0, []() -> util::disasm_interface * { return new mips3_disassembler; } },
{ "mm5799", le, 0, []() -> util::disasm_interface * { return new mm5799_disassembler; } },
{ "mm76", le, 0, []() -> util::disasm_interface * { return new mm76_disassembler; } },
{ "mn10200", le, 0, []() -> util::disasm_interface * { return new mn10200_disassembler; } },
{ "mn1870", be, 0, []() -> util::disasm_interface * { return new mn1870_disassembler; } },
{ "mn1880", be, 0, []() -> util::disasm_interface * { return new mn1880_disassembler; } },