]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: added assembly part of linux/mips64{,le} support
authorYao Zhang <lunaria21@gmail.com>
Thu, 10 Sep 2015 15:25:58 +0000 (11:25 -0400)
committerMinux Ma <minux@golang.org>
Thu, 12 Nov 2015 04:46:17 +0000 (04:46 +0000)
Change-Id: I9e94027ef66c88007107de2b2b75c3d7cf1352af
Reviewed-on: https://go-review.googlesource.com/14467
Reviewed-by: Minux Ma <minux@golang.org>
src/runtime/asm_mips64x.s [new file with mode: 0644]
src/runtime/atomic_mips64x.s [new file with mode: 0644]
src/runtime/duff_mips64x.s [new file with mode: 0644]
src/runtime/memclr_mips64x.s [new file with mode: 0644]
src/runtime/memmove_mips64x.s [new file with mode: 0644]
src/runtime/mkduff.go
src/runtime/rt0_linux_mips64x.s [new file with mode: 0644]
src/runtime/sys_linux_mips64x.s [new file with mode: 0644]
src/runtime/tls_mips64x.s [new file with mode: 0644]

diff --git a/src/runtime/asm_mips64x.s b/src/runtime/asm_mips64x.s
new file mode 100644 (file)
index 0000000..8d0cf12
--- /dev/null
@@ -0,0 +1,820 @@
+// Copyright 2015 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
+
+#include "go_asm.h"
+#include "go_tls.h"
+#include "funcdata.h"
+#include "textflag.h"
+
+#define        REGCTXT R22
+
+TEXT runtime·rt0_go(SB),NOSPLIT,$0
+       // R29 = stack; R1 = argc; R2 = argv
+
+       // initialize essential registers
+       JAL     runtime·reginit(SB)
+
+       ADDV    $-24, R29
+       MOVW    R1, 8(R29) // argc
+       MOVV    R2, 16(R29) // argv
+
+       // create istack out of the given (operating system) stack.
+       // _cgo_init may update stackguard.
+       MOVV    $runtime·g0(SB), g
+       MOVV    $(-64*1024), R28
+       ADDV    R28, R29, R1
+       MOVV    R1, g_stackguard0(g)
+       MOVV    R1, g_stackguard1(g)
+       MOVV    R1, (g_stack+stack_lo)(g)
+       MOVV    R29, (g_stack+stack_hi)(g)
+
+       // no cgo yet
+
+nocgo:
+       // update stackguard after _cgo_init
+       MOVV    (g_stack+stack_lo)(g), R1
+       ADDV    $const__StackGuard, R1
+       MOVV    R1, g_stackguard0(g)
+       MOVV    R1, g_stackguard1(g)
+
+       // set the per-goroutine and per-mach "registers"
+       MOVV    $runtime·m0(SB), R1
+
+       // save m->g0 = g0
+       MOVV    g, m_g0(R1)
+       // save m0 to g0->m
+       MOVV    R1, g_m(g)
+
+       JAL     runtime·check(SB)
+
+       // args are already prepared
+       JAL     runtime·args(SB)
+       JAL     runtime·osinit(SB)
+       JAL     runtime·schedinit(SB)
+
+       // create a new goroutine to start program
+       MOVV    $runtime·mainPC(SB), R1                // entry
+       ADDV    $-24, R29
+       MOVV    R1, 16(R29)
+       MOVV    R0, 8(R29)
+       MOVV    R0, 0(R29)
+       JAL     runtime·newproc(SB)
+       ADDV    $24, R29
+
+       // start this M
+       JAL     runtime·mstart(SB)
+
+       MOVV    R0, 1(R0)
+       RET
+
+DATA   runtime·mainPC+0(SB)/8,$runtime·main(SB)
+GLOBL  runtime·mainPC(SB),RODATA,$8
+
+TEXT runtime·breakpoint(SB),NOSPLIT,$-8-0
+       MOVV    R0, 2(R0) // TODO: TD
+       RET
+
+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
+       // get at the 'runtime.reginit' symbol.
+       JMP     runtime·reginit(SB)
+
+TEXT runtime·reginit(SB),NOSPLIT,$-8-0
+       // initialize essential FP registers
+       MOVD    $0.5, F26
+       SUBD    F26, F26, F24
+       ADDD    F26, F26, F28
+       ADDD    F28, F28, F30
+       RET
+
+/*
+ *  go-routine
+ */
+
+// void gosave(Gobuf*)
+// save state in Gobuf; setjmp
+TEXT runtime·gosave(SB), NOSPLIT, $-8-8
+       MOVV    buf+0(FP), R1
+       MOVV    R29, gobuf_sp(R1)
+       MOVV    R31, gobuf_pc(R1)
+       MOVV    g, gobuf_g(R1)
+       MOVV    R0, gobuf_lr(R1)
+       MOVV    R0, gobuf_ret(R1)
+       MOVV    R0, gobuf_ctxt(R1)
+       RET
+
+// void gogo(Gobuf*)
+// restore state from Gobuf; longjmp
+TEXT runtime·gogo(SB), NOSPLIT, $-8-8
+       MOVV    buf+0(FP), R3
+       MOVV    gobuf_g(R3), g  // make sure g is not nil
+       JAL     runtime·save_g(SB)
+
+       MOVV    0(g), R2
+       MOVV    gobuf_sp(R3), R29
+       MOVV    gobuf_lr(R3), R31
+       MOVV    gobuf_ret(R3), R1
+       MOVV    gobuf_ctxt(R3), REGCTXT
+       MOVV    R0, gobuf_sp(R3)
+       MOVV    R0, gobuf_ret(R3)
+       MOVV    R0, gobuf_lr(R3)
+       MOVV    R0, gobuf_ctxt(R3)
+       MOVV    gobuf_pc(R3), R4
+       JMP     (R4)
+
+// void mcall(fn func(*g))
+// Switch to m->g0's stack, call fn(g).
+// Fn must never return.  It should gogo(&g->sched)
+// to keep running g.
+TEXT runtime·mcall(SB), NOSPLIT, $-8-8
+       // Save caller state in g->sched
+       MOVV    R29, (g_sched+gobuf_sp)(g)
+       MOVV    R31, (g_sched+gobuf_pc)(g)
+       MOVV    R0, (g_sched+gobuf_lr)(g)
+       MOVV    g, (g_sched+gobuf_g)(g)
+
+       // Switch to m->g0 & its stack, call fn.
+       MOVV    g, R1
+       MOVV    g_m(g), R3
+       MOVV    m_g0(R3), g
+       JAL     runtime·save_g(SB)
+       BNE     g, R1, 2(PC)
+       JMP     runtime·badmcall(SB)
+       MOVV    fn+0(FP), REGCTXT                       // context
+       MOVV    0(REGCTXT), R4                  // code pointer
+       MOVV    (g_sched+gobuf_sp)(g), R29      // sp = m->g0->sched.sp
+       ADDV    $-16, R29
+       MOVV    R1, 8(R29)
+       MOVV    R0, 0(R29)
+       JAL     (R4)
+       JMP     runtime·badmcall2(SB)
+
+// systemstack_switch is a dummy routine that systemstack leaves at the bottom
+// of the G stack.  We need to distinguish the routine that
+// lives at the bottom of the G stack from the one that lives
+// at the top of the system stack because the one at the top of
+// the system stack terminates the stack walk (see topofstack()).
+TEXT runtime·systemstack_switch(SB), NOSPLIT, $0-0
+       UNDEF
+       JAL     (R31)   // make sure this function is not leaf
+       RET
+
+// func systemstack(fn func())
+TEXT runtime·systemstack(SB), NOSPLIT, $0-8
+       MOVV    fn+0(FP), R1    // R1 = fn
+       MOVV    R1, REGCTXT             // context
+       MOVV    g_m(g), R2      // R2 = m
+
+       MOVV    m_gsignal(R2), R3       // R3 = gsignal
+       BEQ     g, R3, noswitch
+
+       MOVV    m_g0(R2), R3    // R3 = g0
+       BEQ     g, R3, noswitch
+
+       MOVV    m_curg(R2), R4
+       BEQ     g, R4, switch
+
+       // Bad: g is not gsignal, not g0, not curg. What is it?
+       // Hide call from linker nosplit analysis.
+       MOVV    $runtime·badsystemstack(SB), R4
+       JAL     (R4)
+
+switch:
+       // save our state in g->sched.  Pretend to
+       // be systemstack_switch if the G stack is scanned.
+       MOVV    $runtime·systemstack_switch(SB), R4
+       ADDV    $8, R4  // get past prologue
+       MOVV    R4, (g_sched+gobuf_pc)(g)
+       MOVV    R29, (g_sched+gobuf_sp)(g)
+       MOVV    R0, (g_sched+gobuf_lr)(g)
+       MOVV    g, (g_sched+gobuf_g)(g)
+
+       // switch to g0
+       MOVV    R3, g
+       JAL     runtime·save_g(SB)
+       MOVV    (g_sched+gobuf_sp)(g), R1
+       // make it look like mstart called systemstack on g0, to stop traceback
+       ADDV    $-8, R1
+       MOVV    $runtime·mstart(SB), R2
+       MOVV    R2, 0(R1)
+       MOVV    R1, R29
+
+       // call target function
+       MOVV    0(REGCTXT), R4  // code pointer
+       JAL     (R4)
+
+       // switch back to g
+       MOVV    g_m(g), R1
+       MOVV    m_curg(R1), g
+       JAL     runtime·save_g(SB)
+       MOVV    (g_sched+gobuf_sp)(g), R29
+       MOVV    R0, (g_sched+gobuf_sp)(g)
+       RET
+
+noswitch:
+       // already on m stack, just call directly
+       MOVV    0(REGCTXT), R4  // code pointer
+       JAL     (R4)
+       RET
+
+/*
+ * support for morestack
+ */
+
+// Called during function prolog when more stack is needed.
+// Caller has already loaded:
+// R1: framesize, R2: argsize, R3: LR
+//
+// The traceback routines see morestack on a g0 as being
+// the top of a stack (for example, morestack calling newstack
+// calling the scheduler calling newm calling gc), so we must
+// record an argument size. For that purpose, it has no arguments.
+TEXT runtime·morestack(SB),NOSPLIT,$-8-0
+       // Cannot grow scheduler stack (m->g0).
+       MOVV    g_m(g), R7
+       MOVV    m_g0(R7), R8
+       BNE     g, R8, 2(PC)
+       JAL     runtime·abort(SB)
+
+       // Cannot grow signal stack (m->gsignal).
+       MOVV    m_gsignal(R7), R8
+       BNE     g, R8, 2(PC)
+       JAL     runtime·abort(SB)
+
+       // Called from f.
+       // Set g->sched to context in f.
+       MOVV    REGCTXT, (g_sched+gobuf_ctxt)(g)
+       MOVV    R29, (g_sched+gobuf_sp)(g)
+       MOVV    R31, (g_sched+gobuf_pc)(g)
+       MOVV    R3, (g_sched+gobuf_lr)(g)
+
+       // Called from f.
+       // Set m->morebuf to f's caller.
+       MOVV    R3, (m_morebuf+gobuf_pc)(R7)    // f's caller's PC
+       MOVV    R29, (m_morebuf+gobuf_sp)(R7)   // f's caller's SP
+       MOVV    g, (m_morebuf+gobuf_g)(R7)
+
+       // Call newstack on m->g0's stack.
+       MOVV    m_g0(R7), g
+       JAL     runtime·save_g(SB)
+       MOVV    (g_sched+gobuf_sp)(g), R29
+       JAL     runtime·newstack(SB)
+
+       // Not reached, but make sure the return PC from the call to newstack
+       // is still in this function, and not the beginning of the next.
+       UNDEF
+
+TEXT runtime·morestack_noctxt(SB),NOSPLIT,$-8-0
+       MOVV    R0, REGCTXT
+       JMP     runtime·morestack(SB)
+
+TEXT runtime·stackBarrier(SB),NOSPLIT,$0
+       // We came here via a RET to an overwritten LR.
+       // R1 may be live. Other registers are available.
+
+       // Get the original return PC, g.stkbar[g.stkbarPos].savedLRVal.
+       MOVV    (g_stkbar+slice_array)(g), R2
+       MOVV    g_stkbarPos(g), R3
+       MOVV    $stkbar__size, R4
+       MULVU   R3, R4
+       MOVV    LO, R4
+       ADDV    R2, R4
+       MOVV    stkbar_savedLRVal(R4), R4
+       // Record that this stack barrier was hit.
+       ADDV    $1, R3
+       MOVV    R3, g_stkbarPos(g)
+       // Jump to the original return PC.
+       JMP     (R4)
+
+// reflectcall: call a function with the given argument list
+// func call(argtype *_type, f *FuncVal, arg *byte, argsize, retoffset uint32).
+// we don't have variable-sized frames, so we use a small number
+// of constant-sized-frame functions to encode a few bits of size in the pc.
+// Caution: ugly multiline assembly macros in your future!
+
+#define DISPATCH(NAME,MAXSIZE)         \
+       MOVV    $MAXSIZE, R28;          \
+       SGTU    R1, R28, R28;           \
+       BNE     R28, 3(PC);                     \
+       MOVV    $NAME(SB), R4;  \
+       JMP     (R4)
+// Note: can't just "BR NAME(SB)" - bad inlining results.
+
+TEXT reflect·call(SB), NOSPLIT, $0-0
+       JMP     ·reflectcall(SB)
+
+TEXT ·reflectcall(SB), NOSPLIT, $-8-32
+       MOVWU argsize+24(FP), R1
+       // NOTE(rsc): No call16, because CALLFN needs four words
+       // of argument space to invoke callwritebarrier.
+       DISPATCH(runtime·call32, 32)
+       DISPATCH(runtime·call64, 64)
+       DISPATCH(runtime·call128, 128)
+       DISPATCH(runtime·call256, 256)
+       DISPATCH(runtime·call512, 512)
+       DISPATCH(runtime·call1024, 1024)
+       DISPATCH(runtime·call2048, 2048)
+       DISPATCH(runtime·call4096, 4096)
+       DISPATCH(runtime·call8192, 8192)
+       DISPATCH(runtime·call16384, 16384)
+       DISPATCH(runtime·call32768, 32768)
+       DISPATCH(runtime·call65536, 65536)
+       DISPATCH(runtime·call131072, 131072)
+       DISPATCH(runtime·call262144, 262144)
+       DISPATCH(runtime·call524288, 524288)
+       DISPATCH(runtime·call1048576, 1048576)
+       DISPATCH(runtime·call2097152, 2097152)
+       DISPATCH(runtime·call4194304, 4194304)
+       DISPATCH(runtime·call8388608, 8388608)
+       DISPATCH(runtime·call16777216, 16777216)
+       DISPATCH(runtime·call33554432, 33554432)
+       DISPATCH(runtime·call67108864, 67108864)
+       DISPATCH(runtime·call134217728, 134217728)
+       DISPATCH(runtime·call268435456, 268435456)
+       DISPATCH(runtime·call536870912, 536870912)
+       DISPATCH(runtime·call1073741824, 1073741824)
+       MOVV    $runtime·badreflectcall(SB), R4
+       JMP     (R4)
+
+#define CALLFN(NAME,MAXSIZE)                   \
+TEXT NAME(SB), WRAPPER, $MAXSIZE-24;           \
+       NO_LOCAL_POINTERS;                      \
+       /* copy arguments to stack */           \
+       MOVV    arg+16(FP), R1;                 \
+       MOVWU   argsize+24(FP), R2;                     \
+       MOVV    R29, R3;                                \
+       ADDV    $8, R3;                 \
+       ADDV    R3, R2;                         \
+       BEQ     R3, R2, 6(PC);                          \
+       MOVBU   (R1), R4;                       \
+       ADDV    $1, R1;                 \
+       MOVBU   R4, (R3);                       \
+       ADDV    $1, R3;                 \
+       JMP     -5(PC);                         \
+       /* call function */                     \
+       MOVV    f+8(FP), REGCTXT;                       \
+       MOVV    (REGCTXT), R4;                  \
+       PCDATA  $PCDATA_StackMapIndex, $0;      \
+       JAL     (R4);                           \
+       /* copy return values back */           \
+       MOVV    arg+16(FP), R1;                 \
+       MOVWU   n+24(FP), R2;                   \
+       MOVWU   retoffset+28(FP), R4;           \
+       MOVV    R29, R3;                                \
+       ADDV    R4, R3;                         \
+       ADDV    R4, R1;                         \
+       SUBVU   R4, R2;                         \
+       ADDV    $8, R3;                 \
+       ADDV    R3, R2;                         \
+loop:                                          \
+       BEQ     R3, R2, end;                            \
+       MOVBU   (R3), R4;                       \
+       ADDV    $1, R3;                 \
+       MOVBU   R4, (R1);                       \
+       ADDV    $1, R1;                 \
+       JMP     loop;                           \
+end:                                           \
+       /* execute write barrier updates */     \
+       MOVV    argtype+0(FP), R5;              \
+       MOVV    arg+16(FP), R1;                 \
+       MOVWU   n+24(FP), R2;                   \
+       MOVWU   retoffset+28(FP), R4;           \
+       MOVV    R5, 8(R29);                     \
+       MOVV    R1, 16(R29);                    \
+       MOVV    R2, 24(R29);                    \
+       MOVV    R4, 32(R29);                    \
+       JAL     runtime·callwritebarrier(SB);  \
+       RET
+
+CALLFN(·call16, 16)
+CALLFN(·call32, 32)
+CALLFN(·call64, 64)
+CALLFN(·call128, 128)
+CALLFN(·call256, 256)
+CALLFN(·call512, 512)
+CALLFN(·call1024, 1024)
+CALLFN(·call2048, 2048)
+CALLFN(·call4096, 4096)
+CALLFN(·call8192, 8192)
+CALLFN(·call16384, 16384)
+CALLFN(·call32768, 32768)
+CALLFN(·call65536, 65536)
+CALLFN(·call131072, 131072)
+CALLFN(·call262144, 262144)
+CALLFN(·call524288, 524288)
+CALLFN(·call1048576, 1048576)
+CALLFN(·call2097152, 2097152)
+CALLFN(·call4194304, 4194304)
+CALLFN(·call8388608, 8388608)
+CALLFN(·call16777216, 16777216)
+CALLFN(·call33554432, 33554432)
+CALLFN(·call67108864, 67108864)
+CALLFN(·call134217728, 134217728)
+CALLFN(·call268435456, 268435456)
+CALLFN(·call536870912, 536870912)
+CALLFN(·call1073741824, 1073741824)
+
+TEXT runtime·procyield(SB),NOSPLIT,$0-0
+       RET
+
+// void jmpdefer(fv, sp);
+// called from deferreturn.
+// 1. grab stored LR for caller
+// 2. sub 8 bytes to get back to JAL deferreturn
+// 3. JMP to fn
+TEXT runtime·jmpdefer(SB), NOSPLIT, $-8-16
+       MOVV    0(R29), R31
+       ADDV    $-8, R31
+
+       MOVV    fv+0(FP), REGCTXT
+       MOVV    argp+8(FP), R29
+       ADDV    $-8, R29
+       NOR     R0, R0  // prevent scheduling
+       MOVV    0(REGCTXT), R4
+       JMP     (R4)
+
+// Save state of caller into g->sched. Smashes R31.
+TEXT gosave<>(SB),NOSPLIT,$-8
+       MOVV    R31, (g_sched+gobuf_pc)(g)
+       MOVV    R29, (g_sched+gobuf_sp)(g)
+       MOVV    R0, (g_sched+gobuf_lr)(g)
+       MOVV    R0, (g_sched+gobuf_ret)(g)
+       MOVV    R0, (g_sched+gobuf_ctxt)(g)
+       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
+       UNDEF   // no cgo yet
+       RET
+
+// cgocallback(void (*fn)(void*), void *frame, uintptr framesize)
+// Turn the fn into a Go func (by taking its address) and call
+// cgocallback_gofunc.
+TEXT runtime·cgocallback(SB),NOSPLIT,$24-24
+       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    $runtime·cgocallback_gofunc(SB), R1
+       JAL     (R1)
+       RET
+
+// cgocallback_gofunc(FuncVal*, void *frame, uintptr framesize)
+// See cgocall.go for more details.
+TEXT ·cgocallback_gofunc(SB),NOSPLIT,$16-24
+       NO_LOCAL_POINTERS
+
+       // Load m and g from thread-local storage.
+       MOVB    runtime·iscgo(SB), R1
+       BEQ     R1, nocgo
+       JAL     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.
+       BNE     g, havem
+       MOVV    g, savedm-8(SP) // g is zero, so is m.
+       MOVV    $runtime·needm(SB), R4
+       JAL     (R4)
+
+       // 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.
+       MOVV    g_m(g), R1
+       MOVV    m_g0(R1), R1
+       MOVV    R29, (g_sched+gobuf_sp)(R1)
+
+havem:
+       MOVV    g_m(g), R3
+       MOVV    R3, savedm-8(SP)
+       // 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(R29) aka savedsp-16(SP).
+       MOVV    m_g0(R3), R1
+       MOVV    (g_sched+gobuf_sp)(R1), R2
+       MOVV    R2, savedsp-16(SP)
+       MOVV    R29, (g_sched+gobuf_sp)(R1)
+
+       // 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 stack.
+       // This has the added benefit that it looks to the traceback
+       // routine like cgocallbackg is going to return to that
+       // PC (because the frame we allocate below has the same
+       // size as cgocallback_gofunc's frame declared above)
+       // so that the traceback will seamlessly trace back into
+       // the earlier calls.
+       //
+       // In the new goroutine, -16(SP) and -8(SP) are unused.
+       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    $-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    $24(R29), R2
+       MOVV    R2, (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.)
+       MOVV    g_m(g), R3
+       MOVV    m_g0(R3), g
+       JAL     runtime·save_g(SB)
+       MOVV    (g_sched+gobuf_sp)(g), R29
+       MOVV    savedsp-16(SP), R2
+       MOVV    R2, (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.
+       MOVV    savedm-8(SP), R3
+       BNE     R3, droppedm
+       MOVV    $runtime·dropm(SB), R4
+       JAL     (R4)
+droppedm:
+
+       // Done!
+       RET
+
+// void setg(G*); set g. for use by needm.
+TEXT runtime·setg(SB), NOSPLIT, $0-8
+       MOVV    gg+0(FP), g
+       // This only happens if iscgo, so jump straight to save_g
+       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
+       RET
+
+TEXT runtime·getcallerpc(SB),NOSPLIT,$8-16
+       MOVV    16(R29), R1             // LR saved by caller
+       MOVV    runtime·stackBarrierPC(SB), R2
+       BNE     R1, R2, nobar
+       // Get original return PC.
+       JAL     runtime·nextBarrierPC(SB)
+       MOVV    8(R29), R1
+nobar:
+       MOVV    R1, ret+8(FP)
+       RET
+
+TEXT runtime·setcallerpc(SB),NOSPLIT,$8-16
+       MOVV    pc+8(FP), R1
+       MOVV    16(R29), R2
+       MOVV    runtime·stackBarrierPC(SB), R3
+       BEQ     R2, R3, setbar
+       MOVV    R1, 16(R29)             // set LR in caller
+       RET
+setbar:
+       // Set the stack barrier return PC.
+       MOVV    R1, 8(R29)
+       JAL     runtime·setNextBarrierPC(SB)
+       RET
+
+TEXT runtime·getcallersp(SB),NOSPLIT,$0-16
+       MOVV    argp+0(FP), R1
+       ADDV    $-8, R1
+       MOVV    R1, ret+8(FP)
+       RET
+
+TEXT runtime·abort(SB),NOSPLIT,$-8-0
+       MOVW    (R0), R0
+       UNDEF
+
+// memhash_varlen(p unsafe.Pointer, h seed) uintptr
+// redirects to memhash(p, h, size) using the size
+// stored in the closure.
+TEXT runtime·memhash_varlen(SB),NOSPLIT,$40-24
+       GO_ARGS
+       NO_LOCAL_POINTERS
+       MOVV    p+0(FP), R1
+       MOVV    h+8(FP), R2
+       MOVV    8(REGCTXT), R3
+       MOVV    R1, 8(R29)
+       MOVV    R2, 16(R29)
+       MOVV    R3, 24(R29)
+       JAL     runtime·memhash(SB)
+       MOVV    32(R29), R1
+       MOVV    R1, ret+16(FP)
+       RET
+
+// AES hashing not implemented for mips64
+TEXT runtime·aeshash(SB),NOSPLIT,$-8-0
+       MOVW    (R0), R1
+TEXT runtime·aeshash32(SB),NOSPLIT,$-8-0
+       MOVW    (R0), R1
+TEXT runtime·aeshash64(SB),NOSPLIT,$-8-0
+       MOVW    (R0), R1
+TEXT runtime·aeshashstr(SB),NOSPLIT,$-8-0
+       MOVW    (R0), R1
+
+TEXT runtime·memeq(SB),NOSPLIT,$-8-25
+       MOVV    a+0(FP), R1
+       MOVV    b+8(FP), R2
+       MOVV    size+16(FP), R3
+       ADDV    R1, R3, R4
+loop:
+       BNE     R1, R4, test
+       MOVV    $1, R1
+       MOVB    R1, ret+24(FP)
+       RET
+test:
+       MOVBU   (R1), R6
+       ADDV    $1, R1
+       MOVBU   (R2), R7
+       ADDV    $1, R2
+       BEQ     R6, R7, loop
+
+       MOVB    R0, ret+24(FP)
+       RET
+
+// memequal_varlen(a, b unsafe.Pointer) bool
+TEXT runtime·memequal_varlen(SB),NOSPLIT,$40-17
+       MOVV    a+0(FP), R1
+       MOVV    b+8(FP), R2
+       BEQ     R1, R2, eq
+       MOVV    8(REGCTXT), R3    // compiler stores size at offset 8 in the closure
+       MOVV    R1, 8(R29)
+       MOVV    R2, 16(R29)
+       MOVV    R3, 24(R29)
+       JAL     runtime·memeq(SB)
+       MOVBU   32(R29), R1
+       MOVB    R1, ret+16(FP)
+       RET
+eq:
+       MOVV    $1, R1
+       MOVB    R1, ret+16(FP)
+       RET
+
+// eqstring tests whether two strings are equal.
+// The compiler guarantees that strings passed
+// to eqstring have equal length.
+// See runtime_test.go:eqstring_generic for
+// equivalent Go code.
+TEXT runtime·eqstring(SB),NOSPLIT,$0-33
+       MOVV    s1str+0(FP), R1
+       MOVV    s2str+16(FP), R2
+       MOVV    $1, R3
+       MOVB    R3, ret+32(FP)
+       BNE     R1, R2, 2(PC)
+       RET
+       MOVV    s1len+8(FP), R3
+       ADDV    R1, R3, R4
+loop:
+       BNE     R1, R4, 2(PC)
+       RET
+       MOVBU   (R1), R6
+       ADDV    $1, R1
+       MOVBU   (R2), R7
+       ADDV    $1, R2
+       BEQ     R6, R7, loop
+       MOVB    R0, ret+32(FP)
+       RET
+
+// TODO: share code with memeq?
+TEXT bytes·Equal(SB),NOSPLIT,$0-49
+       MOVV    a_len+8(FP), R3
+       MOVV    b_len+32(FP), R4
+       BNE     R3, R4, noteq           // unequal lengths are not equal
+
+       MOVV    a+0(FP), R1
+       MOVV    b+24(FP), R2
+       ADDV    R1, R3          // end
+
+loop:
+       BEQ     R1, R3, equal           // reached the end
+       MOVBU   (R1), R6
+       ADDV    $1, R1
+       MOVBU   (R2), R7
+       ADDV    $1, R2
+       BEQ     R6, R7, loop
+
+noteq:
+       MOVB    R0, ret+48(FP)
+       RET
+
+equal:
+       MOVV    $1, R1
+       MOVB    R1, ret+48(FP)
+       RET
+
+TEXT bytes·IndexByte(SB),NOSPLIT,$0-40
+       MOVV    s+0(FP), R1
+       MOVV    s_len+8(FP), R2
+       MOVBU   c+24(FP), R3    // byte to find
+       MOVV    R1, R4          // store base for later
+       ADDV    R1, R2          // end
+       ADDV    $-1, R1
+
+loop:
+       ADDV    $1, R1
+       BEQ     R1, R2, notfound
+       MOVBU   (R1), R5
+       BNE     R3, R5, loop
+
+       SUBV    R4, R1          // remove base
+       MOVV    R1, ret+32(FP)
+       RET
+
+notfound:
+       MOVV    $-1, R1
+       MOVV    R1, ret+32(FP)
+       RET
+
+TEXT strings·IndexByte(SB),NOSPLIT,$0-32
+       MOVV    p+0(FP), R1
+       MOVV    b_len+8(FP), R2
+       MOVBU   c+16(FP), R3    // byte to find
+       MOVV    R1, R4          // store base for later
+       ADDV    R1, R2          // end
+       ADDV    $-1, R1
+
+loop:
+       ADDV    $1, R1
+       BEQ     R1, R2, notfound
+       MOVBU   (R1), R5
+       BNE     R3, R5, loop
+
+       SUBV    R4, R1          // remove base
+       MOVV    R1, ret+24(FP)
+       RET
+
+notfound:
+       MOVV    $-1, R1
+       MOVV    R1, ret+24(FP)
+       RET
+
+TEXT runtime·fastrand1(SB), NOSPLIT, $0-4
+       MOVV    g_m(g), R2
+       MOVWU   m_fastrand(R2), R1
+       ADDU    R1, R1
+       BGEZ    R1, 2(PC)
+       XOR     $0x88888eef, R1
+       MOVW    R1, m_fastrand(R2)
+       MOVW    R1, ret+0(FP)
+       RET
+
+TEXT runtime·return0(SB), NOSPLIT, $0
+       MOVW    $0, R1
+       RET
+
+// 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
+       RET
+
+// The top-most function running on a goroutine
+// returns to goexit+PCQuantum.
+TEXT runtime·goexit(SB),NOSPLIT,$-8-0
+       NOR     R0, R0  // NOP
+       JAL     runtime·goexit1(SB)    // does not return
+       // traceback from goexit1 must hit code range of goexit
+       NOR     R0, R0  // NOP
+
+TEXT runtime·prefetcht0(SB),NOSPLIT,$0-8
+       RET
+
+TEXT runtime·prefetcht1(SB),NOSPLIT,$0-8
+       RET
+
+TEXT runtime·prefetcht2(SB),NOSPLIT,$0-8
+       RET
+
+TEXT runtime·prefetchnta(SB),NOSPLIT,$0-8
+       RET
diff --git a/src/runtime/atomic_mips64x.s b/src/runtime/atomic_mips64x.s
new file mode 100644 (file)
index 0000000..0f849ca
--- /dev/null
@@ -0,0 +1,13 @@
+// Copyright 2015 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
+
+#include "textflag.h"
+
+#define SYNC   WORD $0xf
+
+TEXT ·publicationBarrier(SB),NOSPLIT,$-8-0
+       SYNC
+       RET
diff --git a/src/runtime/duff_mips64x.s b/src/runtime/duff_mips64x.s
new file mode 100644 (file)
index 0000000..062e04a
--- /dev/null
@@ -0,0 +1,268 @@
+// AUTO-GENERATED by mkduff.go
+// Run go generate from src/runtime to update.
+// See mkduff.go for comments.
+
+// +build mips64 mips64le
+
+#include "textflag.h"
+
+TEXT runtime·duffzero(SB), NOSPLIT, $-8-0
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       MOVV    R0, 8(R1)
+       ADDV    $8, R1
+       RET
+
+// TODO: Implement runtime·duffcopy.
diff --git a/src/runtime/memclr_mips64x.s b/src/runtime/memclr_mips64x.s
new file mode 100644 (file)
index 0000000..30a4af3
--- /dev/null
@@ -0,0 +1,42 @@
+// Copyright 2015 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
+
+#include "textflag.h"
+
+// void runtime·memclr(void*, uintptr)
+TEXT runtime·memclr(SB),NOSPLIT,$0-16
+       MOVV    ptr+0(FP), R1
+       MOVV    n+8(FP), R2
+       ADDV    R1, R2, R4
+
+       // if less than 8 bytes, do one byte at a time
+       SGTU    $8, R2, R3
+       BNE     R3, out
+
+       // do one byte at a time until 8-aligned
+       AND     $7, R1, R3
+       BEQ     R3, words
+       MOVB    R0, (R1)
+       ADDV    $1, R1
+       JMP     -4(PC)
+
+words:
+       // do 8 bytes at a time if there is room
+       ADDV    $-7, R4, R2
+
+       SGTU    R2, R1, R3
+       BEQ     R3, out
+       MOVV    R0, (R1)
+       ADDV    $8, R1
+       JMP     -4(PC)
+
+out:
+       BEQ     R1, R4, done
+       MOVB    R0, (R1)
+       ADDV    $1, R1
+       JMP     -3(PC)
+done:
+       RET
diff --git a/src/runtime/memmove_mips64x.s b/src/runtime/memmove_mips64x.s
new file mode 100644 (file)
index 0000000..f0f6852
--- /dev/null
@@ -0,0 +1,105 @@
+// Copyright 2015 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
+
+#include "textflag.h"
+
+// void runtime·memmove(void*, void*, uintptr)
+TEXT runtime·memmove(SB), NOSPLIT, $-8-24
+       MOVV    to+0(FP), R1
+       MOVV    from+8(FP), R2
+       MOVV    n+16(FP), R3
+       BNE     R3, check
+       RET
+
+check:
+       SGTU    R1, R2, R4
+       BNE     R4, backward
+
+       ADDV    R1, R3, R6 // end pointer
+
+       // if the two pointers are not of same alignments, do byte copying
+       SUBVU   R2, R1, R4
+       AND     $7, R4
+       BNE     R4, out
+
+       // if less than 8 bytes, do byte copying
+       SGTU    $8, R3, R4
+       BNE     R4, out
+
+       // do one byte at a time until 8-aligned
+       AND     $7, R1, R5
+       BEQ     R5, words
+       MOVB    (R2), R4
+       ADDV    $1, R2
+       MOVB    R4, (R1)
+       ADDV    $1, R1
+       JMP     -6(PC)
+
+words:
+       // do 8 bytes at a time if there is room
+       ADDV    $-7, R6, R3 // R3 is end pointer-7
+
+       SGTU    R3, R1, R5
+       BEQ     R5, out
+       MOVV    (R2), R4
+       ADDV    $8, R2
+       MOVV    R4, (R1)
+       ADDV    $8, R1
+       JMP     -6(PC)
+
+out:
+       BEQ     R1, R6, done
+       MOVB    (R2), R4
+       ADDV    $1, R2
+       MOVB    R4, (R1)
+       ADDV    $1, R1
+       JMP     -5(PC)
+done:
+       RET
+
+backward:
+       ADDV    R3, R2 // from-end pointer
+       ADDV    R1, R3, R6 // to-end pointer
+
+       // if the two pointers are not of same alignments, do byte copying
+       SUBVU   R6, R2, R4
+       AND     $7, R4
+       BNE     R4, out1
+
+       // if less than 8 bytes, do byte copying
+       SGTU    $8, R3, R4
+       BNE     R4, out1
+
+       // do one byte at a time until 8-aligned
+       AND     $7, R6, R5
+       BEQ     R5, words1
+       ADDV    $-1, R2
+       MOVB    (R2), R4
+       ADDV    $-1, R6
+       MOVB    R4, (R6)
+       JMP     -6(PC)
+
+words1:
+       // do 8 bytes at a time if there is room
+       ADDV    $7, R1, R3 // R3 is start pointer+7
+
+       SGTU    R6, R3, R5
+       BEQ     R5, out1
+       ADDV    $-8, R2
+       MOVV    (R2), R4
+       ADDV    $-8, R6
+       MOVV    R4, (R6)
+       JMP     -6(PC)
+
+out1:
+       BEQ     R1, R6, done1
+       ADDV    $-1, R2
+       MOVB    (R2), R4
+       ADDV    $-1, R6
+       MOVB    R4, (R6)
+       JMP     -5(PC)
+done1:
+       RET
index 821906cc2b01fdd18c3c324932ac14ccb55946dd..0e7cc6680641bdc5f2c6b85bf10c23688671141c 100644 (file)
@@ -37,6 +37,7 @@ func main() {
        gen("arm", notags, zeroARM, copyARM)
        gen("arm64", notags, zeroARM64, copyARM64)
        gen("ppc64x", tagsPPC64x, zeroPPC64x, copyPPC64x)
+       gen("mips64x", tagsMIPS64x, zeroMIPS64x, copyMIPS64x)
 }
 
 func gen(arch string, tags, zero, copy func(io.Writer)) {
@@ -183,3 +184,25 @@ func zeroPPC64x(w io.Writer) {
 func copyPPC64x(w io.Writer) {
        fmt.Fprintln(w, "// TODO: Implement runtime·duffcopy.")
 }
+
+func tagsMIPS64x(w io.Writer) {
+       fmt.Fprintln(w)
+       fmt.Fprintln(w, "// +build mips64 mips64le")
+       fmt.Fprintln(w)
+}
+
+func zeroMIPS64x(w io.Writer) {
+       // R0: always zero
+       // R1 (aka REGRT1): ptr to memory to be zeroed - 8
+       // On return, R1 points to the last zeroed dword.
+       fmt.Fprintln(w, "TEXT runtime·duffzero(SB), NOSPLIT, $-8-0")
+       for i := 0; i < 128; i++ {
+               fmt.Fprintln(w, "\tMOVV\tR0, 8(R1)")
+               fmt.Fprintln(w, "\tADDV\t$8, R1")
+       }
+       fmt.Fprintln(w, "\tRET")
+}
+
+func copyMIPS64x(w io.Writer) {
+       fmt.Fprintln(w, "// TODO: Implement runtime·duffcopy.")
+}
diff --git a/src/runtime/rt0_linux_mips64x.s b/src/runtime/rt0_linux_mips64x.s
new file mode 100644 (file)
index 0000000..c7e35f5
--- /dev/null
@@ -0,0 +1,31 @@
+// Copyright 2015 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 linux
+// +build mips64 mips64le
+
+#include "textflag.h"
+
+TEXT _rt0_mips64_linux(SB),NOSPLIT,$0
+       JMP     _main<>(SB)
+
+TEXT _rt0_mips64le_linux(SB),NOSPLIT,$0
+       JMP     _main<>(SB)
+
+TEXT _main<>(SB),NOSPLIT,$-8
+       // In a statically linked binary, the stack contains argc,
+       // argv as argc string pointers followed by a NULL, envv as a
+       // sequence of string pointers followed by a NULL, and auxv.
+       // There is no TLS base pointer.
+#ifdef GOARCH_mips64
+       MOVW 4(R29), R1 // argc, big-endian ABI places int32 at offset 4
+#else
+       MOVW 0(R29), R1 // argc
+#endif
+       ADDV $8, R29, R2 // argv
+       JMP main(SB)
+
+TEXT main(SB),NOSPLIT,$-8
+       MOVV    $runtime·rt0_go(SB), R4
+       JMP     (R4)
diff --git a/src/runtime/sys_linux_mips64x.s b/src/runtime/sys_linux_mips64x.s
new file mode 100644 (file)
index 0000000..6ccb38f
--- /dev/null
@@ -0,0 +1,427 @@
+// Copyright 2015 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 linux
+// +build mips64 mips64le
+
+//
+// System calls and other sys.stuff for mips64, Linux
+//
+
+#include "go_asm.h"
+#include "go_tls.h"
+#include "textflag.h"
+
+#define SYS_exit               5058
+#define SYS_read               5000
+#define SYS_write              5001
+#define SYS_open               5002
+#define SYS_close              5003
+#define SYS_getpid             5038
+#define SYS_kill               5060
+#define SYS_fcntl              5080
+#define SYS_gettimeofday       5094
+#define SYS_mmap               5009
+#define SYS_munmap             5011
+#define SYS_setitimer          5036
+#define SYS_clone              5055
+#define SYS_newselect          5022
+#define SYS_sched_yield                5023
+#define SYS_rt_sigreturn       5211
+#define SYS_rt_sigaction       5013
+#define SYS_rt_sigprocmask     5014
+#define SYS_sigaltstack                5129
+#define SYS_getrlimit          5095
+#define SYS_madvise            5027
+#define SYS_mincore            5026
+#define SYS_gettid             5178
+#define SYS_tkill              5192
+#define SYS_futex              5194
+#define SYS_sched_getaffinity  5196
+#define SYS_exit_group         5205
+#define SYS_epoll_create       5207
+#define SYS_epoll_ctl          5208
+#define SYS_epoll_wait         5209
+#define SYS_clock_gettime      5222
+#define SYS_epoll_create1      5285
+
+TEXT runtime·exit(SB),NOSPLIT,$-8-4
+       MOVW    code+0(FP), R4
+       MOVV    $SYS_exit_group, R2
+       SYSCALL
+       RET
+
+TEXT runtime·exit1(SB),NOSPLIT,$-8-4
+       MOVW    code+0(FP), R4
+       MOVV    $SYS_exit, R2
+       SYSCALL
+       RET
+
+TEXT runtime·open(SB),NOSPLIT,$-8-20
+       MOVV    name+0(FP), R4
+       MOVW    mode+8(FP), R5
+       MOVW    perm+12(FP), R6
+       MOVV    $SYS_open, R2
+       SYSCALL
+       BEQ     R7, 2(PC)
+       MOVW    $-1, R2
+       MOVW    R2, ret+16(FP)
+       RET
+
+TEXT runtime·closefd(SB),NOSPLIT,$-8-12
+       MOVW    fd+0(FP), R4
+       MOVV    $SYS_close, R2
+       SYSCALL
+       BEQ     R7, 2(PC)
+       MOVW    $-1, R2
+       MOVW    R2, ret+8(FP)
+       RET
+
+TEXT runtime·write(SB),NOSPLIT,$-8-28
+       MOVV    fd+0(FP), R4
+       MOVV    p+8(FP), R5
+       MOVW    n+16(FP), R6
+       MOVV    $SYS_write, R2
+       SYSCALL
+       BEQ     R7, 2(PC)
+       MOVW    $-1, R2
+       MOVW    R2, ret+24(FP)
+       RET
+
+TEXT runtime·read(SB),NOSPLIT,$-8-28
+       MOVW    fd+0(FP), R4
+       MOVV    p+8(FP), R5
+       MOVW    n+16(FP), R6
+       MOVV    $SYS_read, R2
+       SYSCALL
+       BEQ     R7, 2(PC)
+       MOVW    $-1, R2
+       MOVW    R2, ret+24(FP)
+       RET
+
+TEXT runtime·getrlimit(SB),NOSPLIT,$-8-20
+       MOVW    kind+0(FP), R4  // _RLIMIT_AS = 6 on linux/mips
+       MOVV    limit+8(FP), R5
+       MOVV    $SYS_getrlimit, R2
+       SYSCALL
+       MOVW    R2, ret+16(FP)
+       RET
+
+TEXT runtime·usleep(SB),NOSPLIT,$16-4
+       MOVWU   usec+0(FP), R3
+       MOVV    R3, R5
+       MOVW    $1000000, R4
+       DIVVU   R4, R3
+       MOVV    LO, R3
+       MOVV    R3, 8(R29)
+       MULVU   R3, R4
+       MOVV    LO, R4
+       SUBVU   R4, R5
+       MOVV    R5, 16(R29)
+
+       // select(0, 0, 0, 0, &tv)
+       MOVW    $0, R4
+       MOVW    $0, R5
+       MOVW    $0, R6
+       MOVW    $0, R7
+       ADDV    $8, R29, R8
+       MOVV    $SYS_newselect, R2
+       SYSCALL
+       RET
+
+TEXT runtime·gettid(SB),NOSPLIT,$0-4
+       MOVV    $SYS_gettid, R2
+       SYSCALL
+       MOVW    R2, ret+0(FP)
+       RET
+
+TEXT runtime·raise(SB),NOSPLIT,$-8
+       MOVV    $SYS_gettid, R2
+       SYSCALL
+       MOVW    R2, R4  // arg 1 tid
+       MOVW    sig+0(FP), R5   // arg 2
+       MOVV    $SYS_tkill, R2
+       SYSCALL
+       RET
+
+TEXT runtime·raiseproc(SB),NOSPLIT,$-8
+       MOVV    $SYS_getpid, R2
+       SYSCALL
+       MOVW    R2, R4  // arg 1 pid
+       MOVW    sig+0(FP), R5   // arg 2
+       MOVV    $SYS_kill, R2
+       SYSCALL
+       RET
+
+TEXT runtime·setitimer(SB),NOSPLIT,$-8-24
+       MOVW    mode+0(FP), R4
+       MOVV    new+8(FP), R5
+       MOVV    old+16(FP), R6
+       MOVV    $SYS_setitimer, R2
+       SYSCALL
+       RET
+
+TEXT runtime·mincore(SB),NOSPLIT,$-8-28
+       MOVV    addr+0(FP), R4
+       MOVV    n+8(FP), R5
+       MOVV    dst+16(FP), R6
+       MOVV    $SYS_mincore, R2
+       SYSCALL
+       MOVW    R2, ret+24(FP)
+       RET
+
+// func now() (sec int64, nsec int32)
+TEXT time·now(SB),NOSPLIT,$16
+       MOVV    $0(R29), R4
+       MOVV    $0, R5
+       MOVV    $SYS_gettimeofday, R2
+       SYSCALL
+       MOVV    0(R29), R3      // sec
+       MOVV    8(R29), R5      // usec
+       MOVV    $1000, R4
+       MULVU   R4, R5
+       MOVV    LO, R5
+       MOVV    R3, sec+0(FP)
+       MOVW    R5, nsec+8(FP)
+       RET
+
+TEXT runtime·nanotime(SB),NOSPLIT,$16
+       MOVW    $1, R4 // CLOCK_MONOTONIC
+       MOVV    $0(R29), R5
+       MOVV    $SYS_clock_gettime, R2
+       SYSCALL
+       MOVV    0(R29), R3      // sec
+       MOVV    8(R29), R5      // nsec
+       // sec is in R3, nsec in R5
+       // return nsec in R3
+       MOVV    $1000000000, R4
+       MULVU   R4, R3
+       MOVV    LO, R3
+       ADDVU   R5, R3
+       MOVV    R3, ret+0(FP)
+       RET
+
+TEXT runtime·rtsigprocmask(SB),NOSPLIT,$-8-28
+       MOVW    sig+0(FP), R4
+       MOVV    new+8(FP), R5
+       MOVV    old+16(FP), R6
+       MOVW    size+24(FP), R7
+       MOVV    $SYS_rt_sigprocmask, R2
+       SYSCALL
+       BEQ     R7, 2(PC)
+       MOVV    R0, 0xf1(R0)    // crash
+       RET
+
+TEXT runtime·rt_sigaction(SB),NOSPLIT,$-8-36
+       MOVV    sig+0(FP), R4
+       MOVV    new+8(FP), R5
+       MOVV    old+16(FP), R6
+       MOVV    size+24(FP), R7
+       MOVV    $SYS_rt_sigaction, R2
+       SYSCALL
+       MOVW    R2, ret+32(FP)
+       RET
+
+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)
+       RET
+
+TEXT runtime·sigtramp(SB),NOSPLIT,$64
+       // initialize essential registers (just in case)
+       JAL     runtime·reginit(SB)
+
+       // this might be called in external code context,
+       // where g is not set.
+       MOVB    runtime·iscgo(SB), R1
+       BEQ     R1, 2(PC)
+       JAL     runtime·load_g(SB)
+
+       MOVW    R4, 8(R29)
+       MOVV    R5, 16(R29)
+       MOVV    R6, 24(R29)
+       MOVV    $runtime·sigtrampgo(SB), R1
+       JAL     (R1)
+       RET
+
+TEXT runtime·mmap(SB),NOSPLIT,$-8
+       MOVV    addr+0(FP), R4
+       MOVV    n+8(FP), R5
+       MOVW    prot+16(FP), R6
+       MOVW    flags+20(FP), R7
+       MOVW    fd+24(FP), R8
+       MOVW    off+28(FP), R9
+
+       MOVV    $SYS_mmap, R2
+       SYSCALL
+       MOVV    R2, ret+32(FP)
+       RET
+
+TEXT runtime·munmap(SB),NOSPLIT,$-8
+       MOVV    addr+0(FP), R4
+       MOVV    n+8(FP), R5
+       MOVV    $SYS_munmap, R2
+       SYSCALL
+       BEQ     R7, 2(PC)
+       MOVV    R0, 0xf3(R0)    // crash
+       RET
+
+TEXT runtime·madvise(SB),NOSPLIT,$-8
+       MOVV    addr+0(FP), R4
+       MOVV    n+8(FP), R5
+       MOVW    flags+16(FP), R6
+       MOVV    $SYS_madvise, R2
+       SYSCALL
+       // ignore failure - maybe pages are locked
+       RET
+
+// int64 futex(int32 *uaddr, int32 op, int32 val,
+//     struct timespec *timeout, int32 *uaddr2, int32 val2);
+TEXT runtime·futex(SB),NOSPLIT,$-8
+       MOVV    addr+0(FP), R4
+       MOVW    op+8(FP), R5
+       MOVW    val+12(FP), R6
+       MOVV    ts+16(FP), R7
+       MOVV    addr2+24(FP), R8
+       MOVW    val3+32(FP), R9
+       MOVV    $SYS_futex, R2
+       SYSCALL
+       MOVW    R2, ret+40(FP)
+       RET
+
+// int64 clone(int32 flags, void *stk, M *mp, G *gp, void (*fn)(void));
+TEXT runtime·clone(SB),NOSPLIT,$-8
+       MOVW    flags+0(FP), R4
+       MOVV    stk+8(FP), R5
+
+       // Copy mp, gp, fn off parent stack for use by child.
+       // Careful: Linux system call clobbers ???.
+       MOVV    mm+16(FP), R16
+       MOVV    gg+24(FP), R17
+       MOVV    fn+32(FP), R18
+
+       MOVV    R16, -8(R5)
+       MOVV    R17, -16(R5)
+       MOVV    R18, -24(R5)
+       MOVV    $1234, R16
+       MOVV    R16, -32(R5)
+
+       MOVV    $SYS_clone, R2
+       SYSCALL
+
+       // In parent, return.
+       BEQ     R2, 3(PC)
+       MOVW    R2, ret+40(FP)
+       RET
+
+       // In child, on new stack.
+       // initialize essential registers
+       JAL     runtime·reginit(SB)
+       MOVV    -32(R29), R16
+       MOVV    $1234, R1
+       BEQ     R16, R1, 2(PC)
+       MOVV    R0, 0(R0)
+
+       // Initialize m->procid to Linux tid
+       MOVV    $SYS_gettid, R2
+       SYSCALL
+
+       MOVV    -24(R29), R18           // fn
+       MOVV    -16(R29), R17           // g
+       MOVV    -8(R29), R16            // m
+
+       BEQ     R16, nog
+       BEQ     R17, nog
+
+       MOVV    R2, m_procid(R16)
+
+       // TODO: setup TLS.
+
+       // In child, set up new stack
+       MOVV    R16, g_m(R17)
+       MOVV    R17, g
+       //CALL  runtime·stackcheck(SB)
+
+nog:
+       // Call fn
+       JAL     (R18)
+
+       // It shouldn't return.  If it does, exit that thread.
+       MOVW    $111, R4
+       MOVV    $SYS_exit, R2
+       SYSCALL
+       JMP     -3(PC)  // keep exiting
+
+TEXT runtime·sigaltstack(SB),NOSPLIT,$-8
+       MOVV    new+0(FP), R4
+       MOVV    old+8(FP), R5
+       MOVV    $SYS_sigaltstack, R2
+       SYSCALL
+       BEQ     R7, 2(PC)
+       MOVV    R0, 0xf1(R0)    // crash
+       RET
+
+TEXT runtime·osyield(SB),NOSPLIT,$-8
+       MOVV    $SYS_sched_yield, R2
+       SYSCALL
+       RET
+
+TEXT runtime·sched_getaffinity(SB),NOSPLIT,$-8
+       MOVV    pid+0(FP), R4
+       MOVV    len+8(FP), R5
+       MOVV    buf+16(FP), R6
+       MOVV    $SYS_sched_getaffinity, R2
+       SYSCALL
+       MOVW    R2, ret+24(FP)
+       RET
+
+// int32 runtime·epollcreate(int32 size);
+TEXT runtime·epollcreate(SB),NOSPLIT,$-8
+       MOVW    size+0(FP), R4
+       MOVV    $SYS_epoll_create, R2
+       SYSCALL
+       MOVW    R2, ret+8(FP)
+       RET
+
+// int32 runtime·epollcreate1(int32 flags);
+TEXT runtime·epollcreate1(SB),NOSPLIT,$-8
+       MOVW    flags+0(FP), R4
+       MOVV    $SYS_epoll_create1, R2
+       SYSCALL
+       MOVW    R2, ret+8(FP)
+       RET
+
+// func epollctl(epfd, op, fd int32, ev *epollEvent) int
+TEXT runtime·epollctl(SB),NOSPLIT,$-8
+       MOVW    epfd+0(FP), R4
+       MOVW    op+4(FP), R5
+       MOVW    fd+8(FP), R6
+       MOVV    ev+16(FP), R7
+       MOVV    $SYS_epoll_ctl, R2
+       SYSCALL
+       MOVW    R2, ret+24(FP)
+       RET
+
+// int32 runtime·epollwait(int32 epfd, EpollEvent *ev, int32 nev, int32 timeout);
+TEXT runtime·epollwait(SB),NOSPLIT,$-8
+       MOVW    epfd+0(FP), R4
+       MOVV    ev+8(FP), R5
+       MOVW    nev+16(FP), R6
+       MOVW    timeout+20(FP), R7
+       MOVV    $SYS_epoll_wait, R2
+       SYSCALL
+       MOVW    R2, ret+24(FP)
+       RET
+
+// void runtime·closeonexec(int32 fd);
+TEXT runtime·closeonexec(SB),NOSPLIT,$-8
+       MOVW    fd+0(FP), R4  // fd
+       MOVV    $2, R5  // F_SETFD
+       MOVV    $1, R6  // FD_CLOEXEC
+       MOVV    $SYS_fcntl, R2
+       SYSCALL
+       RET
diff --git a/src/runtime/tls_mips64x.s b/src/runtime/tls_mips64x.s
new file mode 100644 (file)
index 0000000..c6f5bfa
--- /dev/null
@@ -0,0 +1,23 @@
+// Copyright 2015 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
+
+#include "go_asm.h"
+#include "go_tls.h"
+#include "funcdata.h"
+#include "textflag.h"
+
+// If !iscgo, this is a no-op.
+//
+// NOTE: mcall() assumes this clobbers only R28 (REGTMP).
+TEXT runtime·save_g(SB),NOSPLIT,$-8-0
+       MOVB    runtime·iscgo(SB), R28
+       BEQ     R28, nocgo
+
+nocgo:
+       RET
+
+TEXT runtime·load_g(SB),NOSPLIT,$-8-0
+       RET