...

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

View as plain text