mirror of
https://github.com/pret/agbcc.git
synced 2026-09-30 05:06:27 -05:00
remove alternate versions of thumb files
This commit is contained in:
@@ -39,6 +39,18 @@ Boston, MA 02111-1307, USA. */
|
||||
#error __USER_LABEL_PREFIX__ not defined
|
||||
#endif
|
||||
|
||||
#ifdef __elf__
|
||||
#define __PLT__ (PLT)
|
||||
#define TYPE(x) .type SYM(x),function
|
||||
#define SIZE(x) .size SYM(x), . - SYM(x)
|
||||
#else
|
||||
#define __PLT__
|
||||
#define TYPE(x)
|
||||
#define SIZE(x)
|
||||
#endif
|
||||
|
||||
#define RET mov pc, lr
|
||||
|
||||
/* ANSI concatenation macros. */
|
||||
|
||||
#define CONCAT1(a, b) CONCAT2(a, b)
|
||||
@@ -48,298 +60,290 @@ Boston, MA 02111-1307, USA. */
|
||||
|
||||
#define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
|
||||
|
||||
#define __PLT__
|
||||
|
||||
#ifdef __ELF__
|
||||
#define TYPE(x) .type SYM(x),function
|
||||
#define SIZE(x) .size SYM(x), . - SYM(x)
|
||||
#else
|
||||
#define TYPE(x)
|
||||
#define SIZE(x)
|
||||
#endif
|
||||
|
||||
/* Function end macros. Variants for interworking. */
|
||||
|
||||
# define __THUMB_INTERWORK__
|
||||
# ifdef __THUMB_INTERWORK__
|
||||
# define RET bx lr
|
||||
# define RETc(x) bx##x lr
|
||||
.macro THUMB_LDIV0
|
||||
.Ldiv0:
|
||||
push { lr }
|
||||
bl SYM (__div0)
|
||||
mov r0, #0 @ About as wrong as it could be.
|
||||
pop { r1 }
|
||||
bx r1
|
||||
.endm
|
||||
# else
|
||||
# define RET mov pc, lr
|
||||
# define RETc(x) mov##x pc, lr
|
||||
.macro THUMB_LDIV0
|
||||
.Ldiv0:
|
||||
push { lr }
|
||||
bl SYM (__div0)
|
||||
mov r0, #0 @ About as wrong as it could be.
|
||||
pop { pc }
|
||||
.endm
|
||||
# endif
|
||||
# define RETCOND
|
||||
|
||||
.macro FUNC_END name
|
||||
.Ldiv0:
|
||||
THUMB_LDIV0
|
||||
SIZE (__\name)
|
||||
.endm
|
||||
|
||||
.macro THUMB_FUNC_START name
|
||||
.globl SYM (\name)
|
||||
TYPE (\name)
|
||||
.thumb_func
|
||||
SYM (\name):
|
||||
.endm
|
||||
|
||||
/* Function start macros. */
|
||||
|
||||
#define THUMB_FUNC .thumb_func
|
||||
#define THUMB_CODE .force_thumb
|
||||
|
||||
.macro FUNC_START name
|
||||
.text
|
||||
.globl SYM (__\name)
|
||||
TYPE (__\name)
|
||||
.align 0
|
||||
THUMB_CODE
|
||||
THUMB_FUNC
|
||||
SYM (__\name):
|
||||
.endm
|
||||
|
||||
/* Register aliases. */
|
||||
|
||||
work .req r4 @ XXXX is this safe ?
|
||||
|
||||
#ifdef L_udivsi3
|
||||
|
||||
dividend .req r0
|
||||
divisor .req r1
|
||||
overdone .req r2
|
||||
result .req r2
|
||||
curbit .req r3
|
||||
ip .req r12
|
||||
sp .req r13
|
||||
lr .req r14
|
||||
pc .req r15
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* Bodies of the divsion and modulo routines. */
|
||||
/* ------------------------------------------------------------------------ */
|
||||
.macro THUMB_DIV_MOD_BODY modulo
|
||||
@ Load the constant 0x10000000 into our work register.
|
||||
mov work, #1
|
||||
lsl work, #28
|
||||
.Loop1:
|
||||
@ Unless the divisor is very big, shift it up in multiples of
|
||||
@ four bits, since this is the amount of unwinding in the main
|
||||
@ division loop. Continue shifting until the divisor is
|
||||
@ larger than the dividend.
|
||||
cmp divisor, work
|
||||
bhs .Lbignum
|
||||
cmp divisor, dividend
|
||||
bhs .Lbignum
|
||||
lsl divisor, #4
|
||||
lsl curbit, #4
|
||||
b .Loop1
|
||||
.Lbignum:
|
||||
@ Set work to 0x80000000
|
||||
lsl work, #3
|
||||
.Loop2:
|
||||
@ For very big divisors, we must shift it a bit at a time, or
|
||||
@ we will be in danger of overflowing.
|
||||
cmp divisor, work
|
||||
bhs .Loop3
|
||||
cmp divisor, dividend
|
||||
bhs .Loop3
|
||||
lsl divisor, #1
|
||||
lsl curbit, #1
|
||||
b .Loop2
|
||||
.Loop3:
|
||||
@ Test for possible subtractions ...
|
||||
.if \modulo
|
||||
@ ... On the final pass, this may subtract too much from the dividend,
|
||||
@ so keep track of which subtractions are done, we can fix them up
|
||||
@ afterwards.
|
||||
mov overdone, #0
|
||||
cmp dividend, divisor
|
||||
blo .Lover1
|
||||
sub dividend, dividend, divisor
|
||||
.Lover1:
|
||||
lsr work, divisor, #1
|
||||
cmp dividend, work
|
||||
blo .Lover2
|
||||
sub dividend, dividend, work
|
||||
mov ip, curbit
|
||||
mov work, #1
|
||||
ror curbit, work
|
||||
orr overdone, curbit
|
||||
mov curbit, ip
|
||||
.Lover2:
|
||||
lsr work, divisor, #2
|
||||
cmp dividend, work
|
||||
blo .Lover3
|
||||
sub dividend, dividend, work
|
||||
mov ip, curbit
|
||||
mov work, #2
|
||||
ror curbit, work
|
||||
orr overdone, curbit
|
||||
mov curbit, ip
|
||||
.Lover3:
|
||||
lsr work, divisor, #3
|
||||
cmp dividend, work
|
||||
blo .Lover4
|
||||
sub dividend, dividend, work
|
||||
mov ip, curbit
|
||||
mov work, #3
|
||||
ror curbit, work
|
||||
orr overdone, curbit
|
||||
mov curbit, ip
|
||||
.Lover4:
|
||||
mov ip, curbit
|
||||
.else
|
||||
@ ... and note which bits are done in the result. On the final pass,
|
||||
@ this may subtract too much from the dividend, but the result will be ok,
|
||||
@ since the "bit" will have been shifted out at the bottom.
|
||||
cmp dividend, divisor
|
||||
blo .Lover1
|
||||
sub dividend, dividend, divisor
|
||||
orr result, result, curbit
|
||||
.Lover1:
|
||||
lsr work, divisor, #1
|
||||
cmp dividend, work
|
||||
blo .Lover2
|
||||
sub dividend, dividend, work
|
||||
lsr work, curbit, #1
|
||||
orr result, work
|
||||
.Lover2:
|
||||
lsr work, divisor, #2
|
||||
cmp dividend, work
|
||||
blo .Lover3
|
||||
sub dividend, dividend, work
|
||||
lsr work, curbit, #2
|
||||
orr result, work
|
||||
.Lover3:
|
||||
lsr work, divisor, #3
|
||||
cmp dividend, work
|
||||
blo .Lover4
|
||||
sub dividend, dividend, work
|
||||
lsr work, curbit, #3
|
||||
orr result, work
|
||||
.Lover4:
|
||||
.endif
|
||||
|
||||
cmp dividend, #0 @ Early termination?
|
||||
beq .Lover5
|
||||
lsr curbit, #4 @ No, any more bits to do?
|
||||
beq .Lover5
|
||||
lsr divisor, #4
|
||||
b .Loop3
|
||||
.Lover5:
|
||||
.if \modulo
|
||||
@ Any subtractions that we should not have done will be recorded in
|
||||
@ the top three bits of "overdone". Exactly which were not needed
|
||||
@ are governed by the position of the bit, stored in ip.
|
||||
mov work, #0xe
|
||||
lsl work, #28
|
||||
and overdone, work
|
||||
beq .Lgot_result
|
||||
|
||||
@ If we terminated early, because dividend became zero, then the
|
||||
@ bit in ip will not be in the bottom nibble, and we should not
|
||||
@ perform the additions below. We must test for this though
|
||||
@ (rather relying upon the TSTs to prevent the additions) since
|
||||
@ the bit in ip could be in the top two bits which might then match
|
||||
@ with one of the smaller RORs.
|
||||
mov curbit, ip
|
||||
mov work, #0x7
|
||||
tst curbit, work
|
||||
beq .Lgot_result
|
||||
|
||||
mov curbit, ip
|
||||
mov work, #3
|
||||
ror curbit, work
|
||||
tst overdone, curbit
|
||||
beq .Lover6
|
||||
lsr work, divisor, #3
|
||||
add dividend, work
|
||||
.Lover6:
|
||||
mov curbit, ip
|
||||
mov work, #2
|
||||
ror curbit, work
|
||||
tst overdone, curbit
|
||||
beq .Lover7
|
||||
lsr work, divisor, #2
|
||||
add dividend, work
|
||||
.Lover7:
|
||||
mov curbit, ip
|
||||
mov work, #1
|
||||
ror curbit, work
|
||||
tst overdone, curbit
|
||||
beq .Lgot_result
|
||||
lsr work, divisor, #1
|
||||
add dividend, work
|
||||
.endif
|
||||
.Lgot_result:
|
||||
.endm
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* Start of the Real Functions */
|
||||
/* ------------------------------------------------------------------------ */
|
||||
#ifdef L_udivsi3
|
||||
|
||||
FUNC_START udivsi3
|
||||
|
||||
.text
|
||||
.globl SYM (__udivsi3)
|
||||
TYPE (__udivsi3)
|
||||
.align 0
|
||||
.thumb_func
|
||||
SYM (__udivsi3):
|
||||
cmp divisor, #0
|
||||
beq .Ldiv0
|
||||
beq Ldiv0
|
||||
mov curbit, #1
|
||||
mov result, #0
|
||||
|
||||
push { work }
|
||||
cmp dividend, divisor
|
||||
blo .Lgot_result
|
||||
bcc Lgot_result
|
||||
|
||||
THUMB_DIV_MOD_BODY 0
|
||||
|
||||
@ Load the constant 0x10000000 into our work register
|
||||
mov work, #1
|
||||
lsl work, #28
|
||||
Loop1:
|
||||
@ Unless the divisor is very big, shift it up in multiples of
|
||||
@ four bits, since this is the amount of unwinding in the main
|
||||
@ division loop. Continue shifting until the divisor is
|
||||
@ larger than the dividend.
|
||||
cmp divisor, work
|
||||
bcs Lbignum
|
||||
cmp divisor, dividend
|
||||
bcs Lbignum
|
||||
lsl divisor, #4
|
||||
lsl curbit, #4
|
||||
b Loop1
|
||||
|
||||
Lbignum:
|
||||
@ Set work to 0x80000000
|
||||
lsl work, #3
|
||||
Loop2:
|
||||
@ For very big divisors, we must shift it a bit at a time, or
|
||||
@ we will be in danger of overflowing.
|
||||
cmp divisor, work
|
||||
bcs Loop3
|
||||
cmp divisor, dividend
|
||||
bcs Loop3
|
||||
lsl divisor, #1
|
||||
lsl curbit, #1
|
||||
b Loop2
|
||||
|
||||
Loop3:
|
||||
@ Test for possible subtractions, and note which bits
|
||||
@ are done in the result. On the final pass, this may subtract
|
||||
@ too much from the dividend, but the result will be ok, since the
|
||||
@ "bit" will have been shifted out at the bottom.
|
||||
cmp dividend, divisor
|
||||
bcc Over1
|
||||
sub dividend, dividend, divisor
|
||||
orr result, result, curbit
|
||||
Over1:
|
||||
lsr work, divisor, #1
|
||||
cmp dividend, work
|
||||
bcc Over2
|
||||
sub dividend, dividend, work
|
||||
lsr work, curbit, #1
|
||||
orr result, work
|
||||
Over2:
|
||||
lsr work, divisor, #2
|
||||
cmp dividend, work
|
||||
bcc Over3
|
||||
sub dividend, dividend, work
|
||||
lsr work, curbit, #2
|
||||
orr result, work
|
||||
Over3:
|
||||
lsr work, divisor, #3
|
||||
cmp dividend, work
|
||||
bcc Over4
|
||||
sub dividend, dividend, work
|
||||
lsr work, curbit, #3
|
||||
orr result, work
|
||||
Over4:
|
||||
cmp dividend, #0 @ Early termination?
|
||||
beq Lgot_result
|
||||
lsr curbit, #4 @ No, any more bits to do?
|
||||
beq Lgot_result
|
||||
lsr divisor, #4
|
||||
b Loop3
|
||||
Lgot_result:
|
||||
mov r0, result
|
||||
pop { work }
|
||||
RET
|
||||
|
||||
FUNC_END udivsi3
|
||||
Ldiv0:
|
||||
push { lr }
|
||||
bl SYM (__div0) __PLT__
|
||||
mov r0, #0 @ about as wrong as it could be
|
||||
pop { pc }
|
||||
|
||||
SIZE (__udivsi3)
|
||||
|
||||
#endif /* L_udivsi3 */
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
#ifdef L_umodsi3
|
||||
|
||||
FUNC_START umodsi3
|
||||
|
||||
dividend .req r0
|
||||
divisor .req r1
|
||||
overdone .req r2
|
||||
curbit .req r3
|
||||
ip .req r12
|
||||
sp .req r13
|
||||
lr .req r14
|
||||
pc .req r15
|
||||
|
||||
.text
|
||||
.globl SYM (__umodsi3)
|
||||
TYPE (__umodsi3)
|
||||
.align 0
|
||||
.thumb_func
|
||||
SYM (__umodsi3):
|
||||
cmp divisor, #0
|
||||
beq .Ldiv0
|
||||
beq Ldiv0
|
||||
mov curbit, #1
|
||||
cmp dividend, divisor
|
||||
bhs ..Lover10
|
||||
bcs Over1
|
||||
RET
|
||||
|
||||
..Lover10:
|
||||
Over1:
|
||||
@ Load the constant 0x10000000 into our work register
|
||||
push { work }
|
||||
mov work, #1
|
||||
lsl work, #28
|
||||
Loop1:
|
||||
@ Unless the divisor is very big, shift it up in multiples of
|
||||
@ four bits, since this is the amount of unwinding in the main
|
||||
@ division loop. Continue shifting until the divisor is
|
||||
@ larger than the dividend.
|
||||
cmp divisor, work
|
||||
bcs Lbignum
|
||||
cmp divisor, dividend
|
||||
bcs Lbignum
|
||||
lsl divisor, #4
|
||||
lsl curbit, #4
|
||||
b Loop1
|
||||
|
||||
THUMB_DIV_MOD_BODY 1
|
||||
|
||||
Lbignum:
|
||||
@ Set work to 0x80000000
|
||||
lsl work, #3
|
||||
Loop2:
|
||||
@ For very big divisors, we must shift it a bit at a time, or
|
||||
@ we will be in danger of overflowing.
|
||||
cmp divisor, work
|
||||
bcs Loop3
|
||||
cmp divisor, dividend
|
||||
bcs Loop3
|
||||
lsl divisor, #1
|
||||
lsl curbit, #1
|
||||
b Loop2
|
||||
|
||||
Loop3:
|
||||
@ Test for possible subtractions. On the final pass, this may
|
||||
@ subtract too much from the dividend, so keep track of which
|
||||
@ subtractions are done, we can fix them up afterwards...
|
||||
mov overdone, #0
|
||||
cmp dividend, divisor
|
||||
bcc Over2
|
||||
sub dividend, dividend, divisor
|
||||
Over2:
|
||||
lsr work, divisor, #1
|
||||
cmp dividend, work
|
||||
bcc Over3
|
||||
sub dividend, dividend, work
|
||||
mov ip, curbit
|
||||
mov work, #1
|
||||
ror curbit, work
|
||||
orr overdone, curbit
|
||||
mov curbit, ip
|
||||
Over3:
|
||||
lsr work, divisor, #2
|
||||
cmp dividend, work
|
||||
bcc Over4
|
||||
sub dividend, dividend, work
|
||||
mov ip, curbit
|
||||
mov work, #2
|
||||
ror curbit, work
|
||||
orr overdone, curbit
|
||||
mov curbit, ip
|
||||
Over4:
|
||||
lsr work, divisor, #3
|
||||
cmp dividend, work
|
||||
bcc Over5
|
||||
sub dividend, dividend, work
|
||||
mov ip, curbit
|
||||
mov work, #3
|
||||
ror curbit, work
|
||||
orr overdone, curbit
|
||||
mov curbit, ip
|
||||
Over5:
|
||||
mov ip, curbit
|
||||
cmp dividend, #0 @ Early termination?
|
||||
beq Over6
|
||||
lsr curbit, #4 @ No, any more bits to do?
|
||||
beq Over6
|
||||
lsr divisor, #4
|
||||
b Loop3
|
||||
|
||||
Over6:
|
||||
@ Any subtractions that we should not have done will be recorded in
|
||||
@ the top three bits of "overdone". Exactly which were not needed
|
||||
@ are governed by the position of the bit, stored in ip.
|
||||
@ If we terminated early, because dividend became zero,
|
||||
@ then none of the below will match, since the bit in ip will not be
|
||||
@ in the bottom nibble.
|
||||
|
||||
mov work, #0xe
|
||||
lsl work, #28
|
||||
and overdone, work
|
||||
bne Over7
|
||||
pop { work }
|
||||
RET
|
||||
|
||||
FUNC_END umodsi3
|
||||
RET @ No fixups needed
|
||||
Over7:
|
||||
mov curbit, ip
|
||||
mov work, #3
|
||||
ror curbit, work
|
||||
tst overdone, curbit
|
||||
beq Over8
|
||||
lsr work, divisor, #3
|
||||
add dividend, dividend, work
|
||||
Over8:
|
||||
mov curbit, ip
|
||||
mov work, #2
|
||||
ror curbit, work
|
||||
tst overdone, curbit
|
||||
beq Over9
|
||||
lsr work, divisor, #2
|
||||
add dividend, dividend, work
|
||||
Over9:
|
||||
mov curbit, ip
|
||||
mov work, #1
|
||||
ror curbit, work
|
||||
tst overdone, curbit
|
||||
beq Over10
|
||||
lsr work, divisor, #1
|
||||
add dividend, dividend, work
|
||||
Over10:
|
||||
pop { work }
|
||||
RET
|
||||
|
||||
Ldiv0:
|
||||
push { lr }
|
||||
bl SYM (__div0) __PLT__
|
||||
mov r0, #0 @ about as wrong as it could be
|
||||
pop { pc }
|
||||
|
||||
SIZE (__umodsi3)
|
||||
|
||||
#endif /* L_umodsi3 */
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
#ifdef L_divsi3
|
||||
|
||||
FUNC_START divsi3
|
||||
|
||||
dividend .req r0
|
||||
divisor .req r1
|
||||
result .req r2
|
||||
curbit .req r3
|
||||
ip .req r12
|
||||
sp .req r13
|
||||
lr .req r14
|
||||
pc .req r15
|
||||
|
||||
.text
|
||||
.globl SYM (__divsi3)
|
||||
TYPE (__divsi3)
|
||||
.align 0
|
||||
.thumb_func
|
||||
SYM (__divsi3):
|
||||
cmp divisor, #0
|
||||
beq .Ldiv0
|
||||
beq Ldiv0
|
||||
|
||||
push { work }
|
||||
mov work, dividend
|
||||
@@ -348,111 +352,281 @@ pc .req r15
|
||||
mov curbit, #1
|
||||
mov result, #0
|
||||
cmp divisor, #0
|
||||
bpl .Lover10
|
||||
bpl Over1
|
||||
neg divisor, divisor @ Loops below use unsigned.
|
||||
.Lover10:
|
||||
Over1:
|
||||
cmp dividend, #0
|
||||
bpl .Lover11
|
||||
bpl Over2
|
||||
neg dividend, dividend
|
||||
.Lover11:
|
||||
Over2:
|
||||
cmp dividend, divisor
|
||||
blo .Lgot_result
|
||||
bcc Lgot_result
|
||||
|
||||
THUMB_DIV_MOD_BODY 0
|
||||
mov work, #1
|
||||
lsl work, #28
|
||||
Loop1:
|
||||
@ Unless the divisor is very big, shift it up in multiples of
|
||||
@ four bits, since this is the amount of unwinding in the main
|
||||
@ division loop. Continue shifting until the divisor is
|
||||
@ larger than the dividend.
|
||||
cmp divisor, work
|
||||
Bcs Lbignum
|
||||
cmp divisor, dividend
|
||||
Bcs Lbignum
|
||||
lsl divisor, #4
|
||||
lsl curbit, #4
|
||||
b Loop1
|
||||
|
||||
Lbignum:
|
||||
@ For very big divisors, we must shift it a bit at a time, or
|
||||
@ we will be in danger of overflowing.
|
||||
lsl work, #3
|
||||
Loop2:
|
||||
cmp divisor, work
|
||||
Bcs Loop3
|
||||
cmp divisor, dividend
|
||||
Bcs Loop3
|
||||
lsl divisor, #1
|
||||
lsl curbit, #1
|
||||
b Loop2
|
||||
|
||||
Loop3:
|
||||
@ Test for possible subtractions, and note which bits
|
||||
@ are done in the result. On the final pass, this may subtract
|
||||
@ too much from the dividend, but the result will be ok, since the
|
||||
@ "bit" will have been shifted out at the bottom.
|
||||
cmp dividend, divisor
|
||||
Bcc Over3
|
||||
sub dividend, dividend, divisor
|
||||
orr result, result, curbit
|
||||
Over3:
|
||||
lsr work, divisor, #1
|
||||
cmp dividend, work
|
||||
Bcc Over4
|
||||
sub dividend, dividend, work
|
||||
lsr work, curbit, #1
|
||||
orr result, work
|
||||
Over4:
|
||||
lsr work, divisor, #2
|
||||
cmp dividend, work
|
||||
Bcc Over5
|
||||
sub dividend, dividend, work
|
||||
lsr work, curbit, #2
|
||||
orr result, result, work
|
||||
Over5:
|
||||
lsr work, divisor, #3
|
||||
cmp dividend, work
|
||||
Bcc Over6
|
||||
sub dividend, dividend, work
|
||||
lsr work, curbit, #3
|
||||
orr result, result, work
|
||||
Over6:
|
||||
cmp dividend, #0 @ Early termination?
|
||||
Beq Lgot_result
|
||||
lsr curbit, #4 @ No, any more bits to do?
|
||||
Beq Lgot_result
|
||||
lsr divisor, #4
|
||||
b Loop3
|
||||
|
||||
Lgot_result:
|
||||
mov r0, result
|
||||
mov work, ip
|
||||
cmp work, #0
|
||||
bpl .Lover12
|
||||
Bpl Over7
|
||||
neg r0, r0
|
||||
.Lover12:
|
||||
Over7:
|
||||
pop { work }
|
||||
RET
|
||||
|
||||
FUNC_END divsi3
|
||||
RET
|
||||
|
||||
Ldiv0:
|
||||
push { lr }
|
||||
bl SYM (__div0) __PLT__
|
||||
mov r0, #0 @ about as wrong as it could be
|
||||
pop { pc }
|
||||
|
||||
SIZE (__divsi3)
|
||||
|
||||
#endif /* L_divsi3 */
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
#ifdef L_modsi3
|
||||
|
||||
FUNC_START modsi3
|
||||
|
||||
dividend .req r0
|
||||
divisor .req r1
|
||||
overdone .req r2
|
||||
curbit .req r3
|
||||
ip .req r12
|
||||
sp .req r13
|
||||
lr .req r14
|
||||
pc .req r15
|
||||
|
||||
.text
|
||||
.globl SYM (__modsi3)
|
||||
TYPE (__modsi3)
|
||||
.align 0
|
||||
.thumb_func
|
||||
SYM (__modsi3):
|
||||
mov curbit, #1
|
||||
cmp divisor, #0
|
||||
beq .Ldiv0
|
||||
bpl .Lover10
|
||||
beq Ldiv0
|
||||
Bpl Over1
|
||||
neg divisor, divisor @ Loops below use unsigned.
|
||||
|
||||
.Lover10:
|
||||
Over1:
|
||||
push { work }
|
||||
@ Need to save the sign of the dividend, unfortunately, we need
|
||||
@ work later on. Must do this after saving the original value of
|
||||
@ ip later on. Must do this after saving the original value of
|
||||
@ the work register, because we will pop this value off first.
|
||||
push { dividend }
|
||||
cmp dividend, #0
|
||||
bpl .Lover11
|
||||
Bpl Over2
|
||||
neg dividend, dividend
|
||||
.Lover11:
|
||||
Over2:
|
||||
cmp dividend, divisor
|
||||
blo .Lgot_result
|
||||
bcc Lgot_result
|
||||
mov work, #1
|
||||
lsl work, #28
|
||||
Loop1:
|
||||
@ Unless the divisor is very big, shift it up in multiples of
|
||||
@ four bits, since this is the amount of unwinding in the main
|
||||
@ division loop. Continue shifting until the divisor is
|
||||
@ larger than the dividend.
|
||||
cmp divisor, work
|
||||
bcs Lbignum
|
||||
cmp divisor, dividend
|
||||
bcs Lbignum
|
||||
lsl divisor, #4
|
||||
lsl curbit, #4
|
||||
b Loop1
|
||||
|
||||
THUMB_DIV_MOD_BODY 1
|
||||
|
||||
Lbignum:
|
||||
@ Set work to 0x80000000
|
||||
lsl work, #3
|
||||
Loop2:
|
||||
@ For very big divisors, we must shift it a bit at a time, or
|
||||
@ we will be in danger of overflowing.
|
||||
cmp divisor, work
|
||||
bcs Loop3
|
||||
cmp divisor, dividend
|
||||
bcs Loop3
|
||||
lsl divisor, #1
|
||||
lsl curbit, #1
|
||||
b Loop2
|
||||
|
||||
Loop3:
|
||||
@ Test for possible subtractions. On the final pass, this may
|
||||
@ subtract too much from the dividend, so keep track of which
|
||||
@ subtractions are done, we can fix them up afterwards...
|
||||
mov overdone, #0
|
||||
cmp dividend, divisor
|
||||
bcc Over3
|
||||
sub dividend, dividend, divisor
|
||||
Over3:
|
||||
lsr work, divisor, #1
|
||||
cmp dividend, work
|
||||
bcc Over4
|
||||
sub dividend, dividend, work
|
||||
mov ip, curbit
|
||||
mov work, #1
|
||||
ror curbit, work
|
||||
orr overdone, curbit
|
||||
mov curbit, ip
|
||||
Over4:
|
||||
lsr work, divisor, #2
|
||||
cmp dividend, work
|
||||
bcc Over5
|
||||
sub dividend, dividend, work
|
||||
mov ip, curbit
|
||||
mov work, #2
|
||||
ror curbit, work
|
||||
orr overdone, curbit
|
||||
mov curbit, ip
|
||||
Over5:
|
||||
lsr work, divisor, #3
|
||||
cmp dividend, work
|
||||
bcc Over6
|
||||
sub dividend, dividend, work
|
||||
mov ip, curbit
|
||||
mov work, #3
|
||||
ror curbit, work
|
||||
orr overdone, curbit
|
||||
mov curbit, ip
|
||||
Over6:
|
||||
mov ip, curbit
|
||||
cmp dividend, #0 @ Early termination?
|
||||
beq Over7
|
||||
lsr curbit, #4 @ No, any more bits to do?
|
||||
beq Over7
|
||||
lsr divisor, #4
|
||||
b Loop3
|
||||
|
||||
Over7:
|
||||
@ Any subtractions that we should not have done will be recorded in
|
||||
@ the top three bits of "overdone". Exactly which were not needed
|
||||
@ are governed by the position of the bit, stored in ip.
|
||||
@ If we terminated early, because dividend became zero,
|
||||
@ then none of the below will match, since the bit in ip will not be
|
||||
@ in the bottom nibble.
|
||||
mov work, #0xe
|
||||
lsl work, #28
|
||||
and overdone, work
|
||||
beq Lgot_result
|
||||
|
||||
mov curbit, ip
|
||||
mov work, #3
|
||||
ror curbit, work
|
||||
tst overdone, curbit
|
||||
beq Over8
|
||||
lsr work, divisor, #3
|
||||
add dividend, dividend, work
|
||||
Over8:
|
||||
mov curbit, ip
|
||||
mov work, #2
|
||||
ror curbit, work
|
||||
tst overdone, curbit
|
||||
beq Over9
|
||||
lsr work, divisor, #2
|
||||
add dividend, dividend, work
|
||||
Over9:
|
||||
mov curbit, ip
|
||||
mov work, #1
|
||||
ror curbit, work
|
||||
tst overdone, curbit
|
||||
beq Lgot_result
|
||||
lsr work, divisor, #1
|
||||
add dividend, dividend, work
|
||||
Lgot_result:
|
||||
pop { work }
|
||||
cmp work, #0
|
||||
bpl .Lover12
|
||||
bpl Over10
|
||||
neg dividend, dividend
|
||||
.Lover12:
|
||||
Over10:
|
||||
pop { work }
|
||||
RET
|
||||
|
||||
FUNC_END modsi3
|
||||
|
||||
Ldiv0:
|
||||
push { lr }
|
||||
bl SYM (__div0) __PLT__
|
||||
mov r0, #0 @ about as wrong as it could be
|
||||
pop { pc }
|
||||
|
||||
SIZE (__modsi3)
|
||||
|
||||
#endif /* L_modsi3 */
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
#ifdef L_dvmd_tls
|
||||
|
||||
FUNC_START div0
|
||||
|
||||
RET
|
||||
.globl SYM (__div0)
|
||||
TYPE (__div0)
|
||||
.align 0
|
||||
.thumb_func
|
||||
SYM (__div0):
|
||||
RET
|
||||
|
||||
SIZE (__div0)
|
||||
|
||||
#endif /* L_divmodsi_tools */
|
||||
/* ------------------------------------------------------------------------ */
|
||||
#ifdef L_dvmd_lnx
|
||||
@ GNU/Linux division-by zero handler. Used in place of L_dvmd_tls
|
||||
|
||||
#include <asm/unistd.h>
|
||||
|
||||
#define SIGFPE 8 @ cant use <asm/signal.h> as it
|
||||
@ contains too much C rubbish
|
||||
FUNC_START div0
|
||||
|
||||
stmfd sp!, {r1, lr}
|
||||
swi __NR_getpid
|
||||
cmn r0, #1000
|
||||
ldmhsfd sp!, {r1, pc}RETCOND @ not much we can do
|
||||
mov r1, #SIGFPE
|
||||
swi __NR_kill
|
||||
#ifdef __THUMB_INTERWORK__
|
||||
ldmfd sp!, {r1, lr}
|
||||
bx lr
|
||||
#else
|
||||
ldmfd sp!, {r1, pc}RETCOND
|
||||
#endif
|
||||
|
||||
SIZE (__div0)
|
||||
|
||||
#endif /* L_dvmd_lnx */
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* These next two sections are here despite the fact that they contain Thumb
|
||||
assembler because their presence allows interworked code to be linked even
|
||||
when the GCC library is this one. */
|
||||
|
||||
/* Do not build the interworking functions when the target architecture does
|
||||
not support Thumb instructions. (This can be a multilib option). */
|
||||
#if defined L_call_via_rX
|
||||
#ifdef L_call_via_rX
|
||||
|
||||
/* These labels & instructions are used by the Arm/Thumb interworking code.
|
||||
The address of function to be called is loaded into a register and then
|
||||
@@ -462,14 +636,15 @@ pc .req r15
|
||||
|
||||
.text
|
||||
.align 0
|
||||
.force_thumb
|
||||
|
||||
.macro call_via register
|
||||
THUMB_FUNC_START _call_via_\register
|
||||
|
||||
.globl SYM (_call_via_\register)
|
||||
TYPE (_call_via_\register)
|
||||
.thumb_func
|
||||
SYM (_call_via_\register):
|
||||
bx \register
|
||||
nop
|
||||
|
||||
|
||||
SIZE (_call_via_\register)
|
||||
.endm
|
||||
|
||||
@@ -490,10 +665,8 @@ pc .req r15
|
||||
call_via lr
|
||||
|
||||
#endif /* L_call_via_rX */
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* Do not build the interworking functions when the target architecture does
|
||||
not support Thumb instructions. (This can be a multilib option). */
|
||||
#if defined L_interwork_call_via_rX
|
||||
|
||||
#ifdef L_interwork_call_via_rX
|
||||
|
||||
/* These labels & instructions are used by the Arm/Thumb interworking code,
|
||||
when the target address is in an unknown instruction set. The address
|
||||
@@ -509,22 +682,23 @@ pc .req r15
|
||||
.text
|
||||
.align 0
|
||||
|
||||
.code 32
|
||||
.code 32
|
||||
.globl _arm_return
|
||||
_arm_return:
|
||||
ldmia r13!, {r12}
|
||||
bx r12
|
||||
.code 16
|
||||
|
||||
|
||||
.macro interwork register
|
||||
.code 16
|
||||
|
||||
THUMB_FUNC_START _interwork_call_via_\register
|
||||
|
||||
.code 16
|
||||
|
||||
.globl SYM (_interwork_call_via_\register)
|
||||
TYPE (_interwork_call_via_\register)
|
||||
.thumb_func
|
||||
SYM (_interwork_call_via_\register):
|
||||
bx pc
|
||||
nop
|
||||
|
||||
.code 32
|
||||
.code 32
|
||||
.globl .Lchange_\register
|
||||
.Lchange_\register:
|
||||
tst \register, #1
|
||||
@@ -549,12 +723,13 @@ _arm_return:
|
||||
interwork fp
|
||||
interwork ip
|
||||
interwork sp
|
||||
|
||||
/* The LR case has to be handled a little differently... */
|
||||
|
||||
/* The lr case has to be handled a little differently...*/
|
||||
.code 16
|
||||
|
||||
THUMB_FUNC_START _interwork_call_via_lr
|
||||
|
||||
.globl SYM (_interwork_call_via_lr)
|
||||
TYPE (_interwork_call_via_lr)
|
||||
.thumb_func
|
||||
SYM (_interwork_call_via_lr):
|
||||
bx pc
|
||||
nop
|
||||
|
||||
@@ -566,7 +741,7 @@ _arm_return:
|
||||
mov ip, lr
|
||||
adreq lr, _arm_return
|
||||
bx ip
|
||||
|
||||
|
||||
SIZE (_interwork_call_via_lr)
|
||||
|
||||
#endif /* L_interwork_call_via_rX */
|
||||
|
||||
@@ -1,747 +0,0 @@
|
||||
@ libgcc1 routines for ARM cpu.
|
||||
@ Division routines, written by Richard Earnshaw, (rearnsha@armltd.co.uk)
|
||||
|
||||
/* Copyright (C) 1995, 1996, 1998 Free Software Foundation, Inc.
|
||||
|
||||
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 with other programs, and to distribute
|
||||
those programs 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 another program.)
|
||||
|
||||
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. */
|
||||
|
||||
/* As a special exception, if you link this library with other files,
|
||||
some of which are compiled with GCC, to produce an executable,
|
||||
this library does not by itself cause the resulting executable
|
||||
to be covered by the GNU General Public License.
|
||||
This exception does not however invalidate any other reasons why
|
||||
the executable file might be covered by the GNU General Public License. */
|
||||
|
||||
.code 16
|
||||
|
||||
#ifndef __USER_LABEL_PREFIX__
|
||||
#error __USER_LABEL_PREFIX__ not defined
|
||||
#endif
|
||||
|
||||
#ifdef __elf__
|
||||
#define __PLT__ (PLT)
|
||||
#define TYPE(x) .type SYM(x),function
|
||||
#define SIZE(x) .size SYM(x), . - SYM(x)
|
||||
#else
|
||||
#define __PLT__
|
||||
#define TYPE(x)
|
||||
#define SIZE(x)
|
||||
#endif
|
||||
|
||||
#define RET mov pc, lr
|
||||
|
||||
/* ANSI concatenation macros. */
|
||||
|
||||
#define CONCAT1(a, b) CONCAT2(a, b)
|
||||
#define CONCAT2(a, b) a ## b
|
||||
|
||||
/* Use the right prefix for global labels. */
|
||||
|
||||
#define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
|
||||
|
||||
work .req r4 @ XXXX is this safe ?
|
||||
|
||||
#ifdef L_udivsi3
|
||||
|
||||
dividend .req r0
|
||||
divisor .req r1
|
||||
result .req r2
|
||||
curbit .req r3
|
||||
ip .req r12
|
||||
sp .req r13
|
||||
lr .req r14
|
||||
pc .req r15
|
||||
|
||||
.text
|
||||
.globl SYM (__udivsi3)
|
||||
TYPE (__udivsi3)
|
||||
.align 0
|
||||
.thumb_func
|
||||
SYM (__udivsi3):
|
||||
cmp divisor, #0
|
||||
beq Ldiv0
|
||||
mov curbit, #1
|
||||
mov result, #0
|
||||
|
||||
push { work }
|
||||
cmp dividend, divisor
|
||||
bcc Lgot_result
|
||||
|
||||
@ Load the constant 0x10000000 into our work register
|
||||
mov work, #1
|
||||
lsl work, #28
|
||||
Loop1:
|
||||
@ Unless the divisor is very big, shift it up in multiples of
|
||||
@ four bits, since this is the amount of unwinding in the main
|
||||
@ division loop. Continue shifting until the divisor is
|
||||
@ larger than the dividend.
|
||||
cmp divisor, work
|
||||
bcs Lbignum
|
||||
cmp divisor, dividend
|
||||
bcs Lbignum
|
||||
lsl divisor, #4
|
||||
lsl curbit, #4
|
||||
b Loop1
|
||||
|
||||
Lbignum:
|
||||
@ Set work to 0x80000000
|
||||
lsl work, #3
|
||||
Loop2:
|
||||
@ For very big divisors, we must shift it a bit at a time, or
|
||||
@ we will be in danger of overflowing.
|
||||
cmp divisor, work
|
||||
bcs Loop3
|
||||
cmp divisor, dividend
|
||||
bcs Loop3
|
||||
lsl divisor, #1
|
||||
lsl curbit, #1
|
||||
b Loop2
|
||||
|
||||
Loop3:
|
||||
@ Test for possible subtractions, and note which bits
|
||||
@ are done in the result. On the final pass, this may subtract
|
||||
@ too much from the dividend, but the result will be ok, since the
|
||||
@ "bit" will have been shifted out at the bottom.
|
||||
cmp dividend, divisor
|
||||
bcc Over1
|
||||
sub dividend, dividend, divisor
|
||||
orr result, result, curbit
|
||||
Over1:
|
||||
lsr work, divisor, #1
|
||||
cmp dividend, work
|
||||
bcc Over2
|
||||
sub dividend, dividend, work
|
||||
lsr work, curbit, #1
|
||||
orr result, work
|
||||
Over2:
|
||||
lsr work, divisor, #2
|
||||
cmp dividend, work
|
||||
bcc Over3
|
||||
sub dividend, dividend, work
|
||||
lsr work, curbit, #2
|
||||
orr result, work
|
||||
Over3:
|
||||
lsr work, divisor, #3
|
||||
cmp dividend, work
|
||||
bcc Over4
|
||||
sub dividend, dividend, work
|
||||
lsr work, curbit, #3
|
||||
orr result, work
|
||||
Over4:
|
||||
cmp dividend, #0 @ Early termination?
|
||||
beq Lgot_result
|
||||
lsr curbit, #4 @ No, any more bits to do?
|
||||
beq Lgot_result
|
||||
lsr divisor, #4
|
||||
b Loop3
|
||||
Lgot_result:
|
||||
mov r0, result
|
||||
pop { work }
|
||||
RET
|
||||
|
||||
Ldiv0:
|
||||
push { lr }
|
||||
bl SYM (__div0) __PLT__
|
||||
mov r0, #0 @ about as wrong as it could be
|
||||
pop { pc }
|
||||
|
||||
SIZE (__udivsi3)
|
||||
|
||||
#endif /* L_udivsi3 */
|
||||
|
||||
#ifdef L_umodsi3
|
||||
|
||||
dividend .req r0
|
||||
divisor .req r1
|
||||
overdone .req r2
|
||||
curbit .req r3
|
||||
ip .req r12
|
||||
sp .req r13
|
||||
lr .req r14
|
||||
pc .req r15
|
||||
|
||||
.text
|
||||
.globl SYM (__umodsi3)
|
||||
TYPE (__umodsi3)
|
||||
.align 0
|
||||
.thumb_func
|
||||
SYM (__umodsi3):
|
||||
cmp divisor, #0
|
||||
beq Ldiv0
|
||||
mov curbit, #1
|
||||
cmp dividend, divisor
|
||||
bcs Over1
|
||||
RET
|
||||
|
||||
Over1:
|
||||
@ Load the constant 0x10000000 into our work register
|
||||
push { work }
|
||||
mov work, #1
|
||||
lsl work, #28
|
||||
Loop1:
|
||||
@ Unless the divisor is very big, shift it up in multiples of
|
||||
@ four bits, since this is the amount of unwinding in the main
|
||||
@ division loop. Continue shifting until the divisor is
|
||||
@ larger than the dividend.
|
||||
cmp divisor, work
|
||||
bcs Lbignum
|
||||
cmp divisor, dividend
|
||||
bcs Lbignum
|
||||
lsl divisor, #4
|
||||
lsl curbit, #4
|
||||
b Loop1
|
||||
|
||||
Lbignum:
|
||||
@ Set work to 0x80000000
|
||||
lsl work, #3
|
||||
Loop2:
|
||||
@ For very big divisors, we must shift it a bit at a time, or
|
||||
@ we will be in danger of overflowing.
|
||||
cmp divisor, work
|
||||
bcs Loop3
|
||||
cmp divisor, dividend
|
||||
bcs Loop3
|
||||
lsl divisor, #1
|
||||
lsl curbit, #1
|
||||
b Loop2
|
||||
|
||||
Loop3:
|
||||
@ Test for possible subtractions. On the final pass, this may
|
||||
@ subtract too much from the dividend, so keep track of which
|
||||
@ subtractions are done, we can fix them up afterwards...
|
||||
mov overdone, #0
|
||||
cmp dividend, divisor
|
||||
bcc Over2
|
||||
sub dividend, dividend, divisor
|
||||
Over2:
|
||||
lsr work, divisor, #1
|
||||
cmp dividend, work
|
||||
bcc Over3
|
||||
sub dividend, dividend, work
|
||||
mov ip, curbit
|
||||
mov work, #1
|
||||
ror curbit, work
|
||||
orr overdone, curbit
|
||||
mov curbit, ip
|
||||
Over3:
|
||||
lsr work, divisor, #2
|
||||
cmp dividend, work
|
||||
bcc Over4
|
||||
sub dividend, dividend, work
|
||||
mov ip, curbit
|
||||
mov work, #2
|
||||
ror curbit, work
|
||||
orr overdone, curbit
|
||||
mov curbit, ip
|
||||
Over4:
|
||||
lsr work, divisor, #3
|
||||
cmp dividend, work
|
||||
bcc Over5
|
||||
sub dividend, dividend, work
|
||||
mov ip, curbit
|
||||
mov work, #3
|
||||
ror curbit, work
|
||||
orr overdone, curbit
|
||||
mov curbit, ip
|
||||
Over5:
|
||||
mov ip, curbit
|
||||
cmp dividend, #0 @ Early termination?
|
||||
beq Over6
|
||||
lsr curbit, #4 @ No, any more bits to do?
|
||||
beq Over6
|
||||
lsr divisor, #4
|
||||
b Loop3
|
||||
|
||||
Over6:
|
||||
@ Any subtractions that we should not have done will be recorded in
|
||||
@ the top three bits of "overdone". Exactly which were not needed
|
||||
@ are governed by the position of the bit, stored in ip.
|
||||
@ If we terminated early, because dividend became zero,
|
||||
@ then none of the below will match, since the bit in ip will not be
|
||||
@ in the bottom nibble.
|
||||
|
||||
mov work, #0xe
|
||||
lsl work, #28
|
||||
and overdone, work
|
||||
bne Over7
|
||||
pop { work }
|
||||
RET @ No fixups needed
|
||||
Over7:
|
||||
mov curbit, ip
|
||||
mov work, #3
|
||||
ror curbit, work
|
||||
tst overdone, curbit
|
||||
beq Over8
|
||||
lsr work, divisor, #3
|
||||
add dividend, dividend, work
|
||||
Over8:
|
||||
mov curbit, ip
|
||||
mov work, #2
|
||||
ror curbit, work
|
||||
tst overdone, curbit
|
||||
beq Over9
|
||||
lsr work, divisor, #2
|
||||
add dividend, dividend, work
|
||||
Over9:
|
||||
mov curbit, ip
|
||||
mov work, #1
|
||||
ror curbit, work
|
||||
tst overdone, curbit
|
||||
beq Over10
|
||||
lsr work, divisor, #1
|
||||
add dividend, dividend, work
|
||||
Over10:
|
||||
pop { work }
|
||||
RET
|
||||
|
||||
Ldiv0:
|
||||
push { lr }
|
||||
bl SYM (__div0) __PLT__
|
||||
mov r0, #0 @ about as wrong as it could be
|
||||
pop { pc }
|
||||
|
||||
SIZE (__umodsi3)
|
||||
|
||||
#endif /* L_umodsi3 */
|
||||
|
||||
#ifdef L_divsi3
|
||||
|
||||
dividend .req r0
|
||||
divisor .req r1
|
||||
result .req r2
|
||||
curbit .req r3
|
||||
ip .req r12
|
||||
sp .req r13
|
||||
lr .req r14
|
||||
pc .req r15
|
||||
|
||||
.text
|
||||
.globl SYM (__divsi3)
|
||||
TYPE (__divsi3)
|
||||
.align 0
|
||||
.thumb_func
|
||||
SYM (__divsi3):
|
||||
cmp divisor, #0
|
||||
beq Ldiv0
|
||||
|
||||
push { work }
|
||||
mov work, dividend
|
||||
eor work, divisor @ Save the sign of the result.
|
||||
mov ip, work
|
||||
mov curbit, #1
|
||||
mov result, #0
|
||||
cmp divisor, #0
|
||||
bpl Over1
|
||||
neg divisor, divisor @ Loops below use unsigned.
|
||||
Over1:
|
||||
cmp dividend, #0
|
||||
bpl Over2
|
||||
neg dividend, dividend
|
||||
Over2:
|
||||
cmp dividend, divisor
|
||||
bcc Lgot_result
|
||||
|
||||
mov work, #1
|
||||
lsl work, #28
|
||||
Loop1:
|
||||
@ Unless the divisor is very big, shift it up in multiples of
|
||||
@ four bits, since this is the amount of unwinding in the main
|
||||
@ division loop. Continue shifting until the divisor is
|
||||
@ larger than the dividend.
|
||||
cmp divisor, work
|
||||
Bcs Lbignum
|
||||
cmp divisor, dividend
|
||||
Bcs Lbignum
|
||||
lsl divisor, #4
|
||||
lsl curbit, #4
|
||||
b Loop1
|
||||
|
||||
Lbignum:
|
||||
@ For very big divisors, we must shift it a bit at a time, or
|
||||
@ we will be in danger of overflowing.
|
||||
lsl work, #3
|
||||
Loop2:
|
||||
cmp divisor, work
|
||||
Bcs Loop3
|
||||
cmp divisor, dividend
|
||||
Bcs Loop3
|
||||
lsl divisor, #1
|
||||
lsl curbit, #1
|
||||
b Loop2
|
||||
|
||||
Loop3:
|
||||
@ Test for possible subtractions, and note which bits
|
||||
@ are done in the result. On the final pass, this may subtract
|
||||
@ too much from the dividend, but the result will be ok, since the
|
||||
@ "bit" will have been shifted out at the bottom.
|
||||
cmp dividend, divisor
|
||||
Bcc Over3
|
||||
sub dividend, dividend, divisor
|
||||
orr result, result, curbit
|
||||
Over3:
|
||||
lsr work, divisor, #1
|
||||
cmp dividend, work
|
||||
Bcc Over4
|
||||
sub dividend, dividend, work
|
||||
lsr work, curbit, #1
|
||||
orr result, work
|
||||
Over4:
|
||||
lsr work, divisor, #2
|
||||
cmp dividend, work
|
||||
Bcc Over5
|
||||
sub dividend, dividend, work
|
||||
lsr work, curbit, #2
|
||||
orr result, result, work
|
||||
Over5:
|
||||
lsr work, divisor, #3
|
||||
cmp dividend, work
|
||||
Bcc Over6
|
||||
sub dividend, dividend, work
|
||||
lsr work, curbit, #3
|
||||
orr result, result, work
|
||||
Over6:
|
||||
cmp dividend, #0 @ Early termination?
|
||||
Beq Lgot_result
|
||||
lsr curbit, #4 @ No, any more bits to do?
|
||||
Beq Lgot_result
|
||||
lsr divisor, #4
|
||||
b Loop3
|
||||
|
||||
Lgot_result:
|
||||
mov r0, result
|
||||
mov work, ip
|
||||
cmp work, #0
|
||||
Bpl Over7
|
||||
neg r0, r0
|
||||
Over7:
|
||||
pop { work }
|
||||
RET
|
||||
|
||||
Ldiv0:
|
||||
push { lr }
|
||||
bl SYM (__div0) __PLT__
|
||||
mov r0, #0 @ about as wrong as it could be
|
||||
pop { pc }
|
||||
|
||||
SIZE (__divsi3)
|
||||
|
||||
#endif /* L_divsi3 */
|
||||
|
||||
#ifdef L_modsi3
|
||||
|
||||
dividend .req r0
|
||||
divisor .req r1
|
||||
overdone .req r2
|
||||
curbit .req r3
|
||||
ip .req r12
|
||||
sp .req r13
|
||||
lr .req r14
|
||||
pc .req r15
|
||||
|
||||
.text
|
||||
.globl SYM (__modsi3)
|
||||
TYPE (__modsi3)
|
||||
.align 0
|
||||
.thumb_func
|
||||
SYM (__modsi3):
|
||||
mov curbit, #1
|
||||
cmp divisor, #0
|
||||
beq Ldiv0
|
||||
Bpl Over1
|
||||
neg divisor, divisor @ Loops below use unsigned.
|
||||
Over1:
|
||||
push { work }
|
||||
@ Need to save the sign of the dividend, unfortunately, we need
|
||||
@ ip later on. Must do this after saving the original value of
|
||||
@ the work register, because we will pop this value off first.
|
||||
push { dividend }
|
||||
cmp dividend, #0
|
||||
Bpl Over2
|
||||
neg dividend, dividend
|
||||
Over2:
|
||||
cmp dividend, divisor
|
||||
bcc Lgot_result
|
||||
mov work, #1
|
||||
lsl work, #28
|
||||
Loop1:
|
||||
@ Unless the divisor is very big, shift it up in multiples of
|
||||
@ four bits, since this is the amount of unwinding in the main
|
||||
@ division loop. Continue shifting until the divisor is
|
||||
@ larger than the dividend.
|
||||
cmp divisor, work
|
||||
bcs Lbignum
|
||||
cmp divisor, dividend
|
||||
bcs Lbignum
|
||||
lsl divisor, #4
|
||||
lsl curbit, #4
|
||||
b Loop1
|
||||
|
||||
Lbignum:
|
||||
@ Set work to 0x80000000
|
||||
lsl work, #3
|
||||
Loop2:
|
||||
@ For very big divisors, we must shift it a bit at a time, or
|
||||
@ we will be in danger of overflowing.
|
||||
cmp divisor, work
|
||||
bcs Loop3
|
||||
cmp divisor, dividend
|
||||
bcs Loop3
|
||||
lsl divisor, #1
|
||||
lsl curbit, #1
|
||||
b Loop2
|
||||
|
||||
Loop3:
|
||||
@ Test for possible subtractions. On the final pass, this may
|
||||
@ subtract too much from the dividend, so keep track of which
|
||||
@ subtractions are done, we can fix them up afterwards...
|
||||
mov overdone, #0
|
||||
cmp dividend, divisor
|
||||
bcc Over3
|
||||
sub dividend, dividend, divisor
|
||||
Over3:
|
||||
lsr work, divisor, #1
|
||||
cmp dividend, work
|
||||
bcc Over4
|
||||
sub dividend, dividend, work
|
||||
mov ip, curbit
|
||||
mov work, #1
|
||||
ror curbit, work
|
||||
orr overdone, curbit
|
||||
mov curbit, ip
|
||||
Over4:
|
||||
lsr work, divisor, #2
|
||||
cmp dividend, work
|
||||
bcc Over5
|
||||
sub dividend, dividend, work
|
||||
mov ip, curbit
|
||||
mov work, #2
|
||||
ror curbit, work
|
||||
orr overdone, curbit
|
||||
mov curbit, ip
|
||||
Over5:
|
||||
lsr work, divisor, #3
|
||||
cmp dividend, work
|
||||
bcc Over6
|
||||
sub dividend, dividend, work
|
||||
mov ip, curbit
|
||||
mov work, #3
|
||||
ror curbit, work
|
||||
orr overdone, curbit
|
||||
mov curbit, ip
|
||||
Over6:
|
||||
mov ip, curbit
|
||||
cmp dividend, #0 @ Early termination?
|
||||
beq Over7
|
||||
lsr curbit, #4 @ No, any more bits to do?
|
||||
beq Over7
|
||||
lsr divisor, #4
|
||||
b Loop3
|
||||
|
||||
Over7:
|
||||
@ Any subtractions that we should not have done will be recorded in
|
||||
@ the top three bits of "overdone". Exactly which were not needed
|
||||
@ are governed by the position of the bit, stored in ip.
|
||||
@ If we terminated early, because dividend became zero,
|
||||
@ then none of the below will match, since the bit in ip will not be
|
||||
@ in the bottom nibble.
|
||||
mov work, #0xe
|
||||
lsl work, #28
|
||||
and overdone, work
|
||||
beq Lgot_result
|
||||
|
||||
mov curbit, ip
|
||||
mov work, #3
|
||||
ror curbit, work
|
||||
tst overdone, curbit
|
||||
beq Over8
|
||||
lsr work, divisor, #3
|
||||
add dividend, dividend, work
|
||||
Over8:
|
||||
mov curbit, ip
|
||||
mov work, #2
|
||||
ror curbit, work
|
||||
tst overdone, curbit
|
||||
beq Over9
|
||||
lsr work, divisor, #2
|
||||
add dividend, dividend, work
|
||||
Over9:
|
||||
mov curbit, ip
|
||||
mov work, #1
|
||||
ror curbit, work
|
||||
tst overdone, curbit
|
||||
beq Lgot_result
|
||||
lsr work, divisor, #1
|
||||
add dividend, dividend, work
|
||||
Lgot_result:
|
||||
pop { work }
|
||||
cmp work, #0
|
||||
bpl Over10
|
||||
neg dividend, dividend
|
||||
Over10:
|
||||
pop { work }
|
||||
RET
|
||||
|
||||
Ldiv0:
|
||||
push { lr }
|
||||
bl SYM (__div0) __PLT__
|
||||
mov r0, #0 @ about as wrong as it could be
|
||||
pop { pc }
|
||||
|
||||
SIZE (__modsi3)
|
||||
|
||||
#endif /* L_modsi3 */
|
||||
|
||||
#ifdef L_dvmd_tls
|
||||
|
||||
.globl SYM (__div0)
|
||||
TYPE (__div0)
|
||||
.align 0
|
||||
.thumb_func
|
||||
SYM (__div0):
|
||||
RET
|
||||
|
||||
SIZE (__div0)
|
||||
|
||||
#endif /* L_divmodsi_tools */
|
||||
|
||||
|
||||
#ifdef L_call_via_rX
|
||||
|
||||
/* These labels & instructions are used by the Arm/Thumb interworking code.
|
||||
The address of function to be called is loaded into a register and then
|
||||
one of these labels is called via a BL instruction. This puts the
|
||||
return address into the link register with the bottom bit set, and the
|
||||
code here switches to the correct mode before executing the function. */
|
||||
|
||||
.text
|
||||
.align 0
|
||||
|
||||
.macro call_via register
|
||||
.globl SYM (_call_via_\register)
|
||||
TYPE (_call_via_\register)
|
||||
.thumb_func
|
||||
SYM (_call_via_\register):
|
||||
bx \register
|
||||
nop
|
||||
|
||||
SIZE (_call_via_\register)
|
||||
.endm
|
||||
|
||||
call_via r0
|
||||
call_via r1
|
||||
call_via r2
|
||||
call_via r3
|
||||
call_via r4
|
||||
call_via r5
|
||||
call_via r6
|
||||
call_via r7
|
||||
call_via r8
|
||||
call_via r9
|
||||
call_via sl
|
||||
call_via fp
|
||||
call_via ip
|
||||
call_via sp
|
||||
call_via lr
|
||||
|
||||
#endif /* L_call_via_rX */
|
||||
|
||||
#ifdef L_interwork_call_via_rX
|
||||
|
||||
/* These labels & instructions are used by the Arm/Thumb interworking code,
|
||||
when the target address is in an unknown instruction set. The address
|
||||
of function to be called is loaded into a register and then one of these
|
||||
labels is called via a BL instruction. This puts the return address
|
||||
into the link register with the bottom bit set, and the code here
|
||||
switches to the correct mode before executing the function. Unfortunately
|
||||
the target code cannot be relied upon to return via a BX instruction, so
|
||||
instead we have to store the resturn address on the stack and allow the
|
||||
called function to return here instead. Upon return we recover the real
|
||||
return address and use a BX to get back to Thumb mode. */
|
||||
|
||||
.text
|
||||
.align 0
|
||||
|
||||
.code 32
|
||||
.globl _arm_return
|
||||
_arm_return:
|
||||
ldmia r13!, {r12}
|
||||
bx r12
|
||||
|
||||
.macro interwork register
|
||||
.code 16
|
||||
|
||||
.globl SYM (_interwork_call_via_\register)
|
||||
TYPE (_interwork_call_via_\register)
|
||||
.thumb_func
|
||||
SYM (_interwork_call_via_\register):
|
||||
bx pc
|
||||
nop
|
||||
|
||||
.code 32
|
||||
.globl .Lchange_\register
|
||||
.Lchange_\register:
|
||||
tst \register, #1
|
||||
stmeqdb r13!, {lr}
|
||||
adreq lr, _arm_return
|
||||
bx \register
|
||||
|
||||
SIZE (_interwork_call_via_\register)
|
||||
.endm
|
||||
|
||||
interwork r0
|
||||
interwork r1
|
||||
interwork r2
|
||||
interwork r3
|
||||
interwork r4
|
||||
interwork r5
|
||||
interwork r6
|
||||
interwork r7
|
||||
interwork r8
|
||||
interwork r9
|
||||
interwork sl
|
||||
interwork fp
|
||||
interwork ip
|
||||
interwork sp
|
||||
|
||||
/* The lr case has to be handled a little differently...*/
|
||||
.code 16
|
||||
.globl SYM (_interwork_call_via_lr)
|
||||
TYPE (_interwork_call_via_lr)
|
||||
.thumb_func
|
||||
SYM (_interwork_call_via_lr):
|
||||
bx pc
|
||||
nop
|
||||
|
||||
.code 32
|
||||
.globl .Lchange_lr
|
||||
.Lchange_lr:
|
||||
tst lr, #1
|
||||
stmeqdb r13!, {lr}
|
||||
mov ip, lr
|
||||
adreq lr, _arm_return
|
||||
bx ip
|
||||
|
||||
SIZE (_interwork_call_via_lr)
|
||||
|
||||
#endif /* L_interwork_call_via_rX */
|
||||
@@ -1,443 +0,0 @@
|
||||
/* CYGNUS LOCAL (entire file) clm/arm-elf */
|
||||
/* Definitions of target machine for GNU compiler,
|
||||
for Thumb with ELF obj format.
|
||||
Copyright (C) 1995, 1996, 2001 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
GNU CC 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.
|
||||
|
||||
GNU CC 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 GNU CC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#define OBJECT_FORMAT_ELF
|
||||
|
||||
#define CPP_PREDEFINES "-Dthumb -Dthumbelf -D__thumb -Acpu(arm) -Amachine(arm)"
|
||||
|
||||
#include "arm/thumb.h"
|
||||
|
||||
/* Run-time Target Specification. */
|
||||
#undef TARGET_VERSION
|
||||
#define TARGET_VERSION fputs (" (Thumb/elf)", stderr)
|
||||
|
||||
#define MULTILIB_DEFAULTS { "mlittle-endian" }
|
||||
|
||||
/* Setting this to 32 produces more efficient code, but the value set in previous
|
||||
versions of this toolchain was 8, which produces more compact structures. The
|
||||
command line option -mstructure_size_boundary=<n> can be used to change this
|
||||
value. */
|
||||
#undef STRUCTURE_SIZE_BOUNDARY
|
||||
#define STRUCTURE_SIZE_BOUNDARY arm_structure_size_boundary
|
||||
|
||||
extern int arm_structure_size_boundary;
|
||||
|
||||
/* Debug */
|
||||
#define DWARF_DEBUGGING_INFO
|
||||
#define DWARF2_DEBUGGING_INFO
|
||||
#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
|
||||
|
||||
|
||||
/* Note - it is important that these definitions match those in semi.h for the ARM port. */
|
||||
#undef LOCAL_LABEL_PREFIX
|
||||
#define LOCAL_LABEL_PREFIX "."
|
||||
|
||||
|
||||
/* A C statement to output assembler commands which will identify the
|
||||
object file as having been compiled with GNU CC (or another GNU
|
||||
compiler). */
|
||||
#define ASM_IDENTIFY_GCC(STREAM) \
|
||||
fprintf (STREAM, "%sgcc2_compiled.:\n", LOCAL_LABEL_PREFIX )
|
||||
|
||||
#undef ASM_FILE_START
|
||||
#define ASM_FILE_START(STREAM) \
|
||||
do { \
|
||||
extern char *version_string; \
|
||||
fprintf ((STREAM), "%s Generated by gcc %s for Thumb/elf\n", \
|
||||
ASM_COMMENT_START, version_string); \
|
||||
fprintf ((STREAM), ASM_APP_OFF); \
|
||||
} while (0)
|
||||
|
||||
/* A C statement to output something to the assembler file to switch to section
|
||||
NAME for object DECL which is either a FUNCTION_DECL, a VAR_DECL or
|
||||
NULL_TREE. Some target formats do not support arbitrary sections. Do not
|
||||
define this macro in such cases. */
|
||||
#define ASM_OUTPUT_SECTION_NAME(STREAM, DECL, NAME, RELOC) \
|
||||
do { \
|
||||
if ((DECL) && TREE_CODE (DECL) == FUNCTION_DECL) \
|
||||
fprintf (STREAM, "\t.section %s,\"ax\",%%progbits\n", (NAME)); \
|
||||
else if ((DECL) && DECL_READONLY_SECTION (DECL, RELOC)) \
|
||||
fprintf (STREAM, "\t.section %s,\"a\"\n", (NAME)); \
|
||||
else if (0 == strncmp((NAME), ".bss", sizeof(".bss") - 1)) \
|
||||
fprintf (STREAM, "\t.section %s,\"aw\",%%nobits\n", (NAME)); \
|
||||
else \
|
||||
fprintf (STREAM, "\t.section %s,\"aw\"\n", (NAME)); \
|
||||
} while (0)
|
||||
|
||||
/* Support the ctors/dtors and other sections. */
|
||||
|
||||
#undef INIT_SECTION_ASM_OP
|
||||
|
||||
/* Define this macro if jump tables (for `tablejump' insns) should be
|
||||
output in the text section, along with the assembler instructions.
|
||||
Otherwise, the readonly data section is used. */
|
||||
#define JUMP_TABLES_IN_TEXT_SECTION 1
|
||||
|
||||
#undef READONLY_DATA_SECTION
|
||||
#define READONLY_DATA_SECTION rdata_section
|
||||
#undef RDATA_SECTION_ASM_OP
|
||||
#define RDATA_SECTION_ASM_OP "\t.section .rodata"
|
||||
|
||||
#undef CTORS_SECTION_ASM_OP
|
||||
#define CTORS_SECTION_ASM_OP "\t.section .ctors,\"aw\""
|
||||
#undef DTORS_SECTION_ASM_OP
|
||||
#define DTORS_SECTION_ASM_OP "\t.section .dtors,\"aw\""
|
||||
|
||||
#define USER_LABEL_PREFIX ""
|
||||
|
||||
/* If defined, a C expression whose value is a string containing the
|
||||
assembler operation to identify the following data as
|
||||
uninitialized global data. If not defined, and neither
|
||||
`ASM_OUTPUT_BSS' nor `ASM_OUTPUT_ALIGNED_BSS' are defined,
|
||||
uninitialized global data will be output in the data section if
|
||||
`-fno-common' is passed, otherwise `ASM_OUTPUT_COMMON' will be
|
||||
used. */
|
||||
#ifndef BSS_SECTION_ASM_OP
|
||||
#define BSS_SECTION_ASM_OP ".section\t.bss"
|
||||
#endif
|
||||
|
||||
/* Like `ASM_OUTPUT_BSS' except takes the required alignment as a
|
||||
separate, explicit argument. If you define this macro, it is used
|
||||
in place of `ASM_OUTPUT_BSS', and gives you more flexibility in
|
||||
handling the required alignment of the variable. The alignment is
|
||||
specified as the number of bits.
|
||||
|
||||
Try to use function `asm_output_aligned_bss' defined in file
|
||||
`varasm.c' when defining this macro. */
|
||||
#ifndef ASM_OUTPUT_ALIGNED_BSS
|
||||
#define ASM_OUTPUT_ALIGNED_BSS(FILE, DECL, NAME, SIZE, ALIGN) \
|
||||
asm_output_aligned_bss (FILE, DECL, NAME, SIZE, ALIGN)
|
||||
#endif
|
||||
|
||||
/* Don't know how to order these. UNALIGNED_WORD_ASM_OP is in
|
||||
dwarf2.out. */
|
||||
#define UNALIGNED_WORD_ASM_OP ".4byte"
|
||||
|
||||
#define ASM_OUTPUT_DWARF_ADDR_CONST(FILE,RTX) \
|
||||
do { \
|
||||
fprintf ((FILE), "\t%s\t", UNALIGNED_WORD_ASM_OP); \
|
||||
output_addr_const ((FILE), (RTX)); \
|
||||
fputc ('\n', (FILE)); \
|
||||
} while (0)
|
||||
|
||||
/* This is how to equate one symbol to another symbol. The syntax used is
|
||||
`SYM1=SYM2'. Note that this is different from the way equates are done
|
||||
with most svr4 assemblers, where the syntax is `.set SYM1,SYM2'. */
|
||||
|
||||
#define ASM_OUTPUT_DEF(FILE,LABEL1,LABEL2) \
|
||||
do { fprintf ((FILE), "\t"); \
|
||||
assemble_name (FILE, LABEL1); \
|
||||
fprintf (FILE, " = "); \
|
||||
assemble_name (FILE, LABEL2); \
|
||||
fprintf (FILE, "\n"); \
|
||||
} while (0)
|
||||
|
||||
/* For aliases of functions we use .thumb_set instead. */
|
||||
#define ASM_OUTPUT_DEF_FROM_DECLS(FILE,DECL1,DECL2) \
|
||||
do \
|
||||
{ \
|
||||
char * LABEL1 = XSTR (XEXP (DECL_RTL (decl), 0), 0); \
|
||||
char * LABEL2 = IDENTIFIER_POINTER (DECL2); \
|
||||
\
|
||||
if (TREE_CODE (DECL1) == FUNCTION_DECL) \
|
||||
{ \
|
||||
fprintf (FILE, "\t.thumb_set "); \
|
||||
assemble_name (FILE, LABEL1); \
|
||||
fprintf (FILE, ","); \
|
||||
assemble_name (FILE, LABEL2); \
|
||||
fprintf (FILE, "\n"); \
|
||||
} \
|
||||
else \
|
||||
ASM_OUTPUT_DEF (FILE, LABEL1, LABEL2); \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
/* A list of other sections which the compiler might be "in" at any
|
||||
given time. */
|
||||
#undef EXTRA_SECTIONS
|
||||
#define EXTRA_SECTIONS SUBTARGET_EXTRA_SECTIONS in_rdata, in_ctors, in_dtors
|
||||
|
||||
#define SUBTARGET_EXTRA_SECTIONS
|
||||
|
||||
/* A list of extra section function definitions. */
|
||||
|
||||
#undef EXTRA_SECTION_FUNCTIONS
|
||||
#define EXTRA_SECTION_FUNCTIONS \
|
||||
RDATA_SECTION_FUNCTION \
|
||||
CTORS_SECTION_FUNCTION \
|
||||
DTORS_SECTION_FUNCTION \
|
||||
SUBTARGET_EXTRA_SECTION_FUNCTIONS
|
||||
|
||||
#define SUBTARGET_EXTRA_SECTION_FUNCTIONS
|
||||
|
||||
#define RDATA_SECTION_FUNCTION \
|
||||
void \
|
||||
rdata_section () \
|
||||
{ \
|
||||
if (in_section != in_rdata) \
|
||||
{ \
|
||||
fprintf (asm_out_file, "%s\n", RDATA_SECTION_ASM_OP); \
|
||||
in_section = in_rdata; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define CTOR_LIST_BEGIN \
|
||||
asm (CTORS_SECTION_ASM_OP); \
|
||||
func_ptr __CTOR_LIST__[1] = { (func_ptr) (-1) }
|
||||
|
||||
#define CTOR_LIST_END \
|
||||
asm (CTORS_SECTION_ASM_OP); \
|
||||
func_ptr __CTOR_END__[1] = { (func_ptr) 0 };
|
||||
|
||||
#define DTOR_LIST_BEGIN \
|
||||
asm (DTORS_SECTION_ASM_OP); \
|
||||
func_ptr __DTOR_LIST__[1] = { (func_ptr) (-1) }
|
||||
|
||||
#define DTOR_LIST_END \
|
||||
asm (DTORS_SECTION_ASM_OP); \
|
||||
func_ptr __DTOR_END__[1] = { (func_ptr) 0 };
|
||||
|
||||
#define CTORS_SECTION_FUNCTION \
|
||||
void \
|
||||
ctors_section () \
|
||||
{ \
|
||||
if (in_section != in_ctors) \
|
||||
{ \
|
||||
fprintf (asm_out_file, "%s\n", CTORS_SECTION_ASM_OP); \
|
||||
in_section = in_ctors; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define DTORS_SECTION_FUNCTION \
|
||||
void \
|
||||
dtors_section () \
|
||||
{ \
|
||||
if (in_section != in_dtors) \
|
||||
{ \
|
||||
fprintf (asm_out_file, "%s\n", DTORS_SECTION_ASM_OP); \
|
||||
in_section = in_dtors; \
|
||||
} \
|
||||
}
|
||||
|
||||
/* Support the ctors/dtors sections for g++. */
|
||||
|
||||
#define INT_ASM_OP ".word"
|
||||
|
||||
#define INVOKE__main
|
||||
|
||||
#undef STARTFILE_SPEC
|
||||
#define STARTFILE_SPEC "crtbegin%O%s crt0%O%s"
|
||||
|
||||
#undef ENDFILE_SPEC
|
||||
#define ENDFILE_SPEC "crtend%O%s"
|
||||
|
||||
/* A C statement (sans semicolon) to output an element in the table of
|
||||
global constructors. */
|
||||
#undef ASM_OUTPUT_CONSTRUCTOR
|
||||
#define ASM_OUTPUT_CONSTRUCTOR(STREAM,NAME) \
|
||||
do { \
|
||||
ctors_section (); \
|
||||
fprintf (STREAM, "\t%s\t ", INT_ASM_OP); \
|
||||
assemble_name (STREAM, NAME); \
|
||||
fprintf (STREAM, "\n"); \
|
||||
} while (0)
|
||||
|
||||
/* A C statement (sans semicolon) to output an element in the table of
|
||||
global destructors. */
|
||||
#undef ASM_OUTPUT_DESTRUCTOR
|
||||
#define ASM_OUTPUT_DESTRUCTOR(STREAM,NAME) \
|
||||
do { \
|
||||
dtors_section (); \
|
||||
fprintf (STREAM, "\t%s\t ", INT_ASM_OP); \
|
||||
assemble_name (STREAM, NAME); \
|
||||
fprintf (STREAM, "\n"); \
|
||||
} while (0)
|
||||
|
||||
/* The ARM development system has atexit and doesn't have _exit,
|
||||
so define this for now. */
|
||||
#define HAVE_ATEXIT
|
||||
|
||||
/* The ARM development system defines __main. */
|
||||
#define NAME__MAIN "__gccmain"
|
||||
#define SYMBOL__MAIN __gccmain
|
||||
|
||||
#define MAKE_DECL_ONE_ONLY(DECL) (DECL_WEAK (DECL) = 1)
|
||||
#define UNIQUE_SECTION_P(DECL) (DECL_ONE_ONLY (DECL))
|
||||
#define UNIQUE_SECTION(DECL,RELOC) \
|
||||
do { \
|
||||
int len; \
|
||||
char * name, * string, * prefix; \
|
||||
\
|
||||
name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (DECL)); \
|
||||
\
|
||||
if (! DECL_ONE_ONLY (DECL)) \
|
||||
{ \
|
||||
prefix = "."; \
|
||||
if (TREE_CODE (DECL) == FUNCTION_DECL) \
|
||||
prefix = ".text."; \
|
||||
else if (DECL_READONLY_SECTION (DECL, RELOC)) \
|
||||
prefix = ".rodata."; \
|
||||
else \
|
||||
prefix = ".data."; \
|
||||
} \
|
||||
else if (TREE_CODE (DECL) == FUNCTION_DECL) \
|
||||
prefix = ".gnu.linkonce.t."; \
|
||||
else if (DECL_READONLY_SECTION (DECL, RELOC)) \
|
||||
prefix = ".gnu.linkonce.r."; \
|
||||
else \
|
||||
prefix = ".gnu.linkonce.d."; \
|
||||
\
|
||||
len = strlen (name) + strlen (prefix); \
|
||||
string = alloca (len + 1); \
|
||||
sprintf (string, "%s%s", prefix, name); \
|
||||
\
|
||||
DECL_SECTION_NAME (DECL) = build_string (len, string); \
|
||||
} while (0)
|
||||
|
||||
/* This is how we tell the assembler that a symbol is weak. */
|
||||
#ifndef ASM_WEAKEN_LABEL
|
||||
#define ASM_WEAKEN_LABEL(FILE, NAME) \
|
||||
do \
|
||||
{ \
|
||||
fputs ("\t.weak\t", FILE); \
|
||||
assemble_name (FILE, NAME); \
|
||||
fputc ('\n', FILE); \
|
||||
} \
|
||||
while (0)
|
||||
#endif
|
||||
|
||||
#ifndef TYPE_ASM_OP
|
||||
|
||||
/* These macros generate the special .type and .size directives which
|
||||
are used to set the corresponding fields of the linker symbol table
|
||||
entries in an ELF object file under SVR4. These macros also output
|
||||
the starting labels for the relevant functions/objects. */
|
||||
#define TYPE_ASM_OP ".type"
|
||||
#define SIZE_ASM_OP ".size"
|
||||
|
||||
/* The following macro defines the format used to output the second
|
||||
operand of the .type assembler directive. Different svr4 assemblers
|
||||
expect various different forms for this operand. The one given here
|
||||
is just a default. You may need to override it in your machine-
|
||||
specific tm.h file (depending upon the particulars of your assembler). */
|
||||
#define TYPE_OPERAND_FMT "%s"
|
||||
|
||||
/* Write the extra assembler code needed to declare a function's result.
|
||||
Most svr4 assemblers don't require any special declaration of the
|
||||
result value, but there are exceptions. */
|
||||
#ifndef ASM_DECLARE_RESULT
|
||||
#define ASM_DECLARE_RESULT(FILE, RESULT)
|
||||
#endif
|
||||
|
||||
/* Write the extra assembler code needed to declare a function properly.
|
||||
Some svr4 assemblers need to also have something extra said about the
|
||||
function's return value. We allow for that here. */
|
||||
#undef ASM_DECLARE_FUNCTION_NAME
|
||||
#define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL) \
|
||||
do \
|
||||
{ \
|
||||
fprintf (FILE, "\t%s\t ", TYPE_ASM_OP); \
|
||||
assemble_name (FILE, NAME); \
|
||||
putc (',', FILE); \
|
||||
fprintf (FILE, TYPE_OPERAND_FMT, "function"); \
|
||||
putc ('\n', FILE); \
|
||||
ASM_DECLARE_RESULT (FILE, DECL_RESULT (DECL)); \
|
||||
if (! is_called_in_ARM_mode (decl)) \
|
||||
fprintf (FILE, "\t.thumb_func\n") ; \
|
||||
else \
|
||||
fprintf (FILE, "\t.code\t32\n") ; \
|
||||
ASM_OUTPUT_LABEL(FILE, NAME); \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
/* Write the extra assembler code needed to declare an object properly. */
|
||||
#define ASM_DECLARE_OBJECT_NAME(FILE, NAME, DECL) \
|
||||
do \
|
||||
{ \
|
||||
fprintf (FILE, "\t%s\t ", TYPE_ASM_OP); \
|
||||
assemble_name (FILE, NAME); \
|
||||
putc (',', FILE); \
|
||||
fprintf (FILE, TYPE_OPERAND_FMT, "object"); \
|
||||
putc ('\n', FILE); \
|
||||
size_directive_output = 0; \
|
||||
if (!flag_inhibit_size_directive && DECL_SIZE (DECL)) \
|
||||
{ \
|
||||
size_directive_output = 1; \
|
||||
fprintf (FILE, "\t%s\t ", SIZE_ASM_OP); \
|
||||
assemble_name (FILE, NAME); \
|
||||
putc (',', FILE); \
|
||||
fprintf (FILE, HOST_WIDE_INT_PRINT_DEC, \
|
||||
int_size_in_bytes (TREE_TYPE (DECL))); \
|
||||
fputc ('\n', FILE); \
|
||||
} \
|
||||
ASM_OUTPUT_LABEL(FILE, NAME); \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
/* Output the size directive for a decl in rest_of_decl_compilation
|
||||
in the case where we did not do so before the initializer.
|
||||
Once we find the error_mark_node, we know that the value of
|
||||
size_directive_output was set
|
||||
by ASM_DECLARE_OBJECT_NAME when it was run for the same decl. */
|
||||
#define ASM_FINISH_DECLARE_OBJECT(FILE, DECL, TOP_LEVEL, AT_END) \
|
||||
do \
|
||||
{ \
|
||||
char * name = XSTR (XEXP (DECL_RTL (DECL), 0), 0); \
|
||||
if (!flag_inhibit_size_directive && DECL_SIZE (DECL) \
|
||||
&& ! AT_END && TOP_LEVEL \
|
||||
&& DECL_INITIAL (DECL) == error_mark_node \
|
||||
&& !size_directive_output) \
|
||||
{ \
|
||||
size_directive_output = 1; \
|
||||
fprintf (FILE, "\t%s\t ", SIZE_ASM_OP); \
|
||||
assemble_name (FILE, name); \
|
||||
putc (',', FILE); \
|
||||
fprintf (FILE, HOST_WIDE_INT_PRINT_DEC, \
|
||||
int_size_in_bytes (TREE_TYPE (DECL))); \
|
||||
fputc ('\n', FILE); \
|
||||
} \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
/* This is how to declare the size of a function. */
|
||||
#define ASM_DECLARE_FUNCTION_SIZE(FILE, FNAME, DECL) \
|
||||
do \
|
||||
{ \
|
||||
if (!flag_inhibit_size_directive) \
|
||||
{ \
|
||||
char label[256]; \
|
||||
static int labelno; \
|
||||
labelno ++; \
|
||||
ASM_GENERATE_INTERNAL_LABEL (label, "Lfe", labelno); \
|
||||
ASM_OUTPUT_INTERNAL_LABEL (FILE, "Lfe", labelno); \
|
||||
fprintf (FILE, "\t%s\t ", SIZE_ASM_OP); \
|
||||
assemble_name (FILE, (FNAME)); \
|
||||
fprintf (FILE, ","); \
|
||||
assemble_name (FILE, label); \
|
||||
fprintf (FILE, "-"); \
|
||||
assemble_name (FILE, (FNAME)); \
|
||||
putc ('\n', FILE); \
|
||||
} \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
#endif /* TYPE_ASM_OP */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,168 +0,0 @@
|
||||
***************
|
||||
*** 2103,2105 ****
|
||||
}
|
||||
#endif /* THUMB_PE */
|
||||
/* END CYGNUS LOCAL nickc/thumb-pe */
|
||||
--- 2103,2264 ----
|
||||
}
|
||||
#endif /* THUMB_PE */
|
||||
/* END CYGNUS LOCAL nickc/thumb-pe */
|
||||
+
|
||||
+ /* Return nonzero if ATTR is a valid attribute for TYPE.
|
||||
+ ATTRIBUTES are any existing attributes and ARGS are the arguments
|
||||
+ supplied with ATTR.
|
||||
+
|
||||
+ Supported attributes:
|
||||
+
|
||||
+ short_call: assume the offset from the caller to the callee is small.
|
||||
+
|
||||
+ long_call: don't assume the offset is small. */
|
||||
+
|
||||
+ int
|
||||
+ arm_valid_machine_type_attribute (type, attributes, attr, args)
|
||||
+ tree type;
|
||||
+ tree attributes;
|
||||
+ tree attr;
|
||||
+ tree args;
|
||||
+ {
|
||||
+ if (args != NULL_TREE)
|
||||
+ return 0;
|
||||
+
|
||||
+ if (is_attribute_p ("long_call", attr))
|
||||
+ return 1;
|
||||
+
|
||||
+ if (is_attribute_p ("short_call", attr))
|
||||
+ return 1;
|
||||
+
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ /* Encode long_call or short_call attribute by prefixing
|
||||
+ symbol name in DECL with a special character FLAG. */
|
||||
+
|
||||
+ void
|
||||
+ arm_encode_call_attribute (decl, flag)
|
||||
+ tree decl;
|
||||
+ int flag;
|
||||
+ {
|
||||
+ const char * str = XSTR (XEXP (DECL_RTL (decl), 0), 0);
|
||||
+ int len = strlen (str);
|
||||
+ char * newstr;
|
||||
+
|
||||
+ /* Do not allow weak functions to be treated as short call. */
|
||||
+ if (DECL_WEAK (decl) && flag == SHORT_CALL_FLAG_CHAR)
|
||||
+ return;
|
||||
+
|
||||
+ if (ENCODED_SHORT_CALL_ATTR_P (str)
|
||||
+ || ENCODED_LONG_CALL_ATTR_P (str))
|
||||
+ return;
|
||||
+
|
||||
+ newstr = malloc (len + 2);
|
||||
+ newstr[0] = flag;
|
||||
+ strcpy (newstr + 1, str);
|
||||
+
|
||||
+ XSTR (XEXP (DECL_RTL (decl), 0), 0) = newstr;
|
||||
+ }
|
||||
+
|
||||
+ /* Return the length of a function name prefix
|
||||
+ that starts with the character 'c'. */
|
||||
+
|
||||
+ static int
|
||||
+ arm_get_strip_length (char c)
|
||||
+ {
|
||||
+ switch (c)
|
||||
+ {
|
||||
+ ARM_NAME_ENCODING_LENGTHS
|
||||
+ default: return 0;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* Return a pointer to a function's name with any
|
||||
+ and all prefix encodings stripped from it. */
|
||||
+
|
||||
+ char *
|
||||
+ arm_strip_name_encoding (char * name)
|
||||
+ {
|
||||
+ int skip;
|
||||
+
|
||||
+ while ((skip = arm_get_strip_length (* name)))
|
||||
+ name += skip;
|
||||
+
|
||||
+ return name;
|
||||
+ }
|
||||
+
|
||||
+ /* Return 1 if the operand is a SYMBOL_REF for a function known to be
|
||||
+ defined within the current compilation unit. If this caanot be
|
||||
+ determined, then 0 is returned. */
|
||||
+
|
||||
+ static int
|
||||
+ current_file_function_operand (sym_ref)
|
||||
+ rtx sym_ref;
|
||||
+ {
|
||||
+ /* This is a bit of a fib. A function will have a short call flag
|
||||
+ applied to its name if it has the short call attribute, or it has
|
||||
+ already been defined within the current compilation unit. */
|
||||
+ if (ENCODED_SHORT_CALL_ATTR_P (XSTR (sym_ref, 0)))
|
||||
+ return 1;
|
||||
+
|
||||
+ /* The current function is always defined within the current compilation
|
||||
+ unit. if it s a weak definition however, then this may not be the real
|
||||
+ definition of the function, and so we have to say no. */
|
||||
+ if (sym_ref == XEXP (DECL_RTL (current_function_decl), 0)
|
||||
+ && !DECL_WEAK (current_function_decl))
|
||||
+ return 1;
|
||||
+
|
||||
+ /* We cannot make the determination - default to returning 0. */
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ /* Return non-zero if a 32 bit "long_call" should be generated for
|
||||
+ this call. We generate a long_call if the function:
|
||||
+
|
||||
+ a. has an __attribute__((long call))
|
||||
+ or b. the -mlong-calls command line switch has been specified
|
||||
+
|
||||
+ However we do not generate a long call if the function:
|
||||
+
|
||||
+ c. has an __attribute__ ((short_call))
|
||||
+ or d. has an __attribute__ ((section))
|
||||
+ or e. is defined within the current compilation unit.
|
||||
+
|
||||
+ This function will be called by C fragments contained in the machine
|
||||
+ description file. CALL_REF and CALL_COOKIE correspond to the matched
|
||||
+ rtl operands. CALL_SYMBOL is used to distinguish between
|
||||
+ two different callers of the function. It is set to 1 in the
|
||||
+ "call_symbol" and "call_symbol_value" patterns and to 0 in the "call"
|
||||
+ and "call_value" patterns. This is because of the difference in the
|
||||
+ SYM_REFs passed by these patterns. */
|
||||
+
|
||||
+ int
|
||||
+ arm_is_longcall_p (sym_ref, call_cookie, call_symbol)
|
||||
+ rtx sym_ref;
|
||||
+ int call_cookie;
|
||||
+ int call_symbol;
|
||||
+ {
|
||||
+ if (!call_symbol)
|
||||
+ {
|
||||
+ if (GET_CODE (sym_ref) != MEM)
|
||||
+ return 0;
|
||||
+
|
||||
+ sym_ref = XEXP (sym_ref, 0);
|
||||
+ }
|
||||
+
|
||||
+ if (GET_CODE (sym_ref) != SYMBOL_REF)
|
||||
+ return 0;
|
||||
+
|
||||
+ if (call_cookie & CALL_SHORT)
|
||||
+ return 0;
|
||||
+
|
||||
+ if (TARGET_LONG_CALLS && flag_function_sections)
|
||||
+ return 1;
|
||||
+
|
||||
+ if (current_file_function_operand (sym_ref))
|
||||
+ return 0;
|
||||
+
|
||||
+ return (call_cookie & CALL_LONG)
|
||||
+ || ENCODED_LONG_CALL_ATTR_P (XSTR (sym_ref, 0))
|
||||
+ || TARGET_LONG_CALLS;
|
||||
+ }
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,168 +0,0 @@
|
||||
***************
|
||||
*** 1002,1019 ****
|
||||
;; Call insns
|
||||
|
||||
(define_expand "call"
|
||||
- [(call (match_operand:SI 0 "memory_operand" "")
|
||||
- (match_operand 1 "" ""))]
|
||||
""
|
||||
"
|
||||
{
|
||||
- if (TARGET_LONG_CALLS && GET_CODE (XEXP (operands[0], 0)) != REG)
|
||||
XEXP (operands[0], 0) = force_reg (Pmode, XEXP (operands[0], 0));
|
||||
}")
|
||||
|
||||
(define_insn "*call_indirect"
|
||||
- [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
|
||||
- (match_operand 1 "" ""))]
|
||||
"! TARGET_CALLER_INTERWORKING"
|
||||
"bl\\t%__call_via_%0"
|
||||
[(set_attr "length" "4")])
|
||||
--- 1002,1024 ----
|
||||
;; Call insns
|
||||
|
||||
(define_expand "call"
|
||||
+ [(parallel
|
||||
+ [(call (match_operand:SI 0 "memory_operand" "")
|
||||
+ (match_operand 1 "" ""))
|
||||
+ (use (match_operand 2 "" ""))])]
|
||||
""
|
||||
"
|
||||
{
|
||||
+ if (GET_CODE (XEXP (operands[0], 0)) != REG
|
||||
+ && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
|
||||
XEXP (operands[0], 0) = force_reg (Pmode, XEXP (operands[0], 0));
|
||||
}")
|
||||
|
||||
(define_insn "*call_indirect"
|
||||
+ [(parallel
|
||||
+ [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
|
||||
+ (match_operand 1 "" ""))
|
||||
+ (use (match_operand 2 "" ""))])]
|
||||
"! TARGET_CALLER_INTERWORKING"
|
||||
"bl\\t%__call_via_%0"
|
||||
[(set_attr "length" "4")])
|
||||
***************
|
||||
*** 1023,1075 ****
|
||||
;; would switch back into ARM mode...
|
||||
|
||||
(define_insn "*call_indirect_interwork"
|
||||
- [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
|
||||
- (match_operand 1 "" ""))]
|
||||
"TARGET_CALLER_INTERWORKING"
|
||||
"bl\\t%__interwork_call_via_%0"
|
||||
[(set_attr "length" "4")])
|
||||
|
||||
(define_expand "call_value"
|
||||
- [(set (match_operand 0 "" "")
|
||||
- (call (match_operand 1 "memory_operand" "")
|
||||
- (match_operand 2 "" "")))]
|
||||
""
|
||||
"
|
||||
{
|
||||
- if (TARGET_LONG_CALLS && GET_CODE (XEXP (operands[1], 0)) != REG)
|
||||
XEXP (operands[1], 0) = force_reg (Pmode, XEXP (operands[1], 0));
|
||||
}")
|
||||
|
||||
(define_insn "*call_value_indirect"
|
||||
- [(set (match_operand 0 "" "=l")
|
||||
- (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
|
||||
- (match_operand 2 "" "")))]
|
||||
"! TARGET_CALLER_INTERWORKING"
|
||||
"bl\\t%__call_via_%1"
|
||||
[(set_attr "length" "4")])
|
||||
;; See comment for call_indirect pattern
|
||||
|
||||
(define_insn "*call_value_indirect_interwork"
|
||||
- [(set (match_operand 0 "" "=l")
|
||||
- (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
|
||||
- (match_operand 2 "" "")))]
|
||||
"TARGET_CALLER_INTERWORKING"
|
||||
"bl\\t%__interwork_call_via_%1"
|
||||
[(set_attr "length" "4")])
|
||||
|
||||
|
||||
(define_insn "*call_insn"
|
||||
- [(call (mem:SI (match_operand:SI 0 "" "i"))
|
||||
- (match_operand:SI 1 "" ""))]
|
||||
- "! TARGET_LONG_CALLS && GET_CODE (operands[0]) == SYMBOL_REF"
|
||||
"bl\\t%a0"
|
||||
[(set_attr "length" "4")])
|
||||
|
||||
(define_insn "*call_value_insn"
|
||||
- [(set (match_operand 0 "register_operand" "=l")
|
||||
(call (mem:SI (match_operand 1 "" "i"))
|
||||
- (match_operand 2 "" "")))]
|
||||
- "! TARGET_LONG_CALLS && GET_CODE (operands[1]) == SYMBOL_REF"
|
||||
"bl\\t%a1"
|
||||
[(set_attr "length" "4")])
|
||||
|
||||
--- 1028,1095 ----
|
||||
;; would switch back into ARM mode...
|
||||
|
||||
(define_insn "*call_indirect_interwork"
|
||||
+ [(parallel
|
||||
+ [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
|
||||
+ (match_operand 1 "" ""))
|
||||
+ (use (match_operand 2 "" ""))])]
|
||||
"TARGET_CALLER_INTERWORKING"
|
||||
"bl\\t%__interwork_call_via_%0"
|
||||
[(set_attr "length" "4")])
|
||||
|
||||
(define_expand "call_value"
|
||||
+ [(parallel
|
||||
+ [(set (match_operand 0 "" "")
|
||||
+ (call (match_operand 1 "memory_operand" "")
|
||||
+ (match_operand 2 "" "")))
|
||||
+ (use (match_operand 3 "" ""))])]
|
||||
""
|
||||
"
|
||||
{
|
||||
+ if (GET_CODE (XEXP (operands[1], 0)) != REG
|
||||
+ && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
|
||||
XEXP (operands[1], 0) = force_reg (Pmode, XEXP (operands[1], 0));
|
||||
}")
|
||||
|
||||
(define_insn "*call_value_indirect"
|
||||
+ [(parallel
|
||||
+ [(set (match_operand 0 "" "=l")
|
||||
+ (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
|
||||
+ (match_operand 2 "" "")))
|
||||
+ (use (match_operand 3 "" ""))])]
|
||||
"! TARGET_CALLER_INTERWORKING"
|
||||
"bl\\t%__call_via_%1"
|
||||
[(set_attr "length" "4")])
|
||||
;; See comment for call_indirect pattern
|
||||
|
||||
(define_insn "*call_value_indirect_interwork"
|
||||
+ [(parallel
|
||||
+ [(set (match_operand 0 "" "=l")
|
||||
+ (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
|
||||
+ (match_operand 2 "" "")))
|
||||
+ (use (match_operand 3 "" ""))])]
|
||||
"TARGET_CALLER_INTERWORKING"
|
||||
"bl\\t%__interwork_call_via_%1"
|
||||
[(set_attr "length" "4")])
|
||||
|
||||
|
||||
(define_insn "*call_insn"
|
||||
+ [(parallel
|
||||
+ [(call (mem:SI (match_operand:SI 0 "" "i"))
|
||||
+ (match_operand:SI 1 "" ""))
|
||||
+ (use (match_operand 2 "" ""))])]
|
||||
+ "GET_CODE (operands[0]) == SYMBOL_REF
|
||||
+ && ! arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
|
||||
"bl\\t%a0"
|
||||
[(set_attr "length" "4")])
|
||||
|
||||
(define_insn "*call_value_insn"
|
||||
+ [(parallel
|
||||
+ [(set (match_operand 0 "register_operand" "=l")
|
||||
(call (mem:SI (match_operand 1 "" "i"))
|
||||
+ (match_operand 2 "" "")))
|
||||
+ (use (match_operand 3 "" ""))])]
|
||||
+ "GET_CODE(operands[1]) == SYMBOL_REF
|
||||
+ && ! arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
|
||||
"bl\\t%a1"
|
||||
[(set_attr "length" "4")])
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user