mirror of
https://github.com/holub/mame
synced 2025-04-16 13:34:55 +03:00
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:
parent
1a0b950985
commit
2f02c96baf
@ -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
|
||||
|
@ -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
|
||||
|
@ -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")
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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()
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
};
|
||||
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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];
|
||||
|
@ -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))
|
||||
{ }
|
||||
|
||||
|
@ -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();
|
||||
};
|
||||
|
||||
|
||||
|
@ -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;
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
71
src/devices/cpu/pps41/mm76.cpp
Normal file
71
src/devices/cpu/pps41/mm76.cpp
Normal 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();
|
||||
}
|
59
src/devices/cpu/pps41/mm76.h
Normal file
59
src/devices/cpu/pps41/mm76.h
Normal 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
|
46
src/devices/cpu/pps41/mm76op.cpp
Normal file
46
src/devices/cpu/pps41/mm76op.cpp
Normal 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()
|
||||
{
|
||||
}
|
230
src/devices/cpu/pps41/pps41base.cpp
Normal file
230
src/devices/cpu/pps41/pps41base.cpp
Normal 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;
|
||||
}
|
||||
}
|
94
src/devices/cpu/pps41/pps41base.h
Normal file
94
src/devices/cpu/pps41/pps41base.h
Normal 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
|
141
src/devices/cpu/pps41/pps41d.cpp
Normal file
141
src/devices/cpu/pps41/pps41d.cpp
Normal 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 ¶ms)
|
||||
{
|
||||
// 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 ¶ms)
|
||||
{
|
||||
return common_disasm(mm76_opmap, stream, pc, opcodes, params);
|
||||
}
|
66
src/devices/cpu/pps41/pps41d.h
Normal file
66
src/devices/cpu/pps41/pps41d.h
Normal 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 ¶ms);
|
||||
};
|
||||
|
||||
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 ¶ms) override;
|
||||
|
||||
private:
|
||||
static const u8 mm76_opmap[0x100];
|
||||
|
||||
};
|
||||
|
||||
#endif // MAME_CPU_PPS41_PPS41D_H
|
@ -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();
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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()
|
||||
|
162
src/mame/drivers/hh_pps41.cpp
Normal file
162
src/mame/drivers/hh_pps41.cpp
Normal 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 )
|
@ -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
|
||||
|
@ -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>
|
||||
|
||||
|
||||
|
37
src/mame/layout/hh_pps41_test.lay
Normal file
37
src/mame/layout/hh_pps41_test.lay
Normal 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>
|
@ -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>
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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; } },
|
||||
|
Loading…
Reference in New Issue
Block a user