diff options
-rw-r--r-- | src/devices/cpu/pps41/mm76.h | 2 | ||||
-rw-r--r-- | src/devices/cpu/pps41/mm76op.cpp | 14 | ||||
-rw-r--r-- | src/devices/cpu/pps41/mm78.cpp | 107 | ||||
-rw-r--r-- | src/devices/cpu/pps41/mm78.h | 23 | ||||
-rw-r--r-- | src/devices/cpu/pps41/mm78op.cpp | 138 | ||||
-rw-r--r-- | src/devices/cpu/pps41/pps41base.cpp | 3 |
6 files changed, 278 insertions, 9 deletions
diff --git a/src/devices/cpu/pps41/mm76.h b/src/devices/cpu/pps41/mm76.h index bbad09218b5..82956e1829e 100644 --- a/src/devices/cpu/pps41/mm76.h +++ b/src/devices/cpu/pps41/mm76.h @@ -68,7 +68,6 @@ protected: void ram_w(u8 data); void pop_pc(); void push_pc(); - void op_tr(); void op_illegal(); void op_todo(); @@ -112,6 +111,7 @@ protected: virtual void op_tl(); virtual void op_tm(); virtual void op_tml(); + virtual void op_tr(); virtual void op_nop(); virtual void op_skmea(); diff --git a/src/devices/cpu/pps41/mm76op.cpp b/src/devices/cpu/pps41/mm76op.cpp index b95944cbd37..65748638f47 100644 --- a/src/devices/cpu/pps41/mm76op.cpp +++ b/src/devices/cpu/pps41/mm76op.cpp @@ -33,11 +33,6 @@ 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); @@ -352,6 +347,11 @@ void mm76_device::op_tml() m_pc = (~m_prev_op & 0xf) << 6 | (~m_op & 0x3f); } +void mm76_device::op_tr() +{ + // TR x: prefix for extended opcode +} + void mm76_device::op_nop() { // NOP: no operation @@ -427,7 +427,7 @@ void mm76_device::op_i2c() void mm76_device::op_int1h() { - // INT1H: skip on INT1 + // INT1H: skip on INT1 high m_skip = bool(m_int_line[1]); } @@ -440,7 +440,7 @@ void mm76_device::op_din1() void mm76_device::op_int0l() { - // INT0L: skip on INT0 + // INT0L: skip on INT0 low m_skip = !m_int_line[0]; } diff --git a/src/devices/cpu/pps41/mm78.cpp b/src/devices/cpu/pps41/mm78.cpp index 62a013e33d3..3657799e3b4 100644 --- a/src/devices/cpu/pps41/mm78.cpp +++ b/src/devices/cpu/pps41/mm78.cpp @@ -106,4 +106,111 @@ void mm78_device::device_reset() void mm78_device::execute_one() { + if (op_is_tr(m_prev_op) && op_is_tr(m_prev2_op)) + { + // 3-byte opcodes + switch (m_op & 0xf0) + { + case 0x80: case 0x90: case 0xa0: case 0xb0: op_tmlb(); break; + case 0xc0: case 0xd0: case 0xe0: case 0xf0: op_tlb(); break; + + default: op_illegal(); break; + } + } + else if (op_is_tr(m_prev_op)) + { + // 2-byte opcodes + switch (m_op & 0xf0) + { + case 0x30: op_tr(); break; + case 0x40: op_skbei(); break; + case 0x60: + if (m_op != 0x60) + op_skaei(); + else + op_illegal(); + 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 + { + // standard opcodes + switch (m_op & 0xf0) + { + case 0x10: op_lb(); break; + case 0x30: op_tr(); break; + case 0x40: op_lai(); break; + case 0x60: + if (m_op != 0x60) + op_aisk(); + else + op_i1sk(); + 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: case 0x0c: op_eob(); break; + case 0x20: op_sb(); break; + case 0x24: op_rb(); break; + case 0x28: op_skbf(); break; + case 0x50: op_l(); break; + case 0x54: op_xnsk(); break; + case 0x58: op_xdsk(); break; + case 0x5c: op_x(); break; + + default: + switch (m_op) + { + case 0x00: op_nop(); break; + case 0x01: op_skisl(); break; + case 0x02: op_sknc(); break; + case 0x03: op_int0h(); break; + case 0x04: op_int1l(); break; + case 0x05: op_rc(); break; + case 0x06: op_sc(); break; + case 0x07: op_sag(); break; + + case 0x2c: break; // TAB + case 0x2d: op_ios(); break; + case 0x2e: op_rtsk(); break; + case 0x2f: op_rt(); break; + + case 0x70: op_sos(); break; + case 0x71: op_ros(); break; + case 0x72: op_ix(); break; + case 0x73: op_ox(); break; + case 0x74: op_xas(); break; + case 0x75: op_lxa(); break; + case 0x76: op_lba(); break; + case 0x77: op_com(); break; + case 0x78: op_i2c(); break; + case 0x79: op_xax(); break; + case 0x7a: op_xab(); break; + case 0x7b: op_ioa(); break; + case 0x7c: op_ac(); break; + case 0x7d: op_acsk(); break; + case 0x7e: op_a(); break; + case 0x7f: op_skmea(); break; + + default: op_illegal(); break; // won't happen + } + break; // 0xff + + } + break; // 0xfc + } + } + + // TAB is delayed by 1 cycle + if (m_prev_op == 0x2c) + op_tab(); } diff --git a/src/devices/cpu/pps41/mm78.h b/src/devices/cpu/pps41/mm78.h index a2262bacdec..c09bee4a0d6 100644 --- a/src/devices/cpu/pps41/mm78.h +++ b/src/devices/cpu/pps41/mm78.h @@ -69,6 +69,29 @@ protected: virtual bool op_is_lai(u8 op) override { return (op & 0xf0) == 0x40; }; // opcode handlers + virtual void op_lba() override; + virtual void op_acsk() override; + virtual void op_aisk() override; + virtual void op_sb() override; + virtual void op_rb() override; + virtual void op_skbf() override; + + virtual void op_sos(); + virtual void op_ros(); + virtual void op_skisl(); + + virtual void op_sag(); + virtual void op_lxa(); + virtual void op_xax(); + virtual void op_tlb(); + virtual void op_tmlb(); + virtual void op_tab(); + virtual void op_ix(); + virtual void op_ox(); + virtual void op_ioa(); + virtual void op_i1sk(); + virtual void op_int0h(); + virtual void op_int1l(); }; class mm78l_device : public mm78_device diff --git a/src/devices/cpu/pps41/mm78op.cpp b/src/devices/cpu/pps41/mm78op.cpp index 35f9980b212..6b5ef774481 100644 --- a/src/devices/cpu/pps41/mm78op.cpp +++ b/src/devices/cpu/pps41/mm78op.cpp @@ -11,4 +11,142 @@ // changed opcodes +void mm78_device::op_lba() +{ + // LBA: no RAM delay + mm76_device::op_lba(); + m_ram_delay = false; +} + +void mm78_device::op_acsk() +{ + // ACSK: skip logic is inverted + mm76_device::op_acsk(); + m_skip = !m_skip; +} + +void mm78_device::op_aisk() +{ + // AISK x: don't skip if x=6 (aka DC opcode) + mm76_device::op_aisk(); + if ((m_op & 0xf) == 6) + m_skip = false; +} + +void mm78_device::op_sb() +{ + // SB x: SB/SOS opcodes are separated + ram_w(ram_r() | (1 << (m_op & 3))); +} + +void mm78_device::op_rb() +{ + // RB x: RB/ROS opcodes are separated + ram_w(ram_r() & ~(1 << (m_op & 3))); +} + +void mm78_device::op_skbf() +{ + // SKBF x: SKBF/SKISL opcodes are separated + m_skip = !BIT(ram_r(), m_op & 3); +} + +void mm78_device::op_sos() +{ + // SOS: SB/SOS opcodes are separated + op_todo(); +} + +void mm78_device::op_ros() +{ + // ROS: RB/ROS opcodes are separated + op_todo(); +} + +void mm78_device::op_skisl() +{ + // SKISL: SKBF/SKISL opcodes are separated + op_todo(); +} + + // new opcodes + +void mm78_device::op_sag() +{ + // SAG: set Bu to 3 for the next cycle + m_sag = true; +} + +void mm78_device::op_lxa() +{ + // LXA: load X from A + m_x = m_a; +} + +void mm78_device::op_xax() +{ + // XAX: exchange A with X + u8 a = m_a; + m_a = m_x; + m_x = a; +} + +void mm78_device::op_tlb() +{ + // TLB x: transfer long banked + op_tl(); + m_pc |= 0x400; +} + +void mm78_device::op_tmlb() +{ + // TMLB x: transfer and mark long banked + op_tml(); + m_pc |= 0x400; +} + +void mm78_device::op_tab() +{ + // TAB: table look up transfer + m_skip_count = m_a + 1; + m_a = 0xf; +} + +void mm78_device::op_ix() +{ + // IX: input to X from channel X(aka B) + op_todo(); +} + +void mm78_device::op_ox() +{ + // OX: output from X to channel X(aka B) + op_todo(); +} + +void mm78_device::op_ioa() +{ + // IOA: exchange A with channel A + op_todo(); +} + +void mm78_device::op_i1sk() +{ + // I1SK: add channel 1 to A, skip on no overflow + m_a += m_read_p() & 0xf; + m_skip = !(m_a & 0x10); + m_a &= 0xf; +} + +void mm78_device::op_int0h() +{ + // INT0H: skip on INT0 high + m_skip = bool(m_int_line[0]); +} + +void mm78_device::op_int1l() +{ + // INT1L: skip on INT1 low + m_skip = !m_int_line[1]; +} diff --git a/src/devices/cpu/pps41/pps41base.cpp b/src/devices/cpu/pps41/pps41base.cpp index 74352464aab..9fdc784c74b 100644 --- a/src/devices/cpu/pps41/pps41base.cpp +++ b/src/devices/cpu/pps41/pps41base.cpp @@ -38,9 +38,10 @@ TODO: but again does not explain why - documentation is conflicting whether or not MM76/MM75 can (re)set interrupt flip- flops with SOS/ROS opcodes +- allowed opcodes after TAB should be limited - add MCU mask options, there's one for inverting interrupts - add serial i/o -- add MM78 opcodes +- finish MM78 opcodes - add MM78LA */ |