summaryrefslogtreecommitdiff
path: root/disasm.cpp
diff options
context:
space:
mode:
authorOxore <oxore@protonmail.com>2023-05-08 21:28:07 +0300
committerOxore <oxore@protonmail.com>2023-05-08 21:28:07 +0300
commit3c0b372d623a52a2e0623f48c4adfb74fb727748 (patch)
treef2d052227914cab332ea565ede4081525cc4d7e1 /disasm.cpp
parent5463fd221e7a1071f351ea12b617c90c4fe98d64 (diff)
Impl EXG
Diffstat (limited to 'disasm.cpp')
-rw-r--r--disasm.cpp25
1 files changed, 20 insertions, 5 deletions
diff --git a/disasm.cpp b/disasm.cpp
index 7b42703..401c869 100644
--- a/disasm.cpp
+++ b/disasm.cpp
@@ -1552,11 +1552,26 @@ static void disasm_mulu_muls(
return disasm_verbatim(node, instr, code, s);
}
-static void disasm_exg(
- DisasmNode &node, uint16_t instr, const DataBuffer &code, const Settings &s)
+static inline void disasm_exg(DisasmNode &node, uint16_t instr)
{
- // TODO Implement
- return disasm_verbatim(node, instr, code, s);
+ assert((instr & 0x130) == 0x100);
+ const int m1 = (instr >> 3) & 1;
+ const int m2 = (instr >> 6) & 3;
+ assert(m2 != 0); // Therefore m == 0 and m == 1 are impossible
+ assert(m2 != 3); // Therefore m == 6 and m == 7 are impossible
+ const int m = (m2 << 1) | m1;
+ assert(m != 4); // Only m == 2, m == 3 and m == 5 values are allowed
+ const int xn = instr & 7;
+ const int xi = (instr >> 9) & 7;
+ const auto src = (m == 3) ? AddrModeArg::An(xi) : AddrModeArg::Dn(xi);
+ const auto dst = (m == 2) ? AddrModeArg::Dn(xn) : AddrModeArg::An(xn);
+ char src_str[32]{};
+ char dst_str[32]{};
+ src.SNPrint(src_str, sizeof(src_str));
+ dst.SNPrint(dst_str, sizeof(dst_str));
+ snprintf(node.mnemonic, kMnemonicBufferSize, "exg");
+ snprintf(node.arguments, kArgsBufferSize, "%s,%s", src_str, dst_str);
+ node.size = kInstructionSizeStepBytes + src.Size() + dst.Size();
}
static void disasm_chunk_c(
@@ -1575,7 +1590,7 @@ static void disasm_chunk_c(
}
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_exg(node, instr);
}
return disasm_or_and(node, instr, code, s, opsize, "and");
}