Commit f1adb0a9 by Julian Brown Committed by Julian Brown

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
parent 2d5b90b2
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> 2007-07-03 Geoffrey Keating <geoffk@apple.com>
* tree.h (DECL_ALIGN): Prevent use on a FUNCTION_DECL. * tree.h (DECL_ALIGN): Prevent use on a FUNCTION_DECL.
......
...@@ -2835,7 +2835,7 @@ case "${target}" in ...@@ -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
;; ;;
*) *)
......
...@@ -187,7 +187,10 @@ do { \ ...@@ -187,7 +187,10 @@ do { \
#define CTORS_SECTION_ASM_OP "\tAREA\t|C$$gnu_ctorsvec|, 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" #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 { \ ...@@ -210,7 +213,11 @@ do { \
"s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", \ "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", \
"s8", "s9", "s10", "s11", "s12", "s13", "s14", "s15", \ "s8", "s9", "s10", "s11", "s12", "s13", "s14", "s15", \
"s16", "s17", "s18", "s19", "s20", "s21", "s22", "s23", \ "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" \
} }
......
...@@ -47,7 +47,10 @@ ...@@ -47,7 +47,10 @@
#define LOCAL_LABEL_PREFIX "" #define LOCAL_LABEL_PREFIX ""
#endif #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 #ifndef REGISTER_NAMES
#define REGISTER_NAMES \ #define REGISTER_NAMES \
{ \ { \
...@@ -68,6 +71,10 @@ ...@@ -68,6 +71,10 @@
"s8", "s9", "s10", "s11", "s12", "s13", "s14", "s15", \ "s8", "s9", "s10", "s11", "s12", "s13", "s14", "s15", \
"s16", "s17", "s18", "s19", "s20", "s21", "s22", "s23", \ "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" \
} }
#endif #endif
......
...@@ -67,6 +67,7 @@ extern rtx thumb_legitimize_reload_address (rtx *, enum machine_mode, int, int, ...@@ -67,6 +67,7 @@ extern rtx thumb_legitimize_reload_address (rtx *, enum machine_mode, int, int,
int); int);
extern int arm_const_double_rtx (rtx); extern int arm_const_double_rtx (rtx);
extern int neg_const_double_rtx_ok_for_fpa (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, extern enum reg_class coproc_secondary_reload_class (enum machine_mode, rtx,
bool); bool);
extern bool arm_tls_referenced_p (rtx); extern bool arm_tls_referenced_p (rtx);
......
...@@ -457,6 +457,7 @@ static int thumb_call_reg_needed; ...@@ -457,6 +457,7 @@ static int thumb_call_reg_needed;
#define FL_NOTM (1 << 17) /* Instructions not present in the 'M' #define FL_NOTM (1 << 17) /* Instructions not present in the 'M'
profile. */ profile. */
#define FL_DIV (1 << 18) /* Hardware divide. */ #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[] = ...@@ -700,7 +701,8 @@ static const struct fpu_desc all_fpus[] =
{"fpe2", FPUTYPE_FPA_EMU2}, {"fpe2", FPUTYPE_FPA_EMU2},
{"fpe3", FPUTYPE_FPA_EMU2}, {"fpe3", FPUTYPE_FPA_EMU2},
{"maverick", FPUTYPE_MAVERICK}, {"maverick", FPUTYPE_MAVERICK},
{"vfp", FPUTYPE_VFP} {"vfp", FPUTYPE_VFP},
{"vfp3", FPUTYPE_VFP3},
}; };
...@@ -715,7 +717,8 @@ static const enum fputype fp_model_for_fpu[] = ...@@ -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_EMU2 */
ARM_FP_MODEL_FPA, /* FPUTYPE_FPA_EMU3 */ ARM_FP_MODEL_FPA, /* FPUTYPE_FPA_EMU3 */
ARM_FP_MODEL_MAVERICK, /* FPUTYPE_MAVERICK */ 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) ...@@ -4950,7 +4953,7 @@ arm_rtx_costs_1 (rtx x, enum rtx_code code, enum rtx_code outer)
return 6; return 6;
case CONST_DOUBLE: 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; return outer == SET ? 2 : -1;
else if ((outer == COMPARE || outer == PLUS) else if ((outer == COMPARE || outer == PLUS)
&& neg_const_double_rtx_ok_for_fpa (x)) && neg_const_double_rtx_ok_for_fpa (x))
...@@ -5649,6 +5652,108 @@ neg_const_double_rtx_ok_for_fpa (rtx 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;
}
/* Predicates for `match_operand' and `match_operator'. */ /* Predicates for `match_operand' and `match_operator'. */
...@@ -8808,6 +8913,15 @@ vfp_output_fldmd (FILE * stream, unsigned int base, int reg, int count) ...@@ -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); fputc ('\t', stream);
asm_fprintf (stream, "fldmfdd\t%r!, {", base); asm_fprintf (stream, "fldmfdd\t%r!, {", base);
...@@ -8870,6 +8984,19 @@ vfp_emit_fstmd (int base_reg, int count) ...@@ -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)); par = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count));
dwarf = gen_rtx_SEQUENCE (VOIDmode, rtvec_alloc (count + 1)); dwarf = gen_rtx_SEQUENCE (VOIDmode, rtvec_alloc (count + 1));
...@@ -11982,6 +12109,16 @@ arm_print_operand (FILE *stream, rtx x, int code) ...@@ -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: default:
if (x == 0) if (x == 0)
{ {
...@@ -12761,11 +12898,10 @@ arm_hard_regno_mode_ok (unsigned int regno, enum machine_mode mode) ...@@ -12761,11 +12898,10 @@ arm_hard_regno_mode_ok (unsigned int regno, enum machine_mode mode)
&& IS_VFP_REGNUM (regno)) && IS_VFP_REGNUM (regno))
{ {
if (mode == SFmode || mode == SImode) 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) ...@@ -12828,7 +12964,14 @@ arm_regno_class (int regno)
return CIRRUS_REGS; return CIRRUS_REGS;
if (IS_VFP_REGNUM (regno)) 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)) if (IS_IWMMXT_REGNUM (regno))
return IWMMXT_REGS; return IWMMXT_REGS;
...@@ -15270,6 +15413,7 @@ arm_file_start (void) ...@@ -15270,6 +15413,7 @@ arm_file_start (void)
} }
else else
{ {
int set_float_abi_attributes = 0;
switch (arm_fpu_arch) switch (arm_fpu_arch)
{ {
case FPUTYPE_FPA: case FPUTYPE_FPA:
...@@ -15285,15 +15429,23 @@ arm_file_start (void) ...@@ -15285,15 +15429,23 @@ arm_file_start (void)
fpu_name = "maverick"; fpu_name = "maverick";
break; break;
case FPUTYPE_VFP: 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; break;
default: default:
abort(); 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) ...@@ -16172,6 +16324,7 @@ arm_dbx_register_number (unsigned int regno)
if (IS_FPA_REGNUM (regno)) if (IS_FPA_REGNUM (regno))
return (TARGET_AAPCS_BASED ? 96 : 16) + regno - FIRST_FPA_REGNUM; return (TARGET_AAPCS_BASED ? 96 : 16) + regno - FIRST_FPA_REGNUM;
/* FIXME: VFPv3 register numbering. */
if (IS_VFP_REGNUM (regno)) if (IS_VFP_REGNUM (regno))
return 64 + regno - FIRST_VFP_REGNUM; return 64 + regno - FIRST_VFP_REGNUM;
......
...@@ -206,6 +206,11 @@ extern GTY(()) rtx aof_pic_label; ...@@ -206,6 +206,11 @@ extern GTY(()) rtx aof_pic_label;
/* 32-bit Thumb-2 code. */ /* 32-bit Thumb-2 code. */
#define TARGET_THUMB2 (TARGET_THUMB && arm_arch_thumb2) #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. */ /* "DSP" multiply instructions, eg. SMULxy. */
#define TARGET_DSP_MULTIPLY \ #define TARGET_DSP_MULTIPLY \
(TARGET_32BIT && arm_arch5e && arm_arch_notm) (TARGET_32BIT && arm_arch5e && arm_arch_notm)
...@@ -275,7 +280,9 @@ enum fputype ...@@ -275,7 +280,9 @@ enum fputype
/* Cirrus Maverick floating point co-processor. */ /* Cirrus Maverick floating point co-processor. */
FPUTYPE_MAVERICK, FPUTYPE_MAVERICK,
/* VFP. */ /* 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; ...@@ -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; ...@@ -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; ...@@ -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; \ for (regno = FIRST_VFP_REGNUM; \
regno <= LAST_VFP_REGNUM; ++ regno) \ regno <= LAST_VFP_REGNUM; ++ regno) \
{ \ { \
fixed_regs[regno] = 0; \ 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; ...@@ -898,15 +917,35 @@ extern int arm_structure_size_boundary;
(((REGNUM) >= FIRST_CIRRUS_FP_REGNUM) && ((REGNUM) <= LAST_CIRRUS_FP_REGNUM)) (((REGNUM) >= FIRST_CIRRUS_FP_REGNUM) && ((REGNUM) <= LAST_CIRRUS_FP_REGNUM))
#define FIRST_VFP_REGNUM 63 #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) \ #define IS_VFP_REGNUM(REGNUM) \
(((REGNUM) >= FIRST_VFP_REGNUM) && ((REGNUM) <= LAST_VFP_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. */ /* The number of hard registers is 16 ARM + 8 FPA + 1 CC + 1 SFP + 1 AFP. */
/* + 16 Cirrus registers take us up to 43. */ /* + 16 Cirrus registers take us up to 43. */
/* Intel Wireless MMX Technology registers add 16 + 4 more. */ /* Intel Wireless MMX Technology registers add 16 + 4 more. */
/* VFP adds 32 + 1 more. */ /* VFP (VFP3) adds 32 (64) + 1 more. */
#define FIRST_PSEUDO_REGISTER 96 #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; ...@@ -960,24 +999,32 @@ extern int arm_structure_size_boundary;
function parameters. It is quite good to use lr since other calls may 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 clobber it anyway. Allocate r0 through r3 in reverse order since r3 is
least likely to contain a function parameter; in addition results are least likely to contain a function parameter; in addition results are
returned in r0. */ returned in r0.
For VFP/VFPv3, allocate D16-D31 first, then caller-saved registers (D0-D7),
#define REG_ALLOC_ORDER \ 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
3, 2, 1, 0, 12, 14, 4, 5, \ function. */
6, 7, 8, 10, 9, 11, 13, 15, \
16, 17, 18, 19, 20, 21, 22, 23, \ #define REG_ALLOC_ORDER \
27, 28, 29, 30, 31, 32, 33, 34, \ { \
35, 36, 37, 38, 39, 40, 41, 42, \ 3, 2, 1, 0, 12, 14, 4, 5, \
43, 44, 45, 46, 47, 48, 49, 50, \ 6, 7, 8, 10, 9, 11, 13, 15, \
51, 52, 53, 54, 55, 56, 57, 58, \ 16, 17, 18, 19, 20, 21, 22, 23, \
59, 60, 61, 62, \ 27, 28, 29, 30, 31, 32, 33, 34, \
24, 25, 26, \ 35, 36, 37, 38, 39, 40, 41, 42, \
78, 77, 76, 75, 74, 73, 72, 71, \ 43, 44, 45, 46, 47, 48, 49, 50, \
70, 69, 68, 67, 66, 65, 64, 63, \ 51, 52, 53, 54, 55, 56, 57, 58, \
79, 80, 81, 82, 83, 84, 85, 86, \ 59, 60, 61, 62, \
87, 88, 89, 90, 91, 92, 93, 94, \ 24, 25, 26, \
95 \ 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 ...@@ -996,6 +1043,9 @@ enum reg_class
NO_REGS, NO_REGS,
FPA_REGS, FPA_REGS,
CIRRUS_REGS, CIRRUS_REGS,
VFP_D0_D7_REGS,
VFP_LO_REGS,
VFP_HI_REGS,
VFP_REGS, VFP_REGS,
IWMMXT_GR_REGS, IWMMXT_GR_REGS,
IWMMXT_REGS, IWMMXT_REGS,
...@@ -1018,6 +1068,9 @@ enum reg_class ...@@ -1018,6 +1068,9 @@ enum reg_class
"NO_REGS", \ "NO_REGS", \
"FPA_REGS", \ "FPA_REGS", \
"CIRRUS_REGS", \ "CIRRUS_REGS", \
"VFP_D0_D7_REGS", \
"VFP_LO_REGS", \
"VFP_HI_REGS", \
"VFP_REGS", \ "VFP_REGS", \
"IWMMXT_GR_REGS", \ "IWMMXT_GR_REGS", \
"IWMMXT_REGS", \ "IWMMXT_REGS", \
...@@ -1034,24 +1087,32 @@ enum reg_class ...@@ -1034,24 +1087,32 @@ enum reg_class
/* Define which registers fit in which classes. /* Define which registers fit in which classes.
This is an initializer for a vector of HARD_REG_SET This is an initializer for a vector of HARD_REG_SET
of length N_REG_CLASSES. */ of length N_REG_CLASSES. */
#define REG_CLASS_CONTENTS \ #define REG_CLASS_CONTENTS \
{ \ { \
{ 0x00000000, 0x00000000, 0x00000000 }, /* NO_REGS */ \ { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* NO_REGS */ \
{ 0x00FF0000, 0x00000000, 0x00000000 }, /* FPA_REGS */ \ { 0x00FF0000, 0x00000000, 0x00000000, 0x00000000 }, /* FPA_REGS */ \
{ 0xF8000000, 0x000007FF, 0x00000000 }, /* CIRRUS_REGS */ \ { 0xF8000000, 0x000007FF, 0x00000000, 0x00000000 }, /* CIRRUS_REGS */ \
{ 0x00000000, 0x80000000, 0x7FFFFFFF }, /* VFP_REGS */ \ { 0x00000000, 0x80000000, 0x00007FFF, 0x00000000 }, /* VFP_D0_D7_REGS */ \
{ 0x00000000, 0x00007800, 0x00000000 }, /* IWMMXT_GR_REGS */ \ { 0x00000000, 0x80000000, 0x7FFFFFFF, 0x00000000 }, /* VFP_LO_REGS */ \
{ 0x00000000, 0x7FFF8000, 0x00000000 }, /* IWMMXT_REGS */ \ { 0x00000000, 0x00000000, 0x80000000, 0x7FFFFFFF }, /* VFP_HI_REGS */ \
{ 0x000000FF, 0x00000000, 0x00000000 }, /* LO_REGS */ \ { 0x00000000, 0x80000000, 0xFFFFFFFF, 0x7FFFFFFF }, /* VFP_REGS */ \
{ 0x00002000, 0x00000000, 0x00000000 }, /* STACK_REG */ \ { 0x00000000, 0x00007800, 0x00000000, 0x00000000 }, /* IWMMXT_GR_REGS */ \
{ 0x000020FF, 0x00000000, 0x00000000 }, /* BASE_REGS */ \ { 0x00000000, 0x7FFF8000, 0x00000000, 0x00000000 }, /* IWMMXT_REGS */ \
{ 0x0000FF00, 0x00000000, 0x00000000 }, /* HI_REGS */ \ { 0x000000FF, 0x00000000, 0x00000000, 0x00000000 }, /* LO_REGS */ \
{ 0x01000000, 0x00000000, 0x00000000 }, /* CC_REG */ \ { 0x00002000, 0x00000000, 0x00000000, 0x00000000 }, /* STACK_REG */ \
{ 0x00000000, 0x00000000, 0x80000000 }, /* VFPCC_REG */ \ { 0x000020FF, 0x00000000, 0x00000000, 0x00000000 }, /* BASE_REGS */ \
{ 0x0200FFFF, 0x00000000, 0x00000000 }, /* GENERAL_REGS */ \ { 0x0000FF00, 0x00000000, 0x00000000, 0x00000000 }, /* HI_REGS */ \
{ 0xFAFFFFFF, 0xFFFFFFFF, 0x7FFFFFFF } /* ALL_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: /* The same information, inverted:
Return the class number of the smallest class containing Return the class number of the smallest class containing
reg number REGNO. This could be a conditional expression reg number REGNO. This could be a conditional expression
...@@ -1125,7 +1186,7 @@ enum reg_class ...@@ -1125,7 +1186,7 @@ enum reg_class
#define SECONDARY_OUTPUT_RELOAD_CLASS(CLASS, MODE, X) \ #define SECONDARY_OUTPUT_RELOAD_CLASS(CLASS, MODE, X) \
/* Restrict which direct reloads are allowed for VFP/iWMMXt regs. */ \ /* Restrict which direct reloads are allowed for VFP/iWMMXt regs. */ \
((TARGET_VFP && TARGET_HARD_FLOAT \ ((TARGET_VFP && TARGET_HARD_FLOAT \
&& (CLASS) == VFP_REGS) \ && IS_VFP_CLASS (CLASS)) \
? coproc_secondary_reload_class (MODE, X, FALSE) \ ? coproc_secondary_reload_class (MODE, X, FALSE) \
: (TARGET_IWMMXT && (CLASS) == IWMMXT_REGS) \ : (TARGET_IWMMXT && (CLASS) == IWMMXT_REGS) \
? coproc_secondary_reload_class (MODE, X, TRUE) \ ? coproc_secondary_reload_class (MODE, X, TRUE) \
...@@ -1138,7 +1199,7 @@ enum reg_class ...@@ -1138,7 +1199,7 @@ enum reg_class
#define SECONDARY_INPUT_RELOAD_CLASS(CLASS, MODE, X) \ #define SECONDARY_INPUT_RELOAD_CLASS(CLASS, MODE, X) \
/* Restrict which direct reloads are allowed for VFP/iWMMXt regs. */ \ /* Restrict which direct reloads are allowed for VFP/iWMMXt regs. */ \
((TARGET_VFP && TARGET_HARD_FLOAT \ ((TARGET_VFP && TARGET_HARD_FLOAT \
&& (CLASS) == VFP_REGS) \ && IS_VFP_CLASS (CLASS)) \
? coproc_secondary_reload_class (MODE, X, FALSE) : \ ? coproc_secondary_reload_class (MODE, X, FALSE) : \
(TARGET_IWMMXT && (CLASS) == IWMMXT_REGS) ? \ (TARGET_IWMMXT && (CLASS) == IWMMXT_REGS) ? \
coproc_secondary_reload_class (MODE, X, TRUE) : \ coproc_secondary_reload_class (MODE, X, TRUE) : \
...@@ -1257,8 +1318,8 @@ do { \ ...@@ -1257,8 +1318,8 @@ do { \
(TARGET_32BIT ? \ (TARGET_32BIT ? \
((FROM) == FPA_REGS && (TO) != FPA_REGS ? 20 : \ ((FROM) == FPA_REGS && (TO) != FPA_REGS ? 20 : \
(FROM) != FPA_REGS && (TO) == FPA_REGS ? 20 : \ (FROM) != FPA_REGS && (TO) == FPA_REGS ? 20 : \
(FROM) == VFP_REGS && (TO) != VFP_REGS ? 10 : \ IS_VFP_CLASS (FROM) && !IS_VFP_CLASS (TO) ? 10 : \
(FROM) != VFP_REGS && (TO) == VFP_REGS ? 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_REGS && (TO) == IWMMXT_REGS ? 4 : \ (FROM) != IWMMXT_REGS && (TO) == IWMMXT_REGS ? 4 : \
(FROM) == IWMMXT_GR_REGS || (TO) == IWMMXT_GR_REGS ? 20 : \ (FROM) == IWMMXT_GR_REGS || (TO) == IWMMXT_GR_REGS ? 20 : \
......
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
;; Boston, MA 02110-1301, USA. ;; Boston, MA 02110-1301, USA.
;; The following register constraints have been used: ;; 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 Thumb state: h, k, b
;; - in both states: l, c ;; - in both states: l, c
;; In ARM state, 'l' is an alias for 'r' ;; In ARM state, 'l' is an alias for 'r'
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
;; in Thumb-1 state: I, J, K, L, M, N, O ;; in Thumb-1 state: I, J, K, L, M, N, O
;; The following multi-letter normal constraints have been used: ;; 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: ;; The following memory constraints have been used:
;; in ARM/Thumb-2 state: Q, Uv, Uy ;; in ARM/Thumb-2 state: Q, Uv, Uy
...@@ -40,11 +40,18 @@ ...@@ -40,11 +40,18 @@
(define_register_constraint "f" "TARGET_ARM ? FPA_REGS : NO_REGS" (define_register_constraint "f" "TARGET_ARM ? FPA_REGS : NO_REGS"
"Legacy FPA registers @code{f0}-@code{f7}.") "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" (define_register_constraint "v" "TARGET_ARM ? CIRRUS_REGS : NO_REGS"
"The Cirrus Maverick co-processor registers.") "The Cirrus Maverick co-processor registers.")
(define_register_constraint "w" "TARGET_ARM ? VFP_REGS : NO_REGS" (define_register_constraint "w"
"The VFP registers @code{s0}-@code{s31}.") "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" (define_register_constraint "y" "TARGET_REALLY_IWMMXT ? IWMMXT_REGS : NO_REGS"
"The Intel iWMMX co-processor registers.") "The Intel iWMMX co-processor registers.")
...@@ -157,6 +164,13 @@ ...@@ -157,6 +164,13 @@
(match_test "TARGET_32BIT && arm_const_double_inline_cost (op) == 4 (match_test "TARGET_32BIT && arm_const_double_inline_cost (op) == 4
&& !(optimize_size || arm_ld_sched)"))) && !(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" (define_memory_constraint "Uv"
"@internal "@internal
In ARM/Thumb-2 state a valid VFP load/store address." In ARM/Thumb-2 state a valid VFP load/store address."
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment