github.com/twelsh-aw/go/src@v0.0.0-20230516233729-a56fe86a7c81/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  //go: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  #ifdef GOOS_aix
    14  #define cgoCalleeStackSize 48
    15  #else
    16  #define cgoCalleeStackSize 32
    17  #endif
    18  
    19  TEXT runtime·rt0_go(SB),NOSPLIT|TOPFRAME,$0
    20  	// R1 = stack; R3 = argc; R4 = argv; R13 = C TLS base pointer
    21  
    22  	// initialize essential registers
    23  	BL	runtime·reginit(SB)
    24  
    25  	SUB	$(FIXED_FRAME+16), R1
    26  	MOVD	R2, 24(R1)		// stash the TOC pointer away again now we've created a new frame
    27  	MOVW	R3, FIXED_FRAME+0(R1)	// argc
    28  	MOVD	R4, FIXED_FRAME+8(R1)	// argv
    29  
    30  	// create istack out of the given (operating system) stack.
    31  	// _cgo_init may update stackguard.
    32  	MOVD	$runtime·g0(SB), g
    33  	BL	runtime·save_g(SB)
    34  	MOVD	$(-64*1024), R31
    35  	ADD	R31, R1, R3
    36  	MOVD	R3, g_stackguard0(g)
    37  	MOVD	R3, g_stackguard1(g)
    38  	MOVD	R3, (g_stack+stack_lo)(g)
    39  	MOVD	R1, (g_stack+stack_hi)(g)
    40  
    41  	// If there is a _cgo_init, call it using the gcc ABI.
    42  	MOVD	_cgo_init(SB), R12
    43  	CMP	R0, R12
    44  	BEQ	nocgo
    45  
    46  #ifdef GO_PPC64X_HAS_FUNCDESC
    47  	// Load the real entry address from the first slot of the function descriptor.
    48  	MOVD	8(R12), R2
    49  	MOVD	(R12), R12
    50  #endif
    51  	MOVD	R12, CTR		// r12 = "global function entry point"
    52  	MOVD	R13, R5			// arg 2: TLS base pointer
    53  	MOVD	$setg_gcc<>(SB), R4 	// arg 1: setg
    54  	MOVD	g, R3			// arg 0: G
    55  	// C functions expect 32 (48 for AIX) bytes of space on caller
    56  	// stack frame and a 16-byte aligned R1
    57  	MOVD	R1, R14			// save current stack
    58  	SUB	$cgoCalleeStackSize, R1	// reserve the callee area
    59  	RLDCR	$0, R1, $~15, R1	// 16-byte align
    60  	BL	(CTR)			// may clobber R0, R3-R12
    61  	MOVD	R14, R1			// restore stack
    62  #ifndef GOOS_aix
    63  	MOVD	24(R1), R2
    64  #endif
    65  	XOR	R0, R0			// fix R0
    66  
    67  nocgo:
    68  	// update stackguard after _cgo_init
    69  	MOVD	(g_stack+stack_lo)(g), R3
    70  	ADD	$const_stackGuard, R3
    71  	MOVD	R3, g_stackguard0(g)
    72  	MOVD	R3, g_stackguard1(g)
    73  
    74  	// set the per-goroutine and per-mach "registers"
    75  	MOVD	$runtime·m0(SB), R3
    76  
    77  	// save m->g0 = g0
    78  	MOVD	g, m_g0(R3)
    79  	// save m0 to g0->m
    80  	MOVD	R3, g_m(g)
    81  
    82  	BL	runtime·check(SB)
    83  
    84  	// args are already prepared
    85  	BL	runtime·args(SB)
    86  	BL	runtime·osinit(SB)
    87  	BL	runtime·schedinit(SB)
    88  
    89  	// create a new goroutine to start program
    90  	MOVD	$runtime·mainPC(SB), R3		// entry
    91  	MOVDU	R3, -8(R1)
    92  	MOVDU	R0, -8(R1)
    93  	MOVDU	R0, -8(R1)
    94  	MOVDU	R0, -8(R1)
    95  	MOVDU	R0, -8(R1)
    96  	BL	runtime·newproc(SB)
    97  	ADD	$(8+FIXED_FRAME), R1
    98  
    99  	// start this M
   100  	BL	runtime·mstart(SB)
   101  
   102  	MOVD	R0, 0(R0)
   103  	RET
   104  
   105  DATA	runtime·mainPC+0(SB)/8,$runtime·main<ABIInternal>(SB)
   106  GLOBL	runtime·mainPC(SB),RODATA,$8
   107  
   108  TEXT runtime·breakpoint(SB),NOSPLIT|NOFRAME,$0-0
   109  	TW	$31, R0, R0
   110  	RET
   111  
   112  TEXT runtime·asminit(SB),NOSPLIT|NOFRAME,$0-0
   113  	RET
   114  
   115  // Any changes must be reflected to runtime/cgo/gcc_aix_ppc64.S:.crosscall_ppc64
   116  TEXT _cgo_reginit(SB),NOSPLIT|NOFRAME,$0-0
   117  	// crosscall_ppc64 and crosscall2 need to reginit, but can't
   118  	// get at the 'runtime.reginit' symbol.
   119  	BR	runtime·reginit(SB)
   120  
   121  TEXT runtime·reginit(SB),NOSPLIT|NOFRAME,$0-0
   122  	// set R0 to zero, it's expected by the toolchain
   123  	XOR R0, R0
   124  	RET
   125  
   126  TEXT runtime·mstart(SB),NOSPLIT|TOPFRAME,$0
   127  	BL	runtime·mstart0(SB)
   128  	RET // not reached
   129  
   130  /*
   131   *  go-routine
   132   */
   133  
   134  // void gogo(Gobuf*)
   135  // restore state from Gobuf; longjmp
   136  TEXT runtime·gogo(SB), NOSPLIT|NOFRAME, $0-8
   137  	MOVD	buf+0(FP), R5
   138  	MOVD	gobuf_g(R5), R6
   139  	MOVD	0(R6), R4	// make sure g != nil
   140  	BR	gogo<>(SB)
   141  
   142  TEXT gogo<>(SB), NOSPLIT|NOFRAME, $0
   143  	MOVD	R6, g
   144  	BL	runtime·save_g(SB)
   145  
   146  	MOVD	gobuf_sp(R5), R1
   147  	MOVD	gobuf_lr(R5), R31
   148  #ifndef GOOS_aix
   149  	MOVD	24(R1), R2	// restore R2
   150  #endif
   151  	MOVD	R31, LR
   152  	MOVD	gobuf_ret(R5), R3
   153  	MOVD	gobuf_ctxt(R5), R11
   154  	MOVD	R0, gobuf_sp(R5)
   155  	MOVD	R0, gobuf_ret(R5)
   156  	MOVD	R0, gobuf_lr(R5)
   157  	MOVD	R0, gobuf_ctxt(R5)
   158  	CMP	R0, R0 // set condition codes for == test, needed by stack split
   159  	MOVD	gobuf_pc(R5), R12
   160  	MOVD	R12, CTR
   161  	BR	(CTR)
   162  
   163  // void mcall(fn func(*g))
   164  // Switch to m->g0's stack, call fn(g).
   165  // Fn must never return. It should gogo(&g->sched)
   166  // to keep running g.
   167  TEXT runtime·mcall<ABIInternal>(SB), NOSPLIT|NOFRAME, $0-8
   168  	// Save caller state in g->sched
   169  	// R11 should be safe across save_g??
   170  	MOVD	R3, R11
   171  	MOVD	R1, (g_sched+gobuf_sp)(g)
   172  	MOVD	LR, R31
   173  	MOVD	R31, (g_sched+gobuf_pc)(g)
   174  	MOVD	R0, (g_sched+gobuf_lr)(g)
   175  
   176  	// Switch to m->g0 & its stack, call fn.
   177  	MOVD	g, R3
   178  	MOVD	g_m(g), R8
   179  	MOVD	m_g0(R8), g
   180  	BL	runtime·save_g(SB)
   181  	CMP	g, R3
   182  	BNE	2(PC)
   183  	BR	runtime·badmcall(SB)
   184  	MOVD	0(R11), R12			// code pointer
   185  	MOVD	R12, CTR
   186  	MOVD	(g_sched+gobuf_sp)(g), R1	// sp = m->g0->sched.sp
   187  	// Don't need to do anything special for regabiargs here
   188  	// R3 is g; stack is set anyway
   189  	MOVDU	R3, -8(R1)
   190  	MOVDU	R0, -8(R1)
   191  	MOVDU	R0, -8(R1)
   192  	MOVDU	R0, -8(R1)
   193  	MOVDU	R0, -8(R1)
   194  	BL	(CTR)
   195  	MOVD	24(R1), R2
   196  	BR	runtime·badmcall2(SB)
   197  
   198  // systemstack_switch is a dummy routine that systemstack leaves at the bottom
   199  // of the G stack. We need to distinguish the routine that
   200  // lives at the bottom of the G stack from the one that lives
   201  // at the top of the system stack because the one at the top of
   202  // the system stack terminates the stack walk (see topofstack()).
   203  TEXT runtime·systemstack_switch(SB), NOSPLIT, $0-0
   204  	// We have several undefs here so that 16 bytes past
   205  	// $runtime·systemstack_switch lies within them whether or not the
   206  	// instructions that derive r2 from r12 are there.
   207  	UNDEF
   208  	UNDEF
   209  	UNDEF
   210  	BL	(LR)	// make sure this function is not leaf
   211  	RET
   212  
   213  // func systemstack(fn func())
   214  TEXT runtime·systemstack(SB), NOSPLIT, $0-8
   215  	MOVD	fn+0(FP), R3	// R3 = fn
   216  	MOVD	R3, R11		// context
   217  	MOVD	g_m(g), R4	// R4 = m
   218  
   219  	MOVD	m_gsignal(R4), R5	// R5 = gsignal
   220  	CMP	g, R5
   221  	BEQ	noswitch
   222  
   223  	MOVD	m_g0(R4), R5	// R5 = g0
   224  	CMP	g, R5
   225  	BEQ	noswitch
   226  
   227  	MOVD	m_curg(R4), R6
   228  	CMP	g, R6
   229  	BEQ	switch
   230  
   231  	// Bad: g is not gsignal, not g0, not curg. What is it?
   232  	// Hide call from linker nosplit analysis.
   233  	MOVD	$runtime·badsystemstack(SB), R12
   234  	MOVD	R12, CTR
   235  	BL	(CTR)
   236  	BL	runtime·abort(SB)
   237  
   238  switch:
   239  	// save our state in g->sched. Pretend to
   240  	// be systemstack_switch if the G stack is scanned.
   241  	BL	gosave_systemstack_switch<>(SB)
   242  
   243  	// switch to g0
   244  	MOVD	R5, g
   245  	BL	runtime·save_g(SB)
   246  	MOVD	(g_sched+gobuf_sp)(g), R1
   247  
   248  	// call target function
   249  	MOVD	0(R11), R12	// code pointer
   250  	MOVD	R12, CTR
   251  	BL	(CTR)
   252  
   253  	// restore TOC pointer. It seems unlikely that we will use systemstack
   254  	// to call a function defined in another module, but the results of
   255  	// doing so would be so confusing that it's worth doing this.
   256  	MOVD	g_m(g), R3
   257  	MOVD	m_curg(R3), g
   258  	MOVD	(g_sched+gobuf_sp)(g), R3
   259  #ifndef GOOS_aix
   260  	MOVD	24(R3), R2
   261  #endif
   262  	// switch back to g
   263  	MOVD	g_m(g), R3
   264  	MOVD	m_curg(R3), g
   265  	BL	runtime·save_g(SB)
   266  	MOVD	(g_sched+gobuf_sp)(g), R1
   267  	MOVD	R0, (g_sched+gobuf_sp)(g)
   268  	RET
   269  
   270  noswitch:
   271  	// already on m stack, just call directly
   272  	// On other arches we do a tail call here, but it appears to be
   273  	// impossible to tail call a function pointer in shared mode on
   274  	// ppc64 because the caller is responsible for restoring the TOC.
   275  	MOVD	0(R11), R12	// code pointer
   276  	MOVD	R12, CTR
   277  	BL	(CTR)
   278  #ifndef GOOS_aix
   279  	MOVD	24(R1), R2
   280  #endif
   281  	RET
   282  
   283  /*
   284   * support for morestack
   285   */
   286  
   287  // Called during function prolog when more stack is needed.
   288  // Caller has already loaded:
   289  // R3: framesize, R4: argsize, R5: LR
   290  //
   291  // The traceback routines see morestack on a g0 as being
   292  // the top of a stack (for example, morestack calling newstack
   293  // calling the scheduler calling newm calling gc), so we must
   294  // record an argument size. For that purpose, it has no arguments.
   295  TEXT runtime·morestack(SB),NOSPLIT|NOFRAME,$0-0
   296  	// Cannot grow scheduler stack (m->g0).
   297  	MOVD	g_m(g), R7
   298  	MOVD	m_g0(R7), R8
   299  	CMP	g, R8
   300  	BNE	3(PC)
   301  	BL	runtime·badmorestackg0(SB)
   302  	BL	runtime·abort(SB)
   303  
   304  	// Cannot grow signal stack (m->gsignal).
   305  	MOVD	m_gsignal(R7), R8
   306  	CMP	g, R8
   307  	BNE	3(PC)
   308  	BL	runtime·badmorestackgsignal(SB)
   309  	BL	runtime·abort(SB)
   310  
   311  	// Called from f.
   312  	// Set g->sched to context in f.
   313  	MOVD	R1, (g_sched+gobuf_sp)(g)
   314  	MOVD	LR, R8
   315  	MOVD	R8, (g_sched+gobuf_pc)(g)
   316  	MOVD	R5, (g_sched+gobuf_lr)(g)
   317  	MOVD	R11, (g_sched+gobuf_ctxt)(g)
   318  
   319  	// Called from f.
   320  	// Set m->morebuf to f's caller.
   321  	MOVD	R5, (m_morebuf+gobuf_pc)(R7)	// f's caller's PC
   322  	MOVD	R1, (m_morebuf+gobuf_sp)(R7)	// f's caller's SP
   323  	MOVD	g, (m_morebuf+gobuf_g)(R7)
   324  
   325  	// Call newstack on m->g0's stack.
   326  	MOVD	m_g0(R7), g
   327  	BL	runtime·save_g(SB)
   328  	MOVD	(g_sched+gobuf_sp)(g), R1
   329  	MOVDU   R0, -(FIXED_FRAME+0)(R1)	// create a call frame on g0
   330  	BL	runtime·newstack(SB)
   331  
   332  	// Not reached, but make sure the return PC from the call to newstack
   333  	// is still in this function, and not the beginning of the next.
   334  	UNDEF
   335  
   336  TEXT runtime·morestack_noctxt(SB),NOSPLIT|NOFRAME,$0-0
   337  	// Force SPWRITE. This function doesn't actually write SP,
   338  	// but it is called with a special calling convention where
   339  	// the caller doesn't save LR on stack but passes it as a
   340  	// register (R5), and the unwinder currently doesn't understand.
   341  	// Make it SPWRITE to stop unwinding. (See issue 54332)
   342  	// Use OR R0, R1 instead of MOVD R1, R1 as the MOVD instruction
   343  	// has a special affect on Power8,9,10 by lowering the thread 
   344  	// priority and causing a slowdown in execution time
   345  
   346  	OR	R0, R1
   347  	MOVD	R0, R11
   348  	BR	runtime·morestack(SB)
   349  
   350  // reflectcall: call a function with the given argument list
   351  // func call(stackArgsType *_type, f *FuncVal, stackArgs *byte, stackArgsSize, stackRetOffset, frameSize uint32, regArgs *abi.RegArgs).
   352  // we don't have variable-sized frames, so we use a small number
   353  // of constant-sized-frame functions to encode a few bits of size in the pc.
   354  // Caution: ugly multiline assembly macros in your future!
   355  
   356  #define DISPATCH(NAME,MAXSIZE)		\
   357  	MOVD	$MAXSIZE, R31;		\
   358  	CMP	R3, R31;		\
   359  	BGT	4(PC);			\
   360  	MOVD	$NAME(SB), R12;		\
   361  	MOVD	R12, CTR;		\
   362  	BR	(CTR)
   363  // Note: can't just "BR NAME(SB)" - bad inlining results.
   364  
   365  TEXT ·reflectcall(SB), NOSPLIT|NOFRAME, $0-48
   366  	MOVWZ	frameSize+32(FP), R3
   367  	DISPATCH(runtime·call16, 16)
   368  	DISPATCH(runtime·call32, 32)
   369  	DISPATCH(runtime·call64, 64)
   370  	DISPATCH(runtime·call128, 128)
   371  	DISPATCH(runtime·call256, 256)
   372  	DISPATCH(runtime·call512, 512)
   373  	DISPATCH(runtime·call1024, 1024)
   374  	DISPATCH(runtime·call2048, 2048)
   375  	DISPATCH(runtime·call4096, 4096)
   376  	DISPATCH(runtime·call8192, 8192)
   377  	DISPATCH(runtime·call16384, 16384)
   378  	DISPATCH(runtime·call32768, 32768)
   379  	DISPATCH(runtime·call65536, 65536)
   380  	DISPATCH(runtime·call131072, 131072)
   381  	DISPATCH(runtime·call262144, 262144)
   382  	DISPATCH(runtime·call524288, 524288)
   383  	DISPATCH(runtime·call1048576, 1048576)
   384  	DISPATCH(runtime·call2097152, 2097152)
   385  	DISPATCH(runtime·call4194304, 4194304)
   386  	DISPATCH(runtime·call8388608, 8388608)
   387  	DISPATCH(runtime·call16777216, 16777216)
   388  	DISPATCH(runtime·call33554432, 33554432)
   389  	DISPATCH(runtime·call67108864, 67108864)
   390  	DISPATCH(runtime·call134217728, 134217728)
   391  	DISPATCH(runtime·call268435456, 268435456)
   392  	DISPATCH(runtime·call536870912, 536870912)
   393  	DISPATCH(runtime·call1073741824, 1073741824)
   394  	MOVD	$runtime·badreflectcall(SB), R12
   395  	MOVD	R12, CTR
   396  	BR	(CTR)
   397  
   398  #define CALLFN(NAME,MAXSIZE)			\
   399  TEXT NAME(SB), WRAPPER, $MAXSIZE-48;		\
   400  	NO_LOCAL_POINTERS;			\
   401  	/* copy arguments to stack */		\
   402  	MOVD	stackArgs+16(FP), R3;			\
   403  	MOVWZ	stackArgsSize+24(FP), R4;			\
   404  	MOVD    R1, R5;				\
   405  	CMP	R4, $8;				\
   406  	BLT	tailsetup;			\
   407  	/* copy 8 at a time if possible */	\
   408  	ADD	$(FIXED_FRAME-8), R5;			\
   409  	SUB	$8, R3;				\
   410  top: \
   411  	MOVDU	8(R3), R7;			\
   412  	MOVDU	R7, 8(R5);			\
   413  	SUB	$8, R4;				\
   414  	CMP	R4, $8;				\
   415  	BGE	top;				\
   416  	/* handle remaining bytes */	\
   417  	CMP	$0, R4;			\
   418  	BEQ	callfn;			\
   419  	ADD	$7, R3;			\
   420  	ADD	$7, R5;			\
   421  	BR	tail;			\
   422  tailsetup: \
   423  	CMP	$0, R4;			\
   424  	BEQ	callfn;			\
   425  	ADD     $(FIXED_FRAME-1), R5;	\
   426  	SUB     $1, R3;			\
   427  tail: \
   428  	MOVBU	1(R3), R6;		\
   429  	MOVBU	R6, 1(R5);		\
   430  	SUB	$1, R4;			\
   431  	CMP	$0, R4;			\
   432  	BGT	tail;			\
   433  callfn: \
   434  	/* call function */			\
   435  	MOVD	f+8(FP), R11;			\
   436  #ifdef GOOS_aix				\
   437  	/* AIX won't trigger a SIGSEGV if R11 = nil */	\
   438  	/* So it manually triggers it */	\
   439  	CMP	R0, R11				\
   440  	BNE	2(PC)				\
   441  	MOVD	R0, 0(R0)			\
   442  #endif						\
   443  	MOVD    regArgs+40(FP), R20;    \
   444  	BL      runtime·unspillArgs(SB);        \
   445  	MOVD	(R11), R12;			\
   446  	MOVD	R12, CTR;			\
   447  	PCDATA  $PCDATA_StackMapIndex, $0;	\
   448  	BL	(CTR);				\
   449  #ifndef GOOS_aix				\
   450  	MOVD	24(R1), R2;			\
   451  #endif						\
   452  	/* copy return values back */		\
   453  	MOVD	regArgs+40(FP), R20;		\
   454  	BL	runtime·spillArgs(SB);			\
   455  	MOVD	stackArgsType+0(FP), R7;		\
   456  	MOVD	stackArgs+16(FP), R3;			\
   457  	MOVWZ	stackArgsSize+24(FP), R4;			\
   458  	MOVWZ	stackRetOffset+28(FP), R6;		\
   459  	ADD	$FIXED_FRAME, R1, R5;		\
   460  	ADD	R6, R5; 			\
   461  	ADD	R6, R3;				\
   462  	SUB	R6, R4;				\
   463  	BL	callRet<>(SB);			\
   464  	RET
   465  
   466  // callRet copies return values back at the end of call*. This is a
   467  // separate function so it can allocate stack space for the arguments
   468  // to reflectcallmove. It does not follow the Go ABI; it expects its
   469  // arguments in registers.
   470  TEXT callRet<>(SB), NOSPLIT, $40-0
   471  	NO_LOCAL_POINTERS
   472  	MOVD	R7, FIXED_FRAME+0(R1)
   473  	MOVD	R3, FIXED_FRAME+8(R1)
   474  	MOVD	R5, FIXED_FRAME+16(R1)
   475  	MOVD	R4, FIXED_FRAME+24(R1)
   476  	MOVD	R20, FIXED_FRAME+32(R1)
   477  	BL	runtime·reflectcallmove(SB)
   478  	RET
   479  
   480  CALLFN(·call16, 16)
   481  CALLFN(·call32, 32)
   482  CALLFN(·call64, 64)
   483  CALLFN(·call128, 128)
   484  CALLFN(·call256, 256)
   485  CALLFN(·call512, 512)
   486  CALLFN(·call1024, 1024)
   487  CALLFN(·call2048, 2048)
   488  CALLFN(·call4096, 4096)
   489  CALLFN(·call8192, 8192)
   490  CALLFN(·call16384, 16384)
   491  CALLFN(·call32768, 32768)
   492  CALLFN(·call65536, 65536)
   493  CALLFN(·call131072, 131072)
   494  CALLFN(·call262144, 262144)
   495  CALLFN(·call524288, 524288)
   496  CALLFN(·call1048576, 1048576)
   497  CALLFN(·call2097152, 2097152)
   498  CALLFN(·call4194304, 4194304)
   499  CALLFN(·call8388608, 8388608)
   500  CALLFN(·call16777216, 16777216)
   501  CALLFN(·call33554432, 33554432)
   502  CALLFN(·call67108864, 67108864)
   503  CALLFN(·call134217728, 134217728)
   504  CALLFN(·call268435456, 268435456)
   505  CALLFN(·call536870912, 536870912)
   506  CALLFN(·call1073741824, 1073741824)
   507  
   508  TEXT runtime·procyield(SB),NOSPLIT|NOFRAME,$0-4
   509  	MOVW	cycles+0(FP), R7
   510  	// POWER does not have a pause/yield instruction equivalent.
   511  	// Instead, we can lower the program priority by setting the
   512  	// Program Priority Register prior to the wait loop and set it
   513  	// back to default afterwards. On Linux, the default priority is
   514  	// medium-low. For details, see page 837 of the ISA 3.0.
   515  	OR	R1, R1, R1	// Set PPR priority to low
   516  again:
   517  	SUB	$1, R7
   518  	CMP	$0, R7
   519  	BNE	again
   520  	OR	R6, R6, R6	// Set PPR priority back to medium-low
   521  	RET
   522  
   523  // Save state of caller into g->sched,
   524  // but using fake PC from systemstack_switch.
   525  // Must only be called from functions with no locals ($0)
   526  // or else unwinding from systemstack_switch is incorrect.
   527  // Smashes R31.
   528  TEXT gosave_systemstack_switch<>(SB),NOSPLIT|NOFRAME,$0
   529  	MOVD	$runtime·systemstack_switch(SB), R31
   530  	ADD     $16, R31 // get past prologue (including r2-setting instructions when they're there)
   531  	MOVD	R31, (g_sched+gobuf_pc)(g)
   532  	MOVD	R1, (g_sched+gobuf_sp)(g)
   533  	MOVD	R0, (g_sched+gobuf_lr)(g)
   534  	MOVD	R0, (g_sched+gobuf_ret)(g)
   535  	// Assert ctxt is zero. See func save.
   536  	MOVD	(g_sched+gobuf_ctxt)(g), R31
   537  	CMP	R0, R31
   538  	BEQ	2(PC)
   539  	BL	runtime·abort(SB)
   540  	RET
   541  
   542  #ifdef GOOS_aix
   543  #define asmcgocallSaveOffset cgoCalleeStackSize + 8
   544  #else
   545  #define asmcgocallSaveOffset cgoCalleeStackSize
   546  #endif
   547  
   548  // func asmcgocall(fn, arg unsafe.Pointer) int32
   549  // Call fn(arg) on the scheduler stack,
   550  // aligned appropriately for the gcc ABI.
   551  // See cgocall.go for more details.
   552  TEXT ·asmcgocall(SB),NOSPLIT,$0-20
   553  	MOVD	fn+0(FP), R3
   554  	MOVD	arg+8(FP), R4
   555  
   556  	MOVD	R1, R7		// save original stack pointer
   557  	MOVD	g, R5
   558  
   559  	// Figure out if we need to switch to m->g0 stack.
   560  	// We get called to create new OS threads too, and those
   561  	// come in on the m->g0 stack already. Or we might already
   562  	// be on the m->gsignal stack.
   563  	MOVD	g_m(g), R8
   564  	MOVD	m_gsignal(R8), R6
   565  	CMP	R6, g
   566  	BEQ	g0
   567  	MOVD	m_g0(R8), R6
   568  	CMP	R6, g
   569  	BEQ	g0
   570  	BL	gosave_systemstack_switch<>(SB)
   571  	MOVD	R6, g
   572  	BL	runtime·save_g(SB)
   573  	MOVD	(g_sched+gobuf_sp)(g), R1
   574  
   575  	// Now on a scheduling stack (a pthread-created stack).
   576  g0:
   577  #ifdef GOOS_aix
   578  	// Create a fake LR to improve backtrace.
   579  	MOVD	$runtime·asmcgocall(SB), R6
   580  	MOVD	R6, 16(R1)
   581  	// AIX also save one argument on the stack.
   582  	SUB $8, R1
   583  #endif
   584  	// Save room for two of our pointers, plus the callee
   585  	// save area that lives on the caller stack.
   586  	SUB	$(asmcgocallSaveOffset+16), R1
   587  	RLDCR	$0, R1, $~15, R1	// 16-byte alignment for gcc ABI
   588  	MOVD	R5, (asmcgocallSaveOffset+8)(R1)// save old g on stack
   589  	MOVD	(g_stack+stack_hi)(R5), R5
   590  	SUB	R7, R5
   591  	MOVD	R5, asmcgocallSaveOffset(R1)    // save depth in old g stack (can't just save SP, as stack might be copied during a callback)
   592  #ifdef GOOS_aix
   593  	MOVD	R7, 0(R1)	// Save frame pointer to allow manual backtrace with gdb
   594  #else
   595  	MOVD	R0, 0(R1)	// clear back chain pointer (TODO can we give it real back trace information?)
   596  #endif
   597  	// This is a "global call", so put the global entry point in r12
   598  	MOVD	R3, R12
   599  
   600  #ifdef GO_PPC64X_HAS_FUNCDESC
   601  	// Load the real entry address from the first slot of the function descriptor.
   602  	MOVD	8(R12), R2
   603  	MOVD	(R12), R12
   604  #endif
   605  	MOVD	R12, CTR
   606  	MOVD	R4, R3		// arg in r3
   607  	BL	(CTR)
   608  	// C code can clobber R0, so set it back to 0. F27-F31 are
   609  	// callee save, so we don't need to recover those.
   610  	XOR	R0, R0
   611  	// Restore g, stack pointer, toc pointer.
   612  	// R3 is errno, so don't touch it
   613  	MOVD	(asmcgocallSaveOffset+8)(R1), g
   614  	MOVD	(g_stack+stack_hi)(g), R5
   615  	MOVD	asmcgocallSaveOffset(R1), R6
   616  	SUB	R6, R5
   617  #ifndef GOOS_aix
   618  	MOVD	24(R5), R2
   619  #endif
   620  	MOVD	R5, R1
   621  	BL	runtime·save_g(SB)
   622  
   623  	MOVW	R3, ret+16(FP)
   624  	RET
   625  
   626  // func cgocallback(fn, frame unsafe.Pointer, ctxt uintptr)
   627  // See cgocall.go for more details.
   628  TEXT ·cgocallback(SB),NOSPLIT,$24-24
   629  	NO_LOCAL_POINTERS
   630  
   631  	// Load m and g from thread-local storage.
   632  	MOVBZ	runtime·iscgo(SB), R3
   633  	CMP	R3, $0
   634  	BEQ	nocgo
   635  	BL	runtime·load_g(SB)
   636  nocgo:
   637  
   638  	// If g is nil, Go did not create the current thread.
   639  	// Call needm to obtain one for temporary use.
   640  	// In this case, we're running on the thread stack, so there's
   641  	// lots of space, but the linker doesn't know. Hide the call from
   642  	// the linker analysis by using an indirect call.
   643  	CMP	g, $0
   644  	BEQ	needm
   645  
   646  	MOVD	g_m(g), R8
   647  	MOVD	R8, savedm-8(SP)
   648  	BR	havem
   649  
   650  needm:
   651  	MOVD	g, savedm-8(SP) // g is zero, so is m.
   652  	MOVD	$runtime·needm(SB), R12
   653  	MOVD	R12, CTR
   654  	BL	(CTR)
   655  
   656  	// Set m->sched.sp = SP, so that if a panic happens
   657  	// during the function we are about to execute, it will
   658  	// have a valid SP to run on the g0 stack.
   659  	// The next few lines (after the havem label)
   660  	// will save this SP onto the stack and then write
   661  	// the same SP back to m->sched.sp. That seems redundant,
   662  	// but if an unrecovered panic happens, unwindm will
   663  	// restore the g->sched.sp from the stack location
   664  	// and then systemstack will try to use it. If we don't set it here,
   665  	// that restored SP will be uninitialized (typically 0) and
   666  	// will not be usable.
   667  	MOVD	g_m(g), R8
   668  	MOVD	m_g0(R8), R3
   669  	MOVD	R1, (g_sched+gobuf_sp)(R3)
   670  
   671  havem:
   672  	// Now there's a valid m, and we're running on its m->g0.
   673  	// Save current m->g0->sched.sp on stack and then set it to SP.
   674  	// Save current sp in m->g0->sched.sp in preparation for
   675  	// switch back to m->curg stack.
   676  	// NOTE: unwindm knows that the saved g->sched.sp is at 8(R1) aka savedsp-16(SP).
   677  	MOVD	m_g0(R8), R3
   678  	MOVD	(g_sched+gobuf_sp)(R3), R4
   679  	MOVD	R4, savedsp-24(SP)      // must match frame size
   680  	MOVD	R1, (g_sched+gobuf_sp)(R3)
   681  
   682  	// Switch to m->curg stack and call runtime.cgocallbackg.
   683  	// Because we are taking over the execution of m->curg
   684  	// but *not* resuming what had been running, we need to
   685  	// save that information (m->curg->sched) so we can restore it.
   686  	// We can restore m->curg->sched.sp easily, because calling
   687  	// runtime.cgocallbackg leaves SP unchanged upon return.
   688  	// To save m->curg->sched.pc, we push it onto the curg stack and
   689  	// open a frame the same size as cgocallback's g0 frame.
   690  	// Once we switch to the curg stack, the pushed PC will appear
   691  	// to be the return PC of cgocallback, so that the traceback
   692  	// will seamlessly trace back into the earlier calls.
   693  	MOVD	m_curg(R8), g
   694  	BL	runtime·save_g(SB)
   695  	MOVD	(g_sched+gobuf_sp)(g), R4 // prepare stack as R4
   696  	MOVD	(g_sched+gobuf_pc)(g), R5
   697  	MOVD	R5, -(24+FIXED_FRAME)(R4)       // "saved LR"; must match frame size
   698  	// Gather our arguments into registers.
   699  	MOVD	fn+0(FP), R5
   700  	MOVD	frame+8(FP), R6
   701  	MOVD	ctxt+16(FP), R7
   702  	MOVD	$-(24+FIXED_FRAME)(R4), R1      // switch stack; must match frame size
   703  	MOVD    R5, FIXED_FRAME+0(R1)
   704  	MOVD    R6, FIXED_FRAME+8(R1)
   705  	MOVD    R7, FIXED_FRAME+16(R1)
   706  
   707  	MOVD	$runtime·cgocallbackg(SB), R12
   708  	MOVD	R12, CTR
   709  	CALL	(CTR) // indirect call to bypass nosplit check. We're on a different stack now.
   710  
   711  	// Restore g->sched (== m->curg->sched) from saved values.
   712  	MOVD	0(R1), R5
   713  	MOVD	R5, (g_sched+gobuf_pc)(g)
   714  	MOVD	$(24+FIXED_FRAME)(R1), R4       // must match frame size
   715  	MOVD	R4, (g_sched+gobuf_sp)(g)
   716  
   717  	// Switch back to m->g0's stack and restore m->g0->sched.sp.
   718  	// (Unlike m->curg, the g0 goroutine never uses sched.pc,
   719  	// so we do not have to restore it.)
   720  	MOVD	g_m(g), R8
   721  	MOVD	m_g0(R8), g
   722  	BL	runtime·save_g(SB)
   723  	MOVD	(g_sched+gobuf_sp)(g), R1
   724  	MOVD	savedsp-24(SP), R4      // must match frame size
   725  	MOVD	R4, (g_sched+gobuf_sp)(g)
   726  
   727  	// If the m on entry was nil, we called needm above to borrow an m
   728  	// for the duration of the call. Since the call is over, return it with dropm.
   729  	MOVD	savedm-8(SP), R6
   730  	CMP	R6, $0
   731  	BNE	droppedm
   732  	MOVD	$runtime·dropm(SB), R12
   733  	MOVD	R12, CTR
   734  	BL	(CTR)
   735  droppedm:
   736  
   737  	// Done!
   738  	RET
   739  
   740  // void setg(G*); set g. for use by needm.
   741  TEXT runtime·setg(SB), NOSPLIT, $0-8
   742  	MOVD	gg+0(FP), g
   743  	// This only happens if iscgo, so jump straight to save_g
   744  	BL	runtime·save_g(SB)
   745  	RET
   746  
   747  #ifdef GO_PPC64X_HAS_FUNCDESC
   748  DEFINE_PPC64X_FUNCDESC(setg_gcc<>, _setg_gcc<>)
   749  TEXT _setg_gcc<>(SB),NOSPLIT|NOFRAME,$0-0
   750  #else
   751  TEXT setg_gcc<>(SB),NOSPLIT|NOFRAME,$0-0
   752  #endif
   753  	// The standard prologue clobbers R31, which is callee-save in
   754  	// the C ABI, so we have to use $-8-0 and save LR ourselves.
   755  	MOVD	LR, R4
   756  	// Also save g and R31, since they're callee-save in C ABI
   757  	MOVD	R31, R5
   758  	MOVD	g, R6
   759  
   760  	MOVD	R3, g
   761  	BL	runtime·save_g(SB)
   762  
   763  	MOVD	R6, g
   764  	MOVD	R5, R31
   765  	MOVD	R4, LR
   766  	RET
   767  
   768  TEXT runtime·abort(SB),NOSPLIT|NOFRAME,$0-0
   769  	MOVW	(R0), R0
   770  	UNDEF
   771  
   772  #define	TBR	268
   773  
   774  // int64 runtime·cputicks(void)
   775  TEXT runtime·cputicks(SB),NOSPLIT,$0-8
   776  	MOVD	SPR(TBR), R3
   777  	MOVD	R3, ret+0(FP)
   778  	RET
   779  
   780  // spillArgs stores return values from registers to a *internal/abi.RegArgs in R20.
   781  TEXT runtime·spillArgs(SB),NOSPLIT,$0-0
   782  	MOVD    R3, 0(R20)
   783  	MOVD    R4, 8(R20)
   784  	MOVD    R5, 16(R20)
   785  	MOVD    R6, 24(R20)
   786  	MOVD    R7, 32(R20)
   787  	MOVD    R8, 40(R20)
   788  	MOVD    R9, 48(R20)
   789  	MOVD    R10, 56(R20)
   790  	MOVD	R14, 64(R20)
   791  	MOVD	R15, 72(R20)
   792  	MOVD	R16, 80(R20)
   793  	MOVD	R17, 88(R20)
   794  	FMOVD	F1, 96(R20)
   795  	FMOVD	F2, 104(R20)
   796  	FMOVD   F3, 112(R20)
   797  	FMOVD   F4, 120(R20)
   798  	FMOVD   F5, 128(R20)
   799  	FMOVD   F6, 136(R20)
   800  	FMOVD   F7, 144(R20)
   801  	FMOVD   F8, 152(R20)
   802  	FMOVD   F9, 160(R20)
   803  	FMOVD   F10, 168(R20)
   804  	FMOVD   F11, 176(R20)
   805  	FMOVD   F12, 184(R20)
   806  	RET
   807  
   808  // unspillArgs loads args into registers from a *internal/abi.RegArgs in R20.
   809  TEXT runtime·unspillArgs(SB),NOSPLIT,$0-0
   810  	MOVD    0(R20), R3
   811  	MOVD    8(R20), R4
   812  	MOVD    16(R20), R5
   813  	MOVD    24(R20), R6
   814  	MOVD    32(R20), R7
   815  	MOVD    40(R20), R8
   816  	MOVD    48(R20), R9
   817  	MOVD    56(R20), R10
   818  	MOVD    64(R20), R14
   819  	MOVD    72(R20), R15
   820  	MOVD    80(R20), R16
   821  	MOVD    88(R20), R17
   822  	FMOVD   96(R20), F1
   823  	FMOVD   104(R20), F2
   824  	FMOVD   112(R20), F3
   825  	FMOVD   120(R20), F4
   826  	FMOVD   128(R20), F5
   827  	FMOVD   136(R20), F6
   828  	FMOVD   144(R20), F7
   829  	FMOVD   152(R20), F8
   830  	FMOVD   160(R20), F9
   831  	FMOVD	168(R20), F10
   832  	FMOVD	176(R20), F11
   833  	FMOVD	184(R20), F12
   834  	RET
   835  
   836  // AES hashing not implemented for ppc64
   837  TEXT runtime·memhash<ABIInternal>(SB),NOSPLIT|NOFRAME,$0-32
   838  	JMP	runtime·memhashFallback<ABIInternal>(SB)
   839  TEXT runtime·strhash<ABIInternal>(SB),NOSPLIT|NOFRAME,$0-24
   840  	JMP	runtime·strhashFallback<ABIInternal>(SB)
   841  TEXT runtime·memhash32<ABIInternal>(SB),NOSPLIT|NOFRAME,$0-24
   842  	JMP	runtime·memhash32Fallback<ABIInternal>(SB)
   843  TEXT runtime·memhash64<ABIInternal>(SB),NOSPLIT|NOFRAME,$0-24
   844  	JMP	runtime·memhash64Fallback<ABIInternal>(SB)
   845  
   846  TEXT runtime·return0(SB), NOSPLIT, $0
   847  	MOVW	$0, R3
   848  	RET
   849  
   850  // Called from cgo wrappers, this function returns g->m->curg.stack.hi.
   851  // Must obey the gcc calling convention.
   852  #ifdef GOOS_aix
   853  // On AIX, _cgo_topofstack is defined in runtime/cgo, because it must
   854  // be a longcall in order to prevent trampolines from ld.
   855  TEXT __cgo_topofstack(SB),NOSPLIT|NOFRAME,$0
   856  #else
   857  TEXT _cgo_topofstack(SB),NOSPLIT|NOFRAME,$0
   858  #endif
   859  	// g (R30) and R31 are callee-save in the C ABI, so save them
   860  	MOVD	g, R4
   861  	MOVD	R31, R5
   862  	MOVD	LR, R6
   863  
   864  	BL	runtime·load_g(SB)	// clobbers g (R30), R31
   865  	MOVD	g_m(g), R3
   866  	MOVD	m_curg(R3), R3
   867  	MOVD	(g_stack+stack_hi)(R3), R3
   868  
   869  	MOVD	R4, g
   870  	MOVD	R5, R31
   871  	MOVD	R6, LR
   872  	RET
   873  
   874  // The top-most function running on a goroutine
   875  // returns to goexit+PCQuantum.
   876  //
   877  // When dynamically linking Go, it can be returned to from a function
   878  // implemented in a different module and so needs to reload the TOC pointer
   879  // from the stack (although this function declares that it does not set up x-a
   880  // frame, newproc1 does in fact allocate one for goexit and saves the TOC
   881  // pointer in the correct place).
   882  // goexit+_PCQuantum is halfway through the usual global entry point prologue
   883  // that derives r2 from r12 which is a bit silly, but not harmful.
   884  TEXT runtime·goexit(SB),NOSPLIT|NOFRAME|TOPFRAME,$0-0
   885  	MOVD	24(R1), R2
   886  	BL	runtime·goexit1(SB)	// does not return
   887  	// traceback from goexit1 must hit code range of goexit
   888  	MOVD	R0, R0	// NOP
   889  
   890  // prepGoExitFrame saves the current TOC pointer (i.e. the TOC pointer for the
   891  // module containing runtime) to the frame that goexit will execute in when
   892  // the goroutine exits. It's implemented in assembly mainly because that's the
   893  // easiest way to get access to R2.
   894  TEXT runtime·prepGoExitFrame(SB),NOSPLIT,$0-8
   895  	MOVD    sp+0(FP), R3
   896  	MOVD    R2, 24(R3)
   897  	RET
   898  
   899  TEXT runtime·addmoduledata(SB),NOSPLIT|NOFRAME,$0-0
   900  	ADD	$-8, R1
   901  	MOVD	R31, 0(R1)
   902  	MOVD	runtime·lastmoduledatap(SB), R4
   903  	MOVD	R3, moduledata_next(R4)
   904  	MOVD	R3, runtime·lastmoduledatap(SB)
   905  	MOVD	0(R1), R31
   906  	ADD	$8, R1
   907  	RET
   908  
   909  TEXT ·checkASM(SB),NOSPLIT,$0-1
   910  	MOVW	$1, R3
   911  	MOVB	R3, ret+0(FP)
   912  	RET
   913  
   914  // gcWriteBarrier informs the GC about heap pointer writes.
   915  //
   916  // gcWriteBarrier does NOT follow the Go ABI. It accepts the
   917  // number of bytes of buffer needed in R29, and returns a pointer
   918  // to the buffer space in R29.
   919  // It clobbers condition codes.
   920  // It does not clobber R0 through R17 (except special registers),
   921  // but may clobber any other register, *including* R31.
   922  TEXT gcWriteBarrier<>(SB),NOSPLIT,$112
   923  	// The standard prologue clobbers R31.
   924  	// We use R18, R19, and R31 as scratch registers.
   925  retry:
   926  	MOVD	g_m(g), R18
   927  	MOVD	m_p(R18), R18
   928  	MOVD	(p_wbBuf+wbBuf_next)(R18), R19
   929  	MOVD	(p_wbBuf+wbBuf_end)(R18), R31
   930  	// Increment wbBuf.next position.
   931  	ADD	R29, R19
   932  	// Is the buffer full?
   933  	CMPU	R31, R19
   934  	BLT	flush
   935  	// Commit to the larger buffer.
   936  	MOVD	R19, (p_wbBuf+wbBuf_next)(R18)
   937  	// Make return value (the original next position)
   938  	SUB	R29, R19, R29
   939  	RET
   940  
   941  flush:
   942  	// Save registers R0 through R15 since these were not saved by the caller.
   943  	// We don't save all registers on ppc64 because it takes too much space.
   944  	MOVD	R20, (FIXED_FRAME+0)(R1)
   945  	MOVD	R21, (FIXED_FRAME+8)(R1)
   946  	// R0 is always 0, so no need to spill.
   947  	// R1 is SP.
   948  	// R2 is SB.
   949  	MOVD	R3, (FIXED_FRAME+16)(R1)
   950  	MOVD	R4, (FIXED_FRAME+24)(R1)
   951  	MOVD	R5, (FIXED_FRAME+32)(R1)
   952  	MOVD	R6, (FIXED_FRAME+40)(R1)
   953  	MOVD	R7, (FIXED_FRAME+48)(R1)
   954  	MOVD	R8, (FIXED_FRAME+56)(R1)
   955  	MOVD	R9, (FIXED_FRAME+64)(R1)
   956  	MOVD	R10, (FIXED_FRAME+72)(R1)
   957  	// R11, R12 may be clobbered by external-linker-inserted trampoline
   958  	// R13 is REGTLS
   959  	MOVD	R14, (FIXED_FRAME+80)(R1)
   960  	MOVD	R15, (FIXED_FRAME+88)(R1)
   961  	MOVD	R16, (FIXED_FRAME+96)(R1)
   962  	MOVD	R17, (FIXED_FRAME+104)(R1)
   963  
   964  	CALL	runtime·wbBufFlush(SB)
   965  
   966  	MOVD	(FIXED_FRAME+0)(R1), R20
   967  	MOVD	(FIXED_FRAME+8)(R1), R21
   968  	MOVD	(FIXED_FRAME+16)(R1), R3
   969  	MOVD	(FIXED_FRAME+24)(R1), R4
   970  	MOVD	(FIXED_FRAME+32)(R1), R5
   971  	MOVD	(FIXED_FRAME+40)(R1), R6
   972  	MOVD	(FIXED_FRAME+48)(R1), R7
   973  	MOVD	(FIXED_FRAME+56)(R1), R8
   974  	MOVD	(FIXED_FRAME+64)(R1), R9
   975  	MOVD	(FIXED_FRAME+72)(R1), R10
   976  	MOVD	(FIXED_FRAME+80)(R1), R14
   977  	MOVD	(FIXED_FRAME+88)(R1), R15
   978  	MOVD	(FIXED_FRAME+96)(R1), R16
   979  	MOVD	(FIXED_FRAME+104)(R1), R17
   980  	JMP	retry
   981  
   982  TEXT runtime·gcWriteBarrier1<ABIInternal>(SB),NOSPLIT,$0
   983  	MOVD	$8, R29
   984  	JMP	gcWriteBarrier<>(SB)
   985  TEXT runtime·gcWriteBarrier2<ABIInternal>(SB),NOSPLIT,$0
   986  	MOVD	$16, R29
   987  	JMP	gcWriteBarrier<>(SB)
   988  TEXT runtime·gcWriteBarrier3<ABIInternal>(SB),NOSPLIT,$0
   989  	MOVD	$24, R29
   990  	JMP	gcWriteBarrier<>(SB)
   991  TEXT runtime·gcWriteBarrier4<ABIInternal>(SB),NOSPLIT,$0
   992  	MOVD	$32, R29
   993  	JMP	gcWriteBarrier<>(SB)
   994  TEXT runtime·gcWriteBarrier5<ABIInternal>(SB),NOSPLIT,$0
   995  	MOVD	$40, R29
   996  	JMP	gcWriteBarrier<>(SB)
   997  TEXT runtime·gcWriteBarrier6<ABIInternal>(SB),NOSPLIT,$0
   998  	MOVD	$48, R29
   999  	JMP	gcWriteBarrier<>(SB)
  1000  TEXT runtime·gcWriteBarrier7<ABIInternal>(SB),NOSPLIT,$0
  1001  	MOVD	$56, R29
  1002  	JMP	gcWriteBarrier<>(SB)
  1003  TEXT runtime·gcWriteBarrier8<ABIInternal>(SB),NOSPLIT,$0
  1004  	MOVD	$64, R29
  1005  	JMP	gcWriteBarrier<>(SB)
  1006  
  1007  // Note: these functions use a special calling convention to save generated code space.
  1008  // Arguments are passed in registers, but the space for those arguments are allocated
  1009  // in the caller's stack frame. These stubs write the args into that stack space and
  1010  // then tail call to the corresponding runtime handler.
  1011  // The tail call makes these stubs disappear in backtraces.
  1012  TEXT runtime·panicIndex<ABIInternal>(SB),NOSPLIT,$0-16
  1013  	JMP	runtime·goPanicIndex<ABIInternal>(SB)
  1014  TEXT runtime·panicIndexU<ABIInternal>(SB),NOSPLIT,$0-16
  1015  	JMP	runtime·goPanicIndexU<ABIInternal>(SB)
  1016  TEXT runtime·panicSliceAlen<ABIInternal>(SB),NOSPLIT,$0-16
  1017  	MOVD	R4, R3
  1018  	MOVD	R5, R4
  1019  	JMP	runtime·goPanicSliceAlen<ABIInternal>(SB)
  1020  TEXT runtime·panicSliceAlenU<ABIInternal>(SB),NOSPLIT,$0-16
  1021  	MOVD	R4, R3
  1022  	MOVD	R5, R4
  1023  	JMP	runtime·goPanicSliceAlenU<ABIInternal>(SB)
  1024  TEXT runtime·panicSliceAcap<ABIInternal>(SB),NOSPLIT,$0-16
  1025  	MOVD	R4, R3
  1026  	MOVD	R5, R4
  1027  	JMP	runtime·goPanicSliceAcap<ABIInternal>(SB)
  1028  TEXT runtime·panicSliceAcapU<ABIInternal>(SB),NOSPLIT,$0-16
  1029  	MOVD	R4, R3
  1030  	MOVD	R5, R4
  1031  	JMP	runtime·goPanicSliceAcapU<ABIInternal>(SB)
  1032  TEXT runtime·panicSliceB<ABIInternal>(SB),NOSPLIT,$0-16
  1033  	JMP	runtime·goPanicSliceB<ABIInternal>(SB)
  1034  TEXT runtime·panicSliceBU<ABIInternal>(SB),NOSPLIT,$0-16
  1035  	JMP	runtime·goPanicSliceBU<ABIInternal>(SB)
  1036  TEXT runtime·panicSlice3Alen<ABIInternal>(SB),NOSPLIT,$0-16
  1037  	MOVD	R5, R3
  1038  	MOVD	R6, R4
  1039  	JMP	runtime·goPanicSlice3Alen<ABIInternal>(SB)
  1040  TEXT runtime·panicSlice3AlenU<ABIInternal>(SB),NOSPLIT,$0-16
  1041  	MOVD	R5, R3
  1042  	MOVD	R6, R4
  1043  	JMP	runtime·goPanicSlice3AlenU<ABIInternal>(SB)
  1044  TEXT runtime·panicSlice3Acap<ABIInternal>(SB),NOSPLIT,$0-16
  1045  	MOVD	R5, R3
  1046  	MOVD	R6, R4
  1047  	JMP	runtime·goPanicSlice3Acap<ABIInternal>(SB)
  1048  TEXT runtime·panicSlice3AcapU<ABIInternal>(SB),NOSPLIT,$0-16
  1049  	MOVD	R5, R3
  1050  	MOVD	R6, R4
  1051  	JMP	runtime·goPanicSlice3AcapU<ABIInternal>(SB)
  1052  TEXT runtime·panicSlice3B<ABIInternal>(SB),NOSPLIT,$0-16
  1053  	MOVD	R4, R3
  1054  	MOVD	R5, R4
  1055  	JMP	runtime·goPanicSlice3B<ABIInternal>(SB)
  1056  TEXT runtime·panicSlice3BU<ABIInternal>(SB),NOSPLIT,$0-16
  1057  	MOVD	R4, R3
  1058  	MOVD	R5, R4
  1059  	JMP	runtime·goPanicSlice3BU<ABIInternal>(SB)
  1060  TEXT runtime·panicSlice3C<ABIInternal>(SB),NOSPLIT,$0-16
  1061  	JMP	runtime·goPanicSlice3C<ABIInternal>(SB)
  1062  TEXT runtime·panicSlice3CU<ABIInternal>(SB),NOSPLIT,$0-16
  1063  	JMP	runtime·goPanicSlice3CU<ABIInternal>(SB)
  1064  TEXT runtime·panicSliceConvert<ABIInternal>(SB),NOSPLIT,$0-16
  1065  	MOVD	R5, R3
  1066  	MOVD	R6, R4
  1067  	JMP	runtime·goPanicSliceConvert<ABIInternal>(SB)
  1068  
  1069  // These functions are used when internal linking cgo with external
  1070  // objects compiled with the -Os on gcc. They reduce prologue/epilogue
  1071  // size by deferring preservation of callee-save registers to a shared
  1072  // function. These are defined in PPC64 ELFv2 2.3.3 (but also present
  1073  // in ELFv1)
  1074  //
  1075  // These appear unused, but the linker will redirect calls to functions
  1076  // like _savegpr0_14 or _restgpr1_14 to runtime.elf_savegpr0 or
  1077  // runtime.elf_restgpr1 with an appropriate offset based on the number
  1078  // register operations required when linking external objects which
  1079  // make these calls. For GPR/FPR saves, the minimum register value is
  1080  // 14, for VR it is 20.
  1081  //
  1082  // These are only used when linking such cgo code internally. Note, R12
  1083  // and R0 may be used in different ways than regular ELF compliant
  1084  // functions.
  1085  TEXT runtime·elf_savegpr0(SB),NOSPLIT|NOFRAME,$0
  1086  	// R0 holds the LR of the caller's caller, R1 holds save location
  1087  	MOVD	R14, -144(R1)
  1088  	MOVD	R15, -136(R1)
  1089  	MOVD	R16, -128(R1)
  1090  	MOVD	R17, -120(R1)
  1091  	MOVD	R18, -112(R1)
  1092  	MOVD	R19, -104(R1)
  1093  	MOVD	R20, -96(R1)
  1094  	MOVD	R21, -88(R1)
  1095  	MOVD	R22, -80(R1)
  1096  	MOVD	R23, -72(R1)
  1097  	MOVD	R24, -64(R1)
  1098  	MOVD	R25, -56(R1)
  1099  	MOVD	R26, -48(R1)
  1100  	MOVD	R27, -40(R1)
  1101  	MOVD	R28, -32(R1)
  1102  	MOVD	R29, -24(R1)
  1103  	MOVD	g, -16(R1)
  1104  	MOVD	R31, -8(R1)
  1105  	MOVD	R0, 16(R1)
  1106  	RET
  1107  TEXT runtime·elf_restgpr0(SB),NOSPLIT|NOFRAME,$0
  1108  	// R1 holds save location. This returns to the LR saved on stack (bypassing the caller)
  1109  	MOVD	-144(R1), R14
  1110  	MOVD	-136(R1), R15
  1111  	MOVD	-128(R1), R16
  1112  	MOVD	-120(R1), R17
  1113  	MOVD	-112(R1), R18
  1114  	MOVD	-104(R1), R19
  1115  	MOVD	-96(R1), R20
  1116  	MOVD	-88(R1), R21
  1117  	MOVD	-80(R1), R22
  1118  	MOVD	-72(R1), R23
  1119  	MOVD	-64(R1), R24
  1120  	MOVD	-56(R1), R25
  1121  	MOVD	-48(R1), R26
  1122  	MOVD	-40(R1), R27
  1123  	MOVD	-32(R1), R28
  1124  	MOVD	-24(R1), R29
  1125  	MOVD	-16(R1), g
  1126  	MOVD	-8(R1), R31
  1127  	MOVD	16(R1), R0	// Load and return to saved LR
  1128  	MOVD	R0, LR
  1129  	RET
  1130  TEXT runtime·elf_savegpr1(SB),NOSPLIT|NOFRAME,$0
  1131  	// R12 holds the save location
  1132  	MOVD	R14, -144(R12)
  1133  	MOVD	R15, -136(R12)
  1134  	MOVD	R16, -128(R12)
  1135  	MOVD	R17, -120(R12)
  1136  	MOVD	R18, -112(R12)
  1137  	MOVD	R19, -104(R12)
  1138  	MOVD	R20, -96(R12)
  1139  	MOVD	R21, -88(R12)
  1140  	MOVD	R22, -80(R12)
  1141  	MOVD	R23, -72(R12)
  1142  	MOVD	R24, -64(R12)
  1143  	MOVD	R25, -56(R12)
  1144  	MOVD	R26, -48(R12)
  1145  	MOVD	R27, -40(R12)
  1146  	MOVD	R28, -32(R12)
  1147  	MOVD	R29, -24(R12)
  1148  	MOVD	g, -16(R12)
  1149  	MOVD	R31, -8(R12)
  1150  	RET
  1151  TEXT runtime·elf_restgpr1(SB),NOSPLIT|NOFRAME,$0
  1152  	// R12 holds the save location
  1153  	MOVD	-144(R12), R14
  1154  	MOVD	-136(R12), R15
  1155  	MOVD	-128(R12), R16
  1156  	MOVD	-120(R12), R17
  1157  	MOVD	-112(R12), R18
  1158  	MOVD	-104(R12), R19
  1159  	MOVD	-96(R12), R20
  1160  	MOVD	-88(R12), R21
  1161  	MOVD	-80(R12), R22
  1162  	MOVD	-72(R12), R23
  1163  	MOVD	-64(R12), R24
  1164  	MOVD	-56(R12), R25
  1165  	MOVD	-48(R12), R26
  1166  	MOVD	-40(R12), R27
  1167  	MOVD	-32(R12), R28
  1168  	MOVD	-24(R12), R29
  1169  	MOVD	-16(R12), g
  1170  	MOVD	-8(R12), R31
  1171  	RET
  1172  TEXT runtime·elf_savefpr(SB),NOSPLIT|NOFRAME,$0
  1173  	// R0 holds the LR of the caller's caller, R1 holds save location
  1174  	FMOVD	F14, -144(R1)
  1175  	FMOVD	F15, -136(R1)
  1176  	FMOVD	F16, -128(R1)
  1177  	FMOVD	F17, -120(R1)
  1178  	FMOVD	F18, -112(R1)
  1179  	FMOVD	F19, -104(R1)
  1180  	FMOVD	F20, -96(R1)
  1181  	FMOVD	F21, -88(R1)
  1182  	FMOVD	F22, -80(R1)
  1183  	FMOVD	F23, -72(R1)
  1184  	FMOVD	F24, -64(R1)
  1185  	FMOVD	F25, -56(R1)
  1186  	FMOVD	F26, -48(R1)
  1187  	FMOVD	F27, -40(R1)
  1188  	FMOVD	F28, -32(R1)
  1189  	FMOVD	F29, -24(R1)
  1190  	FMOVD	F30, -16(R1)
  1191  	FMOVD	F31, -8(R1)
  1192  	MOVD	R0, 16(R1)
  1193  	RET
  1194  TEXT runtime·elf_restfpr(SB),NOSPLIT|NOFRAME,$0
  1195  	// R1 holds save location. This returns to the LR saved on stack (bypassing the caller)
  1196  	FMOVD	-144(R1), F14
  1197  	FMOVD	-136(R1), F15
  1198  	FMOVD	-128(R1), F16
  1199  	FMOVD	-120(R1), F17
  1200  	FMOVD	-112(R1), F18
  1201  	FMOVD	-104(R1), F19
  1202  	FMOVD	-96(R1), F20
  1203  	FMOVD	-88(R1), F21
  1204  	FMOVD	-80(R1), F22
  1205  	FMOVD	-72(R1), F23
  1206  	FMOVD	-64(R1), F24
  1207  	FMOVD	-56(R1), F25
  1208  	FMOVD	-48(R1), F26
  1209  	FMOVD	-40(R1), F27
  1210  	FMOVD	-32(R1), F28
  1211  	FMOVD	-24(R1), F29
  1212  	FMOVD	-16(R1), F30
  1213  	FMOVD	-8(R1), F31
  1214  	MOVD	16(R1), R0	// Load and return to saved LR
  1215  	MOVD	R0, LR
  1216  	RET
  1217  TEXT runtime·elf_savevr(SB),NOSPLIT|NOFRAME,$0
  1218  	// R0 holds the save location, R12 is clobbered
  1219  	MOVD	$-192, R12
  1220  	STVX	V20, (R0+R12)
  1221  	MOVD	$-176, R12
  1222  	STVX	V21, (R0+R12)
  1223  	MOVD	$-160, R12
  1224  	STVX	V22, (R0+R12)
  1225  	MOVD	$-144, R12
  1226  	STVX	V23, (R0+R12)
  1227  	MOVD	$-128, R12
  1228  	STVX	V24, (R0+R12)
  1229  	MOVD	$-112, R12
  1230  	STVX	V25, (R0+R12)
  1231  	MOVD	$-96, R12
  1232  	STVX	V26, (R0+R12)
  1233  	MOVD	$-80, R12
  1234  	STVX	V27, (R0+R12)
  1235  	MOVD	$-64, R12
  1236  	STVX	V28, (R0+R12)
  1237  	MOVD	$-48, R12
  1238  	STVX	V29, (R0+R12)
  1239  	MOVD	$-32, R12
  1240  	STVX	V30, (R0+R12)
  1241  	MOVD	$-16, R12
  1242  	STVX	V31, (R0+R12)
  1243  	RET
  1244  TEXT runtime·elf_restvr(SB),NOSPLIT|NOFRAME,$0
  1245  	// R0 holds the save location, R12 is clobbered
  1246  	MOVD	$-192, R12
  1247  	LVX	(R0+R12), V20
  1248  	MOVD	$-176, R12
  1249  	LVX	(R0+R12), V21
  1250  	MOVD	$-160, R12
  1251  	LVX	(R0+R12), V22
  1252  	MOVD	$-144, R12
  1253  	LVX	(R0+R12), V23
  1254  	MOVD	$-128, R12
  1255  	LVX	(R0+R12), V24
  1256  	MOVD	$-112, R12
  1257  	LVX	(R0+R12), V25
  1258  	MOVD	$-96, R12
  1259  	LVX	(R0+R12), V26
  1260  	MOVD	$-80, R12
  1261  	LVX	(R0+R12), V27
  1262  	MOVD	$-64, R12
  1263  	LVX	(R0+R12), V28
  1264  	MOVD	$-48, R12
  1265  	LVX	(R0+R12), V29
  1266  	MOVD	$-32, R12
  1267  	LVX	(R0+R12), V30
  1268  	MOVD	$-16, R12
  1269  	LVX	(R0+R12), V31
  1270  	RET