Blame sysdeps/unix/sysv/linux/arm/sysdep.h

Packit 6c4009
/* Copyright (C) 1992-2018 Free Software Foundation, Inc.
Packit 6c4009
   This file is part of the GNU C Library.
Packit 6c4009
   Contributed by Ulrich Drepper, <drepper@gnu.ai.mit.edu>, August 1995.
Packit 6c4009
   ARM changes by Philip Blundell, <pjb27@cam.ac.uk>, May 1997.
Packit 6c4009
Packit 6c4009
   The GNU C Library is free software; you can redistribute it and/or
Packit 6c4009
   modify it under the terms of the GNU Lesser General Public
Packit 6c4009
   License as published by the Free Software Foundation; either
Packit 6c4009
   version 2.1 of the License, or (at your option) any later version.
Packit 6c4009
Packit 6c4009
   The GNU C Library is distributed in the hope that it will be useful,
Packit 6c4009
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 6c4009
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 6c4009
   Lesser General Public License for more details.
Packit 6c4009
Packit 6c4009
   You should have received a copy of the GNU Lesser General Public
Packit 6c4009
   License along with the GNU C Library.  If not, see
Packit 6c4009
   <http://www.gnu.org/licenses/>.  */
Packit 6c4009
Packit 6c4009
#ifndef _LINUX_ARM_SYSDEP_H
Packit 6c4009
#define _LINUX_ARM_SYSDEP_H 1
Packit 6c4009
Packit 6c4009
/* There is some commonality.  */
Packit 6c4009
#include <sysdeps/unix/sysv/linux/sysdep.h>
Packit 6c4009
#include <sysdeps/unix/arm/sysdep.h>
Packit 6c4009
Packit 6c4009
/* Defines RTLD_PRIVATE_ERRNO and USE_DL_SYSINFO.  */
Packit 6c4009
#include <dl-sysdep.h>
Packit 6c4009
Packit 6c4009
#include <tls.h>
Packit 6c4009
Packit 6c4009
/* In order to get __set_errno() definition in INLINE_SYSCALL.  */
Packit 6c4009
#ifndef __ASSEMBLER__
Packit 6c4009
#include <errno.h>
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
/* For Linux we can use the system call table in the header file
Packit 6c4009
	/usr/include/asm/unistd.h
Packit 6c4009
   of the kernel.  But these symbols do not follow the SYS_* syntax
Packit 6c4009
   so we have to redefine the `SYS_ify' macro here.  */
Packit 6c4009
#undef SYS_ify
Packit 6c4009
#define SYS_ify(syscall_name)	(__NR_##syscall_name)
Packit 6c4009
Packit 6c4009
#include <bits/hwcap.h>
Packit 6c4009
Packit 6c4009
#ifdef __ASSEMBLER__
Packit 6c4009
Packit 6c4009
#ifndef ARCH_HAS_HARD_TP
Packit 6c4009
/* Internal macro calling the linux kernel kuser_get_tls helper.
Packit 6c4009
   Note that in thumb mode, a constant pool break is often out of range, so
Packit 6c4009
   we always expand the constant inline.  */
Packit 6c4009
# ifdef __thumb2__
Packit 6c4009
#  define GET_TLS_BODY			\
Packit 6c4009
	movw	r0, #0x0fe0;		\
Packit 6c4009
	movt	r0, #0xffff;		\
Packit 6c4009
	blx	r0
Packit 6c4009
# else
Packit 6c4009
#  define GET_TLS_BODY \
Packit 6c4009
	mov	r0, #0xffff0fff;	/* Point to the high page.  */	\
Packit 6c4009
	mov	lr, pc;			/* Save our return address.  */	\
Packit 6c4009
	sub	pc, r0, #31		/* Jump to the TLS entry.  */
Packit 6c4009
# endif
Packit 6c4009
Packit 6c4009
/* Helper to get the TLS base pointer.  Save LR in TMP, return in R0,
Packit 6c4009
   and no other registers clobbered.  TMP may be LR itself to indicate
Packit 6c4009
   that no save is necessary.  */
