OSDN Git Service

2002-11-07 Jason Thorpe <thorpej@wasabisystems.com>
authorthorpej <thorpej@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 7 Nov 2002 18:32:00 +0000 (18:32 +0000)
committerthorpej <thorpej@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 7 Nov 2002 18:32:00 +0000 (18:32 +0000)
* config/arm/arm-protos.h (arm_get_frame_size)
(thumb_get_frame_size): New prototypes.
* config/arm/arm.c (arm_get_frame_size)
(thumb_get_frame_size): New functions.
(use_return_insn, arm_output_epilogue, arm_output_function_epilogue)
(arm_compute_initial_elimination_offset, arm_expand_prologue): Use
arm_get_frame_size.
(thumb_expand_prologue, thumb_expand_epilogue): Use
thumb_get_frame_size.
* config/arm/arm.h (PREFERRED_STACK_BOUNDARY): Define.
(machine_function): Add frame_size member.
(THUMB_INITIAL_ELIMINATION_OFFSET): Use thumb_get_frame_size.

2002-11-07  Richard Earnshaw  <rearnsha@arm.com>

* arm.c (bit_count): Make argument unsigned long.  Return unsigned.
Adjust code to use portable unsigned bit manipulation.
(insn_flags, tune_flags): Change type to unsigned.
(struct processors): Make flags unsigned long.
(arm_override_options): Change type of count and current_bit_count
to unsigned.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@58901 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/arm/arm-protos.h
gcc/config/arm/arm.c
gcc/config/arm/arm.h

index fb73fe3..c167ca5 100644 (file)
@@ -1,3 +1,27 @@
+2002-11-07  Jason Thorpe  <thorpej@wasabisystems.com>
+  
+       * config/arm/arm-protos.h (arm_get_frame_size)
+       (thumb_get_frame_size): New prototypes.  
+       * config/arm/arm.c (arm_get_frame_size)
+       (thumb_get_frame_size): New functions.       
+       (use_return_insn, arm_output_epilogue, arm_output_function_epilogue) 
+       (arm_compute_initial_elimination_offset, arm_expand_prologue): Use  
+       arm_get_frame_size.
+       (thumb_expand_prologue, thumb_expand_epilogue): Use
+       thumb_get_frame_size.
+       * config/arm/arm.h (PREFERRED_STACK_BOUNDARY): Define.
+       (machine_function): Add frame_size member.
+       (THUMB_INITIAL_ELIMINATION_OFFSET): Use thumb_get_frame_size.
+
+2002-11-07  Richard Earnshaw  <rearnsha@arm.com>
+
+       * arm.c (bit_count): Make argument unsigned long.  Return unsigned.
+       Adjust code to use portable unsigned bit manipulation.
+       (insn_flags, tune_flags): Change type to unsigned.
+       (struct processors): Make flags unsigned long.
+       (arm_override_options): Change type of count and current_bit_count
+       to unsigned.
+
 2002-11-07  Richard Earnshaw  <rearnsha@arm.com>
 
        * arm/elf.h (TYPE_OPERAND_FMT): Prefix type with %.
index 2055d14..671fe9d 100644 (file)
@@ -31,6 +31,7 @@ extern void   arm_finalize_pic                PARAMS ((int));
 extern int    arm_volatile_func                PARAMS ((void));
 extern const char * arm_output_epilogue        PARAMS ((int));
 extern void   arm_expand_prologue      PARAMS ((void));
+extern HOST_WIDE_INT arm_get_frame_size        PARAMS ((void));
 /* Used in arm.md, but defined in output.c.  */
 extern void   assemble_align           PARAMS ((int)); 
 extern const char * arm_strip_name_encoding    PARAMS ((const char *));
@@ -160,6 +161,7 @@ extern int    arm_float_words_big_endian PARAMS ((void));
 extern void   arm_init_expanders       PARAMS ((void));
 extern int    thumb_far_jump_used_p    PARAMS ((int));
 extern const char * thumb_unexpanded_epilogue  PARAMS ((void));
+extern HOST_WIDE_INT thumb_get_frame_size PARAMS ((void));
 extern void   thumb_expand_prologue    PARAMS ((void));
 extern void   thumb_expand_epilogue    PARAMS ((void));
 #ifdef TREE_CODE
index 5c0eea7..a51b95c 100644 (file)
@@ -65,7 +65,7 @@ const struct attribute_spec arm_attribute_table[];
 /* Forward function declarations.  */
 static void      arm_add_gc_roots              PARAMS ((void));
 static int       arm_gen_constant              PARAMS ((enum rtx_code, Mmode, Hint, rtx, rtx, int, int));
-static Ulong     bit_count                     PARAMS ((signed int));
+static unsigned  bit_count                     PARAMS ((Ulong));
 static int       const_ok_for_op               PARAMS ((Hint, enum rtx_code));
 static int       eliminate_lr2ip               PARAMS ((rtx *));
 static rtx      emit_multi_reg_push            PARAMS ((int));
@@ -246,13 +246,13 @@ int    arm_structure_size_boundary = DEFAULT_STRUCTURE_SIZE_BOUNDARY;
 
 /* The bits in this mask specify which
    instructions we are allowed to generate.  */
