arm.h (arm_stack_offsets): Add locals_base field.
authorRichard Earnshaw <rearnsha@arm.com>
Sat, 20 Aug 2005 10:31:42 +0000 (10:31 +0000)
committerRichard Earnshaw <rearnsha@gcc.gnu.org>
Sat, 20 Aug 2005 10:31:42 +0000 (10:31 +0000)
* arm.h (arm_stack_offsets): Add locals_base field.
* arm.c (arm_get_frame_offsets): Compute it.
(thumb_compute_initial_elimination offset): Make the Thumb frame
pointer point to the base of the local variables.
(thumb_expand_prologue): Update accordingly.
(thumb_expand_epilogue): Likewise.

* arm.md (thumb_movhi_clobber): Make this insn a define_expand.  Change
mode of clobbered scratch to DImode.  Handle a case that's known to
need this.

From-SVN: r103301

gcc/ChangeLog
gcc/config/arm/arm.c
gcc/config/arm/arm.h
gcc/config/arm/arm.md

index 949087e..795baf1 100644 (file)
@@ -1,3 +1,16 @@
+2005-08-20  Richard Earnshaw  <richard.earnshaw@arm.com>
+
+       * arm.h (arm_stack_offsets): Add locals_base field.
+       * arm.c (arm_get_frame_offsets): Compute it.
+       (thumb_compute_initial_elimination offset): Make the Thumb frame
+       pointer point to the base of the local variables.
+       (thumb_expand_prologue): Update accordingly.
+       (thumb_expand_epilogue): Likewise.
+
+       * arm.md (thumb_movhi_clobber): Make this insn a define_expand.  Change
+       mode of clobbered scratch to DImode.  Handle a case that's known to
+       need this.
+
 2005-08-19  David Edelsohn  <edelsohn@gnu.org>
 
        * config/rs6000/rs6000.md (gt0<mode>): Delete.
index 0235c53..9037838 100644 (file)
@@ -9992,7 +9992,7 @@ thumb_force_lr_save (void)
                             |    | \
                             |    |   local
                             |    |   variables
-                            |    | /
+     locals base pointer -> |    | /
                               --
                             |    | \
                             |    |   outgoing
@@ -10109,8 +10109,9 @@ arm_get_frame_offsets (void)
       && (offsets->soft_frame & 7))
     offsets->soft_frame += 4;
 
-  offsets->outgoing_args = offsets->soft_frame + frame_size
-                          + current_function_outgoing_args_size;
+  offsets->locals_base = offsets->soft_frame + frame_size;
+  offsets->outgoing_args = (offsets->locals_base
+                           + current_function_outgoing_args_size);
 
   if (ARM_DOUBLEWORD_ALIGN)
     {
@@ -13158,8 +13159,10 @@ arm_init_expanders (void)
 }
 
 
-/* Like arm_compute_initial_elimination offset.  Simpler because
-   THUMB_HARD_FRAME_POINTER isn't actually the ABI specified frame pointer.  */
+/* Like arm_compute_initial_elimination offset.  Simpler because there
+   isn't an ABI specified frame pointer for Thumb.  Instead, we set it
+   to point at the base of the local variables after static stack
+   space for a function has been allocated.  */
 
 HOST_WIDE_INT
 thumb_compute_initial_elimination_offset (unsigned int from, unsigned int to)
@@ -13179,10 +13182,12 @@ thumb_compute_initial_elimination_offset (unsigned int from, unsigned int to)
        case FRAME_POINTER_REGNUM:
          return offsets->soft_frame - offsets->saved_args;
 
-       case THUMB_HARD_FRAME_POINTER_REGNUM:
        case ARM_HARD_FRAME_POINTER_REGNUM:
          return offsets->saved_regs - offsets->saved_args;
 
+       case THUMB_HARD_FRAME_POINTER_REGNUM:
+         return offsets->locals_base - offsets->saved_args;
+
        default:
          gcc_unreachable ();
        }
@@ -13194,10 +13199,12 @@ thumb_compute_initial_elimination_offset (unsigned int from, unsigned int to)
        case STACK_POINTER_REGNUM:
          return offsets->outgoing_args - offsets->soft_frame;
 
-       case THUMB_HARD_FRAME_POINTER_REGNUM:
        case ARM_HARD_FRAME_POINTER_REGNUM:
          return offsets->saved_regs - offsets->soft_frame;
 
+       case THUMB_HARD_FRAME_POINTER_REGNUM:
+         return offsets->locals_base - offsets->soft_frame;
+
        default:
          gcc_unreachable ();
        }
@@ -13239,18 +13246,11 @@ thumb_expand_prologue (void)
   if (flag_pic)
     arm_load_pic_register (live_regs_mask);
 
