150-arm-ldm.patch 3.4 KB
Newer Older
ZHJ0125's avatar
ZHJ0125 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
diff -durN gcc-3.4.6.orig/gcc/config/arm/arm.c gcc-3.4.6/gcc/config/arm/arm.c
--- gcc-3.4.6.orig/gcc/config/arm/arm.c	2007-08-15 22:56:20.000000000 +0200
+++ gcc-3.4.6/gcc/config/arm/arm.c	2007-08-15 22:56:20.000000000 +0200
@@ -8524,6 +8524,26 @@
   return_used_this_function = 0;  
 }
 
+/* Return the number (counting from 0) of
+   the least significant set bit in MASK.  */
+
+#ifdef __GNUC__
+inline
+#endif
+static int
+number_of_first_bit_set (mask)
+     int mask;
+{
+  int bit;
+
+  for (bit = 0;
+       (mask & (1 << bit)) == 0;
+       ++bit)
+    continue;
+
+  return bit;
+}
+
 const char *
 arm_output_epilogue (rtx sibling)
 {
@@ -8757,27 +8777,47 @@
 	  saved_regs_mask |=   (1 << PC_REGNUM);
 	}
 
-      /* Load the registers off the stack.  If we only have one register
-	 to load use the LDR instruction - it is faster.  */
-      if (saved_regs_mask == (1 << LR_REGNUM))
-	{
-	  /* The exception handler ignores the LR, so we do
-	     not really need to load it off the stack.  */
-	  if (eh_ofs)
-	    asm_fprintf (f, "\tadd\t%r, %r, #4\n", SP_REGNUM, SP_REGNUM);
-	  else
-	    asm_fprintf (f, "\tldr\t%r, [%r], #4\n", LR_REGNUM, SP_REGNUM);
-	}
-      else if (saved_regs_mask)
+      if (saved_regs_mask)
 	{
-	  if (saved_regs_mask & (1 << SP_REGNUM))
-	    /* Note - write back to the stack register is not enabled
-	       (ie "ldmfd sp!...").  We know that the stack pointer is
-	       in the list of registers and if we add writeback the
-	       instruction becomes UNPREDICTABLE.  */
-	    print_multi_reg (f, "ldmfd\t%r", SP_REGNUM, saved_regs_mask);
+	  /* Load the registers off the stack.  If we only have one register
+	     to load use the LDR instruction - it is faster.  */
+	  if (bit_count (saved_regs_mask) == 1)
+	    {
+	      int reg = number_of_first_bit_set (saved_regs_mask);
+
+	      switch (reg)
+		{
+		case SP_REGNUM:
+		  /* Mustn't use base writeback when loading SP.  */
+		  asm_fprintf (f, "\tldr\t%r, [%r]\n", SP_REGNUM, SP_REGNUM);
+		  break;
+		  
+		case LR_REGNUM:
+		  if (eh_ofs)
+		    {
+		      /* The exception handler ignores the LR, so we do
+			 not really need to load it off the stack.  */
+		      asm_fprintf (f, "\tadd\t%r, %r, #4\n", SP_REGNUM, SP_REGNUM);
+		      break;
+		    }
+		  /* else fall through */
+		  
+		default:
+		  asm_fprintf (f, "\tldr\t%r, [%r], #4\n", reg, SP_REGNUM);
+		  break;
+		}
+	    }
 	  else
-	    print_multi_reg (f, "ldmfd\t%r!", SP_REGNUM, saved_regs_mask);
+	    {
+	      if (saved_regs_mask & (1 << SP_REGNUM))
+		/* Note - write back to the stack register is not enabled
+		   (ie "ldmfd sp!...").  We know that the stack pointer is
+		   in the list of registers and if we add writeback the
+		   instruction becomes UNPREDICTABLE.  */
+		print_multi_reg (f, "ldmfd\t%r", SP_REGNUM, saved_regs_mask);
+	      else
+		print_multi_reg (f, "ldmfd\t%r!", SP_REGNUM, saved_regs_mask);
+	    }
 	}
 
       if (current_function_pretend_args_size)
@@ -11405,22 +11445,6 @@
     }
 }
 
-/* Return the number (counting from 0) of
-   the least significant set bit in MASK.  */
-
-inline static int
-number_of_first_bit_set (int mask)
-{
-  int bit;
-
-  for (bit = 0;
-       (mask & (1 << bit)) == 0;
-       ++bit)
-    continue;
-
-  return bit;
-}
-
 /* Generate code to return from a thumb function.
    If 'reg_containing_return_addr' is -1, then the return address is
    actually on the stack, at the stack pointer.  */