@@ -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
@@ -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")
@@ -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
@@ -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)} \
"
@@ -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);
@@ -840,6 +840,8 @@ dump_target_flag_bits (const int flags)
fprintf (stderr, "VIS2 ");
if (flags & MASK_VIS3)
fprintf (stderr, "VIS3 ");
+ if (flags & MASK_CBCOND)
+ fprintf (stderr, "CBCOND ");
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_CBCOND },
};
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_CBCOND
+#endif
);
/* If -mfpu or -mno-fpu was explicitly used, don't override with
@@ -1088,7 +1093,12 @@ 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. */
+ /* -mcbcond implies -mvis3, -mvis2 and -mvis */
+ if (TARGET_CBCOND)
+ target_flags |= MASK_VIS3 | MASK_VIS2 | MASK_VIS;
+
+ /* Don't allow -mvis, -mvis2, -mvis3, or -mfmaf if FPU is
+ disabled. */
if (! TARGET_FPU)
target_flags &= ~(MASK_VIS | MASK_VIS2 | MASK_VIS3 | MASK_FMAF);
@@ -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_CBCOND
+ && 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
@@ -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
@@ -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_CBCOND"
+{
+ 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_CBCOND"
+{
+ return output_cbcond (operands[0], operands[3], insn);
+}
+ [(set_attr "type" "cbcond")])
+
;; There are no 32 bit brreg insns.
;; XXX
@@ -73,6 +73,10 @@ mvis3
Target Report Mask(VIS3)
Use UltraSPARC Visual Instruction Set version 3.0 extensions
+mcbcond
+Target Report Mask(CBCOND)
+Use UltraSPARC Compare-and-Branch extensions
+
mfmaf
Target Report Mask(FMAF)
Use UltraSPARC Fused Multiply-Add extensions
@@ -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_sparc4+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ gcc_cv_as_sparc_sparc4=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_sparc4=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_sparc4" >&5
+$as_echo "$gcc_cv_as_sparc_sparc4" >&6; }
+if test $gcc_cv_as_sparc_sparc4 = yes; then
+
+$as_echo "#define HAVE_AS_SPARC4 1" >>confdefs.h
+
+fi
;;
i[34567]86-*-* | x86_64-*-*)
@@ -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_sparc4,,
+ [-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
@@ -918,6 +918,7 @@ See RS/6000 and PowerPC Options.
-munaligned-doubles -mno-unaligned-doubles @gol
-mv8plus -mno-v8plus -mvis -mno-vis @gol
-mvis2 -mno-vis2 -mvis3 -mno-vis3 @gol
+-mcbcond -mno-cbcond @gol
-mfmaf -mno-fmaf -mpopc -mno-popc @gol
-mfix-at697f}
@@ -18876,6 +18877,16 @@ default is @option{-mvis3} when targeting a cpu that supports such
instructions, such as niagara-3 and later. Setting @option{-mvis3}
also sets @option{-mvis2} and @option{-mvis}.
+@item -mcbcond
+@itemx -mno-cbcond
+@opindex mcbcond
+@opindex mno-cbcond
+With @option{-mcbcond}, GCC generates code that takes advantage of
+compare-and-branch instructions, as defined in the Sparc Architecture 2011.
+The default is @option{-mcbcond} when targeting a cpu that supports such
+instructions, such as niagara-4 and later. Setting @option{-mcbcond} also
+sets @option{-mvis3}, @option{-mvis2}, and @option{-mvis}.
+
@item -mpopc
@itemx -mno-popc
@opindex mpopc
@@ -3157,6 +3157,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