]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
alpha.c (local_symbol_p): Split out from ...
authorRichard Henderson <rth@redhat.com>
Wed, 19 Sep 2001 18:55:22 +0000 (11:55 -0700)
committerRichard Henderson <rth@gcc.gnu.org>
Wed, 19 Sep 2001 18:55:22 +0000 (11:55 -0700)
* config/alpha/alpha.c (local_symbol_p): Split out from ...
(local_symbolic_operand): ... here.
(small_symbolic_operand): Check mode.
(global_symbolic_operand): New.
(input_operand): Reject symbolics if explicit relocs.
(call_operand): Tidy.
(alpha_legitimize_address): Use movdi_er_high_g.
(alpha_expand_mov): Likewise.
* config/alpha/alpha-protos.h: Update.
* config/alpha/alpha.h (PREDICATE_CODES): Update.
* config/alpha/alpha.md (UNSPEC_LITERAL, UNSPEC_LITUSE): New.
(UNSPEC_LDGP2, UNSPECV_PLDGP2): New.
(UNSPECV_LDGP2): Remove.
(all call patterns): Use 's' not 'i' for symbolic constraint.
(call_osf call_value_osf): Use call_operand.
(all osf call patterns): Use $gp.  New peepholes for explicit relocs.
(movdi_er_nofix, movdi_er_fix): Remove symbolic alternative.
(prologue_ldgp_1_er): Remove.
(ldgp_er_1, ldgp_er_2, prologue_ldgp_er_2): New.
(builtin_setjmp_receiver_er patterns): Use them.
(exception_receiver_er): Likewise.

From-SVN: r45694

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

index 336cf9bc32f39f9ebcdb71f91109e1f3d6136613..9c147c8e92b6ed93e9eb34d04597e9bae6661a08 100644 (file)
@@ -1,3 +1,27 @@
+2001-09-19  Richard Henderson  <rth@redhat.com>
+
+       * config/alpha/alpha.c (local_symbol_p): Split out from ...
+       (local_symbolic_operand): ... here.
+       (small_symbolic_operand): Check mode.
+       (global_symbolic_operand): New.
+       (input_operand): Reject symbolics if explicit relocs.
+       (call_operand): Tidy.
+       (alpha_legitimize_address): Use movdi_er_high_g.
+       (alpha_expand_mov): Likewise.
+       * config/alpha/alpha-protos.h: Update.
+       * config/alpha/alpha.h (PREDICATE_CODES): Update.
+       * config/alpha/alpha.md (UNSPEC_LITERAL, UNSPEC_LITUSE): New.
+       (UNSPEC_LDGP2, UNSPECV_PLDGP2): New.
+       (UNSPECV_LDGP2): Remove.
+       (all call patterns): Use 's' not 'i' for symbolic constraint.
+       (call_osf call_value_osf): Use call_operand.
+       (all osf call patterns): Use $gp.  New peepholes for explicit relocs.
+       (movdi_er_nofix, movdi_er_fix): Remove symbolic alternative.
+       (prologue_ldgp_1_er): Remove.
+       (ldgp_er_1, ldgp_er_2, prologue_ldgp_er_2): New.
+       (builtin_setjmp_receiver_er patterns): Use them.
+       (exception_receiver_er): Likewise.
+
 2001-09-19  Richard Henderson  <rth@redhat.com>
 
        * cfgbuild.c (find_sub_basic_blocks): Handle insns that can throw.
index c8ff11228b700adb77b31e6d4f4ba05af7e41390..8aae90c565c82a99705373cbd5d223786f3a4234 100644 (file)
@@ -18,6 +18,8 @@ along with GNU CC; see the file COPYING.  If not, write to
 the Free Software Foundation, 59 Temple Place - Suite 330,
 Boston, MA 02111-1307, USA.  */
 
+extern int alpha_next_sequence_number;
+
 extern void literal_section PARAMS ((void));
 extern void override_options PARAMS ((void));
 extern int zap_mask PARAMS ((HOST_WIDE_INT));
@@ -55,6 +57,8 @@ 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 small_symbolic_operand PARAMS ((rtx, enum machine_mode));
+extern int global_symbolic_operand PARAMS ((rtx, enum machine_mode));
 extern int call_operand PARAMS ((rtx, enum machine_mode));
 extern int symbolic_operand PARAMS ((rtx, enum machine_mode));
 extern int alpha_comparison_operator PARAMS ((rtx, enum machine_mode));
index d2d90d97076e851d21ae74ff936b4a40094ebd3c..79c247b5189e5ad6773579e51026ffbedcd55a01 100644 (file)
@@ -114,6 +114,8 @@ int alpha_this_literal_sequence_number;
 int alpha_this_gpdisp_sequence_number;
 
 /* Declarations of static functions.  */
+static bool local_symbol_p
+  PARAMS ((rtx));
 static void alpha_set_memflags_1
   PARAMS ((rtx, int, int, int));
 static rtx alpha_emit_set_const_1
@@ -795,6 +797,9 @@ input_operand (op, mode)
     case LABEL_REF:
     case SYMBOL_REF:
     case CONST:
