summaryrefslogtreecommitdiffstats
path: root/src/runtime/cgo/gcc_linux_ppc64x.S
diff options
context:
space:
mode:
Diffstat (limited to 'src/runtime/cgo/gcc_linux_ppc64x.S')
-rw-r--r--src/runtime/cgo/gcc_linux_ppc64x.S86
1 files changed, 86 insertions, 0 deletions
diff --git a/src/runtime/cgo/gcc_linux_ppc64x.S b/src/runtime/cgo/gcc_linux_ppc64x.S
new file mode 100644
index 0000000..745d232
--- /dev/null
+++ b/src/runtime/cgo/gcc_linux_ppc64x.S
@@ -0,0 +1,86 @@
+// 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 linux && (ppc64 || ppc64le)
+
+.file "gcc_linux_ppc64x.S"
+
+// Define a frame which has no argument space, but is compatible with
+// a call into a Go ABI. We allocate 32B to match FIXED_FRAME with
+// similar semantics, except we store the backchain pointer, not the
+// LR at offset 0. R2 is stored in the Go TOC save slot (offset 24).
+.set GPR_OFFSET, 32
+.set FPR_OFFSET, GPR_OFFSET + 18*8
+.set VR_OFFSET, FPR_OFFSET + 18*8
+.set FRAME_SIZE, VR_OFFSET + 12*16
+
+.macro FOR_EACH_GPR opcode r=14
+.ifge 31 - \r
+ \opcode \r, GPR_OFFSET + 8*(\r-14)(1)
+ FOR_EACH_GPR \opcode "(\r+1)"
+.endif
+.endm
+
+.macro FOR_EACH_FPR opcode fr=14
+.ifge 31 - \fr
+ \opcode \fr, FPR_OFFSET + 8*(\fr-14)(1)
+ FOR_EACH_FPR \opcode "(\fr+1)"
+.endif
+.endm
+
+.macro FOR_EACH_VR opcode vr=20
+.ifge 31 - \vr
+ li 0, VR_OFFSET + 16*(\vr-20)
+ \opcode \vr, 1, 0
+ FOR_EACH_VR \opcode "(\vr+1)"
+.endif
+.endm
+
+/*
+ * void crosscall_ppc64(void (*fn)(void), void *g)
+ *
+ * Calling into the gc tool chain, where all registers are caller save.
+ * Called from standard ppc64 C ABI, where r2, r14-r31, f14-f31 are
+ * callee-save, so they must be saved explicitly.
+ */
+.globl crosscall_ppc64
+crosscall_ppc64:
+ // Start with standard C stack frame layout and linkage
+ mflr %r0
+ std %r0, 16(%r1) // Save LR in caller's frame
+ mfcr %r0
+ std %r0, 8(%r1) // Save CR in caller's frame
+ stdu %r1, -FRAME_SIZE(%r1)
+ std %r2, 24(%r1)
+
+ FOR_EACH_GPR std
+ FOR_EACH_FPR stfd
+ FOR_EACH_VR stvx
+
+ // Set up Go ABI constant registers
+ li %r0, 0
+
+ // Restore g pointer (r30 in Go ABI, which may have been clobbered by C)
+ mr %r30, %r4
+
+ // Call fn
+ mr %r12, %r3
+ mtctr %r3
+ bctrl
+
+ FOR_EACH_GPR ld
+ FOR_EACH_FPR lfd
+ FOR_EACH_VR lvx
+
+ ld %r2, 24(%r1)
+ addi %r1, %r1, FRAME_SIZE
+ ld %r0, 16(%r1)
+ mtlr %r0
+ ld %r0, 8(%r1)
+ mtcr %r0
+ blr
+
+#ifdef __ELF__
+.section .note.GNU-stack,"",%progbits
+#endif