summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/ddp516
diff options
context:
space:
mode:
author AJR <ajrhacker@users.noreply.github.com>2023-08-14 19:57:58 -0400
committer AJR <ajrhacker@users.noreply.github.com>2023-08-14 19:57:58 -0400
commit81c3564ccfd07e4db6b1530e7912dbac17285480 (patch)
tree4b709ad4beb4b4550823ea17ce24d8b656ee5ef8 /src/devices/cpu/ddp516
parentecdce6505c499531ceb3c4b70c7d59db78e8125b (diff)
unidasm: Add disassemblers for DDP-516 and Prime S, R, V architectures
Diffstat (limited to 'src/devices/cpu/ddp516')
-rw-r--r--src/devices/cpu/ddp516/ddp516d.cpp1651
-rw-r--r--src/devices/cpu/ddp516/ddp516d.h87
2 files changed, 1738 insertions, 0 deletions
diff --git a/src/devices/cpu/ddp516/ddp516d.cpp b/src/devices/cpu/ddp516/ddp516d.cpp
new file mode 100644
index 00000000000..a841cdc2ddc
--- /dev/null
+++ b/src/devices/cpu/ddp516/ddp516d.cpp
@@ -0,0 +1,1651 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/***************************************************************************
+
+ Computer Control Company/Honeywell DDP-516 disassembler
+
+ Alternate disassemblers are provided for Prime Computer's 16S, 32S,
+ 32R, 64R and 64V instruction modes, which are increasingly elaborate
+ extensions of DDP-516. (The 32I and IX modes are general register
+ architectures with mostly different opcodes and are not supported
+ here.)
+
+ Bits are numbered from 1 (sign) to 16 (LSB). All arithmetic is two's
+ complement, though DAP-16 prints memory reference instructions in sign-
+ magnitude format.
+
+ In DBL mode, LDA, STA, ADD and SUB are executed as DLD, DST, DAD and
+ DSB. The alternate mnemonics are not used in the disassembly output.
+ (These operations also perform 31-bit rather than 32-bit arithmetic,
+ omitting the sign bit of B. MPY and DIV likewise have 31-bit products
+ and dividends except in Prime 64V mode.)
+
+ Address 0 is equivalent to index register X, though its indexing tag
+ is conventionally notated as 1. Several other primary registers,
+ including A (1), B (2), S/Y (3) and P (7), are mapped to low memory
+ addresses on Prime processors.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "ddp516d.h"
+
+ddp516_disassembler::ddp516_disassembler()
+ : util::disasm_interface()
+{
+}
+
+prime_disassembler::prime_disassembler(u8 mode)
+ : ddp516_disassembler()
+ , c_mode_key(mode)
+{
+}
+
+prime16s_disassembler::prime16s_disassembler()
+ : prime_disassembler(0)
+{
+}
+
+prime32s_disassembler::prime32s_disassembler()
+ : prime_disassembler(1)
+{
+}
+
+prime32r_disassembler::prime32r_disassembler()
+ : prime_disassembler(3)
+{
+}
+
+prime64r_disassembler::prime64r_disassembler()
+ : prime_disassembler(2)
+{
+}
+
+prime64v_disassembler::prime64v_disassembler()
+ : prime_disassembler(6)
+{
+}
+
+u32 ddp516_disassembler::opcode_alignment() const
+{
+ return 1;
+}
+
+u32 prime64v_disassembler::interface_flags() const
+{
+ return PAGED;
+}
+
+u32 prime64v_disassembler::page_address_bits() const
+{
+ // Virtual space consists of 65536-word segments
+ return 16;
+}
+
+namespace {
+
+constexpr auto STEP_COND = util::disasm_interface::STEP_COND;
+constexpr auto STEP_OVER = util::disasm_interface::STEP_OVER;
+constexpr auto STEP_OUT = util::disasm_interface::STEP_OUT;
+
+const std::pair<const char *, offs_t> s_mr_insts[16] =
+{
+ { "LDX", 0 },
+ { "JMP", 0 },
+ { "LDA", 0 },
+ { "ANA", 0 },
+ { "STA", 0 },
+ { "ERA", 0 },
+ { "ADD", 0 },
+ { "SUB", 0 },
+ { "JST", STEP_OVER },
+ { "CAS", STEP_COND }, // three-way skip, IBM 704 style
+ { "IRS", STEP_COND },
+ { "IMA", 0 },
+ { "IOG", 0 }, // not a real instruction
+ { "STX", 0 },
+ { "MPY", 0 },
+ { "DIV", 0 }
+};
+
+const std::pair<const char *, offs_t> s_mr_insts_r_mode[16][3] =
+{
+ { { nullptr, 0 }, { nullptr, 0 }, { "JSX", STEP_OVER } },
+ { { "EAA", 0 }, { "XEC", 0 }, { "ENTR", 0 } },
+ { { "FLD", 0 }, { "DFLD", 0 }, { "JEQ", STEP_COND } },
+ { { nullptr, 0 }, { nullptr, 0 }, { "JNE", STEP_COND } },
+ { { "FST", 0 }, { "DFST", 0 }, { "JLE", STEP_COND } },
+ { { nullptr, 0 }, { nullptr, 0 }, { "JGT", STEP_COND } },
+ { { "FAD", 0 }, { "DFAD", 0 }, { "JLT", STEP_COND } },
+ { { "FSB", 0 }, { "DFSB", 0 }, { "JGE", STEP_COND } },
+ { { nullptr, 0 }, { "CREP", STEP_OVER }, { nullptr, 0 } },
+ { { "FCS", STEP_COND }, { "DFCS", STEP_COND }, { nullptr, 0 } },
+ { { nullptr, 0 }, { nullptr, 0 }, { nullptr, 0 } },
+ { { nullptr, 0 }, { nullptr, 0 }, { nullptr, 0 } },
+ { { nullptr, 0 }, { nullptr, 0 }, { nullptr, 0 } },
+ { { "FLX", 0 }, { "JDX", STEP_COND }, { "JIX", STEP_COND } },
+ { { "FMP", 0 }, { "DFMP", 0 }, { nullptr, 0 } },
+ { { "FDV", 0 }, { "DFDV", 0 }, { nullptr, 0 } }
+};
+
+const std::pair<const char *, offs_t> s_mr_insts_v_mode[16][4] =
+{
+ { { "LDX", 0 }, { "LDY", 0 }, { "STY", 0 }, { "JSX", STEP_OVER } },
+ { { "JMP", 0 }, { "EAL", 0 }, { "XEC", 0 }, { nullptr, 0 } },
+ { { "LDA", 0 }, { "FLD", 0 }, { "DFLD", 0 }, { "LDL", 0 } },
+ { { "ANA", 0 }, { "STLR", 0 }, { "ORA", 0 }, { "ANL", 0 } },
+ { { "STA", 0 }, { "FST", 0 }, { "DFST", 0 }, { "STL", 0 } },
+ { { "ERA", 0 }, { "LDLR", 0 }, { nullptr, 0 }, { "ERL", 0 } },
+ { { "ADD", 0 }, { "FAD", 0 }, { "DFAD", 0 }, { "ADL", 0 } },
+ { { "SUB", 0 }, { "FSB", 0 }, { "DFSB", 0 }, { "SBL", 0 } },
+ { { "JST", STEP_OVER }, { nullptr, 0 }, { "PCL", STEP_OVER }, { nullptr, 0 } },
+ { { "CAS", STEP_COND }, { "FCS", STEP_COND }, { "DFCS", STEP_COND }, { "CLS", STEP_COND } },
+ { { "IRS", STEP_COND }, { "MIA", 0 }, { "EAXB", 0 }, { nullptr, 0 } },
+ { { "IMA", 0 }, { "MIB", 0 }, { "EALB", 0 }, { nullptr, 0 } },
+ { { "JSY", STEP_OVER }, { "EIO", 0 }, { "JSXB", STEP_OVER }, { nullptr, 0 } },
+ { { "STX", 0 }, { "FLX", 0 }, { "DFLX", 0 }, { "QFLX", 0 } },
+ { { "MPY", 0 }, { "FMP", 0 }, { "DFMP", 0 }, { "MPL", 0 } },
+ { { "DIV", 0 }, { "FDV", 0 }, { "DFDV", 0 }, { "DVL", 0 } }
+};
+
+const char *const s_io_insts[4] =
+{
+ "OCP", "SKS", "INA", "OTA"
+};
+
+const char *const s_skip_insts[10][2] =
+{
+ { "SPL", "SMI" }, // Sign of A
+ { "SPN", "SPS" }, // Memory parity error
+ { "SLZ", "SLN" }, // LSB of A
+ { "SZE", "SNE" }, // A ≠ 0
+ { "SR1", "SS1" }, // Sense switch 1
+ { "SR2", "SS2" }, // Sense switch 2
+ { "SR3", "SS3" }, // Sense switch 3
+ { "SR4", "SS4" }, // Sense switch 4
+ { "SRC", "SSC" }, // C bit
+ { "SKP", "NOP" } // No condition
+};
+
+const char *const s_sh_insts[16] =
+{
+ "LRL", "LRS", "LRR", nullptr, // Long right shifts
+ "LGR", "ARS", "ARR", nullptr, // A right shifts
+ "LLL", "LLS", "LLR", nullptr, // Long left shifts
+ "LGL", "ALS", "ALR", nullptr // A left shifts
+};
+
+const char *const s_sh_insts_prime[16] =
+{
+ "LRL", "LRS", "LRR", nullptr, // Long right shifts
+ "ARR", "ARS", "ARR", nullptr, // A right shifts
+ "LLL", "LLS", "LLR", nullptr, // Long left shifts
+ "ALL", "ALS", "ALR", nullptr // A left shifts
+};
+
+const char *const s_base_regs_v_mode[4] =
+{
+ "PB", "SB", "LB", "XB"
+};
+
+const std::pair<const char *, offs_t> s_quad_insts[8] =
+{
+ { "QFLD", 0 },
+ { "QFST", 0 },
+ { "QFAD", 0 },
+ { "QFSB", 0 },
+ { "QFMP", 0 },
+ { "QFDV", 0 },
+ { "QFCS", STEP_COND },
+ { nullptr, 0 }
+};
+
+} // anonymous namespace
+
+
+void ddp516_disassembler::format_disp(std::ostream &stream, u16 disp) const
+{
+ if (s16(disp) < 0)
+ {
+ stream << '-';
+ disp = -disp;
+ }
+ if (disp > 7)
+ stream << '\'';
+ util::stream_format(stream, "%o", disp);
+}
+
+offs_t ddp516_disassembler::dasm_skip(std::ostream &stream, u16 inst) const
+{
+ const u16 cond = inst & 000777;
+ if (cond == 036)
+ util::stream_format(stream, "SS%c", BIT(inst, 9) ? 'S' : 'R');
+ else if ((cond & (cond - 1)) == 0)
+ stream << s_skip_insts[count_leading_zeros_32(cond) - 23][BIT(inst, 9)];
+ else
+ util::stream_format(stream, "%-6s'%04o", "SKP", inst & 001777);
+ return 1 | (cond != 0 ? STEP_COND : 0) | SUPPORTED;
+}
+
+offs_t ddp516_disassembler::dasm_generic(std::ostream &stream, u16 inst) const
+{
+ switch (inst)
+ {
+ case 000000:
+ stream << "HLT";
+ break;
+
+ case 000005:
+ stream << "SGL";
+ break;
+
+ case 000007:
+ stream << "DBL";
+ break;
+
+ case 000011:
+ stream << "DXA";
+ break;
+
+ case 000013:
+ stream << "EXA";
+ break;
+
+ case 000021:
+ stream << "RMP";
+ break;
+
+ case 000041:
+ stream << "SCA";
+ break;
+
+ case 000043:
+ stream << "INK";
+ break;
+
+ case 000101:
+ stream << "NRM";
+ break;
+
+ case 000201:
+ stream << "IAB";
+ break;
+
+ case 000401:
+ stream << "ENB";
+ break;
+
+ case 001001:
+ stream << "INH";
+ break;
+
+ case 001401:
+ stream << "ERM";
+ break;
+
+ case 0140024:
+ stream << "CHS";
+ break;
+
+ case 0140040:
+ stream << "CRA";
+ break;
+
+ case 0140100:
+ stream << "SSP";
+ break;
+
+ case 0140200:
+ stream << "RCB";
+ break;
+
+ case 0140240:
+ stream << "CCA";
+ break;
+
+ case 0140320:
+ stream << "CSA";
+ break;
+
+ case 0140401:
+ stream << "CMA";
+ break;
+
+ case 0140407:
+ stream << "TCA";
+ break;
+
+ case 0140500:
+ stream << "SSM";
+ break;
+
+ case 0140600:
+ stream << "SCB";
+ break;
+
+ case 0141044:
+ stream << "CAR";
+ break;
+
+ case 0141050:
+ stream << "CAL";
+ break;
+
+ case 0141140:
+ stream << "ICL";
+ break;
+
+ case 0141206:
+ stream << "AOA";
+ break;
+
+ case 0141216:
+ stream << "ACA";
+ break;
+
+ case 0141240:
+ stream << "ICR";
+ break;
+
+ case 0141340:
+ stream << "ICA";
+ break;
+
+ default:
+ // Some combined operations are possible, though not documented
+ util::stream_format(stream, "%-6s%o", "OCT", inst);
+ break;
+ }
+ return 1 | SUPPORTED;
+}
+
+offs_t ddp516_disassembler::disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer &params)
+{
+ const u16 inst = opcodes.r16(pc);
+ if (BIT(inst, 10, 4) != 0)
+ {
+ if (BIT(inst, 10, 4) == 014)
+ {
+ // Input-Output group
+ if ((inst & 0140073) == 0140020)
+ {
+ // Output to device codes '20 and '24 is special
+ if ((inst & 001777) == 01020)
+ stream << "OTK";
+ else
+ util::stream_format(stream, "%-6s'%04o", "SMK", inst & 001777);
+ return 1 | SUPPORTED;
+ }
+ else
+ {
+ util::stream_format(stream, "%-6s'%04o", s_io_insts[BIT(inst, 14, 2)], inst & 001777);
+ return 1 | (BIT(inst, 14, 2) != 0 ? STEP_COND : 0) | SUPPORTED;
+ }
+ }
+ else
+ {
+ // Memory reference instructions
+ const u8 op = BIT(inst, 10, 4) == 015 && BIT(inst, 14) ? 0 : BIT(inst, 10, 4);
+ const auto &mr = s_mr_insts[op];
+ util::stream_format(stream, "%s%-3c", mr.first, BIT(inst, 15) ? '*' : ' ');
+ const u16 ea = (BIT(inst, 9) ? (pc & 077000) : 0) | (inst & 000777); // form sectored address
+ if (!BIT(inst, 9) && ((BIT(inst, 14) && op != 0) || ea == 0))
+ format_disp(stream, ea);
+ else
+ util::stream_format(stream, "'%05o", ea);
+ if (BIT(inst, 14) && op != 0)
+ stream << ",1";
+ return 1 | (BIT(inst, 10, 6) == 041 ? STEP_OUT : mr.second) | SUPPORTED;
+ }
+ }
+ else if (BIT(inst, 14, 2) == 1 && s_sh_insts[BIT(inst, 6, 4)] != nullptr)
+ {
+ // Shift instructions
+ util::stream_format(stream, "%-6s%d", s_sh_insts[BIT(inst, 6, 4)], -inst & 000077);
+ return 1 | SUPPORTED;
+ }
+ else if (BIT(inst, 14, 2) == 2)
+ {
+ // Skip instructions
+ return dasm_skip(stream, inst);
+ }
+ else
+ {
+ // Generic instructions
+ return dasm_generic(stream, inst);
+ }
+}
+
+offs_t prime_disassembler::dasm_generic_prime(std::ostream &stream, u16 inst) const
+{
+ if ((inst >> 6) == 0016)
+ util::stream_format(stream, "%-6s'%02o", "WCS", inst & 000077);
+ else switch (inst)
+ {
+ case 000001:
+ stream << "NOP";
+ break;
+
+ case 000010:
+ stream << "E64V";
+ break;
+
+ case 000011:
+ stream << "E16S";
+ break;
+
+ case 000013:
+ stream << "E32S";
+ break;
+
+ case 000021:
+ stream << "RMC";
+ break;
+
+ case 000311:
+ stream << "VIRY";
+ return 1 | STEP_COND | SUPPORTED;
+
+ case 000400:
+ stream << "ENBM"; // P850
+ break;
+
+ case 000402:
+ stream << "ENBP"; // P850
+ break;
+
+ case 000405:
+ stream << "OTK";
+ break;
+
+ case 000411:
+ stream << "CAI";
+ break;
+
+ case 000415:
+ stream << "ESIM";
+ break;
+
+ case 000417:
+ stream << "EVIM";
+ break;
+
+ case 000501:
+ stream << "EMCM";
+ break;
+
+ case 000503:
+ stream << "LMCM";
+ break;
+
+ case 000505:
+ stream << "SVC";
+ return 1 | STEP_OVER | SUPPORTED;
+
+ case 001000:
+ stream << "INHM"; // P850
+ break;
+
+ case 001002:
+ stream << "INHP"; // P850
+ break;
+
+ case 001010:
+ stream << "E32I";
+ break;
+
+ case 001011:
+ stream << "E64R";
+ break;
+
+ case 001013:
+ stream << "E32R";
+ break;
+
+ case 0140010:
+ stream << "CRL";
+ break;
+
+ case 0140014:
+ stream << "CRB";
+ break;
+
+ case 0140104:
+ stream << "XCA";
+ break;
+
+ case 0140110:
+ stream << "S1A";
+ break;
+
+ case 0140114:
+ stream << "IRX";
+ return 1 | STEP_COND | SUPPORTED;
+
+ case 0140204:
+ stream << "XCB";
+ break;
+
+ case 0141206:
+ stream << "A1A";
+ break;
+
+ case 0140210:
+ stream << "DRX";
+ return 1 | STEP_COND | SUPPORTED;
+
+ case 0140214:
+ stream << "CAZ";
+ return 1 | STEP_COND | SUPPORTED;
+
+ case 0140304:
+ stream << "A2A";
+ break;
+
+ case 0140310:
+ stream << "S2A";
+ break;
+
+ case 0140410:
+ stream << "LLT";
+ break;
+
+ case 0140411:
+ stream << "LLE";
+ break;
+
+ case 0140412:
+ stream << "LNE";
+ break;
+
+ case 0140413:
+ stream << "LEQ";
+ break;
+
+ case 0140414:
+ stream << "LGE";
+ break;
+
+ case 0140415:
+ stream << "LGT";
+ break;
+
+ case 0140416:
+ stream << "LF";
+ break;
+
+ case 0140417:
+ stream << "LT";
+ break;
+
+ case 0140510:
+ stream << "FSZE";
+ return 1 | STEP_COND | SUPPORTED;
+
+ case 0140511:
+ stream << "FSNZ";
+ return 1 | STEP_COND | SUPPORTED;
+
+ case 0140512:
+ stream << "FSMI";
+ return 1 | STEP_COND | SUPPORTED;
+
+ case 0140513:
+ stream << "FSPL";
+ return 1 | STEP_COND | SUPPORTED;
+
+ case 0140514:
+ stream << "FSLE";
+ return 1 | STEP_COND | SUPPORTED;
+
+ case 0140515:
+ stream << "FSGT";
+ return 1 | STEP_COND | SUPPORTED;
+
+ case 0140530:
+ stream << "FCM";
+ break;
+
+ case 0140534:
+ stream << "FRN";
+ break;
+
+ case 0140570:
+ stream << "FRAC";
+ break;
+
+ case 0140574:
+ stream << "DFCM";
+ break;
+
+ default:
+ return dasm_generic(stream, inst);
+ }
+ return 1 | SUPPORTED;
+}
+
+offs_t prime_disassembler::disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer &params)
+{
+ const u16 inst = opcodes.r16(pc);
+ if (BIT(inst, 10, 4) != 0)
+ {
+ if (BIT(inst, 10, 4) == 014)
+ {
+ // Input-Output group
+ if ((inst & 0101777) == 0100020)
+ {
+ util::stream_format(stream, "%cMK", BIT(inst, 14) ? 'S' : 'I');
+ return 1 | SUPPORTED;
+ }
+ else
+ {
+ util::stream_format(stream, "%-6s'%04o", s_io_insts[BIT(inst, 14, 2)], inst & 001777);
+ return 1 | (BIT(inst, 14, 2) != 0 ? STEP_COND : 0) | SUPPORTED;
+ }
+ }
+ else
+ {
+ // Memory reference instructions
+ const u8 op = BIT(inst, 10, 4) == 015 && BIT(inst, 14) ? 0 : BIT(inst, 10, 4);
+ if (BIT(inst, 4, 6) == 060 && c_mode_key >= 2)
+ {
+ const auto &mr = BIT(inst, 2, 2) == 0 ? s_mr_insts[op] : s_mr_insts_r_mode[op][BIT(inst, 2, 2) - 1];
+ if (mr.first != nullptr)
+ {
+ if (!BIT(inst, 1) || (BIT(inst, 14, 2) == 3 && op != 0))
+ {
+ // Stack relative/long reach
+ const bool preindex = BIT(inst, 14) && !BIT(inst, 1) && op != 0;
+ const u16 a = opcodes.r16(pc + 1);
+ if (BIT(inst, 2, 2) == 0 && !BIT(inst, 0))
+ util::stream_format(stream, "%s%-3c", mr.first, '%');
+ else
+ {
+ util::stream_format(stream, "%-6s", mr.first);
+ if (BIT(inst, 0))
+ stream << '@';
+ }
+ if (BIT(inst, 0) || preindex)
+ {
+ if (s16(a) >= 0 && BIT(inst, 0))
+ stream << '+';
+ format_disp(stream, a);
+ }
+ else
+ util::stream_format(stream, "'%0*o", c_mode_key == 2 ? 6 : 5, a);
+ if (preindex)
+ {
+ stream << ",X";
+ if (BIT(inst, 15))
+ stream << '*';
+ }
+ else if (BIT(inst, 15))
+ {
+ stream << ",*";
+ if (BIT(inst, 1))
+ stream << 'X';
+ }
+ return 2 | mr.second | SUPPORTED;
+ }
+ else
+ {
+ // Stack postincrement or predecrement
+ util::stream_format(stream, "%-6s", mr.first);
+ if (BIT(inst, 0))
+ stream << "-@";
+ else
+ stream << "@+";
+ if (BIT(inst, 14) && op != 0)
+ stream << ",*1";
+ else if (BIT(inst, 15))
+ stream << ",*";
+ return 1 | mr.second | SUPPORTED;
+ }
+ }
+ else
+ {
+ util::stream_format(stream, "%-6s%o", "OCT", inst);
+ return 1 | SUPPORTED;
+ }
+ }
+ else
+ {
+ const bool preindex = BIT(inst, 14) && op != 0 && (!BIT(inst, 15) || c_mode_key == 0 || (!BIT(inst, 9) && BIT(inst, 6, 3) == 0));
+ const auto &mr = s_mr_insts[op];
+ util::stream_format(stream, "%-6s", mr.first);
+ if (BIT(inst, 9))
+ {
+ // Sectored or relative addressing
+ const u16 ea = c_mode_key < 2 ? (pc & 077000) | (inst & 000777) : pc + 1 + util::sext(inst, 9);
+ if (c_mode_key == 2)
+ util::stream_format(stream, "'%06o", ea);
+ else
+ util::stream_format(stream, "'%05o", ea & 077777);
+ }
+ else
+ {
+ // Direct addressing
+ const u16 ea = inst & 000777;
+ if (preindex || ea == 0)
+ format_disp(stream, ea);
+ else
+ util::stream_format(stream, "'%0*o", c_mode_key == 2 ? 6 : 5, ea);
+ }
+ if (preindex)
+ {
+ stream << ",1";
+ if (BIT(inst, 15))
+ stream << '*';
+ }
+ else if (BIT(inst, 15))
+ {
+ stream << ",*";
+ if (BIT(inst, 14) && op != 0)
+ stream << '1';
+ }
+ return 1 | (BIT(inst, 10, 6) == 041 ? STEP_OUT : mr.second) | SUPPORTED;
+ }
+ }
+ }
+ else if (BIT(inst, 14, 2) == 1 && s_sh_insts_prime[BIT(inst, 6, 4)] != nullptr)
+ {
+ // Shift instructions
+ util::stream_format(stream, "%-6s%d", s_sh_insts_prime[BIT(inst, 6, 4)], -inst & 000077);
+ return 1 | SUPPORTED;
+ }
+ else if (BIT(inst, 14, 2) == 2)
+ {
+ // Skip instructions
+ if (BIT(inst, 7))
+ {
+ if (BIT(inst, 5, 4) == 5)
+ util::stream_format(stream, "S%c%-4c%d", BIT(inst, 4) ? 'A' : 'N', BIT(inst, 9) ? 'S' : 'R', (inst & 000017) + 1);
+ else switch (inst & 001777)
+ {
+ case 0200:
+ stream << "SMCR";
+ break;
+
+ case 0220:
+ stream << "SGT";
+ break;
+
+ case 01200:
+ stream << "SMCS";
+ break;
+
+ case 01220:
+ stream << "SLE";
+ break;
+
+ default:
+ util::stream_format(stream, "%-6s'%04o", "SKP", inst & 001777);
+ break;
+ }
+ return 1 | STEP_COND | SUPPORTED;
+ }
+ else
+ return dasm_skip(stream, inst);
+ }
+ else
+ {
+ // Generic instructions
+ switch (inst)
+ {
+ case 000105:
+ stream << "RTN";
+ return 1 | STEP_OUT | SUPPORTED;
+
+ case 000111:
+ stream << "CEA";
+ return 1 | SUPPORTED;
+
+ case 000205:
+ stream << "PIM";
+ return 1 | SUPPORTED;
+
+ case 000211:
+ stream << "PID";
+ return 1 | SUPPORTED;
+
+ case 000213:
+ util::stream_format(stream, "%-6s'%06o", "EPMJ", opcodes.r16(pc + 1)); // P300
+ return 2 | SUPPORTED;
+
+ case 000215:
+ util::stream_format(stream, "%-6s'%06o", "LPMJ", opcodes.r16(pc + 1)); // P300
+ return 2 | SUPPORTED;
+
+ case 000235:
+ util::stream_format(stream, "%-6s'%06o", "LPMX", opcodes.r16(pc + 1)); // P300
+ return 2 | SUPPORTED;
+
+ case 000237:
+ util::stream_format(stream, "%-6s'%06o", "EPMX", opcodes.r16(pc + 1)); // P300
+ return 2 | SUPPORTED;
+
+ case 000511:
+ stream << "ISI";
+ return 1 | SUPPORTED;
+
+ case 000515:
+ stream << "OSI";
+ return 1 | SUPPORTED;
+
+ case 000701:
+ util::stream_format(stream, "%-6s'%06o", "ERMJ", opcodes.r16(pc + 1)); // P300
+ return 2 | SUPPORTED;
+
+ case 000703:
+ util::stream_format(stream, "%-6s'%06o", "EVMJ", opcodes.r16(pc + 1)); // P300
+ return 2 | SUPPORTED;
+
+ case 000721:
+ util::stream_format(stream, "%-6s'%06o", "ERMX", opcodes.r16(pc + 1)); // P300
+ return 2 | SUPPORTED;
+
+ case 000723:
+ util::stream_format(stream, "%-6s'%06o", "EVMX", opcodes.r16(pc + 1)); // P300
+ return 2 | SUPPORTED;
+
+ case 0140550:
+ stream << "FLOT";
+ return 1 | SUPPORTED;
+
+ case 0140554:
+ stream << "INT";
+ return 1 | SUPPORTED;
+
+ default:
+ return dasm_generic_prime(stream, inst);
+ }
+ }
+}
+
+void prime64v_disassembler::format_ap(std::ostream &stream, u32 ap) const
+{
+ if (BIT(ap, 24, 2) != 0)
+ {
+ util::stream_format(stream, "%s%%", s_base_regs_v_mode[BIT(ap, 24, 2)]);
+ if (u16(ap) != 0)
+ {
+ if (!BIT(ap, 15))
+ stream << '+';
+ format_disp(stream, u16(ap));
+ }
+ }
+ else
+ util::stream_format(stream, "'%06o", u16(ap));
+ if (BIT(ap, 27))
+ stream << ",*";
+ else if (BIT(ap, 28, 4) != 0)
+ util::stream_format(stream, "+%dB", BIT(ap, 28, 4));
+}
+
+offs_t prime64v_disassembler::disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer &params)
+{
+ const u16 inst = opcodes.r16(pc);
+ if (BIT(inst, 10, 4) != 0)
+ {
+ // Memory reference instructions
+ const u8 op = BIT(inst, 10, 4) == 015 && BIT(inst, 14) ? 0 : BIT(inst, 10, 4);
+ if (BIT(inst, 5, 5) == 030)
+ {
+ const bool quad = op == 5 && BIT(inst, 2, 2) == 2;
+ const auto &mr = quad ? s_quad_insts[std::min<u16>(opcodes.r16(pc + 2), 7)] : s_mr_insts_v_mode[op][BIT(inst, 2, 2)];
+ if (mr.first != nullptr)
+ {
+ const bool preindex = (BIT(inst, 14, 2) != 0 ? !BIT(inst, 4) : BIT(inst, 4)) && op != 0;
+ const u16 d = opcodes.r16(pc + 1);
+ if (!BIT(inst, 15) && BIT(inst, 0, 5) < 3)
+ util::stream_format(stream, "%s%-3c", mr.first, '%');
+ else
+ util::stream_format(stream, "%-6s", mr.first);
+ if (BIT(inst, 0, 2) != 0)
+ {
+ util::stream_format(stream, "%s%%", s_base_regs_v_mode[BIT(inst, 0, 2)]);
+ if (d != 0)
+ {
+ if (s16(d) > 0)
+ stream << '+';
+ format_disp(stream, d);
+ }
+ }
+ else if (preindex && (op != 12 || BIT(inst, 2, 2) != 1))
+ format_disp(stream, d);
+ else
+ util::stream_format(stream, "'%06o", d);
+ if (preindex)
+ {
+ if (BIT(inst, 14))
+ stream << ",X";
+ else
+ stream << ",Y";
+ if (BIT(inst, 15))
+ stream << '*';
+ }
+ else if (op == 0 ? BIT(inst, 15) : BIT(inst, 14, 2) != 0)
+ {
+ stream << ",*";
+ if (BIT(inst, 15) && op != 0)
+ {
+ if (BIT(inst, 14))
+ stream << 'X';
+ else
+ stream << 'Y';
+ }
+ }
+ return (quad ? 3 : 2) | ((inst == 003403 || inst == 003420) && d == 0 ? STEP_OUT : mr.second) | SUPPORTED;
+ }
+ else
+ {
+ util::stream_format(stream, "%-6s%o", "OCT", inst);
+ return 1 | SUPPORTED;
+ }
+ }
+ else
+ {
+ // Short modes
+ const auto &mr = s_mr_insts_v_mode[op][0];
+ util::stream_format(stream, "%s%-3c", mr.first, BIT(inst, 15) ? '#' : ' ');
+ if (BIT(inst, 9))
+ {
+ const u16 ea = pc + 1 + util::sext(inst, 9); // form relative address
+ util::stream_format(stream, "'%06o", ea);
+ if (BIT(inst, 14) && op != 0)
+ {
+ stream << ",1";
+ if (BIT(inst, 15))
+ stream << '*';
+ }
+ else if (BIT(inst, 15))
+ stream << ",*";
+ }
+ else
+ {
+ if (!BIT(inst, 15) && ((BIT(inst, 14) && op != 0) || BIT(inst, 3, 6) != 0))
+ {
+ util::stream_format(stream, "%s%%+", s_base_regs_v_mode[BIT(inst, 8) ? 2 : 1]);
+ format_disp(stream, inst & 000777);
+ if (BIT(inst, 14) && op != 0)
+ stream << ",X";
+ }
+ else if (BIT(inst, 14, 2) == 3 && op != 0 && BIT(inst, 6, 3) == 0)
+ {
+ format_disp(stream, inst & 000077);
+ stream << ",X*";
+ }
+ else
+ {
+ if (BIT(inst, 3, 6) == 0)
+ util::stream_format(stream, "%o", inst & 000777);
+ else
+ util::stream_format(stream, "'%06o", inst & 000777);
+ if (BIT(inst, 15))
+ {
+ stream << ",*";
+ if (BIT(inst, 14) && op != 0)
+ stream << '1';
+ }
+ }
+ }
+ return 1 | (BIT(inst, 10, 6) == 041 ? STEP_OUT : mr.second) | SUPPORTED;
+ }
+ }
+ else if (BIT(inst, 14, 2) == 1)
+ {
+ // Shift instructions + FOP
+ if (s_sh_insts_prime[BIT(inst, 6, 4)] != nullptr)
+ util::stream_format(stream, "%-6s%d", s_sh_insts_prime[BIT(inst, 6, 4)], -inst & 000077);
+ else switch (inst & 01777)
+ {
+ case 0300:
+ stream << "DRN";
+ break;
+
+ case 0301:
+ stream << "DRNP";
+ break;
+
+ case 0302:
+ stream << "DRNZ";
+ break;
+
+ case 0303:
+ stream << "FRNP";
+ break;
+
+ case 0310:
+ stream << "SSSN";
+ break;
+
+ case 0320:
+ stream << "FRNM";
+ break;
+
+ case 0321:
+ stream << "FRNZ";
+ break;
+
+ default:
+ util::stream_format(stream, "%-6s%o", "OCT", inst);
+ break;
+ }
+ return 1 | SUPPORTED;
+ }
+ else if (BIT(inst, 14, 2) == 2)
+ {
+ // Skip instructions
+ if (BIT(inst, 7))
+ {
+ if (BIT(inst, 5, 4) == 5)
+ util::stream_format(stream, "S%c%-4c%d", BIT(inst, 4) ? 'A' : 'N', BIT(inst, 9) ? 'S' : 'R', (inst & 000017) + 1);
+ else switch (inst & 001777)
+ {
+ case 0200:
+ stream << "SMCR";
+ break;
+
+ case 0220:
+ stream << "SGT";
+ break;
+
+ case 01200:
+ stream << "SMCS";
+ break;
+
+ case 01220:
+ stream << "SLE";
+ break;
+
+ default:
+ util::stream_format(stream, "%-6s'%04o", "SKP", inst & 001777);
+ break;
+ }
+ return 1 | STEP_COND | SUPPORTED;
+ }
+ else
+ return dasm_skip(stream, inst);
+ }
+ else
+ {
+ // Generic instructions
+ switch (inst)
+ {
+ case 000015:
+ stream << "PIMA";
+ break;
+
+ case 000024:
+ stream << "STPM";
+ break;
+
+ case 000044:
+ util::stream_format(stream, "%-6s", "LIOT");
+ format_ap(stream, opcodes.r32(pc + 1));
+ return 3 | SUPPORTED;
+
+ case 000064:
+ stream << "PTLB";
+ break;
+
+ case 000115:
+ stream << "PIDA";
+ break;
+
+ case 000301:
+ stream << "PIML";
+ break;
+
+ case 000305:
+ stream << "PIDL";
+ break;
+
+ case 000315:
+ util::stream_format(stream, "%-6s", "WAIT");
+ format_ap(stream, opcodes.r32(pc + 1));
+ return 3 | SUPPORTED;
+
+ case 000510:
+ stream << "STTM";
+ break;
+
+ case 000511:
+ stream << "RTS";
+ break;
+
+ case 000601:
+ stream << "IRTN";
+ return 1 | STEP_OUT | SUPPORTED;
+
+ case 000603:
+ stream << "IRTC";
+ return 1 | STEP_OUT | SUPPORTED;
+
+ case 000605:
+ stream << "ARGT";
+ break;
+
+ case 000611:
+ stream << "PRTN";
+ return 1 | STEP_OUT | SUPPORTED;
+
+ case 000615:
+ stream << "ITLB";
+ break;
+
+ case 000617:
+ stream << "LPID";
+ break;
+
+ case 000705:
+ util::stream_format(stream, "%-6s", "CALF");
+ format_ap(stream, opcodes.r32(pc + 1));
+ return 3 | STEP_OVER | SUPPORTED;
+
+ case 000711:
+ util::stream_format(stream, "%-6s", "LPSW");
+ format_ap(stream, opcodes.r32(pc + 1));
+ return 3 | SUPPORTED;
+
+ case 000715:
+ util::stream_format(stream, "%-6s", "RSAV");
+ format_ap(stream, opcodes.r32(pc + 1));
+ return 3 | SUPPORTED;
+
+ case 000717:
+ util::stream_format(stream, "%-6s", "RRST");
+ format_ap(stream, opcodes.r32(pc + 1));
+ return 3 | SUPPORTED;
+
+ case 001005:
+ stream << "TKA";
+ break;
+
+ case 001015:
+ stream << "TAK";
+ break;
+
+ case 001100:
+ stream << "XAD";
+ break;
+
+ case 001101:
+ stream << "XMV";
+ break;
+
+ case 001102:
+ stream << "XCM";
+ break;
+
+ case 001104:
+ stream << "XMP";
+ break;
+
+ case 001107:
+ stream << "XDV";
+ break;
+
+ case 001110:
+ stream << "ZTRN";
+ break;
+
+ case 001111:
+ stream << "ZED";
+ break;
+
+ case 001112:
+ stream << "XED";
+ break;
+
+ case 001113:
+ stream << "XVRY"; // P500
+ break;
+
+ case 001114:
+ stream << "ZMV";
+ break;
+
+ case 001115:
+ stream << "ZMVD";
+ break;
+
+ case 001116:
+ stream << "ZFIL";
+ break;
+
+ case 001117:
+ stream << "ZCM";
+ break;
+
+ case 001145:
+ stream << "XBTD";
+ break;
+
+ case 001146:
+ stream << "XDTB";
+ break;
+
+ case 001200:
+ util::stream_format(stream, "%-6s", "STAC");
+ format_ap(stream, opcodes.r32(pc + 1));
+ return 3 | SUPPORTED;
+
+ case 001204:
+ util::stream_format(stream, "%-6s", "STLC");
+ format_ap(stream, opcodes.r32(pc + 1));
+ return 3 | SUPPORTED;
+
+ case 001210:
+ util::stream_format(stream, "%-6s", "NFYE");
+ format_ap(stream, opcodes.r32(pc + 1));
+ return 3 | SUPPORTED;
+
+ case 001211:
+ util::stream_format(stream, "%-6s", "NFYB");
+ format_ap(stream, opcodes.r32(pc + 1));
+ return 3 | SUPPORTED;
+
+ case 001214:
+ util::stream_format(stream, "%-6s", "INEN");
+ format_ap(stream, opcodes.r32(pc + 1));
+ return 3 | SUPPORTED;
+
+ case 001215:
+ util::stream_format(stream, "%-6s", "INBN");
+ format_ap(stream, opcodes.r32(pc + 1));
+ return 3 | SUPPORTED;
+
+ case 001216:
+ util::stream_format(stream, "%-6s", "INEC");
+ format_ap(stream, opcodes.r32(pc + 1));
+ return 3 | SUPPORTED;
+
+ case 001217:
+ util::stream_format(stream, "%-6s", "INBC");
+ format_ap(stream, opcodes.r32(pc + 1));
+ return 3 | SUPPORTED;
+
+ case 001300: case 001310:
+ util::stream_format(stream, "%-6s%d,", "EAFA", BIT(inst, 3));
+ format_ap(stream, opcodes.r32(pc + 1));
+ return 3 | SUPPORTED;
+
+ case 001301: case 001311:
+ util::stream_format(stream, "%-6s%d", "ALFA", BIT(inst, 3));
+ break;
+
+ case 001302: case 001312:
+ util::stream_format(stream, "%-6s%d", "LDC", BIT(inst, 3));
+ break;
+
+ case 001303: case 001313:
+ {
+ util::stream_format(stream, "%-6s%d,", "LFLI", BIT(inst, 3));
+ const u16 n = opcodes.r16(pc + 1);
+ if (n > 7)
+ stream << '\'';
+ util::stream_format(stream, "%o", n);
+ return 2 | SUPPORTED;
+ }
+
+ case 001304:
+ stream << "MDEI";
+ break;
+
+ case 001305:
+ stream << "MDII";
+ break;
+
+ case 001306:
+ stream << "MDRS";
+ break;
+
+ case 001307:
+ stream << "MDWC";
+ break;
+
+ case 001314:
+ stream << "CGT";
+ break;
+
+ case 001315:
+ stream << "STEX";
+ break;
+
+ case 001320: case 001330:
+ util::stream_format(stream, "%-6s%d,", "STFA", BIT(inst, 3));
+ format_ap(stream, opcodes.r32(pc + 1));
+ return 3 | SUPPORTED;
+
+ case 001321: case 001331:
+ util::stream_format(stream, "%-6s%d", "TLFL", BIT(inst, 3));
+ break;
+
+ case 001322: case 001332:
+ util::stream_format(stream, "%-6s%d", "STC", BIT(inst, 3));
+ break;
+
+ case 001323: case 001333:
+ util::stream_format(stream, "%-6s%d", "TFLL", BIT(inst, 3));
+ break;
+
+ case 001324:
+ stream << "MDIW";
+ break;
+
+ case 001710:
+ stream << "LWCS";
+ break;
+
+ case 001714:
+ stream << "CXCS";
+ break;
+
+ case 0140015:
+ stream << "CRB"; // old instruction with new opcode
+ break;
+
+ case 0140016:
+ stream << "FDBL";
+ break;
+
+ case 0140314:
+ stream << "TAB";
+ break;
+
+ case 0140504:
+ stream << "TAX";
+ break;
+
+ case 0140505:
+ stream << "TAY";
+ break;
+
+ case 0140531:
+ stream << "INTA";
+ break;
+
+ case 0140532:
+ stream << "FLTA";
+ break;
+
+ case 0140533:
+ stream << "INTL";
+ break;
+
+ case 0140535:
+ stream << "FLTL";
+ break;
+
+ case 0140570:
+ stream << "QFCM";
+ break;
+
+ case 0140571:
+ stream << "FCDQ";
+ break;
+
+ case 0140572:
+ stream << "QINQ";
+ break;
+
+ case 0140573:
+ stream << "QIQR";
+ break;
+
+ case 0140604:
+ stream << "TBA";
+ break;
+
+ case 0140610:
+ util::stream_format(stream, "%-6s'%06o", "BLE", opcodes.r16(pc + 1));
+ return 2 | STEP_COND | SUPPORTED;
+
+ case 0140611:
+ util::stream_format(stream, "%-6s'%06o", "BGT", opcodes.r16(pc + 1));
+ return 2 | STEP_COND | SUPPORTED;
+
+ case 0140612:
+ util::stream_format(stream, "%-6s'%06o", "BEQ", opcodes.r16(pc + 1));
+ return 2 | STEP_COND | SUPPORTED;
+
+ case 0140613:
+ util::stream_format(stream, "%-6s'%06o", "BNE", opcodes.r16(pc + 1));
+ return 2 | STEP_COND | SUPPORTED;
+
+ case 0140614:
+ util::stream_format(stream, "%-6s'%06o", "BLT", opcodes.r16(pc + 1));
+ return 2 | STEP_COND | SUPPORTED;
+
+ case 0140615:
+ util::stream_format(stream, "%-6s'%06o", "BGE", opcodes.r16(pc + 1));
+ return 2 | STEP_COND | SUPPORTED;
+
+ case 0140700:
+ util::stream_format(stream, "%-6s'%06o", "BLLE", opcodes.r16(pc + 1));
+ return 2 | STEP_COND | SUPPORTED;
+
+ case 0140701:
+ util::stream_format(stream, "%-6s'%06o", "BLGT", opcodes.r16(pc + 1));
+ return 2 | STEP_COND | SUPPORTED;
+
+ case 0140702:
+ util::stream_format(stream, "%-6s'%06o", "BLEQ", opcodes.r16(pc + 1));
+ return 2 | STEP_COND | SUPPORTED;
+
+ case 0140703:
+ util::stream_format(stream, "%-6s'%06o", "BLNE", opcodes.r16(pc + 1));
+ return 2 | STEP_COND | SUPPORTED;
+
+ case 0140724:
+ util::stream_format(stream, "%-6s'%06o", "BDY", opcodes.r16(pc + 1));
+ return 2 | STEP_COND | SUPPORTED;
+
+ case 0140734:
+ util::stream_format(stream, "%-6s'%06o", "BDX", opcodes.r16(pc + 1));
+ return 2 | STEP_COND | SUPPORTED;
+
+ case 0141000:
+ stream << "ADDL";
+ break;
+
+ case 0141034:
+ stream << "TXA";
+ break;
+
+ case 0141110:
+ stream << "LFLT";
+ break;
+
+ case 0141111:
+ stream << "LFLE";
+ break;
+
+ case 0141112:
+ stream << "LFNE";
+ break;
+
+ case 0141113:
+ stream << "LFEQ";
+ break;
+
+ case 0141114:
+ stream << "LFGE";
+ break;
+
+ case 0141115:
+ stream << "LFGT";
+ break;
+
+ case 0141124:
+ stream << "TYA";
+ break;
+
+ case 0141210:
+ stream << "TCL";
+ break;
+
+ case 0141324:
+ util::stream_format(stream, "%-6s'%06o", "BIY", opcodes.r16(pc + 1));
+ return 2 | STEP_COND | SUPPORTED;
+
+ case 0141334:
+ util::stream_format(stream, "%-6s'%06o", "BIX", opcodes.r16(pc + 1));
+ return 2 | STEP_COND | SUPPORTED;
+
+ case 0141404:
+ stream << "CRE";
+ break;
+
+ case 0141410:
+ stream << "CRLE";
+ break;
+
+ case 0141414:
+ stream << "ILE";
+ break;
+
+ case 0141500:
+ stream << "LCLT";
+ break;
+
+ case 0141501:
+ stream << "LCLE";
+ break;
+
+ case 0141502:
+ stream << "LCNE";
+ break;
+
+ case 0141503:
+ stream << "LCEQ";
+ break;
+
+ case 0141504:
+ stream << "LCGE";
+ break;
+
+ case 0141505:
+ stream << "LCGT";
+ break;
+
+ case 0141511:
+ stream << "LLLE";
+ break;
+
+ case 0141512:
+ stream << "LLNE";
+ break;
+
+ case 0141513:
+ stream << "LLEQ";
+ break;
+
+ case 0141515:
+ stream << "LLGT";
+ break;
+
+ case 0141600:
+ util::stream_format(stream, "%-6s'%06o", "BCLE", opcodes.r16(pc + 1));
+ return 2 | STEP_COND | SUPPORTED;
+
+ case 0141601:
+ util::stream_format(stream, "%-6s'%06o", "BCGT", opcodes.r16(pc + 1));
+ return 2 | STEP_COND | SUPPORTED;
+
+ case 0141602:
+ util::stream_format(stream, "%-6s'%06o", "BCEQ", opcodes.r16(pc + 1));
+ return 2 | STEP_COND | SUPPORTED;
+
+ case 0141603:
+ util::stream_format(stream, "%-6s'%06o", "BCNE", opcodes.r16(pc + 1));
+ return 2 | STEP_COND | SUPPORTED;
+
+ case 0141604:
+ util::stream_format(stream, "%-6s'%06o", "BCLT", opcodes.r16(pc + 1));
+ return 2 | STEP_COND | SUPPORTED;
+
+ case 0141605:
+ util::stream_format(stream, "%-6s'%06o", "BCGE", opcodes.r16(pc + 1));
+ return 2 | STEP_COND | SUPPORTED;
+
+ case 0141610:
+ util::stream_format(stream, "%-6s'%06o", "BFLE", opcodes.r16(pc + 1));
+ return 2 | STEP_COND | SUPPORTED;
+
+ case 0141611:
+ util::stream_format(stream, "%-6s'%06o", "BFGT", opcodes.r16(pc + 1));
+ return 2 | STEP_COND | SUPPORTED;
+
+ case 0141612:
+ util::stream_format(stream, "%-6s'%06o", "BFEQ", opcodes.r16(pc + 1));
+ return 2 | STEP_COND | SUPPORTED;
+
+ case 0141613:
+ util::stream_format(stream, "%-6s'%06o", "BFNE", opcodes.r16(pc + 1));
+ return 2 | STEP_COND | SUPPORTED;
+
+ case 0141614:
+ util::stream_format(stream, "%-6s'%06o", "BFLT", opcodes.r16(pc + 1));
+ return 2 | STEP_COND | SUPPORTED;
+
+ case 0141615:
+ util::stream_format(stream, "%-6s'%06o", "BFGE", opcodes.r16(pc + 1));
+ return 2 | STEP_COND | SUPPORTED;
+
+ case 0141704:
+ util::stream_format(stream, "%-6s'%06o", "BCS", opcodes.r16(pc + 1));
+ return 2 | STEP_COND | SUPPORTED;
+
+ case 0141705:
+ util::stream_format(stream, "%-6s'%06o", "BCR", opcodes.r16(pc + 1));
+ return 2 | STEP_COND | SUPPORTED;
+
+ case 0141706:
+ util::stream_format(stream, "%-6s'%06o", "BLS", opcodes.r16(pc + 1));
+ return 2 | STEP_COND | SUPPORTED;
+
+ case 0141707:
+ util::stream_format(stream, "%-6s'%06o", "BLR", opcodes.r16(pc + 1));
+ return 2 | STEP_COND | SUPPORTED;
+
+ case 0141710:
+ util::stream_format(stream, "%-6s'%06o", "BMGT", opcodes.r16(pc + 1));
+ return 2 | STEP_COND | SUPPORTED;
+
+ case 0141711:
+ util::stream_format(stream, "%-6s'%06o", "BMLE", opcodes.r16(pc + 1));
+ return 2 | STEP_COND | SUPPORTED;
+
+ case 0141714:
+ util::stream_format(stream, "%-6s", "RTQ");
+ format_ap(stream, opcodes.r32(pc + 1));
+ return 3 | SUPPORTED;
+
+ case 0141715:
+ util::stream_format(stream, "%-6s", "RBQ");
+ format_ap(stream, opcodes.r32(pc + 1));
+ return 3 | SUPPORTED;
+
+ case 0141716:
+ util::stream_format(stream, "%-6s", "ABQ");
+ format_ap(stream, opcodes.r32(pc + 1));
+ return 3 | SUPPORTED;
+
+ case 0141717:
+ util::stream_format(stream, "%-6s", "ATQ");
+ format_ap(stream, opcodes.r32(pc + 1));
+ return 3 | SUPPORTED;
+
+ case 0141757:
+ util::stream_format(stream, "%-6s", "TSTQ");
+ format_ap(stream, opcodes.r32(pc + 1));
+ return 3 | SUPPORTED;
+
+ default:
+ return dasm_generic_prime(stream, inst);
+ }
+ return 1 | SUPPORTED;
+ }
+}
diff --git a/src/devices/cpu/ddp516/ddp516d.h b/src/devices/cpu/ddp516/ddp516d.h
new file mode 100644
index 00000000000..705ee3f6ff0
--- /dev/null
+++ b/src/devices/cpu/ddp516/ddp516d.h
@@ -0,0 +1,87 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+
+#ifndef MAME_CPU_DDP516_DDP516D_H
+#define MAME_CPU_DDP516_DDP516D_H
+
+#pragma once
+
+class ddp516_disassembler : public util::disasm_interface
+{
+public:
+ // construction/destruction
+ ddp516_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 &params) override;
+
+ // formatting and disassembly helpers
+ void format_disp(std::ostream &stream, u16 disp) const;
+ offs_t dasm_skip(std::ostream &stream, u16 inst) const;
+ offs_t dasm_generic(std::ostream &stream, u16 inst) const;
+};
+
+class prime_disassembler : public ddp516_disassembler
+{
+protected:
+ // construction/destruction
+ prime_disassembler(u8 mode);
+
+ // util::disasm_interface overrides
+ virtual offs_t disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer &params) override;
+
+ // disassembly helpers
+ offs_t dasm_generic_prime(std::ostream &stream, u16 inst) const;
+
+private:
+ const u8 c_mode_key;
+};
+
+class prime16s_disassembler : public prime_disassembler
+{
+public:
+ // construction/destruction
+ prime16s_disassembler();
+};
+
+class prime32s_disassembler : public prime_disassembler
+{
+public:
+ // construction/destruction
+ prime32s_disassembler();
+};
+
+class prime32r_disassembler : public prime_disassembler
+{
+public:
+ // construction/destruction
+ prime32r_disassembler();
+};
+
+class prime64r_disassembler : public prime_disassembler
+{
+public:
+ // construction/destruction
+ prime64r_disassembler();
+};
+
+class prime64v_disassembler : public prime_disassembler
+{
+public:
+ // construction/destruction
+ prime64v_disassembler();
+
+protected:
+ // util::disasm_interface overrides
+ virtual u32 interface_flags() const override;
+ virtual u32 page_address_bits() const override;
+ virtual offs_t disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer &params) override;
+
+private:
+ // formatting helper
+ void format_ap(std::ostream &stream, u32 ap) const;
+};
+
+#endif // MAME_CPU_DDP516_DDP516D_H