]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
config.gcc (with_fpu): Allow --with-fpu=vfp3.
authorJulian Brown <julian@codesourcery.com>
Tue, 3 Jul 2007 19:42:36 +0000 (19:42 +0000)
committerJulian Brown <jules@gcc.gnu.org>
Tue, 3 Jul 2007 19:42:36 +0000 (19:42 +0000)
gcc/
* config.gcc (with_fpu): Allow --with-fpu=vfp3.
* config/arm/aout.h (REGISTER_NAMES): Add D16-D31.
* config/arm/aof.h (REGISTER_NAMES): Add D16-D31.
* config/arm/arm.c (FL_VFPV3): New flag for VFPv3 processor
capability.
(all_fpus): Add FPUTYPE_VFP3.
(fp_model_for_fpu): Add VFPv3 field.
(arm_rtx_costs_1): Give cost to VFPv3 constants.
(vfp3_const_double_index): New function. Return integer index of
VFPv3 constant suitable for fconst[sd] insns, or -1 if constant
isn't suitable.
(vfp3_const_double_rtx): New function. True if VFPv3 is enabled
and argument represents a valid RTX for a VFPv3 constant.
(vfp_output_fldmd): Split fldmd with > 16 registers in the list into
two instructions.
(vfp_emit_fstmd): Similar, for fstmd.
(arm_print_operand): Implement new code 'G' for VFPv3 floating-point
constants, represented as integer indices.
(arm_hard_regno_mode_ok): Use VFP_REGNO_OK_FOR_SINGLE,
VFP_REGNO_OK_FOR_DOUBLE macros.
(arm_regno_class): Handle VFPv3 d0-d7, low, high register split.
(arm_file_start): Set float-abi attribute for VFPv3, and output
correct ".fpu" assembler directive.
(arm_dbx_register_numbering): Add FIXME.
* config/arm/arm.h (TARGET_VFP3): New macro. Target supports VFPv3.
(fputype): Add FPUTYPE_VFP3.
(FIXED_REGISTERS): Add 32 registers for D16-D31.
(CALL_USED_REGISTERS): Likewise.
(CONDITIONAL_REGISTER_USAGE): Add note about conditional definition
of LAST_VFP_REGNUM. Make D16-D31 caller-saved, if present.
(LAST_VFP_REGNUM): Extend available VFP registers for VFPv3.
(D7_VFP_REGNUM): New.
(LAST_LO_VFP_REGNUM, FIRST_HI_VFP_REGNUM, LAST_HI_VFP_REGNUM)
(VFP_REGNO_OK_FOR_SINGLE, VFP_REGNO_OK_FOR_SINGLE)
(VFP_REGNO_OK_FOR_DOUBLE): Define new macros.
(FIRST_PSEUDO_REGISTER): Shift up to 128 to accommodate VFPv3.
(REG_ALLOC_ORDER): Adjust for VFPv3.
(reg_class): Add VFP_D0_D7_REGS, VFP_LO_REGS, VFP_HI_REGS.
(REG_CLASS_NAMES): Add entries corresponding to VFP_D0_D7_REGS,
VFP_LO_REGS, VFP_HI_REGS.
(REG_CLASS_CONTENTS): Likewise. Extend contents for VFP_REGS.
(IS_VFP_CLASS): Define macro.
(SECONDARY_OUTPUT_RELOAD_CLASS, SECONDARY_INPUT_RELOAD_CLASS): Use
IS_VFP_CLASS.
(REGISTER_MOVE_COST): Likewise.
* config/arm/arm-protos.h (vfp3_const_double_rtx): Add prototype.
* config/arm/vfp.md (VFPCC_REGNUM): Redefine as 127.
(*arm_movsi_vfp, *thumb2_movsi_vfp, *movsfcc_vfp)
(*thumb2_movsfcc_vfp, *abssf2_vfp, *negsf2_vfp, *addsf3_vfp)
(*subsf3_vfp, *divsf_vfp, *mulsf_vfp, *mulsf3negsf_vfp)
(*mulsf3addsf_vfp, *mulsf3subsf_vfp, *mulsf3negsfaddsf_vfp)
(*extendsfdf2_vfp, *truncdfsf2_vfp, *truncsisf2_vfp)
(*truncsidf2_vfp, fixuns_truncsfsi2, fixuns_truncdfsi2)
(*floatsisf2_vfp, *floatsidf2_vfp, floatunssisf2)
(floatunssidf2, *sqrtsf2_vfp, *cmpsf_split_vfp)
(*cmpsf_trap_split_vfp, *cmpsf_vfp, *cmpsf_trap_vfp): Use 't'
where appropriate for single-word registers.
(*movsf_vfp, *thumb2_movsf_vfp, *movdf_vfp, *thumb2_movdf_vfp):
As above. Fix type attributes.
* config/arm/constraints.md (register_contraint "t"): Define.
(register_constraint "w"): Change to D0-D15, or D0-D31 for
VFPv3/NEON.
(register_constraint "x"): Define.
(constraint "Dv"): Define.

From-SVN: r126272

gcc/ChangeLog
gcc/config.gcc
gcc/config/arm/aof.h
gcc/config/arm/aout.h
gcc/config/arm/arm-protos.h
gcc/config/arm/arm.c
gcc/config/arm/arm.h
gcc/config/arm/constraints.md
gcc/config/arm/vfp.md

index f9413cd1bd0dbafc199e11f15294f4df1b2408cb..4bf74fedf12f5b8e18a39f9baf7cf12168e9d2be 100644 (file)
@@ -1,3 +1,70 @@
+2007-07-03  Julian Brown  <julian@codesourcery.com>
+
+       * config.gcc (with_fpu): Allow --with-fpu=vfp3.
+       * config/arm/aout.h (REGISTER_NAMES): Add D16-D31.
+       * config/arm/aof.h (REGISTER_NAMES): Add D16-D31.
+       * config/arm/arm.c (FL_VFPV3): New flag for VFPv3 processor
+       capability.
+       (all_fpus): Add FPUTYPE_VFP3.
+       (fp_model_for_fpu): Add VFPv3 field.
+       (arm_rtx_costs_1): Give cost to VFPv3 constants.
+       (vfp3_const_double_index): New function. Return integer index of
+       VFPv3 constant suitable for fconst[sd] insns, or -1 if constant
+       isn't suitable.
+       (vfp3_const_double_rtx): New function. True if VFPv3 is enabled
+       and argument represents a valid RTX for a VFPv3 constant.
+       (vfp_output_fldmd): Split fldmd with > 16 registers in the list into
+       two instructions.
+       (vfp_emit_fstmd): Similar, for fstmd.
+       (arm_print_operand): Implement new code 'G' for VFPv3 floating-point
+       constants, represented as integer indices.
+       (arm_hard_regno_mode_ok): Use VFP_REGNO_OK_FOR_SINGLE,
+       VFP_REGNO_OK_FOR_DOUBLE macros.
+       (arm_regno_class): Handle VFPv3 d0-d7, low, high register split.
+       (arm_file_start): Set float-abi attribute for VFPv3, and output
+       correct ".fpu" assembler directive.
+       (arm_dbx_register_numbering): Add FIXME.
+       * config/arm/arm.h (TARGET_VFP3): New macro. Target supports VFPv3.
+       (fputype): Add FPUTYPE_VFP3.
+       (FIXED_REGISTERS): Add 32 registers for D16-D31.
+       (CALL_USED_REGISTERS): Likewise.
+       (CONDITIONAL_REGISTER_USAGE): Add note about conditional definition
+       of LAST_VFP_REGNUM. Make D16-D31 caller-saved, if present.
+       (LAST_VFP_REGNUM): Extend available VFP registers for VFPv3.
+       (D7_VFP_REGNUM): New.
+       (LAST_LO_VFP_REGNUM, FIRST_HI_VFP_REGNUM, LAST_HI_VFP_REGNUM)
+       (VFP_REGNO_OK_FOR_SINGLE, VFP_REGNO_OK_FOR_SINGLE)
+       (VFP_REGNO_OK_FOR_DOUBLE): Define new macros.
+       (FIRST_PSEUDO_REGISTER): Shift up to 128 to accommodate VFPv3.
+       (REG_ALLOC_ORDER): Adjust for VFPv3.
+       (reg_class): Add VFP_D0_D7_REGS, VFP_LO_REGS, VFP_HI_REGS.
+       (REG_CLASS_NAMES): Add entries corresponding to VFP_D0_D7_REGS,
+       VFP_LO_REGS, VFP_HI_REGS.
+       (REG_CLASS_CONTENTS): Likewise. Extend contents for VFP_REGS.
+       (IS_VFP_CLASS): Define macro.
+       (SECONDARY_OUTPUT_RELOAD_CLASS, SECONDARY_INPUT_RELOAD_CLASS): Use
+       IS_VFP_CLASS.
+       (REGISTER_MOVE_COST): Likewise.
+       * config/arm/arm-protos.h (vfp3_const_double_rtx): Add prototype.
+       * config/arm/vfp.md (VFPCC_REGNUM): Redefine as 127.
+       (*arm_movsi_vfp, *thumb2_movsi_vfp, *movsfcc_vfp)
+       (*thumb2_movsfcc_vfp, *abssf2_vfp, *negsf2_vfp, *addsf3_vfp)
+       (*subsf3_vfp, *divsf_vfp, *mulsf_vfp, *mulsf3negsf_vfp)
+       (*mulsf3addsf_vfp, *mulsf3subsf_vfp, *mulsf3negsfaddsf_vfp)
+       (*extendsfdf2_vfp, *truncdfsf2_vfp, *truncsisf2_vfp)
+       (*truncsidf2_vfp, fixuns_truncsfsi2, fixuns_truncdfsi2)
+       (*floatsisf2_vfp, *floatsidf2_vfp, floatunssisf2)
+       (floatunssidf2, *sqrtsf2_vfp, *cmpsf_split_vfp)
+       (*cmpsf_trap_split_vfp, *cmpsf_vfp, *cmpsf_trap_vfp): Use 't'
+       where appropriate for single-word registers.
+       (*movsf_vfp, *thumb2_movsf_vfp, *movdf_vfp, *thumb2_movdf_vfp):
+       As above. Fix type attributes.
+       * config/arm/constraints.md (register_contraint "t"): Define.
+       (register_constraint "w"): Change to D0-D15, or D0-D31 for
+       VFPv3/NEON.
+       (register_constraint "x"): Define.
+       (constraint "Dv"): Define.
+
 2007-07-03  Geoffrey Keating  <geoffk@apple.com>
 
        * tree.h (DECL_ALIGN): Prevent use on a FUNCTION_DECL.
