ebd5ead147 ("Implement os_context_float_register_addr for ppc64-linux") turned the DEFINE-ALIEN-ROUTINE for os_context_float_register_addr into an unconditional toplevel form in src/code/ppc-vm.lisp, which places the symbol in the pre-linked *LINKAGE-INFO* table. Only ppc-linux defined the C function at that point; acd0f7e95a later added it for FreeBSD. Every other ppc target consequently fails at startup with Missing required foreign symbol 'os_context_float_register_addr' Implement the accessor for Darwin. The FPRs are saved in the __fs member of the mcontext as an array of 32 doubles, which is exactly the representation CONTEXT-FLOAT-REGISTER already assumes, so the existing Linux code path applies unchanged. Also restrict the alien routine and both Lisp accessors to the operating systems that actually define the function, so that ppc-netbsd and ppc-openbsd – which are broken in the same way – fall back to the existing stubs rather than referring to a symbol their runtime does not provide. --- src/code/ppc-vm.lisp | 12 ++++++++---- src/runtime/ppc-darwin-os.c | 9 +++++++++ 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src/code/ppc-vm.lisp b/src/code/ppc-vm.lisp index 89986c7..2bdb443 100644 --- src/code/ppc-vm.lisp +++ src/code/ppc-vm.lisp @@ -21,13 +21,17 @@ (defun context-lr (context) (declare (type (alien (* os-context-t)) context)) (int-sap (deref (context-lr-addr context)))) +;;; Only some operating systems expose the FPRs in the signal context. +;;; Referring to the alien routine unconditionally would make the core +;;; fail to start ("Missing required foreign symbol") on the others. +#+(or linux darwin freebsd) (define-alien-routine ("os_context_float_register_addr" context-float-register-addr) (* unsigned) (context (* os-context-t)) (index int)) (defun context-float-register (context index format &optional integer) (declare (ignorable context index)) (aver (not integer)) - #+linux + #+(or linux darwin freebsd) (let ((sap (alien-sap (context-float-register-addr context index)))) (ecase format (single-float @@ -40,14 +44,14 @@ (complex-double-float (complex (sap-ref-double sap 0) (sap-ref-double sap 8))))) - #-linux + #-(or linux darwin freebsd) (progn (warn "stub CONTEXT-FLOAT-REGISTER") (coerce 0 format))) (defun %set-context-float-register (context index format value) (declare (type (alien (* os-context-t)) context)) - #+linux + #+(or linux darwin freebsd) (let ((sap (alien-sap (context-float-register-addr context index)))) (ecase format (single-float @@ -64,7 +68,7 @@ (declare (type (complex double-float) value)) (setf (sap-ref-double sap 0) (realpart value) (sap-ref-double sap 8) (imagpart value)))))) - #-linux + #-(or linux darwin freebsd) (error "%set-context-float-register not working yet? ~S" (list context index format value))) ;;; Given a signal context, return the floating point modes word in diff --git a/src/runtime/ppc-darwin-os.c b/src/runtime/ppc-darwin-os.c index 42c206f..66bc201 100644 --- src/runtime/ppc-darwin-os.c +++ src/runtime/ppc-darwin-os.c @@ -137,6 +137,15 @@ os_context_cr_addr(os_context_t *context) return (os_context_register_t *) &context->uc_mcontext->PPC_DARWIN_REGIFY(ss).PPC_DARWIN_REGIFY(cr); } +/* The FPRs are saved as doubles, which is also how the Lisp side + * (CONTEXT-FLOAT-REGISTER) reads them. */ +os_context_register_t * +os_context_float_register_addr(os_context_t *context, int offset) +{ + return (os_context_register_t *) + &context->uc_mcontext->PPC_DARWIN_REGIFY(fs).PPC_DARWIN_REGIFY(fpregs)[offset]; +} + void os_flush_icache(os_vm_address_t address, os_vm_size_t length) {