Skip to content

Spill floating-point status registers in stackman_switch. - #23

Open
kristjanvalur wants to merge 9 commits into
stackless-dev:masterfrom
kristjanvalur:fp-spill
Open

kristjanvalur wants to merge 9 commits into
stackless-dev:masterfrom
kristjanvalur:fp-spill

Conversation

@kristjanvalur

Copy link
Copy Markdown
Collaborator

Where a thread switch saves a floating-point control or status register, stackman_switch now saves the whole register and writes it back after the restore callback, before the epilogue pops the callee-saved registers. The caller-saved flag bits are included. stackman_call does not touch these registers.

  • armhf: FPSCR, in an 8-byte slot below the pointer passed to the callback.
  • aarch64 and darwin_arm64: FPCR and FPSR, in a 16-byte slot at that pointer. The x29 adjustment is taken from the lowered stack pointer.
  • win_arm64: FPSR next to the existing FPCR spill. The frame grows from 176 to 192 bytes. No SEH unwind codes were added.
  • riscv64: fcsr, in the existing 8-byte pad at the published stack pointer. The frame stays 208 bytes.

Softfp (-mfloat-abi=softfp) is not a supported platform. It still builds as arm32 and runs, and that assembly does not preserve FPSCR.

qemu-arm ran the armhf tests. qemu-aarch64 ran a two-stack switch of the Linux assembly. qemu-riscv64 ran the test suite, and a separate two-stack probe checked fcsr. The Darwin object assembled and was not executed. Windows ARM64 was not assembled here.

Linux saves and restores the whole FPSCR on a VFP context switch.
stackman_switch stores it in an 8-byte slot below the pointer passed
to the callback and writes it back after the restore callback, ahead
of the d8-d15 pop. The caller-saved flag bits travel with that copy.
stackman_call does not change FPSCR.
A thread switch saves both registers. Linux and macOS stackman_switch
store them in a 16-byte slot at the pointer passed to the callback and
write them back after the restore callback, before the epilogue pops
the callee-saved registers. Windows already stored FPCR and now stores
FPSR at [sp, #176]; the frame is 192 bytes. The caller-saved status
bits are included. stackman_call does not touch either register.

qemu-aarch64 ran a two-stack switch of the Linux assembly. The Darwin
object assembled and was not executed. Windows ARM64 was not assembled
here.
A softfp build does not define __ARM_PCS_VFP, so it selects arm32 and
runs. The soft-float assembly does not preserve FPSCR. Do not add that
spill to switch_arm_gcc.S: the file is softvfp, and vmrs fpscr is an
undefined instruction without VFP.
A thread switch saves the whole fcsr. stackman_switch stores it in the
existing 8-byte pad at the pointer passed to the callback and writes it
back after the restore callback, before the epilogue pops fs0-fs11.
The caller-saved exception flags are included. stackman_call does not
touch fcsr.

qemu-riscv64 ran a two-stack switch of this assembly.
The squash of the armhf port said FPSCR was still not spilled. This
branch stores the whole register, so those applied-fix sentences now
say so.
Later ports were being written into docs/abi-register-audit.md. That
file is restored to the audit as it was merged. Current ABI, switching,
and spill rules for each platform are in docs/platform-abi.md.
Later ports stay in docs/platform-abi.md.
The 16-byte spill lowered sp without telling the CFI, so callee-saved
slots were described 16 bytes low across both callbacks. The CFA is
sp+176 until the slot is popped. The macros sit outside the shared
asm block, so the Darwin assembly stays empty there.

The armhf note says the published pointer is the FPSCR slot. The
Windows ARM64 note puts FPSR at [sp, #176] and says the epilogue
reloads x18. The audit banner says the body is the PR 21 outcome
and is not the current tree.
test_09 sets FE_DOWNWARD, lets the callback switch to FE_TOWARDZERO, and
checks that the caller sees FE_DOWNWARD again on ABIs that spill the
floating-point control register. A second check saves a stack while
that mode is current, switches away with FE_UPWARD live, and checks
that the resumed copy still has FE_DOWNWARD. Soft-float arm32 does not
spill FPSCR, and the test expects the callback's mode to remain. The
test programs link libm for fesetround.
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.

1 participant