PATCH: ARM BPABI library routines

Mark Mitchell mark@codesourcery.com
Wed Aug 11 04:11:00 GMT 2004


The ARM BPABI specifies the set of helper routines that the compiler
can use, and these are inconveniently not the same as the libgcc
names.  In addition, there are some differences in semantics: for
example, the long long comparison functions return { -1, 0, 1} rather
than libgcc's { 0, 1, 2 }.  And, there are routines that do "/" and
"%" at the same time, with a non-standard calling convention.

This patch implements this functionality.  The goal, at this point, is
to be correct, not optimal.  This also adds a new target
"arm*-*-eabi*" which will be the generic BPABI target.  (The BPABI
used to be called the EABI, and there are bits in our configure
scripts that understand "eabi" but not "bpabi".)

Tested on arm-none-elf and arm-none-eabi.  There are no regressions on
the former, and the latter passes almost as many tests as the former,
with one GAS patch that has been posted to the binutils mailing list.
The additional EABI failures relate to built-in functions for which no
BPABI helper is available and profiling.

Applied on the mainline.

--
Mark Mitchell
CodeSourcery, LLC
mark@codesourcery.com

2004-08-09  Mark Mitchell  <mark@codesourcery.com>

	* configure.in (arm*-*-eabi*): New target.
	* configure: Regenerate.

2004-08-09  Mark Mitchell  <mark@codesourcery.com>

	* configure.ac (arm*-*-eabi*): New target.
	(arm*-*-symbianelf*): Likewise.
	* configure: Regenerated.

2004-08-09  Mark Mitchell  <mark@codesourcery.com>

	* config.gcc (arm*-*-eabi*): New target.
	* defaults.h (TARGET_LIBGCC_FUNCS): New macro.
	(TARGET_LIB_INT_CMP_BIASED): Likewise.
	* expmed.c (expand_divmod): Try a two-valued divmod function as a
	last resort.
	* gthr.h: Remove bogus tokens at end of #pragma.
	* optabs.c (expand_twoval_binop_libfunc): New function.
	(prepare_cmp_insn): Handle the !TARGET_LIB_INT_CMP_BIASED case.
	(prepare_float_lib_cmp): Try reversing the condition.
	(debug_optab_libfuncs): New function.
	* optabs.h (expand_twoval_binop_libfunc): Declare.
	* config/arm/arm.c (arm_init_libfuncs): New function.
	(arm_compute_initial_eliminatino_offset): Return HOST_WIDE_INT.
	(TARGET_INIT_LIBFUNCS): Define it.
	* config/arm/arm.h (TARGET_BPABI): New macro.
	* config/arm/arm-protos.h
	(arm_compute_initial_elimination_offset): Return HOST_WIDE_INT.
	* config/arm/bpabi.S: New file.
	* config/arm/bpabi.c: Likewise.
	* config/arm/bpabi.h: Likewise.
	* config/arm/ieee754-df.S (__aeabi_dneg): New function or alias.
	(__aeabi_drsub): Likewise.
	(__aeabi_dsub): Likewise.
	(__aeabi_dadd): Likewise.
	(__aeabi_ui2d): Likewise.
	(__aeabi_i2d): Likewise.
	(__aeabi_f2d): Likewise.
	(__aeabi_dmul): Likewise.
	(__aeabi_ddiv): Likewise.
	(__aeabi_cdrcmple): Likewise.
	(__aeabi_cdcmpeq): Likewise.
	(__aeabi_cdcmple): Likewise.
	(__aeabi_dcmpeq): Likewise.
	(__aeabi_dcmplt): Likewise.
	(__aeabi_dcmple): Likewise.
	(__aeabi_dcmpge): Likewise.
	(__aeabi_dcmpgt): Likewise.
	(__aeabi_dcmpun): Likewise.
	(__aeabi_d2iz): Likewise.
	(__aeabi_d2uiz): Likewise.
	(__aeabi_d2f): Likewise.
	* config/arm/ieee754-sf.S (__aeabi_fneg): New function or alias.
	(__aeabi_frsub): Likewise.
	(__aeabi_fsub): Likewise.
	(__aeabi_fadd): Likewise.
	(__aeabi_ui2f): Likewise.
	(__aeabi_i2f): Likewise.
	(__aeabi_fmul): Likewise.
	(__aeabi_fdiv): Likewise.
	(__aeabi_cfrcmple): Likewise.
	(__aeabi_cfcmpeq): Likewise.
	(__aeabi_cfcmple): Likewise.
	(__aeabi_fcmpeq): Likewise.
	(__aeabi_fcmplt): Likewise.
	(__aeabi_fcmple): Likewise.
	(__aeabi_fcmpge): Likewise.
	(__aeabi_fcmpgt): Likewise.
	(__aeabi_fcmpun): Likewise.
	(__aeabi_f2iz): Likewise.
	(__aeabi_f2uiz): Likewise.
	* config/arm/lib1funcs.asm (ARM_CALL): New macro.
	(__aeabi_uidivmod): New function or alias.
	(__aeabi_idivmod): Likewise.
	(__aeabi_idiv0): Likewise.
	(__aeabi_ldiv0): Likewise.
	(__aeabi_llsr): Likewise.
	(__aeabi_lasr): Likewise.
	(__aeabi_llsl): Likewise.
	(bpabi.S): Include it.
	* config/arm/libgcc-bpabi.ver: New file.
	* config/arm/symbian.h (ARM_DEFAULT_ABI): Remove.
	(LINK_SPEC): Remove.
	* config/arm/t-arm-elf (LIB1ASMFUNCS): Add __aeabi_lcmp and
	__aeabi_ulcmp.
	* config/arm/t-bpabi: New file.
	* doc/tm.texi (TARGET_LIBGCC_FUNCS): New entry.
	(TARGET_LIB_INT_CMP_BIASED): Likewise.

2004-08-09  Mark Mitchell  <mark@codesourcery.com>

	* gcc.dg/testsuite/gcc.dg/arm-eabi1.c: New test.
	* gcc.dg/dll-2.c: Fix dg-require syntax.
	* gcc.misc-tests/arm-isr.c (abort): Declare.
	(exit): Likewise.

Index: configure.in
===================================================================
RCS file: /cvs/gcc/gcc/configure.in,v
retrieving revision 1.306
diff -c -5 -p -r1.306 configure.in
*** configure.in	4 Aug 2004 16:11:12 -0000	1.306
--- configure.in	11 Aug 2004 02:43:24 -0000
*************** case "${target}" in
*** 477,487 ****
      noconfigdirs="$noconfigdirs target-libgloss ${libgcj}"
      ;;
    arm-*-coff | strongarm-*-coff | xscale-*-coff)
      noconfigdirs="$noconfigdirs ${libgcj}"
      ;;
!   arm-*-elf* | strongarm-*-elf* | xscale-*-elf*)
      noconfigdirs="$noconfigdirs target-libffi target-qthreads"
      ;;
    arm*-*-symbianelf*)
      noconfigdirs="$noconfigdirs ${libgcj} target-libiberty"
      ;;
--- 477,487 ----
      noconfigdirs="$noconfigdirs target-libgloss ${libgcj}"
      ;;
    arm-*-coff | strongarm-*-coff | xscale-*-coff)
      noconfigdirs="$noconfigdirs ${libgcj}"
      ;;
!   arm-*-elf* | strongarm-*-elf* | xscale-*-elf* | arm*-*-eabi* )
      noconfigdirs="$noconfigdirs target-libffi target-qthreads"
      ;;
    arm*-*-symbianelf*)
      noconfigdirs="$noconfigdirs ${libgcj} target-libiberty"
      ;;
Index: gcc/config.gcc
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config.gcc,v
retrieving revision 1.477
diff -c -5 -p -r1.477 config.gcc
*** gcc/config.gcc	5 Aug 2004 04:55:34 -0000	1.477
--- gcc/config.gcc	11 Aug 2004 02:43:24 -0000
*************** arm*-*-uclinux*)		# ARM ucLinux
*** 650,662 ****
  	;;
  arm*-*-ecos-elf)
  	tm_file="dbxelf.h elfos.h arm/unknown-elf.h arm/elf.h arm/aout.h arm/arm.h arm/ecos-elf.h"
  	tmake_file="arm/t-arm arm/t-arm-elf"
  	;;
! arm*-*-symbianelf*)
! 	tm_file="dbxelf.h elfos.h arm/unknown-elf.h arm/elf.h arm/symbian.h arm/aout.h arm/arm.h"
! 	tmake_file="t-slibgcc-elf-ver arm/t-arm arm/t-arm-elf"
  	;;
  arm*-*-rtems*)
  	tm_file="dbxelf.h elfos.h arm/unknown-elf.h arm/elf.h arm/aout.h arm/arm.h arm/rtems-elf.h rtems.h"
  	tmake_file="arm/t-arm arm/t-arm-elf t-rtems"
  	;;
--- 650,672 ----
  	;;
  arm*-*-ecos-elf)
  	tm_file="dbxelf.h elfos.h arm/unknown-elf.h arm/elf.h arm/aout.h arm/arm.h arm/ecos-elf.h"
  	tmake_file="arm/t-arm arm/t-arm-elf"
  	;;
! arm*-*-eabi* | arm*-*-symbianelf* )
! 	# The BPABI long long divmod functions return a 128-bit value in 
! 	# registers r0-r3.  Correctly modeling that requires the use of
! 	# TImode.
! 	need_64bit_hwint=yes
! 	tm_file="dbxelf.h elfos.h arm/unknown-elf.h arm/elf.h arm/bpabi.h"
! 	case ${target} in
! 	arm*-*-symbianelf*)
! 	  tm_file="${tm_file} arm/symbian.h"
! 	  ;;
! 	esac
! 	tm_file="${tm_file} arm/aout.h arm/arm.h"
! 	tmake_file="t-slibgcc-elf-ver arm/t-arm arm/t-arm-elf arm/t-bpabi"
  	;;
  arm*-*-rtems*)
  	tm_file="dbxelf.h elfos.h arm/unknown-elf.h arm/elf.h arm/aout.h arm/arm.h arm/rtems-elf.h rtems.h"
  	tmake_file="arm/t-arm arm/t-arm-elf t-rtems"
  	;;
Index: gcc/defaults.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/defaults.h,v
retrieving revision 1.144
diff -c -5 -p -r1.144 defaults.h
*** gcc/defaults.h	6 Aug 2004 02:03:19 -0000	1.144
--- gcc/defaults.h	11 Aug 2004 02:43:24 -0000
*************** You Lose!  You must define PREFERRED_DEB
*** 625,634 ****
--- 625,647 ----
  
  #ifndef FLOAT_LIB_COMPARE_RETURNS_BOOL
  #define FLOAT_LIB_COMPARE_RETURNS_BOOL(MODE, COMPARISON) false
  #endif
  
+ /* True if the target should use the standard libgcc arithmetic
+    library functions, like __addsi3 and _fixdfdi.  */
+ #ifndef TARGET_LIBGCC_LIBFUNCS
+ #define TARGET_LIBGCC_LIBFUNCS (true)
+ #endif
+ 
+ /* True if the targets integer-comparision fucntions return { 0, 1, 2
+    } to indicate { <, ==, > }.  False if { -1, 0, 1 } is used
+    instead.  The libgcc routines are biased.  */
+ #ifndef TARGET_LIB_INT_CMP_BIASED
+ #define TARGET_LIB_INT_CMP_BIASED (true)
+ #endif
+ 
  /* If FLOAT_WORDS_BIG_ENDIAN is not defined in the header files,
     then the word-endianness is the same as for integers.  */
  #ifndef FLOAT_WORDS_BIG_ENDIAN
  #define FLOAT_WORDS_BIG_ENDIAN WORDS_BIG_ENDIAN
  #endif
Index: gcc/expmed.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/expmed.c,v
retrieving revision 1.187
diff -c -5 -p -r1.187 expmed.c
*** gcc/expmed.c	9 Aug 2004 22:36:39 -0000	1.187
--- gcc/expmed.c	11 Aug 2004 02:43:24 -0000
*************** expand_divmod (int rem_flag, enum tree_c
*** 4335,4348 ****
      {
        if (target && GET_MODE (target) != compute_mode)
  	target = 0;
  
        if (quotient == 0)
! 	/* No divide instruction either.  Use library for remainder.  */
! 	remainder = sign_expand_binop (compute_mode, umod_optab, smod_optab,
! 				       op0, op1, target,
! 				       unsignedp, OPTAB_LIB_WIDEN);
        else
  	{
  	  /* We divided.  Now finish doing X - Y * (X / Y).  */
  	  remainder = expand_mult (compute_mode, quotient, op1,
  				   NULL_RTX, unsignedp);
--- 4335,4362 ----
      {
        if (target && GET_MODE (target) != compute_mode)
  	target = 0;
  
        if (quotient == 0)
! 	{
! 	  /* No divide instruction either.  Use library for remainder.  */
! 	  remainder = sign_expand_binop (compute_mode, umod_optab, smod_optab,
! 					 op0, op1, target,
! 					 unsignedp, OPTAB_LIB_WIDEN);
! 	  /* No remainder function.  Try a quotient-and-remainder
! 	     function, keeping the remainder.  */
! 	  if (!remainder)
! 	    {
! 	      remainder = gen_reg_rtx (compute_mode);
! 	      if (!expand_twoval_binop_libfunc 
! 		  (unsignedp ? udivmod_optab : sdivmod_optab,
! 		   op0, op1,
! 		   NULL_RTX, remainder,
! 		   unsignedp ? UMOD : MOD))
! 		remainder = NULL_RTX;
! 	    }
! 	}
        else
  	{
  	  /* We divided.  Now finish doing X - Y * (X / Y).  */
  	  remainder = expand_mult (compute_mode, quotient, op1,
  				   NULL_RTX, unsignedp);
Index: gcc/gthr.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/gthr.h,v
retrieving revision 1.14
diff -c -5 -p -r1.14 gthr.h
*** gcc/gthr.h	3 Aug 2004 16:57:40 -0000	1.14
--- gcc/gthr.h	11 Aug 2004 02:43:24 -0000
*************** Software Foundation, 59 Temple Place - S
*** 100,107 ****
  /* Fallback to single thread definitions.  */
  #else
  #include "gthr-single.h"
  #endif
  
! #pragma GCC visibility pop(default)
  
  #endif /* ! GCC_GTHR_H */
--- 100,107 ----
  /* Fallback to single thread definitions.  */
  #else
  #include "gthr-single.h"
  #endif
  
! #pragma GCC visibility pop
  
  #endif /* ! GCC_GTHR_H */
Index: gcc/optabs.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/optabs.c,v
retrieving revision 1.232
diff -c -5 -p -r1.232 optabs.c
*** gcc/optabs.c	9 Aug 2004 06:46:41 -0000	1.232
--- gcc/optabs.c	11 Aug 2004 02:43:24 -0000
*************** expand_twoval_binop (optab binoptab, rtx
*** 2446,2455 ****
--- 2446,2504 ----
      }
  
    delete_insns_since (entry_last);
    return 0;
  }
+ 
+ /* Expand the two-valued library call indicated by BINOPTAB, but
+    preserve only one of the values.  If TARG0 is non-NULL, the first
+    value is placed into TARG0; otherwise the second value is placed
+    into TARG1.  Exactly one of TARG0 and TARG1 must be non-NULL.  The
+    value stored into TARG0 or TARG1 is equivalent to (CODE OP0 OP1).
+    This routine assumes that the value returned by the library call is
+    as if the return value was of an integral mode twice as wide as the
+    mode of OP0.  Returns 1 if the call was successful.  */
+ 
+ bool
+ expand_twoval_binop_libfunc (optab binoptab, rtx op0, rtx op1, 
+ 			     rtx targ0, rtx targ1, enum rtx_code code)
+ {
+   enum machine_mode mode;
+   enum machine_mode libval_mode;
+   rtx libval;
+   rtx insns;
+   
+   /* Exactly one of TARG0 or TARG1 should be non-NULL.  */
+   if (!((targ0 != NULL_RTX) ^ (targ1 != NULL_RTX)))
+     abort ();
+ 
+   mode = GET_MODE (op0);
+   if (!binoptab->handlers[(int) mode].libfunc)
+     return false;
+ 
+   /* The value returned by the library function will have twice as
+      many bits as the nominal MODE.  */
+   libval_mode = smallest_mode_for_size (2 * GET_MODE_BITSIZE (mode), 
+ 					MODE_INT);
+   start_sequence ();
+   libval = emit_library_call_value (binoptab->handlers[(int) mode].libfunc,
+ 				    NULL_RTX, LCT_CONST, 
+ 				    libval_mode, 2,
+ 				    op0, mode, 
+ 				    op1, mode);
+   /* Get the part of VAL containing the value that we want.  */
+   libval = simplify_gen_subreg (mode, libval, libval_mode,
+ 				targ0 ? 0 : GET_MODE_SIZE (mode));
+   insns = get_insns ();
+   end_sequence ();
+   /* Move the into the desired location.  */
+   emit_libcall_block (insns, targ0 ? targ0 : targ1, libval, 
+ 		      gen_rtx_fmt_ee (code, mode, op0, op1));
+   
+   return true;
+ }
+ 
  
  /* Wrapper around expand_unop which takes an rtx code to specify
     the operation to perform, not an optab pointer.  All other
     arguments are the same.  */
  rtx
*************** prepare_cmp_insn (rtx *px, rtx *py, enum
*** 3815,3830 ****
  	libfunc = ucmp_optab->handlers[(int) mode].libfunc;
  
        result = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST_MAKE_BLOCK,
  					word_mode, 2, x, mode, y, mode);
  
-       /* Integer comparison returns a result that must be compared against 1,
- 	 so that even if we do an unsigned compare afterward,
- 	 there is still a value that can represent the result "less than".  */
        *px = result;
-       *py = const1_rtx;
        *pmode = word_mode;
        return;
      }
  
    if (class == MODE_FLOAT)
      prepare_float_lib_cmp (px, py, pcomparison, pmode, punsignedp);
--- 3864,3886 ----
  	libfunc = ucmp_optab->handlers[(int) mode].libfunc;
  
        result = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST_MAKE_BLOCK,
  					word_mode, 2, x, mode, y, mode);
  
        *px = result;
        *pmode = word_mode;
+       if (TARGET_LIB_INT_CMP_BIASED)
+ 	/* Integer comparison returns a result that must be compared
+ 	   against 1, so that even if we do an unsigned compare
+ 	   afterward, there is still a value that can represent the
+ 	   result "less than".  */
+ 	*py = const1_rtx;
+       else
+ 	{
+ 	  *py = const0_rtx;
+ 	  *punsignedp = 1;
+ 	}
        return;
      }
  
    if (class == MODE_FLOAT)
      prepare_float_lib_cmp (px, py, pcomparison, pmode, punsignedp);
*************** static void
*** 3991,4006 ****
--- 4047,4064 ----
  prepare_float_lib_cmp (rtx *px, rtx *py, enum rtx_code *pcomparison,
  		       enum machine_mode *pmode, int *punsignedp)
  {
    enum rtx_code comparison = *pcomparison;
    enum rtx_code swapped = swap_condition (comparison);
+   enum rtx_code reversed = reverse_condition_maybe_unordered (comparison);
    rtx x = *px;
    rtx y = *py;
    enum machine_mode orig_mode = GET_MODE (x);
    enum machine_mode mode;
    rtx value, target, insns, equiv;
    rtx libfunc = 0;
+   bool reversed_p = false;
  
    for (mode = orig_mode; mode != VOIDmode; mode = GET_MODE_WIDER_MODE (mode))
      {
        if ((libfunc = code_to_optab[comparison]->handlers[mode].libfunc))
  	break;
*************** prepare_float_lib_cmp (rtx *px, rtx *py,
*** 4010,4021 ****
  	  rtx tmp;
  	  tmp = x; x = y; y = tmp;
  	  comparison = swapped;
  	  break;
  	}
-     }
  
    if (mode == VOIDmode)
      abort ();
  
    if (mode != orig_mode)
      {
--- 4068,4087 ----
  	  rtx tmp;
  	  tmp = x; x = y; y = tmp;
  	  comparison = swapped;
  	  break;
  	}
  
+       if ((libfunc = code_to_optab[reversed]->handlers[mode].libfunc)
+ 	  && FLOAT_LIB_COMPARE_RETURNS_BOOL (mode, reversed))
+ 	{
+ 	  comparison = reversed;
+ 	  reversed_p = true;
+ 	  break;
+ 	}
+     }
+  
    if (mode == VOIDmode)
      abort ();
  
    if (mode != orig_mode)
      {
*************** prepare_float_lib_cmp (rtx *px, rtx *py,
*** 4087,4100 ****
    end_sequence ();
  
    target = gen_reg_rtx (word_mode);
    emit_libcall_block (insns, target, value, equiv);
  
- 
    if (comparison == UNORDERED
        || FLOAT_LIB_COMPARE_RETURNS_BOOL (mode, comparison))
!     comparison = NE;
  
    *px = target;
    *py = const0_rtx;
    *pmode = word_mode;
    *pcomparison = comparison;
--- 4153,4165 ----
    end_sequence ();
  
    target = gen_reg_rtx (word_mode);
    emit_libcall_block (insns, target, value, equiv);
  
    if (comparison == UNORDERED
        || FLOAT_LIB_COMPARE_RETURNS_BOOL (mode, comparison))
!     comparison = reversed_p ? EQ : NE;
  
    *px = target;
    *py = const0_rtx;
    *pmode = word_mode;
    *pcomparison = comparison;
*************** init_optabs (void)
*** 5416,5491 ****
  
    /* Fill in the optabs with the insns we support.  */
    init_all_optabs ();
  
    /* Initialize the optabs with the names of the library functions.  */
!   init_integral_libfuncs (add_optab, "add", '3');
!   init_floating_libfuncs (add_optab, "add", '3');
!   init_integral_libfuncs (addv_optab, "addv", '3');
!   init_floating_libfuncs (addv_optab, "add", '3');
!   init_integral_libfuncs (sub_optab, "sub", '3');
!   init_floating_libfuncs (sub_optab, "sub", '3');
!   init_integral_libfuncs (subv_optab, "subv", '3');
!   init_floating_libfuncs (subv_optab, "sub", '3');
!   init_integral_libfuncs (smul_optab, "mul", '3');
!   init_floating_libfuncs (smul_optab, "mul", '3');
!   init_integral_libfuncs (smulv_optab, "mulv", '3');
!   init_floating_libfuncs (smulv_optab, "mul", '3');
!   init_integral_libfuncs (sdiv_optab, "div", '3');
!   init_floating_libfuncs (sdiv_optab, "div", '3');
!   init_integral_libfuncs (sdivv_optab, "divv", '3');
!   init_integral_libfuncs (udiv_optab, "udiv", '3');
!   init_integral_libfuncs (sdivmod_optab, "divmod", '4');
!   init_integral_libfuncs (udivmod_optab, "udivmod", '4');
!   init_integral_libfuncs (smod_optab, "mod", '3');
!   init_integral_libfuncs (umod_optab, "umod", '3');
!   init_floating_libfuncs (ftrunc_optab, "ftrunc", '2');
!   init_integral_libfuncs (and_optab, "and", '3');
!   init_integral_libfuncs (ior_optab, "ior", '3');
!   init_integral_libfuncs (xor_optab, "xor", '3');
!   init_integral_libfuncs (ashl_optab, "ashl", '3');
!   init_integral_libfuncs (ashr_optab, "ashr", '3');
!   init_integral_libfuncs (lshr_optab, "lshr", '3');
!   init_integral_libfuncs (smin_optab, "min", '3');
!   init_floating_libfuncs (smin_optab, "min", '3');
!   init_integral_libfuncs (smax_optab, "max", '3');
!   init_floating_libfuncs (smax_optab, "max", '3');
!   init_integral_libfuncs (umin_optab, "umin", '3');
!   init_integral_libfuncs (umax_optab, "umax", '3');
!   init_integral_libfuncs (neg_optab, "neg", '2');
!   init_floating_libfuncs (neg_optab, "neg", '2');
!   init_integral_libfuncs (negv_optab, "negv", '2');
!   init_floating_libfuncs (negv_optab, "neg", '2');
!   init_integral_libfuncs (one_cmpl_optab, "one_cmpl", '2');
!   init_integral_libfuncs (ffs_optab, "ffs", '2');
!   init_integral_libfuncs (clz_optab, "clz", '2');
!   init_integral_libfuncs (ctz_optab, "ctz", '2');
!   init_integral_libfuncs (popcount_optab, "popcount", '2');
!   init_integral_libfuncs (parity_optab, "parity", '2');
! 
!   /* Comparison libcalls for integers MUST come in pairs, signed/unsigned.  */
!   init_integral_libfuncs (cmp_optab, "cmp", '2');
!   init_integral_libfuncs (ucmp_optab, "ucmp", '2');
!   init_floating_libfuncs (cmp_optab, "cmp", '2');
! 
!   /* EQ etc are floating point only.  */
!   init_floating_libfuncs (eq_optab, "eq", '2');
!   init_floating_libfuncs (ne_optab, "ne", '2');
!   init_floating_libfuncs (gt_optab, "gt", '2');
!   init_floating_libfuncs (ge_optab, "ge", '2');
!   init_floating_libfuncs (lt_optab, "lt", '2');
!   init_floating_libfuncs (le_optab, "le", '2');
!   init_floating_libfuncs (unord_optab, "unord", '2');
! 
!   /* Conversions.  */
!   init_interclass_conv_libfuncs (sfloat_optab, "float", MODE_INT, MODE_FLOAT);
!   init_interclass_conv_libfuncs (sfix_optab, "fix",     MODE_FLOAT, MODE_INT);
!   init_interclass_conv_libfuncs (ufix_optab, "fixuns",  MODE_FLOAT, MODE_INT);
! 
!   /* sext_optab is also used for FLOAT_EXTEND.  */
!   init_intraclass_conv_libfuncs (sext_optab, "extend", MODE_FLOAT, true);
!   init_intraclass_conv_libfuncs (trunc_optab, "trunc", MODE_FLOAT, false);
  
    /* Use cabs for double complex abs, since systems generally have cabs.
       Don't define any libcall for float complex, so that cabs will be used.  */
    if (complex_double_type_node)
      abs_optab->handlers[TYPE_MODE (complex_double_type_node)].libfunc
--- 5481,5563 ----
  
    /* Fill in the optabs with the insns we support.  */
    init_all_optabs ();
  
    /* Initialize the optabs with the names of the library functions.  */
!   if (TARGET_LIBGCC_LIBFUNCS)
!     {
!       init_integral_libfuncs (add_optab, "add", '3');
!       init_floating_libfuncs (add_optab, "add", '3');
!       init_integral_libfuncs (addv_optab, "addv", '3');
!       init_floating_libfuncs (addv_optab, "add", '3');
!       init_integral_libfuncs (sub_optab, "sub", '3');
!       init_floating_libfuncs (sub_optab, "sub", '3');
!       init_integral_libfuncs (subv_optab, "subv", '3');
!       init_floating_libfuncs (subv_optab, "sub", '3');
!       init_integral_libfuncs (smul_optab, "mul", '3');
!       init_floating_libfuncs (smul_optab, "mul", '3');
!       init_integral_libfuncs (smulv_optab, "mulv", '3');
!       init_floating_libfuncs (smulv_optab, "mul", '3');
!       init_integral_libfuncs (sdiv_optab, "div", '3');
!       init_floating_libfuncs (sdiv_optab, "div", '3');
!       init_integral_libfuncs (sdivv_optab, "divv", '3');
!       init_integral_libfuncs (udiv_optab, "udiv", '3');
!       init_integral_libfuncs (sdivmod_optab, "divmod", '4');
!       init_integral_libfuncs (udivmod_optab, "udivmod", '4');
!       init_integral_libfuncs (smod_optab, "mod", '3');
!       init_integral_libfuncs (umod_optab, "umod", '3');
!       init_floating_libfuncs (ftrunc_optab, "ftrunc", '2');
!       init_integral_libfuncs (and_optab, "and", '3');
!       init_integral_libfuncs (ior_optab, "ior", '3');
!       init_integral_libfuncs (xor_optab, "xor", '3');
!       init_integral_libfuncs (ashl_optab, "ashl", '3');
!       init_integral_libfuncs (ashr_optab, "ashr", '3');
!       init_integral_libfuncs (lshr_optab, "lshr", '3');
!       init_integral_libfuncs (smin_optab, "min", '3');
!       init_floating_libfuncs (smin_optab, "min", '3');
!       init_integral_libfuncs (smax_optab, "max", '3');
!       init_floating_libfuncs (smax_optab, "max", '3');
!       init_integral_libfuncs (umin_optab, "umin", '3');
!       init_integral_libfuncs (umax_optab, "umax", '3');
!       init_integral_libfuncs (neg_optab, "neg", '2');
!       init_floating_libfuncs (neg_optab, "neg", '2');
!       init_integral_libfuncs (negv_optab, "negv", '2');
!       init_floating_libfuncs (negv_optab, "neg", '2');
!       init_integral_libfuncs (one_cmpl_optab, "one_cmpl", '2');
!       init_integral_libfuncs (ffs_optab, "ffs", '2');
!       init_integral_libfuncs (clz_optab, "clz", '2');
!       init_integral_libfuncs (ctz_optab, "ctz", '2');
!       init_integral_libfuncs (popcount_optab, "popcount", '2');
!       init_integral_libfuncs (parity_optab, "parity", '2');
! 
!       /* Comparison libcalls for integers MUST come in pairs,
! 	 signed/unsigned.  */
!       init_integral_libfuncs (cmp_optab, "cmp", '2');
!       init_integral_libfuncs (ucmp_optab, "ucmp", '2');
!       init_floating_libfuncs (cmp_optab, "cmp", '2');
! 
!       /* EQ etc are floating point only.  */
!       init_floating_libfuncs (eq_optab, "eq", '2');
!       init_floating_libfuncs (ne_optab, "ne", '2');
!       init_floating_libfuncs (gt_optab, "gt", '2');
!       init_floating_libfuncs (ge_optab, "ge", '2');
!       init_floating_libfuncs (lt_optab, "lt", '2');
!       init_floating_libfuncs (le_optab, "le", '2');
!       init_floating_libfuncs (unord_optab, "unord", '2');
! 
!       /* Conversions.  */
!       init_interclass_conv_libfuncs (sfloat_optab, "float", 
! 				     MODE_INT, MODE_FLOAT);
!       init_interclass_conv_libfuncs (sfix_optab, "fix",     
! 				     MODE_FLOAT, MODE_INT);
!       init_interclass_conv_libfuncs (ufix_optab, "fixuns",  
! 				     MODE_FLOAT, MODE_INT);
! 
!       /* sext_optab is also used for FLOAT_EXTEND.  */
!       init_intraclass_conv_libfuncs (sext_optab, "extend", MODE_FLOAT, true);
!       init_intraclass_conv_libfuncs (trunc_optab, "trunc", MODE_FLOAT, false);
!     }
  
    /* Use cabs for double complex abs, since systems generally have cabs.
       Don't define any libcall for float complex, so that cabs will be used.  */
    if (complex_double_type_node)
      abs_optab->handlers[TYPE_MODE (complex_double_type_node)].libfunc
*************** init_optabs (void)
*** 5528,5537 ****
--- 5600,5667 ----
      trap_rtx = gen_rtx_fmt_ee (EQ, VOIDmode, NULL_RTX, NULL_RTX);
  
    /* Allow the target to add more libcalls or rename some, etc.  */
    targetm.init_libfuncs ();
  }
+ 
+ #ifdef DEBUG
+ 
+ /* Print information about the current contents of the optabs on
+    STDERR.  */
+ 
+ static void
+ debug_optab_libfuncs (void)
+ {
+   int i;
+   int j;
+   int k;
+ 
+   /* Dump the arithmetic optabs.  */
+   for (i = 0; i != (int) OTI_MAX; i++) 
+     for (j = 0; j < NUM_MACHINE_MODES; ++j)
+       {
+ 	optab o;
+ 	struct optab_handlers *h;
+ 
+ 	o = optab_table[i];
+ 	h = &o->handlers[j];
+ 	if (h->libfunc)
+ 	  {
+ 	    if (GET_CODE (h->libfunc) != SYMBOL_REF)
+ 	      abort ();
+ 	    fprintf (stderr, "%s\t%s:\t%s\n", 
+ 		     GET_RTX_NAME (o->code),
+ 		     GET_MODE_NAME (j),
+ 		     XSTR (h->libfunc, 0));
+ 	  }
+       }
+ 
+   /* Dump the conversion optabs.  */
+   for (i = 0; i < (int) CTI_MAX; ++i)
+     for (j = 0; j < NUM_MACHINE_MODES; ++j)
+       for (k = 0; k < NUM_MACHINE_MODES; ++k)
+ 	{
+ 	  convert_optab o;
+ 	  struct optab_handlers *h;
+ 
+ 	  o = &convert_optab_table[i];
+ 	  h = &o->handlers[j][k];
+ 	  if (h->libfunc)
+ 	    {
+ 	      if (GET_CODE (h->libfunc) != SYMBOL_REF)
+ 		abort ();
+ 	      fprintf (stderr, "%s\t%s\t%s:\t%s\n", 
+ 		       GET_RTX_NAME (o->code),
+ 		       GET_MODE_NAME (j),
+ 		       GET_MODE_NAME (k),
+ 		       XSTR (h->libfunc, 0));
+ 	    }
+ 	}
+ }
+ 
+ #endif /* DEBUG */
+ 
  
  /* Generate insns to trap with code TCODE if OP1 and OP2 satisfy condition
     CODE.  Return 0 on failure.  */
  
  rtx
Index: gcc/optabs.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/optabs.h,v
retrieving revision 1.32
diff -c -5 -p -r1.32 optabs.h
*** gcc/optabs.h	9 Aug 2004 06:46:41 -0000	1.32
--- gcc/optabs.h	11 Aug 2004 02:43:24 -0000
*************** extern rtx sign_expand_binop (enum machi
*** 415,424 ****
--- 415,429 ----
  extern int expand_twoval_unop (optab, rtx, rtx, rtx, int);
  
  /* Generate code to perform an operation on two operands with two results.  */
  extern int expand_twoval_binop (optab, rtx, rtx, rtx, rtx, int);
  
+ /* Generate code to perform an operation on two operands with two
+    results, using a library function.  */
+ extern bool expand_twoval_binop_libfunc (optab, rtx, rtx, rtx, rtx, 
+ 					 enum rtx_code);
+ 
  /* Expand a unary arithmetic operation given optab rtx operand.  */
  extern rtx expand_unop (enum machine_mode, optab, rtx, rtx, int);
  
  /* Expand the absolute value operation.  */
  extern rtx expand_abs_nojump (enum machine_mode, rtx, rtx, int);
Index: gcc/config/arm/arm-protos.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/arm/arm-protos.h,v
retrieving revision 1.72
diff -c -5 -p -r1.72 arm-protos.h
*** gcc/config/arm/arm-protos.h	10 Aug 2004 16:22:45 -0000	1.72
--- gcc/config/arm/arm-protos.h	11 Aug 2004 02:43:25 -0000
*************** extern int arm_volatile_func (void);
*** 32,43 ****
  extern const char *arm_output_epilogue (rtx);
  extern void arm_expand_prologue (void);
  extern const char *arm_strip_name_encoding (const char *);
  extern void arm_asm_output_labelref (FILE *, const char *);
  extern unsigned long arm_current_func_type (void);
! extern unsigned int arm_compute_initial_elimination_offset (unsigned int,
! 							    unsigned int);
  extern HOST_WIDE_INT thumb_compute_initial_elimination_offset (unsigned int,
  							       unsigned int);
  
  #ifdef TREE_CODE
  extern int arm_return_in_memory (tree);
--- 32,43 ----
  extern const char *arm_output_epilogue (rtx);
  extern void arm_expand_prologue (void);
  extern const char *arm_strip_name_encoding (const char *);
  extern void arm_asm_output_labelref (FILE *, const char *);
  extern unsigned long arm_current_func_type (void);
! extern HOST_WIDE_INT arm_compute_initial_elimination_offset (unsigned int,
! 							     unsigned int);
  extern HOST_WIDE_INT thumb_compute_initial_elimination_offset (unsigned int,
  							       unsigned int);
  
  #ifdef TREE_CODE
  extern int arm_return_in_memory (tree);
Index: gcc/config/arm/arm.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/arm/arm.c,v
retrieving revision 1.384
diff -c -5 -p -r1.384 arm.c
*** gcc/config/arm/arm.c	10 Aug 2004 16:22:46 -0000	1.384
--- gcc/config/arm/arm.c	11 Aug 2004 02:43:25 -0000
*************** static bool arm_align_anon_bitfield (voi
*** 167,176 ****
--- 167,177 ----
  static tree arm_cxx_guard_type (void);
  static bool arm_cxx_guard_mask_bit (void);
  static tree arm_get_cookie_size (tree);
  static bool arm_cookie_has_size (void);
  static bool arm_cxx_cdtor_returns_this (void);
+ static void arm_init_libfuncs (void);
  
  
  /* Initialize the GCC target structure.  */
  #if TARGET_DLLIMPORT_DECL_ATTRIBUTES
  #undef  TARGET_MERGE_DECL_ATTRIBUTES
*************** static bool arm_cxx_cdtor_returns_this (
*** 248,257 ****
--- 249,261 ----
  #undef  TARGET_INIT_BUILTINS
  #define TARGET_INIT_BUILTINS  arm_init_builtins
  #undef  TARGET_EXPAND_BUILTIN
  #define TARGET_EXPAND_BUILTIN arm_expand_builtin
  
+ #undef TARGET_INIT_LIBFUNCS
+ #define TARGET_INIT_LIBFUNCS arm_init_libfuncs
+ 
  #undef TARGET_PROMOTE_FUNCTION_ARGS
  #define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_tree_true
  #undef TARGET_PROMOTE_FUNCTION_RETURN
  #define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_tree_true
  #undef TARGET_PROMOTE_PROTOTYPES
*************** bit_count (unsigned long value)
*** 612,621 ****
--- 616,723 ----
      }
  
    return count;
  }
  
+ /* Set up library functions uqniue to ARM.  */
+ 
+ static void
+ arm_init_libfuncs (void)
+ {
+   /* There are no special library functions unless we are using the
+      ARM BPABI.  */
+   if (!TARGET_BPABI)
+     return;
+ 
+   /* The functions below are described in Section 4 of the "Run-Time
+      ABI for the ARM architecture", Version 1.0.  */
+ 
+   /* Double-precision floating-point arithmetic.  Table 2.  */
+   set_optab_libfunc (add_optab, DFmode, "__aeabi_dadd");
+   set_optab_libfunc (sdiv_optab, DFmode, "__aeabi_ddiv");
+   set_optab_libfunc (smul_optab, DFmode, "__aeabi_dmul");
+   set_optab_libfunc (neg_optab, DFmode, "__aeabi_dneg");
+   set_optab_libfunc (sub_optab, DFmode, "__aeabi_dsub");
+ 
+   /* Double-precision comparisions.  Table 3.  */
+   set_optab_libfunc (eq_optab, DFmode, "__aeabi_dcmpeq");
+   set_optab_libfunc (ne_optab, DFmode, NULL);
+   set_optab_libfunc (lt_optab, DFmode, "__aeabi_dcmplt");
+   set_optab_libfunc (le_optab, DFmode, "__aeabi_dcmple");
+   set_optab_libfunc (ge_optab, DFmode, "__aeabi_dcmpge");
+   set_optab_libfunc (gt_optab, DFmode, "__aeabi_dcmpgt");
+   set_optab_libfunc (unord_optab, DFmode, "__aeabi_dcmpun");
+ 
+   /* Single-precision floating-point arithmetic.  Table 4.  */
+   set_optab_libfunc (add_optab, SFmode, "__aeabi_fadd");
+   set_optab_libfunc (sdiv_optab, SFmode, "__aeabi_fdiv");
+   set_optab_libfunc (smul_optab, SFmode, "__aeabi_fmul");
+   set_optab_libfunc (neg_optab, SFmode, "__aeabi_fneg");
+   set_optab_libfunc (sub_optab, SFmode, "__aeabi_fsub");
+   
+   /* Single-precision comparisions.  Table 5.  */
+   set_optab_libfunc (eq_optab, SFmode, "__aeabi_fcmpeq");
+   set_optab_libfunc (ne_optab, SFmode, NULL);
+   set_optab_libfunc (lt_optab, SFmode, "__aeabi_fcmplt");
+   set_optab_libfunc (le_optab, SFmode, "__aeabi_fcmple");
+   set_optab_libfunc (ge_optab, SFmode, "__aeabi_fcmpge");
+   set_optab_libfunc (gt_optab, SFmode, "__aeabi_fcmpgt");
+   set_optab_libfunc (unord_optab, SFmode, "__aeabi_fcmpun");
+ 
+   /* Floating-point to integer conversions.  Table 6.  */
+   set_conv_libfunc (sfix_optab, SImode, DFmode, "__aeabi_d2iz");
+   set_conv_libfunc (ufix_optab, SImode, DFmode, "__aeabi_d2uiz");
+   set_conv_libfunc (sfix_optab, DImode, DFmode, "__aeabi_d2lz");
+   set_conv_libfunc (ufix_optab, DImode, DFmode, "__aeabi_d2ulz");
+   set_conv_libfunc (sfix_optab, SImode, SFmode, "__aeabi_f2iz");
+   set_conv_libfunc (ufix_optab, SImode, SFmode, "__aeabi_f2uiz");
+   set_conv_libfunc (sfix_optab, DImode, SFmode, "__aeabi_f2lz");
+   set_conv_libfunc (ufix_optab, DImode, SFmode, "__aeabi_f2ulz");
+ 
+   /* Conversions between floating types.  Table 7.  */
+   set_conv_libfunc (trunc_optab, SFmode, DFmode, "__aeabi_d2f");
+   set_conv_libfunc (sext_optab, DFmode, SFmode, "__aeabi_f2d");
+ 
+   /* Integer to floating-point converisons.  Table 8.  */
+   set_conv_libfunc (sfloat_optab, DFmode, SImode, "__aeabi_i2d");
+   set_conv_libfunc (ufloat_optab, DFmode, SImode, "__aeabi_ui2d");
+   set_conv_libfunc (sfloat_optab, DFmode, DImode, "__aeabi_l2d");
+   set_conv_libfunc (ufloat_optab, DFmode, DImode, "__aeabi_ul2d");
+   set_conv_libfunc (sfloat_optab, SFmode, SImode, "__aeabi_i2f");
+   set_conv_libfunc (ufloat_optab, SFmode, SImode, "__aeabi_ui2f");
+   set_conv_libfunc (sfloat_optab, SFmode, DImode, "__aeabi_l2f");
+   set_conv_libfunc (ufloat_optab, SFmode, DImode, "__aeabi_ul2f");
+ 
+   /* Long long.  Table 9.  */
+   set_optab_libfunc (smul_optab, DImode, "__aeabi_lmul");
+   set_optab_libfunc (sdivmod_optab, DImode, "__aeabi_ldivmod");
+   set_optab_libfunc (udivmod_optab, DImode, "__aeabi_uldivmod");
+   set_optab_libfunc (ashl_optab, DImode, "__aeabi_llsl");
+   set_optab_libfunc (lshr_optab, DImode, "__aeabi_llsr");
+   set_optab_libfunc (ashr_optab, DImode, "__aeabi_lasr");
+   set_optab_libfunc (cmp_optab, DImode, "__aeabi_lcmp");
+   set_optab_libfunc (ucmp_optab, DImode, "__aeabi_ulcmp");
+ 
+   /* Integer (32/32->32) division.  \S 4.3.1.  */
+   set_optab_libfunc (sdivmod_optab, SImode, "__aeabi_idivmod");
+   set_optab_libfunc (udivmod_optab, SImode, "__aeabi_uidivmod");
+ 
+   /* The divmod functions are designed so that they can be used for
+      plain division, even though they return both the quotient and the
+      remainder.  The quotient is returned in the usual location (i.e.,
+      r0 for SImode, {r0, r1} for DImode), just as would be expected
+      for an ordinary division routine.  Because the AAPCS calling
+      conventions specify that all of { r0, r1, r2, r3 } are
+      callee-saved registers, there is no need to tell the compiler
+      explicitly that those registers are clobbered by these
+      routines.  */
+   set_optab_libfunc (sdiv_optab, DImode, "__aeabi_ldivmod");
+   set_optab_libfunc (udiv_optab, DImode, "__aeabi_uldivmod");
+   set_optab_libfunc (sdiv_optab, SImode, "__aeabi_idivmod");
+   set_optab_libfunc (udiv_optab, SImode, "__aeabi_uidivmod");
+ }
+ 
  /* Fix up any incompatible options that the user has specified.
     This has now turned into a maze.  */
  void
  arm_override_options (void)
  {
*************** arm_get_frame_offsets (void)
*** 10163,10173 ****
  
  
  /* Calculate the relative offsets for the different stack pointers.  Positive
     offsets are in the direction of stack growth.  */
  
! unsigned int
  arm_compute_initial_elimination_offset (unsigned int from, unsigned int to)
  {
    arm_stack_offsets *offsets;
  
    offsets = arm_get_frame_offsets ();
--- 10265,10275 ----
  
  
  /* Calculate the relative offsets for the different stack pointers.  Positive
     offsets are in the direction of stack growth.  */
  
! HOST_WIDE_INT
  arm_compute_initial_elimination_offset (unsigned int from, unsigned int to)
  {
    arm_stack_offsets *offsets;
  
    offsets = arm_get_frame_offsets ();
Index: gcc/config/arm/arm.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/arm/arm.h,v
retrieving revision 1.246
diff -c -5 -p -r1.246 arm.h
*** gcc/config/arm/arm.h	10 Aug 2004 16:22:46 -0000	1.246
--- gcc/config/arm/arm.h	11 Aug 2004 02:43:25 -0000
*************** extern GTY(()) rtx aof_pic_label;
*** 294,303 ****
--- 294,311 ----
  #define TARGET_CIRRUS_FIX_INVALID_INSNS	(target_flags & CIRRUS_FIX_INVALID_INSNS)
  #define TARGET_LDRD			(arm_arch5e && ARM_DOUBLEWORD_ALIGN)
  #define TARGET_AAPCS_BASED \
      (arm_abi != ARM_ABI_APCS && arm_abi != ARM_ABI_ATPCS)
  
+ /* True iff the full BPABI is being used.  If TARGET_BPABI is true,
+    then TARGET_AAPCS_BASED must be true -- but the converse does not
+    hold.  TARGET_BPABI implies the use of the BPABI runtime library,
+    etc., in addition to just the AAPCS calling conventions.  */
+ #ifndef TARGET_BPABI
+ #define TARGET_BPABI false
+ #endif 
+ 
  /* SUBTARGET_SWITCHES is used to add flags on a per-config basis.  */
  #ifndef SUBTARGET_SWITCHES
  #define SUBTARGET_SWITCHES
  #endif
  
Index: gcc/config/arm/bpabi.S
===================================================================
RCS file: gcc/config/arm/bpabi.S
diff -N gcc/config/arm/bpabi.S
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- gcc/config/arm/bpabi.S	11 Aug 2004 02:43:25 -0000
***************
*** 0 ****
--- 1,95 ----
+ /* Miscellaneous BPABI functions.
+ 
+    Copyright (C) 2003, 2004  Free Software Foundation, Inc.
+    Contributed by CodeSourcery, LLC.
+ 
+    This file is free software; you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by the
+    Free Software Foundation; either version 2, or (at your option) any
+    later version.
+ 
+    In addition to the permissions in the GNU General Public License, the
+    Free Software Foundation gives you unlimited permission to link the
+    compiled version of this file into combinations with other programs,
+    and to distribute those combinations without any restriction coming
+    from the use of this file.  (The General Public License restrictions
+    do apply in other respects; for example, they cover modification of
+    the file, and distribution when not linked into a combine
+    executable.)
+ 
+    This file is distributed in the hope that it will be useful, but
+    WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    General Public License for more details.
+ 
+    You should have received a copy of the GNU General Public License
+    along with this program; see the file COPYING.  If not, write to
+    the Free Software Foundation, 59 Temple Place - Suite 330,
+    Boston, MA 02111-1307, USA.  */
+ 
+ #ifdef __ARMEB__
+ #define xxh r0
+ #define xxl r1
+ #define yyh r2
+ #define yyl r3
+ #else
+ #define xxh r1
+ #define xxl r0
+ #define yyh r3
+ #define yyl r2
+ #endif	
+ 	
+ #ifdef L_aeabi_lcmp
+ 
+ ARM_FUNC_START aeabi_lcmp
+ 	subs	ip, xxl, yyl
+ 	sbcs	ip, xxh, yyh
+ 	subeqs  ip, xxl, yyl
+ 	mov	r0, ip
+ 	RET
+ 	FUNC_END aeabi_lcmp
+ 
+ #endif /* L_aeabi_lcmp */
+ 	
+ #ifdef L_aeabi_ulcmp
+ 
+ ARM_FUNC_START aeabi_ulcmp
+ 	cmp	xxh, yyh
+ 	movlo	r0, #-1
+ 	movhi	r0, #1
+ 	RETc(ne)
+ 	cmp	xxl, yyl
+ 	movlo	r0, #-1
+ 	movhi	r0, #1
+ 	moveq	r0, #0
+ 	RET
+ 	FUNC_END aeabi_ulcmp
+ 
+ #endif /* L_aeabi_ulcmp */
+ 
+ #ifdef L_aeabi_ldivmod
+ 
+ ARM_FUNC_START aeabi_ldivmod
+ 	sub sp, sp, #8
+ 	stmfd sp!, {sp, lr}
+ 	bl SYM(__gnu_ldivmod_helper) __PLT__
+ 	ldr lr, [sp, #4]
+ 	add sp, sp, #8
+ 	ldmfd sp!, {r2, r3}
+ 	RET
+ 	
+ #endif /* L_aeabi_ldivmod */
+ 
+ #ifdef L_aeabi_uldivmod
+ 
+ ARM_FUNC_START aeabi_uldivmod
+ 	sub sp, sp, #8
+ 	stmfd sp!, {sp, lr}
+ 	bl SYM(__gnu_uldivmod_helper) __PLT__
+ 	ldr lr, [sp, #4]
+ 	add sp, sp, #8
+ 	ldmfd sp!, {r2, r3}
+ 	RET
+ 	
+ #endif /* L_aeabi_divmod */
+ 	
Index: gcc/config/arm/bpabi.c
===================================================================
RCS file: gcc/config/arm/bpabi.c
diff -N gcc/config/arm/bpabi.c
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- gcc/config/arm/bpabi.c	11 Aug 2004 02:43:25 -0000
***************
*** 0 ****
--- 1,94 ----
+ /* Miscellaneous BPABI functions.
+ 
+    Copyright (C) 2003, 2004  Free Software Foundation, Inc.
+    Contributed by CodeSourcery, LLC.
+ 
+    This file is free software; you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by the
+    Free Software Foundation; either version 2, or (at your option) any
+    later version.
+ 
+    In addition to the permissions in the GNU General Public License, the
+    Free Software Foundation gives you unlimited permission to link the
+    compiled version of this file into combinations with other programs,
+    and to distribute those combinations without any restriction coming
+    from the use of this file.  (The General Public License restrictions
+    do apply in other respects; for example, they cover modification of
+    the file, and distribution when not linked into a combine
+    executable.)
+ 
+    This file is distributed in the hope that it will be useful, but
+    WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    General Public License for more details.
+ 
+    You should have received a copy of the GNU General Public License
+    along with this program; see the file COPYING.  If not, write to
+    the Free Software Foundation, 59 Temple Place - Suite 330,
+    Boston, MA 02111-1307, USA.  */
+ 
+ extern double __aeabi_ul2d (unsigned long long);
+ extern float __aeabi_ul2f (unsigned long long);
+ extern long long __divdi3 (long long, long long);
+ extern unsigned long long __udivdi3 (unsigned long long, 
+ 				     unsigned long long);
+ extern long long __gnu_ldivmod_helper (long long, long long, long long *);
+ extern unsigned long long __gnu_uldivmod_helper (unsigned long long, 
+ 						 unsigned long long, 
+ 						 unsigned long long *);
+ 
+ /* These functions are based on __floatdidf and __floatdisf, but
+    convert unsigned DImode values instead of signed DImode
+    values.  */
+ 
+ #define WORD_SIZE (sizeof (int) * 8)
+ #define HIGH_HALFWORD_COEFF (((unsigned long long) 1) << (WORD_SIZE / 2))
+ #define HIGH_WORD_COEFF (((unsigned long long) 1) << WORD_SIZE)
+ 
+ double
+ __aeabi_ul2d (unsigned long long u)
+ {
+   double d = (unsigned) (u >> WORD_SIZE);
+   d *= HIGH_HALFWORD_COEFF;
+   d *= HIGH_HALFWORD_COEFF;
+   d += (unsigned) (u & (HIGH_WORD_COEFF - 1));
+ 
+   return d;
+ }
+ 
+ float
+ __aeabi_ul2f (unsigned long long u)
+ {
+   /* Do the calculation in DFmode so that we don't lose any of the
+      precision of the high word while multiplying it.  */
+   double f = (unsigned) (u >> WORD_SIZE);
+   f *= HIGH_HALFWORD_COEFF;
+   f *= HIGH_HALFWORD_COEFF;
+   f += (unsigned) (u & (HIGH_WORD_COEFF - 1));
+ 
+   return (float) f;
+ }
+ 
+ long long
+ __gnu_ldivmod_helper (long long a, 
+ 		      long long b, 
+ 		      long long *remainder)
+ {
+   long long quotient;
+ 
+   quotient = __divdi3 (a, b);
+   *remainder = a - b * quotient;
+   return quotient;
+ }
+ 
+ unsigned long long
+ __gnu_uldivmod_helper (unsigned long long a, 
+ 		       unsigned long long b,
+ 		       unsigned long long *remainder)
+ {
+   unsigned long long quotient;
+ 
+   quotient = __udivdi3 (a, b);
+   *remainder = a - b * quotient;
+   return quotient;
+ }
Index: gcc/config/arm/bpabi.h
===================================================================
RCS file: gcc/config/arm/bpabi.h
diff -N gcc/config/arm/bpabi.h
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- gcc/config/arm/bpabi.h	11 Aug 2004 02:43:25 -0000
***************
*** 0 ****
--- 1,83 ----
+ /* Configuration file for ARM BPABI targets.
+    Copyright (C) 2004
+    Free Software Foundation, Inc.
+    Contributed by CodeSourcery, LLC   
+ 
+    This file is part of GCC.
+ 
+    GCC is free software; you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published
+    by the Free Software Foundation; either version 2, or (at your
+    option) any later version.
+ 
+    GCC is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+    License for more details.
+ 
+    You should have received a copy of the GNU General Public License
+    along with GCC; see the file COPYING.  If not, write to
+    the Free Software Foundation, 59 Temple Place - Suite 330,
+    Boston, MA 02111-1307, USA.  */
+ 
+ /* Use the AAPCS ABI by default.  */
+ #define ARM_DEFAULT_ABI ARM_ABI_AAPCS
+ 
+ /* Assume that AAPCS ABIs should adhere to the full BPABI.  */ 
+ #define TARGET_BPABI (TARGET_AAPCS_BASED)
+ 
+ /* The ARM BPABI functions return a boolean; they use no special
+    calling convention.  */
+ #define FLOAT_LIB_COMPARE_RETURNS_BOOL(MODE, COMPARISON) TARGET_BPABI
+ 
+ /* Do not generate calls to any of the standard GCC functions in
+    libgcc when generating BPABI code.  */
+ #define TARGET_LIBGCC_LIBFUNCS !TARGET_BPABI
+ 
+ /* The BPABI integer comparision routines return { -1, 0, 1 }.  */
+ #define TARGET_LIB_INT_CMP_BIASED !TARGET_BPABI
+ 
+ /* The generic link spec in elf.h does not support shared libraries.  */
+ #undef LINK_SPEC
+ #define LINK_SPEC "%{mbig-endian:-EB} %{mlittle-endian:-EL} "		\
+   "%{static:-Bstatic} %{shared:-shared} %{symbolic:-Bsymbolic} "	\
+   "-X"
+ 
+ #if defined (__thumb__) && !defined (__THUMB_INTERWORD) 
+ #define RENAME_LIBRARY_SET ".thumb_set"
+ #else
+ #define RENAME_LIBRARY_SET ".set"
+ #endif
+ 
+ /* Make __aeabi_AEABI_NAME an alias for __GCC_NAME.  */
+ #define RENAME_LIBRARY(GCC_NAME, AEABI_NAME)		\
+   __asm__ (".globl\t__aeabi_" #AEABI_NAME "\n"		\
+ 	   RENAME_LIBRARY_SET "\t__aeabi_" #AEABI_NAME 	\
+ 	     ", __" #GCC_NAME "\n");
+ 
+ /* Give some libgcc functions an additional __aeabi name.  */
+ #ifdef L_muldi3
+ #define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (muldi3, lmul)
+ #endif
+ #ifdef L_muldi3
+ #define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (muldi3, lmul)
+ #endif
+ #ifdef L_fixdfdi
+ #define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (fixdfdi, d2lz)
+ #endif
+ #ifdef L_fixunsdfdi
+ #define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (fixunsdfdi, d2ulz)
+ #endif
+ #ifdef L_fixsfdi
+ #define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (fixsfdi, f2lz)
+ #endif
+ #ifdef L_fixunssfdi
+ #define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (fixunssfdi, f2ulz)
+ #endif
+ #ifdef L_floatdidf
+ #define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (floatdidf, l2d)
+ #endif
+ #ifdef L_floatdisf
+ #define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (floatdisf, l2f)
+ #endif
+ 
Index: gcc/config/arm/ieee754-df.S
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/arm/ieee754-df.S,v
retrieving revision 1.5
diff -c -5 -p -r1.5 ieee754-df.S
*** gcc/config/arm/ieee754-df.S	3 Mar 2004 16:09:28 -0000	1.5
--- gcc/config/arm/ieee754-df.S	11 Aug 2004 02:43:25 -0000
***************
*** 57,84 ****
  
  
  #ifdef L_negdf2
  
  ARM_FUNC_START negdf2
  	@ flip sign bit
  	eor	xh, xh, #0x80000000
  	RET
  
  	FUNC_END negdf2
  
  #endif
  
  #ifdef L_addsubdf3
  
! ARM_FUNC_START subdf3
  	@ flip sign bit of second arg
  	eor	yh, yh, #0x80000000
  #if defined(__thumb__) && !defined(__THUMB_INTERWORK__)
  	b	1f			@ Skip Thumb-code prologue
  #endif
  
  ARM_FUNC_START adddf3
  
  1:	@ Compare both args, return zero if equal but the sign.
  	teq	xl, yl
  	eoreq	ip, xh, yh
  	teqeq	ip, #0x80000000
--- 57,93 ----
  
  
  #ifdef L_negdf2
  
  ARM_FUNC_START negdf2
+ ARM_FUNC_ALIAS aeabi_dneg negdf2
  	@ flip sign bit
  	eor	xh, xh, #0x80000000
  	RET
  
+ 	FUNC_END aeabi_dneg
  	FUNC_END negdf2
  
  #endif
  
  #ifdef L_addsubdf3
  
! ARM_FUNC_START aeabi_drsub
! 
! 	eor	xh, xh, #0x80000000	@ flip sign bit of first arg
! 	b	1f	
! 
! 	ARM_FUNC_START subdf3
! ARM_FUNC_ALIAS aeabi_dsub subdf3
  	@ flip sign bit of second arg
  	eor	yh, yh, #0x80000000
  #if defined(__thumb__) && !defined(__THUMB_INTERWORK__)
  	b	1f			@ Skip Thumb-code prologue
  #endif
  
  ARM_FUNC_START adddf3
+ ARM_FUNC_ALIAS aeabi_dadd adddf3
  
  1:	@ Compare both args, return zero if equal but the sign.
  	teq	xl, yl
  	eoreq	ip, xh, yh
  	teqeq	ip, #0x80000000
*************** LSYM(Lad_i):
*** 371,384 ****
--- 380,396 ----
  	teqeq	xh, yh
  	orrne	xh, r5, #0x00080000
  	movne	xl, #0
  	RETLDM	"r4, r5"
  
+ 	FUNC_END aeabi_dsub
  	FUNC_END subdf3
+ 	FUNC_END aeabi_dadd
  	FUNC_END adddf3
  
  ARM_FUNC_START floatunsidf
+ ARM_FUNC_ALIAS aeabi_ui2d floatunsidf
  	teq	r0, #0
  	moveq	r1, #0
  	RETc(eq)
  	stmfd	sp!, {r4, r5, lr}
  	mov	r4, #(0x400 << 20)	@ initial exponent
*************** ARM_FUNC_START floatunsidf
*** 386,398 ****
--- 398,412 ----
  	mov	r5, #0			@ sign bit is 0
  	mov	xl, r0
  	mov	xh, #0
  	b	LSYM(Lad_l)
  
+ 	FUNC_END aeabi_ui2d
  	FUNC_END floatunsidf
  
  ARM_FUNC_START floatsidf
+ ARM_FUNC_ALIAS aeabi_i2d floatsidf
  	teq	r0, #0
  	moveq	r1, #0
  	RETc(eq)
  	stmfd	sp!, {r4, r5, lr}
  	mov	r4, #(0x400 << 20)	@ initial exponent
*************** ARM_FUNC_START floatsidf
*** 401,413 ****
--- 415,430 ----
  	rsbmi	r0, r0, #0		@ absolute value
  	mov	xl, r0
  	mov	xh, #0
  	b	LSYM(Lad_l)
  
+ 	FUNC_END aeabi_i2d
  	FUNC_END floatsidf
  
  ARM_FUNC_START extendsfdf2
+ ARM_FUNC_ALIAS aeabi_f2d extendsfdf2
+ 	
  	movs	r2, r0, lsl #1
  	beq	1f			@ value is 0.0 or -0.0
  	mov	xh, r2, asr #3		@ stretch exponent
  	mov	xh, xh, rrx		@ retrieve sign bit
  	mov	xl, r2, lsl #28		@ retrieve remaining bits
*************** ARM_FUNC_START extendsfdf2
*** 427,444 ****
  	add	r4, r4, #(1 << 20)
  	and	r5, xh, #0x80000000	@ move sign bit in r5
  	bic	xh, xh, #0x80000000
  	b	LSYM(Lad_l)
  
  	FUNC_END extendsfdf2
  
  #endif /* L_addsubdf3 */
  
  #ifdef L_muldivdf3
  
  ARM_FUNC_START muldf3
! 
  	stmfd	sp!, {r4, r5, r6, lr}
  
  	@ Mask out exponents.
  	mov	ip, #0x7f000000
  	orr	ip, ip, #0x00f00000
--- 444,462 ----
  	add	r4, r4, #(1 << 20)
  	and	r5, xh, #0x80000000	@ move sign bit in r5
  	bic	xh, xh, #0x80000000
  	b	LSYM(Lad_l)
  
+ 	FUNC_END aeabi_f2d
  	FUNC_END extendsfdf2
  
  #endif /* L_addsubdf3 */
  
  #ifdef L_muldivdf3
  
  ARM_FUNC_START muldf3
! ARM_FUNC_ALIAS aeabi_dmul muldf3
  	stmfd	sp!, {r4, r5, r6, lr}
  
  	@ Mask out exponents.
  	mov	ip, #0x7f000000
  	orr	ip, ip, #0x00f00000
*************** LSYM(Lml_o):
*** 720,733 ****
  LSYM(Lml_n):
  	mov	xh, #0x7f000000
  	orr	xh, xh, #0x00f80000
  	RETLDM	"r4, r5, r6"
  
  	FUNC_END muldf3
  
  ARM_FUNC_START divdf3
! 
  	stmfd	sp!, {r4, r5, r6, lr}
  
  	@ Mask out exponents.
  	mov	ip, #0x7f000000
  	orr	ip, ip, #0x00f00000
--- 738,753 ----
  LSYM(Lml_n):
  	mov	xh, #0x7f000000
  	orr	xh, xh, #0x00f80000
  	RETLDM	"r4, r5, r6"
  
+ 	FUNC_END aeabi_dmul
  	FUNC_END muldf3
  
  ARM_FUNC_START divdf3
! ARM_FUNC_ALIAS aeabi_ddiv divdf3
! 	
  	stmfd	sp!, {r4, r5, r6, lr}
  
  	@ Mask out exponents.
  	mov	ip, #0x7f000000
  	orr	ip, ip, #0x00f00000
*************** LSYM(Ldv_s):
*** 932,941 ****
--- 952,962 ----
  	bne	LSYM(Lml_i)		@ <non_zero> / 0 -> INF
  	orrs	r5, yl, yh, lsl #1
  	bne	LSYM(Lml_z)		@ 0 / <non_zero> -> 0
  	b	LSYM(Lml_n)		@ 0 / 0 -> NAN
  
+ 	FUNC_END aeabi_ddiv
  	FUNC_END divdf3
  
  #endif /* L_muldivdf3 */
  
  #ifdef L_cmpdf2
*************** ARM_FUNC_ALIAS eqdf2 cmpdf2
*** 1011,1025 ****
--- 1032,1113 ----
  	FUNC_END ltdf2
  	FUNC_END nedf2
  	FUNC_END eqdf2
  	FUNC_END cmpdf2
  
+ ARM_FUNC_START aeabi_cdrcmple
+ 	mov	ip, r0
+ 	mov	r0, r2
+ 	mov	r2, ip
+ 	mov	ip, r1
+ 	mov	r1, r3
+ 	mov	r3, ip
+ 	b	6f
+ 	
+ ARM_FUNC_START aeabi_cdcmpeq
+ ARM_FUNC_ALIAS aeabi_cdcmple aeabi_cdcmpeq
+ 	@ The status-returning routines are required to preserve all
+ 	@ registers except ip, lr, and cpsr.
+ 6:	stmfd	sp!, {r0, r1, r2, r3, lr}
+ 	ARM_CALL cmpdf2
+ 	@ Set the Z flag correctly, and the C flag unconditionally.
+ 	cmp	 r0, #0
+ 	@ Clear the C flag if the return value was -1, indicating
+ 	@ that the first operand was smaller than the second.
+ 	cmnmi	 r0, #0
+ 	RETLDM   "r0, r1, r2, r3"
+ 	FUNC_END aeabi_cdcmple
+ 	FUNC_END aeabi_cdcmpeq
+ 	
+ ARM_FUNC_START	aeabi_dcmpeq
+ 	str	lr, [sp, #-4]!
+ 	ARM_CALL aeabi_cdcmple
+ 	moveq	r0, #1	@ Equal to.
+ 	movne	r0, #0	@ Less than, greater than, or unordered.
+ 	RETLDM
+ 	FUNC_END aeabi_dcmpeq
+ 
+ ARM_FUNC_START	aeabi_dcmplt
+ 	str	lr, [sp, #-4]!
+ 	ARM_CALL aeabi_cdcmple
+ 	movcc	r0, #1	@ Less than.
+ 	movcs	r0, #0	@ Equal to, greater than, or unordered.
+ 	RETLDM
+ 	FUNC_END aeabi_dcmplt
+ 
+ ARM_FUNC_START	aeabi_dcmple
+ 	str	lr, [sp, #-4]!
+ 	ARM_CALL aeabi_cdcmple
+ 	movls	r0, #1  @ Less than or equal to.
+ 	movhi	r0, #0	@ Greater than or unordered.
+ 	RETLDM
+ 	FUNC_END aeabi_dcmple
+ 
+ ARM_FUNC_START	aeabi_dcmpge
+ 	str	lr, [sp, #-4]!
+ 	ARM_CALL aeabi_cdrcmple
+ 	movls	r0, #1	@ Operand 2 is less than or equal to operand 1.
+ 	movhi	r0, #0	@ Operand 2 greater than operand 1, or unordered.
+ 	RETLDM
+ 	FUNC_END aeabi_dcmpge
+ 
+ ARM_FUNC_START	aeabi_dcmpgt
+ 	str	lr, [sp, #-4]!
+ 	ARM_CALL aeabi_cdrcmple
+ 	movcc	r0, #1	@ Operand 2 is less than operand 1.
+ 	movcs	r0, #0  @ Operand 2 is greater than or equal to operand 1,
+ 			@ or they are unordered.
+ 	RETLDM
+ 	FUNC_END aeabi_dcmpgt
+ 		
  #endif /* L_cmpdf2 */
  
  #ifdef L_unorddf2
  
  ARM_FUNC_START unorddf2
+ ARM_FUNC_ALIAS aeabi_dcmpun unorddf2
+ 	
  	str	lr, [sp, #-4]!
  	mov	ip, #0x7f000000
  	orr	ip, ip, #0x00f00000
  	and	lr, xh, ip
  	teq	lr, ip
*************** ARM_FUNC_START unorddf2
*** 1035,1051 ****
--- 1123,1141 ----
  	RETLDM
  
  3:	mov	r0, #1			@ arguments are unordered.
  	RETLDM
  
+ 	FUNC_END aeabi_dcmpun
  	FUNC_END unorddf2
  
  #endif /* L_unorddf2 */
  
  #ifdef L_fixdfsi
  
  ARM_FUNC_START fixdfsi
+ ARM_FUNC_ALIAS aeabi_d2iz fixdfsi
  	orrs	ip, xl, xh, lsl #1
  	beq	1f			@ value is 0.
  
  	mov	r3, r3, rrx		@ preserve C flag (the actual sign)
  
*************** ARM_FUNC_START fixdfsi
*** 1082,1098 ****
--- 1172,1190 ----
  	RET
  
  4:	mov	r0, #0			@ How should we convert NAN?
  	RET
  
+ 	FUNC_END aeabi_d2iz
  	FUNC_END fixdfsi
  
  #endif /* L_fixdfsi */
  
  #ifdef L_fixunsdfsi
  
  ARM_FUNC_START fixunsdfsi
+ ARM_FUNC_ALIAS aeabi_d2uiz fixunsdfsi
  	orrs	ip, xl, xh, lsl #1
  	movcss	r0, #0			@ value is negative
  	RETc(eq)			@ or 0 (xl, xh overlap r0)
  
  	@ check exponent range.
*************** ARM_FUNC_START fixunsdfsi
*** 1125,1141 ****
--- 1217,1235 ----
  	RET
  
  4:	mov	r0, #0			@ How should we convert NAN?
  	RET
  
+ 	FUNC_END aeabi_d2uiz
  	FUNC_END fixunsdfsi
  
  #endif /* L_fixunsdfsi */
  
  #ifdef L_truncdfsf2
  
  ARM_FUNC_START truncdfsf2
+ ARM_FUNC_ALIAS aeabi_d2f truncdfsf2
  	orrs	r2, xl, xh, lsl #1
  	moveq	r0, r2, rrx
  	RETc(eq)			@ value is 0.0 or -0.0
  	
  	@ check exponent range.
*************** ARM_FUNC_START truncdfsf2
*** 1217,1224 ****
--- 1311,1319 ----
  	mov	xl, xl, lsr ip
  	orr	xl, xl, xh, lsl r2
  	and	xh, xh, #0x80000000
  	b	5b
  
+ 	FUNC_END aeabi_d2f
  	FUNC_END truncdfsf2
  
  #endif /* L_truncdfsf2 */
Index: gcc/config/arm/ieee754-sf.S
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/arm/ieee754-sf.S,v
retrieving revision 1.4
diff -c -5 -p -r1.4 ieee754-sf.S
*** gcc/config/arm/ieee754-sf.S	15 Jan 2004 16:56:34 -0000	1.4
--- gcc/config/arm/ieee754-sf.S	11 Aug 2004 02:43:25 -0000
***************
*** 39,65 ****
   */
  
  #ifdef L_negsf2
  	
  ARM_FUNC_START negsf2
  	eor	r0, r0, #0x80000000	@ flip sign bit
  	RET
  
  	FUNC_END negsf2
  
  #endif
  
  #ifdef L_addsubsf3
  
  ARM_FUNC_START subsf3
  	eor	r1, r1, #0x80000000	@ flip sign bit of second arg
  #if defined(__thumb__) && !defined(__THUMB_INTERWORK__)
  	b	1f			@ Skip Thumb-code prologue
  #endif
  
  ARM_FUNC_START addsf3
! 
  1:	@ Compare both args, return zero if equal but the sign.
  	eor	r2, r0, r1
  	teq	r2, #0x80000000
  	beq	LSYM(Lad_z)
  
--- 39,76 ----
   */
  
  #ifdef L_negsf2
  	
  ARM_FUNC_START negsf2
+ ARM_FUNC_ALIAS aeabi_fneg negsf2
+ 	
  	eor	r0, r0, #0x80000000	@ flip sign bit
  	RET
  
+ 	FUNC_END aeabi_fneg
  	FUNC_END negsf2
  
  #endif
  
  #ifdef L_addsubsf3
  
+ ARM_FUNC_START aeabi_frsub
+ 
+ 	eor	r0, r0, #0x80000000	@ flip sign bit of first arg
+ 	b	1f	
+ 	
  ARM_FUNC_START subsf3
+ ARM_FUNC_ALIAS aeabi_fsub subsf3
+ 	
  	eor	r1, r1, #0x80000000	@ flip sign bit of second arg
  #if defined(__thumb__) && !defined(__THUMB_INTERWORK__)
  	b	1f			@ Skip Thumb-code prologue
  #endif
  
  ARM_FUNC_START addsf3
! ARM_FUNC_ALIAS aeabi_fadd addsf3
! 	
  1:	@ Compare both args, return zero if equal but the sign.
  	eor	r2, r0, r1
  	teq	r2, #0x80000000
  	beq	LSYM(Lad_z)
  
*************** LSYM(Lad_i):
*** 256,273 ****
--- 267,291 ----
  	moveqs	r2, r1, lsl #9
  	teqeq	r0, r1
  	orrne	r0, r3, #0x00400000	@ NAN
  	RET
  
+ 	FUNC_END aeabi_frsub
+ 	FUNC_END aeabi_fadd
  	FUNC_END addsf3
+ 	FUNC_END aeabi_fsub
  	FUNC_END subsf3
  
  ARM_FUNC_START floatunsisf
+ ARM_FUNC_ALIAS aeabi_ui2f floatunsisf
+ 		
  	mov	r3, #0
  	b	1f
  
  ARM_FUNC_START floatsisf
+ ARM_FUNC_ALIAS aeabi_i2f floatsisf
+ 	
  	ands	r3, r0, #0x80000000
  	rsbmi	r0, r0, #0
  
  1:	teq	r0, #0
  	RETc(eq)
*************** ARM_FUNC_START floatsisf
*** 288,306 ****
  	orr	r1, r1, r0, lsl #30
  	mov	r0, r0, lsr #2
  	add	r2, r2, #(2 << 23)
  	b	LSYM(Lad_p)
  
  	FUNC_END floatsisf
  	FUNC_END floatunsisf
  
  #endif /* L_addsubsf3 */
  
  #ifdef L_muldivsf3
  
  ARM_FUNC_START mulsf3
! 
  	@ Mask out exponents.
  	mov	ip, #0xff000000
  	and	r2, r0, ip, lsr #1
  	and	r3, r1, ip, lsr #1
  
--- 306,327 ----
  	orr	r1, r1, r0, lsl #30
  	mov	r0, r0, lsr #2
  	add	r2, r2, #(2 << 23)
  	b	LSYM(Lad_p)
  
+ 	FUNC_END aeabi_i2f
  	FUNC_END floatsisf
+ 	FUNC_END aeabi_ui2f
  	FUNC_END floatunsisf
  
  #endif /* L_addsubsf3 */
  
  #ifdef L_muldivsf3
  
  ARM_FUNC_START mulsf3
! ARM_FUNC_ALIAS aeabi_fmul mulsf3
! 	
  	@ Mask out exponents.
  	mov	ip, #0xff000000
  	and	r2, r0, ip, lsr #1
  	and	r3, r1, ip, lsr #1
  
*************** LSYM(Lml_o):
*** 483,496 ****
  LSYM(Lml_n):
  	mov	r0, #0x7f000000
  	orr	r0, r0, #0x00c00000
  	RET
  
  	FUNC_END mulsf3
  
  ARM_FUNC_START divsf3
! 
  	@ Mask out exponents.
  	mov	ip, #0xff000000
  	and	r2, r0, ip, lsr #1
  	and	r3, r1, ip, lsr #1
  
--- 504,519 ----
  LSYM(Lml_n):
  	mov	r0, #0x7f000000
  	orr	r0, r0, #0x00c00000
  	RET
  
+ 	FUNC_END aeabi_fmul
  	FUNC_END mulsf3
  
  ARM_FUNC_START divsf3
! ARM_FUNC_ALIAS aeabi_fdiv divsf3
! 	
  	@ Mask out exponents.
  	mov	ip, #0xff000000
  	and	r2, r0, ip, lsr #1
  	and	r3, r1, ip, lsr #1
  
*************** LSYM(Ldv_s):
*** 634,649 ****
--- 657,688 ----
  	bne	LSYM(Lml_i)		@ <non_zero> / 0 -> INF
  	bics	r3, r1, #0x80000000
  	bne	LSYM(Lml_z)		@ 0 / <non_zero> -> 0
  	b	LSYM(Lml_n)		@ 0 / 0 -> NAN
  
+ 	FUNC_END aeabi_fdiv
  	FUNC_END divsf3
  
  #endif /* L_muldivsf3 */
  
  #ifdef L_cmpsf2
  
+ 	@ The return value in r0 is
+ 	@
+ 	@   0  if the operands are equal
+ 	@   1  if the first operand is greater than the second, or
+ 	@      the operands are unordered and the operation is
+ 	@      CMP, LT, LE, NE, or EQ.
+ 	@   -1 if the first operand is less than the second, or
+ 	@      the operands are unordered and the operation is GT
+ 	@      or GE.
+ 	@
+ 	@ The Z flag will be set iff the operands are equal.
+ 	@
+ 	@ The following registers are clobbered by this function:
+ 	@   ip, r0, r1, r2, r3
+ 
  ARM_FUNC_START gtsf2
  ARM_FUNC_ALIAS gesf2 gtsf2
  	mov	r3, #-1
  	b	1f
  
*************** ARM_FUNC_ALIAS lesf2 ltsf2
*** 655,682 ****
  ARM_FUNC_START cmpsf2
  ARM_FUNC_ALIAS nesf2 cmpsf2
  ARM_FUNC_ALIAS eqsf2 cmpsf2
  	mov	r3, #1			@ how should we specify unordered here?
  
! 1:	@ Trap any INF/NAN first.
! 	mov	ip, #0xff000000
  	and	r2, r1, ip, lsr #1
  	teq	r2, ip, lsr #1
  	and	r2, r0, ip, lsr #1
  	teqne	r2, ip, lsr #1
  	beq	3f
  
! 	@ Test for equality.
! 	@ Note that 0.0 is equal to -0.0.
  2:	orr	r3, r0, r1
  	bics	r3, r3, #0x80000000	@ either 0.0 or -0.0
  	teqne	r0, r1			@ or both the same
  	moveq	r0, #0
  	RETc(eq)
  
! 	@ Check for sign difference.  The N flag is set if it is the case.
! 	@ If so, return sign of r0.
  	movmi	r0, r0, asr #31
  	orrmi	r0, r0, #1
  	RETc(mi)
  
  	@ Compare exponents.
--- 694,728 ----
  ARM_FUNC_START cmpsf2
  ARM_FUNC_ALIAS nesf2 cmpsf2
  ARM_FUNC_ALIAS eqsf2 cmpsf2
  	mov	r3, #1			@ how should we specify unordered here?
  
! 	@ Both Inf and NaN have an exponent of 255.  Therefore, we
! 	@ compute (r1 & 0x8f80000) || (r2 & 0x8f8000).
! 1:	mov	ip, #0xff000000
  	and	r2, r1, ip, lsr #1
  	teq	r2, ip, lsr #1
  	and	r2, r0, ip, lsr #1
  	teqne	r2, ip, lsr #1
  	beq	3f
  
! 	@ Test for equality.  The representations of +0.0 and -0.0
! 	@ have all bits set to zero, except for the sign bit.  Since
! 	@ 0.0 is equal to -0.0, we begin by testing 
! 	@ ((r0 | r1) & ~0x8000000).
  2:	orr	r3, r0, r1
+ 	@ If the result of the bitwise and is zero, then the Z flag
+ 	@ will be set.  In any case, the C flag will be set.
  	bics	r3, r3, #0x80000000	@ either 0.0 or -0.0
  	teqne	r0, r1			@ or both the same
+ 	@ If the Z flag is set, the two operands were equal.  Return zero.
  	moveq	r0, #0
  	RETc(eq)
  
! 	@ Check for sign difference.  The N flag is set (due to the
! 	@ use of teq above) if the sign bit is set on exactly one
! 	@ of the operands.  Return the sign of the first operand.
  	movmi	r0, r0, asr #31
  	orrmi	r0, r0, #1
  	RETc(mi)
  
  	@ Compare exponents.
*************** ARM_FUNC_ALIAS eqsf2 cmpsf2
*** 684,725 ****
  	cmp	r2, r3
  
  	@ Compare mantissa if exponents are equal
  	moveq	r0, r0, lsl #9
  	cmpeq	r0, r1, lsl #9
  	movcs	r0, r1, asr #31
  	mvncc	r0, r1, asr #31
  	orr	r0, r0, #1
  	RET
  
! 	@ Look for a NAN. 
  3:	and	r2, r1, ip, lsr #1
  	teq	r2, ip, lsr #1
  	bne	4f
  	movs	r2, r1, lsl #9
  	bne	5f			@ r1 is NAN
  4:	and	r2, r0, ip, lsr #1
  	teq	r2, ip, lsr #1
  	bne	2b
  	movs	ip, r0, lsl #9
  	beq	2b			@ r0 is not NAN
! 5:	mov	r0, r3			@ return unordered code from r3.
  	RET
  
  	FUNC_END gesf2
  	FUNC_END gtsf2
  	FUNC_END lesf2
  	FUNC_END ltsf2
  	FUNC_END nesf2
  	FUNC_END eqsf2
  	FUNC_END cmpsf2
  
  #endif /* L_cmpsf2 */
  
  #ifdef L_unordsf2
  
  ARM_FUNC_START unordsf2
  	mov	ip, #0xff000000
  	and	r2, r1, ip, lsr #1
  	teq	r2, ip, lsr #1
  	bne	1f
  	movs	r2, r1, lsl #9
--- 730,848 ----
  	cmp	r2, r3
  
  	@ Compare mantissa if exponents are equal
  	moveq	r0, r0, lsl #9
  	cmpeq	r0, r1, lsl #9
+ 
+ 	@ We know the operands cannot be equal at this point, so the
+ 	@ Z flag is clear.  The C flag is set if the first operand has
+ 	@ the greater exponent, or the exponents are equal and the 
+ 	@ first operand has the greater mantissa.  Therefore, if the C
+ 	@ flag is set, the first operand is greater iff the sign is
+ 	@ positive.  These next two instructions will put zero in
+ 	@ r0 if the first operand is greater, and -1 if the second
+ 	@ operand is greater.
  	movcs	r0, r1, asr #31
  	mvncc	r0, r1, asr #31
+ 	@ If r0 is 0, the first operand is greater, so return 1.  Leave
+ 	@ -1 unchanged.
  	orr	r0, r0, #1
  	RET
  
! 	@ We know that at least one argument is either Inf or NaN.
! 	@ Look for a NaN. 
  3:	and	r2, r1, ip, lsr #1
  	teq	r2, ip, lsr #1
  	bne	4f
  	movs	r2, r1, lsl #9
  	bne	5f			@ r1 is NAN
  4:	and	r2, r0, ip, lsr #1
  	teq	r2, ip, lsr #1
  	bne	2b
  	movs	ip, r0, lsl #9
  	beq	2b			@ r0 is not NAN
! 5:	@ The Z flag is clear at this point.
! 	mov	r0, r3			@ return unordered code from r3.
  	RET
  
  	FUNC_END gesf2
  	FUNC_END gtsf2
  	FUNC_END lesf2
  	FUNC_END ltsf2
  	FUNC_END nesf2
  	FUNC_END eqsf2
  	FUNC_END cmpsf2
  
+ ARM_FUNC_START aeabi_cfrcmple
+ 	mov	ip, r0
+ 	mov	r0, r1
+ 	mov	r1, ip
+ 	b	6f
+ 	
+ ARM_FUNC_START aeabi_cfcmpeq
+ ARM_FUNC_ALIAS aeabi_cfcmple aeabi_cfcmpeq
+ 	@ The status-returning routines are required to preserve all
+ 	@ registers except ip, lr, and cpsr.
+ 6:	stmfd	sp!, {r0, r1, r2, r3, lr}
+ 	ARM_CALL cmpsf2
+ 	@ Set the Z flag correctly, and the C flag unconditionally.
+ 	cmp	 r0, #0
+ 	@ Clear the C flag if the return value was -1, indicating
+ 	@ that the first operand was smaller than the second.
+ 	cmnmi	 r0, #0
+ 	RETLDM  "r0, r1, r2, r3"
+ 	FUNC_END aeabi_cfcmple
+ 	FUNC_END aeabi_cfcmpeq
+ 	
+ ARM_FUNC_START	aeabi_fcmpeq
+ 	str	lr, [sp, #-4]!
+ 	ARM_CALL aeabi_cfcmple
+ 	moveq	r0, #1	@ Equal to.
+ 	movne	r0, #0	@ Less than, greater than, or unordered.
+ 	RETLDM
+ 	FUNC_END aeabi_fcmpeq
+ 
+ ARM_FUNC_START	aeabi_fcmplt
+ 	str	lr, [sp, #-4]!
+ 	ARM_CALL aeabi_cfcmple
+ 	movcc	r0, #1	@ Less than.
+ 	movcs	r0, #0	@ Equal to, greater than, or unordered.
+ 	RETLDM
+ 	FUNC_END aeabi_fcmplt
+ 
+ ARM_FUNC_START	aeabi_fcmple
+ 	str	lr, [sp, #-4]!
+ 	ARM_CALL aeabi_cfcmple
+ 	movls	r0, #1  @ Less than or equal to.
+ 	movhi	r0, #0	@ Greater than or unordered.
+ 	RETLDM
+ 	FUNC_END aeabi_fcmple
+ 
+ ARM_FUNC_START	aeabi_fcmpge
+ 	str	lr, [sp, #-4]!
+ 	ARM_CALL aeabi_cfrcmple
+ 	movls	r0, #1	@ Operand 2 is less than or equal to operand 1.
+ 	movhi	r0, #0	@ Operand 2 greater than operand 1, or unordered.
+ 	RETLDM
+ 	FUNC_END aeabi_fcmpge
+ 
+ ARM_FUNC_START	aeabi_fcmpgt
+ 	str	lr, [sp, #-4]!
+ 	ARM_CALL aeabi_cfrcmple
+ 	movcc	r0, #1	@ Operand 2 is less than operand 1.
+ 	movcs	r0, #0  @ Operand 2 is greater than or equal to operand 1,
+ 			@ or they are unordered.
+ 	RETLDM
+ 	FUNC_END aeabi_fcmpgt
+ 		
  #endif /* L_cmpsf2 */
  
  #ifdef L_unordsf2
  
  ARM_FUNC_START unordsf2
+ ARM_FUNC_ALIAS aeabi_fcmpun unordsf2
+ 	
  	mov	ip, #0xff000000
  	and	r2, r1, ip, lsr #1
  	teq	r2, ip, lsr #1
  	bne	1f
  	movs	r2, r1, lsl #9
*************** ARM_FUNC_START unordsf2
*** 732,748 ****
--- 855,873 ----
  2:	mov	r0, #0			@ arguments are ordered.
  	RET
  3:	mov	r0, #1			@ arguments are unordered.
  	RET
  
+ 	FUNC_END aeabi_fcmpun
  	FUNC_END unordsf2
  
  #endif /* L_unordsf2 */
  
  #ifdef L_fixsfsi
  
  ARM_FUNC_START fixsfsi
+ ARM_FUNC_ALIAS aeabi_f2iz fixsfsi
  	movs	r0, r0, lsl #1
  	RETc(eq)			@ value is 0.
  
  	mov	r1, r1, rrx		@ preserve C flag (the actual sign)
  
*************** ARM_FUNC_START fixsfsi
*** 772,788 ****
--- 897,915 ----
  	RET
  
  3:	mov	r0, #0			@ What should we convert NAN to?
  	RET
  
+ 	FUNC_END aeabi_f2iz
  	FUNC_END fixsfsi
  
  #endif /* L_fixsfsi */
  
  #ifdef L_fixunssfsi
  
  ARM_FUNC_START fixunssfsi
+ ARM_FUNC_ALIAS aeabi_f2uiz fixunssfsi
  	movs	r0, r0, lsl #1
  	movcss	r0, #0			@ value is negative...
  	RETc(eq)			@ ... or 0.
  
  
*************** ARM_FUNC_START fixunssfsi
*** 809,816 ****
--- 936,944 ----
  	RET
  
  3:	mov	r0, #0			@ What should we convert NAN to?
  	RET
  
+ 	FUNC_END aeabi_f2uiz
  	FUNC_END fixunssfsi
  
  #endif /* L_fixunssfsi */
Index: gcc/config/arm/lib1funcs.asm
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/arm/lib1funcs.asm,v
retrieving revision 1.31
diff -c -5 -p -r1.31 lib1funcs.asm
*** gcc/config/arm/lib1funcs.asm	15 May 2004 17:31:51 -0000	1.31
--- gcc/config/arm/lib1funcs.asm	11 Aug 2004 02:43:25 -0000
*************** SYM (__\name):
*** 197,216 ****
--- 197,222 ----
  	nop
  	.arm
  _L__\name:		/* A hook to tell gdb that we've switched to ARM */
  .endm
  #define EQUIV .thumb_set
+ .macro  ARM_CALL name
+ 	bl	_L__\name
+ .endm
  #else
  .macro	ARM_FUNC_START name
  	.text
  	.globl SYM (__\name)
  	TYPE (__\name)
  	.align 0
  	.arm
  SYM (__\name):
  .endm
  #define EQUIV .set
+ .macro  ARM_CALL name
+ 	bl	__\name
+ .endm
  #endif
  
  .macro	ARM_FUNC_ALIAS new old
  	.globl	SYM (__\new)
  	EQUIV	SYM (__\new), SYM (__\old)
*************** LSYM(Lgot_result):
*** 647,656 ****
--- 653,671 ----
  
  #endif /* ARM version */
  
  	DIV_FUNC_END udivsi3
  
+ ARM_FUNC_START aeabi_uidivmod
+ 	stmfd	sp!, { r0, r1, lr }
+ 	ARM_CALL udivsi3
+ 	ldmfd	sp!, { r1, r2, lr }
+ 	mul	r3, r2, r0
+ 	sub	r1, r1, r3
+ 	RET
+ 	FUNC_END aeabi_uidivmod
+ 	
  #endif /* L_udivsi3 */
  /* ------------------------------------------------------------------------ */
  #ifdef L_umodsi3
  
  	FUNC_START umodsi3
*************** LSYM(Lover12):
*** 767,776 ****
--- 782,800 ----
  
  #endif /* ARM version */
  	
  	DIV_FUNC_END divsi3
  
+ ARM_FUNC_START aeabi_idivmod
+ 	stmfd	sp!, { r0, r1, lr }
+ 	ARM_CALL divsi3
+ 	ldmfd	sp!, { r1, r2, lr }
+ 	mul	r3, r2, r0
+ 	sub	r1, r1, r3
+ 	RET
+ 	FUNC_END aeabi_idivmod
+ 	
  #endif /* L_divsi3 */
  /* ------------------------------------------------------------------------ */
  #ifdef L_modsi3
  
  	FUNC_START modsi3
*************** LSYM(Lover12):
*** 832,844 ****
--- 856,872 ----
  #endif /* L_modsi3 */
  /* ------------------------------------------------------------------------ */
  #ifdef L_dvmd_tls
  
  	FUNC_START div0
+ 	ARM_FUNC_ALIAS aeabi_idiv0 div0
+ 	ARM_FUNC_ALIAS aeabi_ldiv0 div0
  
  	RET
  
+ 	FUNC_END aeabi_ldiv0
+ 	FUNC_END aeabi_idiv0
  	FUNC_END div0
  	
  #endif /* L_divmodsi_tools */
  /* ------------------------------------------------------------------------ */
  #ifdef L_dvmd_lnx
*************** LSYM(Lover12):
*** 882,892 ****
  #endif
  
  #ifdef L_lshrdi3
  
  	FUNC_START lshrdi3
! 
  #ifdef __thumb__
  	lsr	al, r2
  	mov	r3, ah
  	lsr	ah, r2
  	mov	ip, r3
--- 910,921 ----
  #endif
  
  #ifdef L_lshrdi3
  
  	FUNC_START lshrdi3
! 	ARM_FUNC_ALIAS aeabi_llsr lshrdi3
! 	
  #ifdef __thumb__
  	lsr	al, r2
  	mov	r3, ah
  	lsr	ah, r2
  	mov	ip, r3
*************** LSYM(Lover12):
*** 905,921 ****
--- 934,953 ----
  	movpl	al, ah, lsr r3
  	orrmi	al, al, ah, lsl ip
  	mov	ah, ah, lsr r2
  	RET
  #endif
+ 	FUNC_END aeabi_llsr
  	FUNC_END lshrdi3
  
  #endif
  	
  #ifdef L_ashrdi3
  	
  	FUNC_START ashrdi3
+ 	ARM_FUNC_ALIAS aeabi_lasr ashrdi3
+ 	
  #ifdef __thumb__
  	lsr	al, r2
  	mov	r3, ah
  	asr	ah, r2
  	sub	r2, #32
*************** LSYM(Lover12):
*** 939,955 ****
--- 971,990 ----
  	orrmi	al, al, ah, lsl ip
  	mov	ah, ah, asr r2
  	RET
  #endif
  
+ 	FUNC_END aeabi_lasr
  	FUNC_END ashrdi3
  
  #endif
  
  #ifdef L_ashldi3
  
  	FUNC_START ashldi3
+ 	ARM_FUNC_ALIAS aeabi_llsl ashldi3
+ 	
  #ifdef __thumb__
  	lsl	ah, r2
  	mov	r3, al
  	lsl	al, r2
  	mov	ip, r3
*************** LSYM(Lover12):
*** 968,977 ****
--- 1003,1013 ----
  	movpl	ah, al, lsl r3
  	orrmi	ah, ah, al, lsr ip
  	mov	al, al, lsl r2
  	RET
  #endif
+ 	FUNC_END aeabi_llsl
  	FUNC_END ashldi3
  
  #endif
  
  /* ------------------------------------------------------------------------ */
*************** LSYM(Lchange_\register):
*** 1102,1107 ****
  #endif /* L_interwork_call_via_rX */
  #endif /* Arch supports thumb.  */
  
  #include "ieee754-df.S"
  #include "ieee754-sf.S"
! 
--- 1138,1143 ----
  #endif /* L_interwork_call_via_rX */
  #endif /* Arch supports thumb.  */
  
  #include "ieee754-df.S"
  #include "ieee754-sf.S"
! #include "bpabi.S"
Index: gcc/config/arm/libgcc-bpabi.ver
===================================================================
RCS file: gcc/config/arm/libgcc-bpabi.ver
diff -N gcc/config/arm/libgcc-bpabi.ver
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- gcc/config/arm/libgcc-bpabi.ver	11 Aug 2004 02:43:25 -0000
***************
*** 0 ****
--- 1,63 ----
+ GCC_3.5 {
+   # BPABI symbols
+   __aeabi_cdcmpeq
+   __aeabi_cdcmple
+   __aeabi_cdrcmple
+   __aeabi_cfcmpeq
+   __aeabi_cfcmple
+   __aeabi_cfrcmple
+   __aeabi_d2f
+   __aeabi_d2iz
+   __aeabi_d2lz
+   __aeabi_d2uiz
+   __aeabi_d2ulz
+   __aeabi_dadd
+   __aeabi_dcmpeq
+   __aeabi_dcmpge
+   __aeabi_dcmpgt
+   __aeabi_dcmple
+   __aeabi_dcmplt
+   __aeabi_dcmpun
+   __aeabi_ddiv
+   __aeabi_dmul
+   __aeabi_dneg
+   __aeabi_drsub
+   __aeabi_dsub
+   __aeabi_f2d
+   __aeabi_f2iz
+   __aeabi_f2lz
+   __aeabi_f2uiz
+   __aeabi_f2ulz
+   __aeabi_fadd
+   __aeabi_fcmpeq
+   __aeabi_fcmpge
+   __aeabi_fcmpgt
+   __aeabi_fcmple
+   __aeabi_fcmplt
+   __aeabi_fcmpun
+   __aeabi_fdiv
+   __aeabi_fmul
+   __aeabi_fneg
+   __aeabi_frsub
+   __aeabi_fsub
+   __aeabi_i2d
+   __aeabi_i2f
+   __aeabi_idiv0
+   __aeabi_idivmod
+   __aeabi_l2d
+   __aeabi_l2f
+   __aeabi_lasr
+   __aeabi_lcmp
+   __aeabi_ldiv0
+   __aeabi_ldivmod
+   __aeabi_llsl
+   __aeabi_llsr
+   __aeabi_lmul
+   __aeabi_ui2d
+   __aeabi_ui2f
+   __aeabi_uidivmod
+   __aeabi_uldivmod
+   __aeabi_ulcmp
+   __aeabi_ul2d
+   __aeabi_ul2f
+ }
Index: gcc/config/arm/symbian.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/arm/symbian.h,v
retrieving revision 1.4
diff -c -5 -p -r1.4 symbian.h
*** gcc/config/arm/symbian.h	6 Aug 2004 17:51:38 -0000	1.4
--- gcc/config/arm/symbian.h	11 Aug 2004 02:43:25 -0000
***************
*** 18,30 ****
     You should have received a copy of the GNU General Public License
     along with GCC; see the file COPYING.  If not, write to
     the Free Software Foundation, 59 Temple Place - Suite 330,
     Boston, MA 02111-1307, USA.  */
  
- /* Use the SYMBIAN ABI by default.  */
- #define ARM_DEFAULT_ABI ARM_ABI_AAPCS
- 
  /* Do not expand builtin functions (unless explicitly prefixed with
     "__builtin").  Symbian OS code relies on properties of the standard
     library that go beyond those guaranteed by the ANSI/ISO standard.
     For example, "memcpy" works even with overlapping memory, like
     "memmove".  We cannot simply set flag_no_builtin in arm.c because
--- 18,27 ----
***************
*** 51,63 ****
  /* Symbian OS does not use crt0.o, unlike the generic unknown-elf
     configuration.  */
  #undef STARTFILE_SPEC
  #define STARTFILE_SPEC "crti%O%s crtbegin%O%s"
  
- /* The generic link spec in elf.h does not support shared libraries.  */
- #undef LINK_SPEC
- #define LINK_SPEC "%{mbig-endian:-EB} %{mlittle-endian:-EL} "		\
-   "%{static:-Bstatic} %{shared:-shared} %{symbolic:-Bsymbolic} "	\
-   "-X"
- 
  /* Support the "dllimport" attribute.  */
  #define TARGET_DLLIMPORT_DECL_ATTRIBUTES 1
--- 48,54 ----
Index: gcc/config/arm/t-bpabi
===================================================================
RCS file: gcc/config/arm/t-bpabi
diff -N gcc/config/arm/t-bpabi
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- gcc/config/arm/t-bpabi	11 Aug 2004 02:43:25 -0000
***************
*** 0 ****
--- 1,9 ----
+ # Add the bpabi.S functions.
+ LIB1ASMFUNCS += _aeabi_lcmp _aeabi_ulcmp _aeabi_ldivmod _aeabi_uldivmod
+ 
+ # Add the BPABI C functions.
+ LIB2FUNCS_EXTRA = $(srcdir)/config/arm/bpabi.c
+ 
+ # Add the BPABI names.
+ SHLIB_MAPFILES += $(srcdir)/config/arm/libgcc-bpabi.ver
+ 
Index: gcc/doc/tm.texi
===================================================================
RCS file: /cvs/gcc/gcc/gcc/doc/tm.texi,v
retrieving revision 1.350
diff -c -5 -p -r1.350 tm.texi
*** gcc/doc/tm.texi	10 Aug 2004 13:28:26 -0000	1.350
--- gcc/doc/tm.texi	11 Aug 2004 02:43:25 -0000
*************** return a tristate.
*** 4763,4772 ****
--- 4763,4790 ----
  GCC's own floating point libraries return tristates from the
  comparison operators, so the default returns false always.  Most ports
  don't need to define this macro.
  @end defmac
  
+ @defmac TARGET_LIBGCC_FUNCS
+ This macro should evaluate to @code{true} if the standard GCC library
+ names (like @code{__modsi3}) should be used for functions provided in
+ @file{libgcc.a}.  If this macro evaluates to @code{false}, then the
+ target must explictily set the names of all desired library functions
+ itself using the @code{TARGET_INIT_LIBFUNCS} hook.
+ @end defmac
+ 
+ @defmac TARGET_LIB_INT_CMP_BIASED
+ This macro should evaluate to @code{true} if the integer comparison
+ functions (like @code{__cmpdi2}) return 0 to indicate that the first
+ operand is smaller than the second, 1 to indicate that they are equal,
+ and 2 to indicate that the first operand is greater than the second.
+ If this macro evalutes to @code{false} the comparison functions return
+ -1, 0, and 1 instead of 0, 1, and 2.  If the target uses the routines
+ in @file{libgcc.a}, you do not need to define this macro.
+ @end defmac
+ 
  @cindex US Software GOFAST, floating point emulation library
  @cindex floating point emulation library, US Software GOFAST
  @cindex GOFAST, floating point emulation library
  @findex gofast_maybe_init_libfuncs
  @defmac US_SOFTWARE_GOFAST
Index: gcc/testsuite/gcc.dg/arm-eabi1.c
===================================================================
RCS file: gcc/testsuite/gcc.dg/arm-eabi1.c
diff -N gcc/testsuite/gcc.dg/arm-eabi1.c
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- gcc/testsuite/gcc.dg/arm-eabi1.c	11 Aug 2004 02:43:28 -0000
***************
*** 0 ****
--- 1,235 ----
+ /* { dg-do run { target arm*-*-symbianelf* arm*-*-eabi* } } */
+ /* { dg-options "" } */
+ 
+ /* This file tests most of the non-C++ run-time helper functions
+    described in Section 4 of the "Run-Time ABI for the ARM
+    Architecture".  These are basic tests; they do not try to validate
+    all of the corner cases in these routines.  
+ 
+    The functions not tested here are:
+ 
+      __aeabi_cdcmpeq
+      __aeabi_cdcmple
+      __aeabi_cdrcmple
+      __aeabi_cfcmpeq
+      __aeabi_cfcmple
+      __aeabi_cfrcmple
+      __aeabi_ldivmod
+      __aeabi_uldivmod
+      __aeabi_idivmod
+      __aeabi_uidivmod
+ 
+    These functions have non-standard calling conventions that would
+    require the use of inline assembly to test.  It would be good to
+    add such tests, but they have not yet been implemented.  
+ 
+    There are also no tests for the "division by zero", "unaligned
+    memory access", "memory copying, clearing, and setting"
+    functions.  */
+ 
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <math.h>
+ 
+ #define decl_float(code, type)					\
+   extern type __aeabi_ ## code ## add (type, type);		\
+   extern type __aeabi_ ## code ## div (type, type);		\
+   extern type __aeabi_ ## code ## mul (type, type);		\
+   extern type __aeabi_ ## code ## neg (type);			\
+   extern type __aeabi_ ## code ## rsub (type, type);		\
+   extern type __aeabi_ ## code ## sub (type, type);		\
+   extern int __aeabi_ ## code ## cmpeq (type, type);		\
+   extern int __aeabi_ ## code ## cmplt (type, type);		\
+   extern int __aeabi_ ## code ## cmple (type, type);		\
+   extern int __aeabi_ ## code ## cmpge (type, type);		\
+   extern int __aeabi_ ## code ## cmpgt (type, type);		\
+   extern int __aeabi_ ## code ## cmpun (type, type);		\
+   extern int __aeabi_ ## code ## 2iz (type);			\
+   extern unsigned int __aeabi_ ## code ## 2uiz (type);		\
+   extern long long __aeabi_ ## code ## 2lz (type);		\
+   extern unsigned long long __aeabi_ ## code ## 2ulz (type);	\
+   extern type __aeabi_i2 ## code (int);				\
+   extern type __aeabi_ui2 ## code (int);			\
+   extern type __aeabi_l2 ## code (long long);			\
+   extern type __aeabi_ul2 ## code (unsigned long long);		\
+ 								\
+   type code ## zero = 0.0;					\
+   type code ## one = 1.0;					\
+   type code ## two = 2.0;					\
+   type code ## four = 4.0;					\
+   type code ## minus_one = -1.0;				\
+   type code ## minus_two = -2.0;				\
+   type code ## minus_four = -4.0;				\
+   type code ## epsilon = 1E-32;					\
+   type code ## NaN = 0.0 / 0.0;				
+ 
+ decl_float (d, double)
+ decl_float (f, float)
+ 
+ extern float __aeabi_d2f (double);
+ extern double __aeabi_f2d (float);
+ extern long long __aeabi_lmul (long long, long long);
+ extern long long __aeabi_llsl (long long, int);
+ extern long long __aeabi_llsr (long long, int);
+ extern long long __aeabi_lasr (long long, int);
+ extern int __aeabi_lcmp (long long, long long);
+ extern int __aeabi_ulcmp (unsigned long long, unsigned long long);
+ 
+ #define eq(a, b, type, abs, epsilon, format)			\
+   {								\
+     type a1;							\
+     type b1;							\
+ 								\
+     fprintf (stderr, "%d: Test %s == %s\n", __LINE__, #a, #b);	\
+     a1 = a;							\
+     b1 = b;							\
+     if (abs (a1 - b1) > epsilon)				\
+     {								\
+       fprintf (stderr, "%d: " format " != " format "\n",	\
+ 	       __LINE__, a1, b1);				\
+       abort ();							\
+     }								\
+   }
+ 
+ #define ieq(a, b) eq (a, b, int, abs, 0, "%d")
+ #define ueq(a, b) eq (a, b, unsigned int, abs, 0, "%u")
+ #define leq(a, b) eq (a, b, long long, abs, 0, "%lld")
+ #define uleq(a, b) eq (a, b, unsigned long long, abs, 0, "%llu")
+ #define feq(a, b) eq (a, b, float, fabs, fepsilon, "%f")
+ #define deq(a, b) eq (a, b, double, fabs, depsilon, "%g")
+ 
+ int main () {
+   /* Table 2.  Double-precision floating-point arithmetic.  */
+   deq (__aeabi_dadd (dzero, done), done);
+   deq (__aeabi_dadd (done, done), dtwo);
+   deq (__aeabi_ddiv (dminus_four, dminus_two), dtwo);
+   deq (__aeabi_ddiv (dminus_two, dtwo), dminus_one);
+   deq (__aeabi_dmul (dtwo, dtwo), dfour);
+   deq (__aeabi_dmul (dminus_one, dminus_two), dtwo);
+   deq (__aeabi_dneg (dminus_one), done);
+   deq (__aeabi_dneg (dfour), dminus_four);
+   deq (__aeabi_drsub (done, dzero), dminus_one);
+   deq (__aeabi_drsub (dtwo, dminus_two), dminus_four);
+   deq (__aeabi_dsub (dzero, done), dminus_one);
+   deq (__aeabi_dsub (dminus_two, dtwo), dminus_four);
+ 
+   /* Table 3.  Double-precision floating-point comparisons.  */
+   ieq (__aeabi_dcmpeq (done, done), 1);
+   ieq (__aeabi_dcmpeq (done, dzero), 0);
+   ieq (__aeabi_dcmpeq (dNaN, dzero), 0);
+   ieq (__aeabi_dcmpeq (dNaN, dNaN), 0);
+ 
+   ieq (__aeabi_dcmplt (dzero, done), 1);
+   ieq (__aeabi_dcmplt (done, dzero), 0);
+   ieq (__aeabi_dcmplt (dzero, dzero), 0);
+   ieq (__aeabi_dcmplt (dzero, dNaN), 0);
+   ieq (__aeabi_dcmplt (dNaN, dNaN), 0);
+ 
+   ieq (__aeabi_dcmple (dzero, done), 1);
+   ieq (__aeabi_dcmple (done, dzero), 0);
+   ieq (__aeabi_dcmple (dzero, dzero), 1);
+   ieq (__aeabi_dcmple (dzero, dNaN), 0);
+   ieq (__aeabi_dcmple (dNaN, dNaN), 0);
+ 
+   ieq (__aeabi_dcmpge (dzero, done), 0);
+   ieq (__aeabi_dcmpge (done, dzero), 1);
+   ieq (__aeabi_dcmpge (dzero, dzero), 1);
+   ieq (__aeabi_dcmpge (dzero, dNaN), 0);
+   ieq (__aeabi_dcmpge (dNaN, dNaN), 0);
+ 
+   ieq (__aeabi_dcmpgt (dzero, done), 0);
+   ieq (__aeabi_dcmpgt (done, dzero), 1);
+   ieq (__aeabi_dcmplt (dzero, dzero), 0);
+   ieq (__aeabi_dcmpgt (dzero, dNaN), 0);
+   ieq (__aeabi_dcmpgt (dNaN, dNaN), 0);
+ 
+   ieq (__aeabi_dcmpun (done, done), 0);
+   ieq (__aeabi_dcmpun (done, dzero), 0);
+   ieq (__aeabi_dcmpun (dNaN, dzero), 1);
+   ieq (__aeabi_dcmpun (dNaN, dNaN), 1);
+ 
+   /* Table 4.  Single-precision floating-point arithmetic.  */
+   feq (__aeabi_fadd (fzero, fone), fone);
+   feq (__aeabi_fadd (fone, fone), ftwo);
+   feq (__aeabi_fdiv (fminus_four, fminus_two), ftwo);
+   feq (__aeabi_fdiv (fminus_two, ftwo), fminus_one);
+   feq (__aeabi_fmul (ftwo, ftwo), ffour);
+   feq (__aeabi_fmul (fminus_one, fminus_two), ftwo);
+   feq (__aeabi_fneg (fminus_one), fone);
+   feq (__aeabi_fneg (ffour), fminus_four);
+   feq (__aeabi_frsub (fone, fzero), fminus_one);
+   feq (__aeabi_frsub (ftwo, fminus_two), fminus_four);
+   feq (__aeabi_fsub (fzero, fone), fminus_one);
+   feq (__aeabi_fsub (fminus_two, ftwo), fminus_four);
+ 
+   /* Table 5.  Single-precision floating-point comparisons.  */
+   ieq (__aeabi_fcmpeq (fone, fone), 1);
+   ieq (__aeabi_fcmpeq (fone, fzero), 0);
+   ieq (__aeabi_fcmpeq (fNaN, fzero), 0);
+   ieq (__aeabi_fcmpeq (fNaN, fNaN), 0);
+ 
+   ieq (__aeabi_fcmplt (fzero, fone), 1);
+   ieq (__aeabi_fcmplt (fone, fzero), 0);
+   ieq (__aeabi_fcmplt (fzero, fzero), 0);
+   ieq (__aeabi_fcmplt (fzero, fNaN), 0);
+   ieq (__aeabi_fcmplt (fNaN, fNaN), 0);
+ 
+   ieq (__aeabi_fcmple (fzero, fone), 1);
+   ieq (__aeabi_fcmple (fone, fzero), 0);
+   ieq (__aeabi_fcmple (fzero, fzero), 1);
+   ieq (__aeabi_fcmple (fzero, fNaN), 0);
+   ieq (__aeabi_fcmple (fNaN, fNaN), 0);
+ 
+   ieq (__aeabi_fcmpge (fzero, fone), 0);
+   ieq (__aeabi_fcmpge (fone, fzero), 1);
+   ieq (__aeabi_fcmpge (fzero, fzero), 1);
+   ieq (__aeabi_fcmpge (fzero, fNaN), 0);
+   ieq (__aeabi_fcmpge (fNaN, fNaN), 0);
+ 
+   ieq (__aeabi_fcmpgt (fzero, fone), 0);
+   ieq (__aeabi_fcmpgt (fone, fzero), 1);
+   ieq (__aeabi_fcmplt (fzero, fzero), 0);
+   ieq (__aeabi_fcmpgt (fzero, fNaN), 0);
+   ieq (__aeabi_fcmpgt (fNaN, fNaN), 0);
+ 
+   ieq (__aeabi_fcmpun (fone, fone), 0);
+   ieq (__aeabi_fcmpun (fone, fzero), 0);
+   ieq (__aeabi_fcmpun (fNaN, fzero), 1);
+   ieq (__aeabi_fcmpun (fNaN, fNaN), 1);
+ 
+   /* Table 6.  Floating-point to integer conversions.  */
+   ieq (__aeabi_d2iz (dminus_one), -1);
+   ueq (__aeabi_d2uiz (done), 1);
+   leq (__aeabi_d2lz (dminus_two), -2LL);
+   uleq (__aeabi_d2ulz (dfour), 4LL);
+   ieq (__aeabi_f2iz (fminus_one), -1);
+   ueq (__aeabi_f2uiz (fone), 1);
+   leq (__aeabi_f2lz (fminus_two), -2LL);
+   uleq (__aeabi_f2ulz (ffour), 4LL);
+ 
+   /* Table 7.  Conversions between floating types.  */
+   feq (__aeabi_d2f (dtwo), ftwo);
+   deq (__aeabi_f2d (fminus_four), dminus_four);
+ 
+   /* Table 8.  Integer to floating-point conversions.  */
+   deq (__aeabi_i2d (-1), dminus_one);
+   deq (__aeabi_ui2d (2), dtwo);
+   deq (__aeabi_l2d (-1), dminus_one);
+   deq (__aeabi_ul2d (2ULL), dtwo);
+   feq (__aeabi_i2f (-1), fminus_one);
+   feq (__aeabi_ui2f (2), ftwo);
+   feq (__aeabi_l2f (-1), fminus_one);
+   feq (__aeabi_ul2f (2ULL), ftwo);
+ 
+   /* Table 9.  Long long functions.  */
+   leq (__aeabi_lmul (4LL, -1LL), -4LL);
+   leq (__aeabi_llsl (2LL, 1), 4LL);
+   leq (__aeabi_llsr (-1LL, 63), 1);
+   leq (__aeabi_lasr (-1LL, 63), -1);
+   ieq (__aeabi_lcmp (0LL, 1LL), -1);
+   ieq (__aeabi_lcmp (0LL, 0LL), 0);
+   ieq (__aeabi_lcmp (1LL, 0LL), 1);
+   ieq (__aeabi_ulcmp (0LL, 1LL), -1);
+   ieq (__aeabi_ulcmp (0LL, 0LL), 0);
+   ieq (__aeabi_ulcmp (1LL, 0LL), 1);
+ }
Index: gcc/testsuite/gcc.dg/dll-2.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/gcc.dg/dll-2.c,v
retrieving revision 1.6
diff -c -5 -p -r1.6 dll-2.c
*** gcc/testsuite/gcc.dg/dll-2.c	6 Aug 2004 02:03:29 -0000	1.6
--- gcc/testsuite/gcc.dg/dll-2.c	11 Aug 2004 02:43:28 -0000
***************
*** 6,16 ****
     but does not allow dllexport followed by dllimport.
  
     In C, it's ok to redeclare a variable so this works for variables
     and functions.  In C++, it only works for functions.  */
  
! /* { dg-require-dll } */
  
  __declspec (dllimport) int foo1 ();
  __declspec (dllexport) int foo1 ();
  
  __declspec (dllexport) int foo2 ();
--- 6,16 ----
     but does not allow dllexport followed by dllimport.
  
     In C, it's ok to redeclare a variable so this works for variables
     and functions.  In C++, it only works for functions.  */
  
! /* { dg-require-dll "" } */
  
  __declspec (dllimport) int foo1 ();
  __declspec (dllexport) int foo1 ();
  
  __declspec (dllexport) int foo2 ();
Index: gcc/testsuite/gcc.misc-tests/arm-isr.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/gcc.misc-tests/arm-isr.c,v
retrieving revision 1.1
diff -c -5 -p -r1.1 arm-isr.c
*** gcc/testsuite/gcc.misc-tests/arm-isr.c	20 Dec 2001 19:03:37 -0000	1.1
--- gcc/testsuite/gcc.misc-tests/arm-isr.c	11 Aug 2004 02:43:28 -0000
***************
*** 1,5 ****
--- 1,8 ----
+ extern void abort ();
+ extern void exit (int);
+ 
  #ifndef __thumb__
  /* There used to be a couple of bugs in the ARM's prologue and epilogue
     generation for ISR routines.  The wrong epilogue instruction would be
     generated to restore the IP register if it had to be pushed onto the
     stack, and the wrong offset was being computed for local variables if
Index: libcpp/configure.ac
===================================================================
RCS file: /cvs/gcc/gcc/libcpp/configure.ac,v
retrieving revision 1.3
diff -c -5 -p -r1.3 configure.ac
*** libcpp/configure.ac	12 Jun 2004 05:53:54 -0000	1.3
--- libcpp/configure.ac	11 Aug 2004 02:43:28 -0000
*************** if test $enable_checking != no ; then
*** 63,72 ****
--- 63,74 ----
  fi
  
  m4_changequote(,)
  case $target in
  	alpha*-*-* | \
+ 	arm*-*-eabi* | \
+ 	arm*-*-symbianelf* | \
  	x86_64-*-* | \
  	ia64-*-* | \
  	hppa*64*-*-* | parisc*64*-*-* | \
  	mips*-*-* | \
  	mmix-*-* | \



More information about the Gcc-patches mailing list