...
Run Format

Text file src/runtime/asm_mipsx.s

Documentation: runtime

     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,$-4-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,$-4-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	
   184	switch:
   185		// save our state in g->sched.  Pretend to
   186		// be systemstack_switch if the G stack is scanned.
   187		MOVW	$runtime·systemstack_switch(SB), R4
   188		ADDU	$8, R4	// get past prologue
   189		MOVW	R4, (g_sched+gobuf_pc)(g)
   190		MOVW	R29, (g_sched+gobuf_sp)(g)
   191		MOVW	R0, (g_sched+gobuf_lr)(g)
   192		MOVW	g, (g_sched+gobuf_g)(g)
   193	
   194		// switch to g0
   195		MOVW	R3, g
   196		JAL	runtime·save_g(SB)
   197		MOVW	(g_sched+gobuf_sp)(g), R1
   198		// make it look like mstart called systemstack on g0, to stop traceback
   199		ADDU	$-4, R1
   200		MOVW	$runtime·mstart(SB), R2
   201		MOVW	R2, 0(R1)
   202		MOVW	R1, R29
   203	
   204		// call target function
   205		MOVW	0(REGCTXT), R4	// code pointer
   206		JAL	(R4)
   207	
   208		// switch back to g
   209		MOVW	g_m(g), R1
   210		MOVW	m_curg(R1), g
   211		JAL	runtime·save_g(SB)
   212		MOVW	(g_sched+gobuf_sp)(g), R29
   213		MOVW	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		MOVW	0(REGCTXT), R4	// code pointer
   221		MOVW	0(R29), R31	// restore LR
   222		ADD	$4, 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,$-4-0
   238		// Cannot grow scheduler stack (m->g0).
   239		MOVW	g_m(g), R7
   240		MOVW	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		MOVW	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		MOVW	R29, (g_sched+gobuf_sp)(g)
   254		MOVW	R31, (g_sched+gobuf_pc)(g)
   255		MOVW	R3, (g_sched+gobuf_lr)(g)
   256		MOVW	REGCTXT, (g_sched+gobuf_ctxt)(g)
   257	
   258		// Called from f.
   259		// Set m->morebuf to f's caller.
   260		MOVW	R3, (m_morebuf+gobuf_pc)(R7)	// f's caller's PC
   261		MOVW	R29, (m_morebuf+gobuf_sp)(R7)	// f's caller's SP
   262		MOVW	g, (m_morebuf+gobuf_g)(R7)
   263	
   264		// Call newstack on m->g0's stack.
   265		MOVW	m_g0(R7), g
   266		JAL	runtime·save_g(SB)
   267		MOVW	(g_sched+gobuf_sp)(g), R29
   268		// Create a stack frame on g0 to call newstack.
   269		MOVW	R0, -4(R29)	// Zero saved LR in frame
   270		ADDU	$-4, 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,$0-0
   278		MOVW	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	
   286	#define DISPATCH(NAME,MAXSIZE)	\
   287		MOVW	$MAXSIZE, R23;	\
   288		SGTU	R1, R23, R23;	\
   289		BNE	R23, 3(PC);	\
   290		MOVW	$NAME(SB), R4;	\
   291		JMP	(R4)
   292	
   293	TEXT reflect·call(SB),NOSPLIT,$0-20
   294		JMP	·reflectcall(SB)
   295	
   296	TEXT ·reflectcall(SB),NOSPLIT,$-4-20
   297		MOVW	argsize+12(FP), R1
   298	
   299		DISPATCH(runtime·call16, 16)
   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		MOVW	$runtime·badreflectcall(SB), R4
   327		JMP	(R4)
   328	
   329	#define CALLFN(NAME,MAXSIZE)	\
   330	TEXT NAME(SB),WRAPPER,$MAXSIZE-20;	\
   331		NO_LOCAL_POINTERS;	\
   332		/* copy arguments to stack */		\
   333		MOVW	arg+8(FP), R1;	\
   334		MOVW	argsize+12(FP), R2;	\
   335		MOVW	R29, R3;	\
   336		ADDU	$4, R3;	\
   337		ADDU	R3, R2;	\
   338		BEQ	R3, R2, 6(PC);	\
   339		MOVBU	(R1), R4;	\
   340		ADDU	$1, R1;	\
   341		MOVBU	R4, (R3);	\
   342		ADDU	$1, R3;	\
   343		JMP	-5(PC);	\
   344		/* call function */			\
   345		MOVW	f+4(FP), REGCTXT;	\
   346		MOVW	(REGCTXT), R4;	\
   347		PCDATA	$PCDATA_StackMapIndex, $0;	\
   348		JAL	(R4);	\
   349		/* copy return values back */		\
   350		MOVW	argtype+0(FP), R5;	\
   351		MOVW	arg+8(FP), R1;	\
   352		MOVW	n+12(FP), R2;	\
   353		MOVW	retoffset+16(FP), R4;	\
   354		ADDU	$4, R29, R3;	\
   355		ADDU	R4, R3;	\
   356		ADDU	R4, R1;	\
   357		SUBU	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, $16-0
   366		MOVW	R5, 4(R29)
   367		MOVW	R1, 8(R29)
   368		MOVW	R3, 12(R29)
   369		MOVW	R2, 16(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-4
   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,$0-8
   410		MOVW	0(R29), R31
   411		ADDU	$-8, R31
   412	
   413		MOVW	fv+0(FP), REGCTXT
   414		MOVW	argp+4(FP), R29
   415		ADDU	$-4, R29
   416		NOR	R0, R0	// prevent scheduling
   417		MOVW	0(REGCTXT), R4
   418		JMP	(R4)
   419	
   420	// Save state of caller into g->sched. Smashes R1.
   421	TEXT gosave<>(SB),NOSPLIT,$-4
   422		MOVW	R31, (g_sched+gobuf_pc)(g)
   423		MOVW	R29, (g_sched+gobuf_sp)(g)
   424		MOVW	R0, (g_sched+gobuf_lr)(g)
   425		MOVW	R0, (g_sched+gobuf_ret)(g)
   426		// Assert ctxt is zero. See func save.
   427		MOVW	(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-12
   437		MOVW	fn+0(FP), R25
   438		MOVW	arg+4(FP), R4
   439	
   440		MOVW	R29, R3	// save original stack pointer
   441		MOVW	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		MOVW	g_m(g), R5
   447		MOVW	m_g0(R5), R6
   448		BEQ	R6, g, g0
   449	
   450		JAL	gosave<>(SB)
   451		MOVW	R6, g
   452		JAL	runtime·save_g(SB)
   453		MOVW	(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 and O32 frame.
   458		ADDU	$-24, R29
   459		AND	$~7, R29	// O32 ABI expects 8-byte aligned stack on function entry
   460		MOVW	R2, 16(R29)	// save old g on stack
   461		MOVW	(g_stack+stack_hi)(R2), R2
   462		SUBU	R3, R2
   463		MOVW	R2, 20(R29)	// save depth in old g stack (can't just save SP, as stack might be copied during a callback)
   464		JAL	(R25)
   465	
   466		// Restore g, stack pointer. R2 is return value.
   467		MOVW	16(R29), g
   468		JAL	runtime·save_g(SB)
   469		MOVW	(g_stack+stack_hi)(g), R5
   470		MOVW	20(R29), R6
   471		SUBU	R6, R5
   472		MOVW	R5, R29
   473	
   474		MOVW	R2, ret+8(FP)
   475		RET
   476	
   477	// cgocallback(void (*fn)(void*), void *frame, uintptr framesize)
   478	// Turn the fn into a Go func (by taking its address) and call
   479	// cgocallback_gofunc.
   480	TEXT runtime·cgocallback(SB),NOSPLIT,$16-16
   481		MOVW	$fn+0(FP), R1
   482		MOVW	R1, 4(R29)
   483		MOVW	frame+4(FP), R1
   484		MOVW	R1, 8(R29)
   485		MOVW	framesize+8(FP), R1
   486		MOVW	R1, 12(R29)
   487		MOVW	ctxt+12(FP), R1
   488		MOVW	R1, 16(R29)
   489		MOVW	$runtime·cgocallback_gofunc(SB), R1
   490		JAL	(R1)
   491		RET
   492	
   493	// cgocallback_gofunc(FuncVal*, void *frame, uintptr framesize, uintptr ctxt)
   494	// See cgocall.go for more details.
   495	TEXT ·cgocallback_gofunc(SB),NOSPLIT,$8-16
   496		NO_LOCAL_POINTERS
   497	
   498		// Load m and g from thread-local storage.
   499		MOVB	runtime·iscgo(SB), R1
   500		BEQ	R1, nocgo
   501		JAL	runtime·load_g(SB)
   502	nocgo:
   503	
   504		// If g is nil, Go did not create the current thread.
   505		// Call needm to obtain one for temporary use.
   506		// In this case, we're running on the thread stack, so there's
   507		// lots of space, but the linker doesn't know. Hide the call from
   508		// the linker analysis by using an indirect call.
   509		BEQ	g, needm
   510	
   511		MOVW	g_m(g), R3
   512		MOVW	R3, savedm-4(SP)
   513		JMP	havem
   514	
   515	needm:
   516		MOVW	g, savedm-4(SP) // g is zero, so is m.
   517		MOVW	$runtime·needm(SB), R4
   518		JAL	(R4)
   519	
   520		// Set m->sched.sp = SP, so that if a panic happens
   521		// during the function we are about to execute, it will
   522		// have a valid SP to run on the g0 stack.
   523		// The next few lines (after the havem label)
   524		// will save this SP onto the stack and then write
   525		// the same SP back to m->sched.sp. That seems redundant,
   526		// but if an unrecovered panic happens, unwindm will
   527		// restore the g->sched.sp from the stack location
   528		// and then systemstack will try to use it. If we don't set it here,
   529		// that restored SP will be uninitialized (typically 0) and
   530		// will not be usable.
   531		MOVW	g_m(g), R3
   532		MOVW	m_g0(R3), R1
   533		MOVW	R29, (g_sched+gobuf_sp)(R1)
   534	
   535	havem:
   536		// Now there's a valid m, and we're running on its m->g0.
   537		// Save current m->g0->sched.sp on stack and then set it to SP.
   538		// Save current sp in m->g0->sched.sp in preparation for
   539		// switch back to m->curg stack.
   540		// NOTE: unwindm knows that the saved g->sched.sp is at 4(R29) aka savedsp-8(SP).
   541		MOVW	m_g0(R3), R1
   542		MOVW	(g_sched+gobuf_sp)(R1), R2
   543		MOVW	R2, savedsp-8(SP)
   544		MOVW	R29, (g_sched+gobuf_sp)(R1)
   545	
   546		// Switch to m->curg stack and call runtime.cgocallbackg.
   547		// Because we are taking over the execution of m->curg
   548		// but *not* resuming what had been running, we need to
   549		// save that information (m->curg->sched) so we can restore it.
   550		// We can restore m->curg->sched.sp easily, because calling
   551		// runtime.cgocallbackg leaves SP unchanged upon return.
   552		// To save m->curg->sched.pc, we push it onto the stack.
   553		// This has the added benefit that it looks to the traceback
   554		// routine like cgocallbackg is going to return to that
   555		// PC (because the frame we allocate below has the same
   556		// size as cgocallback_gofunc's frame declared above)
   557		// so that the traceback will seamlessly trace back into
   558		// the earlier calls.
   559		//
   560		// In the new goroutine, -4(SP) is unused (where SP refers to
   561		// m->curg's SP while we're setting it up, before we've adjusted it).
   562		MOVW	m_curg(R3), g
   563		JAL	runtime·save_g(SB)
   564		MOVW	(g_sched+gobuf_sp)(g), R2 // prepare stack as R2
   565		MOVW	(g_sched+gobuf_pc)(g), R4
   566		MOVW	R4, -12(R2)
   567		MOVW    ctxt+12(FP), R1
   568		MOVW    R1, -8(R2)
   569		MOVW	$-12(R2), R29
   570		JAL	runtime·cgocallbackg(SB)
   571	
   572		// Restore g->sched (== m->curg->sched) from saved values.
   573		MOVW	0(R29), R4
   574		MOVW	R4, (g_sched+gobuf_pc)(g)
   575		MOVW	$12(R29), R2
   576		MOVW	R2, (g_sched+gobuf_sp)(g)
   577	
   578		// Switch back to m->g0's stack and restore m->g0->sched.sp.
   579		// (Unlike m->curg, the g0 goroutine never uses sched.pc,
   580		// so we do not have to restore it.)
   581		MOVW	g_m(g), R3
   582		MOVW	m_g0(R3), g
   583		JAL	runtime·save_g(SB)
   584		MOVW	(g_sched+gobuf_sp)(g), R29
   585		MOVW	savedsp-8(SP), R2
   586		MOVW	R2, (g_sched+gobuf_sp)(g)
   587	
   588		// If the m on entry was nil, we called needm above to borrow an m
   589		// for the duration of the call. Since the call is over, return it with dropm.
   590		MOVW	savedm-4(SP), R3
   591		BNE	R3, droppedm
   592		MOVW	$runtime·dropm(SB), R4
   593		JAL	(R4)
   594	droppedm:
   595	
   596		// Done!
   597		RET
   598	
   599	// void setg(G*); set g. for use by needm.
   600	// This only happens if iscgo, so jump straight to save_g
   601	TEXT runtime·setg(SB),NOSPLIT,$0-4
   602		MOVW	gg+0(FP), g
   603		JAL	runtime·save_g(SB)
   604		RET
   605	
   606	// void setg_gcc(G*); set g in C TLS.
   607	// Must obey the gcc calling convention.
   608	TEXT setg_gcc<>(SB),NOSPLIT,$0
   609		MOVW	R4, g
   610		JAL	runtime·save_g(SB)
   611		RET
   612	
   613	TEXT runtime·getcallerpc(SB),NOSPLIT,$-4-4
   614		MOVW	0(R29), R1	// LR saved by caller
   615		MOVW	R1, ret+0(FP)
   616		RET
   617	
   618	TEXT runtime·abort(SB),NOSPLIT,$0-0
   619		UNDEF
   620	
   621	// Not implemented.
   622	TEXT runtime·aeshash(SB),NOSPLIT,$0
   623		UNDEF
   624	
   625	// Not implemented.
   626	TEXT runtime·aeshash32(SB),NOSPLIT,$0
   627		UNDEF
   628	
   629	// Not implemented.
   630	TEXT runtime·aeshash64(SB),NOSPLIT,$0
   631		UNDEF
   632	
   633	// Not implemented.
   634	TEXT runtime·aeshashstr(SB),NOSPLIT,$0
   635		UNDEF
   636	
   637	// memequal(a, b unsafe.Pointer, size uintptr) bool
   638	TEXT runtime·memequal(SB),NOSPLIT,$0-13
   639		MOVW	a+0(FP), R1
   640		MOVW	b+4(FP), R2
   641		BEQ	R1, R2, eq
   642		MOVW	size+8(FP), R3
   643		ADDU	R1, R3, R4
   644	loop:
   645		BNE	R1, R4, test
   646		MOVW	$1, R1
   647		MOVB	R1, ret+12(FP)
   648		RET
   649	test:
   650		MOVBU	(R1), R6
   651		ADDU	$1, R1
   652		MOVBU	(R2), R7
   653		ADDU	$1, R2
   654		BEQ	R6, R7, loop
   655	
   656		MOVB	R0, ret+12(FP)
   657		RET
   658	eq:
   659		MOVW	$1, R1
   660		MOVB	R1, ret+12(FP)
   661		RET
   662	
   663	// memequal_varlen(a, b unsafe.Pointer) bool
   664	TEXT runtime·memequal_varlen(SB),NOSPLIT,$0-9
   665		MOVW	a+0(FP), R1
   666		MOVW	b+4(FP), R2
   667		BEQ	R1, R2, eq
   668		MOVW	4(REGCTXT), R3	// compiler stores size at offset 4 in the closure
   669		ADDU	R1, R3, R4
   670	loop:
   671		BNE	R1, R4, test
   672		MOVW	$1, R1
   673		MOVB	R1, ret+8(FP)
   674		RET
   675	test:
   676		MOVBU	(R1), R6
   677		ADDU	$1, R1
   678		MOVBU	(R2), R7
   679		ADDU	$1, R2
   680		BEQ	R6, R7, loop
   681	
   682		MOVB	R0, ret+8(FP)
   683		RET
   684	eq:
   685		MOVW	$1, R1
   686		MOVB	R1, ret+8(FP)
   687		RET
   688	
   689	TEXT bytes·Equal(SB),NOSPLIT,$0-25
   690		MOVW	a_len+4(FP), R3
   691		MOVW	b_len+16(FP), R4
   692		BNE	R3, R4, noteq	// unequal lengths are not equal
   693	
   694		MOVW	a+0(FP), R1
   695		MOVW	b+12(FP), R2
   696		ADDU	R1, R3	// end
   697	
   698	loop:
   699		BEQ	R1, R3, equal	// reached the end
   700		MOVBU	(R1), R6
   701		ADDU	$1, R1
   702		MOVBU	(R2), R7
   703		ADDU	$1, R2
   704		BEQ	R6, R7, loop
   705	
   706	noteq:
   707		MOVB	R0, ret+24(FP)
   708		RET
   709	
   710	equal:
   711		MOVW	$1, R1
   712		MOVB	R1, ret+24(FP)
   713		RET
   714	
   715	TEXT bytes·IndexByte(SB),NOSPLIT,$0-20
   716		MOVW	s+0(FP), R1
   717		MOVW	s_len+4(FP), R2
   718		MOVBU	c+12(FP), R3	// byte to find
   719		ADDU	$1, R1, R4	// store base+1 for later
   720		ADDU	R1, R2	// end
   721	
   722	loop:
   723		BEQ	R1, R2, notfound
   724		MOVBU	(R1), R5
   725		ADDU	$1, R1
   726		BNE	R3, R5, loop
   727	
   728		SUBU	R4, R1	// R1 will be one beyond the position we want so remove (base+1)
   729		MOVW	R1, ret+16(FP)
   730		RET
   731	
   732	notfound:
   733		MOVW	$-1, R1
   734		MOVW	R1, ret+16(FP)
   735		RET
   736	
   737	TEXT strings·IndexByte(SB),NOSPLIT,$0-16
   738		MOVW	s_base+0(FP), R1
   739		MOVW	s_len+4(FP), R2
   740		MOVBU	c+8(FP), R3	// byte to find
   741		ADDU	$1, R1, R4	// store base+1 for later
   742		ADDU	R1, R2	// end
   743	
   744	loop:
   745		BEQ	R1, R2, notfound
   746		MOVBU	(R1), R5
   747		ADDU	$1, R1
   748		BNE	R3, R5, loop
   749	
   750		SUBU	R4, R1	// remove (base+1)
   751		MOVW	R1, ret+12(FP)
   752		RET
   753	
   754	notfound:
   755		MOVW	$-1, R1
   756		MOVW	R1, ret+12(FP)
   757		RET
   758	
   759	TEXT runtime·cmpstring(SB),NOSPLIT,$0-20
   760		MOVW	s1_base+0(FP), R3
   761		MOVW	s1_len+4(FP), R1
   762		MOVW	s2_base+8(FP), R4
   763		MOVW	s2_len+12(FP), R2
   764		BEQ	R3, R4, samebytes
   765		SGTU	R1, R2, R7
   766		MOVW	R1, R8
   767		CMOVN	R7, R2, R8	// R8 is min(R1, R2)
   768	
   769		ADDU	R3, R8	// R3 is current byte in s1, R8 is last byte in s1 to compare
   770	loop:
   771		BEQ	R3, R8, samebytes	// all compared bytes were the same; compare lengths
   772	
   773		MOVBU	(R3), R6
   774		ADDU	$1, R3
   775		MOVBU	(R4), R7
   776		ADDU	$1, R4
   777		BEQ	R6, R7 , loop
   778		// bytes differed
   779		SGTU	R6, R7, R8
   780		MOVW	$-1, R6
   781		CMOVZ	R8, R6, R8
   782		JMP	cmp_ret
   783	samebytes:
   784		SGTU	R1, R2, R6
   785		SGTU	R2, R1, R7
   786		SUBU	R7, R6, R8
   787	cmp_ret:
   788		MOVW	R8, ret+16(FP)
   789		RET
   790	
   791	TEXT bytes·Compare(SB),NOSPLIT,$0-28
   792		MOVW	s1_base+0(FP), R3
   793		MOVW	s2_base+12(FP), R4
   794		MOVW	s1_len+4(FP), R1
   795		MOVW	s2_len+16(FP), R2
   796		BEQ	R3, R4, samebytes
   797		SGTU	R1, R2, R7
   798		MOVW	R1, R8
   799		CMOVN	R7, R2, R8	// R8 is min(R1, R2)
   800	
   801		ADDU	R3, R8	// R3 is current byte in s1, R8 is last byte in s1 to compare
   802	loop:
   803		BEQ	R3, R8, samebytes
   804	
   805		MOVBU	(R3), R6
   806		ADDU	$1, R3
   807		MOVBU	(R4), R7
   808		ADDU	$1, R4
   809		BEQ	R6, R7 , loop
   810	
   811		SGTU	R6, R7, R8
   812		MOVW	$-1, R6
   813		CMOVZ	R8, R6, R8
   814		JMP	cmp_ret
   815	samebytes:
   816		SGTU	R1, R2, R6
   817		SGTU	R2, R1, R7
   818		SUBU	R7, R6, R8
   819	cmp_ret:
   820		MOVW	R8, ret+24(FP)
   821		RET
   822	
   823	TEXT runtime·return0(SB),NOSPLIT,$0
   824		MOVW	$0, R1
   825		RET
   826	
   827	// Called from cgo wrappers, this function returns g->m->curg.stack.hi.
   828	// Must obey the gcc calling convention.
   829	TEXT _cgo_topofstack(SB),NOSPLIT,$-4
   830		// g (R30), R3 and REGTMP (R23) might be clobbered by load_g. R30 and R23
   831		// are callee-save in the gcc calling convention, so save them.
   832		MOVW	R23, R8
   833		MOVW	g, R9
   834		MOVW	R31, R10 // this call frame does not save LR
   835	
   836		JAL	runtime·load_g(SB)
   837		MOVW	g_m(g), R1
   838		MOVW	m_curg(R1), R1
   839		MOVW	(g_stack+stack_hi)(R1), R2 // return value in R2
   840	
   841		MOVW	R8, R23
   842		MOVW	R9, g
   843		MOVW	R10, R31
   844	
   845		RET
   846	
   847	// The top-most function running on a goroutine
   848	// returns to goexit+PCQuantum.
   849	TEXT runtime·goexit(SB),NOSPLIT,$-4-0
   850		NOR	R0, R0	// NOP
   851		JAL	runtime·goexit1(SB)	// does not return
   852		// traceback from goexit1 must hit code range of goexit
   853		NOR	R0, R0	// NOP
   854	
   855	TEXT ·checkASM(SB),NOSPLIT,$0-1
   856		MOVW	$1, R1
   857		MOVB	R1, ret+0(FP)
   858		RET

View as plain text