# This patch contains various fixes for the thumb code handling in GCC 3.4.4
#
# Most of these are minor fixes to code which is either missing (Linux thumb
# div0, thumb clear instruction cache) or uses the wrong return mechanism
# (libffi)
#
# There is also a significant design problem with the _call_via_rx code -
# it cannot be in a shared library because a call via PLT simply won't
# work (for _call_via_ip) and is very inefficient anyway.
#
# This is fixed in uclibc simply by incorporating the code into crti.S
# (an extra 30 bytes for the 15 functions) even though not all link units
# require all the code - there is so little of it.  That doesn't work with
# the crti.asm here because it is linked with libgcc.a which already defines
# these symbols
#
--- gcc-3.4.4/gcc/config/arm/t-linux.orig	2005-08-09 08:55:02.181797492 -0700
+++ gcc-3.4.4/gcc/config/arm/t-linux	2005-08-09 08:58:22.766419486 -0700
@@ -7,6 +7,7 @@
 LIB1ASMFUNCS = _udivsi3 _divsi3 _umodsi3 _modsi3 _dvmd_lnx \
 	_negdf2 _addsubdf3 _muldivdf3 _cmpdf2 _unorddf2 _fixdfsi _fixunsdfsi \
 	_truncdfsf2 _negsf2 _addsubsf3 _muldivsf3 _cmpsf2 _unordsf2 \
+	_call_via_rX \
 	_fixsfsi _fixunssfsi
 
 # MULTILIB_OPTIONS = mhard-float/msoft-float
--- gcc-3.4.4/.pc/gcc34-thumb-support.patch/gcc/config/arm/lib1funcs.asm	2004-01-15 08:56:34.000000000 -0800
+++ gcc-3.4.4/gcc/config/arm/lib1funcs.asm	2005-09-21 21:32:03.376927755 -0700
@@ -811,13 +811,18 @@
 
 /* Constants taken from <asm/unistd.h> and <asm/signal.h> */
 #define SIGFPE	8
+#if !defined __thumb__
 #define __NR_SYSCALL_BASE	0x900000
+#else
+#define __NR_SYSCALL_BASE	0
+#endif
 #define __NR_getpid			(__NR_SYSCALL_BASE+ 20)
 #define __NR_kill			(__NR_SYSCALL_BASE+ 37)
 
 	.code	32
 	FUNC_START div0
 
+#if ! defined __thumb__
 	stmfd	sp!, {r1, lr}
 	swi	__NR_getpid
 	cmn	r0, #1000
@@ -825,6 +830,28 @@
 	mov	r1, #SIGFPE
 	swi	__NR_kill
 	RETLDM	r1
+#else
+	push	{r1, r7, lr}
+	mov	r7, #__NR_getpid
+	swi	0
+	@ above the compare is with -1000, but the standard syscall
+	@ macro checks for -1..-125
+	add	r0, #125
+	bcs	90f
+	sub	r0, #125
+	mov	r1, #SIGFPE
+	mov	r7, #__NR_kill
+	swi	0
+90:	
+#if __ARM_ARCH__ > 4
+	pop	{r1, r7, pc}
+#else
+	@ on 4T that won't work
+	pop	{r1, r7}
+	pop	{r3}
+	bx	r3
+#endif
+#endif
 
 	FUNC_END div0
 	
@@ -845,14 +872,14 @@
    code here switches to the correct mode before executing the function.  */
 	
 	.text
-	.align 0
+	.align 1
         .force_thumb
 
 .macro call_via register
 	THUMB_FUNC_START _call_via_\register
+	.hidden	SYM (_call_via_\register)
 
 	bx	\register
-	nop
 
 	SIZE	(_call_via_\register)
 .endm
@@ -903,6 +930,7 @@
 	.code	16
 
 	THUMB_FUNC_START _interwork_call_via_\register
+	.hidden	SYM (_interwork_call_via_\register)
 
 	bx	pc
 	nop
--- gcc-3.4.4/.pc/gcc34-thumb-support.patch/gcc/config/arm/linux-gas.h	2003-06-19 14:47:06.000000000 -0700
+++ gcc-3.4.4/gcc/config/arm/linux-gas.h	2005-09-20 16:09:55.027862200 -0700
@@ -56,6 +56,7 @@
 
 /* Clear the instruction cache from `beg' to `end'.  This makes an
    inline system call to SYS_cacheflush.  */
+#if !defined(__thumb__)
 #define CLEAR_INSN_CACHE(BEG, END)					\
 {									\
   register unsigned long _beg __asm ("a1") = (unsigned long) (BEG);	\
@@ -65,3 +66,18 @@
 		    : "=r" (_beg)					\
 		    : "0" (_beg), "r" (_end), "r" (_flg));		\
 }
+#else
+#define CLEAR_INSN_CACHE(BEG, END)					\
+{									\
+  register unsigned long _beg __asm ("a1") = (unsigned long) (BEG);	\
+  register unsigned long _end __asm ("a2") = (unsigned long) (END);	\
+  register unsigned long _flg __asm ("a3") = 0;				\
+  register unsigned long _swi __asm ("a4") = 0xf0002;			\
+  __asm __volatile ("push	{r7}\n"					\
+		"	mov	r7,a4\n"				\
+		"	swi	0	@ sys_cacheflush\n"		\
+		"	pop	{r7}\n"					\
+		    : "=r" (_beg)					\
+		    : "0" (_beg), "r" (_end), "r" (_flg), "r" (_swi));	\
+}
+#endif
--- gcc-3.4.4/.pc/gcc34-thumb-support.patch/libffi/src/arm/sysv.S	2003-10-21 12:01:55.000000000 -0700
+++ gcc-3.4.4/libffi/src/arm/sysv.S	2005-09-20 16:09:55.027862200 -0700
@@ -41,6 +41,14 @@
 #define ENTRY(x) .globl CNAME(x); .type CNAME(x),%function; CNAME(x):
 #endif
 	
+/* Get the correct return instruction */
+#if defined(__ARM_ARCH_4T__) || defined(__ARM_ARCH_5__) \
+	|| defined(__ARM_ARCH_5T__) || defined(__ARM_ARCH_5TE__)
+#define RET bx r
+#else
+#define RET mov pc,
+#endif
+
 .text
 
 	# a1:   ffi_prep_args
@@ -66,7 +74,7 @@
 
 	# And call
 	mov   lr, pc
-	mov   pc, ip
+	RET   ip
 
 	# move first 4 parameters in registers
 	ldr   a1, [sp, #0]
