github.com/megatontech/mynoteforgo@v0.0.0-20200507084910-5d0c6ea6e890/源码/runtime/asm_ppc64x.s (about)

     1  // Copyright 2014 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // +build ppc64 ppc64le
     6  
     7  #include "go_asm.h"
     8  #include "go_tls.h"
     9  #include "funcdata.h"
    10  #include "textflag.h"
    11  #include "asm_ppc64x.h"
    12  
    13  TEXT runtime·rt0_go(SB),NOSPLIT,$0
    14  	// R1 = stack; R3 = argc; R4 = argv; R13 = C TLS base pointer
    15  
    16  	// initialize essential registers
    17  	BL	runtime·reginit(SB)
    18  
    19  	SUB	$(FIXED_FRAME+16), R1
    20  	MOVD	R2, 24(R1)		// stash the TOC pointer away again now we've created a new frame
    21  	MOVW	R3, FIXED_FRAME+0(R1)	// argc
    22  	MOVD	R4, FIXED_FRAME+8(R1)	// argv
    23  
    24  	// create istack out of the given (operating system) stack.
    25  	// _cgo_init may update stackguard.
    26  	MOVD	$runtime·g0(SB), g
    27  	BL	runtime·save_g(SB)
    28  	MOVD	$(-64*1024), R31
    29  	ADD	R31, R1, R3
    30  	MOVD	R3, g_stackguard0(g)
    31  	MOVD	R3, g_stackguard1(g)
    32  	MOVD	R3, (g_stack+stack_lo)(g)
    33  	MOVD	R1, (g_stack+stack_hi)(g)
    34  
    35  	// if there is a _cgo_init, call it using the gcc ABI.
    36  	MOVD	_cgo_init(SB), R12
    37  	CMP	R0, R12
    38  	BEQ	nocgo
    39  #ifdef GOARCH_ppc64
    40  	// ppc64 use elf ABI v1. we must get the real entry address from
    41  	// first slot of the function descriptor before call.
    42  	MOVD	8(R12), R2
    43  	MOVD	(R12), R12
    44  #endif
    45  	MOVD	R12, CTR		// r12 = "global function entry point"
    46  	MOVD	R13, R5			// arg 2: TLS base pointer
    47  	MOVD	$setg_gcc<>(SB), R4 	// arg 1: setg
    48  	MOVD	g, R3			// arg 0: G
    49  	// C functions expect 32 bytes of space on caller stack frame
    50  	// and a 16-byte aligned R1
    51  	MOVD	R1, R14			// save current stack
    52  	SUB	$32, R1			// reserve 32 bytes
    53  	RLDCR	$0, R1, $~15, R1	// 16-byte align
    54  	BL	(CTR)			// may clobber R0, R3-R12
    55  	MOVD	R14, R1			// restore stack
    56  	MOVD	24(R1), R2
    57  	XOR	R0, R0			// fix R0
    58  
    59  nocgo:
    60  	// update stackguard after _cgo_init
    61  	MOVD	(g_stack+stack_lo)(g), R3
    62  	ADD	$const__StackGuard, R3
    63  	MOVD	R3, g_stackguard0(g)
    64  	MOVD	R3, g_stackguard1(g)
    65  
    66  	// set the per-goroutine and per-mach "registers"
    67  	MOVD	$runtime·m0(SB), R3
    68  
    69  	// save m->g0 = g0
    70  	MOVD	g, m_g0(R3)
    71  	// save m0 to g0->m
    72  	MOVD	R3, g_m(g)
    73  
    74  	BL	runtime·check(SB)
    75  
    76  	// args are already prepared
    77  	BL	runtime·args(SB)
    78  	BL	runtime·osinit(SB)
    79  	BL	runtime·schedinit(SB)
    80  
    81  	// create a new goroutine to start program
    82  	MOVD	$runtime·mainPC(SB), R3		// entry
    83  	MOVDU	R3, -8(R1)
    84  	MOVDU	R0, -8(R1)
    85  	MOVDU	R0, -8(R1)
    86  	MOVDU	R0, -8(R1)
    87  	MOVDU	R0, -8(R1)
    88  	MOVDU	R0, -8(R1)
    89  	BL	runtime·newproc(SB)
    90  	ADD	$(16+FIXED_FRAME), R1
    91  
    92  	// start this M
    93  	BL	runtime·mstart(SB)
    94  
    95  	MOVD	R0, 0(R0)
    96  	RET
    97  
    98  DATA	runtime·mainPC+0(SB)/8,$runtime·main(SB)
    99  GLOBL	runtime·mainPC(SB),RODATA,$8
   100  
   101  TEXT runtime·breakpoint(SB),NOSPLIT|NOFRAME,$0-0
   102  	MOVD	R0, 0(R0) // TODO: TD
   103  	RET
   104  
   105  TEXT runtime·asminit(SB),NOSPLIT|NOFRAME,$0-0
   106  	RET
   107  
   108  TEXT _cgo_reginit(SB),NOSPLIT|NOFRAME,$0-0
   109  	// crosscall_ppc64 and crosscall2 need to reginit, but can't
   110  	// get at the 'runtime.reginit' symbol.
   111  	BR	runtime·reginit(SB)
   112  
   113  TEXT runtime·reginit(SB),NOSPLIT|NOFRAME,$0-0
   114  	// set R0 to zero, it's expected by the toolchain
   115  	XOR R0, R0
   116  	RET
   117  
   118  /*
   119   *  go-routine
   120   */
   121  
   122  // void gosave(Gobuf*)
   123  // save state in Gobuf; setjmp
   124  TEXT runtime·gosave(SB), NOSPLIT|NOFRAME, $0-8
   125  	MOVD	buf+0(FP), R3
   126  	MOVD	R1, gobuf_sp(R3)
   127  	MOVD	LR, R31
   128  	MOVD	R31, gobuf_pc(R3)
   129  	MOVD	g, gobuf_g(R3)
   130  	MOVD	R0, gobuf_lr(R3)
   131  	MOVD	R0, gobuf_ret(R3)
   132  	// Assert ctxt is zero. See func save.
   133  	MOVD	gobuf_ctxt(R3), R3
   134  	CMP	R0, R3
   135  	BEQ	2(PC)
   136  	BL	runtime·badctxt(SB)
   137  	RET
   138  
   139  // void gogo(Gobuf*)
   140  // restore state from Gobuf; longjmp
   141  TEXT runtime·gogo(SB), NOSPLIT, $16-8
   142  	MOVD	buf+0(FP), R5
   143  	MOVD	gobuf_g(R5), g	// make sure g is not nil
   144  	BL	runtime·save_g(SB)
   145  
   146  	MOVD	0(g), R4
   147  	MOVD	gobuf_sp(R5), R1
   148  	MOVD	gobuf_lr(R5), R31
   149  #ifndef GOOS_aix
   150  	MOVD	24(R1), R2	// restore R2
   151  #endif
   152  	MOVD	R31, LR
   153  	MOVD	gobuf_ret(R5), R3
   154  	MOVD	gobuf_ctxt(R5), R11
   155  	MOVD	R0, gobuf_sp(R5)
   156  	MOVD	R0, gobuf_ret(R5)
   157  	MOVD	R0, gobuf_lr(R5)
   158  	MOVD	R0, gobuf_ctxt(R5)
   159  	CMP	R0, R0 // set condition codes for == test, needed by stack split
   160  	MOVD	gobuf_pc(R5), R12
   161  	MOVD	R12, CTR
   162  	BR	(CTR)
   163  
   164  // void mcall(fn func(*g))
   165  // Switch to m->g0's stack, call fn(g).
   166  // Fn must never return. It should gogo(&g->sched)
   167  // to keep running g.
   168  TEXT runtime·mcall(SB), NOSPLIT|NOFRAME, $0-8
   169  	// Save caller state in g->sched
   170  	MOVD	R1, (g_sched+gobuf_sp)(g)
   171  	MOVD	LR, R31
   172  	MOVD	R31, (g_sched+gobuf_pc)(g)
   173  	MOVD	R0, (g_sched+gobuf_lr)(g)
   174  	MOVD	g, (g_sched+gobuf_g)(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	fn+0(FP), R11			// context
   185  	MOVD	0(R11), R12			// code pointer
   186  	MOVD	R12, CTR
   187  	MOVD	(g_sched+gobuf_sp)(g), R1	// sp = m->g0->sched.sp
   188  	MOVDU	R3, -8(R1)
   189  	MOVDU	R0, -8(R1)
   190  	MOVDU	R0, -8(R1)
   191  	MOVDU	R0, -8(R1)
   192  	MOVDU	R0, -8(R1)
   193  	BL	(CTR)
   194  	MOVD	24(R1), R2
   195  	BR	runtime·badmcall2(SB)
   196  
   197  // systemstack_switch is a dummy routine that systemstack leaves at the bottom
   198  // of the G stack. We need to distinguish the routine that
   199  // lives at the bottom of the G stack from the one that lives
   200  // at the top of the system stack because the one at the top of
   201  // the system stack terminates the stack walk (see topofstack()).
   202  TEXT runtime·systemstack_switch(SB), NOSPLIT, $0-0
   203  	// We have several undefs here so that 16 bytes past
   204  	// $runtime·systemstack_switch lies within them whether or not the
   205          // instructions that derive r2 from r12 are there.
   206  	UNDEF
   207  	UNDEF
   208  	UNDEF
   209  	BL	(LR)	// make sure this function is not leaf
   210  	RET
   211  
   212  // func systemstack(fn func())
   213  TEXT runtime·systemstack(SB), NOSPLIT, $0-8
   214  	MOVD	fn+0(FP), R3	// R3 = fn
   215  	MOVD	R3, R11		// context
   216  	MOVD	g_m(g), R4	// R4 = m
   217  
   218  	MOVD	m_gsignal(R4), R5	// R5 = gsignal
   219  	CMP	g, R5
   220  	BEQ	noswitch
   221  
   222  	MOVD	m_g0(R4), R5	// R5 = g0
   223  	CMP	g, R5
   224  	BEQ	noswitch
   225  
   226  	MOVD	m_curg(R4), R6
   227  	CMP	g, R6
   228  	BEQ	switch
   229  
   230  	// Bad: g is not gsignal, not g0, not curg. What is it?
   231  	// Hide call from linker nosplit analysis.
   232  	MOVD	$runtime·badsystemstack(SB), R12
   233  	MOVD	R12, CTR
   234  	BL	(CTR)
   235  	BL	runtime·abort(SB)
   236  
   237  switch:
   238  	// save our state in g->sched. Pretend to
   239  	// be systemstack_switch if the G stack is scanned.
   240  	MOVD	$runtime·systemstack_switch(SB), R6
   241  	ADD     $16, R6 // get past prologue (including r2-setting instructions when they're there)
   242  	MOVD	R6, (g_sched+gobuf_pc)(g)
   243  	MOVD	R1, (g_sched+gobuf_sp)(g)
   244  	MOVD	R0, (g_sched+gobuf_lr)(g)
   245  	MOVD	g, (g_sched+gobuf_g)(g)
   246  
   247  	// switch to g0
   248  	MOVD	R5, g
   249  	BL	runtime·save_g(SB)
   250  	MOVD	(g_sched+gobuf_sp)(g), R3
   251  	// make it look like mstart called systemstack on g0, to stop traceback
   252  	SUB	$FIXED_FRAME, R3
   253  	MOVD	$runtime·mstart(SB), R4
   254  	MOVD	R4, 0(R3)
   255  	MOVD	R3, R1
   256  
   257  	// call target function
   258  	MOVD	0(R11), R12	// code pointer
   259  	MOVD	R12, CTR
   260  	BL	(CTR)
   261  
   262  	// restore TOC pointer. It seems unlikely that we will use systemstack
   263  	// to call a function defined in another module, but the results of
   264  	// doing so would be so confusing that it's worth doing this.
   265  	MOVD	g_m(g), R3
   266  	MOVD	m_curg(R3), g
   267  	MOVD	(g_sched+gobuf_sp)(g), R3
   268  #ifndef GOOS_aix
   269  	MOVD	24(R3), R2
   270  #endif
   271  	// switch back to g
   272  	MOVD	g_m(g), R3
   273  	MOVD	m_curg(R3), g
   274  	BL	runtime·save_g(SB)
   275  	MOVD	(g_sched+gobuf_sp)(g), R1
   276  	MOVD	R0, (g_sched+gobuf_sp)(g)
   277  	RET
   278  
   279  noswitch:
   280  	// already on m stack, just call directly
   281  	// On other arches we do a tail call here, but it appears to be
   282  	// impossible to tail call a function pointer in shared mode on
   283  	// ppc64 because the caller is responsible for restoring the TOC.
   284  	MOVD	0(R11), R12	// code pointer
   285  	MOVD	R12, CTR
   286  	BL	(CTR)
   287  #ifndef GOOS_aix
   288  	MOVD	24(R1), R2
   289  #endif
   290  	RET
   291  
   292  /*
   293   * support for morestack
   294   */
   295  
   296  // Called during function prolog when more stack is needed.
   297  // Caller has already loaded:
   298  // R3: framesize, R4: argsize, R5: LR
   299  //
   300  // The traceback routines see morestack on a g0 as being
   301  // the top of a stack (for example, morestack calling newstack
   302  // calling the scheduler calling newm calling gc), so we must
   303  // record an argument size. For that purpose, it has no arguments.
   304  TEXT runtime·morestack(SB),NOSPLIT|NOFRAME,$0-0
   305  	// Cannot grow scheduler stack (m->g0).
   306  	MOVD	g_m(g), R7
   307  	MOVD	m_g0(R7), R8
   308  	CMP	g, R8
   309  	BNE	3(PC)
   310  	BL	runtime·badmorestackg0(SB)
   311  	BL	runtime·abort(SB)
   312  
   313  	// Cannot grow signal stack (m->gsignal).
   314  	MOVD	m_gsignal(R7), R8
   315  	CMP	g, R8
   316  	BNE	3(PC)
   317  	BL	runtime·badmorestackgsignal(SB)
   318  	BL	runtime·abort(SB)
   319  
   320  	// Called from f.
   321  	// Set g->sched to context in f.
   322  	MOVD	R1, (g_sched+gobuf_sp)(g)
   323  	MOVD	LR, R8
   324  	MOVD	R8, (g_sched+gobuf_pc)(g)
   325  	MOVD	R5, (g_sched+gobuf_lr)(g)
   326  	MOVD	R11, (g_sched+gobuf_ctxt)(g)
   327  
   328  	// Called from f.
   329  	// Set m->morebuf to f's caller.
   330  	MOVD	R5, (m_morebuf+gobuf_pc)(R7)	// f's caller's PC
   331  	MOVD	R1, (m_morebuf+gobuf_sp)(R7)	// f's caller's SP
   332  	MOVD	g, (m_morebuf+gobuf_g)(R7)
   333  
   334  	// Call newstack on m->g0's stack.
   335  	MOVD	m_g0(R7), g
   336  	BL	runtime·save_g(SB)
   337  	MOVD	(g_sched+gobuf_sp)(g), R1
   338  	MOVDU   R0, -(FIXED_FRAME+0)(R1)	// create a call frame on g0
   339  	BL	runtime·newstack(SB)
   340  
   341  	// Not reached, but make sure the return PC from the call to newstack
   342  	// is still in this function, and not the beginning of the next.
   343  	UNDEF
   344  
   345  TEXT runtime·morestack_noctxt(SB),NOSPLIT|NOFRAME,$0-0
   346  	MOVD	R0, R11
   347  	BR	runtime·morestack(SB)
   348  
   349  // reflectcall: call a function with the given argument list
   350  // func call(argtype *_type, f *FuncVal, arg *byte, argsize, retoffset uint32).
   351  // we don't have variable-sized frames, so we use a small number
   352  // of constant-sized-frame functions to encode a few bits of size in the pc.
   353  // Caution: ugly multiline assembly macros in your future!
   354  
   355  #define DISPATCH(NAME,MAXSIZE)		\
   356  	MOVD	$MAXSIZE, R31;		\
   357  	CMP	R3, R31;		\
   358  	BGT	4(PC);			\
   359  	MOVD	$NAME(SB), R12;		\
   360  	MOVD	R12, CTR;		\
   361  	BR	(CTR)
   362  // Note: can't just "BR NAME(SB)" - bad inlining results.
   363  
   364  TEXT ·reflectcall(SB), NOSPLIT|NOFRAME, $0-32
   365  	MOVWZ argsize+24(FP), R3
   366  	DISPATCH(runtime·call32, 32)
   367  	DISPATCH(runtime·call64, 64)
   368  	DISPATCH(runtime·call128, 128)
   369  	DISPATCH(runtime·call256, 256)
   370  	DISPATCH(runtime·call512, 512)
   371  	DISPATCH(runtime·call1024, 1024)
   372  	DISPATCH(runtime·call2048, 2048)
   373  	DISPATCH(runtime·call4096, 4096)
   374  	DISPATCH(runtime·call8192, 8192)
   375  	DISPATCH(runtime·call16384, 16384)
   376  	DISPATCH(runtime·call32768, 32768)
   377  	DISPATCH(runtime·call65536, 65536)
   378  	DISPATCH(runtime·call131072, 131072)
   379  	DISPATCH(runtime·call262144, 262144)
   380  	DISPATCH(runtime·call524288, 524288)
   381  	DISPATCH(runtime·call1048576, 1048576)
   382  	DISPATCH(runtime·call2097152, 2097152)
   383  	DISPATCH(runtime·call4194304, 4194304)
   384  	DISPATCH(runtime·call8388608, 8388608)
   385  	DISPATCH(runtime·call16777216, 16777216)
   386  	DISPATCH(runtime·call33554432, 33554432)
   387  	DISPATCH(runtime·call67108864, 67108864)
   388  	DISPATCH(runtime·call134217728, 134217728)
   389  	DISPATCH(runtime·call268435456, 268435456)
   390  	DISPATCH(runtime·call536870912, 536870912)
   391  	DISPATCH(runtime·call1073741824, 1073741824)
   392  	MOVD	$runtime·badreflectcall(SB), R12
   393  	MOVD	R12, CTR
   394  	BR	(CTR)
   395  
   396  #define CALLFN(NAME,MAXSIZE)			\
   397  TEXT NAME(SB), WRAPPER, $MAXSIZE-24;		\
   398  	NO_LOCAL_POINTERS;			\
   399  	/* copy arguments to stack */		\
   400  	MOVD	arg+16(FP), R3;			\
   401  	MOVWZ	argsize+24(FP), R4;			\
   402  	MOVD    R1, R5;				\
   403  	CMP	R4, $8;				\
   404  	BLT	tailsetup;			\
   405  	/* copy 8 at a time if possible */	\
   406  	ADD	$(FIXED_FRAME-8), R5;			\
   407  	SUB	$8, R3;				\
   408  top: \
   409  	MOVDU	8(R3), R7;			\
   410  	MOVDU	R7, 8(R5);			\
   411  	SUB	$8, R4;				\
   412  	CMP	R4, $8;				\
   413  	BGE	top;				\
   414  	/* handle remaining bytes */	\
   415  	CMP	$0, R4;			\
   416  	BEQ	callfn;			\
   417  	ADD	$7, R3;			\
   418  	ADD	$7, R5;			\
   419  	BR	tail;			\
   420  tailsetup: \
   421  	CMP	$0, R4;			\
   422  	BEQ	callfn;			\
   423  	ADD     $(FIXED_FRAME-1), R5;	\
   424  	SUB     $1, R3;			\
   425  tail: \
   426  	MOVBU	1(R3), R6;		\
   427  	MOVBU	R6, 1(R5);		\
   428  	SUB	$1, R4;			\
   429  	CMP	$0, R4;			\
   430  	BGT	tail;			\
   431  callfn: \
   432  	/* call function */			\
   433  	MOVD	f+8(FP), R11;			\
   434  #ifdef GOOS_aix				\
   435  	/* AIX won't trigger a SIGSEGV if R11 = nil */	\
   436  	/* So it manually triggers it */	\
   437  	CMP	R0, R11				\
   438  	BNE	2(PC)				\
   439  	MOVD	R0, 0(R0)			\
   440  #endif						\
   441  	MOVD	(R11), R12;			\
   442  	MOVD	R12, CTR;			\
   443  	PCDATA  $PCDATA_StackMapIndex, $0;	\
   444  	BL	(CTR);				\
   445  #ifndef GOOS_aix				\
   446  	MOVD	24(R1), R2;			\
   447  #endif						\
   448  	/* copy return values back */		\
   449  	MOVD	argtype+0(FP), R7;		\
   450  	MOVD	arg+16(FP), R3;			\
   451  	MOVWZ	n+24(FP), R4;			\
   452  	MOVWZ	retoffset+28(FP), R6;		\
   453  	ADD	$FIXED_FRAME, R1, R5;		\
   454  	ADD	R6, R5; 			\
   455  	ADD	R6, R3;				\
   456  	SUB	R6, R4;				\
   457  	BL	callRet<>(SB);			\
   458  	RET
   459  
   460  // callRet copies return values back at the end of call*. This is a
   461  // separate function so it can allocate stack space for the arguments
   462  // to reflectcallmove. It does not follow the Go ABI; it expects its
   463  // arguments in registers.
   464  TEXT callRet<>(SB), NOSPLIT, $32-0
   465  	MOVD	R7, FIXED_FRAME+0(R1)
   466  	MOVD	R3, FIXED_FRAME+8(R1)
   467  	MOVD	R5, FIXED_FRAME+16(R1)
   468  	MOVD	R4, FIXED_FRAME+24(R1)
   469  	BL	runtime·reflectcallmove(SB)
   470  	RET
   471  
   472  CALLFN(·call32, 32)
   473  CALLFN(·call64, 64)
   474  CALLFN(·call128, 128)
   475  CALLFN(·call256, 256)
   476  CALLFN(·call512, 512)
   477  CALLFN(·call1024, 1024)
   478  CALLFN(·call2048, 2048)
   479  CALLFN(·call4096, 4096)
   480  CALLFN(·call8192, 8192)
   481  CALLFN(·call16384, 16384)
   482  CALLFN(·call32768, 32768)
   483  CALLFN(·call65536, 65536)
   484  CALLFN(·call131072, 131072)
   485  CALLFN(·call262144, 262144)
   486  CALLFN(·call524288, 524288)
   487  CALLFN(·call1048576, 1048576)
   488  CALLFN(·call2097152, 2097152)
   489  CALLFN(·call4194304, 4194304)
   490  CALLFN(·call8388608, 8388608)
   491  CALLFN(·call16777216, 16777216)
   492  CALLFN(·call33554432, 33554432)
   493  CALLFN(·call67108864, 67108864)
   494  CALLFN(·call134217728, 134217728)
   495  CALLFN(·call268435456, 268435456)
   496  CALLFN(·call536870912, 536870912)
   497  CALLFN(·call1073741824, 1073741824)
   498  
   499  TEXT runtime·procyield(SB),NOSPLIT|NOFRAME,$0-4
   500  	MOVW	cycles+0(FP), R7
   501  	// POWER does not have a pause/yield instruction equivalent.
   502  	// Instead, we can lower the program priority by setting the
   503  	// Program Priority Register prior to the wait loop and set it
   504  	// back to default afterwards. On Linux, the default priority is
   505  	// medium-low. For details, see page 837 of the ISA 3.0.
   506  	OR	R1, R1, R1	// Set PPR priority to low
   507  again:
   508  	SUB	$1, R7
   509  	CMP	$0, R7
   510  	BNE	again
   511  	OR	R6, R6, R6	// Set PPR priority back to medium-low
   512  	RET
   513  
   514  // void jmpdefer(fv, sp);
   515  // called from deferreturn.
   516  // 1. grab stored LR for caller
   517  // 2. sub 8 bytes to get back to either nop or toc reload before deferreturn
   518  // 3. BR to fn
   519  // When dynamically linking Go, it is not sufficient to rewind to the BL
   520  // deferreturn -- we might be jumping between modules and so we need to reset
   521  // the TOC pointer in r2. To do this, codegen inserts MOVD 24(R1), R2 *before*
   522  // the BL deferreturn and jmpdefer rewinds to that.
   523  TEXT runtime·jmpdefer(SB), NOSPLIT|NOFRAME, $0-16
   524  	MOVD	0(R1), R31
   525  	SUB     $8, R31
   526  	MOVD	R31, LR
   527  
   528  	MOVD	fv+0(FP), R11
   529  	MOVD	argp+8(FP), R1
   530  	SUB	$FIXED_FRAME, R1
   531  #ifdef GOOS_aix
   532  	// AIX won't trigger a SIGSEGV if R11 = nil
   533  	// So it manually triggers it
   534  	CMP	R0, R11
   535  	BNE	2(PC)
   536  	MOVD	R0, 0(R0)
   537  #endif
   538  	MOVD	0(R11), R12
   539  	MOVD	R12, CTR
   540  	BR	(CTR)
   541  
   542  // Save state of caller into g->sched. Smashes R31.
   543  TEXT gosave<>(SB),NOSPLIT|NOFRAME,$0
   544  	MOVD	LR, R31
   545  	MOVD	R31, (g_sched+gobuf_pc)(g)
   546  	MOVD	R1, (g_sched+gobuf_sp)(g)
   547  	MOVD	R0, (g_sched+gobuf_lr)(g)
   548  	MOVD	R0, (g_sched+gobuf_ret)(g)
   549  	// Assert ctxt is zero. See func save.
   550  	MOVD	(g_sched+gobuf_ctxt)(g), R31
   551  	CMP	R0, R31
   552  	BEQ	2(PC)
   553  	BL	runtime·badctxt(SB)
   554  	RET
   555  
   556  // func asmcgocall(fn, arg unsafe.Pointer) int32
   557  // Call fn(arg) on the scheduler stack,
   558  // aligned appropriately for the gcc ABI.
   559  // See cgocall.go for more details.
   560  TEXT ·asmcgocall(SB),NOSPLIT,$0-20
   561  	MOVD	fn+0(FP), R3
   562  	MOVD	arg+8(FP), R4
   563  
   564  	MOVD	R1, R7		// save original stack pointer
   565  	MOVD	g, R5
   566  
   567  	// Figure out if we need to switch to m->g0 stack.
   568  	// We get called to create new OS threads too, and those
   569  	// come in on the m->g0 stack already.
   570  	// Moreover, if it's called inside the signal handler, it must not switch
   571  	// to g0 as it can be in use by another syscall.
   572  	MOVD	g_m(g), R8
   573  	MOVD	m_gsignal(R8), R6
   574  	CMP	R6, g
   575  	BEQ	g0
   576  	MOVD	m_g0(R8), R6
   577  	CMP	R6, g
   578  	BEQ	g0
   579  	BL	gosave<>(SB)
   580  	MOVD	R6, g
   581  	BL	runtime·save_g(SB)
   582  	MOVD	(g_sched+gobuf_sp)(g), R1
   583  
   584  	// Now on a scheduling stack (a pthread-created stack).
   585  g0:
   586  	// Save room for two of our pointers, plus 32 bytes of callee
   587  	// save area that lives on the caller stack.
   588  #ifdef GOOS_aix
   589  	// Create a fake LR to improve backtrace.
   590  	MOVD	$runtime·asmcgocall(SB), R6
   591  	MOVD	R6, 16(R1)
   592  #endif
   593  	SUB	$48, R1
   594  	RLDCR	$0, R1, $~15, R1	// 16-byte alignment for gcc ABI
   595  	MOVD	R5, 40(R1)	// save old g on stack
   596  	MOVD	(g_stack+stack_hi)(R5), R5
   597  	SUB	R7, R5
   598  	MOVD	R5, 32(R1)	// save depth in old g stack (can't just save SP, as stack might be copied during a callback)
   599  #ifdef GOOS_aix
   600  	MOVD	R7, 0(R1)	// Save frame pointer to allow manual backtrace with gdb
   601  #else
   602  	MOVD	R0, 0(R1)	// clear back chain pointer (TODO can we give it real back trace information?)
   603  #endif
   604  	// This is a "global call", so put the global entry point in r12
   605  	MOVD	R3, R12
   606  
   607  #ifdef GOARCH_ppc64
   608  	// ppc64 use elf ABI v1. we must get the real entry address from
   609  	// first slot of the function descriptor before call.
   610  #ifndef GOOS_aix
   611  	// aix just passes the function pointer for the moment, see golang.org/cl/146898 for details.
   612  	MOVD	8(R12), R2
   613  	MOVD	(R12), R12
   614  #endif
   615  #endif
   616  	MOVD	R12, CTR
   617  	MOVD	R4, R3		// arg in r3
   618  	BL	(CTR)
   619  
   620  	// C code can clobber R0, so set it back to 0.  F27-F31 are
   621  	// callee save, so we don't need to recover those.
   622  	XOR	R0, R0
   623  	// Restore g, stack pointer, toc pointer.
   624  	// R3 is errno, so don't touch it
   625  	MOVD	40(R1), g
   626  	MOVD	(g_stack+stack_hi)(g), R5
   627  	MOVD	32(R1), R6
   628  	SUB	R6, R5
   629  #ifndef GOOS_aix
   630  	MOVD	24(R5), R2
   631  #endif
   632  	MOVD	R5, R1
   633  	BL	runtime·save_g(SB)
   634  
   635  	MOVW	R3, ret+16(FP)
   636  	RET
   637  
   638  // cgocallback(void (*fn)(void*), void *frame, uintptr framesize, uintptr ctxt)
   639  // Turn the fn into a Go func (by taking its address) and call
   640  // cgocallback_gofunc.
   641  TEXT runtime·cgocallback(SB),NOSPLIT,$32-32
   642  	MOVD	$fn+0(FP), R3
   643  	MOVD	R3, FIXED_FRAME+0(R1)
   644  	MOVD	frame+8(FP), R3
   645  	MOVD	R3, FIXED_FRAME+8(R1)
   646  	MOVD	framesize+16(FP), R3
   647  	MOVD	R3, FIXED_FRAME+16(R1)
   648  	MOVD	ctxt+24(FP), R3
   649  	MOVD	R3, FIXED_FRAME+24(R1)
   650  	MOVD	$runtime·cgocallback_gofunc(SB), R12
   651  	MOVD	R12, CTR
   652  	BL	(CTR)
   653  	RET
   654  
   655  // cgocallback_gofunc(FuncVal*, void *frame, uintptr framesize, uintptr ctxt)
   656  // See cgocall.go for more details.
   657  TEXT ·cgocallback_gofunc(SB),NOSPLIT,$16-32
   658  	NO_LOCAL_POINTERS
   659  
   660  	// Load m and g from thread-local storage.
   661  	MOVBZ	runtime·iscgo(SB), R3
   662  	CMP	R3, $0
   663  	BEQ	nocgo
   664  	BL	runtime·load_g(SB)
   665  nocgo:
   666  
   667  	// If g is nil, Go did not create the current thread.
   668  	// Call needm to obtain one for temporary use.
   669  	// In this case, we're running on the thread stack, so there's
   670  	// lots of space, but the linker doesn't know. Hide the call from
   671  	// the linker analysis by using an indirect call.
   672  	CMP	g, $0
   673  	BEQ	needm
   674  
   675  	MOVD	g_m(g), R8
   676  	MOVD	R8, savedm-8(SP)
   677  	BR	havem
   678  
   679  needm:
   680  	MOVD	g, savedm-8(SP) // g is zero, so is m.
   681  	MOVD	$runtime·needm(SB), R12
   682  	MOVD	R12, CTR
   683  	BL	(CTR)
   684  
   685  	// Set m->sched.sp = SP, so that if a panic happens
   686  	// during the function we are about to execute, it will
   687  	// have a valid SP to run on the g0 stack.
   688  	// The next few lines (after the havem label)
   689  	// will save this SP onto the stack and then write
   690  	// the same SP back to m->sched.sp. That seems redundant,
   691  	// but if an unrecovered panic happens, unwindm will
   692  	// restore the g->sched.sp from the stack location
   693  	// and then systemstack will try to use it. If we don't set it here,
   694  	// that restored SP will be uninitialized (typically 0) and
   695  	// will not be usable.
   696  	MOVD	g_m(g), R8
   697  	MOVD	m_g0(R8), R3
   698  	MOVD	R1, (g_sched+gobuf_sp)(R3)
   699  
   700  havem:
   701  	// Now there's a valid m, and we're running on its m->g0.
   702  	// Save current m->g0->sched.sp on stack and then set it to SP.
   703  	// Save current sp in m->g0->sched.sp in preparation for
   704  	// switch back to m->curg stack.
   705  	// NOTE: unwindm knows that the saved g->sched.sp is at 8(R1) aka savedsp-16(SP).
   706  	MOVD	m_g0(R8), R3
   707  	MOVD	(g_sched+gobuf_sp)(R3), R4
   708  	MOVD	R4, savedsp-16(SP)
   709  	MOVD	R1, (g_sched+gobuf_sp)(R3)
   710  
   711  	// Switch to m->curg stack and call runtime.cgocallbackg.
   712  	// Because we are taking over the execution of m->curg
   713  	// but *not* resuming what had been running, we need to
   714  	// save that information (m->curg->sched) so we can restore it.
   715  	// We can restore m->curg->sched.sp easily, because calling
   716  	// runtime.cgocallbackg leaves SP unchanged upon return.
   717  	// To save m->curg->sched.pc, we push it onto the stack.
   718  	// This has the added benefit that it looks to the traceback
   719  	// routine like cgocallbackg is going to return to that
   720  	// PC (because the frame we allocate below has the same
   721  	// size as cgocallback_gofunc's frame declared above)
   722  	// so that the traceback will seamlessly trace back into
   723  	// the earlier calls.
   724  	//
   725  	// In the new goroutine, -8(SP) is unused (where SP refers to
   726  	// m->curg's SP while we're setting it up, before we've adjusted it).
   727  	MOVD	m_curg(R8), g
   728  	BL	runtime·save_g(SB)
   729  	MOVD	(g_sched+gobuf_sp)(g), R4 // prepare stack as R4
   730  	MOVD	(g_sched+gobuf_pc)(g), R5
   731  	MOVD	R5, -(FIXED_FRAME+16)(R4)
   732  	MOVD	ctxt+24(FP), R3
   733  	MOVD	R3, -16(R4)
   734  	MOVD	$-(FIXED_FRAME+16)(R4), R1
   735  	BL	runtime·cgocallbackg(SB)
   736  
   737  	// Restore g->sched (== m->curg->sched) from saved values.
   738  	MOVD	0(R1), R5
   739  	MOVD	R5, (g_sched+gobuf_pc)(g)
   740  	MOVD	$(FIXED_FRAME+16)(R1), R4
   741  	MOVD	R4, (g_sched+gobuf_sp)(g)
   742  
   743  	// Switch back to m->g0's stack and restore m->g0->sched.sp.
   744  	// (Unlike m->curg, the g0 goroutine never uses sched.pc,
   745  	// so we do not have to restore it.)
   746  	MOVD	g_m(g), R8
   747  	MOVD	m_g0(R8), g
   748  	BL	runtime·save_g(SB)
   749  	MOVD	(g_sched+gobuf_sp)(g), R1
   750  	MOVD	savedsp-16(SP), R4
   751  	MOVD	R4, (g_sched+gobuf_sp)(g)
   752  
   753  	// If the m on entry was nil, we called needm above to borrow an m
   754  	// for the duration of the call. Since the call is over, return it with dropm.
   755  	MOVD	savedm-8(SP), R6
   756  	CMP	R6, $0
   757  	BNE	droppedm
   758  	MOVD	$runtime·dropm(SB), R12
   759  	MOVD	R12, CTR
   760  	BL	(CTR)
   761  droppedm:
   762  
   763  	// Done!
   764  	RET
   765  
   766  // void setg(G*); set g. for use by needm.
   767  TEXT runtime·setg(SB), NOSPLIT, $0-8
   768  	MOVD	gg+0(FP), g
   769  	// This only happens if iscgo, so jump straight to save_g
   770  	BL	runtime·save_g(SB)
   771  	RET
   772  
   773  #ifdef GOARCH_ppc64
   774  TEXT setg_gcc<>(SB),NOSPLIT|NOFRAME,$0-0
   775  	DWORD	$_setg_gcc<>(SB)
   776  	DWORD	$0
   777  	DWORD	$0
   778  #endif
   779  
   780  // void setg_gcc(G*); set g in C TLS.
   781  // Must obey the gcc calling convention.
   782  #ifdef GOARCH_ppc64le
   783  TEXT setg_gcc<>(SB),NOSPLIT|NOFRAME,$0-0
   784  #else
   785  TEXT _setg_gcc<>(SB),NOSPLIT|NOFRAME,$0-0
   786  #endif
   787  	// The standard prologue clobbers R31, which is callee-save in
   788  	// the C ABI, so we have to use $-8-0 and save LR ourselves.
   789  	MOVD	LR, R4
   790  	// Also save g and R31, since they're callee-save in C ABI
   791  	MOVD	R31, R5
   792  	MOVD	g, R6
   793  
   794  	MOVD	R3, g
   795  	BL	runtime·save_g(SB)
   796  
   797  	MOVD	R6, g
   798  	MOVD	R5, R31
   799  	MOVD	R4, LR
   800  	RET
   801  
   802  TEXT runtime·abort(SB),NOSPLIT|NOFRAME,$0-0
   803  	MOVW	(R0), R0
   804  	UNDEF
   805  
   806  #define	TBR	268
   807  
   808  // int64 runtime·cputicks(void)
   809  TEXT runtime·cputicks(SB),NOSPLIT,$0-8
   810  	MOVD	SPR(TBR), R3
   811  	MOVD	R3, ret+0(FP)
   812  	RET
   813  
   814  // AES hashing not implemented for ppc64
   815  TEXT runtime·aeshash(SB),NOSPLIT|NOFRAME,$0-0
   816  	MOVW	(R0), R1
   817  TEXT runtime·aeshash32(SB),NOSPLIT|NOFRAME,$0-0
   818  	MOVW	(R0), R1
   819  TEXT runtime·aeshash64(SB),NOSPLIT|NOFRAME,$0-0
   820  	MOVW	(R0), R1
   821  TEXT runtime·aeshashstr(SB),NOSPLIT|NOFRAME,$0-0
   822  	MOVW	(R0), R1
   823  
   824  TEXT runtime·return0(SB), NOSPLIT, $0
   825  	MOVW	$0, R3
   826  	RET
   827  
   828  // Called from cgo wrappers, this function returns g->m->curg.stack.hi.
   829  // Must obey the gcc calling convention.
   830  TEXT _cgo_topofstack(SB),NOSPLIT|NOFRAME,$0
   831  	// g (R30) and R31 are callee-save in the C ABI, so save them
   832  	MOVD	g, R4
   833  	MOVD	R31, R5
   834  	MOVD	LR, R6
   835  
   836  	BL	runtime·load_g(SB)	// clobbers g (R30), R31
   837  	MOVD	g_m(g), R3
   838  	MOVD	m_curg(R3), R3
   839  	MOVD	(g_stack+stack_hi)(R3), R3
   840  
   841  	MOVD	R4, g
   842  	MOVD	R5, R31
   843  	MOVD	R6, LR
   844  	RET
   845  
   846  // The top-most function running on a goroutine
   847  // returns to goexit+PCQuantum.
   848  //
   849  // When dynamically linking Go, it can be returned to from a function
   850  // implemented in a different module and so needs to reload the TOC pointer
   851  // from the stack (although this function declares that it does not set up x-a
   852  // frame, newproc1 does in fact allocate one for goexit and saves the TOC
   853  // pointer in the correct place).
   854  // goexit+_PCQuantum is halfway through the usual global entry point prologue
   855  // that derives r2 from r12 which is a bit silly, but not harmful.
   856  TEXT runtime·goexit(SB),NOSPLIT|NOFRAME,$0-0
   857  	MOVD	24(R1), R2
   858  	BL	runtime·goexit1(SB)	// does not return
   859  	// traceback from goexit1 must hit code range of goexit
   860  	MOVD	R0, R0	// NOP
   861  
   862  TEXT runtime·sigreturn(SB),NOSPLIT,$0-0
   863  	RET
   864  
   865  // prepGoExitFrame saves the current TOC pointer (i.e. the TOC pointer for the
   866  // module containing runtime) to the frame that goexit will execute in when
   867  // the goroutine exits. It's implemented in assembly mainly because that's the
   868  // easiest way to get access to R2.
   869  TEXT runtime·prepGoExitFrame(SB),NOSPLIT,$0-8
   870        MOVD    sp+0(FP), R3
   871        MOVD    R2, 24(R3)
   872        RET
   873  
   874  TEXT runtime·addmoduledata(SB),NOSPLIT|NOFRAME,$0-0
   875  	ADD	$-8, R1
   876  	MOVD	R31, 0(R1)
   877  	MOVD	runtime·lastmoduledatap(SB), R4
   878  	MOVD	R3, moduledata_next(R4)
   879  	MOVD	R3, runtime·lastmoduledatap(SB)
   880  	MOVD	0(R1), R31
   881  	ADD	$8, R1
   882  	RET
   883  
   884  TEXT ·checkASM(SB),NOSPLIT,$0-1
   885  	MOVW	$1, R3
   886  	MOVB	R3, ret+0(FP)
   887  	RET
   888  
   889  // gcWriteBarrier performs a heap pointer write and informs the GC.
   890  //
   891  // gcWriteBarrier does NOT follow the Go ABI. It takes two arguments:
   892  // - R20 is the destination of the write
   893  // - R21 is the value being written at R20.
   894  // It clobbers condition codes.
   895  // It does not clobber R0 through R15,
   896  // but may clobber any other register, *including* R31.
   897  TEXT runtime·gcWriteBarrier(SB),NOSPLIT,$112
   898  	// The standard prologue clobbers R31.
   899  	// We use R16 and R17 as scratch registers.
   900  	MOVD	g_m(g), R16
   901  	MOVD	m_p(R16), R16
   902  	MOVD	(p_wbBuf+wbBuf_next)(R16), R17
   903  	// Increment wbBuf.next position.
   904  	ADD	$16, R17
   905  	MOVD	R17, (p_wbBuf+wbBuf_next)(R16)
   906  	MOVD	(p_wbBuf+wbBuf_end)(R16), R16
   907  	CMP	R16, R17
   908  	// Record the write.
   909  	MOVD	R21, -16(R17)	// Record value
   910  	MOVD	(R20), R16	// TODO: This turns bad writes into bad reads.
   911  	MOVD	R16, -8(R17)	// Record *slot
   912  	// Is the buffer full? (flags set in CMP above)
   913  	BEQ	flush
   914  ret:
   915  	// Do the write.
   916  	MOVD	R21, (R20)
   917  	RET
   918  
   919  flush:
   920  	// Save registers R0 through R15 since these were not saved by the caller.
   921  	// We don't save all registers on ppc64 because it takes too much space.
   922  	MOVD	R20, (FIXED_FRAME+0)(R1)	// Also first argument to wbBufFlush
   923  	MOVD	R21, (FIXED_FRAME+8)(R1)	// Also second argument to wbBufFlush
   924  	// R0 is always 0, so no need to spill.
   925  	// R1 is SP.
   926  	// R2 is SB.
   927  	MOVD	R3, (FIXED_FRAME+16)(R1)
   928  	MOVD	R4, (FIXED_FRAME+24)(R1)
   929  	MOVD	R5, (FIXED_FRAME+32)(R1)
   930  	MOVD	R6, (FIXED_FRAME+40)(R1)
   931  	MOVD	R7, (FIXED_FRAME+48)(R1)
   932  	MOVD	R8, (FIXED_FRAME+56)(R1)
   933  	MOVD	R9, (FIXED_FRAME+64)(R1)
   934  	MOVD	R10, (FIXED_FRAME+72)(R1)
   935  	MOVD	R11, (FIXED_FRAME+80)(R1)
   936  	MOVD	R12, (FIXED_FRAME+88)(R1)
   937  	// R13 is REGTLS
   938  	MOVD	R14, (FIXED_FRAME+96)(R1)
   939  	MOVD	R15, (FIXED_FRAME+104)(R1)
   940  
   941  	// This takes arguments R20 and R21.
   942  	CALL	runtime·wbBufFlush(SB)
   943  
   944  	MOVD	(FIXED_FRAME+0)(R1), R20
   945  	MOVD	(FIXED_FRAME+8)(R1), R21
   946  	MOVD	(FIXED_FRAME+16)(R1), R3
   947  	MOVD	(FIXED_FRAME+24)(R1), R4
   948  	MOVD	(FIXED_FRAME+32)(R1), R5
   949  	MOVD	(FIXED_FRAME+40)(R1), R6
   950  	MOVD	(FIXED_FRAME+48)(R1), R7
   951  	MOVD	(FIXED_FRAME+56)(R1), R8
   952  	MOVD	(FIXED_FRAME+64)(R1), R9
   953  	MOVD	(FIXED_FRAME+72)(R1), R10
   954  	MOVD	(FIXED_FRAME+80)(R1), R11
   955  	MOVD	(FIXED_FRAME+88)(R1), R12
   956  	MOVD	(FIXED_FRAME+96)(R1), R14
   957  	MOVD	(FIXED_FRAME+104)(R1), R15
   958  	JMP	ret