diff options
Diffstat (limited to 'src/runtime/sys_solaris_amd64.s')
-rw-r--r-- | src/runtime/sys_solaris_amd64.s | 320 |
1 files changed, 320 insertions, 0 deletions
diff --git a/src/runtime/sys_solaris_amd64.s b/src/runtime/sys_solaris_amd64.s new file mode 100644 index 0000000..05fd187 --- /dev/null +++ b/src/runtime/sys_solaris_amd64.s @@ -0,0 +1,320 @@ +// 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 "go_asm.h" +#include "go_tls.h" +#include "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. +// NOT USING GO CALLING CONVENTION. +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 g(CX), BX + MOVQ g_m(BX), BX + MOVQ AX, (m_mOS+mOS_perrno)(BX) + RET + +// pipe(3c) wrapper that returns fds in AX, DX. +// NOT USING GO CALLING CONVENTION. +TEXT runtime·pipe1(SB),NOSPLIT,$0 + SUBQ $16, SP // 8 bytes will do, but stack has to be 16-byte aligned + MOVQ SP, DI + LEAQ 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. +// NOT USING GO CALLING CONVENTION. +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 g(CX), BX + CMPQ BX, $0 + JEQ skiperrno1 + MOVQ g_m(BX), BX + MOVQ (m_mOS+mOS_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 g(CX), BX + CMPQ BX, $0 + JEQ skiperrno2 + MOVQ g_m(BX), BX + MOVQ (m_mOS+mOS_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, g_m(DX) + + // Layout new m scheduler stack on os stack. + MOVQ SP, AX + MOVQ AX, (g_stack+stack_hi)(DX) + SUBQ $(0x100000), AX // stack size + MOVQ AX, (g_stack+stack_lo)(DX) + ADDQ $const__StackGuard, AX + MOVQ AX, g_stackguard0(DX) + MOVQ AX, g_stackguard1(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 + MOVL AX, ret+8(FP) + 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 g exists + MOVQ g(BX), R10 + CMPQ R10, $0 + JNE allgood + MOVQ SI, 80(SP) + MOVQ DX, 88(SP) + LEAQ 80(SP), AX + MOVQ DI, 0(SP) + MOVQ AX, 8(SP) + MOVQ $runtime·badsignal(SB), AX + CALL AX + JMP exit + +allgood: + // 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 + MOVQ g_m(R10), BP + 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_mOS+mOS_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_mOS+mOS_perrno)(BP), R10 + MOVL 0(R10), R10 + MOVQ R10, 160(SP) + + // prepare call + MOVQ DI, 0(SP) + MOVQ SI, 8(SP) + MOVQ DX, 16(SP) + CALL runtime·sigtrampgo(SB) + + get_tls(BX) + MOVQ g(BX), BP + MOVQ g_m(BP), 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_mOS+mOS_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_mOS+mOS_perrno)(BP), R11 + MOVQ 160(SP), R10 + MOVL R10, 0(R11) + +exit: + // 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 + +TEXT runtime·sigfwd(SB),NOSPLIT,$0-32 + MOVQ fn+0(FP), AX + MOVL sig+8(FP), DI + MOVQ info+16(FP), SI + MOVQ ctx+24(FP), DX + PUSHQ BP + MOVQ SP, BP + ANDQ $~15, SP // alignment for x86_64 ABI + CALL AX + MOVQ BP, SP + POPQ BP + RET + +// Called from runtime·usleep (Go). Can be called on Go stack, on OS stack, +// can also be called in cgo callback path without a g->m. +TEXT runtime·usleep1(SB),NOSPLIT,$0 + MOVL usec+0(FP), DI + MOVQ $usleep2<>(SB), AX // to hide from 6l + + // Execute call on m->g0. + get_tls(R15) + CMPQ R15, $0 + JE noswitch + + MOVQ g(R15), R13 + CMPQ R13, $0 + JE noswitch + MOVQ g_m(R13), R13 + CMPQ R13, $0 + JE noswitch + // TODO(aram): do something about the cpu profiler here. + + MOVQ m_g0(R13), R14 + CMPQ g(R15), R14 + JNE switch + // executing on m->g0 already + CALL AX + RET + +switch: + // Switch to m->g0 stack and back. + MOVQ (g_sched+gobuf_sp)(R14), R14 + MOVQ SP, -8(R14) + LEAQ -8(R14), SP + CALL AX + MOVQ 0(SP), SP + RET + +noswitch: + // Not a Go-managed thread. Do not switch stack. + CALL AX + RET + +// Runs on OS stack. duration (in µs units) is in DI. +TEXT usleep2<>(SB),NOSPLIT,$0 + LEAQ libc_usleep(SB), AX + CALL AX + RET + +// Runs on OS stack, called from runtime·osyield. +TEXT runtime·osyield1(SB),NOSPLIT,$0 + LEAQ libc_sched_yield(SB), AX + CALL AX + RET |