// Copyright 2014 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. //go:build ppc64 || ppc64le #include "textflag.h" #include "asm_ppc64x.h" #include "abi_ppc64x.h" #ifdef GO_PPC64X_HAS_FUNCDESC // crosscall2 is marked with go:cgo_export_static. On AIX, this creates and exports // the symbol name and descriptor as the AIX linker expects, but does not work if // referenced from within Go. Create and use an aliased descriptor of crosscall2 // to workaround this. DEFINE_PPC64X_FUNCDESC(_crosscall2<>, crosscall2) #define CROSSCALL2_FPTR $_crosscall2<>(SB) #else // Use a local trampoline, to avoid taking the address of a dynamically exported // function. #define CROSSCALL2_FPTR $crosscall2_trampoline<>(SB) #endif // Set the x_crosscall2_ptr C function pointer variable point to crosscall2. // It's such a pointer chain: _crosscall2_ptr -> x_crosscall2_ptr -> crosscall2 TEXT ·set_crosscall2(SB),NOSPLIT,$0-0 MOVD _crosscall2_ptr(SB), R5 MOVD CROSSCALL2_FPTR, R6 MOVD R6, (R5) RET TEXT crosscall2_trampoline<>(SB),NOSPLIT,$0-0 JMP crosscall2(SB) // Called by C code generated by cmd/cgo. // func crosscall2(fn, a unsafe.Pointer, n int32, ctxt uintptr) // Saves C callee-saved registers and calls cgocallback with three arguments. // fn is the PC of a func(a unsafe.Pointer) function. // The value of R2 is saved on the new stack frame, and not // the caller's frame due to issue #43228. TEXT crosscall2(SB),NOSPLIT|NOFRAME,$0 // Start with standard C stack frame layout and linkage, allocate // 32 bytes of argument space, save callee-save regs, and set R0 to $0. STACK_AND_SAVE_HOST_TO_GO_ABI(32) // The above will not preserve R2 (TOC). Save it in case Go is // compiled without a TOC pointer (e.g -buildmode=default). MOVD R2, 24(R1) // Load the current g. BL runtime·load_g(SB) #ifdef GO_PPC64X_HAS_FUNCDESC // Load the real entry address from the first slot of the function descriptor. // The first argument fn might be null, that means dropm in pthread key destructor. CMP R3, $0 BEQ nil_fn MOVD 8(R3), R2 MOVD (R3), R3 nil_fn: #endif MOVD R3, FIXED_FRAME+0(R1) // fn unsafe.Pointer MOVD R4, FIXED_FRAME+8(R1) // a unsafe.Pointer // Skip R5 = n uint32 MOVD R6, FIXED_FRAME+16(R1) // ctxt uintptr BL runtime·cgocallback(SB) // Restore the old frame, and R2. MOVD 24(R1), R2 UNSTACK_AND_RESTORE_GO_TO_HOST_ABI(32) RET