112 lines
4.6 KiB
Python
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
|