From 9bb87665baa2faf1edd6fd2ce67c5de28fa0459e Mon Sep 17 00:00:00 2001 From: AJR Date: Wed, 16 Nov 2022 15:07:16 -0500 Subject: unidasm: Add CDC 1700, Cyber 18, Sigma 2 and Xerox 530 disassemblers --- src/devices/cpu/cdc1700/cdc1700d.cpp | 535 +++++++++++++++++++++++++++++++++++ src/devices/cpu/cdc1700/cdc1700d.h | 37 +++ src/devices/cpu/sigma2/sigma2d.cpp | 393 +++++++++++++++++++++++++ src/devices/cpu/sigma2/sigma2d.h | 40 +++ src/tools/unidasm.cpp | 6 + 5 files changed, 1011 insertions(+) create mode 100644 src/devices/cpu/cdc1700/cdc1700d.cpp create mode 100644 src/devices/cpu/cdc1700/cdc1700d.h create mode 100644 src/devices/cpu/sigma2/sigma2d.cpp create mode 100644 src/devices/cpu/sigma2/sigma2d.h diff --git a/src/devices/cpu/cdc1700/cdc1700d.cpp b/src/devices/cpu/cdc1700/cdc1700d.cpp new file mode 100644 index 00000000000..3b80a51f3e2 --- /dev/null +++ b/src/devices/cpu/cdc1700/cdc1700d.cpp @@ -0,0 +1,535 @@ +// license:BSD-3-Clause +// copyright-holders:AJR +/*************************************************************************** + + CDC 1700 & Cyber 18 disassembler + +***************************************************************************/ + +#include "emu.h" +#include "cdc1700d.h" + +cdc1700_disassembler::cdc1700_disassembler() + : util::disasm_interface() +{ +} + +cyber18_disassembler::cyber18_disassembler() + : cdc1700_disassembler() +{ +} + +u32 cdc1700_disassembler::opcode_alignment() const +{ + return 1; +} + +namespace { + +const char *const s_skip_insts[16] = +{ + "SAZ", "SAN", + "SAP", "SAM", + "SQZ", "SQN", + "SQP", "SQM", + "SWS", "SWN", + "SOV", "SNO", + "SPE", "SNP", + "SPF", "SNF" +}; + +const char *const s_destregs[8] = +{ + "0", + "M", + "Q", + "Q,M", + "A", + "A,M", + "A,Q", + "A,Q,M" +}; + +const char *const s_register_insts[15] = +{ + "SLS", "01X", "INP", "OUT", + "EIN", "IIN", "SPB", "CPB", + "08X", "INA", "ENA", "NOP", + "ENQ", "INQ", "EXI" +}; + +const char *const s_memory_insts[15] = +{ + "JMP", "MUI", "DVI", + "STQ", "RTJ", "STA", "SPA", + "ADD", "SUB", "AND", "EOR", + "LDA", "RAO", "LDQ", "ADQ" +}; + +const char *const s_field_insts[6] = +{ + "SFZ", "SFN", + "LFA", "SFA", + "CLF", "SEF" +}; + +const char *const s_misc_micro_insts[13] = +{ + "LMM", + "LRG", + "SRG", + "SIO", + "SPS", + "DMI", + "CPB", + "GPE", + "GPO", + "ASC", + "APM", + "PM0", + "PM1" +}; + +const char *const s_misc_page_insts[6] = +{ + "LLB", + "LUB", + "EMS", + "WPR", + "RPR", + "ECC" +}; + +const char s_reg_names[8] = +{ + '0', + '1', + '2', + '3', + '4', + 'Q', + 'A', + 'I' +}; + +const char *const s_reg_long_names[8] = +{ + "", + "R1", + "R2", + "R3", + "R4", + "Q", + "A", + "I" +}; + +} // anonymous namespace + +void cdc1700_disassembler::format_s8(std::ostream &stream, u8 value) +{ + if (BIT(value, 7)) + { + stream << '-'; + value ^= 0xff; + } + if (value > 9) + stream << '$'; + util::stream_format(stream, "%X", value); +} + +offs_t cdc1700_disassembler::dasm_register_reference(std::ostream &stream, offs_t pc, const data_buffer &opcodes, u16 inst) +{ + util::stream_format(stream, "%-5s", s_register_insts[BIT(inst, 8, 4)]); + u8 modifier = inst & 0x00ff; + if (inst >= 0x0900 && inst < 0x0e00) + format_s8(stream, modifier); + else if (modifier <= 9) + util::stream_format(stream, "%d", modifier); + else + util::stream_format(stream, "$%02X", modifier); + return 1 | SUPPORTED; +} + +offs_t cyber18_disassembler::dasm_register_reference(std::ostream &stream, offs_t pc, const data_buffer &opcodes, u16 inst) +{ + if (inst < 0x0100 && inst != 0x0000) + { + // Type 2 skip instructions + util::stream_format(stream, "S%d%-3c%d", BIT(inst, 6, 2) == 0 ? 4 : BIT(inst, 6, 2), "ZNPM"[BIT(inst, 4, 2)], inst & 0x000f); + return 1 | STEP_COND | SUPPORTED; + } + else if (BIT(inst, 9, 3) == 2 && (inst & 0x00ff) != 0) + { + // Type 2 storage reference instructions & field reference instructions + u16 inst2 = opcodes.r16(pc + 1); + u32 flags = 0; + if (BIT(inst, 8)) + { + if (BIT(inst, 1, 2) != 0) + { + stream << s_field_insts[BIT(inst, 0, 3) - 2]; + flags = (BIT(inst, 2) ? 0 : STEP_COND) | SUPPORTED; + } + } + else switch (BIT(inst2, 8, 8)) + { + case 0x50: + if (BIT(inst, 0, 3) == 0) + { + stream << "SJE"; + flags = STEP_OUT | SUPPORTED; + } + else + { + util::stream_format(stream, "SJ%c", s_reg_names[BIT(inst, 0, 3)]); + flags = STEP_OVER | SUPPORTED; + } + break; + + case 0x80: + if (BIT(inst, 0, 3) != 0) + { + util::stream_format(stream, "AR%c", s_reg_names[BIT(inst, 0, 3)]); + flags = SUPPORTED; + } + break; + + case 0x90: + if (BIT(inst, 0, 3) != 0) + { + util::stream_format(stream, "SB%c", s_reg_names[BIT(inst, 0, 3)]); + flags = SUPPORTED; + } + break; + + case 0xa0: case 0xa1: + if (BIT(inst, 0, 3) != 0) + { + util::stream_format(stream, "A%c%c", BIT(inst2, 8) ? 'M' : 'N', s_reg_names[BIT(inst, 0, 3)]); + flags = SUPPORTED; + } + break; + + case 0xc0: case 0xc1: + if (BIT(inst, 0, 3) != 0) + { + util::stream_format(stream, "%cR%c", BIT(inst2, 8) ? 'S' : 'L', s_reg_names[BIT(inst, 0, 3)]); + flags = SUPPORTED; + } + break; + + case 0xc2: case 0xc3: + if (BIT(inst, 0, 3) != 0) + { + util::stream_format(stream, "%cCA", BIT(inst2, 8) ? 'S' : 'L'); + flags = SUPPORTED; + } + break; + + case 0xd0: case 0xd1: + if (BIT(inst, 0, 3) != 0) + { + util::stream_format(stream, "O%c%c", BIT(inst2, 8) ? 'M' : 'R', s_reg_names[BIT(inst, 0, 3)]); + flags = SUPPORTED; + } + break; + + case 0xe0: + if (BIT(inst, 0, 3) != 0) + { + util::stream_format(stream, "C%cE", s_reg_names[BIT(inst, 0, 3)]); + flags = SUPPORTED | STEP_COND; + } + break; + + case 0xe2: + if (BIT(inst, 0, 3) != 0) + { + stream << "CCE"; + flags = SUPPORTED | STEP_COND; + } + break; + } + + if (flags != 0) + { + u8 delta = inst2 & 0x00ff; + if (delta == 0) + { + u16 addr = opcodes.r16(pc + 2); + util::stream_format(stream, "%c ", BIT(inst, 6, 2) == 1 ? '+' : ' '); + if (BIT(inst, 7)) + { + // Two-word relative addressing + if (BIT(inst, 6)) + stream << '('; + util::stream_format(stream, "$%04X", pc + 2 + addr - (BIT(addr, 15) ? 0xffff : 0)); + if (BIT(inst, 6)) + stream << ')'; + } + else if (BIT(inst, 6)) + { + // Two-word absolute addressing (32K mode assumed; 65K mode does not use bit 15 for indirection) + if (BIT(addr, 15)) + stream << '('; + util::stream_format(stream, "$%04X", addr & 0x7fff); + if (BIT(addr, 15)) + stream << ')'; + } + else + { + // Two-word constant addressing + stream << "=N"; + if (BIT(addr, 15) && !BIT(inst, 8) && (inst2 & 0xef00) == 0x8000) + { + stream << '-'; + addr ^= 0xffff; + } + util::stream_format(stream, "$%04X", addr); + } + } + else + { + // One-word addressing + util::stream_format(stream, "%c ", BIT(inst, 7) ? '*' : '-'); + if (BIT(inst, 6)) + stream << '('; + if (BIT(inst, 7)) + util::stream_format(stream, "$%04X", pc + 1 + delta - (BIT(delta, 7) ? 0xff : 0)); + else if (BIT(inst, 3, 3) != 0 && !BIT(inst, 6)) + format_s8(stream, delta); + else if (delta == 0xff && !BIT(inst, 8)) + stream << 'I'; + else + util::stream_format(stream, "$%04X", delta); + if (BIT(inst, 6)) + stream << ')'; + } + + // For field reference instructions, FLDBUF and FLDLEN are specified after address but before indexing + if (BIT(inst, 8)) + util::stream_format(stream, ",%d,%d", BIT(inst2, 12, 4), BIT(inst2, 8, 4) + 1); + + // For LCA, SCA and CCE, first index is a character index + if (!BIT(inst, 8) && (inst2 & 0xde00) == 0xc200) + util::stream_format(stream, ",%s", s_reg_long_names[BIT(inst, 0, 3)]); + + // Ra indexing is specified last + if (BIT(inst, 3, 3) != 0) + util::stream_format(stream, ",%s", s_reg_long_names[BIT(inst, 3, 3)]); + + return (delta == 0 ? 3 : 2) | flags; + } + else + { + util::stream_format(stream, "%-5s$%04X", "NUM", inst); + return 1 | SUPPORTED; + } + } + else if (BIT(inst, 8, 4) == 6 && BIT(inst, 5, 3) != 0) + { + // Decrement and repeat + util::stream_format(stream, "DR%-3c%d", s_reg_names[BIT(inst, 5, 3)], inst & 0x000f); + return 1 | STEP_COND | SUPPORTED; + } + else if (BIT(inst, 8, 4) == 7 && BIT(inst, 5, 3) != 0 && BIT(inst, 0, 3) != 0) + { + // Type 2 inter-register transfer (bits 5-7 specify origin register, bits 0-2 specify destination register) + util::stream_format(stream, "XF%-3c%s", s_reg_names[BIT(inst, 5, 3)], s_reg_long_names[BIT(inst, 0, 3)]); + return 1 | SUPPORTED; + } + else if (inst > 0x0b00 && inst < 0x0c00) + { + // Miscellaneous enhanced instructions + if (BIT(inst, 5, 3) != 0 && BIT(inst, 0, 3) < 6) + util::stream_format(stream, "%-5s%s", s_misc_page_insts[BIT(inst, 0, 3)], s_reg_long_names[BIT(inst, 5, 3)]); + else if (inst <= 0x0b0d) + util::stream_format(stream, "%-5s0", s_misc_micro_insts[BIT(inst, 0, 4) - 1]); + else + util::stream_format(stream, "%-5s$%04X", "NUM", inst); + return 1 | SUPPORTED; + } + else + return cdc1700_disassembler::dasm_register_reference(stream, pc, opcodes, inst); +} + +offs_t cdc1700_disassembler::disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer ¶ms) +{ + u16 inst = opcodes.r16(pc); + if (inst >= 0x1000) + { + stream << s_memory_insts[BIT(inst, 12, 4) - 1]; + u8 delta = inst & 0x00ff; + if (delta == 0) + { + u16 addr = opcodes.r16(pc + 1); + util::stream_format(stream, "%c ", BIT(inst, 10, 2) == 1 ? '+' : ' '); + if (BIT(inst, 11)) + { + // Two-word relative addressing + if (BIT(inst, 10)) + stream << '('; + util::stream_format(stream, "$%04X", pc + 1 + addr - (BIT(addr, 15) ? 0xffff : 0)); + if (BIT(inst, 10)) + stream << ')'; + } + else if (BIT(inst, 10)) + { + // Two-word absolute addressing (32K mode assumed; 65K mode does not use bit 15 for indirection) + if (BIT(addr, 15)) + stream << '('; + util::stream_format(stream, "$%04X", addr & 0x7fff); + if (BIT(addr, 15)) + stream << ')'; + } + else + { + // Two-word constant addressing + stream << "=N"; + if (BIT(addr, 15) && (BIT(inst, 13, 3) == 1 || BIT(inst, 13, 3) == 4 || inst >= 0xf000)) + { + stream << '-'; + addr ^= 0xffff; + } + util::stream_format(stream, "$%04X", addr); + } + } + else + { + // One-word addressing + util::stream_format(stream, "%c ", BIT(inst, 11) ? '*' : '-'); + if (BIT(inst, 10)) + stream << '('; + if (BIT(inst, 11)) + util::stream_format(stream, "$%04X", pc + delta - (BIT(delta, 7) ? 0xff : 0)); + else if (BIT(inst, 8, 2) != 0 && !BIT(inst, 10)) + format_s8(stream, delta); + else if (delta == 0xff) + stream << 'I'; + else + util::stream_format(stream, "$%04X", delta); + if (BIT(inst, 10)) + stream << ')'; + } + if (BIT(inst, 8, 2) != 0) + util::stream_format(stream, ",%c", "IQB"[BIT(inst, 8, 2) - 1]); + return (delta == 0 ? 2 : 1) | (BIT(inst, 12, 4) == 5 ? STEP_OVER : BIT(inst, 8, 8) == 0x1c ? STEP_OUT : 0) | SUPPORTED; + } + else switch (BIT(inst, 8, 4)) + { + case 1: + // Skip instructions + util::stream_format(stream, "%-5s%d", s_skip_insts[BIT(inst, 4, 4)], inst & 0x000f); + return 1 | STEP_COND | SUPPORTED; + + case 8: + // Interregister operations + switch (inst & 0x00f8) + { + case 0x08: + util::stream_format(stream, "%-5s%s", "TRM", s_destregs[BIT(inst, 0, 3)]); + break; + + case 0x10: + util::stream_format(stream, "%-5s%s", "TRQ", s_destregs[BIT(inst, 0, 3)]); + break; + + case 0x18: + util::stream_format(stream, "%-5s%s", "TRB", s_destregs[BIT(inst, 0, 3)]); + break; + + case 0x20: + util::stream_format(stream, "%-5s%s", "TRA", s_destregs[BIT(inst, 0, 3)]); + break; + + case 0x28: + util::stream_format(stream, "%-5s%s", "AAM", s_destregs[BIT(inst, 0, 3)]); + break; + + case 0x30: + util::stream_format(stream, "%-5s%s", "AAQ", s_destregs[BIT(inst, 0, 3)]); + break; + + case 0x38: + util::stream_format(stream, "%-5s%s", "AAB", s_destregs[BIT(inst, 0, 3)]); + break; + + case 0x40: + util::stream_format(stream, "%-5s%s", "CLR", s_destregs[BIT(inst, 0, 3)]); + break; + + case 0x48: + util::stream_format(stream, "%-5s%s", "TCM", s_destregs[BIT(inst, 0, 3)]); + break; + + case 0x50: + util::stream_format(stream, "%-5s%s", "TCQ", s_destregs[BIT(inst, 0, 3)]); + break; + + case 0x58: + util::stream_format(stream, "%-5s%s", "TCB", s_destregs[BIT(inst, 0, 3)]); + break; + + case 0x60: + util::stream_format(stream, "%-5s%s", "TCA", s_destregs[BIT(inst, 0, 3)]); + break; + + case 0x68: + util::stream_format(stream, "%-5s%s", "EAM", s_destregs[BIT(inst, 0, 3)]); + break; + + case 0x70: + util::stream_format(stream, "%-5s%s", "EAQ", s_destregs[BIT(inst, 0, 3)]); + break; + + case 0x78: + util::stream_format(stream, "%-5s%s", "EAB", s_destregs[BIT(inst, 0, 3)]); + break; + + case 0x80: + util::stream_format(stream, "%-5s%s", "SET", s_destregs[BIT(inst, 0, 3)]); + break; + + case 0xa8: + util::stream_format(stream, "%-5s%s", "LAM", s_destregs[BIT(inst, 0, 3)]); + break; + + case 0xb0: + util::stream_format(stream, "%-5s%s", "LAQ", s_destregs[BIT(inst, 0, 3)]); + break; + + case 0xb8: + util::stream_format(stream, "%-5s%s", "LAB", s_destregs[BIT(inst, 0, 3)]); + break; + + case 0xe8: + util::stream_format(stream, "%-5s%s", "CAM", s_destregs[BIT(inst, 0, 3)]); + break; + + case 0xf0: + util::stream_format(stream, "%-5s%s", "CAQ", s_destregs[BIT(inst, 0, 3)]); + break; + + case 0xf8: + util::stream_format(stream, "%-5s%s", "CAB", s_destregs[BIT(inst, 0, 3)]); + break; + + default: + util::stream_format(stream, "%-5s$%04X", "NUM", inst); + break; + } + return 1 | SUPPORTED; + + case 0xf: + // Shift instructions + if (BIT(inst, 5, 2) != 0) + util::stream_format(stream, "%c%c%-3c%d", "QAL"[BIT(inst, 5, 2) - 1], BIT(inst, 7) ? 'L' : 'R', 'S', inst & 0x001f); + else + util::stream_format(stream, "%-5s$%04X", "NUM", inst); + return 1 | SUPPORTED; + + default: + return dasm_register_reference(stream, pc, opcodes, inst); + } +} diff --git a/src/devices/cpu/cdc1700/cdc1700d.h b/src/devices/cpu/cdc1700/cdc1700d.h new file mode 100644 index 00000000000..63dd04a924a --- /dev/null +++ b/src/devices/cpu/cdc1700/cdc1700d.h @@ -0,0 +1,37 @@ +// license:BSD-3-Clause +// copyright-holders:AJR + +#ifndef MAME_CPU_CDC1700_CDC1700D_H +#define MAME_CPU_CDC1700_CDC1700D_H + +#pragma once + +class cdc1700_disassembler : public util::disasm_interface +{ +public: + // construction/destruction + cdc1700_disassembler(); + +protected: + // util::disasm_interface overrides + virtual u32 opcode_alignment() const override; + virtual offs_t disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer ¶ms) override; + + virtual offs_t dasm_register_reference(std::ostream &stream, offs_t pc, const data_buffer &opcodes, u16 inst); + + // formatting helpers + void format_s8(std::ostream &stream, u8 value); +}; + +class cyber18_disassembler : public cdc1700_disassembler +{ +public: + // construction/destruction + cyber18_disassembler(); + +protected: + // cdc1700_disassembler overrides + virtual offs_t dasm_register_reference(std::ostream &stream, offs_t pc, const data_buffer &opcodes, u16 inst) override; +}; + +#endif // MAME_CPU_CDC1700_CDC1700D_H diff --git a/src/devices/cpu/sigma2/sigma2d.cpp b/src/devices/cpu/sigma2/sigma2d.cpp new file mode 100644 index 00000000000..e62cc38994e --- /dev/null +++ b/src/devices/cpu/sigma2/sigma2d.cpp @@ -0,0 +1,393 @@ +// license:BSD-3-Clause +// copyright-holders:AJR +/*************************************************************************** + + SDS/XDS Sigma 2/3 & Xerox 530 (16-bit) disassemblers + +***************************************************************************/ + +#include "emu.h" +#include "sigma2d.h" + +namespace { + +const char *const s_inst_names[16] = +{ + "WD", "RD", + "S", "MUL", + "B", "DIV", + "BC", "COPY", // non-memory instructions + "LDA", "AND", + "ADD", "SUB", + "LDX", "CP", + "STA", "IM" +}; + +const char *const s_shift_names[8] = +{ + "SARS", "SALS", "SCRS", "SCLS", // Single shifts + "SARD", "SALD", "SCRD", "SCLD" // Double shifts +}; + +const char *const s_bc_names[8] = +{ + "BNO", "BNC", "BAZ", "BIX", + "BXNO", "BXNC", "BEN", "BAN" +}; + +const char *const s_copy_names[32] = +{ + "RAND", "", "RANDI", "", "RANDC", "", "", "", + "ROR", "RCPY", "RORI", "RCPYI", "RORC", "RCPYC", "", "", + "REOR", "", "REORI", "", "REORC", "", "", "", + "RADD", "RCLA", "RADDI", "RCLAI", "RADDC", "RCLAC", "", "" +}; + +const char *const s_sigma2_reg_names[8] = +{ + "Z", "P", + "L", "T", + "X1", "X2", + "E", "A" +}; + +const char *const s_xerox530_reg_names[8] = +{ + "Z", "P", + "L", "T", + "X", "B", + "E", "A" +}; + +} // anonymous namespace + +sigma2_disassembler::sigma2_disassembler(const char *const *reg_names) + : util::disasm_interface() + , m_reg_names(reg_names) +{ +} + +sigma2_disassembler::sigma2_disassembler() + : sigma2_disassembler(s_sigma2_reg_names) +{ +} + +xerox530_disassembler::xerox530_disassembler() + : sigma2_disassembler(s_xerox530_reg_names) +{ +} + +u32 sigma2_disassembler::opcode_alignment() const +{ + return 1; +} + +offs_t sigma2_disassembler::dasm_memory_reference(std::ostream &stream, offs_t pc, const data_buffer &opcodes, u16 inst) const +{ + if (BIT(inst, 10)) + { + // Indirect addressing + stream << '*'; + } + if (BIT(inst, 11)) + { + // Self-relative addressing + util::stream_format(stream, "X'%04X'", (pc + (inst & 0x00ff) - (inst & 0x0100)) & 0xffff); + if (BIT(inst, 9)) + stream << ',' << m_reg_names[4]; + } + else if (BIT(inst, 8, 2) == 0 || BIT(inst, 8, 3) == 6) + { + // Nonrelative direct addressing + util::stream_format(stream, "X'%04X'", inst & 0x00ff); + if (BIT(inst, 9)) + stream << ',' << m_reg_names[4]; + + // Interrupt exit sequence (very special case in which LDX loads PSD and not X1) + if (inst == 0x00d8 && (opcodes.r16(pc + 1) & 0xf000) == 0xc000) + return 1 | STEP_OUT | step_over_extra(1) | SUPPORTED; + } + else + { + // Indexed addressing + if ((inst & 0x00ff) <= 9) + util::stream_format(stream, "%d,", inst & 0x00ff); + else + util::stream_format(stream, "X'%X',", inst & 0x00ff); + if (BIT(inst, 9)) + stream << m_reg_names[4]; + if (BIT(inst, 8)) + stream << ',' << m_reg_names[5]; + } + + return 1 | SUPPORTED; +} + +offs_t sigma2_disassembler::dasm_read_direct(std::ostream &stream, offs_t pc, const data_buffer &opcodes, u16 inst) const +{ + // RD internal control functions + if (inst == 0x1041) + { + stream << "SIO"; + return 1 | SUPPORTED; + } + else if (inst == 0x1042) + { + stream << "TIO"; + return 1 | SUPPORTED; + } + else if (inst == 0x1044) + { + stream << "TDV"; + return 1 | SUPPORTED; + } + else if (inst == 0x1048) + { + stream << "HIO"; + return 1 | SUPPORTED; + } + else if (inst == 0x1050) + { + stream << "AIO"; + return 1 | SUPPORTED; + } + else if (inst > 0x1080 && inst <= 0x10bf) + { + // Multiple precision mode prefix + util::stream_format(stream, "%-8s%s,%d", "SMP", m_reg_names[BIT(inst, 0, 3)], BIT(inst, 3, 3)); + return 1 | SUPPORTED; + } + else + { + // Fall back to disassembling RD using RIXS modes + util::stream_format(stream, "%-8s", "RD"); + return dasm_memory_reference(stream, pc, opcodes, inst); + } +} + +offs_t xerox530_disassembler::dasm_read_direct(std::ostream &stream, offs_t pc, const data_buffer &opcodes, u16 inst) const +{ + // RD internal control functions + if (inst == 0x1041) + { + stream << "SIO"; + return 1 | SUPPORTED; + } + else if (inst == 0x1042) + { + stream << "TIO"; + return 1 | SUPPORTED; + } + else if (inst == 0x1044) + { + stream << "TDV"; + return 1 | SUPPORTED; + } + else if (inst == 0x1048) + { + stream << "HIO"; + return 1 | SUPPORTED; + } + else if (inst == 0x1050) + { + stream << "AIO"; + return 1 | SUPPORTED; + } + else if (inst >= 0x108a && inst <= 0x108e) + { + // General register instructions + u16 inst2 = opcodes.r16(pc + 1); + switch (BIT(inst2, 12, 4)) + { + case 8: + util::stream_format(stream, "LW,%-5s", m_reg_names[BIT(inst, 0, 3)]); + break; + + case 9: + util::stream_format(stream, "AND,%-4s", m_reg_names[BIT(inst, 0, 3)]); + break; + + case 0xa: + util::stream_format(stream, "AW,%-5s", m_reg_names[BIT(inst, 0, 3)]); + break; + + case 0xb: + util::stream_format(stream, "SW,%-5s", m_reg_names[BIT(inst, 0, 3)]); + break; + + case 0xd: + util::stream_format(stream, "CW,%-5s", m_reg_names[BIT(inst, 0, 3)]); + break; + + case 0xe: + util::stream_format(stream, "STW,%-4s", m_reg_names[BIT(inst, 0, 3)]); + break; + + default: + util::stream_format(stream, "%-8sX'%04X'", "DATA", inst); + return 1 | SUPPORTED; + } + return 1 + dasm_memory_reference(stream, pc + 1, opcodes, inst2); + } + else if (inst == 0x109e) + { + // Floating mode: LDA, STA, ADD, SUB, MUL, DIV, CP executed as FLD, FST, FAD, FSB, FML, FDV, FCP until next branch + stream << "SFM"; + return 1 | SUPPORTED; + } + else if (inst >= 0x1088 && inst <= 0x10bf) + { + u16 inst2 = opcodes.r16(pc + 1); + if (BIT(inst, 0, 3) <= 1 || BIT(inst, 0, 3) == 7) + { + // Field addressing instructions + switch (BIT(inst2, 12, 4)) + { + case 5: + stream << "CLF"; + break; + + case 8: + stream << "LLF"; + break; + + case 9: + stream << "LAF"; + break; + + case 0xa: + stream << "STF"; + break; + + case 0xb: + stream << "SZF"; + break; + + case 0xc: + stream << "SOF"; + break; + + case 0xd: + stream << "CAF"; + break; + + case 0xf: + stream << "SLF"; + break; + + default: + util::stream_format(stream, "%-8sX'%04X'", "DATA", inst); + return 1 | SUPPORTED; + } + util::stream_format(stream, ",%s,%d ", BIT(inst, 3, 3) == 1 ? "0" : m_reg_names[BIT(inst, 3, 3)], util::sext(inst, 3)); + return 1 + dasm_memory_reference(stream, pc + 1, opcodes, inst2); + } + else if (inst == 0x1096) + { + // Double-register instructions + switch (BIT(inst2, 12, 4)) + { + case 8: + util::stream_format(stream, "%-8s", "LDD"); + break; + + case 0xa: + util::stream_format(stream, "%-8s", "DAD"); + break; + + case 0xb: + util::stream_format(stream, "%-8s", "DSB"); + break; + + case 0xd: + util::stream_format(stream, "%-8s", "CPD"); + break; + + case 0xe: + util::stream_format(stream, "%-8s", "STD"); + break; + + default: + util::stream_format(stream, "%-8sX'%04X'", "DATA", inst); + return 1 | SUPPORTED; + } + return 1 + dasm_memory_reference(stream, pc + 1, opcodes, inst2); + } + else if (BIT(inst, 3, 3) + BIT(inst, 0, 3) <= 8 && (BIT(inst2, 12, 4) == 8 || BIT(inst2, 12, 4) == 0xe)) + { + // Multiple-register load and store instructions + util::stream_format(stream, "%-8s", inst2 >= 0xe000 ? "STM" : "LDM"); + offs_t result = 1 + dasm_memory_reference(stream, pc + 1, opcodes, inst2); + util::stream_format(stream, ",%s,%d", m_reg_names[BIT(inst, 0, 3)], BIT(inst, 3, 3)); + return result; + } + else + { + util::stream_format(stream, "%-8sX'%04X'", "DATA", inst); + return 1 | SUPPORTED; + } + } + else + { + // Fall back to disassembling RD using RIXS modes + util::stream_format(stream, "%-8s", "RD"); + return dasm_memory_reference(stream, pc, opcodes, inst); + } +} + +offs_t sigma2_disassembler::disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer ¶ms) +{ + u16 inst = opcodes.r16(pc); + if ((inst & 0xf000) == 0x6000) + { + // Conditional branch instructions use self-relative addressing only + util::stream_format(stream, "%-8sX'%04X'", s_bc_names[BIT(inst, 9, 3)], (pc + (inst & 0x00ff) - (inst & 0x0100)) & 0xffff); + return 1 | STEP_COND | SUPPORTED; + } + else if ((inst & 0xf000) == 0x7000) + { + // Copy instructions + const char *name = s_copy_names[BIT(inst, 7, 5)]; + if (name[0] != '\0') + { + util::stream_format(stream, "%-8s", name); + + // Optionally invert source + if (BIT(inst, 3)) + stream << '*'; + util::stream_format(stream, "%s,%s", m_reg_names[BIT(inst, 0, 3)], m_reg_names[BIT(inst, 4, 3)]); + + // Recognize branch-and-link calling convention + if (inst == 0x75a1 && (opcodes.r16(pc + 1) & 0xf000) == 0x4000) + return 1 | STEP_OVER | step_over_extra(1) | SUPPORTED; + else if ((inst & 0xfcff) == 0x7492) + return 1 | STEP_OUT | SUPPORTED; + } + else + util::stream_format(stream, "%-8sX'%04X'", "DATA", inst); + return 1 | SUPPORTED; + } + else if ((inst & 0xfc00) == 0x2000) + { + // Shift instructions + util::stream_format(stream, "%-8s%d", s_shift_names[BIT(inst, 5, 3)], BIT(inst, 0, 5)); + if (BIT(inst, 8, 2) != 0) + { + // Shift count may be indexed + stream << ','; + if (BIT(inst, 9)) + stream << m_reg_names[4]; + if (BIT(inst, 8)) + stream << ',' << m_reg_names[5]; + } + return 1 | SUPPORTED; + } + else if ((inst & 0xf000) == 0x1000) + return dasm_read_direct(stream, pc, opcodes, inst); + else + { + // Memory reference instructions (RIXS) + util::stream_format(stream, "%-8s", s_inst_names[BIT(inst, 12, 4)]); + return dasm_memory_reference(stream, pc, opcodes, inst); + } +} diff --git a/src/devices/cpu/sigma2/sigma2d.h b/src/devices/cpu/sigma2/sigma2d.h new file mode 100644 index 00000000000..afa187f1abf --- /dev/null +++ b/src/devices/cpu/sigma2/sigma2d.h @@ -0,0 +1,40 @@ +// license:BSD-3-Clause +// copyright-holders:AJR + +#ifndef MAME_CPU_SIGMA2_SIGMA2D_H +#define MAME_CPU_SIGMA2_SIGMA2D_H + +#pragma once + +class sigma2_disassembler : public util::disasm_interface +{ +public: + // construction/destruction + sigma2_disassembler(); + +protected: + sigma2_disassembler(const char *const *reg_names); + + // util::disasm_interface overrides + virtual u32 opcode_alignment() const override; + virtual offs_t disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer ¶ms) override; + + // disassembly helpers + offs_t dasm_memory_reference(std::ostream &stream, offs_t pc, const data_buffer &opcodes, u16 inst) const; + virtual offs_t dasm_read_direct(std::ostream &stream, offs_t pc, const data_buffer &opcodes, u16 inst) const; + + const char *const *const m_reg_names; +}; + +class xerox530_disassembler : public sigma2_disassembler +{ +public: + // construction/destruction + xerox530_disassembler(); + +protected: + // sigma2_disassembler overrides + virtual offs_t dasm_read_direct(std::ostream &stream, offs_t pc, const data_buffer &opcodes, u16 inst) const override; +}; + +#endif // MAME_CPU_SIGMA2_SIGMA2D_H diff --git a/src/tools/unidasm.cpp b/src/tools/unidasm.cpp index 13846a2f560..918c6fab73f 100644 --- a/src/tools/unidasm.cpp +++ b/src/tools/unidasm.cpp @@ -29,6 +29,7 @@ using util::BIT; #include "cpu/bcp/bcpdasm.h" #include "cpu/capricorn/capricorn_dasm.h" #include "cpu/ccpu/ccpudasm.h" +#include "cpu/cdc1700/cdc1700d.h" #include "cpu/clipper/clipperd.h" #include "cpu/cop400/cop410ds.h" #include "cpu/cop400/cop420ds.h" @@ -151,6 +152,7 @@ using util::BIT; #include "cpu/se3208/se3208dis.h" #include "cpu/sh/sh_dasm.h" #include "cpu/sharc/sharcdsm.h" +#include "cpu/sigma2/sigma2d.h" #include "cpu/sm510/sm510d.h" #include "cpu/sm8500/sm8500d.h" #include "cpu/sparc/sparcdasm.h" @@ -402,6 +404,7 @@ static const dasm_table_entry dasm_table[] = { "b6100", le, 0, []() -> util::disasm_interface * { return new b6100_disassembler; } }, { "capricorn", le, 0, []() -> util::disasm_interface * { return new capricorn_disassembler; } }, { "ccpu", le, 0, []() -> util::disasm_interface * { return new ccpu_disassembler; } }, + { "cdc1700", be, -1, []() -> util::disasm_interface * { return new cdc1700_disassembler; } }, { "cdp1801", le, 0, []() -> util::disasm_interface * { return new cosmac_disassembler(cosmac_disassembler::TYPE_1801); } }, { "cdp1802", le, 0, []() -> util::disasm_interface * { return new cosmac_disassembler(cosmac_disassembler::TYPE_1802); } }, { "cdp1805", le, 0, []() -> util::disasm_interface * { return new cosmac_disassembler(cosmac_disassembler::TYPE_1805); } }, @@ -419,6 +422,7 @@ static const dasm_table_entry dasm_table[] = { "cquestlin", be, -3, []() -> util::disasm_interface * { return new cquestlin_disassembler; } }, { "cquestrot", be, -3, []() -> util::disasm_interface * { return new cquestrot_disassembler; } }, { "cquestsnd", be, -3, []() -> util::disasm_interface * { return new cquestsnd_disassembler; } }, + { "cyber18", be, -1, []() -> util::disasm_interface * { return new cyber18_disassembler; } }, { "dp8344", le, -1, []() -> util::disasm_interface * { return new dp8344_disassembler; } }, { "ds5002fp", le, 0, []() -> util::disasm_interface * { return new ds5002fp_disassembler; } }, { "ds80c320", le, 0, []() -> util::disasm_interface * { return new ds80c320_disassembler; } }, @@ -570,6 +574,7 @@ static const dasm_table_entry dasm_table[] = { "sh4", le, 0, []() -> util::disasm_interface * { return new sh_disassembler(true); } }, { "sh4be", be, 0, []() -> util::disasm_interface * { return new sh_disassembler(true); } }, { "sharc", le, -3, []() -> util::disasm_interface * { return new sharc_disassembler; } }, + { "sigma2", be, -1, []() -> util::disasm_interface * { return new sigma2_disassembler; } }, { "sm500", le, 0, []() -> util::disasm_interface * { return new sm500_disassembler; } }, { "sm510", le, 0, []() -> util::disasm_interface * { return new sm510_disassembler; } }, { "sm511", le, 0, []() -> util::disasm_interface * { return new sm511_disassembler; } }, @@ -683,6 +688,7 @@ static const dasm_table_entry dasm_table[] = { "xavix", le, 0, []() -> util::disasm_interface * { return new xavix_disassembler; } }, { "xavix2000", le, 0, []() -> util::disasm_interface * { return new xavix2000_disassembler; } }, { "xavix2", le, 0, []() -> util::disasm_interface * { return new xavix2_disassembler; } }, + { "xerox530", be, -1, []() -> util::disasm_interface * { return new xerox530_disassembler; } }, { "z180", le, 0, []() -> util::disasm_interface * { return new z180_disassembler; } }, { "z8", be, 0, []() -> util::disasm_interface * { return new z8_disassembler; } }, { "z80", le, 0, []() -> util::disasm_interface * { return new z80_disassembler; } }, -- cgit v1.2.3