...

Text file src/runtime/asm_mipsx.s

     1	// Copyright 2016 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 mips mipsle
     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		ADDU	$-12, R29
    18		MOVW	R4, 4(R29)	// argc
    19		MOVW	R5, 8(R29)	// argv
    20	
    21		// create istack out of the given (operating system) stack.
    22		// _cgo_init may update stackguard.
    23		MOVW	$runtime·g0(SB), g
    24		MOVW	$(-64*1024), R23
    25		ADD	R23, R29, R1
    26		MOVW	R1, g_stackguard0(g)
    27		MOVW	R1, g_stackguard1(g)
    28		MOVW	R1, (g_stack+stack_lo)(g)
    29		MOVW	R29, (g_stack+stack_hi)(g)
    30	
    31		// if there is a _cgo_init, call it using the gcc ABI.
    32		MOVW	_cgo_init(SB), R25
    33		BEQ	R25, nocgo
    34		ADDU	$-16, R29
    35		MOVW	R0, R7	// arg 3: not used
    36		MOVW	R0, R6	// arg 2: not used
    37		MOVW	$setg_gcc<>(SB), R5	// arg 1: setg
    38		MOVW	g, R4	// arg 0: G
    39		JAL	(R25)
    40		ADDU	$16, R29
    41	
    42	nocgo:
    43		// update stackguard after _cgo_init
    44		MOVW	(g_stack+stack_lo)(g), R1
    45		ADD	$const__StackGuard, R1
    46		MOVW	R1, g_stackguard0(g)
    47		MOVW	R1, g_stackguard1(g)
    48	
    49		// set the per-goroutine and per-mach "registers"
    50		MOVW	$runtime·m0(SB), R1
    51	
    52		// save m->g0 = g0
    53		MOVW	g, m_g0(R1)
    54		// save m0 to g0->m
    55		MOVW	R1, g_m(g)
    56	
    57		JAL	runtime·check(SB)
    58	
    59		// args are already prepared
    60		JAL	runtime·args(SB)
    61		JAL	runtime·osinit(SB)
    62		JAL	runtime·schedinit(SB)
    63	
    64		// create a new goroutine to start program
    65		MOVW	$runtime·mainPC(SB), R1	// entry
    66		ADDU	$-12, R29
    67		MOVW	R1, 8(R29)
    68		MOVW	R0, 4(R29)
    69		MOVW	R0, 0(R29)
    70		JAL	runtime·newproc(SB)
    71		ADDU	$12, R29
    72	
    73		// start this M
    74		JAL	runtime·mstart(SB)
    75	
    76		UNDEF
    77		RET
    78	
    79	DATA	runtime·mainPC+0(SB)/4,$runtime·main(SB)
    80	GLOBL	runtime·mainPC(SB),RODATA,$4
    81	
    82	TEXT runtime·breakpoint(SB),NOSPLIT,$0-0
    83		BREAK
    84		RET
    85	
    86	TEXT runtime·asminit(SB),NOSPLIT,$0-0
    87		RET
    88	
    89	/*
    90	 *  go-routine
    91	 */
    92	
    93	// void gosave(Gobuf*)
    94	// save state in Gobuf; setjmp
    95	TEXT runtime·gosave(SB),NOSPLIT|NOFRAME,$0-4
    96		MOVW	buf+0(FP), R1
    97		MOVW	R29, gobuf_sp(R1)
    98		MOVW	R31, gobuf_pc(R1)
    99		MOVW	g, gobuf_g(R1)
   100		MOVW	R0, gobuf_lr(R1)
   101		MOVW	R0, gobuf_ret(R1)
   102		// Assert ctxt is zero. See func save.
   103		MOVW	gobuf_ctxt(R1), R1
   104		BEQ	R1, 2(PC)
   105		JAL	runtime·badctxt(SB)
   106		RET
   107	
   108	// void gogo(Gobuf*)
   109	// restore state from Gobuf; longjmp
   110	TEXT runtime·gogo(SB),NOSPLIT,$8-4
   111		MOVW	buf+0(FP), R3
   112		MOVW	gobuf_g(R3), g	// make sure g is not nil
   113		JAL	runtime·save_g(SB)
   114	
   115		MOVW	0(g), R2
   116		MOVW	gobuf_sp(R3), R29
   117		MOVW	gobuf_lr(R3), R31
   118		MOVW	gobuf_ret(R3), R1
   119		MOVW	gobuf_ctxt(R3), REGCTXT
   120		MOVW	R0, gobuf_sp(R3)
   121		MOVW	R0, gobuf_ret(R3)
   122		MOVW	R0, gobuf_lr(R3)
   123		MOVW	R0, gobuf_ctxt(R3)
   124		MOVW	gobuf_pc(R3), R4
   125		JMP	(R4)
   126	
   127	// void mcall(fn func(*g))
   128	// Switch to m->g0's stack, call fn(g).
   129	// Fn must never return. It should gogo(&g->sched)
   130	// to keep running g.
   131	TEXT runtime·mcall(SB),NOSPLIT|NOFRAME,$0-4
   132		// Save caller state in g->sched
   133		MOVW	R29, (g_sched+gobuf_sp)(g)
   134		MOVW	R31, (g_sched+gobuf_pc)(g)
   135		MOVW	R0, (g_sched+gobuf_lr)(g)
   136		MOVW	g, (g_sched+gobuf_g)(g)
   137	
   138		// Switch to m->g0 & its stack, call fn.
   139		MOVW	g, R1
   140		MOVW	g_m(g), R3
   141		MOVW	m_g0(R3), g
   142		JAL	runtime·save_g(SB)
   143		BNE	g, R1, 2(PC)
   144		JMP	runtime·badmcall(SB)
   145		MOVW	fn+0(FP), REGCTXT	// context
   146		MOVW	0(REGCTXT), R4	// code pointer
   147		MOVW	(g_sched+gobuf_sp)(g), R29	// sp = m->g0->sched.sp
   148		ADDU	$-8, R29	// make room for 1 arg and fake LR
   149		MOVW	R1, 4(R29)
   150		MOVW	R0, 0(R29)
   151		JAL	(R4)
   152		JMP	runtime·badmcall2(SB)
   153	
   154	// systemstack_switch is a dummy routine that systemstack leaves at the bottom
   155	// of the G stack.  We need to distinguish the routine that
   156	// lives at the bottom of the G stack from the one that lives
   157	// at the top of the system stack because the one at the top of
   158	// the system stack terminates the stack walk (see topofstack()).
   159	TEXT runtime·systemstack_switch(SB),NOSPLIT,$0-0
   160		UNDEF
   161		JAL	(R31)	// make sure this function is not leaf
   162		RET
   163	
   164	// func systemstack(fn func())
   165	TEXT runtime·systemstack(SB),NOSPLIT,$0-4
   166		MOVW	fn+0(FP), R1	// R1 = fn
   167		MOVW	R1, REGCTXT	// context
   168		MOVW	g_m(g), R2	// R2 = m
   169	
   170		MOVW	m_gsignal(R2), R3	// R3 = gsignal
   171		BEQ	g, R3, noswitch
   172	
   173		MOVW	m_g0(R2), R3	// R3 = g0
   174		BEQ	g, R3, noswitch
   175	
   176		MOVW	m_curg(R2), R4
   177		BEQ	g, R4, switch
   178	
   179		// Bad: g is not gsignal, not g0, not curg. What is it?
   180		// Hide call from linker nosplit analysis.
   181		MOVW	$runtime·badsystemstack(SB), R4
   182		JAL	(R4)
   183		JAL	runtime·abort(SB)
   184	
   185	switch:
   186		// save our state in g->sched.  Pretend to
   187		// be systemstack_switch if the G stack is scanned.
   188		MOVW	$runtime·systemstack_switch(SB), R4
   189		ADDU	$8, R4	// get past prologue
   190		MOVW	R4, (g_sched+gobuf_pc)(g)
   191		MOVW	R29, (g_sched+gobuf_sp)(g)
   192		MOVW	R0, (g_sched+gobuf_lr)(g)
   193		MOVW	g, (g_sched+gobuf_g)(g)
   194	
   195		// switch to g0
   196		MOVW	R3, g
   197		JAL	runtime·save_g(SB)
   198		MOVW	(g_sched+gobuf_sp)(g), R1
   199		// make it look like mstart called systemstack on g0, to stop traceback
   200		ADDU	$-4, R1
   201		MOVW	$runtime·mstart(SB), R2
   202		MOVW	R2, 0(R1)
   203		MOVW	R1, R29
   204	
   205		// call target function
   206		MOVW	0(REGCTXT), R4	// code pointer
   207		JAL	(R4)
   208	
   209		// switch back to g
   210		MOVW	g_m(g), R1
   211		MOVW	m_curg(R1), g
   212		JAL	runtime·save_g(SB)
   213		MOVW	(g_sched+gobuf_sp)(g), R29
   214		MOVW	R0, (g_sched+gobuf_sp)(g)
   215		RET
   216	
   217	noswitch:
   218		// already on m stack, just call directly
   219		// Using a tail call here cleans up tracebacks since we won't stop
   220		// at an intermediate systemstack.
   221		MOVW	0(REGCTXT), R4	// code pointer
   222		MOVW	0(R29), R31	// restore LR
   223		ADD	$4, R29
   224		JMP	(R4)
   225	
   226	/*
   227	 * support for morestack
   228	 */
   229	
   230	// Called during function prolog when more stack is needed.
   231	// Caller has already loaded:
   232	// R1: framesize, R2: argsize, R3: LR
   233	//
   234	// The traceback routines see morestack on a g0 as being
   235	// the top of a stack (for example, morestack calling newstack
   236	// calling the scheduler calling newm calling gc), so we must
   237	// record an argument size. For that purpose, it has no arguments.
   238	TEXT runtime·morestack(SB),NOSPLIT|NOFRAME,$0-0
   239		// Cannot grow scheduler stack (m->g0).
   240		MOVW	g_m(g), R7
   241		MOVW	m_g0(R7), R8
   242		BNE	g, R8, 3(PC)
   243		JAL	runtime·badmorestackg0(SB)
   244		JAL	runtime·abort(SB)
   245	
   246		// Cannot grow signal stack (m->gsignal).
   247		MOVW	m_gsignal(R7), R8
   248		BNE	g, R8, 3(PC)
   249		JAL	runtime·badmorestackgsignal(SB)
   250		JAL	runtime·abort(SB)
   251	
   252		// Called from f.
   253		// Set g->sched to context in f.
   254		MOVW	R29, (g_sched+gobuf_sp)(g)
   255		MOVW	R31, (g_sched+gobuf_pc)(g)
   256		MOVW	R3, (g_sched+gobuf_lr)(g)
   257		MOVW	REGCTXT, (g_sched+gobuf_ctxt)(g)
   258	
   259		// Called from f.
   260		// Set m->morebuf to f's caller.
   261		MOVW	R3, (m_morebuf+gobuf_pc)(R7)	// f's caller's PC
   262		MOVW	R29, (m_morebuf+gobuf_sp)(R7)	// f's caller's SP
   263		MOVW	g, (m_morebuf+gobuf_g)(R7)
   264	
   265		// Call newstack on m->g0's stack.
   266		MOVW	m_g0(R7), g
   267		JAL	runtime·save_g(SB)
   268		MOVW	(g_sched+gobuf_sp)(g), R29
   269		// Create a stack frame on g0 to call newstack.
   270		MOVW	R0, -4(R29)	// Zero saved LR in frame
   271		ADDU	$-4, R29
   272		JAL	runtime·newstack(SB)
   273	
   274		// Not reached, but make sure the return PC from the call to newstack
   275		// is still in this function, and not the beginning of the next.
   276		UNDEF
   277	
   278	TEXT runtime·morestack_noctxt(SB),NOSPLIT,$0-0
   279		MOVW	R0, REGCTXT
   280		JMP	runtime·morestack(SB)
   281	
   282	// reflectcall: call a function with the given argument list
   283	// func call(argtype *_type, f *FuncVal, arg *byte, argsize, retoffset uint32).
   284	// we don't have variable-sized frames, so we use a small number
   285	// of constant-sized-frame functions to encode a few bits of size in the pc.
   286	
   287	#define DISPATCH(NAME,MAXSIZE)	\
   288		MOVW	$MAXSIZE, R23;	\
   289		SGTU	R1, R23, R23;	\
   290		BNE	R23, 3(PC);	\
   291		MOVW	$NAME(SB), R4;	\
   292		JMP	(R4)
   293	
   294	TEXT ·reflectcall(SB),NOSPLIT|NOFRAME,$0-20
   295		MOVW	argsize+12(FP), R1
   296	
   297		DISPATCH(runtime·call16, 16)
   298		DISPATCH(runtime·call32, 32)
   299		DISPATCH(runtime·call64, 64)
   300		DISPATCH(runtime·call128, 128)
   301		DISPATCH(runtime·call256, 256)
   302		DISPATCH(runtime·call512, 512)
   303		DISPATCH(runtime·call1024, 1024)
   304		DISPATCH(runtime·call2048, 2048)
   305		DISPATCH(runtime·call4096, 4096)
   306		DISPATCH(runtime·call8192, 8192)
   307		DISPATCH(runtime·call16384, 16384)
   308		DISPATCH(runtime·call32768, 32768)
   309		DISPATCH(runtime·call65536, 65536)
   310		DISPATCH(runtime·call131072, 131072)
   311		DISPATCH(runtime·call262144, 262144)
   312		DISPATCH(runtime·call524288, 524288)
   313		DISPATCH(runtime·call1048576, 1048576)
   314		DISPATCH(runtime·call2097152, 2097152)
   315		DISPATCH(runtime·call4194304, 4194304)
   316		DISPATCH(runtime·call8388608, 8388608)
   317		DISPATCH(runtime·call16777216, 16777216)
   318		DISPATCH(runtime·call33554432, 33554432)
   319		DISPATCH(runtime·call67108864, 67108864)
   320		DISPATCH(runtime·call134217728, 134217728)
   321		DISPATCH(runtime·call268435456, 268435456)
   322		DISPATCH(runtime·call536870912, 536870912)
   323		DISPATCH(runtime·call1073741824, 1073741824)
   324		MOVW	$runtime·badreflectcall(SB), R4
   325		JMP	(R4)
   326	
   327	#define CALLFN(NAME,MAXSIZE)	\
   328	TEXT NAME(SB),WRAPPER,$MAXSIZE-20;	\
   329		NO_LOCAL_POINTERS;	\
   330		/* copy arguments to stack */		\
   331		MOVW	arg+8(FP), R1;	\
   332		MOVW	argsize+12(FP), R2;	\
   333		MOVW	R29, R3;	\
   334		ADDU	$4, R3;	\
   335		ADDU	R3, R2;	\
   336		BEQ	R3, R2, 6(PC);	\
   337		MOVBU	(R1), R4;	\
   338		ADDU	$1, R1;	\
   339		MOVBU	R4, (R3);	\
   340		ADDU	$1, R3;	\
   341		JMP	-5(PC);	\
   342		/* call function */			\
   343		MOVW	f+4(FP), REGCTXT;	\
   344		MOVW	(REGCTXT), R4;	\
   345		PCDATA	$PCDATA_StackMapIndex, $0;	\
   346		JAL	(R4);	\
   347		/* copy return values back */		\
   348		MOVW	argtype+0(FP), R5;	\
   349		MOVW	arg+8(FP), R1;	\
   350		MOVW	n+12(FP), R2;	\
   351		MOVW	retoffset+16(FP), R4;	\
   352		ADDU	$4, R29, R3;	\
   353		ADDU	R4, R3;	\
   354		ADDU	R4, R1;	\
   355		SUBU	R4, R2;	\
   356		JAL	callRet<>(SB);		\
   357		RET
   358	
   359	// callRet copies return values back at the end of call*. This is a
   360	// separate function so it can allocate stack space for the arguments
   361	// to reflectcallmove. It does not follow the Go ABI; it expects its
   362	// arguments in registers.
   363	TEXT callRet<>(SB), NOSPLIT, $16-0
   364		MOVW	R5, 4(R29)
   365		MOVW	R1, 8(R29)
   366		MOVW	R3, 12(R29)
   367		MOVW	R2, 16(R29)
   368		JAL	runtime·reflectcallmove(SB)
   369		RET
   370	
   371	CALLFN(·call16, 16)
   372	CALLFN(·call32, 32)
   373	CALLFN(·call64, 64)
   374	CALLFN(·call128, 128)
   375	CALLFN(·call256, 256)
   376	CALLFN(·call512, 512)
   377	CALLFN(·call1024, 1024)
   378	CALLFN(·call2048, 2048)
   379	CALLFN(·call4096, 4096)
   380	CALLFN(·call8192, 8192)
   381	CALLFN(·call16384, 16384)
   382	CALLFN(·call32768, 32768)
   383	CALLFN(·call65536, 65536)
   384	CALLFN(·call131072, 131072)
   385	CALLFN(·call262144, 262144)
   386	CALLFN(·call524288, 524288)
   387	CALLFN(·call1048576, 1048576)
   388	CALLFN(·call2097152, 2097152)
   389	CALLFN(·call4194304, 4194304)
   390	CALLFN(·call8388608, 8388608)
   391	CALLFN(·call16777216, 16777216)
   392	CALLFN(·call33554432, 33554432)
   393	CALLFN(·call67108864, 67108864)
   394	CALLFN(·call134217728, 134217728)
   395	CALLFN(·call268435456, 268435456)
   396	CALLFN(·call536870912, 536870912)
   397	CALLFN(·call1073741824, 1073741824)
   398	
   399	TEXT runtime·procyield(SB),NOSPLIT,$0-4
   400		RET
   401	
   402	// void jmpdefer(fv, sp);
   403	// called from deferreturn.
   404	// 1. grab stored LR for caller
   405	// 2. sub 8 bytes to get back to JAL deferreturn
   406	// 3. JMP to fn
   407	TEXT runtime·jmpdefer(SB),NOSPLIT,$0-8
   408		MOVW	0(R29), R31
   409		ADDU	$-8, R31
   410	
   411		MOVW	fv+0(FP), REGCTXT
   412		MOVW	argp+4(FP), R29
   413		ADDU	$-4, R29
   414		NOR	R0, R0	// prevent scheduling
   415		MOVW	0(REGCTXT), R4
   416		JMP	(R4)
   417	
   418	// Save state of caller into g->sched. Smashes R1.
   419	TEXT gosave<>(SB),NOSPLIT|NOFRAME,$0
   420		MOVW	R31, (g_sched+gobuf_pc)(g)
   421		MOVW	R29, (g_sched+gobuf_sp)(g)
   422		MOVW	R0, (g_sched+gobuf_lr)(g)
   423		MOVW	R0, (g_sched+gobuf_ret)(g)
   424		// Assert ctxt is zero. See func save.
   425		MOVW	(g_sched+gobuf_ctxt)(g), R1
   426		BEQ	R1, 2(PC)
   427		JAL	runtime·badctxt(SB)
   428		RET
   429	
   430	// func asmcgocall(fn, arg unsafe.Pointer) int32
   431	// Call fn(arg) on the scheduler stack,
   432	// aligned appropriately for the gcc ABI.
   433	// See cgocall.go for more details.
   434	TEXT ·asmcgocall(SB),NOSPLIT,$0-12
   435		MOVW	fn+0(FP), R25
   436		MOVW	arg+4(FP), R4
   437	
   438		MOVW	R29, R3	// save original stack pointer
   439		MOVW	g, R2
   440	
   441		// Figure out if we need to switch to m->g0 stack.
   442		// We get called to create new OS threads too, and those
   443		// come in on the m->g0 stack already.
   444		MOVW	g_m(g), R5
   445		MOVW	m_g0(R5), R6
   446		BEQ	R6, g, g0
   447	
   448		JAL	gosave<>(SB)
   449		MOVW	R6, g
   450		JAL	runtime·save_g(SB)
   451		MOVW	(g_sched+gobuf_sp)(g), R29
   452	
   453		// Now on a scheduling stack (a pthread-created stack).
   454	g0:
   455		// Save room for two of our pointers and O32 frame.
   456		ADDU	$-24, R29
   457		AND	$~7, R29	// O32 ABI expects 8-byte aligned stack on function entry
   458		MOVW	R2, 16(R29)	// save old g on stack
   459		MOVW	(g_stack+stack_hi)(R2), R2
   460		SUBU	R3, R2
   461		MOVW	R2, 20(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		MOVW	16(R29), g
   466		JAL	runtime·save_g(SB)
   467		MOVW	(g_stack+stack_hi)(g), R5
   468		MOVW	20(R29), R6
   469		SUBU	R6, R5
   470		MOVW	R5, R29
   471	
   472		MOVW	R2, ret+8(FP)
   473		RET
   474	
   475	// cgocallback(void (*fn)(void*), void *frame, uintptr framesize)
   476	// Turn the fn into a Go func (by taking its address) and call
   477	// cgocallback_gofunc.
   478	TEXT runtime·cgocallback(SB),NOSPLIT,$16-16
   479		MOVW	$fn+0(FP), R1
   480		MOVW	R1, 4(R29)
   481		MOVW	frame+4(FP), R1
   482		MOVW	R1, 8(R29)
   483		MOVW	framesize+8(FP), R1
   484		MOVW	R1, 12(R29)
   485		MOVW	ctxt+12(FP), R1
   486		MOVW	R1, 16(R29)
   487		MOVW	$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,$8-16
   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		MOVW	g_m(g), R3
   510		MOVW	R3, savedm-4(SP)
   511		JMP	havem
   512	
   513	needm:
   514		MOVW	g, savedm-4(SP) // g is zero, so is m.
   515		MOVW	$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		MOVW	g_m(g), R3
   530		MOVW	m_g0(R3), R1
   531		MOVW	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 4(R29) aka savedsp-8(SP).
   539		MOVW	m_g0(R3), R1
   540		MOVW	(g_sched+gobuf_sp)(R1), R2
   541		MOVW	R2, savedsp-8(SP)
   542		MOVW	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, -4(SP) is unused (where SP refers to
   559		// m->curg's SP while we're setting it up, before we've adjusted it).
   560		MOVW	m_curg(R3), g
   561		JAL	runtime·save_g(SB)
   562		MOVW	(g_sched+gobuf_sp)(g), R2 // prepare stack as R2
   563		MOVW	(g_sched+gobuf_pc)(g), R4
   564		MOVW	R4, -12(R2)
   565		MOVW    ctxt+12(FP), R1
   566		MOVW    R1, -8(R2)
   567		MOVW	$-12(R2), R29
   568		JAL	runtime·cgocallbackg(SB)
   569	
   570		// Restore g->sched (== m->curg->sched) from saved values.
   571		MOVW	0(R29), R4
   572		MOVW	R4, (g_sched+gobuf_pc)(g)
   573		MOVW	$12(R29), R2
   574		MOVW	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		MOVW	g_m(g), R3
   580		MOVW	m_g0(R3), g
   581		JAL	runtime·save_g(SB)
   582		MOVW	(g_sched+gobuf_sp)(g), R29
   583		MOVW	savedsp-8(SP), R2
   584		MOVW	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		MOVW	savedm-4(SP), R3
   589		BNE	R3, droppedm
   590		MOVW	$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	// This only happens if iscgo, so jump straight to save_g
   599	TEXT runtime·setg(SB),NOSPLIT,$0-4
   600		MOVW	gg+0(FP), g
   601		JAL	runtime·save_g(SB)
   602		RET
   603	
   604	// void setg_gcc(G*); set g in C TLS.
   605	// Must obey the gcc calling convention.
   606	TEXT setg_gcc<>(SB),NOSPLIT,$0
   607		MOVW	R4, g
   608		JAL	runtime·save_g(SB)
   609		RET
   610	
   611	TEXT runtime·abort(SB),NOSPLIT,$0-0
   612		UNDEF
   613	
   614	// Not implemented.
   615	TEXT runtime·aeshash(SB),NOSPLIT,$0
   616		UNDEF
   617	
   618	// Not implemented.
   619	TEXT runtime·aeshash32(SB),NOSPLIT,$0
   620		UNDEF
   621	
   622	// Not implemented.
   623	TEXT runtime·aeshash64(SB),NOSPLIT,$0
   624		UNDEF
   625	
   626	// Not implemented.
   627	TEXT runtime·aeshashstr(SB),NOSPLIT,$0
   628		UNDEF
   629	
   630	TEXT runtime·return0(SB),NOSPLIT,$0
   631		MOVW	$0, R1
   632		RET
   633	
   634	// Called from cgo wrappers, this function returns g->m->curg.stack.hi.
   635	// Must obey the gcc calling convention.
   636	TEXT _cgo_topofstack(SB),NOSPLIT|NOFRAME,$0
   637		// g (R30), R3 and REGTMP (R23) might be clobbered by load_g. R30 and R23
   638		// are callee-save in the gcc calling convention, so save them.
   639		MOVW	R23, R8
   640		MOVW	g, R9
   641		MOVW	R31, R10 // this call frame does not save LR
   642	
   643		JAL	runtime·load_g(SB)
   644		MOVW	g_m(g), R1
   645		MOVW	m_curg(R1), R1
   646		MOVW	(g_stack+stack_hi)(R1), R2 // return value in R2
   647	
   648		MOVW	R8, R23
   649		MOVW	R9, g
   650		MOVW	R10, R31
   651	
   652		RET
   653	
   654	// The top-most function running on a goroutine
   655	// returns to goexit+PCQuantum.
   656	TEXT runtime·goexit(SB),NOSPLIT|NOFRAME|TOPFRAME,$0-0
   657		NOR	R0, R0	// NOP
   658		JAL	runtime·goexit1(SB)	// does not return
   659		// traceback from goexit1 must hit code range of goexit
   660		NOR	R0, R0	// NOP
   661	
   662	TEXT ·checkASM(SB),NOSPLIT,$0-1
   663		MOVW	$1, R1
   664		MOVB	R1, ret+0(FP)
   665		RET
   666	
   667	// gcWriteBarrier performs a heap pointer write and informs the GC.
   668	//
   669	// gcWriteBarrier does NOT follow the Go ABI. It takes two arguments:
   670	// - R20 is the destination of the write
   671	// - R21 is the value being written at R20.
   672	// It clobbers R23 (the linker temp register).
   673	// The act of CALLing gcWriteBarrier will clobber R31 (LR).
   674	// It does not clobber any other general-purpose registers,
   675	// but may clobber others (e.g., floating point registers).
   676	TEXT runtime·gcWriteBarrier(SB),NOSPLIT,$104
   677		// Save the registers clobbered by the fast path.
   678		MOVW	R1, 100(R29)
   679		MOVW	R2, 104(R29)
   680		MOVW	g_m(g), R1
   681		MOVW	m_p(R1), R1
   682		MOVW	(p_wbBuf+wbBuf_next)(R1), R2
   683		// Increment wbBuf.next position.
   684		ADD	$8, R2
   685		MOVW	R2, (p_wbBuf+wbBuf_next)(R1)
   686		MOVW	(p_wbBuf+wbBuf_end)(R1), R1
   687		MOVW	R1, R23		// R23 is linker temp register
   688		// Record the write.
   689		MOVW	R21, -8(R2)	// Record value
   690		MOVW	(R20), R1	// TODO: This turns bad writes into bad reads.
   691		MOVW	R1, -4(R2)	// Record *slot
   692		// Is the buffer full?
   693		BEQ	R2, R23, flush
   694	ret:
   695		MOVW	100(R29), R1
   696		MOVW	104(R29), R2
   697		// Do the write.
   698		MOVW	R21, (R20)
   699		RET
   700	
   701	flush:
   702		// Save all general purpose registers since these could be
   703		// clobbered by wbBufFlush and were not saved by the caller.
   704		MOVW	R20, 4(R29)	// Also first argument to wbBufFlush
   705		MOVW	R21, 8(R29)	// Also second argument to wbBufFlush
   706		// R1 already saved
   707		// R2 already saved
   708		MOVW	R3, 12(R29)
   709		MOVW	R4, 16(R29)
   710		MOVW	R5, 20(R29)
   711		MOVW	R6, 24(R29)
   712		MOVW	R7, 28(R29)
   713		MOVW	R8, 32(R29)
   714		MOVW	R9, 36(R29)
   715		MOVW	R10, 40(R29)
   716		MOVW	R11, 44(R29)
   717		MOVW	R12, 48(R29)
   718		MOVW	R13, 52(R29)
   719		MOVW	R14, 56(R29)
   720		MOVW	R15, 60(R29)
   721		MOVW	R16, 64(R29)
   722		MOVW	R17, 68(R29)
   723		MOVW	R18, 72(R29)
   724		MOVW	R19, 76(R29)
   725		MOVW	R20, 80(R29)
   726		// R21 already saved
   727		// R22 already saved.
   728		MOVW	R22, 84(R29)
   729		// R23 is tmp register.
   730		MOVW	R24, 88(R29)
   731		MOVW	R25, 92(R29)
   732		// R26 is reserved by kernel.
   733		// R27 is reserved by kernel.
   734		MOVW	R28, 96(R29)
   735		// R29 is SP.
   736		// R30 is g.
   737		// R31 is LR, which was saved by the prologue.
   738	
   739		// This takes arguments R20 and R21.
   740		CALL	runtime·wbBufFlush(SB)
   741	
   742		MOVW	4(R29), R20
   743		MOVW	8(R29), R21
   744		MOVW	12(R29), R3
   745		MOVW	16(R29), R4
   746		MOVW	20(R29), R5
   747		MOVW	24(R29), R6
   748		MOVW	28(R29), R7
   749		MOVW	32(R29), R8
   750		MOVW	36(R29), R9
   751		MOVW	40(R29), R10
   752		MOVW	44(R29), R11
   753		MOVW	48(R29), R12
   754		MOVW	52(R29), R13
   755		MOVW	56(R29), R14
   756		MOVW	60(R29), R15
   757		MOVW	64(R29), R16
   758		MOVW	68(R29), R17
   759		MOVW	72(R29), R18
   760		MOVW	76(R29), R19
   761		MOVW	80(R29), R20
   762		MOVW	84(R29), R22
   763		MOVW	88(R29), R24
   764		MOVW	92(R29), R25
   765		MOVW	96(R29), R28
   766		JMP	ret
   767	
   768	// Note: these functions use a special calling convention to save generated code space.
   769	// Arguments are passed in registers, but the space for those arguments are allocated
   770	// in the caller's stack frame. These stubs write the args into that stack space and
   771	// then tail call to the corresponding runtime handler.
   772	// The tail call makes these stubs disappear in backtraces.
   773	TEXT runtime·panicIndex(SB),NOSPLIT,$0-8
   774		MOVW	R1, x+0(FP)
   775		MOVW	R2, y+4(FP)
   776		JMP	runtime·goPanicIndex(SB)
   777	TEXT runtime·panicIndexU(SB),NOSPLIT,$0-8
   778		MOVW	R1, x+0(FP)
   779		MOVW	R2, y+4(FP)
   780		JMP	runtime·goPanicIndexU(SB)
   781	TEXT runtime·panicSliceAlen(SB),NOSPLIT,$0-8
   782		MOVW	R2, x+0(FP)
   783		MOVW	R3, y+4(FP)
   784		JMP	runtime·goPanicSliceAlen(SB)
   785	TEXT runtime·panicSliceAlenU(SB),NOSPLIT,$0-8
   786		MOVW	R2, x+0(FP)
   787		MOVW	R3, y+4(FP)
   788		JMP	runtime·goPanicSliceAlenU(SB)
   789	TEXT runtime·panicSliceAcap(SB),NOSPLIT,$0-8
   790		MOVW	R2, x+0(FP)
   791		MOVW	R3, y+4(FP)
   792		JMP	runtime·goPanicSliceAcap(SB)
   793	TEXT runtime·panicSliceAcapU(SB),NOSPLIT,$0-8
   794		MOVW	R2, x+0(FP)
   795		MOVW	R3, y+4(FP)
   796		JMP	runtime·goPanicSliceAcapU(SB)
   797	TEXT runtime·panicSliceB(SB),NOSPLIT,$0-8
   798		MOVW	R1, x+0(FP)
   799		MOVW	R2, y+4(FP)
   800		JMP	runtime·goPanicSliceB(SB)
   801	TEXT runtime·panicSliceBU(SB),NOSPLIT,$0-8
   802		MOVW	R1, x+0(FP)
   803		MOVW	R2, y+4(FP)
   804		JMP	runtime·goPanicSliceBU(SB)
   805	TEXT runtime·panicSlice3Alen(SB),NOSPLIT,$0-8
   806		MOVW	R3, x+0(FP)
   807		MOVW	R4, y+4(FP)
   808		JMP	runtime·goPanicSlice3Alen(SB)
   809	TEXT runtime·panicSlice3AlenU(SB),NOSPLIT,$0-8
   810		MOVW	R3, x+0(FP)
   811		MOVW	R4, y+4(FP)
   812		JMP	runtime·goPanicSlice3AlenU(SB)
   813	TEXT runtime·panicSlice3Acap(SB),NOSPLIT,$0-8
   814		MOVW	R3, x+0(FP)
   815		MOVW	R4, y+4(FP)
   816		JMP	runtime·goPanicSlice3Acap(SB)
   817	TEXT runtime·panicSlice3AcapU(SB),NOSPLIT,$0-8
   818		MOVW	R3, x+0(FP)
   819		MOVW	R4, y+4(FP)
   820		JMP	runtime·goPanicSlice3AcapU(SB)
   821	TEXT runtime·panicSlice3B(SB),NOSPLIT,$0-8
   822		MOVW	R2, x+0(FP)
   823		MOVW	R3, y+4(FP)
   824		JMP	runtime·goPanicSlice3B(SB)
   825	TEXT runtime·panicSlice3BU(SB),NOSPLIT,$0-8
   826		MOVW	R2, x+0(FP)
   827		MOVW	R3, y+4(FP)
   828		JMP	runtime·goPanicSlice3BU(SB)
   829	TEXT runtime·panicSlice3C(SB),NOSPLIT,$0-8
   830		MOVW	R1, x+0(FP)
   831		MOVW	R2, y+4(FP)
   832		JMP	runtime·goPanicSlice3C(SB)
   833	TEXT runtime·panicSlice3CU(SB),NOSPLIT,$0-8
   834		MOVW	R1, x+0(FP)
   835		MOVW	R2, y+4(FP)
   836		JMP	runtime·goPanicSlice3CU(SB)
   837	
   838	// Extended versions for 64-bit indexes.
   839	TEXT runtime·panicExtendIndex(SB),NOSPLIT,$0-12
   840		MOVW	R5, hi+0(FP)
   841		MOVW	R1, lo+4(FP)
   842		MOVW	R2, y+8(FP)
   843		JMP	runtime·goPanicExtendIndex(SB)
   844	TEXT runtime·panicExtendIndexU(SB),NOSPLIT,$0-12
   845		MOVW	R5, hi+0(FP)
   846		MOVW	R1, lo+4(FP)
   847		MOVW	R2, y+8(FP)
   848		JMP	runtime·goPanicExtendIndexU(SB)
   849	TEXT runtime·panicExtendSliceAlen(SB),NOSPLIT,$0-12
   850		MOVW	R5, hi+0(FP)
   851		MOVW	R2, lo+4(FP)
   852		MOVW	R3, y+8(FP)
   853		JMP	runtime·goPanicExtendSliceAlen(SB)
   854	TEXT runtime·panicExtendSliceAlenU(SB),NOSPLIT,$0-12
   855		MOVW	R5, hi+0(FP)
   856		MOVW	R2, lo+4(FP)
   857		MOVW	R3, y+8(FP)
   858		JMP	runtime·goPanicExtendSliceAlenU(SB)
   859	TEXT runtime·panicExtendSliceAcap(SB),NOSPLIT,$0-12
   860		MOVW	R5, hi+0(FP)
   861		MOVW	R2, lo+4(FP)
   862		MOVW	R3, y+8(FP)
   863		JMP	runtime·goPanicExtendSliceAcap(SB)
   864	TEXT runtime·panicExtendSliceAcapU(SB),NOSPLIT,$0-12
   865		MOVW	R5, hi+0(FP)
   866		MOVW	R2, lo+4(FP)
   867		MOVW	R3, y+8(FP)
   868		JMP	runtime·goPanicExtendSliceAcapU(SB)
   869	TEXT runtime·panicExtendSliceB(SB),NOSPLIT,$0-12
   870		MOVW	R5, hi+0(FP)
   871		MOVW	R1, lo+4(FP)
   872		MOVW	R2, y+8(FP)
   873		JMP	runtime·goPanicExtendSliceB(SB)
   874	TEXT runtime·panicExtendSliceBU(SB),NOSPLIT,$0-12
   875		MOVW	R5, hi+0(FP)
   876		MOVW	R1, lo+4(FP)
   877		MOVW	R2, y+8(FP)
   878		JMP	runtime·goPanicExtendSliceBU(SB)
   879	TEXT runtime·panicExtendSlice3Alen(SB),NOSPLIT,$0-12
   880		MOVW	R5, hi+0(FP)
   881		MOVW	R3, lo+4(FP)
   882		MOVW	R4, y+8(FP)
   883		JMP	runtime·goPanicExtendSlice3Alen(SB)
   884	TEXT runtime·panicExtendSlice3AlenU(SB),NOSPLIT,$0-12
   885		MOVW	R5, hi+0(FP)
   886		MOVW	R3, lo+4(FP)
   887		MOVW	R4, y+8(FP)
   888		JMP	runtime·goPanicExtendSlice3AlenU(SB)
   889	TEXT runtime·panicExtendSlice3Acap(SB),NOSPLIT,$0-12
   890		MOVW	R5, hi+0(FP)
   891		MOVW	R3, lo+4(FP)
   892		MOVW	R4, y+8(FP)
   893		JMP	runtime·goPanicExtendSlice3Acap(SB)
   894	TEXT runtime·panicExtendSlice3AcapU(SB),NOSPLIT,$0-12
   895		MOVW	R5, hi+0(FP)
   896		MOVW	R3, lo+4(FP)
   897		MOVW	R4, y+8(FP)
   898		JMP	runtime·goPanicExtendSlice3AcapU(SB)
   899	TEXT runtime·panicExtendSlice3B(SB),NOSPLIT,$0-12
   900		MOVW	R5, hi+0(FP)
   901		MOVW	R2, lo+4(FP)
   902		MOVW	R3, y+8(FP)
   903		JMP	runtime·goPanicExtendSlice3B(SB)
   904	TEXT runtime·panicExtendSlice3BU(SB),NOSPLIT,$0-12
   905		MOVW	R5, hi+0(FP)
   906		MOVW	R2, lo+4(FP)
   907		MOVW	R3, y+8(FP)
   908		JMP	runtime·goPanicExtendSlice3BU(SB)
   909	TEXT runtime·panicExtendSlice3C(SB),NOSPLIT,$0-12
   910		MOVW	R5, hi+0(FP)
   911		MOVW	R1, lo+4(FP)
   912		MOVW	R2, y+8(FP)
   913		JMP	runtime·goPanicExtendSlice3C(SB)
   914	TEXT runtime·panicExtendSlice3CU(SB),NOSPLIT,$0-12
   915		MOVW	R5, hi+0(FP)
   916		MOVW	R1, lo+4(FP)
   917		MOVW	R2, y+8(FP)
   918		JMP	runtime·goPanicExtendSlice3CU(SB)

View as plain text