Text file src/runtime/asm_ppc64x.s

     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  #ifdef GOARCH_ppc64
    46  	// ppc64 use elf ABI v1. we must get the real entry address from
    47  	// first slot of the function descriptor before call.
    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 GOARCH_ppc64
   601  	// ppc64 use elf ABI v1. we must get the real entry address from
   602  	// first slot of the function descriptor before call.
   603  	// Same for AIX.
   604  	MOVD	8(R12), R2
   605  	MOVD	(R12), R12
   606  #endif
   607  	MOVD	R12, CTR
   608  	MOVD	R4, R3		// arg in r3
   609  	BL	(CTR)
   610  	// C code can clobber R0, so set it back to 0. F27-F31 are
   611  	// callee save, so we don't need to recover those.
   612  	XOR	R0, R0
   613  	// Restore g, stack pointer, toc pointer.
   614  	// R3 is errno, so don't touch it
   615  	MOVD	(asmcgocallSaveOffset+8)(R1), g
   616  	MOVD	(g_stack+stack_hi)(g), R5
   617  	MOVD	asmcgocallSaveOffset(R1), R6
   618  	SUB	R6, R5
   619  #ifndef GOOS_aix
   620  	MOVD	24(R5), R2
   621  #endif
   622  	MOVD	R5, R1
   623  	BL	runtime·save_g(SB)
   624  
   625  	MOVW	R3, ret+16(FP)
   626  	RET
   627  
   628  // func cgocallback(fn, frame unsafe.Pointer, ctxt uintptr)
   629  // See cgocall.go for more details.
   630  TEXT ·cgocallback(SB),NOSPLIT,$24-24
   631  	NO_LOCAL_POINTERS
   632  
   633  	// Load m and g from thread-local storage.
   634  	MOVBZ	runtime·iscgo(SB), R3
   635  	CMP	R3, $0
   636  	BEQ	nocgo
   637  	BL	runtime·load_g(SB)
   638  nocgo:
   639  
   640  	// If g is nil, Go did not create the current thread.
   641  	// Call needm to obtain one for temporary use.
   642  	// In this case, we're running on the thread stack, so there's
   643  	// lots of space, but the linker doesn't know. Hide the call from
   644  	// the linker analysis by using an indirect call.
   645  	CMP	g, $0
   646  	BEQ	needm
   647  
   648  	MOVD	g_m(g), R8
   649  	MOVD	R8, savedm-8(SP)
   650  	BR	havem
   651  
   652  needm:
   653  	MOVD	g, savedm-8(SP) // g is zero, so is m.
   654  	MOVD	$runtime·needm(SB), R12
   655  	MOVD	R12, CTR
   656  	BL	(CTR)
   657  
   658  	// Set m->sched.sp = SP, so that if a panic happens
   659  	// during the function we are about to execute, it will
   660  	// have a valid SP to run on the g0 stack.
   661  	// The next few lines (after the havem label)
   662  	// will save this SP onto the stack and then write
   663  	// the same SP back to m->sched.sp. That seems redundant,
   664  	// but if an unrecovered panic happens, unwindm will
   665  	// restore the g->sched.sp from the stack location
   666  	// and then systemstack will try to use it. If we don't set it here,
   667  	// that restored SP will be uninitialized (typically 0) and
   668  	// will not be usable.
   669  	MOVD	g_m(g), R8
   670  	MOVD	m_g0(R8), R3
   671  	MOVD	R1, (g_sched+gobuf_sp)(R3)
   672  
   673  havem:
   674  	// Now there's a valid m, and we're running on its m->g0.
   675  	// Save current m->g0->sched.sp on stack and then set it to SP.
   676  	// Save current sp in m->g0->sched.sp in preparation for
   677  	// switch back to m->curg stack.
   678  	// NOTE: unwindm knows that the saved g->sched.sp is at 8(R1) aka savedsp-16(SP).
   679  	MOVD	m_g0(R8), R3
   680  	MOVD	(g_sched+gobuf_sp)(R3), R4
   681  	MOVD	R4, savedsp-24(SP)      // must match frame size
   682  	MOVD	R1, (g_sched+gobuf_sp)(R3)
   683  
   684  	// Switch to m->curg stack and call runtime.cgocallbackg.
   685  	// Because we are taking over the execution of m->curg
   686  	// but *not* resuming what had been running, we need to
   687  	// save that information (m->curg->sched) so we can restore it.
   688  	// We can restore m->curg->sched.sp easily, because calling
   689  	// runtime.cgocallbackg leaves SP unchanged upon return.
   690  	// To save m->curg->sched.pc, we push it onto the curg stack and
   691  	// open a frame the same size as cgocallback's g0 frame.
   692  	// Once we switch to the curg stack, the pushed PC will appear
   693  	// to be the return PC of cgocallback, so that the traceback
   694  	// will seamlessly trace back into the earlier calls.
   695  	MOVD	m_curg(R8), g
   696  	BL	runtime·save_g(SB)
   697  	MOVD	(g_sched+gobuf_sp)(g), R4 // prepare stack as R4
   698  	MOVD	(g_sched+gobuf_pc)(g), R5
   699  	MOVD	R5, -(24+FIXED_FRAME)(R4)       // "saved LR"; must match frame size
   700  	// Gather our arguments into registers.
   701  	MOVD	fn+0(FP), R5
   702  	MOVD	frame+8(FP), R6
   703  	MOVD	ctxt+16(FP), R7
   704  	MOVD	$-(24+FIXED_FRAME)(R4), R1      // switch stack; must match frame size
   705  	MOVD    R5, FIXED_FRAME+0(R1)
   706  	MOVD    R6, FIXED_FRAME+8(R1)
   707  	MOVD    R7, FIXED_FRAME+16(R1)
   708  
   709  	MOVD	$runtime·cgocallbackg(SB), R12
   710  	MOVD	R12, CTR
   711  	CALL	(CTR) // indirect call to bypass nosplit check. We're on a different stack now.
   712  
   713  	// Restore g->sched (== m->curg->sched) from saved values.
   714  	MOVD	0(R1), R5
   715  	MOVD	R5, (g_sched+gobuf_pc)(g)
   716  	MOVD	$(24+FIXED_FRAME)(R1), R4       // must match frame size
   717  	MOVD	R4, (g_sched+gobuf_sp)(g)
   718  
   719  	// Switch back to m->g0's stack and restore m->g0->sched.sp.
   720  	// (Unlike m->curg, the g0 goroutine never uses sched.pc,
   721  	// so we do not have to restore it.)
   722  	MOVD	g_m(g), R8
   723  	MOVD	m_g0(R8), g
   724  	BL	runtime·save_g(SB)
   725  	MOVD	(g_sched+gobuf_sp)(g), R1
   726  	MOVD	savedsp-24(SP), R4      // must match frame size
   727  	MOVD	R4, (g_sched+gobuf_sp)(g)
   728  
   729  	// If the m on entry was nil, we called needm above to borrow an m
   730  	// for the duration of the call. Since the call is over, return it with dropm.
   731  	MOVD	savedm-8(SP), R6
   732  	CMP	R6, $0
   733  	BNE	droppedm
   734  	MOVD	$runtime·dropm(SB), R12
   735  	MOVD	R12, CTR
   736  	BL	(CTR)
   737  droppedm:
   738  
   739  	// Done!
   740  	RET
   741  
   742  // void setg(G*); set g. for use by needm.
   743  TEXT runtime·setg(SB), NOSPLIT, $0-8
   744  	MOVD	gg+0(FP), g
   745  	// This only happens if iscgo, so jump straight to save_g
   746  	BL	runtime·save_g(SB)
   747  	RET
   748  
   749  #ifdef GOARCH_ppc64
   750  #ifdef GOOS_aix
   751  DATA    setg_gcc<>+0(SB)/8, $_setg_gcc<>(SB)
   752  DATA    setg_gcc<>+8(SB)/8, $TOC(SB)
   753  DATA    setg_gcc<>+16(SB)/8, $0
   754  GLOBL   setg_gcc<>(SB), NOPTR, $24
   755  #else
   756  TEXT setg_gcc<>(SB),NOSPLIT|NOFRAME,$0-0
   757  	DWORD	$_setg_gcc<>(SB)
   758  	DWORD	$0
   759  	DWORD	$0
   760  #endif
   761  #endif
   762  
   763  // void setg_gcc(G*); set g in C TLS.
   764  // Must obey the gcc calling convention.
   765  #ifdef GOARCH_ppc64le
   766  TEXT setg_gcc<>(SB),NOSPLIT|NOFRAME,$0-0
   767  #else
   768  TEXT _setg_gcc<>(SB),NOSPLIT|NOFRAME,$0-0
   769  #endif
   770  	// The standard prologue clobbers R31, which is callee-save in
   771  	// the C ABI, so we have to use $-8-0 and save LR ourselves.
   772  	MOVD	LR, R4
   773  	// Also save g and R31, since they're callee-save in C ABI
   774  	MOVD	R31, R5
   775  	MOVD	g, R6
   776  
   777  	MOVD	R3, g
   778  	BL	runtime·save_g(SB)
   779  
   780  	MOVD	R6, g
   781  	MOVD	R5, R31
   782  	MOVD	R4, LR
   783  	RET
   784  
   785  TEXT runtime·abort(SB),NOSPLIT|NOFRAME,$0-0
   786  	MOVW	(R0), R0
   787  	UNDEF
   788  
   789  #define	TBR	268
   790  
   791  // int64 runtime·cputicks(void)
   792  TEXT runtime·cputicks(SB),NOSPLIT,$0-8
   793  	MOVD	SPR(TBR), R3
   794  	MOVD	R3, ret+0(FP)
   795  	RET
   796  
   797  // spillArgs stores return values from registers to a *internal/abi.RegArgs in R20.
   798  TEXT runtime·spillArgs(SB),NOSPLIT,$0-0
   799  	MOVD    R3, 0(R20)
   800  	MOVD    R4, 8(R20)
   801  	MOVD    R5, 16(R20)
   802  	MOVD    R6, 24(R20)
   803  	MOVD    R7, 32(R20)
   804  	MOVD    R8, 40(R20)
   805  	MOVD    R9, 48(R20)
   806  	MOVD    R10, 56(R20)
   807  	MOVD	R14, 64(R20)
   808  	MOVD	R15, 72(R20)
   809  	MOVD	R16, 80(R20)
   810  	MOVD	R17, 88(R20)
   811  	FMOVD	F1, 96(R20)
   812  	FMOVD	F2, 104(R20)
   813  	FMOVD   F3, 112(R20)
   814  	FMOVD   F4, 120(R20)
   815  	FMOVD   F5, 128(R20)
   816  	FMOVD   F6, 136(R20)
   817  	FMOVD   F7, 144(R20)
   818  	FMOVD   F8, 152(R20)
   819  	FMOVD   F9, 160(R20)
   820  	FMOVD   F10, 168(R20)
   821  	FMOVD   F11, 176(R20)
   822  	FMOVD   F12, 184(R20)
   823  	RET
   824  
   825  // unspillArgs loads args into registers from a *internal/abi.RegArgs in R20.
   826  TEXT runtime·unspillArgs(SB),NOSPLIT,$0-0
   827  	MOVD    0(R20), R3
   828  	MOVD    8(R20), R4
   829  	MOVD    16(R20), R5
   830  	MOVD    24(R20), R6
   831  	MOVD    32(R20), R7
   832  	MOVD    40(R20), R8
   833  	MOVD    48(R20), R9
   834  	MOVD    56(R20), R10
   835  	MOVD    64(R20), R14
   836  	MOVD    72(R20), R15
   837  	MOVD    80(R20), R16
   838  	MOVD    88(R20), R17
   839  	FMOVD   96(R20), F1
   840  	FMOVD   104(R20), F2
   841  	FMOVD   112(R20), F3
   842  	FMOVD   120(R20), F4
   843  	FMOVD   128(R20), F5
   844  	FMOVD   136(R20), F6
   845  	FMOVD   144(R20), F7
   846  	FMOVD   152(R20), F8
   847  	FMOVD   160(R20), F9
   848  	FMOVD	168(R20), F10
   849  	FMOVD	176(R20), F11
   850  	FMOVD	184(R20), F12
   851  	RET
   852  
   853  // AES hashing not implemented for ppc64
   854  TEXT runtime·memhash<ABIInternal>(SB),NOSPLIT|NOFRAME,$0-32
   855  	JMP	runtime·memhashFallback<ABIInternal>(SB)
   856  TEXT runtime·strhash<ABIInternal>(SB),NOSPLIT|NOFRAME,$0-24
   857  	JMP	runtime·strhashFallback<ABIInternal>(SB)
   858  TEXT runtime·memhash32<ABIInternal>(SB),NOSPLIT|NOFRAME,$0-24
   859  	JMP	runtime·memhash32Fallback<ABIInternal>(SB)
   860  TEXT runtime·memhash64<ABIInternal>(SB),NOSPLIT|NOFRAME,$0-24
   861  	JMP	runtime·memhash64Fallback<ABIInternal>(SB)
   862  
   863  TEXT runtime·return0(SB), NOSPLIT, $0
   864  	MOVW	$0, R3
   865  	RET
   866  
   867  // Called from cgo wrappers, this function returns g->m->curg.stack.hi.
   868  // Must obey the gcc calling convention.
   869  #ifdef GOOS_aix
   870  // On AIX, _cgo_topofstack is defined in runtime/cgo, because it must
   871  // be a longcall in order to prevent trampolines from ld.
   872  TEXT __cgo_topofstack(SB),NOSPLIT|NOFRAME,$0
   873  #else
   874  TEXT _cgo_topofstack(SB),NOSPLIT|NOFRAME,$0
   875  #endif
   876  	// g (R30) and R31 are callee-save in the C ABI, so save them
   877  	MOVD	g, R4
   878  	MOVD	R31, R5
   879  	MOVD	LR, R6
   880  
   881  	BL	runtime·load_g(SB)	// clobbers g (R30), R31
   882  	MOVD	g_m(g), R3
   883  	MOVD	m_curg(R3), R3
   884  	MOVD	(g_stack+stack_hi)(R3), R3
   885  
   886  	MOVD	R4, g
   887  	MOVD	R5, R31
   888  	MOVD	R6, LR
   889  	RET
   890  
   891  // The top-most function running on a goroutine
   892  // returns to goexit+PCQuantum.
   893  //
   894  // When dynamically linking Go, it can be returned to from a function
   895  // implemented in a different module and so needs to reload the TOC pointer
   896  // from the stack (although this function declares that it does not set up x-a
   897  // frame, newproc1 does in fact allocate one for goexit and saves the TOC
   898  // pointer in the correct place).
   899  // goexit+_PCQuantum is halfway through the usual global entry point prologue
   900  // that derives r2 from r12 which is a bit silly, but not harmful.
   901  TEXT runtime·goexit(SB),NOSPLIT|NOFRAME|TOPFRAME,$0-0
   902  	MOVD	24(R1), R2
   903  	BL	runtime·goexit1(SB)	// does not return
   904  	// traceback from goexit1 must hit code range of goexit
   905  	MOVD	R0, R0	// NOP
   906  
   907  // prepGoExitFrame saves the current TOC pointer (i.e. the TOC pointer for the
   908  // module containing runtime) to the frame that goexit will execute in when
   909  // the goroutine exits. It's implemented in assembly mainly because that's the
   910  // easiest way to get access to R2.
   911  TEXT runtime·prepGoExitFrame(SB),NOSPLIT,$0-8
   912  	MOVD    sp+0(FP), R3
   913  	MOVD    R2, 24(R3)
   914  	RET
   915  
   916  TEXT runtime·addmoduledata(SB),NOSPLIT|NOFRAME,$0-0
   917  	ADD	$-8, R1
   918  	MOVD	R31, 0(R1)
   919  	MOVD	runtime·lastmoduledatap(SB), R4
   920  	MOVD	R3, moduledata_next(R4)
   921  	MOVD	R3, runtime·lastmoduledatap(SB)
   922  	MOVD	0(R1), R31
   923  	ADD	$8, R1
   924  	RET
   925  
   926  TEXT ·checkASM(SB),NOSPLIT,$0-1
   927  	MOVW	$1, R3
   928  	MOVB	R3, ret+0(FP)
   929  	RET
   930  
   931  // gcWriteBarrier performs a heap pointer write and informs the GC.
   932  //
   933  // gcWriteBarrier does NOT follow the Go ABI. It takes two arguments:
   934  // - R20 is the destination of the write
   935  // - R21 is the value being written at R20.
   936  // It clobbers condition codes.
   937  // It does not clobber R0 through R17 (except special registers),
   938  // but may clobber any other register, *including* R31.
   939  TEXT runtime·gcWriteBarrier<ABIInternal>(SB),NOSPLIT,$112
   940  	// The standard prologue clobbers R31.
   941  	// We use R18 and R19 as scratch registers.
   942  	MOVD	g_m(g), R18
   943  	MOVD	m_p(R18), R18
   944  	MOVD	(p_wbBuf+wbBuf_next)(R18), R19
   945  	// Increment wbBuf.next position.
   946  	ADD	$16, R19
   947  	MOVD	R19, (p_wbBuf+wbBuf_next)(R18)
   948  	MOVD	(p_wbBuf+wbBuf_end)(R18), R18
   949  	CMP	R18, R19
   950  	// Record the write.
   951  	MOVD	R21, -16(R19)	// Record value
   952  	MOVD	(R20), R18	// TODO: This turns bad writes into bad reads.
   953  	MOVD	R18, -8(R19)	// Record *slot
   954  	// Is the buffer full? (flags set in CMP above)
   955  	BEQ	flush
   956  ret:
   957  	// Do the write.
   958  	MOVD	R21, (R20)
   959  	RET
   960  
   961  flush:
   962  	// Save registers R0 through R15 since these were not saved by the caller.
   963  	// We don't save all registers on ppc64 because it takes too much space.
   964  	MOVD	R20, (FIXED_FRAME+0)(R1)	// Also first argument to wbBufFlush
   965  	MOVD	R21, (FIXED_FRAME+8)(R1)	// Also second argument to wbBufFlush
   966  	// R0 is always 0, so no need to spill.
   967  	// R1 is SP.
   968  	// R2 is SB.
   969  	MOVD	R3, (FIXED_FRAME+16)(R1)
   970  	MOVD	R4, (FIXED_FRAME+24)(R1)
   971  	MOVD	R5, (FIXED_FRAME+32)(R1)
   972  	MOVD	R6, (FIXED_FRAME+40)(R1)
   973  	MOVD	R7, (FIXED_FRAME+48)(R1)
   974  	MOVD	R8, (FIXED_FRAME+56)(R1)
   975  	MOVD	R9, (FIXED_FRAME+64)(R1)
   976  	MOVD	R10, (FIXED_FRAME+72)(R1)
   977  	// R11, R12 may be clobbered by external-linker-inserted trampoline
   978  	// R13 is REGTLS
   979  	MOVD	R14, (FIXED_FRAME+80)(R1)
   980  	MOVD	R15, (FIXED_FRAME+88)(R1)
   981  	MOVD	R16, (FIXED_FRAME+96)(R1)
   982  	MOVD	R17, (FIXED_FRAME+104)(R1)
   983  
   984  	// This takes arguments R20 and R21.
   985  	CALL	runtime·wbBufFlush(SB)
   986  
   987  	MOVD	(FIXED_FRAME+0)(R1), R20
   988  	MOVD	(FIXED_FRAME+8)(R1), R21
   989  	MOVD	(FIXED_FRAME+16)(R1), R3
   990  	MOVD	(FIXED_FRAME+24)(R1), R4
   991  	MOVD	(FIXED_FRAME+32)(R1), R5
   992  	MOVD	(FIXED_FRAME+40)(R1), R6
   993  	MOVD	(FIXED_FRAME+48)(R1), R7
   994  	MOVD	(FIXED_FRAME+56)(R1), R8
   995  	MOVD	(FIXED_FRAME+64)(R1), R9
   996  	MOVD	(FIXED_FRAME+72)(R1), R10
   997  	MOVD	(FIXED_FRAME+80)(R1), R14
   998  	MOVD	(FIXED_FRAME+88)(R1), R15
   999  	MOVD	(FIXED_FRAME+96)(R1), R16
  1000  	MOVD	(FIXED_FRAME+104)(R1), R17
  1001  	JMP	ret
  1002  
  1003  // Note: these functions use a special calling convention to save generated code space.
  1004  // Arguments are passed in registers, but the space for those arguments are allocated
  1005  // in the caller's stack frame. These stubs write the args into that stack space and
  1006  // then tail call to the corresponding runtime handler.
  1007  // The tail call makes these stubs disappear in backtraces.
  1008  TEXT runtime·panicIndex<ABIInternal>(SB),NOSPLIT,$0-16
  1009  	JMP	runtime·goPanicIndex<ABIInternal>(SB)
  1010  TEXT runtime·panicIndexU<ABIInternal>(SB),NOSPLIT,$0-16
  1011  	JMP	runtime·goPanicIndexU<ABIInternal>(SB)
  1012  TEXT runtime·panicSliceAlen<ABIInternal>(SB),NOSPLIT,$0-16
  1013  	MOVD	R4, R3
  1014  	MOVD	R5, R4
  1015  	JMP	runtime·goPanicSliceAlen<ABIInternal>(SB)
  1016  TEXT runtime·panicSliceAlenU<ABIInternal>(SB),NOSPLIT,$0-16
  1017  	MOVD	R4, R3
  1018  	MOVD	R5, R4
  1019  	JMP	runtime·goPanicSliceAlenU<ABIInternal>(SB)
  1020  TEXT runtime·panicSliceAcap<ABIInternal>(SB),NOSPLIT,$0-16
  1021  	MOVD	R4, R3
  1022  	MOVD	R5, R4
  1023  	JMP	runtime·goPanicSliceAcap<ABIInternal>(SB)
  1024  TEXT runtime·panicSliceAcapU<ABIInternal>(SB),NOSPLIT,$0-16
  1025  	MOVD	R4, R3
  1026  	MOVD	R5, R4
  1027  	JMP	runtime·goPanicSliceAcapU<ABIInternal>(SB)
  1028  TEXT runtime·panicSliceB<ABIInternal>(SB),NOSPLIT,$0-16
  1029  	JMP	runtime·goPanicSliceB<ABIInternal>(SB)
  1030  TEXT runtime·panicSliceBU<ABIInternal>(SB),NOSPLIT,$0-16
  1031  	JMP	runtime·goPanicSliceBU<ABIInternal>(SB)
  1032  TEXT runtime·panicSlice3Alen<ABIInternal>(SB),NOSPLIT,$0-16
  1033  	MOVD	R5, R3
  1034  	MOVD	R6, R4
  1035  	JMP	runtime·goPanicSlice3Alen<ABIInternal>(SB)
  1036  TEXT runtime·panicSlice3AlenU<ABIInternal>(SB),NOSPLIT,$0-16
  1037  	MOVD	R5, R3
  1038  	MOVD	R6, R4
  1039  	JMP	runtime·goPanicSlice3AlenU<ABIInternal>(SB)
  1040  TEXT runtime·panicSlice3Acap<ABIInternal>(SB),NOSPLIT,$0-16
  1041  	MOVD	R5, R3
  1042  	MOVD	R6, R4
  1043  	JMP	runtime·goPanicSlice3Acap<ABIInternal>(SB)
  1044  TEXT runtime·panicSlice3AcapU<ABIInternal>(SB),NOSPLIT,$0-16
  1045  	MOVD	R5, R3
  1046  	MOVD	R6, R4
  1047  	JMP	runtime·goPanicSlice3AcapU<ABIInternal>(SB)
  1048  TEXT runtime·panicSlice3B<ABIInternal>(SB),NOSPLIT,$0-16
  1049  	MOVD	R4, R3
  1050  	MOVD	R5, R4
  1051  	JMP	runtime·goPanicSlice3B<ABIInternal>(SB)
  1052  TEXT runtime·panicSlice3BU<ABIInternal>(SB),NOSPLIT,$0-16
  1053  	MOVD	R4, R3
  1054  	MOVD	R5, R4
  1055  	JMP	runtime·goPanicSlice3BU<ABIInternal>(SB)
  1056  TEXT runtime·panicSlice3C<ABIInternal>(SB),NOSPLIT,$0-16
  1057  	JMP	runtime·goPanicSlice3C<ABIInternal>(SB)
  1058  TEXT runtime·panicSlice3CU<ABIInternal>(SB),NOSPLIT,$0-16
  1059  	JMP	runtime·goPanicSlice3CU<ABIInternal>(SB)
  1060  TEXT runtime·panicSliceConvert<ABIInternal>(SB),NOSPLIT,$0-16
  1061  	MOVD	R5, R3
  1062  	MOVD	R6, R4
  1063  	JMP	runtime·goPanicSliceConvert<ABIInternal>(SB)
  1064  
  1065  // These functions are used when internal linking cgo with external
  1066  // objects compiled with the -Os on gcc. They reduce prologue/epilogue
  1067  // size by deferring preservation of callee-save registers to a shared
  1068  // function. These are defined in PPC64 ELFv2 2.3.3 (but also present
  1069  // in ELFv1)
  1070  //
  1071  // These appear unused, but the linker will redirect calls to functions
  1072  // like _savegpr0_14 or _restgpr1_14 to runtime.elf_savegpr0 or
  1073  // runtime.elf_restgpr1 with an appropriate offset based on the number
  1074  // register operations required when linking external objects which
  1075  // make these calls. For GPR/FPR saves, the minimum register value is
  1076  // 14, for VR it is 20.
  1077  //
  1078  // These are only used when linking such cgo code internally. Note, R12
  1079  // and R0 may be used in different ways than regular ELF compliant
  1080  // functions.
  1081  TEXT runtime·elf_savegpr0(SB),NOSPLIT|NOFRAME,$0
  1082  	// R0 holds the LR of the caller's caller, R1 holds save location
  1083  	MOVD	R14, -144(R1)
  1084  	MOVD	R15, -136(R1)
  1085  	MOVD	R16, -128(R1)
  1086  	MOVD	R17, -120(R1)
  1087  	MOVD	R18, -112(R1)
  1088  	MOVD	R19, -104(R1)
  1089  	MOVD	R20, -96(R1)
  1090  	MOVD	R21, -88(R1)
  1091  	MOVD	R22, -80(R1)
  1092  	MOVD	R23, -72(R1)
  1093  	MOVD	R24, -64(R1)
  1094  	MOVD	R25, -56(R1)
  1095  	MOVD	R26, -48(R1)
  1096  	MOVD	R27, -40(R1)
  1097  	MOVD	R28, -32(R1)
  1098  	MOVD	R29, -24(R1)
  1099  	MOVD	g, -16(R1)
  1100  	MOVD	R31, -8(R1)
  1101  	MOVD	R0, 16(R1)
  1102  	RET
  1103  TEXT runtime·elf_restgpr0(SB),NOSPLIT|NOFRAME,$0
  1104  	// R1 holds save location. This returns to the LR saved on stack (bypassing the caller)
  1105  	MOVD	-144(R1), R14
  1106  	MOVD	-136(R1), R15
  1107  	MOVD	-128(R1), R16
  1108  	MOVD	-120(R1), R17
  1109  	MOVD	-112(R1), R18
  1110  	MOVD	-104(R1), R19
  1111  	MOVD	-96(R1), R20
  1112  	MOVD	-88(R1), R21
  1113  	MOVD	-80(R1), R22
  1114  	MOVD	-72(R1), R23
  1115  	MOVD	-64(R1), R24
  1116  	MOVD	-56(R1), R25
  1117  	MOVD	-48(R1), R26
  1118  	MOVD	-40(R1), R27
  1119  	MOVD	-32(R1), R28
  1120  	MOVD	-24(R1), R29
  1121  	MOVD	-16(R1), g
  1122  	MOVD	-8(R1), R31
  1123  	MOVD	16(R1), R0	// Load and return to saved LR
  1124  	MOVD	R0, LR
  1125  	RET
  1126  TEXT runtime·elf_savegpr1(SB),NOSPLIT|NOFRAME,$0
  1127  	// R12 holds the save location
  1128  	MOVD	R14, -144(R12)
  1129  	MOVD	R15, -136(R12)
  1130  	MOVD	R16, -128(R12)
  1131  	MOVD	R17, -120(R12)
  1132  	MOVD	R18, -112(R12)
  1133  	MOVD	R19, -104(R12)
  1134  	MOVD	R20, -96(R12)
  1135  	MOVD	R21, -88(R12)
  1136  	MOVD	R22, -80(R12)
  1137  	MOVD	R23, -72(R12)
  1138  	MOVD	R24, -64(R12)
  1139  	MOVD	R25, -56(R12)
  1140  	MOVD	R26, -48(R12)
  1141  	MOVD	R27, -40(R12)
  1142  	MOVD	R28, -32(R12)
  1143  	MOVD	R29, -24(R12)
  1144  	MOVD	g, -16(R12)
  1145  	MOVD	R31, -8(R12)
  1146  	RET
  1147  TEXT runtime·elf_restgpr1(SB),NOSPLIT|NOFRAME,$0
  1148  	// R12 holds the save location
  1149  	MOVD	-144(R12), R14
  1150  	MOVD	-136(R12), R15
  1151  	MOVD	-128(R12), R16
  1152  	MOVD	-120(R12), R17
  1153  	MOVD	-112(R12), R18
  1154  	MOVD	-104(R12), R19
  1155  	MOVD	-96(R12), R20
  1156  	MOVD	-88(R12), R21
  1157  	MOVD	-80(R12), R22
  1158  	MOVD	-72(R12), R23
  1159  	MOVD	-64(R12), R24
  1160  	MOVD	-56(R12), R25
  1161  	MOVD	-48(R12), R26
  1162  	MOVD	-40(R12), R27
  1163  	MOVD	-32(R12), R28
  1164  	MOVD	-24(R12), R29
  1165  	MOVD	-16(R12), g
  1166  	MOVD	-8(R12), R31
  1167  	RET
  1168  TEXT runtime·elf_savefpr(SB),NOSPLIT|NOFRAME,$0
  1169  	// R0 holds the LR of the caller's caller, R1 holds save location
  1170  	FMOVD	F14, -144(R1)
  1171  	FMOVD	F15, -136(R1)
  1172  	FMOVD	F16, -128(R1)
  1173  	FMOVD	F17, -120(R1)
  1174  	FMOVD	F18, -112(R1)
  1175  	FMOVD	F19, -104(R1)
  1176  	FMOVD	F20, -96(R1)
  1177  	FMOVD	F21, -88(R1)
  1178  	FMOVD	F22, -80(R1)
  1179  	FMOVD	F23, -72(R1)
  1180  	FMOVD	F24, -64(R1)
  1181  	FMOVD	F25, -56(R1)
  1182  	FMOVD	F26, -48(R1)
  1183  	FMOVD	F27, -40(R1)
  1184  	FMOVD	F28, -32(R1)
  1185  	FMOVD	F29, -24(R1)
  1186  	FMOVD	F30, -16(R1)
  1187  	FMOVD	F31, -8(R1)
  1188  	MOVD	R0, 16(R1)
  1189  	RET
  1190  TEXT runtime·elf_restfpr(SB),NOSPLIT|NOFRAME,$0
  1191  	// R1 holds save location. This returns to the LR saved on stack (bypassing the caller)
  1192  	FMOVD	-144(R1), F14
  1193  	FMOVD	-136(R1), F15
  1194  	FMOVD	-128(R1), F16
  1195  	FMOVD	-120(R1), F17
  1196  	FMOVD	-112(R1), F18
  1197  	FMOVD	-104(R1), F19
  1198  	FMOVD	-96(R1), F20
  1199  	FMOVD	-88(R1), F21
  1200  	FMOVD	-80(R1), F22
  1201  	FMOVD	-72(R1), F23
  1202  	FMOVD	-64(R1), F24
  1203  	FMOVD	-56(R1), F25
  1204  	FMOVD	-48(R1), F26
  1205  	FMOVD	-40(R1), F27
  1206  	FMOVD	-32(R1), F28
  1207  	FMOVD	-24(R1), F29
  1208  	FMOVD	-16(R1), F30
  1209  	FMOVD	-8(R1), F31
  1210  	MOVD	16(R1), R0	// Load and return to saved LR
  1211  	MOVD	R0, LR
  1212  	RET
  1213  TEXT runtime·elf_savevr(SB),NOSPLIT|NOFRAME,$0
  1214  	// R0 holds the save location, R12 is clobbered
  1215  	MOVD	$-192, R12
  1216  	STVX	V20, (R0+R12)
  1217  	MOVD	$-176, R12
  1218  	STVX	V21, (R0+R12)
  1219  	MOVD	$-160, R12
  1220  	STVX	V22, (R0+R12)
  1221  	MOVD	$-144, R12
  1222  	STVX	V23, (R0+R12)
  1223  	MOVD	$-128, R12
  1224  	STVX	V24, (R0+R12)
  1225  	MOVD	$-112, R12
  1226  	STVX	V25, (R0+R12)
  1227  	MOVD	$-96, R12
  1228  	STVX	V26, (R0+R12)
  1229  	MOVD	$-80, R12
  1230  	STVX	V27, (R0+R12)
  1231  	MOVD	$-64, R12
  1232  	STVX	V28, (R0+R12)
  1233  	MOVD	$-48, R12
  1234  	STVX	V29, (R0+R12)
  1235  	MOVD	$-32, R12
  1236  	STVX	V30, (R0+R12)
  1237  	MOVD	$-16, R12
  1238  	STVX	V31, (R0+R12)
  1239  	RET
  1240  TEXT runtime·elf_restvr(SB),NOSPLIT|NOFRAME,$0
  1241  	// R0 holds the save location, R12 is clobbered
  1242  	MOVD	$-192, R12
  1243  	LVX	(R0+R12), V20
  1244  	MOVD	$-176, R12
  1245  	LVX	(R0+R12), V21
  1246  	MOVD	$-160, R12
  1247  	LVX	(R0+R12), V22
  1248  	MOVD	$-144, R12
  1249  	LVX	(R0+R12), V23
  1250  	MOVD	$-128, R12
  1251  	LVX	(R0+R12), V24
  1252  	MOVD	$-112, R12
  1253  	LVX	(R0+R12), V25
  1254  	MOVD	$-96, R12
  1255  	LVX	(R0+R12), V26
  1256  	MOVD	$-80, R12
  1257  	LVX	(R0+R12), V27
  1258  	MOVD	$-64, R12
  1259  	LVX	(R0+R12), V28
  1260  	MOVD	$-48, R12
  1261  	LVX	(R0+R12), V29
  1262  	MOVD	$-32, R12
  1263  	LVX	(R0+R12), V30
  1264  	MOVD	$-16, R12
  1265  	LVX	(R0+R12), V31
  1266  	RET
  1267  

View as plain text