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
This commit is contained in:
parent
0590533746
commit
09350e36ee
4 changed files with 168 additions and 107 deletions
|
@ -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.
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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"
|
||||
|
|
Loading…
Add table
Reference in a new issue