index d3358c3fad430ece1de87ece073a3ada42a08b0b..66c3dd9c875bde0551414c9d148062da8c482e6f 100644 (file)
@@ -2835,7 +2835,7 @@ case "${target}" in
 
                case "$with_fpu" in
                "" \
-               | fpa | fpe2 | fpe3 | maverick | vfp )
+               | fpa | fpe2 | fpe3 | maverick | vfp | vfp3 )
                        # OK
                        ;;
                *)
index e6694dc1bc74571715a8ced40a3b655381a5523b..71d87a520dbd891c924068e050378e6a02f49485 100644 (file)
@@ -187,7 +187,10 @@ do {                                       \
 #define CTORS_SECTION_ASM_OP "\tAREA\t|C$$gnu_ctorsvec|, DATA, READONLY"
 #define DTORS_SECTION_ASM_OP "\tAREA\t|C$$gnu_dtorsvec|, DATA, READONLY"
 
-/* Output of Assembler Instructions.  */
+/* Output of Assembler Instructions.  Note that the ?xx registers are
+   there so that VFPv3/NEON registers D16-D31 have the same spacing as D0-D15
+   (each of which is overlaid on two S registers), although there are no
+   actual single-precision registers which correspond to D16-D31.  */
 
 #define REGISTER_NAMES                         \
 {                                              \
@@ -210,7 +213,11 @@ do {                                       \
   "s0",  "s1",  "s2",  "s3",  "s4",  "s5",  "s6",  "s7",  \
   "s8",  "s9",  "s10", "s11", "s12", "s13", "s14", "s15", \
   "s16", "s17", "s18", "s19", "s20", "s21", "s22", "s23", \
-  "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31",  \
+  "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31", \
+  "d16", "?16", "d17", "?17", "d18", "?18", "d19", "?19", \
+  "d20", "?20", "d21", "?21", "d22", "?22", "d23", "?23", \
+  "d24", "?24", "d25", "?25", "d26", "?26", "d27", "?27", \
+  "d28", "?28", "d29", "?29", "d30", "?30", "d31", "?31", \
   "vfpcc"                                      \
 }
 
index b91031814bbf95a3023c20a0a6ac33fd73164016..a47859aa4cf51fb0b1c1548b40f4a5159642bd59 100644 (file)
 #define LOCAL_LABEL_PREFIX     ""
 #endif
 
-/* The assembler's names for the registers.  */
+/* The assembler's names for the registers.  Note that the ?xx registers are
+   there so that VFPv3/NEON registers D16-D31 have the same spacing as D0-D15
+   (each of which is overlaid on two S registers), although there are no
+   actual single-precision registers which correspond to D16-D31.  */
 #ifndef REGISTER_NAMES
 #define REGISTER_NAMES                            \
 {                                                 \
   "s8",  "s9",  "s10", "s11", "s12", "s13", "s14", "s15", \
   "s16", "s17", "s18", "s19", "s20", "s21", "s22", "s23", \
   "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31", \
+  "d16", "?16", "d17", "?17", "d18", "?18", "d19", "?19", \
+  "d20", "?20", "d21", "?21", "d22", "?22", "d23", "?23", \
+  "d24", "?24", "d25", "?25", "d26", "?26", "d27", "?27", \
+  "d28", "?28", "d29", "?29", "d30", "?30", "d31", "?31", \
   "vfpcc"                                         \
 }
 #endif
index ea812711af103f16b1481c96d281465620b35a7e..3f928b853a8f09bcef1a43572a50176f563880ce 100644 (file)
@@ -67,6 +67,7 @@ extern rtx thumb_legitimize_reload_address (rtx *, enum machine_mode, int, int,
                                            int);
 extern int arm_const_double_rtx (rtx);
 extern int neg_const_double_rtx_ok_for_fpa (rtx);
+extern int vfp3_const_double_rtx (rtx);
 extern enum reg_class coproc_secondary_reload_class (enum machine_mode, rtx,
                                                     bool);
 extern bool arm_tls_referenced_p (rtx);
index df08c467b1611aef785fe39ebd46bf1202623914..6c9a69594baa3887d050aec8ae3e35e1368e6646 100644 (file)
@@ -457,6 +457,7 @@ static int thumb_call_reg_needed;
 #define FL_NOTM              (1 << 17)       /* Instructions not present in the 'M'
                                         profile.  */
 #define FL_DIV       (1 << 18)       /* Hardware divide.  */
+#define FL_VFPV3      (1 << 19)       /* Vector Floating Point V3.  */
 
 #define FL_IWMMXT     (1 << 29)              /* XScale v2 or "Intel Wireless MMX technology".  */
 
@@ -700,7 +701,8 @@ static const struct fpu_desc all_fpus[] =
   {"fpe2",     FPUTYPE_FPA_EMU2},
   {"fpe3",     FPUTYPE_FPA_EMU2},
   {"maverick", FPUTYPE_MAVERICK},
-  {"vfp",      FPUTYPE_VFP}
+  {"vfp",      FPUTYPE_VFP},
+  {"vfp3",     FPUTYPE_VFP3},
 };
 
 
@@ -715,7 +717,8 @@ static const enum fputype fp_model_for_fpu[] =
   ARM_FP_MODEL_FPA,            /* FPUTYPE_FPA_EMU2  */
   ARM_FP_MODEL_FPA,            /* FPUTYPE_FPA_EMU3  */
   ARM_FP_MODEL_MAVERICK,       /* FPUTYPE_MAVERICK  */
-  ARM_FP_MODEL_VFP             /* FPUTYPE_VFP  */
+  ARM_FP_MODEL_VFP,            /* FPUTYPE_VFP  */
+  ARM_FP_MODEL_VFP             /* FPUTYPE_VFP3  */
 };
 
 
@@ -4950,7 +4953,7 @@ arm_rtx_costs_1 (rtx x, enum rtx_code code, enum rtx_code outer)
       return 6;
 
     case CONST_DOUBLE:
-      if (arm_const_double_rtx (x))
+      if (arm_const_double_rtx (x) || vfp3_const_double_rtx (x))
        return outer == SET ? 2 : -1;
       else if ((outer == COMPARE || outer == PLUS)
               && neg_const_double_rtx_ok_for_fpa (x))
@@ -5649,6 +5652,108 @@ neg_const_double_rtx_ok_for_fpa (rtx x)
 
   return 0;
 }
+
+
+/* VFPv3 has a fairly wide range of representable immediates, formed from
+   "quarter-precision" floating-point values. These can be evaluated using this
+   formula (with ^ for exponentiation):
+
+     -1^s * n * 2^-r
+
+   Where 's' is a sign bit (0/1), 'n' and 'r' are integers such that
+   16 <= n <= 31 and 0 <= r <= 7.
+
+   These values are mapped onto an 8-bit integer ABCDEFGH s.t.
+
+     - A (most-significant) is the sign bit.
+     - BCD are the exponent (encoded as r XOR 3).
+     - EFGH are the mantissa (encoded as n - 16).
+*/
+
+/* Return an integer index for a VFPv3 immediate operand X suitable for the
+   fconst[sd] instruction, or -1 if X isn't suitable.  */
+static int
+vfp3_const_double_index (rtx x)
+{
+  REAL_VALUE_TYPE r, m;
+  int sign, exponent;
+  unsigned HOST_WIDE_INT mantissa, mant_hi;
+  unsigned HOST_WIDE_INT mask;
+  int point_pos = 2 * HOST_BITS_PER_WIDE_INT - 1;
+
+  if (!TARGET_VFP3 || GET_CODE (x) != CONST_DOUBLE)
+    return -1;
+
+  REAL_VALUE_FROM_CONST_DOUBLE (r, x);
+
+  /* We can't represent these things, so detect them first.  */
+  if (REAL_VALUE_ISINF (r) || REAL_VALUE_ISNAN (r) || REAL_VALUE_MINUS_ZERO (r))
+    return -1;
+
+  /* Extract sign, exponent and mantissa.  */
+  sign = REAL_VALUE_NEGATIVE (r) ? 1 : 0;
+  r = REAL_VALUE_ABS (r);
+  exponent = REAL_EXP (&r);
+  /* For the mantissa, we expand into two HOST_WIDE_INTS, apart from the
+     highest (sign) bit, with a fixed binary point at bit point_pos.
+     WARNING: If there's ever a VFP version which uses more than 2 * H_W_I - 1
+     bits for the mantissa, this may fail (low bits would be lost).  */
+  real_ldexp (&m, &r, point_pos - exponent);
+  REAL_VALUE_TO_INT (&mantissa, &mant_hi, m);
+
+  /* If there are bits set in the low part of the mantissa, we can't
+     represent this value.  */
+  if (mantissa != 0)
+    return -1;
+
+  /* Now make it so that mantissa contains the most-significant bits, and move
+     the point_pos to indicate that the least-significant bits have been
+     discarded.  */
+  point_pos -= HOST_BITS_PER_WIDE_INT;
+  mantissa = mant_hi;
+
+  /* We can permit four significant bits of mantissa only, plus a high bit
+     which is always 1.  */
+  mask = ((unsigned HOST_WIDE_INT)1 << (point_pos - 5)) - 1;
+  if ((mantissa & mask) != 0)
+    return -1;
+
+  /* Now we know the mantissa is in range, chop off the unneeded bits.  */
+  mantissa >>= point_pos - 5;
+
+  /* The mantissa may be zero. Disallow that case. (It's possible to load the
+     floating-point immediate zero with Neon using an integer-zero load, but
+     that case is handled elsewhere.)  */
+  if (mantissa == 0)
+    return -1;
+
+  gcc_assert (mantissa >= 16 && mantissa <= 31);
+
+  /* The value of 5 here would be 4 if GCC used IEEE754-like encoding (where
+     normalised significands are in the range [1, 2). (Our mantissa is shifted
+     left 4 places at this point relative to normalised IEEE754 values).  GCC
+     internally uses [0.5, 1) (see real.c), so the exponent returned from
+     REAL_EXP must be altered.  */
+  exponent = 5 - exponent;
+
+  if (exponent < 0 || exponent > 7)
+    return -1;
+
+  /* Sign, mantissa and exponent are now in the correct form to plug into the
+     formulae described in the comment above.  */
+  return (sign << 7) | ((exponent ^ 3) << 4) | (mantissa - 16);
+}
+
+/* Return TRUE if rtx X is a valid immediate VFPv3 constant.  */
+int
+vfp3_const_double_rtx (rtx x)
+{
+  if (!TARGET_VFP3)
+    return 0;
+
+  return vfp3_const_double_index (x) != -1;
+}
+
 \f
 /* Predicates for `match_operand' and `match_operator'.  */
 
@@ -8808,6 +8913,15 @@ vfp_output_fldmd (FILE * stream, unsigned int base, int reg, int count)
       count++;
     }
 
+  /* FLDMD may not load more than 16 doubleword registers at a time. Split the
+     load into multiple parts if we have to handle more than 16 registers.  */
+  if (count > 16)
+    {
+      vfp_output_fldmd (stream, base, reg, 16);
+      vfp_output_fldmd (stream, base, reg + 16, count - 16);
+      return;
+    }
+
   fputc ('\t', stream);
   asm_fprintf (stream, "fldmfdd\t%r!, {", base);
 
@@ -8870,6 +8984,19 @@ vfp_emit_fstmd (int base_reg, int count)
       count++;
     }
 
+  /* FSTMD may not store more than 16 doubleword registers at once.  Split
+     larger stores into multiple parts (up to a maximum of two, in
+     practice).  */
+  if (count > 16)
+    {
+      int saved;
+      /* NOTE: base_reg is an internal register number, so each D register
+         counts as 2.  */
+      saved = vfp_emit_fstmd (base_reg + 32, count - 16);
+      saved += vfp_emit_fstmd (base_reg, 16);
+      return saved;
+    }
+
   par = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count));
   dwarf = gen_rtx_SEQUENCE (VOIDmode, rtvec_alloc (count + 1));
 
@@ -11982,6 +12109,16 @@ arm_print_operand (FILE *stream, rtx x, int code)
       }
       return;
 
+    /* Print a VFPv3 floating-point constant, represented as an integer
+       index.  */
+    case 'G':
+      {
+        int index = vfp3_const_double_index (x);
+       gcc_assert (index != -1);
+       fprintf (stream, "%d", index);
+      }
+      return;
+
     default:
       if (x == 0)
        {
@@ -12761,11 +12898,10 @@ arm_hard_regno_mode_ok (unsigned int regno, enum machine_mode mode)
       && IS_VFP_REGNUM (regno))
     {
       if (mode == SFmode || mode == SImode)
-       return TRUE;
+       return VFP_REGNO_OK_FOR_SINGLE (regno);
 
-      /* DFmode values are only valid in even register pairs.  */
       if (mode == DFmode)
-       return ((regno - FIRST_VFP_REGNUM) & 1) == 0;
+       return VFP_REGNO_OK_FOR_DOUBLE (regno);
       return FALSE;
     }
 
@@ -12828,7 +12964,14 @@ arm_regno_class (int regno)
     return CIRRUS_REGS;
 
   if (IS_VFP_REGNUM (regno))
-    return VFP_REGS;
+    {
+      if (regno <= D7_VFP_REGNUM)
+       return VFP_D0_D7_REGS;
+      else if (regno <= LAST_LO_VFP_REGNUM)
+        return VFP_LO_REGS;
+      else
+        return VFP_HI_REGS;
+    }
 
   if (IS_IWMMXT_REGNUM (regno))
     return IWMMXT_REGS;
@@ -15270,6 +15413,7 @@ arm_file_start (void)
        }
       else
        {
+         int set_float_abi_attributes = 0;
          switch (arm_fpu_arch)
            {
            case FPUTYPE_FPA:
@@ -15285,15 +15429,23 @@ arm_file_start (void)
              fpu_name = "maverick";
              break;
            case FPUTYPE_VFP:
-             if (TARGET_HARD_FLOAT)
-               asm_fprintf (asm_out_file, "\t.eabi_attribute 27, 3\n");
-             if (TARGET_HARD_FLOAT_ABI)
-               asm_fprintf (asm_out_file, "\t.eabi_attribute 28, 1\n");
              fpu_name = "vfp";
+             set_float_abi_attributes = 1;
+             break;
+           case FPUTYPE_VFP3:
+             fpu_name = "vfp3";
+             set_float_abi_attributes = 1;
              break;
            default:
              abort();
            }
+         if (set_float_abi_attributes)
+           {
+             if (TARGET_HARD_FLOAT)
+               asm_fprintf (asm_out_file, "\t.eabi_attribute 27, 3\n");
+             if (TARGET_HARD_FLOAT_ABI)
+               asm_fprintf (asm_out_file, "\t.eabi_attribute 28, 1\n");
+           }
        }
       asm_fprintf (asm_out_file, "\t.fpu %s\n", fpu_name);
 
@@ -16172,6 +16324,7 @@ arm_dbx_register_number (unsigned int regno)
   if (IS_FPA_REGNUM (regno))
     return (TARGET_AAPCS_BASED ? 96 : 16) + regno - FIRST_FPA_REGNUM;
 
+  /* FIXME: VFPv3 register numbering.  */
   if (IS_VFP_REGNUM (regno))
     return 64 + regno - FIRST_VFP_REGNUM;
 
