gcc/
* config/xtensa/constraints.md (Gc): Update comment and drop _S from
TARGET_HARD_FLOAT_CONST.
* config/xtensa/xtensa-protos.h (xtensa_expand_conditional_move):
Change second argument type to machine_mode.
* config/xtensa/xtensa.cc (gen_float_relational): Generate DF
mode comparisons in addition to SF.
(xtensa_expand_conditional_branch): Change TARGET_HARD_FLOAT to
TARGET_FLOAT32 under the E_SFmode case. Add
gen_float_relational() call under the E_DFmode case.
(gen_conditional_move): Handle DFmode case.
(xtensa_expand_conditional_move): Change second argument type to
machine_mode. Change if/else check for floating point/integer
move to a switch for integer/single precision/double precision
floating point move.
(xtensa_copy_incoming_a7): Separate E_DImode and E_DFmode code
and handle E_DFmode case by emitting gen_movdf_internal.
(xtensa_emit_movcc): Generate conditional moves for DFmode.
Use .s suffix, because .d is not handled by the assembler and
both .s and .d instructions have the same encoding.
(xtensa_option_override): Initialize xtensa_hard_regno_mode_ok_p
for DFmode.
(print_operand): Add support for 'T' and 'B' codes. Expand 'U',
'V' and 'G' conditions to cover DFmode.
(xtensa_rtx_costs): Change TARGET_HARD_FLOAT to TARGET_FLOAT32.
Define costs for FP operations on DF mode values when
TARGET_FLOAT64 is on.
(xtensa_legitimate_constant_p): Cover DF mode case. Return true
for 0 and FP constants supported by const.d instruction when
TARGET_FLOAT64 is on.
(xtensa_zero_call_used_regs): Change TARGET_HARD_FLOAT to
TARGET_FLOAT32.
(FPreg_neg_scaled_simm12b): Change TARGET_HARD_FLOAT to
TARGET_FLOAT32.
* config/xtensa/xtensa.h (TARGET_HARD_FLOAT): Change to to be on
when either single precision or double precision hardware FP
support is present.
(TARGET_FLOAT32): Define to 1 when single precision FPU is
available, 0 otherwise.
(TARGET_FLOAT64): Define to 1 when double precision FPU is
available, 0 otherwise.
(TARGET_HARD_FLOAT_DIV): Rename to TARGET_FLOAT32_DIV.
(TARGET_HARD_FLOAT_RECIP): Rename to TARGET_FLOAT32_RECIP.
(TARGET_HARD_FLOAT_SQRT): Rename to TARGET_FLOAT32_SQRT.
(TARGET_HARD_FLOAT_RSQRT): Rename to TARGET_FLOAT32_RSQRT.
(TARGET_FLOAT64_DIV, TARGET_FLOAT64_RECIP, TARGET_FLOAT64_SQRT)
(TARGET_FLOAT64_RSQRT): Define similarly to TARGET_FLOAT32_*,
but for double precision FPU.
(TARGET_HARD_FLOAT_CONST_S): Rename to TARGET_HARD_FLOAT_CONST
and include 64-bit instruction variants into the condition.
(UNITS_PER_FPREG): Define as 8 when 64-bit FPU is available, 4
otherwise.
* config/xtensa/xtensa.md (SDF): New mode iterator for SF and DF.
(sd, sdf_mode_bits): New mode attributes.
(addsf3, subsf3, mulsf3, fmasf4, fnmasf4, abssf2, negsf2)
(fix<s_fix>_truncsfsi2, *fix<s_fix>_truncsfsi2_2x)
(*fix<s_fix>_truncsfsi2_scaled, float<s_float>sisf2)
(*float<s_float>sisf2_scaled, l<m_round>sfsi2)
(*l<m_round>sfsi2_2x, *l<m_round>sfsi2_scaled, *lsip, *ssip)
(cbranchsf4, cstoresf4, movsfcc, movsfcc_internal0)
(movsfcc_internal1, s<code>_sf): Extend support to DF mode using
SDF iterator and corresponding attributes.
(extendsfdf2, truncdfsf2): New patterns.
(movdf): Don't force second argument to a memory const if it
satisfies the Gc constraint.
(movdf_internal): Add instructions for arguments matching the f
constraint. Don't do the split if either argument is n hard FP
register.
gcc/testsuite/
* gcc.target/xtensa/constsynthV2_O2_costs0.c: Adjust
scan-assembler-times count for the hard_float target.
* gcc.target/xtensa/elim_callee_saved.c: Likewise.
---
gcc/config/xtensa/constraints.md | 2 +-
gcc/config/xtensa/xtensa-protos.h | 2 +-
gcc/config/xtensa/xtensa.cc | 165 +++++---
gcc/config/xtensa/xtensa.h | 26 +-
gcc/config/xtensa/xtensa.md | 354 ++++++++++--------
.../xtensa/constsynthV2_O2_costs0.c | 3 +-
.../gcc.target/xtensa/elim_callee_saved.c | 3 +-
7 files changed, 335 insertions(+), 220 deletions(-)
diff --git a/gcc/config/xtensa/constraints.md b/gcc/config/xtensa/constraints.md
index bd1b77da2908..e0b3dfa17132 100644
--- a/gcc/config/xtensa/constraints.md
+++ b/gcc/config/xtensa/constraints.md
@@ -135,7 +135,7 @@
(define_constraint "Gc"
"A single Floating-point constant for use with CONST.S instructions."
(and (match_code "const_double")
- (match_test "TARGET_HARD_FLOAT_CONST_S && xtensa_fp_const (rval) >= 0")))
+ (match_test "TARGET_HARD_FLOAT_CONST && xtensa_fp_const (rval) >= 0")))
;; Memory constraints.
diff --git a/gcc/config/xtensa/xtensa-protos.h
b/gcc/config/xtensa/xtensa-protos.h
index f6fa6c40d331..472b6c3d6c45 100644
--- a/gcc/config/xtensa/xtensa-protos.h
+++ b/gcc/config/xtensa/xtensa-protos.h
@@ -40,7 +40,7 @@ extern bool constantpool_address_p (const_rtx);
extern int constantpool_mem_p (rtx);
extern void xtensa_extend_reg (rtx, rtx);
extern void xtensa_expand_conditional_branch (rtx *, machine_mode);
-extern int xtensa_expand_conditional_move (rtx *, int);
+extern int xtensa_expand_conditional_move (rtx *, machine_mode);
extern int xtensa_expand_scc (rtx *, machine_mode);
extern int xtensa_expand_block_move (rtx *);
extern int xtensa_expand_block_set (rtx *);
diff --git a/gcc/config/xtensa/xtensa.cc b/gcc/config/xtensa/xtensa.cc
index 99a244bf9fdc..0343c35bd194 100644
--- a/gcc/config/xtensa/xtensa.cc
+++ b/gcc/config/xtensa/xtensa.cc
@@ -857,25 +857,26 @@ gen_float_relational (enum rtx_code test_code, /*
relational test (EQ, etc) */
rtx (*gen_fn) (rtx, rtx, rtx);
rtx brtmp;
int reverse_regs, invert;
+ bool sf = GET_MODE (cmp0) == E_SFmode;
switch (test_code)
{
- case EQ: reverse_regs = 0; invert = 0; gen_fn = gen_seq_sf; break;
- case NE: reverse_regs = 0; invert = 1; gen_fn = gen_seq_sf; break;
- case LE: reverse_regs = 0; invert = 0; gen_fn = gen_sle_sf; break;
- case GT: reverse_regs = 1; invert = 0; gen_fn = gen_slt_sf; break;
- case LT: reverse_regs = 0; invert = 0; gen_fn = gen_slt_sf; break;
- case GE: reverse_regs = 1; invert = 0; gen_fn = gen_sle_sf; break;
- case UNEQ: reverse_regs = 0; invert = 0; gen_fn = gen_suneq_sf; break;
- case LTGT: reverse_regs = 0; invert = 1; gen_fn = gen_suneq_sf; break;
- case UNLE: reverse_regs = 0; invert = 0; gen_fn = gen_sunle_sf; break;
- case UNGT: reverse_regs = 1; invert = 0; gen_fn = gen_sunlt_sf; break;
- case UNLT: reverse_regs = 0; invert = 0; gen_fn = gen_sunlt_sf; break;
- case UNGE: reverse_regs = 1; invert = 0; gen_fn = gen_sunle_sf; break;
+ case EQ: reverse_regs = 0; invert = 0; gen_fn = sf ? gen_seq_sf :
gen_seq_df; break;
+ case NE: reverse_regs = 0; invert = 1; gen_fn = sf ? gen_seq_sf :
gen_seq_df; break;
+ case LE: reverse_regs = 0; invert = 0; gen_fn = sf ? gen_sle_sf :
gen_sle_df; break;
+ case GT: reverse_regs = 1; invert = 0; gen_fn = sf ? gen_slt_sf :
gen_slt_df; break;
+ case LT: reverse_regs = 0; invert = 0; gen_fn = sf ? gen_slt_sf :
gen_slt_df; break;
+ case GE: reverse_regs = 1; invert = 0; gen_fn = sf ? gen_sle_sf :
gen_sle_df; break;
+ case UNEQ: reverse_regs = 0; invert = 0; gen_fn = sf ? gen_suneq_sf :
gen_suneq_df; break;
+ case LTGT: reverse_regs = 0; invert = 1; gen_fn = sf ? gen_suneq_sf :
gen_suneq_df; break;
+ case UNLE: reverse_regs = 0; invert = 0; gen_fn = sf ? gen_sunle_sf :
gen_sunle_df; break;
+ case UNGT: reverse_regs = 1; invert = 0; gen_fn = sf ? gen_sunlt_sf :
gen_sunlt_df; break;
+ case UNLT: reverse_regs = 0; invert = 0; gen_fn = sf ? gen_sunlt_sf :
gen_sunlt_df; break;
+ case UNGE: reverse_regs = 1; invert = 0; gen_fn = sf ? gen_sunle_sf :
gen_sunle_df; break;
case UNORDERED:
- reverse_regs = 0; invert = 0; gen_fn = gen_sunordered_sf; break;
+ reverse_regs = 0; invert = 0; gen_fn = sf ? gen_sunordered_sf :
gen_sunordered_df; break;
case ORDERED:
- reverse_regs = 0; invert = 1; gen_fn = gen_sunordered_sf; break;
+ reverse_regs = 0; invert = 1; gen_fn = sf ? gen_sunordered_sf :
gen_sunordered_df; break;
default:
fatal_insn ("bad test", gen_rtx_fmt_ee (test_code, VOIDmode, cmp0,
cmp1));
reverse_regs = 0; invert = 0; gen_fn = 0; /* avoid compiler warnings */
@@ -902,14 +903,21 @@ xtensa_expand_conditional_branch (rtx *operands,
machine_mode mode)
switch (mode)
{
case E_SFmode:
- if (TARGET_HARD_FLOAT)
+ if (TARGET_FLOAT32)
{
cmp = gen_float_relational (test_code, cmp0, cmp1);
break;
}
- /* FALLTHRU */
+ fatal_insn ("bad test", gen_rtx_fmt_ee (test_code, VOIDmode, cmp0,
cmp1));
case E_DFmode:
+ if (TARGET_FLOAT64)
+ {
+ cmp = gen_float_relational (test_code, cmp0, cmp1);
+ break;
+ }
+ /* FALLTHRU */
+
default:
fatal_insn ("bad test", gen_rtx_fmt_ee (test_code, VOIDmode, cmp0,
cmp1));
@@ -992,7 +1000,8 @@ gen_conditional_move (enum rtx_code code, machine_mode
mode,
return gen_rtx_fmt_ee (code, VOIDmode, op0, op1);
}
- if (TARGET_HARD_FLOAT && mode == SFmode)
+ if ((TARGET_FLOAT32 && mode == SFmode)
+ || (TARGET_FLOAT64 && mode == DFmode))
return gen_float_relational (code, op0, op1);
return 0;
@@ -1000,7 +1009,7 @@ gen_conditional_move (enum rtx_code code, machine_mode
mode,
int
-xtensa_expand_conditional_move (rtx *operands, int isflt)
+xtensa_expand_conditional_move (rtx *operands, machine_mode mode)
{
rtx dest = operands[0];
rtx cmp = operands[1];
@@ -1011,14 +1020,29 @@ xtensa_expand_conditional_move (rtx *operands, int
isflt)
XEXP (cmp, 0), XEXP (cmp, 1))))
return 0;
- if (isflt)
- gen_fn = (cmp_mode == SImode
- ? gen_movsfcc_internal0
- : gen_movsfcc_internal1);
- else
- gen_fn = (cmp_mode == SImode
- ? gen_movsicc_internal0
- : gen_movsicc_internal1);
+ switch (mode)
+ {
+ case E_SImode:
+ gen_fn = (cmp_mode == SImode
+ ? gen_movsicc_internal0
+ : gen_movsicc_internal1);
+ break;
+
+ case E_SFmode:
+ gen_fn = (cmp_mode == SImode
+ ? gen_movsfcc_internal0
+ : gen_movsfcc_internal1);
+ break;
+
+ case E_DFmode:
+ gen_fn = (cmp_mode == SImode
+ ? gen_movdfcc_internal0
+ : gen_movdfcc_internal1);
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
emit_insn (gen_fn (dest, XEXP (cmp, 0), operands[2], operands[3], cmp));
return 1;
@@ -1300,6 +1324,8 @@ xtensa_copy_incoming_a7 (rtx opnd)
switch (mode)
{
case E_DFmode:
+ emit_insn (gen_movdf_internal (tmp, gen_raw_REG (mode, A7_REG - 1)));
+ break;
case E_DImode:
/* Copy the value out of A7 here but keep the first word in A6 until
after the set_frame_ptr insn. Otherwise, the register allocator
@@ -1307,6 +1333,8 @@ xtensa_copy_incoming_a7 (rtx opnd)
value. */
emit_insn (gen_movsi_internal (gen_rtx_SUBREG (SImode, tmp, 4),
gen_raw_REG (SImode, A7_REG)));
+ emit_insn (gen_movsi_internal (gen_rtx_SUBREG (SImode, tmp, 0),
+ gen_rtx_REG (SImode, A7_REG - 1)));
break;
case E_SFmode:
emit_insn (gen_movsf_internal (tmp, gen_raw_REG (mode, A7_REG)));
@@ -1326,10 +1354,6 @@ xtensa_copy_incoming_a7 (rtx opnd)
cfun->machine->set_frame_ptr_insn = emit_insn (gen_set_frame_ptr ());
- /* For DF and DI mode arguments, copy the incoming value in A6 now. */
- if (mode == DFmode || mode == DImode)
- emit_insn (gen_movsi_internal (gen_rtx_SUBREG (SImode, tmp, 0),
- gen_rtx_REG (SImode, A7_REG - 1)));
entry_insns = end_sequence ();
if (cfun->machine->vararg_a7)
@@ -2103,6 +2127,8 @@ xtensa_emit_movcc (bool inverted, bool isfp, bool isbool,
rtx *operands)
static char result[64];
enum rtx_code code;
const char *op;
+ const char *dot_suffix = "";
+ int n;
code = GET_CODE (operands[4]);
if (inverted)
@@ -2127,9 +2153,26 @@ xtensa_emit_movcc (bool inverted, bool isfp, bool
isbool, rtx *operands)
default: gcc_unreachable ();
}
}
+ if (isfp)
+ {
+ switch (GET_MODE (operands[0]))
+ {
+ case E_SFmode: dot_suffix = ".s"; break;
+ case E_DFmode: dot_suffix = ".s"; break; /* It should be .d, but this
+ is supposed to be a macro
+ and it's missing in the
+ assembler. */
+ default: gcc_unreachable ();
+ }
+ }
- sprintf (result, "mov%s%s\t%%0, %%%d, %%1",
- op, isfp ? ".s" : "", inverted ? 3 : 2);
+ n = sprintf (result, "mov%s%s\t%%0, %%%d, %%1",
+ op, dot_suffix, inverted ? 3 : 2);
+ if (!isfp && GET_MODE (operands[0]) == E_DFmode)
+ {
+ sprintf (result + n, " ; mov%s\t%%D0, %%D%d, %%1",
+ op, inverted ? 3 : 2);
+ }
return result;
}
@@ -3000,7 +3043,8 @@ xtensa_option_override (void)
else if (GP_REG_P (regno))
temp = ((regno & 1) == 0 || (size <= UNITS_PER_WORD));
else if (FP_REG_P (regno))
- temp = (TARGET_HARD_FLOAT && (mode == SFmode));
+ temp = ((TARGET_FLOAT32 && mode == SFmode)
+ || (TARGET_FLOAT64 && mode == DFmode));
else if (BR_REG_P (regno))
temp = (TARGET_BOOLEANS && (mode == CCmode));
else
@@ -3123,6 +3167,8 @@ xtensa_modes_tieable_p (machine_mode mode1, machine_mode
mode2)
'G', CONST_DOUBLE:SF, print 0~3 when rval is 0.0f, 1.0f, 2.0f, or 0.5f,
respectively.
'D' REG, print second register of double-word register operand
+ 'T' REG, print register holding top bits of double-word register operand
+ 'B' REG, print register holding bottom bits of double-word register operand
'N' MEM, print address of next word following a memory operand
'v' MEM, if memory reference is volatile, output a MEMW before it
't' any constant, add "@h" suffix for top 16 bits
@@ -3157,6 +3203,20 @@ print_operand (FILE *file, rtx x, int letter)
output_operand_lossage ("invalid %%D value");
break;
+ case 'T':
+ if (REG_P (x) || SUBREG_P (x))
+ fprintf (file, "%s", reg_names[xt_true_regnum (x) +
!TARGET_BIG_ENDIAN]);
+ else
+ output_operand_lossage ("invalid %%T value");
+ break;
+
+ case 'B':
+ if (REG_P (x) || SUBREG_P (x))
+ fprintf (file, "%s", reg_names[xt_true_regnum (x) +
!!TARGET_BIG_ENDIAN]);
+ else
+ output_operand_lossage ("invalid %%B value");
+ break;
+
case 'v':
if (MEM_P (x))
{
@@ -3219,21 +3279,21 @@ print_operand (FILE *file, rtx x, int letter)
break;
case 'U':
- if (CONST_DOUBLE_P (x) && GET_MODE (x) == SFmode)
+ if (CONST_DOUBLE_P (x) && (GET_MODE (x) == SFmode || GET_MODE (x) ==
DFmode))
fprintf (file, "%d", REAL_EXP (CONST_DOUBLE_REAL_VALUE (x)) - 1);
else
output_operand_lossage ("invalid %%U value");
break;
case 'V':
- if (CONST_DOUBLE_P (x) && GET_MODE (x) == SFmode)
+ if (CONST_DOUBLE_P (x) && (GET_MODE (x) == SFmode || GET_MODE (x) ==
DFmode))
fprintf (file, "%d", 1 - REAL_EXP (CONST_DOUBLE_REAL_VALUE (x)));
else
output_operand_lossage ("invalid %%V value");
break;
case 'G':
- if (CONST_DOUBLE_P (x) && GET_MODE (x) == SFmode)
+ if (CONST_DOUBLE_P (x) && (GET_MODE (x) == SFmode || GET_MODE (x) ==
DFmode))
fprintf (file, "%d", xtensa_fp_const (CONST_DOUBLE_REAL_VALUE (x)));
else
output_operand_lossage ("invalid %%G value");
@@ -4670,9 +4730,9 @@ xtensa_rtx_costs (rtx x, machine_mode mode, int
outer_code,
case NEG:
{
if (mode == SFmode)
- *total = COSTS_N_INSNS (TARGET_HARD_FLOAT ? 1 : 50);
+ *total = COSTS_N_INSNS (TARGET_FLOAT32 ? 1 : 50);
else if (mode == DFmode)
- *total = COSTS_N_INSNS (50);
+ *total = COSTS_N_INSNS (TARGET_FLOAT64 ? 1 : 50);
else if (mode == DImode)
*total = COSTS_N_INSNS (4);
else
@@ -4684,8 +4744,10 @@ xtensa_rtx_costs (rtx x, machine_mode mode, int
outer_code,
case MINUS:
{
if (mode == SFmode)
- *total = COSTS_N_INSNS (TARGET_HARD_FLOAT ? 1 : 50);
- else if (mode == DFmode || mode == DImode)
+ *total = COSTS_N_INSNS (TARGET_FLOAT32 ? 1 : 50);
+ else if (mode == DFmode)
+ *total = COSTS_N_INSNS (TARGET_FLOAT64 ? 1 : 50);
+ else if (mode == DImode)
*total = COSTS_N_INSNS (50);
else
*total = COSTS_N_INSNS (1);
@@ -4695,9 +4757,9 @@ xtensa_rtx_costs (rtx x, machine_mode mode, int
outer_code,
case MULT:
{
if (mode == SFmode)
- *total = COSTS_N_INSNS (TARGET_HARD_FLOAT ? 4 : 50);
+ *total = COSTS_N_INSNS (TARGET_FLOAT32 ? 4 : 50);
else if (mode == DFmode)
- *total = COSTS_N_INSNS (50);
+ *total = COSTS_N_INSNS (TARGET_FLOAT64 ? 4 : 50);
else if (mode == DImode)
*total = COSTS_N_INSNS (TARGET_MUL32_HIGH ? 10 : 50);
else if (TARGET_MUL32)
@@ -4716,12 +4778,12 @@ xtensa_rtx_costs (rtx x, machine_mode mode, int
outer_code,
{
if (mode == SFmode)
{
- *total = COSTS_N_INSNS (TARGET_HARD_FLOAT_DIV ? 8 : 50);
+ *total = COSTS_N_INSNS (TARGET_FLOAT32_DIV ? 8 : 50);
return true;
}
else if (mode == DFmode)
{
- *total = COSTS_N_INSNS (50);
+ *total = COSTS_N_INSNS (TARGET_FLOAT64_DIV ? 8 : 50);
return true;
}
}
@@ -4741,7 +4803,9 @@ xtensa_rtx_costs (rtx x, machine_mode mode, int
outer_code,
case SQRT:
if (mode == SFmode)
- *total = COSTS_N_INSNS (TARGET_HARD_FLOAT_SQRT ? 8 : 50);
+ *total = COSTS_N_INSNS (TARGET_FLOAT32_SQRT ? 8 : 50);
+ else if (mode == DFmode)
+ *total = COSTS_N_INSNS (TARGET_FLOAT64_SQRT ? 8 : 50);
else
*total = COSTS_N_INSNS (50);
return true;
@@ -5112,11 +5176,14 @@ xtensa_legitimate_constant_p (machine_mode mode
ATTRIBUTE_UNUSED, rtx x)
|| ! xtensa_postreload_completed_p ()
|| xtensa_simm12b (INTVAL (x));
- if (CONST_DOUBLE_P (x) && GET_MODE (x) == SFmode)
+ if (CONST_DOUBLE_P (x) && (GET_MODE (x) == SFmode || GET_MODE (x) == DFmode))
{
int i = xtensa_fp_const (CONST_DOUBLE_REAL_VALUE (x));
- return i == 0 || (TARGET_HARD_FLOAT_CONST_S && i > 0);
+ return i == 0 || (TARGET_HARD_FLOAT_CONST &&
+ ((GET_MODE (x) == SFmode && TARGET_FLOAT32)
+ || (GET_MODE (x) == DFmode && TARGET_FLOAT64))
+ && i > 0);
}
return !xtensa_tls_referenced_p (x);
@@ -5603,7 +5670,7 @@ xtensa_zero_call_used_regs (HARD_REG_SET selected_regs)
rtvec_alloc (0),
UNKNOWN_LOCATION));
}
- else if (TARGET_HARD_FLOAT && FP_REG_P (regno))
+ else if (TARGET_FLOAT32 && FP_REG_P (regno))
emit_move_insn (gen_rtx_REG (SFmode, regno),
gen_rtx_REG (SFmode, zeroed_regno));
else if (TARGET_MAC16 && ACC_REG_P (regno))
@@ -5912,7 +5979,7 @@ FPreg_neg_scaled_simm12b (rtx_insn *insn)
REG_DEAD (reg:SF gpr)
where cst is a negatively-scaled signed 12-bit integer immediate
value. */
- if (TARGET_HARD_FLOAT && !TARGET_CONST16
+ if (TARGET_FLOAT32 && !TARGET_CONST16
&& GET_CODE (pat = PATTERN (insn)) == SET
&& REG_P (dest = SET_DEST (pat)) && GP_REG_P (REGNO (dest))
&& GET_MODE (dest) == SFmode
diff --git a/gcc/config/xtensa/xtensa.h b/gcc/config/xtensa/xtensa.h
index ae0f32bbb2e8..3a98ea9f08d3 100644
--- a/gcc/config/xtensa/xtensa.h
+++ b/gcc/config/xtensa/xtensa.h
@@ -38,11 +38,17 @@ along with GCC; see the file COPYING3. If not see
#define TARGET_CLAMPS XCHAL_HAVE_CLAMPS
#define TARGET_DEPBITS XCHAL_HAVE_DEPBITS
#define TARGET_BOOLEANS XCHAL_HAVE_BOOLEANS
-#define TARGET_HARD_FLOAT XCHAL_HAVE_FP
-#define TARGET_HARD_FLOAT_DIV XCHAL_HAVE_FP_DIV
-#define TARGET_HARD_FLOAT_RECIP XCHAL_HAVE_FP_RECIP
-#define TARGET_HARD_FLOAT_SQRT XCHAL_HAVE_FP_SQRT
-#define TARGET_HARD_FLOAT_RSQRT XCHAL_HAVE_FP_RSQRT
+#define TARGET_HARD_FLOAT (XCHAL_HAVE_FP || XCHAL_HAVE_DFP)
+#define TARGET_FLOAT32 XCHAL_HAVE_FP
+#define TARGET_FLOAT64 XCHAL_HAVE_DFP
+#define TARGET_FLOAT32_DIV XCHAL_HAVE_FP_DIV
+#define TARGET_FLOAT32_RECIP XCHAL_HAVE_FP_RECIP
+#define TARGET_FLOAT32_SQRT XCHAL_HAVE_FP_SQRT
+#define TARGET_FLOAT32_RSQRT XCHAL_HAVE_FP_RSQRT
+#define TARGET_FLOAT64_DIV XCHAL_HAVE_DFP_DIV
+#define TARGET_FLOAT64_RECIP XCHAL_HAVE_DFP_RECIP
+#define TARGET_FLOAT64_SQRT XCHAL_HAVE_DFP_SQRT
+#define TARGET_FLOAT64_RSQRT XCHAL_HAVE_DFP_RSQRT
#define TARGET_HARD_FLOAT_POSTINC XCHAL_HAVE_FP_POSTINC
#define TARGET_ABS XCHAL_HAVE_ABS
#define TARGET_ADDX XCHAL_HAVE_ADDX
@@ -58,9 +64,11 @@ along with GCC; see the file COPYING3. If not see
#define TARGET_SALT (XTENSA_MARCH_EARLIEST >= 270000)
#define TARGET_DEFAULT (MASK_SERIALIZE_VOLATILE)
-#define TARGET_HARD_FLOAT_CONST_S \
- (TARGET_HARD_FLOAT_DIV || TARGET_HARD_FLOAT_RECIP \
- || TARGET_HARD_FLOAT_SQRT || TARGET_HARD_FLOAT_RSQRT)
+#define TARGET_HARD_FLOAT_CONST \
+ (TARGET_FLOAT32_DIV || TARGET_FLOAT32_RECIP \
+ || TARGET_FLOAT32_SQRT || TARGET_FLOAT32_RSQRT \
+ || TARGET_FLOAT64_DIV || TARGET_FLOAT64_RECIP \
+ || TARGET_FLOAT64_SQRT || TARGET_FLOAT64_RSQRT)
#ifndef HAVE_AS_TLS
#define HAVE_AS_TLS 0
@@ -117,7 +125,7 @@ along with GCC; see the file COPYING3. If not see
#define MIN_UNITS_PER_WORD 4
/* Width of a floating point register. */
-#define UNITS_PER_FPREG 4
+#define UNITS_PER_FPREG (TARGET_FLOAT64 ? 8 : 4)
/* Size in bits of various types on the target machine. */
#define INT_TYPE_SIZE 32
diff --git a/gcc/config/xtensa/xtensa.md b/gcc/config/xtensa/xtensa.md
index 1bc05a8bdc74..458ffb0aea09 100644
--- a/gcc/config/xtensa/xtensa.md
+++ b/gcc/config/xtensa/xtensa.md
@@ -91,6 +91,11 @@
(define_mode_iterator HQI [HI QI])
(define_mode_attr mode_bits [(HI "16") (QI "8")])
+;; Single/Double precision floating point iterator
+(define_mode_iterator SDF [SF DF])
+(define_mode_attr sd [(SF "s") (DF "d")])
+(define_mode_attr sdf_mode_bits [(SF "32") (DF "64")])
+
;; This iterator and attribute allow signed/unsigned FP truncations to be
;; generated from one template.
(define_code_iterator any_fix [fix unsigned_fix])
@@ -307,14 +312,14 @@
(const_int 5)
(const_int 6)))])
-(define_insn "addsf3"
- [(set (match_operand:SF 0 "register_operand" "=f")
- (plus:SF (match_operand:SF 1 "register_operand" "%f")
- (match_operand:SF 2 "register_operand" "f")))]
- "TARGET_HARD_FLOAT"
- "add.s\t%0, %1, %2"
+(define_insn "add<mode>3"
+ [(set (match_operand:SDF 0 "register_operand" "=f")
+ (plus:SDF (match_operand:SDF 1 "register_operand" "%f")
+ (match_operand:SDF 2 "register_operand" "f")))]
+ "TARGET_FLOAT<sdf_mode_bits>"
+ "add.<sd>\t%0, %1, %2"
[(set_attr "type" "fmadd")
- (set_attr "mode" "SF")
+ (set_attr "mode" "<MODE>")
(set_attr "length" "3")])
@@ -377,14 +382,14 @@
DONE;
})
-(define_insn "subsf3"
- [(set (match_operand:SF 0 "register_operand" "=f")
- (minus:SF (match_operand:SF 1 "register_operand" "f")
- (match_operand:SF 2 "register_operand" "f")))]
- "TARGET_HARD_FLOAT"
- "sub.s\t%0, %1, %2"
+(define_insn "sub<mode>3"
+ [(set (match_operand:SDF 0 "register_operand" "=f")
+ (minus:SDF (match_operand:SDF 1 "register_operand" "f")
+ (match_operand:SDF 2 "register_operand" "f")))]
+ "TARGET_FLOAT<sdf_mode_bits>"
+ "sub.<sd>\t%0, %1, %2"
[(set_attr "type" "fmadd")
- (set_attr "mode" "SF")
+ (set_attr "mode" "<MODE>")
(set_attr "length" "3")])
@@ -486,37 +491,37 @@
(set_attr "mode" "SI")
(set_attr "length" "3")])
-(define_insn "mulsf3"
- [(set (match_operand:SF 0 "register_operand" "=f")
- (mult:SF (match_operand:SF 1 "register_operand" "%f")
- (match_operand:SF 2 "register_operand" "f")))]
- "TARGET_HARD_FLOAT"
- "mul.s\t%0, %1, %2"
+(define_insn "mul<mode>3"
+ [(set (match_operand:SDF 0 "register_operand" "=f")
+ (mult:SDF (match_operand:SDF 1 "register_operand" "%f")
+ (match_operand:SDF 2 "register_operand" "f")))]
+ "TARGET_FLOAT<sdf_mode_bits>"
+ "mul.<sd>\t%0, %1, %2"
[(set_attr "type" "fmadd")
- (set_attr "mode" "SF")
+ (set_attr "mode" "<MODE>")
(set_attr "length" "3")])
-(define_insn "fmasf4"
- [(set (match_operand:SF 0 "register_operand" "=f")
- (fma:SF (match_operand:SF 1 "register_operand" "f")
- (match_operand:SF 2 "register_operand" "f")
- (match_operand:SF 3 "register_operand" "0")))]
- "TARGET_HARD_FLOAT"
- "madd.s\t%0, %1, %2"
+(define_insn "fma<mode>4"
+ [(set (match_operand:SDF 0 "register_operand" "=f")
+ (fma:SDF (match_operand:SDF 1 "register_operand" "f")
+ (match_operand:SDF 2 "register_operand" "f")
+ (match_operand:SDF 3 "register_operand" "0")))]
+ "TARGET_FLOAT<sdf_mode_bits>"
+ "madd.<sd>\t%0, %1, %2"
[(set_attr "type" "fmadd")
- (set_attr "mode" "SF")
+ (set_attr "mode" "<MODE>")
(set_attr "length" "3")])
;; Note that (C - A*B) = (-A*B + C)
-(define_insn "fnmasf4"
- [(set (match_operand:SF 0 "register_operand" "=f")
- (fma:SF (neg:SF (match_operand:SF 1 "register_operand" "f"))
- (match_operand:SF 2 "register_operand" "f")
- (match_operand:SF 3 "register_operand" "0")))]
- "TARGET_HARD_FLOAT"
- "msub.s\t%0, %1, %2"
+(define_insn "fnma<mode>4"
+ [(set (match_operand:SDF 0 "register_operand" "=f")
+ (fma:SDF (neg:SDF (match_operand:SDF 1 "register_operand" "f"))
+ (match_operand:SDF 2 "register_operand" "f")
+ (match_operand:SDF 3 "register_operand" "0")))]
+ "TARGET_FLOAT<sdf_mode_bits>"
+ "msub.<sd>\t%0, %1, %2"
[(set_attr "type" "fmadd")
- (set_attr "mode" "SF")
+ (set_attr "mode" "<MODE>")
(set_attr "length" "3")])
@@ -577,13 +582,13 @@
(set_attr "mode" "SI")
(set_attr "length" "3")])
-(define_insn "abssf2"
- [(set (match_operand:SF 0 "register_operand" "=f")
- (abs:SF (match_operand:SF 1 "register_operand" "f")))]
- "TARGET_HARD_FLOAT"
- "abs.s\t%0, %1"
+(define_insn "abs<mode>2"
+ [(set (match_operand:SDF 0 "register_operand" "=f")
+ (abs:SDF (match_operand:SDF 1 "register_operand" "f")))]
+ "TARGET_FLOAT<sdf_mode_bits>"
+ "abs.<sd>\t%0, %1"
[(set_attr "type" "farith")
- (set_attr "mode" "SF")
+ (set_attr "mode" "<MODE>")
(set_attr "length" "3")])
@@ -752,14 +757,14 @@
DONE;
})
-(define_insn_and_split "negsf2"
- [(set (match_operand:SF 0 "register_operand")
- (neg:SF (match_operand:SF 1 "register_operand")))
+(define_insn_and_split "neg<mode>2"
+ [(set (match_operand:SDF 0 "register_operand")
+ (neg:SDF (match_operand:SDF 1 "register_operand")))
(clobber (match_scratch:SI 2))]
- "TARGET_HARD_FLOAT"
+ "TARGET_FLOAT<sdf_mode_bits>"
{@ [cons: =0, 1, =2; attrs: type, length]
[D, D, &a; arith , 7] #
- [f, f, X; farith, 3] neg.s\t%0, %1
+ [f, f, X; farith, 3] neg.<sd>\t%0, %1
}
"&& reload_completed && REG_P (operands[2])"
[(set (match_dup 2)
@@ -767,11 +772,17 @@
(set (match_dup 2)
(ashift:SI (match_dup 2)
(const_int 31)))
- (set (subreg:SI (match_dup 0) 0)
- (plus:SI (subreg:SI (match_dup 1) 0)
+ (set (match_dup 3)
+ (plus:SI (match_dup 4)
(match_dup 2)))]
- ""
- [(set_attr "mode" "SF")])
+{
+ if (GET_MODE_SIZE (SImode) < GET_MODE_SIZE (<MODE>mode))
+ emit_insn (gen_movsi (gen_rtx_SUBREG (SImode, operands[0],
subreg_lowpart_offset (SImode, <MODE>mode)),
+ gen_rtx_SUBREG (SImode, operands[1],
subreg_lowpart_offset (SImode, <MODE>mode))));
+ operands[3] = gen_rtx_SUBREG (SImode, operands[0], subreg_highpart_offset
(SImode, <MODE>mode));
+ operands[4] = gen_rtx_SUBREG (SImode, operands[1], subreg_highpart_offset
(SImode, <MODE>mode));
+}
+ [(set_attr "mode" "<MODE>")])
;; Logical instructions.
@@ -1188,79 +1199,97 @@
;; Conversions.
-(define_insn "fix<s_fix>_truncsfsi2"
+(define_insn "fix<s_fix>_trunc<mode>si2"
[(set (match_operand:SI 0 "register_operand" "=a")
- (any_fix:SI (match_operand:SF 1 "register_operand" "f")))]
- "TARGET_HARD_FLOAT"
- "<m_fix>.s\t%0, %1, 0"
+ (any_fix:SI (match_operand:SDF 1 "register_operand" "f")))]
+ "TARGET_FLOAT<sdf_mode_bits>"
+ "<m_fix>.<sd>\t%0, %1, 0"
[(set_attr "type" "fconv")
- (set_attr "mode" "SF")
+ (set_attr "mode" "<MODE>")
(set_attr "length" "3")])
-(define_insn "*fix<s_fix>_truncsfsi2_2x"
+(define_insn "*fix<s_fix>_trunc<mode>si2_2x"
[(set (match_operand:SI 0 "register_operand" "=a")
- (any_fix:SI (plus:SF (match_operand:SF 1 "register_operand" "f")
- (match_dup 1))))]
- "TARGET_HARD_FLOAT"
- "<m_fix>.s\t%0, %1, 1"
+ (any_fix:SI (plus:SDF (match_operand:SDF 1 "register_operand" "f")
+ (match_dup 1))))]
+ "TARGET_FLOAT<sdf_mode_bits>"
+ "<m_fix>.<sd>\t%0, %1, 1"
[(set_attr "type" "fconv")
- (set_attr "mode" "SF")
+ (set_attr "mode" "<MODE>")
(set_attr "length" "3")])
-(define_insn "*fix<s_fix>_truncsfsi2_scaled"
+(define_insn "*fix<s_fix>_trunc<mode>si2_scaled"
[(set (match_operand:SI 0 "register_operand" "=a")
- (any_fix:SI (mult:SF (match_operand:SF 1 "register_operand" "f")
- (match_operand:SF 2 "fix_scaling_operand" ""))))]
- "TARGET_HARD_FLOAT"
- "<m_fix>.s\t%0, %1, %U2"
+ (any_fix:SI (mult:SDF (match_operand:SDF 1 "register_operand" "f")
+ (match_operand:SDF 2 "fix_scaling_operand" ""))))]
+ "TARGET_FLOAT<sdf_mode_bits>"
+ "<m_fix>.<sd>\t%0, %1, %U2"
[(set_attr "type" "fconv")
- (set_attr "mode" "SF")
+ (set_attr "mode" "<MODE>")
(set_attr "length" "3")])
-(define_insn "float<s_float>sisf2"
- [(set (match_operand:SF 0 "register_operand" "=f")
- (any_float:SF (match_operand:SI 1 "register_operand" "a")))]
- "TARGET_HARD_FLOAT"
- "<m_float>.s\t%0, %1, 0"
+(define_insn "float<s_float>si<mode>2"
+ [(set (match_operand:SDF 0 "register_operand" "=f")
+ (any_float:SDF (match_operand:SI 1 "register_operand" "a")))]
+ "TARGET_FLOAT<sdf_mode_bits>"
+ "<m_float>.<sd>\t%0, %1, 0"
[(set_attr "type" "fconv")
- (set_attr "mode" "SF")
+ (set_attr "mode" "<MODE>")
(set_attr "length" "3")])
-(define_insn "*float<s_float>sisf2_scaled"
- [(set (match_operand:SF 0 "register_operand" "=f")
- (mult:SF (any_float:SF (match_operand:SI 1 "register_operand" "a"))
- (match_operand:SF 2 "float_scaling_operand" "")))]
- "TARGET_HARD_FLOAT"
- "<m_float>.s\t%0, %1, %V2"
+(define_insn "*float<s_float>si<mode>2_scaled"
+ [(set (match_operand:SDF 0 "register_operand" "=f")
+ (mult:SDF (any_float:SDF (match_operand:SI 1 "register_operand" "a"))
+ (match_operand:SDF 2 "float_scaling_operand" "")))]
+ "TARGET_FLOAT<sdf_mode_bits>"
+ "<m_float>.<sd>\t%0, %1, %V2"
[(set_attr "type" "fconv")
- (set_attr "mode" "SF")
+ (set_attr "mode" "<MODE>")
(set_attr "length" "3")])
-(define_insn "l<m_round>sfsi2"
+(define_insn "l<m_round><mode>si2"
[(set (match_operand:SI 0 "register_operand" "=a")
- (unspec:SI [(match_operand:SF 1 "register_operand" "f")] ANY_ROUND))]
- "TARGET_HARD_FLOAT"
- "<m_round>.s\t%0, %1, 0"
+ (unspec:SI [(match_operand:SDF 1 "register_operand" "f")] ANY_ROUND))]
+ "TARGET_FLOAT<sdf_mode_bits>"
+ "<m_round>.<sd>\t%0, %1, 0"
[(set_attr "type" "fconv")
- (set_attr "mode" "SF")
+ (set_attr "mode" "<MODE>")
(set_attr "length" "3")])
-(define_insn "*l<m_round>sfsi2_2x"
+(define_insn "*l<m_round><mode>si2_2x"
[(set (match_operand:SI 0 "register_operand" "=a")
- (unspec:SI [(plus:SF (match_operand:SF 1 "register_operand" "f")
- (match_dup 1))] ANY_ROUND))]
- "TARGET_HARD_FLOAT"
- "<m_round>.s\t%0, %1, 1"
+ (unspec:SI [(plus:SDF (match_operand:SDF 1 "register_operand" "f")
+ (match_dup 1))] ANY_ROUND))]
+ "TARGET_FLOAT<sdf_mode_bits>"
+ "<m_round>.<sd>\t%0, %1, 1"
[(set_attr "type" "fconv")
- (set_attr "mode" "SF")
+ (set_attr "mode" "<MODE>")
(set_attr "length" "3")])
-(define_insn "*l<m_round>sfsi2_scaled"
+(define_insn "*l<m_round><mode>si2_scaled"
[(set (match_operand:SI 0 "register_operand" "=a")
- (unspec:SI [(mult:SF (match_operand:SF 1 "register_operand" "f")
- (match_operand:SF 2 "fix_scaling_operand" ""))]
ANY_ROUND))]
- "TARGET_HARD_FLOAT"
- "<m_round>.s\t%0, %1, %U2"
+ (unspec:SI [(mult:SDF (match_operand:SDF 1 "register_operand" "f")
+ (match_operand:SDF 2 "fix_scaling_operand" ""))]
ANY_ROUND))]
+ "TARGET_FLOAT<sdf_mode_bits>"
+ "<m_round>.<sd>\t%0, %1, %U2"
+ [(set_attr "type" "fconv")
+ (set_attr "mode" "<MODE>")
+ (set_attr "length" "3")])
+
+(define_insn "extendsfdf2"
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (float_extend:DF (match_operand:SF 1 "register_operand" "f")))]
+ "TARGET_FLOAT64"
+ "cvtd.s\t%0, %1"
+ [(set_attr "type" "fconv")
+ (set_attr "mode" "DF")
+ (set_attr "length" "3")])
+
+(define_insn "truncdfsf2"
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (float_truncate:SF (match_operand:DF 1 "register_operand" "f")))]
+ "TARGET_FLOAT64"
+ "cvts.d\t%0, %1"
[(set_attr "type" "fconv")
(set_attr "mode" "SF")
(set_attr "length" "3")])
@@ -1496,7 +1525,7 @@
(match_operand:SI 2 "fpmem_offset_operand" ""))))
(set (match_dup 1)
(plus:SI (match_dup 1) (match_dup 2)))]
- "TARGET_HARD_FLOAT && !TARGET_HARD_FLOAT_POSTINC"
+ "TARGET_FLOAT32 && !TARGET_HARD_FLOAT_POSTINC"
{
if (TARGET_SERIALIZE_VOLATILE && volatile_refs_p (PATTERN (insn)))
output_asm_insn ("memw", operands);
@@ -1512,7 +1541,7 @@
(match_operand:SF 2 "register_operand" "f"))
(set (match_dup 0)
(plus:SI (match_dup 0) (match_dup 1)))]
- "TARGET_HARD_FLOAT && !TARGET_HARD_FLOAT_POSTINC"
+ "TARGET_FLOAT32 && !TARGET_HARD_FLOAT_POSTINC"
{
if (TARGET_SERIALIZE_VOLATILE && volatile_refs_p (PATTERN (insn)))
output_asm_insn ("memw", operands);
@@ -1522,36 +1551,36 @@
(set_attr "mode" "SF")
(set_attr "length" "3")])
-(define_insn "*lsip"
- [(set (match_operand:SF 0 "register_operand" "=f")
- (mem:SF (match_operand:SI 1 "register_operand" "+a")))
+(define_insn "*l<sd>ip"
+ [(set (match_operand:SDF 0 "register_operand" "=f")
+ (mem:SDF (match_operand:SI 1 "register_operand" "+a")))
(set (match_dup 1)
(plus:SI (match_dup 1)
(match_operand:SI 2 "fpmem_offset_operand" "")))]
- "TARGET_HARD_FLOAT && TARGET_HARD_FLOAT_POSTINC"
+ "TARGET_FLOAT<sdf_mode_bits> && TARGET_HARD_FLOAT_POSTINC"
{
if (TARGET_SERIALIZE_VOLATILE && volatile_refs_p (PATTERN (insn)))
output_asm_insn ("memw", operands);
- return "lsip\t%0, %1, %2";
+ return "l<sd>ip\t%0, %1, %2";
}
[(set_attr "type" "fload")
- (set_attr "mode" "SF")
+ (set_attr "mode" "<MODE>")
(set_attr "length" "3")])
-(define_insn "*ssip"
- [(set (mem:SF (match_operand:SI 0 "register_operand" "+a"))
- (match_operand:SF 1 "register_operand" "f"))
+(define_insn "*s<sd>ip"
+ [(set (mem:SDF (match_operand:SI 0 "register_operand" "+a"))
+ (match_operand:SDF 1 "register_operand" "f"))
(set (match_dup 0)
(plus:SI (match_dup 0)
(match_operand:SI 2 "fpmem_offset_operand" "")))]
- "TARGET_HARD_FLOAT && TARGET_HARD_FLOAT_POSTINC"
+ "TARGET_FLOAT<sdf_mode_bits> && TARGET_HARD_FLOAT_POSTINC"
{
if (TARGET_SERIALIZE_VOLATILE && volatile_refs_p (PATTERN (insn)))
output_asm_insn ("memw", operands);
- return "ssip\t%1, %0, %2";
+ return "s<sd>ip\t%1, %0, %2";
}
[(set_attr "type" "fstore")
- (set_attr "mode" "SF")
+ (set_attr "mode" "<MODE>")
(set_attr "length" "3")])
;; 64-bit floating point moves
@@ -1561,7 +1590,8 @@
(match_operand:DF 1 "general_operand" ""))]
""
{
- if (!TARGET_CONST16 && !TARGET_AUTO_LITPOOLS && CONST_DOUBLE_P (operands[1]))
+ if (! satisfies_constraint_Gc (operands[1])
+ && !TARGET_CONST16 && !TARGET_AUTO_LITPOOLS && CONST_DOUBLE_P
(operands[1]))
operands[1] = force_const_mem (DFmode, operands[1]);
if (!register_operand (operands[0], DFmode)
@@ -1577,17 +1607,25 @@
"register_operand (operands[0], DFmode)
|| register_operand (operands[1], DFmode)"
{@ [cons: =0, 1; attrs: type, length]
- [a, r; move, 6] #
- [a, Y; load, 6] ^
- [W, iF; move, 12] ^
- [a, T; load, 6] ^
- [a, U; load, 6] ^
- [U, r; store, 6] ^
+ [f, Gc; farith, 3] const.d\t%0, %G1
+ [f, r; farith, 3] wfrd\t%0, %T1, %B1
+ [a, f; farith, 6] rfrd\t%T0, %1\;rfr\t%B0, %1
+ [f, f; farith, 3] mov.d\t%0, %1
+ [f, U; fload , 3] %v1ldi\t%0, %1
+ [U, f; fstore, 3] %v0sdi\t%1, %0
+ [a, r; move , 6] df-move-a-from-r\t%0, %1
+ [a, Y; load , 6] df-load-a-from-Y\t%0, %1
+ [a, T; load , 6] df-load-a-from-T\t%0, %1
+ [a, U; load , 6] df-load-a-from-U\t%0, %1
+ [U, r; store , 6] df-store-r-to-U\t%0, %1
}
"&& reload_completed"
[(set (match_dup 0) (match_dup 2))
(set (match_dup 1) (match_dup 3))]
{
+ if ((register_operand (operands[0], DFmode) && REGNO_REG_CLASS (REGNO
(operands[0])) == FP_REGS)
+ || (register_operand (operands[1], DFmode) && REGNO_REG_CLASS (REGNO
(operands[1])) == FP_REGS))
+ FAIL;
xtensa_split_operand_pair (operands, SFmode);
}
[(set_attr "mode" "DF")])
@@ -1912,14 +1950,14 @@
DONE;
})
-(define_expand "cbranchsf4"
+(define_expand "cbranch<mode>4"
[(match_operator 0 "comparison_operator"
- [(match_operand:SF 1 "register_operand")
- (match_operand:SF 2 "register_operand")])
+ [(match_operand:SDF 1 "register_operand")
+ (match_operand:SDF 2 "register_operand")])
(match_operand 3 "")]
- "TARGET_HARD_FLOAT"
+ "TARGET_FLOAT<sdf_mode_bits>"
{
- xtensa_expand_conditional_branch (operands, SFmode);
+ xtensa_expand_conditional_branch (operands, <MODE>mode);
DONE;
})
@@ -2400,14 +2438,14 @@
DONE;
})
-(define_expand "cstoresf4"
+(define_expand "cstore<mode>4"
[(match_operand:SI 0 "register_operand")
(match_operator:SI 1 "comparison_operator"
- [(match_operand:SF 2 "register_operand")
- (match_operand:SF 3 "register_operand")])]
- "TARGET_HARD_FLOAT"
+ [(match_operand:SDF 2 "register_operand")
+ (match_operand:SDF 3 "register_operand")])]
+ "TARGET_FLOAT<sdf_mode_bits>"
{
- if (!xtensa_expand_scc (operands, SFmode))
+ if (!xtensa_expand_scc (operands, <MODE>mode))
FAIL;
DONE;
})
@@ -2423,19 +2461,19 @@
(match_operand:SI 3 "register_operand" "")))]
""
{
- if (!xtensa_expand_conditional_move (operands, 0))
+ if (!xtensa_expand_conditional_move (operands, SImode))
FAIL;
DONE;
})
-(define_expand "movsfcc"
- [(set (match_operand:SF 0 "register_operand" "")
- (if_then_else:SF (match_operand 1 "comparison_operator" "")
- (match_operand:SF 2 "register_operand" "")
- (match_operand:SF 3 "register_operand" "")))]
+(define_expand "mov<mode>cc"
+ [(set (match_operand:SDF 0 "register_operand" "")
+ (if_then_else:SDF (match_operand 1 "comparison_operator" "")
+ (match_operand:SDF 2 "register_operand" "")
+ (match_operand:SDF 3 "register_operand" "")))]
""
{
- if (!xtensa_expand_conditional_move (operands, 1))
+ if (!xtensa_expand_conditional_move (operands, <MODE>mode))
FAIL;
DONE;
})
@@ -2468,13 +2506,13 @@
}
[(set_attr "mode" "SI")])
-(define_insn "movsfcc_internal0"
- [(set (match_operand:SF 0 "register_operand")
- (if_then_else:SF (match_operator 4 "branch_operator"
- [(match_operand:SI 1 "register_operand")
- (const_int 0)])
- (match_operand:SF 2 "register_operand")
- (match_operand:SF 3 "register_operand")))]
+(define_insn "mov<mode>cc_internal0"
+ [(set (match_operand:SDF 0 "register_operand")
+ (if_then_else:SDF (match_operator 4 "branch_operator"
+ [(match_operand:SI 1 "register_operand")
+ (const_int 0)])
+ (match_operand:SDF 2 "register_operand")
+ (match_operand:SDF 3 "register_operand")))]
""
{@ [cons: =0, 1, 2, 3; attrs: type, length]
[a, r, r, 0; move, 3] << xtensa_emit_movcc (false, false, false,
operands);
@@ -2482,15 +2520,15 @@
[f, r, f, 0; move, 3] << xtensa_emit_movcc (false, true, false, operands);
[f, r, 0, f; move, 3] << xtensa_emit_movcc (true, true, false, operands);
}
- [(set_attr "mode" "SF")])
-
-(define_insn "movsfcc_internal1"
- [(set (match_operand:SF 0 "register_operand")
- (if_then_else:SF (match_operator 4 "boolean_operator"
- [(match_operand:CC 1 "register_operand")
- (const_int 0)])
- (match_operand:SF 2 "register_operand")
- (match_operand:SF 3 "register_operand")))]
+ [(set_attr "mode" "<MODE>")])
+
+(define_insn "mov<mode>cc_internal1"
+ [(set (match_operand:SDF 0 "register_operand")
+ (if_then_else:SDF (match_operator 4 "boolean_operator"
+ [(match_operand:CC 1 "register_operand")
+ (const_int 0)])
+ (match_operand:SDF 2 "register_operand")
+ (match_operand:SDF 3 "register_operand")))]
"TARGET_BOOLEANS"
{@ [cons: =0, 1, 2, 3; attrs: type, length]
[a, b, r, 0; move, 3] << xtensa_emit_movcc (false, false, true, operands);
@@ -2498,17 +2536,17 @@
[f, b, f, 0; move, 3] << xtensa_emit_movcc (false, true, true, operands);
[f, b, 0, f; move, 3] << xtensa_emit_movcc (true, true, true, operands);
}
- [(set_attr "mode" "SF")])
+ [(set_attr "mode" "<MODE>")])
;; Floating-point comparisons.
-(define_insn "s<code>_sf"
+(define_insn "s<code>_<mode>"
[(set (match_operand:CC 0 "register_operand" "=b")
- (any_scc_sf:CC (match_operand:SF 1 "register_operand" "f")
- (match_operand:SF 2 "register_operand" "f")))]
- "TARGET_HARD_FLOAT"
- "<scc_sf>.s\t%0, %1, %2"
+ (any_scc_sf:CC (match_operand:SDF 1 "register_operand" "f")
+ (match_operand:SDF 2 "register_operand" "f")))]
+ "TARGET_FLOAT<sdf_mode_bits>"
+ "<scc_sf>.<sd>\t%0, %1, %2"
[(set_attr "type" "farith")
(set_attr "mode" "BL")
(set_attr "length" "3")])
diff --git a/gcc/testsuite/gcc.target/xtensa/constsynthV2_O2_costs0.c
b/gcc/testsuite/gcc.target/xtensa/constsynthV2_O2_costs0.c
index a32d75c360ab..7bbee3a26202 100644
--- a/gcc/testsuite/gcc.target/xtensa/constsynthV2_O2_costs0.c
+++ b/gcc/testsuite/gcc.target/xtensa/constsynthV2_O2_costs0.c
@@ -16,4 +16,5 @@ _Complex double test(int a[], float b[])
return 1-1i;
}
-/* { dg-final { scan-assembler-times "l32r" 10 } } */
+/* { dg-final { scan-assembler-times "l32r" 10 { target { ! hard_float } } } }
*/
+/* { dg-final { scan-assembler-times "l32r" 9 { target { hard_float } } } } */
diff --git a/gcc/testsuite/gcc.target/xtensa/elim_callee_saved.c
b/gcc/testsuite/gcc.target/xtensa/elim_callee_saved.c
index 69e5be35dfd0..47e9613cd458 100644
--- a/gcc/testsuite/gcc.target/xtensa/elim_callee_saved.c
+++ b/gcc/testsuite/gcc.target/xtensa/elim_callee_saved.c
@@ -34,5 +34,6 @@ int __attribute__((optimize(0))) test3(int a) {
return bar() + a;
}
-/* { dg-final { scan-assembler-times "mov\t|mov.n\t" 20 } } */
+/* { dg-final { scan-assembler-times "mov\t|mov.n\t" 20 { target { !
hard_float } } } } */
+/* { dg-final { scan-assembler-times "mov\t|mov.n\t" 7 { target { hard_float }
} } } */
/* { dg-final { scan-assembler-times "a15, 8" 2 } } */
--
2.47.3