Text file src/runtime/asm_mipsx.s

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

View as plain text