* config/arm/arm.c (arm_attr_length_move_neon): New.
authorjiez <jiez@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 3 Jul 2010 16:49:05 +0000 (16:49 +0000)
committerjiez <jiez@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 3 Jul 2010 16:49:05 +0000 (16:49 +0000)
* config/arm/arm-protos.h (arm_attr_length_move_neon): Declare.
* config/arm/neon.md (define_mode_attr V_slen): Remove.
(neon_mov<mode> for VSTRUCT): Use arm_attr_length_move_neon
to compute length attribute.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@161776 138bc75d-0d04-0410-961f-82ee72b054a4

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

index 8aceaf7..f20eccd 100644 (file)
@@ -1,5 +1,13 @@
 2010-07-03  Jie Zhang  <jie@codesourcery.com>
 
+       * config/arm/arm.c (arm_attr_length_move_neon): New.
+       * config/arm/arm-protos.h (arm_attr_length_move_neon): Declare.
+       * config/arm/neon.md (define_mode_attr V_slen): Remove.
+       (neon_mov<mode> for VSTRUCT): Use arm_attr_length_move_neon
+       to compute length attribute.
+
+2010-07-03  Jie Zhang  <jie@codesourcery.com>
+
        * config/arm/vfp.md (*push_multi_vfp): Use vfp_register_operand
        as predicate for operand 1 and remove its constraint.
        * config/arm/predicates.md (vfp_register_operand): New.
index 40d0f93..11e2e28 100644 (file)
@@ -131,6 +131,7 @@ extern const char *output_move_double (rtx *);
 extern const char *output_move_quad (rtx *);
 extern const char *output_move_vfp (rtx *operands);
 extern const char *output_move_neon (rtx *operands);
+extern int arm_attr_length_move_neon (rtx);
 extern const char *output_add_immediate (rtx *);
 extern const char *arithmetic_instr (rtx, int);
 extern void output_ascii_pseudo_op (FILE *, const unsigned char *, int);
index f59c1fc..85d1e8c 100644 (file)
@@ -12859,6 +12859,57 @@ output_move_neon (rtx *operands)
   return "";
 }
 
+/* Compute and return the length of neon_mov<mode>, where <mode> is
+   one of VSTRUCT modes: EI, OI, CI or XI.  */
+int
+arm_attr_length_move_neon (rtx insn)
+{
+  rtx reg, mem, addr;
+  int regno, load;
+  enum machine_mode mode;
+
+  extract_insn_cached (insn);
+
+  if (REG_P (recog_data.operand[0]) && REG_P (recog_data.operand[1]))
+    {
+      mode = GET_MODE (recog_data.operand[0]);
+      switch (mode)
+       {
+       case EImode:
+       case OImode:
+         return 8;
+       case CImode:
+         return 12;
+       case XImode:
+         return 16;
+       default:
+         gcc_unreachable ();
+       }
+    }
+
+  load = REG_P (recog_data.operand[0]);
+  reg = recog_data.operand[!load];
+  mem = recog_data.operand[load];
+
+  gcc_assert (MEM_P (mem));
+
+  mode = GET_MODE (reg);
+  regno = REGNO (reg);
+  addr = XEXP (mem, 0);
+
+  /* Strip off const from addresses like (const (plus (...))).  */
+  if (GET_CODE (addr) == CONST && GET_CODE (XEXP (addr, 0)) == PLUS)
+    addr = XEXP (addr, 0);
+
+  if (GET_CODE (addr) == LABEL_REF || GET_CODE (addr) == PLUS)
+    {
+      int insns = HARD_REGNO_NREGS (REGNO (reg), mode) / 2;
+      return insns * 4;
+    }
+  else
+    return 4;
+}
+
 /* Output an ADD r, s, #n where n may be too big for one instruction.
    If adding zero to one register, output nothing.  */
 const char *
index 08b6463..15f347c 100644 (file)
 ;; Opaque structure types wider than TImode.
 (define_mode_iterator VSTRUCT [EI OI CI XI])
 
-;; Number of instructions needed to load/store struct elements. FIXME!
-(define_mode_attr V_slen [(EI "2") (OI "2") (CI "3") (XI "4")])
-
 ;; Opaque structure types used in table lookups (except vtbl1/vtbx1).
 (define_mode_iterator VTAB [TI EI OI])
 
     }
 }
   [(set_attr "neon_type" "neon_int_1,neon_stm_2,neon_ldm_2")
-   (set_attr "length" "<V_slen>,<V_slen>,<V_slen>")])
+   (set (attr "length") (symbol_ref "arm_attr_length_move_neon (insn)"))])
 
 (define_split
   [(set (match_operand:EI 0 "s_register_operand" "")