mirror of
https://github.com/holub/mame
synced 2025-07-05 09:57:47 +03:00
pps41: added some mm78 opcodes (untested)
This commit is contained in:
parent
82461369ff
commit
3d056bcb92
@ -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();
|
||||
|
@ -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];
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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];
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user