Patchwork [RFC] Add support for sparc compare-and-branch.

login
register
mail settings
Submitter David Miller
Date Oct. 13, 2012, 3:49 a.m.
Message ID <20121012.234956.61271773376558370.davem@davemloft.net>
Download mbox | patch
Permalink /patch/191274/
State New
Headers show

Comments

David Miller - Oct. 13, 2012, 3:49 a.m.
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  <davem@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.
Eric Botcazou - Oct. 13, 2012, 1:47 p.m.
> 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.

The only versions of the Solaris assembler I have access to only support 
v8plusX according to the man page.  Has that changed recently?

> 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.

sparc4 sounds very 1990-ish...

> 	* config/sparc/sparc.opt (mvis4): New option.
> 	* config/sparc/sparc-c.c (sparc_target_macros): When TARGET_VIS4,
> 	define __VIS__ to 0x400.

What's the relationship between VIS4 and SPARC-T4 exactly?  The above manual 
only speaks of VIS3 as far as I can see.  And the CBcond instructions are not 
marked as belonging to VIS (3 or 4), so using -mvis4 for them seems strange.
Why not make them depend on -mcpu=niagara4 instead?
David Miller - Oct. 13, 2012, 9:52 p.m.
From: Eric Botcazou <ebotcazou@adacore.com>
Date: Sat, 13 Oct 2012 15:47:11 +0200

>> 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.
> 
> The only versions of the Solaris assembler I have access to only support 
> v8plusX according to the man page.  Has that changed recently?

For the older stuff I mean doing something like "-m32 -xarch=v9X"

> 
>> 	* config/sparc/sparc.opt (mvis4): New option.
>> 	* config/sparc/sparc-c.c (sparc_target_macros): When TARGET_VIS4,
>> 	define __VIS__ to 0x400.
> 
> What's the relationship between VIS4 and SPARC-T4 exactly?  The above manual 
> only speaks of VIS3 as far as I can see.  And the CBcond instructions are not 
> marked as belonging to VIS (3 or 4), so using -mvis4 for them seems strange.
> Why not make them depend on -mcpu=niagara4 instead?

The current assembler in Solaris Studio (called 'fbe') calls this
stuff "sparc4" which I guess means "SPARC-T4 and later".

I'm just calling it VIS4 in GCC so that we can export intrinsics of,
for example, the cryptographic instructions at some point using the
__VIS__ version CPP tests.
David Miller - Oct. 13, 2012, 10:29 p.m.
From: David Miller <davem@davemloft.net>
Date: Sat, 13 Oct 2012 17:52:42 -0400 (EDT)

> The current assembler in Solaris Studio (called 'fbe') calls this
> stuff "sparc4" which I guess means "SPARC-T4 and later".

BTW, for reference, see:

http://docs.oracle.com/cd/E24457_01/html/E22003/fbe.1.html
Eric Botcazou - Oct. 15, 2012, 8 a.m.
> > The only versions of the Solaris assembler I have access to only support
> > v8plusX according to the man page.  Has that changed recently?
> 
> For the older stuff I mean doing something like "-m32 -xarch=v9X"

OK, this is for fbe, not for as.  I think that the latter is always available 
on the machines, but I'm not sure for the former.  Rainer very likely knows.

> The current assembler in Solaris Studio (called 'fbe') calls this
> stuff "sparc4" which I guess means "SPARC-T4 and later".

Ah, thanks.  I agree that using the same monikers is the right thing to do...

> I'm just calling it VIS4 in GCC so that we can export intrinsics of,
> for example, the cryptographic instructions at some point using the
> __VIS__ version CPP tests.

...that's why I'm not sure we should invent VIS4 at this point.  How is this 
done on the Solaris Studio side?  Couldn't we add a new architecture to the 
compiler (-mcpu=sparc4, with -mcpu=niagara4 as first variant), and define 
__sparc4__ for the preprocessor?
Rainer Orth - Oct. 15, 2012, 2:25 p.m.
Eric Botcazou <ebotcazou@adacore.com> writes:

>> > The only versions of the Solaris assembler I have access to only support
>> > v8plusX according to the man page.  Has that changed recently?
>> 
>> For the older stuff I mean doing something like "-m32 -xarch=v9X"
>
> OK, this is for fbe, not for as.  I think that the latter is always available 
> on the machines, but I'm not sure for the former.  Rainer very likely knows.

The assembler lives with the Studio compilers as fbe, but once in a
while that version is backported (or provided as a patch) as
/usr/ccs/bin/as.

For Solaris 10, the latest SPARC assembler patch, 118683-08, includes
-xarch=sparc4 support, rev. -07 didn't.

At least in Solaris 11.1, as does as well, not completely sure about
Solaris 11 where it may have only been introduced in an SRU (support
repository update).

	Rainer
Rainer Orth - Oct. 15, 2012, 2:28 p.m.
David Miller <davem@davemloft.net> writes:

> 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.

I assume this works because gas 2.22 had neither SPARC-T4 support nor
did it accept -xarch=sparc4?

> 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,,

Shouldn't reuse a cache variable here, but use
e.g. gcc_cv_as_sparc_sparc4 instead.

> +      [-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

	Rainer
David Miller - Oct. 15, 2012, 2:37 p.m.
From: Eric Botcazou <ebotcazou@adacore.com>
Date: Mon, 15 Oct 2012 10:00:02 +0200

>> > The only versions of the Solaris assembler I have access to only support
>> > v8plusX according to the man page.  Has that changed recently?
>> 
>> For the older stuff I mean doing something like "-m32 -xarch=v9X"
> 
> OK, this is for fbe, not for as.  I think that the latter is always available 
> on the machines, but I'm not sure for the former.  Rainer very likely knows.
> 
>> The current assembler in Solaris Studio (called 'fbe') calls this
>> stuff "sparc4" which I guess means "SPARC-T4 and later".
> 
> Ah, thanks.  I agree that using the same monikers is the right thing to do...
> 
>> I'm just calling it VIS4 in GCC so that we can export intrinsics of,
>> for example, the cryptographic instructions at some point using the
>> __VIS__ version CPP tests.
> 
> ...that's why I'm not sure we should invent VIS4 at this point.  How is this 
> done on the Solaris Studio side?  Couldn't we add a new architecture to the 
> compiler (-mcpu=sparc4, with -mcpu=niagara4 as first variant), and define 
> __sparc4__ for the preprocessor?

I've scanned the documentation and there is no indication of any preprocessor
predefines or anything like that.

And keep in mind that __VIS__ is our very own invention.

Sun's compilers never predefined this.

Their makefiles do for various targets in the MediaLib sources, but that's
a source tree and header file localized convention.

Sun also never provided intrinsics other than via assembler inlines in
their VIS header.  They were never compiler builtins like our's.  The
user had to define __VIS__ on the command line to get visibility of
the routines they wanted from Sun's VIS inline assembler header file.

Sun also does not provide, and is almost certainly not going to ever
provide crypto intrinsics.

Therefore there is no convention to follow and we can do whatever we want
here.
Rainer Orth - Oct. 15, 2012, 2:44 p.m.
David Miller <davem@davemloft.net> writes:

>>> I'm just calling it VIS4 in GCC so that we can export intrinsics of,
>>> for example, the cryptographic instructions at some point using the
>>> __VIS__ version CPP tests.
>> 
>> ...that's why I'm not sure we should invent VIS4 at this point.  How is this 
>> done on the Solaris Studio side?  Couldn't we add a new architecture to the 
>> compiler (-mcpu=sparc4, with -mcpu=niagara4 as first variant), and define 
>> __sparc4__ for the preprocessor?
>
> I've scanned the documentation and there is no indication of any preprocessor
> predefines or anything like that.
>
> And keep in mind that __VIS__ is our very own invention.
>
> Sun's compilers never predefined this.

I've found uses of e.g. __VIS >= 0x200 in their Studio 12.3 headers
(prod/include/cc/sys/vis_*.h), and strings on the cc binary reveals

-D__VIS=0x100
-D__VIS=0x200
-D__VIS=0x300
-D__VIS=0x400

I haven't yet found if those are properly documented, though.

	Rainer
David Miller - Oct. 15, 2012, 2:45 p.m.
From: Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
Date: Mon, 15 Oct 2012 16:28:15 +0200

> David Miller <davem@davemloft.net> writes:
> 
>> 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.
> 
> I assume this works because gas 2.22 had neither SPARC-T4 support nor
> did it accept -xarch=sparc4?

I have a mainline binutils build installed on my system which does
have support for all of these instructions, otherwise how would I have
been able to run the testsuite and see the cbcond instructions
working? :-)

