OSDN Git Service

* pa.md (addvdi3, addvsi3, subvdi3, subvsi3, negvdi2, negvsi2): New
[pf3gnuchains/gcc-fork.git] / gcc / config / pa / pa.md
index e8acd9a..0adfe3f 100644 (file)
@@ -1,6 +1,6 @@
 ;;- Machine description for HP PA-RISC architecture for GCC compiler
 ;;   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
-;;   2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+;;   2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
 ;;   Contributed by the Center for Software Science at the University
 ;;   of Utah.
 
    (UNSPECV_LONGJMP    5)      ; builtin_longjmp
   ])
 
+;; Maximum pc-relative branch offsets.
+
+;; These numbers are a bit smaller than the maximum allowable offsets
+;; so that a few instructions may be inserted before the actual branch.
+
+(define_constants
+  [(MAX_12BIT_OFFSET     8184) ; 12-bit branch
+   (MAX_17BIT_OFFSET   262100) ; 17-bit branch
+  ])
+
 ;; Insn type.  Used to default other attribute values.
 
 ;; type "unary" insns have one input operand (1) and one output operand (0)
 [(set_attr "type" "cbranch")
  (set (attr "length")
     (cond [(lt (abs (minus (match_dup 0) (plus (pc) (const_int 8))))
-              (const_int 8184))
+              (const_int MAX_12BIT_OFFSET))
           (const_int 4)
           (lt (abs (minus (match_dup 0) (plus (pc) (const_int 8))))
-              (const_int 262100))
+              (const_int MAX_17BIT_OFFSET))
           (const_int 8)
           (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
           (const_int 24)
 [(set_attr "type" "cbranch")
  (set (attr "length")
     (cond [(lt (abs (minus (match_dup 0) (plus (pc) (const_int 8))))
-              (const_int 8184))
+              (const_int MAX_12BIT_OFFSET))
           (const_int 4)
           (lt (abs (minus (match_dup 0) (plus (pc) (const_int 8))))
-              (const_int 262100))
+              (const_int MAX_17BIT_OFFSET))
           (const_int 8)
           (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
           (const_int 24)
 [(set_attr "type" "cbranch")
  (set (attr "length")
     (cond [(lt (abs (minus (match_dup 0) (plus (pc) (const_int 8))))
-              (const_int 8184))
+              (const_int MAX_12BIT_OFFSET))
           (const_int 4)
           (lt (abs (minus (match_dup 0) (plus (pc) (const_int 8))))
-              (const_int 262100))
+              (const_int MAX_17BIT_OFFSET))
           (const_int 8)
           (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
           (const_int 24)
 [(set_attr "type" "cbranch")
  (set (attr "length")
     (cond [(lt (abs (minus (match_dup 0) (plus (pc) (const_int 8))))
-              (const_int 8184))
+              (const_int MAX_12BIT_OFFSET))
           (const_int 4)
           (lt (abs (minus (match_dup 0) (plus (pc) (const_int 8))))
-              (const_int 262100))
+              (const_int MAX_17BIT_OFFSET))
           (const_int 8)
           (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
           (const_int 24)
 [(set_attr "type" "cbranch")
  (set (attr "length")
     (cond [(lt (abs (minus (match_dup 0) (plus (pc) (const_int 8))))
-              (const_int 8184))
+              (const_int MAX_12BIT_OFFSET))
           (const_int 4)
           (lt (abs (minus (match_dup 0) (plus (pc) (const_int 8))))
-              (const_int 262100))
+              (const_int MAX_17BIT_OFFSET))
           (const_int 8)
           (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
           (const_int 24)
 [(set_attr "type" "cbranch")
  (set (attr "length")
     (cond [(lt (abs (minus (match_dup 0) (plus (pc) (const_int 8))))
-              (const_int 8184))
+              (const_int MAX_12BIT_OFFSET))
           (const_int 4)
           (lt (abs (minus (match_dup 0) (plus (pc) (const_int 8))))
-              (const_int 262100))
+              (const_int MAX_17BIT_OFFSET))
           (const_int 8)
           (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
           (const_int 24)
 [(set_attr "type" "cbranch")
  (set (attr "length")
     (cond [(lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
-              (const_int 8184))
+              (const_int MAX_12BIT_OFFSET))
           (const_int 4)
           (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
-              (const_int 262100))
+              (const_int MAX_17BIT_OFFSET))
           (const_int 8)
           (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
-          (const_int 28)
+          (const_int 24)
           (eq (symbol_ref "flag_pic") (const_int 0))
-          (const_int 24)]
-         (const_int 32)))])
+          (const_int 20)]
+         (const_int 28)))])
 
 (define_insn ""
   [(set (pc)
 [(set_attr "type" "cbranch")
  (set (attr "length")
     (cond [(lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
-              (const_int 8184))
+              (const_int MAX_12BIT_OFFSET))
           (const_int 4)
           (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
-              (const_int 262100))
+              (const_int MAX_17BIT_OFFSET))
           (const_int 8)
           (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
-          (const_int 28)
+          (const_int 24)
           (eq (symbol_ref "flag_pic") (const_int 0))
-          (const_int 24)]
-         (const_int 32)))])
+          (const_int 20)]
+         (const_int 28)))])
 
 (define_insn ""
   [(set (pc)
 [(set_attr "type" "cbranch")
  (set (attr "length")
     (cond [(lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
-              (const_int 8184))
+              (const_int MAX_12BIT_OFFSET))
           (const_int 4)
           (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
-              (const_int 262100))
+              (const_int MAX_17BIT_OFFSET))
           (const_int 8)
           (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
-          (const_int 28)
+          (const_int 24)
           (eq (symbol_ref "flag_pic") (const_int 0))
-          (const_int 24)]
-         (const_int 32)))])
+          (const_int 20)]
+         (const_int 28)))])
 
 (define_insn ""
   [(set (pc)
 [(set_attr "type" "cbranch")
  (set (attr "length")
     (cond [(lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
-              (const_int 8184))
+              (const_int MAX_12BIT_OFFSET))
           (const_int 4)
           (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
-              (const_int 262100))
+              (const_int MAX_17BIT_OFFSET))
           (const_int 8)
           (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
-          (const_int 28)
+          (const_int 24)
           (eq (symbol_ref "flag_pic") (const_int 0))
-          (const_int 24)]
-         (const_int 32)))])
+          (const_int 20)]
+         (const_int 28)))])
 
 (define_insn ""
   [(set (pc)
 [(set_attr "type" "cbranch")
  (set (attr "length")
     (cond [(lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
-              (const_int 8184))
+              (const_int MAX_12BIT_OFFSET))
           (const_int 4)
           (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
-              (const_int 262100))
+              (const_int MAX_17BIT_OFFSET))
           (const_int 8)
           (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
-          (const_int 28)
+          (const_int 24)
           (eq (symbol_ref "flag_pic") (const_int 0))
-          (const_int 24)]
-         (const_int 32)))])
+          (const_int 20)]
+         (const_int 28)))])
 
 (define_insn ""
   [(set (pc)
 [(set_attr "type" "cbranch")
  (set (attr "length")
     (cond [(lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
-              (const_int 8184))
+              (const_int MAX_12BIT_OFFSET))
           (const_int 4)
           (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
-              (const_int 262100))
+              (const_int MAX_17BIT_OFFSET))
           (const_int 8)
           (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
-          (const_int 28)
+          (const_int 24)
           (eq (symbol_ref "flag_pic") (const_int 0))
-          (const_int 24)]
-         (const_int 32)))])
+          (const_int 20)]
+         (const_int 28)))])
 
 (define_insn ""
   [(set (pc)
 [(set_attr "type" "cbranch")
  (set (attr "length")
     (cond [(lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
-              (const_int 8184))
+              (const_int MAX_12BIT_OFFSET))
           (const_int 4)
           (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
-              (const_int 262100))
+              (const_int MAX_17BIT_OFFSET))
           (const_int 8)
           (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
-          (const_int 28)
+          (const_int 24)
           (eq (symbol_ref "flag_pic") (const_int 0))
-          (const_int 24)]
-         (const_int 32)))])
+          (const_int 20)]
+         (const_int 28)))])
 
 (define_insn ""
   [(set (pc)
 [(set_attr "type" "cbranch")
  (set (attr "length")
     (cond [(lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
-              (const_int 8184))
+              (const_int MAX_12BIT_OFFSET))
           (const_int 4)
           (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
-              (const_int 262100))
+              (const_int MAX_17BIT_OFFSET))
           (const_int 8)
           (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
-          (const_int 28)
+          (const_int 24)
           (eq (symbol_ref "flag_pic") (const_int 0))
-          (const_int 24)]
-         (const_int 32)))])
+          (const_int 20)]
+         (const_int 28)))])
 
 ;; Branch on Variable Bit patterns.
 (define_insn ""
 [(set_attr "type" "cbranch")
  (set (attr "length")
     (cond [(lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
-              (const_int 8184))
+              (const_int MAX_12BIT_OFFSET))
           (const_int 4)
           (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
-              (const_int 262100))
+              (const_int MAX_17BIT_OFFSET))
           (const_int 8)
           (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
-          (const_int 28)
+          (const_int 24)
           (eq (symbol_ref "flag_pic") (const_int 0))
-          (const_int 24)]
-         (const_int 32)))])
+          (const_int 20)]
+         (const_int 28)))])
 
 (define_insn ""
   [(set (pc)
 [(set_attr "type" "cbranch")
  (set (attr "length")
     (cond [(lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
-              (const_int 8184))
+              (const_int MAX_12BIT_OFFSET))
           (const_int 4)
           (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
-              (const_int 262100))
+              (const_int MAX_17BIT_OFFSET))
           (const_int 8)
           (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
-          (const_int 28)
+          (const_int 24)
           (eq (symbol_ref "flag_pic") (const_int 0))
-          (const_int 24)]
-         (const_int 32)))])
+          (const_int 20)]
+         (const_int 28)))])
 
 (define_insn ""
   [(set (pc)
 [(set_attr "type" "cbranch")
  (set (attr "length")
     (cond [(lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
-              (const_int 8184))
+              (const_int MAX_12BIT_OFFSET))
           (const_int 4)
           (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
-              (const_int 262100))
+              (const_int MAX_17BIT_OFFSET))
           (const_int 8)
           (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
-          (const_int 28)
+          (const_int 24)
           (eq (symbol_ref "flag_pic") (const_int 0))
-          (const_int 24)]
-         (const_int 32)))])
+          (const_int 20)]
+         (const_int 28)))])
 
 (define_insn ""
   [(set (pc)
 [(set_attr "type" "cbranch")
  (set (attr "length")
     (cond [(lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
-              (const_int 8184))
+              (const_int MAX_12BIT_OFFSET))
           (const_int 4)
           (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
-              (const_int 262100))
+              (const_int MAX_17BIT_OFFSET))
           (const_int 8)
           (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
-          (const_int 28)
+          (const_int 24)
           (eq (symbol_ref "flag_pic") (const_int 0))
-          (const_int 24)]
-         (const_int 32)))])
+          (const_int 20)]
+         (const_int 28)))])
 
 (define_insn ""
   [(set (pc)
 [(set_attr "type" "cbranch")
  (set (attr "length")
     (cond [(lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
-              (const_int 8184))
+              (const_int MAX_12BIT_OFFSET))
           (const_int 4)
           (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
-              (const_int 262100))
+              (const_int MAX_17BIT_OFFSET))
           (const_int 8)
           (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
-          (const_int 28)
+          (const_int 24)
           (eq (symbol_ref "flag_pic") (const_int 0))
-          (const_int 24)]
-         (const_int 32)))])
+          (const_int 20)]
+         (const_int 28)))])
 
 (define_insn ""
   [(set (pc)
 [(set_attr "type" "cbranch")
  (set (attr "length")
     (cond [(lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
-              (const_int 8184))
+              (const_int MAX_12BIT_OFFSET))
           (const_int 4)
           (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
-              (const_int 262100))
+              (const_int MAX_17BIT_OFFSET))
           (const_int 8)
           (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
-          (const_int 28)
+          (const_int 24)
           (eq (symbol_ref "flag_pic") (const_int 0))
-          (const_int 24)]
-         (const_int 32)))])
+          (const_int 20)]
+         (const_int 28)))])
 
 (define_insn ""
   [(set (pc)
 [(set_attr "type" "cbranch")
  (set (attr "length")
     (cond [(lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
-              (const_int 8184))
+              (const_int MAX_12BIT_OFFSET))
           (const_int 4)
           (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
-              (const_int 262100))
+              (const_int MAX_17BIT_OFFSET))
           (const_int 8)
           (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
-          (const_int 28)
+          (const_int 24)
           (eq (symbol_ref "flag_pic") (const_int 0))
-          (const_int 24)]
-         (const_int 32)))])
+          (const_int 20)]
+         (const_int 28)))])
 
 (define_insn ""
   [(set (pc)
 [(set_attr "type" "cbranch")
  (set (attr "length")
     (cond [(lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
-              (const_int 8184))
+              (const_int MAX_12BIT_OFFSET))
           (const_int 4)
           (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
-              (const_int 262100))
+              (const_int MAX_17BIT_OFFSET))
           (const_int 8)
           (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
-          (const_int 28)
+          (const_int 24)
           (eq (symbol_ref "flag_pic") (const_int 0))
-          (const_int 24)]
-         (const_int 32)))])
+          (const_int 20)]
+         (const_int 28)))])
 
 ;; Floating point branches
 
 [(set_attr "type" "fbranch")
  (set (attr "length")
     (cond [(lt (abs (minus (match_dup 0) (plus (pc) (const_int 8))))
-              (const_int 262100))
+              (const_int MAX_17BIT_OFFSET))
           (const_int 8)
           (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
           (const_int 32)
 [(set_attr "type" "fbranch")
  (set (attr "length")
     (cond [(lt (abs (minus (match_dup 0) (plus (pc) (const_int 8))))
-              (const_int 262100))
+              (const_int MAX_17BIT_OFFSET))
           (const_int 12)
           (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
           (const_int 28)
   switch (GET_CODE (op1))
     {
     case CONST_INT:
+#if HOST_BITS_PER_WIDE_INT <= 32
       operands[0] = operand_subword (op0, 1, 0, DImode);
       output_asm_insn (\"ldil L'%1,%0\", operands);
 
        output_asm_insn (\"ldi -1,%0\", operands);
       else
        output_asm_insn (\"ldi 0,%0\", operands);
+#else
+      operands[0] = operand_subword (op0, 1, 0, DImode);
+      operands[1] = GEN_INT (INTVAL (op1) & 0xffffffff);
+      output_asm_insn (\"ldil L'%1,%0\", operands);
+
+      operands[0] = operand_subword (op0, 0, 0, DImode);
+      operands[1] = GEN_INT (INTVAL (op1) >> 32);
+      output_asm_insn (singlemove_string (operands), operands);
+#endif
       break;
 
     case CONST_DOUBLE:
   return \"\";
 }"
   [(set_attr "type" "move")
-   (set_attr "length" "8")])
+   (set_attr "length" "12")])
 
 (define_insn ""
   [(set (match_operand:DI 0 "move_dest_operand"
      handle it correctly.  */
   if (GET_CODE (operands[2]) == CONST_DOUBLE)
     operands[2] = GEN_INT (CONST_DOUBLE_LOW (operands[2]));
+  else if (HOST_BITS_PER_WIDE_INT > 32
+          && GET_CODE (operands[2]) == CONST_INT)
+    operands[2] = GEN_INT (INTVAL (operands[2]) & 0xffffffff);
   if (which_alternative == 1)
     output_asm_insn (\"copy %1,%0\", operands);
   return \"ldo R'%G2(%R1),%R0\";
   [(set_attr "type" "binary")
    (set_attr "length" "4")])
 
+(define_expand "addvdi3"
+  [(parallel [(set (match_operand:DI 0 "register_operand" "")
+                  (plus:DI (match_operand:DI 1 "reg_or_0_operand" "")
+                           (match_operand:DI 2 "arith11_operand" "")))
+             (trap_if (ne (plus:TI (sign_extend:TI (match_dup 1))
+                                   (sign_extend:TI (match_dup 2)))
+                          (sign_extend:TI (plus:DI (match_dup 1)
+                                                   (match_dup 2))))
+                      (const_int 0))])]
+  ""
+  "")
+
+(define_insn ""
+  [(set (match_operand:DI 0 "register_operand" "=r,r")
+       (plus:DI (match_operand:DI 1 "reg_or_0_operand" "%rM,rM")
+                (match_operand:DI 2 "arith11_operand" "r,I")))
+   (trap_if (ne (plus:TI (sign_extend:TI (match_dup 1))
+                        (sign_extend:TI (match_dup 2)))
+               (sign_extend:TI (plus:DI (match_dup 1)
+                                        (match_dup 2))))
+           (const_int 0))]
+  "TARGET_64BIT"
+  "@
+  add,tsv,* %2,%1,%0
+  addi,tsv,* %2,%1,%0"
+  [(set_attr "type" "binary,binary")
+   (set_attr "length" "4,4")])
+
+(define_insn ""
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (plus:DI (match_operand:DI 1 "reg_or_0_operand" "%rM")
+                (match_operand:DI 2 "arith11_operand" "rI")))
+   (trap_if (ne (plus:TI (sign_extend:TI (match_dup 1))
+                        (sign_extend:TI (match_dup 2)))
+               (sign_extend:TI (plus:DI (match_dup 1)
+                                        (match_dup 2))))
+           (const_int 0))]
+  "!TARGET_64BIT"
+  "*
+{
+  if (GET_CODE (operands[2]) == CONST_INT)
+    {
+      if (INTVAL (operands[2]) >= 0)
+       return \"addi %2,%R1,%R0\;{addco|add,c,tsv} %1,%%r0,%0\";
+      else
+       return \"addi %2,%R1,%R0\;{subbo|sub,b,tsv} %1,%%r0,%0\";
+    }
+  else
+    return \"add %R2,%R1,%R0\;{addco|add,c,tsv} %2,%1,%0\";
+}"
+  [(set_attr "type" "binary")
+   (set_attr "length" "8")])
+
 ;; define_splits to optimize cases of adding a constant integer
 ;; to a register when the constant does not fit in 14 bits.  */
 (define_split
    (set_attr "pa_combine_type" "addmove")
    (set_attr "length" "4,4")])
 
+(define_insn "addvsi3"
+  [(set (match_operand:SI 0 "register_operand" "=r,r")
+       (plus:SI (match_operand:SI 1 "reg_or_0_operand" "%rM,rM")
+                (match_operand:SI 2 "arith11_operand" "r,I")))
+   (trap_if (ne (plus:DI (sign_extend:DI (match_dup 1))
+                        (sign_extend:DI (match_dup 2)))
+               (sign_extend:DI (plus:SI (match_dup 1)
+                                        (match_dup 2))))
+           (const_int 0))]
+  ""
+  "@
+  {addo|add,tsv} %2,%1,%0
+  {addio|addi,tsv} %2,%1,%0"
+  [(set_attr "type" "binary,binary")
+   (set_attr "length" "4,4")])
+
 (define_expand "subdi3"
   [(set (match_operand:DI 0 "register_operand" "")
-       (minus:DI (match_operand:DI 1 "register_operand" "")
-                 (match_operand:DI 2 "register_operand" "")))]
+       (minus:DI (match_operand:DI 1 "arith11_operand" "")
+                 (match_operand:DI 2 "reg_or_0_operand" "")))]
   ""
   "")
 
 (define_insn ""
-  [(set (match_operand:DI 0 "register_operand" "=r")
-       (minus:DI (match_operand:DI 1 "register_operand" "r")
-                 (match_operand:DI 2 "register_operand" "r")))]
-  "!TARGET_64BIT"
-  "sub %R1,%R2,%R0\;{subb|sub,b} %1,%2,%0"
-  [(set_attr "type" "binary")
-  (set_attr "length" "8")])
-
-(define_insn ""
   [(set (match_operand:DI 0 "register_operand" "=r,r,!q")
        (minus:DI (match_operand:DI 1 "arith11_operand" "r,I,!U")
-                 (match_operand:DI 2 "register_operand" "r,r,!r")))]
+                 (match_operand:DI 2 "reg_or_0_operand" "rM,rM,!rM")))]
   "TARGET_64BIT"
   "@
    sub %1,%2,%0
   [(set_attr "type" "binary,binary,move")
   (set_attr "length" "4,4,4")])
 
+(define_insn ""
+  [(set (match_operand:DI 0 "register_operand" "=r,&r")
+       (minus:DI (match_operand:DI 1 "arith11_operand" "r,I")
+                 (match_operand:DI 2 "reg_or_0_operand" "rM,rM")))]
+  "!TARGET_64BIT"
+  "*
+{
+  if (GET_CODE (operands[1]) == CONST_INT)
+    {
+      if (INTVAL (operands[1]) >= 0)
+       return \"subi %1,%R2,%R0\;{subb|sub,b} %%r0,%2,%0\";
+      else
+       return \"ldi -1,%0\;subi %1,%R2,%R0\;{subb|sub,b} %0,%2,%0\";
+    }
+  else
+    return \"sub %R1,%R2,%R0\;{subb|sub,b} %1,%2,%0\";
+}"
+  [(set_attr "type" "binary")
+   (set (attr "length")
+       (if_then_else (eq_attr "alternative" "0")
+         (const_int 8)
+         (if_then_else (ge (symbol_ref "INTVAL (operands[1])")
+                           (const_int 0))
+           (const_int 8)
+           (const_int 12))))])
+
+(define_expand "subvdi3"
+  [(parallel [(set (match_operand:DI 0 "register_operand" "")
+                  (minus:DI (match_operand:DI 1 "arith11_operand" "")
+                            (match_operand:DI 2 "reg_or_0_operand" "")))
+             (trap_if (ne (minus:TI (sign_extend:TI (match_dup 1))
+                                    (sign_extend:TI (match_dup 2)))
+                          (sign_extend:TI (minus:DI (match_dup 1)
+                                                    (match_dup 2))))
+                      (const_int 0))])]
+  ""
+  "")
+
+(define_insn ""
+  [(set (match_operand:DI 0 "register_operand" "=r,r")
+       (minus:DI (match_operand:DI 1 "arith11_operand" "r,I")
+                 (match_operand:DI 2 "reg_or_0_operand" "rM,rM")))
+   (trap_if (ne (minus:TI (sign_extend:TI (match_dup 1))
+                         (sign_extend:TI (match_dup 2)))
+               (sign_extend:TI (minus:DI (match_dup 1)
+                                         (match_dup 2))))
+           (const_int 0))]
+  "TARGET_64BIT"
+  "@
+  {subo|sub,tsv} %1,%2,%0
+  {subio|subi,tsv} %1,%2,%0"
+  [(set_attr "type" "binary,binary")
+   (set_attr "length" "4,4")])
+
+(define_insn ""
+  [(set (match_operand:DI 0 "register_operand" "=r,&r")
+       (minus:DI (match_operand:DI 1 "arith11_operand" "r,I")
+                 (match_operand:DI 2 "reg_or_0_operand" "rM,rM")))
+   (trap_if (ne (minus:TI (sign_extend:TI (match_dup 1))
+                         (sign_extend:TI (match_dup 2)))
+               (sign_extend:TI (minus:DI (match_dup 1)
+                                         (match_dup 2))))
+           (const_int 0))]
+  "!TARGET_64BIT"
+  "*
+{
+  if (GET_CODE (operands[1]) == CONST_INT)
+    {
+      if (INTVAL (operands[1]) >= 0)
+       return \"subi %1,%R2,%R0\;{subbo|sub,b,tsv} %%r0,%2,%0\";
+      else
+       return \"ldi -1,%0\;subi %1,%R2,%R0\;{subbo|sub,b,tsv} %0,%2,%0\";
+    }
+  else
+    return \"sub %R1,%R2,%R0\;{subbo|sub,b,tsv} %1,%2,%0\";
+}"
+  [(set_attr "type" "binary,binary")
+   (set (attr "length")
+       (if_then_else (eq_attr "alternative" "0")
+         (const_int 8)
+         (if_then_else (ge (symbol_ref "INTVAL (operands[1])")
+                           (const_int 0))
+           (const_int 8)
+           (const_int 12))))])
+
 (define_expand "subsi3"
   [(set (match_operand:SI 0 "register_operand" "")
        (minus:SI (match_operand:SI 1 "arith11_operand" "")
   [(set_attr "type" "binary,binary,move")
    (set_attr "length" "4,4,4")])
 
+(define_insn "subvsi3"
+  [(set (match_operand:SI 0 "register_operand" "=r,r")
+       (minus:SI (match_operand:SI 1 "arith11_operand" "rM,I")
+                 (match_operand:SI 2 "reg_or_0_operand" "rM,rM")))
+   (trap_if (ne (minus:DI (sign_extend:DI (match_dup 1))
+                         (sign_extend:DI (match_dup 2)))
+               (sign_extend:DI (minus:SI (match_dup 1)
+                                         (match_dup 2))))
+           (const_int 0))]
+  ""
+  "@
+  {subo|sub,tsv} %1,%2,%0
+  {subio|subi,tsv} %1,%2,%0"
+  [(set_attr "type" "binary,binary")
+   (set_attr "length" "4,4")])
+
 ;; Clobbering a "register_operand" instead of a match_scratch
 ;; in operand3 of millicode calls avoids spilling %r1 and
 ;; produces better code.
   [(set_attr "type" "unary")
    (set_attr "length" "4")])
 
+(define_expand "negvdi2"
+  [(parallel [(set (match_operand:DI 0 "register_operand" "")
+                  (neg:DI (match_operand:DI 1 "register_operand" "")))
+             (trap_if (ne (neg:TI (sign_extend:TI (match_dup 1)))
+                                  (sign_extend:TI (neg:DI (match_dup 1))))
+                      (const_int 0))])]
+  ""
+  "")
+
+(define_insn ""
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (neg:DI (match_operand:DI 1 "register_operand" "r")))
+   (trap_if (ne (neg:TI (sign_extend:TI (match_dup 1)))
+               (sign_extend:TI (neg:DI (match_dup 1))))
+           (const_int 0))]
+  "!TARGET_64BIT"
+  "sub %%r0,%R1,%R0\;{subbo|sub,b,tsv} %%r0,%1,%0"
+  [(set_attr "type" "unary")
+   (set_attr "length" "8")])
+
+(define_insn ""
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (neg:DI (match_operand:DI 1 "register_operand" "r")))
+   (trap_if (ne (neg:TI (sign_extend:TI (match_dup 1)))
+               (sign_extend:TI (neg:DI (match_dup 1))))
+           (const_int 0))]
+  "TARGET_64BIT"
+  "sub,tsv %%r0,%1,%0"
+  [(set_attr "type" "unary")
+   (set_attr "length" "4")])
+
 (define_insn "negsi2"
   [(set (match_operand:SI 0 "register_operand" "=r")
        (neg:SI (match_operand:SI 1 "register_operand" "r")))]
   [(set_attr "type" "unary")
    (set_attr "length" "4")])
 
+(define_insn "negvsi2"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+        (neg:SI (match_operand:SI 1 "register_operand" "r")))
+   (trap_if (ne (neg:DI (sign_extend:DI (match_dup 1)))
+               (sign_extend:DI (neg:SI (match_dup 1))))
+           (const_int 0))]
+   ""
+   "{subo|sub,tsv} %%r0,%1,%0"
+  [(set_attr "type" "unary")
+   (set_attr "length" "4")])
+
 (define_expand "one_cmpldi2"
   [(set (match_operand:DI 0 "register_operand" "")
        (not:DI (match_operand:DI 1 "register_operand" "")))]
     (cond [(eq (symbol_ref "jump_in_call_delay (insn)") (const_int 1))
           (if_then_else (lt (abs (minus (match_dup 0)
                                         (plus (pc) (const_int 8))))
-                            (const_int 8184))
+                            (const_int MAX_12BIT_OFFSET))
           (const_int 4)
           (const_int 8))
           (lt (abs (minus (match_dup 0) (plus (pc) (const_int 8))))
-              (const_int 262100))
+              (const_int MAX_17BIT_OFFSET))
           (const_int 4)
           (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
           (const_int 20)
@@ -9007,10 +9233,10 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
 ;; Short branch has length of 4
 ;; Long branch has length of 8, 20, 24 or 28
        (cond [(lt (abs (minus (match_dup 3) (plus (pc) (const_int 8))))
-              (const_int 8184))
+              (const_int MAX_12BIT_OFFSET))
           (const_int 4)
           (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8))))
-              (const_int 262100))
+              (const_int MAX_17BIT_OFFSET))
           (const_int 8)
           (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
           (const_int 24)
@@ -9023,10 +9249,10 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
        (if_then_else (eq_attr "alternative" "1")
          (if_then_else (lt (match_dup 3) (pc))
             (cond [(lt (abs (minus (match_dup 3) (plus (pc) (const_int 24))))
-                     (const_int 8184))
+                     (const_int MAX_12BIT_OFFSET))
                    (const_int 24)
                    (lt (abs (minus (match_dup 3) (plus (pc) (const_int 24))))
-                     (const_int 262100))
+                     (const_int MAX_17BIT_OFFSET))
                    (const_int 28)
                    (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
                    (const_int 44)
@@ -9034,10 +9260,10 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
                    (const_int 40)]
                  (const_int 48))
             (cond [(lt (abs (minus (match_dup 3) (plus (pc) (const_int 8))))
-                     (const_int 8184))
+                     (const_int MAX_12BIT_OFFSET))
                    (const_int 24)
                    (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8))))
