/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (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 (c) 1988 AT&T	*/
/*	  All Rights Reserved	*/


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

#pragma ident	"%Z%%M%	%I%	%E% SMI"

/*
 * C library -- int syscall(int sysnum, ...);
 * C library -- int __systemcall(sysret_t *, int sysnum, ...);
 *
 * Interpret a given system call
 *
 * This version handles up to 8 'long' arguments to a system call.
 *
 * Even though indirect system call support exists in the SPARC
 * 32-bit kernel, we want to eliminate it in a future release,
 * so the real trap for the desired system call is issued right here.
 *
 * Even though %g5 can be used as a scratch register for sparcv9, we don't
 * use it here because this code is shared between sparcv8 and sparcv9.
 */

	.file	"%M%"

#include <sys/asm_linkage.h>

	ANSI_PRAGMA_WEAK(syscall,function)

#include "SYS.h"

#undef _syscall		/* override "synonyms.h" */
#undef __systemcall

	ENTRY(_syscall)
	save	%sp, -SA(MINFRAME + 2*CLONGSIZE), %sp
	ldn	[%fp + STACK_BIAS + MINFRAME], %o5	! arg 5
	mov	%i3, %o2				! arg 2
	ldn	[%fp + STACK_BIAS + MINFRAME + CLONGSIZE], %g1
	mov	%i4, %o3				! arg 3
	stn	%g1, [%sp + STACK_BIAS + MINFRAME]	! arg 6
	mov	%i5, %o4				! arg 4
	ldn	[%fp + STACK_BIAS + MINFRAME + 2*CLONGSIZE], %g1
	mov	%i1, %o0				! arg 0
	stn	%g1, [%sp + STACK_BIAS + MINFRAME + CLONGSIZE] ! arg 7
	mov	%i2, %o1				! arg 1
	mov	%i0, %g1				! sysnum
	ta	SYSCALL_TRAPNUM
	bcc,a,pt %icc, 1f
	  sra	%o0, 0, %i0				! (int) cast
	restore	%o0, 0, %o0
	ba	__cerror
	  nop
1:
	ret
	  restore
	SET_SIZE(_syscall)

/*
 * Same as _syscall(), but restricted to 6 syscall arguments
 * so it doesn't need to incur the overhead of a register window.
 * Implemented for use only within libc; symbol is not exported.
 */
	ENTRY(_syscall6)
	mov	%o0, %g1			/* sysnum */
	mov	%o1, %o0			/* syscall args */
	mov	%o2, %o1
	mov	%o3, %o2
	mov	%o4, %o3
	mov	%o5, %o4
	ldn	[%sp + STACK_BIAS + MINFRAME], %o5
	ta	SYSCALL_TRAPNUM
	SYSCERROR
	retl
	  sra	%o0, 0, %o0			/* (int) cast */
	SET_SIZE(_syscall6)

	ENTRY(__systemcall)
	save	%sp, -SA(MINFRAME + 2*CLONGSIZE), %sp
	ldn	[%fp + STACK_BIAS + MINFRAME], %o4	! arg 4
	mov	%i3, %o1				! arg 1
	ldn	[%fp + STACK_BIAS + MINFRAME + CLONGSIZE], %o5 ! arg5
	mov	%i4, %o2				! arg 2
	ldn	[%fp + STACK_BIAS + MINFRAME + 2*CLONGSIZE], %g1
	mov	%i5, %o3				! arg 3
	stn	%g1, [%sp + STACK_BIAS + MINFRAME]	! arg 6
	mov	%i2, %o0				! arg 0
	ldn	[%fp + STACK_BIAS + MINFRAME + 3*CLONGSIZE], %g1
	stn	%g1, [%sp + STACK_BIAS + MINFRAME + CLONGSIZE] ! arg7
	mov	%i1, %g1				! sysnum
	ta	SYSCALL_TRAPNUM
	bcc,pt	%icc, 1f
	  mov	-1, %g1
	stn	%g1, [%i0]	/* error */
	ba	2f
	  stn	%g1, [%i0 + CLONGSIZE]
1:
	stn	%o0, [%i0]	/* no error */
	clr	%o0
	stn	%o1, [%i0 + CLONGSIZE]
2:
	ret
	  restore %o0, 0, %o0
	SET_SIZE(__systemcall)

/*
 * Same as __systemcall(), but restricted to 6 syscall arguments
 * so it doesn't need to incur the overhead of a register window.
 * Implemented for use only within libc; symbol is not exported.
 */
	ENTRY(__systemcall6)
	stn	%o0, [%sp + SAVE_OFFSET]	/* sysret address */
	mov	%o1, %g1			/* sysnum */
	mov	%o2, %o0			/* syscall args */
	mov	%o3, %o1
	mov	%o4, %o2
	mov	%o5, %o3
	ldn	[%sp + STACK_BIAS + MINFRAME], %o4
	ldn	[%sp + STACK_BIAS + MINFRAME + CLONGSIZE], %o5
	ta	SYSCALL_TRAPNUM
	bcs,pn	%icc, 1f
	  ldn	[%sp + SAVE_OFFSET], %g1
	stn	%o0, [%g1]	/* no error */
	stn	%o1, [%g1 + CLONGSIZE]
	retl
	  clr	%o0
1:
	mov	-1, %o1		/* error */
	stn	%o1, [%g1]
	retl
	  stn	%o1, [%g1 + CLONGSIZE]
	SET_SIZE(__systemcall6)
