summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOxore <oxore@protonmail.com>2023-04-27 22:31:45 +0300
committerOxore <oxore@protonmail.com>2023-04-27 22:31:45 +0300
commitf29646694f52c4af4957c2263c8d44b91a0ae781 (patch)
tree245df7658a069d41149104fdc9873a89df1376b6
parent75859934969958223cdec7716a1f07c933b09217 (diff)
Impl addq and subq
-rw-r--r--disasm.cpp187
1 files changed, 128 insertions, 59 deletions
diff --git a/disasm.cpp b/disasm.cpp
index 4a25551..3b996a4 100644
--- a/disasm.cpp
+++ b/disasm.cpp
@@ -280,20 +280,108 @@ enum class OpSize {
kInvalid = 3,
};
-static void disasm_subq(
- DisasmNode& n, uint16_t instr, const DataBuffer &c, const Settings &s, int m, OpSize opsize)
+static char suffix_from_opsize(OpSize opsize)
{
- (void) m;
- (void) opsize;
- return disasm_verbatim(n, instr, c, s);
+ switch (opsize) {
+ case OpSize::kByte: return 'b';
+ case OpSize::kWord: return 'w';
+ case OpSize::kLong: return 'l';
+ case OpSize::kInvalid: return 'l';
+ }
+ return 'l';
}
-static void disasm_addq(
- DisasmNode& n, uint16_t instr, const DataBuffer &c, const Settings &s, int m, OpSize opsize)
+static void disasm_addq_subq(
+ DisasmNode& node, uint16_t instr, const DataBuffer &code, const Settings &s, int m, OpSize opsize)
{
- (void) m;
- (void) opsize;
- return disasm_verbatim(n, instr, c, s);
+ const char *mnemonic = (instr >> 8) & 1 ? "subq" : "addq";
+ const char suffix = suffix_from_opsize(opsize);
+ const unsigned imm = ((uint8_t((instr >> 9) & 7) - 1) & 7) + 1;
+ const int xn = (instr & 7);
+ switch (m) {
+ case 0: // 5x00..5x07 / 5x40..5x47 / 5x80..5x87, Dn
+ node.size = kInstructionSizeStepBytes;
+ snprintf(node.mnemonic, kMnemonicBufferSize, "%s%c", mnemonic, suffix);
+ snprintf(node.arguments, kArgsBufferSize, "#%u,%%d%d", imm, xn);
+ return;
+ case 1: // 5x08..5x0f / 5x48..5x4f / 5x88..5x8f, An
+ if (opsize == OpSize::kByte) {
+ // 5x08..5x0f
+ // addqb and subqb with An do not exist
+ return disasm_verbatim(node, instr, code, s);
+ }
+ node.size = kInstructionSizeStepBytes;
+ snprintf(node.mnemonic, kMnemonicBufferSize, "%s%c", mnemonic, suffix);
+ snprintf(node.arguments, kArgsBufferSize, "#%u,%%a%d", imm, xn);
+ return;
+ case 2: // 5x10..5x17 / 5x50..5x57 / 5x90..5x97, (An)
+ node.size = kInstructionSizeStepBytes;
+ snprintf(node.mnemonic, kMnemonicBufferSize, "%s%c", mnemonic, suffix);
+ snprintf(node.arguments, kArgsBufferSize, "#%u,%%a%d@", imm, xn);
+ return;
+ case 3: // 5x18..5x1f / 5x58..5x5f / 5x98..5x9f, (An)+
+ node.size = kInstructionSizeStepBytes;
+ snprintf(node.mnemonic, kMnemonicBufferSize, "%s%c", mnemonic, suffix);
+ snprintf(node.arguments, kArgsBufferSize, "#%u,%%a%d@+", imm, xn);
+ return;
+ case 4: // 5x20..5x27 / 5x60..5x67 / 5xa0..5xa7, -(An)
+ node.size = kInstructionSizeStepBytes;
+ snprintf(node.mnemonic, kMnemonicBufferSize, "%s%c", mnemonic, suffix);
+ snprintf(node.arguments, kArgsBufferSize, "#%u,%%a%d@-", imm, xn);
+ return;
+ case 5: // 5x28..5x2f / 5x68..5x6f / 5xa8..5xaf, (d16, An), Displacement Word
+ node.size = kInstructionSizeStepBytes * 2;
+ snprintf(node.mnemonic, kMnemonicBufferSize, "%s%c", mnemonic, suffix);
+ {
+ const int16_t dispmt = GetI16BE(code.buffer + node.offset + kInstructionSizeStepBytes);
+ snprintf(node.arguments, kArgsBufferSize, "#%u,%%a%d@(%d:w)", imm, xn, dispmt);
+ }
+ return;
+ case 6: // 5x30..5x37 / 5x70..5x77 / 5xb0..5xb7, (d16, An, Xi), Brief Extension Word
+ node.size = kInstructionSizeStepBytes * 2;
+ snprintf(node.mnemonic, kMnemonicBufferSize, "%s%c", mnemonic, suffix);
+ {
+ const uint16_t briefext = GetU16BE(code.buffer + node.offset + kInstructionSizeStepBytes);
+ const char reg = ((briefext >> 15) & 1) ? 'a' : 'd';
+ const int xi = (briefext >> 12) & 7;
+ const char size_spec = ((briefext >> 11) & 1) ? 'l' : 'w';
+ const int8_t dispmt = briefext & 0xff;
+ snprintf(node.arguments, kArgsBufferSize,
+ "#%u,%%a%d@(%d,%%%c%d:%c)", imm, xn, dispmt, reg, xi, size_spec);
+ }
+ return;
+ case 7: // 5x38..5x3f / 5x78..5x7f / 5xb8..5xbf
+ switch (xn) {
+ case 0: // 5x38 / 5x78 / 5xb8 (xxx).W
+ node.size = kInstructionSizeStepBytes * 2;
+ snprintf(node.mnemonic, kMnemonicBufferSize, "%s%c", mnemonic, suffix);
+ {
+ // This shit is real: it is sign extend value
+ const int32_t dispmt = GetI16BE(code.buffer + node.offset + kInstructionSizeStepBytes);
+ snprintf(node.arguments, kArgsBufferSize, "#%u,0x%x:w", imm, dispmt);
+ return;
+ }
+ return;
+ case 1: // 5x39 / 5x79 / 5xb9 (xxx).L
+ node.size = kInstructionSizeStepBytes * 3;
+ snprintf(node.mnemonic, kMnemonicBufferSize, "%s%c", mnemonic, suffix);
+ {
+ const int32_t dispmt = GetI32BE(code.buffer + node.offset + kInstructionSizeStepBytes);
+ snprintf(node.arguments, kArgsBufferSize, "#%u,0x%x:l", imm, dispmt);
+ return;
+ }
+ return;
+ case 2: // 5x3a / 5x7a / 5xba
+ case 3: // 5x3b / 5x7b / 5xbb
+ case 4: // 5x3c / 5x7c / 5xbc
+ case 5: // 5x3d / 5x7d / 5xbd
+ case 6: // 5x3e / 5x7e / 5xbe
+ // Does not exist
+ break;
+ }
+ break;
+ }
+ return disasm_verbatim(node, instr, code, s);
}
static inline const char *scc_mnemonic_by_condition(Condition condition)
@@ -373,7 +461,7 @@ static void disasm_scc(
return;
case 7: // 5xf8..5xff
switch (xn) {
- case 0: // 4eb8 (xxx).W
+ case 0: // 5xf8 (xxx).W
node.size = kInstructionSizeStepBytes * 2;
snprintf(node.mnemonic, kMnemonicBufferSize, mnemonic);
{
@@ -383,7 +471,7 @@ static void disasm_scc(
return;
}
return;
- case 1: // 4eb9 (xxx).L
+ case 1: // 5xf9 (xxx).L
node.size = kInstructionSizeStepBytes * 3;
snprintf(node.mnemonic, kMnemonicBufferSize, mnemonic);
{
@@ -392,11 +480,11 @@ static void disasm_scc(
return;
}
return;
- case 2: // 4eba
- case 3: // 4ebb
- case 4: // 4ebc
- case 5: // 4ebd
- case 6: // 4ebe
+ case 2: // 5xfa
+ case 3: // 5xfb
+ case 4: // 5xfc
+ case 5: // 5xfd
+ case 6: // 5xfe
// Does not exist
break;
}
@@ -457,19 +545,12 @@ static void chunk_mf000_v5000(DisasmNode& n, uint16_t instr, const DataBuffer &c
}
return disasm_scc(n, instr, c, s, m);
}
- if ((instr >> 8) & 1) {
- return disasm_subq(n, instr, c, s, m, opsize);
- }
- return disasm_addq(n, instr, c, s, m, opsize);
+ return disasm_addq_subq(n, instr, c, s, m, opsize);
}
-static void chunk_mf000_v6000(DisasmNode& n, uint16_t i, const DataBuffer &c, const Settings &s)
-{
- return disasm_bra_bsr_bcc(n, i, c, s);
-}
-
-static void chunk_mf000_v7000(DisasmNode& n, uint16_t i, const DataBuffer &c, const Settings &s)
+static void disasm_moveq(DisasmNode& n, uint16_t i, const DataBuffer &c, const Settings &s)
{
+ // TODO
return disasm_verbatim(n, i, c, s);
}
@@ -483,11 +564,6 @@ static void chunk_mf000_v9000(DisasmNode& n, uint16_t i, const DataBuffer &c, co
return disasm_verbatim(n, i, c, s);
}
-static void chunk_mf000_va000(DisasmNode& n, uint16_t i, const DataBuffer &c, const Settings &s)
-{
- return disasm_verbatim(n, i, c, s);
-}
-
static void chunk_mf000_vb000(DisasmNode& n, uint16_t i, const DataBuffer &c, const Settings &s)
{
return disasm_verbatim(n, i, c, s);
@@ -508,35 +584,28 @@ static void chunk_mf000_ve000(DisasmNode& n, uint16_t i, const DataBuffer &c, co
return disasm_verbatim(n, i, c, s);
}
-static void chunk_mf000_vf000(DisasmNode& n, uint16_t i, const DataBuffer &c, const Settings &s)
-{
- return disasm_verbatim(n, i, c, s);
-}
-
-static void (*disasm_mf000[16])(DisasmNode&, uint16_t, const DataBuffer &, const Settings &s) = {
- chunk_mf000_v0000,
- chunk_mf000_v1000,
- chunk_mf000_v2000,
- chunk_mf000_v3000,
- chunk_mf000_v4000,
- chunk_mf000_v5000,
- chunk_mf000_v6000,
- chunk_mf000_v7000,
- chunk_mf000_v8000,
- chunk_mf000_v9000,
- chunk_mf000_va000,
- chunk_mf000_vb000,
- chunk_mf000_vc000,
- chunk_mf000_vd000,
- chunk_mf000_ve000,
- chunk_mf000_vf000,
-};
-
static void m68k_disasm(DisasmNode& n, uint16_t i, const DataBuffer &c, const Settings &s)
{
- const size_t selector = (i & 0xf000) >> 12;
- assert(selector < 16);
- return (disasm_mf000[selector])(n, i, c, s);
+ switch ((i & 0xf000) >> 12) {
+ case 0x0: return chunk_mf000_v0000(n, i, c, s);
+ case 0x1: return chunk_mf000_v1000(n, i, c, s);
+ case 0x2: return chunk_mf000_v2000(n, i, c, s);
+ case 0x3: return chunk_mf000_v3000(n, i, c, s);
+ case 0x4: return chunk_mf000_v4000(n, i, c, s);
+ case 0x5: return chunk_mf000_v5000(n, i, c, s);
+ case 0x6: return disasm_bra_bsr_bcc(n, i, c, s);
+ case 0x7: return disasm_moveq(n, i, c, s);
+ case 0x8: return chunk_mf000_v8000(n, i, c, s);
+ case 0x9: return chunk_mf000_v9000(n, i, c, s);
+ case 0xa: return disasm_verbatim(n, i, c, s);
+ case 0xb: return chunk_mf000_vb000(n, i, c, s);
+ case 0xc: return chunk_mf000_vc000(n, i, c, s);
+ case 0xd: return chunk_mf000_vd000(n, i, c, s);
+ case 0xe: return chunk_mf000_ve000(n, i, c, s);
+ case 0xf: return disasm_verbatim(n, i, c, s);
+ }
+ assert(false);
+ return disasm_verbatim(n, i, c, s);
}
void DisasmNode::Disasm(const DataBuffer &code, const Settings &s)