-static int insn_flags = 0;
+static unsigned long insn_flags = 0;
 
 /* The bits in this mask specify which instruction scheduling options should
    be used.  Note - there is an overlap with the FL_FAST_MULT.  For some
    hardware we want to be able to generate the multiply instructions, but to
    tune as if they were not present in the architecture.  */
-static int tune_flags = 0;
+static unsigned long tune_flags = 0;
 
 /* The following are used in the arm.md file as equivalents to bits
    in the above two flag variables.  */
@@ -324,7 +324,7 @@ static const char * const arm_condition_codes[] =
 struct processors
 {
   const char *const name;
-  const unsigned int flags;
+  const unsigned long flags;
 };
 
 /* Not all of these give usefully different compilation alternatives,
@@ -412,17 +412,17 @@ struct arm_cpu_select arm_select[] =
   { NULL,      "-mtune=",      all_cores }
 };
 
-/* Return the number of bits set in value' */
-static unsigned long
+/* Return the number of bits set in VALUE.  */
+static unsigned
 bit_count (value)
-     signed int value;
+     unsigned long value;
 {
   unsigned long count = 0;
   
   while (value)
     {
-      value &= ~(value & -value);
-      ++count;
+      count++;
+      value &= value - 1;  /* Clear the least-significant set bit.  */
     }
 
   return count;
@@ -549,7 +549,7 @@ arm_override_options ()
 
          if (sel->name == NULL)
            {
-             unsigned int        current_bit_count = 0;
+             unsigned current_bit_count = 0;
              const struct processors * best_fit = NULL;
              
              /* Ideally we would like to issue an error message here
@@ -568,7 +568,7 @@ arm_override_options ()
              for (sel = all_cores; sel->name != NULL; sel++)
                if ((sel->flags & sought) == sought)
                  {
-                   unsigned int count;
+                   unsigned count;
 
                    count = bit_count (sel->flags & insn_flags);
 
@@ -928,7 +928,7 @@ use_return_insn (iscond)
       /* Of if the function calls __builtin_eh_return () */
       || ARM_FUNC_TYPE (func_type) == ARM_FT_EXCEPTION_HANDLER
       /* Or if there is no frame pointer and there is a stack adjustment.  */
-      || ((get_frame_size () + current_function_outgoing_args_size != 0)
+      || ((arm_get_frame_size () + current_function_outgoing_args_size != 0)
          && !frame_pointer_needed))
     return 0;
 
@@ -7564,7 +7564,7 @@ arm_output_epilogue (really_return)
      frame that is $fp + 4 for a non-variadic function.  */
   int floats_offset = 0;
   rtx operands[3];
-  int frame_size = get_frame_size ();
+  int frame_size = arm_get_frame_size ();
   FILE * f = asm_out_file;
   rtx eh_ofs = cfun->machine->eh_epilogue_sp_ofs;
 
@@ -7846,6 +7846,9 @@ arm_output_function_epilogue (file, frame_size)
     }
   else
     {
+      /* We need to take into account any stack-frame rounding.  */
+      frame_size = arm_get_frame_size ();
+
       if (use_return_insn (FALSE)
          && return_used_this_function
          && (frame_size + current_function_outgoing_args_size) != 0
@@ -8088,7 +8091,7 @@ arm_compute_initial_elimination_offset (from, to)
      unsigned int from;
      unsigned int to;
 {
-  unsigned int local_vars    = (get_frame_size () + 3) & ~3;
+  unsigned int local_vars    = arm_get_frame_size ();
   unsigned int outgoing_args = current_function_outgoing_args_size;
   unsigned int stack_frame;
   unsigned int call_saved_registers;
@@ -8209,6 +8212,51 @@ arm_compute_initial_elimination_offset (from, to)
     }
 }
 
+/* Calculate the size of the stack frame, taking into account any
+   padding that is required to ensure stack-alignment.  */
+
+HOST_WIDE_INT
+arm_get_frame_size ()
+{
+  int regno;
+
+  int base_size = ROUND_UP (get_frame_size ());
+  int entry_size = 0;
+  unsigned long func_type = arm_current_func_type ();
+
+  if (! TARGET_ARM)
+    abort();
+
+  if (! TARGET_ATPCS)
+    return base_size;
+
+  /* We know that SP will be word aligned on entry, and we must
+     preserve that condition at any subroutine call.  But those are
+     the only constraints.  */
+
+  /* Space for variadic functions.  */
+  if (current_function_pretend_args_size)
+    entry_size += current_function_pretend_args_size;
+
+  /* Space for saved registers.  */
+  entry_size += bit_count (arm_compute_save_reg_mask ()) * 4;
+
+  /* Space for saved FPA registers.  */
+  if (! IS_VOLATILE (func_type))
+    {
+      for (regno = FIRST_ARM_FP_REGNUM; regno <= LAST_ARM_FP_REGNUM; regno++)
+      if (regs_ever_live[regno] && ! call_used_regs[regno])
+       entry_size += 12;
+    }
+
+  if ((entry_size + base_size + current_function_outgoing_args_size) & 7)
+    base_size += 4;
+  if ((entry_size + base_size + current_function_outgoing_args_size) & 7)
+    abort ();
+
+  return base_size;
+}
+
 /* Generate the prologue instructions for entry into an ARM function.  */
 
 void
@@ -8444,7 +8492,7 @@ arm_expand_prologue ()
        }
     }
 