Packit 6c4009
# undef GET_TLS
Packit 6c4009
# define GET_TLS(TMP)			\
Packit 6c4009
  .ifnc TMP, lr;			\
Packit 6c4009
	mov	TMP, lr;		\
Packit 6c4009
	cfi_register (lr, TMP);		\
Packit 6c4009
	GET_TLS_BODY;			\
Packit 6c4009
	mov	lr, TMP;		\
Packit 6c4009
	cfi_restore (lr);		\
Packit 6c4009
  .else;				\
Packit 6c4009
	GET_TLS_BODY;			\
Packit 6c4009
  .endif
Packit 6c4009
#endif /* ARCH_HAS_HARD_TP */
Packit 6c4009
Packit 6c4009
/* Linux uses a negative return value to indicate syscall errors,
Packit 6c4009
   unlike most Unices, which use the condition codes' carry flag.
Packit 6c4009
Packit 6c4009
   Since version 2.1 the return value of a system call might be
Packit 6c4009
   negative even if the call succeeded.  E.g., the `lseek' system call
Packit 6c4009
   might return a large offset.  Therefore we must not anymore test
Packit 6c4009
   for < 0, but test for a real error by making sure the value in R0
Packit 6c4009
   is a real error number.  Linus said he will make sure the no syscall
Packit 6c4009
   returns a value in -1 .. -4095 as a valid result so we can safely
Packit 6c4009
   test with -4095.  */
Packit 6c4009
Packit 6c4009
#undef	PSEUDO
Packit 6c4009
#define	PSEUDO(name, syscall_name, args)		\
Packit 6c4009
	.text;						\
Packit 6c4009
  ENTRY (name);						\
Packit 6c4009
	DO_CALL (syscall_name, args);			\
Packit 6c4009
	cmn	r0, $4096;
Packit 6c4009
Packit 6c4009
#define PSEUDO_RET					\
Packit 6c4009
	it	cc;					\
Packit 6c4009
	RETINSTR(cc, lr);				\
Packit 6c4009
	b	PLTJMP(SYSCALL_ERROR)
Packit 6c4009
#undef ret
Packit 6c4009
#define ret PSEUDO_RET
Packit 6c4009
Packit 6c4009
#undef	PSEUDO_END
Packit 6c4009
#define	PSEUDO_END(name)				\
Packit 6c4009
	SYSCALL_ERROR_HANDLER;				\
Packit 6c4009
  END (name)
Packit 6c4009
Packit 6c4009
#undef	PSEUDO_NOERRNO
Packit 6c4009
#define	PSEUDO_NOERRNO(name, syscall_name, args)	\
Packit 6c4009
	.text;						\
Packit 6c4009
  ENTRY (name);						\
Packit 6c4009
	DO_CALL (syscall_name, args);
Packit 6c4009
Packit 6c4009
#define PSEUDO_RET_NOERRNO				\
Packit 6c4009
	DO_RET (lr);
Packit 6c4009
Packit 6c4009
#undef ret_NOERRNO
Packit 6c4009
#define ret_NOERRNO PSEUDO_RET_NOERRNO
Packit 6c4009
Packit 6c4009
#undef	PSEUDO_END_NOERRNO
Packit 6c4009
#define	PSEUDO_END_NOERRNO(name)			\
Packit 6c4009
  END (name)
Packit 6c4009
Packit 6c4009
/* The function has to return the error code.  */
Packit 6c4009
#undef	PSEUDO_ERRVAL
Packit 6c4009
#define	PSEUDO_ERRVAL(name, syscall_name, args)		\
Packit 6c4009
	.text;						\
Packit 6c4009
  ENTRY (name)						\
Packit 6c4009
	DO_CALL (syscall_name, args);			\
Packit 6c4009
	rsb	r0, r0, #0
Packit 6c4009
Packit 6c4009
#undef	PSEUDO_END_ERRVAL
Packit 6c4009
#define	PSEUDO_END_ERRVAL(name)				\
Packit 6c4009
  END (name)
