github.com/FenixAra/go@v0.0.0-20170127160404-96ea0918e670/src/runtime/asm_mipsx.s (about)

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