From 5463fd221e7a1071f351ea12b617c90c4fe98d64 Mon Sep 17 00:00:00 2001 From: Oxore Date: Mon, 8 May 2023 20:59:04 +0300 Subject: Impl AND --- disasm.cpp | 67 ++++++++++++++++++++++++++++++++++++++++++++++---------------- test.bash | 15 +++++++++++++- 2 files changed, 64 insertions(+), 18 deletions(-) diff --git a/disasm.cpp b/disasm.cpp index adbd926..7b42703 100644 --- a/disasm.cpp +++ b/disasm.cpp @@ -1456,16 +1456,14 @@ static void disasm_addx_subx_abcd_sbcd( node.size = kInstructionSizeStepBytes + src.Size() + dst.Size(); } -static void disasm_divu_divs_sbcd_or( - DisasmNode &node, uint16_t instr, const DataBuffer &code, const Settings &s) +static void disasm_or_and( + DisasmNode &node, + uint16_t instr, + const DataBuffer &code, + const Settings &s, + const OpSize opsize, + const char* mnemonic) { - if ((instr & 0x1f0) == 0x100) { - return disasm_addx_subx_abcd_sbcd(node, instr, "sbcd", ""); - } - const OpSize opsize = static_cast((instr >> 6) & 3); - if (opsize == OpSize::kInvalid) { - return disasm_divu_divs(node, instr, code, s); - } const char suffix = suffix_from_opsize(opsize); const bool dir_to_addr = (instr >> 8) & 1; const auto addr = AddrModeArg::Fetch( @@ -1503,11 +1501,12 @@ static void disasm_divu_divs_sbcd_or( return disasm_verbatim(node, instr, code, s); } if (1) { - // XXX GNU AS always emits ORI (04xx xxxx [xxxx]) instruction when - // given OR with immediate source argument. It may become an - // option like -fpedantic to generate instruction in this case, but - // for now it is gonna be just plain bytes to keep original and - // reassembled binaries *identical* as it must be by default. + // XXX GNU AS always emits ORI (04xx xxxx [xxxx]) or ANDI (02xx + // xxxx [xxxx]) instruction when given OR or AND correspondingly + // with immediate source argument. It may become an option like + // -fpedantic to generate instruction in this case, but for now it + // is gonna be just plain bytes to keep original and reassembled + // binaries *identical* as it must be by default. return disasm_verbatim(node, instr, code, s); } break; @@ -1518,7 +1517,7 @@ static void disasm_divu_divs_sbcd_or( char reg_str[32]{}; addr.SNPrint(addr_str, sizeof(addr_str)); reg.SNPrint(reg_str, sizeof(reg_str)); - snprintf(node.mnemonic, kMnemonicBufferSize, "%s%c", "or", suffix); + snprintf(node.mnemonic, kMnemonicBufferSize, "%s%c", mnemonic, suffix); if (dir_to_addr) { snprintf(node.arguments, kArgsBufferSize, "%s,%s", reg_str, addr_str); } else { @@ -1527,12 +1526,39 @@ static void disasm_divu_divs_sbcd_or( node.size = kInstructionSizeStepBytes + addr.Size() + reg.Size(); } +static void disasm_divu_divs_sbcd_or( + DisasmNode &node, uint16_t instr, const DataBuffer &code, const Settings &s) +{ + if ((instr & 0x1f0) == 0x100) { + return disasm_addx_subx_abcd_sbcd(node, instr, "sbcd", ""); + } + const OpSize opsize = static_cast((instr >> 6) & 3); + if (opsize == OpSize::kInvalid) { + return disasm_divu_divs(node, instr, code, s); + } + return disasm_or_and(node, instr, code, s, opsize, "or"); +} + static void disasm_chunk_b(DisasmNode &n, uint16_t i, const DataBuffer &c, const Settings &s) { // TODO Implement return disasm_verbatim(n, i, c, s); } +static void disasm_mulu_muls( + DisasmNode &node, uint16_t instr, const DataBuffer &code, const Settings &s) +{ + // TODO Implement + return disasm_verbatim(node, instr, code, s); +} + +static void disasm_exg( + DisasmNode &node, uint16_t instr, const DataBuffer &code, const Settings &s) +{ + // TODO Implement + return disasm_verbatim(node, instr, code, s); +} + static void disasm_chunk_c( DisasmNode &node, uint16_t instr, const DataBuffer &code, const Settings &s) { @@ -1543,8 +1569,15 @@ static void disasm_chunk_c( const bool skip_size_suffix = true; return disasm_addx_subx_abcd_sbcd(node, instr, "abcd", "", skip_size_suffix); } - // TODO Implement - return disasm_verbatim(node, instr, code, s); + const OpSize opsize = static_cast((instr >> 6) & 3); + if (opsize == OpSize::kInvalid) { + return disasm_mulu_muls(node, instr, code, s); + } + const unsigned m_split = instr & 0x1f8; + if (m_split == 0x188 || m_split == 0x148 || m_split == 0x140) { + return disasm_exg(node, instr, code, s); + } + return disasm_or_and(node, instr, code, s, opsize, "and"); } static inline void disasm_adda_suba( diff --git a/test.bash b/test.bash index a6f25d7..5ee822d 100644 --- a/test.bash +++ b/test.bash @@ -93,6 +93,19 @@ run_test_iterative() { done } +# cxxx and +# +run_test_simple "andb Dn, Dn" "\xc4\x01" +run_test_expect_short "andb An, Dn" "\xc4\x09" +run_test_expect_short "andw An, Dn" "\xc4\x49" +run_test_simple "andb (An), Dn" "\xc4\x11" +run_test_simple "andb (An)+, Dn" "\xc4\x19" +run_test_simple "andw -(An), Dn" "\xc4\x61" +run_test_simple "andl (d8,PC,An), Dn" "\xc0\xbb\xc8\x07" +# GNU AS would emit ANDI for "and #imm,Xn", so we diassemble it as short +run_test_expect_short "andl #imm, D6" "\xc6\xbc\x44\xd1\xe6\xe9" +run_test_expect_short "andl D2, D0 swapped direction" "\xc1\x42" + # cxxx abcd # run_test_simple "abcd Dn, Dn" "\xc1\x01" @@ -112,7 +125,7 @@ run_test_simple "orb (An), Dn" "\x84\x11" run_test_simple "orb (An)+, Dn" "\x84\x19" run_test_simple "orw -(An), Dn" "\x84\x61" run_test_simple "orl (d8,PC,An), Dn" "\x80\xbb\x88\x07" -# GNU AS would emit ADDI for "or #imm,Xn", so we diassemble it as short +# GNU AS would emit ORI for "or #imm,Xn", so we diassemble it as short run_test_expect_short "orl #imm, D6" "\x86\xbc\x44\xd1\xe6\xe9" run_test_expect_short "orl D2, D0 swapped direction" "\x81\x42" -- cgit v1.2.3