diff options
Diffstat (limited to 'src/devices/cpu/hp2100/hp2100d.cpp')
-rw-r--r-- | src/devices/cpu/hp2100/hp2100d.cpp | 656 |
1 files changed, 656 insertions, 0 deletions
diff --git a/src/devices/cpu/hp2100/hp2100d.cpp b/src/devices/cpu/hp2100/hp2100d.cpp new file mode 100644 index 00000000000..ded7bfcdd48 --- /dev/null +++ b/src/devices/cpu/hp2100/hp2100d.cpp @@ -0,0 +1,656 @@ +// license:BSD-3-Clause +// copyright-holders:AJR +/*************************************************************************** + + Hewlett-Packard HP2100 disassembler + +***************************************************************************/ + +#include "emu.h" +#include "hp2100d.h" + +hp2100_disassembler::hp2100_disassembler() + : util::disasm_interface() +{ +} + +u32 hp2100_disassembler::opcode_alignment() const +{ + return 1; +} + +void hp2100_disassembler::format_address(std::ostream &stream, u16 addr) const +{ + if ((addr & 077776) == 0) + stream << char('A' + BIT(addr, 0)); + else + util::stream_format(stream, "%05oB", addr & 077777); + + // Indirect addressing? + if (BIT(addr, 15)) + stream << ",I"; +} + +void hp2100_disassembler::format_sc(std::ostream &stream, u8 sc) const +{ + util::stream_format(stream, "%o", sc); + if (sc > 7) + stream << 'B'; +} + +// Memory reference group +offs_t hp2100_disassembler::dasm_mrg(std::ostream &stream, u16 inst, offs_t pc) const +{ + offs_t flags = SUPPORTED; + switch (BIT(inst, 12, 3)) + { + case 1: + if (BIT(inst, 11)) + { + stream << "JSB "; + flags |= STEP_OVER; + } + else + stream << "AND "; + break; + + case 2: + if (BIT(inst, 11)) + { + stream << "JMP "; + if (BIT(inst, 15)) + flags |= STEP_OUT; + } + else + stream << "XOR "; + break; + + case 3: + if (BIT(inst, 11)) + { + stream << "ISZ "; + flags |= STEP_COND; + } + else + stream << "IOR "; + break; + + case 4: + util::stream_format(stream, "AD%c ", cab(inst)); + break; + + case 5: + util::stream_format(stream, "CP%c ", cab(inst)); + flags |= STEP_COND; + break; + + case 6: + util::stream_format(stream, "LD%c ", cab(inst)); + break; + + case 7: + util::stream_format(stream, "ST%c ", cab(inst)); + break; + } + + // Page zero or current page + format_address(stream, (BIT(inst, 10) ? (pc & 077600) : 0) | (inst & 0100177)); + + return 1 | flags; +} + +const char *const hp2100_disassembler::s_shift_ops[2][8] = +{ + { "ALS", "ARS", "RAR", "RAL", "ALR", "ERA", "ELA", "ALF" }, + { "BLS", "BRS", "RBR", "RBL", "BLR", "ERB", "ELB", "BLF" } +}; + +// Shift-rotate group +offs_t hp2100_disassembler::dasm_srg(std::ostream &stream, u16 inst) const +{ + offs_t flags = SUPPORTED; + + if ((inst & 001070) == 0) + { + if (inst == 0) + stream << "NOP"; + else + util::stream_format(stream, "OCT %o", inst); + } + else + { + if (BIT(inst, 9)) + stream << s_shift_ops[BIT(inst, 11)][BIT(inst, 6, 3)]; + + if (BIT(inst, 5)) + { + if (BIT(inst, 9)) + stream << ','; + stream << "CLE"; + } + + // Skip on LSB + if (BIT(inst, 3)) + { + if ((inst & 001040) != 0) + stream << ','; + util::stream_format(stream, "SL%c", cab(inst)); + flags |= STEP_COND; + } + + if (BIT(inst, 4)) + { + if ((inst & 001050) != 0) + stream << ','; + stream << s_shift_ops[BIT(inst, 11)][BIT(inst, 0, 3)]; + } + } + + return 1 | flags; +} + +// Alter-skip group +offs_t hp2100_disassembler::dasm_asg(std::ostream &stream, u16 inst) const +{ + offs_t flags = SUPPORTED; + + if ((inst & 01777) == 0) + util::stream_format(stream, "OCT %o", inst); + else + { + if (BIT(inst, 8, 2) != 0) + util::stream_format(stream, "C%c%c", "LMC"[BIT(inst, 8, 2) - 1], cab(inst)); + + // Extend skip + if (BIT(inst, 5)) + { + if (BIT(inst, 8, 2) != 0) + stream << ','; + stream << "SEZ"; + flags |= STEP_COND; + } + + if (BIT(inst, 6, 2) != 0) + { + if ((inst & 01440) != 0) + stream << ','; + util::stream_format(stream, "C%cE", "LMC"[BIT(inst, 6, 2) - 1]); + } + + // Accumulator skips + if (BIT(inst, 4)) + { + if ((inst & 01740) != 0) + stream << ','; + util::stream_format(stream, "SS%c", cab(inst)); + flags |= STEP_COND; + } + if (BIT(inst, 3)) + { + if ((inst & 01760) != 0) + stream << ','; + util::stream_format(stream, "SL%c", cab(inst)); + flags |= STEP_COND; + } + if (BIT(inst, 2)) + { + if ((inst & 01770) != 0) + stream << ','; + util::stream_format(stream, "IN%c", cab(inst)); + flags |= STEP_COND; + } + if (BIT(inst, 1)) + { + if ((inst & 01774) != 0) + stream << ','; + util::stream_format(stream, "SZ%c", cab(inst)); + flags |= STEP_COND; + } + + // Reverse skip sense + if (BIT(inst, 0)) + { + if ((inst & 01776) != 0) + stream << ','; + stream << "RSS"; + } + } + + return 1 | flags; +} + +// Input-output group +offs_t hp2100_disassembler::dasm_iog(std::ostream &stream, u16 inst) const +{ + u8 sc = BIT(inst, 0, 6); + offs_t flags = SUPPORTED; + + switch (BIT(inst, 6, 3)) + { + case 0: + stream << "HLT"; + if (sc != 0) + { + stream << ' '; + format_sc(stream, sc); + } + break; + + case 1: + if (sc == 1) + { + // Clear or set overflow flag + if (BIT(inst, 9)) + stream << "CLO"; + else + stream << "STO"; + } + else + { + if (BIT(inst, 9)) + stream << "CLF "; + else + stream << "STF "; + format_sc(stream, sc); + } + break; + + case 2: + if (sc == 1) + stream << "SOC"; + else + { + stream << "SFC "; + format_sc(stream, sc); + } + flags |= STEP_COND; + break; + + case 3: + if (sc == 1) + stream << "SOS"; + else + { + stream << "SFS "; + format_sc(stream, sc); + } + flags |= STEP_COND; + break; + + case 4: + util::stream_format(stream, "MI%c ", cab(inst)); + format_sc(stream, sc); + break; + + case 5: + util::stream_format(stream, "LI%c ", cab(inst)); + format_sc(stream, sc); + break; + + case 6: + util::stream_format(stream, "OT%c ", cab(inst)); + format_sc(stream, sc); + break; + + case 7: + if (BIT(inst, 11)) + stream << "CLC "; + else + stream << "STC "; + format_sc(stream, sc); + break; + } + + // Clear flag + if (BIT(inst, 9) && BIT(inst, 6, 3) != 1) + stream << ",C"; + + return 1 | flags; +} + +// Macro instructions (including extended arithmetic group and 12901A floating-point instructions) +offs_t hp2100_disassembler::dasm_mac(std::ostream &stream, u16 inst, offs_t pc, const hp2100_disassembler::data_buffer &opcodes) const +{ + switch (inst & 05760) + { + case 00020: case 01020: + { + u8 n = BIT(inst, 0, 4); + util::stream_format(stream, "AS%c %d", BIT(inst, 9) ? 'R' : 'L', n == 0 ? 16 : n); + return 1 | SUPPORTED; + } + + case 00040: case 01040: + { + u8 n = BIT(inst, 0, 4); + util::stream_format(stream, "LS%c %d", BIT(inst, 9) ? 'R' : 'L', n == 0 ? 16 : n); + return 1 | SUPPORTED; + } + + case 00100: case 01100: + { + u8 n = BIT(inst, 0, 4); + util::stream_format(stream, "RR%c %d", BIT(inst, 9) ? 'R' : 'L', n == 0 ? 16 : n); + return 1 | SUPPORTED; + } + + case 00200: + stream << "MPY "; + format_address(stream, opcodes.r16(pc + 1)); + return 2 | SUPPORTED; + + case 00400: + stream << "DIV "; + format_address(stream, opcodes.r16(pc + 1)); + return 2 | SUPPORTED; + + case 04000: + stream << "DLD "; + format_address(stream, opcodes.r16(pc + 1)); + return 2 | SUPPORTED; + + case 04400: + stream << "DST "; + format_address(stream, opcodes.r16(pc + 1)); + return 2 | SUPPORTED; + + case 05000: + stream << "FAD "; + format_address(stream, opcodes.r16(pc + 1)); + return 2 | SUPPORTED; + + case 05020: + stream << "FSB "; + format_address(stream, opcodes.r16(pc + 1)); + return 2 | SUPPORTED; + + case 05040: + stream << "FML "; + format_address(stream, opcodes.r16(pc + 1)); + return 2 | SUPPORTED; + + case 05060: + stream << "FDV "; + format_address(stream, opcodes.r16(pc + 1)); + return 2 | SUPPORTED; + + case 05100: + stream << "FIX"; + return 1 | SUPPORTED; + + case 05120: + stream << "FLT"; + return 1 | SUPPORTED; + + default: + util::stream_format(stream, "MAC %oB", inst & 05777); + return 1 | SUPPORTED; + } +} + +offs_t hp21mx_disassembler::dasm_mac(std::ostream &stream, u16 inst, offs_t pc, const hp2100_disassembler::data_buffer &opcodes) const +{ + if ((inst & 01740) == 01740) + { + // Extended instruction group + switch (inst & 04027) + { + case 0000: case 04000: + util::stream_format(stream, "S%c%c ", cab(inst), xy(inst)); + format_address(stream, opcodes.r16(pc + 1)); + return 2 | SUPPORTED; + + case 0001: case 04001: + util::stream_format(stream, "C%c%c", cab(inst), xy(inst)); + return 1 | SUPPORTED; + + case 0002: case 04002: + util::stream_format(stream, "L%c%c ", cab(inst), xy(inst)); + format_address(stream, opcodes.r16(pc + 1)); + return 2 | SUPPORTED; + + case 04003: + util::stream_format(stream, "ST%c ", xy(inst)); + format_address(stream, opcodes.r16(pc + 1)); + return 2 | SUPPORTED; + + case 0004: case 04004: + util::stream_format(stream, "C%c%c", xy(inst), cab(inst)); + return 1 | SUPPORTED; + + case 04005: + util::stream_format(stream, "LD%c ", xy(inst)); + format_address(stream, opcodes.r16(pc + 1)); + return 2 | SUPPORTED; + + case 04006: + util::stream_format(stream, "AD%c ", xy(inst)); + format_address(stream, opcodes.r16(pc + 1)); + return 2 | SUPPORTED; + + case 0007: case 04007: + util::stream_format(stream, "X%c%c", cab(inst), xy(inst)); + return 1 | SUPPORTED; + + case 04020: + util::stream_format(stream, "IS%c", xy(inst)); + return 1 | STEP_COND | SUPPORTED; + + case 04021: + util::stream_format(stream, "DS%c", xy(inst)); + return 1 | STEP_COND | SUPPORTED; + + case 04022: + if (BIT(inst, 3)) + { + stream << "JPY "; + format_address(stream, opcodes.r16(pc + 1) & 077777); + } + else + { + stream << "JLY "; + format_address(stream, opcodes.r16(pc + 1)); + } + return 2 | SUPPORTED; + + case 04023: + if (BIT(inst, 3)) + { + stream << "SBS "; + format_address(stream, opcodes.r16(pc + 1)); + stream << ','; + format_address(stream, opcodes.r16(pc + 2)); + return 3 | SUPPORTED; + } + else + { + stream << "LBT"; + return 1 | SUPPORTED; + } + + case 04024: + if (BIT(inst, 3)) + { + stream << "CBS "; + format_address(stream, opcodes.r16(pc + 1)); + stream << ','; + format_address(stream, opcodes.r16(pc + 2)); + return 3 | STEP_COND | SUPPORTED; + } + else + { + stream << "SBT"; + return 1 | SUPPORTED; + } + + case 04025: + if (BIT(inst, 3)) + { + stream << "TBS "; + format_address(stream, opcodes.r16(pc + 1)); + stream << ','; + format_address(stream, opcodes.r16(pc + 2)); + return 3 | STEP_COND | SUPPORTED; + } + else + { + stream << "MBT "; + format_address(stream, opcodes.r16(pc + 1)); + return 3 | SUPPORTED; // one extra word reserved for microcode use + } + + case 04026: + if (BIT(inst, 3)) + stream << "CMW "; + else + stream << "CBT "; + format_address(stream, opcodes.r16(pc + 1)); + return 3 | STEP_COND | SUPPORTED; // one extra word reserved for microcode use + + case 04027: + if (BIT(inst, 3)) + { + stream << "MVW "; + format_address(stream, opcodes.r16(pc + 1)); + return 3 | SUPPORTED; // one extra word reserved for microcode use + } + else + { + stream << "SBT"; + return 1 | STEP_COND | SUPPORTED; + } + + default: + util::stream_format(stream, "MAC %oB", inst & 05777); + return 1 | SUPPORTED; + } + } + else if ((inst & 01740) == 01700) + { + // Dynamic Mapping System + switch (inst & 04037) + { + case 04002: + stream << "MBI"; + return 1 | SUPPORTED; + + case 04003: + stream << "MBF"; + return 1 | SUPPORTED; + + case 04004: + stream << "MBW"; + return 1 | SUPPORTED; + + case 04005: + stream << "MWI"; + return 1 | SUPPORTED; + + case 04006: + stream << "MWF"; + return 1 | SUPPORTED; + + case 04007: + stream << "MWW"; + return 1 | SUPPORTED; + + case 0010: case 04010: + util::stream_format(stream, "SY%c", cab(inst)); + return 1 | SUPPORTED; + + case 0011: case 04011: + util::stream_format(stream, "US%c", cab(inst)); + return 1 | SUPPORTED; + + case 0012: case 0013: case 04012: case 04013: + util::stream_format(stream, "P%c%c", 'A' + BIT(inst, 0), cab(inst)); + return 1 | SUPPORTED; + + case 04014: + stream << "SSM "; + format_address(stream, opcodes.r16(pc + 1)); + return 2 | SUPPORTED; + + case 04015: + stream << "JRS "; + format_address(stream, opcodes.r16(pc + 1)); + stream << ','; + format_address(stream, opcodes.r16(pc + 2)); + return 3 | SUPPORTED; + + case 04020: + stream << "XMM"; + return 1 | SUPPORTED; + + case 04021: + stream << "XMS"; + return 1 | SUPPORTED; + + case 0022: case 04022: + util::stream_format(stream, "XM%c", cab(inst)); + return 1 | SUPPORTED; + + case 0024: case 04024: + util::stream_format(stream, "XL%c", cab(inst)); + return 1 | SUPPORTED; + + case 0025: case 04025: + util::stream_format(stream, "XS%c", cab(inst)); + return 1 | SUPPORTED; + + case 0026: case 04026: + util::stream_format(stream, "XC%c", cab(inst)); + return 1 | STEP_COND | SUPPORTED; + + case 0027: case 04027: + util::stream_format(stream, "LF%c ", cab(inst)); + format_address(stream, opcodes.r16(pc + 1)); + return 2 | SUPPORTED; + + case 0030: case 04030: + util::stream_format(stream, "RS%c", cab(inst)); + return 1 | SUPPORTED; + + case 0031: case 04031: + util::stream_format(stream, "RV%c", cab(inst)); + return 1 | SUPPORTED; + + case 04032: case 04034: case 04036: + util::stream_format(stream, "%cJP ", "DSU"[BIT(inst, 1, 2) - 1]); + format_address(stream, opcodes.r16(pc + 1)); + return 2 | SUPPORTED; + + case 04033: case 04035: case 04037: + util::stream_format(stream, "%cJS ", "DSU"[BIT(inst, 1, 2) - 1]); + format_address(stream, opcodes.r16(pc + 1)); + return 2 | STEP_OVER | SUPPORTED; + + default: + util::stream_format(stream, "MAC %oB", inst & 05777); + return 1 | SUPPORTED; + } + } + else + return hp2100_disassembler::dasm_mac(stream, inst, pc, opcodes); +} + +offs_t hp2100_disassembler::disassemble(std::ostream &stream, offs_t pc, const hp2100_disassembler::data_buffer &opcodes, const hp2100_disassembler::data_buffer ¶ms) +{ + u16 inst = opcodes.r16(pc); + if (BIT(inst, 12, 3) != 0) + return dasm_mrg(stream, inst, pc); + else if (BIT(inst, 15)) + { + if (BIT(inst, 10)) + return dasm_iog(stream, inst); + else + return dasm_mac(stream, inst, pc, opcodes); + } + else + { + if (BIT(inst, 10)) + return dasm_asg(stream, inst); + else + return dasm_srg(stream, inst); + } +} |