pps41: added some mm78 opcodes (untested)

This commit is contained in:
hap 2021-03-08 17:12:55 +01:00
parent 82461369ff
commit 3d056bcb92
6 changed files with 278 additions and 9 deletions

View File

@ -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();

View File

@ -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];
}

View File

@ -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();
}

View File

@ -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

View File

@ -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];
}

View File

@ -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
*/