This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

4.0 patch: Stack limit checking for Blackfin


I've committed this patch, which adds the code to support -fstack-limit-symbol on the Blackfin to the 4.0 branch.

Mark, I realize that the 4.0 branch is meant for regression fixes. The situation is this: we're using a 3.4.x based compiler for our development, adding features whenever they are needed for our uClinux distribution. No one, as far as I am aware, is currently using 4.x compilers on the Blackfin, but we'd like to be able to switch at some point. To do that, we need at least the same user-visible features.

Since this change and a few others that may come up are confined to config/bfin, I personally don't see a problem - but if you disagree, let me know and I'll stop. It's likely that we'll have to create a private branch off gcc-4.0 and gcc-4.1 eventually anyway.


Bernd
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 108227)
+++ ChangeLog	(working copy)
@@ -1,3 +1,17 @@
+2005-12-08  Bernd Schmidt  <bernd.schmidt@analog.com>
+
+	* config/bfin/bfin-protos.h (legitimize_pic_address): Don't declare.
+	* config/bfin/bfin.c (legitimize_pic_address): Now static.  Take
+	extra arg "picreg" and use it instead of pic_offset_table_rtx.
+	All callers changed.
+	(frame_related_constant_load): New arg "related" which controls
+	setting of RTX_FRAME_RELATED_P.  All callers changed.
+	(bfin_load_pic_reg): New function, broken out of bfin_expand_prologue.
+	(bfin_expand_prologue): Add stack limit checking.
+	* config/bfin/bfin.md (trapifcc): New pattern.
+	(compare_eq, compare_ne, compare_le, compare_lt, compare_leu,
+	compare_ltu): Now named patterns.
+
 2005-12-06  Alan Modra  <amodra@bigpond.net.au>
 
 	PR other/13873
Index: config/bfin/bfin-protos.h
===================================================================
--- config/bfin/bfin-protos.h	(revision 108227)
+++ config/bfin/bfin-protos.h	(working copy)
@@ -64,7 +64,6 @@ extern void print_operand (FILE *,  rtx,
 extern void print_address_operand (FILE *, rtx);
 extern void split_di (rtx [], int, rtx [], rtx []);
 extern int split_load_immediate (rtx []);
-extern rtx legitimize_pic_address (rtx, rtx);
 extern void emit_pic_move (rtx *, Mmode);
 extern void override_options (void);
 extern void asm_conditional_branch (rtx, rtx *, int, int);
Index: config/bfin/bfin.c
===================================================================
--- config/bfin/bfin.c	(revision 108227)
+++ config/bfin/bfin.c	(working copy)
@@ -120,6 +120,93 @@ static e_funkind funkind (tree funtype)
     return SUBROUTINE;
 }
 
+/* Legitimize PIC addresses.  If the address is already position-independent,
+   we return ORIG.  Newly generated position-independent addresses go into a
+   reg.  This is REG if nonzero, otherwise we allocate register(s) as
+   necessary.  PICREG is the register holding the pointer to the PIC offset
+   table.  */
+
+static rtx
+legitimize_pic_address (rtx orig, rtx reg, rtx picreg)
+{
+  rtx addr = orig;
+  rtx new = orig;
+
+  if (GET_CODE (addr) == SYMBOL_REF || GET_CODE (addr) == LABEL_REF)
+    {
+      if (GET_CODE (addr) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (addr))
+	reg = new = orig;
+      else
+	{
+	  if (reg == 0)
+	    {
+	      gcc_assert (!no_new_pseudos);
+	      reg = gen_reg_rtx (Pmode);
+	    }
+
+	  if (flag_pic == 2)
+	    {
+	      emit_insn (gen_movsi_high_pic (reg, addr));
+	      emit_insn (gen_movsi_low_pic (reg, reg, addr));
+	      emit_insn (gen_addsi3 (reg, reg, picreg));
+	      new = gen_const_mem (Pmode, reg);
+	    }
+	  else
+	    {
+	      rtx tmp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr),
+					UNSPEC_MOVE_PIC);
+	      new = gen_const_mem (Pmode,
+				   gen_rtx_PLUS (Pmode, picreg, tmp));
+	    }
+	  emit_move_insn (reg, new);
+	}
+      if (picreg == pic_offset_table_rtx)
+	current_function_uses_pic_offset_table = 1;
+      return reg;
+    }
+
+  else if (GET_CODE (addr) == CONST || GET_CODE (addr) == PLUS)
+    {
+      rtx base;
+
+      if (GET_CODE (addr) == CONST)
+	{
+	  addr = XEXP (addr, 0);
+	  gcc_assert (GET_CODE (addr) == PLUS);
+	}
+
+      if (XEXP (addr, 0) == picreg)
+	return orig;
+
+      if (reg == 0)
+	{
+	  gcc_assert (!no_new_pseudos);
+	  reg = gen_reg_rtx (Pmode);
+	}
+
+      base = legitimize_pic_address (XEXP (addr, 0), reg, picreg);
+      addr = legitimize_pic_address (XEXP (addr, 1),
+				     base == reg ? NULL_RTX : reg,
+				     picreg);
+
+      if (GET_CODE (addr) == CONST_INT)
+	{
+	  gcc_assert (! reload_in_progress && ! reload_completed);
+	  addr = force_reg (Pmode, addr);
+	}
+
+      if (GET_CODE (addr) == PLUS && CONSTANT_P (XEXP (addr, 1)))
+	{
+	  base = gen_rtx_PLUS (Pmode, base, XEXP (addr, 0));
+	  addr = XEXP (addr, 1);
+	}
+
+      return gen_rtx_PLUS (Pmode, base, addr);
+    }
+
+  return new;
+}
+
 /* Stack frame layout. */
 
 /* Compute the number of DREGS to save with a push_multiple operation.
@@ -429,11 +516,11 @@ bfin_initial_elimination_offset (int fro
 }
 
 /* Emit code to load a constant CONSTANT into register REG; setting
-   RTX_FRAME_RELATED_P on all insns we generate.  Make sure that the insns
-   we generate need not be split.  */
+   RTX_FRAME_RELATED_P on all insns we generate if RELATED is true.
+   Make sure that the insns we generate need not be split.  */
 
 static void
