Black Lives Matter. Support the Equal Justice Initiative.

Text file src/runtime/asm_mipsx.s

Documentation: runtime

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

View as plain text