>> 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,,
> 
> Shouldn't reuse a cache variable here, but use
> e.g. gcc_cv_as_sparc_sparc4 instead.

Thanks for catching that.
David Miller - Oct. 15, 2012, 2:48 p.m.
From: Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
Date: Mon, 15 Oct 2012 16:44:44 +0200

> David Miller <davem@davemloft.net> writes:
> 
>>>> I'm just calling it VIS4 in GCC so that we can export intrinsics of,
>>>> for example, the cryptographic instructions at some point using the
>>>> __VIS__ version CPP tests.
>>> 
>>> ...that's why I'm not sure we should invent VIS4 at this point.  How is this 
>>> done on the Solaris Studio side?  Couldn't we add a new architecture to the 
>>> compiler (-mcpu=sparc4, with -mcpu=niagara4 as first variant), and define 
>>> __sparc4__ for the preprocessor?
>>
>> I've scanned the documentation and there is no indication of any preprocessor
>> predefines or anything like that.
>>
>> And keep in mind that __VIS__ is our very own invention.
>>
>> Sun's compilers never predefined this.
> 
> I've found uses of e.g. __VIS >= 0x200 in their Studio 12.3 headers
> (prod/include/cc/sys/vis_*.h), and strings on the cc binary reveals
> 
> -D__VIS=0x100
> -D__VIS=0x200
> -D__VIS=0x300
> -D__VIS=0x400
> 
> I haven't yet found if those are properly documented, though.

Strange, ok.
Eric Botcazou - Oct. 16, 2012, 10:10 a.m.
> I've scanned the documentation and there is no indication of any
> preprocessor predefines or anything like that.
> 
> And keep in mind that __VIS__ is our very own invention.
> 
> Sun's compilers never predefined this.
> 
> Their makefiles do for various targets in the MediaLib sources, but that's
> a source tree and header file localized convention.
> 
> Sun also never provided intrinsics other than via assembler inlines in
> their VIS header.  They were never compiler builtins like our's.  The
> user had to define __VIS__ on the command line to get visibility of
> the routines they wanted from Sun's VIS inline assembler header file.
> 
> Sun also does not provide, and is almost certainly not going to ever
> provide crypto intrinsics.
> 
> Therefore there is no convention to follow and we can do whatever we want
> here.

OK, thanks.  I keep thinking that we should use -mcpu=sparc4/-D__sparc4__ for 
new instructions in the SPARC-T4 architecture that aren't related to VIS.

And given Rainer's insight, I agree that switching to the -m{32,64} -xarch= 
scheme with recent assemblers is the way to go.  I'll try and get my hands on 
one of them...
David Miller - Oct. 16, 2012, 4:27 p.m.
From: Eric Botcazou <ebotcazou@adacore.com>
Date: Tue, 16 Oct 2012 12:10:51 +0200

>> I've scanned the documentation and there is no indication of any
>> preprocessor predefines or anything like that.
>> 
>> And keep in mind that __VIS__ is our very own invention.
>> 
>> Sun's compilers never predefined this.
>> 
>> Their makefiles do for various targets in the MediaLib sources, but that's
>> a source tree and header file localized convention.
>> 
>> Sun also never provided intrinsics other than via assembler inlines in
>> their VIS header.  They were never compiler builtins like our's.  The
>> user had to define __VIS__ on the command line to get visibility of
>> the routines they wanted from Sun's VIS inline assembler header file.
>> 
>> Sun also does not provide, and is almost certainly not going to ever
>> provide crypto intrinsics.
>> 
>> Therefore there is no convention to follow and we can do whatever we want
>> here.
> 
> OK, thanks.  I keep thinking that we should use -mcpu=sparc4/-D__sparc4__ for 
> new instructions in the SPARC-T4 architecture that aren't related to VIS.
> 
> And given Rainer's insight, I agree that switching to the -m{32,64} -xarch= 
> scheme with recent assemblers is the way to go.  I'll try and get my hands on 
> one of them...

Ok.

Meanwhile I asked some folks and there doesn't appear to be any special
CPP symbols set by the Solaris compiler when -xarch=sparc4.

So what I'm going to do is get rid of the __VIS__==0x400 thing for now
and we can add that, or something similar, at a later date.

Patch

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