re PR target/5626 (gcc-3.1 on sparcv9 does not generate code for long jumps)
authorJakub Jelinek <jakub@redhat.com>
Wed, 13 Mar 2002 19:48:29 +0000 (20:48 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Wed, 13 Mar 2002 19:48:29 +0000 (20:48 +0100)
PR target/5626
* config/sparc/sparc.md (normal_branch, inverted_branch,
normal_fp_branch, inverted_fp_branch, normal_fpe_branch,
inverted_fp_branch): Adjust calls to output_cbranch.
Set length attribute.
(normal_int_branch_sp64, inverted_int_branch_sp64): Adjust calls to
output_v9branch.  Set length attribute.
* config/sparc/sparc.c (fcc0_reg_operand, noov_compare64_op): New
predicates.
(noov_compare_op): Handle CCX_NOOVmode the same way as CC_NOOVmode.
(output_cbranch): Likewise.  Handle far branches.
(output_v9branch): Handle far branches.
* config/sparc/sparc-protos.h (output_cbranch, output_v9branch):
Adjust prototypes.
* config/sparc/sparc.h (PREDICATE_CODES): Add fcc0_reg_operand and
noov_compare64_op predicates.

From-SVN: r50753

gcc/ChangeLog
gcc/config/sparc/sparc-protos.h
gcc/config/sparc/sparc.c
gcc/config/sparc/sparc.h
gcc/config/sparc/sparc.md

index c7ed555c992c0262ea5ddaa3665c24b406f58fbf..4286a2112cbdf6f3ed2ab878b43722e7cefad63c 100644 (file)
@@ -1,3 +1,22 @@
+2002-03-13  Jakub Jelinek  <jakub@redhat.com>
+
+       PR target/5626
+       * config/sparc/sparc.md (normal_branch, inverted_branch,
+       normal_fp_branch, inverted_fp_branch, normal_fpe_branch,
+       inverted_fp_branch): Adjust calls to output_cbranch.
+       Set length attribute.
+       (normal_int_branch_sp64, inverted_int_branch_sp64): Adjust calls to
+       output_v9branch.  Set length attribute.
+       * config/sparc/sparc.c (fcc0_reg_operand, noov_compare64_op): New
+       predicates.
+       (noov_compare_op): Handle CCX_NOOVmode the same way as CC_NOOVmode.
+       (output_cbranch): Likewise.  Handle far branches.
+       (output_v9branch): Handle far branches.
+       * config/sparc/sparc-protos.h (output_cbranch, output_v9branch):
+       Adjust prototypes.
+       * config/sparc/sparc.h (PREDICATE_CODES): Add fcc0_reg_operand and
+       noov_compare64_op predicates.
+
 2002-03-13  Jason Merrill  <jason@redhat.com>
 
        * gthr-posix.h (__gthread_active_p): Move __gthread_active_ptr
index c0f3edce65dc176abbd520e77eb8624ae1afea96..682b7bdb8533e5e57c1b5bba4277eca01cae1f3c 100644 (file)
@@ -85,10 +85,11 @@ extern void sparc_emit_set_const64 PARAMS ((rtx, rtx));
 extern void sparc_emit_set_symbolic_const64 PARAMS ((rtx, rtx, rtx));
 extern int sparc_splitdi_legitimate PARAMS ((rtx, rtx));
 extern int sparc_absnegfloat_split_legitimate PARAMS ((rtx, rtx));
-extern char *output_cbranch PARAMS ((rtx, int, int, int, int, rtx));
+extern char *output_cbranch PARAMS ((rtx, rtx, int, int, int, int, rtx));
 extern const char *output_return PARAMS ((rtx *));
 extern const char *output_sibcall PARAMS ((rtx, rtx));
-extern char *output_v9branch PARAMS ((rtx, int, int, int, int, int, rtx));
+extern char *output_v9branch PARAMS ((rtx, rtx, int, int, int, int, int,
+                                     rtx));
 extern void emit_v9_brxx_insn PARAMS ((enum rtx_code, rtx, rtx));
 extern void print_operand PARAMS ((FILE *, rtx, int));
 extern int mems_ok_for_ldd_peep PARAMS ((rtx, rtx, rtx));
index d678aa2a2f40352857e82f347ea15d288736f16e..6f33bcc0cb920c673c69b73762d79dc4b8f54d52 100644 (file)
@@ -608,6 +608,27 @@ fcc_reg_operand (op, mode)
 #endif
 }
 
