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);
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
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));
/* 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);
}
}
}
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))
{