summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/machine/i3002.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/machine/i3002.cpp')
-rw-r--r--src/devices/machine/i3002.cpp428
1 files changed, 428 insertions, 0 deletions
diff --git a/src/devices/machine/i3002.cpp b/src/devices/machine/i3002.cpp
new file mode 100644
index 00000000000..0abfff3eb45
--- /dev/null
+++ b/src/devices/machine/i3002.cpp
@@ -0,0 +1,428 @@
+// license:BSD-3-Clause
+// copyright-holders:F. Ulivi
+/**********************************************************************
+
+ i3002.cpp
+
+ Intel 3002 Central Processing Element
+
+**********************************************************************/
+
+#include "emu.h"
+#include "i3002.h"
+
+// Device type definition
+DEFINE_DEVICE_TYPE(I3002, i3002_device, "i3002", "Intel i3002 CPE")
+
+// Bit manipulation
+namespace {
+ template<typename T> constexpr T BIT_MASK(unsigned n)
+ {
+ return (T)1U << n;
+ }
+
+ template<typename T> void BIT_CLR(T& w , unsigned n)
+ {
+ w &= ~BIT_MASK<T>(n);
+ }
+
+ template<typename T> void BIT_SET(T& w , unsigned n)
+ {
+ w |= BIT_MASK<T>(n);
+ }
+}
+
+// Table to decode bits 0..3 of FC into RG and register index
+struct fc_fields {
+ uint8_t rg; // Register group [0..2] ("I" , "II" , "III" in Intel docs)
+ unsigned reg; // Register index
+};
+
+constexpr std::array<struct fc_fields , 16> fc_field_tab =
+ {{
+ { 0 , i3002_device::REG_R0 }, // 0000
+ { 0 , i3002_device::REG_R1 }, // 0001
+ { 0 , i3002_device::REG_R2 }, // 0010
+ { 0 , i3002_device::REG_R3 }, // 0011
+ { 0 , i3002_device::REG_R4 }, // 0100
+ { 0 , i3002_device::REG_R5 }, // 0101
+ { 0 , i3002_device::REG_R6 }, // 0110
+ { 0 , i3002_device::REG_R7 }, // 0111
+ { 0 , i3002_device::REG_R8 }, // 1000
+ { 0 , i3002_device::REG_R9 }, // 1001
+ { 1 , i3002_device::REG_T }, // 1010
+ { 1 , i3002_device::REG_AC }, // 1011
+ { 0 , i3002_device::REG_T }, // 1100
+ { 0 , i3002_device::REG_AC }, // 1101
+ { 2 , i3002_device::REG_T }, // 1110
+ { 2 , i3002_device::REG_AC } // 1111
+ }};
+
+// Register names
+static const std::array<const char* , i3002_device::REG_COUNT> reg_names =
+ {{
+ "R0",
+ "R1",
+ "R2",
+ "R3",
+ "R4",
+ "R5",
+ "R6",
+ "R7",
+ "R8",
+ "R9",
+ "T",
+ "AC",
+ "MAR"
+ }};
+
+i3002_device::i3002_device(const machine_config &mconfig , const char *tag , device_t *owner , uint32_t clock)
+ : device_t(mconfig , I3002 , tag , owner , clock)
+ , m_co_handler(*this)
+ , m_ro_handler(*this)
+ , m_ibus_handler(*this)
+ , m_mbus_handler(*this)
+{
+}
+
+const char *i3002_device::reg_name(unsigned reg_idx)
+{
+ return reg_names[ reg_idx ];
+}
+
+void i3002_device::decode_fc(uint8_t fc , uint8_t& fg , uint8_t& rg , unsigned& reg)
+{
+ // Function group
+ fg = (fc >> 4) & 7;
+
+ uint8_t lsn = fc & 0xf;
+
+ // Register & register group
+ rg = fc_field_tab[ lsn ].rg;
+ reg = fc_field_tab[ lsn ].reg;
+}
+
+void i3002_device::fc_kbus_w(uint8_t fc , uint8_t k)
+{
+ m_fc = fc & 0x7f;
+ m_kbus = k & WORD_MASK;
+}
+
+WRITE_LINE_MEMBER(i3002_device::clk_w)
+{
+ if (state) {
+ update();
+ }
+}
+
+bool i3002_device::update_ro()
+{
+ // Update RO output if doing a right-shift only
+ uint8_t fg;
+ uint8_t rg;
+ unsigned reg;
+
+ decode_fc(m_fc , fg , rg , reg);
+
+ if (fg == 0 && rg == 2) {
+ uint8_t ik = m_ibus_handler() & m_kbus;
+ uint8_t at = m_reg[ reg ];
+ set_ro(BIT(at , 0) && !BIT(ik , 0));
+ return true;
+ } else {
+ return false;
+ }
+}
+
+void i3002_device::device_start()
+{
+ m_co_handler.resolve_safe();
+ m_ro_handler.resolve_safe();
+ m_ibus_handler.resolve_safe(0);
+ m_mbus_handler.resolve_safe(0);
+
+ save_item(NAME(m_reg));
+ save_item(NAME(m_fc));
+ save_item(NAME(m_kbus));
+ save_item(NAME(m_ci));
+ save_item(NAME(m_li));
+ save_item(NAME(m_co));
+ save_item(NAME(m_ro));
+}
+
+void i3002_device::update()
+{
+ uint8_t fg;
+ uint8_t rg;
+ unsigned reg;
+
+ decode_fc(m_fc , fg , rg , reg);
+
+ switch (fg) {
+ case 0:
+ switch (rg) {
+ case 0:
+ // FC 0 RG I
+ {
+ uint8_t tmp = (m_reg[ REG_AC ] & m_kbus) + m_reg[ reg ] + m_ci;
+ m_reg[ REG_AC ] = m_reg[ reg ] = tmp & WORD_MASK;
+ set_co(BIT(tmp , SLICE_SIZE));
+ }
+ break;
+
+ case 1:
+ // FC 0 RG II
+ {
+ uint8_t m = m_mbus_handler() & WORD_MASK;
+ uint8_t tmp = (m_reg[ REG_AC ] & m_kbus) + m + m_ci;
+ m_reg[ reg ] = tmp & WORD_MASK;
+ set_co(BIT(tmp , SLICE_SIZE));
+ }
+ break;
+
+ case 2:
+ // FC 0 RG III
+ {
+ // Who designed this mess???
+ uint8_t ik = m_ibus_handler() & WORD_MASK & m_kbus;
+ uint8_t at = m_reg[ reg ];
+ m_reg[ reg ] = 0;
+ set_ro(BIT(at , 0) && !BIT(ik , 0));
+ if (m_li || (BIT(ik , 1) && BIT(at , 1))) {
+ BIT_SET(m_reg[ reg ] , 1);
+ }
+ if ((BIT(at , 0) && BIT(ik , 0)) || (BIT(at , 1) || BIT(ik , 1))) {
+ BIT_SET(m_reg[ reg ] , 0);
+ }
+ }
+ break;
+ }
+ break;
+
+ case 1:
+ switch (rg) {
+ case 0:
+ // FC 1 RG I
+ {
+ m_reg[ REG_MAR ] = m_kbus | m_reg[ reg ];
+ uint8_t tmp = m_reg[ reg ] + m_kbus + m_ci;
+ m_reg[ reg ] = tmp & WORD_MASK;
+ set_co(BIT(tmp , SLICE_SIZE));
+ }
+ break;
+
+ case 1:
+ // FC 1 RG II
+ {
+ uint8_t m = m_mbus_handler() & WORD_MASK;
+ m_reg[ REG_MAR ] = m_kbus | m;
+ uint8_t tmp = m + m_kbus + m_ci;
+ m_reg[ reg ] = tmp & WORD_MASK;
+ set_co(BIT(tmp , SLICE_SIZE));
+ }
+ break;
+
+ case 2:
+ // FC 1 RG III
+ {
+ uint8_t tmp = ((m_reg[ reg ] ^ WORD_MASK) | m_kbus) + (m_reg[ reg ] & m_kbus) + m_ci;
+ m_reg[ reg ] = tmp & WORD_MASK;
+ set_co(BIT(tmp , SLICE_SIZE));
+ }
+ break;
+ }
+ break;
+
+ case 2:
+ switch (rg) {
+ case 0:
+ case 1:
+ // FC 2 RG I
+ // FC 2 RG II
+ {
+ uint8_t tmp = (m_reg[ REG_AC ] & m_kbus) + WORD_MASK + m_ci;
+ m_reg[ reg ] = tmp & WORD_MASK;
+ set_co(BIT(tmp , SLICE_SIZE));
+ }
+ break;
+
+ case 2:
+ // FC 2 RG III
+ {
+ uint8_t i = m_ibus_handler() & WORD_MASK;
+ uint8_t tmp = (i & m_kbus) + WORD_MASK + m_ci;
+ m_reg[ reg ] = tmp & WORD_MASK;
+ set_co(BIT(tmp , SLICE_SIZE));
+ }
+ break;
+ }
+ break;
+
+ case 3:
+ switch (rg) {
+ case 0:
+ // FC 3 RG I
+ {
+ uint8_t tmp = (m_reg[ REG_AC ] & m_kbus) + m_reg[ reg ] + m_ci;
+ m_reg[ reg ] = tmp & WORD_MASK;
+ set_co(BIT(tmp , SLICE_SIZE));
+ }
+ break;
+
+ case 1:
+ // FC 3 RG II (== FC 0 RG II)
+ {
+ uint8_t m = m_mbus_handler() & WORD_MASK;
+ uint8_t tmp = (m_reg[ REG_AC ] & m_kbus) + m + m_ci;
+ m_reg[ reg ] = tmp & WORD_MASK;
+ set_co(BIT(tmp , SLICE_SIZE));
+ }
+ break;
+
+ case 2:
+ // FC 3 RG III
+ {
+ uint8_t i = m_ibus_handler() & WORD_MASK;
+ uint8_t tmp = (i & m_kbus) + m_reg[ reg ] + m_ci;
+ m_reg[ reg ] = tmp & WORD_MASK;
+ set_co(BIT(tmp , SLICE_SIZE));
+ }
+ break;
+ }
+ break;
+
+ case 4:
+ switch (rg) {
+ case 0:
+ // FC 4 RG I
+ {
+ uint8_t tmp = m_reg[ reg ] & m_reg[ REG_AC ] & m_kbus;
+ m_reg[ reg ] = tmp;
+ set_co(m_ci || tmp != 0);
+ }
+ break;
+
+ case 1:
+ // FC 4 RG II
+ {
+ uint8_t m = m_mbus_handler() & WORD_MASK;
+ uint8_t tmp = m & m_reg[ REG_AC ] & m_kbus;
+ m_reg[ reg ] = tmp;
+ set_co(m_ci || tmp != 0);
+ }
+ break;
+
+ case 2:
+ // FC 4 RG III
+ {
+ uint8_t i = m_ibus_handler() & WORD_MASK;
+ uint8_t tmp = i & m_reg[ reg ] & m_kbus;
+ m_reg[ reg ] = tmp;
+ set_co(m_ci || tmp != 0);
+ }
+ break;
+ }
+ break;
+
+ case 5:
+ switch (rg) {
+ case 0:
+ case 2:
+ // FC 5 RG I
+ // FC 5 RG III
+ {
+ uint8_t tmp = m_reg[ reg ] & m_kbus;
+ m_reg[ reg ] = tmp;
+ set_co(m_ci || tmp != 0);
+ }
+ break;
+
+ case 1:
+ // FC 5 RG II
+ {
+ uint8_t m = m_mbus_handler() & WORD_MASK;
+ uint8_t tmp = m & m_kbus;
+ m_reg[ reg ] = tmp;
+ set_co(m_ci || tmp != 0);
+ }
+ break;
+ }
+ break;
+
+ case 6:
+ switch (rg) {
+ case 0:
+ // FC 6 RG I
+ {
+ uint8_t tmp = m_reg[ REG_AC ] & m_kbus;
+ m_reg[ reg ] |= tmp;
+ set_co(m_ci || tmp != 0);
+ }
+ break;
+
+ case 1:
+ // FC 6 RG II
+ {
+ uint8_t m = m_mbus_handler() & WORD_MASK;
+ uint8_t tmp = m_reg[ REG_AC ] & m_kbus;
+ m_reg[ reg ] = m | tmp;
+ set_co(m_ci || tmp != 0);
+ }
+ break;
+
+ case 2:
+ // FC 6 RG III
+ {
+ uint8_t ik = m_ibus_handler() & WORD_MASK & m_kbus;
+ m_reg[ reg ] |= ik;
+ set_co(m_ci || ik != 0);
+ }
+ break;
+ }
+ break;
+
+ case 7:
+ switch (rg) {
+ case 0:
+ // FC 7 RG I
+ {
+ uint8_t tmp = m_reg[ REG_AC ] & m_kbus;
+ set_co(m_ci || (m_reg[ reg ] & tmp) != 0);
+ m_reg[ reg ] = m_reg[ reg ] ^ tmp ^ WORD_MASK;
+ }
+ break;
+
+ case 1:
+ // FC 7 RG II
+ {
+ uint8_t m = m_mbus_handler() & WORD_MASK;
+ uint8_t tmp = m_reg[ REG_AC ] & m_kbus;
+ set_co(m_ci || (m & tmp) != 0);
+ m_reg[ reg ] = m ^ tmp ^ WORD_MASK;
+ }
+ break;
+
+ case 2:
+ // FC 7 RG III
+ {
+ uint8_t ik = m_ibus_handler() & WORD_MASK & m_kbus;
+ set_co(m_ci || (m_reg[ reg ] & ik) != 0);
+ m_reg[ reg ] = m_reg[ reg ] ^ ik ^ WORD_MASK;
+ }
+ break;
+ }
+ break;
+ }
+}
+
+void i3002_device::set_co(bool co)
+{
+ m_co = co;
+ m_co_handler(m_co);
+}
+
+void i3002_device::set_ro(bool ro)
+{
+ m_ro = ro;
+ m_ro_handler(m_ro);
+}