+/* Nonzero if OP is a floating point condition code fcc0 register.  */
+
+int
+fcc0_reg_operand (op, mode)
+     rtx op;
+     enum machine_mode mode;
+{
+  /* This can happen when recog is called from combine.  Op may be a MEM.
+     Fail instead of calling abort in this case.  */
+  if (GET_CODE (op) != REG)
+    return 0;
+
+  if (mode != VOIDmode && mode != GET_MODE (op))
+    return 0;
+  if (mode == VOIDmode
+      && (GET_MODE (op) != CCFPmode && GET_MODE (op) != CCFPEmode))
+    return 0;
+
+  return REGNO (op) == SPARC_FCC_REG;
+}
+
 /* Nonzero if OP is an integer or floating point condition code register.  */
 
 int
@@ -878,12 +899,35 @@ noov_compare_op (op, mode)
   if (GET_RTX_CLASS (code) != '<')
     return 0;
 
-  if (GET_MODE (XEXP (op, 0)) == CC_NOOVmode)
+  if (GET_MODE (XEXP (op, 0)) == CC_NOOVmode
+      || GET_MODE (XEXP (op, 0)) == CCX_NOOVmode)
     /* These are the only branches which work with CC_NOOVmode.  */
     return (code == EQ || code == NE || code == GE || code == LT);
   return 1;
 }
 
+/* Return 1 if this is a 64-bit comparison operator.  This allows the use of
+   MATCH_OPERATOR to recognize all the branch insns.  */
+
+int
+noov_compare64_op (op, mode)
+    register rtx op;
+    enum machine_mode mode ATTRIBUTE_UNUSED;
+{
+  enum rtx_code code = GET_CODE (op);
+
+  if (! TARGET_V9)
+    return 0;
+
+  if (GET_RTX_CLASS (code) != '<')
+    return 0;
+
+  if (GET_MODE (XEXP (op, 0)) == CCX_NOOVmode)
+    /* These are the only branches which work with CCX_NOOVmode.  */
+    return (code == EQ || code == NE || code == GE || code == LT);
+  return (GET_MODE (XEXP (op, 0)) == CCXmode);
+}
+
 /* Nonzero if OP is a comparison operator suitable for use in v9
    conditional move or branch on register contents instructions.  */
 
@@ -4996,25 +5040,43 @@ sparc_va_arg (valist, type)
    INSN, if set, is the insn.  */
 
 char *
-output_cbranch (op, label, reversed, annul, noop, insn)
-     rtx op;
+output_cbranch (op, dest, label, reversed, annul, noop, insn)
+     rtx op, dest;
      int label;
      int reversed, annul, noop;
      rtx insn;
 {
-  static char string[32];
+  static char string[50];
   enum rtx_code code = GET_CODE (op);
   rtx cc_reg = XEXP (op, 0);
   enum machine_mode mode = GET_MODE (cc_reg);
-  static char v8_labelno[] = "%lX";
-  static char v9_icc_labelno[] = "%%icc, %lX";
-  static char v9_xcc_labelno[] = "%%xcc, %lX";
-  static char v9_fcc_labelno[] = "%%fccX, %lY";
-  char *labelno;
-  const char *branch;
-  int labeloff, spaces = 8;
+  const char *labelno, *branch;
+  int spaces = 8, far;
+  char *p;
+
+  /* v9 branches are limited to +-1MB.  If it is too far away,
+     change
+
+     bne,pt %xcc, .LC30
+
+     to
+
+     be,pn %xcc, .+12
+     nop
+     ba .LC30
+
+     and
+
+     fbne,a,pn %fcc2, .LC29
 
-  if (reversed)
+     to
+
+     fbe,pt %fcc2, .+16
+     nop
+     ba .LC29  */
+
+  far = get_attr_length (insn) >= 3;
+  if (reversed ^ far)
     {
       /* Reversal of FP compares takes care -- an ordered compare
         becomes an unordered compare and vice versa.  */
@@ -5097,7 +5159,7 @@ output_cbranch (op, label, reversed, annul, noop, insn)
          branch = "be";
          break;
        case GE:
-         if (mode == CC_NOOVmode)
+         if (mode == CC_NOOVmode || mode == CCX_NOOVmode)
            branch = "bpos";
          else
            branch = "bge";
@@ -5109,7 +5171,7 @@ output_cbranch (op, label, reversed, annul, noop, insn)
          branch = "ble";
          break;
        case LT:
-         if (mode == CC_NOOVmode)
+         if (mode == CC_NOOVmode || mode == CCX_NOOVmode)
            branch = "bneg";
          else
            branch = "bl";
@@ -5133,54 +5195,89 @@ output_cbranch (op, label, reversed, annul, noop, insn)
       strcpy (string, branch);
     }
   spaces -= strlen (branch);
+  p = strchr (string, '\0');
 
   /* Now add the annulling, the label, and a possible noop.  */
-  if (annul)
+  if (annul && ! far)
     {
-      strcat (string, ",a");
+      strcpy (p, ",a");
+      p += 2;
       spaces -= 2;
     }
 
   if (! TARGET_V9)
-    {
-      labeloff = 2;
-      labelno = v8_labelno;
-    }
+    labelno = "";
   else
     {
       rtx note;
+      int v8 = 0;
 
-      if (insn && (note = find_reg_note (insn, REG_BR_PRED, NULL_RTX)))
+      if (! far && insn && INSN_ADDRESSES_SET_P ())
        {
-         strcat (string,
-                 INTVAL (XEXP (note, 0)) & ATTR_FLAG_likely ? ",pt" : ",pn");
-         spaces -= 3;
+         int delta = (INSN_ADDRESSES (INSN_UID (dest))
+                      - INSN_ADDRESSES (INSN_UID (insn)));
+         /* Leave some instructions for "slop".  */
+         if (delta < -260000 || delta >= 260000)
+           v8 = 1;
        }
 
-      labeloff = 9;
       if (mode == CCFPmode || mode == CCFPEmode)
        {
-         labeloff = 10;
-         labelno = v9_fcc_labelno;
+         static char v9_fcc_labelno[] = "%%fccX, ";
          /* Set the char indicating the number of the fcc reg to use.  */
-         labelno[5] = REGNO (cc_reg) - SPARC_FIRST_V9_FCC_REG + '0';
+         v9_fcc_labelno[5] = REGNO (cc_reg) - SPARC_FIRST_V9_FCC_REG + '0';
+         labelno = v9_fcc_labelno;
+         if (v8)
+           {
+             if (REGNO (cc_reg) == SPARC_FCC_REG)
+               labelno = "";
+             else
+               abort ();
+           }
        }
       else if (mode == CCXmode || mode == CCX_NOOVmode)
-       labelno = v9_xcc_labelno;
+       {
+         labelno = "%%xcc, ";
+         if (v8)
+           abort ();
+       }
       else
-       labelno = v9_icc_labelno;
+       {
+         labelno = "%%icc, ";
+         if (v8)
+           labelno = "";
+       }
+
+      if (*labelno && insn && (note = find_reg_note (insn, REG_BR_PRED, NULL_RTX)))
+       {
+         strcpy (p,
+                 (((INTVAL (XEXP (note, 0)) & ATTR_FLAG_likely) != 0) ^ far)
+                 ? ",pt" : ",pn");
+         p += 3;
+         spaces -= 3;
+       }
     }
-  /* Set the char indicating the number of the operand containing the
-     label_ref.  */
-  labelno[labeloff] = label + '0';
   if (spaces > 0)
-    strcat (string, "\t");
+    *p++ = '\t';
   else
-    strcat (string, " ");
-  strcat (string, labelno);
-
+    *p++ = ' ';
+  strcpy (p, labelno);
+  p = strchr (p, '\0');
+  if (far)
+    {
+      strcpy (p, ".+12\n\tnop\n\tb\t");
+      if (annul || noop)
+        p[3] = '6';
+      p += 13;
+    }
+  *p++ = '%';
+  *p++ = 'l';
+  /* Set the char indicating the number of the operand containing the
+     label_ref.  */
+  *p++ = label + '0';
+  *p = '\0';
   if (noop)
-    strcat (string, "\n\tnop");
+    strcpy (p, "\n\tnop");
 
   return string;
 }
@@ -5338,22 +5435,45 @@ sparc_emit_float_lib_cmp (x, y, comparison)
    NOOP is non-zero if we have to follow this branch by a noop.  */
 
 char *
