Message ID | alpine.DEB.2.00.1708192131080.17596@tp.orcam.me.uk |
---|---|
State | Superseded |
Headers | show |
On 21/08/2017 07:48, Maciej W. Rozycki wrote: > On Sat, 19 Aug 2017, Aurelien Jarno wrote: > >>>> The workaround didn't work. >>> >>> Hmm, that means there's something wrong with binutils which needs fixing. >>> Can you please send me the failing .s file and the command line used to >>> assemble it (from `gcc -v')? >> >> Please find that attached. > > Thanks. There's indeed a bug in GAS, a MIPS16 path of execution has been > missed in the handling of this option. I have a preliminary fix, however > I yet have to prepare test suite cases (originally the option was > mistakenly only covered by regular MIPS and microMIPS testing, which is > clearly why the MIPS16 case has been missed). I expect this fix to be > included in the upcoming 2.29.1 release, and also backported to 2.28 > (although no new 2.28 release is scheduled). > >>> The MIPS16 wrappers were split into individual files so that only ones >>> that are actually used by `ld.so' are pulled. I think it would be good if >>> we preserved that. I'll see if I can experiment with keeping the original >>> MIPS16 0-3 wrappers. >> >> For what I have seen, ld.so already uses syscalls with 1 to 4 arguments. >> It doesn't use any syscall without argument though. So it's only 4 >> instructions overhead. > > Why make things worse where they don't have to be and there's no benefit > elsewhere that would balance the regression? > > Here's what I had in mind. The key was updating the macros appropriately > in sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall.h. Beyond > that I made a number of clean-ups: > > 1. I renamed `__libc_do_syscall?' to `__mips_syscall?', for consistency > with `__mips16_syscall?', and consequently `__libc_do_syscall_return' > to `__mips_syscall_return'. Ok. > > 2. I exported `__mips_syscall?' wrappers from `libc.so' rather than making > them hidden. This is also consistent with `__mips16_syscall?' wrappers > and reduces code duplication of doubtful benefit -- it could be that > some calls, if internal, could be subject to the JALR->BAL > optimisation, however only those that are in range and only in regular > MIPS code, for a minimal execution time saving on some processors only. > Exporting these entries makes the maintenance effort much easier > though, as we don't have to track and record their use in the > individual subdirectories in Makefile. In this case we can still have internal hidden calls for libc with the cost of code duplication by using hiden alias with: libc_hidden_proto (__mips_syscall{5,6,7}, nomips16) And with the pairing libc_hidden_def (__mips_syscall{5,6,7}); On implementation. > > 3. I renamed `_sys_result' to `_sc_ret' where it is declared as `union > __mips_syscall_return', again for clarity and consistency with MIPS16 > INTERNAL_SYSCALL_NCS. Ok. > > 4. I wrapped `number' in parentheses in `internal_syscall5', > `internal_syscall6' and `internal_syscall7', and cast it to `long'. Ok. > > 5. I have adjusted some comments. I think it still worth to add some more explanation (see below). > > Please let me know if you have any questions or concerns about this > update. > > This passes o32 regular MIPS regression testing, however my GCC 8 binary > seems to miscompile support_test_main.c in the MIPS16 mode, causing all > the relevant test cases to crash with SIGILL (in the `support_set_test_dir > (test_dir)' invocation it's `test_dir' that is jumped to rather than > `support_set_test_dir'; I'll file a bug separately). I'll find a way to > run MIPS16 testing eventually, however meanwhile I will appreciate if you > do it for me. > > Maciej > > 2017-08-21 Adhemerval Zanella <adhemerval.zanella@linaro.org> > Aurelien Jarno <aurelien@aurel32.net> > Maciej W. Rozycki <macro@imgtec.com> > > [BZ #21956] > * sysdeps/unix/sysv/linux/mips/mips32/mips16/Makefile > [subdir = misc] (sysdep_routines): Remove `mips16-syscall5', > `mips16-syscall6' and `mips16-syscall7'. > (CFLAGS-mips16-syscall5.c, CFLAGS-mips16-syscall6.c) > (CFLAGS-mips16-syscall7.c): Remove. > * sysdeps/unix/sysv/linux/mips/mips32/mips16/Versions (libc): > Remove `__mips16_syscall5', `__mips16_syscall6' and > `__mips16_syscall7'. > * sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall0.c > (__mips16_syscall0): Rename `__mips16_syscall_return' to > `__mips_syscall_return'. > * sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall1.c > (__mips16_syscall1): Likewise. > * sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall2.c > (__mips16_syscall2): Likewise. > * sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall3.c > (__mips16_syscall3): Likewise. > * sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall4.c > (__mips16_syscall4): Likewise. > * sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall5.c: > Remove. > * sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall6.c: > Remove. > * sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall7.c: > Remove. > * sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall.h > (__mips16_syscall5): Expand to `__mips_syscall5' rather than > `__mips16_syscall5'. Remove prototype. > (__mips16_syscall6): Expand to `__mips_syscall6' rather than > `__mips16_syscall6'. Remove prototype. > (__mips16_syscall7): Expand to `__mips_syscall7' rather than > `__mips16_syscall7'. Remove prototype. > (__nomips16, __mips16_syscall_return): Move to... > * sysdeps/unix/sysv/linux/mips/mips32/sysdep.h > (__nomips16, __mips_syscall_return): ... here. > [__mips16] (INTERNAL_SYSCALL_NCS): Rename > `__mips16_syscall_return' to `__mips_syscall_return'. > [__mips16] (INTERNAL_SYSCALL_MIPS16): Pass `number' to > `internal_syscall##nr'. > [!__mips16] (INTERNAL_SYSCALL): Pass `SYS_ify (name)' to > `internal_syscall##nr'. > (FORCE_FRAME_POINTER): Remove. > (__mips_syscall5): New prototype. > (internal_syscall5): Rewrite to call `__mips_syscall5'. > (__mips_syscall6): New prototype. > (internal_syscall6): Rewrite to call `__mips_syscall6'. > (__mips_syscall7): New prototype. > (internal_syscall7): Rewrite to call `__mips_syscall7'. > * sysdeps/unix/sysv/linux/mips/mips32/mips-syscall5.S: New file. > * sysdeps/unix/sysv/linux/mips/mips32/mips-syscall6.S: New file. > * sysdeps/unix/sysv/linux/mips/mips32/mips-syscall7.S: New file. > * sysdeps/unix/sysv/linux/mips/mips32/Makefile [subdir = misc] > (sysdep_routines): Add libc-do-syscall. > * sysdeps/unix/sysv/linux/mips/mips32/Versions (libc): Add > `__mips_syscall5', `__mips_syscall6' and `__mips_syscall7'. > > --- > sysdeps/unix/sysv/linux/mips/mips32/Makefile | 4 > sysdeps/unix/sysv/linux/mips/mips32/Versions | 3 > sysdeps/unix/sysv/linux/mips/mips32/mips-syscall5.S | 33 ++ > sysdeps/unix/sysv/linux/mips/mips32/mips-syscall6.S | 33 ++ > sysdeps/unix/sysv/linux/mips/mips32/mips-syscall7.S | 33 ++ > sysdeps/unix/sysv/linux/mips/mips32/mips16/Makefile | 6 > sysdeps/unix/sysv/linux/mips/mips32/mips16/Versions | 2 > sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall.h | 44 --- > sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall0.c | 3 > sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall1.c | 3 > sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall2.c | 3 > sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall3.c | 3 > sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall4.c | 3 > sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall5.c | 33 -- > sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall6.c | 33 -- > sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall7.c | 33 -- > sysdeps/unix/sysv/linux/mips/mips32/sysdep.h | 154 ++++------- > 17 files changed, 186 insertions(+), 240 deletions(-) > > glibc-aurelien-mips-o32-syscall.diff > Index: glibc/sysdeps/unix/sysv/linux/mips/mips32/Makefile > =================================================================== > --- glibc.orig/sysdeps/unix/sysv/linux/mips/mips32/Makefile 2017-08-20 01:30:23.485088512 +0100 > +++ glibc/sysdeps/unix/sysv/linux/mips/mips32/Makefile 2017-08-20 01:34:46.716443161 +0100 > @@ -3,6 +3,10 @@ ifeq ($(subdir),conform) > conformtest-xfail-conds += mips-o32-linux > endif > > +ifeq ($(subdir),misc) > +sysdep_routines += mips-syscall5 mips-syscall6 mips-syscall7 > +endif > + > ifeq ($(subdir),stdlib) > tests += bug-getcontext-mips-gp > endif > Index: glibc/sysdeps/unix/sysv/linux/mips/mips32/Versions > =================================================================== > --- glibc.orig/sysdeps/unix/sysv/linux/mips/mips32/Versions 2017-08-20 01:30:23.617089669 +0100 > +++ glibc/sysdeps/unix/sysv/linux/mips/mips32/Versions 2017-08-20 01:34:46.740608292 +0100 > @@ -3,4 +3,7 @@ libc { > getrlimit64; > setrlimit64; > } > + GLIBC_PRIVATE { > + __mips_syscall5; __mips_syscall6; __mips_syscall7; > + } > } > Index: glibc/sysdeps/unix/sysv/linux/mips/mips32/mips-syscall5.S > =================================================================== > --- /dev/null 1970-01-01 00:00:00.000000000 +0000 > +++ glibc/sysdeps/unix/sysv/linux/mips/mips32/mips-syscall5.S 2017-08-20 03:02:13.583854495 +0100 > @@ -0,0 +1,33 @@ One line comment to describe this file. > +/* Copyright (C) 2017 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, see > + <http://www.gnu.org/licenses/>. */ > + > +#include <sysdep.h> > +#include <sys/asm.h> > + > + .text > + .set nomips16 > + > +/* long long __mips_syscall5 (long arg1, long arg2, long arg3, long arg4, > + long arg5, > + long number) */ > + > +ENTRY(__mips_syscall5) > + lw v0, 20(sp) > + syscall > + move v1, a3 > + jr ra > +END(__mips_syscall5) > Index: glibc/sysdeps/unix/sysv/linux/mips/mips32/mips-syscall6.S > =================================================================== > --- /dev/null 1970-01-01 00:00:00.000000000 +0000 > +++ glibc/sysdeps/unix/sysv/linux/mips/mips32/mips-syscall6.S 2017-08-20 03:02:17.294755273 +0100 > @@ -0,0 +1,33 @@ Same as before. > +/* Copyright (C) 2017 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, see > + <http://www.gnu.org/licenses/>. */ > + > +#include <sysdep.h> > +#include <sys/asm.h> > + > + .text > + .set nomips16 > + > +/* long long __mips_syscall6 (long arg1, long arg2, long arg3, long arg4, > + long arg5, long arg6, > + long number) */ > + > +ENTRY(__mips_syscall6) > + lw v0, 24(sp) > + syscall > + move v1, a3 > + jr ra > +END(__mips_syscall6) > Index: glibc/sysdeps/unix/sysv/linux/mips/mips32/mips-syscall7.S > =================================================================== > --- /dev/null 1970-01-01 00:00:00.000000000 +0000 > +++ glibc/sysdeps/unix/sysv/linux/mips/mips32/mips-syscall7.S 2017-08-20 03:02:20.617120331 +0100 > @@ -0,0 +1,33 @@ Same as before. > +/* Copyright (C) 2017 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, see > + <http://www.gnu.org/licenses/>. */ > + > +#include <sysdep.h> > +#include <sys/asm.h> > + > + .text > + .set nomips16 > + > +/* long long __mips_syscall7 (long arg1, long arg2, long arg3, long arg4, > + long arg5, long arg6, long arg7, > + long number) */ > + > +ENTRY(__mips_syscall7) > + lw v0, 28(sp) > + syscall > + move v1, a3 > + jr ra > +END(__mips_syscall7) > Index: glibc/sysdeps/unix/sysv/linux/mips/mips32/mips16/Makefile > =================================================================== > --- glibc.orig/sysdeps/unix/sysv/linux/mips/mips32/mips16/Makefile 2017-08-20 01:30:23.490163141 +0100 > +++ glibc/sysdeps/unix/sysv/linux/mips/mips32/mips16/Makefile 2017-08-20 01:34:46.819433661 +0100 > @@ -1,13 +1,9 @@ > ifeq ($(subdir),misc) > sysdep_routines += mips16-syscall0 mips16-syscall1 mips16-syscall2 > -sysdep_routines += mips16-syscall3 mips16-syscall4 mips16-syscall5 > -sysdep_routines += mips16-syscall6 mips16-syscall7 > +sysdep_routines += mips16-syscall3 mips16-syscall4 > CFLAGS-mips16-syscall0.c += -fexceptions > CFLAGS-mips16-syscall1.c += -fexceptions > CFLAGS-mips16-syscall2.c += -fexceptions > CFLAGS-mips16-syscall3.c += -fexceptions > CFLAGS-mips16-syscall4.c += -fexceptions > -CFLAGS-mips16-syscall5.c += -fexceptions > -CFLAGS-mips16-syscall6.c += -fexceptions > -CFLAGS-mips16-syscall7.c += -fexceptions > endif > Index: glibc/sysdeps/unix/sysv/linux/mips/mips32/mips16/Versions > =================================================================== > --- glibc.orig/sysdeps/unix/sysv/linux/mips/mips32/mips16/Versions 2017-08-20 01:30:23.494195070 +0100 > +++ glibc/sysdeps/unix/sysv/linux/mips/mips32/mips16/Versions 2017-08-20 01:34:46.830600751 +0100 > @@ -1,6 +1,6 @@ > libc { > GLIBC_PRIVATE { > __mips16_syscall0; __mips16_syscall1; __mips16_syscall2; __mips16_syscall3; > - __mips16_syscall4; __mips16_syscall5; __mips16_syscall6; __mips16_syscall7; > + __mips16_syscall4; > } > } > Index: glibc/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall.h > =================================================================== > --- glibc.orig/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall.h 2017-08-20 01:30:23.505269052 +0100 > +++ glibc/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall.h 2017-08-20 01:34:46.845845282 +0100 > @@ -19,19 +19,6 @@ > #ifndef MIPS16_SYSCALL_H > #define MIPS16_SYSCALL_H 1 > > -#define __nomips16 __attribute__ ((nomips16)) > - > -union __mips16_syscall_return > - { > - long long val; > - struct > - { > - long v0; > - long v1; > - } > - reg; > - }; > - > long long __nomips16 __mips16_syscall0 (long number); > #define __mips16_syscall0(dummy, number) \ > __mips16_syscall0 ((long) (number)) > @@ -61,29 +48,22 @@ long long __nomips16 __mips16_syscall4 ( > (long) (a3), \ > (long) (number)) > > -long long __nomips16 __mips16_syscall5 (long a0, long a1, long a2, long a3, > - long a4, > - long number); > +/* The remaining ones use regular MIPS wrappers. */ > + > #define __mips16_syscall5(a0, a1, a2, a3, a4, number) \ > - __mips16_syscall5 ((long) (a0), (long) (a1), (long) (a2), \ > - (long) (a3), (long) (a4), \ > - (long) (number)) > + __mips_syscall5 ((long) (a0), (long) (a1), (long) (a2), \ > + (long) (a3), (long) (a4), \ > + (long) (number)) > > -long long __nomips16 __mips16_syscall6 (long a0, long a1, long a2, long a3, > - long a4, long a5, > - long number); > #define __mips16_syscall6(a0, a1, a2, a3, a4, a5, number) \ > - __mips16_syscall6 ((long) (a0), (long) (a1), (long) (a2), \ > - (long) (a3), (long) (a4), (long) (a5), \ > - (long) (number)) > + __mips_syscall6 ((long) (a0), (long) (a1), (long) (a2), \ > + (long) (a3), (long) (a4), (long) (a5), \ > + (long) (number)) > > -long long __nomips16 __mips16_syscall7 (long a0, long a1, long a2, long a3, > - long a4, long a5, long a6, > - long number); > #define __mips16_syscall7(a0, a1, a2, a3, a4, a5, a6, number) \ > - __mips16_syscall7 ((long) (a0), (long) (a1), (long) (a2), \ > - (long) (a3), (long) (a4), (long) (a5), \ > - (long) (a6), \ > - (long) (number)) > + __mips_syscall7 ((long) (a0), (long) (a1), (long) (a2), \ > + (long) (a3), (long) (a4), (long) (a5), \ > + (long) (a6), \ > + (long) (number)) > > #endif > Index: glibc/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall0.c > =================================================================== > --- glibc.orig/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall0.c 2017-08-20 01:30:23.564450375 +0100 > +++ glibc/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall0.c 2017-08-20 01:34:46.849881768 +0100 > @@ -17,14 +17,13 @@ > <http://www.gnu.org/licenses/>. */ > > #include <sysdep.h> > -#include <mips16-syscall.h> > > #undef __mips16_syscall0 > > long long __nomips16 > __mips16_syscall0 (long number) > { > - union __mips16_syscall_return ret; > + union __mips_syscall_return ret; > ret.reg.v0 = INTERNAL_SYSCALL_MIPS16 (number, ret.reg.v1, 0); > return ret.val; > } > Index: glibc/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall1.c > =================================================================== > --- glibc.orig/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall1.c 2017-08-20 01:30:23.568506526 +0100 > +++ glibc/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall1.c 2017-08-20 01:34:46.860061453 +0100 > @@ -17,7 +17,6 @@ > <http://www.gnu.org/licenses/>. */ > > #include <sysdep.h> > -#include <mips16-syscall.h> > > #undef __mips16_syscall1 > > @@ -25,7 +24,7 @@ long long __nomips16 > __mips16_syscall1 (long a0, > long number) > { > - union __mips16_syscall_return ret; > + union __mips_syscall_return ret; > ret.reg.v0 = INTERNAL_SYSCALL_MIPS16 (number, ret.reg.v1, 1, > a0); > return ret.val; > Index: glibc/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall2.c > =================================================================== > --- glibc.orig/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall2.c 2017-08-20 01:30:23.578642154 +0100 > +++ glibc/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall2.c 2017-08-20 01:34:46.865155941 +0100 > @@ -17,7 +17,6 @@ > <http://www.gnu.org/licenses/>. */ > > #include <sysdep.h> > -#include <mips16-syscall.h> > > #undef __mips16_syscall2 > > @@ -25,7 +24,7 @@ long long __nomips16 > __mips16_syscall2 (long a0, long a1, > long number) > { > - union __mips16_syscall_return ret; > + union __mips_syscall_return ret; > ret.reg.v0 = INTERNAL_SYSCALL_MIPS16 (number, ret.reg.v1, 2, > a0, a1); > return ret.val; > Index: glibc/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall3.c > =================================================================== > --- glibc.orig/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall3.c 2017-08-20 01:30:23.582725033 +0100 > +++ glibc/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall3.c 2017-08-20 01:34:46.873273352 +0100 > @@ -17,7 +17,6 @@ > <http://www.gnu.org/licenses/>. */ > > #include <sysdep.h> > -#include <mips16-syscall.h> > > #undef __mips16_syscall3 > > @@ -25,7 +24,7 @@ long long __nomips16 > __mips16_syscall3 (long a0, long a1, long a2, > long number) > { > - union __mips16_syscall_return ret; > + union __mips_syscall_return ret; > ret.reg.v0 = INTERNAL_SYSCALL_MIPS16 (number, ret.reg.v1, 3, > a0, a1, a2); > return ret.val; > Index: glibc/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall4.c > =================================================================== > --- glibc.orig/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall4.c 2017-08-20 01:30:23.591846747 +0100 > +++ glibc/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall4.c 2017-08-20 01:34:46.894612901 +0100 > @@ -17,7 +17,6 @@ > <http://www.gnu.org/licenses/>. */ > > #include <sysdep.h> > -#include <mips16-syscall.h> > > #undef __mips16_syscall4 > > @@ -25,7 +24,7 @@ long long __nomips16 > __mips16_syscall4 (long a0, long a1, long a2, long a3, > long number) > { > - union __mips16_syscall_return ret; > + union __mips_syscall_return ret; > ret.reg.v0 = INTERNAL_SYSCALL_MIPS16 (number, ret.reg.v1, 4, > a0, a1, a2, a3); > return ret.val; > Index: glibc/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall5.c > =================================================================== > --- glibc.orig/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall5.c 2017-08-20 01:30:23.522504662 +0100 > +++ /dev/null 1970-01-01 00:00:00.000000000 +0000 > @@ -1,33 +0,0 @@ > -/* MIPS16 syscall wrappers. > - Copyright (C) 2013-2017 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, see > - <http://www.gnu.org/licenses/>. */ > - > -#include <sysdep.h> > -#include <mips16-syscall.h> > - > -#undef __mips16_syscall5 > - > -long long __nomips16 > -__mips16_syscall5 (long a0, long a1, long a2, long a3, > - long a4, > - long number) > -{ > - union __mips16_syscall_return ret; > - ret.reg.v0 = INTERNAL_SYSCALL_MIPS16 (number, ret.reg.v1, 5, > - a0, a1, a2, a3, a4); > - return ret.val; > -} > Index: glibc/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall6.c > =================================================================== > --- glibc.orig/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall6.c 2017-08-20 01:30:23.536931914 +0100 > +++ /dev/null 1970-01-01 00:00:00.000000000 +0000 > @@ -1,33 +0,0 @@ > -/* MIPS16 syscall wrappers. > - Copyright (C) 2013-2017 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, see > - <http://www.gnu.org/licenses/>. */ > - > -#include <sysdep.h> > -#include <mips16-syscall.h> > - > -#undef __mips16_syscall6 > - > -long long __nomips16 > -__mips16_syscall6 (long a0, long a1, long a2, long a3, > - long a4, long a5, > - long number) > -{ > - union __mips16_syscall_return ret; > - ret.reg.v0 = INTERNAL_SYSCALL_MIPS16 (number, ret.reg.v1, 6, > - a0, a1, a2, a3, a4, a5); > - return ret.val; > -} > Index: glibc/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall7.c > =================================================================== > --- glibc.orig/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall7.c 2017-08-20 01:30:23.546046859 +0100 > +++ /dev/null 1970-01-01 00:00:00.000000000 +0000 > @@ -1,33 +0,0 @@ > -/* MIPS16 syscall wrappers. > - Copyright (C) 2013-2017 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, see > - <http://www.gnu.org/licenses/>. */ > - > -#include <sysdep.h> > -#include <mips16-syscall.h> > - > -#undef __mips16_syscall7 > - > -long long __nomips16 > -__mips16_syscall7 (long a0, long a1, long a2, long a3, > - long a4, long a5, long a6, > - long number) > -{ > - union __mips16_syscall_return ret; > - ret.reg.v0 = INTERNAL_SYSCALL_MIPS16 (number, ret.reg.v1, 7, > - a0, a1, a2, a3, a4, a5, a6); > - return ret.val; > -} > Index: glibc/sysdeps/unix/sysv/linux/mips/mips32/sysdep.h > =================================================================== > --- glibc.orig/sysdeps/unix/sysv/linux/mips/mips32/sysdep.h 2017-08-20 01:30:23.602967356 +0100 > +++ glibc/sysdeps/unix/sysv/linux/mips/mips32/sysdep.h 2017-08-20 14:15:03.369838111 +0100 > @@ -98,6 +98,19 @@ > #undef INTERNAL_SYSCALL > #undef INTERNAL_SYSCALL_NCS > > +#define __nomips16 __attribute__ ((nomips16)) > + > +union __mips_syscall_return > + { > + long long val; > + struct > + { > + long v0; > + long v1; > + } > + reg; > + }; > + > #ifdef __mips16 > /* There's no MIPS16 syscall instruction, so we go through out-of-line > standard MIPS wrappers. These do use inline snippets below though, > @@ -112,7 +125,7 @@ > > # define INTERNAL_SYSCALL_NCS(number, err, nr, args...) \ > ({ \ > - union __mips16_syscall_return _sc_ret; \ > + union __mips_syscall_return _sc_ret; \ > _sc_ret.val = __mips16_syscall##nr (args, number); \ > err = _sc_ret.reg.v1; \ > _sc_ret.reg.v0; \ > @@ -121,13 +134,13 @@ > # define INTERNAL_SYSCALL_MIPS16(number, err, nr, args...) \ > internal_syscall##nr ("lw\t%0, %2\n\t", \ > "R" (number), \ > - 0, err, args) > + number, err, args) > > #else /* !__mips16 */ > # define INTERNAL_SYSCALL(name, err, nr, args...) \ > internal_syscall##nr ("li\t%0, %2\t\t\t# " #name "\n\t", \ > "IK" (SYS_ify (name)), \ > - 0, err, args) > + SYS_ify (name), err, args) > > # define INTERNAL_SYSCALL_NCS(number, err, nr, args...) \ > internal_syscall##nr (MOVE32 "\t%0, %2\n\t", \ > @@ -262,110 +275,65 @@ > _sys_result; \ > }) > > -/* We need to use a frame pointer for the functions in which we > - adjust $sp around the syscall, or debug information and unwind > - information will be $sp relative and thus wrong during the syscall. As > - of GCC 4.7, this is sufficient. */ > -#define FORCE_FRAME_POINTER \ > - void *volatile __fp_force __attribute__ ((unused)) = alloca (4) > +/* Out-of-line standard MIPS wrappers used for 5, 6, and 7 argument > + syscalls, which require stack arguments. */ I think it is worth to add a comment why we are using out-of-line wrappers for syscalls with 5, 6, and 7 arguments. > + > +long long __nomips16 __mips_syscall5 (long arg1, long arg2, long arg3, > + long arg4, long arg5, > + long number) > > #define internal_syscall5(v0_init, input, number, err, \ > arg1, arg2, arg3, arg4, arg5) \ > ({ \ > - long _sys_result; \ > - \ > - FORCE_FRAME_POINTER; \ > - { \ > - register long __s0 asm ("$16") __attribute__ ((unused)) \ > - = (number); \ > - register long __v0 asm ("$2"); \ > - register long __a0 asm ("$4") = (long) (arg1); \ > - register long __a1 asm ("$5") = (long) (arg2); \ > - register long __a2 asm ("$6") = (long) (arg3); \ > - register long __a3 asm ("$7") = (long) (arg4); \ > - __asm__ volatile ( \ > - ".set\tnoreorder\n\t" \ > - "subu\t$29, 32\n\t" \ > - "sw\t%6, 16($29)\n\t" \ > - v0_init \ > - "syscall\n\t" \ > - "addiu\t$29, 32\n\t" \ > - ".set\treorder" \ > - : "=r" (__v0), "+r" (__a3) \ > - : input, "r" (__a0), "r" (__a1), "r" (__a2), \ > - "r" ((long) (arg5)) \ > - : __SYSCALL_CLOBBERS); \ > - err = __a3; \ > - _sys_result = __v0; \ > - } \ > - _sys_result; \ > + union __mips_syscall_return _sc_ret; \ > + _sc_ret.val = __mips_syscall5 ((long) (arg1), \ > + (long) (arg2), \ > + (long) (arg3), \ > + (long) (arg4), \ > + (long) (arg5), \ > + (long) (number)); \ > + err = _sc_ret.reg.v1; \ > + _sc_ret.reg.v0; \ > }) > > +long long __nomips16 __mips_syscall6 (long arg1, long arg2, long arg3, > + long arg4, long arg5, long arg6, > + long number); > + > #define internal_syscall6(v0_init, input, number, err, \ > arg1, arg2, arg3, arg4, arg5, arg6) \ > ({ \ > - long _sys_result; \ > - \ > - FORCE_FRAME_POINTER; \ > - { \ > - register long __s0 asm ("$16") __attribute__ ((unused)) \ > - = (number); \ > - register long __v0 asm ("$2"); \ > - register long __a0 asm ("$4") = (long) (arg1); \ > - register long __a1 asm ("$5") = (long) (arg2); \ > - register long __a2 asm ("$6") = (long) (arg3); \ > - register long __a3 asm ("$7") = (long) (arg4); \ > - __asm__ volatile ( \ > - ".set\tnoreorder\n\t" \ > - "subu\t$29, 32\n\t" \ > - "sw\t%6, 16($29)\n\t" \ > - "sw\t%7, 20($29)\n\t" \ > - v0_init \ > - "syscall\n\t" \ > - "addiu\t$29, 32\n\t" \ > - ".set\treorder" \ > - : "=r" (__v0), "+r" (__a3) \ > - : input, "r" (__a0), "r" (__a1), "r" (__a2), \ > - "r" ((long) (arg5)), "r" ((long) (arg6)) \ > - : __SYSCALL_CLOBBERS); \ > - err = __a3; \ > - _sys_result = __v0; \ > - } \ > - _sys_result; \ > + union __mips_syscall_return _sc_ret; \ > + _sc_ret.val = __mips_syscall6 ((long) (arg1), \ > + (long) (arg2), \ > + (long) (arg3), \ > + (long) (arg4), \ > + (long) (arg5), \ > + (long) (arg6), \ > + (long) (number)); \ > + err = _sc_ret.reg.v1; \ > + _sc_ret.reg.v0; \ > }) > > +long long __nomips16 __mips_syscall7 (long arg1, long arg2, long arg3, > + long arg4, long arg5, long arg6, > + long arg7, > + long number); > + > #define internal_syscall7(v0_init, input, number, err, \ > arg1, arg2, arg3, arg4, arg5, arg6, arg7) \ > ({ \ > - long _sys_result; \ > - \ > - FORCE_FRAME_POINTER; \ > - { \ > - register long __s0 asm ("$16") __attribute__ ((unused)) \ > - = (number); \ > - register long __v0 asm ("$2"); \ > - register long __a0 asm ("$4") = (long) (arg1); \ > - register long __a1 asm ("$5") = (long) (arg2); \ > - register long __a2 asm ("$6") = (long) (arg3); \ > - register long __a3 asm ("$7") = (long) (arg4); \ > - __asm__ volatile ( \ > - ".set\tnoreorder\n\t" \ > - "subu\t$29, 32\n\t" \ > - "sw\t%6, 16($29)\n\t" \ > - "sw\t%7, 20($29)\n\t" \ > - "sw\t%8, 24($29)\n\t" \ > - v0_init \ > - "syscall\n\t" \ > - "addiu\t$29, 32\n\t" \ > - ".set\treorder" \ > - : "=r" (__v0), "+r" (__a3) \ > - : input, "r" (__a0), "r" (__a1), "r" (__a2), \ > - "r" ((long) (arg5)), "r" ((long) (arg6)), "r" ((long) (arg7)) \ > - : __SYSCALL_CLOBBERS); \ > - err = __a3; \ > - _sys_result = __v0; \ > - } \ > - _sys_result; \ > + union __mips_syscall_return _sc_ret; \ > + _sc_ret.val = __mips_syscall7 ((long) (arg1), \ > + (long) (arg2), \ > + (long) (arg3), \ > + (long) (arg4), \ > + (long) (arg5), \ > + (long) (arg6), \ > + (long) (arg7), \ > + (long) (number)); \ > + err = _sc_ret.reg.v1; \ > + _sc_ret.reg.v0; \ > }) > > #define __SYSCALL_CLOBBERS "$1", "$3", "$8", "$9", "$10", "$11", "$12", "$13", \ >
On 2017-08-21 11:48, Maciej W. Rozycki wrote: > On Sat, 19 Aug 2017, Aurelien Jarno wrote: > > > The MIPS16 wrappers were split into individual files so that only ones > > > that are actually used by `ld.so' are pulled. I think it would be good if > > > we preserved that. I'll see if I can experiment with keeping the original > > > MIPS16 0-3 wrappers. > > > > For what I have seen, ld.so already uses syscalls with 1 to 4 arguments. > > It doesn't use any syscall without argument though. So it's only 4 > > instructions overhead. > > Why make things worse where they don't have to be and there's no benefit > elsewhere that would balance the regression? > > Here's what I had in mind. The key was updating the macros appropriately > in sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall.h. Beyond > that I made a number of clean-ups: > > 1. I renamed `__libc_do_syscall?' to `__mips_syscall?', for consistency > with `__mips16_syscall?', and consequently `__libc_do_syscall_return' > to `__mips_syscall_return'. > > 2. I exported `__mips_syscall?' wrappers from `libc.so' rather than making > them hidden. This is also consistent with `__mips16_syscall?' wrappers > and reduces code duplication of doubtful benefit -- it could be that > some calls, if internal, could be subject to the JALR->BAL > optimisation, however only those that are in range and only in regular > MIPS code, for a minimal execution time saving on some processors only. > Exporting these entries makes the maintenance effort much easier > though, as we don't have to track and record their use in the > individual subdirectories in Makefile. > > 3. I renamed `_sys_result' to `_sc_ret' where it is declared as `union > __mips_syscall_return', again for clarity and consistency with MIPS16 > INTERNAL_SYSCALL_NCS. > > 4. I wrapped `number' in parentheses in `internal_syscall5', > `internal_syscall6' and `internal_syscall7', and cast it to `long'. > > 5. I have adjusted some comments. > > Please let me know if you have any questions or concerns about this > update. > > This passes o32 regular MIPS regression testing, however my GCC 8 binary > seems to miscompile support_test_main.c in the MIPS16 mode, causing all > the relevant test cases to crash with SIGILL (in the `support_set_test_dir > (test_dir)' invocation it's `test_dir' that is jumped to rather than > `support_set_test_dir'; I'll file a bug separately). I'll find a way to > run MIPS16 testing eventually, however meanwhile I will appreciate if you > do it for me. Thanks, this looks fine for me. I don't have more comments than the ones already done by Adhemerval. I have tested it on MIPS O32 BE and LE, I don't see any regression. I can do a test build for MIPS16 and run basic testing under QEMU, but I don't have the hardware to do more. Aurelien
On Tue, 22 Aug 2017, Aurelien Jarno wrote: > > This passes o32 regular MIPS regression testing, however my GCC 8 binary > > seems to miscompile support_test_main.c in the MIPS16 mode, causing all > > the relevant test cases to crash with SIGILL (in the `support_set_test_dir > > (test_dir)' invocation it's `test_dir' that is jumped to rather than > > `support_set_test_dir'; I'll file a bug separately). I'll find a way to > > run MIPS16 testing eventually, however meanwhile I will appreciate if you > > do it for me. > > Thanks, this looks fine for me. I don't have more comments than the ones > already done by Adhemerval. I have tested it on MIPS O32 BE and LE, I > don't see any regression. Great, thanks! I'll yet make the adjustments Adhemerval suggested. > I can do a test build for MIPS16 and run basic testing under QEMU, but I > don't have the hardware to do more. Thanks. I have now identified the cause of my code generation problem (it was actually a register encoding bug in LD relaxation I have implemented in preparation to handle PR ld/21375, and which I thought I had removed from the binutils build used for this verification), so I will be able to run MIPS16 testing myself once I have the updated patch ready. Maciej
On Mon, 21 Aug 2017, Maciej W. Rozycki wrote: > Thanks. There's indeed a bug in GAS, a MIPS16 path of execution has been > missed in the handling of this option. I have a preliminary fix, however > I yet have to prepare test suite cases (originally the option was > mistakenly only covered by regular MIPS and microMIPS testing, which is > clearly why the MIPS16 case has been missed). I expect this fix to be > included in the upcoming 2.29.1 release, and also backported to 2.28 > (although no new 2.28 release is scheduled). The fix has passed QA and has now been applied as commit 278fcf38584d ("MIPS/GAS: Also respect `-mignore-branch-isa' with MIPS16 code") to master, and backported to 2.29 and 2.28. A binutils 2.29.1 release is scheduled mid September. Maciej
On 2017-08-30 16:35, Maciej W. Rozycki wrote: > On Mon, 21 Aug 2017, Maciej W. Rozycki wrote: > > > Thanks. There's indeed a bug in GAS, a MIPS16 path of execution has been > > missed in the handling of this option. I have a preliminary fix, however > > I yet have to prepare test suite cases (originally the option was > > mistakenly only covered by regular MIPS and microMIPS testing, which is > > clearly why the MIPS16 case has been missed). I expect this fix to be > > included in the upcoming 2.29.1 release, and also backported to 2.28 > > (although no new 2.28 release is scheduled). > > The fix has passed QA and has now been applied as commit 278fcf38584d > ("MIPS/GAS: Also respect `-mignore-branch-isa' with MIPS16 code") to > master, and backported to 2.29 and 2.28. A binutils 2.29.1 release is > scheduled mid September. Thanks!
Index: glibc/sysdeps/unix/sysv/linux/mips/mips32/Makefile =================================================================== --- glibc.orig/sysdeps/unix/sysv/linux/mips/mips32/Makefile 2017-08-20 01:30:23.485088512 +0100 +++ glibc/sysdeps/unix/sysv/linux/mips/mips32/Makefile 2017-08-20 01:34:46.716443161 +0100 @@ -3,6 +3,10 @@ ifeq ($(subdir),conform) conformtest-xfail-conds += mips-o32-linux endif +ifeq ($(subdir),misc) +sysdep_routines += mips-syscall5 mips-syscall6 mips-syscall7 +endif + ifeq ($(subdir),stdlib) tests += bug-getcontext-mips-gp endif Index: glibc/sysdeps/unix/sysv/linux/mips/mips32/Versions =================================================================== --- glibc.orig/sysdeps/unix/sysv/linux/mips/mips32/Versions 2017-08-20 01:30:23.617089669 +0100 +++ glibc/sysdeps/unix/sysv/linux/mips/mips32/Versions 2017-08-20 01:34:46.740608292 +0100 @@ -3,4 +3,7 @@ libc { getrlimit64; setrlimit64; } + GLIBC_PRIVATE { + __mips_syscall5; __mips_syscall6; __mips_syscall7; + } } Index: glibc/sysdeps/unix/sysv/linux/mips/mips32/mips-syscall5.S =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ glibc/sysdeps/unix/sysv/linux/mips/mips32/mips-syscall5.S 2017-08-20 03:02:13.583854495 +0100 @@ -0,0 +1,33 @@ +/* Copyright (C) 2017 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, see + <http://www.gnu.org/licenses/>. */ + +#include <sysdep.h> +#include <sys/asm.h> + + .text + .set nomips16 + +/* long long __mips_syscall5 (long arg1, long arg2, long arg3, long arg4, + long arg5, + long number) */ + +ENTRY(__mips_syscall5) + lw v0, 20(sp) + syscall + move v1, a3 + jr ra +END(__mips_syscall5) Index: glibc/sysdeps/unix/sysv/linux/mips/mips32/mips-syscall6.S =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ glibc/sysdeps/unix/sysv/linux/mips/mips32/mips-syscall6.S 2017-08-20 03:02:17.294755273 +0100 @@ -0,0 +1,33 @@ +/* Copyright (C) 2017 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, see + <http://www.gnu.org/licenses/>. */ + +#include <sysdep.h> +#include <sys/asm.h> + + .text + .set nomips16 + +/* long long __mips_syscall6 (long arg1, long arg2, long arg3, long arg4, + long arg5, long arg6, + long number) */ + +ENTRY(__mips_syscall6) + lw v0, 24(sp) + syscall + move v1, a3 + jr ra +END(__mips_syscall6) Index: glibc/sysdeps/unix/sysv/linux/mips/mips32/mips-syscall7.S =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ glibc/sysdeps/unix/sysv/linux/mips/mips32/mips-syscall7.S 2017-08-20 03:02:20.617120331 +0100 @@ -0,0 +1,33 @@ +/* Copyright (C) 2017 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, see + <http://www.gnu.org/licenses/>. */ + +#include <sysdep.h> +#include <sys/asm.h> + + .text + .set nomips16 + +/* long long __mips_syscall7 (long arg1, long arg2, long arg3, long arg4, + long arg5, long arg6, long arg7, + long number) */ + +ENTRY(__mips_syscall7) + lw v0, 28(sp) + syscall + move v1, a3 + jr ra +END(__mips_syscall7) Index: glibc/sysdeps/unix/sysv/linux/mips/mips32/mips16/Makefile =================================================================== --- glibc.orig/sysdeps/unix/sysv/linux/mips/mips32/mips16/Makefile 2017-08-20 01:30:23.490163141 +0100 +++ glibc/sysdeps/unix/sysv/linux/mips/mips32/mips16/Makefile 2017-08-20 01:34:46.819433661 +0100 @@ -1,13 +1,9 @@ ifeq ($(subdir),misc) sysdep_routines += mips16-syscall0 mips16-syscall1 mips16-syscall2 -sysdep_routines += mips16-syscall3 mips16-syscall4 mips16-syscall5 -sysdep_routines += mips16-syscall6 mips16-syscall7 +sysdep_routines += mips16-syscall3 mips16-syscall4 CFLAGS-mips16-syscall0.c += -fexceptions CFLAGS-mips16-syscall1.c += -fexceptions CFLAGS-mips16-syscall2.c += -fexceptions CFLAGS-mips16-syscall3.c += -fexceptions CFLAGS-mips16-syscall4.c += -fexceptions -CFLAGS-mips16-syscall5.c += -fexceptions -CFLAGS-mips16-syscall6.c += -fexceptions -CFLAGS-mips16-syscall7.c += -fexceptions endif Index: glibc/sysdeps/unix/sysv/linux/mips/mips32/mips16/Versions =================================================================== --- glibc.orig/sysdeps/unix/sysv/linux/mips/mips32/mips16/Versions 2017-08-20 01:30:23.494195070 +0100 +++ glibc/sysdeps/unix/sysv/linux/mips/mips32/mips16/Versions 2017-08-20 01:34:46.830600751 +0100 @@ -1,6 +1,6 @@ libc { GLIBC_PRIVATE { __mips16_syscall0; __mips16_syscall1; __mips16_syscall2; __mips16_syscall3; - __mips16_syscall4; __mips16_syscall5; __mips16_syscall6; __mips16_syscall7; + __mips16_syscall4; } } Index: glibc/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall.h =================================================================== --- glibc.orig/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall.h 2017-08-20 01:30:23.505269052 +0100 +++ glibc/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall.h 2017-08-20 01:34:46.845845282 +0100 @@ -19,19 +19,6 @@ #ifndef MIPS16_SYSCALL_H #define MIPS16_SYSCALL_H 1 -#define __nomips16 __attribute__ ((nomips16)) - -union __mips16_syscall_return - { - long long val; - struct - { - long v0; - long v1; - } - reg; - }; - long long __nomips16 __mips16_syscall0 (long number); #define __mips16_syscall0(dummy, number) \ __mips16_syscall0 ((long) (number)) @@ -61,29 +48,22 @@ long long __nomips16 __mips16_syscall4 ( (long) (a3), \ (long) (number)) -long long __nomips16 __mips16_syscall5 (long a0, long a1, long a2, long a3, - long a4, - long number); +/* The remaining ones use regular MIPS wrappers. */ + #define __mips16_syscall5(a0, a1, a2, a3, a4, number) \ - __mips16_syscall5 ((long) (a0), (long) (a1), (long) (a2), \ - (long) (a3), (long) (a4), \ - (long) (number)) + __mips_syscall5 ((long) (a0), (long) (a1), (long) (a2), \ + (long) (a3), (long) (a4), \ + (long) (number)) -long long __nomips16 __mips16_syscall6 (long a0, long a1, long a2, long a3, - long a4, long a5, - long number); #define __mips16_syscall6(a0, a1, a2, a3, a4, a5, number) \ - __mips16_syscall6 ((long) (a0), (long) (a1), (long) (a2), \ - (long) (a3), (long) (a4), (long) (a5), \ - (long) (number)) + __mips_syscall6 ((long) (a0), (long) (a1), (long) (a2), \ + (long) (a3), (long) (a4), (long) (a5), \ + (long) (number)) -long long __nomips16 __mips16_syscall7 (long a0, long a1, long a2, long a3, - long a4, long a5, long a6, - long number); #define __mips16_syscall7(a0, a1, a2, a3, a4, a5, a6, number) \ - __mips16_syscall7 ((long) (a0), (long) (a1), (long) (a2), \ - (long) (a3), (long) (a4), (long) (a5), \ - (long) (a6), \ - (long) (number)) + __mips_syscall7 ((long) (a0), (long) (a1), (long) (a2), \ + (long) (a3), (long) (a4), (long) (a5), \ + (long) (a6), \ + (long) (number)) #endif Index: glibc/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall0.c =================================================================== --- glibc.orig/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall0.c 2017-08-20 01:30:23.564450375 +0100 +++ glibc/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall0.c 2017-08-20 01:34:46.849881768 +0100 @@ -17,14 +17,13 @@ <http://www.gnu.org/licenses/>. */ #include <sysdep.h> -#include <mips16-syscall.h> #undef __mips16_syscall0 long long __nomips16 __mips16_syscall0 (long number) { - union __mips16_syscall_return ret; + union __mips_syscall_return ret; ret.reg.v0 = INTERNAL_SYSCALL_MIPS16 (number, ret.reg.v1, 0); return ret.val; } Index: glibc/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall1.c =================================================================== --- glibc.orig/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall1.c 2017-08-20 01:30:23.568506526 +0100 +++ glibc/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall1.c 2017-08-20 01:34:46.860061453 +0100 @@ -17,7 +17,6 @@ <http://www.gnu.org/licenses/>. */ #include <sysdep.h> -#include <mips16-syscall.h> #undef __mips16_syscall1 @@ -25,7 +24,7 @@ long long __nomips16 __mips16_syscall1 (long a0, long number) { - union __mips16_syscall_return ret; + union __mips_syscall_return ret; ret.reg.v0 = INTERNAL_SYSCALL_MIPS16 (number, ret.reg.v1, 1, a0); return ret.val; Index: glibc/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall2.c =================================================================== --- glibc.orig/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall2.c 2017-08-20 01:30:23.578642154 +0100 +++ glibc/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall2.c 2017-08-20 01:34:46.865155941 +0100 @@ -17,7 +17,6 @@ <http://www.gnu.org/licenses/>. */ #include <sysdep.h> -#include <mips16-syscall.h> #undef __mips16_syscall2 @@ -25,7 +24,7 @@ long long __nomips16 __mips16_syscall2 (long a0, long a1, long number) { - union __mips16_syscall_return ret; + union __mips_syscall_return ret; ret.reg.v0 = INTERNAL_SYSCALL_MIPS16 (number, ret.reg.v1, 2, a0, a1); return ret.val; Index: glibc/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall3.c =================================================================== --- glibc.orig/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall3.c 2017-08-20 01:30:23.582725033 +0100 +++ glibc/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall3.c 2017-08-20 01:34:46.873273352 +0100 @@ -17,7 +17,6 @@ <http://www.gnu.org/licenses/>. */ #include <sysdep.h> -#include <mips16-syscall.h> #undef __mips16_syscall3 @@ -25,7 +24,7 @@ long long __nomips16 __mips16_syscall3 (long a0, long a1, long a2, long number) { - union __mips16_syscall_return ret; + union __mips_syscall_return ret; ret.reg.v0 = INTERNAL_SYSCALL_MIPS16 (number, ret.reg.v1, 3, a0, a1, a2); return ret.val; Index: glibc/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall4.c =================================================================== --- glibc.orig/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall4.c 2017-08-20 01:30:23.591846747 +0100 +++ glibc/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall4.c 2017-08-20 01:34:46.894612901 +0100 @@ -17,7 +17,6 @@ <http://www.gnu.org/licenses/>. */ #include <sysdep.h> -#include <mips16-syscall.h> #undef __mips16_syscall4 @@ -25,7 +24,7 @@ long long __nomips16 __mips16_syscall4 (long a0, long a1, long a2, long a3, long number) { - union __mips16_syscall_return ret; + union __mips_syscall_return ret; ret.reg.v0 = INTERNAL_SYSCALL_MIPS16 (number, ret.reg.v1, 4, a0, a1, a2, a3); return ret.val; Index: glibc/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall5.c =================================================================== --- glibc.orig/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall5.c 2017-08-20 01:30:23.522504662 +0100 +++ /dev/null 1970-01-01 00:00:00.000000000 +0000 @@ -1,33 +0,0 @@ -/* MIPS16 syscall wrappers. - Copyright (C) 2013-2017 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, see - <http://www.gnu.org/licenses/>. */ - -#include <sysdep.h> -#include <mips16-syscall.h> - -#undef __mips16_syscall5 - -long long __nomips16 -__mips16_syscall5 (long a0, long a1, long a2, long a3, - long a4, - long number) -{ - union __mips16_syscall_return ret; - ret.reg.v0 = INTERNAL_SYSCALL_MIPS16 (number, ret.reg.v1, 5, - a0, a1, a2, a3, a4); - return ret.val; -} Index: glibc/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall6.c =================================================================== --- glibc.orig/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall6.c 2017-08-20 01:30:23.536931914 +0100 +++ /dev/null 1970-01-01 00:00:00.000000000 +0000 @@ -1,33 +0,0 @@ -/* MIPS16 syscall wrappers. - Copyright (C) 2013-2017 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, see - <http://www.gnu.org/licenses/>. */ - -#include <sysdep.h> -#include <mips16-syscall.h> - -#undef __mips16_syscall6 - -long long __nomips16 -__mips16_syscall6 (long a0, long a1, long a2, long a3, - long a4, long a5, - long number) -{ - union __mips16_syscall_return ret; - ret.reg.v0 = INTERNAL_SYSCALL_MIPS16 (number, ret.reg.v1, 6, - a0, a1, a2, a3, a4, a5); - return ret.val; -} Index: glibc/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall7.c =================================================================== --- glibc.orig/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall7.c 2017-08-20 01:30:23.546046859 +0100 +++ /dev/null 1970-01-01 00:00:00.000000000 +0000 @@ -1,33 +0,0 @@ -/* MIPS16 syscall wrappers. - Copyright (C) 2013-2017 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, see - <http://www.gnu.org/licenses/>. */ - -#include <sysdep.h> -#include <mips16-syscall.h> - -#undef __mips16_syscall7 - -long long __nomips16 -__mips16_syscall7 (long a0, long a1, long a2, long a3, - long a4, long a5, long a6, - long number) -{ - union __mips16_syscall_return ret; - ret.reg.v0 = INTERNAL_SYSCALL_MIPS16 (number, ret.reg.v1, 7, - a0, a1, a2, a3, a4, a5, a6); - return ret.val; -} Index: glibc/sysdeps/unix/sysv/linux/mips/mips32/sysdep.h =================================================================== --- glibc.orig/sysdeps/unix/sysv/linux/mips/mips32/sysdep.h 2017-08-20 01:30:23.602967356 +0100 +++ glibc/sysdeps/unix/sysv/linux/mips/mips32/sysdep.h 2017-08-20 14:15:03.369838111 +0100 @@ -98,6 +98,19 @@ #undef INTERNAL_SYSCALL #undef INTERNAL_SYSCALL_NCS +#define __nomips16 __attribute__ ((nomips16)) + +union __mips_syscall_return + { + long long val; + struct + { + long v0; + long v1; + } + reg; + }; + #ifdef __mips16 /* There's no MIPS16 syscall instruction, so we go through out-of-line standard MIPS wrappers. These do use inline snippets below though, @@ -112,7 +125,7 @@ # define INTERNAL_SYSCALL_NCS(number, err, nr, args...) \ ({ \ - union __mips16_syscall_return _sc_ret; \ + union __mips_syscall_return _sc_ret; \ _sc_ret.val = __mips16_syscall##nr (args, number); \ err = _sc_ret.reg.v1; \ _sc_ret.reg.v0; \ @@ -121,13 +134,13 @@ # define INTERNAL_SYSCALL_MIPS16(number, err, nr, args...) \ internal_syscall##nr ("lw\t%0, %2\n\t", \ "R" (number), \ - 0, err, args) + number, err, args) #else /* !__mips16 */ # define INTERNAL_SYSCALL(name, err, nr, args...) \ internal_syscall##nr ("li\t%0, %2\t\t\t# " #name "\n\t", \ "IK" (SYS_ify (name)), \ - 0, err, args) + SYS_ify (name), err, args) # define INTERNAL_SYSCALL_NCS(number, err, nr, args...) \ internal_syscall##nr (MOVE32 "\t%0, %2\n\t", \ @@ -262,110 +275,65 @@ _sys_result; \ }) -/* We need to use a frame pointer for the functions in which we - adjust $sp around the syscall, or debug information and unwind - information will be $sp relative and thus wrong during the syscall. As - of GCC 4.7, this is sufficient. */ -#define FORCE_FRAME_POINTER \ - void *volatile __fp_force __attribute__ ((unused)) = alloca (4) +/* Out-of-line standard MIPS wrappers used for 5, 6, and 7 argument + syscalls, which require stack arguments. */ + +long long __nomips16 __mips_syscall5 (long arg1, long arg2, long arg3, + long arg4, long arg5, + long number); #define internal_syscall5(v0_init, input, number, err, \ arg1, arg2, arg3, arg4, arg5) \ ({ \ - long _sys_result; \ - \ - FORCE_FRAME_POINTER; \ - { \ - register long __s0 asm ("$16") __attribute__ ((unused)) \ - = (number); \ - register long __v0 asm ("$2"); \ - register long __a0 asm ("$4") = (long) (arg1); \ - register long __a1 asm ("$5") = (long) (arg2); \ - register long __a2 asm ("$6") = (long) (arg3); \ - register long __a3 asm ("$7") = (long) (arg4); \ - __asm__ volatile ( \ - ".set\tnoreorder\n\t" \ - "subu\t$29, 32\n\t" \ - "sw\t%6, 16($29)\n\t" \ - v0_init \ - "syscall\n\t" \ - "addiu\t$29, 32\n\t" \ - ".set\treorder" \ - : "=r" (__v0), "+r" (__a3) \ - : input, "r" (__a0), "r" (__a1), "r" (__a2), \ - "r" ((long) (arg5)) \ - : __SYSCALL_CLOBBERS); \ - err = __a3; \ - _sys_result = __v0; \ - } \ - _sys_result; \ + union __mips_syscall_return _sc_ret; \ + _sc_ret.val = __mips_syscall5 ((long) (arg1), \ + (long) (arg2), \ + (long) (arg3), \ + (long) (arg4), \ + (long) (arg5), \ + (long) (number)); \ + err = _sc_ret.reg.v1; \ + _sc_ret.reg.v0; \ }) +long long __nomips16 __mips_syscall6 (long arg1, long arg2, long arg3, + long arg4, long arg5, long arg6, + long number); + #define internal_syscall6(v0_init, input, number, err, \ arg1, arg2, arg3, arg4, arg5, arg6) \ ({ \ - long _sys_result; \ - \ - FORCE_FRAME_POINTER; \ - { \ - register long __s0 asm ("$16") __attribute__ ((unused)) \ - = (number); \ - register long __v0 asm ("$2"); \ - register long __a0 asm ("$4") = (long) (arg1); \ - register long __a1 asm ("$5") = (long) (arg2); \ - register long __a2 asm ("$6") = (long) (arg3); \ - register long __a3 asm ("$7") = (long) (arg4); \ - __asm__ volatile ( \ - ".set\tnoreorder\n\t" \ - "subu\t$29, 32\n\t" \ - "sw\t%6, 16($29)\n\t" \ - "sw\t%7, 20($29)\n\t" \ - v0_init \ - "syscall\n\t" \ - "addiu\t$29, 32\n\t" \ - ".set\treorder" \ - : "=r" (__v0), "+r" (__a3) \ - : input, "r" (__a0), "r" (__a1), "r" (__a2), \ - "r" ((long) (arg5)), "r" ((long) (arg6)) \ - : __SYSCALL_CLOBBERS); \ - err = __a3; \ - _sys_result = __v0; \ - } \ - _sys_result; \ + union __mips_syscall_return _sc_ret; \ + _sc_ret.val = __mips_syscall6 ((long) (arg1), \ + (long) (arg2), \ + (long) (arg3), \ + (long) (arg4), \ + (long) (arg5), \ + (long) (arg6), \ + (long) (number)); \ + err = _sc_ret.reg.v1; \ + _sc_ret.reg.v0; \ }) +long long __nomips16 __mips_syscall7 (long arg1, long arg2, long arg3, + long arg4, long arg5, long arg6, + long arg7, + long number); + #define internal_syscall7(v0_init, input, number, err, \ arg1, arg2, arg3, arg4, arg5, arg6, arg7) \ ({ \ - long _sys_result; \ - \ - FORCE_FRAME_POINTER; \ - { \ - register long __s0 asm ("$16") __attribute__ ((unused)) \ - = (number); \ - register long __v0 asm ("$2"); \ - register long __a0 asm ("$4") = (long) (arg1); \ - register long __a1 asm ("$5") = (long) (arg2); \ - register long __a2 asm ("$6") = (long) (arg3); \ - register long __a3 asm ("$7") = (long) (arg4); \ - __asm__ volatile ( \ - ".set\tnoreorder\n\t" \ - "subu\t$29, 32\n\t" \ - "sw\t%6, 16($29)\n\t" \ - "sw\t%7, 20($29)\n\t" \ - "sw\t%8, 24($29)\n\t" \ - v0_init \ - "syscall\n\t" \ - "addiu\t$29, 32\n\t" \ - ".set\treorder" \ - : "=r" (__v0), "+r" (__a3) \ - : input, "r" (__a0), "r" (__a1), "r" (__a2), \ - "r" ((long) (arg5)), "r" ((long) (arg6)), "r" ((long) (arg7)) \ - : __SYSCALL_CLOBBERS); \ - err = __a3; \ - _sys_result = __v0; \ - } \ - _sys_result; \ + union __mips_syscall_return _sc_ret; \ + _sc_ret.val = __mips_syscall7 ((long) (arg1), \ + (long) (arg2), \ + (long) (arg3), \ + (long) (arg4), \ + (long) (arg5), \ + (long) (arg6), \ + (long) (arg7), \ + (long) (number)); \ + err = _sc_ret.reg.v1; \ + _sc_ret.reg.v0; \ }) #define __SYSCALL_CLOBBERS "$1", "$3", "$8", "$9", "$10", "$11", "$12", "$13", \