github.com/x04/go/src@v0.0.0-20200202162449-3d481ceb3525/runtime/asm_mipsx.s (about)

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