...

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_ctxt(R3), REGCTXT
   111	MOVV	R0, gobuf_sp(R3)
   112	MOVV	R0, gobuf_lr(R3)
   113	MOVV	R0, gobuf_ctxt(R3)
   114	MOVV	gobuf_pc(R3), R4
   115	JMP	(R4)
   116
   117// void mcall(fn func(*g))
   118// Switch to m->g0's stack, call fn(g).
   119// Fn must never return. It should gogo(&g->sched)
   120// to keep running g.
   121TEXT runtime·mcall(SB), NOSPLIT|NOFRAME, $0-8
   122	// Save caller state in g->sched
   123	MOVV	R29, (g_sched+gobuf_sp)(g)
   124	MOVV	R31, (g_sched+gobuf_pc)(g)
   125	MOVV	R0, (g_sched+gobuf_lr)(g)
   126
   127	// Switch to m->g0 & its stack, call fn.
   128	MOVV	g, R1
   129	MOVV	g_m(g), R3
   130	MOVV	m_g0(R3), g
   131	JAL	runtime·save_g(SB)
   132	BNE	g, R1, 2(PC)
   133	JMP	runtime·badmcall(SB)
   134	MOVV	fn+0(FP), REGCTXT			// context
   135	MOVV	0(REGCTXT), R4			// code pointer
   136	MOVV	(g_sched+gobuf_sp)(g), R29	// sp = m->g0->sched.sp
   137	ADDV	$-16, R29
   138	MOVV	R1, 8(R29)
   139	MOVV	R0, 0(R29)
   140	JAL	(R4)
   141	JMP	runtime·badmcall2(SB)
   142
   143// systemstack_switch is a dummy routine that systemstack leaves at the bottom
   144// of the G stack. We need to distinguish the routine that
   145// lives at the bottom of the G stack from the one that lives
   146// at the top of the system stack because the one at the top of
   147// the system stack terminates the stack walk (see topofstack()).
   148TEXT runtime·systemstack_switch(SB), NOSPLIT, $0-0
   149	UNDEF
   150	JAL	(R31)	// make sure this function is not leaf
   151	RET
   152
   153// func systemstack(fn func())
   154TEXT runtime·systemstack(SB), NOSPLIT, $0-8
   155	MOVV	fn+0(FP), R1	// R1 = fn
   156	MOVV	R1, REGCTXT		// context
   157	MOVV	g_m(g), R2	// R2 = m
   158
   159	MOVV	m_gsignal(R2), R3	// R3 = gsignal
   160	BEQ	g, R3, noswitch
   161
   162	MOVV	m_g0(R2), R3	// R3 = g0
   163	BEQ	g, R3, noswitch
   164
   165	MOVV	m_curg(R2), R4
   166	BEQ	g, R4, switch
   167
   168	// Bad: g is not gsignal, not g0, not curg. What is it?
   169	// Hide call from linker nosplit analysis.
   170	MOVV	$runtime·badsystemstack(SB), R4
   171	JAL	(R4)
   172	JAL	runtime·abort(SB)
   173
   174switch:
   175	// save our state in g->sched. Pretend to
   176	// be systemstack_switch if the G stack is scanned.
   177	JAL	gosave_systemstack_switch<>(SB)
   178
   179	// switch to g0
   180	MOVV	R3, g
   181	JAL	runtime·save_g(SB)
   182	MOVV	(g_sched+gobuf_sp)(g), R1
   183	MOVV	R1, R29
   184
   185	// call target function
   186	MOVV	0(REGCTXT), R4	// code pointer
   187	JAL	(R4)
   188
   189	// switch back to g
   190	MOVV	g_m(g), R1
   191	MOVV	m_curg(R1), g
   192	JAL	runtime·save_g(SB)
   193	MOVV	(g_sched+gobuf_sp)(g), R29
   194	MOVV	R0, (g_sched+gobuf_sp)(g)
   195	RET
   196
   197noswitch:
   198	// already on m stack, just call directly
   199	// Using a tail call here cleans up tracebacks since we won't stop
   200	// at an intermediate systemstack.
   201	MOVV	0(REGCTXT), R4	// code pointer
   202	MOVV	0(R29), R31	// restore LR
   203	ADDV	$8, R29
   204	JMP	(R4)
   205
   206// func switchToCrashStack0(fn func())
   207TEXT runtime·switchToCrashStack0(SB), NOSPLIT, $0-8
   208	MOVV	fn+0(FP), REGCTXT	// context register
   209	MOVV	g_m(g), R2	// curm
   210
   211	// set g to gcrash
   212	MOVV	$runtime·gcrash(SB), g	// g = &gcrash
   213	CALL	runtime·save_g(SB)
   214	MOVV	R2, g_m(g)	// g.m = curm
   215	MOVV	g, m_g0(R2)	// curm.g0 = g
   216
   217	// switch to crashstack
   218	MOVV	(g_stack+stack_hi)(g), R2
   219	ADDV	$(-4*8), R2, R29
   220
   221	// call target function
   222	MOVV	0(REGCTXT), R25
   223	JAL	(R25)
   224
   225	// should never return
   226	CALL	runtime·abort(SB)
   227	UNDEF
   228
   229/*
   230 * support for morestack
   231 */
   232
   233// Called during function prolog when more stack is needed.
   234// Caller has already loaded:
   235// R1: framesize, R2: argsize, R3: LR
   236//
   237// The traceback routines see morestack on a g0 as being
   238// the top of a stack (for example, morestack calling newstack
   239// calling the scheduler calling newm calling gc), so we must
   240// record an argument size. For that purpose, it has no arguments.
   241TEXT runtime·morestack(SB),NOSPLIT|NOFRAME,$0-0
   242	// Called from f.
   243	// Set g->sched to context in f.
   244	MOVV	R29, (g_sched+gobuf_sp)(g)
   245	MOVV	R31, (g_sched+gobuf_pc)(g)
   246	MOVV	R3, (g_sched+gobuf_lr)(g)
   247	MOVV	REGCTXT, (g_sched+gobuf_ctxt)(g)
   248
   249	// Cannot grow scheduler stack (m->g0).
   250	MOVV	g_m(g), R7
   251	MOVV	m_g0(R7), R8
   252	BNE	g, R8, 3(PC)
   253	JAL	runtime·badmorestackg0(SB)
   254	JAL	runtime·abort(SB)
   255
   256	// Cannot grow signal stack (m->gsignal).
   257	MOVV	m_gsignal(R7), R8
   258	BNE	g, R8, 3(PC)
   259	JAL	runtime·badmorestackgsignal(SB)
   260	JAL	runtime·abort(SB)
   261
   262	// Called from f.
   263	// Set m->morebuf to f's caller.
   264	MOVV	R3, (m_morebuf+gobuf_pc)(R7)	// f's caller's PC
   265	MOVV	R29, (m_morebuf+gobuf_sp)(R7)	// f's caller's SP
   266	MOVV	g, (m_morebuf+gobuf_g)(R7)
   267
   268	// Call newstack on m->g0's stack.
   269	MOVV	m_g0(R7), g
   270	JAL	runtime·save_g(SB)
   271	MOVV	(g_sched+gobuf_sp)(g), R29
   272	// Create a stack frame on g0 to call newstack.
   273	MOVV	R0, -8(R29)	// Zero saved LR in frame
   274	ADDV	$-8, R29
   275	JAL	runtime·newstack(SB)
   276
   277	// Not reached, but make sure the return PC from the call to newstack
   278	// is still in this function, and not the beginning of the next.
   279	UNDEF
   280
   281TEXT runtime·morestack_noctxt(SB),NOSPLIT|NOFRAME,$0-0
   282	// Force SPWRITE. This function doesn't actually write SP,
   283	// but it is called with a special calling convention where
   284	// the caller doesn't save LR on stack but passes it as a
   285	// register (R3), and the unwinder currently doesn't understand.
   286	// Make it SPWRITE to stop unwinding. (See issue 54332)
   287	MOVV	R29, R29
   288
   289	MOVV	R0, REGCTXT
   290	JMP	runtime·morestack(SB)
   291
   292// reflectcall: call a function with the given argument list
   293// func call(stackArgsType *_type, f *FuncVal, stackArgs *byte, stackArgsSize, stackRetOffset, frameSize uint32, regArgs *abi.RegArgs).
   294// we don't have variable-sized frames, so we use a small number
   295// of constant-sized-frame functions to encode a few bits of size in the pc.
   296// Caution: ugly multiline assembly macros in your future!
   297
   298#define DISPATCH(NAME,MAXSIZE)		\
   299	MOVV	$MAXSIZE, R23;		\
   300	SGTU	R1, R23, R23;		\
   301	BNE	R23, 3(PC);			\
   302	MOVV	$NAME(SB), R4;	\
   303	JMP	(R4)
   304// Note: can't just "BR NAME(SB)" - bad inlining results.
   305
   306TEXT ·reflectcall(SB), NOSPLIT|NOFRAME, $0-48
   307	MOVWU	frameSize+32(FP), R1
   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	MOVV	$runtime·badreflectcall(SB), R4
   336	JMP	(R4)
   337
   338#define CALLFN(NAME,MAXSIZE)			\
   339TEXT NAME(SB), WRAPPER, $MAXSIZE-48;		\
   340	NO_LOCAL_POINTERS;			\
   341	/* copy arguments to stack */		\
   342	MOVV	stackArgs+16(FP), R1;			\
   343	MOVWU	stackArgsSize+24(FP), R2;			\
   344	MOVV	R29, R3;				\
   345	ADDV	$8, R3;			\
   346	ADDV	R3, R2;				\
   347	BEQ	R3, R2, 6(PC);				\
   348	MOVBU	(R1), R4;			\
   349	ADDV	$1, R1;			\
   350	MOVBU	R4, (R3);			\
   351	ADDV	$1, R3;			\
   352	JMP	-5(PC);				\
   353	/* call function */			\
   354	MOVV	f+8(FP), REGCTXT;			\
   355	MOVV	(REGCTXT), R4;			\
   356	PCDATA  $PCDATA_StackMapIndex, $0;	\
   357	JAL	(R4);				\
   358	/* copy return values back */		\
   359	MOVV	stackArgsType+0(FP), R5;		\
   360	MOVV	stackArgs+16(FP), R1;			\
   361	MOVWU	stackArgsSize+24(FP), R2;			\
   362	MOVWU	stackRetOffset+28(FP), R4;		\
   363	ADDV	$8, R29, R3;				\
   364	ADDV	R4, R3; 			\
   365	ADDV	R4, R1;				\
   366	SUBVU	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, $40-0
   375	MOVV	R5, 8(R29)
   376	MOVV	R1, 16(R29)
   377	MOVV	R3, 24(R29)
   378	MOVV	R2, 32(R29)
   379	MOVV	$0, 40(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-0
   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	MOVV	$runtime·systemstack_switch(SB), R1
   421	ADDV	$8, R1	// get past prologue
   422	MOVV	R1, (g_sched+gobuf_pc)(g)
   423	MOVV	R29, (g_sched+gobuf_sp)(g)
   424	MOVV	R0, (g_sched+gobuf_lr)(g)
   425	// Assert ctxt is zero. See func save.
   426	MOVV	(g_sched+gobuf_ctxt)(g), R1
   427	BEQ	R1, 2(PC)
   428	JAL	runtime·abort(SB)
   429	RET
   430
   431// func asmcgocall_no_g(fn, arg unsafe.Pointer)
   432// Call fn(arg) aligned appropriately for the gcc ABI.
   433// Called on a system stack, and there may be no g yet (during needm).
   434TEXT ·asmcgocall_no_g(SB),NOSPLIT,$0-16
   435	MOVV	fn+0(FP), R25
   436	MOVV	arg+8(FP), R4
   437	JAL	(R25)
   438	RET
   439
   440// func asmcgocall(fn, arg unsafe.Pointer) int32
   441// Call fn(arg) on the scheduler stack,
   442// aligned appropriately for the gcc ABI.
   443// See cgocall.go for more details.
   444TEXT ·asmcgocall(SB),NOSPLIT,$0-20
   445	MOVV	fn+0(FP), R25
   446	MOVV	arg+8(FP), R4
   447
   448	MOVV	R29, R3	// save original stack pointer
   449	MOVV	g, R2
   450
   451	// Figure out if we need to switch to m->g0 stack.
   452	// We get called to create new OS threads too, and those
   453	// come in on the m->g0 stack already. Or we might already
   454	// be on the m->gsignal stack.
   455	MOVV	g_m(g), R5
   456	MOVV	m_gsignal(R5), R6
   457	BEQ	R6, g, g0
   458	MOVV	m_g0(R5), R6
   459	BEQ	R6, g, g0
   460
   461	JAL	gosave_systemstack_switch<>(SB)
   462	MOVV	R6, g
   463	JAL	runtime·save_g(SB)
   464	MOVV	(g_sched+gobuf_sp)(g), R29
   465
   466	// Now on a scheduling stack (a pthread-created stack).
   467g0:
   468	// Save room for two of our pointers.
   469	ADDV	$-16, R29
   470	MOVV	R2, 0(R29)	// save old g on stack
   471	MOVV	(g_stack+stack_hi)(R2), R2
   472	SUBVU	R3, R2
   473	MOVV	R2, 8(R29)	// save depth in old g stack (can't just save SP, as stack might be copied during a callback)
   474	JAL	(R25)
   475
   476	// Restore g, stack pointer. R2 is return value.
   477	MOVV	0(R29), g
   478	JAL	runtime·save_g(SB)
   479	MOVV	(g_stack+stack_hi)(g), R5
   480	MOVV	8(R29), R6
   481	SUBVU	R6, R5
   482	MOVV	R5, R29
   483
   484	MOVW	R2, ret+16(FP)
   485	RET
   486
   487// func cgocallback(fn, frame unsafe.Pointer, ctxt uintptr)
   488// See cgocall.go for more details.
   489TEXT ·cgocallback(SB),NOSPLIT,$24-24
   490	NO_LOCAL_POINTERS
   491
   492	// Skip cgocallbackg, just dropm when fn is nil, and frame is the saved g.
   493	// It is used to dropm while thread is exiting.
   494	MOVV	fn+0(FP), R5
   495	BNE	R5, loadg
   496	// Restore the g from frame.
   497	MOVV	frame+8(FP), g
   498	JMP	dropm
   499
   500loadg:
   501	// Load m and g from thread-local storage.
   502	MOVB	runtime·iscgo(SB), R1
   503	BEQ	R1, nocgo
   504	JAL	runtime·load_g(SB)
   505nocgo:
   506
   507	// If g is nil, Go did not create the current thread,
   508	// or if this thread never called into Go on pthread platforms.
   509	// Call needm to obtain one for temporary use.
   510	// In this case, we're running on the thread stack, so there's
   511	// lots of space, but the linker doesn't know. Hide the call from
   512	// the linker analysis by using an indirect call.
   513	BEQ	g, needm
   514
   515	MOVV	g_m(g), R3
   516	MOVV	R3, savedm-8(SP)
   517	JMP	havem
   518
   519needm:
   520	MOVV	g, savedm-8(SP) // g is zero, so is m.
   521	MOVV	$runtime·needAndBindM(SB), R4
   522	JAL	(R4)
   523
   524	// Set m->sched.sp = SP, so that if a panic happens
   525	// during the function we are about to execute, it will
   526	// have a valid SP to run on the g0 stack.
   527	// The next few lines (after the havem label)
   528	// will save this SP onto the stack and then write
   529	// the same SP back to m->sched.sp. That seems redundant,
   530	// but if an unrecovered panic happens, unwindm will
   531	// restore the g->sched.sp from the stack location
   532	// and then systemstack will try to use it. If we don't set it here,
   533	// that restored SP will be uninitialized (typically 0) and
   534	// will not be usable.
   535	MOVV	g_m(g), R3
   536	MOVV	m_g0(R3), R1
   537	MOVV	R29, (g_sched+gobuf_sp)(R1)
   538
   539havem:
   540	// Now there's a valid m, and we're running on its m->g0.
   541	// Save current m->g0->sched.sp on stack and then set it to SP.
   542	// Save current sp in m->g0->sched.sp in preparation for
   543	// switch back to m->curg stack.
   544	// NOTE: unwindm knows that the saved g->sched.sp is at 8(R29) aka savedsp-16(SP).
   545	MOVV	m_g0(R3), R1
   546	MOVV	(g_sched+gobuf_sp)(R1), R2
   547	MOVV	R2, savedsp-24(SP)	// must match frame size
   548	MOVV	R29, (g_sched+gobuf_sp)(R1)
   549
   550	// Switch to m->curg stack and call runtime.cgocallbackg.
   551	// Because we are taking over the execution of m->curg
   552	// but *not* resuming what had been running, we need to
   553	// save that information (m->curg->sched) so we can restore it.
   554	// We can restore m->curg->sched.sp easily, because calling
   555	// runtime.cgocallbackg leaves SP unchanged upon return.
   556	// To save m->curg->sched.pc, we push it onto the curg stack and
   557	// open a frame the same size as cgocallback's g0 frame.
   558	// Once we switch to the curg stack, the pushed PC will appear
   559	// to be the return PC of cgocallback, so that the traceback
   560	// will seamlessly trace back into the earlier calls.
   561	MOVV	m_curg(R3), g
   562	JAL	runtime·save_g(SB)
   563	MOVV	(g_sched+gobuf_sp)(g), R2 // prepare stack as R2
   564	MOVV	(g_sched+gobuf_pc)(g), R4
   565	MOVV	R4, -(24+8)(R2)	// "saved LR"; must match frame size
   566	// Gather our arguments into registers.
   567	MOVV	fn+0(FP), R5
   568	MOVV	frame+8(FP), R6
   569	MOVV	ctxt+16(FP), R7
   570	MOVV	$-(24+8)(R2), R29	// switch stack; must match frame size
   571	MOVV	R5, 8(R29)
   572	MOVV	R6, 16(R29)
   573	MOVV	R7, 24(R29)
   574	JAL	runtime·cgocallbackg(SB)
   575
   576	// Restore g->sched (== m->curg->sched) from saved values.
   577	MOVV	0(R29), R4
   578	MOVV	R4, (g_sched+gobuf_pc)(g)
   579	MOVV	$(24+8)(R29), R2	// must match frame size
   580	MOVV	R2, (g_sched+gobuf_sp)(g)
   581
   582	// Switch back to m->g0's stack and restore m->g0->sched.sp.
   583	// (Unlike m->curg, the g0 goroutine never uses sched.pc,
   584	// so we do not have to restore it.)
   585	MOVV	g_m(g), R3
   586	MOVV	m_g0(R3), g
   587	JAL	runtime·save_g(SB)
   588	MOVV	(g_sched+gobuf_sp)(g), R29
   589	MOVV	savedsp-24(SP), R2	// must match frame size
   590	MOVV	R2, (g_sched+gobuf_sp)(g)
   591
   592	// If the m on entry was nil, we called needm above to borrow an m,
   593	// 1. for the duration of the call on non-pthread platforms,
   594	// 2. or the duration of the C thread alive on pthread platforms.
   595	// If the m on entry wasn't nil,
   596	// 1. the thread might be a Go thread,
   597	// 2. or it wasn't the first call from a C thread on pthread platforms,
   598	//    since then we skip dropm to reuse the m in the first call.
   599	MOVV	savedm-8(SP), R3
   600	BNE	R3, droppedm
   601
   602	// Skip dropm to reuse it in the next call, when a pthread key has been created.
   603	MOVV	_cgo_pthread_key_created(SB), R3
   604	// It means cgo is disabled when _cgo_pthread_key_created is a nil pointer, need dropm.
   605	BEQ	R3, dropm
   606	MOVV	(R3), R3
   607	BNE	R3, droppedm
   608
   609dropm:
   610	MOVV	$runtime·dropm(SB), R4
   611	JAL	(R4)
   612droppedm:
   613
   614	// Done!
   615	RET
   616
   617// void setg(G*); set g. for use by needm.
   618TEXT runtime·setg(SB), NOSPLIT, $0-8
   619	MOVV	gg+0(FP), g
   620	// This only happens if iscgo, so jump straight to save_g
   621	JAL	runtime·save_g(SB)
   622	RET
   623
   624// void setg_gcc(G*); set g called from gcc with g in R1
   625TEXT setg_gcc<>(SB),NOSPLIT,$0-0
   626	MOVV	R1, g
   627	JAL	runtime·save_g(SB)
   628	RET
   629
   630TEXT runtime·abort(SB),NOSPLIT|NOFRAME,$0-0
   631	MOVW	(R0), R0
   632	UNDEF
   633
   634// AES hashing not implemented for mips64
   635TEXT runtime·memhash(SB),NOSPLIT|NOFRAME,$0-32
   636	JMP	runtime·memhashFallback(SB)
   637TEXT runtime·strhash(SB),NOSPLIT|NOFRAME,$0-24
   638	JMP	runtime·strhashFallback(SB)
   639TEXT runtime·memhash32(SB),NOSPLIT|NOFRAME,$0-24
   640	JMP	runtime·memhash32Fallback(SB)
   641TEXT runtime·memhash64(SB),NOSPLIT|NOFRAME,$0-24
   642	JMP	runtime·memhash64Fallback(SB)
   643
   644// Called from cgo wrappers, this function returns g->m->curg.stack.hi.
   645// Must obey the gcc calling convention.
   646TEXT _cgo_topofstack(SB),NOSPLIT,$16
   647	// g (R30) and REGTMP (R23)  might be clobbered by load_g. They
   648	// are callee-save in the gcc calling convention, so save them.
   649	MOVV	R23, savedR23-16(SP)
   650	MOVV	g, savedG-8(SP)
   651
   652	JAL	runtime·load_g(SB)
   653	MOVV	g_m(g), R1
   654	MOVV	m_curg(R1), R1
   655	MOVV	(g_stack+stack_hi)(R1), R2 // return value in R2
   656
   657	MOVV	savedG-8(SP), g
   658	MOVV	savedR23-16(SP), R23
   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,$192
   684	// Save the registers clobbered by the fast path.
   685	MOVV	R1, 184(R29)
   686	MOVV	R2, 192(R29)
   687retry:
   688	MOVV	g_m(g), R1
   689	MOVV	m_p(R1), R1
   690	MOVV	(p_wbBuf+wbBuf_next)(R1), R2
   691	MOVV	(p_wbBuf+wbBuf_end)(R1), R23 // R23 is linker temp register
   692	// Increment wbBuf.next position.
   693	ADDV	R25, R2
   694	// Is the buffer full?
   695	SGTU	R2, R23, R23
   696	BNE	R23, flush
   697	// Commit to the larger buffer.
   698	MOVV	R2, (p_wbBuf+wbBuf_next)(R1)
   699	// Make return value (the original next position)
   700	SUBV	R25, R2, R25
   701	// Restore registers.
   702	MOVV	184(R29), R1
   703	MOVV	192(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	MOVV	R20, 8(R29)
   710	MOVV	R21, 16(R29)
   711	// R1 already saved
   712	// R2 already saved
   713	MOVV	R3, 24(R29)
   714	MOVV	R4, 32(R29)
   715	MOVV	R5, 40(R29)
   716	MOVV	R6, 48(R29)
   717	MOVV	R7, 56(R29)
   718	MOVV	R8, 64(R29)
   719	MOVV	R9, 72(R29)
   720	MOVV	R10, 80(R29)
   721	MOVV	R11, 88(R29)
   722	MOVV	R12, 96(R29)
   723	MOVV	R13, 104(R29)
   724	MOVV	R14, 112(R29)
   725	MOVV	R15, 120(R29)
   726	MOVV	R16, 128(R29)
   727	MOVV	R17, 136(R29)
   728	MOVV	R18, 144(R29)
   729	MOVV	R19, 152(R29)
   730	// R20 already saved
   731	// R21 already saved.
   732	MOVV	R22, 160(R29)
   733	// R23 is tmp register.
   734	MOVV	R24, 168(R29)
   735	MOVV	R25, 176(R29)
   736	// R26 is reserved by kernel.
   737	// R27 is reserved by kernel.
   738	// R28 is REGSB (not modified by Go code).
   739	// R29 is SP.
   740	// R30 is g.
   741	// R31 is LR, which was saved by the prologue.
   742
   743	CALL	runtime·wbBufFlush(SB)
   744
   745	MOVV	8(R29), R20
   746	MOVV	16(R29), R21
   747	MOVV	24(R29), R3
   748	MOVV	32(R29), R4
   749	MOVV	40(R29), R5
   750	MOVV	48(R29), R6
   751	MOVV	56(R29), R7
   752	MOVV	64(R29), R8
   753	MOVV	72(R29), R9
   754	MOVV	80(R29), R10
   755	MOVV	88(R29), R11
   756	MOVV	96(R29), R12
   757	MOVV	104(R29), R13
   758	MOVV	112(R29), R14
   759	MOVV	120(R29), R15
   760	MOVV	128(R29), R16
   761	MOVV	136(R29), R17
   762	MOVV	144(R29), R18
   763	MOVV	152(R29), R19
   764	MOVV	160(R29), R22
   765	MOVV	168(R29), R24
   766	MOVV	176(R29), R25
   767	JMP	retry
   768
   769TEXT runtime·gcWriteBarrier1<ABIInternal>(SB),NOSPLIT,$0
   770	MOVV	$8, R25
   771	JMP	gcWriteBarrier<>(SB)
   772TEXT runtime·gcWriteBarrier2<ABIInternal>(SB),NOSPLIT,$0
   773	MOVV	$16, R25
   774	JMP	gcWriteBarrier<>(SB)
   775TEXT runtime·gcWriteBarrier3<ABIInternal>(SB),NOSPLIT,$0
   776	MOVV	$24, R25
   777	JMP	gcWriteBarrier<>(SB)
   778TEXT runtime·gcWriteBarrier4<ABIInternal>(SB),NOSPLIT,$0
   779	MOVV	$32, R25
   780	JMP	gcWriteBarrier<>(SB)
   781TEXT runtime·gcWriteBarrier5<ABIInternal>(SB),NOSPLIT,$0
   782	MOVV	$40, R25
   783	JMP	gcWriteBarrier<>(SB)
   784TEXT runtime·gcWriteBarrier6<ABIInternal>(SB),NOSPLIT,$0
   785	MOVV	$48, R25
   786	JMP	gcWriteBarrier<>(SB)
   787TEXT runtime·gcWriteBarrier7<ABIInternal>(SB),NOSPLIT,$0
   788	MOVV	$56, R25
   789	JMP	gcWriteBarrier<>(SB)
   790TEXT runtime·gcWriteBarrier8<ABIInternal>(SB),NOSPLIT,$0
   791	MOVV	$64, R25
   792	JMP	gcWriteBarrier<>(SB)
   793
   794// Note: these functions use a special calling convention to save generated code space.
   795// Arguments are passed in registers, but the space for those arguments are allocated
   796// in the caller's stack frame. These stubs write the args into that stack space and
   797// then tail call to the corresponding runtime handler.
   798// The tail call makes these stubs disappear in backtraces.
   799TEXT runtime·panicIndex(SB),NOSPLIT,$0-16
   800	MOVV	R1, x+0(FP)
   801	MOVV	R2, y+8(FP)
   802	JMP	runtime·goPanicIndex(SB)
   803TEXT runtime·panicIndexU(SB),NOSPLIT,$0-16
   804	MOVV	R1, x+0(FP)
   805	MOVV	R2, y+8(FP)
   806	JMP	runtime·goPanicIndexU(SB)
   807TEXT runtime·panicSliceAlen(SB),NOSPLIT,$0-16
   808	MOVV	R2, x+0(FP)
   809	MOVV	R3, y+8(FP)
   810	JMP	runtime·goPanicSliceAlen(SB)
   811TEXT runtime·panicSliceAlenU(SB),NOSPLIT,$0-16
   812	MOVV	R2, x+0(FP)
   813	MOVV	R3, y+8(FP)
   814	JMP	runtime·goPanicSliceAlenU(SB)
   815TEXT runtime·panicSliceAcap(SB),NOSPLIT,$0-16
   816	MOVV	R2, x+0(FP)
   817	MOVV	R3, y+8(FP)
   818	JMP	runtime·goPanicSliceAcap(SB)
   819TEXT runtime·panicSliceAcapU(SB),NOSPLIT,$0-16
   820	MOVV	R2, x+0(FP)
   821	MOVV	R3, y+8(FP)
   822	JMP	runtime·goPanicSliceAcapU(SB)
   823TEXT runtime·panicSliceB(SB),NOSPLIT,$0-16
   824	MOVV	R1, x+0(FP)
   825	MOVV	R2, y+8(FP)
   826	JMP	runtime·goPanicSliceB(SB)
   827TEXT runtime·panicSliceBU(SB),NOSPLIT,$0-16
   828	MOVV	R1, x+0(FP)
   829	MOVV	R2, y+8(FP)
   830	JMP	runtime·goPanicSliceBU(SB)
   831TEXT runtime·panicSlice3Alen(SB),NOSPLIT,$0-16
   832	MOVV	R3, x+0(FP)
   833	MOVV	R4, y+8(FP)
   834	JMP	runtime·goPanicSlice3Alen(SB)
   835TEXT runtime·panicSlice3AlenU(SB),NOSPLIT,$0-16
   836	MOVV	R3, x+0(FP)
   837	MOVV	R4, y+8(FP)
   838	JMP	runtime·goPanicSlice3AlenU(SB)
   839TEXT runtime·panicSlice3Acap(SB),NOSPLIT,$0-16
   840	MOVV	R3, x+0(FP)
   841	MOVV	R4, y+8(FP)
   842	JMP	runtime·goPanicSlice3Acap(SB)
   843TEXT runtime·panicSlice3AcapU(SB),NOSPLIT,$0-16
   844	MOVV	R3, x+0(FP)
   845	MOVV	R4, y+8(FP)
   846	JMP	runtime·goPanicSlice3AcapU(SB)
   847TEXT runtime·panicSlice3B(SB),NOSPLIT,$0-16
   848	MOVV	R2, x+0(FP)
   849	MOVV	R3, y+8(FP)
   850	JMP	runtime·goPanicSlice3B(SB)
   851TEXT runtime·panicSlice3BU(SB),NOSPLIT,$0-16
   852	MOVV	R2, x+0(FP)
   853	MOVV	R3, y+8(FP)
   854	JMP	runtime·goPanicSlice3BU(SB)
   855TEXT runtime·panicSlice3C(SB),NOSPLIT,$0-16
   856	MOVV	R1, x+0(FP)
   857	MOVV	R2, y+8(FP)
   858	JMP	runtime·goPanicSlice3C(SB)
   859TEXT runtime·panicSlice3CU(SB),NOSPLIT,$0-16
   860	MOVV	R1, x+0(FP)
   861	MOVV	R2, y+8(FP)
   862	JMP	runtime·goPanicSlice3CU(SB)
   863TEXT runtime·panicSliceConvert(SB),NOSPLIT,$0-16
   864	MOVV	R3, x+0(FP)
   865	MOVV	R4, y+8(FP)
   866	JMP	runtime·goPanicSliceConvert(SB)

View as plain text