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