diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index b1dabd3def0589206970199901c58129763eccf1..f7583c26fbc28ec46b5dad712aade59876ab608f 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,11 @@
+2009-12-24  Julian Brown  <julian@codesourcery.com>
+            Ramana Radhakrishnan  <ramana.radhakrishnan@arm.com>
+
+        PR target/40887
+        * config/arm/arm.c (output_call_mem): Remove armv5 support.
+        * config/arm/arm.md (*call_mem): Disable for armv5. Add note.
+        (*call_value_mem): Likewise.
+
 2009-12-23  Jakub Jelinek  <jakub@redhat.com>
 
 	PR rtl-optimization/42475
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index a9ad903e81d4a3c673d8fce85391a37b2dfe6535..e9ea2bd1ca0cdcbb987094839f51fb00f71a0b78 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -11772,11 +11772,14 @@ output_call (rtx *operands)
   return "";
 }
 
-/* Output a 'call' insn that is a reference in memory.  */
+/* Output a 'call' insn that is a reference in memory. This is
+   disabled for ARMv5 and we prefer a blx instead because otherwise
+   there's a significant performance overhead.  */
 const char *
 output_call_mem (rtx *operands)
 {
-  if (TARGET_INTERWORK && !arm_arch5)
+  gcc_assert (!arm_arch5);
+  if (TARGET_INTERWORK)
     {
       output_asm_insn ("ldr%?\t%|ip, %0", operands);
       output_asm_insn ("mov%?\t%|lr, %|pc", operands);
@@ -11788,16 +11791,11 @@ 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);
-      if (arm_arch5)
-	output_asm_insn ("blx%?\t%|ip", operands);
+      output_asm_insn ("mov%?\t%|lr, %|pc", operands);
+      if (arm_arch4t)
+	output_asm_insn ("bx%?\t%|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);
-	}
+	output_asm_insn ("mov%?\t%|pc, %|ip", operands);
     }
   else
     {
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index e79ef15fa7d57bd9cb5d4e97ad47eb1b631cb5a3..cbb0a1bdf1439e099cfcc9277ed226dcf7c102ac 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -8453,12 +8453,17 @@
    (set_attr "type" "call")]
 )
 
+
+;; Note: not used for armv5+ because the sequence used (ldr pc, ...) is not
+;; considered a function call by the branch predictor of some cores (PR40887).
+;; Falls back to blx rN (*call_reg_armv5).
+
 (define_insn "*call_mem"
   [(call (mem:SI (match_operand:SI 0 "call_memory_operand" "m"))
 	 (match_operand 1 "" ""))
    (use (match_operand 2 "" ""))
    (clobber (reg:SI LR_REGNUM))]
-  "TARGET_ARM"
+  "TARGET_ARM && !arm_arch5"
   "*
   return output_call_mem (operands);
   "
@@ -8560,13 +8565,15 @@
    (set_attr "type" "call")]
 )
 
+;; Note: see *call_mem
+
 (define_insn "*call_value_mem"
   [(set (match_operand 0 "" "")
 	(call (mem:SI (match_operand:SI 1 "call_memory_operand" "m"))
 	      (match_operand 2 "" "")))
    (use (match_operand 3 "" ""))
    (clobber (reg:SI LR_REGNUM))]
-  "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
+  "TARGET_ARM && !arm_arch5 && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
   "*
   return output_call_mem (&operands[1]);
   "
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 98d85f4465f9a5c2e89fb4bdadac2efb0759db60..f2d89276540ba4877b5068b4cf5e98d5e07d64dd 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2009-12-24  Julian Brown  <julian@codesourcery.com>
+            Ramana Radhakrishnan  <ramana.radhakrishnan@arm.com>
+
+        PR target/40887
+	* gcc.target/arm/pr40887.c: New test.
+
 2009-12-23  Jakub Jelinek  <jakub@redhat.com>
 
 	PR rtl-optimization/42475
diff --git a/gcc/testsuite/gcc.target/arm/pr40887.c b/gcc/testsuite/gcc.target/arm/pr40887.c
new file mode 100644
index 0000000000000000000000000000000000000000..ca896fc166691cf0b3d526279b130f39daf9aa1c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pr40887.c
@@ -0,0 +1,9 @@
+/* { dg-options "-O2 -march=armv5te" }  */
+/* { dg-final { scan-assembler "blx" } } */
+
+int (*indirect_func)();
+
+int indirect_call()
+{
+    return indirect_func();
+}