mirror of https://github.com/golang/go.git
cmd/dist,cmd/go,runtime: add support for cgo on linux/riscv64
Fixes #36641 Change-Id: I51868d83ce341d78d33b221d184c5a5110c60d14 Reviewed-on: https://go-review.googlesource.com/c/go/+/263598 Trust: Joel Sing <joel@sing.id.au> Run-TryBot: Joel Sing <joel@sing.id.au> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Cherry Zhang <cherryyz@google.com>
This commit is contained in:
parent
974def803e
commit
393f2bb067
|
|
@ -0,0 +1,31 @@
|
|||
// Copyright 2020 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.
|
||||
|
||||
// +build riscv64
|
||||
// +build !gccgo
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
TEXT ·RewindAndSetgid(SB),NOSPLIT|NOFRAME,$0-0
|
||||
// Rewind stack pointer so anything that happens on the stack
|
||||
// will clobber the test pattern created by the caller
|
||||
ADD $(1024*8), X2
|
||||
|
||||
// Ask signaller to setgid
|
||||
MOV $1, X5
|
||||
FENCE
|
||||
MOVW X5, ·Baton(SB)
|
||||
FENCE
|
||||
|
||||
// Wait for setgid completion
|
||||
loop:
|
||||
FENCE
|
||||
MOVW ·Baton(SB), X5
|
||||
OR X6, X6, X6 // hint that we're in a spin loop
|
||||
BNE ZERO, X5, loop
|
||||
FENCE
|
||||
|
||||
// Restore stack
|
||||
ADD $(-1024*8), X2
|
||||
RET
|
||||
|
|
@ -1549,7 +1549,7 @@ var cgoEnabled = map[string]bool{
|
|||
"linux/mipsle": true,
|
||||
"linux/mips64": true,
|
||||
"linux/mips64le": true,
|
||||
"linux/riscv64": false, // Issue 36641
|
||||
"linux/riscv64": true,
|
||||
"linux/s390x": true,
|
||||
"linux/sparc64": true,
|
||||
"android/386": true,
|
||||
|
|
|
|||
|
|
@ -953,7 +953,7 @@ func (t *tester) internalLink() bool {
|
|||
// Internally linking cgo is incomplete on some architectures.
|
||||
// https://golang.org/issue/10373
|
||||
// https://golang.org/issue/14449
|
||||
if goarch == "mips64" || goarch == "mips64le" || goarch == "mips" || goarch == "mipsle" {
|
||||
if goarch == "mips64" || goarch == "mips64le" || goarch == "mips" || goarch == "mipsle" || goarch == "riscv64" {
|
||||
return false
|
||||
}
|
||||
if goos == "aix" {
|
||||
|
|
@ -1117,8 +1117,8 @@ func (t *tester) cgoTest(dt *distTest) error {
|
|||
"android-arm", "android-arm64",
|
||||
"dragonfly-amd64",
|
||||
"freebsd-386", "freebsd-amd64", "freebsd-arm",
|
||||
"linux-386", "linux-amd64", "linux-arm", "linux-ppc64le", "linux-s390x",
|
||||
"netbsd-386", "netbsd-amd64", "linux-arm64":
|
||||
"linux-386", "linux-amd64", "linux-arm", "linux-arm64", "linux-ppc64le", "linux-riscv64", "linux-s390x",
|
||||
"netbsd-386", "netbsd-amd64":
|
||||
|
||||
cmd := t.addCmd(dt, "misc/cgo/test", t.goTest())
|
||||
cmd.Env = append(os.Environ(), "GOFLAGS=-ldflags=-linkmode=external")
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
# Plugins are only supported on linux,cgo and darwin,cgo.
|
||||
# Plugins are only supported on linux,cgo (!riscv64) and darwin,cgo.
|
||||
[!linux] [!darwin] skip
|
||||
[linux] [riscv64] skip
|
||||
[!cgo] skip
|
||||
|
||||
go build -n testdep
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ func canInternalLink() bool {
|
|||
}
|
||||
case "linux":
|
||||
switch runtime.GOARCH {
|
||||
case "arm64", "mips64", "mips64le", "mips", "mipsle", "ppc64", "ppc64le":
|
||||
case "arm64", "mips64", "mips64le", "mips", "mipsle", "ppc64", "ppc64le", "riscv64":
|
||||
return false
|
||||
}
|
||||
case "openbsd":
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@
|
|||
// func rt0_go()
|
||||
TEXT runtime·rt0_go(SB),NOSPLIT,$0
|
||||
// X2 = stack; A0 = argc; A1 = argv
|
||||
|
||||
ADD $-24, X2
|
||||
MOV A0, 8(X2) // argc
|
||||
MOV A1, 16(X2) // argv
|
||||
|
|
@ -313,10 +312,62 @@ TEXT runtime·gosave(SB), NOSPLIT|NOFRAME, $0-8
|
|||
CALL runtime·badctxt(SB)
|
||||
RET
|
||||
|
||||
// Save state of caller into g->sched. Smashes X31.
|
||||
TEXT gosave<>(SB),NOSPLIT|NOFRAME,$0
|
||||
MOV X1, (g_sched+gobuf_pc)(g)
|
||||
MOV X2, (g_sched+gobuf_sp)(g)
|
||||
MOV ZERO, (g_sched+gobuf_lr)(g)
|
||||
MOV ZERO, (g_sched+gobuf_ret)(g)
|
||||
// Assert ctxt is zero. See func save.
|
||||
MOV (g_sched+gobuf_ctxt)(g), X31
|
||||
BEQ ZERO, X31, 2(PC)
|
||||
CALL runtime·badctxt(SB)
|
||||
RET
|
||||
|
||||
// func asmcgocall(fn, arg unsafe.Pointer) int32
|
||||
// Call fn(arg) on the scheduler stack,
|
||||
// aligned appropriately for the gcc ABI.
|
||||
// See cgocall.go for more details.
|
||||
TEXT ·asmcgocall(SB),NOSPLIT,$0-20
|
||||
// TODO(jsing): Add support for cgo - issue #36641.
|
||||
WORD $0 // crash
|
||||
MOV fn+0(FP), X5
|
||||
MOV arg+8(FP), X10
|
||||
|
||||
MOV X2, X8 // save original stack pointer
|
||||
MOV g, X9
|
||||
|
||||
// Figure out if we need to switch to m->g0 stack.
|
||||
// We get called to create new OS threads too, and those
|
||||
// come in on the m->g0 stack already.
|
||||
MOV g_m(g), X6
|
||||
MOV m_g0(X6), X7
|
||||
BEQ X7, g, g0
|
||||
|
||||
CALL gosave<>(SB)
|
||||
MOV X7, g
|
||||
CALL runtime·save_g(SB)
|
||||
MOV (g_sched+gobuf_sp)(g), X2
|
||||
|
||||
// Now on a scheduling stack (a pthread-created stack).
|
||||
g0:
|
||||
// Save room for two of our pointers.
|
||||
ADD $-16, X2
|
||||
MOV X9, 0(X2) // save old g on stack
|
||||
MOV (g_stack+stack_hi)(X9), X9
|
||||
SUB X8, X9, X8
|
||||
MOV X8, 8(X2) // save depth in old g stack (can't just save SP, as stack might be copied during a callback)
|
||||
|
||||
JALR RA, (X5)
|
||||
|
||||
// Restore g, stack pointer. X10 is return value.
|
||||
MOV 0(X2), g
|
||||
CALL runtime·save_g(SB)
|
||||
MOV (g_stack+stack_hi)(g), X5
|
||||
MOV 8(X2), X6
|
||||
SUB X6, X5, X6
|
||||
MOV X6, X2
|
||||
|
||||
MOVW X10, ret+16(FP)
|
||||
RET
|
||||
|
||||
// func asminit()
|
||||
TEXT runtime·asminit(SB),NOSPLIT|NOFRAME,$0-0
|
||||
|
|
@ -444,6 +495,21 @@ CALLFN(·call268435456, 268435456)
|
|||
CALLFN(·call536870912, 536870912)
|
||||
CALLFN(·call1073741824, 1073741824)
|
||||
|
||||
// Called from cgo wrappers, this function returns g->m->curg.stack.hi.
|
||||
// Must obey the gcc calling convention.
|
||||
TEXT _cgo_topofstack(SB),NOSPLIT,$8
|
||||
// g (X27) and REG_TMP (X31) might be clobbered by load_g.
|
||||
// X27 is callee-save in the gcc calling convention, so save it.
|
||||
MOV g, savedX27-8(SP)
|
||||
|
||||
CALL runtime·load_g(SB)
|
||||
MOV g_m(g), X5
|
||||
MOV m_curg(X5), X5
|
||||
MOV (g_stack+stack_hi)(X5), X10 // return value in X10
|
||||
|
||||
MOV savedX27-8(SP), g
|
||||
RET
|
||||
|
||||
// func goexit(neverCallThisFunction)
|
||||
// The top-most function running on a goroutine
|
||||
// returns to goexit+PCQuantum.
|
||||
|
|
@ -453,11 +519,111 @@ TEXT runtime·goexit(SB),NOSPLIT|NOFRAME|TOPFRAME,$0-0
|
|||
// traceback from goexit1 must hit code range of goexit
|
||||
MOV ZERO, ZERO // NOP
|
||||
|
||||
// cgocallback(fn, frame unsafe.Pointer, ctxt uintptr)
|
||||
// func cgocallback(fn, frame unsafe.Pointer, ctxt uintptr)
|
||||
// See cgocall.go for more details.
|
||||
TEXT ·cgocallback(SB),NOSPLIT,$0-24
|
||||
// TODO(jsing): Add support for cgo - issue #36641.
|
||||
WORD $0 // crash
|
||||
TEXT ·cgocallback(SB),NOSPLIT,$24-24
|
||||
NO_LOCAL_POINTERS
|
||||
|
||||
// Load m and g from thread-local storage.
|
||||
MOVBU runtime·iscgo(SB), X5
|
||||
BEQ ZERO, X5, nocgo
|
||||
CALL runtime·load_g(SB)
|
||||
nocgo:
|
||||
|
||||
// If g is nil, Go did not create the current thread.
|
||||
// Call needm to obtain one for temporary use.
|
||||
// In this case, we're running on the thread stack, so there's
|
||||
// lots of space, but the linker doesn't know. Hide the call from
|
||||
// the linker analysis by using an indirect call.
|
||||
BEQ ZERO, g, needm
|
||||
|
||||
MOV g_m(g), X5
|
||||
MOV X5, savedm-8(SP)
|
||||
JMP havem
|
||||
|
||||
needm:
|
||||
MOV g, savedm-8(SP) // g is zero, so is m.
|
||||
MOV $runtime·needm(SB), X6
|
||||
JALR RA, X6
|
||||
|
||||
// Set m->sched.sp = SP, so that if a panic happens
|
||||
// during the function we are about to execute, it will
|
||||
// have a valid SP to run on the g0 stack.
|
||||
// The next few lines (after the havem label)
|
||||
// will save this SP onto the stack and then write
|
||||
// the same SP back to m->sched.sp. That seems redundant,
|
||||
// but if an unrecovered panic happens, unwindm will
|
||||
// restore the g->sched.sp from the stack location
|
||||
// and then systemstack will try to use it. If we don't set it here,
|
||||
// that restored SP will be uninitialized (typically 0) and
|
||||
// will not be usable.
|
||||
MOV g_m(g), X5
|
||||
MOV m_g0(X5), X6
|
||||
MOV X2, (g_sched+gobuf_sp)(X6)
|
||||
|
||||
havem:
|
||||
// Now there's a valid m, and we're running on its m->g0.
|
||||
// Save current m->g0->sched.sp on stack and then set it to SP.
|
||||
// Save current sp in m->g0->sched.sp in preparation for
|
||||
// switch back to m->curg stack.
|
||||
// NOTE: unwindm knows that the saved g->sched.sp is at 8(X2) aka savedsp-24(SP).
|
||||
MOV m_g0(X5), X6
|
||||
MOV (g_sched+gobuf_sp)(X6), X7
|
||||
MOV X7, savedsp-24(SP) // must match frame size
|
||||
MOV X2, (g_sched+gobuf_sp)(X6)
|
||||
|
||||
// Switch to m->curg stack and call runtime.cgocallbackg.
|
||||
// Because we are taking over the execution of m->curg
|
||||
// but *not* resuming what had been running, we need to
|
||||
// save that information (m->curg->sched) so we can restore it.
|
||||
// We can restore m->curg->sched.sp easily, because calling
|
||||
// runtime.cgocallbackg leaves SP unchanged upon return.
|
||||
// To save m->curg->sched.pc, we push it onto the curg stack and
|
||||
// open a frame the same size as cgocallback's g0 frame.
|
||||
// Once we switch to the curg stack, the pushed PC will appear
|
||||
// to be the return PC of cgocallback, so that the traceback
|
||||
// will seamlessly trace back into the earlier calls.
|
||||
MOV m_curg(X5), g
|
||||
CALL runtime·save_g(SB)
|
||||
MOV (g_sched+gobuf_sp)(g), X6 // prepare stack as X6
|
||||
MOV (g_sched+gobuf_pc)(g), X7
|
||||
MOV X7, -(24+8)(X6) // "saved LR"; must match frame size
|
||||
// Gather our arguments into registers.
|
||||
MOV fn+0(FP), X7
|
||||
MOV frame+8(FP), X8
|
||||
MOV ctxt+16(FP), X9
|
||||
MOV $-(24+8)(X6), X2 // switch stack; must match frame size
|
||||
MOV X7, 8(X2)
|
||||
MOV X8, 16(X2)
|
||||
MOV X9, 24(X2)
|
||||
CALL runtime·cgocallbackg(SB)
|
||||
|
||||
// Restore g->sched (== m->curg->sched) from saved values.
|
||||
MOV 0(X2), X7
|
||||
MOV X7, (g_sched+gobuf_pc)(g)
|
||||
MOV $(24+8)(X2), X6 // must match frame size
|
||||
MOV X6, (g_sched+gobuf_sp)(g)
|
||||
|
||||
// Switch back to m->g0's stack and restore m->g0->sched.sp.
|
||||
// (Unlike m->curg, the g0 goroutine never uses sched.pc,
|
||||
// so we do not have to restore it.)
|
||||
MOV g_m(g), X5
|
||||
MOV m_g0(X5), g
|
||||
CALL runtime·save_g(SB)
|
||||
MOV (g_sched+gobuf_sp)(g), X2
|
||||
MOV savedsp-24(SP), X6 // must match frame size
|
||||
MOV X6, (g_sched+gobuf_sp)(g)
|
||||
|
||||
// If the m on entry was nil, we called needm above to borrow an m
|
||||
// for the duration of the call. Since the call is over, return it with dropm.
|
||||
MOV savedm-8(SP), X5
|
||||
BNE ZERO, X5, droppedm
|
||||
MOV $runtime·dropm(SB), X6
|
||||
JALR RA, X6
|
||||
droppedm:
|
||||
|
||||
// Done!
|
||||
RET
|
||||
|
||||
TEXT runtime·breakpoint(SB),NOSPLIT|NOFRAME,$0-0
|
||||
EBREAK
|
||||
|
|
|
|||
|
|
@ -0,0 +1,84 @@
|
|||
// Copyright 2020 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.
|
||||
|
||||
// +build riscv64
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
// 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.
|
||||
TEXT crosscall2(SB),NOSPLIT|NOFRAME,$0
|
||||
/*
|
||||
* Push arguments for fn (X10, X11, X13), along with all callee-save
|
||||
* registers. Note that at procedure entry the first argument is at
|
||||
* 8(X2).
|
||||
*/
|
||||
ADD $(-8*31), X2
|
||||
MOV X10, (8*1)(X2) // fn unsafe.Pointer
|
||||
MOV X11, (8*2)(X2) // a unsafe.Pointer
|
||||
MOV X13, (8*3)(X2) // ctxt uintptr
|
||||
MOV X8, (8*4)(X2)
|
||||
MOV X9, (8*5)(X2)
|
||||
MOV X18, (8*6)(X2)
|
||||
MOV X19, (8*7)(X2)
|
||||
MOV X20, (8*8)(X2)
|
||||
MOV X21, (8*9)(X2)
|
||||
MOV X22, (8*10)(X2)
|
||||
MOV X23, (8*11)(X2)
|
||||
MOV X24, (8*12)(X2)
|
||||
MOV X25, (8*13)(X2)
|
||||
MOV X26, (8*14)(X2)
|
||||
MOV g, (8*15)(X2)
|
||||
MOV X3, (8*16)(X2)
|
||||
MOV X4, (8*17)(X2)
|
||||
MOV X1, (8*18)(X2)
|
||||
MOVD F8, (8*19)(X2)
|
||||
MOVD F9, (8*20)(X2)
|
||||
MOVD F18, (8*21)(X2)
|
||||
MOVD F19, (8*22)(X2)
|
||||
MOVD F20, (8*23)(X2)
|
||||
MOVD F21, (8*24)(X2)
|
||||
MOVD F22, (8*25)(X2)
|
||||
MOVD F23, (8*26)(X2)
|
||||
MOVD F24, (8*27)(X2)
|
||||
MOVD F25, (8*28)(X2)
|
||||
MOVD F26, (8*29)(X2)
|
||||
MOVD F27, (8*30)(X2)
|
||||
|
||||
// Initialize Go ABI environment
|
||||
CALL runtime·load_g(SB)
|
||||
CALL runtime·cgocallback(SB)
|
||||
|
||||
MOV (8*4)(X2), X8
|
||||
MOV (8*5)(X2), X9
|
||||
MOV (8*6)(X2), X18
|
||||
MOV (8*7)(X2), X19
|
||||
MOV (8*8)(X2), X20
|
||||
MOV (8*9)(X2), X21
|
||||
MOV (8*10)(X2), X22
|
||||
MOV (8*11)(X2), X23
|
||||
MOV (8*12)(X2), X24
|
||||
MOV (8*13)(X2), X25
|
||||
MOV (8*14)(X2), X26
|
||||
MOV (8*15)(X2), g
|
||||
MOV (8*16)(X2), X3
|
||||
MOV (8*17)(X2), X4
|
||||
MOV (8*18)(X2), X1
|
||||
MOVD (8*19)(X2), F8
|
||||
MOVD (8*20)(X2), F9
|
||||
MOVD (8*21)(X2), F18
|
||||
MOVD (8*22)(X2), F19
|
||||
MOVD (8*23)(X2), F20
|
||||
MOVD (8*24)(X2), F21
|
||||
MOVD (8*25)(X2), F22
|
||||
MOVD (8*26)(X2), F23
|
||||
MOVD (8*27)(X2), F24
|
||||
MOVD (8*28)(X2), F25
|
||||
MOVD (8*29)(X2), F26
|
||||
MOVD (8*30)(X2), F27
|
||||
ADD $(8*31), X2
|
||||
|
||||
RET
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
// Copyright 2020 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.
|
||||
|
||||
#include <pthread.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include "libcgo.h"
|
||||
#include "libcgo_unix.h"
|
||||
|
||||
static void *threadentry(void*);
|
||||
|
||||
void (*x_cgo_inittls)(void **tlsg, void **tlsbase);
|
||||
static void (*setg_gcc)(void*);
|
||||
|
||||
void
|
||||
_cgo_sys_thread_start(ThreadStart *ts)
|
||||
{
|
||||
pthread_attr_t attr;
|
||||
sigset_t ign, oset;
|
||||
pthread_t p;
|
||||
size_t size;
|
||||
int err;
|
||||
|
||||
sigfillset(&ign);
|
||||
pthread_sigmask(SIG_SETMASK, &ign, &oset);
|
||||
|
||||
// Not sure why the memset is necessary here,
|
||||
// but without it, we get a bogus stack size
|
||||
// out of pthread_attr_getstacksize. C'est la Linux.
|
||||
memset(&attr, 0, sizeof attr);
|
||||
pthread_attr_init(&attr);
|
||||
size = 0;
|
||||
pthread_attr_getstacksize(&attr, &size);
|
||||
// Leave stacklo=0 and set stackhi=size; mstart will do the rest.
|
||||
ts->g->stackhi = size;
|
||||
err = _cgo_try_pthread_create(&p, &attr, threadentry, ts);
|
||||
|
||||
pthread_sigmask(SIG_SETMASK, &oset, nil);
|
||||
|
||||
if (err != 0) {
|
||||
fatalf("pthread_create failed: %s", strerror(err));
|
||||
}
|
||||
}
|
||||
|
||||
extern void crosscall1(void (*fn)(void), void (*setg_gcc)(void*), void *g);
|
||||
static void*
|
||||
threadentry(void *v)
|
||||
{
|
||||
ThreadStart ts;
|
||||
|
||||
ts = *(ThreadStart*)v;
|
||||
free(v);
|
||||
|
||||
crosscall1(ts.fn, setg_gcc, (void*)ts.g);
|
||||
return nil;
|
||||
}
|
||||
|
||||
void
|
||||
x_cgo_init(G *g, void (*setg)(void*), void **tlsg, void **tlsbase)
|
||||
{
|
||||
pthread_attr_t attr;
|
||||
size_t size;
|
||||
|
||||
setg_gcc = setg;
|
||||
pthread_attr_init(&attr);
|
||||
pthread_attr_getstacksize(&attr, &size);
|
||||
g->stacklo = (uintptr)&attr - size + 4096;
|
||||
pthread_attr_destroy(&attr);
|
||||
|
||||
if (x_cgo_inittls) {
|
||||
x_cgo_inittls(tlsg, tlsbase);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
// Copyright 2020 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.
|
||||
|
||||
/*
|
||||
* void crosscall1(void (*fn)(void), void (*setg_gcc)(void *g), void *g)
|
||||
*
|
||||
* Calling into the gc tool chain, where all registers are caller save.
|
||||
* Called from standard RISCV ELF psABI, where x8-x9, x18-x27, f8-f9 and
|
||||
* f18-f27 are callee-save, so they must be saved explicitly, along with
|
||||
* x1 (LR).
|
||||
*/
|
||||
.globl crosscall1
|
||||
crosscall1:
|
||||
sd x1, -200(sp)
|
||||
addi sp, sp, -200
|
||||
sd x8, 8(sp)
|
||||
sd x9, 16(sp)
|
||||
sd x18, 24(sp)
|
||||
sd x19, 32(sp)
|
||||
sd x20, 40(sp)
|
||||
sd x21, 48(sp)
|
||||
sd x22, 56(sp)
|
||||
sd x23, 64(sp)
|
||||
sd x24, 72(sp)
|
||||
sd x25, 80(sp)
|
||||
sd x26, 88(sp)
|
||||
sd x27, 96(sp)
|
||||
fsd f8, 104(sp)
|
||||
fsd f9, 112(sp)
|
||||
fsd f18, 120(sp)
|
||||
fsd f19, 128(sp)
|
||||
fsd f20, 136(sp)
|
||||
fsd f21, 144(sp)
|
||||
fsd f22, 152(sp)
|
||||
fsd f23, 160(sp)
|
||||
fsd f24, 168(sp)
|
||||
fsd f25, 176(sp)
|
||||
fsd f26, 184(sp)
|
||||
fsd f27, 192(sp)
|
||||
|
||||
// a0 = *fn, a1 = *setg_gcc, a2 = *g
|
||||
mv s1, a0
|
||||
mv s0, a1
|
||||
mv a0, a2
|
||||
jalr ra, s0 // call setg_gcc (clobbers x30 aka g)
|
||||
jalr ra, s1 // call fn
|
||||
|
||||
ld x1, 0(sp)
|
||||
ld x8, 8(sp)
|
||||
ld x9, 16(sp)
|
||||
ld x18, 24(sp)
|
||||
ld x19, 32(sp)
|
||||
ld x20, 40(sp)
|
||||
ld x21, 48(sp)
|
||||
ld x22, 56(sp)
|
||||
ld x23, 64(sp)
|
||||
ld x24, 72(sp)
|
||||
ld x25, 80(sp)
|
||||
ld x26, 88(sp)
|
||||
ld x27, 96(sp)
|
||||
fld f8, 104(sp)
|
||||
fld f9, 112(sp)
|
||||
fld f18, 120(sp)
|
||||
fld f19, 128(sp)
|
||||
fld f20, 136(sp)
|
||||
fld f21, 144(sp)
|
||||
fld f22, 152(sp)
|
||||
fld f23, 160(sp)
|
||||
fld f24, 168(sp)
|
||||
fld f25, 176(sp)
|
||||
fld f26, 184(sp)
|
||||
fld f27, 192(sp)
|
||||
addi sp, sp, 200
|
||||
|
||||
jr ra
|
||||
|
||||
#ifdef __ELF__
|
||||
.section .note.GNU-stack,"",%progbits
|
||||
#endif
|
||||
|
|
@ -309,7 +309,7 @@ func unwindm(restore *bool) {
|
|||
switch GOARCH {
|
||||
default:
|
||||
throw("unwindm not implemented")
|
||||
case "386", "amd64", "arm", "ppc64", "ppc64le", "mips64", "mips64le", "s390x", "mips", "mipsle":
|
||||
case "386", "amd64", "arm", "ppc64", "ppc64le", "mips64", "mips64le", "s390x", "mips", "mipsle", "riscv64":
|
||||
sched.sp = *(*uintptr)(unsafe.Pointer(sched.sp + sys.MinFrameSize))
|
||||
case "arm64":
|
||||
sched.sp = *(*uintptr)(unsafe.Pointer(sched.sp + 16))
|
||||
|
|
|
|||
|
|
@ -9,10 +9,22 @@
|
|||
|
||||
// If !iscgo, this is a no-op.
|
||||
//
|
||||
// NOTE: mcall() assumes this clobbers only R23 (REGTMP).
|
||||
// FIXME: cgo
|
||||
// NOTE: mcall() assumes this clobbers only X31 (REG_TMP).
|
||||
TEXT runtime·save_g(SB),NOSPLIT|NOFRAME,$0-0
|
||||
MOVB runtime·iscgo(SB), X31
|
||||
BEQ X0, X31, nocgo
|
||||
|
||||
MOV runtime·tls_g(SB), X31
|
||||
ADD X4, X31 // add offset to thread pointer (X4)
|
||||
MOV g, (X31)
|
||||
|
||||
nocgo:
|
||||
RET
|
||||
|
||||
TEXT runtime·load_g(SB),NOSPLIT|NOFRAME,$0-0
|
||||
MOV runtime·tls_g(SB), X31
|
||||
ADD X4, X31 // add offset to thread pointer (X4)
|
||||
MOV (X31), g
|
||||
RET
|
||||
|
||||
GLOBL runtime·tls_g(SB), TLSBSS, $8
|
||||
|
|
|
|||
Loading…
Reference in New Issue