gigatron/rom/Contrib/psr/multiply/test/test_sysfunction.py
2025-01-28 19:17:01 +03:00

112 lines
4.6 KiB
Python

"""Tests for the implementation of SYS_MultiplyBytes_126"""
import os.path
import pathlib
from importlib import reload
from types import SimpleNamespace
from hypothesis import given
from hypothesis import strategies as st
import asm
from gtemu import RAM, Emulator
MAX_CYCLES = 120
SYS_DIR = (pathlib.Path(__file__).parent / ".." / "sys").resolve()
SCRIPT = SYS_DIR / "ROM.asm.py"
def setup_module():
global vars
"""Load the Emulator from the ROM script"""
reload(asm)
name, _ = os.path.splitext(os.path.basename(SCRIPT))
script_globals = {"__file__": str(SCRIPT.absolute()), "__name__": name}
with SCRIPT.open("rb") as file:
exec(compile(file.read(), SCRIPT, "exec"), script_globals)
Emulator.load_rom_from_asm_module()
vars = SimpleNamespace(**script_globals)
def setup_function():
RAM[vars.sysFn : vars.sysFn + 2] = asm.symbol("SYS_MultiplyBytes_120").to_bytes(
2, "little"
)
RAM[vars.vTicks] = 75
Emulator.next_instruction = "SYS"
Emulator.AC = 270 - max(14, MAX_CYCLES // 2)
def test_timing_both_lt_128():
"""Follow the routine through, checking the timing comments
This follows the case where both values are less than 128
I'm just trying to check that the comments are correct!
"""
RAM[vars.sysArgs : vars.sysArgs + 2] = 3, 5
# fmt: off
cycles = 9 # On entry to SYS, 9 cycles have already elapsed
cycles += Emulator.run_to("SYS_MultiplyBytes_120"); assert 14 == cycles # noqa: E702, E241, E272
cycles += Emulator.run_to("sys_MultiplyBytes.tableEntry"); assert 29 == cycles # noqa: E702, E241, E272
cycles += Emulator.run_to("sys_MultiplyBytes.high-byte-action.store-inverted"); assert 35 == cycles # noqa: E702, E241, E272
cycles += Emulator.run_to("sys_MultiplyBytes.tableExit"); assert 40 == cycles # noqa: E702, E241, E272
cycles += Emulator.run_to("sys_MultiplyBytes#44"); assert 43 == cycles # noqa: E702, E241, E272
cycles += Emulator.run_to("sys_MultiplyBytes.tableEntry"); assert 51 == cycles # noqa: E702, E241, E272
cycles += Emulator.run_to("sys_MultiplyBytes.high-byte-action.restore-and-add"); assert 57 == cycles # noqa: E702, E241, E272
cycles += Emulator.run_to("sys_MultiplyBytes.tableExit"); assert 64 == cycles # noqa: E702, E241, E272
cycles += Emulator.run_to("sys_MultiplyBytes#68"); assert 67 == cycles # noqa: E702, E241, E272
cycles += Emulator.run_to("NEXTY"); assert 90 == cycles # noqa: E702, E241, E272
# fmt: on
def test_timing_neither_lt_128():
"""Follow the routine through, checking the timing comments
This follows the case where neither value is less than 128
"""
RAM[vars.sysArgs : vars.sysArgs + 2] = 172, 160
# fmt: off
cycles = 9 # On entry to SYS, 9 cycles have already elapsed
cycles += Emulator.run_to("sys_MultiplyBytes#68"); assert 67 == cycles # noqa: E702, E241, E272, E221
cycles += Emulator.run_to("sys_MultiplyBytes#92"); assert 91 == cycles # noqa: E702, E241, E272, E221
cycles += Emulator.run_to("sys_MultiplyBytes#114"); assert 113 == cycles # noqa: E702, E241, E272
cycles += Emulator.run_to("NEXTY"); assert 118 == cycles # noqa: E702, E241, E272
# fmt: on
def test_timing_one_lt_128():
"""Follow the routine through, checking the timing comments
This follows the case where one value is less than 128
"""
RAM[vars.sysArgs : vars.sysArgs + 2] = 3, 160
# fmt: off
cycles = 9 # On entry to SYS, 9 cycles have already elapsed
cycles += Emulator.run_to("sys_MultiplyBytes#68"); assert 67 == cycles # noqa: E702, E241, E272
cycles += Emulator.run_to("sys_MultiplyBytes.oneMsbSetCase"); assert 85 == cycles # noqa: E702, E241, E272
cycles += Emulator.run_to("sys_MultiplyBytes#92"); assert 91 == cycles # noqa: E702, E241, E272
# fmt: on
def _sign_extend(byte_):
if byte_ & 0x80:
return ~0xFF | byte_
return byte_
_bytes = st.integers(min_value=0, max_value=255)
@given(a=_bytes, b=_bytes)
def test_multiply_bytes(a, b):
setup_function()
RAM[vars.sysArgs : vars.sysArgs + 2] = a, b
cycles = 10 # Because Next is marked as zero
cycles += Emulator.run_to("NEXT")
assert cycles <= MAX_CYCLES
assert cycles == _sign_extend(Emulator.AC) * -2
assert a * b == Emulator.vAC