github.com/q45/go@v0.0.0-20151101211701-a4fb8c13db3f/src/runtime/asm_ppc64x.s (about)

     1  // Copyright 2014 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 ppc64 ppc64le
     6  
     7  #include "go_asm.h"
     8  #include "go_tls.h"
     9  #include "funcdata.h"
    10  #include "textflag.h"
    11  #include "asm_ppc64x.h"
    12  
    13  TEXT runtime·rt0_go(SB),NOSPLIT,$0
    14  	// R1 = stack; R3 = argc; R4 = argv; R13 = C TLS base pointer
    15  
    16  	// initialize essential registers
    17  	BL	runtime·reginit(SB)
    18  
    19  	SUB	$(FIXED_FRAME+16), R1
    20  	MOVW	R3, FIXED_FRAME+0(R1) // argc
    21  	MOVD	R4, FIXED_FRAME+8(R1) // argv
    22  
    23  	// create istack out of the given (operating system) stack.
    24  	// _cgo_init may update stackguard.
    25  	MOVD	$runtime·g0(SB), g
    26  	MOVD	$(-64*1024), R31
    27  	ADD	R31, R1, R3
    28  	MOVD	R3, g_stackguard0(g)
    29  	MOVD	R3, g_stackguard1(g)
    30  	MOVD	R3, (g_stack+stack_lo)(g)
    31  	MOVD	R1, (g_stack+stack_hi)(g)
    32  
    33  	// if there is a _cgo_init, call it using the gcc ABI.
    34  	MOVD	_cgo_init(SB), R12
    35  	CMP	R0, R12
    36  	BEQ	nocgo
    37  	MOVD	R12, CTR		// r12 = "global function entry point"
    38  	MOVD	R13, R5			// arg 2: TLS base pointer
    39  	MOVD	$setg_gcc<>(SB), R4 	// arg 1: setg
    40  	MOVD	g, R3			// arg 0: G
    41  	// C functions expect 32 bytes of space on caller stack frame
    42  	// and a 16-byte aligned R1
    43  	MOVD	R1, R14			// save current stack
    44  	SUB	$32, R1			// reserve 32 bytes
    45  	RLDCR	$0, R1, $~15, R1	// 16-byte align
    46  	BL	(CTR)			// may clobber R0, R3-R12
    47  	MOVD	R14, R1			// restore stack
    48  	XOR	R0, R0			// fix R0
    49  
    50  nocgo:
    51  	// update stackguard after _cgo_init
    52  	MOVD	(g_stack+stack_lo)(g), R3
    53  	ADD	$const__StackGuard, R3
    54  	MOVD	R3, g_stackguard0(g)
    55  	MOVD	R3, g_stackguard1(g)
    56  
    57  	// set the per-goroutine and per-mach "registers"
    58  	MOVD	$runtime·m0(SB), R3
    59  
    60  	// save m->g0 = g0
    61  	MOVD	g, m_g0(R3)
    62  	// save m0 to g0->m
    63  	MOVD	R3, g_m(g)
    64  
    65  	BL	runtime·check(SB)
    66  
    67  	// args are already prepared
    68  	BL	runtime·args(SB)
    69  	BL	runtime·osinit(SB)
    70  	BL	runtime·schedinit(SB)
    71  
    72  	// create a new goroutine to start program
    73  	MOVD	$runtime·mainPC(SB), R3		// entry
    74  	MOVDU	R3, -8(R1)
    75  	MOVDU	R0, -8(R1)
    76  	MOVDU	R0, -8(R1)
    77  	BL	runtime·newproc(SB)
    78  	ADD	$24, R1
    79  
    80  	// start this M
    81  	BL	runtime·mstart(SB)
    82  
    83  	MOVD	R0, 1(R0)
    84  	RET
    85  
    86  DATA	runtime·mainPC+0(SB)/8,$runtime·main(SB)
    87  GLOBL	runtime·mainPC(SB),RODATA,$8
    88  
    89  TEXT runtime·breakpoint(SB),NOSPLIT|NOFRAME,$0-0
    90  	MOVD	R0, 2(R0) // TODO: TD
    91  	RET
    92  
    93  TEXT runtime·asminit(SB),NOSPLIT|NOFRAME,$0-0
    94  	RET
    95  
    96  TEXT _cgo_reginit(SB),NOSPLIT|NOFRAME,$0-0
    97  	// crosscall_ppc64 and crosscall2 need to reginit, but can't
    98  	// get at the 'runtime.reginit' symbol.
    99  	BR	runtime·reginit(SB)
   100  
   101  TEXT runtime·reginit(SB),NOSPLIT|NOFRAME,$0-0
   102  	// set R0 to zero, it's expected by the toolchain
   103  	XOR R0, R0
   104  	// initialize essential FP registers
   105  	FMOVD	$4503601774854144.0, F27
   106  	FMOVD	$0.5, F29
   107  	FSUB	F29, F29, F28
   108  	FADD	F29, F29, F30
   109  	FADD	F30, F30, F31
   110  	RET
   111  
   112  /*
   113   *  go-routine
   114   */
   115  
   116  // void gosave(Gobuf*)
   117  // save state in Gobuf; setjmp
   118  TEXT runtime·gosave(SB), NOSPLIT|NOFRAME, $0-8
   119  	MOVD	buf+0(FP), R3
   120  	MOVD	R1, gobuf_sp(R3)
   121  	MOVD	LR, R31
   122  	MOVD	R31, gobuf_pc(R3)
   123  	MOVD	g, gobuf_g(R3)
   124  	MOVD	R0, gobuf_lr(R3)
   125  	MOVD	R0, gobuf_ret(R3)
   126  	MOVD	R0, gobuf_ctxt(R3)
   127  	RET
   128  
   129  // void gogo(Gobuf*)
   130  // restore state from Gobuf; longjmp
   131  TEXT runtime·gogo(SB), NOSPLIT|NOFRAME, $0-8
   132  	MOVD	buf+0(FP), R5
   133  	MOVD	gobuf_g(R5), g	// make sure g is not nil
   134  	BL	runtime·save_g(SB)
   135  
   136  	MOVD	0(g), R4
   137  	MOVD	gobuf_sp(R5), R1
   138  	MOVD	gobuf_lr(R5), R31
   139  	MOVD	R31, LR
   140  	MOVD	gobuf_ret(R5), R3
   141  	MOVD	gobuf_ctxt(R5), R11
   142  	MOVD	R0, gobuf_sp(R5)
   143  	MOVD	R0, gobuf_ret(R5)
   144  	MOVD	R0, gobuf_lr(R5)
   145  	MOVD	R0, gobuf_ctxt(R5)
   146  	CMP	R0, R0 // set condition codes for == test, needed by stack split
   147  	MOVD	gobuf_pc(R5), R12
   148  	MOVD	R12, CTR
   149  	BR	(CTR)
   150  
   151  // void mcall(fn func(*g))
   152  // Switch to m->g0's stack, call fn(g).
   153  // Fn must never return.  It should gogo(&g->sched)
   154  // to keep running g.
   155  TEXT runtime·mcall(SB), NOSPLIT|NOFRAME, $0-8
   156  	// Save caller state in g->sched
   157  	MOVD	R1, (g_sched+gobuf_sp)(g)
   158  	MOVD	LR, R31
   159  	MOVD	R31, (g_sched+gobuf_pc)(g)
   160  	MOVD	R0, (g_sched+gobuf_lr)(g)
   161  	MOVD	g, (g_sched+gobuf_g)(g)
   162  
   163  	// Switch to m->g0 & its stack, call fn.
   164  	MOVD	g, R3
   165  	MOVD	g_m(g), R8
   166  	MOVD	m_g0(R8), g
   167  	BL	runtime·save_g(SB)
   168  	CMP	g, R3
   169  	BNE	2(PC)
   170  	BR	runtime·badmcall(SB)
   171  	MOVD	fn+0(FP), R11			// context
   172  	MOVD	0(R11), R12			// code pointer
   173  	MOVD	R12, CTR
   174  	MOVD	(g_sched+gobuf_sp)(g), R1	// sp = m->g0->sched.sp
   175  	MOVDU	R3, -8(R1)
   176  	MOVDU	R0, -8(R1)
   177  	BL	(CTR)
   178  	BR	runtime·badmcall2(SB)
   179  
   180  // systemstack_switch is a dummy routine that systemstack leaves at the bottom
   181  // of the G stack.  We need to distinguish the routine that
   182  // lives at the bottom of the G stack from the one that lives
   183  // at the top of the system stack because the one at the top of
   184  // the system stack terminates the stack walk (see topofstack()).
   185  TEXT runtime·systemstack_switch(SB), NOSPLIT, $0-0
   186  	UNDEF
   187  	BL	(LR)	// make sure this function is not leaf
   188  	RET
   189  
   190  // func systemstack(fn func())
   191  TEXT runtime·systemstack(SB), NOSPLIT, $0-8
   192  	MOVD	fn+0(FP), R3	// R3 = fn
   193  	MOVD	R3, R11		// context
   194  	MOVD	g_m(g), R4	// R4 = m
   195  
   196  	MOVD	m_gsignal(R4), R5	// R5 = gsignal
   197  	CMP	g, R5
   198  	BEQ	noswitch
   199  
   200  	MOVD	m_g0(R4), R5	// R5 = g0
   201  	CMP	g, R5
   202  	BEQ	noswitch
   203  
   204  	MOVD	m_curg(R4), R6
   205  	CMP	g, R6
   206  	BEQ	switch
   207  
   208  	// Bad: g is not gsignal, not g0, not curg. What is it?
   209  	// Hide call from linker nosplit analysis.
   210  	MOVD	$runtime·badsystemstack(SB), R12
   211  	MOVD	R12, CTR
   212  	BL	(CTR)
   213  
   214  switch:
   215  	// save our state in g->sched.  Pretend to
   216  	// be systemstack_switch if the G stack is scanned.
   217  	MOVD	$runtime·systemstack_switch(SB), R6
   218  	ADD	$8, R6	// get past prologue
   219  	MOVD	R6, (g_sched+gobuf_pc)(g)
   220  	MOVD	R1, (g_sched+gobuf_sp)(g)
   221  	MOVD	R0, (g_sched+gobuf_lr)(g)
   222  	MOVD	g, (g_sched+gobuf_g)(g)
   223  
   224  	// switch to g0
   225  	MOVD	R5, g
   226  	BL	runtime·save_g(SB)
   227  	MOVD	(g_sched+gobuf_sp)(g), R3
   228  	// make it look like mstart called systemstack on g0, to stop traceback
   229  	SUB	$FIXED_FRAME, R3
   230  	MOVD	$runtime·mstart(SB), R4
   231  	MOVD	R4, 0(R3)
   232  	MOVD	R3, R1
   233  
   234  	// call target function
   235  	MOVD	0(R11), R12	// code pointer
   236  	MOVD	R12, CTR
   237  	BL	(CTR)
   238  
   239  	// switch back to g
   240  	MOVD	g_m(g), R3
   241  	MOVD	m_curg(R3), g
   242  	BL	runtime·save_g(SB)
   243  	MOVD	(g_sched+gobuf_sp)(g), R1
   244  	MOVD	R0, (g_sched+gobuf_sp)(g)
   245  	RET
   246  
   247  noswitch:
   248  	// already on m stack, just call directly
   249  	MOVD	0(R11), R12	// code pointer
   250  	MOVD	R12, CTR
   251  	BL	(CTR)
   252  	RET
   253  
   254  /*
   255   * support for morestack
   256   */
   257  
   258  // Called during function prolog when more stack is needed.
   259  // Caller has already loaded:
   260  // R3: framesize, R4: argsize, R5: LR
   261  //
   262  // The traceback routines see morestack on a g0 as being
   263  // the top of a stack (for example, morestack calling newstack
   264  // calling the scheduler calling newm calling gc), so we must
   265  // record an argument size. For that purpose, it has no arguments.
   266  TEXT runtime·morestack(SB),NOSPLIT|NOFRAME,$0-0
   267  	// Cannot grow scheduler stack (m->g0).
   268  	MOVD	g_m(g), R7
   269  	MOVD	m_g0(R7), R8
   270  	CMP	g, R8
   271  	BNE	2(PC)
   272  	BL	runtime·abort(SB)
   273  
   274  	// Cannot grow signal stack (m->gsignal).
   275  	MOVD	m_gsignal(R7), R8
   276  	CMP	g, R8
   277  	BNE	2(PC)
   278  	BL	runtime·abort(SB)
   279  
   280  	// Called from f.
   281  	// Set g->sched to context in f.
   282  	MOVD	R11, (g_sched+gobuf_ctxt)(g)
   283  	MOVD	R1, (g_sched+gobuf_sp)(g)
   284  	MOVD	LR, R8
   285  	MOVD	R8, (g_sched+gobuf_pc)(g)
   286  	MOVD	R5, (g_sched+gobuf_lr)(g)
   287  
   288  	// Called from f.
   289  	// Set m->morebuf to f's caller.
   290  	MOVD	R5, (m_morebuf+gobuf_pc)(R7)	// f's caller's PC
   291  	MOVD	R1, (m_morebuf+gobuf_sp)(R7)	// f's caller's SP
   292  	MOVD	g, (m_morebuf+gobuf_g)(R7)
   293  
   294  	// Call newstack on m->g0's stack.
   295  	MOVD	m_g0(R7), g
   296  	BL	runtime·save_g(SB)
   297  	MOVD	(g_sched+gobuf_sp)(g), R1
   298  	BL	runtime·newstack(SB)
   299  
   300  	// Not reached, but make sure the return PC from the call to newstack
   301  	// is still in this function, and not the beginning of the next.
   302  	UNDEF
   303  
   304  TEXT runtime·morestack_noctxt(SB),NOSPLIT|NOFRAME,$0-0
   305  	MOVD	R0, R11
   306  	BR	runtime·morestack(SB)
   307  
   308  TEXT runtime·stackBarrier(SB),NOSPLIT,$0
   309  	// We came here via a RET to an overwritten LR.
   310  	// R3 may be live. Other registers are available.
   311  
   312  	// Get the original return PC, g.stkbar[g.stkbarPos].savedLRVal.
   313  	MOVD	(g_stkbar+slice_array)(g), R4
   314  	MOVD	g_stkbarPos(g), R5
   315  	MOVD	$stkbar__size, R6
   316  	MULLD	R5, R6
   317  	ADD	R4, R6
   318  	MOVD	stkbar_savedLRVal(R6), R6
   319  	// Record that this stack barrier was hit.
   320  	ADD	$1, R5
   321  	MOVD	R5, g_stkbarPos(g)
   322  	// Jump to the original return PC.
   323  	MOVD	R6, CTR
   324  	BR	(CTR)
   325  
   326  // reflectcall: call a function with the given argument list
   327  // func call(argtype *_type, f *FuncVal, arg *byte, argsize, retoffset uint32).
   328  // we don't have variable-sized frames, so we use a small number
   329  // of constant-sized-frame functions to encode a few bits of size in the pc.
   330  // Caution: ugly multiline assembly macros in your future!
   331  
   332  #define DISPATCH(NAME,MAXSIZE)		\
   333  	MOVD	$MAXSIZE, R31;		\
   334  	CMP	R3, R31;		\
   335  	BGT	4(PC);			\
   336  	MOVD	$NAME(SB), R12;		\
   337  	MOVD	R12, CTR;		\
   338  	BR	(CTR)
   339  // Note: can't just "BR NAME(SB)" - bad inlining results.
   340  
   341  TEXT reflect·call(SB), NOSPLIT, $0-0
   342  	BR	·reflectcall(SB)
   343  
   344  TEXT ·reflectcall(SB), NOSPLIT|NOFRAME, $0-32
   345  	MOVWZ argsize+24(FP), R3
   346  	// NOTE(rsc): No call16, because CALLFN needs four words
   347  	// of argument space to invoke callwritebarrier.
   348  	DISPATCH(runtime·call32, 32)
   349  	DISPATCH(runtime·call64, 64)
   350  	DISPATCH(runtime·call128, 128)
   351  	DISPATCH(runtime·call256, 256)
   352  	DISPATCH(runtime·call512, 512)
   353  	DISPATCH(runtime·call1024, 1024)
   354  	DISPATCH(runtime·call2048, 2048)
   355  	DISPATCH(runtime·call4096, 4096)
   356  	DISPATCH(runtime·call8192, 8192)
   357  	DISPATCH(runtime·call16384, 16384)
   358  	DISPATCH(runtime·call32768, 32768)
   359  	DISPATCH(runtime·call65536, 65536)
   360  	DISPATCH(runtime·call131072, 131072)
   361  	DISPATCH(runtime·call262144, 262144)
   362  	DISPATCH(runtime·call524288, 524288)
   363  	DISPATCH(runtime·call1048576, 1048576)
   364  	DISPATCH(runtime·call2097152, 2097152)
   365  	DISPATCH(runtime·call4194304, 4194304)
   366  	DISPATCH(runtime·call8388608, 8388608)
   367  	DISPATCH(runtime·call16777216, 16777216)
   368  	DISPATCH(runtime·call33554432, 33554432)
   369  	DISPATCH(runtime·call67108864, 67108864)
   370  	DISPATCH(runtime·call134217728, 134217728)
   371  	DISPATCH(runtime·call268435456, 268435456)
   372  	DISPATCH(runtime·call536870912, 536870912)
   373  	DISPATCH(runtime·call1073741824, 1073741824)
   374  	MOVD	$runtime·badreflectcall(SB), R12
   375  	MOVD	R12, CTR
   376  	BR	(CTR)
   377  
   378  #define CALLFN(NAME,MAXSIZE)			\
   379  TEXT NAME(SB), WRAPPER, $MAXSIZE-24;		\
   380  	NO_LOCAL_POINTERS;			\
   381  	/* copy arguments to stack */		\
   382  	MOVD	arg+16(FP), R3;			\
   383  	MOVWZ	argsize+24(FP), R4;			\
   384  	MOVD	R1, R5;				\
   385  	ADD	$(FIXED_FRAME-1), R5;			\
   386  	SUB	$1, R3;				\
   387  	ADD	R5, R4;				\
   388  	CMP	R5, R4;				\
   389  	BEQ	4(PC);				\
   390  	MOVBZU	1(R3), R6;			\
   391  	MOVBZU	R6, 1(R5);			\
   392  	BR	-4(PC);				\
   393  	/* call function */			\
   394  	MOVD	f+8(FP), R11;			\
   395  	MOVD	(R11), R12;			\
   396  	MOVD	R12, CTR;			\
   397  	PCDATA  $PCDATA_StackMapIndex, $0;	\
   398  	BL	(CTR);				\
   399  	/* copy return values back */		\
   400  	MOVD	arg+16(FP), R3;			\
   401  	MOVWZ	n+24(FP), R4;			\
   402  	MOVWZ	retoffset+28(FP), R6;		\
   403  	MOVD	R1, R5;				\
   404  	ADD	R6, R5; 			\
   405  	ADD	R6, R3;				\
   406  	SUB	R6, R4;				\
   407  	ADD	$(FIXED_FRAME-1), R5;			\
   408  	SUB	$1, R3;				\
   409  	ADD	R5, R4;				\
   410  loop:						\
   411  	CMP	R5, R4;				\
   412  	BEQ	end;				\
   413  	MOVBZU	1(R5), R6;			\
   414  	MOVBZU	R6, 1(R3);			\
   415  	BR	loop;				\
   416  end:						\
   417  	/* execute write barrier updates */	\
   418  	MOVD	argtype+0(FP), R7;		\
   419  	MOVD	arg+16(FP), R3;			\
   420  	MOVWZ	n+24(FP), R4;			\
   421  	MOVWZ	retoffset+28(FP), R6;		\
   422  	MOVD	R7, FIXED_FRAME+0(R1);			\
   423  	MOVD	R3, FIXED_FRAME+8(R1);			\
   424  	MOVD	R4, FIXED_FRAME+16(R1);			\
   425  	MOVD	R6, FIXED_FRAME+24(R1);			\
   426  	BL	runtime·callwritebarrier(SB);	\
   427  	RET
   428  
   429  CALLFN(·call32, 32)
   430  CALLFN(·call64, 64)
   431  CALLFN(·call128, 128)
   432  CALLFN(·call256, 256)
   433  CALLFN(·call512, 512)
   434  CALLFN(·call1024, 1024)
   435  CALLFN(·call2048, 2048)
   436  CALLFN(·call4096, 4096)
   437  CALLFN(·call8192, 8192)
   438  CALLFN(·call16384, 16384)
   439  CALLFN(·call32768, 32768)
   440  CALLFN(·call65536, 65536)
   441  CALLFN(·call131072, 131072)
   442  CALLFN(·call262144, 262144)
   443  CALLFN(·call524288, 524288)
   444  CALLFN(·call1048576, 1048576)
   445  CALLFN(·call2097152, 2097152)
   446  CALLFN(·call4194304, 4194304)
   447  CALLFN(·call8388608, 8388608)
   448  CALLFN(·call16777216, 16777216)
   449  CALLFN(·call33554432, 33554432)
   450  CALLFN(·call67108864, 67108864)
   451  CALLFN(·call134217728, 134217728)
   452  CALLFN(·call268435456, 268435456)
   453  CALLFN(·call536870912, 536870912)
   454  CALLFN(·call1073741824, 1073741824)
   455  
   456  // bool cas(uint32 *ptr, uint32 old, uint32 new)
   457  // Atomically:
   458  //	if(*val == old){
   459  //		*val = new;
   460  //		return 1;
   461  //	} else
   462  //		return 0;
   463  TEXT runtime·cas(SB), NOSPLIT, $0-17
   464  	MOVD	ptr+0(FP), R3
   465  	MOVWZ	old+8(FP), R4
   466  	MOVWZ	new+12(FP), R5
   467  cas_again:
   468  	SYNC
   469  	LWAR	(R3), R6
   470  	CMPW	R6, R4
   471  	BNE	cas_fail
   472  	STWCCC	R5, (R3)
   473  	BNE	cas_again
   474  	MOVD	$1, R3
   475  	SYNC
   476  	ISYNC
   477  	MOVB	R3, ret+16(FP)
   478  	RET
   479  cas_fail:
   480  	MOVD	$0, R3
   481  	BR	-5(PC)
   482  
   483  // bool	runtime·cas64(uint64 *ptr, uint64 old, uint64 new)
   484  // Atomically:
   485  //	if(*val == *old){
   486  //		*val = new;
   487  //		return 1;
   488  //	} else {
   489  //		return 0;
   490  //	}
   491  TEXT runtime·cas64(SB), NOSPLIT, $0-25
   492  	MOVD	ptr+0(FP), R3
   493  	MOVD	old+8(FP), R4
   494  	MOVD	new+16(FP), R5
   495  cas64_again:
   496  	SYNC
   497  	LDAR	(R3), R6
   498  	CMP	R6, R4
   499  	BNE	cas64_fail
   500  	STDCCC	R5, (R3)
   501  	BNE	cas64_again
   502  	MOVD	$1, R3
   503  	SYNC
   504  	ISYNC
   505  	MOVB	R3, ret+24(FP)
   506  	RET
   507  cas64_fail:
   508  	MOVD	$0, R3
   509  	BR	-5(PC)
   510  
   511  TEXT runtime·casuintptr(SB), NOSPLIT, $0-25
   512  	BR	runtime·cas64(SB)
   513  
   514  TEXT runtime·atomicloaduintptr(SB), NOSPLIT|NOFRAME, $0-16
   515  	BR	runtime·atomicload64(SB)
   516  
   517  TEXT runtime·atomicloaduint(SB), NOSPLIT|NOFRAME, $0-16
   518  	BR	runtime·atomicload64(SB)
   519  
   520  TEXT runtime·atomicstoreuintptr(SB), NOSPLIT, $0-16
   521  	BR	runtime·atomicstore64(SB)
   522  
   523  // bool casp(void **val, void *old, void *new)
   524  // Atomically:
   525  //	if(*val == old){
   526  //		*val = new;
   527  //		return 1;
   528  //	} else
   529  //		return 0;
   530  TEXT runtime·casp1(SB), NOSPLIT, $0-25
   531  	BR runtime·cas64(SB)
   532  
   533  // uint32 xadd(uint32 volatile *ptr, int32 delta)
   534  // Atomically:
   535  //	*val += delta;
   536  //	return *val;
   537  TEXT runtime·xadd(SB), NOSPLIT, $0-20
   538  	MOVD	ptr+0(FP), R4
   539  	MOVW	delta+8(FP), R5
   540  	SYNC
   541  	LWAR	(R4), R3
   542  	ADD	R5, R3
   543  	STWCCC	R3, (R4)
   544  	BNE	-4(PC)
   545  	SYNC
   546  	ISYNC
   547  	MOVW	R3, ret+16(FP)
   548  	RET
   549  
   550  TEXT runtime·xadd64(SB), NOSPLIT, $0-24
   551  	MOVD	ptr+0(FP), R4
   552  	MOVD	delta+8(FP), R5
   553  	SYNC
   554  	LDAR	(R4), R3
   555  	ADD	R5, R3
   556  	STDCCC	R3, (R4)
   557  	BNE	-4(PC)
   558  	SYNC
   559  	ISYNC
   560  	MOVD	R3, ret+16(FP)
   561  	RET
   562  
   563  TEXT runtime·xchg(SB), NOSPLIT, $0-20
   564  	MOVD	ptr+0(FP), R4
   565  	MOVW	new+8(FP), R5
   566  	SYNC
   567  	LWAR	(R4), R3
   568  	STWCCC	R5, (R4)
   569  	BNE	-3(PC)
   570  	SYNC
   571  	ISYNC
   572  	MOVW	R3, ret+16(FP)
   573  	RET
   574  
   575  TEXT runtime·xchg64(SB), NOSPLIT, $0-24
   576  	MOVD	ptr+0(FP), R4
   577  	MOVD	new+8(FP), R5
   578  	SYNC
   579  	LDAR	(R4), R3
   580  	STDCCC	R5, (R4)
   581  	BNE	-3(PC)
   582  	SYNC
   583  	ISYNC
   584  	MOVD	R3, ret+16(FP)
   585  	RET
   586  
   587  TEXT runtime·xchguintptr(SB), NOSPLIT, $0-24
   588  	BR	runtime·xchg64(SB)
   589  
   590  TEXT runtime·procyield(SB),NOSPLIT,$0-0
   591  	RET
   592  
   593  TEXT runtime·atomicstorep1(SB), NOSPLIT, $0-16
   594  	BR	runtime·atomicstore64(SB)
   595  
   596  TEXT runtime·atomicstore(SB), NOSPLIT, $0-12
   597  	MOVD	ptr+0(FP), R3
   598  	MOVW	val+8(FP), R4
   599  	SYNC
   600  	MOVW	R4, 0(R3)
   601  	RET
   602  
   603  TEXT runtime·atomicstore64(SB), NOSPLIT, $0-16
   604  	MOVD	ptr+0(FP), R3
   605  	MOVD	val+8(FP), R4
   606  	SYNC
   607  	MOVD	R4, 0(R3)
   608  	RET
   609  
   610  // void	runtime·atomicor8(byte volatile*, byte);
   611  TEXT runtime·atomicor8(SB), NOSPLIT, $0-9
   612  	MOVD	ptr+0(FP), R3
   613  	MOVBZ	val+8(FP), R4
   614  	// Align ptr down to 4 bytes so we can use 32-bit load/store.
   615  	// R5 = (R3 << 0) & ~3
   616  	RLDCR	$0, R3, $~3, R5
   617  	// Compute val shift.
   618  #ifdef GOARCH_ppc64
   619  	// Big endian.  ptr = ptr ^ 3
   620  	XOR	$3, R3
   621  #endif
   622  	// R6 = ((ptr & 3) * 8) = (ptr << 3) & (3*8)
   623  	RLDC	$3, R3, $(3*8), R6
   624  	// Shift val for aligned ptr.  R4 = val << R6
   625  	SLD	R6, R4, R4
   626  
   627  again:
   628  	SYNC
   629  	LWAR	(R5), R6
   630  	OR	R4, R6
   631  	STWCCC	R6, (R5)
   632  	BNE	again
   633  	SYNC
   634  	ISYNC
   635  	RET
   636  
   637  // void	runtime·atomicand8(byte volatile*, byte);
   638  TEXT runtime·atomicand8(SB), NOSPLIT, $0-9
   639  	MOVD	ptr+0(FP), R3
   640  	MOVBZ	val+8(FP), R4
   641  	// Align ptr down to 4 bytes so we can use 32-bit load/store.
   642  	// R5 = (R3 << 0) & ~3
   643  	RLDCR	$0, R3, $~3, R5
   644  	// Compute val shift.
   645  #ifdef GOARCH_ppc64
   646  	// Big endian.  ptr = ptr ^ 3
   647  	XOR	$3, R3
   648  #endif
   649  	// R6 = ((ptr & 3) * 8) = (ptr << 3) & (3*8)
   650  	RLDC	$3, R3, $(3*8), R6
   651  	// Shift val for aligned ptr.  R4 = val << R6 | ^(0xFF << R6)
   652  	MOVD	$0xFF, R7
   653  	SLD	R6, R4
   654  	SLD	R6, R7
   655  	XOR $-1, R7
   656  	OR	R7, R4
   657  again:
   658  	SYNC
   659  	LWAR	(R5), R6
   660  	AND	R4, R6
   661  	STWCCC	R6, (R5)
   662  	BNE	again
   663  	SYNC
   664  	ISYNC
   665  	RET
   666  
   667  // void jmpdefer(fv, sp);
   668  // called from deferreturn.
   669  // 1. grab stored LR for caller
   670  // 2. sub 4 bytes to get back to BL deferreturn
   671  // 3. BR to fn
   672  TEXT runtime·jmpdefer(SB), NOSPLIT|NOFRAME, $0-16
   673  	MOVD	0(R1), R31
   674  	SUB	$4, R31
   675  	MOVD	R31, LR
   676  
   677  	MOVD	fv+0(FP), R11
   678  	MOVD	argp+8(FP), R1
   679  	SUB	$FIXED_FRAME, R1
   680  	MOVD	0(R11), R12
   681  	MOVD	R12, CTR
   682  	BR	(CTR)
   683  
   684  // Save state of caller into g->sched. Smashes R31.
   685  TEXT gosave<>(SB),NOSPLIT|NOFRAME,$0
   686  	MOVD	LR, R31
   687  	MOVD	R31, (g_sched+gobuf_pc)(g)
   688  	MOVD	R1, (g_sched+gobuf_sp)(g)
   689  	MOVD	R0, (g_sched+gobuf_lr)(g)
   690  	MOVD	R0, (g_sched+gobuf_ret)(g)
   691  	MOVD	R0, (g_sched+gobuf_ctxt)(g)
   692  	RET
   693  
   694  // func asmcgocall(fn, arg unsafe.Pointer) int32
   695  // Call fn(arg) on the scheduler stack,
   696  // aligned appropriately for the gcc ABI.
   697  // See cgocall.go for more details.
   698  TEXT ·asmcgocall(SB),NOSPLIT,$0-20
   699  	MOVD	fn+0(FP), R3
   700  	MOVD	arg+8(FP), R4
   701  
   702  	MOVD	R1, R7		// save original stack pointer
   703  	MOVD	g, R5
   704  
   705  	// Figure out if we need to switch to m->g0 stack.
   706  	// We get called to create new OS threads too, and those
   707  	// come in on the m->g0 stack already.
   708  	MOVD	g_m(g), R6
   709  	MOVD	m_g0(R6), R6
   710  	CMP	R6, g
   711  	BEQ	g0
   712  	BL	gosave<>(SB)
   713  	MOVD	R6, g
   714  	BL	runtime·save_g(SB)
   715  	MOVD	(g_sched+gobuf_sp)(g), R1
   716  
   717  	// Now on a scheduling stack (a pthread-created stack).
   718  g0:
   719  	// Save room for two of our pointers, plus 32 bytes of callee
   720  	// save area that lives on the caller stack.
   721  	SUB	$48, R1
   722  	RLDCR	$0, R1, $~15, R1	// 16-byte alignment for gcc ABI
   723  	MOVD	R5, 40(R1)	// save old g on stack
   724  	MOVD	(g_stack+stack_hi)(R5), R5
   725  	SUB	R7, R5
   726  	MOVD	R5, 32(R1)	// save depth in old g stack (can't just save SP, as stack might be copied during a callback)
   727  	MOVD	R0, 0(R1)	// clear back chain pointer (TODO can we give it real back trace information?)
   728  	// This is a "global call", so put the global entry point in r12
   729  	MOVD	R3, R12
   730  	MOVD	R12, CTR
   731  	MOVD	R4, R3		// arg in r3
   732  	BL	(CTR)
   733  
   734  	// C code can clobber R0, so set it back to 0.  F27-F31 are
   735  	// callee save, so we don't need to recover those.
   736  	XOR	R0, R0
   737  	// Restore g, stack pointer.  R3 is errno, so don't touch it
   738  	MOVD	40(R1), g
   739  	BL	runtime·save_g(SB)
   740  	MOVD	(g_stack+stack_hi)(g), R5
   741  	MOVD	32(R1), R6
   742  	SUB	R6, R5
   743  	MOVD	R5, R1
   744  
   745  	MOVW	R3, ret+16(FP)
   746  	RET
   747  
   748  // cgocallback(void (*fn)(void*), void *frame, uintptr framesize)
   749  // Turn the fn into a Go func (by taking its address) and call
   750  // cgocallback_gofunc.
   751  TEXT runtime·cgocallback(SB),NOSPLIT,$24-24
   752  	MOVD	$fn+0(FP), R3
   753  	MOVD	R3, FIXED_FRAME+0(R1)
   754  	MOVD	frame+8(FP), R3
   755  	MOVD	R3, FIXED_FRAME+8(R1)
   756  	MOVD	framesize+16(FP), R3
   757  	MOVD	R3, FIXED_FRAME+16(R1)
   758  	MOVD	$runtime·cgocallback_gofunc(SB), R12
   759  	MOVD	R12, CTR
   760  	BL	(CTR)
   761  	RET
   762  
   763  // cgocallback_gofunc(FuncVal*, void *frame, uintptr framesize)
   764  // See cgocall.go for more details.
   765  TEXT ·cgocallback_gofunc(SB),NOSPLIT,$16-24
   766  	NO_LOCAL_POINTERS
   767  
   768  	// Load m and g from thread-local storage.
   769  	MOVB	runtime·iscgo(SB), R3
   770  	CMP	R3, $0
   771  	BEQ	nocgo
   772  	BL	runtime·load_g(SB)
   773  nocgo:
   774  
   775  	// If g is nil, Go did not create the current thread.
   776  	// Call needm to obtain one for temporary use.
   777  	// In this case, we're running on the thread stack, so there's
   778  	// lots of space, but the linker doesn't know. Hide the call from
   779  	// the linker analysis by using an indirect call.
   780  	CMP	g, $0
   781  	BNE	havem
   782  	MOVD	g, savedm-8(SP) // g is zero, so is m.
   783  	MOVD	$runtime·needm(SB), R12
   784  	MOVD	R12, CTR
   785  	BL	(CTR)
   786  
   787  	// Set m->sched.sp = SP, so that if a panic happens
   788  	// during the function we are about to execute, it will
   789  	// have a valid SP to run on the g0 stack.
   790  	// The next few lines (after the havem label)
   791  	// will save this SP onto the stack and then write
   792  	// the same SP back to m->sched.sp. That seems redundant,
   793  	// but if an unrecovered panic happens, unwindm will
   794  	// restore the g->sched.sp from the stack location
   795  	// and then systemstack will try to use it. If we don't set it here,
   796  	// that restored SP will be uninitialized (typically 0) and
   797  	// will not be usable.
   798  	MOVD	g_m(g), R3
   799  	MOVD	m_g0(R3), R3
   800  	MOVD	R1, (g_sched+gobuf_sp)(R3)
   801  
   802  havem:
   803  	MOVD	g_m(g), R8
   804  	MOVD	R8, savedm-8(SP)
   805  	// Now there's a valid m, and we're running on its m->g0.
   806  	// Save current m->g0->sched.sp on stack and then set it to SP.
   807  	// Save current sp in m->g0->sched.sp in preparation for
   808  	// switch back to m->curg stack.
   809  	// NOTE: unwindm knows that the saved g->sched.sp is at 8(R1) aka savedsp-16(SP).
   810  	MOVD	m_g0(R8), R3
   811  	MOVD	(g_sched+gobuf_sp)(R3), R4
   812  	MOVD	R4, savedsp-16(SP)
   813  	MOVD	R1, (g_sched+gobuf_sp)(R3)
   814  
   815  	// Switch to m->curg stack and call runtime.cgocallbackg.
   816  	// Because we are taking over the execution of m->curg
   817  	// but *not* resuming what had been running, we need to
   818  	// save that information (m->curg->sched) so we can restore it.
   819  	// We can restore m->curg->sched.sp easily, because calling
   820  	// runtime.cgocallbackg leaves SP unchanged upon return.
   821  	// To save m->curg->sched.pc, we push it onto the stack.
   822  	// This has the added benefit that it looks to the traceback
   823  	// routine like cgocallbackg is going to return to that
   824  	// PC (because the frame we allocate below has the same
   825  	// size as cgocallback_gofunc's frame declared above)
   826  	// so that the traceback will seamlessly trace back into
   827  	// the earlier calls.
   828  	//
   829  	// In the new goroutine, -16(SP) and -8(SP) are unused.
   830  	MOVD	m_curg(R8), g
   831  	BL	runtime·save_g(SB)
   832  	MOVD	(g_sched+gobuf_sp)(g), R4 // prepare stack as R4
   833  	MOVD	(g_sched+gobuf_pc)(g), R5
   834  	MOVD	R5, -(FIXED_FRAME+16)(R4)
   835  	MOVD	$-(FIXED_FRAME+16)(R4), R1
   836  	BL	runtime·cgocallbackg(SB)
   837  
   838  	// Restore g->sched (== m->curg->sched) from saved values.
   839  	MOVD	0(R1), R5
   840  	MOVD	R5, (g_sched+gobuf_pc)(g)
   841  	MOVD	$(FIXED_FRAME+16)(R1), R4
   842  	MOVD	R4, (g_sched+gobuf_sp)(g)
   843  
   844  	// Switch back to m->g0's stack and restore m->g0->sched.sp.
   845  	// (Unlike m->curg, the g0 goroutine never uses sched.pc,
   846  	// so we do not have to restore it.)
   847  	MOVD	g_m(g), R8
   848  	MOVD	m_g0(R8), g
   849  	BL	runtime·save_g(SB)
   850  	MOVD	(g_sched+gobuf_sp)(g), R1
   851  	MOVD	savedsp-16(SP), R4
   852  	MOVD	R4, (g_sched+gobuf_sp)(g)
   853  
   854  	// If the m on entry was nil, we called needm above to borrow an m
   855  	// for the duration of the call. Since the call is over, return it with dropm.
   856  	MOVD	savedm-8(SP), R6
   857  	CMP	R6, $0
   858  	BNE	droppedm
   859  	MOVD	$runtime·dropm(SB), R12
   860  	MOVD	R12, CTR
   861  	BL	(CTR)
   862  droppedm:
   863  
   864  	// Done!
   865  	RET
   866  
   867  // void setg(G*); set g. for use by needm.
   868  TEXT runtime·setg(SB), NOSPLIT, $0-8
   869  	MOVD	gg+0(FP), g
   870  	// This only happens if iscgo, so jump straight to save_g
   871  	BL	runtime·save_g(SB)
   872  	RET
   873  
   874  // void setg_gcc(G*); set g in C TLS.
   875  // Must obey the gcc calling convention.
   876  TEXT setg_gcc<>(SB),NOSPLIT|NOFRAME,$0-0
   877  	// The standard prologue clobbers R31, which is callee-save in
   878  	// the C ABI, so we have to use $-8-0 and save LR ourselves.
   879  	MOVD	LR, R4
   880  	// Also save g and R31, since they're callee-save in C ABI
   881  	MOVD	R31, R5
   882  	MOVD	g, R6
   883  
   884  	MOVD	R3, g
   885  	BL	runtime·save_g(SB)
   886  
   887  	MOVD	R6, g
   888  	MOVD	R5, R31
   889  	MOVD	R4, LR
   890  	RET
   891  
   892  TEXT runtime·getcallerpc(SB),NOSPLIT,$8-16
   893  	MOVD	FIXED_FRAME+8(R1), R3		// LR saved by caller
   894  	MOVD	runtime·stackBarrierPC(SB), R4
   895  	CMP	R3, R4
   896  	BNE	nobar
   897  	// Get original return PC.
   898  	BL	runtime·nextBarrierPC(SB)
   899  	MOVD	FIXED_FRAME+0(R1), R3
   900  nobar:
   901  	MOVD	R3, ret+8(FP)
   902  	RET
   903  
   904  TEXT runtime·setcallerpc(SB),NOSPLIT,$8-16
   905  	MOVD	pc+8(FP), R3
   906  	MOVD	FIXED_FRAME+8(R1), R4
   907  	MOVD	runtime·stackBarrierPC(SB), R5
   908  	CMP	R4, R5
   909  	BEQ	setbar
   910  	MOVD	R3, FIXED_FRAME+8(R1)		// set LR in caller
   911  	RET
   912  setbar:
   913  	// Set the stack barrier return PC.
   914  	MOVD	R3, FIXED_FRAME+0(R1)
   915  	BL	runtime·setNextBarrierPC(SB)
   916  	RET
   917  
   918  TEXT runtime·getcallersp(SB),NOSPLIT,$0-16
   919  	MOVD	argp+0(FP), R3
   920  	SUB	$FIXED_FRAME, R3
   921  	MOVD	R3, ret+8(FP)
   922  	RET
   923  
   924  TEXT runtime·abort(SB),NOSPLIT|NOFRAME,$0-0
   925  	MOVW	(R0), R0
   926  	UNDEF
   927  
   928  #define	TBRL	268
   929  #define	TBRU	269		/* Time base Upper/Lower */
   930  
   931  // int64 runtime·cputicks(void)
   932  TEXT runtime·cputicks(SB),NOSPLIT,$0-8
   933  	MOVW	SPR(TBRU), R4
   934  	MOVW	SPR(TBRL), R3
   935  	MOVW	SPR(TBRU), R5
   936  	CMPW	R4, R5
   937  	BNE	-4(PC)
   938  	SLD	$32, R5
   939  	OR	R5, R3
   940  	MOVD	R3, ret+0(FP)
   941  	RET
   942  
   943  // memhash_varlen(p unsafe.Pointer, h seed) uintptr
   944  // redirects to memhash(p, h, size) using the size
   945  // stored in the closure.
   946  TEXT runtime·memhash_varlen(SB),NOSPLIT,$40-24
   947  	GO_ARGS
   948  	NO_LOCAL_POINTERS
   949  	MOVD	p+0(FP), R3
   950  	MOVD	h+8(FP), R4
   951  	MOVD	8(R11), R5
   952  	MOVD	R3, FIXED_FRAME+0(R1)
   953  	MOVD	R4, FIXED_FRAME+8(R1)
   954  	MOVD	R5, FIXED_FRAME+16(R1)
   955  	BL	runtime·memhash(SB)
   956  	MOVD	FIXED_FRAME+24(R1), R3
   957  	MOVD	R3, ret+16(FP)
   958  	RET
   959  
   960  // AES hashing not implemented for ppc64
   961  TEXT runtime·aeshash(SB),NOSPLIT|NOFRAME,$0-0
   962  	MOVW	(R0), R1
   963  TEXT runtime·aeshash32(SB),NOSPLIT|NOFRAME,$0-0
   964  	MOVW	(R0), R1
   965  TEXT runtime·aeshash64(SB),NOSPLIT|NOFRAME,$0-0
   966  	MOVW	(R0), R1
   967  TEXT runtime·aeshashstr(SB),NOSPLIT|NOFRAME,$0-0
   968  	MOVW	(R0), R1
   969  
   970  TEXT runtime·memeq(SB),NOSPLIT|NOFRAME,$0-25
   971  	MOVD	a+0(FP), R3
   972  	MOVD	b+8(FP), R4
   973  	MOVD	size+16(FP), R5
   974  	SUB	$1, R3
   975  	SUB	$1, R4
   976  	ADD	R3, R5, R8
   977  loop:
   978  	CMP	R3, R8
   979  	BNE	test
   980  	MOVD	$1, R3
   981  	MOVB	R3, ret+24(FP)
   982  	RET
   983  test:
   984  	MOVBZU	1(R3), R6
   985  	MOVBZU	1(R4), R7
   986  	CMP	R6, R7
   987  	BEQ	loop
   988  
   989  	MOVB	R0, ret+24(FP)
   990  	RET
   991  
   992  // memequal_varlen(a, b unsafe.Pointer) bool
   993  TEXT runtime·memequal_varlen(SB),NOSPLIT,$40-17
   994  	MOVD	a+0(FP), R3
   995  	MOVD	b+8(FP), R4
   996  	CMP	R3, R4
   997  	BEQ	eq
   998  	MOVD	8(R11), R5    // compiler stores size at offset 8 in the closure
   999  	MOVD	R3, FIXED_FRAME+0(R1)
  1000  	MOVD	R4, FIXED_FRAME+8(R1)
  1001  	MOVD	R5, FIXED_FRAME+16(R1)
  1002  	BL	runtime·memeq(SB)
  1003  	MOVBZ	FIXED_FRAME+24(R1), R3
  1004  	MOVB	R3, ret+16(FP)
  1005  	RET
  1006  eq:
  1007  	MOVD	$1, R3
  1008  	MOVB	R3, ret+16(FP)
  1009  	RET
  1010  
  1011  // eqstring tests whether two strings are equal.
  1012  // The compiler guarantees that strings passed
  1013  // to eqstring have equal length.
  1014  // See runtime_test.go:eqstring_generic for
  1015  // equivalent Go code.
  1016  TEXT runtime·eqstring(SB),NOSPLIT,$0-33
  1017  	MOVD	s1str+0(FP), R3
  1018  	MOVD	s2str+16(FP), R4
  1019  	MOVD	$1, R5
  1020  	MOVB	R5, ret+32(FP)
  1021  	CMP	R3, R4
  1022  	BNE	2(PC)
  1023  	RET
  1024  	MOVD	s1len+8(FP), R5
  1025  	SUB	$1, R3
  1026  	SUB	$1, R4
  1027  	ADD	R3, R5, R8
  1028  loop:
  1029  	CMP	R3, R8
  1030  	BNE	2(PC)
  1031  	RET
  1032  	MOVBZU	1(R3), R6
  1033  	MOVBZU	1(R4), R7
  1034  	CMP	R6, R7
  1035  	BEQ	loop
  1036  	MOVB	R0, ret+32(FP)
  1037  	RET
  1038  
  1039  // TODO: share code with memeq?
  1040  TEXT bytes·Equal(SB),NOSPLIT,$0-49
  1041  	MOVD	a_len+8(FP), R3
  1042  	MOVD	b_len+32(FP), R4
  1043  
  1044  	CMP	R3, R4		// unequal lengths are not equal
  1045  	BNE	noteq
  1046  
  1047  	MOVD	a+0(FP), R5
  1048  	MOVD	b+24(FP), R6
  1049  	SUB	$1, R5
  1050  	SUB	$1, R6
  1051  	ADD	R5, R3		// end-1
  1052  
  1053  loop:
  1054  	CMP	R5, R3
  1055  	BEQ	equal		// reached the end
  1056  	MOVBZU	1(R5), R4
  1057  	MOVBZU	1(R6), R7
  1058  	CMP	R4, R7
  1059  	BEQ	loop
  1060  
  1061  noteq:
  1062  	MOVBZ	R0, ret+48(FP)
  1063  	RET
  1064  
  1065  equal:
  1066  	MOVD	$1, R3
  1067  	MOVBZ	R3, ret+48(FP)
  1068  	RET
  1069  
  1070  TEXT bytes·IndexByte(SB),NOSPLIT,$0-40
  1071  	MOVD	s+0(FP), R3
  1072  	MOVD	s_len+8(FP), R4
  1073  	MOVBZ	c+24(FP), R5	// byte to find
  1074  	MOVD	R3, R6		// store base for later
  1075  	SUB	$1, R3
  1076  	ADD	R3, R4		// end-1
  1077  
  1078  loop:
  1079  	CMP	R3, R4
  1080  	BEQ	notfound
  1081  	MOVBZU	1(R3), R7
  1082  	CMP	R7, R5
  1083  	BNE	loop
  1084  
  1085  	SUB	R6, R3		// remove base
  1086  	MOVD	R3, ret+32(FP)
  1087  	RET
  1088  
  1089  notfound:
  1090  	MOVD	$-1, R3
  1091  	MOVD	R3, ret+32(FP)
  1092  	RET
  1093  
  1094  TEXT strings·IndexByte(SB),NOSPLIT,$0-32
  1095  	MOVD	p+0(FP), R3
  1096  	MOVD	b_len+8(FP), R4
  1097  	MOVBZ	c+16(FP), R5	// byte to find
  1098  	MOVD	R3, R6		// store base for later
  1099  	SUB	$1, R3
  1100  	ADD	R3, R4		// end-1
  1101  
  1102  loop:
  1103  	CMP	R3, R4
  1104  	BEQ	notfound
  1105  	MOVBZU	1(R3), R7
  1106  	CMP	R7, R5
  1107  	BNE	loop
  1108  
  1109  	SUB	R6, R3		// remove base
  1110  	MOVD	R3, ret+24(FP)
  1111  	RET
  1112  
  1113  notfound:
  1114  	MOVD	$-1, R3
  1115  	MOVD	R3, ret+24(FP)
  1116  	RET
  1117  
  1118  TEXT runtime·cmpstring(SB),NOSPLIT|NOFRAME,$0-40
  1119  	MOVD	s1_base+0(FP), R5
  1120  	MOVD	s1_len+8(FP), R3
  1121  	MOVD	s2_base+16(FP), R6
  1122  	MOVD	s2_len+24(FP), R4
  1123  	MOVD	$ret+32(FP), R7
  1124  	BR	runtime·cmpbody<>(SB)
  1125  
  1126  TEXT bytes·Compare(SB),NOSPLIT|NOFRAME,$0-56
  1127  	MOVD	s1+0(FP), R5
  1128  	MOVD	s1+8(FP), R3
  1129  	MOVD	s2+24(FP), R6
  1130  	MOVD	s2+32(FP), R4
  1131  	MOVD	$ret+48(FP), R7
  1132  	BR	runtime·cmpbody<>(SB)
  1133  
  1134  // On entry:
  1135  // R3 is the length of s1
  1136  // R4 is the length of s2
  1137  // R5 points to the start of s1
  1138  // R6 points to the start of s2
  1139  // R7 points to return value (-1/0/1 will be written here)
  1140  //
  1141  // On exit:
  1142  // R5, R6, R8, R9 and R10 are clobbered
  1143  TEXT runtime·cmpbody<>(SB),NOSPLIT|NOFRAME,$0-0
  1144  	CMP	R5, R6
  1145  	BEQ	samebytes // same starting pointers; compare lengths
  1146  	SUB	$1, R5
  1147  	SUB	$1, R6
  1148  	MOVD	R4, R8
  1149  	CMP	R3, R4
  1150  	BGE	2(PC)
  1151  	MOVD	R3, R8	// R8 is min(R3, R4)
  1152  	ADD	R5, R8	// R5 is current byte in s1, R8 is last byte in s1 to compare
  1153  loop:
  1154  	CMP	R5, R8
  1155  	BEQ	samebytes // all compared bytes were the same; compare lengths
  1156  	MOVBZU	1(R5), R9
  1157  	MOVBZU	1(R6), R10
  1158  	CMP	R9, R10
  1159  	BEQ	loop
  1160  	// bytes differed
  1161  	MOVD	$1, R4
  1162  	BGT	2(PC)
  1163  	NEG	R4
  1164  	MOVD	R4, (R7)
  1165  	RET
  1166  samebytes:
  1167  	MOVD	$1, R8
  1168  	CMP	R3, R4
  1169  	BNE	3(PC)
  1170  	MOVD	R0, (R7)
  1171  	RET
  1172  	BGT	2(PC)
  1173  	NEG	R8
  1174  	MOVD	R8, (R7)
  1175  	RET
  1176  
  1177  TEXT runtime·fastrand1(SB), NOSPLIT, $0-4
  1178  	MOVD	g_m(g), R4
  1179  	MOVWZ	m_fastrand(R4), R3
  1180  	ADD	R3, R3
  1181  	CMPW	R3, $0
  1182  	BGE	2(PC)
  1183  	XOR	$0x88888eef, R3
  1184  	MOVW	R3, m_fastrand(R4)
  1185  	MOVW	R3, ret+0(FP)
  1186  	RET
  1187  
  1188  TEXT runtime·return0(SB), NOSPLIT, $0
  1189  	MOVW	$0, R3
  1190  	RET
  1191  
  1192  // Called from cgo wrappers, this function returns g->m->curg.stack.hi.
  1193  // Must obey the gcc calling convention.
  1194  TEXT _cgo_topofstack(SB),NOSPLIT|NOFRAME,$0
  1195  	// g (R30) and R31 are callee-save in the C ABI, so save them
  1196  	MOVD	g, R4
  1197  	MOVD	R31, R5
  1198  	MOVD	LR, R6
  1199  
  1200  	BL	runtime·load_g(SB)	// clobbers g (R30), R31
  1201  	MOVD	g_m(g), R3
  1202  	MOVD	m_curg(R3), R3
  1203  	MOVD	(g_stack+stack_hi)(R3), R3
  1204  
  1205  	MOVD	R4, g
  1206  	MOVD	R5, R31
  1207  	MOVD	R6, LR
  1208  	RET
  1209  
  1210  // The top-most function running on a goroutine
  1211  // returns to goexit+PCQuantum.
  1212  TEXT runtime·goexit(SB),NOSPLIT|NOFRAME,$0-0
  1213  	MOVD	R0, R0	// NOP
  1214  	BL	runtime·goexit1(SB)	// does not return
  1215  	// traceback from goexit1 must hit code range of goexit
  1216  	MOVD	R0, R0	// NOP
  1217  
  1218  TEXT runtime·prefetcht0(SB),NOSPLIT,$0-8
  1219  	RET
  1220  
  1221  TEXT runtime·prefetcht1(SB),NOSPLIT,$0-8
  1222  	RET
  1223  
  1224  TEXT runtime·prefetcht2(SB),NOSPLIT,$0-8
  1225  	RET
  1226  
  1227  TEXT runtime·prefetchnta(SB),NOSPLIT,$0-8
  1228  	RET
  1229  
  1230  TEXT runtime·sigreturn(SB),NOSPLIT,$0-8
  1231          RET