diff options
author | Julian Brown <julian@codesourcery.com> | 2007-07-03 19:42:36 +0000 |
---|---|---|
committer | Julian Brown <jules@gcc.gnu.org> | 2007-07-03 19:42:36 +0000 |
commit | f1adb0a9f4d73554d243604b5ffe173843d3d705 (patch) | |
tree | e271e1e30fa0f1bd69a1d4542437b7453aa640aa /gcc | |
parent | 2d5b90b2fdf5e67857942f6ffa6417ad61f4a929 (diff) | |
download | gcc-f1adb0a9f4d73554d243604b5ffe173843d3d705.zip gcc-f1adb0a9f4d73554d243604b5ffe173843d3d705.tar.gz gcc-f1adb0a9f4d73554d243604b5ffe173843d3d705.tar.bz2 |
config.gcc (with_fpu): Allow --with-fpu=vfp3.
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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 67 | ||||
-rw-r--r-- | gcc/config.gcc | 2 | ||||
-rw-r--r-- | gcc/config/arm/aof.h | 11 | ||||
-rw-r--r-- | gcc/config/arm/aout.h | 9 | ||||
-rw-r--r-- | gcc/config/arm/arm-protos.h | 1 | ||||
-rw-r--r-- | gcc/config/arm/arm.c | 175 | ||||
-rw-r--r-- | gcc/config/arm/arm.h | 147 | ||||
-rw-r--r-- | gcc/config/arm/constraints.md | 22 | ||||
-rw-r--r-- | gcc/config/arm/vfp.md | 224 |
9 files changed, 490 insertions, 168 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f9413cd..4bf74fe 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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. diff --git a/gcc/config.gcc b/gcc/config.gcc index d3358c3..66c3dd9 100644 --- a/gcc/config.gcc +++ b/gcc/config.gcc @@ -2835,7 +2835,7 @@ case "${target}" in case "$with_fpu" in "" \ - | fpa | fpe2 | fpe3 | maverick | vfp ) + | fpa | fpe2 | fpe3 | maverick | vfp | vfp3 ) # OK ;; *) diff --git a/gcc/config/arm/aof.h b/gcc/config/arm/aof.h index e6694dc..71d87a5 100644 --- a/gcc/config/arm/aof.h +++ b/gcc/config/arm/aof.h @@ -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" \ } diff --git a/gcc/config/arm/aout.h b/gcc/config/arm/aout.h index b910318..a47859a 100644 --- a/gcc/config/arm/aout.h +++ b/gcc/config/arm/aout.h @@ -47,7 +47,10 @@ #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 \ { \ @@ -68,6 +71,10 @@ "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 diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h index ea81271..3f928b8 100644 --- a/gcc/config/arm/arm-protos.h +++ b/gcc/config/arm/arm-protos.h @@ -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); diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index df08c46..6c9a695 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -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; +} + /* 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; diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h index 67fa99f..8aa88ab 100644 --- a/gcc/config/arm/arm.h +++ b/gcc/config/arm/arm.h @@ -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 : \ diff --git a/gcc/config/arm/constraints.md b/gcc/config/arm/constraints.md index 9a60671..9a6938d 100644 --- a/gcc/config/arm/constraints.md +++ b/gcc/config/arm/constraints.md @@ -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 @@ -40,11 +40,18 @@ (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.") @@ -157,6 +164,13 @@ (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." diff --git a/gcc/config/arm/vfp.md b/gcc/config/arm/vfp.md index 7d5a7dc..d50877c 100644 --- a/gcc/config/arm/vfp.md +++ b/gcc/config/arm/vfp.md @@ -21,7 +21,7 @@ ;; Additional register numbers (define_constants - [(VFPCC_REGNUM 95)] + [(VFPCC_REGNUM 127)] ) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -121,8 +121,8 @@ ;; ??? 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))" @@ -158,8 +158,8 @@ ) (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))" @@ -262,8 +262,8 @@ ;; 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))" @@ -274,29 +274,32 @@ 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))" @@ -307,32 +310,35 @@ 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))" @@ -344,28 +350,31 @@ 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" "* { @@ -375,33 +384,36 @@ 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 @@ -419,12 +431,12 @@ ) (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 @@ -491,8 +503,8 @@ ;; 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") @@ -509,8 +521,8 @@ ) (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 @@ -569,9 +581,9 @@ ;; 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") @@ -590,9 +602,9 @@ (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") @@ -613,9 +625,9 @@ ;; 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") @@ -636,9 +648,9 @@ ;; 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") @@ -657,9 +669,9 @@ (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") @@ -681,9 +693,9 @@ ;; 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" @@ -704,9 +716,9 @@ ;; 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" @@ -727,10 +739,10 @@ ;; 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") @@ -751,10 +763,10 @@ ;; 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" @@ -779,7 +791,7 @@ (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") @@ -787,7 +799,7 @@ ) (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" @@ -796,8 +808,8 @@ ) (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") @@ -805,7 +817,7 @@ ) (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" @@ -815,8 +827,8 @@ (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") @@ -824,8 +836,8 @@ ) (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") @@ -834,8 +846,8 @@ (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") @@ -844,7 +856,7 @@ (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") @@ -853,8 +865,8 @@ (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") @@ -863,7 +875,7 @@ (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") @@ -874,8 +886,8 @@ ;; 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") @@ -905,8 +917,8 @@ (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" @@ -920,8 +932,8 @@ (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" @@ -968,8 +980,8 @@ (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 @@ -980,8 +992,8 @@ (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 |