Commit b840bfb0 by Michael Meissner

Respin DI support to be combine friendly; Allow push of SF without temp reg; Fix…

Respin DI support to be combine friendly; Allow push of SF without temp reg; Fix broken i386 untyped_call

From-SVN: r8098
parent 3221f176
...@@ -378,6 +378,7 @@ find_addr_reg (addr) ...@@ -378,6 +378,7 @@ find_addr_reg (addr)
abort (); abort ();
} }
/* Output an insn to add the constant N to the register X. */ /* Output an insn to add the constant N to the register X. */
static void static void
...@@ -404,6 +405,7 @@ asm_add (n, x) ...@@ -404,6 +405,7 @@ asm_add (n, x)
} }
} }
/* Output assembler code to perform a doubleword move insn /* Output assembler code to perform a doubleword move insn
with operands OPERANDS. */ with operands OPERANDS. */
...@@ -735,6 +737,199 @@ compadr: ...@@ -735,6 +737,199 @@ compadr:
return ""; return "";
} }
#define MAX_TMPS 2 /* max temporary registers used */
/* Output the appropriate code to move push memory on the stack */
char *
output_move_pushmem (operands, insn, length, tmp_start, n_operands)
rtx operands[];
rtx insn;
int length;
int tmp_start;
int n_operands;
{
struct {
char *load;
char *push;
rtx xops[2];
} tmp_info[MAX_TMPS];
rtx src = operands[1];
int max_tmps = 0;
int offset = 0;
int stack_p = reg_overlap_mentioned_p (stack_pointer_rtx, src);
int stack_offset = 0;
int i, num_tmps;
rtx xops[1];
if (!offsettable_memref_p (src))
fatal_insn ("Source is not offsettable", insn);
if ((length & 3) != 0)
fatal_insn ("Pushing non-word aligned size", insn);
/* Figure out which temporary registers we have available */
for (i = tmp_start; i < n_operands; i++)
{
if (GET_CODE (operands[i]) == REG)
{
if (reg_overlap_mentioned_p (operands[i], src))
continue;
tmp_info[ max_tmps++ ].xops[1] = operands[i];
if (max_tmps == MAX_TMPS)
break;
}
}
if (max_tmps == 0)
for (offset = length - 4; offset >= 0; offset -= 4)
{
xops[0] = adj_offsettable_operand (src, offset + stack_offset);
output_asm_insn (AS1(push%L0,%0), xops);
if (stack_p)
stack_offset += 4;
}
else
for (offset = length - 4; offset >= 0; )
{
for (num_tmps = 0; num_tmps < max_tmps && offset >= 0; num_tmps++)
{
tmp_info[num_tmps].load = AS2(mov%L0,%0,%1);
tmp_info[num_tmps].push = AS1(push%L0,%1);
tmp_info[num_tmps].xops[0] = adj_offsettable_operand (src, offset + stack_offset);
offset -= 4;
}
for (i = 0; i < num_tmps; i++)
output_asm_insn (tmp_info[i].load, tmp_info[i].xops);
for (i = 0; i < num_tmps; i++)
output_asm_insn (tmp_info[i].push, tmp_info[i].xops);
if (stack_p)
stack_offset += 4*num_tmps;
}
return "";
}
/* Output the appropriate code to move data between two memory locations */
char *
output_move_memory (operands, insn, length, tmp_start, n_operands)
rtx operands[];
rtx insn;
int length;
int tmp_start;
int n_operands;
{
struct {
char *load;
char *store;
rtx xops[3];
} tmp_info[MAX_TMPS];
rtx dest = operands[0];
rtx src = operands[1];
rtx qi_tmp = NULL_RTX;
int max_tmps = 0;
int offset = 0;
int i, num_tmps;
rtx xops[3];
if (GET_CODE (dest) == MEM
&& GET_CODE (XEXP (dest, 0)) == PRE_INC
&& XEXP (XEXP (dest, 0), 0) == stack_pointer_rtx)
return output_move_pushmem (operands, insn, length, tmp_start, n_operands);
if (!offsettable_memref_p (src))
fatal_insn ("Source is not offsettable", insn);
if (!offsettable_memref_p (dest))
fatal_insn ("Destination is not offsettable", insn);
/* Figure out which temporary registers we have available */
for (i = tmp_start; i < n_operands; i++)
{
if (GET_CODE (operands[i]) == REG)
{
if ((length & 1) != 0 && !qi_tmp && QI_REG_P (operands[i]))
qi_tmp = operands[i];
if (reg_overlap_mentioned_p (operands[i], dest))
fatal_insn ("Temporary register overlaps the destination", insn);
if (reg_overlap_mentioned_p (operands[i], src))
fatal_insn ("Temporary register overlaps the source", insn);
tmp_info[ max_tmps++ ].xops[2] = operands[i];
if (max_tmps == MAX_TMPS)
break;
}
}
if (max_tmps == 0)
fatal_insn ("No scratch registers were found to do memory->memory moves", insn);
if ((length & 1) != 0)
{
if (!qi_tmp)
fatal_insn ("No byte register found when moving odd # of bytes.", insn);
}
while (length > 1)
{
for (num_tmps = 0; num_tmps < max_tmps; num_tmps++)
{
if (length >= 4)
{
tmp_info[num_tmps].load = AS2(mov%L0,%1,%2);
tmp_info[num_tmps].store = AS2(mov%L0,%2,%0);
tmp_info[num_tmps].xops[0] = adj_offsettable_operand (dest, offset);
tmp_info[num_tmps].xops[1] = adj_offsettable_operand (src, offset);
offset += 4;
length -= 4;
}
else if (length >= 2)
{
tmp_info[num_tmps].load = AS2(mov%W0,%1,%2);
tmp_info[num_tmps].store = AS2(mov%W0,%2,%0);
tmp_info[num_tmps].xops[0] = adj_offsettable_operand (dest, offset);
tmp_info[num_tmps].xops[1] = adj_offsettable_operand (src, offset);
offset += 2;
length -= 2;
}
else
break;
}
for (i = 0; i < num_tmps; i++)
output_asm_insn (tmp_info[i].load, tmp_info[i].xops);
for (i = 0; i < num_tmps; i++)
output_asm_insn (tmp_info[i].store, tmp_info[i].xops);
}
if (length == 1)
{
xops[0] = adj_offsettable_operand (dest, offset);
xops[1] = adj_offsettable_operand (src, offset);
xops[2] = qi_tmp;
output_asm_insn (AS2(mov%B0,%1,%2), xops);
output_asm_insn (AS2(mov%B0,%2,%0), xops);
}
return "";
}
int int
standard_80387_constant_p (x) standard_80387_constant_p (x)
......
...@@ -1704,6 +1704,8 @@ extern void output_op_from_reg (); ...@@ -1704,6 +1704,8 @@ extern void output_op_from_reg ();
extern void output_to_reg (); extern void output_to_reg ();
extern char *singlemove_string (); extern char *singlemove_string ();
extern char *output_move_double (); extern char *output_move_double ();
extern char *output_move_memory ();
extern char *output_move_pushmem ();
extern int standard_80387_constant_p (); extern int standard_80387_constant_p ();
extern char *output_move_const_single (); extern char *output_move_const_single ();
extern int symbolic_operand (); extern int symbolic_operand ();
......
...@@ -808,6 +808,11 @@ ...@@ -808,6 +808,11 @@
/* Fastest way to change a 0 to a 1. */ /* Fastest way to change a 0 to a 1. */
return AS1 (inc%L0,%0); return AS1 (inc%L0,%0);
if (flag_pic
&& GET_CODE (operands[1]) == SYMBOL_REF
&& CONSTANT_POOL_ADDRESS_P (operands[1]))
return AS2 (lea%L0,%a1,%0);
return AS2 (mov%L0,%1,%0); return AS2 (mov%L0,%1,%0);
}") }")
...@@ -1108,9 +1113,9 @@ ...@@ -1108,9 +1113,9 @@
}") }")
(define_insn "movsf_push" (define_insn "movsf_push"
[(set (match_operand:SF 0 "push_operand" "=<,<,<") [(set (match_operand:SF 0 "push_operand" "=<,<,<,<")
(match_operand:SF 1 "general_operand" "rF,f,m")) (match_operand:SF 1 "general_operand" "rF,f,m,m"))
(clobber (match_scratch:SI 2 "=X,X,r"))] (clobber (match_scratch:SI 2 "=X,X,r,X"))]
"" ""
"* "*
{ {
...@@ -1134,7 +1139,7 @@ ...@@ -1134,7 +1139,7 @@
RET; RET;
} }
else if (GET_CODE (operands[1]) != MEM) else if (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != REG)
return AS1 (push%L1,%1); return AS1 (push%L1,%1);
else else
...@@ -1301,42 +1306,11 @@ ...@@ -1301,42 +1306,11 @@
RET; RET;
} }
else if (GET_CODE (operands[1]) != MEM else if (GET_CODE (operands[1]) != MEM)
|| GET_CODE (operands[2]) != REG)
return output_move_double (operands); return output_move_double (operands);
else else
{ return output_move_pushmem (operands, insn, GET_MODE_SIZE (DFmode), 2, 4);
rtx low[1], high[1], xop[4];
split_di (&operands[1], 1, low, high);
xop[0] = operands[2];
xop[1] = operands[3];
xop[2] = high[0];
xop[3] = low[0];
if (GET_CODE (operands[3]) == REG)
{ /* 2 scratch registers available */
output_asm_insn (AS2 (mov%L0,%2,%0), xop);
output_asm_insn (AS2 (mov%L0,%3,%1), xop);
output_asm_insn (AS1 (push%L0,%0), xop);
output_asm_insn (AS1 (push%L0,%1), xop);
}
else
{ /* 1 scratch register */
output_asm_insn (AS2 (mov%L0,%2,%0), xop);
output_asm_insn (AS1 (push%L0,%0), xop);
/* account for push above */
if (reg_mentioned_p (stack_pointer_rtx, XEXP (xop[3], 0)))
xop[3] = adj_offsettable_operand (xop[3], 4);
output_asm_insn (AS2 (mov%L0,%3,%0), xop);
output_asm_insn (AS1 (push%L0,%0), xop);
}
RET;
}
}") }")
(define_insn "movdf_mem" (define_insn "movdf_mem"
...@@ -1345,34 +1319,7 @@ ...@@ -1345,34 +1319,7 @@
(clobber (match_scratch:SI 2 "=&r,&r")) (clobber (match_scratch:SI 2 "=&r,&r"))
(clobber (match_scratch:SI 3 "=&r,X"))] (clobber (match_scratch:SI 3 "=&r,X"))]
"" ""
"* "* return output_move_memory (operands, insn, GET_MODE_SIZE (DFmode), 2, 4);")
{
rtx low[2], high[2], xop[6];
split_di (operands, 2, low, high);
xop[0] = operands[2];
xop[1] = operands[3];
xop[2] = high[0];
xop[3] = high[1];
xop[4] = low[0];
xop[5] = low[1];
if (GET_CODE (operands[3]) == REG)
{ /* 2 scratch registers available */
output_asm_insn (AS2 (mov%L0,%5,%0), xop);
output_asm_insn (AS2 (mov%L0,%3,%1), xop);
output_asm_insn (AS2 (mov%L0,%0,%4), xop);
output_asm_insn (AS2 (mov%L0,%1,%2), xop);
}
else
{ /* 1 scratch register */
output_asm_insn (AS2 (mov%L0,%5,%0), xop);
output_asm_insn (AS2 (mov%L0,%0,%4), xop);
output_asm_insn (AS2 (mov%L0,%3,%0), xop);
output_asm_insn (AS2 (mov%L0,%0,%2), xop);
}
RET;
}")
;; For the purposes of regclass, prefer FLOAT_REGS. ;; For the purposes of regclass, prefer FLOAT_REGS.
(define_insn "movdf_normal" (define_insn "movdf_normal"
...@@ -1520,51 +1467,7 @@ ...@@ -1520,51 +1467,7 @@
return output_move_double (operands); return output_move_double (operands);
else else
{ return output_move_pushmem (operands, insn, GET_MODE_SIZE (XFmode), 2, 4);
rtx xop[5];
xop[0] = operands[2];
xop[1] = operands[3];
xop[2] = adj_offsettable_operand (operands[1], 8);
xop[3] = adj_offsettable_operand (operands[1], 4);
xop[4] = operands[1];
if (GET_CODE (operands[3]) == REG)
{ /* 2 scratch registers available */
output_asm_insn (AS2 (mov%L0,%2,%0), xop);
output_asm_insn (AS2 (mov%L0,%3,%1), xop);
output_asm_insn (AS1 (push%L0,%0), xop);
output_asm_insn (AS1 (push%L0,%1), xop);
/* account for 2 pushes above */
if (reg_mentioned_p (stack_pointer_rtx, XEXP (xop[4], 0)))
xop[4] = adj_offsettable_operand (xop[4], 8);
output_asm_insn (AS2 (mov%L0,%4,%0), xop);
output_asm_insn (AS1 (push%L0,%0), xop);
}
else
{ /* 1 scratch register */
output_asm_insn (AS2 (mov%L0,%2,%0), xop);
output_asm_insn (AS1 (push%L0,%0), xop);
/* account for 1 push above */
if (reg_mentioned_p (stack_pointer_rtx, XEXP (xop[3], 0)))
xop[3] = adj_offsettable_operand (xop[3], 4);
output_asm_insn (AS2 (mov%L0,%3,%0), xop);
output_asm_insn (AS1 (push%L0,%0), xop);
/* account for 2 pushes above */
if (reg_mentioned_p (stack_pointer_rtx, XEXP (xop[4], 0)))
xop[4] = adj_offsettable_operand (xop[4], 8);
output_asm_insn (AS2 (mov%L0,%4,%0), xop);
output_asm_insn (AS1 (push%L0,%0), xop);
}
RET;
}
}") }")
(define_insn "movxf_mem" (define_insn "movxf_mem"
...@@ -1573,40 +1476,7 @@ ...@@ -1573,40 +1476,7 @@
(clobber (match_scratch:SI 2 "=&r,&r")) (clobber (match_scratch:SI 2 "=&r,&r"))
(clobber (match_scratch:SI 3 "=&r,X"))] (clobber (match_scratch:SI 3 "=&r,X"))]
"" ""
"* "* return output_move_memory (operands, insn, GET_MODE_SIZE (XFmode), 2, 4);")
{
rtx xop[8];
xop[0] = operands[2];
xop[1] = operands[3];
xop[2] = adj_offsettable_operand (operands[1], 8);
xop[3] = adj_offsettable_operand (operands[1], 4);
xop[4] = operands[1];
xop[5] = adj_offsettable_operand (operands[0], 8);
xop[6] = adj_offsettable_operand (operands[0], 4);
xop[7] = operands[0];
if (GET_CODE (operands[3]) == REG)
{ /* 2 scratch registers available */
output_asm_insn (AS2 (mov%L0,%2,%0), xop);
output_asm_insn (AS2 (mov%L0,%3,%1), xop);
output_asm_insn (AS2 (mov%L5,%0,%5), xop);
output_asm_insn (AS2 (mov%L6,%1,%6), xop);
output_asm_insn (AS2 (mov%L0,%4,%0), xop);
output_asm_insn (AS2 (mov%L7,%0,%7), xop);
}
else
{ /* 1 scratch register */
output_asm_insn (AS2 (mov%L0,%2,%0), xop);
output_asm_insn (AS2 (mov%L0,%0,%5), xop);
output_asm_insn (AS2 (mov%L0,%3,%0), xop);
output_asm_insn (AS2 (mov%L0,%0,%6), xop);
output_asm_insn (AS2 (mov%L0,%4,%0), xop);
output_asm_insn (AS2 (mov%L7,%0,%7), xop);
}
RET;
}")
(define_insn "movxf_normal" (define_insn "movxf_normal"
[(set (match_operand:XF 0 "general_operand" "=f,fm,!*rf,!*rm") [(set (match_operand:XF 0 "general_operand" "=f,fm,!*rf,!*rm")
...@@ -1678,34 +1548,7 @@ ...@@ -1678,34 +1548,7 @@
return AS1 (fxch,%0); return AS1 (fxch,%0);
}") }")
(define_expand "movdi" (define_insn ""
[(set (match_operand:DI 0 "general_operand" "")
(match_operand:DI 1 "general_operand" ""))]
""
"
{
/* Special case memory->memory moves and pushes */
if (TARGET_MOVE
&& (reload_in_progress | reload_completed) == 0
&& GET_CODE (operands[0]) == MEM
&& (GET_CODE (operands[1]) == MEM || push_operand (operands[0], DImode)))
{
rtx (*genfunc) PROTO((rtx, rtx)) = (push_operand (operands[0], DImode))
? gen_movdi_push
: gen_movdi_mem;
emit_insn ((*genfunc) (operands[0], operands[1]));
DONE;
}
}")
(define_insn "movdi_push_nomove"
[(set (match_operand:DI 0 "push_operand" "=<")
(match_operand:DI 1 "general_operand" "roiF"))]
"!TARGET_MOVE"
"* return output_move_double (operands);")
(define_insn "movdi_push"
[(set (match_operand:DI 0 "push_operand" "=<,<,<,<") [(set (match_operand:DI 0 "push_operand" "=<,<,<,<")
(match_operand:DI 1 "general_operand" "riF,o,o,o")) (match_operand:DI 1 "general_operand" "riF,o,o,o"))
(clobber (match_scratch:SI 2 "=X,&r,&r,X")) (clobber (match_scratch:SI 2 "=X,&r,&r,X"))
...@@ -1713,85 +1556,29 @@ ...@@ -1713,85 +1556,29 @@
"" ""
"* "*
{ {
if (GET_CODE (operands[1]) != MEM if (GET_CODE (operands[1]) != MEM)
|| GET_CODE (operands[2]) != REG)
return output_move_double (operands); return output_move_double (operands);
else else
{ return output_move_pushmem (operands, insn, GET_MODE_SIZE (DImode), 2, 4);
rtx low[1], high[1], xop[4];
split_di (&operands[1], 1, low, high);
xop[0] = operands[2];
xop[1] = operands[3];
xop[2] = high[0];
xop[3] = low[0];
if (GET_CODE (operands[3]) == REG)
{ /* 2 scratch registers available */
output_asm_insn (AS2 (mov%L0,%2,%0), xop);
output_asm_insn (AS2 (mov%L0,%3,%1), xop);
output_asm_insn (AS1 (push%L0,%0), xop);
output_asm_insn (AS1 (push%L0,%1), xop);
}
else
{ /* 1 scratch register */
output_asm_insn (AS2 (mov%L0,%2,%0), xop);
output_asm_insn (AS1 (push%L0,%0), xop);
/* account for push above */
if (reg_mentioned_p (stack_pointer_rtx, XEXP (xop[3], 0)))
xop[3] = adj_offsettable_operand (xop[3], 4);
output_asm_insn (AS2 (mov%L0,%3,%0), xop);
output_asm_insn (AS1 (push%L0,%0), xop);
}
RET;
}
}") }")
(define_insn "movdi_mem" (define_insn "movdi"
[(set (match_operand:DI 0 "memory_operand" "=o,o") [(set (match_operand:DI 0 "general_operand" "=o,o,r,rm")
(match_operand:DI 1 "memory_operand" "o,o")) (match_operand:DI 1 "general_operand" "o,o,m,riF"))
(clobber (match_scratch:SI 2 "=&r,&r")) (clobber (match_scratch:SI 2 "=&r,&r,X,X"))
(clobber (match_scratch:SI 3 "=&r,X"))] (clobber (match_scratch:SI 3 "=&r,X,X,X"))]
"" ""
"* "*
{ {
rtx low[2], high[2], xop[6]; rtx low[2], high[2], xop[6];
split_di (operands, 2, low, high); if (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
xop[0] = operands[2]; return output_move_double (operands);
xop[1] = operands[3];
xop[2] = high[0];
xop[3] = high[1];
xop[4] = low[0];
xop[5] = low[1];
if (GET_CODE (operands[3]) == REG)
{ /* 2 scratch registers available */
output_asm_insn (AS2 (mov%L0,%5,%0), xop);
output_asm_insn (AS2 (mov%L0,%3,%1), xop);
output_asm_insn (AS2 (mov%L0,%0,%4), xop);
output_asm_insn (AS2 (mov%L0,%1,%2), xop);
}
else else
{ /* 1 scratch register */ return output_move_memory (operands, insn, GET_MODE_SIZE (DImode), 2, 4);
output_asm_insn (AS2 (mov%L0,%5,%0), xop);
output_asm_insn (AS2 (mov%L0,%0,%4), xop);
output_asm_insn (AS2 (mov%L0,%3,%0), xop);
output_asm_insn (AS2 (mov%L0,%0,%2), xop);
}
RET;
}") }")
(define_insn "movdi_normal"
[(set (match_operand:DI 0 "general_operand" "=r,rm")
(match_operand:DI 1 "general_operand" "m,riF"))]
"(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)"
"* return output_move_double (operands);")
;;- conversion instructions ;;- conversion instructions
;;- NONE ;;- NONE
...@@ -5296,126 +5083,42 @@ ...@@ -5296,126 +5083,42 @@
"!HALF_PIC_P ()" "!HALF_PIC_P ()"
"call %P1") "call %P1")
;; Call subroutine returning any type.
(define_expand "untyped_call" (define_expand "untyped_call"
[(parallel [(call (match_operand:QI 0 "indirect_operand" "") [(parallel [(call (match_operand 0 "" "")
(const_int 0)) (const_int 0))
(match_operand:BLK 1 "memory_operand" "") (match_operand 1 "" "")
(match_operand 2 "" "")])] (match_operand 2 "" "")])]
"" ""
" "
{ {
rtx addr; int i;
if (flag_pic) emit_call_insn (gen_call (operands[0], const0_rtx, NULL, const0_rtx));
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));
if (! expander_call_insn_operand (operands[1], QImode))
operands[1]
= change_address (operands[1], VOIDmode,
copy_to_mode_reg (Pmode, XEXP (operands[1], 0)));
}")
(define_insn "" for (i = 0; i < XVECLEN (operands[2], 0); i++)
[(call (match_operand:QI 0 "call_insn_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); rtx set = XVECEXP (operands[2], 0, i);
output_asm_insn (AS1 (call,%*%0), operands); emit_move_insn (SET_DEST (set), SET_SRC (set));
} }
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);
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. */ /* The optimizer does not know that the call sets the function value
emit_move_insn (valreg1, change_address (result, SImode, XEXP (result, 0))); registers we stored in the result block. We avoid problems by
emit_move_insn (valreg2, claiming that all hard registers are used and clobbered at this
change_address (result, SImode, point. */
plus_constant (XEXP (result, 0), 4))); emit_insn (gen_blockage ());
/* 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; DONE;
}") }")
(define_insn "update_return" ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
[(unspec:SI [(match_operand:SI 0 "memory_operand" "m")] 0)] ;; all of memory. This blocks insns from being moved across this point.
(define_insn "blockage"
[(unspec_volatile [(const_int 0)] 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.
......
...@@ -68,9 +68,7 @@ nil_method(id receiver, SEL op, ...) ...@@ -68,9 +68,7 @@ nil_method(id receiver, SEL op, ...)
} }
/* Given a class and selector, return the selector's implementation. */ /* Given a class and selector, return the selector's implementation. */
#ifndef i386 __inline__
__inline__ /* this is broken on i386... */
#endif
IMP IMP
get_imp (Class* class, SEL sel) get_imp (Class* class, SEL sel)
{ {
......
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