Commit 496b84c8 by Richard Earnshaw Committed by Richard Earnshaw

lib1funcs.asm (RETCOND): Delete.

2003-08-30  Richard Earnshaw  <rearnsha@arm.com>
	Nicolas Pitre <nico@cam.org>

* arm/lib1funcs.asm (RETCOND): Delete.
(RETLDM): New assembler macro.  Use it for returning with ldm/ldr.
(ARM_LDIV0, THUMB_LDIV0): Collapse multiple definitions.
(__ARM_ARCH__): Move here from ieee754-?f.S.
(RET, RETc): Clean up definitions.
(DIV_FUNC_END): Renamed from FUNC_END.  All uses changed.
(FUNC_END): New macro that marks the end of any function.
(ARM_FUNC_START): New macro that allows an assembler routine to be
implemented in ARM code even if a Thumb-only build.
Unconditionally include ieee754-?f.S.
* arm/ieee754-df.S: Delete macros moved to lib1funcs.asm.
Mark ends of functions.
Split into separate conditionally-compiled units.
Use RETLDM to return from routines.
* arm/ieee754-sf.S: Similarly.
* t-arm-elf (LIB1ASMFUNCS): Remove _ieee754_dp and _ieee754_sp.
Add _negdf2 _addsubdf3 _muldivdf3 _cmpdf2 _unorddf2 _fixdfsi
_truncdfsf2 _negsf2 _addsubsf3 _muldivsf3 _cmpsf2 _unordsf2
_fixsfsi and _fixunssfsi.

* arm/ieee754-df.S (__muldf3): Fix bug when result of a
multiplication underflows to zero.
(__adddf3): Fix bug when using VFP ordering on little-endian
processors.
(__fixdfsi): Use rrx to extract the carry into a register instead of
MRS instruction.  Optimize later use of result.
* arm/ieee754-sf.S (__fixsfsi): Likewise.
(__fixunssfsi): Use a better sequence for handling negative-or-zero.

Co-Authored-By: Nicolas Pitre <nico@cam.org>