-frame_related_constant_load (rtx reg, HOST_WIDE_INT constant)
+frame_related_constant_load (rtx reg, HOST_WIDE_INT constant, bool related)
 {
   rtx insn;
   rtx cst = GEN_INT (constant);
@@ -445,10 +532,12 @@ frame_related_constant_load (rtx reg, HO
       /* We don't call split_load_immediate here, since dwarf2out.c can get
 	 confused about some of the more clever sequences it can generate.  */
       insn = emit_insn (gen_movsi_high (reg, cst));
-      RTX_FRAME_RELATED_P (insn) = 1;
+      if (related)
+	RTX_FRAME_RELATED_P (insn) = 1;
       insn = emit_insn (gen_movsi_low (reg, reg, cst));
     }
-  RTX_FRAME_RELATED_P (insn) = 1;
+  if (related)
+    RTX_FRAME_RELATED_P (insn) = 1;
 }
 
 /* Generate efficient code to add a value to the frame pointer.  We
@@ -470,7 +559,7 @@ add_to_sp (rtx spreg, HOST_WIDE_INT valu
       rtx insn;
 
       if (frame)
-	frame_related_constant_load (tmpreg, value);
+	frame_related_constant_load (tmpreg, value, TRUE);
       else
 	{
 	  insn = emit_move_insn (tmpreg, GEN_INT (value));
@@ -537,7 +626,7 @@ emit_link_insn (rtx spreg, HOST_WIDE_INT
       /* Must use a call-clobbered PREG that isn't the static chain.  */
       rtx tmpreg = gen_rtx_REG (Pmode, REG_P1);
 
-      frame_related_constant_load (tmpreg, -frame_size);
+      frame_related_constant_load (tmpreg, -frame_size, TRUE);
       insn = emit_insn (gen_addsi3 (spreg, spreg, tmpreg));
       RTX_FRAME_RELATED_P (insn) = 1;
     }
@@ -771,6 +860,24 @@ expand_interrupt_handler_epilogue (rtx s
   emit_jump_insn (gen_return_internal (GEN_INT (fkind)));
 }
 
+/* Used while emitting the prologue to generate code to load the correct value
+   into the PIC register, which is passed in DEST.  */
+
+static void
+bfin_load_pic_reg (rtx dest)
+{
+  rtx addr, insn;
+      
+  if (bfin_library_id_string)
+    addr = plus_constant (pic_offset_table_rtx, atoi (bfin_library_id_string));
+  else
+    addr = gen_rtx_PLUS (Pmode, pic_offset_table_rtx,
+			 gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx),
+					     UNSPEC_LIBRARY_OFFSET));
+  insn = emit_insn (gen_movsi (dest, gen_rtx_MEM (Pmode, addr)));
+  REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx, NULL);
+}
+
 /* Generate RTL for the prologue of the current function.  */
 
 void
@@ -780,6 +887,7 @@ bfin_expand_prologue (void)
   HOST_WIDE_INT frame_size = get_frame_size ();
   rtx spreg = gen_rtx_REG (Pmode, REG_SP);
   e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
+  rtx pic_reg_loaded = NULL_RTX;
 
   if (fkind != SUBROUTINE)
     {
@@ -787,6 +895,39 @@ bfin_expand_prologue (void)
       return;
     }
 
