vt52: Extremely preliminary CPU execution (many instructions still unimplemented)

This commit is contained in:
AJR 2019-12-18 12:52:58 -05:00
parent 5da18d7422
commit 7c6a82c3d1
4 changed files with 318 additions and 4 deletions

View File

@ -33,6 +33,12 @@ vt5x_cpu_device::vt5x_cpu_device(const machine_config &mconfig, device_type type
, m_x8(false)
, m_cursor_ff(false)
, m_video_process(false)
, m_t(0)
, m_write_ff(false)
, m_flag_test_ff(false)
, m_load_pc(false)
, m_qa_e23(0)
, m_icount(0)
{
m_rom_config.m_is_octal = true;
m_ram_config.m_is_octal = true;
@ -101,6 +107,11 @@ void vt5x_cpu_device::device_start()
save_item(NAME(m_x8));
save_item(NAME(m_cursor_ff));
save_item(NAME(m_video_process));
save_item(NAME(m_t));
save_item(NAME(m_write_ff));
save_item(NAME(m_flag_test_ff));
save_item(NAME(m_load_pc));
save_item(NAME(m_qa_e23));
}
void vt5x_cpu_device::device_reset()
@ -108,13 +119,301 @@ void vt5x_cpu_device::device_reset()
m_pc = 0;
m_rom_bank = 0;
m_video_process = false;
m_t = 7;
m_flag_test_ff = false;
m_load_pc = false;
m_qa_e23 = false;
}
void vt5x_cpu_device::execute_te(u8 inst)
{
if (BIT(inst, 3) && !BIT(inst, 7))
{
switch (inst & 0160)
{
case 0000:
// ZXZY
m_x = 0;
m_y = 0;
break;
case 0020:
// X8
m_x8 = !m_x8;
break;
case 0040:
// IXDY
m_x = (m_x + 1) & 0177;
m_y = (m_y - 1) & ((1 << m_ybits) - 1);
break;
case 0060:
// IX
m_x = (m_x + 1) & 0177;
break;
case 0100:
// ZA
m_ac = 0;
break;
case 0120:
// M1
m_mode_ff = true;
break;
case 0140:
// ZX
m_x = 0;
break;
case 0160:
// M0
m_mode_ff = false;
break;
}
}
m_flag_test_ff = false;
m_load_pc = false;
if (!BIT(inst, 7))
m_done_ff = false;
}
void vt5x_cpu_device::execute_tf(u8 inst)
{
if (BIT(inst, 2) && !BIT(inst, 7))
{
switch (inst & 0160)
{
case 0000:
// DXDY
m_x = (m_x - 1) & 0177;
m_y = (m_y - 1) & ((1 << m_ybits) - 1);
break;
case 0020:
case 0040:
// IA or IA1
m_ac = (m_ac + 1) & 0177;
break;
case 0060:
// IY
m_y = (m_y + 1) & ((1 << m_ybits) - 1);
break;
case 0100:
// DY
m_y = (m_y - 1) & ((1 << m_ybits) - 1);
break;
case 0120:
// IROM
m_rom_bank = (m_rom_bank + 1) & 3;
break;
case 0140:
// DX
m_x = (m_x - 1) & 0177;
break;
case 0160:
// DA
m_ac = (m_ac - 1) & 0177;
break;
}
}
}
void vt5x_cpu_device::execute_tw(u8 inst)
{
if ((inst & 0217) == 0)
{
switch (inst & 0160)
{
case 0000:
// SCFF
m_cursor_ff = true;
break;
case 0020:
// SVID
m_video_process = true;
break;
case 0040:
// B2Y
m_y = m_buffer & ((1 << m_ybits) - 1);
break;
case 0060:
// CBFF (TODO)
break;
case 0100:
// ZCAV
m_cursor_ff = false;
m_video_process = false;
break;
case 0120:
// LPB (TODO: load print shift register)
break;
case 0140:
// EPR (TODO: start printer)
break;
case 0160:
// HPR!ZY (TODO: halt printer)
m_y = 0;
break;
}
}
if (BIT(inst, 0) && !BIT(inst, 7))
m_flag_test_ff = true;
// set FF for instructions that write to RAM
m_write_ff = (BIT(inst, 7) && !m_done_ff) || inst == 022 || inst == 042 || inst == 062;
if (m_write_ff)
m_done_ff = true;
}
void vt5x_cpu_device::execute_tg(u8 inst)
{
// TODO
m_write_ff = false;
}
void vt5x_cpu_device::execute_th(u8 inst)
{
if (m_flag_test_ff)
{
switch (inst & 0160)
{
case 0000:
// M0: PSCJ (TODO)
// M1: URJ (TODO)
break;
case 0020:
// M0: TABJ
// M1: AEMJ (TODO)
if (!m_mode_ff)
m_load_pc = (m_ac & 7) == 7;
break;
case 0040:
// M0: KCLJ (TODO)
// M1: ALMJ (TODO)
break;
case 0060:
// M0: FRQJ (TODO)
// M1: ADXJ
if (m_mode_ff)
m_load_pc = m_ac != m_x;
break;
case 0100:
// M0: PRQJ (TODO)
// M1: AEM2J (TODO)
break;
case 0120:
// TRUJ
m_load_pc = true;
break;
case 0140:
// M0: UTJ (TODO)
// M1: VSCJ (TODO)
break;
case 0160:
// M0: TOSJ (TODO)
// M1: KEYJ (TODO)
break;
}
}
if ((m_pc & 0377) == 0377)
m_rom_bank = (m_rom_bank + 1) & 3;
m_pc = (m_pc + 1) & 03777;
}
void vt5x_cpu_device::execute_tj(u8 dest)
{
if (m_load_pc)
m_pc = u16(m_rom_bank) << 8 | dest;
else
m_pc = (m_pc + 1) & 03777;
}
void vt5x_cpu_device::execute_run()
{
debugger_instruction_hook(m_pc);
while (m_icount > 0)
{
switch (m_t)
{
case 0:
if (!m_qa_e23)
debugger_instruction_hook(m_pc);
m_t = 1;
break;
m_icount = 0;
case 1:
if (!m_qa_e23)
execute_te(m_rom_cache->read_byte(m_pc));
m_t = 2;
break;
case 2:
if (!m_qa_e23)
execute_tf(m_rom_cache->read_byte(m_pc));
m_t = 3;
break;
case 3:
if (m_qa_e23 && m_write_ff)
execute_tg(m_rom_cache->read_byte(m_pc));
m_t = 4;
break;
case 4:
if (m_qa_e23)
execute_th(m_rom_cache->read_byte(m_pc));
m_t = 5;
break;
case 5:
m_t = 6;
break;
case 6:
if (m_qa_e23 && m_flag_test_ff)
execute_tj(m_rom_cache->read_byte(m_pc));
m_t = 7;
break;
case 7:
if (!m_qa_e23)
execute_tw(m_rom_cache->read_byte(m_pc));
m_t = 8;
break;
case 8:
m_t = 0;
m_qa_e23 = !m_qa_e23;
break;
}
m_icount--;
}
}
void vt5x_cpu_device::state_string_export(const device_state_entry &entry, std::string &str) const

