re PR target/19162 (ICE while building libobjc's sendmsg.c)
* PR target/19162 * arm.c (arm_apply_result_size): New function. * arm.h (APPLY_RESULT_SIZE): Define. * arm-protos.h (arm_apply_result_size): Add prototype. * arm.md (RO_REGNUM, FPA_F0_REGNUM, FPA_F7_REGNUM): New constants. (movxf): New expand. (ldmsi_postinc4_thumb, stmsi_postinc4_thumb): New patterns for Thumb. (call_value_symbol): Remove predicate for operand 0. (call_value_insn, sibcall_value, sibcall_value_insn): Likewise. (untyped_call): Rework to correclty return values for any type. (untyped_return): New expand. * fpa.md (movxf_fpa): Simplify and use sfm/lfm when appropriate. From-SVN: r95119
This commit is contained in:
parent
f0b81cbc9f
commit
9f7bf991d0
|
@ -1,3 +1,18 @@
|
|||
2005-02-16 Richard Earnshaw <rearnsha@arm.com>
|
||||
|
||||
* PR target/19162
|
||||
* arm.c (arm_apply_result_size): New function.
|
||||
* arm.h (APPLY_RESULT_SIZE): Define.
|
||||
* arm-protos.h (arm_apply_result_size): Add prototype.
|
||||
* arm.md (RO_REGNUM, FPA_F0_REGNUM, FPA_F7_REGNUM): New constants.
|
||||
(movxf): New expand.
|
||||
(ldmsi_postinc4_thumb, stmsi_postinc4_thumb): New patterns for Thumb.
|
||||
(call_value_symbol): Remove predicate for operand 0.
|
||||
(call_value_insn, sibcall_value, sibcall_value_insn): Likewise.
|
||||
(untyped_call): Rework to correclty return values for any type.
|
||||
(untyped_return): New expand.
|
||||
* fpa.md (movxf_fpa): Simplify and use sfm/lfm when appropriate.
|
||||
|
||||
2005-02-16 Stan Shebs <shebs@apple.com>
|
||||
|
||||
* config.gcc (powerpc-*-darwin*): Use fragment for Darwin 8 or later.
|
||||
|
|
|
@ -123,6 +123,7 @@ extern void arm_init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, tree);
|
|||
extern bool arm_needs_doubleword_align (enum machine_mode, tree);
|
||||
extern rtx arm_function_value(tree, tree);
|
||||
#endif
|
||||
extern int arm_apply_result_size (void);
|
||||
|
||||
#if defined AOF_ASSEMBLER
|
||||
extern rtx aof_pic_entry (rtx);
|
||||
|
|
|
@ -2283,7 +2283,8 @@ arm_canonicalize_comparison (enum rtx_code code, rtx * op1)
|
|||
|
||||
/* Define how to find the value returned by a function. */
|
||||
|
||||
rtx arm_function_value(tree type, tree func ATTRIBUTE_UNUSED)
|
||||
rtx
|
||||
arm_function_value(tree type, tree func ATTRIBUTE_UNUSED)
|
||||
{
|
||||
enum machine_mode mode;
|
||||
int unsignedp ATTRIBUTE_UNUSED;
|
||||
|
@ -2297,6 +2298,28 @@ rtx arm_function_value(tree type, tree func ATTRIBUTE_UNUSED)
|
|||
return LIBCALL_VALUE(mode);
|
||||
}
|
||||
|
||||
/* Determine the amount of memory needed to store the possible return
|
||||
registers of an untyped call. */
|
||||
int
|
||||
arm_apply_result_size (void)
|
||||
{
|
||||
int size = 16;
|
||||
|
||||
if (TARGET_ARM)
|
||||
{
|
||||
if (TARGET_HARD_FLOAT_ABI)
|
||||
{
|
||||
if (TARGET_FPA)
|
||||
size += 12;
|
||||
if (TARGET_MAVERICK)
|
||||
size += 8;
|
||||
}
|
||||
if (TARGET_IWMMXT_ABI)
|
||||
size += 8;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
/* Decide whether a type should be returned in memory (true)
|
||||
or in a register (false). This is called by the macro
|
||||
|
|
|
@ -1617,6 +1617,10 @@ enum reg_class
|
|||
|| (TARGET_ARM && ((REGNO) == FIRST_FPA_REGNUM) \
|
||||
&& TARGET_HARD_FLOAT_ABI && TARGET_FPA))
|
||||
|
||||
/* Amount of memory needed for an untyped call to save all possible return
|
||||
registers. */
|
||||
#define APPLY_RESULT_SIZE arm_apply_result_size()
|
||||
|
||||
/* How large values are returned */
|
||||
/* A C expression which can inhibit the returning of certain function values
|
||||
in registers, based on the type of value. */
|
||||
|
|
|
@ -30,12 +30,15 @@
|
|||
|
||||
;; Register numbers
|
||||
(define_constants
|
||||
[(IP_REGNUM 12) ; Scratch register
|
||||
[(R0_REGNUM 0) ; First CORE register
|
||||
(IP_REGNUM 12) ; Scratch register
|
||||
(SP_REGNUM 13) ; Stack pointer
|
||||
(LR_REGNUM 14) ; Return address register
|
||||
(PC_REGNUM 15) ; Program counter
|
||||
(CC_REGNUM 24) ; Condition code pseudo register
|
||||
(LAST_ARM_REGNUM 15)
|
||||
(LAST_ARM_REGNUM 15) ;
|
||||
(FPA_F0_REGNUM 16) ; FIRST_FPA_REGNUM
|
||||
(FPA_F7_REGNUM 23) ; LAST_FPA_REGNUM
|
||||
]
|
||||
)
|
||||
;; 3rd operand to select_dominance_cc_mode
|
||||
|
@ -5216,6 +5219,16 @@
|
|||
(set_attr "pool_range" "*,*,*,1020,*,*")]
|
||||
)
|
||||
|
||||
(define_expand "movxf"
|
||||
[(set (match_operand:XF 0 "general_operand" "")
|
||||
(match_operand:XF 1 "general_operand" ""))]
|
||||
"TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
|
||||
"
|
||||
if (GET_CODE (operands[0]) == MEM)
|
||||
operands[1] = force_reg (XFmode, operands[1]);
|
||||
"
|
||||
)
|
||||
|
||||
;; Vector Moves
|
||||
(define_expand "movv2si"
|
||||
[(set (match_operand:V2SI 0 "nonimmediate_operand" "")
|
||||
|
@ -5288,6 +5301,24 @@
|
|||
(set_attr "predicable" "yes")]
|
||||
)
|
||||
|
||||
(define_insn "*ldmsi_postinc4_thumb"
|
||||
[(match_parallel 0 "load_multiple_operation"
|
||||
[(set (match_operand:SI 1 "s_register_operand" "=l")
|
||||
(plus:SI (match_operand:SI 2 "s_register_operand" "1")
|
||||
(const_int 16)))
|
||||
(set (match_operand:SI 3 "arm_hard_register_operand" "")
|
||||
(mem:SI (match_dup 2)))
|
||||
(set (match_operand:SI 4 "arm_hard_register_operand" "")
|
||||
(mem:SI (plus:SI (match_dup 2) (const_int 4))))
|
||||
(set (match_operand:SI 5 "arm_hard_register_operand" "")
|
||||
(mem:SI (plus:SI (match_dup 2) (const_int 8))))
|
||||
(set (match_operand:SI 6 "arm_hard_register_operand" "")
|
||||
(mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
|
||||
"TARGET_THUMB && XVECLEN (operands[0], 0) == 5"
|
||||
"ldmia\\t%1!, {%3, %4, %5, %6}"
|
||||
[(set_attr "type" "load4")]
|
||||
)
|
||||
|
||||
(define_insn "*ldmsi_postinc3"
|
||||
[(match_parallel 0 "load_multiple_operation"
|
||||
[(set (match_operand:SI 1 "s_register_operand" "=r")
|
||||
|
@ -5409,6 +5440,24 @@
|
|||
(set_attr "type" "store4")]
|
||||
)
|
||||
|
||||
(define_insn "*stmsi_postinc4_thumb"
|
||||
[(match_parallel 0 "store_multiple_operation"
|
||||
[(set (match_operand:SI 1 "s_register_operand" "=l")
|
||||
(plus:SI (match_operand:SI 2 "s_register_operand" "1")
|
||||
(const_int 16)))
|
||||
(set (mem:SI (match_dup 2))
|
||||
(match_operand:SI 3 "arm_hard_register_operand" ""))
|
||||
(set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
|
||||
(match_operand:SI 4 "arm_hard_register_operand" ""))
|
||||
(set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
|
||||
(match_operand:SI 5 "arm_hard_register_operand" ""))
|
||||
(set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
|
||||
(match_operand:SI 6 "arm_hard_register_operand" ""))])]
|
||||
"TARGET_THUMB && XVECLEN (operands[0], 0) == 5"
|
||||
"stmia\\t%1!, {%3, %4, %5, %6}"
|
||||
[(set_attr "type" "store4")]
|
||||
)
|
||||
|
||||
(define_insn "*stmsi_postinc3"
|
||||
[(match_parallel 0 "store_multiple_operation"
|
||||
[(set (match_operand:SI 1 "s_register_operand" "=r")
|
||||
|
@ -7560,7 +7609,7 @@
|
|||
)
|
||||
|
||||
(define_insn "*call_value_symbol"
|
||||
[(set (match_operand 0 "s_register_operand" "")
|
||||
[(set (match_operand 0 "" "")
|
||||
(call (mem:SI (match_operand:SI 1 "" ""))
|
||||
(match_operand:SI 2 "" "")))
|
||||
(use (match_operand 3 "" ""))
|
||||
|
@ -7589,7 +7638,7 @@
|
|||
)
|
||||
|
||||
(define_insn "*call_value_insn"
|
||||
[(set (match_operand 0 "register_operand" "")
|
||||
[(set (match_operand 0 "" "")
|
||||
(call (mem:SI (match_operand 1 "" ""))
|
||||
(match_operand 2 "" "")))
|
||||
(use (match_operand 3 "" ""))
|
||||
|
@ -7617,7 +7666,7 @@
|
|||
)
|
||||
|
||||
(define_expand "sibcall_value"
|
||||
[(parallel [(set (match_operand 0 "register_operand" "")
|
||||
[(parallel [(set (match_operand 0 "" "")
|
||||
(call (match_operand 1 "memory_operand" "")
|
||||
(match_operand 2 "general_operand" "")))
|
||||
(return)
|
||||
|
@ -7643,7 +7692,7 @@
|
|||
)
|
||||
|
||||
(define_insn "*sibcall_value_insn"
|
||||
[(set (match_operand 0 "s_register_operand" "")
|
||||
[(set (match_operand 0 "" "")
|
||||
(call (mem:SI (match_operand:SI 1 "" "X"))
|
||||
(match_operand 2 "" "")))
|
||||
(return)
|
||||
|
@ -7749,18 +7798,59 @@
|
|||
(const_int 0))
|
||||
(match_operand 1 "" "")
|
||||
(match_operand 2 "" "")])]
|
||||
"TARGET_ARM"
|
||||
"TARGET_EITHER"
|
||||
"
|
||||
{
|
||||
int i;
|
||||
rtx par = gen_rtx_PARALLEL (VOIDmode,
|
||||
rtvec_alloc (XVECLEN (operands[2], 0)));
|
||||
rtx addr = gen_reg_rtx (Pmode);
|
||||
rtx mem;
|
||||
int size = 0;
|
||||
|
||||
emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx));
|
||||
emit_move_insn (addr, XEXP (operands[1], 0));
|
||||
mem = change_address (operands[1], BLKmode, addr);
|
||||
|
||||
for (i = 0; i < XVECLEN (operands[2], 0); i++)
|
||||
{
|
||||
rtx set = XVECEXP (operands[2], 0, i);
|
||||
rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
|
||||
|
||||
emit_move_insn (SET_DEST (set), SET_SRC (set));
|
||||
/* Default code only uses r0 as a return value, but we could
|
||||
be using anything up to 4 registers. */
|
||||
if (REGNO (src) == R0_REGNUM)
|
||||
src = gen_rtx_REG (TImode, R0_REGNUM);
|
||||
|
||||
XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
|
||||
GEN_INT (size));
|
||||
size += GET_MODE_SIZE (GET_MODE (src));
|
||||
}
|
||||
|
||||
emit_call_insn (GEN_CALL_VALUE (par, operands[0], const0_rtx, NULL,
|
||||
const0_rtx));
|
||||
|
||||
size = 0;
|
||||
|
||||
for (i = 0; i < XVECLEN (par, 0); i++)
|
||||
{
|
||||
HOST_WIDE_INT offset = 0;
|
||||
rtx reg = XEXP (XVECEXP (par, 0, i), 0);
|
||||
|
||||
if (size != 0)
|
||||
emit_move_insn (addr, plus_constant (addr, size));
|
||||
|
||||
mem = change_address (mem, GET_MODE (reg), NULL);
|
||||
if (REGNO (reg) == R0_REGNUM)
|
||||
{
|
||||
/* On thumb we have to use a write-back instruction. */
|
||||
emit_insn (arm_gen_store_multiple (R0_REGNUM, 4, addr, TRUE,
|
||||
TARGET_THUMB ? TRUE : FALSE, mem, &offset));
|
||||
size = TARGET_ARM ? 16 : 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
emit_move_insn (mem, reg);
|
||||
size = GET_MODE_SIZE (GET_MODE (reg));
|
||||
}
|
||||
}
|
||||
|
||||
/* The optimizer does not know that the call sets the function value
|
||||
|
@ -7773,6 +7863,55 @@
|
|||
}"
|
||||
)
|
||||
|
||||
(define_expand "untyped_return"
|
||||
[(match_operand:BLK 0 "memory_operand" "")
|
||||
(match_operand 1 "" "")]
|
||||
"TARGET_EITHER"
|
||||
"
|
||||
{
|
||||
int i;
|
||||
rtx addr = gen_reg_rtx (Pmode);
|
||||
rtx mem;
|
||||
int size = 0;
|
||||
|
||||
emit_move_insn (addr, XEXP (operands[0], 0));
|
||||
mem = change_address (operands[0], BLKmode, addr);
|
||||
|
||||
for (i = 0; i < XVECLEN (operands[1], 0); i++)
|
||||
{
|
||||
HOST_WIDE_INT offset = 0;
|
||||
rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
|
||||
|
||||
if (size != 0)
|
||||
emit_move_insn (addr, plus_constant (addr, size));
|
||||
|
||||
mem = change_address (mem, GET_MODE (reg), NULL);
|
||||
if (REGNO (reg) == R0_REGNUM)
|
||||
{
|
||||
/* On thumb we have to use a write-back instruction. */
|
||||
emit_insn (arm_gen_load_multiple (R0_REGNUM, 4, addr, TRUE,
|
||||
TARGET_THUMB ? TRUE : FALSE, mem, &offset));
|
||||
size = TARGET_ARM ? 16 : 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
emit_move_insn (reg, mem);
|
||||
size = GET_MODE_SIZE (GET_MODE (reg));
|
||||
}
|
||||
}
|
||||
|
||||
/* Emit USE insns before the return. */
|
||||
for (i = 0; i < XVECLEN (operands[1], 0); i++)
|
||||
emit_insn (gen_rtx_USE (VOIDmode,
|
||||
SET_DEST (XVECEXP (operands[1], 0, i))));
|
||||
|
||||
/* Construct the return. */
|
||||
expand_naked_return ();
|
||||
|
||||
DONE;
|
||||
}"
|
||||
)
|
||||
|
||||
;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
|
||||
;; all of memory. This blocks insns from being moved across this point.
|
||||
|
||||
|
|
|
@ -581,33 +581,31 @@
|
|||
(set_attr "neg_pool_range" "*,*,*,*,1008,*,*,1008,*,*,*")]
|
||||
)
|
||||
|
||||
;; Saving and restoring the floating point registers in the prologue should
|
||||
;; be done in XFmode, even though we don't support that for anything else
|
||||
;; (Well, strictly it's 'internal representation', but that's effectively
|
||||
;; XFmode).
|
||||
|
||||
;; We treat XFmode as meaning 'internal format'. It's the right size and we
|
||||
;; don't use it for anything else. We only support moving between FPA
|
||||
;; registers and moving an FPA register to/from memory.
|
||||
(define_insn "*movxf_fpa"
|
||||
[(set (match_operand:XF 0 "nonimmediate_operand" "=f,f,f,m,f,r,r")
|
||||
(match_operand:XF 1 "general_operand" "fG,H,m,f,r,f,r"))]
|
||||
"TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA && reload_completed"
|
||||
[(set (match_operand:XF 0 "nonimmediate_operand" "=f,f,m")
|
||||
(match_operand:XF 1 "general_operand" "f,m,f"))]
|
||||
"TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA
|
||||
&& (register_operand (operands[0], XFmode)
|
||||
|| register_operand (operands[1], XFmode))"
|
||||
"*
|
||||
switch (which_alternative)
|
||||
{
|
||||
default:
|
||||
case 0: return \"mvf%?e\\t%0, %1\";
|
||||
case 1: return \"mnf%?e\\t%0, #%N1\";
|
||||
case 2: return \"ldf%?e\\t%0, %1\";
|
||||
case 3: return \"stf%?e\\t%1, %0\";
|
||||
case 4: return output_mov_long_double_fpa_from_arm (operands);
|
||||
case 5: return output_mov_long_double_arm_from_fpa (operands);
|
||||
case 6: return output_mov_long_double_arm_from_arm (operands);
|
||||
case 1: if (arm_fpu_arch == FPUTYPE_FPA_EMU2)
|
||||
return \"ldf%?e\\t%0, %1\";
|
||||
return \"lfm%?\\t%0, 1, %1\";
|
||||
case 2: if (arm_fpu_arch == FPUTYPE_FPA_EMU2)
|
||||
return \"stf%?e\\t%1, %0\";
|
||||
return \"sfm%?\\t%1, 1, %0\";
|
||||
}
|
||||
"
|
||||
[(set_attr "length" "4,4,4,4,8,8,12")
|
||||
[(set_attr "length" "4,4,4")
|
||||
(set_attr "predicable" "yes")
|
||||
(set_attr "type" "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*")
|
||||
(set_attr "pool_range" "*,*,1024,*,*,*,*")
|
||||
(set_attr "neg_pool_range" "*,*,1004,*,*,*,*")]
|
||||
(set_attr "type" "ffarith,f_load,f_store")]
|
||||
)
|
||||
|
||||
(define_insn "*cmpsf_fpa"
|
||||
|
@ -749,4 +747,3 @@
|
|||
(set_attr "type" "ffarith")
|
||||
(set_attr "conds" "use")]
|
||||
)
|
||||
|
||||
|
|
Loading…
Reference in New Issue