summaryrefslogtreecommitdiff
path: root/gcc/config/avr/avr.c
diff options
context:
space:
mode:
authorbstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4>2008-05-23 09:19:59 +0000
committerbstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4>2008-05-23 09:19:59 +0000
commit14fe89dbbbdfb8dd1b0211c508bf67bee8ff7eca (patch)
tree90d249c04b656468b1035211af60b276e9a62992 /gcc/config/avr/avr.c
parentef6304520b84aaf884d6ef65ca01226adf273b51 (diff)
downloadgcc-14fe89dbbbdfb8dd1b0211c508bf67bee8ff7eca.tar.gz
2008-05-22 Basile Starynkevitch <basile@starynkevitch.net>
MELT branch merged with trunk r135793 git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/melt-branch@135794 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config/avr/avr.c')
-rw-r--r--gcc/config/avr/avr.c174
1 files changed, 102 insertions, 72 deletions
diff --git a/gcc/config/avr/avr.c b/gcc/config/avr/avr.c
index 1293a4b3463..012a7e4fd1b 100644
--- a/gcc/config/avr/avr.c
+++ b/gcc/config/avr/avr.c
@@ -54,6 +54,7 @@ static int signal_function_p (tree);
static int avr_OS_task_function_p (tree);
static int avr_OS_main_function_p (tree);
static int avr_regs_to_save (HARD_REG_SET *);
+static int get_sequence_length (rtx insns);
static int sequent_regs_live (void);
static const char *ptrreg_to_str (int);
static const char *cond_string (enum rtx_code);
@@ -585,6 +586,20 @@ sequent_regs_live (void)
return (cur_seq == live_seq) ? live_seq : 0;
}
+/* Obtain the length sequence of insns. */
+
+int
+get_sequence_length (rtx insns)
+{
+ rtx insn;
+ int length;
+
+ for (insn = insns, length = 0; insn; insn = NEXT_INSN (insn))
+ length += get_attr_length (insn);
+
+ return length;
+}
+
/* Output function prologue. */
void
@@ -718,12 +733,11 @@ expand_prologue (void)
To avoid a complex logic, both methods are tested and shortest
is selected. */
rtx myfp;
- /* First method. */
+ rtx fp_plus_insns;
+ rtx sp_plus_insns = NULL_RTX;
+
if (TARGET_TINY_STACK)
{
- if (size < -63 || size > 63)
- warning (0, "large frame pointer change (%d) with -mtiny-stack", size);
-
/* The high byte (r29) doesn't change - prefer 'subi' (1 cycle)
over 'sbiw' (2 cycles, same size). */
myfp = gen_rtx_REG (QImode, REGNO (frame_pointer_rtx));
@@ -733,51 +747,53 @@ expand_prologue (void)
/* Normal sized addition. */
myfp = frame_pointer_rtx;
}
- /* Calculate length. */
- int method1_length;
- method1_length =
- get_attr_length (gen_move_insn (frame_pointer_rtx, stack_pointer_rtx));
- method1_length +=
- get_attr_length (gen_move_insn (myfp,
- gen_rtx_PLUS (GET_MODE(myfp), myfp,
- gen_int_mode (-size,
- GET_MODE(myfp)))));
- method1_length +=
- get_attr_length (gen_move_insn (stack_pointer_rtx, frame_pointer_rtx));
-
+
+ /* Method 1-Adjust frame pointer. */
+ start_sequence ();
+
+ insn = emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
+ RTX_FRAME_RELATED_P (insn) = 1;
+
+ insn =
+ emit_move_insn (myfp,
+ gen_rtx_PLUS (GET_MODE(myfp), myfp,
+ gen_int_mode (-size,
+ GET_MODE(myfp))));
+ RTX_FRAME_RELATED_P (insn) = 1;
+
+ insn = emit_move_insn (stack_pointer_rtx, frame_pointer_rtx);
+ RTX_FRAME_RELATED_P (insn) = 1;
+
+ fp_plus_insns = get_insns ();
+ end_sequence ();
+
/* Method 2-Adjust Stack pointer. */
- int sp_plus_length = 0;
if (size <= 6)
{
- sp_plus_length =
- get_attr_length (gen_move_insn (stack_pointer_rtx,
- gen_rtx_PLUS (HImode, stack_pointer_rtx,
- gen_int_mode (-size,
- HImode))));
- sp_plus_length +=
- get_attr_length (gen_move_insn (frame_pointer_rtx, stack_pointer_rtx));
+ start_sequence ();
+
+ insn =
+ emit_move_insn (stack_pointer_rtx,
+ gen_rtx_PLUS (HImode,
+ stack_pointer_rtx,
+ gen_int_mode (-size,
+ HImode)));
+ RTX_FRAME_RELATED_P (insn) = 1;
+
+ insn =
+ emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
+ RTX_FRAME_RELATED_P (insn) = 1;
+
+ sp_plus_insns = get_insns ();
+ end_sequence ();
}
+
/* Use shortest method. */
- if (size <= 6 && (sp_plus_length < method1_length))
- {
- insn = emit_move_insn (stack_pointer_rtx,
- gen_rtx_PLUS (HImode, stack_pointer_rtx,
- gen_int_mode (-size, HImode)));
- RTX_FRAME_RELATED_P (insn) = 1;
- insn = emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
- RTX_FRAME_RELATED_P (insn) = 1;
- }
+ if (size <= 6 && (get_sequence_length (sp_plus_insns)
+ < get_sequence_length (fp_plus_insns)))
+ emit_insn (sp_plus_insns);
else
- {
- insn = emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
- RTX_FRAME_RELATED_P (insn) = 1;
- insn = emit_move_insn (myfp,
- gen_rtx_PLUS (GET_MODE(myfp), myfp,
- gen_int_mode (-size, GET_MODE(myfp))));
- RTX_FRAME_RELATED_P (insn) = 1;
- insn = emit_move_insn ( stack_pointer_rtx, frame_pointer_rtx);
- RTX_FRAME_RELATED_P (insn) = 1;
- }
+ emit_insn (fp_plus_insns);
}
}
}
@@ -872,42 +888,56 @@ expand_epilogue (void)
if (size)
{
/* Try two methods to adjust stack and select shortest. */
- int fp_plus_length;
+ rtx myfp;
+ rtx fp_plus_insns;
+ rtx sp_plus_insns = NULL_RTX;
+
+ if (TARGET_TINY_STACK)
+ {
+ /* The high byte (r29) doesn't change - prefer 'subi'
+ (1 cycle) over 'sbiw' (2 cycles, same size). */
+ myfp = gen_rtx_REG (QImode, REGNO (frame_pointer_rtx));
+ }
+ else
+ {
+ /* Normal sized addition. */
+ myfp = frame_pointer_rtx;
+ }
+
/* Method 1-Adjust frame pointer. */
- fp_plus_length =
- get_attr_length (gen_move_insn (frame_pointer_rtx,
- gen_rtx_PLUS (HImode, frame_pointer_rtx,
- gen_int_mode (size,
- HImode))));
- /* Copy to stack pointer. */
- fp_plus_length +=
- get_attr_length (gen_move_insn (stack_pointer_rtx, frame_pointer_rtx));
-
+ start_sequence ();
+
+ emit_move_insn (myfp,
+ gen_rtx_PLUS (HImode, myfp,
+ gen_int_mode (size,
+ GET_MODE(myfp))));
+
+ /* Copy to stack pointer. */
+ emit_move_insn (stack_pointer_rtx, frame_pointer_rtx);
+
+ fp_plus_insns = get_insns ();
+ end_sequence ();
+
/* Method 2-Adjust Stack pointer. */
- int sp_plus_length = 0;
if (size <= 5)
{
- sp_plus_length =
- get_attr_length (gen_move_insn (stack_pointer_rtx,
- gen_rtx_PLUS (HImode, stack_pointer_rtx,
- gen_int_mode (size,
- HImode))));
+ start_sequence ();
+
+ emit_move_insn (stack_pointer_rtx,
+ gen_rtx_PLUS (HImode, stack_pointer_rtx,
+ gen_int_mode (size,
+ HImode)));
+
+ sp_plus_insns = get_insns ();
+ end_sequence ();
}
+
/* Use shortest method. */
- if (size <= 5 && (sp_plus_length < fp_plus_length))
- {
- emit_move_insn (stack_pointer_rtx,
- gen_rtx_PLUS (HImode, stack_pointer_rtx,
- gen_int_mode (size, HImode)));
- }
+ if (size <= 5 && (get_sequence_length (sp_plus_insns)
+ < get_sequence_length (fp_plus_insns)))
+ emit_insn (sp_plus_insns);
else
- {
- emit_move_insn (frame_pointer_rtx,
- gen_rtx_PLUS (HImode, frame_pointer_rtx,
- gen_int_mode (size, HImode)));
- /* Copy to stack pointer. */
- emit_move_insn (stack_pointer_rtx, frame_pointer_rtx);
- }
+ emit_insn (fp_plus_insns);
}
if (!(cfun->machine->is_OS_task || cfun->machine->is_OS_main))
{