summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--disasm.cpp131
-rw-r--r--test.bash34
2 files changed, 162 insertions, 3 deletions
diff --git a/disasm.cpp b/disasm.cpp
index 7080ba6..ef53952 100644
--- a/disasm.cpp
+++ b/disasm.cpp
@@ -534,9 +534,134 @@ static void disasm_bra_bsr_bcc(
return;
}
-static void chunk_mf000_v0000(DisasmNode& n, uint16_t i, const DataBuffer &c, const Settings &s)
+const char *mnemonic_for_bitops(OpSize opsize)
{
- return disasm_verbatim(n, i, c, s);
+ switch (opsize) {
+ case OpSize::kByte: return "btst";
+ case OpSize::kWord: return "bchg";
+ case OpSize::kLong: return "bclr";
+ case OpSize::kInvalid: return "bset";
+ }
+ assert(false);
+ return "?";
+}
+
+static void disasm_dobule_args_bitops_movep(
+ DisasmNode& node, uint16_t instr, const DataBuffer &code, const Settings &s)
+{
+ // TODO
+ return disasm_verbatim(node, instr, code, s);
+}
+
+static void disasm_bitops(
+ DisasmNode& node, uint16_t instr, const DataBuffer &code, const Settings &s)
+{
+ // TODO
+ return disasm_verbatim(node, instr, code, s);
+}
+
+static inline void disasm_logical_imm_to(
+ DisasmNode& node, const char* mnemonic, const char suffix, const int16_t imm)
+{
+ const char *reg = suffix == 'b' ? "ccr" : "sr";
+ snprintf(node.mnemonic, kMnemonicBufferSize, "%s%c", mnemonic, suffix);
+ snprintf(node.arguments, kArgsBufferSize, "#%d,%%%s", imm, reg);
+ node.size = kInstructionSizeStepBytes * 2;
+}
+
+const char *mnemonic_for_chunk_mf000_v1000(const unsigned opcode)
+{
+ switch (opcode) {
+ case 0: return "ori";
+ case 1: return "andi";
+ case 2: return "subi";
+ case 3: return "addi";
+ case 4: break;
+ case 5: return "eori";
+ case 6: return "cmpi";
+ case 7: break;
+ }
+ assert(false);
+ return "?";
+}
+
+static void chunk_mf000_v0000(
+ DisasmNode& node, uint16_t instr, const DataBuffer &code, const Settings &s)
+{
+ const bool has_source_reg = (instr >> 8) & 1;
+ if (has_source_reg) {
+ return disasm_dobule_args_bitops_movep(node, instr, code, s);
+ }
+ const unsigned opcode = (instr >> 9) & 7;
+ if (opcode == 7) {
+ // Does not exist
+ return disasm_verbatim(node, instr, code, s);
+ }
+ if (opcode == 4) {
+ return disasm_bitops(node, instr, code, s);
+ }
+ const int m = (instr >> 3) & 7;
+ const int xn = instr & 7;
+ const auto opsize = static_cast<OpSize>((instr >> 6) & 3);
+ if (opsize == OpSize::kInvalid) {
+ // Does not exist
+ return disasm_verbatim(node, instr, code, s);
+ }
+ // Anticipating #imm which means "to CCR"/"to SR", depending on OpSize
+ if (m == 7 && xn == 4) {
+ if (opcode == 2 || opcode == 3 || opcode == 6) {
+ // CMPI, SUBI and ANDI neither have immediate destination arguments
+ // nor "to CCR"/"to SR" variations
+ return disasm_verbatim(node, instr, code, s);
+ }
+ if (opsize == OpSize::kLong) {
+ // Does not exist
+ return disasm_verbatim(node, instr, code, s);
+ }
+ }
+ const char suffix = suffix_from_opsize(opsize);
+ const auto src = AddrModeArg::Fetch(
+ node.offset + kInstructionSizeStepBytes, code, 7, 4, suffix);
+ if (src.mode == AddrMode::kInvalid) {
+ return disasm_verbatim(node, instr, code, s);
+ }
+ assert(src.mode == AddrMode::kImmediate);
+ const char *mnemonic = mnemonic_for_chunk_mf000_v1000(opcode);
+ if (m == 7 && xn == 4) {
+ return disasm_logical_imm_to(node, mnemonic, suffix, src.value);
+ }
+ const auto dst = AddrModeArg::Fetch(
+ node.offset + kInstructionSizeStepBytes + src.Size(), code, m, xn, suffix);
+ switch (dst.mode) {
+ case AddrMode::kInvalid:
+ return disasm_verbatim(node, instr, code, s);
+ case AddrMode::kDn:
+ break;
+ case AddrMode::kAn:
+ return disasm_verbatim(node, instr, code, s);
+ case AddrMode::kAnAddr:
+ case AddrMode::kAnAddrIncr:
+ case AddrMode::kAnAddrDecr:
+ case AddrMode::kD16AnAddr:
+ case AddrMode::kD8AnXiAddr:
+ case AddrMode::kWord:
+ case AddrMode::kLong:
+ break;
+ case AddrMode::kD16PCAddr:
+ case AddrMode::kD8PCXiAddr:
+ if (opcode != 6) {
+ // PC relative destination address argument available for CMPI only
+ return disasm_verbatim(node, instr, code, s);
+ }
+ break;
+ case AddrMode::kImmediate:
+ return disasm_verbatim(node, instr, code, s);
+ }
+ char dst_str[32]{};
+ dst.SNPrint(dst_str, sizeof(dst_str));
+ snprintf(node.mnemonic, kMnemonicBufferSize, "%s%c", mnemonic, suffix);
+ snprintf(node.arguments, kArgsBufferSize, "#%d,%s", src.value, dst_str);
+ node.size = kInstructionSizeStepBytes + src.Size() + dst.Size();
}
static void disasm_move_movea(
@@ -760,7 +885,7 @@ static void disasm_tst_tas_illegal(
{
const auto opsize = static_cast<OpSize>((instr >> 6) & 3);
const int m = (instr >> 3) & 7;
- const int xn = instr& 7;
+ const int xn = instr & 7;
if (opsize == OpSize::kInvalid) {
if (m == 7 && xn == 4){
return disasm_trivial(node, instr, code, s, "illegal");
diff --git a/test.bash b/test.bash
index 57681e9..a3bff0e 100644
--- a/test.bash
+++ b/test.bash
@@ -93,6 +93,34 @@ run_test_iterative() {
done
}
+# 0xxx
+#
+run_test_simple "orib zero to CCR" "\x00\x3c\x00\x00"
+run_test_simple "orib positive to CCR" "\x00\x3c\x00\x01"
+run_test_simple "orib positive to CCR" "\x00\x3c\x00\x7f"
+run_test_expect_short "orib #imm (too much for orib) to CCR" "\x00\x3c\x01\x00"
+run_test_simple "orib negative to CCR" "\x00\x3c\xff\x80"
+run_test_simple "orib negative to CCR" "\x00\x3c\xff\xff"
+run_test_simple "oriw zero to SR" "\x00\x7c\x00\x00"
+run_test_simple "oriw positive to SR" "\x00\x7c\x00\x0a"
+run_test_simple "andiw positive to SR" "\x02\x7c\x00\x0a"
+run_test_simple "eoriw positive to SR" "\x0a\x7c\x00\x0a"
+run_test_simple "andib positive to CCR" "\x02\x3c\x00\x0a"
+run_test_simple "eorib positive to CCR" "\x0a\x3c\x00\x0a"
+run_test_simple "orib positive to Dn" "\x00\x07\x00\x0a"
+run_test_simple "oriw positive to Dn" "\x00\x45\x00\x0a"
+run_test_simple "oril positive to Dn" "\x00\x83\x00\x00\x00\x0a"
+run_test_simple "andib negative to Dn" "\x00\x07\xff\x80"
+run_test_simple "andiw negative to Dn" "\x00\x45\xff\x80"
+run_test_simple "andil negative to Dn" "\x00\x83\xff\x80\x00\x00"
+run_test_simple "addiw zero to (An)+" "\x06\x5a\x00\x00"
+run_test_simple "subiw zero from -(An)" "\x06\x62\x00\x00"
+run_test_simple "cmpib zero to (An)" "\x0c\x12\x00\x20"
+run_test_simple "cmpiw zero to (An)" "\x0c\x52\x00\x30"
+run_test_simple "cmpil zero to (An)" "\x0c\x92\x00\x00\x00\x40"
+# From random tests
+run_test_expect_short "cmpil with invalid opsize" "\x0c\xe4\x26\xa3"
+
# 4axx
#
run_test_simple "tas Dn" "\x4a\xc2"
@@ -356,6 +384,12 @@ run_test_simple "blts" "\x6d\x0a"
run_test_simple "bgts" "\x6e\x0a"
run_test_simple "bles" "\x6f\x0a"
+# 4afc
+#
+# reset
+#
+run_test_simple "illegal" "\x4a\xfc"
+
# 4e70
#
# reset