index 67fa99f22a540f0fb1390facc991b1c5c9f4954c..8aa88ab35a232fe75012311eab21cfc7ccf4c545 100644 (file)
@@ -206,6 +206,11 @@ extern GTY(()) rtx aof_pic_label;
 /* 32-bit Thumb-2 code.  */
 #define TARGET_THUMB2                  (TARGET_THUMB && arm_arch_thumb2)
 
+/* FPU is VFPv3 (with twice the number of D registers).  Setting the FPU to
+   Neon automatically enables VFPv3 too.  */
+#define TARGET_VFP3 (arm_fp_model == ARM_FP_MODEL_VFP \
+                    && (arm_fpu_arch == FPUTYPE_VFP3))
+
 /* "DSP" multiply instructions, eg. SMULxy.  */
 #define TARGET_DSP_MULTIPLY \
   (TARGET_32BIT && arm_arch5e && arm_arch_notm)
@@ -275,7 +280,9 @@ enum fputype
   /* Cirrus Maverick floating point co-processor.  */
   FPUTYPE_MAVERICK,
   /* VFP.  */
-  FPUTYPE_VFP
+  FPUTYPE_VFP,
+  /* VFPv3.  */
+  FPUTYPE_VFP3
 };
 
 /* Recast the floating point class to be the floating point attribute.  */
@@ -643,6 +650,10 @@ extern int arm_structure_size_boundary;
   1,1,1,1,1,1,1,1,     \
   1,1,1,1,1,1,1,1,     \
   1,1,1,1,1,1,1,1,     \
+  1,1,1,1,1,1,1,1,     \
+  1,1,1,1,1,1,1,1,     \
+  1,1,1,1,1,1,1,1,     \
+  1,1,1,1,1,1,1,1,     \
   1                    \
 }
 
@@ -669,6 +680,10 @@ extern int arm_structure_size_boundary;
   1,1,1,1,1,1,1,1,          \
   1,1,1,1,1,1,1,1,          \
   1,1,1,1,1,1,1,1,          \
+  1,1,1,1,1,1,1,1,          \
+  1,1,1,1,1,1,1,1,          \
+  1,1,1,1,1,1,1,1,          \
+  1,1,1,1,1,1,1,1,          \
   1                         \
 }
 
@@ -720,11 +735,15 @@ extern int arm_structure_size_boundary;
        }                                                       \
       if (TARGET_VFP)                                          \
        {                                                       \
+         /* VFPv3 registers are disabled when earlier VFP      \
+            versions are selected due to the definition of     \
+            LAST_VFP_REGNUM.  */                               \
          for (regno = FIRST_VFP_REGNUM;                        \
               regno <= LAST_VFP_REGNUM; ++ regno)              \
            {                                                   \
              fixed_regs[regno] = 0;                            \
-             call_used_regs[regno] = regno < FIRST_VFP_REGNUM + 16; \
+             call_used_regs[regno] = regno < FIRST_VFP_REGNUM + 16 \
+               || regno >= FIRST_VFP_REGNUM + 32;              \
            }                                                   \
        }                                                       \
     }                                                          \
@@ -898,15 +917,35 @@ extern int arm_structure_size_boundary;
   (((REGNUM) >= FIRST_CIRRUS_FP_REGNUM) && ((REGNUM) <= LAST_CIRRUS_FP_REGNUM))
 
 #define FIRST_VFP_REGNUM       63
-#define LAST_VFP_REGNUM                94
+#define D7_VFP_REGNUM          78  /* Registers 77 and 78 == VFP reg D7.  */
+#define LAST_VFP_REGNUM        \
+  (TARGET_VFP3 ? LAST_HI_VFP_REGNUM : LAST_LO_VFP_REGNUM)
+
 #define IS_VFP_REGNUM(REGNUM) \
   (((REGNUM) >= FIRST_VFP_REGNUM) && ((REGNUM) <= LAST_VFP_REGNUM))
 
+/* VFP registers are split into two types: those defined by VFP versions < 3
+   have D registers overlaid on consecutive pairs of S registers. VFP version 3
+   defines 16 new D registers (d16-d31) which, for simplicity and correctness
+   in various parts of the backend, we implement as "fake" single-precision
+   registers (which would be S32-S63, but cannot be used in that way).  The
+   following macros define these ranges of registers.  */
+#define LAST_LO_VFP_REGNUM     94
+#define FIRST_HI_VFP_REGNUM    95
+#define LAST_HI_VFP_REGNUM     126
+
+#define VFP_REGNO_OK_FOR_SINGLE(REGNUM) \
+  ((REGNUM) <= LAST_LO_VFP_REGNUM)
+
+/* DFmode values are only valid in even register pairs.  */
+#define VFP_REGNO_OK_FOR_DOUBLE(REGNUM) \
+  ((((REGNUM) - FIRST_VFP_REGNUM) & 1) == 0)
+
 /* The number of hard registers is 16 ARM + 8 FPA + 1 CC + 1 SFP + 1 AFP.  */
 /* + 16 Cirrus registers take us up to 43.  */
 /* Intel Wireless MMX Technology registers add 16 + 4 more.  */
-/* VFP adds 32 + 1 more.  */
-#define FIRST_PSEUDO_REGISTER   96
+/* VFP (VFP3) adds 32 (64) + 1 more.  */
+#define FIRST_PSEUDO_REGISTER   128
 
 #define DBX_REGISTER_NUMBER(REGNO) arm_dbx_register_number (REGNO)
 
@@ -960,24 +999,32 @@ extern int arm_structure_size_boundary;
    function parameters.  It is quite good to use lr since other calls may
    clobber it anyway.  Allocate r0 through r3 in reverse order since r3 is
    least likely to contain a function parameter; in addition results are
