1
0

Data flow improvements in pseudo code generator

This commit is contained in:
Aiden
2026-05-25 14:40:55 +10:00
parent 80819448cf
commit 1d7f00e59c
16 changed files with 105891 additions and 5141 deletions

View File

@@ -0,0 +1,132 @@
import unittest
from h8536.pseudocode import PseudocodeOptions, generate_pseudocode
def _instruction(
address,
mnemonic,
operands="",
*,
kind="normal",
targets=None,
text=None,
):
return {
"address": address,
"text": text or f"{mnemonic} {operands}".strip(),
"mnemonic": mnemonic,
"operands": operands,
"kind": kind,
"targets": list(targets or []),
"references": [],
"comment": "",
}
def _payload(instructions):
start = min(ins["address"] for ins in instructions)
end = max(ins["address"] for ins in instructions)
return {
"vectors": [],
"call_graph": {
"nodes": [
{
"start": start,
"end": end,
"label": f"loc_{start:04X}",
"sources": [],
"instruction_count": len(instructions),
"calls": [],
}
],
"edges": [],
},
"instructions": instructions,
}
def _options(**overrides):
values = {
"include_asm": False,
"include_addresses": False,
"emit_declarations": False,
}
values.update(overrides)
return PseudocodeOptions(**values)
class PseudocodeStructuringTest(unittest.TestCase):
def test_backward_conditional_branch_becomes_do_while(self):
payload = _payload(
[
_instruction(0x0100, "MOV.B", "#H'00, R0"),
_instruction(0x0102, "ADD.B", "#H'01, R0"),
_instruction(0x0104, "CMP.B", "#H'03, R0"),
_instruction(0x0106, "BNE", "loc_0102", kind="branch", targets=[0x0102]),
_instruction(0x0108, "RTS", kind="return"),
]
)
text = generate_pseudocode(payload, options=_options())
self.assertIn("do {", text)
self.assertIn("} while (!Z);", text)
self.assertNotIn("goto loc_0102;", text)
self.assertNotIn("loc_0102:", text)
def test_forward_conditional_branch_over_small_span_becomes_if(self):
payload = _payload(
[
_instruction(0x0100, "CMP.B", "#H'00, R0"),
_instruction(0x0102, "BEQ", "loc_0108", kind="branch", targets=[0x0108]),
_instruction(0x0104, "MOV.B", "#H'01, R1"),
_instruction(0x0106, "ADD.B", "#H'02, R1"),
_instruction(0x0108, "RTS", kind="return"),
]
)
text = generate_pseudocode(payload, options=_options())
self.assertIn("if (!Z) {", text)
self.assertIn("R1 = (uint8_t)(0x01);", text)
self.assertIn("R1 += (uint8_t)(0x02);", text)
self.assertNotIn("goto loc_0108;", text)
self.assertNotIn("loc_0108:", text)
def test_structuring_can_be_disabled(self):
payload = _payload(
[
_instruction(0x0100, "CMP.B", "#H'00, R0"),
_instruction(0x0102, "BEQ", "loc_0108", kind="branch", targets=[0x0108]),
_instruction(0x0104, "MOV.B", "#H'01, R1"),
_instruction(0x0108, "RTS", kind="return"),
]
)
text = generate_pseudocode(payload, options=_options(structured=False))
self.assertIn("if (Z) goto loc_0108;", text)
self.assertIn("loc_0108:", text)
self.assertNotIn("if (!Z) {", text)
def test_ambiguous_forward_branch_keeps_goto_fallback(self):
payload = _payload(
[
_instruction(0x0100, "BEQ", "loc_0108", kind="branch", targets=[0x0108]),
_instruction(0x0102, "MOV.B", "#H'01, R1"),
_instruction(0x0104, "BRA", "loc_0108", kind="jump", targets=[0x0108]),
_instruction(0x0108, "RTS", kind="return"),
]
)
text = generate_pseudocode(payload, options=_options())
self.assertIn("if (Z) goto loc_0108;", text)
self.assertIn("goto loc_0108;", text)
self.assertIn("loc_0108:", text)
self.assertNotIn("if (!Z) {", text)
if __name__ == "__main__":
unittest.main()