github.com/megatontech/mynoteforgo@v0.0.0-20200507084910-5d0c6ea6e890/源码/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|NOFRAME,$0-0
    82  	MOVV	R0, 2(R0) // TODO: TD
    83  	RET
    84  
    85  TEXT runtime·asminit(SB),NOSPLIT|NOFRAME,$0-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|NOFRAME, $0-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|NOFRAME, $0-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  	JAL	runtime·abort(SB)
   183  
   184  switch:
   185  	// save our state in g->sched. Pretend to
   186  	// be systemstack_switch if the G stack is scanned.
   187  	MOVV	$runtime·systemstack_switch(SB), R4
   188  	ADDV	$8, R4	// get past prologue
   189  	MOVV	R4, (g_sched+gobuf_pc)(g)
   190  	MOVV	R29, (g_sched+gobuf_sp)(g)
   191  	MOVV	R0, (g_sched+gobuf_lr)(g)
   192  	MOVV	g, (g_sched+gobuf_g)(g)
   193  
   194  	// switch to g0
   195  	MOVV	R3, g
   196  	JAL	runtime·save_g(SB)
   197  	MOVV	(g_sched+gobuf_sp)(g), R1
   198  	// make it look like mstart called systemstack on g0, to stop traceback
   199  	ADDV	$-8, R1
   200  	MOVV	$runtime·mstart(SB), R2
   201  	MOVV	R2, 0(R1)
   202  	MOVV	R1, R29
   203  
   204  	// call target function
   205  	MOVV	0(REGCTXT), R4	// code pointer
   206  	JAL	(R4)
   207  
   208  	// switch back to g
   209  	MOVV	g_m(g), R1
   210  	MOVV	m_curg(R1), g
   211  	JAL	runtime·save_g(SB)
   212  	MOVV	(g_sched+gobuf_sp)(g), R29
   213  	MOVV	R0, (g_sched+gobuf_sp)(g)
   214  	RET
   215  
   216  noswitch:
   217  	// already on m stack, just call directly
   218  	// Using a tail call here cleans up tracebacks since we won't stop
   219  	// at an intermediate systemstack.
   220  	MOVV	0(REGCTXT), R4	// code pointer
   221  	MOVV	0(R29), R31	// restore LR
   222  	ADDV	$8, R29
   223  	JMP	(R4)
   224  
   225  /*
   226   * support for morestack
   227   */
   228  
   229  // Called during function prolog when more stack is needed.
   230  // Caller has already loaded:
   231  // R1: framesize, R2: argsize, R3: LR
   232  //
   233  // The traceback routines see morestack on a g0 as being
   234  // the top of a stack (for example, morestack calling newstack
   235  // calling the scheduler calling newm calling gc), so we must
   236  // record an argument size. For that purpose, it has no arguments.
   237  TEXT runtime·morestack(SB),NOSPLIT|NOFRAME,$0-0
   238  	// Cannot grow scheduler stack (m->g0).
   239  	MOVV	g_m(g), R7
   240  	MOVV	m_g0(R7), R8
   241  	BNE	g, R8, 3(PC)
   242  	JAL	runtime·badmorestackg0(SB)
   243  	JAL	runtime·abort(SB)
   244  
   245  	// Cannot grow signal stack (m->gsignal).
   246  	MOVV	m_gsignal(R7), R8
   247  	BNE	g, R8, 3(PC)
   248  	JAL	runtime·badmorestackgsignal(SB)
   249  	JAL	runtime·abort(SB)
   250  
   251  	// Called from f.
   252  	// Set g->sched to context in f.
   253  	MOVV	R29, (g_sched+gobuf_sp)(g)
   254  	MOVV	R31, (g_sched+gobuf_pc)(g)
   255  	MOVV	R3, (g_sched+gobuf_lr)(g)
   256  	MOVV	REGCTXT, (g_sched+gobuf_ctxt)(g)
   257  
   258  	// Called from f.
   259  	// Set m->morebuf to f's caller.
   260  	MOVV	R3, (m_morebuf+gobuf_pc)(R7)	// f's caller's PC
   261  	MOVV	R29, (m_morebuf+gobuf_sp)(R7)	// f's caller's SP
   262  	MOVV	g, (m_morebuf+gobuf_g)(R7)
   263  
   264  	// Call newstack on m->g0's stack.
   265  	MOVV	m_g0(R7), g
   266  	JAL	runtime·save_g(SB)
   267  	MOVV	(g_sched+gobuf_sp)(g), R29
   268  	// Create a stack frame on g0 to call newstack.
   269  	MOVV	R0, -8(R29)	// Zero saved LR in frame
   270  	ADDV	$-8, R29
   271  	JAL	runtime·newstack(SB)
   272  
   273  	// Not reached, but make sure the return PC from the call to newstack
   274  	// is still in this function, and not the beginning of the next.
   275  	UNDEF
   276  
   277  TEXT runtime·morestack_noctxt(SB),NOSPLIT|NOFRAME,$0-0
   278  	MOVV	R0, REGCTXT
   279  	JMP	runtime·morestack(SB)
   280  
   281  // reflectcall: call a function with the given argument list
   282  // func call(argtype *_type, f *FuncVal, arg *byte, argsize, retoffset uint32).
   283  // we don't have variable-sized frames, so we use a small number
   284  // of constant-sized-frame functions to encode a few bits of size in the pc.
   285  // Caution: ugly multiline assembly macros in your future!
   286  
   287  #define DISPATCH(NAME,MAXSIZE)		\
   288  	MOVV	$MAXSIZE, R23;		\
   289  	SGTU	R1, R23, R23;		\
   290  	BNE	R23, 3(PC);			\
   291  	MOVV	$NAME(SB), R4;	\
   292  	JMP	(R4)
   293  // Note: can't just "BR NAME(SB)" - bad inlining results.
   294  
   295  TEXT ·reflectcall(SB), NOSPLIT|NOFRAME, $0-32
   296  	MOVWU argsize+24(FP), R1
   297  	DISPATCH(runtime·call32, 32)
   298  	DISPATCH(runtime·call64, 64)
   299  	DISPATCH(runtime·call128, 128)
   300  	DISPATCH(runtime·call256, 256)
   301  	DISPATCH(runtime·call512, 512)
   302  	DISPATCH(runtime·call1024, 1024)
   303  	DISPATCH(runtime·call2048, 2048)
   304  	DISPATCH(runtime·call4096, 4096)
   305  	DISPATCH(runtime·call8192, 8192)
   306  	DISPATCH(runtime·call16384, 16384)
   307  	DISPATCH(runtime·call32768, 32768)
   308  	DISPATCH(runtime·call65536, 65536)
   309  	DISPATCH(runtime·call131072, 131072)
   310  	DISPATCH(runtime·call262144, 262144)
   311  	DISPATCH(runtime·call524288, 524288)
   312  	DISPATCH(runtime·call1048576, 1048576)
   313  	DISPATCH(runtime·call2097152, 2097152)
   314  	DISPATCH(runtime·call4194304, 4194304)
   315  	DISPATCH(runtime·call8388608, 8388608)
   316  	DISPATCH(runtime·call16777216, 16777216)
   317  	DISPATCH(runtime·call33554432, 33554432)
   318  	DISPATCH(runtime·call67108864, 67108864)
   319  	DISPATCH(runtime·call134217728, 134217728)
   320  	DISPATCH(runtime·call268435456, 268435456)
   321  	DISPATCH(runtime·call536870912, 536870912)
   322  	DISPATCH(runtime·call1073741824, 1073741824)
   323  	MOVV	$runtime·badreflectcall(SB), R4
   324  	JMP	(R4)
   325  
   326  #define CALLFN(NAME,MAXSIZE)			\
   327  TEXT NAME(SB), WRAPPER, $MAXSIZE-24;		\
   328  	NO_LOCAL_POINTERS;			\
   329  	/* copy arguments to stack */		\
   330  	MOVV	arg+16(FP), R1;			\
   331  	MOVWU	argsize+24(FP), R2;			\
   332  	MOVV	R29, R3;				\
   333  	ADDV	$8, R3;			\
   334  	ADDV	R3, R2;				\
   335  	BEQ	R3, R2, 6(PC);				\
   336  	MOVBU	(R1), R4;			\
   337  	ADDV	$1, R1;			\
   338  	MOVBU	R4, (R3);			\
   339  	ADDV	$1, R3;			\
   340  	JMP	-5(PC);				\
   341  	/* call function */			\
   342  	MOVV	f+8(FP), REGCTXT;			\
   343  	MOVV	(REGCTXT), R4;			\
   344  	PCDATA  $PCDATA_StackMapIndex, $0;	\
   345  	JAL	(R4);				\
   346  	/* copy return values back */		\
   347  	MOVV	argtype+0(FP), R5;		\
   348  	MOVV	arg+16(FP), R1;			\
   349  	MOVWU	n+24(FP), R2;			\
   350  	MOVWU	retoffset+28(FP), R4;		\
   351  	ADDV	$8, R29, R3;				\
   352  	ADDV	R4, R3; 			\
   353  	ADDV	R4, R1;				\
   354  	SUBVU	R4, R2;				\
   355  	JAL	callRet<>(SB);			\
   356  	RET
   357  
   358  // callRet copies return values back at the end of call*. This is a
   359  // separate function so it can allocate stack space for the arguments
   360  // to reflectcallmove. It does not follow the Go ABI; it expects its
   361  // arguments in registers.
   362  TEXT callRet<>(SB), NOSPLIT, $32-0
   363  	MOVV	R5, 8(R29)
   364  	MOVV	R1, 16(R29)
   365  	MOVV	R3, 24(R29)
   366  	MOVV	R2, 32(R29)
   367  	JAL	runtime·reflectcallmove(SB)
   368  	RET
   369  
   370  CALLFN(·call16, 16)
   371  CALLFN(·call32, 32)
   372  CALLFN(·call64, 64)
   373  CALLFN(·call128, 128)
   374  CALLFN(·call256, 256)
   375  CALLFN(·call512, 512)
   376  CALLFN(·call1024, 1024)
   377  CALLFN(·call2048, 2048)
   378  CALLFN(·call4096, 4096)
   379  CALLFN(·call8192, 8192)
   380  CALLFN(·call16384, 16384)
   381  CALLFN(·call32768, 32768)
   382  CALLFN(·call65536, 65536)
   383  CALLFN(·call131072, 131072)
   384  CALLFN(·call262144, 262144)
   385  CALLFN(·call524288, 524288)
   386  CALLFN(·call1048576, 1048576)
   387  CALLFN(·call2097152, 2097152)
   388  CALLFN(·call4194304, 4194304)
   389  CALLFN(·call8388608, 8388608)
   390  CALLFN(·call16777216, 16777216)
   391  CALLFN(·call33554432, 33554432)
   392  CALLFN(·call67108864, 67108864)
   393  CALLFN(·call134217728, 134217728)
   394  CALLFN(·call268435456, 268435456)
   395  CALLFN(·call536870912, 536870912)
   396  CALLFN(·call1073741824, 1073741824)
   397  
   398  TEXT runtime·procyield(SB),NOSPLIT,$0-0
   399  	RET
   400  
   401  // void jmpdefer(fv, sp);
   402  // called from deferreturn.
   403  // 1. grab stored LR for caller
   404  // 2. sub 8 bytes to get back to JAL deferreturn
   405  // 3. JMP to fn
   406  TEXT runtime·jmpdefer(SB), NOSPLIT|NOFRAME, $0-16
   407  	MOVV	0(R29), R31
   408  	ADDV	$-8, R31
   409  
   410  	MOVV	fv+0(FP), REGCTXT
   411  	MOVV	argp+8(FP), R29
   412  	ADDV	$-8, R29
   413  	NOR	R0, R0	// prevent scheduling
   414  	MOVV	0(REGCTXT), R4
   415  	JMP	(R4)
   416  
   417  // Save state of caller into g->sched. Smashes R1.
   418  TEXT gosave<>(SB),NOSPLIT|NOFRAME,$0
   419  	MOVV	R31, (g_sched+gobuf_pc)(g)
   420  	MOVV	R29, (g_sched+gobuf_sp)(g)
   421  	MOVV	R0, (g_sched+gobuf_lr)(g)
   422  	MOVV	R0, (g_sched+gobuf_ret)(g)
   423  	// Assert ctxt is zero. See func save.
   424  	MOVV	(g_sched+gobuf_ctxt)(g), R1
   425  	BEQ	R1, 2(PC)
   426  	JAL	runtime·badctxt(SB)
   427  	RET
   428  
   429  // func asmcgocall(fn, arg unsafe.Pointer) int32
   430  // Call fn(arg) on the scheduler stack,
   431  // aligned appropriately for the gcc ABI.
   432  // See cgocall.go for more details.
   433  TEXT ·asmcgocall(SB),NOSPLIT,$0-20
   434  	MOVV	fn+0(FP), R25
   435  	MOVV	arg+8(FP), R4
   436  
   437  	MOVV	R29, R3	// save original stack pointer
   438  	MOVV	g, R2
   439  
   440  	// Figure out if we need to switch to m->g0 stack.
   441  	// We get called to create new OS threads too, and those
   442  	// come in on the m->g0 stack already.
   443  	MOVV	g_m(g), R5
   444  	MOVV	m_g0(R5), R6
   445  	BEQ	R6, g, g0
   446  
   447  	JAL	gosave<>(SB)
   448  	MOVV	R6, g
   449  	JAL	runtime·save_g(SB)
   450  	MOVV	(g_sched+gobuf_sp)(g), R29
   451  
   452  	// Now on a scheduling stack (a pthread-created stack).
   453  g0:
   454  	// Save room for two of our pointers.
   455  	ADDV	$-16, R29
   456  	MOVV	R2, 0(R29)	// save old g on stack
   457  	MOVV	(g_stack+stack_hi)(R2), R2
   458  	SUBVU	R3, R2
   459  	MOVV	R2, 8(R29)	// save depth in old g stack (can't just save SP, as stack might be copied during a callback)
   460  	JAL	(R25)
   461  
   462  	// Restore g, stack pointer. R2 is return value.
   463  	MOVV	0(R29), g
   464  	JAL	runtime·save_g(SB)
   465  	MOVV	(g_stack+stack_hi)(g), R5
   466  	MOVV	8(R29), R6
   467  	SUBVU	R6, R5
   468  	MOVV	R5, R29
   469  
   470  	MOVW	R2, ret+16(FP)
   471  	RET
   472  
   473  // cgocallback(void (*fn)(void*), void *frame, uintptr framesize, uintptr ctxt)
   474  // Turn the fn into a Go func (by taking its address) and call
   475  // cgocallback_gofunc.
   476  TEXT runtime·cgocallback(SB),NOSPLIT,$32-32
   477  	MOVV	$fn+0(FP), R1
   478  	MOVV	R1, 8(R29)
   479  	MOVV	frame+8(FP), R1
   480  	MOVV	R1, 16(R29)
   481  	MOVV	framesize+16(FP), R1
   482  	MOVV	R1, 24(R29)
   483  	MOVV	ctxt+24(FP), R1
   484  	MOVV	R1, 32(R29)
   485  	MOVV	$runtime·cgocallback_gofunc(SB), R1
   486  	JAL	(R1)
   487  	RET
   488  
   489  // cgocallback_gofunc(FuncVal*, void *frame, uintptr framesize, uintptr ctxt)
   490  // See cgocall.go for more details.
   491  TEXT ·cgocallback_gofunc(SB),NOSPLIT,$16-32
   492  	NO_LOCAL_POINTERS
   493  
   494  	// Load m and g from thread-local storage.
   495  	MOVB	runtime·iscgo(SB), R1
   496  	BEQ	R1, nocgo
   497  	JAL	runtime·load_g(SB)
   498  nocgo:
   499  
   500  	// If g is nil, Go did not create the current thread.
   501  	// Call needm to obtain one for temporary use.
   502  	// In this case, we're running on the thread stack, so there's
   503  	// lots of space, but the linker doesn't know. Hide the call from
   504  	// the linker analysis by using an indirect call.
   505  	BEQ	g, needm
   506  
   507  	MOVV	g_m(g), R3
   508  	MOVV	R3, savedm-8(SP)
   509  	JMP	havem
   510  
   511  needm:
   512  	MOVV	g, savedm-8(SP) // g is zero, so is m.
   513  	MOVV	$runtime·needm(SB), R4
   514  	JAL	(R4)
   515  
   516  	// Set m->sched.sp = SP, so that if a panic happens
   517  	// during the function we are about to execute, it will
   518  	// have a valid SP to run on the g0 stack.
   519  	// The next few lines (after the havem label)
   520  	// will save this SP onto the stack and then write
   521  	// the same SP back to m->sched.sp. That seems redundant,
   522  	// but if an unrecovered panic happens, unwindm will
   523  	// restore the g->sched.sp from the stack location
   524  	// and then systemstack will try to use it. If we don't set it here,
   525  	// that restored SP will be uninitialized (typically 0) and
   526  	// will not be usable.
   527  	MOVV	g_m(g), R3
   528  	MOVV	m_g0(R3), R1
   529  	MOVV	R29, (g_sched+gobuf_sp)(R1)
   530  
   531  havem:
   532  	// Now there's a valid m, and we're running on its m->g0.
   533  	// Save current m->g0->sched.sp on stack and then set it to SP.
   534  	// Save current sp in m->g0->sched.sp in preparation for
   535  	// switch back to m->curg stack.
   536  	// NOTE: unwindm knows that the saved g->sched.sp is at 8(R29) aka savedsp-16(SP).
   537  	MOVV	m_g0(R3), R1
   538  	MOVV	(g_sched+gobuf_sp)(R1), R2
   539  	MOVV	R2, savedsp-16(SP)
   540  	MOVV	R29, (g_sched+gobuf_sp)(R1)
   541  
   542  	// Switch to m->curg stack and call runtime.cgocallbackg.
   543  	// Because we are taking over the execution of m->curg
   544  	// but *not* resuming what had been running, we need to
   545  	// save that information (m->curg->sched) so we can restore it.
   546  	// We can restore m->curg->sched.sp easily, because calling
   547  	// runtime.cgocallbackg leaves SP unchanged upon return.
   548  	// To save m->curg->sched.pc, we push it onto the stack.
   549  	// This has the added benefit that it looks to the traceback
   550  	// routine like cgocallbackg is going to return to that
   551  	// PC (because the frame we allocate below has the same
   552  	// size as cgocallback_gofunc's frame declared above)
   553  	// so that the traceback will seamlessly trace back into
   554  	// the earlier calls.
   555  	//
   556  	// In the new goroutine, -8(SP) is unused (where SP refers to
   557  	// m->curg's SP while we're setting it up, before we've adjusted it).
   558  	MOVV	m_curg(R3), g
   559  	JAL	runtime·save_g(SB)
   560  	MOVV	(g_sched+gobuf_sp)(g), R2 // prepare stack as R2
   561  	MOVV	(g_sched+gobuf_pc)(g), R4
   562  	MOVV	R4, -24(R2)
   563  	MOVV    ctxt+24(FP), R1
   564  	MOVV    R1, -16(R2)
   565  	MOVV	$-24(R2), R29
   566  	JAL	runtime·cgocallbackg(SB)
   567  
   568  	// Restore g->sched (== m->curg->sched) from saved values.
   569  	MOVV	0(R29), R4
   570  	MOVV	R4, (g_sched+gobuf_pc)(g)
   571  	MOVV	$24(R29), R2
   572  	MOVV	R2, (g_sched+gobuf_sp)(g)
   573  
   574  	// Switch back to m->g0's stack and restore m->g0->sched.sp.
   575  	// (Unlike m->curg, the g0 goroutine never uses sched.pc,
   576  	// so we do not have to restore it.)
   577  	MOVV	g_m(g), R3
   578  	MOVV	m_g0(R3), g
   579  	JAL	runtime·save_g(SB)
   580  	MOVV	(g_sched+gobuf_sp)(g), R29
   581  	MOVV	savedsp-16(SP), R2
   582  	MOVV	R2, (g_sched+gobuf_sp)(g)
   583  
   584  	// If the m on entry was nil, we called needm above to borrow an m
   585  	// for the duration of the call. Since the call is over, return it with dropm.
   586  	MOVV	savedm-8(SP), R3
   587  	BNE	R3, droppedm
   588  	MOVV	$runtime·dropm(SB), R4
   589  	JAL	(R4)
   590  droppedm:
   591  
   592  	// Done!
   593  	RET
   594  
   595  // void setg(G*); set g. for use by needm.
   596  TEXT runtime·setg(SB), NOSPLIT, $0-8
   597  	MOVV	gg+0(FP), g
   598  	// This only happens if iscgo, so jump straight to save_g
   599  	JAL	runtime·save_g(SB)
   600  	RET
   601  
   602  // void setg_gcc(G*); set g called from gcc with g in R1
   603  TEXT setg_gcc<>(SB),NOSPLIT,$0-0
   604  	MOVV	R1, g
   605  	JAL	runtime·save_g(SB)
   606  	RET
   607  
   608  TEXT runtime·abort(SB),NOSPLIT|NOFRAME,$0-0
   609  	MOVW	(R0), R0
   610  	UNDEF
   611  
   612  // AES hashing not implemented for mips64
   613  TEXT runtime·aeshash(SB),NOSPLIT|NOFRAME,$0-0
   614  	MOVW	(R0), R1
   615  TEXT runtime·aeshash32(SB),NOSPLIT|NOFRAME,$0-0
   616  	MOVW	(R0), R1
   617  TEXT runtime·aeshash64(SB),NOSPLIT|NOFRAME,$0-0
   618  	MOVW	(R0), R1
   619  TEXT runtime·aeshashstr(SB),NOSPLIT|NOFRAME,$0-0
   620  	MOVW	(R0), R1
   621  
   622  TEXT runtime·return0(SB), NOSPLIT, $0
   623  	MOVW	$0, R1
   624  	RET
   625  
   626  // Called from cgo wrappers, this function returns g->m->curg.stack.hi.
   627  // Must obey the gcc calling convention.
   628  TEXT _cgo_topofstack(SB),NOSPLIT,$16
   629  	// g (R30) and REGTMP (R23)  might be clobbered by load_g. They
   630  	// are callee-save in the gcc calling convention, so save them.
   631  	MOVV	R23, savedR23-16(SP)
   632  	MOVV	g, savedG-8(SP)
   633  
   634  	JAL	runtime·load_g(SB)
   635  	MOVV	g_m(g), R1
   636  	MOVV	m_curg(R1), R1
   637  	MOVV	(g_stack+stack_hi)(R1), R2 // return value in R2
   638  
   639  	MOVV	savedG-8(SP), g
   640  	MOVV	savedR23-16(SP), R23
   641  	RET
   642  
   643  // The top-most function running on a goroutine
   644  // returns to goexit+PCQuantum.
   645  TEXT runtime·goexit(SB),NOSPLIT|NOFRAME,$0-0
   646  	NOR	R0, R0	// NOP
   647  	JAL	runtime·goexit1(SB)	// does not return
   648  	// traceback from goexit1 must hit code range of goexit
   649  	NOR	R0, R0	// NOP
   650  
   651  TEXT ·checkASM(SB),NOSPLIT,$0-1
   652  	MOVW	$1, R1
   653  	MOVB	R1, ret+0(FP)
   654  	RET
   655  
   656  // gcWriteBarrier performs a heap pointer write and informs the GC.
   657  //
   658  // gcWriteBarrier does NOT follow the Go ABI. It takes two arguments:
   659  // - R20 is the destination of the write
   660  // - R21 is the value being written at R20.
   661  // It clobbers R23 (the linker temp register).
   662  // The act of CALLing gcWriteBarrier will clobber R31 (LR).
   663  // It does not clobber any other general-purpose registers,
   664  // but may clobber others (e.g., floating point registers).
   665  TEXT runtime·gcWriteBarrier(SB),NOSPLIT,$192
   666  	// Save the registers clobbered by the fast path.
   667  	MOVV	R1, 184(R29)
   668  	MOVV	R2, 192(R29)
   669  	MOVV	g_m(g), R1
   670  	MOVV	m_p(R1), R1
   671  	MOVV	(p_wbBuf+wbBuf_next)(R1), R2
   672  	// Increment wbBuf.next position.
   673  	ADDV	$16, R2
   674  	MOVV	R2, (p_wbBuf+wbBuf_next)(R1)
   675  	MOVV	(p_wbBuf+wbBuf_end)(R1), R1
   676  	MOVV	R1, R23		// R23 is linker temp register
   677  	// Record the write.
   678  	MOVV	R21, -16(R2)	// Record value
   679  	MOVV	(R20), R1	// TODO: This turns bad writes into bad reads.
   680  	MOVV	R1, -8(R2)	// Record *slot
   681  	// Is the buffer full?
   682  	BEQ	R2, R23, flush
   683  ret:
   684  	MOVV	184(R29), R1
   685  	MOVV	192(R29), R2
   686  	// Do the write.
   687  	MOVV	R21, (R20)
   688  	RET
   689  
   690  flush:
   691  	// Save all general purpose registers since these could be
   692  	// clobbered by wbBufFlush and were not saved by the caller.
   693  	MOVV	R20, 8(R29)	// Also first argument to wbBufFlush
   694  	MOVV	R21, 16(R29)	// Also second argument to wbBufFlush
   695  	// R1 already saved
   696  	// R2 already saved
   697  	MOVV	R3, 24(R29)
   698  	MOVV	R4, 32(R29)
   699  	MOVV	R5, 40(R29)
   700  	MOVV	R6, 48(R29)
   701  	MOVV	R7, 56(R29)
   702  	MOVV	R8, 64(R29)
   703  	MOVV	R9, 72(R29)
   704  	MOVV	R10, 80(R29)
   705  	MOVV	R11, 88(R29)
   706  	MOVV	R12, 96(R29)
   707  	MOVV	R13, 104(R29)
   708  	MOVV	R14, 112(R29)
   709  	MOVV	R15, 120(R29)
   710  	MOVV	R16, 128(R29)
   711  	MOVV	R17, 136(R29)
   712  	MOVV	R18, 144(R29)
   713  	MOVV	R19, 152(R29)
   714  	// R20 already saved
   715  	// R21 already saved.
   716  	MOVV	R22, 160(R29)
   717  	// R23 is tmp register.
   718  	MOVV	R24, 168(R29)
   719  	MOVV	R25, 176(R29)
   720  	// R26 is reserved by kernel.
   721  	// R27 is reserved by kernel.
   722  	// R28 is REGSB (not modified by Go code).
   723  	// R29 is SP.
   724  	// R30 is g.
   725  	// R31 is LR, which was saved by the prologue.
   726  
   727  	// This takes arguments R20 and R21.
   728  	CALL	runtime·wbBufFlush(SB)
   729  
   730  	MOVV	8(R29), R20
   731  	MOVV	16(R29), R21
   732  	MOVV	24(R29), R3
   733  	MOVV	32(R29), R4
   734  	MOVV	40(R29), R5
   735  	MOVV	48(R29), R6
   736  	MOVV	56(R29), R7
   737  	MOVV	64(R29), R8
   738  	MOVV	72(R29), R9
   739  	MOVV	80(R29), R10
   740  	MOVV	88(R29), R11
   741  	MOVV	96(R29), R12
   742  	MOVV	104(R29), R13
   743  	MOVV	112(R29), R14
   744  	MOVV	120(R29), R15
   745  	MOVV	128(R29), R16
   746  	MOVV	136(R29), R17
   747  	MOVV	144(R29), R18
   748  	MOVV	152(R29), R19
   749  	MOVV	160(R29), R22
   750  	MOVV	168(R29), R24
   751  	MOVV	176(R29), R25
   752  	JMP	ret