root/usr/src/lib/libc/amd64/sys/syscall.S
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */

/*
 * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

        .file   "syscall.s"

#include "SYS.h"

        ANSI_PRAGMA_WEAK(syscall,function)

        ENTRY(syscall)
        pushq   %rbp
        movq    %rsp, %rbp
        /* construct a new call stack frame */
        movl    %edi, %eax      /* sysnum */
        movq    %rsi, %rdi      /* arg0 */
        movq    %rdx, %rsi      /* arg1 */
        movq    %rcx, %rdx      /* arg2 */
        movq    %r8, %rcx       /* arg3 */
        movq    %r9, %r8        /* arg4 */
        movq    16(%rbp), %r9   /* arg5 */
        movq    32(%rbp), %r10
        pushq   %r10            /* arg7 */
        movq    24(%rbp), %r10
        pushq   %r10            /* arg6 */
        movq    8(%rbp), %r10
        pushq   %r10            /* return addr */
        /* issue the system call */
        movq    %rcx, %r10
        syscall
        /* restore the stack frame */
        leave
        SYSCERROR
        ret
        SET_SIZE(syscall)

/*
 * Same as _syscall(), but restricted to 6 syscall arguments
 * so it doesn't need to incur the overhead of a new call stack frame.
 * Implemented for use only within libc; symbol is not exported.
 */
        ENTRY(_syscall6)
        movl    %edi, %eax      /* sysnum */
        movq    %rsi, %rdi      /* arg0 */
        movq    %rdx, %rsi      /* arg1 */
        movq    %rcx, %rdx      /* arg2 */
        movq    %r8, %rcx       /* arg3 */
        movq    %r9, %r8        /* arg4 */
        movq    8(%rsp), %r9    /* arg5 */
        movq    %rcx, %r10
        syscall
        SYSCERROR
        ret
        SET_SIZE(_syscall6)

        ENTRY(__systemcall)
        pushq   %rbp
        movq    %rsp, %rbp
        /* construct a new call stack frame */
        pushq   %rdi            /* sysret_t pointer */
        movl    %esi, %eax      /* sysnum */
        movq    %rdx, %rdi      /* arg0 */
        movq    %rcx, %rsi      /* arg1 */
        movq    %r8, %rdx       /* arg2 */
        movq    %r9, %rcx       /* arg3 */
        movq    16(%rbp), %r8   /* arg4 */
        movq    24(%rbp), %r9   /* arg5 */
        movq    40(%rbp), %r10
        pushq   %r10            /* arg7 */
        movq    32(%rbp), %r10
        pushq   %r10            /* arg6 */
        movq    8(%rbp), %r10
        pushq   %r10            /* return addr */
        /* issue the system call */
        movq    %rcx, %r10
        syscall
        movq    -8(%rbp), %r10  /* sysret_t pointer */
        jb      1f
        movq    %rax, 0(%r10)   /* no error */
        movq    %rdx, 8(%r10)
        xorq    %rax, %rax
        /* restore the stack frame */
        leave
        ret
1:
        movq    $-1, 0(%r10)    /* error */
        movq    $-1, 8(%r10)
        /* restore the stack frame */
        leave
        ret
        SET_SIZE(__systemcall)

/*
 * Same as __systemcall(), but restricted to 6 syscall arguments
 * so it doesn't need to incur the overhead of a new call stack frame.
 * Implemented for use only within libc; symbol is not exported.
 */
        ENTRY(__systemcall6)
        pushq   %rdi            /* sysret_t pointer */
        movl    %esi, %eax      /* sysnum */
        movq    %rdx, %rdi      /* arg0 */
        movq    %rcx, %rsi      /* arg1 */
        movq    %r8, %rdx       /* arg2 */
        movq    %r9, %rcx       /* arg3 */
        movq    16(%rsp), %r8   /* arg4 */
        movq    24(%rsp), %r9   /* arg5 */
        /* issue the system call */
        movq    %rcx, %r10
        syscall
        popq    %r10            /* sysret_t pointer */
        jb      1f
        movq    %rax, 0(%r10)   /* no error */
        movq    %rdx, 8(%r10)
        xorq    %rax, %rax
        ret
1:
        movq    $-1, 0(%r10)    /* error */
        movq    $-1, 8(%r10)
        ret
        SET_SIZE(__systemcall6)