-                     (const_int 262100))
+                     (const_int MAX_17BIT_OFFSET))
                    (const_int 28)
                    (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
                    (const_int 44)
@@ -9049,10 +9275,10 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
 ;; Extra goo to deal with additional reload insns.
        (if_then_else (lt (match_dup 3) (pc))
             (cond [(lt (abs (minus (match_dup 3) (plus (pc) (const_int 12))))
-                     (const_int 8184))
+                     (const_int MAX_12BIT_OFFSET))
                    (const_int 12)
                    (lt (abs (minus (match_dup 3) (plus (pc) (const_int 12))))
-                     (const_int 262100))
+                     (const_int MAX_17BIT_OFFSET))
                    (const_int 16)
                    (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
                    (const_int 32)
@@ -9060,10 +9286,10 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
                    (const_int 28)]
                  (const_int 36))
             (cond [(lt (abs (minus (match_dup 3) (plus (pc) (const_int 8))))
-                     (const_int 8184))
+                     (const_int MAX_12BIT_OFFSET))
                    (const_int 12)
                    (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8))))
-                     (const_int 262100))
+                     (const_int MAX_17BIT_OFFSET))
                    (const_int 16)
                    (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
                    (const_int 32)
@@ -9090,10 +9316,10 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
 ;; Short branch has length of 4
 ;; Long branch has length of 8, 20, 24 or 28
         (cond [(lt (abs (minus (match_dup 3) (plus (pc) (const_int 8))))
-              (const_int 8184))
+              (const_int MAX_12BIT_OFFSET))
           (const_int 4)
           (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8))))
