...
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	
   113		// If ctxt is not nil, invoke deletion barrier before overwriting.
   114		MOVW	gobuf_ctxt(R3), R1
   115		BEQ	R1, nilctxt
   116		MOVW	$gobuf_ctxt(R3), R1
   117		MOVW	R1, 4(R29)
   118		MOVW	R0, 8(R29)
   119		JAL	runtime·writebarrierptr_prewrite(SB)
   120		MOVW	buf+0(FP), R3
   121	
   122	nilctxt:
   123		MOVW	gobuf_g(R3), g	// make sure g is not nil
   124		JAL	runtime·save_g(SB)
   125	
   126		MOVW	0(g), R2
   127		MOVW	gobuf_sp(R3), R29
   128		MOVW	gobuf_lr(R3), R31
   129		MOVW	gobuf_ret(R3), R1
   130		MOVW	gobuf_ctxt(R3), REGCTXT
   131		MOVW	R0, gobuf_sp(R3)
   132		MOVW	R0, gobuf_ret(R3)
   133		MOVW	R0, gobuf_lr(R3)
   134		MOVW	R0, gobuf_ctxt(R3)
   135		MOVW	gobuf_pc(R3), R4
   136		JMP	(R4)
   137	
   138	// void mcall(fn func(*g))
   139	// Switch to m->g0's stack, call fn(g).
   140	// Fn must never return. It should gogo(&g->sched)
   141	// to keep running g.
   142	TEXT runtime·mcall(SB),NOSPLIT,$-4-4
   143		// Save caller state in g->sched
   144		MOVW	R29, (g_sched+gobuf_sp)(g)
   145		MOVW	R31, (g_sched+gobuf_pc)(g)
   146		MOVW	R0, (g_sched+gobuf_lr)(g)
   147		MOVW	g, (g_sched+gobuf_g)(g)
   148	
   149		// Switch to m->g0 & its stack, call fn.
   150		MOVW	g, R1
   151		MOVW	g_m(g), R3
   152		MOVW	m_g0(R3), g
   153		JAL	runtime·save_g(SB)
   154		BNE	g, R1, 2(PC)
   155		JMP	runtime·badmcall(SB)
   156		MOVW	fn+0(FP), REGCTXT	// context
   157		MOVW	0(REGCTXT), R4	// code pointer
   158		MOVW	(g_sched+gobuf_sp)(g), R29	// sp = m->g0->sched.sp
   159		ADDU	$-8, R29	// make room for 1 arg and fake LR
   160		MOVW	R1, 4(R29)
   161		MOVW	R0, 0(R29)
   162		JAL	(R4)
   163		JMP	runtime·badmcall2(SB)
   164	
   165	// systemstack_switch is a dummy routine that systemstack leaves at the bottom
   166	// of the G stack.  We need to distinguish the routine that
   167	// lives at the bottom of the G stack from the one that lives
   168	// at the top of the system stack because the one at the top of
   169	// the system stack terminates the stack walk (see topofstack()).
   170	TEXT runtime·systemstack_switch(SB),NOSPLIT,$0-0
   171		UNDEF
   172		JAL	(R31)	// make sure this function is not leaf
   173		RET
   174	
   175	// func systemstack(fn func())
   176	TEXT runtime·systemstack(SB),NOSPLIT,$0-4
   177		MOVW	fn+0(FP), R1	// R1 = fn
   178		MOVW	R1, REGCTXT	// context
   179		MOVW	g_m(g), R2	// R2 = m
   180	
   181		MOVW	m_gsignal(R2), R3	// R3 = gsignal
   182		BEQ	g, R3, noswitch
   183	
   184		MOVW	m_g0(R2), R3	// R3 = g0
   185		BEQ	g, R3, noswitch
   186	
   187		MOVW	m_curg(R2), R4
   188		BEQ	g, R4, switch
   189	
   190		// Bad: g is not gsignal, not g0, not curg. What is it?
   191		// Hide call from linker nosplit analysis.
   192		MOVW	$runtime·badsystemstack(SB), R4
   193		JAL	(R4)
   194	
   195	switch:
   196		// save our state in g->sched.  Pretend to
   197		// be systemstack_switch if the G stack is scanned.
   198		MOVW	$runtime·systemstack_switch(SB), R4
   199		ADDU	$8, R4	// get past prologue
   200		MOVW	R4, (g_sched+gobuf_pc)(g)
   201		MOVW	R29, (g_sched+gobuf_sp)(g)
   202		MOVW	R0, (g_sched+gobuf_lr)(g)
   203		MOVW	g, (g_sched+gobuf_g)(g)
   204	
   205		// switch to g0
   206		MOVW	R3, g
   207		JAL	runtime·save_g(SB)
   208		MOVW	(g_sched+gobuf_sp)(g), R1
   209		// make it look like mstart called systemstack on g0, to stop traceback
   210		ADDU	$-4, R1
   211		MOVW	$runtime·mstart(SB), R2
   212		MOVW	R2, 0(R1)
   213		MOVW	R1, R29
   214	
   215		// call target function
   216		MOVW	0(REGCTXT), R4	// code pointer
   217		JAL	(R4)
   218	
   219		// switch back to g
   220		MOVW	g_m(g), R1
   221		MOVW	m_curg(R1), g
   222		JAL	runtime·save_g(SB)
   223		MOVW	(g_sched+gobuf_sp)(g), R29
   224		MOVW	R0, (g_sched+gobuf_sp)(g)
   225		RET
   226	
   227	noswitch:
   228		// already on m stack, just call directly
   229		MOVW	0(REGCTXT), R4	// code pointer
   230		JAL	(R4)
   231		RET
   232	
   233	/*
   234	 * support for morestack
   235	 */
   236	
   237	// Called during function prolog when more stack is needed.
   238	// Caller has already loaded:
   239	// R1: framesize, R2: argsize, R3: LR
   240	//
   241	// The traceback routines see morestack on a g0 as being
   242	// the top of a stack (for example, morestack calling newstack
   243	// calling the scheduler calling newm calling gc), so we must
   244	// record an argument size. For that purpose, it has no arguments.
   245	TEXT runtime·morestack(SB),NOSPLIT,$-4-0
   246		// Cannot grow scheduler stack (m->g0).
   247		MOVW	g_m(g), R7
   248		MOVW	m_g0(R7), R8
   249		BNE	g, R8, 3(PC)
   250		JAL	runtime·badmorestackg0(SB)
   251		JAL	runtime·abort(SB)
   252	
   253		// Cannot grow signal stack (m->gsignal).
   254		MOVW	m_gsignal(R7), R8
   255		BNE	g, R8, 3(PC)
   256		JAL	runtime·badmorestackgsignal(SB)
   257		JAL	runtime·abort(SB)
   258	
   259		// Called from f.
   260		// Set g->sched to context in f.
   261		MOVW	R29, (g_sched+gobuf_sp)(g)
   262		MOVW	R31, (g_sched+gobuf_pc)(g)
   263		MOVW	R3, (g_sched+gobuf_lr)(g)
   264		// newstack will fill gobuf.ctxt.
   265	
   266		// Called from f.
   267		// Set m->morebuf to f's caller.
   268		MOVW	R3, (m_morebuf+gobuf_pc)(R7)	// f's caller's PC
   269		MOVW	R29, (m_morebuf+gobuf_sp)(R7)	// f's caller's SP
   270		MOVW	g, (m_morebuf+gobuf_g)(R7)
   271	
   272		// Call newstack on m->g0's stack.
   273		MOVW	m_g0(R7), g
   274		JAL	runtime·save_g(SB)
   275		MOVW	(g_sched+gobuf_sp)(g), R29
   276		// Create a stack frame on g0 to call newstack.
   277		MOVW	R0, -8(R29)	// Zero saved LR in frame
   278		ADDU	$-8, R29
   279		MOVW	REGCTXT, 4(R29)	// ctxt argument
   280		JAL	runtime·newstack(SB)
   281	
   282		// Not reached, but make sure the return PC from the call to newstack
   283		// is still in this function, and not the beginning of the next.
   284		UNDEF
   285	
   286	TEXT runtime·morestack_noctxt(SB),NOSPLIT,$0-0
   287		MOVW	R0, REGCTXT
   288		JMP	runtime·morestack(SB)
   289	
   290	// reflectcall: call a function with the given argument list
   291	// func call(argtype *_type, f *FuncVal, arg *byte, argsize, retoffset uint32).
   292	// we don't have variable-sized frames, so we use a small number
   293	// of constant-sized-frame functions to encode a few bits of size in the pc.
   294	
   295	#define DISPATCH(NAME,MAXSIZE)	\
   296		MOVW	$MAXSIZE, R23;	\
   297		SGTU	R1, R23, R23;	\
   298		BNE	R23, 3(PC);	\
   299		MOVW	$NAME(SB), R4;	\
   300		JMP	(R4)
   301	
   302	TEXT reflect·call(SB),NOSPLIT,$0-20
   303		JMP	·reflectcall(SB)
   304	
   305	TEXT ·reflectcall(SB),NOSPLIT,$-4-20
   306		MOVW	argsize+12(FP), R1
   307	
   308		DISPATCH(runtime·call16, 16)
   309		DISPATCH(runtime·call32, 32)
   310		DISPATCH(runtime·call64, 64)
   311		DISPATCH(runtime·call128, 128)
   312		DISPATCH(runtime·call256, 256)
   313		DISPATCH(runtime·call512, 512)
   314		DISPATCH(runtime·call1024, 1024)
   315		DISPATCH(runtime·call2048, 2048)
   316		DISPATCH(runtime·call4096, 4096)
   317		DISPATCH(runtime·call8192, 8192)
   318		DISPATCH(runtime·call16384, 16384)
   319		DISPATCH(runtime·call32768, 32768)
   320		DISPATCH(runtime·call65536, 65536)
   321		DISPATCH(runtime·call131072, 131072)
   322		DISPATCH(runtime·call262144, 262144)
   323		DISPATCH(runtime·call524288, 524288)
   324		DISPATCH(runtime·call1048576, 1048576)
   325		DISPATCH(runtime·call2097152, 2097152)
   326		DISPATCH(runtime·call4194304, 4194304)
   327		DISPATCH(runtime·call8388608, 8388608)
   328		DISPATCH(runtime·call16777216, 16777216)
   329		DISPATCH(runtime·call33554432, 33554432)
   330		DISPATCH(runtime·call67108864, 67108864)
   331		DISPATCH(runtime·call134217728, 134217728)
   332		DISPATCH(runtime·call268435456, 268435456)
   333		DISPATCH(runtime·call536870912, 536870912)
   334		DISPATCH(runtime·call1073741824, 1073741824)
   335		MOVW	$runtime·badreflectcall(SB), R4
   336		JMP	(R4)
   337	
   338	#define CALLFN(NAME,MAXSIZE)	\
   339	TEXT NAME(SB),WRAPPER,$MAXSIZE-20;	\
   340		NO_LOCAL_POINTERS;	\
   341		/* copy arguments to stack */		\
   342		MOVW	arg+8(FP), R1;	\
   343		MOVW	argsize+12(FP), R2;	\
   344		MOVW	R29, R3;	\
   345		ADDU	$4, R3;	\
   346		ADDU	R3, R2;	\
   347		BEQ	R3, R2, 6(PC);	\
   348		MOVBU	(R1), R4;	\
   349		ADDU	$1, R1;	\
   350		MOVBU	R4, (R3);	\
   351		ADDU	$1, R3;	\
   352		JMP	-5(PC);	\
   353		/* call function */			\
   354		MOVW	f+4(FP), REGCTXT;	\
   355		MOVW	(REGCTXT), R4;	\
   356		PCDATA	$PCDATA_StackMapIndex, $0;	\
   357		JAL	(R4);	\
   358		/* copy return values back */		\
   359		MOVW	argtype+0(FP), R5;	\
   360		MOVW	arg+8(FP), R1;	\
   361		MOVW	n+12(FP), R2;	\
   362		MOVW	retoffset+16(FP), R4;	\
   363		ADDU	$4, R29, R3;	\
   364		ADDU	R4, R3;	\
   365		ADDU	R4, R1;	\
   366		SUBU	R4, R2;	\
   367		JAL	callRet<>(SB);		\
   368		RET
   369	
   370	// callRet copies return values back at the end of call*. This is a
   371	// separate function so it can allocate stack space for the arguments
   372	// to reflectcallmove. It does not follow the Go ABI; it expects its
   373	// arguments in registers.
   374	TEXT callRet<>(SB), NOSPLIT, $16-0
   375		MOVW	R5, 4(R29)
   376		MOVW	R1, 8(R29)
   377		MOVW	R3, 12(R29)
   378		MOVW	R2, 16(R29)
   379		JAL	runtime·reflectcallmove(SB)
   380		RET
   381	
   382	CALLFN(·call16, 16)
   383	CALLFN(·call32, 32)
   384	CALLFN(·call64, 64)
   385	CALLFN(·call128, 128)
   386	CALLFN(·call256, 256)
   387	CALLFN(·call512, 512)
   388	CALLFN(·call1024, 1024)
   389	CALLFN(·call2048, 2048)
   390	CALLFN(·call4096, 4096)
   391	CALLFN(·call8192, 8192)
   392	CALLFN(·call16384, 16384)
   393	CALLFN(·call32768, 32768)
   394	CALLFN(·call65536, 65536)
   395	CALLFN(·call131072, 131072)
   396	CALLFN(·call262144, 262144)
   397	CALLFN(·call524288, 524288)
   398	CALLFN(·call1048576, 1048576)
   399	CALLFN(·call2097152, 2097152)
   400	CALLFN(·call4194304, 4194304)
   401	CALLFN(·call8388608, 8388608)
   402	CALLFN(·call16777216, 16777216)
   403	CALLFN(·call33554432, 33554432)
   404	CALLFN(·call67108864, 67108864)
   405	CALLFN(·call134217728, 134217728)
   406	CALLFN(·call268435456, 268435456)
   407	CALLFN(·call536870912, 536870912)
   408	CALLFN(·call1073741824, 1073741824)
   409	
   410	TEXT runtime·procyield(SB),NOSPLIT,$0-4
   411		RET
   412	
   413	// void jmpdefer(fv, sp);
   414	// called from deferreturn.
   415	// 1. grab stored LR for caller
   416	// 2. sub 8 bytes to get back to JAL deferreturn
   417	// 3. JMP to fn
   418	TEXT runtime·jmpdefer(SB),NOSPLIT,$0-8
   419		MOVW	0(R29), R31
   420		ADDU	$-8, R31
   421	
   422		MOVW	fv+0(FP), REGCTXT
   423		MOVW	argp+4(FP), R29
   424		ADDU	$-4, R29
   425		NOR	R0, R0	// prevent scheduling
   426		MOVW	0(REGCTXT), R4
   427		JMP	(R4)
   428	
   429	// Save state of caller into g->sched. Smashes R1.
   430	TEXT gosave<>(SB),NOSPLIT,$-4
   431		MOVW	R31, (g_sched+gobuf_pc)(g)
   432		MOVW	R29, (g_sched+gobuf_sp)(g)
   433		MOVW	R0, (g_sched+gobuf_lr)(g)
   434		MOVW	R0, (g_sched+gobuf_ret)(g)
   435		// Assert ctxt is zero. See func save.
   436		MOVW	(g_sched+gobuf_ctxt)(g), R1
   437		BEQ	R1, 2(PC)
   438		JAL	runtime·badctxt(SB)
   439		RET
   440	
   441	// func asmcgocall(fn, arg unsafe.Pointer) int32
   442	// Call fn(arg) on the scheduler stack,
   443	// aligned appropriately for the gcc ABI.
   444	// See cgocall.go for more details.
   445	TEXT ·asmcgocall(SB),NOSPLIT,$0-12
   446		MOVW	fn+0(FP), R25
   447		MOVW	arg+4(FP), R4
   448	
   449		MOVW	R29, R3	// save original stack pointer
   450		MOVW	g, R2
   451	
   452		// Figure out if we need to switch to m->g0 stack.
   453		// We get called to create new OS threads too, and those
   454		// come in on the m->g0 stack already.
   455		MOVW	g_m(g), R5
   456		MOVW	m_g0(R5), R6
   457		BEQ	R6, g, g0
   458	
   459		JAL	gosave<>(SB)
   460		MOVW	R6, g
   461		JAL	runtime·save_g(SB)
   462		MOVW	(g_sched+gobuf_sp)(g), R29
   463	
   464		// Now on a scheduling stack (a pthread-created stack).
   465	g0:
   466		// Save room for two of our pointers and O32 frame.
   467		ADDU	$-24, R29
   468		AND	$~7, R29	// O32 ABI expects 8-byte aligned stack on function entry
   469		MOVW	R2, 16(R29)	// save old g on stack
   470		MOVW	(g_stack+stack_hi)(R2), R2
   471		SUBU	R3, R2
   472		MOVW	R2, 20(R29)	// save depth in old g stack (can't just save SP, as stack might be copied during a callback)
   473		JAL	(R25)
   474	
   475		// Restore g, stack pointer. R2 is return value.
   476		MOVW	16(R29), g
   477		JAL	runtime·save_g(SB)
   478		MOVW	(g_stack+stack_hi)(g), R5
   479		MOVW	20(R29), R6
   480		SUBU	R6, R5
   481		MOVW	R5, R29
   482	
   483		MOVW	R2, ret+8(FP)
   484		RET
   485	
   486	// cgocallback(void (*fn)(void*), void *frame, uintptr framesize)
   487	// Turn the fn into a Go func (by taking its address) and call
   488	// cgocallback_gofunc.
   489	TEXT runtime·cgocallback(SB),NOSPLIT,$16-16
   490		MOVW	$fn+0(FP), R1
   491		MOVW	R1, 4(R29)
   492		MOVW	frame+4(FP), R1
   493		MOVW	R1, 8(R29)
   494		MOVW	framesize+8(FP), R1
   495		MOVW	R1, 12(R29)
   496		MOVW	ctxt+12(FP), R1
   497		MOVW	R1, 16(R29)
   498		MOVW	$runtime·cgocallback_gofunc(SB), R1
   499		JAL	(R1)
   500		RET
   501	
   502	// cgocallback_gofunc(FuncVal*, void *frame, uintptr framesize, uintptr ctxt)
   503	// See cgocall.go for more details.
   504	TEXT ·cgocallback_gofunc(SB),NOSPLIT,$8-16
   505		NO_LOCAL_POINTERS
   506	
   507		// Load m and g from thread-local storage.
   508		MOVB	runtime·iscgo(SB), R1
   509		BEQ	R1, nocgo
   510		JAL	runtime·load_g(SB)
   511	nocgo:
   512	
   513		// If g is nil, Go did not create the current thread.
   514		// Call needm to obtain one for temporary use.
   515		// In this case, we're running on the thread stack, so there's
   516		// lots of space, but the linker doesn't know. Hide the call from
   517		// the linker analysis by using an indirect call.
   518		BEQ	g, needm
   519	
   520		MOVW	g_m(g), R3
   521		MOVW	R3, savedm-4(SP)
   522		JMP	havem
   523	
   524	needm:
   525		MOVW	g, savedm-4(SP) // g is zero, so is m.
   526		MOVW	$runtime·needm(SB), R4
   527		JAL	(R4)
   528	
   529		// Set m->sched.sp = SP, so that if a panic happens
   530		// during the function we are about to execute, it will
   531		// have a valid SP to run on the g0 stack.
   532		// The next few lines (after the havem label)
   533		// will save this SP onto the stack and then write
   534		// the same SP back to m->sched.sp. That seems redundant,
   535		// but if an unrecovered panic happens, unwindm will
   536		// restore the g->sched.sp from the stack location
   537		// and then systemstack will try to use it. If we don't set it here,
   538		// that restored SP will be uninitialized (typically 0) and
   539		// will not be usable.
   540		MOVW	g_m(g), R3
   541		MOVW	m_g0(R3), R1
   542		MOVW	R29, (g_sched+gobuf_sp)(R1)
   543	
   544	havem:
   545		// Now there's a valid m, and we're running on its m->g0.
   546		// Save current m->g0->sched.sp on stack and then set it to SP.
   547		// Save current sp in m->g0->sched.sp in preparation for
   548		// switch back to m->curg stack.
   549		// NOTE: unwindm knows that the saved g->sched.sp is at 4(R29) aka savedsp-8(SP).
   550		MOVW	m_g0(R3), R1
   551		MOVW	(g_sched+gobuf_sp)(R1), R2
   552		MOVW	R2, savedsp-8(SP)
   553		MOVW	R29, (g_sched+gobuf_sp)(R1)
   554	
   555		// Switch to m->curg stack and call runtime.cgocallbackg.
   556		// Because we are taking over the execution of m->curg
   557		// but *not* resuming what had been running, we need to
   558		// save that information (m->curg->sched) so we can restore it.
   559		// We can restore m->curg->sched.sp easily, because calling
   560		// runtime.cgocallbackg leaves SP unchanged upon return.
   561		// To save m->curg->sched.pc, we push it onto the stack.
   562		// This has the added benefit that it looks to the traceback
   563		// routine like cgocallbackg is going to return to that
   564		// PC (because the frame we allocate below has the same
   565		// size as cgocallback_gofunc's frame declared above)
   566		// so that the traceback will seamlessly trace back into
   567		// the earlier calls.
   568		//
   569		// In the new goroutine, -4(SP) is unused (where SP refers to
   570		// m->curg's SP while we're setting it up, before we've adjusted it).
   571		MOVW	m_curg(R3), g
   572		JAL	runtime·save_g(SB)
   573		MOVW	(g_sched+gobuf_sp)(g), R2 // prepare stack as R2
   574		MOVW	(g_sched+gobuf_pc)(g), R4
   575		MOVW	R4, -12(R2)
   576		MOVW    ctxt+12(FP), R1
   577		MOVW    R1, -8(R2)
   578		MOVW	$-12(R2), R29
   579		JAL	runtime·cgocallbackg(SB)
   580	
   581		// Restore g->sched (== m->curg->sched) from saved values.
   582		MOVW	0(R29), R4
   583		MOVW	R4, (g_sched+gobuf_pc)(g)
   584		MOVW	$12(R29), R2
   585		MOVW	R2, (g_sched+gobuf_sp)(g)
   586	
   587		// Switch back to m->g0's stack and restore m->g0->sched.sp.
   588		// (Unlike m->curg, the g0 goroutine never uses sched.pc,
   589		// so we do not have to restore it.)
   590		MOVW	g_m(g), R3
   591		MOVW	m_g0(R3), g
   592		JAL	runtime·save_g(SB)
   593		MOVW	(g_sched+gobuf_sp)(g), R29
   594		MOVW	savedsp-8(SP), R2
   595		MOVW	R2, (g_sched+gobuf_sp)(g)
   596	
   597		// If the m on entry was nil, we called needm above to borrow an m
   598		// for the duration of the call. Since the call is over, return it with dropm.
   599		MOVW	savedm-4(SP), R3
   600		BNE	R3, droppedm
   601		MOVW	$runtime·dropm(SB), R4
   602		JAL	(R4)
   603	droppedm:
   604	
   605		// Done!
   606		RET
   607	
   608	// void setg(G*); set g. for use by needm.
   609	// This only happens if iscgo, so jump straight to save_g
   610	TEXT runtime·setg(SB),NOSPLIT,$0-4
   611		MOVW	gg+0(FP), g
   612		JAL	runtime·save_g(SB)
   613		RET
   614	
   615	// void setg_gcc(G*); set g in C TLS.
   616	// Must obey the gcc calling convention.
   617	TEXT setg_gcc<>(SB),NOSPLIT,$0
   618		MOVW	R4, g
   619		JAL	runtime·save_g(SB)
   620		RET
   621	
   622	TEXT runtime·getcallerpc(SB),NOSPLIT,$4-8
   623		MOVW	8(R29), R1	// LR saved by caller
   624		MOVW	R1, ret+4(FP)
   625		RET
   626	
   627	TEXT runtime·abort(SB),NOSPLIT,$0-0
   628		UNDEF
   629	
   630	// memhash_varlen(p unsafe.Pointer, h seed) uintptr
   631	// redirects to memhash(p, h, size) using the size
   632	// stored in the closure.
   633	TEXT runtime·memhash_varlen(SB),NOSPLIT,$16-12
   634		GO_ARGS
   635		NO_LOCAL_POINTERS
   636		MOVW	p+0(FP), R1
   637		MOVW	h+4(FP), R2
   638		MOVW	4(REGCTXT), R3
   639		MOVW	R1, 4(R29)
   640		MOVW	R2, 8(R29)
   641		MOVW	R3, 12(R29)
   642		JAL	runtime·memhash(SB)
   643		MOVW	16(R29), R1
   644		MOVW	R1, ret+8(FP)
   645		RET
   646	
   647	// Not implemented.
   648	TEXT runtime·aeshash(SB),NOSPLIT,$0
   649		UNDEF
   650	
   651	// Not implemented.
   652	TEXT runtime·aeshash32(SB),NOSPLIT,$0
   653		UNDEF
   654	
   655	// Not implemented.
   656	TEXT runtime·aeshash64(SB),NOSPLIT,$0
   657		UNDEF
   658	
   659	// Not implemented.
   660	TEXT runtime·aeshashstr(SB),NOSPLIT,$0
   661		UNDEF
   662	
   663	// memequal(a, b unsafe.Pointer, size uintptr) bool
   664	TEXT runtime·memequal(SB),NOSPLIT,$0-13
   665		MOVW	a+0(FP), R1
   666		MOVW	b+4(FP), R2
   667		BEQ	R1, R2, eq
   668		MOVW	size+8(FP), R3
   669		ADDU	R1, R3, R4
   670	loop:
   671		BNE	R1, R4, test
   672		MOVW	$1, R1
   673		MOVB	R1, ret+12(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+12(FP)
   683		RET
   684	eq:
   685		MOVW	$1, R1
   686		MOVB	R1, ret+12(FP)
   687		RET
   688	
   689	// memequal_varlen(a, b unsafe.Pointer) bool
   690	TEXT runtime·memequal_varlen(SB),NOSPLIT,$0-9
   691		MOVW	a+0(FP), R1
   692		MOVW	b+4(FP), R2
   693		BEQ	R1, R2, eq
   694		MOVW	4(REGCTXT), R3	// compiler stores size at offset 4 in the closure
   695		ADDU	R1, R3, R4
   696	loop:
   697		BNE	R1, R4, test
   698		MOVW	$1, R1
   699		MOVB	R1, ret+8(FP)
   700		RET
   701	test:
   702		MOVBU	(R1), R6
   703		ADDU	$1, R1
   704		MOVBU	(R2), R7
   705		ADDU	$1, R2
   706		BEQ	R6, R7, loop
   707	
   708		MOVB	R0, ret+8(FP)
   709		RET
   710	eq:
   711		MOVW	$1, R1
   712		MOVB	R1, ret+8(FP)
   713		RET
   714	
   715	// eqstring tests whether two strings are equal.
   716	// The compiler guarantees that strings passed
   717	// to eqstring have equal length.
   718	// See runtime_test.go:eqstring_generic for
   719	// equivalent Go code.
   720	TEXT runtime·eqstring(SB),NOSPLIT,$0-17
   721		MOVW	s1_base+0(FP), R1
   722		MOVW	s2_base+8(FP), R2
   723		MOVW	$1, R3
   724		MOVBU	R3, ret+16(FP)
   725		BNE	R1, R2, 2(PC)
   726		RET
   727		MOVW	s1_len+4(FP), R3
   728		ADDU	R1, R3, R4
   729	loop:
   730		BNE	R1, R4, 2(PC)
   731		RET
   732		MOVBU	(R1), R6
   733		ADDU	$1, R1
   734		MOVBU	(R2), R7
   735		ADDU	$1, R2
   736		BEQ	R6, R7, loop
   737		MOVB	R0, ret+16(FP)
   738		RET
   739	
   740	TEXT bytes·Equal(SB),NOSPLIT,$0-25
   741		MOVW	a_len+4(FP), R3
   742		MOVW	b_len+16(FP), R4
   743		BNE	R3, R4, noteq	// unequal lengths are not equal
   744	
   745		MOVW	a+0(FP), R1
   746		MOVW	b+12(FP), R2
   747		ADDU	R1, R3	// end
   748	
   749	loop:
   750		BEQ	R1, R3, equal	// reached the end
   751		MOVBU	(R1), R6
   752		ADDU	$1, R1
   753		MOVBU	(R2), R7
   754		ADDU	$1, R2
   755		BEQ	R6, R7, loop
   756	
   757	noteq:
   758		MOVB	R0, ret+24(FP)
   759		RET
   760	
   761	equal:
   762		MOVW	$1, R1
   763		MOVB	R1, ret+24(FP)
   764		RET
   765	
   766	TEXT bytes·IndexByte(SB),NOSPLIT,$0-20
   767		MOVW	s+0(FP), R1
   768		MOVW	s_len+4(FP), R2
   769		MOVBU	c+12(FP), R3	// byte to find
   770		ADDU	$1, R1, R4	// store base+1 for later
   771		ADDU	R1, R2	// end
   772	
   773	loop:
   774		BEQ	R1, R2, notfound
   775		MOVBU	(R1), R5
   776		ADDU	$1, R1
   777		BNE	R3, R5, loop
   778	
   779		SUBU	R4, R1	// R1 will be one beyond the position we want so remove (base+1)
   780		MOVW	R1, ret+16(FP)
   781		RET
   782	
   783	notfound:
   784		MOVW	$-1, R1
   785		MOVW	R1, ret+16(FP)
   786		RET
   787	
   788	TEXT strings·IndexByte(SB),NOSPLIT,$0-16
   789		MOVW	s_base+0(FP), R1
   790		MOVW	s_len+4(FP), R2
   791		MOVBU	c+8(FP), R3	// byte to find
   792		ADDU	$1, R1, R4	// store base+1 for later
   793		ADDU	R1, R2	// end
   794	
   795	loop:
   796		BEQ	R1, R2, notfound
   797		MOVBU	(R1), R5
   798		ADDU	$1, R1
   799		BNE	R3, R5, loop
   800	
   801		SUBU	R4, R1	// remove (base+1)
   802		MOVW	R1, ret+12(FP)
   803		RET
   804	
   805	notfound:
   806		MOVW	$-1, R1
   807		MOVW	R1, ret+12(FP)
   808		RET
   809	
   810	TEXT runtime·cmpstring(SB),NOSPLIT,$0-20
   811		MOVW	s1_base+0(FP), R3
   812		MOVW	s1_len+4(FP), R1
   813		MOVW	s2_base+8(FP), R4
   814		MOVW	s2_len+12(FP), R2
   815		BEQ	R3, R4, samebytes
   816		SGTU	R1, R2, R7
   817		MOVW	R1, R8
   818		CMOVN	R7, R2, R8	// R8 is min(R1, R2)
   819	
   820		ADDU	R3, R8	// R3 is current byte in s1, R8 is last byte in s1 to compare
   821	loop:
   822		BEQ	R3, R8, samebytes	// all compared bytes were the same; compare lengths
   823	
   824		MOVBU	(R3), R6
   825		ADDU	$1, R3
   826		MOVBU	(R4), R7
   827		ADDU	$1, R4
   828		BEQ	R6, R7 , loop
   829		// bytes differed
   830		SGTU	R6, R7, R8
   831		MOVW	$-1, R6
   832		CMOVZ	R8, R6, R8
   833		JMP	cmp_ret
   834	samebytes:
   835		SGTU	R1, R2, R6
   836		SGTU	R2, R1, R7
   837		SUBU	R7, R6, R8
   838	cmp_ret:
   839		MOVW	R8, ret+16(FP)
   840		RET
   841	
   842	TEXT bytes·Compare(SB),NOSPLIT,$0-28
   843		MOVW	s1_base+0(FP), R3
   844		MOVW	s2_base+12(FP), R4
   845		MOVW	s1_len+4(FP), R1
   846		MOVW	s2_len+16(FP), R2
   847		BEQ	R3, R4, samebytes
   848		SGTU	R1, R2, R7
   849		MOVW	R1, R8
   850		CMOVN	R7, R2, R8	// R8 is min(R1, R2)
   851	
   852		ADDU	R3, R8	// R3 is current byte in s1, R8 is last byte in s1 to compare
   853	loop:
   854		BEQ	R3, R8, samebytes
   855	
   856		MOVBU	(R3), R6
   857		ADDU	$1, R3
   858		MOVBU	(R4), R7
   859		ADDU	$1, R4
   860		BEQ	R6, R7 , loop
   861	
   862		SGTU	R6, R7, R8
   863		MOVW	$-1, R6
   864		CMOVZ	R8, R6, R8
   865		JMP	cmp_ret
   866	samebytes:
   867		SGTU	R1, R2, R6
   868		SGTU	R2, R1, R7
   869		SUBU	R7, R6, R8
   870	cmp_ret:
   871		MOVW	R8, ret+24(FP)
   872		RET
   873	
   874	TEXT runtime·return0(SB),NOSPLIT,$0
   875		MOVW	$0, R1
   876		RET
   877	
   878	// Called from cgo wrappers, this function returns g->m->curg.stack.hi.
   879	// Must obey the gcc calling convention.
   880	TEXT _cgo_topofstack(SB),NOSPLIT,$-4
   881		// g (R30), R3 and REGTMP (R23) might be clobbered by load_g. R30 and R23
   882		// are callee-save in the gcc calling convention, so save them.
   883		MOVW	R23, R8
   884		MOVW	g, R9
   885		MOVW	R31, R10 // this call frame does not save LR
   886	
   887		JAL	runtime·load_g(SB)
   888		MOVW	g_m(g), R1
   889		MOVW	m_curg(R1), R1
   890		MOVW	(g_stack+stack_hi)(R1), R2 // return value in R2
   891	
   892		MOVW	R8, R23
   893		MOVW	R9, g
   894		MOVW	R10, R31
   895	
   896		RET
   897	
   898	// The top-most function running on a goroutine
   899	// returns to goexit+PCQuantum.
   900	TEXT runtime·goexit(SB),NOSPLIT,$-4-0
   901		NOR	R0, R0	// NOP
   902		JAL	runtime·goexit1(SB)	// does not return
   903		// traceback from goexit1 must hit code range of goexit
   904		NOR	R0, R0	// NOP
   905	
   906	TEXT runtime·prefetcht0(SB),NOSPLIT,$0-4
   907		RET
   908	
   909	TEXT runtime·prefetcht1(SB),NOSPLIT,$0-4
   910		RET
   911	
   912	TEXT runtime·prefetcht2(SB),NOSPLIT,$0-4
   913		RET
   914	
   915	TEXT runtime·prefetchnta(SB),NOSPLIT,$0-4
   916		RET
   917	
   918	TEXT ·checkASM(SB),NOSPLIT,$0-1
   919		MOVW	$1, R1
   920		MOVB	R1, ret+0(FP)
   921		RET

View as plain text