summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/i8089/i8089_ops.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/i8089/i8089_ops.cpp')
-rw-r--r--src/devices/cpu/i8089/i8089_ops.cpp415
1 files changed, 415 insertions, 0 deletions
diff --git a/src/devices/cpu/i8089/i8089_ops.cpp b/src/devices/cpu/i8089/i8089_ops.cpp
new file mode 100644
index 00000000000..09c8f5cd037
--- /dev/null
+++ b/src/devices/cpu/i8089/i8089_ops.cpp
@@ -0,0 +1,415 @@
+// license:GPL-2.0+
+// copyright-holders:Dirk Best,Carl
+/***************************************************************************
+
+ Intel 8089 I/O Processor
+
+ Opcode implementations
+
+***************************************************************************/
+
+#include "emu.h"
+#include "i8089_channel.h"
+
+#define UNIMPLEMENTED logerror("%s('%s'): unimplemented opcode: %s\n", shortname(), tag(), __FUNCTION__);
+
+#define LWR(m, o) ((INT16)m_iop->read_word(m_r[m].t, o))
+#define LBR(m, o) ((INT8)m_iop->read_byte(m_r[m].t, o))
+#define SWR(m, o, d) (m_iop->write_word(m_r[m].t, o, d))
+#define SBR(m, o, d) (m_iop->write_byte(m_r[m].t, o, d))
+
+void i8089_channel::add_rm(int r, int m, int o)
+{
+ set_reg(r, m_r[r].w + LWR(m, o));
+}
+
+void i8089_channel::add_mr(int m, int r, int o)
+{
+ SWR(m, o, LWR(m, o) + m_r[r].w);
+}
+
+void i8089_channel::addb_rm(int r, int m, int o)
+{
+ set_reg(r, m_r[r].w + LBR(m, o));
+}
+
+void i8089_channel::addb_mr(int m, int r, int o)
+{
+ SBR(m, o, LBR(m, o) + m_r[r].w);
+}
+
+void i8089_channel::addbi_ri(int r, INT8 i)
+{
+ set_reg(r, m_r[r].w + i);
+}
+
+void i8089_channel::addbi_mi(int m, INT8 i, int o)
+{
+ SBR(m, o, LBR(m, o) + i);
+}
+
+void i8089_channel::addi_ri(int r, INT16 i)
+{
+ set_reg(r, m_r[r].w + i);
+}
+
+void i8089_channel::addi_mi(int m, INT16 i, int o)
+{
+ SWR(m, o, LWR(m, o) + i);
+}
+
+void i8089_channel::and_rm(int r, int m, int o)
+{
+ set_reg(r, m_r[r].w & LWR(m, o));
+}
+
+void i8089_channel::and_mr(int m, int r, int o)
+{
+ SWR(m, o, LWR(m, o) & m_r[r].w);
+}
+
+void i8089_channel::andb_rm(int r, int m, int o)
+{
+ set_reg(r, m_r[r].w & (INT16)LBR(m, o));
+}
+
+void i8089_channel::andb_mr(int m, int r, int o)
+{
+ SBR(m, o, LBR(m, o) & m_r[r].w);
+}
+
+void i8089_channel::andbi_ri(int r, INT8 i)
+{
+ set_reg(r, m_r[r].w & (INT16)i);
+}
+
+void i8089_channel::andbi_mi(int m, INT8 i, int o)
+{
+ SBR(m, o, LBR(m, o) & i);
+}
+
+void i8089_channel::andi_ri(int r, INT16 i)
+{
+ set_reg(r, m_r[r].w & i);
+}
+
+void i8089_channel::andi_mi(int m, INT16 i, int o)
+{
+ SWR(m, o, LWR(m, o) & i);
+}
+
+void i8089_channel::call(int m, INT16 d, int o)
+{
+ movp_mp(m, TP, o);
+ set_reg(TP, m_r[TP].w + d);
+}
+
+void i8089_channel::clr(int m, int b, int o)
+{
+ SBR(m, o, LBR(m, o) & ~(1<<b));
+}
+
+void i8089_channel::dec_r(int r)
+{
+ m_icount += 3;
+ set_reg(r, m_r[r].w - 1);
+}
+
+void i8089_channel::dec_m(int m, int o)
+{
+ SWR(m, o, LWR(m, o) - 1);
+}
+
+void i8089_channel::decb(int m, int o)
+{
+ SBR(m, o, LBR(m, o) - 1);
+}
+
+// halt
+void i8089_channel::hlt()
+{
+ movbi_mi(CP, 0x00, m_r[CP].w + 1);
+ m_r[PSW].w &= ~(1 << 2);
+ m_prio = PRIO_IDLE;
+}
+
+void i8089_channel::inc_r(int r)
+{
+ set_reg(r, m_r[r].w + 1);
+}
+
+void i8089_channel::inc_m(int m, int o)
+{
+ SWR(m, o, LWR(m, o) + 1);
+}
+
+void i8089_channel::incb(int m, int o)
+{
+ SBR(m, o, LBR(m, o) + 1);
+}
+
+void i8089_channel::jbt(int m, int b, INT16 d, int o)
+{
+ if(LBR(m, o) & (1<<b))
+ set_reg(TP, m_r[TP].w + d);
+}
+
+void i8089_channel::jmce(int m, INT16 d, int o)
+{
+ if(!((LBR(m, o) ^ (m_r[MC].w & 0xff)) & (m_r[MC].w >> 8)))
+ set_reg(TP, m_r[TP].w + d);
+}
+
+void i8089_channel::jmcne(int m, INT16 d, int o)
+{
+ if((LBR(m, o) ^ (m_r[MC].w & 0xff)) & (m_r[MC].w >> 8))
+ set_reg(TP, m_r[TP].w + d);
+}
+
+void i8089_channel::jnbt(int m, int b, INT16 d, int o)
+{
+ if(!(LBR(m, o) & (1<<b)))
+ set_reg(TP, m_r[TP].w + d);
+}
+
+void i8089_channel::jnz_r(int r, INT16 d)
+{
+ m_icount += 5;
+ if(m_r[r].w & 0xffff)
+ set_reg(TP, m_r[TP].w + d);
+}
+
+void i8089_channel::jnz_m(int m, INT16 d, int o)
+{
+ if(LWR(m, o))
+ set_reg(TP, m_r[TP].w + d);
+}
+
+void i8089_channel::jnzb(int m, INT16 d, int o)
+{
+ if(LBR(m, o))
+ set_reg(TP, m_r[TP].w + d);
+}
+
+void i8089_channel::jz_r(int r, INT16 d)
+{
+ if(!(m_r[r].w & 0xffff))
+ set_reg(TP, m_r[TP].w + d);
+}
+
+void i8089_channel::jz_m(int m, INT16 d, int o)
+{
+ if(!LWR(m, o))
+ set_reg(TP, m_r[TP].w + d);
+}
+
+void i8089_channel::jzb(int m, INT16 d, int o)
+{
+ if(!LBR(m, o))
+ set_reg(TP, m_r[TP].w + d);
+}
+
+
+// load pointer from memory
+void i8089_channel::lpd(int p, int m, int o)
+{
+ UINT16 offset = m_iop->read_word(m_r[m].t, o);
+ UINT16 segment = m_iop->read_word(m_r[m].t, o + 2);
+
+ set_reg(p, ((segment << 4) + offset) & 0xfffff, 0);
+}
+
+// load pointer from immediate data
+void i8089_channel::lpdi(int p, int s, int o)
+{
+ set_reg(p, (s << 4) + (o & 0xffff), 0);
+}
+
+void i8089_channel::mov_mr(int m, int r, int o)
+{
+ SWR(m, o, m_r[r].w);
+}
+
+void i8089_channel::mov_rm(int r, int m, int o)
+{
+ set_reg(r, (INT32)LWR(m, o), 1);
+}
+
+void i8089_channel::mov_mm(int m1, int m2, int o1, int o2)
+{
+ SWR(m2, o2, LWR(m1, o1));
+}
+
+// move register to memory byte
+void i8089_channel::movb_mr(int m, int r, int o)
+{
+ m_iop->write_byte(m_r[m].t, o, m_r[r].w & 0xff);
+}
+
+// move memory byte to register
+void i8089_channel::movb_rm(int r, int m, int o)
+{
+ UINT8 byte = m_iop->read_byte(m_r[m].t, o);
+ set_reg(r, (BIT(byte, 7) ? 0xfff00 : 0x00000) | byte, 1);
+}
+
+// move memory byte to memory byte
+void i8089_channel::movb_mm(int m1, int m2, int o1, int o2)
+{
+ UINT8 byte = m_iop->read_byte(m_r[m1].t, o1);
+ m_iop->write_byte(m_r[m2].t, o2, byte);
+}
+
+// move immediate byte to register
+void i8089_channel::movbi_ri(int r, INT8 i)
+{
+ set_reg(r, (BIT(i, 7) ? 0xfff00 : 0x00000) | (i & 0xff), 1);
+}
+
+// move immediate byte to memory byte
+void i8089_channel::movbi_mi(int m, INT8 i, int o)
+{
+ m_iop->write_byte(m_r[m].t, o, i & 0xff);
+}
+
+// move immediate word to register
+void i8089_channel::movi_ri(int r, INT16 i)
+{
+ set_reg(r, (BIT(i, 15) ? 0xf0000 : 0x00000) | (i & 0xffff), 1);
+}
+
+// move immediate word to memory word
+void i8089_channel::movi_mi(int m, INT16 i, int o)
+{
+ m_iop->write_word(m_r[m].t, o, (BIT(i, 15) ? 0xf0000 : 0x00000) | (i & 0xffff));
+}
+
+// move pointer to memory (store)
+void i8089_channel::movp_mp(int m, int p, int o)
+{
+ m_iop->write_word(m_r[m].t, o, m_r[p].w & 0xffff);
+ m_iop->write_byte(m_r[m].t, o + 2, ((m_r[p].w >> 12) & 0xf0) | (m_r[p].t << 3));
+}
+
+// move memory to pointer (restore)
+void i8089_channel::movp_pm(int p, int m, int o)
+{
+ UINT16 offset = m_iop->read_word(m_r[m].t, o);
+ UINT16 segment = m_iop->read_byte(m_r[m].t, o + 2);
+
+ set_reg(p, (((segment & 0xf0) << 12) + offset) & 0xfffff, segment >> 3 & 0x01);
+}
+
+// no operation
+void i8089_channel::nop()
+{
+}
+
+void i8089_channel::not_r(int r)
+{
+ set_reg(r, ~m_r[r].w);
+}
+
+void i8089_channel::not_m(int m, int o)
+{
+ SWR(m, o, ~LWR(m, o));
+}
+
+void i8089_channel::not_rm(int r, int m, int o)
+{
+ set_reg(r, ~(INT32)LWR(m, o));
+}
+
+void i8089_channel::notb_m(int m, int o)
+{
+ SBR(m, o, ~LBR(m, o));
+}
+
+void i8089_channel::notb_rm(int r, int m, int o)
+{
+ set_reg(r, ~(INT32)LBR(m, o));
+}
+
+void i8089_channel::or_rm(int r, int m, int o)
+{
+ set_reg(r, m_r[r].w | LWR(m, o));
+}
+
+void i8089_channel::or_mr(int m, int r, int o)
+{
+ SWR(m, o, LWR(m, o) | m_r[r].w);
+}
+
+void i8089_channel::orb_rm(int r, int m, int o)
+{
+ set_reg(r, m_r[r].w | (INT16)LBR(m, o));
+}
+
+void i8089_channel::orb_mr(int m, int r, int o)
+{
+ SBR(m, o, LBR(m, o) | m_r[r].w);
+}
+
+void i8089_channel::orbi_ri(int r, INT8 i)
+{
+ set_reg(r, m_r[r].w | (INT16)i);
+}
+
+void i8089_channel::orbi_mi(int m, INT8 i, int o)
+{
+ SBR(m, o, LBR(m, o) | i);
+}
+
+void i8089_channel::ori_ri(int r, INT16 i)
+{
+ set_reg(r, m_r[r].w | i);
+}
+
+void i8089_channel::ori_mi(int m, INT16 i, int o)
+{
+ SWR(m, o, LWR(m, o) | i);
+}
+
+void i8089_channel::setb(int m, int b, int o)
+{
+ SBR(m, o, LBR(m, o) | (1<<b));
+}
+
+
+// set interrupt service flip-flop
+void i8089_channel::sintr()
+{
+ if (BIT(m_r[PSW].w, 4))
+ {
+ m_r[PSW].w |= 1 << 5;
+ m_write_sintr(1);
+ }
+}
+
+void i8089_channel::tsl(int m, INT8 i, INT8 d, int o)
+{
+ if(LBR(m, o))
+ set_reg(TP, m_r[TP].w + d);
+ else
+ SBR(m, o, i);
+}
+
+
+// set source and destination logical widths
+void i8089_channel::wid(int s, int d)
+{
+ m_r[PSW].w &= 0x3f;
+ m_r[PSW].w |= d << 0;
+ m_r[PSW].w |= s << 1;
+}
+
+// enter dma transfer mode after next instruction
+void i8089_channel::xfer()
+{
+ m_xfer_pending = true;
+}
+
+void i8089_channel::invalid(int opc)
+{
+ logerror("%s('%s'): invalid opcode: %02x\n", shortname(), tag(), opc);
+}