Starting with SPARC-T4 we have support for fused compare-and-branch
instructions.  These are documented at:

http://www.oracle.com/technetwork/systems/opensparc/sparc-architecture-2011-1728132.pdf

But, to summarize the form is:

        c{w,x}b{$COND}  rs1, {rs2,imm5}, LABEL

'w' means 32-bit, 'x' means 64-bit

rs1 is an integer register, rs2 may be either an integer register or a
5-bit signed immediate.

No condition codes are modified, it's all done internally to the
instruction.

There is no delay slot.

The branch destination field is only 10-bits large, so the range is
around +-2K.

This patch below works extremely well for me.  The only tests that
fail are things like the test that makes sure that sparc delay slots
are filled :-)  I'll adjust stuff like that before the final version.

The trouble area, and where I need help from either Rainer or Eric,
is the Solaris2 bits.

I think we need to move the Solaris assembler stuff over to a model
where it passes:

        -m{32,64} -xarch=sparcFOO

instead of using the v8plusX stuff to indicate 32bit.  And that's
the direction I tried to move in here.

Could one of you help me get the solaris side correct?  I made sure
that binutils accepts the same options for this stuff, that's why
I can unconditionally use '-xarch=sparc4' in the configure test.

That config test should work fine as-is on Solaris, but if it doesn't
please let me know.

Thanks!

gcc/

2012-10-12  David S. Miller  <da...@davemloft.net>

        * configure.ac: Add check for assembler SPARC4 instruction
        support.
        * configure: Rebuild.
        * config.in: Add HAVE_AS_SPARC4 section.
        * config/sparc/sparc.opt (mvis4): New option.
        * config/sparc/sparc-c.c (sparc_target_macros): When TARGET_VIS4,
        define __VIS__ to 0x400.
        * config/sparc/constraints.md: New constraint 'A' for 5-bit signed
        immediates.
        * doc/md.texi: Document it.
        * config/sparc/sparc.c (dump_target_flag_bits): Handle MASK_VIS4.
        (sparc_option_override): Likewise.
        (emit_cbcond_insn): New function.
        (emit_conditional_branch_insn): Call it.
        (output_cbcond): New function.
        * config/sparc/sparc-protos.h (output_cbcond): Declare it.
        * config/sparc/sparc.md (type attribute): New type 'cbcond'.
        (length attribute): Handle it.
        (*cbcond_sp32, *cbcond_sp64): New insn patterns.
        * config/sparc/niagara4.md: Match 'cbcond' in 'n4_cti'.
        * config/sparc/sparc.h (AS_NIAGARA4_FLAG): New macro, use it
        when target default is niagara4.
        (SPARC_SIMM5_P): Define.
        * config/sparc/sol2.h (AS_SPARC64_FLAG): Adjust.
        (AS_SPARC32_FLAG): Define.
        (ASM_CPU32_DEFAULT_SPEC, ASM_CPU64_DEFAULT_SPEC): Use
        AS_NIAGARA4_FLAG as needed.

diff --git a/gcc/config.in b/gcc/config.in
index b13805d..791d14a 100644
--- a/gcc/config.in
+++ b/gcc/config.in
@@ -266,6 +266,12 @@
 #endif
 
 
+/* Define if your assembler supports SPARC4 instructions. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_SPARC4
+#endif
+
+
 /* Define if your assembler supports fprnd. */
 #ifndef USED_FOR_TARGET
 #undef HAVE_AS_FPRND
diff --git a/gcc/config/sparc/constraints.md b/gcc/config/sparc/constraints.md
index 472490f..e5d973f 100644
--- a/gcc/config/sparc/constraints.md
+++ b/gcc/config/sparc/constraints.md
@@ -18,7 +18,7 @@
 ;; <http://www.gnu.org/licenses/>.
 
 ;;; Unused letters:
-;;;    AB                       
+;;;     B                       
 ;;;    a        jkl    q  tuv xyz
 
 
@@ -62,6 +62,11 @@
 
 ;; Integer constant constraints
 
+(define_constraint "A"
+ "Signed 5-bit integer constant"
+ (and (match_code "const_int")
+      (match_test "SPARC_SIMM5_P (ival)")))
+
 (define_constraint "H"
  "Valid operand of double arithmetic operation"
  (and (match_code "const_double")
diff --git a/gcc/config/sparc/niagara4.md b/gcc/config/sparc/niagara4.md
index 272c8ff..0dc0eb0 100644
--- a/gcc/config/sparc/niagara4.md
+++ b/gcc/config/sparc/niagara4.md
@@ -56,7 +56,7 @@
 
 (define_insn_reservation "n4_cti" 2
   (and (eq_attr "cpu" "niagara4")
-    (eq_attr "type" 
"branch,call,sibcall,call_no_delay_slot,uncond_branch,return"))
+    (eq_attr "type" 
"cbcond,branch,call,sibcall,call_no_delay_slot,uncond_branch,return"))
   "n4_slot1, nothing")
 
 (define_insn_reservation "n4_fp" 11
diff --git a/gcc/config/sparc/sol2.h b/gcc/config/sparc/sol2.h
index ba2ec35..68cc592 100644
--- a/gcc/config/sparc/sol2.h
+++ b/gcc/config/sparc/sol2.h
@@ -58,8 +58,10 @@ along with GCC; see the file COPYING3.  If not see
    other assemblers will accept.  */
 
 #ifndef USE_GAS
-#define AS_SPARC64_FLAG        "-xarch=v9"
+#define AS_SPARC32_FLAG        "-m32 -xarch=v9"
+#define AS_SPARC64_FLAG        "-m64 -xarch=v9"
 #else
+#define AS_SPARC32_FLAG        "-TSO -32 -Av9"
 #define AS_SPARC64_FLAG        "-TSO -64 -Av9"
 #endif
 
@@ -136,9 +138,9 @@ along with GCC; see the file COPYING3.  If not see
 #undef CPP_CPU64_DEFAULT_SPEC
 #define CPP_CPU64_DEFAULT_SPEC ""
 #undef ASM_CPU32_DEFAULT_SPEC
-#define ASM_CPU32_DEFAULT_SPEC "-xarch=v8plusb"
+#define ASM_CPU32_DEFAULT_SPEC AS_SPARC32_FLAG AS_NIAGARA4_FLAG
 #undef ASM_CPU64_DEFAULT_SPEC
-#define ASM_CPU64_DEFAULT_SPEC AS_SPARC64_FLAG "b"
+#define ASM_CPU64_DEFAULT_SPEC AS_SPARC64_FLAG AS_NIAGARA4_FLAG
 #undef ASM_CPU_DEFAULT_SPEC
 #define ASM_CPU_DEFAULT_SPEC ASM_CPU32_DEFAULT_SPEC
 #endif
@@ -241,7 +243,7 @@ extern const char *host_detect_local_cpu (int argc, const 
char **argv);
 %{mcpu=niagara:" DEF_ARCH32_SPEC("-xarch=v8plusb") 
DEF_ARCH64_SPEC(AS_SPARC64_FLAG "b") "} \
 %{mcpu=niagara2:" DEF_ARCH32_SPEC("-xarch=v8plusb") 
DEF_ARCH64_SPEC(AS_SPARC64_FLAG "b") "} \
 %{mcpu=niagara3:" DEF_ARCH32_SPEC("-xarch=v8plus" AS_NIAGARA3_FLAG) 
DEF_ARCH64_SPEC(AS_SPARC64_FLAG AS_NIAGARA3_FLAG) "} \
-%{mcpu=niagara4:" DEF_ARCH32_SPEC("-xarch=v8plus" AS_NIAGARA3_FLAG) 
DEF_ARCH64_SPEC(AS_SPARC64_FLAG AS_NIAGARA3_FLAG) "} \
+%{mcpu=niagara4:" DEF_ARCH32_SPEC(AS_SPARC32_FLAG AS_NIAGARA4_FLAG) 
DEF_ARCH64_SPEC(AS_SPARC64_FLAG AS_NIAGARA4_FLAG) "} \
 
%{!mcpu=niagara4:%{!mcpu=niagara3:%{!mcpu=niagara2:%{!mcpu=niagara:%{!mcpu=ultrasparc3:%{!mcpu=ultrasparc:%{!mcpu=v9:%{mcpu*:"
 DEF_ARCH32_SPEC("-xarch=v8") DEF_ARCH64_SPEC(AS_SPARC64_FLAG) "}}}}}}}} \
 %{!mcpu*:%(asm_cpu_default)} \
 "
diff --git a/gcc/config/sparc/sparc-c.c b/gcc/config/sparc/sparc-c.c
index c187970..bd3221c 100644
--- a/gcc/config/sparc/sparc-c.c
+++ b/gcc/config/sparc/sparc-c.c
@@ -45,7 +45,12 @@ sparc_target_macros (void)
       cpp_assert (parse_in, "machine=sparc");
     }
 
-  if (TARGET_VIS3)
+  if (TARGET_VIS4)
+    {
+      cpp_define (parse_in, "__VIS__=0x400");
+      cpp_define (parse_in, "__VIS=0x400");
+    }
+  else if (TARGET_VIS3)
     {
       cpp_define (parse_in, "__VIS__=0x300");
       cpp_define (parse_in, "__VIS=0x300");
diff --git a/gcc/config/sparc/sparc-protos.h b/gcc/config/sparc/sparc-protos.h
index 97f6233..20ef7a8 100644
--- a/gcc/config/sparc/sparc-protos.h
+++ b/gcc/config/sparc/sparc-protos.h
@@ -79,6 +79,7 @@ extern const char *output_v8plus_shift (rtx, rtx *, const 
char *);
 extern const char *output_v8plus_mult (rtx, rtx *, const char *);
 extern const char *output_v9branch (rtx, rtx, int, int, int, int, rtx);
 extern const char *output_probe_stack_range (rtx, rtx);
+extern const char *output_cbcond (rtx, rtx, rtx);
 extern bool emit_scc_insn (rtx []);
 extern void emit_conditional_branch_insn (rtx []);
 extern int mems_ok_for_ldd_peep (rtx, rtx, rtx);
diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c
index 8849c03..c892209 100644
--- a/gcc/config/sparc/sparc.c
+++ b/gcc/config/sparc/sparc.c
@@ -840,6 +840,8 @@ dump_target_flag_bits (const int flags)
     fprintf (stderr, "VIS2 ");
   if (flags & MASK_VIS3)
     fprintf (stderr, "VIS3 ");
+  if (flags & MASK_VIS4)
+    fprintf (stderr, "VIS4 ");
   if (flags & MASK_DEPRECATED_V8_INSNS)
     fprintf (stderr, "DEPRECATED_V8_INSNS ");
   if (flags & MASK_SPARCLET)
@@ -946,7 +948,7 @@ sparc_option_override (void)
       MASK_V9|MASK_POPC|MASK_VIS2|MASK_VIS3|MASK_FMAF },
     /* UltraSPARC T4 */
     { "niagara4",      MASK_ISA,
-      MASK_V9|MASK_POPC|MASK_VIS2|MASK_VIS3|MASK_FMAF },
+      MASK_V9|MASK_POPC|MASK_VIS2|MASK_VIS3|MASK_FMAF|MASK_VIS4 },
   };
   const struct cpu_table *cpu;
   unsigned int i;
@@ -1073,6 +1075,9 @@ sparc_option_override (void)
 #ifndef HAVE_AS_FMAF_HPC_VIS3
                   & ~(MASK_FMAF | MASK_VIS3)
 #endif
+#ifndef HAVE_AS_SPARC4
+                  & ~MASK_VIS4
+#endif
                   );
 
   /* If -mfpu or -mno-fpu was explicitly used, don't override with
@@ -1088,9 +1093,14 @@ sparc_option_override (void)
   if (TARGET_VIS3)
     target_flags |= MASK_VIS2 | MASK_VIS;
 
-  /* Don't allow -mvis, -mvis2, -mvis3, or -mfmaf if FPU is disabled.  */
+  /* -mvis4 implies -mvis3, -mvis2 and -mvis */
+  if (TARGET_VIS4)
+    target_flags |= MASK_VIS3 | MASK_VIS2 | MASK_VIS;
+
+  /* Don't allow -mvis, -mvis2, -mvis3, -mvis4, or -mfmaf if FPU is
+     disabled.  */
   if (! TARGET_FPU)
-    target_flags &= ~(MASK_VIS | MASK_VIS2 | MASK_VIS3 | MASK_FMAF);
+    target_flags &= ~(MASK_VIS | MASK_VIS2 | MASK_VIS3 | MASK_VIS4 | 
MASK_FMAF);
 
   /* -mvis assumes UltraSPARC+, so we are sure v9 instructions
      are available.
@@ -2660,6 +2670,24 @@ emit_v9_brxx_insn (enum rtx_code code, rtx op0, rtx 
label)
                                    pc_rtx)));
 }
 
+/* Emit a conditional jump insn for the UA2011 architecture using
+   comparison code CODE and jump target LABEL.  This function exists
+   to take advantage of the UA2011 Compare and Branch insns.  */
+
+static void
+emit_cbcond_insn (enum rtx_code code, rtx op0, rtx op1, rtx label)
+{
+  rtx if_then_else;
+
+  if_then_else = gen_rtx_IF_THEN_ELSE (VOIDmode,
+                                      gen_rtx_fmt_ee(code, GET_MODE(op0),
+                                                     op0, op1),
+                                      gen_rtx_LABEL_REF (VOIDmode, label),
+                                      pc_rtx);
+
+  emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, if_then_else));
+}
+
 void
 emit_conditional_branch_insn (rtx operands[])
 {
@@ -2674,6 +2702,15 @@ emit_conditional_branch_insn (rtx operands[])
       operands[2] = XEXP (operands[0], 1);
     }
 
+  if (TARGET_VIS4
+      && GET_CODE (operands[1]) == REG
+      && (GET_MODE (operands[1]) == SImode
+         || (TARGET_ARCH64 && GET_MODE (operands[1]) == DImode)))
+    {
+      emit_cbcond_insn (GET_CODE (operands[0]), operands[1], operands[2], 
operands[3]);
+      return;
+    }
+
   if (TARGET_ARCH64 && operands[2] == const0_rtx
       && GET_CODE (operands[1]) == REG
       && GET_MODE (operands[1]) == DImode)
@@ -7604,6 +7641,180 @@ sparc_emit_fixunsdi (rtx *operands, enum machine_mode 
mode)
   emit_label (donelab);
 }
 
+/* Return the string to output a compare and branch instruction to DEST.
+   DEST is the destination insn (i.e. the label), INSN is the source,
+   and OP is the conditional expression.  */
+
+const char *
+output_cbcond (rtx op, rtx dest, rtx insn)
+{
+  enum machine_mode mode = GET_MODE (XEXP (op, 0));
+  enum rtx_code code = GET_CODE (op);
+  static char string[64];
+  char *p;
+  int far;
+
+  /* Compare and Branch is limited to +-2KB.  If it is too far away,
+     change
+
+     cxbne X, Y, .LC30
+
+     to
+
+     cxbe X, Y, .+12
+     ba,pt xcc, .LC30
+      nop  */
+
+  far = get_attr_length (insn) == 3;
+
+  if (far)
+    code = reverse_condition (code);
+
+  p = string;
+
+  *p++ = 'c';
+  *p++ = mode == SImode ? 'w' : 'x';
+  *p++ = 'b';
+
+  switch (code)
+    {
+    case NE:
+      *p++ = 'n';
+      *p++ = 'e';
+      break;
+
+    case EQ:
+      *p++ = 'e';
+      break;
+
+    case GE:
+      if (mode == CC_NOOVmode || mode == CCX_NOOVmode)
+       {
+         *p++ = 'p';
+         *p++ = 'o';
+         *p++ = 's';
+       }
+      else
+       {
+         *p++ = 'g';
+         *p++ = 'e';
+       }
+      break;
+
+    case GT:
+      *p++ = 'g';
+      break;
+
+    case LE:
+      *p++ = 'l';
+      *p++ = 'e';
+      break;
+
+    case LT:
+      if (mode == CC_NOOVmode || mode == CCX_NOOVmode)
+       {
+         *p++ = 'n';
+         *p++ = 'e';
+         *p++ = 'g';
+       }
+      else
+       *p++ = 'l';
+      break;
+
+    case GEU:
+      *p++ = 'c';
+      *p++ = 'c';
+      break;
+
+    case GTU:
+      *p++ = 'g';
+      *p++ = 'u';
+      break;
+
+    case LEU:
+      *p++ = 'l';
+      *p++ = 'e';
+      *p++ = 'u';
+      break;
+
+    case LTU:
+      *p++ = 'c';
+      *p++ = 's';
+      break;
+
+    default:
+      gcc_unreachable ();
+    }
+
+  *p++ = '\t';
+  *p++ = '%';
+  *p++ = '1';
+  *p++ = ',';
+  *p++ = ' ';
+  *p++ = '%';
+  *p++ = '2';
+  *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;
+       }
+      *p++ = '.';
+      *p++ = '+';
+      *p++ = '1';
+      *p++ = '2';
+      *p++ = '\n';
+      *p++ = '\t';
+      if (veryfar)
+       {
+         *p++ = 'b';
+         *p++ = '\t';
+       }
+      else
+       {
+         *p++ = 'b';
+         *p++ = 'a';
+         *p++ = ',';
+         *p++ = 'p';
+         *p++ = 't';
+         *p++ = '\t';
+         *p++ = '%';
+         *p++ = '%';
+         *p++ = 'x';
+         *p++ = 'c';
+         *p++ = 'c';
+         *p++ = ',';
+         *p++ = ' ';
+       }
+    }
+
+  *p++ = '%';
+  *p++ = 'l';
+  *p++ = '3';
+
+  if (far)
+    {
+      *p++ = '\n';
+      *p++ = '\t';
+      *p++ = 'n';
+      *p++ = 'o';
+      *p++ = 'p';
+    }
+
+  *p = '\0';
+
+  return string;
+}
+
 /* Return the string to output a conditional branch to LABEL, testing
    register REG.  LABEL is the operand number of the label; REG is the
    operand number of the reg.  OP is the conditional expression.  The mode
diff --git a/gcc/config/sparc/sparc.h b/gcc/config/sparc/sparc.h
index 8f86100..374919f 100644
--- a/gcc/config/sparc/sparc.h
+++ b/gcc/config/sparc/sparc.h
@@ -195,7 +195,7 @@ extern enum cmodel sparc_cmodel;
 #endif
 #if TARGET_CPU_DEFAULT == TARGET_CPU_niagara4
 #define CPP_CPU64_DEFAULT_SPEC "-D__sparc_v9__"
-#define ASM_CPU64_DEFAULT_SPEC "-Av9" AS_NIAGARA3_FLAG
+#define ASM_CPU64_DEFAULT_SPEC AS_NIAGARA4_FLAG
 #endif
 
 #else
@@ -337,7 +337,7 @@ extern enum cmodel sparc_cmodel;
 %{mcpu=niagara:%{!mv8plus:-Av9b}} \
 %{mcpu=niagara2:%{!mv8plus:-Av9b}} \
 %{mcpu=niagara3:%{!mv8plus:-Av9" AS_NIAGARA3_FLAG "}} \
-%{mcpu=niagara4:%{!mv8plus:-Av9" AS_NIAGARA3_FLAG "}} \
+%{mcpu=niagara4:%{!mv8plus:" AS_NIAGARA4_FLAG "}} \
 %{!mcpu*:%(asm_cpu_default)} \
 "
 
@@ -1006,7 +1006,8 @@ extern char leaf_reg_remap[];
 /* Local macro to handle the two v9 classes of FP regs.  */
 #define FP_REG_CLASS_P(CLASS) ((CLASS) == FP_REGS || (CLASS) == EXTRA_FP_REGS)
 
-/* Predicates for 10-bit, 11-bit and 13-bit signed constants.  */
+/* Predicates for 5-bit, 10-bit, 11-bit and 13-bit signed constants.  */
+#define SPARC_SIMM5_P(X)  ((unsigned HOST_WIDE_INT) (X) + 0x10 < 0x20)
 #define SPARC_SIMM10_P(X) ((unsigned HOST_WIDE_INT) (X) + 0x200 < 0x400)
 #define SPARC_SIMM11_P(X) ((unsigned HOST_WIDE_INT) (X) + 0x400 < 0x800)
 #define SPARC_SIMM13_P(X) ((unsigned HOST_WIDE_INT) (X) + 0x1000 < 0x2000)
@@ -1746,6 +1747,12 @@ extern int sparc_indent_opcode;
 #define AS_NIAGARA3_FLAG "d"
 #endif
 
+#ifndef HAVE_AS_SPARC4
+#define AS_NIAGARA4_FLAG " -xarch=v9b"
+#else
+#define AS_NIAGARA4_FLAG " -xarch=sparc4"
+#endif
+
 /* We use gcc _mcount for profiling.  */
 #define NO_PROFILE_COUNTERS 0
 
diff --git a/gcc/config/sparc/sparc.md b/gcc/config/sparc/sparc.md
index f604f46..8fa2ce7 100644
--- a/gcc/config/sparc/sparc.md
+++ b/gcc/config/sparc/sparc.md
@@ -257,6 +257,7 @@
   "ialu,compare,shift,
    load,sload,store,
    uncond_branch,branch,call,sibcall,call_no_delay_slot,return,
+   cbcond,
    imul,idiv,
    fpload,fpstore,
    fp,fpmove,
@@ -377,6 +378,14 @@
               (if_then_else (eq_attr "empty_delay_slot" "true")
                 (const_int 4)
                 (const_int 3))))
+         (eq_attr "type" "cbcond")
+          (if_then_else (lt (pc) (match_dup 3))
+            (if_then_else (lt (minus (match_dup 3) (pc)) (const_int 500))
+               (const_int 1)
+               (const_int 3))
+            (if_then_else (lt (minus (pc) (match_dup 3)) (const_int 500))
+               (const_int 1)
+               (const_int 3)))
         ] (const_int 1)))
 
 ;; FP precision.
@@ -1313,6 +1322,32 @@
 ;; SPARC V9-specific jump insns.  None of these are guaranteed to be
 ;; in the architecture.
 
+(define_insn "*cbcond_sp32"
+  [(set (pc)
+        (if_then_else (match_operator 0 "noov_compare_operator"
+                       [(match_operand:SI 1 "register_operand" "r")
+                        (match_operand:SI 2 "arith_operand" "rA")])
+                      (label_ref (match_operand 3 "" ""))
+                      (pc)))]
+  "TARGET_VIS4"
+{
+  return output_cbcond (operands[0], operands[3], insn);
+}
+  [(set_attr "type" "cbcond")])
+
+(define_insn "*cbcond_sp64"
+  [(set (pc)
+        (if_then_else (match_operator 0 "noov_compare_operator"
+                       [(match_operand:DI 1 "register_operand" "r")
+                        (match_operand:DI 2 "arith_operand" "rA")])
+                      (label_ref (match_operand 3 "" ""))
+                      (pc)))]
+  "TARGET_ARCH64 && TARGET_VIS4"
+{
+  return output_cbcond (operands[0], operands[3], insn);
+}
+  [(set_attr "type" "cbcond")])
+
 ;; There are no 32 bit brreg insns.
 
 ;; XXX
