github.com/eun/go@v0.0.0-20170811110501-92cfd07a6cfd/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  
   112  	// If ctxt is not nil, invoke deletion barrier before overwriting.
   113  	MOVV	gobuf_ctxt(R3), R1
   114  	BEQ	R1, nilctxt
   115  	MOVV	$gobuf_ctxt(R3), R1
   116  	MOVV	R1, 8(R29)
   117  	MOVV	R0, 16(R29)
   118  	JAL	runtime·writebarrierptr_prewrite(SB)
   119  	MOVV	buf+0(FP), R3
   120  
   121  nilctxt:
   122  	MOVV	gobuf_g(R3), g	// make sure g is not nil
   123  	JAL	runtime·save_g(SB)
   124  
   125  	MOVV	0(g), R2
   126  	MOVV	gobuf_sp(R3), R29
   127  	MOVV	gobuf_lr(R3), R31
   128  	MOVV	gobuf_ret(R3), R1
   129  	MOVV	gobuf_ctxt(R3), REGCTXT
   130  	MOVV	R0, gobuf_sp(R3)
   131  	MOVV	R0, gobuf_ret(R3)
   132  	MOVV	R0, gobuf_lr(R3)
   133  	MOVV	R0, gobuf_ctxt(R3)
   134  	MOVV	gobuf_pc(R3), R4
   135  	JMP	(R4)
   136  
   137  // void mcall(fn func(*g))
   138  // Switch to m->g0's stack, call fn(g).
   139  // Fn must never return. It should gogo(&g->sched)
   140  // to keep running g.
   141  TEXT runtime·mcall(SB), NOSPLIT, $-8-8
   142  	// Save caller state in g->sched
   143  	MOVV	R29, (g_sched+gobuf_sp)(g)
   144  	MOVV	R31, (g_sched+gobuf_pc)(g)
   145  	MOVV	R0, (g_sched+gobuf_lr)(g)
   146  	MOVV	g, (g_sched+gobuf_g)(g)
   147  
   148  	// Switch to m->g0 & its stack, call fn.
   149  	MOVV	g, R1
   150  	MOVV	g_m(g), R3
   151  	MOVV	m_g0(R3), g
   152  	JAL	runtime·save_g(SB)
   153  	BNE	g, R1, 2(PC)
   154  	JMP	runtime·badmcall(SB)
   155  	MOVV	fn+0(FP), REGCTXT			// context
   156  	MOVV	0(REGCTXT), R4			// code pointer
   157  	MOVV	(g_sched+gobuf_sp)(g), R29	// sp = m->g0->sched.sp
   158  	ADDV	$-16, R29
   159  	MOVV	R1, 8(R29)
   160  	MOVV	R0, 0(R29)
   161  	JAL	(R4)
   162  	JMP	runtime·badmcall2(SB)
   163  
   164  // systemstack_switch is a dummy routine that systemstack leaves at the bottom
   165  // of the G stack. We need to distinguish the routine that
   166  // lives at the bottom of the G stack from the one that lives
   167  // at the top of the system stack because the one at the top of
   168  // the system stack terminates the stack walk (see topofstack()).
   169  TEXT runtime·systemstack_switch(SB), NOSPLIT, $0-0
   170  	UNDEF
   171  	JAL	(R31)	// make sure this function is not leaf
   172  	RET
   173  
   174  // func systemstack(fn func())
   175  TEXT runtime·systemstack(SB), NOSPLIT, $0-8
   176  	MOVV	fn+0(FP), R1	// R1 = fn
   177  	MOVV	R1, REGCTXT		// context
   178  	MOVV	g_m(g), R2	// R2 = m
   179  
   180  	MOVV	m_gsignal(R2), R3	// R3 = gsignal
   181  	BEQ	g, R3, noswitch
   182  
   183  	MOVV	m_g0(R2), R3	// R3 = g0
   184  	BEQ	g, R3, noswitch
   185  
   186  	MOVV	m_curg(R2), R4
   187  	BEQ	g, R4, switch
   188  
   189  	// Bad: g is not gsignal, not g0, not curg. What is it?
   190  	// Hide call from linker nosplit analysis.
   191  	MOVV	$runtime·badsystemstack(SB), R4
   192  	JAL	(R4)
   193  
   194  switch:
   195  	// save our state in g->sched. Pretend to
   196  	// be systemstack_switch if the G stack is scanned.
   197  	MOVV	$runtime·systemstack_switch(SB), R4
   198  	ADDV	$8, R4	// get past prologue
   199  	MOVV	R4, (g_sched+gobuf_pc)(g)
   200  	MOVV	R29, (g_sched+gobuf_sp)(g)
   201  	MOVV	R0, (g_sched+gobuf_lr)(g)
   202  	MOVV	g, (g_sched+gobuf_g)(g)
   203  
   204  	// switch to g0
   205  	MOVV	R3, g
   206  	JAL	runtime·save_g(SB)
   207  	MOVV	(g_sched+gobuf_sp)(g), R1
   208  	// make it look like mstart called systemstack on g0, to stop traceback
   209  	ADDV	$-8, R1
   210  	MOVV	$runtime·mstart(SB), R2
   211  	MOVV	R2, 0(R1)
   212  	MOVV	R1, R29
   213  
   214  	// call target function
   215  	MOVV	0(REGCTXT), R4	// code pointer
   216  	JAL	(R4)
   217  
   218  	// switch back to g
   219  	MOVV	g_m(g), R1
   220  	MOVV	m_curg(R1), g
   221  	JAL	runtime·save_g(SB)
   222  	MOVV	(g_sched+gobuf_sp)(g), R29
   223  	MOVV	R0, (g_sched+gobuf_sp)(g)
   224  	RET
   225  
   226  noswitch:
   227  	// already on m stack, just call directly
   228  	MOVV	0(REGCTXT), R4	// code pointer
   229  	JAL	(R4)
   230  	RET
   231  
   232  /*
   233   * support for morestack
   234   */
   235  
   236  // Called during function prolog when more stack is needed.
   237  // Caller has already loaded:
   238  // R1: framesize, R2: argsize, R3: LR
   239  //
   240  // The traceback routines see morestack on a g0 as being
   241  // the top of a stack (for example, morestack calling newstack
   242  // calling the scheduler calling newm calling gc), so we must
   243  // record an argument size. For that purpose, it has no arguments.
   244  TEXT runtime·morestack(SB),NOSPLIT,$-8-0
   245  	// Cannot grow scheduler stack (m->g0).
   246  	MOVV	g_m(g), R7
   247  	MOVV	m_g0(R7), R8
   248  	BNE	g, R8, 3(PC)
   249  	JAL	runtime·badmorestackg0(SB)
   250  	JAL	runtime·abort(SB)
   251  
   252  	// Cannot grow signal stack (m->gsignal).
   253  	MOVV	m_gsignal(R7), R8
   254  	BNE	g, R8, 3(PC)
   255  	JAL	runtime·badmorestackgsignal(SB)
   256  	JAL	runtime·abort(SB)
   257  
   258  	// Called from f.
   259  	// Set g->sched to context in f.
   260  	MOVV	R29, (g_sched+gobuf_sp)(g)
   261  	MOVV	R31, (g_sched+gobuf_pc)(g)
   262  	MOVV	R3, (g_sched+gobuf_lr)(g)
   263  	// newstack will fill gobuf.ctxt.
   264  
   265  	// Called from f.
   266  	// Set m->morebuf to f's caller.
   267  	MOVV	R3, (m_morebuf+gobuf_pc)(R7)	// f's caller's PC
   268  	MOVV	R29, (m_morebuf+gobuf_sp)(R7)	// f's caller's SP
   269  	MOVV	g, (m_morebuf+gobuf_g)(R7)
   270  
   271  	// Call newstack on m->g0's stack.
   272  	MOVV	m_g0(R7), g
   273  	JAL	runtime·save_g(SB)
   274  	MOVV	(g_sched+gobuf_sp)(g), R29
   275  	// Create a stack frame on g0 to call newstack.
   276  	MOVV	R0, -16(R29)	// Zero saved LR in frame
   277  	ADDV	$-16, R29
   278  	MOVV	REGCTXT, 8(R29)	// ctxt argument
   279  	JAL	runtime·newstack(SB)
   280  
   281  	// Not reached, but make sure the return PC from the call to newstack
   282  	// is still in this function, and not the beginning of the next.
   283  	UNDEF
   284  
   285  TEXT runtime·morestack_noctxt(SB),NOSPLIT,$-8-0
   286  	MOVV	R0, REGCTXT
   287  	JMP	runtime·morestack(SB)
   288  
   289  // reflectcall: call a function with the given argument list
   290  // func call(argtype *_type, f *FuncVal, arg *byte, argsize, retoffset uint32).
   291  // we don't have variable-sized frames, so we use a small number
   292  // of constant-sized-frame functions to encode a few bits of size in the pc.
   293  // Caution: ugly multiline assembly macros in your future!
   294  
   295  #define DISPATCH(NAME,MAXSIZE)		\
   296  	MOVV	$MAXSIZE, R23;		\
   297  	SGTU	R1, R23, R23;		\
   298  	BNE	R23, 3(PC);			\
   299  	MOVV	$NAME(SB), R4;	\
   300  	JMP	(R4)
   301  // Note: can't just "BR NAME(SB)" - bad inlining results.
   302  
   303  TEXT reflect·call(SB), NOSPLIT, $0-0
   304  	JMP	·reflectcall(SB)
   305  
   306  TEXT ·reflectcall(SB), NOSPLIT, $-8-32
   307  	MOVWU argsize+24(FP), R1
   308  	DISPATCH(runtime·call32, 32)
   309  	DISPATCH(runtime·call64, 64)
   310  	DISPATCH(runtime·call128, 128)
   311  	DISPATCH(runtime·call256, 256)
   312  	DISPATCH(runtime·call512, 512)
   313  	DISPATCH(runtime·call1024, 1024)
   314  	DISPATCH(runtime·call2048, 2048)
   315  	DISPATCH(runtime·call4096, 4096)
   316  	DISPATCH(runtime·call8192, 8192)
   317  	DISPATCH(runtime·call16384, 16384)
   318  	DISPATCH(runtime·call32768, 32768)
   319  	DISPATCH(runtime·call65536, 65536)
   320  	DISPATCH(runtime·call131072, 131072)
   321  	DISPATCH(runtime·call262144, 262144)
   322  	DISPATCH(runtime·call524288, 524288)
   323  	DISPATCH(runtime·call1048576, 1048576)
   324  	DISPATCH(runtime·call2097152, 2097152)
   325  	DISPATCH(runtime·call4194304, 4194304)
   326  	DISPATCH(runtime·call8388608, 8388608)
   327  	DISPATCH(runtime·call16777216, 16777216)
   328  	DISPATCH(runtime·call33554432, 33554432)
   329  	DISPATCH(runtime·call67108864, 67108864)
   330  	DISPATCH(runtime·call134217728, 134217728)
   331  	DISPATCH(runtime·call268435456, 268435456)
   332  	DISPATCH(runtime·call536870912, 536870912)
   333  	DISPATCH(runtime·call1073741824, 1073741824)
   334  	MOVV	$runtime·badreflectcall(SB), R4
   335  	JMP	(R4)
   336  
   337  #define CALLFN(NAME,MAXSIZE)			\
   338  TEXT NAME(SB), WRAPPER, $MAXSIZE-24;		\
   339  	NO_LOCAL_POINTERS;			\
   340  	/* copy arguments to stack */		\
   341  	MOVV	arg+16(FP), R1;			\
   342  	MOVWU	argsize+24(FP), R2;			\
   343  	MOVV	R29, R3;				\
   344  	ADDV	$8, R3;			\
   345  	ADDV	R3, R2;				\
   346  	BEQ	R3, R2, 6(PC);				\
   347  	MOVBU	(R1), R4;			\
   348  	ADDV	$1, R1;			\
   349  	MOVBU	R4, (R3);			\
   350  	ADDV	$1, R3;			\
   351  	JMP	-5(PC);				\
   352  	/* call function */			\
   353  	MOVV	f+8(FP), REGCTXT;			\
   354  	MOVV	(REGCTXT), R4;			\
   355  	PCDATA  $PCDATA_StackMapIndex, $0;	\
   356  	JAL	(R4);				\
   357  	/* copy return values back */		\
   358  	MOVV	argtype+0(FP), R5;		\
   359  	MOVV	arg+16(FP), R1;			\
   360  	MOVWU	n+24(FP), R2;			\
   361  	MOVWU	retoffset+28(FP), R4;		\
   362  	ADDV	$8, R29, R3;				\
   363  	ADDV	R4, R3; 			\
   364  	ADDV	R4, R1;				\
   365  	SUBVU	R4, R2;				\
   366  	JAL	callRet<>(SB);			\
   367  	RET
   368  
   369  // callRet copies return values back at the end of call*. This is a
   370  // separate function so it can allocate stack space for the arguments
   371  // to reflectcallmove. It does not follow the Go ABI; it expects its
   372  // arguments in registers.
   373  TEXT callRet<>(SB), NOSPLIT, $32-0
   374  	MOVV	R5, 8(R29)
   375  	MOVV	R1, 16(R29)
   376  	MOVV	R3, 24(R29)
   377  	MOVV	R2, 32(R29)
   378  	JAL	runtime·reflectcallmove(SB)
   379  	RET
   380  
   381  CALLFN(·call16, 16)
   382  CALLFN(·call32, 32)
   383  CALLFN(·call64, 64)
   384  CALLFN(·call128, 128)
   385  CALLFN(·call256, 256)
   386  CALLFN(·call512, 512)
   387  CALLFN(·call1024, 1024)
   388  CALLFN(·call2048, 2048)
   389  CALLFN(·call4096, 4096)
   390  CALLFN(·call8192, 8192)
   391  CALLFN(·call16384, 16384)
   392  CALLFN(·call32768, 32768)
   393  CALLFN(·call65536, 65536)
   394  CALLFN(·call131072, 131072)
   395  CALLFN(·call262144, 262144)
   396  CALLFN(·call524288, 524288)
   397  CALLFN(·call1048576, 1048576)
   398  CALLFN(·call2097152, 2097152)
   399  CALLFN(·call4194304, 4194304)
   400  CALLFN(·call8388608, 8388608)
   401  CALLFN(·call16777216, 16777216)
   402  CALLFN(·call33554432, 33554432)
   403  CALLFN(·call67108864, 67108864)
   404  CALLFN(·call134217728, 134217728)
   405  CALLFN(·call268435456, 268435456)
   406  CALLFN(·call536870912, 536870912)
   407  CALLFN(·call1073741824, 1073741824)
   408  
   409  TEXT runtime·procyield(SB),NOSPLIT,$0-0
   410  	RET
   411  
   412  // void jmpdefer(fv, sp);
   413  // called from deferreturn.
   414  // 1. grab stored LR for caller
   415  // 2. sub 8 bytes to get back to JAL deferreturn
   416  // 3. JMP to fn
   417  TEXT runtime·jmpdefer(SB), NOSPLIT, $-8-16
   418  	MOVV	0(R29), R31
   419  	ADDV	$-8, R31
   420  
   421  	MOVV	fv+0(FP), REGCTXT
   422  	MOVV	argp+8(FP), R29
   423  	ADDV	$-8, R29
   424  	NOR	R0, R0	// prevent scheduling
   425  	MOVV	0(REGCTXT), R4
   426  	JMP	(R4)
   427  
   428  // Save state of caller into g->sched. Smashes R1.
   429  TEXT gosave<>(SB),NOSPLIT,$-8
   430  	MOVV	R31, (g_sched+gobuf_pc)(g)
   431  	MOVV	R29, (g_sched+gobuf_sp)(g)
   432  	MOVV	R0, (g_sched+gobuf_lr)(g)
   433  	MOVV	R0, (g_sched+gobuf_ret)(g)
   434  	// Assert ctxt is zero. See func save.
   435  	MOVV	(g_sched+gobuf_ctxt)(g), R1
   436  	BEQ	R1, 2(PC)
   437  	JAL	runtime·badctxt(SB)
   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.
   444  TEXT ·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.
   454  	MOVV	g_m(g), R5
   455  	MOVV	m_g0(R5), R6
   456  	BEQ	R6, g, g0
   457  
   458  	JAL	gosave<>(SB)
   459  	MOVV	R6, g
   460  	JAL	runtime·save_g(SB)
   461  	MOVV	(g_sched+gobuf_sp)(g), R29
   462  
   463  	// Now on a scheduling stack (a pthread-created stack).
   464  g0:
   465  	// Save room for two of our pointers.
   466  	ADDV	$-16, R29
   467  	MOVV	R2, 0(R29)	// save old g on stack
   468  	MOVV	(g_stack+stack_hi)(R2), R2
   469  	SUBVU	R3, R2
   470  	MOVV	R2, 8(R29)	// save depth in old g stack (can't just save SP, as stack might be copied during a callback)
   471  	JAL	(R25)
   472  
   473  	// Restore g, stack pointer. R2 is return value.
   474  	MOVV	0(R29), g
   475  	JAL	runtime·save_g(SB)
   476  	MOVV	(g_stack+stack_hi)(g), R5
   477  	MOVV	8(R29), R6
   478  	SUBVU	R6, R5
   479  	MOVV	R5, R29
   480  
   481  	MOVW	R2, ret+16(FP)
   482  	RET
   483  
   484  // cgocallback(void (*fn)(void*), void *frame, uintptr framesize, uintptr ctxt)
   485  // Turn the fn into a Go func (by taking its address) and call
   486  // cgocallback_gofunc.
   487  TEXT runtime·cgocallback(SB),NOSPLIT,$32-32
   488  	MOVV	$fn+0(FP), R1
   489  	MOVV	R1, 8(R29)
   490  	MOVV	frame+8(FP), R1
   491  	MOVV	R1, 16(R29)
   492  	MOVV	framesize+16(FP), R1
   493  	MOVV	R1, 24(R29)
   494  	MOVV	ctxt+24(FP), R1
   495  	MOVV	R1, 32(R29)
   496  	MOVV	$runtime·cgocallback_gofunc(SB), R1
   497  	JAL	(R1)
   498  	RET
   499  
   500  // cgocallback_gofunc(FuncVal*, void *frame, uintptr framesize, uintptr ctxt)
   501  // See cgocall.go for more details.
   502  TEXT ·cgocallback_gofunc(SB),NOSPLIT,$16-32
   503  	NO_LOCAL_POINTERS
   504  
   505  	// Load m and g from thread-local storage.
   506  	MOVB	runtime·iscgo(SB), R1
   507  	BEQ	R1, nocgo
   508  	JAL	runtime·load_g(SB)
   509  nocgo:
   510  
   511  	// If g is nil, Go did not create the current thread.
   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  
   522  needm:
   523  	MOVV	g, savedm-8(SP) // g is zero, so is m.
   524  	MOVV	$runtime·needm(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  
   542  havem:
   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-16(SP)
   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 stack.
   560  	// This has the added benefit that it looks to the traceback
   561  	// routine like cgocallbackg is going to return to that
   562  	// PC (because the frame we allocate below has the same
   563  	// size as cgocallback_gofunc's frame declared above)
   564  	// so that the traceback will seamlessly trace back into
   565  	// the earlier calls.
   566  	//
   567  	// In the new goroutine, -8(SP) is unused (where SP refers to
   568  	// m->curg's SP while we're setting it up, before we've adjusted it).
   569  	MOVV	m_curg(R3), g
   570  	JAL	runtime·save_g(SB)
   571  	MOVV	(g_sched+gobuf_sp)(g), R2 // prepare stack as R2
   572  	MOVV	(g_sched+gobuf_pc)(g), R4
   573  	MOVV	R4, -24(R2)
   574  	MOVV    ctxt+24(FP), R1
   575  	MOVV    R1, -16(R2)
   576  	MOVV	$-24(R2), 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(R29), R2
   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-16(SP), R2
   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  	// for the duration of the call. Since the call is over, return it with dropm.
   597  	MOVV	savedm-8(SP), R3
   598  	BNE	R3, droppedm
   599  	MOVV	$runtime·dropm(SB), R4
   600  	JAL	(R4)
   601  droppedm:
   602  
   603  	// Done!
   604  	RET
   605  
   606  // void setg(G*); set g. for use by needm.
   607  TEXT runtime·setg(SB), NOSPLIT, $0-8
   608  	MOVV	gg+0(FP), g
   609  	// This only happens if iscgo, so jump straight to save_g
   610  	JAL	runtime·save_g(SB)
   611  	RET
   612  
   613  // void setg_gcc(G*); set g called from gcc with g in R1
   614  TEXT setg_gcc<>(SB),NOSPLIT,$0-0
   615  	MOVV	R1, g
   616  	JAL	runtime·save_g(SB)
   617  	RET
   618  
   619  TEXT runtime·getcallerpc(SB),NOSPLIT,$8-16
   620  	MOVV	16(R29), R1		// LR saved by caller
   621  	MOVV	R1, ret+8(FP)
   622  	RET
   623  
   624  TEXT runtime·abort(SB),NOSPLIT,$-8-0
   625  	MOVW	(R0), R0
   626  	UNDEF
   627  
   628  // memhash_varlen(p unsafe.Pointer, h seed) uintptr
   629  // redirects to memhash(p, h, size) using the size
   630  // stored in the closure.
   631  TEXT runtime·memhash_varlen(SB),NOSPLIT,$40-24
   632  	GO_ARGS
   633  	NO_LOCAL_POINTERS
   634  	MOVV	p+0(FP), R1
   635  	MOVV	h+8(FP), R2
   636  	MOVV	8(REGCTXT), R3
   637  	MOVV	R1, 8(R29)
   638  	MOVV	R2, 16(R29)
   639  	MOVV	R3, 24(R29)
   640  	JAL	runtime·memhash(SB)
   641  	MOVV	32(R29), R1
   642  	MOVV	R1, ret+16(FP)
   643  	RET
   644  
   645  // AES hashing not implemented for mips64
   646  TEXT runtime·aeshash(SB),NOSPLIT,$-8-0
   647  	MOVW	(R0), R1
   648  TEXT runtime·aeshash32(SB),NOSPLIT,$-8-0
   649  	MOVW	(R0), R1
   650  TEXT runtime·aeshash64(SB),NOSPLIT,$-8-0
   651  	MOVW	(R0), R1
   652  TEXT runtime·aeshashstr(SB),NOSPLIT,$-8-0
   653  	MOVW	(R0), R1
   654  
   655  // memequal(p, q unsafe.Pointer, size uintptr) bool
   656  TEXT runtime·memequal(SB),NOSPLIT,$-8-25
   657  	MOVV	a+0(FP), R1
   658  	MOVV	b+8(FP), R2
   659  	BEQ	R1, R2, eq
   660  	MOVV	size+16(FP), R3
   661  	ADDV	R1, R3, R4
   662  loop:
   663  	BNE	R1, R4, test
   664  	MOVV	$1, R1
   665  	MOVB	R1, ret+24(FP)
   666  	RET
   667  test:
   668  	MOVBU	(R1), R6
   669  	ADDV	$1, R1
   670  	MOVBU	(R2), R7
   671  	ADDV	$1, R2
   672  	BEQ	R6, R7, loop
   673  
   674  	MOVB	R0, ret+24(FP)
   675  	RET
   676  eq:
   677  	MOVV	$1, R1
   678  	MOVB	R1, ret+24(FP)
   679  	RET
   680  
   681  // memequal_varlen(a, b unsafe.Pointer) bool
   682  TEXT runtime·memequal_varlen(SB),NOSPLIT,$40-17
   683  	MOVV	a+0(FP), R1
   684  	MOVV	b+8(FP), R2
   685  	BEQ	R1, R2, eq
   686  	MOVV	8(REGCTXT), R3    // compiler stores size at offset 8 in the closure
   687  	MOVV	R1, 8(R29)
   688  	MOVV	R2, 16(R29)
   689  	MOVV	R3, 24(R29)
   690  	JAL	runtime·memequal(SB)
   691  	MOVBU	32(R29), R1
   692  	MOVB	R1, ret+16(FP)
   693  	RET
   694  eq:
   695  	MOVV	$1, R1
   696  	MOVB	R1, ret+16(FP)
   697  	RET
   698  
   699  // eqstring tests whether two strings are equal.
   700  // The compiler guarantees that strings passed
   701  // to eqstring have equal length.
   702  // See runtime_test.go:eqstring_generic for
   703  // equivalent Go code.
   704  TEXT runtime·eqstring(SB),NOSPLIT,$0-33
   705  	MOVV	s1_base+0(FP), R1
   706  	MOVV	s2_base+16(FP), R2
   707  	MOVV	$1, R3
   708  	MOVB	R3, ret+32(FP)
   709  	BNE	R1, R2, 2(PC)
   710  	RET
   711  	MOVV	s1_len+8(FP), R3
   712  	ADDV	R1, R3, R4
   713  loop:
   714  	BNE	R1, R4, 2(PC)
   715  	RET
   716  	MOVBU	(R1), R6
   717  	ADDV	$1, R1
   718  	MOVBU	(R2), R7
   719  	ADDV	$1, R2
   720  	BEQ	R6, R7, loop
   721  	MOVB	R0, ret+32(FP)
   722  	RET
   723  
   724  // TODO: share code with memequal?
   725  TEXT bytes·Equal(SB),NOSPLIT,$0-49
   726  	MOVV	a_len+8(FP), R3
   727  	MOVV	b_len+32(FP), R4
   728  	BNE	R3, R4, noteq		// unequal lengths are not equal
   729  
   730  	MOVV	a+0(FP), R1
   731  	MOVV	b+24(FP), R2
   732  	ADDV	R1, R3		// end
   733  
   734  loop:
   735  	BEQ	R1, R3, equal		// reached the end
   736  	MOVBU	(R1), R6
   737  	ADDV	$1, R1
   738  	MOVBU	(R2), R7
   739  	ADDV	$1, R2
   740  	BEQ	R6, R7, loop
   741  
   742  noteq:
   743  	MOVB	R0, ret+48(FP)
   744  	RET
   745  
   746  equal:
   747  	MOVV	$1, R1
   748  	MOVB	R1, ret+48(FP)
   749  	RET
   750  
   751  TEXT bytes·IndexByte(SB),NOSPLIT,$0-40
   752  	MOVV	s+0(FP), R1
   753  	MOVV	s_len+8(FP), R2
   754  	MOVBU	c+24(FP), R3	// byte to find
   755  	MOVV	R1, R4		// store base for later
   756  	ADDV	R1, R2		// end
   757  	ADDV	$-1, R1
   758  
   759  loop:
   760  	ADDV	$1, R1
   761  	BEQ	R1, R2, notfound
   762  	MOVBU	(R1), R5
   763  	BNE	R3, R5, loop
   764  
   765  	SUBV	R4, R1		// remove base
   766  	MOVV	R1, ret+32(FP)
   767  	RET
   768  
   769  notfound:
   770  	MOVV	$-1, R1
   771  	MOVV	R1, ret+32(FP)
   772  	RET
   773  
   774  TEXT strings·IndexByte(SB),NOSPLIT,$0-32
   775  	MOVV	p+0(FP), R1
   776  	MOVV	b_len+8(FP), R2
   777  	MOVBU	c+16(FP), R3	// byte to find
   778  	MOVV	R1, R4		// store base for later
   779  	ADDV	R1, R2		// end
   780  	ADDV	$-1, R1
   781  
   782  loop:
   783  	ADDV	$1, R1
   784  	BEQ	R1, R2, notfound
   785  	MOVBU	(R1), R5
   786  	BNE	R3, R5, loop
   787  
   788  	SUBV	R4, R1		// remove base
   789  	MOVV	R1, ret+24(FP)
   790  	RET
   791  
   792  notfound:
   793  	MOVV	$-1, R1
   794  	MOVV	R1, ret+24(FP)
   795  	RET
   796  
   797  TEXT runtime·return0(SB), NOSPLIT, $0
   798  	MOVW	$0, R1
   799  	RET
   800  
   801  // Called from cgo wrappers, this function returns g->m->curg.stack.hi.
   802  // Must obey the gcc calling convention.
   803  TEXT _cgo_topofstack(SB),NOSPLIT,$16
   804  	// g (R30) and REGTMP (R23)  might be clobbered by load_g. They
   805  	// are callee-save in the gcc calling convention, so save them.
   806  	MOVV	R23, savedR23-16(SP)
   807  	MOVV	g, savedG-8(SP)
   808  
   809  	JAL	runtime·load_g(SB)
   810  	MOVV	g_m(g), R1
   811  	MOVV	m_curg(R1), R1
   812  	MOVV	(g_stack+stack_hi)(R1), R2 // return value in R2
   813  
   814  	MOVV	savedG-8(SP), g
   815  	MOVV	savedR23-16(SP), R23
   816  	RET
   817  
   818  // The top-most function running on a goroutine
   819  // returns to goexit+PCQuantum.
   820  TEXT runtime·goexit(SB),NOSPLIT,$-8-0
   821  	NOR	R0, R0	// NOP
   822  	JAL	runtime·goexit1(SB)	// does not return
   823  	// traceback from goexit1 must hit code range of goexit
   824  	NOR	R0, R0	// NOP
   825  
   826  TEXT ·checkASM(SB),NOSPLIT,$0-1
   827  	MOVW	$1, R1
   828  	MOVB	R1, ret+0(FP)
   829  	RET