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