diff -urp gcc/config/spu.orig/spu.c gcc/config/spu/spu.c
--- gcc/config/spu.orig/spu.c	2010-12-10 16:51:16.000000000 +0100
+++ gcc/config/spu/spu.c	2010-12-21 16:49:02.000000000 +0100
@@ -4572,7 +4572,13 @@ int
 spu_expand_mov (rtx * ops, enum machine_mode mode)
 {
   if (GET_CODE (ops[0]) == SUBREG && !valid_subreg (ops[0]))
-    abort ();
+    {
+      /* Perform the move in the destination SUBREG's inner mode.  */
+      ops[0] = SUBREG_REG (ops[0]);
+      mode = GET_MODE (ops[0]);
+      ops[1] = gen_lowpart_common (mode, ops[1]);
+      gcc_assert (ops[1]);
+    }
 
   if (GET_CODE (ops[1]) == SUBREG && !valid_subreg (ops[1]))
     {
diff -urp gcc/config/spu.orig/spu.md gcc/config/spu/spu.md
--- gcc/config/spu.orig/spu.md	2010-12-10 16:51:16.000000000 +0100
+++ gcc/config/spu/spu.md	2010-12-21 16:57:27.000000000 +0100
@@ -269,8 +269,8 @@
 ;; mov
 
 (define_expand "mov<mode>"
-  [(set (match_operand:ALL 0 "spu_nonimm_operand" "=r,r,r,m")
-	(match_operand:ALL 1 "general_operand" "r,i,m,r"))]
+  [(set (match_operand:ALL 0 "nonimmediate_operand" "")
+	(match_operand:ALL 1 "general_operand" ""))]
   ""
   {
     if (spu_expand_mov(operands, <MODE>mode))
