extend.texi (Half-Precision): Update wording to reflect that there are now multiple -mfpu options that enable...
2009-11-09 Paul Brook <paul@codesourcery.com> Daniel Jacobowitz <dan@codesourcery.com> Sandra Loosemore <sandra@codesourcery.com> gcc/ * doc/extend.texi (Half-Precision): Update wording to reflect that there are now multiple -mfpu options that enable fp16 hardware support. * doc/invoke.texi: Update list of ARM -mfpu= options. * config.gcc: Update ARM --with-fpu option list. * config/arm/arm.c (all_fpus): Add vfpv3-fp16, vfpv3-d16-fp16, vfpv3xd and vfpv3xd-fp16. (use_vfp_abi): New function. (aapcs_vfp_is_call_or_return_candidate): Avoid double precision regs when undesirable. (aapcs_vfp_is_return_candidate, aapcs_vfp_is_call_candidate, aapcs_vfp_allocate_return_reg): Use use_vfp_abi. (arm_rtx_costs_1, arm_size_rtx_costs, arm_fastmul_rtx_costs, arm_9e_rtx_costs): Only expect double-precision operations if the FPU provides them. (coproc_secondary_reload_class): Reload HFmode via GENERAL_REGS if no NEON. (arm_print_operand): Handle 'p' modifier. (arm_hard_regno_mode_ok): : Allow HFmode in VFP registers if TARGET_FP16. * config/arm/arm.h (TARGET_VFP_SINGLE, TARGET_VFP_DOUBLE): Define. (TARGET_FP16): Define. * config/arm/vfp.md: Disable double-precision patterns if the FPU does not provide them. (arm_movdi_vfp, thumb2_movdi_vfp): Use fcpys to move double-precision values on a single-precision FPU. (movdf_vfp, thumb2_movdf_vfp): Likewise. Use "Dy" for double-precision constants. (movhf_vfp_neon): New pattern (was movhf_vfp). (movhf_vfp): Remove NEON instructions. * config/arm/constraints.md: Add new "Dy" constraint for double-precision constants. Update description of "Dv". * config/arm/arm.md: Disable double-precision patterns if the FPU does not provide them Co-Authored-By: Daniel Jacobowitz <dan@codesourcery.com> Co-Authored-By: Sandra Loosemore <sandra@codesourcery.com> From-SVN: r154034
This commit is contained in:
parent
2bf1730836
commit
e0dc3601d3
9 changed files with 319 additions and 106 deletions
|
@ -1,3 +1,42 @@
|
|||
2009-11-09 Paul Brook <paul@codesourcery.com>
|
||||
Daniel Jacobowitz <dan@codesourcery.com>
|
||||
Sandra Loosemore <sandra@codesourcery.com>
|
||||
|
||||
* doc/extend.texi (Half-Precision): Update wording to reflect
|
||||
that there are now multiple -mfpu options that enable fp16
|
||||
hardware support.
|
||||
* doc/invoke.texi: Update list of ARM -mfpu= options.
|
||||
* config.gcc: Update ARM --with-fpu option list.
|
||||
* config/arm/arm.c (all_fpus): Add vfpv3-fp16, vfpv3-d16-fp16,
|
||||
vfpv3xd and vfpv3xd-fp16.
|
||||
(use_vfp_abi): New function.
|
||||
(aapcs_vfp_is_call_or_return_candidate): Avoid double precision regs
|
||||
when undesirable.
|
||||
(aapcs_vfp_is_return_candidate, aapcs_vfp_is_call_candidate,
|
||||
aapcs_vfp_allocate_return_reg): Use use_vfp_abi.
|
||||
(arm_rtx_costs_1, arm_size_rtx_costs, arm_fastmul_rtx_costs,
|
||||
arm_9e_rtx_costs): Only expect double-precision operations if the FPU
|
||||
provides them.
|
||||
(coproc_secondary_reload_class): Reload HFmode via GENERAL_REGS if no
|
||||
NEON.
|
||||
(arm_print_operand): Handle 'p' modifier.
|
||||
(arm_hard_regno_mode_ok): : Allow HFmode in VFP registers if
|
||||
TARGET_FP16.
|
||||
* config/arm/arm.h (TARGET_VFP_SINGLE, TARGET_VFP_DOUBLE): Define.
|
||||
(TARGET_FP16): Define.
|
||||
* config/arm/vfp.md: Disable double-precision patterns if the FPU
|
||||
does not provide them.
|
||||
(arm_movdi_vfp, thumb2_movdi_vfp): Use fcpys to move
|
||||
double-precision values on a single-precision FPU.
|
||||
(movdf_vfp, thumb2_movdf_vfp): Likewise. Use "Dy" for
|
||||
double-precision constants.
|
||||
(movhf_vfp_neon): New pattern (was movhf_vfp).
|
||||
(movhf_vfp): Remove NEON instructions.
|
||||
* config/arm/constraints.md: Add new "Dy" constraint for
|
||||
double-precision constants. Update description of "Dv".
|
||||
* config/arm/arm.md: Disable double-precision patterns if the FPU
|
||||
does not provide them
|
||||
|
||||
2009-11-09 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
* config/i386/i386.c (print_operand) <case 'D'>: Fix formatting.
|
||||
|
|
|
@ -2817,7 +2817,7 @@ case "${target}" in
|
|||
|
||||
case "$with_fpu" in
|
||||
"" \
|
||||
| fpa | fpe2 | fpe3 | maverick | vfp | vfp3 | neon )
|
||||
| fpa | fpe2 | fpe3 | maverick | vfp | vfp3 | vfpv3 | vfpv3-fp16 | vfpv3-d16 | vfpv3-d16-fp16 | vfpv3xd | vfpv3xd-fp16 | neon | neon-fp16 )
|
||||
# OK
|
||||
;;
|
||||
*)
|
||||
|
|
|
@ -816,7 +816,11 @@ static const struct arm_fpu_desc all_fpus[] =
|
|||
{"maverick", ARM_FP_MODEL_MAVERICK, 0, 0, false, false},
|
||||
{"vfp", ARM_FP_MODEL_VFP, 2, VFP_REG_D16, false, false},
|
||||
{"vfpv3", ARM_FP_MODEL_VFP, 3, VFP_REG_D32, false, false},
|
||||
{"vfpv3-fp16", ARM_FP_MODEL_VFP, 3, VFP_REG_D32, false, true},
|
||||
{"vfpv3-d16", ARM_FP_MODEL_VFP, 3, VFP_REG_D16, false, false},
|
||||
{"vfpv3-d16-fp16", ARM_FP_MODEL_VFP, 3, VFP_REG_D16, false, true},
|
||||
{"vfpv3xd", ARM_FP_MODEL_VFP, 3, VFP_REG_SINGLE, false, false},
|
||||
{"vfpv3xd-fp16", ARM_FP_MODEL_VFP, 3, VFP_REG_SINGLE, false, true},
|
||||
{"neon", ARM_FP_MODEL_VFP, 3, VFP_REG_D32, true , false},
|
||||
{"neon-fp16", ARM_FP_MODEL_VFP, 3, VFP_REG_D32, true , true },
|
||||
/* Compatibility aliases. */
|
||||
|
@ -3817,38 +3821,57 @@ aapcs_vfp_sub_candidate (const_tree type, enum machine_mode *modep)
|
|||
return -1;
|
||||
}
|
||||
|
||||
/* Return true if PCS_VARIANT should use VFP registers. */
|
||||
static bool
|
||||
aapcs_vfp_is_call_or_return_candidate (enum machine_mode mode, const_tree type,
|
||||
enum machine_mode *base_mode,
|
||||
int *count)
|
||||
use_vfp_abi (enum arm_pcs pcs_variant, bool is_double)
|
||||
{
|
||||
if (pcs_variant == ARM_PCS_AAPCS_VFP)
|
||||
return true;
|
||||
|
||||
if (pcs_variant != ARM_PCS_AAPCS_LOCAL)
|
||||
return false;
|
||||
|
||||
return (TARGET_32BIT && TARGET_VFP && TARGET_HARD_FLOAT &&
|
||||
(TARGET_VFP_DOUBLE || !is_double));
|
||||
}
|
||||
|
||||
static bool
|
||||
aapcs_vfp_is_call_or_return_candidate (enum arm_pcs pcs_variant,
|
||||
enum machine_mode mode, const_tree type,
|
||||
int *base_mode, int *count)
|
||||
{
|
||||
enum machine_mode new_mode = VOIDmode;
|
||||
|
||||
if (GET_MODE_CLASS (mode) == MODE_FLOAT
|
||||
|| GET_MODE_CLASS (mode) == MODE_VECTOR_INT
|
||||
|| GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT)
|
||||
{
|
||||
*count = 1;
|
||||
*base_mode = mode;
|
||||
return true;
|
||||
new_mode = mode;
|
||||
}
|
||||
else if (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT)
|
||||
{
|
||||
*count = 2;
|
||||
*base_mode = (mode == DCmode ? DFmode : SFmode);
|
||||
return true;
|
||||
new_mode = (mode == DCmode ? DFmode : SFmode);
|
||||
}
|
||||
else if (type && (mode == BLKmode || TREE_CODE (type) == VECTOR_TYPE))
|
||||
{
|
||||
enum machine_mode aggregate_mode = VOIDmode;
|
||||
int ag_count = aapcs_vfp_sub_candidate (type, &aggregate_mode);
|
||||
int ag_count = aapcs_vfp_sub_candidate (type, &new_mode);
|
||||
|
||||
if (ag_count > 0 && ag_count <= 4)
|
||||
{
|
||||
*count = ag_count;
|
||||
*base_mode = aggregate_mode;
|
||||
return true;
|
||||
}
|
||||
*count = ag_count;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
else
|
||||
return false;
|
||||
|
||||
|
||||
if (!use_vfp_abi (pcs_variant, ARM_NUM_REGS (new_mode) > 1))
|
||||
return false;
|
||||
|
||||
*base_mode = new_mode;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
|
@ -3858,22 +3881,20 @@ aapcs_vfp_is_return_candidate (enum arm_pcs pcs_variant,
|
|||
int count ATTRIBUTE_UNUSED;
|
||||
enum machine_mode ag_mode ATTRIBUTE_UNUSED;
|
||||
|
||||
if (!(pcs_variant == ARM_PCS_AAPCS_VFP
|
||||
|| (pcs_variant == ARM_PCS_AAPCS_LOCAL
|
||||
&& TARGET_32BIT && TARGET_VFP && TARGET_HARD_FLOAT)))
|
||||
if (!use_vfp_abi (pcs_variant, false))
|
||||
return false;
|
||||
return aapcs_vfp_is_call_or_return_candidate (mode, type, &ag_mode, &count);
|
||||
return aapcs_vfp_is_call_or_return_candidate (pcs_variant, mode, type,
|
||||
&ag_mode, &count);
|
||||
}
|
||||
|
||||
static bool
|
||||
aapcs_vfp_is_call_candidate (CUMULATIVE_ARGS *pcum, enum machine_mode mode,
|
||||
const_tree type)
|
||||
{
|
||||
if (!(pcum->pcs_variant == ARM_PCS_AAPCS_VFP
|
||||
|| (pcum->pcs_variant == ARM_PCS_AAPCS_LOCAL
|
||||
&& TARGET_32BIT && TARGET_VFP && TARGET_HARD_FLOAT)))
|
||||
if (!use_vfp_abi (pcum->pcs_variant, false))
|
||||
return false;
|
||||
return aapcs_vfp_is_call_or_return_candidate (mode, type,
|
||||
|
||||
return aapcs_vfp_is_call_or_return_candidate (pcum->pcs_variant, mode, type,
|
||||
&pcum->aapcs_vfp_rmode,
|
||||
&pcum->aapcs_vfp_rcount);
|
||||
}
|
||||
|
@ -3934,10 +3955,9 @@ aapcs_vfp_allocate_return_reg (enum arm_pcs pcs_variant ATTRIBUTE_UNUSED,
|
|||
enum machine_mode mode,
|
||||
const_tree type ATTRIBUTE_UNUSED)
|
||||
{
|
||||
if (!(pcs_variant == ARM_PCS_AAPCS_VFP
|
||||
|| (pcs_variant == ARM_PCS_AAPCS_LOCAL
|
||||
&& TARGET_32BIT && TARGET_VFP && TARGET_HARD_FLOAT)))
|
||||
if (!use_vfp_abi (pcs_variant, false))
|
||||
return false;
|
||||
|
||||
if (mode == BLKmode || (mode == TImode && !TARGET_NEON))
|
||||
{
|
||||
int count;
|
||||
|
@ -3946,7 +3966,8 @@ aapcs_vfp_allocate_return_reg (enum arm_pcs pcs_variant ATTRIBUTE_UNUSED,
|
|||
rtx par;
|
||||
int shift;
|
||||
|
||||
aapcs_vfp_is_call_or_return_candidate (mode, type, &ag_mode, &count);
|
||||
aapcs_vfp_is_call_or_return_candidate (pcs_variant, mode, type,
|
||||
&ag_mode, &count);
|
||||
|
||||
if (!TARGET_NEON)
|
||||
{
|
||||
|
@ -6316,7 +6337,7 @@ arm_rtx_costs_1 (rtx x, enum rtx_code outer, int* total, bool speed)
|
|||
case UMOD:
|
||||
if (TARGET_HARD_FLOAT && mode == SFmode)
|
||||
*total = COSTS_N_INSNS (2);
|
||||
else if (TARGET_HARD_FLOAT && mode == DFmode)
|
||||
else if (TARGET_HARD_FLOAT && mode == DFmode && !TARGET_VFP_SINGLE)
|
||||
*total = COSTS_N_INSNS (4);
|
||||
else
|
||||
*total = COSTS_N_INSNS (20);
|
||||
|
@ -6394,7 +6415,9 @@ arm_rtx_costs_1 (rtx x, enum rtx_code outer, int* total, bool speed)
|
|||
|
||||
if (GET_MODE_CLASS (mode) == MODE_FLOAT)
|
||||
{
|
||||
if (TARGET_HARD_FLOAT && (mode == SFmode || mode == DFmode))
|
||||
if (TARGET_HARD_FLOAT
|
||||
&& (mode == SFmode
|
||||
|| (mode == DFmode && !TARGET_VFP_SINGLE)))
|
||||
{
|
||||
*total = COSTS_N_INSNS (1);
|
||||
if (GET_CODE (XEXP (x, 0)) == CONST_DOUBLE
|
||||
|
@ -6489,7 +6512,9 @@ arm_rtx_costs_1 (rtx x, enum rtx_code outer, int* total, bool speed)
|
|||
|
||||
if (GET_MODE_CLASS (mode) == MODE_FLOAT)
|
||||
{
|
||||
if (TARGET_HARD_FLOAT && (mode == SFmode || mode == DFmode))
|
||||
if (TARGET_HARD_FLOAT
|
||||
&& (mode == SFmode
|
||||
|| (mode == DFmode && !TARGET_VFP_SINGLE)))
|
||||
{
|
||||
*total = COSTS_N_INSNS (1);
|
||||
if (GET_CODE (XEXP (x, 1)) == CONST_DOUBLE
|
||||
|
@ -6602,7 +6627,9 @@ arm_rtx_costs_1 (rtx x, enum rtx_code outer, int* total, bool speed)
|
|||
case NEG:
|
||||
if (GET_MODE_CLASS (mode) == MODE_FLOAT)
|
||||
{
|
||||
if (TARGET_HARD_FLOAT && (mode == SFmode || mode == DFmode))
|
||||
if (TARGET_HARD_FLOAT
|
||||
&& (mode == SFmode
|
||||
|| (mode == DFmode && !TARGET_VFP_SINGLE)))
|
||||
{
|
||||
*total = COSTS_N_INSNS (1);
|
||||
return false;
|
||||
|
@ -6751,7 +6778,9 @@ arm_rtx_costs_1 (rtx x, enum rtx_code outer, int* total, bool speed)
|
|||
case ABS:
|
||||
if (GET_MODE_CLASS (mode) == MODE_FLOAT)
|
||||
{
|
||||
if (TARGET_HARD_FLOAT && (mode == SFmode || mode == DFmode))
|
||||
if (TARGET_HARD_FLOAT
|
||||
&& (mode == SFmode
|
||||
|| (mode == DFmode && !TARGET_VFP_SINGLE)))
|
||||
{
|
||||
*total = COSTS_N_INSNS (1);
|
||||
return false;
|
||||
|
@ -6854,7 +6883,8 @@ arm_rtx_costs_1 (rtx x, enum rtx_code outer, int* total, bool speed)
|
|||
return true;
|
||||
|
||||
case CONST_DOUBLE:
|
||||
if (TARGET_HARD_FLOAT && vfp3_const_double_rtx (x))
|
||||
if (TARGET_HARD_FLOAT && vfp3_const_double_rtx (x)
|
||||
&& (mode == SFmode || !TARGET_VFP_SINGLE))
|
||||
*total = COSTS_N_INSNS (1);
|
||||
else
|
||||
*total = COSTS_N_INSNS (4);
|
||||
|
@ -6929,7 +6959,8 @@ arm_size_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code,
|
|||
return false;
|
||||
|
||||
case MINUS:
|
||||
if (TARGET_HARD_FLOAT && GET_MODE_CLASS (mode) == MODE_FLOAT)
|
||||
if (TARGET_HARD_FLOAT && GET_MODE_CLASS (mode) == MODE_FLOAT
|
||||
&& (mode == SFmode || !TARGET_VFP_SINGLE))
|
||||
{
|
||||
*total = COSTS_N_INSNS (1);
|
||||
return false;
|
||||
|
@ -6959,7 +6990,8 @@ arm_size_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code,
|
|||
return false;
|
||||
|
||||
case PLUS:
|
||||
if (TARGET_HARD_FLOAT && GET_MODE_CLASS (mode) == MODE_FLOAT)
|
||||
if (TARGET_HARD_FLOAT && GET_MODE_CLASS (mode) == MODE_FLOAT
|
||||
&& (mode == SFmode || !TARGET_VFP_SINGLE))
|
||||
{
|
||||
*total = COSTS_N_INSNS (1);
|
||||
return false;
|
||||
|
@ -6999,7 +7031,8 @@ arm_size_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code,
|
|||
return false;
|
||||
|
||||
case NEG:
|
||||
if (TARGET_HARD_FLOAT && GET_MODE_CLASS (mode) == MODE_FLOAT)
|
||||
if (TARGET_HARD_FLOAT && GET_MODE_CLASS (mode) == MODE_FLOAT
|
||||
&& (mode == SFmode || !TARGET_VFP_SINGLE))
|
||||
{
|
||||
*total = COSTS_N_INSNS (1);
|
||||
return false;
|
||||
|
@ -7023,7 +7056,8 @@ arm_size_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code,
|
|||
return false;
|
||||
|
||||
case ABS:
|
||||
if (TARGET_HARD_FLOAT && GET_MODE_CLASS (mode) == MODE_FLOAT)
|
||||
if (TARGET_HARD_FLOAT && GET_MODE_CLASS (mode) == MODE_FLOAT
|
||||
&& (mode == SFmode || !TARGET_VFP_SINGLE))
|
||||
*total = COSTS_N_INSNS (1);
|
||||
else
|
||||
*total = COSTS_N_INSNS (1 + ARM_NUM_REGS (mode));
|
||||
|
@ -7245,7 +7279,9 @@ arm_fastmul_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code,
|
|||
|
||||
if (GET_MODE_CLASS (mode) == MODE_FLOAT)
|
||||
{
|
||||
if (TARGET_HARD_FLOAT && (mode == SFmode || mode == DFmode))
|
||||
if (TARGET_HARD_FLOAT
|
||||
&& (mode == SFmode
|
||||
|| (mode == DFmode && !TARGET_VFP_SINGLE)))
|
||||
{
|
||||
*total = COSTS_N_INSNS (1);
|
||||
return false;
|
||||
|
@ -7402,7 +7438,9 @@ arm_9e_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code,
|
|||
|
||||
if (GET_MODE_CLASS (mode) == MODE_FLOAT)
|
||||
{
|
||||
if (TARGET_HARD_FLOAT && (mode == SFmode || mode == DFmode))
|
||||
if (TARGET_HARD_FLOAT
|
||||
&& (mode == SFmode
|
||||
|| (mode == DFmode && !TARGET_VFP_SINGLE)))
|
||||
{
|
||||
*total = COSTS_N_INSNS (1);
|
||||
return false;
|
||||
|
@ -8341,6 +8379,8 @@ coproc_secondary_reload_class (enum machine_mode mode, rtx x, bool wb)
|
|||
{
|
||||
if (mode == HFmode)
|
||||
{
|
||||
if (!TARGET_NEON_FP16)
|
||||
return GENERAL_REGS;
|
||||
if (s_register_operand (x, mode) || neon_vector_mem_operand (x, 2))
|
||||
return NO_REGS;
|
||||
return GENERAL_REGS;
|
||||
|
@ -15055,6 +15095,30 @@ arm_print_operand (FILE *stream, rtx x, int code)
|
|||
}
|
||||
return;
|
||||
|
||||
/* Print the high single-precision register of a VFP double-precision
|
||||
register. */
|
||||
case 'p':
|
||||
{
|
||||
int mode = GET_MODE (x);
|
||||
int regno;
|
||||
|
||||
if (GET_MODE_SIZE (mode) != 8 || GET_CODE (x) != REG)
|
||||
{
|
||||
output_operand_lossage ("invalid operand for code '%c'", code);
|
||||
return;
|
||||
}
|
||||
|
||||
regno = REGNO (x);
|
||||
if (!VFP_REGNO_OK_FOR_DOUBLE (regno))
|
||||
{
|
||||
output_operand_lossage ("invalid operand for code '%c'", code);
|
||||
return;
|
||||
}
|
||||
|
||||
fprintf (stream, "s%d", regno - FIRST_VFP_REGNUM + 1);
|
||||
}
|
||||
return;
|
||||
|
||||
/* Print a VFP/Neon double precision or quad precision register name. */
|
||||
case 'P':
|
||||
case 'q':
|
||||
|
@ -15973,10 +16037,9 @@ arm_hard_regno_mode_ok (unsigned int regno, enum machine_mode mode)
|
|||
return VFP_REGNO_OK_FOR_DOUBLE (regno);
|
||||
|
||||
/* VFP registers can hold HFmode values, but there is no point in
|
||||
putting them there unless we have the NEON extensions for
|
||||
loading/storing them, too. */
|
||||
putting them there unless we have hardware conversion insns. */
|
||||
if (mode == HFmode)
|
||||
return TARGET_NEON_FP16 && VFP_REGNO_OK_FOR_SINGLE (regno);
|
||||
return TARGET_FP16 && VFP_REGNO_OK_FOR_SINGLE (regno);
|
||||
|
||||
if (TARGET_NEON)
|
||||
return (VALID_NEON_DREG_MODE (mode) && VFP_REGNO_OK_FOR_DOUBLE (regno))
|
||||
|
|
|
@ -230,10 +230,19 @@ extern void (*arm_lang_output_object_attributes_hook)(void);
|
|||
/* FPU supports VFPv3 instructions. */
|
||||
#define TARGET_VFP3 (TARGET_VFP && arm_fpu_desc->rev >= 3)
|
||||
|
||||
/* FPU supports NEON/VFP half-precision floating-point. */
|
||||
/* FPU only supports VFP single-precision instructions. */
|
||||
#define TARGET_VFP_SINGLE (TARGET_VFP && arm_fpu_desc->regs == VFP_REG_SINGLE)
|
||||
|
||||
/* FPU supports VFP double-precision instructions. */
|
||||
#define TARGET_VFP_DOUBLE (TARGET_VFP && arm_fpu_desc->regs != VFP_REG_SINGLE)
|
||||
|
||||
/* FPU supports half-precision floating-point with NEON element load/store. */
|
||||
#define TARGET_NEON_FP16 \
|
||||
(TARGET_VFP && arm_fpu_desc->neon && arm_fpu_desc->fp16)
|
||||
|
||||
/* FPU supports VFP half-precision floating-point. */
|
||||
#define TARGET_FP16 (TARGET_VFP && arm_fpu_desc->fp16)
|
||||
|
||||
/* FPU supports Neon instructions. The setting of this macro gets
|
||||
revealed via __ARM_NEON__ so we add extra guards upon TARGET_32BIT
|
||||
and TARGET_HARD_FLOAT to ensure that NEON instructions are
|
||||
|
|
|
@ -958,7 +958,7 @@
|
|||
[(set (match_operand:DF 0 "s_register_operand" "")
|
||||
(plus:DF (match_operand:DF 1 "s_register_operand" "")
|
||||
(match_operand:DF 2 "arm_float_add_operand" "")))]
|
||||
"TARGET_32BIT && TARGET_HARD_FLOAT"
|
||||
"TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
|
||||
"
|
||||
if (TARGET_MAVERICK
|
||||
&& !cirrus_fp_register (operands[2], DFmode))
|
||||
|
@ -1196,7 +1196,7 @@
|
|||
[(set (match_operand:DF 0 "s_register_operand" "")
|
||||
(minus:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
|
||||
(match_operand:DF 2 "arm_float_rhs_operand" "")))]
|
||||
"TARGET_32BIT && TARGET_HARD_FLOAT"
|
||||
"TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
|
||||
"
|
||||
if (TARGET_MAVERICK)
|
||||
{
|
||||
|
@ -1733,7 +1733,7 @@
|
|||
[(set (match_operand:DF 0 "s_register_operand" "")
|
||||
(mult:DF (match_operand:DF 1 "s_register_operand" "")
|
||||
(match_operand:DF 2 "arm_float_rhs_operand" "")))]
|
||||
"TARGET_32BIT && TARGET_HARD_FLOAT"
|
||||
"TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
|
||||
"
|
||||
if (TARGET_MAVERICK
|
||||
&& !cirrus_fp_register (operands[2], DFmode))
|
||||
|
@ -1753,7 +1753,7 @@
|
|||
[(set (match_operand:DF 0 "s_register_operand" "")
|
||||
(div:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
|
||||
(match_operand:DF 2 "arm_float_rhs_operand" "")))]
|
||||
"TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
|
||||
"TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
|
||||
"")
|
||||
|
||||
;; Modulo insns
|
||||
|
@ -3605,7 +3605,7 @@
|
|||
(define_expand "negdf2"
|
||||
[(set (match_operand:DF 0 "s_register_operand" "")
|
||||
(neg:DF (match_operand:DF 1 "s_register_operand" "")))]
|
||||
"TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
|
||||
"TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
|
||||
"")
|
||||
|
||||
;; abssi2 doesn't really clobber the condition codes if a different register
|
||||
|
@ -3691,7 +3691,7 @@
|
|||
(define_expand "absdf2"
|
||||
[(set (match_operand:DF 0 "s_register_operand" "")
|
||||
(abs:DF (match_operand:DF 1 "s_register_operand" "")))]
|
||||
"TARGET_32BIT && TARGET_HARD_FLOAT"
|
||||
"TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
|
||||
"")
|
||||
|
||||
(define_expand "sqrtsf2"
|
||||
|
@ -3703,7 +3703,7 @@
|
|||
(define_expand "sqrtdf2"
|
||||
[(set (match_operand:DF 0 "s_register_operand" "")
|
||||
(sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
|
||||
"TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
|
||||
"TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
|
||||
"")
|
||||
|
||||
(define_insn_and_split "one_cmpldi2"
|
||||
|
@ -3814,7 +3814,7 @@
|
|||
(define_expand "floatsidf2"
|
||||
[(set (match_operand:DF 0 "s_register_operand" "")
|
||||
(float:DF (match_operand:SI 1 "s_register_operand" "")))]
|
||||
"TARGET_32BIT && TARGET_HARD_FLOAT"
|
||||
"TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
|
||||
"
|
||||
if (TARGET_MAVERICK)
|
||||
{
|
||||
|
@ -3866,7 +3866,7 @@
|
|||
(define_expand "fix_truncdfsi2"
|
||||
[(set (match_operand:SI 0 "s_register_operand" "")
|
||||
(fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" ""))))]
|
||||
"TARGET_32BIT && TARGET_HARD_FLOAT"
|
||||
"TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
|
||||
"
|
||||
if (TARGET_MAVERICK)
|
||||
{
|
||||
|
@ -3883,7 +3883,7 @@
|
|||
[(set (match_operand:SF 0 "s_register_operand" "")
|
||||
(float_truncate:SF
|
||||
(match_operand:DF 1 "s_register_operand" "")))]
|
||||
"TARGET_32BIT && TARGET_HARD_FLOAT"
|
||||
"TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
|
||||
""
|
||||
)
|
||||
|
||||
|
@ -4784,7 +4784,7 @@
|
|||
(define_expand "extendsfdf2"
|
||||
[(set (match_operand:DF 0 "s_register_operand" "")
|
||||
(float_extend:DF (match_operand:SF 1 "s_register_operand" "")))]
|
||||
"TARGET_32BIT && TARGET_HARD_FLOAT"
|
||||
"TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
|
||||
""
|
||||
)
|
||||
|
||||
|
@ -5971,7 +5971,7 @@
|
|||
(define_insn "*arm32_movhf"
|
||||
[(set (match_operand:HF 0 "nonimmediate_operand" "=r,m,r,r")
|
||||
(match_operand:HF 1 "general_operand" " m,r,r,F"))]
|
||||
"TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_NEON_FP16)
|
||||
"TARGET_32BIT && !(TARGET_HARD_FLOAT && TARGET_FP16)
|
||||
&& ( s_register_operand (operands[0], HFmode)
|
||||
|| s_register_operand (operands[1], HFmode))"
|
||||
"*
|
||||
|
@ -6682,7 +6682,7 @@
|
|||
(match_operand:DF 2 "arm_float_compare_operand" "")])
|
||||
(label_ref (match_operand 3 "" ""))
|
||||
(pc)))]
|
||||
"TARGET_32BIT && TARGET_HARD_FLOAT"
|
||||
"TARGET_32BIT && TARGET_HARD_FLOAT && !TARGET_VFP_SINGLE"
|
||||
"emit_jump_insn (gen_cbranch_cc (operands[0], operands[1], operands[2],
|
||||
operands[3])); DONE;"
|
||||
)
|
||||
|
@ -8296,7 +8296,7 @@
|
|||
(if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
|
||||
(match_operand:DF 2 "s_register_operand" "")
|
||||
(match_operand:DF 3 "arm_float_add_operand" "")))]
|
||||
"TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
|
||||
"TARGET_32BIT && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP_DOUBLE)"
|
||||
"
|
||||
{
|
||||
enum rtx_code code = GET_CODE (operands[1]);
|
||||
|
|
|
@ -29,7 +29,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, Dn, Dl, DL, Dv
|
||||
;; in ARM/Thumb-2 state: Da, Db, Dc, Dn, Dl, DL, Dv, Dy
|
||||
;; in Thumb-1 state: Pa, Pb
|
||||
|
||||
;; The following memory constraints have been used:
|
||||
|
@ -207,10 +207,17 @@
|
|||
(define_constraint "Dv"
|
||||
"@internal
|
||||
In ARM/Thumb-2 state a const_double which can be used with a VFP fconsts
|
||||
or fconstd instruction."
|
||||
instruction."
|
||||
(and (match_code "const_double")
|
||||
(match_test "TARGET_32BIT && vfp3_const_double_rtx (op)")))
|
||||
|
||||
(define_constraint "Dy"
|
||||
"@internal
|
||||
In ARM/Thumb-2 state a const_double which can be used with a VFP fconstd
|
||||
instruction."
|
||||
(and (match_code "const_double")
|
||||
(match_test "TARGET_32BIT && TARGET_VFP_DOUBLE && vfp3_const_double_rtx (op)")))
|
||||
|
||||
(define_memory_constraint "Ut"
|
||||
"@internal
|
||||
In ARM/Thumb-2 state an address valid for loading/storing opaque structure
|
||||
|
|
|
@ -145,7 +145,10 @@
|
|||
case 4:
|
||||
return \"fmrrd%?\\t%Q0, %R0, %P1\\t%@ int\";
|
||||
case 5:
|
||||
return \"fcpyd%?\\t%P0, %P1\\t%@ int\";
|
||||
if (TARGET_VFP_SINGLE)
|
||||
return \"fcpys%?\\t%0, %1\\t%@ int\;fcpys%?\\t%p0, %p1\\t%@ int\";
|
||||
else
|
||||
return \"fcpyd%?\\t%P0, %P1\\t%@ int\";
|
||||
case 6: case 7:
|
||||
return output_move_vfp (operands);
|
||||
default:
|
||||
|
@ -153,7 +156,14 @@
|
|||
}
|
||||
"
|
||||
[(set_attr "type" "*,load2,store2,r_2_f,f_2_r,ffarithd,f_loadd,f_stored")
|
||||
(set_attr "length" "8,8,8,4,4,4,4,4")
|
||||
(set (attr "length") (cond [(eq_attr "alternative" "0,1,2") (const_int 8)
|
||||
(eq_attr "alternative" "5")
|
||||
(if_then_else
|
||||
(eq (symbol_ref "TARGET_VFP_SINGLE")
|
||||
(const_int 1))
|
||||
(const_int 8)
|
||||
(const_int 4))]
|
||||
(const_int 4)))
|
||||
(set_attr "predicable" "yes")
|
||||
(set_attr "pool_range" "*,1020,*,*,*,*,1020,*")
|
||||
(set_attr "neg_pool_range" "*,1008,*,*,*,*,1008,*")]
|
||||
|
@ -173,7 +183,10 @@
|
|||
case 4:
|
||||
return \"fmrrd%?\\t%Q0, %R0, %P1\\t%@ int\";
|
||||
case 5:
|
||||
return \"fcpyd%?\\t%P0, %P1\\t%@ int\";
|
||||
if (TARGET_VFP_SINGLE)
|
||||
return \"fcpys%?\\t%0, %1\\t%@ int\;fcpys%?\\t%p0, %p1\\t%@ int\";
|
||||
else
|
||||
return \"fcpyd%?\\t%P0, %P1\\t%@ int\";
|
||||
case 6: case 7:
|
||||
return output_move_vfp (operands);
|
||||
default:
|
||||
|
@ -181,13 +194,20 @@
|
|||
}
|
||||
"
|
||||
[(set_attr "type" "*,load2,store2,r_2_f,f_2_r,ffarithd,f_load,f_store")
|
||||
(set_attr "length" "8,8,8,4,4,4,4,4")
|
||||
(set (attr "length") (cond [(eq_attr "alternative" "0,1,2") (const_int 8)
|
||||
(eq_attr "alternative" "5")
|
||||
(if_then_else
|
||||
(eq (symbol_ref "TARGET_VFP_SINGLE")
|
||||
(const_int 1))
|
||||
(const_int 8)
|
||||
(const_int 4))]
|
||||
(const_int 4)))
|
||||
(set_attr "pool_range" "*,4096,*,*,*,*,1020,*")
|
||||
(set_attr "neg_pool_range" "*, 0,*,*,*,*,1008,*")]
|
||||
)
|
||||
|
||||
;; HFmode moves
|
||||
(define_insn "*movhf_vfp"
|
||||
(define_insn "*movhf_vfp_neon"
|
||||
[(set (match_operand:HF 0 "nonimmediate_operand" "= t,Um,r,m,t,r,t,r,r")
|
||||
(match_operand:HF 1 "general_operand" " Um, t,m,r,t,r,r,t,F"))]
|
||||
"TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_NEON_FP16
|
||||
|
@ -241,6 +261,56 @@
|
|||
(set_attr "length" "4,4,4,4,4,4,4,4,8")]
|
||||
)
|
||||
|
||||
;; FP16 without element load/store instructions.
|
||||
(define_insn "*movhf_vfp"
|
||||
[(set (match_operand:HF 0 "nonimmediate_operand" "=r,m,t,r,t,r,r")
|
||||
(match_operand:HF 1 "general_operand" " m,r,t,r,r,t,F"))]
|
||||
"TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FP16 && !TARGET_NEON_FP16
|
||||
&& ( s_register_operand (operands[0], HFmode)
|
||||
|| s_register_operand (operands[1], HFmode))"
|
||||
"*
|
||||
switch (which_alternative)
|
||||
{
|
||||
case 0: /* ARM register from memory */
|
||||
return \"ldrh\\t%0, %1\\t%@ __fp16\";
|
||||
case 1: /* memory from ARM register */
|
||||
return \"strh\\t%1, %0\\t%@ __fp16\";
|
||||
case 2: /* S register from S register */
|
||||
return \"fcpys\\t%0, %1\";
|
||||
case 3: /* ARM register from ARM register */
|
||||
return \"mov\\t%0, %1\\t%@ __fp16\";
|
||||
case 4: /* S register from ARM register */
|
||||
return \"fmsr\\t%0, %1\";
|
||||
case 5: /* ARM register from S register */
|
||||
return \"fmrs\\t%0, %1\";
|
||||
case 6: /* ARM register from constant */
|
||||
{
|
||||
REAL_VALUE_TYPE r;
|
||||
long bits;
|
||||
rtx ops[4];
|
||||
|
||||
REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
|
||||
bits = real_to_target (NULL, &r, HFmode);
|
||||
ops[0] = operands[0];
|
||||
ops[1] = GEN_INT (bits);
|
||||
ops[2] = GEN_INT (bits & 0xff00);
|
||||
ops[3] = GEN_INT (bits & 0x00ff);
|
||||
|
||||
if (arm_arch_thumb2)
|
||||
output_asm_insn (\"movw\\t%0, %1\", ops);
|
||||
else
|
||||
output_asm_insn (\"mov\\t%0, %2\;orr\\t%0, %0, %3\", ops);
|
||||
return \"\";
|
||||
}
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
}
|
||||
"
|
||||
[(set_attr "conds" "unconditional")
|
||||
(set_attr "type" "load1,store1,fcpys,*,r_2_f,f_2_r,*")
|
||||
(set_attr "length" "4,4,4,4,4,4,8")]
|
||||
)
|
||||
|
||||
|
||||
;; SFmode moves
|
||||
;; Disparage the w<->r cases because reloading an invalid address is
|
||||
|
@ -323,7 +393,7 @@
|
|||
|
||||
(define_insn "*movdf_vfp"
|
||||
[(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"))]
|
||||
(match_operand:DF 1 "soft_df_operand" " ?r,w,Dy,mF,r,UvF,w, w,r"))]
|
||||
"TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP
|
||||
&& ( register_operand (operands[0], DFmode)
|
||||
|| register_operand (operands[1], DFmode))"
|
||||
|
@ -336,13 +406,17 @@
|
|||
case 1:
|
||||
return \"fmrrd%?\\t%Q0, %R0, %P1\";
|
||||
case 2:
|
||||
gcc_assert (TARGET_VFP_DOUBLE);
|
||||
return \"fconstd%?\\t%P0, #%G1\";
|
||||
case 3: case 4:
|
||||
return output_move_double (operands);
|
||||
case 5: case 6:
|
||||
return output_move_vfp (operands);
|
||||
case 7:
|
||||
return \"fcpyd%?\\t%P0, %P1\";
|
||||
if (TARGET_VFP_SINGLE)
|
||||
return \"fcpys%?\\t%0, %1\;fcpys%?\\t%p0, %p1\";
|
||||
else
|
||||
return \"fcpyd%?\\t%P0, %P1\";
|
||||
case 8:
|
||||
return \"#\";
|
||||
default:
|
||||
|
@ -352,7 +426,14 @@
|
|||
"
|
||||
[(set_attr "type"
|
||||
"r_2_f,f_2_r,fconstd,f_loadd,f_stored,load2,store2,ffarithd,*")
|
||||
(set_attr "length" "4,4,4,8,8,4,4,4,8")
|
||||
(set (attr "length") (cond [(eq_attr "alternative" "3,4,8") (const_int 8)
|
||||
(eq_attr "alternative" "7")
|
||||
(if_then_else
|
||||
(eq (symbol_ref "TARGET_VFP_SINGLE")
|
||||
(const_int 1))
|
||||
(const_int 8)
|
||||
(const_int 4))]
|
||||
(const_int 4)))
|
||||
(set_attr "predicable" "yes")
|
||||
(set_attr "pool_range" "*,*,*,1020,*,1020,*,*,*")
|
||||
(set_attr "neg_pool_range" "*,*,*,1008,*,1008,*,*,*")]
|
||||
|
@ -360,7 +441,7 @@
|
|||
|
||||
(define_insn "*thumb2_movdf_vfp"
|
||||
[(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"))]
|
||||
(match_operand:DF 1 "soft_df_operand" " ?r,w,Dy,mF,r,UvF,w, w,r"))]
|
||||
"TARGET_THUMB2 && TARGET_HARD_FLOAT && TARGET_VFP"
|
||||
"*
|
||||
{
|
||||
|
@ -371,13 +452,17 @@
|
|||
case 1:
|
||||
return \"fmrrd%?\\t%Q0, %R0, %P1\";
|
||||
case 2:
|
||||
gcc_assert (TARGET_VFP_DOUBLE);
|
||||
return \"fconstd%?\\t%P0, #%G1\";
|
||||
case 3: case 4: case 8:
|
||||
return output_move_double (operands);
|
||||
case 5: case 6:
|
||||
return output_move_vfp (operands);
|
||||
case 7:
|
||||
return \"fcpyd%?\\t%P0, %P1\";
|
||||
if (TARGET_VFP_SINGLE)
|
||||
return \"fcpys%?\\t%0, %1\;fcpys%?\\t%p0, %p1\";
|
||||
else
|
||||
return \"fcpyd%?\\t%P0, %P1\";
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
|
@ -385,7 +470,14 @@
|
|||
"
|
||||
[(set_attr "type"
|
||||
"r_2_f,f_2_r,fconstd,load2,store2,f_load,f_store,ffarithd,*")
|
||||
(set_attr "length" "4,4,4,8,8,4,4,4,8")
|
||||
(set (attr "length") (cond [(eq_attr "alternative" "3,4,8") (const_int 8)
|
||||
(eq_attr "alternative" "7")
|
||||
(if_then_else
|
||||
(eq (symbol_ref "TARGET_VFP_SINGLE")
|
||||
(const_int 1))
|
||||
(const_int 8)
|
||||
(const_int 4))]
|
||||
(const_int 4)))
|
||||
(set_attr "pool_range" "*,*,*,4096,*,1020,*,*,*")
|
||||
(set_attr "neg_pool_range" "*,*,*,0,*,1008,*,*,*")]
|
||||
)
|
||||
|
@ -446,7 +538,7 @@
|
|||
[(match_operand 4 "cc_register" "") (const_int 0)])
|
||||
(match_operand:DF 1 "s_register_operand" "0,w,w,0,?r,?r,0,w,w")
|
||||
(match_operand:DF 2 "s_register_operand" "w,0,w,?r,0,?r,w,0,w")))]
|
||||
"TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
|
||||
"TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
|
||||
"@
|
||||
fcpyd%D3\\t%P0, %P2
|
||||
fcpyd%d3\\t%P0, %P1
|
||||
|
@ -469,7 +561,7 @@
|
|||
[(match_operand 4 "cc_register" "") (const_int 0)])
|
||||
(match_operand:DF 1 "s_register_operand" "0,w,w,0,?r,?r,0,w,w")
|
||||
(match_operand:DF 2 "s_register_operand" "w,0,w,?r,0,?r,w,0,w")))]
|
||||
"TARGET_THUMB2 && TARGET_HARD_FLOAT && TARGET_VFP"
|
||||
"TARGET_THUMB2 && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
|
||||
"@
|
||||
it\\t%D3\;fcpyd%D3\\t%P0, %P2
|
||||
it\\t%d3\;fcpyd%d3\\t%P0, %P1
|
||||
|
@ -500,7 +592,7 @@
|
|||
(define_insn "*absdf2_vfp"
|
||||
[(set (match_operand:DF 0 "s_register_operand" "=w")
|
||||
(abs:DF (match_operand:DF 1 "s_register_operand" "w")))]
|
||||
"TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
|
||||
"TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
|
||||
"fabsd%?\\t%P0, %P1"
|
||||
[(set_attr "predicable" "yes")
|
||||
(set_attr "type" "ffarithd")]
|
||||
|
@ -520,12 +612,12 @@
|
|||
(define_insn_and_split "*negdf2_vfp"
|
||||
[(set (match_operand:DF 0 "s_register_operand" "=w,?r,?r")
|
||||
(neg:DF (match_operand:DF 1 "s_register_operand" "w,0,r")))]
|
||||
"TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
|
||||
"TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
|
||||
"@
|
||||
fnegd%?\\t%P0, %P1
|
||||
#
|
||||
#"
|
||||
"TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP && reload_completed
|
||||
"TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE && reload_completed
|
||||
&& arm_general_register_operand (operands[0], DFmode)"
|
||||
[(set (match_dup 0) (match_dup 1))]
|
||||
"
|
||||
|
@ -580,7 +672,7 @@
|
|||
[(set (match_operand:DF 0 "s_register_operand" "=w")
|
||||
(plus:DF (match_operand:DF 1 "s_register_operand" "w")
|
||||
(match_operand:DF 2 "s_register_operand" "w")))]
|
||||
"TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
|
||||
"TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
|
||||
"faddd%?\\t%P0, %P1, %P2"
|
||||
[(set_attr "predicable" "yes")
|
||||
(set_attr "type" "faddd")]
|
||||
|
@ -601,7 +693,7 @@
|
|||
[(set (match_operand:DF 0 "s_register_operand" "=w")
|
||||
(minus:DF (match_operand:DF 1 "s_register_operand" "w")
|
||||
(match_operand:DF 2 "s_register_operand" "w")))]
|
||||
"TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
|
||||
"TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
|
||||
"fsubd%?\\t%P0, %P1, %P2"
|
||||
[(set_attr "predicable" "yes")
|
||||
(set_attr "type" "faddd")]
|
||||
|
@ -624,7 +716,7 @@
|
|||
[(set (match_operand:DF 0 "s_register_operand" "+w")
|
||||
(div:DF (match_operand:DF 1 "s_register_operand" "w")
|
||||
(match_operand:DF 2 "s_register_operand" "w")))]
|
||||
"TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
|
||||
"TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
|
||||
"fdivd%?\\t%P0, %P1, %P2"
|
||||
[(set_attr "predicable" "yes")
|
||||
(set_attr "type" "fdivd")]
|
||||
|
@ -647,7 +739,7 @@
|
|||
[(set (match_operand:DF 0 "s_register_operand" "+w")
|
||||
(mult:DF (match_operand:DF 1 "s_register_operand" "w")
|
||||
(match_operand:DF 2 "s_register_operand" "w")))]
|
||||
"TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
|
||||
"TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
|
||||
"fmuld%?\\t%P0, %P1, %P2"
|
||||
[(set_attr "predicable" "yes")
|
||||
(set_attr "type" "fmuld")]
|
||||
|
@ -668,7 +760,7 @@
|
|||
[(set (match_operand:DF 0 "s_register_operand" "+w")
|
||||
(mult:DF (neg:DF (match_operand:DF 1 "s_register_operand" "w"))
|
||||
(match_operand:DF 2 "s_register_operand" "w")))]
|
||||
"TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
|
||||
"TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
|
||||
"fnmuld%?\\t%P0, %P1, %P2"
|
||||
[(set_attr "predicable" "yes")
|
||||
(set_attr "type" "fmuld")]
|
||||
|
@ -694,7 +786,7 @@
|
|||
(plus:DF (mult:DF (match_operand:DF 2 "s_register_operand" "w")
|
||||
(match_operand:DF 3 "s_register_operand" "w"))
|
||||
(match_operand:DF 1 "s_register_operand" "0")))]
|
||||
"TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
|
||||
"TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
|
||||
"fmacd%?\\t%P0, %P2, %P3"
|
||||
[(set_attr "predicable" "yes")
|
||||
(set_attr "type" "fmacd")]
|
||||
|
@ -717,7 +809,7 @@
|
|||
(minus:DF (mult:DF (match_operand:DF 2 "s_register_operand" "w")
|
||||
(match_operand:DF 3 "s_register_operand" "w"))
|
||||
(match_operand:DF 1 "s_register_operand" "0")))]
|
||||
"TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
|
||||
"TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
|
||||
"fmscd%?\\t%P0, %P2, %P3"
|
||||
[(set_attr "predicable" "yes")
|
||||
(set_attr "type" "fmacd")]
|
||||
|
@ -740,7 +832,7 @@
|
|||
(minus:DF (match_operand:DF 1 "s_register_operand" "0")
|
||||
(mult:DF (match_operand:DF 2 "s_register_operand" "w")
|
||||
(match_operand:DF 3 "s_register_operand" "w"))))]
|
||||
"TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
|
||||
"TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
|
||||
"fnmacd%?\\t%P0, %P2, %P3"
|
||||
[(set_attr "predicable" "yes")
|
||||
(set_attr "type" "fmacd")]
|
||||
|
@ -766,7 +858,7 @@
|
|||
(neg:DF (match_operand:DF 2 "s_register_operand" "w"))
|
||||
(match_operand:DF 3 "s_register_operand" "w"))
|
||||
(match_operand:DF 1 "s_register_operand" "0")))]
|
||||
"TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
|
||||
"TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
|
||||
"fnmscd%?\\t%P0, %P2, %P3"
|
||||
[(set_attr "predicable" "yes")
|
||||
(set_attr "type" "fmacd")]
|
||||
|
@ -778,7 +870,7 @@
|
|||
(define_insn "*extendsfdf2_vfp"
|
||||
[(set (match_operand:DF 0 "s_register_operand" "=w")
|
||||
(float_extend:DF (match_operand:SF 1 "s_register_operand" "t")))]
|
||||
"TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
|
||||
"TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
|
||||
"fcvtds%?\\t%P0, %1"
|
||||
[(set_attr "predicable" "yes")
|
||||
(set_attr "type" "f_cvt")]
|
||||
|
@ -787,7 +879,7 @@
|
|||
(define_insn "*truncdfsf2_vfp"
|
||||
[(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"
|
||||
"TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
|
||||
"fcvtsd%?\\t%0, %P1"
|
||||
[(set_attr "predicable" "yes")
|
||||
(set_attr "type" "f_cvt")]
|
||||
|
@ -796,7 +888,7 @@
|
|||
(define_insn "extendhfsf2"
|
||||
[(set (match_operand:SF 0 "s_register_operand" "=t")
|
||||
(float_extend:SF (match_operand:HF 1 "s_register_operand" "t")))]
|
||||
"TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_NEON_FP16"
|
||||
"TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FP16"
|
||||
"vcvtb%?.f32.f16\\t%0, %1"
|
||||
[(set_attr "predicable" "yes")
|
||||
(set_attr "type" "f_cvt")]
|
||||
|
@ -805,7 +897,7 @@
|
|||
(define_insn "truncsfhf2"
|
||||
[(set (match_operand:HF 0 "s_register_operand" "=t")
|
||||
(float_truncate:HF (match_operand:SF 1 "s_register_operand" "t")))]
|
||||
"TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_NEON_FP16"
|
||||
"TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_FP16"
|
||||
"vcvtb%?.f16.f32\\t%0, %1"
|
||||
[(set_attr "predicable" "yes")
|
||||
(set_attr "type" "f_cvt")]
|
||||
|
@ -823,7 +915,7 @@
|
|||
(define_insn "*truncsidf2_vfp"
|
||||
[(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"
|
||||
"TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
|
||||
"ftosizd%?\\t%0, %P1"
|
||||
[(set_attr "predicable" "yes")
|
||||
(set_attr "type" "f_cvt")]
|
||||
|
@ -842,7 +934,7 @@
|
|||
(define_insn "fixuns_truncdfsi2"
|
||||
[(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"
|
||||
"TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
|
||||
"ftouizd%?\\t%0, %P1"
|
||||
[(set_attr "predicable" "yes")
|
||||
(set_attr "type" "f_cvt")]
|
||||
|
@ -861,7 +953,7 @@
|
|||
(define_insn "*floatsidf2_vfp"
|
||||
[(set (match_operand:DF 0 "s_register_operand" "=w")
|
||||
(float:DF (match_operand:SI 1 "s_register_operand" "t")))]
|
||||
"TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
|
||||
"TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
|
||||
"fsitod%?\\t%P0, %1"
|
||||
[(set_attr "predicable" "yes")
|
||||
(set_attr "type" "f_cvt")]
|
||||
|
@ -880,7 +972,7 @@
|
|||
(define_insn "floatunssidf2"
|
||||
[(set (match_operand:DF 0 "s_register_operand" "=w")
|
||||
(unsigned_float:DF (match_operand:SI 1 "s_register_operand" "t")))]
|
||||
"TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
|
||||
"TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
|
||||
"fuitod%?\\t%P0, %1"
|
||||
[(set_attr "predicable" "yes")
|
||||
(set_attr "type" "f_cvt")]
|
||||
|
@ -901,7 +993,7 @@
|
|||
(define_insn "*sqrtdf2_vfp"
|
||||
[(set (match_operand:DF 0 "s_register_operand" "=w")
|
||||
(sqrt:DF (match_operand:DF 1 "s_register_operand" "w")))]
|
||||
"TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
|
||||
"TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
|
||||
"fsqrtd%?\\t%P0, %P1"
|
||||
[(set_attr "predicable" "yes")
|
||||
(set_attr "type" "fdivd")]
|
||||
|
@ -953,9 +1045,9 @@
|
|||
[(set (reg:CCFP CC_REGNUM)
|
||||
(compare:CCFP (match_operand:DF 0 "s_register_operand" "w")
|
||||
(match_operand:DF 1 "vfp_compare_operand" "wG")))]
|
||||
"TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
|
||||
"TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
|
||||
"#"
|
||||
"TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
|
||||
"TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
|
||||
[(set (reg:CCFP VFPCC_REGNUM)
|
||||
(compare:CCFP (match_dup 0)
|
||||
(match_dup 1)))
|
||||
|
@ -968,9 +1060,9 @@
|
|||
[(set (reg:CCFPE CC_REGNUM)
|
||||
(compare:CCFPE (match_operand:DF 0 "s_register_operand" "w")
|
||||
(match_operand:DF 1 "vfp_compare_operand" "wG")))]
|
||||
"TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
|
||||
"TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
|
||||
"#"
|
||||
"TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
|
||||
"TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
|
||||
[(set (reg:CCFPE VFPCC_REGNUM)
|
||||
(compare:CCFPE (match_dup 0)
|
||||
(match_dup 1)))
|
||||
|
@ -1010,7 +1102,7 @@
|
|||
[(set (reg:CCFP VFPCC_REGNUM)
|
||||
(compare:CCFP (match_operand:DF 0 "s_register_operand" "w,w")
|
||||
(match_operand:DF 1 "vfp_compare_operand" "w,G")))]
|
||||
"TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
|
||||
"TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
|
||||
"@
|
||||
fcmpd%?\\t%P0, %P1
|
||||
fcmpzd%?\\t%P0"
|
||||
|
@ -1022,7 +1114,7 @@
|
|||
[(set (reg:CCFPE VFPCC_REGNUM)
|
||||
(compare:CCFPE (match_operand:DF 0 "s_register_operand" "w,w")
|
||||
(match_operand:DF 1 "vfp_compare_operand" "w,G")))]
|
||||
"TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP"
|
||||
"TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
|
||||
"@
|
||||
fcmped%?\\t%P0, %P1
|
||||
fcmpezd%?\\t%P0"
|
||||
|
|
|
@ -960,8 +960,9 @@ direct conversion.
|
|||
ARM provides hardware support for conversions between
|
||||
@code{__fp16} and @code{float} values
|
||||
as an extension to VFP and NEON (Advanced SIMD). GCC generates
|
||||
code using the instructions provided by this extension if you compile
|
||||
with the options @option{-mfpu=neon-fp16 -mfloat-abi=softfp},
|
||||
code using these hardware instructions if you compile with
|
||||
options to select an FPU that provides them;
|
||||
for example, @option{-mfpu=neon-fp16 -mfloat-abi=softfp},
|
||||
in addition to the @option{-mfp16-format} option to select
|
||||
a half-precision format.
|
||||
|
||||
|
|
|
@ -9788,10 +9788,12 @@ of the @option{-mcpu=} option. Permissible names are: @samp{armv2},
|
|||
@opindex mfp
|
||||
This specifies what floating point hardware (or hardware emulation) is
|
||||
available on the target. Permissible names are: @samp{fpa}, @samp{fpe2},
|
||||
@samp{fpe3}, @samp{maverick}, @samp{vfp}, @samp{vfpv3}, @samp{vfpv3-d16},
|
||||
@samp{neon}, and @samp{neon-fp16}. @option{-mfp} and @option{-mfpe}
|
||||
are synonyms for @option{-mfpu}=@samp{fpe}@var{number}, for compatibility
|
||||
with older versions of GCC@.
|
||||
@samp{fpe3}, @samp{maverick}, @samp{vfp}, @samp{vfpv3}, @samp{vfpv3-fp16},
|
||||
@samp{vfpv3-d16}, @samp{vfpv3-d16-fp16}, @samp{vfpv3xd}, @samp{vfpv3xd-fp16},
|
||||
@samp{neon}, and @samp{neon-fp16}.
|
||||
@option{-mfp} and @option{-mfpe} are synonyms for
|
||||
@option{-mfpu}=@samp{fpe}@var{number}, for compatibility with older versions
|
||||
of GCC@.
|
||||
|
||||
If @option{-msoft-float} is specified this specifies the format of
|
||||
floating point values.
|
||||
|
|
Loading…
Add table
Reference in a new issue