...
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|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 reflect·call(SB), NOSPLIT, $0-0
   296		JMP	·reflectcall(SB)
   297	
   298	TEXT ·reflectcall(SB), NOSPLIT|NOFRAME, $0-32
   299		MOVWU argsize+24(FP), R1
   300		DISPATCH(runtime·call32, 32)
   301		DISPATCH(runtime·call64, 64)
   302		DISPATCH(runtime·call128, 128)
   303		DISPATCH(runtime·call256, 256)
   304		DISPATCH(runtime·call512, 512)
   305		DISPATCH(runtime·call1024, 1024)
   306		DISPATCH(runtime·call2048, 2048)
   307		DISPATCH(runtime·call4096, 4096)
   308		DISPATCH(runtime·call8192, 8192)
   309		DISPATCH(runtime·call16384, 16384)
   310		DISPATCH(runtime·call32768, 32768)
   311		DISPATCH(runtime·call65536, 65536)
   312		DISPATCH(runtime·call131072, 131072)
   313		DISPATCH(runtime·call262144, 262144)
   314		DISPATCH(runtime·call524288, 524288)
   315		DISPATCH(runtime·call1048576, 1048576)
   316		DISPATCH(runtime·call2097152, 2097152)
   317		DISPATCH(runtime·call4194304, 4194304)
   318		DISPATCH(runtime·call8388608, 8388608)
   319		DISPATCH(runtime·call16777216, 16777216)
   320		DISPATCH(runtime·call33554432, 33554432)
   321		DISPATCH(runtime·call67108864, 67108864)
   322		DISPATCH(runtime·call134217728, 134217728)
   323		DISPATCH(runtime·call268435456, 268435456)
   324		DISPATCH(runtime·call536870912, 536870912)
   325		DISPATCH(runtime·call1073741824, 1073741824)
   326		MOVV	$runtime·badreflectcall(SB), R4
   327		JMP	(R4)
   328	
   329	#define CALLFN(NAME,MAXSIZE)			\
   330	TEXT NAME(SB), WRAPPER, $MAXSIZE-24;		\
   331		NO_LOCAL_POINTERS;			\
   332		/* copy arguments to stack */		\
   333		MOVV	arg+16(FP), R1;			\
   334		MOVWU	argsize+24(FP), R2;			\
   335		MOVV	R29, R3;				\
   336		ADDV	$8, R3;			\
   337		ADDV	R3, R2;				\
   338		BEQ	R3, R2, 6(PC);				\
   339		MOVBU	(R1), R4;			\
   340		ADDV	$1, R1;			\
   341		MOVBU	R4, (R3);			\
   342		ADDV	$1, R3;			\
   343		JMP	-5(PC);				\
   344		/* call function */			\
   345		MOVV	f+8(FP), REGCTXT;			\
   346		MOVV	(REGCTXT), R4;			\
   347		PCDATA  $PCDATA_StackMapIndex, $0;	\
   348		JAL	(R4);				\
   349		/* copy return values back */		\
   350		MOVV	argtype+0(FP), R5;		\
   351		MOVV	arg+16(FP), R1;			\
   352		MOVWU	n+24(FP), R2;			\
   353		MOVWU	retoffset+28(FP), R4;		\
   354		ADDV	$8, R29, R3;				\
   355		ADDV	R4, R3; 			\
   356		ADDV	R4, R1;				\
   357		SUBVU	R4, R2;				\
   358		JAL	callRet<>(SB);			\
   359		RET
   360	
   361	// callRet copies return values back at the end of call*. This is a
   362	// separate function so it can allocate stack space for the arguments
   363	// to reflectcallmove. It does not follow the Go ABI; it expects its
   364	// arguments in registers.
   365	TEXT callRet<>(SB), NOSPLIT, $32-0
   366		MOVV	R5, 8(R29)
   367		MOVV	R1, 16(R29)
   368		MOVV	R3, 24(R29)
   369		MOVV	R2, 32(R29)
   370		JAL	runtime·reflectcallmove(SB)
   371		RET
   372	
   373	CALLFN(·call16, 16)
   374	CALLFN(·call32, 32)
   375	CALLFN(·call64, 64)
   376	CALLFN(·call128, 128)
   377	CALLFN(·call256, 256)
   378	CALLFN(·call512, 512)
   379	CALLFN(·call1024, 1024)
   380	CALLFN(·call2048, 2048)
   381	CALLFN(·call4096, 4096)
   382	CALLFN(·call8192, 8192)
   383	CALLFN(·call16384, 16384)
   384	CALLFN(·call32768, 32768)
   385	CALLFN(·call65536, 65536)
   386	CALLFN(·call131072, 131072)
   387	CALLFN(·call262144, 262144)
   388	CALLFN(·call524288, 524288)
   389	CALLFN(·call1048576, 1048576)
   390	CALLFN(·call2097152, 2097152)
   391	CALLFN(·call4194304, 4194304)
   392	CALLFN(·call8388608, 8388608)
   393	CALLFN(·call16777216, 16777216)
   394	CALLFN(·call33554432, 33554432)
   395	CALLFN(·call67108864, 67108864)
   396	CALLFN(·call134217728, 134217728)
   397	CALLFN(·call268435456, 268435456)
   398	CALLFN(·call536870912, 536870912)
   399	CALLFN(·call1073741824, 1073741824)
   400	
   401	TEXT runtime·procyield(SB),NOSPLIT,$0-0
   402		RET
   403	
   404	// void jmpdefer(fv, sp);
   405	// called from deferreturn.
   406	// 1. grab stored LR for caller
   407	// 2. sub 8 bytes to get back to JAL deferreturn
   408	// 3. JMP to fn
   409	TEXT runtime·jmpdefer(SB), NOSPLIT|NOFRAME, $0-16
   410		MOVV	0(R29), R31
   411		ADDV	$-8, R31
   412	
   413		MOVV	fv+0(FP), REGCTXT
   414		MOVV	argp+8(FP), R29
   415		ADDV	$-8, R29
   416		NOR	R0, R0	// prevent scheduling
   417		MOVV	0(REGCTXT), R4
   418		JMP	(R4)
   419	
   420	// Save state of caller into g->sched. Smashes R1.
   421	TEXT gosave<>(SB),NOSPLIT|NOFRAME,$0
   422		MOVV	R31, (g_sched+gobuf_pc)(g)
   423		MOVV	R29, (g_sched+gobuf_sp)(g)
   424		MOVV	R0, (g_sched+gobuf_lr)(g)
   425		MOVV	R0, (g_sched+gobuf_ret)(g)
   426		// Assert ctxt is zero. See func save.
   427		MOVV	(g_sched+gobuf_ctxt)(g), R1
   428		BEQ	R1, 2(PC)
   429		JAL	runtime·badctxt(SB)
   430		RET
   431	
   432	// func asmcgocall(fn, arg unsafe.Pointer) int32
   433	// Call fn(arg) on the scheduler stack,
   434	// aligned appropriately for the gcc ABI.
   435	// See cgocall.go for more details.
   436	TEXT ·asmcgocall(SB),NOSPLIT,$0-20
   437		MOVV	fn+0(FP), R25
   438		MOVV	arg+8(FP), R4
   439	
   440		MOVV	R29, R3	// save original stack pointer
   441		MOVV	g, R2
   442	
   443		// Figure out if we need to switch to m->g0 stack.
   444		// We get called to create new OS threads too, and those
   445		// come in on the m->g0 stack already.
   446		MOVV	g_m(g), R5
   447		MOVV	m_g0(R5), R6
   448		BEQ	R6, g, g0
   449	
   450		JAL	gosave<>(SB)
   451		MOVV	R6, g
   452		JAL	runtime·save_g(SB)
   453		MOVV	(g_sched+gobuf_sp)(g), R29
   454	
   455		// Now on a scheduling stack (a pthread-created stack).
   456	g0:
   457		// Save room for two of our pointers.
   458		ADDV	$-16, R29
   459		MOVV	R2, 0(R29)	// save old g on stack
   460		MOVV	(g_stack+stack_hi)(R2), R2
   461		SUBVU	R3, R2
   462		MOVV	R2, 8(R29)	// save depth in old g stack (can't just save SP, as stack might be copied during a callback)
   463		JAL	(R25)
   464	
   465		// Restore g, stack pointer. R2 is return value.
   466		MOVV	0(R29), g
   467		JAL	runtime·save_g(SB)
   468		MOVV	(g_stack+stack_hi)(g), R5
   469		MOVV	8(R29), R6
   470		SUBVU	R6, R5
   471		MOVV	R5, R29
   472	
   473		MOVW	R2, ret+16(FP)
   474		RET
   475	
   476	// cgocallback(void (*fn)(void*), void *frame, uintptr framesize, uintptr ctxt)
   477	// Turn the fn into a Go func (by taking its address) and call
   478	// cgocallback_gofunc.
   479	TEXT runtime·cgocallback(SB),NOSPLIT,$32-32
   480		MOVV	$fn+0(FP), R1
   481		MOVV	R1, 8(R29)
   482		MOVV	frame+8(FP), R1
   483		MOVV	R1, 16(R29)
   484		MOVV	framesize+16(FP), R1
   485		MOVV	R1, 24(R29)
   486		MOVV	ctxt+24(FP), R1
   487		MOVV	R1, 32(R29)
   488		MOVV	$runtime·cgocallback_gofunc(SB), R1
   489		JAL	(R1)
   490		RET
   491	
   492	// cgocallback_gofunc(FuncVal*, void *frame, uintptr framesize, uintptr ctxt)
   493	// See cgocall.go for more details.
   494	TEXT ·cgocallback_gofunc(SB),NOSPLIT,$16-32
   495		NO_LOCAL_POINTERS
   496	
   497		// Load m and g from thread-local storage.
   498		MOVB	runtime·iscgo(SB), R1
   499		BEQ	R1, nocgo
   500		JAL	runtime·load_g(SB)
   501	nocgo:
   502	
   503		// If g is nil, Go did not create the current thread.
   504		// Call needm to obtain one for temporary use.
   505		// In this case, we're running on the thread stack, so there's
   506		// lots of space, but the linker doesn't know. Hide the call from
   507		// the linker analysis by using an indirect call.
   508		BEQ	g, needm
   509	
   510		MOVV	g_m(g), R3
   511		MOVV	R3, savedm-8(SP)
   512		JMP	havem
   513	
   514	needm:
   515		MOVV	g, savedm-8(SP) // g is zero, so is m.
   516		MOVV	$runtime·needm(SB), R4
   517		JAL	(R4)
   518	
   519		// Set m->sched.sp = SP, so that if a panic happens
   520		// during the function we are about to execute, it will
   521		// have a valid SP to run on the g0 stack.
   522		// The next few lines (after the havem label)
   523		// will save this SP onto the stack and then write
   524		// the same SP back to m->sched.sp. That seems redundant,
   525		// but if an unrecovered panic happens, unwindm will
   526		// restore the g->sched.sp from the stack location
   527		// and then systemstack will try to use it. If we don't set it here,
   528		// that restored SP will be uninitialized (typically 0) and
   529		// will not be usable.
   530		MOVV	g_m(g), R3
   531		MOVV	m_g0(R3), R1
   532		MOVV	R29, (g_sched+gobuf_sp)(R1)
   533	
   534	havem:
   535		// Now there's a valid m, and we're running on its m->g0.
   536		// Save current m->g0->sched.sp on stack and then set it to SP.
   537		// Save current sp in m->g0->sched.sp in preparation for
   538		// switch back to m->curg stack.
   539		// NOTE: unwindm knows that the saved g->sched.sp is at 8(R29) aka savedsp-16(SP).
   540		MOVV	m_g0(R3), R1
   541		MOVV	(g_sched+gobuf_sp)(R1), R2
   542		MOVV	R2, savedsp-16(SP)
   543		MOVV	R29, (g_sched+gobuf_sp)(R1)
   544	
   545		// Switch to m->curg stack and call runtime.cgocallbackg.
   546		// Because we are taking over the execution of m->curg
   547		// but *not* resuming what had been running, we need to
   548		// save that information (m->curg->sched) so we can restore it.
   549		// We can restore m->curg->sched.sp easily, because calling
   550		// runtime.cgocallbackg leaves SP unchanged upon return.
   551		// To save m->curg->sched.pc, we push it onto the stack.
   552		// This has the added benefit that it looks to the traceback
   553		// routine like cgocallbackg is going to return to that
   554		// PC (because the frame we allocate below has the same
   555		// size as cgocallback_gofunc's frame declared above)
   556		// so that the traceback will seamlessly trace back into
   557		// the earlier calls.
   558		//
   559		// In the new goroutine, -8(SP) is unused (where SP refers to
   560		// m->curg's SP while we're setting it up, before we've adjusted it).
   561		MOVV	m_curg(R3), g
   562		JAL	runtime·save_g(SB)
   563		MOVV	(g_sched+gobuf_sp)(g), R2 // prepare stack as R2
   564		MOVV	(g_sched+gobuf_pc)(g), R4
   565		MOVV	R4, -24(R2)
   566		MOVV    ctxt+24(FP), R1
   567		MOVV    R1, -16(R2)
   568		MOVV	$-24(R2), R29
   569		JAL	runtime·cgocallbackg(SB)
   570	
   571		// Restore g->sched (== m->curg->sched) from saved values.
   572		MOVV	0(R29), R4
   573		MOVV	R4, (g_sched+gobuf_pc)(g)
   574		MOVV	$24(R29), R2
   575		MOVV	R2, (g_sched+gobuf_sp)(g)
   576	
   577		// Switch back to m->g0's stack and restore m->g0->sched.sp.
   578		// (Unlike m->curg, the g0 goroutine never uses sched.pc,
   579		// so we do not have to restore it.)
   580		MOVV	g_m(g), R3
   581		MOVV	m_g0(R3), g
   582		JAL	runtime·save_g(SB)
   583		MOVV	(g_sched+gobuf_sp)(g), R29
   584		MOVV	savedsp-16(SP), R2
   585		MOVV	R2, (g_sched+gobuf_sp)(g)
   586	
   587		// If the m on entry was nil, we called needm above to borrow an m
   588		// for the duration of the call. Since the call is over, return it with dropm.
   589		MOVV	savedm-8(SP), R3
   590		BNE	R3, droppedm
   591		MOVV	$runtime·dropm(SB), R4
   592		JAL	(R4)
   593	droppedm:
   594	
   595		// Done!
   596		RET
   597	
   598	// void setg(G*); set g. for use by needm.
   599	TEXT runtime·setg(SB), NOSPLIT, $0-8
   600		MOVV	gg+0(FP), g
   601		// This only happens if iscgo, so jump straight to save_g
   602		JAL	runtime·save_g(SB)
   603		RET
   604	
   605	// void setg_gcc(G*); set g called from gcc with g in R1
   606	TEXT setg_gcc<>(SB),NOSPLIT,$0-0
   607		MOVV	R1, g
   608		JAL	runtime·save_g(SB)
   609		RET
   610	
   611	TEXT runtime·abort(SB),NOSPLIT|NOFRAME,$0-0
   612		MOVW	(R0), R0
   613		UNDEF
   614	
   615	// AES hashing not implemented for mips64
   616	TEXT runtime·aeshash(SB),NOSPLIT|NOFRAME,$0-0
   617		MOVW	(R0), R1
   618	TEXT runtime·aeshash32(SB),NOSPLIT|NOFRAME,$0-0
   619		MOVW	(R0), R1
   620	TEXT runtime·aeshash64(SB),NOSPLIT|NOFRAME,$0-0
   621		MOVW	(R0), R1
   622	TEXT runtime·aeshashstr(SB),NOSPLIT|NOFRAME,$0-0
   623		MOVW	(R0), R1
   624	
   625	TEXT runtime·return0(SB), NOSPLIT, $0
   626		MOVW	$0, R1
   627		RET
   628	
   629	// Called from cgo wrappers, this function returns g->m->curg.stack.hi.
   630	// Must obey the gcc calling convention.
   631	TEXT _cgo_topofstack(SB),NOSPLIT,$16
   632		// g (R30) and REGTMP (R23)  might be clobbered by load_g. They
   633		// are callee-save in the gcc calling convention, so save them.
   634		MOVV	R23, savedR23-16(SP)
   635		MOVV	g, savedG-8(SP)
   636	
   637		JAL	runtime·load_g(SB)
   638		MOVV	g_m(g), R1
   639		MOVV	m_curg(R1), R1
   640		MOVV	(g_stack+stack_hi)(R1), R2 // return value in R2
   641	
   642		MOVV	savedG-8(SP), g
   643		MOVV	savedR23-16(SP), R23
   644		RET
   645	
   646	// The top-most function running on a goroutine
   647	// returns to goexit+PCQuantum.
   648	TEXT runtime·goexit(SB),NOSPLIT|NOFRAME,$0-0
   649		NOR	R0, R0	// NOP
   650		JAL	runtime·goexit1(SB)	// does not return
   651		// traceback from goexit1 must hit code range of goexit
   652		NOR	R0, R0	// NOP
   653	
   654	TEXT ·checkASM(SB),NOSPLIT,$0-1
   655		MOVW	$1, R1
   656		MOVB	R1, ret+0(FP)
   657		RET
   658	
   659	// gcWriteBarrier performs a heap pointer write and informs the GC.
   660	//
   661	// gcWriteBarrier does NOT follow the Go ABI. It takes two arguments:
   662	// - R20 is the destination of the write
   663	// - R21 is the value being written at R20.
   664	// It clobbers R23 (the linker temp register).
   665	// The act of CALLing gcWriteBarrier will clobber R31 (LR).
   666	// It does not clobber any other general-purpose registers,
   667	// but may clobber others (e.g., floating point registers).
   668	TEXT runtime·gcWriteBarrier(SB),NOSPLIT,$192
   669		// Save the registers clobbered by the fast path.
   670		MOVV	R1, 184(R29)
   671		MOVV	R2, 192(R29)
   672		MOVV	g_m(g), R1
   673		MOVV	m_p(R1), R1
   674		MOVV	(p_wbBuf+wbBuf_next)(R1), R2
   675		// Increment wbBuf.next position.
   676		ADDV	$16, R2
   677		MOVV	R2, (p_wbBuf+wbBuf_next)(R1)
   678		MOVV	(p_wbBuf+wbBuf_end)(R1), R1
   679		MOVV	R1, R23		// R23 is linker temp register
   680		// Record the write.
   681		MOVV	R21, -16(R2)	// Record value
   682		MOVV	(R20), R1	// TODO: This turns bad writes into bad reads.
   683		MOVV	R1, -8(R2)	// Record *slot
   684		// Is the buffer full?
   685		BEQ	R2, R23, flush
   686	ret:
   687		MOVV	184(R29), R1
   688		MOVV	192(R29), R2
   689		// Do the write.
   690		MOVV	R21, (R20)
   691		RET
   692	
   693	flush:
   694		// Save all general purpose registers since these could be
   695		// clobbered by wbBufFlush and were not saved by the caller.
   696		MOVV	R20, 8(R29)	// Also first argument to wbBufFlush
   697		MOVV	R21, 16(R29)	// Also second argument to wbBufFlush
   698		// R1 already saved
   699		// R2 already saved
   700		MOVV	R3, 24(R29)
   701		MOVV	R4, 32(R29)
   702		MOVV	R5, 40(R29)
   703		MOVV	R6, 48(R29)
   704		MOVV	R7, 56(R29)
   705		MOVV	R8, 64(R29)
   706		MOVV	R9, 72(R29)
   707		MOVV	R10, 80(R29)
   708		MOVV	R11, 88(R29)
   709		MOVV	R12, 96(R29)
   710		MOVV	R13, 104(R29)
   711		MOVV	R14, 112(R29)
   712		MOVV	R15, 120(R29)
   713		MOVV	R16, 128(R29)
   714		MOVV	R17, 136(R29)
   715		MOVV	R18, 144(R29)
   716		MOVV	R19, 152(R29)
   717		// R20 already saved
   718		// R21 already saved.
   719		MOVV	R22, 160(R29)
   720		// R23 is tmp register.
   721		MOVV	R24, 168(R29)
   722		MOVV	R25, 176(R29)
   723		// R26 is reserved by kernel.
   724		// R27 is reserved by kernel.
   725		// R28 is REGSB (not modified by Go code).
   726		// R29 is SP.
   727		// R30 is g.
   728		// R31 is LR, which was saved by the prologue.
   729	
   730		// This takes arguments R20 and R21.
   731		CALL	runtime·wbBufFlush(SB)
   732	
   733		MOVV	8(R29), R20
   734		MOVV	16(R29), R21
   735		MOVV	24(R29), R3
   736		MOVV	32(R29), R4
   737		MOVV	40(R29), R5
   738		MOVV	48(R29), R6
   739		MOVV	56(R29), R7
   740		MOVV	64(R29), R8
   741		MOVV	72(R29), R9
   742		MOVV	80(R29), R10
   743		MOVV	88(R29), R11
   744		MOVV	96(R29), R12
   745		MOVV	104(R29), R13
   746		MOVV	112(R29), R14
   747		MOVV	120(R29), R15
   748		MOVV	128(R29), R16
   749		MOVV	136(R29), R17
   750		MOVV	144(R29), R18
   751		MOVV	152(R29), R19
   752		MOVV	160(R29), R22
   753		MOVV	168(R29), R24
   754		MOVV	176(R29), R25
   755		JMP	ret

View as plain text