...

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

View as plain text