aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/bfin
diff options
context:
space:
mode:
authorBernd Schmidt <bernd.schmidt@analog.com>2007-09-25 12:59:32 +0000
committerBernd Schmidt <bernds@gcc.gnu.org>2007-09-25 12:59:32 +0000
commitbf3f95816f81b9bbc73f01bb9591cab6f7dd59c3 (patch)
tree545f5d3d1adea9facf28db08a70069214f49303d /gcc/config/bfin
parent1bde00421fc1d93e9a92ffe6cd0c221f4494fd33 (diff)
downloadgcc-bf3f95816f81b9bbc73f01bb9591cab6f7dd59c3.zip
gcc-bf3f95816f81b9bbc73f01bb9591cab6f7dd59c3.tar.gz
gcc-bf3f95816f81b9bbc73f01bb9591cab6f7dd59c3.tar.bz2
bfin.c (expand_prologue_reg_save, [...]): Code to save and restore I/M/B/L regs and ASTAT moved here...
* config/bfin/bfin.c (expand_prologue_reg_save, expand_epilogue_reg_restore): Code to save and restore I/M/B/L regs and ASTAT moved here... (expand_interrupt_handler_prologue, expand_interrupt_handler_epilogue): ... from here. New argument ALL; callers changed. (n_regs_saved_by_prologue): Count ASTAT for plain saveall functions. (bfin_expand_prologue, bfin_expand_epilogue): Deal with functions that have the "saveall" attribute. From-SVN: r128762
Diffstat (limited to 'gcc/config/bfin')
-rw-r--r--gcc/config/bfin/bfin.c129
1 files changed, 73 insertions, 56 deletions
diff --git a/gcc/config/bfin/bfin.c b/gcc/config/bfin/bfin.c
index 3a23e84..c3b5988 100644
--- a/gcc/config/bfin/bfin.c
+++ b/gcc/config/bfin/bfin.c
@@ -416,6 +416,8 @@ stack_frame_needed_p (void)
static void
expand_prologue_reg_save (rtx spreg, int saveall, bool is_inthandler)
{
+ rtx predec1 = gen_rtx_PRE_DEC (SImode, spreg);
+ rtx predec = gen_rtx_MEM (SImode, predec1);
int ndregs = saveall ? 8 : n_dregs_to_save (is_inthandler);
int npregs = saveall ? 6 : n_pregs_to_save (is_inthandler);
int dregno = REG_R7 + 1 - ndregs;
@@ -424,7 +426,13 @@ expand_prologue_reg_save (rtx spreg, int saveall, bool is_inthandler)
int i;
rtx pat, insn, val;
- if (total == 0)
+ if (saveall || is_inthandler)
+ {
+ insn = emit_move_insn (predec, gen_rtx_REG (SImode, REG_ASTAT));
+ RTX_FRAME_RELATED_P (insn) = 1;
+ }
+
+ if (total == 0 && !saveall)
return;
val = GEN_INT (-total * 4);
@@ -458,6 +466,20 @@ expand_prologue_reg_save (rtx spreg, int saveall, bool is_inthandler)
}
insn = emit_insn (pat);
RTX_FRAME_RELATED_P (insn) = 1;
+
+ for (i = REG_P7 + 1; i < REG_CC; i++)
+ if (saveall
+ || (is_inthandler
+ && (df_regs_ever_live_p (i)
+ || (!leaf_function_p () && call_used_regs[i]))))
+ {
+ if (i == REG_A0 || i == REG_A1)
+ insn = emit_move_insn (gen_rtx_MEM (PDImode, predec1),
+ gen_rtx_REG (PDImode, i));
+ else
+ insn = emit_move_insn (predec, gen_rtx_REG (SImode, i));
+ RTX_FRAME_RELATED_P (insn) = 1;
+ }
}
/* Emit code to restore registers in the epilogue. SAVEALL is nonzero if we
@@ -468,12 +490,35 @@ expand_prologue_reg_save (rtx spreg, int saveall, bool is_inthandler)
static void
expand_epilogue_reg_restore (rtx spreg, bool saveall, bool is_inthandler)
{
+ rtx postinc1 = gen_rtx_POST_INC (SImode, spreg);
+ rtx postinc = gen_rtx_MEM (SImode, postinc1);
+
int ndregs = saveall ? 8 : n_dregs_to_save (is_inthandler);
int npregs = saveall ? 6 : n_pregs_to_save (is_inthandler);
int total = ndregs + npregs;
int i, regno;
rtx pat, insn;
+ /* A slightly crude technique to stop flow from trying to delete "dead"
+ insns. */
+ MEM_VOLATILE_P (postinc) = 1;
+
+ for (i = REG_CC - 1; i > REG_P7; i--)
+ if (saveall
+ || (is_inthandler
+ && (df_regs_ever_live_p (i)
+ || (!leaf_function_p () && call_used_regs[i]))))
+ {
+ if (i == REG_A0 || i == REG_A1)
+ {
+ rtx mem = gen_rtx_MEM (PDImode, postinc1);
+ MEM_VOLATILE_P (mem) = 1;
+ emit_move_insn (gen_rtx_REG (PDImode, i), mem);
+ }
+ else
+ emit_move_insn (gen_rtx_REG (SImode, i), postinc);
+ }
+
if (total == 0)
return;
@@ -507,6 +552,9 @@ expand_epilogue_reg_restore (rtx spreg, bool saveall, bool is_inthandler)
insn = emit_insn (pat);
RTX_FRAME_RELATED_P (insn) = 1;
+
+ if (saveall || is_inthandler)
+ emit_move_insn (gen_rtx_REG (SImode, REG_ASTAT), postinc);
}
/* Perform any needed actions needed for a function that is receiving a
@@ -591,6 +639,7 @@ n_regs_saved_by_prologue (void)
int ndregs = all ? 8 : n_dregs_to_save (is_inthandler);
int npregs = all ? 6 : n_pregs_to_save (is_inthandler);
int n = ndregs + npregs;
+ int i;
if (all || stack_frame_needed_p ())
/* We use a LINK instruction in this case. */
@@ -603,23 +652,24 @@ n_regs_saved_by_prologue (void)
n++;
}
+ if (fkind != SUBROUTINE || all)
+ /* Increment once for ASTAT. */
+ n++;
+
if (fkind != SUBROUTINE)
{
- int i;
-
- /* Increment once for ASTAT. */
- n++;
-
/* RETE/X/N. */
if (lookup_attribute ("nesting", attrs))
n++;
-
- for (i = REG_P7 + 1; i < REG_CC; i++)
- if (all
- || df_regs_ever_live_p (i)
- || (!leaf_function_p () && call_used_regs[i]))
- n += i == REG_A0 || i == REG_A1 ? 2 : 1;
}
+
+ for (i = REG_P7 + 1; i < REG_CC; i++)
+ if (all
+ || (fkind != SUBROUTINE
+ && (df_regs_ever_live_p (i)
+ || (!leaf_function_p () && call_used_regs[i]))))
+ n += i == REG_A0 || i == REG_A1 ? 2 : 1;
+
return n;
}
@@ -882,15 +932,13 @@ do_unlink (rtx spreg, HOST_WIDE_INT frame_size, bool all, int epilogue_p)
SPREG contains (reg:SI REG_SP). */
static void
-expand_interrupt_handler_prologue (rtx spreg, e_funkind fkind)
+expand_interrupt_handler_prologue (rtx spreg, e_funkind fkind, bool all)
{
- int i;
HOST_WIDE_INT frame_size = get_frame_size ();
rtx predec1 = gen_rtx_PRE_DEC (SImode, spreg);
rtx predec = gen_rtx_MEM (SImode, predec1);
rtx insn;
tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
- bool all = lookup_attribute ("saveall", attrs) != NULL_TREE;
tree kspisusp = lookup_attribute ("kspisusp", attrs);
if (kspisusp)
@@ -907,28 +955,12 @@ expand_interrupt_handler_prologue (rtx spreg, e_funkind fkind)
RTX_FRAME_RELATED_P (insn) = 1;
}
- insn = emit_move_insn (predec, gen_rtx_REG (SImode, REG_ASTAT));
- RTX_FRAME_RELATED_P (insn) = 1;
-
/* If we're calling other functions, they won't save their call-clobbered
registers, so we must save everything here. */
if (!current_function_is_leaf)
all = true;
expand_prologue_reg_save (spreg, all, true);
- for (i = REG_P7 + 1; i < REG_CC; i++)
- if (all
- || df_regs_ever_live_p (i)
- || (!leaf_function_p () && call_used_regs[i]))
- {
- if (i == REG_A0 || i == REG_A1)
- insn = emit_move_insn (gen_rtx_MEM (PDImode, predec1),
- gen_rtx_REG (PDImode, i));
- else
- insn = emit_move_insn (predec, gen_rtx_REG (SImode, i));
- RTX_FRAME_RELATED_P (insn) = 1;
- }
-
if (lookup_attribute ("nesting", attrs))
{
rtx srcreg = gen_rtx_REG (Pmode, (fkind == EXCPT_HANDLER ? REG_RETX
@@ -961,13 +993,11 @@ expand_interrupt_handler_prologue (rtx spreg, e_funkind fkind)
SPREG contains (reg:SI REG_SP). */
static void
-expand_interrupt_handler_epilogue (rtx spreg, e_funkind fkind)
+expand_interrupt_handler_epilogue (rtx spreg, e_funkind fkind, bool all)
{
- int i;
+ tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
rtx postinc1 = gen_rtx_POST_INC (SImode, spreg);
rtx postinc = gen_rtx_MEM (SImode, postinc1);
- tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
- bool all = lookup_attribute ("saveall", attrs) != NULL_TREE;
/* A slightly crude technique to stop flow from trying to delete "dead"
insns. */
@@ -988,25 +1018,8 @@ expand_interrupt_handler_epilogue (rtx spreg, e_funkind fkind)
if (!current_function_is_leaf)
all = true;
- for (i = REG_CC - 1; i > REG_P7; i--)
- if (all
- || df_regs_ever_live_p (i)
- || (!leaf_function_p () && call_used_regs[i]))
- {
- if (i == REG_A0 || i == REG_A1)
- {
- rtx mem = gen_rtx_MEM (PDImode, postinc1);
- MEM_VOLATILE_P (mem) = 1;
- emit_move_insn (gen_rtx_REG (PDImode, i), mem);
- }
- else
- emit_move_insn (gen_rtx_REG (SImode, i), postinc);
- }
-
expand_epilogue_reg_restore (spreg, all, true);
- emit_move_insn (gen_rtx_REG (SImode, REG_ASTAT), postinc);
-
/* Deallocate any space we left on the stack in case we needed to save the
argument registers. */
if (fkind == EXCPT_HANDLER)
@@ -1051,10 +1064,12 @@ bfin_expand_prologue (void)
rtx spreg = gen_rtx_REG (Pmode, REG_SP);
e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
rtx pic_reg_loaded = NULL_RTX;
+ tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
+ bool all = lookup_attribute ("saveall", attrs) != NULL_TREE;
if (fkind != SUBROUTINE)
{
- expand_interrupt_handler_prologue (spreg, fkind);
+ expand_interrupt_handler_prologue (spreg, fkind, all);
return;
}
@@ -1104,7 +1119,7 @@ bfin_expand_prologue (void)
emit_insn (gen_compare_lt (bfin_cc_rtx, spreg, lim));
emit_insn (gen_trapifcc ());
}
- expand_prologue_reg_save (spreg, 0, false);
+ expand_prologue_reg_save (spreg, all, false);
do_link (spreg, frame_size, false);
@@ -1126,16 +1141,18 @@ bfin_expand_epilogue (int need_return, int eh_return, bool sibcall_p)
rtx spreg = gen_rtx_REG (Pmode, REG_SP);
e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
int e = sibcall_p ? -1 : 1;
+ tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
+ bool all = lookup_attribute ("saveall", attrs) != NULL_TREE;
if (fkind != SUBROUTINE)
{
- expand_interrupt_handler_epilogue (spreg, fkind);
+ expand_interrupt_handler_epilogue (spreg, fkind, all);
return;
}
do_unlink (spreg, get_frame_size (), false, e);
- expand_epilogue_reg_restore (spreg, false, false);
+ expand_epilogue_reg_restore (spreg, all, false);
/* Omit the return insn if this is for a sibcall. */
if (! need_return)