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

Reply via email to