-   returned in r0.  */
-
-#define REG_ALLOC_ORDER            \
-{                                   \
-     3,  2,  1,  0, 12, 14,  4,  5, \
-     6,  7,  8, 10,  9, 11, 13, 15, \
-    16, 17, 18, 19, 20, 21, 22, 23, \
-    27, 28, 29, 30, 31, 32, 33, 34, \
-    35, 36, 37, 38, 39, 40, 41, 42, \
-    43, 44, 45, 46, 47, 48, 49, 50, \
-    51, 52, 53, 54, 55, 56, 57, 58, \
-    59, 60, 61, 62,                \
-    24, 25, 26,                            \
-    78, 77, 76, 75, 74, 73, 72, 71, \
-    70, 69, 68, 67, 66, 65, 64, 63, \
-    79, 80, 81, 82, 83, 84, 85, 86, \
-    87, 88, 89, 90, 91, 92, 93, 94, \
-    95                             \
+   returned in r0.
+   For VFP/VFPv3, allocate D16-D31 first, then caller-saved registers (D0-D7),
+   then D8-D15.  The reason for doing this is to attempt to reduce register
+   pressure when both single- and double-precision registers are used in a
+   function.  */
+
+#define REG_ALLOC_ORDER                                \
+{                                              \
+     3,  2,  1,  0, 12, 14,  4,  5,            \
+     6,  7,  8, 10,  9, 11, 13, 15,            \
+    16, 17, 18, 19, 20, 21, 22, 23,            \
+    27, 28, 29, 30, 31, 32, 33, 34,            \
+    35, 36, 37, 38, 39, 40, 41, 42,            \
+    43, 44, 45, 46, 47, 48, 49, 50,            \
+    51, 52, 53, 54, 55, 56, 57, 58,            \
+    59, 60, 61, 62,                            \
+    24, 25, 26,                                        \
+    95,  96,  97,  98,  99, 100, 101, 102,     \
+   103, 104, 105, 106, 107, 108, 109, 110,     \
+   111, 112, 113, 114, 115, 116, 117, 118,     \
+   119, 120, 121, 122, 123, 124, 125, 126,     \
+    78,  77,  76,  75,  74,  73,  72,  71,     \
+    70,  69,  68,  67,  66,  65,  64,  63,     \
+    79,  80,  81,  82,  83,  84,  85,  86,     \
+    87,  88,  89,  90,  91,  92,  93,  94,     \
+   127                                         \
 }
 
 /* Interrupt functions can only use registers that have already been
@@ -996,6 +1043,9 @@ enum reg_class
   NO_REGS,
   FPA_REGS,
   CIRRUS_REGS,
+  VFP_D0_D7_REGS,
+  VFP_LO_REGS,
+  VFP_HI_REGS,
   VFP_REGS,
   IWMMXT_GR_REGS,
   IWMMXT_REGS,
@@ -1018,6 +1068,9 @@ enum reg_class
   "NO_REGS",           \
   "FPA_REGS",          \
   "CIRRUS_REGS",       \
+  "VFP_D0_D7_REGS",    \
+  "VFP_LO_REGS",       \
+  "VFP_HI_REGS",       \
   "VFP_REGS",          \
   "IWMMXT_GR_REGS",    \
   "IWMMXT_REGS",       \
@@ -1034,24 +1087,32 @@ enum reg_class
 /* Define which registers fit in which classes.
    This is an initializer for a vector of HARD_REG_SET
    of length N_REG_CLASSES.  */
-#define REG_CLASS_CONTENTS                                     \
-{                                                              \
-  { 0x00000000, 0x00000000, 0x00000000 }, /* NO_REGS  */       \
-  { 0x00FF0000, 0x00000000, 0x00000000 }, /* FPA_REGS */       \
-  { 0xF8000000, 0x000007FF, 0x00000000 }, /* CIRRUS_REGS */    \
-  { 0x00000000, 0x80000000, 0x7FFFFFFF }, /* VFP_REGS  */      \
-  { 0x00000000, 0x00007800, 0x00000000 }, /* IWMMXT_GR_REGS */ \
-  { 0x00000000, 0x7FFF8000, 0x00000000 }, /* IWMMXT_REGS */    \
-  { 0x000000FF, 0x00000000, 0x00000000 }, /* LO_REGS */                \
-  { 0x00002000, 0x00000000, 0x00000000 }, /* STACK_REG */      \
-  { 0x000020FF, 0x00000000, 0x00000000 }, /* BASE_REGS */      \
-  { 0x0000FF00, 0x00000000, 0x00000000 }, /* HI_REGS */                \
-  { 0x01000000, 0x00000000, 0x00000000 }, /* CC_REG */         \
-  { 0x00000000, 0x00000000, 0x80000000 }, /* VFPCC_REG */      \
-  { 0x0200FFFF, 0x00000000, 0x00000000 }, /* GENERAL_REGS */   \
-  { 0xFAFFFFFF, 0xFFFFFFFF, 0x7FFFFFFF }  /* ALL_REGS */       \
+#define REG_CLASS_CONTENTS                                             \
+{                                                                      \
+  { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* NO_REGS  */   \
+  { 0x00FF0000, 0x00000000, 0x00000000, 0x00000000 }, /* FPA_REGS */   \
+  { 0xF8000000, 0x000007FF, 0x00000000, 0x00000000 }, /* CIRRUS_REGS */        \
+  { 0x00000000, 0x80000000, 0x00007FFF, 0x00000000 }, /* VFP_D0_D7_REGS  */ \
+  { 0x00000000, 0x80000000, 0x7FFFFFFF, 0x00000000 }, /* VFP_LO_REGS  */ \
+  { 0x00000000, 0x00000000, 0x80000000, 0x7FFFFFFF }, /* VFP_HI_REGS  */ \
+  { 0x00000000, 0x80000000, 0xFFFFFFFF, 0x7FFFFFFF }, /* VFP_REGS  */  \
+  { 0x00000000, 0x00007800, 0x00000000, 0x00000000 }, /* IWMMXT_GR_REGS */ \
+  { 0x00000000, 0x7FFF8000, 0x00000000, 0x00000000 }, /* IWMMXT_REGS */        \
+  { 0x000000FF, 0x00000000, 0x00000000, 0x00000000 }, /* LO_REGS */    \
+  { 0x00002000, 0x00000000, 0x00000000, 0x00000000 }, /* STACK_REG */  \
+  { 0x000020FF, 0x00000000, 0x00000000, 0x00000000 }, /* BASE_REGS */  \
+  { 0x0000FF00, 0x00000000, 0x00000000, 0x00000000 }, /* HI_REGS */    \
+  { 0x01000000, 0x00000000, 0x00000000, 0x00000000 }, /* CC_REG */     \
+  { 0x00000000, 0x00000000, 0x00000000, 0x80000000 }, /* VFPCC_REG */  \
+  { 0x0200FFFF, 0x00000000, 0x00000000, 0x00000000 }, /* GENERAL_REGS */ \
+  { 0xFAFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x7FFFFFFF }  /* ALL_REGS */   \
 }
 
+/* Any of the VFP register classes.  */
+#define IS_VFP_CLASS(X) \
+  ((X) == VFP_D0_D7_REGS || (X) == VFP_LO_REGS \
+   || (X) == VFP_HI_REGS || (X) == VFP_REGS)
+
 /* The same information, inverted:
    Return the class number of the smallest class containing
    reg number REGNO.  This could be a conditional expression
@@ -1125,7 +1186,7 @@ enum reg_class
 #define SECONDARY_OUTPUT_RELOAD_CLASS(CLASS, MODE, X)          \
   /* Restrict which direct reloads are allowed for VFP/iWMMXt regs.  */ \
   ((TARGET_VFP && TARGET_HARD_FLOAT                            \
-    && (CLASS) == VFP_REGS)                                    \
+    && IS_VFP_CLASS (CLASS))                                   \
    ? coproc_secondary_reload_class (MODE, X, FALSE)            \
    : (TARGET_IWMMXT && (CLASS) == IWMMXT_REGS)                 \
    ? coproc_secondary_reload_class (MODE, X, TRUE)             \
@@ -1138,7 +1199,7 @@ enum reg_class
 #define SECONDARY_INPUT_RELOAD_CLASS(CLASS, MODE, X)           \
   /* Restrict which direct reloads are allowed for VFP/iWMMXt regs.  */ \
   ((TARGET_VFP && TARGET_HARD_FLOAT                            \
-    && (CLASS) == VFP_REGS)                                    \
+    && IS_VFP_CLASS (CLASS))                                   \
     ? coproc_secondary_reload_class (MODE, X, FALSE) :         \
     (TARGET_IWMMXT && (CLASS) == IWMMXT_REGS) ?                        \
     coproc_secondary_reload_class (MODE, X, TRUE) :            \
@@ -1257,8 +1318,8 @@ do {                                                                            \
   (TARGET_32BIT ?                                              \
    ((FROM) == FPA_REGS && (TO) != FPA_REGS ? 20 :      \
     (FROM) != FPA_REGS && (TO) == FPA_REGS ? 20 :      \
-    (FROM) == VFP_REGS && (TO) != VFP_REGS ? 10 :  \
-    (FROM) != VFP_REGS && (TO) == VFP_REGS ? 10 :  \
+    IS_VFP_CLASS (FROM) && !IS_VFP_CLASS (TO) ? 10 :   \
+    !IS_VFP_CLASS (FROM) && IS_VFP_CLASS (TO) ? 10 :   \
     (FROM) == IWMMXT_REGS && (TO) != IWMMXT_REGS ? 4 :  \
     (FROM) != IWMMXT_REGS && (TO) == IWMMXT_REGS ? 4 :  \
     (FROM) == IWMMXT_GR_REGS || (TO) == IWMMXT_GR_REGS ? 20 :  \
index 9a60671f1042b3981d5ce8998c37b8d2bc705ce9..9a6938d0897458d67d3fa409bde63aa1608510c2 100644 (file)
@@ -20,7 +20,7 @@
 ;; Boston, MA 02110-1301, USA.
 
 ;; The following register constraints have been used:
-;; - in ARM/Thumb-2 state: f, v, w, y, z
+;; - in ARM/Thumb-2 state: f, t, v, w, x, y, z
 ;; - in Thumb state: h, k, b
 ;; - in both states: l, c
 ;; In ARM state, 'l' is an alias for 'r'
@@ -30,7 +30,7 @@
 ;; in Thumb-1 state: I, J, K, L, M, N, O
 
 ;; The following multi-letter normal constraints have been used:
-;; in ARM/Thumb-2 state: Da, Db, Dc
+;; in ARM/Thumb-2 state: Da, Db, Dc, Dv
 
 ;; The following memory constraints have been used:
 ;; in ARM/Thumb-2 state: Q, Uv, Uy
 (define_register_constraint "f" "TARGET_ARM ? FPA_REGS : NO_REGS"
  "Legacy FPA registers @code{f0}-@code{f7}.")
 
+(define_register_constraint "t" "TARGET_32BIT ? VFP_LO_REGS : NO_REGS"
+ "The VFP registers @code{s0}-@code{s31}.")
+
 (define_register_constraint "v" "TARGET_ARM ? CIRRUS_REGS : NO_REGS"
  "The Cirrus Maverick co-processor registers.")
 
-(define_register_constraint "w" "TARGET_ARM ? VFP_REGS : NO_REGS"
- "The VFP registers @code{s0}-@code{s31}.")
+(define_register_constraint "w"
+  "TARGET_32BIT ? (TARGET_VFP3 ? VFP_REGS : VFP_LO_REGS) : NO_REGS"
+ "The VFP registers @code{d0}-@code{d15}, or @code{d0}-@code{d31} for VFPv3.")
+
+(define_register_constraint "x" "TARGET_32BIT ? VFP_D0_D7_REGS : NO_REGS"
+ "The VFP registers @code{d0}-@code{d7}.")
 
 (define_register_constraint "y" "TARGET_REALLY_IWMMXT ? IWMMXT_REGS : NO_REGS"
  "The Intel iWMMX co-processor registers.")
       (match_test "TARGET_32BIT && arm_const_double_inline_cost (op) == 4
                   && !(optimize_size || arm_ld_sched)")))
 
+(define_constraint "Dv"
+ "@internal
+  In ARM/Thumb-2 state a const_double which can be used with a VFP fconsts
+  or fconstd instruction."
+ (and (match_code "const_double")
+      (match_test "TARGET_32BIT && vfp3_const_double_rtx (op)")))
+
 (define_memory_constraint "Uv"
  "@internal
   In ARM/Thumb-2 state a valid VFP load/store address."
index 7d5a7dcb9b63dcd48c92f108914bfa47cfefb1ee..d50877ca4978c2426f9205643d93cea6a7ca10b9 100644 (file)
@@ -21,7 +21,7 @@
 
 ;; Additional register numbers
 (define_constants
-  [(VFPCC_REGNUM 95)]
+  [(VFPCC_REGNUM 127)]
 )
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; ??? For now do not allow loading constants into vfp regs.  This causes
 ;; problems because small constants get converted into adds.
 (define_insn "*arm_movsi_vfp"
-  [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,r ,m,*w,r,*w,*w, *Uv")
-      (match_operand:SI 1 "general_operand"       "rI,K,N,mi,r,r,*w,*w,*Uvi,*w"))]
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,r ,m,*t,r,*t,*t, *Uv")
+      (match_operand:SI 1 "general_operand"       "rI,K,N,mi,r,r,*t,*t,*Uvi,*t"))]
   "TARGET_ARM && TARGET_VFP && TARGET_HARD_FLOAT
    && (   s_register_operand (operands[0], SImode)
        || s_register_operand (operands[1], SImode))"
 )
 
 (define_insn "*thumb2_movsi_vfp"
-  [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,r,m,*w,r,*w,*w, *Uv")
-      (match_operand:SI 1 "general_operand"       "rI,K,N,mi,r,r,*w,*w,*Uvi,*w"))]
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,r,m,*t,r,*t,*t, *Uv")
+      (match_operand:SI 1 "general_operand"       "rI,K,N,mi,r,r,*t,*t,*Uvi,*t"))]
   "TARGET_THUMB2 && TARGET_VFP && TARGET_HARD_FLOAT
    && (   s_register_operand (operands[0], SImode)
        || s_register_operand (operands[1], SImode))"
 ;; preferable to loading the value via integer registers.
 
 (define_insn "*movsf_vfp"
-  [(set (match_operand:SF 0 "nonimmediate_operand" "=w,?r,w  ,Uv,r ,m,w,r")
-       (match_operand:SF 1 "general_operand"      " ?r,w,UvE,w, mE,r,w,r"))]
+  [(set (match_operand:SF 0 "nonimmediate_operand" "=t,?r,t ,t  ,Uv,r ,m,t,r")
+       (match_operand:SF 1 "general_operand"      " ?r,t,Dv,UvE,t, mE,r,t,r"))]
   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP
    && (   s_register_operand (operands[0], SFmode)
        || s_register_operand (operands[1], SFmode))"
       return \"fmsr%?\\t%0, %1\";
     case 1:
       return \"fmrs%?\\t%0, %1\";
-    case 2: case 3:
+    case 2:
+      return \"fconsts%?\\t%0, #%G1\";
+    case 3: case 4:
       return output_move_vfp (operands);
-    case 4:
-      return \"ldr%?\\t%0, %1\\t%@ float\";
     case 5:
-      return \"str%?\\t%1, %0\\t%@ float\";
+      return \"ldr%?\\t%0, %1\\t%@ float\";
     case 6:
-      return \"fcpys%?\\t%0, %1\";
+      return \"str%?\\t%1, %0\\t%@ float\";
     case 7:
+      return \"fcpys%?\\t%0, %1\";
+    case 8:
       return \"mov%?\\t%0, %1\\t%@ float\";
     default:
       gcc_unreachable ();
     }
   "
   [(set_attr "predicable" "yes")
-   (set_attr "type" "r_2_f,f_2_r,ffarith,*,f_loads,f_stores,load1,store1")
-   (set_attr "pool_range" "*,*,1020,*,4096,*,*,*")
-   (set_attr "neg_pool_range" "*,*,1008,*,4080,*,*,*")]
+   (set_attr "type"
+     "r_2_f,f_2_r,farith,f_loads,f_stores,load1,store1,ffarith,*")
+   (set_attr "pool_range" "*,*,*,1020,*,4096,*,*,*")
+   (set_attr "neg_pool_range" "*,*,*,1008,*,4080,*,*,*")]
 )
 
 (define_insn "*thumb2_movsf_vfp"
-  [(set (match_operand:SF 0 "nonimmediate_operand" "=w,?r,w  ,Uv,r ,m,w,r")
-       (match_operand:SF 1 "general_operand"      " ?r,w,UvE,w, mE,r,w,r"))]
+  [(set (match_operand:SF 0 "nonimmediate_operand" "=t,?r,t, t  ,Uv,r ,m,t,r")
+       (match_operand:SF 1 "general_operand"      " ?r,t,Dv,UvE,t, mE,r,t,r"))]
   "TARGET_THUMB2 && TARGET_HARD_FLOAT && TARGET_VFP
    && (   s_register_operand (operands[0], SFmode)
        || s_register_operand (operands[1], SFmode))"
       return \"fmsr%?\\t%0, %1\";
     case 1:
       return \"fmrs%?\\t%0, %1\";
-    case 2: case 3:
+    case 2:
+      return \"fconsts%?\\t%0, #%G1\";
+    case 3: case 4:
       return output_move_vfp (operands);
-    case 4:
-      return \"ldr%?\\t%0, %1\\t%@ float\";
     case 5:
-      return \"str%?\\t%1, %0\\t%@ float\";
+      return \"ldr%?\\t%0, %1\\t%@ float\";
     case 6:
-      return \"fcpys%?\\t%0, %1\";
+      return \"str%?\\t%1, %0\\t%@ float\";
     case 7:
+      return \"fcpys%?\\t%0, %1\";
+    case 8:
       return \"mov%?\\t%0, %1\\t%@ float\";
     default:
       gcc_unreachable ();
     }
   "
   [(set_attr "predicable" "yes")
-   (set_attr "type" "r_2_f,f_2_r,ffarith,*,f_load,f_store,load1,store1")
-   (set_attr "pool_range" "*,*,1020,*,4092,*,*,*")
-   (set_attr "neg_pool_range" "*,*,1008,*,0,*,*,*")]
+   (set_attr "type"
+     "r_2_f,f_2_r,farith,f_load,f_store,load1,store1,ffarith,*")
+   (set_attr "pool_range" "*,*,*,1020,*,4092,*,*,*")
+   (set_attr "neg_pool_range" "*,*,*,1008,*,0,*,*,*")]
 )
 
 
 ;; DFmode moves
 
 (define_insn "*movdf_vfp"
-  [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=w,?r,r, m,w  ,Uv,w,r")
-       (match_operand:DF 1 "soft_df_operand"              " ?r,w,mF,r,UvF,w, w,r"))]
+  [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=w,?r,w ,r, m,w  ,Uv,w,r")
+       (match_operand:DF 1 "soft_df_operand"              " ?r,w,Dv,mF,r,UvF,w, w,r"))]
   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP
    && (   register_operand (operands[0], DFmode)
        || register_operand (operands[1], DFmode))"
        return \"fmdrr%?\\t%P0, %Q1, %R1\";
       case 1:
        return \"fmrrd%?\\t%Q0, %R0, %P1\";
