Skip to content

Implement fninit - #2778

Open
emkey1 wants to merge 1 commit into
ish-app:masterfrom
emkey1:implement_fninit
Open

Implement fninit#2778
emkey1 wants to merge 1 commit into
ish-app:masterfrom
emkey1:implement_fninit

Conversation

@emkey1

@emkey1 emkey1 commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

fninit (DB E3) is missing from the x87 decode table, so it raises SIGILL, while its immediate neighbour fnclex (DB E2) is there.

Reported in #2415, where it kills the Free Pascal compiler at startup: fpc emits fninit in its FPU setup, so nothing compiled with it runs.

What it does

Resets the control word to 0x037f and clears the status word. Clearing fsw also resets TOP, since TOP is a field of it, which is what empties the register stack; there is no tag word to write because none is modelled. The control word changing means the live rounding mode has to follow it, the same way fldcw does.

Verification

Same static i386 binary run on real Linux and on iSH, after dirtying the FPU with a non-default control word and a non-empty register stack:

before after / real Linux
fninit SIGILL runs
control word -- 0x037f
status word (incl. TOP) -- 0x0000
FPU usable afterwards -- yes

Reproduced on the Alpine 3.19.0 rootfs the App Store build downloads (ROOTFS_URL in app/iSH.xcconfig), against master 7864dd6.

Note that fpc is not packaged for x86 in 3.19, so this is the instruction on its own rather than that program; #2415 is the report, the table above is the check.

The test reads the status word with fnstsw ax rather than fnstsw m16, because the memory form is also unimplemented. That is a separate gap.

fninit (DB E3) is missing from the x87 decode table, so it raises SIGILL,
while its immediate neighbour fnclex (DB E2) is there. Reported in ish-app#2415,
where it kills the Free Pascal compiler at startup: fpc emits fninit in
its FPU setup, so nothing compiled with it runs.

It resets the control word to 0x037f and clears the status word. Clearing
fsw also resets TOP, since TOP is a field of it, which is what empties the
register stack; there is no tag word to write because none is modelled.
The control word changing means the live rounding mode has to follow it,
the same way fldcw does.

Verified against real Linux with the same static i386 binary, after
dirtying the FPU with a non-default control word and a non-empty stack:

                          before        after / real Linux
  fninit                  SIGILL        runs
  control word            --            0x037f
  status word (incl TOP)  --            0x0000
  FPU usable afterwards   --            yes

(The test reads the status word with fnstsw ax rather than fnstsw m16,
because the memory form is also unimplemented -- a separate gap.)
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