-              (const_int 262100))
+              (const_int MAX_17BIT_OFFSET))
           (const_int 8)
           (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
           (const_int 24)
@@ -9106,10 +9332,10 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
        (if_then_else (eq_attr "alternative" "1")
          (if_then_else (lt (match_dup 3) (pc))
             (cond [(lt (abs (minus (match_dup 3) (plus (pc) (const_int 12))))
-                     (const_int 8184))
+                     (const_int MAX_12BIT_OFFSET))
                    (const_int 12)
                    (lt (abs (minus (match_dup 3) (plus (pc) (const_int 12))))
-                     (const_int 262100))
+                     (const_int MAX_17BIT_OFFSET))
                    (const_int 16)
                    (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
                    (const_int 32)
@@ -9117,10 +9343,10 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
                    (const_int 28)]
                  (const_int 36))
             (cond [(lt (abs (minus (match_dup 3) (plus (pc) (const_int 8))))
-                     (const_int 8184))
+                     (const_int MAX_12BIT_OFFSET))
                    (const_int 12)
                    (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8))))
-                     (const_int 262100))
+                     (const_int MAX_17BIT_OFFSET))
                    (const_int 16)
                    (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
                    (const_int 32)
@@ -9131,10 +9357,10 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
 ;; Loop counter in memory or sar case.
 ;; Extra goo to deal with additional reload insns.
        (cond [(lt (abs (minus (match_dup 3) (plus (pc) (const_int 8))))
-                  (const_int 8184))
+                  (const_int MAX_12BIT_OFFSET))
                (const_int 8)
                (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8))))
