summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/bcp/dp8344.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/bcp/dp8344.cpp')
-rw-r--r--src/devices/cpu/bcp/dp8344.cpp1201
1 files changed, 1016 insertions, 185 deletions
diff --git a/src/devices/cpu/bcp/dp8344.cpp b/src/devices/cpu/bcp/dp8344.cpp
index a1cd2fac1f1..3c37aa7f874 100644
--- a/src/devices/cpu/bcp/dp8344.cpp
+++ b/src/devices/cpu/bcp/dp8344.cpp
@@ -47,24 +47,25 @@
// GLOBAL VARIABLES
//**************************************************************************
-DEFINE_DEVICE_TYPE(DP8344, dp8344_device, "dp8344", "DP8344 BCP")
+// device type definitions
+DEFINE_DEVICE_TYPE(DP8344A, dp8344a_device, "dp8344a", "National Semiconductor DP8344A BCP")
+DEFINE_DEVICE_TYPE(DP8344B, dp8344b_device, "dp8344b", "National Semiconductor DP8344B BCP")
//**************************************************************************
// DEVICE CONSTRUCTION AND INITIALIZATION
//**************************************************************************
+ALLOW_SAVE_TYPE(dp8344_device::inst_state);
+
//-------------------------------------------------
// dp8344_device - constructor
//-------------------------------------------------
-dp8344_device::dp8344_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
- : cpu_device(mconfig, DP8344, tag, owner, clock)
+dp8344_device::dp8344_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock)
+ : cpu_device(mconfig, type, tag, owner, clock)
, m_inst_config("instruction", ENDIANNESS_LITTLE, 16, 16, -1)
, m_data_config("data", ENDIANNESS_LITTLE, 8, 16, 0)
- , m_inst_space(nullptr)
- , m_data_space(nullptr)
- , m_inst_cache(nullptr)
, m_birq_out_cb(*this)
, m_data_out_cb(*this)
, m_data_dly_cb(*this)
@@ -72,6 +73,9 @@ dp8344_device::dp8344_device(const machine_config &mconfig, const char *tag, dev
, m_pc(0)
, m_icount(0)
, m_nmi_pending(false)
+ , m_wait_states(0)
+ , m_source_data(0)
+ , m_data_address(0)
, m_ccr(0)
, m_ncf(0)
, m_icr(0)
@@ -86,8 +90,10 @@ dp8344_device::dp8344_device(const machine_config &mconfig, const char *tag, dev
, m_tmr(0)
, m_gp_main{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
, m_gp_alt{0, 0, 0, 0}
- , m_ir{{0}, {0}, {0}, {0}}
+ , m_ir{0, 0, 0, 0}
, m_tr(0)
+ , m_tclk(0)
+ , m_tcount(0)
, m_as{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
, m_ds{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
, m_asp(0)
@@ -103,37 +109,43 @@ dp8344_device::dp8344_device(const machine_config &mconfig, const char *tag, dev
, m_tfifo{0, 0, 0}
, m_rfifo_head(0)
, m_tfifo_head(0)
+ , m_receiver_interrupt(false)
{
}
//-------------------------------------------------
-// memory_space_config - return a vector of
-// configuration structures for memory spaces
+// dp8344a_device - constructor
//-------------------------------------------------
-device_memory_interface::space_config_vector dp8344_device::memory_space_config() const
+dp8344a_device::dp8344a_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : dp8344_device(mconfig, DP8344A, tag, owner, clock)
{
- return space_config_vector {
- std::make_pair(AS_PROGRAM, &m_inst_config),
- std::make_pair(AS_DATA, &m_data_config)
- };
}
//-------------------------------------------------
-// device_resolve_objects - resolve objects that
-// may be needed for other devices to set
-// initial conditions at start time
+// dp8344b_device - constructor
+//-------------------------------------------------
+
+dp8344b_device::dp8344b_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : dp8344_device(mconfig, DP8344B, tag, owner, clock)
+{
+ // TODO: emulate differences between DP8344A and DP8344B
+}
+
+
+//-------------------------------------------------
+// memory_space_config - return a vector of
+// configuration structures for memory spaces
//-------------------------------------------------
-void dp8344_device::device_resolve_objects()
+device_memory_interface::space_config_vector dp8344_device::memory_space_config() const
{
- // resolve output callbacks
- m_birq_out_cb.resolve_safe();
- m_data_out_cb.resolve_safe();
- m_data_dly_cb.resolve_safe();
- m_tx_act_cb.resolve_safe();
+ return space_config_vector {
+ std::make_pair(AS_PROGRAM, &m_inst_config),
+ std::make_pair(AS_DATA, &m_data_config)
+ };
}
@@ -144,17 +156,17 @@ void dp8344_device::device_resolve_objects()
void dp8344_device::device_start()
{
// get memory spaces
- m_inst_space = &space(AS_PROGRAM);
- m_data_space = &space(AS_DATA);
- m_inst_cache = m_inst_space->cache<1, -1, ENDIANNESS_LITTLE>();
+ space(AS_PROGRAM).cache(m_inst_cache);
+ space(AS_PROGRAM).specific(m_inst_space);
+ space(AS_DATA).specific(m_data_space);
set_icountptr(m_icount);
// debug state registration
- state_add(BCP_PC, "PC", m_pc);
+ state_add(BCP_PC, "PC", m_pc, [this](u16 data) { m_pc = m_ppc = data; prefetch_instruction(); });
state_add(STATE_GENPC, "GENPC", m_pc).noshow();
state_add(STATE_GENPCBASE, "GENPCBASE", m_pc).noshow();
- state_add(STATE_GENFLAGS, "GENFLAGS", m_ccr).noshow();
+ state_add(STATE_GENFLAGS, "GENFLAGS", m_ccr).formatstr("%09s").noshow();
state_add(BCP_BA, "BA", m_ba);
state_add(BCP_BB, "BB", m_bb);
state_add(BCP_CCR, "CCR", m_ccr);
@@ -175,18 +187,24 @@ void dp8344_device::device_start()
state_add(BCP_GP4_ALT + i, string_format("GP%da", 4 + i).c_str(), m_gp_alt[i]);
for (int i = 0; i < 4; i++)
{
- state_add(BCP_IW + i, string_format("I%c", 'W' + i).c_str(), m_ir[i].w);
- state_add(BCP_IWLO + i, string_format("I%cLO", 'W' + i).c_str(), m_ir[i].b.l).noshow();
- state_add(BCP_IWHI + i, string_format("I%cHI", 'W' + i).c_str(), m_ir[i].b.h).noshow();
+ state_add(BCP_IW + i, string_format("I%c", 'W' + i).c_str(), m_ir[i]);
+ state_add<u8>(BCP_IWLO + i, string_format("I%cLO", 'W' + i).c_str(),
+ [this, i]() -> u8 { return m_ir[i] & 0x00ff; },
+ [this, i](u8 data) { m_ir[i] = (m_ir[i] & 0xff00) | data; }).noshow();
+ state_add<u8>(BCP_IWHI + i, string_format("I%cHI", 'W' + i).c_str(),
+ [this, i]() -> u8 { return (m_ir[i] & 0xff00) >> 8; },
+ [this, i](u8 data) { m_ir[i] = (m_ir[i] & 0x00ff) | u16(data) << 8; }).noshow();
}
for (int i = 8; i < 16; i++)
state_add(BCP_GP8 + i - 8, string_format("GP%d", i).c_str(), m_gp_main[i]);
state_add(BCP_TR, "TR", m_tr);
+ state_add(BCP_COUNT, "COUNT", m_tcount);
state_add(BCP_ASP, "ASP", m_asp).mask(0xf);
state_add(BCP_DSP, "DSP", m_dsp).mask(0xf);
// save states
save_item(NAME(m_pc));
+ save_item(NAME(m_ppc));
save_item(NAME(m_nmi_state));
save_item(NAME(m_ccr));
save_item(NAME(m_ncf));
@@ -202,9 +220,10 @@ void dp8344_device::device_start()
save_item(NAME(m_tmr));
save_item(NAME(m_gp_main));
save_item(NAME(m_gp_alt));
- for (int i = 0; i < 4; i++)
- save_item(NAME(m_ir[i].w), i);
+ save_item(NAME(m_ir));
save_item(NAME(m_tr));
+ save_item(NAME(m_tclk));
+ save_item(NAME(m_tcount));
save_item(NAME(m_asp));
save_item(NAME(m_dsp));
save_item(NAME(m_as)); // 12-word Address Stack
@@ -215,10 +234,15 @@ void dp8344_device::device_start()
save_item(NAME(m_hib));
save_item(NAME(m_latched_instr));
save_item(NAME(m_nmi_pending));
+ save_item(NAME(m_inst_state));
+ save_item(NAME(m_wait_states));
+ save_item(NAME(m_source_data));
+ save_item(NAME(m_data_address));
save_item(NAME(m_rfifo)); // 3-frame Receive FIFO
save_item(NAME(m_tfifo)); // 3-frame Transmit FIFO
save_item(NAME(m_rfifo_head));
save_item(NAME(m_tfifo_head));
+ save_item(NAME(m_receiver_interrupt));
}
@@ -229,12 +253,12 @@ void dp8344_device::device_start()
void dp8344_device::device_reset()
{
// Reset Program Counter
- m_pc = 0x0000;
+ m_pc = m_ppc = 0x0000;
// Reset Condition Code Register
m_ccr &= 0x10;
- // Reset Interrupt Control Register
+ // Reset Interrupt Control Register (all interrupts masked out)
m_icr = 0xff;
// Reset Auxiliary Control Register and timer interrupt
@@ -264,8 +288,12 @@ void dp8344_device::device_reset()
// Reset Remote Interface Configuration Register
m_ric = m_auto_start ? 0x03 : 0x01;
m_hib = false;
+ if (!m_auto_start)
+ suspend(SUSPEND_REASON_HALT, true);
+ // Reset execution state
m_nmi_pending = false;
+ m_inst_state = T1_START;
transceiver_reset();
@@ -274,49 +302,21 @@ void dp8344_device::device_reset()
}
-//**************************************************************************
-// CONTROL REGISTERS AND CONDITION CODES
-//**************************************************************************
-
//-------------------------------------------------
-// get_flag - retrieve condition from CCR or TSR
+// create_disassembler - factory method for
+// disassembling program code
//-------------------------------------------------
-bool dp8344_device::get_flag(unsigned f) const
+std::unique_ptr<util::disasm_interface> dp8344_device::create_disassembler()
{
- switch (f)
- {
- case 0: // Zero/Equal
- return BIT(m_ccr, 0);
-
- case 1: // Carry
- return BIT(m_ccr, 1);
-
- case 2: // Overflow
- return BIT(m_ccr, 2);
-
- case 3: // Negative (or else Positive)
- return BIT(m_ccr, 3);
-
- case 4: // Receiver Active
- return BIT(m_tsr, 4);
-
- case 5: // Receiver Error
- return BIT(m_tsr, 5);
-
- case 6: // Data Available
- return BIT(m_tsr, 3); // FIXME: differs from numeric value!
-
- case 7: // Transmitter FIFO Full (or else Not Full)
- return BIT(m_tsr, 7);
-
- default:
- logerror("Unknown flag %d\n", f);
- return false;
- }
+ return std::make_unique<dp8344_disassembler>();
}
+//**************************************************************************
+// INTERRUPTS AND CONTROL REGISTERS
+//**************************************************************************
+
//-------------------------------------------------
// set_receiver_interrupt - update receiver
// interrupt request status
@@ -324,7 +324,7 @@ bool dp8344_device::get_flag(unsigned f) const
void dp8344_device::set_receiver_interrupt(bool state)
{
- // TODO
+ m_receiver_interrupt = state;
}
@@ -405,6 +405,10 @@ void dp8344_device::set_condition_code(u8 data)
}
+//-------------------------------------------------
+// set_interrupt_control - write to ICR
+//-------------------------------------------------
+
void dp8344_device::set_interrupt_control(u8 data)
{
// IM0: Receiver
@@ -462,26 +466,248 @@ void dp8344_device::set_auxiliary_control(u8 data)
// Clearing Timer StarT disables the timer and its interrupt
if (!BIT(data, 7) && BIT(m_acr, 7))
+ {
+ logerror("%04X: Timer Stop\n", m_ppc);
set_timer_interrupt(false);
+ }
+ else if (BIT(data, 7) && !BIT(m_acr, 7))
+ {
+ unsigned prescale = (BIT(m_dcr, 7) ? 2 : 1) * (BIT(data, 5) ? 2 : 16);
+ logerror("%04X: Timer Start (TO Period = %d Hz)\n",
+ m_ppc,
+ int(clocks_to_attotime(prescale * (m_tr == 0 ? 65536 : m_tr)).as_hz()));
+ }
+
+ if (BIT(data, 6))
+ {
+ logerror("%04X: Timer Load (TR = %d)\n", m_ppc, m_tr);
+ m_tcount = m_tr;
- // Bit 3 is reserved
+ // TODO: only cleared when load pulse finishes
+ data &= 0xbf;
+ }
+
+ // Bit 3 is reserved (TODO: DP8344B uses this to extend read cycles)
m_acr = data & 0xf7;
}
+//-------------------------------------------------
+// set_device_control - write to DCR
+//-------------------------------------------------
+
+void dp8344_device::set_device_control(u8 data)
+{
+ if ((data & 0xe0) != (m_dcr & 0xe0))
+ {
+ if ((data & 0x60) == 0x60)
+ logerror("%04X: CPU Clock = OCLK%s (%.4f MHz); Transceiver Clock = X-TCLK\n",
+ m_ppc,
+ BIT(data, 7) ? "/2" : "",
+ clocks_to_attotime(BIT(data, 7) ? 2 : 1).as_mhz());
+ else
+ logerror("%04X: CPU Clock = OCLK%s (%.4f MHz); Transceiver Clock = OCLK%s (%.4f MHz)\n",
+ m_ppc,
+ BIT(data, 7) ? "/2" : "",
+ clocks_to_attotime(BIT(data, 7) ? 2 : 1).as_mhz(),
+ BIT(data, 6) ? "/4" : BIT(data, 5) ? "/2" : "",
+ clocks_to_attotime(BIT(data, 6) ? 4 : BIT(data, 5) ? 2 : 1).as_mhz());
+ }
+
+ if ((data & 0x1f) != (m_dcr & 0x1f))
+ logerror("%04X: Wait States = %d (Instruction Memory), %d (Data Memory)\n",
+ m_ppc,
+ (data & 0x18) >> 3,
+ data & 0x07);
+
+ m_dcr = data;
+}
+
+
+//-------------------------------------------------
+// interrupt_active - determine if any of the
+// five maskable interrupts is active
+//-------------------------------------------------
+
+bool dp8344_device::interrupt_active() const
+{
+ // TODO: non-receiver, non-timer interrupts
+ return (!BIT(m_icr, 0) && m_receiver_interrupt) || (!BIT(m_icr, 4) && BIT(m_ccr, 7));
+}
+
+
+//-------------------------------------------------
+// get_interrupt_vector - return the vector for
+// the highest priority maskable interrupt
+//-------------------------------------------------
+
+u8 dp8344_device::get_interrupt_vector() const
+{
+ // TODO: non-receiver, non-timer interrupts
+ if (!BIT(m_icr, 0) && m_receiver_interrupt)
+ return 0x04;
+ else
+ return 0x14;
+}
+
+
+//**************************************************************************
+// CONDITION CODES AND ALU HELPERS
+//**************************************************************************
+
+//-------------------------------------------------
+// get_flag - retrieve condition from CCR or TSR
+//-------------------------------------------------
+
+bool dp8344_device::get_flag(unsigned f) const
+{
+ switch (f)
+ {
+ case 0: // Zero/Equal
+ return BIT(m_ccr, 0);
+
+ case 1: // Carry
+ return BIT(m_ccr, 1);
+
+ case 2: // Overflow
+ return BIT(m_ccr, 2);
+
+ case 3: // Negative (or else Positive)
+ return BIT(m_ccr, 3);
+
+ case 4: // Receiver Active
+ return BIT(m_tsr, 4);
+
+ case 5: // Receiver Error
+ return BIT(m_tsr, 5);
+
+ case 6: // Data Available (differs from DAV bit in TSR)
+ return m_rfifo_head < 3;
+
+ case 7: // Transmitter FIFO Full (or else Not Full)
+ return BIT(m_tsr, 7);
+
+ default:
+ logerror("Unknown flag %d\n", f);
+ return false;
+ }
+}
+
+
+//-------------------------------------------------
+// set_nz - set the N and Z flags based on the
+// result of an ALU operation
+//-------------------------------------------------
+
+void dp8344_device::set_nz(u8 result)
+{
+ m_ccr &= 0xf6;
+ if (result == 0)
+ m_ccr |= 0x01;
+ else if (BIT(result, 7))
+ m_ccr |= 0x08;
+}
+
+
+//-------------------------------------------------
+// set_carry - set or clear the C flag
+//-------------------------------------------------
+
+void dp8344_device::set_carry(bool state)
+{
+ if (state)
+ m_ccr |= 0x02;
+ else
+ m_ccr &= 0xfd;
+}
+
+
+//-------------------------------------------------
+// rotate_right - perform right rotation for ROT
+// and JRMK instructions
+//-------------------------------------------------
+
+u8 dp8344_device::rotate_right(u8 data, u8 b)
+{
+ return (data >> b) | (data << (8 - b));
+}
+
+
+//-------------------------------------------------
+// add_nzcv - add and set N, Z, C, V flags for
+// ADCA, ADD and ADDA instructions
+//-------------------------------------------------
+
+u8 dp8344_device::add_nzcv(u8 s1, u8 s2, bool carry_in)
+{
+ s16 result = s8(s1) + s8(s2) + (carry_in ? 1 : 0);
+ if (result >= 128 || result < -128)
+ m_ccr |= 0x04;
+ else
+ m_ccr &= 0xfb;
+
+ set_carry(s1 + s2 + (carry_in ? 1 : 0) >= 0x100);
+ set_nz(u8(result));
+ return u8(result);
+}
+
+
+//-------------------------------------------------
+// sub_nzcv - add and set N, Z, C, V flags for
+// CMP, SBCA, SUB and SUBA instructions
+//-------------------------------------------------
+
+u8 dp8344_device::sub_nzcv(u8 s1, u8 s2, bool carry_in)
+{
+ s16 result = s8(s1) - s8(s2) - (carry_in ? 1 : 0);
+ if (result >= 128 || result < -128)
+ m_ccr |= 0x04;
+ else
+ m_ccr &= 0xfb;
+
+ set_carry(s1 < s2 + (carry_in ? 1 : 0));
+ set_nz(u8(result));
+ return u8(result);
+}
+
+
+void dp8344_device::state_string_export(const device_state_entry &entry, std::string &str) const
+{
+ switch (entry.index())
+ {
+ case STATE_GENFLAGS:
+ str = string_format("%c%c%c%c %c%c%c%c",
+ BIT(m_ccr, 7) ? 'T' : '.', // TO
+ BIT(m_ccr, 6) ? 'R' : '.', // RR
+ BIT(m_ccr, 5) ? 'W' : '.', // RW
+ BIT(m_ccr, 4) ? 'B' : '.', // BIRQ
+ BIT(m_ccr, 3) ? 'N' : '.',
+ BIT(m_ccr, 2) ? 'V' : '.',
+ BIT(m_ccr, 1) ? 'C' : '.',
+ BIT(m_ccr, 0) ? 'Z' : '.');
+ break;
+ }
+}
+
+
//**************************************************************************
// 16-BIT TIMER
//**************************************************************************
//-------------------------------------------------
-// get_timer_count - return current count status
-// of the timer
+// timer_count - count down on timer
//-------------------------------------------------
-u16 dp8344_device::get_timer_count()
+void dp8344_device::timer_count()
{
- // TODO
- return 0;
+ // Count down to zero
+ if (--m_tcount == 0)
+ {
+ set_timer_interrupt(true);
+
+ // Count automatically reloads
+ m_tcount = m_tr;
+ }
}
@@ -498,8 +724,8 @@ void dp8344_device::address_stack_push()
{
m_as[m_asp++] = u32(m_pc)
| (u32(m_ccr & 0x0f) << 16)
- | (m_ba << 20)
- | (m_bb << 21)
+ | (m_ba << 21)
+ | (m_bb << 20)
| (u32(m_acr & 0x01) << 22);
if (m_asp >= 12)
m_asp = 0;
@@ -511,23 +737,23 @@ void dp8344_device::address_stack_push()
// executing a RET or RETF instruction
//-------------------------------------------------
-void dp8344_device::address_stack_pop(u8 grf)
+void dp8344_device::address_stack_pop(u8 g, bool rf)
{
m_asp = (m_asp == 0) ? 11 : m_asp - 1;
m_pc = m_as[m_asp] & 0xffff;
// Optionally restore, set or clear GIE
- if (BIT(grf, 6))
- set_gie(BIT(grf, 5));
- else if (BIT(grf, 5))
+ if (BIT(g, 1))
+ set_gie(!BIT(g, 0));
+ else if (BIT(g, 0))
set_gie(BIT(m_as[m_asp], 22));
// Optionally restore ALU flags and register banks
- if (BIT(grf, 4))
+ if (rf)
{
- m_ccr = (m_ccr & 0xf0) | (m_as[m_asp] & 0xf0000) >> 20;
- m_ba = BIT(m_as[m_asp], 20);
- m_bb = BIT(m_as[m_asp], 21);
+ m_ccr = (m_ccr & 0xf0) | (m_as[m_asp] & 0xf0000) >> 16;
+ m_ba = BIT(m_as[m_asp], 21);
+ m_bb = BIT(m_as[m_asp], 20);
}
}
@@ -561,17 +787,29 @@ void dp8344_device::data_stack_push(u8 data)
u8 dp8344_device::data_stack_pop()
{
+ // TBD: do test instructions (BIT, CMP, JRMK, etc.) suppress side effects as with RTR and ECR?
m_dsp = (m_dsp - 1) & 0xf;
return m_ds[m_dsp];
}
-
-
//**************************************************************************
// TRANSCEIVER OPERATION
//**************************************************************************
+const char *const dp8344_device::s_protocol_names[8] =
+{
+ "IBM 3270",
+ "IBM 3299 Multiplexer",
+ "IBM 3299 Controller",
+ "IBM 3299 Repeater",
+ "IBM 5250",
+ "IBM 5250 Promiscuous",
+ "8-bit",
+ "8-bit Promiscuous"
+};
+
+
//-------------------------------------------------
// transceiver_reset - reset the receiver and
// transmitter
@@ -610,6 +848,30 @@ void dp8344_device::transceiver_reset()
void dp8344_device::transmit_fifo_push(u8 data)
{
+ // HACK: loopback data
+ if (BIT(m_tmr, 6))
+ {
+ u16 frame = data | u16(m_tcr & 0x07) << 8;
+ if ((m_tmr & 0x07) == 0x00)
+ {
+ // Calculate odd parity on 3270 data frames
+ if (!BIT(m_tcr, 2))
+ {
+ if ((population_count_32(data) & 1) == 0)
+ frame |= 0x100;
+ else
+ frame &= 0x2ff;
+ }
+
+ // Calculate word parity
+ frame &= 0x3ff;
+ if ((population_count_32(frame) & 1) != BIT(m_tcr, 3))
+ frame |= 0x400;
+ }
+ receive_fifo_push(frame);
+ return;
+ }
+
// Push OWP, TF10-8 and RTF7-0 onto transmit FIFO
m_tfifo[0] = data | u16(m_tcr & 0x0f) << 8;
@@ -690,14 +952,43 @@ void dp8344_device::receiver_active()
//-------------------------------------------------
-// receive_fifo_push -
+// receive_fifo_push - push a data frame onto
+// the receive FIFO
//-------------------------------------------------
-void dp8344_device::receive_fifo_push(u8 data)
+void dp8344_device::receive_fifo_push(u16 data)
{
- // Overflow error if the receive FIFO is already full
- if (BIT(m_ncf, 6))
+ // Push word onto receive FIFO
+ m_rfifo[0] = data;
+
+ if (m_rfifo_head != 0)
+ {
+ // Asynchronously propagate data through FIFO (actually takes 40 ns)
+ m_rfifo_head--;
+ for (int i = 0; i < m_rfifo_head; i++)
+ m_rfifo[i + 1] = m_rfifo[i];
+
+ // Set data available flag
+ m_tsr |= 0x08;
+ if ((m_icr & 0xc0) == 0x40)
+ set_receiver_interrupt(true);
+
+ // Copy upper bits to TSR
+ m_tsr = (m_tsr & 0xf8) | (data & 0x700) >> 8;
+
+ // Set flag when FIFO is full
+ if (m_rfifo_head == 0)
+ {
+ m_tsr |= 0x40;
+ if ((m_icr & 0xc0) == 0x00)
+ set_receiver_interrupt(true);
+ }
+ }
+ else
+ {
+ // Overflow error if the receive FIFO is already full
set_receiver_error(0x10);
+ }
}
@@ -705,17 +996,34 @@ void dp8344_device::receive_fifo_push(u8 data)
// receive_fifo_pop - read from RTR
//-------------------------------------------------
-u8 dp8344_device::receive_fifo_pop()
+u8 dp8344_device::receive_fifo_pop(bool test)
{
- // Clear Receive FIFO Full, DEME, Auto-Response and Poll/Acknowledge bits in NCF
- m_ncf &= 0xb0;
+ u8 data = m_rfifo[m_rfifo_head < 3 ? m_rfifo_head : 2] & 0x0ff;
- // Clear Data Available flag in TSR
- m_tsr &= 0xf7;
- if ((m_icr & 0xc0) == 0xc0)
- set_receiver_interrupt(false);
+ if (!test)
+ {
+ if (m_rfifo_head < 3)
+ {
+ // Advance the FIFO
+ m_rfifo_head++;
- return 0;
+ // Copy upper bits to TSR
+ if (m_rfifo_head < 3)
+ m_tsr = (m_tsr & 0xf8) | (m_rfifo[m_rfifo_head] & 0x700) >> 8;
+ }
+
+ // Clear Data Available flag in TSR
+ m_tsr &= 0xf7;
+
+ // Clear Receive FIFO Full, DEME, Auto-Response and Poll/Acknowledge bits in NCF
+ m_ncf &= 0xb0;
+
+ // Clear receiver interrupt unless error interrupt exists
+ if (BIT(m_icr, 7) || !BIT(m_tsr, 5))
+ set_receiver_interrupt(false);
+ }
+
+ return data;
}
@@ -746,29 +1054,39 @@ void dp8344_device::set_receiver_error(u8 code)
// get_error_code - read from ECR
//-------------------------------------------------
-u8 dp8344_device::get_error_code()
+u8 dp8344_device::get_error_code(bool test)
{
u8 code = m_ecr;
- // Clear Error Code Register and Receiver Error flag in NCF
- m_ecr = 0x00;
- m_ncf &= 0xdf;
+ // Upper bits come from receive FIFO
+ code |= m_rfifo[m_rfifo_head < 3 ? m_rfifo_head : 2] & 0x0e0;
- // Update interrupt status if RE interrupt selected
- switch (m_icr & 0xc0)
+ if (!test)
{
- case 0x00:
- // Interrupt on RFF
- set_receiver_interrupt(BIT(m_ncf, 6));
- break;
+ // Clear Error Code Register and Receiver Error flag in NCF
+ m_ecr = 0x00;
+ m_ncf &= 0xdf;
- case 0x40:
- // Interrupt on DAV
- set_receiver_interrupt(BIT(m_tsr, 3));
- break;
+ // Reassert DAV if FIFO is not empty
+ if (m_rfifo_head < 3)
+ m_tsr |= 0x08;
- default:
- break;
+ // Update interrupt status if RE interrupt selected
+ switch (m_icr & 0xc0)
+ {
+ case 0x00:
+ // Interrupt on RFF
+ set_receiver_interrupt(BIT(m_ncf, 6));
+ break;
+
+ case 0x40:
+ // Interrupt on DAV
+ set_receiver_interrupt(BIT(m_tsr, 3));
+ break;
+
+ default:
+ break;
+ }
}
return code;
@@ -776,6 +1094,23 @@ u8 dp8344_device::get_error_code()
//-------------------------------------------------
+// set_transceiver_command - write to TCR
+//-------------------------------------------------
+
+void dp8344_device::set_transceiver_command(u8 data)
+{
+ if ((data & 0xb0) != (m_tcr & 0xb0))
+ logerror("%04X: Receiver Selected as %s with %d Quiesces; TX-ACT %sAdvanced\n",
+ m_ppc,
+ BIT(data, 5) ? "ALG" : "DATA-IN",
+ BIT(data, 7) ? 3 : 2,
+ BIT(data, 4) ? "" : "Not ");
+
+ m_tcr = data;
+}
+
+
+//-------------------------------------------------
// set_transceiver_mode - write to TMR
//-------------------------------------------------
@@ -789,40 +1124,8 @@ void dp8344_device::set_transceiver_mode(u8 data)
if (!BIT(m_tmr, 6) && BIT(data, 6))
m_tx_act_cb(0);
- switch (data & 0x07)
- {
- case 0:
- logerror("Protocol Select: IBM 3270\n");
- break;
-
- case 1:
- logerror("Protocol Select: IBM 3299 Multiplexer\n");
- break;
-
- case 2:
- logerror("Protocol Select: IBM 3299 Controller\n");
- break;
-
- case 3:
- logerror("Protocol Select: IBM 3299 Repeater\n");
- break;
-
- case 4:
- logerror("Protocol Select: IBM 5250\n");
- break;
-
- case 5:
- logerror("Protocol Select: IBM 5250 Promiscuous\n");
- break;
-
- case 6:
- logerror("Protocol Select: 8-bit\n");
- break;
-
- case 7:
- logerror("Protocol Select: 8-bit Promiscuous\n");
- break;
- }
+ if ((m_tmr & 0x07) != (data & 0x07))
+ logerror("%04X: Protocol Select: %s\n", m_ppc, s_protocol_names[data & 0x07]);
m_tmr = data;
}
@@ -851,7 +1154,7 @@ void dp8344_device::clear_network_command_flag(u8 data)
// read_register - read from source register
//-------------------------------------------------
-u8 dp8344_device::read_register(unsigned reg)
+u8 dp8344_device::read_register(unsigned reg, bool test)
{
switch (reg)
{
@@ -881,7 +1184,7 @@ u8 dp8344_device::read_register(unsigned reg)
case 4: // GP0 (main) or Receive/Transmit Register and/or Error Code Register (alternate)
if (m_bb)
- return BIT(m_tcr, 6) ? get_error_code() : receive_fifo_pop();
+ return BIT(m_tcr, 6) ? get_error_code(test) : receive_fifo_pop(test);
else
return m_gp_main[0];
@@ -928,28 +1231,28 @@ u8 dp8344_device::read_register(unsigned reg)
return m_gp_main[7];
case 12: // IW (low byte)
- return m_ir[0].b.l;
+ return m_ir[0] & 0x00ff;
case 13: // IW (high byte)
- return m_ir[0].b.h;
+ return (m_ir[0] & 0xff00) >> 8;
case 14: // IX (low byte)
- return m_ir[1].b.l;
+ return m_ir[1] & 0x00ff;
case 15: // IX (high byte)
- return m_ir[1].b.h;
+ return (m_ir[1] & 0xff00) >> 8;
case 16: // IY (low byte)
- return m_ir[2].b.l;
+ return m_ir[2] & 0x00ff;
case 17: // IY (high byte)
- return m_ir[2].b.h;
+ return (m_ir[2] & 0xff00) >> 8;
case 18: // IZ (low byte)
- return m_ir[3].b.l;
+ return m_ir[3] & 0x00ff;
case 19: // IZ (high byte)
- return m_ir[3].b.h;
+ return (m_ir[3] & 0xff00) >> 8;
case 20: // GP8
return m_gp_main[8];
@@ -976,10 +1279,10 @@ u8 dp8344_device::read_register(unsigned reg)
return m_gp_main[15];
case 28: // TRL count status
- return get_timer_count() & 0x00ff;
+ return m_tcount & 0x00ff;
case 29: // TRH count status
- return get_timer_count() >> 8;
+ return (m_tcount & 0xff00) >> 8;
case 30: // Internal Stack Pointer
return (m_asp << 4) | m_dsp;
@@ -1015,7 +1318,7 @@ void dp8344_device::write_register(unsigned reg, u8 data)
{
case 0: // Condition Code Register (main) or Device Control Register (alternate)
if (m_ba)
- m_dcr = data;
+ set_device_control(data);
else
set_condition_code(data);
break;
@@ -1053,10 +1356,11 @@ void dp8344_device::write_register(unsigned reg, u8 data)
logerror("Transceiver Status Register is read-only\n");
else
m_gp_main[1] = data;
+ break;
case 6: // GP2 (main) or Transceiver Command Register (alternate)
if (m_bb)
- m_tcr = data;
+ set_transceiver_command(data);
else
m_gp_main[2] = data;
break;
@@ -1097,35 +1401,35 @@ void dp8344_device::write_register(unsigned reg, u8 data)
break;
case 12: // IW (low byte)
- m_ir[0].b.l = data;
+ m_ir[0] = (m_ir[0] & 0xff00) | data;
break;
case 13: // IW (high byte)
- m_ir[0].b.h = data;
+ m_ir[0] = (m_ir[0] & 0x00ff) | u16(data) << 8;
break;
case 14: // IX (low byte)
- m_ir[1].b.l = data;
+ m_ir[1] = (m_ir[1] & 0xff00) | data;
break;
case 15: // IX (high byte)
- m_ir[1].b.h = data;
+ m_ir[1] = (m_ir[1] & 0x00ff) | u16(data) << 8;
break;
case 16: // IY (low byte)
- m_ir[2].b.l = data;
+ m_ir[2] = (m_ir[2] & 0xff00) | data;
break;
case 17: // IY (high byte)
- m_ir[2].b.h = data;
+ m_ir[2] = (m_ir[2] & 0x00ff) | u16(data) << 8;
break;
case 18: // IZ (low byte)
- m_ir[3].b.l = data;
+ m_ir[3] = (m_ir[3] & 0xff00) | data;
break;
case 19: // IZ (high byte)
- m_ir[3].b.h = data;
+ m_ir[3] = (m_ir[3] & 0x00ff) | u16(data) << 8;
break;
case 20: // GP8
@@ -1220,12 +1524,379 @@ void dp8344_device::execute_set_input(int irqline, int state)
//**************************************************************************
//-------------------------------------------------
-// create_disassembler -
+// prefetch_instruction - fetch the next
+// instruction word from program memory
//-------------------------------------------------
-std::unique_ptr<util::disasm_interface> dp8344_device::create_disassembler()
+void dp8344_device::prefetch_instruction()
{
- return std::make_unique<dp8344_disassembler>();
+ m_latched_instr = m_inst_cache.read_word(m_pc);
+}
+
+
+//-------------------------------------------------
+// latch_address - handle ALE cycle and set T2
+// wait states for instructions referencing data
+// memory
+//-------------------------------------------------
+
+void dp8344_device::latch_address(bool rw)
+{
+ //logerror("Latching data memory address %04Xh for %sing (PC = %04Xh)\n", m_data_address, rw ? "read" : "writ", m_pc);
+ if ((m_dcr & 0x18) == 0)
+ m_wait_states = m_dcr & 0x07;
+ else
+ m_wait_states = std::max(m_dcr & 0x07, ((m_dcr & 0x18) >> 3) - 1);
+}
+
+
+//-------------------------------------------------
+// instruction_wait - set T2 wait states for
+// non-memory instructions
+//-------------------------------------------------
+
+void dp8344_device::instruction_wait()
+{
+ m_wait_states = (m_dcr & 0x18) >> 3;
+}
+
+
+//-------------------------------------------------
+// decode_instruction - begin execution of an
+// opcode
+//-------------------------------------------------
+
+dp8344_device::inst_state dp8344_device::decode_instruction()
+{
+ if (m_latched_instr < 0x8000)
+ {
+ m_source_data = read_register(m_latched_instr & 0x000f, (m_latched_instr & 0x7000) == 0x3000);
+ if ((m_latched_instr & 0xf000) == 0x1000)
+ {
+ // MOVE to indexed data memory
+ m_data_address = m_ir[3] + ((m_latched_instr & 0x0ff0) >> 4);
+ return TX_WRITE;
+ }
+ else
+ {
+ instruction_wait();
+ return T2_STORE;
+ }
+ }
+ else if ((m_latched_instr & 0xf800) == 0x8000)
+ {
+ // JRMK
+ m_source_data = read_register(m_latched_instr & 0x001f, true);
+ return TX1_JRMK;
+ }
+ else if ((m_latched_instr & 0xfc00) == 0x8800)
+ {
+ // MOVE immediate to data memory
+ m_source_data = (m_latched_instr & 0x0380) >> 2 | (m_latched_instr & 0x001f);
+ m_data_address = m_ir[(m_latched_instr & 0x0060) >> 5];
+ return TX_WRITE;
+ }
+ else if ((m_latched_instr & 0xfc00) == 0x8c00)
+ {
+ // LJMP or LCALL, conditional
+ m_source_data = read_register(m_latched_instr & 0x001f, true);
+ instruction_wait();
+ return T2_ABSOLUTE;
+ }
+ else if ((m_latched_instr & 0xf000) == 0x9000)
+ {
+ // MOVE from indexed data memory
+ m_data_address = m_ir[3] + ((m_latched_instr & 0x0ff0) >> 4);
+ return TX_READ;
+ }
+ else if ((m_latched_instr >= 0xa000 && m_latched_instr < 0xae00) || (m_latched_instr & 0xfc00) == 0xc000)
+ {
+ if ((m_latched_instr & 0xfe00) != 0xc000)
+ m_source_data = read_register(m_latched_instr & 0x001f, false);
+ switch (m_latched_instr & 0x0180)
+ {
+ case 0x0000:
+ m_data_address = m_ir[(m_latched_instr & 0x0060) >> 5]--;
+ break;
+ case 0x0080:
+ m_data_address = m_ir[(m_latched_instr & 0x0060) >> 5];
+ break;
+ case 0x0100:
+ m_data_address = m_ir[(m_latched_instr & 0x0060) >> 5]++;
+ break;
+ case 0x0180:
+ m_data_address = ++m_ir[(m_latched_instr & 0x0060) >> 5];
+ break;
+ }
+ return (m_latched_instr & 0xfe00) == 0xc000 ? TX_READ : TX_WRITE;
+ }
+ else if ((m_latched_instr & 0xff80) == 0xae80)
+ {
+ // EXX
+ m_ba = BIT(m_latched_instr, 4);
+ m_bb = BIT(m_latched_instr, 3);
+ if (BIT(m_latched_instr, 6))
+ set_gie(!BIT(m_latched_instr, 5));
+ instruction_wait();
+ return T2_NEXT;
+ }
+ else if ((m_latched_instr & 0xff00) == 0xaf00)
+ {
+ // RET or RETF
+ if (BIT(m_latched_instr, 7))
+ {
+ address_stack_pop((m_latched_instr & 0x0060) >> 5, BIT(m_latched_instr, 4));
+ instruction_wait();
+ return T2_NEXT;
+ }
+ else if (get_flag(m_latched_instr & 0x0007) == BIT(m_latched_instr, 3))
+ return TX_RETF;
+ else
+ {
+ instruction_wait();
+ return T2_NEXT;
+ }
+ }
+ else if ((m_latched_instr & 0xf000) == 0xb000)
+ {
+ // MOVE immediate to register
+ instruction_wait();
+ return T2_STORE;
+ }
+ else if ((m_latched_instr & 0xfc00) == 0xc400)
+ {
+ // MOVE to or from accumulator-indexed data memory
+ if (BIT(m_latched_instr, 7))
+ m_source_data = read_register(m_latched_instr & 0x001f, false);
+ m_data_address = m_ir[(m_latched_instr & 0x0060) >> 5] + read_accumulator();
+ return BIT(m_latched_instr, 7) ? TX_WRITE : TX_READ;
+ }
+ else if ((m_latched_instr & 0xff00) == 0xcb00)
+ {
+ // JMP to relative destination
+ m_source_data = m_latched_instr & 0x00ff;
+ return TX2_JMP;
+ }
+ else if ((m_latched_instr & 0xff00) == 0xcc00)
+ {
+ // CALL to relative destination
+ m_source_data = m_latched_instr & 0x00ff;
+ return TX_CALL;
+ }
+ else if ((m_latched_instr & 0xff80) == 0xcd00)
+ {
+ // LJMP to index register
+ m_pc = m_ir[(m_latched_instr & 0x0060) >> 5];
+ instruction_wait();
+ return T2_NEXT;
+ }
+ else if ((m_latched_instr & 0xff80) == 0xcd80)
+ {
+ // JMP, register-based
+ m_source_data = read_register(m_latched_instr & 0x001f, true);
+ return TX1_JMP;
+ }
+ else if ((m_latched_instr & 0xff00) == 0xce00)
+ {
+ // LJMP or LCALL, unconditional
+ instruction_wait();
+ return T2_ABSOLUTE;
+ }
+ else if ((m_latched_instr & 0xff80) == 0xcf80)
+ {
+ // TRAP or interrupt
+ address_stack_push();
+ m_pc = u16(m_ibr) << 8 | (m_latched_instr & 0x003f);
+ if (BIT(m_latched_instr, 6))
+ set_gie(false);
+ instruction_wait();
+ return T2_NEXT;
+ }
+ else if ((m_latched_instr & 0xf000) == 0xd000)
+ {
+ // JMP, conditional
+ m_source_data = m_latched_instr & 0x00ff;
+ if (get_flag((m_latched_instr & 0x0700) >> 8) == BIT(m_latched_instr, 11))
+ return TX2_JMP;
+ else
+ {
+ instruction_wait();
+ return T2_NEXT;
+ }
+ }
+ else
+ {
+ m_source_data = read_register(m_latched_instr & 0x001f, false);
+ instruction_wait();
+ return T2_STORE;
+ }
+}
+
+
+//-------------------------------------------------
+// store_result - calculate and store the result
+// of a register operation
+//-------------------------------------------------
+
+void dp8344_device::store_result()
+{
+ switch (m_latched_instr & 0xf000)
+ {
+ case 0x0000:
+ m_source_data = add_nzcv(m_source_data, (m_latched_instr & 0x0ff0) >> 4, false);
+ write_register(m_latched_instr & 0x000f, m_source_data);
+ break;
+
+ case 0x2000:
+ m_source_data = sub_nzcv(m_source_data, (m_latched_instr & 0x0ff0) >> 4, false);
+ write_register(m_latched_instr & 0x000f, m_source_data);
+ break;
+
+ case 0x3000:
+ (void)sub_nzcv(m_source_data, (m_latched_instr & 0x0ff0) >> 4, false);
+ break;
+
+ case 0x4000:
+ m_source_data &= (m_latched_instr & 0x0ff0) >> 4;
+ set_nz(m_source_data);
+ write_register(m_latched_instr & 0x000f, m_source_data);
+ break;
+
+ case 0x5000:
+ m_source_data |= (m_latched_instr & 0x0ff0) >> 4;
+ set_nz(m_source_data);
+ write_register(m_latched_instr & 0x000f, m_source_data);
+ break;
+
+ case 0x6000:
+ m_source_data ^= (m_latched_instr & 0x0ff0) >> 4;
+ set_nz(m_source_data);
+ write_register(m_latched_instr & 0x000f, m_source_data);
+ break;
+
+ case 0x7000:
+ m_source_data &= (m_latched_instr & 0x0ff0) >> 4;
+ set_nz(m_source_data);
+ break;
+
+ case 0xa000:
+ assert((m_latched_instr & 0x0f80) == 0x0e00);
+ m_source_data ^= 0xff;
+ set_nz(m_source_data);
+ write_register(m_latched_instr & 0x001f, m_source_data);
+ break;
+
+ case 0xb000:
+ write_register(m_latched_instr & 0x000f, (m_latched_instr & 0x0ff0) >> 4);
+ break;
+
+ case 0xc000:
+ switch (m_latched_instr & 0x0f00)
+ {
+ case 0x800:
+ set_carry(BIT(u16(m_source_data) << 1, (m_latched_instr & 0x00e0) >> 5));
+ m_source_data >>= (m_latched_instr & 0x00e0) >> 5;
+ set_nz(m_source_data);
+ write_register(m_latched_instr & 0x001f, m_source_data);
+ break;
+
+ case 0x900:
+ set_carry(BIT(m_source_data, (m_latched_instr & 0x00e0) >> 5));
+ if ((m_latched_instr & 0x00e0) != 0)
+ m_source_data <<= 8 - ((m_latched_instr & 0x00e0) >> 5);
+ set_nz(m_source_data);
+ write_register(m_latched_instr & 0x001f, m_source_data);
+ break;
+
+ case 0xa00:
+ set_carry(BIT(u16(m_source_data) << 1, (m_latched_instr & 0x00e0) >> 5));
+ m_source_data = rotate_right(m_source_data, (m_latched_instr & 0x00e0) >> 5);
+ set_nz(m_source_data);
+ write_register(m_latched_instr & 0x001f, m_source_data);
+ break;
+ }
+ break;
+
+ case 0xe000:
+ if (BIT(m_latched_instr, 11))
+ m_source_data = sub_nzcv(m_source_data, read_accumulator(), BIT(m_latched_instr, 10) && BIT(m_ccr, 1));
+ else
+ m_source_data = add_nzcv(m_source_data, read_accumulator(), BIT(m_latched_instr, 10) && BIT(m_ccr, 1));
+ write_register((m_latched_instr & 0x03e0) >> 5, m_source_data);
+ break;
+
+ case 0xf000:
+ switch (m_latched_instr & 0x0c00)
+ {
+ case 0x000:
+ m_source_data &= read_accumulator();
+ set_nz(m_source_data);
+ break;
+
+ case 0x400:
+ m_source_data |= read_accumulator();
+ set_nz(m_source_data);
+ break;
+
+ case 0x800:
+ m_source_data ^= read_accumulator();
+ set_nz(m_source_data);
+ break;
+
+ case 0xc00:
+ break;
+ }
+ write_register((m_latched_instr & 0x03e0) >> 5, m_source_data);
+ break;
+ }
+}
+
+
+//-------------------------------------------------
+// data_write - write one byte to data memory to
+// finish instruction
+//-------------------------------------------------
+
+void dp8344_device::data_write()
+{
+ switch (m_latched_instr & 0xfe00)
+ {
+ case 0xa000: case 0xa200:
+ m_source_data = add_nzcv(m_source_data, read_accumulator(), BIT(m_latched_instr, 9) && BIT(m_ccr, 1));
+ break;
+
+ case 0xa400: case 0xa600:
+ m_source_data = sub_nzcv(m_source_data, read_accumulator(), BIT(m_latched_instr, 9) && BIT(m_ccr, 1));
+ break;
+
+ case 0xa800:
+ m_source_data &= read_accumulator();
+ set_nz(m_source_data);
+ break;
+
+ case 0xaa00:
+ m_source_data |= read_accumulator();
+ set_nz(m_source_data);
+ break;
+
+ case 0xac00:
+ m_source_data ^= read_accumulator();
+ set_nz(m_source_data);
+ break;
+ }
+
+ m_data_space.write_byte(m_data_address, m_source_data);
+}
+
+
+//-------------------------------------------------
+// data_read - read one byte from data memory
+// into register to finish instruction
+//-------------------------------------------------
+
+void dp8344_device::data_read()
+{
+ write_register(m_latched_instr & ((m_latched_instr & 0xf000) == 0x9000 ? 0x000f : 0x001f), m_data_space.read_byte(m_data_address));
}
@@ -1235,10 +1906,167 @@ std::unique_ptr<util::disasm_interface> dp8344_device::create_disassembler()
void dp8344_device::execute_run()
{
- debugger_instruction_hook(m_pc);
+ while (m_icount > 0)
+ {
+ switch (m_inst_state)
+ {
+ case T1_DECODE:
+ m_ppc = m_pc;
+ debugger_instruction_hook(m_pc);
+
+ if (m_nmi_pending)
+ {
+ m_nmi_pending = false;
+
+ // TRAP to interrupt vector
+ m_latched_instr = 0xcfdc;
+ }
+ else if (BIT(m_acr, 0) && interrupt_active())
+ {
+ // TRAP to interrupt vector
+ m_latched_instr = 0xcfc0 | get_interrupt_vector();
+ }
+ else
+ m_pc++;
+
+ m_inst_state = decode_instruction();
+ break;
+
+ case T1_START:
+ instruction_wait();
+ m_inst_state = T2_NEXT;
+ break;
+
+ case T1_SKIP:
+ m_pc++;
+ instruction_wait();
+ m_inst_state = T2_NEXT;
+ break;
+
+ case T1_LJMP:
+ m_pc = m_latched_instr;
+ instruction_wait();
+ m_inst_state = T2_NEXT;
+ break;
+
+ case T1_LCALL:
+ m_pc++;
+ address_stack_push();
+ m_pc = m_latched_instr;
+ instruction_wait();
+ m_inst_state = T2_NEXT;
+ break;
+
+ case TX_READ:
+ latch_address(true);
+ m_inst_state = T2_READ;
+ break;
- // TODO: everything
- m_icount = 0;
+ case TX_WRITE:
+ latch_address(false);
+ m_inst_state = T2_WRITE;
+ break;
+
+ case TX1_JRMK:
+ m_source_data = rotate_right(m_source_data, (m_latched_instr & 0x00e0) >> 5);
+ m_source_data &= (0xff >> ((m_latched_instr & 0x0700) >> 8)) & 0xfe;
+ m_inst_state = TX2_JMP;
+ break;
+
+ case TX1_JMP:
+ m_inst_state = TX2_JMP;
+ break;
+
+ case TX2_JMP:
+ m_pc += s8(m_source_data);
+ instruction_wait();
+ m_inst_state = T2_NEXT;
+ break;
+
+ case TX_CALL:
+ address_stack_push();
+ m_pc += s8(m_source_data);
+ instruction_wait();
+ m_inst_state = T2_NEXT;
+ break;
+
+ case TX_RETF:
+ address_stack_pop((m_latched_instr & 0x0060) >> 5, BIT(m_latched_instr, 4));
+ instruction_wait();
+ m_inst_state = T2_NEXT;
+ break;
+
+ case T2_NEXT:
+ if (m_wait_states != 0)
+ m_wait_states--;
+ else
+ {
+ prefetch_instruction();
+ m_inst_state = T1_DECODE;
+ }
+ break;
+
+ case T2_STORE:
+ if (m_wait_states != 0)
+ m_wait_states--;
+ else
+ {
+ store_result();
+ prefetch_instruction();
+ m_inst_state = T1_DECODE;
+ }
+ break;
+
+ case T2_READ:
+ if (m_wait_states != 0)
+ m_wait_states--;
+ else
+ {
+ data_read();
+ prefetch_instruction();
+ m_inst_state = T1_DECODE;
+ }
+ break;
+
+ case T2_WRITE:
+ if (m_wait_states != 0)
+ m_wait_states--;
+ else
+ {
+ data_write();
+ prefetch_instruction();
+ m_inst_state = T1_DECODE;
+ }
+ break;
+
+ case T2_ABSOLUTE:
+ if (m_wait_states != 0)
+ m_wait_states--;
+ else
+ {
+ if ((m_latched_instr & 0xfc00) == 0x8c00)
+ {
+ if (BIT(m_source_data, (m_latched_instr & 0x00e0) >> 5) == BIT(m_latched_instr, 8))
+ m_inst_state = BIT(m_latched_instr, 9) ? T1_LCALL : T1_LJMP;
+ else
+ m_inst_state = T1_SKIP;
+ }
+ else
+ m_inst_state = BIT(m_latched_instr, 7) ? T1_LCALL : T1_LJMP;
+ prefetch_instruction();
+ }
+ break;
+ }
+
+ // If the timer is started, run it
+ if (BIT(m_acr, 7))
+ {
+ if ((m_tclk++ & (BIT(m_acr, 5) ? 1 : 15)) == 0)
+ timer_count();
+ }
+
+ m_icount--;
+ }
}
@@ -1280,6 +2108,10 @@ void dp8344_device::cmd_w(u8 data)
BIT(data, 3) ? "latched" : BIT(data, 5) ? "fast buffered" : "slow buffered",
BIT(data, 6) ? "single step" : BIT(data, 2) ? "start" : "stop");
+ // Make sure not to restart in the middle of an instruction
+ if (!BIT(m_ric, 2) && BIT(data, 2))
+ m_inst_state = T1_START;
+
m_ric = data;
set_input_line(INPUT_LINE_HALT, BIT(data, 2) ? CLEAR_LINE : ASSERT_LINE);
}
@@ -1299,13 +2131,13 @@ u8 dp8344_device::remote_read(offs_t offset)
{
case 0x00:
// Read from data memory
- data = m_data_space->read_byte(offset);
+ data = m_data_space.read_byte(offset);
break;
case 0x01:
// Read from instruction memory
if (!m_hib && !machine().side_effects_disabled())
- m_latched_instr = m_inst_space->read_word(m_pc);
+ m_latched_instr = m_inst_space.read_word(m_pc);
data = m_hib ? m_latched_instr >> 8 : m_latched_instr & 0xff;
if (!machine().side_effects_disabled())
{
@@ -1341,12 +2173,11 @@ u8 dp8344_device::remote_read(offs_t offset)
void dp8344_device::remote_write(offs_t offset, u8 data)
{
// TODO: stop CPU if not accessing DMEM or RIC
-
switch (m_ric & 0x03)
{
case 0x00:
// Write to data memory
- m_data_space->write_byte(offset, data);
+ m_data_space.write_byte(offset, data);
break;
case 0x01:
@@ -1359,7 +2190,7 @@ void dp8344_device::remote_write(offs_t offset, u8 data)
{
m_hib = !m_hib;
if (!m_hib)
- m_inst_space->write_word(m_pc++, m_latched_instr);
+ m_inst_space.write_word(m_pc++, m_latched_instr);
}
break;