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  	// Load m and g from thread-local storage.
   463  	MOVB	runtime·iscgo(SB), R1
   464  	BEQ	R1, nocgo
   465  	JAL	runtime·load_g(SB)
   466  nocgo:
   467  
   468  	// If g is nil, Go did not create the current thread.
   469  	// Call needm to obtain one for temporary use.
   470  	// In this case, we're running on the thread stack, so there's
   471  	// lots of space, but the linker doesn't know. Hide the call from
   472  	// the linker analysis by using an indirect call.
   473  	BEQ	g, needm
   474  
   475  	MOVW	g_m(g), R3
   476  	MOVW	R3, savedm-4(SP)
   477  	JMP	havem
   478  
   479  needm:
   480  	MOVW	g, savedm-4(SP) // g is zero, so is m.
   481  	MOVW	$runtime·needm(SB), R4
   482  	JAL	(R4)
   483  
   484  	// Set m->sched.sp = SP, so that if a panic happens
   485  	// during the function we are about to execute, it will
   486  	// have a valid SP to run on the g0 stack.
   487  	// The next few lines (after the havem label)
   488  	// will save this SP onto the stack and then write
   489  	// the same SP back to m->sched.sp. That seems redundant,
   490  	// but if an unrecovered panic happens, unwindm will
   491  	// restore the g->sched.sp from the stack location
   492  	// and then systemstack will try to use it. If we don't set it here,
   493  	// that restored SP will be uninitialized (typically 0) and
   494  	// will not be usable.
   495  	MOVW	g_m(g), R3
   496  	MOVW	m_g0(R3), R1
   497  	MOVW	R29, (g_sched+gobuf_sp)(R1)
   498  
   499  havem:
   500  	// Now there's a valid m, and we're running on its m->g0.
   501  	// Save current m->g0->sched.sp on stack and then set it to SP.
   502  	// Save current sp in m->g0->sched.sp in preparation for
   503  	// switch back to m->curg stack.
   504  	// NOTE: unwindm knows that the saved g->sched.sp is at 4(R29) aka savedsp-8(SP).
   505  	MOVW	m_g0(R3), R1
   506  	MOVW	(g_sched+gobuf_sp)(R1), R2
   507  	MOVW	R2, savedsp-12(SP)	// must match frame size
   508  	MOVW	R29, (g_sched+gobuf_sp)(R1)
   509  
   510  	// Switch to m->curg stack and call runtime.cgocallbackg.
   511  	// Because we are taking over the execution of m->curg
   512  	// but *not* resuming what had been running, we need to
   513  	// save that information (m->curg->sched) so we can restore it.
   514  	// We can restore m->curg->sched.sp easily, because calling
   515  	// runtime.cgocallbackg leaves SP unchanged upon return.
   516  	// To save m->curg->sched.pc, we push it onto the curg stack and
   517  	// open a frame the same size as cgocallback's g0 frame.
   518  	// Once we switch to the curg stack, the pushed PC will appear
   519  	// to be the return PC of cgocallback, so that the traceback
   520  	// will seamlessly trace back into the earlier calls.
   521  	MOVW	m_curg(R3), g
   522  	JAL	runtime·save_g(SB)
   523  	MOVW	(g_sched+gobuf_sp)(g), R2 // prepare stack as R2
   524  	MOVW	(g_sched+gobuf_pc)(g), R4
   525  	MOVW	R4, -(12+4)(R2)	// "saved LR"; must match frame size
   526  	// Gather our arguments into registers.
   527  	MOVW	fn+0(FP), R5
   528  	MOVW	frame+4(FP), R6
   529  	MOVW	ctxt+8(FP), R7
   530  	MOVW	$-(12+4)(R2), R29	// switch stack; must match frame size
   531  	MOVW	R5, 4(R29)
   532  	MOVW	R6, 8(R29)
   533  	MOVW	R7, 12(R29)
   534  	JAL	runtime·cgocallbackg(SB)
   535  
   536  	// Restore g->sched (== m->curg->sched) from saved values.
   537  	MOVW	0(R29), R4
   538  	MOVW	R4, (g_sched+gobuf_pc)(g)
   539  	MOVW	$(12+4)(R29), R2	// must match frame size
   540  	MOVW	R2, (g_sched+gobuf_sp)(g)
   541  
   542  	// Switch back to m->g0's stack and restore m->g0->sched.sp.
   543  	// (Unlike m->curg, the g0 goroutine never uses sched.pc,
   544  	// so we do not have to restore it.)
   545  	MOVW	g_m(g), R3
   546  	MOVW	m_g0(R3), g
   547  	JAL	runtime·save_g(SB)
   548  	MOVW	(g_sched+gobuf_sp)(g), R29
   549  	MOVW	savedsp-12(SP), R2	// must match frame size
   550  	MOVW	R2, (g_sched+gobuf_sp)(g)
   551  
   552  	// If the m on entry was nil, we called needm above to borrow an m
   553  	// for the duration of the call. Since the call is over, return it with dropm.
   554  	MOVW	savedm-4(SP), R3
   555  	BNE	R3, droppedm
   556  	MOVW	$runtime·dropm(SB), R4
   557  	JAL	(R4)
   558  droppedm:
   559  
   560  	// Done!
   561  	RET
   562  
   563  // void setg(G*); set g. for use by needm.
   564  // This only happens if iscgo, so jump straight to save_g
   565  TEXT runtime·setg(SB),NOSPLIT,$0-4
   566  	MOVW	gg+0(FP), g
   567  	JAL	runtime·save_g(SB)
   568  	RET
   569  
   570  // void setg_gcc(G*); set g in C TLS.
   571  // Must obey the gcc calling convention.
   572  TEXT setg_gcc<>(SB),NOSPLIT,$0
   573  	MOVW	R4, g
   574  	JAL	runtime·save_g(SB)
   575  	RET
   576  
   577  TEXT runtime·abort(SB),NOSPLIT,$0-0
   578  	UNDEF
   579  
   580  // AES hashing not implemented for mips
   581  TEXT runtime·memhash(SB),NOSPLIT|NOFRAME,$0-16
   582  	JMP	runtime·memhashFallback(SB)
   583  TEXT runtime·strhash(SB),NOSPLIT|NOFRAME,$0-12
   584  	JMP	runtime·strhashFallback(SB)
   585  TEXT runtime·memhash32(SB),NOSPLIT|NOFRAME,$0-12
   586  	JMP	runtime·memhash32Fallback(SB)
   587  TEXT runtime·memhash64(SB),NOSPLIT|NOFRAME,$0-12
   588  	JMP	runtime·memhash64Fallback(SB)
   589  
   590  TEXT runtime·return0(SB),NOSPLIT,$0
   591  	MOVW	$0, R1
   592  	RET
   593  
   594  // Called from cgo wrappers, this function returns g->m->curg.stack.hi.
   595  // Must obey the gcc calling convention.
   596  TEXT _cgo_topofstack(SB),NOSPLIT|NOFRAME,$0
   597  	// g (R30), R3 and REGTMP (R23) might be clobbered by load_g. R30 and R23
   598  	// are callee-save in the gcc calling convention, so save them.
   599  	MOVW	R23, R8
   600  	MOVW	g, R9
   601  	MOVW	R31, R10 // this call frame does not save LR
   602  
   603  	JAL	runtime·load_g(SB)
   604  	MOVW	g_m(g), R1
   605  	MOVW	m_curg(R1), R1
   606  	MOVW	(g_stack+stack_hi)(R1), R2 // return value in R2
   607  
   608  	MOVW	R8, R23
   609  	MOVW	R9, g
   610  	MOVW	R10, R31
   611  
   612  	RET
   613  
   614  // The top-most function running on a goroutine
   615  // returns to goexit+PCQuantum.
   616  TEXT runtime·goexit(SB),NOSPLIT|NOFRAME|TOPFRAME,$0-0
   617  	NOR	R0, R0	// NOP
   618  	JAL	runtime·goexit1(SB)	// does not return
   619  	// traceback from goexit1 must hit code range of goexit
   620  	NOR	R0, R0	// NOP
   621  
   622  TEXT ·checkASM(SB),NOSPLIT,$0-1
   623  	MOVW	$1, R1
   624  	MOVB	R1, ret+0(FP)
   625  	RET
   626  
   627  // gcWriteBarrier performs a heap pointer write and informs the GC.
   628  //
   629  // gcWriteBarrier does NOT follow the Go ABI. It takes two arguments:
   630  // - R20 is the destination of the write
   631  // - R21 is the value being written at R20.
   632  // It clobbers R23 (the linker temp register).
   633  // The act of CALLing gcWriteBarrier will clobber R31 (LR).
   634  // It does not clobber any other general-purpose registers,
   635  // but may clobber others (e.g., floating point registers).
   636  TEXT runtime·gcWriteBarrier(SB),NOSPLIT,$104
   637  	// Save the registers clobbered by the fast path.
   638  	MOVW	R1, 100(R29)
   639  	MOVW	R2, 104(R29)
   640  	MOVW	g_m(g), R1
   641  	MOVW	m_p(R1), R1
   642  	MOVW	(p_wbBuf+wbBuf_next)(R1), R2
   643  	// Increment wbBuf.next position.
   644  	ADD	$8, R2
   645  	MOVW	R2, (p_wbBuf+wbBuf_next)(R1)
   646  	MOVW	(p_wbBuf+wbBuf_end)(R1), R1
   647  	MOVW	R1, R23		// R23 is linker temp register
   648  	// Record the write.
   649  	MOVW	R21, -8(R2)	// Record value
   650  	MOVW	(R20), R1	// TODO: This turns bad writes into bad reads.
   651  	MOVW	R1, -4(R2)	// Record *slot
   652  	// Is the buffer full?
   653  	BEQ	R2, R23, flush
   654  ret:
   655  	MOVW	100(R29), R1
   656  	MOVW	104(R29), R2
   657  	// Do the write.
   658  	MOVW	R21, (R20)
   659  	RET
   660  
   661  flush:
   662  	// Save all general purpose registers since these could be
   663  	// clobbered by wbBufFlush and were not saved by the caller.
   664  	MOVW	R20, 4(R29)	// Also first argument to wbBufFlush
   665  	MOVW	R21, 8(R29)	// Also second argument to wbBufFlush
   666  	// R1 already saved
   667  	// R2 already saved
   668  	MOVW	R3, 12(R29)
   669  	MOVW	R4, 16(R29)
   670  	MOVW	R5, 20(R29)
   671  	MOVW	R6, 24(R29)
   672  	MOVW	R7, 28(R29)
   673  	MOVW	R8, 32(R29)
   674  	MOVW	R9, 36(R29)
   675  	MOVW	R10, 40(R29)
   676  	MOVW	R11, 44(R29)
   677  	MOVW	R12, 48(R29)
   678  	MOVW	R13, 52(R29)
   679  	MOVW	R14, 56(R29)
   680  	MOVW	R15, 60(R29)
   681  	MOVW	R16, 64(R29)
   682  	MOVW	R17, 68(R29)
   683  	MOVW	R18, 72(R29)
   684  	MOVW	R19, 76(R29)
   685  	MOVW	R20, 80(R29)
   686  	// R21 already saved
   687  	// R22 already saved.
   688  	MOVW	R22, 84(R29)
   689  	// R23 is tmp register.
   690  	MOVW	R24, 88(R29)
   691  	MOVW	R25, 92(R29)
   692  	// R26 is reserved by kernel.
   693  	// R27 is reserved by kernel.
   694  	MOVW	R28, 96(R29)
   695  	// R29 is SP.
   696  	// R30 is g.
   697  	// R31 is LR, which was saved by the prologue.
   698  
   699  	// This takes arguments R20 and R21.
   700  	CALL	runtime·wbBufFlush(SB)
   701  
   702  	MOVW	4(R29), R20
   703  	MOVW	8(R29), R21
   704  	MOVW	12(R29), R3
   705  	MOVW	16(R29), R4
   706  	MOVW	20(R29), R5
   707  	MOVW	24(R29), R6
   708  	MOVW	28(R29), R7
   709  	MOVW	32(R29), R8
   710  	MOVW	36(R29), R9
   711  	MOVW	40(R29), R10
   712  	MOVW	44(R29), R11
   713  	MOVW	48(R29), R12
   714  	MOVW	52(R29), R13
   715  	MOVW	56(R29), R14
   716  	MOVW	60(R29), R15
   717  	MOVW	64(R29), R16
   718  	MOVW	68(R29), R17
   719  	MOVW	72(R29), R18
   720  	MOVW	76(R29), R19
   721  	MOVW	80(R29), R20
   722  	MOVW	84(R29), R22
   723  	MOVW	88(R29), R24
   724  	MOVW	92(R29), R25
   725  	MOVW	96(R29), R28
   726  	JMP	ret
   727  
   728  // Note: these functions use a special calling convention to save generated code space.
   729  // Arguments are passed in registers, but the space for those arguments are allocated
   730  // in the caller's stack frame. These stubs write the args into that stack space and
   731  // then tail call to the corresponding runtime handler.
   732  // The tail call makes these stubs disappear in backtraces.
   733  TEXT runtime·panicIndex(SB),NOSPLIT,$0-8
   734  	MOVW	R1, x+0(FP)
   735  	MOVW	R2, y+4(FP)
   736  	JMP	runtime·goPanicIndex(SB)
   737  TEXT runtime·panicIndexU(SB),NOSPLIT,$0-8
   738  	MOVW	R1, x+0(FP)
   739  	MOVW	R2, y+4(FP)
   740  	JMP	runtime·goPanicIndexU(SB)
   741  TEXT runtime·panicSliceAlen(SB),NOSPLIT,$0-8
   742  	MOVW	R2, x+0(FP)
   743  	MOVW	R3, y+4(FP)
   744  	JMP	runtime·goPanicSliceAlen(SB)
   745  TEXT runtime·panicSliceAlenU(SB),NOSPLIT,$0-8
   746  	MOVW	R2, x+0(FP)
   747  	MOVW	R3, y+4(FP)
   748  	JMP	runtime·goPanicSliceAlenU(SB)
   749  TEXT runtime·panicSliceAcap(SB),NOSPLIT,$0-8
   750  	MOVW	R2, x+0(FP)
   751  	MOVW	R3, y+4(FP)
   752  	JMP	runtime·goPanicSliceAcap(SB)
   753  TEXT runtime·panicSliceAcapU(SB),NOSPLIT,$0-8
   754  	MOVW	R2, x+0(FP)
   755  	MOVW	R3, y+4(FP)
   756  	JMP	runtime·goPanicSliceAcapU(SB)
   757  TEXT runtime·panicSliceB(SB),NOSPLIT,$0-8
   758  	MOVW	R1, x+0(FP)
   759  	MOVW	R2, y+4(FP)
   760  	JMP	runtime·goPanicSliceB(SB)
   761  TEXT runtime·panicSliceBU(SB),NOSPLIT,$0-8
   762  	MOVW	R1, x+0(FP)
   763  	MOVW	R2, y+4(FP)
   764  	JMP	runtime·goPanicSliceBU(SB)
   765  TEXT runtime·panicSlice3Alen(SB),NOSPLIT,$0-8
   766  	MOVW	R3, x+0(FP)
   767  	MOVW	R4, y+4(FP)
   768  	JMP	runtime·goPanicSlice3Alen(SB)
   769  TEXT runtime·panicSlice3AlenU(SB),NOSPLIT,$0-8
   770  	MOVW	R3, x+0(FP)
   771  	MOVW	R4, y+4(FP)
   772  	JMP	runtime·goPanicSlice3AlenU(SB)
   773  TEXT runtime·panicSlice3Acap(SB),NOSPLIT,$0-8
   774  	MOVW	R3, x+0(FP)
   775  	MOVW	R4, y+4(FP)
   776  	JMP	runtime·goPanicSlice3Acap(SB)
   777  TEXT runtime·panicSlice3AcapU(SB),NOSPLIT,$0-8
   778  	MOVW	R3, x+0(FP)
   779  	MOVW	R4, y+4(FP)
   780  	JMP	runtime·goPanicSlice3AcapU(SB)
   781  TEXT runtime·panicSlice3B(SB),NOSPLIT,$0-8
   782  	MOVW	R2, x+0(FP)
   783  	MOVW	R3, y+4(FP)
   784  	JMP	runtime·goPanicSlice3B(SB)
   785  TEXT runtime·panicSlice3BU(SB),NOSPLIT,$0-8
   786  	MOVW	R2, x+0(FP)
   787  	MOVW	R3, y+4(FP)
   788  	JMP	runtime·goPanicSlice3BU(SB)
   789  TEXT runtime·panicSlice3C(SB),NOSPLIT,$0-8
   790  	MOVW	R1, x+0(FP)
   791  	MOVW	R2, y+4(FP)
   792  	JMP	runtime·goPanicSlice3C(SB)
   793  TEXT runtime·panicSlice3CU(SB),NOSPLIT,$0-8
   794  	MOVW	R1, x+0(FP)
   795  	MOVW	R2, y+4(FP)
   796  	JMP	runtime·goPanicSlice3CU(SB)
   797  TEXT runtime·panicSliceConvert(SB),NOSPLIT,$0-8
   798  	MOVW	R3, x+0(FP)
   799  	MOVW	R4, y+4(FP)
   800  	JMP	runtime·goPanicSliceConvert(SB)
   801  
   802  // Extended versions for 64-bit indexes.
   803  TEXT runtime·panicExtendIndex(SB),NOSPLIT,$0-12
   804  	MOVW	R5, hi+0(FP)
   805  	MOVW	R1, lo+4(FP)
   806  	MOVW	R2, y+8(FP)
   807  	JMP	runtime·goPanicExtendIndex(SB)
   808  TEXT runtime·panicExtendIndexU(SB),NOSPLIT,$0-12
   809  	MOVW	R5, hi+0(FP)
   810  	MOVW	R1, lo+4(FP)
   811  	MOVW	R2, y+8(FP)
   812  	JMP	runtime·goPanicExtendIndexU(SB)
   813  TEXT runtime·panicExtendSliceAlen(SB),NOSPLIT,$0-12
   814  	MOVW	R5, hi+0(FP)
   815  	MOVW	R2, lo+4(FP)
   816  	MOVW	R3, y+8(FP)
   817  	JMP	runtime·goPanicExtendSliceAlen(SB)
   818  TEXT runtime·panicExtendSliceAlenU(SB),NOSPLIT,$0-12
   819  	MOVW	R5, hi+0(FP)
   820  	MOVW	R2, lo+4(FP)
   821  	MOVW	R3, y+8(FP)
   822  	JMP	runtime·goPanicExtendSliceAlenU(SB)
   823  TEXT runtime·panicExtendSliceAcap(SB),NOSPLIT,$0-12
   824  	MOVW	R5, hi+0(FP)
   825  	MOVW	R2, lo+4(FP)
   826  	MOVW	R3, y+8(FP)
   827  	JMP	runtime·goPanicExtendSliceAcap(SB)
   828  TEXT runtime·panicExtendSliceAcapU(SB),NOSPLIT,$0-12
   829  	MOVW	R5, hi+0(FP)
   830  	MOVW	R2, lo+4(FP)
   831  	MOVW	R3, y+8(FP)
   832  	JMP	runtime·goPanicExtendSliceAcapU(SB)
   833  TEXT runtime·panicExtendSliceB(SB),NOSPLIT,$0-12
   834  	MOVW	R5, hi+0(FP)
   835  	MOVW	R1, lo+4(FP)
   836  	MOVW	R2, y+8(FP)
   837  	JMP	runtime·goPanicExtendSliceB(SB)
   838  TEXT runtime·panicExtendSliceBU(SB),NOSPLIT,$0-12
   839  	MOVW	R5, hi+0(FP)
   840  	MOVW	R1, lo+4(FP)
   841  	MOVW	R2, y+8(FP)
   842  	JMP	runtime·goPanicExtendSliceBU(SB)
   843  TEXT runtime·panicExtendSlice3Alen(SB),NOSPLIT,$0-12
   844  	MOVW	R5, hi+0(FP)
   845  	MOVW	R3, lo+4(FP)
   846  	MOVW	R4, y+8(FP)
   847  	JMP	runtime·goPanicExtendSlice3Alen(SB)
   848  TEXT runtime·panicExtendSlice3AlenU(SB),NOSPLIT,$0-12
   849  	MOVW	R5, hi+0(FP)
   850  	MOVW	R3, lo+4(FP)
   851  	MOVW	R4, y+8(FP)
   852  	JMP	runtime·goPanicExtendSlice3AlenU(SB)
   853  TEXT runtime·panicExtendSlice3Acap(SB),NOSPLIT,$0-12
   854  	MOVW	R5, hi+0(FP)
   855  	MOVW	R3, lo+4(FP)
   856  	MOVW	R4, y+8(FP)
   857  	JMP	runtime·goPanicExtendSlice3Acap(SB)
   858  TEXT runtime·panicExtendSlice3AcapU(SB),NOSPLIT,$0-12
   859  	MOVW	R5, hi+0(FP)
   860  	MOVW	R3, lo+4(FP)
   861  	MOVW	R4, y+8(FP)
   862  	JMP	runtime·goPanicExtendSlice3AcapU(SB)
   863  TEXT runtime·panicExtendSlice3B(SB),NOSPLIT,$0-12
   864  	MOVW	R5, hi+0(FP)
   865  	MOVW	R2, lo+4(FP)
   866  	MOVW	R3, y+8(FP)
   867  	JMP	runtime·goPanicExtendSlice3B(SB)
   868  TEXT runtime·panicExtendSlice3BU(SB),NOSPLIT,$0-12
   869  	MOVW	R5, hi+0(FP)
   870  	MOVW	R2, lo+4(FP)
   871  	MOVW	R3, y+8(FP)
   872  	JMP	runtime·goPanicExtendSlice3BU(SB)
   873  TEXT runtime·panicExtendSlice3C(SB),NOSPLIT,$0-12
   874  	MOVW	R5, hi+0(FP)
   875  	MOVW	R1, lo+4(FP)
   876  	MOVW	R2, y+8(FP)
   877  	JMP	runtime·goPanicExtendSlice3C(SB)
   878  TEXT runtime·panicExtendSlice3CU(SB),NOSPLIT,$0-12
   879  	MOVW	R5, hi+0(FP)
   880  	MOVW	R1, lo+4(FP)
   881  	MOVW	R2, y+8(FP)
   882  	JMP	runtime·goPanicExtendSlice3CU(SB)
   883  

View as plain text