summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorYamaArashi <shadow962@live.com>2016-02-13 16:22:29 -0800
committerYamaArashi <shadow962@live.com>2016-02-13 16:22:29 -0800
commit3878c0ffc606b95917af8a9f3fb406a1718b6c2e (patch)
tree89b919f26b8670b3629914df486859370b39a8ba /gcc
parent47d5ab74c312567d17cd5df362d73d36f53eb0c2 (diff)
remove alternate versions of thumb files
Diffstat (limited to 'gcc')
-rwxr-xr-xgcc/config/arm/lib1thumb.asm745
-rwxr-xr-xgcc/config/arm/lib1thumb_981111.asm747
-rwxr-xr-xgcc/config/arm/telf_020422.h443
-rwxr-xr-xgcc/config/arm/thumb.c.orig2132
-rwxr-xr-xgcc/config/arm/thumb.c.rej168
-rwxr-xr-xgcc/config/arm/thumb.h.orig1195
-rwxr-xr-xgcc/config/arm/thumb.md.orig1174
-rwxr-xr-xgcc/config/arm/thumb.md.rej168
-rwxr-xr-xgcc/config/arm/thumb_000513.h1187
-rwxr-xr-xgcc/config/arm/thumb_010110a.c2124
-rwxr-xr-xgcc/config/arm/thumb_010110a.md1166
-rwxr-xr-xgcc/config/arm/thumb_010309a.c2132
-rwxr-xr-xgcc/config/arm/thumb_020422.c2291
-rwxr-xr-xgcc/config/arm/thumb_020422.h1295
-rwxr-xr-xgcc/config/arm/thumb_020422.md1194
-rwxr-xr-xgcc/config/arm/thumb_020428.h1297
-rwxr-xr-xgcc/config/arm/thumb_020428.md1194
-rwxr-xr-xgcc/config/arm/thumb_981111.md1166
18 files changed, 460 insertions, 21358 deletions
diff --git a/gcc/config/arm/lib1thumb.asm b/gcc/config/arm/lib1thumb.asm
index 1789356..dcabcf4 100755
--- a/gcc/config/arm/lib1thumb.asm
+++ b/gcc/config/arm/lib1thumb.asm
@@ -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__
+work .req r4 @ XXXX is this safe ?
-#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
+#ifdef L_udivsi3
-/* Function end macros. Variants for interworking. */
+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
-# 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
+ @ 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
-.macro FUNC_END name
-.Ldiv0:
- THUMB_LDIV0
- SIZE (__\name)
-.endm
+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
-.macro THUMB_FUNC_START name
- .globl SYM (\name)
- TYPE (\name)
- .thumb_func
-SYM (\name):
-.endm
+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
-/* Function start macros. */
+Ldiv0:
+ push { lr }
+ bl SYM (__div0) __PLT__
+ mov r0, #0 @ about as wrong as it could be
+ pop { pc }
-#define THUMB_FUNC .thumb_func
-#define THUMB_CODE .force_thumb
+ SIZE (__udivsi3)
-.macro FUNC_START name
- .text
- .globl SYM (__\name)
- TYPE (__\name)
- .align 0
- THUMB_CODE
- THUMB_FUNC
-SYM (__\name):
-.endm
-
-/* Register aliases. */
+#endif /* L_udivsi3 */
+
+#ifdef L_umodsi3
-work .req r4 @ XXXX is this safe ?
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
+
+ .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
-/* ------------------------------------------------------------------------ */
-/* Bodies of the divsion and modulo routines. */
-/* ------------------------------------------------------------------------ */
-.macro THUMB_DIV_MOD_BODY modulo
- @ Load the constant 0x10000000 into our work register.
+Over1:
+ @ Load the constant 0x10000000 into our work register
+ push { work }
mov work, #1
lsl work, #28
-.Loop1:
+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
+ bcs Lbignum
cmp divisor, dividend
- bhs .Lbignum
+ bcs Lbignum
lsl divisor, #4
- lsl curbit, #4
- b .Loop1
-.Lbignum:
+ lsl curbit, #4
+ b Loop1
+
+Lbignum:
@ Set work to 0x80000000
lsl work, #3
-.Loop2:
+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
+ bcs Loop3
cmp divisor, dividend
- bhs .Loop3
+ bcs 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.
+ 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
- blo .Lover1
+ bcc Over2
sub dividend, dividend, divisor
-.Lover1:
+Over2:
lsr work, divisor, #1
cmp dividend, work
- blo .Lover2
+ bcc Over3
sub dividend, dividend, work
mov ip, curbit
mov work, #1
ror curbit, work
orr overdone, curbit
mov curbit, ip
-.Lover2:
+Over3:
lsr work, divisor, #2
cmp dividend, work
- blo .Lover3
+ bcc Over4
sub dividend, dividend, work
mov ip, curbit
mov work, #2
ror curbit, work
orr overdone, curbit
mov curbit, ip
-.Lover3:
+Over4:
lsr work, divisor, #3
cmp dividend, work
- blo .Lover4
+ bcc Over5
sub dividend, dividend, work
mov ip, curbit
mov work, #3
ror curbit, work
orr overdone, curbit
mov curbit, ip
-.Lover4:
+Over5:
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
+ beq Over6
+ lsr curbit, #4 @ No, any more bits to do?
+ beq Over6
lsr divisor, #4
- b .Loop3
-.Lover5:
- .if \modulo
+ 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
+ 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
-
+ bne Over7
+ pop { work }
+ RET @ No fixups needed
+Over7:
mov curbit, ip
mov work, #3
ror curbit, work
tst overdone, curbit
- beq .Lover6
+ beq Over8
lsr work, divisor, #3
- add dividend, work
-.Lover6:
+ add dividend, dividend, work
+Over8:
mov curbit, ip
mov work, #2
ror curbit, work
tst overdone, curbit
- beq .Lover7
+ beq Over9
lsr work, divisor, #2
- add dividend, work
-.Lover7:
+ add dividend, dividend, work
+Over9:
mov curbit, ip
mov work, #1
ror curbit, work
tst overdone, curbit
- beq .Lgot_result
+ beq Over10
lsr work, divisor, #1
- add dividend, work
- .endif
-.Lgot_result:
-.endm
-/* ------------------------------------------------------------------------ */
-/* Start of the Real Functions */
-/* ------------------------------------------------------------------------ */
-#ifdef L_udivsi3
-
- FUNC_START udivsi3
-
- cmp divisor, #0
- beq .Ldiv0
- mov curbit, #1
- mov result, #0
-
- push { work }
- cmp dividend, divisor
- blo .Lgot_result
-
- THUMB_DIV_MOD_BODY 0
-
- mov r0, result
+ add dividend, dividend, work
+Over10:
pop { work }
- RET
-
- FUNC_END udivsi3
-
-#endif /* L_udivsi3 */
-/* ------------------------------------------------------------------------ */
-#ifdef L_umodsi3
-
- FUNC_START umodsi3
-
- cmp divisor, #0
- beq .Ldiv0
- mov curbit, #1
- cmp dividend, divisor
- bhs ..Lover10
RET
-..Lover10:
- push { work }
+Ldiv0:
+ push { lr }
+ bl SYM (__div0) __PLT__
+ mov r0, #0 @ about as wrong as it could be
+ pop { pc }
- THUMB_DIV_MOD_BODY 1
+ SIZE (__umodsi3)
- pop { work }
- RET
-
- FUNC_END umodsi3
-
#endif /* L_umodsi3 */
-/* ------------------------------------------------------------------------ */
-#ifdef L_divsi3
- FUNC_START divsi3
+#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
+ 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
+
+ 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 0
+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
+#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 .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
+#ifdef L_dvmd_tls
- 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... */
- .code 16
-
- THUMB_FUNC_START _interwork_call_via_lr
+ /* 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
@@ -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 */
diff --git a/gcc/config/arm/lib1thumb_981111.asm b/gcc/config/arm/lib1thumb_981111.asm
deleted file mode 100755
index dcabcf4..0000000
--- a/gcc/config/arm/lib1thumb_981111.asm
+++ /dev/null
@@ -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 */
diff --git a/gcc/config/arm/telf_020422.h b/gcc/config/arm/telf_020422.h
deleted file mode 100755
index 6e59404..0000000
--- a/gcc/config/arm/telf_020422.h
+++ /dev/null
@@ -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 */
diff --git a/gcc/config/arm/thumb.c.orig b/gcc/config/arm/thumb.c.orig
deleted file mode 100755
index 778cda9..0000000
--- a/gcc/config/arm/thumb.c.orig
+++ /dev/null
@@ -1,2132 +0,0 @@
-/* Output routines for GCC for ARM/Thumb
- Copyright (C) 1996 Cygnus Software Technologies Ltd
- The basis of this contribution was generated by
- Richard Earnshaw, Advanced RISC Machines Ltd
-
-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. */
-
-#include <stdio.h>
-#include <string.h>
-#include "config.h"
-#include "rtl.h"
-#include "hard-reg-set.h"
-#include "regs.h"
-#include "output.h"
-#include "insn-flags.h"
-#include "insn-attr.h"
-#include "flags.h"
-#include "tree.h"
-#include "expr.h"
-
-
-int current_function_anonymous_args = 0;
-static int current_function_has_far_jump = 0;
-
-/* Used to parse -mstructure_size_boundary command line option. */
-char * structure_size_string = NULL;
-int arm_structure_size_boundary = 32; /* Used to be 8 */
-
-
-/* Predicates */
-int
-reload_memory_operand (op, mode)
- rtx op;
- enum machine_mode mode;
-{
- int regno = true_regnum (op);
-
- return (! CONSTANT_P (op)
- && (regno == -1
- || (GET_CODE (op) == REG
- && REGNO (op) >= FIRST_PSEUDO_REGISTER)));
-}
-
-/* Return nonzero if op is suitable for the RHS of a cmp instruction. */
-int
-thumb_cmp_operand (op, mode)
- rtx op;
- enum machine_mode mode;
-{
- return ((GET_CODE (op) == CONST_INT
- && (unsigned HOST_WIDE_INT) (INTVAL (op)) < 256)
- || register_operand (op, mode));
-}
-
-int
-thumb_shiftable_const (val)
- HOST_WIDE_INT val;
-{
- unsigned HOST_WIDE_INT x = val;
- unsigned HOST_WIDE_INT mask = 0xff;
- int i;
-
- for (i = 0; i < 25; i++)
- if ((val & (mask << i)) == val)
- return 1;
-
- return 0;
-}
-
-int
-thumb_trivial_epilogue ()
-{
- int regno;
-
- /* ??? If this function ever returns 1, we get a function without any
- epilogue at all. It appears that the intent was to cause a "return"
- insn to be emitted, but that does not happen. */
- return 0;
-
-#if 0
- if (get_frame_size ()
- || current_function_outgoing_args_size
- || current_function_pretend_args_size)
- return 0;
-
- for (regno = 8; regno < 13; regno++)
- if (regs_ever_live[regno] && ! call_used_regs[regno])
- return 0;
-
- return 1;
-#endif
-}
-
-
-/* Routines for handling the constant pool */
-/* This is unashamedly hacked from the version in sh.c, since the problem is
- extremely similar. */
-
-/* Thumb instructions cannot load a large constant into a register,
- constants have to come from a pc relative load. The reference of a pc
- relative load instruction must be less than 1k infront of the instruction.
- This means that we often have to dump a constant inside a function, and
- generate code to branch around it.
-
- It is important to minimize this, since the branches will slow things
- down and make things bigger.
-
- Worst case code looks like:
-
- ldr rn, L1
- b L2
- align
- L1: .long value
- L2:
- ..
-
- ldr rn, L3
- b L4
- align
- L3: .long value
- L4:
- ..
-
- We fix this by performing a scan before scheduling, which notices which
- instructions need to have their operands fetched from the constant table
- and builds the table.
-
-
- The algorithm is:
-
- scan, find an instruction which needs a pcrel move. Look forward, find the
- last barrier which is within MAX_COUNT bytes of the requirement.
- If there isn't one, make one. Process all the instructions between
- the find and the barrier.
-
- In the above example, we can tell that L3 is within 1k of L1, so
- the first move can be shrunk from the 2 insn+constant sequence into
- just 1 insn, and the constant moved to L3 to make:
-
- ldr rn, L1
- ..
- ldr rn, L3
- b L4
- align
- L1: .long value
- L3: .long value
- L4:
-
- Then the second move becomes the target for the shortening process.
-
- */
-
-typedef struct
-{
- rtx value; /* Value in table */
- HOST_WIDE_INT next_offset;
- enum machine_mode mode; /* Mode of value */
-} pool_node;
-
-/* The maximum number of constants that can fit into one pool, since
- the pc relative range is 0...1020 bytes and constants are at least 4
- bytes long */
-
-#define MAX_POOL_SIZE (1020/4)
-static pool_node pool_vector[MAX_POOL_SIZE];
-static int pool_size;
-static rtx pool_vector_label;
-
-/* Add a constant to the pool and return its label. */
-
-static HOST_WIDE_INT
-add_constant (x, mode)
- rtx x;
- enum machine_mode mode;
-{
- int i;
- rtx lab;
- HOST_WIDE_INT offset;
-
- if (mode == SImode && GET_CODE (x) == MEM && CONSTANT_P (XEXP (x, 0))
- && CONSTANT_POOL_ADDRESS_P (XEXP (x, 0)))
- x = get_pool_constant (XEXP (x, 0));
-
- /* First see if we've already got it */
-
- for (i = 0; i < pool_size; i++)
- {
- if (x->code == pool_vector[i].value->code
- && mode == pool_vector[i].mode)
- {
- if (x->code == CODE_LABEL)
- {
- if (XINT (x, 3) != XINT (pool_vector[i].value, 3))
- continue;
- }
- if (rtx_equal_p (x, pool_vector[i].value))
- return pool_vector[i].next_offset - GET_MODE_SIZE (mode);
- }
- }
-
- /* Need a new one */
-
- pool_vector[pool_size].next_offset = GET_MODE_SIZE (mode);
- offset = 0;
- if (pool_size == 0)
- pool_vector_label = gen_label_rtx ();
- else
- pool_vector[pool_size].next_offset
- += (offset = pool_vector[pool_size - 1].next_offset);
-
- pool_vector[pool_size].value = x;
- pool_vector[pool_size].mode = mode;
- pool_size++;
- return offset;
-}
-
-/* Output the literal table */
-
-static void
-dump_table (scan)
- rtx scan;
-{
- int i;
-
- scan = emit_label_after (gen_label_rtx (), scan);
- scan = emit_insn_after (gen_align_4 (), scan);
- scan = emit_label_after (pool_vector_label, scan);
-
- for (i = 0; i < pool_size; i++)
- {
- pool_node *p = pool_vector + i;
-
- switch (GET_MODE_SIZE (p->mode))
- {
- case 4:
- scan = emit_insn_after (gen_consttable_4 (p->value), scan);
- break;
-
- case 8:
- scan = emit_insn_after (gen_consttable_8 (p->value), scan);
- break;
-
- default:
- abort ();
- break;
- }
- }
-
- scan = emit_insn_after (gen_consttable_end (), scan);
- scan = emit_barrier_after (scan);
- pool_size = 0;
-}
-
-/* Non zero if the src operand needs to be fixed up */
-static
-int
-fixit (src, mode)
- rtx src;
- enum machine_mode mode;
-{
- return ((CONSTANT_P (src)
- && (GET_CODE (src) != CONST_INT
- || ! (CONST_OK_FOR_LETTER_P (INTVAL (src), 'I')
- || CONST_OK_FOR_LETTER_P (INTVAL (src), 'J')
- || (mode != DImode
- && CONST_OK_FOR_LETTER_P (INTVAL (src), 'K')))))
- || (mode == SImode && GET_CODE (src) == MEM
- && GET_CODE (XEXP (src, 0)) == SYMBOL_REF
- && CONSTANT_POOL_ADDRESS_P (XEXP (src, 0))));
-}
-
-/* Find the last barrier less than MAX_COUNT bytes from FROM, or create one. */
-
-#define MAX_COUNT_SI 1000
-
-static rtx
-find_barrier (from)
- rtx from;
-{
- int count = 0;
- rtx found_barrier = 0;
- rtx label;
-
- while (from && count < MAX_COUNT_SI)
- {
- if (GET_CODE (from) == BARRIER)
- return from;
-
- /* Count the length of this insn */
- if (GET_CODE (from) == INSN
- && GET_CODE (PATTERN (from)) == SET
- && CONSTANT_P (SET_SRC (PATTERN (from)))
- && CONSTANT_POOL_ADDRESS_P (SET_SRC (PATTERN (from))))
- {
- rtx src = SET_SRC (PATTERN (from));
- count += 2;
- }
- else
- count += get_attr_length (from);
-
- from = NEXT_INSN (from);
- }
-
- /* We didn't find a barrier in time to
- dump our stuff, so we'll make one */
- label = gen_label_rtx ();
-
- if (from)
- from = PREV_INSN (from);
- else
- from = get_last_insn ();
-
- /* Walk back to be just before any jump */
- while (GET_CODE (from) == JUMP_INSN
- || GET_CODE (from) == NOTE
- || GET_CODE (from) == CODE_LABEL)
- from = PREV_INSN (from);
-
- from = emit_jump_insn_after (gen_jump (label), from);
- JUMP_LABEL (from) = label;
- found_barrier = emit_barrier_after (from);
- emit_label_after (label, found_barrier);
- return found_barrier;
-}
-
-/* Non zero if the insn is a move instruction which needs to be fixed. */
-
-static int
-broken_move (insn)
- rtx insn;
-{
- if (!INSN_DELETED_P (insn)
- && GET_CODE (insn) == INSN
- && GET_CODE (PATTERN (insn)) == SET)
- {
- rtx pat = PATTERN (insn);
- rtx src = SET_SRC (pat);
- rtx dst = SET_DEST (pat);
- enum machine_mode mode = GET_MODE (dst);
- if (dst == pc_rtx)
- return 0;
- return fixit (src, mode);
- }
- return 0;
-}
-
-/* Recursively search through all of the blocks in a function
- checking to see if any of the variables created in that
- function match the RTX called 'orig'. If they do then
- replace them with the RTX called 'new'. */
-
-static void
-replace_symbols_in_block (tree block, rtx orig, rtx new)
-{
- for (; block; block = BLOCK_CHAIN (block))
- {
- tree sym;
-
- if (! TREE_USED (block))
- continue;
-
- for (sym = BLOCK_VARS (block); sym; sym = TREE_CHAIN (sym))
- {
- if ( (DECL_NAME (sym) == 0 && TREE_CODE (sym) != TYPE_DECL)
- || DECL_IGNORED_P (sym)
- || TREE_CODE (sym) != VAR_DECL
- || DECL_EXTERNAL (sym)
- || ! rtx_equal_p (DECL_RTL (sym), orig)
- )
- continue;
-
- DECL_RTL (sym) = new;
- }
-
- replace_symbols_in_block (BLOCK_SUBBLOCKS (block), orig, new);
- }
-}
-
-void
-thumb_reorg (first)
- rtx first;
-{
- rtx insn;
- for (insn = first; insn; insn = NEXT_INSN (insn))
- {
- if (broken_move (insn))
- {
- /* This is a broken move instruction, scan ahead looking for
- a barrier to stick the constant table behind */
- rtx scan;
- rtx barrier = find_barrier (insn);
-
- /* Now find all the moves between the points and modify them */
- for (scan = insn; scan != barrier; scan = NEXT_INSN (scan))
- {
- if (broken_move (scan))
- {
- /* This is a broken move instruction, add it to the pool */
- rtx pat = PATTERN (scan);
- rtx src = SET_SRC (pat);
- rtx dst = SET_DEST (pat);
- enum machine_mode mode = GET_MODE (dst);
- HOST_WIDE_INT offset;
- rtx newinsn;
- rtx newsrc;
-
- /* If this is an HImode constant load, convert it into
- an SImode constant load. Since the register is always
- 32 bits this is safe. We have to do this, since the
- load pc-relative instruction only does a 32-bit load. */
- if (mode == HImode)
- {
- mode = SImode;
- if (GET_CODE (dst) != REG)
- abort ();
- PUT_MODE (dst, SImode);
- }
-
- offset = add_constant (src, mode);
- newsrc = gen_rtx (MEM, mode,
- plus_constant (gen_rtx (LABEL_REF,
- VOIDmode,
- pool_vector_label),
- offset));
-
- /* Build a jump insn wrapper around the move instead
- of an ordinary insn, because we want to have room for
- the target label rtx in fld[7], which an ordinary
- insn doesn't have. */
- newinsn = emit_jump_insn_after (gen_rtx (SET, VOIDmode,
- dst, newsrc), scan);
- JUMP_LABEL (newinsn) = pool_vector_label;
-
- /* But it's still an ordinary insn */
- PUT_CODE (newinsn, INSN);
-
- /* If debugging information is going to be emitted
- then we must make sure that any refences to
- symbols which are removed by the above code are
- also removed in the descriptions of the
- function's variables. Failure to do this means
- that the debugging information emitted could
- refer to symbols which are not emited by
- output_constant_pool() because
- mark_constant_pool() never sees them as being
- used. */
-
-
- /* These are the tests used in
- output_constant_pool() to decide if the constant
- pool will be marked. Only necessary if debugging
- info is being emitted. Only necessary for
- references to memory whose address is given by a
- symbol. */
-
- if (optimize > 0
- && flag_expensive_optimizations
- && write_symbols != NO_DEBUG
- && GET_CODE (src) == MEM
- && GET_CODE (XEXP (src, 0)) == SYMBOL_REF)
- replace_symbols_in_block
- (DECL_INITIAL (current_function_decl), src, newsrc);
-
- /* Kill old insn */
- delete_insn (scan);
- scan = newinsn;
- }
- }
- dump_table (barrier);
- }
- }
-}
-
-
-/* Routines for generating rtl */
-
-void
-thumb_expand_movstrqi (operands)
- rtx *operands;
-{
- rtx out = copy_to_mode_reg (SImode, XEXP (operands[0], 0));
- rtx in = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
- HOST_WIDE_INT len = INTVAL (operands[2]);
- HOST_WIDE_INT offset = 0;
-
- while (len >= 12)
- {
- emit_insn (gen_movmem12b (out, in));
- len -= 12;
- }
- if (len >= 8)
- {
- emit_insn (gen_movmem8b (out, in));
- len -= 8;
- }
- if (len >= 4)
- {
- rtx reg = gen_reg_rtx (SImode);
- emit_insn (gen_movsi (reg, gen_rtx (MEM, SImode, in)));
- emit_insn (gen_movsi (gen_rtx (MEM, SImode, out), reg));
- len -= 4;
- offset += 4;
- }
- if (len >= 2)
- {
- rtx reg = gen_reg_rtx (HImode);
- emit_insn (gen_movhi (reg, gen_rtx (MEM, HImode,
- plus_constant (in, offset))));
- emit_insn (gen_movhi (gen_rtx (MEM, HImode, plus_constant (out, offset)),
- reg));
- len -= 2;
- offset += 2;
- }
- if (len)
- {
- rtx reg = gen_reg_rtx (QImode);
- emit_insn (gen_movqi (reg, gen_rtx (MEM, QImode,
- plus_constant (in, offset))));
- emit_insn (gen_movqi (gen_rtx (MEM, QImode, plus_constant (out, offset)),
- reg));
- }
-}
-
-
-/* Routines for reloading */
-
-void
-thumb_reload_out_si (operands)
- rtx operands;
-{
- abort ();
-}
-
-/* CYGNUS LOCAL nickc/thumb-pe */
-
-#ifdef THUMB_PE
-/* Return non-zero if FUNC is a naked function. */
-
-static int
-arm_naked_function_p (func)
- tree func;
-{
- tree a;
-
- if (TREE_CODE (func) != FUNCTION_DECL)
- abort ();
-
- a = lookup_attribute ("naked", DECL_MACHINE_ATTRIBUTES (func));
- return a != NULL_TREE;
-}
-#endif
-/* END CYGNUS LOCAL nickc/thumb-pe */
-
-/* Return non-zero if FUNC must be entered in ARM mode. */
-int
-is_called_in_ARM_mode (func)
- tree func;
-{
- if (TREE_CODE (func) != FUNCTION_DECL)
- abort ();
-
- /* Ignore the problem about functions whoes address is taken. */
- if (TARGET_CALLEE_INTERWORKING && TREE_PUBLIC (func))
- return TRUE;
-
-/* CYGNUS LOCAL nickc/thumb-pe */
-#ifdef THUMB_PE
- return lookup_attribute ("interfacearm", DECL_MACHINE_ATTRIBUTES (func)) != NULL_TREE;
-#else
- return FALSE;
-#endif
-/* END CYGNUS LOCAL */
-}
-
-
-/* Routines for emitting code */
-
-void
-final_prescan_insn(insn)
- rtx insn;
-{
- extern int *insn_addresses;
-
- if (flag_print_asm_name)
- fprintf (asm_out_file, "%s 0x%04x\n", ASM_COMMENT_START,
- insn_addresses[INSN_UID (insn)]);
-}
-
-
-static void thumb_pushpop ( FILE *, int, int ); /* Forward declaration. */
-
-#ifdef __GNUC__
-inline
-#endif
-static int
-number_of_first_bit_set (mask)
- int mask;
-{
- int bit;
-
- for (bit = 0;
- (mask & (1 << bit)) == 0;
- ++ bit)
- continue;
-
- return bit;
-}
-
-#define ARG_1_REGISTER 0
-#define ARG_2_REGISTER 1
-#define ARG_3_REGISTER 2
-#define ARG_4_REGISTER 3
-#define WORK_REGISTER 7
-#define FRAME_POINTER 11
-#define IP_REGISTER 12
-#define STACK_POINTER STACK_POINTER_REGNUM
-#define LINK_REGISTER 14
-#define PROGRAM_COUNTER 15
-
-/* Generate code to return from a thumb function. If
- 'reg_containing_return_addr' is -1, then the return address is
- actually on the stack, at the stack pointer. */
-static void
-thumb_exit (f, reg_containing_return_addr)
- FILE * f;
- int reg_containing_return_addr;
-{
- int regs_available_for_popping;
- int regs_to_pop;
- int pops_needed;
- int reg;
- int available;
- int required;
- int mode;
- int size;
- int restore_a4 = FALSE;
-
- /* Compute the registers we need to pop. */
- regs_to_pop = 0;
- pops_needed = 0;
-
- if (reg_containing_return_addr == -1)
- {
- regs_to_pop |= 1 << LINK_REGISTER;
- ++ pops_needed;
- }
-
- if (TARGET_BACKTRACE)
- {
- /* Restore frame pointer and stack pointer. */
- regs_to_pop |= (1 << FRAME_POINTER) | (1 << STACK_POINTER);
- pops_needed += 2;
- }
-
- /* If there is nothing to pop then just emit the BX instruction and return.*/
- if (pops_needed == 0)
- {
- asm_fprintf (f, "\tbx\t%s\n", reg_names [reg_containing_return_addr]);
-
- return;
- }
-
- /* Otherwise if we are not supporting interworking and we have not created
- a backtrace structure and the function was not entered in ARM mode then
- just pop the return address straight into the PC. */
- else if ( ! TARGET_THUMB_INTERWORK
- && ! TARGET_BACKTRACE
- && ! is_called_in_ARM_mode (current_function_decl))
- {
- asm_fprintf (f, "\tpop\t{pc}\n" );
-
- return;
- }
-
- /* Find out how many of the (return) argument registers we can corrupt. */
- regs_available_for_popping = 0;
-
-#ifdef RTX_CODE
- /* If we can deduce the registers used from the function's return value.
- This is more reliable that examining regs_ever_live[] because that
- will be set if the register is ever used in the function, not just if
- the register is used to hold a return value. */
-
- if (current_function_return_rtx != 0)
- mode = GET_MODE (current_function_return_rtx);
- else
-#endif
- mode = DECL_MODE (DECL_RESULT (current_function_decl));
-
- size = GET_MODE_SIZE (mode);
-
- if (size == 0)
- {
- /* In a void function we can use any argument register.
- In a function that returns a structure on the stack
- we can use the second and third argument registers. */
- if (mode == VOIDmode)
- regs_available_for_popping =
- (1 << ARG_1_REGISTER)
- | (1 << ARG_2_REGISTER)
- | (1 << ARG_3_REGISTER);
- else
- regs_available_for_popping =
- (1 << ARG_2_REGISTER)
- | (1 << ARG_3_REGISTER);
- }
- else if (size <= 4) regs_available_for_popping =
- (1 << ARG_2_REGISTER)
- | (1 << ARG_3_REGISTER);
- else if (size <= 8) regs_available_for_popping =
- (1 << ARG_3_REGISTER);
-
- /* Match registers to be popped with registers into which we pop them. */
- for (available = regs_available_for_popping,
- required = regs_to_pop;
- required != 0 && available != 0;
- available &= ~(available & - available),
- required &= ~(required & - required))
- -- pops_needed;
-
- /* If we have any popping registers left over, remove them. */
- if (available > 0)
- regs_available_for_popping &= ~ available;
-
- /* Otherwise if we need another popping register we can use
- the fourth argument register. */
- else if (pops_needed)
- {
- /* If we have not found any free argument registers and
- reg a4 contains the return address, we must move it. */
- if (regs_available_for_popping == 0
- && reg_containing_return_addr == ARG_4_REGISTER)
- {
- asm_fprintf (f, "\tmov\t%s, %s\n",
- reg_names [LINK_REGISTER], reg_names [ARG_4_REGISTER]);
- reg_containing_return_addr = LINK_REGISTER;
- }
- else if (size > 12)
- {
- /* Register a4 is being used to hold part of the return value,
- but we have dire need of a free, low register. */
- restore_a4 = TRUE;
-
- asm_fprintf (f, "\tmov\t%s, %s\n",
- reg_names [IP_REGISTER], reg_names [ARG_4_REGISTER]);
- }
-
- if (reg_containing_return_addr != ARG_4_REGISTER)
- {
- /* The fourth argument register is available. */
- regs_available_for_popping |= 1 << ARG_4_REGISTER;
-
- -- pops_needed;
- }
- }
-
- /* Pop as many registers as we can. */
- thumb_pushpop (f, regs_available_for_popping, FALSE);
-
- /* Process the registers we popped. */
- if (reg_containing_return_addr == -1)
- {
- /* The return address was popped into the lowest numbered register. */
- regs_to_pop &= ~ (1 << LINK_REGISTER);
-
- reg_containing_return_addr =
- number_of_first_bit_set (regs_available_for_popping);
-
- /* Remove this register for the mask of available registers, so that
- the return address will not be corrupted by futher pops. */
- regs_available_for_popping &= ~ (1 << reg_containing_return_addr);
- }
-
- /* If we popped other registers then handle them here. */
- if (regs_available_for_popping)
- {
- int frame_pointer;
-
- /* Work out which register currently contains the frame pointer. */
- frame_pointer = number_of_first_bit_set (regs_available_for_popping);
-
- /* Move it into the correct place. */
- asm_fprintf (f, "\tmov\tfp, %s\n", reg_names [frame_pointer]);
-
- /* (Temporarily) remove it from the mask of popped registers. */
- regs_available_for_popping &= ~ (1 << frame_pointer);
- regs_to_pop &= ~ (1 << FRAME_POINTER);
-
- if (regs_available_for_popping)
- {
- int stack_pointer;
-
- /* We popped the stack pointer as well, find the register that
- contains it.*/
- stack_pointer = number_of_first_bit_set (regs_available_for_popping);
-
- /* Move it into the stack register. */
- asm_fprintf (f, "\tmov\tsp, %s\n", reg_names [stack_pointer]);
-
- /* At this point we have popped all necessary registers, so
- do not worry about restoring regs_available_for_popping
- to its correct value:
-
- assert (pops_needed == 0)
- assert (regs_available_for_popping == (1 << frame_pointer))
- assert (regs_to_pop == (1 << STACK_POINTER)) */
- }
- else
- {
- /* Since we have just move the popped value into the frame
- pointer, the popping register is available for reuse, and
- we know that we still have the stack pointer left to pop. */
- regs_available_for_popping |= (1 << frame_pointer);
- }
- }
-
- /* If we still have registers left on the stack, but we no longer have
- any registers into which we can pop them, then we must move the return
- address into the link register and make available the register that
- contained it. */
- if (regs_available_for_popping == 0 && pops_needed > 0)
- {
- regs_available_for_popping |= 1 << reg_containing_return_addr;
-
- asm_fprintf (f, "\tmov\t%s, %s\n",
- reg_names [LINK_REGISTER],
- reg_names [reg_containing_return_addr]);
-
- reg_containing_return_addr = LINK_REGISTER;
- }
-
- /* If we have registers left on the stack then pop some more.
- We know that at most we will want to pop FP and SP. */
- if (pops_needed > 0)
- {
- int popped_into;
- int move_to;
-
- thumb_pushpop (f, regs_available_for_popping, FALSE);
-
- /* We have popped either FP or SP.
- Move whichever one it is into the correct register. */
- popped_into = number_of_first_bit_set (regs_available_for_popping);
- move_to = number_of_first_bit_set (regs_to_pop);
-
- asm_fprintf (f, "\tmov\t%s, %s\n",
- reg_names [move_to], reg_names [popped_into]);
-
- regs_to_pop &= ~ (1 << move_to);
-
- -- pops_needed;
- }
-
- /* If we still have not popped everything then we must have only
- had one register available to us and we are now popping the SP. */
- if (pops_needed > 0)
- {
- int popped_into;
-
- thumb_pushpop (f, regs_available_for_popping, FALSE);
-
- popped_into = number_of_first_bit_set (regs_available_for_popping);
-
- asm_fprintf (f, "\tmov\tsp, %s\n", reg_names [popped_into]);
-
- /*
- assert (regs_to_pop == (1 << STACK_POINTER))
- assert (pops_needed == 1)
- */
- }
-
- /* If necessary restore the a4 register. */
- if (restore_a4)
- {
- if (reg_containing_return_addr != LINK_REGISTER)
- {
- asm_fprintf (f, "\tmov\t%s, %s\n",
- reg_names [LINK_REGISTER], reg_names [ARG_4_REGISTER]);
- reg_containing_return_addr = LINK_REGISTER;
- }
-
- asm_fprintf (f, "\tmov\t%s, %s\n",
- reg_names [ARG_4_REGISTER], reg_names [IP_REGISTER]);
- }
-
- /* Return to caller. */
- asm_fprintf (f, "\tbx\t%s\n", reg_names [reg_containing_return_addr]);
-}
-
-/* Emit code to push or pop registers to or from the stack. */
-static void
-thumb_pushpop (f, mask, push)
- FILE * f;
- int mask;
- int push;
-{
- int regno;
- int lo_mask = mask & 0xFF;
-
- if (lo_mask == 0 && ! push && (mask & (1 << 15)))
- {
- /* Special case. Do not generate a POP PC statement here, do it in
- thumb_exit() */
-
- thumb_exit (f, -1);
- return;
- }
-
- asm_fprintf (f, "\t%s\t{", push ? "push" : "pop");
-
- /* Look at the low registers first. */
-
- for (regno = 0; regno < 8; regno ++, lo_mask >>= 1)
- {
- if (lo_mask & 1)
- {
- asm_fprintf (f, reg_names[regno]);
-
- if ((lo_mask & ~1) != 0)
- asm_fprintf (f, ", ");
- }
- }
-
- if (push && (mask & (1 << 14)))
- {
- /* Catch pushing the LR. */
-
- if (mask & 0xFF)
- asm_fprintf (f, ", ");
-
- asm_fprintf (f, reg_names[14]);
- }
- else if (!push && (mask & (1 << 15)))
- {
- /* Catch popping the PC. */
-
- if (TARGET_THUMB_INTERWORK || TARGET_BACKTRACE)
- {
- /* The PC is never poped directly, instead
- it is popped into r3 and then BX is used. */
-
- asm_fprintf (f, "}\n");
-
- thumb_exit (f, -1);
-
- return;
- }
- else
- {
- if (mask & 0xFF)
- asm_fprintf (f, ", ");
-
- asm_fprintf (f, reg_names[15]);
- }
- }
-
- asm_fprintf (f, "}\n");
-}
-
-/* Returns non-zero if the current function contains a far jump */
-
-int
-far_jump_used_p (void)
-{
- rtx insn;
-
- if (current_function_has_far_jump)
- return 1;
-
- for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
- {
- if (GET_CODE (insn) == JUMP_INSN
- /* Ignore tablejump patterns. */
- && GET_CODE (PATTERN (insn)) != ADDR_VEC
- && GET_CODE (PATTERN (insn)) != ADDR_DIFF_VEC
- && get_attr_far_jump (insn) == FAR_JUMP_YES)
- {
- current_function_has_far_jump = 1;
- return 1;
- }
- }
-
- return 0;
-}
-
-static int return_used_this_function = 0;
-
-char *
-output_return ()
-{
- int regno;
- int live_regs_mask = 0;
-
- /* CYGNUS LOCAL nickc/thumb-pe */
-#ifdef THUMB_PE
- /* If a function is naked, don't use the "return" insn. */
- if (arm_naked_function_p (current_function_decl))
- return "";
-#endif
- /* END CYGNUS LOCAL nickc/thumb-pe */
-
- return_used_this_function = 1;
-
- for (regno = 0; regno < 8; regno++)
- if (regs_ever_live[regno] && ! call_used_regs[regno])
- live_regs_mask |= 1 << regno;
-
- if (live_regs_mask == 0)
- {
- if (leaf_function_p () && ! far_jump_used_p())
- {
- thumb_exit (asm_out_file, 14);
- }
- else if ( TARGET_THUMB_INTERWORK
- || TARGET_BACKTRACE
- || is_called_in_ARM_mode (current_function_decl))
- {
- thumb_exit (asm_out_file, -1);
- }
- else
- asm_fprintf (asm_out_file, "\tpop\t{pc}\n");
- }
- else
- {
- asm_fprintf (asm_out_file, "\tpop\t{");
-
- for (regno = 0; live_regs_mask; regno ++, live_regs_mask >>= 1)
- if (live_regs_mask & 1)
- {
- asm_fprintf (asm_out_file, reg_names[regno]);
- if (live_regs_mask & ~1)
- asm_fprintf (asm_out_file, ", ");
- }
-
- if ( TARGET_THUMB_INTERWORK
- || TARGET_BACKTRACE
- || is_called_in_ARM_mode (current_function_decl))
- {
- asm_fprintf (asm_out_file, "}\n");
- thumb_exit (asm_out_file, -1);
- }
- else
- asm_fprintf (asm_out_file, ", pc}\n");
- }
-
- return "";
-}
-
-void
-thumb_function_prologue (f, frame_size)
- FILE *f;
- int frame_size;
-{
- int amount = frame_size + current_function_outgoing_args_size;
- int live_regs_mask = 0;
- int high_regs_pushed = 0;
- int store_arg_regs = 0;
- int regno;
-
-/* CYGNUS LOCAL nickc/thumb-pe */
-#ifdef THUMB_PE
- if (arm_naked_function_p (current_function_decl))
- return;
-#endif
-/* CYGNUS LOCAL nickc/thumb-pe */
-
- if (is_called_in_ARM_mode (current_function_decl))
- {
- char * name;
- if (GET_CODE (DECL_RTL (current_function_decl)) != MEM)
- abort();
- if (GET_CODE (XEXP (DECL_RTL (current_function_decl), 0)) != SYMBOL_REF)
- abort();
- name = XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0);
-
- /* Generate code sequence to switch us into Thumb mode. */
- /* The .code 32 directive has already been emitted by
- ASM_DECLARE_FUNCITON_NAME */
- asm_fprintf (f, "\torr\tr12, pc, #1\n");
- asm_fprintf (f, "\tbx\tr12\n");
-
- /* Generate a label, so that the debugger will notice the
- change in instruction sets. This label is also used by
- the assembler to bypass the ARM code when this function
- is called from a Thumb encoded function elsewhere in the
- same file. Hence the definition of STUB_NAME here must
- agree with the definition in gas/config/tc-arm.c */
-
-#define STUB_NAME ".real_start_of"
-
- asm_fprintf (f, "\t.code\t16\n");
- asm_fprintf (f, "\t.globl %s%U%s\n", STUB_NAME, name);
- asm_fprintf (f, "\t.thumb_func\n");
- asm_fprintf (f, "%s%U%s:\n", STUB_NAME, name);
- }
-
- if (current_function_anonymous_args && current_function_pretend_args_size)
- store_arg_regs = 1;
-
- if (current_function_pretend_args_size)
- {
- if (store_arg_regs)
- {
- asm_fprintf (f, "\tpush\t{");
- for (regno = 4 - current_function_pretend_args_size / 4 ; regno < 4;
- regno++)
- asm_fprintf (f, "%s%s", reg_names[regno], regno == 3 ? "" : ", ");
- asm_fprintf (f, "}\n");
- }
- else
- asm_fprintf (f, "\tsub\t%Rsp, %Rsp, #%d\n",
- current_function_pretend_args_size);
- }
-
- for (regno = 0; regno < 8; regno++)
- if (regs_ever_live[regno] && ! call_used_regs[regno])
- live_regs_mask |= 1 << regno;
-
- if (live_regs_mask || ! leaf_function_p () || far_jump_used_p())
- live_regs_mask |= 1 << 14;
-
- if (TARGET_BACKTRACE)
- {
- char * name;
- int offset;
- int work_register = 0;
-
-
- /* We have been asked to create a stack backtrace structure.
- The code looks like this:
-
- 0 .align 2
- 0 func:
- 0 sub SP, #16 Reserve space for 4 registers.
- 2 push {R7} Get a work register.
- 4 add R7, SP, #20 Get the stack pointer before the push.
- 6 str R7, [SP, #8] Store the stack pointer (before reserving the space).
- 8 mov R7, PC Get hold of the start of this code plus 12.
- 10 str R7, [SP, #16] Store it.
- 12 mov R7, FP Get hold of the current frame pointer.
- 14 str R7, [SP, #4] Store it.
- 16 mov R7, LR Get hold of the current return address.
- 18 str R7, [SP, #12] Store it.
- 20 add R7, SP, #16 Point at the start of the backtrace structure.
- 22 mov FP, R7 Put this value into the frame pointer. */
-
- if ((live_regs_mask & 0xFF) == 0)
- {
- /* See if the a4 register is free. */
-
- if (regs_ever_live[ 3 ] == 0)
- work_register = 3;
- else /* We must push a register of our own */
- live_regs_mask |= (1 << 7);
- }
-
- if (work_register == 0)
- {
- /* Select a register from the list that will be pushed to use as our work register. */
-
- for (work_register = 8; work_register--;)
- if ((1 << work_register) & live_regs_mask)
- break;
- }
-
- name = reg_names[ work_register ];
-
- asm_fprintf (f, "\tsub\tsp, sp, #16\t@ Create stack backtrace structure\n");
-
- if (live_regs_mask)
- thumb_pushpop (f, live_regs_mask, 1);
-
- for (offset = 0, work_register = 1 << 15; work_register; work_register >>= 1)
- if (work_register & live_regs_mask)
- offset += 4;
-
- asm_fprintf (f, "\tadd\t%s, sp, #%d\n",
- name, offset + 16 + current_function_pretend_args_size);
-
- asm_fprintf (f, "\tstr\t%s, [sp, #%d]\n", name, offset + 4);
-
- /* Make sure that the instruction fetching the PC is in the right place
- to calculate "start of backtrace creation code + 12". */
-
- if (live_regs_mask)
- {
- asm_fprintf (f, "\tmov\t%s, pc\n", name);
- asm_fprintf (f, "\tstr\t%s, [sp, #%d]\n", name, offset + 12);
- asm_fprintf (f, "\tmov\t%s, fp\n", name);
- asm_fprintf (f, "\tstr\t%s, [sp, #%d]\n", name, offset);
- }
- else
- {
- asm_fprintf (f, "\tmov\t%s, fp\n", name);
- asm_fprintf (f, "\tstr\t%s, [sp, #%d]\n", name, offset);
- asm_fprintf (f, "\tmov\t%s, pc\n", name);
- asm_fprintf (f, "\tstr\t%s, [sp, #%d]\n", name, offset + 12);
- }
-
- asm_fprintf (f, "\tmov\t%s, lr\n", name);
- asm_fprintf (f, "\tstr\t%s, [sp, #%d]\n", name, offset + 8);
- asm_fprintf (f, "\tadd\t%s, sp, #%d\n", name, offset + 12);
- asm_fprintf (f, "\tmov\tfp, %s\t\t@ Backtrace structure created\n", name);
- }
- else if (live_regs_mask)
- thumb_pushpop (f, live_regs_mask, 1);
-
- for (regno = 8; regno < 13; regno++)
- {
- if (regs_ever_live[regno] && ! call_used_regs[regno])
- high_regs_pushed++;
- }
-
- if (high_regs_pushed)
- {
- int pushable_regs = 0;
- int mask = live_regs_mask & 0xff;
- int next_hi_reg;
-
- for (next_hi_reg = 12; next_hi_reg > 7; next_hi_reg--)
- {
- if (regs_ever_live[next_hi_reg] && ! call_used_regs[next_hi_reg])
- break;
- }
-
- pushable_regs = mask;
-
- if (pushable_regs == 0)
- {
- /* desperation time -- this probably will never happen */
- if (regs_ever_live[3] || ! call_used_regs[3])
- asm_fprintf (f, "\tmov\t%s, %s\n", reg_names[12], reg_names[3]);
- mask = 1 << 3;
- }
-
- while (high_regs_pushed > 0)
- {
- for (regno = 7; regno >= 0; regno--)
- {
- if (mask & (1 << regno))
- {
- asm_fprintf (f, "\tmov\t%s, %s\n", reg_names[regno],
- reg_names[next_hi_reg]);
- high_regs_pushed--;
- if (high_regs_pushed)
- for (next_hi_reg--; next_hi_reg > 7; next_hi_reg--)
- {
- if (regs_ever_live[next_hi_reg]
- && ! call_used_regs[next_hi_reg])
- break;
- }
- else
- {
- mask &= ~ ((1 << regno) - 1);
- break;
- }
- }
- }
- thumb_pushpop (f, mask, 1);
- }
-
- if (pushable_regs == 0 && (regs_ever_live[3] || ! call_used_regs[3]))
- asm_fprintf (f, "\tmov\t%s, %s\n", reg_names[3], reg_names[12]);
- }
-}
-
-void
-thumb_expand_prologue ()
-{
- HOST_WIDE_INT amount = (get_frame_size ()
- + current_function_outgoing_args_size);
- int regno;
- int live_regs_mask;
-
- /* CYGNUS LOCAL nickc/thumb-pe */
-#ifdef THUMB_PE
- /* Naked functions don't have prologues. */
- if (arm_naked_function_p (current_function_decl))
- return;
-#endif
- /* END CYGNUS LOCAL nickc/thumb-pe */
-
- if (amount)
- {
- live_regs_mask = 0;
- for (regno = 0; regno < 8; regno++)
- if (regs_ever_live[regno] && ! call_used_regs[regno])
- live_regs_mask |= 1 << regno;
-
- if (amount < 512)
- emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
- GEN_INT (-amount)));
- else
- {
- rtx reg, spare;
-
- if ((live_regs_mask & 0xff) == 0) /* Very unlikely */
- emit_insn (gen_movsi (spare = gen_rtx (REG, SImode, 12),
- reg = gen_rtx (REG, SImode, 4)));
- else
- {
- for (regno = 0; regno < 8; regno++)
- if (live_regs_mask & (1 << regno))
- break;
- reg = gen_rtx (REG, SImode, regno);
- }
-
- emit_insn (gen_movsi (reg, GEN_INT (-amount)));
- emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, reg));
- if ((live_regs_mask & 0xff) == 0)
- emit_insn (gen_movsi (reg, spare));
- }
- }
-
- if (frame_pointer_needed)
- {
- if (current_function_outgoing_args_size)
- {
- rtx offset = GEN_INT (current_function_outgoing_args_size);
-
- if (current_function_outgoing_args_size < 1024)
- emit_insn (gen_addsi3 (frame_pointer_rtx, stack_pointer_rtx,
- offset));
- else
- {
- emit_insn (gen_movsi (frame_pointer_rtx, offset));
- emit_insn (gen_addsi3 (frame_pointer_rtx, frame_pointer_rtx,
- stack_pointer_rtx));
- }
- }
- else
- emit_insn (gen_movsi (frame_pointer_rtx, stack_pointer_rtx));
- }
-
- /* if (profile_flag || profile_block_flag) */
- emit_insn (gen_blockage ());
-}
-
-void
-thumb_expand_epilogue ()
-{
- HOST_WIDE_INT amount = (get_frame_size ()
- + current_function_outgoing_args_size);
- int regno;
-
- /* CYGNUS LOCAL nickc/thumb-pe */
-#ifdef THUMB_PE
- /* Naked functions don't have epilogues. */
- if (arm_naked_function_p (current_function_decl))
- return;
-#endif
- /* END CYGNUS LOCAL nickc/thumb-pe */
-
- if (amount)
- {
- if (amount < 512)
- emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
- GEN_INT (amount)));
- else
- {
- rtx reg = gen_rtx (REG, SImode, 3); /* Always free in the epilogue */
-
- emit_insn (gen_movsi (reg, GEN_INT (amount)));
- emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, reg));
- }
- /* if (profile_flag || profile_block_flag) */
- emit_insn (gen_blockage ());
- }
-}
-
-void
-thumb_function_epilogue (f, frame_size)
- FILE *f;
- int frame_size;
-{
- /* ??? Probably not safe to set this here, since it assumes that a
- function will be emitted as assembly immediately after we generate
- RTL for it. This does not happen for inline functions. */
- return_used_this_function = 0;
- current_function_has_far_jump = 0;
-#if 0 /* TODO : comment not really needed */
- fprintf (f, "%s THUMB Epilogue\n", ASM_COMMENT_START);
-#endif
-}
-
-/* The bits which aren't usefully expanded as rtl. */
-char *
-thumb_unexpanded_epilogue ()
-{
- int regno;
- int live_regs_mask = 0;
- int high_regs_pushed = 0;
- int leaf_function = leaf_function_p ();
- int had_to_push_lr;
-
- if (return_used_this_function)
- return "";
-
- for (regno = 0; regno < 8; regno++)
- if (regs_ever_live[regno] && ! call_used_regs[regno])
- live_regs_mask |= 1 << regno;
-
- for (regno = 8; regno < 13; regno++)
- {
- if (regs_ever_live[regno] && ! call_used_regs[regno])
- high_regs_pushed ++;
- }
-
- /* The prolog may have pushed some high registers to use as
- work registers. eg the testuite file:
- gcc/testsuite/gcc/gcc.c-torture/execute/complex-2.c
- compiles to produce:
- push {r4, r5, r6, r7, lr}
- mov r7, r9
- mov r6, r8
- push {r6, r7}
- as part of the prolog. We have to undo that pushing here. */
-
- if (high_regs_pushed)
- {
- int mask = live_regs_mask;
- int next_hi_reg;
- int size;
- int mode;
-
-#ifdef RTX_CODE
- /* If we can deduce the registers used from the function's return value.
- This is more reliable that examining regs_ever_live[] because that
- will be set if the register is ever used in the function, not just if
- the register is used to hold a return value. */
-
- if (current_function_return_rtx != 0)
- {
- mode = GET_MODE (current_function_return_rtx);
- }
- else
-#endif
- {
- mode = DECL_MODE (DECL_RESULT (current_function_decl));
- }
-
- size = GET_MODE_SIZE (mode);
-
- /* Unless we are returning a type of size > 12 register r3 is available. */
- if (size < 13)
- mask |= 1 << 3;
-
- if (mask == 0)
- {
- /* Oh dear! We have no low registers into which we can pop high registers! */
-
- fatal ("No low registers available for popping high registers");
- }
-
- for (next_hi_reg = 8; next_hi_reg < 13; next_hi_reg++)
- if (regs_ever_live[next_hi_reg] && ! call_used_regs[next_hi_reg])
- break;
-
- while (high_regs_pushed)
- {
- /* Find low register(s) into which the high register(s) can be popped. */
- for (regno = 0; regno < 8; regno++)
- {
- if (mask & (1 << regno))
- high_regs_pushed--;
- if (high_regs_pushed == 0)
- break;
- }
-
- mask &= (2 << regno) - 1; /* A noop if regno == 8 */
-
- /* Pop the values into the low register(s). */
- thumb_pushpop (asm_out_file, mask, 0);
-
- /* Move the value(s) into the high registers. */
- for (regno = 0; regno < 8; regno++)
- {
- if (mask & (1 << regno))
- {
- asm_fprintf (asm_out_file, "\tmov\t%s, %s\n",
- reg_names[next_hi_reg], reg_names[regno]);
- for (next_hi_reg++; next_hi_reg < 13; next_hi_reg++)
- if (regs_ever_live[next_hi_reg] &&
- ! call_used_regs[next_hi_reg])
- break;
- }
- }
- }
- }
-
- had_to_push_lr = (live_regs_mask || ! leaf_function || far_jump_used_p());
-
- if (TARGET_BACKTRACE && ((live_regs_mask & 0xFF) == 0) && regs_ever_live[ ARG_4_REGISTER ] != 0)
- {
- /* The stack backtrace structure creation code had to
- push R7 in order to get a work register, so we pop
- it now. */
-
- live_regs_mask |= (1 << WORK_REGISTER);
- }
-
- if (current_function_pretend_args_size == 0 || TARGET_BACKTRACE)
- {
- if (had_to_push_lr
- && ! is_called_in_ARM_mode (current_function_decl))
- live_regs_mask |= 1 << PROGRAM_COUNTER;
-
- /* Either no argument registers were pushed or a backtrace
- structure was created which includes an adjusted stack
- pointer, so just pop everything. */
-
- if (live_regs_mask)
- thumb_pushpop (asm_out_file, live_regs_mask, FALSE);
-
- /* We have either just popped the return address into the
- PC or it is was kept in LR for the entire function or
- it is still on the stack because we do not want to
- return by doing a pop {pc}. */
-
- if ((live_regs_mask & (1 << PROGRAM_COUNTER)) == 0)
- thumb_exit (asm_out_file,
- (had_to_push_lr
- && is_called_in_ARM_mode (current_function_decl)) ?
- -1 : LINK_REGISTER);
- }
- else
- {
- /* Pop everything but the return address. */
- live_regs_mask &= ~ (1 << PROGRAM_COUNTER);
-
- if (live_regs_mask)
- thumb_pushpop (asm_out_file, live_regs_mask, FALSE);
-
- if (had_to_push_lr)
- {
- /* Get the return address into a temporary register. */
- thumb_pushpop (asm_out_file, 1 << ARG_4_REGISTER, 0);
- }
-
- /* Remove the argument registers that were pushed onto the stack. */
- asm_fprintf (asm_out_file, "\tadd\t%s, %s, #%d\n",
- reg_names [STACK_POINTER],
- reg_names [STACK_POINTER],
- current_function_pretend_args_size);
-
- thumb_exit (asm_out_file, had_to_push_lr ? ARG_4_REGISTER : LINK_REGISTER);
- }
-
- return "";
-}
-
-/* Handle the case of a double word load into a low register from
- a computed memory address. The computed address may involve a
- register which is overwritten by the load. */
-
-char *
-thumb_load_double_from_address (operands)
- rtx * operands;
-{
- rtx addr;
- rtx base;
- rtx offset;
- rtx arg1;
- rtx arg2;
-
- if (GET_CODE (operands[0]) != REG)
- fatal ("thumb_load_double_from_address: destination is not a register");
-
- if (GET_CODE (operands[1]) != MEM)
- fatal ("thumb_load_double_from_address: source is not a computed memory address");
-
- /* Get the memory address. */
-
- addr = XEXP (operands[1], 0);
-
- /* Work out how the memory address is computed. */
-
- switch (GET_CODE (addr))
- {
- case REG:
- operands[2] = gen_rtx (MEM, SImode, plus_constant (XEXP (operands[1], 0), 4));
-
- if (REGNO (operands[0]) == REGNO (addr))
- {
- output_asm_insn ("ldr\t%H0, %2\t\t%@ created by thumb_load_double_from_address", operands);
- output_asm_insn ("ldr\t%0, %1\t\t%@ created by thumb_load_double_from_address", operands);
- }
- else
- {
- output_asm_insn ("ldr\t%0, %1\t\t%@ created by thumb_load_double_from_address", operands);
- output_asm_insn ("ldr\t%H0, %2\t\t%@ created by thumb_load_double_from_address", operands);
- }
- break;
-
- case CONST:
- /* Compute <address> + 4 for the high order load. */
-
- operands[2] = gen_rtx (MEM, SImode, plus_constant (XEXP (operands[1], 0), 4));
-
- output_asm_insn ("ldr\t%0, %1\t\t%@ created by thumb_load_double_from_address", operands);
- output_asm_insn ("ldr\t%H0, %2\t\t%@ created by thumb_load_double_from_address", operands);
- break;
-
- case PLUS:
- arg1 = XEXP (addr, 0);
- arg2 = XEXP (addr, 1);
-
- if (CONSTANT_P (arg1))
- base = arg2, offset = arg1;
- else
- base = arg1, offset = arg2;
-
- if (GET_CODE (base) != REG)
- fatal ("thumb_load_double_from_address: base is not a register");
-
- /* Catch the case of <address> = <reg> + <reg> */
-
- if (GET_CODE (offset) == REG)
- {
- int reg_offset = REGNO (offset);
- int reg_base = REGNO (base);
- int reg_dest = REGNO (operands[0]);
-
- /* Add the base and offset registers together into the higher destination register. */
-
- fprintf (asm_out_file, "\tadd\t%s, %s, %s\t\t%s created by thumb_load_double_from_address",
- reg_names[ reg_dest + 1 ],
- reg_names[ reg_base ],
- reg_names[ reg_offset ],
- ASM_COMMENT_START);
-
- /* Load the lower destination register from the address in the higher destination register. */
-
- fprintf (asm_out_file, "\tldr\t%s, [%s, #0]\t\t%s created by thumb_load_double_from_address",
- reg_names[ reg_dest ],
- reg_names[ reg_dest + 1],
- ASM_COMMENT_START);
-
- /* Load the higher destination register from its own address plus 4. */
-
- fprintf (asm_out_file, "\tldr\t%s, [%s, #4]\t\t%s created by thumb_load_double_from_address",
- reg_names[ reg_dest + 1 ],
- reg_names[ reg_dest + 1 ],
- ASM_COMMENT_START);
- }
- else
- {
- /* Compute <address> + 4 for the high order load. */
-
- operands[2] = gen_rtx (MEM, SImode, plus_constant (XEXP (operands[1], 0), 4));
-
- /* If the computed address is held in the low order register
- then load the high order register first, otherwise always
- load the low order register first. */
-
- if (REGNO (operands[0]) == REGNO (base))
- {
- output_asm_insn ("ldr\t%H0, %2\t\t%@ created by thumb_load_double_from_address", operands);
- output_asm_insn ("ldr\t%0, %1\t\t%@ created by thumb_load_double_from_address", operands);
- }
- else
- {
- output_asm_insn ("ldr\t%0, %1\t\t%@ created by thumb_load_double_from_address", operands);
- output_asm_insn ("ldr\t%H0, %2\t\t%@ created by thumb_load_double_from_address", operands);
- }
- }
- break;
-
- case LABEL_REF:
- /* With no registers to worry about we can just load the value directly. */
- operands[2] = gen_rtx (MEM, SImode, plus_constant (XEXP (operands[1], 0), 4));
-
- output_asm_insn ("ldr\t%H0, %2\t\t%@ created by thumb_load_double_from_address", operands);
- output_asm_insn ("ldr\t%0, %1\t\t%@ created by thumb_load_double_from_address", operands);
- break;
-
- default:
- debug_rtx (operands[1]);
- fatal ("thumb_load_double_from_address: Unhandled address calculation");
- break;
- }
-
- return "";
-}
-
-char *
-output_move_mem_multiple (n, operands)
- int n;
- rtx *operands;
-{
- rtx tmp;
-
- switch (n)
- {
- case 2:
- if (REGNO (operands[2]) > REGNO (operands[3]))
- {
- tmp = operands[2];
- operands[2] = operands[3];
- operands[3] = tmp;
- }
- output_asm_insn ("ldmia\t%1!, {%2, %3}", operands);
- output_asm_insn ("stmia\t%0!, {%2, %3}", operands);
- break;
-
- case 3:
- if (REGNO (operands[2]) > REGNO (operands[3]))
- {
- tmp = operands[2];
- operands[2] = operands[3];
- operands[3] = tmp;
- }
- if (REGNO (operands[3]) > REGNO (operands[4]))
- {
- tmp = operands[3];
- operands[3] = operands[4];
- operands[4] = tmp;
- }
- if (REGNO (operands[2]) > REGNO (operands[3]))
- {
- tmp = operands[2];
- operands[2] = operands[3];
- operands[3] = tmp;
- }
- output_asm_insn ("ldmia\t%1!, {%2, %3, %4}", operands);
- output_asm_insn ("stmia\t%0!, {%2, %3, %4}", operands);
- break;
-
- default:
- abort ();
- }
-
- return "";
-}
-
-
-int
-thumb_epilogue_size ()
-{
- return 42; /* The answer to .... */
-}
-
-static char *conds[] =
-{
- "eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc",
- "hi", "ls", "ge", "lt", "gt", "le"
-};
-
-static char *
-thumb_condition_code (x, invert)
- rtx x;
- int invert;
-{
- int val;
-
- switch (GET_CODE (x))
- {
- case EQ: val = 0; break;
- case NE: val = 1; break;
- case GEU: val = 2; break;
- case LTU: val = 3; break;
- case GTU: val = 8; break;
- case LEU: val = 9; break;
- case GE: val = 10; break;
- case LT: val = 11; break;
- case GT: val = 12; break;
- case LE: val = 13; break;
- default:
- abort ();
- }
-
- return conds[val ^ invert];
-}
-
-void
-thumb_print_operand (f, x, code)
- FILE *f;
- rtx x;
- int code;
-{
- if (code)
- {
- switch (code)
- {
- case '@':
- fputs (ASM_COMMENT_START, f);
- return;
-
- case '_':
- fputs (user_label_prefix, f);
- return;
-
- case 'D':
- if (x)
- fputs (thumb_condition_code (x, 1), f);
- return;
-
- case 'd':
- if (x)
- fputs (thumb_condition_code (x, 0), f);
- return;
-
- /* An explanation of the 'Q', 'R' and 'H' register operands:
-
- In a pair of registers containing a DI or DF value the 'Q'
- operand returns the register number of the register containing
- the least signficant part of the value. The 'R' operand returns
- the register number of the register containing the most
- significant part of the value.
-
- The 'H' operand returns the higher of the two register numbers.
- On a run where WORDS_BIG_ENDIAN is true the 'H' operand is the
- same as the 'Q' operand, since the most signficant part of the
- value is held in the lower number register. The reverse is true
- on systems where WORDS_BIG_ENDIAN is false.
-
- The purpose of these operands is to distinguish between cases
- where the endian-ness of the values is important (for example
- when they are added together), and cases where the endian-ness
- is irrelevant, but the order of register operations is important.
- For example when loading a value from memory into a register
- pair, the endian-ness does not matter. Provided that the value
- from the lower memory address is put into the lower numbered
- register, and the value from the higher address is put into the
- higher numbered register, the load will work regardless of whether
- the value being loaded is big-wordian or little-wordian. The
- order of the two register loads can matter however, if the address
- of the memory location is actually held in one of the registers
- being overwritten by the load. */
- case 'Q':
- if (REGNO (x) > 15)
- abort ();
- fputs (reg_names[REGNO (x) + (WORDS_BIG_ENDIAN ? 1 : 0)], f);
- return;
-
- case 'R':
- if (REGNO (x) > 15)
- abort ();
- fputs (reg_names[REGNO (x) + (WORDS_BIG_ENDIAN ? 0 : 1)], f);
- return;
-
- case 'H':
- if (REGNO (x) > 15)
- abort ();
- fputs (reg_names[REGNO (x) + 1], f);
- return;
-
- case 'c':
- /* We use 'c' operands with symbols for .vtinherit */
- if (GET_CODE (x) == SYMBOL_REF)
- output_addr_const(f, x);
- return;
-
- default:
- abort ();
- }
- }
- if (GET_CODE (x) == REG)
- fputs (reg_names[REGNO (x)], f);
- else if (GET_CODE (x) == MEM)
- output_address (XEXP (x, 0));
- else if (GET_CODE (x) == CONST_INT)
- {
- fputc ('#', f);
- output_addr_const (f, x);
- }
- else
- abort ();
-}
-
-#ifdef AOF_ASSEMBLER
-int arm_text_section_count = 1;
-
-char *
-aof_text_section (in_readonly)
- int in_readonly;
-{
- static char buf[100];
- if (in_readonly)
- return "";
- sprintf (buf, "\tCODE16\n\tAREA |C$$code%d|, CODE, READONLY",
- arm_text_section_count++);
- return buf;
-}
-
-static int arm_data_section_count = 1;
-
-char *
-aof_data_section ()
-{
- static char buf[100];
- sprintf (buf, "\tAREA |C$$data%d|, DATA", arm_data_section_count++);
- return buf;
-}
-
-/* The AOF thumb assembler is religiously strict about declarations of
- imported and exported symbols, so that it is impossible to declare a
- function as imported near the begining of the file, and then to export
- it later on. It is, however, possible to delay the decision until all
- the functions in the file have been compiled. To get around this, we
- maintain a list of the imports and exports, and delete from it any that
- are subsequently defined. At the end of compilation we spit the
- remainder of the list out before the END directive. */
-
-struct import
-{
- struct import *next;
- char *name;
-};
-
-static struct import *imports_list = NULL;
-
-void
-thumb_aof_add_import (name)
- char *name;
-{
- struct import *new;
-
- for (new = imports_list; new; new = new->next)
- if (new->name == name)
- return;
-
- new = (struct import *) xmalloc (sizeof (struct import));
- new->next = imports_list;
- imports_list = new;
- new->name = name;
-}
-
-void
-thumb_aof_delete_import (name)
- char *name;
-{
- struct import **old;
-
- for (old = &imports_list; *old; old = & (*old)->next)
- {
- if ((*old)->name == name)
- {
- *old = (*old)->next;
- return;
- }
- }
-}
-
-void
-thumb_aof_dump_imports (f)
- FILE *f;
-{
- while (imports_list)
- {
- fprintf (f, "\tIMPORT\t");
- assemble_name (f, imports_list->name);
- fputc ('\n', f);
- imports_list = imports_list->next;
- }
-}
-#endif
-
-/* Decide whether a type should be returned in memory (true)
- or in a register (false). This is called by the macro
- RETURN_IN_MEMORY. */
-
-int
-thumb_return_in_memory (type)
- tree type;
-{
- if (! AGGREGATE_TYPE_P (type))
- {
- /* All simple types are returned in registers. */
-
- return 0;
- }
- else if (int_size_in_bytes (type) > 4)
- {
- /* All structures/unions bigger than one word are returned in memory. */
-
- return 1;
- }
- else if (TREE_CODE (type) == RECORD_TYPE)
- {
- tree field;
-
- /* For a struct the APCS says that we must return in a register if
- every addressable element has an offset of zero. For practical
- purposes this means that the structure can have at most one non-
- bit-field element and that this element must be the first one in
- the structure. */
-
- /* Find the first field, ignoring non FIELD_DECL things which will
- have been created by C++. */
- for (field = TYPE_FIELDS (type);
- field && TREE_CODE (field) != FIELD_DECL;
- field = TREE_CHAIN (field))
- continue;
-
- if (field == NULL)
- return 0; /* An empty structure. Allowed by an extension to ANSI C. */
-
- /* Now check the remaining fields, if any. */
- for (field = TREE_CHAIN (field); field; field = TREE_CHAIN (field))
- {
- if (TREE_CODE (field) != FIELD_DECL)
- continue;
-
- if (! DECL_BIT_FIELD_TYPE (field))
- return 1;
- }
-
- return 0;
- }
- else if (TREE_CODE (type) == UNION_TYPE)
- {
- tree field;
-
- /* Unions can be returned in registers if every element is
- integral, or can be returned in an integer register. */
-
- for (field = TYPE_FIELDS (type);
- field;
- field = TREE_CHAIN (field))
- {
- if (TREE_CODE (field) != FIELD_DECL)
- continue;
-
- if (RETURN_IN_MEMORY (TREE_TYPE (field)))
- return 1;
- }
-
- return 0;
- }
- /* XXX Not sure what should be done for other aggregates, so put them in
- memory. */
- return 1;
-}
-
-void
-thumb_override_options ()
-{
- if (structure_size_string != NULL)
- {
- int size = strtol (structure_size_string, NULL, 0);
-
- if (size == 8 || size == 32)
- arm_structure_size_boundary = size;
- else
- warning ("Structure size boundary can only be set to 8 or 32");
- }
-
- if (flag_pic)
- {
- warning ("Position independent code not supported. Ignored");
- flag_pic = 0;
- }
-}
-
-/* CYGNUS LOCAL nickc/thumb-pe */
-
-#ifdef THUMB_PE
-/* Return nonzero if ATTR is a valid attribute for DECL.
- ATTRIBUTES are any existing attributes and ARGS are the arguments
- supplied with ATTR.
-
- Supported attributes:
-
- naked: don't output any prologue or epilogue code, the user is assumed
- to do the right thing.
-
- interfacearm: Always assume that this function will be entered in ARM
- mode, not Thumb mode, and that the caller wishes to be returned to in
- ARM mode. */
-int
-arm_valid_machine_decl_attribute (decl, attributes, attr, args)
- tree decl;
- tree attributes;
- tree attr;
- tree args;
-{
- if (args != NULL_TREE)
- return 0;
-
- if (is_attribute_p ("naked", attr))
- return TREE_CODE (decl) == FUNCTION_DECL;
-
- if (is_attribute_p ("interfacearm", attr))
- return TREE_CODE (decl) == FUNCTION_DECL;
-
- return 0;
-}
-#endif /* THUMB_PE */
-/* END CYGNUS LOCAL nickc/thumb-pe */
-
-/* s_register_operand is the same as register_operand, but it doesn't accept
- (SUBREG (MEM)...).
-
- This function exists because at the time it was put in it led to better
- code. SUBREG(MEM) always needs a reload in the places where
- s_register_operand is used, and this seemed to lead to excessive
- reloading. */
-
-int
-s_register_operand (op, mode)
- register rtx op;
- enum machine_mode mode;
-{
- if (GET_MODE (op) != mode && mode != VOIDmode)
- return 0;
-
- if (GET_CODE (op) == SUBREG)
- op = SUBREG_REG (op);
-
- /* We don't consider registers whose class is NO_REGS
- to be a register operand. */
- /* XXX might have to check for lo regs only for thumb ??? */
- return (GET_CODE (op) == REG
- && (REGNO (op) >= FIRST_PSEUDO_REGISTER
- || REGNO_REG_CLASS (REGNO (op)) != NO_REGS));
-}
diff --git a/gcc/config/arm/thumb.c.rej b/gcc/config/arm/thumb.c.rej
deleted file mode 100755
index 0233312..0000000
--- a/gcc/config/arm/thumb.c.rej
+++ /dev/null
@@ -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;
-+ }
diff --git a/gcc/config/arm/thumb.h.orig b/gcc/config/arm/thumb.h.orig
deleted file mode 100755
index 9cd719a..0000000
--- a/gcc/config/arm/thumb.h.orig
+++ /dev/null
@@ -1,1195 +0,0 @@
-/* Definitions of target machine for GNU compiler, for ARM/Thumb.
- Copyright (C) 1996, 1997, 1998, 1999, 2002 Free Software Foundation, Inc.
- The basis of this contribution was generated by
- Richard Earnshaw, Advanced RISC Machines Ltd
-
-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. */
-
-/* ??? The files thumb.{c,h,md} are all seriously lacking comments. */
-
-/* ??? The files thumb.{c,h,md} need to be reviewed by an experienced
- gcc hacker in their entirety. */
-
-/* ??? The files thumb.{c,h,md} and tcoff.h are all separate from the arm
- files, which will lead to many maintenance problems. These files are
- likely missing all bug fixes made to the arm port since they diverged. */
-
-/* ??? Many patterns in the md file accept operands that will require a
- reload. These should be eliminated if possible by tightening the
- predicates and/or constraints. This will give faster/smaller code. */
-
-/* ??? There is no pattern for the TST instuction. Check for other unsupported
- instructions. */
-
-/* Run Time Target Specifications */
-#ifndef CPP_PREDEFINES
-#define CPP_PREDEFINES "-Dthumb -D__thumb -Acpu(arm) -Amachine(arm)"
-#endif
-
-#ifndef CPP_SPEC
-#define CPP_SPEC "\
-%{mbig-endian:-D__ARMEB__ -D__THUMBEB__} \
-%{mbe:-D__ARMEB__ -D__THUMBEB__} \
-%{!mbe: %{!mbig-endian:-D__ARMEL__ -D__THUMBEL__}} \
-"
-#endif
-
-#ifndef ASM_SPEC
-#define ASM_SPEC "-marm7tdmi %{mthumb-interwork:-mthumb-interwork} %{mbig-endian:-EB}"
-#endif
-#define LINK_SPEC "%{mbig-endian:-EB} -X"
-
-#define TARGET_VERSION fputs (" (ARM/THUMB:generic)", stderr);
-
-/* Nonzero if we should compile with BYTES_BIG_ENDIAN set to 1. */
-#define THUMB_FLAG_BIG_END 0x0001
-#define THUMB_FLAG_BACKTRACE 0x0002
-#define THUMB_FLAG_LEAF_BACKTRACE 0x0004
-#define ARM_FLAG_THUMB 0x1000 /* same as in arm.h */
-#define THUMB_FLAG_CALLEE_SUPER_INTERWORKING 0x40000
-#define THUMB_FLAG_CALLER_SUPER_INTERWORKING 0x80000
-
-/* Nonzero if all call instructions should be indirect. */
-#define ARM_FLAG_LONG_CALLS (0x10000) /* same as in arm.h */
-
-
-/* Run-time compilation parameters selecting different hardware/software subsets. */
-extern int target_flags;
-#define TARGET_DEFAULT 0 /* ARM_FLAG_THUMB */
-#define TARGET_BIG_END (target_flags & THUMB_FLAG_BIG_END)
-#define TARGET_THUMB_INTERWORK (target_flags & ARM_FLAG_THUMB)
-#define TARGET_BACKTRACE (leaf_function_p() \
- ? (target_flags & THUMB_FLAG_LEAF_BACKTRACE) \
- : (target_flags & THUMB_FLAG_BACKTRACE))
-
-/* Set if externally visable functions should assume that they
- might be called in ARM mode, from a non-thumb aware code. */
-#define TARGET_CALLEE_INTERWORKING \
- (target_flags & THUMB_FLAG_CALLEE_SUPER_INTERWORKING)
-
-/* Set if calls via function pointers should assume that their
- destination is non-Thumb aware. */
-#define TARGET_CALLER_INTERWORKING \
- (target_flags & THUMB_FLAG_CALLER_SUPER_INTERWORKING)
-
-#define TARGET_LONG_CALLS (target_flags & ARM_FLAG_LONG_CALLS)
-
-/* SUBTARGET_SWITCHES is used to add flags on a per-config basis. */
-#ifndef SUBTARGET_SWITCHES
-#define SUBTARGET_SWITCHES
-#endif
-
-#define TARGET_SWITCHES \
-{ \
- {"big-endian", THUMB_FLAG_BIG_END}, \
- {"little-endian", -THUMB_FLAG_BIG_END}, \
- {"thumb-interwork", ARM_FLAG_THUMB}, \
- {"no-thumb-interwork", -ARM_FLAG_THUMB}, \
- {"tpcs-frame", THUMB_FLAG_BACKTRACE}, \
- {"no-tpcs-frame", -THUMB_FLAG_BACKTRACE}, \
- {"tpcs-leaf-frame", THUMB_FLAG_LEAF_BACKTRACE}, \
- {"no-tpcs-leaf-frame", -THUMB_FLAG_LEAF_BACKTRACE}, \
- {"callee-super-interworking", THUMB_FLAG_CALLEE_SUPER_INTERWORKING}, \
- {"no-callee-super-interworking", -THUMB_FLAG_CALLEE_SUPER_INTERWORKING}, \
- {"caller-super-interworking", THUMB_FLAG_CALLER_SUPER_INTERWORKING}, \
- {"no-caller-super-interworking", -THUMB_FLAG_CALLER_SUPER_INTERWORKING}, \
- {"long-calls", ARM_FLAG_LONG_CALLS, \
- "Generate all call instructions as indirect calls"}, \
- {"no-long-calls", -ARM_FLAG_LONG_CALLS, ""}, \
- SUBTARGET_SWITCHES \
- {"", TARGET_DEFAULT} \
-}
-
-#define TARGET_OPTIONS \
-{ \
- { "structure-size-boundary=", & structure_size_string }, \
-}
-
-#define REGISTER_PREFIX ""
-
-#define CAN_DEBUG_WITHOUT_FP 1
-
-#define ASM_APP_ON ""
-#define ASM_APP_OFF "\t.code\t16\n"
-
-/* Output a gap. In fact we fill it with nulls. */
-#define ASM_OUTPUT_SKIP(STREAM, NBYTES) \
- fprintf ((STREAM), "\t.space\t%u\n", (NBYTES))
-
-/* This is how to output an assembler line
- that says to advance the location counter
- to a multiple of 2**LOG bytes. */
-#define ASM_OUTPUT_ALIGN(STREAM,LOG) \
-{ \
- if ((LOG) > 0) \
- fprintf (STREAM, "\t.align\t%d\n", (LOG)); \
-}
-
-/* Output a common block */
-#define ASM_OUTPUT_COMMON(STREAM, NAME, SIZE, ROUNDED) \
- (fprintf ((STREAM), "\t.comm\t"), \
- assemble_name ((STREAM), (NAME)), \
- fprintf((STREAM), ", %d\t%s %d\n", (ROUNDED), (ASM_COMMENT_START), (SIZE)))
-
-#define ASM_GENERATE_INTERNAL_LABEL(STRING,PREFIX,NUM) \
- sprintf ((STRING), "*%s%s%d", (LOCAL_LABEL_PREFIX), (PREFIX), (NUM))
-
-/* This is how to output an internal numbered label where
- PREFIX is the class of label and NUM is the number within the class. */
-#define ASM_OUTPUT_INTERNAL_LABEL(STREAM,PREFIX,NUM) \
- fprintf ((STREAM), "%s%s%d:\n", (LOCAL_LABEL_PREFIX), (PREFIX), (NUM))
-
-/* This is how to output a label which precedes a jumptable. Since
- instructions are 2 bytes, we need explicit alignment here. */
-
-#define ASM_OUTPUT_CASE_LABEL(FILE,PREFIX,NUM,JUMPTABLE) \
- do { \
- ASM_OUTPUT_ALIGN (FILE, 2); \
- ASM_OUTPUT_INTERNAL_LABEL (FILE, PREFIX, NUM); \
- } while (0)
-
-/* This says how to define a local common symbol (ie, not visible to
- linker). */
-#define ASM_OUTPUT_LOCAL(STREAM, NAME, SIZE, ROUNDED) \
- (fprintf((STREAM),"\n\t.lcomm\t"), \
- assemble_name((STREAM),(NAME)), \
- fprintf((STREAM),",%u\n",(SIZE)))
-
-/* Output a reference to a label. */
-#define ASM_OUTPUT_LABELREF(STREAM,NAME) \
- fprintf ((STREAM), "%s%s", user_label_prefix, (NAME))
-
-/* This is how to output an assembler line for a numeric constant byte. */
-#define ASM_OUTPUT_BYTE(STREAM,VALUE) \
- fprintf ((STREAM), "\t.byte\t0x%x\n", (VALUE))
-
-#define ASM_OUTPUT_INT(STREAM,VALUE) \
-{ \
- fprintf (STREAM, "\t.word\t"); \
- output_addr_const (STREAM, (VALUE)); \
- fprintf (STREAM, "\n"); \
-}
-
-#define ASM_OUTPUT_SHORT(STREAM,VALUE) \
-{ \
- fprintf (STREAM, "\t.short\t"); \
- output_addr_const (STREAM, (VALUE)); \
- fprintf (STREAM, "\n"); \
-}
-
-#define ASM_OUTPUT_CHAR(STREAM,VALUE) \
-{ \
- fprintf (STREAM, "\t.byte\t"); \
- output_addr_const (STREAM, (VALUE)); \
- fprintf (STREAM, "\n"); \
-}
-
-#define ASM_OUTPUT_LONG_DOUBLE(STREAM,VALUE) \
-do { char dstr[30]; \
- long l[3]; \
- REAL_VALUE_TO_TARGET_LONG_DOUBLE (VALUE, l); \
- REAL_VALUE_TO_DECIMAL (VALUE, "%.20g", dstr); \
- fprintf (STREAM, "\t.long 0x%lx,0x%lx,0x%lx\t%s long double %s\n", \
- l[0], l[1], l[2], ASM_COMMENT_START, dstr); \
- } while (0)
-
-#define ASM_OUTPUT_DOUBLE(STREAM, VALUE) \
-do { char dstr[30]; \
- long l[2]; \
- REAL_VALUE_TO_TARGET_DOUBLE (VALUE, l); \
- REAL_VALUE_TO_DECIMAL (VALUE, "%.14g", dstr); \
- fprintf (STREAM, "\t.long 0x%lx, 0x%lx\t%s double %s\n", l[0], \
- l[1], ASM_COMMENT_START, dstr); \
- } while (0)
-
-#define ASM_OUTPUT_FLOAT(STREAM, VALUE) \
-do { char dstr[30]; \
- long l; \
- REAL_VALUE_TO_TARGET_SINGLE (VALUE, l); \
- REAL_VALUE_TO_DECIMAL (VALUE, "%.7g", dstr); \
- fprintf (STREAM, "\t.word 0x%lx\t%s float %s\n", l, \
- ASM_COMMENT_START, dstr); \
- } while (0);
-
-/* Define results of standard character escape sequences. */
-#define TARGET_BELL 007
-#define TARGET_BS 010
-#define TARGET_TAB 011
-#define TARGET_NEWLINE 012
-#define TARGET_VT 013
-#define TARGET_FF 014
-#define TARGET_CR 015
-
-/* This is how to output a string. */
-#define ASM_OUTPUT_ASCII(STREAM, STRING, LEN) \
-do { \
- register int i, c, len = (LEN), cur_pos = 17; \
- register unsigned char *string = (unsigned char *)(STRING); \
- fprintf ((STREAM), "\t.ascii\t\""); \
- for (i = 0; i < len; i++) \
- { \
- register int c = string[i]; \
- \
- switch (c) \
- { \
- case '\"': \
- case '\\': \
- putc ('\\', (STREAM)); \
- putc (c, (STREAM)); \
- cur_pos += 2; \
- break; \
- \
- case TARGET_NEWLINE: \
- fputs ("\\n", (STREAM)); \
- if (i+1 < len \
- && (((c = string[i+1]) >= '\040' && c <= '~') \
- || c == TARGET_TAB)) \
- cur_pos = 32767; /* break right here */ \
- else \
- cur_pos += 2; \
- break; \
- \
- case TARGET_TAB: \
- fputs ("\\t", (STREAM)); \
- cur_pos += 2; \
- break; \
- \
- case TARGET_FF: \
- fputs ("\\f", (STREAM)); \
- cur_pos += 2; \
- break; \
- \
- case TARGET_BS: \
- fputs ("\\b", (STREAM)); \
- cur_pos += 2; \
- break; \
- \
- case TARGET_CR: \
- fputs ("\\r", (STREAM)); \
- cur_pos += 2; \
- break; \
- \
- default: \
- if (c >= ' ' && c < 0177) \
- { \
- putc (c, (STREAM)); \
- cur_pos++; \
- } \
- else \
- { \
- fprintf ((STREAM), "\\%03o", c); \
- cur_pos += 4; \
- } \
- } \
- \
- if (cur_pos > 72 && i+1 < len) \
- { \
- cur_pos = 17; \
- fprintf ((STREAM), "\"\n\t.ascii\t\""); \
- } \
- } \
- fprintf ((STREAM), "\"\n"); \
-} while (0)
-
-/* Output and Generation of Labels */
-#define ASM_OUTPUT_LABEL(STREAM,NAME) \
- (assemble_name ((STREAM), (NAME)), \
- fprintf ((STREAM), ":\n"))
-
-#define ASM_GLOBALIZE_LABEL(STREAM,NAME) \
- (fprintf ((STREAM), "\t.globl\t"), \
- assemble_name ((STREAM), (NAME)), \
- fputc ('\n', (STREAM)))
-
-/* Construct a private name. */
-#define ASM_FORMAT_PRIVATE_NAME(OUTVAR,NAME,NUMBER) \
- ((OUTVAR) = (char *) alloca (strlen (NAME) + 10), \
- sprintf ((OUTVAR), "%s.%d", (NAME), (NUMBER)))
-
-/* Switch to the text or data segment. */
-#define TEXT_SECTION_ASM_OP ".text"
-#define DATA_SECTION_ASM_OP ".data"
-#define BSS_SECTION_ASM_OP ".bss"
-
-/* The assembler's names for the registers. */
-#ifndef REGISTER_NAMES
-#define REGISTER_NAMES \
-{ \
- "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \
- "r8", "r9", "sl", "fp", "ip", "sp", "lr", "pc", "ap" \
-}
-#endif
-
-#ifndef ADDITIONAL_REGISTER_NAMES
-#define ADDITIONAL_REGISTER_NAMES \
-{ \
- {"a1", 0}, \
- {"a2", 1}, \
- {"a3", 2}, \
- {"a4", 3}, \
- {"v1", 4}, \
- {"v2", 5}, \
- {"v3", 6}, \
- {"v4", 7}, \
- {"v5", 8}, \
- {"v6", 9}, \
- {"sb", 9}, \
- {"v7", 10}, \
- {"r10", 10}, /* sl */ \
- {"r11", 11}, /* fp */ \
- {"r12", 12}, /* ip */ \
- {"r13", 13}, /* sp */ \
- {"r14", 14}, /* lr */ \
- {"r15", 15} /* pc */ \
-}
-#endif
-
-/* The assembler's parentheses characters. */
-#define ASM_OPEN_PAREN "("
-#define ASM_CLOSE_PAREN ")"
-
-#ifndef ASM_COMMENT_START
-#define ASM_COMMENT_START "@"
-#endif
-
-/* Output an element of a dispatch table. */
-#define ASM_OUTPUT_ADDR_VEC_ELT(STREAM,VALUE) \
- fprintf (STREAM, "\t.word\t%sL%d\n", (LOCAL_LABEL_PREFIX), (VALUE))
-
-#define ASM_OUTPUT_ADDR_DIFF_ELT(STREAM,BODY,VALUE,REL) \
- fprintf (STREAM, "\tb\t%sL%d\n", (LOCAL_LABEL_PREFIX), (VALUE))
-
-/* Storage Layout */
-
-/* Define this is most significant bit is lowest numbered in
- instructions that operate on numbered bit-fields. */
-#define BITS_BIG_ENDIAN 0
-
-/* Define this if most significant byte of a word is the lowest
- numbered. */
-#define BYTES_BIG_ENDIAN (TARGET_BIG_END != 0)
-
-#define WORDS_BIG_ENDIAN (BYTES_BIG_ENDIAN)
-
-/* LIBGCC2_WORDS_BIG_ENDIAN has to be a constant, so we define this based
- on processor pre-defineds when compiling libgcc2.c. */
-#if defined(__THUMBEB__) && !defined(__THUMBEL__)
-#define LIBGCC2_WORDS_BIG_ENDIAN 1
-#else
-#define LIBGCC2_WORDS_BIG_ENDIAN 0
-#endif
-
-#define FLOAT_WORDS_BIG_ENDIAN 1
-
-#define BITS_PER_UNIT 8
-#define BITS_PER_WORD 32
-
-#define UNITS_PER_WORD 4
-
-#define POINTER_SIZE 32
-
-#define PROMOTE_MODE(MODE,UNSIGNEDP,TYPE) \
-{ \
- if (GET_MODE_CLASS (MODE) == MODE_INT \
- && GET_MODE_SIZE (MODE) < 4) \
- { \
- (UNSIGNEDP) = 1; \
- (MODE) = SImode; \
- } \
-}
-
-#define PARM_BOUNDARY 32
-#define STACK_BOUNDARY 32
-
-#define FUNCTION_BOUNDARY 32
-#define BIGGEST_ALIGNMENT 32
-
-/* Make strings word-aligned so strcpy from constants will be faster. */
-#define CONSTANT_ALIGNMENT(EXP, ALIGN) \
- (TREE_CODE (EXP) == STRING_CST \
- && (ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN))
-
-#define EMPTY_FIELD_BOUNDARY 32
-
-#define STRUCTURE_SIZE_BOUNDARY 32
-
-/* Used when parsing command line option -mstructure_size_boundary. */
-extern char * structure_size_string;
-
-#define STRICT_ALIGNMENT 1
-
-#define TARGET_FLOAT_FORMAT IEEE_FLOAT_FORMAT
-
-
-/* Layout of Source Language Data Types */
-
-#define DEFAULT_SIGNED_CHAR 0
-
-#define TARGET_BELL 007
-#define TARGET_BS 010
-#define TARGET_TAB 011
-#define TARGET_NEWLINE 012
-#define TARGET_VT 013
-#define TARGET_FF 014
-#define TARGET_CR 015
-
-
-/* Register Usage */
-
-/* Note there are 16 hard registers on the Thumb. We invent a 17th register
- which is assigned to ARG_POINTER_REGNUM, but this is later removed by
- elimination passes in the compiler. */
-#define FIRST_PSEUDO_REGISTER 17
-
-/* ??? This is questionable. */
-#define FIXED_REGISTERS \
-{ \
- 0,0,0,0, \
- 0,0,0,0, \
- 0,0,0,1, \
- 0,1,1,1,1 \
-}
-
-/* ??? This is questionable. */
-#define CALL_USED_REGISTERS \
-{ \
- 1,1,1,1, \
- 0,0,0,0, \
- 0,0,0,1, \
- 1,1,1,1,1 \
-}
-
-#define HARD_REGNO_NREGS(REGNO,MODE) \
- ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) \
- / UNITS_PER_WORD)
-
-/* ??? Probably should only allow DImode/DFmode in even numbered registers. */
-#define HARD_REGNO_MODE_OK(REGNO,MODE) ((GET_MODE_SIZE (MODE) > UNITS_PER_WORD) ? (REGNO < 7) : 1)
-
-#define MODES_TIEABLE_P(MODE1,MODE2) 1
-
-/* The NOARG_LO_REGS class is the set of LO_REGS that are not used for passing
- arguments to functions. These are the registers that are available for
- spilling during reload. The code in reload1.c:init_reload() will detect this
- class and place it into 'reload_address_base_reg_class'. */
-
-enum reg_class
-{
- NO_REGS,
- NONARG_LO_REGS,
- LO_REGS,
- STACK_REG,
- BASE_REGS,
- HI_REGS,
- ALL_REGS,
- LIM_REG_CLASSES
-};
-
-#define GENERAL_REGS ALL_REGS
-
-#define N_REG_CLASSES (int) LIM_REG_CLASSES
-
-#define REG_CLASS_NAMES \
-{ \
- "NO_REGS", \
- "NONARG_LO_REGS", \
- "LO_REGS", \
- "STACK_REG", \
- "BASE_REGS", \
- "HI_REGS", \
- "ALL_REGS" \
-}
-
-#define REG_CLASS_CONTENTS \
-{ \
- 0x00000, \
- 0x000f0, \
- 0x000ff, \
- 0x02000, \
- 0x020ff, \
- 0x0ff00, \
- 0x1ffff, \
-}
-
-#define REGNO_REG_CLASS(REGNO) \
- ((REGNO) == STACK_POINTER_REGNUM ? STACK_REG \
- : (REGNO) < 8 ? ((REGNO) < 4 ? LO_REGS \
- : NONARG_LO_REGS) \
- : HI_REGS)
-
-#define BASE_REG_CLASS BASE_REGS
-
-#define MODE_BASE_REG_CLASS(MODE) \
- ((MODE) != QImode && (MODE) != HImode \
- ? BASE_REGS : LO_REGS)
-
-#define INDEX_REG_CLASS LO_REGS
-
-/* When SMALL_REGISTER_CLASSES is nonzero, the compiler allows
- registers explicitly used in the rtl to be used as spill registers
- but prevents the compiler from extending the lifetime of these
- registers. */
-
-#define SMALL_REGISTER_CLASSES 1
-
-#define REG_CLASS_FROM_LETTER(C) \
- ((C) == 'l' ? LO_REGS \
- : (C) == 'h' ? HI_REGS \
- : (C) == 'b' ? BASE_REGS \
- : (C) == 'k' ? STACK_REG \
- : NO_REGS)
-
-#define REGNO_OK_FOR_BASE_P(REGNO) \
- ((REGNO) < 8 \
- || (REGNO) == STACK_POINTER_REGNUM \
- || (unsigned) reg_renumber[REGNO] < 8 \
- || (unsigned) reg_renumber[REGNO] == STACK_POINTER_REGNUM)
-
-#define REGNO_MODE_OK_FOR_BASE_P(REGNO, MODE) \
- ((REGNO) < 8 \
- || (unsigned) reg_renumber[REGNO] < 8 \
- || (GET_MODE_SIZE (MODE) >= 4 \
- && ((REGNO) == STACK_POINTER_REGNUM \
- || (unsigned) reg_renumber[REGNO] == STACK_POINTER_REGNUM)))
-
-#define REGNO_OK_FOR_INDEX_P(REGNO) \
- ((REGNO) < 8 \
- || (unsigned) reg_renumber[REGNO] < 8)
-
-/* ??? This looks suspiciously wrong. */
-/* We need to leave BASE_REGS reloads alone, in order to avoid caller_save
- lossage. Caller_saves requests a BASE_REGS reload (caller_save_spill_class)
- and then later we verify that one was allocated. If PREFERRED_RELOAD_CLASS
- says to allocate a LO_REGS spill instead, then this mismatch gives an
- abort. Alternatively, this could be fixed by modifying BASE_REG_CLASS
- to be LO_REGS instead of BASE_REGS. It is not clear what affect this
- change would have. */
-/* ??? This looks even more suspiciously wrong. PREFERRED_RELOAD_CLASS
- must always return a strict subset of the input class. Just blindly
- returning LO_REGS is safe only if the input class is a superset of LO_REGS,
- but there is no check for this. Added another exception for NONARG_LO_REGS
- because it is not a superset of LO_REGS. */
-/* ??? We now use NONARG_LO_REGS for caller_save_spill_class, so the
- comments about BASE_REGS are now obsolete. */
-#define PREFERRED_RELOAD_CLASS(X,CLASS) \
- ((CLASS) == BASE_REGS || (CLASS) == NONARG_LO_REGS ? (CLASS) \
- : LO_REGS)
-/*
- ((CONSTANT_P ((X)) && GET_CODE ((X)) != CONST_INT \
- && ! CONSTANT_POOL_ADDRESS_P((X))) ? NO_REGS \
- : (GET_CODE ((X)) == CONST_INT \
- && (unsigned HOST_WIDE_INT) INTVAL ((X)) > 255) ? NO_REGS \
- : LO_REGS) */
-
-/* Must leave BASE_REGS and NONARG_LO_REGS reloads alone, see comment
- above. */
-#define SECONDARY_RELOAD_CLASS(CLASS,MODE,X) \
- ((CLASS) != LO_REGS && (CLASS) != BASE_REGS && (CLASS) != NONARG_LO_REGS \
- ? ((true_regnum (X) == -1 ? LO_REGS \
- : (true_regnum (X) + HARD_REGNO_NREGS (0, MODE) > 8) ? LO_REGS \
- : NO_REGS)) \
- : NO_REGS)
-
-#define CLASS_MAX_NREGS(CLASS,MODE) HARD_REGNO_NREGS(0,(MODE))
-
-int thumb_shiftable_const ();
-
-#define CONST_OK_FOR_LETTER_P(VAL,C) \
- ((C) == 'I' ? (unsigned HOST_WIDE_INT) (VAL) < 256 \
- : (C) == 'J' ? (VAL) > -256 && (VAL) <= 0 \
- : (C) == 'K' ? thumb_shiftable_const (VAL) \
- : (C) == 'L' ? (VAL) > -8 && (VAL) < 8 \
- : (C) == 'M' ? ((unsigned HOST_WIDE_INT) (VAL) < 1024 \
- && ((VAL) & 3) == 0) \
- : (C) == 'N' ? ((unsigned HOST_WIDE_INT) (VAL) < 32) \
- : (C) == 'O' ? ((VAL) >= -508 && (VAL) <= 508) \
- : 0)
-
-#define CONST_DOUBLE_OK_FOR_LETTER_P(VAL,C) 0
-
-#define EXTRA_CONSTRAINT(X,C) \
- ((C) == 'Q' ? (GET_CODE (X) == MEM \
- && GET_CODE (XEXP (X, 0)) == LABEL_REF) : 0)
-
-/* Stack Layout and Calling Conventions */
-
-#define STACK_GROWS_DOWNWARD 1
-
-/* #define FRAME_GROWS_DOWNWARD 1 */
-
-/* #define ARGS_GROW_DOWNWARD 1 */
-
-#define STARTING_FRAME_OFFSET 0
-
-#define FIRST_PARM_OFFSET(FNDECL) 0
-
-/* Registers that address the stack frame */
-
-#define STACK_POINTER_REGNUM 13 /* Defined by the TPCS. */
-
-#define FRAME_POINTER_REGNUM 7 /* TPCS defines this as 11 but it does not really mean it. */
-
-#define ARG_POINTER_REGNUM 16 /* A fake hard register that is eliminated later on. */
-
-#define STATIC_CHAIN_REGNUM 9
-
-#define FRAME_POINTER_REQUIRED 0
-
-#define ELIMINABLE_REGS \
-{{ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
- {ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM}, \
- {FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}}
-
-/* On the Thumb we always want to perform the eliminations as we
- actually only have one real register pointing to the stashed
- variables: the stack pointer, and we never use the frame pointer. */
-#define CAN_ELIMINATE(FROM,TO) 1
-
-/* Note: This macro must match the code in thumb_function_prologue() in thumb.c. */
-#define INITIAL_ELIMINATION_OFFSET(FROM,TO,OFFSET) \
-{ \
- (OFFSET) = 0; \
- if ((FROM) == ARG_POINTER_REGNUM) \
- { \
- int count_regs = 0; \
- int regno; \
- (OFFSET) += get_frame_size (); \
- for (regno = 8; regno < 13; regno++) \
- if (regs_ever_live[regno] && ! call_used_regs[regno]) \
- count_regs++; \
- if (count_regs) \
- (OFFSET) += 4 * count_regs; \
- count_regs = 0; \
- for (regno = 0; regno < 8; regno++) \
- if (regs_ever_live[regno] && ! call_used_regs[regno]) \
- count_regs++; \
- if (count_regs || ! leaf_function_p () || far_jump_used_p()) \
- (OFFSET) += 4 * (count_regs + 1); \
- if (TARGET_BACKTRACE) { \
- if ((count_regs & 0xFF) == 0 && (regs_ever_live[3] != 0)) \
- (OFFSET) += 20; \
- else \
- (OFFSET) += 16; } \
- } \
- if ((TO) == STACK_POINTER_REGNUM) \
- (OFFSET) += current_function_outgoing_args_size; \
-}
-
-/* Passing Arguments on the stack */
-
-#define PROMOTE_PROTOTYPES 1
-
-#define ACCUMULATE_OUTGOING_ARGS 1
-
-#define RETURN_POPS_ARGS(FUNDECL,FUNTYPE,SIZE) 0
-
-#define FUNCTION_ARG(CUM,MODE,TYPE,NAMED) \
- ((NAMED) ? ((CUM) >= 16 ? 0 : gen_rtx (REG, (MODE), (CUM) / 4)) \
- : 0)
-
-#define FUNCTION_ARG_PARTIAL_NREGS(CUM,MODE,TYPE,NAMED) \
- (((CUM) < 16 && (CUM) + (((MODE) == BLKmode) \
- ? int_size_in_bytes (TYPE) \
- : HARD_REGNO_NREGS (0, (MODE)) * 4) > 16) \
- ? 4 - (CUM) / 4 : 0)
-
-#define CUMULATIVE_ARGS int
-
-#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT) \
- ((CUM) = ((FNTYPE) && aggregate_value_p (TREE_TYPE (FNTYPE))) ? 4 : 0)
-
-#define FUNCTION_ARG_ADVANCE(CUM,MODE,TYPE,NAMED) \
- (CUM) += ((((MODE) == BLKmode) \
- ? int_size_in_bytes (TYPE) \
- : GET_MODE_SIZE (MODE)) + 3) & ~3
-
-#define FUNCTION_ARG_REGNO_P(REGNO) \
- ((REGNO) >=0 && (REGNO) <= 3)
-
-#define FUNCTION_VALUE(VALTYPE,FUNC) gen_rtx (REG, TYPE_MODE (VALTYPE), 0)
-
-#define LIBCALL_VALUE(MODE) gen_rtx (REG, (MODE), 0)
-
-#define FUNCTION_VALUE_REGNO_P(REGNO) ((REGNO) == 0)
-
- /* How large values are returned */
-/* A C expression which can inhibit the returning of certain function values
- in registers, based on the type of value. */
-#define RETURN_IN_MEMORY(TYPE) thumb_return_in_memory (TYPE)
-
-/* Define DEFAULT_PCC_STRUCT_RETURN to 1 if all structure and union return
- values must be in memory. On the ARM, they need only do so if larger
- than a word, or if they contain elements offset from zero in the struct. */
-#define DEFAULT_PCC_STRUCT_RETURN 0
-
-
-#define STRUCT_VALUE_REGNUM 0
-
-#define FUNCTION_PROLOGUE(FILE,SIZE) thumb_function_prologue((FILE),(SIZE))
-
-#define FUNCTION_EPILOGUE(FILE,SIZE) thumb_function_epilogue((FILE),(SIZE))
-
-/* Implementing the Varargs Macros */
-
-#define SETUP_INCOMING_VARARGS(CUM,MODE,TYPE,PRETEND_SIZE,NO_RTL) \
-{ \
- extern int current_function_anonymous_args; \
- current_function_anonymous_args = 1; \
- if ((CUM) < 16) \
- (PRETEND_SIZE) = 16 - (CUM); \
-}
-
-/* Trampolines for nested functions */
-
-/* Output assembler code for a block containing the constant parts of
- a trampoline, leaving space for the variable parts.
-
- On the Thumb we always switch into ARM mode to execute the trampoline.
- Why - because it is easier. This code will always be branched to via
- a BX instruction and since the compiler magically generates the address
- of the function the linker has no opportunity to ensure that the
- bottom bit is set. Thus the processor will be in ARM mode when it
- reaches this code. So we duplicate the ARM trampoline code and add
- a switch into Thumb mode as well.
-
- On the ARM, (if r8 is the static chain regnum, and remembering that
- referencing pc adds an offset of 8) the trampoline looks like:
- ldr r8, [pc, #0]
- ldr pc, [pc]
- .word static chain value
- .word function's address
- ??? FIXME: When the trampoline returns, r8 will be clobbered. */
-#define TRAMPOLINE_TEMPLATE(FILE) \
-{ \
- fprintf ((FILE), "\t.code 32\n"); \
- fprintf ((FILE), ".Ltrampoline_start:\n"); \
- fprintf ((FILE), "\tldr\t%s, [%spc, #8]\n", \
- reg_names[STATIC_CHAIN_REGNUM], REGISTER_PREFIX); \
- fprintf ((FILE), "\tldr\t%sip, [%spc, #8]\n", \
- REGISTER_PREFIX, REGISTER_PREFIX); \
- fprintf ((FILE), "\torr\t%sip, %sip, #1\n", \
- REGISTER_PREFIX, REGISTER_PREFIX); \
- fprintf ((FILE), "\tbx\t%sip\n", REGISTER_PREFIX); \
- fprintf ((FILE), "\t.word\t0\n"); \
- fprintf ((FILE), "\t.word\t0\n"); \
- fprintf ((FILE), "\t.code 16\n"); \
-}
-
-/* Length in units of the trampoline for entering a nested function. */
-#define TRAMPOLINE_SIZE 24
-
-/* Alignment required for a trampoline in units. */
-#define TRAMPOLINE_ALIGN 4
-
-#define INITIALIZE_TRAMPOLINE(ADDR,FNADDR,CHAIN) \
-{ \
- emit_move_insn (gen_rtx (MEM, SImode, plus_constant ((ADDR), 16)), \
- (CHAIN)); \
- emit_move_insn (gen_rtx (MEM, SImode, plus_constant ((ADDR), 20)), \
- (FNADDR)); \
-}
-
-
-/* Implicit Calls to Library Routines */
-
-#define TARGET_MEM_FUNCTIONS 1
-
-#define OVERRIDE_OPTIONS thumb_override_options ()
-
-
-/* Addressing Modes */
-
-#define HAVE_POST_INCREMENT 1
-
-#define CONSTANT_ADDRESS_P(X) \
- (GET_CODE (X) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (X))
-
-#define MAX_REGS_PER_ADDRESS 2
-
-#ifdef REG_OK_STRICT
-
-#define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P (REGNO (X))
-#define REG_OK_FOR_INDEX_P(X) REGNO_OK_FOR_INDEX_P (REGNO (X))
-
-#define REG_MODE_OK_FOR_BASE_P(X,MODE) \
- REGNO_MODE_OK_FOR_BASE_P (REGNO (X), MODE)
-
-#else /* REG_OK_STRICT */
-
-#define REG_OK_FOR_BASE_P(X) \
- (REGNO (X) < 8 || REGNO (X) == STACK_POINTER_REGNUM \
- || (X) == arg_pointer_rtx \
- || REGNO (X) >= FIRST_PSEUDO_REGISTER)
-
-#define REG_MODE_OK_FOR_BASE_P(X,MODE) \
- (REGNO (X) < 8 \
- || REGNO (X) >= FIRST_PSEUDO_REGISTER \
- || (GET_MODE_SIZE (MODE) >= 4 \
- && (REGNO (X) == STACK_POINTER_REGNUM \
- || (X) == arg_pointer_rtx)))
-
-#define REG_OK_FOR_INDEX_P(X) \
- (REGNO (X) < 8 \
- || REGNO (X) >= FIRST_PSEUDO_REGISTER)
-
-#endif /* REG_OK_STRICT */
-
-/* In a REG+REG address, both must be INDEX registers. */
-#define REG_OK_FOR_INDEXED_BASE_P(X) REG_OK_FOR_INDEX_P(X)
-
-#define LEGITIMATE_OFFSET(MODE,VAL) \
-(GET_MODE_SIZE (MODE) == 1 ? ((unsigned HOST_WIDE_INT) (VAL) < 32) \
- : GET_MODE_SIZE (MODE) == 2 ? ((unsigned HOST_WIDE_INT) (VAL) < 64 \
- && ((VAL) & 1) == 0) \
- : ((VAL) >= 0 && ((VAL) + GET_MODE_SIZE (MODE)) <= 128 \
- && ((VAL) & 3) == 0))
-
-/* The AP may be eliminated to either the SP or the FP, so we use the
- least common denominator, e.g. SImode, and offsets from 0 to 64. */
-
-/* ??? Verify whether the above is the right approach. */
-
-/* ??? Also, the FP may be eliminated to the SP, so perhaps that
- needs special handling also. */
-
-/* ??? Look at how the mips16 port solves this problem. It probably uses
- better ways to solve some of these problems. */
-
-/* Although it is not incorrect, we don't accept QImode and HImode
- addresses based on the frame pointer or arg pointer until the reload pass starts.
- This is so that eliminating such addresses into stack based ones
- won't produce impossible code. */
-#define GO_IF_LEGITIMATE_ADDRESS(MODE,X,WIN) \
-{ \
- /* ??? Not clear if this is right. Experiment. */ \
- if (GET_MODE_SIZE (MODE) < 4 \
- && ! (reload_in_progress || reload_completed) \
- && (reg_mentioned_p (frame_pointer_rtx, X) \
- || reg_mentioned_p (arg_pointer_rtx, X) \
- || reg_mentioned_p (virtual_incoming_args_rtx, X) \
- || reg_mentioned_p (virtual_outgoing_args_rtx, X) \
- || reg_mentioned_p (virtual_stack_dynamic_rtx, X) \
- || reg_mentioned_p (virtual_stack_vars_rtx, X))) \
- ; \
- /* Accept any base register. SP only in SImode or larger. */ \
- else if (GET_CODE (X) == REG && REG_MODE_OK_FOR_BASE_P(X, MODE)) \
- goto WIN; \
- /* This is PC relative data before MACHINE_DEPENDENT_REORG runs. */ \
- else if (GET_MODE_SIZE (MODE) >= 4 && CONSTANT_P (X) \
- && CONSTANT_POOL_ADDRESS_P (X)) \
- goto WIN; \
- /* This is PC relative data after MACHINE_DEPENDENT_REORG runs. */ \
- else if (GET_MODE_SIZE (MODE) >= 4 && reload_completed \
- && (GET_CODE (X) == LABEL_REF \
- || (GET_CODE (X) == CONST \
- && GET_CODE (XEXP (X, 0)) == PLUS \
- && GET_CODE (XEXP (XEXP (X, 0), 0)) == LABEL_REF \
- && GET_CODE (XEXP (XEXP (X, 0), 1)) == CONST_INT))) \
- goto WIN; \
- /* Post-inc indexing only supported for SImode and larger. */ \
- else if (GET_CODE (X) == POST_INC && GET_MODE_SIZE (MODE) >= 4 \
- && GET_CODE (XEXP (X, 0)) == REG \
- && REG_OK_FOR_INDEX_P (XEXP (X, 0))) \
- goto WIN; \
- else if (GET_CODE (X) == PLUS) \
- { \
- /* REG+REG address can be any two index registers. */ \
- /* ??? REG+REG addresses have been completely disabled before \
- reload completes, because we do not have enough available \
- reload registers. We only have 3 guaranteed reload registers \
- (NONARG_LO_REGS - the frame pointer), but we need at least 4 \
- to support REG+REG addresses. We have left them enabled after \
- reload completes, in the hope that reload_cse_regs and related \
- routines will be able to create them after the fact. It is \
- probably possible to support REG+REG addresses with additional \
- reload work, but I do not not have enough time to attempt such \
- a change at this time. */ \
- /* ??? Normally checking the mode here is wrong, since it isn't \
- impossible to use REG+REG with DFmode. However, the movdf \
- pattern requires offsettable addresses, and REG+REG is not \
- offsettable, so it must be rejected somehow. Trying to use \
- 'o' fails, because offsettable_address_p does a QImode check. \
- QImode is not valid for stack addresses, and has a smaller \
- range for non-stack bases, and this causes valid addresses \
- to be rejected. So we just eliminate REG+REG here by checking \
- the mode. */ \
- /* We also disallow FRAME+REG addressing since we know that FRAME \
- will be replaced with STACK, and SP relative addressing only \
- permits SP+OFFSET. */ \
- if (GET_MODE_SIZE (MODE) <= 4 \
- /* ??? See comment above. */ \
- && reload_completed \
- && GET_CODE (XEXP (X, 0)) == REG \
- && GET_CODE (XEXP (X, 1)) == REG \
- && XEXP (X, 0) != frame_pointer_rtx \
- && XEXP (X, 1) != frame_pointer_rtx \
- && XEXP (X, 0) != virtual_stack_vars_rtx \
- && XEXP (X, 1) != virtual_stack_vars_rtx \
- && REG_OK_FOR_INDEX_P (XEXP (X, 0)) \
- && REG_OK_FOR_INDEX_P (XEXP (X, 1))) \
- goto WIN; \
- /* REG+const has 5-7 bit offset for non-SP registers. */ \
- else if (GET_CODE (XEXP (X, 0)) == REG \
- && (REG_OK_FOR_INDEX_P (XEXP (X, 0)) \
- || XEXP (X, 0) == arg_pointer_rtx) \
- && GET_CODE (XEXP (X, 1)) == CONST_INT \
- && LEGITIMATE_OFFSET (MODE, INTVAL (XEXP (X, 1)))) \
- goto WIN; \
- /* REG+const has 10 bit offset for SP, but only SImode and \
- larger is supported. */ \
- /* ??? Should probably check for DI/DFmode overflow here \
- just like GO_IF_LEGITIMATE_OFFSET does. */ \
- else if (GET_CODE (XEXP (X, 0)) == REG \
- && REGNO (XEXP (X, 0)) == STACK_POINTER_REGNUM \
- && GET_MODE_SIZE (MODE) >= 4 \
- && GET_CODE (XEXP (X, 1)) == CONST_INT \
- && (unsigned HOST_WIDE_INT) INTVAL (XEXP (X, 1)) < 1024 \
- && (INTVAL (XEXP (X, 1)) & 3) == 0) \
- goto WIN; \
- } \
-}
-
-/* ??? If an HImode FP+large_offset address is converted to an HImode
- SP+large_offset address, then reload won't know how to fix it. It sees
- only that SP isn't valid for HImode, and so reloads the SP into an index
- register, but the resulting address is still invalid because the offset
- is too big. We fix it here instead by reloading the entire address. */
-/* We could probably achieve better results by defining PROMOTE_MODE to help
- cope with the variances between the Thumb's signed and unsigned byte and
- halfword load instructions. */
-#define LEGITIMIZE_RELOAD_ADDRESS(X,MODE,OPNUM,TYPE,IND_LEVELS,WIN) \
-{ \
- if (GET_CODE (X) == PLUS \
- && GET_MODE_SIZE (MODE) < 4 \
- && GET_CODE (XEXP (X, 0)) == REG \
- && XEXP (X, 0) == stack_pointer_rtx \
- && GET_CODE (XEXP (X, 1)) == CONST_INT \
- && ! LEGITIMATE_OFFSET (MODE, INTVAL (XEXP (X, 1)))) \
- { \
- rtx orig_X = X; \
- X = copy_rtx (X); \
- push_reload (orig_X, NULL_RTX, &X, NULL_PTR, \
- BASE_REG_CLASS, \
- Pmode, VOIDmode, 0, 0, OPNUM, TYPE); \
- goto WIN; \
- } \
-}
-
-#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR,LABEL)
-
-#define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN)
-
-#define LEGITIMATE_CONSTANT_P(X) \
- (GET_CODE (X) == CONST_INT \
- || GET_CODE (X) == CONST_DOUBLE \
- || CONSTANT_ADDRESS_P (X))
-
-
-/* Condition Code Status */
-
-#define NOTICE_UPDATE_CC(EXP,INSN) \
-{ \
- if (get_attr_conds ((INSN)) != CONDS_UNCHANGED) \
- CC_STATUS_INIT; \
-}
-
-
-/* Describing Relative Costs of Operations */
-
-#define SLOW_BYTE_ACCESS 0
-
-#define SLOW_UNALIGNED_ACCESS 1
-
-#define NO_FUNCTION_CSE 1
-
-#define NO_RECURSIVE_FUNCTION_CSE 1
-
-#define REGISTER_MOVE_COST(FROM,TO) \
- (((FROM) == HI_REGS || (TO) == HI_REGS) ? 4 : 2)
-
-#define MEMORY_MOVE_COST(M,CLASS,IN) \
- ((GET_MODE_SIZE(M) < 4 ? 8 : 2 * GET_MODE_SIZE(M)) * (CLASS == LO_REGS ? 1 : 2))
-
-/* This will allow better space optimization when compiling with -O */
-#define BRANCH_COST (optimize > 1 ? 1 : 0)
-
-#define RTX_COSTS(X,CODE,OUTER) \
- case MULT: \
- if (GET_CODE (XEXP (X, 1)) == CONST_INT) \
- { \
- int cycles = 0; \
- unsigned HOST_WIDE_INT i = INTVAL (XEXP (X, 1)); \
- while (i) \
- { \
- i >>= 2; \
- cycles++; \
- } \
- return COSTS_N_INSNS (2) + cycles; \
- } \
- return COSTS_N_INSNS (1) + 16; \
- case ASHIFT: case ASHIFTRT: case LSHIFTRT: case ROTATERT: \
- case PLUS: case MINUS: case COMPARE: case NEG: case NOT: \
- return COSTS_N_INSNS (1); \
- case SET: \
- return (COSTS_N_INSNS (1) \
- + 4 * ((GET_CODE (SET_SRC (X)) == MEM) \
- + GET_CODE (SET_DEST (X)) == MEM))
-
-#define CONST_COSTS(X,CODE,OUTER) \
- case CONST_INT: \
- if ((OUTER) == SET) \
- { \
- if ((unsigned HOST_WIDE_INT) INTVAL (X) < 256) \
- return 0; \
- if (thumb_shiftable_const (INTVAL (X))) \
- return COSTS_N_INSNS (2); \
- return COSTS_N_INSNS (3); \
- } \
- else if (OUTER == PLUS \
- && INTVAL (X) < 256 && INTVAL (X) > -256) \
- return 0; \
- else if (OUTER == COMPARE \
- && (unsigned HOST_WIDE_INT) INTVAL (X) < 256) \
- return 0; \
- else if (OUTER == ASHIFT || OUTER == ASHIFTRT \
- || OUTER == LSHIFTRT) \
- return 0; \
- return COSTS_N_INSNS (2); \
- case CONST: \
- case CONST_DOUBLE: \
- case LABEL_REF: \
- case SYMBOL_REF: \
- return COSTS_N_INSNS(3);
-
-#define ADDRESS_COST(X) \
- ((GET_CODE (X) == REG \
- || (GET_CODE (X) == PLUS && GET_CODE (XEXP (X, 0)) == REG \
- && GET_CODE (XEXP (X, 1)) == CONST_INT)) \
- ? 1 : 2)
-
-
-/* Position Independent Code */
-
-#define PRINT_OPERAND(STREAM,X,CODE) \
- thumb_print_operand((STREAM), (X), (CODE))
-
-#define PRINT_OPERAND_ADDRESS(STREAM,X) \
-{ \
- if (GET_CODE ((X)) == REG) \
- fprintf ((STREAM), "[%s]", reg_names[REGNO ((X))]); \
- else if (GET_CODE ((X)) == POST_INC) \
- fprintf ((STREAM), "%s!", reg_names[REGNO (XEXP (X, 0))]); \
- else if (GET_CODE ((X)) == PLUS) \
- { \
- if (GET_CODE (XEXP ((X), 1)) == CONST_INT) \
- fprintf ((STREAM), "[%s, #%d]", \
- reg_names[REGNO (XEXP ((X), 0))], \
- (int) INTVAL (XEXP ((X), 1))); \
- else \
- fprintf ((STREAM), "[%s, %s]", \
- reg_names[REGNO (XEXP ((X), 0))], \
- reg_names[REGNO (XEXP ((X), 1))]); \
- } \
- else \
- output_addr_const ((STREAM), (X)); \
-}
-
-#define PRINT_OPERAND_PUNCT_VALID_P(CODE) ((CODE) == '@' || ((CODE) == '_'))
-
-/* Emit a special directive when defining a function name.
- This is used by the assembler to assit with interworking. */
-#define ASM_DECLARE_FUNCTION_NAME(file, name, 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)
-
-#define ASM_OUTPUT_REG_PUSH(STREAM,REGNO) \
- asm_fprintf ((STREAM), "\tpush {%R%s}\n", reg_names[(REGNO)])
-
-#define ASM_OUTPUT_REG_POP(STREAM,REGNO) \
- fprintf ((STREAM), "\tpop {%R%s}\n", reg_names[(REGNO)])
-
-#define FINAL_PRESCAN_INSN(INSN,OPVEC,NOPERANDS) \
- final_prescan_insn((INSN))
-
-/* Controlling Debugging Information Format */
-#define DBX_REGISTER_NUMBER(REGNO) (REGNO)
-
-/* Specific options for DBX Output */
-
-#define DBX_DEBUGGING_INFO 1
-
-#define DEFAULT_GDB_EXTENSIONS 1
-
-
-/* Cross Compilation and Floating Point */
-
-#define REAL_ARITHMETIC
-
-
-/* Miscellaneous Parameters */
-
-#define PREDICATE_CODES \
- {"thumb_cmp_operand", {SUBREG, REG, CONST_INT}},
-
-#define CASE_VECTOR_MODE Pmode
-
-#define WORD_REGISTER_OPERATIONS
-
-#define LOAD_EXTEND_OP(MODE) ZERO_EXTEND
-
-#define IMPLICIT_FIX_EXPR FIX_ROUND_EXPR
-
-#define EASY_DIV_EXPR TRUNC_DIV_EXPR
-
-#define MOVE_MAX 4
-
-#define TRULY_NOOP_TRUNCATION(OUTPREC,INPREC) 1
-
-#define STORE_FLAG_VALUE 1
-
-#define Pmode SImode
-
-#define FUNCTION_MODE SImode
-
-#define DOLLARS_IN_IDENTIFIERS 0
-
-#define NO_DOLLAR_IN_LABEL 1
-
-#define HAVE_ATEXIT
-
-/* The literal pool needs to reside in the text area due to the
- limited PC addressing range: */
-#define MACHINE_DEPENDENT_REORG(INSN) thumb_reorg ((INSN))
-
-
-/* Options specific to Thumb */
-
-/* True if a return instruction can be used in this function. */
-int thumb_trivial_epilogue ();
-#define USE_RETURN (reload_completed && thumb_trivial_epilogue ())
-
-extern char * thumb_unexpanded_epilogue ();
-extern char * output_move_mem_multiple ();
-extern char * thumb_load_double_from_address ();
-extern char * output_return ();
-extern int far_jump_used_p();
-extern int is_called_in_ARM_mode ();
-
diff --git a/gcc/config/arm/thumb.md.orig b/gcc/config/arm/thumb.md.orig
deleted file mode 100755
index dd86008..0000000
--- a/gcc/config/arm/thumb.md.orig
+++ /dev/null
@@ -1,1174 +0,0 @@
-;; thumb.md Machine description for ARM/Thumb processors
-;; Copyright (C) 1996, 1997, 1998, 2002 Free Software Foundation, Inc.
-;; The basis of this contribution was generated by
-;; Richard Earnshaw, Advanced RISC Machines Ltd
-
-;; 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.
-
-;; LENGTH of an instruction is 2 bytes
-(define_attr "length" "" (const_int 2))
-
-;; CONDS is set to UNCHANGED when an insn does not affect the condition codes
-;; Most insns change the condition codes
-(define_attr "conds" "changed,unchanged" (const_string "changed"))
-
-;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
-;; distant label.
-(define_attr "far_jump" "yes,no" (const_string "no"))
-
-;; Start with move insns
-
-(define_expand "movsi"
- [(set (match_operand:SI 0 "general_operand" "")
- (match_operand:SI 1 "general_operand" ""))]
- ""
- "
- if (! (reload_in_progress || reload_completed))
- {
- if (GET_CODE (operands[0]) != REG)
- operands[1] = force_reg (SImode, operands[1]);
- }
-")
-
-(define_insn "*movsi_insn"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l,m,*r,*h")
- (match_operand:SI 1 "general_operand" "l,I,J,K,>,l,mi,l,*h,*r"))]
- "register_operand (operands[0], SImode)
- || register_operand (operands[1], SImode)"
- "@
- add\\t%0, %1, #0
- mov\\t%0, %1
- #
- #
- ldmia\\t%1, {%0}
- stmia\\t%0, {%1}
- ldr\\t%0, %1
- str\\t%1, %0
- mov\\t%0, %1
- mov\\t%0, %1"
-[(set_attr "length" "2,2,4,4,2,2,2,2,2,2")])
-
-(define_split
- [(set (match_operand:SI 0 "register_operand" "")
- (match_operand:SI 1 "const_int_operand" ""))]
- "thumb_shiftable_const (INTVAL (operands[1]))"
- [(set (match_dup 0) (match_dup 1))
- (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
- "
-{
- unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
- unsigned HOST_WIDE_INT mask = 0xff;
- int i;
- for (i = 0; i < 25; i++)
- if ((val & (mask << i)) == val)
- break;
-
- if (i == 0)
- FAIL;
-
- operands[1] = GEN_INT (val >> i);
- operands[2] = GEN_INT (i);
-}")
-
-(define_split
- [(set (match_operand:SI 0 "register_operand" "")
- (match_operand:SI 1 "const_int_operand" ""))]
- "INTVAL (operands[1]) < 0 && INTVAL (operands[1]) > -256"
- [(set (match_dup 0) (match_dup 1))
- (set (match_dup 0) (neg:SI (match_dup 0)))]
- "
- operands[1] = GEN_INT (- INTVAL (operands[1]));
-")
-
-;;(define_expand "reload_outsi"
-;; [(set (match_operand:SI 2 "register_operand" "=&l")
-;; (match_operand:SI 1 "register_operand" "h"))
-;; (set (match_operand:SI 0 "reload_memory_operand" "=o")
-;; (match_dup 2))]
-;; ""
-;; "
-;;/* thumb_reload_out_si (operands);
-;; DONE; */
-;;")
-
-(define_expand "movhi"
- [(set (match_operand:HI 0 "general_operand" "")
- (match_operand:HI 1 "general_operand" ""))]
- ""
- "
-{
- if (! (reload_in_progress || reload_completed))
- {
- if (GET_CODE (operands[0]) != REG)
- operands[1] = force_reg (HImode, operands[1]);
-
- /* ??? We shouldn't really get invalid addresses here, but this can
- happen if we are passed a SP (never OK for HImode/QImode) or virtual
- register (rejected by GO_IF_LEGITIMATE_ADDRESS for HImode/QImode)
- relative address. */
- /* ??? This should perhaps be fixed elsewhere, for instance, in
- fixup_stack_1, by checking for other kinds of invalid addresses,
- e.g. a bare reference to a virtual register. This may confuse the
- alpha though, which must handle this case differently. */
- if (GET_CODE (operands[0]) == MEM
- && ! memory_address_p (GET_MODE (operands[0]),
- XEXP (operands[0], 0)))
- {
- rtx temp = copy_to_reg (XEXP (operands[0], 0));
- operands[0] = change_address (operands[0], VOIDmode, temp);
- }
- if (GET_CODE (operands[1]) == MEM
- && ! memory_address_p (GET_MODE (operands[1]),
- XEXP (operands[1], 0)))
- {
- rtx temp = copy_to_reg (XEXP (operands[1], 0));
- operands[1] = change_address (operands[1], VOIDmode, temp);
- }
- }
- /* Handle loading a large integer during reload */
- else if (GET_CODE (operands[1]) == CONST_INT
- && ! CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
- {
- /* Writing a constant to memory needs a scratch, which should
- be handled with SECONDARY_RELOADs. */
- if (GET_CODE (operands[0]) != REG)
- abort ();
-
- operands[0] = gen_rtx (SUBREG, SImode, operands[0], 0);
- emit_insn (gen_movsi (operands[0], operands[1]));
- DONE;
- }
-}")
-
-(define_insn "*movhi_insn"
- [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
- (match_operand:HI 1 "general_operand" "l,m,l,*h,*r,I"))]
- "register_operand (operands[0], HImode)
- || register_operand (operands[1], HImode)"
- "@
- add\\t%0, %1, #0
- ldrh\\t%0, %1
- strh\\t%1, %0
- mov\\t%0, %1
- mov\\t%0, %1
- mov\\t%0, %1")
-
-(define_expand "movqi"
- [(set (match_operand:QI 0 "general_operand" "")
- (match_operand:QI 1 "general_operand" ""))]
- ""
- "
-{
- if (! (reload_in_progress || reload_completed))
- {
- if (GET_CODE (operands[0]) != REG)
- operands[1] = force_reg (QImode, operands[1]);
-
- /* ??? We shouldn't really get invalid addresses here, but this can
- happen if we are passed a SP (never OK for HImode/QImode) or virtual
- register (rejected by GO_IF_LEGITIMATE_ADDRESS for HImode/QImode)
- relative address. */
- /* ??? This should perhaps be fixed elsewhere, for instance, in
- fixup_stack_1, by checking for other kinds of invalid addresses,
- e.g. a bare reference to a virtual register. This may confuse the
- alpha though, which must handle this case differently. */
- if (GET_CODE (operands[0]) == MEM
- && ! memory_address_p (GET_MODE (operands[0]),
- XEXP (operands[0], 0)))
- {
- rtx temp = copy_to_reg (XEXP (operands[0], 0));
- operands[0] = change_address (operands[0], VOIDmode, temp);
- }
- if (GET_CODE (operands[1]) == MEM
- && ! memory_address_p (GET_MODE (operands[1]),
- XEXP (operands[1], 0)))
- {
- rtx temp = copy_to_reg (XEXP (operands[1], 0));
- operands[1] = change_address (operands[1], VOIDmode, temp);
- }
- }
- /* Handle loading a large integer during reload */
- else if (GET_CODE (operands[1]) == CONST_INT
- && ! CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
- {
- /* Writing a constant to memory needs a scratch, which should
- be handled with SECONDARY_RELOADs. */
- if (GET_CODE (operands[0]) != REG)
- abort ();
-
- operands[0] = gen_rtx (SUBREG, SImode, operands[0], 0);
- emit_insn (gen_movsi (operands[0], operands[1]));
- DONE;
- }
-}")
-
-(define_insn "*movqi_insn"
- [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
- (match_operand:QI 1 "general_operand" "l,m,l,*h,*r,I"))]
- "register_operand (operands[0], QImode)
- || register_operand (operands[1], QImode)"
- "@
- add\\t%0, %1, #0
- ldrb\\t%0, %1
- strb\\t%1, %0
- mov\\t%0, %1
- mov\\t%0, %1
- mov\\t%0, %1")
-
-(define_expand "movdi"
- [(set (match_operand:DI 0 "general_operand" "")
- (match_operand:DI 1 "general_operand" ""))]
- ""
- "
- if (! (reload_in_progress || reload_completed))
- {
- if (GET_CODE (operands[0]) != REG)
- operands[1] = force_reg (DImode, operands[1]);
- }
-")
-
-;;; ??? This should have alternatives for constants.
-;;; ??? This was originally identical to the movdf_insn pattern.
-;;; ??? The 'i' constraint looks funny, but it should always be replaced by
-;;; thumb_reorg with a memory reference.
-(define_insn "*movdi_insn"
- [(set (match_operand:DI 0 "general_operand" "=l,l,l,l,>,l,m,*r")
- (match_operand:DI 1 "general_operand" "l,I,J,>,l,mi,l,*r"))]
- "register_operand (operands[0], DImode)
- || register_operand (operands[1], DImode)"
- "*
-{
- switch (which_alternative)
- {
- case 0:
- if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
- return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
- return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
- case 1:
- return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
- case 2:
- operands[1] = GEN_INT (- INTVAL (operands[1]));
- return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
- case 3:
- return \"ldmia\\t%1, {%0, %H0}\";
- case 4:
- return \"stmia\\t%0, {%1, %H1}\";
- case 5:
- return thumb_load_double_from_address (operands);
- case 6:
- operands[2] = gen_rtx (MEM, SImode, plus_constant (XEXP (operands[0], 0), 4));
- output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
- return \"\";
- case 7:
- if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
- return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
- return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
- }
-}"[(set_attr "length" "4,4,6,2,2,6,4,4")])
-
-(define_expand "movdf"
- [(set (match_operand:DF 0 "general_operand" "")
- (match_operand:DF 1 "general_operand" ""))]
- ""
- "
- if (! (reload_in_progress || reload_completed))
- {
- if (GET_CODE (operands[0]) != REG)
- operands[1] = force_reg (DFmode, operands[1]);
- }
-")
-
-;;; ??? This should have alternatives for constants.
-;;; ??? This was originally identical to the movdi_insn pattern.
-;;; ??? The 'F' constraint looks funny, but it should always be replaced by
-;;; thumb_reorg with a memory reference.
-(define_insn "*movdf_insn"
- [(set (match_operand:DF 0 "general_operand" "=l,l,>,l,m,*r")
- (match_operand:DF 1 "general_operand" "l,>,l,mF,l,*r"))]
- "register_operand (operands[0], DFmode)
- || register_operand (operands[1], DFmode)"
- "*
- switch (which_alternative)
- {
- case 0:
- if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
- return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
- return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
- case 1:
- return \"ldmia\\t%1, {%0, %H0}\";
- case 2:
- return \"stmia\\t%0, {%1, %H1}\";
- case 3:
- return thumb_load_double_from_address (operands);
- case 4:
- operands[2] = gen_rtx (MEM, SImode, plus_constant (XEXP (operands[0], 0), 4));
- output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
- return \"\";
- case 5:
- if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
- return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
- return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
- }
-"[(set_attr "length" "4,2,2,6,4,4")])
-
-(define_expand "movsf"
- [(set (match_operand:SF 0 "general_operand" "")
- (match_operand:SF 1 "general_operand" ""))]
- ""
- "
- if (! (reload_in_progress || reload_completed))
- {
- if (GET_CODE (operands[0]) != REG)
- operands[1] = force_reg (SFmode, operands[1]);
- }
-")
-
-;;; ??? This should have alternatives for constants.
-(define_insn "*movsf_insn"
- [(set (match_operand:SF 0 "nonimmediate_operand" "=l,l,>,l,m,*r,*h")
- (match_operand:SF 1 "general_operand" "l,>,l,mF,l,*h,*r"))]
- "register_operand (operands[0], SFmode)
- || register_operand (operands[1], SFmode)"
- "@
- add\\t%0, %1, #0
- ldmia\\t%1, {%0}
- stmia\\t%0, {%1}
- ldr\\t%0, %1
- str\\t%1, %0
- mov\\t%0, %1
- mov\\t%0, %1")
-
-;; Widening move insns
-
-(define_expand "zero_extendhisi2"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
- ""
- "
- if (GET_CODE (operands[1]) != MEM)
- {
- rtx temp = gen_reg_rtx (SImode);
-
- operands[1] = force_reg (HImode, operands[1]);
- operands[1] = gen_lowpart (SImode, operands[1]);
- emit_insn (gen_ashlsi3 (temp, operands[1], GEN_INT (16)));
- emit_insn (gen_lshrsi3 (operands[0], temp, GEN_INT (16)));
- DONE;
- }
-")
-
-(define_insn "*zero_extendhisi2_insn"
- [(set (match_operand:SI 0 "s_register_operand" "=l")
- (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
- ""
- "ldrh\\t%0, %1")
-
-(define_expand "zero_extendqisi2"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
- ""
- "
- if (GET_CODE (operands[1]) != MEM)
- {
- rtx temp = gen_reg_rtx (SImode);
-
- operands[1] = force_reg (QImode, operands[1]);
- operands[1] = gen_lowpart (SImode, operands[1]);
- emit_insn (gen_ashlsi3 (temp, operands[1], GEN_INT (24)));
- emit_insn (gen_lshrsi3 (operands[0], temp, GEN_INT (24)));
- DONE;
- }
-")
-
-(define_insn "*zero_extendqisi2_insn"
- [(set (match_operand:SI 0 "s_register_operand" "=l")
- (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
- ""
- "ldrb\\t%0, %1")
-
-(define_expand "extendhisi2"
- [(parallel [(set (match_operand:SI 0 "s_register_operand" "")
- (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))
- (clobber (match_scratch:SI 2 ""))])]
- ""
- "
- if (GET_CODE (operands[1]) != MEM)
- {
- rtx temp = gen_reg_rtx (SImode);
-
- operands[1] = force_reg (HImode, operands[1]);
- operands[1] = gen_lowpart (SImode, operands[1]);
- emit_insn (gen_ashlsi3 (temp, operands[1], GEN_INT (16)));
- emit_insn (gen_ashrsi3 (operands[0], temp, GEN_INT (16)));
- DONE;
- }
-")
-
-(define_insn "*extendhisi2_insn"
- [(set (match_operand:SI 0 "s_register_operand" "=l")
- (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
- (clobber (match_scratch:SI 2 "=&l"))]
- ""
- "*
-{
- rtx ops[4];
- /* This code used to try to use 'V', and fix the address only if it was
- offsettable, but this fails for e.g. REG+48 because 48 is outside the
- range of QImode offsets, and offsettable_address_p does a QImode
- address check. */
-
- if (GET_CODE (XEXP (operands[1], 0)) == PLUS)
- {
- ops[1] = XEXP (XEXP (operands[1], 0), 0);
- ops[2] = XEXP (XEXP (operands[1], 0), 1);
- }
- else
- {
- ops[1] = XEXP (operands[1], 0);
- ops[2] = const0_rtx;
- }
- if (GET_CODE (ops[2]) == REG)
- return \"ldrsh\\t%0, %1\";
-
- ops[0] = operands[0];
- ops[3] = operands[2];
- output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
- return \"\";
-}"
-[(set_attr "length" "4")])
-
-(define_expand "extendqisi2"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
- ""
- "
- if (GET_CODE (operands[1]) != MEM)
- {
- rtx temp = gen_reg_rtx (SImode);
-
- operands[1] = force_reg (QImode, operands[1]);
- operands[1] = gen_lowpart (SImode, operands[1]);
- emit_insn (gen_ashlsi3 (temp, operands[1], GEN_INT (24)));
- emit_insn (gen_ashrsi3 (operands[0], temp, GEN_INT (24)));
- DONE;
- }
-")
-
-(define_insn "*extendqisi2_insn"
- [(set (match_operand:SI 0 "s_register_operand" "=l,l")
- (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
- ""
- "*
-{
- rtx ops[3];
-
- if (which_alternative == 0)
- return \"ldrsb\\t%0, %1\";
- ops[0] = operands[0];
- if (GET_CODE (XEXP (operands[1], 0)) == PLUS)
- {
- ops[1] = XEXP (XEXP (operands[1], 0), 0);
- ops[2] = XEXP (XEXP (operands[1], 0), 1);
-
- if (GET_CODE (ops[1]) == REG && GET_CODE (ops[2]) == REG)
- output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
- else if (GET_CODE (ops[1]) == REG)
- {
- if (REGNO (ops[1]) == REGNO (operands[0]))
- output_asm_insn (\"ldrb\\t%0, [%1, %2]\;lsl\\t%0, %0, #24\;asr\\t%0, %0, #24\", ops);
- else
- output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
- }
- else
- {
- if (REGNO (ops[2]) == REGNO (operands[0]))
- output_asm_insn (\"ldrb\\t%0, [%2, %1]\;lsl\\t%0, %0, #24\;asr\\t%0, %0, #24\", ops);
- else
- output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
- }
- }
- else if (REGNO (operands[0]) == REGNO (XEXP (operands[1], 0)))
- {
- output_asm_insn (\"ldrb\\t%0, [%0, #0]\;lsl\\t%0, %0, #24\;asr\\t%0, %0, #24\", ops);
- }
- else
- {
- ops[1] = XEXP (operands[1], 0);
- ops[2] = const0_rtx;
- output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
- }
- return \"\";
-}"
-[(set_attr "length" "2,6")])
-
-;; We don't really have extzv, but defining this using shifts helps
-;; to reduce register pressure later on.
-
-(define_expand "extzv"
- [(set (match_dup 4)
- (ashift:SI (match_operand:SI 1 "register_operand" "")
- (match_operand:SI 2 "const_int_operand" "")))
- (set (match_operand:SI 0 "register_operand" "")
- (lshiftrt:SI (match_dup 4)
- (match_operand:SI 3 "const_int_operand" "")))]
- ""
- "
-{
- HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
- HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
- operands[3] = GEN_INT (rshift);
- if (lshift == 0)
- {
- emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
- DONE;
- }
- operands[2] = GEN_INT (lshift);
- operands[4] = gen_reg_rtx (SImode);
-}
-")
-
-;; Block-move insns
-
-(define_expand "movstrqi"
- [(match_operand:BLK 0 "general_operand" "")
- (match_operand:BLK 1 "general_operand" "")
- (match_operand:SI 2 "" "")
- (match_operand:SI 3 "const_int_operand" "")]
- ""
- "
- if (INTVAL (operands[3]) != 4
- || GET_CODE (operands[2]) != CONST_INT
- || INTVAL (operands[2]) > 48)
- FAIL;
-
- thumb_expand_movstrqi (operands);
- DONE;
-")
-
-(define_insn "movmem12b"
- [(set (mem:SI (match_operand:SI 0 "register_operand" "+&l"))
- (mem:SI (match_operand:SI 1 "register_operand" "+&l")))
- (set (mem:SI (plus:SI (match_dup 0) (const_int 4)))
- (mem:SI (plus:SI (match_dup 1) (const_int 4))))
- (set (mem:SI (plus:SI (match_dup 0) (const_int 8)))
- (mem:SI (plus:SI (match_dup 1) (const_int 8))))
- (set (match_dup 0) (plus:SI (match_dup 0) (const_int 12)))
- (set (match_dup 1) (plus:SI (match_dup 1) (const_int 12)))
- (clobber (match_scratch:SI 2 "=&l"))
- (clobber (match_scratch:SI 3 "=&l"))
- (clobber (match_scratch:SI 4 "=&l"))]
- ""
- "* return output_move_mem_multiple (3, operands);"
-[(set_attr "length" "4")])
-
-(define_insn "movmem8b"
- [(set (mem:SI (match_operand:SI 0 "register_operand" "+&l"))
- (mem:SI (match_operand:SI 1 "register_operand" "+&l")))
- (set (mem:SI (plus:SI (match_dup 0) (const_int 4)))
- (mem:SI (plus:SI (match_dup 1) (const_int 4))))
- (set (match_dup 0) (plus:SI (match_dup 0) (const_int 8)))
- (set (match_dup 1) (plus:SI (match_dup 1) (const_int 8)))
- (clobber (match_scratch:SI 2 "=&l"))
- (clobber (match_scratch:SI 3 "=&l"))]
- ""
- "* return output_move_mem_multiple (2, operands);"
-[(set_attr "length" "4")])
-
-;; Arithmetic insns
-
-(define_insn "adddi3"
- [(set (match_operand:DI 0 "s_register_operand" "=l")
- (plus:DI (match_operand:DI 1 "s_register_operand" "%0")
- (match_operand:DI 2 "s_register_operand" "l")))]
- ""
- "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
-[(set_attr "conds" "changed")
- (set_attr "length" "8")])
-
-;; register group 'k' is a single register group containing only the stack
-;; register. Trying to reload it will always fail catastrophically,
-;; so never allow those alternatives to match if reloading is needed.
-(define_insn "addsi3"
- [(set (match_operand:SI 0 "s_register_operand" "=l,l,l,*r,*h,l,!k")
- (plus:SI (match_operand:SI 1 "s_register_operand" "%0,0,l,*0,*0,!k,!k")
- (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))]
- ""
- "*
- static char *asms[] =
-{
- \"add\\t%0, %0, %2\",
- \"sub\\t%0, %0, #%n2\",
- \"add\\t%0, %1, %2\",
- \"add\\t%0, %0, %2\",
- \"add\\t%0, %0, %2\",
- \"add\\t%0, %1, %2\",
- \"add\\t%0, %1, %2\"
-};
- if (which_alternative == 2 && GET_CODE (operands[2]) == CONST_INT
- && INTVAL (operands[2]) < 0)
- return \"sub\\t%0, %1, #%n2\";
- return asms[which_alternative];
-")
-
-; reloading and elimination of the frame pointer can sometimes cause this
-; optimization to be missed.
-(define_peephole
- [(set (match_operand:SI 0 "register_operand" "=l")
- (match_operand:SI 1 "const_int_operand" "M"))
- (set (match_dup 0)
- (plus:SI (match_dup 0) (match_operand:SI 2 "register_operand" "k")))]
- "REGNO (operands[2]) == STACK_POINTER_REGNUM
- && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
- && (INTVAL (operands[1]) & 3) == 0"
- "add\\t%0, %2, %1")
-
-(define_insn "subdi3"
- [(set (match_operand:DI 0 "s_register_operand" "=l")
- (minus:DI (match_operand:DI 1 "s_register_operand" "0")
- (match_operand:DI 2 "s_register_operand" "l")))]
- ""
- "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
-[(set_attr "conds" "changed")
- (set_attr "length" "8")])
-
-(define_insn "subsi3"
- [(set (match_operand:SI 0 "s_register_operand" "=l")
- (minus:SI (match_operand:SI 1 "s_register_operand" "l")
- (match_operand:SI 2 "s_register_operand" "l")))]
- ""
- "sub\\t%0, %1, %2")
-
-;; We must ensure that one input matches the output, and that the other input
-;; does not match the output. Using 0 satisfies the first, and using &
-;; satisfies the second. Unfortunately, this fails when operands 1 and 2
-;; are the same, because reload will make operand 0 match operand 1 without
-;; realizing that this conflicts with operand 2. We fix this by adding another
-;; alternative to match this case, and then `reload' it ourselves. This
-;; alternative must come first.
-(define_insn "mulsi3"
- [(set (match_operand:SI 0 "s_register_operand" "=&l,&l,&l")
- (mult:SI (match_operand:SI 1 "s_register_operand" "%l,*h,0")
- (match_operand:SI 2 "s_register_operand" "l,l,l")))]
- ""
- "*
-{
- if (which_alternative < 2)
- return \"mov\\t%0, %1\;mul\\t%0, %0, %2\";
- else
- return \"mul\\t%0, %0, %2\";
-}"
- [(set_attr "length" "4,4,2")])
-
-(define_insn "negsi2"
- [(set (match_operand:SI 0 "s_register_operand" "=l")
- (neg:SI (match_operand:SI 1 "s_register_operand" "l")))]
- ""
- "neg\\t%0, %1")
-
-;; Logical insns
-
-(define_expand "andsi3"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (and:SI (match_operand:SI 1 "s_register_operand" "")
- (match_operand:SI 2 "nonmemory_operand" "")))]
- ""
- "
- if (GET_CODE (operands[2]) != CONST_INT)
- operands[2] = force_reg (SImode, operands[2]);
- else
- {
- int i;
- if (((unsigned HOST_WIDE_INT) ~ INTVAL (operands[2])) < 256)
- {
- operands[2] = force_reg (SImode, GEN_INT (~INTVAL (operands[2])));
- emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
- DONE;
- }
-
- for (i = 9; i <= 31; i++)
- if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
- {
- emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
- const0_rtx));
- DONE;
- }
- else if ((((HOST_WIDE_INT) 1) << i) - 1 == ~ INTVAL (operands[2]))
- {
- rtx shift = GEN_INT (i);
- rtx reg = gen_reg_rtx (SImode);
- emit_insn (gen_lshrsi3 (reg, operands[1], shift));
- emit_insn (gen_ashlsi3 (operands[0], reg, shift));
- DONE;
- }
-
- operands[2] = force_reg (SImode, operands[2]);
- }
-")
-
-(define_insn "*andsi3_insn"
- [(set (match_operand:SI 0 "s_register_operand" "=l")
- (and:SI (match_operand:SI 1 "s_register_operand" "%0")
- (match_operand:SI 2 "s_register_operand" "l")))]
- ""
- "and\\t%0, %0, %2")
-
-(define_insn "bicsi3"
- [(set (match_operand:SI 0 "s_register_operand" "=l")
- (and:SI (not:SI (match_operand:SI 1 "s_register_operand" "l"))
- (match_operand:SI 2 "s_register_operand" "0")))]
- ""
- "bic\\t%0, %0, %1")
-
-(define_insn "iorsi3"
- [(set (match_operand:SI 0 "s_register_operand" "=l")
- (ior:SI (match_operand:SI 1 "s_register_operand" "%0")
- (match_operand:SI 2 "s_register_operand" "l")))]
- ""
- "orr\\t%0, %0, %2")
-
-(define_insn "xorsi3"
- [(set (match_operand:SI 0 "s_register_operand" "=l")
- (xor:SI (match_operand:SI 1 "s_register_operand" "%0")
- (match_operand:SI 2 "s_register_operand" "l")))]
- ""
- "eor\\t%0, %0, %2")
-
-(define_insn "one_cmplsi2"
- [(set (match_operand:SI 0 "s_register_operand" "=l")
- (not:SI (match_operand:SI 1 "s_register_operand" "l")))]
- ""
- "mvn\\t%0, %1")
-
-;; Shift and rotation insns
-
-(define_insn "ashlsi3"
- [(set (match_operand:SI 0 "s_register_operand" "=l,l")
- (ashift:SI (match_operand:SI 1 "s_register_operand" "l,0")
- (match_operand:SI 2 "nonmemory_operand" "N,l")))]
- ""
- "@
- lsl\\t%0, %1, %2
- lsl\\t%0, %0, %2")
-
-(define_insn "ashrsi3"
- [(set (match_operand:SI 0 "s_register_operand" "=l,l")
- (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "l,0")
- (match_operand:SI 2 "nonmemory_operand" "N,l")))]
- ""
- "@
- asr\\t%0, %1, %2
- asr\\t%0, %0, %2")
-
-(define_insn "lshrsi3"
- [(set (match_operand:SI 0 "s_register_operand" "=l,l")
- (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "l,0")
- (match_operand:SI 2 "nonmemory_operand" "N,l")))]
- ""
- "@
- lsr\\t%0, %1, %2
- lsr\\t%0, %0, %2")
-
-(define_insn "rotrsi3"
- [(set (match_operand:SI 0 "s_register_operand" "=l")
- (rotatert:SI (match_operand:SI 1 "s_register_operand" "0")
- (match_operand:SI 2 "s_register_operand" "l")))]
- ""
- "ror\\t%0, %0, %2")
-
-;; Comparison insns
-
-(define_expand "cmpsi"
- [(set (cc0) (compare (match_operand:SI 0 "s_register_operand" "")
- (match_operand:SI 1 "nonmemory_operand" "")))]
- ""
- "
- if (GET_CODE (operands[1]) != REG && GET_CODE (operands[1]) != SUBREG)
- {
- if (GET_CODE (operands[1]) != CONST_INT
- || (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) >= 256)
- {
- if (GET_CODE (operands[1]) != CONST_INT
- || INTVAL (operands[1]) < -255
- || INTVAL (operands[1]) > 0)
- operands[1] = force_reg (SImode, operands[1]);
- else
- {
- operands[1] = force_reg (SImode,
- GEN_INT (- INTVAL (operands[1])));
- emit_insn (gen_cmnsi (operands[0], operands[1]));
- DONE;
- }
- }
- }
-")
-
-(define_insn "*cmpsi_insn"
- [(set (cc0) (compare (match_operand:SI 0 "s_register_operand" "l,*r,*h")
- (match_operand:SI 1 "thumb_cmp_operand" "lI,*h,*r")))]
- ""
- "@
- cmp\\t%0, %1
- cmp\\t%0, %1
- cmp\\t%0, %1")
-
-(define_insn "tstsi"
- [(set (cc0) (match_operand:SI 0 "s_register_operand" "l"))]
- ""
- "cmp\\t%0, #0")
-
-(define_insn "cmnsi"
- [(set (cc0) (compare (match_operand:SI 0 "s_register_operand" "l")
- (neg:SI (match_operand:SI 1 "s_register_operand" "l"))))]
- ""
- "cmn\\t%0, %1")
-
-;; Jump insns
-
-(define_insn "jump"
- [(set (pc) (label_ref (match_operand 0 "" "")))]
- ""
- "*
- if (get_attr_length (insn) == 2)
- return \"b\\t%l0\";
- return \"bl\\t%l0\\t%@ far jump\";
-"[(set (attr "far_jump")
- (if_then_else (eq_attr "length" "4")
- (const_string "yes")
- (const_string "no")))
- (set (attr "length")
- (if_then_else (and (ge (minus (match_dup 0) (pc)) (const_int -2048))
- (le (minus (match_dup 0) (pc)) (const_int 2044)))
- (const_int 2)
- (const_int 4)))])
-
-
-(define_expand "beq"
- [(set (pc) (if_then_else (eq (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_expand "bne"
- [(set (pc) (if_then_else (ne (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_expand "bge"
- [(set (pc) (if_then_else (ge (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_expand "ble"
- [(set (pc) (if_then_else (le (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_expand "bgt"
- [(set (pc) (if_then_else (gt (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_expand "blt"
- [(set (pc) (if_then_else (lt (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_expand "bgeu"
- [(set (pc) (if_then_else (geu (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_expand "bleu"
- [(set (pc) (if_then_else (leu (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_expand "bgtu"
- [(set (pc) (if_then_else (gtu (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_expand "bltu"
- [(set (pc) (if_then_else (ltu (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_insn "*cond_branch"
- [(set (pc) (if_then_else (match_operator 1 "comparison_operator"
- [(cc0) (const_int 0)])
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "*
- switch (get_attr_length (insn))
- {
- case 2: return \"b%d1\\t%l0\\t%@cond_branch\";
- case 4: return \"b%D1\\t.LCB%=\;b\\t%l0\\t%@long jump\\n.LCB%=:\";
- default: return \"b%D1\\t.LCB%=\;bl\\t%l0\\t%@far jump\\n.LCB%=:\";
- }
-"[(set (attr "far_jump")
- (if_then_else (eq_attr "length" "6")
- (const_string "yes")
- (const_string "no")))
- (set (attr "length")
- (if_then_else
- (and (ge (minus (match_dup 0) (pc)) (const_int -252))
- (le (minus (match_dup 0) (pc)) (const_int 254)))
- (const_int 2)
- (if_then_else (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
- (le (minus (match_dup 0) (pc)) (const_int 2044)))
- (const_int 4)
- (const_int 6))))])
-
-(define_insn "*cond_branch_reversed"
- [(set (pc) (if_then_else (match_operator 1 "comparison_operator"
- [(cc0) (const_int 0)])
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
- "*
- switch (get_attr_length (insn))
- {
- case 2: return \"b%D1\\t%l0\\t%@cond_branch_reversed\";
- case 4: return \"b%d1\\t.LCBR%=\;b\\t%l0\\t%@long jump\\n.LCBR%=:\";
- default: return \"b%d1\\t.LCBR%=\;bl\\t%l0\\t%@far jump\\n.LCBR%=:\";
- }
- return \"\";
-"[(set (attr "far_jump")
- (if_then_else (eq_attr "length" "6")
- (const_string "yes")
- (const_string "no")))
- (set (attr "length")
- (if_then_else
- (and (ge (minus (match_dup 0) (pc)) (const_int -252))
- (le (minus (match_dup 0) (pc)) (const_int 254)))
- (const_int 2)
- (if_then_else (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
- (le (minus (match_dup 0) (pc)) (const_int 2044)))
- (const_int 4)
- (const_int 6))))])
-
-(define_insn "indirect_jump"
- [(set (pc) (match_operand:SI 0 "s_register_operand" "l*r"))]
- ""
- "mov\\tpc, %0")
-
-(define_insn "tablejump"
- [(set (pc) (match_operand:SI 0 "s_register_operand" "l*r"))
- (use (label_ref (match_operand 1 "" "")))]
- ""
- "mov\\tpc, %0")
-
-(define_insn "return"
- [(return)]
- "USE_RETURN"
- "* return output_return ();"
-[(set_attr "length" "18")])
-
-;; 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 "s_register_operand" "l*r"))
- (match_operand 1 "" ""))]
- "! TARGET_CALLER_INTERWORKING"
- "bl\\t%__call_via_%0"
-[(set_attr "length" "4")])
-;; The non THUMB_INTERWORK, non TARGET_CALLER_INTERWORKING version
-;; used to be: "mov\\tlr,pc\;bx\\t%0", but the mov does not set
-;; the bottom bit of lr so that a function return (using bx)
-;; would switch back into ARM mode...
-
-(define_insn "*call_indirect_interwork"
- [(call (mem:SI (match_operand:SI 0 "s_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 "s_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 "s_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 "s_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")])
-
-;; Untyped call not required, since all funcs return in r0
-
-;; Miscellaneous patterns
-
-(define_insn "nop"
- [(clobber (const_int 0))]
- ""
- "mov\\tr8, r8")
-
-(define_insn "blockage"
- [(unspec_volatile [(const_int 0)] 0)]
- ""
- ""
- [(set_attr "length" "0")])
-
-(define_expand "prologue"
- [(const_int 0)]
- ""
- "
- thumb_expand_prologue ();
- DONE;
-")
-
-(define_expand "epilogue"
- [(unspec_volatile [(const_int 0)] 1)]
- "! thumb_trivial_epilogue ()"
- "
- thumb_expand_epilogue ();
-")
-
-(define_insn "*epilogue_insns"
- [(unspec_volatile [(const_int 0)] 1)]
- ""
- "*
- return thumb_unexpanded_epilogue ();
-"
-[(set_attr "length" "42")])
-
-;; Special patterns for dealing with the constant pool
-
-(define_insn "consttable_4"
- [(unspec_volatile [(match_operand 0 "" "")] 2)]
- ""
- "*
-{
- switch (GET_MODE_CLASS (GET_MODE (operands[0])))
- {
- case MODE_FLOAT:
- {
- union real_extract u;
- bcopy ((char *) &CONST_DOUBLE_LOW (operands[0]), (char *) &u, sizeof u);
- assemble_real (u.d, GET_MODE (operands[0]));
- break;
- }
- default:
- assemble_integer (operands[0], 4, 1);
- break;
- }
- return \"\";
-}"
-[(set_attr "length" "4")])
-
-(define_insn "consttable_8"
- [(unspec_volatile [(match_operand 0 "" "")] 3)]
- ""
- "*
-{
- switch (GET_MODE_CLASS (GET_MODE (operands[0])))
- {
- case MODE_FLOAT:
- {
- union real_extract u;
- bcopy ((char *) &CONST_DOUBLE_LOW (operands[0]), (char *) &u, sizeof u);
- assemble_real (u.d, GET_MODE (operands[0]));
- break;
- }
- default:
- assemble_integer (operands[0], 8, 1);
- break;
- }
- return \"\";
-}"
-[(set_attr "length" "8")])
-
-(define_insn "consttable_end"
- [(unspec_volatile [(const_int 0)] 4)]
- ""
- "*
- /* Nothing to do (currently). */
- return \"\";
-")
-
-(define_insn "align_4"
- [(unspec_volatile [(const_int 0)] 5)]
- ""
- "*
- assemble_align (32);
- return \"\";
-")
diff --git a/gcc/config/arm/thumb.md.rej b/gcc/config/arm/thumb.md.rej
deleted file mode 100755
index 2a1ba64..0000000
--- a/gcc/config/arm/thumb.md.rej
+++ /dev/null
@@ -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")])
-
diff --git a/gcc/config/arm/thumb_000513.h b/gcc/config/arm/thumb_000513.h
deleted file mode 100755
index a5c25b9..0000000
--- a/gcc/config/arm/thumb_000513.h
+++ /dev/null
@@ -1,1187 +0,0 @@
-/* Definitions of target machine for GNU compiler, for ARM/Thumb.
- Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
- The basis of this contribution was generated by
- Richard Earnshaw, Advanced RISC Machines Ltd
-
-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. */
-
-/* ??? The files thumb.{c,h,md} are all seriously lacking comments. */
-
-/* ??? The files thumb.{c,h,md} need to be reviewed by an experienced
- gcc hacker in their entirety. */
-
-/* ??? The files thumb.{c,h,md} and tcoff.h are all separate from the arm
- files, which will lead to many maintenance problems. These files are
- likely missing all bug fixes made to the arm port since they diverged. */
-
-/* ??? Many patterns in the md file accept operands that will require a
- reload. These should be eliminated if possible by tightening the
- predicates and/or constraints. This will give faster/smaller code. */
-
-/* ??? There is no pattern for the TST instuction. Check for other unsupported
- instructions. */
-
-/* Run Time Target Specifications */
-#ifndef CPP_PREDEFINES
-#define CPP_PREDEFINES "-Dthumb -D__thumb -Acpu(arm) -Amachine(arm)"
-#endif
-
-#ifndef CPP_SPEC
-#define CPP_SPEC "\
-%{mbig-endian:-D__ARMEB__ -D__THUMBEB__} \
-%{mbe:-D__ARMEB__ -D__THUMBEB__} \
-%{!mbe: %{!mbig-endian:-D__ARMEL__ -D__THUMBEL__}} \
-"
-#endif
-
-#ifndef ASM_SPEC
-#define ASM_SPEC "-marm7tdmi %{mthumb-interwork:-mthumb-interwork} %{mbig-endian:-EB}"
-#endif
-#define LINK_SPEC "%{mbig-endian:-EB} -X"
-
-#define TARGET_VERSION fputs (" (ARM/THUMB:generic)", stderr);
-
-/* Nonzero if we should compile with BYTES_BIG_ENDIAN set to 1. */
-#define THUMB_FLAG_BIG_END 0x0001
-#define THUMB_FLAG_BACKTRACE 0x0002
-#define THUMB_FLAG_LEAF_BACKTRACE 0x0004
-#define ARM_FLAG_THUMB 0x1000 /* same as in arm.h */
-#define THUMB_FLAG_CALLEE_SUPER_INTERWORKING 0x40000
-#define THUMB_FLAG_CALLER_SUPER_INTERWORKING 0x80000
-
-
-/* Run-time compilation parameters selecting different hardware/software subsets. */
-extern int target_flags;
-#define TARGET_DEFAULT 0 /* ARM_FLAG_THUMB */
-#define TARGET_BIG_END (target_flags & THUMB_FLAG_BIG_END)
-#define TARGET_THUMB_INTERWORK (target_flags & ARM_FLAG_THUMB)
-#define TARGET_BACKTRACE (leaf_function_p() \
- ? (target_flags & THUMB_FLAG_LEAF_BACKTRACE) \
- : (target_flags & THUMB_FLAG_BACKTRACE))
-
-/* Set if externally visable functions should assume that they
- might be called in ARM mode, from a non-thumb aware code. */
-#define TARGET_CALLEE_INTERWORKING \
- (target_flags & THUMB_FLAG_CALLEE_SUPER_INTERWORKING)
-
-/* Set if calls via function pointers should assume that their
- destination is non-Thumb aware. */
-#define TARGET_CALLER_INTERWORKING \
- (target_flags & THUMB_FLAG_CALLER_SUPER_INTERWORKING)
-
-/* SUBTARGET_SWITCHES is used to add flags on a per-config basis. */
-#ifndef SUBTARGET_SWITCHES
-#define SUBTARGET_SWITCHES
-#endif
-
-#define TARGET_SWITCHES \
-{ \
- {"big-endian", THUMB_FLAG_BIG_END}, \
- {"little-endian", -THUMB_FLAG_BIG_END}, \
- {"thumb-interwork", ARM_FLAG_THUMB}, \
- {"no-thumb-interwork", -ARM_FLAG_THUMB}, \
- {"tpcs-frame", THUMB_FLAG_BACKTRACE}, \
- {"no-tpcs-frame", -THUMB_FLAG_BACKTRACE}, \
- {"tpcs-leaf-frame", THUMB_FLAG_LEAF_BACKTRACE}, \
- {"no-tpcs-leaf-frame", -THUMB_FLAG_LEAF_BACKTRACE}, \
- {"callee-super-interworking", THUMB_FLAG_CALLEE_SUPER_INTERWORKING}, \
- {"no-callee-super-interworking", -THUMB_FLAG_CALLEE_SUPER_INTERWORKING}, \
- {"caller-super-interworking", THUMB_FLAG_CALLER_SUPER_INTERWORKING}, \
- {"no-caller-super-interworking", -THUMB_FLAG_CALLER_SUPER_INTERWORKING}, \
- SUBTARGET_SWITCHES \
- {"", TARGET_DEFAULT} \
-}
-
-#define TARGET_OPTIONS \
-{ \
- { "structure-size-boundary=", & structure_size_string }, \
-}
-
-#define REGISTER_PREFIX ""
-
-#define CAN_DEBUG_WITHOUT_FP 1
-
-#define ASM_APP_ON ""
-#define ASM_APP_OFF "\t.code\t16\n"
-
-/* Output a gap. In fact we fill it with nulls. */
-#define ASM_OUTPUT_SKIP(STREAM, NBYTES) \
- fprintf ((STREAM), "\t.space\t%u\n", (NBYTES))
-
-/* This is how to output an assembler line
- that says to advance the location counter
- to a multiple of 2**LOG bytes. */
-#define ASM_OUTPUT_ALIGN(STREAM,LOG) \
-{ \
- if ((LOG) > 0) \
- fprintf (STREAM, "\t.align\t%d\n", (LOG)); \
-}
-
-/* Output a common block */
-#define ASM_OUTPUT_COMMON(STREAM, NAME, SIZE, ROUNDED) \
- (fprintf ((STREAM), "\t.comm\t"), \
- assemble_name ((STREAM), (NAME)), \
- fprintf((STREAM), ", %d\t%s %d\n", (ROUNDED), (ASM_COMMENT_START), (SIZE)))
-
-#define ASM_GENERATE_INTERNAL_LABEL(STRING,PREFIX,NUM) \
- sprintf ((STRING), "*%s%s%d", (LOCAL_LABEL_PREFIX), (PREFIX), (NUM))
-
-/* This is how to output an internal numbered label where
- PREFIX is the class of label and NUM is the number within the class. */
-#define ASM_OUTPUT_INTERNAL_LABEL(STREAM,PREFIX,NUM) \
- fprintf ((STREAM), "%s%s%d:\n", (LOCAL_LABEL_PREFIX), (PREFIX), (NUM))
-
-/* This is how to output a label which precedes a jumptable. Since
- instructions are 2 bytes, we need explicit alignment here. */
-
-#define ASM_OUTPUT_CASE_LABEL(FILE,PREFIX,NUM,JUMPTABLE) \
- do { \
- ASM_OUTPUT_ALIGN (FILE, 2); \
- ASM_OUTPUT_INTERNAL_LABEL (FILE, PREFIX, NUM); \
- } while (0)
-
-/* This says how to define a local common symbol (ie, not visible to
- linker). */
-#define ASM_OUTPUT_LOCAL(STREAM, NAME, SIZE, ROUNDED) \
- (fprintf((STREAM),"\n\t.lcomm\t"), \
- assemble_name((STREAM),(NAME)), \
- fprintf((STREAM),",%u\n",(SIZE)))
-
-/* Output a reference to a label. */
-#define ASM_OUTPUT_LABELREF(STREAM,NAME) \
- fprintf ((STREAM), "%s%s", user_label_prefix, (NAME))
-
-/* This is how to output an assembler line for a numeric constant byte. */
-#define ASM_OUTPUT_BYTE(STREAM,VALUE) \
- fprintf ((STREAM), "\t.byte\t0x%x\n", (VALUE))
-
-#define ASM_OUTPUT_INT(STREAM,VALUE) \
-{ \
- fprintf (STREAM, "\t.word\t"); \
- output_addr_const (STREAM, (VALUE)); \
- fprintf (STREAM, "\n"); \
-}
-
-#define ASM_OUTPUT_SHORT(STREAM,VALUE) \
-{ \
- fprintf (STREAM, "\t.short\t"); \
- output_addr_const (STREAM, (VALUE)); \
- fprintf (STREAM, "\n"); \
-}
-
-#define ASM_OUTPUT_CHAR(STREAM,VALUE) \
-{ \
- fprintf (STREAM, "\t.byte\t"); \
- output_addr_const (STREAM, (VALUE)); \
- fprintf (STREAM, "\n"); \
-}
-
-#define ASM_OUTPUT_LONG_DOUBLE(STREAM,VALUE) \
-do { char dstr[30]; \
- long l[3]; \
- REAL_VALUE_TO_TARGET_LONG_DOUBLE (VALUE, l); \
- REAL_VALUE_TO_DECIMAL (VALUE, "%.20g", dstr); \
- fprintf (STREAM, "\t.long 0x%lx,0x%lx,0x%lx\t%s long double %s\n", \
- l[0], l[1], l[2], ASM_COMMENT_START, dstr); \
- } while (0)
-
-#define ASM_OUTPUT_DOUBLE(STREAM, VALUE) \
-do { char dstr[30]; \
- long l[2]; \
- REAL_VALUE_TO_TARGET_DOUBLE (VALUE, l); \
- REAL_VALUE_TO_DECIMAL (VALUE, "%.14g", dstr); \
- fprintf (STREAM, "\t.long 0x%lx, 0x%lx\t%s double %s\n", l[0], \
- l[1], ASM_COMMENT_START, dstr); \
- } while (0)
-
-#define ASM_OUTPUT_FLOAT(STREAM, VALUE) \
-do { char dstr[30]; \
- long l; \
- REAL_VALUE_TO_TARGET_SINGLE (VALUE, l); \
- REAL_VALUE_TO_DECIMAL (VALUE, "%.7g", dstr); \
- fprintf (STREAM, "\t.word 0x%lx\t%s float %s\n", l, \
- ASM_COMMENT_START, dstr); \
- } while (0);
-
-/* Define results of standard character escape sequences. */
-#define TARGET_BELL 007
-#define TARGET_BS 010
-#define TARGET_TAB 011
-#define TARGET_NEWLINE 012
-#define TARGET_VT 013
-#define TARGET_FF 014
-#define TARGET_CR 015
-
-/* This is how to output a string. */
-#define ASM_OUTPUT_ASCII(STREAM, STRING, LEN) \
-do { \
- register int i, c, len = (LEN), cur_pos = 17; \
- register unsigned char *string = (unsigned char *)(STRING); \
- fprintf ((STREAM), "\t.ascii\t\""); \
- for (i = 0; i < len; i++) \
- { \
- register int c = string[i]; \
- \
- switch (c) \
- { \
- case '\"': \
- case '\\': \
- putc ('\\', (STREAM)); \
- putc (c, (STREAM)); \
- cur_pos += 2; \
- break; \
- \
- case TARGET_NEWLINE: \
- fputs ("\\n", (STREAM)); \
- if (i+1 < len \
- && (((c = string[i+1]) >= '\040' && c <= '~') \
- || c == TARGET_TAB)) \
- cur_pos = 32767; /* break right here */ \
- else \
- cur_pos += 2; \
- break; \
- \
- case TARGET_TAB: \
- fputs ("\\t", (STREAM)); \
- cur_pos += 2; \
- break; \
- \
- case TARGET_FF: \
- fputs ("\\f", (STREAM)); \
- cur_pos += 2; \
- break; \
- \
- case TARGET_BS: \
- fputs ("\\b", (STREAM)); \
- cur_pos += 2; \
- break; \
- \
- case TARGET_CR: \
- fputs ("\\r", (STREAM)); \
- cur_pos += 2; \
- break; \
- \
- default: \
- if (c >= ' ' && c < 0177) \
- { \
- putc (c, (STREAM)); \
- cur_pos++; \
- } \
- else \
- { \
- fprintf ((STREAM), "\\%03o", c); \
- cur_pos += 4; \
- } \
- } \
- \
- if (cur_pos > 72 && i+1 < len) \
- { \
- cur_pos = 17; \
- fprintf ((STREAM), "\"\n\t.ascii\t\""); \
- } \
- } \
- fprintf ((STREAM), "\"\n"); \
-} while (0)
-
-/* Output and Generation of Labels */
-#define ASM_OUTPUT_LABEL(STREAM,NAME) \
- (assemble_name ((STREAM), (NAME)), \
- fprintf ((STREAM), ":\n"))
-
-#define ASM_GLOBALIZE_LABEL(STREAM,NAME) \
- (fprintf ((STREAM), "\t.globl\t"), \
- assemble_name ((STREAM), (NAME)), \
- fputc ('\n', (STREAM)))
-
-/* Construct a private name. */
-#define ASM_FORMAT_PRIVATE_NAME(OUTVAR,NAME,NUMBER) \
- ((OUTVAR) = (char *) alloca (strlen (NAME) + 10), \
- sprintf ((OUTVAR), "%s.%d", (NAME), (NUMBER)))
-
-/* Switch to the text or data segment. */
-#define TEXT_SECTION_ASM_OP ".text"
-#define DATA_SECTION_ASM_OP ".data"
-#define BSS_SECTION_ASM_OP ".bss"
-
-/* The assembler's names for the registers. */
-#ifndef REGISTER_NAMES
-#define REGISTER_NAMES \
-{ \
- "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \
- "r8", "r9", "sl", "fp", "ip", "sp", "lr", "pc", "ap" \
-}
-#endif
-
-#ifndef ADDITIONAL_REGISTER_NAMES
-#define ADDITIONAL_REGISTER_NAMES \
-{ \
- {"a1", 0}, \
- {"a2", 1}, \
- {"a3", 2}, \
- {"a4", 3}, \
- {"v1", 4}, \
- {"v2", 5}, \
- {"v3", 6}, \
- {"v4", 7}, \
- {"v5", 8}, \
- {"v6", 9}, \
- {"sb", 9}, \
- {"v7", 10}, \
- {"r10", 10}, /* sl */ \
- {"r11", 11}, /* fp */ \
- {"r12", 12}, /* ip */ \
- {"r13", 13}, /* sp */ \
- {"r14", 14}, /* lr */ \
- {"r15", 15} /* pc */ \
-}
-#endif
-
-/* The assembler's parentheses characters. */
-#define ASM_OPEN_PAREN "("
-#define ASM_CLOSE_PAREN ")"
-
-#ifndef ASM_COMMENT_START
-#define ASM_COMMENT_START "@"
-#endif
-
-/* Output an element of a dispatch table. */
-#define ASM_OUTPUT_ADDR_VEC_ELT(STREAM,VALUE) \
- fprintf (STREAM, "\t.word\t%sL%d\n", (LOCAL_LABEL_PREFIX), (VALUE))
-
-#define ASM_OUTPUT_ADDR_DIFF_ELT(STREAM,BODY,VALUE,REL) \
- fprintf (STREAM, "\tb\t%sL%d\n", (LOCAL_LABEL_PREFIX), (VALUE))
-
-/* Storage Layout */
-
-/* Define this is most significant bit is lowest numbered in
- instructions that operate on numbered bit-fields. */
-#define BITS_BIG_ENDIAN 0
-
-/* Define this if most significant byte of a word is the lowest
- numbered. */
-#define BYTES_BIG_ENDIAN (TARGET_BIG_END != 0)
-
-#define WORDS_BIG_ENDIAN (BYTES_BIG_ENDIAN)
-
-/* LIBGCC2_WORDS_BIG_ENDIAN has to be a constant, so we define this based
- on processor pre-defineds when compiling libgcc2.c. */
-#if defined(__THUMBEB__) && !defined(__THUMBEL__)
-#define LIBGCC2_WORDS_BIG_ENDIAN 1
-#else
-#define LIBGCC2_WORDS_BIG_ENDIAN 0
-#endif
-
-#define FLOAT_WORDS_BIG_ENDIAN 1
-
-#define BITS_PER_UNIT 8
-#define BITS_PER_WORD 32
-
-#define UNITS_PER_WORD 4
-
-#define POINTER_SIZE 32
-
-#define PROMOTE_MODE(MODE,UNSIGNEDP,TYPE) \
-{ \
- if (GET_MODE_CLASS (MODE) == MODE_INT \
- && GET_MODE_SIZE (MODE) < 4) \
- { \
- (UNSIGNEDP) = 1; \
- (MODE) = SImode; \
- } \
-}
-
-#define PARM_BOUNDARY 32
-#define STACK_BOUNDARY 32
-
-#define FUNCTION_BOUNDARY 32
-#define BIGGEST_ALIGNMENT 32
-
-/* Make strings word-aligned so strcpy from constants will be faster. */
-#define CONSTANT_ALIGNMENT(EXP, ALIGN) \
- (TREE_CODE (EXP) == STRING_CST \
- && (ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN))
-
-#define EMPTY_FIELD_BOUNDARY 32
-
-#define STRUCTURE_SIZE_BOUNDARY 32
-
-/* Used when parsing command line option -mstructure_size_boundary. */
-extern char * structure_size_string;
-
-#define STRICT_ALIGNMENT 1
-
-#define TARGET_FLOAT_FORMAT IEEE_FLOAT_FORMAT
-
-
-/* Layout of Source Language Data Types */
-
-#define DEFAULT_SIGNED_CHAR 0
-
-#define TARGET_BELL 007
-#define TARGET_BS 010
-#define TARGET_TAB 011
-#define TARGET_NEWLINE 012
-#define TARGET_VT 013
-#define TARGET_FF 014
-#define TARGET_CR 015
-
-
-/* Register Usage */
-
-/* Note there are 16 hard registers on the Thumb. We invent a 17th register
- which is assigned to ARG_POINTER_REGNUM, but this is later removed by
- elimination passes in the compiler. */
-#define FIRST_PSEUDO_REGISTER 17
-
-/* ??? This is questionable. */
-#define FIXED_REGISTERS \
-{ \
- 0,0,0,0, \
- 0,0,0,0, \
- 0,0,0,1, \
- 0,1,1,1,1 \
-}
-
-/* ??? This is questionable. */
-#define CALL_USED_REGISTERS \
-{ \
- 1,1,1,1, \
- 0,0,0,0, \
- 0,0,0,1, \
- 1,1,1,1,1 \
-}
-
-#define HARD_REGNO_NREGS(REGNO,MODE) \
- ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) \
- / UNITS_PER_WORD)
-
-/* ??? Probably should only allow DImode/DFmode in even numbered registers. */
-#define HARD_REGNO_MODE_OK(REGNO,MODE) ((GET_MODE_SIZE (MODE) > UNITS_PER_WORD) ? (REGNO < 7) : 1)
-
-#define MODES_TIEABLE_P(MODE1,MODE2) 1
-
-/* The NOARG_LO_REGS class is the set of LO_REGS that are not used for passing
- arguments to functions. These are the registers that are available for
- spilling during reload. The code in reload1.c:init_reload() will detect this
- class and place it into 'reload_address_base_reg_class'. */
-
-enum reg_class
-{
- NO_REGS,
- NONARG_LO_REGS,
- LO_REGS,
- STACK_REG,
- BASE_REGS,
- HI_REGS,
- ALL_REGS,
- LIM_REG_CLASSES
-};
-
-#define GENERAL_REGS ALL_REGS
-
-#define N_REG_CLASSES (int) LIM_REG_CLASSES
-
-#define REG_CLASS_NAMES \
-{ \
- "NO_REGS", \
- "NONARG_LO_REGS", \
- "LO_REGS", \
- "STACK_REG", \
- "BASE_REGS", \
- "HI_REGS", \
- "ALL_REGS" \
-}
-
-#define REG_CLASS_CONTENTS \
-{ \
- 0x00000, \
- 0x000f0, \
- 0x000ff, \
- 0x02000, \
- 0x020ff, \
- 0x0ff00, \
- 0x1ffff, \
-}
-
-#define REGNO_REG_CLASS(REGNO) \
- ((REGNO) == STACK_POINTER_REGNUM ? STACK_REG \
- : (REGNO) < 8 ? ((REGNO) < 4 ? LO_REGS \
- : NONARG_LO_REGS) \
- : HI_REGS)
-
-#define BASE_REG_CLASS BASE_REGS
-
-#define MODE_BASE_REG_CLASS(MODE) \
- ((MODE) != QImode && (MODE) != HImode \
- ? BASE_REGS : LO_REGS)
-
-#define INDEX_REG_CLASS LO_REGS
-
-/* When SMALL_REGISTER_CLASSES is nonzero, the compiler allows
- registers explicitly used in the rtl to be used as spill registers
- but prevents the compiler from extending the lifetime of these
- registers. */
-
-#define SMALL_REGISTER_CLASSES 1
-
-#define REG_CLASS_FROM_LETTER(C) \
- ((C) == 'l' ? LO_REGS \
- : (C) == 'h' ? HI_REGS \
- : (C) == 'b' ? BASE_REGS \
- : (C) == 'k' ? STACK_REG \
- : NO_REGS)
-
-#define REGNO_OK_FOR_BASE_P(REGNO) \
- ((REGNO) < 8 \
- || (REGNO) == STACK_POINTER_REGNUM \
- || (unsigned) reg_renumber[REGNO] < 8 \
- || (unsigned) reg_renumber[REGNO] == STACK_POINTER_REGNUM)
-
-#define REGNO_MODE_OK_FOR_BASE_P(REGNO, MODE) \
- ((REGNO) < 8 \
- || (unsigned) reg_renumber[REGNO] < 8 \
- || (GET_MODE_SIZE (MODE) >= 4 \
- && ((REGNO) == STACK_POINTER_REGNUM \
- || (unsigned) reg_renumber[REGNO] == STACK_POINTER_REGNUM)))
-
-#define REGNO_OK_FOR_INDEX_P(REGNO) \
- ((REGNO) < 8 \
- || (unsigned) reg_renumber[REGNO] < 8)
-
-/* ??? This looks suspiciously wrong. */
-/* We need to leave BASE_REGS reloads alone, in order to avoid caller_save
- lossage. Caller_saves requests a BASE_REGS reload (caller_save_spill_class)
- and then later we verify that one was allocated. If PREFERRED_RELOAD_CLASS
- says to allocate a LO_REGS spill instead, then this mismatch gives an
- abort. Alternatively, this could be fixed by modifying BASE_REG_CLASS
- to be LO_REGS instead of BASE_REGS. It is not clear what affect this
- change would have. */
-/* ??? This looks even more suspiciously wrong. PREFERRED_RELOAD_CLASS
- must always return a strict subset of the input class. Just blindly
- returning LO_REGS is safe only if the input class is a superset of LO_REGS,
- but there is no check for this. Added another exception for NONARG_LO_REGS
- because it is not a superset of LO_REGS. */
-/* ??? We now use NONARG_LO_REGS for caller_save_spill_class, so the
- comments about BASE_REGS are now obsolete. */
-#define PREFERRED_RELOAD_CLASS(X,CLASS) \
- ((CLASS) == BASE_REGS || (CLASS) == NONARG_LO_REGS ? (CLASS) \
- : LO_REGS)
-/*
- ((CONSTANT_P ((X)) && GET_CODE ((X)) != CONST_INT \
- && ! CONSTANT_POOL_ADDRESS_P((X))) ? NO_REGS \
- : (GET_CODE ((X)) == CONST_INT \
- && (unsigned HOST_WIDE_INT) INTVAL ((X)) > 255) ? NO_REGS \
- : LO_REGS) */
-
-/* Must leave BASE_REGS and NONARG_LO_REGS reloads alone, see comment
- above. */
-#define SECONDARY_RELOAD_CLASS(CLASS,MODE,X) \
- ((CLASS) != LO_REGS && (CLASS) != BASE_REGS && (CLASS) != NONARG_LO_REGS \
- ? ((true_regnum (X) == -1 ? LO_REGS \
- : (true_regnum (X) + HARD_REGNO_NREGS (0, MODE) > 8) ? LO_REGS \
- : NO_REGS)) \
- : NO_REGS)
-
-#define CLASS_MAX_NREGS(CLASS,MODE) HARD_REGNO_NREGS(0,(MODE))
-
-int thumb_shiftable_const ();
-
-#define CONST_OK_FOR_LETTER_P(VAL,C) \
- ((C) == 'I' ? (unsigned HOST_WIDE_INT) (VAL) < 256 \
- : (C) == 'J' ? (VAL) > -256 && (VAL) <= 0 \
- : (C) == 'K' ? thumb_shiftable_const (VAL) \
- : (C) == 'L' ? (VAL) > -8 && (VAL) < 8 \
- : (C) == 'M' ? ((unsigned HOST_WIDE_INT) (VAL) < 1024 \
- && ((VAL) & 3) == 0) \
- : (C) == 'N' ? ((unsigned HOST_WIDE_INT) (VAL) < 32) \
- : (C) == 'O' ? ((VAL) >= -508 && (VAL) <= 508) \
- : 0)
-
-#define CONST_DOUBLE_OK_FOR_LETTER_P(VAL,C) 0
-
-#define EXTRA_CONSTRAINT(X,C) \
- ((C) == 'Q' ? (GET_CODE (X) == MEM \
- && GET_CODE (XEXP (X, 0)) == LABEL_REF) : 0)
-
-/* Stack Layout and Calling Conventions */
-
-#define STACK_GROWS_DOWNWARD 1
-
-/* #define FRAME_GROWS_DOWNWARD 1 */
-
-/* #define ARGS_GROW_DOWNWARD 1 */
-
-#define STARTING_FRAME_OFFSET 0
-
-#define FIRST_PARM_OFFSET(FNDECL) 0
-
-/* Registers that address the stack frame */
-
-#define STACK_POINTER_REGNUM 13 /* Defined by the TPCS. */
-
-#define FRAME_POINTER_REGNUM 7 /* TPCS defines this as 11 but it does not really mean it. */
-
-#define ARG_POINTER_REGNUM 16 /* A fake hard register that is eliminated later on. */
-
-#define STATIC_CHAIN_REGNUM 9
-
-#define FRAME_POINTER_REQUIRED 0
-
-#define ELIMINABLE_REGS \
-{{ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
- {ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM}, \
- {FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}}
-
-/* On the Thumb we always want to perform the eliminations as we
- actually only have one real register pointing to the stashed
- variables: the stack pointer, and we never use the frame pointer. */
-#define CAN_ELIMINATE(FROM,TO) 1
-
-/* Note: This macro must match the code in thumb_function_prologue() in thumb.c. */
-#define INITIAL_ELIMINATION_OFFSET(FROM,TO,OFFSET) \
-{ \
- (OFFSET) = 0; \
- if ((FROM) == ARG_POINTER_REGNUM) \
- { \
- int count_regs = 0; \
- int regno; \
- (OFFSET) += get_frame_size (); \
- for (regno = 8; regno < 13; regno++) \
- if (regs_ever_live[regno] && ! call_used_regs[regno]) \
- count_regs++; \
- if (count_regs) \
- (OFFSET) += 4 * count_regs; \
- count_regs = 0; \
- for (regno = 0; regno < 8; regno++) \
- if (regs_ever_live[regno] && ! call_used_regs[regno]) \
- count_regs++; \
- if (count_regs || ! leaf_function_p () || far_jump_used_p()) \
- (OFFSET) += 4 * (count_regs + 1); \
- if (TARGET_BACKTRACE) { \
- if ((count_regs & 0xFF) == 0 && (regs_ever_live[3] != 0)) \
- (OFFSET) += 20; \
- else \
- (OFFSET) += 16; } \
- } \
- if ((TO) == STACK_POINTER_REGNUM) \
- (OFFSET) += current_function_outgoing_args_size; \
-}
-
-/* Passing Arguments on the stack */
-
-#define PROMOTE_PROTOTYPES 1
-
-#define ACCUMULATE_OUTGOING_ARGS 1
-
-#define RETURN_POPS_ARGS(FUNDECL,FUNTYPE,SIZE) 0
-
-#define FUNCTION_ARG(CUM,MODE,TYPE,NAMED) \
- ((NAMED) ? ((CUM) >= 16 ? 0 : gen_rtx (REG, (MODE), (CUM) / 4)) \
- : 0)
-
-#define FUNCTION_ARG_PARTIAL_NREGS(CUM,MODE,TYPE,NAMED) \
- (((CUM) < 16 && (CUM) + (((MODE) == BLKmode) \
- ? int_size_in_bytes (TYPE) \
- : HARD_REGNO_NREGS (0, (MODE)) * 4) > 16) \
- ? 4 - (CUM) / 4 : 0)
-
-#define CUMULATIVE_ARGS int
-
-#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT) \
- ((CUM) = ((FNTYPE) && aggregate_value_p (TREE_TYPE (FNTYPE))) ? 4 : 0)
-
-#define FUNCTION_ARG_ADVANCE(CUM,MODE,TYPE,NAMED) \
- (CUM) += ((((MODE) == BLKmode) \
- ? int_size_in_bytes (TYPE) \
- : GET_MODE_SIZE (MODE)) + 3) & ~3
-
-#define FUNCTION_ARG_REGNO_P(REGNO) \
- ((REGNO) >=0 && (REGNO) <= 3)
-
-#define FUNCTION_VALUE(VALTYPE,FUNC) gen_rtx (REG, TYPE_MODE (VALTYPE), 0)
-
-#define LIBCALL_VALUE(MODE) gen_rtx (REG, (MODE), 0)
-
-#define FUNCTION_VALUE_REGNO_P(REGNO) ((REGNO) == 0)
-
- /* How large values are returned */
-/* A C expression which can inhibit the returning of certain function values
- in registers, based on the type of value. */
-#define RETURN_IN_MEMORY(TYPE) thumb_return_in_memory (TYPE)
-
-/* Define DEFAULT_PCC_STRUCT_RETURN to 1 if all structure and union return
- values must be in memory. On the ARM, they need only do so if larger
- than a word, or if they contain elements offset from zero in the struct. */
-#define DEFAULT_PCC_STRUCT_RETURN 0
-
-
-#define STRUCT_VALUE_REGNUM 0
-
-#define FUNCTION_PROLOGUE(FILE,SIZE) thumb_function_prologue((FILE),(SIZE))
-
-#define FUNCTION_EPILOGUE(FILE,SIZE) thumb_function_epilogue((FILE),(SIZE))
-
-/* Implementing the Varargs Macros */
-
-#define SETUP_INCOMING_VARARGS(CUM,MODE,TYPE,PRETEND_SIZE,NO_RTL) \
-{ \
- extern int current_function_anonymous_args; \
- current_function_anonymous_args = 1; \
- if ((CUM) < 16) \
- (PRETEND_SIZE) = 16 - (CUM); \
-}
-
-/* Trampolines for nested functions */
-
-/* Output assembler code for a block containing the constant parts of
- a trampoline, leaving space for the variable parts.
-
- On the Thumb we always switch into ARM mode to execute the trampoline.
- Why - because it is easier. This code will always be branched to via
- a BX instruction and since the compiler magically generates the address
- of the function the linker has no opportunity to ensure that the
- bottom bit is set. Thus the processor will be in ARM mode when it
- reaches this code. So we duplicate the ARM trampoline code and add
- a switch into Thumb mode as well.
-
- On the ARM, (if r8 is the static chain regnum, and remembering that
- referencing pc adds an offset of 8) the trampoline looks like:
- ldr r8, [pc, #0]
- ldr pc, [pc]
- .word static chain value
- .word function's address
- ??? FIXME: When the trampoline returns, r8 will be clobbered. */
-#define TRAMPOLINE_TEMPLATE(FILE) \
-{ \
- fprintf ((FILE), "\t.code 32\n"); \
- fprintf ((FILE), ".Ltrampoline_start:\n"); \
- fprintf ((FILE), "\tldr\t%s, [%spc, #8]\n", \
- reg_names[STATIC_CHAIN_REGNUM], REGISTER_PREFIX); \
- fprintf ((FILE), "\tldr\t%sip, [%spc, #8]\n", \
- REGISTER_PREFIX, REGISTER_PREFIX); \
- fprintf ((FILE), "\torr\t%sip, %sip, #1\n", \
- REGISTER_PREFIX, REGISTER_PREFIX); \
- fprintf ((FILE), "\tbx\t%sip\n", REGISTER_PREFIX); \
- fprintf ((FILE), "\t.word\t0\n"); \
- fprintf ((FILE), "\t.word\t0\n"); \
- fprintf ((FILE), "\t.code 16\n"); \
-}
-
-/* Length in units of the trampoline for entering a nested function. */
-#define TRAMPOLINE_SIZE 24
-
-/* Alignment required for a trampoline in units. */
-#define TRAMPOLINE_ALIGN 4
-
-#define INITIALIZE_TRAMPOLINE(ADDR,FNADDR,CHAIN) \
-{ \
- emit_move_insn (gen_rtx (MEM, SImode, plus_constant ((ADDR), 16)), \
- (CHAIN)); \
- emit_move_insn (gen_rtx (MEM, SImode, plus_constant ((ADDR), 20)), \
- (FNADDR)); \
-}
-
-
-/* Implicit Calls to Library Routines */
-
-#define TARGET_MEM_FUNCTIONS 1
-
-#define OVERRIDE_OPTIONS thumb_override_options ()
-
-
-/* Addressing Modes */
-
-#define HAVE_POST_INCREMENT 1
-
-#define CONSTANT_ADDRESS_P(X) \
- (GET_CODE (X) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (X))
-
-#define MAX_REGS_PER_ADDRESS 2
-
-#ifdef REG_OK_STRICT
-
-#define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P (REGNO (X))
-#define REG_OK_FOR_INDEX_P(X) REGNO_OK_FOR_INDEX_P (REGNO (X))
-
-#define REG_MODE_OK_FOR_BASE_P(X,MODE) \
- REGNO_MODE_OK_FOR_BASE_P (REGNO (X), MODE)
-
-#else /* REG_OK_STRICT */
-
-#define REG_OK_FOR_BASE_P(X) \
- (REGNO (X) < 8 || REGNO (X) == STACK_POINTER_REGNUM \
- || (X) == arg_pointer_rtx \
- || REGNO (X) >= FIRST_PSEUDO_REGISTER)
-
-#define REG_MODE_OK_FOR_BASE_P(X,MODE) \
- (REGNO (X) < 8 \
- || REGNO (X) >= FIRST_PSEUDO_REGISTER \
- || (GET_MODE_SIZE (MODE) >= 4 \
- && (REGNO (X) == STACK_POINTER_REGNUM \
- || (X) == arg_pointer_rtx)))
-
-#define REG_OK_FOR_INDEX_P(X) \
- (REGNO (X) < 8 \
- || REGNO (X) >= FIRST_PSEUDO_REGISTER)
-
-#endif /* REG_OK_STRICT */
-
-/* In a REG+REG address, both must be INDEX registers. */
-#define REG_OK_FOR_INDEXED_BASE_P(X) REG_OK_FOR_INDEX_P(X)
-
-#define LEGITIMATE_OFFSET(MODE,VAL) \
-(GET_MODE_SIZE (MODE) == 1 ? ((unsigned HOST_WIDE_INT) (VAL) < 32) \
- : GET_MODE_SIZE (MODE) == 2 ? ((unsigned HOST_WIDE_INT) (VAL) < 64 \
- && ((VAL) & 1) == 0) \
- : ((VAL) >= 0 && ((VAL) + GET_MODE_SIZE (MODE)) <= 128 \
- && ((VAL) & 3) == 0))
-
-/* The AP may be eliminated to either the SP or the FP, so we use the
- least common denominator, e.g. SImode, and offsets from 0 to 64. */
-
-/* ??? Verify whether the above is the right approach. */
-
-/* ??? Also, the FP may be eliminated to the SP, so perhaps that
- needs special handling also. */
-
-/* ??? Look at how the mips16 port solves this problem. It probably uses
- better ways to solve some of these problems. */
-
-/* Although it is not incorrect, we don't accept QImode and HImode
- addresses based on the frame pointer or arg pointer until the reload pass starts.
- This is so that eliminating such addresses into stack based ones
- won't produce impossible code. */
-#define GO_IF_LEGITIMATE_ADDRESS(MODE,X,WIN) \
-{ \
- /* ??? Not clear if this is right. Experiment. */ \
- if (GET_MODE_SIZE (MODE) < 4 \
- && ! (reload_in_progress || reload_completed) \
- && (reg_mentioned_p (frame_pointer_rtx, X) \
- || reg_mentioned_p (arg_pointer_rtx, X) \
- || reg_mentioned_p (virtual_incoming_args_rtx, X) \
- || reg_mentioned_p (virtual_outgoing_args_rtx, X) \
- || reg_mentioned_p (virtual_stack_dynamic_rtx, X) \
- || reg_mentioned_p (virtual_stack_vars_rtx, X))) \
- ; \
- /* Accept any base register. SP only in SImode or larger. */ \
- else if (GET_CODE (X) == REG && REG_MODE_OK_FOR_BASE_P(X, MODE)) \
- goto WIN; \
- /* This is PC relative data before MACHINE_DEPENDENT_REORG runs. */ \
- else if (GET_MODE_SIZE (MODE) >= 4 && CONSTANT_P (X) \
- && CONSTANT_POOL_ADDRESS_P (X)) \
- goto WIN; \
- /* This is PC relative data after MACHINE_DEPENDENT_REORG runs. */ \
- else if (GET_MODE_SIZE (MODE) >= 4 && reload_completed \
- && (GET_CODE (X) == LABEL_REF \
- || (GET_CODE (X) == CONST \
- && GET_CODE (XEXP (X, 0)) == PLUS \
- && GET_CODE (XEXP (XEXP (X, 0), 0)) == LABEL_REF \
- && GET_CODE (XEXP (XEXP (X, 0), 1)) == CONST_INT))) \
- goto WIN; \
- /* Post-inc indexing only supported for SImode and larger. */ \
- else if (GET_CODE (X) == POST_INC && GET_MODE_SIZE (MODE) >= 4 \
- && GET_CODE (XEXP (X, 0)) == REG \
- && REG_OK_FOR_INDEX_P (XEXP (X, 0))) \
- goto WIN; \
- else if (GET_CODE (X) == PLUS) \
- { \
- /* REG+REG address can be any two index registers. */ \
- /* ??? REG+REG addresses have been completely disabled before \
- reload completes, because we do not have enough available \
- reload registers. We only have 3 guaranteed reload registers \
- (NONARG_LO_REGS - the frame pointer), but we need at least 4 \
- to support REG+REG addresses. We have left them enabled after \
- reload completes, in the hope that reload_cse_regs and related \
- routines will be able to create them after the fact. It is \
- probably possible to support REG+REG addresses with additional \
- reload work, but I do not not have enough time to attempt such \
- a change at this time. */ \
- /* ??? Normally checking the mode here is wrong, since it isn't \
- impossible to use REG+REG with DFmode. However, the movdf \
- pattern requires offsettable addresses, and REG+REG is not \
- offsettable, so it must be rejected somehow. Trying to use \
- 'o' fails, because offsettable_address_p does a QImode check. \
- QImode is not valid for stack addresses, and has a smaller \
- range for non-stack bases, and this causes valid addresses \
- to be rejected. So we just eliminate REG+REG here by checking \
- the mode. */ \
- /* We also disallow FRAME+REG addressing since we know that FRAME \
- will be replaced with STACK, and SP relative addressing only \
- permits SP+OFFSET. */ \
- if (GET_MODE_SIZE (MODE) <= 4 \
- /* ??? See comment above. */ \
- && reload_completed \
- && GET_CODE (XEXP (X, 0)) == REG \
- && GET_CODE (XEXP (X, 1)) == REG \
- && XEXP (X, 0) != frame_pointer_rtx \
- && XEXP (X, 1) != frame_pointer_rtx \
- && XEXP (X, 0) != virtual_stack_vars_rtx \
- && XEXP (X, 1) != virtual_stack_vars_rtx \
- && REG_OK_FOR_INDEX_P (XEXP (X, 0)) \
- && REG_OK_FOR_INDEX_P (XEXP (X, 1))) \
- goto WIN; \
- /* REG+const has 5-7 bit offset for non-SP registers. */ \
- else if (GET_CODE (XEXP (X, 0)) == REG \
- && (REG_OK_FOR_INDEX_P (XEXP (X, 0)) \
- || XEXP (X, 0) == arg_pointer_rtx) \
- && GET_CODE (XEXP (X, 1)) == CONST_INT \
- && LEGITIMATE_OFFSET (MODE, INTVAL (XEXP (X, 1)))) \
- goto WIN; \
- /* REG+const has 10 bit offset for SP, but only SImode and \
- larger is supported. */ \
- /* ??? Should probably check for DI/DFmode overflow here \
- just like GO_IF_LEGITIMATE_OFFSET does. */ \
- else if (GET_CODE (XEXP (X, 0)) == REG \
- && REGNO (XEXP (X, 0)) == STACK_POINTER_REGNUM \
- && GET_MODE_SIZE (MODE) >= 4 \
- && GET_CODE (XEXP (X, 1)) == CONST_INT \
- && (unsigned HOST_WIDE_INT) INTVAL (XEXP (X, 1)) < 1024 \
- && (INTVAL (XEXP (X, 1)) & 3) == 0) \
- goto WIN; \
- } \
-}
-
-/* ??? If an HImode FP+large_offset address is converted to an HImode
- SP+large_offset address, then reload won't know how to fix it. It sees
- only that SP isn't valid for HImode, and so reloads the SP into an index
- register, but the resulting address is still invalid because the offset
- is too big. We fix it here instead by reloading the entire address. */
-/* We could probably achieve better results by defining PROMOTE_MODE to help
- cope with the variances between the Thumb's signed and unsigned byte and
- halfword load instructions. */
-#define LEGITIMIZE_RELOAD_ADDRESS(X,MODE,OPNUM,TYPE,IND_LEVELS,WIN) \
-{ \
- if (GET_CODE (X) == PLUS \
- && GET_MODE_SIZE (MODE) < 4 \
- && GET_CODE (XEXP (X, 0)) == REG \
- && XEXP (X, 0) == stack_pointer_rtx \
- && GET_CODE (XEXP (X, 1)) == CONST_INT \
- && ! LEGITIMATE_OFFSET (MODE, INTVAL (XEXP (X, 1)))) \
- { \
- rtx orig_X = X; \
- X = copy_rtx (X); \
- push_reload (orig_X, NULL_RTX, &X, NULL_PTR, \
- BASE_REG_CLASS, \
- Pmode, VOIDmode, 0, 0, OPNUM, TYPE); \
- goto WIN; \
- } \
-}
-
-#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR,LABEL)
-
-#define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN)
-
-#define LEGITIMATE_CONSTANT_P(X) \
- (GET_CODE (X) == CONST_INT \
- || GET_CODE (X) == CONST_DOUBLE \
- || CONSTANT_ADDRESS_P (X))
-
-
-/* Condition Code Status */
-
-#define NOTICE_UPDATE_CC(EXP,INSN) \
-{ \
- if (get_attr_conds ((INSN)) != CONDS_UNCHANGED) \
- CC_STATUS_INIT; \
-}
-
-
-/* Describing Relative Costs of Operations */
-
-#define SLOW_BYTE_ACCESS 0
-
-#define SLOW_UNALIGNED_ACCESS 1
-
-#define NO_FUNCTION_CSE 1
-
-#define NO_RECURSIVE_FUNCTION_CSE 1
-
-#define REGISTER_MOVE_COST(FROM,TO) \
- (((FROM) == HI_REGS || (TO) == HI_REGS) ? 4 : 2)
-
-#define MEMORY_MOVE_COST(M,CLASS,IN) \
- ((GET_MODE_SIZE(M) < 4 ? 8 : 2 * GET_MODE_SIZE(M)) * (CLASS == LO_REGS ? 1 : 2))
-
-/* This will allow better space optimization when compiling with -O */
-#define BRANCH_COST (optimize > 1 ? 1 : 0)
-
-#define RTX_COSTS(X,CODE,OUTER) \
- case MULT: \
- if (GET_CODE (XEXP (X, 1)) == CONST_INT) \
- { \
- int cycles = 0; \
- unsigned HOST_WIDE_INT i = INTVAL (XEXP (X, 1)); \
- while (i) \
- { \
- i >>= 2; \
- cycles++; \
- } \
- return COSTS_N_INSNS (2) + cycles; \
- } \
- return COSTS_N_INSNS (1) + 16; \
- case ASHIFT: case ASHIFTRT: case LSHIFTRT: case ROTATERT: \
- case PLUS: case MINUS: case COMPARE: case NEG: case NOT: \
- return COSTS_N_INSNS (1); \
- case SET: \
- return (COSTS_N_INSNS (1) \
- + 4 * ((GET_CODE (SET_SRC (X)) == MEM) \
- + GET_CODE (SET_DEST (X)) == MEM))
-
-#define CONST_COSTS(X,CODE,OUTER) \
- case CONST_INT: \
- if ((OUTER) == SET) \
- { \
- if ((unsigned HOST_WIDE_INT) INTVAL (X) < 256) \
- return 0; \
- if (thumb_shiftable_const (INTVAL (X))) \
- return COSTS_N_INSNS (2); \
- return COSTS_N_INSNS (3); \
- } \
- else if (OUTER == PLUS \
- && INTVAL (X) < 256 && INTVAL (X) > -256) \
- return 0; \
- else if (OUTER == COMPARE \
- && (unsigned HOST_WIDE_INT) INTVAL (X) < 256) \
- return 0; \
- else if (OUTER == ASHIFT || OUTER == ASHIFTRT \
- || OUTER == LSHIFTRT) \
- return 0; \
- return COSTS_N_INSNS (2); \
- case CONST: \
- case CONST_DOUBLE: \
- case LABEL_REF: \
- case SYMBOL_REF: \
- return COSTS_N_INSNS(3);
-
-#define ADDRESS_COST(X) \
- ((GET_CODE (X) == REG \
- || (GET_CODE (X) == PLUS && GET_CODE (XEXP (X, 0)) == REG \
- && GET_CODE (XEXP (X, 1)) == CONST_INT)) \
- ? 1 : 2)
-
-
-/* Position Independent Code */
-
-#define PRINT_OPERAND(STREAM,X,CODE) \
- thumb_print_operand((STREAM), (X), (CODE))
-
-#define PRINT_OPERAND_ADDRESS(STREAM,X) \
-{ \
- if (GET_CODE ((X)) == REG) \
- fprintf ((STREAM), "[%s]", reg_names[REGNO ((X))]); \
- else if (GET_CODE ((X)) == POST_INC) \
- fprintf ((STREAM), "%s!", reg_names[REGNO (XEXP (X, 0))]); \
- else if (GET_CODE ((X)) == PLUS) \
- { \
- if (GET_CODE (XEXP ((X), 1)) == CONST_INT) \
- fprintf ((STREAM), "[%s, #%d]", \
- reg_names[REGNO (XEXP ((X), 0))], \
- (int) INTVAL (XEXP ((X), 1))); \
- else \
- fprintf ((STREAM), "[%s, %s]", \
- reg_names[REGNO (XEXP ((X), 0))], \
- reg_names[REGNO (XEXP ((X), 1))]); \
- } \
- else \
- output_addr_const ((STREAM), (X)); \
-}
-
-#define PRINT_OPERAND_PUNCT_VALID_P(CODE) ((CODE) == '@' || ((CODE) == '_'))
-
-/* Emit a special directive when defining a function name.
- This is used by the assembler to assit with interworking. */
-#define ASM_DECLARE_FUNCTION_NAME(file, name, 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)
-
-#define ASM_OUTPUT_REG_PUSH(STREAM,REGNO) \
- asm_fprintf ((STREAM), "\tpush {%R%s}\n", reg_names[(REGNO)])
-
-#define ASM_OUTPUT_REG_POP(STREAM,REGNO) \
- fprintf ((STREAM), "\tpop {%R%s}\n", reg_names[(REGNO)])
-
-#define FINAL_PRESCAN_INSN(INSN,OPVEC,NOPERANDS) \
- final_prescan_insn((INSN))
-
-/* Controlling Debugging Information Format */
-#define DBX_REGISTER_NUMBER(REGNO) (REGNO)
-
-/* Specific options for DBX Output */
-
-#define DBX_DEBUGGING_INFO 1
-
-#define DEFAULT_GDB_EXTENSIONS 1
-
-
-/* Cross Compilation and Floating Point */
-
-#define REAL_ARITHMETIC
-
-
-/* Miscellaneous Parameters */
-
-#define PREDICATE_CODES \
- {"thumb_cmp_operand", {SUBREG, REG, CONST_INT}},
-
-#define CASE_VECTOR_MODE Pmode
-
-#define WORD_REGISTER_OPERATIONS
-
-#define LOAD_EXTEND_OP(MODE) ZERO_EXTEND
-
-#define IMPLICIT_FIX_EXPR FIX_ROUND_EXPR
-
-#define EASY_DIV_EXPR TRUNC_DIV_EXPR
-
-#define MOVE_MAX 4
-
-#define TRULY_NOOP_TRUNCATION(OUTPREC,INPREC) 1
-
-#define STORE_FLAG_VALUE 1
-
-#define Pmode SImode
-
-#define FUNCTION_MODE SImode
-
-#define DOLLARS_IN_IDENTIFIERS 0
-
-#define NO_DOLLAR_IN_LABEL 1
-
-#define HAVE_ATEXIT
-
-/* The literal pool needs to reside in the text area due to the
- limited PC addressing range: */
-#define MACHINE_DEPENDENT_REORG(INSN) thumb_reorg ((INSN))
-
-
-/* Options specific to Thumb */
-
-/* True if a return instruction can be used in this function. */
-int thumb_trivial_epilogue ();
-#define USE_RETURN (reload_completed && thumb_trivial_epilogue ())
-
-extern char * thumb_unexpanded_epilogue ();
-extern char * output_move_mem_multiple ();
-extern char * thumb_load_double_from_address ();
-extern char * output_return ();
-extern int far_jump_used_p();
-extern int is_called_in_ARM_mode ();
-
diff --git a/gcc/config/arm/thumb_010110a.c b/gcc/config/arm/thumb_010110a.c
deleted file mode 100755
index ef7ebff..0000000
--- a/gcc/config/arm/thumb_010110a.c
+++ /dev/null
@@ -1,2124 +0,0 @@
-/* Output routines for GCC for ARM/Thumb
- Copyright (C) 1996 Cygnus Software Technologies Ltd
- The basis of this contribution was generated by
- Richard Earnshaw, Advanced RISC Machines Ltd
-
-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. */
-
-#include <stdio.h>
-#include <string.h>
-#include "config.h"
-#include "rtl.h"
-#include "hard-reg-set.h"
-#include "regs.h"
-#include "output.h"
-#include "insn-flags.h"
-#include "insn-attr.h"
-#include "flags.h"
-#include "tree.h"
-#include "expr.h"
-
-
-int current_function_anonymous_args = 0;
-
-/* Used to parse -mstructure_size_boundary command line option. */
-char * structure_size_string = NULL;
-int arm_structure_size_boundary = 32; /* Used to be 8 */
-
-
-/* Predicates */
-int
-reload_memory_operand (op, mode)
- rtx op;
- enum machine_mode mode;
-{
- int regno = true_regnum (op);
-
- return (! CONSTANT_P (op)
- && (regno == -1
- || (GET_CODE (op) == REG
- && REGNO (op) >= FIRST_PSEUDO_REGISTER)));
-}
-
-/* Return nonzero if op is suitable for the RHS of a cmp instruction. */
-int
-thumb_cmp_operand (op, mode)
- rtx op;
- enum machine_mode mode;
-{
- return ((GET_CODE (op) == CONST_INT
- && (unsigned HOST_WIDE_INT) (INTVAL (op)) < 256)
- || register_operand (op, mode));
-}
-
-int
-thumb_shiftable_const (val)
- HOST_WIDE_INT val;
-{
- unsigned HOST_WIDE_INT x = val;
- unsigned HOST_WIDE_INT mask = 0xff;
- int i;
-
- for (i = 0; i < 25; i++)
- if ((val & (mask << i)) == val)
- return 1;
-
- return 0;
-}
-
-int
-thumb_trivial_epilogue ()
-{
- int regno;
-
- /* ??? If this function ever returns 1, we get a function without any
- epilogue at all. It appears that the intent was to cause a "return"
- insn to be emitted, but that does not happen. */
- return 0;
-
-#if 0
- if (get_frame_size ()
- || current_function_outgoing_args_size
- || current_function_pretend_args_size)
- return 0;
-
- for (regno = 8; regno < 13; regno++)
- if (regs_ever_live[regno] && ! call_used_regs[regno])
- return 0;
-
- return 1;
-#endif
-}
-
-
-/* Routines for handling the constant pool */
-/* This is unashamedly hacked from the version in sh.c, since the problem is
- extremely similar. */
-
-/* Thumb instructions cannot load a large constant into a register,
- constants have to come from a pc relative load. The reference of a pc
- relative load instruction must be less than 1k infront of the instruction.
- This means that we often have to dump a constant inside a function, and
- generate code to branch around it.
-
- It is important to minimize this, since the branches will slow things
- down and make things bigger.
-
- Worst case code looks like:
-
- ldr rn, L1
- b L2
- align
- L1: .long value
- L2:
- ..
-
- ldr rn, L3
- b L4
- align
- L3: .long value
- L4:
- ..
-
- We fix this by performing a scan before scheduling, which notices which
- instructions need to have their operands fetched from the constant table
- and builds the table.
-
-
- The algorithm is:
-
- scan, find an instruction which needs a pcrel move. Look forward, find the
- last barrier which is within MAX_COUNT bytes of the requirement.
- If there isn't one, make one. Process all the instructions between
- the find and the barrier.
-
- In the above example, we can tell that L3 is within 1k of L1, so
- the first move can be shrunk from the 2 insn+constant sequence into
- just 1 insn, and the constant moved to L3 to make:
-
- ldr rn, L1
- ..
- ldr rn, L3
- b L4
- align
- L1: .long value
- L3: .long value
- L4:
-
- Then the second move becomes the target for the shortening process.
-
- */
-
-typedef struct
-{
- rtx value; /* Value in table */
- HOST_WIDE_INT next_offset;
- enum machine_mode mode; /* Mode of value */
-} pool_node;
-
-/* The maximum number of constants that can fit into one pool, since
- the pc relative range is 0...1020 bytes and constants are at least 4
- bytes long */
-
-#define MAX_POOL_SIZE (1020/4)
-static pool_node pool_vector[MAX_POOL_SIZE];
-static int pool_size;
-static rtx pool_vector_label;
-
-/* Add a constant to the pool and return its label. */
-
-static HOST_WIDE_INT
-add_constant (x, mode)
- rtx x;
- enum machine_mode mode;
-{
- int i;
- rtx lab;
- HOST_WIDE_INT offset;
-
- if (mode == SImode && GET_CODE (x) == MEM && CONSTANT_P (XEXP (x, 0))
- && CONSTANT_POOL_ADDRESS_P (XEXP (x, 0)))
- x = get_pool_constant (XEXP (x, 0));
-
- /* First see if we've already got it */
-
- for (i = 0; i < pool_size; i++)
- {
- if (x->code == pool_vector[i].value->code
- && mode == pool_vector[i].mode)
- {
- if (x->code == CODE_LABEL)
- {
- if (XINT (x, 3) != XINT (pool_vector[i].value, 3))
- continue;
- }
- if (rtx_equal_p (x, pool_vector[i].value))
- return pool_vector[i].next_offset - GET_MODE_SIZE (mode);
- }
- }
-
- /* Need a new one */
-
- pool_vector[pool_size].next_offset = GET_MODE_SIZE (mode);
- offset = 0;
- if (pool_size == 0)
- pool_vector_label = gen_label_rtx ();
- else
- pool_vector[pool_size].next_offset
- += (offset = pool_vector[pool_size - 1].next_offset);
-
- pool_vector[pool_size].value = x;
- pool_vector[pool_size].mode = mode;
- pool_size++;
- return offset;
-}
-
-/* Output the literal table */
-
-static void
-dump_table (scan)
- rtx scan;
-{
- int i;
-
- scan = emit_label_after (gen_label_rtx (), scan);
- scan = emit_insn_after (gen_align_4 (), scan);
- scan = emit_label_after (pool_vector_label, scan);
-
- for (i = 0; i < pool_size; i++)
- {
- pool_node *p = pool_vector + i;
-
- switch (GET_MODE_SIZE (p->mode))
- {
- case 4:
- scan = emit_insn_after (gen_consttable_4 (p->value), scan);
- break;
-
- case 8:
- scan = emit_insn_after (gen_consttable_8 (p->value), scan);
- break;
-
- default:
- abort ();
- break;
- }
- }
-
- scan = emit_insn_after (gen_consttable_end (), scan);
- scan = emit_barrier_after (scan);
- pool_size = 0;
-}
-
-/* Non zero if the src operand needs to be fixed up */
-static
-int
-fixit (src, mode)
- rtx src;
- enum machine_mode mode;
-{
- return ((CONSTANT_P (src)
- && (GET_CODE (src) != CONST_INT
- || ! (CONST_OK_FOR_LETTER_P (INTVAL (src), 'I')
- || CONST_OK_FOR_LETTER_P (INTVAL (src), 'J')
- || (mode != DImode
- && CONST_OK_FOR_LETTER_P (INTVAL (src), 'K')))))
- || (mode == SImode && GET_CODE (src) == MEM
- && GET_CODE (XEXP (src, 0)) == SYMBOL_REF
- && CONSTANT_POOL_ADDRESS_P (XEXP (src, 0))));
-}
-
-/* Find the last barrier less than MAX_COUNT bytes from FROM, or create one. */
-
-#define MAX_COUNT_SI 1000
-
-static rtx
-find_barrier (from)
- rtx from;
-{
- int count = 0;
- rtx found_barrier = 0;
- rtx label;
-
- while (from && count < MAX_COUNT_SI)
- {
- if (GET_CODE (from) == BARRIER)
- return from;
-
- /* Count the length of this insn */
- if (GET_CODE (from) == INSN
- && GET_CODE (PATTERN (from)) == SET
- && CONSTANT_P (SET_SRC (PATTERN (from)))
- && CONSTANT_POOL_ADDRESS_P (SET_SRC (PATTERN (from))))
- {
- rtx src = SET_SRC (PATTERN (from));
- count += 2;
- }
- else
- count += get_attr_length (from);
-
- from = NEXT_INSN (from);
- }
-
- /* We didn't find a barrier in time to
- dump our stuff, so we'll make one */
- label = gen_label_rtx ();
-
- if (from)
- from = PREV_INSN (from);
- else
- from = get_last_insn ();
-
- /* Walk back to be just before any jump */
- while (GET_CODE (from) == JUMP_INSN
- || GET_CODE (from) == NOTE
- || GET_CODE (from) == CODE_LABEL)
- from = PREV_INSN (from);
-
- from = emit_jump_insn_after (gen_jump (label), from);
- JUMP_LABEL (from) = label;
- found_barrier = emit_barrier_after (from);
- emit_label_after (label, found_barrier);
- return found_barrier;
-}
-
-/* Non zero if the insn is a move instruction which needs to be fixed. */
-
-static int
-broken_move (insn)
- rtx insn;
-{
- if (!INSN_DELETED_P (insn)
- && GET_CODE (insn) == INSN
- && GET_CODE (PATTERN (insn)) == SET)
- {
- rtx pat = PATTERN (insn);
- rtx src = SET_SRC (pat);
- rtx dst = SET_DEST (pat);
- enum machine_mode mode = GET_MODE (dst);
- if (dst == pc_rtx)
- return 0;
- return fixit (src, mode);
- }
- return 0;
-}
-
-/* Recursively search through all of the blocks in a function
- checking to see if any of the variables created in that
- function match the RTX called 'orig'. If they do then
- replace them with the RTX called 'new'. */
-
-static void
-replace_symbols_in_block (tree block, rtx orig, rtx new)
-{
- for (; block; block = BLOCK_CHAIN (block))
- {
- tree sym;
-
- if (! TREE_USED (block))
- continue;
-
- for (sym = BLOCK_VARS (block); sym; sym = TREE_CHAIN (sym))
- {
- if ( (DECL_NAME (sym) == 0 && TREE_CODE (sym) != TYPE_DECL)
- || DECL_IGNORED_P (sym)
- || TREE_CODE (sym) != VAR_DECL
- || DECL_EXTERNAL (sym)
- || ! rtx_equal_p (DECL_RTL (sym), orig)
- )
- continue;
-
- DECL_RTL (sym) = new;
- }
-
- replace_symbols_in_block (BLOCK_SUBBLOCKS (block), orig, new);
- }
-}
-
-void
-thumb_reorg (first)
- rtx first;
-{
- rtx insn;
- for (insn = first; insn; insn = NEXT_INSN (insn))
- {
- if (broken_move (insn))
- {
- /* This is a broken move instruction, scan ahead looking for
- a barrier to stick the constant table behind */
- rtx scan;
- rtx barrier = find_barrier (insn);
-
- /* Now find all the moves between the points and modify them */
- for (scan = insn; scan != barrier; scan = NEXT_INSN (scan))
- {
- if (broken_move (scan))
- {
- /* This is a broken move instruction, add it to the pool */
- rtx pat = PATTERN (scan);
- rtx src = SET_SRC (pat);
- rtx dst = SET_DEST (pat);
- enum machine_mode mode = GET_MODE (dst);
- HOST_WIDE_INT offset;
- rtx newinsn;
- rtx newsrc;
-
- /* If this is an HImode constant load, convert it into
- an SImode constant load. Since the register is always
- 32 bits this is safe. We have to do this, since the
- load pc-relative instruction only does a 32-bit load. */
- if (mode == HImode)
- {
- mode = SImode;
- if (GET_CODE (dst) != REG)
- abort ();
- PUT_MODE (dst, SImode);
- }
-
- offset = add_constant (src, mode);
- newsrc = gen_rtx (MEM, mode,
- plus_constant (gen_rtx (LABEL_REF,
- VOIDmode,
- pool_vector_label),
- offset));
-
- /* Build a jump insn wrapper around the move instead
- of an ordinary insn, because we want to have room for
- the target label rtx in fld[7], which an ordinary
- insn doesn't have. */
- newinsn = emit_jump_insn_after (gen_rtx (SET, VOIDmode,
- dst, newsrc), scan);
- JUMP_LABEL (newinsn) = pool_vector_label;
-
- /* But it's still an ordinary insn */
- PUT_CODE (newinsn, INSN);
-
- /* If debugging information is going to be emitted
- then we must make sure that any refences to
- symbols which are removed by the above code are
- also removed in the descriptions of the
- function's variables. Failure to do this means
- that the debugging information emitted could
- refer to symbols which are not emited by
- output_constant_pool() because
- mark_constant_pool() never sees them as being
- used. */
-
-
- /* These are the tests used in
- output_constant_pool() to decide if the constant
- pool will be marked. Only necessary if debugging
- info is being emitted. Only necessary for
- references to memory whose address is given by a
- symbol. */
-
- if (optimize > 0
- && flag_expensive_optimizations
- && write_symbols != NO_DEBUG
- && GET_CODE (src) == MEM
- && GET_CODE (XEXP (src, 0)) == SYMBOL_REF)
- replace_symbols_in_block
- (DECL_INITIAL (current_function_decl), src, newsrc);
-
- /* Kill old insn */
- delete_insn (scan);
- scan = newinsn;
- }
- }
- dump_table (barrier);
- }
- }
-}
-
-
-/* Routines for generating rtl */
-
-void
-thumb_expand_movstrqi (operands)
- rtx *operands;
-{
- rtx out = copy_to_mode_reg (SImode, XEXP (operands[0], 0));
- rtx in = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
- HOST_WIDE_INT len = INTVAL (operands[2]);
- HOST_WIDE_INT offset = 0;
-
- while (len >= 12)
- {
- emit_insn (gen_movmem12b (out, in));
- len -= 12;
- }
- if (len >= 8)
- {
- emit_insn (gen_movmem8b (out, in));
- len -= 8;
- }
- if (len >= 4)
- {
- rtx reg = gen_reg_rtx (SImode);
- emit_insn (gen_movsi (reg, gen_rtx (MEM, SImode, in)));
- emit_insn (gen_movsi (gen_rtx (MEM, SImode, out), reg));
- len -= 4;
- offset += 4;
- }
- if (len >= 2)
- {
- rtx reg = gen_reg_rtx (HImode);
- emit_insn (gen_movhi (reg, gen_rtx (MEM, HImode,
- plus_constant (in, offset))));
- emit_insn (gen_movhi (gen_rtx (MEM, HImode, plus_constant (out, offset)),
- reg));
- len -= 2;
- offset += 2;
- }
- if (len)
- {
- rtx reg = gen_reg_rtx (QImode);
- emit_insn (gen_movqi (reg, gen_rtx (MEM, QImode,
- plus_constant (in, offset))));
- emit_insn (gen_movqi (gen_rtx (MEM, QImode, plus_constant (out, offset)),
- reg));
- }
-}
-
-
-/* Routines for reloading */
-
-void
-thumb_reload_out_si (operands)
- rtx operands;
-{
- abort ();
-}
-
-/* CYGNUS LOCAL nickc/thumb-pe */
-
-#ifdef THUMB_PE
-/* Return non-zero if FUNC is a naked function. */
-
-static int
-arm_naked_function_p (func)
- tree func;
-{
- tree a;
-
- if (TREE_CODE (func) != FUNCTION_DECL)
- abort ();
-
- a = lookup_attribute ("naked", DECL_MACHINE_ATTRIBUTES (func));
- return a != NULL_TREE;
-}
-#endif
-/* END CYGNUS LOCAL nickc/thumb-pe */
-
-/* Return non-zero if FUNC must be entered in ARM mode. */
-int
-is_called_in_ARM_mode (func)
- tree func;
-{
- if (TREE_CODE (func) != FUNCTION_DECL)
- abort ();
-
- /* Ignore the problem about functions whoes address is taken. */
- if (TARGET_CALLEE_INTERWORKING && TREE_PUBLIC (func))
- return TRUE;
-
-/* CYGNUS LOCAL nickc/thumb-pe */
-#ifdef THUMB_PE
- return lookup_attribute ("interfacearm", DECL_MACHINE_ATTRIBUTES (func)) != NULL_TREE;
-#else
- return FALSE;
-#endif
-/* END CYGNUS LOCAL */
-}
-
-
-/* Routines for emitting code */
-
-void
-final_prescan_insn(insn)
- rtx insn;
-{
- extern int *insn_addresses;
-
- if (flag_print_asm_name)
- fprintf (asm_out_file, "%s 0x%04x\n", ASM_COMMENT_START,
- insn_addresses[INSN_UID (insn)]);
-}
-
-
-static void thumb_pushpop ( FILE *, int, int ); /* Forward declaration. */
-
-#ifdef __GNUC__
-inline
-#endif
-static int
-number_of_first_bit_set (mask)
- int mask;
-{
- int bit;
-
- for (bit = 0;
- (mask & (1 << bit)) == 0;
- ++ bit)
- continue;
-
- return bit;
-}
-
-#define ARG_1_REGISTER 0
-#define ARG_2_REGISTER 1
-#define ARG_3_REGISTER 2
-#define ARG_4_REGISTER 3
-#define WORK_REGISTER 7
-#define FRAME_POINTER 11
-#define IP_REGISTER 12
-#define STACK_POINTER STACK_POINTER_REGNUM
-#define LINK_REGISTER 14
-#define PROGRAM_COUNTER 15
-
-/* Generate code to return from a thumb function. If
- 'reg_containing_return_addr' is -1, then the return address is
- actually on the stack, at the stack pointer. */
-static void
-thumb_exit (f, reg_containing_return_addr)
- FILE * f;
- int reg_containing_return_addr;
-{
- int regs_available_for_popping;
- int regs_to_pop;
- int pops_needed;
- int reg;
- int available;
- int required;
- int mode;
- int size;
- int restore_a4 = FALSE;
-
- /* Compute the registers we need to pop. */
- regs_to_pop = 0;
- pops_needed = 0;
-
- if (reg_containing_return_addr == -1)
- {
- regs_to_pop |= 1 << LINK_REGISTER;
- ++ pops_needed;
- }
-
- if (TARGET_BACKTRACE)
- {
- /* Restore frame pointer and stack pointer. */
- regs_to_pop |= (1 << FRAME_POINTER) | (1 << STACK_POINTER);
- pops_needed += 2;
- }
-
- /* If there is nothing to pop then just emit the BX instruction and return.*/
- if (pops_needed == 0)
- {
- asm_fprintf (f, "\tbx\t%s\n", reg_names [reg_containing_return_addr]);
-
- return;
- }
-
- /* Otherwise if we are not supporting interworking and we have not created
- a backtrace structure and the function was not entered in ARM mode then
- just pop the return address straight into the PC. */
- else if ( ! TARGET_THUMB_INTERWORK
- && ! TARGET_BACKTRACE
- && ! is_called_in_ARM_mode (current_function_decl))
- {
- asm_fprintf (f, "\tpop\t{pc}\n" );
-
- return;
- }
-
- /* Find out how many of the (return) argument registers we can corrupt. */
- regs_available_for_popping = 0;
-
-#ifdef RTX_CODE
- /* If we can deduce the registers used from the function's return value.
- This is more reliable that examining regs_ever_live[] because that
- will be set if the register is ever used in the function, not just if
- the register is used to hold a return value. */
-
- if (current_function_return_rtx != 0)
- mode = GET_MODE (current_function_return_rtx);
- else
-#endif
- mode = DECL_MODE (DECL_RESULT (current_function_decl));
-
- size = GET_MODE_SIZE (mode);
-
- if (size == 0)
- {
- /* In a void function we can use any argument register.
- In a function that returns a structure on the stack
- we can use the second and third argument registers. */
- if (mode == VOIDmode)
- regs_available_for_popping =
- (1 << ARG_1_REGISTER)
- | (1 << ARG_2_REGISTER)
- | (1 << ARG_3_REGISTER);
- else
- regs_available_for_popping =
- (1 << ARG_2_REGISTER)
- | (1 << ARG_3_REGISTER);
- }
- else if (size <= 4) regs_available_for_popping =
- (1 << ARG_2_REGISTER)
- | (1 << ARG_3_REGISTER);
- else if (size <= 8) regs_available_for_popping =
- (1 << ARG_3_REGISTER);
-
- /* Match registers to be popped with registers into which we pop them. */
- for (available = regs_available_for_popping,
- required = regs_to_pop;
- required != 0 && available != 0;
- available &= ~(available & - available),
- required &= ~(required & - required))
- -- pops_needed;
-
- /* If we have any popping registers left over, remove them. */
- if (available > 0)
- regs_available_for_popping &= ~ available;
-
- /* Otherwise if we need another popping register we can use
- the fourth argument register. */
- else if (pops_needed)
- {
- /* If we have not found any free argument registers and
- reg a4 contains the return address, we must move it. */
- if (regs_available_for_popping == 0
- && reg_containing_return_addr == ARG_4_REGISTER)
- {
- asm_fprintf (f, "\tmov\t%s, %s\n",
- reg_names [LINK_REGISTER], reg_names [ARG_4_REGISTER]);
- reg_containing_return_addr = LINK_REGISTER;
- }
- else if (size > 12)
- {
- /* Register a4 is being used to hold part of the return value,
- but we have dire need of a free, low register. */
- restore_a4 = TRUE;
-
- asm_fprintf (f, "\tmov\t%s, %s\n",
- reg_names [IP_REGISTER], reg_names [ARG_4_REGISTER]);
- }
-
- if (reg_containing_return_addr != ARG_4_REGISTER)
- {
- /* The fourth argument register is available. */
- regs_available_for_popping |= 1 << ARG_4_REGISTER;
-
- -- pops_needed;
- }
- }
-
- /* Pop as many registers as we can. */
- thumb_pushpop (f, regs_available_for_popping, FALSE);
-
- /* Process the registers we popped. */
- if (reg_containing_return_addr == -1)
- {
- /* The return address was popped into the lowest numbered register. */
- regs_to_pop &= ~ (1 << LINK_REGISTER);
-
- reg_containing_return_addr =
- number_of_first_bit_set (regs_available_for_popping);
-
- /* Remove this register for the mask of available registers, so that
- the return address will not be corrupted by futher pops. */
- regs_available_for_popping &= ~ (1 << reg_containing_return_addr);
- }
-
- /* If we popped other registers then handle them here. */
- if (regs_available_for_popping)
- {
- int frame_pointer;
-
- /* Work out which register currently contains the frame pointer. */
- frame_pointer = number_of_first_bit_set (regs_available_for_popping);
-
- /* Move it into the correct place. */
- asm_fprintf (f, "\tmov\tfp, %s\n", reg_names [frame_pointer]);
-
- /* (Temporarily) remove it from the mask of popped registers. */
- regs_available_for_popping &= ~ (1 << frame_pointer);
- regs_to_pop &= ~ (1 << FRAME_POINTER);
-
- if (regs_available_for_popping)
- {
- int stack_pointer;
-
- /* We popped the stack pointer as well, find the register that
- contains it.*/
- stack_pointer = number_of_first_bit_set (regs_available_for_popping);
-
- /* Move it into the stack register. */
- asm_fprintf (f, "\tmov\tsp, %s\n", reg_names [stack_pointer]);
-
- /* At this point we have popped all necessary registers, so
- do not worry about restoring regs_available_for_popping
- to its correct value:
-
- assert (pops_needed == 0)
- assert (regs_available_for_popping == (1 << frame_pointer))
- assert (regs_to_pop == (1 << STACK_POINTER)) */
- }
- else
- {
- /* Since we have just move the popped value into the frame
- pointer, the popping register is available for reuse, and
- we know that we still have the stack pointer left to pop. */
- regs_available_for_popping |= (1 << frame_pointer);
- }
- }
-
- /* If we still have registers left on the stack, but we no longer have
- any registers into which we can pop them, then we must move the return
- address into the link register and make available the register that
- contained it. */
- if (regs_available_for_popping == 0 && pops_needed > 0)
- {
- regs_available_for_popping |= 1 << reg_containing_return_addr;
-
- asm_fprintf (f, "\tmov\t%s, %s\n",
- reg_names [LINK_REGISTER],
- reg_names [reg_containing_return_addr]);
-
- reg_containing_return_addr = LINK_REGISTER;
- }
-
- /* If we have registers left on the stack then pop some more.
- We know that at most we will want to pop FP and SP. */
- if (pops_needed > 0)
- {
- int popped_into;
- int move_to;
-
- thumb_pushpop (f, regs_available_for_popping, FALSE);
-
- /* We have popped either FP or SP.
- Move whichever one it is into the correct register. */
- popped_into = number_of_first_bit_set (regs_available_for_popping);
- move_to = number_of_first_bit_set (regs_to_pop);
-
- asm_fprintf (f, "\tmov\t%s, %s\n",
- reg_names [move_to], reg_names [popped_into]);
-
- regs_to_pop &= ~ (1 << move_to);
-
- -- pops_needed;
- }
-
- /* If we still have not popped everything then we must have only
- had one register available to us and we are now popping the SP. */
- if (pops_needed > 0)
- {
- int popped_into;
-
- thumb_pushpop (f, regs_available_for_popping, FALSE);
-
- popped_into = number_of_first_bit_set (regs_available_for_popping);
-
- asm_fprintf (f, "\tmov\tsp, %s\n", reg_names [popped_into]);
-
- /*
- assert (regs_to_pop == (1 << STACK_POINTER))
- assert (pops_needed == 1)
- */
- }
-
- /* If necessary restore the a4 register. */
- if (restore_a4)
- {
- if (reg_containing_return_addr != LINK_REGISTER)
- {
- asm_fprintf (f, "\tmov\t%s, %s\n",
- reg_names [LINK_REGISTER], reg_names [ARG_4_REGISTER]);
- reg_containing_return_addr = LINK_REGISTER;
- }
-
- asm_fprintf (f, "\tmov\t%s, %s\n",
- reg_names [ARG_4_REGISTER], reg_names [IP_REGISTER]);
- }
-
- /* Return to caller. */
- asm_fprintf (f, "\tbx\t%s\n", reg_names [reg_containing_return_addr]);
-}
-
-/* Emit code to push or pop registers to or from the stack. */
-static void
-thumb_pushpop (f, mask, push)
- FILE * f;
- int mask;
- int push;
-{
- int regno;
- int lo_mask = mask & 0xFF;
-
- if (lo_mask == 0 && ! push && (mask & (1 << 15)))
- {
- /* Special case. Do not generate a POP PC statement here, do it in
- thumb_exit() */
-
- thumb_exit (f, -1);
- return;
- }
-
- asm_fprintf (f, "\t%s\t{", push ? "push" : "pop");
-
- /* Look at the low registers first. */
-
- for (regno = 0; regno < 8; regno ++, lo_mask >>= 1)
- {
- if (lo_mask & 1)
- {
- asm_fprintf (f, reg_names[regno]);
-
- if ((lo_mask & ~1) != 0)
- asm_fprintf (f, ", ");
- }
- }
-
- if (push && (mask & (1 << 14)))
- {
- /* Catch pushing the LR. */
-
- if (mask & 0xFF)
- asm_fprintf (f, ", ");
-
- asm_fprintf (f, reg_names[14]);
- }
- else if (!push && (mask & (1 << 15)))
- {
- /* Catch popping the PC. */
-
- if (TARGET_THUMB_INTERWORK || TARGET_BACKTRACE)
- {
- /* The PC is never poped directly, instead
- it is popped into r3 and then BX is used. */
-
- asm_fprintf (f, "}\n");
-
- thumb_exit (f, -1);
-
- return;
- }
- else
- {
- if (mask & 0xFF)
- asm_fprintf (f, ", ");
-
- asm_fprintf (f, reg_names[15]);
- }
- }
-
- asm_fprintf (f, "}\n");
-}
-
-/* Returns non-zero if the current function contains a far jump */
-
-int
-far_jump_used_p (void)
-{
- rtx insn;
-
- for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
- {
- if (GET_CODE (insn) == JUMP_INSN
- /* Ignore tablejump patterns. */
- && GET_CODE (PATTERN (insn)) != ADDR_VEC
- && GET_CODE (PATTERN (insn)) != ADDR_DIFF_VEC
- && get_attr_far_jump (insn) == FAR_JUMP_YES)
- return 1;
- }
-
- return 0;
-}
-
-static int return_used_this_function = 0;
-
-char *
-output_return ()
-{
- int regno;
- int live_regs_mask = 0;
-
- /* CYGNUS LOCAL nickc/thumb-pe */
-#ifdef THUMB_PE
- /* If a function is naked, don't use the "return" insn. */
- if (arm_naked_function_p (current_function_decl))
- return "";
-#endif
- /* END CYGNUS LOCAL nickc/thumb-pe */
-
- return_used_this_function = 1;
-
- for (regno = 0; regno < 8; regno++)
- if (regs_ever_live[regno] && ! call_used_regs[regno])
- live_regs_mask |= 1 << regno;
-
- if (live_regs_mask == 0)
- {
- if (leaf_function_p () && ! far_jump_used_p())
- {
- thumb_exit (asm_out_file, 14);
- }
- else if ( TARGET_THUMB_INTERWORK
- || TARGET_BACKTRACE
- || is_called_in_ARM_mode (current_function_decl))
- {
- thumb_exit (asm_out_file, -1);
- }
- else
- asm_fprintf (asm_out_file, "\tpop\t{pc}\n");
- }
- else
- {
- asm_fprintf (asm_out_file, "\tpop\t{");
-
- for (regno = 0; live_regs_mask; regno ++, live_regs_mask >>= 1)
- if (live_regs_mask & 1)
- {
- asm_fprintf (asm_out_file, reg_names[regno]);
- if (live_regs_mask & ~1)
- asm_fprintf (asm_out_file, ", ");
- }
-
- if ( TARGET_THUMB_INTERWORK
- || TARGET_BACKTRACE
- || is_called_in_ARM_mode (current_function_decl))
- {
- asm_fprintf (asm_out_file, "}\n");
- thumb_exit (asm_out_file, -1);
- }
- else
- asm_fprintf (asm_out_file, ", pc}\n");
- }
-
- return "";
-}
-
-void
-thumb_function_prologue (f, frame_size)
- FILE *f;
- int frame_size;
-{
- int amount = frame_size + current_function_outgoing_args_size;
- int live_regs_mask = 0;
- int high_regs_pushed = 0;
- int store_arg_regs = 0;
- int regno;
-
-/* CYGNUS LOCAL nickc/thumb-pe */
-#ifdef THUMB_PE
- if (arm_naked_function_p (current_function_decl))
- return;
-#endif
-/* CYGNUS LOCAL nickc/thumb-pe */
-
- if (is_called_in_ARM_mode (current_function_decl))
- {
- char * name;
- if (GET_CODE (DECL_RTL (current_function_decl)) != MEM)
- abort();
- if (GET_CODE (XEXP (DECL_RTL (current_function_decl), 0)) != SYMBOL_REF)
- abort();
- name = XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0);
-
- /* Generate code sequence to switch us into Thumb mode. */
- /* The .code 32 directive has already been emitted by
- ASM_DECLARE_FUNCITON_NAME */
- asm_fprintf (f, "\torr\tr12, pc, #1\n");
- asm_fprintf (f, "\tbx\tr12\n");
-
- /* Generate a label, so that the debugger will notice the
- change in instruction sets. This label is also used by
- the assembler to bypass the ARM code when this function
- is called from a Thumb encoded function elsewhere in the
- same file. Hence the definition of STUB_NAME here must
- agree with the definition in gas/config/tc-arm.c */
-
-#define STUB_NAME ".real_start_of"
-
- asm_fprintf (f, "\t.code\t16\n");
- asm_fprintf (f, "\t.globl %s%U%s\n", STUB_NAME, name);
- asm_fprintf (f, "\t.thumb_func\n");
- asm_fprintf (f, "%s%U%s:\n", STUB_NAME, name);
- }
-
- if (current_function_anonymous_args && current_function_pretend_args_size)
- store_arg_regs = 1;
-
- if (current_function_pretend_args_size)
- {
- if (store_arg_regs)
- {
- asm_fprintf (f, "\tpush\t{");
- for (regno = 4 - current_function_pretend_args_size / 4 ; regno < 4;
- regno++)
- asm_fprintf (f, "%s%s", reg_names[regno], regno == 3 ? "" : ", ");
- asm_fprintf (f, "}\n");
- }
- else
- asm_fprintf (f, "\tsub\t%Rsp, %Rsp, #%d\n",
- current_function_pretend_args_size);
- }
-
- for (regno = 0; regno < 8; regno++)
- if (regs_ever_live[regno] && ! call_used_regs[regno])
- live_regs_mask |= 1 << regno;
-
- if (live_regs_mask || ! leaf_function_p () || far_jump_used_p())
- live_regs_mask |= 1 << 14;
-
- if (TARGET_BACKTRACE)
- {
- char * name;
- int offset;
- int work_register = 0;
-
-
- /* We have been asked to create a stack backtrace structure.
- The code looks like this:
-
- 0 .align 2
- 0 func:
- 0 sub SP, #16 Reserve space for 4 registers.
- 2 push {R7} Get a work register.
- 4 add R7, SP, #20 Get the stack pointer before the push.
- 6 str R7, [SP, #8] Store the stack pointer (before reserving the space).
- 8 mov R7, PC Get hold of the start of this code plus 12.
- 10 str R7, [SP, #16] Store it.
- 12 mov R7, FP Get hold of the current frame pointer.
- 14 str R7, [SP, #4] Store it.
- 16 mov R7, LR Get hold of the current return address.
- 18 str R7, [SP, #12] Store it.
- 20 add R7, SP, #16 Point at the start of the backtrace structure.
- 22 mov FP, R7 Put this value into the frame pointer. */
-
- if ((live_regs_mask & 0xFF) == 0)
- {
- /* See if the a4 register is free. */
-
- if (regs_ever_live[ 3 ] == 0)
- work_register = 3;
- else /* We must push a register of our own */
- live_regs_mask |= (1 << 7);
- }
-
- if (work_register == 0)
- {
- /* Select a register from the list that will be pushed to use as our work register. */
-
- for (work_register = 8; work_register--;)
- if ((1 << work_register) & live_regs_mask)
- break;
- }
-
- name = reg_names[ work_register ];
-
- asm_fprintf (f, "\tsub\tsp, sp, #16\t@ Create stack backtrace structure\n");
-
- if (live_regs_mask)
- thumb_pushpop (f, live_regs_mask, 1);
-
- for (offset = 0, work_register = 1 << 15; work_register; work_register >>= 1)
- if (work_register & live_regs_mask)
- offset += 4;
-
- asm_fprintf (f, "\tadd\t%s, sp, #%d\n",
- name, offset + 16 + current_function_pretend_args_size);
-
- asm_fprintf (f, "\tstr\t%s, [sp, #%d]\n", name, offset + 4);
-
- /* Make sure that the instruction fetching the PC is in the right place
- to calculate "start of backtrace creation code + 12". */
-
- if (live_regs_mask)
- {
- asm_fprintf (f, "\tmov\t%s, pc\n", name);
- asm_fprintf (f, "\tstr\t%s, [sp, #%d]\n", name, offset + 12);
- asm_fprintf (f, "\tmov\t%s, fp\n", name);
- asm_fprintf (f, "\tstr\t%s, [sp, #%d]\n", name, offset);
- }
- else
- {
- asm_fprintf (f, "\tmov\t%s, fp\n", name);
- asm_fprintf (f, "\tstr\t%s, [sp, #%d]\n", name, offset);
- asm_fprintf (f, "\tmov\t%s, pc\n", name);
- asm_fprintf (f, "\tstr\t%s, [sp, #%d]\n", name, offset + 12);
- }
-
- asm_fprintf (f, "\tmov\t%s, lr\n", name);
- asm_fprintf (f, "\tstr\t%s, [sp, #%d]\n", name, offset + 8);
- asm_fprintf (f, "\tadd\t%s, sp, #%d\n", name, offset + 12);
- asm_fprintf (f, "\tmov\tfp, %s\t\t@ Backtrace structure created\n", name);
- }
- else if (live_regs_mask)
- thumb_pushpop (f, live_regs_mask, 1);
-
- for (regno = 8; regno < 13; regno++)
- {
- if (regs_ever_live[regno] && ! call_used_regs[regno])
- high_regs_pushed++;
- }
-
- if (high_regs_pushed)
- {
- int pushable_regs = 0;
- int mask = live_regs_mask & 0xff;
- int next_hi_reg;
-
- for (next_hi_reg = 12; next_hi_reg > 7; next_hi_reg--)
- {
- if (regs_ever_live[next_hi_reg] && ! call_used_regs[next_hi_reg])
- break;
- }
-
- pushable_regs = mask;
-
- if (pushable_regs == 0)
- {
- /* desperation time -- this probably will never happen */
- if (regs_ever_live[3] || ! call_used_regs[3])
- asm_fprintf (f, "\tmov\t%s, %s\n", reg_names[12], reg_names[3]);
- mask = 1 << 3;
- }
-
- while (high_regs_pushed > 0)
- {
- for (regno = 7; regno >= 0; regno--)
- {
- if (mask & (1 << regno))
- {
- asm_fprintf (f, "\tmov\t%s, %s\n", reg_names[regno],
- reg_names[next_hi_reg]);
- high_regs_pushed--;
- if (high_regs_pushed)
- for (next_hi_reg--; next_hi_reg > 7; next_hi_reg--)
- {
- if (regs_ever_live[next_hi_reg]
- && ! call_used_regs[next_hi_reg])
- break;
- }
- else
- {
- mask &= ~ ((1 << regno) - 1);
- break;
- }
- }
- }
- thumb_pushpop (f, mask, 1);
- }
-
- if (pushable_regs == 0 && (regs_ever_live[3] || ! call_used_regs[3]))
- asm_fprintf (f, "\tmov\t%s, %s\n", reg_names[3], reg_names[12]);
- }
-}
-
-void
-thumb_expand_prologue ()
-{
- HOST_WIDE_INT amount = (get_frame_size ()
- + current_function_outgoing_args_size);
- int regno;
- int live_regs_mask;
-
- /* CYGNUS LOCAL nickc/thumb-pe */
-#ifdef THUMB_PE
- /* Naked functions don't have prologues. */
- if (arm_naked_function_p (current_function_decl))
- return;
-#endif
- /* END CYGNUS LOCAL nickc/thumb-pe */
-
- if (amount)
- {
- live_regs_mask = 0;
- for (regno = 0; regno < 8; regno++)
- if (regs_ever_live[regno] && ! call_used_regs[regno])
- live_regs_mask |= 1 << regno;
-
- if (amount < 512)
- emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
- GEN_INT (-amount)));
- else
- {
- rtx reg, spare;
-
- if ((live_regs_mask & 0xff) == 0) /* Very unlikely */
- emit_insn (gen_movsi (spare = gen_rtx (REG, SImode, 12),
- reg = gen_rtx (REG, SImode, 4)));
- else
- {
- for (regno = 0; regno < 8; regno++)
- if (live_regs_mask & (1 << regno))
- break;
- reg = gen_rtx (REG, SImode, regno);
- }
-
- emit_insn (gen_movsi (reg, GEN_INT (-amount)));
- emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, reg));
- if ((live_regs_mask & 0xff) == 0)
- emit_insn (gen_movsi (reg, spare));
- }
- }
-
- if (frame_pointer_needed)
- {
- if (current_function_outgoing_args_size)
- {
- rtx offset = GEN_INT (current_function_outgoing_args_size);
-
- if (current_function_outgoing_args_size < 1024)
- emit_insn (gen_addsi3 (frame_pointer_rtx, stack_pointer_rtx,
- offset));
- else
- {
- emit_insn (gen_movsi (frame_pointer_rtx, offset));
- emit_insn (gen_addsi3 (frame_pointer_rtx, frame_pointer_rtx,
- stack_pointer_rtx));
- }
- }
- else
- emit_insn (gen_movsi (frame_pointer_rtx, stack_pointer_rtx));
- }
-
- /* if (profile_flag || profile_block_flag) */
- emit_insn (gen_blockage ());
-}
-
-void
-thumb_expand_epilogue ()
-{
- HOST_WIDE_INT amount = (get_frame_size ()
- + current_function_outgoing_args_size);
- int regno;
-
- /* CYGNUS LOCAL nickc/thumb-pe */
-#ifdef THUMB_PE
- /* Naked functions don't have epilogues. */
- if (arm_naked_function_p (current_function_decl))
- return;
-#endif
- /* END CYGNUS LOCAL nickc/thumb-pe */
-
- if (amount)
- {
- if (amount < 512)
- emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
- GEN_INT (amount)));
- else
- {
- rtx reg = gen_rtx (REG, SImode, 3); /* Always free in the epilogue */
-
- emit_insn (gen_movsi (reg, GEN_INT (amount)));
- emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, reg));
- }
- /* if (profile_flag || profile_block_flag) */
- emit_insn (gen_blockage ());
- }
-}
-
-void
-thumb_function_epilogue (f, frame_size)
- FILE *f;
- int frame_size;
-{
- /* ??? Probably not safe to set this here, since it assumes that a
- function will be emitted as assembly immediately after we generate
- RTL for it. This does not happen for inline functions. */
- return_used_this_function = 0;
-#if 0 /* TODO : comment not really needed */
- fprintf (f, "%s THUMB Epilogue\n", ASM_COMMENT_START);
-#endif
-}
-
-/* The bits which aren't usefully expanded as rtl. */
-char *
-thumb_unexpanded_epilogue ()
-{
- int regno;
- int live_regs_mask = 0;
- int high_regs_pushed = 0;
- int leaf_function = leaf_function_p ();
- int had_to_push_lr;
-
- if (return_used_this_function)
- return "";
-
- for (regno = 0; regno < 8; regno++)
- if (regs_ever_live[regno] && ! call_used_regs[regno])
- live_regs_mask |= 1 << regno;
-
- for (regno = 8; regno < 13; regno++)
- {
- if (regs_ever_live[regno] && ! call_used_regs[regno])
- high_regs_pushed ++;
- }
-
- /* The prolog may have pushed some high registers to use as
- work registers. eg the testuite file:
- gcc/testsuite/gcc/gcc.c-torture/execute/complex-2.c
- compiles to produce:
- push {r4, r5, r6, r7, lr}
- mov r7, r9
- mov r6, r8
- push {r6, r7}
- as part of the prolog. We have to undo that pushing here. */
-
- if (high_regs_pushed)
- {
- int mask = live_regs_mask;
- int next_hi_reg;
- int size;
- int mode;
-
-#ifdef RTX_CODE
- /* If we can deduce the registers used from the function's return value.
- This is more reliable that examining regs_ever_live[] because that
- will be set if the register is ever used in the function, not just if
- the register is used to hold a return value. */
-
- if (current_function_return_rtx != 0)
- {
- mode = GET_MODE (current_function_return_rtx);
- }
- else
-#endif
- {
- mode = DECL_MODE (DECL_RESULT (current_function_decl));
- }
-
- size = GET_MODE_SIZE (mode);
-
- /* Unless we are returning a type of size > 12 register r3 is available. */
- if (size < 13)
- mask |= 1 << 3;
-
- if (mask == 0)
- {
- /* Oh dear! We have no low registers into which we can pop high registers! */
-
- fatal ("No low registers available for popping high registers");
- }
-
- for (next_hi_reg = 8; next_hi_reg < 13; next_hi_reg++)
- if (regs_ever_live[next_hi_reg] && ! call_used_regs[next_hi_reg])
- break;
-
- while (high_regs_pushed)
- {
- /* Find low register(s) into which the high register(s) can be popped. */
- for (regno = 0; regno < 8; regno++)
- {
- if (mask & (1 << regno))
- high_regs_pushed--;
- if (high_regs_pushed == 0)
- break;
- }
-
- mask &= (2 << regno) - 1; /* A noop if regno == 8 */
-
- /* Pop the values into the low register(s). */
- thumb_pushpop (asm_out_file, mask, 0);
-
- /* Move the value(s) into the high registers. */
- for (regno = 0; regno < 8; regno++)
- {
- if (mask & (1 << regno))
- {
- asm_fprintf (asm_out_file, "\tmov\t%s, %s\n",
- reg_names[next_hi_reg], reg_names[regno]);
- for (next_hi_reg++; next_hi_reg < 13; next_hi_reg++)
- if (regs_ever_live[next_hi_reg] &&
- ! call_used_regs[next_hi_reg])
- break;
- }
- }
- }
- }
-
- had_to_push_lr = (live_regs_mask || ! leaf_function || far_jump_used_p());
-
- if (TARGET_BACKTRACE && ((live_regs_mask & 0xFF) == 0) && regs_ever_live[ ARG_4_REGISTER ] != 0)
- {
- /* The stack backtrace structure creation code had to
- push R7 in order to get a work register, so we pop
- it now. */
-
- live_regs_mask |= (1 << WORK_REGISTER);
- }
-
- if (current_function_pretend_args_size == 0 || TARGET_BACKTRACE)
- {
- if (had_to_push_lr
- && ! is_called_in_ARM_mode (current_function_decl))
- live_regs_mask |= 1 << PROGRAM_COUNTER;
-
- /* Either no argument registers were pushed or a backtrace
- structure was created which includes an adjusted stack
- pointer, so just pop everything. */
-
- if (live_regs_mask)
- thumb_pushpop (asm_out_file, live_regs_mask, FALSE);
-
- /* We have either just popped the return address into the
- PC or it is was kept in LR for the entire function or
- it is still on the stack because we do not want to
- return by doing a pop {pc}. */
-
- if ((live_regs_mask & (1 << PROGRAM_COUNTER)) == 0)
- thumb_exit (asm_out_file,
- (had_to_push_lr
- && is_called_in_ARM_mode (current_function_decl)) ?
- -1 : LINK_REGISTER);
- }
- else
- {
- /* Pop everything but the return address. */
- live_regs_mask &= ~ (1 << PROGRAM_COUNTER);
-
- if (live_regs_mask)
- thumb_pushpop (asm_out_file, live_regs_mask, FALSE);
-
- if (had_to_push_lr)
- {
- /* Get the return address into a temporary register. */
- thumb_pushpop (asm_out_file, 1 << ARG_4_REGISTER, 0);
- }
-
- /* Remove the argument registers that were pushed onto the stack. */
- asm_fprintf (asm_out_file, "\tadd\t%s, %s, #%d\n",
- reg_names [STACK_POINTER],
- reg_names [STACK_POINTER],
- current_function_pretend_args_size);
-
- thumb_exit (asm_out_file, had_to_push_lr ? ARG_4_REGISTER : LINK_REGISTER);
- }
-
- return "";
-}
-
-/* Handle the case of a double word load into a low register from
- a computed memory address. The computed address may involve a
- register which is overwritten by the load. */
-
-char *
-thumb_load_double_from_address (operands)
- rtx * operands;
-{
- rtx addr;
- rtx base;
- rtx offset;
- rtx arg1;
- rtx arg2;
-
- if (GET_CODE (operands[0]) != REG)
- fatal ("thumb_load_double_from_address: destination is not a register");
-
- if (GET_CODE (operands[1]) != MEM)
- fatal ("thumb_load_double_from_address: source is not a computed memory address");
-
- /* Get the memory address. */
-
- addr = XEXP (operands[1], 0);
-
- /* Work out how the memory address is computed. */
-
- switch (GET_CODE (addr))
- {
- case REG:
- operands[2] = gen_rtx (MEM, SImode, plus_constant (XEXP (operands[1], 0), 4));
-
- if (REGNO (operands[0]) == REGNO (addr))
- {
- output_asm_insn ("ldr\t%H0, %2\t\t%@ created by thumb_load_double_from_address", operands);
- output_asm_insn ("ldr\t%0, %1\t\t%@ created by thumb_load_double_from_address", operands);
- }
- else
- {
- output_asm_insn ("ldr\t%0, %1\t\t%@ created by thumb_load_double_from_address", operands);
- output_asm_insn ("ldr\t%H0, %2\t\t%@ created by thumb_load_double_from_address", operands);
- }
- break;
-
- case CONST:
- /* Compute <address> + 4 for the high order load. */
-
- operands[2] = gen_rtx (MEM, SImode, plus_constant (XEXP (operands[1], 0), 4));
-
- output_asm_insn ("ldr\t%0, %1\t\t%@ created by thumb_load_double_from_address", operands);
- output_asm_insn ("ldr\t%H0, %2\t\t%@ created by thumb_load_double_from_address", operands);
- break;
-
- case PLUS:
- arg1 = XEXP (addr, 0);
- arg2 = XEXP (addr, 1);
-
- if (CONSTANT_P (arg1))
- base = arg2, offset = arg1;
- else
- base = arg1, offset = arg2;
-
- if (GET_CODE (base) != REG)
- fatal ("thumb_load_double_from_address: base is not a register");
-
- /* Catch the case of <address> = <reg> + <reg> */
-
- if (GET_CODE (offset) == REG)
- {
- int reg_offset = REGNO (offset);
- int reg_base = REGNO (base);
- int reg_dest = REGNO (operands[0]);
-
- /* Add the base and offset registers together into the higher destination register. */
-
- fprintf (asm_out_file, "\tadd\t%s, %s, %s\t\t%s created by thumb_load_double_from_address",
- reg_names[ reg_dest + 1 ],
- reg_names[ reg_base ],
- reg_names[ reg_offset ],
- ASM_COMMENT_START);
-
- /* Load the lower destination register from the address in the higher destination register. */
-
- fprintf (asm_out_file, "\tldr\t%s, [%s, #0]\t\t%s created by thumb_load_double_from_address",
- reg_names[ reg_dest ],
- reg_names[ reg_dest + 1],
- ASM_COMMENT_START);
-
- /* Load the higher destination register from its own address plus 4. */
-
- fprintf (asm_out_file, "\tldr\t%s, [%s, #4]\t\t%s created by thumb_load_double_from_address",
- reg_names[ reg_dest + 1 ],
- reg_names[ reg_dest + 1 ],
- ASM_COMMENT_START);
- }
- else
- {
- /* Compute <address> + 4 for the high order load. */
-
- operands[2] = gen_rtx (MEM, SImode, plus_constant (XEXP (operands[1], 0), 4));
-
- /* If the computed address is held in the low order register
- then load the high order register first, otherwise always
- load the low order register first. */
-
- if (REGNO (operands[0]) == REGNO (base))
- {
- output_asm_insn ("ldr\t%H0, %2\t\t%@ created by thumb_load_double_from_address", operands);
- output_asm_insn ("ldr\t%0, %1\t\t%@ created by thumb_load_double_from_address", operands);
- }
- else
- {
- output_asm_insn ("ldr\t%0, %1\t\t%@ created by thumb_load_double_from_address", operands);
- output_asm_insn ("ldr\t%H0, %2\t\t%@ created by thumb_load_double_from_address", operands);
- }
- }
- break;
-
- case LABEL_REF:
- /* With no registers to worry about we can just load the value directly. */
- operands[2] = gen_rtx (MEM, SImode, plus_constant (XEXP (operands[1], 0), 4));
-
- output_asm_insn ("ldr\t%H0, %2\t\t%@ created by thumb_load_double_from_address", operands);
- output_asm_insn ("ldr\t%0, %1\t\t%@ created by thumb_load_double_from_address", operands);
- break;
-
- default:
- debug_rtx (operands[1]);
- fatal ("thumb_load_double_from_address: Unhandled address calculation");
- break;
- }
-
- return "";
-}
-
-char *
-output_move_mem_multiple (n, operands)
- int n;
- rtx *operands;
-{
- rtx tmp;
-
- switch (n)
- {
- case 2:
- if (REGNO (operands[2]) > REGNO (operands[3]))
- {
- tmp = operands[2];
- operands[2] = operands[3];
- operands[3] = tmp;
- }
- output_asm_insn ("ldmia\t%1!, {%2, %3}", operands);
- output_asm_insn ("stmia\t%0!, {%2, %3}", operands);
- break;
-
- case 3:
- if (REGNO (operands[2]) > REGNO (operands[3]))
- {
- tmp = operands[2];
- operands[2] = operands[3];
- operands[3] = tmp;
- }
- if (REGNO (operands[3]) > REGNO (operands[4]))
- {
- tmp = operands[3];
- operands[3] = operands[4];
- operands[4] = tmp;
- }
- if (REGNO (operands[2]) > REGNO (operands[3]))
- {
- tmp = operands[2];
- operands[2] = operands[3];
- operands[3] = tmp;
- }
- output_asm_insn ("ldmia\t%1!, {%2, %3, %4}", operands);
- output_asm_insn ("stmia\t%0!, {%2, %3, %4}", operands);
- break;
-
- default:
- abort ();
- }
-
- return "";
-}
-
-
-int
-thumb_epilogue_size ()
-{
- return 42; /* The answer to .... */
-}
-
-static char *conds[] =
-{
- "eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc",
- "hi", "ls", "ge", "lt", "gt", "le"
-};
-
-static char *
-thumb_condition_code (x, invert)
- rtx x;
- int invert;
-{
- int val;
-
- switch (GET_CODE (x))
- {
- case EQ: val = 0; break;
- case NE: val = 1; break;
- case GEU: val = 2; break;
- case LTU: val = 3; break;
- case GTU: val = 8; break;
- case LEU: val = 9; break;
- case GE: val = 10; break;
- case LT: val = 11; break;
- case GT: val = 12; break;
- case LE: val = 13; break;
- default:
- abort ();
- }
-
- return conds[val ^ invert];
-}
-
-void
-thumb_print_operand (f, x, code)
- FILE *f;
- rtx x;
- int code;
-{
- if (code)
- {
- switch (code)
- {
- case '@':
- fputs (ASM_COMMENT_START, f);
- return;
-
- case '_':
- fputs (user_label_prefix, f);
- return;
-
- case 'D':
- if (x)
- fputs (thumb_condition_code (x, 1), f);
- return;
-
- case 'd':
- if (x)
- fputs (thumb_condition_code (x, 0), f);
- return;
-
- /* An explanation of the 'Q', 'R' and 'H' register operands:
-
- In a pair of registers containing a DI or DF value the 'Q'
- operand returns the register number of the register containing
- the least signficant part of the value. The 'R' operand returns
- the register number of the register containing the most
- significant part of the value.
-
- The 'H' operand returns the higher of the two register numbers.
- On a run where WORDS_BIG_ENDIAN is true the 'H' operand is the
- same as the 'Q' operand, since the most signficant part of the
- value is held in the lower number register. The reverse is true
- on systems where WORDS_BIG_ENDIAN is false.
-
- The purpose of these operands is to distinguish between cases
- where the endian-ness of the values is important (for example
- when they are added together), and cases where the endian-ness
- is irrelevant, but the order of register operations is important.
- For example when loading a value from memory into a register
- pair, the endian-ness does not matter. Provided that the value
- from the lower memory address is put into the lower numbered
- register, and the value from the higher address is put into the
- higher numbered register, the load will work regardless of whether
- the value being loaded is big-wordian or little-wordian. The
- order of the two register loads can matter however, if the address
- of the memory location is actually held in one of the registers
- being overwritten by the load. */
- case 'Q':
- if (REGNO (x) > 15)
- abort ();
- fputs (reg_names[REGNO (x) + (WORDS_BIG_ENDIAN ? 1 : 0)], f);
- return;
-
- case 'R':
- if (REGNO (x) > 15)
- abort ();
- fputs (reg_names[REGNO (x) + (WORDS_BIG_ENDIAN ? 0 : 1)], f);
- return;
-
- case 'H':
- if (REGNO (x) > 15)
- abort ();
- fputs (reg_names[REGNO (x) + 1], f);
- return;
-
- case 'c':
- /* We use 'c' operands with symbols for .vtinherit */
- if (GET_CODE (x) == SYMBOL_REF)
- output_addr_const(f, x);
- return;
-
- default:
- abort ();
- }
- }
- if (GET_CODE (x) == REG)
- fputs (reg_names[REGNO (x)], f);
- else if (GET_CODE (x) == MEM)
- output_address (XEXP (x, 0));
- else if (GET_CODE (x) == CONST_INT)
- {
- fputc ('#', f);
- output_addr_const (f, x);
- }
- else
- abort ();
-}
-
-#ifdef AOF_ASSEMBLER
-int arm_text_section_count = 1;
-
-char *
-aof_text_section (in_readonly)
- int in_readonly;
-{
- static char buf[100];
- if (in_readonly)
- return "";
- sprintf (buf, "\tCODE16\n\tAREA |C$$code%d|, CODE, READONLY",
- arm_text_section_count++);
- return buf;
-}
-
-static int arm_data_section_count = 1;
-
-char *
-aof_data_section ()
-{
- static char buf[100];
- sprintf (buf, "\tAREA |C$$data%d|, DATA", arm_data_section_count++);
- return buf;
-}
-
-/* The AOF thumb assembler is religiously strict about declarations of
- imported and exported symbols, so that it is impossible to declare a
- function as imported near the begining of the file, and then to export
- it later on. It is, however, possible to delay the decision until all
- the functions in the file have been compiled. To get around this, we
- maintain a list of the imports and exports, and delete from it any that
- are subsequently defined. At the end of compilation we spit the
- remainder of the list out before the END directive. */
-
-struct import
-{
- struct import *next;
- char *name;
-};
-
-static struct import *imports_list = NULL;
-
-void
-thumb_aof_add_import (name)
- char *name;
-{
- struct import *new;
-
- for (new = imports_list; new; new = new->next)
- if (new->name == name)
- return;
-
- new = (struct import *) xmalloc (sizeof (struct import));
- new->next = imports_list;
- imports_list = new;
- new->name = name;
-}
-
-void
-thumb_aof_delete_import (name)
- char *name;
-{
- struct import **old;
-
- for (old = &imports_list; *old; old = & (*old)->next)
- {
- if ((*old)->name == name)
- {
- *old = (*old)->next;
- return;
- }
- }
-}
-
-void
-thumb_aof_dump_imports (f)
- FILE *f;
-{
- while (imports_list)
- {
- fprintf (f, "\tIMPORT\t");
- assemble_name (f, imports_list->name);
- fputc ('\n', f);
- imports_list = imports_list->next;
- }
-}
-#endif
-
-/* Decide whether a type should be returned in memory (true)
- or in a register (false). This is called by the macro
- RETURN_IN_MEMORY. */
-
-int
-thumb_return_in_memory (type)
- tree type;
-{
- if (! AGGREGATE_TYPE_P (type))
- {
- /* All simple types are returned in registers. */
-
- return 0;
- }
- else if (int_size_in_bytes (type) > 4)
- {
- /* All structures/unions bigger than one word are returned in memory. */
-
- return 1;
- }
- else if (TREE_CODE (type) == RECORD_TYPE)
- {
- tree field;
-
- /* For a struct the APCS says that we must return in a register if
- every addressable element has an offset of zero. For practical
- purposes this means that the structure can have at most one non-
- bit-field element and that this element must be the first one in
- the structure. */
-
- /* Find the first field, ignoring non FIELD_DECL things which will
- have been created by C++. */
- for (field = TYPE_FIELDS (type);
- field && TREE_CODE (field) != FIELD_DECL;
- field = TREE_CHAIN (field))
- continue;
-
- if (field == NULL)
- return 0; /* An empty structure. Allowed by an extension to ANSI C. */
-
- /* Now check the remaining fields, if any. */
- for (field = TREE_CHAIN (field); field; field = TREE_CHAIN (field))
- {
- if (TREE_CODE (field) != FIELD_DECL)
- continue;
-
- if (! DECL_BIT_FIELD_TYPE (field))
- return 1;
- }
-
- return 0;
- }
- else if (TREE_CODE (type) == UNION_TYPE)
- {
- tree field;
-
- /* Unions can be returned in registers if every element is
- integral, or can be returned in an integer register. */
-
- for (field = TYPE_FIELDS (type);
- field;
- field = TREE_CHAIN (field))
- {
- if (TREE_CODE (field) != FIELD_DECL)
- continue;
-
- if (RETURN_IN_MEMORY (TREE_TYPE (field)))
- return 1;
- }
-
- return 0;
- }
- /* XXX Not sure what should be done for other aggregates, so put them in
- memory. */
- return 1;
-}
-
-void
-thumb_override_options ()
-{
- if (structure_size_string != NULL)
- {
- int size = strtol (structure_size_string, NULL, 0);
-
- if (size == 8 || size == 32)
- arm_structure_size_boundary = size;
- else
- warning ("Structure size boundary can only be set to 8 or 32");
- }
-
- if (flag_pic)
- {
- warning ("Position independent code not supported. Ignored");
- flag_pic = 0;
- }
-}
-
-/* CYGNUS LOCAL nickc/thumb-pe */
-
-#ifdef THUMB_PE
-/* Return nonzero if ATTR is a valid attribute for DECL.
- ATTRIBUTES are any existing attributes and ARGS are the arguments
- supplied with ATTR.
-
- Supported attributes:
-
- naked: don't output any prologue or epilogue code, the user is assumed
- to do the right thing.
-
- interfacearm: Always assume that this function will be entered in ARM
- mode, not Thumb mode, and that the caller wishes to be returned to in
- ARM mode. */
-int
-arm_valid_machine_decl_attribute (decl, attributes, attr, args)
- tree decl;
- tree attributes;
- tree attr;
- tree args;
-{
- if (args != NULL_TREE)
- return 0;
-
- if (is_attribute_p ("naked", attr))
- return TREE_CODE (decl) == FUNCTION_DECL;
-
- if (is_attribute_p ("interfacearm", attr))
- return TREE_CODE (decl) == FUNCTION_DECL;
-
- return 0;
-}
-#endif /* THUMB_PE */
-/* END CYGNUS LOCAL nickc/thumb-pe */
-
-/* s_register_operand is the same as register_operand, but it doesn't accept
- (SUBREG (MEM)...).
-
- This function exists because at the time it was put in it led to better
- code. SUBREG(MEM) always needs a reload in the places where
- s_register_operand is used, and this seemed to lead to excessive
- reloading. */
-
-int
-s_register_operand (op, mode)
- register rtx op;
- enum machine_mode mode;
-{
- if (GET_MODE (op) != mode && mode != VOIDmode)
- return 0;
-
- if (GET_CODE (op) == SUBREG)
- op = SUBREG_REG (op);
-
- /* We don't consider registers whose class is NO_REGS
- to be a register operand. */
- /* XXX might have to check for lo regs only for thumb ??? */
- return (GET_CODE (op) == REG
- && (REGNO (op) >= FIRST_PSEUDO_REGISTER
- || REGNO_REG_CLASS (REGNO (op)) != NO_REGS));
-}
diff --git a/gcc/config/arm/thumb_010110a.md b/gcc/config/arm/thumb_010110a.md
deleted file mode 100755
index 29a75bb..0000000
--- a/gcc/config/arm/thumb_010110a.md
+++ /dev/null
@@ -1,1166 +0,0 @@
-;; thumb.md Machine description for ARM/Thumb processors
-;; Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
-;; The basis of this contribution was generated by
-;; Richard Earnshaw, Advanced RISC Machines Ltd
-
-;; 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.
-
-;; LENGTH of an instruction is 2 bytes
-(define_attr "length" "" (const_int 2))
-
-;; CONDS is set to UNCHANGED when an insn does not affect the condition codes
-;; Most insns change the condition codes
-(define_attr "conds" "changed,unchanged" (const_string "changed"))
-
-;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
-;; distant label.
-(define_attr "far_jump" "yes,no" (const_string "no"))
-
-;; Start with move insns
-
-(define_expand "movsi"
- [(set (match_operand:SI 0 "general_operand" "")
- (match_operand:SI 1 "general_operand" ""))]
- ""
- "
- if (! (reload_in_progress || reload_completed))
- {
- if (GET_CODE (operands[0]) != REG)
- operands[1] = force_reg (SImode, operands[1]);
- }
-")
-
-(define_insn "*movsi_insn"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l,m,*r,*h")
- (match_operand:SI 1 "general_operand" "l,I,J,K,>,l,mi,l,*h,*r"))]
- "register_operand (operands[0], SImode)
- || register_operand (operands[1], SImode)"
- "@
- add\\t%0, %1, #0
- mov\\t%0, %1
- #
- #
- ldmia\\t%1, {%0}
- stmia\\t%0, {%1}
- ldr\\t%0, %1
- str\\t%1, %0
- mov\\t%0, %1
- mov\\t%0, %1"
-[(set_attr "length" "2,2,4,4,2,2,2,2,2,2")])
-
-(define_split
- [(set (match_operand:SI 0 "register_operand" "")
- (match_operand:SI 1 "const_int_operand" ""))]
- "thumb_shiftable_const (INTVAL (operands[1]))"
- [(set (match_dup 0) (match_dup 1))
- (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
- "
-{
- unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
- unsigned HOST_WIDE_INT mask = 0xff;
- int i;
- for (i = 0; i < 25; i++)
- if ((val & (mask << i)) == val)
- break;
-
- if (i == 0)
- FAIL;
-
- operands[1] = GEN_INT (val >> i);
- operands[2] = GEN_INT (i);
-}")
-
-(define_split
- [(set (match_operand:SI 0 "register_operand" "")
- (match_operand:SI 1 "const_int_operand" ""))]
- "INTVAL (operands[1]) < 0 && INTVAL (operands[1]) > -256"
- [(set (match_dup 0) (match_dup 1))
- (set (match_dup 0) (neg:SI (match_dup 0)))]
- "
- operands[1] = GEN_INT (- INTVAL (operands[1]));
-")
-
-;;(define_expand "reload_outsi"
-;; [(set (match_operand:SI 2 "register_operand" "=&l")
-;; (match_operand:SI 1 "register_operand" "h"))
-;; (set (match_operand:SI 0 "reload_memory_operand" "=o")
-;; (match_dup 2))]
-;; ""
-;; "
-;;/* thumb_reload_out_si (operands);
-;; DONE; */
-;;")
-
-(define_expand "movhi"
- [(set (match_operand:HI 0 "general_operand" "")
- (match_operand:HI 1 "general_operand" ""))]
- ""
- "
-{
- if (! (reload_in_progress || reload_completed))
- {
- if (GET_CODE (operands[0]) != REG)
- operands[1] = force_reg (HImode, operands[1]);
-
- /* ??? We shouldn't really get invalid addresses here, but this can
- happen if we are passed a SP (never OK for HImode/QImode) or virtual
- register (rejected by GO_IF_LEGITIMATE_ADDRESS for HImode/QImode)
- relative address. */
- /* ??? This should perhaps be fixed elsewhere, for instance, in
- fixup_stack_1, by checking for other kinds of invalid addresses,
- e.g. a bare reference to a virtual register. This may confuse the
- alpha though, which must handle this case differently. */
- if (GET_CODE (operands[0]) == MEM
- && ! memory_address_p (GET_MODE (operands[0]),
- XEXP (operands[0], 0)))
- {
- rtx temp = copy_to_reg (XEXP (operands[0], 0));
- operands[0] = change_address (operands[0], VOIDmode, temp);
- }
- if (GET_CODE (operands[1]) == MEM
- && ! memory_address_p (GET_MODE (operands[1]),
- XEXP (operands[1], 0)))
- {
- rtx temp = copy_to_reg (XEXP (operands[1], 0));
- operands[1] = change_address (operands[1], VOIDmode, temp);
- }
- }
- /* Handle loading a large integer during reload */
- else if (GET_CODE (operands[1]) == CONST_INT
- && ! CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
- {
- /* Writing a constant to memory needs a scratch, which should
- be handled with SECONDARY_RELOADs. */
- if (GET_CODE (operands[0]) != REG)
- abort ();
-
- operands[0] = gen_rtx (SUBREG, SImode, operands[0], 0);
- emit_insn (gen_movsi (operands[0], operands[1]));
- DONE;
- }
-}")
-
-(define_insn "*movhi_insn"
- [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
- (match_operand:HI 1 "general_operand" "l,m,l,*h,*r,I"))]
- "register_operand (operands[0], HImode)
- || register_operand (operands[1], HImode)"
- "@
- add\\t%0, %1, #0
- ldrh\\t%0, %1
- strh\\t%1, %0
- mov\\t%0, %1
- mov\\t%0, %1
- mov\\t%0, %1")
-
-(define_expand "movqi"
- [(set (match_operand:QI 0 "general_operand" "")
- (match_operand:QI 1 "general_operand" ""))]
- ""
- "
-{
- if (! (reload_in_progress || reload_completed))
- {
- if (GET_CODE (operands[0]) != REG)
- operands[1] = force_reg (QImode, operands[1]);
-
- /* ??? We shouldn't really get invalid addresses here, but this can
- happen if we are passed a SP (never OK for HImode/QImode) or virtual
- register (rejected by GO_IF_LEGITIMATE_ADDRESS for HImode/QImode)
- relative address. */
- /* ??? This should perhaps be fixed elsewhere, for instance, in
- fixup_stack_1, by checking for other kinds of invalid addresses,
- e.g. a bare reference to a virtual register. This may confuse the
- alpha though, which must handle this case differently. */
- if (GET_CODE (operands[0]) == MEM
- && ! memory_address_p (GET_MODE (operands[0]),
- XEXP (operands[0], 0)))
- {
- rtx temp = copy_to_reg (XEXP (operands[0], 0));
- operands[0] = change_address (operands[0], VOIDmode, temp);
- }
- if (GET_CODE (operands[1]) == MEM
- && ! memory_address_p (GET_MODE (operands[1]),
- XEXP (operands[1], 0)))
- {
- rtx temp = copy_to_reg (XEXP (operands[1], 0));
- operands[1] = change_address (operands[1], VOIDmode, temp);
- }
- }
- /* Handle loading a large integer during reload */
- else if (GET_CODE (operands[1]) == CONST_INT
- && ! CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
- {
- /* Writing a constant to memory needs a scratch, which should
- be handled with SECONDARY_RELOADs. */
- if (GET_CODE (operands[0]) != REG)
- abort ();
-
- operands[0] = gen_rtx (SUBREG, SImode, operands[0], 0);
- emit_insn (gen_movsi (operands[0], operands[1]));
- DONE;
- }
-}")
-
-(define_insn "*movqi_insn"
- [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
- (match_operand:QI 1 "general_operand" "l,m,l,*h,*r,I"))]
- "register_operand (operands[0], QImode)
- || register_operand (operands[1], QImode)"
- "@
- add\\t%0, %1, #0
- ldrb\\t%0, %1
- strb\\t%1, %0
- mov\\t%0, %1
- mov\\t%0, %1
- mov\\t%0, %1")
-
-(define_expand "movdi"
- [(set (match_operand:DI 0 "general_operand" "")
- (match_operand:DI 1 "general_operand" ""))]
- ""
- "
- if (! (reload_in_progress || reload_completed))
- {
- if (GET_CODE (operands[0]) != REG)
- operands[1] = force_reg (DImode, operands[1]);
- }
-")
-
-;;; ??? This should have alternatives for constants.
-;;; ??? This was originally identical to the movdf_insn pattern.
-;;; ??? The 'i' constraint looks funny, but it should always be replaced by
-;;; thumb_reorg with a memory reference.
-(define_insn "*movdi_insn"
- [(set (match_operand:DI 0 "general_operand" "=l,l,l,l,>,l,m,*r")
- (match_operand:DI 1 "general_operand" "l,I,J,>,l,mi,l,*r"))]
- "register_operand (operands[0], DImode)
- || register_operand (operands[1], DImode)"
- "*
-{
- switch (which_alternative)
- {
- case 0:
- if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
- return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
- return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
- case 1:
- return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
- case 2:
- operands[1] = GEN_INT (- INTVAL (operands[1]));
- return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
- case 3:
- return \"ldmia\\t%1, {%0, %H0}\";
- case 4:
- return \"stmia\\t%0, {%1, %H1}\";
- case 5:
- return thumb_load_double_from_address (operands);
- case 6:
- operands[2] = gen_rtx (MEM, SImode, plus_constant (XEXP (operands[0], 0), 4));
- output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
- return \"\";
- case 7:
- if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
- return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
- return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
- }
-}"[(set_attr "length" "4,4,6,2,2,6,4,4")])
-
-(define_expand "movdf"
- [(set (match_operand:DF 0 "general_operand" "")
- (match_operand:DF 1 "general_operand" ""))]
- ""
- "
- if (! (reload_in_progress || reload_completed))
- {
- if (GET_CODE (operands[0]) != REG)
- operands[1] = force_reg (DFmode, operands[1]);
- }
-")
-
-;;; ??? This should have alternatives for constants.
-;;; ??? This was originally identical to the movdi_insn pattern.
-;;; ??? The 'F' constraint looks funny, but it should always be replaced by
-;;; thumb_reorg with a memory reference.
-(define_insn "*movdf_insn"
- [(set (match_operand:DF 0 "general_operand" "=l,l,>,l,m,*r")
- (match_operand:DF 1 "general_operand" "l,>,l,mF,l,*r"))]
- "register_operand (operands[0], DFmode)
- || register_operand (operands[1], DFmode)"
- "*
- switch (which_alternative)
- {
- case 0:
- if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
- return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
- return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
- case 1:
- return \"ldmia\\t%1, {%0, %H0}\";
- case 2:
- return \"stmia\\t%0, {%1, %H1}\";
- case 3:
- return thumb_load_double_from_address (operands);
- case 4:
- operands[2] = gen_rtx (MEM, SImode, plus_constant (XEXP (operands[0], 0), 4));
- output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
- return \"\";
- case 5:
- if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
- return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
- return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
- }
-"[(set_attr "length" "4,2,2,6,4,4")])
-
-(define_expand "movsf"
- [(set (match_operand:SF 0 "general_operand" "")
- (match_operand:SF 1 "general_operand" ""))]
- ""
- "
- if (! (reload_in_progress || reload_completed))
- {
- if (GET_CODE (operands[0]) != REG)
- operands[1] = force_reg (SFmode, operands[1]);
- }
-")
-
-;;; ??? This should have alternatives for constants.
-(define_insn "*movsf_insn"
- [(set (match_operand:SF 0 "nonimmediate_operand" "=l,l,>,l,m,*r,*h")
- (match_operand:SF 1 "general_operand" "l,>,l,mF,l,*h,*r"))]
- "register_operand (operands[0], SFmode)
- || register_operand (operands[1], SFmode)"
- "@
- add\\t%0, %1, #0
- ldmia\\t%1, {%0}
- stmia\\t%0, {%1}
- ldr\\t%0, %1
- str\\t%1, %0
- mov\\t%0, %1
- mov\\t%0, %1")
-
-;; Widening move insns
-
-(define_expand "zero_extendhisi2"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
- ""
- "
- if (GET_CODE (operands[1]) != MEM)
- {
- rtx temp = gen_reg_rtx (SImode);
-
- operands[1] = force_reg (HImode, operands[1]);
- operands[1] = gen_lowpart (SImode, operands[1]);
- emit_insn (gen_ashlsi3 (temp, operands[1], GEN_INT (16)));
- emit_insn (gen_lshrsi3 (operands[0], temp, GEN_INT (16)));
- DONE;
- }
-")
-
-(define_insn "*zero_extendhisi2_insn"
- [(set (match_operand:SI 0 "s_register_operand" "=l")
- (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
- ""
- "ldrh\\t%0, %1")
-
-(define_expand "zero_extendqisi2"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
- ""
- "
- if (GET_CODE (operands[1]) != MEM)
- {
- rtx temp = gen_reg_rtx (SImode);
-
- operands[1] = force_reg (QImode, operands[1]);
- operands[1] = gen_lowpart (SImode, operands[1]);
- emit_insn (gen_ashlsi3 (temp, operands[1], GEN_INT (24)));
- emit_insn (gen_lshrsi3 (operands[0], temp, GEN_INT (24)));
- DONE;
- }
-")
-
-(define_insn "*zero_extendqisi2_insn"
- [(set (match_operand:SI 0 "s_register_operand" "=l")
- (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
- ""
- "ldrb\\t%0, %1")
-
-(define_expand "extendhisi2"
- [(parallel [(set (match_operand:SI 0 "s_register_operand" "")
- (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))
- (clobber (match_scratch:SI 2 ""))])]
- ""
- "
- if (GET_CODE (operands[1]) != MEM)
- {
- rtx temp = gen_reg_rtx (SImode);
-
- operands[1] = force_reg (HImode, operands[1]);
- operands[1] = gen_lowpart (SImode, operands[1]);
- emit_insn (gen_ashlsi3 (temp, operands[1], GEN_INT (16)));
- emit_insn (gen_ashrsi3 (operands[0], temp, GEN_INT (16)));
- DONE;
- }
-")
-
-(define_insn "*extendhisi2_insn"
- [(set (match_operand:SI 0 "s_register_operand" "=l")
- (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
- (clobber (match_scratch:SI 2 "=&l"))]
- ""
- "*
-{
- rtx ops[4];
- /* This code used to try to use 'V', and fix the address only if it was
- offsettable, but this fails for e.g. REG+48 because 48 is outside the
- range of QImode offsets, and offsettable_address_p does a QImode
- address check. */
-
- if (GET_CODE (XEXP (operands[1], 0)) == PLUS)
- {
- ops[1] = XEXP (XEXP (operands[1], 0), 0);
- ops[2] = XEXP (XEXP (operands[1], 0), 1);
- }
- else
- {
- ops[1] = XEXP (operands[1], 0);
- ops[2] = const0_rtx;
- }
- if (GET_CODE (ops[2]) == REG)
- return \"ldrsh\\t%0, %1\";
-
- ops[0] = operands[0];
- ops[3] = operands[2];
- output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
- return \"\";
-}"
-[(set_attr "length" "4")])
-
-(define_expand "extendqisi2"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
- ""
- "
- if (GET_CODE (operands[1]) != MEM)
- {
- rtx temp = gen_reg_rtx (SImode);
-
- operands[1] = force_reg (QImode, operands[1]);
- operands[1] = gen_lowpart (SImode, operands[1]);
- emit_insn (gen_ashlsi3 (temp, operands[1], GEN_INT (24)));
- emit_insn (gen_ashrsi3 (operands[0], temp, GEN_INT (24)));
- DONE;
- }
-")
-
-(define_insn "*extendqisi2_insn"
- [(set (match_operand:SI 0 "s_register_operand" "=l,l")
- (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
- ""
- "*
-{
- rtx ops[3];
-
- if (which_alternative == 0)
- return \"ldrsb\\t%0, %1\";
- ops[0] = operands[0];
- if (GET_CODE (XEXP (operands[1], 0)) == PLUS)
- {
- ops[1] = XEXP (XEXP (operands[1], 0), 0);
- ops[2] = XEXP (XEXP (operands[1], 0), 1);
-
- if (GET_CODE (ops[1]) == REG && GET_CODE (ops[2]) == REG)
- output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
- else if (GET_CODE (ops[1]) == REG)
- {
- if (REGNO (ops[1]) == REGNO (operands[0]))
- output_asm_insn (\"ldrb\\t%0, [%1, %2]\;lsl\\t%0, %0, #24\;asr\\t%0, %0, #24\", ops);
- else
- output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
- }
- else
- {
- if (REGNO (ops[2]) == REGNO (operands[0]))
- output_asm_insn (\"ldrb\\t%0, [%2, %1]\;lsl\\t%0, %0, #24\;asr\\t%0, %0, #24\", ops);
- else
- output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
- }
- }
- else if (REGNO (operands[0]) == REGNO (XEXP (operands[1], 0)))
- {
- output_asm_insn (\"ldrb\\t%0, [%0, #0]\;lsl\\t%0, %0, #24\;asr\\t%0, %0, #24\", ops);
- }
- else
- {
- ops[1] = XEXP (operands[1], 0);
- ops[2] = const0_rtx;
- output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
- }
- return \"\";
-}"
-[(set_attr "length" "2,6")])
-
-;; We don't really have extzv, but defining this using shifts helps
-;; to reduce register pressure later on.
-
-(define_expand "extzv"
- [(set (match_dup 4)
- (ashift:SI (match_operand:SI 1 "register_operand" "")
- (match_operand:SI 2 "const_int_operand" "")))
- (set (match_operand:SI 0 "register_operand" "")
- (lshiftrt:SI (match_dup 4)
- (match_operand:SI 3 "const_int_operand" "")))]
- ""
- "
-{
- HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
- HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
- operands[3] = GEN_INT (rshift);
- if (lshift == 0)
- {
- emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
- DONE;
- }
- operands[2] = GEN_INT (lshift);
- operands[4] = gen_reg_rtx (SImode);
-}
-")
-
-;; Block-move insns
-
-(define_expand "movstrqi"
- [(match_operand:BLK 0 "general_operand" "")
- (match_operand:BLK 1 "general_operand" "")
- (match_operand:SI 2 "" "")
- (match_operand:SI 3 "const_int_operand" "")]
- ""
- "
- if (INTVAL (operands[3]) != 4
- || GET_CODE (operands[2]) != CONST_INT
- || INTVAL (operands[2]) > 48)
- FAIL;
-
- thumb_expand_movstrqi (operands);
- DONE;
-")
-
-(define_insn "movmem12b"
- [(set (mem:SI (match_operand:SI 0 "register_operand" "+&l"))
- (mem:SI (match_operand:SI 1 "register_operand" "+&l")))
- (set (mem:SI (plus:SI (match_dup 0) (const_int 4)))
- (mem:SI (plus:SI (match_dup 1) (const_int 4))))
- (set (mem:SI (plus:SI (match_dup 0) (const_int 8)))
- (mem:SI (plus:SI (match_dup 1) (const_int 8))))
- (set (match_dup 0) (plus:SI (match_dup 0) (const_int 12)))
- (set (match_dup 1) (plus:SI (match_dup 1) (const_int 12)))
- (clobber (match_scratch:SI 2 "=&l"))
- (clobber (match_scratch:SI 3 "=&l"))
- (clobber (match_scratch:SI 4 "=&l"))]
- ""
- "* return output_move_mem_multiple (3, operands);"
-[(set_attr "length" "4")])
-
-(define_insn "movmem8b"
- [(set (mem:SI (match_operand:SI 0 "register_operand" "+&l"))
- (mem:SI (match_operand:SI 1 "register_operand" "+&l")))
- (set (mem:SI (plus:SI (match_dup 0) (const_int 4)))
- (mem:SI (plus:SI (match_dup 1) (const_int 4))))
- (set (match_dup 0) (plus:SI (match_dup 0) (const_int 8)))
- (set (match_dup 1) (plus:SI (match_dup 1) (const_int 8)))
- (clobber (match_scratch:SI 2 "=&l"))
- (clobber (match_scratch:SI 3 "=&l"))]
- ""
- "* return output_move_mem_multiple (2, operands);"
-[(set_attr "length" "4")])
-
-;; Arithmetic insns
-
-(define_insn "adddi3"
- [(set (match_operand:DI 0 "s_register_operand" "=l")
- (plus:DI (match_operand:DI 1 "s_register_operand" "%0")
- (match_operand:DI 2 "s_register_operand" "l")))]
- ""
- "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
-[(set_attr "conds" "changed")
- (set_attr "length" "8")])
-
-;; register group 'k' is a single register group containing only the stack
-;; register. Trying to reload it will always fail catastrophically,
-;; so never allow those alternatives to match if reloading is needed.
-(define_insn "addsi3"
- [(set (match_operand:SI 0 "s_register_operand" "=l,l,l,*r,*h,l,!k")
- (plus:SI (match_operand:SI 1 "s_register_operand" "%0,0,l,*0,*0,!k,!k")
- (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))]
- ""
- "*
- static char *asms[] =
-{
- \"add\\t%0, %0, %2\",
- \"sub\\t%0, %0, #%n2\",
- \"add\\t%0, %1, %2\",
- \"add\\t%0, %0, %2\",
- \"add\\t%0, %0, %2\",
- \"add\\t%0, %1, %2\",
- \"add\\t%0, %1, %2\"
-};
- if (which_alternative == 2 && GET_CODE (operands[2]) == CONST_INT
- && INTVAL (operands[2]) < 0)
- return \"sub\\t%0, %1, #%n2\";
- return asms[which_alternative];
-")
-
-; reloading and elimination of the frame pointer can sometimes cause this
-; optimization to be missed.
-(define_peephole
- [(set (match_operand:SI 0 "register_operand" "=l")
- (match_operand:SI 1 "const_int_operand" "M"))
- (set (match_dup 0)
- (plus:SI (match_dup 0) (match_operand:SI 2 "register_operand" "k")))]
- "REGNO (operands[2]) == STACK_POINTER_REGNUM
- && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
- && (INTVAL (operands[1]) & 3) == 0"
- "add\\t%0, %2, %1")
-
-(define_insn "subdi3"
- [(set (match_operand:DI 0 "s_register_operand" "=l")
- (minus:DI (match_operand:DI 1 "s_register_operand" "0")
- (match_operand:DI 2 "s_register_operand" "l")))]
- ""
- "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
-[(set_attr "conds" "changed")
- (set_attr "length" "8")])
-
-(define_insn "subsi3"
- [(set (match_operand:SI 0 "s_register_operand" "=l")
- (minus:SI (match_operand:SI 1 "s_register_operand" "l")
- (match_operand:SI 2 "s_register_operand" "l")))]
- ""
- "sub\\t%0, %1, %2")
-
-;; We must ensure that one input matches the output, and that the other input
-;; does not match the output. Using 0 satisfies the first, and using &
-;; satisfies the second. Unfortunately, this fails when operands 1 and 2
-;; are the same, because reload will make operand 0 match operand 1 without
-;; realizing that this conflicts with operand 2. We fix this by adding another
-;; alternative to match this case, and then `reload' it ourselves. This
-;; alternative must come first.
-(define_insn "mulsi3"
- [(set (match_operand:SI 0 "s_register_operand" "=&l,&l,&l")
- (mult:SI (match_operand:SI 1 "s_register_operand" "%l,*h,0")
- (match_operand:SI 2 "s_register_operand" "l,l,l")))]
- ""
- "*
-{
- if (which_alternative < 2)
- return \"mov\\t%0, %1\;mul\\t%0, %0, %2\";
- else
- return \"mul\\t%0, %0, %2\";
-}"
- [(set_attr "length" "4,4,2")])
-
-(define_insn "negsi2"
- [(set (match_operand:SI 0 "s_register_operand" "=l")
- (neg:SI (match_operand:SI 1 "s_register_operand" "l")))]
- ""
- "neg\\t%0, %1")
-
-;; Logical insns
-
-(define_expand "andsi3"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (and:SI (match_operand:SI 1 "s_register_operand" "")
- (match_operand:SI 2 "nonmemory_operand" "")))]
- ""
- "
- if (GET_CODE (operands[2]) != CONST_INT)
- operands[2] = force_reg (SImode, operands[2]);
- else
- {
- int i;
- if (((unsigned HOST_WIDE_INT) ~ INTVAL (operands[2])) < 256)
- {
- operands[2] = force_reg (SImode, GEN_INT (~INTVAL (operands[2])));
- emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
- DONE;
- }
-
- for (i = 9; i <= 31; i++)
- if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
- {
- emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
- const0_rtx));
- DONE;
- }
- else if ((((HOST_WIDE_INT) 1) << i) - 1 == ~ INTVAL (operands[2]))
- {
- rtx shift = GEN_INT (i);
- rtx reg = gen_reg_rtx (SImode);
- emit_insn (gen_lshrsi3 (reg, operands[1], shift));
- emit_insn (gen_ashlsi3 (operands[0], reg, shift));
- DONE;
- }
-
- operands[2] = force_reg (SImode, operands[2]);
- }
-")
-
-(define_insn "*andsi3_insn"
- [(set (match_operand:SI 0 "s_register_operand" "=l")
- (and:SI (match_operand:SI 1 "s_register_operand" "%0")
- (match_operand:SI 2 "s_register_operand" "l")))]
- ""
- "and\\t%0, %0, %2")
-
-(define_insn "bicsi3"
- [(set (match_operand:SI 0 "s_register_operand" "=l")
- (and:SI (not:SI (match_operand:SI 1 "s_register_operand" "l"))
- (match_operand:SI 2 "s_register_operand" "0")))]
- ""
- "bic\\t%0, %0, %1")
-
-(define_insn "iorsi3"
- [(set (match_operand:SI 0 "s_register_operand" "=l")
- (ior:SI (match_operand:SI 1 "s_register_operand" "%0")
- (match_operand:SI 2 "s_register_operand" "l")))]
- ""
- "orr\\t%0, %0, %2")
-
-(define_insn "xorsi3"
- [(set (match_operand:SI 0 "s_register_operand" "=l")
- (xor:SI (match_operand:SI 1 "s_register_operand" "%0")
- (match_operand:SI 2 "s_register_operand" "l")))]
- ""
- "eor\\t%0, %0, %2")
-
-(define_insn "one_cmplsi2"
- [(set (match_operand:SI 0 "s_register_operand" "=l")
- (not:SI (match_operand:SI 1 "s_register_operand" "l")))]
- ""
- "mvn\\t%0, %1")
-
-;; Shift and rotation insns
-
-(define_insn "ashlsi3"
- [(set (match_operand:SI 0 "s_register_operand" "=l,l")
- (ashift:SI (match_operand:SI 1 "s_register_operand" "l,0")
- (match_operand:SI 2 "nonmemory_operand" "N,l")))]
- ""
- "@
- lsl\\t%0, %1, %2
- lsl\\t%0, %0, %2")
-
-(define_insn "ashrsi3"
- [(set (match_operand:SI 0 "s_register_operand" "=l,l")
- (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "l,0")
- (match_operand:SI 2 "nonmemory_operand" "N,l")))]
- ""
- "@
- asr\\t%0, %1, %2
- asr\\t%0, %0, %2")
-
-(define_insn "lshrsi3"
- [(set (match_operand:SI 0 "s_register_operand" "=l,l")
- (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "l,0")
- (match_operand:SI 2 "nonmemory_operand" "N,l")))]
- ""
- "@
- lsr\\t%0, %1, %2
- lsr\\t%0, %0, %2")
-
-(define_insn "rotrsi3"
- [(set (match_operand:SI 0 "s_register_operand" "=l")
- (rotatert:SI (match_operand:SI 1 "s_register_operand" "0")
- (match_operand:SI 2 "s_register_operand" "l")))]
- ""
- "ror\\t%0, %0, %2")
-
-;; Comparison insns
-
-(define_expand "cmpsi"
- [(set (cc0) (compare (match_operand:SI 0 "s_register_operand" "")
- (match_operand:SI 1 "nonmemory_operand" "")))]
- ""
- "
- if (GET_CODE (operands[1]) != REG && GET_CODE (operands[1]) != SUBREG)
- {
- if (GET_CODE (operands[1]) != CONST_INT
- || (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) >= 256)
- {
- if (GET_CODE (operands[1]) != CONST_INT
- || INTVAL (operands[1]) < -255
- || INTVAL (operands[1]) > 0)
- operands[1] = force_reg (SImode, operands[1]);
- else
- {
- operands[1] = force_reg (SImode,
- GEN_INT (- INTVAL (operands[1])));
- emit_insn (gen_cmnsi (operands[0], operands[1]));
- DONE;
- }
- }
- }
-")
-
-(define_insn "*cmpsi_insn"
- [(set (cc0) (compare (match_operand:SI 0 "s_register_operand" "l,*r,*h")
- (match_operand:SI 1 "thumb_cmp_operand" "lI,*h,*r")))]
- ""
- "@
- cmp\\t%0, %1
- cmp\\t%0, %1
- cmp\\t%0, %1")
-
-(define_insn "tstsi"
- [(set (cc0) (match_operand:SI 0 "s_register_operand" "l"))]
- ""
- "cmp\\t%0, #0")
-
-(define_insn "cmnsi"
- [(set (cc0) (compare (match_operand:SI 0 "s_register_operand" "l")
- (neg:SI (match_operand:SI 1 "s_register_operand" "l"))))]
- ""
- "cmn\\t%0, %1")
-
-;; Jump insns
-
-(define_insn "jump"
- [(set (pc) (label_ref (match_operand 0 "" "")))]
- ""
- "*
- if (get_attr_length (insn) == 2)
- return \"b\\t%l0\";
- return \"bl\\t%l0\\t%@ far jump\";
-"[(set (attr "far_jump")
- (if_then_else (eq_attr "length" "4")
- (const_string "yes")
- (const_string "no")))
- (set (attr "length")
- (if_then_else (and (ge (minus (match_dup 0) (pc)) (const_int -2048))
- (le (minus (match_dup 0) (pc)) (const_int 2044)))
- (const_int 2)
- (const_int 4)))])
-
-
-(define_expand "beq"
- [(set (pc) (if_then_else (eq (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_expand "bne"
- [(set (pc) (if_then_else (ne (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_expand "bge"
- [(set (pc) (if_then_else (ge (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_expand "ble"
- [(set (pc) (if_then_else (le (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_expand "bgt"
- [(set (pc) (if_then_else (gt (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_expand "blt"
- [(set (pc) (if_then_else (lt (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_expand "bgeu"
- [(set (pc) (if_then_else (geu (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_expand "bleu"
- [(set (pc) (if_then_else (leu (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_expand "bgtu"
- [(set (pc) (if_then_else (gtu (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_expand "bltu"
- [(set (pc) (if_then_else (ltu (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_insn "*cond_branch"
- [(set (pc) (if_then_else (match_operator 1 "comparison_operator"
- [(cc0) (const_int 0)])
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "*
- switch (get_attr_length (insn))
- {
- case 2: return \"b%d1\\t%l0\\t%@cond_branch\";
- case 4: return \"b%D1\\t.LCB%=\;b\\t%l0\\t%@long jump\\n.LCB%=:\";
- default: return \"b%D1\\t.LCB%=\;bl\\t%l0\\t%@far jump\\n.LCB%=:\";
- }
-"[(set (attr "far_jump")
- (if_then_else (eq_attr "length" "6")
- (const_string "yes")
- (const_string "no")))
- (set (attr "length")
- (if_then_else
- (and (ge (minus (match_dup 0) (pc)) (const_int -252))
- (le (minus (match_dup 0) (pc)) (const_int 254)))
- (const_int 2)
- (if_then_else (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
- (le (minus (match_dup 0) (pc)) (const_int 2044)))
- (const_int 4)
- (const_int 6))))])
-
-(define_insn "*cond_branch_reversed"
- [(set (pc) (if_then_else (match_operator 1 "comparison_operator"
- [(cc0) (const_int 0)])
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
- "*
- switch (get_attr_length (insn))
- {
- case 2: return \"b%D1\\t%l0\\t%@cond_branch_reversed\";
- case 4: return \"b%d1\\t.LCBR%=\;b\\t%l0\\t%@long jump\\n.LCBR%=:\";
- default: return \"b%d1\\t.LCBR%=\;bl\\t%l0\\t%@far jump\\n.LCBR%=:\";
- }
- return \"\";
-"[(set (attr "far_jump")
- (if_then_else (eq_attr "length" "6")
- (const_string "yes")
- (const_string "no")))
- (set (attr "length")
- (if_then_else
- (and (ge (minus (match_dup 0) (pc)) (const_int -252))
- (le (minus (match_dup 0) (pc)) (const_int 254)))
- (const_int 2)
- (if_then_else (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
- (le (minus (match_dup 0) (pc)) (const_int 2044)))
- (const_int 4)
- (const_int 6))))])
-
-(define_insn "indirect_jump"
- [(set (pc) (match_operand:SI 0 "s_register_operand" "l*r"))]
- ""
- "mov\\tpc, %0")
-
-(define_insn "tablejump"
- [(set (pc) (match_operand:SI 0 "s_register_operand" "l*r"))
- (use (label_ref (match_operand 1 "" "")))]
- ""
- "mov\\tpc, %0")
-
-(define_insn "return"
- [(return)]
- "USE_RETURN"
- "* return output_return ();"
-[(set_attr "length" "18")])
-
-;; Call insns
-
-(define_expand "call"
- [(call (match_operand:SI 0 "memory_operand" "")
- (match_operand 1 "" ""))]
- ""
- "")
-
-(define_insn "*call_indirect"
- [(call (mem:SI (match_operand:SI 0 "s_register_operand" "l*r"))
- (match_operand 1 "" ""))]
- "! TARGET_CALLER_INTERWORKING"
- "bl\\t%__call_via_%0"
-[(set_attr "length" "4")])
-;; The non THUMB_INTERWORK, non TARGET_CALLER_INTERWORKING version
-;; used to be: "mov\\tlr,pc\;bx\\t%0", but the mov does not set
-;; the bottom bit of lr so that a function return (using bx)
-;; would switch back into ARM mode...
-
-(define_insn "*call_indirect_interwork"
- [(call (mem:SI (match_operand:SI 0 "s_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 "" "")))]
- ""
- "")
-
-(define_insn "*call_value_indirect"
- [(set (match_operand 0 "" "=l")
- (call (mem:SI (match_operand:SI 1 "s_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 "s_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 "" ""))]
- "GET_CODE (operands[0]) == SYMBOL_REF"
- "bl\\t%a0"
-[(set_attr "length" "4")])
-
-(define_insn "*call_value_insn"
- [(set (match_operand 0 "s_register_operand" "=l")
- (call (mem:SI (match_operand 1 "" "i"))
- (match_operand 2 "" "")))]
- "GET_CODE (operands[1]) == SYMBOL_REF"
- "bl\\t%a1"
-[(set_attr "length" "4")])
-
-;; Untyped call not required, since all funcs return in r0
-
-;; Miscellaneous patterns
-
-(define_insn "nop"
- [(clobber (const_int 0))]
- ""
- "mov\\tr8, r8")
-
-(define_insn "blockage"
- [(unspec_volatile [(const_int 0)] 0)]
- ""
- ""
- [(set_attr "length" "0")])
-
-(define_expand "prologue"
- [(const_int 0)]
- ""
- "
- thumb_expand_prologue ();
- DONE;
-")
-
-(define_expand "epilogue"
- [(unspec_volatile [(const_int 0)] 1)]
- "! thumb_trivial_epilogue ()"
- "
- thumb_expand_epilogue ();
-")
-
-(define_insn "*epilogue_insns"
- [(unspec_volatile [(const_int 0)] 1)]
- ""
- "*
- return thumb_unexpanded_epilogue ();
-"
-[(set_attr "length" "42")])
-
-;; Special patterns for dealing with the constant pool
-
-(define_insn "consttable_4"
- [(unspec_volatile [(match_operand 0 "" "")] 2)]
- ""
- "*
-{
- switch (GET_MODE_CLASS (GET_MODE (operands[0])))
- {
- case MODE_FLOAT:
- {
- union real_extract u;
- bcopy ((char *) &CONST_DOUBLE_LOW (operands[0]), (char *) &u, sizeof u);
- assemble_real (u.d, GET_MODE (operands[0]));
- break;
- }
- default:
- assemble_integer (operands[0], 4, 1);
- break;
- }
- return \"\";
-}"
-[(set_attr "length" "4")])
-
-(define_insn "consttable_8"
- [(unspec_volatile [(match_operand 0 "" "")] 3)]
- ""
- "*
-{
- switch (GET_MODE_CLASS (GET_MODE (operands[0])))
- {
- case MODE_FLOAT:
- {
- union real_extract u;
- bcopy ((char *) &CONST_DOUBLE_LOW (operands[0]), (char *) &u, sizeof u);
- assemble_real (u.d, GET_MODE (operands[0]));
- break;
- }
- default:
- assemble_integer (operands[0], 8, 1);
- break;
- }
- return \"\";
-}"
-[(set_attr "length" "8")])
-
-(define_insn "consttable_end"
- [(unspec_volatile [(const_int 0)] 4)]
- ""
- "*
- /* Nothing to do (currently). */
- return \"\";
-")
-
-(define_insn "align_4"
- [(unspec_volatile [(const_int 0)] 5)]
- ""
- "*
- assemble_align (32);
- return \"\";
-")
diff --git a/gcc/config/arm/thumb_010309a.c b/gcc/config/arm/thumb_010309a.c
deleted file mode 100755
index 778cda9..0000000
--- a/gcc/config/arm/thumb_010309a.c
+++ /dev/null
@@ -1,2132 +0,0 @@
-/* Output routines for GCC for ARM/Thumb
- Copyright (C) 1996 Cygnus Software Technologies Ltd
- The basis of this contribution was generated by
- Richard Earnshaw, Advanced RISC Machines Ltd
-
-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. */
-
-#include <stdio.h>
-#include <string.h>
-#include "config.h"
-#include "rtl.h"
-#include "hard-reg-set.h"
-#include "regs.h"
-#include "output.h"
-#include "insn-flags.h"
-#include "insn-attr.h"
-#include "flags.h"
-#include "tree.h"
-#include "expr.h"
-
-
-int current_function_anonymous_args = 0;
-static int current_function_has_far_jump = 0;
-
-/* Used to parse -mstructure_size_boundary command line option. */
-char * structure_size_string = NULL;
-int arm_structure_size_boundary = 32; /* Used to be 8 */
-
-
-/* Predicates */
-int
-reload_memory_operand (op, mode)
- rtx op;
- enum machine_mode mode;
-{
- int regno = true_regnum (op);
-
- return (! CONSTANT_P (op)
- && (regno == -1
- || (GET_CODE (op) == REG
- && REGNO (op) >= FIRST_PSEUDO_REGISTER)));
-}
-
-/* Return nonzero if op is suitable for the RHS of a cmp instruction. */
-int
-thumb_cmp_operand (op, mode)
- rtx op;
- enum machine_mode mode;
-{
- return ((GET_CODE (op) == CONST_INT
- && (unsigned HOST_WIDE_INT) (INTVAL (op)) < 256)
- || register_operand (op, mode));
-}
-
-int
-thumb_shiftable_const (val)
- HOST_WIDE_INT val;
-{
- unsigned HOST_WIDE_INT x = val;
- unsigned HOST_WIDE_INT mask = 0xff;
- int i;
-
- for (i = 0; i < 25; i++)
- if ((val & (mask << i)) == val)
- return 1;
-
- return 0;
-}
-
-int
-thumb_trivial_epilogue ()
-{
- int regno;
-
- /* ??? If this function ever returns 1, we get a function without any
- epilogue at all. It appears that the intent was to cause a "return"
- insn to be emitted, but that does not happen. */
- return 0;
-
-#if 0
- if (get_frame_size ()
- || current_function_outgoing_args_size
- || current_function_pretend_args_size)
- return 0;
-
- for (regno = 8; regno < 13; regno++)
- if (regs_ever_live[regno] && ! call_used_regs[regno])
- return 0;
-
- return 1;
-#endif
-}
-
-
-/* Routines for handling the constant pool */
-/* This is unashamedly hacked from the version in sh.c, since the problem is
- extremely similar. */
-
-/* Thumb instructions cannot load a large constant into a register,
- constants have to come from a pc relative load. The reference of a pc
- relative load instruction must be less than 1k infront of the instruction.
- This means that we often have to dump a constant inside a function, and
- generate code to branch around it.
-
- It is important to minimize this, since the branches will slow things
- down and make things bigger.
-
- Worst case code looks like:
-
- ldr rn, L1
- b L2
- align
- L1: .long value
- L2:
- ..
-
- ldr rn, L3
- b L4
- align
- L3: .long value
- L4:
- ..
-
- We fix this by performing a scan before scheduling, which notices which
- instructions need to have their operands fetched from the constant table
- and builds the table.
-
-
- The algorithm is:
-
- scan, find an instruction which needs a pcrel move. Look forward, find the
- last barrier which is within MAX_COUNT bytes of the requirement.
- If there isn't one, make one. Process all the instructions between
- the find and the barrier.
-
- In the above example, we can tell that L3 is within 1k of L1, so
- the first move can be shrunk from the 2 insn+constant sequence into
- just 1 insn, and the constant moved to L3 to make:
-
- ldr rn, L1
- ..
- ldr rn, L3
- b L4
- align
- L1: .long value
- L3: .long value
- L4:
-
- Then the second move becomes the target for the shortening process.
-
- */
-
-typedef struct
-{
- rtx value; /* Value in table */
- HOST_WIDE_INT next_offset;
- enum machine_mode mode; /* Mode of value */
-} pool_node;
-
-/* The maximum number of constants that can fit into one pool, since
- the pc relative range is 0...1020 bytes and constants are at least 4
- bytes long */
-
-#define MAX_POOL_SIZE (1020/4)
-static pool_node pool_vector[MAX_POOL_SIZE];
-static int pool_size;
-static rtx pool_vector_label;
-
-/* Add a constant to the pool and return its label. */
-
-static HOST_WIDE_INT
-add_constant (x, mode)
- rtx x;
- enum machine_mode mode;
-{
- int i;
- rtx lab;
- HOST_WIDE_INT offset;
-
- if (mode == SImode && GET_CODE (x) == MEM && CONSTANT_P (XEXP (x, 0))
- && CONSTANT_POOL_ADDRESS_P (XEXP (x, 0)))
- x = get_pool_constant (XEXP (x, 0));
-
- /* First see if we've already got it */
-
- for (i = 0; i < pool_size; i++)
- {
- if (x->code == pool_vector[i].value->code
- && mode == pool_vector[i].mode)
- {
- if (x->code == CODE_LABEL)
- {
- if (XINT (x, 3) != XINT (pool_vector[i].value, 3))
- continue;
- }
- if (rtx_equal_p (x, pool_vector[i].value))
- return pool_vector[i].next_offset - GET_MODE_SIZE (mode);
- }
- }
-
- /* Need a new one */
-
- pool_vector[pool_size].next_offset = GET_MODE_SIZE (mode);
- offset = 0;
- if (pool_size == 0)
- pool_vector_label = gen_label_rtx ();
- else
- pool_vector[pool_size].next_offset
- += (offset = pool_vector[pool_size - 1].next_offset);
-
- pool_vector[pool_size].value = x;
- pool_vector[pool_size].mode = mode;
- pool_size++;
- return offset;
-}
-
-/* Output the literal table */
-
-static void
-dump_table (scan)
- rtx scan;
-{
- int i;
-
- scan = emit_label_after (gen_label_rtx (), scan);
- scan = emit_insn_after (gen_align_4 (), scan);
- scan = emit_label_after (pool_vector_label, scan);
-
- for (i = 0; i < pool_size; i++)
- {
- pool_node *p = pool_vector + i;
-
- switch (GET_MODE_SIZE (p->mode))
- {
- case 4:
- scan = emit_insn_after (gen_consttable_4 (p->value), scan);
- break;
-
- case 8:
- scan = emit_insn_after (gen_consttable_8 (p->value), scan);
- break;
-
- default:
- abort ();
- break;
- }
- }
-
- scan = emit_insn_after (gen_consttable_end (), scan);
- scan = emit_barrier_after (scan);
- pool_size = 0;
-}
-
-/* Non zero if the src operand needs to be fixed up */
-static
-int
-fixit (src, mode)
- rtx src;
- enum machine_mode mode;
-{
- return ((CONSTANT_P (src)
- && (GET_CODE (src) != CONST_INT
- || ! (CONST_OK_FOR_LETTER_P (INTVAL (src), 'I')
- || CONST_OK_FOR_LETTER_P (INTVAL (src), 'J')
- || (mode != DImode
- && CONST_OK_FOR_LETTER_P (INTVAL (src), 'K')))))
- || (mode == SImode && GET_CODE (src) == MEM
- && GET_CODE (XEXP (src, 0)) == SYMBOL_REF
- && CONSTANT_POOL_ADDRESS_P (XEXP (src, 0))));
-}
-
-/* Find the last barrier less than MAX_COUNT bytes from FROM, or create one. */
-
-#define MAX_COUNT_SI 1000
-
-static rtx
-find_barrier (from)
- rtx from;
-{
- int count = 0;
- rtx found_barrier = 0;
- rtx label;
-
- while (from && count < MAX_COUNT_SI)
- {
- if (GET_CODE (from) == BARRIER)
- return from;
-
- /* Count the length of this insn */
- if (GET_CODE (from) == INSN
- && GET_CODE (PATTERN (from)) == SET
- && CONSTANT_P (SET_SRC (PATTERN (from)))
- && CONSTANT_POOL_ADDRESS_P (SET_SRC (PATTERN (from))))
- {
- rtx src = SET_SRC (PATTERN (from));
- count += 2;
- }
- else
- count += get_attr_length (from);
-
- from = NEXT_INSN (from);
- }
-
- /* We didn't find a barrier in time to
- dump our stuff, so we'll make one */
- label = gen_label_rtx ();
-
- if (from)
- from = PREV_INSN (from);
- else
- from = get_last_insn ();
-
- /* Walk back to be just before any jump */
- while (GET_CODE (from) == JUMP_INSN
- || GET_CODE (from) == NOTE
- || GET_CODE (from) == CODE_LABEL)
- from = PREV_INSN (from);
-
- from = emit_jump_insn_after (gen_jump (label), from);
- JUMP_LABEL (from) = label;
- found_barrier = emit_barrier_after (from);
- emit_label_after (label, found_barrier);
- return found_barrier;
-}
-
-/* Non zero if the insn is a move instruction which needs to be fixed. */
-
-static int
-broken_move (insn)
- rtx insn;
-{
- if (!INSN_DELETED_P (insn)
- && GET_CODE (insn) == INSN
- && GET_CODE (PATTERN (insn)) == SET)
- {
- rtx pat = PATTERN (insn);
- rtx src = SET_SRC (pat);
- rtx dst = SET_DEST (pat);
- enum machine_mode mode = GET_MODE (dst);
- if (dst == pc_rtx)
- return 0;
- return fixit (src, mode);
- }
- return 0;
-}
-
-/* Recursively search through all of the blocks in a function
- checking to see if any of the variables created in that
- function match the RTX called 'orig'. If they do then
- replace them with the RTX called 'new'. */
-
-static void
-replace_symbols_in_block (tree block, rtx orig, rtx new)
-{
- for (; block; block = BLOCK_CHAIN (block))
- {
- tree sym;
-
- if (! TREE_USED (block))
- continue;
-
- for (sym = BLOCK_VARS (block); sym; sym = TREE_CHAIN (sym))
- {
- if ( (DECL_NAME (sym) == 0 && TREE_CODE (sym) != TYPE_DECL)
- || DECL_IGNORED_P (sym)
- || TREE_CODE (sym) != VAR_DECL
- || DECL_EXTERNAL (sym)
- || ! rtx_equal_p (DECL_RTL (sym), orig)
- )
- continue;
-
- DECL_RTL (sym) = new;
- }
-
- replace_symbols_in_block (BLOCK_SUBBLOCKS (block), orig, new);
- }
-}
-
-void
-thumb_reorg (first)
- rtx first;
-{
- rtx insn;
- for (insn = first; insn; insn = NEXT_INSN (insn))
- {
- if (broken_move (insn))
- {
- /* This is a broken move instruction, scan ahead looking for
- a barrier to stick the constant table behind */
- rtx scan;
- rtx barrier = find_barrier (insn);
-
- /* Now find all the moves between the points and modify them */
- for (scan = insn; scan != barrier; scan = NEXT_INSN (scan))
- {
- if (broken_move (scan))
- {
- /* This is a broken move instruction, add it to the pool */
- rtx pat = PATTERN (scan);
- rtx src = SET_SRC (pat);
- rtx dst = SET_DEST (pat);
- enum machine_mode mode = GET_MODE (dst);
- HOST_WIDE_INT offset;
- rtx newinsn;
- rtx newsrc;
-
- /* If this is an HImode constant load, convert it into
- an SImode constant load. Since the register is always
- 32 bits this is safe. We have to do this, since the
- load pc-relative instruction only does a 32-bit load. */
- if (mode == HImode)
- {
- mode = SImode;
- if (GET_CODE (dst) != REG)
- abort ();
- PUT_MODE (dst, SImode);
- }
-
- offset = add_constant (src, mode);
- newsrc = gen_rtx (MEM, mode,
- plus_constant (gen_rtx (LABEL_REF,
- VOIDmode,
- pool_vector_label),
- offset));
-
- /* Build a jump insn wrapper around the move instead
- of an ordinary insn, because we want to have room for
- the target label rtx in fld[7], which an ordinary
- insn doesn't have. */
- newinsn = emit_jump_insn_after (gen_rtx (SET, VOIDmode,
- dst, newsrc), scan);
- JUMP_LABEL (newinsn) = pool_vector_label;
-
- /* But it's still an ordinary insn */
- PUT_CODE (newinsn, INSN);
-
- /* If debugging information is going to be emitted
- then we must make sure that any refences to
- symbols which are removed by the above code are
- also removed in the descriptions of the
- function's variables. Failure to do this means
- that the debugging information emitted could
- refer to symbols which are not emited by
- output_constant_pool() because
- mark_constant_pool() never sees them as being
- used. */
-
-
- /* These are the tests used in
- output_constant_pool() to decide if the constant
- pool will be marked. Only necessary if debugging
- info is being emitted. Only necessary for
- references to memory whose address is given by a
- symbol. */
-
- if (optimize > 0
- && flag_expensive_optimizations
- && write_symbols != NO_DEBUG
- && GET_CODE (src) == MEM
- && GET_CODE (XEXP (src, 0)) == SYMBOL_REF)
- replace_symbols_in_block
- (DECL_INITIAL (current_function_decl), src, newsrc);
-
- /* Kill old insn */
- delete_insn (scan);
- scan = newinsn;
- }
- }
- dump_table (barrier);
- }
- }
-}
-
-
-/* Routines for generating rtl */
-
-void
-thumb_expand_movstrqi (operands)
- rtx *operands;
-{
- rtx out = copy_to_mode_reg (SImode, XEXP (operands[0], 0));
- rtx in = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
- HOST_WIDE_INT len = INTVAL (operands[2]);
- HOST_WIDE_INT offset = 0;
-
- while (len >= 12)
- {
- emit_insn (gen_movmem12b (out, in));
- len -= 12;
- }
- if (len >= 8)
- {
- emit_insn (gen_movmem8b (out, in));
- len -= 8;
- }
- if (len >= 4)
- {
- rtx reg = gen_reg_rtx (SImode);
- emit_insn (gen_movsi (reg, gen_rtx (MEM, SImode, in)));
- emit_insn (gen_movsi (gen_rtx (MEM, SImode, out), reg));
- len -= 4;
- offset += 4;
- }
- if (len >= 2)
- {
- rtx reg = gen_reg_rtx (HImode);
- emit_insn (gen_movhi (reg, gen_rtx (MEM, HImode,
- plus_constant (in, offset))));
- emit_insn (gen_movhi (gen_rtx (MEM, HImode, plus_constant (out, offset)),
- reg));
- len -= 2;
- offset += 2;
- }
- if (len)
- {
- rtx reg = gen_reg_rtx (QImode);
- emit_insn (gen_movqi (reg, gen_rtx (MEM, QImode,
- plus_constant (in, offset))));
- emit_insn (gen_movqi (gen_rtx (MEM, QImode, plus_constant (out, offset)),
- reg));
- }
-}
-
-
-/* Routines for reloading */
-
-void
-thumb_reload_out_si (operands)
- rtx operands;
-{
- abort ();
-}
-
-/* CYGNUS LOCAL nickc/thumb-pe */
-
-#ifdef THUMB_PE
-/* Return non-zero if FUNC is a naked function. */
-
-static int
-arm_naked_function_p (func)
- tree func;
-{
- tree a;
-
- if (TREE_CODE (func) != FUNCTION_DECL)
- abort ();
-
- a = lookup_attribute ("naked", DECL_MACHINE_ATTRIBUTES (func));
- return a != NULL_TREE;
-}
-#endif
-/* END CYGNUS LOCAL nickc/thumb-pe */
-
-/* Return non-zero if FUNC must be entered in ARM mode. */
-int
-is_called_in_ARM_mode (func)
- tree func;
-{
- if (TREE_CODE (func) != FUNCTION_DECL)
- abort ();
-
- /* Ignore the problem about functions whoes address is taken. */
- if (TARGET_CALLEE_INTERWORKING && TREE_PUBLIC (func))
- return TRUE;
-
-/* CYGNUS LOCAL nickc/thumb-pe */
-#ifdef THUMB_PE
- return lookup_attribute ("interfacearm", DECL_MACHINE_ATTRIBUTES (func)) != NULL_TREE;
-#else
- return FALSE;
-#endif
-/* END CYGNUS LOCAL */
-}
-
-
-/* Routines for emitting code */
-
-void
-final_prescan_insn(insn)
- rtx insn;
-{
- extern int *insn_addresses;
-
- if (flag_print_asm_name)
- fprintf (asm_out_file, "%s 0x%04x\n", ASM_COMMENT_START,
- insn_addresses[INSN_UID (insn)]);
-}
-
-
-static void thumb_pushpop ( FILE *, int, int ); /* Forward declaration. */
-
-#ifdef __GNUC__
-inline
-#endif
-static int
-number_of_first_bit_set (mask)
- int mask;
-{
- int bit;
-
- for (bit = 0;
- (mask & (1 << bit)) == 0;
- ++ bit)
- continue;
-
- return bit;
-}
-
-#define ARG_1_REGISTER 0
-#define ARG_2_REGISTER 1
-#define ARG_3_REGISTER 2
-#define ARG_4_REGISTER 3
-#define WORK_REGISTER 7
-#define FRAME_POINTER 11
-#define IP_REGISTER 12
-#define STACK_POINTER STACK_POINTER_REGNUM
-#define LINK_REGISTER 14
-#define PROGRAM_COUNTER 15
-
-/* Generate code to return from a thumb function. If
- 'reg_containing_return_addr' is -1, then the return address is
- actually on the stack, at the stack pointer. */
-static void
-thumb_exit (f, reg_containing_return_addr)
- FILE * f;
- int reg_containing_return_addr;
-{
- int regs_available_for_popping;
- int regs_to_pop;
- int pops_needed;
- int reg;
- int available;
- int required;
- int mode;
- int size;
- int restore_a4 = FALSE;
-
- /* Compute the registers we need to pop. */
- regs_to_pop = 0;
- pops_needed = 0;
-
- if (reg_containing_return_addr == -1)
- {
- regs_to_pop |= 1 << LINK_REGISTER;
- ++ pops_needed;
- }
-
- if (TARGET_BACKTRACE)
- {
- /* Restore frame pointer and stack pointer. */
- regs_to_pop |= (1 << FRAME_POINTER) | (1 << STACK_POINTER);
- pops_needed += 2;
- }
-
- /* If there is nothing to pop then just emit the BX instruction and return.*/
- if (pops_needed == 0)
- {
- asm_fprintf (f, "\tbx\t%s\n", reg_names [reg_containing_return_addr]);
-
- return;
- }
-
- /* Otherwise if we are not supporting interworking and we have not created
- a backtrace structure and the function was not entered in ARM mode then
- just pop the return address straight into the PC. */
- else if ( ! TARGET_THUMB_INTERWORK
- && ! TARGET_BACKTRACE
- && ! is_called_in_ARM_mode (current_function_decl))
- {
- asm_fprintf (f, "\tpop\t{pc}\n" );
-
- return;
- }
-
- /* Find out how many of the (return) argument registers we can corrupt. */
- regs_available_for_popping = 0;
-
-#ifdef RTX_CODE
- /* If we can deduce the registers used from the function's return value.
- This is more reliable that examining regs_ever_live[] because that
- will be set if the register is ever used in the function, not just if
- the register is used to hold a return value. */
-
- if (current_function_return_rtx != 0)
- mode = GET_MODE (current_function_return_rtx);
- else
-#endif
- mode = DECL_MODE (DECL_RESULT (current_function_decl));
-
- size = GET_MODE_SIZE (mode);
-
- if (size == 0)
- {
- /* In a void function we can use any argument register.
- In a function that returns a structure on the stack
- we can use the second and third argument registers. */
- if (mode == VOIDmode)
- regs_available_for_popping =
- (1 << ARG_1_REGISTER)
- | (1 << ARG_2_REGISTER)
- | (1 << ARG_3_REGISTER);
- else
- regs_available_for_popping =
- (1 << ARG_2_REGISTER)
- | (1 << ARG_3_REGISTER);
- }
- else if (size <= 4) regs_available_for_popping =
- (1 << ARG_2_REGISTER)
- | (1 << ARG_3_REGISTER);
- else if (size <= 8) regs_available_for_popping =
- (1 << ARG_3_REGISTER);
-
- /* Match registers to be popped with registers into which we pop them. */
- for (available = regs_available_for_popping,
- required = regs_to_pop;
- required != 0 && available != 0;
- available &= ~(available & - available),
- required &= ~(required & - required))
- -- pops_needed;
-
- /* If we have any popping registers left over, remove them. */
- if (available > 0)
- regs_available_for_popping &= ~ available;
-
- /* Otherwise if we need another popping register we can use
- the fourth argument register. */
- else if (pops_needed)
- {
- /* If we have not found any free argument registers and
- reg a4 contains the return address, we must move it. */
- if (regs_available_for_popping == 0
- && reg_containing_return_addr == ARG_4_REGISTER)
- {
- asm_fprintf (f, "\tmov\t%s, %s\n",
- reg_names [LINK_REGISTER], reg_names [ARG_4_REGISTER]);
- reg_containing_return_addr = LINK_REGISTER;
- }
- else if (size > 12)
- {
- /* Register a4 is being used to hold part of the return value,
- but we have dire need of a free, low register. */
- restore_a4 = TRUE;
-
- asm_fprintf (f, "\tmov\t%s, %s\n",
- reg_names [IP_REGISTER], reg_names [ARG_4_REGISTER]);
- }
-
- if (reg_containing_return_addr != ARG_4_REGISTER)
- {
- /* The fourth argument register is available. */
- regs_available_for_popping |= 1 << ARG_4_REGISTER;
-
- -- pops_needed;
- }
- }
-
- /* Pop as many registers as we can. */
- thumb_pushpop (f, regs_available_for_popping, FALSE);
-
- /* Process the registers we popped. */
- if (reg_containing_return_addr == -1)
- {
- /* The return address was popped into the lowest numbered register. */
- regs_to_pop &= ~ (1 << LINK_REGISTER);
-
- reg_containing_return_addr =
- number_of_first_bit_set (regs_available_for_popping);
-
- /* Remove this register for the mask of available registers, so that
- the return address will not be corrupted by futher pops. */
- regs_available_for_popping &= ~ (1 << reg_containing_return_addr);
- }
-
- /* If we popped other registers then handle them here. */
- if (regs_available_for_popping)
- {
- int frame_pointer;
-
- /* Work out which register currently contains the frame pointer. */
- frame_pointer = number_of_first_bit_set (regs_available_for_popping);
-
- /* Move it into the correct place. */
- asm_fprintf (f, "\tmov\tfp, %s\n", reg_names [frame_pointer]);
-
- /* (Temporarily) remove it from the mask of popped registers. */
- regs_available_for_popping &= ~ (1 << frame_pointer);
- regs_to_pop &= ~ (1 << FRAME_POINTER);
-
- if (regs_available_for_popping)
- {
- int stack_pointer;
-
- /* We popped the stack pointer as well, find the register that
- contains it.*/
- stack_pointer = number_of_first_bit_set (regs_available_for_popping);
-
- /* Move it into the stack register. */
- asm_fprintf (f, "\tmov\tsp, %s\n", reg_names [stack_pointer]);
-
- /* At this point we have popped all necessary registers, so
- do not worry about restoring regs_available_for_popping
- to its correct value:
-
- assert (pops_needed == 0)
- assert (regs_available_for_popping == (1 << frame_pointer))
- assert (regs_to_pop == (1 << STACK_POINTER)) */
- }
- else
- {
- /* Since we have just move the popped value into the frame
- pointer, the popping register is available for reuse, and
- we know that we still have the stack pointer left to pop. */
- regs_available_for_popping |= (1 << frame_pointer);
- }
- }
-
- /* If we still have registers left on the stack, but we no longer have
- any registers into which we can pop them, then we must move the return
- address into the link register and make available the register that
- contained it. */
- if (regs_available_for_popping == 0 && pops_needed > 0)
- {
- regs_available_for_popping |= 1 << reg_containing_return_addr;
-
- asm_fprintf (f, "\tmov\t%s, %s\n",
- reg_names [LINK_REGISTER],
- reg_names [reg_containing_return_addr]);
-
- reg_containing_return_addr = LINK_REGISTER;
- }
-
- /* If we have registers left on the stack then pop some more.
- We know that at most we will want to pop FP and SP. */
- if (pops_needed > 0)
- {
- int popped_into;
- int move_to;
-
- thumb_pushpop (f, regs_available_for_popping, FALSE);
-
- /* We have popped either FP or SP.
- Move whichever one it is into the correct register. */
- popped_into = number_of_first_bit_set (regs_available_for_popping);
- move_to = number_of_first_bit_set (regs_to_pop);
-
- asm_fprintf (f, "\tmov\t%s, %s\n",
- reg_names [move_to], reg_names [popped_into]);
-
- regs_to_pop &= ~ (1 << move_to);
-
- -- pops_needed;
- }
-
- /* If we still have not popped everything then we must have only
- had one register available to us and we are now popping the SP. */
- if (pops_needed > 0)
- {
- int popped_into;
-
- thumb_pushpop (f, regs_available_for_popping, FALSE);
-
- popped_into = number_of_first_bit_set (regs_available_for_popping);
-
- asm_fprintf (f, "\tmov\tsp, %s\n", reg_names [popped_into]);
-
- /*
- assert (regs_to_pop == (1 << STACK_POINTER))
- assert (pops_needed == 1)
- */
- }
-
- /* If necessary restore the a4 register. */
- if (restore_a4)
- {
- if (reg_containing_return_addr != LINK_REGISTER)
- {
- asm_fprintf (f, "\tmov\t%s, %s\n",
- reg_names [LINK_REGISTER], reg_names [ARG_4_REGISTER]);
- reg_containing_return_addr = LINK_REGISTER;
- }
-
- asm_fprintf (f, "\tmov\t%s, %s\n",
- reg_names [ARG_4_REGISTER], reg_names [IP_REGISTER]);
- }
-
- /* Return to caller. */
- asm_fprintf (f, "\tbx\t%s\n", reg_names [reg_containing_return_addr]);
-}
-
-/* Emit code to push or pop registers to or from the stack. */
-static void
-thumb_pushpop (f, mask, push)
- FILE * f;
- int mask;
- int push;
-{
- int regno;
- int lo_mask = mask & 0xFF;
-
- if (lo_mask == 0 && ! push && (mask & (1 << 15)))
- {
- /* Special case. Do not generate a POP PC statement here, do it in
- thumb_exit() */
-
- thumb_exit (f, -1);
- return;
- }
-
- asm_fprintf (f, "\t%s\t{", push ? "push" : "pop");
-
- /* Look at the low registers first. */
-
- for (regno = 0; regno < 8; regno ++, lo_mask >>= 1)
- {
- if (lo_mask & 1)
- {
- asm_fprintf (f, reg_names[regno]);
-
- if ((lo_mask & ~1) != 0)
- asm_fprintf (f, ", ");
- }
- }
-
- if (push && (mask & (1 << 14)))
- {
- /* Catch pushing the LR. */
-
- if (mask & 0xFF)
- asm_fprintf (f, ", ");
-
- asm_fprintf (f, reg_names[14]);
- }
- else if (!push && (mask & (1 << 15)))
- {
- /* Catch popping the PC. */
-
- if (TARGET_THUMB_INTERWORK || TARGET_BACKTRACE)
- {
- /* The PC is never poped directly, instead
- it is popped into r3 and then BX is used. */
-
- asm_fprintf (f, "}\n");
-
- thumb_exit (f, -1);
-
- return;
- }
- else
- {
- if (mask & 0xFF)
- asm_fprintf (f, ", ");
-
- asm_fprintf (f, reg_names[15]);
- }
- }
-
- asm_fprintf (f, "}\n");
-}
-
-/* Returns non-zero if the current function contains a far jump */
-
-int
-far_jump_used_p (void)
-{
- rtx insn;
-
- if (current_function_has_far_jump)
- return 1;
-
- for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
- {
- if (GET_CODE (insn) == JUMP_INSN
- /* Ignore tablejump patterns. */
- && GET_CODE (PATTERN (insn)) != ADDR_VEC
- && GET_CODE (PATTERN (insn)) != ADDR_DIFF_VEC
- && get_attr_far_jump (insn) == FAR_JUMP_YES)
- {
- current_function_has_far_jump = 1;
- return 1;
- }
- }
-
- return 0;
-}
-
-static int return_used_this_function = 0;
-
-char *
-output_return ()
-{
- int regno;
- int live_regs_mask = 0;
-
- /* CYGNUS LOCAL nickc/thumb-pe */
-#ifdef THUMB_PE
- /* If a function is naked, don't use the "return" insn. */
- if (arm_naked_function_p (current_function_decl))
- return "";
-#endif
- /* END CYGNUS LOCAL nickc/thumb-pe */
-
- return_used_this_function = 1;
-
- for (regno = 0; regno < 8; regno++)
- if (regs_ever_live[regno] && ! call_used_regs[regno])
- live_regs_mask |= 1 << regno;
-
- if (live_regs_mask == 0)
- {
- if (leaf_function_p () && ! far_jump_used_p())
- {
- thumb_exit (asm_out_file, 14);
- }
- else if ( TARGET_THUMB_INTERWORK
- || TARGET_BACKTRACE
- || is_called_in_ARM_mode (current_function_decl))
- {
- thumb_exit (asm_out_file, -1);
- }
- else
- asm_fprintf (asm_out_file, "\tpop\t{pc}\n");
- }
- else
- {
- asm_fprintf (asm_out_file, "\tpop\t{");
-
- for (regno = 0; live_regs_mask; regno ++, live_regs_mask >>= 1)
- if (live_regs_mask & 1)
- {
- asm_fprintf (asm_out_file, reg_names[regno]);
- if (live_regs_mask & ~1)
- asm_fprintf (asm_out_file, ", ");
- }
-
- if ( TARGET_THUMB_INTERWORK
- || TARGET_BACKTRACE
- || is_called_in_ARM_mode (current_function_decl))
- {
- asm_fprintf (asm_out_file, "}\n");
- thumb_exit (asm_out_file, -1);
- }
- else
- asm_fprintf (asm_out_file, ", pc}\n");
- }
-
- return "";
-}
-
-void
-thumb_function_prologue (f, frame_size)
- FILE *f;
- int frame_size;
-{
- int amount = frame_size + current_function_outgoing_args_size;
- int live_regs_mask = 0;
- int high_regs_pushed = 0;
- int store_arg_regs = 0;
- int regno;
-
-/* CYGNUS LOCAL nickc/thumb-pe */
-#ifdef THUMB_PE
- if (arm_naked_function_p (current_function_decl))
- return;
-#endif
-/* CYGNUS LOCAL nickc/thumb-pe */
-
- if (is_called_in_ARM_mode (current_function_decl))
- {
- char * name;
- if (GET_CODE (DECL_RTL (current_function_decl)) != MEM)
- abort();
- if (GET_CODE (XEXP (DECL_RTL (current_function_decl), 0)) != SYMBOL_REF)
- abort();
- name = XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0);
-
- /* Generate code sequence to switch us into Thumb mode. */
- /* The .code 32 directive has already been emitted by
- ASM_DECLARE_FUNCITON_NAME */
- asm_fprintf (f, "\torr\tr12, pc, #1\n");
- asm_fprintf (f, "\tbx\tr12\n");
-
- /* Generate a label, so that the debugger will notice the
- change in instruction sets. This label is also used by
- the assembler to bypass the ARM code when this function
- is called from a Thumb encoded function elsewhere in the
- same file. Hence the definition of STUB_NAME here must
- agree with the definition in gas/config/tc-arm.c */
-
-#define STUB_NAME ".real_start_of"
-
- asm_fprintf (f, "\t.code\t16\n");
- asm_fprintf (f, "\t.globl %s%U%s\n", STUB_NAME, name);
- asm_fprintf (f, "\t.thumb_func\n");
- asm_fprintf (f, "%s%U%s:\n", STUB_NAME, name);
- }
-
- if (current_function_anonymous_args && current_function_pretend_args_size)
- store_arg_regs = 1;
-
- if (current_function_pretend_args_size)
- {
- if (store_arg_regs)
- {
- asm_fprintf (f, "\tpush\t{");
- for (regno = 4 - current_function_pretend_args_size / 4 ; regno < 4;
- regno++)
- asm_fprintf (f, "%s%s", reg_names[regno], regno == 3 ? "" : ", ");
- asm_fprintf (f, "}\n");
- }
- else
- asm_fprintf (f, "\tsub\t%Rsp, %Rsp, #%d\n",
- current_function_pretend_args_size);
- }
-
- for (regno = 0; regno < 8; regno++)
- if (regs_ever_live[regno] && ! call_used_regs[regno])
- live_regs_mask |= 1 << regno;
-
- if (live_regs_mask || ! leaf_function_p () || far_jump_used_p())
- live_regs_mask |= 1 << 14;
-
- if (TARGET_BACKTRACE)
- {
- char * name;
- int offset;
- int work_register = 0;
-
-
- /* We have been asked to create a stack backtrace structure.
- The code looks like this:
-
- 0 .align 2
- 0 func:
- 0 sub SP, #16 Reserve space for 4 registers.
- 2 push {R7} Get a work register.
- 4 add R7, SP, #20 Get the stack pointer before the push.
- 6 str R7, [SP, #8] Store the stack pointer (before reserving the space).
- 8 mov R7, PC Get hold of the start of this code plus 12.
- 10 str R7, [SP, #16] Store it.
- 12 mov R7, FP Get hold of the current frame pointer.
- 14 str R7, [SP, #4] Store it.
- 16 mov R7, LR Get hold of the current return address.
- 18 str R7, [SP, #12] Store it.
- 20 add R7, SP, #16 Point at the start of the backtrace structure.
- 22 mov FP, R7 Put this value into the frame pointer. */
-
- if ((live_regs_mask & 0xFF) == 0)
- {
- /* See if the a4 register is free. */
-
- if (regs_ever_live[ 3 ] == 0)
- work_register = 3;
- else /* We must push a register of our own */
- live_regs_mask |= (1 << 7);
- }
-
- if (work_register == 0)
- {
- /* Select a register from the list that will be pushed to use as our work register. */
-
- for (work_register = 8; work_register--;)
- if ((1 << work_register) & live_regs_mask)
- break;
- }
-
- name = reg_names[ work_register ];
-
- asm_fprintf (f, "\tsub\tsp, sp, #16\t@ Create stack backtrace structure\n");
-
- if (live_regs_mask)
- thumb_pushpop (f, live_regs_mask, 1);
-
- for (offset = 0, work_register = 1 << 15; work_register; work_register >>= 1)
- if (work_register & live_regs_mask)
- offset += 4;
-
- asm_fprintf (f, "\tadd\t%s, sp, #%d\n",
- name, offset + 16 + current_function_pretend_args_size);
-
- asm_fprintf (f, "\tstr\t%s, [sp, #%d]\n", name, offset + 4);
-
- /* Make sure that the instruction fetching the PC is in the right place
- to calculate "start of backtrace creation code + 12". */
-
- if (live_regs_mask)
- {
- asm_fprintf (f, "\tmov\t%s, pc\n", name);
- asm_fprintf (f, "\tstr\t%s, [sp, #%d]\n", name, offset + 12);
- asm_fprintf (f, "\tmov\t%s, fp\n", name);
- asm_fprintf (f, "\tstr\t%s, [sp, #%d]\n", name, offset);
- }
- else
- {
- asm_fprintf (f, "\tmov\t%s, fp\n", name);
- asm_fprintf (f, "\tstr\t%s, [sp, #%d]\n", name, offset);
- asm_fprintf (f, "\tmov\t%s, pc\n", name);
- asm_fprintf (f, "\tstr\t%s, [sp, #%d]\n", name, offset + 12);
- }
-
- asm_fprintf (f, "\tmov\t%s, lr\n", name);
- asm_fprintf (f, "\tstr\t%s, [sp, #%d]\n", name, offset + 8);
- asm_fprintf (f, "\tadd\t%s, sp, #%d\n", name, offset + 12);
- asm_fprintf (f, "\tmov\tfp, %s\t\t@ Backtrace structure created\n", name);
- }
- else if (live_regs_mask)
- thumb_pushpop (f, live_regs_mask, 1);
-
- for (regno = 8; regno < 13; regno++)
- {
- if (regs_ever_live[regno] && ! call_used_regs[regno])
- high_regs_pushed++;
- }
-
- if (high_regs_pushed)
- {
- int pushable_regs = 0;
- int mask = live_regs_mask & 0xff;
- int next_hi_reg;
-
- for (next_hi_reg = 12; next_hi_reg > 7; next_hi_reg--)
- {
- if (regs_ever_live[next_hi_reg] && ! call_used_regs[next_hi_reg])
- break;
- }
-
- pushable_regs = mask;
-
- if (pushable_regs == 0)
- {
- /* desperation time -- this probably will never happen */
- if (regs_ever_live[3] || ! call_used_regs[3])
- asm_fprintf (f, "\tmov\t%s, %s\n", reg_names[12], reg_names[3]);
- mask = 1 << 3;
- }
-
- while (high_regs_pushed > 0)
- {
- for (regno = 7; regno >= 0; regno--)
- {
- if (mask & (1 << regno))
- {
- asm_fprintf (f, "\tmov\t%s, %s\n", reg_names[regno],
- reg_names[next_hi_reg]);
- high_regs_pushed--;
- if (high_regs_pushed)
- for (next_hi_reg--; next_hi_reg > 7; next_hi_reg--)
- {
- if (regs_ever_live[next_hi_reg]
- && ! call_used_regs[next_hi_reg])
- break;
- }
- else
- {
- mask &= ~ ((1 << regno) - 1);
- break;
- }
- }
- }
- thumb_pushpop (f, mask, 1);
- }
-
- if (pushable_regs == 0 && (regs_ever_live[3] || ! call_used_regs[3]))
- asm_fprintf (f, "\tmov\t%s, %s\n", reg_names[3], reg_names[12]);
- }
-}
-
-void
-thumb_expand_prologue ()
-{
- HOST_WIDE_INT amount = (get_frame_size ()
- + current_function_outgoing_args_size);
- int regno;
- int live_regs_mask;
-
- /* CYGNUS LOCAL nickc/thumb-pe */
-#ifdef THUMB_PE
- /* Naked functions don't have prologues. */
- if (arm_naked_function_p (current_function_decl))
- return;
-#endif
- /* END CYGNUS LOCAL nickc/thumb-pe */
-
- if (amount)
- {
- live_regs_mask = 0;
- for (regno = 0; regno < 8; regno++)
- if (regs_ever_live[regno] && ! call_used_regs[regno])
- live_regs_mask |= 1 << regno;
-
- if (amount < 512)
- emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
- GEN_INT (-amount)));
- else
- {
- rtx reg, spare;
-
- if ((live_regs_mask & 0xff) == 0) /* Very unlikely */
- emit_insn (gen_movsi (spare = gen_rtx (REG, SImode, 12),
- reg = gen_rtx (REG, SImode, 4)));
- else
- {
- for (regno = 0; regno < 8; regno++)
- if (live_regs_mask & (1 << regno))
- break;
- reg = gen_rtx (REG, SImode, regno);
- }
-
- emit_insn (gen_movsi (reg, GEN_INT (-amount)));
- emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, reg));
- if ((live_regs_mask & 0xff) == 0)
- emit_insn (gen_movsi (reg, spare));
- }
- }
-
- if (frame_pointer_needed)
- {
- if (current_function_outgoing_args_size)
- {
- rtx offset = GEN_INT (current_function_outgoing_args_size);
-
- if (current_function_outgoing_args_size < 1024)
- emit_insn (gen_addsi3 (frame_pointer_rtx, stack_pointer_rtx,
- offset));
- else
- {
- emit_insn (gen_movsi (frame_pointer_rtx, offset));
- emit_insn (gen_addsi3 (frame_pointer_rtx, frame_pointer_rtx,
- stack_pointer_rtx));
- }
- }
- else
- emit_insn (gen_movsi (frame_pointer_rtx, stack_pointer_rtx));
- }
-
- /* if (profile_flag || profile_block_flag) */
- emit_insn (gen_blockage ());
-}
-
-void
-thumb_expand_epilogue ()
-{
- HOST_WIDE_INT amount = (get_frame_size ()
- + current_function_outgoing_args_size);
- int regno;
-
- /* CYGNUS LOCAL nickc/thumb-pe */
-#ifdef THUMB_PE
- /* Naked functions don't have epilogues. */
- if (arm_naked_function_p (current_function_decl))
- return;
-#endif
- /* END CYGNUS LOCAL nickc/thumb-pe */
-
- if (amount)
- {
- if (amount < 512)
- emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
- GEN_INT (amount)));
- else
- {
- rtx reg = gen_rtx (REG, SImode, 3); /* Always free in the epilogue */
-
- emit_insn (gen_movsi (reg, GEN_INT (amount)));
- emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, reg));
- }
- /* if (profile_flag || profile_block_flag) */
- emit_insn (gen_blockage ());
- }
-}
-
-void
-thumb_function_epilogue (f, frame_size)
- FILE *f;
- int frame_size;
-{
- /* ??? Probably not safe to set this here, since it assumes that a
- function will be emitted as assembly immediately after we generate
- RTL for it. This does not happen for inline functions. */
- return_used_this_function = 0;
- current_function_has_far_jump = 0;
-#if 0 /* TODO : comment not really needed */
- fprintf (f, "%s THUMB Epilogue\n", ASM_COMMENT_START);
-#endif
-}
-
-/* The bits which aren't usefully expanded as rtl. */
-char *
-thumb_unexpanded_epilogue ()
-{
- int regno;
- int live_regs_mask = 0;
- int high_regs_pushed = 0;
- int leaf_function = leaf_function_p ();
- int had_to_push_lr;
-
- if (return_used_this_function)
- return "";
-
- for (regno = 0; regno < 8; regno++)
- if (regs_ever_live[regno] && ! call_used_regs[regno])
- live_regs_mask |= 1 << regno;
-
- for (regno = 8; regno < 13; regno++)
- {
- if (regs_ever_live[regno] && ! call_used_regs[regno])
- high_regs_pushed ++;
- }
-
- /* The prolog may have pushed some high registers to use as
- work registers. eg the testuite file:
- gcc/testsuite/gcc/gcc.c-torture/execute/complex-2.c
- compiles to produce:
- push {r4, r5, r6, r7, lr}
- mov r7, r9
- mov r6, r8
- push {r6, r7}
- as part of the prolog. We have to undo that pushing here. */
-
- if (high_regs_pushed)
- {
- int mask = live_regs_mask;
- int next_hi_reg;
- int size;
- int mode;
-
-#ifdef RTX_CODE
- /* If we can deduce the registers used from the function's return value.
- This is more reliable that examining regs_ever_live[] because that
- will be set if the register is ever used in the function, not just if
- the register is used to hold a return value. */
-
- if (current_function_return_rtx != 0)
- {
- mode = GET_MODE (current_function_return_rtx);
- }
- else
-#endif
- {
- mode = DECL_MODE (DECL_RESULT (current_function_decl));
- }
-
- size = GET_MODE_SIZE (mode);
-
- /* Unless we are returning a type of size > 12 register r3 is available. */
- if (size < 13)
- mask |= 1 << 3;
-
- if (mask == 0)
- {
- /* Oh dear! We have no low registers into which we can pop high registers! */
-
- fatal ("No low registers available for popping high registers");
- }
-
- for (next_hi_reg = 8; next_hi_reg < 13; next_hi_reg++)
- if (regs_ever_live[next_hi_reg] && ! call_used_regs[next_hi_reg])
- break;
-
- while (high_regs_pushed)
- {
- /* Find low register(s) into which the high register(s) can be popped. */
- for (regno = 0; regno < 8; regno++)
- {
- if (mask & (1 << regno))
- high_regs_pushed--;
- if (high_regs_pushed == 0)
- break;
- }
-
- mask &= (2 << regno) - 1; /* A noop if regno == 8 */
-
- /* Pop the values into the low register(s). */
- thumb_pushpop (asm_out_file, mask, 0);
-
- /* Move the value(s) into the high registers. */
- for (regno = 0; regno < 8; regno++)
- {
- if (mask & (1 << regno))
- {
- asm_fprintf (asm_out_file, "\tmov\t%s, %s\n",
- reg_names[next_hi_reg], reg_names[regno]);
- for (next_hi_reg++; next_hi_reg < 13; next_hi_reg++)
- if (regs_ever_live[next_hi_reg] &&
- ! call_used_regs[next_hi_reg])
- break;
- }
- }
- }
- }
-
- had_to_push_lr = (live_regs_mask || ! leaf_function || far_jump_used_p());
-
- if (TARGET_BACKTRACE && ((live_regs_mask & 0xFF) == 0) && regs_ever_live[ ARG_4_REGISTER ] != 0)
- {
- /* The stack backtrace structure creation code had to
- push R7 in order to get a work register, so we pop
- it now. */
-
- live_regs_mask |= (1 << WORK_REGISTER);
- }
-
- if (current_function_pretend_args_size == 0 || TARGET_BACKTRACE)
- {
- if (had_to_push_lr
- && ! is_called_in_ARM_mode (current_function_decl))
- live_regs_mask |= 1 << PROGRAM_COUNTER;
-
- /* Either no argument registers were pushed or a backtrace
- structure was created which includes an adjusted stack
- pointer, so just pop everything. */
-
- if (live_regs_mask)
- thumb_pushpop (asm_out_file, live_regs_mask, FALSE);
-
- /* We have either just popped the return address into the
- PC or it is was kept in LR for the entire function or
- it is still on the stack because we do not want to
- return by doing a pop {pc}. */
-
- if ((live_regs_mask & (1 << PROGRAM_COUNTER)) == 0)
- thumb_exit (asm_out_file,
- (had_to_push_lr
- && is_called_in_ARM_mode (current_function_decl)) ?
- -1 : LINK_REGISTER);
- }
- else
- {
- /* Pop everything but the return address. */
- live_regs_mask &= ~ (1 << PROGRAM_COUNTER);
-
- if (live_regs_mask)
- thumb_pushpop (asm_out_file, live_regs_mask, FALSE);
-
- if (had_to_push_lr)
- {
- /* Get the return address into a temporary register. */
- thumb_pushpop (asm_out_file, 1 << ARG_4_REGISTER, 0);
- }
-
- /* Remove the argument registers that were pushed onto the stack. */
- asm_fprintf (asm_out_file, "\tadd\t%s, %s, #%d\n",
- reg_names [STACK_POINTER],
- reg_names [STACK_POINTER],
- current_function_pretend_args_size);
-
- thumb_exit (asm_out_file, had_to_push_lr ? ARG_4_REGISTER : LINK_REGISTER);
- }
-
- return "";
-}
-
-/* Handle the case of a double word load into a low register from
- a computed memory address. The computed address may involve a
- register which is overwritten by the load. */
-
-char *
-thumb_load_double_from_address (operands)
- rtx * operands;
-{
- rtx addr;
- rtx base;
- rtx offset;
- rtx arg1;
- rtx arg2;
-
- if (GET_CODE (operands[0]) != REG)
- fatal ("thumb_load_double_from_address: destination is not a register");
-
- if (GET_CODE (operands[1]) != MEM)
- fatal ("thumb_load_double_from_address: source is not a computed memory address");
-
- /* Get the memory address. */
-
- addr = XEXP (operands[1], 0);
-
- /* Work out how the memory address is computed. */
-
- switch (GET_CODE (addr))
- {
- case REG:
- operands[2] = gen_rtx (MEM, SImode, plus_constant (XEXP (operands[1], 0), 4));
-
- if (REGNO (operands[0]) == REGNO (addr))
- {
- output_asm_insn ("ldr\t%H0, %2\t\t%@ created by thumb_load_double_from_address", operands);
- output_asm_insn ("ldr\t%0, %1\t\t%@ created by thumb_load_double_from_address", operands);
- }
- else
- {
- output_asm_insn ("ldr\t%0, %1\t\t%@ created by thumb_load_double_from_address", operands);
- output_asm_insn ("ldr\t%H0, %2\t\t%@ created by thumb_load_double_from_address", operands);
- }
- break;
-
- case CONST:
- /* Compute <address> + 4 for the high order load. */
-
- operands[2] = gen_rtx (MEM, SImode, plus_constant (XEXP (operands[1], 0), 4));
-
- output_asm_insn ("ldr\t%0, %1\t\t%@ created by thumb_load_double_from_address", operands);
- output_asm_insn ("ldr\t%H0, %2\t\t%@ created by thumb_load_double_from_address", operands);
- break;
-
- case PLUS:
- arg1 = XEXP (addr, 0);
- arg2 = XEXP (addr, 1);
-
- if (CONSTANT_P (arg1))
- base = arg2, offset = arg1;
- else
- base = arg1, offset = arg2;
-
- if (GET_CODE (base) != REG)
- fatal ("thumb_load_double_from_address: base is not a register");
-
- /* Catch the case of <address> = <reg> + <reg> */
-
- if (GET_CODE (offset) == REG)
- {
- int reg_offset = REGNO (offset);
- int reg_base = REGNO (base);
- int reg_dest = REGNO (operands[0]);
-
- /* Add the base and offset registers together into the higher destination register. */
-
- fprintf (asm_out_file, "\tadd\t%s, %s, %s\t\t%s created by thumb_load_double_from_address",
- reg_names[ reg_dest + 1 ],
- reg_names[ reg_base ],
- reg_names[ reg_offset ],
- ASM_COMMENT_START);
-
- /* Load the lower destination register from the address in the higher destination register. */
-
- fprintf (asm_out_file, "\tldr\t%s, [%s, #0]\t\t%s created by thumb_load_double_from_address",
- reg_names[ reg_dest ],
- reg_names[ reg_dest + 1],
- ASM_COMMENT_START);
-
- /* Load the higher destination register from its own address plus 4. */
-
- fprintf (asm_out_file, "\tldr\t%s, [%s, #4]\t\t%s created by thumb_load_double_from_address",
- reg_names[ reg_dest + 1 ],
- reg_names[ reg_dest + 1 ],
- ASM_COMMENT_START);
- }
- else
- {
- /* Compute <address> + 4 for the high order load. */
-
- operands[2] = gen_rtx (MEM, SImode, plus_constant (XEXP (operands[1], 0), 4));
-
- /* If the computed address is held in the low order register
- then load the high order register first, otherwise always
- load the low order register first. */
-
- if (REGNO (operands[0]) == REGNO (base))
- {
- output_asm_insn ("ldr\t%H0, %2\t\t%@ created by thumb_load_double_from_address", operands);
- output_asm_insn ("ldr\t%0, %1\t\t%@ created by thumb_load_double_from_address", operands);
- }
- else
- {
- output_asm_insn ("ldr\t%0, %1\t\t%@ created by thumb_load_double_from_address", operands);
- output_asm_insn ("ldr\t%H0, %2\t\t%@ created by thumb_load_double_from_address", operands);
- }
- }
- break;
-
- case LABEL_REF:
- /* With no registers to worry about we can just load the value directly. */
- operands[2] = gen_rtx (MEM, SImode, plus_constant (XEXP (operands[1], 0), 4));
-
- output_asm_insn ("ldr\t%H0, %2\t\t%@ created by thumb_load_double_from_address", operands);
- output_asm_insn ("ldr\t%0, %1\t\t%@ created by thumb_load_double_from_address", operands);
- break;
-
- default:
- debug_rtx (operands[1]);
- fatal ("thumb_load_double_from_address: Unhandled address calculation");
- break;
- }
-
- return "";
-}
-
-char *
-output_move_mem_multiple (n, operands)
- int n;
- rtx *operands;
-{
- rtx tmp;
-
- switch (n)
- {
- case 2:
- if (REGNO (operands[2]) > REGNO (operands[3]))
- {
- tmp = operands[2];
- operands[2] = operands[3];
- operands[3] = tmp;
- }
- output_asm_insn ("ldmia\t%1!, {%2, %3}", operands);
- output_asm_insn ("stmia\t%0!, {%2, %3}", operands);
- break;
-
- case 3:
- if (REGNO (operands[2]) > REGNO (operands[3]))
- {
- tmp = operands[2];
- operands[2] = operands[3];
- operands[3] = tmp;
- }
- if (REGNO (operands[3]) > REGNO (operands[4]))
- {
- tmp = operands[3];
- operands[3] = operands[4];
- operands[4] = tmp;
- }
- if (REGNO (operands[2]) > REGNO (operands[3]))
- {
- tmp = operands[2];
- operands[2] = operands[3];
- operands[3] = tmp;
- }
- output_asm_insn ("ldmia\t%1!, {%2, %3, %4}", operands);
- output_asm_insn ("stmia\t%0!, {%2, %3, %4}", operands);
- break;
-
- default:
- abort ();
- }
-
- return "";
-}
-
-
-int
-thumb_epilogue_size ()
-{
- return 42; /* The answer to .... */
-}
-
-static char *conds[] =
-{
- "eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc",
- "hi", "ls", "ge", "lt", "gt", "le"
-};
-
-static char *
-thumb_condition_code (x, invert)
- rtx x;
- int invert;
-{
- int val;
-
- switch (GET_CODE (x))
- {
- case EQ: val = 0; break;
- case NE: val = 1; break;
- case GEU: val = 2; break;
- case LTU: val = 3; break;
- case GTU: val = 8; break;
- case LEU: val = 9; break;
- case GE: val = 10; break;
- case LT: val = 11; break;
- case GT: val = 12; break;
- case LE: val = 13; break;
- default:
- abort ();
- }
-
- return conds[val ^ invert];
-}
-
-void
-thumb_print_operand (f, x, code)
- FILE *f;
- rtx x;
- int code;
-{
- if (code)
- {
- switch (code)
- {
- case '@':
- fputs (ASM_COMMENT_START, f);
- return;
-
- case '_':
- fputs (user_label_prefix, f);
- return;
-
- case 'D':
- if (x)
- fputs (thumb_condition_code (x, 1), f);
- return;
-
- case 'd':
- if (x)
- fputs (thumb_condition_code (x, 0), f);
- return;
-
- /* An explanation of the 'Q', 'R' and 'H' register operands:
-
- In a pair of registers containing a DI or DF value the 'Q'
- operand returns the register number of the register containing
- the least signficant part of the value. The 'R' operand returns
- the register number of the register containing the most
- significant part of the value.
-
- The 'H' operand returns the higher of the two register numbers.
- On a run where WORDS_BIG_ENDIAN is true the 'H' operand is the
- same as the 'Q' operand, since the most signficant part of the
- value is held in the lower number register. The reverse is true
- on systems where WORDS_BIG_ENDIAN is false.
-
- The purpose of these operands is to distinguish between cases
- where the endian-ness of the values is important (for example
- when they are added together), and cases where the endian-ness
- is irrelevant, but the order of register operations is important.
- For example when loading a value from memory into a register
- pair, the endian-ness does not matter. Provided that the value
- from the lower memory address is put into the lower numbered
- register, and the value from the higher address is put into the
- higher numbered register, the load will work regardless of whether
- the value being loaded is big-wordian or little-wordian. The
- order of the two register loads can matter however, if the address
- of the memory location is actually held in one of the registers
- being overwritten by the load. */
- case 'Q':
- if (REGNO (x) > 15)
- abort ();
- fputs (reg_names[REGNO (x) + (WORDS_BIG_ENDIAN ? 1 : 0)], f);
- return;
-
- case 'R':
- if (REGNO (x) > 15)
- abort ();
- fputs (reg_names[REGNO (x) + (WORDS_BIG_ENDIAN ? 0 : 1)], f);
- return;
-
- case 'H':
- if (REGNO (x) > 15)
- abort ();
- fputs (reg_names[REGNO (x) + 1], f);
- return;
-
- case 'c':
- /* We use 'c' operands with symbols for .vtinherit */
- if (GET_CODE (x) == SYMBOL_REF)
- output_addr_const(f, x);
- return;
-
- default:
- abort ();
- }
- }
- if (GET_CODE (x) == REG)
- fputs (reg_names[REGNO (x)], f);
- else if (GET_CODE (x) == MEM)
- output_address (XEXP (x, 0));
- else if (GET_CODE (x) == CONST_INT)
- {
- fputc ('#', f);
- output_addr_const (f, x);
- }
- else
- abort ();
-}
-
-#ifdef AOF_ASSEMBLER
-int arm_text_section_count = 1;
-
-char *
-aof_text_section (in_readonly)
- int in_readonly;
-{
- static char buf[100];
- if (in_readonly)
- return "";
- sprintf (buf, "\tCODE16\n\tAREA |C$$code%d|, CODE, READONLY",
- arm_text_section_count++);
- return buf;
-}
-
-static int arm_data_section_count = 1;
-
-char *
-aof_data_section ()
-{
- static char buf[100];
- sprintf (buf, "\tAREA |C$$data%d|, DATA", arm_data_section_count++);
- return buf;
-}
-
-/* The AOF thumb assembler is religiously strict about declarations of
- imported and exported symbols, so that it is impossible to declare a
- function as imported near the begining of the file, and then to export
- it later on. It is, however, possible to delay the decision until all
- the functions in the file have been compiled. To get around this, we
- maintain a list of the imports and exports, and delete from it any that
- are subsequently defined. At the end of compilation we spit the
- remainder of the list out before the END directive. */
-
-struct import
-{
- struct import *next;
- char *name;
-};
-
-static struct import *imports_list = NULL;
-
-void
-thumb_aof_add_import (name)
- char *name;
-{
- struct import *new;
-
- for (new = imports_list; new; new = new->next)
- if (new->name == name)
- return;
-
- new = (struct import *) xmalloc (sizeof (struct import));
- new->next = imports_list;
- imports_list = new;
- new->name = name;
-}
-
-void
-thumb_aof_delete_import (name)
- char *name;
-{
- struct import **old;
-
- for (old = &imports_list; *old; old = & (*old)->next)
- {
- if ((*old)->name == name)
- {
- *old = (*old)->next;
- return;
- }
- }
-}
-
-void
-thumb_aof_dump_imports (f)
- FILE *f;
-{
- while (imports_list)
- {
- fprintf (f, "\tIMPORT\t");
- assemble_name (f, imports_list->name);
- fputc ('\n', f);
- imports_list = imports_list->next;
- }
-}
-#endif
-
-/* Decide whether a type should be returned in memory (true)
- or in a register (false). This is called by the macro
- RETURN_IN_MEMORY. */
-
-int
-thumb_return_in_memory (type)
- tree type;
-{
- if (! AGGREGATE_TYPE_P (type))
- {
- /* All simple types are returned in registers. */
-
- return 0;
- }
- else if (int_size_in_bytes (type) > 4)
- {
- /* All structures/unions bigger than one word are returned in memory. */
-
- return 1;
- }
- else if (TREE_CODE (type) == RECORD_TYPE)
- {
- tree field;
-
- /* For a struct the APCS says that we must return in a register if
- every addressable element has an offset of zero. For practical
- purposes this means that the structure can have at most one non-
- bit-field element and that this element must be the first one in
- the structure. */
-
- /* Find the first field, ignoring non FIELD_DECL things which will
- have been created by C++. */
- for (field = TYPE_FIELDS (type);
- field && TREE_CODE (field) != FIELD_DECL;
- field = TREE_CHAIN (field))
- continue;
-
- if (field == NULL)
- return 0; /* An empty structure. Allowed by an extension to ANSI C. */
-
- /* Now check the remaining fields, if any. */
- for (field = TREE_CHAIN (field); field; field = TREE_CHAIN (field))
- {
- if (TREE_CODE (field) != FIELD_DECL)
- continue;
-
- if (! DECL_BIT_FIELD_TYPE (field))
- return 1;
- }
-
- return 0;
- }
- else if (TREE_CODE (type) == UNION_TYPE)
- {
- tree field;
-
- /* Unions can be returned in registers if every element is
- integral, or can be returned in an integer register. */
-
- for (field = TYPE_FIELDS (type);
- field;
- field = TREE_CHAIN (field))
- {
- if (TREE_CODE (field) != FIELD_DECL)
- continue;
-
- if (RETURN_IN_MEMORY (TREE_TYPE (field)))
- return 1;
- }
-
- return 0;
- }
- /* XXX Not sure what should be done for other aggregates, so put them in
- memory. */
- return 1;
-}
-
-void
-thumb_override_options ()
-{
- if (structure_size_string != NULL)
- {
- int size = strtol (structure_size_string, NULL, 0);
-
- if (size == 8 || size == 32)
- arm_structure_size_boundary = size;
- else
- warning ("Structure size boundary can only be set to 8 or 32");
- }
-
- if (flag_pic)
- {
- warning ("Position independent code not supported. Ignored");
- flag_pic = 0;
- }
-}
-
-/* CYGNUS LOCAL nickc/thumb-pe */
-
-#ifdef THUMB_PE
-/* Return nonzero if ATTR is a valid attribute for DECL.
- ATTRIBUTES are any existing attributes and ARGS are the arguments
- supplied with ATTR.
-
- Supported attributes:
-
- naked: don't output any prologue or epilogue code, the user is assumed
- to do the right thing.
-
- interfacearm: Always assume that this function will be entered in ARM
- mode, not Thumb mode, and that the caller wishes to be returned to in
- ARM mode. */
-int
-arm_valid_machine_decl_attribute (decl, attributes, attr, args)
- tree decl;
- tree attributes;
- tree attr;
- tree args;
-{
- if (args != NULL_TREE)
- return 0;
-
- if (is_attribute_p ("naked", attr))
- return TREE_CODE (decl) == FUNCTION_DECL;
-
- if (is_attribute_p ("interfacearm", attr))
- return TREE_CODE (decl) == FUNCTION_DECL;
-
- return 0;
-}
-#endif /* THUMB_PE */
-/* END CYGNUS LOCAL nickc/thumb-pe */
-
-/* s_register_operand is the same as register_operand, but it doesn't accept
- (SUBREG (MEM)...).
-
- This function exists because at the time it was put in it led to better
- code. SUBREG(MEM) always needs a reload in the places where
- s_register_operand is used, and this seemed to lead to excessive
- reloading. */
-
-int
-s_register_operand (op, mode)
- register rtx op;
- enum machine_mode mode;
-{
- if (GET_MODE (op) != mode && mode != VOIDmode)
- return 0;
-
- if (GET_CODE (op) == SUBREG)
- op = SUBREG_REG (op);
-
- /* We don't consider registers whose class is NO_REGS
- to be a register operand. */
- /* XXX might have to check for lo regs only for thumb ??? */
- return (GET_CODE (op) == REG
- && (REGNO (op) >= FIRST_PSEUDO_REGISTER
- || REGNO_REG_CLASS (REGNO (op)) != NO_REGS));
-}
diff --git a/gcc/config/arm/thumb_020422.c b/gcc/config/arm/thumb_020422.c
deleted file mode 100755
index cefc7d4..0000000
--- a/gcc/config/arm/thumb_020422.c
+++ /dev/null
@@ -1,2291 +0,0 @@
-/* Output routines for GCC for ARM/Thumb
- Copyright (C) 1996 Cygnus Software Technologies Ltd
- The basis of this contribution was generated by
- Richard Earnshaw, Advanced RISC Machines Ltd
-
-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. */
-
-#include <stdio.h>
-#include <string.h>
-#include "config.h"
-#include "rtl.h"
-#include "hard-reg-set.h"
-#include "regs.h"
-#include "output.h"
-#include "insn-flags.h"
-#include "insn-attr.h"
-#include "flags.h"
-#include "tree.h"
-#include "expr.h"
-
-
-int current_function_anonymous_args = 0;
-static int current_function_has_far_jump = 0;
-
-/* Used to parse -mstructure_size_boundary command line option. */
-char * structure_size_string = NULL;
-int arm_structure_size_boundary = 32; /* Used to be 8 */
-
-
-/* Predicates */
-int
-reload_memory_operand (op, mode)
- rtx op;
- enum machine_mode mode;
-{
- int regno = true_regnum (op);
-
- return (! CONSTANT_P (op)
- && (regno == -1
- || (GET_CODE (op) == REG
- && REGNO (op) >= FIRST_PSEUDO_REGISTER)));
-}
-
-/* Return nonzero if op is suitable for the RHS of a cmp instruction. */
-int
-thumb_cmp_operand (op, mode)
- rtx op;
- enum machine_mode mode;
-{
- return ((GET_CODE (op) == CONST_INT
- && (unsigned HOST_WIDE_INT) (INTVAL (op)) < 256)
- || register_operand (op, mode));
-}
-
-int
-thumb_shiftable_const (val)
- HOST_WIDE_INT val;
-{
- unsigned HOST_WIDE_INT x = val;
- unsigned HOST_WIDE_INT mask = 0xff;
- int i;
-
- for (i = 0; i < 25; i++)
- if ((val & (mask << i)) == val)
- return 1;
-
- return 0;
-}
-
-int
-thumb_trivial_epilogue ()
-{
- int regno;
-
- /* ??? If this function ever returns 1, we get a function without any
- epilogue at all. It appears that the intent was to cause a "return"
- insn to be emitted, but that does not happen. */
- return 0;
-
-#if 0
- if (get_frame_size ()
- || current_function_outgoing_args_size
- || current_function_pretend_args_size)
- return 0;
-
- for (regno = 8; regno < 13; regno++)
- if (regs_ever_live[regno] && ! call_used_regs[regno])
- return 0;
-
- return 1;
-#endif
-}
-
-
-/* Routines for handling the constant pool */
-/* This is unashamedly hacked from the version in sh.c, since the problem is
- extremely similar. */
-
-/* Thumb instructions cannot load a large constant into a register,
- constants have to come from a pc relative load. The reference of a pc
- relative load instruction must be less than 1k infront of the instruction.
- This means that we often have to dump a constant inside a function, and
- generate code to branch around it.
-
- It is important to minimize this, since the branches will slow things
- down and make things bigger.
-
- Worst case code looks like:
-
- ldr rn, L1
- b L2
- align
- L1: .long value
- L2:
- ..
-
- ldr rn, L3
- b L4
- align
- L3: .long value
- L4:
- ..
-
- We fix this by performing a scan before scheduling, which notices which
- instructions need to have their operands fetched from the constant table
- and builds the table.
-
-
- The algorithm is:
-
- scan, find an instruction which needs a pcrel move. Look forward, find the
- last barrier which is within MAX_COUNT bytes of the requirement.
- If there isn't one, make one. Process all the instructions between
- the find and the barrier.
-
- In the above example, we can tell that L3 is within 1k of L1, so
- the first move can be shrunk from the 2 insn+constant sequence into
- just 1 insn, and the constant moved to L3 to make:
-
- ldr rn, L1
- ..
- ldr rn, L3
- b L4
- align
- L1: .long value
- L3: .long value
- L4:
-
- Then the second move becomes the target for the shortening process.
-
- */
-
-typedef struct
-{
- rtx value; /* Value in table */
- HOST_WIDE_INT next_offset;
- enum machine_mode mode; /* Mode of value */
-} pool_node;
-
-/* The maximum number of constants that can fit into one pool, since
- the pc relative range is 0...1020 bytes and constants are at least 4
- bytes long */
-
-#define MAX_POOL_SIZE (1020/4)
-static pool_node pool_vector[MAX_POOL_SIZE];
-static int pool_size;
-static rtx pool_vector_label;
-
-/* Add a constant to the pool and return its label. */
-
-static HOST_WIDE_INT
-add_constant (x, mode)
- rtx x;
- enum machine_mode mode;
-{
- int i;
- rtx lab;
- HOST_WIDE_INT offset;
-
- if (mode == SImode && GET_CODE (x) == MEM && CONSTANT_P (XEXP (x, 0))
- && CONSTANT_POOL_ADDRESS_P (XEXP (x, 0)))
- x = get_pool_constant (XEXP (x, 0));
-
- /* First see if we've already got it */
-
- for (i = 0; i < pool_size; i++)
- {
- if (x->code == pool_vector[i].value->code
- && mode == pool_vector[i].mode)
- {
- if (x->code == CODE_LABEL)
- {
- if (XINT (x, 3) != XINT (pool_vector[i].value, 3))
- continue;
- }
- if (rtx_equal_p (x, pool_vector[i].value))
- return pool_vector[i].next_offset - GET_MODE_SIZE (mode);
- }
- }
-
- /* Need a new one */
-
- pool_vector[pool_size].next_offset = GET_MODE_SIZE (mode);
- offset = 0;
- if (pool_size == 0)
- pool_vector_label = gen_label_rtx ();
- else
- pool_vector[pool_size].next_offset
- += (offset = pool_vector[pool_size - 1].next_offset);
-
- pool_vector[pool_size].value = x;
- pool_vector[pool_size].mode = mode;
- pool_size++;
- return offset;
-}
-
-/* Output the literal table */
-
-static void
-dump_table (scan)
- rtx scan;
-{
- int i;
-
- scan = emit_label_after (gen_label_rtx (), scan);
- scan = emit_insn_after (gen_align_4 (), scan);
- scan = emit_label_after (pool_vector_label, scan);
-
- for (i = 0; i < pool_size; i++)
- {
- pool_node *p = pool_vector + i;
-
- switch (GET_MODE_SIZE (p->mode))
- {
- case 4:
- scan = emit_insn_after (gen_consttable_4 (p->value), scan);
- break;
-
- case 8:
- scan = emit_insn_after (gen_consttable_8 (p->value), scan);
- break;
-
- default:
- abort ();
- break;
- }
- }
-
- scan = emit_insn_after (gen_consttable_end (), scan);
- scan = emit_barrier_after (scan);
- pool_size = 0;
-}
-
-/* Non zero if the src operand needs to be fixed up */
-static
-int
-fixit (src, mode)
- rtx src;
- enum machine_mode mode;
-{
- return ((CONSTANT_P (src)
- && (GET_CODE (src) != CONST_INT
- || ! (CONST_OK_FOR_LETTER_P (INTVAL (src), 'I')
- || CONST_OK_FOR_LETTER_P (INTVAL (src), 'J')
- || (mode != DImode
- && CONST_OK_FOR_LETTER_P (INTVAL (src), 'K')))))
- || (mode == SImode && GET_CODE (src) == MEM
- && GET_CODE (XEXP (src, 0)) == SYMBOL_REF
- && CONSTANT_POOL_ADDRESS_P (XEXP (src, 0))));
-}
-
-/* Find the last barrier less than MAX_COUNT bytes from FROM, or create one. */
-
-#define MAX_COUNT_SI 1000
-
-static rtx
-find_barrier (from)
- rtx from;
-{
- int count = 0;
- rtx found_barrier = 0;
- rtx label;
-
- while (from && count < MAX_COUNT_SI)
- {
- if (GET_CODE (from) == BARRIER)
- return from;
-
- /* Count the length of this insn */
- if (GET_CODE (from) == INSN
- && GET_CODE (PATTERN (from)) == SET
- && CONSTANT_P (SET_SRC (PATTERN (from)))
- && CONSTANT_POOL_ADDRESS_P (SET_SRC (PATTERN (from))))
- {
- rtx src = SET_SRC (PATTERN (from));
- count += 2;
- }
- else
- count += get_attr_length (from);
-
- from = NEXT_INSN (from);
- }
-
- /* We didn't find a barrier in time to
- dump our stuff, so we'll make one */
- label = gen_label_rtx ();
-
- if (from)
- from = PREV_INSN (from);
- else
- from = get_last_insn ();
-
- /* Walk back to be just before any jump */
- while (GET_CODE (from) == JUMP_INSN
- || GET_CODE (from) == NOTE
- || GET_CODE (from) == CODE_LABEL)
- from = PREV_INSN (from);
-
- from = emit_jump_insn_after (gen_jump (label), from);
- JUMP_LABEL (from) = label;
- found_barrier = emit_barrier_after (from);
- emit_label_after (label, found_barrier);
- return found_barrier;
-}
-
-/* Non zero if the insn is a move instruction which needs to be fixed. */
-
-static int
-broken_move (insn)
- rtx insn;
-{
- if (!INSN_DELETED_P (insn)
- && GET_CODE (insn) == INSN
- && GET_CODE (PATTERN (insn)) == SET)
- {
- rtx pat = PATTERN (insn);
- rtx src = SET_SRC (pat);
- rtx dst = SET_DEST (pat);
- enum machine_mode mode = GET_MODE (dst);
- if (dst == pc_rtx)
- return 0;
- return fixit (src, mode);
- }
- return 0;
-}
-
-/* Recursively search through all of the blocks in a function
- checking to see if any of the variables created in that
- function match the RTX called 'orig'. If they do then
- replace them with the RTX called 'new'. */
-
-static void
-replace_symbols_in_block (tree block, rtx orig, rtx new)
-{
- for (; block; block = BLOCK_CHAIN (block))
- {
- tree sym;
-
- if (! TREE_USED (block))
- continue;
-
- for (sym = BLOCK_VARS (block); sym; sym = TREE_CHAIN (sym))
- {
- if ( (DECL_NAME (sym) == 0 && TREE_CODE (sym) != TYPE_DECL)
- || DECL_IGNORED_P (sym)
- || TREE_CODE (sym) != VAR_DECL
- || DECL_EXTERNAL (sym)
- || ! rtx_equal_p (DECL_RTL (sym), orig)
- )
- continue;
-
- DECL_RTL (sym) = new;
- }
-
- replace_symbols_in_block (BLOCK_SUBBLOCKS (block), orig, new);
- }
-}
-
-void
-thumb_reorg (first)
- rtx first;
-{
- rtx insn;
- for (insn = first; insn; insn = NEXT_INSN (insn))
- {
- if (broken_move (insn))
- {
- /* This is a broken move instruction, scan ahead looking for
- a barrier to stick the constant table behind */
- rtx scan;
- rtx barrier = find_barrier (insn);
-
- /* Now find all the moves between the points and modify them */
- for (scan = insn; scan != barrier; scan = NEXT_INSN (scan))
- {
- if (broken_move (scan))
- {
- /* This is a broken move instruction, add it to the pool */
- rtx pat = PATTERN (scan);
- rtx src = SET_SRC (pat);
- rtx dst = SET_DEST (pat);
- enum machine_mode mode = GET_MODE (dst);
- HOST_WIDE_INT offset;
- rtx newinsn;
- rtx newsrc;
-
- /* If this is an HImode constant load, convert it into
- an SImode constant load. Since the register is always
- 32 bits this is safe. We have to do this, since the
- load pc-relative instruction only does a 32-bit load. */
- if (mode == HImode)
- {
- mode = SImode;
- if (GET_CODE (dst) != REG)
- abort ();
- PUT_MODE (dst, SImode);
- }
-
- offset = add_constant (src, mode);
- newsrc = gen_rtx (MEM, mode,
- plus_constant (gen_rtx (LABEL_REF,
- VOIDmode,
- pool_vector_label),
- offset));
-
- /* Build a jump insn wrapper around the move instead
- of an ordinary insn, because we want to have room for
- the target label rtx in fld[7], which an ordinary
- insn doesn't have. */
- newinsn = emit_jump_insn_after (gen_rtx (SET, VOIDmode,
- dst, newsrc), scan);
- JUMP_LABEL (newinsn) = pool_vector_label;
-
- /* But it's still an ordinary insn */
- PUT_CODE (newinsn, INSN);
-
- /* If debugging information is going to be emitted
- then we must make sure that any refences to
- symbols which are removed by the above code are
- also removed in the descriptions of the
- function's variables. Failure to do this means
- that the debugging information emitted could
- refer to symbols which are not emited by
- output_constant_pool() because
- mark_constant_pool() never sees them as being
- used. */
-
-
- /* These are the tests used in
- output_constant_pool() to decide if the constant
- pool will be marked. Only necessary if debugging
- info is being emitted. Only necessary for
- references to memory whose address is given by a
- symbol. */
-
- if (optimize > 0
- && flag_expensive_optimizations
- && write_symbols != NO_DEBUG
- && GET_CODE (src) == MEM
- && GET_CODE (XEXP (src, 0)) == SYMBOL_REF)
- replace_symbols_in_block
- (DECL_INITIAL (current_function_decl), src, newsrc);
-
- /* Kill old insn */
- delete_insn (scan);
- scan = newinsn;
- }
- }
- dump_table (barrier);
- }
- }
-}
-
-
-/* Routines for generating rtl */
-
-void
-thumb_expand_movstrqi (operands)
- rtx *operands;
-{
- rtx out = copy_to_mode_reg (SImode, XEXP (operands[0], 0));
- rtx in = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
- HOST_WIDE_INT len = INTVAL (operands[2]);
- HOST_WIDE_INT offset = 0;
-
- while (len >= 12)
- {
- emit_insn (gen_movmem12b (out, in));
- len -= 12;
- }
- if (len >= 8)
- {
- emit_insn (gen_movmem8b (out, in));
- len -= 8;
- }
- if (len >= 4)
- {
- rtx reg = gen_reg_rtx (SImode);
- emit_insn (gen_movsi (reg, gen_rtx (MEM, SImode, in)));
- emit_insn (gen_movsi (gen_rtx (MEM, SImode, out), reg));
- len -= 4;
- offset += 4;
- }
- if (len >= 2)
- {
- rtx reg = gen_reg_rtx (HImode);
- emit_insn (gen_movhi (reg, gen_rtx (MEM, HImode,
- plus_constant (in, offset))));
- emit_insn (gen_movhi (gen_rtx (MEM, HImode, plus_constant (out, offset)),
- reg));
- len -= 2;
- offset += 2;
- }
- if (len)
- {
- rtx reg = gen_reg_rtx (QImode);
- emit_insn (gen_movqi (reg, gen_rtx (MEM, QImode,
- plus_constant (in, offset))));
- emit_insn (gen_movqi (gen_rtx (MEM, QImode, plus_constant (out, offset)),
- reg));
- }
-}
-
-
-/* Routines for reloading */
-
-void
-thumb_reload_out_si (operands)
- rtx operands;
-{
- abort ();
-}
-
-/* CYGNUS LOCAL nickc/thumb-pe */
-
-#ifdef THUMB_PE
-/* Return non-zero if FUNC is a naked function. */
-
-static int
-arm_naked_function_p (func)
- tree func;
-{
- tree a;
-
- if (TREE_CODE (func) != FUNCTION_DECL)
- abort ();
-
- a = lookup_attribute ("naked", DECL_MACHINE_ATTRIBUTES (func));
- return a != NULL_TREE;
-}
-#endif
-/* END CYGNUS LOCAL nickc/thumb-pe */
-
-/* Return non-zero if FUNC must be entered in ARM mode. */
-int
-is_called_in_ARM_mode (func)
- tree func;
-{
- if (TREE_CODE (func) != FUNCTION_DECL)
- abort ();
-
- /* Ignore the problem about functions whoes address is taken. */
- if (TARGET_CALLEE_INTERWORKING && TREE_PUBLIC (func))
- return TRUE;
-
-/* CYGNUS LOCAL nickc/thumb-pe */
-#ifdef THUMB_PE
- return lookup_attribute ("interfacearm", DECL_MACHINE_ATTRIBUTES (func)) != NULL_TREE;
-#else
- return FALSE;
-#endif
-/* END CYGNUS LOCAL */
-}
-
-
-/* Routines for emitting code */
-
-void
-final_prescan_insn(insn)
- rtx insn;
-{
- extern int *insn_addresses;
-
- if (flag_print_asm_name)
- fprintf (asm_out_file, "%s 0x%04x\n", ASM_COMMENT_START,
- insn_addresses[INSN_UID (insn)]);
-}
-
-
-static void thumb_pushpop ( FILE *, int, int ); /* Forward declaration. */
-
-#ifdef __GNUC__
-inline
-#endif
-static int
-number_of_first_bit_set (mask)
- int mask;
-{
- int bit;
-
- for (bit = 0;
- (mask & (1 << bit)) == 0;
- ++ bit)
- continue;
-
- return bit;
-}
-
-#define ARG_1_REGISTER 0
-#define ARG_2_REGISTER 1
-#define ARG_3_REGISTER 2
-#define ARG_4_REGISTER 3
-#define WORK_REGISTER 7
-#define FRAME_POINTER 11
-#define IP_REGISTER 12
-#define STACK_POINTER STACK_POINTER_REGNUM
-#define LINK_REGISTER 14
-#define PROGRAM_COUNTER 15
-
-/* Generate code to return from a thumb function. If
- 'reg_containing_return_addr' is -1, then the return address is
- actually on the stack, at the stack pointer. */
-static void
-thumb_exit (f, reg_containing_return_addr)
- FILE * f;
- int reg_containing_return_addr;
-{
- int regs_available_for_popping;
- int regs_to_pop;
- int pops_needed;
- int reg;
- int available;
- int required;
- int mode;
- int size;
- int restore_a4 = FALSE;
-
- /* Compute the registers we need to pop. */
- regs_to_pop = 0;
- pops_needed = 0;
-
- if (reg_containing_return_addr == -1)
- {
- regs_to_pop |= 1 << LINK_REGISTER;
- ++ pops_needed;
- }
-
- if (TARGET_BACKTRACE)
- {
- /* Restore frame pointer and stack pointer. */
- regs_to_pop |= (1 << FRAME_POINTER) | (1 << STACK_POINTER);
- pops_needed += 2;
- }
-
- /* If there is nothing to pop then just emit the BX instruction and return.*/
- if (pops_needed == 0)
- {
- asm_fprintf (f, "\tbx\t%s\n", reg_names [reg_containing_return_addr]);
-
- return;
- }
-
- /* Otherwise if we are not supporting interworking and we have not created
- a backtrace structure and the function was not entered in ARM mode then
- just pop the return address straight into the PC. */
- else if ( ! TARGET_THUMB_INTERWORK
- && ! TARGET_BACKTRACE
- && ! is_called_in_ARM_mode (current_function_decl))
- {
- asm_fprintf (f, "\tpop\t{pc}\n" );
-
- return;
- }
-
- /* Find out how many of the (return) argument registers we can corrupt. */
- regs_available_for_popping = 0;
-
-#ifdef RTX_CODE
- /* If we can deduce the registers used from the function's return value.
- This is more reliable that examining regs_ever_live[] because that
- will be set if the register is ever used in the function, not just if
- the register is used to hold a return value. */
-
- if (current_function_return_rtx != 0)
- mode = GET_MODE (current_function_return_rtx);
- else
-#endif
- mode = DECL_MODE (DECL_RESULT (current_function_decl));
-
- size = GET_MODE_SIZE (mode);
-
- if (size == 0)
- {
- /* In a void function we can use any argument register.
- In a function that returns a structure on the stack
- we can use the second and third argument registers. */
- if (mode == VOIDmode)
- regs_available_for_popping =
- (1 << ARG_1_REGISTER)
- | (1 << ARG_2_REGISTER)
- | (1 << ARG_3_REGISTER);
- else
- regs_available_for_popping =
- (1 << ARG_2_REGISTER)
- | (1 << ARG_3_REGISTER);
- }
- else if (size <= 4) regs_available_for_popping =
- (1 << ARG_2_REGISTER)
- | (1 << ARG_3_REGISTER);
- else if (size <= 8) regs_available_for_popping =
- (1 << ARG_3_REGISTER);
-
- /* Match registers to be popped with registers into which we pop them. */
- for (available = regs_available_for_popping,
- required = regs_to_pop;
- required != 0 && available != 0;
- available &= ~(available & - available),
- required &= ~(required & - required))
- -- pops_needed;
-
- /* If we have any popping registers left over, remove them. */
- if (available > 0)
- regs_available_for_popping &= ~ available;
-
- /* Otherwise if we need another popping register we can use
- the fourth argument register. */
- else if (pops_needed)
- {
- /* If we have not found any free argument registers and
- reg a4 contains the return address, we must move it. */
- if (regs_available_for_popping == 0
- && reg_containing_return_addr == ARG_4_REGISTER)
- {
- asm_fprintf (f, "\tmov\t%s, %s\n",
- reg_names [LINK_REGISTER], reg_names [ARG_4_REGISTER]);
- reg_containing_return_addr = LINK_REGISTER;
- }
- else if (size > 12)
- {
- /* Register a4 is being used to hold part of the return value,
- but we have dire need of a free, low register. */
- restore_a4 = TRUE;
-
- asm_fprintf (f, "\tmov\t%s, %s\n",
- reg_names [IP_REGISTER], reg_names [ARG_4_REGISTER]);
- }
-
- if (reg_containing_return_addr != ARG_4_REGISTER)
- {
- /* The fourth argument register is available. */
- regs_available_for_popping |= 1 << ARG_4_REGISTER;
-
- -- pops_needed;
- }
- }
-
- /* Pop as many registers as we can. */
- thumb_pushpop (f, regs_available_for_popping, FALSE);
-
- /* Process the registers we popped. */
- if (reg_containing_return_addr == -1)
- {
- /* The return address was popped into the lowest numbered register. */
- regs_to_pop &= ~ (1 << LINK_REGISTER);
-
- reg_containing_return_addr =
- number_of_first_bit_set (regs_available_for_popping);
-
- /* Remove this register for the mask of available registers, so that
- the return address will not be corrupted by futher pops. */
- regs_available_for_popping &= ~ (1 << reg_containing_return_addr);
- }
-
- /* If we popped other registers then handle them here. */
- if (regs_available_for_popping)
- {
- int frame_pointer;
-
- /* Work out which register currently contains the frame pointer. */
- frame_pointer = number_of_first_bit_set (regs_available_for_popping);
-
- /* Move it into the correct place. */
- asm_fprintf (f, "\tmov\tfp, %s\n", reg_names [frame_pointer]);
-
- /* (Temporarily) remove it from the mask of popped registers. */
- regs_available_for_popping &= ~ (1 << frame_pointer);
- regs_to_pop &= ~ (1 << FRAME_POINTER);
-
- if (regs_available_for_popping)
- {
- int stack_pointer;
-
- /* We popped the stack pointer as well, find the register that
- contains it.*/
- stack_pointer = number_of_first_bit_set (regs_available_for_popping);
-
- /* Move it into the stack register. */
- asm_fprintf (f, "\tmov\tsp, %s\n", reg_names [stack_pointer]);
-
- /* At this point we have popped all necessary registers, so
- do not worry about restoring regs_available_for_popping
- to its correct value:
-
- assert (pops_needed == 0)
- assert (regs_available_for_popping == (1 << frame_pointer))
- assert (regs_to_pop == (1 << STACK_POINTER)) */
- }
- else
- {
- /* Since we have just move the popped value into the frame
- pointer, the popping register is available for reuse, and
- we know that we still have the stack pointer left to pop. */
- regs_available_for_popping |= (1 << frame_pointer);
- }
- }
-
- /* If we still have registers left on the stack, but we no longer have
- any registers into which we can pop them, then we must move the return
- address into the link register and make available the register that
- contained it. */
- if (regs_available_for_popping == 0 && pops_needed > 0)
- {
- regs_available_for_popping |= 1 << reg_containing_return_addr;
-
- asm_fprintf (f, "\tmov\t%s, %s\n",
- reg_names [LINK_REGISTER],
- reg_names [reg_containing_return_addr]);
-
- reg_containing_return_addr = LINK_REGISTER;
- }
-
- /* If we have registers left on the stack then pop some more.
- We know that at most we will want to pop FP and SP. */
- if (pops_needed > 0)
- {
- int popped_into;
- int move_to;
-
- thumb_pushpop (f, regs_available_for_popping, FALSE);
-
- /* We have popped either FP or SP.
- Move whichever one it is into the correct register. */
- popped_into = number_of_first_bit_set (regs_available_for_popping);
- move_to = number_of_first_bit_set (regs_to_pop);
-
- asm_fprintf (f, "\tmov\t%s, %s\n",
- reg_names [move_to], reg_names [popped_into]);
-
- regs_to_pop &= ~ (1 << move_to);
-
- -- pops_needed;
- }
-
- /* If we still have not popped everything then we must have only
- had one register available to us and we are now popping the SP. */
- if (pops_needed > 0)
- {
- int popped_into;
-
- thumb_pushpop (f, regs_available_for_popping, FALSE);
-
- popped_into = number_of_first_bit_set (regs_available_for_popping);
-
- asm_fprintf (f, "\tmov\tsp, %s\n", reg_names [popped_into]);
-
- /*
- assert (regs_to_pop == (1 << STACK_POINTER))
- assert (pops_needed == 1)
- */
- }
-
- /* If necessary restore the a4 register. */
- if (restore_a4)
- {
- if (reg_containing_return_addr != LINK_REGISTER)
- {
- asm_fprintf (f, "\tmov\t%s, %s\n",
- reg_names [LINK_REGISTER], reg_names [ARG_4_REGISTER]);
- reg_containing_return_addr = LINK_REGISTER;
- }
-
- asm_fprintf (f, "\tmov\t%s, %s\n",
- reg_names [ARG_4_REGISTER], reg_names [IP_REGISTER]);
- }
-
- /* Return to caller. */
- asm_fprintf (f, "\tbx\t%s\n", reg_names [reg_containing_return_addr]);
-}
-
-/* Emit code to push or pop registers to or from the stack. */
-static void
-thumb_pushpop (f, mask, push)
- FILE * f;
- int mask;
- int push;
-{
- int regno;
- int lo_mask = mask & 0xFF;
-
- if (lo_mask == 0 && ! push && (mask & (1 << 15)))
- {
- /* Special case. Do not generate a POP PC statement here, do it in
- thumb_exit() */
-
- thumb_exit (f, -1);
- return;
- }
-
- asm_fprintf (f, "\t%s\t{", push ? "push" : "pop");
-
- /* Look at the low registers first. */
-
- for (regno = 0; regno < 8; regno ++, lo_mask >>= 1)
- {
- if (lo_mask & 1)
- {
- asm_fprintf (f, reg_names[regno]);
-
- if ((lo_mask & ~1) != 0)
- asm_fprintf (f, ", ");
- }
- }
-
- if (push && (mask & (1 << 14)))
- {
- /* Catch pushing the LR. */
-
- if (mask & 0xFF)
- asm_fprintf (f, ", ");
-
- asm_fprintf (f, reg_names[14]);
- }
- else if (!push && (mask & (1 << 15)))
- {
- /* Catch popping the PC. */
-
- if (TARGET_THUMB_INTERWORK || TARGET_BACKTRACE)
- {
- /* The PC is never poped directly, instead
- it is popped into r3 and then BX is used. */
-
- asm_fprintf (f, "}\n");
-
- thumb_exit (f, -1);
-
- return;
- }
- else
- {
- if (mask & 0xFF)
- asm_fprintf (f, ", ");
-
- asm_fprintf (f, reg_names[15]);
- }
- }
-
- asm_fprintf (f, "}\n");
-}
-
-/* Returns non-zero if the current function contains a far jump */
-
-int
-far_jump_used_p (void)
-{
- rtx insn;
-
- if (current_function_has_far_jump)
- return 1;
-
- for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
- {
- if (GET_CODE (insn) == JUMP_INSN
- /* Ignore tablejump patterns. */
- && GET_CODE (PATTERN (insn)) != ADDR_VEC
- && GET_CODE (PATTERN (insn)) != ADDR_DIFF_VEC
- && get_attr_far_jump (insn) == FAR_JUMP_YES)
- {
- current_function_has_far_jump = 1;
- return 1;
- }
- }
-
- return 0;
-}
-
-static int return_used_this_function = 0;
-
-char *
-output_return ()
-{
- int regno;
- int live_regs_mask = 0;
-
- /* CYGNUS LOCAL nickc/thumb-pe */
-#ifdef THUMB_PE
- /* If a function is naked, don't use the "return" insn. */
- if (arm_naked_function_p (current_function_decl))
- return "";
-#endif
- /* END CYGNUS LOCAL nickc/thumb-pe */
-
- return_used_this_function = 1;
-
- for (regno = 0; regno < 8; regno++)
- if (regs_ever_live[regno] && ! call_used_regs[regno])
- live_regs_mask |= 1 << regno;
-
- if (live_regs_mask == 0)
- {
- if (leaf_function_p () && ! far_jump_used_p())
- {
- thumb_exit (asm_out_file, 14);
- }
- else if ( TARGET_THUMB_INTERWORK
- || TARGET_BACKTRACE
- || is_called_in_ARM_mode (current_function_decl))
- {
- thumb_exit (asm_out_file, -1);
- }
- else
- asm_fprintf (asm_out_file, "\tpop\t{pc}\n");
- }
- else
- {
- asm_fprintf (asm_out_file, "\tpop\t{");
-
- for (regno = 0; live_regs_mask; regno ++, live_regs_mask >>= 1)
- if (live_regs_mask & 1)
- {
- asm_fprintf (asm_out_file, reg_names[regno]);
- if (live_regs_mask & ~1)
- asm_fprintf (asm_out_file, ", ");
- }
-
- if ( TARGET_THUMB_INTERWORK
- || TARGET_BACKTRACE
- || is_called_in_ARM_mode (current_function_decl))
- {
- asm_fprintf (asm_out_file, "}\n");
- thumb_exit (asm_out_file, -1);
- }
- else
- asm_fprintf (asm_out_file, ", pc}\n");
- }
-
- return "";
-}
-
-void
-thumb_function_prologue (f, frame_size)
- FILE *f;
- int frame_size;
-{
- int amount = frame_size + current_function_outgoing_args_size;
- int live_regs_mask = 0;
- int high_regs_pushed = 0;
- int store_arg_regs = 0;
- int regno;
-
-/* CYGNUS LOCAL nickc/thumb-pe */
-#ifdef THUMB_PE
- if (arm_naked_function_p (current_function_decl))
- return;
-#endif
-/* CYGNUS LOCAL nickc/thumb-pe */
-
- if (is_called_in_ARM_mode (current_function_decl))
- {
- char * name;
- if (GET_CODE (DECL_RTL (current_function_decl)) != MEM)
- abort();
- if (GET_CODE (XEXP (DECL_RTL (current_function_decl), 0)) != SYMBOL_REF)
- abort();
- name = XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0);
-
- /* Generate code sequence to switch us into Thumb mode. */
- /* The .code 32 directive has already been emitted by
- ASM_DECLARE_FUNCITON_NAME */
- asm_fprintf (f, "\torr\tr12, pc, #1\n");
- asm_fprintf (f, "\tbx\tr12\n");
-
- /* Generate a label, so that the debugger will notice the
- change in instruction sets. This label is also used by
- the assembler to bypass the ARM code when this function
- is called from a Thumb encoded function elsewhere in the
- same file. Hence the definition of STUB_NAME here must
- agree with the definition in gas/config/tc-arm.c */
-
-#define STUB_NAME ".real_start_of"
-
- asm_fprintf (f, "\t.code\t16\n");
- asm_fprintf (f, "\t.globl %s%U%s\n", STUB_NAME, name);
- asm_fprintf (f, "\t.thumb_func\n");
- asm_fprintf (f, "%s%U%s:\n", STUB_NAME, name);
- }
-
- if (current_function_anonymous_args && current_function_pretend_args_size)
- store_arg_regs = 1;
-
- if (current_function_pretend_args_size)
- {
- if (store_arg_regs)
- {
- asm_fprintf (f, "\tpush\t{");
- for (regno = 4 - current_function_pretend_args_size / 4 ; regno < 4;
- regno++)
- asm_fprintf (f, "%s%s", reg_names[regno], regno == 3 ? "" : ", ");
- asm_fprintf (f, "}\n");
- }
- else
- asm_fprintf (f, "\tsub\t%Rsp, %Rsp, #%d\n",
- current_function_pretend_args_size);
- }
-
- for (regno = 0; regno < 8; regno++)
- if (regs_ever_live[regno] && ! call_used_regs[regno])
- live_regs_mask |= 1 << regno;
-
- if (live_regs_mask || ! leaf_function_p () || far_jump_used_p())
- live_regs_mask |= 1 << 14;
-
- if (TARGET_BACKTRACE)
- {
- char * name;
- int offset;
- int work_register = 0;
-
-
- /* We have been asked to create a stack backtrace structure.
- The code looks like this:
-
- 0 .align 2
- 0 func:
- 0 sub SP, #16 Reserve space for 4 registers.
- 2 push {R7} Get a work register.
- 4 add R7, SP, #20 Get the stack pointer before the push.
- 6 str R7, [SP, #8] Store the stack pointer (before reserving the space).
- 8 mov R7, PC Get hold of the start of this code plus 12.
- 10 str R7, [SP, #16] Store it.
- 12 mov R7, FP Get hold of the current frame pointer.
- 14 str R7, [SP, #4] Store it.
- 16 mov R7, LR Get hold of the current return address.
- 18 str R7, [SP, #12] Store it.
- 20 add R7, SP, #16 Point at the start of the backtrace structure.
- 22 mov FP, R7 Put this value into the frame pointer. */
-
- if ((live_regs_mask & 0xFF) == 0)
- {
- /* See if the a4 register is free. */
-
- if (regs_ever_live[ 3 ] == 0)
- work_register = 3;
- else /* We must push a register of our own */
- live_regs_mask |= (1 << 7);
- }
-
- if (work_register == 0)
- {
- /* Select a register from the list that will be pushed to use as our work register. */
-
- for (work_register = 8; work_register--;)
- if ((1 << work_register) & live_regs_mask)
- break;
- }
-
- name = reg_names[ work_register ];
-
- asm_fprintf (f, "\tsub\tsp, sp, #16\t@ Create stack backtrace structure\n");
-
- if (live_regs_mask)
- thumb_pushpop (f, live_regs_mask, 1);
-
- for (offset = 0, work_register = 1 << 15; work_register; work_register >>= 1)
- if (work_register & live_regs_mask)
- offset += 4;
-
- asm_fprintf (f, "\tadd\t%s, sp, #%d\n",
- name, offset + 16 + current_function_pretend_args_size);
-
- asm_fprintf (f, "\tstr\t%s, [sp, #%d]\n", name, offset + 4);
-
- /* Make sure that the instruction fetching the PC is in the right place
- to calculate "start of backtrace creation code + 12". */
-
- if (live_regs_mask)
- {
- asm_fprintf (f, "\tmov\t%s, pc\n", name);
- asm_fprintf (f, "\tstr\t%s, [sp, #%d]\n", name, offset + 12);
- asm_fprintf (f, "\tmov\t%s, fp\n", name);
- asm_fprintf (f, "\tstr\t%s, [sp, #%d]\n", name, offset);
- }
- else
- {
- asm_fprintf (f, "\tmov\t%s, fp\n", name);
- asm_fprintf (f, "\tstr\t%s, [sp, #%d]\n", name, offset);
- asm_fprintf (f, "\tmov\t%s, pc\n", name);
- asm_fprintf (f, "\tstr\t%s, [sp, #%d]\n", name, offset + 12);
- }
-
- asm_fprintf (f, "\tmov\t%s, lr\n", name);
- asm_fprintf (f, "\tstr\t%s, [sp, #%d]\n", name, offset + 8);
- asm_fprintf (f, "\tadd\t%s, sp, #%d\n", name, offset + 12);
- asm_fprintf (f, "\tmov\tfp, %s\t\t@ Backtrace structure created\n", name);
- }
- else if (live_regs_mask)
- thumb_pushpop (f, live_regs_mask, 1);
-
- for (regno = 8; regno < 13; regno++)
- {
- if (regs_ever_live[regno] && ! call_used_regs[regno])
- high_regs_pushed++;
- }
-
- if (high_regs_pushed)
- {
- int pushable_regs = 0;
- int mask = live_regs_mask & 0xff;
- int next_hi_reg;
-
- for (next_hi_reg = 12; next_hi_reg > 7; next_hi_reg--)
- {
- if (regs_ever_live[next_hi_reg] && ! call_used_regs[next_hi_reg])
- break;
- }
-
- pushable_regs = mask;
-
- if (pushable_regs == 0)
- {
- /* desperation time -- this probably will never happen */
- if (regs_ever_live[3] || ! call_used_regs[3])
- asm_fprintf (f, "\tmov\t%s, %s\n", reg_names[12], reg_names[3]);
- mask = 1 << 3;
- }
-
- while (high_regs_pushed > 0)
- {
- for (regno = 7; regno >= 0; regno--)
- {
- if (mask & (1 << regno))
- {
- asm_fprintf (f, "\tmov\t%s, %s\n", reg_names[regno],
- reg_names[next_hi_reg]);
- high_regs_pushed--;
- if (high_regs_pushed)
- for (next_hi_reg--; next_hi_reg > 7; next_hi_reg--)
- {
- if (regs_ever_live[next_hi_reg]
- && ! call_used_regs[next_hi_reg])
- break;
- }
- else
- {
- mask &= ~ ((1 << regno) - 1);
- break;
- }
- }
- }
- thumb_pushpop (f, mask, 1);
- }
-
- if (pushable_regs == 0 && (regs_ever_live[3] || ! call_used_regs[3]))
- asm_fprintf (f, "\tmov\t%s, %s\n", reg_names[3], reg_names[12]);
- }
-}
-
-void
-thumb_expand_prologue ()
-{
- HOST_WIDE_INT amount = (get_frame_size ()
- + current_function_outgoing_args_size);
- int regno;
- int live_regs_mask;
-
- /* CYGNUS LOCAL nickc/thumb-pe */
-#ifdef THUMB_PE
- /* Naked functions don't have prologues. */
- if (arm_naked_function_p (current_function_decl))
- return;
-#endif
- /* END CYGNUS LOCAL nickc/thumb-pe */
-
- if (amount)
- {
- live_regs_mask = 0;
- for (regno = 0; regno < 8; regno++)
- if (regs_ever_live[regno] && ! call_used_regs[regno])
- live_regs_mask |= 1 << regno;
-
- if (amount < 512)
- emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
- GEN_INT (-amount)));
- else
- {
- rtx reg, spare;
-
- if ((live_regs_mask & 0xff) == 0) /* Very unlikely */
- emit_insn (gen_movsi (spare = gen_rtx (REG, SImode, 12),
- reg = gen_rtx (REG, SImode, 4)));
- else
- {
- for (regno = 0; regno < 8; regno++)
- if (live_regs_mask & (1 << regno))
- break;
- reg = gen_rtx (REG, SImode, regno);
- }
-
- emit_insn (gen_movsi (reg, GEN_INT (-amount)));
- emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, reg));
- if ((live_regs_mask & 0xff) == 0)
- emit_insn (gen_movsi (reg, spare));
- }
- }
-
- if (frame_pointer_needed)
- {
- if (current_function_outgoing_args_size)
- {
- rtx offset = GEN_INT (current_function_outgoing_args_size);
-
- if (current_function_outgoing_args_size < 1024)
- emit_insn (gen_addsi3 (frame_pointer_rtx, stack_pointer_rtx,
- offset));
- else
- {
- emit_insn (gen_movsi (frame_pointer_rtx, offset));
- emit_insn (gen_addsi3 (frame_pointer_rtx, frame_pointer_rtx,
- stack_pointer_rtx));
- }
- }
- else
- emit_insn (gen_movsi (frame_pointer_rtx, stack_pointer_rtx));
- }
-
- /* if (profile_flag || profile_block_flag) */
- emit_insn (gen_blockage ());
-}
-
-void
-thumb_expand_epilogue ()
-{
- HOST_WIDE_INT amount = (get_frame_size ()
- + current_function_outgoing_args_size);
- int regno;
-
- /* CYGNUS LOCAL nickc/thumb-pe */
-#ifdef THUMB_PE
- /* Naked functions don't have epilogues. */
- if (arm_naked_function_p (current_function_decl))
- return;
-#endif
- /* END CYGNUS LOCAL nickc/thumb-pe */
-
- if (amount)
- {
- if (amount < 512)
- emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
- GEN_INT (amount)));
- else
- {
- rtx reg = gen_rtx (REG, SImode, 3); /* Always free in the epilogue */
-
- emit_insn (gen_movsi (reg, GEN_INT (amount)));
- emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, reg));
- }
- /* if (profile_flag || profile_block_flag) */
- emit_insn (gen_blockage ());
- }
-}
-
-void
-thumb_function_epilogue (f, frame_size)
- FILE *f;
- int frame_size;
-{
- /* ??? Probably not safe to set this here, since it assumes that a
- function will be emitted as assembly immediately after we generate
- RTL for it. This does not happen for inline functions. */
- return_used_this_function = 0;
- current_function_has_far_jump = 0;
-#if 0 /* TODO : comment not really needed */
- fprintf (f, "%s THUMB Epilogue\n", ASM_COMMENT_START);
-#endif
-}
-
-/* The bits which aren't usefully expanded as rtl. */
-char *
-thumb_unexpanded_epilogue ()
-{
- int regno;
- int live_regs_mask = 0;
- int high_regs_pushed = 0;
- int leaf_function = leaf_function_p ();
- int had_to_push_lr;
-
- if (return_used_this_function)
- return "";
-
- for (regno = 0; regno < 8; regno++)
- if (regs_ever_live[regno] && ! call_used_regs[regno])
- live_regs_mask |= 1 << regno;
-
- for (regno = 8; regno < 13; regno++)
- {
- if (regs_ever_live[regno] && ! call_used_regs[regno])
- high_regs_pushed ++;
- }
-
- /* The prolog may have pushed some high registers to use as
- work registers. eg the testuite file:
- gcc/testsuite/gcc/gcc.c-torture/execute/complex-2.c
- compiles to produce:
- push {r4, r5, r6, r7, lr}
- mov r7, r9
- mov r6, r8
- push {r6, r7}
- as part of the prolog. We have to undo that pushing here. */
-
- if (high_regs_pushed)
- {
- int mask = live_regs_mask;
- int next_hi_reg;
- int size;
- int mode;
-
-#ifdef RTX_CODE
- /* If we can deduce the registers used from the function's return value.
- This is more reliable that examining regs_ever_live[] because that
- will be set if the register is ever used in the function, not just if
- the register is used to hold a return value. */
-
- if (current_function_return_rtx != 0)
- {
- mode = GET_MODE (current_function_return_rtx);
- }
- else
-#endif
- {
- mode = DECL_MODE (DECL_RESULT (current_function_decl));
- }
-
- size = GET_MODE_SIZE (mode);
-
- /* Unless we are returning a type of size > 12 register r3 is available. */
- if (size < 13)
- mask |= 1 << 3;
-
- if (mask == 0)
- {
- /* Oh dear! We have no low registers into which we can pop high registers! */
-
- fatal ("No low registers available for popping high registers");
- }
-
- for (next_hi_reg = 8; next_hi_reg < 13; next_hi_reg++)
- if (regs_ever_live[next_hi_reg] && ! call_used_regs[next_hi_reg])
- break;
-
- while (high_regs_pushed)
- {
- /* Find low register(s) into which the high register(s) can be popped. */
- for (regno = 0; regno < 8; regno++)
- {
- if (mask & (1 << regno))
- high_regs_pushed--;
- if (high_regs_pushed == 0)
- break;
- }
-
- mask &= (2 << regno) - 1; /* A noop if regno == 8 */
-
- /* Pop the values into the low register(s). */
- thumb_pushpop (asm_out_file, mask, 0);
-
- /* Move the value(s) into the high registers. */
- for (regno = 0; regno < 8; regno++)
- {
- if (mask & (1 << regno))
- {
- asm_fprintf (asm_out_file, "\tmov\t%s, %s\n",
- reg_names[next_hi_reg], reg_names[regno]);
- for (next_hi_reg++; next_hi_reg < 13; next_hi_reg++)
- if (regs_ever_live[next_hi_reg] &&
- ! call_used_regs[next_hi_reg])
- break;
- }
- }
- }
- }
-
- had_to_push_lr = (live_regs_mask || ! leaf_function || far_jump_used_p());
-
- if (TARGET_BACKTRACE && ((live_regs_mask & 0xFF) == 0) && regs_ever_live[ ARG_4_REGISTER ] != 0)
- {
- /* The stack backtrace structure creation code had to
- push R7 in order to get a work register, so we pop
- it now. */
-
- live_regs_mask |= (1 << WORK_REGISTER);
- }
-
- if (current_function_pretend_args_size == 0 || TARGET_BACKTRACE)
- {
- if (had_to_push_lr
- && ! is_called_in_ARM_mode (current_function_decl))
- live_regs_mask |= 1 << PROGRAM_COUNTER;
-
- /* Either no argument registers were pushed or a backtrace
- structure was created which includes an adjusted stack
- pointer, so just pop everything. */
-
- if (live_regs_mask)
- thumb_pushpop (asm_out_file, live_regs_mask, FALSE);
-
- /* We have either just popped the return address into the
- PC or it is was kept in LR for the entire function or
- it is still on the stack because we do not want to
- return by doing a pop {pc}. */
-
- if ((live_regs_mask & (1 << PROGRAM_COUNTER)) == 0)
- thumb_exit (asm_out_file,
- (had_to_push_lr
- && is_called_in_ARM_mode (current_function_decl)) ?
- -1 : LINK_REGISTER);
- }
- else
- {
- /* Pop everything but the return address. */
- live_regs_mask &= ~ (1 << PROGRAM_COUNTER);
-
- if (live_regs_mask)
- thumb_pushpop (asm_out_file, live_regs_mask, FALSE);
-
- if (had_to_push_lr)
- {
- /* Get the return address into a temporary register. */
- thumb_pushpop (asm_out_file, 1 << ARG_4_REGISTER, 0);
- }
-
- /* Remove the argument registers that were pushed onto the stack. */
- asm_fprintf (asm_out_file, "\tadd\t%s, %s, #%d\n",
- reg_names [STACK_POINTER],
- reg_names [STACK_POINTER],
- current_function_pretend_args_size);
-
- thumb_exit (asm_out_file, had_to_push_lr ? ARG_4_REGISTER : LINK_REGISTER);
- }
-
- return "";
-}
-
-/* Handle the case of a double word load into a low register from
- a computed memory address. The computed address may involve a
- register which is overwritten by the load. */
-
-char *
-thumb_load_double_from_address (operands)
- rtx * operands;
-{
- rtx addr;
- rtx base;
- rtx offset;
- rtx arg1;
- rtx arg2;
-
- if (GET_CODE (operands[0]) != REG)
- fatal ("thumb_load_double_from_address: destination is not a register");
-
- if (GET_CODE (operands[1]) != MEM)
- fatal ("thumb_load_double_from_address: source is not a computed memory address");
-
- /* Get the memory address. */
-
- addr = XEXP (operands[1], 0);
-
- /* Work out how the memory address is computed. */
-
- switch (GET_CODE (addr))
- {
- case REG:
- operands[2] = gen_rtx (MEM, SImode, plus_constant (XEXP (operands[1], 0), 4));
-
- if (REGNO (operands[0]) == REGNO (addr))
- {
- output_asm_insn ("ldr\t%H0, %2\t\t%@ created by thumb_load_double_from_address", operands);
- output_asm_insn ("ldr\t%0, %1\t\t%@ created by thumb_load_double_from_address", operands);
- }
- else
- {
- output_asm_insn ("ldr\t%0, %1\t\t%@ created by thumb_load_double_from_address", operands);
- output_asm_insn ("ldr\t%H0, %2\t\t%@ created by thumb_load_double_from_address", operands);
- }
- break;
-
- case CONST:
- /* Compute <address> + 4 for the high order load. */
-
- operands[2] = gen_rtx (MEM, SImode, plus_constant (XEXP (operands[1], 0), 4));
-
- output_asm_insn ("ldr\t%0, %1\t\t%@ created by thumb_load_double_from_address", operands);
- output_asm_insn ("ldr\t%H0, %2\t\t%@ created by thumb_load_double_from_address", operands);
- break;
-
- case PLUS:
- arg1 = XEXP (addr, 0);
- arg2 = XEXP (addr, 1);
-
- if (CONSTANT_P (arg1))
- base = arg2, offset = arg1;
- else
- base = arg1, offset = arg2;
-
- if (GET_CODE (base) != REG)
- fatal ("thumb_load_double_from_address: base is not a register");
-
- /* Catch the case of <address> = <reg> + <reg> */
-
- if (GET_CODE (offset) == REG)
- {
- int reg_offset = REGNO (offset);
- int reg_base = REGNO (base);
- int reg_dest = REGNO (operands[0]);
-
- /* Add the base and offset registers together into the higher destination register. */
-
- fprintf (asm_out_file, "\tadd\t%s, %s, %s\t\t%s created by thumb_load_double_from_address",
- reg_names[ reg_dest + 1 ],
- reg_names[ reg_base ],
- reg_names[ reg_offset ],
- ASM_COMMENT_START);
-
- /* Load the lower destination register from the address in the higher destination register. */
-
- fprintf (asm_out_file, "\tldr\t%s, [%s, #0]\t\t%s created by thumb_load_double_from_address",
- reg_names[ reg_dest ],
- reg_names[ reg_dest + 1],
- ASM_COMMENT_START);
-
- /* Load the higher destination register from its own address plus 4. */
-
- fprintf (asm_out_file, "\tldr\t%s, [%s, #4]\t\t%s created by thumb_load_double_from_address",
- reg_names[ reg_dest + 1 ],
- reg_names[ reg_dest + 1 ],
- ASM_COMMENT_START);
- }
- else
- {
- /* Compute <address> + 4 for the high order load. */
-
- operands[2] = gen_rtx (MEM, SImode, plus_constant (XEXP (operands[1], 0), 4));
-
- /* If the computed address is held in the low order register
- then load the high order register first, otherwise always
- load the low order register first. */
-
- if (REGNO (operands[0]) == REGNO (base))
- {
- output_asm_insn ("ldr\t%H0, %2\t\t%@ created by thumb_load_double_from_address", operands);
- output_asm_insn ("ldr\t%0, %1\t\t%@ created by thumb_load_double_from_address", operands);
- }
- else
- {
- output_asm_insn ("ldr\t%0, %1\t\t%@ created by thumb_load_double_from_address", operands);
- output_asm_insn ("ldr\t%H0, %2\t\t%@ created by thumb_load_double_from_address", operands);
- }
- }
- break;
-
- case LABEL_REF:
- /* With no registers to worry about we can just load the value directly. */
- operands[2] = gen_rtx (MEM, SImode, plus_constant (XEXP (operands[1], 0), 4));
-
- output_asm_insn ("ldr\t%H0, %2\t\t%@ created by thumb_load_double_from_address", operands);
- output_asm_insn ("ldr\t%0, %1\t\t%@ created by thumb_load_double_from_address", operands);
- break;
-
- default:
- debug_rtx (operands[1]);
- fatal ("thumb_load_double_from_address: Unhandled address calculation");
- break;
- }
-
- return "";
-}
-
-char *
-output_move_mem_multiple (n, operands)
- int n;
- rtx *operands;
-{
- rtx tmp;
-
- switch (n)
- {
- case 2:
- if (REGNO (operands[2]) > REGNO (operands[3]))
- {
- tmp = operands[2];
- operands[2] = operands[3];
- operands[3] = tmp;
- }
- output_asm_insn ("ldmia\t%1!, {%2, %3}", operands);
- output_asm_insn ("stmia\t%0!, {%2, %3}", operands);
- break;
-
- case 3:
- if (REGNO (operands[2]) > REGNO (operands[3]))
- {
- tmp = operands[2];
- operands[2] = operands[3];
- operands[3] = tmp;
- }
- if (REGNO (operands[3]) > REGNO (operands[4]))
- {
- tmp = operands[3];
- operands[3] = operands[4];
- operands[4] = tmp;
- }
- if (REGNO (operands[2]) > REGNO (operands[3]))
- {
- tmp = operands[2];
- operands[2] = operands[3];
- operands[3] = tmp;
- }
- output_asm_insn ("ldmia\t%1!, {%2, %3, %4}", operands);
- output_asm_insn ("stmia\t%0!, {%2, %3, %4}", operands);
- break;
-
- default:
- abort ();
- }
-
- return "";
-}
-
-
-int
-thumb_epilogue_size ()
-{
- return 42; /* The answer to .... */
-}
-
-static char *conds[] =
-{
- "eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc",
- "hi", "ls", "ge", "lt", "gt", "le"
-};
-
-static char *
-thumb_condition_code (x, invert)
- rtx x;
- int invert;
-{
- int val;
-
- switch (GET_CODE (x))
- {
- case EQ: val = 0; break;
- case NE: val = 1; break;
- case GEU: val = 2; break;
- case LTU: val = 3; break;
- case GTU: val = 8; break;
- case LEU: val = 9; break;
- case GE: val = 10; break;
- case LT: val = 11; break;
- case GT: val = 12; break;
- case LE: val = 13; break;
- default:
- abort ();
- }
-
- return conds[val ^ invert];
-}
-
-void
-thumb_print_operand (f, x, code)
- FILE *f;
- rtx x;
- int code;
-{
- if (code)
- {
- switch (code)
- {
- case '@':
- fputs (ASM_COMMENT_START, f);
- return;
-
- case '_':
- fputs (user_label_prefix, f);
- return;
-
- case 'D':
- if (x)
- fputs (thumb_condition_code (x, 1), f);
- return;
-
- case 'd':
- if (x)
- fputs (thumb_condition_code (x, 0), f);
- return;
-
- /* An explanation of the 'Q', 'R' and 'H' register operands:
-
- In a pair of registers containing a DI or DF value the 'Q'
- operand returns the register number of the register containing
- the least signficant part of the value. The 'R' operand returns
- the register number of the register containing the most
- significant part of the value.
-
- The 'H' operand returns the higher of the two register numbers.
- On a run where WORDS_BIG_ENDIAN is true the 'H' operand is the
- same as the 'Q' operand, since the most signficant part of the
- value is held in the lower number register. The reverse is true
- on systems where WORDS_BIG_ENDIAN is false.
-
- The purpose of these operands is to distinguish between cases
- where the endian-ness of the values is important (for example
- when they are added together), and cases where the endian-ness
- is irrelevant, but the order of register operations is important.
- For example when loading a value from memory into a register
- pair, the endian-ness does not matter. Provided that the value
- from the lower memory address is put into the lower numbered
- register, and the value from the higher address is put into the
- higher numbered register, the load will work regardless of whether
- the value being loaded is big-wordian or little-wordian. The
- order of the two register loads can matter however, if the address
- of the memory location is actually held in one of the registers
- being overwritten by the load. */
- case 'Q':
- if (REGNO (x) > 15)
- abort ();
- fputs (reg_names[REGNO (x) + (WORDS_BIG_ENDIAN ? 1 : 0)], f);
- return;
-
- case 'R':
- if (REGNO (x) > 15)
- abort ();
- fputs (reg_names[REGNO (x) + (WORDS_BIG_ENDIAN ? 0 : 1)], f);
- return;
-
- case 'H':
- if (REGNO (x) > 15)
- abort ();
- fputs (reg_names[REGNO (x) + 1], f);
- return;
-
- case 'c':
- /* We use 'c' operands with symbols for .vtinherit */
- if (GET_CODE (x) == SYMBOL_REF)
- output_addr_const(f, x);
- return;
-
- default:
- abort ();
- }
- }
- if (GET_CODE (x) == REG)
- fputs (reg_names[REGNO (x)], f);
- else if (GET_CODE (x) == MEM)
- output_address (XEXP (x, 0));
- else if (GET_CODE (x) == CONST_INT)
- {
- fputc ('#', f);
- output_addr_const (f, x);
- }
- else
- abort ();
-}
-
-#ifdef AOF_ASSEMBLER
-int arm_text_section_count = 1;
-
-char *
-aof_text_section (in_readonly)
- int in_readonly;
-{
- static char buf[100];
- if (in_readonly)
- return "";
- sprintf (buf, "\tCODE16\n\tAREA |C$$code%d|, CODE, READONLY",
- arm_text_section_count++);
- return buf;
-}
-
-static int arm_data_section_count = 1;
-
-char *
-aof_data_section ()
-{
- static char buf[100];
- sprintf (buf, "\tAREA |C$$data%d|, DATA", arm_data_section_count++);
- return buf;
-}
-
-/* The AOF thumb assembler is religiously strict about declarations of
- imported and exported symbols, so that it is impossible to declare a
- function as imported near the begining of the file, and then to export
- it later on. It is, however, possible to delay the decision until all
- the functions in the file have been compiled. To get around this, we
- maintain a list of the imports and exports, and delete from it any that
- are subsequently defined. At the end of compilation we spit the
- remainder of the list out before the END directive. */
-
-struct import
-{
- struct import *next;
- char *name;
-};
-
-static struct import *imports_list = NULL;
-
-void
-thumb_aof_add_import (name)
- char *name;
-{
- struct import *new;
-
- for (new = imports_list; new; new = new->next)
- if (new->name == name)
- return;
-
- new = (struct import *) xmalloc (sizeof (struct import));
- new->next = imports_list;
- imports_list = new;
- new->name = name;
-}
-
-void
-thumb_aof_delete_import (name)
- char *name;
-{
- struct import **old;
-
- for (old = &imports_list; *old; old = & (*old)->next)
- {
- if ((*old)->name == name)
- {
- *old = (*old)->next;
- return;
- }
- }
-}
-
-void
-thumb_aof_dump_imports (f)
- FILE *f;
-{
- while (imports_list)
- {
- fprintf (f, "\tIMPORT\t");
- assemble_name (f, imports_list->name);
- fputc ('\n', f);
- imports_list = imports_list->next;
- }
-}
-#endif
-
-/* Decide whether a type should be returned in memory (true)
- or in a register (false). This is called by the macro
- RETURN_IN_MEMORY. */
-
-int
-thumb_return_in_memory (type)
- tree type;
-{
- if (! AGGREGATE_TYPE_P (type))
- {
- /* All simple types are returned in registers. */
-
- return 0;
- }
- else if (int_size_in_bytes (type) > 4)
- {
- /* All structures/unions bigger than one word are returned in memory. */
-
- return 1;
- }
- else if (TREE_CODE (type) == RECORD_TYPE)
- {
- tree field;
-
- /* For a struct the APCS says that we must return in a register if
- every addressable element has an offset of zero. For practical
- purposes this means that the structure can have at most one non-
- bit-field element and that this element must be the first one in
- the structure. */
-
- /* Find the first field, ignoring non FIELD_DECL things which will
- have been created by C++. */
- for (field = TYPE_FIELDS (type);
- field && TREE_CODE (field) != FIELD_DECL;
- field = TREE_CHAIN (field))
- continue;
-
- if (field == NULL)
- return 0; /* An empty structure. Allowed by an extension to ANSI C. */
-
- /* Now check the remaining fields, if any. */
- for (field = TREE_CHAIN (field); field; field = TREE_CHAIN (field))
- {
- if (TREE_CODE (field) != FIELD_DECL)
- continue;
-
- if (! DECL_BIT_FIELD_TYPE (field))
- return 1;
- }
-
- return 0;
- }
- else if (TREE_CODE (type) == UNION_TYPE)
- {
- tree field;
-
- /* Unions can be returned in registers if every element is
- integral, or can be returned in an integer register. */
-
- for (field = TYPE_FIELDS (type);
- field;
- field = TREE_CHAIN (field))
- {
- if (TREE_CODE (field) != FIELD_DECL)
- continue;
-
- if (RETURN_IN_MEMORY (TREE_TYPE (field)))
- return 1;
- }
-
- return 0;
- }
- /* XXX Not sure what should be done for other aggregates, so put them in
- memory. */
- return 1;
-}
-
-void
-thumb_override_options ()
-{
- if (structure_size_string != NULL)
- {
- int size = strtol (structure_size_string, NULL, 0);
-
- if (size == 8 || size == 32)
- arm_structure_size_boundary = size;
- else
- warning ("Structure size boundary can only be set to 8 or 32");
- }
-
- if (flag_pic)
- {
- warning ("Position independent code not supported. Ignored");
- flag_pic = 0;
- }
-}
-
-/* CYGNUS LOCAL nickc/thumb-pe */
-
-#ifdef THUMB_PE
-/* Return nonzero if ATTR is a valid attribute for DECL.
- ATTRIBUTES are any existing attributes and ARGS are the arguments
- supplied with ATTR.
-
- Supported attributes:
-
- naked: don't output any prologue or epilogue code, the user is assumed
- to do the right thing.
-
- interfacearm: Always assume that this function will be entered in ARM
- mode, not Thumb mode, and that the caller wishes to be returned to in
- ARM mode. */
-int
-arm_valid_machine_decl_attribute (decl, attributes, attr, args)
- tree decl;
- tree attributes;
- tree attr;
- tree args;
-{
- if (args != NULL_TREE)
- return 0;
-
- if (is_attribute_p ("naked", attr))
- return TREE_CODE (decl) == FUNCTION_DECL;
-
- if (is_attribute_p ("interfacearm", attr))
- return TREE_CODE (decl) == FUNCTION_DECL;
-
- return 0;
-}
-#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;
-}
-
-/* s_register_operand is the same as register_operand, but it doesn't accept
- (SUBREG (MEM)...).
-
- This function exists because at the time it was put in it led to better
- code. SUBREG(MEM) always needs a reload in the places where
- s_register_operand is used, and this seemed to lead to excessive
- reloading. */
-
-int
-s_register_operand (op, mode)
- register rtx op;
- enum machine_mode mode;
-{
- if (GET_MODE (op) != mode && mode != VOIDmode)
- return 0;
-
- if (GET_CODE (op) == SUBREG)
- op = SUBREG_REG (op);
-
- /* We don't consider registers whose class is NO_REGS
- to be a register operand. */
- /* XXX might have to check for lo regs only for thumb ??? */
- return (GET_CODE (op) == REG
- && (REGNO (op) >= FIRST_PSEUDO_REGISTER
- || REGNO_REG_CLASS (REGNO (op)) != NO_REGS));
-}
diff --git a/gcc/config/arm/thumb_020422.h b/gcc/config/arm/thumb_020422.h
deleted file mode 100755
index 554ed1d..0000000
--- a/gcc/config/arm/thumb_020422.h
+++ /dev/null
@@ -1,1295 +0,0 @@
-/* Definitions of target machine for GNU compiler, for ARM/Thumb.
- Copyright (C) 1996, 1997, 1998, 1999, 2002 Free Software Foundation, Inc.
- The basis of this contribution was generated by
- Richard Earnshaw, Advanced RISC Machines Ltd
-
-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. */
-
-/* ??? The files thumb.{c,h,md} are all seriously lacking comments. */
-
-/* ??? The files thumb.{c,h,md} need to be reviewed by an experienced
- gcc hacker in their entirety. */
-
-/* ??? The files thumb.{c,h,md} and tcoff.h are all separate from the arm
- files, which will lead to many maintenance problems. These files are
- likely missing all bug fixes made to the arm port since they diverged. */
-
-/* ??? Many patterns in the md file accept operands that will require a
- reload. These should be eliminated if possible by tightening the
- predicates and/or constraints. This will give faster/smaller code. */
-
-/* ??? There is no pattern for the TST instuction. Check for other unsupported
- instructions. */
-
-/* Run Time Target Specifications */
-#ifndef CPP_PREDEFINES
-#define CPP_PREDEFINES "-Dthumb -D__thumb -Acpu(arm) -Amachine(arm)"
-#endif
-
-#ifndef CPP_SPEC
-#define CPP_SPEC "\
-%{mbig-endian:-D__ARMEB__ -D__THUMBEB__} \
-%{mbe:-D__ARMEB__ -D__THUMBEB__} \
-%{!mbe: %{!mbig-endian:-D__ARMEL__ -D__THUMBEL__}} \
-"
-#endif
-
-#ifndef ASM_SPEC
-#define ASM_SPEC "-marm7tdmi %{mthumb-interwork:-mthumb-interwork} %{mbig-endian:-EB}"
-#endif
-#define LINK_SPEC "%{mbig-endian:-EB} -X"
-
-#define TARGET_VERSION fputs (" (ARM/THUMB:generic)", stderr);
-
-/* Nonzero if we should compile with BYTES_BIG_ENDIAN set to 1. */
-#define THUMB_FLAG_BIG_END 0x0001
-#define THUMB_FLAG_BACKTRACE 0x0002
-#define THUMB_FLAG_LEAF_BACKTRACE 0x0004
-#define ARM_FLAG_THUMB 0x1000 /* same as in arm.h */
-#define THUMB_FLAG_CALLEE_SUPER_INTERWORKING 0x40000
-#define THUMB_FLAG_CALLER_SUPER_INTERWORKING 0x80000
-
-/* Nonzero if all call instructions should be indirect. */
-#define ARM_FLAG_LONG_CALLS (0x10000) /* same as in arm.h */
-
-
-/* Run-time compilation parameters selecting different hardware/software subsets. */
-extern int target_flags;
-#define TARGET_DEFAULT 0 /* ARM_FLAG_THUMB */
-#define TARGET_BIG_END (target_flags & THUMB_FLAG_BIG_END)
-#define TARGET_THUMB_INTERWORK (target_flags & ARM_FLAG_THUMB)
-#define TARGET_BACKTRACE (leaf_function_p() \
- ? (target_flags & THUMB_FLAG_LEAF_BACKTRACE) \
- : (target_flags & THUMB_FLAG_BACKTRACE))
-
-/* Set if externally visable functions should assume that they
- might be called in ARM mode, from a non-thumb aware code. */
-#define TARGET_CALLEE_INTERWORKING \
- (target_flags & THUMB_FLAG_CALLEE_SUPER_INTERWORKING)
-
-/* Set if calls via function pointers should assume that their
- destination is non-Thumb aware. */
-#define TARGET_CALLER_INTERWORKING \
- (target_flags & THUMB_FLAG_CALLER_SUPER_INTERWORKING)
-
-#define TARGET_LONG_CALLS (target_flags & ARM_FLAG_LONG_CALLS)
-
-/* SUBTARGET_SWITCHES is used to add flags on a per-config basis. */
-#ifndef SUBTARGET_SWITCHES
-#define SUBTARGET_SWITCHES
-#endif
-
-#define TARGET_SWITCHES \
-{ \
- {"big-endian", THUMB_FLAG_BIG_END}, \
- {"little-endian", -THUMB_FLAG_BIG_END}, \
- {"thumb-interwork", ARM_FLAG_THUMB}, \
- {"no-thumb-interwork", -ARM_FLAG_THUMB}, \
- {"tpcs-frame", THUMB_FLAG_BACKTRACE}, \
- {"no-tpcs-frame", -THUMB_FLAG_BACKTRACE}, \
- {"tpcs-leaf-frame", THUMB_FLAG_LEAF_BACKTRACE}, \
- {"no-tpcs-leaf-frame", -THUMB_FLAG_LEAF_BACKTRACE}, \
- {"callee-super-interworking", THUMB_FLAG_CALLEE_SUPER_INTERWORKING}, \
- {"no-callee-super-interworking", -THUMB_FLAG_CALLEE_SUPER_INTERWORKING}, \
- {"caller-super-interworking", THUMB_FLAG_CALLER_SUPER_INTERWORKING}, \
- {"no-caller-super-interworking", -THUMB_FLAG_CALLER_SUPER_INTERWORKING}, \
- {"long-calls", ARM_FLAG_LONG_CALLS, \
- "Generate all call instructions as indirect calls"}, \
- {"no-long-calls", -ARM_FLAG_LONG_CALLS, ""}, \
- SUBTARGET_SWITCHES \
- {"", TARGET_DEFAULT} \
-}
-
-#define TARGET_OPTIONS \
-{ \
- { "structure-size-boundary=", & structure_size_string }, \
-}
-
-#define REGISTER_PREFIX ""
-
-#define CAN_DEBUG_WITHOUT_FP 1
-
-#define ASM_APP_ON ""
-#define ASM_APP_OFF "\t.code\t16\n"
-
-/* Output a gap. In fact we fill it with nulls. */
-#define ASM_OUTPUT_SKIP(STREAM, NBYTES) \
- fprintf ((STREAM), "\t.space\t%u\n", (NBYTES))
-
-/* This is how to output an assembler line
- that says to advance the location counter
- to a multiple of 2**LOG bytes. */
-#define ASM_OUTPUT_ALIGN(STREAM,LOG) \
-{ \
- if ((LOG) > 0) \
- fprintf (STREAM, "\t.align\t%d\n", (LOG)); \
-}
-
-/* Output a common block */
-#define ASM_OUTPUT_COMMON(STREAM, NAME, SIZE, ROUNDED) \
- (fprintf ((STREAM), "\t.comm\t"), \
- assemble_name ((STREAM), (NAME)), \
- fprintf((STREAM), ", %d\t%s %d\n", (ROUNDED), (ASM_COMMENT_START), (SIZE)))
-
-#define ASM_GENERATE_INTERNAL_LABEL(STRING,PREFIX,NUM) \
- sprintf ((STRING), "*%s%s%d", (LOCAL_LABEL_PREFIX), (PREFIX), (NUM))
-
-/* This is how to output an internal numbered label where
- PREFIX is the class of label and NUM is the number within the class. */
-#define ASM_OUTPUT_INTERNAL_LABEL(STREAM,PREFIX,NUM) \
- fprintf ((STREAM), "%s%s%d:\n", (LOCAL_LABEL_PREFIX), (PREFIX), (NUM))
-
-/* This is how to output a label which precedes a jumptable. Since
- instructions are 2 bytes, we need explicit alignment here. */
-
-#define ASM_OUTPUT_CASE_LABEL(FILE,PREFIX,NUM,JUMPTABLE) \
- do { \
- ASM_OUTPUT_ALIGN (FILE, 2); \
- ASM_OUTPUT_INTERNAL_LABEL (FILE, PREFIX, NUM); \
- } while (0)
-
-/* This says how to define a local common symbol (ie, not visible to
- linker). */
-#define ASM_OUTPUT_LOCAL(STREAM, NAME, SIZE, ROUNDED) \
- (fprintf((STREAM),"\n\t.lcomm\t"), \
- assemble_name((STREAM),(NAME)), \
- fprintf((STREAM),",%u\n",(SIZE)))
-
-/* This is how to output an assembler line for a numeric constant byte. */
-#define ASM_OUTPUT_BYTE(STREAM,VALUE) \
- fprintf ((STREAM), "\t.byte\t0x%x\n", (VALUE))
-
-#define ASM_OUTPUT_INT(STREAM,VALUE) \
-{ \
- fprintf (STREAM, "\t.word\t"); \
- output_addr_const (STREAM, (VALUE)); \
- fprintf (STREAM, "\n"); \
-}
-
-#define ASM_OUTPUT_SHORT(STREAM,VALUE) \
-{ \
- fprintf (STREAM, "\t.short\t"); \
- output_addr_const (STREAM, (VALUE)); \
- fprintf (STREAM, "\n"); \
-}
-
-#define ASM_OUTPUT_CHAR(STREAM,VALUE) \
-{ \
- fprintf (STREAM, "\t.byte\t"); \
- output_addr_const (STREAM, (VALUE)); \
- fprintf (STREAM, "\n"); \
-}
-
-#define ASM_OUTPUT_LONG_DOUBLE(STREAM,VALUE) \
-do { char dstr[30]; \
- long l[3]; \
- REAL_VALUE_TO_TARGET_LONG_DOUBLE (VALUE, l); \
- REAL_VALUE_TO_DECIMAL (VALUE, "%.20g", dstr); \
- fprintf (STREAM, "\t.long 0x%lx,0x%lx,0x%lx\t%s long double %s\n", \
- l[0], l[1], l[2], ASM_COMMENT_START, dstr); \
- } while (0)
-
-#define ASM_OUTPUT_DOUBLE(STREAM, VALUE) \
-do { char dstr[30]; \
- long l[2]; \
- REAL_VALUE_TO_TARGET_DOUBLE (VALUE, l); \
- REAL_VALUE_TO_DECIMAL (VALUE, "%.14g", dstr); \
- fprintf (STREAM, "\t.long 0x%lx, 0x%lx\t%s double %s\n", l[0], \
- l[1], ASM_COMMENT_START, dstr); \
- } while (0)
-
-#define ASM_OUTPUT_FLOAT(STREAM, VALUE) \
-do { char dstr[30]; \
- long l; \
- REAL_VALUE_TO_TARGET_SINGLE (VALUE, l); \
- REAL_VALUE_TO_DECIMAL (VALUE, "%.7g", dstr); \
- fprintf (STREAM, "\t.word 0x%lx\t%s float %s\n", l, \
- ASM_COMMENT_START, dstr); \
- } while (0);
-
-/* Define results of standard character escape sequences. */
-#define TARGET_BELL 007
-#define TARGET_BS 010
-#define TARGET_TAB 011
-#define TARGET_NEWLINE 012
-#define TARGET_VT 013
-#define TARGET_FF 014
-#define TARGET_CR 015
-
-/* This is how to output a string. */
-#define ASM_OUTPUT_ASCII(STREAM, STRING, LEN) \
-do { \
- register int i, c, len = (LEN), cur_pos = 17; \
- register unsigned char *string = (unsigned char *)(STRING); \
- fprintf ((STREAM), "\t.ascii\t\""); \
- for (i = 0; i < len; i++) \
- { \
- register int c = string[i]; \
- \
- switch (c) \
- { \
- case '\"': \
- case '\\': \
- putc ('\\', (STREAM)); \
- putc (c, (STREAM)); \
- cur_pos += 2; \
- break; \
- \
- case TARGET_NEWLINE: \
- fputs ("\\n", (STREAM)); \
- if (i+1 < len \
- && (((c = string[i+1]) >= '\040' && c <= '~') \
- || c == TARGET_TAB)) \
- cur_pos = 32767; /* break right here */ \
- else \
- cur_pos += 2; \
- break; \
- \
- case TARGET_TAB: \
- fputs ("\\t", (STREAM)); \
- cur_pos += 2; \
- break; \
- \
- case TARGET_FF: \
- fputs ("\\f", (STREAM)); \
- cur_pos += 2; \
- break; \
- \
- case TARGET_BS: \
- fputs ("\\b", (STREAM)); \
- cur_pos += 2; \
- break; \
- \
- case TARGET_CR: \
- fputs ("\\r", (STREAM)); \
- cur_pos += 2; \
- break; \
- \
- default: \
- if (c >= ' ' && c < 0177) \
- { \
- putc (c, (STREAM)); \
- cur_pos++; \
- } \
- else \
- { \
- fprintf ((STREAM), "\\%03o", c); \
- cur_pos += 4; \
- } \
- } \
- \
- if (cur_pos > 72 && i+1 < len) \
- { \
- cur_pos = 17; \
- fprintf ((STREAM), "\"\n\t.ascii\t\""); \
- } \
- } \
- fprintf ((STREAM), "\"\n"); \
-} while (0)
-
-/* Output and Generation of Labels */
-#define ASM_OUTPUT_LABEL(STREAM,NAME) \
- (assemble_name ((STREAM), (NAME)), \
- fprintf ((STREAM), ":\n"))
-
-#define ASM_GLOBALIZE_LABEL(STREAM,NAME) \
- (fprintf ((STREAM), "\t.globl\t"), \
- assemble_name ((STREAM), (NAME)), \
- fputc ('\n', (STREAM)))
-
-/* Construct a private name. */
-#define ASM_FORMAT_PRIVATE_NAME(OUTVAR,NAME,NUMBER) \
- ((OUTVAR) = (char *) alloca (strlen (NAME) + 10), \
- sprintf ((OUTVAR), "%s.%d", (NAME), (NUMBER)))
-
-/* Switch to the text or data segment. */
-#define TEXT_SECTION_ASM_OP ".text"
-#define DATA_SECTION_ASM_OP ".data"
-#define BSS_SECTION_ASM_OP ".bss"
-
-/* The assembler's names for the registers. */
-#ifndef REGISTER_NAMES
-#define REGISTER_NAMES \
-{ \
- "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \
- "r8", "r9", "sl", "fp", "ip", "sp", "lr", "pc", "ap" \
-}
-#endif
-
-#ifndef ADDITIONAL_REGISTER_NAMES
-#define ADDITIONAL_REGISTER_NAMES \
-{ \
- {"a1", 0}, \
- {"a2", 1}, \
- {"a3", 2}, \
- {"a4", 3}, \
- {"v1", 4}, \
- {"v2", 5}, \
- {"v3", 6}, \
- {"v4", 7}, \
- {"v5", 8}, \
- {"v6", 9}, \
- {"sb", 9}, \
- {"v7", 10}, \
- {"r10", 10}, /* sl */ \
- {"r11", 11}, /* fp */ \
- {"r12", 12}, /* ip */ \
- {"r13", 13}, /* sp */ \
- {"r14", 14}, /* lr */ \
- {"r15", 15} /* pc */ \
-}
-#endif
-
-/* The assembler's parentheses characters. */
-#define ASM_OPEN_PAREN "("
-#define ASM_CLOSE_PAREN ")"
-
-#ifndef ASM_COMMENT_START
-#define ASM_COMMENT_START "@"
-#endif
-
-/* Output an element of a dispatch table. */
-#define ASM_OUTPUT_ADDR_VEC_ELT(STREAM,VALUE) \
- fprintf (STREAM, "\t.word\t%sL%d\n", (LOCAL_LABEL_PREFIX), (VALUE))
-
-#define ASM_OUTPUT_ADDR_DIFF_ELT(STREAM,BODY,VALUE,REL) \
- fprintf (STREAM, "\tb\t%sL%d\n", (LOCAL_LABEL_PREFIX), (VALUE))
-
-/* Storage Layout */
-
-/* Define this is most significant bit is lowest numbered in
- instructions that operate on numbered bit-fields. */
-#define BITS_BIG_ENDIAN 0
-
-/* Define this if most significant byte of a word is the lowest
- numbered. */
-#define BYTES_BIG_ENDIAN (TARGET_BIG_END != 0)
-
-#define WORDS_BIG_ENDIAN (BYTES_BIG_ENDIAN)
-
-/* LIBGCC2_WORDS_BIG_ENDIAN has to be a constant, so we define this based
- on processor pre-defineds when compiling libgcc2.c. */
-#if defined(__THUMBEB__) && !defined(__THUMBEL__)
-#define LIBGCC2_WORDS_BIG_ENDIAN 1
-#else
-#define LIBGCC2_WORDS_BIG_ENDIAN 0
-#endif
-
-#define FLOAT_WORDS_BIG_ENDIAN 1
-
-#define BITS_PER_UNIT 8
-#define BITS_PER_WORD 32
-
-#define UNITS_PER_WORD 4
-
-#define POINTER_SIZE 32
-
-#define PROMOTE_MODE(MODE,UNSIGNEDP,TYPE) \
-{ \
- if (GET_MODE_CLASS (MODE) == MODE_INT \
- && GET_MODE_SIZE (MODE) < 4) \
- { \
- (UNSIGNEDP) = 1; \
- (MODE) = SImode; \
- } \
-}
-
-#define PARM_BOUNDARY 32
-#define STACK_BOUNDARY 32
-
-#define FUNCTION_BOUNDARY 32
-#define BIGGEST_ALIGNMENT 32
-
-/* Make strings word-aligned so strcpy from constants will be faster. */
-#define CONSTANT_ALIGNMENT(EXP, ALIGN) \
- (TREE_CODE (EXP) == STRING_CST \
- && (ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN))
-
-#define EMPTY_FIELD_BOUNDARY 32
-
-#define STRUCTURE_SIZE_BOUNDARY 32
-
-/* Used when parsing command line option -mstructure_size_boundary. */
-extern char * structure_size_string;
-
-#define STRICT_ALIGNMENT 1
-
-#define TARGET_FLOAT_FORMAT IEEE_FLOAT_FORMAT
-
-
-/* Layout of Source Language Data Types */
-
-#define DEFAULT_SIGNED_CHAR 0
-
-#define TARGET_BELL 007
-#define TARGET_BS 010
-#define TARGET_TAB 011
-#define TARGET_NEWLINE 012
-#define TARGET_VT 013
-#define TARGET_FF 014
-#define TARGET_CR 015
-
-
-/* Register Usage */
-
-/* Note there are 16 hard registers on the Thumb. We invent a 17th register
- which is assigned to ARG_POINTER_REGNUM, but this is later removed by
- elimination passes in the compiler. */
-#define FIRST_PSEUDO_REGISTER 17
-
-/* ??? This is questionable. */
-#define FIXED_REGISTERS \
-{ \
- 0,0,0,0, \
- 0,0,0,0, \
- 0,0,0,1, \
- 0,1,1,1,1 \
-}
-
-/* ??? This is questionable. */
-#define CALL_USED_REGISTERS \
-{ \
- 1,1,1,1, \
- 0,0,0,0, \
- 0,0,0,1, \
- 1,1,1,1,1 \
-}
-
-#define HARD_REGNO_NREGS(REGNO,MODE) \
- ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) \
- / UNITS_PER_WORD)
-
-/* ??? Probably should only allow DImode/DFmode in even numbered registers. */
-#define HARD_REGNO_MODE_OK(REGNO,MODE) ((GET_MODE_SIZE (MODE) > UNITS_PER_WORD) ? (REGNO < 7) : 1)
-
-#define MODES_TIEABLE_P(MODE1,MODE2) 1
-
-/* The NOARG_LO_REGS class is the set of LO_REGS that are not used for passing
- arguments to functions. These are the registers that are available for
- spilling during reload. The code in reload1.c:init_reload() will detect this
- class and place it into 'reload_address_base_reg_class'. */
-
-enum reg_class
-{
- NO_REGS,
- NONARG_LO_REGS,
- LO_REGS,
- STACK_REG,
- BASE_REGS,
- HI_REGS,
- ALL_REGS,
- LIM_REG_CLASSES
-};
-
-#define GENERAL_REGS ALL_REGS
-
-#define N_REG_CLASSES (int) LIM_REG_CLASSES
-
-#define REG_CLASS_NAMES \
-{ \
- "NO_REGS", \
- "NONARG_LO_REGS", \
- "LO_REGS", \
- "STACK_REG", \
- "BASE_REGS", \
- "HI_REGS", \
- "ALL_REGS" \
-}
-
-#define REG_CLASS_CONTENTS \
-{ \
- 0x00000, \
- 0x000f0, \
- 0x000ff, \
- 0x02000, \
- 0x020ff, \
- 0x0ff00, \
- 0x1ffff, \
-}
-
-#define REGNO_REG_CLASS(REGNO) \
- ((REGNO) == STACK_POINTER_REGNUM ? STACK_REG \
- : (REGNO) < 8 ? ((REGNO) < 4 ? LO_REGS \
- : NONARG_LO_REGS) \
- : HI_REGS)
-
-#define BASE_REG_CLASS BASE_REGS
-
-#define MODE_BASE_REG_CLASS(MODE) \
- ((MODE) != QImode && (MODE) != HImode \
- ? BASE_REGS : LO_REGS)
-
-#define INDEX_REG_CLASS LO_REGS
-
-/* When SMALL_REGISTER_CLASSES is nonzero, the compiler allows
- registers explicitly used in the rtl to be used as spill registers
- but prevents the compiler from extending the lifetime of these
- registers. */
-
-#define SMALL_REGISTER_CLASSES 1
-
-#define REG_CLASS_FROM_LETTER(C) \
- ((C) == 'l' ? LO_REGS \
- : (C) == 'h' ? HI_REGS \
- : (C) == 'b' ? BASE_REGS \
- : (C) == 'k' ? STACK_REG \
- : NO_REGS)
-
-#define REGNO_OK_FOR_BASE_P(REGNO) \
- ((REGNO) < 8 \
- || (REGNO) == STACK_POINTER_REGNUM \
- || (unsigned) reg_renumber[REGNO] < 8 \
- || (unsigned) reg_renumber[REGNO] == STACK_POINTER_REGNUM)
-
-#define REGNO_MODE_OK_FOR_BASE_P(REGNO, MODE) \
- ((REGNO) < 8 \
- || (unsigned) reg_renumber[REGNO] < 8 \
- || (GET_MODE_SIZE (MODE) >= 4 \
- && ((REGNO) == STACK_POINTER_REGNUM \
- || (unsigned) reg_renumber[REGNO] == STACK_POINTER_REGNUM)))
-
-#define REGNO_OK_FOR_INDEX_P(REGNO) \
- ((REGNO) < 8 \
- || (unsigned) reg_renumber[REGNO] < 8)
-
-/* ??? This looks suspiciously wrong. */
-/* We need to leave BASE_REGS reloads alone, in order to avoid caller_save
- lossage. Caller_saves requests a BASE_REGS reload (caller_save_spill_class)
- and then later we verify that one was allocated. If PREFERRED_RELOAD_CLASS
- says to allocate a LO_REGS spill instead, then this mismatch gives an
- abort. Alternatively, this could be fixed by modifying BASE_REG_CLASS
- to be LO_REGS instead of BASE_REGS. It is not clear what affect this
- change would have. */
-/* ??? This looks even more suspiciously wrong. PREFERRED_RELOAD_CLASS
- must always return a strict subset of the input class. Just blindly
- returning LO_REGS is safe only if the input class is a superset of LO_REGS,
- but there is no check for this. Added another exception for NONARG_LO_REGS
- because it is not a superset of LO_REGS. */
-/* ??? We now use NONARG_LO_REGS for caller_save_spill_class, so the
- comments about BASE_REGS are now obsolete. */
-#define PREFERRED_RELOAD_CLASS(X,CLASS) \
- ((CLASS) == BASE_REGS || (CLASS) == NONARG_LO_REGS ? (CLASS) \
- : LO_REGS)
-/*
- ((CONSTANT_P ((X)) && GET_CODE ((X)) != CONST_INT \
- && ! CONSTANT_POOL_ADDRESS_P((X))) ? NO_REGS \
- : (GET_CODE ((X)) == CONST_INT \
- && (unsigned HOST_WIDE_INT) INTVAL ((X)) > 255) ? NO_REGS \
- : LO_REGS) */
-
-/* Must leave BASE_REGS and NONARG_LO_REGS reloads alone, see comment
- above. */
-#define SECONDARY_RELOAD_CLASS(CLASS,MODE,X) \
- ((CLASS) != LO_REGS && (CLASS) != BASE_REGS && (CLASS) != NONARG_LO_REGS \
- ? ((true_regnum (X) == -1 ? LO_REGS \
- : (true_regnum (X) + HARD_REGNO_NREGS (0, MODE) > 8) ? LO_REGS \
- : NO_REGS)) \
- : NO_REGS)
-
-#define CLASS_MAX_NREGS(CLASS,MODE) HARD_REGNO_NREGS(0,(MODE))
-
-int thumb_shiftable_const ();
-
-#define CONST_OK_FOR_LETTER_P(VAL,C) \
- ((C) == 'I' ? (unsigned HOST_WIDE_INT) (VAL) < 256 \
- : (C) == 'J' ? (VAL) > -256 && (VAL) <= 0 \
- : (C) == 'K' ? thumb_shiftable_const (VAL) \
- : (C) == 'L' ? (VAL) > -8 && (VAL) < 8 \
- : (C) == 'M' ? ((unsigned HOST_WIDE_INT) (VAL) < 1024 \
- && ((VAL) & 3) == 0) \
- : (C) == 'N' ? ((unsigned HOST_WIDE_INT) (VAL) < 32) \
- : (C) == 'O' ? ((VAL) >= -508 && (VAL) <= 508) \
- : 0)
-
-#define CONST_DOUBLE_OK_FOR_LETTER_P(VAL,C) 0
-
-#define EXTRA_CONSTRAINT(X,C) \
- ((C) == 'Q' ? (GET_CODE (X) == MEM \
- && GET_CODE (XEXP (X, 0)) == LABEL_REF) : 0)
-
-/* Stack Layout and Calling Conventions */
-
-#define STACK_GROWS_DOWNWARD 1
-
-/* #define FRAME_GROWS_DOWNWARD 1 */
-
-/* #define ARGS_GROW_DOWNWARD 1 */
-
-#define STARTING_FRAME_OFFSET 0
-
-#define FIRST_PARM_OFFSET(FNDECL) 0
-
-/* Registers that address the stack frame */
-
-#define STACK_POINTER_REGNUM 13 /* Defined by the TPCS. */
-
-#define FRAME_POINTER_REGNUM 7 /* TPCS defines this as 11 but it does not really mean it. */
-
-#define ARG_POINTER_REGNUM 16 /* A fake hard register that is eliminated later on. */
-
-#define STATIC_CHAIN_REGNUM 9
-
-#define FRAME_POINTER_REQUIRED 0
-
-#define ELIMINABLE_REGS \
-{{ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
- {ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM}, \
- {FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}}
-
-/* On the Thumb we always want to perform the eliminations as we
- actually only have one real register pointing to the stashed
- variables: the stack pointer, and we never use the frame pointer. */
-#define CAN_ELIMINATE(FROM,TO) 1
-
-/* Note: This macro must match the code in thumb_function_prologue() in thumb.c. */
-#define INITIAL_ELIMINATION_OFFSET(FROM,TO,OFFSET) \
-{ \
- (OFFSET) = 0; \
- if ((FROM) == ARG_POINTER_REGNUM) \
- { \
- int count_regs = 0; \
- int regno; \
- (OFFSET) += get_frame_size (); \
- for (regno = 8; regno < 13; regno++) \
- if (regs_ever_live[regno] && ! call_used_regs[regno]) \
- count_regs++; \
- if (count_regs) \
- (OFFSET) += 4 * count_regs; \
- count_regs = 0; \
- for (regno = 0; regno < 8; regno++) \
- if (regs_ever_live[regno] && ! call_used_regs[regno]) \
- count_regs++; \
- if (count_regs || ! leaf_function_p () || far_jump_used_p()) \
- (OFFSET) += 4 * (count_regs + 1); \
- if (TARGET_BACKTRACE) { \
- if ((count_regs & 0xFF) == 0 && (regs_ever_live[3] != 0)) \
- (OFFSET) += 20; \
- else \
- (OFFSET) += 16; } \
- } \
- if ((TO) == STACK_POINTER_REGNUM) \
- (OFFSET) += current_function_outgoing_args_size; \
-}
-
-/* Passing Arguments on the stack */
-
-#define PROMOTE_PROTOTYPES 1
-
-#define ACCUMULATE_OUTGOING_ARGS 1
-
-#define RETURN_POPS_ARGS(FUNDECL,FUNTYPE,SIZE) 0
-
-#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
- ((MODE) == VOIDmode \
- ? GEN_INT ((CUM).call_cookie) \
- : (NAMED) \
- ? ((CUM).nregs >= 16 ? 0 : gen_rtx (REG, MODE, (CUM).nregs / 4)) \
- : 0)
-
-#define FUNCTION_ARG_PARTIAL_NREGS(CUM,MODE,TYPE,NAMED) \
- (((CUM).nregs < 16 && (CUM).nregs + (((MODE) == BLKmode) \
- ? int_size_in_bytes (TYPE) \
- : (HARD_REGNO_NREGS (0, (MODE)) \
- * 4)) > 16) \
- ? 4 - (CUM).nregs / 4 : 0)
-
-/* A C type for declaring a variable that is used as the first argument of
- `FUNCTION_ARG' and other related values. For some target machines, the
- type `int' suffices and can hold the number of bytes of argument so far.
-
- On the ARM, this is the number of bytes of arguments scanned so far. */
-typedef struct
-{
- /* This is the number of registers of arguments scanned so far. */
- int nregs;
- /* One of CALL_NORMAL, CALL_LONG or CALL_SHORT . */
- int call_cookie;
-} CUMULATIVE_ARGS;
-
-
-/* Initialize a variable CUM of type CUMULATIVE_ARGS
- for a call to a function whose data type is FNTYPE.
- For a library call, FNTYPE is 0.
- On the ARM, the offset starts at 0. */
-#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT) \
- ((CUM).nregs = (((FNTYPE) && aggregate_value_p (TREE_TYPE ((FNTYPE)))) \
- ? 4 : 0), \
- (CUM).call_cookie = \
- (((FNTYPE) && lookup_attribute ("short_call", TYPE_ATTRIBUTES (FNTYPE))) \
- ? CALL_SHORT \
- : (((FNTYPE) && lookup_attribute ("long_call", \
- TYPE_ATTRIBUTES (FNTYPE)))\
- || TARGET_LONG_CALLS) \
- ? CALL_LONG \
- : CALL_NORMAL))
-
-/* Update the data in CUM to advance over an argument
- of mode MODE and data type TYPE.
- (TYPE is null for libcalls where that information may not be available.) */
-#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \
- (CUM).nregs += ((MODE) != BLKmode \
- ? (GET_MODE_SIZE (MODE) + 3) & ~3 \
- : (int_size_in_bytes (TYPE) + 3) & ~3) \
-
-#define FUNCTION_ARG_REGNO_P(REGNO) \
- ((REGNO) >=0 && (REGNO) <= 3)
-
-#define FUNCTION_VALUE(VALTYPE,FUNC) gen_rtx (REG, TYPE_MODE (VALTYPE), 0)
-
-#define LIBCALL_VALUE(MODE) gen_rtx (REG, (MODE), 0)
-
-#define FUNCTION_VALUE_REGNO_P(REGNO) ((REGNO) == 0)
-
- /* How large values are returned */
-/* A C expression which can inhibit the returning of certain function values
- in registers, based on the type of value. */
-#define RETURN_IN_MEMORY(TYPE) thumb_return_in_memory (TYPE)
-
-/* Define DEFAULT_PCC_STRUCT_RETURN to 1 if all structure and union return
- values must be in memory. On the ARM, they need only do so if larger
- than a word, or if they contain elements offset from zero in the struct. */
-#define DEFAULT_PCC_STRUCT_RETURN 0
-
-
-#define STRUCT_VALUE_REGNUM 0
-
-#define FUNCTION_PROLOGUE(FILE,SIZE) thumb_function_prologue((FILE),(SIZE))
-
-#define FUNCTION_EPILOGUE(FILE,SIZE) thumb_function_epilogue((FILE),(SIZE))
-
-/* Implementing the Varargs Macros */
-
-#define SETUP_INCOMING_VARARGS(CUM,MODE,TYPE,PRETEND_SIZE,NO_RTL) \
-{ \
- extern int current_function_anonymous_args; \
- current_function_anonymous_args = 1; \
- if ((CUM).nregs < 16) \
- (PRETEND_SIZE) = 16 - (CUM).nregs; \
-}
-
-/* Trampolines for nested functions */
-
-/* Output assembler code for a block containing the constant parts of
- a trampoline, leaving space for the variable parts.
-
- On the Thumb we always switch into ARM mode to execute the trampoline.
- Why - because it is easier. This code will always be branched to via
- a BX instruction and since the compiler magically generates the address
- of the function the linker has no opportunity to ensure that the
- bottom bit is set. Thus the processor will be in ARM mode when it
- reaches this code. So we duplicate the ARM trampoline code and add
- a switch into Thumb mode as well.
-
- On the ARM, (if r8 is the static chain regnum, and remembering that
- referencing pc adds an offset of 8) the trampoline looks like:
- ldr r8, [pc, #0]
- ldr pc, [pc]
- .word static chain value
- .word function's address
- ??? FIXME: When the trampoline returns, r8 will be clobbered. */
-#define TRAMPOLINE_TEMPLATE(FILE) \
-{ \
- fprintf ((FILE), "\t.code 32\n"); \
- fprintf ((FILE), ".Ltrampoline_start:\n"); \
- fprintf ((FILE), "\tldr\t%s, [%spc, #8]\n", \
- reg_names[STATIC_CHAIN_REGNUM], REGISTER_PREFIX); \
- fprintf ((FILE), "\tldr\t%sip, [%spc, #8]\n", \
- REGISTER_PREFIX, REGISTER_PREFIX); \
- fprintf ((FILE), "\torr\t%sip, %sip, #1\n", \
- REGISTER_PREFIX, REGISTER_PREFIX); \
- fprintf ((FILE), "\tbx\t%sip\n", REGISTER_PREFIX); \
- fprintf ((FILE), "\t.word\t0\n"); \
- fprintf ((FILE), "\t.word\t0\n"); \
- fprintf ((FILE), "\t.code 16\n"); \
-}
-
-/* Length in units of the trampoline for entering a nested function. */
-#define TRAMPOLINE_SIZE 24
-
-/* Alignment required for a trampoline in units. */
-#define TRAMPOLINE_ALIGN 4
-
-#define INITIALIZE_TRAMPOLINE(ADDR,FNADDR,CHAIN) \
-{ \
- emit_move_insn (gen_rtx (MEM, SImode, plus_constant ((ADDR), 16)), \
- (CHAIN)); \
- emit_move_insn (gen_rtx (MEM, SImode, plus_constant ((ADDR), 20)), \
- (FNADDR)); \
-}
-
-
-/* Implicit Calls to Library Routines */
-
-#define TARGET_MEM_FUNCTIONS 1
-
-#define OVERRIDE_OPTIONS thumb_override_options ()
-
-
-/* Addressing Modes */
-
-#define HAVE_POST_INCREMENT 1
-
-#define CONSTANT_ADDRESS_P(X) \
- (GET_CODE (X) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (X))
-
-#define MAX_REGS_PER_ADDRESS 2
-
-#ifdef REG_OK_STRICT
-
-#define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P (REGNO (X))
-#define REG_OK_FOR_INDEX_P(X) REGNO_OK_FOR_INDEX_P (REGNO (X))
-
-#define REG_MODE_OK_FOR_BASE_P(X,MODE) \
- REGNO_MODE_OK_FOR_BASE_P (REGNO (X), MODE)
-
-#else /* REG_OK_STRICT */
-
-#define REG_OK_FOR_BASE_P(X) \
- (REGNO (X) < 8 || REGNO (X) == STACK_POINTER_REGNUM \
- || (X) == arg_pointer_rtx \
- || REGNO (X) >= FIRST_PSEUDO_REGISTER)
-
-#define REG_MODE_OK_FOR_BASE_P(X,MODE) \
- (REGNO (X) < 8 \
- || REGNO (X) >= FIRST_PSEUDO_REGISTER \
- || (GET_MODE_SIZE (MODE) >= 4 \
- && (REGNO (X) == STACK_POINTER_REGNUM \
- || (X) == arg_pointer_rtx)))
-
-#define REG_OK_FOR_INDEX_P(X) \
- (REGNO (X) < 8 \
- || REGNO (X) >= FIRST_PSEUDO_REGISTER)
-
-#endif /* REG_OK_STRICT */
-
-/* In a REG+REG address, both must be INDEX registers. */
-#define REG_OK_FOR_INDEXED_BASE_P(X) REG_OK_FOR_INDEX_P(X)
-
-#define LEGITIMATE_OFFSET(MODE,VAL) \
-(GET_MODE_SIZE (MODE) == 1 ? ((unsigned HOST_WIDE_INT) (VAL) < 32) \
- : GET_MODE_SIZE (MODE) == 2 ? ((unsigned HOST_WIDE_INT) (VAL) < 64 \
- && ((VAL) & 1) == 0) \
- : ((VAL) >= 0 && ((VAL) + GET_MODE_SIZE (MODE)) <= 128 \
- && ((VAL) & 3) == 0))
-
-/* The AP may be eliminated to either the SP or the FP, so we use the
- least common denominator, e.g. SImode, and offsets from 0 to 64. */
-
-/* ??? Verify whether the above is the right approach. */
-
-/* ??? Also, the FP may be eliminated to the SP, so perhaps that
- needs special handling also. */
-
-/* ??? Look at how the mips16 port solves this problem. It probably uses
- better ways to solve some of these problems. */
-
-/* Although it is not incorrect, we don't accept QImode and HImode
- addresses based on the frame pointer or arg pointer until the reload pass starts.
- This is so that eliminating such addresses into stack based ones
- won't produce impossible code. */
-#define GO_IF_LEGITIMATE_ADDRESS(MODE,X,WIN) \
-{ \
- /* ??? Not clear if this is right. Experiment. */ \
- if (GET_MODE_SIZE (MODE) < 4 \
- && ! (reload_in_progress || reload_completed) \
- && (reg_mentioned_p (frame_pointer_rtx, X) \
- || reg_mentioned_p (arg_pointer_rtx, X) \
- || reg_mentioned_p (virtual_incoming_args_rtx, X) \
- || reg_mentioned_p (virtual_outgoing_args_rtx, X) \
- || reg_mentioned_p (virtual_stack_dynamic_rtx, X) \
- || reg_mentioned_p (virtual_stack_vars_rtx, X))) \
- ; \
- /* Accept any base register. SP only in SImode or larger. */ \
- else if (GET_CODE (X) == REG && REG_MODE_OK_FOR_BASE_P(X, MODE)) \
- goto WIN; \
- /* This is PC relative data before MACHINE_DEPENDENT_REORG runs. */ \
- else if (GET_MODE_SIZE (MODE) >= 4 && CONSTANT_P (X) \
- && CONSTANT_POOL_ADDRESS_P (X)) \
- goto WIN; \
- /* This is PC relative data after MACHINE_DEPENDENT_REORG runs. */ \
- else if (GET_MODE_SIZE (MODE) >= 4 && reload_completed \
- && (GET_CODE (X) == LABEL_REF \
- || (GET_CODE (X) == CONST \
- && GET_CODE (XEXP (X, 0)) == PLUS \
- && GET_CODE (XEXP (XEXP (X, 0), 0)) == LABEL_REF \
- && GET_CODE (XEXP (XEXP (X, 0), 1)) == CONST_INT))) \
- goto WIN; \
- /* Post-inc indexing only supported for SImode and larger. */ \
- else if (GET_CODE (X) == POST_INC && GET_MODE_SIZE (MODE) >= 4 \
- && GET_CODE (XEXP (X, 0)) == REG \
- && REG_OK_FOR_INDEX_P (XEXP (X, 0))) \
- goto WIN; \
- else if (GET_CODE (X) == PLUS) \
- { \
- /* REG+REG address can be any two index registers. */ \
- /* ??? REG+REG addresses have been completely disabled before \
- reload completes, because we do not have enough available \
- reload registers. We only have 3 guaranteed reload registers \
- (NONARG_LO_REGS - the frame pointer), but we need at least 4 \
- to support REG+REG addresses. We have left them enabled after \
- reload completes, in the hope that reload_cse_regs and related \
- routines will be able to create them after the fact. It is \
- probably possible to support REG+REG addresses with additional \
- reload work, but I do not not have enough time to attempt such \
- a change at this time. */ \
- /* ??? Normally checking the mode here is wrong, since it isn't \
- impossible to use REG+REG with DFmode. However, the movdf \
- pattern requires offsettable addresses, and REG+REG is not \
- offsettable, so it must be rejected somehow. Trying to use \
- 'o' fails, because offsettable_address_p does a QImode check. \
- QImode is not valid for stack addresses, and has a smaller \
- range for non-stack bases, and this causes valid addresses \
- to be rejected. So we just eliminate REG+REG here by checking \
- the mode. */ \
- /* We also disallow FRAME+REG addressing since we know that FRAME \
- will be replaced with STACK, and SP relative addressing only \
- permits SP+OFFSET. */ \
- if (GET_MODE_SIZE (MODE) <= 4 \
- /* ??? See comment above. */ \
- && reload_completed \
- && GET_CODE (XEXP (X, 0)) == REG \
- && GET_CODE (XEXP (X, 1)) == REG \
- && XEXP (X, 0) != frame_pointer_rtx \
- && XEXP (X, 1) != frame_pointer_rtx \
- && XEXP (X, 0) != virtual_stack_vars_rtx \
- && XEXP (X, 1) != virtual_stack_vars_rtx \
- && REG_OK_FOR_INDEX_P (XEXP (X, 0)) \
- && REG_OK_FOR_INDEX_P (XEXP (X, 1))) \
- goto WIN; \
- /* REG+const has 5-7 bit offset for non-SP registers. */ \
- else if (GET_CODE (XEXP (X, 0)) == REG \
- && (REG_OK_FOR_INDEX_P (XEXP (X, 0)) \
- || XEXP (X, 0) == arg_pointer_rtx) \
- && GET_CODE (XEXP (X, 1)) == CONST_INT \
- && LEGITIMATE_OFFSET (MODE, INTVAL (XEXP (X, 1)))) \
- goto WIN; \
- /* REG+const has 10 bit offset for SP, but only SImode and \
- larger is supported. */ \
- /* ??? Should probably check for DI/DFmode overflow here \
- just like GO_IF_LEGITIMATE_OFFSET does. */ \
- else if (GET_CODE (XEXP (X, 0)) == REG \
- && REGNO (XEXP (X, 0)) == STACK_POINTER_REGNUM \
- && GET_MODE_SIZE (MODE) >= 4 \
- && GET_CODE (XEXP (X, 1)) == CONST_INT \
- && (unsigned HOST_WIDE_INT) INTVAL (XEXP (X, 1)) < 1024 \
- && (INTVAL (XEXP (X, 1)) & 3) == 0) \
- goto WIN; \
- } \
-}
-
-/* ??? If an HImode FP+large_offset address is converted to an HImode
- SP+large_offset address, then reload won't know how to fix it. It sees
- only that SP isn't valid for HImode, and so reloads the SP into an index
- register, but the resulting address is still invalid because the offset
- is too big. We fix it here instead by reloading the entire address. */
-/* We could probably achieve better results by defining PROMOTE_MODE to help
- cope with the variances between the Thumb's signed and unsigned byte and
- halfword load instructions. */
-#define LEGITIMIZE_RELOAD_ADDRESS(X,MODE,OPNUM,TYPE,IND_LEVELS,WIN) \
-{ \
- if (GET_CODE (X) == PLUS \
- && GET_MODE_SIZE (MODE) < 4 \
- && GET_CODE (XEXP (X, 0)) == REG \
- && XEXP (X, 0) == stack_pointer_rtx \
- && GET_CODE (XEXP (X, 1)) == CONST_INT \
- && ! LEGITIMATE_OFFSET (MODE, INTVAL (XEXP (X, 1)))) \
- { \
- rtx orig_X = X; \
- X = copy_rtx (X); \
- push_reload (orig_X, NULL_RTX, &X, NULL_PTR, \
- BASE_REG_CLASS, \
- Pmode, VOIDmode, 0, 0, OPNUM, TYPE); \
- goto WIN; \
- } \
-}
-
-#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR,LABEL)
-
-#define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN)
-
-#define LEGITIMATE_CONSTANT_P(X) \
- (GET_CODE (X) == CONST_INT \
- || GET_CODE (X) == CONST_DOUBLE \
- || CONSTANT_ADDRESS_P (X))
-
-/* Flags for the call/call_value rtl operations set up by function_arg. */
-#define CALL_NORMAL 0x00000000 /* No special processing. */
-#define CALL_LONG 0x00000001 /* Always call indirect. */
-#define CALL_SHORT 0x00000002 /* Never call indirect. */
-
-#define ENCODE_SECTION_INFO(decl) \
-{ \
- ARM_ENCODE_CALL_TYPE (decl) \
-}
-
-/* A C expression whose value is nonzero if IDENTIFIER with arguments ARGS
- is a valid machine specific attribute for DECL.
- The attributes in ATTRIBUTES have previously been assigned to DECL. */
-int arm_valid_machine_type_attribute (/* union tree_node *, union tree_node *,
- union tree_node *,
- union tree_node * */);
-#define VALID_MACHINE_TYPE_ATTRIBUTE(DECL, ATTRIBUTES, IDENTIFIER, ARGS) \
-arm_valid_machine_type_attribute (DECL, ATTRIBUTES, IDENTIFIER, ARGS)
-
-/* If we are referencing a function that is weak then encode a long call
- flag in the function name, otherwise if the function is static or
- or known to be defined in this file then encode a short call flag.
- This macro is used inside the ENCODE_SECTION macro. */
-#define ARM_ENCODE_CALL_TYPE(decl) \
- if (TREE_CODE_CLASS (TREE_CODE (decl)) == 'd') \
- { \
- if (TREE_CODE (decl) == FUNCTION_DECL && DECL_WEAK (decl)) \
- arm_encode_call_attribute (decl, LONG_CALL_FLAG_CHAR); \
- else if (! TREE_PUBLIC (decl)) \
- arm_encode_call_attribute (decl, SHORT_CALL_FLAG_CHAR); \
- }
-
-/* Special characters prefixed to function names
- in order to encode attribute like information.
- Note, '@' and '*' have already been taken. */
-#define SHORT_CALL_FLAG_CHAR '^'
-#define LONG_CALL_FLAG_CHAR '#'
-
-#define ENCODED_SHORT_CALL_ATTR_P(SYMBOL_NAME) \
- (*(SYMBOL_NAME) == SHORT_CALL_FLAG_CHAR)
-
-#define ENCODED_LONG_CALL_ATTR_P(SYMBOL_NAME) \
- (*(SYMBOL_NAME) == LONG_CALL_FLAG_CHAR)
-
-#ifndef SUBTARGET_NAME_ENCODING_LENGTHS
-#define SUBTARGET_NAME_ENCODING_LENGTHS
-#endif
-
-/* This is a C fragement for the inside of a switch statement.
- Each case label should return the number of characters to
- be stripped from the start of a function's name, if that
- name starts with the indicated character. */
-#define ARM_NAME_ENCODING_LENGTHS \
- case SHORT_CALL_FLAG_CHAR: return 1; \
- case LONG_CALL_FLAG_CHAR: return 1; \
- case '*': return 1; \
- SUBTARGET_NAME_ENCODING_LENGTHS
-
-/* This has to be handled by a function because more than part of the
- ARM backend uses function name prefixes to encode attributes. */
-#undef STRIP_NAME_ENCODING
-#define STRIP_NAME_ENCODING(VAR, SYMBOL_NAME) \
- (VAR) = arm_strip_name_encoding (SYMBOL_NAME)
-
-/* This is how to output a reference to a user-level label named NAME.
- `assemble_name' uses this. */
-#undef ASM_OUTPUT_LABELREF
-#define ASM_OUTPUT_LABELREF(FILE, NAME) \
- asm_fprintf (FILE, "%U%s", arm_strip_name_encoding (NAME))
-
-
-/* Condition Code Status */
-
-#define NOTICE_UPDATE_CC(EXP,INSN) \
-{ \
- if (get_attr_conds ((INSN)) != CONDS_UNCHANGED) \
- CC_STATUS_INIT; \
-}
-
-
-/* Describing Relative Costs of Operations */
-
-#define SLOW_BYTE_ACCESS 0
-
-#define SLOW_UNALIGNED_ACCESS 1
-
-#define NO_FUNCTION_CSE 1
-
-#define NO_RECURSIVE_FUNCTION_CSE 1
-
-#define REGISTER_MOVE_COST(FROM,TO) \
- (((FROM) == HI_REGS || (TO) == HI_REGS) ? 4 : 2)
-
-#define MEMORY_MOVE_COST(M,CLASS,IN) \
- ((GET_MODE_SIZE(M) < 4 ? 8 : 2 * GET_MODE_SIZE(M)) * (CLASS == LO_REGS ? 1 : 2))
-
-/* This will allow better space optimization when compiling with -O */
-#define BRANCH_COST (optimize > 1 ? 1 : 0)
-
-#define RTX_COSTS(X,CODE,OUTER) \
- case MULT: \
- if (GET_CODE (XEXP (X, 1)) == CONST_INT) \
- { \
- int cycles = 0; \
- unsigned HOST_WIDE_INT i = INTVAL (XEXP (X, 1)); \
- while (i) \
- { \
- i >>= 2; \
- cycles++; \
- } \
- return COSTS_N_INSNS (2) + cycles; \
- } \
- return COSTS_N_INSNS (1) + 16; \
- case ASHIFT: case ASHIFTRT: case LSHIFTRT: case ROTATERT: \
- case PLUS: case MINUS: case COMPARE: case NEG: case NOT: \
- return COSTS_N_INSNS (1); \
- case SET: \
- return (COSTS_N_INSNS (1) \
- + 4 * ((GET_CODE (SET_SRC (X)) == MEM) \
- + GET_CODE (SET_DEST (X)) == MEM))
-
-#define CONST_COSTS(X,CODE,OUTER) \
- case CONST_INT: \
- if ((OUTER) == SET) \
- { \
- if ((unsigned HOST_WIDE_INT) INTVAL (X) < 256) \
- return 0; \
- if (thumb_shiftable_const (INTVAL (X))) \
- return COSTS_N_INSNS (2); \
- return COSTS_N_INSNS (3); \
- } \
- else if (OUTER == PLUS \
- && INTVAL (X) < 256 && INTVAL (X) > -256) \
- return 0; \
- else if (OUTER == COMPARE \
- && (unsigned HOST_WIDE_INT) INTVAL (X) < 256) \
- return 0; \
- else if (OUTER == ASHIFT || OUTER == ASHIFTRT \
- || OUTER == LSHIFTRT) \
- return 0; \
- return COSTS_N_INSNS (2); \
- case CONST: \
- case CONST_DOUBLE: \
- case LABEL_REF: \
- case SYMBOL_REF: \
- return COSTS_N_INSNS(3);
-
-#define ADDRESS_COST(X) \
- ((GET_CODE (X) == REG \
- || (GET_CODE (X) == PLUS && GET_CODE (XEXP (X, 0)) == REG \
- && GET_CODE (XEXP (X, 1)) == CONST_INT)) \
- ? 1 : 2)
-
-
-/* Position Independent Code */
-
-#define PRINT_OPERAND(STREAM,X,CODE) \
- thumb_print_operand((STREAM), (X), (CODE))
-
-#define PRINT_OPERAND_ADDRESS(STREAM,X) \
-{ \
- if (GET_CODE ((X)) == REG) \
- fprintf ((STREAM), "[%s]", reg_names[REGNO ((X))]); \
- else if (GET_CODE ((X)) == POST_INC) \
- fprintf ((STREAM), "%s!", reg_names[REGNO (XEXP (X, 0))]); \
- else if (GET_CODE ((X)) == PLUS) \
- { \
- if (GET_CODE (XEXP ((X), 1)) == CONST_INT) \
- fprintf ((STREAM), "[%s, #%d]", \
- reg_names[REGNO (XEXP ((X), 0))], \
- (int) INTVAL (XEXP ((X), 1))); \
- else \
- fprintf ((STREAM), "[%s, %s]", \
- reg_names[REGNO (XEXP ((X), 0))], \
- reg_names[REGNO (XEXP ((X), 1))]); \
- } \
- else \
- output_addr_const ((STREAM), (X)); \
-}
-
-#define PRINT_OPERAND_PUNCT_VALID_P(CODE) ((CODE) == '@' || ((CODE) == '_'))
-
-/* Emit a special directive when defining a function name.
- This is used by the assembler to assit with interworking. */
-#define ASM_DECLARE_FUNCTION_NAME(file, name, 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)
-
-#define ASM_OUTPUT_REG_PUSH(STREAM,REGNO) \
- asm_fprintf ((STREAM), "\tpush {%R%s}\n", reg_names[(REGNO)])
-
-#define ASM_OUTPUT_REG_POP(STREAM,REGNO) \
- fprintf ((STREAM), "\tpop {%R%s}\n", reg_names[(REGNO)])
-
-#define FINAL_PRESCAN_INSN(INSN,OPVEC,NOPERANDS) \
- final_prescan_insn((INSN))
-
-/* Controlling Debugging Information Format */
-#define DBX_REGISTER_NUMBER(REGNO) (REGNO)
-
-/* Specific options for DBX Output */
-
-#define DBX_DEBUGGING_INFO 1
-
-#define DEFAULT_GDB_EXTENSIONS 1
-
-
-/* Cross Compilation and Floating Point */
-
-#define REAL_ARITHMETIC
-
-
-/* Miscellaneous Parameters */
-
-#define PREDICATE_CODES \
- {"thumb_cmp_operand", {SUBREG, REG, CONST_INT}},
-
-#define CASE_VECTOR_MODE Pmode
-
-#define WORD_REGISTER_OPERATIONS
-
-#define LOAD_EXTEND_OP(MODE) ZERO_EXTEND
-
-#define IMPLICIT_FIX_EXPR FIX_ROUND_EXPR
-
-#define EASY_DIV_EXPR TRUNC_DIV_EXPR
-
-#define MOVE_MAX 4
-
-#define TRULY_NOOP_TRUNCATION(OUTPREC,INPREC) 1
-
-#define STORE_FLAG_VALUE 1
-
-#define Pmode SImode
-
-#define FUNCTION_MODE SImode
-
-#define DOLLARS_IN_IDENTIFIERS 0
-
-#define NO_DOLLAR_IN_LABEL 1
-
-#define HAVE_ATEXIT
-
-/* The literal pool needs to reside in the text area due to the
- limited PC addressing range: */
-#define MACHINE_DEPENDENT_REORG(INSN) thumb_reorg ((INSN))
-
-
-/* Options specific to Thumb */
-
-/* True if a return instruction can be used in this function. */
-int thumb_trivial_epilogue ();
-#define USE_RETURN (reload_completed && thumb_trivial_epilogue ())
-
-extern char * thumb_unexpanded_epilogue ();
-extern char * output_move_mem_multiple ();
-extern char * thumb_load_double_from_address ();
-extern char * output_return ();
-extern int far_jump_used_p();
-extern int is_called_in_ARM_mode ();
-
-char *arm_strip_name_encoding (/* const char * */);
-int arm_is_longcall_p (/* rtx, int, int */);
diff --git a/gcc/config/arm/thumb_020422.md b/gcc/config/arm/thumb_020422.md
deleted file mode 100755
index 04de07c..0000000
--- a/gcc/config/arm/thumb_020422.md
+++ /dev/null
@@ -1,1194 +0,0 @@
-;; thumb.md Machine description for ARM/Thumb processors
-;; Copyright (C) 1996, 1997, 1998, 2002 Free Software Foundation, Inc.
-;; The basis of this contribution was generated by
-;; Richard Earnshaw, Advanced RISC Machines Ltd
-
-;; 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.
-
-;; LENGTH of an instruction is 2 bytes
-(define_attr "length" "" (const_int 2))
-
-;; CONDS is set to UNCHANGED when an insn does not affect the condition codes
-;; Most insns change the condition codes
-(define_attr "conds" "changed,unchanged" (const_string "changed"))
-
-;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
-;; distant label.
-(define_attr "far_jump" "yes,no" (const_string "no"))
-
-;; Start with move insns
-
-(define_expand "movsi"
- [(set (match_operand:SI 0 "general_operand" "")
- (match_operand:SI 1 "general_operand" ""))]
- ""
- "
- if (! (reload_in_progress || reload_completed))
- {
- if (GET_CODE (operands[0]) != REG)
- operands[1] = force_reg (SImode, operands[1]);
- }
-")
-
-(define_insn "*movsi_insn"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l,m,*r,*h")
- (match_operand:SI 1 "general_operand" "l,I,J,K,>,l,mi,l,*h,*r"))]
- "register_operand (operands[0], SImode)
- || register_operand (operands[1], SImode)"
- "@
- add\\t%0, %1, #0
- mov\\t%0, %1
- #
- #
- ldmia\\t%1, {%0}
- stmia\\t%0, {%1}
- ldr\\t%0, %1
- str\\t%1, %0
- mov\\t%0, %1
- mov\\t%0, %1"
-[(set_attr "length" "2,2,4,4,2,2,2,2,2,2")])
-
-(define_split
- [(set (match_operand:SI 0 "register_operand" "")
- (match_operand:SI 1 "const_int_operand" ""))]
- "thumb_shiftable_const (INTVAL (operands[1]))"
- [(set (match_dup 0) (match_dup 1))
- (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
- "
-{
- unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
- unsigned HOST_WIDE_INT mask = 0xff;
- int i;
- for (i = 0; i < 25; i++)
- if ((val & (mask << i)) == val)
- break;
-
- if (i == 0)
- FAIL;
-
- operands[1] = GEN_INT (val >> i);
- operands[2] = GEN_INT (i);
-}")
-
-(define_split
- [(set (match_operand:SI 0 "register_operand" "")
- (match_operand:SI 1 "const_int_operand" ""))]
- "INTVAL (operands[1]) < 0 && INTVAL (operands[1]) > -256"
- [(set (match_dup 0) (match_dup 1))
- (set (match_dup 0) (neg:SI (match_dup 0)))]
- "
- operands[1] = GEN_INT (- INTVAL (operands[1]));
-")
-
-;;(define_expand "reload_outsi"
-;; [(set (match_operand:SI 2 "register_operand" "=&l")
-;; (match_operand:SI 1 "register_operand" "h"))
-;; (set (match_operand:SI 0 "reload_memory_operand" "=o")
-;; (match_dup 2))]
-;; ""
-;; "
-;;/* thumb_reload_out_si (operands);
-;; DONE; */
-;;")
-
-(define_expand "movhi"
- [(set (match_operand:HI 0 "general_operand" "")
- (match_operand:HI 1 "general_operand" ""))]
- ""
- "
-{
- if (! (reload_in_progress || reload_completed))
- {
- if (GET_CODE (operands[0]) != REG)
- operands[1] = force_reg (HImode, operands[1]);
-
- /* ??? We shouldn't really get invalid addresses here, but this can
- happen if we are passed a SP (never OK for HImode/QImode) or virtual
- register (rejected by GO_IF_LEGITIMATE_ADDRESS for HImode/QImode)
- relative address. */
- /* ??? This should perhaps be fixed elsewhere, for instance, in
- fixup_stack_1, by checking for other kinds of invalid addresses,
- e.g. a bare reference to a virtual register. This may confuse the
- alpha though, which must handle this case differently. */
- if (GET_CODE (operands[0]) == MEM
- && ! memory_address_p (GET_MODE (operands[0]),
- XEXP (operands[0], 0)))
- {
- rtx temp = copy_to_reg (XEXP (operands[0], 0));
- operands[0] = change_address (operands[0], VOIDmode, temp);
- }
- if (GET_CODE (operands[1]) == MEM
- && ! memory_address_p (GET_MODE (operands[1]),
- XEXP (operands[1], 0)))
- {
- rtx temp = copy_to_reg (XEXP (operands[1], 0));
- operands[1] = change_address (operands[1], VOIDmode, temp);
- }
- }
- /* Handle loading a large integer during reload */
- else if (GET_CODE (operands[1]) == CONST_INT
- && ! CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
- {
- /* Writing a constant to memory needs a scratch, which should
- be handled with SECONDARY_RELOADs. */
- if (GET_CODE (operands[0]) != REG)
- abort ();
-
- operands[0] = gen_rtx (SUBREG, SImode, operands[0], 0);
- emit_insn (gen_movsi (operands[0], operands[1]));
- DONE;
- }
-}")
-
-(define_insn "*movhi_insn"
- [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
- (match_operand:HI 1 "general_operand" "l,m,l,*h,*r,I"))]
- "register_operand (operands[0], HImode)
- || register_operand (operands[1], HImode)"
- "@
- add\\t%0, %1, #0
- ldrh\\t%0, %1
- strh\\t%1, %0
- mov\\t%0, %1
- mov\\t%0, %1
- mov\\t%0, %1")
-
-(define_expand "movqi"
- [(set (match_operand:QI 0 "general_operand" "")
- (match_operand:QI 1 "general_operand" ""))]
- ""
- "
-{
- if (! (reload_in_progress || reload_completed))
- {
- if (GET_CODE (operands[0]) != REG)
- operands[1] = force_reg (QImode, operands[1]);
-
- /* ??? We shouldn't really get invalid addresses here, but this can
- happen if we are passed a SP (never OK for HImode/QImode) or virtual
- register (rejected by GO_IF_LEGITIMATE_ADDRESS for HImode/QImode)
- relative address. */
- /* ??? This should perhaps be fixed elsewhere, for instance, in
- fixup_stack_1, by checking for other kinds of invalid addresses,
- e.g. a bare reference to a virtual register. This may confuse the
- alpha though, which must handle this case differently. */
- if (GET_CODE (operands[0]) == MEM
- && ! memory_address_p (GET_MODE (operands[0]),
- XEXP (operands[0], 0)))
- {
- rtx temp = copy_to_reg (XEXP (operands[0], 0));
- operands[0] = change_address (operands[0], VOIDmode, temp);
- }
- if (GET_CODE (operands[1]) == MEM
- && ! memory_address_p (GET_MODE (operands[1]),
- XEXP (operands[1], 0)))
- {
- rtx temp = copy_to_reg (XEXP (operands[1], 0));
- operands[1] = change_address (operands[1], VOIDmode, temp);
- }
- }
- /* Handle loading a large integer during reload */
- else if (GET_CODE (operands[1]) == CONST_INT
- && ! CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
- {
- /* Writing a constant to memory needs a scratch, which should
- be handled with SECONDARY_RELOADs. */
- if (GET_CODE (operands[0]) != REG)
- abort ();
-
- operands[0] = gen_rtx (SUBREG, SImode, operands[0], 0);
- emit_insn (gen_movsi (operands[0], operands[1]));
- DONE;
- }
-}")
-
-(define_insn "*movqi_insn"
- [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
- (match_operand:QI 1 "general_operand" "l,m,l,*h,*r,I"))]
- "register_operand (operands[0], QImode)
- || register_operand (operands[1], QImode)"
- "@
- add\\t%0, %1, #0
- ldrb\\t%0, %1
- strb\\t%1, %0
- mov\\t%0, %1
- mov\\t%0, %1
- mov\\t%0, %1")
-
-(define_expand "movdi"
- [(set (match_operand:DI 0 "general_operand" "")
- (match_operand:DI 1 "general_operand" ""))]
- ""
- "
- if (! (reload_in_progress || reload_completed))
- {
- if (GET_CODE (operands[0]) != REG)
- operands[1] = force_reg (DImode, operands[1]);
- }
-")
-
-;;; ??? This should have alternatives for constants.
-;;; ??? This was originally identical to the movdf_insn pattern.
-;;; ??? The 'i' constraint looks funny, but it should always be replaced by
-;;; thumb_reorg with a memory reference.
-(define_insn "*movdi_insn"
- [(set (match_operand:DI 0 "general_operand" "=l,l,l,l,>,l,m,*r")
- (match_operand:DI 1 "general_operand" "l,I,J,>,l,mi,l,*r"))]
- "register_operand (operands[0], DImode)
- || register_operand (operands[1], DImode)"
- "*
-{
- switch (which_alternative)
- {
- case 0:
- if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
- return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
- return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
- case 1:
- return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
- case 2:
- operands[1] = GEN_INT (- INTVAL (operands[1]));
- return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
- case 3:
- return \"ldmia\\t%1, {%0, %H0}\";
- case 4:
- return \"stmia\\t%0, {%1, %H1}\";
- case 5:
- return thumb_load_double_from_address (operands);
- case 6:
- operands[2] = gen_rtx (MEM, SImode, plus_constant (XEXP (operands[0], 0), 4));
- output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
- return \"\";
- case 7:
- if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
- return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
- return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
- }
-}"[(set_attr "length" "4,4,6,2,2,6,4,4")])
-
-(define_expand "movdf"
- [(set (match_operand:DF 0 "general_operand" "")
- (match_operand:DF 1 "general_operand" ""))]
- ""
- "
- if (! (reload_in_progress || reload_completed))
- {
- if (GET_CODE (operands[0]) != REG)
- operands[1] = force_reg (DFmode, operands[1]);
- }
-")
-
-;;; ??? This should have alternatives for constants.
-;;; ??? This was originally identical to the movdi_insn pattern.
-;;; ??? The 'F' constraint looks funny, but it should always be replaced by
-;;; thumb_reorg with a memory reference.
-(define_insn "*movdf_insn"
- [(set (match_operand:DF 0 "general_operand" "=l,l,>,l,m,*r")
- (match_operand:DF 1 "general_operand" "l,>,l,mF,l,*r"))]
- "register_operand (operands[0], DFmode)
- || register_operand (operands[1], DFmode)"
- "*
- switch (which_alternative)
- {
- case 0:
- if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
- return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
- return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
- case 1:
- return \"ldmia\\t%1, {%0, %H0}\";
- case 2:
- return \"stmia\\t%0, {%1, %H1}\";
- case 3:
- return thumb_load_double_from_address (operands);
- case 4:
- operands[2] = gen_rtx (MEM, SImode, plus_constant (XEXP (operands[0], 0), 4));
- output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
- return \"\";
- case 5:
- if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
- return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
- return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
- }
-"[(set_attr "length" "4,2,2,6,4,4")])
-
-(define_expand "movsf"
- [(set (match_operand:SF 0 "general_operand" "")
- (match_operand:SF 1 "general_operand" ""))]
- ""
- "
- if (! (reload_in_progress || reload_completed))
- {
- if (GET_CODE (operands[0]) != REG)
- operands[1] = force_reg (SFmode, operands[1]);
- }
-")
-
-;;; ??? This should have alternatives for constants.
-(define_insn "*movsf_insn"
- [(set (match_operand:SF 0 "nonimmediate_operand" "=l,l,>,l,m,*r,*h")
- (match_operand:SF 1 "general_operand" "l,>,l,mF,l,*h,*r"))]
- "register_operand (operands[0], SFmode)
- || register_operand (operands[1], SFmode)"
- "@
- add\\t%0, %1, #0
- ldmia\\t%1, {%0}
- stmia\\t%0, {%1}
- ldr\\t%0, %1
- str\\t%1, %0
- mov\\t%0, %1
- mov\\t%0, %1")
-
-;; Widening move insns
-
-(define_expand "zero_extendhisi2"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
- ""
- "
- if (GET_CODE (operands[1]) != MEM)
- {
- rtx temp = gen_reg_rtx (SImode);
-
- operands[1] = force_reg (HImode, operands[1]);
- operands[1] = gen_lowpart (SImode, operands[1]);
- emit_insn (gen_ashlsi3 (temp, operands[1], GEN_INT (16)));
- emit_insn (gen_lshrsi3 (operands[0], temp, GEN_INT (16)));
- DONE;
- }
-")
-
-(define_insn "*zero_extendhisi2_insn"
- [(set (match_operand:SI 0 "s_register_operand" "=l")
- (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
- ""
- "ldrh\\t%0, %1")
-
-(define_expand "zero_extendqisi2"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
- ""
- "
- if (GET_CODE (operands[1]) != MEM)
- {
- rtx temp = gen_reg_rtx (SImode);
-
- operands[1] = force_reg (QImode, operands[1]);
- operands[1] = gen_lowpart (SImode, operands[1]);
- emit_insn (gen_ashlsi3 (temp, operands[1], GEN_INT (24)));
- emit_insn (gen_lshrsi3 (operands[0], temp, GEN_INT (24)));
- DONE;
- }
-")
-
-(define_insn "*zero_extendqisi2_insn"
- [(set (match_operand:SI 0 "s_register_operand" "=l")
- (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
- ""
- "ldrb\\t%0, %1")
-
-(define_expand "extendhisi2"
- [(parallel [(set (match_operand:SI 0 "s_register_operand" "")
- (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))
- (clobber (match_scratch:SI 2 ""))])]
- ""
- "
- if (GET_CODE (operands[1]) != MEM)
- {
- rtx temp = gen_reg_rtx (SImode);
-
- operands[1] = force_reg (HImode, operands[1]);
- operands[1] = gen_lowpart (SImode, operands[1]);
- emit_insn (gen_ashlsi3 (temp, operands[1], GEN_INT (16)));
- emit_insn (gen_ashrsi3 (operands[0], temp, GEN_INT (16)));
- DONE;
- }
-")
-
-(define_insn "*extendhisi2_insn"
- [(set (match_operand:SI 0 "s_register_operand" "=l")
- (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
- (clobber (match_scratch:SI 2 "=&l"))]
- ""
- "*
-{
- rtx ops[4];
- /* This code used to try to use 'V', and fix the address only if it was
- offsettable, but this fails for e.g. REG+48 because 48 is outside the
- range of QImode offsets, and offsettable_address_p does a QImode
- address check. */
-
- if (GET_CODE (XEXP (operands[1], 0)) == PLUS)
- {
- ops[1] = XEXP (XEXP (operands[1], 0), 0);
- ops[2] = XEXP (XEXP (operands[1], 0), 1);
- }
- else
- {
- ops[1] = XEXP (operands[1], 0);
- ops[2] = const0_rtx;
- }
- if (GET_CODE (ops[2]) == REG)
- return \"ldrsh\\t%0, %1\";
-
- ops[0] = operands[0];
- ops[3] = operands[2];
- output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
- return \"\";
-}"
-[(set_attr "length" "4")])
-
-(define_expand "extendqisi2"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
- ""
- "
- if (GET_CODE (operands[1]) != MEM)
- {
- rtx temp = gen_reg_rtx (SImode);
-
- operands[1] = force_reg (QImode, operands[1]);
- operands[1] = gen_lowpart (SImode, operands[1]);
- emit_insn (gen_ashlsi3 (temp, operands[1], GEN_INT (24)));
- emit_insn (gen_ashrsi3 (operands[0], temp, GEN_INT (24)));
- DONE;
- }
-")
-
-(define_insn "*extendqisi2_insn"
- [(set (match_operand:SI 0 "s_register_operand" "=l,l")
- (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
- ""
- "*
-{
- rtx ops[3];
-
- if (which_alternative == 0)
- return \"ldrsb\\t%0, %1\";
- ops[0] = operands[0];
- if (GET_CODE (XEXP (operands[1], 0)) == PLUS)
- {
- ops[1] = XEXP (XEXP (operands[1], 0), 0);
- ops[2] = XEXP (XEXP (operands[1], 0), 1);
-
- if (GET_CODE (ops[1]) == REG && GET_CODE (ops[2]) == REG)
- output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
- else if (GET_CODE (ops[1]) == REG)
- {
- if (REGNO (ops[1]) == REGNO (operands[0]))
- output_asm_insn (\"ldrb\\t%0, [%1, %2]\;lsl\\t%0, %0, #24\;asr\\t%0, %0, #24\", ops);
- else
- output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
- }
- else
- {
- if (REGNO (ops[2]) == REGNO (operands[0]))
- output_asm_insn (\"ldrb\\t%0, [%2, %1]\;lsl\\t%0, %0, #24\;asr\\t%0, %0, #24\", ops);
- else
- output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
- }
- }
- else if (REGNO (operands[0]) == REGNO (XEXP (operands[1], 0)))
- {
- output_asm_insn (\"ldrb\\t%0, [%0, #0]\;lsl\\t%0, %0, #24\;asr\\t%0, %0, #24\", ops);
- }
- else
- {
- ops[1] = XEXP (operands[1], 0);
- ops[2] = const0_rtx;
- output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
- }
- return \"\";
-}"
-[(set_attr "length" "2,6")])
-
-;; We don't really have extzv, but defining this using shifts helps
-;; to reduce register pressure later on.
-
-(define_expand "extzv"
- [(set (match_dup 4)
- (ashift:SI (match_operand:SI 1 "register_operand" "")
- (match_operand:SI 2 "const_int_operand" "")))
- (set (match_operand:SI 0 "register_operand" "")
- (lshiftrt:SI (match_dup 4)
- (match_operand:SI 3 "const_int_operand" "")))]
- ""
- "
-{
- HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
- HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
- operands[3] = GEN_INT (rshift);
- if (lshift == 0)
- {
- emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
- DONE;
- }
- operands[2] = GEN_INT (lshift);
- operands[4] = gen_reg_rtx (SImode);
-}
-")
-
-;; Block-move insns
-
-(define_expand "movstrqi"
- [(match_operand:BLK 0 "general_operand" "")
- (match_operand:BLK 1 "general_operand" "")
- (match_operand:SI 2 "" "")
- (match_operand:SI 3 "const_int_operand" "")]
- ""
- "
- if (INTVAL (operands[3]) != 4
- || GET_CODE (operands[2]) != CONST_INT
- || INTVAL (operands[2]) > 48)
- FAIL;
-
- thumb_expand_movstrqi (operands);
- DONE;
-")
-
-(define_insn "movmem12b"
- [(set (mem:SI (match_operand:SI 0 "register_operand" "+&l"))
- (mem:SI (match_operand:SI 1 "register_operand" "+&l")))
- (set (mem:SI (plus:SI (match_dup 0) (const_int 4)))
- (mem:SI (plus:SI (match_dup 1) (const_int 4))))
- (set (mem:SI (plus:SI (match_dup 0) (const_int 8)))
- (mem:SI (plus:SI (match_dup 1) (const_int 8))))
- (set (match_dup 0) (plus:SI (match_dup 0) (const_int 12)))
- (set (match_dup 1) (plus:SI (match_dup 1) (const_int 12)))
- (clobber (match_scratch:SI 2 "=&l"))
- (clobber (match_scratch:SI 3 "=&l"))
- (clobber (match_scratch:SI 4 "=&l"))]
- ""
- "* return output_move_mem_multiple (3, operands);"
-[(set_attr "length" "4")])
-
-(define_insn "movmem8b"
- [(set (mem:SI (match_operand:SI 0 "register_operand" "+&l"))
- (mem:SI (match_operand:SI 1 "register_operand" "+&l")))
- (set (mem:SI (plus:SI (match_dup 0) (const_int 4)))
- (mem:SI (plus:SI (match_dup 1) (const_int 4))))
- (set (match_dup 0) (plus:SI (match_dup 0) (const_int 8)))
- (set (match_dup 1) (plus:SI (match_dup 1) (const_int 8)))
- (clobber (match_scratch:SI 2 "=&l"))
- (clobber (match_scratch:SI 3 "=&l"))]
- ""
- "* return output_move_mem_multiple (2, operands);"
-[(set_attr "length" "4")])
-
-;; Arithmetic insns
-
-(define_insn "adddi3"
- [(set (match_operand:DI 0 "s_register_operand" "=l")
- (plus:DI (match_operand:DI 1 "s_register_operand" "%0")
- (match_operand:DI 2 "s_register_operand" "l")))]
- ""
- "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
-[(set_attr "conds" "changed")
- (set_attr "length" "8")])
-
-;; register group 'k' is a single register group containing only the stack
-;; register. Trying to reload it will always fail catastrophically,
-;; so never allow those alternatives to match if reloading is needed.
-(define_insn "addsi3"
- [(set (match_operand:SI 0 "s_register_operand" "=l,l,l,*r,*h,l,!k")
- (plus:SI (match_operand:SI 1 "s_register_operand" "%0,0,l,*0,*0,!k,!k")
- (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))]
- ""
- "*
- static char *asms[] =
-{
- \"add\\t%0, %0, %2\",
- \"sub\\t%0, %0, #%n2\",
- \"add\\t%0, %1, %2\",
- \"add\\t%0, %0, %2\",
- \"add\\t%0, %0, %2\",
- \"add\\t%0, %1, %2\",
- \"add\\t%0, %1, %2\"
-};
- if (which_alternative == 2 && GET_CODE (operands[2]) == CONST_INT
- && INTVAL (operands[2]) < 0)
- return \"sub\\t%0, %1, #%n2\";
- return asms[which_alternative];
-")
-
-; reloading and elimination of the frame pointer can sometimes cause this
-; optimization to be missed.
-(define_peephole
- [(set (match_operand:SI 0 "register_operand" "=l")
- (match_operand:SI 1 "const_int_operand" "M"))
- (set (match_dup 0)
- (plus:SI (match_dup 0) (match_operand:SI 2 "register_operand" "k")))]
- "REGNO (operands[2]) == STACK_POINTER_REGNUM
- && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
- && (INTVAL (operands[1]) & 3) == 0"
- "add\\t%0, %2, %1")
-
-(define_insn "subdi3"
- [(set (match_operand:DI 0 "s_register_operand" "=l")
- (minus:DI (match_operand:DI 1 "s_register_operand" "0")
- (match_operand:DI 2 "s_register_operand" "l")))]
- ""
- "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
-[(set_attr "conds" "changed")
- (set_attr "length" "8")])
-
-(define_insn "subsi3"
- [(set (match_operand:SI 0 "s_register_operand" "=l")
- (minus:SI (match_operand:SI 1 "s_register_operand" "l")
- (match_operand:SI 2 "s_register_operand" "l")))]
- ""
- "sub\\t%0, %1, %2")
-
-;; We must ensure that one input matches the output, and that the other input
-;; does not match the output. Using 0 satisfies the first, and using &
-;; satisfies the second. Unfortunately, this fails when operands 1 and 2
-;; are the same, because reload will make operand 0 match operand 1 without
-;; realizing that this conflicts with operand 2. We fix this by adding another
-;; alternative to match this case, and then `reload' it ourselves. This
-;; alternative must come first.
-(define_insn "mulsi3"
- [(set (match_operand:SI 0 "s_register_operand" "=&l,&l,&l")
- (mult:SI (match_operand:SI 1 "s_register_operand" "%l,*h,0")
- (match_operand:SI 2 "s_register_operand" "l,l,l")))]
- ""
- "*
-{
- if (which_alternative < 2)
- return \"mov\\t%0, %1\;mul\\t%0, %0, %2\";
- else
- return \"mul\\t%0, %0, %2\";
-}"
- [(set_attr "length" "4,4,2")])
-
-(define_insn "negsi2"
- [(set (match_operand:SI 0 "s_register_operand" "=l")
- (neg:SI (match_operand:SI 1 "s_register_operand" "l")))]
- ""
- "neg\\t%0, %1")
-
-;; Logical insns
-
-(define_expand "andsi3"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (and:SI (match_operand:SI 1 "s_register_operand" "")
- (match_operand:SI 2 "nonmemory_operand" "")))]
- ""
- "
- if (GET_CODE (operands[2]) != CONST_INT)
- operands[2] = force_reg (SImode, operands[2]);
- else
- {
- int i;
- if (((unsigned HOST_WIDE_INT) ~ INTVAL (operands[2])) < 256)
- {
- operands[2] = force_reg (SImode, GEN_INT (~INTVAL (operands[2])));
- emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
- DONE;
- }
-
- for (i = 9; i <= 31; i++)
- if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
- {
- emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
- const0_rtx));
- DONE;
- }
- else if ((((HOST_WIDE_INT) 1) << i) - 1 == ~ INTVAL (operands[2]))
- {
- rtx shift = GEN_INT (i);
- rtx reg = gen_reg_rtx (SImode);
- emit_insn (gen_lshrsi3 (reg, operands[1], shift));
- emit_insn (gen_ashlsi3 (operands[0], reg, shift));
- DONE;
- }
-
- operands[2] = force_reg (SImode, operands[2]);
- }
-")
-
-(define_insn "*andsi3_insn"
- [(set (match_operand:SI 0 "s_register_operand" "=l")
- (and:SI (match_operand:SI 1 "s_register_operand" "%0")
- (match_operand:SI 2 "s_register_operand" "l")))]
- ""
- "and\\t%0, %0, %2")
-
-(define_insn "bicsi3"
- [(set (match_operand:SI 0 "s_register_operand" "=l")
- (and:SI (not:SI (match_operand:SI 1 "s_register_operand" "l"))
- (match_operand:SI 2 "s_register_operand" "0")))]
- ""
- "bic\\t%0, %0, %1")
-
-(define_insn "iorsi3"
- [(set (match_operand:SI 0 "s_register_operand" "=l")
- (ior:SI (match_operand:SI 1 "s_register_operand" "%0")
- (match_operand:SI 2 "s_register_operand" "l")))]
- ""
- "orr\\t%0, %0, %2")
-
-(define_insn "xorsi3"
- [(set (match_operand:SI 0 "s_register_operand" "=l")
- (xor:SI (match_operand:SI 1 "s_register_operand" "%0")
- (match_operand:SI 2 "s_register_operand" "l")))]
- ""
- "eor\\t%0, %0, %2")
-
-(define_insn "one_cmplsi2"
- [(set (match_operand:SI 0 "s_register_operand" "=l")
- (not:SI (match_operand:SI 1 "s_register_operand" "l")))]
- ""
- "mvn\\t%0, %1")
-
-;; Shift and rotation insns
-
-(define_insn "ashlsi3"
- [(set (match_operand:SI 0 "s_register_operand" "=l,l")
- (ashift:SI (match_operand:SI 1 "s_register_operand" "l,0")
- (match_operand:SI 2 "nonmemory_operand" "N,l")))]
- ""
- "@
- lsl\\t%0, %1, %2
- lsl\\t%0, %0, %2")
-
-(define_insn "ashrsi3"
- [(set (match_operand:SI 0 "s_register_operand" "=l,l")
- (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "l,0")
- (match_operand:SI 2 "nonmemory_operand" "N,l")))]
- ""
- "@
- asr\\t%0, %1, %2
- asr\\t%0, %0, %2")
-
-(define_insn "lshrsi3"
- [(set (match_operand:SI 0 "s_register_operand" "=l,l")
- (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "l,0")
- (match_operand:SI 2 "nonmemory_operand" "N,l")))]
- ""
- "@
- lsr\\t%0, %1, %2
- lsr\\t%0, %0, %2")
-
-(define_insn "rotrsi3"
- [(set (match_operand:SI 0 "s_register_operand" "=l")
- (rotatert:SI (match_operand:SI 1 "s_register_operand" "0")
- (match_operand:SI 2 "s_register_operand" "l")))]
- ""
- "ror\\t%0, %0, %2")
-
-;; Comparison insns
-
-(define_expand "cmpsi"
- [(set (cc0) (compare (match_operand:SI 0 "s_register_operand" "")
- (match_operand:SI 1 "nonmemory_operand" "")))]
- ""
- "
- if (GET_CODE (operands[1]) != REG && GET_CODE (operands[1]) != SUBREG)
- {
- if (GET_CODE (operands[1]) != CONST_INT
- || (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) >= 256)
- {
- if (GET_CODE (operands[1]) != CONST_INT
- || INTVAL (operands[1]) < -255
- || INTVAL (operands[1]) > 0)
- operands[1] = force_reg (SImode, operands[1]);
- else
- {
- operands[1] = force_reg (SImode,
- GEN_INT (- INTVAL (operands[1])));
- emit_insn (gen_cmnsi (operands[0], operands[1]));
- DONE;
- }
- }
- }
-")
-
-(define_insn "*cmpsi_insn"
- [(set (cc0) (compare (match_operand:SI 0 "s_register_operand" "l,*r,*h")
- (match_operand:SI 1 "thumb_cmp_operand" "lI,*h,*r")))]
- ""
- "@
- cmp\\t%0, %1
- cmp\\t%0, %1
- cmp\\t%0, %1")
-
-(define_insn "tstsi"
- [(set (cc0) (match_operand:SI 0 "s_register_operand" "l"))]
- ""
- "cmp\\t%0, #0")
-
-(define_insn "cmnsi"
- [(set (cc0) (compare (match_operand:SI 0 "s_register_operand" "l")
- (neg:SI (match_operand:SI 1 "s_register_operand" "l"))))]
- ""
- "cmn\\t%0, %1")
-
-;; Jump insns
-
-(define_insn "jump"
- [(set (pc) (label_ref (match_operand 0 "" "")))]
- ""
- "*
- if (get_attr_length (insn) == 2)
- return \"b\\t%l0\";
- return \"bl\\t%l0\\t%@ far jump\";
-"[(set (attr "far_jump")
- (if_then_else (eq_attr "length" "4")
- (const_string "yes")
- (const_string "no")))
- (set (attr "length")
- (if_then_else (and (ge (minus (match_dup 0) (pc)) (const_int -2048))
- (le (minus (match_dup 0) (pc)) (const_int 2044)))
- (const_int 2)
- (const_int 4)))])
-
-
-(define_expand "beq"
- [(set (pc) (if_then_else (eq (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_expand "bne"
- [(set (pc) (if_then_else (ne (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_expand "bge"
- [(set (pc) (if_then_else (ge (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_expand "ble"
- [(set (pc) (if_then_else (le (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_expand "bgt"
- [(set (pc) (if_then_else (gt (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_expand "blt"
- [(set (pc) (if_then_else (lt (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_expand "bgeu"
- [(set (pc) (if_then_else (geu (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_expand "bleu"
- [(set (pc) (if_then_else (leu (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_expand "bgtu"
- [(set (pc) (if_then_else (gtu (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_expand "bltu"
- [(set (pc) (if_then_else (ltu (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_insn "*cond_branch"
- [(set (pc) (if_then_else (match_operator 1 "comparison_operator"
- [(cc0) (const_int 0)])
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "*
- switch (get_attr_length (insn))
- {
- case 2: return \"b%d1\\t%l0\\t%@cond_branch\";
- case 4: return \"b%D1\\t.LCB%=\;b\\t%l0\\t%@long jump\\n.LCB%=:\";
- default: return \"b%D1\\t.LCB%=\;bl\\t%l0\\t%@far jump\\n.LCB%=:\";
- }
-"[(set (attr "far_jump")
- (if_then_else (eq_attr "length" "6")
- (const_string "yes")
- (const_string "no")))
- (set (attr "length")
- (if_then_else
- (and (ge (minus (match_dup 0) (pc)) (const_int -252))
- (le (minus (match_dup 0) (pc)) (const_int 254)))
- (const_int 2)
- (if_then_else (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
- (le (minus (match_dup 0) (pc)) (const_int 2044)))
- (const_int 4)
- (const_int 6))))])
-
-(define_insn "*cond_branch_reversed"
- [(set (pc) (if_then_else (match_operator 1 "comparison_operator"
- [(cc0) (const_int 0)])
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
- "*
- switch (get_attr_length (insn))
- {
- case 2: return \"b%D1\\t%l0\\t%@cond_branch_reversed\";
- case 4: return \"b%d1\\t.LCBR%=\;b\\t%l0\\t%@long jump\\n.LCBR%=:\";
- default: return \"b%d1\\t.LCBR%=\;bl\\t%l0\\t%@far jump\\n.LCBR%=:\";
- }
- return \"\";
-"[(set (attr "far_jump")
- (if_then_else (eq_attr "length" "6")
- (const_string "yes")
- (const_string "no")))
- (set (attr "length")
- (if_then_else
- (and (ge (minus (match_dup 0) (pc)) (const_int -252))
- (le (minus (match_dup 0) (pc)) (const_int 254)))
- (const_int 2)
- (if_then_else (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
- (le (minus (match_dup 0) (pc)) (const_int 2044)))
- (const_int 4)
- (const_int 6))))])
-
-(define_insn "indirect_jump"
- [(set (pc) (match_operand:SI 0 "s_register_operand" "l*r"))]
- ""
- "mov\\tpc, %0")
-
-(define_insn "tablejump"
- [(set (pc) (match_operand:SI 0 "s_register_operand" "l*r"))
- (use (label_ref (match_operand 1 "" "")))]
- ""
- "mov\\tpc, %0")
-
-(define_insn "return"
- [(return)]
- "USE_RETURN"
- "* return output_return ();"
-[(set_attr "length" "18")])
-
-;; 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")])
-;; The non THUMB_INTERWORK, non TARGET_CALLER_INTERWORKING version
-;; used to be: "mov\\tlr,pc\;bx\\t%0", but the mov does not set
-;; the bottom bit of lr so that a function return (using bx)
-;; 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")])
-
-;; Untyped call not required, since all funcs return in r0
-
-;; Miscellaneous patterns
-
-(define_insn "nop"
- [(clobber (const_int 0))]
- ""
- "mov\\tr8, r8")
-
-(define_insn "blockage"
- [(unspec_volatile [(const_int 0)] 0)]
- ""
- ""
- [(set_attr "length" "0")])
-
-(define_expand "prologue"
- [(const_int 0)]
- ""
- "
- thumb_expand_prologue ();
- DONE;
-")
-
-(define_expand "epilogue"
- [(unspec_volatile [(const_int 0)] 1)]
- "! thumb_trivial_epilogue ()"
- "
- thumb_expand_epilogue ();
-")
-
-(define_insn "*epilogue_insns"
- [(unspec_volatile [(const_int 0)] 1)]
- ""
- "*
- return thumb_unexpanded_epilogue ();
-"
-[(set_attr "length" "42")])
-
-;; Special patterns for dealing with the constant pool
-
-(define_insn "consttable_4"
- [(unspec_volatile [(match_operand 0 "" "")] 2)]
- ""
- "*
-{
- switch (GET_MODE_CLASS (GET_MODE (operands[0])))
- {
- case MODE_FLOAT:
- {
- union real_extract u;
- bcopy ((char *) &CONST_DOUBLE_LOW (operands[0]), (char *) &u, sizeof u);
- assemble_real (u.d, GET_MODE (operands[0]));
- break;
- }
- default:
- assemble_integer (operands[0], 4, 1);
- break;
- }
- return \"\";
-}"
-[(set_attr "length" "4")])
-
-(define_insn "consttable_8"
- [(unspec_volatile [(match_operand 0 "" "")] 3)]
- ""
- "*
-{
- switch (GET_MODE_CLASS (GET_MODE (operands[0])))
- {
- case MODE_FLOAT:
- {
- union real_extract u;
- bcopy ((char *) &CONST_DOUBLE_LOW (operands[0]), (char *) &u, sizeof u);
- assemble_real (u.d, GET_MODE (operands[0]));
- break;
- }
- default:
- assemble_integer (operands[0], 8, 1);
- break;
- }
- return \"\";
-}"
-[(set_attr "length" "8")])
-
-(define_insn "consttable_end"
- [(unspec_volatile [(const_int 0)] 4)]
- ""
- "*
- /* Nothing to do (currently). */
- return \"\";
-")
-
-(define_insn "align_4"
- [(unspec_volatile [(const_int 0)] 5)]
- ""
- "*
- assemble_align (32);
- return \"\";
-")
diff --git a/gcc/config/arm/thumb_020428.h b/gcc/config/arm/thumb_020428.h
deleted file mode 100755
index 8bba8d0..0000000
--- a/gcc/config/arm/thumb_020428.h
+++ /dev/null
@@ -1,1297 +0,0 @@
-/* Definitions of target machine for GNU compiler, for ARM/Thumb.
- Copyright (C) 1996, 1997, 1998, 1999, 2002 Free Software Foundation, Inc.
- The basis of this contribution was generated by
- Richard Earnshaw, Advanced RISC Machines Ltd
-
-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. */
-
-/* ??? The files thumb.{c,h,md} are all seriously lacking comments. */
-
-/* ??? The files thumb.{c,h,md} need to be reviewed by an experienced
- gcc hacker in their entirety. */
-
-/* ??? The files thumb.{c,h,md} and tcoff.h are all separate from the arm
- files, which will lead to many maintenance problems. These files are
- likely missing all bug fixes made to the arm port since they diverged. */
-
-/* ??? Many patterns in the md file accept operands that will require a
- reload. These should be eliminated if possible by tightening the
- predicates and/or constraints. This will give faster/smaller code. */
-
-/* ??? There is no pattern for the TST instuction. Check for other unsupported
- instructions. */
-
-/* Run Time Target Specifications */
-#ifndef CPP_PREDEFINES
-#define CPP_PREDEFINES "-Dthumb -D__thumb -Acpu(arm) -Amachine(arm)"
-#endif
-
-#ifndef CPP_SPEC
-#define CPP_SPEC "\
-%{mbig-endian:-D__ARMEB__ -D__THUMBEB__} \
-%{mbe:-D__ARMEB__ -D__THUMBEB__} \
-%{!mbe: %{!mbig-endian:-D__ARMEL__ -D__THUMBEL__}} \
-"
-#endif
-
-#ifndef ASM_SPEC
-#define ASM_SPEC "-marm7tdmi %{mthumb-interwork:-mthumb-interwork} %{mbig-endian:-EB}"
-#endif
-#define LINK_SPEC "%{mbig-endian:-EB} -X"
-
-#define TARGET_VERSION fputs (" (ARM/THUMB:generic)", stderr);
-
-/* Nonzero if we should compile with BYTES_BIG_ENDIAN set to 1. */
-#define THUMB_FLAG_BIG_END 0x0001
-#define THUMB_FLAG_BACKTRACE 0x0002
-#define THUMB_FLAG_LEAF_BACKTRACE 0x0004
-#define ARM_FLAG_THUMB 0x1000 /* same as in arm.h */
-#define THUMB_FLAG_CALLEE_SUPER_INTERWORKING 0x40000
-#define THUMB_FLAG_CALLER_SUPER_INTERWORKING 0x80000
-
-/* Nonzero if all call instructions should be indirect. */
-#define ARM_FLAG_LONG_CALLS (0x10000) /* same as in arm.h */
-
-
-/* Run-time compilation parameters selecting different hardware/software subsets. */
-extern int target_flags;
-#define TARGET_DEFAULT 0 /* ARM_FLAG_THUMB */
-#define TARGET_BIG_END (target_flags & THUMB_FLAG_BIG_END)
-#define TARGET_THUMB_INTERWORK (target_flags & ARM_FLAG_THUMB)
-#define TARGET_BACKTRACE (leaf_function_p() \
- ? (target_flags & THUMB_FLAG_LEAF_BACKTRACE) \
- : (target_flags & THUMB_FLAG_BACKTRACE))
-
-/* Set if externally visable functions should assume that they
- might be called in ARM mode, from a non-thumb aware code. */
-#define TARGET_CALLEE_INTERWORKING \
- (target_flags & THUMB_FLAG_CALLEE_SUPER_INTERWORKING)
-
-/* Set if calls via function pointers should assume that their
- destination is non-Thumb aware. */
-#define TARGET_CALLER_INTERWORKING \
- (target_flags & THUMB_FLAG_CALLER_SUPER_INTERWORKING)
-
-#define TARGET_LONG_CALLS (target_flags & ARM_FLAG_LONG_CALLS)
-
-/* SUBTARGET_SWITCHES is used to add flags on a per-config basis. */
-#ifndef SUBTARGET_SWITCHES
-#define SUBTARGET_SWITCHES
-#endif
-
-#define TARGET_SWITCHES \
-{ \
- {"big-endian", THUMB_FLAG_BIG_END}, \
- {"little-endian", -THUMB_FLAG_BIG_END}, \
- {"thumb-interwork", ARM_FLAG_THUMB}, \
- {"no-thumb-interwork", -ARM_FLAG_THUMB}, \
- {"tpcs-frame", THUMB_FLAG_BACKTRACE}, \
- {"no-tpcs-frame", -THUMB_FLAG_BACKTRACE}, \
- {"tpcs-leaf-frame", THUMB_FLAG_LEAF_BACKTRACE}, \
- {"no-tpcs-leaf-frame", -THUMB_FLAG_LEAF_BACKTRACE}, \
- {"callee-super-interworking", THUMB_FLAG_CALLEE_SUPER_INTERWORKING}, \
- {"no-callee-super-interworking", -THUMB_FLAG_CALLEE_SUPER_INTERWORKING}, \
- {"caller-super-interworking", THUMB_FLAG_CALLER_SUPER_INTERWORKING}, \
- {"no-caller-super-interworking", -THUMB_FLAG_CALLER_SUPER_INTERWORKING}, \
- {"long-calls", ARM_FLAG_LONG_CALLS, \
- "Generate all call instructions as indirect calls"}, \
- {"no-long-calls", -ARM_FLAG_LONG_CALLS, ""}, \
- SUBTARGET_SWITCHES \
- {"", TARGET_DEFAULT} \
-}
-
-#define TARGET_OPTIONS \
-{ \
- { "structure-size-boundary=", & structure_size_string }, \
-}
-
-#define REGISTER_PREFIX ""
-
-#define CAN_DEBUG_WITHOUT_FP 1
-
-#define ASM_APP_ON ""
-#define ASM_APP_OFF "\t.code\t16\n"
-
-/* Output a gap. In fact we fill it with nulls. */
-#define ASM_OUTPUT_SKIP(STREAM, NBYTES) \
- fprintf ((STREAM), "\t.space\t%u\n", (NBYTES))
-
-/* This is how to output an assembler line
- that says to advance the location counter
- to a multiple of 2**LOG bytes. */
-#define ASM_OUTPUT_ALIGN(STREAM,LOG) \
-{ \
- if ((LOG) > 0) \
- fprintf (STREAM, "\t.align\t%d\n", (LOG)); \
-}
-
-/* Output a common block */
-#define ASM_OUTPUT_COMMON(STREAM, NAME, SIZE, ROUNDED) \
- (fprintf ((STREAM), "\t.comm\t"), \
- assemble_name ((STREAM), (NAME)), \
- fprintf((STREAM), ", %d\t%s %d\n", (ROUNDED), (ASM_COMMENT_START), (SIZE)))
-
-#define ASM_GENERATE_INTERNAL_LABEL(STRING,PREFIX,NUM) \
- sprintf ((STRING), "*%s%s%d", (LOCAL_LABEL_PREFIX), (PREFIX), (NUM))
-
-/* This is how to output an internal numbered label where
- PREFIX is the class of label and NUM is the number within the class. */
-#define ASM_OUTPUT_INTERNAL_LABEL(STREAM,PREFIX,NUM) \
- fprintf ((STREAM), "%s%s%d:\n", (LOCAL_LABEL_PREFIX), (PREFIX), (NUM))
-
-/* This is how to output a label which precedes a jumptable. Since
- instructions are 2 bytes, we need explicit alignment here. */
-
-#define ASM_OUTPUT_CASE_LABEL(FILE,PREFIX,NUM,JUMPTABLE) \
- do { \
- ASM_OUTPUT_ALIGN (FILE, 2); \
- ASM_OUTPUT_INTERNAL_LABEL (FILE, PREFIX, NUM); \
- } while (0)
-
-/* This says how to define a local common symbol (ie, not visible to
- linker). */
-#define ASM_OUTPUT_LOCAL(STREAM, NAME, SIZE, ROUNDED) \
- (fprintf((STREAM),"\n\t.lcomm\t"), \
- assemble_name((STREAM),(NAME)), \
- fprintf((STREAM),",%u\n",(SIZE)))
-
-/* This is how to output an assembler line for a numeric constant byte. */
-#define ASM_OUTPUT_BYTE(STREAM,VALUE) \
- fprintf ((STREAM), "\t.byte\t0x%x\n", (VALUE))
-
-#define ASM_OUTPUT_INT(STREAM,VALUE) \
-{ \
- fprintf (STREAM, "\t.word\t"); \
- output_addr_const (STREAM, (VALUE)); \
- fprintf (STREAM, "\n"); \
-}
-
-#define ASM_OUTPUT_SHORT(STREAM,VALUE) \
-{ \
- fprintf (STREAM, "\t.short\t"); \
- output_addr_const (STREAM, (VALUE)); \
- fprintf (STREAM, "\n"); \
-}
-
-#define ASM_OUTPUT_CHAR(STREAM,VALUE) \
-{ \
- fprintf (STREAM, "\t.byte\t"); \
- output_addr_const (STREAM, (VALUE)); \
- fprintf (STREAM, "\n"); \
-}
-
-#define ASM_OUTPUT_LONG_DOUBLE(STREAM,VALUE) \
-do { char dstr[30]; \
- long l[3]; \
- REAL_VALUE_TO_TARGET_LONG_DOUBLE (VALUE, l); \
- REAL_VALUE_TO_DECIMAL (VALUE, "%.20g", dstr); \
- fprintf (STREAM, "\t.long 0x%lx,0x%lx,0x%lx\t%s long double %s\n", \
- l[0], l[1], l[2], ASM_COMMENT_START, dstr); \
- } while (0)
-
-#define ASM_OUTPUT_DOUBLE(STREAM, VALUE) \
-do { char dstr[30]; \
- long l[2]; \
- REAL_VALUE_TO_TARGET_DOUBLE (VALUE, l); \
- REAL_VALUE_TO_DECIMAL (VALUE, "%.14g", dstr); \
- fprintf (STREAM, "\t.long 0x%lx, 0x%lx\t%s double %s\n", l[0], \
- l[1], ASM_COMMENT_START, dstr); \
- } while (0)
-
-#define ASM_OUTPUT_FLOAT(STREAM, VALUE) \
-do { char dstr[30]; \
- long l; \
- REAL_VALUE_TO_TARGET_SINGLE (VALUE, l); \
- REAL_VALUE_TO_DECIMAL (VALUE, "%.7g", dstr); \
- fprintf (STREAM, "\t.word 0x%lx\t%s float %s\n", l, \
- ASM_COMMENT_START, dstr); \
- } while (0);
-
-/* Define results of standard character escape sequences. */
-#define TARGET_BELL 007
-#define TARGET_BS 010
-#define TARGET_TAB 011
-#define TARGET_NEWLINE 012
-#define TARGET_VT 013
-#define TARGET_FF 014
-#define TARGET_CR 015
-
-/* This is how to output a string. */
-#define ASM_OUTPUT_ASCII(STREAM, STRING, LEN) \
-do { \
- register int i, c, len = (LEN), cur_pos = 17; \
- register unsigned char *string = (unsigned char *)(STRING); \
- fprintf ((STREAM), "\t.ascii\t\""); \
- for (i = 0; i < len; i++) \
- { \
- register int c = string[i]; \
- \
- switch (c) \
- { \
- case '\"': \
- case '\\': \
- putc ('\\', (STREAM)); \
- putc (c, (STREAM)); \
- cur_pos += 2; \
- break; \
- \
- case TARGET_NEWLINE: \
- fputs ("\\n", (STREAM)); \
- if (i+1 < len \
- && (((c = string[i+1]) >= '\040' && c <= '~') \
- || c == TARGET_TAB)) \
- cur_pos = 32767; /* break right here */ \
- else \
- cur_pos += 2; \
- break; \
- \
- case TARGET_TAB: \
- fputs ("\\t", (STREAM)); \
- cur_pos += 2; \
- break; \
- \
- case TARGET_FF: \
- fputs ("\\f", (STREAM)); \
- cur_pos += 2; \
- break; \
- \
- case TARGET_BS: \
- fputs ("\\b", (STREAM)); \
- cur_pos += 2; \
- break; \
- \
- case TARGET_CR: \
- fputs ("\\r", (STREAM)); \
- cur_pos += 2; \
- break; \
- \
- default: \
- if (c >= ' ' && c < 0177) \
- { \
- putc (c, (STREAM)); \
- cur_pos++; \
- } \
- else \
- { \
- fprintf ((STREAM), "\\%03o", c); \
- cur_pos += 4; \
- } \
- } \
- \
- if (cur_pos > 72 && i+1 < len) \
- { \
- cur_pos = 17; \
- fprintf ((STREAM), "\"\n\t.ascii\t\""); \
- } \
- } \
- fprintf ((STREAM), "\"\n"); \
-} while (0)
-
-/* Output and Generation of Labels */
-#define ASM_OUTPUT_LABEL(STREAM,NAME) \
- (assemble_name ((STREAM), (NAME)), \
- fprintf ((STREAM), ":\n"))
-
-#define ASM_GLOBALIZE_LABEL(STREAM,NAME) \
- (fprintf ((STREAM), "\t.globl\t"), \
- assemble_name ((STREAM), (NAME)), \
- fputc ('\n', (STREAM)))
-
-/* Construct a private name. */
-#define ASM_FORMAT_PRIVATE_NAME(OUTVAR,NAME,NUMBER) \
- ((OUTVAR) = (char *) alloca (strlen (NAME) + 10), \
- sprintf ((OUTVAR), "%s.%d", (NAME), (NUMBER)))
-
-/* Switch to the text or data segment. */
-#define TEXT_SECTION_ASM_OP ".text"
-#define DATA_SECTION_ASM_OP ".data"
-#define BSS_SECTION_ASM_OP ".bss"
-
-/* The assembler's names for the registers. */
-#ifndef REGISTER_NAMES
-#define REGISTER_NAMES \
-{ \
- "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \
- "r8", "r9", "sl", "fp", "ip", "sp", "lr", "pc", "ap" \
-}
-#endif
-
-#ifndef ADDITIONAL_REGISTER_NAMES
-#define ADDITIONAL_REGISTER_NAMES \
-{ \
- {"a1", 0}, \
- {"a2", 1}, \
- {"a3", 2}, \
- {"a4", 3}, \
- {"v1", 4}, \
- {"v2", 5}, \
- {"v3", 6}, \
- {"v4", 7}, \
- {"v5", 8}, \
- {"v6", 9}, \
- {"sb", 9}, \
- {"v7", 10}, \
- {"r10", 10}, /* sl */ \
- {"r11", 11}, /* fp */ \
- {"r12", 12}, /* ip */ \
- {"r13", 13}, /* sp */ \
- {"r14", 14}, /* lr */ \
- {"r15", 15} /* pc */ \
-}
-#endif
-
-/* The assembler's parentheses characters. */
-#define ASM_OPEN_PAREN "("
-#define ASM_CLOSE_PAREN ")"
-
-#ifndef ASM_COMMENT_START
-#define ASM_COMMENT_START "@"
-#endif
-
-/* Output an element of a dispatch table. */
-#define ASM_OUTPUT_ADDR_VEC_ELT(STREAM,VALUE) \
- fprintf (STREAM, "\t.word\t%sL%d\n", (LOCAL_LABEL_PREFIX), (VALUE))
-
-#define ASM_OUTPUT_ADDR_DIFF_ELT(STREAM,BODY,VALUE,REL) \
- fprintf (STREAM, "\tb\t%sL%d\n", (LOCAL_LABEL_PREFIX), (VALUE))
-
-/* Storage Layout */
-
-/* Define this is most significant bit is lowest numbered in
- instructions that operate on numbered bit-fields. */
-#define BITS_BIG_ENDIAN 0
-
-/* Define this if most significant byte of a word is the lowest
- numbered. */
-#define BYTES_BIG_ENDIAN (TARGET_BIG_END != 0)
-
-#define WORDS_BIG_ENDIAN (BYTES_BIG_ENDIAN)
-
-/* LIBGCC2_WORDS_BIG_ENDIAN has to be a constant, so we define this based
- on processor pre-defineds when compiling libgcc2.c. */
-#if defined(__THUMBEB__) && !defined(__THUMBEL__)
-#define LIBGCC2_WORDS_BIG_ENDIAN 1
-#else
-#define LIBGCC2_WORDS_BIG_ENDIAN 0
-#endif
-
-#define FLOAT_WORDS_BIG_ENDIAN 1
-
-#define BITS_PER_UNIT 8
-#define BITS_PER_WORD 32
-
-#define UNITS_PER_WORD 4
-
-#define POINTER_SIZE 32
-
-#define PROMOTE_MODE(MODE,UNSIGNEDP,TYPE) \
-{ \
- if (GET_MODE_CLASS (MODE) == MODE_INT \
- && GET_MODE_SIZE (MODE) < 4) \
- { \
- (UNSIGNEDP) = 1; \
- (MODE) = SImode; \
- } \
-}
-
-#define PARM_BOUNDARY 32
-#define STACK_BOUNDARY 32
-
-#define FUNCTION_BOUNDARY 32
-#define BIGGEST_ALIGNMENT 32
-
-/* Make strings word-aligned so strcpy from constants will be faster. */
-#define CONSTANT_ALIGNMENT(EXP, ALIGN) \
- (TREE_CODE (EXP) == STRING_CST \
- && (ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN))
-
-#define EMPTY_FIELD_BOUNDARY 32
-
-#define STRUCTURE_SIZE_BOUNDARY 32
-
-/* Used when parsing command line option -mstructure_size_boundary. */
-extern char * structure_size_string;
-
-#define STRICT_ALIGNMENT 1
-
-#define TARGET_FLOAT_FORMAT IEEE_FLOAT_FORMAT
-
-
-/* Layout of Source Language Data Types */
-
-#define DEFAULT_SIGNED_CHAR 0
-
-#define TARGET_BELL 007
-#define TARGET_BS 010
-#define TARGET_TAB 011
-#define TARGET_NEWLINE 012
-#define TARGET_VT 013
-#define TARGET_FF 014
-#define TARGET_CR 015
-
-
-/* Register Usage */
-
-/* Note there are 16 hard registers on the Thumb. We invent a 17th register
- which is assigned to ARG_POINTER_REGNUM, but this is later removed by
- elimination passes in the compiler. */
-#define FIRST_PSEUDO_REGISTER 17
-
-/* ??? This is questionable. */
-#define FIXED_REGISTERS \
-{ \
- 0,0,0,0, \
- 0,0,0,0, \
- 0,0,0,1, \
- 0,1,1,1,1 \
-}
-
-/* ??? This is questionable. */
-#define CALL_USED_REGISTERS \
-{ \
- 1,1,1,1, \
- 0,0,0,0, \
- 0,0,0,1, \
- 1,1,1,1,1 \
-}
-
-#define HARD_REGNO_NREGS(REGNO,MODE) \
- ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) \
- / UNITS_PER_WORD)
-
-/* ??? Probably should only allow DImode/DFmode in even numbered registers. */
-#define HARD_REGNO_MODE_OK(REGNO,MODE) ((GET_MODE_SIZE (MODE) > UNITS_PER_WORD) ? (REGNO < 7) : 1)
-
-#define MODES_TIEABLE_P(MODE1,MODE2) 1
-
-/* The NOARG_LO_REGS class is the set of LO_REGS that are not used for passing
- arguments to functions. These are the registers that are available for
- spilling during reload. The code in reload1.c:init_reload() will detect this
- class and place it into 'reload_address_base_reg_class'. */
-
-enum reg_class
-{
- NO_REGS,
- NONARG_LO_REGS,
- LO_REGS,
- STACK_REG,
- BASE_REGS,
- HI_REGS,
- ALL_REGS,
- LIM_REG_CLASSES
-};
-
-#define GENERAL_REGS ALL_REGS
-
-#define N_REG_CLASSES (int) LIM_REG_CLASSES
-
-#define REG_CLASS_NAMES \
-{ \
- "NO_REGS", \
- "NONARG_LO_REGS", \
- "LO_REGS", \
- "STACK_REG", \
- "BASE_REGS", \
- "HI_REGS", \
- "ALL_REGS" \
-}
-
-#define REG_CLASS_CONTENTS \
-{ \
- 0x00000, \
- 0x000f0, \
- 0x000ff, \
- 0x02000, \
- 0x020ff, \
- 0x0ff00, \
- 0x1ffff, \
-}
-
-#define REGNO_REG_CLASS(REGNO) \
- ((REGNO) == STACK_POINTER_REGNUM ? STACK_REG \
- : (REGNO) < 8 ? ((REGNO) < 4 ? LO_REGS \
- : NONARG_LO_REGS) \
- : HI_REGS)
-
-#define BASE_REG_CLASS BASE_REGS
-
-#define MODE_BASE_REG_CLASS(MODE) \
- ((MODE) != QImode && (MODE) != HImode \
- ? BASE_REGS : LO_REGS)
-
-#define INDEX_REG_CLASS LO_REGS
-
-/* When SMALL_REGISTER_CLASSES is nonzero, the compiler allows
- registers explicitly used in the rtl to be used as spill registers
- but prevents the compiler from extending the lifetime of these
- registers. */
-
-#define SMALL_REGISTER_CLASSES 1
-
-#define REG_CLASS_FROM_LETTER(C) \
- ((C) == 'l' ? LO_REGS \
- : (C) == 'h' ? HI_REGS \
- : (C) == 'b' ? BASE_REGS \
- : (C) == 'k' ? STACK_REG \
- : NO_REGS)
-
-#define REGNO_OK_FOR_BASE_P(REGNO) \
- ((REGNO) < 8 \
- || (REGNO) == STACK_POINTER_REGNUM \
- || (unsigned) reg_renumber[REGNO] < 8 \
- || (unsigned) reg_renumber[REGNO] == STACK_POINTER_REGNUM)
-
-#define REGNO_MODE_OK_FOR_BASE_P(REGNO, MODE) \
- ((REGNO) < 8 \
- || (unsigned) reg_renumber[REGNO] < 8 \
- || (GET_MODE_SIZE (MODE) >= 4 \
- && ((REGNO) == STACK_POINTER_REGNUM \
- || (unsigned) reg_renumber[REGNO] == STACK_POINTER_REGNUM)))
-
-#define REGNO_OK_FOR_INDEX_P(REGNO) \
- ((REGNO) < 8 \
- || (unsigned) reg_renumber[REGNO] < 8)
-
-/* ??? This looks suspiciously wrong. */
-/* We need to leave BASE_REGS reloads alone, in order to avoid caller_save
- lossage. Caller_saves requests a BASE_REGS reload (caller_save_spill_class)
- and then later we verify that one was allocated. If PREFERRED_RELOAD_CLASS
- says to allocate a LO_REGS spill instead, then this mismatch gives an
- abort. Alternatively, this could be fixed by modifying BASE_REG_CLASS
- to be LO_REGS instead of BASE_REGS. It is not clear what affect this
- change would have. */
-/* ??? This looks even more suspiciously wrong. PREFERRED_RELOAD_CLASS
- must always return a strict subset of the input class. Just blindly
- returning LO_REGS is safe only if the input class is a superset of LO_REGS,
- but there is no check for this. Added another exception for NONARG_LO_REGS
- because it is not a superset of LO_REGS. */
-/* ??? We now use NONARG_LO_REGS for caller_save_spill_class, so the
- comments about BASE_REGS are now obsolete. */
-#define PREFERRED_RELOAD_CLASS(X,CLASS) \
- ((CLASS) == BASE_REGS || (CLASS) == NONARG_LO_REGS ? (CLASS) \
- : LO_REGS)
-/*
- ((CONSTANT_P ((X)) && GET_CODE ((X)) != CONST_INT \
- && ! CONSTANT_POOL_ADDRESS_P((X))) ? NO_REGS \
- : (GET_CODE ((X)) == CONST_INT \
- && (unsigned HOST_WIDE_INT) INTVAL ((X)) > 255) ? NO_REGS \
- : LO_REGS) */
-
-/* Must leave BASE_REGS and NONARG_LO_REGS reloads alone, see comment
- above. */
-#define SECONDARY_RELOAD_CLASS(CLASS,MODE,X) \
- ((CLASS) != LO_REGS && (CLASS) != BASE_REGS && (CLASS) != NONARG_LO_REGS \
- ? ((true_regnum (X) == -1 ? LO_REGS \
- : (true_regnum (X) + HARD_REGNO_NREGS (0, MODE) > 8) ? LO_REGS \
- : NO_REGS)) \
- : NO_REGS)
-
-#define CLASS_MAX_NREGS(CLASS,MODE) HARD_REGNO_NREGS(0,(MODE))
-
-int thumb_shiftable_const ();
-
-#define CONST_OK_FOR_LETTER_P(VAL,C) \
- ((C) == 'I' ? (unsigned HOST_WIDE_INT) (VAL) < 256 \
- : (C) == 'J' ? (VAL) > -256 && (VAL) <= 0 \
- : (C) == 'K' ? thumb_shiftable_const (VAL) \
- : (C) == 'L' ? (VAL) > -8 && (VAL) < 8 \
- : (C) == 'M' ? ((unsigned HOST_WIDE_INT) (VAL) < 1024 \
- && ((VAL) & 3) == 0) \
- : (C) == 'N' ? ((unsigned HOST_WIDE_INT) (VAL) < 32) \
- : (C) == 'O' ? ((VAL) >= -508 && (VAL) <= 508) \
- : 0)
-
-#define CONST_DOUBLE_OK_FOR_LETTER_P(VAL,C) 0
-
-#define EXTRA_CONSTRAINT(X,C) \
- ((C) == 'Q' ? (GET_CODE (X) == MEM \
- && GET_CODE (XEXP (X, 0)) == LABEL_REF) : 0)
-
-/* Stack Layout and Calling Conventions */
-
-#define STACK_GROWS_DOWNWARD 1
-
-/* #define FRAME_GROWS_DOWNWARD 1 */
-
-/* #define ARGS_GROW_DOWNWARD 1 */
-
-#define STARTING_FRAME_OFFSET 0
-
-#define FIRST_PARM_OFFSET(FNDECL) 0
-
-/* Registers that address the stack frame */
-
-#define STACK_POINTER_REGNUM 13 /* Defined by the TPCS. */
-
-#define FRAME_POINTER_REGNUM 7 /* TPCS defines this as 11 but it does not really mean it. */
-
-#define ARG_POINTER_REGNUM 16 /* A fake hard register that is eliminated later on. */
-
-#define STATIC_CHAIN_REGNUM 9
-
-#define FRAME_POINTER_REQUIRED 0
-
-#define ELIMINABLE_REGS \
-{{ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
- {ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM}, \
- {FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}}
-
-/* On the Thumb we always want to perform the eliminations as we
- actually only have one real register pointing to the stashed
- variables: the stack pointer, and we never use the frame pointer. */
-#define CAN_ELIMINATE(FROM,TO) 1
-
-/* Note: This macro must match the code in thumb_function_prologue() in thumb.c. */
-#define INITIAL_ELIMINATION_OFFSET(FROM,TO,OFFSET) \
-{ \
- (OFFSET) = 0; \
- if ((FROM) == ARG_POINTER_REGNUM) \
- { \
- int count_regs = 0; \
- int regno; \
- (OFFSET) += get_frame_size (); \
- for (regno = 8; regno < 13; regno++) \
- if (regs_ever_live[regno] && ! call_used_regs[regno]) \
- count_regs++; \
- if (count_regs) \
- (OFFSET) += 4 * count_regs; \
- count_regs = 0; \
- for (regno = 0; regno < 8; regno++) \
- if (regs_ever_live[regno] && ! call_used_regs[regno]) \
- count_regs++; \
- if (count_regs || ! leaf_function_p () || far_jump_used_p()) \
- (OFFSET) += 4 * (count_regs + 1); \
- if (TARGET_BACKTRACE) { \
- if ((count_regs & 0xFF) == 0 && (regs_ever_live[3] != 0)) \
- (OFFSET) += 20; \
- else \
- (OFFSET) += 16; } \
- } \
- if ((TO) == STACK_POINTER_REGNUM) \
- (OFFSET) += current_function_outgoing_args_size; \
-}
-
-/* Passing Arguments on the stack */
-
-#define PROMOTE_PROTOTYPES 1
-
-#define ACCUMULATE_OUTGOING_ARGS 1
-
-#define RETURN_POPS_ARGS(FUNDECL,FUNTYPE,SIZE) 0
-
-#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
- ((MODE) == VOIDmode \
- ? GEN_INT ((CUM).call_cookie) \
- : (NAMED) \
- ? ((CUM).nregs >= 16 ? 0 : gen_rtx (REG, MODE, (CUM).nregs / 4)) \
- : 0)
-
-#define FUNCTION_ARG_PARTIAL_NREGS(CUM,MODE,TYPE,NAMED) \
- (((CUM).nregs < 16 && (CUM).nregs + (((MODE) == BLKmode) \
- ? int_size_in_bytes (TYPE) \
- : (HARD_REGNO_NREGS (0, (MODE)) \
- * 4)) > 16) \
- ? 4 - (CUM).nregs / 4 : 0)
-
-/* A C type for declaring a variable that is used as the first argument of
- `FUNCTION_ARG' and other related values. For some target machines, the
- type `int' suffices and can hold the number of bytes of argument so far.
-
- On the ARM, this is the number of bytes of arguments scanned so far. */
-typedef struct
-{
- /* This is the number of registers of arguments scanned so far. */
- int nregs;
- /* One of CALL_NORMAL, CALL_LONG or CALL_SHORT . */
- int call_cookie;
-} CUMULATIVE_ARGS;
-
-
-/* Initialize a variable CUM of type CUMULATIVE_ARGS
- for a call to a function whose data type is FNTYPE.
- For a library call, FNTYPE is 0.
- On the ARM, the offset starts at 0. */
-#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT) \
- ((CUM).nregs = (((FNTYPE) && aggregate_value_p (TREE_TYPE ((FNTYPE)))) \
- ? 4 : 0), \
- (CUM).call_cookie = \
- (((FNTYPE) && lookup_attribute ("short_call", TYPE_ATTRIBUTES (FNTYPE))) \
- ? CALL_SHORT \
- : (((FNTYPE) && lookup_attribute ("long_call", \
- TYPE_ATTRIBUTES (FNTYPE)))\
- || TARGET_LONG_CALLS) \
- ? CALL_LONG \
- : CALL_NORMAL))
-
-/* Update the data in CUM to advance over an argument
- of mode MODE and data type TYPE.
- (TYPE is null for libcalls where that information may not be available.) */
-#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \
- (CUM).nregs += ((MODE) != BLKmode \
- ? (GET_MODE_SIZE (MODE) + 3) & ~3 \
- : (int_size_in_bytes (TYPE) + 3) & ~3) \
-
-#define FUNCTION_ARG_REGNO_P(REGNO) \
- ((REGNO) >=0 && (REGNO) <= 3)
-
-#define FUNCTION_VALUE(VALTYPE,FUNC) gen_rtx (REG, TYPE_MODE (VALTYPE), 0)
-
-#define LIBCALL_VALUE(MODE) gen_rtx (REG, (MODE), 0)
-
-#define FUNCTION_VALUE_REGNO_P(REGNO) ((REGNO) == 0)
-
- /* How large values are returned */
-/* A C expression which can inhibit the returning of certain function values
- in registers, based on the type of value. */
-#define RETURN_IN_MEMORY(TYPE) thumb_return_in_memory (TYPE)
-
-/* Define DEFAULT_PCC_STRUCT_RETURN to 1 if all structure and union return
- values must be in memory. On the ARM, they need only do so if larger
- than a word, or if they contain elements offset from zero in the struct. */
-#define DEFAULT_PCC_STRUCT_RETURN 0
-
-
-#define STRUCT_VALUE_REGNUM 0
-
-#define FUNCTION_PROLOGUE(FILE,SIZE) thumb_function_prologue((FILE),(SIZE))
-
-#define FUNCTION_EPILOGUE(FILE,SIZE) thumb_function_epilogue((FILE),(SIZE))
-
-/* Implementing the Varargs Macros */
-
-#define SETUP_INCOMING_VARARGS(CUM,MODE,TYPE,PRETEND_SIZE,NO_RTL) \
-{ \
- extern int current_function_anonymous_args; \
- current_function_anonymous_args = 1; \
- if ((CUM).nregs < 16) \
- (PRETEND_SIZE) = 16 - (CUM).nregs; \
-}
-
-/* Trampolines for nested functions */
-
-/* Output assembler code for a block containing the constant parts of
- a trampoline, leaving space for the variable parts.
-
- On the Thumb we always switch into ARM mode to execute the trampoline.
- Why - because it is easier. This code will always be branched to via
- a BX instruction and since the compiler magically generates the address
- of the function the linker has no opportunity to ensure that the
- bottom bit is set. Thus the processor will be in ARM mode when it
- reaches this code. So we duplicate the ARM trampoline code and add
- a switch into Thumb mode as well.
-
- On the ARM, (if r8 is the static chain regnum, and remembering that
- referencing pc adds an offset of 8) the trampoline looks like:
- ldr r8, [pc, #0]
- ldr pc, [pc]
- .word static chain value
- .word function's address
- ??? FIXME: When the trampoline returns, r8 will be clobbered. */
-#define TRAMPOLINE_TEMPLATE(FILE) \
-{ \
- fprintf ((FILE), "\t.code 32\n"); \
- fprintf ((FILE), ".Ltrampoline_start:\n"); \
- fprintf ((FILE), "\tldr\t%s, [%spc, #8]\n", \
- reg_names[STATIC_CHAIN_REGNUM], REGISTER_PREFIX); \
- fprintf ((FILE), "\tldr\t%sip, [%spc, #8]\n", \
- REGISTER_PREFIX, REGISTER_PREFIX); \
- fprintf ((FILE), "\torr\t%sip, %sip, #1\n", \
- REGISTER_PREFIX, REGISTER_PREFIX); \
- fprintf ((FILE), "\tbx\t%sip\n", REGISTER_PREFIX); \
- fprintf ((FILE), "\t.word\t0\n"); \
- fprintf ((FILE), "\t.word\t0\n"); \
- fprintf ((FILE), "\t.code 16\n"); \
-}
-
-/* Length in units of the trampoline for entering a nested function. */
-#define TRAMPOLINE_SIZE 24
-
-/* Alignment required for a trampoline in units. */
-#define TRAMPOLINE_ALIGN 4
-
-#define INITIALIZE_TRAMPOLINE(ADDR,FNADDR,CHAIN) \
-{ \
- emit_move_insn (gen_rtx (MEM, SImode, plus_constant ((ADDR), 16)), \
- (CHAIN)); \
- emit_move_insn (gen_rtx (MEM, SImode, plus_constant ((ADDR), 20)), \
- (FNADDR)); \
-}
-
-
-/* Implicit Calls to Library Routines */
-
-#define TARGET_MEM_FUNCTIONS 1
-
-#define OVERRIDE_OPTIONS thumb_override_options ()
-
-
-/* Addressing Modes */
-
-#define HAVE_POST_INCREMENT 1
-
-#define CONSTANT_ADDRESS_P(X) \
- (GET_CODE (X) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (X))
-
-#define MAX_REGS_PER_ADDRESS 2
-
-#ifdef REG_OK_STRICT
-
-#define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P (REGNO (X))
-#define REG_OK_FOR_INDEX_P(X) REGNO_OK_FOR_INDEX_P (REGNO (X))
-
-#define REG_MODE_OK_FOR_BASE_P(X,MODE) \
- REGNO_MODE_OK_FOR_BASE_P (REGNO (X), MODE)
-
-#else /* REG_OK_STRICT */
-
-#define REG_OK_FOR_BASE_P(X) \
- (REGNO (X) < 8 || REGNO (X) == STACK_POINTER_REGNUM \
- || (X) == arg_pointer_rtx \
- || REGNO (X) >= FIRST_PSEUDO_REGISTER)
-
-#define REG_MODE_OK_FOR_BASE_P(X,MODE) \
- (REGNO (X) < 8 \
- || REGNO (X) >= FIRST_PSEUDO_REGISTER \
- || (GET_MODE_SIZE (MODE) >= 4 \
- && (REGNO (X) == STACK_POINTER_REGNUM \
- || (X) == arg_pointer_rtx)))
-
-#define REG_OK_FOR_INDEX_P(X) \
- (REGNO (X) < 8 \
- || REGNO (X) >= FIRST_PSEUDO_REGISTER)
-
-#endif /* REG_OK_STRICT */
-
-/* In a REG+REG address, both must be INDEX registers. */
-#define REG_OK_FOR_INDEXED_BASE_P(X) REG_OK_FOR_INDEX_P(X)
-
-#define LEGITIMATE_OFFSET(MODE,VAL) \
-(GET_MODE_SIZE (MODE) == 1 ? ((unsigned HOST_WIDE_INT) (VAL) < 32) \
- : GET_MODE_SIZE (MODE) == 2 ? ((unsigned HOST_WIDE_INT) (VAL) < 64 \
- && ((VAL) & 1) == 0) \
- : ((VAL) >= 0 && ((VAL) + GET_MODE_SIZE (MODE)) <= 128 \
- && ((VAL) & 3) == 0))
-
-/* The AP may be eliminated to either the SP or the FP, so we use the
- least common denominator, e.g. SImode, and offsets from 0 to 64. */
-
-/* ??? Verify whether the above is the right approach. */
-
-/* ??? Also, the FP may be eliminated to the SP, so perhaps that
- needs special handling also. */
-
-/* ??? Look at how the mips16 port solves this problem. It probably uses
- better ways to solve some of these problems. */
-
-/* Although it is not incorrect, we don't accept QImode and HImode
- addresses based on the frame pointer or arg pointer until the reload pass starts.
- This is so that eliminating such addresses into stack based ones
- won't produce impossible code. */
-#define GO_IF_LEGITIMATE_ADDRESS(MODE,X,WIN) \
-{ \
- /* ??? Not clear if this is right. Experiment. */ \
- if (GET_MODE_SIZE (MODE) < 4 \
- && ! (reload_in_progress || reload_completed) \
- && (reg_mentioned_p (frame_pointer_rtx, X) \
- || reg_mentioned_p (arg_pointer_rtx, X) \
- || reg_mentioned_p (virtual_incoming_args_rtx, X) \
- || reg_mentioned_p (virtual_outgoing_args_rtx, X) \
- || reg_mentioned_p (virtual_stack_dynamic_rtx, X) \
- || reg_mentioned_p (virtual_stack_vars_rtx, X))) \
- ; \
- /* Accept any base register. SP only in SImode or larger. */ \
- else if (GET_CODE (X) == REG && REG_MODE_OK_FOR_BASE_P(X, MODE)) \
- goto WIN; \
- /* This is PC relative data before MACHINE_DEPENDENT_REORG runs. */ \
- else if (GET_MODE_SIZE (MODE) >= 4 && CONSTANT_P (X) \
- && CONSTANT_POOL_ADDRESS_P (X)) \
- goto WIN; \
- /* This is PC relative data after MACHINE_DEPENDENT_REORG runs. */ \
- else if (GET_MODE_SIZE (MODE) >= 4 && reload_completed \
- && (GET_CODE (X) == LABEL_REF \
- || (GET_CODE (X) == CONST \
- && GET_CODE (XEXP (X, 0)) == PLUS \
- && GET_CODE (XEXP (XEXP (X, 0), 0)) == LABEL_REF \
- && GET_CODE (XEXP (XEXP (X, 0), 1)) == CONST_INT))) \
- goto WIN; \
- /* Post-inc indexing only supported for SImode and larger. */ \
- else if (GET_CODE (X) == POST_INC && GET_MODE_SIZE (MODE) >= 4 \
- && GET_CODE (XEXP (X, 0)) == REG \
- && REG_OK_FOR_INDEX_P (XEXP (X, 0))) \
- goto WIN; \
- else if (GET_CODE (X) == PLUS) \
- { \
- /* REG+REG address can be any two index registers. */ \
- /* ??? REG+REG addresses have been completely disabled before \
- reload completes, because we do not have enough available \
- reload registers. We only have 3 guaranteed reload registers \
- (NONARG_LO_REGS - the frame pointer), but we need at least 4 \
- to support REG+REG addresses. We have left them enabled after \
- reload completes, in the hope that reload_cse_regs and related \
- routines will be able to create them after the fact. It is \
- probably possible to support REG+REG addresses with additional \
- reload work, but I do not not have enough time to attempt such \
- a change at this time. */ \
- /* ??? Normally checking the mode here is wrong, since it isn't \
- impossible to use REG+REG with DFmode. However, the movdf \
- pattern requires offsettable addresses, and REG+REG is not \
- offsettable, so it must be rejected somehow. Trying to use \
- 'o' fails, because offsettable_address_p does a QImode check. \
- QImode is not valid for stack addresses, and has a smaller \
- range for non-stack bases, and this causes valid addresses \
- to be rejected. So we just eliminate REG+REG here by checking \
- the mode. */ \
- /* We also disallow FRAME+REG addressing since we know that FRAME \
- will be replaced with STACK, and SP relative addressing only \
- permits SP+OFFSET. */ \
- if (GET_MODE_SIZE (MODE) <= 4 \
- /* ??? See comment above. */ \
- && reload_completed \
- && GET_CODE (XEXP (X, 0)) == REG \
- && GET_CODE (XEXP (X, 1)) == REG \
- && XEXP (X, 0) != frame_pointer_rtx \
- && XEXP (X, 1) != frame_pointer_rtx \
- && XEXP (X, 0) != virtual_stack_vars_rtx \
- && XEXP (X, 1) != virtual_stack_vars_rtx \
- && REG_OK_FOR_INDEX_P (XEXP (X, 0)) \
- && REG_OK_FOR_INDEX_P (XEXP (X, 1))) \
- goto WIN; \
- /* REG+const has 5-7 bit offset for non-SP registers. */ \
- else if (GET_CODE (XEXP (X, 0)) == REG \
- && (REG_OK_FOR_INDEX_P (XEXP (X, 0)) \
- || XEXP (X, 0) == arg_pointer_rtx) \
- && GET_CODE (XEXP (X, 1)) == CONST_INT \
- && LEGITIMATE_OFFSET (MODE, INTVAL (XEXP (X, 1)))) \
- goto WIN; \
- /* REG+const has 10 bit offset for SP, but only SImode and \
- larger is supported. */ \
- /* ??? Should probably check for DI/DFmode overflow here \
- just like GO_IF_LEGITIMATE_OFFSET does. */ \
- else if (GET_CODE (XEXP (X, 0)) == REG \
- && REGNO (XEXP (X, 0)) == STACK_POINTER_REGNUM \
- && GET_MODE_SIZE (MODE) >= 4 \
- && GET_CODE (XEXP (X, 1)) == CONST_INT \
- && (unsigned HOST_WIDE_INT) INTVAL (XEXP (X, 1)) < 1024 \
- && (INTVAL (XEXP (X, 1)) & 3) == 0) \
- goto WIN; \
- } \
-}
-
-/* ??? If an HImode FP+large_offset address is converted to an HImode
- SP+large_offset address, then reload won't know how to fix it. It sees
- only that SP isn't valid for HImode, and so reloads the SP into an index
- register, but the resulting address is still invalid because the offset
- is too big. We fix it here instead by reloading the entire address. */
-/* We could probably achieve better results by defining PROMOTE_MODE to help
- cope with the variances between the Thumb's signed and unsigned byte and
- halfword load instructions. */
-#define LEGITIMIZE_RELOAD_ADDRESS(X,MODE,OPNUM,TYPE,IND_LEVELS,WIN) \
-{ \
- if (GET_CODE (X) == PLUS \
- && GET_MODE_SIZE (MODE) < 4 \
- && GET_CODE (XEXP (X, 0)) == REG \
- && XEXP (X, 0) == stack_pointer_rtx \
- && GET_CODE (XEXP (X, 1)) == CONST_INT \
- && ! LEGITIMATE_OFFSET (MODE, INTVAL (XEXP (X, 1)))) \
- { \
- rtx orig_X = X; \
- X = copy_rtx (X); \
- push_reload (orig_X, NULL_RTX, &X, NULL_PTR, \
- BASE_REG_CLASS, \
- Pmode, VOIDmode, 0, 0, OPNUM, TYPE); \
- goto WIN; \
- } \
-}
-
-#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR,LABEL)
-
-#define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN)
-
-#define LEGITIMATE_CONSTANT_P(X) \
- (GET_CODE (X) == CONST_INT \
- || GET_CODE (X) == CONST_DOUBLE \
- || CONSTANT_ADDRESS_P (X))
-
-/* Flags for the call/call_value rtl operations set up by function_arg. */
-#define CALL_NORMAL 0x00000000 /* No special processing. */
-#define CALL_LONG 0x00000001 /* Always call indirect. */
-#define CALL_SHORT 0x00000002 /* Never call indirect. */
-
-#define ENCODE_SECTION_INFO(decl) \
-{ \
- ARM_ENCODE_CALL_TYPE (decl) \
-}
-
-/* A C expression whose value is nonzero if IDENTIFIER with arguments ARGS
- is a valid machine specific attribute for DECL.
- The attributes in ATTRIBUTES have previously been assigned to DECL. */
-int arm_valid_machine_type_attribute (/* union tree_node *, union tree_node *,
- union tree_node *,
- union tree_node * */);
-#define VALID_MACHINE_TYPE_ATTRIBUTE(DECL, ATTRIBUTES, IDENTIFIER, ARGS) \
-arm_valid_machine_type_attribute (DECL, ATTRIBUTES, IDENTIFIER, ARGS)
-
-/* If we are referencing a function that is weak then encode a long call
- flag in the function name, otherwise if the function is static or
- or known to be defined in this file then encode a short call flag.
- This macro is used inside the ENCODE_SECTION macro. */
-#define ARM_ENCODE_CALL_TYPE(decl) \
- if (TREE_CODE_CLASS (TREE_CODE (decl)) == 'd') \
- { \
- if (TREE_CODE (decl) == FUNCTION_DECL && DECL_WEAK (decl)) \
- arm_encode_call_attribute (decl, LONG_CALL_FLAG_CHAR); \
- else if (! TREE_PUBLIC (decl)) \
- arm_encode_call_attribute (decl, SHORT_CALL_FLAG_CHAR); \
- }
-
-/* Special characters prefixed to function names
- in order to encode attribute like information.
- Note, '@' and '*' have already been taken. */
-#define SHORT_CALL_FLAG_CHAR '^'
-#define LONG_CALL_FLAG_CHAR '#'
-
-#define ENCODED_SHORT_CALL_ATTR_P(SYMBOL_NAME) \
- (*(SYMBOL_NAME) == SHORT_CALL_FLAG_CHAR)
-
-#define ENCODED_LONG_CALL_ATTR_P(SYMBOL_NAME) \
- (*(SYMBOL_NAME) == LONG_CALL_FLAG_CHAR)
-
-#ifndef SUBTARGET_NAME_ENCODING_LENGTHS
-#define SUBTARGET_NAME_ENCODING_LENGTHS
-#endif
-
-/* This is a C fragement for the inside of a switch statement.
- Each case label should return the number of characters to
- be stripped from the start of a function's name, if that
- name starts with the indicated character. */
-#define ARM_NAME_ENCODING_LENGTHS \
- case SHORT_CALL_FLAG_CHAR: return 1; \
- case LONG_CALL_FLAG_CHAR: return 1; \
- case '*': return 1; \
- SUBTARGET_NAME_ENCODING_LENGTHS
-
-/* This has to be handled by a function because more than part of the
- ARM backend uses function name prefixes to encode attributes. */
-#undef STRIP_NAME_ENCODING
-#define STRIP_NAME_ENCODING(VAR, SYMBOL_NAME) \
- (VAR) = arm_strip_name_encoding (SYMBOL_NAME)
-
-/* This is how to output a reference to a user-level label named NAME.
- `assemble_name' uses this. */
-#undef ASM_OUTPUT_LABELREF
-#define ASM_OUTPUT_LABELREF(FILE, NAME) \
- asm_fprintf (FILE, "%U%s", arm_strip_name_encoding (NAME))
-
-
-/* Condition Code Status */
-
-#define NOTICE_UPDATE_CC(EXP,INSN) \
-{ \
- if (get_attr_conds ((INSN)) != CONDS_UNCHANGED) \
- CC_STATUS_INIT; \
-}
-
-
-/* Describing Relative Costs of Operations */
-
-#define SLOW_BYTE_ACCESS 0
-
-#define SLOW_UNALIGNED_ACCESS 1
-
-#define NO_FUNCTION_CSE 1
-
-#define NO_RECURSIVE_FUNCTION_CSE 1
-
-#define REGISTER_MOVE_COST(FROM,TO) \
- (((FROM) == HI_REGS || (TO) == HI_REGS) ? 4 : 2)
-
-#define MEMORY_MOVE_COST(M,CLASS,IN) \
- ((GET_MODE_SIZE(M) < 4 ? 8 : 2 * GET_MODE_SIZE(M)) * (CLASS == LO_REGS ? 1 : 2))
-
-/* This will allow better space optimization when compiling with -O */
-#define BRANCH_COST (optimize > 1 ? 1 : 0)
-
-#define RTX_COSTS(X,CODE,OUTER) \
- case MULT: \
- if (GET_CODE (XEXP (X, 1)) == CONST_INT) \
- { \
- int cycles = 0; \
- unsigned HOST_WIDE_INT i = INTVAL (XEXP (X, 1)); \
- while (i) \
- { \
- i >>= 2; \
- cycles++; \
- } \
- return COSTS_N_INSNS (2) + cycles; \
- } \
- return COSTS_N_INSNS (1) + 16; \
- case ASHIFT: case ASHIFTRT: case LSHIFTRT: case ROTATERT: \
- case PLUS: case MINUS: case COMPARE: case NEG: case NOT: \
- return COSTS_N_INSNS (1); \
- case SET: \
- return (COSTS_N_INSNS (1) \
- + 4 * ((GET_CODE (SET_SRC (X)) == MEM) \
- + GET_CODE (SET_DEST (X)) == MEM))
-
-#define CONST_COSTS(X,CODE,OUTER) \
- case CONST_INT: \
- if ((OUTER) == SET) \
- { \
- if ((unsigned HOST_WIDE_INT) INTVAL (X) < 256) \
- return 0; \
- if (thumb_shiftable_const (INTVAL (X))) \
- return COSTS_N_INSNS (2); \
- return COSTS_N_INSNS (3); \
- } \
- else if (OUTER == PLUS \
- && INTVAL (X) < 256 && INTVAL (X) > -256) \
- return 0; \
- else if (OUTER == COMPARE \
- && (unsigned HOST_WIDE_INT) INTVAL (X) < 256) \
- return 0; \
- else if (OUTER == ASHIFT || OUTER == ASHIFTRT \
- || OUTER == LSHIFTRT) \
- return 0; \
- return COSTS_N_INSNS (2); \
- case CONST: \
- case CONST_DOUBLE: \
- case LABEL_REF: \
- case SYMBOL_REF: \
- return COSTS_N_INSNS(3);
-
-#define ADDRESS_COST(X) \
- ((GET_CODE (X) == REG \
- || (GET_CODE (X) == PLUS && GET_CODE (XEXP (X, 0)) == REG \
- && GET_CODE (XEXP (X, 1)) == CONST_INT)) \
- ? 1 : 2)
-
-
-/* Position Independent Code */
-
-#define PRINT_OPERAND(STREAM,X,CODE) \
- thumb_print_operand((STREAM), (X), (CODE))
-
-#define PRINT_OPERAND_ADDRESS(STREAM,X) \
-{ \
- if (GET_CODE ((X)) == REG) \
- fprintf ((STREAM), "[%s]", reg_names[REGNO ((X))]); \
- else if (GET_CODE ((X)) == POST_INC) \
- fprintf ((STREAM), "%s!", reg_names[REGNO (XEXP (X, 0))]); \
- else if (GET_CODE ((X)) == PLUS) \
- { \
- if (GET_CODE (XEXP ((X), 1)) == CONST_INT) \
- fprintf ((STREAM), "[%s, #%d]", \
- reg_names[REGNO (XEXP ((X), 0))], \
- (int) INTVAL (XEXP ((X), 1))); \
- else \
- fprintf ((STREAM), "[%s, %s]", \
- reg_names[REGNO (XEXP ((X), 0))], \
- reg_names[REGNO (XEXP ((X), 1))]); \
- } \
- else \
- output_addr_const ((STREAM), (X)); \
-}
-
-#define PRINT_OPERAND_PUNCT_VALID_P(CODE) ((CODE) == '@' || ((CODE) == '_'))
-
-/* Emit a special directive when defining a function name.
- This is used by the assembler to assit with interworking. */
-#define ASM_DECLARE_FUNCTION_NAME(file, name, 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)
-
-#define ASM_OUTPUT_REG_PUSH(STREAM,REGNO) \
- asm_fprintf ((STREAM), "\tpush {%R%s}\n", reg_names[(REGNO)])
-
-#define ASM_OUTPUT_REG_POP(STREAM,REGNO) \
- fprintf ((STREAM), "\tpop {%R%s}\n", reg_names[(REGNO)])
-
-#define FINAL_PRESCAN_INSN(INSN,OPVEC,NOPERANDS) \
- final_prescan_insn((INSN))
-
-/* Controlling Debugging Information Format */
-#define DBX_REGISTER_NUMBER(REGNO) (REGNO)
-
-/* Specific options for DBX Output */
-
-#define DBX_DEBUGGING_INFO 1
-
-#define DEFAULT_GDB_EXTENSIONS 1
-
-
-/* Cross Compilation and Floating Point */
-
-#define REAL_ARITHMETIC
-
-
-/* Miscellaneous Parameters */
-
-#define PREDICATE_CODES \
- {"s_register_operand", {SUBREG, REG}}, \
- {"thumb_cmp_operand", {SUBREG, REG, CONST_INT}},
-
-#define CASE_VECTOR_MODE Pmode
-
-#define WORD_REGISTER_OPERATIONS
-
-#define LOAD_EXTEND_OP(MODE) ZERO_EXTEND
-
-#define IMPLICIT_FIX_EXPR FIX_ROUND_EXPR
-
-#define EASY_DIV_EXPR TRUNC_DIV_EXPR
-
-#define MOVE_MAX 4
-
-#define TRULY_NOOP_TRUNCATION(OUTPREC,INPREC) 1
-
-#define STORE_FLAG_VALUE 1
-
-#define Pmode SImode
-
-#define FUNCTION_MODE SImode
-
-#define DOLLARS_IN_IDENTIFIERS 0
-
-#define NO_DOLLAR_IN_LABEL 1
-
-#define HAVE_ATEXIT
-
-/* The literal pool needs to reside in the text area due to the
- limited PC addressing range: */
-#define MACHINE_DEPENDENT_REORG(INSN) thumb_reorg ((INSN))
-
-
-/* Options specific to Thumb */
-
-/* True if a return instruction can be used in this function. */
-int thumb_trivial_epilogue ();
-#define USE_RETURN (reload_completed && thumb_trivial_epilogue ())
-
-extern char * thumb_unexpanded_epilogue ();
-extern char * output_move_mem_multiple ();
-extern char * thumb_load_double_from_address ();
-extern char * output_return ();
-extern int far_jump_used_p();
-extern int is_called_in_ARM_mode ();
-
-char *arm_strip_name_encoding (/* const char * */);
-int arm_is_longcall_p (/* rtx, int, int */);
-int s_register_operand (/* register rtx op, enum machine_mode mode */);
diff --git a/gcc/config/arm/thumb_020428.md b/gcc/config/arm/thumb_020428.md
deleted file mode 100755
index dedf42e..0000000
--- a/gcc/config/arm/thumb_020428.md
+++ /dev/null
@@ -1,1194 +0,0 @@
-;; thumb.md Machine description for ARM/Thumb processors
-;; Copyright (C) 1996, 1997, 1998, 2002 Free Software Foundation, Inc.
-;; The basis of this contribution was generated by
-;; Richard Earnshaw, Advanced RISC Machines Ltd
-
-;; 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.
-
-;; LENGTH of an instruction is 2 bytes
-(define_attr "length" "" (const_int 2))
-
-;; CONDS is set to UNCHANGED when an insn does not affect the condition codes
-;; Most insns change the condition codes
-(define_attr "conds" "changed,unchanged" (const_string "changed"))
-
-;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
-;; distant label.
-(define_attr "far_jump" "yes,no" (const_string "no"))
-
-;; Start with move insns
-
-(define_expand "movsi"
- [(set (match_operand:SI 0 "general_operand" "")
- (match_operand:SI 1 "general_operand" ""))]
- ""
- "
- if (! (reload_in_progress || reload_completed))
- {
- if (GET_CODE (operands[0]) != REG)
- operands[1] = force_reg (SImode, operands[1]);
- }
-")
-
-(define_insn "*movsi_insn"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l,m,*r,*h")
- (match_operand:SI 1 "general_operand" "l,I,J,K,>,l,mi,l,*h,*r"))]
- "register_operand (operands[0], SImode)
- || register_operand (operands[1], SImode)"
- "@
- add\\t%0, %1, #0
- mov\\t%0, %1
- #
- #
- ldmia\\t%1, {%0}
- stmia\\t%0, {%1}
- ldr\\t%0, %1
- str\\t%1, %0
- mov\\t%0, %1
- mov\\t%0, %1"
-[(set_attr "length" "2,2,4,4,2,2,2,2,2,2")])
-
-(define_split
- [(set (match_operand:SI 0 "register_operand" "")
- (match_operand:SI 1 "const_int_operand" ""))]
- "thumb_shiftable_const (INTVAL (operands[1]))"
- [(set (match_dup 0) (match_dup 1))
- (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
- "
-{
- unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
- unsigned HOST_WIDE_INT mask = 0xff;
- int i;
- for (i = 0; i < 25; i++)
- if ((val & (mask << i)) == val)
- break;
-
- if (i == 0)
- FAIL;
-
- operands[1] = GEN_INT (val >> i);
- operands[2] = GEN_INT (i);
-}")
-
-(define_split
- [(set (match_operand:SI 0 "register_operand" "")
- (match_operand:SI 1 "const_int_operand" ""))]
- "INTVAL (operands[1]) < 0 && INTVAL (operands[1]) > -256"
- [(set (match_dup 0) (match_dup 1))
- (set (match_dup 0) (neg:SI (match_dup 0)))]
- "
- operands[1] = GEN_INT (- INTVAL (operands[1]));
-")
-
-;;(define_expand "reload_outsi"
-;; [(set (match_operand:SI 2 "register_operand" "=&l")
-;; (match_operand:SI 1 "register_operand" "h"))
-;; (set (match_operand:SI 0 "reload_memory_operand" "=o")
-;; (match_dup 2))]
-;; ""
-;; "
-;;/* thumb_reload_out_si (operands);
-;; DONE; */
-;;")
-
-(define_expand "movhi"
- [(set (match_operand:HI 0 "general_operand" "")
- (match_operand:HI 1 "general_operand" ""))]
- ""
- "
-{
- if (! (reload_in_progress || reload_completed))
- {
- if (GET_CODE (operands[0]) != REG)
- operands[1] = force_reg (HImode, operands[1]);
-
- /* ??? We shouldn't really get invalid addresses here, but this can
- happen if we are passed a SP (never OK for HImode/QImode) or virtual
- register (rejected by GO_IF_LEGITIMATE_ADDRESS for HImode/QImode)
- relative address. */
- /* ??? This should perhaps be fixed elsewhere, for instance, in
- fixup_stack_1, by checking for other kinds of invalid addresses,
- e.g. a bare reference to a virtual register. This may confuse the
- alpha though, which must handle this case differently. */
- if (GET_CODE (operands[0]) == MEM
- && ! memory_address_p (GET_MODE (operands[0]),
- XEXP (operands[0], 0)))
- {
- rtx temp = copy_to_reg (XEXP (operands[0], 0));
- operands[0] = change_address (operands[0], VOIDmode, temp);
- }
- if (GET_CODE (operands[1]) == MEM
- && ! memory_address_p (GET_MODE (operands[1]),
- XEXP (operands[1], 0)))
- {
- rtx temp = copy_to_reg (XEXP (operands[1], 0));
- operands[1] = change_address (operands[1], VOIDmode, temp);
- }
- }
- /* Handle loading a large integer during reload */
- else if (GET_CODE (operands[1]) == CONST_INT
- && ! CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
- {
- /* Writing a constant to memory needs a scratch, which should
- be handled with SECONDARY_RELOADs. */
- if (GET_CODE (operands[0]) != REG)
- abort ();
-
- operands[0] = gen_rtx (SUBREG, SImode, operands[0], 0);
- emit_insn (gen_movsi (operands[0], operands[1]));
- DONE;
- }
-}")
-
-(define_insn "*movhi_insn"
- [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
- (match_operand:HI 1 "general_operand" "l,m,l,*h,*r,I"))]
- "register_operand (operands[0], HImode)
- || register_operand (operands[1], HImode)"
- "@
- add\\t%0, %1, #0
- ldrh\\t%0, %1
- strh\\t%1, %0
- mov\\t%0, %1
- mov\\t%0, %1
- mov\\t%0, %1")
-
-(define_expand "movqi"
- [(set (match_operand:QI 0 "general_operand" "")
- (match_operand:QI 1 "general_operand" ""))]
- ""
- "
-{
- if (! (reload_in_progress || reload_completed))
- {
- if (GET_CODE (operands[0]) != REG)
- operands[1] = force_reg (QImode, operands[1]);
-
- /* ??? We shouldn't really get invalid addresses here, but this can
- happen if we are passed a SP (never OK for HImode/QImode) or virtual
- register (rejected by GO_IF_LEGITIMATE_ADDRESS for HImode/QImode)
- relative address. */
- /* ??? This should perhaps be fixed elsewhere, for instance, in
- fixup_stack_1, by checking for other kinds of invalid addresses,
- e.g. a bare reference to a virtual register. This may confuse the
- alpha though, which must handle this case differently. */
- if (GET_CODE (operands[0]) == MEM
- && ! memory_address_p (GET_MODE (operands[0]),
- XEXP (operands[0], 0)))
- {
- rtx temp = copy_to_reg (XEXP (operands[0], 0));
- operands[0] = change_address (operands[0], VOIDmode, temp);
- }
- if (GET_CODE (operands[1]) == MEM
- && ! memory_address_p (GET_MODE (operands[1]),
- XEXP (operands[1], 0)))
- {
- rtx temp = copy_to_reg (XEXP (operands[1], 0));
- operands[1] = change_address (operands[1], VOIDmode, temp);
- }
- }
- /* Handle loading a large integer during reload */
- else if (GET_CODE (operands[1]) == CONST_INT
- && ! CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
- {
- /* Writing a constant to memory needs a scratch, which should
- be handled with SECONDARY_RELOADs. */
- if (GET_CODE (operands[0]) != REG)
- abort ();
-
- operands[0] = gen_rtx (SUBREG, SImode, operands[0], 0);
- emit_insn (gen_movsi (operands[0], operands[1]));
- DONE;
- }
-}")
-
-(define_insn "*movqi_insn"
- [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
- (match_operand:QI 1 "general_operand" "l,m,l,*h,*r,I"))]
- "register_operand (operands[0], QImode)
- || register_operand (operands[1], QImode)"
- "@
- add\\t%0, %1, #0
- ldrb\\t%0, %1
- strb\\t%1, %0
- mov\\t%0, %1
- mov\\t%0, %1
- mov\\t%0, %1")
-
-(define_expand "movdi"
- [(set (match_operand:DI 0 "general_operand" "")
- (match_operand:DI 1 "general_operand" ""))]
- ""
- "
- if (! (reload_in_progress || reload_completed))
- {
- if (GET_CODE (operands[0]) != REG)
- operands[1] = force_reg (DImode, operands[1]);
- }
-")
-
-;;; ??? This should have alternatives for constants.
-;;; ??? This was originally identical to the movdf_insn pattern.
-;;; ??? The 'i' constraint looks funny, but it should always be replaced by
-;;; thumb_reorg with a memory reference.
-(define_insn "*movdi_insn"
- [(set (match_operand:DI 0 "general_operand" "=l,l,l,l,>,l,m,*r")
- (match_operand:DI 1 "general_operand" "l,I,J,>,l,mi,l,*r"))]
- "register_operand (operands[0], DImode)
- || register_operand (operands[1], DImode)"
- "*
-{
- switch (which_alternative)
- {
- case 0:
- if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
- return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
- return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
- case 1:
- return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
- case 2:
- operands[1] = GEN_INT (- INTVAL (operands[1]));
- return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
- case 3:
- return \"ldmia\\t%1, {%0, %H0}\";
- case 4:
- return \"stmia\\t%0, {%1, %H1}\";
- case 5:
- return thumb_load_double_from_address (operands);
- case 6:
- operands[2] = gen_rtx (MEM, SImode, plus_constant (XEXP (operands[0], 0), 4));
- output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
- return \"\";
- case 7:
- if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
- return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
- return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
- }
-}"[(set_attr "length" "4,4,6,2,2,6,4,4")])
-
-(define_expand "movdf"
- [(set (match_operand:DF 0 "general_operand" "")
- (match_operand:DF 1 "general_operand" ""))]
- ""
- "
- if (! (reload_in_progress || reload_completed))
- {
- if (GET_CODE (operands[0]) != REG)
- operands[1] = force_reg (DFmode, operands[1]);
- }
-")
-
-;;; ??? This should have alternatives for constants.
-;;; ??? This was originally identical to the movdi_insn pattern.
-;;; ??? The 'F' constraint looks funny, but it should always be replaced by
-;;; thumb_reorg with a memory reference.
-(define_insn "*movdf_insn"
- [(set (match_operand:DF 0 "general_operand" "=l,l,>,l,m,*r")
- (match_operand:DF 1 "general_operand" "l,>,l,mF,l,*r"))]
- "register_operand (operands[0], DFmode)
- || register_operand (operands[1], DFmode)"
- "*
- switch (which_alternative)
- {
- case 0:
- if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
- return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
- return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
- case 1:
- return \"ldmia\\t%1, {%0, %H0}\";
- case 2:
- return \"stmia\\t%0, {%1, %H1}\";
- case 3:
- return thumb_load_double_from_address (operands);
- case 4:
- operands[2] = gen_rtx (MEM, SImode, plus_constant (XEXP (operands[0], 0), 4));
- output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
- return \"\";
- case 5:
- if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
- return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
- return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
- }
-"[(set_attr "length" "4,2,2,6,4,4")])
-
-(define_expand "movsf"
- [(set (match_operand:SF 0 "general_operand" "")
- (match_operand:SF 1 "general_operand" ""))]
- ""
- "
- if (! (reload_in_progress || reload_completed))
- {
- if (GET_CODE (operands[0]) != REG)
- operands[1] = force_reg (SFmode, operands[1]);
- }
-")
-
-;;; ??? This should have alternatives for constants.
-(define_insn "*movsf_insn"
- [(set (match_operand:SF 0 "nonimmediate_operand" "=l,l,>,l,m,*r,*h")
- (match_operand:SF 1 "general_operand" "l,>,l,mF,l,*h,*r"))]
- "register_operand (operands[0], SFmode)
- || register_operand (operands[1], SFmode)"
- "@
- add\\t%0, %1, #0
- ldmia\\t%1, {%0}
- stmia\\t%0, {%1}
- ldr\\t%0, %1
- str\\t%1, %0
- mov\\t%0, %1
- mov\\t%0, %1")
-
-;; Widening move insns
-
-(define_expand "zero_extendhisi2"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
- ""
- "
- if (GET_CODE (operands[1]) != MEM)
- {
- rtx temp = gen_reg_rtx (SImode);
-
- operands[1] = force_reg (HImode, operands[1]);
- operands[1] = gen_lowpart (SImode, operands[1]);
- emit_insn (gen_ashlsi3 (temp, operands[1], GEN_INT (16)));
- emit_insn (gen_lshrsi3 (operands[0], temp, GEN_INT (16)));
- DONE;
- }
-")
-
-(define_insn "*zero_extendhisi2_insn"
- [(set (match_operand:SI 0 "s_register_operand" "=l")
- (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
- ""
- "ldrh\\t%0, %1")
-
-(define_expand "zero_extendqisi2"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
- ""
- "
- if (GET_CODE (operands[1]) != MEM)
- {
- rtx temp = gen_reg_rtx (SImode);
-
- operands[1] = force_reg (QImode, operands[1]);
- operands[1] = gen_lowpart (SImode, operands[1]);
- emit_insn (gen_ashlsi3 (temp, operands[1], GEN_INT (24)));
- emit_insn (gen_lshrsi3 (operands[0], temp, GEN_INT (24)));
- DONE;
- }
-")
-
-(define_insn "*zero_extendqisi2_insn"
- [(set (match_operand:SI 0 "s_register_operand" "=l")
- (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
- ""
- "ldrb\\t%0, %1")
-
-(define_expand "extendhisi2"
- [(parallel [(set (match_operand:SI 0 "s_register_operand" "")
- (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))
- (clobber (match_scratch:SI 2 ""))])]
- ""
- "
- if (GET_CODE (operands[1]) != MEM)
- {
- rtx temp = gen_reg_rtx (SImode);
-
- operands[1] = force_reg (HImode, operands[1]);
- operands[1] = gen_lowpart (SImode, operands[1]);
- emit_insn (gen_ashlsi3 (temp, operands[1], GEN_INT (16)));
- emit_insn (gen_ashrsi3 (operands[0], temp, GEN_INT (16)));
- DONE;
- }
-")
-
-(define_insn "*extendhisi2_insn"
- [(set (match_operand:SI 0 "s_register_operand" "=l")
- (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
- (clobber (match_scratch:SI 2 "=&l"))]
- ""
- "*
-{
- rtx ops[4];
- /* This code used to try to use 'V', and fix the address only if it was
- offsettable, but this fails for e.g. REG+48 because 48 is outside the
- range of QImode offsets, and offsettable_address_p does a QImode
- address check. */
-
- if (GET_CODE (XEXP (operands[1], 0)) == PLUS)
- {
- ops[1] = XEXP (XEXP (operands[1], 0), 0);
- ops[2] = XEXP (XEXP (operands[1], 0), 1);
- }
- else
- {
- ops[1] = XEXP (operands[1], 0);
- ops[2] = const0_rtx;
- }
- if (GET_CODE (ops[2]) == REG)
- return \"ldrsh\\t%0, %1\";
-
- ops[0] = operands[0];
- ops[3] = operands[2];
- output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
- return \"\";
-}"
-[(set_attr "length" "4")])
-
-(define_expand "extendqisi2"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
- ""
- "
- if (GET_CODE (operands[1]) != MEM)
- {
- rtx temp = gen_reg_rtx (SImode);
-
- operands[1] = force_reg (QImode, operands[1]);
- operands[1] = gen_lowpart (SImode, operands[1]);
- emit_insn (gen_ashlsi3 (temp, operands[1], GEN_INT (24)));
- emit_insn (gen_ashrsi3 (operands[0], temp, GEN_INT (24)));
- DONE;
- }
-")
-
-(define_insn "*extendqisi2_insn"
- [(set (match_operand:SI 0 "s_register_operand" "=l,l")
- (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
- ""
- "*
-{
- rtx ops[3];
-
- if (which_alternative == 0)
- return \"ldrsb\\t%0, %1\";
- ops[0] = operands[0];
- if (GET_CODE (XEXP (operands[1], 0)) == PLUS)
- {
- ops[1] = XEXP (XEXP (operands[1], 0), 0);
- ops[2] = XEXP (XEXP (operands[1], 0), 1);
-
- if (GET_CODE (ops[1]) == REG && GET_CODE (ops[2]) == REG)
- output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
- else if (GET_CODE (ops[1]) == REG)
- {
- if (REGNO (ops[1]) == REGNO (operands[0]))
- output_asm_insn (\"ldrb\\t%0, [%1, %2]\;lsl\\t%0, %0, #24\;asr\\t%0, %0, #24\", ops);
- else
- output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
- }
- else
- {
- if (REGNO (ops[2]) == REGNO (operands[0]))
- output_asm_insn (\"ldrb\\t%0, [%2, %1]\;lsl\\t%0, %0, #24\;asr\\t%0, %0, #24\", ops);
- else
- output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
- }
- }
- else if (REGNO (operands[0]) == REGNO (XEXP (operands[1], 0)))
- {
- output_asm_insn (\"ldrb\\t%0, [%0, #0]\;lsl\\t%0, %0, #24\;asr\\t%0, %0, #24\", ops);
- }
- else
- {
- ops[1] = XEXP (operands[1], 0);
- ops[2] = const0_rtx;
- output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
- }
- return \"\";
-}"
-[(set_attr "length" "2,6")])
-
-;; We don't really have extzv, but defining this using shifts helps
-;; to reduce register pressure later on.
-
-(define_expand "extzv"
- [(set (match_dup 4)
- (ashift:SI (match_operand:SI 1 "register_operand" "")
- (match_operand:SI 2 "const_int_operand" "")))
- (set (match_operand:SI 0 "register_operand" "")
- (lshiftrt:SI (match_dup 4)
- (match_operand:SI 3 "const_int_operand" "")))]
- ""
- "
-{
- HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
- HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
- operands[3] = GEN_INT (rshift);
- if (lshift == 0)
- {
- emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
- DONE;
- }
- operands[2] = GEN_INT (lshift);
- operands[4] = gen_reg_rtx (SImode);
-}
-")
-
-;; Block-move insns
-
-(define_expand "movstrqi"
- [(match_operand:BLK 0 "general_operand" "")
- (match_operand:BLK 1 "general_operand" "")
- (match_operand:SI 2 "" "")
- (match_operand:SI 3 "const_int_operand" "")]
- ""
- "
- if (INTVAL (operands[3]) != 4
- || GET_CODE (operands[2]) != CONST_INT
- || INTVAL (operands[2]) > 48)
- FAIL;
-
- thumb_expand_movstrqi (operands);
- DONE;
-")
-
-(define_insn "movmem12b"
- [(set (mem:SI (match_operand:SI 0 "register_operand" "+&l"))
- (mem:SI (match_operand:SI 1 "register_operand" "+&l")))
- (set (mem:SI (plus:SI (match_dup 0) (const_int 4)))
- (mem:SI (plus:SI (match_dup 1) (const_int 4))))
- (set (mem:SI (plus:SI (match_dup 0) (const_int 8)))
- (mem:SI (plus:SI (match_dup 1) (const_int 8))))
- (set (match_dup 0) (plus:SI (match_dup 0) (const_int 12)))
- (set (match_dup 1) (plus:SI (match_dup 1) (const_int 12)))
- (clobber (match_scratch:SI 2 "=&l"))
- (clobber (match_scratch:SI 3 "=&l"))
- (clobber (match_scratch:SI 4 "=&l"))]
- ""
- "* return output_move_mem_multiple (3, operands);"
-[(set_attr "length" "4")])
-
-(define_insn "movmem8b"
- [(set (mem:SI (match_operand:SI 0 "register_operand" "+&l"))
- (mem:SI (match_operand:SI 1 "register_operand" "+&l")))
- (set (mem:SI (plus:SI (match_dup 0) (const_int 4)))
- (mem:SI (plus:SI (match_dup 1) (const_int 4))))
- (set (match_dup 0) (plus:SI (match_dup 0) (const_int 8)))
- (set (match_dup 1) (plus:SI (match_dup 1) (const_int 8)))
- (clobber (match_scratch:SI 2 "=&l"))
- (clobber (match_scratch:SI 3 "=&l"))]
- ""
- "* return output_move_mem_multiple (2, operands);"
-[(set_attr "length" "4")])
-
-;; Arithmetic insns
-
-(define_insn "adddi3"
- [(set (match_operand:DI 0 "s_register_operand" "=l")
- (plus:DI (match_operand:DI 1 "s_register_operand" "%0")
- (match_operand:DI 2 "s_register_operand" "l")))]
- ""
- "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
-[(set_attr "conds" "changed")
- (set_attr "length" "8")])
-
-;; register group 'k' is a single register group containing only the stack
-;; register. Trying to reload it will always fail catastrophically,
-;; so never allow those alternatives to match if reloading is needed.
-(define_insn "addsi3"
- [(set (match_operand:SI 0 "s_register_operand" "=l,l,l,*r,*h,l,!k")
- (plus:SI (match_operand:SI 1 "s_register_operand" "%0,0,l,*0,*0,!k,!k")
- (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))]
- ""
- "*
- static char *asms[] =
-{
- \"add\\t%0, %0, %2\",
- \"sub\\t%0, %0, #%n2\",
- \"add\\t%0, %1, %2\",
- \"add\\t%0, %0, %2\",
- \"add\\t%0, %0, %2\",
- \"add\\t%0, %1, %2\",
- \"add\\t%0, %1, %2\"
-};
- if (which_alternative == 2 && GET_CODE (operands[2]) == CONST_INT
- && INTVAL (operands[2]) < 0)
- return \"sub\\t%0, %1, #%n2\";
- return asms[which_alternative];
-")
-
-; reloading and elimination of the frame pointer can sometimes cause this
-; optimization to be missed.
-(define_peephole
- [(set (match_operand:SI 0 "register_operand" "=l")
- (match_operand:SI 1 "const_int_operand" "M"))
- (set (match_dup 0)
- (plus:SI (match_dup 0) (match_operand:SI 2 "register_operand" "k")))]
- "REGNO (operands[2]) == STACK_POINTER_REGNUM
- && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
- && (INTVAL (operands[1]) & 3) == 0"
- "add\\t%0, %2, %1")
-
-(define_insn "subdi3"
- [(set (match_operand:DI 0 "s_register_operand" "=l")
- (minus:DI (match_operand:DI 1 "s_register_operand" "0")
- (match_operand:DI 2 "s_register_operand" "l")))]
- ""
- "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
-[(set_attr "conds" "changed")
- (set_attr "length" "8")])
-
-(define_insn "subsi3"
- [(set (match_operand:SI 0 "s_register_operand" "=l")
- (minus:SI (match_operand:SI 1 "s_register_operand" "l")
- (match_operand:SI 2 "s_register_operand" "l")))]
- ""
- "sub\\t%0, %1, %2")
-
-;; We must ensure that one input matches the output, and that the other input
-;; does not match the output. Using 0 satisfies the first, and using &
-;; satisfies the second. Unfortunately, this fails when operands 1 and 2
-;; are the same, because reload will make operand 0 match operand 1 without
-;; realizing that this conflicts with operand 2. We fix this by adding another
-;; alternative to match this case, and then `reload' it ourselves. This
-;; alternative must come first.
-(define_insn "mulsi3"
- [(set (match_operand:SI 0 "s_register_operand" "=&l,&l,&l")
- (mult:SI (match_operand:SI 1 "s_register_operand" "%l,*h,0")
- (match_operand:SI 2 "s_register_operand" "l,l,l")))]
- ""
- "*
-{
- if (which_alternative < 2)
- return \"mov\\t%0, %1\;mul\\t%0, %0, %2\";
- else
- return \"mul\\t%0, %0, %2\";
-}"
- [(set_attr "length" "4,4,2")])
-
-(define_insn "negsi2"
- [(set (match_operand:SI 0 "s_register_operand" "=l")
- (neg:SI (match_operand:SI 1 "s_register_operand" "l")))]
- ""
- "neg\\t%0, %1")
-
-;; Logical insns
-
-(define_expand "andsi3"
- [(set (match_operand:SI 0 "s_register_operand" "")
- (and:SI (match_operand:SI 1 "s_register_operand" "")
- (match_operand:SI 2 "nonmemory_operand" "")))]
- ""
- "
- if (GET_CODE (operands[2]) != CONST_INT)
- operands[2] = force_reg (SImode, operands[2]);
- else
- {
- int i;
- if (((unsigned HOST_WIDE_INT) ~ INTVAL (operands[2])) < 256)
- {
- operands[2] = force_reg (SImode, GEN_INT (~INTVAL (operands[2])));
- emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
- DONE;
- }
-
- for (i = 9; i <= 31; i++)
- if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
- {
- emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
- const0_rtx));
- DONE;
- }
- else if ((((HOST_WIDE_INT) 1) << i) - 1 == ~ INTVAL (operands[2]))
- {
- rtx shift = GEN_INT (i);
- rtx reg = gen_reg_rtx (SImode);
- emit_insn (gen_lshrsi3 (reg, operands[1], shift));
- emit_insn (gen_ashlsi3 (operands[0], reg, shift));
- DONE;
- }
-
- operands[2] = force_reg (SImode, operands[2]);
- }
-")
-
-(define_insn "*andsi3_insn"
- [(set (match_operand:SI 0 "s_register_operand" "=l")
- (and:SI (match_operand:SI 1 "s_register_operand" "%0")
- (match_operand:SI 2 "s_register_operand" "l")))]
- ""
- "and\\t%0, %0, %2")
-
-(define_insn "bicsi3"
- [(set (match_operand:SI 0 "s_register_operand" "=l")
- (and:SI (not:SI (match_operand:SI 1 "s_register_operand" "l"))
- (match_operand:SI 2 "s_register_operand" "0")))]
- ""
- "bic\\t%0, %0, %1")
-
-(define_insn "iorsi3"
- [(set (match_operand:SI 0 "s_register_operand" "=l")
- (ior:SI (match_operand:SI 1 "s_register_operand" "%0")
- (match_operand:SI 2 "s_register_operand" "l")))]
- ""
- "orr\\t%0, %0, %2")
-
-(define_insn "xorsi3"
- [(set (match_operand:SI 0 "s_register_operand" "=l")
- (xor:SI (match_operand:SI 1 "s_register_operand" "%0")
- (match_operand:SI 2 "s_register_operand" "l")))]
- ""
- "eor\\t%0, %0, %2")
-
-(define_insn "one_cmplsi2"
- [(set (match_operand:SI 0 "s_register_operand" "=l")
- (not:SI (match_operand:SI 1 "s_register_operand" "l")))]
- ""
- "mvn\\t%0, %1")
-
-;; Shift and rotation insns
-
-(define_insn "ashlsi3"
- [(set (match_operand:SI 0 "s_register_operand" "=l,l")
- (ashift:SI (match_operand:SI 1 "s_register_operand" "l,0")
- (match_operand:SI 2 "nonmemory_operand" "N,l")))]
- ""
- "@
- lsl\\t%0, %1, %2
- lsl\\t%0, %0, %2")
-
-(define_insn "ashrsi3"
- [(set (match_operand:SI 0 "s_register_operand" "=l,l")
- (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "l,0")
- (match_operand:SI 2 "nonmemory_operand" "N,l")))]
- ""
- "@
- asr\\t%0, %1, %2
- asr\\t%0, %0, %2")
-
-(define_insn "lshrsi3"
- [(set (match_operand:SI 0 "s_register_operand" "=l,l")
- (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "l,0")
- (match_operand:SI 2 "nonmemory_operand" "N,l")))]
- ""
- "@
- lsr\\t%0, %1, %2
- lsr\\t%0, %0, %2")
-
-(define_insn "rotrsi3"
- [(set (match_operand:SI 0 "s_register_operand" "=l")
- (rotatert:SI (match_operand:SI 1 "s_register_operand" "0")
- (match_operand:SI 2 "s_register_operand" "l")))]
- ""
- "ror\\t%0, %0, %2")
-
-;; Comparison insns
-
-(define_expand "cmpsi"
- [(set (cc0) (compare (match_operand:SI 0 "s_register_operand" "")
- (match_operand:SI 1 "nonmemory_operand" "")))]
- ""
- "
- if (GET_CODE (operands[1]) != REG && GET_CODE (operands[1]) != SUBREG)
- {
- if (GET_CODE (operands[1]) != CONST_INT
- || (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) >= 256)
- {
- if (GET_CODE (operands[1]) != CONST_INT
- || INTVAL (operands[1]) < -255
- || INTVAL (operands[1]) > 0)
- operands[1] = force_reg (SImode, operands[1]);
- else
- {
- operands[1] = force_reg (SImode,
- GEN_INT (- INTVAL (operands[1])));
- emit_insn (gen_cmnsi (operands[0], operands[1]));
- DONE;
- }
- }
- }
-")
-
-(define_insn "*cmpsi_insn"
- [(set (cc0) (compare (match_operand:SI 0 "s_register_operand" "l,*r,*h")
- (match_operand:SI 1 "thumb_cmp_operand" "lI,*h,*r")))]
- ""
- "@
- cmp\\t%0, %1
- cmp\\t%0, %1
- cmp\\t%0, %1")
-
-(define_insn "tstsi"
- [(set (cc0) (match_operand:SI 0 "s_register_operand" "l"))]
- ""
- "cmp\\t%0, #0")
-
-(define_insn "cmnsi"
- [(set (cc0) (compare (match_operand:SI 0 "s_register_operand" "l")
- (neg:SI (match_operand:SI 1 "s_register_operand" "l"))))]
- ""
- "cmn\\t%0, %1")
-
-;; Jump insns
-
-(define_insn "jump"
- [(set (pc) (label_ref (match_operand 0 "" "")))]
- ""
- "*
- if (get_attr_length (insn) == 2)
- return \"b\\t%l0\";
- return \"bl\\t%l0\\t%@ far jump\";
-"[(set (attr "far_jump")
- (if_then_else (eq_attr "length" "4")
- (const_string "yes")
- (const_string "no")))
- (set (attr "length")
- (if_then_else (and (ge (minus (match_dup 0) (pc)) (const_int -2048))
- (le (minus (match_dup 0) (pc)) (const_int 2044)))
- (const_int 2)
- (const_int 4)))])
-
-
-(define_expand "beq"
- [(set (pc) (if_then_else (eq (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_expand "bne"
- [(set (pc) (if_then_else (ne (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_expand "bge"
- [(set (pc) (if_then_else (ge (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_expand "ble"
- [(set (pc) (if_then_else (le (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_expand "bgt"
- [(set (pc) (if_then_else (gt (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_expand "blt"
- [(set (pc) (if_then_else (lt (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_expand "bgeu"
- [(set (pc) (if_then_else (geu (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_expand "bleu"
- [(set (pc) (if_then_else (leu (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_expand "bgtu"
- [(set (pc) (if_then_else (gtu (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_expand "bltu"
- [(set (pc) (if_then_else (ltu (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_insn "*cond_branch"
- [(set (pc) (if_then_else (match_operator 1 "comparison_operator"
- [(cc0) (const_int 0)])
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "*
- switch (get_attr_length (insn))
- {
- case 2: return \"b%d1\\t%l0\\t%@cond_branch\";
- case 4: return \"b%D1\\t.LCB%=\;b\\t%l0\\t%@long jump\\n.LCB%=:\";
- default: return \"b%D1\\t.LCB%=\;bl\\t%l0\\t%@far jump\\n.LCB%=:\";
- }
-"[(set (attr "far_jump")
- (if_then_else (eq_attr "length" "6")
- (const_string "yes")
- (const_string "no")))
- (set (attr "length")
- (if_then_else
- (and (ge (minus (match_dup 0) (pc)) (const_int -252))
- (le (minus (match_dup 0) (pc)) (const_int 254)))
- (const_int 2)
- (if_then_else (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
- (le (minus (match_dup 0) (pc)) (const_int 2044)))
- (const_int 4)
- (const_int 6))))])
-
-(define_insn "*cond_branch_reversed"
- [(set (pc) (if_then_else (match_operator 1 "comparison_operator"
- [(cc0) (const_int 0)])
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
- "*
- switch (get_attr_length (insn))
- {
- case 2: return \"b%D1\\t%l0\\t%@cond_branch_reversed\";
- case 4: return \"b%d1\\t.LCBR%=\;b\\t%l0\\t%@long jump\\n.LCBR%=:\";
- default: return \"b%d1\\t.LCBR%=\;bl\\t%l0\\t%@far jump\\n.LCBR%=:\";
- }
- return \"\";
-"[(set (attr "far_jump")
- (if_then_else (eq_attr "length" "6")
- (const_string "yes")
- (const_string "no")))
- (set (attr "length")
- (if_then_else
- (and (ge (minus (match_dup 0) (pc)) (const_int -252))
- (le (minus (match_dup 0) (pc)) (const_int 254)))
- (const_int 2)
- (if_then_else (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
- (le (minus (match_dup 0) (pc)) (const_int 2044)))
- (const_int 4)
- (const_int 6))))])
-
-(define_insn "indirect_jump"
- [(set (pc) (match_operand:SI 0 "s_register_operand" "l*r"))]
- ""
- "mov\\tpc, %0")
-
-(define_insn "tablejump"
- [(set (pc) (match_operand:SI 0 "s_register_operand" "l*r"))
- (use (label_ref (match_operand 1 "" "")))]
- ""
- "mov\\tpc, %0")
-
-(define_insn "return"
- [(return)]
- "USE_RETURN"
- "* return output_return ();"
-[(set_attr "length" "18")])
-
-;; 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 "s_register_operand" "l*r"))
- (match_operand 1 "" ""))
- (use (match_operand 2 "" ""))])]
- "! TARGET_CALLER_INTERWORKING"
- "bl\\t%__call_via_%0"
-[(set_attr "length" "4")])
-;; The non THUMB_INTERWORK, non TARGET_CALLER_INTERWORKING version
-;; used to be: "mov\\tlr,pc\;bx\\t%0", but the mov does not set
-;; the bottom bit of lr so that a function return (using bx)
-;; would switch back into ARM mode...
-
-(define_insn "*call_indirect_interwork"
- [(parallel
- [(call (mem:SI (match_operand:SI 0 "s_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 "s_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 "s_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 "s_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")])
-
-;; Untyped call not required, since all funcs return in r0
-
-;; Miscellaneous patterns
-
-(define_insn "nop"
- [(clobber (const_int 0))]
- ""
- "mov\\tr8, r8")
-
-(define_insn "blockage"
- [(unspec_volatile [(const_int 0)] 0)]
- ""
- ""
- [(set_attr "length" "0")])
-
-(define_expand "prologue"
- [(const_int 0)]
- ""
- "
- thumb_expand_prologue ();
- DONE;
-")
-
-(define_expand "epilogue"
- [(unspec_volatile [(const_int 0)] 1)]
- "! thumb_trivial_epilogue ()"
- "
- thumb_expand_epilogue ();
-")
-
-(define_insn "*epilogue_insns"
- [(unspec_volatile [(const_int 0)] 1)]
- ""
- "*
- return thumb_unexpanded_epilogue ();
-"
-[(set_attr "length" "42")])
-
-;; Special patterns for dealing with the constant pool
-
-(define_insn "consttable_4"
- [(unspec_volatile [(match_operand 0 "" "")] 2)]
- ""
- "*
-{
- switch (GET_MODE_CLASS (GET_MODE (operands[0])))
- {
- case MODE_FLOAT:
- {
- union real_extract u;
- bcopy ((char *) &CONST_DOUBLE_LOW (operands[0]), (char *) &u, sizeof u);
- assemble_real (u.d, GET_MODE (operands[0]));
- break;
- }
- default:
- assemble_integer (operands[0], 4, 1);
- break;
- }
- return \"\";
-}"
-[(set_attr "length" "4")])
-
-(define_insn "consttable_8"
- [(unspec_volatile [(match_operand 0 "" "")] 3)]
- ""
- "*
-{
- switch (GET_MODE_CLASS (GET_MODE (operands[0])))
- {
- case MODE_FLOAT:
- {
- union real_extract u;
- bcopy ((char *) &CONST_DOUBLE_LOW (operands[0]), (char *) &u, sizeof u);
- assemble_real (u.d, GET_MODE (operands[0]));
- break;
- }
- default:
- assemble_integer (operands[0], 8, 1);
- break;
- }
- return \"\";
-}"
-[(set_attr "length" "8")])
-
-(define_insn "consttable_end"
- [(unspec_volatile [(const_int 0)] 4)]
- ""
- "*
- /* Nothing to do (currently). */
- return \"\";
-")
-
-(define_insn "align_4"
- [(unspec_volatile [(const_int 0)] 5)]
- ""
- "*
- assemble_align (32);
- return \"\";
-")
diff --git a/gcc/config/arm/thumb_981111.md b/gcc/config/arm/thumb_981111.md
deleted file mode 100755
index 93d0c05..0000000
--- a/gcc/config/arm/thumb_981111.md
+++ /dev/null
@@ -1,1166 +0,0 @@
-;; thumb.md Machine description for ARM/Thumb processors
-;; Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
-;; The basis of this contribution was generated by
-;; Richard Earnshaw, Advanced RISC Machines Ltd
-
-;; 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.
-
-;; LENGTH of an instruction is 2 bytes
-(define_attr "length" "" (const_int 2))
-
-;; CONDS is set to UNCHANGED when an insn does not affect the condition codes
-;; Most insns change the condition codes
-(define_attr "conds" "changed,unchanged" (const_string "changed"))
-
-;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
-;; distant label.
-(define_attr "far_jump" "yes,no" (const_string "no"))
-
-;; Start with move insns
-
-(define_expand "movsi"
- [(set (match_operand:SI 0 "general_operand" "")
- (match_operand:SI 1 "general_operand" ""))]
- ""
- "
- if (! (reload_in_progress || reload_completed))
- {
- if (GET_CODE (operands[0]) != REG)
- operands[1] = force_reg (SImode, operands[1]);
- }
-")
-
-(define_insn "*movsi_insn"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l,m,*r,*h")
- (match_operand:SI 1 "general_operand" "l,I,J,K,>,l,mi,l,*h,*r"))]
- "register_operand (operands[0], SImode)
- || register_operand (operands[1], SImode)"
- "@
- add\\t%0, %1, #0
- mov\\t%0, %1
- #
- #
- ldmia\\t%1, {%0}
- stmia\\t%0, {%1}
- ldr\\t%0, %1
- str\\t%1, %0
- mov\\t%0, %1
- mov\\t%0, %1"
-[(set_attr "length" "2,2,4,4,2,2,2,2,2,2")])
-
-(define_split
- [(set (match_operand:SI 0 "register_operand" "")
- (match_operand:SI 1 "const_int_operand" ""))]
- "thumb_shiftable_const (INTVAL (operands[1]))"
- [(set (match_dup 0) (match_dup 1))
- (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
- "
-{
- unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
- unsigned HOST_WIDE_INT mask = 0xff;
- int i;
- for (i = 0; i < 25; i++)
- if ((val & (mask << i)) == val)
- break;
-
- if (i == 0)
- FAIL;
-
- operands[1] = GEN_INT (val >> i);
- operands[2] = GEN_INT (i);
-}")
-
-(define_split
- [(set (match_operand:SI 0 "register_operand" "")
- (match_operand:SI 1 "const_int_operand" ""))]
- "INTVAL (operands[1]) < 0 && INTVAL (operands[1]) > -256"
- [(set (match_dup 0) (match_dup 1))
- (set (match_dup 0) (neg:SI (match_dup 0)))]
- "
- operands[1] = GEN_INT (- INTVAL (operands[1]));
-")
-
-;;(define_expand "reload_outsi"
-;; [(set (match_operand:SI 2 "register_operand" "=&l")
-;; (match_operand:SI 1 "register_operand" "h"))
-;; (set (match_operand:SI 0 "reload_memory_operand" "=o")
-;; (match_dup 2))]
-;; ""
-;; "
-;;/* thumb_reload_out_si (operands);
-;; DONE; */
-;;")
-
-(define_expand "movhi"
- [(set (match_operand:HI 0 "general_operand" "")
- (match_operand:HI 1 "general_operand" ""))]
- ""
- "
-{
- if (! (reload_in_progress || reload_completed))
- {
- if (GET_CODE (operands[0]) != REG)
- operands[1] = force_reg (HImode, operands[1]);
-
- /* ??? We shouldn't really get invalid addresses here, but this can
- happen if we are passed a SP (never OK for HImode/QImode) or virtual
- register (rejected by GO_IF_LEGITIMATE_ADDRESS for HImode/QImode)
- relative address. */
- /* ??? This should perhaps be fixed elsewhere, for instance, in
- fixup_stack_1, by checking for other kinds of invalid addresses,
- e.g. a bare reference to a virtual register. This may confuse the
- alpha though, which must handle this case differently. */
- if (GET_CODE (operands[0]) == MEM
- && ! memory_address_p (GET_MODE (operands[0]),
- XEXP (operands[0], 0)))
- {
- rtx temp = copy_to_reg (XEXP (operands[0], 0));
- operands[0] = change_address (operands[0], VOIDmode, temp);
- }
- if (GET_CODE (operands[1]) == MEM
- && ! memory_address_p (GET_MODE (operands[1]),
- XEXP (operands[1], 0)))
- {
- rtx temp = copy_to_reg (XEXP (operands[1], 0));
- operands[1] = change_address (operands[1], VOIDmode, temp);
- }
- }
- /* Handle loading a large integer during reload */
- else if (GET_CODE (operands[1]) == CONST_INT
- && ! CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
- {
- /* Writing a constant to memory needs a scratch, which should
- be handled with SECONDARY_RELOADs. */
- if (GET_CODE (operands[0]) != REG)
- abort ();
-
- operands[0] = gen_rtx (SUBREG, SImode, operands[0], 0);
- emit_insn (gen_movsi (operands[0], operands[1]));
- DONE;
- }
-}")
-
-(define_insn "*movhi_insn"
- [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
- (match_operand:HI 1 "general_operand" "l,m,l,*h,*r,I"))]
- "register_operand (operands[0], HImode)
- || register_operand (operands[1], HImode)"
- "@
- add\\t%0, %1, #0
- ldrh\\t%0, %1
- strh\\t%1, %0
- mov\\t%0, %1
- mov\\t%0, %1
- mov\\t%0, %1")
-
-(define_expand "movqi"
- [(set (match_operand:QI 0 "general_operand" "")
- (match_operand:QI 1 "general_operand" ""))]
- ""
- "
-{
- if (! (reload_in_progress || reload_completed))
- {
- if (GET_CODE (operands[0]) != REG)
- operands[1] = force_reg (QImode, operands[1]);
-
- /* ??? We shouldn't really get invalid addresses here, but this can
- happen if we are passed a SP (never OK for HImode/QImode) or virtual
- register (rejected by GO_IF_LEGITIMATE_ADDRESS for HImode/QImode)
- relative address. */
- /* ??? This should perhaps be fixed elsewhere, for instance, in
- fixup_stack_1, by checking for other kinds of invalid addresses,
- e.g. a bare reference to a virtual register. This may confuse the
- alpha though, which must handle this case differently. */
- if (GET_CODE (operands[0]) == MEM
- && ! memory_address_p (GET_MODE (operands[0]),
- XEXP (operands[0], 0)))
- {
- rtx temp = copy_to_reg (XEXP (operands[0], 0));
- operands[0] = change_address (operands[0], VOIDmode, temp);
- }
- if (GET_CODE (operands[1]) == MEM
- && ! memory_address_p (GET_MODE (operands[1]),
- XEXP (operands[1], 0)))
- {
- rtx temp = copy_to_reg (XEXP (operands[1], 0));
- operands[1] = change_address (operands[1], VOIDmode, temp);
- }
- }
- /* Handle loading a large integer during reload */
- else if (GET_CODE (operands[1]) == CONST_INT
- && ! CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
- {
- /* Writing a constant to memory needs a scratch, which should
- be handled with SECONDARY_RELOADs. */
- if (GET_CODE (operands[0]) != REG)
- abort ();
-
- operands[0] = gen_rtx (SUBREG, SImode, operands[0], 0);
- emit_insn (gen_movsi (operands[0], operands[1]));
- DONE;
- }
-}")
-
-(define_insn "*movqi_insn"
- [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
- (match_operand:QI 1 "general_operand" "l,m,l,*h,*r,I"))]
- "register_operand (operands[0], QImode)
- || register_operand (operands[1], QImode)"
- "@
- add\\t%0, %1, #0
- ldrb\\t%0, %1
- strb\\t%1, %0
- mov\\t%0, %1
- mov\\t%0, %1
- mov\\t%0, %1")
-
-(define_expand "movdi"
- [(set (match_operand:DI 0 "general_operand" "")
- (match_operand:DI 1 "general_operand" ""))]
- ""
- "
- if (! (reload_in_progress || reload_completed))
- {
- if (GET_CODE (operands[0]) != REG)
- operands[1] = force_reg (DImode, operands[1]);
- }
-")
-
-;;; ??? This should have alternatives for constants.
-;;; ??? This was originally identical to the movdf_insn pattern.
-;;; ??? The 'i' constraint looks funny, but it should always be replaced by
-;;; thumb_reorg with a memory reference.
-(define_insn "*movdi_insn"
- [(set (match_operand:DI 0 "general_operand" "=l,l,l,l,>,l,m,*r")
- (match_operand:DI 1 "general_operand" "l,I,J,>,l,mi,l,*r"))]
- "register_operand (operands[0], DImode)
- || register_operand (operands[1], DImode)"
- "*
-{
- switch (which_alternative)
- {
- case 0:
- if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
- return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
- return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
- case 1:
- return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
- case 2:
- operands[1] = GEN_INT (- INTVAL (operands[1]));
- return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
- case 3:
- return \"ldmia\\t%1, {%0, %H0}\";
- case 4:
- return \"stmia\\t%0, {%1, %H1}\";
- case 5:
- return thumb_load_double_from_address (operands);
- case 6:
- operands[2] = gen_rtx (MEM, SImode, plus_constant (XEXP (operands[0], 0), 4));
- output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
- return \"\";
- case 7:
- if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
- return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
- return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
- }
-}"[(set_attr "length" "4,4,6,2,2,6,4,4")])
-
-(define_expand "movdf"
- [(set (match_operand:DF 0 "general_operand" "")
- (match_operand:DF 1 "general_operand" ""))]
- ""
- "
- if (! (reload_in_progress || reload_completed))
- {
- if (GET_CODE (operands[0]) != REG)
- operands[1] = force_reg (DFmode, operands[1]);
- }
-")
-
-;;; ??? This should have alternatives for constants.
-;;; ??? This was originally identical to the movdi_insn pattern.
-;;; ??? The 'F' constraint looks funny, but it should always be replaced by
-;;; thumb_reorg with a memory reference.
-(define_insn "*movdf_insn"
- [(set (match_operand:DF 0 "general_operand" "=l,l,>,l,m,*r")
- (match_operand:DF 1 "general_operand" "l,>,l,mF,l,*r"))]
- "register_operand (operands[0], DFmode)
- || register_operand (operands[1], DFmode)"
- "*
- switch (which_alternative)
- {
- case 0:
- if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
- return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
- return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
- case 1:
- return \"ldmia\\t%1, {%0, %H0}\";
- case 2:
- return \"stmia\\t%0, {%1, %H1}\";
- case 3:
- return thumb_load_double_from_address (operands);
- case 4:
- operands[2] = gen_rtx (MEM, SImode, plus_constant (XEXP (operands[0], 0), 4));
- output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
- return \"\";
- case 5:
- if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
- return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
- return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
- }
-"[(set_attr "length" "4,2,2,6,4,4")])
-
-(define_expand "movsf"
- [(set (match_operand:SF 0 "general_operand" "")
- (match_operand:SF 1 "general_operand" ""))]
- ""
- "
- if (! (reload_in_progress || reload_completed))
- {
- if (GET_CODE (operands[0]) != REG)
- operands[1] = force_reg (SFmode, operands[1]);
- }
-")
-
-;;; ??? This should have alternatives for constants.
-(define_insn "*movsf_insn"
- [(set (match_operand:SF 0 "nonimmediate_operand" "=l,l,>,l,m,*r,*h")
- (match_operand:SF 1 "general_operand" "l,>,l,mF,l,*h,*r"))]
- "register_operand (operands[0], SFmode)
- || register_operand (operands[1], SFmode)"
- "@
- add\\t%0, %1, #0
- ldmia\\t%1, {%0}
- stmia\\t%0, {%1}
- ldr\\t%0, %1
- str\\t%1, %0
- mov\\t%0, %1
- mov\\t%0, %1")
-
-;; Widening move insns
-
-(define_expand "zero_extendhisi2"
- [(set (match_operand:SI 0 "register_operand" "")
- (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
- ""
- "
- if (GET_CODE (operands[1]) != MEM)
- {
- rtx temp = gen_reg_rtx (SImode);
-
- operands[1] = force_reg (HImode, operands[1]);
- operands[1] = gen_lowpart (SImode, operands[1]);
- emit_insn (gen_ashlsi3 (temp, operands[1], GEN_INT (16)));
- emit_insn (gen_lshrsi3 (operands[0], temp, GEN_INT (16)));
- DONE;
- }
-")
-
-(define_insn "*zero_extendhisi2_insn"
- [(set (match_operand:SI 0 "register_operand" "=l")
- (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
- ""
- "ldrh\\t%0, %1")
-
-(define_expand "zero_extendqisi2"
- [(set (match_operand:SI 0 "register_operand" "")
- (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
- ""
- "
- if (GET_CODE (operands[1]) != MEM)
- {
- rtx temp = gen_reg_rtx (SImode);
-
- operands[1] = force_reg (QImode, operands[1]);
- operands[1] = gen_lowpart (SImode, operands[1]);
- emit_insn (gen_ashlsi3 (temp, operands[1], GEN_INT (24)));
- emit_insn (gen_lshrsi3 (operands[0], temp, GEN_INT (24)));
- DONE;
- }
-")
-
-(define_insn "*zero_extendqisi2_insn"
- [(set (match_operand:SI 0 "register_operand" "=l")
- (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
- ""
- "ldrb\\t%0, %1")
-
-(define_expand "extendhisi2"
- [(parallel [(set (match_operand:SI 0 "register_operand" "")
- (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))
- (clobber (match_scratch:SI 2 ""))])]
- ""
- "
- if (GET_CODE (operands[1]) != MEM)
- {
- rtx temp = gen_reg_rtx (SImode);
-
- operands[1] = force_reg (HImode, operands[1]);
- operands[1] = gen_lowpart (SImode, operands[1]);
- emit_insn (gen_ashlsi3 (temp, operands[1], GEN_INT (16)));
- emit_insn (gen_ashrsi3 (operands[0], temp, GEN_INT (16)));
- DONE;
- }
-")
-
-(define_insn "*extendhisi2_insn"
- [(set (match_operand:SI 0 "register_operand" "=l")
- (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
- (clobber (match_scratch:SI 2 "=&l"))]
- ""
- "*
-{
- rtx ops[4];
- /* This code used to try to use 'V', and fix the address only if it was
- offsettable, but this fails for e.g. REG+48 because 48 is outside the
- range of QImode offsets, and offsettable_address_p does a QImode
- address check. */
-
- if (GET_CODE (XEXP (operands[1], 0)) == PLUS)
- {
- ops[1] = XEXP (XEXP (operands[1], 0), 0);
- ops[2] = XEXP (XEXP (operands[1], 0), 1);
- }
- else
- {
- ops[1] = XEXP (operands[1], 0);
- ops[2] = const0_rtx;
- }
- if (GET_CODE (ops[2]) == REG)
- return \"ldrsh\\t%0, %1\";
-
- ops[0] = operands[0];
- ops[3] = operands[2];
- output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
- return \"\";
-}"
-[(set_attr "length" "4")])
-
-(define_expand "extendqisi2"
- [(set (match_operand:SI 0 "register_operand" "")
- (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
- ""
- "
- if (GET_CODE (operands[1]) != MEM)
- {
- rtx temp = gen_reg_rtx (SImode);
-
- operands[1] = force_reg (QImode, operands[1]);
- operands[1] = gen_lowpart (SImode, operands[1]);
- emit_insn (gen_ashlsi3 (temp, operands[1], GEN_INT (24)));
- emit_insn (gen_ashrsi3 (operands[0], temp, GEN_INT (24)));
- DONE;
- }
-")
-
-(define_insn "*extendqisi2_insn"
- [(set (match_operand:SI 0 "register_operand" "=l,l")
- (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
- ""
- "*
-{
- rtx ops[3];
-
- if (which_alternative == 0)
- return \"ldrsb\\t%0, %1\";
- ops[0] = operands[0];
- if (GET_CODE (XEXP (operands[1], 0)) == PLUS)
- {
- ops[1] = XEXP (XEXP (operands[1], 0), 0);
- ops[2] = XEXP (XEXP (operands[1], 0), 1);
-
- if (GET_CODE (ops[1]) == REG && GET_CODE (ops[2]) == REG)
- output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
- else if (GET_CODE (ops[1]) == REG)
- {
- if (REGNO (ops[1]) == REGNO (operands[0]))
- output_asm_insn (\"ldrb\\t%0, [%1, %2]\;lsl\\t%0, %0, #24\;asr\\t%0, %0, #24\", ops);
- else
- output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
- }
- else
- {
- if (REGNO (ops[2]) == REGNO (operands[0]))
- output_asm_insn (\"ldrb\\t%0, [%2, %1]\;lsl\\t%0, %0, #24\;asr\\t%0, %0, #24\", ops);
- else
- output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
- }
- }
- else if (REGNO (operands[0]) == REGNO (XEXP (operands[1], 0)))
- {
- output_asm_insn (\"ldrb\\t%0, [%0, #0]\;lsl\\t%0, %0, #24\;asr\\t%0, %0, #24\", ops);
- }
- else
- {
- ops[1] = XEXP (operands[1], 0);
- ops[2] = const0_rtx;
- output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
- }
- return \"\";
-}"
-[(set_attr "length" "2,6")])
-
-;; We don't really have extzv, but defining this using shifts helps
-;; to reduce register pressure later on.
-
-(define_expand "extzv"
- [(set (match_dup 4)
- (ashift:SI (match_operand:SI 1 "register_operand" "")
- (match_operand:SI 2 "const_int_operand" "")))
- (set (match_operand:SI 0 "register_operand" "")
- (lshiftrt:SI (match_dup 4)
- (match_operand:SI 3 "const_int_operand" "")))]
- ""
- "
-{
- HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
- HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
- operands[3] = GEN_INT (rshift);
- if (lshift == 0)
- {
- emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
- DONE;
- }
- operands[2] = GEN_INT (lshift);
- operands[4] = gen_reg_rtx (SImode);
-}
-")
-
-;; Block-move insns
-
-(define_expand "movstrqi"
- [(match_operand:BLK 0 "general_operand" "")
- (match_operand:BLK 1 "general_operand" "")
- (match_operand:SI 2 "" "")
- (match_operand:SI 3 "const_int_operand" "")]
- ""
- "
- if (INTVAL (operands[3]) != 4
- || GET_CODE (operands[2]) != CONST_INT
- || INTVAL (operands[2]) > 48)
- FAIL;
-
- thumb_expand_movstrqi (operands);
- DONE;
-")
-
-(define_insn "movmem12b"
- [(set (mem:SI (match_operand:SI 0 "register_operand" "+&l"))
- (mem:SI (match_operand:SI 1 "register_operand" "+&l")))
- (set (mem:SI (plus:SI (match_dup 0) (const_int 4)))
- (mem:SI (plus:SI (match_dup 1) (const_int 4))))
- (set (mem:SI (plus:SI (match_dup 0) (const_int 8)))
- (mem:SI (plus:SI (match_dup 1) (const_int 8))))
- (set (match_dup 0) (plus:SI (match_dup 0) (const_int 12)))
- (set (match_dup 1) (plus:SI (match_dup 1) (const_int 12)))
- (clobber (match_scratch:SI 2 "=&l"))
- (clobber (match_scratch:SI 3 "=&l"))
- (clobber (match_scratch:SI 4 "=&l"))]
- ""
- "* return output_move_mem_multiple (3, operands);"
-[(set_attr "length" "4")])
-
-(define_insn "movmem8b"
- [(set (mem:SI (match_operand:SI 0 "register_operand" "+&l"))
- (mem:SI (match_operand:SI 1 "register_operand" "+&l")))
- (set (mem:SI (plus:SI (match_dup 0) (const_int 4)))
- (mem:SI (plus:SI (match_dup 1) (const_int 4))))
- (set (match_dup 0) (plus:SI (match_dup 0) (const_int 8)))
- (set (match_dup 1) (plus:SI (match_dup 1) (const_int 8)))
- (clobber (match_scratch:SI 2 "=&l"))
- (clobber (match_scratch:SI 3 "=&l"))]
- ""
- "* return output_move_mem_multiple (2, operands);"
-[(set_attr "length" "4")])
-
-;; Arithmetic insns
-
-(define_insn "adddi3"
- [(set (match_operand:DI 0 "register_operand" "=l")
- (plus:DI (match_operand:DI 1 "register_operand" "%0")
- (match_operand:DI 2 "register_operand" "l")))]
- ""
- "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
-[(set_attr "conds" "changed")
- (set_attr "length" "8")])
-
-;; register group 'k' is a single register group containing only the stack
-;; register. Trying to reload it will always fail catastrophically,
-;; so never allow those alternatives to match if reloading is needed.
-(define_insn "addsi3"
- [(set (match_operand:SI 0 "register_operand" "=l,l,l,*r,*h,l,!k")
- (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k")
- (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))]
- ""
- "*
- static char *asms[] =
-{
- \"add\\t%0, %0, %2\",
- \"sub\\t%0, %0, #%n2\",
- \"add\\t%0, %1, %2\",
- \"add\\t%0, %0, %2\",
- \"add\\t%0, %0, %2\",
- \"add\\t%0, %1, %2\",
- \"add\\t%0, %1, %2\"
-};
- if (which_alternative == 2 && GET_CODE (operands[2]) == CONST_INT
- && INTVAL (operands[2]) < 0)
- return \"sub\\t%0, %1, #%n2\";
- return asms[which_alternative];
-")
-
-; reloading and elimination of the frame pointer can sometimes cause this
-; optimization to be missed.
-(define_peephole
- [(set (match_operand:SI 0 "register_operand" "=l")
- (match_operand:SI 1 "const_int_operand" "M"))
- (set (match_dup 0)
- (plus:SI (match_dup 0) (match_operand:SI 2 "register_operand" "k")))]
- "REGNO (operands[2]) == STACK_POINTER_REGNUM
- && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
- && (INTVAL (operands[1]) & 3) == 0"
- "add\\t%0, %2, %1")
-
-(define_insn "subdi3"
- [(set (match_operand:DI 0 "register_operand" "=l")
- (minus:DI (match_operand:DI 1 "register_operand" "0")
- (match_operand:DI 2 "register_operand" "l")))]
- ""
- "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
-[(set_attr "conds" "changed")
- (set_attr "length" "8")])
-
-(define_insn "subsi3"
- [(set (match_operand:SI 0 "register_operand" "=l")
- (minus:SI (match_operand:SI 1 "register_operand" "l")
- (match_operand:SI 2 "register_operand" "l")))]
- ""
- "sub\\t%0, %1, %2")
-
-;; We must ensure that one input matches the output, and that the other input
-;; does not match the output. Using 0 satisfies the first, and using &
-;; satisfies the second. Unfortunately, this fails when operands 1 and 2
-;; are the same, because reload will make operand 0 match operand 1 without
-;; realizing that this conflicts with operand 2. We fix this by adding another
-;; alternative to match this case, and then `reload' it ourselves. This
-;; alternative must come first.
-(define_insn "mulsi3"
- [(set (match_operand:SI 0 "register_operand" "=&l,&l,&l")
- (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
- (match_operand:SI 2 "register_operand" "l,l,l")))]
- ""
- "*
-{
- if (which_alternative < 2)
- return \"mov\\t%0, %1\;mul\\t%0, %0, %2\";
- else
- return \"mul\\t%0, %0, %2\";
-}"
- [(set_attr "length" "4,4,2")])
-
-(define_insn "negsi2"
- [(set (match_operand:SI 0 "register_operand" "=l")
- (neg:SI (match_operand:SI 1 "register_operand" "l")))]
- ""
- "neg\\t%0, %1")
-
-;; Logical insns
-
-(define_expand "andsi3"
- [(set (match_operand:SI 0 "register_operand" "")
- (and:SI (match_operand:SI 1 "register_operand" "")
- (match_operand:SI 2 "nonmemory_operand" "")))]
- ""
- "
- if (GET_CODE (operands[2]) != CONST_INT)
- operands[2] = force_reg (SImode, operands[2]);
- else
- {
- int i;
- if (((unsigned HOST_WIDE_INT) ~ INTVAL (operands[2])) < 256)
- {
- operands[2] = force_reg (SImode, GEN_INT (~INTVAL (operands[2])));
- emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
- DONE;
- }
-
- for (i = 9; i <= 31; i++)
- if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
- {
- emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
- const0_rtx));
- DONE;
- }
- else if ((((HOST_WIDE_INT) 1) << i) - 1 == ~ INTVAL (operands[2]))
- {
- rtx shift = GEN_INT (i);
- rtx reg = gen_reg_rtx (SImode);
- emit_insn (gen_lshrsi3 (reg, operands[1], shift));
- emit_insn (gen_ashlsi3 (operands[0], reg, shift));
- DONE;
- }
-
- operands[2] = force_reg (SImode, operands[2]);
- }
-")
-
-(define_insn "*andsi3_insn"
- [(set (match_operand:SI 0 "register_operand" "=l")
- (and:SI (match_operand:SI 1 "register_operand" "%0")
- (match_operand:SI 2 "register_operand" "l")))]
- ""
- "and\\t%0, %0, %2")
-
-(define_insn "bicsi3"
- [(set (match_operand:SI 0 "register_operand" "=l")
- (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
- (match_operand:SI 2 "register_operand" "0")))]
- ""
- "bic\\t%0, %0, %1")
-
-(define_insn "iorsi3"
- [(set (match_operand:SI 0 "register_operand" "=l")
- (ior:SI (match_operand:SI 1 "register_operand" "%0")
- (match_operand:SI 2 "register_operand" "l")))]
- ""
- "orr\\t%0, %0, %2")
-
-(define_insn "xorsi3"
- [(set (match_operand:SI 0 "register_operand" "=l")
- (xor:SI (match_operand:SI 1 "register_operand" "%0")
- (match_operand:SI 2 "register_operand" "l")))]
- ""
- "eor\\t%0, %0, %2")
-
-(define_insn "one_cmplsi2"
- [(set (match_operand:SI 0 "register_operand" "=l")
- (not:SI (match_operand:SI 1 "register_operand" "l")))]
- ""
- "mvn\\t%0, %1")
-
-;; Shift and rotation insns
-
-(define_insn "ashlsi3"
- [(set (match_operand:SI 0 "register_operand" "=l,l")
- (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
- (match_operand:SI 2 "nonmemory_operand" "N,l")))]
- ""
- "@
- lsl\\t%0, %1, %2
- lsl\\t%0, %0, %2")
-
-(define_insn "ashrsi3"
- [(set (match_operand:SI 0 "register_operand" "=l,l")
- (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
- (match_operand:SI 2 "nonmemory_operand" "N,l")))]
- ""
- "@
- asr\\t%0, %1, %2
- asr\\t%0, %0, %2")
-
-(define_insn "lshrsi3"
- [(set (match_operand:SI 0 "register_operand" "=l,l")
- (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
- (match_operand:SI 2 "nonmemory_operand" "N,l")))]
- ""
- "@
- lsr\\t%0, %1, %2
- lsr\\t%0, %0, %2")
-
-(define_insn "rotrsi3"
- [(set (match_operand:SI 0 "register_operand" "=l")
- (rotatert:SI (match_operand:SI 1 "register_operand" "0")
- (match_operand:SI 2 "register_operand" "l")))]
- ""
- "ror\\t%0, %0, %2")
-
-;; Comparison insns
-
-(define_expand "cmpsi"
- [(set (cc0) (compare (match_operand:SI 0 "register_operand" "")
- (match_operand:SI 1 "nonmemory_operand" "")))]
- ""
- "
- if (GET_CODE (operands[1]) != REG && GET_CODE (operands[1]) != SUBREG)
- {
- if (GET_CODE (operands[1]) != CONST_INT
- || (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) >= 256)
- {
- if (GET_CODE (operands[1]) != CONST_INT
- || INTVAL (operands[1]) < -255
- || INTVAL (operands[1]) > 0)
- operands[1] = force_reg (SImode, operands[1]);
- else
- {
- operands[1] = force_reg (SImode,
- GEN_INT (- INTVAL (operands[1])));
- emit_insn (gen_cmnsi (operands[0], operands[1]));
- DONE;
- }
- }
- }
-")
-
-(define_insn "*cmpsi_insn"
- [(set (cc0) (compare (match_operand:SI 0 "register_operand" "l,*r,*h")
- (match_operand:SI 1 "thumb_cmp_operand" "lI,*h,*r")))]
- ""
- "@
- cmp\\t%0, %1
- cmp\\t%0, %1
- cmp\\t%0, %1")
-
-(define_insn "tstsi"
- [(set (cc0) (match_operand:SI 0 "register_operand" "l"))]
- ""
- "cmp\\t%0, #0")
-
-(define_insn "cmnsi"
- [(set (cc0) (compare (match_operand:SI 0 "register_operand" "l")
- (neg:SI (match_operand:SI 1 "register_operand" "l"))))]
- ""
- "cmn\\t%0, %1")
-
-;; Jump insns
-
-(define_insn "jump"
- [(set (pc) (label_ref (match_operand 0 "" "")))]
- ""
- "*
- if (get_attr_length (insn) == 2)
- return \"b\\t%l0\";
- return \"bl\\t%l0\\t%@ far jump\";
-"[(set (attr "far_jump")
- (if_then_else (eq_attr "length" "4")
- (const_string "yes")
- (const_string "no")))
- (set (attr "length")
- (if_then_else (and (ge (minus (match_dup 0) (pc)) (const_int -2048))
- (le (minus (match_dup 0) (pc)) (const_int 2044)))
- (const_int 2)
- (const_int 4)))])
-
-
-(define_expand "beq"
- [(set (pc) (if_then_else (eq (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_expand "bne"
- [(set (pc) (if_then_else (ne (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_expand "bge"
- [(set (pc) (if_then_else (ge (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_expand "ble"
- [(set (pc) (if_then_else (le (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_expand "bgt"
- [(set (pc) (if_then_else (gt (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_expand "blt"
- [(set (pc) (if_then_else (lt (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_expand "bgeu"
- [(set (pc) (if_then_else (geu (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_expand "bleu"
- [(set (pc) (if_then_else (leu (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_expand "bgtu"
- [(set (pc) (if_then_else (gtu (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_expand "bltu"
- [(set (pc) (if_then_else (ltu (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_insn "*cond_branch"
- [(set (pc) (if_then_else (match_operator 1 "comparison_operator"
- [(cc0) (const_int 0)])
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "*
- switch (get_attr_length (insn))
- {
- case 2: return \"b%d1\\t%l0\\t%@cond_branch\";
- case 4: return \"b%D1\\t.LCB%=\;b\\t%l0\\t%@long jump\\n.LCB%=:\";
- default: return \"b%D1\\t.LCB%=\;bl\\t%l0\\t%@far jump\\n.LCB%=:\";
- }
-"[(set (attr "far_jump")
- (if_then_else (eq_attr "length" "6")
- (const_string "yes")
- (const_string "no")))
- (set (attr "length")
- (if_then_else
- (and (ge (minus (match_dup 0) (pc)) (const_int -252))
- (le (minus (match_dup 0) (pc)) (const_int 254)))
- (const_int 2)
- (if_then_else (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
- (le (minus (match_dup 0) (pc)) (const_int 2044)))
- (const_int 4)
- (const_int 6))))])
-
-(define_insn "*cond_branch_reversed"
- [(set (pc) (if_then_else (match_operator 1 "comparison_operator"
- [(cc0) (const_int 0)])
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
- "*
- switch (get_attr_length (insn))
- {
- case 2: return \"b%D1\\t%l0\\t%@cond_branch_reversed\";
- case 4: return \"b%d1\\t.LCBR%=\;b\\t%l0\\t%@long jump\\n.LCBR%=:\";
- default: return \"b%d1\\t.LCBR%=\;bl\\t%l0\\t%@far jump\\n.LCBR%=:\";
- }
- return \"\";
-"[(set (attr "far_jump")
- (if_then_else (eq_attr "length" "6")
- (const_string "yes")
- (const_string "no")))
- (set (attr "length")
- (if_then_else
- (and (ge (minus (match_dup 0) (pc)) (const_int -252))
- (le (minus (match_dup 0) (pc)) (const_int 254)))
- (const_int 2)
- (if_then_else (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
- (le (minus (match_dup 0) (pc)) (const_int 2044)))
- (const_int 4)
- (const_int 6))))])
-
-(define_insn "indirect_jump"
- [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))]
- ""
- "mov\\tpc, %0")
-
-(define_insn "tablejump"
- [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
- (use (label_ref (match_operand 1 "" "")))]
- ""
- "mov\\tpc, %0")
-
-(define_insn "return"
- [(return)]
- "USE_RETURN"
- "* return output_return ();"
-[(set_attr "length" "18")])
-
-;; Call insns
-
-(define_expand "call"
- [(call (match_operand:SI 0 "memory_operand" "")
- (match_operand 1 "" ""))]
- ""
- "")
-
-(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")])
-;; The non THUMB_INTERWORK, non TARGET_CALLER_INTERWORKING version
-;; used to be: "mov\\tlr,pc\;bx\\t%0", but the mov does not set
-;; the bottom bit of lr so that a function return (using bx)
-;; 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 "" "")))]
- ""
- "")
-
-(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 "" ""))]
- "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 "" "")))]
- "GET_CODE (operands[1]) == SYMBOL_REF"
- "bl\\t%a1"
-[(set_attr "length" "4")])
-
-;; Untyped call not required, since all funcs return in r0
-
-;; Miscellaneous patterns
-
-(define_insn "nop"
- [(clobber (const_int 0))]
- ""
- "mov\\tr8, r8")
-
-(define_insn "blockage"
- [(unspec_volatile [(const_int 0)] 0)]
- ""
- ""
- [(set_attr "length" "0")])
-
-(define_expand "prologue"
- [(const_int 0)]
- ""
- "
- thumb_expand_prologue ();
- DONE;
-")
-
-(define_expand "epilogue"
- [(unspec_volatile [(const_int 0)] 1)]
- "! thumb_trivial_epilogue ()"
- "
- thumb_expand_epilogue ();
-")
-
-(define_insn "*epilogue_insns"
- [(unspec_volatile [(const_int 0)] 1)]
- ""
- "*
- return thumb_unexpanded_epilogue ();
-"
-[(set_attr "length" "42")])
-
-;; Special patterns for dealing with the constant pool
-
-(define_insn "consttable_4"
- [(unspec_volatile [(match_operand 0 "" "")] 2)]
- ""
- "*
-{
- switch (GET_MODE_CLASS (GET_MODE (operands[0])))
- {
- case MODE_FLOAT:
- {
- union real_extract u;
- bcopy ((char *) &CONST_DOUBLE_LOW (operands[0]), (char *) &u, sizeof u);
- assemble_real (u.d, GET_MODE (operands[0]));
- break;
- }
- default:
- assemble_integer (operands[0], 4, 1);
- break;
- }
- return \"\";
-}"
-[(set_attr "length" "4")])
-
-(define_insn "consttable_8"
- [(unspec_volatile [(match_operand 0 "" "")] 3)]
- ""
- "*
-{
- switch (GET_MODE_CLASS (GET_MODE (operands[0])))
- {
- case MODE_FLOAT:
- {
- union real_extract u;
- bcopy ((char *) &CONST_DOUBLE_LOW (operands[0]), (char *) &u, sizeof u);
- assemble_real (u.d, GET_MODE (operands[0]));
- break;
- }
- default:
- assemble_integer (operands[0], 8, 1);
- break;
- }
- return \"\";
-}"
-[(set_attr "length" "8")])
-
-(define_insn "consttable_end"
- [(unspec_volatile [(const_int 0)] 4)]
- ""
- "*
- /* Nothing to do (currently). */
- return \"\";
-")
-
-(define_insn "align_4"
- [(unspec_volatile [(const_int 0)] 5)]
- ""
- "*
- assemble_align (32);
- return \"\";
-")