diff --git a/gcc/config/sparc/sparc.opt b/gcc/config/sparc/sparc.opt
index 58ba6b7..f46543b 100644
--- a/gcc/config/sparc/sparc.opt
+++ b/gcc/config/sparc/sparc.opt
@@ -73,6 +73,10 @@ mvis3
 Target Report Mask(VIS3)
 Use UltraSPARC Visual Instruction Set version 3.0 extensions
 
+mvis4
+Target Report Mask(VIS4)
+Use UltraSPARC Visual Instruction Set version 4.0 extensions
+
 mfmaf
 Target Report Mask(FMAF)
 Use UltraSPARC Fused Multiply-Add extensions
diff --git a/gcc/configure b/gcc/configure
index 387de5b..32929f0 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -24090,6 +24090,48 @@ if test $gcc_cv_as_sparc_fmaf = yes; then
 $as_echo "#define HAVE_AS_FMAF_HPC_VIS3 1" >>confdefs.h
 
 fi
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for SPARC4 
instructions" >&5
+$as_echo_n "checking assembler for SPARC4 instructions... " >&6; }
+if test "${gcc_cv_as_sparc_fmaf+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  gcc_cv_as_sparc_fmaf=no
+  if test x$gcc_cv_as != x; then
+    $as_echo '.text
+       .register %g2, #scratch
+       .register %g3, #scratch
+       .align 4
+       cxbe %g2, %g3, 1f
+1:     cwbneg %g2, %g3, 1f
+1:     sha1
+       md5
+       aes_kexpand0 %f4, %f6, %f8
+       des_round %f38, %f40, %f42, %f44
+       camellia_f %f54, %f56, %f58, %f60
+       kasumi_fi_xor %f46, %f48, %f50, %f52' > conftest.s
+    if { ac_try='$gcc_cv_as $gcc_cv_as_flags -xarch=sparc4 -o conftest.o 
conftest.s >&5'
+  { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }
+    then
+       gcc_cv_as_sparc_fmaf=yes
+    else
+      echo "configure: failed program was" >&5
+      cat conftest.s >&5
+    fi
+    rm -f conftest.o conftest.s
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_as_sparc_fmaf" >&5
+$as_echo "$gcc_cv_as_sparc_fmaf" >&6; }
+if test $gcc_cv_as_sparc_fmaf = yes; then
+
+$as_echo "#define HAVE_AS_SPARC4 1" >>confdefs.h
+
+fi
     ;;
 
   i[34567]86-*-* | x86_64-*-*)
