aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Thorpe <thorpej@gcc.gnu.org>2002-11-07 18:32:00 +0000
committerJason Thorpe <thorpej@gcc.gnu.org>2002-11-07 18:32:00 +0000
commit0977774ba0e8c40e13183a40300a255a803ecf89 (patch)
treeb440b7d0e8a2ef0a9d7bb246087b79a351005a5d /gcc
parentf150fe3fa7cc90fa7abd9bd64e4b5ccd6646d5a7 (diff)
downloadgcc-0977774ba0e8c40e13183a40300a255a803ecf89.zip
gcc-0977774ba0e8c40e13183a40300a255a803ecf89.tar.gz
gcc-0977774ba0e8c40e13183a40300a255a803ecf89.tar.bz2
[multiple changes]
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. From-SVN: r58901
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog24
-rw-r--r--gcc/config/arm/arm-protos.h2
-rw-r--r--gcc/config/arm/arm.c157
-rw-r--r--gcc/config/arm/arm.h6
4 files changed, 171 insertions, 18 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index fb73fe3..c167ca5 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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 %.
diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h
index 2055d14..671fe9d 100644
--- a/gcc/config/arm/arm-protos.h
+++ b/gcc/config/arm/arm-protos.h
@@ -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
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 5c0eea7..a51b95c 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -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. */
diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h
index 2f5ba3b..13da6f7 100644
--- a/gcc/config/arm/arm.h
+++ b/gcc/config/arm/arm.h
@@ -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 (); \
} \
}