Files
tms-c-compiler/scripts/m4/fnptr-check.lua
T
arti 7a89a1fe4c tests: M4 function-pointer/indirect-call gate
Add the fnptr C callback test (direct symbol, volatile local pointer and
global pointer), its GSPA entry and marker script, and scripts/tests/m4/
fnptr.sh.  The gate compiles at the default -O2 pipeline, requires all four
markers to be 42 in MAME, and checks the linked assembly: _apply calls through
an A register (CALL, never CALLA) after the argument push, while _fnptr_test
keeps the direct CALLA and materialises inc with MOVI.  It also pins the GSPA
0x0920 encoding and requires dis34 to decode the call as 'call aN'.
2026-11-12 06:40:12 +00:00

44 lines
1.3 KiB
Lua

-- fnptr-check.lua -- M4 function-pointer/indirect-call markers.
--
-- M4_LOADER_LUA path to vendor/vt1200/dwt/loader/loader.lua
-- LOADER_END loader inspection/exit frame
--
-- Markers (0x20 bits apart):
-- 018A8000 apply(inc, 41) == 42
-- 018A8020 apply(vf, 41) == 42 (volatile local function pointer)
-- 018A8040 apply(g_fn, 43) == 42 (global function pointer = dec)
-- 018A8060 fnptr_test() == 42 (return value, stored by the entry)
dofile(os.getenv("M4_LOADER_LUA"))
local ENDF = tonumber(os.getenv("LOADER_END") or "2700")
local frames = 0
local checked = false
emu.register_frame_done(function()
frames = frames + 1
if frames == ENDF - 1 and not checked then
checked = true
local prog = manager.machine.devices[':maincpu'].spaces['program']
local m = {}
for i = 0, 3 do
m[i] = prog:read_u32(0x018A8000 + i * 0x20)
end
print(string.format("M4: fnptr=%d fnptr_volatile=%d fnptr_global=%d fnptr_ret=%d",
m[0], m[1], m[2], m[3]))
local want = {42, 42, 42, 42}
local ok = true
for i = 0, 3 do
if m[i] ~= want[i + 1] then
ok = false
end
end
if ok then
print("M4 MAME: PASS")
else
print("M4 MAME: FAIL (want fnptr=42 fnptr_volatile=42 fnptr_global=42 fnptr_ret=42)")
end
end
end, "fnptr-check")