[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
This commit is contained in:
parent
f150fe3fa7
commit
0977774ba0
@ -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 %.
|
||||
|
@ -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
|
||||
|
@ -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. */
|
||||
|
@ -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 (); \
|
||||
} \
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user