...

Text file src/runtime/asm_mips64x.s

Documentation: runtime

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

View as plain text