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