JIT broken on Power
JIT does not work on Power, as seen on NetBSD/powerpc (pull request #10) and AIX/power (pull request #17).
It looks like the JIT-generated code conflicts with gcc generated code w.r.t. usage of callee-saved registers. The first hurdle is that when xec()
calls comvec
, the latter clobbers %r31
. When comvec
returns, p->R = R;
assignment segfaults because the code in xec()
to compute &p->R
uses %r31
that has been clobbered.
I have fixed that with a wrapper that saves/restores all callee-saved registers around a call to comvec
. The next hurdle after that is that R.MP
seems to be clobbered when we return from the jitted code, so the next time MP
is used it crashes.
ATTN: @yk
Comments (7)
-
-
reporter So the second bug was that
macjit
is never set, soSETR0()
ends up doing nothing and when jitted code runs its%r0
is not zero. That was the source of garbage inf->mp
.After I've changed
SETR0
to always clear%r0
, jit works!The only other place where
macjit
is checked isICVTFW
. -
macjit is set (when needed) by the code section in the emu config
-
reporter Right, but it's set by MacOS configs that also set
dontcompile
, which forces JIT to be turned off. ... which makes me wonder if "mac" in "macjit" means "MacOS" and not "macros" (as inMacRET
and friends).I gather from the comment to
Rzero
that Plan9/Inferno keep%r0
as an always-zero register, kinda like sparc's%g0
but in ABI, not hardware. That makes sense. But what about its second use? What makesMacCVTFW
plan9-specific? -
reporter I have committed the fix to my pull request branch. It's saves/restores all callee-saved registers and CR indiscriminately. A dozen of instructions can be shaved off if only the registers that the compiler actually uses are preserved.
-
reporter Fixed in 09a88c5.
-
reporter - changed status to resolved
- Log in to comment
the quickest way seems to be to move mp to R5, avoiding R13, and save R14-R31 in preamble, restoring on each use of xpc to return to the C environment, which you might already be doing in your wrapper.. Nothing cares all that much which registers are used, except for R0, SP, SB, since the Plan 9 environment has most registers dead on entry to a called function. R4 can be used I think instead of R31 for Rlink. When the JIT calls out to surrounding C code, in punt, it saves and restores the few values it needs (partly because it might never return if there's an exception), so that part should be ok. It's really the path through comvec that matters, so your wrapper approach was about right.