+  if (current_function_limit_stack)
+    {
+      HOST_WIDE_INT offset
+	= bfin_initial_elimination_offset (ARG_POINTER_REGNUM,
+					   STACK_POINTER_REGNUM);
+      rtx lim = stack_limit_rtx;
+
+      if (GET_CODE (lim) == SYMBOL_REF)
+	{
+	  rtx p2reg = gen_rtx_REG (Pmode, REG_P2);
+	  if (TARGET_ID_SHARED_LIBRARY)
+	    {
+	      rtx p1reg = gen_rtx_REG (Pmode, REG_P1);
+	      rtx r3reg = gen_rtx_REG (Pmode, REG_R3);
+	      rtx val;
+	      pic_reg_loaded = p2reg;
+	      bfin_load_pic_reg (pic_reg_loaded);
+	      val = legitimize_pic_address (stack_limit_rtx, p1reg, p2reg);
+	      emit_move_insn (p1reg, val);
+	      frame_related_constant_load (p2reg, offset, FALSE);
+	      emit_insn (gen_addsi3 (p2reg, p2reg, p1reg));
+	      lim = p2reg;
+	    }
+	  else
+	    {
+	      rtx limit = plus_constant (stack_limit_rtx, offset);
+	      emit_move_insn (p2reg, limit);
+	      lim = p2reg;
+	    }
+	}
+      emit_insn (gen_compare_lt (bfin_cc_rtx, spreg, lim));
+      emit_insn (gen_trapifcc ());
+    }
   expand_prologue_reg_save (spreg, 0, false);
 
   do_link (spreg, frame_size, false);
@@ -794,19 +935,7 @@ bfin_expand_prologue (void)
   if (TARGET_ID_SHARED_LIBRARY
       && (current_function_uses_pic_offset_table
 	  || !current_function_is_leaf))
-    {
-      rtx addr;
-      
-      if (bfin_library_id_string)
-	addr = plus_constant (pic_offset_table_rtx, atoi (bfin_library_id_string));
-      else
-	addr = gen_rtx_PLUS (Pmode, pic_offset_table_rtx,
-			     gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx),
-					     UNSPEC_LIBRARY_OFFSET));
-      insn = emit_insn (gen_movsi (pic_offset_table_rtx,
-				   gen_rtx_MEM (Pmode, addr)));
-      REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx, NULL);
-    }
+    bfin_load_pic_reg (pic_offset_table_rtx);
 }
 
 /* Generate RTL for the epilogue of the current function.  NEED_RETURN is zero
@@ -1384,97 +1513,6 @@ initialize_trampoline (tramp, fnaddr, cx
   emit_move_insn (gen_rtx_MEM (HImode, addr), gen_lowpart (HImode, t2));
 }
 
-/* Legitimize PIC addresses.  If the address is already position-independent,
-   we return ORIG.  Newly generated position-independent addresses go into a
-   reg.  This is REG if nonzero, otherwise we allocate register(s) as
-   necessary.  */
-
-rtx
-legitimize_pic_address (rtx orig, rtx reg)
-{
-  rtx addr = orig;
-  rtx new = orig;
-
-  if (GET_CODE (addr) == SYMBOL_REF || GET_CODE (addr) == LABEL_REF)
-    {
-      if (GET_CODE (addr) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (addr))
-	reg = new = orig;
-      else
-	{
-	  if (reg == 0)
-	    {
-	      if (no_new_pseudos)
-		abort ();
-	      reg = gen_reg_rtx (Pmode);
-	    }
-
-	  if (flag_pic == 2)
-	    {
-	      emit_insn (gen_movsi_high_pic (reg, addr));
-	      emit_insn (gen_movsi_low_pic (reg, reg, addr));
-	      emit_insn (gen_addsi3 (reg, reg, pic_offset_table_rtx));
-	      new = gen_rtx_MEM (Pmode, reg);
-	    }
-	  else
-	    {
-	      rtx tmp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr),
-					UNSPEC_MOVE_PIC);
-	      new = gen_rtx_MEM (Pmode,
-				 gen_rtx_PLUS (Pmode, pic_offset_table_rtx,
-					       tmp));
-	    }
-	  emit_move_insn (reg, new);
-	}
-      current_function_uses_pic_offset_table = 1;
-      return reg;
-    }
-
-  else if (GET_CODE (addr) == CONST || GET_CODE (addr) == PLUS)
-    {
-      rtx base;
-
-      if (GET_CODE (addr) == CONST)
-	{
-	  addr = XEXP (addr, 0);
-	  if (GET_CODE (addr) != PLUS)
-	    abort ();
-	}
-
-      if (XEXP (addr, 0) == pic_offset_table_rtx)
-	return orig;
-
-      if (reg == 0)
-	{
-	  if (no_new_pseudos)
-	    abort ();
-	  reg = gen_reg_rtx (Pmode);
-	}
-
-      base = legitimize_pic_address (XEXP (addr, 0), reg);
-      addr = legitimize_pic_address (XEXP (addr, 1),
-				     base == reg ? NULL_RTX : reg);
-
-      if (GET_CODE (addr) == CONST_INT)
-	{
-	  if (! reload_in_progress && ! reload_completed)
-	    addr = force_reg (Pmode, addr);
-	  else
-	    /* If we reach here, then something is seriously wrong.  */
-	    abort ();
-	}
-
-      if (GET_CODE (addr) == PLUS && CONSTANT_P (XEXP (addr, 1)))
-	{
-	  base = gen_rtx_PLUS (Pmode, base, XEXP (addr, 0));
-	  addr = XEXP (addr, 1);
-	}
-
-      return gen_rtx_PLUS (Pmode, base, addr);
-    }
-
-  return new;
-}
-
 /* Emit insns to move operands[1] into operands[0].  */
 
 void
