Commit 272032d0 authored by Vladimir Stefanovic's avatar Vladimir Stefanovic Committed by Brad Fitzpatrick

runtime: add support files for linux/mips{,le} port

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: default avatarCherry Zhang <cherryyz@google.com>
parent 4d1fdd8b
// 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
CALLFNcall16, 16)
CALLFNcall32, 32)
CALLFNcall64, 64)
CALLFNcall128, 128)
CALLFNcall256, 256)
CALLFNcall512, 512)
CALLFNcall1024, 1024)
CALLFNcall2048, 2048)
CALLFNcall4096, 4096)
CALLFNcall8192, 8192)
CALLFNcall16384, 16384)
CALLFNcall32768, 32768)
CALLFNcall65536, 65536)
CALLFNcall131072, 131072)
CALLFNcall262144, 262144)
CALLFNcall524288, 524288)
CALLFNcall1048576, 1048576)
CALLFNcall2097152, 2097152)
CALLFNcall4194304, 4194304)
CALLFNcall8388608, 8388608)
CALLFNcall16777216, 16777216)
CALLFNcall33554432, 33554432)
CALLFNcall67108864, 67108864)
CALLFNcall134217728, 134217728)
CALLFNcall268435456, 268435456)
CALLFNcall536870912, 536870912)
CALLFNcall1073741824, 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
// 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
......@@ -6,6 +6,8 @@
// +build !arm64
// +build !mips64
// +build !mips64le
// +build !mips
// +build !mipsle
package runtime
......
// 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
}
......@@ -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
......
......@@ -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
......
......@@ -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
......
......@@ -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)
......
// 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
// 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
......@@ -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
......
......@@ -30,7 +30,7 @@ func cputicks() int64 {
const (
_SS_DISABLE = 2
_NSIG = 65
_NSIG = 129
_SI_USER = 0
_SIG_BLOCK = 1
_SIG_UNBLOCK = 2
......
// 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)
}
......@@ -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
......
// 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)
// 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 }
// 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)))
}
......@@ -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
......
// 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"},
}
// 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"},
}
......@@ -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
......
// 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
// 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
}
// 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
......@@ -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
......
......@@ -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
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment