Emulator learnings folded back into decompiler
This commit is contained in:
@@ -73,8 +73,19 @@ def fixture_payload() -> dict[str, object]:
|
||||
ins(0xBECB, "BTST.B #7, @H'FAA3", references=[0xFAA3]),
|
||||
ins(0xBED1, "CLR.B @H'F9C3", references=[0xF9C3]),
|
||||
ins(0xBED5, "BSR loc_BA26", targets=[0xBA26]),
|
||||
ins(0xBEEA, "BCLR.B #5, @FRT1_TCSR"),
|
||||
ins(0xBEEE, "TST.B @H'F9C0", references=[0xF9C0]),
|
||||
ins(0xBEF2, "BEQ loc_BEF8", targets=[0xBEF8]),
|
||||
ins(0xBEF4, "ADD:Q.B #-1, @H'F9C0", references=[0xF9C0]),
|
||||
ins(0xBEF8, "TST.B @H'F9C1", references=[0xF9C1]),
|
||||
ins(0xBEFC, "BEQ loc_BF02", targets=[0xBF02]),
|
||||
ins(0xBEFE, "ADD:Q.B #-1, @H'F9C1", references=[0xF9C1]),
|
||||
ins(0xBF02, "TST.W @H'F9C6", references=[0xF9C6]),
|
||||
ins(0xBF06, "BEQ loc_BF0C", targets=[0xBF0C]),
|
||||
ins(0xBF08, "ADD:Q.W #-1, @H'F9C6", references=[0xF9C6]),
|
||||
]
|
||||
return {
|
||||
"vectors": [{"address": 0x0062, "name": "frt1_ocia", "target": 0xBEEA, "target_label": "vec_frt1_ocia_BEEA"}],
|
||||
"call_graph": {"nodes": [{"start": 0x3FD3, "label": "loc_3FD3"}, {"start": 0xBAF2, "label": "loc_BAF2"}]},
|
||||
"instructions": rows,
|
||||
}
|
||||
@@ -95,12 +106,26 @@ class SerialGateTest(unittest.TestCase):
|
||||
self.assertTrue(analysis["evidence"]["rx_session_maintenance"]["present"])
|
||||
self.assertTrue(any("0x0007" in caveat and "0x0015" in caveat for caveat in analysis["caveats"]))
|
||||
|
||||
def test_json_analysis_includes_frt1_tick_timer_roles(self):
|
||||
analysis = analyze_serial_gate(fixture_payload())
|
||||
tick = analysis["evidence"]["timer_tick_evidence"]
|
||||
|
||||
self.assertTrue(tick["present"])
|
||||
self.assertEqual(tick["vector_address_hex"], "H'0062")
|
||||
self.assertEqual(tick["handler_address_hex"], "H'BEEA")
|
||||
self.assertIn("FRT1_TCSR.OCFA", tick["summary"])
|
||||
roles = {role["address"]: role for role in tick["candidate_timer_roles"]}
|
||||
self.assertIn("post-TX/report delay", roles[0xF9C0]["role"])
|
||||
self.assertIn("secondary delay", roles[0xF9C1]["role"])
|
||||
self.assertIn("periodic report/heartbeat", roles[0xF9C6]["role"])
|
||||
|
||||
def test_summarizes_key_state_readers_and_writers(self):
|
||||
analysis = analyze_serial_gate(fixture_payload())
|
||||
accesses = {entry["address"]: entry for entry in analysis["state_accesses"]}
|
||||
|
||||
self.assertGreaterEqual(accesses[0xF9B5]["read_count"], 1)
|
||||
self.assertGreaterEqual(accesses[0xF9B5]["read_write_count"], 1)
|
||||
self.assertGreaterEqual(accesses[0xF9C1]["read_write_count"], 1)
|
||||
self.assertGreaterEqual(accesses[0xFAA3]["write_count"], 1)
|
||||
self.assertIn("sample_accesses", accesses[0xFAA2])
|
||||
|
||||
@@ -111,6 +136,15 @@ class SerialGateTest(unittest.TestCase):
|
||||
self.assertIn("capture overlays/runtime queue entries", text)
|
||||
self.assertIn("H'F9B5", text)
|
||||
|
||||
def test_text_report_mentions_frt1_tick_timer_roles(self):
|
||||
text = format_text_report(analyze_serial_gate(fixture_payload()))
|
||||
|
||||
self.assertIn("FRT1 OCIA periodic tick countdowns: present", text)
|
||||
self.assertIn("H'BEEA: BCLR.B #5, @FRT1_TCSR", text)
|
||||
self.assertIn("H'F9C0: candidate post-TX/report delay countdown", text)
|
||||
self.assertIn("H'F9C1: candidate secondary delay countdown", text)
|
||||
self.assertIn("H'F9C6: candidate periodic report/heartbeat countdown", text)
|
||||
|
||||
def test_cli_json_output_and_out_file(self):
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
input_path = Path(tmp) / "rom.json"
|
||||
|
||||
Reference in New Issue
Block a user