From 09350e36ee3973f286340455d1e8c01506699f73 Mon Sep 17 00:00:00 2001 From: Bernd Schmidt Date: Wed, 20 Jul 2005 11:12:26 +0000 Subject: 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 --- gcc/config/bfin/bfin-protos.h | 1 - gcc/config/bfin/bfin.c | 257 +++++++++++++++++++++++++----------------- gcc/config/bfin/bfin.md | 7 ++ 3 files changed, 158 insertions(+), 107 deletions(-) (limited to 'gcc/config') 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" -- cgit v1.1