bfin-protos.h (legitimize_pic_address): Don't declare.
authorBernd Schmidt <bernd.schmidt@analog.com>
Wed, 20 Jul 2005 11:12:26 +0000 (11:12 +0000)
committerBernd Schmidt <bernds@gcc.gnu.org>
Wed, 20 Jul 2005 11:12:26 +0000 (11:12 +0000)
* 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.

From-SVN: r102195

gcc/ChangeLog
gcc/config/bfin/bfin-protos.h
gcc/config/bfin/bfin.c
gcc/config/bfin/bfin.md

index f5edcf18ed913d5bafd8328513c01e872523a3a8..da0313f1915ac0cdeaedfb50ba8d7fe4b3562247 100644 (file)
@@ -1,5 +1,15 @@
 2005-07-20  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.
+
        * config/bfin/bfin.c: Include "langhooks.h".
        (def_builtin): Go through lang_hooks to call builtin_function.
 
index 7f69a6899b2209bb72bd0079b734080acdda4d36..ae38a07369d4b14f2b4e2a32e9e3319a1156e842 100644 (file)
@@ -64,7 +64,6 @@ extern void print_operand (FILE *,  rtx, char);
 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 a0c768d5a2abb4a00a3a09a72b730442f68f49de..05541640c5629fd886f7c4d0357f718f47c04336 100644 (file)
@@ -121,6 +121,93 @@ static e_funkind funkind (tree funtype)
     return SUBROUTINE;
 }
 \f
+/* 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.  */
+
+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_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, 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;
+}
+\f
 /* Stack frame layout. */
 
 /* Compute the number of DREGS to save with a push_multiple operation.
@@ -422,11 +509,11 @@ bfin_initial_elimination_offset (int from, int to)
 }
 
 /* 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);
@@ -438,10 +525,12 @@ frame_related_constant_load (rtx reg, HOST_WIDE_INT constant)
       /* 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
@@ -463,7 +552,7 @@ add_to_sp (rtx spreg, HOST_WIDE_INT value, int frame)
       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));
@@ -529,7 +618,7 @@ emit_link_insn (rtx spreg, HOST_WIDE_INT frame_size)
       /* 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;
     }
@@ -752,6 +841,24 @@ expand_interrupt_handler_epilogue (rtx spreg, e_funkind fkind)
   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_lib_id_given)
+    addr = plus_constant (pic_offset_table_rtx, -4 - bfin_library_id * 4);
+  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
@@ -761,6 +868,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)
     {
@@ -768,6 +876,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);
 
   do_link (spreg, frame_size);
@@ -775,19 +916,7 @@ bfin_expand_prologue (void)
   if (TARGET_ID_SHARED_LIBRARY
       && (current_function_uses_pic_offset_table
          || !current_function_is_leaf))
-    {
-      rtx addr;
-      
-      if (bfin_lib_id_given)
-       addr = plus_constant (pic_offset_table_rtx, -4 - bfin_library_id * 4);
-      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
@@ -1374,91 +1503,6 @@ initialize_trampoline (tramp, fnaddr, cxt)
   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)
-           {
-             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, 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);
-         gcc_assert (GET_CODE (addr) == PLUS);
-       }
-
-      if (XEXP (addr, 0) == pic_offset_table_rtx)
-       return orig;
-
-      if (reg == 0)
-       {
-         gcc_assert (!no_new_pseudos);
-         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)
-       {
-         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;
-}
-
 /* Emit insns to move operands[1] into operands[0].  */
 
 void
@@ -1469,7 +1513,8 @@ emit_pic_move (rtx *operands, enum machine_mode mode ATTRIBUTE_UNUSED)
   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 d0c93b4b42fab5c7630646d6c69e5a1deb8e1a83..1bbbacde7645d630ecead5adc582045d647a490c 100644 (file)
   "ssync;"
   [(set_attr "type" "sync")])
 
+(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 "addv2hi3"