Packit 6c4009
Packit 6c4009
#define ret_ERRVAL PSEUDO_RET_NOERRNO
Packit 6c4009
Packit 6c4009
#if !IS_IN (libc)
Packit 6c4009
# define SYSCALL_ERROR __local_syscall_error
Packit 6c4009
# if RTLD_PRIVATE_ERRNO
Packit 6c4009
#  define SYSCALL_ERROR_HANDLER					\
Packit 6c4009
__local_syscall_error:						\
Packit 6c4009
	rsb	r0, r0, #0;					\
Packit 6c4009
	LDST_PCREL(str, r0, r1, C_SYMBOL_NAME(rtld_errno));	\
Packit 6c4009
	mvn	r0, #0;						\
Packit 6c4009
	DO_RET(lr)
Packit 6c4009
# else
Packit 6c4009
#  if defined(__ARM_ARCH_4T__) && defined(__THUMB_INTERWORK__)
Packit 6c4009
#   define POP_PC \
Packit 6c4009
  pop { lr }; \
Packit 6c4009
  cfi_adjust_cfa_offset (-4); \
Packit 6c4009
  cfi_restore (lr); \
Packit 6c4009
  bx lr
Packit 6c4009
#  else
Packit 6c4009
#   define POP_PC  pop { pc }
Packit 6c4009
#  endif
Packit 6c4009
#  define SYSCALL_ERROR_HANDLER					\
Packit 6c4009
__local_syscall_error:						\
Packit 6c4009
	push	{ lr };						\
Packit 6c4009
	cfi_adjust_cfa_offset (4);				\
Packit 6c4009
	cfi_rel_offset (lr, 0);					\
Packit 6c4009
	push	{ r0 };	    					\
Packit 6c4009
	cfi_adjust_cfa_offset (4);				\
Packit 6c4009
	bl	PLTJMP(C_SYMBOL_NAME(__errno_location)); 	\
Packit 6c4009
	pop	{ r1 };						\
Packit 6c4009
	cfi_adjust_cfa_offset (-4);				\
Packit 6c4009
	rsb	r1, r1, #0;					\
Packit 6c4009
	str	r1, [r0];					\
Packit 6c4009
	mvn	r0, #0;						\
Packit 6c4009
	POP_PC;
Packit 6c4009
# endif
Packit 6c4009
#else
Packit 6c4009
# define SYSCALL_ERROR_HANDLER	/* Nothing here; code in sysdep.S is used.  */
Packit 6c4009
# define SYSCALL_ERROR __syscall_error
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
/* The ARM EABI user interface passes the syscall number in r7, instead
Packit 6c4009
   of in the swi.  This is more efficient, because the kernel does not need
Packit 6c4009
   to fetch the swi from memory to find out the number; which can be painful
Packit 6c4009
   with separate I-cache and D-cache.  Make sure to use 0 for the SWI
Packit 6c4009
   argument; otherwise the (optional) compatibility code for APCS binaries
Packit 6c4009
   may be invoked.  */