+      if (TARGET_EXPLICIT_RELOCS)
+       return 0;
+
       /* This handles both the Windows/NT and OSF cases.  */
       return mode == ptr_mode || mode == DImode;
 
@@ -840,16 +845,32 @@ 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.  */
+/* Return true if OP is a LABEL_REF, or SYMBOL_REF or CONST referencing
+   a variable known to be defined in this file.  */
+
+static bool
+local_symbol_p (op)
+     rtx op;
+{
+  const char *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] == '$'));
+}
 
 int
 local_symbolic_operand (op, mode)
      rtx op;
      enum machine_mode mode;
 {
-  const char *str;
-
   if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op))
     return 0;
 
@@ -864,18 +885,7 @@ local_symbolic_operand (op, mode)
   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 local_symbol_p (op);
 }
 
 /* Return true if OP is a SYMBOL_REF or CONST referencing a variable
@@ -891,6 +901,9 @@ small_symbolic_operand (op, mode)
   if (! TARGET_SMALL_DATA)
     return 0;
 
+  if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op))
+    return 0;
+
   if (GET_CODE (op) == CONST
       && GET_CODE (XEXP (op, 0)) == PLUS
       && GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST_INT)
@@ -900,7 +913,7 @@ small_symbolic_operand (op, mode)
     return 0;
 
   if (CONSTANT_POOL_ADDRESS_P (op))
-    return GET_MODE_SIZE (get_pool_mode (op)) <= g_switch_value;
+    return GET_MODE_SIZE (get_pool_mode (op)) <= (unsigned) g_switch_value;
   else
     {
       str = XSTR (op, 0);
@@ -908,6 +921,28 @@ small_symbolic_operand (op, mode)
     }
 }
 
+/* Return true if OP is a SYMBOL_REF or CONST referencing a variable
+   not known (or known not) to be defined in this file.  */
+
+int
+global_symbolic_operand (op, mode)
+     rtx op;
+     enum machine_mode mode;
+{
+  if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op))
+    return 0;
+
+  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;
+
+  return ! local_symbol_p (op);
+}
+
 /* Return 1 if OP is a valid operand for the MEM of a CALL insn.  */
 
 int
@@ -918,10 +953,6 @@ call_operand (op, mode)
   if (mode != Pmode)
     return 0;
 
-  if (TARGET_ABI_UNICOSMK)
-    return GET_CODE (op) == REG;
-  if (GET_CODE (op) == SYMBOL_REF)
-    return 1;
   if (GET_CODE (op) == REG)
     {
       if (TARGET_ABI_OSF)
@@ -929,6 +960,10 @@ call_operand (op, mode)
       else
        return 1;
     }
+  if (TARGET_ABI_UNICOSMK)
+    return 0;
+  if (GET_CODE (op) == SYMBOL_REF)
+    return 1;
 
   return 0;
 }
@@ -1593,26 +1628,36 @@ alpha_legitimize_address (x, oldx, mode)
     }
 
   /* If this is a local symbol, split the address into HIGH/LO_SUM parts.  */
-  if (TARGET_EXPLICIT_RELOCS && local_symbolic_operand (x, Pmode))
+  if (TARGET_EXPLICIT_RELOCS && symbolic_operand (x, Pmode))
     {
       rtx scratch;
+      if (local_symbolic_operand (x, Pmode))
+       {
+         if (small_symbolic_operand (x, Pmode))
+           scratch = pic_offset_table_rtx;
+         else
+           {
+             rtx insn, tmp;
 
-      if (small_symbolic_operand (x, Pmode))
-       scratch = pic_offset_table_rtx;
+             scratch = gen_reg_rtx (Pmode);
+
+             tmp = gen_rtx_HIGH (Pmode, x);
+             tmp = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, tmp);
+              insn = emit_insn (gen_rtx_SET (VOIDmode, scratch, tmp));
+             REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, tmp,
+                                                   REG_NOTES (insn));
+           }
+
+         return gen_rtx_LO_SUM (Pmode, scratch, x);
+       }
       else
        {
-         rtx insn, tmp;
-
          scratch = gen_reg_rtx (Pmode);
-
-         tmp = gen_rtx_HIGH (Pmode, x);
-         tmp = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, tmp);
-          insn = emit_insn (gen_rtx_SET (VOIDmode, scratch, tmp));
-         REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, tmp,
-                                               REG_NOTES (insn));
+         emit_insn (gen_movdi_er_high_g (scratch, pic_offset_table_rtx,
+                                         x, const0_rtx));
+         /* ??? FIXME: Tag the use of scratch with a lituse.  */
+         return scratch;
        }
-
-      return gen_rtx_LO_SUM (Pmode, scratch, x);
     }
 
   return NULL;
@@ -2172,27 +2217,36 @@ 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))
+  if (TARGET_EXPLICIT_RELOCS && symbolic_operand (operands[1], mode))
     {
-      rtx scratch;
-
-      if (small_symbolic_operand (operands[1], Pmode))
-       scratch = pic_offset_table_rtx;
-      else
+      if (local_symbolic_operand (operands[1], mode))
        {
-         rtx insn, tmp;
+         rtx scratch;
 
-         scratch = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode);
+         if (small_symbolic_operand (operands[1], Pmode))
+           scratch = pic_offset_table_rtx;
+         else
+           {
+             rtx insn, tmp;
 
-         tmp = gen_rtx_HIGH (Pmode, operands[1]);
-         tmp = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, tmp);
-          insn = emit_insn (gen_rtx_SET (VOIDmode, scratch, tmp));
-         REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, tmp,
-                                               REG_NOTES (insn));
-       }
+             scratch = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode);
+
+             tmp = gen_rtx_HIGH (Pmode, operands[1]);
+             tmp = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, tmp);
+              insn = emit_insn (gen_rtx_SET (VOIDmode, scratch, tmp));
+             REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, tmp,
+                                                   REG_NOTES (insn));
+           }
 
-      operands[1] = gen_rtx_LO_SUM (Pmode, scratch, operands[1]);
-      return false;
+          operands[1] = gen_rtx_LO_SUM (Pmode, scratch, operands[1]);
+         return false;
+       }
+      else
+       {
+         emit_insn (gen_movdi_er_high_g (operands[0], pic_offset_table_rtx,
+                                         operands[1], const0_rtx));
+         return true;
+       }
     }
 
   /* Early out for non-constants and valid constants.  */
index b8db8d743527c91586cb072a4e428eec7b3f791a..45ff18c8f7ff6f8261027c21daff760ebdb6c6e9 100644 (file)
@@ -2189,6 +2189,8 @@ do {                                                                      \
   {"fp0_operand", {CONST_DOUBLE}},                                     \
   {"current_file_function_operand", {SYMBOL_REF}},                     \
   {"local_symbolic_operand", {SYMBOL_REF, CONST, LABEL_REF}},          \
+  {"small_symbolic_operand", {SYMBOL_REF, CONST}},                     \
+  {"global_symbolic_operand", {SYMBOL_REF, CONST}},                    \
   {"call_operand", {REG, SYMBOL_REF}},                                 \
   {"input_operand", {SUBREG, REG, MEM, CONST_INT, CONST_DOUBLE,                \
                     SYMBOL_REF, CONST, LABEL_REF}},                    \
index 494a997754fc357379cfc9e580e1d34dde59077f..55f084593533f8bd147904ecad839e7090ebaa25 100644 (file)
@@ -35,6 +35,9 @@
    (UNSPEC_UMK_LALM    7)
    (UNSPEC_UMK_LAL     8)
    (UNSPEC_UMK_LOAD_CIW        9)
+   (UNSPEC_LDGP2       10)
+   (UNSPEC_LITERAL     11)
+   (UNSPEC_LITUSE      12)
   ])
 
 ;; UNSPEC_VOLATILE:
@@ -49,9 +52,9 @@
    (UNSPECV_REALIGN    6)
    (UNSPECV_EHR                7)      ; exception_receiver
    (UNSPECV_MCOUNT     8)
-   (UNSPECV_LDGP1      9)
-   (UNSPECV_LDGP2      10)
-   (UNSPECV_FORCE_MOV  11)
+   (UNSPECV_FORCE_MOV  9)
+   (UNSPECV_LDGP1      10)
+   (UNSPECV_PLDGP2     11)     ; prologue ldgp
   ])
 
 ;; Where necessary, the suffixes _le and _be are used to distinguish between
@@ -638,7 +641,7 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
   ""
   "")
 
-(define_insn "*adddi_er_high"
+(define_insn "*adddi_er_high_l"
   [(set (match_operand:DI 0 "register_operand" "=r")
        (plus:DI (match_operand:DI 1 "register_operand" "r")
                 (high:DI (match_operand:DI 2 "local_symbolic_operand" ""))))]
@@ -4502,8 +4505,9 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
 })
 
 (define_expand "sibcall"
-  [(call (mem:DI (match_operand 0 "" ""))
-                (match_operand 1 "" ""))]
+  [(parallel [(call (mem:DI (match_operand 0 "" ""))
+                           (match_operand 1 "" ""))
+             (use (reg:DI 29))])]
   "TARGET_ABI_OSF"
 {
   if (GET_CODE (operands[0]) != MEM)
@@ -4514,7 +4518,7 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
 (define_expand "call_osf"
   [(parallel [(call (mem:DI (match_operand 0 "" ""))
                    (match_operand 1 "" ""))
-             (clobber (reg:DI 27))
+             (use (reg:DI 29))
              (clobber (reg:DI 26))])]
   ""
 {
@@ -4522,13 +4526,11 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
     abort ();
 
   operands[0] = XEXP (operands[0], 0);
-
-  if (GET_CODE (operands[0]) != SYMBOL_REF
-      && ! (GET_CODE (operands[0]) == REG && REGNO (operands[0]) == 27))
+  if (! call_operand (operands[0], Pmode))
     {
-      rtx tem = gen_rtx_REG (DImode, 27);
-      emit_move_insn (tem, operands[0]);
-      operands[0] = tem;
+      rtx pv = gen_rtx_REG (Pmode, 27);
+      emit_move_insn (pv, operands[0]);
+      operands[0] = pv;
     }
 })
 
@@ -4634,9 +4636,10 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
 })
 
 (define_expand "sibcall_value"
-  [(set (match_operand 0 "" "")
-       (call (mem:DI (match_operand 1 "" ""))
-             (match_operand 2 "" "")))]
+  [(parallel [(set (match_operand 0 "" "")
+                  (call (mem:DI (match_operand 1 "" ""))
+                        (match_operand 2 "" "")))
+             (use (reg:DI 29))])]
   "TARGET_ABI_OSF"
 {
   if (GET_CODE (operands[1]) != MEM)
@@ -4648,7 +4651,7 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
   [(parallel [(set (match_operand 0 "" "")
                   (call (mem:DI (match_operand 1 "" ""))
                         (match_operand 2 "" "")))
-             (clobber (reg:DI 27))
+             (use (reg:DI 29))
              (clobber (reg:DI 26))])]
   ""
 {
@@ -4656,13 +4659,11 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
     abort ();
 
   operands[1] = XEXP (operands[1], 0);
-
-  if (GET_CODE (operands[1]) != SYMBOL_REF
-      && ! (GET_CODE (operands[1]) == REG && REGNO (operands[1]) == 27))
+  if (! call_operand (operands[1], Pmode))
     {
-      rtx tem = gen_rtx_REG (DImode, 27);
-      emit_move_insn (tem, operands[1]);
-      operands[1] = tem;
+      rtx pv = gen_rtx_REG (Pmode, 27);
+      emit_move_insn (pv, operands[1]);
+      operands[1] = pv;
     }
 })
 
@@ -4735,39 +4736,98 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
   emit_move_insn (gen_rtx_REG (DImode, 25), operands[2]);
 })
 
-(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"))
+  [(call (mem:DI (match_operand:DI 0 "call_operand" "c,R,s"))
         (match_operand 1 "" ""))
-   (clobber (reg:DI 27))
+   (use (reg:DI 29))
    (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!%*
+   jsr $26,(%0),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!%*"
+   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")])
 
+;; We must use peep2 instead of a split because we need accurate life
+;; information for $gp.  Consider the case of { bar(); while (1); }.
+(define_peephole2
+  [(parallel [(call (mem:DI (match_operand:DI 0 "call_operand" ""))
+                   (match_operand 1 "" ""))
+             (use (reg:DI 29))
+             (clobber (reg:DI 26))])]
+  "TARGET_EXPLICIT_RELOCS && TARGET_ABI_OSF && reload_completed
+   && ! current_file_function_operand (operands[0], Pmode)
+   && peep2_regno_dead_p (1, 29)"
+  [(parallel [(call (mem:DI (match_dup 2))
+                   (match_dup 1))
+             (set (reg:DI 26) (plus:DI (pc) (const_int 4)))
+             (unspec_volatile [(reg:DI 29)] UNSPECV_BLOCKAGE)
+             (use (match_dup 0))])]
+{
+  if (CONSTANT_P (operands[0]))
+    {
+      operands[2] = gen_rtx_REG (Pmode, 27);
+      emit_move_insn (operands[2], operands[0]);
+    }
+  else
+    {
+      operands[2] = operands[0];
+      operands[0] = const0_rtx;
+    }
+})
+
+(define_peephole2
+  [(parallel [(call (mem:DI (match_operand:DI 0 "call_operand" ""))
+                   (match_operand 1 "" ""))
+             (use (reg:DI 29))
+             (clobber (reg:DI 26))])]
+  "TARGET_EXPLICIT_RELOCS && TARGET_ABI_OSF && reload_completed
+   && ! current_file_function_operand (operands[0], Pmode)
+   && ! peep2_regno_dead_p (1, 29)"
+  [(parallel [(call (mem:DI (match_dup 2))
+                   (match_dup 1))
+             (set (reg:DI 26) (plus:DI (pc) (const_int 4)))
+             (unspec_volatile [(reg:DI 29)] UNSPECV_BLOCKAGE)
+             (use (match_dup 0))])
+   (set (reg:DI 29)
+       (unspec_volatile:DI [(reg:DI 26) (match_dup 3)] UNSPECV_LDGP1))
+   (set (reg:DI 29)
+       (unspec:DI [(reg:DI 29) (match_dup 3)] UNSPEC_LDGP2))]
+{
+  if (CONSTANT_P (operands[0]))
+    {
+      operands[2] = gen_rtx_REG (Pmode, 27);
+      emit_move_insn (operands[2], operands[0]);
+    }
+  else
+    {
+      operands[2] = operands[0];
+      operands[0] = const0_rtx;
+    }
+  operands[3] = GEN_INT (alpha_next_sequence_number++);
+})
+
+;; We add a blockage unspec_volatile to prevent insns from moving down
+;; from above the call to in between the call and the ldah gpdisp.
+
+(define_insn "*call_osf_2_er"
+  [(call (mem:DI (match_operand:DI 0 "register_operand" "c"))
+        (match_operand 1 "" ""))
+   (set (reg:DI 26) (plus:DI (pc) (const_int 4)))
+   (unspec_volatile [(reg:DI 29)] UNSPECV_BLOCKAGE)
+   (use (match_operand 2 "" ""))]
+  "TARGET_EXPLICIT_RELOCS && TARGET_ABI_OSF"
+  "jsr $26,(%0),%2"
+  [(set_attr "type" "jsr")])
+
 (define_insn "*call_osf_1_noreturn"
-  [(call (mem:DI (match_operand:DI 0 "call_operand" "c,R,i"))
+  [(call (mem:DI (match_operand:DI 0 "call_operand" "c,R,s"))
         (match_operand 1 "" ""))
-   (clobber (reg:DI 27))
+   (use (reg:DI 29))
    (clobber (reg:DI 26))]
-  "TARGET_ABI_OSF && find_reg_note (insn, REG_NORETURN, NULL_RTX)"
+  "! TARGET_EXPLICIT_RELOCS && TARGET_ABI_OSF
+   && find_reg_note (insn, REG_NORETURN, NULL_RTX)"
   "@
    jsr $26,($27),0
    bsr $26,$%0..ng
@@ -4776,11 +4836,11 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
    (set_attr "length" "*,*,8")])
 
 (define_insn "*call_osf_1"
-  [(call (mem:DI (match_operand:DI 0 "call_operand" "c,R,i"))
+  [(call (mem:DI (match_operand:DI 0 "call_operand" "c,R,s"))
         (match_operand 1 "" ""))
-   (clobber (reg:DI 27))
+   (use (reg:DI 29))
    (clobber (reg:DI 26))]
-  "TARGET_ABI_OSF"
+  "! TARGET_EXPLICIT_RELOCS && TARGET_ABI_OSF"
   "@
    jsr $26,($27),0\;ldgp $29,0($26)
    bsr $26,$%0..ng
@@ -4790,13 +4850,14 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
 
 (define_insn "*sibcall_osf_1"
   [(call (mem:DI (match_operand:DI 0 "current_file_function_operand" "R"))
-        (match_operand 1 "" ""))]
+        (match_operand 1 "" ""))
+   (use (reg:DI 29))]
   "TARGET_ABI_OSF"
   "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"))
+  [(call (mem:DI (match_operand:DI 0 "call_operand" "r,R,s"))
         (match_operand 1 "" ""))
    (clobber (reg:DI 26))]
   "TARGET_ABI_WINDOWS_NT"
@@ -4808,7 +4869,7 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
    (set_attr "length" "*,*,12")])
 
 (define_insn "*call_vms_1"
-  [(call (mem:DI (match_operand:DI 0 "call_operand" "r,i"))
+  [(call (mem:DI (match_operand:DI 0 "call_operand" "r,s"))
         (match_operand 1 "" ""))
    (use (match_operand:DI 2 "nonimmediate_operand" "r,m"))
    (use (reg:DI 25))
@@ -5302,7 +5363,7 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
 }
   [(set_attr "type" "iadd")])
 
-(define_insn "*movdi_er_low"
+(define_insn "*movdi_er_low_l"
   [(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" "")))]
@@ -5314,25 +5375,33 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
     return "lda %0,%2(%1)\t\t!gprellow";
 })
 
+(define_insn "movdi_er_high_g"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (unspec:DI [(match_operand:DI 1 "register_operand" "r")
+                   (match_operand:DI 2 "global_symbolic_operand" "")
+                   (match_operand 3 "const_int_operand" "")]
+                  UNSPEC_LITERAL))]
+  "TARGET_EXPLICIT_RELOCS"
+  "ldq %0,%2(%1)\t\t!literal"
+  [(set_attr "type" "ldsym")])
+
 (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"))]
+  [(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,T,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)"
+       || reg_or_0_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")])
+  [(set_attr "type" "ilog,iadd,iadd,iadd,ild,ist,fcpys,fld,fst")])
 
 ;; The 'U' constraint matches symbolic operands on Unicos/Mk. Those should
 ;; have been split up by the rules above but we shouldn't reject the
@@ -5359,18 +5428,16 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
    (set_attr "length" "*,*,*,16,*,*,*,*,*,*")])
 
 (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"))]
+  [(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,T,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)"
+       || reg_or_0_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
@@ -5378,7 +5445,7 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
    stt %R1,%0
    ftoit %1,%0
    itoft %1,%0"
-  [(set_attr "type" "ilog,iadd,iadd,iadd,ldsym,ild,ist,fcpys,fld,fst,ftoi,itof")])
+  [(set_attr "type" "ilog,iadd,iadd,iadd,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")
@@ -6260,23 +6327,56 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
 ;; with them.
 
 (define_expand "prologue_ldgp"
-  [(unspec_volatile [(const_int 0)] UNSPECV_LDGP1)
-   (unspec_volatile [(const_int 0)] UNSPECV_LDGP2)]
+  [(set (match_dup 0)
+       (unspec_volatile:DI [(match_dup 1) (match_dup 2)] UNSPECV_LDGP1))
+   (set (match_dup 0)
+       (unspec_volatile:DI [(match_dup 0) (match_dup 2)] UNSPECV_PLDGP2))]
   ""
-  "")
+{
+  operands[0] = pic_offset_table_rtx;
+  operands[1] = gen_rtx_REG (Pmode, 27);
+  operands[2] = (TARGET_EXPLICIT_RELOCS
+                ? GEN_INT (alpha_next_sequence_number++)
+                : const0_rtx);
+})
 
-(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 "*ldgp_er_1"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (unspec_volatile:DI [(match_operand:DI 1 "register_operand" "r")
+                            (match_operand 2 "const_int_operand" "")]
+                           UNSPECV_LDGP1))]
+  "TARGET_EXPLICIT_RELOCS && TARGET_ABI_OSF"
+  "ldah %0,0(%1)\t\t!gpdisp!%2")
+
+(define_insn "*ldgp_er_2"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (unspec:DI [(match_operand:DI 1 "register_operand" "r")
+                   (match_operand 2 "const_int_operand" "")]
+                  UNSPEC_LDGP2))]
+  "TARGET_EXPLICIT_RELOCS && TARGET_ABI_OSF"
+  "lda %0,0(%1)\t\t!gpdisp!%2")
+
+(define_insn "*prologue_ldgp_er_2"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (unspec_volatile:DI [(match_operand:DI 1 "register_operand" "r")
+                            (match_operand 2 "const_int_operand" "")]
+                           UNSPECV_PLDGP2))]
+  "TARGET_EXPLICIT_RELOCS && TARGET_ABI_OSF"
+  "lda %0,0(%1)\t\t!gpdisp!%2\n$%~..ng:")
 
 (define_insn "*prologue_ldgp_1"
-  [(unspec_volatile [(const_int 0)] UNSPECV_LDGP1)]
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (unspec_volatile:DI [(match_operand:DI 1 "register_operand" "r")
+                            (match_operand 2 "const_int_operand" "")]
+                           UNSPECV_LDGP1))]
   ""
-  "ldgp $29,0($27)\n$%~..ng:")
+  "ldgp %0,0(%1)\n$%~..ng:")
 
 (define_insn "*prologue_ldgp_2"
-  [(unspec_volatile [(const_int 0)] UNSPECV_LDGP2)]
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (unspec_volatile:DI [(match_operand:DI 1 "register_operand" "r")
+                            (match_operand 2 "const_int_operand" "")]
+                           UNSPECV_PLDGP2))]
   ""
   "")
 
@@ -6359,33 +6459,66 @@ 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"
+(define_insn "*builtin_setjmp_receiver_er_sl_1"
   [(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")])
+  "lda $27,$LSJ%=-%l0($27)\n$LSJ%=:")
+  
+(define_insn "*builtin_setjmp_receiver_er_1"
+  [(unspec_volatile [(label_ref (match_operand 0 "" ""))] UNSPECV_SETJMPR)]
+  "TARGET_EXPLICIT_RELOCS && TARGET_ABI_OSF"
+  "br $27,$LSJ%=\n$LSJ%=:"
+  [(set_attr "type" "ibr")])
 
-(define_insn "*builtin_setjmp_receiver_sub_label"
+(define_split
   [(unspec_volatile [(label_ref (match_operand 0 "" ""))] UNSPECV_SETJMPR)]
-  "TARGET_ABI_OSF && TARGET_AS_CAN_SUBTRACT_LABELS"
-  "\n$LSJ%=:\;ldgp $29,$LSJ%=-%l0($27)"
-  [(set_attr "length" "8")
-   (set_attr "type" "multi")])
+  "TARGET_EXPLICIT_RELOCS && TARGET_ABI_OSF
+   && prev_nonnote_insn (insn) == operands[0]"
+  [(const_int 0)]
+  "DONE;")
 
-(define_insn "*builtin_setjmp_receiver_er"
+(define_insn "*builtin_setjmp_receiver_1"
   [(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!%*"
+  "TARGET_ABI_OSF"
+  "br $27,$LSJ%=\n$LSJ%=:\;ldgp $29,0($27)"
   [(set_attr "length" "12")
    (set_attr "type" "multi")])
 
-(define_insn "builtin_setjmp_receiver"
+(define_expand "builtin_setjmp_receiver_er"
+  [(unspec_volatile [(label_ref (match_operand 0 "" ""))] UNSPECV_SETJMPR)
+   (set (match_dup 1)
+       (unspec_volatile:DI [(match_dup 2) (match_dup 3)] UNSPECV_LDGP1))
+   (set (match_dup 1)
+       (unspec:DI [(match_dup 1) (match_dup 3)] UNSPEC_LDGP2))]
+  ""
+{
+  operands[1] = pic_offset_table_rtx;
+  operands[2] = gen_rtx_REG (Pmode, 27);
+  operands[3] = GEN_INT (alpha_next_sequence_number++);
+})
+
+(define_expand "builtin_setjmp_receiver"
   [(unspec_volatile [(label_ref (match_operand 0 "" ""))] UNSPECV_SETJMPR)]
   "TARGET_ABI_OSF"
-  "br $29,$LSJ%=\n$LSJ%=:\;ldgp $29,0($29)"
-  [(set_attr "length" "12")
-   (set_attr "type" "multi")])
+{
+  if (TARGET_EXPLICIT_RELOCS)
+    {
+      emit_insn (gen_builtin_setjmp_receiver_er (operands[0]));
+      DONE;
+    }
+})
+
+(define_expand "exception_receiver_er"
+  [(set (match_dup 0)
+       (unspec_volatile:DI [(match_dup 1) (match_dup 2)] UNSPECV_LDGP1))
+   (set (match_dup 0)
+       (unspec:DI [(match_dup 0) (match_dup 2)] UNSPEC_LDGP2))]
+  ""
+{
+  operands[0] = pic_offset_table_rtx;
+  operands[1] = gen_rtx_REG (Pmode, 26);
+  operands[2] = GEN_INT (alpha_next_sequence_number++);
+})
 
 (define_expand "exception_receiver"
   [(unspec_volatile [(match_dup 0)] UNSPECV_EHR)]
@@ -6393,17 +6526,15 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
 {
   if (TARGET_LD_BUGGY_LDGP)
     operands[0] = alpha_gp_save_rtx ();
+  else if (TARGET_EXPLICIT_RELOCS)
+    {
+      emit_insn (gen_exception_receiver_er ());
+      DONE;
+    }
   else
     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"
@@ -6411,16 +6542,12 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
   [(set_attr "length" "8")
    (set_attr "type" "multi")])
 
-;; ??? We don't represent the usage of $29 properly in address loads
-;; and function calls.  This leads to the following move being deleted
-;; as dead code unless it is represented as a volatile unspec.
-
 (define_insn "*exception_receiver_2"
   [(unspec_volatile [(match_operand:DI 0 "nonimmediate_operand" "r,m")]
                    UNSPECV_EHR)]
   "TARGET_LD_BUGGY_LDGP"
   "@
-   mov %0,$29
+   bis $31,%0,$29
    ldq $29,%0"
   [(set_attr "type" "ilog,ild")])
 
@@ -6555,37 +6682,119 @@ 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_umk"
+(define_insn "*call_value_osf_1_er"
   [(set (match_operand 0 "" "")
-       (call (mem:DI (match_operand:DI 1 "call_operand" "r"))
+       (call (mem:DI (match_operand:DI 1 "call_operand" "c,R,s"))
              (match_operand 2 "" "")))
-   (use (reg:DI 25))
+   (use (reg:DI 29))
    (clobber (reg:DI 26))]
-  "TARGET_ABI_UNICOSMK"
-  "jsr $26,(%1)"
+  "TARGET_EXPLICIT_RELOCS && TARGET_ABI_OSF"
+  "@
+   jsr $26,(%1),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),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")])
+
+;; We must use peep2 instead of a split because we need accurate life
+;; information for $gp.  Consider the case of { bar(); while (1); }.
+(define_peephole2
+  [(parallel [(set (match_operand 0 "" "")
+                  (call (mem:DI (match_operand:DI 1 "call_operand" ""))
+                        (match_operand 2 "" "")))
+             (use (reg:DI 29))
+             (clobber (reg:DI 26))])]
+  "TARGET_EXPLICIT_RELOCS && TARGET_ABI_OSF  && reload_completed
+   && ! current_file_function_operand (operands[0], Pmode)
+   && peep2_regno_dead_p (1, 29)"
+  [(parallel [(set (match_dup 0)
+                  (call (mem:DI (match_dup 3))
+                        (match_dup 2)))
+             (set (reg:DI 26) (plus:DI (pc) (const_int 4)))
+             (unspec_volatile [(reg:DI 29)] UNSPECV_BLOCKAGE)
+             (use (match_dup 1))])]
+{
+  if (CONSTANT_P (operands[1]))
+    {
+      operands[3] = gen_rtx_REG (Pmode, 27);
+      emit_move_insn (operands[3], operands[1]);
+    }
+  else
+    {
+      operands[3] = operands[1];
+      operands[1] = const0_rtx;
+    }
+})
+
+(define_peephole2
+  [(parallel [(set (match_operand 0 "" "")
+                  (call (mem:DI (match_operand:DI 1 "call_operand" ""))
+                        (match_operand 2 "" "")))
+             (use (reg:DI 29))
+             (clobber (reg:DI 26))])]
+  "TARGET_EXPLICIT_RELOCS && TARGET_ABI_OSF  && reload_completed
+   && ! current_file_function_operand (operands[0], Pmode)
+   && ! peep2_regno_dead_p (1, 29)"
+  [(parallel [(set (match_dup 0)
+                  (call (mem:DI (match_dup 3))
+                        (match_dup 2)))
+             (set (reg:DI 26) (plus:DI (pc) (const_int 4)))
+             (unspec_volatile [(reg:DI 29)] UNSPECV_BLOCKAGE)
+             (use (match_dup 1))])
+   (set (reg:DI 29)
+       (unspec_volatile:DI [(reg:DI 26) (match_dup 4)] UNSPECV_LDGP1))
+   (set (reg:DI 29)
+       (unspec:DI [(reg:DI 29) (match_dup 4)] UNSPEC_LDGP2))]
+{
+  if (CONSTANT_P (operands[1]))
+    {
+      operands[3] = gen_rtx_REG (Pmode, 27);
+      emit_move_insn (operands[3], operands[1]);
+    }
+  else
+    {
+      operands[3] = operands[1];
+      operands[1] = const0_rtx;
+    }
+  operands[4] = GEN_INT (alpha_next_sequence_number++);
+})
+
+;; We add a blockage unspec_volatile to prevent insns from moving down
+;; from above the call to in between the call and the ldah gpdisp.
+(define_insn "*call_value_osf_2_er"
+  [(set (match_operand 0 "" "")
+       (call (mem:DI (match_operand:DI 1 "register_operand" "c"))
+             (match_operand 2 "" "")))
+   (set (reg:DI 26)
+       (plus:DI (pc) (const_int 4)))
+   (unspec_volatile [(reg:DI 29)] UNSPECV_BLOCKAGE)
+   (use (match_operand 3 "" ""))]
+  "TARGET_EXPLICIT_RELOCS && TARGET_ABI_OSF"
+  "jsr $26,(%1),%3"
   [(set_attr "type" "jsr")])
 
-(define_insn "*call_value_osf_1_er"
+(define_insn "*call_value_osf_1_noreturn"
   [(set (match_operand 0 "" "")
-       (call (mem:DI (match_operand:DI 1 "call_operand" "c,R,i"))
+       (call (mem:DI (match_operand:DI 1 "call_operand" "c,R,s"))
              (match_operand 2 "" "")))
-   (clobber (reg:DI 27))
+   (use (reg:DI 29))
    (clobber (reg:DI 26))]
-  "TARGET_EXPLICIT_RELOCS && TARGET_ABI_OSF"
+  "! TARGET_EXPLICIT_RELOCS && TARGET_ABI_OSF
+   && find_reg_note (insn, REG_NORETURN, NULL_RTX)"
   "@
-   jsr $26,($27),0\;ldah $29,0($26)\t\t!gpdisp!%*\;lda $29,0($29)\t\t!gpdisp!%*
+   jsr $26,($27),0
    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!%*"
+   jsr $26,%1"
   [(set_attr "type" "jsr")
-   (set_attr "length" "12,*,16")])
+   (set_attr "length" "*,*,8")])
 
 (define_insn "*call_value_osf_1"
   [(set (match_operand 0 "" "")
-       (call (mem:DI (match_operand:DI 1 "call_operand" "c,R,i"))
+       (call (mem:DI (match_operand:DI 1 "call_operand" "c,R,s"))
              (match_operand 2 "" "")))
-   (clobber (reg:DI 27))
+   (use (reg:DI 29))
    (clobber (reg:DI 26))]
-  "TARGET_ABI_OSF"
+  "! TARGET_EXPLICIT_RELOCS && TARGET_ABI_OSF"
   "@
    jsr $26,($27),0\;ldgp $29,0($26)
    bsr $26,$%1..ng
@@ -6596,14 +6805,15 @@ 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 "current_file_function_operand" "R"))
-             (match_operand 2 "" "")))]
+             (match_operand 2 "" "")))
+   (use (reg:DI 29))]
   "TARGET_ABI_OSF"
   "br $31,$%1..ng"
   [(set_attr "type" "jsr")])
 
 (define_insn "*call_value_nt_1"
   [(set (match_operand 0 "" "")
-       (call (mem:DI (match_operand:DI 1 "call_operand" "r,R,i"))
+       (call (mem:DI (match_operand:DI 1 "call_operand" "r,R,s"))
              (match_operand 2 "" "")))
    (clobber (reg:DI 26))]
   "TARGET_ABI_WINDOWS_NT"
@@ -6616,7 +6826,7 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
 
 (define_insn "*call_value_vms_1"
   [(set (match_operand 0 "" "")
-       (call (mem:DI (match_operand:DI 1 "call_operand" "r,i"))
+       (call (mem:DI (match_operand:DI 1 "call_operand" "r,s"))
              (match_operand 2 "" "")))
    (use (match_operand:DI 3 "nonimmediate_operand" "r,m"))
    (use (reg:DI 25))
@@ -6628,3 +6838,14 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
    ldq $27,%3\;jsr $26,%1\;ldq $27,0($29)"
   [(set_attr "type" "jsr")
    (set_attr "length" "12,16")])
+
+(define_insn "*call_value_umk"
+  [(set (match_operand 0 "" "")
+       (call (mem:DI (match_operand:DI 1 "call_operand" "r"))
+             (match_operand 2 "" "")))
+   (use (reg:DI 25))
+   (clobber (reg:DI 26))]
+  "TARGET_ABI_UNICOSMK"
+  "jsr $26,(%1)"
+  [(set_attr "type" "jsr")])
+