diff options
Diffstat (limited to 'src/devices/cpu/nova/novadasm.cpp')
-rw-r--r-- | src/devices/cpu/nova/novadasm.cpp | 262 |
1 files changed, 262 insertions, 0 deletions
diff --git a/src/devices/cpu/nova/novadasm.cpp b/src/devices/cpu/nova/novadasm.cpp new file mode 100644 index 00000000000..408f6329fb9 --- /dev/null +++ b/src/devices/cpu/nova/novadasm.cpp @@ -0,0 +1,262 @@ +// license:BSD-3-Clause +// copyright-holders:AJR +/*************************************************************************** + + Data General Nova disassembler + +***************************************************************************/ + +#include "emu.h" +#include "novadasm.h" + +nova_disassembler::nova_disassembler() +{ +} + +u32 nova_disassembler::opcode_alignment() const +{ + return 1; +} + +namespace { + +const char *const s_alc_ops[8] = +{ + "COM", "NEG", "MOV", "INC", + "ADC", "SUB", "ADD", "AND" +}; + +const char *const s_skip_codes[8] = +{ + "0", "SKP", + "SZC", "SNC", + "SZR", "SNR", + "SEZ", "SBN" +}; + +const char *const s_io_ops[8] = +{ + "NIO", "DIA", "DOA", "DIB", + "DOB", "DIC", "DOC", "SKP" +}; + +} // anonymous namespace + +void nova_disassembler::format_effective_address(std::ostream &stream, offs_t pc, u16 inst) +{ + if (BIT(inst, 10)) + stream << '@'; + u8 disp = inst & 0377; + if (BIT(inst, 9)) + { + if (s8(disp) < 0) + { + stream << '-'; + disp = -disp; + } + util::stream_format(stream, "%o,%d", disp, BIT(inst, 8, 2)); + } + else + util::stream_format(stream, "%05o", BIT(inst, 8) ? (pc + int(s8(disp))) & 077777 : disp); +} + +void nova_disassembler::format_device_code(std::ostream &stream, u8 device) +{ + switch (device) + { + case 001: + stream << "MDV"; + break; + + case 002: case 003: case 004: + util::stream_format(stream, "MAP%d", device - 2); + break; + + case 006: + stream << "MCAT"; + break; + + case 007: + stream << "MCAR"; + break; + + case 010: + stream << "TTI"; + break; + + case 011: + stream << "TTO"; + break; + + case 012: + stream << "PTR"; + break; + + case 013: + stream << "PTP"; + break; + + case 014: + stream << "RTC"; + break; + + case 015: + stream << "PLT"; + break; + + case 016: + stream << "CDR"; + break; + + case 017: + stream << "LPT"; + break; + + case 020: + stream << "DSK"; + break; + + case 021: + stream << "ADCV"; + break; + + case 022: + stream << "MTA"; + break; + + case 023: + stream << "DACV"; + break; + + case 024: + stream << "DCM"; + break; + + case 033: + stream << "DKP"; + break; + + case 040: + stream << "SCR"; + break; + + case 041: + stream << "SCT"; + break; + + case 077: + stream << "CPU"; + break; + + default: + util::stream_format(stream, "%o", device); + break; + } +} + +offs_t nova_disassembler::disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer ¶ms) +{ + u16 inst = opcodes.r16(pc); + if (BIT(inst, 15)) + { + // ALC (arithmetic-logical) + std::string alcop(s_alc_ops[BIT(inst, 8, 3)]); + if (BIT(inst, 4, 2) != 0) + alcop.push_back("ZOC"[BIT(inst, 4, 2) - 1]); + if (BIT(inst, 6, 2) != 0) + alcop.push_back("LRS"[BIT(inst, 6, 2) - 1]); + if (BIT(inst, 3)) + alcop.push_back('#'); + util::stream_format(stream, "%-8s%d,%d", alcop, BIT(inst, 13, 2), BIT(inst, 11, 2)); + if (BIT(inst, 0, 3) != 0) + stream << ',' << s_skip_codes[BIT(inst, 0, 3)]; + return 1 | (BIT(inst, 1, 2) != 0 ? STEP_COND : 0) | SUPPORTED; + } + else if (inst >= 060000) + { + // I/O + switch (inst & 03777) + { + case 00177: + stream << "INTEN"; + return 1 | SUPPORTED; + + case 00277: + stream << "INTDS"; + return 1 | SUPPORTED; + + case 00477: + util::stream_format(stream, "%-8s%d", "READS", BIT(inst, 11, 2)); + return 1 | SUPPORTED; + + case 01477: + util::stream_format(stream, "%-8s%d", "INTA", BIT(inst, 11, 2)); + return 1 | SUPPORTED; + + case 02077: + util::stream_format(stream, "%-8s%d", "MSKO", BIT(inst, 11, 2)); + return 1 | SUPPORTED; + + case 02677: + stream << "IORST"; + return 1 | SUPPORTED; + + case 03077: + stream << "HALT"; + return 1 | SUPPORTED; + + case 03101: + if (BIT(inst, 11, 2) == 2) + { + stream << "DIV"; + return 1 | SUPPORTED; + } + break; + + case 03301: + if (BIT(inst, 11, 2) == 2) + { + stream << "MUL"; + return 1 | SUPPORTED; + } + break; + } + + stream << s_io_ops[BIT(inst, 8, 3)]; + if (BIT(inst, 8, 3) == 7) + { + util::stream_format(stream, "%c%-4c", BIT(inst, 7) ? 'D' : 'B', BIT(inst, 6) ? 'Z' : 'N'); + format_device_code(stream, BIT(inst, 0, 6)); + return 1 | STEP_COND | SUPPORTED; + } + else + { + util::stream_format(stream, "%-5c", " SCP"[BIT(inst, 6, 2)]); + if (BIT(inst, 8, 3) != 0) + util::stream_format(stream, "%d,", BIT(inst, 11, 2)); + format_device_code(stream, BIT(inst, 0, 6)); + return 1 | SUPPORTED; + } + } + else if (inst >= 020000) + { + // Memory reference with accumulator + util::stream_format(stream, "%-8s%d,", BIT(inst, 14) ? "STA" : "LDA", BIT(inst, 11, 2)); + format_effective_address(stream, pc, inst); + return 1 | SUPPORTED; + } + else if (BIT(inst, 12)) + { + // Memory reference with conditional skip + util::stream_format(stream, "%-8s", BIT(inst, 11) ? "DSZ" : "ISZ"); + format_effective_address(stream, pc, inst); + return 1 | STEP_COND | SUPPORTED; + } + else + { + // Memory reference with jump + util::stream_format(stream, "%-8s", BIT(inst, 11) ? "JSR" : "JMP"); + format_effective_address(stream, pc, inst); + return 1 | (BIT(inst, 11) ? STEP_OVER : 0) | SUPPORTED; + } +} |