]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: add linux/mips64x cgo support
authorCherry Zhang <lunaria21@gmail.com>
Thu, 28 Apr 2016 02:18:24 +0000 (22:18 -0400)
committerMinux Ma <minux@golang.org>
Wed, 4 May 2016 16:41:10 +0000 (16:41 +0000)
Change-Id: Id40dd05b7b264f3b779fdf9ccc2421ba4bc70589
Reviewed-on: https://go-review.googlesource.com/19806
Reviewed-by: Minux Ma <minux@golang.org>
src/runtime/asm_mips64x.s
src/runtime/cgo_mips64x.go [new file with mode: 0644]
src/runtime/cgocall.go
src/runtime/sys_linux_mips64x.s
src/runtime/tls_mips64x.s

index 85b71d2d907c3027a9d90c5cffa52dfc7e01ec4e..7dd35aa0f595299419cc718094eb36c0150ded2f 100644 (file)
@@ -31,7 +31,15 @@ TEXT runtime·rt0_go(SB),NOSPLIT,$0
        MOVV    R1, (g_stack+stack_lo)(g)
        MOVV    R29, (g_stack+stack_hi)(g)
 
-       // no cgo yet
+       // if there is a _cgo_init, call it using the gcc ABI.
+       MOVV    _cgo_init(SB), R25
+       BEQ     R25, nocgo
+
+       MOVV    R0, R7  // arg 3: not used
+       MOVV    R0, R6  // arg 2: not used
+       MOVV    $setg_gcc<>(SB), R5     // arg 1: setg
+       MOVV    g, R4   // arg 0: G
+       JAL     (R25)
 
 nocgo:
        // update stackguard after _cgo_init
@@ -81,7 +89,7 @@ TEXT runtime·asminit(SB),NOSPLIT,$-8-0
        RET
 
 TEXT _cgo_reginit(SB),NOSPLIT,$-8-0
-       // crosscall_ppc64 and crosscall2 need to reginit, but can't
+       // crosscall1 needs to reginit, but can't
        // get at the 'runtime.reginit' symbol.
        JMP     runtime·reginit(SB)
 
@@ -453,26 +461,64 @@ TEXT gosave<>(SB),NOSPLIT,$-8
 // aligned appropriately for the gcc ABI.
 // See cgocall.go for more details.
 TEXT ·asmcgocall(SB),NOSPLIT,$0-20
-       UNDEF   // no cgo yet
+       MOVV    fn+0(FP), R25
+       MOVV    arg+8(FP), R4
+
+       MOVV    R29, R3 // save original stack pointer
+       MOVV    g, R2
+
+       // 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.
+       MOVV    g_m(g), R5
+       MOVV    m_g0(R5), R6
+       BEQ     R6, g, g0
+
+       JAL     gosave<>(SB)
+       MOVV    R6, g
+       JAL     runtime·save_g(SB)
+       MOVV    (g_sched+gobuf_sp)(g), R29
+
+       // Now on a scheduling stack (a pthread-created stack).
+g0:
+       // Save room for two of our pointers.
+       ADDV    $-16, R29
+       MOVV    R2, 0(R29)      // save old g on stack
+       MOVV    (g_stack+stack_hi)(R2), R2
+       SUBVU   R3, R2
+       MOVV    R2, 8(R29)      // save depth in old g stack (can't just save SP, as stack might be copied during a callback)
+       JAL     (R25)
+
+       // Restore g, stack pointer. R2 is return value.
+       MOVV    0(R29), g
+       JAL     runtime·save_g(SB)
+       MOVV    (g_stack+stack_hi)(g), R5
+       MOVV    8(R29), R6
+       SUBVU   R6, R5
+       MOVV    R5, R29
+
+       MOVW    R2, ret+16(FP)
        RET
 
-// cgocallback(void (*fn)(void*), void *frame, uintptr framesize)
+// cgocallback(void (*fn)(void*), void *frame, uintptr framesize, uintptr ctxt)
 // Turn the fn into a Go func (by taking its address) and call
 // cgocallback_gofunc.
-TEXT runtime·cgocallback(SB),NOSPLIT,$24-24
+TEXT runtime·cgocallback(SB),NOSPLIT,$32-32
        MOVV    $fn+0(FP), R1
        MOVV    R1, 8(R29)
        MOVV    frame+8(FP), R1
        MOVV    R1, 16(R29)
        MOVV    framesize+16(FP), R1
        MOVV    R1, 24(R29)
+       MOVV    ctxt+24(FP), R1
+       MOVV    R1, 32(R29)
        MOVV    $runtime·cgocallback_gofunc(SB), R1
        JAL     (R1)
        RET
 
-// cgocallback_gofunc(FuncVal*, void *frame, uintptr framesize)
+// cgocallback_gofunc(FuncVal*, void *frame, uintptr framesize, uintptr ctxt)
 // See cgocall.go for more details.
-TEXT ·cgocallback_gofunc(SB),NOSPLIT,$16-24
+TEXT ·cgocallback_gofunc(SB),NOSPLIT,$16-32
        NO_LOCAL_POINTERS
 
        // Load m and g from thread-local storage.
@@ -508,8 +554,8 @@ needm:
        // 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.
-       MOVV    g_m(g), R1
-       MOVV    m_g0(R1), R1
+       MOVV    g_m(g), R3
+       MOVV    m_g0(R3), R1
        MOVV    R29, (g_sched+gobuf_sp)(R1)
 
 havem:
@@ -537,18 +583,21 @@ havem:
        // so that the traceback will seamlessly trace back into
        // the earlier calls.
        //
-       // In the new goroutine, -16(SP) and -8(SP) are unused.
+       // In the new goroutine, -8(SP) is unused (where SP refers to
+       // m->curg's SP while we're setting it up, before we've adjusted it).
        MOVV    m_curg(R3), g
        JAL     runtime·save_g(SB)
        MOVV    (g_sched+gobuf_sp)(g), R2 // prepare stack as R2
-       MOVV    (g_sched+gobuf_pc)(g), R3
-       MOVV    R3, -24(R2)
+       MOVV    (g_sched+gobuf_pc)(g), R4
+       MOVV    R4, -24(R2)
+       MOVV    ctxt+24(FP), R1
+       MOVV    R1, -16(R2)
        MOVV    $-24(R2), R29
        JAL     runtime·cgocallbackg(SB)
 
        // Restore g->sched (== m->curg->sched) from saved values.
-       MOVV    0(R29), R3
-       MOVV    R3, (g_sched+gobuf_pc)(g)
+       MOVV    0(R29), R4
+       MOVV    R4, (g_sched+gobuf_pc)(g)
        MOVV    $24(R29), R2
        MOVV    R2, (g_sched+gobuf_sp)(g)
 
@@ -580,10 +629,10 @@ TEXT runtime·setg(SB), NOSPLIT, $0-8
        JAL     runtime·save_g(SB)
        RET
 
-// void setg_gcc(G*); set g in C TLS.
-// Must obey the gcc calling convention.
-TEXT setg_gcc<>(SB),NOSPLIT,$-8-0
-       UNDEF   // no cgo yet
+// void setg_gcc(G*); set g called from gcc with g in R1
+TEXT setg_gcc<>(SB),NOSPLIT,$0-0
+       MOVV    R1, g
+       JAL     runtime·save_g(SB)
        RET
 
 TEXT runtime·getcallerpc(SB),NOSPLIT,$8-16
@@ -805,8 +854,19 @@ TEXT runtime·return0(SB), NOSPLIT, $0
 
 // Called from cgo wrappers, this function returns g->m->curg.stack.hi.
 // Must obey the gcc calling convention.
