aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Clifton <nickc@cygnus.com>1999-11-01 14:23:53 +0000
committerNick Clifton <nickc@gcc.gnu.org>1999-11-01 14:23:53 +0000
commit9074519dd453b59f727b83dfe9169ccc5ae73778 (patch)
tree4b67ec2110e11576cdcfb82a01c505cb06582b88
parentda2c02192bfb2849b893b0c71e1b007db6426b7c (diff)
downloadgcc-9074519dd453b59f727b83dfe9169ccc5ae73778.zip
gcc-9074519dd453b59f727b83dfe9169ccc5ae73778.tar.gz
gcc-9074519dd453b59f727b83dfe9169ccc5ae73778.tar.bz2
Add comments explaining what thumb_expand_prologue() does.
From-SVN: r30321
-rw-r--r--gcc/ChangeLog5
-rw-r--r--gcc/config/arm/thumb.c73
2 files changed, 56 insertions, 22 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index b1ea458..fa08e92 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,8 @@
+Mon Nov 1 14:22:51 1999 Nick Clifton <nickc@cygnus.com>
+
+ * config/arm/thumb.c (thumb_expand_prologue): Add comments
+ explaining what is goin on in this function.
+
Mon Nov 1 08:03:15 1999 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
* regclass.c (record_reg_classes): In matching case, recompute
diff --git a/gcc/config/arm/thumb.c b/gcc/config/arm/thumb.c
index 3dea3e9..b549e0f 100644
--- a/gcc/config/arm/thumb.c
+++ b/gcc/config/arm/thumb.c
@@ -1515,9 +1515,6 @@ thumb_expand_prologue ()
{
HOST_WIDE_INT amount = (get_frame_size ()
+ current_function_outgoing_args_size);
- int regno;
- int live_regs_mask;
-
#ifdef THUMB_PE
/* Naked functions don't have prologues. */
if (arm_naked_function_p (current_function_decl))
@@ -1526,34 +1523,66 @@ thumb_expand_prologue ()
if (amount)
{
- live_regs_mask = 0;
- for (regno = 0; regno < 8; regno++)
- if (regs_ever_live[regno] && ! call_used_regs[regno]
- && ! (TARGET_SINGLE_PIC_BASE && (regno == thumb_pic_register)))
- live_regs_mask |= 1 << regno;
-
if (amount < 512)
emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
- GEN_INT (-amount)));
+ GEN_INT (- amount)));
else
{
- rtx reg, spare;
+ int regno;
+ rtx reg;
+
+ /* The stack decrement is too big for an immediate value in a single
+ insn. In theory we could issue multiple subtracts, but after
+ three of them it becomes more space efficient to place the full
+ value in the constant pool and load into a register. (Also the
+ ARM debugger really likes to see only one stack decrement per
+ function). So instead we look for a scratch register into which
+ we can load the decrement, and then we subtract this from the
+ stack pointer. Unfortunately on the thumb the only available
+ scratch registers are the argument registers, and we cannot use
+ these as they may hold arguments to the function. Instead we
+ attempt to locate a call preserved register which is used by this
+ function. If we can find one, then we know that it will have
+ been pushed at the start of the prologue and so we can corrupt
+ it now. */
+ for (regno = 4; regno < 8; regno++)
+ if (regs_ever_live[regno]
+ && ! call_used_regs[regno] /* Paranoia */
+ && ! (TARGET_SINGLE_PIC_BASE && (regno == thumb_pic_register)))
+ break;
- if ((live_regs_mask & 0xff) == 0) /* Very unlikely */
- emit_insn (gen_movsi (spare = gen_rtx (REG, SImode, 12),
- reg = gen_rtx (REG, SImode, 4)));
+ if (regno == 8) /* Very unlikely */
+ {
+ rtx spare = gen_rtx (REG, SImode, 12);
+
+ /* Choose an arbitary, non-argument low register. */
+ reg = gen_rtx (REG, SImode, 4);
+
+ /* Save it by copying it into a high, scratch register. */
+ emit_insn (gen_movsi (spare, reg));
+
+ /* Decrement the stack. */
+ emit_insn (gen_movsi (reg, GEN_INT (- amount)));
+ emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
+ reg));
+
+ /* Restore the low register's original value. */
+ emit_insn (gen_movsi (reg, spare));
+
+ /* Emit a USE of the restored scratch register, so that flow
+ analysis will not consider the restore redundant. The
+ register won't be used again in this function and isn't
+ restored by the epilogue. */
+ emit_insn (gen_rtx_USE (VOIDmode, reg));
+ }
else
{
- for (regno = 0; regno < 8; regno++)
- if (live_regs_mask & (1 << regno))
- break;
reg = gen_rtx (REG, SImode, regno);
- }
- emit_insn (gen_movsi (reg, GEN_INT (-amount)));
- emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, reg));
- if ((live_regs_mask & 0xff) == 0)
- emit_insn (gen_movsi (reg, spare));
+ emit_insn (gen_movsi (reg, GEN_INT (- amount)));
+ emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
+ reg));
+ }
}
}