Index: gcc-fsf-trunk-quilt/libgcc/config.host
===================================================================
--- gcc-fsf-trunk-quilt.orig/libgcc/config.host	2013-08-16 20:19:15.000000000 +0100
+++ gcc-fsf-trunk-quilt/libgcc/config.host	2013-08-16 20:21:23.568799943 +0100
@@ -741,13 +741,13 @@ mips*-*-linux*)				# Linux MIPS, either 
 	extra_parts="$extra_parts crtfastmath.o"
 	tmake_file="${tmake_file} t-crtfm"
 	case ${host} in
-		mips64r5900* | mipsr5900*)
-			# The MIPS16 support code uses floating point
-			# instructions that are not supported on r5900.
-			;;
-		*)
-			tmake_file="${tmake_file} mips/t-mips16"
-			;;
+	  mips64r5900* | mipsr5900*)
+	    # The MIPS16 support code uses floating point
+	    # instructions that are not supported on r5900.
+	    ;;
+	  *)
+	    tmake_file="${tmake_file} mips/t-mips16 t-slibgcc-libgcc"
+	    ;;
 	esac
 	md_unwind_header=mips/linux-unwind.h
 	if test "${ac_cv_sizeof_long_double}" = 16; then
Index: gcc-fsf-trunk-quilt/libgcc/config/mips/libgcc-mips16.ver
===================================================================
--- gcc-fsf-trunk-quilt.orig/libgcc/config/mips/libgcc-mips16.ver	2013-08-16 22:41:01.000000000 +0100
+++ gcc-fsf-trunk-quilt/libgcc/config/mips/libgcc-mips16.ver	2013-08-16 22:41:09.617705885 +0100
@@ -45,42 +45,4 @@ GCC_4.4.0 {
   __mips16_floatsidf
   __mips16_floatunsidf
   __mips16_fix_truncdfsi
-  __mips16_ret_sf
-  __mips16_ret_sc
-  __mips16_ret_df
-  __mips16_ret_dc
-  __mips16_call_stub_1
-  __mips16_call_stub_5
-  __mips16_call_stub_2
-  __mips16_call_stub_6
-  __mips16_call_stub_9
-  __mips16_call_stub_10
-  __mips16_call_stub_sf_0
-  __mips16_call_stub_sf_1
-  __mips16_call_stub_sf_5
-  __mips16_call_stub_sf_2
-  __mips16_call_stub_sf_6
-  __mips16_call_stub_sf_9
-  __mips16_call_stub_sf_10
-  __mips16_call_stub_sc_0
-  __mips16_call_stub_sc_1
-  __mips16_call_stub_sc_5
-  __mips16_call_stub_sc_2
-  __mips16_call_stub_sc_6
-  __mips16_call_stub_sc_9
-  __mips16_call_stub_sc_10
-  __mips16_call_stub_df_0
-  __mips16_call_stub_df_1
-  __mips16_call_stub_df_5
-  __mips16_call_stub_df_2
-  __mips16_call_stub_df_6
-  __mips16_call_stub_df_9
-  __mips16_call_stub_df_10
-  __mips16_call_stub_dc_0
-  __mips16_call_stub_dc_1
-  __mips16_call_stub_dc_5
-  __mips16_call_stub_dc_2
-  __mips16_call_stub_dc_6
-  __mips16_call_stub_dc_9
-  __mips16_call_stub_dc_10
 }
Index: gcc-fsf-trunk-quilt/libgcc/config/mips/mips16.S
===================================================================
--- gcc-fsf-trunk-quilt.orig/libgcc/config/mips/mips16.S	2013-08-16 20:06:14.000000000 +0100
+++ gcc-fsf-trunk-quilt/libgcc/config/mips/mips16.S	2013-08-16 20:21:23.568799943 +0100
@@ -479,13 +479,35 @@ STARTFN (__mips16_fix_truncdfsi)
 #endif
 #endif /* !__mips_single_float */
 
+/* We don't export stubs from libgcc_s.so and always require static
+   versions to be pulled from libgcc.a as needed because they use $2
+   and possibly $3 as arguments, diverging from the standard SysV ABI,
+   and as such would require severe pessimisation of MIPS16 PLT entries
+   just for this single special case.
+
+   For compatibility with old binaries that used safe standard MIPS PLT
+   entries and referred to these functions we still export them at
+   version GCC_4.4.0 for run-time loading only.  */
+
+#ifdef SHARED
+#define CE_STARTFN(NAME)			\
+STARTFN (NAME##_compat);			\
+	.symver NAME##_compat, NAME@GCC_4.4.0
+#define CE_ENDFN(NAME) ENDFN (NAME##_compat)
+#else
+#define CE_STARTFN(NAME)			\
+STARTFN (NAME);					\
+	.hidden NAME
+#define CE_ENDFN(NAME) ENDFN (NAME)
+#endif
+
 /* Define a function NAME that moves a return value of mode MODE from
    FPRs to GPRs.  */
 
 #define RET_FUNCTION(NAME, MODE)	\
-STARTFN (NAME);				\
+CE_STARTFN (NAME);			\
 	MOVE_##MODE##_RET (t, $31);	\
-	ENDFN (NAME)
+	CE_ENDFN (NAME)
 
 #ifdef L_m16retsf
 RET_FUNCTION (__mips16_ret_sf, SF)
@@ -526,13 +548,13 @@ RET_FUNCTION (__mips16_ret_dc, DC)
    to FPRs and then call function $2.  */
 
 #define CALL_STUB_NO_RET(NAME, CODE)	\
-STARTFN (NAME);				\
+CE_STARTFN (NAME);			\
 	STUB_ARGS_##CODE;		\
 	.set	noreorder;		\
 	jr	$2;			\
 	move	$25,$2;			\
 	.set	reorder;		\
-	ENDFN (NAME)
+	CE_ENDFN (NAME)
 
 #ifdef L_m16stub1
 CALL_STUB_NO_RET (__mips16_call_stub_1, 1)
@@ -575,7 +597,7 @@ CALL_STUB_NO_RET (__mips16_call_stub_10,
    however, it's faster to always do the copy.  */
 
 #define CALL_STUB_RET(NAME, CODE, MODE)					\
-STARTFN (NAME);								\
+CE_STARTFN (NAME);							\
 	.cfi_startproc;							\
 	/* Create a fake CFA 4 bytes below the stack pointer.  */	\
 	.cfi_def_cfa 29,-4;						\
@@ -591,7 +613,7 @@ STARTFN (NAME);								\
 	.set	reorder;						\
 	MOVE_##MODE##_RET (f, $18);					\
 	.cfi_endproc;							\
-	ENDFN (NAME)
+	CE_ENDFN (NAME)
 
 /* First, instantiate the single-float set.  */
 