-  offsets = arm_get_frame_offsets ();
-
-  if (frame_pointer_needed)
-    {
-      insn = emit_insn (gen_movsi (hard_frame_pointer_rtx,
-                                  stack_pointer_rtx));
-      RTX_FRAME_RELATED_P (insn) = 1;
-    }
-  else if (CALLER_INTERWORKING_SLOT_SIZE > 0)
+  if (!frame_pointer_needed && CALLER_INTERWORKING_SLOT_SIZE > 0)
     emit_move_insn (gen_rtx_REG (Pmode, ARM_HARD_FRAME_POINTER_REGNUM),
                    stack_pointer_rtx);
 
+  offsets = arm_get_frame_offsets ();
   amount = offsets->outgoing_args - offsets->saved_regs;
   if (amount)
     {
@@ -13336,12 +13336,29 @@ thumb_expand_prologue (void)
                                     REG_NOTES (insn));
            }
        }
-      /* If the frame pointer is needed, emit a special barrier that
-        will prevent the scheduler from moving stores to the frame
-        before the stack adjustment.  */
-      if (frame_pointer_needed)
-       emit_insn (gen_stack_tie (stack_pointer_rtx,
-                                 hard_frame_pointer_rtx));
+    }
+
+  if (frame_pointer_needed)
+    {
+      amount = offsets->outgoing_args - offsets->locals_base;
+      
+      if (amount < 1024)
+       insn = emit_insn (gen_addsi3 (hard_frame_pointer_rtx,
+                                     stack_pointer_rtx, GEN_INT (amount)));
+      else
+       {
+         emit_insn (gen_movsi (hard_frame_pointer_rtx, GEN_INT (amount)));
+         insn = emit_insn (gen_addsi3 (hard_frame_pointer_rtx,
+                                       hard_frame_pointer_rtx,
+                                       stack_pointer_rtx));
+         dwarf = gen_rtx_SET (SImode, hard_frame_pointer_rtx,
+                              plus_constant (stack_pointer_rtx, amount));
+         RTX_FRAME_RELATED_P (dwarf) = 1;
+         REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR, dwarf,
+                                               REG_NOTES (insn));
+       }
+
+      RTX_FRAME_RELATED_P (insn) = 1;
     }
 
   if (current_function_profile || !TARGET_SCHED_PROLOG)
@@ -13373,8 +13390,12 @@ thumb_expand_epilogue (void)
   amount = offsets->outgoing_args - offsets->saved_regs;
 
   if (frame_pointer_needed)
-    emit_insn (gen_movsi (stack_pointer_rtx, hard_frame_pointer_rtx));
-  else if (amount)
+    {
+      emit_insn (gen_movsi (stack_pointer_rtx, hard_frame_pointer_rtx));
+      amount = offsets->locals_base - offsets->saved_regs;
+    }
+  
+  if (amount)
     {
       if (amount < 512)
        emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
index a434d4f..64b5e37 100644 (file)
@@ -1476,6 +1476,7 @@ typedef struct arm_stack_offsets GTY(())
   int frame;           /* ARM_HARD_FRAME_POINTER_REGNUM.  */
   int saved_regs;
   int soft_frame;      /* FRAME_POINTER_REGNUM.  */
+  int locals_base;     /* THUMB_HARD_FRAME_POINTER_REGNUM.  */
   int outgoing_args;   /* STACK_POINTER_REGNUM.  */
 }
 arm_stack_offsets;
index eaa7d51..3bc62de 100644 (file)
   [(set_attr "predicable" "yes")]
 )
 
-(define_insn "thumb_movhi_clobber"
-  [(set (match_operand:HI     0 "memory_operand"   "=m")
-       (match_operand:HI     1 "register_operand" "l"))
-   (clobber (match_operand:SI 2 "register_operand" "=&l"))]
+(define_expand "thumb_movhi_clobber"
+  [(set (match_operand:HI     0 "memory_operand"   "")
+       (match_operand:HI     1 "register_operand" ""))
+   (clobber (match_operand:DI 2 "register_operand" ""))]
   "TARGET_THUMB"
-  "*
-  gcc_unreachable ();"
+  "
+  if (strict_memory_address_p (HImode, XEXP (operands[0], 0))
+      && REGNO (operands[1]) <= LAST_LO_REGNUM)
+    {
+      emit_insn (gen_movhi (operands[0], operands[1]));
+      DONE;
+    }
+  /* XXX Fixme, need to handle other cases here as well.  */
+  gcc_unreachable ();
+  "
 )
        
 ;; We use a DImode scratch because we may occasionally need an additional