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