github.com/hlts2/go@v0.0.0-20170904000733-812b34efaed8/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  // AES hashing not implemented for mips64
   629  TEXT runtime·aeshash(SB),NOSPLIT,$-8-0
   630  	MOVW	(R0), R1
   631  TEXT runtime·aeshash32(SB),NOSPLIT,$-8-0
   632  	MOVW	(R0), R1
   633  TEXT runtime·aeshash64(SB),NOSPLIT,$-8-0
   634  	MOVW	(R0), R1
   635  TEXT runtime·aeshashstr(SB),NOSPLIT,$-8-0
   636  	MOVW	(R0), R1
   637  
   638  // memequal(p, q unsafe.Pointer, size uintptr) bool
   639  TEXT runtime·memequal(SB),NOSPLIT,$-8-25
   640  	MOVV	a+0(FP), R1
   641  	MOVV	b+8(FP), R2
   642  	BEQ	R1, R2, eq
   643  	MOVV	size+16(FP), R3
   644  	ADDV	R1, R3, R4
   645  loop:
   646  	BNE	R1, R4, test
   647  	MOVV	$1, R1
   648  	MOVB	R1, ret+24(FP)
   649  	RET
   650  test:
   651  	MOVBU	(R1), R6
   652  	ADDV	$1, R1
   653  	MOVBU	(R2), R7
   654  	ADDV	$1, R2
   655  	BEQ	R6, R7, loop
   656  
   657  	MOVB	R0, ret+24(FP)
   658  	RET
   659  eq:
   660  	MOVV	$1, R1
   661  	MOVB	R1, ret+24(FP)
   662  	RET
   663  
   664  // memequal_varlen(a, b unsafe.Pointer) bool
   665  TEXT runtime·memequal_varlen(SB),NOSPLIT,$40-17
   666  	MOVV	a+0(FP), R1
   667  	MOVV	b+8(FP), R2
   668  	BEQ	R1, R2, eq
   669  	MOVV	8(REGCTXT), R3    // compiler stores size at offset 8 in the closure
   670  	MOVV	R1, 8(R29)
   671  	MOVV	R2, 16(R29)
   672  	MOVV	R3, 24(R29)
   673  	JAL	runtime·memequal(SB)
   674  	MOVBU	32(R29), R1
   675  	MOVB	R1, ret+16(FP)
   676  	RET
   677  eq:
   678  	MOVV	$1, R1
   679  	MOVB	R1, ret+16(FP)
   680  	RET
   681  
   682  // TODO: share code with memequal?
   683  TEXT bytes·Equal(SB),NOSPLIT,$0-49
   684  	MOVV	a_len+8(FP), R3
   685  	MOVV	b_len+32(FP), R4
   686  	BNE	R3, R4, noteq		// unequal lengths are not equal
   687  
   688  	MOVV	a+0(FP), R1
   689  	MOVV	b+24(FP), R2
   690  	ADDV	R1, R3		// end
   691  
   692  loop:
   693  	BEQ	R1, R3, equal		// reached the end
   694  	MOVBU	(R1), R6
   695  	ADDV	$1, R1
   696  	MOVBU	(R2), R7
   697  	ADDV	$1, R2
   698  	BEQ	R6, R7, loop
   699  
   700  noteq:
   701  	MOVB	R0, ret+48(FP)
   702  	RET
   703  
   704  equal:
   705  	MOVV	$1, R1
   706  	MOVB	R1, ret+48(FP)
   707  	RET
   708  
   709  TEXT bytes·IndexByte(SB),NOSPLIT,$0-40
   710  	MOVV	s+0(FP), R1
   711  	MOVV	s_len+8(FP), R2
   712  	MOVBU	c+24(FP), R3	// byte to find
   713  	MOVV	R1, R4		// store base for later
   714  	ADDV	R1, R2		// end
   715  	ADDV	$-1, R1
   716  
   717  loop:
   718  	ADDV	$1, R1
   719  	BEQ	R1, R2, notfound
   720  	MOVBU	(R1), R5
   721  	BNE	R3, R5, loop
   722  
   723  	SUBV	R4, R1		// remove base
   724  	MOVV	R1, ret+32(FP)
   725  	RET
   726  
   727  notfound:
   728  	MOVV	$-1, R1
   729  	MOVV	R1, ret+32(FP)
   730  	RET
   731  
   732  TEXT strings·IndexByte(SB),NOSPLIT,$0-32
   733  	MOVV	p+0(FP), R1
   734  	MOVV	b_len+8(FP), R2
   735  	MOVBU	c+16(FP), R3	// byte to find
   736  	MOVV	R1, R4		// store base for later
   737  	ADDV	R1, R2		// end
   738  	ADDV	$-1, R1
   739  
   740  loop:
   741  	ADDV	$1, R1
   742  	BEQ	R1, R2, notfound
   743  	MOVBU	(R1), R5
   744  	BNE	R3, R5, loop
   745  
   746  	SUBV	R4, R1		// remove base
   747  	MOVV	R1, ret+24(FP)
   748  	RET
   749  
   750  notfound:
   751  	MOVV	$-1, R1
   752  	MOVV	R1, ret+24(FP)
   753  	RET
   754  
   755  TEXT runtime·return0(SB), NOSPLIT, $0
   756  	MOVW	$0, R1
   757  	RET
   758  
   759  // Called from cgo wrappers, this function returns g->m->curg.stack.hi.
   760  // Must obey the gcc calling convention.
   761  TEXT _cgo_topofstack(SB),NOSPLIT,$16
   762  	// g (R30) and REGTMP (R23)  might be clobbered by load_g. They
   763  	// are callee-save in the gcc calling convention, so save them.
   764  	MOVV	R23, savedR23-16(SP)
   765  	MOVV	g, savedG-8(SP)
   766  
   767  	JAL	runtime·load_g(SB)
   768  	MOVV	g_m(g), R1
   769  	MOVV	m_curg(R1), R1
   770  	MOVV	(g_stack+stack_hi)(R1), R2 // return value in R2
   771  
   772  	MOVV	savedG-8(SP), g
   773  	MOVV	savedR23-16(SP), R23
   774  	RET
   775  
   776  // The top-most function running on a goroutine
   777  // returns to goexit+PCQuantum.
   778  TEXT runtime·goexit(SB),NOSPLIT,$-8-0
   779  	NOR	R0, R0	// NOP
   780  	JAL	runtime·goexit1(SB)	// does not return
   781  	// traceback from goexit1 must hit code range of goexit
   782  	NOR	R0, R0	// NOP
   783  
   784  TEXT ·checkASM(SB),NOSPLIT,$0-1
   785  	MOVW	$1, R1
   786  	MOVB	R1, ret+0(FP)
   787  	RET