dp8344: Add preliminary execution core

This commit is contained in:
AJR 2019-12-01 16:15:44 -05:00
parent 0553965fe5
commit edbc9a763b
2 changed files with 771 additions and 80 deletions

View File

@ -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);
// TODO: everything
m_icount = 0;
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;
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--;
}
}

View File

@ -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;