Packit 6c4009
Packit 6c4009
/* Linux takes system call args in registers:
Packit 6c4009
	arg 1		r0
Packit 6c4009
	arg 2		r1
Packit 6c4009
	arg 3		r2
Packit 6c4009
	arg 4		r3
Packit 6c4009
	arg 5		r4	(this is different from the APCS convention)
Packit 6c4009
	arg 6		r5
Packit 6c4009
	arg 7		r6
Packit 6c4009
Packit 6c4009
   The compiler is going to form a call by coming here, through PSEUDO, with
Packit 6c4009
   arguments
Packit 6c4009
	syscall number	in the DO_CALL macro
Packit 6c4009
	arg 1		r0
Packit 6c4009
	arg 2		r1
Packit 6c4009
	arg 3		r2
Packit 6c4009
	arg 4		r3
Packit 6c4009
	arg 5		[sp]
Packit 6c4009
	arg 6		[sp+4]
Packit 6c4009
	arg 7		[sp+8]
Packit 6c4009
Packit 6c4009
   We need to shuffle values between R4..R6 and the stack so that the
Packit 6c4009
   caller's v1..v3 and stack frame are not corrupted, and the kernel
Packit 6c4009
   sees the right arguments.
Packit 6c4009
Packit 6c4009
*/
Packit 6c4009
Packit 6c4009
/* We must save and restore r7 (call-saved) for the syscall number.
Packit 6c4009
   We never make function calls from inside here (only potentially
Packit 6c4009
   signal handlers), so we do not bother with doubleword alignment.
Packit 6c4009
Packit 6c4009
   Just like the APCS syscall convention, the EABI syscall convention uses
Packit 6c4009
   r0 through r6 for up to seven syscall arguments.  None are ever passed to
Packit 6c4009
   the kernel on the stack, although incoming arguments are on the stack for
Packit 6c4009
   syscalls with five or more arguments.
Packit 6c4009
Packit 6c4009
   The assembler will convert the literal pool load to a move for most
Packit 6c4009
   syscalls.  */
Packit 6c4009
Packit 6c4009
#undef	DO_CALL
Packit 6c4009
#define DO_CALL(syscall_name, args)			\
Packit 6c4009
	DOARGS_##args;					\
Packit 6c4009
	ldr	r7, =SYS_ify (syscall_name);		\
Packit 6c4009
	swi	0x0;					\
Packit 6c4009
	UNDOARGS_##args
Packit 6c4009
Packit 6c4009
#undef  DOARGS_0
Packit 6c4009
#define DOARGS_0					\
Packit 6c4009
	.fnstart;					\
Packit 6c4009
	push	{ r7 };					\
Packit 6c4009
	cfi_adjust_cfa_offset (4);			\
Packit 6c4009
	cfi_rel_offset (r7, 0);				\
Packit 6c4009
	.save	{ r7 }
Packit 6c4009
#undef  DOARGS_1
Packit 6c4009
#define DOARGS_1 DOARGS_0
Packit 6c4009
#undef  DOARGS_2
Packit 6c4009
#define DOARGS_2 DOARGS_0
Packit 6c4009
#undef  DOARGS_3
Packit 6c4009
#define DOARGS_3 DOARGS_0
Packit 6c4009
#undef  DOARGS_4
Packit 6c4009
#define DOARGS_4 DOARGS_0
Packit 6c4009
#undef  DOARGS_5
Packit 6c4009
#define DOARGS_5					\
Packit 6c4009
	.fnstart;					\
Packit 6c4009
	push	{r4, r7};				\
Packit 6c4009
	cfi_adjust_cfa_offset (8);			\
Packit 6c4009
	cfi_rel_offset (r4, 0);				\
Packit 6c4009
	cfi_rel_offset (r7, 4);				\
Packit 6c4009
	.save	{ r4, r7 };				\
Packit 6c4009
	ldr	r4, [sp, #8]
Packit 6c4009
#undef  DOARGS_6
Packit 6c4009
#define DOARGS_6					\
Packit 6c4009
	.fnstart;					\
Packit 6c4009
	mov	ip, sp;					\
Packit 6c4009
	push	{r4, r5, r7};				\
Packit 6c4009
	cfi_adjust_cfa_offset (12);			\
Packit 6c4009
	cfi_rel_offset (r4, 0);				\
Packit 6c4009
	cfi_rel_offset (r5, 4);				\
Packit 6c4009
	cfi_rel_offset (r7, 8);				\
Packit 6c4009
	.save	{ r4, r5, r7 };				\
Packit 6c4009
	ldmia	ip, {r4, r5}
Packit 6c4009
#undef  DOARGS_7
Packit 6c4009
#define DOARGS_7					\
Packit 6c4009
	.fnstart;					\
Packit 6c4009
	mov	ip, sp;					\
Packit 6c4009
	push	{r4, r5, r6, r7};			\
Packit 6c4009
	cfi_adjust_cfa_offset (16);			\
Packit 6c4009
	cfi_rel_offset (r4, 0);				\
Packit 6c4009
	cfi_rel_offset (r5, 4);				\
Packit 6c4009
	cfi_rel_offset (r6, 8);				\
Packit 6c4009
	cfi_rel_offset (r7, 12);			\
Packit 6c4009
	.save	{ r4, r5, r6, r7 };			\
Packit 6c4009
	ldmia	ip, {r4, r5, r6}
Packit 6c4009
Packit 6c4009
#undef  UNDOARGS_0
Packit 6c4009
#define UNDOARGS_0					\
Packit 6c4009
	pop	{r7};					\
Packit 6c4009
	cfi_adjust_cfa_offset (-4);			\
Packit 6c4009
	cfi_restore (r7);				\
Packit 6c4009
	.fnend
Packit 6c4009
#undef  UNDOARGS_1
Packit 6c4009
#define UNDOARGS_1 UNDOARGS_0
Packit 6c4009
#undef  UNDOARGS_2
Packit 6c4009
#define UNDOARGS_2 UNDOARGS_0
Packit 6c4009
#undef  UNDOARGS_3
Packit 6c4009
#define UNDOARGS_3 UNDOARGS_0
Packit 6c4009
#undef  UNDOARGS_4
Packit 6c4009
#define UNDOARGS_4 UNDOARGS_0
Packit 6c4009
#undef  UNDOARGS_5
Packit 6c4009
#define UNDOARGS_5					\
Packit 6c4009
	pop	{r4, r7};				\
Packit 6c4009
	cfi_adjust_cfa_offset (-8);			\
Packit 6c4009
	cfi_restore (r4);				\
Packit 6c4009
	cfi_restore (r7);				\
Packit 6c4009
	.fnend
Packit 6c4009
#undef  UNDOARGS_6
Packit 6c4009
#define UNDOARGS_6					\
Packit 6c4009
	pop	{r4, r5, r7};				\
Packit 6c4009
	cfi_adjust_cfa_offset (-12);			\
Packit 6c4009
	cfi_restore (r4);				\
Packit 6c4009
	cfi_restore (r5);				\
Packit 6c4009
	cfi_restore (r7);				\
Packit 6c4009
	.fnend
Packit 6c4009
#undef  UNDOARGS_7
Packit 6c4009
#define UNDOARGS_7					\
Packit 6c4009
	pop	{r4, r5, r6, r7};			\
Packit 6c4009
	cfi_adjust_cfa_offset (-16);			\
Packit 6c4009
	cfi_restore (r4);				\
Packit 6c4009
	cfi_restore (r5);				\
Packit 6c4009
	cfi_restore (r6);				\
Packit 6c4009
	cfi_restore (r7);				\
Packit 6c4009
	.fnend
Packit 6c4009
Packit 6c4009
#else /* not __ASSEMBLER__ */
Packit 6c4009
Packit 6c4009
/* Define a macro which expands into the inline wrapper code for a system
Packit 6c4009
   call.  */
Packit 6c4009
#undef INLINE_SYSCALL
Packit 6c4009
#define INLINE_SYSCALL(name, nr, args...)				\
Packit 6c4009
  ({ unsigned int _sys_result = INTERNAL_SYSCALL (name, , nr, args);	\
Packit 6c4009
     if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (_sys_result, ), 0))	\
Packit 6c4009
       {								\
Packit 6c4009
	 __set_errno (INTERNAL_SYSCALL_ERRNO (_sys_result, ));		\
Packit 6c4009
	 _sys_result = (unsigned int) -1;				\
Packit 6c4009
       }								\
Packit 6c4009
     (int) _sys_result; })
