root/src/pkg/runtime/sys_solaris_amd64.s

/* [<][>][^][v][top][bottom][index][help] */
// Copyright 2014 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 <sys/time_impl.h>
        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

/* [<][>][^][v][top][bottom][index][help] */