aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMichael Meissner <meissner@gcc.gnu.org>1994-09-20 18:36:51 +0000
committerMichael Meissner <meissner@gcc.gnu.org>1994-09-20 18:36:51 +0000
commitb840bfb0a22793c3794793a6e4817f9fb7b8e03a (patch)
tree6807dcc71df9d1143e9db694545eb8346bd766b6 /gcc
parent3221f176136402b4df91492f2234ce203cba6e76 (diff)
downloadgcc-b840bfb0a22793c3794793a6e4817f9fb7b8e03a.zip
gcc-b840bfb0a22793c3794793a6e4817f9fb7b8e03a.tar.gz
gcc-b840bfb0a22793c3794793a6e4817f9fb7b8e03a.tar.bz2
Respin DI support to be combine friendly; Allow push of SF without temp reg; Fix broken i386 untyped_call
From-SVN: r8098
Diffstat (limited to 'gcc')
-rw-r--r--gcc/config/i386/i386.c195
-rw-r--r--gcc/config/i386/i386.h2
-rw-r--r--gcc/config/i386/i386.md387
-rw-r--r--gcc/objc/sendmsg.c4
4 files changed, 243 insertions, 345 deletions
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 0e9d4b3..5a9e882 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -378,6 +378,7 @@ find_addr_reg (addr)
abort ();
}
+
/* Output an insn to add the constant N to the register X. */
static void
@@ -404,6 +405,7 @@ asm_add (n, x)
}
}
+
/* Output assembler code to perform a doubleword move insn
with operands OPERANDS. */
@@ -735,6 +737,199 @@ compadr:
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
standard_80387_constant_p (x)
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index c68b32d..562f0bd 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -1704,6 +1704,8 @@ extern void output_op_from_reg ();
extern void output_to_reg ();
extern char *singlemove_string ();
extern char *output_move_double ();
+extern char *output_move_memory ();
+extern char *output_move_pushmem ();
extern int standard_80387_constant_p ();
extern char *output_move_const_single ();
extern int symbolic_operand ();
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 330002b..0c1c31c 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -808,6 +808,11 @@
/* Fastest way to change a 0 to a 1. */
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);
}")
@@ -1108,9 +1113,9 @@
}")
(define_insn "movsf_push"
- [(set (match_operand:SF 0 "push_operand" "=<,<,<")
- (match_operand:SF 1 "general_operand" "rF,f,m"))
- (clobber (match_scratch:SI 2 "=X,X,r"))]
+ [(set (match_operand:SF 0 "push_operand" "=<,<,<,<")
+ (match_operand:SF 1 "general_operand" "rF,f,m,m"))
+ (clobber (match_scratch:SI 2 "=X,X,r,X"))]
""
"*
{
@@ -1134,7 +1139,7 @@
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);
else
@@ -1301,42 +1306,11 @@
RET;
}
- else if (GET_CODE (operands[1]) != MEM
- || GET_CODE (operands[2]) != REG)
+ else if (GET_CODE (operands[1]) != MEM)
return output_move_double (operands);
else
- {
- 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;
- }
+ return output_move_pushmem (operands, insn, GET_MODE_SIZE (DFmode), 2, 4);
}")
(define_insn "movdf_mem"
@@ -1345,34 +1319,7 @@
(clobber (match_scratch:SI 2 "=&r,&r"))
(clobber (match_scratch:SI 3 "=&r,X"))]
""
- "*
-{
- 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;
-}")
+ "* return output_move_memory (operands, insn, GET_MODE_SIZE (DFmode), 2, 4);")
;; For the purposes of regclass, prefer FLOAT_REGS.
(define_insn "movdf_normal"
@@ -1520,51 +1467,7 @@
return output_move_double (operands);
else
- {
- 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;
- }
+ return output_move_pushmem (operands, insn, GET_MODE_SIZE (XFmode), 2, 4);
}")
(define_insn "movxf_mem"
@@ -1573,40 +1476,7 @@
(clobber (match_scratch:SI 2 "=&r,&r"))
(clobber (match_scratch:SI 3 "=&r,X"))]
""
- "*
-{
- 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;
-}")
+ "* return output_move_memory (operands, insn, GET_MODE_SIZE (XFmode), 2, 4);")
(define_insn "movxf_normal"
[(set (match_operand:XF 0 "general_operand" "=f,fm,!*rf,!*rm")
@@ -1678,34 +1548,7 @@
return AS1 (fxch,%0);
}")
-(define_expand "movdi"
- [(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"
+(define_insn ""
[(set (match_operand:DI 0 "push_operand" "=<,<,<,<")
(match_operand:DI 1 "general_operand" "riF,o,o,o"))
(clobber (match_scratch:SI 2 "=X,&r,&r,X"))
@@ -1713,85 +1556,29 @@
""
"*
{
- if (GET_CODE (operands[1]) != MEM
- || GET_CODE (operands[2]) != REG)
+ if (GET_CODE (operands[1]) != MEM)
return output_move_double (operands);
else
- {
- 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;
- }
+ return output_move_pushmem (operands, insn, GET_MODE_SIZE (DImode), 2, 4);
}")
-(define_insn "movdi_mem"
- [(set (match_operand:DI 0 "memory_operand" "=o,o")
- (match_operand:DI 1 "memory_operand" "o,o"))
- (clobber (match_scratch:SI 2 "=&r,&r"))
- (clobber (match_scratch:SI 3 "=&r,X"))]
+(define_insn "movdi"
+ [(set (match_operand:DI 0 "general_operand" "=o,o,r,rm")
+ (match_operand:DI 1 "general_operand" "o,o,m,riF"))
+ (clobber (match_scratch:SI 2 "=&r,&r,X,X"))
+ (clobber (match_scratch:SI 3 "=&r,X,X,X"))]
""
"*
{
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);
- }
+ if (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
+ return output_move_double (operands);
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;
+ return output_move_memory (operands, insn, GET_MODE_SIZE (DImode), 2, 4);
}")
-(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
;;- NONE
@@ -5296,126 +5083,42 @@
"!HALF_PIC_P ()"
"call %P1")
+;; Call subroutine returning any type.
+
(define_expand "untyped_call"
- [(parallel [(call (match_operand:QI 0 "indirect_operand" "")
+ [(parallel [(call (match_operand 0 "" "")
(const_int 0))
- (match_operand:BLK 1 "memory_operand" "")
+ (match_operand 1 "" "")
(match_operand 2 "" "")])]
""
"
{
- rtx addr;
+ int i;
- 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));
- if (! expander_call_insn_operand (operands[1], QImode))
- operands[1]
- = change_address (operands[1], VOIDmode,
- copy_to_mode_reg (Pmode, XEXP (operands[1], 0)));
-}")
+ emit_call_insn (gen_call (operands[0], const0_rtx, NULL, const0_rtx));
-(define_insn ""
- [(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)))
+ for (i = 0; i < XVECLEN (operands[2], 0); i++)
{
- operands[0] = XEXP (operands[0], 0);
- output_asm_insn (AS1 (call,%*%0), operands);
+ rtx set = XVECEXP (operands[2], 0, i);
+ 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. */
- 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 ();
+ /* The optimizer does not know that the call sets the function value
+ registers we stored in the result block. We avoid problems by
+ claiming that all hard registers are used and clobbered at this
+ point. */
+ emit_insn (gen_blockage ());
DONE;
}")
-(define_insn "update_return"
- [(unspec:SI [(match_operand:SI 0 "memory_operand" "m")] 0)]
+;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
+;; 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.
;; This is only done if the function's epilogue is known to be simple.
diff --git a/gcc/objc/sendmsg.c b/gcc/objc/sendmsg.c
index 3e4f504..8185485 100644
--- a/gcc/objc/sendmsg.c
+++ b/gcc/objc/sendmsg.c
@@ -68,9 +68,7 @@ nil_method(id receiver, SEL op, ...)
}
/* Given a class and selector, return the selector's implementation. */
-#ifndef i386
-__inline__ /* this is broken on i386... */
-#endif
+__inline__
IMP
get_imp (Class* class, SEL sel)
{