diff options
Diffstat (limited to 'src/devices/cpu/f2mc16/f2mc16d.cpp')
-rw-r--r-- | src/devices/cpu/f2mc16/f2mc16d.cpp | 1641 |
1 files changed, 1641 insertions, 0 deletions
diff --git a/src/devices/cpu/f2mc16/f2mc16d.cpp b/src/devices/cpu/f2mc16/f2mc16d.cpp new file mode 100644 index 00000000000..90aaf712ca5 --- /dev/null +++ b/src/devices/cpu/f2mc16/f2mc16d.cpp @@ -0,0 +1,1641 @@ +// license:BSD-3-Clause +// copyright-holders:AJR +/*************************************************************************** + + Fujitsu F²MC-16 family disassembler + +***************************************************************************/ + +#include "emu.h" +#include "f2mc16d.h" + +f2mc16_disassembler::f2mc16_disassembler() + : util::disasm_interface() +{ +} + +const std::string_view f2mc16_disassembler::s_segment_prefixes[4] = +{ + "PCB", "DTB", "ADB", "SPB" +}; + +const std::string_view f2mc16_disassembler::s_segment_registers[6] = +{ + "DTB", "ADB", "SSB", "USB", "DPR", "SPB" +}; + +const std::string_view f2mc16_disassembler::s_bit_ops[8] = +{ + "MOVB", "MOVB", + "CLRB", "SETB", + "BBC", "BBS", + "WBTS", "WBTC" +}; + +const std::string_view f2mc16_disassembler::s_movs_ops[4] = +{ + "MOVSI", "MOVSD", "MOVSWI", "MOVSWD" +}; + +const std::string_view f2mc16_disassembler::s_sceq_ops[4] = +{ + "SCEQI", "SCEQD", "SCWEQI", "SCWEQD" +}; + +const std::string_view f2mc16_disassembler::s_shift_ops[3][4] = +{ + { "LSLW", "???", "ASRW", "LSRW" }, + { "LSLL", "???", "ASRL", "LSRL" }, + { "LSL", "NRML", "ASR", "LSR" } +}; + +const std::string_view f2mc16_disassembler::s_movp_ops[4] = +{ + "MOVP", "MOVPX", "MOVPW", "MOVPL" +}; + +const std::string_view f2mc16_disassembler::s_bcc_ops[16] = +{ + "BZ", "BNZ", + "BC", "BNC", + "BN", "BP", + "BV", "BNV", + "BT", "BNT", + "BLT", "BGE", + "BLE", "BGT", + "BLS", "BHI" +}; + +offs_t f2mc16_disassembler::opcode_alignment() const +{ + return 1; +} + +u32 f2mc16_disassembler::interface_flags() const +{ + return PAGED; +} + +u32 f2mc16_disassembler::page_address_bits() const +{ + return 16; +} + +void f2mc16_disassembler::format_imm4(std::ostream &stream, u8 x) +{ + if (x > 9) + util::stream_format(stream, "#0x%X", x); + else + util::stream_format(stream, "#%d", x); +} + +void f2mc16_disassembler::format_imm8(std::ostream &stream, u8 x) +{ + util::stream_format(stream, "#0x%02X", x); +} + +void f2mc16_disassembler::format_imm16(std::ostream &stream, u16 x) +{ + util::stream_format(stream, "#0x%04X", x); +} + +void f2mc16_disassembler::format_imm32(std::ostream &stream, u32 x) +{ + util::stream_format(stream, "#0x%08X", x); +} + +void f2mc16_disassembler::format_imm_signed(std::ostream &stream, s32 x) +{ + stream << '#'; + if (x < 0) + { + stream << '-'; + x = -x; + } + if (u32(x) > 9) + util::stream_format(stream, "0x%X", u32(x)); + else + util::stream_format(stream, "%d", x); +} + +void f2mc16_disassembler::format_dir(std::ostream &stream, u8 segm, u8 addr) +{ + if (segm != 0) + util::stream_format(stream, "%s:", s_segment_prefixes[segm & 0x03]); + util::stream_format(stream, "S:0x%02X", addr); +} + +void f2mc16_disassembler::format_io(std::ostream &stream, u8 addr) +{ + util::stream_format(stream, "I:0x%02X", addr); +} + +void f2mc16_disassembler::format_addr16(std::ostream &stream, u8 segm, u16 addr) +{ + if (segm != 0) + util::stream_format(stream, "%s:", s_segment_prefixes[segm & 0x03]); + else + stream << "D:"; + util::stream_format(stream, "0x%04X", addr); +} + +void f2mc16_disassembler::format_dst16(std::ostream &stream, u16 addr) +{ + util::stream_format(stream, "0x%04X", addr); +} + +void f2mc16_disassembler::format_addr24(std::ostream &stream, u32 addr) +{ + util::stream_format(stream, "0x%06X", addr); +} + +void f2mc16_disassembler::format_rel(std::ostream &stream, offs_t pc, s8 disp) +{ + util::stream_format(stream, "0x%04X", (pc + disp) & 0xffff); +} + +void f2mc16_disassembler::format_rwdisp8(std::ostream &stream, u8 r, u8 segm, s8 disp) +{ + if (segm != 0) + util::stream_format(stream, "%s:", s_segment_prefixes[segm & 0x03]); + util::stream_format(stream, "@RW%d", r); + if (disp < 0) + { + stream << '-'; + disp = -disp; + } + else + stream << '+'; + if (u8(disp) > 9) + stream << "0x"; + util::stream_format(stream, "%X", u8(disp)); +} + +void f2mc16_disassembler::format_rwdisp16(std::ostream &stream, u8 r, u8 segm, u16 disp) +{ + if (segm != 0) + util::stream_format(stream, "%s:", s_segment_prefixes[segm & 0x03]); + util::stream_format(stream, "@RW%d+0x%04X", r, disp); +} + +void f2mc16_disassembler::format_rldisp8(std::ostream &stream, u8 r, s8 disp) +{ + util::stream_format(stream, "@RL%d", r); + if (disp < 0) + { + stream << '-'; + disp = -disp; + } + else + stream << '+'; + if (u8(disp) > 9) + stream << "0x"; + util::stream_format(stream, "%X", u8(disp)); +} + +void f2mc16_disassembler::format_spdisp8(std::ostream &stream, s8 disp) +{ + stream << "@SP"; + if (disp < 0) + { + stream << '-'; + disp = -disp; + } + else + stream << '+'; + if (u8(disp) > 9) + stream << "0x"; + util::stream_format(stream, "%X", u8(disp)); +} + +void f2mc16_disassembler::format_pcdisp16(std::ostream &stream, s16 disp) +{ + if (disp < 0) + { + stream << "@PC-"; + disp = -disp; + } + else + stream << "@PC+"; + if (u16(disp) > 9) + stream << "0x"; + util::stream_format(stream, "%X", u16(disp)); +} + +void f2mc16_disassembler::format_rlist(std::ostream &stream, u8 rlst) +{ + stream << '('; + + bool first = true; + int last = -1; + for (int i = 0; i <= 8; i++) + { + if (i != 8 && BIT(rlst, i)) + { + if (last == -1) + last = i; + } + else if (last != -1) + { + if (first) + first = false; + else + stream << ','; + util::stream_format(stream, "RW%d", last); + if (last != i - 1) + util::stream_format(stream, "-RW%d", i - 1); + last = -1; + } + } + + stream << ')'; +} + +u32 f2mc16_disassembler::dasm_ea8(std::ostream &stream, offs_t pc, u8 op2, u8 segm, const f2mc16_disassembler::data_buffer &opcodes) +{ + op2 &= 0x1f; + if (op2 < 0x08) + { + util::stream_format(stream, "R%d", op2); + return 0; + } + else if (op2 < 0x10) + { + if (segm != 0) + util::stream_format(stream, "%s:", s_segment_prefixes[segm & 0x03]); + util::stream_format(stream, "@RW%d", op2 & 0x03); + if (op2 >= 0x0c) + stream << '+'; + return 0; + } + else if (op2 < 0x18) + { + format_rwdisp8(stream, op2 & 0x07, segm, opcodes.r8(pc)); + return 1; + } + else if (op2 < 0x1c) + { + format_rwdisp16(stream, op2 & 0x03, segm, opcodes.r16(pc)); + return 2; + } + else if (op2 < 0x1e) + { + if (segm != 0) + util::stream_format(stream, "%s:", s_segment_prefixes[segm & 0x03]); + util::stream_format(stream, "@RW%d+RW7", op2 & 0x01); + return 0; + } + else if (op2 == 0x1e) + { + format_pcdisp16(stream, s16(opcodes.r16(pc))); + return 2; + } + else + { + format_addr16(stream, segm, opcodes.r16(pc)); + return 2; + } +} + +u32 f2mc16_disassembler::dasm_ea16(std::ostream &stream, offs_t pc, u8 op2, u8 segm, const f2mc16_disassembler::data_buffer &opcodes) +{ + if ((op2 & 0x18) == 0) + { + util::stream_format(stream, "RW%d", op2 & 0x07); + return 0; + } + else + return dasm_ea8(stream, pc, op2, segm, opcodes); +} + +u32 f2mc16_disassembler::dasm_ea32(std::ostream &stream, offs_t pc, u8 op2, u8 segm, const f2mc16_disassembler::data_buffer &opcodes) +{ + if ((op2 & 0x18) == 0) + { + util::stream_format(stream, "RL%d", BIT(op2, 1, 2)); + return 0; + } + else + return dasm_ea8(stream, pc, op2, segm, opcodes); +} + +offs_t f2mc16_disassembler::dasm_bitop(std::ostream &stream, offs_t pc, u32 bytes, u8 segm, const f2mc16_disassembler::data_buffer &opcodes) +{ + u8 op2 = opcodes.r8(pc + bytes++); + if (op2 >= 0xf8) + { + util::stream_format(stream, "%-8s", "SBBS"); + format_addr16(stream, segm, opcodes.r16(pc + bytes)); + util::stream_format(stream, ":%d, ", op2 & 0x07); + format_rel(stream, pc + bytes + 3, opcodes.r8(pc + bytes + 2)); + bytes += 3; + } + else if ((op2 & 0x18) != 0x10 && (op2 & 0xc8) != 0xc8) + { + util::stream_format(stream, "%-8s", s_bit_ops[BIT(op2, 5, 3)]); + if (op2 < 0x20) + stream << "A, "; + if (BIT(op2, 4)) + { + format_addr16(stream, segm, opcodes.r16(pc + bytes)); + bytes += 2; + } + else if (BIT(op2, 3)) + format_dir(stream, segm, opcodes.r8(pc + bytes++)); + else + format_io(stream, opcodes.r8(pc + bytes++)); + util::stream_format(stream, ":%d", op2 & 0x07); + if ((op2 & 0xc0) == 0x80) + { + stream << ", "; + format_rel(stream, pc + bytes + 1, opcodes.r8(pc + bytes)); + return (bytes + 1) | STEP_COND | SUPPORTED; + } + else if ((op2 & 0xe0) == 0x20) + stream << ", A"; + } + else + { + util::stream_format(stream, "%-8s0x%02X", ".DATA.B", segm != 0 ? segm : 0x6c); + return 1 | SUPPORTED; + } + return bytes | SUPPORTED; +} + +offs_t f2mc16_disassembler::dasm_movm(std::ostream &stream, offs_t pc, u32 bytes, u8 segm, const f2mc16_disassembler::data_buffer &opcodes) +{ + // 16F only? + u8 op2 = opcodes.r8(pc + bytes++); + util::stream_format(stream, "%-8s", BIT(op2, 6) ? "MOVMW" : "MOVM"); + if (op2 < 0x80) + { + if (BIT(op2, 5)) + stream << "@A"; + else + { + format_addr16(stream, segm, opcodes.r16(pc + bytes)); + bytes += 2; + } + stream << ", "; + } + if ((op2 & 0x18) == 0) + util::stream_format(stream, "@RL%d", BIT(op2, 1, 2)); + else + bytes += dasm_ea8(stream, pc + bytes, op2, segm, opcodes); + if (op2 >= 0x80) + { + stream << ", "; + if (BIT(op2, 5)) + stream << "@A"; + else + { + format_addr16(stream, segm, opcodes.r16(pc + bytes)); + bytes += 2; + } + } + stream << ", "; + format_imm8(stream, opcodes.r8(pc + bytes++)); + return bytes | SUPPORTED; +} + +offs_t f2mc16_disassembler::dasm_cstrop(std::ostream &stream, offs_t pc, u32 bytes, u8 segm, const f2mc16_disassembler::data_buffer &opcodes) +{ + u8 op2 = opcodes.r8(pc + bytes++); + if (op2 < 0x40) + util::stream_format(stream, "%-8s%s, %s", s_movs_ops[BIT(op2, 4, 2)], s_segment_prefixes[BIT(op2, 2, 2)], s_segment_prefixes[BIT(op2, 0, 2)]); + else if (op2 < 0x60) + { + // 16F only? + util::stream_format(stream, "%-8s", BIT(op2, 4) ? "MOVMW" : "MOVM"); + format_addr16(stream, 0x04 | BIT(op2, 2, 2), opcodes.r16(pc + bytes)); + stream << ", "; + format_addr16(stream, 0x04 | BIT(op2, 0, 2), opcodes.r16(pc + bytes + 2)); + stream << ", "; + format_imm8(stream, opcodes.r16(pc + bytes + 4)); + bytes += 5; + } + else if ((op2 & 0xcc) == 0x80) + util::stream_format(stream, "%-8s%s", s_sceq_ops[BIT(op2, 4, 2)], s_segment_prefixes[BIT(op2, 0, 2)]); + else if ((op2 & 0xdc) == 0xc0) + util::stream_format(stream, "%-8s%s", op2 >= 0xe0 ? "FILSWI" : "FILSI", s_segment_prefixes[BIT(op2, 0, 2)]); + else + { + util::stream_format(stream, "%-8s0x%02X", ".DATA.B", segm != 0 ? segm : 0x6e); + return 1 | SUPPORTED; + } + return bytes | SUPPORTED; +} + +offs_t f2mc16_disassembler::dasm_op6f(std::ostream &stream, offs_t pc, u32 bytes, u8 segm, const f2mc16_disassembler::data_buffer &opcodes) +{ + u8 op2 = opcodes.r8(pc + bytes++); + switch (op2) + { + case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: + util::stream_format(stream, "%-8sA, %s", "MOV", s_segment_registers[op2]); + break; + + case 0x05: case 0x0d: + util::stream_format(stream, "%-8sA, ", BIT(op2, 3) ? "MOVW" : "MOV"); + if (segm != 0) + util::stream_format(stream, "%s:", s_segment_prefixes[segm & 0x03]); + stream << "@A"; + break; + + case 0x06: + util::stream_format(stream, "%-8sA, PCB", "MOV"); + break; + + case 0x07: + util::stream_format(stream, "%-8sA", "ROLC"); + break; + + case 0x08: case 0x0a: case 0x0b: + case 0x18: case 0x1a: case 0x1b: + case 0x28: case 0x2a: case 0x2b: // all 16F only? + util::stream_format(stream, "%-8sA, ", s_shift_ops[BIT(op2, 4, 2)][BIT(op2, 0, 2)]); + format_imm8(stream, opcodes.r8(pc + bytes++)); + break; + + case 0x09: // 16F only? + util::stream_format(stream, "%-8sA, SPB", "MOV"); + break; + + case 0x0c: case 0x0e: case 0x0f: + case 0x1c: case 0x1e: case 0x1f: + case 0x2c: case 0x2d: case 0x2e: case 0x2f: + util::stream_format(stream, "%-8sA, R0", s_shift_ops[BIT(op2, 4, 2)][BIT(op2, 0, 2)]); + break; + + case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: + util::stream_format(stream, "%-8s%s, A", "MOV", s_segment_registers[op2 & 0x07]); + break; + + case 0x15: case 0x1d: + util::stream_format(stream, "%-8sAL, ", BIT(op2, 3) ? "MOVW" : "MOV"); + if (segm != 0) + util::stream_format(stream, "%s:", s_segment_prefixes[segm & 0x03]); + stream << "@AH"; + break; + + case 0x16: + util::stream_format(stream, "%-8sA, ", "MOVX"); + if (segm != 0) + util::stream_format(stream, "%s:", s_segment_prefixes[segm & 0x03]); + stream << "@A"; + break; + + case 0x17: + util::stream_format(stream, "%-8sA", "RORC"); + break; + + case 0x19: // 16F only? + util::stream_format(stream, "%-8sSPB, A", "MOV"); + break; + + case 0x20: case 0x22: case 0x24: case 0x26: + case 0x21: case 0x23: case 0x25: case 0x27: // defined as aliases on 16F only? + util::stream_format(stream, "%-8sA, ", "MOVX"); + format_rldisp8(stream, BIT(op2, 1, 2), opcodes.r8(pc + bytes++)); + break; + + case 0x29: // 16F only? + stream << "RETIQ"; + return bytes | STEP_OUT | SUPPORTED; + + case 0x30: case 0x32: case 0x34: case 0x36: case 0x38: case 0x3a: case 0x3c: case 0x3e: + case 0x31: case 0x33: case 0x35: case 0x37: case 0x39: case 0x3b: case 0x3d: case 0x3f: // defined as aliases on 16F only? + util::stream_format(stream, "%-8s", BIT(op2, 3) ? "MOVW" : "MOV"); + format_rldisp8(stream, BIT(op2, 1, 2), opcodes.r8(pc + bytes++)); + stream << ", A"; + break; + + case 0x40: case 0x42: case 0x44: case 0x46: case 0x48: case 0x4a: case 0x4c: case 0x4e: + case 0x41: case 0x43: case 0x45: case 0x47: case 0x49: case 0x4b: case 0x4d: case 0x4f: // defined as aliases on 16F only? + util::stream_format(stream, "%-8sA, ", BIT(op2, 3) ? "MOVW" : "MOV"); + format_rldisp8(stream, BIT(op2, 1, 2), opcodes.r8(pc + bytes++)); + break; + + case 0x50: case 0x51: case 0x52: case 0x53: case 0x54: case 0x55: // 16F only? + util::stream_format(stream, "%-8s%s, ", "MOV", s_segment_registers[op2 & 0x07]); + format_imm8(stream, opcodes.r8(pc + bytes++)); + break; + + case 0x56: case 0x57: // 16F only? + util::stream_format(stream, "%-8sSPC%c, ", "MOVW", BIT(op2, 0) ? 'L' : 'U'); + format_imm8(stream, opcodes.r16(pc + bytes)); + bytes += 2; + break; + + case 0x58: case 0x59: case 0x5a: case 0x5b: // 16F only? + util::stream_format(stream, "%-8sA, @A", s_movp_ops[op2 & 0x03]); + break; + + case 0x5c: // 16F only? + util::stream_format(stream, "%-8sA", "BTSCN"); + break; + + case 0x5d: // 16F only? + stream << "SETSPC"; + break; + + case 0x5e: // 16F only? + util::stream_format(stream, "%-8sA", "BTSCNS"); + break; + + case 0x5f: // 16F only? + util::stream_format(stream, "%-8sA", "BTSCND"); + break; + + case 0x60: // 16F only? + util::stream_format(stream, "%-8sA, ", "MOV"); + format_spdisp8(stream, opcodes.r8(pc + bytes++)); + break; + + case 0x61: // 16F only? + util::stream_format(stream, "%-8sA, ", "MOVX"); + format_spdisp8(stream, opcodes.r8(pc + bytes++)); + break; + + case 0x62: // 16F only? + util::stream_format(stream, "%-8sA, ", "MOVW"); + format_spdisp8(stream, opcodes.r8(pc + bytes++)); + break; + + case 0x63: // 16F only? + util::stream_format(stream, "%-8sA, ", "MOVL"); + format_spdisp8(stream, opcodes.r8(pc + bytes++)); + break; + + case 0x64: // 16F only? + util::stream_format(stream, "%-8s", "MOV"); + format_spdisp8(stream, opcodes.r8(pc + bytes++)); + stream << ", A"; + break; + + case 0x65: // 16F only? + util::stream_format(stream, "%-8sSP, ", "MOVW"); + format_imm16(stream, opcodes.r16(pc + bytes)); + bytes += 2; + break; + + case 0x66: // 16F only? + util::stream_format(stream, "%-8s", "MOVW"); + format_spdisp8(stream, opcodes.r8(pc + bytes++)); + stream << ", A"; + break; + + case 0x67: // 16F only? + util::stream_format(stream, "%-8s", "MOVL"); + format_spdisp8(stream, opcodes.r8(pc + bytes++)); + stream << ", A"; + break; + + case 0x68: case 0x69: case 0x6a: case 0x6b: // 16F only? + util::stream_format(stream, "%-8sA, ", s_movp_ops[op2 & 0x03]); + format_addr24(stream, opcodes.r16(pc + bytes) | u32(opcodes.r8(pc + bytes + 2)) << 16); + bytes += 3; + break; + + case 0x6c: case 0x6e: case 0x6f: // 16F only? + util::stream_format(stream, "%-8s", s_movp_ops[op2 & 0x03]); + format_addr24(stream, opcodes.r16(pc + bytes) | u32(opcodes.r8(pc + bytes + 2)) << 16); + stream << ", A"; + bytes += 3; + break; + + case 0x6d: // 16F only? + stream << "CLRSPC"; + break; + + case 0x70: case 0x71: case 0x72: case 0x73: case 0x74: case 0x75: case 0x76: case 0x77: // 16F only? + util::stream_format(stream, "%-8s@A, RL%d", "MOVPL", BIT(op2, 1, 2)); + break; + + case 0x78: // 16F, 16FX, 16LX only? + util::stream_format(stream, "%-8sA", "MUL"); + break; + + case 0x79: // 16F, 16FX, 16LX only? + util::stream_format(stream, "%-8sA", "MULW"); + break; + + case 0x7a: // 16F, 16FX, 16LX only? + util::stream_format(stream, "%-8sA", "DIV"); + break; + + case 0x7b: // 16F only? + util::stream_format(stream, "%-8sA", "ABS"); + break; + + case 0x7c: // 16F only? + util::stream_format(stream, "%-8sA", "ABSW"); + break; + + case 0x7d: // 16F only? + util::stream_format(stream, "%-8sA", "ABSL"); + break; + + case 0x80: case 0x81: case 0x82: case 0x83: case 0x84: case 0x85: case 0x86: case 0x87: // 16F only? + util::stream_format(stream, "%-8s@A, R%d", "MOVP", op2 & 0x07); + break; + + case 0x88: case 0x89: case 0x8a: case 0x8b: case 0x8c: case 0x8d: case 0x8e: case 0x8f: // 16F only? + util::stream_format(stream, "%-8s@A, RW%d", "MOVPW", op2 & 0x07); + break; + + default: + util::stream_format(stream, "%-8s0x%02X", ".DATA.B", segm != 0 ? segm : 0x6f); + return 1 | SUPPORTED; + } + + return bytes | SUPPORTED; +} + +offs_t f2mc16_disassembler::dasm_eainst(std::ostream &stream, offs_t pc, u32 bytes, u8 op1, u8 segm, const f2mc16_disassembler::data_buffer &opcodes) +{ + u8 op2 = opcodes.r8(pc + bytes++); + switch ((op1 & 0x0f) | (op2 & 0xe0)) + { + case 0x00: + util::stream_format(stream, "%-8sA, ", "ADDL"); + bytes += dasm_ea32(stream, pc + bytes, op2, segm, opcodes); + break; + + case 0x20: + util::stream_format(stream, "%-8sA, ", "SUBL"); + bytes += dasm_ea32(stream, pc + bytes, op2, segm, opcodes); + break; + + case 0x40: + util::stream_format(stream, "%-8s", "CWBNE"); + if ((op2 & 0x1e) == 0x0e) + stream << "(use prohibited)"; + else + bytes += dasm_ea16(stream, pc + bytes, op2, segm, opcodes); + stream << ", "; + format_imm16(stream, opcodes.r16(pc + bytes)); + stream << ", "; + format_rel(stream, pc + bytes + 3, opcodes.r8(pc + bytes + 2)); + bytes += 3; + break; + + case 0x60: + util::stream_format(stream, "%-8sA, ", "CMPL"); + bytes += dasm_ea32(stream, pc + bytes, op2, segm, opcodes); + break; + + case 0x80: + util::stream_format(stream, "%-8sA, ", "ANDL"); + bytes += dasm_ea32(stream, pc + bytes, op2, segm, opcodes); + break; + + case 0xa0: + util::stream_format(stream, "%-8sA, ", "ORL"); + bytes += dasm_ea32(stream, pc + bytes, op2, segm, opcodes); + break; + + case 0xc0: + util::stream_format(stream, "%-8sA, ", "XORL"); + bytes += dasm_ea32(stream, pc + bytes, op2, segm, opcodes); + break; + + case 0xe0: + util::stream_format(stream, "%-8s", "CBNE"); + if ((op2 & 0x1e) == 0x0e) + stream << "(use prohibited)"; + else + bytes += dasm_ea8(stream, pc + bytes, op2, segm, opcodes); + stream << ", "; + format_imm8(stream, opcodes.r8(pc + bytes)); + stream << ", "; + format_rel(stream, pc + bytes + 2, opcodes.r8(pc + bytes + 1)); + return (bytes + 2) | STEP_COND | SUPPORTED; + + case 0x01: + util::stream_format(stream, "%-8s@", "JMPP"); + bytes += dasm_ea32(stream, pc + bytes, op2, segm, opcodes); + break; + + case 0x21: + util::stream_format(stream, "%-8s@", "CALLP"); + bytes += dasm_ea32(stream, pc + bytes, op2, segm, opcodes); + return bytes | STEP_OVER | SUPPORTED; + + case 0x41: + util::stream_format(stream, "%-8s", "INCL"); + bytes += dasm_ea32(stream, pc + bytes, op2, segm, opcodes); + break; + + case 0x61: + util::stream_format(stream, "%-8s", "DECL"); + bytes += dasm_ea32(stream, pc + bytes, op2, segm, opcodes); + break; + + case 0x81: + util::stream_format(stream, "%-8sA, ", "MOVL"); + bytes += dasm_ea32(stream, pc + bytes, op2, segm, opcodes); + break; + + case 0xa1: + util::stream_format(stream, "%-8s", "MOVL"); + bytes += dasm_ea32(stream, pc + bytes, op2, segm, opcodes); + stream << ", A"; + break; + + case 0xc1: + util::stream_format(stream, "%-8s", "MOV"); + bytes += dasm_ea8(stream, pc + bytes, op2, segm, opcodes); + stream << ", "; + format_imm8(stream, opcodes.r8(pc + bytes++)); + break; + + case 0xe1: + util::stream_format(stream, "%-8sA, ", "MOVEA"); + bytes += dasm_ea16(stream, pc + bytes, op2, 0, opcodes); + break; + + case 0x02: + util::stream_format(stream, "%-8s", "ROLC"); + bytes += dasm_ea8(stream, pc + bytes, op2, segm, opcodes); + break; + + case 0x22: + util::stream_format(stream, "%-8s", "RORC"); + bytes += dasm_ea8(stream, pc + bytes, op2, segm, opcodes); + break; + + case 0x42: + util::stream_format(stream, "%-8s", "INC"); + bytes += dasm_ea8(stream, pc + bytes, op2, segm, opcodes); + break; + + case 0x62: + util::stream_format(stream, "%-8s", "DEC"); + bytes += dasm_ea8(stream, pc + bytes, op2, segm, opcodes); + break; + + case 0x82: + util::stream_format(stream, "%-8sA, ", "MOV"); + bytes += dasm_ea8(stream, pc + bytes, op2, segm, opcodes); + break; + + case 0xa2: + util::stream_format(stream, "%-8s", "MOV"); + bytes += dasm_ea8(stream, pc + bytes, op2, segm, opcodes); + stream << ", A"; + break; + + case 0xc2: + util::stream_format(stream, "%-8sA, ", "MOVX"); + bytes += dasm_ea8(stream, pc + bytes, op2, segm, opcodes); + break; + + case 0xe2: + util::stream_format(stream, "%-8sA, ", "XCH"); + bytes += dasm_ea8(stream, pc + bytes, op2, segm, opcodes); + break; + + case 0x03: + util::stream_format(stream, "%-8s@", "JMP"); + bytes += dasm_ea16(stream, pc + bytes, op2, segm, opcodes); + break; + + case 0x23: + util::stream_format(stream, "%-8s@", "CALL"); + bytes += dasm_ea16(stream, pc + bytes, op2, segm, opcodes); + return bytes | STEP_OVER | SUPPORTED; + + case 0x43: + util::stream_format(stream, "%-8s", "INCW"); + bytes += dasm_ea16(stream, pc + bytes, op2, segm, opcodes); + break; + + case 0x63: + util::stream_format(stream, "%-8s", "DECW"); + bytes += dasm_ea16(stream, pc + bytes, op2, segm, opcodes); + break; + + case 0x83: + util::stream_format(stream, "%-8sA, ", "MOVW"); + bytes += dasm_ea16(stream, pc + bytes, op2, segm, opcodes); + break; + + case 0xa3: + util::stream_format(stream, "%-8s", "MOVW"); + bytes += dasm_ea16(stream, pc + bytes, op2, segm, opcodes); + stream << ", A"; + break; + + case 0xc3: + util::stream_format(stream, "%-8s", "MOVW"); + bytes += dasm_ea16(stream, pc + bytes, op2, segm, opcodes); + stream << ", "; + format_imm16(stream, opcodes.r16(pc + bytes)); + bytes += 2; + break; + + case 0xe3: + util::stream_format(stream, "%-8sA, ", "XCHW"); + bytes += dasm_ea16(stream, pc + bytes, op2, segm, opcodes); + break; + + case 0x04: + util::stream_format(stream, "%-8sA, ", "ADD"); + bytes += dasm_ea8(stream, pc + bytes, op2, segm, opcodes); + break; + + case 0x24: + util::stream_format(stream, "%-8sA, ", "SUB"); + bytes += dasm_ea8(stream, pc + bytes, op2, segm, opcodes); + break; + + case 0x44: + util::stream_format(stream, "%-8sA, ", "ADDC"); + bytes += dasm_ea8(stream, pc + bytes, op2, segm, opcodes); + break; + + case 0x64: + util::stream_format(stream, "%-8sA, ", "CMP"); + bytes += dasm_ea8(stream, pc + bytes, op2, segm, opcodes); + break; + + case 0x84: + util::stream_format(stream, "%-8sA, ", "AND"); + bytes += dasm_ea8(stream, pc + bytes, op2, segm, opcodes); + break; + + case 0xa4: + util::stream_format(stream, "%-8sA, ", "OR"); + bytes += dasm_ea8(stream, pc + bytes, op2, segm, opcodes); + break; + + case 0xc4: + util::stream_format(stream, "%-8sA, ", "XOR"); + bytes += dasm_ea8(stream, pc + bytes, op2, segm, opcodes); + break; + + case 0xe4: + util::stream_format(stream, "%-8s", "DBNZ"); + bytes += dasm_ea8(stream, pc + bytes, op2, segm, opcodes); + stream << ", "; + format_rel(stream, pc + bytes + 1, opcodes.r8(pc + bytes)); + return (bytes + 1) | STEP_COND | SUPPORTED; + + case 0x05: + util::stream_format(stream, "%-8s", "ADD"); + bytes += dasm_ea8(stream, pc + bytes, op2, segm, opcodes); + stream << ", A"; + break; + + case 0x25: + util::stream_format(stream, "%-8s", "SUB"); + bytes += dasm_ea8(stream, pc + bytes, op2, segm, opcodes); + stream << ", A"; + break; + + case 0x45: + util::stream_format(stream, "%-8sA, ", "SUBC"); + bytes += dasm_ea8(stream, pc + bytes, op2, segm, opcodes); + break; + + case 0x65: + util::stream_format(stream, "%-8s", "NEG"); + bytes += dasm_ea8(stream, pc + bytes, op2, segm, opcodes); + break; + + case 0x85: + util::stream_format(stream, "%-8s", "AND"); + bytes += dasm_ea8(stream, pc + bytes, op2, segm, opcodes); + stream << ", A"; + break; + + case 0xa5: + util::stream_format(stream, "%-8s", "OR"); + bytes += dasm_ea8(stream, pc + bytes, op2, segm, opcodes); + stream << ", A"; + break; + + case 0xc5: + util::stream_format(stream, "%-8s", "XOR"); + bytes += dasm_ea8(stream, pc + bytes, op2, segm, opcodes); + stream << ", A"; + break; + + case 0xe5: + util::stream_format(stream, "%-8s", "NOT"); + bytes += dasm_ea8(stream, pc + bytes, op2, segm, opcodes); + break; + + case 0x06: + util::stream_format(stream, "%-8sA, ", "ADDW"); + bytes += dasm_ea16(stream, pc + bytes, op2, segm, opcodes); + break; + + case 0x26: + util::stream_format(stream, "%-8sA, ", "SUBW"); + bytes += dasm_ea16(stream, pc + bytes, op2, segm, opcodes); + break; + + case 0x46: + util::stream_format(stream, "%-8sA, ", "ADDCW"); + bytes += dasm_ea16(stream, pc + bytes, op2, segm, opcodes); + break; + + case 0x66: + util::stream_format(stream, "%-8sA, ", "CMPW"); + bytes += dasm_ea16(stream, pc + bytes, op2, segm, opcodes); + break; + + case 0x86: + util::stream_format(stream, "%-8sA, ", "ANDW"); + bytes += dasm_ea16(stream, pc + bytes, op2, segm, opcodes); + break; + + case 0xa6: + util::stream_format(stream, "%-8sA, ", "ORW"); + bytes += dasm_ea16(stream, pc + bytes, op2, segm, opcodes); + break; + + case 0xc6: + util::stream_format(stream, "%-8sA, ", "XORW"); + bytes += dasm_ea16(stream, pc + bytes, op2, segm, opcodes); + break; + + case 0xe6: + util::stream_format(stream, "%-8s", "DWBNZ"); + bytes += dasm_ea16(stream, pc + bytes, op2, segm, opcodes); + stream << ", "; + format_rel(stream, pc + bytes + 1, opcodes.r8(pc + bytes)); + return (bytes + 1) | STEP_COND | SUPPORTED; + + case 0x07: + util::stream_format(stream, "%-8s", "ADDW"); + bytes += dasm_ea16(stream, pc + bytes, op2, segm, opcodes); + stream << ", A"; + break; + + case 0x27: + util::stream_format(stream, "%-8s", "SUBW"); + bytes += dasm_ea16(stream, pc + bytes, op2, segm, opcodes); + stream << ", A"; + break; + + case 0x47: + util::stream_format(stream, "%-8sA, ", "SUBCW"); + bytes += dasm_ea16(stream, pc + bytes, op2, segm, opcodes); + break; + + case 0x67: + util::stream_format(stream, "%-8s", "NEGW"); + bytes += dasm_ea16(stream, pc + bytes, op2, segm, opcodes); + break; + + case 0x87: + util::stream_format(stream, "%-8s", "ANDW"); + bytes += dasm_ea16(stream, pc + bytes, op2, segm, opcodes); + stream << ", A"; + break; + + case 0xa7: + util::stream_format(stream, "%-8s", "ORW"); + bytes += dasm_ea16(stream, pc + bytes, op2, segm, opcodes); + stream << ", A"; + break; + + case 0xc7: + util::stream_format(stream, "%-8s", "XORW"); + bytes += dasm_ea16(stream, pc + bytes, op2, segm, opcodes); + stream << ", A"; + break; + + case 0xe7: + util::stream_format(stream, "%-8s", "NOTW"); + bytes += dasm_ea8(stream, pc + bytes, op2, segm, opcodes); + break; + + case 0x08: case 0x48: // MUL is 16F, 16FX, 16LX only? + util::stream_format(stream, "%-8sA, ", BIT(op2, 6) ? "MUL" : "MULU"); + bytes += dasm_ea8(stream, pc + bytes, op2, segm, opcodes); + break; + + case 0x28: case 0x68: // MULW is 16F, 16FX, 16LX only? + util::stream_format(stream, "%-8sA, ", BIT(op2, 6) ? "MULW" : "MULUW"); + bytes += dasm_ea16(stream, pc + bytes, op2, segm, opcodes); + break; + + case 0x88: case 0xc8: // DIV is 16F, 16FX, 16LX only? + util::stream_format(stream, "%-8sA, ", BIT(op2, 6) ? "DIV" : "DIVU"); + bytes += dasm_ea8(stream, pc + bytes, op2, segm, opcodes); + break; + + case 0xa8: case 0xe8: // DIVW is 16F, 16FX, 16LX only? + util::stream_format(stream, "%-8sA, ", BIT(op2, 6) ? "DIVW" : "DIVUW"); + bytes += dasm_ea16(stream, pc + bytes, op2, segm, opcodes); + break; + + default: + util::stream_format(stream, "%-8s0x%02X", ".DATA.B", segm != 0 ? segm : op1); + return 1 | SUPPORTED; + } + + return bytes | SUPPORTED; +} + +offs_t f2mc16_disassembler::disassemble(std::ostream &stream, offs_t pc, const f2mc16_disassembler::data_buffer &opcodes, const f2mc16_disassembler::data_buffer ¶ms) +{ + u8 op = opcodes.r8(pc); + u8 segm = 0; + u32 bytes = 1; + if ((op & 0xfc) == 0x04) + { + segm = op; + op = opcodes.r8(pc + 1); + ++bytes; + } + + if (op >= 0xf0) + { + util::stream_format(stream, "%-8s", s_bcc_ops[op & 0x0f]); + format_rel(stream, pc + bytes + 1, opcodes.r8(pc + bytes)); + return (bytes + 1) | STEP_COND | SUPPORTED; + } + else if (op >= 0xe0) + { + util::stream_format(stream, "%-8s#%d", "CALLV", op & 0x0f); + return bytes | STEP_OVER | SUPPORTED; + } + else if (op >= 0xd0) + { + util::stream_format(stream, "%-8sA, ", "MOVN"); + format_imm4(stream, op & 0x0f); + } + else if (op >= 0xc8) + { + util::stream_format(stream, "%-8s", "MOVW"); + format_rwdisp8(stream, op & 0x07, segm, opcodes.r8(pc + bytes++)); + stream << ", A"; + } + else if (op >= 0xc0) + { + util::stream_format(stream, "%-8sA, ", "MOVX"); + format_rwdisp8(stream, op & 0x07, segm, opcodes.r8(pc + bytes++)); + } + else if (op >= 0xb8) + { + util::stream_format(stream, "%-8sA, ", "MOVW"); + format_rwdisp8(stream, op & 0x07, segm, opcodes.r8(pc + bytes++)); + } + else if (op >= 0xb0) + util::stream_format(stream, "%-8sA, R%d", "MOVX", op & 0x07); + else if (op >= 0xa8) + { + util::stream_format(stream, "%-8sRW%d, ", "MOVW", op & 0x07); + format_imm16(stream, opcodes.r16(pc + bytes)); + bytes += 2; + } + else if (op >= 0xa0) + { + util::stream_format(stream, "%-8sR%d, ", "MOV", op & 0x07); + format_imm8(stream, opcodes.r8(pc + bytes++)); + } + else if (op >= 0x98) + util::stream_format(stream, "%-8sRW%d, A", "MOVW", op & 0x07); + else if (op >= 0x90) + util::stream_format(stream, "%-8sR%d, A", "MOV", op & 0x07); + else if (op >= 0x88) + util::stream_format(stream, "%-8sA, RW%d", "MOVW", op & 0x07); + else if (op >= 0x80) + util::stream_format(stream, "%-8sA, R%d", "MOV", op & 0x07); + else switch (op) + { + case 0x00: + stream << "NOP"; + break; + + case 0x01: + stream << "INT9"; + return bytes | STEP_OVER | SUPPORTED; + + case 0x02: + util::stream_format(stream, "%-8sA", "ADDDC"); + break; + + case 0x03: + util::stream_format(stream, "%-8sA", "NEG"); + break; + + case 0x08: + util::stream_format(stream, "%-8s", "LINK"); + format_imm8(stream, opcodes.r8(pc + bytes++)); + break; + + case 0x09: + stream << "UNLINK"; + break; + + case 0x0a: + util::stream_format(stream, "%-8sRP, ", "MOV"); + format_imm8(stream, opcodes.r8(pc + bytes++)); + break; + + case 0x0b: + util::stream_format(stream, "%-8sA", "NEGW"); + break; + + case 0x0c: case 0x0e: case 0x0f: + util::stream_format(stream, "%-8sA", s_shift_ops[0][BIT(op, 0, 2)]); + break; + + case 0x0d: + stream << "INTE"; + return bytes | STEP_OVER | SUPPORTED; + + case 0x10: + stream << "CMR"; + break; + + case 0x11: + stream << "NCC"; + break; + + case 0x12: + util::stream_format(stream, "%-8sA", "SUBDC"); + break; + + case 0x13: + util::stream_format(stream, "%-8s@A", "JCTX"); + break; + + case 0x14: case 0x1c: + stream << "EXT"; + if (BIT(op, 3)) + stream << 'W'; + break; + + case 0x15: case 0x1d: + stream << "ZEXT"; + if (BIT(op, 3)) + stream << 'W'; + break; + + case 0x16: case 0x1e: + stream << "SWAP"; + if (BIT(op, 3)) + stream << 'W'; + break; + + case 0x17: case 0x1f: + util::stream_format(stream, "%-8s", "ADDSP"); + if (BIT(op, 3)) + { + format_imm_signed(stream, s32(s16(opcodes.r16(pc + bytes)))); + bytes += 2; + } + else + format_imm_signed(stream, s32(s8(opcodes.r8(pc + bytes++)))); + break; + + case 0x18: case 0x19: + { + u32 operand = opcodes.r32(pc + bytes); + if (operand == 0x00000001) + util::stream_format(stream, "%-8sA", BIT(op, 0) ? "DECL" : "INCL"); + else + { + util::stream_format(stream, "%-8sA, ", BIT(op, 0) ? "SUBL" : "ADDL"); + format_imm_signed(stream, s32(operand)); + } + bytes += 4; + break; + } + + case 0x1a: + util::stream_format(stream, "%-8sILM, ", "MOV"); + format_imm8(stream, opcodes.r8(pc + bytes++)); + break; + + case 0x1b: + util::stream_format(stream, "%-8sA, ", "CMPL"); + format_imm_signed(stream, s32(opcodes.r32(pc + bytes))); + bytes += 4; + break; + + case 0x20: + util::stream_format(stream, "%-8sA, ", "ADD"); + format_dir(stream, segm, opcodes.r8(pc + bytes++)); + break; + + case 0x21: + util::stream_format(stream, "%-8sA, ", "SUB"); + format_dir(stream, segm, opcodes.r8(pc + bytes++)); + break; + + case 0x22: + util::stream_format(stream, "%-8sA", "ADDC"); + break; + + case 0x23: case 0x33: + util::stream_format(stream, "%-8sA", "CMP"); + if (BIT(op, 4)) + { + stream << ", "; + format_imm_signed(stream, s32(s8(opcodes.r8(pc + bytes++)))); + } + break; + + case 0x24: + util::stream_format(stream, "%-8sCCR, ", "AND"); + format_imm8(stream, opcodes.r8(pc + bytes++)); + break; + + case 0x25: + util::stream_format(stream, "%-8sCCR, ", "OR"); + format_imm8(stream, opcodes.r8(pc + bytes++)); + break; + + case 0x26: + util::stream_format(stream, "%-8sA", "DIVU"); + break; + + case 0x27: + util::stream_format(stream, "%-8sA", "MULU"); + break; + + case 0x28: + util::stream_format(stream, "%-8sA", "ADDW"); + break; + + case 0x29: + util::stream_format(stream, "%-8sA", "SUBW"); + break; + + case 0x2a: + util::stream_format(stream, "%-8sA, ", "CBNE"); + format_imm8(stream, opcodes.r8(pc + bytes++)); + stream << ", "; + format_rel(stream, pc + bytes + 1, opcodes.r8(pc + bytes)); + return (bytes + 1) | STEP_COND | SUPPORTED; + + case 0x2b: case 0x3b: + util::stream_format(stream, "%-8sA", "CMPW"); + if (BIT(op, 4)) + { + stream << ", "; + format_imm_signed(stream, s32(s16(opcodes.r16(pc + bytes)))); + bytes += 2; + } + break; + + case 0x2c: case 0x3c: + util::stream_format(stream, "%-8sA", "ANDW"); + if (BIT(op, 4)) + { + stream << ", "; + format_imm16(stream, opcodes.r16(pc + bytes)); + bytes += 2; + } + break; + + case 0x2d: case 0x3d: + util::stream_format(stream, "%-8sA", "ORW"); + if (BIT(op, 4)) + { + stream << ", "; + format_imm16(stream, opcodes.r16(pc + bytes)); + bytes += 2; + } + break; + + case 0x2e: case 0x3e: + util::stream_format(stream, "%-8sA", "XORW"); + if (BIT(op, 4)) + { + stream << ", "; + format_imm16(stream, opcodes.r16(pc + bytes)); + bytes += 2; + } + break; + + case 0x2f: + util::stream_format(stream, "%-8sA", "MULUW"); + break; + + case 0x30: case 0x31: + util::stream_format(stream, "%-8sA, ", BIT(op, 0) ? "SUB" : "ADD"); + format_imm_signed(stream, s32(s8(opcodes.r8(pc + bytes++)))); + break; + + case 0x32: + util::stream_format(stream, "%-8sA", "SUBC"); + break; + + case 0x34: + util::stream_format(stream, "%-8sA, ", "AND"); + format_imm8(stream, opcodes.r8(pc + bytes++)); + break; + + case 0x35: + util::stream_format(stream, "%-8sA, ", "OR"); + format_imm8(stream, opcodes.r8(pc + bytes++)); + break; + + case 0x36: + util::stream_format(stream, "%-8sA, ", "XOR"); + format_imm8(stream, opcodes.r8(pc + bytes++)); + break; + + case 0x37: + util::stream_format(stream, "%-8sA", "NOT"); + break; + + case 0x38: case 0x39: + { + u16 operand = opcodes.r16(pc + bytes); + if (operand == 0x0001) + util::stream_format(stream, "%-8sA", BIT(op, 0) ? "DECW" : "INCW"); + else + { + util::stream_format(stream, "%-8sA, ", BIT(op, 0) ? "SUBW" : "ADDW"); + format_imm_signed(stream, s32(s16(operand))); + } + bytes += 2; + break; + } + + case 0x3a: + util::stream_format(stream, "%-8sA, ", "CWBNE"); + format_imm16(stream, opcodes.r16(pc + bytes)); + stream << ", "; + format_rel(stream, pc + bytes + 3, opcodes.r8(pc + bytes + 2)); + bytes += 3; + break; + + case 0x3f: + util::stream_format(stream, "%-8sA", "NOTW"); + break; + + case 0x40: case 0x50: + util::stream_format(stream, "%-8sA, ", "MOV"); + if (BIT(op, 4)) + format_io(stream, opcodes.r8(pc + bytes++)); + else + format_dir(stream, segm, opcodes.r8(pc + bytes++)); + break; + + case 0x41: case 0x51: + util::stream_format(stream, "%-8s", "MOV"); + if (BIT(op, 4)) + format_io(stream, opcodes.r8(pc + bytes++)); + else + format_dir(stream, segm, opcodes.r8(pc + bytes++)); + stream << ", A"; + break; + + case 0x42: + util::stream_format(stream, "%-8sA, ", "MOV"); + format_imm8(stream, opcodes.r8(pc + bytes++)); + break; + + case 0x43: + util::stream_format(stream, "%-8sA, ", "MOVX"); + format_imm_signed(stream, s32(s8(opcodes.r8(pc + bytes++)))); + break; + + case 0x44: case 0x54: + util::stream_format(stream, "%-8s", "MOV"); + if (BIT(op, 4)) + format_io(stream, opcodes.r8(pc + bytes++)); + else + format_dir(stream, segm, opcodes.r8(pc + bytes++)); + stream << ", "; + format_imm8(stream, opcodes.r8(pc + bytes++)); + break; + + case 0x45: case 0x55: + util::stream_format(stream, "%-8sA, ", "MOVX"); + if (BIT(op, 4)) + format_io(stream, opcodes.r8(pc + bytes++)); + else + format_dir(stream, segm, opcodes.r8(pc + bytes++)); + break; + + case 0x46: + util::stream_format(stream, "%-8sA, SP", "MOVW"); + break; + + case 0x47: + util::stream_format(stream, "%-8sSP, A", "MOVW"); + break; + + case 0x48: case 0x58: + util::stream_format(stream, "%-8sA, ", "MOVW"); + if (BIT(op, 4)) + format_io(stream, opcodes.r8(pc + bytes++)); + else + format_dir(stream, segm, opcodes.r8(pc + bytes++)); + break; + + case 0x49: case 0x59: + util::stream_format(stream, "%-8s", "MOVW"); + if (BIT(op, 4)) + format_io(stream, opcodes.r8(pc + bytes++)); + else + format_dir(stream, segm, opcodes.r8(pc + bytes++)); + stream << ", A"; + break; + + case 0x4a: + util::stream_format(stream, "%-8sA, ", "MOVW"); + format_imm16(stream, opcodes.r16(pc + bytes)); + bytes += 2; + break; + + case 0x4b: + util::stream_format(stream, "%-8sA, ", "MOVL"); + format_imm32(stream, opcodes.r32(pc + bytes)); + bytes += 4; + break; + + case 0x4c: case 0x4d: + util::stream_format(stream, "%-8sA", "PUSHW"); + if (BIT(op, 0)) + stream << 'H'; + break; + + case 0x4e: + util::stream_format(stream, "%-8sPS", "PUSHW"); + break; + + case 0x4f: + util::stream_format(stream, "%-8s", "PUSHW"); + format_rlist(stream, opcodes.r8(pc + bytes++)); + break; + + case 0x52: case 0x5a: + util::stream_format(stream, "%-8sA, ", BIT(op, 3) ? "MOVW" : "MOV"); + format_addr16(stream, segm, opcodes.r16(pc + bytes)); + bytes += 2; + break; + + case 0x53: case 0x5b: + util::stream_format(stream, "%-8s", BIT(op, 3) ? "MOVW" : "MOV"); + format_addr16(stream, segm, opcodes.r16(pc + bytes)); + stream << ", A"; + bytes += 2; + break; + + case 0x56: + util::stream_format(stream, "%-8s", "MOVW"); + format_io(stream, opcodes.r8(pc + bytes++)); + stream << ", "; + format_imm16(stream, opcodes.r16(pc + bytes)); + bytes += 2; + break; + + case 0x57: + util::stream_format(stream, "%-8sA, ", "MOVX"); + format_addr16(stream, segm, opcodes.r16(pc + bytes)); + bytes += 2; + break; + + case 0x5c: case 0x5d: + util::stream_format(stream, "%-8sA", "POPW"); + if (BIT(op, 0)) + stream << 'H'; + break; + + case 0x5e: + util::stream_format(stream, "%-8sPS", "POPW"); + break; + + case 0x5f: + util::stream_format(stream, "%-8s", "POPW"); + format_rlist(stream, opcodes.r8(pc + bytes++)); + break; + + case 0x60: + util::stream_format(stream, "%-8s", "BRA"); + format_rel(stream, pc + bytes + 1, opcodes.r8(pc + bytes)); + ++bytes; + break; + + case 0x61: + util::stream_format(stream, "%-8s@A", "JMP"); + break; + + case 0x62: + util::stream_format(stream, "%-8s", "JMP"); + format_dst16(stream, opcodes.r16(pc + bytes)); + bytes += 2; + break; + + case 0x63: + util::stream_format(stream, "%-8s", "JMPP"); + format_addr24(stream, opcodes.r16(pc + bytes) | u32(opcodes.r8(pc + bytes + 2)) << 16); + bytes += 3; + break; + + case 0x64: + util::stream_format(stream, "%-8s", "CALL"); + format_dst16(stream, opcodes.r16(pc + bytes)); + bytes += 2; + return bytes | STEP_OVER | SUPPORTED; + + case 0x65: + util::stream_format(stream, "%-8s", "CALLP"); + format_addr24(stream, opcodes.r16(pc + bytes) | u32(opcodes.r8(pc + bytes + 2)) << 16); + bytes += 3; + return bytes | STEP_OVER | SUPPORTED; + + case 0x66: case 0x67: + stream << "RET"; + if (!BIT(op, 0)) + stream << 'P'; + return bytes | STEP_OUT | SUPPORTED; + + case 0x68: + util::stream_format(stream, "%-8s", "INT"); + format_imm8(stream, opcodes.r8(pc + bytes++)); + return bytes | STEP_OVER | SUPPORTED; + + case 0x69: + util::stream_format(stream, "%-8s", "INT"); + format_dst16(stream, opcodes.r16(pc + bytes)); + bytes += 2; + return bytes | STEP_OVER | SUPPORTED; + + case 0x6a: + util::stream_format(stream, "%-8s", "INTP"); + format_addr24(stream, opcodes.r16(pc + bytes) | u32(opcodes.r8(pc + bytes + 2)) << 16); + bytes += 3; + return bytes | STEP_OVER | SUPPORTED; + + case 0x6b: + stream << "RETI"; + return bytes | STEP_OUT | SUPPORTED; + + case 0x6c: + return dasm_bitop(stream, pc, bytes, segm, opcodes); + + case 0x6d: + return dasm_movm(stream, pc, bytes, segm, opcodes); + + case 0x6e: + return dasm_cstrop(stream, pc, bytes, segm, opcodes); + + case 0x6f: + return dasm_op6f(stream, pc, bytes, segm, opcodes); + + case 0x70: case 0x71: case 0x72: case 0x73: case 0x74: case 0x75: case 0x76: case 0x77: case 0x78: + return dasm_eainst(stream, pc, bytes, op, segm, opcodes); + + case 0x79: + { + u8 op2 = opcodes.r8(pc + bytes++); + util::stream_format(stream, "%-8sRW%d, ", "MOVEA", BIT(op2, 5, 3)); + bytes += dasm_ea16(stream, pc + bytes, op2, 0, opcodes); + break; + } + + case 0x7a: case 0x7e: + { + u8 op2 = opcodes.r8(pc + bytes++); + util::stream_format(stream, "%-8sR%d, ", BIT(op, 2) ? "XCH" : "MOV", BIT(op2, 5, 3)); + bytes += dasm_ea8(stream, pc + bytes, op2, segm, opcodes); + break; + } + + case 0x7b: case 0x7f: + { + u8 op2 = opcodes.r8(pc + bytes++); + util::stream_format(stream, "%-8sRW%d, ", BIT(op, 2) ? "XCHW" : "MOVW", BIT(op2, 5, 3)); + bytes += dasm_ea16(stream, pc + bytes, op2, segm, opcodes); + break; + } + + case 0x7c: + { + u8 op2 = opcodes.r8(pc + bytes++); + util::stream_format(stream, "%-8s", "MOV"); + bytes += dasm_ea8(stream, pc + bytes, op2, segm, opcodes); + util::stream_format(stream, ", R%d", BIT(op2, 5, 3)); + break; + } + + case 0x7d: + { + u8 op2 = opcodes.r8(pc + bytes++); + util::stream_format(stream, "%-8s", "MOVW"); + bytes += dasm_ea16(stream, pc + bytes, op2, segm, opcodes); + util::stream_format(stream, ", RW%d", BIT(op2, 5, 3)); + break; + } + + default: + util::stream_format(stream, "%-8s0x%02X", ".DATA.B", segm != 0 ? segm : op); + return 1 | SUPPORTED; + } + + return bytes | SUPPORTED; +} |