From 3dc90b0b7b0b8db69e6bb4fd46118ead74e6815d Mon Sep 17 00:00:00 2001
From: nickc <nickc@138bc75d-0d04-0410-961f-82ee72b054a4>
Date: Mon, 1 Nov 1999 14:23:53 +0000
Subject: [PATCH] Add comments explaining what thumb_expand_prologue() does.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@30321 138bc75d-0d04-0410-961f-82ee72b054a4
---
 gcc/ChangeLog          |  5 +++
 gcc/config/arm/thumb.c | 73 +++++++++++++++++++++++++++++-------------
 2 files changed, 56 insertions(+), 22 deletions(-)

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index b1ea4581f7c..fa08e92c8be 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 3dea3e957cf..b549e0f593e 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));
+	    }
 	}
     }
 
-- 
GitLab