summaryrefslogtreecommitdiff
path: root/src/disasm.h
diff options
context:
space:
mode:
authorOxore <oxore@protonmail.com>2025-01-08 00:46:44 +0300
committerOxore <oxore@protonmail.com>2025-02-01 18:26:18 +0300
commit6769fca1dd90f4e34e1fd6b2256c3795bbcaf658 (patch)
tree80899430ea776d80b98be4e198591a61f8384d16 /src/disasm.h
parent8340b1f42288e0143bca8a254600fb34025ec803 (diff)
WIP
Diffstat (limited to 'src/disasm.h')
-rw-r--r--src/disasm.h111
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;
}