-      case 2: case 3:
+      case 2:
+        return \"fconstd%?\\t%P0, #%G1\";
+      case 3: case 4:
        return output_move_double (operands);
-      case 4: case 5:
+      case 5: case 6:
        return output_move_vfp (operands);
-      case 6:
-       return \"fcpyd%?\\t%P0, %P1\";
       case 7:
+       return \"fcpyd%?\\t%P0, %P1\";
+      case 8:
         return \"#\";
       default:
        gcc_unreachable ();
       }
     }
   "
-  [(set_attr "type" "r_2_f,f_2_r,ffarith,*,load2,store2,f_loadd,f_stored")
-   (set_attr "length" "4,4,8,8,4,4,4,8")
-   (set_attr "pool_range" "*,*,1020,*,1020,*,*,*")
-   (set_attr "neg_pool_range" "*,*,1008,*,1008,*,*,*")]
+  [(set_attr "type"
+     "r_2_f,f_2_r,farith,f_loadd,f_stored,load2,store2,ffarith,*")
+   (set_attr "length" "4,4,4,8,8,4,4,4,8")
+   (set_attr "pool_range" "*,*,*,1020,*,1020,*,*,*")
+   (set_attr "neg_pool_range" "*,*,*,1008,*,1008,*,*,*")]
 )
 
 (define_insn "*thumb2_movdf_vfp"
-  [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=w,?r,r, m,w  ,Uv,w,r")
-       (match_operand:DF 1 "soft_df_operand"              " ?r,w,mF,r,UvF,w, w,r"))]
+  [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=w,?r,w ,r, m,w  ,Uv,w,r")
+       (match_operand:DF 1 "soft_df_operand"              " ?r,w,Dv,mF,r,UvF,w, w,r"))]
   "TARGET_THUMB2 && TARGET_HARD_FLOAT && TARGET_VFP"
   "*
   {
        return \"fmdrr%?\\t%P0, %Q1, %R1\";
       case 1:
        return \"fmrrd%?\\t%Q0, %R0, %P1\";
-      case 2: case 3: case 7:
+      case 2:
+       return \"fconstd%?\\t%P0, #%G1\";
+      case 3: case 4: case 8:
        return output_move_double (operands);
-      case 4: case 5:
+      case 5: case 6:
        return output_move_vfp (operands);
-      case 6:
+      case 7:
        return \"fcpyd%?\\t%P0, %P1\";
       default:
        abort ();
       }
     }
   "
