github.com/riscv/riscv-go@v0.0.0-20200123204226-124ebd6fcc8e/src/runtime/asm_riscv.s (about)

     1  // Copyright 2017 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 riscv
     6  
     7  #include "go_asm.h"
     8  #include "funcdata.h"
     9  #include "textflag.h"
    10  
    11  // func rt0_go()
    12  TEXT runtime·rt0_go(SB),NOSPLIT,$0
    13  	// X2 = stack; A0 = argc; A1 = argv
    14  
    15  	ADD	$-24, X2
    16  	MOV	A0, 8(X2) // argc
    17  	MOV	A1, 16(X2) // argv
    18  
    19  	// create istack out of the given (operating system) stack.
    20  	// _cgo_init may update stackguard.
    21  	MOV	$runtime·g0(SB), g
    22  	MOV	$(-64*1024), T0
    23  	ADD	T0, X2, T1
    24  	MOV	T1, g_stackguard0(g)
    25  	MOV	T1, g_stackguard1(g)
    26  	MOV	T1, (g_stack+stack_lo)(g)
    27  	MOV	X2, (g_stack+stack_hi)(g)
    28  
    29  	// if there is a _cgo_init, call it using the gcc ABI.
    30  	MOV	_cgo_init(SB), T0
    31  	BEQ	T0, ZERO, nocgo
    32  
    33  	MOV	ZERO, A3	// arg 3: not used
    34  	MOV	ZERO, A2	// arg 2: not used
    35  	MOV	$setg_gcc<>(SB), A1	// arg 1: setg
    36  	MOV	g, A0	// arg 0: G
    37  	JALR	RA, T0
    38  
    39  nocgo:
    40  	// update stackguard after _cgo_init
    41  	MOV	(g_stack+stack_lo)(g), T0
    42  	ADD	$const__StackGuard, T0
    43  	MOV	T0, g_stackguard0(g)
    44  	MOV	T0, g_stackguard1(g)
    45  
    46  	// set the per-goroutine and per-mach "registers"
    47  	MOV	$runtime·m0(SB), T0
    48  
    49  	// save m->g0 = g0
    50  	MOV	g, m_g0(T0)
    51  	// save m0 to g0->m
    52  	MOV	T0, g_m(g)
    53  
    54  	CALL	runtime·check(SB)
    55  
    56  	// args are already prepared
    57  	CALL	runtime·args(SB)
    58  	CALL	runtime·osinit(SB)
    59  	CALL	runtime·schedinit(SB)
    60  
    61  	// create a new goroutine to start program
    62  	MOV	$runtime·mainPC(SB), T0		// entry
    63  	ADD	$-24, X2
    64  	MOV	T0, 16(X2)
    65  	MOV	ZERO, 8(X2)
    66  	MOV	ZERO, 0(X2)
    67  	CALL	runtime·newproc(SB)
    68  	ADD	$24, X2
    69  
    70  	// start this M
    71  	CALL	runtime·mstart(SB)
    72  
    73  	WORD $0 // crash if reached
    74  	RET
    75  
    76  // void setg_gcc(G*); set g called from gcc with g in A0
    77  TEXT setg_gcc<>(SB),NOSPLIT,$0-0
    78  	MOV	A0, g
    79  	CALL	runtime·save_g(SB)
    80  	RET
    81  
    82  // func cputicks() int64
    83  TEXT runtime·cputicks(SB),NOSPLIT,$0-8
    84  	WORD	$0xc0102573	// rdtime a0
    85  	MOV	A0, ret+0(FP)
    86  	RET
    87  
    88  // systemstack_switch is a dummy routine that systemstack leaves at the bottom
    89  // of the G stack. We need to distinguish the routine that
    90  // lives at the bottom of the G stack from the one that lives
    91  // at the top of the system stack because the one at the top of
    92  // the system stack terminates the stack walk (see topofstack()).
    93  TEXT runtime·systemstack_switch(SB), NOSPLIT, $0-0
    94  	UNDEF
    95  	JALR	RA, ZERO	// make sure this function is not leaf
    96  	RET
    97  
    98  // func systemstack(fn func())
    99  TEXT runtime·systemstack(SB), NOSPLIT, $0-8
   100  	MOV	fn+0(FP), CTXT	// CTXT = fn
   101  	MOV	g_m(g), T0	// T0 = m
   102  
   103  	MOV	m_gsignal(T0), T1	// T1 = gsignal
   104  	BEQ	g, T1, noswitch
   105  
   106  	MOV	m_g0(T0), T1	// T1 = g0
   107  	BEQ	g, T1, noswitch
   108  
   109  	MOV	m_curg(T0), T2
   110  	BEQ	g, T2, switch
   111  
   112  	// Bad: g is not gsignal, not g0, not curg. What is it?
   113  	// Hide call from linker nosplit analysis.
   114  	MOV	$runtime·badsystemstack(SB), T1
   115  	JALR	RA, T1
   116  
   117  switch:
   118  	// save our state in g->sched. Pretend to
   119  	// be systemstack_switch if the G stack is scanned.
   120  	MOV	$runtime·systemstack_switch(SB), T2
   121  	ADD	$8, T2	// get past prologue
   122  	MOV	T2, (g_sched+gobuf_pc)(g)
   123  	MOV	X2, (g_sched+gobuf_sp)(g)
   124  	MOV	ZERO, (g_sched+gobuf_lr)(g)
   125  	MOV	g, (g_sched+gobuf_g)(g)
   126  
   127  	// switch to g0
   128  	MOV	T1, g
   129  	CALL	runtime·save_g(SB)
   130  	MOV	(g_sched+gobuf_sp)(g), T0
   131  	// make it look like mstart called systemstack on g0, to stop traceback
   132  	ADD	$-16, T0
   133  	AND	$~15, T0
   134  	MOV	$runtime·mstart(SB), T1
   135  	MOV	T1, 0(T0)
   136  	MOV	T0, X2
   137  
   138  	// call target function
   139  	MOV	0(CTXT), T1	// code pointer
   140  	JALR	RA, T1
   141  
   142  	// switch back to g
   143  	MOV	g_m(g), T0
   144  	MOV	m_curg(T0), g
   145  	CALL	runtime·save_g(SB)
   146  	MOV	(g_sched+gobuf_sp)(g), X2
   147  	MOV	ZERO, (g_sched+gobuf_sp)(g)
   148  	RET
   149  
   150  noswitch:
   151  	// already on m stack, just call directly
   152  	MOV	0(CTXT), T1	// code pointer
   153  	JALR	RA, T1
   154  	RET
   155  
   156  // func getcallerpc(argp unsafe.Pointer) uintptr
   157  TEXT runtime·getcallerpc(SB),NOSPLIT,$8-16
   158  	MOV	16(X2), T0		// LR saved by caller
   159  	MOV	runtime·stackBarrierPC(SB), T1
   160  	BNE	T0, T1, nobar
   161  	// Get original return PC.
   162  	CALL	runtime·nextBarrierPC(SB)
   163  	MOV	8(X2), T0
   164  nobar:
   165  	MOV	T0, ret+8(FP)
   166  	RET
   167  
   168  // func fastrand() uint32
   169  TEXT runtime·fastrand(SB),NOSPLIT,$0-4
   170  	MOV	g_m(g), A2
   171  	MOVWU	m_fastrand(A2), A1
   172  	ADD	A1, A1
   173  	// TODO(sorear): Just use ADDW once an encoding is added
   174  	SLL	$32, A1
   175  	SRA	$32, A1
   176  	BGE	A1, ZERO, noxor
   177  	MOV	$0x88888eef - 1<<32, A0
   178  	XOR	A0, A1
   179  noxor:
   180  	MOVW	A1, m_fastrand(A2)
   181  	MOVW	A1, ret+0(FP)
   182  	RET
   183  
   184  // eqstring tests whether two strings are equal.
   185  // The compiler guarantees that strings passed
   186  // to eqstring have equal length.
   187  // See runtime_test.go:eqstring_generic for
   188  // equivalent Go code.
   189  
   190  // func eqstring(s1, s2 string) bool
   191  TEXT runtime·eqstring(SB),NOSPLIT,$0-33
   192  	MOV	s1_base+0(FP), T0
   193  	MOV	s2_base+16(FP), T1
   194  	MOV	$1, T2
   195  	MOVB	T2, ret+32(FP)
   196  	BNE	T0, T1, diff_len
   197  	RET
   198  diff_len:
   199  	MOV	s1_len+8(FP), T2
   200  	ADD	T0, T2, T3
   201  loop:
   202  	BNE	T0, T3, 2(PC)
   203  	RET
   204  	MOVBU	(T0), T5
   205  	ADD	$1, T0
   206  	MOVBU	(T1), T6
   207  	ADD	$1, T1
   208  	BEQ	T5, T6, loop
   209  	MOVB	ZERO, ret+32(FP)
   210  	RET
   211  
   212  /*
   213   * support for morestack
   214   */
   215  
   216  // Called during function prolog when more stack is needed.
   217  // Caller has already loaded:
   218  // R1: framesize, R2: argsize, R3: LR
   219  //
   220  // The traceback routines see morestack on a g0 as being
   221  // the top of a stack (for example, morestack calling newstack
   222  // calling the scheduler calling newm calling gc), so we must
   223  // record an argument size. For that purpose, it has no arguments.
   224  
   225  // func morestack()
   226  TEXT runtime·morestack(SB),NOSPLIT,$-8-0
   227  	// Cannot grow scheduler stack (m->g0).
   228  	MOV	g_m(g), A0
   229  	MOV	m_g0(A0), A1
   230  	BNE	g, A1, 3(PC)
   231  	CALL	runtime·badmorestackg0(SB)
   232  	CALL	runtime·abort(SB)
   233  
   234  	// Cannot grow signal stack (m->gsignal).
   235  	MOV	m_gsignal(A0), A1
   236  	BNE	g, A1, 3(PC)
   237  	CALL	runtime·badmorestackgsignal(SB)
   238  	CALL	runtime·abort(SB)
   239  
   240  	// Called from f.
   241  	// Set g->sched to context in f.
   242  	MOV	X2, (g_sched+gobuf_sp)(g)
   243  	MOV	T0, (g_sched+gobuf_pc)(g)
   244  	MOV	RA, (g_sched+gobuf_lr)(g)
   245  	// newstack will fill gobuf.ctxt.
   246  
   247  	// Called from f.
   248  	// Set m->morebuf to f's caller.
   249  	MOV	RA, (m_morebuf+gobuf_pc)(A0)	// f's caller's PC
   250  	MOV	X2, (m_morebuf+gobuf_sp)(A0)	// f's caller's SP
   251  	MOV	g, (m_morebuf+gobuf_g)(A0)
   252  
   253  	// Call newstack on m->g0's stack.
   254  	MOV	m_g0(A0), g
   255  	CALL	runtime·save_g(SB)
   256  	MOV	(g_sched+gobuf_sp)(g), X2
   257  	// Create a stack frame on g0 to call newstack.
   258  	MOV	ZERO, -16(X2)	// Zero saved LR in frame
   259  	ADD	$-16, X2
   260  	MOV	CTXT, 8(X2)	// ctxt argument
   261  	CALL	runtime·newstack(SB)
   262  
   263  	// Not reached, but make sure the return PC from the call to newstack
   264  	// is still in this function, and not the beginning of the next.
   265  	UNDEF
   266  
   267  // func morestack_noctxt()
   268  TEXT runtime·morestack_noctxt(SB),NOSPLIT,$-8-0
   269  	MOV	ZERO, CTXT
   270  	JMP	runtime·morestack(SB)
   271  
   272  // func return0()
   273  TEXT runtime·return0(SB), NOSPLIT, $0
   274  	MOV	$0, A0
   275  	RET
   276  
   277  // func memequal(a, b unsafe.Pointer, size uintptr) bool
   278  TEXT runtime·memequal(SB),NOSPLIT,$-8-25
   279  	MOV	a+0(FP), A1
   280  	MOV	b+8(FP), A2
   281  	BEQ	A1, A2, eq
   282  	MOV	size+16(FP), A3
   283  	ADD	A1, A3, A4
   284  loop:
   285  	BNE	A1, A4, test
   286  	MOV	$1, A1
   287  	MOVB	A1, ret+24(FP)
   288  	RET
   289  test:
   290  	MOVBU	(A1), A6
   291  	ADD	$1, A1
   292  	MOVBU	(A2), A7
   293  	ADD	$1, A2
   294  	BEQ	A6, A7, loop
   295  
   296  	MOVB	ZERO, ret+24(FP)
   297  	RET
   298  eq:
   299  	MOV	$1, A1
   300  	MOVB	A1, ret+24(FP)
   301  	RET
   302  
   303  // func memequal_varlen(a, b unsafe.Pointer) bool
   304  TEXT runtime·memequal_varlen(SB),NOSPLIT,$40-17
   305  	MOV	a+0(FP), A1
   306  	MOV	b+8(FP), A2
   307  	BEQ	A1, A2, eq
   308  	MOV	8(CTXT), A3    // compiler stores size at offset 8 in the closure
   309  	MOV	A1, 8(X2)
   310  	MOV	A2, 16(X2)
   311  	MOV	A3, 24(X2)
   312  	CALL	runtime·memequal(SB)
   313  	MOVBU	32(X2), A1
   314  	MOVB	A1, ret+16(FP)
   315  	RET
   316  eq:
   317  	MOV	$1, A1
   318  	MOVB	A1, ret+16(FP)
   319  	RET
   320  
   321  // restore state from Gobuf; longjmp
   322  
   323  // func gogo(buf *gobuf)
   324  TEXT runtime·gogo(SB), NOSPLIT, $16-8
   325  	MOV	buf+0(FP), T0
   326  
   327  	// If ctxt is not nil, invoke deletion barrier before overwriting.
   328  	MOV	gobuf_ctxt(T0), T1
   329  	BEQ	T1, ZERO, nilctxt
   330  	ADD	$gobuf_ctxt, T0, T1
   331  	MOV	T1, 8(X2)
   332  	MOV	ZERO, 16(X2)
   333  	CALL	runtime·writebarrierptr_prewrite(SB)
   334  	MOV	buf+0(FP), T0
   335  
   336  nilctxt:
   337  	MOV	gobuf_g(T0), g	// make sure g is not nil
   338  	CALL	runtime·save_g(SB)
   339  
   340  	MOV	(g), ZERO // make sure g is not nil
   341  	MOV	gobuf_sp(T0), X2
   342  	MOV	gobuf_lr(T0), RA
   343  	MOV	gobuf_ret(T0), A0
   344  	MOV	gobuf_ctxt(T0), CTXT
   345  	MOV	ZERO, gobuf_sp(T0)
   346  	MOV	ZERO, gobuf_ret(T0)
   347  	MOV	ZERO, gobuf_lr(T0)
   348  	MOV	ZERO, gobuf_ctxt(T0)
   349  	MOV	gobuf_pc(T0), T0
   350  	JALR	ZERO, T0
   351  
   352  // func jmpdefer(fv *funcval, argp uintptr)
   353  // called from deferreturn
   354  // 1. grab stored return address from the caller's frame
   355  // 2. sub 12 bytes to get back to JAL deferreturn
   356  // 3. JMP to fn
   357  // TODO(sorear): There are shorter jump sequences.  This function will need to be updated when we use them.
   358  TEXT runtime·jmpdefer(SB), NOSPLIT, $-8-16
   359  	MOV	0(X2), RA
   360  	ADD	$-12, RA
   361  
   362  	MOV	fv+0(FP), CTXT
   363  	MOV	argp+8(FP), X2
   364  	ADD	$-8, X2
   365  	MOV	0(CTXT), T0
   366  	JALR	ZERO, T0
   367  
   368  // func procyield(cycles uint32)
   369  TEXT runtime·procyield(SB),NOSPLIT,$0-0
   370  	RET
   371  
   372  // Switch to m->g0's stack, call fn(g).
   373  // Fn must never return. It should gogo(&g->sched)
   374  // to keep running g.
   375  
   376  // func mcall(fn func(*g))
   377  TEXT runtime·mcall(SB), NOSPLIT, $-8-8
   378  	// Save caller state in g->sched
   379  	MOV	X2, (g_sched+gobuf_sp)(g)
   380  	MOV	RA, (g_sched+gobuf_pc)(g)
   381  	MOV	ZERO, (g_sched+gobuf_lr)(g)
   382  	MOV	g, (g_sched+gobuf_g)(g)
   383  
   384  	// Switch to m->g0 & its stack, call fn.
   385  	MOV	g, T0
   386  	MOV	g_m(g), T1
   387  	MOV	m_g0(T1), g
   388  	CALL	runtime·save_g(SB)
   389  	BNE	g, T0, 2(PC)
   390  	JMP	runtime·badmcall(SB)
   391  	MOV	fn+0(FP), CTXT			// context
   392  	MOV	0(CTXT), T1			// code pointer
   393  	MOV	(g_sched+gobuf_sp)(g), X2	// sp = m->g0->sched.sp
   394  	ADD	$-16, X2
   395  	MOV	T0, 8(X2)
   396  	MOV	ZERO, 0(X2)
   397  	JALR	RA, T1
   398  	JMP	runtime·badmcall2(SB)
   399  
   400  // func gosave(buf *gobuf)
   401  // save state in Gobuf; setjmp
   402  TEXT runtime·gosave(SB), NOSPLIT, $-8-8
   403  	MOV	buf+0(FP), T1
   404  	MOV	X2, gobuf_sp(T1)
   405  	MOV	RA, gobuf_pc(T1)
   406  	MOV	g, gobuf_g(T1)
   407  	MOV	ZERO, gobuf_lr(T1)
   408  	MOV	ZERO, gobuf_ret(T1)
   409  	// Assert ctxt is zero. See func save.
   410  	MOV	gobuf_ctxt(T1), T1
   411  	BEQ	T1, ZERO, 2(PC)
   412  	CALL	runtime·badctxt(SB)
   413  	RET
   414  
   415  // func asmcgocall(fn, arg unsafe.Pointer) int32
   416  TEXT ·asmcgocall(SB),NOSPLIT,$0-12
   417  	WORD $0
   418  
   419  // redirects to memhash(p, h, size) using the size
   420  // stored in the closure.
   421  
   422  // func memhash_varlen(p unsafe.Pointer, h uintptr) uintptr
   423  TEXT runtime·memhash_varlen(SB),NOSPLIT,$40-24
   424  	GO_ARGS
   425  	NO_LOCAL_POINTERS
   426  	MOV	p+0(FP), A1
   427  	MOV	h+8(FP), A2
   428  	MOV	8(CTXT), A3
   429  	MOV	A1, 8(X2)
   430  	MOV	A2, 16(X2)
   431  	MOV	A3, 24(X2)
   432  	CALL	runtime·memhash(SB)
   433  	MOV	32(X2), A1
   434  	MOV	A1, ret+16(FP)
   435  	RET
   436  
   437  // func asminit()
   438  TEXT runtime·asminit(SB),NOSPLIT,$-8-0
   439  	RET
   440  
   441  // reflectcall: call a function with the given argument list
   442  // func call(argtype *_type, f *FuncVal, arg *byte, argsize, retoffset uint32).
   443  // we don't have variable-sized frames, so we use a small number
   444  // of constant-sized-frame functions to encode a few bits of size in the pc.
   445  // Caution: ugly multiline assembly macros in your future!
   446  
   447  #define DISPATCH(NAME,MAXSIZE)	\
   448  	MOV	$MAXSIZE, T1	\
   449  	BLTU	T1, T0, 3(PC)	\
   450  	MOV	$NAME(SB), T2;	\
   451  	JALR	ZERO, T2
   452  // Note: can't just "BR NAME(SB)" - bad inlining results.
   453  
   454  // func call(argtype *rtype, fn, arg unsafe.Pointer, n uint32, retoffset uint32)
   455  TEXT reflect·call(SB), NOSPLIT, $0-0
   456  	JMP	·reflectcall(SB)
   457  
   458  // func reflectcall(argtype *_type, fn, arg unsafe.Pointer, argsize uint32, retoffset uint32)
   459  TEXT ·reflectcall(SB), NOSPLIT, $-8-32
   460  	MOVWU argsize+24(FP), T0
   461  	DISPATCH(runtime·call32, 32)
   462  	DISPATCH(runtime·call64, 64)
   463  	DISPATCH(runtime·call128, 128)
   464  	DISPATCH(runtime·call256, 256)
   465  	DISPATCH(runtime·call512, 512)
   466  	DISPATCH(runtime·call1024, 1024)
   467  	DISPATCH(runtime·call2048, 2048)
   468  	DISPATCH(runtime·call4096, 4096)
   469  	DISPATCH(runtime·call8192, 8192)
   470  	DISPATCH(runtime·call16384, 16384)
   471  	DISPATCH(runtime·call32768, 32768)
   472  	DISPATCH(runtime·call65536, 65536)
   473  	DISPATCH(runtime·call131072, 131072)
   474  	DISPATCH(runtime·call262144, 262144)
   475  	DISPATCH(runtime·call524288, 524288)
   476  	DISPATCH(runtime·call1048576, 1048576)
   477  	DISPATCH(runtime·call2097152, 2097152)
   478  	DISPATCH(runtime·call4194304, 4194304)
   479  	DISPATCH(runtime·call8388608, 8388608)
   480  	DISPATCH(runtime·call16777216, 16777216)
   481  	DISPATCH(runtime·call33554432, 33554432)
   482  	DISPATCH(runtime·call67108864, 67108864)
   483  	DISPATCH(runtime·call134217728, 134217728)
   484  	DISPATCH(runtime·call268435456, 268435456)
   485  	DISPATCH(runtime·call536870912, 536870912)
   486  	DISPATCH(runtime·call1073741824, 1073741824)
   487  	MOV	$runtime·badreflectcall(SB), T2
   488  	JALR	ZERO, T2
   489  
   490  #define CALLFN(NAME,MAXSIZE)			\
   491  TEXT NAME(SB), WRAPPER, $MAXSIZE-24;		\
   492  	NO_LOCAL_POINTERS;			\
   493  	/* copy arguments to stack */		\
   494  	MOV	arg+16(FP), A1;			\
   495  	MOVWU	argsize+24(FP), A2;		\
   496  	MOV	X2, A3;				\
   497  	ADD	$8, A3;				\
   498  	ADD	A3, A2;				\
   499  	BEQ	A3, A2, 6(PC);			\
   500  	MOVBU	(A1), A4;			\
   501  	ADD	$1, A1;				\
   502  	MOVB	A4, (A3);			\
   503  	ADD	$1, A3;				\
   504  	JMP	-5(PC);				\
   505  	/* call function */			\
   506  	MOV	f+8(FP), CTXT;			\
   507  	MOV	(CTXT), A4;			\
   508  	PCDATA  $PCDATA_StackMapIndex, $0;	\
   509  	JALR	RA, A4;				\
   510  	/* copy return values back */		\
   511  	MOV	argtype+0(FP), A5;		\
   512  	MOV	arg+16(FP), A1;			\
   513  	MOVWU	n+24(FP), A2;			\
   514  	MOVWU	retoffset+28(FP), A4;		\
   515  	ADD	$8, X2, A3;			\
   516  	ADD	A4, A3; 			\
   517  	ADD	A4, A1;				\
   518  	SUB	A4, A2;				\
   519  	CALL	callRet<>(SB);			\
   520  	RET
   521  
   522  // callRet copies return values back at the end of call*. This is a
   523  // separate function so it can allocate stack space for the arguments
   524  // to reflectcallmove. It does not follow the Go ABI; it expects its
   525  // arguments in registers.
   526  TEXT callRet<>(SB), NOSPLIT, $32-0
   527  	MOV	A5, 8(X2)
   528  	MOV	A1, 16(X2)
   529  	MOV	A3, 24(X2)
   530  	MOV	A2, 32(X2)
   531  	CALL	runtime·reflectcallmove(SB)
   532  	RET
   533  
   534  CALLFN(·call16, 16)
   535  CALLFN(·call32, 32)
   536  CALLFN(·call64, 64)
   537  CALLFN(·call128, 128)
   538  CALLFN(·call256, 256)
   539  CALLFN(·call512, 512)
   540  CALLFN(·call1024, 1024)
   541  CALLFN(·call2048, 2048)
   542  CALLFN(·call4096, 4096)
   543  CALLFN(·call8192, 8192)
   544  CALLFN(·call16384, 16384)
   545  CALLFN(·call32768, 32768)
   546  CALLFN(·call65536, 65536)
   547  CALLFN(·call131072, 131072)
   548  CALLFN(·call262144, 262144)
   549  CALLFN(·call524288, 524288)
   550  CALLFN(·call1048576, 1048576)
   551  CALLFN(·call2097152, 2097152)
   552  CALLFN(·call4194304, 4194304)
   553  CALLFN(·call8388608, 8388608)
   554  CALLFN(·call16777216, 16777216)
   555  CALLFN(·call33554432, 33554432)
   556  CALLFN(·call67108864, 67108864)
   557  CALLFN(·call134217728, 134217728)
   558  CALLFN(·call268435456, 268435456)
   559  CALLFN(·call536870912, 536870912)
   560  CALLFN(·call1073741824, 1073741824)
   561  
   562  // func goexit(neverCallThisFunction)
   563  // The top-most function running on a goroutine
   564  // returns to goexit+PCQuantum.
   565  TEXT runtime·goexit(SB),NOSPLIT,$-8-0
   566  	MOV	ZERO, ZERO	// NOP
   567  	CALL	runtime·goexit1(SB)	// does not return
   568  	// traceback from goexit1 must hit code range of goexit
   569  	MOV	ZERO, ZERO	// NOP
   570  
   571  // func setcallerpc(argp unsafe.Pointer, pc uintptr)
   572  TEXT runtime·setcallerpc(SB),NOSPLIT,$8-16
   573  	MOV	pc+8(FP), A1
   574  	MOV	16(X2), A2
   575  	MOV	runtime·stackBarrierPC(SB), A3
   576  	BEQ	A2, A3, setbar
   577  	MOV	A1, 16(X2)		// set LR in caller
   578  	RET
   579  setbar:
   580  	// Set the stack barrier return PC.
   581  	MOV	A1, 8(X2)
   582  	CALL	runtime·setNextBarrierPC(SB)
   583  	RET
   584  
   585  // func IndexByte(s []byte, c byte) int
   586  TEXT bytes·IndexByte(SB),NOSPLIT,$0-40
   587  	MOV	s+0(FP), A1
   588  	MOV	s_len+8(FP), A2
   589  	MOVBU	c+24(FP), A3	// byte to find
   590  	MOV	A1, A4		// store base for later
   591  	ADD	A1, A2		// end
   592  	ADD	$-1, A1
   593  
   594  loop:
   595  	ADD	$1, A1
   596  	BEQ	A1, A2, notfound
   597  	MOVBU	(A1), A5
   598  	BNE	A3, A5, loop
   599  
   600  	SUB	A4, A1		// remove base
   601  	MOV	A1, ret+32(FP)
   602  	RET
   603  
   604  notfound:
   605  	MOV	$-1, A1
   606  	MOV	A1, ret+32(FP)
   607  	RET
   608  
   609  // func IndexByte(s string, c byte) int
   610  TEXT strings·IndexByte(SB),NOSPLIT,$0-32
   611  	MOV	p+0(FP), A1
   612  	MOV	b_len+8(FP), A2
   613  	MOVBU	c+16(FP), A3	// byte to find
   614  	MOV	A1, A4		// store base for later
   615  	ADD	A1, A2		// end
   616  	ADD	$-1, A1
   617  
   618  loop:
   619  	ADD	$1, A1
   620  	BEQ	A1, A2, notfound
   621  	MOVBU	(A1), A5
   622  	BNE	A3, A5, loop
   623  
   624  	SUB	A4, A1		// remove base
   625  	MOV	A1, ret+24(FP)
   626  	RET
   627  
   628  notfound:
   629  	MOV	$-1, A1
   630  	MOV	A1, ret+24(FP)
   631  	RET
   632  
   633  // TODO: share code with memequal?
   634  // func Equal(a, b []byte) bool
   635  TEXT bytes·Equal(SB),NOSPLIT,$0-49
   636  	MOV	a_len+8(FP), A3
   637  	MOV	b_len+32(FP), A4
   638  	BNE	A3, A4, noteq		// unequal lengths are not equal
   639  
   640  	MOV	a+0(FP), A1
   641  	MOV	b+24(FP), A2
   642  	ADD	A1, A3		// end
   643  
   644  loop:
   645  	BEQ	A1, A3, equal		// reached the end
   646  	MOVBU	(A1), A6
   647  	ADD	$1, A1
   648  	MOVBU	(A2), A7
   649  	ADD	$1, A2
   650  	BEQ	A6, A7, loop
   651  
   652  noteq:
   653  	MOVB	ZERO, ret+48(FP)
   654  	RET
   655  
   656  equal:
   657  	MOV	$1, A1
   658  	MOVB	A1, ret+48(FP)
   659  	RET
   660  
   661  TEXT runtime·stackBarrier(SB),NOSPLIT,$0
   662  	WORD $0
   663  
   664  // func cgocallback_gofunc(fv uintptr, frame uintptr, framesize, ctxt uintptr)
   665  TEXT ·cgocallback_gofunc(SB),NOSPLIT,$24-32
   666  	WORD $0
   667  
   668  TEXT runtime·prefetcht0(SB),NOSPLIT,$0-8
   669  	RET
   670  
   671  TEXT runtime·prefetcht1(SB),NOSPLIT,$0-8
   672  	RET
   673  
   674  TEXT runtime·prefetcht2(SB),NOSPLIT,$0-8
   675  	RET
   676  
   677  TEXT runtime·prefetchnta(SB),NOSPLIT,$0-8
   678  	RET
   679  
   680  TEXT runtime·breakpoint(SB),NOSPLIT,$-8-0
   681  	EBREAK
   682  	RET
   683  
   684  TEXT runtime·abort(SB),NOSPLIT,$-8-0
   685  	EBREAK
   686  	RET
   687  
   688  // void setg(G*); set g. for use by needm.
   689  TEXT runtime·setg(SB), NOSPLIT, $0-8
   690  	MOV	gg+0(FP), g
   691  	// This only happens if iscgo, so jump straight to save_g
   692  	CALL	runtime·save_g(SB)
   693  	RET
   694  
   695  TEXT ·checkASM(SB),NOSPLIT,$0-1
   696  	MOV	$1, T0
   697  	MOV	T0, ret+0(FP)
   698  	RET
   699  
   700  DATA	runtime·mainPC+0(SB)/8,$runtime·main(SB)
   701  GLOBL	runtime·mainPC(SB),RODATA,$8