From-SVN: r70949
parent 88d032eb
2003-08-30 Richard Earnshaw <rearnsha@arm.com>
Nicolas Pitre <nico@cam.org>
* arm/lib1funcs.asm (RETCOND): Delete.
(RETLDM): New assembler macro. Use it for returning with ldm/ldr.
(ARM_LDIV0, THUMB_LDIV0): Collapse multiple definitions.
(__ARM_ARCH__): Move here from ieee754-?f.S.
(RET, RETc): Clean up definitions.
(DIV_FUNC_END): Renamed from FUNC_END. All uses changed.
(FUNC_END): New macro that marks the end of any function.
(ARM_FUNC_START): New macro that allows an assembler routine to be
implemented in ARM code even if a Thumb-only build.
Unconditionally include ieee754-?f.S.
* arm/ieee754-df.S: Delete macros moved to lib1funcs.asm.
Mark ends of functions.
Split into separate conditionally-compiled units.
Use RETLDM to return from routines.
* arm/ieee754-sf.S: Similarly.
* t-arm-elf (LIB1ASMFUNCS): Remove _ieee754_dp and _ieee754_sp.
Add _negdf2 _addsubdf3 _muldivdf3 _cmpdf2 _unorddf2 _fixdfsi
_truncdfsf2 _negsf2 _addsubsf3 _muldivsf3 _cmpsf2 _unordsf2
_fixsfsi and _fixunssfsi.
* arm/ieee754-df.S (__muldf3): Fix bug when result of a
multiplication underflows to zero.
(__adddf3): Fix bug when using VFP ordering on little-endian
processors.
(__fixdfsi): Use rrx to extract the carry into a register instead of
MRS instruction. Optimize later use of result.
* arm/ieee754-sf.S (__fixsfsi): Likewise.
(__fixunssfsi): Use a better sequence for handling negative-or-zero.
2003-08-29 Richard Henderson <rth@redhat.com> 2003-08-29 Richard Henderson <rth@redhat.com>
* tree-optimize.c: New file. * tree-optimize.c: New file.
......
...@@ -40,33 +40,6 @@ ...@@ -40,33 +40,6 @@
* if necessary without impacting performances. * if necessary without impacting performances.
*/ */
@ This selects the minimum architecture level required.
#undef __ARM_ARCH__
#define __ARM_ARCH__ 3
#if defined(__ARM_ARCH_3M__) || defined(__ARM_ARCH_4__) \
|| defined(__ARM_ARCH_4T__)
#undef __ARM_ARCH__
/* We use __ARM_ARCH__ set to 4 here, but in reality it's any processor with
long multiply instructions. That includes v3M. */
#define __ARM_ARCH__ 4
#endif
#if defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5T__) \
|| defined(__ARM_ARCH_5TE__)
#undef __ARM_ARCH__
#define __ARM_ARCH__ 5
#endif
#if (__ARM_ARCH__ > 4) || defined(__ARM_ARCH_4T__)
#undef RET
#undef RETc
#define RET bx lr
#define RETc(x) bx##x lr
#if (__ARM_ARCH__ == 4) && (defined(__thumb__) || defined(__THUMB_INTERWORK__))
#define __FP_INTERWORKING__
#endif
#endif
@ For FPA, float words are always big-endian. @ For FPA, float words are always big-endian.
@ For VFP, floats words follow the memory system mode. @ For VFP, floats words follow the memory system mode.
...@@ -83,24 +56,19 @@ ...@@ -83,24 +56,19 @@
#endif #endif
#if defined(__thumb__) && !defined(__THUMB_INTERWORK__) #ifdef L_negdf2
.macro ARM_FUNC_START name
FUNC_START \name
bx pc
nop
.arm
.endm
#else
.macro ARM_FUNC_START name
FUNC_START \name
.endm
#endif
ARM_FUNC_START negdf2 ARM_FUNC_START negdf2
@ flip sign bit @ flip sign bit
eor xh, xh, #0x80000000 eor xh, xh, #0x80000000
RET RET
FUNC_END negdf2
#endif
#ifdef L_addsubdf3
ARM_FUNC_START subdf3 ARM_FUNC_START subdf3
@ flip sign bit of second arg @ flip sign bit of second arg
eor yh, yh, #0x80000000 eor yh, yh, #0x80000000
...@@ -155,12 +123,7 @@ ARM_FUNC_START adddf3 ...@@ -155,12 +123,7 @@ ARM_FUNC_START adddf3
@ already in xh-xl. We need up to 54 bit to handle proper rounding @ already in xh-xl. We need up to 54 bit to handle proper rounding
@ of 0x1p54 - 1.1. @ of 0x1p54 - 1.1.
cmp r5, #(54 << 20) cmp r5, #(54 << 20)
#ifdef __FP_INTERWORKING__ RETLDM "r4, r5" hi
ldmhifd sp!, {r4, r5, lr}
bxhi lr
#else
ldmhifd sp!, {r4, r5, pc}RETCOND
#endif
@ Convert mantissa to signed integer. @ Convert mantissa to signed integer.
tst xh, #0x80000000 tst xh, #0x80000000
...@@ -227,9 +190,9 @@ LSYM(Lad_x): ...@@ -227,9 +190,9 @@ LSYM(Lad_x):
LSYM(Lad_p): LSYM(Lad_p):
cmp xh, #0x00100000 cmp xh, #0x00100000
bcc LSYM(Lad_l) bcc LSYM(Lad_l)
cmp r0, #0x00200000 cmp xh, #0x00200000
bcc LSYM(Lad_r0) bcc LSYM(Lad_r0)
cmp r0, #0x00400000 cmp xh, #0x00400000
bcc LSYM(Lad_r1) bcc LSYM(Lad_r1)
@ Result needs to be shifted right. @ Result needs to be shifted right.
...@@ -268,14 +231,10 @@ LSYM(Lad_e): ...@@ -268,14 +231,10 @@ LSYM(Lad_e):
bic xh, xh, #0x00300000 bic xh, xh, #0x00300000
orr xh, xh, r4 orr xh, xh, r4
orr xh, xh, r5 orr xh, xh, r5
#ifdef __FP_INTERWORKING__ RETLDM "r4, r5"
ldmfd sp!, {r4, r5, lr}
bx lr
#else
ldmfd sp!, {r4, r5, pc}RETCOND
#endif
LSYM(Lad_l): @ Result must be shifted left and exponent adjusted. LSYM(Lad_l):
@ Result must be shifted left and exponent adjusted.
@ No rounding necessary since ip will always be 0. @ No rounding necessary since ip will always be 0.
#if __ARM_ARCH__ < 5 #if __ARM_ARCH__ < 5
...@@ -351,12 +310,7 @@ LSYM(Lad_l): @ Result must be shifted left and exponent adjusted. ...@@ -351,12 +310,7 @@ LSYM(Lad_l): @ Result must be shifted left and exponent adjusted.
mov xl, xl, lsr r4 mov xl, xl, lsr r4
orr xl, xl, xh, lsl r2 orr xl, xl, xh, lsl r2
orr xh, r5, xh, lsr r4 orr xh, r5, xh, lsr r4
#ifdef __FP_INTERWORKING RETLDM "r4, r5"
ldmfd sp!, {r4, r5, lr}
bx lr
#else
ldmfd sp!, {r4, r5, pc}RETCOND
#endif
@ shift result right of 21 to 31 bits, or left 11 to 1 bits after @ shift result right of 21 to 31 bits, or left 11 to 1 bits after
@ a register switch from xh to xl. @ a register switch from xh to xl.
...@@ -365,23 +319,13 @@ LSYM(Lad_l): @ Result must be shifted left and exponent adjusted. ...@@ -365,23 +319,13 @@ LSYM(Lad_l): @ Result must be shifted left and exponent adjusted.
mov xl, xl, lsr r2 mov xl, xl, lsr r2
orr xl, xl, xh, lsl r4 orr xl, xl, xh, lsl r4
mov xh, r5 mov xh, r5
#ifdef __FP_INTERWORKING__ RETLDM "r4, r5"
ldmfd sp!, {r4, r5, lr}
bx lr
#else
ldmfd sp!, {r4, r5, pc}RETCOND
#endif
@ Shift value right of 32 to 64 bits, or 0 to 32 bits after a switch @ Shift value right of 32 to 64 bits, or 0 to 32 bits after a switch
@ from xh to xl. @ from xh to xl.
2: mov xl, xh, lsr r4 2: mov xl, xh, lsr r4
mov xh, r5 mov xh, r5
#ifdef __FP_INTERWORKING__ RETLDM "r4, r5"
ldmfd sp!, {r4, r5, lr}
bx lr
#else
ldmfd sp!, {r4, r5, pc}RETCOND
#endif
@ Adjust exponents for denormalized arguments. @ Adjust exponents for denormalized arguments.
LSYM(Lad_d): LSYM(Lad_d):
...@@ -407,12 +351,7 @@ LSYM(Lad_o): ...@@ -407,12 +351,7 @@ LSYM(Lad_o):
orr xh, r5, #0x7f000000 orr xh, r5, #0x7f000000
orr xh, xh, #0x00f00000 orr xh, xh, #0x00f00000
mov xl, #0 mov xl, #0
#ifdef __FP_INTERWORKING__ RETLDM "r4, r5"
ldmfd sp!, {r4, r5, lr}
bx lr
#else
ldmfd sp!, {r4, r5, pc}RETCOND
#endif
@ At least one of x or y is INF/NAN. @ At least one of x or y is INF/NAN.
@ if xh-xl != INF/NAN: return yh-yl (which is INF/NAN) @ if xh-xl != INF/NAN: return yh-yl (which is INF/NAN)
...@@ -425,24 +364,17 @@ LSYM(Lad_i): ...@@ -425,24 +364,17 @@ LSYM(Lad_i):
movne xh, yh movne xh, yh
movne xl, yl movne xl, yl
teqeq r5, ip teqeq r5, ip
#ifdef __FP_INTERWORKING__ RETLDM "r4, r5" ne
ldmnefd sp!, {r4, r5, lr}
bxne lr
#else
ldmnefd sp!, {r4, r5, pc}RETCOND
#endif
orrs r4, xl, xh, lsl #12 orrs r4, xl, xh, lsl #12
orreqs r4, yl, yh, lsl #12 orreqs r4, yl, yh, lsl #12
teqeq xh, yh teqeq xh, yh
orrne xh, r5, #0x00080000 orrne xh, r5, #0x00080000
movne xl, #0 movne xl, #0
#ifdef __FP_INTERWORKING__ RETLDM "r4, r5"
ldmfd sp!, {r4, r5, lr}
bx lr
#else
ldmfd sp!, {r4, r5, pc}RETCOND
#endif
FUNC_END subdf3
FUNC_END adddf3
ARM_FUNC_START floatunsidf ARM_FUNC_START floatunsidf
teq r0, #0 teq r0, #0
...@@ -456,6 +388,7 @@ ARM_FUNC_START floatunsidf ...@@ -456,6 +388,7 @@ ARM_FUNC_START floatunsidf
mov xh, #0 mov xh, #0
b LSYM(Lad_l) b LSYM(Lad_l)
FUNC_END floatunsidf
ARM_FUNC_START floatsidf ARM_FUNC_START floatsidf
teq r0, #0 teq r0, #0
...@@ -470,6 +403,7 @@ ARM_FUNC_START floatsidf ...@@ -470,6 +403,7 @@ ARM_FUNC_START floatsidf
mov xh, #0 mov xh, #0
b LSYM(Lad_l) b LSYM(Lad_l)
FUNC_END floatsidf
ARM_FUNC_START extendsfdf2 ARM_FUNC_START extendsfdf2
movs r2, r0, lsl #1 movs r2, r0, lsl #1
...@@ -495,6 +429,11 @@ ARM_FUNC_START extendsfdf2 ...@@ -495,6 +429,11 @@ ARM_FUNC_START extendsfdf2
bic xh, xh, #0x80000000 bic xh, xh, #0x80000000
b LSYM(Lad_l) b LSYM(Lad_l)
FUNC_END extendsfdf2
#endif /* L_addsubdf3 */
#ifdef L_muldivdf3
ARM_FUNC_START muldf3 ARM_FUNC_START muldf3
...@@ -656,12 +595,7 @@ LSYM(Lml_x): ...@@ -656,12 +595,7 @@ LSYM(Lml_x):
@ Add final exponent. @ Add final exponent.
bic xh, xh, #0x00300000 bic xh, xh, #0x00300000
orr xh, xh, r4, lsl #1 orr xh, xh, r4, lsl #1
#ifdef __FP_INTERWORKING__ RETLDM "r4, r5, r6"
ldmfd sp!, {r4, r5, r6, lr}
bx lr
#else
ldmfd sp!, {r4, r5, r6, pc}RETCOND
#endif
@ Result is 0, but determine sign anyway. @ Result is 0, but determine sign anyway.
LSYM(Lml_z): LSYM(Lml_z):
...@@ -669,23 +603,14 @@ LSYM(Lml_z): ...@@ -669,23 +603,14 @@ LSYM(Lml_z):
LSYM(Ldv_z): LSYM(Ldv_z):
bic xh, xh, #0x7fffffff bic xh, xh, #0x7fffffff
mov xl, #0 mov xl, #0
#ifdef __FP_INTERWORKING__ RETLDM "r4, r5, r6"
ldmfd sp!, {r4, r5, r6, lr}
bx lr
#else
ldmfd sp!, {r4, r5, r6, pc}RETCOND
#endif
@ Check if denormalized result is possible, otherwise return signed 0. @ Check if denormalized result is possible, otherwise return signed 0.
LSYM(Lml_u): LSYM(Lml_u):
cmn r4, #(53 << 19) cmn r4, #(53 << 19)
movle xl, #0 movle xl, #0
#ifdef __FP_INTERWORKING__ bicle xh, xh, #0x7fffffff
ldmlefd sp!, {r4, r5, r6, lr} RETLDM "r4, r5, r6" le
bxle lr
#else
ldmlefd sp!, {r4, r5, r6, pc}RETCOND
#endif
@ Find out proper shift value. @ Find out proper shift value.
LSYM(Lml_r): LSYM(Lml_r):
...@@ -709,12 +634,7 @@ LSYM(Lml_r): ...@@ -709,12 +634,7 @@ LSYM(Lml_r):
teq lr, #0 teq lr, #0
teqeq r3, #0x80000000 teqeq r3, #0x80000000
biceq xl, xl, #1 biceq xl, xl, #1
#ifdef __FP_INTERWORKING__ RETLDM "r4, r5, r6"
ldmfd sp!, {r4, r5, r6, lr}
bx lr
#else
ldmfd sp!, {r4, r5, r6, pc}RETCOND
#endif
@ shift result right of 21 to 31 bits, or left 11 to 1 bits after @ shift result right of 21 to 31 bits, or left 11 to 1 bits after
@ a register switch from xh to xl. Then round. @ a register switch from xh to xl. Then round.
...@@ -729,12 +649,7 @@ LSYM(Lml_r): ...@@ -729,12 +649,7 @@ LSYM(Lml_r):
teq lr, #0 teq lr, #0
teqeq r3, #0x80000000 teqeq r3, #0x80000000
biceq xl, xl, #1 biceq xl, xl, #1
#ifdef __FP_INTERWORKING__ RETLDM "r4, r5, r6"
ldmfd sp!, {r4, r5, r6, lr}
bx lr
#else
ldmfd sp!, {r4, r5, r6, pc}RETCOND
#endif
@ Shift value right of 32 to 64 bits, or 0 to 32 bits after a switch @ Shift value right of 32 to 64 bits, or 0 to 32 bits after a switch
@ from xh to xl. Leftover bits are in r3-r6-lr for rounding. @ from xh to xl. Leftover bits are in r3-r6-lr for rounding.
...@@ -749,12 +664,7 @@ LSYM(Lml_r): ...@@ -749,12 +664,7 @@ LSYM(Lml_r):
orrs r6, r6, lr orrs r6, r6, lr
teqeq r3, #0x80000000 teqeq r3, #0x80000000
biceq xl, xl, #1 biceq xl, xl, #1
#ifdef __FP_INTERWORKING__ RETLDM "r4, r5, r6"
ldmfd sp!, {r4, r5, r6, lr}
bx lr
#else
ldmfd sp!, {r4, r5, r6, pc}RETCOND
#endif
@ One or both arguments are denormalized. @ One or both arguments are denormalized.
@ Scale them leftwards and preserve sign bit. @ Scale them leftwards and preserve sign bit.
...@@ -804,24 +714,15 @@ LSYM(Lml_o): ...@@ -804,24 +714,15 @@ LSYM(Lml_o):
orr xh, xh, #0x7f000000 orr xh, xh, #0x7f000000
orr xh, xh, #0x00f00000 orr xh, xh, #0x00f00000
mov xl, #0 mov xl, #0
#ifdef __FP_INTERWORKING__ RETLDM "r4, r5, r6"
ldmfd sp!, {r4, r5, r6, lr}
bx lr
#else
ldmfd sp!, {r4, r5, r6, pc}RETCOND
#endif
@ Return NAN. @ Return NAN.
LSYM(Lml_n): LSYM(Lml_n):
mov xh, #0x7f000000 mov xh, #0x7f000000
orr xh, xh, #0x00f80000 orr xh, xh, #0x00f80000
#ifdef __FP_INTERWORKING__ RETLDM "r4, r5, r6"
ldmfd sp!, {r4, r5, r6, lr}
bx lr
#else
ldmfd sp!, {r4, r5, r6, pc}RETCOND
#endif
FUNC_END muldf3
ARM_FUNC_START divdf3 ARM_FUNC_START divdf3
...@@ -961,12 +862,7 @@ LSYM(Ldv_x): ...@@ -961,12 +862,7 @@ LSYM(Ldv_x):
@ Add exponent to result. @ Add exponent to result.
bic xh, xh, #0x00100000 bic xh, xh, #0x00100000
orr xh, xh, r4, lsl #1 orr xh, xh, r4, lsl #1
#ifdef __FP_INTERWORKING__ RETLDM "r4, r5, r6"
ldmfd sp!, {r4, r5, r6, lr}
bx lr
#else
ldmfd sp!, {r4, r5, r6, pc}RETCOND
#endif
@ Division by 0x1p*: shortcut a lot of code. @ Division by 0x1p*: shortcut a lot of code.
LSYM(Ldv_1): LSYM(Ldv_1):
...@@ -978,12 +874,8 @@ LSYM(Ldv_1): ...@@ -978,12 +874,8 @@ LSYM(Ldv_1):
bge LSYM(Lml_o) bge LSYM(Lml_o)
cmp r4, #0 cmp r4, #0
orrgt xh, xh, r4, lsl #1 orrgt xh, xh, r4, lsl #1
#ifdef __FP_INTERWORKING__ RETLDM "r4, r5, r6" gt
ldmgtfd sp!, {r4, r5, r6, lr}
bxgt lr
#else
ldmgtfd sp!, {r4, r5, r6, pc}RETCOND
#endif
cmn r4, #(53 << 19) cmn r4, #(53 << 19)
ble LSYM(Ldv_z) ble LSYM(Ldv_z)
orr xh, xh, #0x00100000 orr xh, xh, #0x00100000
...@@ -1042,6 +934,11 @@ LSYM(Ldv_s): ...@@ -1042,6 +934,11 @@ LSYM(Ldv_s):
bne LSYM(Lml_z) @ 0 / <non_zero> -> 0 bne LSYM(Lml_z) @ 0 / <non_zero> -> 0
b LSYM(Lml_n) @ 0 / 0 -> NAN b LSYM(Lml_n) @ 0 / 0 -> NAN
FUNC_END divdf3
#endif /* L_muldivdf3 */
#ifdef L_cmpdf2
FUNC_START gedf2 FUNC_START gedf2
ARM_FUNC_START gtdf2 ARM_FUNC_START gtdf2
...@@ -1076,23 +973,13 @@ ARM_FUNC_START cmpdf2 ...@@ -1076,23 +973,13 @@ ARM_FUNC_START cmpdf2
teqne xh, yh @ or xh == yh teqne xh, yh @ or xh == yh
teqeq xl, yl @ and xl == yl teqeq xl, yl @ and xl == yl
moveq r0, #0 @ then equal. moveq r0, #0 @ then equal.
#ifdef __FP_INTERWORKING__ RETLDM "r4, r5" eq
ldmeqfd sp!, {r4, r5, lr}
bxeq lr
#else
ldmeqfd sp!, {r4, r5, pc}RETCOND
#endif
@ Check for sign difference. @ Check for sign difference.
teq xh, yh teq xh, yh
movmi r0, xh, asr #31 movmi r0, xh, asr #31
orrmi r0, r0, #1 orrmi r0, r0, #1
#ifdef __FP_INTERWORKING__ RETLDM "r4, r5" mi
ldmmifd sp!, {r4, r5, lr}
bxmi lr
#else
ldmmifd sp!, {r4, r5, pc}RETCOND
#endif
@ Compare exponents. @ Compare exponents.
cmp r4, r5 cmp r4, r5
...@@ -1104,12 +991,7 @@ ARM_FUNC_START cmpdf2 ...@@ -1104,12 +991,7 @@ ARM_FUNC_START cmpdf2
movcs r0, yh, asr #31 movcs r0, yh, asr #31
mvncc r0, yh, asr #31 mvncc r0, yh, asr #31
orr r0, r0, #1 orr r0, r0, #1
#ifdef __FP_INTERWORKING__ RETLDM "r4, r5"
ldmfd sp!, {r4, r5, lr}
bx lr
#else
ldmfd sp!, {r4, r5, pc}RETCOND
#endif
@ Look for a NAN. @ Look for a NAN.
3: teq r4, lr 3: teq r4, lr
...@@ -1121,13 +1003,19 @@ ARM_FUNC_START cmpdf2 ...@@ -1121,13 +1003,19 @@ ARM_FUNC_START cmpdf2
orrs yl, yl, yh, lsl #12 orrs yl, yl, yh, lsl #12
beq 2b @ y is not NAN beq 2b @ y is not NAN
5: mov r0, ip @ return unordered code from ip 5: mov r0, ip @ return unordered code from ip
#ifdef __FP_INTERWORKING__ RETLDM "r4, r5"
ldmfd sp!, {r4, r5, lr}
bx lr
#else
ldmfd sp!, {r4, r5, pc}RETCOND
#endif
FUNC_END gedf2
FUNC_END gtdf2
FUNC_END ledf2
FUNC_END ltdf2
FUNC_END nedf2
FUNC_END eqdf2
FUNC_END cmpdf2
#endif /* L_cmpdf2 */
#ifdef L_unorddf2
ARM_FUNC_START unorddf2 ARM_FUNC_START unorddf2
str lr, [sp, #-4]! str lr, [sp, #-4]!
...@@ -1144,35 +1032,22 @@ ARM_FUNC_START unorddf2 ...@@ -1144,35 +1032,22 @@ ARM_FUNC_START unorddf2
orrs yl, yl, yh, lsl #12 orrs yl, yl, yh, lsl #12
bne 3f @ y is NAN bne 3f @ y is NAN
2: mov r0, #0 @ arguments are ordered. 2: mov r0, #0 @ arguments are ordered.
#ifdef __FP_INTERWORKING__ RETLDM
ldr lr, [sp], #4
bx lr
#elif defined (__APCS_26__)
ldmia sp!, {pc}^
#else
ldr pc, [sp], #4
#endif
3: mov r0, #1 @ arguments are unordered. 3: mov r0, #1 @ arguments are unordered.
#ifdef __FP_INTERWORKING__ RETLDM
ldr lr, [sp], #4
bx lr FUNC_END unorddf2
#elif defined (__APCS_26__)
ldmia sp!, {pc}^
#else
ldr pc, [sp], #4
#endif
#endif /* L_unorddf2 */
#ifdef L_fixdfsi
ARM_FUNC_START fixdfsi ARM_FUNC_START fixdfsi
orrs ip, xl, xh, lsl #1 orrs ip, xl, xh, lsl #1
beq 1f @ value is 0. beq 1f @ value is 0.
@ preserve C flag (the actual sign) mov r3, r3, rrx @ preserve C flag (the actual sign)
#ifdef __APCS_26__
mov r3, pc
#else
mrs r3, cpsr
#endif
@ check exponent range. @ check exponent range.
mov ip, #0x7f000000 mov ip, #0x7f000000
...@@ -1192,8 +1067,8 @@ ARM_FUNC_START fixdfsi ...@@ -1192,8 +1067,8 @@ ARM_FUNC_START fixdfsi
orr ip, ip, #0x80000000 orr ip, ip, #0x80000000
orr ip, ip, xl, lsr #21 orr ip, ip, xl, lsr #21
mov r2, r2, lsr #20 mov r2, r2, lsr #20
tst r3, #0x80000000 @ the sign bit
mov r0, ip, lsr r2 mov r0, ip, lsr r2
tst r3, #0x20000000 @ the sign bit
rsbne r0, r0, #0 rsbne r0, r0, #0
RET RET
...@@ -1202,18 +1077,19 @@ ARM_FUNC_START fixdfsi ...@@ -1202,18 +1077,19 @@ ARM_FUNC_START fixdfsi
2: orrs xl, xl, xh, lsl #12 2: orrs xl, xl, xh, lsl #12
bne 4f @ r0 is NAN. bne 4f @ r0 is NAN.
3: tst r3, #0x20000000 @ the sign bit 3: ands r0, r3, #0x80000000 @ the sign bit
moveq r0, #0x7fffffff @ maximum signed positive si moveq r0, #0x7fffffff @ maximum signed positive si
movne r0, #0x80000000 @ maximum signed negative si
RET RET
4: mov r0, #0 @ How should we convert NAN? 4: mov r0, #0 @ How should we convert NAN?
RET RET
FUNC_END fixdfsi
ARM_FUNC_START fixunsdfsi ARM_FUNC_START fixunsdfsi
orrs ip, xl, xh, lsl #1 orrs ip, xl, xh, lsl #1
beq 1b @ value is 0 movcss r0, #0 @ value is negative
bcs 1b @ value is negative RETc(eq) @ or 0 (xl, xh overlap r0)
@ check exponent range. @ check exponent range.
mov ip, #0x7f000000 mov ip, #0x7f000000
...@@ -1241,6 +1117,11 @@ ARM_FUNC_START fixunsdfsi ...@@ -1241,6 +1117,11 @@ ARM_FUNC_START fixunsdfsi
2: mov r0, #0xffffffff @ maximum unsigned si 2: mov r0, #0xffffffff @ maximum unsigned si
RET RET
FUNC_END fixunsdfsi
#endif /* L_fixunsdfdi */
#ifdef L_truncdfsf2
ARM_FUNC_START truncdfsf2 ARM_FUNC_START truncdfsf2
orrs r2, xl, xh, lsl #1 orrs r2, xl, xh, lsl #1
...@@ -1328,4 +1209,6 @@ ARM_FUNC_START truncdfsf2 ...@@ -1328,4 +1209,6 @@ ARM_FUNC_START truncdfsf2
and xh, xh, #0x80000000 and xh, xh, #0x80000000
b 5b b 5b
FUNC_END truncdfsf2
#endif /* L_truncdfsf2 */
...@@ -38,50 +38,17 @@ ...@@ -38,50 +38,17 @@
* if necessary without impacting performances. * if necessary without impacting performances.
*/ */
@ This selects the minimum architecture level required. #ifdef L_negsf2
#undef __ARM_ARCH__
#define __ARM_ARCH__ 3
#if defined(__ARM_ARCH_3M__) || defined(__ARM_ARCH_4__) \
|| defined(__ARM_ARCH_4T__)
#undef __ARM_ARCH__
/* We use __ARM_ARCH__ set to 4 here, but in reality it's any processor with
long multiply instructions. That includes v3M. */
#define __ARM_ARCH__ 4
#endif
#if defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5T__) \ ARM_FUNC_START negsf2
|| defined(__ARM_ARCH_5TE__) eor r0, r0, #0x80000000 @ flip sign bit
#undef __ARM_ARCH__ RET
#define __ARM_ARCH__ 5
#endif
#if (__ARM_ARCH__ > 4) || defined(__ARM_ARCH_4T__) FUNC_END negsf2
#undef RET
#undef RETc
#define RET bx lr
#define RETc(x) bx##x lr
#if (__ARM_ARCH__ == 4) && (defined(__thumb__) || defined(__THUMB_INTERWORK__))
#define __FP_INTERWORKING__
#endif
#endif
#if defined(__thumb__) && !defined(__THUMB_INTERWORK__)
.macro ARM_FUNC_START name
FUNC_START \name
bx pc
nop
.arm
.endm
#else
.macro ARM_FUNC_START name
FUNC_START \name
.endm
#endif #endif
ARM_FUNC_START negsf2 #ifdef L_addsubsf3
eor r0, r0, #0x80000000 @ flip sign bit
RET
ARM_FUNC_START subsf3 ARM_FUNC_START subsf3
eor r1, r1, #0x80000000 @ flip sign bit of second arg eor r1, r1, #0x80000000 @ flip sign bit of second arg
...@@ -291,6 +258,8 @@ LSYM(Lad_i): ...@@ -291,6 +258,8 @@ LSYM(Lad_i):
orrne r0, r3, #0x00400000 @ NAN orrne r0, r3, #0x00400000 @ NAN
RET RET
FUNC_END addsf3
FUNC_END subsf3
ARM_FUNC_START floatunsisf ARM_FUNC_START floatunsisf
mov r3, #0 mov r3, #0
...@@ -321,6 +290,12 @@ ARM_FUNC_START floatsisf ...@@ -321,6 +290,12 @@ ARM_FUNC_START floatsisf
add r2, r2, #(2 << 23) add r2, r2, #(2 << 23)
b LSYM(Lad_p) b LSYM(Lad_p)
FUNC_END floatsisf
FUNC_END floatunsisf
#endif /* L_addsubsf3 */
#ifdef L_muldivsf3
ARM_FUNC_START mulsf3 ARM_FUNC_START mulsf3
...@@ -509,6 +484,7 @@ LSYM(Lml_n): ...@@ -509,6 +484,7 @@ LSYM(Lml_n):
orr r0, r0, #0x00c00000 orr r0, r0, #0x00c00000
RET RET
FUNC_END mulsf3
ARM_FUNC_START divsf3 ARM_FUNC_START divsf3
...@@ -659,6 +635,11 @@ LSYM(Ldv_s): ...@@ -659,6 +635,11 @@ LSYM(Ldv_s):
bne LSYM(Lml_z) @ 0 / <non_zero> -> 0 bne LSYM(Lml_z) @ 0 / <non_zero> -> 0
b LSYM(Lml_n) @ 0 / 0 -> NAN b LSYM(Lml_n) @ 0 / 0 -> NAN
FUNC_END divsf3
#endif /* L_muldivsf3 */
#ifdef L_cmpsf2
FUNC_START gesf2 FUNC_START gesf2
ARM_FUNC_START gtsf2 ARM_FUNC_START gtsf2
...@@ -723,6 +704,17 @@ ARM_FUNC_START cmpsf2 ...@@ -723,6 +704,17 @@ ARM_FUNC_START cmpsf2
5: mov r0, r3 @ return unordered code from r3. 5: mov r0, r3 @ return unordered code from r3.
RET 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 ARM_FUNC_START unordsf2
mov ip, #0xff000000 mov ip, #0xff000000
...@@ -741,16 +733,17 @@ ARM_FUNC_START unordsf2 ...@@ -741,16 +733,17 @@ ARM_FUNC_START unordsf2
3: mov r0, #1 @ arguments are unordered. 3: mov r0, #1 @ arguments are unordered.
RET RET
FUNC_END unordsf2
#endif /* L_unordsf2 */
#ifdef L_fixsfsi
ARM_FUNC_START fixsfsi ARM_FUNC_START fixsfsi
movs r0, r0, lsl #1 movs r0, r0, lsl #1
RETc(eq) @ value is 0. RETc(eq) @ value is 0.
@ preserve C flag (the actual sign)
#ifdef __APCS_26__ mov r1, r1, rrx @ preserve C flag (the actual sign)
mov r1, pc
#else
mrs r1, cpsr
#endif
@ check exponent range. @ check exponent range.
and r2, r0, #0xff000000 and r2, r0, #0xff000000
...@@ -764,8 +757,8 @@ ARM_FUNC_START fixsfsi ...@@ -764,8 +757,8 @@ ARM_FUNC_START fixsfsi
orr r0, r0, #0x80000000 orr r0, r0, #0x80000000
mov r2, r2, lsr #24 mov r2, r2, lsr #24
rsb r2, r2, #(127 + 31) rsb r2, r2, #(127 + 31)
tst r1, #0x80000000 @ the sign bit
mov r0, r0, lsr r2 mov r0, r0, lsr r2
tst r1, #0x20000000 @ the sign bit
rsbne r0, r0, #0 rsbne r0, r0, #0
RET RET
...@@ -773,20 +766,24 @@ ARM_FUNC_START fixsfsi ...@@ -773,20 +766,24 @@ ARM_FUNC_START fixsfsi
bne 2f bne 2f
movs r0, r0, lsl #8 movs r0, r0, lsl #8
bne 3f @ r0 is NAN. bne 3f @ r0 is NAN.
2: tst r1, #0x20000000 @ the sign bit 2: ands r0, r1, #0x80000000 @ the sign bit
moveq r0, #0x7fffffff @ the maximum signed positive si moveq r0, #0x7fffffff @ the maximum signed positive si
movne r0, #0x80000000 @ the maximum signed negative si
RET RET
3: mov r0, #0 @ What should we convert NAN to? 3: mov r0, #0 @ What should we convert NAN to?
RET RET
FUNC_END fixsfsi
#endif /* L_fixsfsi */
#ifdef L_fixunssfsi
ARM_FUNC_START fixunssfsi ARM_FUNC_START fixunssfsi
movs r0, r0, lsl #1 movs r0, r0, lsl #1
RETc(eq) @ value is 0. movcss r0, #0 @ value is negative...
movcs r0, #0 RETc(eq) @ ... or 0.
RETc(cs) @ value is negative.
@ check exponent range. @ check exponent range.
and r2, r0, #0xff000000 and r2, r0, #0xff000000
...@@ -806,8 +803,13 @@ ARM_FUNC_START fixunssfsi ...@@ -806,8 +803,13 @@ ARM_FUNC_START fixunssfsi
1: teq r2, #0xff000000 1: teq r2, #0xff000000
bne 2f bne 2f
movs r0, r0, lsl #8 movs r0, r0, lsl #8
bne 3b @ r0 is NAN. bne 3f @ r0 is NAN.
2: mov r0, #0xffffffff @ maximum unsigned si 2: mov r0, #0xffffffff @ maximum unsigned si
RET RET
3: mov r0, #0 @ What should we convert NAN to?
RET
FUNC_END fixunssfsi
#endif /* L_fixunssfsi */
...@@ -61,66 +61,107 @@ Boston, MA 02111-1307, USA. */ ...@@ -61,66 +61,107 @@ Boston, MA 02111-1307, USA. */
/* Function end macros. Variants for 26 bit APCS and interworking. */ /* Function end macros. Variants for 26 bit APCS and interworking. */
@ This selects the minimum architecture level required.
#define __ARM_ARCH__ 3
#if defined(__ARM_ARCH_3M__) || defined(__ARM_ARCH_4__) \
|| defined(__ARM_ARCH_4T__)
/* We use __ARM_ARCH__ set to 4 here, but in reality it's any processor with
long multiply instructions. That includes v3M. */
# undef __ARM_ARCH__
# define __ARM_ARCH__ 4
#endif
#if defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5T__) \
|| defined(__ARM_ARCH_5TE__)
# undef __ARM_ARCH__
# define __ARM_ARCH__ 5
#endif
/* How to return from a function call depends on the architecture variant. */
#ifdef __APCS_26__ #ifdef __APCS_26__
# define RET movs pc, lr # define RET movs pc, lr
# define RETc(x) mov##x##s pc, lr # define RETc(x) mov##x##s pc, lr
# define RETCOND ^
#elif (__ARM_ARCH__ > 4) || defined(__ARM_ARCH_4T__)
# define RET bx lr
# define RETc(x) bx##x lr
# if (__ARM_ARCH__ == 4) \
&& (defined(__thumb__) || defined(__THUMB_INTERWORK__))
# define __INTERWORKING__
# endif
#else
# define RET mov pc, lr
# define RETc(x) mov##x pc, lr
#endif
/* Don't pass dirn, it's there just to get token pasting right. */
.macro RETLDM regs=, cond=, dirn=ia
#ifdef __APCS_26__
.ifc "\regs",""
ldm\cond\dirn sp!, {pc}^
.else
ldm\cond\dirn sp!, {\regs, pc}^
.endif
#elif defined (__INTERWORKING__)
.ifc "\regs",""
ldr\cond lr, [sp], #4
.else
ldm\cond\dirn sp!, {\regs, lr}
.endif
bx\cond lr
#else
.ifc "\regs",""
ldr\cond pc, [sp], #4
.else
ldm\cond\dirn sp!, {\regs, pc}
.endif
#endif
.endm
.macro ARM_LDIV0 .macro ARM_LDIV0
LSYM(Ldiv0): LSYM(Ldiv0):
str lr, [sp, #-4]! str lr, [sp, #-4]!
bl SYM (__div0) __PLT__ bl SYM (__div0) __PLT__
mov r0, #0 @ About as wrong as it could be. mov r0, #0 @ About as wrong as it could be.
ldmia sp!, {pc}^ RETLDM
.endm .endm
#else
# ifdef __THUMB_INTERWORK__
# define RET bx lr
# define RETc(x) bx##x lr
.macro THUMB_LDIV0 .macro THUMB_LDIV0
LSYM(Ldiv0): LSYM(Ldiv0):
push { lr } push { lr }
bl SYM (__div0) bl SYM (__div0)
mov r0, #0 @ About as wrong as it could be. mov r0, #0 @ About as wrong as it could be.
#if defined (__INTERWORKING__)
pop { r1 } pop { r1 }
bx r1 bx r1
.endm #else
.macro ARM_LDIV0
LSYM(Ldiv0):
str lr, [sp, #-4]!
bl SYM (__div0) __PLT__
mov r0, #0 @ About as wrong as it could be.
ldr lr, [sp], #4
bx lr
.endm
# else
# define RET mov pc, lr
# define RETc(x) mov##x pc, lr
.macro THUMB_LDIV0
LSYM(Ldiv0):
push { lr }
bl SYM (__div0)
mov r0, #0 @ About as wrong as it could be.
pop { pc } pop { pc }
.endm
.macro ARM_LDIV0
LSYM(Ldiv0):
str lr, [sp, #-4]!
bl SYM (__div0) __PLT__
mov r0, #0 @ About as wrong as it could be.
ldmia sp!, {pc}
.endm
# endif
# define RETCOND
#endif #endif
.endm
.macro FUNC_END name .macro FUNC_END name
SIZE (__\name)
.endm
.macro DIV_FUNC_END name
LSYM(Ldiv0): LSYM(Ldiv0):
#ifdef __thumb__ #ifdef __thumb__
THUMB_LDIV0 THUMB_LDIV0
#else #else
ARM_LDIV0 ARM_LDIV0
#endif #endif
SIZE (__\name) FUNC_END \name
.endm .endm
.macro THUMB_FUNC_START name .macro THUMB_FUNC_START name
...@@ -149,7 +190,24 @@ SYM (\name): ...@@ -149,7 +190,24 @@ SYM (\name):
THUMB_FUNC THUMB_FUNC
SYM (__\name): SYM (__\name):
.endm .endm
/* Special function that will always be coded in ARM assembly, even if
in Thumb-only compilation. */
#if defined(__thumb__) && !defined(__THUMB_INTERWORK__)
.macro ARM_FUNC_START name
FUNC_START \name
bx pc
nop
.arm
_L__\name: /* A hook to tell gdb that we've switched to ARM */
.endm
#else
.macro ARM_FUNC_START name
FUNC_START \name
.endm
#endif
/* Register aliases. */ /* Register aliases. */
work .req r4 @ XXXX is this safe ? work .req r4 @ XXXX is this safe ?
...@@ -452,7 +510,7 @@ LSYM(Lgot_result): ...@@ -452,7 +510,7 @@ LSYM(Lgot_result):
#endif /* ARM version */ #endif /* ARM version */
FUNC_END udivsi3 DIV_FUNC_END udivsi3
#endif /* L_udivsi3 */ #endif /* L_udivsi3 */
/* ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */
...@@ -493,7 +551,7 @@ LSYM(Lover10): ...@@ -493,7 +551,7 @@ LSYM(Lover10):
#endif /* ARM version. */ #endif /* ARM version. */
FUNC_END umodsi3 DIV_FUNC_END umodsi3
#endif /* L_umodsi3 */ #endif /* L_umodsi3 */
/* ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */
...@@ -555,7 +613,7 @@ LSYM(Lover12): ...@@ -555,7 +613,7 @@ LSYM(Lover12):
#endif /* ARM version */ #endif /* ARM version */
FUNC_END divsi3 DIV_FUNC_END divsi3
#endif /* L_divsi3 */ #endif /* L_divsi3 */
/* ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */
...@@ -616,7 +674,7 @@ LSYM(Lover12): ...@@ -616,7 +674,7 @@ LSYM(Lover12):
#endif /* ARM version */ #endif /* ARM version */
FUNC_END modsi3 DIV_FUNC_END modsi3
#endif /* L_modsi3 */ #endif /* L_modsi3 */
/* ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */
...@@ -626,7 +684,7 @@ LSYM(Lover12): ...@@ -626,7 +684,7 @@ LSYM(Lover12):
RET RET
SIZE (__div0) FUNC_END div0
#endif /* L_divmodsi_tools */ #endif /* L_divmodsi_tools */
/* ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */
...@@ -639,22 +697,18 @@ LSYM(Lover12): ...@@ -639,22 +697,18 @@ LSYM(Lover12):
#define __NR_getpid (__NR_SYSCALL_BASE+ 20) #define __NR_getpid (__NR_SYSCALL_BASE+ 20)
#define __NR_kill (__NR_SYSCALL_BASE+ 37) #define __NR_kill (__NR_SYSCALL_BASE+ 37)
.code 32
FUNC_START div0 FUNC_START div0
stmfd sp!, {r1, lr} stmfd sp!, {r1, lr}
swi __NR_getpid swi __NR_getpid
cmn r0, #1000 cmn r0, #1000
ldmhsfd sp!, {r1, pc}RETCOND @ not much we can do RETLDM r1 hs
mov r1, #SIGFPE mov r1, #SIGFPE
swi __NR_kill swi __NR_kill
#ifdef __THUMB_INTERWORK__ RETLDM r1
ldmfd sp!, {r1, lr}
bx lr
#else
ldmfd sp!, {r1, pc}RETCOND
#endif
SIZE (__div0) FUNC_END div0
#endif /* L_dvmd_lnx */ #endif /* L_dvmd_lnx */
/* ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */
...@@ -723,24 +777,23 @@ LSYM(Lover12): ...@@ -723,24 +777,23 @@ LSYM(Lover12):
.code 32 .code 32
.globl _arm_return .globl _arm_return
_arm_return: _arm_return:
ldmia r13!, {r12} RETLDM
bx r12
.code 16 .code 16
.macro interwork register .macro interwork register
.code 16 .code 16
THUMB_FUNC_START _interwork_call_via_\register THUMB_FUNC_START _interwork_call_via_\register
bx pc bx pc
nop nop
.code 32 .code 32
.globl .Lchange_\register .globl LSYM(Lchange_\register)
.Lchange_\register: LSYM(Lchange_\register):
tst \register, #1 tst \register, #1
stmeqdb r13!, {lr} streq lr, [sp, #-4]!
adreq lr, _arm_return adreq lr, _arm_return
bx \register bx \register
...@@ -783,16 +836,6 @@ _arm_return: ...@@ -783,16 +836,6 @@ _arm_return:
#endif /* L_interwork_call_via_rX */ #endif /* L_interwork_call_via_rX */
#ifdef L_ieee754_dp
/* These functions are coded in ARM state, even when called from
Thumb. */
.arm
#include "ieee754-df.S" #include "ieee754-df.S"
#endif
#ifdef L_ieee754_sp
/* These functions are coded in ARM state, even when called from
Thumb. */
.arm
#include "ieee754-sf.S" #include "ieee754-sf.S"
#endif
LIB1ASMSRC = arm/lib1funcs.asm LIB1ASMSRC = arm/lib1funcs.asm
LIB1ASMFUNCS = _udivsi3 _divsi3 _umodsi3 _modsi3 _dvmd_tls _bb_init_func _call_via_rX _interwork_call_via_rX _ieee754_dp _ieee754_sp LIB1ASMFUNCS = _udivsi3 _divsi3 _umodsi3 _modsi3 _dvmd_tls _bb_init_func \
_call_via_rX _interwork_call_via_rX \
_negdf2 _addsubdf3 _muldivdf3 _cmpdf2 _unorddf2 _fixdfsi \
_truncdfsf2 _negsf2 _addsubsf3 _muldivsf3 _cmpsf2 _unordsf2 \
_fixsfsi _fixunssfsi
MULTILIB_OPTIONS = marm/mthumb MULTILIB_OPTIONS = marm/mthumb
MULTILIB_DIRNAMES = arm thumb MULTILIB_DIRNAMES = arm thumb
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment