OSDN Git Service

* config/alpha/alpha.c (alpha_next_sequence_number): New.
authorrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 9 Sep 2001 08:42:40 +0000 (08:42 +0000)
committerrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 9 Sep 2001 08:42:40 +0000 (08:42 +0000)
(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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@45493 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/alpha/alpha-protos.h
gcc/config/alpha/alpha.c
gcc/config/alpha/alpha.h
gcc/config/alpha/alpha.md
gcc/config/alpha/elf.h

index 7442f6f..fddbac3 100644 (file)
@@ -1,3 +1,50 @@
+2001-09-09  Richard Henderson  <rth@redhat.com>
+
+       * 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  <jh@suse.cz>
 
        * reg-stack.c (subst_stack_regs_pat): Fix fcmov reversal code.
index 7de2c62..be18c63 100644 (file)
@@ -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 */
index 3250fe8..d0bbb96 100644 (file)
@@ -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;
 }
 \f
+/* 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)
@@ -4969,6 +5231,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 ()
 {
   rtx insn;
@@ -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;
index c320701..220eb62 100644 (file)
@@ -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)  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 ENCODE_SECTION_INFO(DECL)  \
-  if (TREE_CODE (DECL) == FUNCTION_DECL && ! TREE_PUBLIC (DECL)) \
-    SYMBOL_REF_FLAG (XEXP (DECL_RTL (DECL), 0)) = 1;
+#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) == '*')
 \f
 /* 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}},                                 \
index 828024b..3cce979 100644 (file)
@@ -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 "" "")
index c8e7667..3bb51cc 100644 (file)
@@ -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;