diff options
Diffstat (limited to 'src/pkg/runtime/sys_solaris_amd64.s')
-rw-r--r-- | src/pkg/runtime/sys_solaris_amd64.s | 267 |
1 files changed, 267 insertions, 0 deletions
diff --git a/src/pkg/runtime/sys_solaris_amd64.s b/src/pkg/runtime/sys_solaris_amd64.s new file mode 100644 index 000000000..21517693b --- /dev/null +++ b/src/pkg/runtime/sys_solaris_amd64.s @@ -0,0 +1,267 @@ +// 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 |