Files

86 lines
2.8 KiB
Lua

-- probe_os.lua -- private probe for the COFF loader work.
--
-- Prints the OS-phase heap free list (global list only, as HEAP.md advises),
-- and tests whether the CPU registers can be written from a frame hook while
-- the machine is running (the debugger is attached with -debug -debugger none).
--
-- VT1200_SKIP_LEVEL1=1 <mame> vt1200 ... -autoboot_script dwt/loader/probe_os.lua
--
-- Env: PROBE_AT (frame to sample, default 2500), PROBE_END (exit frame, 2520)
local function hex(v, w) return string.format("%0" .. (w or 8) .. "X", v) end
local machine = manager.machine
local cpu = machine.devices[':maincpu']
local dbg = machine.debugger
local prog = cpu.spaces['program']
if not dbg then
print("PROBE: no debugger")
machine:exit()
return
end
local AT = tonumber(os.getenv("PROBE_AT") or "2500")
local ENDF = tonumber(os.getenv("PROBE_END") or "2520")
local frames = 0
local tested = false
local function u32(a)
local ok, v = pcall(function() return prog:read_u32(a) end)
if ok then return v end
return 0xdeadbeef
end
local function heap()
print(string.format("PROBE: free counter @1E8BA0 = %d bits (%d bytes)",
u32(0x1E8BA0), math.floor(u32(0x1E8BA0) / 8)))
local head = u32(0x1E8AC0)
print(string.format("PROBE: global free-list head @1E8AC0 = %s", hex(head)))
local b = head
for i = 0, 15 do
if b == 0 then break end
local size = u32(b)
local nextp = u32(b + 0x20)
print(string.format("PROBE: block[%d] hdr=%s size=%d bits (%d B) user=%s..%s next=%s",
i, hex(b), size, math.floor(size / 8), hex(b + 0x40),
hex(b + size), hex(nextp)))
if nextp == head then break end
b = nextp
end
end
emu.register_frame_done(function()
frames = frames + 1
if frames == AT then
print(string.format("PROBE: frame %d PC=%s SP=%s A8=%s A14=%s",
frames, hex(cpu.state['PC'].value), hex(cpu.state['SP'].value),
hex(cpu.state['A8'].value), hex(cpu.state['A14'].value)))
heap()
-- Scratch return stub test: write jruc self at 01880F00, return address
-- at 01880F10, then set SP/PC from the frame hook.
prog:write_u16(0x01880F00, 0xC0FF) -- jruc 01880F00 (short, -1 word)
prog:write_u32(0x01880F10, 0x01880F00)
prog:write_u32(0x01880F20, 0xDEADBEEF)
print(string.format("PROBE: spin word readback=%04X ret=%s",
prog:read_u16(0x01880F00), hex(prog:read_u32(0x01880F10))))
cpu.state['SP'].value = 0x01880F10
cpu.state['A8'].value = 0x01880E00
cpu.state['PC'].value = 0x01880F00
tested = true
end
if tested and frames == AT + 2 then
print(string.format("PROBE: after 2 frames PC=%s SP=%s A8=%s",
hex(cpu.state['PC'].value), hex(cpu.state['SP'].value),
hex(cpu.state['A8'].value)))
end
if frames >= ENDF then
print(string.format("PROBE: marker 01880F20=%s (should be DEADBEEF, untouched)",
hex(u32(0x01880F20))))
machine:exit()
end
end, "vt1200-loader-probe")
dbg.visible_cpu = cpu
dbg.execution_state = 'run'