summaryrefslogtreecommitdiff
path: root/gcc/config/arm/ieee754-sf.S
diff options
context:
space:
mode:
authormmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>2004-08-11 02:50:14 +0000
committermmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>2004-08-11 02:50:14 +0000
commit30e9913fe6eb2f1c2519cfeacdf9100ccb26cbb7 (patch)
tree8ecb27f99fc899aec528b0cc2ea297f10080750c /gcc/config/arm/ieee754-sf.S
parente042bf99fa1f08ea70f276bd0b65ebade5c10aba (diff)
downloadgcc-30e9913fe6eb2f1c2519cfeacdf9100ccb26cbb7.tar.gz
* configure.in (arm*-*-eabi*): New target.
* configure: Regenerate. * configure.ac (arm*-*-eabi*): New target. (arm*-*-symbianelf*): Likewise. * configure: Regenerated. * 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. * 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@85788 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config/arm/ieee754-sf.S')
-rw-r--r--gcc/config/arm/ieee754-sf.S150
1 files changed, 139 insertions, 11 deletions
diff --git a/gcc/config/arm/ieee754-sf.S b/gcc/config/arm/ieee754-sf.S
index 5c972452954..627fd7231d3 100644
--- a/gcc/config/arm/ieee754-sf.S
+++ b/gcc/config/arm/ieee754-sf.S
@@ -41,23 +41,34 @@
#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
@@ -258,14 +269,21 @@ LSYM(Lad_i):
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
@@ -290,7 +308,9 @@ ARM_FUNC_START floatsisf
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 */
@@ -298,7 +318,8 @@ ARM_FUNC_START floatsisf
#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
@@ -485,10 +506,12 @@ LSYM(Lml_n):
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
@@ -636,12 +659,28 @@ LSYM(Ldv_s):
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
@@ -657,24 +696,31 @@ 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
+ @ 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.
- @ Note that 0.0 is equal to -0.0.
+ @ 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 if it is the case.
- @ If so, return sign of r0.
+ @ 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)
@@ -686,12 +732,24 @@ ARM_FUNC_ALIAS eqsf2 cmpsf2
@ 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
- @ Look for a NAN.
+ @ 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
@@ -702,7 +760,8 @@ ARM_FUNC_ALIAS eqsf2 cmpsf2
bne 2b
movs ip, r0, lsl #9
beq 2b @ r0 is not NAN
-5: mov r0, r3 @ return unordered code from r3.
+5: @ The Z flag is clear at this point.
+ mov r0, r3 @ return unordered code from r3.
RET
FUNC_END gesf2
@@ -713,11 +772,75 @@ ARM_FUNC_ALIAS eqsf2 cmpsf2
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
@@ -734,6 +857,7 @@ ARM_FUNC_START unordsf2
3: mov r0, #1 @ arguments are unordered.
RET
+ FUNC_END aeabi_fcmpun
FUNC_END unordsf2
#endif /* L_unordsf2 */
@@ -741,6 +865,7 @@ ARM_FUNC_START unordsf2
#ifdef L_fixsfsi
ARM_FUNC_START fixsfsi
+ARM_FUNC_ALIAS aeabi_f2iz fixsfsi
movs r0, r0, lsl #1
RETc(eq) @ value is 0.
@@ -774,6 +899,7 @@ ARM_FUNC_START fixsfsi
3: mov r0, #0 @ What should we convert NAN to?
RET
+ FUNC_END aeabi_f2iz
FUNC_END fixsfsi
#endif /* L_fixsfsi */
@@ -781,6 +907,7 @@ ARM_FUNC_START 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.
@@ -811,6 +938,7 @@ ARM_FUNC_START fixunssfsi
3: mov r0, #0 @ What should we convert NAN to?
RET
+ FUNC_END aeabi_f2uiz
FUNC_END fixunssfsi
#endif /* L_fixunssfsi */