From 7c6a82c3d14e4c68918f95d76ae0801877ca40ea Mon Sep 17 00:00:00 2001 From: AJR Date: Wed, 18 Dec 2019 12:52:58 -0500 Subject: [PATCH] vt52: Extremely preliminary CPU execution (many instructions still unimplemented) --- src/devices/cpu/vt50/vt50.cpp | 303 +++++++++++++++++++++++++++++- src/devices/cpu/vt50/vt50.h | 15 ++ src/devices/cpu/vt50/vt50dasm.cpp | 2 +- src/mame/drivers/vt52.cpp | 2 +- 4 files changed, 318 insertions(+), 4 deletions(-) diff --git a/src/devices/cpu/vt50/vt50.cpp b/src/devices/cpu/vt50/vt50.cpp index 260f2190aa2..80b94012859 100644 --- a/src/devices/cpu/vt50/vt50.cpp +++ b/src/devices/cpu/vt50/vt50.cpp @@ -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 diff --git a/src/devices/cpu/vt50/vt50.h b/src/devices/cpu/vt50/vt50.h index 894a5bb7538..69d7f6f2b09 100644 --- a/src/devices/cpu/vt50/vt50.h +++ b/src/devices/cpu/vt50/vt50.h @@ -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; }; diff --git a/src/devices/cpu/vt50/vt50dasm.cpp b/src/devices/cpu/vt50/vt50dasm.cpp index 9b2e603e0c4..69d0d5b68f8 100644 --- a/src/devices/cpu/vt50/vt50dasm.cpp +++ b/src/devices/cpu/vt50/vt50dasm.cpp @@ -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)); diff --git a/src/mame/drivers/vt52.cpp b/src/mame/drivers/vt52.cpp index 06a827a5690..ddb11c5dadc 100644 --- a/src/mame/drivers/vt52.cpp +++ b/src/mame/drivers/vt52.cpp @@ -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)