gameboy superoptimizer
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

47 lines
1.3 KiB

  1. from dataclasses import dataclass, field, replace
  2. from typing import List, Union
  3. from gbso.cpu.cpu import CPU
  4. from gbso.cpu.regs import R8
  5. from gbso.program.program import Program
  6. from gbso.cpu.state import CPUState
  7. # TODO: Support 16-bit memory/register outputs
  8. Output = Union[R8, int]
  9. @dataclass
  10. class TestCase:
  11. __test__ = False
  12. state: CPUState = field(default_factory=CPUState)
  13. # TODO: Allow p_cpu to be computed AOT
  14. # TODO: Add penalty for undefined behavior (uninitialized register/memory reads)
  15. def eq_on_testcase(
  16. p: Program, q: Program, case: TestCase, outputs: List[Output]
  17. ) -> int:
  18. p_cpu = p.execute(case.state.copy())
  19. q_cpu = q.execute(case.state.copy())
  20. return sum([eq_on_output(o, p_cpu, q_cpu) for o in outputs])
  21. def eq_on_output(o: Output, p_cpu: CPU, q_cpu: CPU) -> int:
  22. if type(o) == R8:
  23. delta = eq_8bit(p_cpu.state.reg8[o], q_cpu.state.reg8[o])
  24. elif type(o) == int:
  25. delta = eq_8bit(p_cpu.state.memory[o], q_cpu.state.memory[o])
  26. else:
  27. raise TypeError(f"unknown output type {type(o)}")
  28. return delta
  29. # Counts differing bits between two 8-bit values
  30. def eq_8bit(x: int, y: int) -> int:
  31. delta = 0
  32. for i in range(8):
  33. mask = 1 << i
  34. if x & mask != y & mask:
  35. delta += 1
  36. return delta