Backport changes from the FSF development tree that ensure that code

build for ARM architecture 5 or later is always interworking clean.
This commit is contained in:
rearnsha 2004-08-21 10:48:54 +00:00
parent 90fe9fb58c
commit d2d54a40b5
3 changed files with 119 additions and 40 deletions

View File

@ -262,6 +262,9 @@ int arm_fast_multiply = 0;
/* Nonzero if this chip supports the ARM Architecture 4 extensions. */ /* Nonzero if this chip supports the ARM Architecture 4 extensions. */
int arm_arch4 = 0; int arm_arch4 = 0;
/* Nonzero if this chip supports the ARM Architecture 4t extensions. */
int arm_arch4t = 0;
/* Nonzero if this chip supports the ARM Architecture 5 extensions. */ /* Nonzero if this chip supports the ARM Architecture 5 extensions. */
int arm_arch5 = 0; int arm_arch5 = 0;
@ -682,6 +685,7 @@ arm_override_options ()
/* Initialize boolean versions of the flags, for use in the arm.md file. */ /* Initialize boolean versions of the flags, for use in the arm.md file. */
arm_fast_multiply = (insn_flags & FL_FAST_MULT) != 0; arm_fast_multiply = (insn_flags & FL_FAST_MULT) != 0;
arm_arch4 = (insn_flags & FL_ARCH4) != 0; arm_arch4 = (insn_flags & FL_ARCH4) != 0;
arm_arch4t = arm_arch4 & ((insn_flags & FL_THUMB) != 0);
arm_arch5 = (insn_flags & FL_ARCH5) != 0; arm_arch5 = (insn_flags & FL_ARCH5) != 0;
arm_arch5e = (insn_flags & FL_ARCH5E) != 0; arm_arch5e = (insn_flags & FL_ARCH5E) != 0;
arm_is_xscale = (insn_flags & FL_XSCALE) != 0; arm_is_xscale = (insn_flags & FL_XSCALE) != 0;
@ -692,6 +696,11 @@ arm_override_options ()
arm_is_6_or_7 = (((tune_flags & (FL_MODE26 | FL_MODE32)) arm_is_6_or_7 = (((tune_flags & (FL_MODE26 | FL_MODE32))
&& !(tune_flags & FL_ARCH4))) != 0; && !(tune_flags & FL_ARCH4))) != 0;
/* V5 code we generate is completely interworking capable, so we turn off
TARGET_INTERWORK here to avoid many tests later on. */
if (arm_arch5)
target_flags &= ~ARM_FLAG_INTERWORK;
/* Default value for floating point code... if no co-processor /* Default value for floating point code... if no co-processor
bus, then schedule for emulated floating point. Otherwise, bus, then schedule for emulated floating point. Otherwise,
assume the user has an FPA. assume the user has an FPA.
@ -6411,8 +6420,10 @@ const char *
output_call (operands) output_call (operands)
rtx * operands; rtx * operands;
{ {
/* Handle calls to lr using ip (which may be clobbered in subr anyway). */ if (arm_arch5)
abort (); /* Patterns should call blx <reg> directly. */
/* Handle calls to lr using ip (which may be clobbered in subr anyway). */
if (REGNO (operands[0]) == LR_REGNUM) if (REGNO (operands[0]) == LR_REGNUM)
{ {
operands[0] = gen_rtx_REG (SImode, IP_REGNUM); operands[0] = gen_rtx_REG (SImode, IP_REGNUM);
@ -6421,7 +6432,7 @@ output_call (operands)
output_asm_insn ("mov%?\t%|lr, %|pc", operands); output_asm_insn ("mov%?\t%|lr, %|pc", operands);
if (TARGET_INTERWORK) if (TARGET_INTERWORK || arm_arch4t)
output_asm_insn ("bx%?\t%0", operands); output_asm_insn ("bx%?\t%0", operands);
else else
output_asm_insn ("mov%?\t%|pc, %0", operands); output_asm_insn ("mov%?\t%|pc, %0", operands);
@ -6435,7 +6446,7 @@ const char *
output_call_mem (operands) output_call_mem (operands)
rtx * operands; rtx * operands;
{ {
if (TARGET_INTERWORK) if (TARGET_INTERWORK && !arm_arch5)
{ {
output_asm_insn ("ldr%?\t%|ip, %0", operands); output_asm_insn ("ldr%?\t%|ip, %0", operands);
output_asm_insn ("mov%?\t%|lr, %|pc", operands); output_asm_insn ("mov%?\t%|lr, %|pc", operands);
@ -6447,8 +6458,16 @@ output_call_mem (operands)
first instruction. It's safe to use IP as the target of the first instruction. It's safe to use IP as the target of the
load since the call will kill it anyway. */ load since the call will kill it anyway. */
output_asm_insn ("ldr%?\t%|ip, %0", operands); output_asm_insn ("ldr%?\t%|ip, %0", operands);
output_asm_insn ("mov%?\t%|lr, %|pc", operands); if (arm_arch5)
output_asm_insn ("mov%?\t%|pc, %|ip", operands); output_asm_insn ("blx%?%|ip", operands);
else
{
output_asm_insn ("mov%?\t%|lr, %|pc", operands);
if (arm_arch4t)
output_asm_insn ("bx%?\t%|ip", operands);
else
output_asm_insn ("mov%?\t%|pc, %|ip", operands);
}
} }
else else
{ {
@ -7431,7 +7450,7 @@ output_return_instruction (operand, really_return, reverse)
default: default:
/* ARMv5 implementations always provide BX, so interworking /* ARMv5 implementations always provide BX, so interworking
is the default unless APCS-26 is in use. */ is the default unless APCS-26 is in use. */
if ((insn_flags & FL_ARCH5) != 0 && TARGET_APCS_32) if ((arm_arch5 || arm_arch4t) && TARGET_APCS_32)
sprintf (instr, "bx%s\t%%|lr", conditional); sprintf (instr, "bx%s\t%%|lr", conditional);
else else
sprintf (instr, "mov%s%s\t%%|pc, %%|lr", sprintf (instr, "mov%s%s\t%%|pc, %%|lr",
@ -7831,6 +7850,8 @@ arm_output_epilogue (really_return)
/* Similarly we may have been able to load LR into the PC /* Similarly we may have been able to load LR into the PC
even if we did not create a stack frame. */ even if we did not create a stack frame. */
; ;
else if (TARGET_APCS_32 && (arm_arch5 || arm_arch4t))
asm_fprintf (f, "\tbx\t%r\n", LR_REGNUM);
else if (TARGET_APCS_32) else if (TARGET_APCS_32)
asm_fprintf (f, "\tmov\t%r, %r\n", PC_REGNUM, LR_REGNUM); asm_fprintf (f, "\tmov\t%r, %r\n", PC_REGNUM, LR_REGNUM);
else else
@ -9169,6 +9190,16 @@ arm_final_prescan_insn (insn)
break; break;
case CALL_INSN: case CALL_INSN:
/* The AAPCS says that conditional calls should not be
used since they make interworking inefficient (the
linker can't transform BL<cond> into BLX). That's
only a problem if the machine has BLX. */
if (arm_arch5)
{
fail = TRUE;
break;
}
/* If using 32-bit addresses the cc is not preserved over /* If using 32-bit addresses the cc is not preserved over
calls. */ calls. */
if (TARGET_APCS_32) if (TARGET_APCS_32)

View File

@ -555,6 +555,9 @@ extern int arm_fast_multiply;
/* Nonzero if this chip supports the ARM Architecture 4 extensions */ /* Nonzero if this chip supports the ARM Architecture 4 extensions */
extern int arm_arch4; extern int arm_arch4;
/* Nonzero if this chip supports the ARM Architecture 4T extensions. */
extern int arm_arch4t;
/* Nonzero if this chip supports the ARM Architecture 5 extensions */ /* Nonzero if this chip supports the ARM Architecture 5 extensions */
extern int arm_arch5; extern int arm_arch5;

View File

@ -6530,12 +6530,22 @@
}" }"
) )
(define_insn "*call_reg" (define_insn "*call_reg_armv5"
[(call (mem:SI (match_operand:SI 0 "s_register_operand" "r")) [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
(match_operand 1 "" "")) (match_operand 1 "" ""))
(use (match_operand 2 "" "")) (use (match_operand 2 "" ""))
(clobber (reg:SI LR_REGNUM))] (clobber (reg:SI LR_REGNUM))]
"TARGET_ARM" "TARGET_ARM && arm_arch5"
"blx%?\\t%0"
[(set_attr "type" "call")]
)
(define_insn "*call_reg_arm"
[(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
(match_operand 1 "" ""))
(use (match_operand 2 "" ""))
(clobber (reg:SI LR_REGNUM))]
"TARGET_ARM && !arm_arch5"
"* "*
return output_call (operands); return output_call (operands);
" "
@ -6557,12 +6567,23 @@
(set_attr "type" "call")] (set_attr "type" "call")]
) )
(define_insn "*call_indirect" (define_insn "*call_reg_thumb_v5"
[(call (mem:SI (match_operand:SI 0 "register_operand" "l*r")) [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
(match_operand 1 "" "")) (match_operand 1 "" ""))
(use (match_operand 2 "" "")) (use (match_operand 2 "" ""))
(clobber (reg:SI LR_REGNUM))] (clobber (reg:SI LR_REGNUM))]
"TARGET_THUMB" "TARGET_THUMB && arm_arch5"
"blx\\t%0"
[(set_attr "length" "2")
(set_attr "type" "call")]
)
(define_insn "*call_reg_thumb"
[(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
(match_operand 1 "" ""))
(use (match_operand 2 "" ""))
(clobber (reg:SI LR_REGNUM))]
"TARGET_THUMB && !arm_arch5"
"* "*
{ {
if (TARGET_CALLER_INTERWORKING) if (TARGET_CALLER_INTERWORKING)
@ -6573,23 +6594,6 @@
[(set_attr "type" "call")] [(set_attr "type" "call")]
) )
(define_insn "*call_value_indirect"
[(set (match_operand 0 "" "=l")
(call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
(match_operand 2 "" "")))
(use (match_operand 3 "" ""))
(clobber (reg:SI LR_REGNUM))]
"TARGET_THUMB"
"*
{
if (TARGET_CALLER_INTERWORKING)
return \"bl\\t%__interwork_call_via_%1\";
else
return \"bl\\t%__call_via_%1\";
}"
[(set_attr "type" "call")]
)
(define_expand "call_value" (define_expand "call_value"
[(parallel [(set (match_operand 0 "" "") [(parallel [(set (match_operand 0 "" "")
(call (match_operand 1 "memory_operand" "") (call (match_operand 1 "memory_operand" "")
@ -6612,13 +6616,24 @@
}" }"
) )
(define_insn "*call_value_reg" (define_insn "*call_value_reg_armv5"
[(set (match_operand 0 "" "=r,f") [(set (match_operand 0 "" "")
(call (mem:SI (match_operand:SI 1 "s_register_operand" "r,r")) (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
(match_operand 2 "" ""))) (match_operand 2 "" "")))
(use (match_operand 3 "" "")) (use (match_operand 3 "" ""))
(clobber (reg:SI LR_REGNUM))] (clobber (reg:SI LR_REGNUM))]
"TARGET_ARM" "TARGET_ARM && arm_arch5"
"blx%?\\t%1"
[(set_attr "type" "call")]
)
(define_insn "*call_value_reg_arm"
[(set (match_operand 0 "" "")
(call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
(match_operand 2 "" "")))
(use (match_operand 3 "" ""))
(clobber (reg:SI LR_REGNUM))]
"TARGET_ARM && !arm_arch5"
"* "*
return output_call (&operands[1]); return output_call (&operands[1]);
" "
@ -6627,8 +6642,8 @@
) )
(define_insn "*call_value_mem" (define_insn "*call_value_mem"
[(set (match_operand 0 "" "=r,f") [(set (match_operand 0 "" "")
(call (mem:SI (match_operand:SI 1 "memory_operand" "m,m")) (call (mem:SI (match_operand:SI 1 "memory_operand" "m"))
(match_operand 2 "" ""))) (match_operand 2 "" "")))
(use (match_operand 3 "" "")) (use (match_operand 3 "" ""))
(clobber (reg:SI LR_REGNUM))] (clobber (reg:SI LR_REGNUM))]
@ -6640,6 +6655,35 @@
(set_attr "type" "call")] (set_attr "type" "call")]
) )
(define_insn "*call_value_reg_thumb_v5"
[(set (match_operand 0 "" "")
(call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
(match_operand 2 "" "")))
(use (match_operand 3 "" ""))
(clobber (reg:SI LR_REGNUM))]
"TARGET_THUMB && arm_arch5"
"blx\\t%1"
[(set_attr "length" "2")
(set_attr "type" "call")]
)
(define_insn "*call_value_reg_thumb"
[(set (match_operand 0 "" "")
(call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
(match_operand 2 "" "")))
(use (match_operand 3 "" ""))
(clobber (reg:SI LR_REGNUM))]
"TARGET_THUMB && !arm_arch5"
"*
{
if (TARGET_CALLER_INTERWORKING)
return \"bl\\t%__interwork_call_via_%1\";
else
return \"bl\\t%__call_via_%1\";
}"
[(set_attr "type" "call")]
)
;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
;; The 'a' causes the operand to be treated as an address, i.e. no '#' output. ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
@ -6659,8 +6703,8 @@
) )
(define_insn "*call_value_symbol" (define_insn "*call_value_symbol"
[(set (match_operand 0 "s_register_operand" "=r,f") [(set (match_operand 0 "s_register_operand" "")
(call (mem:SI (match_operand:SI 1 "" "X,X")) (call (mem:SI (match_operand:SI 1 "" "X"))
(match_operand:SI 2 "" ""))) (match_operand:SI 2 "" "")))
(use (match_operand 3 "" "")) (use (match_operand 3 "" ""))
(clobber (reg:SI LR_REGNUM))] (clobber (reg:SI LR_REGNUM))]
@ -6688,7 +6732,7 @@
) )
(define_insn "*call_value_insn" (define_insn "*call_value_insn"
[(set (match_operand 0 "register_operand" "=l") [(set (match_operand 0 "register_operand" "")
(call (mem:SI (match_operand 1 "" "X")) (call (mem:SI (match_operand 1 "" "X"))
(match_operand 2 "" ""))) (match_operand 2 "" "")))
(use (match_operand 3 "" "")) (use (match_operand 3 "" ""))
@ -6742,8 +6786,8 @@
) )
(define_insn "*sibcall_value_insn" (define_insn "*sibcall_value_insn"
[(set (match_operand 0 "s_register_operand" "=r,f") [(set (match_operand 0 "s_register_operand" "")
(call (mem:SI (match_operand:SI 1 "" "X,X")) (call (mem:SI (match_operand:SI 1 "" "X"))
(match_operand 2 "" ""))) (match_operand 2 "" "")))
(return) (return)
(use (match_operand 3 "" ""))] (use (match_operand 3 "" ""))]
@ -6937,6 +6981,7 @@
"" ""
) )
;; NB Never uses BX.
(define_insn "*arm_indirect_jump" (define_insn "*arm_indirect_jump"
[(set (pc) [(set (pc)
(match_operand:SI 0 "s_register_operand" "r"))] (match_operand:SI 0 "s_register_operand" "r"))]
@ -6945,8 +6990,6 @@
[(set_attr "predicable" "yes")] [(set_attr "predicable" "yes")]
) )
;; Although not supported by the define_expand above,
;; cse/combine may generate this form.
(define_insn "*load_indirect_jump" (define_insn "*load_indirect_jump"
[(set (pc) [(set (pc)
(match_operand:SI 0 "memory_operand" "m"))] (match_operand:SI 0 "memory_operand" "m"))]
@ -6958,6 +7001,7 @@
(set_attr "predicable" "yes")] (set_attr "predicable" "yes")]
) )
;; NB Never uses BX.
(define_insn "*thumb_indirect_jump" (define_insn "*thumb_indirect_jump"
[(set (pc) [(set (pc)
(match_operand:SI 0 "register_operand" "l*r"))] (match_operand:SI 0 "register_operand" "l*r"))]
@ -9104,6 +9148,7 @@
" "
) )
;; NB never uses BX.
(define_insn "*thumb_tablejump" (define_insn "*thumb_tablejump"
[(set (pc) (match_operand:SI 0 "register_operand" "l*r")) [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
(use (label_ref (match_operand 1 "" "")))] (use (label_ref (match_operand 1 "" "")))]