summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOxore <oxore@protonmail.com>2023-05-08 15:55:37 +0300
committerOxore <oxore@protonmail.com>2023-05-08 15:55:37 +0300
commitc12ef2015384fd7f35150f058dfb3b3df46dcd2c (patch)
treead2135ea9ddf067083303ebbbec7932d3848ec4e
parentbacac6360c7415f9632014bc82fd646f76cb2560 (diff)
Impl EXT
-rw-r--r--disasm.cpp43
-rw-r--r--test.bash5
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<MoveDirection>((instr >> 10) & 1);
+ const unsigned m = (instr >> 3) & 7;
+ const unsigned xn = instr & 7;
+ const auto opsize = static_cast<OpSize>(((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<MoveDirection>((instr >> 10) & 1);
- const auto opsize = static_cast<OpSize>(((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<OpSize>((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"