diff --git a/gcc/configure.ac b/gcc/configure.ac
index b6c049b..9d2eb29 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -3501,6 +3501,24 @@ foo:
        fnaddd %f10, %f12, %f14],,
       [AC_DEFINE(HAVE_AS_FMAF_HPC_VIS3, 1,
                 [Define if your assembler supports FMAF, HPC, and VIS 3.0 
instructions.])])
+
+    gcc_GAS_CHECK_FEATURE([SPARC4 instructions],
+      gcc_cv_as_sparc_fmaf,,
+      [-xarch=sparc4],
+      [.text
+       .register %g2, #scratch
+       .register %g3, #scratch
+       .align 4
+       cxbe %g2, %g3, 1f
+1:     cwbneg %g2, %g3, 1f
+1:     sha1
+       md5
+       aes_kexpand0 %f4, %f6, %f8
+       des_round %f38, %f40, %f42, %f44
+       camellia_f %f54, %f56, %f58, %f60
+       kasumi_fi_xor %f46, %f48, %f50, %f52],,
+      [AC_DEFINE(HAVE_AS_SPARC4, 1,
+                [Define if your assembler supports SPARC4 instructions.])])
     ;;
 
 changequote(,)dnl
diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi
index f17d55e..61f8202 100644
--- a/gcc/doc/md.texi
+++ b/gcc/doc/md.texi
@@ -3141,6 +3141,9 @@ when the Visual Instruction Set is available.
 @item h
 64-bit global or out register for the SPARC-V8+ architecture.
 
+@item A
+Signed 5-bit constant
+
 @item D
 A vector constant
 

Reply via email to