-output_v9branch (op, reg, label, reversed, annul, noop, insn)
-     rtx op;
+output_v9branch (op, dest, reg, label, reversed, annul, noop, insn)
+     rtx op, dest;
      int reg, label;
      int reversed, annul, noop;
      rtx insn;
 {
-  static char string[20];
+  static char string[50];
   enum rtx_code code = GET_CODE (op);
   enum machine_mode mode = GET_MODE (XEXP (op, 0));
-  static char labelno[] = "%X, %lX";
   rtx note;
-  int spaces = 8;
+  int far;
+  char *p;
+
+  /* branch on register are limited to +-128KB.  If it is too far away,
+     change
+     
+     brnz,pt %g1, .LC30
+     
+     to
+     
+     brz,pn %g1, .+12
+     nop
+     ba,pt %xcc, .LC30
+     
+     and
+     
+     brgez,a,pn %o1, .LC29
+     
+     to
+     
+     brlz,pt %o1, .+16
+     nop
+     ba,pt %xcc, .LC29  */
+
+  far = get_attr_length (insn) >= 3;
 
   /* If not floating-point or if EQ or NE, we can just reverse the code.  */
-  if (reversed)
-    code = reverse_condition (code), reversed = 0;
+  if (reversed ^ far)
+    code = reverse_condition (code);
 
   /* Only 64 bit versions of these instructions exist.  */
   if (mode != DImode)
@@ -5365,62 +5485,90 @@ output_v9branch (op, reg, label, reversed, annul, noop, insn)
     {
     case NE:
       strcpy (string, "brnz");
-      spaces -= 4;
       break;
 
     case EQ:
       strcpy (string, "brz");
-      spaces -= 3;
       break;
 
     case GE:
       strcpy (string, "brgez");
-      spaces -= 5;
       break;
 
     case LT:
       strcpy (string, "brlz");
-      spaces -= 4;
       break;
 
     case LE:
       strcpy (string, "brlez");
-      spaces -= 5;
       break;
 
     case GT:
       strcpy (string, "brgz");
-      spaces -= 4;
       break;
 
     default:
       abort ();
     }
 
+  p = strchr (string, '\0');
+
   /* Now add the annulling, reg, label, and nop.  */
-  if (annul)
+  if (annul && ! far)
     {
-      strcat (string, ",a");
-      spaces -= 2;
+      strcpy (p, ",a");
+      p += 2;
     }
 
   if (insn && (note = find_reg_note (insn, REG_BR_PRED, NULL_RTX)))
     {
-      strcat (string,
-             INTVAL (XEXP (note, 0)) & ATTR_FLAG_likely ? ",pt" : ",pn");
-      spaces -= 3;
+      strcpy (p,
+             (((INTVAL (XEXP (note, 0)) & ATTR_FLAG_likely) != 0) ^ far)
+             ? ",pt" : ",pn");
+      p += 3;
     }
 
-  labelno[1] = reg + '0';
-  labelno[6] = label + '0';
-  if (spaces > 0)
-    strcat (string, "\t");
-  else
-    strcat (string, " ");
-  strcat (string, labelno);
+  *p = p < string + 8 ? '\t' : ' ';
+  p++;
+  *p++ = '%';
+  *p++ = '0' + reg;
+  *p++ = ',';
+  *p++ = ' ';
+  if (far)
+    {
+      int veryfar = 1, delta;
+
+      if (INSN_ADDRESSES_SET_P ())
+       {
+         delta = (INSN_ADDRESSES (INSN_UID (dest))
+                  - INSN_ADDRESSES (INSN_UID (insn)));
+         /* Leave some instructions for "slop".  */
+         if (delta >= -260000 && delta < 260000)
+           veryfar = 0;
+       }
+
+      strcpy (p, ".+12\n\tnop\n\t");
+      if (annul || noop)
+        p[3] = '6';
+      p += 11;
+      if (veryfar)
+       {
+         strcpy (p, "b\t");
+         p += 2;
+       }
+      else
+       {
+         strcpy (p, "ba,pt\t%%xcc, ");
+         p += 13;
+       }
+    }
+  *p++ = '%';
+  *p++ = 'l';
+  *p++ = '0' + label;
+  *p = '\0';
 
   if (noop)
-    strcat (string, "\n\tnop");
+    strcpy (p, "\n\tnop");
 
   return string;
 }
index 8caa9328acdca919f783975dddf636d405b45b40..e765973c07d0bc0ac7cc4334ffcc68935f55e3d8 100644 (file)
@@ -2974,6 +2974,7 @@ do {                                                                      \
 {"fp_zero_operand", {CONST_DOUBLE}},                                   \
 {"intreg_operand", {SUBREG, REG}},                                     \
 {"fcc_reg_operand", {REG}},                                            \
+{"fcc0_reg_operand", {REG}},                                           \
 {"icc_or_fcc_reg_operand", {REG}},                                     \
 {"restore_operand", {REG}},                                            \
 {"call_operand", {MEM}},                                               \
@@ -2991,6 +2992,7 @@ do {                                                                      \
 {"eq_or_neq", {EQ, NE}},                                               \
 {"normal_comp_operator", {GE, GT, LE, LT, GTU, LEU}},                  \
 {"noov_compare_op", {NE, EQ, GE, GT, LE, LT, GEU, GTU, LEU, LTU}},     \
+{"noov_compare64_op", {NE, EQ, GE, GT, LE, LT, GEU, GTU, LEU, LTU}},   \
 {"v9_regcmp_op", {EQ, NE, GE, LT, LE, GT}},                            \
 {"extend_op", {SIGN_EXTEND, ZERO_EXTEND}},                             \
 {"cc_arithop", {AND, IOR, XOR}},                                       \
index 18b2ba8f90fef214db841fe1fe0fb5b62163c90a..c203e4fa89208eabad641998415d07d67d3dfdaf 100644 (file)
   ""
   "*
 {
-  return output_cbranch (operands[0], 1, 0,
+  return output_cbranch (operands[0], operands[1], 1, 0,
                         final_sequence && INSN_ANNULLED_BRANCH_P (insn),
                         ! final_sequence, insn);
 }"
-  [(set_attr "type" "branch")])
+  [(set_attr "type" "branch")
+   (set (attr "length")
+       (if_then_else (match_operand 0 "noov_compare64_op" "")
+                     (if_then_else (lt (pc) (match_dup 1))
+                                   (if_then_else (lt (minus (match_dup 1) (pc))
+                                                     (const_int 260000))
+                                                 (const_int 1)
+                                                 (const_int 3))
+                                   (if_then_else (lt (minus (pc) (match_dup 1))
+                                                     (const_int 260000))
+                                                 (const_int 1)
+                                                 (const_int 3)))
+                     (const_int 1)))])
 
 ;; XXX fpcmp nop braindamage
 (define_insn "*inverted_branch"
   ""
   "*
 {
-  return output_cbranch (operands[0], 1, 1,
+  return output_cbranch (operands[0], operands[1], 1, 1,
                         final_sequence && INSN_ANNULLED_BRANCH_P (insn),
                         ! final_sequence, insn);
 }"
-  [(set_attr "type" "branch")])
+  [(set_attr "type" "branch")
+   (set (attr "length")
+       (if_then_else (match_operand 0 "noov_compare64_op" "")
+                     (if_then_else (lt (pc) (match_dup 1))
+                                   (if_then_else (lt (minus (match_dup 1) (pc))
+                                                     (const_int 260000))
+                                                 (const_int 1)
+                                                 (const_int 3))
+                                   (if_then_else (lt (minus (pc) (match_dup 1))
+                                                     (const_int 260000))
+                                                 (const_int 1)
+                                                 (const_int 3)))
+                     (const_int 1)))])
 
 ;; XXX fpcmp nop braindamage
 (define_insn "*normal_fp_branch"
   ""
   "*
 {
-  return output_cbranch (operands[1], 2, 0,
+  return output_cbranch (operands[1], operands[2], 2, 0,
                         final_sequence && INSN_ANNULLED_BRANCH_P (insn),
                         ! final_sequence, insn);
 }"
-  [(set_attr "type" "branch")])
+  [(set_attr "type" "branch")
+   (set (attr "length")
+       (if_then_else (match_operand 0 "fcc0_reg_operand" "")
+                     (const_int 1)
+                     (if_then_else (lt (pc) (match_dup 2))
+                                   (if_then_else (lt (minus (match_dup 2) (pc))
+                                                     (const_int 260000))
+                                                 (const_int 1)
+                                                 (const_int 3))
+                                   (if_then_else (lt (minus (pc) (match_dup 2))
+                                                     (const_int 260000))
+                                                 (const_int 1)
+                                                 (const_int 3)))))])
 
 ;; XXX fpcmp nop braindamage
 (define_insn "*inverted_fp_branch"
   ""
   "*
 {
-  return output_cbranch (operands[1], 2, 1,
+  return output_cbranch (operands[1], operands[2], 2, 1,
                         final_sequence && INSN_ANNULLED_BRANCH_P (insn),
                         ! final_sequence, insn);
 }"
-  [(set_attr "type" "branch")])
+  [(set_attr "type" "branch")
+   (set (attr "length")
+       (if_then_else (match_operand 0 "fcc0_reg_operand" "")
+                     (const_int 1)
+                     (if_then_else (lt (pc) (match_dup 2))
+                                   (if_then_else (lt (minus (match_dup 2) (pc))
+                                                     (const_int 260000))
+                                                 (const_int 1)
+                                                 (const_int 3))
+                                   (if_then_else (lt (minus (pc) (match_dup 2))
+                                                     (const_int 260000))
+                                                 (const_int 1)
+                                                 (const_int 3)))))])
 
 ;; XXX fpcmp nop braindamage
 (define_insn "*normal_fpe_branch"
   ""
   "*
 {
-  return output_cbranch (operands[1], 2, 0,
+  return output_cbranch (operands[1], operands[2], 2, 0,
                         final_sequence && INSN_ANNULLED_BRANCH_P (insn),
                         ! final_sequence, insn);
 }"
-  [(set_attr "type" "branch")])
+  [(set_attr "type" "branch")
+   (set (attr "length")
+       (if_then_else (match_operand 0 "fcc0_reg_operand" "")
+                     (const_int 1)
+                     (if_then_else (lt (pc) (match_dup 2))
+                                   (if_then_else (lt (minus (match_dup 2) (pc))
+                                                     (const_int 260000))
+                                                 (const_int 1)
+                                                 (const_int 3))
+                                   (if_then_else (lt (minus (pc) (match_dup 2))
+                                                     (const_int 260000))
+                                                 (const_int 1)
+                                                 (const_int 3)))))])
 
 ;; XXX fpcmp nop braindamage
 (define_insn "*inverted_fpe_branch"
   ""
   "*
 {
-  return output_cbranch (operands[1], 2, 1,
+  return output_cbranch (operands[1], operands[2], 2, 1,
                         final_sequence && INSN_ANNULLED_BRANCH_P (insn),
                         ! final_sequence, insn);
 }"
-  [(set_attr "type" "branch")])
+  [(set_attr "type" "branch")
+   (set (attr "length")
+       (if_then_else (match_operand 0 "fcc0_reg_operand" "")
+                     (const_int 1)
+                     (if_then_else (lt (pc) (match_dup 2))
+                                   (if_then_else (lt (minus (match_dup 2) (pc))
+                                                     (const_int 260000))
+                                                 (const_int 1)
+                                                 (const_int 3))
+                                   (if_then_else (lt (minus (pc) (match_dup 2))
+                                                     (const_int 260000))
+                                                 (const_int 1)
+                                                 (const_int 3)))))])
 
 ;; Sparc V9-specific jump insns.  None of these are guaranteed to be
 ;; in the architecture.
   "TARGET_ARCH64"
   "*
 {
-  return output_v9branch (operands[0], 1, 2, 0,
+  return output_v9branch (operands[0], operands[2], 1, 2, 0,
                          final_sequence && INSN_ANNULLED_BRANCH_P (insn),
                          ! final_sequence, insn);
 }"
-  [(set_attr "type" "branch")])
+  [(set_attr "type" "branch")
+   (set (attr "length")
+        (if_then_else (lt (pc) (match_dup 2))
+                     (if_then_else (lt (minus (match_dup 2) (pc))
+                                       (const_int 32000))
+                                   (const_int 1)
+                                   (const_int 3))
+                     (if_then_else (lt (minus (pc) (match_dup 2))
+                                       (const_int 32000))
+                                   (const_int 1)
+                                   (const_int 3))))])
 
 ;; XXX
 (define_insn "*inverted_int_branch_sp64"
   "TARGET_ARCH64"
   "*
 {
-  return output_v9branch (operands[0], 1, 2, 1,
+  return output_v9branch (operands[0], operands[2], 1, 2, 1,
                          final_sequence && INSN_ANNULLED_BRANCH_P (insn),
                          ! final_sequence, insn);
 }"
-  [(set_attr "type" "branch")])
+  [(set_attr "type" "branch")
+   (set (attr "length")
+        (if_then_else (lt (pc) (match_dup 2))
+                     (if_then_else (lt (minus (match_dup 2) (pc))
+                                       (const_int 32000))
+                                   (const_int 1)
+                                   (const_int 3))
+                     (if_then_else (lt (minus (pc) (match_dup 2))
+                                       (const_int 32000))
+                                   (const_int 1)
+                                   (const_int 3))))])
 \f
 ;; Load program counter insns.