Index: gcc/config.gcc
===================================================================
--- gcc/config.gcc	(revision 212508)
+++ gcc/config.gcc	(working copy)
@@ -1129,8 +1129,7 @@ cris-*-elf | cris-*-none)
 	;;
 crisv32-*-linux* | cris-*-linux*)
 	tm_file="dbxelf.h elfos.h ${tm_file} gnu-user.h linux.h glibc-stdint.h cris/linux.h"
-	# We need to avoid using t-linux, so override default tmake_file
-	tmake_file="cris/t-cris cris/t-linux t-slibgcc t-linux"
+	tmake_file="${tmake_file} cris/t-cris cris/t-linux"
 	extra_options="${extra_options} cris/linux.opt"
 	case $target in
 	  cris-*-*)

The "actual" breakage in PR61737 is due to incorrect
PICification.  The call insns needed pic_offset_table_rtx but
didn't mention it and also middle-end was allowed to
delegitimize symbols so e.g. a call to abort lost its PICness.
Cured by somewhat extensive changes, extracted from local
changes done over the years.  (There's TLS and stack-protect
changes too but I prefer to restrict this patch this time.)

There's now ("now" that it builds, but new since about 4.7) a
complaint when building libgcc that UNSPECs that make it into the
debug info are not delegitimized.  I know what's up with that, but am
going to leave it out of this patch as the complaint is "just" a
warning.

Testing for cris-linux and crisv32-linux is limited to observing that
libgcc compiles, at least with the --disable-threads option used in
the PR.

Regtested cris-elf and crisv32-elf to avoid fallout.  Committed
separately to trunk and 4.9-branch; both branches tested as
above.  (Target maintainers of tertiary-or-lesser targets have
the option to commit non-regression changes to release branches,
but it's certainly a regression not to build and not to be able
to compile libgcc anymore.)

	PR target/61737.
	* config/cris/cris.c (TARGET_LEGITIMATE_CONSTANT_P)
	(TARGET_CANNOT_FORCE_CONST_MEM): Define.
	(cris_cannot_force_const_mem, cris_legitimate_constant_p): New
	functions.
	(cris_print_index, cris_print_operand, cris_constant_index_p)
	(cris_side_effect_mode_ok): Replace CONSTANT_P with CRIS_CONSTANT_P.
	(cris_address_cost): Ditto last CONSTANT_P.
	(cris_symbol_type_of): Rename from cris_pic_symbol_type_of.  All
        callers changed.  Yield cris_offsettable_symbol for non-PIC
        constant symbolic expressions including labels.  Yield cris_unspec
	for all unspecs.
	(cris_expand_pic_call_address): New parameter MARKERP.  Set its
        target to pic_offset_table_rtx for calls that will likely go
        through PLT, const0_rtx when they can't.  All callers changed.
	Assert flag_pic.  Use CONSTANT_P, not CONSTANT_ADDRESS_P, for
	symbolic expressions to be PICified.  Remove second, redundant,
	assert on can_create_pseudo_p returning non-zero.  Use
	replace_equiv_address_nv, not replace_equiv_address, for final
	operand update.
	* config/cris/cris.md ("movsi"): Move variable t to pattern
	toplevel. Adjust assert for new cris_symbol_type member.  Use
	CONSTANT_P instead of CONSTANT_ADDRESS_P.
	("*movsi_internal") <case 9>: Make check for valid unspec operands
	for lapc stricter.
	<case CRIS_UNSPEC_PCREL, CRIS_UNSPEC_PLT_PCREL>: Clear condition
	codes.
	("call", "call_value"): Use second incoming operand as a marker
	for pic-offset-table-register being used.
	("*expanded_call_non_v32", "*expanded_call_v32")
        ("*expanded_call_value_non_v32", "*expanded_call_value_v32"): For
	second incoming operand to CALL, match cris_call_type_marker.
	("*expanded_call_value_side"): Ditto.  Disable before
	reload_completed.
	("*expanded_call_side"): Ditto.  Fix typo in comment.
	(moverside, movemside peepholes): Check for CRIS_CONSTANT_P, not
	CONSTANT_P.
	* config/cris/predicates.md ("cris_call_type_marker"): New predicate.
	* config/cris/cris.h (CRIS_CONSTANT_P): New macro.
	(enum cris_symbol_type): Rename from cris_pic_symbol_type.  All
        users changed.  Add members cris_offsettable_symbol and
	cris_unspec.
	(cris_symbol_type): Rename from cris_pic_symbol_type.
	* config/cris/constraints.md ("T"): Use CRIS_CONSTANT_P, not
        just CONSTANT_P.
	* config/cris/cris-protos.h (cris_symbol_type_of,
	cris_expand_pic_call_address): Adjust prototypes.
	(cris_legitimate_constant_p): New prototype.

Index: gcc/config/cris/cris.md
===================================================================
--- gcc/config/cris/cris.md	(revision 212537)
+++ gcc/config/cris/cris.md	(working copy)
@@ -919,6 +919,8 @@ (define_expand "movsi"
     (match_operand:SI 1 "cris_general_operand_or_symbol" ""))]
   ""
 {
+  enum cris_symbol_type t;
+
   /* If the output goes to a MEM, make sure we have zero or a register as
      input.  */
   if (MEM_P (operands[0])
@@ -934,12 +936,12 @@ (define_expand "movsi"
      valid symbol?  Can we exclude global PIC addresses with an added
      offset?  */
     if (flag_pic
-	&& CONSTANT_ADDRESS_P (operands[1])
+	&& CONSTANT_P (operands[1])
 	&& !cris_valid_pic_const (operands[1], false))
       {
-	enum cris_pic_symbol_type t = cris_pic_symbol_type_of (operands[1]);
+	t = cris_symbol_type_of (operands[1]);
 
-	gcc_assert (t != cris_no_symbol);
+	gcc_assert (t != cris_no_symbol && t != cris_offsettable_symbol);
 
 	if (! REG_S_P (operands[0]))
 	  {
@@ -1086,7 +1088,12 @@ (define_insn "*movsi_internal"
 	 if (!flag_pic
 	     && (GET_CODE (operands[1]) == SYMBOL_REF
 		 || GET_CODE (operands[1]) == LABEL_REF
-		 || GET_CODE (operands[1]) == CONST))
+		 || (GET_CODE (operands[1]) == CONST
+		     && (GET_CODE (XEXP (operands[1], 0)) != UNSPEC
+			 || (XINT (XEXP (operands[1], 0), 1)
+			     == CRIS_UNSPEC_PLT_PCREL)
+			 || (XINT (XEXP (operands[1], 0), 1)
+			     == CRIS_UNSPEC_PCREL)))))
 	   {
 	     /* FIXME: Express this through (set_attr cc none) instead,
 		since we can't express the ``none'' at this point.  FIXME:
@@ -1169,6 +1176,12 @@ (define_insn "*movsi_internal"
 	  case CRIS_UNSPEC_PCREL:
 	  case CRIS_UNSPEC_PLT_PCREL:
 	    gcc_assert (TARGET_V32);
+	    /* LAPC doesn't set condition codes; clear them to make the
+	       (equivalence-marked) result of this insn not presumed
+	       present.  This instruction can be a PIC symbol load (for
+	       a hidden symbol) which for weak symbols will be followed
+	       by a test for NULL.  */
+	    CC_STATUS_INIT;
 	    return "lapc %1,%0";
 
 	  default:
@@ -3710,15 +3723,16 @@ (define_expand "call"
 {
   gcc_assert (MEM_P (operands[0]));
   if (flag_pic)
-    cris_expand_pic_call_address (&operands[0]);
+    cris_expand_pic_call_address (&operands[0], &operands[1]);
+  else
+    operands[1] = const0_rtx;
 })
 
-;; Accept *anything* as operand 1.  Accept operands for operand 0 in
-;; order of preference.
+;; Accept operands for operand 0 in order of preference.
 
 (define_insn "*expanded_call_non_v32"
   [(call (mem:QI (match_operand:SI 0 "general_operand" "r,Q>,g"))
-	 (match_operand 1 "" ""))
+	 (match_operand:SI 1 "cris_call_type_marker" "rM,rM,rM"))
    (clobber (reg:SI CRIS_SRP_REGNUM))]
   "!TARGET_V32"
   "jsr %0")
@@ -3727,7 +3741,7 @@ (define_insn "*expanded_call_v32"
   [(call
     (mem:QI
      (match_operand:SI 0 "cris_nonmemory_operand_or_callable_symbol" "n,r,U,i"))
-    (match_operand 1 "" ""))
+    (match_operand:SI 1 "cris_call_type_marker" "rM,rM,rM,rM"))
    (clobber (reg:SI CRIS_SRP_REGNUM))]
   "TARGET_V32"
   "@
@@ -3740,19 +3754,21 @@ (define_insn "*expanded_call_v32"
 ;; Parallel when calculating and reusing address of indirect pointer
 ;; with simple offset.  (Makes most sense with PIC.)  It looks a bit
 ;; wrong not to have the clobber last, but that's the way combine
-;; generates it (except it doesn' look into the *inner* mem, so this
+;; generates it (except it doesn't look into the *inner* mem, so this
 ;; just matches a peephole2).  FIXME: investigate that.
 (define_insn "*expanded_call_side"
   [(call (mem:QI
 	  (mem:SI
 	   (plus:SI (match_operand:SI 0 "cris_bdap_operand" "%r,  r,r")
 		    (match_operand:SI 1 "cris_bdap_operand" "r>Rn,r,>Rn"))))
-	 (match_operand 2 "" ""))
+	 (match_operand:SI 2 "cris_call_type_marker" "rM,rM,rM"))
    (clobber (reg:SI CRIS_SRP_REGNUM))
    (set (match_operand:SI 3 "register_operand" "=*0,r,r")
 	(plus:SI (match_dup 0)
 		 (match_dup 1)))]
-  "!TARGET_AVOID_GOTPLT && !TARGET_V32"
+  ;; Disabled until after reload until we can avoid an output reload for
+  ;; operand 3 (being forbidden for call insns).
+  "reload_completed && !TARGET_AVOID_GOTPLT && !TARGET_V32"
   "jsr [%3=%0%S1]")
 
 (define_expand "call_value"
@@ -3764,10 +3780,12 @@ (define_expand "call_value"
 {
   gcc_assert (MEM_P (operands[1]));
   if (flag_pic)
-    cris_expand_pic_call_address (&operands[1]);
+    cris_expand_pic_call_address (&operands[1], &operands[2]);
+  else
+    operands[2] = const0_rtx;
 })
 
-;; Accept *anything* as operand 2.  The validity other than "general" of
+;; The validity other than "general" of
 ;; operand 0 will be checked elsewhere.  Accept operands for operand 1 in
 ;; order of preference (Q includes r, but r is shorter, faster).
 ;;  We also accept a PLT symbol.  We output it as [rPIC+sym:GOTPLT] rather
@@ -3776,7 +3794,7 @@ (define_expand "call_value"
 (define_insn "*expanded_call_value_non_v32"
   [(set (match_operand 0 "nonimmediate_operand" "=g,g,g")
 	(call (mem:QI (match_operand:SI 1 "general_operand" "r,Q>,g"))
-	      (match_operand 2 "" "")))
+	      (match_operand:SI 2 "cris_call_type_marker" "rM,rM,rM")))
    (clobber (reg:SI CRIS_SRP_REGNUM))]
   "!TARGET_V32"
   "Jsr %1"
@@ -3790,12 +3808,14 @@ (define_insn "*expanded_call_value_side"
 	  (mem:SI
 	   (plus:SI (match_operand:SI 1 "cris_bdap_operand" "%r,  r,r")
 		    (match_operand:SI 2 "cris_bdap_operand" "r>Rn,r,>Rn"))))
-	      (match_operand 3 "" "")))
+	 (match_operand:SI 3 "cris_call_type_marker" "rM,rM,rM")))
    (clobber (reg:SI CRIS_SRP_REGNUM))
    (set (match_operand:SI 4 "register_operand" "=*1,r,r")
 	(plus:SI (match_dup 1)
 		 (match_dup 2)))]
-  "!TARGET_AVOID_GOTPLT && !TARGET_V32"
+  ;; Disabled until after reload until we can avoid an output reload for
+  ;; operand 4 (being forbidden for call insns).
+  "reload_completed && !TARGET_AVOID_GOTPLT && !TARGET_V32"
   "Jsr [%4=%1%S2]"
   [(set_attr "cc" "clobber")])
 
@@ -3805,7 +3825,7 @@ (define_insn "*expanded_call_value_v32"
     (call
      (mem:QI
       (match_operand:SI 1 "cris_nonmemory_operand_or_callable_symbol" "n,r,U,i"))
-     (match_operand 2 "" "")))
+     (match_operand:SI 2 "cris_call_type_marker" "rM,rM,rM,rM")))
    (clobber (reg:SI 16))]
   "TARGET_V32"
   "@
@@ -4827,7 +4847,7 @@ (define_peephole2 ; moverside (peephole 
   /* Make sure we have canonical RTX so we match the insn pattern -
      not a constant in the first operand.  We also require the order
      (plus reg mem) to match the final pattern.  */
-  if (CONSTANT_P (otherop) || MEM_P (otherop))
+  if (CRIS_CONSTANT_P (otherop) || MEM_P (otherop))
     {
       operands[7] = operands[1];
       operands[8] = otherop;
@@ -4878,7 +4898,7 @@ (define_peephole2 ; movemside (peephole 
   /* Make sure we have canonical RTX so we match the insn pattern -
      not a constant in the first operand.  We also require the order
      (plus reg mem) to match the final pattern.  */
-  if (CONSTANT_P (otherop) || MEM_P (otherop))
+  if (CRIS_CONSTANT_P (otherop) || MEM_P (otherop))
     {
       operands[7] = operands[1];
       operands[8] = otherop;
Index: gcc/config/cris/cris.c
===================================================================
--- gcc/config/cris/cris.c	(revision 212537)
+++ gcc/config/cris/cris.c	(working copy)
@@ -147,6 +147,7 @@ static rtx cris_function_incoming_arg (c
 static void cris_function_arg_advance (cumulative_args_t, enum machine_mode,
 				       const_tree, bool);
 static tree cris_md_asm_clobbers (tree, tree, tree);
+static bool cris_cannot_force_const_mem (enum machine_mode, rtx);
 
 static void cris_option_override (void);
 
@@ -214,6 +215,9 @@ int cris_cpu_version = CRIS_DEFAULT_CPU_
 #undef TARGET_LEGITIMATE_ADDRESS_P
 #define TARGET_LEGITIMATE_ADDRESS_P cris_legitimate_address_p
 
+#undef TARGET_LEGITIMATE_CONSTANT_P
+#define TARGET_LEGITIMATE_CONSTANT_P cris_legitimate_constant_p
+
 #undef TARGET_PREFERRED_RELOAD_CLASS
 #define TARGET_PREFERRED_RELOAD_CLASS cris_preferred_reload_class
 
@@ -248,6 +252,10 @@ int cris_cpu_version = CRIS_DEFAULT_CPU_
 #define TARGET_FUNCTION_ARG_ADVANCE cris_function_arg_advance
 #undef TARGET_MD_ASM_CLOBBERS
 #define TARGET_MD_ASM_CLOBBERS cris_md_asm_clobbers
+
+#undef TARGET_CANNOT_FORCE_CONST_MEM
+#define TARGET_CANNOT_FORCE_CONST_MEM cris_cannot_force_const_mem
+
 #undef TARGET_FRAME_POINTER_REQUIRED
 #define TARGET_FRAME_POINTER_REQUIRED cris_frame_pointer_required
 
@@ -506,6 +514,21 @@ cris_cfun_uses_pic_table (void)
   return crtl->uses_pic_offset_table;
 }
 
+/* Worker function for TARGET_CANNOT_FORCE_CONST_MEM.
+   We can't put PIC addresses in the constant pool, not even the ones that
+   can be reached as pc-relative as we can't tell when or how to do that.  */
+
+static bool
+cris_cannot_force_const_mem (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x)
+{
+  enum cris_symbol_type t = cris_symbol_type_of (x);
+
+  return
+    t == cris_unspec
+    || t == cris_got_symbol
+    || t == cris_rel_symbol;
+}
+
 /* Given an rtx, return the text string corresponding to the CODE of X.
    Intended for use in the assembly language output section of a
    define_insn.  */
@@ -601,7 +624,7 @@ cris_print_index (rtx index, FILE *file)
 
   if (REG_P (index))
     fprintf (file, "$%s.b", reg_names[REGNO (index)]);
-  else if (CONSTANT_P (index))
+  else if (CRIS_CONSTANT_P (index))
     cris_output_addr_const (file, index);
   else if (GET_CODE (index) == MULT)
     {
@@ -1041,7 +1064,7 @@ cris_print_operand (FILE *file, rtx x, i
       /* If this is a GOT symbol, force it to be emitted as :GOT and
 	 :GOTPLT regardless of -fpic (i.e. not as :GOT16, :GOTPLT16).
 	 Avoid making this too much of a special case.  */
-      if (flag_pic == 1 && CONSTANT_P (operand))
+      if (flag_pic == 1 && CRIS_CONSTANT_P (operand))
 	{
 	  int flag_pic_save = flag_pic;
 
@@ -1161,7 +1184,7 @@ cris_print_operand (FILE *file, rtx x, i
     default:
       /* No need to handle all strange variants, let output_addr_const
 	 do it for us.  */
-      if (CONSTANT_P (operand))
+      if (CRIS_CONSTANT_P (operand))
 	{
 	  cris_output_addr_const (file, operand);
 	  return;
@@ -1358,7 +1381,7 @@ reg_ok_for_index_p (const_rtx x, bool st
 bool
 cris_constant_index_p (const_rtx x)
 {
-  return (CONSTANT_P (x) && (!flag_pic || cris_valid_pic_const (x, true)));
+  return (CRIS_CONSTANT_P (x) && (!flag_pic || cris_valid_pic_const (x, true)));
 }
 
 /* True if X is a valid base register.  */
@@ -1467,6 +1490,29 @@ cris_legitimate_address_p (enum machine_
   return false;
 }
 
+/* Worker function for TARGET_LEGITIMATE_CONSTANT_P.  We have to handle
+   PIC constants that aren't legitimized.  FIXME: there used to be a
+   guarantee that the target LEGITIMATE_CONSTANT_P didn't have to handle
+   PIC constants, but no more (4.7 era); testcase: glibc init-first.c.
+   While that may be seen as a bug, that guarantee seems a wart by design,
+   so don't bother; fix the documentation instead.  */
+
+bool
+cris_legitimate_constant_p (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x)
+{
+  enum cris_symbol_type t;
+
+  if (flag_pic)
+    return LEGITIMATE_PIC_OPERAND_P (x);
+
+  t = cris_symbol_type_of (x);
+
+  return
+    t == cris_no_symbol
+    || t == cris_offsettable_symbol
+    || t == cris_unspec;
+}
+
 /* Worker function for LEGITIMIZE_RELOAD_ADDRESS.  */
 
 bool
@@ -2214,7 +2260,7 @@ cris_address_cost (rtx x, enum machine_m
 	return (2 + 2) / 2;
 
       /* A BDAP with some other constant is 2 bytes extra.  */
-      if (CONSTANT_P (tem2))
+      if (CRIS_CONSTANT_P (tem2))
 	return (2 + 2 + 2) / 2;
 
       /* BDAP with something indirect should have a higher cost than
@@ -2312,7 +2358,7 @@ cris_side_effect_mode_ok (enum rtx_code 
 	return 0;
 
       /* Check allowed cases, like [r(+)?].[bwd] and const.  */
-      if (CONSTANT_P (val_rtx))
+      if (CRIS_CONSTANT_P (val_rtx))
 	return 1;
 
       if (MEM_P (val_rtx)
@@ -2464,32 +2510,34 @@ cris_valid_pic_const (const_rtx x, bool 
 	gcc_unreachable ();
       }
 
-  return cris_pic_symbol_type_of (x) == cris_no_symbol;
+  return cris_symbol_type_of (x) == cris_no_symbol;
 }
 
-/* Helper function to find the right PIC-type symbol to generate,
+/* Helper function to find the right symbol-type to generate,
    given the original (non-PIC) representation.  */
 
-enum cris_pic_symbol_type
-cris_pic_symbol_type_of (const_rtx x)
+enum cris_symbol_type
+cris_symbol_type_of (const_rtx x)
 {
   switch (GET_CODE (x))
     {
     case SYMBOL_REF:
-      return SYMBOL_REF_LOCAL_P (x)
-	? cris_rel_symbol : cris_got_symbol;
+      return flag_pic
+	? (SYMBOL_REF_LOCAL_P (x)
+	   ? cris_rel_symbol : cris_got_symbol)
+	: cris_offsettable_symbol;
 
     case LABEL_REF:
-      return cris_rel_symbol;
+      return flag_pic ? cris_rel_symbol : cris_offsettable_symbol;
 
     case CONST:
-      return cris_pic_symbol_type_of (XEXP (x, 0));
+      return cris_symbol_type_of (XEXP (x, 0));
 
     case PLUS:
     case MINUS:
       {
-	enum cris_pic_symbol_type t1 = cris_pic_symbol_type_of (XEXP (x, 0));
-	enum cris_pic_symbol_type t2 = cris_pic_symbol_type_of (XEXP (x, 1));
+	enum cris_symbol_type t1 = cris_symbol_type_of (XEXP (x, 0));
+	enum cris_symbol_type t2 = cris_symbol_type_of (XEXP (x, 1));
 
 	gcc_assert (t1 == cris_no_symbol || t2 == cris_no_symbol);
 
@@ -2504,9 +2552,7 @@ cris_pic_symbol_type_of (const_rtx x)
       return cris_no_symbol;
 
     case UNSPEC:
-      /* Likely an offsettability-test attempting to add a constant to
-	 a GOTREAD symbol, which can't be handled.  */
-      return cris_invalid_pic_symbol;
+      return cris_unspec;
 
     default:
       fatal_insn ("unrecognized supposed constant", x);
@@ -3714,19 +3760,19 @@ cris_emit_movem_store (rtx dest, rtx nre
 /* Worker function for expanding the address for PIC function calls.  */
 
 void
-cris_expand_pic_call_address (rtx *opp)
+cris_expand_pic_call_address (rtx *opp, rtx *markerp)
 {
   rtx op = *opp;
 
-  gcc_assert (MEM_P (op));
+  gcc_assert (flag_pic && MEM_P (op));
   op = XEXP (op, 0);
 
   /* It might be that code can be generated that jumps to 0 (or to a
      specific address).  Don't die on that.  (There is a
      testcase.)  */
-  if (CONSTANT_ADDRESS_P (op) && !CONST_INT_P (op))
+  if (CONSTANT_P (op) && !CONST_INT_P (op))
     {
-      enum cris_pic_symbol_type t = cris_pic_symbol_type_of (op);
+      enum cris_symbol_type t = cris_symbol_type_of (op);
 
       CRIS_ASSERT (can_create_pseudo_p ());
 
@@ -3752,18 +3798,21 @@ cris_expand_pic_call_address (rtx *opp)
 	    }
 	  else
 	    op = force_reg (Pmode, op);
+
+	  /* A local call.  */
+	  *markerp = const0_rtx;
 	}
       else if (t == cris_got_symbol)
 	{
 	  if (TARGET_AVOID_GOTPLT)
 	    {
 	      /* Change a "jsr sym" into (allocate register rM, rO)
-		 "move.d (const (unspec [sym rPIC] CRIS_UNSPEC_PLT_GOTREL)),rM"
+		 "move.d (const (unspec [sym] CRIS_UNSPEC_PLT_GOTREL)),rM"
 		 "add.d rPIC,rM,rO", "jsr rO" for pre-v32 and
-		 "jsr (const (unspec [sym rPIC] CRIS_UNSPEC_PLT_PCREL))"
+		 "jsr (const (unspec [sym] CRIS_UNSPEC_PLT_PCREL))"
 		 for v32.  */
 	      rtx tem, rm, ro;
-	      gcc_assert (can_create_pseudo_p ());
+
 	      crtl->uses_pic_offset_table = 1;
 	      tem = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, op),
 				    TARGET_V32
@@ -3817,14 +3866,27 @@ cris_expand_pic_call_address (rtx *opp)
 	      MEM_NOTRAP_P (mem) = 1;
 	      op = mem;
 	    }
+
+	  /* We need to prepare this call to go through the PLT; we
+	     need to make GOT available.  */
+	  *markerp = pic_offset_table_rtx;
 	}
       else
-	/* Can't possibly get a GOT-needing-fixup for a function-call,
-	   right?  */
+	/* Can't possibly get anything else for a function-call, right?  */
 	fatal_insn ("unidentifiable call op", op);
 
-      *opp = replace_equiv_address (*opp, op);
+      /* If the validizing variant is called, it will try to validize
+	 the address as a valid any-operand constant, but as it's only
+	 valid for calls and moves, it will fail and always be forced
+	 into a register.  */
+      *opp = replace_equiv_address_nv (*opp, op);
     }
+  else
+    /* Can't tell what locality a call to a non-constant address has;
+       better make the GOT register alive at it.
+       FIXME: Can we see whether the register has known constant
+       contents?  */
+    *markerp = pic_offset_table_rtx;
 }
 
 /* Make sure operands are in the right order for an addsi3 insn as
Index: gcc/config/cris/predicates.md
===================================================================
--- gcc/config/cris/predicates.md	(revision 212537)
+++ gcc/config/cris/predicates.md	(working copy)
@@ -142,7 +142,7 @@ (define_special_predicate "cris_general_
   (ior (match_operand 0 "general_operand")
        (and (match_code "const, symbol_ref, label_ref")
        	    ; The following test is actually just an assertion.
-	    (match_test "cris_pic_symbol_type_of (op) != cris_no_symbol"))))
+	    (match_test "cris_symbol_type_of (op) != cris_no_symbol"))))
 
 ;; A predicate for the anon movsi expansion, one that fits a PCREL
 ;; operand as well as general_operand.
@@ -176,3 +176,15 @@ (define_predicate "cris_mem_call_operand
        (ior (match_operand 0 "memory_operand")
 	    (match_test "cris_general_operand_or_symbol (XEXP (op, 0),
 							 Pmode)"))))
+
+;; A marker for the call-insn: (const_int 0) for a call to a
+;; hidden or static function and non-pic and
+;; pic_offset_table_rtx for a call that *might* go through the
+;; PLT.
+
+(define_predicate "cris_call_type_marker"
+  (ior (and (match_operand 0 "const_int_operand")
+	    (match_test "op == const0_rtx"))
+       (and (and (match_operand 0 "register_operand")
+		 (match_test "op == pic_offset_table_rtx"))
+	    (match_test "flag_pic != 0"))))
Index: gcc/config/cris/cris.h
===================================================================
--- gcc/config/cris/cris.h	(revision 212537)
+++ gcc/config/cris/cris.h	(working copy)
@@ -794,6 +794,12 @@ struct cum_args {int regs;};
     }									\
   while (0)
 
+/* The mode argument to cris_legitimate_constant_p isn't used, so just
+   pass a cheap dummy.  N.B. we have to cast away const from the
+   parameter rather than adjust the parameter, as it's type is mandated
+   by the TARGET_LEGITIMATE_CONSTANT_P target hook interface.  */
+#define CRIS_CONSTANT_P(X) \
+  (CONSTANT_P (X) && cris_legitimate_constant_p (VOIDmode, CONST_CAST_RTX (X)))
 
 /* Node: Condition Code */
 
@@ -833,13 +839,14 @@ struct cum_args {int regs;};
 
 /* Helper type.  */
 
-enum cris_pic_symbol_type
+enum cris_symbol_type
   {
     cris_no_symbol = 0,
     cris_got_symbol = 1,
     cris_rel_symbol = 2,
     cris_got_symbol_needing_fixup = 3,
-    cris_invalid_pic_symbol = 4
+    cris_unspec = 7,
+    cris_offsettable_symbol = 8
   };
 
 #define PIC_OFFSET_TABLE_REGNUM (flag_pic ? CRIS_GOT_REGNUM : INVALID_REGNUM)
Index: gcc/config/cris/constraints.md
===================================================================
--- gcc/config/cris/constraints.md	(revision 212537)
+++ gcc/config/cris/constraints.md	(working copy)
@@ -118,7 +118,7 @@ (define_constraint "T"
 						       reload_in_progress
 						       || reload_completed)"))
 	    ;; Just an explicit indirect reference: [const]?
-	    (match_test "CONSTANT_P (XEXP (op, 0))")
+	    (match_test "CRIS_CONSTANT_P (XEXP (op, 0))")
 	    ;; Something that is indexed; [...+...]?
 	    (and (match_code "plus" "0")
 		      ;; A BDAP constant: [reg+(8|16|32)bit offset]?
@@ -159,6 +159,8 @@ (define_constraint "S"
 (define_constraint "U"
   "@internal"
   (and (match_test "flag_pic")
+       ;; We're just interested in the ..._or_callable_symbol part.
+       ;; (Using CRIS_CONSTANT_P would exclude that too.)
        (match_test "CONSTANT_P (op)")
        (match_operand 0 "cris_nonmemory_operand_or_callable_symbol")))
 
Index: gcc/config/cris/cris-protos.h
===================================================================
--- gcc/config/cris/cris-protos.h	(revision 212537)
+++ gcc/config/cris/cris-protos.h	(working copy)
@@ -31,8 +31,9 @@ extern bool cris_cc0_user_requires_cmp (
 extern rtx cris_return_addr_rtx (int, rtx);
 extern rtx cris_split_movdx (rtx *);
 extern int cris_legitimate_pic_operand (rtx);
-extern enum cris_pic_symbol_type cris_pic_symbol_type_of (const_rtx);
+extern enum cris_symbol_type cris_symbol_type_of (const_rtx);
 extern bool cris_valid_pic_const (const_rtx, bool);
+extern bool cris_legitimate_constant_p (enum machine_mode, rtx);
 extern bool cris_constant_index_p (const_rtx);
 extern bool cris_base_p (const_rtx, bool);
 extern bool cris_base_or_autoincr_p (const_rtx, bool);
@@ -46,7 +47,7 @@ extern int cris_cfun_uses_pic_table (voi
 extern void cris_asm_output_case_end (FILE *, int, rtx);
 extern rtx cris_gen_movem_load (rtx, rtx, int);
 extern rtx cris_emit_movem_store (rtx, rtx, int, bool);
-extern void cris_expand_pic_call_address (rtx *);
+extern void cris_expand_pic_call_address (rtx *, rtx *);
 extern void cris_order_for_addsi3 (rtx *, int);
 extern void cris_emit_trap_for_misalignment (rtx);
 #endif /* RTX_CODE */
