aboutsummaryrefslogtreecommitdiff
path: root/sysdeps/unix
diff options
context:
space:
mode:
authorRoland McGrath <roland@gnu.org>2002-09-17 23:50:03 +0000
committerRoland McGrath <roland@gnu.org>2002-09-17 23:50:03 +0000
commitcfc91acd418d2ea62a4520b42406a16ef07257c3 (patch)
treec7d291182781c1534a03528b33d417983b8d2e54 /sysdeps/unix
parent81cb0d8214c425e356c3f79b4b024caab36540b8 (diff)
downloadglibc-cfc91acd418d2ea62a4520b42406a16ef07257c3.tar
glibc-cfc91acd418d2ea62a4520b42406a16ef07257c3.tar.gz
glibc-cfc91acd418d2ea62a4520b42406a16ef07257c3.tar.bz2
glibc-cfc91acd418d2ea62a4520b42406a16ef07257c3.zip
2002-09-17 Steven Munroe <sjmunroe@us.ibm.com>
Ported to PowerPC64 running Linux. * sysdeps/powerpc/powerpc64/Dist: New file. * sysdeps/powerpc/powerpc64/Implies: New file. * sysdeps/powerpc/powerpc64/Makefile: New file. * sysdeps/powerpc/powerpc64/__longjmp.S: New file. * sysdeps/powerpc/powerpc64/atomicity.h: New file. * sysdeps/powerpc/powerpc64/backtrace.c: New file. * sysdeps/powerpc/powerpc64/bp-asm.h: New file. * sysdeps/powerpc/powerpc64/bsd-_setjmp.S: New file. * sysdeps/powerpc/powerpc64/bsd-setjmp.S: New file. * sysdeps/powerpc/powerpc64/dl-dtprocnum.h: New file. * sysdeps/powerpc/powerpc64/dl-lookupcfg.h: New file. * sysdeps/powerpc/powerpc64/dl-machine.c: New file. * sysdeps/powerpc/powerpc64/dl-machine.h: New file. * sysdeps/powerpc/powerpc64/memset.S: New file. * sysdeps/powerpc/powerpc64/ppc-mcount.S: New file. * sysdeps/powerpc/powerpc64/register-dump.h: New file. * sysdeps/powerpc/powerpc64/setjmp.S: New file. * sysdeps/powerpc/powerpc64/stpcpy.S: New file. * sysdeps/powerpc/powerpc64/strchr.S: New file. * sysdeps/powerpc/powerpc64/strcmp.S: New file. * sysdeps/powerpc/powerpc64/strcpy.S: New file. * sysdeps/powerpc/powerpc64/strlen.S: New file. * sysdeps/powerpc/powerpc64/elf/bzero.S: New file. * sysdeps/powerpc/powerpc64/elf/start.S: New file. * sysdeps/powerpc/powerpc64/fpu/s_copysign.S: New file. * sysdeps/powerpc/powerpc64/fpu/s_copysignf.S: New file. * sysdeps/unix/sysv/linux/powerpc/powerpc64/Versions: New File. * sysdeps/unix/sysv/linux/powerpc/powerpc64/brk.S: New file. * sysdeps/unix/sysv/linux/powerpc/powerpc64/clone.S: New file. * sysdeps/unix/sysv/linux/powerpc/powerpc64/glob64.c: New file. * sysdeps/unix/sysv/linux/powerpc/powerpc64/socket.S: New file. * sysdeps/unix/sysv/linux/powerpc/powerpc64/syscalls.list: New file. * sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h: New file.
Diffstat (limited to 'sysdeps/unix')
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/powerpc64/Versions18
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/powerpc64/brk.S45
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/powerpc64/clone.S101
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/powerpc64/glob64.c2
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/powerpc64/socket.S89
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/powerpc64/syscalls.list52
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h178
7 files changed, 485 insertions, 0 deletions
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/Versions b/sysdeps/unix/sysv/linux/powerpc/powerpc64/Versions
new file mode 100644
index 0000000000..0026730c17
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/Versions
@@ -0,0 +1,18 @@
+libc {
+ GLIBC_2.2 {
+ # functions used in other libraries
+ __xstat64; __fxstat64; __lxstat64;
+
+ # g*
+ glob64;
+
+ # New rlimit interface
+ getrlimit; setrlimit; getrlimit64; setrlimit64;
+
+ # r*
+ readdir64; readdir64_r;
+
+ # s*
+ scandir64;
+ }
+}
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/brk.S b/sysdeps/unix/sysv/linux/powerpc/powerpc64/brk.S
new file mode 100644
index 0000000000..d8f8bab94d
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/brk.S
@@ -0,0 +1,45 @@
+/* brk system call for Linux. PowerPC64 version.
+ Copyright (C) 1995,96,97,99, 2000, 2002 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <sysdep.h>
+#define _ERRNO_H 1
+#include <bits/errno.h>
+#include <bp-sym.h>
+#include <bp-asm.h>
+
+ .comm __curbrk,8,8
+ .section ".text"
+ENTRY (BP_SYM (__brk))
+ DISCARD_BOUNDS (r3) /* the bounds are meaningless, so toss 'em. */
+
+ stdu r1,-64(r1)
+ std r3,48(r1)
+ DO_CALL(SYS_ify(brk))
+ ld r6,48(r1)
+ ld r5,__curbrk@got(r2)
+ std r3,0(r5)
+ cmpld r6,r3
+ addi r1,r1,64
+ li r3,0
+ blelr+
+ li r3,ENOMEM
+ b JUMPTARGET(__syscall_error)
+END (BP_SYM (__brk))
+
+weak_alias (BP_SYM (__brk), BP_SYM (brk))
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/clone.S b/sysdeps/unix/sysv/linux/powerpc/powerpc64/clone.S
new file mode 100644
index 0000000000..97e27f3fbf
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/clone.S
@@ -0,0 +1,101 @@
+/* Wrapper around clone system call. PowerPC64 version.
+ Copyright (C) 1997,98,99,2000,02 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <sysdep.h>
+#define _ERRNO_H 1
+#include <bits/errno.h>
+#include <bp-sym.h>
+#include <bp-asm.h>
+
+/* This is the only really unusual system call in PPC linux, but not
+ because of any weirdness in the system call itself; because of
+ all the freaky stuff we have to do to make the call useful. */
+
+/* int [r3] clone(int (*fn)(void *arg) [r3], void *child_stack [r4],
+ int flags [r5], void *arg [r6]); */
+
+ENTRY (BP_SYM (__clone))
+ /* GKM FIXME: add bounds checks, where sensible. */
+ DISCARD_BOUNDS (r4)
+ DISCARD_BOUNDS (r6)
+
+ /* Check for child_stack == NULL || fn == NULL. */
+ cmpdi cr0,r4,0
+ ld r7,0(r3)
+ cmpdi cr1,r7,0
+ cror cr0*4+eq,cr1*4+eq,cr0*4+eq
+ beq- cr0,L(badargs)
+
+ /* Set up stack frame for parent. */
+ stdu r1,-80(r1)
+ std r29,56(r1)
+ std r30,64(r1)
+ std r31,72(r1)
+
+ /* Set up stack frame for child. */
+ clrrdi r4,r4,4
+ li r0,0
+ stdu r0,-48(r4) /* min stack frame is 48 bytes per ABI */
+
+ /* Save fn, args, stack across syscall. */
+ mr r29,r3 /* Function in r29. */
+ mr r30,r4 /* Stack pointer in r30. */
+ mr r31,r6 /* Argument in r31. */
+
+ /* 'flags' argument is first parameter to clone syscall. (The other
+ argument is the stack pointer, already in r4.) */
+ mr r3,r5
+
+ /* Do the call. */
+ DO_CALL(SYS_ify(clone))
+
+ /* Check for child process. */
+ cmpdi cr1,r3,0
+ crandc cr1*4+eq,cr1*4+eq,cr0*4+so
+ bne- cr1,L(parent) /* The '-' is to minimise the race. */
+
+ /* On at least mklinux DR3a5, clone() doesn't actually change
+ the stack pointer. I'm pretty sure this is a bug, because
+ it adds a race condition if a signal is sent to a thread
+ just after it is created (in the previous three instructions). */
+ mr r1,r30
+ /* Call procedure. */
+ ld r0,0(r29)
+ ld r2,8(r29)
+ mtctr r0
+ mr r3,r31
+ bctrl
+ /* Call _exit with result from procedure. */
+ b JUMPTARGET(_exit)
+
+L(parent):
+ /* Parent. Restore registers & return. */
+ ld r31,72(r1)
+ ld r30,64(r1)
+ ld r29,56(r1)
+ addi r1,r1,80
+ bnslr+
+ b JUMPTARGET(__syscall_error)
+
+L(badargs):
+ li r3,EINVAL
+ b JUMPTARGET(__syscall_error)
+END (BP_SYM (__clone))
+
+weak_alias (BP_SYM (__clone), BP_SYM (clone))
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/glob64.c b/sysdeps/unix/sysv/linux/powerpc/powerpc64/glob64.c
new file mode 100644
index 0000000000..4a3eee9c23
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/glob64.c
@@ -0,0 +1,2 @@
+/* glob64 is in glob.c */
+/* File glob64.c is redundent to glob.c in 64-bit. */
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/socket.S b/sysdeps/unix/sysv/linux/powerpc/powerpc64/socket.S
new file mode 100644
index 0000000000..08696c3cf3
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/socket.S
@@ -0,0 +1,89 @@
+/* Copyright (C) 1995, 1996, 1997, 1999 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#include <sysdep.h>
+#include <socketcall.h>
+
+#define P(a, b) P2(a, b)
+#define P2(a, b) a##b
+
+/* The socket-oriented system calls are handled unusally in Linux.
+ They are all gated through the single `socketcall' system call number.
+ `socketcall' takes two arguments: the first is the subcode, specifying
+ which socket function is being called; and the second is a pointer to
+ the arguments to the specific function.
+
+ The .S files for the other calls just #define socket and #include this.
+ They also #define a 'number-of-arguments' word in NARGS, which
+ defaults to 3. */
+
+#ifndef NARGS
+#ifdef socket
+#error NARGS not defined
+#endif
+#define NARGS 3
+#endif
+
+#define stackblock 48 /* offset to parm save area */
+
+#ifndef socket
+/* If this is just socket.S leave it alone! */
+#else
+#ifndef __socket
+#define __socket P(__,socket)
+#endif
+#endif
+
+ .text
+ENTRY(__socket)
+ stdu r1,-112(r1)
+#if NARGS >= 1
+ std r3,stackblock(r1)
+#endif
+#if NARGS >= 2
+ std r4,8+stackblock(r1)
+#endif
+#if NARGS >= 3
+ std r5,16+stackblock(r1)
+#endif
+#if NARGS >= 4
+ std r6,24+stackblock(r1)
+#endif
+#if NARGS >= 5
+ std r7,32+stackblock(r1)
+#endif
+#if NARGS >= 6
+ std r8,40+stackblock(r1)
+#endif
+#if NARGS >= 7
+ std r9,48+stackblock(r1)
+#endif
+#if NARGS >= 8
+ std r10,56+stackblock(r1)
+#endif
+#if NARGS >= 9
+#error too many arguments!
+#endif
+ li r3,P(SOCKOP_,socket)
+ addi r4,r1,stackblock
+ DO_CALL(SYS_ify(socketcall))
+ addi r1,r1,112
+ PSEUDO_RET
+PSEUDO_END (__socket)
+
+weak_alias (__socket, socket)
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/syscalls.list b/sysdeps/unix/sysv/linux/powerpc/powerpc64/syscalls.list
new file mode 100644
index 0000000000..fd81f0d975
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/syscalls.list
@@ -0,0 +1,52 @@
+# File name Caller Syscall name # args Strong name Weak names
+
+# System calls with wrappers.
+s_ioctl ioctl ioctl i:iiI __syscall_ioctl
+s_ipc msgget ipc i:iiiip __syscall_ipc
+s_llseek llseek _llseek i:iiipi __syscall__llseek
+s_readahead readahead readahead i:iiii __syscall_readahead
+s_chown chown chown i:sii __syscall_chown
+s_execve execve execve i:spp __syscall_execve
+rt_sigaction - rt_sigaction i:ippi __syscall_rt_sigaction
+rt_sigpending - rt_sigpending i:pi __syscall_rt_sigpending
+rt_sigprocmask - rt_sigprocmask i:ippi __syscall_rt_sigprocmask
+rt_sigqueueinfo - rt_sigqueueinfo i:iip __syscall_rt_sigqueueinfo
+rt_sigsuspend - rt_sigsuspend i:pi __syscall_rt_sigsuspend
+rt_sigtimedwait - rt_sigtimedwait i:pppi __syscall_rt_sigtimedwait
+s_fcntl fcntl fcntl i:iiF __syscall_fcntl
+s_fcntl64 fcntl64 fcntl64 i:iiF __syscall_fcntl64
+s_fstat64 fxstat64 fstat64 i:ip __syscall_fstat64
+s_ftruncate64 ftruncate64 ftruncate64 i:iii __syscall_ftruncate64
+s_getcwd getcwd getcwd i:pi __syscall_getcwd
+s_getdents getdents getdents i:ipi __syscall_getdents
+s_getdents64 getdents getdents64 i:ipi __syscall_getdents64
+s_getpmsg getpmsg getpmsg i:ipppp __syscall_getpmsg
+s_getpriority getpriority getpriority i:ii __syscall_getpriority
+getresgid - getresgid i:ppp getresgid
+getresuid - getresuid i:ppp getresuid
+s_getrlimit getrlimit getrlimit i:ip __syscall_getrlimit
+s_lstat64 lxstat64 lstat64 i:sp __syscall_lstat64
+s_mmap2 mmap64 mmap2 b:aniiii __syscall_mmap2
+s_poll poll poll i:pii __syscall_poll
+s_pread64 pread64 pread i:ibnii __syscall_pread
+s_ptrace ptrace ptrace i:iipp __syscall_ptrace
+s_putpmsg putpmsg putpmsg i:ippii __syscall_putpmsg
+s_pwrite64 pwrite64 pwrite i:ibnii __syscall_pwrite
+s_reboot reboot reboot i:iii __syscall_reboot
+s_setrlimit setrlimit setrlimit i:ip __syscall_setrlimit
+s_sigaction sigaction sigaction i:ipp __syscall_sigaction
+s_sigpending sigpending sigpending i:p __syscall_sigpending
+s_sigprocmask sigprocmask sigprocmask i:ipp __syscall_sigprocmask
+s_sigsuspend sigsuspend sigsuspend i:iii __syscall_sigsuspend
+s_stat64 xstat64 stat64 i:sp __syscall_stat64
+s_sysctl sysctl _sysctl i:p __syscall__sysctl
+s_truncate64 truncate64 truncate64 i:sii __syscall_truncate64
+s_ugetrlimit getrlimit ugetrlimit i:ip __syscall_ugetrlimit
+s_ustat ustat ustat i:ip __syscall_ustat
+s_vfork vfork vfork i: __syscall_vfork
+sys_fstat fxstat fstat i:ip __syscall_fstat
+sys_lstat lxstat lstat i:sp __syscall_lstat
+sys_mknod xmknod mknod i:pii __syscall_mknod
+sys_readv readv readv i:ipi __syscall_readv
+sys_stat xstat stat i:sp __syscall_stat
+sys_writev writev writev i:ipi __syscall_writev
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h b/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h
new file mode 100644
index 0000000000..8e43a39c10
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h
@@ -0,0 +1,178 @@
+/* Copyright (C) 1992, 1997, 1998, 1999, 2000, 2001, 2002
+ Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+/* Alan Modra <amodra@bigpond.net.au> rewrote the INLINE_SYSCALL macro */
+
+#ifndef _LINUX_POWERPC_SYSDEP_H
+#define _LINUX_POWERPC_SYSDEP_H 1
+
+#include <sysdeps/unix/powerpc/sysdep.h>
+
+/* Define __set_errno() for INLINE_SYSCALL macro below. */
+#ifndef __ASSEMBLER__
+#include <errno.h>
+#endif
+
+/* For Linux we can use the system call table in the header file
+ /usr/include/asm/unistd.h
+ of the kernel. But these symbols do not follow the SYS_* syntax
+ so we have to redefine the `SYS_ify' macro here. */
+#undef SYS_ify
+#ifdef __STDC__
+# define SYS_ify(syscall_name) __NR_##syscall_name
+#else
+# define SYS_ify(syscall_name) __NR_/**/syscall_name
+#endif
+
+#ifdef __ASSEMBLER__
+
+/* This seems to always be the case on PPC. */
+#define ALIGNARG(log2) log2
+/* For ELF we need the `.type' directive to make shared libs work right. */
+#define ASM_TYPE_DIRECTIVE(name,typearg) .type name,typearg;
+#define ASM_SIZE_DIRECTIVE(name) .size name,.-name
+
+#endif /* __ASSEMBLER__ */
+
+#undef INLINE_SYSCALL
+#if 1
+#define INLINE_SYSCALL(name, nr, args...) \
+ ({ \
+ DECLARGS_##nr; \
+ long ret, err; \
+ LOADARGS_##nr(name, args); \
+ __asm__ ("sc\n\t" \
+ "mfcr %1\n\t" \
+ : "=r" (r3), "=r" (err) \
+ : ASM_INPUT_##nr \
+ : "cc", "memory"); \
+ ret = r3; \
+ if (err & 1 << 28) \
+ { \
+ __set_errno (ret); \
+ ret = -1L; \
+ } \
+ ret; \
+ })
+
+#define DECLARGS_0 register long r0 __asm__ ("r0"); \
+ register long r3 __asm__ ("r3")
+#define DECLARGS_1 DECLARGS_0
+#define DECLARGS_2 DECLARGS_1; register long r4 __asm__ ("r4")
+#define DECLARGS_3 DECLARGS_2; register long r5 __asm__ ("r5")
+#define DECLARGS_4 DECLARGS_3; register long r6 __asm__ ("r6")
+#define DECLARGS_5 DECLARGS_4; register long r7 __asm__ ("r7")
+#define DECLARGS_6 DECLARGS_5; register long r8 __asm__ ("r8")
+
+#define LOADARGS_0(name) \
+ r0 = __NR_##name
+#define LOADARGS_1(name, arg1) \
+ LOADARGS_0(name); \
+ r3 = (long) (arg1)
+#define LOADARGS_2(name, arg1, arg2) \
+ LOADARGS_1(name, arg1); \
+ r4 = (long) (arg2)
+#define LOADARGS_3(name, arg1, arg2, arg3) \
+ LOADARGS_2(name, arg1, arg2); \
+ r5 = (long) (arg3)
+#define LOADARGS_4(name, arg1, arg2, arg3, arg4) \
+ LOADARGS_3(name, arg1, arg2, arg3); \
+ r6 = (long) (arg4)
+#define LOADARGS_5(name, arg1, arg2, arg3, arg4, arg5) \
+ LOADARGS_4(name, arg1, arg2, arg3, arg4); \
+ r7 = (long) (arg5)
+#define LOADARGS_6(name, arg1, arg2, arg3, arg4, arg5, arg6) \
+ LOADARGS_5(name, arg1, arg2, arg3, arg4, arg5); \
+ r8 = (long) (arg6)
+
+#define ASM_INPUT_0 "r" (r0)
+#define ASM_INPUT_1 ASM_INPUT_0, "0" (r3)
+#define ASM_INPUT_2 ASM_INPUT_1, "r" (r4)
+#define ASM_INPUT_3 ASM_INPUT_2, "r" (r5)
+#define ASM_INPUT_4 ASM_INPUT_3, "r" (r6)
+#define ASM_INPUT_5 ASM_INPUT_4, "r" (r7)
+#define ASM_INPUT_6 ASM_INPUT_5, "r" (r8)
+
+#else
+/* This version is for kernels that implement system calls that
+ behave like function calls as far as register saving. */
+#define INLINE_SYSCALL(name, nr, args...) \
+ ({ \
+ register long r0 __asm__ ("r0"); \
+ register long r3 __asm__ ("r3"); \
+ register long r4 __asm__ ("r4"); \
+ register long r5 __asm__ ("r5"); \
+ register long r6 __asm__ ("r6"); \
+ register long r7 __asm__ ("r7"); \
+ register long r8 __asm__ ("r8"); \
+ long ret, err; \
+ LOADARGS_##nr(name, args); \
+ __asm__ ("sc\n\t" \
+ "mfcr %7\n\t" \
+ : "=r" (r0), "=r" (r3), "=r" (r4), "=r" (r5), \
+ "=r" (r6), "=r" (r7), "=r" (r8), "=r" (err) \
+ : ASM_INPUT_##nr \
+ : "r9", "r10", "r11", "r12", \
+ "fr0", "fr1", "fr2", "fr3", \
+ "fr4", "fr5", "fr6", "fr7", \
+ "fr8", "fr9", "fr10", "fr11", \
+ "fr12", "fr13", \
+ "ctr", "lr", \
+ "cr0", "cr1", "cr5", "cr6", "cr7", "memory"); \
+ ret = r3; \
+ if (err & 1 << 28) \
+ { \
+ __set_errno (ret); \
+ ret = -1L; \
+ } \
+ ret; \
+ })
+
+#define LOADARGS_0(name) \
+ r0 = __NR_##name
+#define LOADARGS_1(name, arg1) \
+ LOADARGS_0(name); \
+ r3 = (long) (arg1)
+#define LOADARGS_2(name, arg1, arg2) \
+ LOADARGS_1(name, arg1); \
+ r4 = (long) (arg2)
+#define LOADARGS_3(name, arg1, arg2, arg3) \
+ LOADARGS_2(name, arg1, arg2); \
+ r5 = (long) (arg3)
+#define LOADARGS_4(name, arg1, arg2, arg3, arg4) \
+ LOADARGS_3(name, arg1, arg2, arg3); \
+ r6 = (long) (arg4)
+#define LOADARGS_5(name, arg1, arg2, arg3, arg4, arg5) \
+ LOADARGS_4(name, arg1, arg2, arg3, arg4); \
+ r7 = (long) (arg5)
+#define LOADARGS_6(name, arg1, arg2, arg3, arg4, arg5, arg6) \
+ LOADARGS_5(name, arg1, arg2, arg3, arg4, arg5); \
+ r8 = (long) (arg6)
+
+#define ASM_INPUT_0 "0" (r0)
+#define ASM_INPUT_1 ASM_INPUT_0, "1" (r3)
+#define ASM_INPUT_2 ASM_INPUT_1, "2" (r4)
+#define ASM_INPUT_3 ASM_INPUT_2, "3" (r5)
+#define ASM_INPUT_4 ASM_INPUT_3, "4" (r6)
+#define ASM_INPUT_5 ASM_INPUT_4, "5" (r7)
+#define ASM_INPUT_6 ASM_INPUT_5, "6" (r8)
+
+#endif
+
+#endif /* linux/powerpc/powerpc64/sysdep.h */