diff --git gcc/config/cris/cris.c gcc/config/cris/cris.c
index 110e985..159b31b 100644
--- gcc/config/cris/cris.c
+++ gcc/config/cris/cris.c
@@ -1360,24 +1360,11 @@ static int
 cris_register_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
 			 reg_class_t from, reg_class_t to)
 {
-  if (!TARGET_V32)
-    {
-      /* Pretend that classes that we don't support are ALL_REGS, so
-	 we give them the highest cost.  */
-      if (from != SPECIAL_REGS && from != MOF_REGS
-	  && from != GENERAL_REGS && from != GENNONACR_REGS)
-	from = ALL_REGS;
-
-      if (to != SPECIAL_REGS && to != MOF_REGS
-	  && to != GENERAL_REGS && to != GENNONACR_REGS)
-	to = ALL_REGS;
-    }
-
   /* Can't move to and from a SPECIAL_REGS register, so we have to say
      their move cost within that class is higher.  How about 7?  That's 3
      for a move to a GENERAL_REGS register, 3 for the move from the
      GENERAL_REGS register, and 1 for the increased register pressure.
-     Also, it's higher than the memory move cost, which is in order.  
+     Also, it's higher than the memory move cost, as it should.
      We also do this for ALL_REGS, since we don't want that class to be
      preferred (even to memory) at all where GENERAL_REGS doesn't fit.
      Whenever it's about to be used, it's for SPECIAL_REGS.  If we don't
@@ -1386,13 +1373,15 @@ cris_register_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
      GENERAL_REGS left to allocate.  This is because the fall-back when
      the most preferred register class isn't available, isn't the next
      (or next good) wider register class, but the *most widest* register
-     class.  */
+     class.  FIXME: pre-IRA comment, perhaps obsolete now.  */
 
   if ((reg_classes_intersect_p (from, SPECIAL_REGS)
        && reg_classes_intersect_p (to, SPECIAL_REGS))
       || from == ALL_REGS || to == ALL_REGS)
     return 7;
 
+  /* Make moves to/from SPECIAL_REGS slightly more expensive, as we
+     generally prefer GENERAL_REGS.  */
   if (reg_classes_intersect_p (from, SPECIAL_REGS)
       || reg_classes_intersect_p (to, SPECIAL_REGS))
     return 3;
diff --git gcc/config/cris/cris.h gcc/config/cris/cris.h
index 57bdd46..872165e 100644
--- gcc/config/cris/cris.h
+++ gcc/config/cris/cris.h
@@ -418,7 +418,7 @@ extern int cris_cpu_version;
    registers are fixed at the moment.  The faked argument pointer register
    is fixed too.  */
 #define FIXED_REGISTERS \
- {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0}
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1}
 
 /* Register r9 is used for structure-address, r10-r13 for parameters,
    r10- for return values.  */
@@ -488,17 +488,17 @@ extern int cris_cpu_version;
 
 /* Node: Register Classes */
 
-/* FIXME: A separate class for the return register would make sense.
-
-   We need a separate register class to handle register allocation for
+/* We need a separate register class to handle register allocation for
    ACR, since it can't be used for post-increment.
 
    It's not obvious, but having subunions of all movable-between
-   register classes does really help register allocation.  */
+   register classes does really help register allocation (pre-IRA
+   comment).  */
 enum reg_class
   {
     NO_REGS,
-    ACR_REGS, MOF_REGS, CC0_REGS, SPECIAL_REGS,
+    ACR_REGS, MOF_REGS, SRP_REGS, CC0_REGS,
+    MOF_SRP_REGS, SPECIAL_REGS,
     SPEC_ACR_REGS, GENNONACR_REGS,
     SPEC_GENNONACR_REGS, GENERAL_REGS,
     ALL_REGS,
@@ -509,7 +509,8 @@ enum reg_class
 
 #define REG_CLASS_NAMES						\
   {"NO_REGS",							\
-   "ACR_REGS", "MOF_REGS", "CC0_REGS", "SPECIAL_REGS",		\
+   "ACR_REGS", "MOF_REGS", "SRP_REGS", "CC0_REGS",		\
+   "MOF_SRP_REGS", "SPECIAL_REGS",				\
    "SPEC_ACR_REGS", "GENNONACR_REGS", "SPEC_GENNONACR_REGS",	\
    "GENERAL_REGS", "ALL_REGS"}
 
@@ -522,7 +523,10 @@ enum reg_class
    {0},						\
    {1 << CRIS_ACR_REGNUM},			\
    {1 << CRIS_MOF_REGNUM},			\
+   {1 << CRIS_SRP_REGNUM},			\
    {1 << CRIS_CC0_REGNUM},			\
+   {(1 << CRIS_MOF_REGNUM)			\
+    | (1 << CRIS_SRP_REGNUM)},			\
    {CRIS_SPECIAL_REGS_CONTENTS},		\
    {CRIS_SPECIAL_REGS_CONTENTS			\
     | (1 << CRIS_ACR_REGNUM)},			\
@@ -539,8 +543,8 @@ enum reg_class
 #define REGNO_REG_CLASS(REGNO)			\
   ((REGNO) == CRIS_ACR_REGNUM ? ACR_REGS :	\
    (REGNO) == CRIS_MOF_REGNUM ? MOF_REGS :	\
+   (REGNO) == CRIS_SRP_REGNUM ? SRP_REGS :	\
    (REGNO) == CRIS_CC0_REGNUM ? CC0_REGS :	\
-   (REGNO) == CRIS_SRP_REGNUM ? SPECIAL_REGS :	\
    GENERAL_REGS)
 
 #define BASE_REG_CLASS GENERAL_REGS
@@ -590,6 +594,7 @@ enum reg_class
 #define PREFERRED_RELOAD_CLASS(X, CLASS)	\
  ((CLASS) != ACR_REGS				\
   && (CLASS) != MOF_REGS			\
+  && (CLASS) != SRP_REGS			\
   && (CLASS) != CC0_REGS			\
   && (CLASS) != SPECIAL_REGS			\
   ? GENERAL_REGS : (CLASS))
@@ -601,7 +606,7 @@ enum reg_class
    the effect that any X that isn't a special-register is treated as
    a non-empty intersection with GENERAL_REGS.  */
 #define SECONDARY_RELOAD_CLASS(CLASS, MODE, X)				\
- ((((CLASS) == SPECIAL_REGS || (CLASS) == MOF_REGS)			\
+ ((reg_class_subset_p (CLASS, SPECIAL_REGS)				\
    && ((GET_MODE_SIZE (MODE) < 4 && MEM_P (X))				\
        || !reg_classes_intersect_p (REGNO_REG_CLASS (true_regnum (X)),	\
 				    GENERAL_REGS)))			\
