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  	MOVD	R1, R1
   343  
   344  	MOVD	R0, R11
   345  	BR	runtime·morestack(SB)
   346  
   347  // reflectcall: call a function with the given argument list
   348  // func call(stackArgsType *_type, f *FuncVal, stackArgs *byte, stackArgsSize, stackRetOffset, frameSize uint32, regArgs *abi.RegArgs).
   349  // we don't have variable-sized frames, so we use a small number
   350  // of constant-sized-frame functions to encode a few bits of size in the pc.
   351  // Caution: ugly multiline assembly macros in your future!
   352  
   353  #define DISPATCH(NAME,MAXSIZE)		\
   354  	MOVD	$MAXSIZE, R31;		\
   355  	CMP	R3, R31;		\
   356  	BGT	4(PC);			\
   357  	MOVD	$NAME(SB), R12;		\
   358  	MOVD	R12, CTR;		\
   359  	BR	(CTR)
   360  // Note: can't just "BR NAME(SB)" - bad inlining results.
   361  
   362  TEXT ·reflectcall(SB), NOSPLIT|NOFRAME, $0-48
   363  	MOVWZ	frameSize+32(FP), R3
   364  	DISPATCH(runtime·call16, 16)
   365  	DISPATCH(runtime·call32, 32)
   366  	DISPATCH(runtime·call64, 64)
   367  	DISPATCH(runtime·call128, 128)
   368  	DISPATCH(runtime·call256, 256)
   369  	DISPATCH(runtime·call512, 512)
   370  	DISPATCH(runtime·call1024, 1024)
   371  	DISPATCH(runtime·call2048, 2048)
   372  	DISPATCH(runtime·call4096, 4096)
   373  	DISPATCH(runtime·call8192, 8192)
   374  	DISPATCH(runtime·call16384, 16384)
   375  	DISPATCH(runtime·call32768, 32768)
   376  	DISPATCH(runtime·call65536, 65536)
   377  	DISPATCH(runtime·call131072, 131072)
   378  	DISPATCH(runtime·call262144, 262144)
   379  	DISPATCH(runtime·call524288, 524288)
   380  	DISPATCH(runtime·call1048576, 1048576)
   381  	DISPATCH(runtime·call2097152, 2097152)
   382  	DISPATCH(runtime·call4194304, 4194304)
   383  	DISPATCH(runtime·call8388608, 8388608)
   384  	DISPATCH(runtime·call16777216, 16777216)
   385  	DISPATCH(runtime·call33554432, 33554432)
   386  	DISPATCH(runtime·call67108864, 67108864)
   387  	DISPATCH(runtime·call134217728, 134217728)
   388  	DISPATCH(runtime·call268435456, 268435456)
   389  	DISPATCH(runtime·call536870912, 536870912)
   390  	DISPATCH(runtime·call1073741824, 1073741824)
   391  	MOVD	$runtime·badreflectcall(SB), R12
   392  	MOVD	R12, CTR
   393  	BR	(CTR)
   394  
   395  #define CALLFN(NAME,MAXSIZE)			\
   396  TEXT NAME(SB), WRAPPER, $MAXSIZE-48;		\
   397  	NO_LOCAL_POINTERS;			\
   398  	/* copy arguments to stack */		\
   399  	MOVD	stackArgs+16(FP), R3;			\
   400  	MOVWZ	stackArgsSize+24(FP), R4;			\
   401  	MOVD    R1, R5;				\
   402  	CMP	R4, $8;				\
   403  	BLT	tailsetup;			\
   404  	/* copy 8 at a time if possible */	\
   405  	ADD	$(FIXED_FRAME-8), R5;			\
   406  	SUB	$8, R3;				\
   407  top: \
   408  	MOVDU	8(R3), R7;			\
   409  	MOVDU	R7, 8(R5);			\
   410  	SUB	$8, R4;				\
   411  	CMP	R4, $8;				\
   412  	BGE	top;				\
   413  	/* handle remaining bytes */	\
   414  	CMP	$0, R4;			\
   415  	BEQ	callfn;			\
   416  	ADD	$7, R3;			\
   417  	ADD	$7, R5;			\
   418  	BR	tail;			\
   419  tailsetup: \
   420  	CMP	$0, R4;			\
   421  	BEQ	callfn;			\
   422  	ADD     $(FIXED_FRAME-1), R5;	\
   423  	SUB     $1, R3;			\
   424  tail: \
   425  	MOVBU	1(R3), R6;		\
   426  	MOVBU	R6, 1(R5);		\
   427  	SUB	$1, R4;			\
   428  	CMP	$0, R4;			\
   429  	BGT	tail;			\
   430  callfn: \
   431  	/* call function */			\
   432  	MOVD	f+8(FP), R11;			\
   433  #ifdef GOOS_aix				\
   434  	/* AIX won't trigger a SIGSEGV if R11 = nil */	\
   435  	/* So it manually triggers it */	\
   436  	CMP	R0, R11				\
   437  	BNE	2(PC)				\
   438  	MOVD	R0, 0(R0)			\
   439  #endif						\
   440  	MOVD    regArgs+40(FP), R20;    \
   441  	BL      runtime·unspillArgs(SB);        \
   442  	MOVD	(R11), R12;			\
   443  	MOVD	R12, CTR;			\
   444  	PCDATA  $PCDATA_StackMapIndex, $0;	\
   445  	BL	(CTR);				\
   446  #ifndef GOOS_aix				\
   447  	MOVD	24(R1), R2;			\
   448  #endif						\
   449  	/* copy return values back */		\
   450  	MOVD	regArgs+40(FP), R20;		\
   451  	BL	runtime·spillArgs(SB);			\
   452  	MOVD	stackArgsType+0(FP), R7;		\
   453  	MOVD	stackArgs+16(FP), R3;			\
   454  	MOVWZ	stackArgsSize+24(FP), R4;			\
   455  	MOVWZ	stackRetOffset+28(FP), R6;		\
   456  	ADD	$FIXED_FRAME, R1, R5;		\
   457  	ADD	R6, R5; 			\
   458  	ADD	R6, R3;				\
   459  	SUB	R6, R4;				\
   460  	BL	callRet<>(SB);			\
   461  	RET
   462  
   463  // callRet copies return values back at the end of call*. This is a
   464  // separate function so it can allocate stack space for the arguments
   465  // to reflectcallmove. It does not follow the Go ABI; it expects its
   466  // arguments in registers.
   467  TEXT callRet<>(SB), NOSPLIT, $40-0
   468  	NO_LOCAL_POINTERS
   469  	MOVD	R7, FIXED_FRAME+0(R1)
   470  	MOVD	R3, FIXED_FRAME+8(R1)
   471  	MOVD	R5, FIXED_FRAME+16(R1)
   472  	MOVD	R4, FIXED_FRAME+24(R1)
   473  	MOVD	R20, FIXED_FRAME+32(R1)
   474  	BL	runtime·reflectcallmove(SB)
   475  	RET
   476  
   477  CALLFN(·call16, 16)
   478  CALLFN(·call32, 32)
   479  CALLFN(·call64, 64)
   480  CALLFN(·call128, 128)
   481  CALLFN(·call256, 256)
   482  CALLFN(·call512, 512)
   483  CALLFN(·call1024, 1024)
   484  CALLFN(·call2048, 2048)
   485  CALLFN(·call4096, 4096)
   486  CALLFN(·call8192, 8192)
   487  CALLFN(·call16384, 16384)
   488  CALLFN(·call32768, 32768)
   489  CALLFN(·call65536, 65536)
   490  CALLFN(·call131072, 131072)
   491  CALLFN(·call262144, 262144)
   492  CALLFN(·call524288, 524288)
   493  CALLFN(·call1048576, 1048576)
   494  CALLFN(·call2097152, 2097152)
   495  CALLFN(·call4194304, 4194304)
   496  CALLFN(·call8388608, 8388608)
   497  CALLFN(·call16777216, 16777216)
   498  CALLFN(·call33554432, 33554432)
   499  CALLFN(·call67108864, 67108864)
   500  CALLFN(·call134217728, 134217728)
   501  CALLFN(·call268435456, 268435456)
   502  CALLFN(·call536870912, 536870912)
   503  CALLFN(·call1073741824, 1073741824)
   504  
   505  TEXT runtime·procyield(SB),NOSPLIT|NOFRAME,$0-4
   506  	MOVW	cycles+0(FP), R7
   507  	// POWER does not have a pause/yield instruction equivalent.
   508  	// Instead, we can lower the program priority by setting the
   509  	// Program Priority Register prior to the wait loop and set it
   510  	// back to default afterwards. On Linux, the default priority is
   511  	// medium-low. For details, see page 837 of the ISA 3.0.
   512  	OR	R1, R1, R1	// Set PPR priority to low
   513  again:
   514  	SUB	$1, R7
   515  	CMP	$0, R7
   516  	BNE	again
   517  	OR	R6, R6, R6	// Set PPR priority back to medium-low
   518  	RET
   519  
   520  // Save state of caller into g->sched,
   521  // but using fake PC from systemstack_switch.
   522  // Must only be called from functions with no locals ($0)
   523  // or else unwinding from systemstack_switch is incorrect.
   524  // Smashes R31.
   525  TEXT gosave_systemstack_switch<>(SB),NOSPLIT|NOFRAME,$0
   526  	MOVD	$runtime·systemstack_switch(SB), R31
   527  	ADD     $16, R31 // get past prologue (including r2-setting instructions when they're there)
   528  	MOVD	R31, (g_sched+gobuf_pc)(g)
   529  	MOVD	R1, (g_sched+gobuf_sp)(g)
   530  	MOVD	R0, (g_sched+gobuf_lr)(g)
   531  	MOVD	R0, (g_sched+gobuf_ret)(g)
   532  	// Assert ctxt is zero. See func save.
   533  	MOVD	(g_sched+gobuf_ctxt)(g), R31
   534  	CMP	R0, R31
   535  	BEQ	2(PC)
   536  	BL	runtime·abort(SB)
   537  	RET
   538  
   539  #ifdef GOOS_aix
   540  #define asmcgocallSaveOffset cgoCalleeStackSize + 8
   541  #else
   542  #define asmcgocallSaveOffset cgoCalleeStackSize
   543  #endif
   544  
   545  // func asmcgocall(fn, arg unsafe.Pointer) int32
   546  // Call fn(arg) on the scheduler stack,
   547  // aligned appropriately for the gcc ABI.
   548  // See cgocall.go for more details.
   549  TEXT ·asmcgocall(SB),NOSPLIT,$0-20
   550  	MOVD	fn+0(FP), R3
   551  	MOVD	arg+8(FP), R4
   552  
   553  	MOVD	R1, R7		// save original stack pointer
   554  	MOVD	g, R5
   555  
   556  	// Figure out if we need to switch to m->g0 stack.
   557  	// We get called to create new OS threads too, and those
   558  	// come in on the m->g0 stack already. Or we might already
   559  	// be on the m->gsignal stack.
   560  	MOVD	g_m(g), R8
   561  	MOVD	m_gsignal(R8), R6
   562  	CMP	R6, g
   563  	BEQ	g0
   564  	MOVD	m_g0(R8), R6
   565  	CMP	R6, g
   566  	BEQ	g0
   567  	BL	gosave_systemstack_switch<>(SB)
   568  	MOVD	R6, g
   569  	BL	runtime·save_g(SB)
   570  	MOVD	(g_sched+gobuf_sp)(g), R1
   571  
   572  	// Now on a scheduling stack (a pthread-created stack).
   573  g0:
   574  #ifdef GOOS_aix
   575  	// Create a fake LR to improve backtrace.
   576  	MOVD	$runtime·asmcgocall(SB), R6
   577  	MOVD	R6, 16(R1)
   578  	// AIX also save one argument on the stack.
   579  	SUB $8, R1
   580  #endif
   581  	// Save room for two of our pointers, plus the callee
   582  	// save area that lives on the caller stack.
   583  	SUB	$(asmcgocallSaveOffset+16), R1
   584  	RLDCR	$0, R1, $~15, R1	// 16-byte alignment for gcc ABI
   585  	MOVD	R5, (asmcgocallSaveOffset+8)(R1)// save old g on stack
   586  	MOVD	(g_stack+stack_hi)(R5), R5
   587  	SUB	R7, R5
   588  	MOVD	R5, asmcgocallSaveOffset(R1)    // save depth in old g stack (can't just save SP, as stack might be copied during a callback)
   589  #ifdef GOOS_aix
   590  	MOVD	R7, 0(R1)	// Save frame pointer to allow manual backtrace with gdb
   591  #else
   592  	MOVD	R0, 0(R1)	// clear back chain pointer (TODO can we give it real back trace information?)
   593  #endif
   594  	// This is a "global call", so put the global entry point in r12
   595  	MOVD	R3, R12
   596  
   597  #ifdef GOARCH_ppc64
   598  	// ppc64 use elf ABI v1. we must get the real entry address from
   599  	// first slot of the function descriptor before call.
   600  	// Same for AIX.
   601  	MOVD	8(R12), R2
   602  	MOVD	(R12), R12
   603  #endif
   604  	MOVD	R12, CTR
   605  	MOVD	R4, R3		// arg in r3
   606  	BL	(CTR)
   607  	// C code can clobber R0, so set it back to 0. F27-F31 are
   608  	// callee save, so we don't need to recover those.
   609  	XOR	R0, R0
   610  	// Restore g, stack pointer, toc pointer.
   611  	// R3 is errno, so don't touch it
   612  	MOVD	(asmcgocallSaveOffset+8)(R1), g
   613  	MOVD	(g_stack+stack_hi)(g), R5
   614  	MOVD	asmcgocallSaveOffset(R1), R6
   615  	SUB	R6, R5
   616  #ifndef GOOS_aix
   617  	MOVD	24(R5), R2
   618  #endif
   619  	MOVD	R5, R1
   620  	BL	runtime·save_g(SB)
   621  
   622  	MOVW	R3, ret+16(FP)
   623  	RET
   624  
   625  // func cgocallback(fn, frame unsafe.Pointer, ctxt uintptr)
   626  // See cgocall.go for more details.
   627  TEXT ·cgocallback(SB),NOSPLIT,$24-24
   628  	NO_LOCAL_POINTERS
   629  
   630  	// Load m and g from thread-local storage.
   631  	MOVBZ	runtime·iscgo(SB), R3
   632  	CMP	R3, $0
   633  	BEQ	nocgo
   634  	BL	runtime·load_g(SB)
   635  nocgo:
   636  
   637  	// If g is nil, Go did not create the current thread.
   638  	// Call needm to obtain one for temporary use.
   639  	// In this case, we're running on the thread stack, so there's
   640  	// lots of space, but the linker doesn't know. Hide the call from
   641  	// the linker analysis by using an indirect call.
   642  	CMP	g, $0
   643  	BEQ	needm
   644  
   645  	MOVD	g_m(g), R8
   646  	MOVD	R8, savedm-8(SP)
   647  	BR	havem
   648  
   649  needm:
   650  	MOVD	g, savedm-8(SP) // g is zero, so is m.
   651  	MOVD	$runtime·needm(SB), R12
   652  	MOVD	R12, CTR
   653  	BL	(CTR)
   654  
   655  	// Set m->sched.sp = SP, so that if a panic happens
   656  	// during the function we are about to execute, it will
   657  	// have a valid SP to run on the g0 stack.
   658  	// The next few lines (after the havem label)
   659  	// will save this SP onto the stack and then write
   660  	// the same SP back to m->sched.sp. That seems redundant,
   661  	// but if an unrecovered panic happens, unwindm will
   662  	// restore the g->sched.sp from the stack location
   663  	// and then systemstack will try to use it. If we don't set it here,
   664  	// that restored SP will be uninitialized (typically 0) and
   665  	// will not be usable.
   666  	MOVD	g_m(g), R8
   667  	MOVD	m_g0(R8), R3
   668  	MOVD	R1, (g_sched+gobuf_sp)(R3)
   669  
   670  havem:
   671  	// Now there's a valid m, and we're running on its m->g0.
   672  	// Save current m->g0->sched.sp on stack and then set it to SP.
   673  	// Save current sp in m->g0->sched.sp in preparation for
   674  	// switch back to m->curg stack.
   675  	// NOTE: unwindm knows that the saved g->sched.sp is at 8(R1) aka savedsp-16(SP).
   676  	MOVD	m_g0(R8), R3
   677  	MOVD	(g_sched+gobuf_sp)(R3), R4
   678  	MOVD	R4, savedsp-24(SP)      // must match frame size
   679  	MOVD	R1, (g_sched+gobuf_sp)(R3)
   680  
   681  	// Switch to m->curg stack and call runtime.cgocallbackg.
   682  	// Because we are taking over the execution of m->curg
   683  	// but *not* resuming what had been running, we need to
   684  	// save that information (m->curg->sched) so we can restore it.
   685  	// We can restore m->curg->sched.sp easily, because calling
   686  	// runtime.cgocallbackg leaves SP unchanged upon return.
   687  	// To save m->curg->sched.pc, we push it onto the curg stack and
   688  	// open a frame the same size as cgocallback's g0 frame.
   689  	// Once we switch to the curg stack, the pushed PC will appear
   690  	// to be the return PC of cgocallback, so that the traceback
   691  	// will seamlessly trace back into the earlier calls.
   692  	MOVD	m_curg(R8), g
   693  	BL	runtime·save_g(SB)
   694  	MOVD	(g_sched+gobuf_sp)(g), R4 // prepare stack as R4
   695  	MOVD	(g_sched+gobuf_pc)(g), R5
   696  	MOVD	R5, -(24+FIXED_FRAME)(R4)       // "saved LR"; must match frame size
   697  	// Gather our arguments into registers.
   698  	MOVD	fn+0(FP), R5
   699  	MOVD	frame+8(FP), R6
   700  	MOVD	ctxt+16(FP), R7
   701  	MOVD	$-(24+FIXED_FRAME)(R4), R1      // switch stack; must match frame size
   702  	MOVD    R5, FIXED_FRAME+0(R1)
   703  	MOVD    R6, FIXED_FRAME+8(R1)
   704  	MOVD    R7, FIXED_FRAME+16(R1)
   705  
   706  	MOVD	$runtime·cgocallbackg(SB), R12
   707  	MOVD	R12, CTR
   708  	CALL	(CTR) // indirect call to bypass nosplit check. We're on a different stack now.
   709  
   710  	// Restore g->sched (== m->curg->sched) from saved values.
   711  	MOVD	0(R1), R5
   712  	MOVD	R5, (g_sched+gobuf_pc)(g)
   713  	MOVD	$(24+FIXED_FRAME)(R1), R4       // must match frame size
   714  	MOVD	R4, (g_sched+gobuf_sp)(g)
   715  
   716  	// Switch back to m->g0's stack and restore m->g0->sched.sp.
   717  	// (Unlike m->curg, the g0 goroutine never uses sched.pc,
   718  	// so we do not have to restore it.)
   719  	MOVD	g_m(g), R8
   720  	MOVD	m_g0(R8), g
   721  	BL	runtime·save_g(SB)
   722  	MOVD	(g_sched+gobuf_sp)(g), R1
   723  	MOVD	savedsp-24(SP), R4      // must match frame size
   724  	MOVD	R4, (g_sched+gobuf_sp)(g)
   725  
   726  	// If the m on entry was nil, we called needm above to borrow an m
   727  	// for the duration of the call. Since the call is over, return it with dropm.
   728  	MOVD	savedm-8(SP), R6
   729  	CMP	R6, $0
   730  	BNE	droppedm
   731  	MOVD	$runtime·dropm(SB), R12
   732  	MOVD	R12, CTR
   733  	BL	(CTR)
   734  droppedm:
   735  
   736  	// Done!
   737  	RET
   738  
   739  // void setg(G*); set g. for use by needm.
   740  TEXT runtime·setg(SB), NOSPLIT, $0-8
   741  	MOVD	gg+0(FP), g
   742  	// This only happens if iscgo, so jump straight to save_g
   743  	BL	runtime·save_g(SB)
   744  	RET
   745  
   746  #ifdef GOARCH_ppc64
   747  #ifdef GOOS_aix
   748  DATA    setg_gcc<>+0(SB)/8, $_setg_gcc<>(SB)
   749  DATA    setg_gcc<>+8(SB)/8, $TOC(SB)
   750  DATA    setg_gcc<>+16(SB)/8, $0
   751  GLOBL   setg_gcc<>(SB), NOPTR, $24
   752  #else
   753  TEXT setg_gcc<>(SB),NOSPLIT|NOFRAME,$0-0
   754  	DWORD	$_setg_gcc<>(SB)
   755  	DWORD	$0
   756  	DWORD	$0
   757  #endif
   758  #endif
   759  
   760  // void setg_gcc(G*); set g in C TLS.
   761  // Must obey the gcc calling convention.
   762  #ifdef GOARCH_ppc64le
   763  TEXT setg_gcc<>(SB),NOSPLIT|NOFRAME,$0-0
   764  #else
   765  TEXT _setg_gcc<>(SB),NOSPLIT|NOFRAME,$0-0
   766  #endif
   767  	// The standard prologue clobbers R31, which is callee-save in
   768  	// the C ABI, so we have to use $-8-0 and save LR ourselves.
   769  	MOVD	LR, R4
   770  	// Also save g and R31, since they're callee-save in C ABI
   771  	MOVD	R31, R5
   772  	MOVD	g, R6
   773  
   774  	MOVD	R3, g
   775  	BL	runtime·save_g(SB)
   776  
   777  	MOVD	R6, g
   778  	MOVD	R5, R31
   779  	MOVD	R4, LR
   780  	RET
   781  
   782  TEXT runtime·abort(SB),NOSPLIT|NOFRAME,$0-0
   783  	MOVW	(R0), R0
   784  	UNDEF
   785  
   786  #define	TBR	268
   787  
   788  // int64 runtime·cputicks(void)
   789  TEXT runtime·cputicks(SB),NOSPLIT,$0-8
   790  	MOVD	SPR(TBR), R3
   791  	MOVD	R3, ret+0(FP)
   792  	RET
   793  
   794  // spillArgs stores return values from registers to a *internal/abi.RegArgs in R20.
   795  TEXT runtime·spillArgs(SB),NOSPLIT,$0-0
   796  	MOVD    R3, 0(R20)
   797  	MOVD    R4, 8(R20)
   798  	MOVD    R5, 16(R20)
   799  	MOVD    R6, 24(R20)
   800  	MOVD    R7, 32(R20)
   801  	MOVD    R8, 40(R20)
   802  	MOVD    R9, 48(R20)
   803  	MOVD    R10, 56(R20)
   804  	MOVD	R14, 64(R20)
   805  	MOVD	R15, 72(R20)
   806  	MOVD	R16, 80(R20)
   807  	MOVD	R17, 88(R20)
   808  	FMOVD	F1, 96(R20)
   809  	FMOVD	F2, 104(R20)
   810  	FMOVD   F3, 112(R20)
   811  	FMOVD   F4, 120(R20)
   812  	FMOVD   F5, 128(R20)
   813  	FMOVD   F6, 136(R20)
   814  	FMOVD   F7, 144(R20)
   815  	FMOVD   F8, 152(R20)
   816  	FMOVD   F9, 160(R20)
   817  	FMOVD   F10, 168(R20)
   818  	FMOVD   F11, 176(R20)
   819  	FMOVD   F12, 184(R20)
   820  	RET
   821  
   822  // unspillArgs loads args into registers from a *internal/abi.RegArgs in R20.
   823  TEXT runtime·unspillArgs(SB),NOSPLIT,$0-0
   824  	MOVD    0(R20), R3
   825  	MOVD    8(R20), R4
   826  	MOVD    16(R20), R5
   827  	MOVD    24(R20), R6
   828  	MOVD    32(R20), R7
   829  	MOVD    40(R20), R8
   830  	MOVD    48(R20), R9
   831  	MOVD    56(R20), R10
   832  	MOVD    64(R20), R14
   833  	MOVD    72(R20), R15
   834  	MOVD    80(R20), R16
   835  	MOVD    88(R20), R17
   836  	FMOVD   96(R20), F1
   837  	FMOVD   104(R20), F2
   838  	FMOVD   112(R20), F3
   839  	FMOVD   120(R20), F4
   840  	FMOVD   128(R20), F5
   841  	FMOVD   136(R20), F6
   842  	FMOVD   144(R20), F7
   843  	FMOVD   152(R20), F8
   844  	FMOVD   160(R20), F9
   845  	FMOVD	168(R20), F10
   846  	FMOVD	176(R20), F11
   847  	FMOVD	184(R20), F12
   848  	RET
   849  
   850  // AES hashing not implemented for ppc64
   851  TEXT runtime·memhash<ABIInternal>(SB),NOSPLIT|NOFRAME,$0-32
   852  	JMP	runtime·memhashFallback<ABIInternal>(SB)
   853  TEXT runtime·strhash<ABIInternal>(SB),NOSPLIT|NOFRAME,$0-24
   854  	JMP	runtime·strhashFallback<ABIInternal>(SB)
   855  TEXT runtime·memhash32<ABIInternal>(SB),NOSPLIT|NOFRAME,$0-24
   856  	JMP	runtime·memhash32Fallback<ABIInternal>(SB)
   857  TEXT runtime·memhash64<ABIInternal>(SB),NOSPLIT|NOFRAME,$0-24
   858  	JMP	runtime·memhash64Fallback<ABIInternal>(SB)
   859  
   860  TEXT runtime·return0(SB), NOSPLIT, $0
   861  	MOVW	$0, R3
   862  	RET
   863  
   864  // Called from cgo wrappers, this function returns g->m->curg.stack.hi.
   865  // Must obey the gcc calling convention.
   866  #ifdef GOOS_aix
   867  // On AIX, _cgo_topofstack is defined in runtime/cgo, because it must
   868  // be a longcall in order to prevent trampolines from ld.
   869  TEXT __cgo_topofstack(SB),NOSPLIT|NOFRAME,$0
   870  #else
   871  TEXT _cgo_topofstack(SB),NOSPLIT|NOFRAME,$0
   872  #endif
   873  	// g (R30) and R31 are callee-save in the C ABI, so save them
   874  	MOVD	g, R4
   875  	MOVD	R31, R5
   876  	MOVD	LR, R6
   877  
   878  	BL	runtime·load_g(SB)	// clobbers g (R30), R31
   879  	MOVD	g_m(g), R3
   880  	MOVD	m_curg(R3), R3
   881  	MOVD	(g_stack+stack_hi)(R3), R3
   882  
   883  	MOVD	R4, g
   884  	MOVD	R5, R31
   885  	MOVD	R6, LR
   886  	RET
   887  
   888  // The top-most function running on a goroutine
   889  // returns to goexit+PCQuantum.
   890  //
   891  // When dynamically linking Go, it can be returned to from a function
   892  // implemented in a different module and so needs to reload the TOC pointer
   893  // from the stack (although this function declares that it does not set up x-a
   894  // frame, newproc1 does in fact allocate one for goexit and saves the TOC
   895  // pointer in the correct place).
   896  // goexit+_PCQuantum is halfway through the usual global entry point prologue
   897  // that derives r2 from r12 which is a bit silly, but not harmful.
   898  TEXT runtime·goexit(SB),NOSPLIT|NOFRAME|TOPFRAME,$0-0
   899  	MOVD	24(R1), R2
   900  	BL	runtime·goexit1(SB)	// does not return
   901  	// traceback from goexit1 must hit code range of goexit
   902  	MOVD	R0, R0	// NOP
   903  
   904  // prepGoExitFrame saves the current TOC pointer (i.e. the TOC pointer for the
   905  // module containing runtime) to the frame that goexit will execute in when
   906  // the goroutine exits. It's implemented in assembly mainly because that's the
   907  // easiest way to get access to R2.
   908  TEXT runtime·prepGoExitFrame(SB),NOSPLIT,$0-8
   909  	MOVD    sp+0(FP), R3
   910  	MOVD    R2, 24(R3)
   911  	RET
   912  
   913  TEXT runtime·addmoduledata(SB),NOSPLIT|NOFRAME,$0-0
   914  	ADD	$-8, R1
   915  	MOVD	R31, 0(R1)
   916  	MOVD	runtime·lastmoduledatap(SB), R4
   917  	MOVD	R3, moduledata_next(R4)
   918  	MOVD	R3, runtime·lastmoduledatap(SB)
   919  	MOVD	0(R1), R31
   920  	ADD	$8, R1
   921  	RET
   922  
   923  TEXT ·checkASM(SB),NOSPLIT,$0-1
   924  	MOVW	$1, R3
   925  	MOVB	R3, ret+0(FP)
   926  	RET
   927  
   928  // gcWriteBarrier performs a heap pointer write and informs the GC.
   929  //
   930  // gcWriteBarrier does NOT follow the Go ABI. It takes two arguments:
   931  // - R20 is the destination of the write
   932  // - R21 is the value being written at R20.
   933  // It clobbers condition codes.
   934  // It does not clobber R0 through R17 (except special registers),
   935  // but may clobber any other register, *including* R31.
   936  TEXT runtime·gcWriteBarrier<ABIInternal>(SB),NOSPLIT,$112
   937  	// The standard prologue clobbers R31.
   938  	// We use R18 and R19 as scratch registers.
   939  	MOVD	g_m(g), R18
   940  	MOVD	m_p(R18), R18
   941  	MOVD	(p_wbBuf+wbBuf_next)(R18), R19
   942  	// Increment wbBuf.next position.
   943  	ADD	$16, R19
   944  	MOVD	R19, (p_wbBuf+wbBuf_next)(R18)
   945  	MOVD	(p_wbBuf+wbBuf_end)(R18), R18
   946  	CMP	R18, R19
   947  	// Record the write.
   948  	MOVD	R21, -16(R19)	// Record value
   949  	MOVD	(R20), R18	// TODO: This turns bad writes into bad reads.
   950  	MOVD	R18, -8(R19)	// Record *slot
   951  	// Is the buffer full? (flags set in CMP above)
   952  	BEQ	flush
   953  ret:
   954  	// Do the write.
   955  	MOVD	R21, (R20)
   956  	RET
   957  
   958  flush:
   959  	// Save registers R0 through R15 since these were not saved by the caller.
   960  	// We don't save all registers on ppc64 because it takes too much space.
   961  	MOVD	R20, (FIXED_FRAME+0)(R1)	// Also first argument to wbBufFlush
   962  	MOVD	R21, (FIXED_FRAME+8)(R1)	// Also second argument to wbBufFlush
   963  	// R0 is always 0, so no need to spill.
   964  	// R1 is SP.
   965  	// R2 is SB.
   966  	MOVD	R3, (FIXED_FRAME+16)(R1)
   967  	MOVD	R4, (FIXED_FRAME+24)(R1)
   968  	MOVD	R5, (FIXED_FRAME+32)(R1)
   969  	MOVD	R6, (FIXED_FRAME+40)(R1)
   970  	MOVD	R7, (FIXED_FRAME+48)(R1)
   971  	MOVD	R8, (FIXED_FRAME+56)(R1)
   972  	MOVD	R9, (FIXED_FRAME+64)(R1)
   973  	MOVD	R10, (FIXED_FRAME+72)(R1)
   974  	// R11, R12 may be clobbered by external-linker-inserted trampoline
   975  	// R13 is REGTLS
   976  	MOVD	R14, (FIXED_FRAME+80)(R1)
   977  	MOVD	R15, (FIXED_FRAME+88)(R1)
   978  	MOVD	R16, (FIXED_FRAME+96)(R1)
   979  	MOVD	R17, (FIXED_FRAME+104)(R1)
   980  
   981  	// This takes arguments R20 and R21.
   982  	CALL	runtime·wbBufFlush(SB)
   983  
   984  	MOVD	(FIXED_FRAME+0)(R1), R20
   985  	MOVD	(FIXED_FRAME+8)(R1), R21
   986  	MOVD	(FIXED_FRAME+16)(R1), R3
   987  	MOVD	(FIXED_FRAME+24)(R1), R4
   988  	MOVD	(FIXED_FRAME+32)(R1), R5
   989  	MOVD	(FIXED_FRAME+40)(R1), R6
   990  	MOVD	(FIXED_FRAME+48)(R1), R7
   991  	MOVD	(FIXED_FRAME+56)(R1), R8
   992  	MOVD	(FIXED_FRAME+64)(R1), R9
   993  	MOVD	(FIXED_FRAME+72)(R1), R10
   994  	MOVD	(FIXED_FRAME+80)(R1), R14
   995  	MOVD	(FIXED_FRAME+88)(R1), R15
   996  	MOVD	(FIXED_FRAME+96)(R1), R16
   997  	MOVD	(FIXED_FRAME+104)(R1), R17
   998  	JMP	ret
   999  
  1000  // Note: these functions use a special calling convention to save generated code space.
  1001  // Arguments are passed in registers, but the space for those arguments are allocated
  1002  // in the caller's stack frame. These stubs write the args into that stack space and
  1003  // then tail call to the corresponding runtime handler.
  1004  // The tail call makes these stubs disappear in backtraces.
  1005  TEXT runtime·panicIndex<ABIInternal>(SB),NOSPLIT,$0-16
  1006  	JMP	runtime·goPanicIndex<ABIInternal>(SB)
  1007  TEXT runtime·panicIndexU<ABIInternal>(SB),NOSPLIT,$0-16
  1008  	JMP	runtime·goPanicIndexU<ABIInternal>(SB)
  1009  TEXT runtime·panicSliceAlen<ABIInternal>(SB),NOSPLIT,$0-16
  1010  	MOVD	R4, R3
  1011  	MOVD	R5, R4
  1012  	JMP	runtime·goPanicSliceAlen<ABIInternal>(SB)
  1013  TEXT runtime·panicSliceAlenU<ABIInternal>(SB),NOSPLIT,$0-16
  1014  	MOVD	R4, R3
  1015  	MOVD	R5, R4
  1016  	JMP	runtime·goPanicSliceAlenU<ABIInternal>(SB)
  1017  TEXT runtime·panicSliceAcap<ABIInternal>(SB),NOSPLIT,$0-16
  1018  	MOVD	R4, R3
  1019  	MOVD	R5, R4
  1020  	JMP	runtime·goPanicSliceAcap<ABIInternal>(SB)
  1021  TEXT runtime·panicSliceAcapU<ABIInternal>(SB),NOSPLIT,$0-16
  1022  	MOVD	R4, R3
  1023  	MOVD	R5, R4
  1024  	JMP	runtime·goPanicSliceAcapU<ABIInternal>(SB)
  1025  TEXT runtime·panicSliceB<ABIInternal>(SB),NOSPLIT,$0-16
  1026  	JMP	runtime·goPanicSliceB<ABIInternal>(SB)
  1027  TEXT runtime·panicSliceBU<ABIInternal>(SB),NOSPLIT,$0-16
  1028  	JMP	runtime·goPanicSliceBU<ABIInternal>(SB)
  1029  TEXT runtime·panicSlice3Alen<ABIInternal>(SB),NOSPLIT,$0-16
  1030  	MOVD	R5, R3
  1031  	MOVD	R6, R4
  1032  	JMP	runtime·goPanicSlice3Alen<ABIInternal>(SB)
  1033  TEXT runtime·panicSlice3AlenU<ABIInternal>(SB),NOSPLIT,$0-16
  1034  	MOVD	R5, R3
  1035  	MOVD	R6, R4
  1036  	JMP	runtime·goPanicSlice3AlenU<ABIInternal>(SB)
  1037  TEXT runtime·panicSlice3Acap<ABIInternal>(SB),NOSPLIT,$0-16
  1038  	MOVD	R5, R3
  1039  	MOVD	R6, R4
  1040  	JMP	runtime·goPanicSlice3Acap<ABIInternal>(SB)
  1041  TEXT runtime·panicSlice3AcapU<ABIInternal>(SB),NOSPLIT,$0-16
  1042  	MOVD	R5, R3
  1043  	MOVD	R6, R4
  1044  	JMP	runtime·goPanicSlice3AcapU<ABIInternal>(SB)
  1045  TEXT runtime·panicSlice3B<ABIInternal>(SB),NOSPLIT,$0-16
  1046  	MOVD	R4, R3
  1047  	MOVD	R5, R4
  1048  	JMP	runtime·goPanicSlice3B<ABIInternal>(SB)
  1049  TEXT runtime·panicSlice3BU<ABIInternal>(SB),NOSPLIT,$0-16
  1050  	MOVD	R4, R3
  1051  	MOVD	R5, R4
  1052  	JMP	runtime·goPanicSlice3BU<ABIInternal>(SB)
  1053  TEXT runtime·panicSlice3C<ABIInternal>(SB),NOSPLIT,$0-16
  1054  	JMP	runtime·goPanicSlice3C<ABIInternal>(SB)
  1055  TEXT runtime·panicSlice3CU<ABIInternal>(SB),NOSPLIT,$0-16
  1056  	JMP	runtime·goPanicSlice3CU<ABIInternal>(SB)
  1057  TEXT runtime·panicSliceConvert<ABIInternal>(SB),NOSPLIT,$0-16
  1058  	MOVD	R5, R3
  1059  	MOVD	R6, R4
  1060  	JMP	runtime·goPanicSliceConvert<ABIInternal>(SB)
  1061  
  1062  // These functions are used when internal linking cgo with external
  1063  // objects compiled with the -Os on gcc. They reduce prologue/epilogue
  1064  // size by deferring preservation of callee-save registers to a shared
  1065  // function. These are defined in PPC64 ELFv2 2.3.3 (but also present
  1066  // in ELFv1)
  1067  //
  1068  // These appear unused, but the linker will redirect calls to functions
  1069  // like _savegpr0_14 or _restgpr1_14 to runtime.elf_savegpr0 or
  1070  // runtime.elf_restgpr1 with an appropriate offset based on the number
  1071  // register operations required when linking external objects which
  1072  // make these calls. For GPR/FPR saves, the minimum register value is
  1073  // 14, for VR it is 20.
  1074  //
  1075  // These are only used when linking such cgo code internally. Note, R12
  1076  // and R0 may be used in different ways than regular ELF compliant
  1077  // functions.
  1078  TEXT runtime·elf_savegpr0(SB),NOSPLIT|NOFRAME,$0
  1079  	// R0 holds the LR of the caller's caller, R1 holds save location
  1080  	MOVD	R14, -144(R1)
  1081  	MOVD	R15, -136(R1)
  1082  	MOVD	R16, -128(R1)
  1083  	MOVD	R17, -120(R1)
  1084  	MOVD	R18, -112(R1)
  1085  	MOVD	R19, -104(R1)
  1086  	MOVD	R20, -96(R1)
  1087  	MOVD	R21, -88(R1)
  1088  	MOVD	R22, -80(R1)
  1089  	MOVD	R23, -72(R1)
  1090  	MOVD	R24, -64(R1)
  1091  	MOVD	R25, -56(R1)
  1092  	MOVD	R26, -48(R1)
  1093  	MOVD	R27, -40(R1)
  1094  	MOVD	R28, -32(R1)
  1095  	MOVD	R29, -24(R1)
  1096  	MOVD	g, -16(R1)
  1097  	MOVD	R31, -8(R1)
  1098  	MOVD	R0, 16(R1)
  1099  	RET
  1100  TEXT runtime·elf_restgpr0(SB),NOSPLIT|NOFRAME,$0
  1101  	// R1 holds save location. This returns to the LR saved on stack (bypassing the caller)
  1102  	MOVD	-144(R1), R14
  1103  	MOVD	-136(R1), R15
  1104  	MOVD	-128(R1), R16
  1105  	MOVD	-120(R1), R17
  1106  	MOVD	-112(R1), R18
  1107  	MOVD	-104(R1), R19
  1108  	MOVD	-96(R1), R20
  1109  	MOVD	-88(R1), R21
  1110  	MOVD	-80(R1), R22
  1111  	MOVD	-72(R1), R23
  1112  	MOVD	-64(R1), R24
  1113  	MOVD	-56(R1), R25
  1114  	MOVD	-48(R1), R26
  1115  	MOVD	-40(R1), R27
  1116  	MOVD	-32(R1), R28
  1117  	MOVD	-24(R1), R29
  1118  	MOVD	-16(R1), g
  1119  	MOVD	-8(R1), R31
  1120  	MOVD	16(R1), R0	// Load and return to saved LR
  1121  	MOVD	R0, LR
  1122  	RET
  1123  TEXT runtime·elf_savegpr1(SB),NOSPLIT|NOFRAME,$0
  1124  	// R12 holds the save location
  1125  	MOVD	R14, -144(R12)
  1126  	MOVD	R15, -136(R12)
  1127  	MOVD	R16, -128(R12)
  1128  	MOVD	R17, -120(R12)
  1129  	MOVD	R18, -112(R12)
  1130  	MOVD	R19, -104(R12)
  1131  	MOVD	R20, -96(R12)
  1132  	MOVD	R21, -88(R12)
  1133  	MOVD	R22, -80(R12)
  1134  	MOVD	R23, -72(R12)
  1135  	MOVD	R24, -64(R12)
  1136  	MOVD	R25, -56(R12)
  1137  	MOVD	R26, -48(R12)
  1138  	MOVD	R27, -40(R12)
  1139  	MOVD	R28, -32(R12)
  1140  	MOVD	R29, -24(R12)
  1141  	MOVD	g, -16(R12)
  1142  	MOVD	R31, -8(R12)
  1143  	RET
  1144  TEXT runtime·elf_restgpr1(SB),NOSPLIT|NOFRAME,$0
  1145  	// R12 holds the save location
  1146  	MOVD	-144(R12), R14
  1147  	MOVD	-136(R12), R15
  1148  	MOVD	-128(R12), R16
  1149  	MOVD	-120(R12), R17
  1150  	MOVD	-112(R12), R18
  1151  	MOVD	-104(R12), R19
  1152  	MOVD	-96(R12), R20
  1153  	MOVD	-88(R12), R21
  1154  	MOVD	-80(R12), R22
  1155  	MOVD	-72(R12), R23
  1156  	MOVD	-64(R12), R24
  1157  	MOVD	-56(R12), R25
  1158  	MOVD	-48(R12), R26
  1159  	MOVD	-40(R12), R27
  1160  	MOVD	-32(R12), R28
  1161  	MOVD	-24(R12), R29
  1162  	MOVD	-16(R12), g
  1163  	MOVD	-8(R12), R31
  1164  	RET
  1165  TEXT runtime·elf_savefpr(SB),NOSPLIT|NOFRAME,$0
  1166  	// R0 holds the LR of the caller's caller, R1 holds save location
  1167  	FMOVD	F14, -144(R1)
  1168  	FMOVD	F15, -136(R1)
  1169  	FMOVD	F16, -128(R1)
  1170  	FMOVD	F17, -120(R1)
  1171  	FMOVD	F18, -112(R1)
  1172  	FMOVD	F19, -104(R1)
  1173  	FMOVD	F20, -96(R1)
  1174  	FMOVD	F21, -88(R1)
  1175  	FMOVD	F22, -80(R1)
  1176  	FMOVD	F23, -72(R1)
  1177  	FMOVD	F24, -64(R1)
  1178  	FMOVD	F25, -56(R1)
  1179  	FMOVD	F26, -48(R1)
  1180  	FMOVD	F27, -40(R1)
  1181  	FMOVD	F28, -32(R1)
  1182  	FMOVD	F29, -24(R1)
  1183  	FMOVD	F30, -16(R1)
  1184  	FMOVD	F31, -8(R1)
  1185  	MOVD	R0, 16(R1)
  1186  	RET
  1187  TEXT runtime·elf_restfpr(SB),NOSPLIT|NOFRAME,$0
  1188  	// R1 holds save location. This returns to the LR saved on stack (bypassing the caller)
  1189  	FMOVD	-144(R1), F14
  1190  	FMOVD	-136(R1), F15
  1191  	FMOVD	-128(R1), F16
  1192  	FMOVD	-120(R1), F17
  1193  	FMOVD	-112(R1), F18
  1194  	FMOVD	-104(R1), F19
  1195  	FMOVD	-96(R1), F20
  1196  	FMOVD	-88(R1), F21
  1197  	FMOVD	-80(R1), F22
  1198  	FMOVD	-72(R1), F23
  1199  	FMOVD	-64(R1), F24
  1200  	FMOVD	-56(R1), F25
  1201  	FMOVD	-48(R1), F26
  1202  	FMOVD	-40(R1), F27
  1203  	FMOVD	-32(R1), F28
  1204  	FMOVD	-24(R1), F29
  1205  	FMOVD	-16(R1), F30
  1206  	FMOVD	-8(R1), F31
  1207  	MOVD	16(R1), R0	// Load and return to saved LR
  1208  	MOVD	R0, LR
  1209  	RET
  1210  TEXT runtime·elf_savevr(SB),NOSPLIT|NOFRAME,$0
  1211  	// R0 holds the save location, R12 is clobbered
  1212  	MOVD	$-192, R12
  1213  	STVX	V20, (R0+R12)
  1214  	MOVD	$-176, R12
  1215  	STVX	V21, (R0+R12)
  1216  	MOVD	$-160, R12
  1217  	STVX	V22, (R0+R12)
  1218  	MOVD	$-144, R12
  1219  	STVX	V23, (R0+R12)
  1220  	MOVD	$-128, R12
  1221  	STVX	V24, (R0+R12)
  1222  	MOVD	$-112, R12
  1223  	STVX	V25, (R0+R12)
  1224  	MOVD	$-96, R12
  1225  	STVX	V26, (R0+R12)
  1226  	MOVD	$-80, R12
  1227  	STVX	V27, (R0+R12)
  1228  	MOVD	$-64, R12
  1229  	STVX	V28, (R0+R12)
  1230  	MOVD	$-48, R12
  1231  	STVX	V29, (R0+R12)
  1232  	MOVD	$-32, R12
  1233  	STVX	V30, (R0+R12)
  1234  	MOVD	$-16, R12
  1235  	STVX	V31, (R0+R12)
  1236  	RET
  1237  TEXT runtime·elf_restvr(SB),NOSPLIT|NOFRAME,$0
  1238  	// R0 holds the save location, R12 is clobbered
  1239  	MOVD	$-192, R12
  1240  	LVX	(R0+R12), V20
  1241  	MOVD	$-176, R12
  1242  	LVX	(R0+R12), V21
  1243  	MOVD	$-160, R12
  1244  	LVX	(R0+R12), V22
  1245  	MOVD	$-144, R12
  1246  	LVX	(R0+R12), V23
  1247  	MOVD	$-128, R12
  1248  	LVX	(R0+R12), V24
  1249  	MOVD	$-112, R12
  1250  	LVX	(R0+R12), V25
  1251  	MOVD	$-96, R12
  1252  	LVX	(R0+R12), V26
  1253  	MOVD	$-80, R12
  1254  	LVX	(R0+R12), V27
  1255  	MOVD	$-64, R12
  1256  	LVX	(R0+R12), V28
  1257  	MOVD	$-48, R12
  1258  	LVX	(R0+R12), V29
  1259  	MOVD	$-32, R12
  1260  	LVX	(R0+R12), V30
  1261  	MOVD	$-16, R12
  1262  	LVX	(R0+R12), V31
  1263  	RET
  1264  

View as plain text