github.com/dara-project/godist@v0.0.0-20200823115410-e0c80c8f0c78/src/runtime/asm_mips64x.s (about)

     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  // +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  
    14  TEXT runtime·rt0_go(SB),NOSPLIT,$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  
    41  nocgo:
    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	$-24, R29
    66  	MOVV	R1, 16(R29)
    67  	MOVV	R0, 8(R29)
    68  	MOVV	R0, 0(R29)
    69  	JAL	runtime·newproc(SB)
    70  	ADDV	$24, R29
    71  
    72  	// start this M
    73  	JAL	runtime·mstart(SB)
    74  
    75  	MOVV	R0, 1(R0)
    76  	RET
    77  
    78  DATA	runtime·mainPC+0(SB)/8,$runtime·main(SB)
    79  GLOBL	runtime·mainPC(SB),RODATA,$8
    80  
    81  TEXT runtime·breakpoint(SB),NOSPLIT,$-8-0
    82  	MOVV	R0, 2(R0) // TODO: TD
    83  	RET
    84  
    85  TEXT runtime·asminit(SB),NOSPLIT,$-8-0
    86  	RET
    87  
    88  /*
    89   *  go-routine
    90   */
    91  
    92  // void gosave(Gobuf*)
    93  // save state in Gobuf; setjmp
    94  TEXT runtime·gosave(SB), NOSPLIT, $-8-8
    95  	MOVV	buf+0(FP), R1
    96  	MOVV	R29, gobuf_sp(R1)
    97  	MOVV	R31, gobuf_pc(R1)
    98  	MOVV	g, gobuf_g(R1)
    99  	MOVV	R0, gobuf_lr(R1)
   100  	MOVV	R0, gobuf_ret(R1)
   101  	// Assert ctxt is zero. See func save.
   102  	MOVV	gobuf_ctxt(R1), R1
   103  	BEQ	R1, 2(PC)
   104  	JAL	runtime·badctxt(SB)
   105  	RET
   106  
   107  // void gogo(Gobuf*)
   108  // restore state from Gobuf; longjmp
   109  TEXT runtime·gogo(SB), NOSPLIT, $16-8
   110  	MOVV	buf+0(FP), R3
   111  	MOVV	gobuf_g(R3), g	// make sure g is not nil
   112  	JAL	runtime·save_g(SB)
   113  
   114  	MOVV	0(g), R2
   115  	MOVV	gobuf_sp(R3), R29
   116  	MOVV	gobuf_lr(R3), R31
   117  	MOVV	gobuf_ret(R3), R1
   118  	MOVV	gobuf_ctxt(R3), REGCTXT
   119  	MOVV	R0, gobuf_sp(R3)
   120  	MOVV	R0, gobuf_ret(R3)
   121  	MOVV	R0, gobuf_lr(R3)
   122  	MOVV	R0, gobuf_ctxt(R3)
   123  	MOVV	gobuf_pc(R3), R4
   124  	JMP	(R4)
   125  
   126  // void mcall(fn func(*g))
   127  // Switch to m->g0's stack, call fn(g).
   128  // Fn must never return. It should gogo(&g->sched)
   129  // to keep running g.
   130  TEXT runtime·mcall(SB), NOSPLIT, $-8-8
   131  	// Save caller state in g->sched
   132  	MOVV	R29, (g_sched+gobuf_sp)(g)
   133  	MOVV	R31, (g_sched+gobuf_pc)(g)
   134  	MOVV	R0, (g_sched+gobuf_lr)(g)
   135  	MOVV	g, (g_sched+gobuf_g)(g)
   136  
   137  	// Switch to m->g0 & its stack, call fn.
   138  	MOVV	g, R1
   139  	MOVV	g_m(g), R3
   140  	MOVV	m_g0(R3), g
   141  	JAL	runtime·save_g(SB)
   142  	BNE	g, R1, 2(PC)
   143  	JMP	runtime·badmcall(SB)
   144  	MOVV	fn+0(FP), REGCTXT			// context
   145  	MOVV	0(REGCTXT), R4			// code pointer
   146  	MOVV	(g_sched+gobuf_sp)(g), R29	// sp = m->g0->sched.sp
   147  	ADDV	$-16, R29
   148  	MOVV	R1, 8(R29)
   149  	MOVV	R0, 0(R29)
   150  	JAL	(R4)
   151  	JMP	runtime·badmcall2(SB)
   152  
   153  // systemstack_switch is a dummy routine that systemstack leaves at the bottom
   154  // of the G stack. We need to distinguish the routine that
   155  // lives at the bottom of the G stack from the one that lives
   156  // at the top of the system stack because the one at the top of
   157  // the system stack terminates the stack walk (see topofstack()).
   158  TEXT runtime·systemstack_switch(SB), NOSPLIT, $0-0
   159  	UNDEF
   160  	JAL	(R31)	// make sure this function is not leaf
   161  	RET
   162  
   163  // func systemstack(fn func())
   164  TEXT runtime·systemstack(SB), NOSPLIT, $0-8
   165  	MOVV	fn+0(FP), R1	// R1 = fn
   166  	MOVV	R1, REGCTXT		// context
   167  	MOVV	g_m(g), R2	// R2 = m
   168  
   169  	MOVV	m_gsignal(R2), R3	// R3 = gsignal
   170  	BEQ	g, R3, noswitch
   171  
   172  	MOVV	m_g0(R2), R3	// R3 = g0
   173  	BEQ	g, R3, noswitch
   174  
   175  	MOVV	m_curg(R2), R4
   176  	BEQ	g, R4, switch
   177  
   178  	// Bad: g is not gsignal, not g0, not curg. What is it?
   179  	// Hide call from linker nosplit analysis.
   180  	MOVV	$runtime·badsystemstack(SB), R4
   181  	JAL	(R4)
   182  
   183  switch:
   184  	// save our state in g->sched. Pretend to
   185  	// be systemstack_switch if the G stack is scanned.
   186  	MOVV	$runtime·systemstack_switch(SB), R4
   187  	ADDV	$8, R4	// get past prologue
   188  	MOVV	R4, (g_sched+gobuf_pc)(g)
   189  	MOVV	R29, (g_sched+gobuf_sp)(g)
   190  	MOVV	R0, (g_sched+gobuf_lr)(g)
   191  	MOVV	g, (g_sched+gobuf_g)(g)
   192  
   193  	// switch to g0
   194  	MOVV	R3, g
   195  	JAL	runtime·save_g(SB)
   196  	MOVV	(g_sched+gobuf_sp)(g), R1
   197  	// make it look like mstart called systemstack on g0, to stop traceback
   198  	ADDV	$-8, R1
   199  	MOVV	$runtime·mstart(SB), R2
   200  	MOVV	R2, 0(R1)
   201  	MOVV	R1, R29
   202  
   203  	// call target function
   204  	MOVV	0(REGCTXT), R4	// code pointer
   205  	JAL	(R4)
   206  
   207  	// switch back to g
   208  	MOVV	g_m(g), R1
   209  	MOVV	m_curg(R1), g
   210  	JAL	runtime·save_g(SB)
   211  	MOVV	(g_sched+gobuf_sp)(g), R29
   212  	MOVV	R0, (g_sched+gobuf_sp)(g)
   213  	RET
   214  
   215  noswitch:
   216  	// already on m stack, just call directly
   217  	// Using a tail call here cleans up tracebacks since we won't stop
   218  	// at an intermediate systemstack.
   219  	MOVV	0(REGCTXT), R4	// code pointer
   220  	MOVV	0(R29), R31	// restore LR
   221  	ADDV	$8, R29
   222  	JMP	(R4)
   223  
   224  /*
   225   * support for morestack
   226   */
   227  
   228  // Called during function prolog when more stack is needed.
   229  // Caller has already loaded:
   230  // R1: framesize, R2: argsize, R3: LR
   231  //
   232  // The traceback routines see morestack on a g0 as being
   233  // the top of a stack (for example, morestack calling newstack
   234  // calling the scheduler calling newm calling gc), so we must
   235  // record an argument size. For that purpose, it has no arguments.
   236  TEXT runtime·morestack(SB),NOSPLIT,$-8-0
   237  	// Cannot grow scheduler stack (m->g0).
   238  	MOVV	g_m(g), R7
   239  	MOVV	m_g0(R7), R8
   240  	BNE	g, R8, 3(PC)
   241  	JAL	runtime·badmorestackg0(SB)
   242  	JAL	runtime·abort(SB)
   243  
   244  	// Cannot grow signal stack (m->gsignal).
   245  	MOVV	m_gsignal(R7), R8
   246  	BNE	g, R8, 3(PC)
   247  	JAL	runtime·badmorestackgsignal(SB)
   248  	JAL	runtime·abort(SB)
   249  
   250  	// Called from f.
   251  	// Set g->sched to context in f.
   252  	MOVV	R29, (g_sched+gobuf_sp)(g)
   253  	MOVV	R31, (g_sched+gobuf_pc)(g)
   254  	MOVV	R3, (g_sched+gobuf_lr)(g)
   255  	MOVV	REGCTXT, (g_sched+gobuf_ctxt)(g)
   256  
   257  	// Called from f.
   258  	// Set m->morebuf to f's caller.
   259  	MOVV	R3, (m_morebuf+gobuf_pc)(R7)	// f's caller's PC
   260  	MOVV	R29, (m_morebuf+gobuf_sp)(R7)	// f's caller's SP
   261  	MOVV	g, (m_morebuf+gobuf_g)(R7)
   262  
   263  	// Call newstack on m->g0's stack.
   264  	MOVV	m_g0(R7), g
   265  	JAL	runtime·save_g(SB)
   266  	MOVV	(g_sched+gobuf_sp)(g), R29
   267  	// Create a stack frame on g0 to call newstack.
   268  	MOVV	R0, -8(R29)	// Zero saved LR in frame
   269  	ADDV	$-8, R29
   270  	JAL	runtime·newstack(SB)
   271  
   272  	// Not reached, but make sure the return PC from the call to newstack
   273  	// is still in this function, and not the beginning of the next.
   274  	UNDEF
   275  
   276  TEXT runtime·morestack_noctxt(SB),NOSPLIT,$-8-0
   277  	MOVV	R0, REGCTXT
   278  	JMP	runtime·morestack(SB)
   279  
   280  // reflectcall: call a function with the given argument list
   281  // func call(argtype *_type, f *FuncVal, arg *byte, argsize, retoffset uint32).
   282  // we don't have variable-sized frames, so we use a small number
   283  // of constant-sized-frame functions to encode a few bits of size in the pc.
   284  // Caution: ugly multiline assembly macros in your future!
   285  
   286  #define DISPATCH(NAME,MAXSIZE)		\
   287  	MOVV	$MAXSIZE, R23;		\
   288  	SGTU	R1, R23, R23;		\
   289  	BNE	R23, 3(PC);			\
   290  	MOVV	$NAME(SB), R4;	\
   291  	JMP	(R4)
   292  // Note: can't just "BR NAME(SB)" - bad inlining results.
   293  
   294  TEXT reflect·call(SB), NOSPLIT, $0-0
   295  	JMP	·reflectcall(SB)
   296  
   297  TEXT ·reflectcall(SB), NOSPLIT, $-8-32
   298  	MOVWU argsize+24(FP), R1
   299  	DISPATCH(runtime·call32, 32)
   300  	DISPATCH(runtime·call64, 64)
   301  	DISPATCH(runtime·call128, 128)
   302  	DISPATCH(runtime·call256, 256)
   303  	DISPATCH(runtime·call512, 512)
   304  	DISPATCH(runtime·call1024, 1024)
   305  	DISPATCH(runtime·call2048, 2048)
   306  	DISPATCH(runtime·call4096, 4096)
   307  	DISPATCH(runtime·call8192, 8192)
   308  	DISPATCH(runtime·call16384, 16384)
   309  	DISPATCH(runtime·call32768, 32768)
   310  	DISPATCH(runtime·call65536, 65536)
   311  	DISPATCH(runtime·call131072, 131072)
   312  	DISPATCH(runtime·call262144, 262144)
   313  	DISPATCH(runtime·call524288, 524288)
   314  	DISPATCH(runtime·call1048576, 1048576)
   315  	DISPATCH(runtime·call2097152, 2097152)
   316  	DISPATCH(runtime·call4194304, 4194304)
   317  	DISPATCH(runtime·call8388608, 8388608)
   318  	DISPATCH(runtime·call16777216, 16777216)
   319  	DISPATCH(runtime·call33554432, 33554432)
   320  	DISPATCH(runtime·call67108864, 67108864)
   321  	DISPATCH(runtime·call134217728, 134217728)
   322  	DISPATCH(runtime·call268435456, 268435456)
   323  	DISPATCH(runtime·call536870912, 536870912)
   324  	DISPATCH(runtime·call1073741824, 1073741824)
   325  	MOVV	$runtime·badreflectcall(SB), R4
   326  	JMP	(R4)
   327  
   328  #define CALLFN(NAME,MAXSIZE)			\
   329  TEXT NAME(SB), WRAPPER, $MAXSIZE-24;		\
   330  	NO_LOCAL_POINTERS;			\
   331  	/* copy arguments to stack */		\
   332  	MOVV	arg+16(FP), R1;			\
   333  	MOVWU	argsize+24(FP), R2;			\
   334  	MOVV	R29, R3;				\
   335  	ADDV	$8, R3;			\
   336  	ADDV	R3, R2;				\
   337  	BEQ	R3, R2, 6(PC);				\
   338  	MOVBU	(R1), R4;			\
   339  	ADDV	$1, R1;			\
   340  	MOVBU	R4, (R3);			\
   341  	ADDV	$1, R3;			\
   342  	JMP	-5(PC);				\
   343  	/* call function */			\
   344  	MOVV	f+8(FP), REGCTXT;			\
   345  	MOVV	(REGCTXT), R4;			\
   346  	PCDATA  $PCDATA_StackMapIndex, $0;	\
   347  	JAL	(R4);				\
   348  	/* copy return values back */		\
   349  	MOVV	argtype+0(FP), R5;		\
   350  	MOVV	arg+16(FP), R1;			\
   351  	MOVWU	n+24(FP), R2;			\
   352  	MOVWU	retoffset+28(FP), R4;		\
   353  	ADDV	$8, R29, R3;				\
   354  	ADDV	R4, R3; 			\
   355  	ADDV	R4, R1;				\
   356  	SUBVU	R4, R2;				\
   357  	JAL	callRet<>(SB);			\
   358  	RET
   359  
   360  // callRet copies return values back at the end of call*. This is a
   361  // separate function so it can allocate stack space for the arguments
   362  // to reflectcallmove. It does not follow the Go ABI; it expects its
   363  // arguments in registers.
   364  TEXT callRet<>(SB), NOSPLIT, $32-0
   365  	MOVV	R5, 8(R29)
   366  	MOVV	R1, 16(R29)
   367  	MOVV	R3, 24(R29)
   368  	MOVV	R2, 32(R29)
   369  	JAL	runtime·reflectcallmove(SB)
   370  	RET
   371  
   372  CALLFN(·call16, 16)
   373  CALLFN(·call32, 32)
   374  CALLFN(·call64, 64)
   375  CALLFN(·call128, 128)
   376  CALLFN(·call256, 256)
   377  CALLFN(·call512, 512)
   378  CALLFN(·call1024, 1024)
   379  CALLFN(·call2048, 2048)
   380  CALLFN(·call4096, 4096)
   381  CALLFN(·call8192, 8192)
   382  CALLFN(·call16384, 16384)
   383  CALLFN(·call32768, 32768)
   384  CALLFN(·call65536, 65536)
   385  CALLFN(·call131072, 131072)
   386  CALLFN(·call262144, 262144)
   387  CALLFN(·call524288, 524288)
   388  CALLFN(·call1048576, 1048576)
   389  CALLFN(·call2097152, 2097152)
   390  CALLFN(·call4194304, 4194304)
   391  CALLFN(·call8388608, 8388608)
   392  CALLFN(·call16777216, 16777216)
   393  CALLFN(·call33554432, 33554432)
   394  CALLFN(·call67108864, 67108864)
   395  CALLFN(·call134217728, 134217728)
   396  CALLFN(·call268435456, 268435456)
   397  CALLFN(·call536870912, 536870912)
   398  CALLFN(·call1073741824, 1073741824)
   399  
   400  TEXT runtime·procyield(SB),NOSPLIT,$0-0
   401  	RET
   402  
   403  // void jmpdefer(fv, sp);
   404  // called from deferreturn.
   405  // 1. grab stored LR for caller
   406  // 2. sub 8 bytes to get back to JAL deferreturn
   407  // 3. JMP to fn
   408  TEXT runtime·jmpdefer(SB), NOSPLIT, $-8-16
   409  	MOVV	0(R29), R31
   410  	ADDV	$-8, R31
   411  
   412  	MOVV	fv+0(FP), REGCTXT
   413  	MOVV	argp+8(FP), R29
   414  	ADDV	$-8, R29
   415  	NOR	R0, R0	// prevent scheduling
   416  	MOVV	0(REGCTXT), R4
   417  	JMP	(R4)
   418  
   419  // Save state of caller into g->sched. Smashes R1.
   420  TEXT gosave<>(SB),NOSPLIT,$-8
   421  	MOVV	R31, (g_sched+gobuf_pc)(g)
   422  	MOVV	R29, (g_sched+gobuf_sp)(g)
   423  	MOVV	R0, (g_sched+gobuf_lr)(g)
   424  	MOVV	R0, (g_sched+gobuf_ret)(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·badctxt(SB)
   429  	RET
   430  
   431  // func asmcgocall(fn, arg unsafe.Pointer) int32
   432  // Call fn(arg) on the scheduler stack,
   433  // aligned appropriately for the gcc ABI.
   434  // See cgocall.go for more details.
   435  TEXT ·asmcgocall(SB),NOSPLIT,$0-20
   436  	MOVV	fn+0(FP), R25
   437  	MOVV	arg+8(FP), R4
   438  
   439  	MOVV	R29, R3	// save original stack pointer
   440  	MOVV	g, R2
   441  
   442  	// Figure out if we need to switch to m->g0 stack.
   443  	// We get called to create new OS threads too, and those
   444  	// come in on the m->g0 stack already.
   445  	MOVV	g_m(g), R5
   446  	MOVV	m_g0(R5), R6
   447  	BEQ	R6, g, g0
   448  
   449  	JAL	gosave<>(SB)
   450  	MOVV	R6, g
   451  	JAL	runtime·save_g(SB)
   452  	MOVV	(g_sched+gobuf_sp)(g), R29
   453  
   454  	// Now on a scheduling stack (a pthread-created stack).
   455  g0:
   456  	// Save room for two of our pointers.
   457  	ADDV	$-16, R29
   458  	MOVV	R2, 0(R29)	// save old g on stack
   459  	MOVV	(g_stack+stack_hi)(R2), R2
   460  	SUBVU	R3, R2
   461  	MOVV	R2, 8(R29)	// save depth in old g stack (can't just save SP, as stack might be copied during a callback)
   462  	JAL	(R25)
   463  
   464  	// Restore g, stack pointer. R2 is return value.
   465  	MOVV	0(R29), g
   466  	JAL	runtime·save_g(SB)
   467  	MOVV	(g_stack+stack_hi)(g), R5
   468  	MOVV	8(R29), R6
   469  	SUBVU	R6, R5
   470  	MOVV	R5, R29
   471  
   472  	MOVW	R2, ret+16(FP)
   473  	RET
   474  
   475  // cgocallback(void (*fn)(void*), void *frame, uintptr framesize, uintptr ctxt)
   476  // Turn the fn into a Go func (by taking its address) and call
   477  // cgocallback_gofunc.
   478  TEXT runtime·cgocallback(SB),NOSPLIT,$32-32
   479  	MOVV	$fn+0(FP), R1
   480  	MOVV	R1, 8(R29)
   481  	MOVV	frame+8(FP), R1
   482  	MOVV	R1, 16(R29)
   483  	MOVV	framesize+16(FP), R1
   484  	MOVV	R1, 24(R29)
   485  	MOVV	ctxt+24(FP), R1
   486  	MOVV	R1, 32(R29)
   487  	MOVV	$runtime·cgocallback_gofunc(SB), R1
   488  	JAL	(R1)
   489  	RET
   490  
   491  // cgocallback_gofunc(FuncVal*, void *frame, uintptr framesize, uintptr ctxt)
   492  // See cgocall.go for more details.
   493  TEXT ·cgocallback_gofunc(SB),NOSPLIT,$16-32
   494  	NO_LOCAL_POINTERS
   495  
   496  	// Load m and g from thread-local storage.
   497  	MOVB	runtime·iscgo(SB), R1
   498  	BEQ	R1, nocgo
   499  	JAL	runtime·load_g(SB)
   500  nocgo:
   501  
   502  	// If g is nil, Go did not create the current thread.
   503  	// Call needm to obtain one for temporary use.
   504  	// In this case, we're running on the thread stack, so there's
   505  	// lots of space, but the linker doesn't know. Hide the call from
   506  	// the linker analysis by using an indirect call.
   507  	BEQ	g, needm
   508  
   509  	MOVV	g_m(g), R3
   510  	MOVV	R3, savedm-8(SP)
   511  	JMP	havem
   512  
   513  needm:
   514  	MOVV	g, savedm-8(SP) // g is zero, so is m.
   515  	MOVV	$runtime·needm(SB), R4
   516  	JAL	(R4)
   517  
   518  	// Set m->sched.sp = SP, so that if a panic happens
   519  	// during the function we are about to execute, it will
   520  	// have a valid SP to run on the g0 stack.
   521  	// The next few lines (after the havem label)
   522  	// will save this SP onto the stack and then write
   523  	// the same SP back to m->sched.sp. That seems redundant,
   524  	// but if an unrecovered panic happens, unwindm will
   525  	// restore the g->sched.sp from the stack location
   526  	// and then systemstack will try to use it. If we don't set it here,
   527  	// that restored SP will be uninitialized (typically 0) and
   528  	// will not be usable.
   529  	MOVV	g_m(g), R3
   530  	MOVV	m_g0(R3), R1
   531  	MOVV	R29, (g_sched+gobuf_sp)(R1)
   532  
   533  havem:
   534  	// Now there's a valid m, and we're running on its m->g0.
   535  	// Save current m->g0->sched.sp on stack and then set it to SP.
   536  	// Save current sp in m->g0->sched.sp in preparation for
   537  	// switch back to m->curg stack.
   538  	// NOTE: unwindm knows that the saved g->sched.sp is at 8(R29) aka savedsp-16(SP).
   539  	MOVV	m_g0(R3), R1
   540  	MOVV	(g_sched+gobuf_sp)(R1), R2
   541  	MOVV	R2, savedsp-16(SP)
   542  	MOVV	R29, (g_sched+gobuf_sp)(R1)
   543  
   544  	// Switch to m->curg stack and call runtime.cgocallbackg.
   545  	// Because we are taking over the execution of m->curg
   546  	// but *not* resuming what had been running, we need to
   547  	// save that information (m->curg->sched) so we can restore it.
   548  	// We can restore m->curg->sched.sp easily, because calling
   549  	// runtime.cgocallbackg leaves SP unchanged upon return.
   550  	// To save m->curg->sched.pc, we push it onto the stack.
   551  	// This has the added benefit that it looks to the traceback
   552  	// routine like cgocallbackg is going to return to that
   553  	// PC (because the frame we allocate below has the same
   554  	// size as cgocallback_gofunc's frame declared above)
   555  	// so that the traceback will seamlessly trace back into
   556  	// the earlier calls.
   557  	//
   558  	// In the new goroutine, -8(SP) is unused (where SP refers to
   559  	// m->curg's SP while we're setting it up, before we've adjusted it).
   560  	MOVV	m_curg(R3), g
   561  	JAL	runtime·save_g(SB)
   562  	MOVV	(g_sched+gobuf_sp)(g), R2 // prepare stack as R2
   563  	MOVV	(g_sched+gobuf_pc)(g), R4
   564  	MOVV	R4, -24(R2)
   565  	MOVV    ctxt+24(FP), R1
   566  	MOVV    R1, -16(R2)
   567  	MOVV	$-24(R2), R29
   568  	JAL	runtime·cgocallbackg(SB)
   569  
   570  	// Restore g->sched (== m->curg->sched) from saved values.
   571  	MOVV	0(R29), R4
   572  	MOVV	R4, (g_sched+gobuf_pc)(g)
   573  	MOVV	$24(R29), R2
   574  	MOVV	R2, (g_sched+gobuf_sp)(g)
   575  
   576  	// Switch back to m->g0's stack and restore m->g0->sched.sp.
   577  	// (Unlike m->curg, the g0 goroutine never uses sched.pc,
   578  	// so we do not have to restore it.)
   579  	MOVV	g_m(g), R3
   580  	MOVV	m_g0(R3), g
   581  	JAL	runtime·save_g(SB)
   582  	MOVV	(g_sched+gobuf_sp)(g), R29
   583  	MOVV	savedsp-16(SP), R2
   584  	MOVV	R2, (g_sched+gobuf_sp)(g)
   585  
   586  	// If the m on entry was nil, we called needm above to borrow an m
   587  	// for the duration of the call. Since the call is over, return it with dropm.
   588  	MOVV	savedm-8(SP), R3
   589  	BNE	R3, droppedm
   590  	MOVV	$runtime·dropm(SB), R4
   591  	JAL	(R4)
   592  droppedm:
   593  
   594  	// Done!
   595  	RET
   596  
   597  // void setg(G*); set g. for use by needm.
   598  TEXT runtime·setg(SB), NOSPLIT, $0-8
   599  	MOVV	gg+0(FP), g
   600  	// This only happens if iscgo, so jump straight to save_g
   601  	JAL	runtime·save_g(SB)
   602  	RET
   603  
   604  // void setg_gcc(G*); set g called from gcc with g in R1
   605  TEXT setg_gcc<>(SB),NOSPLIT,$0-0
   606  	MOVV	R1, g
   607  	JAL	runtime·save_g(SB)
   608  	RET
   609  
   610  TEXT runtime·getcallerpc(SB),NOSPLIT,$-8-8
   611  	MOVV	0(R29), R1		// LR saved by caller
   612  	MOVV	R1, ret+0(FP)
   613  	RET
   614  
   615  TEXT runtime·abort(SB),NOSPLIT,$-8-0
   616  	MOVW	(R0), R0
   617  	UNDEF
   618  
   619  // AES hashing not implemented for mips64
   620  TEXT runtime·aeshash(SB),NOSPLIT,$-8-0
   621  	MOVW	(R0), R1
   622  TEXT runtime·aeshash32(SB),NOSPLIT,$-8-0
   623  	MOVW	(R0), R1
   624  TEXT runtime·aeshash64(SB),NOSPLIT,$-8-0
   625  	MOVW	(R0), R1
   626  TEXT runtime·aeshashstr(SB),NOSPLIT,$-8-0
   627  	MOVW	(R0), R1
   628  
   629  // memequal(p, q unsafe.Pointer, size uintptr) bool
   630  TEXT runtime·memequal(SB),NOSPLIT,$-8-25
   631  	MOVV	a+0(FP), R1
   632  	MOVV	b+8(FP), R2
   633  	BEQ	R1, R2, eq
   634  	MOVV	size+16(FP), R3
   635  	ADDV	R1, R3, R4
   636  loop:
   637  	BNE	R1, R4, test
   638  	MOVV	$1, R1
   639  	MOVB	R1, ret+24(FP)
   640  	RET
   641  test:
   642  	MOVBU	(R1), R6
   643  	ADDV	$1, R1
   644  	MOVBU	(R2), R7
   645  	ADDV	$1, R2
   646  	BEQ	R6, R7, loop
   647  
   648  	MOVB	R0, ret+24(FP)
   649  	RET
   650  eq:
   651  	MOVV	$1, R1
   652  	MOVB	R1, ret+24(FP)
   653  	RET
   654  
   655  // memequal_varlen(a, b unsafe.Pointer) bool
   656  TEXT runtime·memequal_varlen(SB),NOSPLIT,$40-17
   657  	MOVV	a+0(FP), R1
   658  	MOVV	b+8(FP), R2
   659  	BEQ	R1, R2, eq
   660  	MOVV	8(REGCTXT), R3    // compiler stores size at offset 8 in the closure
   661  	MOVV	R1, 8(R29)
   662  	MOVV	R2, 16(R29)
   663  	MOVV	R3, 24(R29)
   664  	JAL	runtime·memequal(SB)
   665  	MOVBU	32(R29), R1
   666  	MOVB	R1, ret+16(FP)
   667  	RET
   668  eq:
   669  	MOVV	$1, R1
   670  	MOVB	R1, ret+16(FP)
   671  	RET
   672  
   673  // TODO: share code with memequal?
   674  TEXT bytes·Equal(SB),NOSPLIT,$0-49
   675  	MOVV	a_len+8(FP), R3
   676  	MOVV	b_len+32(FP), R4
   677  	BNE	R3, R4, noteq		// unequal lengths are not equal
   678  
   679  	MOVV	a+0(FP), R1
   680  	MOVV	b+24(FP), R2
   681  	ADDV	R1, R3		// end
   682  
   683  loop:
   684  	BEQ	R1, R3, equal		// reached the end
   685  	MOVBU	(R1), R6
   686  	ADDV	$1, R1
   687  	MOVBU	(R2), R7
   688  	ADDV	$1, R2
   689  	BEQ	R6, R7, loop
   690  
   691  noteq:
   692  	MOVB	R0, ret+48(FP)
   693  	RET
   694  
   695  equal:
   696  	MOVV	$1, R1
   697  	MOVB	R1, ret+48(FP)
   698  	RET
   699  
   700  TEXT bytes·IndexByte(SB),NOSPLIT,$0-40
   701  	MOVV	s+0(FP), R1
   702  	MOVV	s_len+8(FP), R2
   703  	MOVBU	c+24(FP), R3	// byte to find
   704  	MOVV	R1, R4		// store base for later
   705  	ADDV	R1, R2		// end
   706  	ADDV	$-1, R1
   707  
   708  loop:
   709  	ADDV	$1, R1
   710  	BEQ	R1, R2, notfound
   711  	MOVBU	(R1), R5
   712  	BNE	R3, R5, loop
   713  
   714  	SUBV	R4, R1		// remove base
   715  	MOVV	R1, ret+32(FP)
   716  	RET
   717  
   718  notfound:
   719  	MOVV	$-1, R1
   720  	MOVV	R1, ret+32(FP)
   721  	RET
   722  
   723  TEXT strings·IndexByte(SB),NOSPLIT,$0-32
   724  	MOVV	p+0(FP), R1
   725  	MOVV	b_len+8(FP), R2
   726  	MOVBU	c+16(FP), R3	// byte to find
   727  	MOVV	R1, R4		// store base for later
   728  	ADDV	R1, R2		// end
   729  	ADDV	$-1, R1
   730  
   731  loop:
   732  	ADDV	$1, R1
   733  	BEQ	R1, R2, notfound
   734  	MOVBU	(R1), R5
   735  	BNE	R3, R5, loop
   736  
   737  	SUBV	R4, R1		// remove base
   738  	MOVV	R1, ret+24(FP)
   739  	RET
   740  
   741  notfound:
   742  	MOVV	$-1, R1
   743  	MOVV	R1, ret+24(FP)
   744  	RET
   745  
   746  TEXT runtime·return0(SB), NOSPLIT, $0
   747  	MOVW	$0, R1
   748  	RET
   749  
   750  // Called from cgo wrappers, this function returns g->m->curg.stack.hi.
   751  // Must obey the gcc calling convention.
   752  TEXT _cgo_topofstack(SB),NOSPLIT,$16
   753  	// g (R30) and REGTMP (R23)  might be clobbered by load_g. They
   754  	// are callee-save in the gcc calling convention, so save them.
   755  	MOVV	R23, savedR23-16(SP)
   756  	MOVV	g, savedG-8(SP)
   757  
   758  	JAL	runtime·load_g(SB)
   759  	MOVV	g_m(g), R1
   760  	MOVV	m_curg(R1), R1
   761  	MOVV	(g_stack+stack_hi)(R1), R2 // return value in R2
   762  
   763  	MOVV	savedG-8(SP), g
   764  	MOVV	savedR23-16(SP), R23
   765  	RET
   766  
   767  // The top-most function running on a goroutine
   768  // returns to goexit+PCQuantum.
   769  TEXT runtime·goexit(SB),NOSPLIT,$-8-0
   770  	NOR	R0, R0	// NOP
   771  	JAL	runtime·goexit1(SB)	// does not return
   772  	// traceback from goexit1 must hit code range of goexit
   773  	NOR	R0, R0	// NOP
   774  
   775  TEXT ·checkASM(SB),NOSPLIT,$0-1
   776  	MOVW	$1, R1
   777  	MOVB	R1, ret+0(FP)
   778  	RET