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