github.com/lzhfromustc/gofuzz@v0.0.0-20211116160056-151b3108bbd1/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·call16, 16)
   298  	DISPATCH(runtime·call32, 32)
   299  	DISPATCH(runtime·call64, 64)
   300  	DISPATCH(runtime·call128, 128)
   301  	DISPATCH(runtime·call256, 256)
   302  	DISPATCH(runtime·call512, 512)
   303  	DISPATCH(runtime·call1024, 1024)
   304  	DISPATCH(runtime·call2048, 2048)
   305  	DISPATCH(runtime·call4096, 4096)
   306  	DISPATCH(runtime·call8192, 8192)
   307  	DISPATCH(runtime·call16384, 16384)
   308  	DISPATCH(runtime·call32768, 32768)
   309  	DISPATCH(runtime·call65536, 65536)
   310  	DISPATCH(runtime·call131072, 131072)
   311  	DISPATCH(runtime·call262144, 262144)
   312  	DISPATCH(runtime·call524288, 524288)
   313  	DISPATCH(runtime·call1048576, 1048576)
   314  	DISPATCH(runtime·call2097152, 2097152)
   315  	DISPATCH(runtime·call4194304, 4194304)
   316  	DISPATCH(runtime·call8388608, 8388608)
   317  	DISPATCH(runtime·call16777216, 16777216)
   318  	DISPATCH(runtime·call33554432, 33554432)
   319  	DISPATCH(runtime·call67108864, 67108864)
   320  	DISPATCH(runtime·call134217728, 134217728)
   321  	DISPATCH(runtime·call268435456, 268435456)
   322  	DISPATCH(runtime·call536870912, 536870912)
   323  	DISPATCH(runtime·call1073741824, 1073741824)
   324  	MOVV	$runtime·badreflectcall(SB), R4
   325  	JMP	(R4)
   326  
   327  #define CALLFN(NAME,MAXSIZE)			\
   328  TEXT NAME(SB), WRAPPER, $MAXSIZE-24;		\
   329  	NO_LOCAL_POINTERS;			\
   330  	/* copy arguments to stack */		\
   331  	MOVV	arg+16(FP), R1;			\
   332  	MOVWU	argsize+24(FP), R2;			\
   333  	MOVV	R29, R3;				\
   334  	ADDV	$8, R3;			\
   335  	ADDV	R3, R2;				\
   336  	BEQ	R3, R2, 6(PC);				\
   337  	MOVBU	(R1), R4;			\
   338  	ADDV	$1, R1;			\
   339  	MOVBU	R4, (R3);			\
   340  	ADDV	$1, R3;			\
   341  	JMP	-5(PC);				\
   342  	/* call function */			\
   343  	MOVV	f+8(FP), REGCTXT;			\
   344  	MOVV	(REGCTXT), R4;			\
   345  	PCDATA  $PCDATA_StackMapIndex, $0;	\
   346  	JAL	(R4);				\
   347  	/* copy return values back */		\
   348  	MOVV	argtype+0(FP), R5;		\
   349  	MOVV	arg+16(FP), R1;			\
   350  	MOVWU	n+24(FP), R2;			\
   351  	MOVWU	retoffset+28(FP), R4;		\
   352  	ADDV	$8, R29, R3;				\
   353  	ADDV	R4, R3; 			\
   354  	ADDV	R4, R1;				\
   355  	SUBVU	R4, R2;				\
   356  	JAL	callRet<>(SB);			\
   357  	RET
   358  
   359  // callRet copies return values back at the end of call*. This is a
   360  // separate function so it can allocate stack space for the arguments
   361  // to reflectcallmove. It does not follow the Go ABI; it expects its
   362  // arguments in registers.
   363  TEXT callRet<>(SB), NOSPLIT, $32-0
   364  	MOVV	R5, 8(R29)
   365  	MOVV	R1, 16(R29)
   366  	MOVV	R3, 24(R29)
   367  	MOVV	R2, 32(R29)
   368  	JAL	runtime·reflectcallmove(SB)
   369  	RET
   370  
   371  CALLFN(·call16, 16)
   372  CALLFN(·call32, 32)
   373  CALLFN(·call64, 64)
   374  CALLFN(·call128, 128)
   375  CALLFN(·call256, 256)
   376  CALLFN(·call512, 512)
   377  CALLFN(·call1024, 1024)
   378  CALLFN(·call2048, 2048)
   379  CALLFN(·call4096, 4096)
   380  CALLFN(·call8192, 8192)
   381  CALLFN(·call16384, 16384)
   382  CALLFN(·call32768, 32768)
   383  CALLFN(·call65536, 65536)
   384  CALLFN(·call131072, 131072)
   385  CALLFN(·call262144, 262144)
   386  CALLFN(·call524288, 524288)
   387  CALLFN(·call1048576, 1048576)
   388  CALLFN(·call2097152, 2097152)
   389  CALLFN(·call4194304, 4194304)
   390  CALLFN(·call8388608, 8388608)
   391  CALLFN(·call16777216, 16777216)
   392  CALLFN(·call33554432, 33554432)
   393  CALLFN(·call67108864, 67108864)
   394  CALLFN(·call134217728, 134217728)
   395  CALLFN(·call268435456, 268435456)
   396  CALLFN(·call536870912, 536870912)
   397  CALLFN(·call1073741824, 1073741824)
   398  
   399  TEXT runtime·procyield(SB),NOSPLIT,$0-0
   400  	RET
   401  
   402  // void jmpdefer(fv, sp);
   403  // called from deferreturn.
   404  // 1. grab stored LR for caller
   405  // 2. sub 8 bytes to get back to JAL deferreturn
   406  // 3. JMP to fn
   407  TEXT runtime·jmpdefer(SB), NOSPLIT|NOFRAME, $0-16
   408  	MOVV	0(R29), R31
   409  	ADDV	$-8, R31
   410  
   411  	MOVV	fv+0(FP), REGCTXT
   412  	MOVV	argp+8(FP), R29
   413  	ADDV	$-8, R29
   414  	NOR	R0, R0	// prevent scheduling
   415  	MOVV	0(REGCTXT), R4
   416  	JMP	(R4)
   417  
   418  // Save state of caller into g->sched. Smashes R1.
   419  TEXT gosave<>(SB),NOSPLIT|NOFRAME,$0
   420  	MOVV	R31, (g_sched+gobuf_pc)(g)
   421  	MOVV	R29, (g_sched+gobuf_sp)(g)
   422  	MOVV	R0, (g_sched+gobuf_lr)(g)
   423  	MOVV	R0, (g_sched+gobuf_ret)(g)
   424  	// Assert ctxt is zero. See func save.
   425  	MOVV	(g_sched+gobuf_ctxt)(g), R1
   426  	BEQ	R1, 2(PC)
   427  	JAL	runtime·badctxt(SB)
   428  	RET
   429  
   430  // func asmcgocall(fn, arg unsafe.Pointer) int32
   431  // Call fn(arg) on the scheduler stack,
   432  // aligned appropriately for the gcc ABI.
   433  // See cgocall.go for more details.
   434  TEXT ·asmcgocall(SB),NOSPLIT,$0-20
   435  	MOVV	fn+0(FP), R25
   436  	MOVV	arg+8(FP), R4
   437  
   438  	MOVV	R29, R3	// save original stack pointer
   439  	MOVV	g, R2
   440  
   441  	// Figure out if we need to switch to m->g0 stack.
   442  	// We get called to create new OS threads too, and those
   443  	// come in on the m->g0 stack already.
   444  	MOVV	g_m(g), R5
   445  	MOVV	m_g0(R5), R6
   446  	BEQ	R6, g, g0
   447  
   448  	JAL	gosave<>(SB)
   449  	MOVV	R6, g
   450  	JAL	runtime·save_g(SB)
   451  	MOVV	(g_sched+gobuf_sp)(g), R29
   452  
   453  	// Now on a scheduling stack (a pthread-created stack).
   454  g0:
   455  	// Save room for two of our pointers.
   456  	ADDV	$-16, R29
   457  	MOVV	R2, 0(R29)	// save old g on stack
   458  	MOVV	(g_stack+stack_hi)(R2), R2
   459  	SUBVU	R3, R2
   460  	MOVV	R2, 8(R29)	// save depth in old g stack (can't just save SP, as stack might be copied during a callback)
   461  	JAL	(R25)
   462  
   463  	// Restore g, stack pointer. R2 is return value.
   464  	MOVV	0(R29), g
   465  	JAL	runtime·save_g(SB)
   466  	MOVV	(g_stack+stack_hi)(g), R5
   467  	MOVV	8(R29), R6
   468  	SUBVU	R6, R5
   469  	MOVV	R5, R29
   470  
   471  	MOVW	R2, ret+16(FP)
   472  	RET
   473  
   474  // func cgocallback(fn, frame unsafe.Pointer, ctxt uintptr)
   475  // See cgocall.go for more details.
   476  TEXT ·cgocallback(SB),NOSPLIT,$24-24
   477  	NO_LOCAL_POINTERS
   478  
   479  	// Load m and g from thread-local storage.
   480  	MOVB	runtime·iscgo(SB), R1
   481  	BEQ	R1, nocgo
   482  	JAL	runtime·load_g(SB)
   483  nocgo:
   484  
   485  	// If g is nil, Go did not create the current thread.
   486  	// Call needm to obtain one for temporary use.
   487  	// In this case, we're running on the thread stack, so there's
   488  	// lots of space, but the linker doesn't know. Hide the call from
   489  	// the linker analysis by using an indirect call.
   490  	BEQ	g, needm
   491  
   492  	MOVV	g_m(g), R3
   493  	MOVV	R3, savedm-8(SP)
   494  	JMP	havem
   495  
   496  needm:
   497  	MOVV	g, savedm-8(SP) // g is zero, so is m.
   498  	MOVV	$runtime·needm(SB), R4
   499  	JAL	(R4)
   500  
   501  	// Set m->sched.sp = SP, so that if a panic happens
   502  	// during the function we are about to execute, it will
   503  	// have a valid SP to run on the g0 stack.
   504  	// The next few lines (after the havem label)
   505  	// will save this SP onto the stack and then write
   506  	// the same SP back to m->sched.sp. That seems redundant,
   507  	// but if an unrecovered panic happens, unwindm will
   508  	// restore the g->sched.sp from the stack location
   509  	// and then systemstack will try to use it. If we don't set it here,
   510  	// that restored SP will be uninitialized (typically 0) and
   511  	// will not be usable.
   512  	MOVV	g_m(g), R3
   513  	MOVV	m_g0(R3), R1
   514  	MOVV	R29, (g_sched+gobuf_sp)(R1)
   515  
   516  havem:
   517  	// Now there's a valid m, and we're running on its m->g0.
   518  	// Save current m->g0->sched.sp on stack and then set it to SP.
   519  	// Save current sp in m->g0->sched.sp in preparation for
   520  	// switch back to m->curg stack.
   521  	// NOTE: unwindm knows that the saved g->sched.sp is at 8(R29) aka savedsp-16(SP).
   522  	MOVV	m_g0(R3), R1
   523  	MOVV	(g_sched+gobuf_sp)(R1), R2
   524  	MOVV	R2, savedsp-24(SP)	// must match frame size
   525  	MOVV	R29, (g_sched+gobuf_sp)(R1)
   526  
   527  	// Switch to m->curg stack and call runtime.cgocallbackg.
   528  	// Because we are taking over the execution of m->curg
   529  	// but *not* resuming what had been running, we need to
   530  	// save that information (m->curg->sched) so we can restore it.
   531  	// We can restore m->curg->sched.sp easily, because calling
   532  	// runtime.cgocallbackg leaves SP unchanged upon return.
   533  	// To save m->curg->sched.pc, we push it onto the curg stack and
   534  	// open a frame the same size as cgocallback's g0 frame.
   535  	// Once we switch to the curg stack, the pushed PC will appear
   536  	// to be the return PC of cgocallback, so that the traceback
   537  	// will seamlessly trace back into the earlier calls.
   538  	MOVV	m_curg(R3), g
   539  	JAL	runtime·save_g(SB)
   540  	MOVV	(g_sched+gobuf_sp)(g), R2 // prepare stack as R2
   541  	MOVV	(g_sched+gobuf_pc)(g), R4
   542  	MOVV	R4, -(24+8)(R2)	// "saved LR"; must match frame size
   543  	// Gather our arguments into registers.
   544  	MOVV	fn+0(FP), R5
   545  	MOVV	frame+8(FP), R6
   546  	MOVV	ctxt+16(FP), R7
   547  	MOVV	$-(24+8)(R2), R29	// switch stack; must match frame size
   548  	MOVV	R5, 8(R29)
   549  	MOVV	R6, 16(R29)
   550  	MOVV	R7, 24(R29)
   551  	JAL	runtime·cgocallbackg(SB)
   552  
   553  	// Restore g->sched (== m->curg->sched) from saved values.
   554  	MOVV	0(R29), R4
   555  	MOVV	R4, (g_sched+gobuf_pc)(g)
   556  	MOVV	$(24+8)(R29), R2	// must match frame size
   557  	MOVV	R2, (g_sched+gobuf_sp)(g)
   558  
   559  	// Switch back to m->g0's stack and restore m->g0->sched.sp.
   560  	// (Unlike m->curg, the g0 goroutine never uses sched.pc,
   561  	// so we do not have to restore it.)
   562  	MOVV	g_m(g), R3
   563  	MOVV	m_g0(R3), g
   564  	JAL	runtime·save_g(SB)
   565  	MOVV	(g_sched+gobuf_sp)(g), R29
   566  	MOVV	savedsp-24(SP), R2	// must match frame size
   567  	MOVV	R2, (g_sched+gobuf_sp)(g)
   568  
   569  	// If the m on entry was nil, we called needm above to borrow an m
   570  	// for the duration of the call. Since the call is over, return it with dropm.
   571  	MOVV	savedm-8(SP), R3
   572  	BNE	R3, droppedm
   573  	MOVV	$runtime·dropm(SB), R4
   574  	JAL	(R4)
   575  droppedm:
   576  
   577  	// Done!
   578  	RET
   579  
   580  // void setg(G*); set g. for use by needm.
   581  TEXT runtime·setg(SB), NOSPLIT, $0-8
   582  	MOVV	gg+0(FP), g
   583  	// This only happens if iscgo, so jump straight to save_g
   584  	JAL	runtime·save_g(SB)
   585  	RET
   586  
   587  // void setg_gcc(G*); set g called from gcc with g in R1
   588  TEXT setg_gcc<>(SB),NOSPLIT,$0-0
   589  	MOVV	R1, g
   590  	JAL	runtime·save_g(SB)
   591  	RET
   592  
   593  TEXT runtime·abort(SB),NOSPLIT|NOFRAME,$0-0
   594  	MOVW	(R0), R0
   595  	UNDEF
   596  
   597  // AES hashing not implemented for mips64
   598  TEXT runtime·memhash(SB),NOSPLIT|NOFRAME,$0-32
   599  	JMP	runtime·memhashFallback(SB)
   600  TEXT runtime·strhash(SB),NOSPLIT|NOFRAME,$0-24
   601  	JMP	runtime·strhashFallback(SB)
   602  TEXT runtime·memhash32(SB),NOSPLIT|NOFRAME,$0-24
   603  	JMP	runtime·memhash32Fallback(SB)
   604  TEXT runtime·memhash64(SB),NOSPLIT|NOFRAME,$0-24
   605  	JMP	runtime·memhash64Fallback(SB)
   606  
   607  TEXT runtime·return0(SB), NOSPLIT, $0
   608  	MOVW	$0, R1
   609  	RET
   610  
   611  // Called from cgo wrappers, this function returns g->m->curg.stack.hi.
   612  // Must obey the gcc calling convention.
   613  TEXT _cgo_topofstack(SB),NOSPLIT,$16
   614  	// g (R30) and REGTMP (R23)  might be clobbered by load_g. They
   615  	// are callee-save in the gcc calling convention, so save them.
   616  	MOVV	R23, savedR23-16(SP)
   617  	MOVV	g, savedG-8(SP)
   618  
   619  	JAL	runtime·load_g(SB)
   620  	MOVV	g_m(g), R1
   621  	MOVV	m_curg(R1), R1
   622  	MOVV	(g_stack+stack_hi)(R1), R2 // return value in R2
   623  
   624  	MOVV	savedG-8(SP), g
   625  	MOVV	savedR23-16(SP), R23
   626  	RET
   627  
   628  // The top-most function running on a goroutine
   629  // returns to goexit+PCQuantum.
   630  TEXT runtime·goexit(SB),NOSPLIT|NOFRAME|TOPFRAME,$0-0
   631  	NOR	R0, R0	// NOP
   632  	JAL	runtime·goexit1(SB)	// does not return
   633  	// traceback from goexit1 must hit code range of goexit
   634  	NOR	R0, R0	// NOP
   635  
   636  TEXT ·checkASM(SB),NOSPLIT,$0-1
   637  	MOVW	$1, R1
   638  	MOVB	R1, ret+0(FP)
   639  	RET
   640  
   641  // gcWriteBarrier performs a heap pointer write and informs the GC.
   642  //
   643  // gcWriteBarrier does NOT follow the Go ABI. It takes two arguments:
   644  // - R20 is the destination of the write
   645  // - R21 is the value being written at R20.
   646  // It clobbers R23 (the linker temp register).
   647  // The act of CALLing gcWriteBarrier will clobber R31 (LR).
   648  // It does not clobber any other general-purpose registers,
   649  // but may clobber others (e.g., floating point registers).
   650  TEXT runtime·gcWriteBarrier(SB),NOSPLIT,$192
   651  	// Save the registers clobbered by the fast path.
   652  	MOVV	R1, 184(R29)
   653  	MOVV	R2, 192(R29)
   654  	MOVV	g_m(g), R1
   655  	MOVV	m_p(R1), R1
   656  	MOVV	(p_wbBuf+wbBuf_next)(R1), R2
   657  	// Increment wbBuf.next position.
   658  	ADDV	$16, R2
   659  	MOVV	R2, (p_wbBuf+wbBuf_next)(R1)
   660  	MOVV	(p_wbBuf+wbBuf_end)(R1), R1
   661  	MOVV	R1, R23		// R23 is linker temp register
   662  	// Record the write.
   663  	MOVV	R21, -16(R2)	// Record value
   664  	MOVV	(R20), R1	// TODO: This turns bad writes into bad reads.
   665  	MOVV	R1, -8(R2)	// Record *slot
   666  	// Is the buffer full?
   667  	BEQ	R2, R23, flush
   668  ret:
   669  	MOVV	184(R29), R1
   670  	MOVV	192(R29), R2
   671  	// Do the write.
   672  	MOVV	R21, (R20)
   673  	RET
   674  
   675  flush:
   676  	// Save all general purpose registers since these could be
   677  	// clobbered by wbBufFlush and were not saved by the caller.
   678  	MOVV	R20, 8(R29)	// Also first argument to wbBufFlush
   679  	MOVV	R21, 16(R29)	// Also second argument to wbBufFlush
   680  	// R1 already saved
   681  	// R2 already saved
   682  	MOVV	R3, 24(R29)
   683  	MOVV	R4, 32(R29)
   684  	MOVV	R5, 40(R29)
   685  	MOVV	R6, 48(R29)
   686  	MOVV	R7, 56(R29)
   687  	MOVV	R8, 64(R29)
   688  	MOVV	R9, 72(R29)
   689  	MOVV	R10, 80(R29)
   690  	MOVV	R11, 88(R29)
   691  	MOVV	R12, 96(R29)
   692  	MOVV	R13, 104(R29)
   693  	MOVV	R14, 112(R29)
   694  	MOVV	R15, 120(R29)
   695  	MOVV	R16, 128(R29)
   696  	MOVV	R17, 136(R29)
   697  	MOVV	R18, 144(R29)
   698  	MOVV	R19, 152(R29)
   699  	// R20 already saved
   700  	// R21 already saved.
   701  	MOVV	R22, 160(R29)
   702  	// R23 is tmp register.
   703  	MOVV	R24, 168(R29)
   704  	MOVV	R25, 176(R29)
   705  	// R26 is reserved by kernel.
   706  	// R27 is reserved by kernel.
   707  	// R28 is REGSB (not modified by Go code).
   708  	// R29 is SP.
   709  	// R30 is g.
   710  	// R31 is LR, which was saved by the prologue.
   711  
   712  	// This takes arguments R20 and R21.
   713  	CALL	runtime·wbBufFlush(SB)
   714  
   715  	MOVV	8(R29), R20
   716  	MOVV	16(R29), R21
   717  	MOVV	24(R29), R3
   718  	MOVV	32(R29), R4
   719  	MOVV	40(R29), R5
   720  	MOVV	48(R29), R6
   721  	MOVV	56(R29), R7
   722  	MOVV	64(R29), R8
   723  	MOVV	72(R29), R9
   724  	MOVV	80(R29), R10
   725  	MOVV	88(R29), R11
   726  	MOVV	96(R29), R12
   727  	MOVV	104(R29), R13
   728  	MOVV	112(R29), R14
   729  	MOVV	120(R29), R15
   730  	MOVV	128(R29), R16
   731  	MOVV	136(R29), R17
   732  	MOVV	144(R29), R18
   733  	MOVV	152(R29), R19
   734  	MOVV	160(R29), R22
   735  	MOVV	168(R29), R24
   736  	MOVV	176(R29), R25
   737  	JMP	ret
   738  
   739  // Note: these functions use a special calling convention to save generated code space.
   740  // Arguments are passed in registers, but the space for those arguments are allocated
   741  // in the caller's stack frame. These stubs write the args into that stack space and
   742  // then tail call to the corresponding runtime handler.
   743  // The tail call makes these stubs disappear in backtraces.
   744  TEXT runtime·panicIndex(SB),NOSPLIT,$0-16
   745  	MOVV	R1, x+0(FP)
   746  	MOVV	R2, y+8(FP)
   747  	JMP	runtime·goPanicIndex(SB)
   748  TEXT runtime·panicIndexU(SB),NOSPLIT,$0-16
   749  	MOVV	R1, x+0(FP)
   750  	MOVV	R2, y+8(FP)
   751  	JMP	runtime·goPanicIndexU(SB)
   752  TEXT runtime·panicSliceAlen(SB),NOSPLIT,$0-16
   753  	MOVV	R2, x+0(FP)
   754  	MOVV	R3, y+8(FP)
   755  	JMP	runtime·goPanicSliceAlen(SB)
   756  TEXT runtime·panicSliceAlenU(SB),NOSPLIT,$0-16
   757  	MOVV	R2, x+0(FP)
   758  	MOVV	R3, y+8(FP)
   759  	JMP	runtime·goPanicSliceAlenU(SB)
   760  TEXT runtime·panicSliceAcap(SB),NOSPLIT,$0-16
   761  	MOVV	R2, x+0(FP)
   762  	MOVV	R3, y+8(FP)
   763  	JMP	runtime·goPanicSliceAcap(SB)
   764  TEXT runtime·panicSliceAcapU(SB),NOSPLIT,$0-16
   765  	MOVV	R2, x+0(FP)
   766  	MOVV	R3, y+8(FP)
   767  	JMP	runtime·goPanicSliceAcapU(SB)
   768  TEXT runtime·panicSliceB(SB),NOSPLIT,$0-16
   769  	MOVV	R1, x+0(FP)
   770  	MOVV	R2, y+8(FP)
   771  	JMP	runtime·goPanicSliceB(SB)
   772  TEXT runtime·panicSliceBU(SB),NOSPLIT,$0-16
   773  	MOVV	R1, x+0(FP)
   774  	MOVV	R2, y+8(FP)
   775  	JMP	runtime·goPanicSliceBU(SB)
   776  TEXT runtime·panicSlice3Alen(SB),NOSPLIT,$0-16
   777  	MOVV	R3, x+0(FP)
   778  	MOVV	R4, y+8(FP)
   779  	JMP	runtime·goPanicSlice3Alen(SB)
   780  TEXT runtime·panicSlice3AlenU(SB),NOSPLIT,$0-16
   781  	MOVV	R3, x+0(FP)
   782  	MOVV	R4, y+8(FP)
   783  	JMP	runtime·goPanicSlice3AlenU(SB)
   784  TEXT runtime·panicSlice3Acap(SB),NOSPLIT,$0-16
   785  	MOVV	R3, x+0(FP)
   786  	MOVV	R4, y+8(FP)
   787  	JMP	runtime·goPanicSlice3Acap(SB)
   788  TEXT runtime·panicSlice3AcapU(SB),NOSPLIT,$0-16
   789  	MOVV	R3, x+0(FP)
   790  	MOVV	R4, y+8(FP)
   791  	JMP	runtime·goPanicSlice3AcapU(SB)
   792  TEXT runtime·panicSlice3B(SB),NOSPLIT,$0-16
   793  	MOVV	R2, x+0(FP)
   794  	MOVV	R3, y+8(FP)
   795  	JMP	runtime·goPanicSlice3B(SB)
   796  TEXT runtime·panicSlice3BU(SB),NOSPLIT,$0-16
   797  	MOVV	R2, x+0(FP)
   798  	MOVV	R3, y+8(FP)
   799  	JMP	runtime·goPanicSlice3BU(SB)
   800  TEXT runtime·panicSlice3C(SB),NOSPLIT,$0-16
   801  	MOVV	R1, x+0(FP)
   802  	MOVV	R2, y+8(FP)
   803  	JMP	runtime·goPanicSlice3C(SB)
   804  TEXT runtime·panicSlice3CU(SB),NOSPLIT,$0-16
   805  	MOVV	R1, x+0(FP)
   806  	MOVV	R2, y+8(FP)
   807  	JMP	runtime·goPanicSlice3CU(SB)