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>
* tree-optimize.c: New file.
......
......@@ -40,33 +40,6 @@
* 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 VFP, floats words follow the memory system mode.
......@@ -83,24 +56,19 @@
#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
#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
......@@ -155,12 +123,7 @@ ARM_FUNC_START adddf3
@ already in xh-xl. We need up to 54 bit to handle proper rounding
@ of 0x1p54 - 1.1.
cmp r5, #(54 << 20)
#ifdef __FP_INTERWORKING__
ldmhifd sp!, {r4, r5, lr}
bxhi lr
#else
ldmhifd sp!, {r4, r5, pc}RETCOND
#endif
RETLDM "r4, r5" hi
@ Convert mantissa to signed integer.
tst xh, #0x80000000
......@@ -227,9 +190,9 @@ LSYM(Lad_x):
LSYM(Lad_p):
cmp xh, #0x00100000
bcc LSYM(Lad_l)
cmp r0, #0x00200000
cmp xh, #0x00200000
bcc LSYM(Lad_r0)
cmp r0, #0x00400000
cmp xh, #0x00400000
bcc LSYM(Lad_r1)
@ Result needs to be shifted right.
......@@ -268,14 +231,10 @@ LSYM(Lad_e):
bic xh, xh, #0x00300000
orr xh, xh, r4
orr xh, xh, r5
#ifdef __FP_INTERWORKING__
ldmfd sp!, {r4, r5, lr}
bx lr
#else
ldmfd sp!, {r4, r5, pc}RETCOND
#endif
RETLDM "r4, r5"
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.
#if __ARM_ARCH__ < 5
......@@ -351,12 +310,7 @@ LSYM(Lad_l): @ Result must be shifted left and exponent adjusted.
mov xl, xl, lsr r4
orr xl, xl, xh, lsl r2
orr xh, r5, xh, lsr r4
#ifdef __FP_INTERWORKING
ldmfd sp!, {r4, r5, lr}
bx lr
#else
ldmfd sp!, {r4, r5, pc}RETCOND
#endif
RETLDM "r4, r5"
@ shift result right of 21 to 31 bits, or left 11 to 1 bits after
@ a register switch from xh to xl.
......@@ -365,23 +319,13 @@ LSYM(Lad_l): @ Result must be shifted left and exponent adjusted.
mov xl, xl, lsr r2
orr xl, xl, xh, lsl r4
mov xh, r5
#ifdef __FP_INTERWORKING__
ldmfd sp!, {r4, r5, lr}
bx lr
#else
ldmfd sp!, {r4, r5, pc}RETCOND
#endif
RETLDM "r4, r5"
@ Shift value right of 32 to 64 bits, or 0 to 32 bits after a switch
@ from xh to xl.
2: mov xl, xh, lsr r4
mov xh, r5
#ifdef __FP_INTERWORKING__
ldmfd sp!, {r4, r5, lr}
bx lr
#else
ldmfd sp!, {r4, r5, pc}RETCOND
#endif
RETLDM "r4, r5"
@ Adjust exponents for denormalized arguments.
LSYM(Lad_d):
......@@ -407,12 +351,7 @@ LSYM(Lad_o):
orr xh, r5, #0x7f000000
orr xh, xh, #0x00f00000
mov xl, #0
#ifdef __FP_INTERWORKING__
ldmfd sp!, {r4, r5, lr}
bx lr
#else
ldmfd sp!, {r4, r5, pc}RETCOND
#endif
RETLDM "r4, r5"
@ At least one of x or y is INF/NAN.
@ if xh-xl != INF/NAN: return yh-yl (which is INF/NAN)
......@@ -425,24 +364,17 @@ LSYM(Lad_i):
movne xh, yh
movne xl, yl
teqeq r5, ip
#ifdef __FP_INTERWORKING__
ldmnefd sp!, {r4, r5, lr}
bxne lr
#else
ldmnefd sp!, {r4, r5, pc}RETCOND
#endif
RETLDM "r4, r5" ne
orrs r4, xl, xh, lsl #12
orreqs r4, yl, yh, lsl #12
teqeq xh, yh
orrne xh, r5, #0x00080000
movne xl, #0
#ifdef __FP_INTERWORKING__
ldmfd sp!, {r4, r5, lr}
bx lr
#else
ldmfd sp!, {r4, r5, pc}RETCOND
#endif
RETLDM "r4, r5"
FUNC_END subdf3
FUNC_END adddf3
ARM_FUNC_START floatunsidf
teq r0, #0
......@@ -456,6 +388,7 @@ ARM_FUNC_START floatunsidf
mov xh, #0
b LSYM(Lad_l)
FUNC_END floatunsidf
ARM_FUNC_START floatsidf
teq r0, #0
......@@ -470,6 +403,7 @@ ARM_FUNC_START floatsidf
mov xh, #0
b LSYM(Lad_l)
FUNC_END floatsidf
ARM_FUNC_START extendsfdf2
movs r2, r0, lsl #1
......@@ -495,6 +429,11 @@ ARM_FUNC_START extendsfdf2
bic xh, xh, #0x80000000
b LSYM(Lad_l)
FUNC_END extendsfdf2
#endif /* L_addsubdf3 */
#ifdef L_muldivdf3
ARM_FUNC_START muldf3
......@@ -656,12 +595,7 @@ LSYM(Lml_x):
@ Add final exponent.
bic xh, xh, #0x00300000
orr xh, xh, r4, lsl #1
#ifdef __FP_INTERWORKING__
ldmfd sp!, {r4, r5, r6, lr}
bx lr
#else
ldmfd sp!, {r4, r5, r6, pc}RETCOND
#endif
RETLDM "r4, r5, r6"
@ Result is 0, but determine sign anyway.
LSYM(Lml_z):
......@@ -669,23 +603,14 @@ LSYM(Lml_z):
LSYM(Ldv_z):
bic xh, xh, #0x7fffffff
mov xl, #0
#ifdef __FP_INTERWORKING__
ldmfd sp!, {r4, r5, r6, lr}
bx lr
#else
ldmfd sp!, {r4, r5, r6, pc}RETCOND
#endif
RETLDM "r4, r5, r6"
@ Check if denormalized result is possible, otherwise return signed 0.
LSYM(Lml_u):
cmn r4, #(53 << 19)
movle xl, #0
#ifdef __FP_INTERWORKING__
ldmlefd sp!, {r4, r5, r6, lr}
bxle lr
#else
ldmlefd sp!, {r4, r5, r6, pc}RETCOND
#endif
bicle xh, xh, #0x7fffffff
RETLDM "r4, r5, r6" le
@ Find out proper shift value.
LSYM(Lml_r):
......@@ -709,12 +634,7 @@ LSYM(Lml_r):
teq lr, #0
teqeq r3, #0x80000000
biceq xl, xl, #1
#ifdef __FP_INTERWORKING__
ldmfd sp!, {r4, r5, r6, lr}
bx lr
#else
ldmfd sp!, {r4, r5, r6, pc}RETCOND
#endif
RETLDM "r4, r5, r6"
@ shift result right of 21 to 31 bits, or left 11 to 1 bits after
@ a register switch from xh to xl. Then round.
......@@ -729,12 +649,7 @@ LSYM(Lml_r):
teq lr, #0
teqeq r3, #0x80000000
biceq xl, xl, #1
#ifdef __FP_INTERWORKING__
ldmfd sp!, {r4, r5, r6, lr}
bx lr
#else
ldmfd sp!, {r4, r5, r6, pc}RETCOND
#endif
RETLDM "r4, r5, r6"
@ 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.
......@@ -749,12 +664,7 @@ LSYM(Lml_r):
orrs r6, r6, lr
teqeq r3, #0x80000000
biceq xl, xl, #1
#ifdef __FP_INTERWORKING__
ldmfd sp!, {r4, r5, r6, lr}
bx lr
#else
ldmfd sp!, {r4, r5, r6, pc}RETCOND
#endif
RETLDM "r4, r5, r6"
@ One or both arguments are denormalized.
@ Scale them leftwards and preserve sign bit.
......@@ -804,24 +714,15 @@ LSYM(Lml_o):
orr xh, xh, #0x7f000000
orr xh, xh, #0x00f00000
mov xl, #0
#ifdef __FP_INTERWORKING__
ldmfd sp!, {r4, r5, r6, lr}
bx lr
#else
ldmfd sp!, {r4, r5, r6, pc}RETCOND
#endif
RETLDM "r4, r5, r6"
@ Return NAN.
LSYM(Lml_n):
mov xh, #0x7f000000
orr xh, xh, #0x00f80000
#ifdef __FP_INTERWORKING__
ldmfd sp!, {r4, r5, r6, lr}
bx lr
#else
ldmfd sp!, {r4, r5, r6, pc}RETCOND
#endif
RETLDM "r4, r5, r6"
FUNC_END muldf3
ARM_FUNC_START divdf3
......@@ -961,12 +862,7 @@ LSYM(Ldv_x):
@ Add exponent to result.
bic xh, xh, #0x00100000
orr xh, xh, r4, lsl #1
#ifdef __FP_INTERWORKING__
ldmfd sp!, {r4, r5, r6, lr}
bx lr
#else
ldmfd sp!, {r4, r5, r6, pc}RETCOND
#endif
RETLDM "r4, r5, r6"
@ Division by 0x1p*: shortcut a lot of code.
LSYM(Ldv_1):
......@@ -978,12 +874,8 @@ LSYM(Ldv_1):
bge LSYM(Lml_o)
cmp r4, #0
orrgt xh, xh, r4, lsl #1
#ifdef __FP_INTERWORKING__
ldmgtfd sp!, {r4, r5, r6, lr}
bxgt lr
#else
ldmgtfd sp!, {r4, r5, r6, pc}RETCOND
#endif
RETLDM "r4, r5, r6" gt
cmn r4, #(53 << 19)
ble LSYM(Ldv_z)
orr xh, xh, #0x00100000
......@@ -1042,6 +934,11 @@ LSYM(Ldv_s):
bne LSYM(Lml_z) @ 0 / <non_zero> -> 0
b LSYM(Lml_n) @ 0 / 0 -> NAN
FUNC_END divdf3
#endif /* L_muldivdf3 */
#ifdef L_cmpdf2
FUNC_START gedf2
ARM_FUNC_START gtdf2
......@@ -1076,23 +973,13 @@ ARM_FUNC_START cmpdf2
teqne xh, yh @ or xh == yh
teqeq xl, yl @ and xl == yl
moveq r0, #0 @ then equal.
#ifdef __FP_INTERWORKING__
ldmeqfd sp!, {r4, r5, lr}
bxeq lr
#else
ldmeqfd sp!, {r4, r5, pc}RETCOND
#endif
RETLDM "r4, r5" eq
@ Check for sign difference.
teq xh, yh
movmi r0, xh, asr #31
orrmi r0, r0, #1
#ifdef __FP_INTERWORKING__
ldmmifd sp!, {r4, r5, lr}
bxmi lr
#else
ldmmifd sp!, {r4, r5, pc}RETCOND
#endif
RETLDM "r4, r5" mi
@ Compare exponents.
cmp r4, r5
......@@ -1104,12 +991,7 @@ ARM_FUNC_START cmpdf2
movcs r0, yh, asr #31
mvncc r0, yh, asr #31
orr r0, r0, #1
#ifdef __FP_INTERWORKING__
ldmfd sp!, {r4, r5, lr}
bx lr
#else
ldmfd sp!, {r4, r5, pc}RETCOND
#endif
RETLDM "r4, r5"
@ Look for a NAN.
3: teq r4, lr
......@@ -1121,13 +1003,19 @@ ARM_FUNC_START cmpdf2
orrs yl, yl, yh, lsl #12
beq 2b @ y is not NAN
5: mov r0, ip @ return unordered code from ip
#ifdef __FP_INTERWORKING__
ldmfd sp!, {r4, r5, lr}
bx lr
#else
ldmfd sp!, {r4, r5, pc}RETCOND
#endif
RETLDM "r4, r5"
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
str lr, [sp, #-4]!
......@@ -1144,35 +1032,22 @@ ARM_FUNC_START unorddf2
orrs yl, yl, yh, lsl #12
bne 3f @ y is NAN
2: mov r0, #0 @ arguments are ordered.
#ifdef __FP_INTERWORKING__
ldr lr, [sp], #4
bx lr
#elif defined (__APCS_26__)
ldmia sp!, {pc}^
#else
ldr pc, [sp], #4
#endif
RETLDM
3: mov r0, #1 @ arguments are unordered.
#ifdef __FP_INTERWORKING__
ldr lr, [sp], #4
bx lr
#elif defined (__APCS_26__)
ldmia sp!, {pc}^
#else
ldr pc, [sp], #4
#endif
RETLDM
FUNC_END unorddf2
#endif /* L_unorddf2 */
#ifdef L_fixdfsi
ARM_FUNC_START fixdfsi
orrs ip, xl, xh, lsl #1
beq 1f @ value is 0.
@ preserve C flag (the actual sign)
#ifdef __APCS_26__
mov r3, pc
#else
mrs r3, cpsr
#endif
mov r3, r3, rrx @ preserve C flag (the actual sign)
@ check exponent range.
mov ip, #0x7f000000
......@@ -1192,8 +1067,8 @@ ARM_FUNC_START fixdfsi
orr ip, ip, #0x80000000
orr ip, ip, xl, lsr #21
mov r2, r2, lsr #20
tst r3, #0x80000000 @ the sign bit
mov r0, ip, lsr r2
tst r3, #0x20000000 @ the sign bit
rsbne r0, r0, #0
RET
......@@ -1202,18 +1077,19 @@ ARM_FUNC_START fixdfsi
2: orrs xl, xl, xh, lsl #12
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
movne r0, #0x80000000 @ maximum signed negative si
RET
4: mov r0, #0 @ How should we convert NAN?
RET
FUNC_END fixdfsi
ARM_FUNC_START fixunsdfsi
orrs ip, xl, xh, lsl #1
beq 1b @ value is 0
bcs 1b @ value is negative
movcss r0, #0 @ value is negative
RETc(eq) @ or 0 (xl, xh overlap r0)
@ check exponent range.
mov ip, #0x7f000000
......@@ -1241,6 +1117,11 @@ ARM_FUNC_START fixunsdfsi
2: mov r0, #0xffffffff @ maximum unsigned si
RET
FUNC_END fixunsdfsi
#endif /* L_fixunsdfdi */
#ifdef L_truncdfsf2
ARM_FUNC_START truncdfsf2
orrs r2, xl, xh, lsl #1
......@@ -1328,4 +1209,6 @@ ARM_FUNC_START truncdfsf2
and xh, xh, #0x80000000
b 5b
FUNC_END truncdfsf2
#endif /* L_truncdfsf2 */
......@@ -38,50 +38,17 @@
* 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
#ifdef L_negsf2
#if defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5T__) \
|| defined(__ARM_ARCH_5TE__)
#undef __ARM_ARCH__
#define __ARM_ARCH__ 5
#endif
ARM_FUNC_START negsf2
eor r0, r0, #0x80000000 @ flip sign bit
RET
#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
FUNC_END negsf2
#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
ARM_FUNC_START negsf2
eor r0, r0, #0x80000000 @ flip sign bit
RET
#ifdef L_addsubsf3
ARM_FUNC_START subsf3
eor r1, r1, #0x80000000 @ flip sign bit of second arg
......@@ -291,6 +258,8 @@ LSYM(Lad_i):
orrne r0, r3, #0x00400000 @ NAN
RET
FUNC_END addsf3
FUNC_END subsf3
ARM_FUNC_START floatunsisf
mov r3, #0
......@@ -321,6 +290,12 @@ ARM_FUNC_START floatsisf
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
......@@ -509,6 +484,7 @@ LSYM(Lml_n):
orr r0, r0, #0x00c00000
RET
FUNC_END mulsf3
ARM_FUNC_START divsf3
......@@ -659,6 +635,11 @@ LSYM(Ldv_s):
bne LSYM(Lml_z) @ 0 / <non_zero> -> 0
b LSYM(Lml_n) @ 0 / 0 -> NAN
FUNC_END divsf3
#endif /* L_muldivsf3 */
#ifdef L_cmpsf2
FUNC_START gesf2
ARM_FUNC_START gtsf2
......@@ -723,6 +704,17 @@ ARM_FUNC_START cmpsf2
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
......@@ -741,16 +733,17 @@ ARM_FUNC_START unordsf2
3: mov r0, #1 @ arguments are unordered.
RET
FUNC_END unordsf2
#endif /* L_unordsf2 */
#ifdef L_fixsfsi
ARM_FUNC_START fixsfsi
movs r0, r0, lsl #1
RETc(eq) @ value is 0.
@ preserve C flag (the actual sign)
#ifdef __APCS_26__
mov r1, pc
#else
mrs r1, cpsr
#endif
mov r1, r1, rrx @ preserve C flag (the actual sign)
@ check exponent range.
and r2, r0, #0xff000000
......@@ -764,8 +757,8 @@ ARM_FUNC_START fixsfsi
orr r0, r0, #0x80000000
mov r2, r2, lsr #24
rsb r2, r2, #(127 + 31)
tst r1, #0x80000000 @ the sign bit
mov r0, r0, lsr r2
tst r1, #0x20000000 @ the sign bit
rsbne r0, r0, #0
RET
......@@ -773,20 +766,24 @@ ARM_FUNC_START fixsfsi
bne 2f
movs r0, r0, lsl #8
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
movne r0, #0x80000000 @ the maximum signed negative si
RET
3: mov r0, #0 @ What should we convert NAN to?
RET
FUNC_END fixsfsi
#endif /* L_fixsfsi */
#ifdef L_fixunssfsi
ARM_FUNC_START fixunssfsi
movs r0, r0, lsl #1
RETc(eq) @ value is 0.
movcs r0, #0
RETc(cs) @ value is negative.
movcss r0, #0 @ value is negative...
RETc(eq) @ ... or 0.
@ check exponent range.
and r2, r0, #0xff000000
......@@ -806,8 +803,13 @@ ARM_FUNC_START fixunssfsi
1: teq r2, #0xff000000
bne 2f
movs r0, r0, lsl #8
bne 3b @ r0 is NAN.
bne 3f @ r0 is NAN.
2: mov r0, #0xffffffff @ maximum unsigned si
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. */
/* 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__
# define RET movs pc, lr
# define RETc(x) mov##x##s pc, lr
# define RETCOND ^
.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
#else
# ifdef __THUMB_INTERWORK__
#elif (__ARM_ARCH__ > 4) || defined(__ARM_ARCH_4T__)
# define RET bx lr
# define RETc(x) bx##x lr
.macro THUMB_LDIV0
LSYM(Ldiv0):
push { lr }
bl SYM (__div0)
mov r0, #0 @ About as wrong as it could be.
pop { r1 }
bx r1
# 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
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
RETLDM
.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.
#if defined (__INTERWORKING__)
pop { r1 }
bx r1
#else
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
.endm
.macro FUNC_END name
SIZE (__\name)
.endm
.macro DIV_FUNC_END name
LSYM(Ldiv0):
#ifdef __thumb__
THUMB_LDIV0
#else
ARM_LDIV0
#endif
SIZE (__\name)
FUNC_END \name
.endm
.macro THUMB_FUNC_START name
......@@ -150,6 +191,23 @@ SYM (\name):
SYM (__\name):
.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. */
work .req r4 @ XXXX is this safe ?
......@@ -452,7 +510,7 @@ LSYM(Lgot_result):
#endif /* ARM version */
FUNC_END udivsi3
DIV_FUNC_END udivsi3
#endif /* L_udivsi3 */
/* ------------------------------------------------------------------------ */
......@@ -493,7 +551,7 @@ LSYM(Lover10):
#endif /* ARM version. */
FUNC_END umodsi3
DIV_FUNC_END umodsi3
#endif /* L_umodsi3 */
/* ------------------------------------------------------------------------ */
......@@ -555,7 +613,7 @@ LSYM(Lover12):
#endif /* ARM version */
FUNC_END divsi3
DIV_FUNC_END divsi3
#endif /* L_divsi3 */
/* ------------------------------------------------------------------------ */
......@@ -616,7 +674,7 @@ LSYM(Lover12):
#endif /* ARM version */
FUNC_END modsi3
DIV_FUNC_END modsi3
#endif /* L_modsi3 */
/* ------------------------------------------------------------------------ */
......@@ -626,7 +684,7 @@ LSYM(Lover12):
RET
SIZE (__div0)
FUNC_END div0
#endif /* L_divmodsi_tools */
/* ------------------------------------------------------------------------ */
......@@ -639,22 +697,18 @@ LSYM(Lover12):
#define __NR_getpid (__NR_SYSCALL_BASE+ 20)
#define __NR_kill (__NR_SYSCALL_BASE+ 37)
.code 32
FUNC_START div0
stmfd sp!, {r1, lr}
swi __NR_getpid
cmn r0, #1000
ldmhsfd sp!, {r1, pc}RETCOND @ not much we can do
RETLDM r1 hs
mov r1, #SIGFPE
swi __NR_kill
#ifdef __THUMB_INTERWORK__
ldmfd sp!, {r1, lr}
bx lr
#else
ldmfd sp!, {r1, pc}RETCOND
#endif
RETLDM r1
SIZE (__div0)
FUNC_END div0
#endif /* L_dvmd_lnx */
/* ------------------------------------------------------------------------ */
......@@ -724,8 +778,7 @@ LSYM(Lover12):
.code 32
.globl _arm_return
_arm_return:
ldmia r13!, {r12}
bx r12
RETLDM
.code 16
.macro interwork register
......@@ -737,10 +790,10 @@ _arm_return:
nop
.code 32
.globl .Lchange_\register
.Lchange_\register:
.globl LSYM(Lchange_\register)
LSYM(Lchange_\register):
tst \register, #1
stmeqdb r13!, {lr}
streq lr, [sp, #-4]!
adreq lr, _arm_return
bx \register
......@@ -783,16 +836,6 @@ _arm_return:
#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"
#endif
#ifdef L_ieee754_sp
/* These functions are coded in ARM state, even when called from
Thumb. */
.arm
#include "ieee754-sf.S"
#endif
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_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