- fix syscall API and vfork - support 6-argument syscalls - add open/openat special handling for non-regparm arches Signed-off-by: Thorsten Glaser <tg@xxxxxxxxxx> --- usr/klibc/README.klibc | 2 +- usr/klibc/SYSCALLS.def | 4 +- usr/klibc/arch/m68k/Kbuild | 1 + usr/klibc/arch/m68k/open.S | 22 +++++++++++++++++++++ usr/klibc/arch/m68k/openat.S | 26 +++++++++++++++++++++++++ usr/klibc/arch/m68k/syscall.S | 42 +++++++++++++++++++++++++++++++++------- usr/klibc/arch/m68k/vfork.S | 13 +++-------- usr/klibc/open.c | 2 +- usr/klibc/openat.c | 2 +- 9 files changed, 92 insertions(+), 22 deletions(-) create mode 100644 usr/klibc/arch/m68k/open.S create mode 100644 usr/klibc/arch/m68k/openat.S diff --git a/usr/klibc/README.klibc b/usr/klibc/README.klibc index b4135cb..5417049 100644 --- a/usr/klibc/README.klibc +++ b/usr/klibc/README.klibc @@ -44,7 +44,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 6ed6bdf..12aef49 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 8d6137c..d56ae0e 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 0000000..c9a7ee3 --- /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 0000000..25d8a1a --- /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 966c92d..c909e2a 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 a3a7e44..98170a6 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 9b0897a..126f6db 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 83c87cd..8e5baa0 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); -- 1.7.8.3 -- To unsubscribe from this list: send the line "unsubscribe linux-m68k" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html