diff options
author | Oxore <oxore@protonmail.com> | 2023-04-23 19:17:01 +0300 |
---|---|---|
committer | Oxore <oxore@protonmail.com> | 2023-04-23 19:17:01 +0300 |
commit | e8bc35a6297da6bea1eed833ac25cfebe1fee355 (patch) | |
tree | 2bf1b5826036bdc51023181ea8ab70a6fb7e0a8e | |
parent | 771b675f2ec83c1b6b2d41d236fc4bd3c368b1cd (diff) |
Impl separate xref types call and branch
-rw-r--r-- | disasm.cpp | 33 | ||||
-rw-r--r-- | disasm.h | 18 | ||||
-rw-r--r-- | main.cpp | 21 |
3 files changed, 62 insertions, 10 deletions
@@ -44,6 +44,7 @@ static void disasm_jsr_jmp( DisasmNode& node, uint16_t instr, const DataBuffer &code, const Settings &s, JsrJmp jsrjmp) { const char *mnemonic = (jsrjmp == JsrJmp::kJsr) ? "jsr" : "jmp"; + node.is_call = (jsrjmp == JsrJmp::kJsr); const int addrmode = instr & 0x3f; const int m = (addrmode >> 3) & 0x7; const int xn = addrmode & 0x7; @@ -52,6 +53,8 @@ static void disasm_jsr_jmp( case 1: // 4e88 .. 4e8f break; case 2: // 4e90 .. 4e97 + // NOTE: dynamic jump, branch_addr may possibly be obtained during the + // trace node.size = kInstructionSizeStepBytes; snprintf(node.mnemonic, kMnemonicBufferSize, "%s", mnemonic); snprintf(node.arguments, kArgsBufferSize, "%%a%d@", xn); @@ -61,6 +64,8 @@ static void disasm_jsr_jmp( break; case 5: // 4ea8 .. 4eaf, Displacement { + // NOTE: dynamic jump, branch_addr may possibly be obtained during + // the trace node.size = kInstructionSizeStepBytes * 2; const int16_t dispmt = GetI16BE(code.buffer + node.offset + kInstructionSizeStepBytes); snprintf(node.mnemonic, kMnemonicBufferSize, "%s", mnemonic); @@ -69,6 +74,8 @@ static void disasm_jsr_jmp( } case 6: // 4eb0 .. 4eb7, Brief Extension Word { + // NOTE: dynamic jump, branch_addr may possibly be obtained during + // the trace node.size = kInstructionSizeStepBytes * 2; const uint16_t briefext = GetU16BE(code.buffer + node.offset + kInstructionSizeStepBytes); const char reg = ((briefext >> 15) & 1) ? 'a' : 'd'; @@ -84,9 +91,15 @@ static void disasm_jsr_jmp( switch (xn) { case 0: // 4eb8 (xxx).W { - // TODO set has_branch_addr and branch_addr node.size = kInstructionSizeStepBytes * 2; + // This shit is real: it is sign extend value const int32_t dispmt = GetI16BE(code.buffer + node.offset + kInstructionSizeStepBytes); + // So jumping to negative value will land PC on something like + // 0xffff8a0c, effectively making jump possible only to lowest + // 32K range 0..0x7fff and highest 32K range + // 0xffff8000...0xffffffff + node.branch_addr = static_cast<uint32_t>(dispmt); + node.has_branch_addr = true; snprintf(node.mnemonic, kMnemonicBufferSize, "%s", mnemonic); snprintf(node.arguments, kArgsBufferSize, "0x%x:w", dispmt); return; @@ -95,20 +108,27 @@ static void disasm_jsr_jmp( { node.size = kInstructionSizeStepBytes * 3; const int32_t dispmt = GetI32BE(code.buffer + node.offset + kInstructionSizeStepBytes); + node.branch_addr = static_cast<uint32_t>(dispmt); + node.has_branch_addr = true; snprintf(node.mnemonic, kMnemonicBufferSize, "%s", mnemonic); snprintf(node.arguments, kArgsBufferSize, "0x%x:l", dispmt); return; } case 2: // 4eba, Displacement { - node.size = kInstructionSizeStepBytes * 2; const int16_t dispmt = GetI16BE(code.buffer + node.offset + kInstructionSizeStepBytes); + // Add 2 to current PC, as usual + node.branch_addr = node.offset + dispmt + kInstructionSizeStepBytes; + node.has_branch_addr = true; + node.size = kInstructionSizeStepBytes * 2; snprintf(node.mnemonic, kMnemonicBufferSize, "%s", mnemonic); snprintf(node.arguments, kArgsBufferSize, "%%pc@(%d:w)", dispmt); return; } case 3: // 4ebb { + // NOTE: dynamic jump, branch_addr may possibly be obtained + // during the trace node.size = kInstructionSizeStepBytes * 2; const uint16_t briefext = GetU16BE( code.buffer + node.offset + kInstructionSizeStepBytes); @@ -188,7 +208,10 @@ static inline const char *branch_instr_name_by_cond(Condition condition) static void disasm_bra_bsr_bcc( DisasmNode& node, uint16_t instr, const DataBuffer &code, const Settings &) { - const char *mnemonic = branch_instr_name_by_cond(static_cast<Condition>((instr >> 8) & 0xf)); + Condition condition = static_cast<Condition>((instr >> 8) & 0xf); + const char *mnemonic = branch_instr_name_by_cond(condition); + // False condition Indicates BSR + node.is_call = (condition == Condition::kF); int dispmt = static_cast<int8_t>(instr & 0xff); const char *size_spec = "s"; if (dispmt == 0) { @@ -236,7 +259,7 @@ void DisasmNode::Disasm(const DataBuffer &code, const Settings &s) } -void DisasmNode::AddReferencedBy(uint32_t offset) +void DisasmNode::AddReferencedBy(uint32_t offset, ReferenceType type) { ReferenceNode *node{}; if (this->last_ref_by) { @@ -246,7 +269,7 @@ void DisasmNode::AddReferencedBy(uint32_t offset) assert(node); this->ref_by = this->last_ref_by = node; } - node->refs[node->refs_count] = offset; + node->refs[node->refs_count] = ReferenceRecord{type, offset}; node->refs_count++; if (node->refs_count >= kRefsCountPerBuffer) { ReferenceNode *new_node = new ReferenceNode{}; @@ -17,9 +17,20 @@ constexpr size_t kMnemonicBufferSize = 8; constexpr size_t kArgsBufferSize = 64; constexpr size_t kMarkBufferSize = 64; +enum class ReferenceType { + kUnknown = 0, + kBranch, + kCall, +}; + +struct ReferenceRecord { + ReferenceType type{}; + uint32_t address{}; +}; + struct ReferenceNode { ReferenceNode *next{}; - uint32_t refs[kRefsCountPerBuffer]; + ReferenceRecord refs[kRefsCountPerBuffer]; uint32_t refs_count{}; }; @@ -33,6 +44,9 @@ struct DisasmNode { bool has_branch_addr{}; /// Absolute address of where to branch to uint32_t branch_addr{}; + /// Indicates whether instruction is a call (BSR, JSR) or just a branch + /// (Bcc, JMP) if `has_branch_addr` is set + bool is_call{}; /// Mnemonic of the instruction at the current offset char mnemonic[kMnemonicBufferSize]{}; /// Formatted arguments of the instruction; @@ -43,7 +57,7 @@ struct DisasmNode { ReferenceNode *ref_by{}; ReferenceNode *last_ref_by{}; void Disasm(const DataBuffer &code, const Settings&); - void AddReferencedBy(uint32_t offset); + void AddReferencedBy(uint32_t offset, ReferenceType); ~DisasmNode(); private: }; @@ -82,7 +82,8 @@ void DisasmMap::DisasmAll(const DataBuffer &code, const Settings & s) auto *ref_node = insertTracedNode( node->branch_addr, TracedNodeType::kInstruction); ref_node->Disasm(code, s); - ref_node->AddReferencedBy(node->offset); + ref_node->AddReferencedBy( + node->offset, node->is_call ? ReferenceType::kCall : ReferenceType::kBranch); } } } @@ -115,6 +116,16 @@ static size_t RenderRawDataComment( return overall_sz; } +static const char *ReferenceTypeToString(ReferenceType type) +{ + switch (type) { + case ReferenceType::kUnknown: return "UNKN"; + case ReferenceType::kBranch: return "BRANCH"; + case ReferenceType::kCall: return "CALL"; + } + return "UNKN"; +} + static void RenderDisassembly( FILE *output, const DisasmMap &disasm_map, const DataBuffer &code, const Settings &) { @@ -124,11 +135,15 @@ static void RenderDisassembly( char comment[100]{}; RenderRawDataComment(comment, sizeof(comment) - 1, node->offset, node->size, code); if (node->ref_by) { - fprintf(output, "| Referenced by:\n"); + fprintf(output, "| XREFS:\n"); for (ReferenceNode *ref{node->ref_by}; ref; ref = ref->next) { + if (ref->refs_count == 0) { + continue; + } fprintf(output, "|"); for (size_t i = 0; i < ref->refs_count; i++) { - fprintf(output, " @%08x", ref->refs[i]); + const ReferenceRecord r = ref->refs[i]; + fprintf(output, " %s @%08x", ReferenceTypeToString(r.type), r.address); } fprintf(output, "\n"); } |