This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
Re: [PATCH] mips/o32: fix internal_syscall5/6/7
On 2017-08-17 18:09, Adhemerval Zanella wrote:
>
>
> On 17/08/2017 17:34, Maciej W. Rozycki wrote:
> > On Thu, 17 Aug 2017, Adhemerval Zanella wrote:
> >
> >> My point is I think we should aim for compiler optimization safeness
> >> (to avoid code breakage over compiler defined default flags) and taking
> >> as base current approach to *avoid* VLA on GLIBC I do not think it is
> >> good approach to use it as a bridge to force GCC to generate the expected
> >> code.
> >
> > You certainly have a point here overall, although I don't think a VLA
> > whose size is always 0 really hurts. And we've used the approach with
> > `alloca' since forever with no adverse effects until we added a place
> > where the caller invokes the syscall wrapper in a loop. So I wouldn't
> > necessarily call it an issue. Mind that this is target-specific code, so
> > we can rely on a target-specific execution model rather than limiting
> > ourselves to what generic ISO C guarantees.
> >
> > Aurelien's figures indicating a clear size reduction certainly count as a
> > pro though.
>
> Joseph pointed out another advantage of avoid VLAs (building with
> -Werror=alloca -Werror=vla). My main problem here is we are betting that
> compiler won't mess with our assumptions and generate the desirable code
> without trying to adhere what it is suppose to provide. Target generic
> ISO C give us a better guarantee and any deviation indicates a possible
> compiler issue, not otherwise (such this case). My another point is we
> can optimize if required later if this is the case and imho this is hardly
> the case here (at least for latency).
>
> If I understood correctly Aurelien's suggestion of returning err in v1
> is not ABI strictly so it will end up calling __libc_do_syscall with a
> non-conformant ABI convention (similar to pipe implementation where requires
> assembly specific implementation for a lot of architectures to get this
> right). Again this is something I would really to avoid.
>
> >
> >> I still thinking trying to optimize for 5/6/7 syscall argument is over
> >> engineering in this *specific* case. As I put in my last message,
> >> 5/6/7 argument syscalls are used for
> >>
> >> pread, pwrite, lseek, llseek, ppoll, posix_fadvice, posix_fallocate,
> >> sync_file_range, fallocate, preadv, pwritev, preadv2, pwritev2, select,
> >> pselect, mmap, readahead, epoll_pwait, splice, recvfrom, sendto, recvmmsg,
> >> msgsnd, msgrcv, msgget, msgctl, semop, semget, semctl, semtimedop, shmat,
> >> shmdt, shmget, and shmctl.
> >>
> >> Which are the one generated from C implementation (some are still auto
> >> generated). The majority of them are blocking syscalls, so both context
> >> switch plus the required work for syscall completion itself will taking
> >> proportionally all the required time. So trying to squeeze some cycles
> >> don't really pay off comparing to code maintainability (just all this
> >> discussion of which C construct would be safe enough to generate the
> >> correct stack spill plus the current issue should indicate we should
> >> aim for correctness first).
> >
> > TBH, I find it questionable whether it's really the approach I proposed
> > that requires more engineering (and long-term maintenance) effort rather
> > than using a separate handwritten assembly-language call stub. Especially
> > if a non-standard calling convention is used.
>
> IMHO I find the VLA suggestion more fragile in long term.
>
> >
> > If everyone but me thinks there's a clear advantage in using such a
> > handcoded stub though, then as I previously noted please adjust the
> > affected MIPS16 stubs to avoid the extra indirection, i.e. you can call
> > `__libc_do_syscall' directly from MIPS16 code as you'd do from regular
> > MIPS or microMIPS code, as the lone reason for the existence of the MIPS16
> > stubs is the inexistence of a MIPS16 SYSCALL instruction.
>
> Ok, I will try to at least check it on qemu. If you have any points on how
> correctly build a mips16 glibc it could be helpful.
The patch below, based on Adhemerval's version should do it. The changes
I have done:
- return err through v1 instead of using a negative value
- fix build of mips16-syscallX.c
- route mips16 syscalls with 5 to 7th arguments through __libc_do_syscall
I see no regression on mipsel o32. I have only lightly tested mips o32
(the testsuite is still running). I haven't been able to fully compile
mips16 due to the following error compiling dl-tunables.c:
/tmp/ccI2NMgJ.s: Assembler messages:
/tmp/ccI2NMgJ.s:1376: Error: branch to a symbol in another ISA mode
It doesn't seem to be related to my changes.
Aurelien
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/Makefile b/sysdeps/unix/sysv/linux/mips/mips32/Makefile
index 33b461500c..cbdf032c3a 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/Makefile
+++ b/sysdeps/unix/sysv/linux/mips/mips32/Makefile
@@ -1,8 +1,26 @@
+ifeq ($(subdir),elf)
+sysdep-dl-routines += libc-do-syscall
+endif
+
ifeq ($(subdir),conform)
# For bugs 17786 and 21278.
conformtest-xfail-conds += mips-o32-linux
endif
+ifeq ($(subdir),io)
+sysdep_routines += libc-do-syscall
+endif
+
+ifeq ($(subdir),nptl)
+libpthread-sysdep_routines += libc-do-syscall
+libpthread-shared-only-routines += libc-do-syscall
+endif
+
+ifeq ($(subdir),rt)
+librt-sysdep_routines += libc-do-syscall
+librt-shared-only-routines += libc-do-syscall
+endif
+
ifeq ($(subdir),stdlib)
tests += bug-getcontext-mips-gp
endif
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/libc-do-syscall.S b/sysdeps/unix/sysv/linux/mips/mips32/libc-do-syscall.S
new file mode 100644
index 0000000000..c02f507008
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/mips/mips32/libc-do-syscall.S
@@ -0,0 +1,52 @@
+/* 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 <sys/asm.h>
+#include <sysdep.h>
+#include <asm/unistd.h>
+#include <sgidefs.h>
+
+
+/* long int __libc_do_syscall (long int, ...) */
+
+#define FRAMESZ 32
+
+ .text
+ .set nomips16
+ .hidden __libc_do_syscall
+ENTRY(__libc_do_syscall)
+ move v0, a0
+ move a0, a1
+ move a1, a2
+ move a2, a3
+ lw a3, 16(sp)
+ lw t0, 20(sp)
+ lw t1, 24(sp)
+ lw t2, 28(sp)
+ .set noreorder
+ PTR_SUBU sp, FRAMESZ
+ cfi_adjust_cfa_offset (FRAMESZ)
+ sw t0, 16(sp)
+ sw t1, 20(sp)
+ sw t2, 24(sp)
+ syscall
+ PTR_ADDU sp, FRAMESZ
+ cfi_adjust_cfa_offset (-FRAMESZ)
+ .set reorder
+ move v1, a3
+1: ret
+END (__libc_do_syscall)
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/mips16/Makefile b/sysdeps/unix/sysv/linux/mips/mips32/mips16/Makefile
index fa9fcb7e6f..6869bf4f7c 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/mips16/Makefile
+++ b/sysdeps/unix/sysv/linux/mips/mips32/mips16/Makefile
@@ -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
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/mips16/Versions b/sysdeps/unix/sysv/linux/mips/mips32/mips16/Versions
index 73bcfb566c..bb21747f44 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/mips16/Versions
+++ b/sysdeps/unix/sysv/linux/mips/mips32/mips16/Versions
@@ -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;
}
}
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall.h b/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall.h
index 880e9908e8..60f856d248 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall.h
+++ b/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall.h
@@ -21,17 +21,6 @@
#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))
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall0.c b/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall0.c
index 490245b34e..b9f78e875f 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall0.c
+++ b/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall0.c
@@ -24,7 +24,7 @@
long long __nomips16
__mips16_syscall0 (long number)
{
- union __mips16_syscall_return ret;
+ union __libc_do_syscall_return ret;
ret.reg.v0 = INTERNAL_SYSCALL_MIPS16 (number, ret.reg.v1, 0);
return ret.val;
}
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall1.c b/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall1.c
index 3061e8accb..284ce712cc 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall1.c
+++ b/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall1.c
@@ -25,7 +25,7 @@ long long __nomips16
__mips16_syscall1 (long a0,
long number)
{
- union __mips16_syscall_return ret;
+ union __libc_do_syscall_return ret;
ret.reg.v0 = INTERNAL_SYSCALL_MIPS16 (number, ret.reg.v1, 1,
a0);
return ret.val;
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall2.c b/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall2.c
index 440a4ed285..4e76329239 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall2.c
+++ b/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall2.c
@@ -25,7 +25,7 @@ long long __nomips16
__mips16_syscall2 (long a0, long a1,
long number)
{
- union __mips16_syscall_return ret;
+ union __libc_do_syscall_return ret;
ret.reg.v0 = INTERNAL_SYSCALL_MIPS16 (number, ret.reg.v1, 2,
a0, a1);
return ret.val;
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall3.c b/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall3.c
index c3f83fc1f6..dbb31d2f20 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall3.c
+++ b/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall3.c
@@ -25,7 +25,7 @@ long long __nomips16
__mips16_syscall3 (long a0, long a1, long a2,
long number)
{
- union __mips16_syscall_return ret;
+ union __libc_do_syscall_return ret;
ret.reg.v0 = INTERNAL_SYSCALL_MIPS16 (number, ret.reg.v1, 3,
a0, a1, a2);
return ret.val;
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall4.c b/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall4.c
index 496297d296..a5dade3b3f 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall4.c
+++ b/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall4.c
@@ -25,7 +25,7 @@ long long __nomips16
__mips16_syscall4 (long a0, long a1, long a2, long a3,
long number)
{
- union __mips16_syscall_return ret;
+ union __libc_do_syscall_return ret;
ret.reg.v0 = INTERNAL_SYSCALL_MIPS16 (number, ret.reg.v1, 4,
a0, a1, a2, a3);
return ret.val;
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall5.c b/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall5.c
deleted file mode 100644
index ad265d88e2..0000000000
--- a/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall5.c
+++ /dev/null
@@ -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;
-}
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall6.c b/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall6.c
deleted file mode 100644
index bfbd395ed3..0000000000
--- a/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall6.c
+++ /dev/null
@@ -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;
-}
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall7.c b/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall7.c
deleted file mode 100644
index e1267616dc..0000000000
--- a/sysdeps/unix/sysv/linux/mips/mips32/mips16/mips16-syscall7.c
+++ /dev/null
@@ -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;
-}
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/sysdep.h b/sysdeps/unix/sysv/linux/mips/mips32/sysdep.h
index e9e3ee7e82..8e55538a5c 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/sysdep.h
+++ b/sysdeps/unix/sysv/linux/mips/mips32/sysdep.h
@@ -49,9 +49,9 @@
/* Define a macro which expands into the inline wrapper code for a system
call. */
#undef INLINE_SYSCALL
-#define INLINE_SYSCALL(name, nr, args...) \
+#define INLINE_SYSCALL(name, nr, ...) \
({ INTERNAL_SYSCALL_DECL (_sc_err); \
- long result_var = INTERNAL_SYSCALL (name, _sc_err, nr, args); \
+ long result_var = INTERNAL_SYSCALL (name, _sc_err, nr, ## __VA_ARGS__); \
if ( INTERNAL_SYSCALL_ERROR_P (result_var, _sc_err) ) \
{ \
__set_errno (INTERNAL_SYSCALL_ERRNO (result_var, _sc_err)); \
@@ -98,6 +98,19 @@
#undef INTERNAL_SYSCALL
#undef INTERNAL_SYSCALL_NCS
+long long __attribute__ ((nomips16)) __libc_do_syscall (long int, ...) attribute_hidden;
+
+union __libc_do_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,
@@ -107,13 +120,16 @@
# include <mips16-syscall.h>
-# define INTERNAL_SYSCALL(name, err, nr, args...) \
- INTERNAL_SYSCALL_NCS (SYS_ify (name), err, nr, args)
+# define INTERNAL_SYSCALL(name, err, nr, ...) \
+ INTERNAL_SYSCALL_NCS (SYS_ify (name), err, nr, ## __VA_ARGS__)
-# define INTERNAL_SYSCALL_NCS(number, err, nr, args...) \
+# define INTERNAL_SYSCALL_NCS(number, err, nr, ...) \
({ \
- union __mips16_syscall_return _sc_ret; \
- _sc_ret.val = __mips16_syscall##nr (args, number); \
+ union __libc_do_syscall_return _sc_ret; \
+ if (nr <= 4) \
+ _sc_ret.val = __mips16_syscall##nr (__VA_ARGS__, number); \
+ else \
+ _sc_ret.val = __libc_do_syscall (number, ## __VA_ARGS__); \
err = _sc_ret.reg.v1; \
_sc_ret.reg.v0; \
})
@@ -121,13 +137,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", \
@@ -136,6 +152,7 @@
#endif /* !__mips16 */
+
#define internal_syscall0(v0_init, input, number, err, dummy...) \
({ \
long _sys_result; \
@@ -262,110 +279,34 @@
_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)
-
#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 __libc_do_syscall_return _sys_result; \
+ _sys_result.val = __libc_do_syscall (number, arg1, arg2, arg3, \
+ arg4, arg5); \
+ err = _sys_result.reg.v1; \
+ _sys_result.reg.v0; \
})
#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 __libc_do_syscall_return _sys_result; \
+ _sys_result.val = __libc_do_syscall (number, arg1, arg2, arg3, \
+ arg4, arg5, arg6); \
+ err = _sys_result.reg.v1; \
+ _sys_result.reg.v0; \
})
#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 __libc_do_syscall_return _sys_result; \
+ _sys_result.val = __libc_do_syscall (number, arg1, arg2, arg3, \
+ arg4, arg5, arg6, arg7); \
+ err = _sys_result.reg.v1; \
+ _sys_result.reg.v0; \
})
#define __SYSCALL_CLOBBERS "$1", "$3", "$8", "$9", "$10", "$11", "$12", "$13", \
--
Aurelien Jarno GPG: 4096R/1DDD8C9B
aurelien@aurel32.net http://www.aurel32.net