diff options
Diffstat (limited to 'gcc/config/alpha/alpha.c')
-rw-r--r-- | gcc/config/alpha/alpha.c | 110 |
1 files changed, 65 insertions, 45 deletions
diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c index d6a9f6bc661..e5ee7d8b0e5 100644 --- a/gcc/config/alpha/alpha.c +++ b/gcc/config/alpha/alpha.c @@ -1,6 +1,6 @@ /* Subroutines used for code generation on the DEC Alpha. Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, - 2000, 2001, 2002 Free Software Foundation, Inc. + 2000, 2001, 2002, 2003 Free Software Foundation, Inc. Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu) This file is part of GNU CC. @@ -148,7 +148,7 @@ static rtx alpha_expand_builtin PARAMS ((tree, rtx, rtx, enum machine_mode, int)); static void alpha_sa_mask PARAMS ((unsigned long *imaskP, unsigned long *fmaskP)); -static int find_lo_sum +static int find_lo_sum_using_gp PARAMS ((rtx *, void *)); static int alpha_does_function_need_gp PARAMS ((void)); @@ -501,6 +501,9 @@ override_options () warning ("trap mode not supported for VAX floats"); alpha_fptm = ALPHA_FPTM_SU; } + if (target_flags_explicit & MASK_LONG_DOUBLE_128) + warning ("128-bit long double not supported for VAX floats"); + target_flags &= ~MASK_LONG_DOUBLE_128; } { @@ -1205,9 +1208,12 @@ tls_symbolic_operand_1 (op, mode, size, unspec) else return 0; - letter = (unspec == UNSPEC_DTPREL ? 'D' : 'T'); - - return str[1] == letter; + if (unspec == UNSPEC_DTPREL) + return str[1] == 'D'; + else if (str[1] == 'I') + return size == 64; + else + return str[1] == 'T'; } /* Return true if OP is valid for 16-bit DTP relative relocations. */ @@ -1762,7 +1768,7 @@ tls_symbolic_operand_type (symbol) attribute visibility next time. At least we don't crash... */ if (str[1] == 'G' || str[1] == 'D') return TLS_MODEL_GLOBAL_DYNAMIC; - if (str[1] == 'T') + if (str[1] == 'I' || str[1] == 'T') return TLS_MODEL_INITIAL_EXEC; } else if (str[0] == '@') @@ -1776,6 +1782,8 @@ tls_symbolic_operand_type (symbol) else return TLS_MODEL_GLOBAL_DYNAMIC; } + if (str[1] == 'I') + return TLS_MODEL_INITIAL_EXEC; if (str[1] == 'T') { /* 64-bit local exec is the same as initial exec except without @@ -1817,6 +1825,10 @@ alpha_in_small_data_p (exp) if (TREE_CODE (exp) == STRING_CST) return false; + /* Functions are never in the small data area. Duh. */ + if (TREE_CODE (exp) == FUNCTION_DECL) + return false; + if (TREE_CODE (exp) == VAR_DECL && DECL_SECTION_NAME (exp)) { const char *section = TREE_STRING_POINTER (DECL_SECTION_NAME (exp)); @@ -1901,6 +1913,8 @@ alpha_encode_section_info (decl, first) encoding = 'D'; break; case TLS_MODEL_INITIAL_EXEC: + encoding = 'I'; + break; case TLS_MODEL_LOCAL_EXEC: encoding = 'T'; break; @@ -1920,18 +1934,22 @@ alpha_encode_section_info (decl, first) { char *newstr; size_t len; + char want_prefix = (is_local ? '@' : '%'); + char other_prefix = (is_local ? '%' : '@'); - if (symbol_str[0] == (is_local ? '@' : '%')) + if (symbol_str[0] == want_prefix) { if (symbol_str[1] == encoding) return; symbol_str += 2; } + else if (symbol_str[0] == other_prefix) + symbol_str += 2; len = strlen (symbol_str) + 1; newstr = alloca (len + 2); - newstr[0] = (is_local ? '@' : '%'); + newstr[0] = want_prefix; newstr[1] = encoding; memcpy (newstr + 2, symbol_str, len); @@ -2945,12 +2963,8 @@ alpha_expand_mov (mode, operands) compiled at the end of compilation. In the meantime, someone can re-encode-section-info on some symbol changing it e.g. from global to local-not-small. If this happens, we'd have emitted a plain - load rather than a high+losum load and not recognize the insn. - - So if rtl inlining is in effect, we delay the global/not-global - decision until rest_of_compilation by wrapping it in an - UNSPEC_SYMBOL. */ - if (TARGET_EXPLICIT_RELOCS && flag_inline_functions + load rather than a high+losum load and not recognize the insn. */ + if (TARGET_EXPLICIT_RELOCS && rtx_equal_function_value_matters && global_symbolic_operand (operands[1], mode)) { @@ -3011,7 +3025,7 @@ alpha_expand_mov (mode, operands) } /* Otherwise we've nothing left but to drop the thing to memory. */ - operands[1] = force_const_mem (DImode, operands[1]); + operands[1] = force_const_mem (mode, operands[1]); if (reload_in_progress) { emit_move_insn (operands[0], XEXP (operands[1], 0)); @@ -3332,10 +3346,10 @@ alpha_emit_conditional_branch (code) if (op1 == const0_rtx) cmp_code = NIL, branch_code = code; - /* We want to use cmpcc/bcc when we can, since there is a zero delay - bypass between logicals and br/cmov on EV5. But we don't want to - force valid immediate constants into registers needlessly. */ - else if (GET_CODE (op1) == CONST_INT) + /* 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)) { HOST_WIDE_INT v = INTVAL (op1), n = -v; @@ -5385,7 +5399,7 @@ alpha_gp_save_rtx () { rtx r = get_hard_reg_initial_val (DImode, 29); if (GET_CODE (r) != MEM) - r = gen_mem_addressof (r, NULL_TREE); + r = gen_mem_addressof (r, NULL_TREE, /*rescan=*/true); return r; } @@ -6241,12 +6255,15 @@ alpha_va_start (valist, nextarg) If no integer registers need be stored, then we must subtract 48 in order to account for the integer arg registers which are counted - in argsize above, but which are not actually stored on the stack. */ + in argsize above, but which are not actually stored on the stack. + Must further be careful here about structures straddling the last + integer argument register; that futzes with pretend_args_size, + which changes the meaning of AP. */ if (NUM_ARGS <= 6) offset = TARGET_ABI_OPEN_VMS ? UNITS_PER_WORD : 6 * UNITS_PER_WORD; else - offset = -6 * UNITS_PER_WORD; + offset = -6 * UNITS_PER_WORD + current_function_pretend_args_size; if (TARGET_ABI_OPEN_VMS) { @@ -6741,14 +6758,16 @@ alpha_sa_mask (imaskP, fmaskP) /* We need to restore these for the handler. */ if (current_function_calls_eh_return) - for (i = 0; ; ++i) - { - unsigned regno = EH_RETURN_DATA_REGNO (i); - if (regno == INVALID_REGNUM) - break; - imask |= 1L << regno; - } - + { + for (i = 0; ; ++i) + { + unsigned regno = EH_RETURN_DATA_REGNO (i); + if (regno == INVALID_REGNUM) + break; + imask |= 1L << regno; + } + } + /* If any register spilled, then spill the return address also. */ /* ??? This is required by the Digital stack unwind specification and isn't needed if we're doing Dwarf2 unwinding. */ @@ -6890,11 +6909,18 @@ const struct attribute_spec vms_attribute_table[] = #endif static int -find_lo_sum (px, data) +find_lo_sum_using_gp (px, data) rtx *px; void *data ATTRIBUTE_UNUSED; { - return GET_CODE (*px) == LO_SUM; + return GET_CODE (*px) == LO_SUM && XEXP (*px, 0) == pic_offset_table_rtx; +} + +int +alpha_find_lo_sum_using_gp (insn) + rtx insn; +{ + return for_each_rtx (&PATTERN (insn), find_lo_sum_using_gp, NULL) > 0; } static int @@ -6923,15 +6949,9 @@ alpha_does_function_need_gp () for (; insn; insn = NEXT_INSN (insn)) if (INSN_P (insn) && GET_CODE (PATTERN (insn)) != USE - && GET_CODE (PATTERN (insn)) != CLOBBER) - { - enum attr_type type = get_attr_type (insn); - if (type == TYPE_LDSYM || type == TYPE_JSR) - return 1; - if (TARGET_EXPLICIT_RELOCS - && for_each_rtx (&PATTERN (insn), find_lo_sum, NULL) > 0) - return 1; - } + && GET_CODE (PATTERN (insn)) != CLOBBER + && get_attr_usegp (insn)) + return 1; return 0; } @@ -7202,7 +7222,7 @@ alpha_expand_prologue () } /* Now save any other registers required to be saved. */ - for (i = 0; i < 32; i++) + for (i = 0; i < 31; i++) if (imask & (1L << i)) { mem = gen_rtx_MEM (DImode, plus_constant (sa_reg, reg_offset)); @@ -7211,7 +7231,7 @@ alpha_expand_prologue () reg_offset += 8; } - for (i = 0; i < 32; i++) + for (i = 0; i < 31; i++) if (fmask & (1L << i)) { mem = gen_rtx_MEM (DFmode, plus_constant (sa_reg, reg_offset)); @@ -7617,7 +7637,7 @@ alpha_expand_epilogue () reg_offset += 8; imask &= ~(1L << REG_RA); - for (i = 0; i < 32; ++i) + for (i = 0; i < 31; ++i) if (imask & (1L << i)) { if (i == HARD_FRAME_POINTER_REGNUM && fp_is_frame_pointer) @@ -7631,7 +7651,7 @@ alpha_expand_epilogue () reg_offset += 8; } - for (i = 0; i < 32; ++i) + for (i = 0; i < 31; ++i) if (fmask & (1L << i)) { mem = gen_rtx_MEM (DFmode, plus_constant(sa_reg, reg_offset)); |