diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index c83587caac18bcc8768989320e53a4cd59a952d1..1dbc7e87ac245a8341dc67b3c44bbaeb9bc1b511 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,7 @@
+2006-01-26  Adam Nemet  <anemet@caviumnetworks.com>
+
+	* config/mips/mips.md (*clear_upper32): New combiner pattern.
+
 2006-01-26  Richard Earnshaw  <richard.earnshaw@arm.com>
 
 	* arm.md (smaxsi3, sminsi3): Convert to define_expand.
diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md
index b0ceff8dbe319b8a0fe5488b11e543d0078196f4..af8f709b53f3caada7010db0b79c2c735d3791d1 100644
--- a/gcc/config/mips/mips.md
+++ b/gcc/config/mips/mips.md
@@ -2332,6 +2332,31 @@
    (set_attr "mode" "DI")
    (set_attr "length" "8,*")])
 
+;; Combine is not allowed to convert this insn into a zero_extendsidi2
+;; because of TRULY_NOOP_TRUNCATION.
+
+(define_insn_and_split "*clear_upper32"
+  [(set (match_operand:DI 0 "register_operand" "=d,d")
+        (and:DI (match_operand:DI 1 "nonimmediate_operand" "d,o")
+		(const_int 4294967295)))]
+  "TARGET_64BIT"
+{
+  if (which_alternative == 0)
+    return "#";
+
+  operands[1] = gen_lowpart (SImode, operands[1]);
+  return "lwu\t%0,%1";
+}
+  "&& reload_completed && REG_P (operands[1])"
+  [(set (match_dup 0)
+        (ashift:DI (match_dup 1) (const_int 32)))
+   (set (match_dup 0)
+        (lshiftrt:DI (match_dup 0) (const_int 32)))]
+  ""
+  [(set_attr "type" "multi,load")
+   (set_attr "mode" "DI")
+   (set_attr "length" "8,*")])
+
 (define_expand "zero_extend<SHORT:mode><GPR:mode>2"
   [(set (match_operand:GPR 0 "register_operand")
         (zero_extend:GPR (match_operand:SHORT 1 "nonimmediate_operand")))]