diff options
Diffstat (limited to 'src/runtime/sys_aix_ppc64.s')
-rw-r--r-- | src/runtime/sys_aix_ppc64.s | 318 |
1 files changed, 318 insertions, 0 deletions
diff --git a/src/runtime/sys_aix_ppc64.s b/src/runtime/sys_aix_ppc64.s new file mode 100644 index 0000000..ab18c5e --- /dev/null +++ b/src/runtime/sys_aix_ppc64.s @@ -0,0 +1,318 @@ +// 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. + +// +// 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 structure +// 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. It must +// follow AIX convention, thus the first local variable must +// be stored at the offset 112, after the linker area (48 bytes) +// and the argument area (64). +// The AIX convention is described here: +// https://www.ibm.com/docs/en/aix/7.2?topic=overview-runtime-process-stack +// 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 + // Save libcall for later + MOVD R3, 112(R1) + 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 112(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|TOPFRAME,$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 |