diff --git a/gcc/config/xtensa/xtensa.cc b/gcc/config/xtensa/xtensa.cc
index 2e7a9df32d2..7573b55b36b 100644
--- a/gcc/config/xtensa/xtensa.cc
+++ b/gcc/config/xtensa/xtensa.cc
@@ -110,6 +110,7 @@ struct GTY(()) machine_function
    rtx last_logues_a9_content;
    HARD_REG_SET eliminated_callee_saved;
    hash_map<rtx, int> *litpool_usage;
+  int hard_float_insn_usage;
  };
  
  static void xtensa_option_override (void);
@@ -203,6 +204,7 @@ static rtx xtensa_delegitimize_address (rtx);
  static reg_class_t xtensa_ira_change_pseudo_allocno_class (int, reg_class_t,
  							   reg_class_t);
  static HARD_REG_SET xtensa_zero_call_used_regs (HARD_REG_SET);
+static reg_class_t xtensa_spill_class (reg_class_t, machine_mode);
  
  
  
@@ -376,6 +378,9 @@ static HARD_REG_SET xtensa_zero_call_used_regs (HARD_REG_SET);
  #undef TARGET_ZERO_CALL_USED_REGS
  #define TARGET_ZERO_CALL_USED_REGS xtensa_zero_call_used_regs
  
+#undef TARGET_SPILL_CLASS
+#define TARGET_SPILL_CLASS xtensa_spill_class
+
  struct gcc_target targetm = TARGET_INITIALIZER;
  
  
@@ -3040,7 +3045,7 @@ 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_HARD_FLOAT && (mode == SFmode || mode == SImode));
  	  else if (BR_REG_P (regno))
  	    temp = (TARGET_BOOLEANS && (mode == CCmode));
  	  else
@@ -5671,4 +5676,71 @@ xtensa_zero_call_used_regs (HARD_REG_SET selected_regs)
    return selected_regs;
  }
  
+/* Implement TARGET_SPILL_CLASS.
+
+   This hook is called several times during the LRA pass, for each function
+   being compiled.  */
+
+static reg_class_t
+xtensa_spill_class (reg_class_t rclass, machine_mode mode)
+{
+  rtx_insn *insn;
+
+  /* This does not apply unless all of the following conditions are met:
+      - The Floating-Point Coprocessor Option is enabled (prerequisite)
+      - The optimization level is greater than 1
+      - Optimizing for speed or the Code Density Option is not enabled  */
+  if (! (TARGET_HARD_FLOAT
+	 && optimize > 1
+	 && (!optimize_size || !TARGET_DENSITY)))
+    return NO_REGS;
+
+  /* Allow integer registers to be spilled into FP_REGS rclass (to which
+     floating-point registers belong) only if the function currently being
+     compiled does not contain any floating-point coprocessor instructions.  */
+retry:
+  switch (cfun->machine->hard_float_insn_usage)
+    {
+    case 0:	/* Not yet investigated (the initial state).  */
+      /* Scan the insns in the function for floating-point coprocessor
+	 instructions.  */
+      for (insn = get_insns ();
+	   (insn = next_nonnote_nondebug_insn (insn)); )
+	if (recog_memoized (insn) >= 0)
+	  switch (get_attr_type (insn))
+	    {
+	    /* An insn that is a floating-point coprocessor instruction is
+	       found, so record this.  */
+	    case TYPE_FARITH:
+	    case TYPE_FMADD:
+	    case TYPE_FCONV:
+	    case TYPE_FLOAD:
+	    case TYPE_FSTORE:
+	      cfun->machine->hard_float_insn_usage = 1;
+	      goto retry;
+	    default:
+	      break;
+	    }
+      /* No insn that is a floating-point coprocessor instruction was found,
+	 so record this.  */
+      cfun->machine->hard_float_insn_usage = 2;
+      goto retry;
+    case 1:	/* Contains floating-point coprocessor instructions.  */
+      /* Deny spilling to any rclass.  */
+      return NO_REGS;
+    default:	/* Does not contain floating-point coprocessor
+		   instructions.  */
+      break;
+    }
+
+  /* If rclass belongs to GENERAL_REGS and SImode is specified, spilling
+     to FP_REGS is allowed.  */
+  if (reg_class_subset_p (rclass, GENERAL_REGS)
+      && mode == SImode)
+    return FP_REGS;
+
+  /* Deny spilling to any rclass.  */
+  return NO_REGS;
+}
+
  #include "gt-xtensa.h"
diff --git a/gcc/config/xtensa/xtensa.md b/gcc/config/xtensa/xtensa.md
index 52ffb161c0f..6371e3976f1 100644
--- a/gcc/config/xtensa/xtensa.md
+++ b/gcc/config/xtensa/xtensa.md
@@ -1293,22 +1293,24 @@
  	(match_operand:SI 1 "move_operand"))]
    "xtensa_valid_move (SImode, operands)"
    {@ [cons: =0, 1; attrs: type, length]
-     [ D,  M; move , 2] movi.n\t%0, %x1
-     [ D,  D; move , 2] mov.n\t%0, %1
-     [ D,  d; move , 2] ^
-     [ D,  R; load , 2] %v1l32i.n\t%0, %1
-     [ R,  D; store, 2] %v0s32i.n\t%1, %0
-     [ R,  d; store, 2] ^
-     [ a,  r; move , 3] mov\t%0, %1
-     [ q,  r; move , 3] movsp\t%0, %1
-     [ a,  I; move , 3] movi\t%0, %x1
-     [ a,  Y; load , 3] movi\t%0, %1
-     [ W,  i; move , 6] const16\t%0, %t1\;const16\t%0, %b1
-     [ a,  T; load , 3] %v1l32r\t%0, %1
-     [ a,  U; load , 3] %v1l32i\t%0, %1
-     [ U,  r; store, 3] %v0s32i\t%1, %0
-     [*a, *A; rsr  , 3] rsr\t%0, ACCLO
-     [*A, *r; wsr  , 3] wsr\t%1, ACCLO
+     [ D,  M; move  , 2] movi.n\t%0, %x1
+     [ D,  D; move  , 2] mov.n\t%0, %1
+     [ D,  d; move  , 2] ^
+     [ D,  R; load  , 2] %v1l32i.n\t%0, %1
+     [ R,  D; store , 2] %v0s32i.n\t%1, %0
+     [ R,  d; store , 2] ^
+     [ a,  r; move  , 3] mov\t%0, %1
+     [ q,  r; move  , 3] movsp\t%0, %1
+     [ a,  I; move  , 3] movi\t%0, %x1
+     [ a,  Y; load  , 3] movi\t%0, %1
+     [ W,  i; move  , 6] const16\t%0, %t1\;const16\t%0, %b1
+     [ a,  T; load  , 3] %v1l32r\t%0, %1
+     [ a,  U; load  , 3] %v1l32i\t%0, %1
+     [ U,  r; store , 3] %v0s32i\t%1, %0
+     [*a, *f; farith, 3] rfr\t%0, %1
+     [*f, *r; farith, 3] wfr\t%0, %1
+     [*a, *A; rsr   , 3] rsr\t%0, ACCLO
+     [*A, *r; wsr   , 3] wsr\t%1, ACCLO
    }
    [(set_attr "mode" "SI")])
  
