github.com/karrick/go@v0.0.0-20170817181416-d5b0ec858b37/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  // reflectcall: call a function with the given argument list
   291  // func call(argtype *_type, f *FuncVal, arg *byte, argsize, retoffset uint32).
   292  // we don't have variable-sized frames, so we use a small number
   293  // of constant-sized-frame functions to encode a few bits of size in the pc.
   294  
   295  #define DISPATCH(NAME,MAXSIZE)	\
   296  	MOVW	$MAXSIZE, R23;	\
   297  	SGTU	R1, R23, R23;	\
   298  	BNE	R23, 3(PC);	\
   299  	MOVW	$NAME(SB), R4;	\
   300  	JMP	(R4)
   301  
   302  TEXT reflect·call(SB),NOSPLIT,$0-20
   303  	JMP	·reflectcall(SB)
   304  
   305  TEXT ·reflectcall(SB),NOSPLIT,$-4-20
   306  	MOVW	argsize+12(FP), R1
   307  
   308  	DISPATCH(runtime·call16, 16)
   309  	DISPATCH(runtime·call32, 32)
   310  	DISPATCH(runtime·call64, 64)
   311  	DISPATCH(runtime·call128, 128)
   312  	DISPATCH(runtime·call256, 256)
   313  	DISPATCH(runtime·call512, 512)
   314  	DISPATCH(runtime·call1024, 1024)
   315  	DISPATCH(runtime·call2048, 2048)
   316  	DISPATCH(runtime·call4096, 4096)
   317  	DISPATCH(runtime·call8192, 8192)
   318  	DISPATCH(runtime·call16384, 16384)
   319  	DISPATCH(runtime·call32768, 32768)
   320  	DISPATCH(runtime·call65536, 65536)
   321  	DISPATCH(runtime·call131072, 131072)
   322  	DISPATCH(runtime·call262144, 262144)
   323  	DISPATCH(runtime·call524288, 524288)
   324  	DISPATCH(runtime·call1048576, 1048576)
   325  	DISPATCH(runtime·call2097152, 2097152)
   326  	DISPATCH(runtime·call4194304, 4194304)
   327  	DISPATCH(runtime·call8388608, 8388608)
   328  	DISPATCH(runtime·call16777216, 16777216)
   329  	DISPATCH(runtime·call33554432, 33554432)
   330  	DISPATCH(runtime·call67108864, 67108864)
   331  	DISPATCH(runtime·call134217728, 134217728)
   332  	DISPATCH(runtime·call268435456, 268435456)
   333  	DISPATCH(runtime·call536870912, 536870912)
   334  	DISPATCH(runtime·call1073741824, 1073741824)
   335  	MOVW	$runtime·badreflectcall(SB), R4
   336  	JMP	(R4)
   337  
   338  #define CALLFN(NAME,MAXSIZE)	\
   339  TEXT NAME(SB),WRAPPER,$MAXSIZE-20;	\
   340  	NO_LOCAL_POINTERS;	\
   341  	/* copy arguments to stack */		\
   342  	MOVW	arg+8(FP), R1;	\
   343  	MOVW	argsize+12(FP), R2;	\
   344  	MOVW	R29, R3;	\
   345  	ADDU	$4, R3;	\
   346  	ADDU	R3, R2;	\
   347  	BEQ	R3, R2, 6(PC);	\
   348  	MOVBU	(R1), R4;	\
   349  	ADDU	$1, R1;	\
   350  	MOVBU	R4, (R3);	\
   351  	ADDU	$1, R3;	\
   352  	JMP	-5(PC);	\
   353  	/* call function */			\
   354  	MOVW	f+4(FP), REGCTXT;	\
   355  	MOVW	(REGCTXT), R4;	\
   356  	PCDATA	$PCDATA_StackMapIndex, $0;	\
   357  	JAL	(R4);	\
   358  	/* copy return values back */		\
   359  	MOVW	argtype+0(FP), R5;	\
   360  	MOVW	arg+8(FP), R1;	\
   361  	MOVW	n+12(FP), R2;	\
   362  	MOVW	retoffset+16(FP), R4;	\
   363  	ADDU	$4, R29, R3;	\
   364  	ADDU	R4, R3;	\
   365  	ADDU	R4, R1;	\
   366  	SUBU	R4, R2;	\
   367  	JAL	callRet<>(SB);		\
   368  	RET
   369  
   370  // callRet copies return values back at the end of call*. This is a
   371  // separate function so it can allocate stack space for the arguments
   372  // to reflectcallmove. It does not follow the Go ABI; it expects its
   373  // arguments in registers.
   374  TEXT callRet<>(SB), NOSPLIT, $16-0
   375  	MOVW	R5, 4(R29)
   376  	MOVW	R1, 8(R29)
   377  	MOVW	R3, 12(R29)
   378  	MOVW	R2, 16(R29)
   379  	JAL	runtime·reflectcallmove(SB)
   380  	RET
   381  
   382  CALLFN(·call16, 16)
   383  CALLFN(·call32, 32)
   384  CALLFN(·call64, 64)
   385  CALLFN(·call128, 128)
   386  CALLFN(·call256, 256)
   387  CALLFN(·call512, 512)
   388  CALLFN(·call1024, 1024)
   389  CALLFN(·call2048, 2048)
   390  CALLFN(·call4096, 4096)
   391  CALLFN(·call8192, 8192)
   392  CALLFN(·call16384, 16384)
   393  CALLFN(·call32768, 32768)
   394  CALLFN(·call65536, 65536)
   395  CALLFN(·call131072, 131072)
   396  CALLFN(·call262144, 262144)
   397  CALLFN(·call524288, 524288)
   398  CALLFN(·call1048576, 1048576)
   399  CALLFN(·call2097152, 2097152)
   400  CALLFN(·call4194304, 4194304)
   401  CALLFN(·call8388608, 8388608)
   402  CALLFN(·call16777216, 16777216)
   403  CALLFN(·call33554432, 33554432)
   404  CALLFN(·call67108864, 67108864)
   405  CALLFN(·call134217728, 134217728)
   406  CALLFN(·call268435456, 268435456)
   407  CALLFN(·call536870912, 536870912)
   408  CALLFN(·call1073741824, 1073741824)
   409  
   410  TEXT runtime·procyield(SB),NOSPLIT,$0-4
   411  	RET
   412  
   413  // void jmpdefer(fv, sp);
   414  // called from deferreturn.
   415  // 1. grab stored LR for caller
   416  // 2. sub 8 bytes to get back to JAL deferreturn
   417  // 3. JMP to fn
   418  TEXT runtime·jmpdefer(SB),NOSPLIT,$0-8
   419  	MOVW	0(R29), R31
   420  	ADDU	$-8, R31
   421  
   422  	MOVW	fv+0(FP), REGCTXT
   423  	MOVW	argp+4(FP), R29
   424  	ADDU	$-4, R29
   425  	NOR	R0, R0	// prevent scheduling
   426  	MOVW	0(REGCTXT), R4
   427  	JMP	(R4)
   428  
   429  // Save state of caller into g->sched. Smashes R1.
   430  TEXT gosave<>(SB),NOSPLIT,$-4
   431  	MOVW	R31, (g_sched+gobuf_pc)(g)
   432  	MOVW	R29, (g_sched+gobuf_sp)(g)
   433  	MOVW	R0, (g_sched+gobuf_lr)(g)
   434  	MOVW	R0, (g_sched+gobuf_ret)(g)
   435  	// Assert ctxt is zero. See func save.
   436  	MOVW	(g_sched+gobuf_ctxt)(g), R1
   437  	BEQ	R1, 2(PC)
   438  	JAL	runtime·badctxt(SB)
   439  	RET
   440  
   441  // func asmcgocall(fn, arg unsafe.Pointer) int32
   442  // Call fn(arg) on the scheduler stack,
   443  // aligned appropriately for the gcc ABI.
   444  // See cgocall.go for more details.
   445  TEXT ·asmcgocall(SB),NOSPLIT,$0-12
   446  	MOVW	fn+0(FP), R25
   447  	MOVW	arg+4(FP), R4
   448  
   449  	MOVW	R29, R3	// save original stack pointer
   450  	MOVW	g, R2
   451  
   452  	// Figure out if we need to switch to m->g0 stack.
   453  	// We get called to create new OS threads too, and those
   454  	// come in on the m->g0 stack already.
   455  	MOVW	g_m(g), R5
   456  	MOVW	m_g0(R5), R6
   457  	BEQ	R6, g, g0
   458  
   459  	JAL	gosave<>(SB)
   460  	MOVW	R6, g
   461  	JAL	runtime·save_g(SB)
   462  	MOVW	(g_sched+gobuf_sp)(g), R29
   463  
   464  	// Now on a scheduling stack (a pthread-created stack).
   465  g0:
   466  	// Save room for two of our pointers and O32 frame.
   467  	ADDU	$-24, R29
   468  	AND	$~7, R29	// O32 ABI expects 8-byte aligned stack on function entry
   469  	MOVW	R2, 16(R29)	// save old g on stack
   470  	MOVW	(g_stack+stack_hi)(R2), R2
   471  	SUBU	R3, R2
   472  	MOVW	R2, 20(R29)	// save depth in old g stack (can't just save SP, as stack might be copied during a callback)
   473  	JAL	(R25)
   474  
   475  	// Restore g, stack pointer. R2 is return value.
   476  	MOVW	16(R29), g
   477  	JAL	runtime·save_g(SB)
   478  	MOVW	(g_stack+stack_hi)(g), R5
   479  	MOVW	20(R29), R6
   480  	SUBU	R6, R5
   481  	MOVW	R5, R29
   482  
   483  	MOVW	R2, ret+8(FP)
   484  	RET
   485  
   486  // cgocallback(void (*fn)(void*), void *frame, uintptr framesize)
   487  // Turn the fn into a Go func (by taking its address) and call
   488  // cgocallback_gofunc.
   489  TEXT runtime·cgocallback(SB),NOSPLIT,$16-16
   490  	MOVW	$fn+0(FP), R1
   491  	MOVW	R1, 4(R29)
   492  	MOVW	frame+4(FP), R1
   493  	MOVW	R1, 8(R29)
   494  	MOVW	framesize+8(FP), R1
   495  	MOVW	R1, 12(R29)
   496  	MOVW	ctxt+12(FP), R1
   497  	MOVW	R1, 16(R29)
   498  	MOVW	$runtime·cgocallback_gofunc(SB), R1
   499  	JAL	(R1)
   500  	RET
   501  
   502  // cgocallback_gofunc(FuncVal*, void *frame, uintptr framesize, uintptr ctxt)
   503  // See cgocall.go for more details.
   504  TEXT ·cgocallback_gofunc(SB),NOSPLIT,$8-16
   505  	NO_LOCAL_POINTERS
   506  
   507  	// Load m and g from thread-local storage.
   508  	MOVB	runtime·iscgo(SB), R1
   509  	BEQ	R1, nocgo
   510  	JAL	runtime·load_g(SB)
   511  nocgo:
   512  
   513  	// If g is nil, Go did not create the current thread.
   514  	// Call needm to obtain one for temporary use.
   515  	// In this case, we're running on the thread stack, so there's
   516  	// lots of space, but the linker doesn't know. Hide the call from
   517  	// the linker analysis by using an indirect call.
   518  	BEQ	g, needm
   519  
   520  	MOVW	g_m(g), R3
   521  	MOVW	R3, savedm-4(SP)
   522  	JMP	havem
   523  
   524  needm:
   525  	MOVW	g, savedm-4(SP) // g is zero, so is m.
   526  	MOVW	$runtime·needm(SB), R4
   527  	JAL	(R4)
   528  
   529  	// Set m->sched.sp = SP, so that if a panic happens
   530  	// during the function we are about to execute, it will
   531  	// have a valid SP to run on the g0 stack.
   532  	// The next few lines (after the havem label)
   533  	// will save this SP onto the stack and then write
   534  	// the same SP back to m->sched.sp. That seems redundant,
   535  	// but if an unrecovered panic happens, unwindm will
   536  	// restore the g->sched.sp from the stack location
   537  	// and then systemstack will try to use it. If we don't set it here,
   538  	// that restored SP will be uninitialized (typically 0) and
   539  	// will not be usable.
   540  	MOVW	g_m(g), R3
   541  	MOVW	m_g0(R3), R1
   542  	MOVW	R29, (g_sched+gobuf_sp)(R1)
   543  
   544  havem:
   545  	// Now there's a valid m, and we're running on its m->g0.
   546  	// Save current m->g0->sched.sp on stack and then set it to SP.
   547  	// Save current sp in m->g0->sched.sp in preparation for
   548  	// switch back to m->curg stack.
   549  	// NOTE: unwindm knows that the saved g->sched.sp is at 4(R29) aka savedsp-8(SP).
   550  	MOVW	m_g0(R3), R1
   551  	MOVW	(g_sched+gobuf_sp)(R1), R2
   552  	MOVW	R2, savedsp-8(SP)
   553  	MOVW	R29, (g_sched+gobuf_sp)(R1)
   554  
   555  	// Switch to m->curg stack and call runtime.cgocallbackg.
   556  	// Because we are taking over the execution of m->curg
   557  	// but *not* resuming what had been running, we need to
   558  	// save that information (m->curg->sched) so we can restore it.
   559  	// We can restore m->curg->sched.sp easily, because calling
   560  	// runtime.cgocallbackg leaves SP unchanged upon return.
   561  	// To save m->curg->sched.pc, we push it onto the stack.
   562  	// This has the added benefit that it looks to the traceback
   563  	// routine like cgocallbackg is going to return to that
   564  	// PC (because the frame we allocate below has the same
   565  	// size as cgocallback_gofunc's frame declared above)
   566  	// so that the traceback will seamlessly trace back into
   567  	// the earlier calls.
   568  	//
   569  	// In the new goroutine, -4(SP) is unused (where SP refers to
   570  	// m->curg's SP while we're setting it up, before we've adjusted it).
   571  	MOVW	m_curg(R3), g
   572  	JAL	runtime·save_g(SB)
   573  	MOVW	(g_sched+gobuf_sp)(g), R2 // prepare stack as R2
   574  	MOVW	(g_sched+gobuf_pc)(g), R4
   575  	MOVW	R4, -12(R2)
   576  	MOVW    ctxt+12(FP), R1
   577  	MOVW    R1, -8(R2)
   578  	MOVW	$-12(R2), R29
   579  	JAL	runtime·cgocallbackg(SB)
   580  
   581  	// Restore g->sched (== m->curg->sched) from saved values.
   582  	MOVW	0(R29), R4
   583  	MOVW	R4, (g_sched+gobuf_pc)(g)
   584  	MOVW	$12(R29), R2
   585  	MOVW	R2, (g_sched+gobuf_sp)(g)
   586  
   587  	// Switch back to m->g0's stack and restore m->g0->sched.sp.
   588  	// (Unlike m->curg, the g0 goroutine never uses sched.pc,
   589  	// so we do not have to restore it.)
   590  	MOVW	g_m(g), R3
   591  	MOVW	m_g0(R3), g
   592  	JAL	runtime·save_g(SB)
   593  	MOVW	(g_sched+gobuf_sp)(g), R29
   594  	MOVW	savedsp-8(SP), R2
   595  	MOVW	R2, (g_sched+gobuf_sp)(g)
   596  
   597  	// If the m on entry was nil, we called needm above to borrow an m
   598  	// for the duration of the call. Since the call is over, return it with dropm.
   599  	MOVW	savedm-4(SP), R3
   600  	BNE	R3, droppedm
   601  	MOVW	$runtime·dropm(SB), R4
   602  	JAL	(R4)
   603  droppedm:
   604  
   605  	// Done!
   606  	RET
   607  
   608  // void setg(G*); set g. for use by needm.
   609  // This only happens if iscgo, so jump straight to save_g
   610  TEXT runtime·setg(SB),NOSPLIT,$0-4
   611  	MOVW	gg+0(FP), g
   612  	JAL	runtime·save_g(SB)
   613  	RET
   614  
   615  // void setg_gcc(G*); set g in C TLS.
   616  // Must obey the gcc calling convention.
   617  TEXT setg_gcc<>(SB),NOSPLIT,$0
   618  	MOVW	R4, g
   619  	JAL	runtime·save_g(SB)
   620  	RET
   621  
   622  TEXT runtime·getcallerpc(SB),NOSPLIT,$4-8
   623  	MOVW	8(R29), R1	// LR saved by caller
   624  	MOVW	R1, ret+4(FP)
   625  	RET
   626  
   627  TEXT runtime·abort(SB),NOSPLIT,$0-0
   628  	UNDEF
   629  
   630  // Not implemented.
   631  TEXT runtime·aeshash(SB),NOSPLIT,$0
   632  	UNDEF
   633  
   634  // Not implemented.
   635  TEXT runtime·aeshash32(SB),NOSPLIT,$0
   636  	UNDEF
   637  
   638  // Not implemented.
   639  TEXT runtime·aeshash64(SB),NOSPLIT,$0
   640  	UNDEF
   641  
   642  // Not implemented.
   643  TEXT runtime·aeshashstr(SB),NOSPLIT,$0
   644  	UNDEF
   645  
   646  // memequal(a, b unsafe.Pointer, size uintptr) bool
   647  TEXT runtime·memequal(SB),NOSPLIT,$0-13
   648  	MOVW	a+0(FP), R1
   649  	MOVW	b+4(FP), R2
   650  	BEQ	R1, R2, eq
   651  	MOVW	size+8(FP), R3
   652  	ADDU	R1, R3, R4
   653  loop:
   654  	BNE	R1, R4, test
   655  	MOVW	$1, R1
   656  	MOVB	R1, ret+12(FP)
   657  	RET
   658  test:
   659  	MOVBU	(R1), R6
   660  	ADDU	$1, R1
   661  	MOVBU	(R2), R7
   662  	ADDU	$1, R2
   663  	BEQ	R6, R7, loop
   664  
   665  	MOVB	R0, ret+12(FP)
   666  	RET
   667  eq:
   668  	MOVW	$1, R1
   669  	MOVB	R1, ret+12(FP)
   670  	RET
   671  
   672  // memequal_varlen(a, b unsafe.Pointer) bool
   673  TEXT runtime·memequal_varlen(SB),NOSPLIT,$0-9
   674  	MOVW	a+0(FP), R1
   675  	MOVW	b+4(FP), R2
   676  	BEQ	R1, R2, eq
   677  	MOVW	4(REGCTXT), R3	// compiler stores size at offset 4 in the closure
   678  	ADDU	R1, R3, R4
   679  loop:
   680  	BNE	R1, R4, test
   681  	MOVW	$1, R1
   682  	MOVB	R1, ret+8(FP)
   683  	RET
   684  test:
   685  	MOVBU	(R1), R6
   686  	ADDU	$1, R1
   687  	MOVBU	(R2), R7
   688  	ADDU	$1, R2
   689  	BEQ	R6, R7, loop
   690  
   691  	MOVB	R0, ret+8(FP)
   692  	RET
   693  eq:
   694  	MOVW	$1, R1
   695  	MOVB	R1, ret+8(FP)
   696  	RET
   697  
   698  // eqstring tests whether two strings are equal.
   699  // The compiler guarantees that strings passed
   700  // to eqstring have equal length.
   701  // See runtime_test.go:eqstring_generic for
   702  // equivalent Go code.
   703  TEXT runtime·eqstring(SB),NOSPLIT,$0-17
   704  	MOVW	s1_base+0(FP), R1
   705  	MOVW	s2_base+8(FP), R2
   706  	MOVW	$1, R3
   707  	MOVBU	R3, ret+16(FP)
   708  	BNE	R1, R2, 2(PC)
   709  	RET
   710  	MOVW	s1_len+4(FP), R3
   711  	ADDU	R1, R3, R4
   712  loop:
   713  	BNE	R1, R4, 2(PC)
   714  	RET
   715  	MOVBU	(R1), R6
   716  	ADDU	$1, R1
   717  	MOVBU	(R2), R7
   718  	ADDU	$1, R2
   719  	BEQ	R6, R7, loop
   720  	MOVB	R0, ret+16(FP)
   721  	RET
   722  
   723  TEXT bytes·Equal(SB),NOSPLIT,$0-25
   724  	MOVW	a_len+4(FP), R3
   725  	MOVW	b_len+16(FP), R4
   726  	BNE	R3, R4, noteq	// unequal lengths are not equal
   727  
   728  	MOVW	a+0(FP), R1
   729  	MOVW	b+12(FP), R2
   730  	ADDU	R1, R3	// end
   731  
   732  loop:
   733  	BEQ	R1, R3, equal	// reached the end
   734  	MOVBU	(R1), R6
   735  	ADDU	$1, R1
   736  	MOVBU	(R2), R7
   737  	ADDU	$1, R2
   738  	BEQ	R6, R7, loop
   739  
   740  noteq:
   741  	MOVB	R0, ret+24(FP)
   742  	RET
   743  
   744  equal:
   745  	MOVW	$1, R1
   746  	MOVB	R1, ret+24(FP)
   747  	RET
   748  
   749  TEXT bytes·IndexByte(SB),NOSPLIT,$0-20
   750  	MOVW	s+0(FP), R1
   751  	MOVW	s_len+4(FP), R2
   752  	MOVBU	c+12(FP), R3	// byte to find
   753  	ADDU	$1, R1, R4	// store base+1 for later
   754  	ADDU	R1, R2	// end
   755  
   756  loop:
   757  	BEQ	R1, R2, notfound
   758  	MOVBU	(R1), R5
   759  	ADDU	$1, R1
   760  	BNE	R3, R5, loop
   761  
   762  	SUBU	R4, R1	// R1 will be one beyond the position we want so remove (base+1)
   763  	MOVW	R1, ret+16(FP)
   764  	RET
   765  
   766  notfound:
   767  	MOVW	$-1, R1
   768  	MOVW	R1, ret+16(FP)
   769  	RET
   770  
   771  TEXT strings·IndexByte(SB),NOSPLIT,$0-16
   772  	MOVW	s_base+0(FP), R1
   773  	MOVW	s_len+4(FP), R2
   774  	MOVBU	c+8(FP), R3	// byte to find
   775  	ADDU	$1, R1, R4	// store base+1 for later
   776  	ADDU	R1, R2	// end
   777  
   778  loop:
   779  	BEQ	R1, R2, notfound
   780  	MOVBU	(R1), R5
   781  	ADDU	$1, R1
   782  	BNE	R3, R5, loop
   783  
   784  	SUBU	R4, R1	// remove (base+1)
   785  	MOVW	R1, ret+12(FP)
   786  	RET
   787  
   788  notfound:
   789  	MOVW	$-1, R1
   790  	MOVW	R1, ret+12(FP)
   791  	RET
   792  
   793  TEXT runtime·cmpstring(SB),NOSPLIT,$0-20
   794  	MOVW	s1_base+0(FP), R3
   795  	MOVW	s1_len+4(FP), R1
   796  	MOVW	s2_base+8(FP), R4
   797  	MOVW	s2_len+12(FP), R2
   798  	BEQ	R3, R4, samebytes
   799  	SGTU	R1, R2, R7
   800  	MOVW	R1, R8
   801  	CMOVN	R7, R2, R8	// R8 is min(R1, R2)
   802  
   803  	ADDU	R3, R8	// R3 is current byte in s1, R8 is last byte in s1 to compare
   804  loop:
   805  	BEQ	R3, R8, samebytes	// all compared bytes were the same; compare lengths
   806  
   807  	MOVBU	(R3), R6
   808  	ADDU	$1, R3
   809  	MOVBU	(R4), R7
   810  	ADDU	$1, R4
   811  	BEQ	R6, R7 , loop
   812  	// bytes differed
   813  	SGTU	R6, R7, R8
   814  	MOVW	$-1, R6
   815  	CMOVZ	R8, R6, R8
   816  	JMP	cmp_ret
   817  samebytes:
   818  	SGTU	R1, R2, R6
   819  	SGTU	R2, R1, R7
   820  	SUBU	R7, R6, R8
   821  cmp_ret:
   822  	MOVW	R8, ret+16(FP)
   823  	RET
   824  
   825  TEXT bytes·Compare(SB),NOSPLIT,$0-28
   826  	MOVW	s1_base+0(FP), R3
   827  	MOVW	s2_base+12(FP), R4
   828  	MOVW	s1_len+4(FP), R1
   829  	MOVW	s2_len+16(FP), R2
   830  	BEQ	R3, R4, samebytes
   831  	SGTU	R1, R2, R7
   832  	MOVW	R1, R8
   833  	CMOVN	R7, R2, R8	// R8 is min(R1, R2)
   834  
   835  	ADDU	R3, R8	// R3 is current byte in s1, R8 is last byte in s1 to compare
   836  loop:
   837  	BEQ	R3, R8, samebytes
   838  
   839  	MOVBU	(R3), R6
   840  	ADDU	$1, R3
   841  	MOVBU	(R4), R7
   842  	ADDU	$1, R4
   843  	BEQ	R6, R7 , loop
   844  
   845  	SGTU	R6, R7, R8
   846  	MOVW	$-1, R6
   847  	CMOVZ	R8, R6, R8
   848  	JMP	cmp_ret
   849  samebytes:
   850  	SGTU	R1, R2, R6
   851  	SGTU	R2, R1, R7
   852  	SUBU	R7, R6, R8
   853  cmp_ret:
   854  	MOVW	R8, ret+24(FP)
   855  	RET
   856  
   857  TEXT runtime·return0(SB),NOSPLIT,$0
   858  	MOVW	$0, R1
   859  	RET
   860  
   861  // Called from cgo wrappers, this function returns g->m->curg.stack.hi.
   862  // Must obey the gcc calling convention.
   863  TEXT _cgo_topofstack(SB),NOSPLIT,$-4
   864  	// g (R30), R3 and REGTMP (R23) might be clobbered by load_g. R30 and R23
   865  	// are callee-save in the gcc calling convention, so save them.
   866  	MOVW	R23, R8
   867  	MOVW	g, R9
   868  	MOVW	R31, R10 // this call frame does not save LR
   869  
   870  	JAL	runtime·load_g(SB)
   871  	MOVW	g_m(g), R1
   872  	MOVW	m_curg(R1), R1
   873  	MOVW	(g_stack+stack_hi)(R1), R2 // return value in R2
   874  
   875  	MOVW	R8, R23
   876  	MOVW	R9, g
   877  	MOVW	R10, R31
   878  
   879  	RET
   880  
   881  // The top-most function running on a goroutine
   882  // returns to goexit+PCQuantum.
   883  TEXT runtime·goexit(SB),NOSPLIT,$-4-0
   884  	NOR	R0, R0	// NOP
   885  	JAL	runtime·goexit1(SB)	// does not return
   886  	// traceback from goexit1 must hit code range of goexit
   887  	NOR	R0, R0	// NOP
   888  
   889  TEXT ·checkASM(SB),NOSPLIT,$0-1
   890  	MOVW	$1, R1
   891  	MOVB	R1, ret+0(FP)
   892  	RET