mirror of https://github.com/golang/go.git
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:
parent
1e51b1fac3
commit
5c51e9f45b
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue