arm.c (arm_arch4t): New variable.
* arm.c (arm_arch4t): New variable. (arm_override_options): Initialize it. If compiling for armv5 or higher clear TARGET_INTERWORK. (output_call): Abort if called for armv5. Use BX if it's available. (output_call_mem): Use BLX if available and ensure that all armv5 code is interworking safe. (output_return_instruction): Always use BX in preference to MOV if it's available. (arm_output_epilogue): Likewise. (arm_final_prescan_insn): Never conditionally call a subroutine on armv5. * arm.h (arm_arch4t): Declare. * arm.md (call_reg_armv5, call_value_reg_armv5): New. (call_reg_arm, call_value_reg_arm): Renamed from call_reg and call_value_reg respectively. (call_reg_thumb_v5, call_value_reg_thumb_v5): New. (call_reg_thumb, call_value_reg_thumb): Renamed from call_indirect and call_value_indirect respectively. From-SVN: r83647
This commit is contained in:
parent
576df3214c
commit
68d560d4d6
@ -1,3 +1,24 @@
|
||||
2004-06-25 Richard Earnshaw <rearnsha@arm.com>
|
||||
|
||||
* arm.c (arm_arch4t): New variable.
|
||||
(arm_override_options): Initialize it. If compiling for armv5 or
|
||||
higher clear TARGET_INTERWORK.
|
||||
(output_call): Abort if called for armv5. Use BX if it's available.
|
||||
(output_call_mem): Use BLX if available and ensure that all armv5
|
||||
code is interworking safe.
|
||||
(output_return_instruction): Always use BX in preference to MOV if
|
||||
it's available.
|
||||
(arm_output_epilogue): Likewise.
|
||||
(arm_final_prescan_insn): Never conditionally call a subroutine
|
||||
on armv5.
|
||||
* arm.h (arm_arch4t): Declare.
|
||||
* arm.md (call_reg_armv5, call_value_reg_armv5): New.
|
||||
(call_reg_arm, call_value_reg_arm): Renamed from call_reg and
|
||||
call_value_reg respectively.
|
||||
(call_reg_thumb_v5, call_value_reg_thumb_v5): New.
|
||||
(call_reg_thumb, call_value_reg_thumb): Renamed from call_indirect
|
||||
and call_value_indirect respectively.
|
||||
|
||||
2004-06-25 Richard Sandiford <rsandifo@redhat.com>
|
||||
|
||||
* config/mips/mips.c (reg_or_const_float_1_operand): Reimplement
|
||||
|
@ -366,6 +366,9 @@ int arm_arch3m = 0;
|
||||
/* Nonzero if this chip supports the ARM Architecture 4 extensions. */
|
||||
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. */
|
||||
int arm_arch5 = 0;
|
||||
|
||||
@ -802,6 +805,7 @@ arm_override_options (void)
|
||||
/* Initialize boolean versions of the flags, for use in the arm.md file. */
|
||||
arm_arch3m = (insn_flags & FL_ARCH3M) != 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_arch5e = (insn_flags & FL_ARCH5E) != 0;
|
||||
arm_arch6 = (insn_flags & FL_ARCH6) != 0;
|
||||
@ -816,6 +820,11 @@ arm_override_options (void)
|
||||
arm_tune_xscale = (tune_flags & FL_XSCALE) != 0;
|
||||
arm_arch_iwmmxt = (insn_flags & FL_IWMMXT) != 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;
|
||||
|
||||
if (target_abi_name)
|
||||
{
|
||||
for (i = 0; i < ARRAY_SIZE (arm_all_abis); i++)
|
||||
@ -8000,8 +8009,10 @@ vfp_emit_fstmx (int base_reg, int count)
|
||||
const char *
|
||||
output_call (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)
|
||||
{
|
||||
operands[0] = gen_rtx_REG (SImode, IP_REGNUM);
|
||||
@ -8010,7 +8021,7 @@ output_call (rtx *operands)
|
||||
|
||||
output_asm_insn ("mov%?\t%|lr, %|pc", operands);
|
||||
|
||||
if (TARGET_INTERWORK)
|
||||
if (TARGET_INTERWORK || arm_arch4t)
|
||||
output_asm_insn ("bx%?\t%0", operands);
|
||||
else
|
||||
output_asm_insn ("mov%?\t%|pc, %0", operands);
|
||||
@ -8022,7 +8033,7 @@ output_call (rtx *operands)
|
||||
const char *
|
||||
output_call_mem (rtx *operands)
|
||||
{
|
||||
if (TARGET_INTERWORK)
|
||||
if (TARGET_INTERWORK && !arm_arch5)
|
||||
{
|
||||
output_asm_insn ("ldr%?\t%|ip, %0", operands);
|
||||
output_asm_insn ("mov%?\t%|lr, %|pc", operands);
|
||||
@ -8034,8 +8045,16 @@ output_call_mem (rtx *operands)
|
||||
first instruction. It's safe to use IP as the target of the
|
||||
load since the call will kill it anyway. */
|
||||
output_asm_insn ("ldr%?\t%|ip, %0", operands);
|
||||
output_asm_insn ("mov%?\t%|lr, %|pc", operands);
|
||||
output_asm_insn ("mov%?\t%|pc, %|ip", operands);
|
||||
if (arm_arch5)
|
||||
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
|
||||
{
|
||||
@ -9261,9 +9280,8 @@ output_return_instruction (rtx operand, int really_return, int reverse)
|
||||
break;
|
||||
|
||||
default:
|
||||
/* ARMv5 implementations always provide BX, so interworking
|
||||
is the default. */
|
||||
if ((insn_flags & FL_ARCH5) != 0)
|
||||
/* Use bx if it's available. */
|
||||
if (arm_arch5 || arm_arch4t)
|
||||
sprintf (instr, "bx%s\t%%|lr", conditional);
|
||||
else
|
||||
sprintf (instr, "mov%s\t%%|pc, %%|lr", conditional);
|
||||
@ -9729,7 +9747,10 @@ arm_output_epilogue (rtx sibling)
|
||||
break;
|
||||
|
||||
default:
|
||||
asm_fprintf (f, "\tmov\t%r, %r\n", PC_REGNUM, LR_REGNUM);
|
||||
if (arm_arch5 || arm_arch4t)
|
||||
asm_fprintf (f, "\tbx\t%r\n", LR_REGNUM);
|
||||
else
|
||||
asm_fprintf (f, "\tmov\t%r, %r\n", PC_REGNUM, LR_REGNUM);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -11234,6 +11255,16 @@ arm_final_prescan_insn (rtx insn)
|
||||
break;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* Succeed if the following insn is the target label, or
|
||||
if the following two insns are a barrier and the
|
||||
target label. */
|
||||
|
@ -490,6 +490,9 @@ extern int arm_arch3m;
|
||||
/* Nonzero if this chip supports the ARM Architecture 4 extensions. */
|
||||
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. */
|
||||
extern int arm_arch5;
|
||||
|
||||
|
@ -7377,12 +7377,22 @@
|
||||
}"
|
||||
)
|
||||
|
||||
(define_insn "*call_reg"
|
||||
(define_insn "*call_reg_armv5"
|
||||
[(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"
|
||||
"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);
|
||||
"
|
||||
@ -7404,12 +7414,23 @@
|
||||
(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"))
|
||||
(match_operand 1 "" ""))
|
||||
(use (match_operand 2 "" ""))
|
||||
(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)
|
||||
@ -7420,23 +7441,6 @@
|
||||
[(set_attr "type" "call")]
|
||||
)
|
||||
|
||||
(define_insn "*call_value_indirect"
|
||||
[(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"
|
||||
"*
|
||||
{
|
||||
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"
|
||||
[(parallel [(set (match_operand 0 "" "")
|
||||
(call (match_operand 1 "memory_operand" "")
|
||||
@ -7459,13 +7463,24 @@
|
||||
}"
|
||||
)
|
||||
|
||||
(define_insn "*call_value_reg"
|
||||
(define_insn "*call_value_reg_armv5"
|
||||
[(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"
|
||||
"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]);
|
||||
"
|
||||
@ -7487,6 +7502,35 @@
|
||||
(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
|
||||
;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
|
||||
|
||||
@ -7786,6 +7830,7 @@
|
||||
""
|
||||
)
|
||||
|
||||
;; NB Never uses BX.
|
||||
(define_insn "*arm_indirect_jump"
|
||||
[(set (pc)
|
||||
(match_operand:SI 0 "s_register_operand" "r"))]
|
||||
@ -7794,8 +7839,6 @@
|
||||
[(set_attr "predicable" "yes")]
|
||||
)
|
||||
|
||||
;; Although not supported by the define_expand above,
|
||||
;; cse/combine may generate this form.
|
||||
(define_insn "*load_indirect_jump"
|
||||
[(set (pc)
|
||||
(match_operand:SI 0 "memory_operand" "m"))]
|
||||
@ -7807,6 +7850,7 @@
|
||||
(set_attr "predicable" "yes")]
|
||||
)
|
||||
|
||||
;; NB Never uses BX.
|
||||
(define_insn "*thumb_indirect_jump"
|
||||
[(set (pc)
|
||||
(match_operand:SI 0 "register_operand" "l*r"))]
|
||||
@ -10099,6 +10143,7 @@
|
||||
"
|
||||
)
|
||||
|
||||
;; NB never uses BX.
|
||||
(define_insn "*thumb_tablejump"
|
||||
[(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
|
||||
(use (label_ref (match_operand 1 "" "")))]
|
||||
|
Loading…
Reference in New Issue
Block a user