91 lines
3.1 KiB
Python
91 lines
3.1 KiB
Python
import json
|
|
import tempfile
|
|
import unittest
|
|
from pathlib import Path
|
|
|
|
from h8536.model import Instruction
|
|
from h8536.peripheral_access import analyze_peripheral_access, peripheral_comment_for_instruction
|
|
from h8536.render import write_json
|
|
from h8536.tables import IO_REGISTERS
|
|
|
|
|
|
class PeripheralAccessTest(unittest.TestCase):
|
|
def test_frt1_manual_register_map_has_full_16_bit_pairs(self):
|
|
self.assertEqual(IO_REGISTERS[0xFE94], "FRT1_OCRA_H")
|
|
self.assertEqual(IO_REGISTERS[0xFE95], "FRT1_OCRA_L")
|
|
self.assertEqual(IO_REGISTERS[0xFE98], "FRT1_ICR_H")
|
|
|
|
def test_frt_word_access_is_marked_as_temp_safe(self):
|
|
instructions = {
|
|
0x1000: Instruction(
|
|
0x1000,
|
|
bytes.fromhex("1DFEA2051234"),
|
|
"MOV:G.W",
|
|
"#H'1234, @FRT2_FRC_H",
|
|
references=[0xFEA2],
|
|
),
|
|
}
|
|
|
|
analysis = analyze_peripheral_access(instructions)
|
|
|
|
self.assertIn("TEMP byte-order hazard avoided", peripheral_comment_for_instruction(analysis, 0x1000))
|
|
self.assertEqual(analysis["warnings"], [])
|
|
|
|
def test_low_byte_read_before_high_byte_warns(self):
|
|
instructions = {
|
|
0x1000: Instruction(
|
|
0x1000,
|
|
bytes.fromhex("15FEE105"),
|
|
"MOV:G.B",
|
|
"@ADDRA_L, R0",
|
|
references=[0xFEE1],
|
|
),
|
|
}
|
|
|
|
analysis = analyze_peripheral_access(instructions)
|
|
|
|
self.assertEqual(len(analysis["warnings"]), 1)
|
|
self.assertIn("low byte read before matching high byte", analysis["warnings"][0]["message"])
|
|
self.assertIn("check TEMP ordering", peripheral_comment_for_instruction(analysis, 0x1000))
|
|
|
|
def test_ad_upper_byte_read_alone_is_allowed_for_8_bit_accuracy(self):
|
|
instructions = {
|
|
0x1000: Instruction(
|
|
0x1000,
|
|
bytes.fromhex("15FEE005"),
|
|
"MOV:G.B",
|
|
"@ADDRA_H, R0",
|
|
references=[0xFEE0],
|
|
),
|
|
}
|
|
|
|
analysis = analyze_peripheral_access(instructions)
|
|
|
|
self.assertEqual(analysis["warnings"], [])
|
|
self.assertIn("valid 8-bit result", peripheral_comment_for_instruction(analysis, 0x1000))
|
|
|
|
def test_json_includes_top_level_warnings_and_instruction_metadata(self):
|
|
instructions = {
|
|
0x1000: Instruction(
|
|
0x1000,
|
|
b"",
|
|
"MOV:G.B",
|
|
"@ADDRA_L, R0",
|
|
references=[0xFEE1],
|
|
),
|
|
}
|
|
analysis = analyze_peripheral_access(instructions)
|
|
|
|
with tempfile.TemporaryDirectory() as tmp:
|
|
path = Path(tmp) / "out.json"
|
|
write_json(path, instructions, {}, {}, peripheral_access=analysis)
|
|
payload = json.loads(path.read_text(encoding="utf-8"))
|
|
|
|
self.assertEqual(payload["peripheral_access"]["warnings"][0]["register"], "ADDRA")
|
|
instruction = payload["instructions"][0]
|
|
self.assertEqual(instruction["peripheral_access"][0]["register"], "ADDRA")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|