Packit 6c4009
Packit 6c4009
#undef INTERNAL_SYSCALL_DECL
Packit 6c4009
#define INTERNAL_SYSCALL_DECL(err) do { } while (0)
Packit 6c4009
Packit 6c4009
#if defined(__thumb__)
Packit 6c4009
/* We can not expose the use of r7 to the compiler.  GCC (as
Packit 6c4009
   of 4.5) uses r7 as the hard frame pointer for Thumb - although
Packit 6c4009
   for Thumb-2 it isn't obviously a better choice than r11.
Packit 6c4009
   And GCC does not support asms that conflict with the frame
Packit 6c4009
   pointer.
Packit 6c4009
Packit 6c4009
   This would be easier if syscall numbers never exceeded 255,
Packit 6c4009
   but they do.  For the moment the LOAD_ARGS_7 is sacrificed.
Packit 6c4009
   We can't use push/pop inside the asm because that breaks
Packit 6c4009
   unwinding (i.e. thread cancellation) for this frame.  We can't
Packit 6c4009
   locally save and restore r7, because we do not know if this
Packit 6c4009
   function uses r7 or if it is our caller's r7; if it is our caller's,
Packit 6c4009
   then unwinding will fail higher up the stack.  So we move the
Packit 6c4009
   syscall out of line and provide its own unwind information.  */
Packit 6c4009
# undef INTERNAL_SYSCALL_RAW
Packit 6c4009
# define INTERNAL_SYSCALL_RAW(name, err, nr, args...)		\
Packit 6c4009
  ({								\
Packit 6c4009
      register int _a1 asm ("a1");				\
Packit 6c4009
      int _nametmp = name;					\
Packit 6c4009
      LOAD_ARGS_##nr (args)					\
Packit 6c4009
      register int _name asm ("ip") = _nametmp;			\
Packit 6c4009
      asm volatile ("bl      __libc_do_syscall"			\
Packit 6c4009
                    : "=r" (_a1)				\
Packit 6c4009
                    : "r" (_name) ASM_ARGS_##nr			\
Packit 6c4009
                    : "memory", "lr");				\
Packit 6c4009
      _a1; })
Packit 6c4009
#else /* ARM */
Packit 6c4009
# undef INTERNAL_SYSCALL_RAW
Packit 6c4009
# define INTERNAL_SYSCALL_RAW(name, err, nr, args...)		\
Packit 6c4009
  ({								\
Packit 6c4009
       register int _a1 asm ("r0"), _nr asm ("r7");		\
Packit 6c4009
       LOAD_ARGS_##nr (args)					\
Packit 6c4009
       _nr = name;						\
Packit 6c4009
       asm volatile ("swi	0x0	@ syscall " #name	\
Packit 6c4009
		     : "=r" (_a1)				\
Packit 6c4009
		     : "r" (_nr) ASM_ARGS_##nr			\
Packit 6c4009
		     : "memory");				\
Packit 6c4009
       _a1; })
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
#undef INTERNAL_SYSCALL
Packit 6c4009
#define INTERNAL_SYSCALL(name, err, nr, args...)		\
Packit 6c4009
	INTERNAL_SYSCALL_RAW(SYS_ify(name), err, nr, args)
