github.com/panjjo/go@v0.0.0-20161104043856-d62b31386338/src/runtime/asm_mips64x.s (about)

     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  // +build mips64 mips64le
     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,$0
    15  	// R29 = stack; R4 = argc; R5 = argv
    16  
    17  	ADDV	$-24, R29
    18  	MOVW	R4, 8(R29) // argc
    19  	MOVV	R5, 16(R29) // argv
    20  
    21  	// create istack out of the given (operating system) stack.
    22  	// _cgo_init may update stackguard.
    23  	MOVV	$runtime·g0(SB), g
    24  	MOVV	$(-64*1024), R23
    25  	ADDV	R23, R29, R1
    26  	MOVV	R1, g_stackguard0(g)
    27  	MOVV	R1, g_stackguard1(g)
    28  	MOVV	R1, (g_stack+stack_lo)(g)
    29  	MOVV	R29, (g_stack+stack_hi)(g)
    30  
    31  	// if there is a _cgo_init, call it using the gcc ABI.
    32  	MOVV	_cgo_init(SB), R25
    33  	BEQ	R25, nocgo
    34  
    35  	MOVV	R0, R7	// arg 3: not used
    36  	MOVV	R0, R6	// arg 2: not used
    37  	MOVV	$setg_gcc<>(SB), R5	// arg 1: setg
    38  	MOVV	g, R4	// arg 0: G
    39  	JAL	(R25)
    40  
    41  nocgo:
    42  	// update stackguard after _cgo_init
    43  	MOVV	(g_stack+stack_lo)(g), R1
    44  	ADDV	$const__StackGuard, R1
    45  	MOVV	R1, g_stackguard0(g)
    46  	MOVV	R1, g_stackguard1(g)
    47  
    48  	// set the per-goroutine and per-mach "registers"
    49  	MOVV	$runtime·m0(SB), R1
    50  
    51  	// save m->g0 = g0
    52  	MOVV	g, m_g0(R1)
    53  	// save m0 to g0->m
    54  	MOVV	R1, g_m(g)
    55  
    56  	JAL	runtime·check(SB)
    57  
    58  	// args are already prepared
    59  	JAL	runtime·args(SB)
    60  	JAL	runtime·osinit(SB)
    61  	JAL	runtime·schedinit(SB)
    62  
    63  	// create a new goroutine to start program
    64  	MOVV	$runtime·mainPC(SB), R1		// entry
    65  	ADDV	$-24, R29
    66  	MOVV	R1, 16(R29)
    67  	MOVV	R0, 8(R29)
    68  	MOVV	R0, 0(R29)
    69  	JAL	runtime·newproc(SB)
    70  	ADDV	$24, R29
    71  
    72  	// start this M
    73  	JAL	runtime·mstart(SB)
    74  
    75  	MOVV	R0, 1(R0)
    76  	RET
    77  
    78  DATA	runtime·mainPC+0(SB)/8,$runtime·main(SB)
    79  GLOBL	runtime·mainPC(SB),RODATA,$8
    80  
    81  TEXT runtime·breakpoint(SB),NOSPLIT,$-8-0
    82  	MOVV	R0, 2(R0) // TODO: TD
    83  	RET
    84  
    85  TEXT runtime·asminit(SB),NOSPLIT,$-8-0
    86  	RET
    87  
    88  /*
    89   *  go-routine
    90   */
    91  
    92  // void gosave(Gobuf*)
    93  // save state in Gobuf; setjmp
    94  TEXT runtime·gosave(SB), NOSPLIT, $-8-8
    95  	MOVV	buf+0(FP), R1
    96  	MOVV	R29, gobuf_sp(R1)
    97  	MOVV	R31, gobuf_pc(R1)
    98  	MOVV	g, gobuf_g(R1)
    99  	MOVV	R0, gobuf_lr(R1)
   100  	MOVV	R0, gobuf_ret(R1)
   101  	// Assert ctxt is zero. See func save.
   102  	MOVV	gobuf_ctxt(R1), R1
   103  	BEQ	R1, 2(PC)
   104  	JAL	runtime·badctxt(SB)
   105  	RET
   106  
   107  // void gogo(Gobuf*)
   108  // restore state from Gobuf; longjmp
   109  TEXT runtime·gogo(SB), NOSPLIT, $16-8
   110  	MOVV	buf+0(FP), R3
   111  
   112  	// If ctxt is not nil, invoke deletion barrier before overwriting.
   113  	MOVV	gobuf_ctxt(R3), R1
   114  	BEQ	R1, nilctxt
   115  	MOVV	$gobuf_ctxt(R3), R1
   116  	MOVV	R1, 8(R29)
   117  	MOVV	R0, 16(R29)
   118  	JAL	runtime·writebarrierptr_prewrite(SB)
   119  	MOVV	buf+0(FP), R3
   120  
   121  nilctxt:
   122  	MOVV	gobuf_g(R3), g	// make sure g is not nil
   123  	JAL	runtime·save_g(SB)
   124  
   125  	MOVV	0(g), R2
   126  	MOVV	gobuf_sp(R3), R29
   127  	MOVV	gobuf_lr(R3), R31
   128  	MOVV	gobuf_ret(R3), R1
   129  	MOVV	gobuf_ctxt(R3), REGCTXT
   130  	MOVV	R0, gobuf_sp(R3)
   131  	MOVV	R0, gobuf_ret(R3)
   132  	MOVV	R0, gobuf_lr(R3)
   133  	MOVV	R0, gobuf_ctxt(R3)
   134  	MOVV	gobuf_pc(R3), R4
   135  	JMP	(R4)
   136  
   137  // void mcall(fn func(*g))
   138  // Switch to m->g0's stack, call fn(g).
   139  // Fn must never return. It should gogo(&g->sched)
   140  // to keep running g.
   141  TEXT runtime·mcall(SB), NOSPLIT, $-8-8
   142  	// Save caller state in g->sched
   143  	MOVV	R29, (g_sched+gobuf_sp)(g)
   144  	MOVV	R31, (g_sched+gobuf_pc)(g)
   145  	MOVV	R0, (g_sched+gobuf_lr)(g)
   146  	MOVV	g, (g_sched+gobuf_g)(g)
   147  
   148  	// Switch to m->g0 & its stack, call fn.
   149  	MOVV	g, R1
   150  	MOVV	g_m(g), R3
   151  	MOVV	m_g0(R3), g
   152  	JAL	runtime·save_g(SB)
   153  	BNE	g, R1, 2(PC)
   154  	JMP	runtime·badmcall(SB)
   155  	MOVV	fn+0(FP), REGCTXT			// context
   156  	MOVV	0(REGCTXT), R4			// code pointer
   157  	MOVV	(g_sched+gobuf_sp)(g), R29	// sp = m->g0->sched.sp
   158  	ADDV	$-16, R29
   159  	MOVV	R1, 8(R29)
   160  	MOVV	R0, 0(R29)
   161  	JAL	(R4)
   162  	JMP	runtime·badmcall2(SB)
   163  
   164  // systemstack_switch is a dummy routine that systemstack leaves at the bottom
   165  // of the G stack. We need to distinguish the routine that
   166  // lives at the bottom of the G stack from the one that lives
   167  // at the top of the system stack because the one at the top of
   168  // the system stack terminates the stack walk (see topofstack()).
   169  TEXT runtime·systemstack_switch(SB), NOSPLIT, $0-0
   170  	UNDEF
   171  	JAL	(R31)	// make sure this function is not leaf
   172  	RET
   173  
   174  // func systemstack(fn func())
   175  TEXT runtime·systemstack(SB), NOSPLIT, $0-8
   176  	MOVV	fn+0(FP), R1	// R1 = fn
   177  	MOVV	R1, REGCTXT		// context
   178  	MOVV	g_m(g), R2	// R2 = m
   179  
   180  	MOVV	m_gsignal(R2), R3	// R3 = gsignal
   181  	BEQ	g, R3, noswitch
   182  
   183  	MOVV	m_g0(R2), R3	// R3 = g0
   184  	BEQ	g, R3, noswitch
   185  
   186  	MOVV	m_curg(R2), R4
   187  	BEQ	g, R4, switch
   188  
   189  	// Bad: g is not gsignal, not g0, not curg. What is it?
   190  	// Hide call from linker nosplit analysis.
   191  	MOVV	$runtime·badsystemstack(SB), R4
   192  	JAL	(R4)
   193  
   194  switch:
   195  	// save our state in g->sched. Pretend to
   196  	// be systemstack_switch if the G stack is scanned.
   197  	MOVV	$runtime·systemstack_switch(SB), R4
   198  	ADDV	$8, R4	// get past prologue
   199  	MOVV	R4, (g_sched+gobuf_pc)(g)
   200  	MOVV	R29, (g_sched+gobuf_sp)(g)
   201  	MOVV	R0, (g_sched+gobuf_lr)(g)
   202  	MOVV	g, (g_sched+gobuf_g)(g)
   203  
   204  	// switch to g0
   205  	MOVV	R3, g
   206  	JAL	runtime·save_g(SB)
   207  	MOVV	(g_sched+gobuf_sp)(g), R1
   208  	// make it look like mstart called systemstack on g0, to stop traceback
   209  	ADDV	$-8, R1
   210  	MOVV	$runtime·mstart(SB), R2
   211  	MOVV	R2, 0(R1)
   212  	MOVV	R1, R29
   213  
   214  	// call target function
   215  	MOVV	0(REGCTXT), R4	// code pointer
   216  	JAL	(R4)
   217  
   218  	// switch back to g
   219  	MOVV	g_m(g), R1
   220  	MOVV	m_curg(R1), g
   221  	JAL	runtime·save_g(SB)
   222  	MOVV	(g_sched+gobuf_sp)(g), R29
   223  	MOVV	R0, (g_sched+gobuf_sp)(g)
   224  	RET
   225  
   226  noswitch:
   227  	// already on m stack, just call directly
   228  	MOVV	0(REGCTXT), R4	// code pointer
   229  	JAL	(R4)
   230  	RET
   231  
   232  /*
   233   * support for morestack
   234   */
   235  
   236  // Called during function prolog when more stack is needed.
   237  // Caller has already loaded:
   238  // R1: framesize, R2: argsize, R3: LR
   239  //
   240  // The traceback routines see morestack on a g0 as being
   241  // the top of a stack (for example, morestack calling newstack
   242  // calling the scheduler calling newm calling gc), so we must
   243  // record an argument size. For that purpose, it has no arguments.
   244  TEXT runtime·morestack(SB),NOSPLIT,$-8-0
   245  	// Cannot grow scheduler stack (m->g0).
   246  	MOVV	g_m(g), R7
   247  	MOVV	m_g0(R7), R8
   248  	BNE	g, R8, 3(PC)
   249  	JAL	runtime·badmorestackg0(SB)
   250  	JAL	runtime·abort(SB)
   251  
   252  	// Cannot grow signal stack (m->gsignal).
   253  	MOVV	m_gsignal(R7), R8
   254  	BNE	g, R8, 3(PC)
   255  	JAL	runtime·badmorestackgsignal(SB)
   256  	JAL	runtime·abort(SB)
   257  
   258  	// Called from f.
   259  	// Set g->sched to context in f.
   260  	MOVV	R29, (g_sched+gobuf_sp)(g)
   261  	MOVV	R31, (g_sched+gobuf_pc)(g)
   262  	MOVV	R3, (g_sched+gobuf_lr)(g)
   263  	// newstack will fill gobuf.ctxt.
   264  
   265  	// Called from f.
   266  	// Set m->morebuf to f's caller.
   267  	MOVV	R3, (m_morebuf+gobuf_pc)(R7)	// f's caller's PC
   268  	MOVV	R29, (m_morebuf+gobuf_sp)(R7)	// f's caller's SP
   269  	MOVV	g, (m_morebuf+gobuf_g)(R7)
   270  
   271  	// Call newstack on m->g0's stack.
   272  	MOVV	m_g0(R7), g
   273  	JAL	runtime·save_g(SB)
   274  	MOVV	(g_sched+gobuf_sp)(g), R29
   275  	// Create a stack frame on g0 to call newstack.
   276  	MOVV	R0, -16(R29)	// Zero saved LR in frame
   277  	ADDV	$-16, R29
   278  	MOVV	REGCTXT, 8(R29)	// ctxt argument
   279  	JAL	runtime·newstack(SB)
   280  
   281  	// Not reached, but make sure the return PC from the call to newstack
   282  	// is still in this function, and not the beginning of the next.
   283  	UNDEF
   284  
   285  TEXT runtime·morestack_noctxt(SB),NOSPLIT,$-8-0
   286  	MOVV	R0, REGCTXT
   287  	JMP	runtime·morestack(SB)
   288  
   289  TEXT runtime·stackBarrier(SB),NOSPLIT,$0
   290  	// We came here via a RET to an overwritten LR.
   291  	// R1 may be live. Other registers are available.
   292  
   293  	// Get the original return PC, g.stkbar[g.stkbarPos].savedLRVal.
   294  	MOVV	(g_stkbar+slice_array)(g), R2
   295  	MOVV	g_stkbarPos(g), R3
   296  	MOVV	$stkbar__size, R4
   297  	MULVU	R3, R4
   298  	MOVV	LO, R4
   299  	ADDV	R2, R4
   300  	MOVV	stkbar_savedLRVal(R4), R4
   301  	// Record that this stack barrier was hit.
   302  	ADDV	$1, R3
   303  	MOVV	R3, g_stkbarPos(g)
   304  	// Jump to the original return PC.
   305  	JMP	(R4)
   306  
   307  // reflectcall: call a function with the given argument list
   308  // func call(argtype *_type, f *FuncVal, arg *byte, argsize, retoffset uint32).
   309  // we don't have variable-sized frames, so we use a small number
   310  // of constant-sized-frame functions to encode a few bits of size in the pc.
   311  // Caution: ugly multiline assembly macros in your future!
   312  
   313  #define DISPATCH(NAME,MAXSIZE)		\
   314  	MOVV	$MAXSIZE, R23;		\
   315  	SGTU	R1, R23, R23;		\
   316  	BNE	R23, 3(PC);			\
   317  	MOVV	$NAME(SB), R4;	\
   318  	JMP	(R4)
   319  // Note: can't just "BR NAME(SB)" - bad inlining results.
   320  
   321  TEXT reflect·call(SB), NOSPLIT, $0-0
   322  	JMP	·reflectcall(SB)
   323  
   324  TEXT ·reflectcall(SB), NOSPLIT, $-8-32
   325  	MOVWU argsize+24(FP), R1
   326  	DISPATCH(runtime·call32, 32)
   327  	DISPATCH(runtime·call64, 64)
   328  	DISPATCH(runtime·call128, 128)
   329  	DISPATCH(runtime·call256, 256)
   330  	DISPATCH(runtime·call512, 512)
   331  	DISPATCH(runtime·call1024, 1024)
   332  	DISPATCH(runtime·call2048, 2048)
   333  	DISPATCH(runtime·call4096, 4096)
   334  	DISPATCH(runtime·call8192, 8192)
   335  	DISPATCH(runtime·call16384, 16384)
   336  	DISPATCH(runtime·call32768, 32768)
   337  	DISPATCH(runtime·call65536, 65536)
   338  	DISPATCH(runtime·call131072, 131072)
   339  	DISPATCH(runtime·call262144, 262144)
   340  	DISPATCH(runtime·call524288, 524288)
   341  	DISPATCH(runtime·call1048576, 1048576)
   342  	DISPATCH(runtime·call2097152, 2097152)
   343  	DISPATCH(runtime·call4194304, 4194304)
   344  	DISPATCH(runtime·call8388608, 8388608)
   345  	DISPATCH(runtime·call16777216, 16777216)
   346  	DISPATCH(runtime·call33554432, 33554432)
   347  	DISPATCH(runtime·call67108864, 67108864)
   348  	DISPATCH(runtime·call134217728, 134217728)
   349  	DISPATCH(runtime·call268435456, 268435456)
   350  	DISPATCH(runtime·call536870912, 536870912)
   351  	DISPATCH(runtime·call1073741824, 1073741824)
   352  	MOVV	$runtime·badreflectcall(SB), R4
   353  	JMP	(R4)
   354  
   355  #define CALLFN(NAME,MAXSIZE)			\
   356  TEXT NAME(SB), WRAPPER, $MAXSIZE-24;		\
   357  	NO_LOCAL_POINTERS;			\
   358  	/* copy arguments to stack */		\
   359  	MOVV	arg+16(FP), R1;			\
   360  	MOVWU	argsize+24(FP), R2;			\
   361  	MOVV	R29, R3;				\
   362  	ADDV	$8, R3;			\
   363  	ADDV	R3, R2;				\
   364  	BEQ	R3, R2, 6(PC);				\
   365  	MOVBU	(R1), R4;			\
   366  	ADDV	$1, R1;			\
   367  	MOVBU	R4, (R3);			\
   368  	ADDV	$1, R3;			\
   369  	JMP	-5(PC);				\
   370  	/* call function */			\
   371  	MOVV	f+8(FP), REGCTXT;			\
   372  	MOVV	(REGCTXT), R4;			\
   373  	PCDATA  $PCDATA_StackMapIndex, $0;	\
   374  	JAL	(R4);				\
   375  	/* copy return values back */		\
   376  	MOVV	argtype+0(FP), R5;		\
   377  	MOVV	arg+16(FP), R1;			\
   378  	MOVWU	n+24(FP), R2;			\
   379  	MOVWU	retoffset+28(FP), R4;		\
   380  	ADDV	$8, R29, R3;				\
   381  	ADDV	R4, R3; 			\
   382  	ADDV	R4, R1;				\
   383  	SUBVU	R4, R2;				\
   384  	JAL	callRet<>(SB);			\
   385  	RET
   386  
   387  // callRet copies return values back at the end of call*. This is a
   388  // separate function so it can allocate stack space for the arguments
   389  // to reflectcallmove. It does not follow the Go ABI; it expects its
   390  // arguments in registers.
   391  TEXT callRet<>(SB), NOSPLIT, $32-0
   392  	MOVV	R5, 8(R29)
   393  	MOVV	R1, 16(R29)
   394  	MOVV	R3, 24(R29)
   395  	MOVV	R2, 32(R29)
   396  	JAL	runtime·reflectcallmove(SB)
   397  	RET
   398  
   399  CALLFN(·call16, 16)
   400  CALLFN(·call32, 32)
   401  CALLFN(·call64, 64)
   402  CALLFN(·call128, 128)
   403  CALLFN(·call256, 256)
   404  CALLFN(·call512, 512)
   405  CALLFN(·call1024, 1024)
   406  CALLFN(·call2048, 2048)
   407  CALLFN(·call4096, 4096)
   408  CALLFN(·call8192, 8192)
   409  CALLFN(·call16384, 16384)
   410  CALLFN(·call32768, 32768)
   411  CALLFN(·call65536, 65536)
   412  CALLFN(·call131072, 131072)
   413  CALLFN(·call262144, 262144)
   414  CALLFN(·call524288, 524288)
   415  CALLFN(·call1048576, 1048576)
   416  CALLFN(·call2097152, 2097152)
   417  CALLFN(·call4194304, 4194304)
   418  CALLFN(·call8388608, 8388608)
   419  CALLFN(·call16777216, 16777216)
   420  CALLFN(·call33554432, 33554432)
   421  CALLFN(·call67108864, 67108864)
   422  CALLFN(·call134217728, 134217728)
   423  CALLFN(·call268435456, 268435456)
   424  CALLFN(·call536870912, 536870912)
   425  CALLFN(·call1073741824, 1073741824)
   426  
   427  TEXT runtime·procyield(SB),NOSPLIT,$0-0
   428  	RET
   429  
   430  // void jmpdefer(fv, sp);
   431  // called from deferreturn.
   432  // 1. grab stored LR for caller
   433  // 2. sub 8 bytes to get back to JAL deferreturn
   434  // 3. JMP to fn
   435  TEXT runtime·jmpdefer(SB), NOSPLIT, $-8-16
   436  	MOVV	0(R29), R31
   437  	ADDV	$-8, R31
   438  
   439  	MOVV	fv+0(FP), REGCTXT
   440  	MOVV	argp+8(FP), R29
   441  	ADDV	$-8, R29
   442  	NOR	R0, R0	// prevent scheduling
   443  	MOVV	0(REGCTXT), R4
   444  	JMP	(R4)
   445  
   446  // Save state of caller into g->sched. Smashes R1.
   447  TEXT gosave<>(SB),NOSPLIT,$-8
   448  	MOVV	R31, (g_sched+gobuf_pc)(g)
   449  	MOVV	R29, (g_sched+gobuf_sp)(g)
   450  	MOVV	R0, (g_sched+gobuf_lr)(g)
   451  	MOVV	R0, (g_sched+gobuf_ret)(g)
   452  	// Assert ctxt is zero. See func save.
   453  	MOVV	(g_sched+gobuf_ctxt)(g), R1
   454  	BEQ	R1, 2(PC)
   455  	JAL	runtime·badctxt(SB)
   456  	RET
   457  
   458  // func asmcgocall(fn, arg unsafe.Pointer) int32
   459  // Call fn(arg) on the scheduler stack,
   460  // aligned appropriately for the gcc ABI.
   461  // See cgocall.go for more details.
   462  TEXT ·asmcgocall(SB),NOSPLIT,$0-20
   463  	MOVV	fn+0(FP), R25
   464  	MOVV	arg+8(FP), R4
   465  
   466  	MOVV	R29, R3	// save original stack pointer
   467  	MOVV	g, R2
   468  
   469  	// Figure out if we need to switch to m->g0 stack.
   470  	// We get called to create new OS threads too, and those
   471  	// come in on the m->g0 stack already.
   472  	MOVV	g_m(g), R5
   473  	MOVV	m_g0(R5), R6
   474  	BEQ	R6, g, g0
   475  
   476  	JAL	gosave<>(SB)
   477  	MOVV	R6, g
   478  	JAL	runtime·save_g(SB)
   479  	MOVV	(g_sched+gobuf_sp)(g), R29
   480  
   481  	// Now on a scheduling stack (a pthread-created stack).
   482  g0:
   483  	// Save room for two of our pointers.
   484  	ADDV	$-16, R29
   485  	MOVV	R2, 0(R29)	// save old g on stack
   486  	MOVV	(g_stack+stack_hi)(R2), R2
   487  	SUBVU	R3, R2
   488  	MOVV	R2, 8(R29)	// save depth in old g stack (can't just save SP, as stack might be copied during a callback)
   489  	JAL	(R25)
   490  
   491  	// Restore g, stack pointer. R2 is return value.
   492  	MOVV	0(R29), g
   493  	JAL	runtime·save_g(SB)
   494  	MOVV	(g_stack+stack_hi)(g), R5
   495  	MOVV	8(R29), R6
   496  	SUBVU	R6, R5
   497  	MOVV	R5, R29
   498  
   499  	MOVW	R2, ret+16(FP)
   500  	RET
   501  
   502  // cgocallback(void (*fn)(void*), void *frame, uintptr framesize, uintptr ctxt)
   503  // Turn the fn into a Go func (by taking its address) and call
   504  // cgocallback_gofunc.
   505  TEXT runtime·cgocallback(SB),NOSPLIT,$32-32
   506  	MOVV	$fn+0(FP), R1
   507  	MOVV	R1, 8(R29)
   508  	MOVV	frame+8(FP), R1
   509  	MOVV	R1, 16(R29)
   510  	MOVV	framesize+16(FP), R1
   511  	MOVV	R1, 24(R29)
   512  	MOVV	ctxt+24(FP), R1
   513  	MOVV	R1, 32(R29)
   514  	MOVV	$runtime·cgocallback_gofunc(SB), R1
   515  	JAL	(R1)
   516  	RET
   517  
   518  // cgocallback_gofunc(FuncVal*, void *frame, uintptr framesize, uintptr ctxt)
   519  // See cgocall.go for more details.
   520  TEXT ·cgocallback_gofunc(SB),NOSPLIT,$16-32
   521  	NO_LOCAL_POINTERS
   522  
   523  	// Load m and g from thread-local storage.
   524  	MOVB	runtime·iscgo(SB), R1
   525  	BEQ	R1, nocgo
   526  	JAL	runtime·load_g(SB)
   527  nocgo:
   528  
   529  	// If g is nil, Go did not create the current thread.
   530  	// Call needm to obtain one for temporary use.
   531  	// In this case, we're running on the thread stack, so there's
   532  	// lots of space, but the linker doesn't know. Hide the call from
   533  	// the linker analysis by using an indirect call.
   534  	BEQ	g, needm
   535  
   536  	MOVV	g_m(g), R3
   537  	MOVV	R3, savedm-8(SP)
   538  	JMP	havem
   539  
   540  needm:
   541  	MOVV	g, savedm-8(SP) // g is zero, so is m.
   542  	MOVV	$runtime·needm(SB), R4
   543  	JAL	(R4)
   544  
   545  	// Set m->sched.sp = SP, so that if a panic happens
   546  	// during the function we are about to execute, it will
   547  	// have a valid SP to run on the g0 stack.
   548  	// The next few lines (after the havem label)
   549  	// will save this SP onto the stack and then write
   550  	// the same SP back to m->sched.sp. That seems redundant,
   551  	// but if an unrecovered panic happens, unwindm will
   552  	// restore the g->sched.sp from the stack location
   553  	// and then systemstack will try to use it. If we don't set it here,
   554  	// that restored SP will be uninitialized (typically 0) and
   555  	// will not be usable.
   556  	MOVV	g_m(g), R3
   557  	MOVV	m_g0(R3), R1
   558  	MOVV	R29, (g_sched+gobuf_sp)(R1)
   559  
   560  havem:
   561  	// Now there's a valid m, and we're running on its m->g0.
   562  	// Save current m->g0->sched.sp on stack and then set it to SP.
   563  	// Save current sp in m->g0->sched.sp in preparation for
   564  	// switch back to m->curg stack.
   565  	// NOTE: unwindm knows that the saved g->sched.sp is at 8(R29) aka savedsp-16(SP).
   566  	MOVV	m_g0(R3), R1
   567  	MOVV	(g_sched+gobuf_sp)(R1), R2
   568  	MOVV	R2, savedsp-16(SP)
   569  	MOVV	R29, (g_sched+gobuf_sp)(R1)
   570  
   571  	// Switch to m->curg stack and call runtime.cgocallbackg.
   572  	// Because we are taking over the execution of m->curg
   573  	// but *not* resuming what had been running, we need to
   574  	// save that information (m->curg->sched) so we can restore it.
   575  	// We can restore m->curg->sched.sp easily, because calling
   576  	// runtime.cgocallbackg leaves SP unchanged upon return.
   577  	// To save m->curg->sched.pc, we push it onto the stack.
   578  	// This has the added benefit that it looks to the traceback
   579  	// routine like cgocallbackg is going to return to that
   580  	// PC (because the frame we allocate below has the same
   581  	// size as cgocallback_gofunc's frame declared above)
   582  	// so that the traceback will seamlessly trace back into
   583  	// the earlier calls.
   584  	//
   585  	// In the new goroutine, -8(SP) is unused (where SP refers to
   586  	// m->curg's SP while we're setting it up, before we've adjusted it).
   587  	MOVV	m_curg(R3), g
   588  	JAL	runtime·save_g(SB)
   589  	MOVV	(g_sched+gobuf_sp)(g), R2 // prepare stack as R2
   590  	MOVV	(g_sched+gobuf_pc)(g), R4
   591  	MOVV	R4, -24(R2)
   592  	MOVV    ctxt+24(FP), R1
   593  	MOVV    R1, -16(R2)
   594  	MOVV	$-24(R2), R29
   595  	JAL	runtime·cgocallbackg(SB)
   596  
   597  	// Restore g->sched (== m->curg->sched) from saved values.
   598  	MOVV	0(R29), R4
   599  	MOVV	R4, (g_sched+gobuf_pc)(g)
   600  	MOVV	$24(R29), R2
   601  	MOVV	R2, (g_sched+gobuf_sp)(g)
   602  
   603  	// Switch back to m->g0's stack and restore m->g0->sched.sp.
   604  	// (Unlike m->curg, the g0 goroutine never uses sched.pc,
   605  	// so we do not have to restore it.)
   606  	MOVV	g_m(g), R3
   607  	MOVV	m_g0(R3), g
   608  	JAL	runtime·save_g(SB)
   609  	MOVV	(g_sched+gobuf_sp)(g), R29
   610  	MOVV	savedsp-16(SP), R2
   611  	MOVV	R2, (g_sched+gobuf_sp)(g)
   612  
   613  	// If the m on entry was nil, we called needm above to borrow an m
   614  	// for the duration of the call. Since the call is over, return it with dropm.
   615  	MOVV	savedm-8(SP), R3
   616  	BNE	R3, droppedm
   617  	MOVV	$runtime·dropm(SB), R4
   618  	JAL	(R4)
   619  droppedm:
   620  
   621  	// Done!
   622  	RET
   623  
   624  // void setg(G*); set g. for use by needm.
   625  TEXT runtime·setg(SB), NOSPLIT, $0-8
   626  	MOVV	gg+0(FP), g
   627  	// This only happens if iscgo, so jump straight to save_g
   628  	JAL	runtime·save_g(SB)
   629  	RET
   630  
   631  // void setg_gcc(G*); set g called from gcc with g in R1
   632  TEXT setg_gcc<>(SB),NOSPLIT,$0-0
   633  	MOVV	R1, g
   634  	JAL	runtime·save_g(SB)
   635  	RET
   636  
   637  TEXT runtime·getcallerpc(SB),NOSPLIT,$8-16
   638  	MOVV	16(R29), R1		// LR saved by caller
   639  	MOVV	runtime·stackBarrierPC(SB), R2
   640  	BNE	R1, R2, nobar
   641  	// Get original return PC.
   642  	JAL	runtime·nextBarrierPC(SB)
   643  	MOVV	8(R29), R1
   644  nobar:
   645  	MOVV	R1, ret+8(FP)
   646  	RET
   647  
   648  TEXT runtime·setcallerpc(SB),NOSPLIT,$8-16
   649  	MOVV	pc+8(FP), R1
   650  	MOVV	16(R29), R2
   651  	MOVV	runtime·stackBarrierPC(SB), R3
   652  	BEQ	R2, R3, setbar
   653  	MOVV	R1, 16(R29)		// set LR in caller
   654  	RET
   655  setbar:
   656  	// Set the stack barrier return PC.
   657  	MOVV	R1, 8(R29)
   658  	JAL	runtime·setNextBarrierPC(SB)
   659  	RET
   660  
   661  TEXT runtime·abort(SB),NOSPLIT,$-8-0
   662  	MOVW	(R0), R0
   663  	UNDEF
   664  
   665  // memhash_varlen(p unsafe.Pointer, h seed) uintptr
   666  // redirects to memhash(p, h, size) using the size
   667  // stored in the closure.
   668  TEXT runtime·memhash_varlen(SB),NOSPLIT,$40-24
   669  	GO_ARGS
   670  	NO_LOCAL_POINTERS
   671  	MOVV	p+0(FP), R1
   672  	MOVV	h+8(FP), R2
   673  	MOVV	8(REGCTXT), R3
   674  	MOVV	R1, 8(R29)
   675  	MOVV	R2, 16(R29)
   676  	MOVV	R3, 24(R29)
   677  	JAL	runtime·memhash(SB)
   678  	MOVV	32(R29), R1
   679  	MOVV	R1, ret+16(FP)
   680  	RET
   681  
   682  // AES hashing not implemented for mips64
   683  TEXT runtime·aeshash(SB),NOSPLIT,$-8-0
   684  	MOVW	(R0), R1
   685  TEXT runtime·aeshash32(SB),NOSPLIT,$-8-0
   686  	MOVW	(R0), R1
   687  TEXT runtime·aeshash64(SB),NOSPLIT,$-8-0
   688  	MOVW	(R0), R1
   689  TEXT runtime·aeshashstr(SB),NOSPLIT,$-8-0
   690  	MOVW	(R0), R1
   691  
   692  // memequal(p, q unsafe.Pointer, size uintptr) bool
   693  TEXT runtime·memequal(SB),NOSPLIT,$-8-25
   694  	MOVV	a+0(FP), R1
   695  	MOVV	b+8(FP), R2
   696  	BEQ	R1, R2, eq
   697  	MOVV	size+16(FP), R3
   698  	ADDV	R1, R3, R4
   699  loop:
   700  	BNE	R1, R4, test
   701  	MOVV	$1, R1
   702  	MOVB	R1, ret+24(FP)
   703  	RET
   704  test:
   705  	MOVBU	(R1), R6
   706  	ADDV	$1, R1
   707  	MOVBU	(R2), R7
   708  	ADDV	$1, R2
   709  	BEQ	R6, R7, loop
   710  
   711  	MOVB	R0, ret+24(FP)
   712  	RET
   713  eq:
   714  	MOVV	$1, R1
   715  	MOVB	R1, ret+24(FP)
   716  	RET
   717  
   718  // memequal_varlen(a, b unsafe.Pointer) bool
   719  TEXT runtime·memequal_varlen(SB),NOSPLIT,$40-17
   720  	MOVV	a+0(FP), R1
   721  	MOVV	b+8(FP), R2
   722  	BEQ	R1, R2, eq
   723  	MOVV	8(REGCTXT), R3    // compiler stores size at offset 8 in the closure
   724  	MOVV	R1, 8(R29)
   725  	MOVV	R2, 16(R29)
   726  	MOVV	R3, 24(R29)
   727  	JAL	runtime·memequal(SB)
   728  	MOVBU	32(R29), R1
   729  	MOVB	R1, ret+16(FP)
   730  	RET
   731  eq:
   732  	MOVV	$1, R1
   733  	MOVB	R1, ret+16(FP)
   734  	RET
   735  
   736  // eqstring tests whether two strings are equal.
   737  // The compiler guarantees that strings passed
   738  // to eqstring have equal length.
   739  // See runtime_test.go:eqstring_generic for
   740  // equivalent Go code.
   741  TEXT runtime·eqstring(SB),NOSPLIT,$0-33
   742  	MOVV	s1_base+0(FP), R1
   743  	MOVV	s2_base+16(FP), R2
   744  	MOVV	$1, R3
   745  	MOVB	R3, ret+32(FP)
   746  	BNE	R1, R2, 2(PC)
   747  	RET
   748  	MOVV	s1_len+8(FP), R3
   749  	ADDV	R1, R3, R4
   750  loop:
   751  	BNE	R1, R4, 2(PC)
   752  	RET
   753  	MOVBU	(R1), R6
   754  	ADDV	$1, R1
   755  	MOVBU	(R2), R7
   756  	ADDV	$1, R2
   757  	BEQ	R6, R7, loop
   758  	MOVB	R0, ret+32(FP)
   759  	RET
   760  
   761  // TODO: share code with memequal?
   762  TEXT bytes·Equal(SB),NOSPLIT,$0-49
   763  	MOVV	a_len+8(FP), R3
   764  	MOVV	b_len+32(FP), R4
   765  	BNE	R3, R4, noteq		// unequal lengths are not equal
   766  
   767  	MOVV	a+0(FP), R1
   768  	MOVV	b+24(FP), R2
   769  	ADDV	R1, R3		// end
   770  
   771  loop:
   772  	BEQ	R1, R3, equal		// reached the end
   773  	MOVBU	(R1), R6
   774  	ADDV	$1, R1
   775  	MOVBU	(R2), R7
   776  	ADDV	$1, R2
   777  	BEQ	R6, R7, loop
   778  
   779  noteq:
   780  	MOVB	R0, ret+48(FP)
   781  	RET
   782  
   783  equal:
   784  	MOVV	$1, R1
   785  	MOVB	R1, ret+48(FP)
   786  	RET
   787  
   788  TEXT bytes·IndexByte(SB),NOSPLIT,$0-40
   789  	MOVV	s+0(FP), R1
   790  	MOVV	s_len+8(FP), R2
   791  	MOVBU	c+24(FP), R3	// byte to find
   792  	MOVV	R1, R4		// store base for later
   793  	ADDV	R1, R2		// end
   794  	ADDV	$-1, R1
   795  
   796  loop:
   797  	ADDV	$1, R1
   798  	BEQ	R1, R2, notfound
   799  	MOVBU	(R1), R5
   800  	BNE	R3, R5, loop
   801  
   802  	SUBV	R4, R1		// remove base
   803  	MOVV	R1, ret+32(FP)
   804  	RET
   805  
   806  notfound:
   807  	MOVV	$-1, R1
   808  	MOVV	R1, ret+32(FP)
   809  	RET
   810  
   811  TEXT strings·IndexByte(SB),NOSPLIT,$0-32
   812  	MOVV	p+0(FP), R1
   813  	MOVV	b_len+8(FP), R2
   814  	MOVBU	c+16(FP), R3	// byte to find
   815  	MOVV	R1, R4		// store base for later
   816  	ADDV	R1, R2		// end
   817  	ADDV	$-1, R1
   818  
   819  loop:
   820  	ADDV	$1, R1
   821  	BEQ	R1, R2, notfound
   822  	MOVBU	(R1), R5
   823  	BNE	R3, R5, loop
   824  
   825  	SUBV	R4, R1		// remove base
   826  	MOVV	R1, ret+24(FP)
   827  	RET
   828  
   829  notfound:
   830  	MOVV	$-1, R1
   831  	MOVV	R1, ret+24(FP)
   832  	RET
   833  
   834  TEXT runtime·fastrand(SB), NOSPLIT, $0-4
   835  	MOVV	g_m(g), R2
   836  	MOVWU	m_fastrand(R2), R1
   837  	ADDU	R1, R1
   838  	BGEZ	R1, 2(PC)
   839  	XOR	$0x88888eef, R1
   840  	MOVW	R1, m_fastrand(R2)
   841  	MOVW	R1, ret+0(FP)
   842  	RET
   843  
   844  TEXT runtime·return0(SB), NOSPLIT, $0
   845  	MOVW	$0, R1
   846  	RET
   847  
   848  // Called from cgo wrappers, this function returns g->m->curg.stack.hi.
   849  // Must obey the gcc calling convention.
   850  TEXT _cgo_topofstack(SB),NOSPLIT,$16
   851  	// g (R30) and REGTMP (R23)  might be clobbered by load_g. They
   852  	// are callee-save in the gcc calling convention, so save them.
   853  	MOVV	R23, savedR23-16(SP)
   854  	MOVV	g, savedG-8(SP)
   855  
   856  	JAL	runtime·load_g(SB)
   857  	MOVV	g_m(g), R1
   858  	MOVV	m_curg(R1), R1
   859  	MOVV	(g_stack+stack_hi)(R1), R2 // return value in R2
   860  
   861  	MOVV	savedG-8(SP), g
   862  	MOVV	savedR23-16(SP), R23
   863  	RET
   864  
   865  // The top-most function running on a goroutine
   866  // returns to goexit+PCQuantum.
   867  TEXT runtime·goexit(SB),NOSPLIT,$-8-0
   868  	NOR	R0, R0	// NOP
   869  	JAL	runtime·goexit1(SB)	// does not return
   870  	// traceback from goexit1 must hit code range of goexit
   871  	NOR	R0, R0	// NOP
   872  
   873  TEXT runtime·prefetcht0(SB),NOSPLIT,$0-8
   874  	RET
   875  
   876  TEXT runtime·prefetcht1(SB),NOSPLIT,$0-8
   877  	RET
   878  
   879  TEXT runtime·prefetcht2(SB),NOSPLIT,$0-8
   880  	RET
   881  
   882  TEXT runtime·prefetchnta(SB),NOSPLIT,$0-8
   883  	RET
   884  
   885  TEXT ·checkASM(SB),NOSPLIT,$0-1
   886  	MOVW	$1, R1
   887  	MOVB	R1, ret+0(FP)
   888  	RET