summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/vt61/vt61dasm.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/vt61/vt61dasm.cpp')
-rw-r--r--src/devices/cpu/vt61/vt61dasm.cpp275
1 files changed, 275 insertions, 0 deletions
diff --git a/src/devices/cpu/vt61/vt61dasm.cpp b/src/devices/cpu/vt61/vt61dasm.cpp
new file mode 100644
index 00000000000..1471cf0a918
--- /dev/null
+++ b/src/devices/cpu/vt61/vt61dasm.cpp
@@ -0,0 +1,275 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+/***************************************************************************
+
+ DEC VT61 microcode disassembler
+
+ No microprogram source listing appears to have been published by DEC,
+ nor any instruction reference other than the decode signal references
+ in the schematics. The instruction format should not be regarded as
+ official, though it draws on some of DEC's PDP assembly languages.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "vt61dasm.h"
+
+vt61_disassembler::vt61_disassembler()
+ : util::disasm_interface()
+{
+}
+
+const char *const vt61_disassembler::s_opr_a[8] = {
+ "NOP", // NO OP A
+ "IAC", // INC AC
+ "LIR", // LD IR
+ "IMA", // INC MA
+ "SMD", // SHIFT MDR
+ "JMP0", // CLR PC
+ "CMPC8", // COMP PC 8
+ "LDR" // LD RAM
+};
+
+const char *const vt61_disassembler::s_opr_b[16] = {
+ "OPR", // NO OP B
+ "SPARE",
+ "RC", // RESET C FLAG
+ "SPARE",
+ "SPARE",
+ "LMISC", // LD MISC FLAG
+ "LLED", // LD LED FLAG
+ "LMOD", // LD MODEM FLAG
+ "SKCLK", // SET KEYCLICK
+ "LINTRC", // LD INTRPT CONTROL
+ "SPARE",
+ "CNBR", // CLR NBR
+ "LSYNC", // LD SYNC + CLR NBX
+ "PLD", // PLD
+ "CVSR", // CLR VID SERV REQ
+ "ENVID" // ENABLE VID LOAD
+};
+
+const char *const vt61_disassembler::s_sources[12] = {
+ "AC", // SEL AC
+ "STAT1", // SEL STATUS 1
+ "SW", // SEL SWITCHES
+ "CAS1", // SEL CAS 1
+ "CAS2", // SEL CAS 2
+ "RAM", // SEL RAM
+ "IDR", // SEL IDR
+ "UART", // SEL UART
+ "SPARE",
+ "TBSW", // TEST BOX SWITCH
+ "invalid", // SEL SPM LO
+ "invalid" // SEL SPM HI
+};
+
+const char *const vt61_disassembler::s_conditions[32][2] = {
+ { "NINTR1", "INTR1" }, // INTR 1 L
+ { "NBXF", "NBXT" }, // NBX L
+ { "NBRF", "NBRT" }, // NBR L
+ { "NF1", "F1" }, // F1 L
+ { "NF2", "F2" }, // F2 L
+ { "NCF", "CF" }, // C L
+ { "NURF", "URF" }, // UART R FLAG L
+ { "NUTB", "UTB" }, // UART T BUFF L
+ { "NXOFF", "XOFF" }, // DO X OFF L
+ { "NGOSR", "GOSR" }, // GOUT SER RQ L
+ { "NF3", "F3" }, // F3 L
+ { "NINTR2", "INTR2" }, // INTR 2 L
+ { "KEYUP", "KEYDN" }, // KEY DOWN L
+ { "NPWRUP", "PWRUP" }, // PWR UP L
+ { "NSYNC", "SYNC" }, // SYNC ENA L
+ { "PE", "NPE" }, // PARITY ERROR H
+ { "BZY", "NBZY" }, // MEM BZY H
+ { "EQ", "NE" }, // EQUAL H
+ { "CC", "CS" }, // CARRY OUT L
+ { "MDOFO", "MDOFZ" }, // MDR O.F. OUT H
+ { "NCSR", "CSR" }, // COPIER SER REQ L
+ { "NCPCF", "CPCF" }, // C-PCF L
+ { "T", "F" }, // TRUE H
+ { "NVSR", "VSR" }, // VID SERV REQ L
+ { "?H", "?L" },
+ { "?H", "?L" },
+ { "?H", "?L" },
+ { "?H", "?L" },
+ { "?H", "?L" },
+ { "?H", "?L" },
+ { "?H", "?L" },
+ { "?H", "?L" }
+};
+
+u32 vt61_disassembler::opcode_alignment() const
+{
+ return 1;
+}
+
+u32 vt61_disassembler::interface_flags() const
+{
+ return PAGED;
+}
+
+u32 vt61_disassembler::page_address_bits() const
+{
+ return 8;
+}
+
+void vt61_disassembler::dasm_spr(std::ostream &stream, u8 r)
+{
+ if (BIT(r, 4))
+ util::stream_format(stream, "IR%d", r & 9);
+ else
+ util::stream_format(stream, "R%d", r);
+}
+
+void vt61_disassembler::dasm_source(std::ostream &stream, u16 inst)
+{
+ if ((inst & 003000) == 003000)
+ util::stream_format(stream, "#%03o", inst & 000377);
+ else
+ {
+ if ((inst & 003400) == 002400 && (inst & 070000) != 070000)
+ dasm_spr(stream, (inst & 000170) >> 2 | (inst & 000200) >> 7);
+ else
+ stream << s_sources[(inst & 003600) >> 7];
+ if ((inst & 000007) != 0 && (inst & 0170000) != 0100000)
+ stream << "," << s_opr_a[inst & 000007];
+ }
+}
+
+offs_t vt61_disassembler::disassemble(std::ostream &stream, offs_t pc, const vt61_disassembler::data_buffer &opcodes, const vt61_disassembler::data_buffer &params)
+{
+ u16 inst = opcodes.r16(pc);
+ offs_t flags = SUPPORTED;
+
+ if (!BIT(inst, 15))
+ {
+ if ((inst & 074000) == 054000)
+ {
+ stream << "LDU";
+ if ((inst & 000007) != 0 && (inst & 003000) != 003000)
+ {
+ stream << " " << s_opr_a[inst & 000007];
+ if ((inst & 000007) == 5)
+ flags |= STEP_OUT;
+ }
+ }
+ else
+ {
+ switch (inst & 070000)
+ {
+ case 000000:
+ stream << "LAC ";
+ break;
+
+ case 040000:
+ stream << "LMA " << (BIT(inst, 11) ? "HI," : "LO,");
+ break;
+
+ case 050000:
+ stream << "JMP ";
+ break;
+
+ case 060000:
+ if (BIT(inst, 11))
+ stream << "LMD ";
+ else
+ stream << "CAS3 ";
+ break;
+
+ case 070000:
+ stream << "LSP ";
+ dasm_spr(stream, (inst & 000170) >> 2 | (inst & 004000) >> 11);
+ stream << ",";
+ break;
+
+ default:
+ stream << "LD? ";
+ break;
+ }
+
+ dasm_source(stream, inst);
+ if ((inst & 000007) == 5 && (inst & 003000) != 003000)
+ flags |= STEP_OUT;
+ }
+ }
+ else if (BIT(inst, 14))
+ {
+ util::stream_format(stream, "BR %s,%03o", s_conditions[(inst & 017400) >> 8][BIT(inst, 13)], inst & 000377);
+ }
+ else if (BIT(inst, 13))
+ {
+ if ((inst & 007407) == 0)
+ stream << "NOP";
+ else
+ {
+ stream << s_opr_b[(inst & 007400) >> 8];
+ if ((inst & 000007) != 0)
+ {
+ stream << " " << s_opr_a[inst & 000007];
+ if ((inst & 000207) == 000204)
+ stream << "A"; // ENABLE MDR A (CAS DATA)
+ if ((inst & 000107) == 000104)
+ stream << "B"; // ENABLE MDR B (SYNC DATA IN)
+ if ((inst & 000007) == 5)
+ flags |= STEP_OUT;
+ }
+ }
+ }
+ else if (BIT(inst, 12))
+ {
+ stream << "CMP ";
+ dasm_source(stream, inst);
+ if ((inst & 000007) == 5 && (inst & 003000) != 003000)
+ flags |= STEP_OUT;
+ }
+ else switch (inst & 000007)
+ {
+ case 0:
+ stream << "CMA";
+ break;
+
+ case 1:
+ stream << "ORA ";
+ dasm_source(stream, inst);
+ break;
+
+ case 2:
+ stream << "XOR ";
+ dasm_source(stream, inst);
+ break;
+
+ case 3:
+ stream << "AND ";
+ dasm_source(stream, inst);
+ break;
+
+ case 4:
+ stream << "DCA";
+ if (BIT(inst, 11))
+ stream << " C";
+ break;
+
+ case 5:
+ stream << "ADD ";
+ if (BIT(inst, 11))
+ stream << "C,";
+ dasm_source(stream, inst);
+ break;
+
+ case 6:
+ stream << "SUB ";
+ if (BIT(inst, 11))
+ stream << "C,";
+ dasm_source(stream, inst);
+ break;
+
+ case 7:
+ stream << "SLA";
+ if (BIT(inst, 11))
+ stream << " C";
+ break;
+ }
+
+ return 1 | flags;
+}