Black Lives Matter. Support the Equal Justice Initiative.

Text file src/runtime/asm_mips64x.s

Documentation: runtime

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

View as plain text