aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThorsten Glaser <tg@mirbsd.de>2011-01-29 17:19:10 +0000
committerH. Peter Anvin <hpa@linux.intel.com>2012-05-15 11:33:14 -0700
commit543b4b9a8a248cfad4a0b2920a87ecde6c3cd53b (patch)
tree4975e72b34f4e48f3a5163ab4ebf0634b64b1310
parent7e911e43f51feb1a0255efaea3aa3bcb79adbede (diff)
downloadklibc-543b4b9a8a248cfad4a0b2920a87ecde6c3cd53b.tar.gz
[klibc] Fix m68k support
- fix syscall API and vfork - support 6-argument syscalls - add open/openat special handling for non-regparm arches Signed-off-by: Thorsten Glaser <tg@mirbsd.org> Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
-rw-r--r--usr/klibc/README.klibc2
-rw-r--r--usr/klibc/SYSCALLS.def4
-rw-r--r--usr/klibc/arch/m68k/Kbuild1
-rw-r--r--usr/klibc/arch/m68k/open.S22
-rw-r--r--usr/klibc/arch/m68k/openat.S26
-rw-r--r--usr/klibc/arch/m68k/syscall.S42
-rw-r--r--usr/klibc/arch/m68k/vfork.S13
-rw-r--r--usr/klibc/open.c2
-rw-r--r--usr/klibc/openat.c2
9 files changed, 92 insertions, 22 deletions
diff --git a/usr/klibc/README.klibc b/usr/klibc/README.klibc
index 8b6e92314b9b1..d4e424096cdfe 100644
--- a/usr/klibc/README.klibc
+++ b/usr/klibc/README.klibc
@@ -43,7 +43,7 @@ b) If you're cross-compiling, you need to set KLIBCARCH to the
i386: Working
ia64: Working static, shared untested
m32r: Untested
- m68k: Untested
+ m68k: Working
m68knommu: Not yet ported
mips: Working
mips64: Not yet ported
diff --git a/usr/klibc/SYSCALLS.def b/usr/klibc/SYSCALLS.def
index 6ed6bdf228320..12aef49e9a580 100644
--- a/usr/klibc/SYSCALLS.def
+++ b/usr/klibc/SYSCALLS.def
@@ -154,8 +154,8 @@ int getcwd::__getcwd(char *, size_t);
/*
* I/O operations
*/
-<!i386,64> int open::__open(const char *, int, mode_t);
-<?!i386,64> int openat::__openat(int, const char *, int, mode_t);
+<!i386,m68k,64> int open::__open(const char *, int, mode_t);
+<?!i386,m68k,64> int openat::__openat(int, const char *, int, mode_t);
<64> int open(const char *, int, mode_t);
ssize_t read(int, void *, size_t);
ssize_t write(int, const void *, size_t);
diff --git a/usr/klibc/arch/m68k/Kbuild b/usr/klibc/arch/m68k/Kbuild
index 8d6137cad7fa3..d56ae0ecef96d 100644
--- a/usr/klibc/arch/m68k/Kbuild
+++ b/usr/klibc/arch/m68k/Kbuild
@@ -3,6 +3,7 @@
#
klib-y := setjmp.o syscall.o vfork.o
+klib-y += open.o openat.o
always := crt0.o
targets := crt0.o
diff --git a/usr/klibc/arch/m68k/open.S b/usr/klibc/arch/m68k/open.S
new file mode 100644
index 0000000000000..c9a7ee33942cc
--- /dev/null
+++ b/usr/klibc/arch/m68k/open.S
@@ -0,0 +1,22 @@
+/*
+ * arch/m68k/open.S
+ *
+ * Handle the open() system call - oddball due to the varadic
+ * prototype, which forces the use of the cdecl calling convention,
+ * and the need for O_LARGEFILE.
+ */
+
+#include <asm/unistd.h>
+
+/* <asm/fcntl.h>, despite the name, isn't assembly-safe */
+#define O_LARGEFILE 0400000
+
+ .globl open
+ .type open,@function
+
+open:
+ or.l # O_LARGEFILE, 8(%sp)
+ move.l # __NR_open, %d0
+ br __syscall_common
+
+ .size open,.-open
diff --git a/usr/klibc/arch/m68k/openat.S b/usr/klibc/arch/m68k/openat.S
new file mode 100644
index 0000000000000..25d8a1ace9eb7
--- /dev/null
+++ b/usr/klibc/arch/m68k/openat.S
@@ -0,0 +1,26 @@
+/*
+ * arch/m68k/openat.S
+ *
+ * Handle the openat() system call - oddball due to the varadic
+ * prototype, which forces the use of the cdecl calling convention,
+ * and the need for O_LARGEFILE.
+ */
+
+#include <asm/unistd.h>
+
+/* <asm/fcntl.h>, despite the name, isn't assembly-safe */
+#define O_LARGEFILE 0400000
+
+#ifdef __NR_openat /* Don't build if kernel headers too old */
+
+ .globl openat
+ .type openat,@function
+
+openat:
+ or.l # O_LARGEFILE, 12(%sp)
+ move.l # __NR_openat, %d0
+ br __syscall_common
+
+ .size openat,.-openat
+
+#endif
diff --git a/usr/klibc/arch/m68k/syscall.S b/usr/klibc/arch/m68k/syscall.S
index 966c92def99f9..c909e2a0a2061 100644
--- a/usr/klibc/arch/m68k/syscall.S
+++ b/usr/klibc/arch/m68k/syscall.S
@@ -11,17 +11,43 @@
.globl __syscall_common
.type __syscall_common, @function
__syscall_common:
- movem.l %d2-%d6, -(%sp) /* 5 registers saved */
- movem.l 24(%sp), %d1-%d6
+ /*
+ * According to eglibc, separate moves are faster than movem;
+ * speed is important and this code is not duplicated anyway,
+ * so we do the same here. We use %a1 as scratch register for
+ * saving; syscall arguments are to be in %d1 to %d5 and %a0.
+ */
+ move.l 24(%sp), %a0 /* orig.sp+24: arg 6 */
+ move.l %d5, -(%sp) /* push d5 (callee saved) */
+ move.l 24(%sp), %d5 /* orig.sp+20: arg 5 */
+ move.l %d4, -(%sp) /* push d4 (callee saved) */
+ move.l 24(%sp), %d4 /* orig.sp+16: arg 4 */
+ move.l %d3, -(%sp) /* push d3 (callee saved) */
+ move.l 24(%sp), %d3 /* orig.sp+12: arg 3 */
+ move.l %d2, %a1 /* save d2 (callee saved) in a1 */
+ move.l 20(%sp), %d2 /* orig.sp+8: arg 2 */
+ move.l 16(%sp), %d1 /* orig.sp+4: arg 1 */
trap #0
- cmpi.l #-4095, %d0
- blt.l 1f
+ move.l %a1, %d2 /* restore d2 from a1 (scratch) */
+ move.l (%sp)+, %d3 /* pop d3..d5, see above */
+ move.l (%sp)+, %d4
+ move.l (%sp)+, %d5
+
+ /* syscall is done, result in %d0, registers are restored */
+ .globl __syscall_checkandout
+__syscall_checkandout:
+ /* now check for error */
+ cmp.l #-4095, %d0
+ bcs.l 1f /* jump if _not_ error */
+
+ /* prepare for error return */
neg.l %d0
move.l %d0, (errno)
- moveq #-1, %d0
-1:
- movea.l %d0, %a0 /* Redundant return */
- movem.l (%sp)+, %d2-%d6 /* Restore registers */
+ move.l #-1, %d0
+ /* fallthrough into common return path */
+
+1: /* copy return value to %a0 for syscalls returning pointers */
+ move.l %d0, %a0
rts
.size __syscall_common,.-__syscall_common
diff --git a/usr/klibc/arch/m68k/vfork.S b/usr/klibc/arch/m68k/vfork.S
index a3a7e44bb09d2..98170a6c957c5 100644
--- a/usr/klibc/arch/m68k/vfork.S
+++ b/usr/klibc/arch/m68k/vfork.S
@@ -15,14 +15,9 @@ vfork:
move.l (%sp)+, %d1 /* Return address */
move.l # __NR_vfork, %d0
trap #0
- move.l %d1, -(%sp)
- cmpi.l #-4095, %d0
- blt.l 1f
- neg.l %d0
- move.l %d0, (errno)
- moveq #-1, %d0
-1:
- movea.l %d0, %a0
- rts
+ move.l %d1, -(%sp) /* restore stack */
+
+ /* fallthrough into common code from syscall.S */
+ bra __syscall_checkandout
.size vfork, .-vfork
diff --git a/usr/klibc/open.c b/usr/klibc/open.c
index 9b0897a77927a..126f6db2d9067 100644
--- a/usr/klibc/open.c
+++ b/usr/klibc/open.c
@@ -10,7 +10,7 @@
#include <fcntl.h>
#include <bitsize.h>
-#if _BITSIZE == 32 && !defined(__i386__)
+#if _BITSIZE == 32 && !defined(__i386__) && !defined(__m68k__)
extern int __open(const char *, int, mode_t);
diff --git a/usr/klibc/openat.c b/usr/klibc/openat.c
index 83c87cd49b1f4..8e5baa0c59aed 100644
--- a/usr/klibc/openat.c
+++ b/usr/klibc/openat.c
@@ -10,7 +10,7 @@
#include <fcntl.h>
#include <bitsize.h>
-#if _BITSIZE == 32 && !defined(__i386__) && defined(__NR_openat)
+#if _BITSIZE == 32 && !defined(__i386__) && !defined(__m68k__) && defined(__NR_openat)
extern int __openat(int, const char *, int, mode_t);