From c12ef2015384fd7f35150f058dfb3b3df46dcd2c Mon Sep 17 00:00:00 2001 From: Oxore Date: Mon, 8 May 2023 15:55:37 +0300 Subject: Impl EXT --- disasm.cpp | 43 ++++++++++++++++++++++++++++++++++--------- test.bash | 5 +++++ 2 files changed, 39 insertions(+), 9 deletions(-) diff --git a/disasm.cpp b/disasm.cpp index 056ec83..ead5a86 100644 --- a/disasm.cpp +++ b/disasm.cpp @@ -394,11 +394,30 @@ static void disasm_jsr_jmp( (void) ret; } -static void disasm_movem( +static void disasm_ext( + DisasmNode &node, + const char suffix, + const AddrModeArg arg) +{ + assert(arg.mode == AddrMode::kDn); + snprintf(node.mnemonic, kMnemonicBufferSize, "ext%c", suffix); + arg.SNPrint(node.arguments, kArgsBufferSize); + node.size = kInstructionSizeStepBytes + arg.Size(); +} + +static void disasm_ext_movem( DisasmNode &node, uint16_t instr, const DataBuffer &code, const Settings &s) { + const auto dir = static_cast((instr >> 10) & 1); + const unsigned m = (instr >> 3) & 7; + const unsigned xn = instr & 7; + const auto opsize = static_cast(((instr >> 6) & 1) + 1); + const char suffix = suffix_from_opsize(opsize); + if (m == 0 && dir == MoveDirection::kRegisterToMemory) { + return disasm_ext(node, suffix, AddrModeArg::Dn(xn)); + } if (node.offset + kInstructionSizeStepBytes >= code.occupied_size) { - // Not enough space for regmask + // Not enough space for regmask, but maybe it is just EXT? return disasm_verbatim(node, instr, code, s); } const unsigned regmask = GetU16BE(code.buffer + node.offset + kInstructionSizeStepBytes); @@ -406,11 +425,8 @@ static void disasm_movem( // This is just not representable: at least one register must be specified return disasm_verbatim(node, instr, code, s); } - const auto dir = static_cast((instr >> 10) & 1); - const auto opsize = static_cast(((instr >> 6) & 1) + 1); - const char suffix = suffix_from_opsize(opsize); const auto a = AddrModeArg::Fetch( - node.offset + kInstructionSizeStepBytes * 2, code, instr, suffix); + node.offset + kInstructionSizeStepBytes * 2, code, m, xn, suffix); switch (a.mode) { case AddrMode::kInvalid: case AddrMode::kDn: // 4880..4887 / 4c80..4c87 / 48c0..48c7 / 4cc0..4cc7 @@ -952,7 +968,7 @@ static inline const char *mnemonic_for_negx_clr_neg_not(const unsigned opcode) return "?"; } -static void disasm_negx_clr_neg_not( +static void disasm_move_negx_clr_neg_not( DisasmNode &node, uint16_t instr, const DataBuffer &code, const Settings &s) { const auto opsize = static_cast((instr >> 6) & 3); @@ -1141,11 +1157,20 @@ static void disasm_move_usp( } } +static void disasm_nbcd_swap_pea( + DisasmNode &node, uint16_t instr, const DataBuffer &code, const Settings &s) +{ + return disasm_verbatim(node, instr, code, s); +} + static void disasm_chunk_4( DisasmNode &node, uint16_t instr, const DataBuffer &code, const Settings &s) { if ((instr & 0xf900) == 0x4000) { - return disasm_negx_clr_neg_not(node, instr, code, s); + return disasm_move_negx_clr_neg_not(node, instr, code, s); + } else if ((instr & 0xff80) == 0x4800) { + // NOTE EXT is handled with MOVEM + return disasm_nbcd_swap_pea(node, instr, code, s); } else if ((instr & 0xff00) == 0x4a00) { return disasm_tst_tas_illegal(node, instr, code, s); } else if ((instr & 0xfff0) == 0x4e40) { @@ -1179,7 +1204,7 @@ static void disasm_chunk_4( } else if ((instr & 0xffc0) == 0x4ec0) { return disasm_jsr_jmp(node, instr, code, s, JType::kJmp); } else if ((instr & 0xfb80) == 0x4880) { - return disasm_movem(node, instr, code, s); + return disasm_ext_movem(node, instr, code, s); } else if ((instr & 0xf1c0) == 0x41c0) { return disasm_lea(node, instr, code, s); } else if ((instr & 0xf1c0) == 0x4180) { diff --git a/test.bash b/test.bash index b4dd6ac..cfa3aab 100644 --- a/test.bash +++ b/test.bash @@ -93,6 +93,11 @@ run_test_iterative() { done } +# 48xx ext +# +run_test_simple "extw %d7" "\x48\x87" +run_test_simple "extl %d4" "\x48\xc4" + # exxx asl, asr, lsl, lsr, roxl, roxr, rol, ror # run_test_simple "asrb Dn, Dn" "\xe2\x22" -- cgit v1.2.3