diff --git a/gnu/dist/gcc/gcc/config/arm/arm.c b/gnu/dist/gcc/gcc/config/arm/arm.c index 7422f1d03aff..70352a8461b1 100644 --- a/gnu/dist/gcc/gcc/config/arm/arm.c +++ b/gnu/dist/gcc/gcc/config/arm/arm.c @@ -262,6 +262,9 @@ int arm_fast_multiply = 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; @@ -682,6 +685,7 @@ arm_override_options () /* Initialize boolean versions of the flags, for use in the arm.md file. */ arm_fast_multiply = (insn_flags & FL_FAST_MULT) != 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_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)) && !(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 bus, then schedule for emulated floating point. Otherwise, assume the user has an FPA. @@ -6411,8 +6420,10 @@ const char * output_call (operands) rtx * operands; { - /* Handle calls to lr using ip (which may be clobbered in subr anyway). */ + if (arm_arch5) + abort (); /* Patterns should call blx 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); @@ -6421,7 +6432,7 @@ output_call (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); @@ -6435,7 +6446,7 @@ const char * output_call_mem (operands) 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); @@ -6447,8 +6458,16 @@ output_call_mem (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 { @@ -7431,7 +7450,7 @@ output_return_instruction (operand, really_return, reverse) default: /* ARMv5 implementations always provide BX, so interworking 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); else 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 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) asm_fprintf (f, "\tmov\t%r, %r\n", PC_REGNUM, LR_REGNUM); else @@ -9169,6 +9190,16 @@ arm_final_prescan_insn (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 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 calls. */ if (TARGET_APCS_32) diff --git a/gnu/dist/gcc/gcc/config/arm/arm.h b/gnu/dist/gcc/gcc/config/arm/arm.h index 6506830c5cd1..192a6f857a6b 100644 --- a/gnu/dist/gcc/gcc/config/arm/arm.h +++ b/gnu/dist/gcc/gcc/config/arm/arm.h @@ -555,6 +555,9 @@ extern int arm_fast_multiply; /* 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; diff --git a/gnu/dist/gcc/gcc/config/arm/arm.md b/gnu/dist/gcc/gcc/config/arm/arm.md index c0f40d28c675..3039d35861a5 100644 --- a/gnu/dist/gcc/gcc/config/arm/arm.md +++ b/gnu/dist/gcc/gcc/config/arm/arm.md @@ -6530,12 +6530,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); " @@ -6557,12 +6567,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) @@ -6573,23 +6594,6 @@ [(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" [(parallel [(set (match_operand 0 "" "") (call (match_operand 1 "memory_operand" "") @@ -6612,13 +6616,24 @@ }" ) -(define_insn "*call_value_reg" - [(set (match_operand 0 "" "=r,f") - (call (mem:SI (match_operand:SI 1 "s_register_operand" "r,r")) +(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]); " @@ -6627,8 +6642,8 @@ ) (define_insn "*call_value_mem" - [(set (match_operand 0 "" "=r,f") - (call (mem:SI (match_operand:SI 1 "memory_operand" "m,m")) + [(set (match_operand 0 "" "") + (call (mem:SI (match_operand:SI 1 "memory_operand" "m")) (match_operand 2 "" ""))) (use (match_operand 3 "" "")) (clobber (reg:SI LR_REGNUM))] @@ -6640,6 +6655,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. @@ -6659,8 +6703,8 @@ ) (define_insn "*call_value_symbol" - [(set (match_operand 0 "s_register_operand" "=r,f") - (call (mem:SI (match_operand:SI 1 "" "X,X")) + [(set (match_operand 0 "s_register_operand" "") + (call (mem:SI (match_operand:SI 1 "" "X")) (match_operand:SI 2 "" ""))) (use (match_operand 3 "" "")) (clobber (reg:SI LR_REGNUM))] @@ -6688,7 +6732,7 @@ ) (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")) (match_operand 2 "" ""))) (use (match_operand 3 "" "")) @@ -6742,8 +6786,8 @@ ) (define_insn "*sibcall_value_insn" - [(set (match_operand 0 "s_register_operand" "=r,f") - (call (mem:SI (match_operand:SI 1 "" "X,X")) + [(set (match_operand 0 "s_register_operand" "") + (call (mem:SI (match_operand:SI 1 "" "X")) (match_operand 2 "" ""))) (return) (use (match_operand 3 "" ""))] @@ -6937,6 +6981,7 @@ "" ) +;; NB Never uses BX. (define_insn "*arm_indirect_jump" [(set (pc) (match_operand:SI 0 "s_register_operand" "r"))] @@ -6945,8 +6990,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"))] @@ -6958,6 +7001,7 @@ (set_attr "predicable" "yes")] ) +;; NB Never uses BX. (define_insn "*thumb_indirect_jump" [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))] @@ -9104,6 +9148,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 "" "")))]