mips/o32: fix internal_syscall5/6/7

Message ID alpine.DEB.2.00.1708192131080.17596@tp.orcam.me.uk
State Superseded
Headers

Commit Message

Maciej W. Rozycki Aug. 21, 2017, 10:48 a.m. UTC
  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'.

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.

  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
  

Comments

Adhemerval Zanella Aug. 21, 2017, 2:30 p.m. UTC | #1
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", \
>
  
Aurelien Jarno Aug. 22, 2017, 8:24 a.m. UTC | #2
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
  
Maciej W. Rozycki Aug. 22, 2017, 10:07 a.m. UTC | #3
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
  
Maciej W. Rozycki Aug. 30, 2017, 3:35 p.m. UTC | #4
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
  
Aurelien Jarno Aug. 30, 2017, 8:33 p.m. UTC | #5
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!
  

Patch

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", \