@@ -1485,7 +1523,8 @@ emit_pic_move (rtx *operands, enum machi
   if (GET_CODE (operands[0]) == MEM && SYMBOLIC_CONST (operands[1]))
     operands[1] = force_reg (SImode, operands[1]);
   else
-    operands[1] = legitimize_pic_address (operands[1], temp);
+    operands[1] = legitimize_pic_address (operands[1], temp,
+					  pic_offset_table_rtx);
 }
 
 /* Expand a move operation in mode MODE.  The operands are in OPERANDS.  */
Index: config/bfin/bfin.md
===================================================================
--- config/bfin/bfin.md	(revision 108227)
+++ config/bfin/bfin.md	(working copy)
@@ -1435,7 +1435,7 @@ (define_expand "cmpsi"
   DONE;
 })
 
-(define_insn ""
+(define_insn "compare_eq"
   [(set (match_operand:BI 0 "cc_operand" "=C,C")
         (eq:BI (match_operand:SI 1 "validreg_operand" "d,a")
                (match_operand:SI 2 "nonmemory_operand" "dKs3,aKs3")))]
@@ -1443,7 +1443,7 @@ (define_insn ""
   "cc =%1==%2;"
   [(set_attr "type" "compare")])
 
-(define_insn ""
+(define_insn "compare_ne"
   [(set (match_operand:BI 0 "cc_operand" "=C,C")
         (ne:BI (match_operand:SI 1 "validreg_operand" "d,a")
                (match_operand:SI 2 "nonmemory_operand" "dKs3,aKs3")))]
@@ -1451,7 +1451,7 @@ (define_insn ""
   "cc =%1!=%2;"
   [(set_attr "type" "compare")])
 
-(define_insn ""
+(define_insn "compare_lt"
   [(set (match_operand:BI 0 "cc_operand" "=C,C")
         (lt:BI (match_operand:SI 1 "validreg_operand" "d,a")
                (match_operand:SI 2 "nonmemory_operand" "dKs3,aKs3")))]
@@ -1459,7 +1459,7 @@ (define_insn ""
   "cc =%1<%2;"
   [(set_attr "type" "compare")])
 
-(define_insn ""
+(define_insn "compare_le"
   [(set (match_operand:BI 0 "cc_operand" "=C,C")
         (le:BI (match_operand:SI 1 "validreg_operand" "d,a")
                (match_operand:SI 2 "nonmemory_operand" "dKs3,aKs3")))]
@@ -1467,7 +1467,7 @@ (define_insn ""
   "cc =%1<=%2;"
   [(set_attr "type" "compare")])
 
-(define_insn ""
+(define_insn "compare_leu"
   [(set (match_operand:BI 0 "cc_operand" "=C,C")
         (leu:BI (match_operand:SI 1 "validreg_operand" "d,a")
                 (match_operand:SI 2 "nonmemory_operand" "dKu3,aKu3")))]
@@ -1475,7 +1475,7 @@ (define_insn ""
   "cc =%1<=%2 (iu);"
   [(set_attr "type" "compare")])
 
-(define_insn ""
+(define_insn "compare_ltu"
   [(set (match_operand:BI 0 "cc_operand" "=C,C")
         (ltu:BI (match_operand:SI 1 "validreg_operand" "d,a")
                 (match_operand:SI 2 "nonmemory_operand" "dKu3,aKu3")))]
@@ -1929,6 +1929,13 @@ (define_insn "trap"
   [(set_attr "type" "misc")
    (set_attr "length" "2")])
 
+(define_insn "trapifcc"
+  [(trap_if (reg:BI REG_CC) (const_int 3))]
+  ""
+  "if !cc jump 4 (bp); excpt 3;"
+  [(set_attr "type" "misc")
+   (set_attr "length" "4")])
+
 ;;; Vector instructions
 
 (define_insn "addv2hi"

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]