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:
parent
90fe9fb58c
commit
d2d54a40b5
43
gnu/dist/gcc/gcc/config/arm/arm.c
vendored
43
gnu/dist/gcc/gcc/config/arm/arm.c
vendored
@ -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)
|
||||||
|
3
gnu/dist/gcc/gcc/config/arm/arm.h
vendored
3
gnu/dist/gcc/gcc/config/arm/arm.h
vendored
@ -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;
|
||||||
|
|
||||||
|
113
gnu/dist/gcc/gcc/config/arm/arm.md
vendored
113
gnu/dist/gcc/gcc/config/arm/arm.md
vendored
@ -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 "" "")))]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user