summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices
diff options
context:
space:
mode:
authorGravatarGravatar AJR <ajrhacker@users.noreply.github.com>2019-12-01 16:15:44 -0500
committerGravatarGravatar AJR <ajrhacker@users.noreply.github.com>2019-12-01 16:15:44 -0500
commitedbc9a763b08a9c858870231b2e247d45a177a67 (patch)
treed0b8d8ca872ce418c0d087ebb25de69214af0917 /src/devices
parent0553965fe5af75a89d1b5be098e08369dd6a6c6a (diff)
dp8344: Add preliminary execution core
Diffstat (limited to 'src/devices')
-rw-r--r--src/devices/cpu/bcp/dp8344.cpp816
-rw-r--r--src/devices/cpu/bcp/dp8344.h35
2 files changed, 771 insertions, 80 deletions
diff --git a/src/devices/cpu/bcp/dp8344.cpp b/src/devices/cpu/bcp/dp8344.cpp
index a1cd2fac1f1..54062c8d634 100644
--- a/src/devices/cpu/bcp/dp8344.cpp
+++ b/src/devices/cpu/bcp/dp8344.cpp
@@ -54,6 +54,8 @@ DEFINE_DEVICE_TYPE(DP8344, dp8344_device, "dp8344", "DP8344 BCP")
// DEVICE CONSTRUCTION AND INITIALIZATION
//**************************************************************************
+ALLOW_SAVE_TYPE(dp8344_device::inst_state);
+
//-------------------------------------------------
// dp8344_device - constructor
//-------------------------------------------------
@@ -72,6 +74,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,7 +91,7 @@ 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_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}
@@ -151,10 +156,10 @@ void dp8344_device::device_start()
set_icountptr(m_icount);
// debug state registration
- state_add(BCP_PC, "PC", m_pc);
+ state_add<u16>(BCP_PC, "PC", [this]() { return 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,9 +180,13 @@ 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]);
@@ -187,6 +196,7 @@ void dp8344_device::device_start()
// 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,8 +212,7 @@ 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_asp));
save_item(NAME(m_dsp));
@@ -215,6 +224,10 @@ 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));
@@ -229,7 +242,7 @@ 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;
@@ -265,7 +278,9 @@ void dp8344_device::device_reset()
m_ric = m_auto_start ? 0x03 : 0x01;
m_hib = false;
+ // Reset execution state
m_nmi_pending = false;
+ m_inst_state = T1_START;
transceiver_reset();
@@ -274,49 +289,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
@@ -405,6 +392,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
@@ -469,6 +460,169 @@ void dp8344_device::set_auxiliary_control(u8 data)
}
+//-------------------------------------------------
+// interrupt_active - determine if any of the
+// five maskable interrupts is active
+//-------------------------------------------------
+
+bool dp8344_device::interrupt_active() const
+{
+ // TODO
+ return false;
+}
+
+
+//-------------------------------------------------
+// get_interrupt_vector - return the vector for
+// the highest priority maskable interrupt
+//-------------------------------------------------
+
+u8 dp8344_device::get_interrupt_vector() const
+{
+ // TODO
+ return 0;
+}
+
+
+//**************************************************************************
+// 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
+ 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;
+ }
+}
+
+
+//-------------------------------------------------
+// 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
//**************************************************************************
@@ -498,8 +652,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 +665,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);
}
}
@@ -928,28 +1082,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];
@@ -1097,35 +1251,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 +1374,371 @@ 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);
+ 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);
+ 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);
+ 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);
+ 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) || get_flag(m_latched_instr & 0x0007) == BIT(m_latched_instr, 3))
+ return TX_RET;
+ 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);
+ 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);
+ 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);
+ 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 + ((m_latched_instr & 0x0ff0) >> 4));
+ 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 + ((m_latched_instr & 0x0ff0) >> 4));
+ 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));
+ 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;
+ }
+
+ 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 +1748,159 @@ 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:
+ 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;
+
+ 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_RET:
+ 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;
- // TODO: everything
- m_icount = 0;
+ 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;
+ }
+
+ m_icount--;
+ }
}
diff --git a/src/devices/cpu/bcp/dp8344.h b/src/devices/cpu/bcp/dp8344.h
index b256a175dd6..c141271d999 100644
--- a/src/devices/cpu/bcp/dp8344.h
+++ b/src/devices/cpu/bcp/dp8344.h
@@ -82,9 +82,18 @@ protected:
// device_memory_interface overrides
virtual space_config_vector memory_space_config() const override;
+ // device_state_interface overrides
+ virtual void state_string_export(const device_state_entry &entry, std::string &str) const override;
+
private:
+ enum inst_state : u8 {
+ T1_DECODE, T1_START, T1_SKIP, T1_LJMP, T1_LCALL,
+ TX_READ, TX_WRITE,
+ TX1_JRMK, TX1_JMP, TX2_JMP, TX_CALL, TX_RET,
+ T2_NEXT, T2_STORE, T2_READ, T2_WRITE, T2_ABSOLUTE
+ };
+
// internal functions
- bool get_flag(unsigned f) const;
void set_receiver_interrupt(bool state);
void set_transmitter_interrupt(bool state);
void set_line_turn_around_interrupt(bool state);
@@ -94,9 +103,17 @@ private:
void set_condition_code(u8 data);
void set_interrupt_control(u8 data);
void set_auxiliary_control(u8 data);
+ bool interrupt_active() const;
+ u8 get_interrupt_vector() const;
+ bool get_flag(unsigned f) const;
+ void set_nz(u8 result);
+ void set_carry(bool state);
+ static u8 rotate_right(u8 data, u8 b);
+ u8 add_nzcv(u8 s1, u8 s2, bool carry_in);
+ u8 sub_nzcv(u8 s1, u8 s2, bool carry_in);
u16 get_timer_count();
void address_stack_push();
- void address_stack_pop(u8 grf);
+ void address_stack_pop(u8 g, bool rf);
void set_stack_pointer(u8 data);
void data_stack_push(u8 data);
u8 data_stack_pop();
@@ -114,6 +131,13 @@ private:
u8 read_register(unsigned reg);
u8 read_accumulator() const;
void write_register(unsigned reg, u8 data);
+ void prefetch_instruction();
+ void latch_address(bool rw);
+ void instruction_wait();
+ inst_state decode_instruction();
+ void store_result();
+ void data_write();
+ void data_read();
// address spaces
const address_space_config m_inst_config;
@@ -130,8 +154,13 @@ private:
// execution state
u16 m_pc;
+ u16 m_ppc;
s32 m_icount;
bool m_nmi_pending;
+ inst_state m_inst_state;
+ u8 m_wait_states;
+ u8 m_source_data;
+ u16 m_data_address;
// control registers
u8 m_ccr;
@@ -152,7 +181,7 @@ private:
u8 m_gp_alt[4];
// index registers
- PAIR16 m_ir[4];
+ u16 m_ir[4];
// timer registers
u16 m_tr;