diff options
author | 2021-03-05 20:20:33 +0100 | |
---|---|---|
committer | 2021-03-05 20:20:46 +0100 | |
commit | 9a79ec0a50cf1827228b741cea445f5f795a6969 (patch) | |
tree | adc23d530b1943c36e6d07de9c307b2cb88640d1 | |
parent | f9e493cc6a67ee959fc59748beaa6f544ad5e577 (diff) |
pps41: added most of the mm76 opcodes except for i/o
-rw-r--r-- | src/devices/cpu/pps41/mm76.cpp | 83 | ||||
-rw-r--r-- | src/devices/cpu/pps41/mm76.h | 60 | ||||
-rw-r--r-- | src/devices/cpu/pps41/mm76op.cpp | 353 | ||||
-rw-r--r-- | src/devices/cpu/pps41/pps41base.cpp | 27 | ||||
-rw-r--r-- | src/devices/cpu/pps41/pps41base.h | 14 | ||||
-rw-r--r-- | src/mame/drivers/hh_tms1k.cpp | 3 |
6 files changed, 526 insertions, 14 deletions
diff --git a/src/devices/cpu/pps41/mm76.cpp b/src/devices/cpu/pps41/mm76.cpp index 2981467c0ac..3af749c62ce 100644 --- a/src/devices/cpu/pps41/mm76.cpp +++ b/src/devices/cpu/pps41/mm76.cpp @@ -59,7 +59,7 @@ void mm76e_device::program_1k(address_map &map) void mm76_device::data_48x4(address_map &map) { - map(0x00, 0x2f).ram(); + //map(0x00, 0x2f).ram(); } @@ -97,5 +97,84 @@ void mm76_device::device_reset() void mm76_device::execute_one() { - op_nop(); + if (op_is_tr(m_prev_op)) + { + switch (m_op & 0xf0) + { + case 0x20: op_skbei(); break; + case 0x60: op_skaei(); break; + + case 0x80: case 0x90: case 0xa0: case 0xb0: op_tml(); break; + case 0xc0: case 0xd0: case 0xe0: case 0xf0: op_tl(); break; + + default: op_illegal(); break; + } + } + else + { + switch (m_op & 0xf0) + { + case 0x20: op_lb(); break; + case 0x30: op_tr(); break; + case 0x60: op_aisk(); break; + case 0x70: op_lai(); break; + + case 0x80: case 0x90: case 0xa0: case 0xb0: op_tm(); break; + case 0xc0: case 0xd0: case 0xe0: case 0xf0: op_t(); break; + + default: + switch (m_op & 0xfc) + { + case 0x08: op_skbf(); break; + case 0x10: op_sb(); break; + case 0x14: op_rb(); break; + case 0x1c: op_eob(); break; + case 0x50: op_l(); break; + case 0x54: op_xnsk(); break; + case 0x58: op_x(); break; + case 0x5c: op_xdsk(); break; + + default: + switch (m_op) + { + case 0x00: op_nop(); break; + case 0x01: op_sknc(); break; + case 0x02: op_rt(); break; + case 0x03: op_rtsk(); break; + case 0x04: op_int0l(); break; + case 0x05: op_int1h(); break; + case 0x06: op_din1(); break; + case 0x07: op_din0(); break; + case 0x0c: op_sc(); break; + case 0x0d: op_rc(); break; + case 0x0e: op_seg1(); break; + case 0x0f: op_seg2(); break; + + case 0x18: op_oa(); break; + case 0x19: op_ob(); break; + case 0x1a: op_iam(); break; + case 0x1b: op_ibm(); break; + + case 0x40: op_ac(); break; + case 0x41: op_acsk(); break; + case 0x42: op_a(); break; + case 0x43: op_ask(); break; + case 0x44: op_lba(); break; + case 0x45: op_com(); break; + case 0x46: op_xab(); break; + case 0x47: op_skmea(); break; + case 0x4a: op_i1(); break; + case 0x4b: op_i2c(); break; + case 0x4c: op_lsa(); break; + case 0x4d: op_ios(); break; + case 0x4e: op_xas(); break; + + default: op_illegal(); break; + } + break; // 0xff + + } + break; // 0xfc + } + } } diff --git a/src/devices/cpu/pps41/mm76.h b/src/devices/cpu/pps41/mm76.h index 2bc3c7af670..bbad09218b5 100644 --- a/src/devices/cpu/pps41/mm76.h +++ b/src/devices/cpu/pps41/mm76.h @@ -68,13 +68,69 @@ protected: void ram_w(u8 data); void pop_pc(); void push_pc(); + void op_tr(); void op_illegal(); + void op_todo(); - virtual bool op_is_prefix(u8 op) override { return (op & 0xf0) == 0x30; }; + virtual bool op_is_tr(u8 op) override { return (op & 0xf0) == 0x30; }; + virtual bool op_is_eob(u8 op) { return (op & 0xfc) == 0x1c; }; + virtual bool op_is_lb(u8 op) { return (op & 0xf0) == 0x20; }; + virtual bool op_is_lai(u8 op) { return (op & 0xf0) == 0x70; }; // opcode handlers - void op_nop(); + virtual void op_xab(); + virtual void op_lba(); + virtual void op_lb(); + virtual void op_eob(); + + virtual void op_sb(); + virtual void op_rb(); + virtual void op_skbf(); + + virtual void op_xas(); + virtual void op_lsa(); + + virtual void op_l(); + virtual void op_x(); + virtual void op_xdsk(); + virtual void op_xnsk(); + + virtual void op_a(); + virtual void op_ac(); + virtual void op_acsk(); + virtual void op_ask(); + virtual void op_com(); + virtual void op_rc(); + virtual void op_sc(); + virtual void op_sknc(); + virtual void op_lai(); + virtual void op_aisk(); + + virtual void op_rt(); + virtual void op_rtsk(); + virtual void op_t(); + virtual void op_tl(); + virtual void op_tm(); + virtual void op_tml(); + virtual void op_nop(); + + virtual void op_skmea(); + virtual void op_skbei(); + virtual void op_skaei(); + + virtual void op_ibm(); + virtual void op_ob(); + virtual void op_iam(); + virtual void op_oa(); virtual void op_ios(); + virtual void op_i1(); + virtual void op_i2c(); + virtual void op_int1h(); + virtual void op_din1(); + virtual void op_int0l(); + virtual void op_din0(); + virtual void op_seg1(); + virtual void op_seg2(); }; class mm76l_device : public mm76_device diff --git a/src/devices/cpu/pps41/mm76op.cpp b/src/devices/cpu/pps41/mm76op.cpp index f0560fee9d8..fced467662c 100644 --- a/src/devices/cpu/pps41/mm76op.cpp +++ b/src/devices/cpu/pps41/mm76op.cpp @@ -11,12 +11,12 @@ inline u8 mm76_device::ram_r() { - return m_data->read_byte(m_b & m_datamask) & 0xf; + return m_data->read_byte(m_ram_addr & m_datamask) & 0xf; } inline void mm76_device::ram_w(u8 data) { - m_data->write_byte(m_b & m_datamask, data & 0xf); + m_data->write_byte(m_ram_addr & m_datamask, data & 0xf); } void mm76_device::pop_pc() @@ -33,18 +33,367 @@ void mm76_device::push_pc() m_stack[0] = m_pc; } +void mm76_device::op_tr() +{ + // TR x: prefix for extended opcode +} + void mm76_device::op_illegal() { logerror("unknown opcode $%02X at $%03X\n", m_op, m_prev_pc); } +void mm76_device::op_todo() +{ + logerror("unimplemented opcode $%02X at $%03X\n", m_op, m_prev_pc); +} + // opcodes +// RAM addressing instructions + +void mm76_device::op_xab() +{ + // XAB: exchange A with Bl + u8 a = m_a; + m_a = m_b & 0xf; + m_b = (m_b & ~0xf) | a; + m_ram_delay = true; +} + +void mm76_device::op_lba() +{ + // LBA: load Bl from A + m_b = (m_b & ~0xf) | m_a; + m_ram_delay = true; +} + +void mm76_device::op_lb() +{ + // LB x: load B from x (successive LB/EOB are ignored) + if (!(op_is_lb(m_prev_op) && !op_is_tr(m_prev2_op)) && !op_is_eob(m_prev_op)) + m_b = m_op & 0xf; +} + +void mm76_device::op_eob() +{ + // EOB x: XOR Bu with x (successive LB/EOB are ignored, except after first executed LB) + bool first_lb = (op_is_lb(m_prev_op) && !op_is_tr(m_prev2_op)) && !(op_is_lb(m_prev2_op) && !op_is_tr(m_prev3_op)) && !op_is_eob(m_prev2_op); + if ((!(op_is_lb(m_prev_op) && !op_is_tr(m_prev2_op)) && !op_is_eob(m_prev_op)) || first_lb) + m_b ^= m_op << 4 & m_datamask; +} + + +// bit manipulation instructions + +void mm76_device::op_sb() +{ + // Bu != 3: SB x: set memory bit + // Bu == 3: SOS: set output + op_todo(); +} + +void mm76_device::op_rb() +{ + // Bu != 3: RB x: reset memory bit + // Bu == 3: ROS: reset output + op_todo(); +} + +void mm76_device::op_skbf() +{ + // Bu != 3: SKBF x: test memory bit + // Bu == 3: SKISL: test input + op_todo(); +} + + +// register to register instructions + +void mm76_device::op_xas() +{ + // XAS: exchange A with S + u8 a = m_a; + m_a = m_s; + m_s = a; +} + +void mm76_device::op_lsa() +{ + // LSA: load S from A + m_s = m_a; +} + + +// register memory instructions + +void mm76_device::op_l() +{ + // L x: load A from memory, XOR Bu with x + m_a = ram_r(); + m_b ^= m_op << 4 & 0x30; +} + +void mm76_device::op_x() +{ + // X x: exchange A with memory, XOR Bu with x + u8 a = m_a; + m_a = ram_r(); + ram_w(a); + m_b ^= m_op << 4 & 0x30; +} + +void mm76_device::op_xdsk() +{ + // XDSK x: X x + decrement Bl + op_x(); + m_b = (m_b & ~0xf) | ((m_b - 1) & 0xf); + m_skip = (m_b & 0xf) == 0xf; + m_ram_delay = true; +} + +void mm76_device::op_xnsk() +{ + // XNSK x: X x + increment Bl + op_x(); + m_b = (m_b & ~0xf) | ((m_b + 1) & 0xf); + m_skip = (m_b & 0xf) == 0; + m_ram_delay = true; +} + + +// arithmetic instructions + +void mm76_device::op_a() +{ + // A: add memory to A + m_a = (m_a + ram_r()) & 0xf; +} + +void mm76_device::op_ac() +{ + // AC: add memory and carry to A + m_a += ram_r() + m_c_in; + m_c = m_a >> 4 & 1; + m_a &= 0xf; + m_c_delay = true; +} + +void mm76_device::op_acsk() +{ + // ACSK: AC + skip on no overflow + op_ac(); + m_skip = !m_c; +} + +void mm76_device::op_ask() +{ + // ASK: A + skip on no overflow + u8 a = m_a; + op_a(); + m_skip = m_a >= a; +} + +void mm76_device::op_com() +{ + // COM: complement A + m_a ^= 0xf; +} + +void mm76_device::op_rc() +{ + // RC: reset carry + m_c = 0; +} + +void mm76_device::op_sc() +{ + // SC: set carry + m_c = 1; +} + +void mm76_device::op_sknc() +{ + // SKNC: skip on no carry + m_skip = !m_c_in; +} + +void mm76_device::op_lai() +{ + // LAI x: load A from x (successive LAI are ignored) + if (!(op_is_lai(m_prev_op) && !op_is_tr(m_prev2_op))) + m_a = m_op & 0xf; +} + +void mm76_device::op_aisk() +{ + // AISK x: add x to A, skip on no overflow + m_a += m_op & 0xf; + m_skip = !(m_a & 0x10); + m_a &= 0xf; +} + + +// ROM addressing instructions + +void mm76_device::op_rt() +{ + // RT: return from subroutine + cycle(); + pop_pc(); +} + +void mm76_device::op_rtsk() +{ + // RTSK: RT + skip next instruction + op_rt(); + m_skip = true; +} + +void mm76_device::op_t() +{ + // T x: transfer on-page + cycle(); + + // jumps from subroutine pages reset page to SR1 + u16 mask = m_prgmask ^ 0x7f; + if ((m_pc & mask) == mask) + m_pc &= ~0x40; + + m_pc = (m_pc & ~0x3f) | (~m_op & 0x3f); +} + +void mm76_device::op_tl() +{ + // TL x: transfer long off-page + cycle(); + m_pc = (~m_prev_op & 0xf) << 6 | (~m_op & 0x3f); +} + +void mm76_device::op_tm() +{ + // TM x: transfer and mark to SR0 + cycle(); + + // calls from subroutine pages don't push PC + u16 mask = m_prgmask ^ 0x7f; + if ((m_pc & mask) != mask) + push_pc(); + + m_pc = ((~m_op & 0x3f) | ~0x3f) & m_prgmask; +} + +void mm76_device::op_tml() +{ + // TML x: transfer and mark long + cycle(); + push_pc(); + m_pc = (~m_prev_op & 0xf) << 6 | (~m_op & 0x3f); +} + void mm76_device::op_nop() { + // NOP: no operation +} + + +// logical comparison instructions + +void mm76_device::op_skmea() +{ + // SKMEA: skip on memory equals A + m_skip = m_a == ram_r(); +} + +void mm76_device::op_skbei() +{ + // SKBEI x: skip on Bl equals x + m_skip = (m_b & 0xf) == (m_op & 0xf); +} + +void mm76_device::op_skaei() +{ + // SKAEI x: skip on A equals X + m_skip = m_a == (~m_op & 0xf); +} + + +// input/output instructions + +void mm76_device::op_ibm() +{ + // IBM: input channel B to A +} + +void mm76_device::op_ob() +{ + // OB: output from A to channel B + op_todo(); +} + +void mm76_device::op_iam() +{ + // IAM: input channel A to A + op_todo(); +} + +void mm76_device::op_oa() +{ + // OA: output from A to channel A + op_todo(); } void mm76_device::op_ios() { + // IOS: start serial I/O + op_todo(); +} + +void mm76_device::op_i1() +{ + // I1: input channel 1 to A + op_todo(); +} + +void mm76_device::op_i2c() +{ + // I2C: input channel 2 to A + op_todo(); +} + +void mm76_device::op_int1h() +{ + // INT1H: skip on INT1 + op_todo(); +} + +void mm76_device::op_din1() +{ + // DIN1: test INT1 flip-flop + op_todo(); +} + +void mm76_device::op_int0l() +{ + // INT1H: skip on INT0 + op_todo(); +} + +void mm76_device::op_din0() +{ + // DIN0: test INT0 flip-flop + op_todo(); +} + +void mm76_device::op_seg1() +{ + // SEG1: output A+carry through PLA to channel A + op_todo(); +} + +void mm76_device::op_seg2() +{ + // SEG2: output A+carry through PLA to channel B + op_todo(); } diff --git a/src/devices/cpu/pps41/pps41base.cpp b/src/devices/cpu/pps41/pps41base.cpp index 2766fead2cf..4177c4c4841 100644 --- a/src/devices/cpu/pps41/pps41base.cpp +++ b/src/devices/cpu/pps41/pps41base.cpp @@ -48,7 +48,9 @@ pps41_base_device::pps41_base_device(const machine_config &mconfig, device_type m_data_config("data", ENDIANNESS_LITTLE, 8, datawidth, 0, data), m_prgwidth(prgwidth), m_datawidth(datawidth), - m_opla(*this, "opla") + m_opla(*this, "opla"), + m_read_r(*this), + m_write_r(*this) { } @@ -58,7 +60,7 @@ pps41_base_device::pps41_base_device(const machine_config &mconfig, device_type enum { - PPS41_PC=1, PPS41_A, PPS41_C, PPS41_B + PPS41_PC=1, PPS41_A, PPS41_C, PPS41_B, PPS41_S }; void pps41_base_device::device_start() @@ -69,7 +71,8 @@ void pps41_base_device::device_start() m_datamask = (1 << m_datawidth) - 1; // resolve callbacks - //.. + m_read_r.resolve_safe(0); + m_write_r.resolve_safe(); // zerofill m_pc = 0; @@ -77,6 +80,7 @@ void pps41_base_device::device_start() m_op = 0; m_prev_op = 0; m_prev2_op = 0; + m_prev3_op = 0; memset(m_stack, 0, sizeof(m_stack)); m_a = 0; @@ -90,15 +94,20 @@ void pps41_base_device::device_start() m_prev_c = 0; m_c_in = 0; m_c_delay = false; + m_s = 0; m_skip = false; m_skip_count = 0; + m_cha = 0; + m_chb = 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_prev3_op)); save_item(NAME(m_stack)); save_item(NAME(m_a)); @@ -112,9 +121,13 @@ void pps41_base_device::device_start() save_item(NAME(m_prev_c)); save_item(NAME(m_c_in)); save_item(NAME(m_c_delay)); + save_item(NAME(m_s)); save_item(NAME(m_skip)); save_item(NAME(m_skip_count)); + save_item(NAME(m_cha)); + save_item(NAME(m_chb)); + // 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(); @@ -123,6 +136,7 @@ void pps41_base_device::device_start() 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"); + state_add(PPS41_S, "S", m_s).formatstr("%01X"); set_icountptr(m_icount); } @@ -148,7 +162,8 @@ void pps41_base_device::device_reset() m_skip_count = 0; // clear outputs - //.. + m_cha = m_chb = 0xf; + m_write_r(0); } @@ -174,6 +189,7 @@ void pps41_base_device::execute_run() while (m_icount > 0) { // remember previous state + m_prev3_op = m_prev2_op; m_prev2_op = m_prev_op; m_prev_op = m_op; m_prev_pc = m_pc; @@ -193,7 +209,7 @@ void pps41_base_device::execute_run() if (m_skip) { // still skip through prefix(es) - m_skip = op_is_prefix(m_op); + m_skip = op_is_tr(m_op); m_op = 0; // fake nop } else if (m_skip_count) @@ -203,6 +219,7 @@ void pps41_base_device::execute_run() // restore opcode state m_op = m_prev_op; m_prev_op = m_prev2_op; + m_prev2_op = m_prev3_op; } else execute_one(); diff --git a/src/devices/cpu/pps41/pps41base.h b/src/devices/cpu/pps41/pps41base.h index 3f8459c8002..5157e53f417 100644 --- a/src/devices/cpu/pps41/pps41base.h +++ b/src/devices/cpu/pps41/pps41base.h @@ -20,7 +20,9 @@ public: // configuration helpers // I/O ports: - //.. + // 8-bit R I/O + auto read_r() { return m_read_r.bind(); } + auto write_r() { return m_write_r.bind(); } // set MCU mask options: @@ -59,7 +61,8 @@ protected: optional_device<pla_device> m_opla; // segment output PLA // i/o handlers - //.. + devcb_read8 m_read_r; + devcb_write8 m_write_r; // internal state, regs u16 m_pc; @@ -67,6 +70,7 @@ protected: u8 m_op; u8 m_prev_op; u8 m_prev2_op; + u8 m_prev3_op; int m_stack_levels; u16 m_stack[2]; // max 2 int m_d_pins; @@ -82,11 +86,15 @@ protected: int m_prev_c; int m_c_in; bool m_c_delay; + u8 m_s; bool m_skip; int m_skip_count; + u8 m_cha; + u8 m_chb; + // misc handlers - virtual bool op_is_prefix(u8 op) = 0; + virtual bool op_is_tr(u8 op) = 0; void cycle(); void increment_pc(); }; diff --git a/src/mame/drivers/hh_tms1k.cpp b/src/mame/drivers/hh_tms1k.cpp index 29a0382674c..360ce6434aa 100644 --- a/src/mame/drivers/hh_tms1k.cpp +++ b/src/mame/drivers/hh_tms1k.cpp @@ -11514,6 +11514,9 @@ ROM_END Tiger/Yeno also published an LCD handheld called Sub Wars, it's not related. + This handheld was modified and used as a prop in the 1981 movie Escape from + New York, Snake Plissken uses it as a homing device. + ***************************************************************************/ class subwars_state : public hh_tms1k_state |