View File

@ -34,6 +34,14 @@ protected:
virtual void state_string_export(const device_state_entry &entry, std::string &str) const override;
private:
// execution helpers
void execute_te(u8 inst);
void execute_tf(u8 inst);
void execute_tw(u8 inst);
void execute_tg(u8 inst);
void execute_th(u8 inst);
void execute_tj(u8 dest);
// address spaces
address_space_config m_rom_config;
address_space_config m_ram_config;
@ -56,6 +64,13 @@ private:
bool m_x8;
bool m_cursor_ff;
bool m_video_process;
// execution phases
u8 m_t;
bool m_write_ff;
bool m_flag_test_ff;
bool m_load_pc;
bool m_qa_e23;
s32 m_icount;
};

View File

@ -103,7 +103,7 @@ offs_t vt5x_disassembler::disassemble(std::ostream &stream, offs_t pc, const vt5
if (m_jumps_h[1][(opcode & 0160) >> 4] != nullptr)
util::stream_format(stream, "/%sJ", m_jumps_h[1][(opcode & 0160) >> 4]);
u16 nextpc = pc + 2;
u16 nextpc = pc + 1;
if ((opcode & 0164) == 0124) // IROM!TRUJ adjustment
nextpc += 0400;
util::stream_format(stream, " %04o", (nextpc & 01400) | opcodes.r8(pc + 1));

View File

@ -97,4 +97,4 @@ ROM_START(vt52)
ROM_LOAD("23-002b4.e1", 0x000, 0x400, NO_DUMP)
ROM_END
COMP(1975, vt52, 0, 0, vt52, vt52, vt52_state, empty_init, "DEC", "VT52", MACHINE_IS_SKELETON)
COMP(1975, vt52, 0, 0, vt52, vt52, vt52_state, empty_init, "Digital Equipment Corporation", "VT52", MACHINE_IS_SKELETON)