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

View as plain text