This is the mail archive of the libc-alpha@sources.redhat.com mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

IA64 INLINE_SYSCALL Support


I found this patch
http://sources.redhat.com/ml/libc-hacker/2001-03/msg00061.html which I
have modified.

The most obvious problem with that patch is that on IA64 the returned
errno is not negative.  on a syscall return, r10 is set to -1 to
flag an error, and r8 then contains the return value or the positive
errno (this is not the case for internal kernel errors though, where
the errno convention follows the single value return for error and
errno, it's just de-multiplexed for return to userspace).

The less obvious problem is that using register variables (_r8 and
_r10 in the original) doesn't really work.  It seems to work some of
the time, but other times r8 manages to get it's self corrupted
somewhere between returning and going back to the calling function.

At any rate the attached modified patch works for me.

-i
ianw@gelato.unsw.edu.au

--- sysdeps/unix/sysv/linux/ia64/sysdep.h.old	2002-12-04 11:59:33.000000000 +1100
+++ sysdeps/unix/sysv/linux/ia64/sysdep.h	2002-12-03 16:35:24.000000000 +1100
@@ -102,11 +102,74 @@

 #else /* not __ASSEMBLER__ */

-/* Define a macro which expands into the inline wrapper code for a system
-   call.  */
-#if 0
-#undef INLINE_SYSCALL
-#define INLINE_SYSCALL(name, nr, args...)	__##name (args)
-#endif
+/* On IA-64 we have stacked registers for passing arguments.  The
+   "out" registers end up being the called function's "in"
+   registers.

+   Also, since we have plenty of registers we have two return values
+   from a syscall.  r10 is set to -1 on error, whilst r8 contains the
+   (non-negative) errno on error or the return value on success.
+*/
+#define INLINE_SYSCALL(name, nr, args...)			\
+  ({								\
+    int syscall = __NR_##name; /* r15 */			\
+    int retval; 	        /* r8  */			\
+    int error; 	        /* r10 */			\
+    LOAD_ARGS_##nr (args);					\
+    asm volatile (  "mov r15=%2\n\t" 				\
+		    "break %3;;\n\t"				\
+		    "mov %0=r8\n\t"				\
+		    "mov %1=r10\n\t" 				\
+                   : "=r" (retval), "=r" (error) 		\
+                   : "r"(syscall) , "i" (__BREAK_SYSCALL) 	\
+		   ASM_ARGS_##nr				\
+                   : "memory" ASM_CLOBBERS_##nr);		\
+     if (error == (long) -1)					\
+       {							\
+         __set_errno (retval);					\
+         retval = (long) -1;					\
+       }							\
+     (int) retval; })
+
+#define LOAD_ARGS_0()   do { } while (0)
+#define LOAD_ARGS_1(out0)				\
+  register long _out0 asm ("out0") = (long) (out0);	\
+  LOAD_ARGS_0 ()
+#define LOAD_ARGS_2(out0, out1)			\
+  register long _out1 asm ("out1") = (long) (out1);	\
+  LOAD_ARGS_1 (out0)
+#define LOAD_ARGS_3(out0, out1, out2)			\
+  register long _out2 asm ("out2") = (long) (out2);	\
+  LOAD_ARGS_2 (out0, out1)
+#define LOAD_ARGS_4(out0, out1, out2, out3)		\
+  register long _out3 asm ("out3") = (long) (out3);	\
+  LOAD_ARGS_3 (out0, out1, out2)
+#define LOAD_ARGS_5(out0, out1, out2, out3, out4)	\
+  register long _out4 asm ("out4") = (long) (out4);	\
+  LOAD_ARGS_4 (out0, out1, out2, out3)
+
+#define ASM_ARGS_0
+#define ASM_ARGS_1      ASM_ARGS_0, "r" (_out0)
+#define ASM_ARGS_2      ASM_ARGS_1, "r" (_out1)
+#define ASM_ARGS_3      ASM_ARGS_2, "r" (_out2)
+#define ASM_ARGS_4      ASM_ARGS_3, "r" (_out3)
+#define ASM_ARGS_5      ASM_ARGS_4, "r" (_out4)
+
+#define ASM_CLOBBERS_0	ASM_CLOBBERS_1, "out0"
+#define ASM_CLOBBERS_1	ASM_CLOBBERS_2, "out1"
+#define ASM_CLOBBERS_2	ASM_CLOBBERS_3, "out2"
+#define ASM_CLOBBERS_3	ASM_CLOBBERS_4, "out3"
+#define ASM_CLOBBERS_4	ASM_CLOBBERS_5, "out4"
+#define ASM_CLOBBERS_5	, "out5", "out6", "out7",			\
+  /* Non-stacked integer registers, minus r8, r10, r15.  */		\
+  "r2", "r3", "r9", "r11", "r12", "r13", "r14", "r16", "r17", "r18",	\
+  "r19", "r20", "r21", "r22", "r23", "r24", "r25", "r26", "r27",	\
+  "r28", "r29", "r30", "r31",						\
+  /* Predicate registers.  */						\
+  "p6", "p7", "p8", "p9", "p10", "p11", "p12", "p13", "p14", "p15",	\
+  /* Non-rotating fp registers.  */					\
+  "f6", "f7", "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",	\
+  /* Branch registers.  */						\
+  "b6", "b7"
+
 #endif /* not __ASSEMBLER__ */


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]