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