From: rearnsha Date: Wed, 16 Feb 2005 21:57:10 +0000 (+0000) Subject: * PR target/19162 X-Git-Url: http://git.sourceforge.jp/view?p=pf3gnuchains%2Fgcc-fork.git;a=commitdiff_plain;h=ccd90aaa3dbf50d8b05431904eaf6b3ea2f7d254 * 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@95119 138bc75d-0d04-0410-961f-82ee72b054a4 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 2864e13fe5b..379b422014a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,18 @@ +2005-02-16 Richard Earnshaw + + * 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 * config.gcc (powerpc-*-darwin*): Use fragment for Darwin 8 or later. diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h index 5c040bda1ce..e7811ca8c8e 100644 --- a/gcc/config/arm/arm-protos.h +++ b/gcc/config/arm/arm-protos.h @@ -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); diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index 95fe7fe48f1..7c614fd5396 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -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 diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h index 5955d3ced66..2db95373c9f 100644 --- a/gcc/config/arm/arm.h +++ b/gcc/config/arm/arm.h @@ -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. */ diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md index 17b88a64a77..f25846675ee 100644 --- a/gcc/config/arm/arm.md +++ b/gcc/config/arm/arm.md @@ -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. diff --git a/gcc/config/arm/fpa.md b/gcc/config/arm/fpa.md index 886bba151e3..54e1319097d 100644 --- a/gcc/config/arm/fpa.md +++ b/gcc/config/arm/fpa.md @@ -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")] ) -