mirror of
https://github.com/tangerineturtle1/NX2navi.git
synced 2026-11-15 19:19:58 -04:00
kernel.c's preemption stub has two bodies since 00f06e66: kern_ap_stub_ymm saves YMM0-15 with vmovdqa and is chosen only when ap_init's cpu_keeps_ymm() finds AVX, OSXSAVE and XCR0 bits 1 and 2, and kern_ap_stub_xmm serves every other processor. tools/check_isa.py's DISPATCHED listed only sha256.c's blocks_ni, so it took the YMM body for an undispatched AVX function and stopped every tools/build_game.py --cpu v2 build. The entry names that check. Players' builds (make_game.py) run no such check and were not affected.
Reproduced before the change: kernel.c built with the ucrt64 clang at -march=x86-64-v2 failed tools/check_isa.py with "kern_ap_stub_ymm ...: vmovdqa x32, vzeroupper x1", and passes now. Checks that passed: the new tests/check_isa_test.py (kernel.c and sha256.c built with -march=x86-64-v2 and without -march pass; an AVX function not in DISPATCHED still fails; it fails before the change) and tools/check_content.py --staged.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
54 lines
2.2 KiB
Python
54 lines
2.2 KiB
Python
"""tools/check_isa.py on the runtime files that hold instructions above x86-64-v2 behind a runtime CPU check
|
|
(runtime/kernel.c kern_ap_stub_ymm, runtime/sha256.c blocks_ni): built as tools/build_game.py --cpu v2 builds the
|
|
runtime (-march=x86-64-v2) and as players' builds do (no -march), they pass, and a function with such an instruction
|
|
and no entry in DISPATCHED still fails. Needs the MSYS2 UCRT64 clang and an objdump (skipped without them); no game
|
|
files.
|
|
|
|
Run: python tests/check_isa_test.py
|
|
"""
|
|
import shutil
|
|
import subprocess
|
|
import sys
|
|
import tempfile
|
|
import unittest
|
|
from pathlib import Path
|
|
|
|
ROOT = Path(__file__).resolve().parent.parent
|
|
sys.path.insert(0, str(ROOT / 'tools'))
|
|
|
|
import check_isa # noqa: E402
|
|
|
|
UCRT = Path(r'C:\msys64\ucrt64\bin')
|
|
CC = next((str(c) for c in (UCRT / 'clang.exe', shutil.which('clang')) if c and Path(c).is_file()), None)
|
|
OBJDUMP = check_isa.find_objdump(str(UCRT / 'objdump.exe') if (UCRT / 'objdump.exe').is_file() else None)
|
|
FLAGS = ['-O2', '-g', '-fno-strict-aliasing', '-w'] # tools/build_game.py RT_FLAGS, without its warnings
|
|
|
|
|
|
@unittest.skipUnless(CC and OBJDUMP, 'needs clang and objdump')
|
|
class CheckIsaTest(unittest.TestCase):
|
|
def setUp(self):
|
|
td = tempfile.TemporaryDirectory()
|
|
self.addCleanup(td.cleanup)
|
|
self.tmp = Path(td.name)
|
|
|
|
def compile(self, src, march, name=None):
|
|
out = self.tmp / f'{name or Path(src).stem}{march or ""}.o'
|
|
subprocess.run([CC, *FLAGS, *([march] if march else []), '-I', str(ROOT / 'runtime'), '-c', str(src),
|
|
'-o', str(out)], check=True, capture_output=True, timeout=600)
|
|
return out
|
|
|
|
def test_the_dispatched_functions_pass(self):
|
|
for march in ('-march=x86-64-v2', None):
|
|
objs = [self.compile(ROOT / 'runtime' / f, march) for f in ('kernel.c', 'sha256.c')]
|
|
self.assertEqual(check_isa.scan(objs, OBJDUMP), {}, march)
|
|
|
|
def test_an_undispatched_avx_function_fails(self):
|
|
src = self.tmp / 'wide.c'
|
|
src.write_text('void wide(void) { __asm__ volatile("vzeroupper"); }\n', encoding='utf-8')
|
|
hits = check_isa.scan([self.compile(src, '-march=x86-64-v2')], OBJDUMP)
|
|
self.assertEqual([f for _, f in hits], ['wide'])
|
|
|
|
|
|
if __name__ == '__main__':
|
|
unittest.main(verbosity=2)
|