// Copyright 2013 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 AMD64, SunOS // /usr/include/sys/syscall.h for syscall numbers. // #include "zasm_GOOS_GOARCH.h" #include "../../cmd/ld/textflag.h" // This is needed by asm_amd64.s TEXT runtime·settls(SB),NOSPLIT,$8 RET // void libc·miniterrno(void *(*___errno)(void)); // // Set the TLS errno pointer in M. // // Called using runtime·asmcgocall from os_solaris.c:/minit. TEXT runtime·miniterrno(SB),NOSPLIT,$0 // asmcgocall will put first argument into DI. CALL DI // SysV ABI so returns in AX get_tls(CX) MOVQ m(CX), BX MOVQ AX, m_perrno(BX) RET // int64 runtime·nanotime1(void); // // clock_gettime(3c) wrapper because Timespec is too large for // runtime·nanotime stack. // // Called using runtime·sysvicall6 from os_solaris.c:/nanotime. TEXT runtime·nanotime1(SB),NOSPLIT,$0 // need space for the timespec argument. SUBQ $64, SP // 16 bytes will do, but who knows in the future? MOVQ $3, DI // CLOCK_REALTIME from MOVQ SP, SI MOVQ libc·clock_gettime(SB), AX CALL AX MOVQ (SP), AX // tv_sec from struct timespec IMULQ $1000000000, AX // multiply into nanoseconds ADDQ 8(SP), AX // tv_nsec, offset should be stable. ADDQ $64, SP RET // pipe(3c) wrapper that returns fds in AX, DX. TEXT runtime·pipe1(SB),NOSPLIT,$0 SUBQ $16, SP // 8 bytes will do, but stack has to be 16-byte alligned MOVQ SP, DI MOVQ libc·pipe(SB), AX CALL AX MOVL 0(SP), AX MOVL 4(SP), DX ADDQ $16, SP RET // Call a library function with SysV calling conventions. // The called function can take a maximum of 6 INTEGER class arguments, // see // Michael Matz, Jan Hubicka, Andreas Jaeger, and Mark Mitchell // System V Application Binary Interface // AMD64 Architecture Processor Supplement // section 3.2.3. // // Called by runtime·asmcgocall or runtime·cgocall. TEXT runtime·asmsysvicall6(SB),NOSPLIT,$0 // asmcgocall will put first argument into DI. PUSHQ DI // save for later MOVQ libcall_fn(DI), AX MOVQ libcall_args(DI), R11 MOVQ libcall_n(DI), R10 get_tls(CX) MOVQ m(CX), BX MOVQ m_perrno(BX), DX CMPQ DX, $0 JEQ skiperrno1 MOVL $0, 0(DX) skiperrno1: CMPQ R11, $0 JEQ skipargs // Load 6 args into correspondent registers. MOVQ 0(R11), DI MOVQ 8(R11), SI MOVQ 16(R11), DX MOVQ 24(R11), CX MOVQ 32(R11), R8 MOVQ 40(R11), R9 skipargs: // Call SysV function CALL AX // Return result POPQ DI MOVQ AX, libcall_r1(DI) MOVQ DX, libcall_r2(DI) get_tls(CX) MOVQ m(CX), BX MOVQ m_perrno(BX), AX CMPQ AX, $0 JEQ skiperrno2 MOVL 0(AX), AX MOVQ AX, libcall_err(DI) skiperrno2: RET // uint32 tstart_sysvicall(M *newm); TEXT runtime·tstart_sysvicall(SB),NOSPLIT,$0 // DI contains first arg newm MOVQ m_g0(DI), DX // g // Make TLS entries point at g and m. get_tls(BX) MOVQ DX, g(BX) MOVQ DI, m(BX) // Layout new m scheduler stack on os stack. MOVQ SP, AX MOVQ AX, g_stackbase(DX) SUBQ $(0x100000), AX // stack size MOVQ AX, g_stackguard(DX) MOVQ AX, g_stackguard0(DX) // Someday the convention will be D is always cleared. CLD CALL runtime·stackcheck(SB) // clobbers AX,CX CALL runtime·mstart(SB) XORL AX, AX // return 0 == success RET // Careful, this is called by __sighndlr, a libc function. We must preserve // registers as per AMD 64 ABI. TEXT runtime·sigtramp(SB),NOSPLIT,$0 // 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: SUBQ $184, SP // save registers MOVQ BX, 32(SP) MOVQ BP, 40(SP) MOVQ R12, 48(SP) MOVQ R13, 56(SP) MOVQ R14, 64(SP) MOVQ R15, 72(SP) get_tls(BX) // check that m exists MOVQ m(BX), BP CMPQ BP, $0 JNE allgood MOVQ DI, 0(SP) MOVQ $runtime·badsignal(SB), AX CALL AX RET allgood: // save g MOVQ g(BX), R10 MOVQ R10, 80(SP) // Save m->libcall and m->scratch. We need to do this because we // might get interrupted by a signal in runtime·asmcgocall. // save m->libcall LEAQ m_libcall(BP), R11 MOVQ libcall_fn(R11), R10 MOVQ R10, 88(SP) MOVQ libcall_args(R11), R10 MOVQ R10, 96(SP) MOVQ libcall_n(R11), R10 MOVQ R10, 104(SP) MOVQ libcall_r1(R11), R10 MOVQ R10, 168(SP) MOVQ libcall_r2(R11), R10 MOVQ R10, 176(SP) // save m->scratch LEAQ m_scratch(BP), R11 MOVQ 0(R11), R10 MOVQ R10, 112(SP) MOVQ 8(R11), R10 MOVQ R10, 120(SP) MOVQ 16(R11), R10 MOVQ R10, 128(SP) MOVQ 24(R11), R10 MOVQ R10, 136(SP) MOVQ 32(R11), R10 MOVQ R10, 144(SP) MOVQ 40(R11), R10 MOVQ R10, 152(SP) // save errno, it might be EINTR; stuff we do here might reset it. MOVQ m_perrno(BP), R10 MOVL 0(R10), R10 MOVQ R10, 160(SP) MOVQ g(BX), R10 // g = m->gsignal MOVQ m_gsignal(BP), BP MOVQ BP, g(BX) // prepare call MOVQ DI, 0(SP) MOVQ SI, 8(SP) MOVQ DX, 16(SP) MOVQ R10, 24(SP) CALL runtime·sighandler(SB) get_tls(BX) MOVQ m(BX), BP // restore libcall LEAQ m_libcall(BP), R11 MOVQ 88(SP), R10 MOVQ R10, libcall_fn(R11) MOVQ 96(SP), R10 MOVQ R10, libcall_args(R11) MOVQ 104(SP), R10 MOVQ R10, libcall_n(R11) MOVQ 168(SP), R10 MOVQ R10, libcall_r1(R11) MOVQ 176(SP), R10 MOVQ R10, libcall_r2(R11) // restore scratch LEAQ m_scratch(BP), R11 MOVQ 112(SP), R10 MOVQ R10, 0(R11) MOVQ 120(SP), R10 MOVQ R10, 8(R11) MOVQ 128(SP), R10 MOVQ R10, 16(R11) MOVQ 136(SP), R10 MOVQ R10, 24(R11) MOVQ 144(SP), R10 MOVQ R10, 32(R11) MOVQ 152(SP), R10 MOVQ R10, 40(R11) // restore errno MOVQ m_perrno(BP), R11 MOVQ 160(SP), R10 MOVL R10, 0(R11) // restore g MOVQ 80(SP), R10 MOVQ R10, g(BX) // restore registers MOVQ 32(SP), BX MOVQ 40(SP), BP MOVQ 48(SP), R12 MOVQ 56(SP), R13 MOVQ 64(SP), R14 MOVQ 72(SP), R15 ADDQ $184, SP RET