aboutsummaryrefslogtreecommitdiff
path: root/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h')
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h131
1 files changed, 60 insertions, 71 deletions
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h b/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h
index d56ff877ac..d37be2ef4f 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h
@@ -69,65 +69,7 @@
#endif /* __ASSEMBLER__ */
#undef INLINE_SYSCALL
-#if 1
-#define INLINE_SYSCALL(name, nr, args...) \
- ({ \
- DECLARGS_##nr; \
- long ret, err; \
- LOADARGS_##nr(name, args); \
- __asm __volatile ("sc\n\t" \
- "mfcr %1\n\t" \
- : "=r" (r3), "=r" (err) \
- : ASM_INPUT_##nr \
- : "cc", "memory"); \
- ret = r3; \
- if (err & 1 << 28) \
- { \
- __set_errno (ret); \
- ret = -1L; \
- } \
- ret; \
- })
-
-#define DECLARGS_0 register long r0 __asm__ ("r0"); \
- register long r3 __asm__ ("r3")
-#define DECLARGS_1 DECLARGS_0
-#define DECLARGS_2 DECLARGS_1; register long r4 __asm__ ("r4")
-#define DECLARGS_3 DECLARGS_2; register long r5 __asm__ ("r5")
-#define DECLARGS_4 DECLARGS_3; register long r6 __asm__ ("r6")
-#define DECLARGS_5 DECLARGS_4; register long r7 __asm__ ("r7")
-#define DECLARGS_6 DECLARGS_5; register long r8 __asm__ ("r8")
-
-#define LOADARGS_0(name) \
- r0 = __NR_##name
-#define LOADARGS_1(name, arg1) \
- LOADARGS_0(name); \
- r3 = (long) (arg1)
-#define LOADARGS_2(name, arg1, arg2) \
- LOADARGS_1(name, arg1); \
- r4 = (long) (arg2)
-#define LOADARGS_3(name, arg1, arg2, arg3) \
- LOADARGS_2(name, arg1, arg2); \
- r5 = (long) (arg3)
-#define LOADARGS_4(name, arg1, arg2, arg3, arg4) \
- LOADARGS_3(name, arg1, arg2, arg3); \
- r6 = (long) (arg4)
-#define LOADARGS_5(name, arg1, arg2, arg3, arg4, arg5) \
- LOADARGS_4(name, arg1, arg2, arg3, arg4); \
- r7 = (long) (arg5)
-#define LOADARGS_6(name, arg1, arg2, arg3, arg4, arg5, arg6) \
- LOADARGS_5(name, arg1, arg2, arg3, arg4, arg5); \
- r8 = (long) (arg6)
-
-#define ASM_INPUT_0 "r" (r0)
-#define ASM_INPUT_1 ASM_INPUT_0, "0" (r3)
-#define ASM_INPUT_2 ASM_INPUT_1, "r" (r4)
-#define ASM_INPUT_3 ASM_INPUT_2, "r" (r5)
-#define ASM_INPUT_4 ASM_INPUT_3, "r" (r6)
-#define ASM_INPUT_5 ASM_INPUT_4, "r" (r7)
-#define ASM_INPUT_6 ASM_INPUT_5, "r" (r8)
-#else
/* This version is for kernels that implement system calls that
behave like function calls as far as register saving. */
#define INLINE_SYSCALL(name, nr, args...) \
@@ -149,40 +91,89 @@
: ASM_INPUT_##nr \
: "r9", "r10", "r11", "r12", \
"fr0", "fr1", "fr2", "fr3", \
- "fr4", "fr5", "fr6", "fr7", \
- "fr8", "fr9", "fr10", "fr11", \
- "fr12", "fr13", \
- "ctr", "lr", \
- "cr0", "cr1", "cr5", "cr6", "cr7", \
- "memory"); \
+ "fr4", "fr5", "fr6", "fr7", \
+ "fr8", "fr9", "fr10", "fr11", \
+ "fr12", "fr13", \
+ "ctr", "lr", \
+ "cr0", "cr1", "cr5", "cr6", "cr7", \
+ "memory"); \
ret = r3; \
- if (err & 1 << 28) \
+ if (__builtin_expect ((err & (1 << 28)), 0)) \
{ \
- __set_errno (ret); \
- ret = -1L; \
+ __set_errno (ret); \
+ ret = -1L; \
} \
ret; \
})
-#define LOADARGS_0(name) \
+/* Define a macro which expands inline into the wrapper code for a system
+ call. This use is for internal calls that do not need to handle errors
+ normally. It will never touch errno. This returns just what the kernel
+ gave back in the non-error (CR0.SO cleared) case, otherwise (CR0.SO set)
+ the negation of the return value in the kernel gets reverted. */
+
+# undef INTERNAL_SYSCALL
+# define INTERNAL_SYSCALL(name, nr, args...) \
+ ({ \
+ register long r0 __asm__ ("r0"); \
+ register long r3 __asm__ ("r3"); \
+ register long r4 __asm__ ("r4"); \
+ register long r5 __asm__ ("r5"); \
+ register long r6 __asm__ ("r6"); \
+ register long r7 __asm__ ("r7"); \
+ register long r8 __asm__ ("r8"); \
+ LOADARGS_##nr(name, args); \
+ __asm__ __volatile__ \
+ ("sc\n\t" \
+ "bns+ 0f\n\t" \
+ "neg %1,%1\n" \
+ "0:" \
+ : "=&r" (r0), \
+ "=&r" (r3), "=&r" (r4), "=&r" (r5), \
+ "=&r" (r6), "=&r" (r7), "=&r" (r8) \
+ : ASM_INPUT_##nr \
+ : "r9", "r10", "r11", "r12", \
+ "cr0", "ctr", "memory"); \
+ (int) r3; \
+ })
+
+# undef INTERNAL_SYSCALL_ERROR_P
+# define INTERNAL_SYSCALL_ERROR_P(val) ((unsigned long) (val) >= 0xfffffffffffff001u)
+
+# undef INTERNAL_SYSCALL_ERRNO
+# define INTERNAL_SYSCALL_ERRNO(val) (-(val))
+
+#define LOADARGS_0(name, dummy) \
r0 = __NR_##name
#define LOADARGS_1(name, arg1) \
- LOADARGS_0(name); \
+ LOADARGS_0(name, 0); \
+ extern void __illegally_sized_syscall_##name##_arg1 (void); \
+ if (sizeof (arg1) > 8) __illegally_sized_syscall_##name##_arg1 (); \
r3 = (long) (arg1)
#define LOADARGS_2(name, arg1, arg2) \
LOADARGS_1(name, arg1); \
+ extern void __illegally_sized_syscall_##name##_arg2 (void); \
+ if (sizeof (arg2) > 8) __illegally_sized_syscall_##name##_arg2 (); \
r4 = (long) (arg2)
#define LOADARGS_3(name, arg1, arg2, arg3) \
LOADARGS_2(name, arg1, arg2); \
+ extern void __illegally_sized_syscall_##name##_arg3 (void); \
+ if (sizeof (arg3) > 8) __illegally_sized_syscall_##name##_arg3 (); \
r5 = (long) (arg3)
#define LOADARGS_4(name, arg1, arg2, arg3, arg4) \
LOADARGS_3(name, arg1, arg2, arg3); \
+ extern void __illegally_sized_syscall_##name##_arg4 (void); \
+ if (sizeof (arg4) > 8) __illegally_sized_syscall_##name##_arg4 (); \
r6 = (long) (arg4)
#define LOADARGS_5(name, arg1, arg2, arg3, arg4, arg5) \
LOADARGS_4(name, arg1, arg2, arg3, arg4); \
+ extern void __illegally_sized_syscall_##name##_arg5 (void); \
+ if (sizeof (arg5) > 8) __illegally_sized_syscall_##name##_arg5 (); \
r7 = (long) (arg5)
#define LOADARGS_6(name, arg1, arg2, arg3, arg4, arg5, arg6) \
LOADARGS_5(name, arg1, arg2, arg3, arg4, arg5); \
+ extern void __illegally_sized_syscall_##name##_arg6 (void); \
+ if (sizeof (arg6) > 8) __illegally_sized_syscall_##name##_arg6 (); \
r8 = (long) (arg6)
#define ASM_INPUT_0 "0" (r0)
@@ -193,6 +184,4 @@
#define ASM_INPUT_5 ASM_INPUT_4, "5" (r7)
#define ASM_INPUT_6 ASM_INPUT_5, "6" (r8)
-#endif
-
#endif /* linux/powerpc/powerpc64/sysdep.h */