diff options
author | Thorsten Glaser <tg@mirbsd.de> | 2011-01-29 17:19:10 +0000 |
---|---|---|
committer | H. Peter Anvin <hpa@linux.intel.com> | 2012-05-15 11:33:14 -0700 |
commit | 543b4b9a8a248cfad4a0b2920a87ecde6c3cd53b (patch) | |
tree | 4975e72b34f4e48f3a5163ab4ebf0634b64b1310 | |
parent | 7e911e43f51feb1a0255efaea3aa3bcb79adbede (diff) | |
download | klibc-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.klibc | 2 | ||||
-rw-r--r-- | usr/klibc/SYSCALLS.def | 4 | ||||
-rw-r--r-- | usr/klibc/arch/m68k/Kbuild | 1 | ||||
-rw-r--r-- | usr/klibc/arch/m68k/open.S | 22 | ||||
-rw-r--r-- | usr/klibc/arch/m68k/openat.S | 26 | ||||
-rw-r--r-- | usr/klibc/arch/m68k/syscall.S | 42 | ||||
-rw-r--r-- | usr/klibc/arch/m68k/vfork.S | 13 | ||||
-rw-r--r-- | usr/klibc/open.c | 2 | ||||
-rw-r--r-- | usr/klibc/openat.c | 2 |
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); |