summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libc/sysdeps/linux/arm/Makefile.arch3
-rw-r--r--libc/sysdeps/linux/arm/syscall-eabi.S73
-rw-r--r--libc/sysdeps/linux/arm/syscall.c53
3 files changed, 129 insertions, 0 deletions
diff --git a/libc/sysdeps/linux/arm/Makefile.arch b/libc/sysdeps/linux/arm/Makefile.arch
index 76f617997..e7296d3d9 100644
--- a/libc/sysdeps/linux/arm/Makefile.arch
+++ b/libc/sysdeps/linux/arm/Makefile.arch
@@ -19,9 +19,12 @@ ifeq ($(CONFIG_ARM_EABI),y)
CSRC += aeabi_assert.c aeabi_atexit.c aeabi_errno_addr.c \
aeabi_localeconv.c aeabi_memclr.c aeabi_memcpy.c \
aeabi_memmove.c aeabi_memset.c find_exidx.c
+SSRC += syscall-eabi.S
ifeq ($(UCLIBC_HAS_WCHAR),y)
CSRC += aeabi_mb_cur_max.c
endif
+else
+CSRC += syscall.c
endif
ifeq ($(CONFIG_ARM_EABI),y)
diff --git a/libc/sysdeps/linux/arm/syscall-eabi.S b/libc/sysdeps/linux/arm/syscall-eabi.S
new file mode 100644
index 000000000..b9318821b
--- /dev/null
+++ b/libc/sysdeps/linux/arm/syscall-eabi.S
@@ -0,0 +1,73 @@
+/* Copyright (C) 2005 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 <sys/syscall.h>
+#include <bits/arm_asm.h>
+
+/* In the EABI syscall interface, we don't need a special syscall to
+ implement syscall(). It won't work reliably with 64-bit arguments
+ (but that is true on many modern platforms). */
+
+.text
+.global syscall
+.type syscall,%function
+.align 4
+#if defined(THUMB1_ONLY)
+.thumb_func
+syscall:
+ push {r4, r5, r6, r7}
+ mov ip, r0
+ mov r0, r1
+ mov r1, r2
+ mov r2, r3
+ add r7, sp, #(4 * 4)
+ ldmia r7!, {r3, r4, r5, r6}
+ mov r7, ip
+ swi 0x0
+ pop {r4, r5, r6, r7}
+ ldr r1, =0xfffff000
+ cmp r0, r1
+ bcs 1f
+ bx lr
+1:
+ push {r3, lr}
+ bl __syscall_error
+ POP_RET
+.pool
+#else
+syscall:
+ mov ip, sp
+ stmfd sp!, {r4, r5, r6, r7}
+ mov r7, r0
+ mov r0, r1
+ mov r1, r2
+ mov r2, r3
+ ldmfd ip, {r3, r4, r5, r6}
+ swi 0x0
+ ldmfd sp!, {r4, r5, r6, r7}
+ cmn r0, #4096
+ IT(t, cc)
+#if defined(__USE_BX__)
+ bxcc lr
+#else
+ movcc pc, lr
+#endif
+ b __syscall_error
+#endif
+
+.size syscall,.-syscall
diff --git a/libc/sysdeps/linux/arm/syscall.c b/libc/sysdeps/linux/arm/syscall.c
new file mode 100644
index 000000000..60fbcf89b
--- /dev/null
+++ b/libc/sysdeps/linux/arm/syscall.c
@@ -0,0 +1,53 @@
+/* vi: set sw=4 ts=4: */
+/* syscall for arm/uClibc
+ *
+ * Copyright (C) 2002 by Erik Andersen <andersen@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#include <features.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/syscall.h>
+
+
+long syscall(long sysnum, long a, long b, long c, long d, long e, long f)
+{
+#if !defined(__thumb__)
+ register long _r0 __asm__("r0")=(long)(sysnum);
+ register long _r6 __asm__("r6")=(long)(f);
+ register long _r5 __asm__("r5")=(long)(e);
+ register long _r4 __asm__("r4")=(long)(d);
+ register long _r3 __asm__("r3")=(long)(c);
+ register long _r2 __asm__("r2")=(long)(b);
+ register long _r1 __asm__("r1")=(long)(a);
+ __asm__ __volatile__(
+ "swi %1"
+ : "=r"(_r0)
+ : "i"(__NR_syscall), "r"(_r0), "r"(_r1),
+ "r"(_r2), "r"(_r3), "r"(_r4), "r"(_r5),
+ "r"(_r6)
+ : "memory");
+#else
+ register long _r7 __asm__("r7")=(long)(sysnum);
+ register long _r5 __asm__("r5")=(long)(f);
+ register long _r4 __asm__("r4")=(long)(e);
+ register long _r3 __asm__("r3")=(long)(d);
+ register long _r2 __asm__("r2")=(long)(c);
+ register long _r1 __asm__("r1")=(long)(b);
+ register long _r0 __asm__("r0")=(long)(a);
+ __asm__ __volatile__(
+ "swi 0"
+ : "=r"(_r0)
+ : "r"(_r0), "r"(_r1), "r"(_r2), "r"(_r3),
+ "r"(_r4), "r"(_r5), "r"(_r7)
+ : "memory");
+#endif
+ if(_r0 >=(unsigned long) -4095) {
+ long err = _r0;
+ (*__errno_location())=(-err);
+ _r0=(unsigned long) -1;
+ }
+ return (long) _r0;
+}