diff options
author | Alexander Kabaev <kan@FreeBSD.org> | 2005-06-03 03:50:42 +0000 |
---|---|---|
committer | Alexander Kabaev <kan@FreeBSD.org> | 2005-06-03 03:50:42 +0000 |
commit | 31a119f3ede3e46847ca7849e70407c96e04d1f3 (patch) | |
tree | 56d842dca34faa3e40f969e13617dfdbb051d690 /contrib/gcc/config/alpha/alpha.c | |
parent | 2554b2d12b64808f2da1a31320628c91ab16164a (diff) |
Stock files.
Notes
Notes:
svn path=/head/; revision=146906
Diffstat (limited to 'contrib/gcc/config/alpha/alpha.c')
-rw-r--r-- | contrib/gcc/config/alpha/alpha.c | 139 |
1 files changed, 83 insertions, 56 deletions
diff --git a/contrib/gcc/config/alpha/alpha.c b/contrib/gcc/config/alpha/alpha.c index 0086968afb7a..fbaeabe5049a 100644 --- a/contrib/gcc/config/alpha/alpha.c +++ b/contrib/gcc/config/alpha/alpha.c @@ -1947,6 +1947,17 @@ alpha_legitimize_address (rtx x, rtx scratch, } } +/* Primarily this is required for TLS symbols, but given that our move + patterns *ought* to be able to handle any symbol at any time, we + should never be spilling symbolic operands to the constant pool, ever. */ + +static bool +alpha_cannot_force_const_mem (rtx x) +{ + enum rtx_code code = GET_CODE (x); + return code == SYMBOL_REF || code == LABEL_REF || code == CONST; +} + /* We do not allow indirect calls to be optimized into sibling calls, nor can we allow a call to a function with a different GP to be optimized into a sibcall. */ @@ -3186,7 +3197,13 @@ alpha_emit_conditional_branch (enum rtx_code code) /* If the constants doesn't fit into an immediate, but can be generated by lda/ldah, we adjust the argument and compare against zero, so we can use beq/bne directly. */ - else if (GET_CODE (op1) == CONST_INT && (code == EQ || code == NE)) + /* ??? Don't do this when comparing against symbols, otherwise + we'll reduce (&x == 0x1234) to (&x-0x1234 == 0), which will + be declared false out of hand (at least for non-weak). */ + else if (GET_CODE (op1) == CONST_INT + && (code == EQ || code == NE) + && !(symbolic_operand (op0, VOIDmode) + || (GET_CODE (op0) == REG && REG_POINTER (op0)))) { HOST_WIDE_INT v = INTVAL (op1), n = -v; @@ -6786,11 +6803,6 @@ alpha_sa_mask (unsigned long *imaskP, unsigned long *fmaskP) break; imask |= 1UL << regno; } - - /* Glibc likes to use $31 as an unwind stopper for crt0. To - avoid hackery in unwind-dw2.c, we need to actively store a - zero in the prologue of _Unwind_RaiseException et al. */ - imask |= 1UL << 31; } /* If any register spilled, then spill the return address also. */ @@ -7046,6 +7058,48 @@ set_frame_related_p (void) #define FRP(exp) (start_sequence (), exp, set_frame_related_p ()) +/* Generates a store with the proper unwind info attached. VALUE is + stored at BASE_REG+BASE_OFS. If FRAME_BIAS is non-zero, then BASE_REG + contains SP+FRAME_BIAS, and that is the unwind info that should be + generated. If FRAME_REG != VALUE, then VALUE is being stored on + behalf of FRAME_REG, and FRAME_REG should be present in the unwind. */ + +static void +emit_frame_store_1 (rtx value, rtx base_reg, HOST_WIDE_INT frame_bias, + HOST_WIDE_INT base_ofs, rtx frame_reg) +{ + rtx addr, mem, insn; + + addr = plus_constant (base_reg, base_ofs); + mem = gen_rtx_MEM (DImode, addr); + set_mem_alias_set (mem, alpha_sr_alias_set); + + insn = emit_move_insn (mem, value); + RTX_FRAME_RELATED_P (insn) = 1; + + if (frame_bias || value != frame_reg) + { + if (frame_bias) + { + addr = plus_constant (stack_pointer_rtx, frame_bias + base_ofs); + mem = gen_rtx_MEM (DImode, addr); + } + + REG_NOTES (insn) + = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR, + gen_rtx_SET (VOIDmode, mem, frame_reg), + REG_NOTES (insn)); + } +} + +static void +emit_frame_store (unsigned int regno, rtx base_reg, + HOST_WIDE_INT frame_bias, HOST_WIDE_INT base_ofs) +{ + rtx reg = gen_rtx_REG (DImode, regno); + emit_frame_store_1 (reg, base_reg, frame_bias, base_ofs, reg); +} + /* Write function prologue. */ /* On vms we have two kinds of functions: @@ -7075,7 +7129,7 @@ alpha_expand_prologue (void) HOST_WIDE_INT frame_size; /* Offset from base reg to register save area. */ HOST_WIDE_INT reg_offset; - rtx sa_reg, mem; + rtx sa_reg; int i; sa_size = alpha_sa_size (); @@ -7225,37 +7279,40 @@ alpha_expand_prologue (void) if (!TARGET_ABI_UNICOSMK) { + HOST_WIDE_INT sa_bias = 0; + /* Cope with very large offsets to the register save area. */ sa_reg = stack_pointer_rtx; if (reg_offset + sa_size > 0x8000) { int low = ((reg_offset & 0xffff) ^ 0x8000) - 0x8000; - HOST_WIDE_INT bias; + rtx sa_bias_rtx; if (low + sa_size <= 0x8000) - bias = reg_offset - low, reg_offset = low; + sa_bias = reg_offset - low, reg_offset = low; else - bias = reg_offset, reg_offset = 0; + sa_bias = reg_offset, reg_offset = 0; sa_reg = gen_rtx_REG (DImode, 24); - FRP (emit_insn (gen_adddi3 (sa_reg, stack_pointer_rtx, - GEN_INT (bias)))); + sa_bias_rtx = GEN_INT (sa_bias); + + if (add_operand (sa_bias_rtx, DImode)) + emit_insn (gen_adddi3 (sa_reg, stack_pointer_rtx, sa_bias_rtx)); + else + { + emit_move_insn (sa_reg, sa_bias_rtx); + emit_insn (gen_adddi3 (sa_reg, stack_pointer_rtx, sa_reg)); + } } /* Save regs in stack order. Beginning with VMS PV. */ if (TARGET_ABI_OPEN_VMS && alpha_procedure_type == PT_STACK) - { - mem = gen_rtx_MEM (DImode, stack_pointer_rtx); - set_mem_alias_set (mem, alpha_sr_alias_set); - FRP (emit_move_insn (mem, gen_rtx_REG (DImode, REG_PV))); - } + emit_frame_store (REG_PV, stack_pointer_rtx, 0, 0); /* Save register RA next. */ if (imask & (1UL << REG_RA)) { - mem = gen_rtx_MEM (DImode, plus_constant (sa_reg, reg_offset)); - set_mem_alias_set (mem, alpha_sr_alias_set); - FRP (emit_move_insn (mem, gen_rtx_REG (DImode, REG_RA))); + emit_frame_store (REG_RA, sa_reg, sa_bias, reg_offset); imask &= ~(1UL << REG_RA); reg_offset += 8; } @@ -7264,36 +7321,14 @@ alpha_expand_prologue (void) for (i = 0; i < 31; i++) if (imask & (1UL << i)) { - mem = gen_rtx_MEM (DImode, plus_constant (sa_reg, reg_offset)); - set_mem_alias_set (mem, alpha_sr_alias_set); - FRP (emit_move_insn (mem, gen_rtx_REG (DImode, i))); + emit_frame_store (i, sa_reg, sa_bias, reg_offset); reg_offset += 8; } - /* Store a zero if requested for unwinding. */ - if (imask & (1UL << 31)) - { - rtx insn, t; - - mem = gen_rtx_MEM (DImode, plus_constant (sa_reg, reg_offset)); - set_mem_alias_set (mem, alpha_sr_alias_set); - insn = emit_move_insn (mem, const0_rtx); - - RTX_FRAME_RELATED_P (insn) = 1; - t = gen_rtx_REG (Pmode, 31); - t = gen_rtx_SET (VOIDmode, mem, t); - t = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR, t, REG_NOTES (insn)); - REG_NOTES (insn) = t; - - reg_offset += 8; - } - for (i = 0; i < 31; i++) if (fmask & (1UL << i)) { - mem = gen_rtx_MEM (DFmode, plus_constant (sa_reg, reg_offset)); - set_mem_alias_set (mem, alpha_sr_alias_set); - FRP (emit_move_insn (mem, gen_rtx_REG (DFmode, i+32))); + emit_frame_store (i+32, sa_reg, sa_bias, reg_offset); reg_offset += 8; } } @@ -7307,19 +7342,13 @@ alpha_expand_prologue (void) for (i = 9; i < 15; i++) if (imask & (1UL << i)) { - mem = gen_rtx_MEM (DImode, plus_constant(hard_frame_pointer_rtx, - reg_offset)); - set_mem_alias_set (mem, alpha_sr_alias_set); - FRP (emit_move_insn (mem, gen_rtx_REG (DImode, i))); + emit_frame_store (i, hard_frame_pointer_rtx, 0, reg_offset); reg_offset -= 8; } for (i = 2; i < 10; i++) if (fmask & (1UL << i)) { - mem = gen_rtx_MEM (DFmode, plus_constant (hard_frame_pointer_rtx, - reg_offset)); - set_mem_alias_set (mem, alpha_sr_alias_set); - FRP (emit_move_insn (mem, gen_rtx_REG (DFmode, i+32))); + emit_frame_store (i+32, hard_frame_pointer_rtx, 0, reg_offset); reg_offset -= 8; } } @@ -7713,9 +7742,6 @@ alpha_expand_epilogue (void) reg_offset += 8; } - if (imask & (1UL << 31)) - reg_offset += 8; - for (i = 0; i < 31; ++i) if (fmask & (1UL << i)) { @@ -10215,6 +10241,8 @@ alpha_init_libfuncs (void) #define TARGET_FUNCTION_OK_FOR_SIBCALL alpha_function_ok_for_sibcall #undef TARGET_CANNOT_COPY_INSN_P #define TARGET_CANNOT_COPY_INSN_P alpha_cannot_copy_insn_p +#undef TARGET_CANNOT_FORCE_CONST_MEM +#define TARGET_CANNOT_FORCE_CONST_MEM alpha_cannot_force_const_mem #if TARGET_ABI_OSF #undef TARGET_ASM_OUTPUT_MI_THUNK @@ -10257,4 +10285,3 @@ struct gcc_target targetm = TARGET_INITIALIZER; #include "gt-alpha.h" - |