+2007-09-07 Richard Sandiford <richard@codesourcery.com>
+
+ * config/mips/mips.c (build_mips16_call_stub): Emit all direct
+ float calls here, rather than leaving some to the caller.
+ Use call_internal_direct and call_value_internal_direct.
+ * config/mips/mips.md (call_internal_direct): New pattern.
+ (call_value_internal_direct): Likewise.
+
2007-09-07 Richard Sandiford <richard@codesourcery.com>
* config/mips/mips.c (mips_base_move_loop_invariants): New variable.
tree stubid, stubdecl;
int need_comma;
unsigned int f;
+ rtx insn;
/* We don't need to do anything if we aren't in mips16 mode, or if
we were invoked with the -msoft-float option. */
if (fpret && ! l->fpret)
error ("cannot handle inconsistent calls to %qs", fnname);
+ if (retval == NULL_RTX)
+ insn = gen_call_internal_direct (fn, arg_size);
+ else
+ insn = gen_call_value_internal_direct (retval, fn, arg_size);
+ insn = emit_call_insn (insn);
+
/* If we are calling a stub which handles a floating point return
value, we need to arrange to save $18 in the prologue. We do
this by marking the function call as using the register. The
prologue will later see that it is used, and emit code to save
it. */
-
if (l->fpret)
- {
- rtx insn;
+ CALL_INSN_FUNCTION_USAGE (insn) =
+ gen_rtx_EXPR_LIST (VOIDmode,
+ gen_rtx_USE (VOIDmode, gen_rtx_REG (word_mode, 18)),
+ CALL_INSN_FUNCTION_USAGE (insn));
- if (retval == NULL_RTX)
- insn = gen_call_internal (fn, arg_size);
- else
- insn = gen_call_value_internal (retval, fn, arg_size);
- insn = emit_call_insn (insn);
-
- CALL_INSN_FUNCTION_USAGE (insn) =
- gen_rtx_EXPR_LIST (VOIDmode,
- gen_rtx_USE (VOIDmode, gen_rtx_REG (word_mode, 18)),
- CALL_INSN_FUNCTION_USAGE (insn));
-
- /* Return 1 to tell the caller that we've generated the call
- insn. */
- return 1;
- }
-
- /* Return 0 to let the caller generate the call insn. */
- return 0;
+ /* Return 1 to tell the caller that we've generated the call
+ insn. */
+ return 1;
}
/* An entry in the mips16 constant pool. VALUE is the pool constant,
[(set_attr "jal" "indirect,direct")
(set_attr "extended_mips16" "no,yes")])
+;; A pattern for calls that must be made directly. It is used for
+;; MIPS16 calls that the linker may need to redirect to a hard-float
+;; stub; the linker relies on the call relocation type to detect when
+;; such redirection is needed.
+(define_insn "call_internal_direct"
+ [(call (mem:SI (match_operand 0 "const_call_insn_operand"))
+ (match_operand 1))
+ (const_int 1)
+ (clobber (reg:SI 31))]
+ ""
+ { return MIPS_CALL ("jal", operands, 0); })
+
(define_insn "call_split"
[(call (mem:SI (match_operand 0 "call_insn_operand" "cS"))
(match_operand 1 "" ""))
{ return MIPS_CALL ("jal", operands, 1); }
[(set_attr "type" "call")])
+;; See call_internal_direct.
+(define_insn "call_value_internal_direct"
+ [(set (match_operand 0 "register_operand")
+ (call (mem:SI (match_operand 1 "const_call_insn_operand"))
+ (match_operand 2)))
+ (const_int 1)
+ (clobber (reg:SI 31))]
+ ""
+ { return MIPS_CALL ("jal", operands, 1); })
+
;; See comment for call_internal.
(define_insn_and_split "call_value_multiple_internal"
[(set (match_operand 0 "register_operand" "")