aboutsummaryrefslogtreecommitdiff
path: root/gcc/config
diff options
context:
space:
mode:
authorBernd Schmidt <bernd.schmidt@analog.com>2005-07-20 11:12:26 +0000
committerBernd Schmidt <bernds@gcc.gnu.org>2005-07-20 11:12:26 +0000
commit09350e36ee3973f286340455d1e8c01506699f73 (patch)
treee9669b4398d2b9cbbb11f2e9f6d65e2c3ef9d3a7 /gcc/config
parent0590533746b2500bdb91af99562fe026f9a8e313 (diff)
downloadgcc-09350e36ee3973f286340455d1e8c01506699f73.zip
gcc-09350e36ee3973f286340455d1e8c01506699f73.tar.gz
gcc-09350e36ee3973f286340455d1e8c01506699f73.tar.bz2
bfin-protos.h (legitimize_pic_address): Don't declare.
* 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
Diffstat (limited to 'gcc/config')
-rw-r--r--gcc/config/bfin/bfin-protos.h1
-rw-r--r--gcc/config/bfin/bfin.c257
-rw-r--r--gcc/config/bfin/bfin.md7
3 files changed, 158 insertions, 107 deletions
diff --git a/gcc/config/bfin/bfin-protos.h b/gcc/config/bfin/bfin-protos.h
index 7f69a68..ae38a07 100644
--- a/gcc/config/bfin/bfin-protos.h
+++ b/gcc/config/bfin/bfin-protos.h
@@ -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);
diff --git a/gcc/config/bfin/bfin.c b/gcc/config/bfin/bfin.c
index a0c768d..0554164 100644
--- a/gcc/config/bfin/bfin.c
+++ b/gcc/config/bfin/bfin.c
@@ -121,6 +121,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. */
+
+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;
+}
+
/* 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. */
diff --git a/gcc/config/bfin/bfin.md b/gcc/config/bfin/bfin.md
index d0c93b4..1bbbacd 100644
--- a/gcc/config/bfin/bfin.md
+++ b/gcc/config/bfin/bfin.md
@@ -1999,6 +1999,13 @@
"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"