runtime/cgo: preserve VRs across crosscall_ppc64 on linux

Rework this function to closely match the PPC64 crosscall2, but
written in gnu asm. Likewise, fix this to store TOC in the new
frame, not the caller's, as is required by the ELF ABIs.

Change-Id: I8902c74f2607e3436260882a7bea52e72a67b8f9
Reviewed-on: https://go-review.googlesource.com/c/go/+/486335
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Run-TryBot: Paul Murphy <murp@ibm.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Lynn Boger <laboger@linux.vnet.ibm.com>
Reviewed-by: Carlos Amedee <carlos@golang.org>
Auto-Submit: Carlos Amedee <carlos@golang.org>
This commit is contained in:
Paul E. Murphy 2023-03-31 13:33:25 -05:00 committed by Gopher Robot
parent 1e51b1fac3
commit 5c51e9f45b
1 changed files with 47 additions and 91 deletions

View File

@ -6,6 +6,37 @@
.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)
*
@ -18,13 +49,17 @@ crosscall_ppc64:
// Start with standard C stack frame layout and linkage
mflr %r0
std %r0, 16(%r1) // Save LR in caller's frame
std %r2, 24(%r1) // Save TOC in caller's frame
bl saveregs
stdu %r1, -296(%r1)
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
bl _cgo_reginit
nop
li %r0, 0
// Restore g pointer (r30 in Go ABI, which may have been clobbered by C)
mr %r30, %r4
@ -34,97 +69,18 @@ crosscall_ppc64:
mtctr %r3
bctrl
addi %r1, %r1, 296
bl restoreregs
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
saveregs:
// Save callee-save registers
// O=-288; for R in %r{14..31}; do echo "\tstd\t$R, $O(%r1)"; ((O+=8)); done; for F in f{14..31}; do echo "\tstfd\t$F, $O(%r1)"; ((O+=8)); done
std %r14, -288(%r1)
std %r15, -280(%r1)
std %r16, -272(%r1)
std %r17, -264(%r1)
std %r18, -256(%r1)
std %r19, -248(%r1)
std %r20, -240(%r1)
std %r21, -232(%r1)
std %r22, -224(%r1)
std %r23, -216(%r1)
std %r24, -208(%r1)
std %r25, -200(%r1)
std %r26, -192(%r1)
std %r27, -184(%r1)
std %r28, -176(%r1)
std %r29, -168(%r1)
std %r30, -160(%r1)
std %r31, -152(%r1)
stfd %f14, -144(%r1)
stfd %f15, -136(%r1)
stfd %f16, -128(%r1)
stfd %f17, -120(%r1)
stfd %f18, -112(%r1)
stfd %f19, -104(%r1)
stfd %f20, -96(%r1)
stfd %f21, -88(%r1)
stfd %f22, -80(%r1)
stfd %f23, -72(%r1)
stfd %f24, -64(%r1)
stfd %f25, -56(%r1)
stfd %f26, -48(%r1)
stfd %f27, -40(%r1)
stfd %f28, -32(%r1)
stfd %f29, -24(%r1)
stfd %f30, -16(%r1)
stfd %f31, -8(%r1)
blr
restoreregs:
// O=-288; for R in %r{14..31}; do echo "\tld\t$R, $O(%r1)"; ((O+=8)); done; for F in %f{14..31}; do echo "\tlfd\t$F, $O(%r1)"; ((O+=8)); done
ld %r14, -288(%r1)
ld %r15, -280(%r1)
ld %r16, -272(%r1)
ld %r17, -264(%r1)
ld %r18, -256(%r1)
ld %r19, -248(%r1)
ld %r20, -240(%r1)
ld %r21, -232(%r1)
ld %r22, -224(%r1)
ld %r23, -216(%r1)
ld %r24, -208(%r1)
ld %r25, -200(%r1)
ld %r26, -192(%r1)
ld %r27, -184(%r1)
ld %r28, -176(%r1)
ld %r29, -168(%r1)
ld %r30, -160(%r1)
ld %r31, -152(%r1)
lfd %f14, -144(%r1)
lfd %f15, -136(%r1)
lfd %f16, -128(%r1)
lfd %f17, -120(%r1)
lfd %f18, -112(%r1)
lfd %f19, -104(%r1)
lfd %f20, -96(%r1)
lfd %f21, -88(%r1)
lfd %f22, -80(%r1)
lfd %f23, -72(%r1)
lfd %f24, -64(%r1)
lfd %f25, -56(%r1)
lfd %f26, -48(%r1)
lfd %f27, -40(%r1)
lfd %f28, -32(%r1)
lfd %f29, -24(%r1)
lfd %f30, -16(%r1)
lfd %f31, -8(%r1)
blr
#ifdef __ELF__
.section .note.GNU-stack,"",%progbits
#endif