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

View as plain text