From 1eb356b98df2a898b6650c7641d629fcf3db0c30 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sun, 9 Sep 2001 01:42:40 -0700 Subject: [PATCH] alpha.c (alpha_next_sequence_number): New. * config/alpha/alpha.c (alpha_next_sequence_number): New. (alpha_this_literal_sequence_number): New. (alpha_this_gpdisp_sequence_number): New. (some_operand, input_operand): Add HIGH. (local_symbolic_operand): New. (alpha_encode_section_info): New. (alpha_legitimate_address_p): Allow LO_SUM. (alpha_legitimize_address): Generate HIGH+LO_SUM. (alpha_expand_mov): Likewise. (secondary_reload_class): Check memory_operand not general_operand for FP_REGS test. (alpha_expand_unaligned_load): Force LO_SUM addresses into a register. (alpha_expand_unaligned_store): Likewise. (alpha_expand_unaligned_load_words): Likewise. (alpha_expand_unaligned_store_words): Likewise. (alpha_expand_block_clear): Likewise. (print_operand): Handle %#, %*, %H. (print_operand_address): Handle LO_SUM. (find_lo_sum): New. (alpha_does_function_need_gp): Use it. (alpha_expand_block_move): Fix signed compare warnings. (alpha_sa_mask, alpha_align_insns): Likewise. * config/alpha/alpha-protos.h: Update. * config/alpha/alpha.h (TARGET_EXPLICIT_RELOCS): New. (MASK_EXPLICIT_RELOCS): New. (TARGET_SWITCHES): Add -mexplicit-relocs. (EXTRA_CONSTRAINT): Add 'T'. (PREFERRED_RELOAD_CLASS): HIGH goes in GENERAL_REGS. (ASM_APP_ON, ASM_APP_OFF): Turn on and off asm macro expansion. (ENCODE_SECTION_INFO): Out line. (REDO_SECTION_INFO_P): New. (STRIP_NAME_ENCODING): New. (ASM_OUTPUT_LABELREF): New. (PRINT_OPERAND_PUNCT_VALID_P): Add #, *. (PREDICATE_CODES): Update. * config/alpha/alpha.md (divmodsi_internal_er, divmoddi_internal_er, call_osf_1_er_noreturn, call_osf_1_er, movdi_er_low, movdi_er_nofix, movdi_er_fix, prologue_ldgp_1_er, builtin_setjmp_receiver_sub_label_er, builtin_setjmp_receiver_er, exception_receiver_1_er, call_value_osf_1_er): New patterns. (sibcall_osf_1, sibcall_value_osf_1): Remove register alternative. (movqi, movhi, movsi): Add explicit $31 base register to lda. * config/alpha/elf.h (ASM_FILE_START): Set nomacro if explicit relocs. (FINAL_PRESCAN_INSN): New. From-SVN: r45493 --- gcc/ChangeLog | 47 +++++ gcc/config/alpha/alpha-protos.h | 2 + gcc/config/alpha/alpha.c | 345 ++++++++++++++++++++++++++++---- gcc/config/alpha/alpha.h | 69 +++++-- gcc/config/alpha/alpha.md | 185 ++++++++++++++--- gcc/config/alpha/elf.h | 10 + 6 files changed, 581 insertions(+), 77 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 7442f6f5855..fddbac35d20 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,50 @@ +2001-09-09 Richard Henderson + + * config/alpha/alpha.c (alpha_next_sequence_number): New. + (alpha_this_literal_sequence_number): New. + (alpha_this_gpdisp_sequence_number): New. + (some_operand, input_operand): Add HIGH. + (local_symbolic_operand): New. + (alpha_encode_section_info): New. + (alpha_legitimate_address_p): Allow LO_SUM. + (alpha_legitimize_address): Generate HIGH+LO_SUM. + (alpha_expand_mov): Likewise. + (secondary_reload_class): Check memory_operand not general_operand + for FP_REGS test. + (alpha_expand_unaligned_load): Force LO_SUM addresses into a register. + (alpha_expand_unaligned_store): Likewise. + (alpha_expand_unaligned_load_words): Likewise. + (alpha_expand_unaligned_store_words): Likewise. + (alpha_expand_block_clear): Likewise. + (print_operand): Handle %#, %*, %H. + (print_operand_address): Handle LO_SUM. + (find_lo_sum): New. + (alpha_does_function_need_gp): Use it. + (alpha_expand_block_move): Fix signed compare warnings. + (alpha_sa_mask, alpha_align_insns): Likewise. + * config/alpha/alpha-protos.h: Update. + * config/alpha/alpha.h (TARGET_EXPLICIT_RELOCS): New. + (MASK_EXPLICIT_RELOCS): New. + (TARGET_SWITCHES): Add -mexplicit-relocs. + (EXTRA_CONSTRAINT): Add 'T'. + (PREFERRED_RELOAD_CLASS): HIGH goes in GENERAL_REGS. + (ASM_APP_ON, ASM_APP_OFF): Turn on and off asm macro expansion. + (ENCODE_SECTION_INFO): Out line. + (REDO_SECTION_INFO_P): New. + (STRIP_NAME_ENCODING): New. + (ASM_OUTPUT_LABELREF): New. + (PRINT_OPERAND_PUNCT_VALID_P): Add #, *. + (PREDICATE_CODES): Update. + * config/alpha/alpha.md (divmodsi_internal_er, divmoddi_internal_er, + call_osf_1_er_noreturn, call_osf_1_er, movdi_er_low, movdi_er_nofix, + movdi_er_fix, prologue_ldgp_1_er, builtin_setjmp_receiver_sub_label_er, + builtin_setjmp_receiver_er, exception_receiver_1_er, + call_value_osf_1_er): New patterns. + (sibcall_osf_1, sibcall_value_osf_1): Remove register alternative. + (movqi, movhi, movsi): Add explicit $31 base register to lda. + * config/alpha/elf.h (ASM_FILE_START): Set nomacro if explicit relocs. + (FINAL_PRESCAN_INSN): New. + Sat Sep 8 22:00:55 CEST 2001 Jan Hubicka * reg-stack.c (subst_stack_regs_pat): Fix fcmov reversal code. diff --git a/gcc/config/alpha/alpha-protos.h b/gcc/config/alpha/alpha-protos.h index 7de2c62d717..be18c633910 100644 --- a/gcc/config/alpha/alpha-protos.h +++ b/gcc/config/alpha/alpha-protos.h @@ -54,6 +54,7 @@ extern int some_operand PARAMS ((rtx, enum machine_mode)); extern int some_ni_operand PARAMS ((rtx, enum machine_mode)); extern int input_operand PARAMS ((rtx, enum machine_mode)); extern int current_file_function_operand PARAMS ((rtx, enum machine_mode)); +extern int local_symbolic_operand PARAMS ((rtx, enum machine_mode)); extern int call_operand PARAMS ((rtx, enum machine_mode)); extern int alpha_comparison_operator PARAMS ((rtx, enum machine_mode)); extern int alpha_zero_comparison_operator PARAMS ((rtx, enum machine_mode)); @@ -146,4 +147,5 @@ extern rtx function_arg PARAMS ((CUMULATIVE_ARGS, enum machine_mode, #endif extern void alpha_start_function PARAMS ((FILE *, const char *, tree)); extern void alpha_end_function PARAMS ((FILE *, const char *, tree)); +extern void alpha_encode_section_info PARAMS ((tree)); #endif /* TREE CODE */ diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c index 3250fe8b2b8..d0bbb9664fc 100644 --- a/gcc/config/alpha/alpha.c +++ b/gcc/config/alpha/alpha.c @@ -105,6 +105,14 @@ static int alpha_sr_alias_set; static const char *alpha_fnname; +/* The next explicit relocation sequence number. */ +int alpha_next_sequence_number = 1; + +/* The literal and gpdisp sequence numbers for this insn, as printed + by %# and %* respectively. */ +int alpha_this_literal_sequence_number; +int alpha_this_gpdisp_sequence_number; + /* Declarations of static functions. */ static void alpha_set_memflags_1 PARAMS ((rtx, int, int, int)); @@ -116,6 +124,8 @@ static void alpha_expand_unaligned_store_words PARAMS ((rtx *out_regs, rtx smem, HOST_WIDE_INT words, HOST_WIDE_INT ofs)); static void alpha_sa_mask PARAMS ((unsigned long *imaskP, unsigned long *fmaskP)); +static int find_lo_sum + PARAMS ((rtx *, void *)); static int alpha_does_function_need_gp PARAMS ((void)); static int alpha_ra_ever_killed @@ -662,7 +672,7 @@ some_operand (op, mode) switch (GET_CODE (op)) { case REG: case MEM: case CONST_DOUBLE: case CONST_INT: case LABEL_REF: - case SYMBOL_REF: case CONST: + case SYMBOL_REF: case CONST: case HIGH: return 1; case SUBREG: @@ -733,6 +743,10 @@ input_operand (op, mode) case CONSTANT_P_RTX: return 1; + case HIGH: + return (TARGET_EXPLICIT_RELOCS + && local_symbolic_operand (XEXP (op, 0), mode)); + default: break; } @@ -754,6 +768,41 @@ current_file_function_operand (op, mode) || op == XEXP (DECL_RTL (current_function_decl), 0))); } +/* Return true if OP is a SYMBOL_REF or CONST referencing a variable + known to be defined in this file. */ + +int +local_symbolic_operand (op, mode) + rtx op; + enum machine_mode mode ATTRIBUTE_UNUSED; +{ + const char *str; + + if (GET_CODE (op) == LABEL_REF) + return 1; + + if (GET_CODE (op) == CONST + && GET_CODE (XEXP (op, 0)) == PLUS + && GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST_INT) + op = XEXP (XEXP (op, 0), 0); + + if (GET_CODE (op) != SYMBOL_REF) + return 0; + + str = XSTR (op, 0); + + /* ??? SYMBOL_REF_FLAG is set for local function symbols, but we + run into problems with the rtl inliner in that the symbol was + once external, but is local after inlining, which results in + unrecognizable insns. */ + + return (CONSTANT_POOL_ADDRESS_P (op) + /* If @, then ENCODE_SECTION_INFO sez it's local. */ + || str[0] == '@' + /* If *$, then ASM_GENERATE_INTERNAL_LABEL sez it's local. */ + || (str[0] == '*' && str[1] == '$')); +} + /* Return 1 if OP is a valid operand for the MEM of a CALL insn. */ int @@ -1154,6 +1203,120 @@ alpha_tablejump_best_label (insn) return best_label ? best_label : const0_rtx; } +/* If we are referencing a function that is static, make the SYMBOL_REF + special. We use this to see indicate we can branch to this function + without setting PV or restoring GP. + + If this is a variable that is known to be defined locally, add "@v" + to the name. If in addition the variable is to go in .sdata/.sbss, + then add "@s" instead. */ + +void +alpha_encode_section_info (decl) + tree decl; +{ + const char *symbol_str; + bool is_local, is_small; + + if (TREE_CODE (decl) == FUNCTION_DECL) + { + if (! TREE_PUBLIC (decl)) + SYMBOL_REF_FLAG (XEXP (DECL_RTL (decl), 0)) = 1; + return; + } + + /* Early out if we're not going to do anything with this data. */ + if (! TARGET_EXPLICIT_RELOCS) + return; + + /* Careful not to prod global register variables. */ + if (TREE_CODE (decl) != VAR_DECL + || GET_CODE (DECL_RTL (decl)) != MEM + || GET_CODE (XEXP (DECL_RTL (decl), 0)) != SYMBOL_REF) + return; + + symbol_str = XSTR (XEXP (DECL_RTL (decl), 0), 0); + + /* A variable is considered "local" if it is defined in this module. */ + + if (DECL_EXTERNAL (decl)) + is_local = false; + /* Linkonce and weak data is never local. */ + else if (DECL_ONE_ONLY (decl) || DECL_WEAK (decl)) + is_local = false; + else if (! TREE_PUBLIC (decl)) + is_local = true; + /* If PIC, then assume that any global name can be overridden by + symbols resolved from other modules. */ + else if (flag_pic) + is_local = false; + /* Uninitialized COMMON variable may be unified with symbols + resolved from other modules. */ + else if (DECL_COMMON (decl) + && (DECL_INITIAL (decl) == NULL + || DECL_INITIAL (decl) == error_mark_node)) + is_local = false; + /* Otherwise we're left with initialized (or non-common) global data + which is of necessity defined locally. */ + else + is_local = true; + + /* Determine if DECL will wind up in .sdata/.sbss. */ + + is_small = false; + if (DECL_SECTION_NAME (decl)) + { + const char *section = TREE_STRING_POINTER (DECL_SECTION_NAME (decl)); + if (strcmp (section, ".sdata") == 0 + || strcmp (section, ".sbss") == 0) + is_small = true; + } + else + { + HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (decl)); + + /* If the variable has already been defined in the output file, then it + is too late to put it in sdata if it wasn't put there in the first + place. The test is here rather than above, because if it is already + in sdata, then it can stay there. */ + + if (TREE_ASM_WRITTEN (decl)) + ; + + /* If this is an incomplete type with size 0, then we can't put it in + sdata because it might be too big when completed. */ + else if (size > 0 && size <= g_switch_value) + is_small = true; + } + + /* Finally, encode this into the symbol string. */ + if (is_local) + { + const char *string; + char *newstr; + size_t len; + + if (symbol_str[0] == '@') + { + if (symbol_str[1] == (is_small ? 's' : 'v')) + return; + symbol_str += 2; + } + + len = strlen (symbol_str) + 1; + newstr = alloca (len + 2); + + newstr[0] = '@'; + newstr[1] = (is_small ? 's' : 'v'); + memcpy (newstr + 2, symbol_str, len); + + string = ggc_alloc_string (newstr, len + 2 - 1); + XSTR (XEXP (DECL_RTL (decl), 0), 0) = string; + } + else if (symbol_str[0] == '@') + abort (); +} + /* legitimate_address_p recognizes an RTL expression that is a valid memory address for an instruction. The MODE argument is the machine mode for the MEM expression that wants to use this address. @@ -1222,6 +1385,30 @@ alpha_legitimate_address_p (mode, x, strict) return true; } + /* If we're managing explicit relocations, LO_SUM is valid. */ + else if (TARGET_EXPLICIT_RELOCS && GET_CODE (x) == LO_SUM) + { + rtx ofs = XEXP (x, 1); + x = XEXP (x, 0); + + /* Discard non-paradoxical subregs. */ + if (GET_CODE (x) == SUBREG + && (GET_MODE_SIZE (GET_MODE (x)) + < GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))))) + x = SUBREG_REG (x); + + /* Must have a valid base register. */ + if (! (REG_P (x) + && (strict + ? STRICT_REG_OK_FOR_BASE_P (x) + : NONSTRICT_REG_OK_FOR_BASE_P (x)))) + return false; + + /* The symbol must be local. */ + if (local_symbolic_operand (ofs, Pmode)) + return true; + } + return false; } @@ -1278,6 +1465,14 @@ alpha_legitimize_address (x, oldx, mode) goto split_addend; } + /* If this is a local symbol, split the address into HIGH/LO_SUM parts. */ + if (TARGET_EXPLICIT_RELOCS && local_symbolic_operand (x, Pmode)) + { + rtx temp = gen_reg_rtx (Pmode); + emit_insn (gen_rtx_SET (VOIDmode, temp, gen_rtx_HIGH (Pmode, x))); + return gen_rtx_LO_SUM (Pmode, temp, x); + } + return NULL; split_addend: @@ -1465,7 +1660,8 @@ secondary_reload_class (class, mode, x, in) > GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))))) return GENERAL_REGS; - if (in && INTEGRAL_MODE_P (mode) && ! general_operand (x, mode)) + if (in && INTEGRAL_MODE_P (mode) + && ! (memory_operand (x, mode) || x == const0_rtx)) return GENERAL_REGS; } @@ -1830,6 +2026,15 @@ alpha_expand_mov (mode, operands) && ! reg_or_0_operand (operands[1], mode)) operands[1] = force_reg (mode, operands[1]); + if (TARGET_EXPLICIT_RELOCS && local_symbolic_operand (operands[1], mode)) + { + rtx scratch = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode); + emit_insn (gen_rtx_SET (VOIDmode, scratch, + gen_rtx_HIGH (Pmode, operands[1]))); + operands[1] = gen_rtx_LO_SUM (Pmode, scratch, operands[1]); + return false; + } + /* Early out for non-constants and valid constants. */ if (! CONSTANT_P (operands[1]) || input_operand (operands[1], mode)) return false; @@ -2961,7 +3166,7 @@ alpha_expand_unaligned_load (tgt, mem, size, ofs, sign) HOST_WIDE_INT size, ofs; int sign; { - rtx meml, memh, addr, extl, exth, tmp; + rtx meml, memh, addr, extl, exth, tmp, mema; enum machine_mode mode; meml = gen_reg_rtx (DImode); @@ -2970,28 +3175,31 @@ alpha_expand_unaligned_load (tgt, mem, size, ofs, sign) extl = gen_reg_rtx (DImode); exth = gen_reg_rtx (DImode); + mema = XEXP (mem, 0); + if (GET_CODE (mema) == LO_SUM) + mema = force_reg (Pmode, mema); + /* AND addresses cannot be in any alias set, since they may implicitly alias surrounding code. Ideally we'd have some alias set that covered all types except those with alignment 8 or higher. */ tmp = change_address (mem, DImode, gen_rtx_AND (DImode, - plus_constant (XEXP (mem, 0), ofs), + plus_constant (mema, ofs), GEN_INT (-8))); set_mem_alias_set (tmp, 0); emit_move_insn (meml, tmp); tmp = change_address (mem, DImode, gen_rtx_AND (DImode, - plus_constant (XEXP (mem, 0), - ofs + size - 1), + plus_constant (mema, ofs + size - 1), GEN_INT (-8))); set_mem_alias_set (tmp, 0); emit_move_insn (memh, tmp); if (sign && size == 2) { - emit_move_insn (addr, plus_constant (XEXP (mem, 0), ofs+2)); + emit_move_insn (addr, plus_constant (mema, ofs+2)); emit_insn (gen_extxl (extl, meml, GEN_INT (64), addr)); emit_insn (gen_extqh (exth, memh, addr)); @@ -3005,7 +3213,7 @@ alpha_expand_unaligned_load (tgt, mem, size, ofs, sign) } else { - emit_move_insn (addr, plus_constant (XEXP (mem, 0), ofs)); + emit_move_insn (addr, plus_constant (mema, ofs)); emit_insn (gen_extxl (extl, meml, GEN_INT (size*8), addr)); switch ((int) size) { @@ -3044,33 +3252,36 @@ alpha_expand_unaligned_store (dst, src, size, ofs) rtx dst, src; HOST_WIDE_INT size, ofs; { - rtx dstl, dsth, addr, insl, insh, meml, memh; + rtx dstl, dsth, addr, insl, insh, meml, memh, dsta; dstl = gen_reg_rtx (DImode); dsth = gen_reg_rtx (DImode); insl = gen_reg_rtx (DImode); insh = gen_reg_rtx (DImode); + dsta = XEXP (dst, 0); + if (GET_CODE (dsta) == LO_SUM) + dsta = force_reg (Pmode, dsta); + /* AND addresses cannot be in any alias set, since they may implicitly alias surrounding code. Ideally we'd have some alias set that covered all types except those with alignment 8 or higher. */ meml = change_address (dst, DImode, gen_rtx_AND (DImode, - plus_constant (XEXP (dst, 0), ofs), + plus_constant (dsta, ofs), GEN_INT (-8))); set_mem_alias_set (meml, 0); memh = change_address (dst, DImode, gen_rtx_AND (DImode, - plus_constant (XEXP (dst, 0), - ofs+size-1), + plus_constant (dsta, ofs + size - 1), GEN_INT (-8))); set_mem_alias_set (memh, 0); emit_move_insn (dsth, memh); emit_move_insn (dstl, meml); - addr = copy_addr_to_reg (plus_constant (XEXP (dst, 0), ofs)); + addr = copy_addr_to_reg (plus_constant (dsta, ofs)); if (src != const0_rtx) { @@ -3143,9 +3354,13 @@ alpha_expand_unaligned_load_words (out_regs, smem, words, ofs) rtx const im8 = GEN_INT (-8); rtx const i64 = GEN_INT (64); rtx ext_tmps[MAX_MOVE_WORDS], data_regs[MAX_MOVE_WORDS+1]; - rtx sreg, areg, tmp; + rtx sreg, areg, tmp, smema; HOST_WIDE_INT i; + smema = XEXP (smem, 0); + if (GET_CODE (smema) == LO_SUM) + smema = force_reg (Pmode, smema); + /* Generate all the tmp registers we need. */ for (i = 0; i < words; ++i) { @@ -3162,7 +3377,7 @@ alpha_expand_unaligned_load_words (out_regs, smem, words, ofs) { tmp = change_address (smem, DImode, gen_rtx_AND (DImode, - plus_constant (XEXP(smem,0), 8*i), + plus_constant (smema, 8*i), im8)); set_mem_alias_set (tmp, 0); emit_move_insn (data_regs[i], tmp); @@ -3170,7 +3385,7 @@ alpha_expand_unaligned_load_words (out_regs, smem, words, ofs) tmp = change_address (smem, DImode, gen_rtx_AND (DImode, - plus_constant (XEXP(smem,0), 8*words - 1), + plus_constant (smema, 8*words - 1), im8)); set_mem_alias_set (tmp, 0); emit_move_insn (data_regs[words], tmp); @@ -3179,7 +3394,7 @@ alpha_expand_unaligned_load_words (out_regs, smem, words, ofs) extxh with offset zero a noop instead of zeroing the register, so we must take care of that edge condition ourselves with cmov. */ - sreg = copy_addr_to_reg (XEXP (smem, 0)); + sreg = copy_addr_to_reg (smema); areg = expand_binop (DImode, and_optab, sreg, GEN_INT (7), NULL, 1, OPTAB_WIDEN); for (i = 0; i < words; ++i) @@ -3220,9 +3435,13 @@ alpha_expand_unaligned_store_words (data_regs, dmem, words, ofs) #endif rtx ins_tmps[MAX_MOVE_WORDS]; rtx st_tmp_1, st_tmp_2, dreg; - rtx st_addr_1, st_addr_2; + rtx st_addr_1, st_addr_2, dmema; HOST_WIDE_INT i; + dmema = XEXP (dmem, 0); + if (GET_CODE (dmema) == LO_SUM) + dmema = force_reg (Pmode, dmema); + /* Generate all the tmp registers we need. */ if (data_regs != NULL) for (i = 0; i < words; ++i) @@ -3235,15 +3454,12 @@ alpha_expand_unaligned_store_words (data_regs, dmem, words, ofs) st_addr_2 = change_address (dmem, DImode, gen_rtx_AND (DImode, - plus_constant (XEXP(dmem,0), - words*8 - 1), + plus_constant (dmema, words*8 - 1), im8)); set_mem_alias_set (st_addr_2, 0); st_addr_1 = change_address (dmem, DImode, - gen_rtx_AND (DImode, - XEXP (dmem, 0), - im8)); + gen_rtx_AND (DImode, dmema, im8)); set_mem_alias_set (st_addr_1, 0); /* Load up the destination end bits. */ @@ -3251,7 +3467,7 @@ alpha_expand_unaligned_store_words (data_regs, dmem, words, ofs) emit_move_insn (st_tmp_1, st_addr_1); /* Shift the input data into place. */ - dreg = copy_addr_to_reg (XEXP (dmem, 0)); + dreg = copy_addr_to_reg (dmema); if (data_regs != NULL) { for (i = words-1; i >= 0; --i) @@ -3285,7 +3501,7 @@ alpha_expand_unaligned_store_words (data_regs, dmem, words, ofs) { rtx tmp = change_address (dmem, DImode, gen_rtx_AND (DImode, - plus_constant(XEXP (dmem,0), i*8), + plus_constant(dmema, i*8), im8)); set_mem_alias_set (tmp, 0); emit_move_insn (tmp, data_regs ? ins_tmps[i-1] : const0_rtx); @@ -3315,7 +3531,7 @@ alpha_expand_block_move (operands) rtx orig_dst = operands[0]; rtx data_regs[2 * MAX_MOVE_WORDS + 16]; rtx tmp; - int i, words, ofs, nregs = 0; + unsigned int i, words, ofs, nregs = 0; if (orig_bytes <= 0) return 1; @@ -3773,7 +3989,7 @@ alpha_expand_block_clear (operands) words = bytes / 8; for (i = 0; i < words; ++i) - emit_move_insn (adjust_address(orig_dst, DImode, ofs + i * 8), + emit_move_insn (adjust_address (orig_dst, DImode, ofs + i * 8), const0_rtx); bytes -= words * 8; @@ -3785,18 +4001,23 @@ alpha_expand_block_clear (operands) if (align >= 32 && bytes > 16) { + rtx orig_dsta; + emit_move_insn (adjust_address (orig_dst, SImode, ofs), const0_rtx); bytes -= 4; ofs += 4; + orig_dsta = XEXP (orig_dst, 0); + if (GET_CODE (orig_dsta) == LO_SUM) + orig_dsta = force_reg (Pmode, orig_dsta); + words = bytes / 8; for (i = 0; i < words; ++i) { rtx mem = change_address (orig_dst, DImode, gen_rtx_AND (DImode, - plus_constant (XEXP (orig_dst, 0), - ofs + i*8), + plus_constant (orig_dsta, ofs + i*8), GEN_INT (-8))); set_mem_alias_set (mem, 0); emit_move_insn (mem, const0_rtx); @@ -4272,6 +4493,28 @@ print_operand (file, x, code) fputc ((TARGET_FLOAT_VAX ? 'g' : 't'), file); break; + case '#': + if (alpha_this_literal_sequence_number == 0) + alpha_this_literal_sequence_number = alpha_next_sequence_number++; + fprintf (file, "%d", alpha_this_literal_sequence_number); + break; + + case '*': + if (alpha_this_gpdisp_sequence_number == 0) + alpha_this_gpdisp_sequence_number = alpha_next_sequence_number++; + fprintf (file, "%d", alpha_this_gpdisp_sequence_number); + break; + + case 'H': + if (GET_CODE (x) == HIGH) + { + output_addr_const (file, XEXP (x, 0)); + fputs ("($29)\t\t!gprelhigh", file); + } + else + output_operand_lossage ("invalid %%H value"); + break; + case 'r': /* If this operand is the constant zero, write it as "$31". */ if (GET_CODE (x) == REG) @@ -4280,7 +4523,6 @@ print_operand (file, x, code) fprintf (file, "$31"); else output_operand_lossage ("invalid %%r value"); - break; case 'R': @@ -4291,7 +4533,6 @@ print_operand (file, x, code) fprintf (file, "$f31"); else output_operand_lossage ("invalid %%R value"); - break; case 'N': @@ -4512,12 +4753,33 @@ print_operand_address (file, addr) offset = INTVAL (XEXP (addr, 1)); addr = XEXP (addr, 0); } + + if (GET_CODE (addr) == LO_SUM) + { + output_addr_const (file, XEXP (addr, 1)); + if (offset) + { + fputc ('+', file); + fprintf (file, HOST_WIDE_INT_PRINT_DEC, offset); + } + + addr = XEXP (addr, 0); + if (GET_CODE (addr) == REG) + basereg = REGNO (addr); + else if (GET_CODE (addr) == SUBREG + && GET_CODE (SUBREG_REG (addr)) == REG) + basereg = subreg_regno (addr); + else + abort (); + fprintf (file, "($%d)\t\t!gprellow", basereg); + return; + } + if (GET_CODE (addr) == REG) basereg = REGNO (addr); else if (GET_CODE (addr) == SUBREG && GET_CODE (SUBREG_REG (addr)) == REG) - basereg = REGNO (SUBREG_REG (addr)) - + SUBREG_BYTE (addr) / GET_MODE_SIZE (GET_MODE (addr)); + basereg = subreg_regno (addr); else if (GET_CODE (addr) == CONST_INT) offset = INTVAL (addr); else @@ -4827,7 +5089,7 @@ alpha_sa_mask (imaskP, fmaskP) { unsigned long imask = 0; unsigned long fmask = 0; - int i; + unsigned int i; #ifdef ASM_OUTPUT_MI_THUNK if (!current_function_is_thunk) @@ -4968,6 +5230,14 @@ vms_valid_decl_attribute_p (decl, attributes, identifier, args) #endif +static int +find_lo_sum (px, data) + rtx *px; + void *data ATTRIBUTE_UNUSED; +{ + return GET_CODE (*px) == LO_SUM; +} + static int alpha_does_function_need_gp () { @@ -5001,6 +5271,9 @@ alpha_does_function_need_gp () 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; } return 0; @@ -6606,7 +6879,7 @@ alpha_align_insns (insns, max_align, next_group, next_nop) /* If the known alignment is smaller than the recognized insn group, realign the output. */ - else if (align < len) + else if ((int) align < len) { unsigned int new_log_align = len > 8 ? 4 : 3; rtx where; @@ -6626,7 +6899,7 @@ alpha_align_insns (insns, max_align, next_group, next_nop) can make use of the knowledge of what sorts of instructions were issued in the previous group to make sure that all of the added nops are really free. */ - else if (ofs + len > align) + else if (ofs + len > (int) align) { int nop_count = (align - ofs) / 4; rtx where; diff --git a/gcc/config/alpha/alpha.h b/gcc/config/alpha/alpha.h index c320701d37d..220eb6235a7 100644 --- a/gcc/config/alpha/alpha.h +++ b/gcc/config/alpha/alpha.h @@ -158,6 +158,10 @@ extern enum alpha_fp_trap_mode alpha_fptm; #define MASK_CIX (1 << 11) #define TARGET_CIX (target_flags & MASK_CIX) +/* This means use !literal style explicit relocations. */ +#define MASK_EXPLICIT_RELOCS (1 << 12) +#define TARGET_EXPLICIT_RELOCS (target_flags & MASK_EXPLICIT_RELOCS) + /* This means that the processor is an EV5, EV56, or PCA56. Unlike alpha_cpu this is not affected by -mtune= setting. */ #define MASK_CPU_EV5 (1 << 28) @@ -227,6 +231,9 @@ extern enum alpha_fp_trap_mode alpha_fptm; {"no-fix", -MASK_FIX, ""}, \ {"cix", MASK_CIX, N_("Emit code for the counting ISA extension")}, \ {"no-cix", -MASK_CIX, ""}, \ + {"explicit-relocs", MASK_EXPLICIT_RELOCS, \ + N_("Emit code using explicit relocation directives")}, \ + {"no-explicit-relocs", -MASK_EXPLICIT_RELOCS, ""}, \ {"", TARGET_DEFAULT | TARGET_CPU_DEFAULT, ""} } #define TARGET_DEFAULT MASK_FP|MASK_FPREGS @@ -792,6 +799,7 @@ enum reg_class { NO_REGS, PV_REG, GENERAL_REGS, FLOAT_REGS, ALL_REGS, : (C) == 'R' ? current_file_function_operand (OP, Pmode) \ : (C) == 'S' ? (GET_CODE (OP) == CONST_INT \ && (unsigned HOST_WIDE_INT) INTVAL (OP) < 64) \ + : (C) == 'T' ? GET_CODE (OP) == HIGH \ : 0) /* Given an rtx X being reloaded into a reg required to be @@ -803,8 +811,9 @@ enum reg_class { NO_REGS, PV_REG, GENERAL_REGS, FLOAT_REGS, ALL_REGS, register via memory. */ #define PREFERRED_RELOAD_CLASS(X, CLASS) \ - (CONSTANT_P (X) && (X) != const0_rtx && (X) != CONST0_RTX (GET_MODE (X)) \ - ? ((CLASS) == FLOAT_REGS || (CLASS) == NO_REGS ? NO_REGS : GENERAL_REGS)\ + (GET_CODE (X) == HIGH ? GENERAL_REGS \ + : CONSTANT_P (X) && (X) != const0_rtx && (X) != CONST0_RTX (GET_MODE (X)) \ + ? ((CLASS) == FLOAT_REGS || (CLASS) == NO_REGS ? NO_REGS : GENERAL_REGS) \ : (CLASS)) /* Loading and storing HImode or QImode values to and from memory @@ -1737,13 +1746,11 @@ do { \ /* Output to assembler file text saying following lines may contain character constants, extra white space, comments, etc. */ - -#define ASM_APP_ON "" +#define ASM_APP_ON (TARGET_EXPLICIT_RELOCS ? "\t.set\tmacro\n" : "") /* Output to assembler file text saying following lines no longer contain unusual constructs. */ - -#define ASM_APP_OFF "" +#define ASM_APP_OFF (TARGET_EXPLICIT_RELOCS ? "\t.set\tnomacro\n" : "") #define TEXT_SECTION_ASM_OP "\t.text" @@ -1785,13 +1792,29 @@ literal_section () \ #define READONLY_DATA_SECTION literal_section -/* If we are referencing a function that is static, make the SYMBOL_REF - special. We use this to see indicate we can branch to this function - without setting PV or restoring GP. */ +/* Define this macro if references to a symbol must be treated differently + depending on something about the variable or function named by the symbol + (such as what section it is in). */ -#define ENCODE_SECTION_INFO(DECL) \ - if (TREE_CODE (DECL) == FUNCTION_DECL && ! TREE_PUBLIC (DECL)) \ - SYMBOL_REF_FLAG (XEXP (DECL_RTL (DECL), 0)) = 1; +#define ENCODE_SECTION_INFO(DECL) alpha_encode_section_info (DECL) + +/* If a variable is weakened, made one only or moved into a different + section, it may be necessary to redo the section info to move the + variable out of sdata. */ + +#define REDO_SECTION_INFO_P(DECL) \ + ((TREE_CODE (DECL) == VAR_DECL) \ + && (DECL_ONE_ONLY (DECL) || DECL_WEAK (DECL) || DECL_COMMON (DECL) \ + || DECL_SECTION_NAME (DECL) != 0)) + +#define STRIP_NAME_ENCODING(VAR,SYMBOL_NAME) \ +do { \ + (VAR) = (SYMBOL_NAME); \ + if ((VAR)[0] == '@') \ + (VAR) += 2; \ + if ((VAR)[0] == '*') \ + (VAR)++; \ +} while (0) /* How to refer to registers in assembler output. This sequence is indexed by compiler's hard-register-number (see above). */ @@ -1810,6 +1833,20 @@ literal_section () \ #define DBX_REGISTER_NUMBER(REGNO) (REGNO) +/* Strip name encoding when emitting labels. */ + +#define ASM_OUTPUT_LABELREF(STREAM, NAME) \ +do { \ + const char *name_ = NAME; \ + if (*name_ == '@') \ + name_ += 2; \ + if (*name_ == '*') \ + name_++; \ + else \ + fputs (user_label_prefix, STREAM); \ + fputs (name_, STREAM); \ +} while (0) + /* This is how to output the definition of a user-level label named NAME, such as the label on a static function or variable NAME. */ @@ -2089,7 +2126,8 @@ do { \ */ #define PRINT_OPERAND_PUNCT_VALID_P(CODE) \ - ((CODE) == '/' || (CODE) == ',' || (CODE) == '-' || (CODE) == '~') + ((CODE) == '/' || (CODE) == ',' || (CODE) == '-' || (CODE) == '~' \ + || (CODE) == '#' || (CODE) == '*') /* Print a memory address as an operand to reference that memory location. */ @@ -2121,11 +2159,12 @@ do { \ {"divmod_operator", {DIV, MOD, UDIV, UMOD}}, \ {"fp0_operand", {CONST_DOUBLE}}, \ {"current_file_function_operand", {SYMBOL_REF}}, \ + {"local_symbolic_operand", {SYMBOL_REF, CONST, LABEL_REF}}, \ {"call_operand", {REG, SYMBOL_REF}}, \ {"input_operand", {SUBREG, REG, MEM, CONST_INT, CONST_DOUBLE, \ - SYMBOL_REF, CONST, LABEL_REF}}, \ + SYMBOL_REF, CONST, LABEL_REF, HIGH, LO_SUM}}, \ {"some_operand", {SUBREG, REG, MEM, CONST_INT, CONST_DOUBLE, \ - SYMBOL_REF, CONST, LABEL_REF}}, \ + SYMBOL_REF, CONST, LABEL_REF, HIGH, LO_SUM}}, \ {"some_ni_operand", {SUBREG, REG, MEM}}, \ {"aligned_memory_operand", {MEM}}, \ {"unaligned_memory_operand", {MEM}}, \ diff --git a/gcc/config/alpha/alpha.md b/gcc/config/alpha/alpha.md index 828024b37a1..3cce9794b24 100644 --- a/gcc/config/alpha/alpha.md +++ b/gcc/config/alpha/alpha.md @@ -1103,6 +1103,18 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi" ;; Lengths of 8 for ldq $t12,__divq($gp); jsr $t9,($t12),__divq as ;; expanded by the assembler. + +(define_insn "*divmodsi_internal_er" + [(set (reg:DI 27) + (sign_extend:DI (match_operator:SI 0 "divmod_operator" + [(reg:DI 24) (reg:DI 25)]))) + (clobber (reg:DI 23)) + (clobber (reg:DI 28))] + "TARGET_EXPLICIT_RELOCS && ! TARGET_ABI_OPEN_VMS" + "ldq $27,__%E0($29)\t\t!literal!%#\;jsr $23,($27),__%E0\t\t!lituse_jsr!%#" + [(set_attr "type" "jsr") + (set_attr "length" "8")]) + (define_insn "*divmodsi_internal" [(set (reg:DI 27) (sign_extend:DI (match_operator:SI 0 "divmod_operator" @@ -1114,6 +1126,17 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi" [(set_attr "type" "jsr") (set_attr "length" "8")]) +(define_insn "*divmoddi_internal_er" + [(set (reg:DI 27) + (match_operator:DI 0 "divmod_operator" + [(reg:DI 24) (reg:DI 25)])) + (clobber (reg:DI 23)) + (clobber (reg:DI 28))] + "TARGET_EXPLICIT_RELOCS && ! TARGET_ABI_OPEN_VMS" + "ldq $27,__%E0($29)\t\t!literal!%#\;jsr $23,($27),__%E0\t\t!lituse_jsr!%#" + [(set_attr "type" "jsr") + (set_attr "length" "8")]) + (define_insn "*divmoddi_internal" [(set (reg:DI 27) (match_operator:DI 0 "divmod_operator" @@ -4346,6 +4369,33 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi" } }) +(define_insn "*call_osf_1_er_noreturn" + [(call (mem:DI (match_operand:DI 0 "call_operand" "c,R,i")) + (match_operand 1 "" "")) + (clobber (reg:DI 27)) + (clobber (reg:DI 26))] + "TARGET_EXPLICIT_RELOCS && TARGET_ABI_OSF + && find_reg_note (insn, REG_NORETURN, NULL_RTX)" + "@ + jsr $26,($27),0 + bsr $26,$%0..ng + ldq $27,%0($29)\t\t!literal!%#\;jsr $26,($27),%0\t\t!lituse_jsr!%#" + [(set_attr "type" "jsr") + (set_attr "length" "*,*,8")]) + +(define_insn "*call_osf_1_er" + [(call (mem:DI (match_operand:DI 0 "call_operand" "c,R,i")) + (match_operand 1 "" "")) + (clobber (reg:DI 27)) + (clobber (reg:DI 26))] + "TARGET_EXPLICIT_RELOCS && TARGET_ABI_OSF" + "@ + jsr $26,($27),0\;ldah $29,0($26)\t\t!gpdisp!%*\;lda $29,0($29)\t\t!gpdisp!%* + bsr $26,$%0..ng + ldq $27,%0($29)\t\t!literal!%#\;jsr $26,($27),%0\t\t!lituse_jsr!%#\;ldah $29,0($26)\t\t!gpdisp!%*\;lda $29,0($29)\t\t!gpdisp!%*" + [(set_attr "type" "jsr") + (set_attr "length" "12,*,16")]) + (define_insn "*call_osf_1_noreturn" [(call (mem:DI (match_operand:DI 0 "call_operand" "c,R,i")) (match_operand 1 "" "")) @@ -4373,14 +4423,11 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi" (set_attr "length" "12,*,16")]) (define_insn "*sibcall_osf_1" - [(call (mem:DI (match_operand:DI 0 "call_operand" "R,i")) + [(call (mem:DI (match_operand:DI 0 "current_file_function_operand" "R")) (match_operand 1 "" ""))] "TARGET_ABI_OSF" - "@ - br $31,$%0..ng - jmp $31,%0" - [(set_attr "type" "jsr") - (set_attr "length" "*,8")]) + "br $31,$%0..ng" + [(set_attr "type" "jsr")]) (define_insn "*call_nt_1" [(call (mem:DI (match_operand:DI 0 "call_operand" "r,R,i")) @@ -4707,8 +4754,8 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi" || reg_or_0_operand (operands[1], SImode))" "@ mov %r1,%0 - lda %0,%1 - ldah %0,%h1 + lda %0,%1($31) + ldah %0,%h1($31) ldl %0,%1 stl %r1,%0 fmov %R1,%0 @@ -4724,8 +4771,8 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi" || reg_or_0_operand (operands[1], SImode))" "@ mov %r1,%0 - lda %0,%1 - ldah %0,%h1 + lda %0,%1($31) + ldah %0,%h1($31) ldl %0,%1 stl %r1,%0 fmov %R1,%0 @@ -4761,7 +4808,7 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi" || register_operand (operands[1], HImode))" "@ mov %r1,%0 - lda %0,%L1" + lda %0,%L1($31)" [(set_attr "type" "ilog,iadd")]) (define_insn "*movhi_bwx" @@ -4772,7 +4819,7 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi" || reg_or_0_operand (operands[1], HImode))" "@ mov %r1,%0 - lda %0,%L1 + lda %0,%L1($31) ldwu %0,%1 stw %r1,%0" [(set_attr "type" "ilog,iadd,ild,ist")]) @@ -4785,7 +4832,7 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi" || register_operand (operands[1], QImode))" "@ mov %r1,%0 - lda %0,%L1" + lda %0,%L1($31)" [(set_attr "type" "ilog,iadd")]) (define_insn "*movqi_bwx" @@ -4796,7 +4843,7 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi" || reg_or_0_operand (operands[1], QImode))" "@ mov %r1,%0 - lda %0,%L1 + lda %0,%L1($31) ldbu %0,%1 stb %r1,%0" [(set_attr "type" "ilog,iadd,ild,ist")]) @@ -4832,16 +4879,43 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi" FAIL; }) +(define_insn "*movdi_er_low" + [(set (match_operand:DI 0 "register_operand" "=r") + (lo_sum:DI (match_operand:DI 1 "register_operand" "r") + (match_operand:DI 2 "local_symbolic_operand" "")))] + "TARGET_EXPLICIT_RELOCS" + "lda %0,%2(%1)\t\t!gprellow") + +(define_insn "*movdi_er_nofix" + [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,r,r,r,m,*f,*f,Q") + (match_operand:DI 1 "input_operand" "rJ,K,L,T,s,m,rJ,*fJ,Q,*f"))] + "TARGET_EXPLICIT_RELOCS && ! TARGET_FIX + && (register_operand (operands[0], DImode) + || reg_or_0_operand (operands[1], DImode)) + && ! local_symbolic_operand (operands[1], DImode)" + "@ + mov %r1,%0 + lda %0,%1($31) + ldah %0,%h1($31) + ldah %0,%H1 + ldq %0,%1($29)\t\t!literal + ldq%A1 %0,%1 + stq%A0 %r1,%0 + fmov %R1,%0 + ldt %0,%1 + stt %R1,%0" + [(set_attr "type" "ilog,iadd,iadd,iadd,ldsym,ild,ist,fcpys,fld,fst")]) + (define_insn "*movdi_nofix" [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,r,r,m,*f,*f,Q") (match_operand:DI 1 "input_operand" "rJ,K,L,s,m,rJ,*fJ,Q,*f"))] - "! TARGET_FIX + "! TARGET_EXPLICIT_RELOCS && ! TARGET_FIX && (register_operand (operands[0], DImode) || reg_or_0_operand (operands[1], DImode))" "@ mov %r1,%0 - lda %0,%1 - ldah %0,%h1 + lda %0,%1($31) + ldah %0,%h1($31) lda %0,%1 ldq%A1 %0,%1 stq%A0 %r1,%0 @@ -4850,16 +4924,38 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi" stt %R1,%0" [(set_attr "type" "ilog,iadd,iadd,ldsym,ild,ist,fcpys,fld,fst")]) +(define_insn "*movdi_er_fix" + [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,r,r,r,m,*f,*f,Q,r,*f") + (match_operand:DI 1 "input_operand" "rJ,K,L,T,s,m,rJ,*fJ,Q,*f,*f,r"))] + "TARGET_EXPLICIT_RELOCS && TARGET_FIX + && (register_operand (operands[0], DImode) + || reg_or_0_operand (operands[1], DImode)) + && ! local_symbolic_operand (operands[1], DImode)" + "@ + mov %r1,%0 + lda %0,%1($31) + ldah %0,%h1($31) + ldah %0,%H1 + ldq %0,%1($29)\t\t!literal + ldq%A1 %0,%1 + stq%A0 %r1,%0 + fmov %R1,%0 + ldt %0,%1 + stt %R1,%0 + ftoit %1,%0 + itoft %1,%0" + [(set_attr "type" "ilog,iadd,iadd,iadd,ldsym,ild,ist,fcpys,fld,fst,ftoi,itof")]) + (define_insn "*movdi_fix" [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,r,r,m,*f,*f,Q,r,*f") (match_operand:DI 1 "input_operand" "rJ,K,L,s,m,rJ,*fJ,Q,*f,*f,r"))] - "TARGET_FIX + "! TARGET_EXPLICIT_RELOCS && TARGET_FIX && (register_operand (operands[0], DImode) || reg_or_0_operand (operands[1], DImode))" "@ mov %r1,%0 - lda %0,%1 - ldah %0,%h1 + lda %0,%1($31) + ldah %0,%h1($31) lda %0,%1 ldq%A1 %0,%1 stq%A0 %r1,%0 @@ -5548,6 +5644,11 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi" "" "") +(define_insn "*prologue_ldgp_1_er" + [(unspec_volatile [(const_int 0)] UNSPECV_LDGP1)] + "TARGET_EXPLICIT_RELOCS" + "ldah $29,0($27)\t\t!gpdisp!%*\;lda $29,0($29)\t\t!gpdisp!%*\n$%~..ng:") + (define_insn "*prologue_ldgp_1" [(unspec_volatile [(const_int 0)] UNSPECV_LDGP1)] "" @@ -5637,6 +5738,13 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi" "jmp $31,(%0),0" [(set_attr "type" "ibr")]) +(define_insn "*builtin_setjmp_receiver_sub_label_er" + [(unspec_volatile [(label_ref (match_operand 0 "" ""))] UNSPECV_SETJMPR)] + "TARGET_EXPLICIT_RELOCS && TARGET_ABI_OSF && TARGET_AS_CAN_SUBTRACT_LABELS" + "\n$LSJ%=:\;ldah $29,0($27)\t\t!gpdisp!%*\;lda $29,$LSJ%=-%l0($29)\t\t!gpdisp!%*" + [(set_attr "length" "8") + (set_attr "type" "multi")]) + (define_insn "*builtin_setjmp_receiver_sub_label" [(unspec_volatile [(label_ref (match_operand 0 "" ""))] UNSPECV_SETJMPR)] "TARGET_ABI_OSF && TARGET_AS_CAN_SUBTRACT_LABELS" @@ -5644,6 +5752,13 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi" [(set_attr "length" "8") (set_attr "type" "multi")]) +(define_insn "*builtin_setjmp_receiver_er" + [(unspec_volatile [(label_ref (match_operand 0 "" ""))] UNSPECV_SETJMPR)] + "TARGET_EXPLICIT_RELOCS && TARGET_ABI_OSF" + "br $29,$LSJ%=\n$LSJ%=:\;ldah $29,0($29)\t\t!gpdisp!%*\;lda $29,0($29)\t\t!gpdisp!%*" + [(set_attr "length" "12") + (set_attr "type" "multi")]) + (define_insn "builtin_setjmp_receiver" [(unspec_volatile [(label_ref (match_operand 0 "" ""))] UNSPECV_SETJMPR)] "TARGET_ABI_OSF" @@ -5661,6 +5776,13 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi" operands[0] = const0_rtx; }) +(define_insn "*exception_receiver_1_er" + [(unspec_volatile [(const_int 0)] UNSPECV_EHR)] + "TARGET_EXPLICIT_RELOCS && ! TARGET_LD_BUGGY_LDGP" + "ldah $29,0($26)\t\t!gpdisp!%*\;lda $29,0($29)\t\t!gpdisp!%*" + [(set_attr "length" "8") + (set_attr "type" "multi")]) + (define_insn "*exception_receiver_1" [(unspec_volatile [(const_int 0)] UNSPECV_EHR)] "! TARGET_LD_BUGGY_LDGP" @@ -5752,6 +5874,20 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi" ;; The call patterns are at the end of the file because their ;; wildcard operand0 interferes with nice recognition. +(define_insn "*call_value_osf_1_er" + [(set (match_operand 0 "" "") + (call (mem:DI (match_operand:DI 1 "call_operand" "c,R,i")) + (match_operand 2 "" ""))) + (clobber (reg:DI 27)) + (clobber (reg:DI 26))] + "TARGET_EXPLICIT_RELOCS && TARGET_ABI_OSF" + "@ + jsr $26,($27),0\;ldah $29,0($26)\t\t!gpdisp!%*\;lda $29,0($29)\t\t!gpdisp!%* + bsr $26,$%1..ng + ldq $27,%1($29)\t\t!literal!%#\;jsr $26,($27),%1\t\t!lituse_jsr!%#\;ldah $29,0($26)\t\t!gpdisp!%*\;lda $29,0($29)\t\t!gpdisp!%*" + [(set_attr "type" "jsr") + (set_attr "length" "12,*,16")]) + (define_insn "*call_value_osf_1" [(set (match_operand 0 "" "") (call (mem:DI (match_operand:DI 1 "call_operand" "c,R,i")) @@ -5768,14 +5904,11 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi" (define_insn "*sibcall_value_osf_1" [(set (match_operand 0 "" "") - (call (mem:DI (match_operand:DI 1 "call_operand" "R,i")) + (call (mem:DI (match_operand:DI 1 "current_file_function_operand" "R")) (match_operand 2 "" "")))] "TARGET_ABI_OSF" - "@ - br $31,$%1..ng - jmp $31,%1" - [(set_attr "type" "jsr") - (set_attr "length" "*,8")]) + "br $31,$%1..ng" + [(set_attr "type" "jsr")]) (define_insn "*call_value_nt_1" [(set (match_operand 0 "" "") diff --git a/gcc/config/alpha/elf.h b/gcc/config/alpha/elf.h index c8e7667da82..3bb51cca6b2 100644 --- a/gcc/config/alpha/elf.h +++ b/gcc/config/alpha/elf.h @@ -58,6 +58,8 @@ do { \ } \ fprintf (FILE, "\t.set noat\n"); \ fprintf (FILE, "\t.set noreorder\n"); \ + if (TARGET_EXPLICIT_RELOCS) \ + fprintf (FILE, "\t.set nomacro\n"); \ if (TARGET_BWX | TARGET_MAX | TARGET_FIX | TARGET_CIX) \ { \ fprintf (FILE, "\t.arch %s\n", \ @@ -591,3 +593,11 @@ void FN () \ only EH sections. */ #define ASM_PREFERRED_EH_DATA_FORMAT(CODE,GLOBAL) \ (((GLOBAL) ? DW_EH_PE_indirect : 0) | DW_EH_PE_pcrel | DW_EH_PE_sdata4) + +/* If defined, a C statement to be executed just prior to the output of + assembler code for INSN. */ +#define FINAL_PRESCAN_INSN(INSN, OPVEC, NOPERANDS) \ + (alpha_this_literal_sequence_number = 0, \ + alpha_this_gpdisp_sequence_number = 0) +extern int alpha_this_literal_sequence_number; +extern int alpha_this_gpdisp_sequence_number;