summaryrefslogtreecommitdiff
path: root/recipes/uclibc/uclibc-0.9.28/thumb-swi-r7.patch
blob: 330ceb6869ec1e5d801fe9714f11e74139b5d010 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# This is a work round for a fairly serious GCC compiler bug - when
# the syscall assembler overwrites r7 (required on thumb) the
# compiler fails to protect the register when it is using it as a
# frame pointer.
#
--- uClibc-0.9.28/libc/sysdeps/linux/arm/bits/syscalls.h	2005-09-12 17:51:26.062205918 -0700
+++ uClibc-0.9.28/libc/sysdeps/linux/arm/bits/syscalls.h	2005-09-12 18:16:15.507930828 -0700
@@ -111,6 +111,11 @@
      }								\
      (int) _sys_result; })
 #else
+#if 0
+/* This doesn't work because GCC uses r7 as a frame pointer in
+ * some cases and doesn't notice that the _r7 value changes
+ * it, resulting in mysterious crashes after the SWI.
+ */
 #define INTERNAL_SYSCALL(name, err, nr, args...)		\
   ({ unsigned int _sys_result;					\
      {								\
@@ -124,6 +129,28 @@
        _sys_result = _a1;					\
      }								\
      (int) _sys_result; })
+#else
+/* So hide the use of r7 from the compiler, this would be a lot
+ * easier but for the fact that the syscalls can exceed 255.
+ * For the moment the LOAD_ARG_7 is sacrificed.
+ */
+#define INTERNAL_SYSCALL(name, err, nr, args...)		\
+  ({ unsigned int _sys_result;					\
+     {								\
+       register int _a1 asm ("a1");				\
+       LOAD_ARGS_##nr (args)					\
+       register int _v3 asm ("v3") = (int) (SYS_ify(name));	\
+       asm volatile ("push	{r7}\n"				\
+	       	     "\tmov	r7, v3\n"			\
+	       	     "\tswi	0	@ syscall " #name "\n"	\
+		     "\tpop	{r7}"				\
+		     : "=r" (_a1)				\
+		     : "r" (_v3) ASM_ARGS_##nr			\
+		     : "memory");				\
+       _sys_result = _a1;					\
+     }								\
+     (int) _sys_result; })
+#endif
 #endif
 
 #undef INTERNAL_SYSCALL_ERROR_P