-                 (const_int 262100))
+                 (const_int MAX_17BIT_OFFSET))
                (const_int 12)
                (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
                (const_int 28)
@@ -9162,10 +9388,10 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
 ;; Short branch has length of 4
 ;; Long branch has length of 8
         (cond [(lt (abs (minus (match_dup 3) (plus (pc) (const_int 8))))
-              (const_int 8184))
+              (const_int MAX_12BIT_OFFSET))
           (const_int 4)
           (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8))))
-              (const_int 262100))
+              (const_int MAX_17BIT_OFFSET))
           (const_int 8)
           (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
           (const_int 24)
@@ -9178,10 +9404,10 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
        (if_then_else (eq_attr "alternative" "1")
          (if_then_else (lt (match_dup 3) (pc))
             (cond [(lt (abs (minus (match_dup 3) (plus (pc) (const_int 12))))
-                     (const_int 8184))
+                     (const_int MAX_12BIT_OFFSET))
                    (const_int 12)
                    (lt (abs (minus (match_dup 3) (plus (pc) (const_int 12))))
-                     (const_int 262100))
+                     (const_int MAX_17BIT_OFFSET))
                    (const_int 16)
                    (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
                    (const_int 32)
@@ -9189,10 +9415,10 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
                    (const_int 28)]
                  (const_int 36))
             (cond [(lt (abs (minus (match_dup 3) (plus (pc) (const_int 8))))
-                     (const_int 8184))
+                     (const_int MAX_12BIT_OFFSET))
                    (const_int 12)
                    (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8))))
-                     (const_int 262100))
+                     (const_int MAX_17BIT_OFFSET))
                    (const_int 16)
                    (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
                    (const_int 32)
@@ -9203,10 +9429,10 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
 ;; Loop counter in memory or SAR case.
 ;; Extra goo to deal with additional reload insns.
        (cond [(lt (abs (minus (match_dup 3) (plus (pc) (const_int 8))))
-                  (const_int 8184))
+                  (const_int MAX_12BIT_OFFSET))
                (const_int 8)
                (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8))))
-                 (const_int 262100))
+                 (const_int MAX_17BIT_OFFSET))
                (const_int 12)
                (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
                (const_int 28)
@@ -9227,10 +9453,10 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
 [(set_attr "type" "parallel_branch")
  (set (attr "length")
     (cond [(lt (abs (minus (match_dup 3) (plus (pc) (const_int 8))))
-              (const_int 8184))
+              (const_int MAX_12BIT_OFFSET))
           (const_int 4)
           (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8))))
-              (const_int 262100))
+              (const_int MAX_17BIT_OFFSET))
           (const_int 8)
           (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
           (const_int 24)
@@ -9250,10 +9476,10 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
 [(set_attr "type" "parallel_branch")
  (set (attr "length")
     (cond [(lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
-              (const_int 8184))
+              (const_int MAX_12BIT_OFFSET))
           (const_int 4)
           (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
-              (const_int 262100))
+              (const_int MAX_17BIT_OFFSET))
           (const_int 8)
           (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
           (const_int 24)
@@ -9273,10 +9499,10 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
 [(set_attr "type" "parallel_branch")
  (set (attr "length")
     (cond [(lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
-              (const_int 8184))
+              (const_int MAX_12BIT_OFFSET))
           (const_int 4)
           (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
-              (const_int 262100))
+              (const_int MAX_17BIT_OFFSET))
           (const_int 8)
           (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
           (const_int 24)
@@ -9296,10 +9522,10 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
 [(set_attr "type" "parallel_branch")
  (set (attr "length")
     (cond [(lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
-              (const_int 8184))
+              (const_int MAX_12BIT_OFFSET))
           (const_int 4)
           (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
-              (const_int 262100))
+              (const_int MAX_17BIT_OFFSET))
           (const_int 8)
           (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
           (const_int 24)
@@ -9319,10 +9545,10 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
 [(set_attr "type" "parallel_branch")
  (set (attr "length")
     (cond [(lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
-              (const_int 8184))
+              (const_int MAX_12BIT_OFFSET))
           (const_int 4)
           (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
-              (const_int 262100))
+              (const_int MAX_17BIT_OFFSET))
           (const_int 8)
           (ne (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
           (const_int 24)
@@ -9883,7 +10109,7 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
   [(set (match_operand:SI 0 "register_operand" "=r")
        (unspec:SI [(const_int 0)] UNSPEC_TP))]
   ""
-  "{mfctl|mfctl,w} %%cr27,%0"
+  "mfctl %%cr27,%0"
   [(set_attr "type" "multi")
    (set_attr "length" "4")])