]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: add support files for linux/mips{,le} port
authorVladimir Stefanovic <vladimir.stefanovic@imgtec.com>
Tue, 18 Oct 2016 21:51:01 +0000 (23:51 +0200)
committerBrad Fitzpatrick <bradfitz@golang.org>
Tue, 15 Nov 2016 21:49:01 +0000 (21:49 +0000)
Only exe buildmode without cgo supported.

Change-Id: Id104a79a99d3285c04db00fd98b8affa94ea3c37
Reviewed-on: https://go-review.googlesource.com/31487
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
26 files changed:
src/runtime/asm_mipsx.s [new file with mode: 0644]
src/runtime/atomic_mipsx.s [new file with mode: 0644]
src/runtime/cputicks.go
src/runtime/defs_linux_mipsx.go [new file with mode: 0644]
src/runtime/gcinfo_test.go
src/runtime/hash32.go
src/runtime/lfstack_32bit.go
src/runtime/malloc.go
src/runtime/memclr_mipsx.s [new file with mode: 0644]
src/runtime/memmove_mipsx.s [new file with mode: 0644]
src/runtime/os_linux_generic.go
src/runtime/os_linux_mips64x.go
src/runtime/os_linux_mipsx.go [new file with mode: 0644]
src/runtime/os_linux_noauxv.go
src/runtime/rt0_linux_mipsx.s [new file with mode: 0644]
src/runtime/signal_linux_mipsx.go [new file with mode: 0644]
src/runtime/signal_mipsx.go [new file with mode: 0644]
src/runtime/sigtab_linux_generic.go
src/runtime/sigtab_linux_mips64x.go [deleted file]
src/runtime/sigtab_linux_mipsx.go [new file with mode: 0644]
src/runtime/stubs32.go
src/runtime/sys_linux_mipsx.s [new file with mode: 0644]
src/runtime/sys_mipsx.go [new file with mode: 0644]
src/runtime/tls_mipsx.s [new file with mode: 0644]
src/runtime/unaligned2.go
src/runtime/vlrt.go

diff --git a/src/runtime/asm_mipsx.s b/src/runtime/asm_mipsx.s
new file mode 100644 (file)
index 0000000..cd855c7
--- /dev/null
@@ -0,0 +1,794 @@
+// 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 mips mipsle
+
+#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
+
+       ADDU    $-12, R29
+       MOVW    R1, 4(R29)      // argc
+       MOVW    R2, 8(R29)      // argv
+
+       // create istack out of the given (operating system) stack.
+       // _cgo_init may update stackguard.
+       MOVW    $runtime·g0(SB), g
+       MOVW    $(-64*1024), R23
+       ADD     R23, R29, R1
+       MOVW    R1, g_stackguard0(g)
+       MOVW    R1, g_stackguard1(g)
+       MOVW    R1, (g_stack+stack_lo)(g)
+       MOVW    R29, (g_stack+stack_hi)(g)
+
+// TODO(mips32): cgo
+
+nocgo:
+       // update stackguard after _cgo_init
+       MOVW    (g_stack+stack_lo)(g), R1
+       ADD     $const__StackGuard, R1
+       MOVW    R1, g_stackguard0(g)
+       MOVW    R1, g_stackguard1(g)
+
+       // set the per-goroutine and per-mach "registers"
+       MOVW    $runtime·m0(SB), R1
+
+       // save m->g0 = g0
+       MOVW    g, m_g0(R1)
+       // save m0 to g0->m
+       MOVW    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
+       MOVW    $runtime·mainPC(SB), R1        // entry
+       ADDU    $-12, R29
+       MOVW    R1, 8(R29)
+       MOVW    R0, 4(R29)
+       MOVW    R0, 0(R29)
+       JAL     runtime·newproc(SB)
+       ADDU    $12, R29
+
+       // start this M
+       JAL     runtime·mstart(SB)
+
+       UNDEF
+       RET
+
+DATA   runtime·mainPC+0(SB)/4,$runtime·main(SB)
+GLOBL  runtime·mainPC(SB),RODATA,$4
+
+TEXT runtime·breakpoint(SB),NOSPLIT,$0-0
+       BREAK
+       RET
+
+TEXT runtime·asminit(SB),NOSPLIT,$0-0
+       RET
+
+/*
+ *  go-routine
+ */
+
+// void gosave(Gobuf*)
+// save state in Gobuf; setjmp
+TEXT runtime·gosave(SB),NOSPLIT,$-4-4
+       MOVW    buf+0(FP), R1
+       MOVW    R29, gobuf_sp(R1)
+       MOVW    R31, gobuf_pc(R1)
+       MOVW    g, gobuf_g(R1)
+       MOVW    R0, gobuf_lr(R1)
+       MOVW    R0, gobuf_ret(R1)
+       // Assert ctxt is zero. See func save.
+       MOVW    gobuf_ctxt(R1), R1
+       BEQ     R1, 2(PC)
+       JAL     runtime·badctxt(SB)
+       RET
+
+// void gogo(Gobuf*)
+// restore state from Gobuf; longjmp
+TEXT runtime·gogo(SB),NOSPLIT,$8-4
+       MOVW    buf+0(FP), R3
+
+       // If ctxt is not nil, invoke deletion barrier before overwriting.
+       MOVW    gobuf_ctxt(R3), R1
+       BEQ     R1, nilctxt
+       MOVW    $gobuf_ctxt(R3), R1
+       MOVW    R1, 4(R29)
+       MOVW    R0, 8(R29)
+       JAL     runtime·writebarrierptr_prewrite(SB)
+       MOVW    buf+0(FP), R3
+
+nilctxt:
+       MOVW    gobuf_g(R3), g  // make sure g is not nil
+       JAL     runtime·save_g(SB)
+
+       MOVW    0(g), R2
+       MOVW    gobuf_sp(R3), R29
+       MOVW    gobuf_lr(R3), R31
+       MOVW    gobuf_ret(R3), R1
+       MOVW    gobuf_ctxt(R3), REGCTXT
+       MOVW    R0, gobuf_sp(R3)
+       MOVW    R0, gobuf_ret(R3)
+       MOVW    R0, gobuf_lr(R3)
+       MOVW    R0, gobuf_ctxt(R3)
+       MOVW    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,$-4-4
+       // Save caller state in g->sched
+       MOVW    R29, (g_sched+gobuf_sp)(g)
+       MOVW    R31, (g_sched+gobuf_pc)(g)
+       MOVW    R0, (g_sched+gobuf_lr)(g)
+       MOVW    g, (g_sched+gobuf_g)(g)
+
+       // Switch to m->g0 & its stack, call fn.
+       MOVW    g, R1
+       MOVW    g_m(g), R3
+       MOVW    m_g0(R3), g
+       JAL     runtime·save_g(SB)
+       BNE     g, R1, 2(PC)
+       JMP     runtime·badmcall(SB)
+       MOVW    fn+0(FP), REGCTXT       // context
+       MOVW    0(REGCTXT), R4  // code pointer
+       MOVW    (g_sched+gobuf_sp)(g), R29      // sp = m->g0->sched.sp
+       ADDU    $-8, R29        // make room for 1 arg and fake LR
+       MOVW    R1, 4(R29)
+       MOVW    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-4
+       MOVW    fn+0(FP), R1    // R1 = fn
+       MOVW    R1, REGCTXT     // context
+       MOVW    g_m(g), R2      // R2 = m
+
+       MOVW    m_gsignal(R2), R3       // R3 = gsignal
+       BEQ     g, R3, noswitch
+
+       MOVW    m_g0(R2), R3    // R3 = g0
+       BEQ     g, R3, noswitch
+
+       MOVW    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.
+       MOVW    $runtime·badsystemstack(SB), R4
+       JAL     (R4)
+
+switch:
+       // save our state in g->sched.  Pretend to
+       // be systemstack_switch if the G stack is scanned.
+       MOVW    $runtime·systemstack_switch(SB), R4
+       ADDU    $8, R4  // get past prologue
+       MOVW    R4, (g_sched+gobuf_pc)(g)
+       MOVW    R29, (g_sched+gobuf_sp)(g)
+       MOVW    R0, (g_sched+gobuf_lr)(g)
+       MOVW    g, (g_sched+gobuf_g)(g)
+
+       // switch to g0
+       MOVW    R3, g
+       JAL     runtime·save_g(SB)
+       MOVW    (g_sched+gobuf_sp)(g), R1
+       // make it look like mstart called systemstack on g0, to stop traceback
+       ADDU    $-4, R1
+       MOVW    $runtime·mstart(SB), R2
+       MOVW    R2, 0(R1)
+       MOVW    R1, R29
+
+       // call target function
+       MOVW    0(REGCTXT), R4  // code pointer
+       JAL     (R4)
+
+       // switch back to g
+       MOVW    g_m(g), R1
+       MOVW    m_curg(R1), g
+       JAL     runtime·save_g(SB)
+       MOVW    (g_sched+gobuf_sp)(g), R29
+       MOVW    R0, (g_sched+gobuf_sp)(g)
+       RET
+
+noswitch:
+       // already on m stack, just call directly
+       MOVW    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,$-4-0
+       // Cannot grow scheduler stack (m->g0).
+       MOVW    g_m(g), R7
+       MOVW    m_g0(R7), R8
+       BNE     g, R8, 3(PC)
+       JAL     runtime·badmorestackg0(SB)
+       JAL     runtime·abort(SB)
+
+       // Cannot grow signal stack (m->gsignal).
+       MOVW    m_gsignal(R7), R8
+       BNE     g, R8, 3(PC)
+       JAL     runtime·badmorestackgsignal(SB)
+       JAL     runtime·abort(SB)
+
+       // Called from f.
+       // Set g->sched to context in f.
+       MOVW    R29, (g_sched+gobuf_sp)(g)
+       MOVW    R31, (g_sched+gobuf_pc)(g)
+       MOVW    R3, (g_sched+gobuf_lr)(g)
+       // newstack will fill gobuf.ctxt.
+
+       // Called from f.
+       // Set m->morebuf to f's caller.
+       MOVW    R3, (m_morebuf+gobuf_pc)(R7)    // f's caller's PC
+       MOVW    R29, (m_morebuf+gobuf_sp)(R7)   // f's caller's SP
+       MOVW    g, (m_morebuf+gobuf_g)(R7)
+
+       // Call newstack on m->g0's stack.
+       MOVW    m_g0(R7), g
+       JAL     runtime·save_g(SB)
+       MOVW    (g_sched+gobuf_sp)(g), R29
+       // Create a stack frame on g0 to call newstack.
+       MOVW    R0, -8(R29)     // Zero saved LR in frame
+       ADDU    $-8, R29
+       MOVW    REGCTXT, 4(R29) // ctxt argument
+       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,$0-0
+       MOVW    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.
+       MOVW    (g_stkbar+slice_array)(g), R2
+       MOVW    g_stkbarPos(g), R3
+       MOVW    $stkbar__size, R4
+       MULU    R3, R4
+       MOVW    LO, R4
+       ADDU    R2, R4
+       MOVW    stkbar_savedLRVal(R4), R4
+       ADDU    $1, R3
+       MOVW    R3, g_stkbarPos(g)      // Record that this stack barrier was hit.
+       JMP     (R4)    // Jump to the original return PC.
+
+// 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.
+
+#define DISPATCH(NAME,MAXSIZE) \
+       MOVW    $MAXSIZE, R23;  \
+       SGTU    R1, R23, R23;   \
+       BNE     R23, 3(PC);     \
+       MOVW    $NAME(SB), R4;  \
+       JMP     (R4)
+
+TEXT reflect·call(SB),NOSPLIT,$0-20
+       JMP     ·reflectcall(SB)
+
+TEXT ·reflectcall(SB),NOSPLIT,$-4-20
+       MOVW    argsize+12(FP), R1
+
+       DISPATCH(runtime·call16, 16)
+       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)
+       MOVW    $runtime·badreflectcall(SB), R4
+       JMP     (R4)
+
+#define CALLFN(NAME,MAXSIZE)   \
+TEXT NAME(SB),WRAPPER,$MAXSIZE-20;     \
+       NO_LOCAL_POINTERS;      \
+       /* copy arguments to stack */           \
+       MOVW    arg+8(FP), R1;  \
+       MOVW    argsize+12(FP), R2;     \
+       MOVW    R29, R3;        \
+       ADDU    $4, R3; \
+       ADDU    R3, R2; \
+       BEQ     R3, R2, 6(PC);  \
+       MOVBU   (R1), R4;       \
+       ADDU    $1, R1; \
+       MOVBU   R4, (R3);       \
+       ADDU    $1, R3; \
+       JMP     -5(PC); \
+       /* call function */                     \
+       MOVW    f+4(FP), REGCTXT;       \
+       MOVW    (REGCTXT), R4;  \
+       PCDATA  $PCDATA_StackMapIndex, $0;      \
+       JAL     (R4);   \
+       /* copy return values back */           \
+       MOVW    argtype+0(FP), R5;      \
+       MOVW    arg+8(FP), R1;  \
+       MOVW    n+12(FP), R2;   \
+       MOVW    retoffset+16(FP), R4;   \
+       ADDU    $4, R29, R3;    \
+       ADDU    R4, R3; \
+       ADDU    R4, R1; \
+       SUBU    R4, R2; \
+       JAL     callRet<>(SB);          \
+       RET
+
+// callRet copies return values back at the end of call*. This is a
+// separate function so it can allocate stack space for the arguments
+// to reflectcallmove. It does not follow the Go ABI; it expects its
+// arguments in registers.
+TEXT callRet<>(SB), NOSPLIT, $16-0
+       MOVW    R5, 4(R29)
+       MOVW    R1, 8(R29)
+       MOVW    R3, 12(R29)
+       MOVW    R2, 16(R29)
+       JAL     runtime·reflectcallmove(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-4
+       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,$0-8
+       MOVW    0(R29), R31
+       ADDU    $-8, R31
+
+       MOVW    fv+0(FP), REGCTXT
+       MOVW    argp+4(FP), R29
+       ADDU    $-4, R29
+       NOR     R0, R0  // prevent scheduling
+       MOVW    0(REGCTXT), R4
+       JMP     (R4)
+
+// Save state of caller into g->sched. Smashes R1.
+TEXT gosave<>(SB),NOSPLIT,$0
+       MOVW    R31, (g_sched+gobuf_pc)(g)
+       MOVW    R29, (g_sched+gobuf_sp)(g)
+       MOVW    R0, (g_sched+gobuf_lr)(g)
+       MOVW    R0, (g_sched+gobuf_ret)(g)
+       // Assert ctxt is zero. See func save.
+       MOVW    (g_sched+gobuf_ctxt)(g), R1
+       BEQ     R1, 2(PC)
+       JAL     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.
+// Not implemented.
+TEXT ·asmcgocall(SB),NOSPLIT,$0-12
+       UNDEF
+
+// cgocallback(void (*fn)(void*), void *frame, uintptr framesize)
+// Turn the fn into a Go func (by taking its address) and call
+// cgocallback_gofunc.
+// Not implemented.
+TEXT runtime·cgocallback(SB),NOSPLIT,$0-16
+       UNDEF
+
+// cgocallback_gofunc(FuncVal*, void *frame, uintptr framesize)
+// See cgocall.go for more details.
+// Not implemented.
+TEXT ·cgocallback_gofunc(SB),NOSPLIT,$0-16
+       UNDEF
+
+// void setg(G*); set g. for use by needm.
+// This only happens if iscgo, so jump straight to save_g
+TEXT runtime·setg(SB),NOSPLIT,$0-4
+       MOVW    gg+0(FP), g
+       JAL     runtime·save_g(SB)
+       RET
+
+// void setg_gcc(G*); set g in C TLS.
+// Must obey the gcc calling convention.
+// Not implemented.
+TEXT setg_gcc<>(SB),NOSPLIT,$0
+       UNDEF
+
+TEXT runtime·getcallerpc(SB),NOSPLIT,$4-8
+       MOVW    8(R29), R1      // LR saved by caller
+       MOVW    runtime·stackBarrierPC(SB), R2
+       BNE     R1, R2, nobar
+       JAL     runtime·nextBarrierPC(SB)      // Get original return PC.
+       MOVW    4(R29), R1
+nobar:
+       MOVW    R1, ret+4(FP)
+       RET
+
+TEXT runtime·setcallerpc(SB),NOSPLIT,$4-8
+       MOVW    pc+4(FP), R1
+       MOVW    8(R29), R2
+       MOVW    runtime·stackBarrierPC(SB), R3
+       BEQ     R2, R3, setbar
+       MOVW    R1, 8(R29)      // set LR in caller
+       RET
+setbar:
+       MOVW    R1, 4(R29)
+       JAL     runtime·setNextBarrierPC(SB)   // Set the stack barrier return PC.
+       RET
+
+TEXT runtime·abort(SB),NOSPLIT,$0-0
+       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,$16-12
+       GO_ARGS
+       NO_LOCAL_POINTERS
+       MOVW    p+0(FP), R1
+       MOVW    h+4(FP), R2
+       MOVW    4(REGCTXT), R3
+       MOVW    R1, 4(R29)
+       MOVW    R2, 8(R29)
+       MOVW    R3, 12(R29)
+       JAL     runtime·memhash(SB)
+       MOVW    16(R29), R1
+       MOVW    R1, ret+8(FP)
+       RET
+
+// Not implemented.
+TEXT runtime·aeshash(SB),NOSPLIT,$0
+       UNDEF
+
+// Not implemented.
+TEXT runtime·aeshash32(SB),NOSPLIT,$0
+       UNDEF
+
+// Not implemented.
+TEXT runtime·aeshash64(SB),NOSPLIT,$0
+       UNDEF
+
+// Not implemented.
+TEXT runtime·aeshashstr(SB),NOSPLIT,$0
+       UNDEF
+
+// memequal(a, b unsafe.Pointer, size uintptr) bool
+TEXT runtime·memequal(SB),NOSPLIT,$0-13
+       MOVW    a+0(FP), R1
+       MOVW    b+4(FP), R2
+       BEQ     R1, R2, eq
+       MOVW    size+8(FP), R3
+       ADDU    R1, R3, R4
+loop:
+       BNE     R1, R4, test
+       MOVW    $1, R1
+       MOVB    R1, ret+12(FP)
+       RET
+test:
+       MOVBU   (R1), R6
+       ADDU    $1, R1
+       MOVBU   (R2), R7
+       ADDU    $1, R2
+       BEQ     R6, R7, loop
+
+       MOVB    R0, ret+12(FP)
+       RET
+eq:
+       MOVW    $1, R1
+       MOVB    R1, ret+12(FP)
+       RET
+
+// memequal_varlen(a, b unsafe.Pointer) bool
+TEXT runtime·memequal_varlen(SB),NOSPLIT,$0-9
+       MOVW    a+0(FP), R1
+       MOVW    b+4(FP), R2
+       BEQ     R1, R2, eq
+       MOVW    4(REGCTXT), R3  // compiler stores size at offset 4 in the closure
+       ADDU    R1, R3, R4
+loop:
+       BNE     R1, R4, test
+       MOVW    $1, R1
+       MOVB    R1, ret+8(FP)
+       RET
+test:
+       MOVBU   (R1), R6
+       ADDU    $1, R1
+       MOVBU   (R2), R7
+       ADDU    $1, R2
+       BEQ     R6, R7, loop
+
+       MOVB    R0, ret+8(FP)
+       RET
+eq:
+       MOVW    $1, R1
+       MOVB    R1, ret+8(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-17
+       MOVW    s1_base+0(FP), R1
+       MOVW    s2_base+8(FP), R2
+       MOVW    $1, R3
+       MOVBU   R3, ret+16(FP)
+       BNE     R1, R2, 2(PC)
+       RET
+       MOVW    s1_len+4(FP), R3
+       ADDU    R1, R3, R4
+loop:
+       BNE     R1, R4, 2(PC)
+       RET
+       MOVBU   (R1), R6
+       ADDU    $1, R1
+       MOVBU   (R2), R7
+       ADDU    $1, R2
+       BEQ     R6, R7, loop
+       MOVB    R0, ret+16(FP)
+       RET
+
+TEXT bytes·Equal(SB),NOSPLIT,$0-25
+       MOVW    a_len+4(FP), R3
+       MOVW    b_len+16(FP), R4
+       BNE     R3, R4, noteq   // unequal lengths are not equal
+
+       MOVW    a+0(FP), R1
+       MOVW    b+12(FP), R2
+       ADDU    R1, R3  // end
+
+loop:
+       BEQ     R1, R3, equal   // reached the end
+       MOVBU   (R1), R6
+       ADDU    $1, R1
+       MOVBU   (R2), R7
+       ADDU    $1, R2
+       BEQ     R6, R7, loop
+
+noteq:
+       MOVB    R0, ret+24(FP)
+       RET
+
+equal:
+       MOVW    $1, R1
+       MOVB    R1, ret+24(FP)
+       RET
+
+TEXT bytes·IndexByte(SB),NOSPLIT,$0-20
+       MOVW    s+0(FP), R1
+       MOVW    s_len+4(FP), R2
+       MOVBU   c+12(FP), R3    // byte to find
+       ADDU    $1, R1, R4      // store base+1 for later
+       ADDU    R1, R2  // end
+
+loop:
+       BEQ     R1, R2, notfound
+       MOVBU   (R1), R5
+       ADDU    $1, R1
+       BNE     R3, R5, loop
+
+       SUBU    R4, R1  // R1 will be one beyond the position we want so remove (base+1)
+       MOVW    R1, ret+16(FP)
+       RET
+
+notfound:
+       MOVW    $-1, R1
+       MOVW    R1, ret+16(FP)
+       RET
+
+TEXT strings·IndexByte(SB),NOSPLIT,$0-16
+       MOVW    s_base+0(FP), R1
+       MOVW    s_len+4(FP), R2
+       MOVBU   c+8(FP), R3     // byte to find
+       ADDU    $1, R1, R4      // store base+1 for later
+       ADDU    R1, R2  // end
+
+loop:
+       BEQ     R1, R2, notfound
+       MOVBU   (R1), R5
+       ADDU    $1, R1
+       BNE     R3, R5, loop
+
+       SUBU    R4, R1  // remove (base+1)
+       MOVW    R1, ret+12(FP)
+       RET
+
+notfound:
+       MOVW    $-1, R1
+       MOVW    R1, ret+12(FP)
+       RET
+
+TEXT runtime·cmpstring(SB),NOSPLIT,$0-20
+       MOVW    s1_base+0(FP), R3
+       MOVW    s1_len+4(FP), R1
+       MOVW    s2_base+8(FP), R4
+       MOVW    s2_len+12(FP), R2
+       BEQ     R3, R4, samebytes
+       SGTU    R1, R2, R7
+       MOVW    R1, R8
+       CMOVN   R7, R2, R8      // R8 is min(R1, R2)
+
+       ADDU    R3, R8  // R3 is current byte in s1, R8 is last byte in s1 to compare
+loop:
+       BEQ     R3, R8, samebytes       // all compared bytes were the same; compare lengths
+
+       MOVBU   (R3), R6
+       ADDU    $1, R3
+       MOVBU   (R4), R7
+       ADDU    $1, R4
+       BEQ     R6, R7 , loop
+       // bytes differed
+       SGTU    R6, R7, R8
+       MOVW    $-1, R6
+       CMOVZ   R8, R6, R8
+       JMP     cmp_ret
+samebytes:
+       SGTU    R1, R2, R6
+       SGTU    R2, R1, R7
+       SUBU    R7, R6, R8
+cmp_ret:
+       MOVW    R8, ret+16(FP)
+       RET
+
+TEXT bytes·Compare(SB),NOSPLIT,$0-28
+       MOVW    s1_base+0(FP), R3
+       MOVW    s2_base+12(FP), R4
+       MOVW    s1_len+4(FP), R1
+       MOVW    s2_len+16(FP), R2
+       BEQ     R3, R4, samebytes
+       SGTU    R1, R2, R7
+       MOVW    R1, R8
+       CMOVN   R7, R2, R8      // R8 is min(R1, R2)
+
+       ADDU    R3, R8  // R3 is current byte in s1, R8 is last byte in s1 to compare
+loop:
+       BEQ     R3, R8, samebytes
+
+       MOVBU   (R3), R6
+       ADDU    $1, R3
+       MOVBU   (R4), R7
+       ADDU    $1, R4
+       BEQ     R6, R7 , loop
+
+       SGTU    R6, R7, R8
+       MOVW    $-1, R6
+       CMOVZ   R8, R6, R8
+       JMP     cmp_ret
+samebytes:
+       SGTU    R1, R2, R6
+       SGTU    R2, R1, R7
+       SUBU    R7, R6, R8
+cmp_ret:
+       MOVW    R8, ret+24(FP)
+       RET
+
+TEXT runtime·fastrand(SB),NOSPLIT,$0-4
+       MOVW    g_m(g), R2
+       MOVW    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.
+// Not implemented.
+TEXT _cgo_topofstack(SB),NOSPLIT,$-4
+       UNDEF
+
+// The top-most function running on a goroutine
+// returns to goexit+PCQuantum.
+TEXT runtime·goexit(SB),NOSPLIT,$-4-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-4
+       RET
+
+TEXT runtime·prefetcht1(SB),NOSPLIT,$0-4
+       RET
+
+TEXT runtime·prefetcht2(SB),NOSPLIT,$0-4
+       RET
+
+TEXT runtime·prefetchnta(SB),NOSPLIT,$0-4
+       RET
+
+TEXT ·checkASM(SB),NOSPLIT,$0-1
+       MOVW    $1, R1
+       MOVB    R1, ret+0(FP)
+       RET
diff --git a/src/runtime/atomic_mipsx.s b/src/runtime/atomic_mipsx.s
new file mode 100644 (file)
index 0000000..ed078a2
--- /dev/null
@@ -0,0 +1,11 @@
+// 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 mips mipsle
+
+#include "textflag.h"
+
+TEXT ·publicationBarrier(SB),NOSPLIT,$0
+       SYNC
+       RET
index 91627460c3c05d920cab0e354775ba62a906d75a..ccc3947bb2ffecdf30ccef003e3ffadb69658718 100644 (file)
@@ -6,6 +6,8 @@
 // +build !arm64
 // +build !mips64
 // +build !mips64le
+// +build !mips
+// +build !mipsle
 
 package runtime
 
diff --git a/src/runtime/defs_linux_mipsx.go b/src/runtime/defs_linux_mipsx.go
new file mode 100644 (file)
index 0000000..702fbb5
--- /dev/null
@@ -0,0 +1,188 @@
+// 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 mips mipsle
+// +build linux
+
+package runtime
+
+const (
+       _EINTR  = 0x4
+       _EAGAIN = 0xb
+       _ENOMEM = 0xc
+
+       _PROT_NONE  = 0x0
+       _PROT_READ  = 0x1
+       _PROT_WRITE = 0x2
+       _PROT_EXEC  = 0x4
+
+       _MAP_ANON    = 0x800
+       _MAP_PRIVATE = 0x2
+       _MAP_FIXED   = 0x10
+
+       _MADV_DONTNEED   = 0x4
+       _MADV_HUGEPAGE   = 0xe
+       _MADV_NOHUGEPAGE = 0xf
+
+       _SA_RESTART = 0x10000000
+       _SA_ONSTACK = 0x8000000
+       _SA_SIGINFO = 0x8
+
+       _SIGHUP    = 0x1
+       _SIGINT    = 0x2
+       _SIGQUIT   = 0x3
+       _SIGILL    = 0x4
+       _SIGTRAP   = 0x5
+       _SIGABRT   = 0x6
+       _SIGEMT    = 0x7
+       _SIGFPE    = 0x8
+       _SIGKILL   = 0x9
+       _SIGBUS    = 0xa
+       _SIGSEGV   = 0xb
+       _SIGSYS    = 0xc
+       _SIGPIPE   = 0xd
+       _SIGALRM   = 0xe
+       _SIGUSR1   = 0x10
+       _SIGUSR2   = 0x11
+       _SIGCHLD   = 0x12
+       _SIGPWR    = 0x13
+       _SIGWINCH  = 0x14
+       _SIGURG    = 0x15
+       _SIGIO     = 0x16
+       _SIGSTOP   = 0x17
+       _SIGTSTP   = 0x18
+       _SIGCONT   = 0x19
+       _SIGTTIN   = 0x1a
+       _SIGTTOU   = 0x1b
+       _SIGVTALRM = 0x1c
+       _SIGPROF   = 0x1d
+       _SIGXCPU   = 0x1e
+       _SIGXFSZ   = 0x1f
+
+       _FPE_INTDIV = 0x1
+       _FPE_INTOVF = 0x2
+       _FPE_FLTDIV = 0x3
+       _FPE_FLTOVF = 0x4
+       _FPE_FLTUND = 0x5
+       _FPE_FLTRES = 0x6
+       _FPE_FLTINV = 0x7
+       _FPE_FLTSUB = 0x8
+
+       _BUS_ADRALN = 0x1
+       _BUS_ADRERR = 0x2
+       _BUS_OBJERR = 0x3
+
+       _SEGV_MAPERR = 0x1
+       _SEGV_ACCERR = 0x2
+
+       _ITIMER_REAL    = 0x0
+       _ITIMER_VIRTUAL = 0x1
+       _ITIMER_PROF    = 0x2
+
+       _EPOLLIN       = 0x1
+       _EPOLLOUT      = 0x4
+       _EPOLLERR      = 0x8
+       _EPOLLHUP      = 0x10
+       _EPOLLRDHUP    = 0x2000
+       _EPOLLET       = 0x80000000
+       _EPOLL_CLOEXEC = 0x80000
+       _EPOLL_CTL_ADD = 0x1
+       _EPOLL_CTL_DEL = 0x2
+       _EPOLL_CTL_MOD = 0x3
+)
+
+type timespec struct {
+       tv_sec  int32
+       tv_nsec int32
+}
+
+//go:nosplit
+func (ts *timespec) set_sec(x int64) {
+       ts.tv_sec = int32(x)
+}
+
+//go:nosplit
+func (ts *timespec) set_nsec(x int32) {
+       ts.tv_nsec = x
+}
+
+type timeval struct {
+       tv_sec  int32
+       tv_usec int32
+}
+
+//go:nosplit
+func (tv *timeval) set_usec(x int32) {
+       tv.tv_usec = x
+}
+
+type sigactiont struct {
+       sa_flags   uint32
+       sa_handler uintptr
+       sa_mask    [4]uint32
+       // linux header does not have sa_restorer field,
+       // but it is used in setsig(). it is no harm to put it here
+       sa_restorer uintptr
+}
+
+type siginfo struct {
+       si_signo int32
+       si_code  int32
+       si_errno int32
+       // below here is a union; si_addr is the only field we use
+       si_addr uint32
+}
+
+type itimerval struct {
+       it_interval timeval
+       it_value    timeval
+}
+
+type epollevent struct {
+       events    uint32
+       pad_cgo_0 [4]byte
+       data      uint64
+}
+
+const (
+       _O_RDONLY    = 0x0
+       _O_CLOEXEC   = 0x80000
+       _SA_RESTORER = 0
+)
+
+type stackt struct {
+       ss_sp    *byte
+       ss_size  uintptr
+       ss_flags int32
+}
+
+type sigcontext struct {
+       sc_regmask   uint32
+       sc_status    uint32
+       sc_pc        uint64
+       sc_regs      [32]uint64
+       sc_fpregs    [32]uint64
+       sc_acx       uint32
+       sc_fpc_csr   uint32
+       sc_fpc_eir   uint32
+       sc_used_math uint32
+       sc_dsp       uint32
+       sc_mdhi      uint64
+       sc_mdlo      uint64
+       sc_hi1       uint32
+       sc_lo1       uint32
+       sc_hi2       uint32
+       sc_lo2       uint32
+       sc_hi3       uint32
+       sc_lo3       uint32
+}
+
+type ucontext struct {
+       uc_flags    uint32
+       uc_link     *ucontext
+       uc_stack    stackt
+       Pad_cgo_0   [4]byte
+       uc_mcontext sigcontext
+       uc_sigmask  [4]uint32
+}
index 011f0054032060247dc31b47538fd9b12ca65a74..14f514f96a23e8bdc89e02448b6e3130a32a8a71 100644 (file)
@@ -139,7 +139,7 @@ type BigStruct struct {
 
 func infoBigStruct() []byte {
        switch runtime.GOARCH {
-       case "386", "arm":
+       case "386", "arm", "mips", "mipsle":
                return []byte{
                        typePointer,                                                // q *int
                        typeScalar, typeScalar, typeScalar, typeScalar, typeScalar, // w byte; e [17]byte
index 2b7c5c0c6835469228b214505ab274d669625499..be59076635ae6fe7119a222c23bbcfda3e51bcb5 100644 (file)
@@ -6,7 +6,7 @@
 //   xxhash: https://code.google.com/p/xxhash/
 // cityhash: https://code.google.com/p/cityhash/
 
-// +build 386 arm
+// +build 386 arm mips mipsle
 
 package runtime
 
index 2f59e0212efa5a914b026f2d040b891a0313291e..d36ca50971d6e0298c4b6d79629aa91cf33bce2e 100644 (file)
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build 386 arm nacl
+// +build 386 arm nacl mips mipsle
 
 package runtime
 
index 366fe9608daff58d67e7540638ed4f3a7f1b9bfb..1c9efc3432e422fcbc4b3ae3e5e27f1a46c42988 100644 (file)
@@ -141,10 +141,11 @@ const (
        // See https://golang.org/issue/5402 and https://golang.org/issue/5236.
        // On other 64-bit platforms, we limit the arena to 512GB, or 39 bits.
        // On 32-bit, we don't bother limiting anything, so we use the full 32-bit address.
+       // The only exception is mips32 which only has access to low 2GB of virtual memory.
        // On Darwin/arm64, we cannot reserve more than ~5GB of virtual memory,
        // but as most devices have less than 4GB of physical memory anyway, we
        // try to be conservative here, and only ask for a 2GB heap.
-       _MHeapMap_TotalBits = (_64bit*sys.GoosWindows)*35 + (_64bit*(1-sys.GoosWindows)*(1-sys.GoosDarwin*sys.GoarchArm64))*39 + sys.GoosDarwin*sys.GoarchArm64*31 + (1-_64bit)*32
+       _MHeapMap_TotalBits = (_64bit*sys.GoosWindows)*35 + (_64bit*(1-sys.GoosWindows)*(1-sys.GoosDarwin*sys.GoarchArm64))*39 + sys.GoosDarwin*sys.GoarchArm64*31 + (1-_64bit)*(32-(sys.GoarchMips+sys.GoarchMipsle))
        _MHeapMap_Bits      = _MHeapMap_TotalBits - _PageShift
 
        _MaxMem = uintptr(1<<_MHeapMap_TotalBits - 1)
diff --git a/src/runtime/memclr_mipsx.s b/src/runtime/memclr_mipsx.s
new file mode 100644 (file)
index 0000000..ad013b8
--- /dev/null
@@ -0,0 +1,71 @@
+// 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 mips mipsle
+
+#include "textflag.h"
+
+#ifdef GOARCH_mips
+#define MOVWHI  MOVWL
+#define MOVWLO  MOVWR
+#else
+#define MOVWHI  MOVWR
+#define MOVWLO  MOVWL
+#endif
+
+// void runtime·memclrNoHeapPointers(void*, uintptr)
+TEXT runtime·memclrNoHeapPointers(SB),NOSPLIT,$0-8
+       MOVW    n+4(FP), R2
+       MOVW    ptr+0(FP), R1
+
+       SGTU    $4, R2, R3
+       ADDU    R2, R1, R4
+       BNE     R3, small_zero
+
+ptr_align:
+       AND     $3, R1, R3
+       BEQ     R3, setup
+       SUBU    R1, R0, R3
+       AND     $3, R3          // R3 contains number of bytes needed to align ptr
+       MOVWHI  R0, 0(R1)       // MOVWHI will write zeros up to next word boundary
+       SUBU    R3, R2
+       ADDU    R3, R1
+
+setup:
+       AND     $31, R2, R6
+       AND     $3, R2, R5
+       SUBU    R6, R4, R6      // end pointer for 32-byte chunks
+       SUBU    R5, R4, R5      // end pointer for 4-byte chunks
+
+large:
+       BEQ     R1, R6, words
+       MOVW    R0, 0(R1)
+       MOVW    R0, 4(R1)
+       MOVW    R0, 8(R1)
+       MOVW    R0, 12(R1)
+       MOVW    R0, 16(R1)
+       MOVW    R0, 20(R1)
+       MOVW    R0, 24(R1)
+       MOVW    R0, 28(R1)
+       ADDU    $32, R1
+       JMP     large
+
+words:
+       BEQ     R1, R5, tail
+       MOVW    R0, 0(R1)
+       ADDU    $4, R1
+       JMP     words
+
+tail:
+       BEQ     R1, R4, ret
+       MOVWLO  R0, -1(R4)
+
+ret:
+       RET
+
+small_zero:
+       BEQ     R1, R4, ret
+       MOVB    R0, 0(R1)
+       ADDU    $1, R1
+       JMP     small_zero
diff --git a/src/runtime/memmove_mipsx.s b/src/runtime/memmove_mipsx.s
new file mode 100644 (file)
index 0000000..e934e4d
--- /dev/null
@@ -0,0 +1,258 @@
+// 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 mips mipsle
+
+#include "textflag.h"
+
+#ifdef GOARCH_mips
+#define MOVWHI  MOVWL
+#define MOVWLO  MOVWR
+#else
+#define MOVWHI  MOVWR
+#define MOVWLO  MOVWL
+#endif
+
+// void runtime·memmove(void*, void*, uintptr)
+TEXT runtime·memmove(SB),NOSPLIT,$-0-12
+       MOVW    n+8(FP), R3
+       MOVW    from+4(FP), R2
+       MOVW    to+0(FP), R1
+
+       ADDU    R3, R2, R4      // end pointer for source
+       ADDU    R3, R1, R5      // end pointer for destination
+
+       // if destination is ahead of source, start at the end of the buffer and go backward.
+       SGTU    R1, R2, R6
+       BNE     R6, backward
+
+       // if less than 4 bytes, use byte by byte copying
+       SGTU    $4, R3, R6
+       BNE     R6, f_small_copy
+
+       // align destination to 4 bytes
+       AND     $3, R1, R6
+       BEQ     R6, f_dest_aligned
+       SUBU    R1, R0, R6
+       AND     $3, R6
+       MOVWHI  0(R2), R7
+       SUBU    R6, R3
+       MOVWLO  3(R2), R7
+       ADDU    R6, R2
+       MOVWHI  R7, 0(R1)
+       ADDU    R6, R1
+
+f_dest_aligned:
+       AND     $31, R3, R7
+       AND     $3, R3, R6
+       SUBU    R7, R5, R7      // end pointer for 32-byte chunks
+       SUBU    R6, R5, R6      // end pointer for 4-byte chunks
+
+       // if source is not aligned, use unaligned reads
+       AND     $3, R2, R8
+       BNE     R8, f_large_ua
+
+f_large:
+       BEQ     R1, R7, f_words
+       ADDU    $32, R1
+       MOVW    0(R2), R8
+       MOVW    4(R2), R9
+       MOVW    8(R2), R10
+       MOVW    12(R2), R11
+       MOVW    16(R2), R12
+       MOVW    20(R2), R13
+       MOVW    24(R2), R14
+       MOVW    28(R2), R15
+       ADDU    $32, R2
+       MOVW    R8, -32(R1)
+       MOVW    R9, -28(R1)
+       MOVW    R10, -24(R1)
+       MOVW    R11, -20(R1)
+       MOVW    R12, -16(R1)
+       MOVW    R13, -12(R1)
+       MOVW    R14, -8(R1)
+       MOVW    R15, -4(R1)
+       JMP     f_large
+
+f_words:
+       BEQ     R1, R6, f_tail
+       ADDU    $4, R1
+       MOVW    0(R2), R8
+       ADDU    $4, R2
+       MOVW    R8, -4(R1)
+       JMP     f_words
+
+f_tail:
+       BEQ     R1, R5, ret
+       MOVWLO  -1(R4), R8
+       MOVWLO  R8, -1(R5)
+
+ret:
+       RET
+
+f_large_ua:
+       BEQ     R1, R7, f_words_ua
+       ADDU    $32, R1
+       MOVWHI  0(R2), R8
+       MOVWHI  4(R2), R9
+       MOVWHI  8(R2), R10
+       MOVWHI  12(R2), R11
+       MOVWHI  16(R2), R12
+       MOVWHI  20(R2), R13
+       MOVWHI  24(R2), R14
+       MOVWHI  28(R2), R15
+       MOVWLO  3(R2), R8
+       MOVWLO  7(R2), R9
+       MOVWLO  11(R2), R10
+       MOVWLO  15(R2), R11
+       MOVWLO  19(R2), R12
+       MOVWLO  23(R2), R13
+       MOVWLO  27(R2), R14
+       MOVWLO  31(R2), R15
+       ADDU    $32, R2
+       MOVW    R8, -32(R1)
+       MOVW    R9, -28(R1)
+       MOVW    R10, -24(R1)
+       MOVW    R11, -20(R1)
+       MOVW    R12, -16(R1)
+       MOVW    R13, -12(R1)
+       MOVW    R14, -8(R1)
+       MOVW    R15, -4(R1)
+       JMP     f_large_ua
+
+f_words_ua:
+       BEQ     R1, R6, f_tail_ua
+       MOVWHI  0(R2), R8
+       ADDU    $4, R1
+       MOVWLO  3(R2), R8
+       ADDU    $4, R2
+       MOVW    R8, -4(R1)
+       JMP     f_words_ua
+
+f_tail_ua:
+       BEQ     R1, R5, ret
+       MOVWHI  -4(R4), R8
+       MOVWLO  -1(R4), R8
+       MOVWLO  R8, -1(R5)
+       JMP     ret
+
+f_small_copy:
+       BEQ     R1, R5, ret
+       ADDU    $1, R1
+       MOVB    0(R2), R6
+       ADDU    $1, R2
+       MOVB    R6, -1(R1)
+       JMP     f_small_copy
+
+backward:
+       SGTU    $4, R3, R6
+       BNE     R6, b_small_copy
+
+       AND     $3, R5, R6
+       BEQ     R6, b_dest_aligned
+       MOVWHI  -4(R4), R7
+       SUBU    R6, R3
+       MOVWLO  -1(R4), R7
+       SUBU    R6, R4
+       MOVWLO  R7, -1(R5)
+       SUBU    R6, R5
+
+b_dest_aligned:
+       AND     $31, R3, R7
+       AND     $3, R3, R6
+       ADDU    R7, R1, R7
+       ADDU    R6, R1, R6
+
+       AND     $3, R4, R8
+       BNE     R8, b_large_ua
+
+b_large:
+       BEQ     R5, R7, b_words
+       ADDU    $-32, R5
+       MOVW    -4(R4), R8
+       MOVW    -8(R4), R9
+       MOVW    -12(R4), R10
+       MOVW    -16(R4), R11
+       MOVW    -20(R4), R12
+       MOVW    -24(R4), R13
+       MOVW    -28(R4), R14
+       MOVW    -32(R4), R15
+       ADDU    $-32, R4
+       MOVW    R8, 28(R5)
+       MOVW    R9, 24(R5)
+       MOVW    R10, 20(R5)
+       MOVW    R11, 16(R5)
+       MOVW    R12, 12(R5)
+       MOVW    R13, 8(R5)
+       MOVW    R14, 4(R5)
+       MOVW    R15, 0(R5)
+       JMP     b_large
+
+b_words:
+       BEQ     R5, R6, b_tail
+       ADDU    $-4, R5
+       MOVW    -4(R4), R8
+       ADDU    $-4, R4
+       MOVW    R8, 0(R5)
+       JMP     b_words
+
+b_tail:
+       BEQ     R5, R1, ret
+       MOVWHI  0(R2), R8       // R2 and R1 have the same alignment so we don't need to load a whole word
+       MOVWHI  R8, 0(R1)
+       JMP     ret
+
+b_large_ua:
+       BEQ     R5, R7, b_words_ua
+       ADDU    $-32, R5
+       MOVWHI  -4(R4), R8
+       MOVWHI  -8(R4), R9
+       MOVWHI  -12(R4), R10
+       MOVWHI  -16(R4), R11
+       MOVWHI  -20(R4), R12
+       MOVWHI  -24(R4), R13
+       MOVWHI  -28(R4), R14
+       MOVWHI  -32(R4), R15
+       MOVWLO  -1(R4), R8
+       MOVWLO  -5(R4), R9
+       MOVWLO  -9(R4), R10
+       MOVWLO  -13(R4), R11
+       MOVWLO  -17(R4), R12
+       MOVWLO  -21(R4), R13
+       MOVWLO  -25(R4), R14
+       MOVWLO  -29(R4), R15
+       ADDU    $-32, R4
+       MOVW    R8, 28(R5)
+       MOVW    R9, 24(R5)
+       MOVW    R10, 20(R5)
+       MOVW    R11, 16(R5)
+       MOVW    R12, 12(R5)
+       MOVW    R13, 8(R5)
+       MOVW    R14, 4(R5)
+       MOVW    R15, 0(R5)
+       JMP     b_large_ua
+
+b_words_ua:
+       BEQ     R5, R6, b_tail_ua
+       MOVWHI  -4(R4), R8
+       ADDU    $-4, R5
+       MOVWLO  -1(R4), R8
+       ADDU    $-4, R4
+       MOVW    R8, 0(R5)
+       JMP     b_words_ua
+
+b_tail_ua:
+       BEQ     R5, R1, ret
+       MOVWHI  (R2), R8
+       MOVWLO  3(R2), R8
+       MOVWHI  R8, 0(R1)
+       JMP ret
+
+b_small_copy:
+       BEQ     R5, R1, ret
+       ADDU    $-1, R5
+       MOVB    -1(R4), R6
+       ADDU    $-1, R4
+       MOVB    R6, 0(R5)
+       JMP     b_small_copy
index 43d0093c3199c58fa05745860835110fc71b98e3..f672162eaeb4505f3b3cfafbeb871644bc3c3608 100644 (file)
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build !mips
+// +build !mipsle
 // +build !mips64
 // +build !mips64le
 // +build !s390x
index 1c690fed0a12701415b2a72354e2914af4235e7f..be2b71911baf83256b6b21a7d35076a935cd537d 100644 (file)
@@ -30,7 +30,7 @@ func cputicks() int64 {
 
 const (
        _SS_DISABLE  = 2
-       _NSIG        = 65
+       _NSIG        = 129
        _SI_USER     = 0
        _SIG_BLOCK   = 1
        _SIG_UNBLOCK = 2
diff --git a/src/runtime/os_linux_mipsx.go b/src/runtime/os_linux_mipsx.go
new file mode 100644 (file)
index 0000000..313da1b
--- /dev/null
@@ -0,0 +1,62 @@
+// 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 linux
+// +build mips mipsle
+
+package runtime
+
+var randomNumber uint32
+
+func archauxv(tag, val uintptr) {
+       switch tag {
+       case _AT_RANDOM:
+               // sysargs filled in startupRandomData, but that
+               // pointer may not be word aligned, so we must treat
+               // it as a byte array.
+               randomNumber = uint32(startupRandomData[4]) | uint32(startupRandomData[5])<<8 |
+                       uint32(startupRandomData[6])<<16 | uint32(startupRandomData[7])<<24
+       }
+}
+
+//go:nosplit
+func cputicks() int64 {
+       // Currently cputicks() is used in blocking profiler and to seed fastrand().
+       // nanotime() is a poor approximation of CPU ticks that is enough for the profiler.
+       // randomNumber provides better seeding of fastrand1.
+       return nanotime() + int64(randomNumber)
+}
+
+const (
+       _SS_DISABLE  = 2
+       _NSIG        = 128 + 1
+       _SI_USER     = 0
+       _SIG_BLOCK   = 1
+       _SIG_UNBLOCK = 2
+       _SIG_SETMASK = 3
+       _RLIMIT_AS   = 6
+)
+
+type sigset [4]uint32
+
+type rlimit struct {
+       rlim_cur uintptr
+       rlim_max uintptr
+}
+
+var sigset_all = sigset{^uint32(0), ^uint32(0), ^uint32(0), ^uint32(0)}
+
+//go:nosplit
+//go:nowritebarrierrec
+func sigaddset(mask *sigset, i int) {
+       (*mask)[(i-1)/32] |= 1 << ((uint32(i) - 1) & 31)
+}
+
+func sigdelset(mask *sigset, i int) {
+       (*mask)[(i-1)/32] &^= 1 << ((uint32(i) - 1) & 31)
+}
+
+func sigfillset(mask *[4]uint32) {
+       (*mask)[0], (*mask)[1], (*mask)[2], (*mask)[3] = ^uint32(0), ^uint32(0), ^uint32(0), ^uint32(0)
+}
index 3b0e34a3372d8e80356eda1290ab7763ea95dc99..5e9f03120d0927cc277e1a8065c2bfd49f528960 100644 (file)
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build !amd64,!arm,!arm64,!mips64,!mips64le,!s390x,!ppc64,!ppc64le
+// +build !amd64,!arm,!arm64,!mips,!mipsle,!mips64,!mips64le,!s390x,!ppc64,!ppc64le
 
 package runtime
 
diff --git a/src/runtime/rt0_linux_mipsx.s b/src/runtime/rt0_linux_mipsx.s
new file mode 100644 (file)
index 0000000..5e8c5c3
--- /dev/null
@@ -0,0 +1,27 @@
+// 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 linux
+// +build mips mipsle
+
+#include "textflag.h"
+
+TEXT _rt0_mips_linux(SB),NOSPLIT,$0
+       JMP     _main<>(SB)
+
+TEXT _rt0_mipsle_linux(SB),NOSPLIT,$0
+       JMP     _main<>(SB)
+
+TEXT _main<>(SB),NOSPLIT,$-4
+       // 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.
+       MOVW    0(R29), R1      // argc
+       ADD     $4, R29, R2     // argv
+       JMP     main(SB)
+
+TEXT main(SB),NOSPLIT,$-4
+       MOVW    $runtime·rt0_go(SB), R4
+       JMP     (R4)
diff --git a/src/runtime/signal_linux_mipsx.go b/src/runtime/signal_linux_mipsx.go
new file mode 100644 (file)
index 0000000..c88ac4d
--- /dev/null
@@ -0,0 +1,65 @@
+// 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 linux
+// +build mips mipsle
+
+package runtime
+
+import "unsafe"
+
+type sigctxt struct {
+       info *siginfo
+       ctxt unsafe.Pointer
+}
+
+func (c *sigctxt) regs() *sigcontext { return &(*ucontext)(c.ctxt).uc_mcontext }
+func (c *sigctxt) r0() uint32        { return uint32(c.regs().sc_regs[0]) }
+func (c *sigctxt) r1() uint32        { return uint32(c.regs().sc_regs[1]) }
+func (c *sigctxt) r2() uint32        { return uint32(c.regs().sc_regs[2]) }
+func (c *sigctxt) r3() uint32        { return uint32(c.regs().sc_regs[3]) }
+func (c *sigctxt) r4() uint32        { return uint32(c.regs().sc_regs[4]) }
+func (c *sigctxt) r5() uint32        { return uint32(c.regs().sc_regs[5]) }
+func (c *sigctxt) r6() uint32        { return uint32(c.regs().sc_regs[6]) }
+func (c *sigctxt) r7() uint32        { return uint32(c.regs().sc_regs[7]) }
+func (c *sigctxt) r8() uint32        { return uint32(c.regs().sc_regs[8]) }
+func (c *sigctxt) r9() uint32        { return uint32(c.regs().sc_regs[9]) }
+func (c *sigctxt) r10() uint32       { return uint32(c.regs().sc_regs[10]) }
+func (c *sigctxt) r11() uint32       { return uint32(c.regs().sc_regs[11]) }
+func (c *sigctxt) r12() uint32       { return uint32(c.regs().sc_regs[12]) }
+func (c *sigctxt) r13() uint32       { return uint32(c.regs().sc_regs[13]) }
+func (c *sigctxt) r14() uint32       { return uint32(c.regs().sc_regs[14]) }
+func (c *sigctxt) r15() uint32       { return uint32(c.regs().sc_regs[15]) }
+func (c *sigctxt) r16() uint32       { return uint32(c.regs().sc_regs[16]) }
+func (c *sigctxt) r17() uint32       { return uint32(c.regs().sc_regs[17]) }
+func (c *sigctxt) r18() uint32       { return uint32(c.regs().sc_regs[18]) }
+func (c *sigctxt) r19() uint32       { return uint32(c.regs().sc_regs[19]) }
+func (c *sigctxt) r20() uint32       { return uint32(c.regs().sc_regs[20]) }
+func (c *sigctxt) r21() uint32       { return uint32(c.regs().sc_regs[21]) }
+func (c *sigctxt) r22() uint32       { return uint32(c.regs().sc_regs[22]) }
+func (c *sigctxt) r23() uint32       { return uint32(c.regs().sc_regs[23]) }
+func (c *sigctxt) r24() uint32       { return uint32(c.regs().sc_regs[24]) }
+func (c *sigctxt) r25() uint32       { return uint32(c.regs().sc_regs[25]) }
+func (c *sigctxt) r26() uint32       { return uint32(c.regs().sc_regs[26]) }
+func (c *sigctxt) r27() uint32       { return uint32(c.regs().sc_regs[27]) }
+func (c *sigctxt) r28() uint32       { return uint32(c.regs().sc_regs[28]) }
+func (c *sigctxt) r29() uint32       { return uint32(c.regs().sc_regs[29]) }
+func (c *sigctxt) r30() uint32       { return uint32(c.regs().sc_regs[30]) }
+func (c *sigctxt) r31() uint32       { return uint32(c.regs().sc_regs[31]) }
+func (c *sigctxt) sp() uint32        { return uint32(c.regs().sc_regs[29]) }
+func (c *sigctxt) pc() uint32        { return uint32(c.regs().sc_pc) }
+func (c *sigctxt) link() uint32      { return uint32(c.regs().sc_regs[31]) }
+func (c *sigctxt) lo() uint32        { return uint32(c.regs().sc_mdlo) }
+func (c *sigctxt) hi() uint32        { return uint32(c.regs().sc_mdhi) }
+
+func (c *sigctxt) sigcode() uint32 { return uint32(c.info.si_code) }
+func (c *sigctxt) sigaddr() uint32 { return c.info.si_addr }
+
+func (c *sigctxt) set_r30(x uint32)  { c.regs().sc_regs[30] = uint64(x) }
+func (c *sigctxt) set_pc(x uint32)   { c.regs().sc_pc = uint64(x) }
+func (c *sigctxt) set_sp(x uint32)   { c.regs().sc_regs[29] = uint64(x) }
+func (c *sigctxt) set_link(x uint32) { c.regs().sc_regs[31] = uint64(x) }
+
+func (c *sigctxt) set_sigcode(x uint32) { c.info.si_code = int32(x) }
+func (c *sigctxt) set_sigaddr(x uint32) { c.info.si_addr = x }
diff --git a/src/runtime/signal_mipsx.go b/src/runtime/signal_mipsx.go
new file mode 100644 (file)
index 0000000..62df79c
--- /dev/null
@@ -0,0 +1,91 @@
+// 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 linux
+// +build mips mipsle
+
+package runtime
+
+import (
+       "runtime/internal/sys"
+       "unsafe"
+)
+
+func dumpregs(c *sigctxt) {
+       print("r0   ", hex(c.r0()), "\t")
+       print("r1   ", hex(c.r1()), "\n")
+       print("r2   ", hex(c.r2()), "\t")
+       print("r3   ", hex(c.r3()), "\n")
+       print("r4   ", hex(c.r4()), "\t")
+       print("r5   ", hex(c.r5()), "\n")
+       print("r6   ", hex(c.r6()), "\t")
+       print("r7   ", hex(c.r7()), "\n")
+       print("r8   ", hex(c.r8()), "\t")
+       print("r9   ", hex(c.r9()), "\n")
+       print("r10  ", hex(c.r10()), "\t")
+       print("r11  ", hex(c.r11()), "\n")
+       print("r12  ", hex(c.r12()), "\t")
+       print("r13  ", hex(c.r13()), "\n")
+       print("r14  ", hex(c.r14()), "\t")
+       print("r15  ", hex(c.r15()), "\n")
+       print("r16  ", hex(c.r16()), "\t")
+       print("r17  ", hex(c.r17()), "\n")
+       print("r18  ", hex(c.r18()), "\t")
+       print("r19  ", hex(c.r19()), "\n")
+       print("r20  ", hex(c.r20()), "\t")
+       print("r21  ", hex(c.r21()), "\n")
+       print("r22  ", hex(c.r22()), "\t")
+       print("r23  ", hex(c.r23()), "\n")
+       print("r24  ", hex(c.r24()), "\t")
+       print("r25  ", hex(c.r25()), "\n")
+       print("r26  ", hex(c.r26()), "\t")
+       print("r27  ", hex(c.r27()), "\n")
+       print("r28  ", hex(c.r28()), "\t")
+       print("r29  ", hex(c.r29()), "\n")
+       print("r30  ", hex(c.r30()), "\t")
+       print("r31  ", hex(c.r31()), "\n")
+       print("pc   ", hex(c.pc()), "\t")
+       print("link ", hex(c.link()), "\n")
+       print("lo   ", hex(c.lo()), "\t")
+       print("hi   ", hex(c.hi()), "\n")
+}
+
+func (c *sigctxt) sigpc() uintptr { return uintptr(c.pc()) }
+func (c *sigctxt) sigsp() uintptr { return uintptr(c.sp()) }
+func (c *sigctxt) siglr() uintptr { return uintptr(c.link()) }
+func (c *sigctxt) fault() uintptr { return uintptr(c.sigaddr()) }
+
+// preparePanic sets up the stack to look like a call to sigpanic.
+func (c *sigctxt) preparePanic(sig uint32, gp *g) {
+       // We arrange link, and pc to pretend the panicking
+       // function calls sigpanic directly.
+       // Always save LINK to stack so that panics in leaf
+       // functions are correctly handled. This smashes
+       // the stack frame but we're not going back there
+       // anyway.
+       sp := c.sp() - sys.MinFrameSize
+       c.set_sp(sp)
+       *(*uint32)(unsafe.Pointer(uintptr(sp))) = c.link()
+
+       pc := gp.sigpc
+
+       // If we don't recognize the PC as code
+       // but we do recognize the link register as code,
+       // then assume this was a call to non-code and treat like
+       // pc == 0, to make unwinding show the context.
+       if pc != 0 && findfunc(pc) == nil && findfunc(uintptr(c.link())) != nil {
+               pc = 0
+       }
+
+       // Don't bother saving PC if it's zero, which is
+       // probably a call to a nil func: the old link register
+       // is more useful in the stack trace.
+       if pc != 0 {
+               c.set_link(uint32(pc))
+       }
+
+       // In case we are panicking from external C code
+       c.set_r30(uint32(uintptr(unsafe.Pointer(gp))))
+       c.set_pc(uint32(funcPC(sigpanic)))
+}
index ea36bf3645254c4f76b7a1b6e7aee97ec05cc262..874148e1d25913c053d35955f6a45c001ab895a1 100644 (file)
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
+// +build !mips
+// +build !mipsle
 // +build !mips64
 // +build !mips64le
 // +build linux
diff --git a/src/runtime/sigtab_linux_mips64x.go b/src/runtime/sigtab_linux_mips64x.go
deleted file mode 100644 (file)
index 201fe3d..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-// 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
-// +build linux
-
-package runtime
-
-type sigTabT struct {
-       flags int32
-       name  string
-}
-
-var sigtable = [...]sigTabT{
-       /* 0 */ {0, "SIGNONE: no trap"},
-       /* 1 */ {_SigNotify + _SigKill, "SIGHUP: terminal line hangup"},
-       /* 2 */ {_SigNotify + _SigKill, "SIGINT: interrupt"},
-       /* 3 */ {_SigNotify + _SigThrow, "SIGQUIT: quit"},
-       /* 4 */ {_SigThrow + _SigUnblock, "SIGILL: illegal instruction"},
-       /* 5 */ {_SigThrow + _SigUnblock, "SIGTRAP: trace trap"},
-       /* 6 */ {_SigNotify + _SigThrow, "SIGABRT: abort"},
-       /* 7 */ {_SigThrow, "SIGEMT"},
-       /* 8 */ {_SigPanic + _SigUnblock, "SIGFPE: floating-point exception"},
-       /* 9 */ {0, "SIGKILL: kill"},
-       /* 10 */ {_SigPanic + _SigUnblock, "SIGBUS: bus error"},
-       /* 11 */ {_SigPanic + _SigUnblock, "SIGSEGV: segmentation violation"},
-       /* 12 */ {_SigThrow, "SIGSYS: bad system call"},
-       /* 13 */ {_SigNotify, "SIGPIPE: write to broken pipe"},
-       /* 14 */ {_SigNotify, "SIGALRM: alarm clock"},
-       /* 15 */ {_SigNotify + _SigKill, "SIGTERM: termination"},
-       /* 16 */ {_SigNotify, "SIGUSR1: user-defined signal 1"},
-       /* 17 */ {_SigNotify, "SIGUSR2: user-defined signal 2"},
-       /* 18 */ {_SigNotify + _SigUnblock, "SIGCHLD: child status has changed"},
-       /* 19 */ {_SigNotify, "SIGPWR: power failure restart"},
-       /* 20 */ {_SigNotify, "SIGWINCH: window size change"},
-       /* 21 */ {_SigNotify, "SIGURG: urgent condition on socket"},
-       /* 22 */ {_SigNotify, "SIGIO: i/o now possible"},
-       /* 23 */ {0, "SIGSTOP: stop, unblockable"},
-       /* 24 */ {_SigNotify + _SigDefault, "SIGTSTP: keyboard stop"},
-       /* 25 */ {_SigNotify + _SigDefault, "SIGCONT: continue"},
-       /* 26 */ {_SigNotify + _SigDefault, "SIGTTIN: background read from tty"},
-       /* 27 */ {_SigNotify + _SigDefault, "SIGTTOU: background write to tty"},
-       /* 28 */ {_SigNotify, "SIGVTALRM: virtual alarm clock"},
-       /* 29 */ {_SigNotify + _SigUnblock, "SIGPROF: profiling alarm clock"},
-       /* 30 */ {_SigNotify, "SIGXCPU: cpu limit exceeded"},
-       /* 31 */ {_SigNotify, "SIGXFSZ: file size limit exceeded"},
-       /* 32 */ {_SigSetStack + _SigUnblock, "signal 32"}, /* SIGCANCEL; see issue 6997 */
-       /* 33 */ {_SigSetStack + _SigUnblock, "signal 33"}, /* SIGSETXID; see issues 3871, 9400, 12498 */
-       /* 34 */ {_SigNotify, "signal 34"},
-       /* 35 */ {_SigNotify, "signal 35"},
-       /* 36 */ {_SigNotify, "signal 36"},
-       /* 37 */ {_SigNotify, "signal 37"},
-       /* 38 */ {_SigNotify, "signal 38"},
-       /* 39 */ {_SigNotify, "signal 39"},
-       /* 40 */ {_SigNotify, "signal 40"},
-       /* 41 */ {_SigNotify, "signal 41"},
-       /* 42 */ {_SigNotify, "signal 42"},
-       /* 43 */ {_SigNotify, "signal 43"},
-       /* 44 */ {_SigNotify, "signal 44"},
-       /* 45 */ {_SigNotify, "signal 45"},
-       /* 46 */ {_SigNotify, "signal 46"},
-       /* 47 */ {_SigNotify, "signal 47"},
-       /* 48 */ {_SigNotify, "signal 48"},
-       /* 49 */ {_SigNotify, "signal 49"},
-       /* 50 */ {_SigNotify, "signal 50"},
-       /* 51 */ {_SigNotify, "signal 51"},
-       /* 52 */ {_SigNotify, "signal 52"},
-       /* 53 */ {_SigNotify, "signal 53"},
-       /* 54 */ {_SigNotify, "signal 54"},
-       /* 55 */ {_SigNotify, "signal 55"},
-       /* 56 */ {_SigNotify, "signal 56"},
-       /* 57 */ {_SigNotify, "signal 57"},
-       /* 58 */ {_SigNotify, "signal 58"},
-       /* 59 */ {_SigNotify, "signal 59"},
-       /* 60 */ {_SigNotify, "signal 60"},
-       /* 61 */ {_SigNotify, "signal 61"},
-       /* 62 */ {_SigNotify, "signal 62"},
-       /* 63 */ {_SigNotify, "signal 63"},
-       /* 64 */ {_SigNotify, "signal 64"},
-}
diff --git a/src/runtime/sigtab_linux_mipsx.go b/src/runtime/sigtab_linux_mipsx.go
new file mode 100644 (file)
index 0000000..8d9fb06
--- /dev/null
@@ -0,0 +1,145 @@
+// 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 mips mipsle mips64 mips64le
+// +build linux
+
+package runtime
+
+type sigTabT struct {
+       flags int32
+       name  string
+}
+
+var sigtable = [...]sigTabT{
+       /*  0 */ {0, "SIGNONE: no trap"},
+       /*  1 */ {_SigNotify + _SigKill, "SIGHUP: terminal line hangup"},
+       /*  2 */ {_SigNotify + _SigKill, "SIGINT: interrupt"},
+       /*  3 */ {_SigNotify + _SigThrow, "SIGQUIT: quit"},
+       /*  4 */ {_SigThrow + _SigUnblock, "SIGILL: illegal instruction"},
+       /*  5 */ {_SigThrow + _SigUnblock, "SIGTRAP: trace trap"},
+       /*  6 */ {_SigNotify + _SigThrow, "SIGABRT: abort"},
+       /*  7 */ {_SigThrow, "SIGEMT"},
+       /*  8 */ {_SigPanic + _SigUnblock, "SIGFPE: floating-point exception"},
+       /*  9 */ {0, "SIGKILL: kill"},
+       /*  10 */ {_SigPanic + _SigUnblock, "SIGBUS: bus error"},
+       /*  11 */ {_SigPanic + _SigUnblock, "SIGSEGV: segmentation violation"},
+       /*  12 */ {_SigThrow, "SIGSYS: bad system call"},
+       /*  13 */ {_SigNotify, "SIGPIPE: write to broken pipe"},
+       /*  14 */ {_SigNotify, "SIGALRM: alarm clock"},
+       /*  15 */ {_SigNotify + _SigKill, "SIGTERM: termination"},
+       /*  16 */ {_SigNotify, "SIGUSR1: user-defined signal 1"},
+       /*  17 */ {_SigNotify, "SIGUSR2: user-defined signal 2"},
+       /*  18 */ {_SigNotify + _SigUnblock, "SIGCHLD: child status has changed"},
+       /*  19 */ {_SigNotify, "SIGPWR: power failure restart"},
+       /*  20 */ {_SigNotify, "SIGWINCH: window size change"},
+       /*  21 */ {_SigNotify, "SIGURG: urgent condition on socket"},
+       /*  22 */ {_SigNotify, "SIGIO: i/o now possible"},
+       /*  23 */ {0, "SIGSTOP: stop, unblockable"},
+       /*  24 */ {_SigNotify + _SigDefault, "SIGTSTP: keyboard stop"},
+       /*  25 */ {_SigNotify + _SigDefault, "SIGCONT: continue"},
+       /*  26 */ {_SigNotify + _SigDefault, "SIGTTIN: background read from tty"},
+       /*  27 */ {_SigNotify + _SigDefault, "SIGTTOU: background write to tty"},
+       /*  28 */ {_SigNotify, "SIGVTALRM: virtual alarm clock"},
+       /*  29 */ {_SigNotify + _SigUnblock, "SIGPROF: profiling alarm clock"},
+       /*  30 */ {_SigNotify, "SIGXCPU: cpu limit exceeded"},
+       /*  31 */ {_SigNotify, "SIGXFSZ: file size limit exceeded"},
+       /*  32 */ {_SigSetStack + _SigUnblock, "signal 32"}, /* SIGCANCEL; see issue 6997 */
+       /*  33 */ {_SigSetStack + _SigUnblock, "signal 33"}, /* SIGSETXID; see issues 3871, 9400, 12498 */
+       /*  34 */ {_SigNotify, "signal 34"},
+       /*  35 */ {_SigNotify, "signal 35"},
+       /*  36 */ {_SigNotify, "signal 36"},
+       /*  37 */ {_SigNotify, "signal 37"},
+       /*  38 */ {_SigNotify, "signal 38"},
+       /*  39 */ {_SigNotify, "signal 39"},
+       /*  40 */ {_SigNotify, "signal 40"},
+       /*  41 */ {_SigNotify, "signal 41"},
+       /*  42 */ {_SigNotify, "signal 42"},
+       /*  43 */ {_SigNotify, "signal 43"},
+       /*  44 */ {_SigNotify, "signal 44"},
+       /*  45 */ {_SigNotify, "signal 45"},
+       /*  46 */ {_SigNotify, "signal 46"},
+       /*  47 */ {_SigNotify, "signal 47"},
+       /*  48 */ {_SigNotify, "signal 48"},
+       /*  49 */ {_SigNotify, "signal 49"},
+       /*  50 */ {_SigNotify, "signal 50"},
+       /*  51 */ {_SigNotify, "signal 51"},
+       /*  52 */ {_SigNotify, "signal 52"},
+       /*  53 */ {_SigNotify, "signal 53"},
+       /*  54 */ {_SigNotify, "signal 54"},
+       /*  55 */ {_SigNotify, "signal 55"},
+       /*  56 */ {_SigNotify, "signal 56"},
+       /*  57 */ {_SigNotify, "signal 57"},
+       /*  58 */ {_SigNotify, "signal 58"},
+       /*  59 */ {_SigNotify, "signal 59"},
+       /*  60 */ {_SigNotify, "signal 60"},
+       /*  61 */ {_SigNotify, "signal 61"},
+       /*  62 */ {_SigNotify, "signal 62"},
+       /*  63 */ {_SigNotify, "signal 63"},
+       /*  64 */ {_SigNotify, "signal 64"},
+       /*  65 */ {_SigNotify, "signal 65"},
+       /*  66 */ {_SigNotify, "signal 66"},
+       /*  67 */ {_SigNotify, "signal 67"},
+       /*  68 */ {_SigNotify, "signal 68"},
+       /*  69 */ {_SigNotify, "signal 69"},
+       /*  70 */ {_SigNotify, "signal 70"},
+       /*  71 */ {_SigNotify, "signal 71"},
+       /*  72 */ {_SigNotify, "signal 72"},
+       /*  73 */ {_SigNotify, "signal 73"},
+       /*  74 */ {_SigNotify, "signal 74"},
+       /*  75 */ {_SigNotify, "signal 75"},
+       /*  76 */ {_SigNotify, "signal 76"},
+       /*  77 */ {_SigNotify, "signal 77"},
+       /*  78 */ {_SigNotify, "signal 78"},
+       /*  79 */ {_SigNotify, "signal 79"},
+       /*  80 */ {_SigNotify, "signal 80"},
+       /*  81 */ {_SigNotify, "signal 81"},
+       /*  82 */ {_SigNotify, "signal 82"},
+       /*  83 */ {_SigNotify, "signal 83"},
+       /*  84 */ {_SigNotify, "signal 84"},
+       /*  85 */ {_SigNotify, "signal 85"},
+       /*  86 */ {_SigNotify, "signal 86"},
+       /*  87 */ {_SigNotify, "signal 87"},
+       /*  88 */ {_SigNotify, "signal 88"},
+       /*  89 */ {_SigNotify, "signal 89"},
+       /*  90 */ {_SigNotify, "signal 90"},
+       /*  91 */ {_SigNotify, "signal 91"},
+       /*  92 */ {_SigNotify, "signal 92"},
+       /*  93 */ {_SigNotify, "signal 93"},
+       /*  94 */ {_SigNotify, "signal 94"},
+       /*  95 */ {_SigNotify, "signal 95"},
+       /*  96 */ {_SigNotify, "signal 96"},
+       /*  97 */ {_SigNotify, "signal 97"},
+       /*  98 */ {_SigNotify, "signal 98"},
+       /*  99 */ {_SigNotify, "signal 99"},
+       /* 100 */ {_SigNotify, "signal 100"},
+       /* 101 */ {_SigNotify, "signal 101"},
+       /* 102 */ {_SigNotify, "signal 102"},
+       /* 103 */ {_SigNotify, "signal 103"},
+       /* 104 */ {_SigNotify, "signal 104"},
+       /* 105 */ {_SigNotify, "signal 105"},
+       /* 106 */ {_SigNotify, "signal 106"},
+       /* 107 */ {_SigNotify, "signal 107"},
+       /* 108 */ {_SigNotify, "signal 108"},
+       /* 109 */ {_SigNotify, "signal 109"},
+       /* 110 */ {_SigNotify, "signal 110"},
+       /* 111 */ {_SigNotify, "signal 111"},
+       /* 112 */ {_SigNotify, "signal 112"},
+       /* 113 */ {_SigNotify, "signal 113"},
+       /* 114 */ {_SigNotify, "signal 114"},
+       /* 115 */ {_SigNotify, "signal 115"},
+       /* 116 */ {_SigNotify, "signal 116"},
+       /* 117 */ {_SigNotify, "signal 117"},
+       /* 118 */ {_SigNotify, "signal 118"},
+       /* 119 */ {_SigNotify, "signal 119"},
+       /* 120 */ {_SigNotify, "signal 120"},
+       /* 121 */ {_SigNotify, "signal 121"},
+       /* 122 */ {_SigNotify, "signal 122"},
+       /* 123 */ {_SigNotify, "signal 123"},
+       /* 124 */ {_SigNotify, "signal 124"},
+       /* 125 */ {_SigNotify, "signal 125"},
+       /* 126 */ {_SigNotify, "signal 126"},
+       /* 127 */ {_SigNotify, "signal 127"},
+       /* 128 */ {_SigNotify, "signal 128"},
+}
index cd442e92dc91621563af8e67b03c01efbea4aa06..149560fd931945203fb18219ffd98bd22674c6e1 100644 (file)
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build 386 arm amd64p32
+// +build 386 arm amd64p32 mips mipsle
 
 package runtime
 
diff --git a/src/runtime/sys_linux_mipsx.s b/src/runtime/sys_linux_mipsx.s
new file mode 100644 (file)
index 0000000..6f089f5
--- /dev/null
@@ -0,0 +1,467 @@
+// 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 linux
+// +build mips mipsle
+
+//
+// System calls and other sys.stuff for mips, Linux
+//
+
+#include "go_asm.h"
+#include "go_tls.h"
+#include "textflag.h"
+
+#define SYS_exit                       4001
+#define SYS_read                       4003
+#define SYS_write                      4004
+#define SYS_open                       4005
+#define SYS_close                      4006
+#define SYS_getpid                     4020
+#define SYS_kill                       4037
+#define SYS_fcntl                      4055
+#define SYS_gettimeofday           4078
+#define SYS_mmap                       4090
+#define SYS_munmap                     4091
+#define SYS_setitimer              4104
+#define SYS_clone                      4120
+#define SYS_newselect              4142
+#define SYS_sched_yield                    4162
+#define SYS_rt_sigreturn           4193
+#define SYS_rt_sigaction           4194
+#define SYS_rt_sigprocmask             4195
+#define SYS_sigaltstack                    4206
+#define SYS_getrlimit              4076
+#define SYS_madvise                    4218
+#define SYS_mincore                    4217
+#define SYS_gettid                     4222
+#define SYS_tkill                      4236
+#define SYS_futex                      4238
+#define SYS_sched_getaffinity  4240
+#define SYS_exit_group             4246
+#define SYS_epoll_create           4248
+#define SYS_epoll_ctl              4249
+#define SYS_epoll_wait             4250
+#define SYS_clock_gettime          4263
+#define SYS_epoll_create1          4326
+
+TEXT runtime·exit(SB),NOSPLIT,$0-4
+       MOVW    code+0(FP), R4
+       MOVW    $SYS_exit_group, R2
+       SYSCALL
+       UNDEF
+       RET
+
+TEXT runtime·exit1(SB),NOSPLIT,$0-4
+       MOVW    code+0(FP), R4
+       MOVW    $SYS_exit, R2
+       SYSCALL
+       UNDEF
+       RET
+
+TEXT runtime·open(SB),NOSPLIT,$0-16
+       MOVW    name+0(FP), R4
+       MOVW    mode+4(FP), R5
+       MOVW    perm+8(FP), R6
+       MOVW    $SYS_open, R2
+       SYSCALL
+       BEQ     R7, 2(PC)
+       MOVW    $-1, R2
+       MOVW    R2, ret+12(FP)
+       RET
+
+TEXT runtime·closefd(SB),NOSPLIT,$0-8
+       MOVW    fd+0(FP), R4
+       MOVW    $SYS_close, R2
+       SYSCALL
+       BEQ     R7, 2(PC)
+       MOVW    $-1, R2
+       MOVW    R2, ret+4(FP)
+       RET
+
+TEXT runtime·write(SB),NOSPLIT,$0-16
+       MOVW    fd+0(FP), R4
+       MOVW    p+4(FP), R5
+       MOVW    n+8(FP), R6
+       MOVW    $SYS_write, R2
+       SYSCALL
+       BEQ     R7, 2(PC)
+       MOVW    $-1, R2
+       MOVW    R2, ret+12(FP)
+       RET
+
+TEXT runtime·read(SB),NOSPLIT,$0-16
+       MOVW    fd+0(FP), R4
+       MOVW    p+4(FP), R5
+       MOVW    n+8(FP), R6
+       MOVW    $SYS_read, R2
+       SYSCALL
+       BEQ     R7, 2(PC)
+       MOVW    $-1, R2
+       MOVW    R2, ret+12(FP)
+       RET
+
+TEXT runtime·getrlimit(SB),NOSPLIT,$0-12
+       MOVW    kind+0(FP), R4
+       MOVW    limit+4(FP), R5
+       MOVW    $SYS_getrlimit, R2
+       SYSCALL
+       MOVW    R2, ret+8(FP)
+       RET
+
+TEXT runtime·usleep(SB),NOSPLIT,$28-4
+       MOVW    usec+0(FP), R3
+       MOVW    R3, R5
+       MOVW    $1000000, R4
+       DIVU    R4, R3
+       MOVW    LO, R3
+       MOVW    R3, 24(R29)
+       MULU    R3, R4
+       MOVW    LO, R4
+       SUBU    R4, R5
+       MOVW    R5, 28(R29)
+
+       // select(0, 0, 0, 0, &tv)
+       MOVW    $0, R4
+       MOVW    $0, R5
+       MOVW    $0, R6
+       MOVW    $0, R7
+       ADDU    $24, R29, R8
+       MOVW    R8, 16(R29)
+       MOVW    $SYS_newselect, R2
+       SYSCALL
+       RET
+
+TEXT runtime·gettid(SB),NOSPLIT,$0-4
+       MOVW    $SYS_gettid, R2
+       SYSCALL
+       MOVW    R2, ret+0(FP)
+       RET
+
+TEXT runtime·raise(SB),NOSPLIT,$0-4
+       MOVW    $SYS_gettid, R2
+       SYSCALL
+       MOVW    R2, R4  // arg 1 tid
+       MOVW    sig+0(FP), R5   // arg 2
+       MOVW    $SYS_tkill, R2
+       SYSCALL
+       RET
+
+TEXT runtime·raiseproc(SB),NOSPLIT,$0
+       MOVW    $SYS_getpid, R2
+       SYSCALL
+       MOVW    R2, R4  // arg 1 pid
+       MOVW    sig+0(FP), R5   // arg 2
+       MOVW    $SYS_kill, R2
+       SYSCALL
+       RET
+
+TEXT runtime·setitimer(SB),NOSPLIT,$0-12
+       MOVW    mode+0(FP), R4
+       MOVW    new+4(FP), R5
+       MOVW    old+8(FP), R6
+       MOVW    $SYS_setitimer, R2
+       SYSCALL
+       RET
+
+TEXT runtime·mincore(SB),NOSPLIT,$0-16
+       MOVW    addr+0(FP), R4
+       MOVW    n+4(FP), R5
+       MOVW    dst+8(FP), R6
+       MOVW    $SYS_mincore, R2
+       SYSCALL
+       SUBU    R2, R0, R2      // caller expects negative errno
+       MOVW    R2, ret+12(FP)
+       RET
+
+// func now() (sec int64, nsec int32)
+TEXT time·now(SB),NOSPLIT,$8-12
+       MOVW    $0, R4  // CLOCK_REALTIME
+       MOVW    $4(R29), R5
+       MOVW    $SYS_clock_gettime, R2
+       SYSCALL
+       MOVW    4(R29), R3      // sec
+       MOVW    8(R29), R5      // nsec
+#ifdef GOARCH_mips
+       MOVW    R3, sec_lo+4(FP)
+       MOVW    R0, sec_hi+0(FP)
+#else
+       MOVW    R3, sec_lo+0(FP)
+       MOVW    R0, sec_hi+4(FP)
+#endif
+       MOVW    R5, nsec+8(FP)
+       RET
+
+TEXT runtime·nanotime(SB),NOSPLIT,$8-8
+       MOVW    $1, R4  // CLOCK_MONOTONIC
+       MOVW    $4(R29), R5
+       MOVW    $SYS_clock_gettime, R2
+       SYSCALL
+       MOVW    4(R29), R3      // sec
+       MOVW    8(R29), R5      // nsec
+       // sec is in R3, nsec in R5
+       // return nsec in R3
+       MOVW    $1000000000, R4
+       MULU    R4, R3
+       MOVW    LO, R3
+       ADDU    R5, R3
+       SGTU    R5, R3, R4
+#ifdef GOARCH_mips
+       MOVW    R3, ret_lo+4(FP)
+#else
+       MOVW    R3, ret_lo+0(FP)
+#endif
+       MOVW    HI, R3
+       ADDU    R4, R3
+#ifdef GOARCH_mips
+       MOVW    R3, ret_hi+0(FP)
+#else
+       MOVW    R3, ret_hi+4(FP)
+#endif
+       RET
+
+TEXT runtime·rtsigprocmask(SB),NOSPLIT,$0-16
+       MOVW    how+0(FP), R4
+       MOVW    new+4(FP), R5
+       MOVW    old+8(FP), R6
+       MOVW    size+12(FP), R7
+       MOVW    $SYS_rt_sigprocmask, R2
+       SYSCALL
+       BEQ     R7, 2(PC)
+       UNDEF   // crash
+       RET
+
+TEXT runtime·rt_sigaction(SB),NOSPLIT,$0-20
+       MOVW    sig+0(FP), R4
+       MOVW    new+4(FP), R5
+       MOVW    old+8(FP), R6
+       MOVW    size+12(FP), R7
+       MOVW    $SYS_rt_sigaction, R2
+       SYSCALL
+       MOVW    R2, ret+16(FP)
+       RET
+
+TEXT runtime·sigfwd(SB),NOSPLIT,$0-16
+       MOVW    sig+4(FP), R4
+       MOVW    info+8(FP), R5
+       MOVW    ctx+12(FP), R6
+       MOVW    fn+0(FP), R25
+       MOVW    R29, R22
+       SUBU    $16, R29
+       AND     $0x7, R29       // shadow space for 4 args aligned to 8 bytes as per O32 ABI
+       JAL     (R25)
+       MOVW    R22, R29
+       RET
+
+TEXT runtime·sigtramp(SB),NOSPLIT,$12
+       // 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, 4(R29)
+       MOVW    R5, 8(R29)
+       MOVW    R6, 12(R29)
+       MOVW    $runtime·sigtrampgo(SB), R1
+       JAL     (R1)
+       RET
+
+TEXT runtime·cgoSigtramp(SB),NOSPLIT,$0
+       JMP     runtime·sigtramp(SB)
+
+TEXT runtime·mmap(SB),NOSPLIT,$20-28
+       MOVW    addr+0(FP), R4
+       MOVW    n+4(FP), R5
+       MOVW    prot+8(FP), R6
+       MOVW    flags+12(FP), R7
+       MOVW    fd+16(FP), R8
+       MOVW    off+20(FP), R9
+       MOVW    R8, 16(R29)
+       MOVW    R9, 20(R29)
+
+       MOVW    $SYS_mmap, R2
+       SYSCALL
+       MOVW    R2, ret+24(FP)
+       RET
+
+TEXT runtime·munmap(SB),NOSPLIT,$0-8
+       MOVW    addr+0(FP), R4
+       MOVW    n+4(FP), R5
+       MOVW    $SYS_munmap, R2
+       SYSCALL
+       BEQ     R7, 2(PC)
+       UNDEF   // crash
+       RET
+
+TEXT runtime·madvise(SB),NOSPLIT,$0-12
+       MOVW    addr+0(FP), R4
+       MOVW    n+4(FP), R5
+       MOVW    flags+8(FP), R6
+       MOVW    $SYS_madvise, R2
+       SYSCALL
+       // ignore failure - maybe pages are locked
+       RET
+
+// int32 futex(int32 *uaddr, int32 op, int32 val, struct timespec *timeout, int32 *uaddr2, int32 val2);
+TEXT runtime·futex(SB),NOSPLIT,$20-28
+       MOVW    addr+0(FP), R4
+       MOVW    op+4(FP), R5
+       MOVW    val+8(FP), R6
+       MOVW    ts+12(FP), R7
+
+       MOVW    addr2+16(FP), R8
+       MOVW    val3+20(FP), R9
+
+       MOVW    R8, 16(R29)
+       MOVW    R9, 20(R29)
+
+       MOVW    $SYS_futex, R2
+       SYSCALL
+       MOVW    R2, ret+24(FP)
+       RET
+
+
+// int32 clone(int32 flags, void *stk, M *mm, G *gg, void (*fn)(void));
+TEXT runtime·clone(SB),NOSPLIT,$-4-24
+       MOVW    flags+0(FP), R4
+       MOVW    stk+4(FP), R5
+       MOVW    R0, R6  // ptid
+       MOVW    R0, R7  // tls
+
+       // O32 syscall handler unconditionally copies arguments 5-8 from stack,
+       // even for syscalls with less than 8 arguments. Reserve 32 bytes of new
+       // stack so that any syscall invoked immediately in the new thread won't fail.
+       ADD     $-32, R5
+
+       // Copy mm, gg, fn off parent stack for use by child.
+       MOVW    mm+8(FP), R16
+       MOVW    gg+12(FP), R17
+       MOVW    fn+16(FP), R18
+
+       MOVW    $1234, R1
+
+       MOVW    R16, 0(R5)
+       MOVW    R17, 4(R5)
+       MOVW    R18, 8(R5)
+
+       MOVW    R1, 12(R5)
+
+       MOVW    $SYS_clone, R2
+       SYSCALL
+
+       // In parent, return.
+       BEQ     R2, 5(PC)
+       SUBU    R2, R0, R3
+       CMOVN   R7, R3, R2
+       MOVW    R2, ret+20(FP)
+       RET
+
+       // In child, on new stack.
+       // Check that SP is as we expect
+       MOVW    12(R29), R16
+       MOVW    $1234, R1
+       BEQ     R16, R1, 2(PC)
+       MOVW    (R0), R0
+
+       // Initialize m->procid to Linux tid
+       MOVW    $SYS_gettid, R2
+       SYSCALL
+
+       MOVW    0(R29), R16     // m
+       MOVW    4(R29), R17     // g
+       MOVW    8(R29), R18     // fn
+
+       BEQ     R16, nog
+       BEQ     R17, nog
+
+       MOVW    R2, m_procid(R16)
+
+       // In child, set up new stack
+       MOVW    R16, g_m(R17)
+       MOVW    R17, g
+
+// TODO(mips32): doesn't have runtime·stackcheck(SB)
+
+nog:
+       // Call fn
+       ADDU    $32, R29
+       JAL     (R18)
+
+       // It shouldn't return.  If it does, exit that thread.
+       ADDU    $-32, R29
+       MOVW    $0xf4, R4
+       MOVW    $SYS_exit, R2
+       SYSCALL
+       UNDEF
+
+TEXT runtime·sigaltstack(SB),NOSPLIT,$0
+       MOVW    new+0(FP), R4
+       MOVW    old+4(FP), R5
+       MOVW    $SYS_sigaltstack, R2
+       SYSCALL
+       BEQ     R7, 2(PC)
+       UNDEF   // crash
+       RET
+
+TEXT runtime·osyield(SB),NOSPLIT,$0
+       MOVW    $SYS_sched_yield, R2
+       SYSCALL
+       RET
+
+TEXT runtime·sched_getaffinity(SB),NOSPLIT,$0-16
+       MOVW    pid+0(FP), R4
+       MOVW    len+4(FP), R5
+       MOVW    buf+8(FP), R6
+       MOVW    $SYS_sched_getaffinity, R2
+       SYSCALL
+       MOVW    R2, ret+12(FP)
+       RET
+
+// int32 runtime·epollcreate(int32 size);
+TEXT runtime·epollcreate(SB),NOSPLIT,$0-8
+       MOVW    size+0(FP), R4
+       MOVW    $SYS_epoll_create, R2
+       SYSCALL
+       MOVW    R2, ret+4(FP)
+       RET
+
+// int32 runtime·epollcreate1(int32 flags);
+TEXT runtime·epollcreate1(SB),NOSPLIT,$0-8
+       MOVW    flags+0(FP), R4
+       MOVW    $SYS_epoll_create1, R2
+       SYSCALL
+       MOVW    R2, ret+4(FP)
+       RET
+
+// func epollctl(epfd, op, fd int32, ev *epollEvent) int
+TEXT runtime·epollctl(SB),NOSPLIT,$0-20
+       MOVW    epfd+0(FP), R4
+       MOVW    op+4(FP), R5
+       MOVW    fd+8(FP), R6
+       MOVW    ev+12(FP), R7
+       MOVW    $SYS_epoll_ctl, R2
+       SYSCALL
+       MOVW    R2, ret+16(FP)
+       RET
+
+// int32 runtime·epollwait(int32 epfd, EpollEvent *ev, int32 nev, int32 timeout);
+TEXT runtime·epollwait(SB),NOSPLIT,$0-20
+       MOVW    epfd+0(FP), R4
+       MOVW    ev+4(FP), R5
+       MOVW    nev+8(FP), R6
+       MOVW    timeout+12(FP), R7
+       MOVW    $SYS_epoll_wait, R2
+       SYSCALL
+       MOVW    R2, ret+16(FP)
+       RET
+
+// void runtime·closeonexec(int32 fd);
+TEXT runtime·closeonexec(SB),NOSPLIT,$0-4
+       MOVW    fd+0(FP), R4    // fd
+       MOVW    $2, R5  // F_SETFD
+       MOVW    $1, R6  // FD_CLOEXEC
+       MOVW    $SYS_fcntl, R2
+       SYSCALL
+       RET
diff --git a/src/runtime/sys_mipsx.go b/src/runtime/sys_mipsx.go
new file mode 100644 (file)
index 0000000..2819218
--- /dev/null
@@ -0,0 +1,20 @@
+// 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 mips mipsle
+
+package runtime
+
+import "unsafe"
+
+// adjust Gobuf as if it executed a call to fn with context ctxt
+// and then did an immediate Gosave.
+func gostartcall(buf *gobuf, fn, ctxt unsafe.Pointer) {
+       if buf.lr != 0 {
+               throw("invalid use of gostartcall")
+       }
+       buf.lr = buf.pc
+       buf.pc = uintptr(fn)
+       buf.ctxt = ctxt
+}
diff --git a/src/runtime/tls_mipsx.s b/src/runtime/tls_mipsx.s
new file mode 100644 (file)
index 0000000..95fbc32
--- /dev/null
@@ -0,0 +1,21 @@
+// 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 mips mipsle
+
+#include "go_asm.h"
+#include "go_tls.h"
+#include "funcdata.h"
+#include "textflag.h"
+
+// If !iscgo, this is a no-op.
+TEXT runtime·save_g(SB),NOSPLIT,$-4-0
+       MOVB    runtime·iscgo(SB), R23
+       BEQ     R23, nocgo
+       UNDEF
+nocgo:
+       RET
+
+TEXT runtime·load_g(SB),NOSPLIT,$-4-0
+       RET
index fed3cca1fdd51b759e2e26696d7a4ba48cbb2f0f..28b61192c49657bc6f9f4d39796e5bb5d87d2038 100644 (file)
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build arm mips64 mips64le
+// +build arm mips mipsle mips64 mips64le
 
 package runtime
 
index f60457d084b18bb08512d86b4e1564d4afe60f9a..d63da9c8908b2f6ee3169b6b6aea3bc1d8adafa7 100644 (file)
@@ -23,7 +23,7 @@
 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 // THE SOFTWARE.
 
-// +build arm 386
+// +build arm 386 mips mipsle
 
 package runtime
 
@@ -198,6 +198,11 @@ func dodiv(n, d uint64) (q, r uint64) {
                return slowdodiv(n, d)
        }
 
+       if GOARCH == "mips" || GOARCH == "mipsle" {
+               // No _div64by32 on mips and using only _mul64by32 doesn't bring much benefit
+               return slowdodiv(n, d)
+       }
+
        if d > n {
                return 0, n
        }