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

View as plain text