github.com/lzhfromustc/gofuzz@v0.0.0-20211116160056-151b3108bbd1/runtime/asm_mipsx.s (about)

     1  // Copyright 2016 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 mips mipsle
     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  	ADDU	$-12, R29
    18  	MOVW	R4, 4(R29)	// argc
    19  	MOVW	R5, 8(R29)	// argv
    20  
    21  	// create istack out of the given (operating system) stack.
    22  	// _cgo_init may update stackguard.
    23  	MOVW	$runtime·g0(SB), g
    24  	MOVW	$(-64*1024), R23
    25  	ADD	R23, R29, R1
    26  	MOVW	R1, g_stackguard0(g)
    27  	MOVW	R1, g_stackguard1(g)
    28  	MOVW	R1, (g_stack+stack_lo)(g)
    29  	MOVW	R29, (g_stack+stack_hi)(g)
    30  
    31  	// if there is a _cgo_init, call it using the gcc ABI.
    32  	MOVW	_cgo_init(SB), R25
    33  	BEQ	R25, nocgo
    34  	ADDU	$-16, R29
    35  	MOVW	R0, R7	// arg 3: not used
    36  	MOVW	R0, R6	// arg 2: not used
    37  	MOVW	$setg_gcc<>(SB), R5	// arg 1: setg
    38  	MOVW	g, R4	// arg 0: G
    39  	JAL	(R25)
    40  	ADDU	$16, R29
    41  
    42  nocgo:
    43  	// update stackguard after _cgo_init
    44  	MOVW	(g_stack+stack_lo)(g), R1
    45  	ADD	$const__StackGuard, R1
    46  	MOVW	R1, g_stackguard0(g)
    47  	MOVW	R1, g_stackguard1(g)
    48  
    49  	// set the per-goroutine and per-mach "registers"
    50  	MOVW	$runtime·m0(SB), R1
    51  
    52  	// save m->g0 = g0
    53  	MOVW	g, m_g0(R1)
    54  	// save m0 to g0->m
    55  	MOVW	R1, g_m(g)
    56  
    57  	JAL	runtime·check(SB)
    58  
    59  	// args are already prepared
    60  	JAL	runtime·args(SB)
    61  	JAL	runtime·osinit(SB)
    62  	JAL	runtime·schedinit(SB)
    63  
    64  	// create a new goroutine to start program
    65  	MOVW	$runtime·mainPC(SB), R1	// entry
    66  	ADDU	$-12, R29
    67  	MOVW	R1, 8(R29)
    68  	MOVW	R0, 4(R29)
    69  	MOVW	R0, 0(R29)
    70  	JAL	runtime·newproc(SB)
    71  	ADDU	$12, R29
    72  
    73  	// start this M
    74  	JAL	runtime·mstart(SB)
    75  
    76  	UNDEF
    77  	RET
    78  
    79  DATA	runtime·mainPC+0(SB)/4,$runtime·main(SB)
    80  GLOBL	runtime·mainPC(SB),RODATA,$4
    81  
    82  TEXT runtime·breakpoint(SB),NOSPLIT,$0-0
    83  	BREAK
    84  	RET
    85  
    86  TEXT runtime·asminit(SB),NOSPLIT,$0-0
    87  	RET
    88  
    89  /*
    90   *  go-routine
    91   */
    92  
    93  // void gosave(Gobuf*)
    94  // save state in Gobuf; setjmp
    95  TEXT runtime·gosave(SB),NOSPLIT|NOFRAME,$0-4
    96  	MOVW	buf+0(FP), R1
    97  	MOVW	R29, gobuf_sp(R1)
    98  	MOVW	R31, gobuf_pc(R1)
    99  	MOVW	g, gobuf_g(R1)
   100  	MOVW	R0, gobuf_lr(R1)
   101  	MOVW	R0, gobuf_ret(R1)
   102  	// Assert ctxt is zero. See func save.
   103  	MOVW	gobuf_ctxt(R1), R1
   104  	BEQ	R1, 2(PC)
   105  	JAL	runtime·badctxt(SB)
   106  	RET
   107  
   108  // void gogo(Gobuf*)
   109  // restore state from Gobuf; longjmp
   110  TEXT runtime·gogo(SB),NOSPLIT,$8-4
   111  	MOVW	buf+0(FP), R3
   112  	MOVW	gobuf_g(R3), g	// make sure g is not nil
   113  	JAL	runtime·save_g(SB)
   114  
   115  	MOVW	0(g), R2
   116  	MOVW	gobuf_sp(R3), R29
   117  	MOVW	gobuf_lr(R3), R31
   118  	MOVW	gobuf_ret(R3), R1
   119  	MOVW	gobuf_ctxt(R3), REGCTXT
   120  	MOVW	R0, gobuf_sp(R3)
   121  	MOVW	R0, gobuf_ret(R3)
   122  	MOVW	R0, gobuf_lr(R3)
   123  	MOVW	R0, gobuf_ctxt(R3)
   124  	MOVW	gobuf_pc(R3), R4
   125  	JMP	(R4)
   126  
   127  // void mcall(fn func(*g))
   128  // Switch to m->g0's stack, call fn(g).
   129  // Fn must never return. It should gogo(&g->sched)
   130  // to keep running g.
   131  TEXT runtime·mcall(SB),NOSPLIT|NOFRAME,$0-4
   132  	// Save caller state in g->sched
   133  	MOVW	R29, (g_sched+gobuf_sp)(g)
   134  	MOVW	R31, (g_sched+gobuf_pc)(g)
   135  	MOVW	R0, (g_sched+gobuf_lr)(g)
   136  	MOVW	g, (g_sched+gobuf_g)(g)
   137  
   138  	// Switch to m->g0 & its stack, call fn.
   139  	MOVW	g, R1
   140  	MOVW	g_m(g), R3
   141  	MOVW	m_g0(R3), g
   142  	JAL	runtime·save_g(SB)
   143  	BNE	g, R1, 2(PC)
   144  	JMP	runtime·badmcall(SB)
   145  	MOVW	fn+0(FP), REGCTXT	// context
   146  	MOVW	0(REGCTXT), R4	// code pointer
   147  	MOVW	(g_sched+gobuf_sp)(g), R29	// sp = m->g0->sched.sp
   148  	ADDU	$-8, R29	// make room for 1 arg and fake LR
   149  	MOVW	R1, 4(R29)
   150  	MOVW	R0, 0(R29)
   151  	JAL	(R4)
   152  	JMP	runtime·badmcall2(SB)
   153  
   154  // systemstack_switch is a dummy routine that systemstack leaves at the bottom
   155  // of the G stack.  We need to distinguish the routine that
   156  // lives at the bottom of the G stack from the one that lives
   157  // at the top of the system stack because the one at the top of
   158  // the system stack terminates the stack walk (see topofstack()).
   159  TEXT runtime·systemstack_switch(SB),NOSPLIT,$0-0
   160  	UNDEF
   161  	JAL	(R31)	// make sure this function is not leaf
   162  	RET
   163  
   164  // func systemstack(fn func())
   165  TEXT runtime·systemstack(SB),NOSPLIT,$0-4
   166  	MOVW	fn+0(FP), R1	// R1 = fn
   167  	MOVW	R1, REGCTXT	// context
   168  	MOVW	g_m(g), R2	// R2 = m
   169  
   170  	MOVW	m_gsignal(R2), R3	// R3 = gsignal
   171  	BEQ	g, R3, noswitch
   172  
   173  	MOVW	m_g0(R2), R3	// R3 = g0
   174  	BEQ	g, R3, noswitch
   175  
   176  	MOVW	m_curg(R2), R4
   177  	BEQ	g, R4, switch
   178  
   179  	// Bad: g is not gsignal, not g0, not curg. What is it?
   180  	// Hide call from linker nosplit analysis.
   181  	MOVW	$runtime·badsystemstack(SB), R4
   182  	JAL	(R4)
   183  	JAL	runtime·abort(SB)
   184  
   185  switch:
   186  	// save our state in g->sched.  Pretend to
   187  	// be systemstack_switch if the G stack is scanned.
   188  	MOVW	$runtime·systemstack_switch(SB), R4
   189  	ADDU	$8, R4	// get past prologue
   190  	MOVW	R4, (g_sched+gobuf_pc)(g)
   191  	MOVW	R29, (g_sched+gobuf_sp)(g)
   192  	MOVW	R0, (g_sched+gobuf_lr)(g)
   193  	MOVW	g, (g_sched+gobuf_g)(g)
   194  
   195  	// switch to g0
   196  	MOVW	R3, g
   197  	JAL	runtime·save_g(SB)
   198  	MOVW	(g_sched+gobuf_sp)(g), R1
   199  	// make it look like mstart called systemstack on g0, to stop traceback
   200  	ADDU	$-4, R1
   201  	MOVW	$runtime·mstart(SB), R2
   202  	MOVW	R2, 0(R1)
   203  	MOVW	R1, R29
   204  
   205  	// call target function
   206  	MOVW	0(REGCTXT), R4	// code pointer
   207  	JAL	(R4)
   208  
   209  	// switch back to g
   210  	MOVW	g_m(g), R1
   211  	MOVW	m_curg(R1), g
   212  	JAL	runtime·save_g(SB)
   213  	MOVW	(g_sched+gobuf_sp)(g), R29
   214  	MOVW	R0, (g_sched+gobuf_sp)(g)
   215  	RET
   216  
   217  noswitch:
   218  	// already on m stack, just call directly
   219  	// Using a tail call here cleans up tracebacks since we won't stop
   220  	// at an intermediate systemstack.
   221  	MOVW	0(REGCTXT), R4	// code pointer
   222  	MOVW	0(R29), R31	// restore LR
   223  	ADD	$4, R29
   224  	JMP	(R4)
   225  
   226  /*
   227   * support for morestack
   228   */
   229  
   230  // Called during function prolog when more stack is needed.
   231  // Caller has already loaded:
   232  // R1: framesize, R2: argsize, R3: LR
   233  //
   234  // The traceback routines see morestack on a g0 as being
   235  // the top of a stack (for example, morestack calling newstack
   236  // calling the scheduler calling newm calling gc), so we must
   237  // record an argument size. For that purpose, it has no arguments.
   238  TEXT runtime·morestack(SB),NOSPLIT|NOFRAME,$0-0
   239  	// Cannot grow scheduler stack (m->g0).
   240  	MOVW	g_m(g), R7
   241  	MOVW	m_g0(R7), R8
   242  	BNE	g, R8, 3(PC)
   243  	JAL	runtime·badmorestackg0(SB)
   244  	JAL	runtime·abort(SB)
   245  
   246  	// Cannot grow signal stack (m->gsignal).
   247  	MOVW	m_gsignal(R7), R8
   248  	BNE	g, R8, 3(PC)
   249  	JAL	runtime·badmorestackgsignal(SB)
   250  	JAL	runtime·abort(SB)
   251  
   252  	// Called from f.
   253  	// Set g->sched to context in f.
   254  	MOVW	R29, (g_sched+gobuf_sp)(g)
   255  	MOVW	R31, (g_sched+gobuf_pc)(g)
   256  	MOVW	R3, (g_sched+gobuf_lr)(g)
   257  	MOVW	REGCTXT, (g_sched+gobuf_ctxt)(g)
   258  
   259  	// Called from f.
   260  	// Set m->morebuf to f's caller.
   261  	MOVW	R3, (m_morebuf+gobuf_pc)(R7)	// f's caller's PC
   262  	MOVW	R29, (m_morebuf+gobuf_sp)(R7)	// f's caller's SP
   263  	MOVW	g, (m_morebuf+gobuf_g)(R7)
   264  
   265  	// Call newstack on m->g0's stack.
   266  	MOVW	m_g0(R7), g
   267  	JAL	runtime·save_g(SB)
   268  	MOVW	(g_sched+gobuf_sp)(g), R29
   269  	// Create a stack frame on g0 to call newstack.
   270  	MOVW	R0, -4(R29)	// Zero saved LR in frame
   271  	ADDU	$-4, R29
   272  	JAL	runtime·newstack(SB)
   273  
   274  	// Not reached, but make sure the return PC from the call to newstack
   275  	// is still in this function, and not the beginning of the next.
   276  	UNDEF
   277  
   278  TEXT runtime·morestack_noctxt(SB),NOSPLIT,$0-0
   279  	MOVW	R0, REGCTXT
   280  	JMP	runtime·morestack(SB)
   281  
   282  // reflectcall: call a function with the given argument list
   283  // func call(argtype *_type, f *FuncVal, arg *byte, argsize, retoffset uint32).
   284  // we don't have variable-sized frames, so we use a small number
   285  // of constant-sized-frame functions to encode a few bits of size in the pc.
   286  
   287  #define DISPATCH(NAME,MAXSIZE)	\
   288  	MOVW	$MAXSIZE, R23;	\
   289  	SGTU	R1, R23, R23;	\
   290  	BNE	R23, 3(PC);	\
   291  	MOVW	$NAME(SB), R4;	\
   292  	JMP	(R4)
   293  
   294  TEXT ·reflectcall(SB),NOSPLIT|NOFRAME,$0-20
   295  	MOVW	argsize+12(FP), R1
   296  
   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  	MOVW	$runtime·badreflectcall(SB), R4
   325  	JMP	(R4)
   326  
   327  #define CALLFN(NAME,MAXSIZE)	\
   328  TEXT NAME(SB),WRAPPER,$MAXSIZE-20;	\
   329  	NO_LOCAL_POINTERS;	\
   330  	/* copy arguments to stack */		\
   331  	MOVW	arg+8(FP), R1;	\
   332  	MOVW	argsize+12(FP), R2;	\
   333  	MOVW	R29, R3;	\
   334  	ADDU	$4, R3;	\
   335  	ADDU	R3, R2;	\
   336  	BEQ	R3, R2, 6(PC);	\
   337  	MOVBU	(R1), R4;	\
   338  	ADDU	$1, R1;	\
   339  	MOVBU	R4, (R3);	\
   340  	ADDU	$1, R3;	\
   341  	JMP	-5(PC);	\
   342  	/* call function */			\
   343  	MOVW	f+4(FP), REGCTXT;	\
   344  	MOVW	(REGCTXT), R4;	\
   345  	PCDATA	$PCDATA_StackMapIndex, $0;	\
   346  	JAL	(R4);	\
   347  	/* copy return values back */		\
   348  	MOVW	argtype+0(FP), R5;	\
   349  	MOVW	arg+8(FP), R1;	\
   350  	MOVW	n+12(FP), R2;	\
   351  	MOVW	retoffset+16(FP), R4;	\
   352  	ADDU	$4, R29, R3;	\
   353  	ADDU	R4, R3;	\
   354  	ADDU	R4, R1;	\
   355  	SUBU	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, $16-0
   364  	MOVW	R5, 4(R29)
   365  	MOVW	R1, 8(R29)
   366  	MOVW	R3, 12(R29)
   367  	MOVW	R2, 16(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-4
   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,$0-8
   408  	MOVW	0(R29), R31
   409  	ADDU	$-8, R31
   410  
   411  	MOVW	fv+0(FP), REGCTXT
   412  	MOVW	argp+4(FP), R29
   413  	ADDU	$-4, R29
   414  	NOR	R0, R0	// prevent scheduling
   415  	MOVW	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  	MOVW	R31, (g_sched+gobuf_pc)(g)
   421  	MOVW	R29, (g_sched+gobuf_sp)(g)
   422  	MOVW	R0, (g_sched+gobuf_lr)(g)
   423  	MOVW	R0, (g_sched+gobuf_ret)(g)
   424  	// Assert ctxt is zero. See func save.
   425  	MOVW	(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-12
   435  	MOVW	fn+0(FP), R25
   436  	MOVW	arg+4(FP), R4
   437  
   438  	MOVW	R29, R3	// save original stack pointer
   439  	MOVW	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  	MOVW	g_m(g), R5
   445  	MOVW	m_g0(R5), R6
   446  	BEQ	R6, g, g0
   447  
   448  	JAL	gosave<>(SB)
   449  	MOVW	R6, g
   450  	JAL	runtime·save_g(SB)
   451  	MOVW	(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 and O32 frame.
   456  	ADDU	$-24, R29
   457  	AND	$~7, R29	// O32 ABI expects 8-byte aligned stack on function entry
   458  	MOVW	R2, 16(R29)	// save old g on stack
   459  	MOVW	(g_stack+stack_hi)(R2), R2
   460  	SUBU	R3, R2
   461  	MOVW	R2, 20(R29)	// save depth in old g stack (can't just save SP, as stack might be copied during a callback)
   462  	JAL	(R25)
   463  
   464  	// Restore g, stack pointer. R2 is return value.
   465  	MOVW	16(R29), g
   466  	JAL	runtime·save_g(SB)
   467  	MOVW	(g_stack+stack_hi)(g), R5
   468  	MOVW	20(R29), R6
   469  	SUBU	R6, R5
   470  	MOVW	R5, R29
   471  
   472  	MOVW	R2, ret+8(FP)
   473  	RET
   474  
   475  // cgocallback(fn, frame unsafe.Pointer, ctxt uintptr)
   476  // See cgocall.go for more details.
   477  TEXT ·cgocallback(SB),NOSPLIT,$12-12
   478  	NO_LOCAL_POINTERS
   479  
   480  	// Load m and g from thread-local storage.
   481  	MOVB	runtime·iscgo(SB), R1
   482  	BEQ	R1, nocgo
   483  	JAL	runtime·load_g(SB)
   484  nocgo:
   485  
   486  	// If g is nil, Go did not create the current thread.
   487  	// Call needm to obtain one for temporary use.
   488  	// In this case, we're running on the thread stack, so there's
   489  	// lots of space, but the linker doesn't know. Hide the call from
   490  	// the linker analysis by using an indirect call.
   491  	BEQ	g, needm
   492  
   493  	MOVW	g_m(g), R3
   494  	MOVW	R3, savedm-4(SP)
   495  	JMP	havem
   496  
   497  needm:
   498  	MOVW	g, savedm-4(SP) // g is zero, so is m.
   499  	MOVW	$runtime·needm(SB), R4
   500  	JAL	(R4)
   501  
   502  	// Set m->sched.sp = SP, so that if a panic happens
   503  	// during the function we are about to execute, it will
   504  	// have a valid SP to run on the g0 stack.
   505  	// The next few lines (after the havem label)
   506  	// will save this SP onto the stack and then write
   507  	// the same SP back to m->sched.sp. That seems redundant,
   508  	// but if an unrecovered panic happens, unwindm will
   509  	// restore the g->sched.sp from the stack location
   510  	// and then systemstack will try to use it. If we don't set it here,
   511  	// that restored SP will be uninitialized (typically 0) and
   512  	// will not be usable.
   513  	MOVW	g_m(g), R3
   514  	MOVW	m_g0(R3), R1
   515  	MOVW	R29, (g_sched+gobuf_sp)(R1)
   516  
   517  havem:
   518  	// Now there's a valid m, and we're running on its m->g0.
   519  	// Save current m->g0->sched.sp on stack and then set it to SP.
   520  	// Save current sp in m->g0->sched.sp in preparation for
   521  	// switch back to m->curg stack.
   522  	// NOTE: unwindm knows that the saved g->sched.sp is at 4(R29) aka savedsp-8(SP).
   523  	MOVW	m_g0(R3), R1
   524  	MOVW	(g_sched+gobuf_sp)(R1), R2
   525  	MOVW	R2, savedsp-12(SP)	// must match frame size
   526  	MOVW	R29, (g_sched+gobuf_sp)(R1)
   527  
   528  	// Switch to m->curg stack and call runtime.cgocallbackg.
   529  	// Because we are taking over the execution of m->curg
   530  	// but *not* resuming what had been running, we need to
   531  	// save that information (m->curg->sched) so we can restore it.
   532  	// We can restore m->curg->sched.sp easily, because calling
   533  	// runtime.cgocallbackg leaves SP unchanged upon return.
   534  	// To save m->curg->sched.pc, we push it onto the curg stack and
   535  	// open a frame the same size as cgocallback's g0 frame.
   536  	// Once we switch to the curg stack, the pushed PC will appear
   537  	// to be the return PC of cgocallback, so that the traceback
   538  	// will seamlessly trace back into the earlier calls.
   539  	MOVW	m_curg(R3), g
   540  	JAL	runtime·save_g(SB)
   541  	MOVW	(g_sched+gobuf_sp)(g), R2 // prepare stack as R2
   542  	MOVW	(g_sched+gobuf_pc)(g), R4
   543  	MOVW	R4, -(12+4)(R2)	// "saved LR"; must match frame size
   544  	// Gather our arguments into registers.
   545  	MOVW	fn+0(FP), R5
   546  	MOVW	frame+4(FP), R6
   547  	MOVW	ctxt+8(FP), R7
   548  	MOVW	$-(12+4)(R2), R29	// switch stack; must match frame size
   549  	MOVW	R5, 4(R29)
   550  	MOVW	R6, 8(R29)
   551  	MOVW	R7, 12(R29)
   552  	JAL	runtime·cgocallbackg(SB)
   553  
   554  	// Restore g->sched (== m->curg->sched) from saved values.
   555  	MOVW	0(R29), R4
   556  	MOVW	R4, (g_sched+gobuf_pc)(g)
   557  	MOVW	$(12+4)(R29), R2	// must match frame size
   558  	MOVW	R2, (g_sched+gobuf_sp)(g)
   559  
   560  	// Switch back to m->g0's stack and restore m->g0->sched.sp.
   561  	// (Unlike m->curg, the g0 goroutine never uses sched.pc,
   562  	// so we do not have to restore it.)
   563  	MOVW	g_m(g), R3
   564  	MOVW	m_g0(R3), g
   565  	JAL	runtime·save_g(SB)
   566  	MOVW	(g_sched+gobuf_sp)(g), R29
   567  	MOVW	savedsp-12(SP), R2	// must match frame size
   568  	MOVW	R2, (g_sched+gobuf_sp)(g)
   569  
   570  	// If the m on entry was nil, we called needm above to borrow an m
   571  	// for the duration of the call. Since the call is over, return it with dropm.
   572  	MOVW	savedm-4(SP), R3
   573  	BNE	R3, droppedm
   574  	MOVW	$runtime·dropm(SB), R4
   575  	JAL	(R4)
   576  droppedm:
   577  
   578  	// Done!
   579  	RET
   580  
   581  // void setg(G*); set g. for use by needm.
   582  // This only happens if iscgo, so jump straight to save_g
   583  TEXT runtime·setg(SB),NOSPLIT,$0-4
   584  	MOVW	gg+0(FP), g
   585  	JAL	runtime·save_g(SB)
   586  	RET
   587  
   588  // void setg_gcc(G*); set g in C TLS.
   589  // Must obey the gcc calling convention.
   590  TEXT setg_gcc<>(SB),NOSPLIT,$0
   591  	MOVW	R4, g
   592  	JAL	runtime·save_g(SB)
   593  	RET
   594  
   595  TEXT runtime·abort(SB),NOSPLIT,$0-0
   596  	UNDEF
   597  
   598  // AES hashing not implemented for mips
   599  TEXT runtime·memhash(SB),NOSPLIT|NOFRAME,$0-16
   600  	JMP	runtime·memhashFallback(SB)
   601  TEXT runtime·strhash(SB),NOSPLIT|NOFRAME,$0-12
   602  	JMP	runtime·strhashFallback(SB)
   603  TEXT runtime·memhash32(SB),NOSPLIT|NOFRAME,$0-12
   604  	JMP	runtime·memhash32Fallback(SB)
   605  TEXT runtime·memhash64(SB),NOSPLIT|NOFRAME,$0-12
   606  	JMP	runtime·memhash64Fallback(SB)
   607  
   608  TEXT runtime·return0(SB),NOSPLIT,$0
   609  	MOVW	$0, R1
   610  	RET
   611  
   612  // Called from cgo wrappers, this function returns g->m->curg.stack.hi.
   613  // Must obey the gcc calling convention.
   614  TEXT _cgo_topofstack(SB),NOSPLIT|NOFRAME,$0
   615  	// g (R30), R3 and REGTMP (R23) might be clobbered by load_g. R30 and R23
   616  	// are callee-save in the gcc calling convention, so save them.
   617  	MOVW	R23, R8
   618  	MOVW	g, R9
   619  	MOVW	R31, R10 // this call frame does not save LR
   620  
   621  	JAL	runtime·load_g(SB)
   622  	MOVW	g_m(g), R1
   623  	MOVW	m_curg(R1), R1
   624  	MOVW	(g_stack+stack_hi)(R1), R2 // return value in R2
   625  
   626  	MOVW	R8, R23
   627  	MOVW	R9, g
   628  	MOVW	R10, R31
   629  
   630  	RET
   631  
   632  // The top-most function running on a goroutine
   633  // returns to goexit+PCQuantum.
   634  TEXT runtime·goexit(SB),NOSPLIT|NOFRAME|TOPFRAME,$0-0
   635  	NOR	R0, R0	// NOP
   636  	JAL	runtime·goexit1(SB)	// does not return
   637  	// traceback from goexit1 must hit code range of goexit
   638  	NOR	R0, R0	// NOP
   639  
   640  TEXT ·checkASM(SB),NOSPLIT,$0-1
   641  	MOVW	$1, R1
   642  	MOVB	R1, ret+0(FP)
   643  	RET
   644  
   645  // gcWriteBarrier performs a heap pointer write and informs the GC.
   646  //
   647  // gcWriteBarrier does NOT follow the Go ABI. It takes two arguments:
   648  // - R20 is the destination of the write
   649  // - R21 is the value being written at R20.
   650  // It clobbers R23 (the linker temp register).
   651  // The act of CALLing gcWriteBarrier will clobber R31 (LR).
   652  // It does not clobber any other general-purpose registers,
   653  // but may clobber others (e.g., floating point registers).
   654  TEXT runtime·gcWriteBarrier(SB),NOSPLIT,$104
   655  	// Save the registers clobbered by the fast path.
   656  	MOVW	R1, 100(R29)
   657  	MOVW	R2, 104(R29)
   658  	MOVW	g_m(g), R1
   659  	MOVW	m_p(R1), R1
   660  	MOVW	(p_wbBuf+wbBuf_next)(R1), R2
   661  	// Increment wbBuf.next position.
   662  	ADD	$8, R2
   663  	MOVW	R2, (p_wbBuf+wbBuf_next)(R1)
   664  	MOVW	(p_wbBuf+wbBuf_end)(R1), R1
   665  	MOVW	R1, R23		// R23 is linker temp register
   666  	// Record the write.
   667  	MOVW	R21, -8(R2)	// Record value
   668  	MOVW	(R20), R1	// TODO: This turns bad writes into bad reads.
   669  	MOVW	R1, -4(R2)	// Record *slot
   670  	// Is the buffer full?
   671  	BEQ	R2, R23, flush
   672  ret:
   673  	MOVW	100(R29), R1
   674  	MOVW	104(R29), R2
   675  	// Do the write.
   676  	MOVW	R21, (R20)
   677  	RET
   678  
   679  flush:
   680  	// Save all general purpose registers since these could be
   681  	// clobbered by wbBufFlush and were not saved by the caller.
   682  	MOVW	R20, 4(R29)	// Also first argument to wbBufFlush
   683  	MOVW	R21, 8(R29)	// Also second argument to wbBufFlush
   684  	// R1 already saved
   685  	// R2 already saved
   686  	MOVW	R3, 12(R29)
   687  	MOVW	R4, 16(R29)
   688  	MOVW	R5, 20(R29)
   689  	MOVW	R6, 24(R29)
   690  	MOVW	R7, 28(R29)
   691  	MOVW	R8, 32(R29)
   692  	MOVW	R9, 36(R29)
   693  	MOVW	R10, 40(R29)
   694  	MOVW	R11, 44(R29)
   695  	MOVW	R12, 48(R29)
   696  	MOVW	R13, 52(R29)
   697  	MOVW	R14, 56(R29)
   698  	MOVW	R15, 60(R29)
   699  	MOVW	R16, 64(R29)
   700  	MOVW	R17, 68(R29)
   701  	MOVW	R18, 72(R29)
   702  	MOVW	R19, 76(R29)
   703  	MOVW	R20, 80(R29)
   704  	// R21 already saved
   705  	// R22 already saved.
   706  	MOVW	R22, 84(R29)
   707  	// R23 is tmp register.
   708  	MOVW	R24, 88(R29)
   709  	MOVW	R25, 92(R29)
   710  	// R26 is reserved by kernel.
   711  	// R27 is reserved by kernel.
   712  	MOVW	R28, 96(R29)
   713  	// R29 is SP.
   714  	// R30 is g.
   715  	// R31 is LR, which was saved by the prologue.
   716  
   717  	// This takes arguments R20 and R21.
   718  	CALL	runtime·wbBufFlush(SB)
   719  
   720  	MOVW	4(R29), R20
   721  	MOVW	8(R29), R21
   722  	MOVW	12(R29), R3
   723  	MOVW	16(R29), R4
   724  	MOVW	20(R29), R5
   725  	MOVW	24(R29), R6
   726  	MOVW	28(R29), R7
   727  	MOVW	32(R29), R8
   728  	MOVW	36(R29), R9
   729  	MOVW	40(R29), R10
   730  	MOVW	44(R29), R11
   731  	MOVW	48(R29), R12
   732  	MOVW	52(R29), R13
   733  	MOVW	56(R29), R14
   734  	MOVW	60(R29), R15
   735  	MOVW	64(R29), R16
   736  	MOVW	68(R29), R17
   737  	MOVW	72(R29), R18
   738  	MOVW	76(R29), R19
   739  	MOVW	80(R29), R20
   740  	MOVW	84(R29), R22
   741  	MOVW	88(R29), R24
   742  	MOVW	92(R29), R25
   743  	MOVW	96(R29), R28
   744  	JMP	ret
   745  
   746  // Note: these functions use a special calling convention to save generated code space.
   747  // Arguments are passed in registers, but the space for those arguments are allocated
   748  // in the caller's stack frame. These stubs write the args into that stack space and
   749  // then tail call to the corresponding runtime handler.
   750  // The tail call makes these stubs disappear in backtraces.
   751  TEXT runtime·panicIndex(SB),NOSPLIT,$0-8
   752  	MOVW	R1, x+0(FP)
   753  	MOVW	R2, y+4(FP)
   754  	JMP	runtime·goPanicIndex(SB)
   755  TEXT runtime·panicIndexU(SB),NOSPLIT,$0-8
   756  	MOVW	R1, x+0(FP)
   757  	MOVW	R2, y+4(FP)
   758  	JMP	runtime·goPanicIndexU(SB)
   759  TEXT runtime·panicSliceAlen(SB),NOSPLIT,$0-8
   760  	MOVW	R2, x+0(FP)
   761  	MOVW	R3, y+4(FP)
   762  	JMP	runtime·goPanicSliceAlen(SB)
   763  TEXT runtime·panicSliceAlenU(SB),NOSPLIT,$0-8
   764  	MOVW	R2, x+0(FP)
   765  	MOVW	R3, y+4(FP)
   766  	JMP	runtime·goPanicSliceAlenU(SB)
   767  TEXT runtime·panicSliceAcap(SB),NOSPLIT,$0-8
   768  	MOVW	R2, x+0(FP)
   769  	MOVW	R3, y+4(FP)
   770  	JMP	runtime·goPanicSliceAcap(SB)
   771  TEXT runtime·panicSliceAcapU(SB),NOSPLIT,$0-8
   772  	MOVW	R2, x+0(FP)
   773  	MOVW	R3, y+4(FP)
   774  	JMP	runtime·goPanicSliceAcapU(SB)
   775  TEXT runtime·panicSliceB(SB),NOSPLIT,$0-8
   776  	MOVW	R1, x+0(FP)
   777  	MOVW	R2, y+4(FP)
   778  	JMP	runtime·goPanicSliceB(SB)
   779  TEXT runtime·panicSliceBU(SB),NOSPLIT,$0-8
   780  	MOVW	R1, x+0(FP)
   781  	MOVW	R2, y+4(FP)
   782  	JMP	runtime·goPanicSliceBU(SB)
   783  TEXT runtime·panicSlice3Alen(SB),NOSPLIT,$0-8
   784  	MOVW	R3, x+0(FP)
   785  	MOVW	R4, y+4(FP)
   786  	JMP	runtime·goPanicSlice3Alen(SB)
   787  TEXT runtime·panicSlice3AlenU(SB),NOSPLIT,$0-8
   788  	MOVW	R3, x+0(FP)
   789  	MOVW	R4, y+4(FP)
   790  	JMP	runtime·goPanicSlice3AlenU(SB)
   791  TEXT runtime·panicSlice3Acap(SB),NOSPLIT,$0-8
   792  	MOVW	R3, x+0(FP)
   793  	MOVW	R4, y+4(FP)
   794  	JMP	runtime·goPanicSlice3Acap(SB)
   795  TEXT runtime·panicSlice3AcapU(SB),NOSPLIT,$0-8
   796  	MOVW	R3, x+0(FP)
   797  	MOVW	R4, y+4(FP)
   798  	JMP	runtime·goPanicSlice3AcapU(SB)
   799  TEXT runtime·panicSlice3B(SB),NOSPLIT,$0-8
   800  	MOVW	R2, x+0(FP)
   801  	MOVW	R3, y+4(FP)
   802  	JMP	runtime·goPanicSlice3B(SB)
   803  TEXT runtime·panicSlice3BU(SB),NOSPLIT,$0-8
   804  	MOVW	R2, x+0(FP)
   805  	MOVW	R3, y+4(FP)
   806  	JMP	runtime·goPanicSlice3BU(SB)
   807  TEXT runtime·panicSlice3C(SB),NOSPLIT,$0-8
   808  	MOVW	R1, x+0(FP)
   809  	MOVW	R2, y+4(FP)
   810  	JMP	runtime·goPanicSlice3C(SB)
   811  TEXT runtime·panicSlice3CU(SB),NOSPLIT,$0-8
   812  	MOVW	R1, x+0(FP)
   813  	MOVW	R2, y+4(FP)
   814  	JMP	runtime·goPanicSlice3CU(SB)
   815  
   816  // Extended versions for 64-bit indexes.
   817  TEXT runtime·panicExtendIndex(SB),NOSPLIT,$0-12
   818  	MOVW	R5, hi+0(FP)
   819  	MOVW	R1, lo+4(FP)
   820  	MOVW	R2, y+8(FP)
   821  	JMP	runtime·goPanicExtendIndex(SB)
   822  TEXT runtime·panicExtendIndexU(SB),NOSPLIT,$0-12
   823  	MOVW	R5, hi+0(FP)
   824  	MOVW	R1, lo+4(FP)
   825  	MOVW	R2, y+8(FP)
   826  	JMP	runtime·goPanicExtendIndexU(SB)
   827  TEXT runtime·panicExtendSliceAlen(SB),NOSPLIT,$0-12
   828  	MOVW	R5, hi+0(FP)
   829  	MOVW	R2, lo+4(FP)
   830  	MOVW	R3, y+8(FP)
   831  	JMP	runtime·goPanicExtendSliceAlen(SB)
   832  TEXT runtime·panicExtendSliceAlenU(SB),NOSPLIT,$0-12
   833  	MOVW	R5, hi+0(FP)
   834  	MOVW	R2, lo+4(FP)
   835  	MOVW	R3, y+8(FP)
   836  	JMP	runtime·goPanicExtendSliceAlenU(SB)
   837  TEXT runtime·panicExtendSliceAcap(SB),NOSPLIT,$0-12
   838  	MOVW	R5, hi+0(FP)
   839  	MOVW	R2, lo+4(FP)
   840  	MOVW	R3, y+8(FP)
   841  	JMP	runtime·goPanicExtendSliceAcap(SB)
   842  TEXT runtime·panicExtendSliceAcapU(SB),NOSPLIT,$0-12
   843  	MOVW	R5, hi+0(FP)
   844  	MOVW	R2, lo+4(FP)
   845  	MOVW	R3, y+8(FP)
   846  	JMP	runtime·goPanicExtendSliceAcapU(SB)
   847  TEXT runtime·panicExtendSliceB(SB),NOSPLIT,$0-12
   848  	MOVW	R5, hi+0(FP)
   849  	MOVW	R1, lo+4(FP)
   850  	MOVW	R2, y+8(FP)
   851  	JMP	runtime·goPanicExtendSliceB(SB)
   852  TEXT runtime·panicExtendSliceBU(SB),NOSPLIT,$0-12
   853  	MOVW	R5, hi+0(FP)
   854  	MOVW	R1, lo+4(FP)
   855  	MOVW	R2, y+8(FP)
   856  	JMP	runtime·goPanicExtendSliceBU(SB)
   857  TEXT runtime·panicExtendSlice3Alen(SB),NOSPLIT,$0-12
   858  	MOVW	R5, hi+0(FP)
   859  	MOVW	R3, lo+4(FP)
   860  	MOVW	R4, y+8(FP)
   861  	JMP	runtime·goPanicExtendSlice3Alen(SB)
   862  TEXT runtime·panicExtendSlice3AlenU(SB),NOSPLIT,$0-12
   863  	MOVW	R5, hi+0(FP)
   864  	MOVW	R3, lo+4(FP)
   865  	MOVW	R4, y+8(FP)
   866  	JMP	runtime·goPanicExtendSlice3AlenU(SB)
   867  TEXT runtime·panicExtendSlice3Acap(SB),NOSPLIT,$0-12
   868  	MOVW	R5, hi+0(FP)
   869  	MOVW	R3, lo+4(FP)
   870  	MOVW	R4, y+8(FP)
   871  	JMP	runtime·goPanicExtendSlice3Acap(SB)
   872  TEXT runtime·panicExtendSlice3AcapU(SB),NOSPLIT,$0-12
   873  	MOVW	R5, hi+0(FP)
   874  	MOVW	R3, lo+4(FP)
   875  	MOVW	R4, y+8(FP)
   876  	JMP	runtime·goPanicExtendSlice3AcapU(SB)
   877  TEXT runtime·panicExtendSlice3B(SB),NOSPLIT,$0-12
   878  	MOVW	R5, hi+0(FP)
   879  	MOVW	R2, lo+4(FP)
   880  	MOVW	R3, y+8(FP)
   881  	JMP	runtime·goPanicExtendSlice3B(SB)
   882  TEXT runtime·panicExtendSlice3BU(SB),NOSPLIT,$0-12
   883  	MOVW	R5, hi+0(FP)
   884  	MOVW	R2, lo+4(FP)
   885  	MOVW	R3, y+8(FP)
   886  	JMP	runtime·goPanicExtendSlice3BU(SB)
   887  TEXT runtime·panicExtendSlice3C(SB),NOSPLIT,$0-12
   888  	MOVW	R5, hi+0(FP)
   889  	MOVW	R1, lo+4(FP)
   890  	MOVW	R2, y+8(FP)
   891  	JMP	runtime·goPanicExtendSlice3C(SB)
   892  TEXT runtime·panicExtendSlice3CU(SB),NOSPLIT,$0-12
   893  	MOVW	R5, hi+0(FP)
   894  	MOVW	R1, lo+4(FP)
   895  	MOVW	R2, y+8(FP)
   896  	JMP	runtime·goPanicExtendSlice3CU(SB)