...
Run Format

Text file src/runtime/asm_ppc64x.s

Documentation: runtime

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

View as plain text