-TEXT _cgo_topofstack(SB),NOSPLIT,$-8
-       UNDEF   // no cgo yet
+TEXT _cgo_topofstack(SB),NOSPLIT,$16
+       // g (R30) and REGTMP (R23)  might be clobbered by load_g. They
+       // are callee-save in the gcc calling convention, so save them.
+       MOVV    R23, savedR23-16(SP)
+       MOVV    g, savedG-8(SP)
+
+       JAL     runtime·load_g(SB)
+       MOVV    g_m(g), R1
+       MOVV    m_curg(R1), R1
+       MOVV    (g_stack+stack_hi)(R1), R2 // return value in R2
+
+       MOVV    savedG-8(SP), g
+       MOVV    savedR23-16(SP), R23
        RET
 
 // The top-most function running on a goroutine
diff --git a/src/runtime/cgo_mips64x.go b/src/runtime/cgo_mips64x.go
new file mode 100644 (file)
index 0000000..f718e92
--- /dev/null
@@ -0,0 +1,12 @@
+// Copyright 2016 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 mips64 mips64le
+
+package runtime
+
+// crosscall1 calls into the runtime to set up the registers the
+// Go runtime expects and so the symbol it calls needs to be exported
+// for external linking to work.
+//go:cgo_export_static _cgo_reginit
index 6dceff09efd1ebd02c14e9089b7a74deebbfae22..8457fb2de73c71a415f3a97d236c4f1f6debf26e 100644 (file)
@@ -286,6 +286,10 @@ func cgocallbackg1(ctxt uintptr) {
                // |                    | fixed frame area             |
                // +--------------------+------------------------------+ <- sp
                cb = (*args)(unsafe.Pointer(sp + 2*sys.MinFrameSize + 2*sys.PtrSize))
+       case "mips64", "mips64le":
+               // On mips64x, stack frame is two words and there's a saved LR between
+               // SP and the stack frame and between the stack frame and the arguments.
+               cb = (*args)(unsafe.Pointer(sp + 4*sys.PtrSize))
        }
 
        // Invoke callback.
@@ -323,7 +327,7 @@ func unwindm(restore *bool) {
        switch GOARCH {
        default:
                throw("unwindm not implemented")
-       case "386", "amd64", "arm", "ppc64", "ppc64le", "s390x":
+       case "386", "amd64", "arm", "ppc64", "ppc64le", "mips64", "mips64le", "s390x":
                sched.sp = *(*uintptr)(unsafe.Pointer(sched.sp + sys.MinFrameSize))
        case "arm64":
                sched.sp = *(*uintptr)(unsafe.Pointer(sched.sp + 16))
index e84b2c5bd5c3674670c89b2280a35ff912301e16..d4a81ca3647ff84e07dc7af0c8bff90453d4f848 100644 (file)
@@ -228,8 +228,8 @@ TEXT runtime·sigfwd(SB),NOSPLIT,$0-32
        MOVW    sig+8(FP), R4
        MOVV    info+16(FP), R5
        MOVV    ctx+24(FP), R6
-       MOVV    fn+0(FP), R1
-       JAL     (R1)
+       MOVV    fn+0(FP), R25
+       JAL     (R25)
        RET
 
 TEXT runtime·sigtramp(SB),NOSPLIT,$64
index 870eecb8dd6f92e44ee9f8c719d379cd8ca4dcc6..53bd6f2615ff81fd77157b9241e901964188a86a 100644 (file)
@@ -16,8 +16,15 @@ TEXT runtime·save_g(SB),NOSPLIT,$-8-0
        MOVB    runtime·iscgo(SB), R23
        BEQ     R23, nocgo
 
+       MOVV    R3, R23 // save R3
+       MOVV    g, runtime·tls_g(SB) // TLS relocation clobbers R3
+       MOVV    R23, R3 // restore R3
+
 nocgo:
        RET
 
 TEXT runtime·load_g(SB),NOSPLIT,$-8-0
+       MOVV    runtime·tls_g(SB), g // TLS relocation clobbers R3
        RET
+
+GLOBL runtime·tls_g(SB), TLSBSS, $8