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