OSDN Git Service

gcc/
authorjules <jules@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 3 Jul 2007 19:42:36 +0000 (19:42 +0000)
committerjules <jules@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 3 Jul 2007 19:42:36 +0000 (19:42 +0000)
* 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.

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

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 f9413cd..4bf74fe 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.
 2007-07-03  Geoffrey Keating  <geoffk@apple.com>
 
        * tree.h (DECL_ALIGN): Prevent use on a FUNCTION_DECL.
index d3358c3..66c3dd9 100644 (file)
@@ -2835,7 +2835,7 @@ case "${target}" in
 
                case "$with_fpu" in
                "" \
 
                case "$with_fpu" in
                "" \
-               | fpa | fpe2 | fpe3 | maverick | vfp )
+               | fpa | fpe2 | fpe3 | maverick | vfp | vfp3 )
                        # OK
                        ;;
                *)
                        # OK
                        ;;
                *)
index e6694dc..71d87a5 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"
 
 #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                         \
 {                                              \
 
 #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", \
   "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"                                      \
 }
 
   "vfpcc"                                      \
 }
 
index b910318..a47859a 100644 (file)
 #define LOCAL_LABEL_PREFIX     ""
 #endif
 
 #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                            \
 {                                                 \
 #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", \
   "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
   "vfpcc"                                         \
 }
 #endif
index ea81271..3f928b8 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);
                                            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);
 extern enum reg_class coproc_secondary_reload_class (enum machine_mode, rtx,
                                                     bool);
 extern bool arm_tls_referenced_p (rtx);
index df08c46..6c9a695 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_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".  */
 
 
 #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},
   {"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_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:
       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))
        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;
 }
 
   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'.  */
 
 \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++;
     }
 
       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);
 
   fputc ('\t', stream);
   asm_fprintf (stream, "fldmfdd\t%r!, {", base);
 
@@ -8870,6 +8984,19 @@ vfp_emit_fstmd (int base_reg, int count)
       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));
 
   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;
 
       }
       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)
        {
     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)
       && 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)
       if (mode == DFmode)
-       return ((regno - FIRST_VFP_REGNUM) & 1) == 0;
+       return VFP_REGNO_OK_FOR_DOUBLE (regno);
       return FALSE;
     }
 
       return FALSE;
     }
 
@@ -12828,7 +12964,14 @@ arm_regno_class (int regno)
     return CIRRUS_REGS;
 
   if (IS_VFP_REGNUM (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;
 
   if (IS_IWMMXT_REGNUM (regno))
     return IWMMXT_REGS;
@@ -15270,6 +15413,7 @@ arm_file_start (void)
        }
       else
        {
        }
       else
        {
+         int set_float_abi_attributes = 0;
          switch (arm_fpu_arch)
            {
            case FPUTYPE_FPA:
          switch (arm_fpu_arch)
            {
            case FPUTYPE_FPA:
@@ -15285,15 +15429,23 @@ arm_file_start (void)
              fpu_name = "maverick";
              break;
            case FPUTYPE_VFP:
              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";
              fpu_name = "vfp";
+             set_float_abi_attributes = 1;
+             break;
+           case FPUTYPE_VFP3:
+             fpu_name = "vfp3";
+             set_float_abi_attributes = 1;
              break;
            default:
              abort();
            }
              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);
 
        }
       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;
 
   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;
 
   if (IS_VFP_REGNUM (regno))
     return 64 + regno - FIRST_VFP_REGNUM;
 
index 67fa99f..8aa88ab 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)
 
 /* 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)
 /* "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.  */
   /* 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.  */
 };
 
 /* 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,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,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)                                          \
        {                                                       \
        }                                                       \
       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;                            \
          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
   (((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))
 
 #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.  */
 /* 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)
 
 
 #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
    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
 }
 
 /* Interrupt functions can only use registers that have already been
@@ -996,6 +1043,9 @@ enum reg_class
   NO_REGS,
   FPA_REGS,
   CIRRUS_REGS,
   NO_REGS,
   FPA_REGS,
   CIRRUS_REGS,
+  VFP_D0_D7_REGS,
+  VFP_LO_REGS,
+  VFP_HI_REGS,
   VFP_REGS,
   IWMMXT_GR_REGS,
   IWMMXT_REGS,
   VFP_REGS,
   IWMMXT_GR_REGS,
   IWMMXT_REGS,
@@ -1018,6 +1068,9 @@ enum reg_class
   "NO_REGS",           \
   "FPA_REGS",          \
   "CIRRUS_REGS",       \
   "NO_REGS",           \
   "FPA_REGS",          \
   "CIRRUS_REGS",       \
+  "VFP_D0_D7_REGS",    \
+  "VFP_LO_REGS",       \
+  "VFP_HI_REGS",       \
   "VFP_REGS",          \
   "IWMMXT_GR_REGS",    \
   "IWMMXT_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 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
 /* 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                            \
 #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)             \
    ? 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                            \
 #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) :            \
     ? 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 :      \
   (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 :  \
     (FROM) == IWMMXT_REGS && (TO) != IWMMXT_REGS ? 4 :  \
     (FROM) != IWMMXT_REGS && (TO) == IWMMXT_REGS ? 4 :  \
     (FROM) == IWMMXT_GR_REGS || (TO) == IWMMXT_GR_REGS ? 20 :  \
index 9a60671..9a6938d 100644 (file)
@@ -20,7 +20,7 @@
 ;; Boston, MA 02110-1301, USA.
 
 ;; The following register constraints have been used:
 ;; 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'
 ;; - 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 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
 
 ;; 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 "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 "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.")
 
 (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)")))
 
       (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."
 (define_memory_constraint "Uv"
  "@internal
   In ARM/Thumb-2 state a valid VFP load/store address."
index 7d5a7dc..d50877c 100644 (file)
@@ -21,7 +21,7 @@
 
 ;; Additional register numbers
 (define_constants
 
 ;; 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"
 ;; ??? 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))"
   "TARGET_ARM && TARGET_VFP && TARGET_HARD_FLOAT
    && (   s_register_operand (operands[0], SImode)
        || s_register_operand (operands[1], SImode))"
 )
 
 (define_insn "*thumb2_movsi_vfp"
 )
 
 (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))"
   "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"
 ;; 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))"
   "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\";
       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);
       return output_move_vfp (operands);
-    case 4:
-      return \"ldr%?\\t%0, %1\\t%@ float\";
     case 5:
     case 5:
-      return \"str%?\\t%1, %0\\t%@ float\";
+      return \"ldr%?\\t%0, %1\\t%@ float\";
     case 6:
     case 6:
-      return \"fcpys%?\\t%0, %1\";
+      return \"str%?\\t%1, %0\\t%@ float\";
     case 7:
     case 7:
+      return \"fcpys%?\\t%0, %1\";
+    case 8:
       return \"mov%?\\t%0, %1\\t%@ float\";
     default:
       gcc_unreachable ();
     }
   "
   [(set_attr "predicable" "yes")
       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"
 )
 
 (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))"
   "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\";
       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);
       return output_move_vfp (operands);
-    case 4:
-      return \"ldr%?\\t%0, %1\\t%@ float\";
     case 5:
     case 5:
-      return \"str%?\\t%1, %0\\t%@ float\";
+      return \"ldr%?\\t%0, %1\\t%@ float\";
     case 6:
     case 6:
-      return \"fcpys%?\\t%0, %1\";
+      return \"str%?\\t%1, %0\\t%@ float\";
     case 7:
     case 7:
+      return \"fcpys%?\\t%0, %1\";
+    case 8:
       return \"mov%?\\t%0, %1\\t%@ float\";
     default:
       gcc_unreachable ();
     }
   "
   [(set_attr "predicable" "yes")
       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"
 )
 
 
 ;; 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))"
   "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\";
        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);
        return output_move_double (operands);
-      case 4: case 5:
+      case 5: case 6:
        return output_move_vfp (operands);
        return output_move_vfp (operands);
-      case 6:
-       return \"fcpyd%?\\t%P0, %P1\";
       case 7:
       case 7:
+       return \"fcpyd%?\\t%P0, %P1\";
+      case 8:
         return \"#\";
       default:
        gcc_unreachable ();
       }
     }
   "
         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"
 )
 
 (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"
   "*
   {
   "TARGET_THUMB2 && TARGET_HARD_FLOAT && TARGET_VFP"
   "*
   {
        return \"fmdrr%?\\t%P0, %Q1, %R1\";
       case 1:
        return \"fmrrd%?\\t%Q0, %R0, %P1\";
        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);
        return output_move_double (operands);
-      case 4: case 5:
+      case 5: case 6:
        return output_move_vfp (operands);
        return output_move_vfp (operands);
-      case 6:
+      case 7:
        return \"fcpyd%?\\t%P0, %P1\";
       default:
        abort ();
       }
     }
   "
        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"
 )
 
 
 ;; 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)])
        (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
   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
   "@
    fcpys%D3\\t%0, %2
 )
 
 (define_insn "*thumb2_movsfcc_vfp"
 )
 
 (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)])
        (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
   "TARGET_THUMB2 && TARGET_HARD_FLOAT && TARGET_VFP"
   "@
    it\\t%D3\;fcpys%D3\\t%0, %2
 ;; Sign manipulation functions
 
 (define_insn "*abssf2_vfp"
 ;; 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")
   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
   "fabss%?\\t%0, %1"
   [(set_attr "predicable" "yes")
 )
 
 (define_insn "*negsf2_vfp"
 )
 
 (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
   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
   "@
    fnegs%?\\t%0, %1
 ;; Arithmetic insns
 
 (define_insn "*addsf3_vfp"
 ;; 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")
   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
   "fadds%?\\t%0, %1, %2"
   [(set_attr "predicable" "yes")
 
 
 (define_insn "*subsf3_vfp"
 
 
 (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")
   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
   "fsubs%?\\t%0, %1, %2"
   [(set_attr "predicable" "yes")
 ;; Division insns
 
 (define_insn "*divsf3_vfp"
 ;; 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")
   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
   "fdivs%?\\t%0, %1, %2"
   [(set_attr "predicable" "yes")
 ;; Multiplication insns
 
 (define_insn "*mulsf3_vfp"
 ;; 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")
   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
   "fmuls%?\\t%0, %1, %2"
   [(set_attr "predicable" "yes")
 
 
 (define_insn "*mulsf3negsf_vfp"
 
 
 (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")
   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
   "fnmuls%?\\t%0, %1, %2"
   [(set_attr "predicable" "yes")
 
 ;; 0 = 1 * 2 + 0
 (define_insn "*mulsf3addsf_vfp"
 
 ;; 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"
                 (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"
 
 ;; 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"
                  (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"
 
 ;; 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")
        (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")
   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
   "fnmacs%?\\t%0, %2, %3"
   [(set_attr "predicable" "yes")
 
 ;; 0 = -(1 * 2) - 0
 (define_insn "*mulsf3negsfsubsf_vfp"
 
 ;; 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
        (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"
                  (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")
 
 (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")
   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
   "fcvtds%?\\t%P0, %1"
   [(set_attr "predicable" "yes")
 )
 
 (define_insn "*truncdfsf2_vfp"
 )
 
 (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"
        (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"
 )
 
 (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")
   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
   "ftosizs%?\\t%0, %1"
   [(set_attr "predicable" "yes")
 )
 
 (define_insn "*truncsidf2_vfp"
 )
 
 (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"
        (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"
 
 
 (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")
   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
   "ftouizs%?\\t%0, %1"
   [(set_attr "predicable" "yes")
 )
 
 (define_insn "fixuns_truncdfsi2"
 )
 
 (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")
   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
   "ftouizd%?\\t%0, %P1"
   [(set_attr "predicable" "yes")
 
 
 (define_insn "*floatsisf2_vfp"
 
 
 (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")
   "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")
 
 (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")
   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
   "fsitod%?\\t%P0, %1"
   [(set_attr "predicable" "yes")
 
 
 (define_insn "floatunssisf2"
 
 
 (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")
   "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")
 
 (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")
   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
   "fuitod%?\\t%P0, %1"
   [(set_attr "predicable" "yes")
 ;; Sqrt insns.
 
 (define_insn "*sqrtsf2_vfp"
 ;; 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")
   "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)
 
 (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"
   "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)
 
 (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"
   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
   "#"
   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
 
 (define_insn "*cmpsf_vfp"
   [(set (reg:CCFP VFPCC_REGNUM)
 
 (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
   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
   "@
    fcmps%?\\t%0, %1
 
 (define_insn "*cmpsf_trap_vfp"
   [(set (reg:CCFPE VFPCC_REGNUM)
 
 (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
   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
   "@
    fcmpes%?\\t%0, %1