-  [(set_attr "type" "r_2_f,f_2_r,ffarith,*,load2,store2,f_load,f_store")
-   (set_attr "length" "4,4,8,8,4,4,4,8")
-   (set_attr "pool_range" "*,*,4096,*,1020,*,*,*")
-   (set_attr "neg_pool_range" "*,*,0,*,1008,*,*,*")]
+  [(set_attr "type"
+     "r_2_f,f_2_r,farith,load2,store2,f_load,f_store,ffarith,*")
+   (set_attr "length" "4,4,4,8,8,4,4,4,8")
+   (set_attr "pool_range" "*,*,*,4096,*,1020,*,*,*")
+   (set_attr "neg_pool_range" "*,*,*,0,*,1008,*,*,*")]
 )
 
 
 ;; Conditional move patterns
 
 (define_insn "*movsfcc_vfp"
-  [(set (match_operand:SF   0 "s_register_operand" "=w,w,w,w,w,w,?r,?r,?r")
+  [(set (match_operand:SF   0 "s_register_operand" "=t,t,t,t,t,t,?r,?r,?r")
        (if_then_else:SF
          (match_operator   3 "arm_comparison_operator"
            [(match_operand 4 "cc_register" "") (const_int 0)])
-         (match_operand:SF 1 "s_register_operand" "0,w,w,0,?r,?r,0,w,w")
-         (match_operand:SF 2 "s_register_operand" "w,0,w,?r,0,?r,w,0,w")))]
+         (match_operand:SF 1 "s_register_operand" "0,t,t,0,?r,?r,0,t,t")
+         (match_operand:SF 2 "s_register_operand" "t,0,t,?r,0,?r,t,0,t")))]
   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
   "@
    fcpys%D3\\t%0, %2
 )
 
 (define_insn "*thumb2_movsfcc_vfp"
-  [(set (match_operand:SF   0 "s_register_operand" "=w,w,w,w,w,w,?r,?r,?r")
+  [(set (match_operand:SF   0 "s_register_operand" "=t,t,t,t,t,t,?r,?r,?r")
        (if_then_else:SF
          (match_operator   3 "arm_comparison_operator"
            [(match_operand 4 "cc_register" "") (const_int 0)])
-         (match_operand:SF 1 "s_register_operand" "0,w,w,0,?r,?r,0,w,w")
-         (match_operand:SF 2 "s_register_operand" "w,0,w,?r,0,?r,w,0,w")))]
+         (match_operand:SF 1 "s_register_operand" "0,t,t,0,?r,?r,0,t,t")
+         (match_operand:SF 2 "s_register_operand" "t,0,t,?r,0,?r,t,0,t")))]
   "TARGET_THUMB2 && TARGET_HARD_FLOAT && TARGET_VFP"
   "@
    it\\t%D3\;fcpys%D3\\t%0, %2
 ;; Sign manipulation functions
 
 (define_insn "*abssf2_vfp"
-  [(set (match_operand:SF        0 "s_register_operand" "=w")
-       (abs:SF (match_operand:SF 1 "s_register_operand" "w")))]
+  [(set (match_operand:SF        0 "s_register_operand" "=t")
+       (abs:SF (match_operand:SF 1 "s_register_operand" "t")))]
   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
   "fabss%?\\t%0, %1"
   [(set_attr "predicable" "yes")
 )
 
 (define_insn "*negsf2_vfp"
-  [(set (match_operand:SF        0 "s_register_operand" "=w,?r")
-       (neg:SF (match_operand:SF 1 "s_register_operand" "w,r")))]
+  [(set (match_operand:SF        0 "s_register_operand" "=t,?r")
+       (neg:SF (match_operand:SF 1 "s_register_operand" "t,r")))]
   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
   "@
    fnegs%?\\t%0, %1
 ;; Arithmetic insns
 
 (define_insn "*addsf3_vfp"
-  [(set (match_operand:SF         0 "s_register_operand" "=w")
-       (plus:SF (match_operand:SF 1 "s_register_operand" "w")
-                (match_operand:SF 2 "s_register_operand" "w")))]
+  [(set (match_operand:SF         0 "s_register_operand" "=t")
+       (plus:SF (match_operand:SF 1 "s_register_operand" "t")
+                (match_operand:SF 2 "s_register_operand" "t")))]
   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
   "fadds%?\\t%0, %1, %2"
   [(set_attr "predicable" "yes")
 
 
 (define_insn "*subsf3_vfp"
-  [(set (match_operand:SF          0 "s_register_operand" "=w")
-       (minus:SF (match_operand:SF 1 "s_register_operand" "w")
-                 (match_operand:SF 2 "s_register_operand" "w")))]
+  [(set (match_operand:SF          0 "s_register_operand" "=t")
+       (minus:SF (match_operand:SF 1 "s_register_operand" "t")
+                 (match_operand:SF 2 "s_register_operand" "t")))]
   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
   "fsubs%?\\t%0, %1, %2"
   [(set_attr "predicable" "yes")
 ;; Division insns
 
 (define_insn "*divsf3_vfp"
-  [(set (match_operand:SF        0 "s_register_operand" "+w")
-       (div:SF (match_operand:SF 1 "s_register_operand" "w")
-               (match_operand:SF 2 "s_register_operand" "w")))]
+  [(set (match_operand:SF        0 "s_register_operand" "+t")
+       (div:SF (match_operand:SF 1 "s_register_operand" "t")
+               (match_operand:SF 2 "s_register_operand" "t")))]
   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
   "fdivs%?\\t%0, %1, %2"
   [(set_attr "predicable" "yes")
 ;; Multiplication insns
 
 (define_insn "*mulsf3_vfp"
-  [(set (match_operand:SF         0 "s_register_operand" "+w")
-       (mult:SF (match_operand:SF 1 "s_register_operand" "w")
-                (match_operand:SF 2 "s_register_operand" "w")))]
+  [(set (match_operand:SF         0 "s_register_operand" "+t")
+       (mult:SF (match_operand:SF 1 "s_register_operand" "t")
+                (match_operand:SF 2 "s_register_operand" "t")))]
   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
   "fmuls%?\\t%0, %1, %2"
   [(set_attr "predicable" "yes")
 
 
 (define_insn "*mulsf3negsf_vfp"
-  [(set (match_operand:SF                 0 "s_register_operand" "+w")
-       (mult:SF (neg:SF (match_operand:SF 1 "s_register_operand" "w"))
-                (match_operand:SF         2 "s_register_operand" "w")))]
+  [(set (match_operand:SF                 0 "s_register_operand" "+t")
+       (mult:SF (neg:SF (match_operand:SF 1 "s_register_operand" "t"))
+                (match_operand:SF         2 "s_register_operand" "t")))]
   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
   "fnmuls%?\\t%0, %1, %2"
   [(set_attr "predicable" "yes")
 
 ;; 0 = 1 * 2 + 0
 (define_insn "*mulsf3addsf_vfp"
-  [(set (match_operand:SF                  0 "s_register_operand" "=w")
-       (plus:SF (mult:SF (match_operand:SF 2 "s_register_operand" "w")
-                         (match_operand:SF 3 "s_register_operand" "w"))
+  [(set (match_operand:SF                  0 "s_register_operand" "=t")
+       (plus:SF (mult:SF (match_operand:SF 2 "s_register_operand" "t")
+                         (match_operand:SF 3 "s_register_operand" "t"))
                 (match_operand:SF          1 "s_register_operand" "0")))]
   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
   "fmacs%?\\t%0, %2, %3"
 
 ;; 0 = 1 * 2 - 0
 (define_insn "*mulsf3subsf_vfp"
-  [(set (match_operand:SF                   0 "s_register_operand" "=w")
-       (minus:SF (mult:SF (match_operand:SF 2 "s_register_operand" "w")
-                          (match_operand:SF 3 "s_register_operand" "w"))
+  [(set (match_operand:SF                   0 "s_register_operand" "=t")
+       (minus:SF (mult:SF (match_operand:SF 2 "s_register_operand" "t")
+                          (match_operand:SF 3 "s_register_operand" "t"))
                  (match_operand:SF          1 "s_register_operand" "0")))]
   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
   "fmscs%?\\t%0, %2, %3"
 
 ;; 0 = -(1 * 2) + 0
 (define_insn "*mulsf3negsfaddsf_vfp"
-  [(set (match_operand:SF                   0 "s_register_operand" "=w")
+  [(set (match_operand:SF                   0 "s_register_operand" "=t")
        (minus:SF (match_operand:SF          1 "s_register_operand" "0")
-                 (mult:SF (match_operand:SF 2 "s_register_operand" "w")
-                          (match_operand:SF 3 "s_register_operand" "w"))))]
+                 (mult:SF (match_operand:SF 2 "s_register_operand" "t")
+                          (match_operand:SF 3 "s_register_operand" "t"))))]
   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
   "fnmacs%?\\t%0, %2, %3"
   [(set_attr "predicable" "yes")
 
 ;; 0 = -(1 * 2) - 0
 (define_insn "*mulsf3negsfsubsf_vfp"
-  [(set (match_operand:SF                    0 "s_register_operand" "=w")
+  [(set (match_operand:SF                    0 "s_register_operand" "=t")
        (minus:SF (mult:SF
-                   (neg:SF (match_operand:SF 2 "s_register_operand" "w"))
-                   (match_operand:SF         3 "s_register_operand" "w"))
+                   (neg:SF (match_operand:SF 2 "s_register_operand" "t"))
+                   (match_operand:SF         3 "s_register_operand" "t"))
                  (match_operand:SF           1 "s_register_operand" "0")))]
   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
   "fnmscs%?\\t%0, %2, %3"
 
 (define_insn "*extendsfdf2_vfp"
   [(set (match_operand:DF                 0 "s_register_operand" "=w")
-       (float_extend:DF (match_operand:SF 1 "s_register_operand" "w")))]
+       (float_extend:DF (match_operand:SF 1 "s_register_operand" "t")))]
   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
   "fcvtds%?\\t%P0, %1"
   [(set_attr "predicable" "yes")
 )
 
 (define_insn "*truncdfsf2_vfp"
-  [(set (match_operand:SF                 0 "s_register_operand" "=w")
+  [(set (match_operand:SF                 0 "s_register_operand" "=t")
        (float_truncate:SF (match_operand:DF 1 "s_register_operand" "w")))]
   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
   "fcvtsd%?\\t%0, %P1"
 )
 
 (define_insn "*truncsisf2_vfp"
-  [(set (match_operand:SI                0 "s_register_operand" "=w")
-       (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" "w"))))]
+  [(set (match_operand:SI                0 "s_register_operand" "=t")
+       (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" "t"))))]
   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
   "ftosizs%?\\t%0, %1"
   [(set_attr "predicable" "yes")
 )
 
 (define_insn "*truncsidf2_vfp"
-  [(set (match_operand:SI                0 "s_register_operand" "=w")
+  [(set (match_operand:SI                0 "s_register_operand" "=t")
        (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" "w"))))]
   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
   "ftosizd%?\\t%0, %P1"
 
 
 (define_insn "fixuns_truncsfsi2"
-  [(set (match_operand:SI                0 "s_register_operand" "=w")
-       (unsigned_fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" "w"))))]
+  [(set (match_operand:SI                0 "s_register_operand" "=t")
+       (unsigned_fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" "t"))))]
   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
   "ftouizs%?\\t%0, %1"
   [(set_attr "predicable" "yes")
 )
 
 (define_insn "fixuns_truncdfsi2"
-  [(set (match_operand:SI                0 "s_register_operand" "=w")
-       (unsigned_fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" "w"))))]
+  [(set (match_operand:SI                0 "s_register_operand" "=t")
+       (unsigned_fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" "t"))))]
   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
   "ftouizd%?\\t%0, %P1"
   [(set_attr "predicable" "yes")
 
 
 (define_insn "*floatsisf2_vfp"
-  [(set (match_operand:SF          0 "s_register_operand" "=w")
-       (float:SF (match_operand:SI 1 "s_register_operand" "w")))]
+  [(set (match_operand:SF          0 "s_register_operand" "=t")
+       (float:SF (match_operand:SI 1 "s_register_operand" "t")))]
   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
   "fsitos%?\\t%0, %1"
   [(set_attr "predicable" "yes")
 
 (define_insn "*floatsidf2_vfp"
   [(set (match_operand:DF          0 "s_register_operand" "=w")
-       (float:DF (match_operand:SI 1 "s_register_operand" "w")))]
+       (float:DF (match_operand:SI 1 "s_register_operand" "t")))]
   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
   "fsitod%?\\t%P0, %1"
   [(set_attr "predicable" "yes")
 
 
 (define_insn "floatunssisf2"
-  [(set (match_operand:SF          0 "s_register_operand" "=w")
-       (unsigned_float:SF (match_operand:SI 1 "s_register_operand" "w")))]
+  [(set (match_operand:SF          0 "s_register_operand" "=t")
+       (unsigned_float:SF (match_operand:SI 1 "s_register_operand" "t")))]
   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
   "fuitos%?\\t%0, %1"
   [(set_attr "predicable" "yes")
 
 (define_insn "floatunssidf2"
   [(set (match_operand:DF          0 "s_register_operand" "=w")
-       (unsigned_float:DF (match_operand:SI 1 "s_register_operand" "w")))]
+       (unsigned_float:DF (match_operand:SI 1 "s_register_operand" "t")))]
   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
   "fuitod%?\\t%P0, %1"
   [(set_attr "predicable" "yes")
 ;; Sqrt insns.
 
 (define_insn "*sqrtsf2_vfp"
-  [(set (match_operand:SF         0 "s_register_operand" "=w")
-       (sqrt:SF (match_operand:SF 1 "s_register_operand" "w")))]
+  [(set (match_operand:SF         0 "s_register_operand" "=t")
+       (sqrt:SF (match_operand:SF 1 "s_register_operand" "t")))]
   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
   "fsqrts%?\\t%0, %1"
   [(set_attr "predicable" "yes")
 
 (define_insn_and_split "*cmpsf_split_vfp"
   [(set (reg:CCFP CC_REGNUM)
-       (compare:CCFP (match_operand:SF 0 "s_register_operand"  "w")
-                     (match_operand:SF 1 "vfp_compare_operand" "wG")))]
+       (compare:CCFP (match_operand:SF 0 "s_register_operand"  "t")
+                     (match_operand:SF 1 "vfp_compare_operand" "tG")))]
   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
   "#"
   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
 
 (define_insn_and_split "*cmpsf_trap_split_vfp"
   [(set (reg:CCFPE CC_REGNUM)
-       (compare:CCFPE (match_operand:SF 0 "s_register_operand"  "w")
-                      (match_operand:SF 1 "vfp_compare_operand" "wG")))]
+       (compare:CCFPE (match_operand:SF 0 "s_register_operand"  "t")
+                      (match_operand:SF 1 "vfp_compare_operand" "tG")))]
   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
   "#"
   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
 
 (define_insn "*cmpsf_vfp"
   [(set (reg:CCFP VFPCC_REGNUM)
-       (compare:CCFP (match_operand:SF 0 "s_register_operand"  "w,w")
-                     (match_operand:SF 1 "vfp_compare_operand" "w,G")))]
+       (compare:CCFP (match_operand:SF 0 "s_register_operand"  "t,t")
+                     (match_operand:SF 1 "vfp_compare_operand" "t,G")))]
   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
   "@
    fcmps%?\\t%0, %1
 
 (define_insn "*cmpsf_trap_vfp"
   [(set (reg:CCFPE VFPCC_REGNUM)
-       (compare:CCFPE (match_operand:SF 0 "s_register_operand"  "w,w")
-                      (match_operand:SF 1 "vfp_compare_operand" "w,G")))]
+       (compare:CCFPE (match_operand:SF 0 "s_register_operand"  "t,t")
+                      (match_operand:SF 1 "vfp_compare_operand" "t,G")))]
   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
   "@
    fcmpes%?\\t%0, %1