This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
PATCH: ARM BPABI library routines
- From: Mark Mitchell <mark at codesourcery dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Tue, 10 Aug 2004 19:57:19 -0700
- Subject: PATCH: ARM BPABI library routines
- Reply-to: mark at codesourcery dot com
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-*-* | \