Commit 576182a3 by Tom Wood

(untyped_call, untyped_return): New patterns.

From-SVN: r3837
parent e9125c09
...@@ -4113,6 +4113,123 @@ ...@@ -4113,6 +4113,123 @@
"!HALF_PIC_P ()" "!HALF_PIC_P ()"
"call %P1") "call %P1")
(define_expand "untyped_call"
[(parallel [(call (match_operand:QI 0 "indirect_operand" "")
(const_int 0))
(match_operand:BLK 1 "memory_operand" "")
(match_operand 2 "" "")])]
""
"
{
rtx addr;
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);
operands[1] = change_address (operands[1], DImode, XEXP (operands[1], 0));
}")
(define_insn ""
[(call (match_operand:QI 0 "indirect_operand" "m")
(const_int 0))
(match_operand:DI 1 "memory_operand" "o")
(match_operand 2 "" "")]
""
"*
{
rtx addr = operands[1];
if (GET_CODE (operands[0]) == MEM
&& ! CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
{
operands[0] = XEXP (operands[0], 0);
output_asm_insn (AS1 (call,%*%0), operands);
}
else
output_asm_insn (AS1 (call,%P0), operands);
operands[2] = gen_rtx (REG, SImode, 0);
output_asm_insn (AS2 (mov%L2,%2,%1), operands);
operands[2] = gen_rtx (REG, SImode, 1);
operands[1] = adj_offsettable_operand (addr, 4);
output_asm_insn (AS2 (mov%L2,%2,%1), operands);
operands[1] = adj_offsettable_operand (addr, 8);
return AS1 (fnsave,%1);
}")
(define_insn ""
[(call (mem:QI (match_operand:SI 0 "symbolic_operand" ""))
(const_int 0))
(match_operand:DI 1 "memory_operand" "o")
(match_operand 2 "" "")]
"!HALF_PIC_P ()"
"*
{
rtx addr = operands[1];
output_asm_insn (AS1 (call,%P0));
operands[2] = gen_rtx (REG, SImode, 0);
output_asm_insn (AS2 (mov%L2,%2,%1), operands);
operands[2] = gen_rtx (REG, SImode, 1);
operands[1] = adj_offsettable_operand (addr, 4);
output_asm_insn (AS2 (mov%L2,%2,%1), operands);
operands[1] = adj_offsettable_operand (addr, 8);
return AS1 (fnsave,%1);
}")
;; We use fnsave and frstor to save and restore the floating point result.
;; These are expensive instructions and require a large space to save the
;; FPU state. An more complicated alternative is to use fnstenv to store
;; the FPU environment and test whether the stack top is valid. Store the
;; result of the test, and if it is valid, pop and save the value. The
;; untyped_return would check the test and optionally push the saved value.
(define_expand "untyped_return"
[(match_operand:BLK 0 "memory_operand" "")
(match_operand 1 "" "")]
""
"
{
rtx valreg1 = gen_rtx (REG, SImode, 0);
rtx valreg2 = gen_rtx (REG, SImode, 1);
rtx result = operands[0];
/* Restore the FPU state. */
emit_insn (gen_update_return (change_address (result, SImode,
plus_constant (XEXP (result, 0),
8))));
/* Reload the function value registers. */
emit_move_insn (valreg1, change_address (result, SImode, XEXP (result, 0)));
emit_move_insn (valreg2,
change_address (result, SImode,
plus_constant (XEXP (result, 0), 4)));
/* Put USE insns before the return. */
emit_insn (gen_rtx (USE, VOIDmode, valreg1));
emit_insn (gen_rtx (USE, VOIDmode, valreg2));
/* Construct the return. */
expand_null_return ();
DONE;
}")
(define_insn "update_return"
[(unspec:SI [(match_operand:SI 0 "memory_operand" "m")] 0)]
""
"frstor %0")
;; Insn emitted into the body of a function to return from a function. ;; Insn emitted into the body of a function to return from a function.
;; This is only done if the function's epilogue is known to be simple. ;; This is only done if the function's epilogue is known to be simple.
;; See comments for simple_386_epilogue in i386.c. ;; See comments for simple_386_epilogue in i386.c.
......
...@@ -2749,6 +2749,83 @@ ...@@ -2749,6 +2749,83 @@
return \"call %a1,%2%#\"; return \"call %a1,%2%#\";
}" }"
[(set_attr "type" "call")]) [(set_attr "type" "call")])
(define_expand "untyped_call"
[(parallel [(call (match_operand:SI 0 "call_operand" "")
(const_int 0))
(match_operand:BLK 1 "memory_operand" "")
(match_operand 2 "" "")
(clobber (reg:SI 15))])]
""
"
{
operands[1] = change_address (operands[1], DImode, XEXP (operands[1], 0));
}")
;; Make a call followed by two nops in case the function being called
;; returns a structure value and expects to skip an unimp instruction.
(define_insn ""
[(call (mem:SI (match_operand:SI 0 "call_operand_address" "rS"))
(const_int 0))
(match_operand:DI 1 "memory_operand" "o")
(match_operand 2 "" "")
(clobber (reg:SI 15))]
""
"*
{
operands[2] = adj_offsettable_operand (operands[1], 8);
return \"call %a0,0\;nop\;nop\;std %%o0,%1\;st %%f0,%2\";
}"
[(set_attr "type" "multi")])
;; Prepare to return any type including a structure value.
(define_expand "untyped_return"
[(match_operand:BLK 0 "memory_operand" "")
(match_operand 1 "" "")]
""
"
{
rtx valreg1 = gen_rtx (REG, DImode, 24);
rtx valreg2 = gen_rtx (REG, DFmode, 32);
rtx result = operands[0];
rtx rtnreg = gen_rtx (REG, SImode, (leaf_function ? 15 : 31));
rtx value = gen_reg_rtx (SImode);
/* Fetch the instruction where we will return to and see if it's an unimp
instruction (the most significant 10 bits will be zero). If so,
update the return address to skip the unimp instruction. */
emit_move_insn (value,
gen_rtx (MEM, SImode, plus_constant (rtnreg, 8)));
emit_insn (gen_lshrsi3 (value, value, GEN_INT (22)));
emit_insn (gen_update_return (rtnreg, value));
/* Reload the function value registers. */
emit_move_insn (valreg1, change_address (result, DImode, XEXP (result, 0)));
emit_move_insn (valreg2,
change_address (result, DFmode,
plus_constant (XEXP (result, 0), 8)));
/* Put USE insns before the return. */
emit_insn (gen_rtx (USE, VOIDmode, valreg1));
emit_insn (gen_rtx (USE, VOIDmode, valreg2));
/* Construct the return. */
expand_null_return ();
DONE;
}")
;; This is a bit of a hack. We're incrementing a fixed register (%i7),
;; and parts of the compiler don't want to believe that the add is needed.
(define_insn "update_return"
[(unspec:SI [(match_operand:SI 0 "register_operand" "r")
(match_operand:SI 1 "register_operand" "r")] 0)]
""
"cmp %1,0\;be,a .+8\;add %0,4,%0"
[(set_attr "type" "multi")])
(define_insn "return" (define_insn "return"
[(return)] [(return)]
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment