Index: config/arm/arm.md
===================================================================
--- config/arm/arm.md.orig
+++ config/arm/arm.md
@@ -393,6 +393,9 @@
 ;; The integer modes up to word size
 (define_mode_iterator QHSI [QI HI SI])
 
+;; The integer modes below word size
+(define_mode_iterator QHI [QI HI])
+
 ;;---------------------------------------------------------------------------
 ;; Predicates
 
@@ -6686,6 +6689,63 @@
 		(const_int 8))))]
 )
 
+(define_mode_attr mode_lshift [(QI "24") (HI "16")])
+
+(define_insn "cbranch<mode>4_insn"
+  [(set (pc) (if_then_else
+	      (match_operator 0 "arm_comparison_operator"
+	       [(match_operand:QHI 1 "s_register_operand" "l")
+	        (const_int 0)])
+	      (label_ref (match_operand 2 "" ""))
+	      (pc)))
+   (clobber (match_scratch:QHI 3 "=l"))]
+  "TARGET_THUMB1"
+{
+  int len = get_attr_length (insn);
+  output_asm_insn ("lsl\t%3, %1, #<mode_lshift>", operands);
+
+  if (!noov_comparison_operator (operands[0], VOIDmode))
+    {
+      output_asm_insn ("cmp\t%3, #0", operands);
+      len -= 2;
+    }
+
+  switch (len)
+    {
+    case 4:  return "b%d0\t%l2";
+    case 6:  return "b%D0\t.LCB%=\;b\t%l2\t%@long jump\n.LCB%=:";
+    default: return "b%D0\t.LCB%=\;bl\t%l2\t%@far jump\n.LCB%=:";
+    }
+}
+  [(set (attr "far_jump")
+        (if_then_else
+	    (ior (and (match_operand 0 "noov_comparison_operator")
+		      (eq_attr "length" "8"))
+		 (eq_attr "length" "10"))
+	    (const_string "yes")
+            (const_string "no")))
+   (set (attr "length")
+     (if_then_else
+       (match_operand 0 "noov_comparison_operator")
+       (if_then_else
+	 (and (ge (minus (match_dup 2) (pc)) (const_int -250))
+	      (le (minus (match_dup 2) (pc)) (const_int 256)))
+	 (const_int 4)
+	 (if_then_else
+	   (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
+		(le (minus (match_dup 2) (pc)) (const_int 2048)))
+	   (const_int 6)
+	   (const_int 8)))
+       (if_then_else
+	 (and (ge (minus (match_dup 2) (pc)) (const_int -248))
+	      (le (minus (match_dup 2) (pc)) (const_int 256)))
+	 (const_int 6)
+	 (if_then_else
+	   (and (ge (minus (match_dup 2) (pc)) (const_int -2038))
+		(le (minus (match_dup 2) (pc)) (const_int 2048)))
+	   (const_int 8)
+	   (const_int 10)))))])
+
 (define_insn "cbranchsi4_scratch"
   [(set (pc) (if_then_else
 	      (match_operator 4 "arm_comparison_operator"
Index: config/arm/predicates.md
===================================================================
--- config/arm/predicates.md.orig
+++ config/arm/predicates.md
@@ -235,6 +235,9 @@
 (define_special_predicate "lt_ge_comparison_operator"
   (match_code "lt,ge"))
 
+(define_special_predicate "noov_comparison_operator"
+  (match_code "lt,ge,eq,ne"))
+
 (define_special_predicate "minmax_operator"
   (and (match_code "smin,smax,umin,umax")
        (match_test "mode == GET_MODE (op)")))
