|  | // Copyright 2018 The Go Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style | 
|  | // license that can be found in the LICENSE file. | 
|  |  | 
|  | // +build aix | 
|  | // +build ppc64 ppc64le | 
|  |  | 
|  | // | 
|  | // System calls and other sys.stuff for ppc64, Aix | 
|  | // | 
|  |  | 
|  | #include "go_asm.h" | 
|  | #include "go_tls.h" | 
|  | #include "textflag.h" | 
|  | #include "asm_ppc64x.h" | 
|  |  | 
|  | // This function calls a C function with the function descriptor in R12 | 
|  | TEXT callCfunction<>(SB),	NOSPLIT|NOFRAME,$0 | 
|  | MOVD	0(R12), R12 | 
|  | MOVD	R2, 40(R1) | 
|  | MOVD	0(R12), R0 | 
|  | MOVD	8(R12), R2 | 
|  | MOVD	R0, CTR | 
|  | BR	(CTR) | 
|  |  | 
|  |  | 
|  | // asmsyscall6 calls a library function with a function descriptor | 
|  | // stored in libcall_fn and store the results in libcall struture | 
|  | // Up to 6 arguments can be passed to this C function | 
|  | // Called by runtime.asmcgocall | 
|  | // It reserves a stack of 288 bytes for the C function. | 
|  | // NOT USING GO CALLING CONVENTION | 
|  | // runtime.asmsyscall6 is a function descriptor to the real asmsyscall6. | 
|  | DATA	runtime·asmsyscall6+0(SB)/8, $asmsyscall6<>(SB) | 
|  | DATA	runtime·asmsyscall6+8(SB)/8, $TOC(SB) | 
|  | DATA	runtime·asmsyscall6+16(SB)/8, $0 | 
|  | GLOBL	runtime·asmsyscall6(SB), NOPTR, $24 | 
|  |  | 
|  | TEXT asmsyscall6<>(SB),NOSPLIT,$256 | 
|  | MOVD	R3, 48(R1) // Save libcall for later | 
|  | MOVD	libcall_fn(R3), R12 | 
|  | MOVD	libcall_args(R3), R9 | 
|  | MOVD	0(R9), R3 | 
|  | MOVD	8(R9), R4 | 
|  | MOVD	16(R9), R5 | 
|  | MOVD	24(R9), R6 | 
|  | MOVD	32(R9), R7 | 
|  | MOVD	40(R9), R8 | 
|  | BL	callCfunction<>(SB) | 
|  |  | 
|  | // Restore R0 and TOC | 
|  | XOR	R0, R0 | 
|  | MOVD	40(R1), R2 | 
|  |  | 
|  | // Store result in libcall | 
|  | MOVD	48(R1), R5 | 
|  | MOVD	R3, (libcall_r1)(R5) | 
|  | MOVD	$-1, R6 | 
|  | CMP	R6, R3 | 
|  | BNE	skiperrno | 
|  |  | 
|  | // Save errno in libcall | 
|  | BL	runtime·load_g(SB) | 
|  | MOVD	g_m(g), R4 | 
|  | MOVD	(m_mOS + mOS_perrno)(R4), R9 | 
|  | MOVW	0(R9), R9 | 
|  | MOVD	R9, (libcall_err)(R5) | 
|  | RET | 
|  | skiperrno: | 
|  | // Reset errno if no error has been returned | 
|  | MOVD	R0, (libcall_err)(R5) | 
|  | RET | 
|  |  | 
|  |  | 
|  | TEXT runtime·sigfwd(SB),NOSPLIT,$0-32 | 
|  | MOVW	sig+8(FP), R3 | 
|  | MOVD	info+16(FP), R4 | 
|  | MOVD	ctx+24(FP), R5 | 
|  | MOVD	fn+0(FP), R12 | 
|  | // fn is a function descriptor | 
|  | // R2 must be saved on restore | 
|  | MOVD	0(R12), R0 | 
|  | MOVD	R2, 40(R1) | 
|  | MOVD	8(R12), R2 | 
|  | MOVD	R0, CTR | 
|  | BL	(CTR) | 
|  | MOVD	40(R1), R2 | 
|  | BL	runtime·reginit(SB) | 
|  | RET | 
|  |  | 
|  |  | 
|  | // runtime.sigtramp is a function descriptor to the real sigtramp. | 
|  | DATA	runtime·sigtramp+0(SB)/8, $sigtramp<>(SB) | 
|  | DATA	runtime·sigtramp+8(SB)/8, $TOC(SB) | 
|  | DATA	runtime·sigtramp+16(SB)/8, $0 | 
|  | GLOBL	runtime·sigtramp(SB), NOPTR, $24 | 
|  |  | 
|  | // This function must not have any frame as we want to control how | 
|  | // every registers are used. | 
|  | // TODO(aix): Implement SetCgoTraceback handler. | 
|  | TEXT sigtramp<>(SB),NOSPLIT|NOFRAME,$0 | 
|  | MOVD	LR, R0 | 
|  | MOVD	R0, 16(R1) | 
|  | // initialize essential registers (just in case) | 
|  | BL	runtime·reginit(SB) | 
|  |  | 
|  | // Note that we are executing on altsigstack here, so we have | 
|  | // more stack available than NOSPLIT would have us believe. | 
|  | // To defeat the linker, we make our own stack frame with | 
|  | // more space. | 
|  | SUB	$144+FIXED_FRAME, R1 | 
|  |  | 
|  | // Save registers | 
|  | MOVD	R31, 56(R1) | 
|  | MOVD	g, 64(R1) | 
|  | MOVD	R29, 72(R1) | 
|  | MOVD	R14, 80(R1) | 
|  | MOVD	R15, 88(R1) | 
|  |  | 
|  | BL	runtime·load_g(SB) | 
|  |  | 
|  | CMP	$0, g | 
|  | BEQ	sigtramp // g == nil | 
|  | MOVD	g_m(g), R6 | 
|  | CMP	$0, R6 | 
|  | BEQ	sigtramp	// g.m == nil | 
|  |  | 
|  | // Save m->libcall. We need to do this because we | 
|  | // might get interrupted by a signal in runtime·asmcgocall. | 
|  | MOVD	(m_libcall+libcall_fn)(R6), R7 | 
|  | MOVD	R7, 96(R1) | 
|  | MOVD	(m_libcall+libcall_args)(R6), R7 | 
|  | MOVD	R7, 104(R1) | 
|  | MOVD	(m_libcall+libcall_n)(R6), R7 | 
|  | MOVD	R7, 112(R1) | 
|  | MOVD	(m_libcall+libcall_r1)(R6), R7 | 
|  | MOVD	R7, 120(R1) | 
|  | MOVD	(m_libcall+libcall_r2)(R6), R7 | 
|  | MOVD	R7, 128(R1) | 
|  |  | 
|  | // save errno, it might be EINTR; stuff we do here might reset it. | 
|  | MOVD	(m_mOS+mOS_perrno)(R6), R8 | 
|  | MOVD	0(R8), R8 | 
|  | MOVD	R8, 136(R1) | 
|  |  | 
|  | sigtramp: | 
|  | MOVW	R3, FIXED_FRAME+0(R1) | 
|  | MOVD	R4, FIXED_FRAME+8(R1) | 
|  | MOVD	R5, FIXED_FRAME+16(R1) | 
|  | MOVD	$runtime·sigtrampgo(SB), R12 | 
|  | MOVD	R12, CTR | 
|  | BL	(CTR) | 
|  |  | 
|  | CMP	$0, g | 
|  | BEQ	exit // g == nil | 
|  | MOVD	g_m(g), R6 | 
|  | CMP	$0, R6 | 
|  | BEQ	exit	// g.m == nil | 
|  |  | 
|  | // restore libcall | 
|  | MOVD	96(R1), R7 | 
|  | MOVD	R7, (m_libcall+libcall_fn)(R6) | 
|  | MOVD	104(R1), R7 | 
|  | MOVD	R7, (m_libcall+libcall_args)(R6) | 
|  | MOVD	112(R1), R7 | 
|  | MOVD	R7, (m_libcall+libcall_n)(R6) | 
|  | MOVD	120(R1), R7 | 
|  | MOVD	R7, (m_libcall+libcall_r1)(R6) | 
|  | MOVD	128(R1), R7 | 
|  | MOVD	R7, (m_libcall+libcall_r2)(R6) | 
|  |  | 
|  | // restore errno | 
|  | MOVD	(m_mOS+mOS_perrno)(R6), R7 | 
|  | MOVD	136(R1), R8 | 
|  | MOVD	R8, 0(R7) | 
|  |  | 
|  | exit: | 
|  | // restore registers | 
|  | MOVD	56(R1),R31 | 
|  | MOVD	64(R1),g | 
|  | MOVD	72(R1),R29 | 
|  | MOVD	80(R1), R14 | 
|  | MOVD	88(R1), R15 | 
|  |  | 
|  | // Don't use RET because we need to restore R31 ! | 
|  | ADD $144+FIXED_FRAME, R1 | 
|  | MOVD	16(R1), R0 | 
|  | MOVD	R0, LR | 
|  | BR (LR) | 
|  |  | 
|  | // runtime.tstart is a function descriptor to the real tstart. | 
|  | DATA	runtime·tstart+0(SB)/8, $tstart<>(SB) | 
|  | DATA	runtime·tstart+8(SB)/8, $TOC(SB) | 
|  | DATA	runtime·tstart+16(SB)/8, $0 | 
|  | GLOBL	runtime·tstart(SB), NOPTR, $24 | 
|  |  | 
|  | TEXT tstart<>(SB),NOSPLIT,$0 | 
|  | XOR	 R0, R0 // reset R0 | 
|  |  | 
|  | // set g | 
|  | MOVD	m_g0(R3), g | 
|  | BL	runtime·save_g(SB) | 
|  | MOVD	R3, g_m(g) | 
|  |  | 
|  | // Layout new m scheduler stack on os stack. | 
|  | MOVD	R1, R3 | 
|  | MOVD	R3, (g_stack+stack_hi)(g) | 
|  | SUB	$(const_threadStackSize), R3		// stack size | 
|  | MOVD	R3, (g_stack+stack_lo)(g) | 
|  | ADD	$const__StackGuard, R3 | 
|  | MOVD	R3, g_stackguard0(g) | 
|  | MOVD	R3, g_stackguard1(g) | 
|  |  | 
|  | BL	runtime·mstart(SB) | 
|  |  | 
|  | MOVD R0, R3 | 
|  | RET | 
|  |  | 
|  |  | 
|  | #define CSYSCALL()			\ | 
|  | MOVD	0(R12), R12		\ | 
|  | MOVD	R2, 40(R1)		\ | 
|  | MOVD	0(R12), R0		\ | 
|  | MOVD	8(R12), R2		\ | 
|  | MOVD	R0, CTR			\ | 
|  | BL	(CTR)			\ | 
|  | MOVD	40(R1), R2		\ | 
|  | BL runtime·reginit(SB) | 
|  |  | 
|  |  | 
|  | // Runs on OS stack, called from runtime·osyield. | 
|  | TEXT runtime·osyield1(SB),NOSPLIT,$0 | 
|  | MOVD	$libc_sched_yield(SB), R12 | 
|  | CSYSCALL() | 
|  | RET | 
|  |  | 
|  |  | 
|  | // Runs on OS stack, called from runtime·sigprocmask. | 
|  | TEXT runtime·sigprocmask1(SB),NOSPLIT,$0-24 | 
|  | MOVD	how+0(FP), R3 | 
|  | MOVD	new+8(FP), R4 | 
|  | MOVD	old+16(FP), R5 | 
|  | MOVD	$libpthread_sigthreadmask(SB), R12 | 
|  | CSYSCALL() | 
|  | RET | 
|  |  | 
|  | // Runs on OS stack, called from runtime·usleep. | 
|  | TEXT runtime·usleep1(SB),NOSPLIT,$0-4 | 
|  | MOVW	us+0(FP), R3 | 
|  | MOVD	$libc_usleep(SB), R12 | 
|  | CSYSCALL() | 
|  | RET | 
|  |  | 
|  | // Runs on OS stack, called from runtime·exit. | 
|  | TEXT runtime·exit1(SB),NOSPLIT,$0-4 | 
|  | MOVW	code+0(FP), R3 | 
|  | MOVD	$libc_exit(SB), R12 | 
|  | CSYSCALL() | 
|  | RET | 
|  |  | 
|  | // Runs on OS stack, called from runtime·write1. | 
|  | TEXT runtime·write2(SB),NOSPLIT,$0-28 | 
|  | MOVD	fd+0(FP), R3 | 
|  | MOVD	p+8(FP), R4 | 
|  | MOVW	n+16(FP), R5 | 
|  | MOVD	$libc_write(SB), R12 | 
|  | CSYSCALL() | 
|  | MOVW	R3, ret+24(FP) | 
|  | RET | 
|  |  | 
|  | // Runs on OS stack, called from runtime·pthread_attr_init. | 
|  | TEXT runtime·pthread_attr_init1(SB),NOSPLIT,$0-12 | 
|  | MOVD	attr+0(FP), R3 | 
|  | MOVD	$libpthread_attr_init(SB), R12 | 
|  | CSYSCALL() | 
|  | MOVW	R3, ret+8(FP) | 
|  | RET | 
|  |  | 
|  | // Runs on OS stack, called from runtime·pthread_attr_setstacksize. | 
|  | TEXT runtime·pthread_attr_setstacksize1(SB),NOSPLIT,$0-20 | 
|  | MOVD	attr+0(FP), R3 | 
|  | MOVD	size+8(FP), R4 | 
|  | MOVD	$libpthread_attr_setstacksize(SB), R12 | 
|  | CSYSCALL() | 
|  | MOVW	R3, ret+16(FP) | 
|  | RET | 
|  |  | 
|  | // Runs on OS stack, called from runtime·pthread_setdetachstate. | 
|  | TEXT runtime·pthread_attr_setdetachstate1(SB),NOSPLIT,$0-20 | 
|  | MOVD	attr+0(FP), R3 | 
|  | MOVW	state+8(FP), R4 | 
|  | MOVD	$libpthread_attr_setdetachstate(SB), R12 | 
|  | CSYSCALL() | 
|  | MOVW	R3, ret+16(FP) | 
|  | RET | 
|  |  | 
|  | // Runs on OS stack, called from runtime·pthread_create. | 
|  | TEXT runtime·pthread_create1(SB),NOSPLIT,$0-36 | 
|  | MOVD	tid+0(FP), R3 | 
|  | MOVD	attr+8(FP), R4 | 
|  | MOVD	fn+16(FP), R5 | 
|  | MOVD	arg+24(FP), R6 | 
|  | MOVD	$libpthread_create(SB), R12 | 
|  | CSYSCALL() | 
|  | MOVW	R3, ret+32(FP) | 
|  | RET | 
|  |  | 
|  | // Runs on OS stack, called from runtime·sigaction. | 
|  | TEXT runtime·sigaction1(SB),NOSPLIT,$0-24 | 
|  | MOVD	sig+0(FP), R3 | 
|  | MOVD	new+8(FP), R4 | 
|  | MOVD	old+16(FP), R5 | 
|  | MOVD	$libc_sigaction(SB), R12 | 
|  | CSYSCALL() | 
|  | RET |