blob: b4fe4a88510fa4cba149b190adfc0aee0f8088ec [file]
// 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 crosscall1(void (*fn)(void), void (*setg_gcc)(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.
* ABI: r3=fn, r4=setg_gcc, r5=g on entry.
*/
.globl crosscall1
crosscall1:
// 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
// Save fn in r14 (callee-save) while we call setg_gcc
mr %r14, %r3
// Restore g pointer (r30 in Go ABI, which may have been clobbered by C)
mr %r30, %r5
// Call setg_gcc(g)
mr %r3, %r5 /* arg: g */
mr %r12, %r4 /* setg_gcc */
mtctr %r12
bctrl
// Call fn()
mr %r12, %r14
mtctr %r12
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