Skip to content

exec.library: Supervisor enters its routine through a real exception frame - #199

Merged
sidick merged 1 commit into
sidick:mainfrom
codewiz:supervisor-frame
Oct 23, 2026
Merged

sidick merged 1 commit into
sidick:mainfrom
codewiz:supervisor-frame

Conversation

@codewiz

@codewiz codewiz commented Oct 23, 2026

Copy link
Copy Markdown
Contributor

Supervisor() pushed a 6-byte 68000 exception frame (SR, PC) whatever the emulated CPU. On a 68010 and later, RTE reads a format word after the PC (m68k-rs decode.rs, 0x4E73), so every Supervisor() routine crashed on --cpu 68020/68040; even moveq #42,d0 ; rte:

--cpu 68000: Supervisor -> 42
--cpu 68020: unexpected CPU stop at 0x2d300000: program counter ran off the end of guest memory

ixemul.library's longjmp() showed it, and two more gaps. It calls sigreturn(), a Supervisor() routine that sets USP, rewrites the frame's PC and SR to the setjmp() point, and RTEs there in user mode (library/trap.S _do_sigreturn). So the routine's RTE never came back to the continuation the trampoline queued, which then confused later calls (on --cpu 68000: "continuation stub trapped ... with no pending continuation"); and later Supervisor() calls came from user mode, where the frame belongs on the supervisor stack, not the caller's.

Supervisor() now enters its routine the way the CPU enters an exception: a new Cpu::push_exception_frame switches to supervisor mode and the supervisor stack (trace bits cleared) and pushes the frame the model's RTE pops (SR, PC, and on a 68010+ a format 0 vector word $20), returning straight to the caller in its own SR. No continuation is queued, so the routine may make library calls (#192 still holds) and may RTE anywhere. ContinuationStack::trampoline_rte had no other user and is removed. The new SP is published to the --sanitize shadow before the frame is written, as the per-instruction hook does for guest pushes.

With this, gcc's pr56982.c and 20210505-1.c (setjmp/longjmp) pass at every -O level linked against ixemul 47.3 and 80.1, with --sanitize, on --cpu 68000 and 68020; together with #197 and #198, gcc's C execute testsuite against ixemul fails only one test (an unrelated toolchain issue).

Test plan

🤖 Generated with Claude Code

…frame

The 6-byte 68000 frame broke every Supervisor routine on a 68010 or
later, whose RTE reads a format word; switch to the supervisor stack as
exception entry does, and return straight to the caller, so a routine
may RTE elsewhere (ixemul's longjmp).

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
@sidick
sidick merged commit 72a9132 into sidick:main Oct 23, 2026
9 checks passed
@codewiz
codewiz deleted the supervisor-frame branch October 23, 2026 15:14
@sidick sidick mentioned this pull request Oct 23, 2026
4 tasks done
sidick added a commit that referenced this pull request Oct 23, 2026
Fills in the 0.13 changelog: ixemul.library's full path-based file
I/O (GetDeviceProc's dvp_Port, the path packet actions, and Info())
from #197/#198, Supervisor()'s real exception frame unblocking nested
library calls from #199, the dl_TimeReq clock() fix from #194, the
remaining AllocDosObject types (DOS_STDPKT/DOS_CLI) from #187, and
#200's new_lock leak fix. Also documents these in
Supported-Libraries.md (expanded packet-action list, Supervisor's
RTE-anywhere support, dl_TimeReq).

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants