diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 3a8ef09f41e095317d668e3feecb635d32172942..845748b2ac8de12f93269a6433f3a5651bd8bf82 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,10 @@
+2005-02-07  Alexandre Oliva  <aoliva@redhat.com>
+
+	* config/frv/frv.md ("tls_indirect_call"): Turn into libcall-like
+	expand.
+	("*tls_indirect_call"): New, reference hard regs directly.
+	* config/frv/frv.c (gen_inlined_tls_plt): Adjust.
+
 2005-02-07  Ralf Corsepius  <ralf.corsepius@rtems.org>
 
 	* config/arm/rtems-elf.h (SUBTARGET_EXTRA_ASM_SPEC): 
diff --git a/gcc/config/frv/frv.c b/gcc/config/frv/frv.c
index 833ccee686a62d67aa4260fffa9cca87c3dcdadc..c45145864aa511f32da34651c3f468dc5ba1729e 100644
--- a/gcc/config/frv/frv.c
+++ b/gcc/config/frv/frv.c
@@ -3481,8 +3481,7 @@ gen_inlined_tls_plt (rtx addr)
     }
 
   retval = gen_reg_rtx (Pmode);
-  emit_insn (gen_tls_indirect_call (retval, addr, dest, gen_reg_rtx (Pmode),
-				    picreg));
+  emit_insn (gen_tls_indirect_call (retval, addr, dest, picreg));
   return retval;
 }
 
diff --git a/gcc/config/frv/frv.md b/gcc/config/frv/frv.md
index 94520ef46a9432b9e5343eabb852e7333874a7e2..4515c0b44dd89af37d91ca1c5591c7a63b3e9c7d 100644
--- a/gcc/config/frv/frv.md
+++ b/gcc/config/frv/frv.md
@@ -8203,25 +8203,42 @@
   [(set_attr "length" "4")
    (set_attr "type" "load_or_call")])
 
-;; Reads GR8 and GR9.
-;; Clobbers GR8.
-;; Modifies GR9.
-(define_insn "tls_indirect_call"
-  [(set (match_operand:SI 0 "register_operand" "=D09")
+;; We have to expand this like a libcall (it sort of actually is)
+;; because otherwise sched may move, for example, an insn that sets up
+;; GR8 for a subsequence call before the *tls_indirect_call insn, and
+;; then reload won't be able to fix things up.
+(define_expand "tls_indirect_call"
+  [(set (reg:DI GR8_REG)
+	(match_operand:DI 2 "register_operand" ""))
+   (parallel
+    [(set (reg:SI GR9_REG)
+	  (unspec:SI
+	   [(match_operand:SI 1 "symbolic_operand" "")
+	   (reg:DI GR8_REG)]
+	   UNSPEC_TLS_INDIRECT_CALL))
+    (clobber (reg:SI GR8_REG))
+    (clobber (reg:SI LRREG))
+    (use (match_operand:SI 3 "register_operand" ""))])
+   (set (match_operand:SI 0 "register_operand" "")
+	(reg:SI GR9_REG))]
+  "HAVE_AS_TLS")
+
+(define_insn "*tls_indirect_call"
+  [(set (reg:SI GR9_REG)
 	(unspec:SI
-	 [(match_operand:SI 1 "symbolic_operand" "")
-	  (match_operand:DI 2 "register_operand" "D89")]
+	 [(match_operand:SI 0 "symbolic_operand" "")
+	  (reg:DI GR8_REG)]
 	 UNSPEC_TLS_INDIRECT_CALL))
-   (clobber (match_operand:SI 3 "register_operand" "=D08"))
+   (clobber (reg:SI GR8_REG))
    (clobber (reg:SI LRREG))
    ;; If there was a way to represent the fact that we don't need GR9
    ;; or GR15 to be set before this instruction (it could be in
    ;; parallel), we could use it here.  This change wouldn't apply to
    ;; call_gettlsoff, thought, since the linker may turn the latter
    ;; into ldi @(gr15,offset),gr9.
-   (use (match_operand:SI 4 "register_operand" "D15"))]
+   (use (match_operand:SI 1 "register_operand" "D15"))]
   "HAVE_AS_TLS"
-  "calll #gettlsoff(%a1)@(%2,gr0)"
+  "calll #gettlsoff(%a0)@(gr8,gr0)"
   [(set_attr "length" "4")
    (set_attr "type" "jumpl")])