-  amount = GEN_INT (-(get_frame_size ()
+  amount = GEN_INT (-(arm_get_frame_size ()
                      + current_function_outgoing_args_size));
 
   if (amount != const0_rtx)
@@ -10193,12 +10241,87 @@ arm_init_expanders ()
   init_machine_status = arm_init_machine_status;
 }
 
+HOST_WIDE_INT
+thumb_get_frame_size ()
+{
+  int regno;
+
+  int base_size = ROUND_UP (get_frame_size ());
+  int count_regs = 0;
+  int entry_size = 0;
+
+  if (! TARGET_THUMB)
+    abort ();
+
+  if (! TARGET_ATPCS)
+    return base_size;
+
+  /* We need to know if we are a leaf function.  Unfortunately, it
+     is possible to be called after start_sequence has been called,
+     which causes get_insns to return the insns for the sequence,
+     not the function, which will cause leaf_function_p to return
+     the incorrect result.
+
+     To work around this, we cache the computed frame size.  This
+     works because we will only be calling RTL expanders that need
+     to know about leaf functions once reload has completed, and the
+     frame size cannot be changed after that time, so we can safely
+     use the cached value.  */
+
+  if (reload_completed)
+    return cfun->machine->frame_size;
+
+  /* We know that SP will be word aligned on entry, and we must
+     preserve that condition at any subroutine call.  But those are
+     the only constraints.  */
+
+  /* Space for variadic functions.  */
+  if (current_function_pretend_args_size)
+    entry_size += current_function_pretend_args_size;
+
+  /* Space for pushed lo registers.  */
+  for (regno = 0; regno <= LAST_LO_REGNUM; regno++)
+    if (THUMB_REG_PUSHED_P (regno))
+      count_regs++;
+
+  /* Space for backtrace structure.  */
+  if (TARGET_BACKTRACE)
+    {
+      if (count_regs == 0 && regs_ever_live[LAST_ARG_REGNUM] != 0)
+       entry_size += 20;
+      else
+       entry_size += 16;
+    }
+
+  if (count_regs || !leaf_function_p () || thumb_far_jump_used_p (1))
+    count_regs++;      /* LR */
+
+  entry_size += count_regs * 4;
+  count_regs = 0;
+
+  /* Space for pushed hi regs.  */
+  for (regno = 8; regno < 13; regno++)
+    if (THUMB_REG_PUSHED_P (regno))
+      count_regs++;
+
+  entry_size += count_regs * 4;
+
+  if ((entry_size + base_size + current_function_outgoing_args_size) & 7)
+    base_size += 4;
+  if ((entry_size + base_size + current_function_outgoing_args_size) & 7)
+    abort ();
+
+  cfun->machine->frame_size = base_size;
+
+  return base_size;
+}
+
 /* Generate the rest of a function's prologue.  */
 
 void
 thumb_expand_prologue ()
 {
-  HOST_WIDE_INT amount = (get_frame_size ()
+  HOST_WIDE_INT amount = (thumb_get_frame_size ()
                          + current_function_outgoing_args_size);
   unsigned long func_type;
 
@@ -10293,7 +10416,7 @@ thumb_expand_prologue ()
 void
 thumb_expand_epilogue ()
 {
-  HOST_WIDE_INT amount = (get_frame_size ()
+  HOST_WIDE_INT amount = (thumb_get_frame_size ()
                          + current_function_outgoing_args_size);
   
   /* Naked functions don't have prologues.  */
index 2f5ba3b..13da6f7 100644 (file)
@@ -689,6 +689,8 @@ extern int arm_is_6_or_7;
 
 #define STACK_BOUNDARY  32
 
+#define PREFERRED_STACK_BOUNDARY (TARGET_ATPCS ? 64 : 32)
+
 #define FUNCTION_BOUNDARY  32
 
 /* The lowest bit is used to indicate Thumb-mode functions, so the
@@ -1436,6 +1438,8 @@ typedef struct machine_function GTY(())
   int arg_pointer_live;
   /* Records if the save of LR has been eliminated.  */
   int lr_save_eliminated;
+  /* The size of the stack frame.  Only valid after reload.  */
+  int frame_size;
   /* Records the type of the current function.  */
   unsigned long func_type;
   /* Record if the function has a variable argument list.  */
@@ -1679,7 +1683,7 @@ typedef struct
   if ((TO) == STACK_POINTER_REGNUM)                                    \
     {                                                                  \
       (OFFSET) += current_function_outgoing_args_size;                 \
-      (OFFSET) += ROUND_UP (get_frame_size ());                                \
+      (OFFSET) += thumb_get_frame_size ();                             \
      }                                                                 \
 }