/* Subroutines for insn-output.c for NEC V850 series
- Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
Contributed by Jeff Law (law@cygnus.com).
This file is part of GNU CC.
be popping more registers than is strictly necessary, but
it does save code space. */
- if (first == last)
- sprintf (buff, "jr __return_%s", reg_names [first]);
+ if (TARGET_LONG_CALLS)
+ {
+ char name[40];
+
+ if (first == last)
+ sprintf (name, "__return_%s", reg_names [first]);
+ else
+ sprintf (name, "__return_%s_%s", reg_names [first], reg_names [last]);
+
+ sprintf (buff, "movhi hi(%s), r0, r6\n\tmovea lo(%s), r6, r6\n\tjmp r6",
+ name, name);
+ }
else
- sprintf (buff, "jr __return_%s_%s", reg_names [first], reg_names [last]);
-
+ {
+ if (first == last)
+ sprintf (buff, "jr __return_%s", reg_names [first]);
+ else
+ sprintf (buff, "jr __return_%s_%s", reg_names [first], reg_names [last]);
+ }
+
return buff;
}
be pushing more registers than is strictly necessary, but
it does save code space. */
- if (first == last)
- sprintf (buff, "jarl __save_%s, r10", reg_names [first]);
+ if (TARGET_LONG_CALLS)
+ {
+ char name[40];
+
+ if (first == last)
+ sprintf (name, "__save_%s", reg_names [first]);
+ else
+ sprintf (name, "__save_%s_%s", reg_names [first], reg_names [last]);
+
+ sprintf (buff, "movhi hi(%s), r0, r11\n\tmovea lo(%s), r11, r11\n\tjarl .+4, r10\n\tadd 4, r10\n\tjmp r11",
+ name, name);
+ }
else
- sprintf (buff, "jarl __save_%s_%s, r10", reg_names [first],
- reg_names [last]);
+ {
+ if (first == last)
+ sprintf (buff, "jarl __save_%s, r10", reg_names [first]);
+ else
+ sprintf (buff, "jarl __save_%s_%s, r10", reg_names [first],
+ reg_names [last]);
+ }
return buff;
}
;; GCC machine description for NEC V850
-;; Copyright (C) 1996, 1997 Free Software Foundation, Inc.
+;; Copyright (C) 1996, 1997, 1999 Free Software Foundation, Inc.
;; Contributed by Jeff Law (law@cygnus.com).
(define_attr "length" ""
(const_int 200))
+(define_attr "long_calls" "yes,no"
+ (const (if_then_else (symbol_ref "TARGET_LONG_CALLS")
+ (const_string "yes")
+ (const_string "no"))))
+
;; Types of instructions (for scheduling purposes).
(define_attr "type" "load,mult,other"
if (! call_address_operand (XEXP (operands[0], 0))
|| TARGET_LONG_CALLS)
XEXP (operands[0], 0) = force_reg (SImode, XEXP (operands[0], 0));
- emit_call_insn (gen_call_internal (XEXP (operands[0], 0), operands[1]));
+ if (TARGET_LONG_CALLS)
+ emit_call_insn (gen_call_internal_long (XEXP (operands[0], 0), operands[1]));
+ else
+ emit_call_insn (gen_call_internal_short (XEXP (operands[0], 0), operands[1]));
+
DONE;
}")
-(define_insn "call_internal"
+(define_insn "call_internal_short"
[(call (mem:QI (match_operand:SI 0 "call_address_operand" "S,r"))
(match_operand:SI 1 "general_operand" "g,g"))
(clobber (reg:SI 31))]
- ""
+ "! TARGET_LONG_CALLS"
"@
jarl %0,r31
jarl .+4,r31\\n\\tadd 4,r31\\n\\tjmp %0"
- [(set_attr "length" "4,8")])
+ [(set_attr "length" "4,8")]
+)
+
+(define_insn "call_internal_long"
+ [(call (mem:QI (match_operand:SI 0 "call_address_operand" "S,r"))
+ (match_operand:SI 1 "general_operand" "g,g"))
+ (clobber (reg:SI 31))]
+ "TARGET_LONG_CALLS"
+ "*
+ {
+ if (which_alternative == 0)
+ {
+ if (GET_CODE (operands[0]) == REG)
+ return \"jarl %0,r31\";
+ else
+ return \"movhi hi(%0), r0, r11\\n\\tmovea lo(%0), r11, r11\\n\\tjarl .+4,r31\\n\\tadd 4, r31\\n\\tjmp r11\";
+ }
+ else
+ return \"jarl .+4,r31\\n\\tadd 4,r31\\n\\tjmp %0\";
+ }"
+ [(set_attr "length" "16,8")]
+)
;; Call subroutine, returning value in operand 0
;; (which must be a hard register).
if (! call_address_operand (XEXP (operands[1], 0))
|| TARGET_LONG_CALLS)
XEXP (operands[1], 0) = force_reg (SImode, XEXP (operands[1], 0));
- emit_call_insn (gen_call_value_internal (operands[0],
- XEXP (operands[1], 0),
- operands[2]));
+ if (TARGET_LONG_CALLS)
+ emit_call_insn (gen_call_value_internal_long (operands[0],
+ XEXP (operands[1], 0),
+ operands[2]));
+ else
+ emit_call_insn (gen_call_value_internal_short (operands[0],
+ XEXP (operands[1], 0),
+ operands[2]));
DONE;
}")
-(define_insn "call_value_internal"
+(define_insn "call_value_internal_short"
[(set (match_operand 0 "" "=r,r")
(call (mem:QI (match_operand:SI 1 "call_address_operand" "S,r"))
(match_operand:SI 2 "general_operand" "g,g")))
(clobber (reg:SI 31))]
- ""
+ "! TARGET_LONG_CALLS"
"@
jarl %1,r31
jarl .+4,r31\\n\\tadd 4,r31\\n\\tjmp %1"
- [(set_attr "length" "4,8")])
+ [(set_attr "length" "4,8")]
+)
+
+(define_insn "call_value_internal_long"
+ [(set (match_operand 0 "" "=r,r")
+ (call (mem:QI (match_operand:SI 1 "call_address_operand" "S,r"))
+ (match_operand:SI 2 "general_operand" "g,g")))
+ (clobber (reg:SI 31))]
+ "TARGET_LONG_CALLS"
+ "*
+ {
+ if (which_alternative == 0)
+ {
+ if (GET_CODE (operands[1]) == REG)
+ return \"jarl %1, r31\";
+ else
+ /* Reload can generate this pattern... */
+ return \"movhi hi(%1), r0, r11\\n\\tmovea lo(%1), r11, r11\\n\\tjarl .+4, r31\\n\\tadd 4, r31\\n\\tjmp r11\";
+ }
+ else
+ return \"jarl .+4, r31\\n\\tadd 4, r31\\n\\tjmp %1\";
+ }"
+ [(set_attr "length" "16,8")]
+)
(define_insn "nop"
[(const_int 0)]
"TARGET_PROLOG_FUNCTION"
"* return construct_save_jarl (operands[0]);
"
- [(set_attr "length" "4")
+ [(set (attr "length") (if_then_else (eq_attr "long_calls" "yes")
+ (const_string "16")
+ (const_string "4")))
(set_attr "cc" "clobber")])
;; This pattern will match a return RTX followed by any number of pop RTXs
"TARGET_PROLOG_FUNCTION && TARGET_V850"
"* return construct_restore_jr (operands[0]);
"
- [(set_attr "length" "4")
+ [(set (attr "length") (if_then_else (eq_attr "long_calls" "yes")
+ (const_string "12")
+ (const_string "4")))
(set_attr "cc" "clobber")])
;; Initialize an interrupt function. Do not depend on TARGET_PROLOG_FUNCTION.
(set (mem:SI (plus:SI (reg:SI 3) (const_int -4))) (reg:SI 10))
(set (mem:SI (plus:SI (reg:SI 3) (const_int -8))) (reg:SI 4))
(set (mem:SI (plus:SI (reg:SI 3) (const_int -12))) (reg:SI 1))]
- "TARGET_V850"
+ "TARGET_V850 && ! TARGET_LONG_CALLS"
"add -16,sp\;st.w r10,12[sp]\;jarl __save_interrupt,r10"
[(set_attr "length" "12")
(set_attr "cc" "clobber")])
(define_insn "save_all_interrupt"
[(unspec_volatile [(const_int 0)] 0)]
- "TARGET_V850"
+ "TARGET_V850 && ! TARGET_LONG_CALLS"
"jarl __save_all_interrupt,r10"
[(set_attr "length" "4")
(set_attr "cc" "clobber")])
(define_insn "restore_all_interrupt"
[(unspec_volatile [(const_int 0)] 1)]
- "TARGET_V850"
+ "TARGET_V850 && ! TARGET_LONG_CALLS"
"jarl __restore_all_interrupt,r10"
[(set_attr "length" "4")
(set_attr "cc" "clobber")])
(set (mem:SI (plus:SI (reg:SI 3) (const_int 8))) (reg:SI 8))
(set (mem:SI (plus:SI (reg:SI 3) (const_int 12))) (reg:SI 9))
(clobber (reg:SI 10))]
- "TARGET_PROLOG_FUNCTION"
+ "TARGET_PROLOG_FUNCTION && ! TARGET_LONG_CALLS"
"jarl __save_r6_r9,r10"
[(set_attr "length" "4")
(set_attr "cc" "clobber")])