Packit 6c4009
Packit 6c4009
#undef INTERNAL_SYSCALL_ARM
Packit 6c4009
#define INTERNAL_SYSCALL_ARM(name, err, nr, args...)		\
Packit 6c4009
	INTERNAL_SYSCALL_RAW(__ARM_NR_##name, err, nr, args)
Packit 6c4009
Packit 6c4009
#undef INTERNAL_SYSCALL_ERROR_P
Packit 6c4009
#define INTERNAL_SYSCALL_ERROR_P(val, err) \
Packit 6c4009
  ((unsigned int) (val) >= 0xfffff001u)
Packit 6c4009
Packit 6c4009
#undef INTERNAL_SYSCALL_ERRNO
Packit 6c4009
#define INTERNAL_SYSCALL_ERRNO(val, err)	(-(val))
Packit 6c4009
Packit 6c4009
/* List of system calls which are supported as vsyscalls.  */
Packit 6c4009
#define HAVE_CLOCK_GETTIME_VSYSCALL	1
Packit 6c4009
#define HAVE_GETTIMEOFDAY_VSYSCALL	1
Packit 6c4009
Packit 6c4009
#define LOAD_ARGS_0()
Packit 6c4009
#define ASM_ARGS_0
Packit 6c4009
#define LOAD_ARGS_1(a1)				\
Packit 6c4009
  int _a1tmp = (int) (a1);			\
Packit 6c4009
  LOAD_ARGS_0 ()				\
Packit 6c4009
  _a1 = _a1tmp;
Packit 6c4009
#define ASM_ARGS_1	ASM_ARGS_0, "r" (_a1)
Packit 6c4009
#define LOAD_ARGS_2(a1, a2)			\
Packit 6c4009
  int _a2tmp = (int) (a2);			\
Packit 6c4009
  LOAD_ARGS_1 (a1)				\
Packit 6c4009
  register int _a2 asm ("a2") = _a2tmp;
Packit 6c4009
#define ASM_ARGS_2	ASM_ARGS_1, "r" (_a2)
Packit 6c4009
#define LOAD_ARGS_3(a1, a2, a3)			\
Packit 6c4009
  int _a3tmp = (int) (a3);			\
Packit 6c4009
  LOAD_ARGS_2 (a1, a2)				\
Packit 6c4009
  register int _a3 asm ("a3") = _a3tmp;
Packit 6c4009
#define ASM_ARGS_3	ASM_ARGS_2, "r" (_a3)
Packit 6c4009
#define LOAD_ARGS_4(a1, a2, a3, a4)		\
Packit 6c4009
  int _a4tmp = (int) (a4);			\
Packit 6c4009
  LOAD_ARGS_3 (a1, a2, a3)			\
Packit 6c4009
  register int _a4 asm ("a4") = _a4tmp;
Packit 6c4009
#define ASM_ARGS_4	ASM_ARGS_3, "r" (_a4)
Packit 6c4009
#define LOAD_ARGS_5(a1, a2, a3, a4, a5)		\
Packit 6c4009
  int _v1tmp = (int) (a5);			\
Packit 6c4009
  LOAD_ARGS_4 (a1, a2, a3, a4)			\
Packit 6c4009
  register int _v1 asm ("v1") = _v1tmp;
Packit 6c4009
#define ASM_ARGS_5	ASM_ARGS_4, "r" (_v1)
Packit 6c4009
#define LOAD_ARGS_6(a1, a2, a3, a4, a5, a6)	\
Packit 6c4009
  int _v2tmp = (int) (a6);			\
Packit 6c4009
  LOAD_ARGS_5 (a1, a2, a3, a4, a5)		\
Packit 6c4009
  register int _v2 asm ("v2") = _v2tmp;
Packit 6c4009
#define ASM_ARGS_6	ASM_ARGS_5, "r" (_v2)
Packit 6c4009
#ifndef __thumb__
Packit 6c4009
# define LOAD_ARGS_7(a1, a2, a3, a4, a5, a6, a7)	\
Packit 6c4009
  int _v3tmp = (int) (a7);				\
Packit 6c4009
  LOAD_ARGS_6 (a1, a2, a3, a4, a5, a6)			\
Packit 6c4009
  register int _v3 asm ("v3") = _v3tmp;
Packit 6c4009
# define ASM_ARGS_7	ASM_ARGS_6, "r" (_v3)
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
/* For EABI, non-constant syscalls are actually pretty easy...  */
Packit 6c4009
#undef INTERNAL_SYSCALL_NCS
Packit 6c4009
#define INTERNAL_SYSCALL_NCS(number, err, nr, args...)          \
Packit 6c4009
  INTERNAL_SYSCALL_RAW (number, err, nr, args)
Packit 6c4009
Packit 6c4009
#define SINGLE_THREAD_BY_GLOBAL	1
Packit 6c4009
Packit 6c4009
#endif	/* __ASSEMBLER__ */
Packit 6c4009
Packit 6c4009
#endif /* linux/arm/sysdep.h */