diff --git a/scripts/src/cpu.lua b/scripts/src/cpu.lua index 938501f73943a..0ca72a6b3d7dd 100644 --- a/scripts/src/cpu.lua +++ b/scripts/src/cpu.lua @@ -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 diff --git a/scripts/target/mame/arcade.lua b/scripts/target/mame/arcade.lua index 7d66cd65977f5..f63bb1b1226b0 100644 --- a/scripts/target/mame/arcade.lua +++ b/scripts/target/mame/arcade.lua @@ -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 diff --git a/scripts/target/mame/mess.lua b/scripts/target/mame/mess.lua index f81851af8ee23..841ee009defea 100644 --- a/scripts/target/mame/mess.lua +++ b/scripts/target/mame/mess.lua @@ -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") diff --git a/src/devices/cpu/amis2000/amis2000.cpp b/src/devices/cpu/amis2000/amis2000.cpp index 70df8370ae409..0558f5117dbe8 100644 --- a/src/devices/cpu/amis2000/amis2000.cpp +++ b/src/devices/cpu/amis2000/amis2000.cpp @@ -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; diff --git a/src/devices/cpu/amis2000/amis2000op.cpp b/src/devices/cpu/amis2000/amis2000op.cpp index 92c2eaae3dc3f..53c17f4bb4c4e 100644 --- a/src/devices/cpu/amis2000/amis2000op.cpp +++ b/src/devices/cpu/amis2000/amis2000op.cpp @@ -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() diff --git a/src/devices/cpu/cops1/cops1base.cpp b/src/devices/cpu/cops1/cops1base.cpp index 540724e61c259..713cde93a9cdc 100644 --- a/src/devices/cpu/cops1/cops1base.cpp +++ b/src/devices/cpu/cops1/cops1base.cpp @@ -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 @@ looks more like a complex state machine. #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(); diff --git a/src/devices/cpu/cops1/cops1base.h b/src/devices/cpu/cops1/cops1base.h index 485e120c6e851..b4ff862ebcc0b 100644 --- a/src/devices/cpu/cops1/cops1base.h +++ b/src/devices/cpu/cops1/cops1base.h @@ -64,7 +64,7 @@ class cops1_base_device : public cpu_device 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 @@ class cops1_base_device : public cpu_device 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 @@ class cops1_base_device : public cpu_device // 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(); }; diff --git a/src/devices/cpu/cops1/cops1d.cpp b/src/devices/cpu/cops1/cops1d.cpp index 0d20a0f03702d..60bab31a9f571 100644 --- a/src/devices/cpu/cops1/cops1d.cpp +++ b/src/devices/cpu/cops1/cops1d.cpp @@ -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); } diff --git a/src/devices/cpu/cops1/cops1d.h b/src/devices/cpu/cops1/cops1d.h index 4ebe663641254..d0491d8f04d58 100644 --- a/src/devices/cpu/cops1/cops1d.h +++ b/src/devices/cpu/cops1/cops1d.h @@ -39,8 +39,8 @@ class cops1_common_disassembler : public util::disasm_interface }; 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]; diff --git a/src/devices/cpu/cops1/mm5799.cpp b/src/devices/cpu/cops1/mm5799.cpp index 7ea0ce4a1ff12..85f6674806d86 100644 --- a/src/devices/cpu/cops1/mm5799.cpp +++ b/src/devices/cpu/cops1/mm5799.cpp @@ -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)) { } diff --git a/src/devices/cpu/cops1/mm5799.h b/src/devices/cpu/cops1/mm5799.h index d8f568e38087a..a07aecd97faaf 100644 --- a/src/devices/cpu/cops1/mm5799.h +++ b/src/devices/cpu/cops1/mm5799.h @@ -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 @@ class mm5799_device : public cops1_base_device 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(); }; diff --git a/src/devices/cpu/cops1/cops1op.cpp b/src/devices/cpu/cops1/mm5799op.cpp similarity index 75% rename from src/devices/cpu/cops1/cops1op.cpp rename to src/devices/cpu/cops1/mm5799op.cpp index c87821e7c11b3..180ae25701130 100644 --- a/src/devices/cpu/cops1/cops1op.cpp +++ b/src/devices/cpu/cops1/mm5799op.cpp @@ -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; diff --git a/src/devices/cpu/e0c6200/e0c6200.cpp b/src/devices/cpu/e0c6200/e0c6200.cpp index 0cd9f4ef2cb52..322401ed12145 100644 --- a/src/devices/cpu/e0c6200/e0c6200.cpp +++ b/src/devices/cpu/e0c6200/e0c6200.cpp @@ -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 diff --git a/src/devices/cpu/e0c6200/e0c6s46.cpp b/src/devices/cpu/e0c6200/e0c6s46.cpp index 5094c36a5f770..7c5b1196fb0b7 100644 --- a/src/devices/cpu/e0c6200/e0c6s46.cpp +++ b/src/devices/cpu/e0c6200/e0c6s46.cpp @@ -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; } } diff --git a/src/devices/cpu/hmcs40/hmcs40.cpp b/src/devices/cpu/hmcs40/hmcs40.cpp index 505856ef79c6c..ce4846e105bde 100644 --- a/src/devices/cpu/hmcs40/hmcs40.cpp +++ b/src/devices/cpu/hmcs40/hmcs40.cpp @@ -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); } diff --git a/src/devices/cpu/hmcs40/hmcs40op.cpp b/src/devices/cpu/hmcs40/hmcs40op.cpp index a0c6c6efb5cbf..d5251094ad7f3 100644 --- a/src/devices/cpu/hmcs40/hmcs40op.cpp +++ b/src/devices/cpu/hmcs40/hmcs40op.cpp @@ -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); } diff --git a/src/devices/cpu/melps4/melps4.cpp b/src/devices/cpu/melps4/melps4.cpp index e179c331de2df..e5903387823ed 100644 --- a/src/devices/cpu/melps4/melps4.cpp +++ b/src/devices/cpu/melps4/melps4.cpp @@ -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); diff --git a/src/devices/cpu/melps4/melps4op.cpp b/src/devices/cpu/melps4/melps4op.cpp index 755d5a10ef1a0..349f38047c2a0 100644 --- a/src/devices/cpu/melps4/melps4op.cpp +++ b/src/devices/cpu/melps4/melps4op.cpp @@ -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); } diff --git a/src/devices/cpu/pps41/mm76.cpp b/src/devices/cpu/pps41/mm76.cpp new file mode 100644 index 0000000000000..073d8406bbd9a --- /dev/null +++ b/src/devices/cpu/pps41/mm76.cpp @@ -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 mm76_device::create_disassembler() +{ + return std::make_unique(); +} + + +// 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(); +} diff --git a/src/devices/cpu/pps41/mm76.h b/src/devices/cpu/pps41/mm76.h new file mode 100644 index 0000000000000..8df0866f80a8d --- /dev/null +++ b/src/devices/cpu/pps41/mm76.h @@ -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 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 diff --git a/src/devices/cpu/pps41/mm76op.cpp b/src/devices/cpu/pps41/mm76op.cpp new file mode 100644 index 0000000000000..55b1980f8595f --- /dev/null +++ b/src/devices/cpu/pps41/mm76op.cpp @@ -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() +{ +} diff --git a/src/devices/cpu/pps41/pps41base.cpp b/src/devices/cpu/pps41/pps41base.cpp new file mode 100644 index 0000000000000..55cf0506171df --- /dev/null +++ b/src/devices/cpu/pps41/pps41base.cpp @@ -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; + } +} diff --git a/src/devices/cpu/pps41/pps41base.h b/src/devices/cpu/pps41/pps41base.h new file mode 100644 index 0000000000000..b8b42a44a78aa --- /dev/null +++ b/src/devices/cpu/pps41/pps41base.h @@ -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 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 diff --git a/src/devices/cpu/pps41/pps41d.cpp b/src/devices/cpu/pps41/pps41d.cpp new file mode 100644 index 0000000000000..8925bb82c71e7 --- /dev/null +++ b/src/devices/cpu/pps41/pps41d.cpp @@ -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); +} diff --git a/src/devices/cpu/pps41/pps41d.h b/src/devices/cpu/pps41/pps41d.h new file mode 100644 index 0000000000000..5e35adbd53bcd --- /dev/null +++ b/src/devices/cpu/pps41/pps41d.h @@ -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 diff --git a/src/devices/cpu/sm510/sm510base.cpp b/src/devices/cpu/sm510/sm510base.cpp index f5f0ae6bbb2ba..cca35da7730dd 100644 --- a/src/devices/cpu/sm510/sm510base.cpp +++ b/src/devices/cpu/sm510/sm510base.cpp @@ -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(); diff --git a/src/devices/cpu/sm510/sm510op.cpp b/src/devices/cpu/sm510/sm510op.cpp index 52516c16503c1..8570f6139b58e 100644 --- a/src/devices/cpu/sm510/sm510op.cpp +++ b/src/devices/cpu/sm510/sm510op.cpp @@ -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); } diff --git a/src/devices/cpu/sm510/sm511core.cpp b/src/devices/cpu/sm510/sm511core.cpp index 70df0cd1c0ecd..90de18142f733 100644 --- a/src/devices/cpu/sm510/sm511core.cpp +++ b/src/devices/cpu/sm510/sm511core.cpp @@ -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); } } diff --git a/src/devices/cpu/ucom4/ucom4.cpp b/src/devices/cpu/ucom4/ucom4.cpp index 3eab39eca70c5..8d98f1d2f942e 100644 --- a/src/devices/cpu/ucom4/ucom4.cpp +++ b/src/devices/cpu/ucom4/ucom4.cpp @@ -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); diff --git a/src/devices/cpu/ucom4/ucom4op.cpp b/src/devices/cpu/ucom4/ucom4op.cpp index 4facf3efb3bde..cecd08d800ea0 100644 --- a/src/devices/cpu/ucom4/ucom4op.cpp +++ b/src/devices/cpu/ucom4/ucom4op.cpp @@ -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() diff --git a/src/mame/drivers/hh_pps41.cpp b/src/mame/drivers/hh_pps41.cpp new file mode 100644 index 0000000000000..f3ef9ea653a9c --- /dev/null +++ b/src/mame/drivers/hh_pps41.cpp @@ -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 m_maincpu; + optional_device m_display; + optional_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 ) diff --git a/src/mame/drivers/hh_ucom4.cpp b/src/mame/drivers/hh_ucom4.cpp index c6c778bb9b38b..074bf619f55d8 100644 --- a/src/mame/drivers/hh_ucom4.cpp +++ b/src/mame/drivers/hh_ucom4.cpp @@ -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 diff --git a/src/mame/layout/hh_melps4_test.lay b/src/mame/layout/hh_melps4_test.lay index 4f1315c3b2912..d737d0126880d 100644 --- a/src/mame/layout/hh_melps4_test.lay +++ b/src/mame/layout/hh_melps4_test.lay @@ -10,7 +10,7 @@ license:CC0 - + diff --git a/src/mame/layout/hh_pps41_test.lay b/src/mame/layout/hh_pps41_test.lay new file mode 100644 index 0000000000000..d737d0126880d --- /dev/null +++ b/src/mame/layout/hh_pps41_test.lay @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/mame/layout/hh_ucom4_test.lay b/src/mame/layout/hh_ucom4_test.lay index af24003941d66..d737d0126880d 100644 --- a/src/mame/layout/hh_ucom4_test.lay +++ b/src/mame/layout/hh_ucom4_test.lay @@ -10,7 +10,7 @@ license:CC0 - + diff --git a/src/mame/mame.lst b/src/mame/mame.lst index 5f9bf1edf5e07..ffdee2746d834 100644 --- a/src/mame/mame.lst +++ b/src/mame/mame.lst @@ -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 diff --git a/src/mame/mess.flt b/src/mame/mess.flt index 168887afa47ee..801939fa2fed0 100644 --- a/src/mame/mess.flt +++ b/src/mame/mess.flt @@ -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 diff --git a/src/tools/unidasm.cpp b/src/tools/unidasm.cpp index 81a250c0ebf66..7bf28fec35ca2 100644 --- a/src/tools/unidasm.cpp +++ b/src/tools/unidasm.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; } },