diff options
author | Bernd Schmidt <bernd.schmidt@analog.com> | 2007-09-25 12:59:32 +0000 |
---|---|---|
committer | Bernd Schmidt <bernds@gcc.gnu.org> | 2007-09-25 12:59:32 +0000 |
commit | bf3f95816f81b9bbc73f01bb9591cab6f7dd59c3 (patch) | |
tree | 545f5d3d1adea9facf28db08a70069214f49303d /gcc/config/bfin | |
parent | 1bde00421fc1d93e9a92ffe6cd0c221f4494fd33 (diff) | |
download | gcc-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.c | 129 |
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) |