if (GET_CODE (op) == CONST_INT)
return 0;
- /* Otherwise we can allow any general_operand in the address. */
- return general_operand (op, Pmode);
-}
-
-/* Like call_insn_operand but allow (mem (symbol_ref ...)) even if pic. */
-
-int
-expander_call_insn_operand (op, mode)
- rtx op;
- enum machine_mode mode;
-{
- if (GET_CODE (op) == MEM
- && GET_CODE (XEXP (op, 0)) == SYMBOL_REF)
+ /* Explicitly allow SYMBOL_REF even if pic. */
+ if (GET_CODE (op) == SYMBOL_REF)
return 1;
- return call_insn_operand (op, mode);
+ /* Half-pic doesn't allow anything but registers and constants.
+ We've just taken care of the later. */
+ if (HALF_PIC_P ())
+ return register_operand (op, Pmode);
+
+ /* Otherwise we can allow any general_operand in the address. */
+ return general_operand (op, Pmode);
}
int
rtx op;
enum machine_mode mode ATTRIBUTE_UNUSED;
{
- return GET_CODE (op) == MEM &&
- CONSTANT_ADDRESS_P (XEXP (op, 0)) &&
- GET_CODE (XEXP (op, 0)) != CONST_INT;
+ return (GET_CODE (op) == MEM
+ && CONSTANT_ADDRESS_P (XEXP (op, 0))
+ && GET_CODE (XEXP (op, 0)) != CONST_INT);
}
/* Match exactly zero and one. */
/* Restore function stack, frame, and registers. */
void
-ix86_expand_epilogue ()
+ix86_expand_epilogue (emit_return)
+ int emit_return;
{
int nregs;
int regno;
emit_insn (gen_popsi1 (gen_rtx_REG (SImode, regno)));
}
+ /* Sibcall epilogues don't want a return instruction. */
+ if (! emit_return)
+ return;
+
if (current_function_pops_args && current_function_args_size)
{
rtx popc = GEN_INT (current_function_pops_args);
\f
;; Call instructions.
-;; If generating PIC code, the predicate indirect_operand will fail
-;; for operands[0] containing symbolic references on all of the named
-;; call* patterns. Each named pattern is followed by an unnamed pattern
-;; that matches any call to a symbolic CONST (ie, a symbol_ref). The
-;; unnamed patterns are only used while generating PIC code, because
-;; otherwise the named patterns match.
+;; The predicates normally associated with named expanders are not properly
+;; checked for calls. This is a bug in the generic code, but it isn't that
+;; easy to fix. Ignore it for now and be prepared to fix things up.
;; Call subroutine returning no value.
(define_expand "call_pop"
- [(parallel [(call (match_operand:QI 0 "indirect_operand" "")
- (match_operand:SI 1 "general_operand" ""))
+ [(parallel [(call (match_operand:QI 0 "" "")
+ (match_operand:SI 1 "" ""))
(set (reg:SI 7)
(plus:SI (reg:SI 7)
- (match_operand:SI 3 "immediate_operand" "")))])]
+ (match_operand:SI 3 "" "")))])]
""
"
{
- rtx addr;
-
if (operands[3] == const0_rtx)
{
emit_insn (gen_call (operands[0], operands[1]));
DONE;
}
+ /* ??? Not true for calls to static functions. */
if (flag_pic)
current_function_uses_pic_offset_table = 1;
- /* With half-pic, force the address into a register. */
- addr = XEXP (operands[0], 0);
- if (GET_CODE (addr) != REG && HALF_PIC_P () && !CONSTANT_ADDRESS_P (addr))
- XEXP (operands[0], 0) = force_reg (Pmode, addr);
-
- if (! expander_call_insn_operand (operands[0], QImode))
- operands[0]
- = change_address (operands[0], VOIDmode,
- copy_to_mode_reg (Pmode, XEXP (operands[0], 0)));
+ if (! call_insn_operand (operands[0], QImode))
+ XEXP (operands[0], 0) = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
}")
-(define_insn "*call_pop_pic"
+(define_insn "*call_pop_1"
[(call (match_operand:QI 0 "call_insn_operand" "m")
(match_operand:SI 1 "general_operand" "g"))
(set (reg:SI 7) (plus:SI (reg:SI 7)
}"
[(set_attr "type" "call")])
-(define_insn "*call_pop_pic2"
- [(call (match_operand:QI 0 "constant_call_address_operand" "")
- (match_operand:SI 1 "general_operand" "g"))
- (set (reg:SI 7) (plus:SI (reg:SI 7)
- (match_operand:SI 3 "immediate_operand" "i")))]
- "!HALF_PIC_P ()"
- "call\\t%P0"
- [(set_attr "type" "call")])
-
(define_expand "call"
- [(call (match_operand:QI 0 "indirect_operand" "")
- (match_operand:SI 1 "general_operand" ""))]
+ [(call (match_operand:QI 0 "" "")
+ (match_operand:SI 1 "" ""))]
;; Operand 1 not used on the i386.
""
"
{
- rtx addr;
-
+ /* ??? Not true for calls to static functions. */
if (flag_pic)
current_function_uses_pic_offset_table = 1;
- /* With half-pic, force the address into a register. */
- addr = XEXP (operands[0], 0);
- if (GET_CODE (addr) != REG && HALF_PIC_P () && !CONSTANT_ADDRESS_P (addr))
- XEXP (operands[0], 0) = force_reg (Pmode, addr);
-
- if (! expander_call_insn_operand (operands[0], QImode))
- operands[0]
- = change_address (operands[0], VOIDmode,
- copy_to_mode_reg (Pmode, XEXP (operands[0], 0)));
+ if (! call_insn_operand (operands[0], QImode))
+ XEXP (operands[0], 0) = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
}")
-(define_insn "*call_pic"
+(define_insn "*call_1"
[(call (match_operand:QI 0 "call_insn_operand" "m")
(match_operand:SI 1 "general_operand" "g"))]
;; Operand 1 not used on the i386.
"*
{
if (constant_call_address_operand (operands[0], GET_MODE (operands[0])))
- return \"call\\t%P0\";
-
+ {
+ if (SIBLING_CALL_P (insn))
+ return \"jmp\\t%P0\";
+ else
+ return \"call\\t%P0\";
+ }
+
operands[0] = XEXP (operands[0], 0);
- return \"call\\t%*%0\";
+ if (SIBLING_CALL_P (insn))
+ return \"jmp\\t%*%0\";
+ else
+ return \"call\\t%*%0\";
}"
[(set_attr "type" "call")])
-(define_insn "*call_pic2"
- [(call (match_operand:QI 0 "constant_call_address_operand" "")
- (match_operand:SI 1 "general_operand" "g"))]
- "!HALF_PIC_P ()"
- "call\\t%P0"
- [(set_attr "type" "call")])
-
;; Call subroutine, returning value in operand 0
;; (which must be a hard register).
(define_expand "call_value_pop"
[(parallel [(set (match_operand 0 "" "")
- (call (match_operand:QI 1 "indirect_operand" "")
- (match_operand:SI 2 "general_operand" "")))
+ (call (match_operand:QI 1 "" "")
+ (match_operand:SI 2 "" "")))
(set (reg:SI 7)
(plus:SI (reg:SI 7)
- (match_operand:SI 4 "immediate_operand" "")))])]
+ (match_operand:SI 4 "" "")))])]
""
"
{
DONE;
}
+ /* ??? Not true for calls to static functions. */
if (flag_pic)
current_function_uses_pic_offset_table = 1;
- /* With half-pic, force the address into a register. */
- addr = XEXP (operands[1], 0);
- if (GET_CODE (addr) != REG && HALF_PIC_P () && !CONSTANT_ADDRESS_P (addr))
- XEXP (operands[1], 0) = force_reg (Pmode, addr);
-
- if (! expander_call_insn_operand (operands[1], QImode))
- operands[1]
- = change_address (operands[1], VOIDmode,
- copy_to_mode_reg (Pmode, XEXP (operands[1], 0)));
+ if (! call_insn_operand (operands[1], QImode))
+ XEXP (operands[1], 0) = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
}")
(define_expand "call_value"
[(set (match_operand 0 "" "")
- (call (match_operand:QI 1 "indirect_operand" "")
- (match_operand:SI 2 "general_operand" "")))]
+ (call (match_operand:QI 1 "" "")
+ (match_operand:SI 2 "" "")))]
;; Operand 2 not used on the i386.
""
"
{
rtx addr;
+ /* ??? Not true for calls to static functions. */
if (flag_pic)
current_function_uses_pic_offset_table = 1;
- /* With half-pic, force the address into a register. */
- addr = XEXP (operands[1], 0);
- if (GET_CODE (addr) != REG && HALF_PIC_P () && !CONSTANT_ADDRESS_P (addr))
- XEXP (operands[1], 0) = force_reg (Pmode, addr);
-
- if (! expander_call_insn_operand (operands[1], QImode))
- operands[1]
- = change_address (operands[1], VOIDmode,
- copy_to_mode_reg (Pmode, XEXP (operands[1], 0)));
+ if (! call_insn_operand (operands[1], QImode))
+ XEXP (operands[1], 0) = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
}")
;; Call subroutine returning any type.
(define_expand "epilogue"
[(const_int 1)]
""
- "ix86_expand_epilogue (); DONE;")
+ "ix86_expand_epilogue (1); DONE;")
+
+(define_expand "sibcall_epilogue"
+ [(const_int 1)]
+ ""
+ "ix86_expand_epilogue (0); DONE;")
(define_insn "leave"
[(set (reg:SI 7) (reg:SI 6))
}"
[(set_attr "type" "callv")])
-(define_insn "*call_value_pop_2"
- [(set (match_operand 0 "" "")
- (call (match_operand:QI 1 "constant_call_address_operand" "")
- (match_operand:SI 2 "general_operand" "g")))
- (set (reg:SI 7) (plus:SI (reg:SI 7)
- (match_operand:SI 4 "immediate_operand" "i")))]
- "!HALF_PIC_P ()"
- "call\\t%P1"
- [(set_attr "type" "callv")])
-
(define_insn "*call_value_1"
[(set (match_operand 0 "" "")
(call (match_operand:QI 1 "call_insn_operand" "m")
"*
{
if (constant_call_address_operand (operands[1], GET_MODE (operands[1])))
- return \"call\\t%P1\";
+ {
+ if (SIBLING_CALL_P (insn))
+ return \"jmp\\t%P1\";
+ else
+ return \"call\\t%P1\";
+ }
operands[1] = XEXP (operands[1], 0);
- return \"call\\t%*%1\";
+ if (SIBLING_CALL_P (insn))
+ return \"jmp\\t%*%1\";
+ else
+ return \"call\\t%*%1\";
}"
[(set_attr "type" "callv")])
-
-(define_insn "*call_value_2"
- [(set (match_operand 0 "" "")
- (call (match_operand:QI 1 "constant_call_address_operand" "")
- (match_operand:SI 2 "general_operand" "g")))]
- "!HALF_PIC_P ()"
- "call\\t%P1"
- [(set_attr "type" "callv")])