diff options
Diffstat (limited to 'src/disasm.h')
-rw-r--r-- | src/disasm.h | 111 |
1 files changed, 99 insertions, 12 deletions
diff --git a/src/disasm.h b/src/disasm.h index 2a6a1d0..13109a5 100644 --- a/src/disasm.h +++ b/src/disasm.h @@ -25,18 +25,28 @@ struct ReferenceRecord { uint32_t address{}; }; +enum class DisasmMapType { + kTraced, + kRaw, +}; + enum class NodeType { kTracedInstruction, kRefInstruction, - kData, + kRefData, }; +static constexpr uint32_t AlignInstructionAddress(const uint32_t address) +{ + return address & ~1UL; +} + struct DisasmNode { const NodeType type{}; /// Address of the instruction (PC value basically) const uint32_t address{}; /// Instruction size in bytes - size_t size{kInstructionSizeStepBytes}; + size_t size{selectSize(type, kInstructionSizeStepBytes)}; /// Indicates whether `ref_addr` should be interpreted and how RefKindMask ref_kinds{}; /// Address of first argument reference @@ -46,6 +56,48 @@ struct DisasmNode { ReferenceRecord *ref_by{}; ReferenceRecord *last_ref_by{}; Op op{}; + static DisasmNode Simple(NodeType t, uint32_t address) + { + return DisasmNode{ + /* .type = */ t, + /* .address = */ alignAddress(NodeType::kTracedInstruction, address), + /* .size = */ selectSize(t, (address & 1) ? 1 : 2), + /* .ref_kinds = */ 0, + /* .ref1_addr = */ 0, + /* .ref2_addr = */ 0, + /* .ref_by = */ nullptr, + /* .last_ref_by = */ nullptr, + /* .op = */ selectOp(t, (address & 1) ? 1 : 2), + }; + } + static DisasmNode TracedRaw(uint32_t address, uint16_t raw) + { + return DisasmNode{ + /* .type = */ NodeType::kTracedInstruction, + /* .address = */ alignAddress(NodeType::kTracedInstruction, address), + /* .size = */ sizeof(raw), + /* .ref_kinds = */ 0, + /* .ref1_addr = */ 0, + /* .ref2_addr = */ 0, + /* .ref_by = */ nullptr, + /* .last_ref_by = */ nullptr, + /* .op = */ Op::Raw(raw), + }; + } + static DisasmNode DataRaw8(uint32_t address, uint8_t raw) + { + return DisasmNode{ + /* .type = */ NodeType::kRefData, + /* .address = */ address, + /* .size = */ sizeof(raw), + /* .ref_kinds = */ 0, + /* .ref1_addr = */ 0, + /* .ref2_addr = */ 0, + /* .ref_by = */ nullptr, + /* .last_ref_by = */ nullptr, + /* .op = */ Op::Raw8(raw), + }; + } /*! Disassembles instruction with arguments * returns size of whole instruction with arguments in bytes @@ -53,7 +105,46 @@ struct DisasmNode { size_t Disasm(const DataView &code, const Settings &); size_t DisasmAsRaw(const DataView &code); void AddReferencedBy(uint32_t address, ReferenceType); + bool IsYetToBeHandled(DisasmMapType dmtype) + { + return op.opcode == OpCode::kNone || + (dmtype == DisasmMapType::kRaw && op.opcode == OpCode::kRaw); + } ~DisasmNode(); +private: + static constexpr uint32_t alignAddress(NodeType t, uint32_t address) + { + switch (t) { + case NodeType::kTracedInstruction: + case NodeType::kRefInstruction: + return AlignInstructionAddress(address); + case NodeType::kRefData: + return address; + } + return address; + } + static constexpr uint32_t selectSize(NodeType t, size_t size) + { + switch (t) { + case NodeType::kTracedInstruction: + case NodeType::kRefInstruction: + return kInstructionSizeStepBytes; + case NodeType::kRefData: + return size; + } + return 1; + } + static constexpr Op selectOp(NodeType t, size_t size) + { + switch (t) { + case NodeType::kTracedInstruction: + case NodeType::kRefInstruction: + return Op{}; + case NodeType::kRefData: + return (size & 1) ? Op::Raw8(0) : Op::Raw(0); + } + return Op{}; + } }; static constexpr inline bool IsInstruction(NodeType t) @@ -74,14 +165,10 @@ struct Symbol { size_t size{}; }; -enum class DisasmMapType { - kTraced, - kRaw, -}; - class DisasmMap { const DisasmMapType _type; - DisasmNode *_map[kDisasmMapSizeElements]{}; + DisasmNode **_map{static_cast<DisasmNode **>(calloc(kRomSizeBytes, sizeof(*_map)))}; + size_t _code_size{}; Symbol *_symtab{}; size_t _symtab_size{}; TraceTable _tt{}; @@ -116,7 +203,7 @@ public: constexpr DisasmNode *DisasmMap::findNodeByAddress(uint32_t address) const { if (address < kRomSizeBytes) - return _map[address / kInstructionSizeStepBytes]; + return _map[address]; return nullptr; } @@ -191,10 +278,10 @@ constexpr bool DisasmMap::HasSymbolsInRange( constexpr bool DisasmMap::canBeAllocated(const DisasmNode& node) const { - const auto size = node.size / kInstructionSizeStepBytes; + const auto size = node.size; const auto *const node_real = findNodeByAddress(node.address); - for (size_t i = 1; i < size; i++) { - const auto *const ptr = _map[node.address / kInstructionSizeStepBytes + i]; + for (size_t i = 0; i < size; i++) { + const auto *const ptr = _map[node.address + i]; if (ptr != nullptr && ptr != node_real) { return false; } |