summaryrefslogtreecommitdiff
path: root/gcc/config/arm/arm.c
diff options
context:
space:
mode:
authorgretay <gretay@138bc75d-0d04-0410-961f-82ee72b054a4>2012-06-18 18:02:03 +0000
committergretay <gretay@138bc75d-0d04-0410-961f-82ee72b054a4>2012-06-18 18:02:03 +0000
commit8cba51a5af340dc81a275d8ce778b4beab33c331 (patch)
tree7d4ce384c1e137bcd335966b253e29ecd86c1521 /gcc/config/arm/arm.c
parente2549f8182c644e2b091b0b1c6d556da129e9fad (diff)
downloadgcc-8cba51a5af340dc81a275d8ce778b4beab33c331.tar.gz
Generate RTL for return in Thumb2 mode. Used by expand of return insn.
2012-06-18 Ian Bolton <ian.bolton@arm.com> Sameera Deshpande <sameera.deshpande@arm.com> Greta Yorsh <greta.yorsh@arm.com> * config/arm/arm-protos.h (thumb2_expand_return): New declaration. * config/arm/arm.c (thumb2_expand_return): New function. * config/arm/arm.md (return): Update condition and code. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@188744 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config/arm/arm.c')
-rw-r--r--gcc/config/arm/arm.c46
1 files changed, 46 insertions, 0 deletions
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index b9e0f7bbf1a..3f5b5002f8b 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -23265,6 +23265,52 @@ thumb1_expand_prologue (void)
cfun->machine->lr_save_eliminated = 0;
}
+/* Generate pattern *pop_multiple_with_stack_update_and_return if single
+ POP instruction can be generated. LR should be replaced by PC. All
+ the checks required are already done by USE_RETURN_INSN (). Hence,
+ all we really need to check here is if single register is to be
+ returned, or multiple register return. */
+void
+thumb2_expand_return (void)
+{
+ int i, num_regs;
+ unsigned long saved_regs_mask;
+ arm_stack_offsets *offsets;
+
+ offsets = arm_get_frame_offsets ();
+ saved_regs_mask = offsets->saved_regs_mask;
+
+ for (i = 0, num_regs = 0; i <= LAST_ARM_REGNUM; i++)
+ if (saved_regs_mask & (1 << i))
+ num_regs++;
+
+ if (saved_regs_mask)
+ {
+ if (num_regs == 1)
+ {
+ rtx par = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (2));
+ rtx reg = gen_rtx_REG (SImode, PC_REGNUM);
+ rtx addr = gen_rtx_MEM (SImode,
+ gen_rtx_POST_INC (SImode,
+ stack_pointer_rtx));
+ set_mem_alias_set (addr, get_frame_alias_set ());
+ XVECEXP (par, 0, 0) = ret_rtx;
+ XVECEXP (par, 0, 1) = gen_rtx_SET (SImode, reg, addr);
+ RTX_FRAME_RELATED_P (XVECEXP (par, 0, 1)) = 1;
+ emit_jump_insn (par);
+ }
+ else
+ {
+ saved_regs_mask &= ~ (1 << LR_REGNUM);
+ saved_regs_mask |= (1 << PC_REGNUM);
+ arm_emit_multi_reg_pop (saved_regs_mask);
+ }
+ }
+ else
+ {
+ emit_jump_insn (simple_return_rtx);
+ }
+}
void
thumb1_expand_epilogue (void)