OSDN Git Service

* PR target/19162
authorrearnsha <rearnsha@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 16 Feb 2005 21:57:10 +0000 (21:57 +0000)
committerrearnsha <rearnsha@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 16 Feb 2005 21:57:10 +0000 (21:57 +0000)
* 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

gcc/ChangeLog
gcc/config/arm/arm-protos.h
gcc/config/arm/arm.c
gcc/config/arm/arm.h
gcc/config/arm/arm.md
gcc/config/arm/fpa.md

index 2864e13..379b422 100644 (file)
@@ -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.
index 5c040bd..e7811ca 100644 (file)
@@ -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);
index 95fe7fe..7c614fd 100644 (file)
@@ -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
index 5955d3c..2db9537 100644 (file)
@@ -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.  */
index 17b88a6..f258466 100644 (file)
 
 ;; 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
    (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" "")
    (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")
    (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")
 )
 
 (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 "" ""))
 )
 
 (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 "" ""))
 )
 
 (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)
 )
 
 (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)
                    (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
   }"
 )
 
+(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.
 
index 886bba1..54e1319 100644 (file)
    (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"
    (set_attr "type" "ffarith")
    (set_attr "conds" "use")]
 )
-