...

Text file src/runtime/asm_mips64x.s

     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|NOFRAME,$0-0
    82		MOVV	R0, 2(R0) // TODO: TD
    83		RET
    84	
    85	TEXT runtime·asminit(SB),NOSPLIT|NOFRAME,$0-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|NOFRAME, $0-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|NOFRAME, $0-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		JAL	runtime·abort(SB)
   183	
   184	switch:
   185		// save our state in g->sched. Pretend to
   186		// be systemstack_switch if the G stack is scanned.
   187		MOVV	$runtime·systemstack_switch(SB), R4
   188		ADDV	$8, R4	// get past prologue
   189		MOVV	R4, (g_sched+gobuf_pc)(g)
   190		MOVV	R29, (g_sched+gobuf_sp)(g)
   191		MOVV	R0, (g_sched+gobuf_lr)(g)
   192		MOVV	g, (g_sched+gobuf_g)(g)
   193	
   194		// switch to g0
   195		MOVV	R3, g
   196		JAL	runtime·save_g(SB)
   197		MOVV	(g_sched+gobuf_sp)(g), R1
   198		// make it look like mstart called systemstack on g0, to stop traceback
   199		ADDV	$-8, R1
   200		MOVV	$runtime·mstart(SB), R2
   201		MOVV	R2, 0(R1)
   202		MOVV	R1, R29
   203	
   204		// call target function
   205		MOVV	0(REGCTXT), R4	// code pointer
   206		JAL	(R4)
   207	
   208		// switch back to g
   209		MOVV	g_m(g), R1
   210		MOVV	m_curg(R1), g
   211		JAL	runtime·save_g(SB)
   212		MOVV	(g_sched+gobuf_sp)(g), R29
   213		MOVV	R0, (g_sched+gobuf_sp)(g)
   214		RET
   215	
   216	noswitch:
   217		// already on m stack, just call directly
   218		// Using a tail call here cleans up tracebacks since we won't stop
   219		// at an intermediate systemstack.
   220		MOVV	0(REGCTXT), R4	// code pointer
   221		MOVV	0(R29), R31	// restore LR
   222		ADDV	$8, R29
   223		JMP	(R4)
   224	
   225	/*
   226	 * support for morestack
   227	 */
   228	
   229	// Called during function prolog when more stack is needed.
   230	// Caller has already loaded:
   231	// R1: framesize, R2: argsize, R3: LR
   232	//
   233	// The traceback routines see morestack on a g0 as being
   234	// the top of a stack (for example, morestack calling newstack
   235	// calling the scheduler calling newm calling gc), so we must
   236	// record an argument size. For that purpose, it has no arguments.
   237	TEXT runtime·morestack(SB),NOSPLIT|NOFRAME,$0-0
   238		// Cannot grow scheduler stack (m->g0).
   239		MOVV	g_m(g), R7
   240		MOVV	m_g0(R7), R8
   241		BNE	g, R8, 3(PC)
   242		JAL	runtime·badmorestackg0(SB)
   243		JAL	runtime·abort(SB)
   244	
   245		// Cannot grow signal stack (m->gsignal).
   246		MOVV	m_gsignal(R7), R8
   247		BNE	g, R8, 3(PC)
   248		JAL	runtime·badmorestackgsignal(SB)
   249		JAL	runtime·abort(SB)
   250	
   251		// Called from f.
   252		// Set g->sched to context in f.
   253		MOVV	R29, (g_sched+gobuf_sp)(g)
   254		MOVV	R31, (g_sched+gobuf_pc)(g)
   255		MOVV	R3, (g_sched+gobuf_lr)(g)
   256		MOVV	REGCTXT, (g_sched+gobuf_ctxt)(g)
   257	
   258		// Called from f.
   259		// Set m->morebuf to f's caller.
   260		MOVV	R3, (m_morebuf+gobuf_pc)(R7)	// f's caller's PC
   261		MOVV	R29, (m_morebuf+gobuf_sp)(R7)	// f's caller's SP
   262		MOVV	g, (m_morebuf+gobuf_g)(R7)
   263	
   264		// Call newstack on m->g0's stack.
   265		MOVV	m_g0(R7), g
   266		JAL	runtime·save_g(SB)
   267		MOVV	(g_sched+gobuf_sp)(g), R29
   268		// Create a stack frame on g0 to call newstack.
   269		MOVV	R0, -8(R29)	// Zero saved LR in frame
   270		ADDV	$-8, R29
   271		JAL	runtime·newstack(SB)
   272	
   273		// Not reached, but make sure the return PC from the call to newstack
   274		// is still in this function, and not the beginning of the next.
   275		UNDEF
   276	
   277	TEXT runtime·morestack_noctxt(SB),NOSPLIT|NOFRAME,$0-0
   278		MOVV	R0, REGCTXT
   279		JMP	runtime·morestack(SB)
   280	
   281	// reflectcall: call a function with the given argument list
   282	// func call(argtype *_type, f *FuncVal, arg *byte, argsize, retoffset uint32).
   283	// we don't have variable-sized frames, so we use a small number
   284	// of constant-sized-frame functions to encode a few bits of size in the pc.
   285	// Caution: ugly multiline assembly macros in your future!
   286	
   287	#define DISPATCH(NAME,MAXSIZE)		\
   288		MOVV	$MAXSIZE, R23;		\
   289		SGTU	R1, R23, R23;		\
   290		BNE	R23, 3(PC);			\
   291		MOVV	$NAME(SB), R4;	\
   292		JMP	(R4)
   293	// Note: can't just "BR NAME(SB)" - bad inlining results.
   294	
   295	TEXT ·reflectcall(SB), NOSPLIT|NOFRAME, $0-32
   296		MOVWU argsize+24(FP), R1
   297		DISPATCH(runtime·call32, 32)
   298		DISPATCH(runtime·call64, 64)
   299		DISPATCH(runtime·call128, 128)
   300		DISPATCH(runtime·call256, 256)
   301		DISPATCH(runtime·call512, 512)
   302		DISPATCH(runtime·call1024, 1024)
   303		DISPATCH(runtime·call2048, 2048)
   304		DISPATCH(runtime·call4096, 4096)
   305		DISPATCH(runtime·call8192, 8192)
   306		DISPATCH(runtime·call16384, 16384)
   307		DISPATCH(runtime·call32768, 32768)
   308		DISPATCH(runtime·call65536, 65536)
   309		DISPATCH(runtime·call131072, 131072)
   310		DISPATCH(runtime·call262144, 262144)
   311		DISPATCH(runtime·call524288, 524288)
   312		DISPATCH(runtime·call1048576, 1048576)
   313		DISPATCH(runtime·call2097152, 2097152)
   314		DISPATCH(runtime·call4194304, 4194304)
   315		DISPATCH(runtime·call8388608, 8388608)
   316		DISPATCH(runtime·call16777216, 16777216)
   317		DISPATCH(runtime·call33554432, 33554432)
   318		DISPATCH(runtime·call67108864, 67108864)
   319		DISPATCH(runtime·call134217728, 134217728)
   320		DISPATCH(runtime·call268435456, 268435456)
   321		DISPATCH(runtime·call536870912, 536870912)
   322		DISPATCH(runtime·call1073741824, 1073741824)
   323		MOVV	$runtime·badreflectcall(SB), R4
   324		JMP	(R4)
   325	
   326	#define CALLFN(NAME,MAXSIZE)			\
   327	TEXT NAME(SB), WRAPPER, $MAXSIZE-24;		\
   328		NO_LOCAL_POINTERS;			\
   329		/* copy arguments to stack */		\
   330		MOVV	arg+16(FP), R1;			\
   331		MOVWU	argsize+24(FP), R2;			\
   332		MOVV	R29, R3;				\
   333		ADDV	$8, R3;			\
   334		ADDV	R3, R2;				\
   335		BEQ	R3, R2, 6(PC);				\
   336		MOVBU	(R1), R4;			\
   337		ADDV	$1, R1;			\
   338		MOVBU	R4, (R3);			\
   339		ADDV	$1, R3;			\
   340		JMP	-5(PC);				\
   341		/* call function */			\
   342		MOVV	f+8(FP), REGCTXT;			\
   343		MOVV	(REGCTXT), R4;			\
   344		PCDATA  $PCDATA_StackMapIndex, $0;	\
   345		JAL	(R4);				\
   346		/* copy return values back */		\
   347		MOVV	argtype+0(FP), R5;		\
   348		MOVV	arg+16(FP), R1;			\
   349		MOVWU	n+24(FP), R2;			\
   350		MOVWU	retoffset+28(FP), R4;		\
   351		ADDV	$8, R29, R3;				\
   352		ADDV	R4, R3; 			\
   353		ADDV	R4, R1;				\
   354		SUBVU	R4, R2;				\
   355		JAL	callRet<>(SB);			\
   356		RET
   357	
   358	// callRet copies return values back at the end of call*. This is a
   359	// separate function so it can allocate stack space for the arguments
   360	// to reflectcallmove. It does not follow the Go ABI; it expects its
   361	// arguments in registers.
   362	TEXT callRet<>(SB), NOSPLIT, $32-0
   363		MOVV	R5, 8(R29)
   364		MOVV	R1, 16(R29)
   365		MOVV	R3, 24(R29)
   366		MOVV	R2, 32(R29)
   367		JAL	runtime·reflectcallmove(SB)
   368		RET
   369	
   370	CALLFN(·call16, 16)
   371	CALLFN(·call32, 32)
   372	CALLFN(·call64, 64)
   373	CALLFN(·call128, 128)
   374	CALLFN(·call256, 256)
   375	CALLFN(·call512, 512)
   376	CALLFN(·call1024, 1024)
   377	CALLFN(·call2048, 2048)
   378	CALLFN(·call4096, 4096)
   379	CALLFN(·call8192, 8192)
   380	CALLFN(·call16384, 16384)
   381	CALLFN(·call32768, 32768)
   382	CALLFN(·call65536, 65536)
   383	CALLFN(·call131072, 131072)
   384	CALLFN(·call262144, 262144)
   385	CALLFN(·call524288, 524288)
   386	CALLFN(·call1048576, 1048576)
   387	CALLFN(·call2097152, 2097152)
   388	CALLFN(·call4194304, 4194304)
   389	CALLFN(·call8388608, 8388608)
   390	CALLFN(·call16777216, 16777216)
   391	CALLFN(·call33554432, 33554432)
   392	CALLFN(·call67108864, 67108864)
   393	CALLFN(·call134217728, 134217728)
   394	CALLFN(·call268435456, 268435456)
   395	CALLFN(·call536870912, 536870912)
   396	CALLFN(·call1073741824, 1073741824)
   397	
   398	TEXT runtime·procyield(SB),NOSPLIT,$0-0
   399		RET
   400	
   401	// void jmpdefer(fv, sp);
   402	// called from deferreturn.
   403	// 1. grab stored LR for caller
   404	// 2. sub 8 bytes to get back to JAL deferreturn
   405	// 3. JMP to fn
   406	TEXT runtime·jmpdefer(SB), NOSPLIT|NOFRAME, $0-16
   407		MOVV	0(R29), R31
   408		ADDV	$-8, R31
   409	
   410		MOVV	fv+0(FP), REGCTXT
   411		MOVV	argp+8(FP), R29
   412		ADDV	$-8, R29
   413		NOR	R0, R0	// prevent scheduling
   414		MOVV	0(REGCTXT), R4
   415		JMP	(R4)
   416	
   417	// Save state of caller into g->sched. Smashes R1.
   418	TEXT gosave<>(SB),NOSPLIT|NOFRAME,$0
   419		MOVV	R31, (g_sched+gobuf_pc)(g)
   420		MOVV	R29, (g_sched+gobuf_sp)(g)
   421		MOVV	R0, (g_sched+gobuf_lr)(g)
   422		MOVV	R0, (g_sched+gobuf_ret)(g)
   423		// Assert ctxt is zero. See func save.
   424		MOVV	(g_sched+gobuf_ctxt)(g), R1
   425		BEQ	R1, 2(PC)
   426		JAL	runtime·badctxt(SB)
   427		RET
   428	
   429	// func asmcgocall(fn, arg unsafe.Pointer) int32
   430	// Call fn(arg) on the scheduler stack,
   431	// aligned appropriately for the gcc ABI.
   432	// See cgocall.go for more details.
   433	TEXT ·asmcgocall(SB),NOSPLIT,$0-20
   434		MOVV	fn+0(FP), R25
   435		MOVV	arg+8(FP), R4
   436	
   437		MOVV	R29, R3	// save original stack pointer
   438		MOVV	g, R2
   439	
   440		// Figure out if we need to switch to m->g0 stack.
   441		// We get called to create new OS threads too, and those
   442		// come in on the m->g0 stack already.
   443		MOVV	g_m(g), R5
   444		MOVV	m_g0(R5), R6
   445		BEQ	R6, g, g0
   446	
   447		JAL	gosave<>(SB)
   448		MOVV	R6, g
   449		JAL	runtime·save_g(SB)
   450		MOVV	(g_sched+gobuf_sp)(g), R29
   451	
   452		// Now on a scheduling stack (a pthread-created stack).
   453	g0:
   454		// Save room for two of our pointers.
   455		ADDV	$-16, R29
   456		MOVV	R2, 0(R29)	// save old g on stack
   457		MOVV	(g_stack+stack_hi)(R2), R2
   458		SUBVU	R3, R2
   459		MOVV	R2, 8(R29)	// save depth in old g stack (can't just save SP, as stack might be copied during a callback)
   460		JAL	(R25)
   461	
   462		// Restore g, stack pointer. R2 is return value.
   463		MOVV	0(R29), g
   464		JAL	runtime·save_g(SB)
   465		MOVV	(g_stack+stack_hi)(g), R5
   466		MOVV	8(R29), R6
   467		SUBVU	R6, R5
   468		MOVV	R5, R29
   469	
   470		MOVW	R2, ret+16(FP)
   471		RET
   472	
   473	// cgocallback(void (*fn)(void*), void *frame, uintptr framesize, uintptr ctxt)
   474	// Turn the fn into a Go func (by taking its address) and call
   475	// cgocallback_gofunc.
   476	TEXT runtime·cgocallback(SB),NOSPLIT,$32-32
   477		MOVV	$fn+0(FP), R1
   478		MOVV	R1, 8(R29)
   479		MOVV	frame+8(FP), R1
   480		MOVV	R1, 16(R29)
   481		MOVV	framesize+16(FP), R1
   482		MOVV	R1, 24(R29)
   483		MOVV	ctxt+24(FP), R1
   484		MOVV	R1, 32(R29)
   485		MOVV	$runtime·cgocallback_gofunc(SB), R1
   486		JAL	(R1)
   487		RET
   488	
   489	// cgocallback_gofunc(FuncVal*, void *frame, uintptr framesize, uintptr ctxt)
   490	// See cgocall.go for more details.
   491	TEXT ·cgocallback_gofunc(SB),NOSPLIT,$16-32
   492		NO_LOCAL_POINTERS
   493	
   494		// Load m and g from thread-local storage.
   495		MOVB	runtime·iscgo(SB), R1
   496		BEQ	R1, nocgo
   497		JAL	runtime·load_g(SB)
   498	nocgo:
   499	
   500		// If g is nil, Go did not create the current thread.
   501		// Call needm to obtain one for temporary use.
   502		// In this case, we're running on the thread stack, so there's
   503		// lots of space, but the linker doesn't know. Hide the call from
   504		// the linker analysis by using an indirect call.
   505		BEQ	g, needm
   506	
   507		MOVV	g_m(g), R3
   508		MOVV	R3, savedm-8(SP)
   509		JMP	havem
   510	
   511	needm:
   512		MOVV	g, savedm-8(SP) // g is zero, so is m.
   513		MOVV	$runtime·needm(SB), R4
   514		JAL	(R4)
   515	
   516		// Set m->sched.sp = SP, so that if a panic happens
   517		// during the function we are about to execute, it will
   518		// have a valid SP to run on the g0 stack.
   519		// The next few lines (after the havem label)
   520		// will save this SP onto the stack and then write
   521		// the same SP back to m->sched.sp. That seems redundant,
   522		// but if an unrecovered panic happens, unwindm will
   523		// restore the g->sched.sp from the stack location
   524		// and then systemstack will try to use it. If we don't set it here,
   525		// that restored SP will be uninitialized (typically 0) and
   526		// will not be usable.
   527		MOVV	g_m(g), R3
   528		MOVV	m_g0(R3), R1
   529		MOVV	R29, (g_sched+gobuf_sp)(R1)
   530	
   531	havem:
   532		// Now there's a valid m, and we're running on its m->g0.
   533		// Save current m->g0->sched.sp on stack and then set it to SP.
   534		// Save current sp in m->g0->sched.sp in preparation for
   535		// switch back to m->curg stack.
   536		// NOTE: unwindm knows that the saved g->sched.sp is at 8(R29) aka savedsp-16(SP).
   537		MOVV	m_g0(R3), R1
   538		MOVV	(g_sched+gobuf_sp)(R1), R2
   539		MOVV	R2, savedsp-16(SP)
   540		MOVV	R29, (g_sched+gobuf_sp)(R1)
   541	
   542		// Switch to m->curg stack and call runtime.cgocallbackg.
   543		// Because we are taking over the execution of m->curg
   544		// but *not* resuming what had been running, we need to
   545		// save that information (m->curg->sched) so we can restore it.
   546		// We can restore m->curg->sched.sp easily, because calling
   547		// runtime.cgocallbackg leaves SP unchanged upon return.
   548		// To save m->curg->sched.pc, we push it onto the stack.
   549		// This has the added benefit that it looks to the traceback
   550		// routine like cgocallbackg is going to return to that
   551		// PC (because the frame we allocate below has the same
   552		// size as cgocallback_gofunc's frame declared above)
   553		// so that the traceback will seamlessly trace back into
   554		// the earlier calls.
   555		//
   556		// In the new goroutine, -8(SP) is unused (where SP refers to
   557		// m->curg's SP while we're setting it up, before we've adjusted it).
   558		MOVV	m_curg(R3), g
   559		JAL	runtime·save_g(SB)
   560		MOVV	(g_sched+gobuf_sp)(g), R2 // prepare stack as R2
   561		MOVV	(g_sched+gobuf_pc)(g), R4
   562		MOVV	R4, -24(R2)
   563		MOVV    ctxt+24(FP), R1
   564		MOVV    R1, -16(R2)
   565		MOVV	$-24(R2), R29
   566		JAL	runtime·cgocallbackg(SB)
   567	
   568		// Restore g->sched (== m->curg->sched) from saved values.
   569		MOVV	0(R29), R4
   570		MOVV	R4, (g_sched+gobuf_pc)(g)
   571		MOVV	$24(R29), R2
   572		MOVV	R2, (g_sched+gobuf_sp)(g)
   573	
   574		// Switch back to m->g0's stack and restore m->g0->sched.sp.
   575		// (Unlike m->curg, the g0 goroutine never uses sched.pc,
   576		// so we do not have to restore it.)
   577		MOVV	g_m(g), R3
   578		MOVV	m_g0(R3), g
   579		JAL	runtime·save_g(SB)
   580		MOVV	(g_sched+gobuf_sp)(g), R29
   581		MOVV	savedsp-16(SP), R2
   582		MOVV	R2, (g_sched+gobuf_sp)(g)
   583	
   584		// If the m on entry was nil, we called needm above to borrow an m
   585		// for the duration of the call. Since the call is over, return it with dropm.
   586		MOVV	savedm-8(SP), R3
   587		BNE	R3, droppedm
   588		MOVV	$runtime·dropm(SB), R4
   589		JAL	(R4)
   590	droppedm:
   591	
   592		// Done!
   593		RET
   594	
   595	// void setg(G*); set g. for use by needm.
   596	TEXT runtime·setg(SB), NOSPLIT, $0-8
   597		MOVV	gg+0(FP), g
   598		// This only happens if iscgo, so jump straight to save_g
   599		JAL	runtime·save_g(SB)
   600		RET
   601	
   602	// void setg_gcc(G*); set g called from gcc with g in R1
   603	TEXT setg_gcc<>(SB),NOSPLIT,$0-0
   604		MOVV	R1, g
   605		JAL	runtime·save_g(SB)
   606		RET
   607	
   608	TEXT runtime·abort(SB),NOSPLIT|NOFRAME,$0-0
   609		MOVW	(R0), R0
   610		UNDEF
   611	
   612	// AES hashing not implemented for mips64
   613	TEXT runtime·aeshash(SB),NOSPLIT|NOFRAME,$0-0
   614		MOVW	(R0), R1
   615	TEXT runtime·aeshash32(SB),NOSPLIT|NOFRAME,$0-0
   616		MOVW	(R0), R1
   617	TEXT runtime·aeshash64(SB),NOSPLIT|NOFRAME,$0-0
   618		MOVW	(R0), R1
   619	TEXT runtime·aeshashstr(SB),NOSPLIT|NOFRAME,$0-0
   620		MOVW	(R0), R1
   621	
   622	TEXT runtime·return0(SB), NOSPLIT, $0
   623		MOVW	$0, R1
   624		RET
   625	
   626	// Called from cgo wrappers, this function returns g->m->curg.stack.hi.
   627	// Must obey the gcc calling convention.
   628	TEXT _cgo_topofstack(SB),NOSPLIT,$16
   629		// g (R30) and REGTMP (R23)  might be clobbered by load_g. They
   630		// are callee-save in the gcc calling convention, so save them.
   631		MOVV	R23, savedR23-16(SP)
   632		MOVV	g, savedG-8(SP)
   633	
   634		JAL	runtime·load_g(SB)
   635		MOVV	g_m(g), R1
   636		MOVV	m_curg(R1), R1
   637		MOVV	(g_stack+stack_hi)(R1), R2 // return value in R2
   638	
   639		MOVV	savedG-8(SP), g
   640		MOVV	savedR23-16(SP), R23
   641		RET
   642	
   643	// The top-most function running on a goroutine
   644	// returns to goexit+PCQuantum.
   645	TEXT runtime·goexit(SB),NOSPLIT|NOFRAME|TOPFRAME,$0-0
   646		NOR	R0, R0	// NOP
   647		JAL	runtime·goexit1(SB)	// does not return
   648		// traceback from goexit1 must hit code range of goexit
   649		NOR	R0, R0	// NOP
   650	
   651	TEXT ·checkASM(SB),NOSPLIT,$0-1
   652		MOVW	$1, R1
   653		MOVB	R1, ret+0(FP)
   654		RET
   655	
   656	// gcWriteBarrier performs a heap pointer write and informs the GC.
   657	//
   658	// gcWriteBarrier does NOT follow the Go ABI. It takes two arguments:
   659	// - R20 is the destination of the write
   660	// - R21 is the value being written at R20.
   661	// It clobbers R23 (the linker temp register).
   662	// The act of CALLing gcWriteBarrier will clobber R31 (LR).
   663	// It does not clobber any other general-purpose registers,
   664	// but may clobber others (e.g., floating point registers).
   665	TEXT runtime·gcWriteBarrier(SB),NOSPLIT,$192
   666		// Save the registers clobbered by the fast path.
   667		MOVV	R1, 184(R29)
   668		MOVV	R2, 192(R29)
   669		MOVV	g_m(g), R1
   670		MOVV	m_p(R1), R1
   671		MOVV	(p_wbBuf+wbBuf_next)(R1), R2
   672		// Increment wbBuf.next position.
   673		ADDV	$16, R2
   674		MOVV	R2, (p_wbBuf+wbBuf_next)(R1)
   675		MOVV	(p_wbBuf+wbBuf_end)(R1), R1
   676		MOVV	R1, R23		// R23 is linker temp register
   677		// Record the write.
   678		MOVV	R21, -16(R2)	// Record value
   679		MOVV	(R20), R1	// TODO: This turns bad writes into bad reads.
   680		MOVV	R1, -8(R2)	// Record *slot
   681		// Is the buffer full?
   682		BEQ	R2, R23, flush
   683	ret:
   684		MOVV	184(R29), R1
   685		MOVV	192(R29), R2
   686		// Do the write.
   687		MOVV	R21, (R20)
   688		RET
   689	
   690	flush:
   691		// Save all general purpose registers since these could be
   692		// clobbered by wbBufFlush and were not saved by the caller.
   693		MOVV	R20, 8(R29)	// Also first argument to wbBufFlush
   694		MOVV	R21, 16(R29)	// Also second argument to wbBufFlush
   695		// R1 already saved
   696		// R2 already saved
   697		MOVV	R3, 24(R29)
   698		MOVV	R4, 32(R29)
   699		MOVV	R5, 40(R29)
   700		MOVV	R6, 48(R29)
   701		MOVV	R7, 56(R29)
   702		MOVV	R8, 64(R29)
   703		MOVV	R9, 72(R29)
   704		MOVV	R10, 80(R29)
   705		MOVV	R11, 88(R29)
   706		MOVV	R12, 96(R29)
   707		MOVV	R13, 104(R29)
   708		MOVV	R14, 112(R29)
   709		MOVV	R15, 120(R29)
   710		MOVV	R16, 128(R29)
   711		MOVV	R17, 136(R29)
   712		MOVV	R18, 144(R29)
   713		MOVV	R19, 152(R29)
   714		// R20 already saved
   715		// R21 already saved.
   716		MOVV	R22, 160(R29)
   717		// R23 is tmp register.
   718		MOVV	R24, 168(R29)
   719		MOVV	R25, 176(R29)
   720		// R26 is reserved by kernel.
   721		// R27 is reserved by kernel.
   722		// R28 is REGSB (not modified by Go code).
   723		// R29 is SP.
   724		// R30 is g.
   725		// R31 is LR, which was saved by the prologue.
   726	
   727		// This takes arguments R20 and R21.
   728		CALL	runtime·wbBufFlush(SB)
   729	
   730		MOVV	8(R29), R20
   731		MOVV	16(R29), R21
   732		MOVV	24(R29), R3
   733		MOVV	32(R29), R4
   734		MOVV	40(R29), R5
   735		MOVV	48(R29), R6
   736		MOVV	56(R29), R7
   737		MOVV	64(R29), R8
   738		MOVV	72(R29), R9
   739		MOVV	80(R29), R10
   740		MOVV	88(R29), R11
   741		MOVV	96(R29), R12
   742		MOVV	104(R29), R13
   743		MOVV	112(R29), R14
   744		MOVV	120(R29), R15
   745		MOVV	128(R29), R16
   746		MOVV	136(R29), R17
   747		MOVV	144(R29), R18
   748		MOVV	152(R29), R19
   749		MOVV	160(R29), R22
   750		MOVV	168(R29), R24
   751		MOVV	176(R29), R25
   752		JMP	ret
   753	
   754	// Note: these functions use a special calling convention to save generated code space.
   755	// Arguments are passed in registers, but the space for those arguments are allocated
   756	// in the caller's stack frame. These stubs write the args into that stack space and
   757	// then tail call to the corresponding runtime handler.
   758	// The tail call makes these stubs disappear in backtraces.
   759	TEXT runtime·panicIndex(SB),NOSPLIT,$0-16
   760		MOVV	R1, x+0(FP)
   761		MOVV	R2, y+8(FP)
   762		JMP	runtime·goPanicIndex(SB)
   763	TEXT runtime·panicIndexU(SB),NOSPLIT,$0-16
   764		MOVV	R1, x+0(FP)
   765		MOVV	R2, y+8(FP)
   766		JMP	runtime·goPanicIndexU(SB)
   767	TEXT runtime·panicSliceAlen(SB),NOSPLIT,$0-16
   768		MOVV	R2, x+0(FP)
   769		MOVV	R3, y+8(FP)
   770		JMP	runtime·goPanicSliceAlen(SB)
   771	TEXT runtime·panicSliceAlenU(SB),NOSPLIT,$0-16
   772		MOVV	R2, x+0(FP)
   773		MOVV	R3, y+8(FP)
   774		JMP	runtime·goPanicSliceAlenU(SB)
   775	TEXT runtime·panicSliceAcap(SB),NOSPLIT,$0-16
   776		MOVV	R2, x+0(FP)
   777		MOVV	R3, y+8(FP)
   778		JMP	runtime·goPanicSliceAcap(SB)
   779	TEXT runtime·panicSliceAcapU(SB),NOSPLIT,$0-16
   780		MOVV	R2, x+0(FP)
   781		MOVV	R3, y+8(FP)
   782		JMP	runtime·goPanicSliceAcapU(SB)
   783	TEXT runtime·panicSliceB(SB),NOSPLIT,$0-16
   784		MOVV	R1, x+0(FP)
   785		MOVV	R2, y+8(FP)
   786		JMP	runtime·goPanicSliceB(SB)
   787	TEXT runtime·panicSliceBU(SB),NOSPLIT,$0-16
   788		MOVV	R1, x+0(FP)
   789		MOVV	R2, y+8(FP)
   790		JMP	runtime·goPanicSliceBU(SB)
   791	TEXT runtime·panicSlice3Alen(SB),NOSPLIT,$0-16
   792		MOVV	R3, x+0(FP)
   793		MOVV	R4, y+8(FP)
   794		JMP	runtime·goPanicSlice3Alen(SB)
   795	TEXT runtime·panicSlice3AlenU(SB),NOSPLIT,$0-16
   796		MOVV	R3, x+0(FP)
   797		MOVV	R4, y+8(FP)
   798		JMP	runtime·goPanicSlice3AlenU(SB)
   799	TEXT runtime·panicSlice3Acap(SB),NOSPLIT,$0-16
   800		MOVV	R3, x+0(FP)
   801		MOVV	R4, y+8(FP)
   802		JMP	runtime·goPanicSlice3Acap(SB)
   803	TEXT runtime·panicSlice3AcapU(SB),NOSPLIT,$0-16
   804		MOVV	R3, x+0(FP)
   805		MOVV	R4, y+8(FP)
   806		JMP	runtime·goPanicSlice3AcapU(SB)
   807	TEXT runtime·panicSlice3B(SB),NOSPLIT,$0-16
   808		MOVV	R2, x+0(FP)
   809		MOVV	R3, y+8(FP)
   810		JMP	runtime·goPanicSlice3B(SB)
   811	TEXT runtime·panicSlice3BU(SB),NOSPLIT,$0-16
   812		MOVV	R2, x+0(FP)
   813		MOVV	R3, y+8(FP)
   814		JMP	runtime·goPanicSlice3BU(SB)
   815	TEXT runtime·panicSlice3C(SB),NOSPLIT,$0-16
   816		MOVV	R1, x+0(FP)
   817		MOVV	R2, y+8(FP)
   818		JMP	runtime·goPanicSlice3C(SB)
   819	TEXT runtime·panicSlice3CU(SB),NOSPLIT,$0-16
   820		MOVV	R1, x+0(FP)
   821		MOVV	R2, y+8(FP)
   822		JMP	runtime·goPanicSlice3CU(SB)

View as plain text