...
Run Format

Text file src/runtime/asm_mips64x.s

Documentation: runtime

     1	// Copyright 2015 The Go Authors. All rights reserved.
     2	// Use of this source code is governed by a BSD-style
     3	// license that can be found in the LICENSE file.
     4	
     5	// +build mips64 mips64le
     6	
     7	#include "go_asm.h"
     8	#include "go_tls.h"
     9	#include "funcdata.h"
    10	#include "textflag.h"
    11	
    12	#define	REGCTXT	R22
    13	
    14	TEXT runtime·rt0_go(SB),NOSPLIT,$0
    15		// R29 = stack; R4 = argc; R5 = argv
    16	
    17		ADDV	$-24, R29
    18		MOVW	R4, 8(R29) // argc
    19		MOVV	R5, 16(R29) // argv
    20	
    21		// create istack out of the given (operating system) stack.
    22		// _cgo_init may update stackguard.
    23		MOVV	$runtime·g0(SB), g
    24		MOVV	$(-64*1024), R23
    25		ADDV	R23, R29, R1
    26		MOVV	R1, g_stackguard0(g)
    27		MOVV	R1, g_stackguard1(g)
    28		MOVV	R1, (g_stack+stack_lo)(g)
    29		MOVV	R29, (g_stack+stack_hi)(g)
    30	
    31		// if there is a _cgo_init, call it using the gcc ABI.
    32		MOVV	_cgo_init(SB), R25
    33		BEQ	R25, nocgo
    34	
    35		MOVV	R0, R7	// arg 3: not used
    36		MOVV	R0, R6	// arg 2: not used
    37		MOVV	$setg_gcc<>(SB), R5	// arg 1: setg
    38		MOVV	g, R4	// arg 0: G
    39		JAL	(R25)
    40	
    41	nocgo:
    42		// update stackguard after _cgo_init
    43		MOVV	(g_stack+stack_lo)(g), R1
    44		ADDV	$const__StackGuard, R1
    45		MOVV	R1, g_stackguard0(g)
    46		MOVV	R1, g_stackguard1(g)
    47	
    48		// set the per-goroutine and per-mach "registers"
    49		MOVV	$runtime·m0(SB), R1
    50	
    51		// save m->g0 = g0
    52		MOVV	g, m_g0(R1)
    53		// save m0 to g0->m
    54		MOVV	R1, g_m(g)
    55	
    56		JAL	runtime·check(SB)
    57	
    58		// args are already prepared
    59		JAL	runtime·args(SB)
    60		JAL	runtime·osinit(SB)
    61		JAL	runtime·schedinit(SB)
    62	
    63		// create a new goroutine to start program
    64		MOVV	$runtime·mainPC(SB), R1		// entry
    65		ADDV	$-24, R29
    66		MOVV	R1, 16(R29)
    67		MOVV	R0, 8(R29)
    68		MOVV	R0, 0(R29)
    69		JAL	runtime·newproc(SB)
    70		ADDV	$24, R29
    71	
    72		// start this M
    73		JAL	runtime·mstart(SB)
    74	
    75		MOVV	R0, 1(R0)
    76		RET
    77	
    78	DATA	runtime·mainPC+0(SB)/8,$runtime·main(SB)
    79	GLOBL	runtime·mainPC(SB),RODATA,$8
    80	
    81	TEXT runtime·breakpoint(SB),NOSPLIT,$-8-0
    82		MOVV	R0, 2(R0) // TODO: TD
    83		RET
    84	
    85	TEXT runtime·asminit(SB),NOSPLIT,$-8-0
    86		RET
    87	
    88	/*
    89	 *  go-routine
    90	 */
    91	
    92	// void gosave(Gobuf*)
    93	// save state in Gobuf; setjmp
    94	TEXT runtime·gosave(SB), NOSPLIT, $-8-8
    95		MOVV	buf+0(FP), R1
    96		MOVV	R29, gobuf_sp(R1)
    97		MOVV	R31, gobuf_pc(R1)
    98		MOVV	g, gobuf_g(R1)
    99		MOVV	R0, gobuf_lr(R1)
   100		MOVV	R0, gobuf_ret(R1)
   101		// Assert ctxt is zero. See func save.
   102		MOVV	gobuf_ctxt(R1), R1
   103		BEQ	R1, 2(PC)
   104		JAL	runtime·badctxt(SB)
   105		RET
   106	
   107	// void gogo(Gobuf*)
   108	// restore state from Gobuf; longjmp
   109	TEXT runtime·gogo(SB), NOSPLIT, $16-8
   110		MOVV	buf+0(FP), R3
   111		MOVV	gobuf_g(R3), g	// make sure g is not nil
   112		JAL	runtime·save_g(SB)
   113	
   114		MOVV	0(g), R2
   115		MOVV	gobuf_sp(R3), R29
   116		MOVV	gobuf_lr(R3), R31
   117		MOVV	gobuf_ret(R3), R1
   118		MOVV	gobuf_ctxt(R3), REGCTXT
   119		MOVV	R0, gobuf_sp(R3)
   120		MOVV	R0, gobuf_ret(R3)
   121		MOVV	R0, gobuf_lr(R3)
   122		MOVV	R0, gobuf_ctxt(R3)
   123		MOVV	gobuf_pc(R3), R4
   124		JMP	(R4)
   125	
   126	// void mcall(fn func(*g))
   127	// Switch to m->g0's stack, call fn(g).
   128	// Fn must never return. It should gogo(&g->sched)
   129	// to keep running g.
   130	TEXT runtime·mcall(SB), NOSPLIT, $-8-8
   131		// Save caller state in g->sched
   132		MOVV	R29, (g_sched+gobuf_sp)(g)
   133		MOVV	R31, (g_sched+gobuf_pc)(g)
   134		MOVV	R0, (g_sched+gobuf_lr)(g)
   135		MOVV	g, (g_sched+gobuf_g)(g)
   136	
   137		// Switch to m->g0 & its stack, call fn.
   138		MOVV	g, R1
   139		MOVV	g_m(g), R3
   140		MOVV	m_g0(R3), g
   141		JAL	runtime·save_g(SB)
   142		BNE	g, R1, 2(PC)
   143		JMP	runtime·badmcall(SB)
   144		MOVV	fn+0(FP), REGCTXT			// context
   145		MOVV	0(REGCTXT), R4			// code pointer
   146		MOVV	(g_sched+gobuf_sp)(g), R29	// sp = m->g0->sched.sp
   147		ADDV	$-16, R29
   148		MOVV	R1, 8(R29)
   149		MOVV	R0, 0(R29)
   150		JAL	(R4)
   151		JMP	runtime·badmcall2(SB)
   152	
   153	// systemstack_switch is a dummy routine that systemstack leaves at the bottom
   154	// of the G stack. We need to distinguish the routine that
   155	// lives at the bottom of the G stack from the one that lives
   156	// at the top of the system stack because the one at the top of
   157	// the system stack terminates the stack walk (see topofstack()).
   158	TEXT runtime·systemstack_switch(SB), NOSPLIT, $0-0
   159		UNDEF
   160		JAL	(R31)	// make sure this function is not leaf
   161		RET
   162	
   163	// func systemstack(fn func())
   164	TEXT runtime·systemstack(SB), NOSPLIT, $0-8
   165		MOVV	fn+0(FP), R1	// R1 = fn
   166		MOVV	R1, REGCTXT		// context
   167		MOVV	g_m(g), R2	// R2 = m
   168	
   169		MOVV	m_gsignal(R2), R3	// R3 = gsignal
   170		BEQ	g, R3, noswitch
   171	
   172		MOVV	m_g0(R2), R3	// R3 = g0
   173		BEQ	g, R3, noswitch
   174	
   175		MOVV	m_curg(R2), R4
   176		BEQ	g, R4, switch
   177	
   178		// Bad: g is not gsignal, not g0, not curg. What is it?
   179		// Hide call from linker nosplit analysis.
   180		MOVV	$runtime·badsystemstack(SB), R4
   181		JAL	(R4)
   182	
   183	switch:
   184		// save our state in g->sched. Pretend to
   185		// be systemstack_switch if the G stack is scanned.
   186		MOVV	$runtime·systemstack_switch(SB), R4
   187		ADDV	$8, R4	// get past prologue
   188		MOVV	R4, (g_sched+gobuf_pc)(g)
   189		MOVV	R29, (g_sched+gobuf_sp)(g)
   190		MOVV	R0, (g_sched+gobuf_lr)(g)
   191		MOVV	g, (g_sched+gobuf_g)(g)
   192	
   193		// switch to g0
   194		MOVV	R3, g
   195		JAL	runtime·save_g(SB)
   196		MOVV	(g_sched+gobuf_sp)(g), R1
   197		// make it look like mstart called systemstack on g0, to stop traceback
   198		ADDV	$-8, R1
   199		MOVV	$runtime·mstart(SB), R2
   200		MOVV	R2, 0(R1)
   201		MOVV	R1, R29
   202	
   203		// call target function
   204		MOVV	0(REGCTXT), R4	// code pointer
   205		JAL	(R4)
   206	
   207		// switch back to g
   208		MOVV	g_m(g), R1
   209		MOVV	m_curg(R1), g
   210		JAL	runtime·save_g(SB)
   211		MOVV	(g_sched+gobuf_sp)(g), R29
   212		MOVV	R0, (g_sched+gobuf_sp)(g)
   213		RET
   214	
   215	noswitch:
   216		// already on m stack, just call directly
   217		// Using a tail call here cleans up tracebacks since we won't stop
   218		// at an intermediate systemstack.
   219		MOVV	0(REGCTXT), R4	// code pointer
   220		MOVV	0(R29), R31	// restore LR
   221		ADDV	$8, R29
   222		JMP	(R4)
   223	
   224	/*
   225	 * support for morestack
   226	 */
   227	
   228	// Called during function prolog when more stack is needed.
   229	// Caller has already loaded:
   230	// R1: framesize, R2: argsize, R3: LR
   231	//
   232	// The traceback routines see morestack on a g0 as being
   233	// the top of a stack (for example, morestack calling newstack
   234	// calling the scheduler calling newm calling gc), so we must
   235	// record an argument size. For that purpose, it has no arguments.
   236	TEXT runtime·morestack(SB),NOSPLIT,$-8-0
   237		// Cannot grow scheduler stack (m->g0).
   238		MOVV	g_m(g), R7
   239		MOVV	m_g0(R7), R8
   240		BNE	g, R8, 3(PC)
   241		JAL	runtime·badmorestackg0(SB)
   242		JAL	runtime·abort(SB)
   243	
   244		// Cannot grow signal stack (m->gsignal).
   245		MOVV	m_gsignal(R7), R8
   246		BNE	g, R8, 3(PC)
   247		JAL	runtime·badmorestackgsignal(SB)
   248		JAL	runtime·abort(SB)
   249	
   250		// Called from f.
   251		// Set g->sched to context in f.
   252		MOVV	R29, (g_sched+gobuf_sp)(g)
   253		MOVV	R31, (g_sched+gobuf_pc)(g)
   254		MOVV	R3, (g_sched+gobuf_lr)(g)
   255		MOVV	REGCTXT, (g_sched+gobuf_ctxt)(g)
   256	
   257		// Called from f.
   258		// Set m->morebuf to f's caller.
   259		MOVV	R3, (m_morebuf+gobuf_pc)(R7)	// f's caller's PC
   260		MOVV	R29, (m_morebuf+gobuf_sp)(R7)	// f's caller's SP
   261		MOVV	g, (m_morebuf+gobuf_g)(R7)
   262	
   263		// Call newstack on m->g0's stack.
   264		MOVV	m_g0(R7), g
   265		JAL	runtime·save_g(SB)
   266		MOVV	(g_sched+gobuf_sp)(g), R29
   267		// Create a stack frame on g0 to call newstack.
   268		MOVV	R0, -8(R29)	// Zero saved LR in frame
   269		ADDV	$-8, R29
   270		JAL	runtime·newstack(SB)
   271	
   272		// Not reached, but make sure the return PC from the call to newstack
   273		// is still in this function, and not the beginning of the next.
   274		UNDEF
   275	
   276	TEXT runtime·morestack_noctxt(SB),NOSPLIT,$-8-0
   277		MOVV	R0, REGCTXT
   278		JMP	runtime·morestack(SB)
   279	
   280	// reflectcall: call a function with the given argument list
   281	// func call(argtype *_type, f *FuncVal, arg *byte, argsize, retoffset uint32).
   282	// we don't have variable-sized frames, so we use a small number
   283	// of constant-sized-frame functions to encode a few bits of size in the pc.
   284	// Caution: ugly multiline assembly macros in your future!
   285	
   286	#define DISPATCH(NAME,MAXSIZE)		\
   287		MOVV	$MAXSIZE, R23;		\
   288		SGTU	R1, R23, R23;		\
   289		BNE	R23, 3(PC);			\
   290		MOVV	$NAME(SB), R4;	\
   291		JMP	(R4)
   292	// Note: can't just "BR NAME(SB)" - bad inlining results.
   293	
   294	TEXT reflect·call(SB), NOSPLIT, $0-0
   295		JMP	·reflectcall(SB)
   296	
   297	TEXT ·reflectcall(SB), NOSPLIT, $-8-32
   298		MOVWU argsize+24(FP), R1
   299		DISPATCH(runtime·call32, 32)
   300		DISPATCH(runtime·call64, 64)
   301		DISPATCH(runtime·call128, 128)
   302		DISPATCH(runtime·call256, 256)
   303		DISPATCH(runtime·call512, 512)
   304		DISPATCH(runtime·call1024, 1024)
   305		DISPATCH(runtime·call2048, 2048)
   306		DISPATCH(runtime·call4096, 4096)
   307		DISPATCH(runtime·call8192, 8192)
   308		DISPATCH(runtime·call16384, 16384)
   309		DISPATCH(runtime·call32768, 32768)
   310		DISPATCH(runtime·call65536, 65536)
   311		DISPATCH(runtime·call131072, 131072)
   312		DISPATCH(runtime·call262144, 262144)
   313		DISPATCH(runtime·call524288, 524288)
   314		DISPATCH(runtime·call1048576, 1048576)
   315		DISPATCH(runtime·call2097152, 2097152)
   316		DISPATCH(runtime·call4194304, 4194304)
   317		DISPATCH(runtime·call8388608, 8388608)
   318		DISPATCH(runtime·call16777216, 16777216)
   319		DISPATCH(runtime·call33554432, 33554432)
   320		DISPATCH(runtime·call67108864, 67108864)
   321		DISPATCH(runtime·call134217728, 134217728)
   322		DISPATCH(runtime·call268435456, 268435456)
   323		DISPATCH(runtime·call536870912, 536870912)
   324		DISPATCH(runtime·call1073741824, 1073741824)
   325		MOVV	$runtime·badreflectcall(SB), R4
   326		JMP	(R4)
   327	
   328	#define CALLFN(NAME,MAXSIZE)			\
   329	TEXT NAME(SB), WRAPPER, $MAXSIZE-24;		\
   330		NO_LOCAL_POINTERS;			\
   331		/* copy arguments to stack */		\
   332		MOVV	arg+16(FP), R1;			\
   333		MOVWU	argsize+24(FP), R2;			\
   334		MOVV	R29, R3;				\
   335		ADDV	$8, R3;			\
   336		ADDV	R3, R2;				\
   337		BEQ	R3, R2, 6(PC);				\
   338		MOVBU	(R1), R4;			\
   339		ADDV	$1, R1;			\
   340		MOVBU	R4, (R3);			\
   341		ADDV	$1, R3;			\
   342		JMP	-5(PC);				\
   343		/* call function */			\
   344		MOVV	f+8(FP), REGCTXT;			\
   345		MOVV	(REGCTXT), R4;			\
   346		PCDATA  $PCDATA_StackMapIndex, $0;	\
   347		JAL	(R4);				\
   348		/* copy return values back */		\
   349		MOVV	argtype+0(FP), R5;		\
   350		MOVV	arg+16(FP), R1;			\
   351		MOVWU	n+24(FP), R2;			\
   352		MOVWU	retoffset+28(FP), R4;		\
   353		ADDV	$8, R29, R3;				\
   354		ADDV	R4, R3; 			\
   355		ADDV	R4, R1;				\
   356		SUBVU	R4, R2;				\
   357		JAL	callRet<>(SB);			\
   358		RET
   359	
   360	// callRet copies return values back at the end of call*. This is a
   361	// separate function so it can allocate stack space for the arguments
   362	// to reflectcallmove. It does not follow the Go ABI; it expects its
   363	// arguments in registers.
   364	TEXT callRet<>(SB), NOSPLIT, $32-0
   365		MOVV	R5, 8(R29)
   366		MOVV	R1, 16(R29)
   367		MOVV	R3, 24(R29)
   368		MOVV	R2, 32(R29)
   369		JAL	runtime·reflectcallmove(SB)
   370		RET
   371	
   372	CALLFN(·call16, 16)
   373	CALLFN(·call32, 32)
   374	CALLFN(·call64, 64)
   375	CALLFN(·call128, 128)
   376	CALLFN(·call256, 256)
   377	CALLFN(·call512, 512)
   378	CALLFN(·call1024, 1024)
   379	CALLFN(·call2048, 2048)
   380	CALLFN(·call4096, 4096)
   381	CALLFN(·call8192, 8192)
   382	CALLFN(·call16384, 16384)
   383	CALLFN(·call32768, 32768)
   384	CALLFN(·call65536, 65536)
   385	CALLFN(·call131072, 131072)
   386	CALLFN(·call262144, 262144)
   387	CALLFN(·call524288, 524288)
   388	CALLFN(·call1048576, 1048576)
   389	CALLFN(·call2097152, 2097152)
   390	CALLFN(·call4194304, 4194304)
   391	CALLFN(·call8388608, 8388608)
   392	CALLFN(·call16777216, 16777216)
   393	CALLFN(·call33554432, 33554432)
   394	CALLFN(·call67108864, 67108864)
   395	CALLFN(·call134217728, 134217728)
   396	CALLFN(·call268435456, 268435456)
   397	CALLFN(·call536870912, 536870912)
   398	CALLFN(·call1073741824, 1073741824)
   399	
   400	TEXT runtime·procyield(SB),NOSPLIT,$0-0
   401		RET
   402	
   403	// void jmpdefer(fv, sp);
   404	// called from deferreturn.
   405	// 1. grab stored LR for caller
   406	// 2. sub 8 bytes to get back to JAL deferreturn
   407	// 3. JMP to fn
   408	TEXT runtime·jmpdefer(SB), NOSPLIT, $-8-16
   409		MOVV	0(R29), R31
   410		ADDV	$-8, R31
   411	
   412		MOVV	fv+0(FP), REGCTXT
   413		MOVV	argp+8(FP), R29
   414		ADDV	$-8, R29
   415		NOR	R0, R0	// prevent scheduling
   416		MOVV	0(REGCTXT), R4
   417		JMP	(R4)
   418	
   419	// Save state of caller into g->sched. Smashes R1.
   420	TEXT gosave<>(SB),NOSPLIT,$-8
   421		MOVV	R31, (g_sched+gobuf_pc)(g)
   422		MOVV	R29, (g_sched+gobuf_sp)(g)
   423		MOVV	R0, (g_sched+gobuf_lr)(g)
   424		MOVV	R0, (g_sched+gobuf_ret)(g)
   425		// Assert ctxt is zero. See func save.
   426		MOVV	(g_sched+gobuf_ctxt)(g), R1
   427		BEQ	R1, 2(PC)
   428		JAL	runtime·badctxt(SB)
   429		RET
   430	
   431	// func asmcgocall(fn, arg unsafe.Pointer) int32
   432	// Call fn(arg) on the scheduler stack,
   433	// aligned appropriately for the gcc ABI.
   434	// See cgocall.go for more details.
   435	TEXT ·asmcgocall(SB),NOSPLIT,$0-20
   436		MOVV	fn+0(FP), R25
   437		MOVV	arg+8(FP), R4
   438	
   439		MOVV	R29, R3	// save original stack pointer
   440		MOVV	g, R2
   441	
   442		// Figure out if we need to switch to m->g0 stack.
   443		// We get called to create new OS threads too, and those
   444		// come in on the m->g0 stack already.
   445		MOVV	g_m(g), R5
   446		MOVV	m_g0(R5), R6
   447		BEQ	R6, g, g0
   448	
   449		JAL	gosave<>(SB)
   450		MOVV	R6, g
   451		JAL	runtime·save_g(SB)
   452		MOVV	(g_sched+gobuf_sp)(g), R29
   453	
   454		// Now on a scheduling stack (a pthread-created stack).
   455	g0:
   456		// Save room for two of our pointers.
   457		ADDV	$-16, R29
   458		MOVV	R2, 0(R29)	// save old g on stack
   459		MOVV	(g_stack+stack_hi)(R2), R2
   460		SUBVU	R3, R2
   461		MOVV	R2, 8(R29)	// save depth in old g stack (can't just save SP, as stack might be copied during a callback)
   462		JAL	(R25)
   463	
   464		// Restore g, stack pointer. R2 is return value.
   465		MOVV	0(R29), g
   466		JAL	runtime·save_g(SB)
   467		MOVV	(g_stack+stack_hi)(g), R5
   468		MOVV	8(R29), R6
   469		SUBVU	R6, R5
   470		MOVV	R5, R29
   471	
   472		MOVW	R2, ret+16(FP)
   473		RET
   474	
   475	// cgocallback(void (*fn)(void*), void *frame, uintptr framesize, uintptr ctxt)
   476	// Turn the fn into a Go func (by taking its address) and call
   477	// cgocallback_gofunc.
   478	TEXT runtime·cgocallback(SB),NOSPLIT,$32-32
   479		MOVV	$fn+0(FP), R1
   480		MOVV	R1, 8(R29)
   481		MOVV	frame+8(FP), R1
   482		MOVV	R1, 16(R29)
   483		MOVV	framesize+16(FP), R1
   484		MOVV	R1, 24(R29)
   485		MOVV	ctxt+24(FP), R1
   486		MOVV	R1, 32(R29)
   487		MOVV	$runtime·cgocallback_gofunc(SB), R1
   488		JAL	(R1)
   489		RET
   490	
   491	// cgocallback_gofunc(FuncVal*, void *frame, uintptr framesize, uintptr ctxt)
   492	// See cgocall.go for more details.
   493	TEXT ·cgocallback_gofunc(SB),NOSPLIT,$16-32
   494		NO_LOCAL_POINTERS
   495	
   496		// Load m and g from thread-local storage.
   497		MOVB	runtime·iscgo(SB), R1
   498		BEQ	R1, nocgo
   499		JAL	runtime·load_g(SB)
   500	nocgo:
   501	
   502		// If g is nil, Go did not create the current thread.
   503		// Call needm to obtain one for temporary use.
   504		// In this case, we're running on the thread stack, so there's
   505		// lots of space, but the linker doesn't know. Hide the call from
   506		// the linker analysis by using an indirect call.
   507		BEQ	g, needm
   508	
   509		MOVV	g_m(g), R3
   510		MOVV	R3, savedm-8(SP)
   511		JMP	havem
   512	
   513	needm:
   514		MOVV	g, savedm-8(SP) // g is zero, so is m.
   515		MOVV	$runtime·needm(SB), R4
   516		JAL	(R4)
   517	
   518		// Set m->sched.sp = SP, so that if a panic happens
   519		// during the function we are about to execute, it will
   520		// have a valid SP to run on the g0 stack.
   521		// The next few lines (after the havem label)
   522		// will save this SP onto the stack and then write
   523		// the same SP back to m->sched.sp. That seems redundant,
   524		// but if an unrecovered panic happens, unwindm will
   525		// restore the g->sched.sp from the stack location
   526		// and then systemstack will try to use it. If we don't set it here,
   527		// that restored SP will be uninitialized (typically 0) and
   528		// will not be usable.
   529		MOVV	g_m(g), R3
   530		MOVV	m_g0(R3), R1
   531		MOVV	R29, (g_sched+gobuf_sp)(R1)
   532	
   533	havem:
   534		// Now there's a valid m, and we're running on its m->g0.
   535		// Save current m->g0->sched.sp on stack and then set it to SP.
   536		// Save current sp in m->g0->sched.sp in preparation for
   537		// switch back to m->curg stack.
   538		// NOTE: unwindm knows that the saved g->sched.sp is at 8(R29) aka savedsp-16(SP).
   539		MOVV	m_g0(R3), R1
   540		MOVV	(g_sched+gobuf_sp)(R1), R2
   541		MOVV	R2, savedsp-16(SP)
   542		MOVV	R29, (g_sched+gobuf_sp)(R1)
   543	
   544		// Switch to m->curg stack and call runtime.cgocallbackg.
   545		// Because we are taking over the execution of m->curg
   546		// but *not* resuming what had been running, we need to
   547		// save that information (m->curg->sched) so we can restore it.
   548		// We can restore m->curg->sched.sp easily, because calling
   549		// runtime.cgocallbackg leaves SP unchanged upon return.
   550		// To save m->curg->sched.pc, we push it onto the stack.
   551		// This has the added benefit that it looks to the traceback
   552		// routine like cgocallbackg is going to return to that
   553		// PC (because the frame we allocate below has the same
   554		// size as cgocallback_gofunc's frame declared above)
   555		// so that the traceback will seamlessly trace back into
   556		// the earlier calls.
   557		//
   558		// In the new goroutine, -8(SP) is unused (where SP refers to
   559		// m->curg's SP while we're setting it up, before we've adjusted it).
   560		MOVV	m_curg(R3), g
   561		JAL	runtime·save_g(SB)
   562		MOVV	(g_sched+gobuf_sp)(g), R2 // prepare stack as R2
   563		MOVV	(g_sched+gobuf_pc)(g), R4
   564		MOVV	R4, -24(R2)
   565		MOVV    ctxt+24(FP), R1
   566		MOVV    R1, -16(R2)
   567		MOVV	$-24(R2), R29
   568		JAL	runtime·cgocallbackg(SB)
   569	
   570		// Restore g->sched (== m->curg->sched) from saved values.
   571		MOVV	0(R29), R4
   572		MOVV	R4, (g_sched+gobuf_pc)(g)
   573		MOVV	$24(R29), R2
   574		MOVV	R2, (g_sched+gobuf_sp)(g)
   575	
   576		// Switch back to m->g0's stack and restore m->g0->sched.sp.
   577		// (Unlike m->curg, the g0 goroutine never uses sched.pc,
   578		// so we do not have to restore it.)
   579		MOVV	g_m(g), R3
   580		MOVV	m_g0(R3), g
   581		JAL	runtime·save_g(SB)
   582		MOVV	(g_sched+gobuf_sp)(g), R29
   583		MOVV	savedsp-16(SP), R2
   584		MOVV	R2, (g_sched+gobuf_sp)(g)
   585	
   586		// If the m on entry was nil, we called needm above to borrow an m
   587		// for the duration of the call. Since the call is over, return it with dropm.
   588		MOVV	savedm-8(SP), R3
   589		BNE	R3, droppedm
   590		MOVV	$runtime·dropm(SB), R4
   591		JAL	(R4)
   592	droppedm:
   593	
   594		// Done!
   595		RET
   596	
   597	// void setg(G*); set g. for use by needm.
   598	TEXT runtime·setg(SB), NOSPLIT, $0-8
   599		MOVV	gg+0(FP), g
   600		// This only happens if iscgo, so jump straight to save_g
   601		JAL	runtime·save_g(SB)
   602		RET
   603	
   604	// void setg_gcc(G*); set g called from gcc with g in R1
   605	TEXT setg_gcc<>(SB),NOSPLIT,$0-0
   606		MOVV	R1, g
   607		JAL	runtime·save_g(SB)
   608		RET
   609	
   610	TEXT runtime·getcallerpc(SB),NOSPLIT,$-8-8
   611		MOVV	0(R29), R1		// LR saved by caller
   612		MOVV	R1, ret+0(FP)
   613		RET
   614	
   615	TEXT runtime·abort(SB),NOSPLIT,$-8-0
   616		MOVW	(R0), R0
   617		UNDEF
   618	
   619	// AES hashing not implemented for mips64
   620	TEXT runtime·aeshash(SB),NOSPLIT,$-8-0
   621		MOVW	(R0), R1
   622	TEXT runtime·aeshash32(SB),NOSPLIT,$-8-0
   623		MOVW	(R0), R1
   624	TEXT runtime·aeshash64(SB),NOSPLIT,$-8-0
   625		MOVW	(R0), R1
   626	TEXT runtime·aeshashstr(SB),NOSPLIT,$-8-0
   627		MOVW	(R0), R1
   628	
   629	// memequal(p, q unsafe.Pointer, size uintptr) bool
   630	TEXT runtime·memequal(SB),NOSPLIT,$-8-25
   631		MOVV	a+0(FP), R1
   632		MOVV	b+8(FP), R2
   633		BEQ	R1, R2, eq
   634		MOVV	size+16(FP), R3
   635		ADDV	R1, R3, R4
   636	loop:
   637		BNE	R1, R4, test
   638		MOVV	$1, R1
   639		MOVB	R1, ret+24(FP)
   640		RET
   641	test:
   642		MOVBU	(R1), R6
   643		ADDV	$1, R1
   644		MOVBU	(R2), R7
   645		ADDV	$1, R2
   646		BEQ	R6, R7, loop
   647	
   648		MOVB	R0, ret+24(FP)
   649		RET
   650	eq:
   651		MOVV	$1, R1
   652		MOVB	R1, ret+24(FP)
   653		RET
   654	
   655	// memequal_varlen(a, b unsafe.Pointer) bool
   656	TEXT runtime·memequal_varlen(SB),NOSPLIT,$40-17
   657		MOVV	a+0(FP), R1
   658		MOVV	b+8(FP), R2
   659		BEQ	R1, R2, eq
   660		MOVV	8(REGCTXT), R3    // compiler stores size at offset 8 in the closure
   661		MOVV	R1, 8(R29)
   662		MOVV	R2, 16(R29)
   663		MOVV	R3, 24(R29)
   664		JAL	runtime·memequal(SB)
   665		MOVBU	32(R29), R1
   666		MOVB	R1, ret+16(FP)
   667		RET
   668	eq:
   669		MOVV	$1, R1
   670		MOVB	R1, ret+16(FP)
   671		RET
   672	
   673	// TODO: share code with memequal?
   674	TEXT bytes·Equal(SB),NOSPLIT,$0-49
   675		MOVV	a_len+8(FP), R3
   676		MOVV	b_len+32(FP), R4
   677		BNE	R3, R4, noteq		// unequal lengths are not equal
   678	
   679		MOVV	a+0(FP), R1
   680		MOVV	b+24(FP), R2
   681		ADDV	R1, R3		// end
   682	
   683	loop:
   684		BEQ	R1, R3, equal		// reached the end
   685		MOVBU	(R1), R6
   686		ADDV	$1, R1
   687		MOVBU	(R2), R7
   688		ADDV	$1, R2
   689		BEQ	R6, R7, loop
   690	
   691	noteq:
   692		MOVB	R0, ret+48(FP)
   693		RET
   694	
   695	equal:
   696		MOVV	$1, R1
   697		MOVB	R1, ret+48(FP)
   698		RET
   699	
   700	TEXT bytes·IndexByte(SB),NOSPLIT,$0-40
   701		MOVV	s+0(FP), R1
   702		MOVV	s_len+8(FP), R2
   703		MOVBU	c+24(FP), R3	// byte to find
   704		MOVV	R1, R4		// store base for later
   705		ADDV	R1, R2		// end
   706		ADDV	$-1, R1
   707	
   708	loop:
   709		ADDV	$1, R1
   710		BEQ	R1, R2, notfound
   711		MOVBU	(R1), R5
   712		BNE	R3, R5, loop
   713	
   714		SUBV	R4, R1		// remove base
   715		MOVV	R1, ret+32(FP)
   716		RET
   717	
   718	notfound:
   719		MOVV	$-1, R1
   720		MOVV	R1, ret+32(FP)
   721		RET
   722	
   723	TEXT strings·IndexByte(SB),NOSPLIT,$0-32
   724		MOVV	p+0(FP), R1
   725		MOVV	b_len+8(FP), R2
   726		MOVBU	c+16(FP), R3	// byte to find
   727		MOVV	R1, R4		// store base for later
   728		ADDV	R1, R2		// end
   729		ADDV	$-1, R1
   730	
   731	loop:
   732		ADDV	$1, R1
   733		BEQ	R1, R2, notfound
   734		MOVBU	(R1), R5
   735		BNE	R3, R5, loop
   736	
   737		SUBV	R4, R1		// remove base
   738		MOVV	R1, ret+24(FP)
   739		RET
   740	
   741	notfound:
   742		MOVV	$-1, R1
   743		MOVV	R1, ret+24(FP)
   744		RET
   745	
   746	TEXT runtime·return0(SB), NOSPLIT, $0
   747		MOVW	$0, R1
   748		RET
   749	
   750	// Called from cgo wrappers, this function returns g->m->curg.stack.hi.
   751	// Must obey the gcc calling convention.
   752	TEXT _cgo_topofstack(SB),NOSPLIT,$16
   753		// g (R30) and REGTMP (R23)  might be clobbered by load_g. They
   754		// are callee-save in the gcc calling convention, so save them.
   755		MOVV	R23, savedR23-16(SP)
   756		MOVV	g, savedG-8(SP)
   757	
   758		JAL	runtime·load_g(SB)
   759		MOVV	g_m(g), R1
   760		MOVV	m_curg(R1), R1
   761		MOVV	(g_stack+stack_hi)(R1), R2 // return value in R2
   762	
   763		MOVV	savedG-8(SP), g
   764		MOVV	savedR23-16(SP), R23
   765		RET
   766	
   767	// The top-most function running on a goroutine
   768	// returns to goexit+PCQuantum.
   769	TEXT runtime·goexit(SB),NOSPLIT,$-8-0
   770		NOR	R0, R0	// NOP
   771		JAL	runtime·goexit1(SB)	// does not return
   772		// traceback from goexit1 must hit code range of goexit
   773		NOR	R0, R0	// NOP
   774	
   775	TEXT ·checkASM(SB),NOSPLIT,$0-1
   776		MOVW	$1, R1
   777		MOVB	R1, ret+0(FP)
   778		RET

View as plain text