Data flow improvements in pseudo code generator
This commit is contained in:
72
tests/test_indirect_flow.py
Normal file
72
tests/test_indirect_flow.py
Normal file
@@ -0,0 +1,72 @@
|
||||
import unittest
|
||||
|
||||
from h8536.indirect import analyze_indirect_flow, indirect_comment_for_instruction
|
||||
from h8536.model import Instruction
|
||||
from h8536.render import format_listing, write_json
|
||||
from h8536.rom import Rom
|
||||
import json
|
||||
import tempfile
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
class IndirectFlowTest(unittest.TestCase):
|
||||
def test_detects_indexed_pointer_table_before_indirect_jump(self):
|
||||
data = bytearray([0xFF] * 0x240)
|
||||
data[0x0200:0x0206] = bytes.fromhex("01200300FFFF")
|
||||
instructions = {
|
||||
0x0100: Instruction(0x0100, b"", "MOV:G.W", "@(H'0200,R4), R1"),
|
||||
0x0104: Instruction(0x0104, b"", "JMP", "@R1", kind="jump", fallthrough=False),
|
||||
0x0120: Instruction(0x0120, b"\x19", "RTS", kind="return", fallthrough=False),
|
||||
0x0300: Instruction(0x0300, b"\x19", "RTS", kind="return", fallthrough=False),
|
||||
}
|
||||
|
||||
analysis = analyze_indirect_flow(Rom(bytes(data)), instructions, {0x0120: "loc_0120"})
|
||||
site = analysis["sites"][0]
|
||||
|
||||
self.assertEqual(site["address"], 0x0104)
|
||||
self.assertEqual(site["target_register"], "R1")
|
||||
self.assertEqual(site["table"]["base"], 0x0200)
|
||||
self.assertEqual(site["table"]["entry_count"], 2)
|
||||
self.assertEqual(site["table"]["decoded_target_count"], 2)
|
||||
self.assertIn("pointer table H'0200", indirect_comment_for_instruction(analysis, 0x0104))
|
||||
|
||||
def test_records_unknown_indirect_call_without_prior_table_load(self):
|
||||
instructions = {
|
||||
0x0100: Instruction(0x0100, b"", "JSR", "@R0", kind="call"),
|
||||
}
|
||||
|
||||
analysis = analyze_indirect_flow(Rom(bytes([0xFF] * 0x200)), instructions)
|
||||
|
||||
self.assertEqual(analysis["sites"][0]["confidence"], "unknown")
|
||||
self.assertIn("target not resolved", analysis["sites"][0]["summary"])
|
||||
|
||||
def test_listing_and_json_include_indirect_flow_metadata(self):
|
||||
instructions = {
|
||||
0x0100: Instruction(0x0100, b"", "JSR", "@R0", kind="call"),
|
||||
}
|
||||
analysis = analyze_indirect_flow(Rom(bytes([0xFF] * 0x200)), instructions)
|
||||
|
||||
listing = format_listing(
|
||||
Path("rom.bin"),
|
||||
Rom(bytes([0xFF] * 0x200)),
|
||||
instructions,
|
||||
{},
|
||||
{},
|
||||
"min",
|
||||
traced=True,
|
||||
indirect_flow=analysis,
|
||||
)
|
||||
|
||||
self.assertIn("target not resolved", listing)
|
||||
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
path = Path(tmp) / "out.json"
|
||||
write_json(path, instructions, {}, {}, indirect_flow=analysis)
|
||||
payload = json.loads(path.read_text(encoding="utf-8"))
|
||||
|
||||
self.assertEqual(payload["indirect_flow"]["sites"][0]["address"], 0x0100)
|
||||
self.assertEqual(payload["instructions"][0]["indirect_flow"]["confidence"], "unknown")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user