...

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

View as plain text