aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/arm/arm.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config/arm/arm.c')
-rw-r--r--gcc/config/arm/arm.c147
1 files changed, 112 insertions, 35 deletions
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 6051cd1..3177a64 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -64,8 +64,8 @@ static int eliminate_lr2ip PARAMS ((rtx *));
static char * shift_op PARAMS ((rtx, HOST_WIDE_INT *));
static int pattern_really_clobbers_lr PARAMS ((rtx));
static int function_really_clobbers_lr PARAMS ((rtx));
-static void emit_multi_reg_push PARAMS ((int));
-static void emit_sfm PARAMS ((int, int));
+static rtx emit_multi_reg_push PARAMS ((int));
+static rtx emit_sfm PARAMS ((int, int));
static enum arm_cond_code get_arm_condition_code PARAMS ((rtx));
static int const_ok_for_op PARAMS ((HOST_WIDE_INT, enum rtx_code));
static void arm_add_gc_roots PARAMS ((void));
@@ -6268,13 +6268,20 @@ output_func_epilogue (frame_size)
after_arm_reorg = 0;
}
-static void
+/* Generate and emit an insn that we will recognize as a push_multi.
+ Unfortunately, since this insn does not reflect very well the actual
+ semantics of the operation, we need to annotate the insn for the benefit
+ of DWARF2 frame unwind information. */
+
+static rtx
emit_multi_reg_push (mask)
int mask;
{
int num_regs = 0;
int i, j;
rtx par;
+ rtx dwarf;
+ rtx tmp, reg;
for (i = 0; i < 16; i++)
if (mask & (1 << i))
@@ -6284,20 +6291,32 @@ emit_multi_reg_push (mask)
abort ();
par = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (num_regs));
+ dwarf = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (num_regs));
+ RTX_FRAME_RELATED_P (dwarf) = 1;
for (i = 0; i < 16; i++)
{
if (mask & (1 << i))
{
+ reg = gen_rtx_REG (SImode, i);
+
XVECEXP (par, 0, 0)
= gen_rtx_SET (VOIDmode,
gen_rtx_MEM (BLKmode,
gen_rtx_PRE_DEC (BLKmode,
stack_pointer_rtx)),
gen_rtx_UNSPEC (BLKmode,
- gen_rtvec (1,
- gen_rtx_REG (SImode, i)),
+ gen_rtvec (1, reg),
2));
+
+ tmp = gen_rtx_SET (VOIDmode,
+ gen_rtx_MEM (SImode,
+ gen_rtx_PRE_DEC (BLKmode,
+ stack_pointer_rtx)),
+ reg);
+ RTX_FRAME_RELATED_P (tmp) = 1;
+ XVECEXP (dwarf, 0, num_regs - 1) = tmp;
+
break;
}
}
@@ -6306,38 +6325,77 @@ emit_multi_reg_push (mask)
{
if (mask & (1 << i))
{
- XVECEXP (par, 0, j)
- = gen_rtx_USE (VOIDmode, gen_rtx_REG (SImode, i));
+ reg = gen_rtx_REG (SImode, i);
+
+ XVECEXP (par, 0, j) = gen_rtx_USE (VOIDmode, reg);
+
+ tmp = gen_rtx_SET (VOIDmode,
+ gen_rtx_MEM (SImode,
+ gen_rtx_PRE_DEC (BLKmode,
+ stack_pointer_rtx)),
+ reg);
+ RTX_FRAME_RELATED_P (tmp) = 1;
+ XVECEXP (dwarf, 0, num_regs - j - 1) = tmp;
+
j++;
}
}
- emit_insn (par);
+ par = emit_insn (par);
+ REG_NOTES (par) = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR, dwarf,
+ REG_NOTES (par));
+ return par;
}
-static void
+static rtx
emit_sfm (base_reg, count)
int base_reg;
int count;
{
rtx par;
+ rtx dwarf;
+ rtx tmp, reg;
int i;
par = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count));
+ dwarf = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count));
+ RTX_FRAME_RELATED_P (dwarf) = 1;
+
+ reg = gen_rtx_REG (XFmode, base_reg++);
XVECEXP (par, 0, 0)
= gen_rtx_SET (VOIDmode,
gen_rtx_MEM (BLKmode,
gen_rtx_PRE_DEC (BLKmode, stack_pointer_rtx)),
gen_rtx_UNSPEC (BLKmode,
- gen_rtvec (1, gen_rtx_REG (XFmode,
- base_reg++)),
+ gen_rtvec (1, reg),
2));
+ tmp
+ = gen_rtx_SET (VOIDmode,
+ gen_rtx_MEM (XFmode,
+ gen_rtx_PRE_DEC (BLKmode, stack_pointer_rtx)),
+ reg);
+ RTX_FRAME_RELATED_P (tmp) = 1;
+ XVECEXP (dwarf, 0, count - 1) = tmp;
+
for (i = 1; i < count; i++)
- XVECEXP (par, 0, i) = gen_rtx_USE (VOIDmode,
- gen_rtx_REG (XFmode, base_reg++));
+ {
+ reg = gen_rtx_REG (XFmode, base_reg++);
+ XVECEXP (par, 0, i) = gen_rtx_USE (VOIDmode, reg);
+
+ tmp = gen_rtx_SET (VOIDmode,
+ gen_rtx_MEM (XFmode,
+ gen_rtx_PRE_DEC (BLKmode,
+ stack_pointer_rtx)),
+ reg);
+ RTX_FRAME_RELATED_P (tmp) = 1;
+ XVECEXP (dwarf, 0, count - i - 1) = tmp;
+ }
- emit_insn (par);
+ par = emit_insn (par);
+ REG_NOTES (par) = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR, dwarf,
+ REG_NOTES (par));
+ return par;
}
void
@@ -6352,6 +6410,7 @@ arm_expand_prologue ()
the call-saved regs. */
int volatile_func = (optimize > 0
&& TREE_THIS_VOLATILE (current_function_decl));
+ rtx insn;
/* Naked functions don't have prologues. */
if (arm_naked_function_p (current_function_decl))
@@ -6376,18 +6435,21 @@ arm_expand_prologue ()
if (frame_pointer_needed)
{
live_regs_mask |= 0xD800;
- emit_insn (gen_movsi (gen_rtx_REG (SImode, IP_REGNUM),
- stack_pointer_rtx));
+ insn = emit_insn (gen_movsi (gen_rtx_REG (SImode, IP_REGNUM),
+ stack_pointer_rtx));
+ RTX_FRAME_RELATED_P (insn) = 1;
}
if (current_function_pretend_args_size)
{
if (store_arg_regs)
- emit_multi_reg_push ((0xf0 >> (current_function_pretend_args_size / 4))
- & 0xf);
+ insn = emit_multi_reg_push
+ ((0xf0 >> (current_function_pretend_args_size / 4)) & 0xf);
else
- emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
- GEN_INT (-current_function_pretend_args_size)));
+ insn = emit_insn
+ (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
+ GEN_INT (-current_function_pretend_args_size)));
+ RTX_FRAME_RELATED_P (insn) = 1;
}
if (live_regs_mask)
@@ -6395,10 +6457,11 @@ arm_expand_prologue ()
/* If we have to push any regs, then we must push lr as well, or
we won't get a proper return. */
live_regs_mask |= 1 << LR_REGNUM;
- emit_multi_reg_push (live_regs_mask);
+ insn = emit_multi_reg_push (live_regs_mask);
+ RTX_FRAME_RELATED_P (insn) = 1;
}
- /* For now the integer regs are still pushed in output_func_epilogue (). */
+ /* And now the floating point regs. */
if (! volatile_func)
{
@@ -6406,12 +6469,13 @@ arm_expand_prologue ()
{
for (reg = 23; reg > 15; reg--)
if (regs_ever_live[reg] && ! call_used_regs[reg])
- emit_insn (gen_rtx_SET
- (VOIDmode,
- gen_rtx_MEM (XFmode,
- gen_rtx_PRE_DEC (XFmode,
- stack_pointer_rtx)),
- gen_rtx_REG (XFmode, reg)));
+ {
+ insn = gen_rtx_PRE_DEC (XFmode, stack_pointer_rtx);
+ insn = gen_rtx_MEM (XFmode, insn);
+ insn = emit_insn (gen_rtx_SET (VOIDmode, insn,
+ gen_rtx_REG (XFmode, reg)));
+ RTX_FRAME_RELATED_P (insn) = 1;
+ }
}
else
{
@@ -6423,31 +6487,44 @@ arm_expand_prologue ()
{
if (start_reg - reg == 3)
{
- emit_sfm (reg, 4);
+ insn = emit_sfm (reg, 4);
+ RTX_FRAME_RELATED_P (insn) = 1;
start_reg = reg - 1;
}
}
else
{
if (start_reg != reg)
- emit_sfm (reg + 1, start_reg - reg);
+ {
+ insn = emit_sfm (reg + 1, start_reg - reg);
+ RTX_FRAME_RELATED_P (insn) = 1;
+ }
start_reg = reg - 1;
}
}
if (start_reg != reg)
- emit_sfm (reg + 1, start_reg - reg);
+ {
+ insn = emit_sfm (reg + 1, start_reg - reg);
+ RTX_FRAME_RELATED_P (insn) = 1;
+ }
}
}
if (frame_pointer_needed)
- emit_insn (gen_addsi3 (hard_frame_pointer_rtx, gen_rtx_REG (SImode, IP_REGNUM),
- (GEN_INT
- (-(4 + current_function_pretend_args_size)))));
+ {
+ insn = GEN_INT (-(4 + current_function_pretend_args_size));
+ insn = emit_insn (gen_addsi3 (hard_frame_pointer_rtx,
+ gen_rtx_REG (SImode, IP_REGNUM),
+ insn));
+ RTX_FRAME_RELATED_P (insn) = 1;
+ }
if (amount != const0_rtx)
{
- emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, amount));
+ insn = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
+ amount));
+ RTX_FRAME_RELATED_P (insn) = 1;
emit_insn (gen_rtx_CLOBBER (VOIDmode,
gen_rtx_MEM (BLKmode, stack_pointer_rtx)));
}