[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>
|
2002-11-07 Richard Earnshaw <rearnsha@arm.com>
|
||||||
|
|
||||||
* arm/elf.h (TYPE_OPERAND_FMT): Prefix type with %.
|
* 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 int arm_volatile_func PARAMS ((void));
|
||||||
extern const char * arm_output_epilogue PARAMS ((int));
|
extern const char * arm_output_epilogue PARAMS ((int));
|
||||||
extern void arm_expand_prologue PARAMS ((void));
|
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. */
|
/* Used in arm.md, but defined in output.c. */
|
||||||
extern void assemble_align PARAMS ((int));
|
extern void assemble_align PARAMS ((int));
|
||||||
extern const char * arm_strip_name_encoding PARAMS ((const char *));
|
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 void arm_init_expanders PARAMS ((void));
|
||||||
extern int thumb_far_jump_used_p PARAMS ((int));
|
extern int thumb_far_jump_used_p PARAMS ((int));
|
||||||
extern const char * thumb_unexpanded_epilogue PARAMS ((void));
|
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_prologue PARAMS ((void));
|
||||||
extern void thumb_expand_epilogue PARAMS ((void));
|
extern void thumb_expand_epilogue PARAMS ((void));
|
||||||
#ifdef TREE_CODE
|
#ifdef TREE_CODE
|
||||||
|
|
|
@ -65,7 +65,7 @@ const struct attribute_spec arm_attribute_table[];
|
||||||
/* Forward function declarations. */
|
/* Forward function declarations. */
|
||||||
static void arm_add_gc_roots PARAMS ((void));
|
static void arm_add_gc_roots PARAMS ((void));
|
||||||
static int arm_gen_constant PARAMS ((enum rtx_code, Mmode, Hint, rtx, rtx, int, int));
|
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 const_ok_for_op PARAMS ((Hint, enum rtx_code));
|
||||||
static int eliminate_lr2ip PARAMS ((rtx *));
|
static int eliminate_lr2ip PARAMS ((rtx *));
|
||||||
static rtx emit_multi_reg_push PARAMS ((int));
|
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
|
/* The bits in this mask specify which
|
||||||
instructions we are allowed to generate. */
|
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
|
/* 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
|
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
|
hardware we want to be able to generate the multiply instructions, but to
|
||||||
tune as if they were not present in the architecture. */
|
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
|
/* The following are used in the arm.md file as equivalents to bits
|
||||||
in the above two flag variables. */
|
in the above two flag variables. */
|
||||||
|
@ -324,7 +324,7 @@ static const char * const arm_condition_codes[] =
|
||||||
struct processors
|
struct processors
|
||||||
{
|
{
|
||||||
const char *const name;
|
const char *const name;
|
||||||
const unsigned int flags;
|
const unsigned long flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Not all of these give usefully different compilation alternatives,
|
/* Not all of these give usefully different compilation alternatives,
|
||||||
|
@ -412,17 +412,17 @@ struct arm_cpu_select arm_select[] =
|
||||||
{ NULL, "-mtune=", all_cores }
|
{ NULL, "-mtune=", all_cores }
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Return the number of bits set in value' */
|
/* Return the number of bits set in VALUE. */
|
||||||
static unsigned long
|
static unsigned
|
||||||
bit_count (value)
|
bit_count (value)
|
||||||
signed int value;
|
unsigned long value;
|
||||||
{
|
{
|
||||||
unsigned long count = 0;
|
unsigned long count = 0;
|
||||||
|
|
||||||
while (value)
|
while (value)
|
||||||
{
|
{
|
||||||
value &= ~(value & -value);
|
count++;
|
||||||
++count;
|
value &= value - 1; /* Clear the least-significant set bit. */
|
||||||
}
|
}
|
||||||
|
|
||||||
return count;
|
return count;
|
||||||
|
@ -549,7 +549,7 @@ arm_override_options ()
|
||||||
|
|
||||||
if (sel->name == NULL)
|
if (sel->name == NULL)
|
||||||
{
|
{
|
||||||
unsigned int current_bit_count = 0;
|
unsigned current_bit_count = 0;
|
||||||
const struct processors * best_fit = NULL;
|
const struct processors * best_fit = NULL;
|
||||||
|
|
||||||
/* Ideally we would like to issue an error message here
|
/* 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++)
|
for (sel = all_cores; sel->name != NULL; sel++)
|
||||||
if ((sel->flags & sought) == sought)
|
if ((sel->flags & sought) == sought)
|
||||||
{
|
{
|
||||||
unsigned int count;
|
unsigned count;
|
||||||
|
|
||||||
count = bit_count (sel->flags & insn_flags);
|
count = bit_count (sel->flags & insn_flags);
|
||||||
|
|
||||||
|
@ -928,7 +928,7 @@ use_return_insn (iscond)
|
||||||
/* Of if the function calls __builtin_eh_return () */
|
/* Of if the function calls __builtin_eh_return () */
|
||||||
|| ARM_FUNC_TYPE (func_type) == ARM_FT_EXCEPTION_HANDLER
|
|| ARM_FUNC_TYPE (func_type) == ARM_FT_EXCEPTION_HANDLER
|
||||||
/* Or if there is no frame pointer and there is a stack adjustment. */
|
/* 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))
|
&& !frame_pointer_needed))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -7564,7 +7564,7 @@ arm_output_epilogue (really_return)
|
||||||
frame that is $fp + 4 for a non-variadic function. */
|
frame that is $fp + 4 for a non-variadic function. */
|
||||||
int floats_offset = 0;
|
int floats_offset = 0;
|
||||||
rtx operands[3];
|
rtx operands[3];
|
||||||
int frame_size = get_frame_size ();
|
int frame_size = arm_get_frame_size ();
|
||||||
FILE * f = asm_out_file;
|
FILE * f = asm_out_file;
|
||||||
rtx eh_ofs = cfun->machine->eh_epilogue_sp_ofs;
|
rtx eh_ofs = cfun->machine->eh_epilogue_sp_ofs;
|
||||||
|
|
||||||
|
@ -7846,6 +7846,9 @@ arm_output_function_epilogue (file, frame_size)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
/* We need to take into account any stack-frame rounding. */
|
||||||
|
frame_size = arm_get_frame_size ();
|
||||||
|
|
||||||
if (use_return_insn (FALSE)
|
if (use_return_insn (FALSE)
|
||||||
&& return_used_this_function
|
&& return_used_this_function
|
||||||
&& (frame_size + current_function_outgoing_args_size) != 0
|
&& (frame_size + current_function_outgoing_args_size) != 0
|
||||||
|
@ -8088,7 +8091,7 @@ arm_compute_initial_elimination_offset (from, to)
|
||||||
unsigned int from;
|
unsigned int from;
|
||||||
unsigned int to;
|
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 outgoing_args = current_function_outgoing_args_size;
|
||||||
unsigned int stack_frame;
|
unsigned int stack_frame;
|
||||||
unsigned int call_saved_registers;
|
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. */
|
/* Generate the prologue instructions for entry into an ARM function. */
|
||||||
|
|
||||||
void
|
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));
|
+ current_function_outgoing_args_size));
|
||||||
|
|
||||||
if (amount != const0_rtx)
|
if (amount != const0_rtx)
|
||||||
|
@ -10193,12 +10241,87 @@ arm_init_expanders ()
|
||||||
init_machine_status = arm_init_machine_status;
|
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. */
|
/* Generate the rest of a function's prologue. */
|
||||||
|
|
||||||
void
|
void
|
||||||
thumb_expand_prologue ()
|
thumb_expand_prologue ()
|
||||||
{
|
{
|
||||||
HOST_WIDE_INT amount = (get_frame_size ()
|
HOST_WIDE_INT amount = (thumb_get_frame_size ()
|
||||||
+ current_function_outgoing_args_size);
|
+ current_function_outgoing_args_size);
|
||||||
unsigned long func_type;
|
unsigned long func_type;
|
||||||
|
|
||||||
|
@ -10293,7 +10416,7 @@ thumb_expand_prologue ()
|
||||||
void
|
void
|
||||||
thumb_expand_epilogue ()
|
thumb_expand_epilogue ()
|
||||||
{
|
{
|
||||||
HOST_WIDE_INT amount = (get_frame_size ()
|
HOST_WIDE_INT amount = (thumb_get_frame_size ()
|
||||||
+ current_function_outgoing_args_size);
|
+ current_function_outgoing_args_size);
|
||||||
|
|
||||||
/* Naked functions don't have prologues. */
|
/* Naked functions don't have prologues. */
|
||||||
|
|
|
@ -689,6 +689,8 @@ extern int arm_is_6_or_7;
|
||||||
|
|
||||||
#define STACK_BOUNDARY 32
|
#define STACK_BOUNDARY 32
|
||||||
|
|
||||||
|
#define PREFERRED_STACK_BOUNDARY (TARGET_ATPCS ? 64 : 32)
|
||||||
|
|
||||||
#define FUNCTION_BOUNDARY 32
|
#define FUNCTION_BOUNDARY 32
|
||||||
|
|
||||||
/* The lowest bit is used to indicate Thumb-mode functions, so the
|
/* 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;
|
int arg_pointer_live;
|
||||||
/* Records if the save of LR has been eliminated. */
|
/* Records if the save of LR has been eliminated. */
|
||||||
int lr_save_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. */
|
/* Records the type of the current function. */
|
||||||
unsigned long func_type;
|
unsigned long func_type;
|
||||||
/* Record if the function has a variable argument list. */
|
/* Record if the function has a variable argument list. */
|
||||||
|
@ -1679,7 +1683,7 @@ typedef struct
|
||||||
if ((TO) == STACK_POINTER_REGNUM) \
|
if ((TO) == STACK_POINTER_REGNUM) \
|
||||||
{ \
|
{ \
|
||||||
(OFFSET) += current_function_outgoing_args_size; \
|
(OFFSET) += current_function_outgoing_args_size; \
|
||||||
(OFFSET) += ROUND_UP (get_frame_size ()); \
|
(OFFSET) += thumb_get_frame_size (); \
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue