mirror of
https://github.com/holub/mame
synced 2025-04-22 16:31:49 +03:00
dp8344: Add preliminary execution core
This commit is contained in:
parent
0553965fe5
commit
edbc9a763b
@ -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--;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user