| // 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 |