CALL_DEST is the routine we are calling.
RETURN_POINTER is the register which will hold the return address.
- %r2 for most calls, %r31 for millicode calls. */
+ %r2 for most calls, %r31 for millicode calls.
+
+ When TARGET_LONG_CALLS is true, output_call is only called for
+ millicode calls. In addition, no delay slots are available when
+ TARGET_LONG_CALLS is true. */
+
char *
output_call (insn, call_dest, return_pointer)
rtx insn;
{
xoperands[0] = call_dest;
xoperands[1] = return_pointer;
- output_asm_insn ("bl %0,%r1%#", xoperands);
+ if (TARGET_LONG_CALLS)
+ {
+ output_asm_insn ("ldil L%%%0,%%r29", xoperands);
+ output_asm_insn ("ldo R%%%0(%%r29),%%r29", xoperands);
+ output_asm_insn ("blr 0,%r1\n\tbv,n 0(%%r29)\n\tnop", xoperands);
+ }
+ else
+ output_asm_insn ("bl %0,%r1%#", xoperands);
return "";
}
/* Emit code which follows the new portable runtime calling conventions
HP wants everyone to use for ELF objects. If at all possible you want
- to avoid this since it's a performance loss for non-prototyped code. */
+ to avoid this since it's a performance loss for non-prototyped code.
+
+ Note TARGET_PORTABLE_RUNTIME also implies TARGET_LONG_CALLS. */
#define TARGET_PORTABLE_RUNTIME (target_flags & 64)
{"no-long-calls", -16}, \
{"disable-indexing", 32}, \
{"no-disable-indexing", -32},\
- {"portable-runtime", 64}, \
- {"no-portable-runtime", -64},\
+ {"portable-runtime", 64+16},\
+ {"no-portable-runtime", -(64+16)},\
{"gas", 128}, \
{"no-gas", -128}, \
{ "", TARGET_DEFAULT}}
(const_string "false")))
-;; Unconditional branch, call, and millicode call delay slot description.
-(define_delay (eq_attr "type" "uncond_branch,branch,call,milli")
+;; Unconditional branch and call delay slot description.
+(define_delay (eq_attr "type" "uncond_branch,branch,call")
[(eq_attr "in_call_delay" "true") (nil) (nil)])
+;; millicode call delay slot description. Note it disallows delay slot
+;; when TARGET_LONG_CALLS is true.
+(define_delay (eq_attr "type" "milli")
+ [(and (eq_attr "in_call_delay" "true")
+ (eq (symbol_ref "TARGET_LONG_CALLS") (const_int 0)))
+ (nil) (nil)])
+
;; Unconditional branch, return and other similar instructions.
(define_delay (eq_attr "type" "uncond_branch,branch")
[(eq_attr "in_branch_delay" "true") (nil) (nil)])
(clobber (reg:SI 31))]
""
"* return output_mul_insn (0, insn);"
- [(set_attr "type" "milli")])
+ [(set_attr "type" "milli")
+ (set (attr "length") (if_then_else (ne (symbol_ref "TARGET_LONG_CALLS")
+ (const_int 0))
+ (const_int 4)
+ (const_int 24)))])
;;; Division and mod.
(define_expand "divsi3"
""
"*
return output_div_insn (operands, 0, insn);"
- [(set_attr "type" "milli")])
+ [(set_attr "type" "milli")
+ (set (attr "length") (if_then_else (ne (symbol_ref "TARGET_LONG_CALLS")
+ (const_int 0))
+ (const_int 4)
+ (const_int 24)))])
(define_expand "udivsi3"
[(set (reg:SI 26) (match_operand:SI 1 "move_operand" ""))
""
"*
return output_div_insn (operands, 1, insn);"
- [(set_attr "type" "milli")])
+ [(set_attr "type" "milli")
+ (set (attr "length") (if_then_else (ne (symbol_ref "TARGET_LONG_CALLS")
+ (const_int 0))
+ (const_int 4)
+ (const_int 24)))])
(define_expand "modsi3"
[(set (reg:SI 26) (match_operand:SI 1 "move_operand" ""))
""
"*
return output_mod_insn (0, insn);"
- [(set_attr "type" "milli")])
+ [(set_attr "type" "milli")
+ (set (attr "length") (if_then_else (ne (symbol_ref "TARGET_LONG_CALLS")
+ (const_int 0))
+ (const_int 4)
+ (const_int 24)))])
(define_expand "umodsi3"
[(set (reg:SI 26) (match_operand:SI 1 "move_operand" ""))
""
"*
return output_mod_insn (1, insn);"
- [(set_attr "type" "milli")])
+ [(set_attr "type" "milli")
+ (set (attr "length") (if_then_else (ne (symbol_ref "TARGET_LONG_CALLS")
+ (const_int 0))
+ (const_int 4)
+ (const_int 24)))])
;;- and instructions
;; We define DImode `and` so with DImode `not` we can get
(clobber (reg:SI 2))
(use (const_int 1))]
""
- "copy %r0,%%r22\;.CALL\\tARGW0=GR\;bl $$dyncall,%%r31\;copy %%r31,%%r2"
+ "*
+{
+ /* Yuk! bl may not be able to reach $$dyncall. */
+ if (TARGET_LONG_CALLS)
+ return \"copy %r0,%%r22\;ldil L%%$$dyncall,%%r31\;ldo R%%$$dyncall(%%r31),%%r31\;blr 0,%%r2\;bv,n 0(%%r31)\;nop\";
+ else
+ return \"copy %r0,%%r22\;.CALL\\tARGW0=GR\;bl $$dyncall,%%r31\;copy %%r31,%%r2\";
+}"
[(set_attr "type" "dyncall")
- (set_attr "length" "12")])
+ (set (attr "length") (if_then_else (ne (symbol_ref "TARGET_LONG_CALLS")
+ (const_int 0))
+ (const_int 12)
+ (const_int 24)))])
(define_expand "call_value"
[(parallel [(set (match_operand 0 "" "")
(use (const_int 1))]
;;- Don't use operand 1 for most machines.
""
- "copy %r1,%%r22\;.CALL\\tARGW0=GR\;bl $$dyncall,%%r31\;copy %%r31,%%r2"
+ "*
+{
+ /* Yuk! bl may not be able to reach $$dyncall. */
+ if (TARGET_LONG_CALLS)
+ return \"copy %r1,%%r22\;ldil L%%$$dyncall,%%r31\;ldo R%%$$dyncall(%%r31),%%r31\;blr 0,%%r2\;bv,n 0(%%r31)\;nop\";
+ else
+ return \"copy %r1,%%r22\;.CALL\\tARGW0=GR\;bl $$dyncall,%%r31\;copy %%r31,%%r2\";
+}"
[(set_attr "type" "dyncall")
- (set_attr "length" "12")])
+ (set (attr "length") (if_then_else (ne (symbol_ref "TARGET_LONG_CALLS")
+ (const_int 0))
+ (const_int 12)
+ (const_int 24)))])
;; Call subroutine returning any type.