Index: gcc/optabs.c
===================================================================
--- gcc/optabs.c	2013-01-31 09:17:21.551473246 +0000
+++ gcc/optabs.c	2013-01-31 09:27:35.535226561 +0000
@@ -8261,23 +8261,35 @@ get_traditional_extraction_insn (extract
 {
   const struct insn_data_d *data = &insn_data[icode];
 
-  enum machine_mode struct_mode = data->operand[struct_op].mode;
-  if (struct_mode == VOIDmode)
-    struct_mode = word_mode;
-  if (mode != struct_mode)
-    return false;
-
   enum machine_mode field_mode = data->operand[field_op].mode;
   if (field_mode == VOIDmode)
     field_mode = word_mode;
 
+  enum machine_mode struct_mode;
+  if (type == ET_unaligned_mem)
+    {
+      /* Memory structure operands refer to the first byte of the
+	 bitfield and the true mode is taken from the field operand.  */
+      struct_mode = byte_mode;
+      if (mode != field_mode)
+	return false;
+    }
+  else
+    {
+      struct_mode = data->operand[struct_op].mode;
+      if (struct_mode == VOIDmode)
+	struct_mode = word_mode;
+      if (mode != struct_mode)
+	return false;
+    }
+
   enum machine_mode pos_mode = data->operand[struct_op + 2].mode;
   if (pos_mode == VOIDmode)
     pos_mode = word_mode;
 
   insn->icode = icode;
   insn->field_mode = field_mode;
-  insn->struct_mode = (type == ET_unaligned_mem ? byte_mode : struct_mode);
+  insn->struct_mode = struct_mode;
   insn->pos_mode = pos_mode;
   return true;
 }
