+2003-07-07 David Edelsohn <edelsohn@gnu.org>
+ Fariborz Jahanian <fjahanian@apple.com>
+
+ * configure.in: Test for PowerPC mfcr field support in assembler.
+ * config.in, configure: Regenderated.
+
+ * config/rs6000/power4.md: Add mfcrf reservation.
+ * config/rs6000/rs6000-protos.h (mfcr_operation): Declare.
+ * config/rs6000/rs6000.c (mfcr_operation): Define.
+ (print_operand): Add 'Q' case for mfcrf.
+ * config/rs6000/rs6000.h (TARGET_MFCRF): New.
+ * config/rs6000/rs6000.md (attribute "type"): Add mfcrf.
+ (movcc_internal1): Emit optional field operand for mfcr and set
+ "type" attribute appropriately.
+ (mfcr SCC): Likewise.
+ (movesi_from_cr_one): New.
+
2003-07-07 Roger Sayle <roger@eyesopen.com>
* config/i386/i386.md: Correct check-in of incorrect version.
/* Define if your assembler supports ltoffx and ldxmov relocations. */
#undef HAVE_AS_LTOFFX_LDXMOV_RELOCS
+/* Define if your assembler supports mfcr field. */
+#undef HAVE_AS_MFCRF
+
/* Define if your assembler supports dwarf2 .file/.loc directives,
and preserves file table indices exactly as given. */
#undef HAVE_AS_DWARF2_DEBUG_LINE
|(du2_power4+du3_power4,iu2_power4,iu2_power4)\
|(du3_power4+du4_power4,nothing,iu2_power4,iu1_power4)")
-(define_bypass 4 "power4-compare" "power4-branch,power4-crlogical,power4-delayedcr,power4-mfcr")
+(define_bypass 4 "power4-compare" "power4-branch,power4-crlogical,power4-delayedcr,power4-mfcr,power4-mfcrf")
(define_insn_reservation "power4-lmul-cmp" 7
(and (eq_attr "type" "lmul_compare")
|(du3_power4+du4_power4,iu2_power4*6,iu1_power4)")
; |(du3_power4+du4_power4,nothing,iu2_power4*6,iu1_power4)")
-(define_bypass 10 "power4-lmul-cmp" "power4-branch,power4-crlogical,power4-delayedcr,power4-mfcr")
+(define_bypass 10 "power4-lmul-cmp" "power4-branch,power4-crlogical,power4-delayedcr,power4-mfcr,power4-mfcrf")
(define_insn_reservation "power4-imul-cmp" 5
(and (eq_attr "type" "imul_compare")
|(du3_power4+du4_power4,iu2_power4*4,iu1_power4)")
; |(du3_power4+du4_power4,nothing,iu2_power4*4,iu1_power4)")
-(define_bypass 8 "power4-imul-cmp" "power4-branch,power4-crlogical,power4-delayedcr,power4-mfcr")
+(define_bypass 8 "power4-imul-cmp" "power4-branch,power4-crlogical,power4-delayedcr,power4-mfcr,power4-mfcrf")
(define_insn_reservation "power4-lmul" 7
(and (eq_attr "type" "lmul")
du1_power4+du2_power4+du3_power4+du4_power4+cru_power4,\
cru_power4,cru_power4,cru_power4")
+; mfcrf (1 field)
+(define_insn_reservation "power4-mfcrf" 3
+ (and (eq_attr "type" "mfcrf")
+ (eq_attr "cpu" "power4"))
+ "du1_power4,cru_power4")
+
; mtcrf (1 field)
(define_insn_reservation "power4-mtcr" 4
(and (eq_attr "type" "mtcr")
(define_bypass 9 "power4-vecfloat" "power4-vecperm")
(define_bypass 5 "power4-vecsimple,power4-veccomplex"
- "power4-branch,power4-crlogical,power4-delayedcr,power4-mfcr")
+ "power4-branch,power4-crlogical,power4-delayedcr,power4-mfcr,power4-mfcrf")
(define_bypass 4 "power4-vecsimple,power4-vecperm" "power4-vecstore")
(define_bypass 7 "power4-veccomplex" "power4-vecstore")
extern struct rtx_def *rs6000_longcall_ref PARAMS ((rtx));
extern void rs6000_fatal_bad_address PARAMS ((rtx));
extern int stmw_operation PARAMS ((rtx, enum machine_mode));
+extern int mfcr_operation PARAMS ((rtx, enum machine_mode));
extern int mtcrf_operation PARAMS ((rtx, enum machine_mode));
extern int lmw_operation PARAMS ((rtx, enum machine_mode));
extern struct rtx_def *create_TOC_reference PARAMS ((rtx));
return 1;
}
+/* Return 1 for an PARALLEL suitable for mfcr. */
+
+int
+mfcr_operation (op, mode)
+ rtx op;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
+{
+ int count = XVECLEN (op, 0);
+ int i;
+
+ /* Perform a quick check so we don't blow up below. */
+ if (count < 1
+ || GET_CODE (XVECEXP (op, 0, 0)) != SET
+ || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != UNSPEC
+ || XVECLEN (SET_SRC (XVECEXP (op, 0, 0)), 0) != 2)
+ return 0;
+
+ for (i = 0; i < count; i++)
+ {
+ rtx exp = XVECEXP (op, 0, i);
+ rtx unspec;
+ int maskval;
+ rtx src_reg;
+
+ src_reg = XVECEXP (SET_SRC (exp), 0, 0);
+
+ if (GET_CODE (src_reg) != REG
+ || GET_MODE (src_reg) != CCmode
+ || ! CR_REGNO_P (REGNO (src_reg)))
+ return 0;
+
+ if (GET_CODE (exp) != SET
+ || GET_CODE (SET_DEST (exp)) != REG
+ || GET_MODE (SET_DEST (exp)) != SImode
+ || ! INT_REGNO_P (REGNO (SET_DEST (exp))))
+ return 0;
+ unspec = SET_SRC (exp);
+ maskval = 1 << (MAX_CR_REGNO - REGNO (src_reg));
+
+ if (GET_CODE (unspec) != UNSPEC
+ || XINT (unspec, 1) != UNSPEC_MOVESI_FROM_CR
+ || XVECLEN (unspec, 0) != 2
+ || XVECEXP (unspec, 0, 0) != src_reg
+ || GET_CODE (XVECEXP (unspec, 0, 1)) != CONST_INT
+ || INTVAL (XVECEXP (unspec, 0, 1)) != maskval)
+ return 0;
+ }
+ return 1;
+}
+
/* Return 1 for an PARALLEL suitable for mtcrf. */
int
}
return;
+ case 'Q':
+ if (TARGET_MFCRF)
+ fputc (',',file);
+ /* FALLTHRU */
+ else
+ return;
+
case 'R':
/* X is a CR register. Print the mask for `mtcrf'. */
if (GET_CODE (x) != REG || ! CR_REGNO_P (REGNO (x)))
{
enum attr_type type = get_attr_type (insn);
if (type == TYPE_LOAD_EXT_U || type == TYPE_LOAD_EXT_UX
- || type == TYPE_LOAD_UX || type == TYPE_STORE_UX)
+ || type == TYPE_LOAD_UX || type == TYPE_STORE_UX
+ || type == TYPE_MFCR)
return 0;
else if (type == TYPE_LOAD_U || type == TYPE_STORE_U
|| type == TYPE_FPLOAD_U || type == TYPE_FPSTORE_U
#define TARGET_ALIGN_NATURAL 0
#endif
+/* Define TARGET_MFCRF if the target assembler supports the optional
+ field operand for mfcr and the target processor supports the
+ instruction. */
+
+#ifdef HAVE_AS_MFCRF
+#define TARGET_MFCRF (rs6000_cpu == PROCESSOR_POWER4)
+#else
+#define TARGET_MFCRF 0
+#endif
+
#define TARGET_LONG_DOUBLE_128 (rs6000_long_double_type_size == 128)
#define TARGET_ALTIVEC_ABI rs6000_altivec_abi
#define TARGET_ALTIVEC_VRSAVE rs6000_altivec_vrsave
\f
;; Define an insn type attribute. This is used in function unit delay
;; computations.
-(define_attr "type" "integer,load,load_ext,load_ext_u,load_ext_ux,load_ux,load_u,store,store_ux,store_u,fpload,fpload_ux,fpload_u,fpstore,fpstore_ux,fpstore_u,vecload,vecstore,imul,imul2,imul3,lmul,idiv,ldiv,insert_word,branch,cmp,fast_compare,compare,delayed_compare,imul_compare,lmul_compare,fpcompare,cr_logical,delayed_cr,mfcr,mtcr,mfjmpr,mtjmpr,fp,fpsimple,dmul,sdiv,ddiv,ssqrt,dsqrt,jmpreg,brinc,vecsimple,veccomplex,vecdiv,veccmp,veccmpsimple,vecperm,vecfloat,vecfdiv"
+(define_attr "type" "integer,load,load_ext,load_ext_u,load_ext_ux,load_ux,load_u,store,store_ux,store_u,fpload,fpload_ux,fpload_u,fpstore,fpstore_ux,fpstore_u,vecload,vecstore,imul,imul2,imul3,lmul,idiv,ldiv,insert_word,branch,cmp,fast_compare,compare,delayed_compare,imul_compare,lmul_compare,fpcompare,cr_logical,delayed_cr,mfcr,mfcrf,mtcr,mfjmpr,mtjmpr,fp,fpsimple,dmul,sdiv,ddiv,ssqrt,dsqrt,jmpreg,brinc,vecsimple,veccomplex,vecdiv,veccmp,veccmpsimple,vecperm,vecfloat,vecfdiv"
(const_string "integer"))
;; Length (in bytes).
mcrf %0,%1
mtcrf 128,%1
{rlinm|rlwinm} %1,%1,%F0,0xffffffff\;mtcrf %R0,%1\;{rlinm|rlwinm} %1,%1,%f0,0xffffffff
- mfcr %0
- mfcr %0\;{rlinm|rlwinm} %0,%0,%f1,0xf0000000
+ mfcr %0%Q1
+ mfcr %0%Q1\;{rlinm|rlwinm} %0,%0,%f1,0xf0000000
mr %0,%1
mf%1 %0
mt%0 %1
mt%0 %1
{l%U1%X1|lwz%U1%X1} %0,%1
{st%U0%U1|stw%U0%U1} %1,%0"
- [(set_attr "type" "cr_logical,mtcr,mtcr,mfcr,mfcr,*,mfjmpr,*,mtjmpr,load,store")
+ [(set (attr "type")
+ (cond [(eq_attr "alternative" "0")
+ (const_string "cr_logical")
+ (eq_attr "alternative" "1,2")
+ (const_string "mtcr")
+ (eq_attr "alternative" "5,7")
+ (const_string "integer")
+ (eq_attr "alternative" "6")
+ (const_string "mfjmpr")
+ (eq_attr "alternative" "8")
+ (const_string "mtjmpr")
+ (eq_attr "alternative" "9")
+ (const_string "load")
+ (eq_attr "alternative" "10")
+ (const_string "store")
+ (ne (symbol_ref "TARGET_MFCRF") (const_int 0))
+ (const_string "mfcrf")
+ ]
+ (const_string "mfcr")))
(set_attr "length" "4,4,12,4,8,4,4,4,4,4,4")])
\f
;; For floating-point, we normally deal with the floating-point registers
[(match_operand 2 "cc_reg_operand" "y")
(const_int 0)]))]
""
- "mfcr %0\;{rlinm|rlwinm} %0,%0,%J1,1"
- [(set_attr "type" "mfcr")
+ "mfcr %0%Q2\;{rlinm|rlwinm} %0,%0,%J1,1"
+ [(set (attr "type")
+ (cond [(ne (symbol_ref "TARGET_MFCRF") (const_int 0))
+ (const_string "mfcrf")
+ ]
+ (const_string "mfcr")))
(set_attr "length" "12")])
;; Same as above, but get the OV/ORDERED bit.
[(match_operand 2 "cc_reg_operand" "y")
(const_int 0)]))]
"TARGET_POWERPC64"
- "mfcr %0\;{rlinm|rlwinm} %0,%0,%J1,1"
- [(set_attr "type" "mfcr")
+ "mfcr %0%Q2\;{rlinm|rlwinm} %0,%0,%J1,1"
+ [(set (attr "type")
+ (cond [(ne (symbol_ref "TARGET_MFCRF") (const_int 0))
+ (const_string "mfcrf")
+ ]
+ (const_string "mfcr")))
(set_attr "length" "12")])
(define_insn ""
(match_op_dup 1 [(match_dup 2) (const_int 0)]))]
"! TARGET_POWERPC64"
"@
- mfcr %3\;{rlinm.|rlwinm.} %3,%3,%J1,1
+ mfcr %3%Q2\;{rlinm.|rlwinm.} %3,%3,%J1,1
#"
[(set_attr "type" "delayed_compare")
(set_attr "length" "12,16")])
operands[4] = GEN_INT (count);
operands[5] = GEN_INT (put_bit);
- return \"mfcr %0\;{rlinm|rlwinm} %0,%0,%4,%5,%5\";
+ return \"mfcr %0%Q2\;{rlinm|rlwinm} %0,%0,%4,%5,%5\";
}"
- [(set_attr "type" "mfcr")
+ [(set (attr "type")
+ (cond [(ne (symbol_ref "TARGET_MFCRF") (const_int 0))
+ (const_string "mfcrf")
+ ]
+ (const_string "mfcr")))
(set_attr "length" "12")])
(define_insn ""
operands[5] = GEN_INT (count);
operands[6] = GEN_INT (put_bit);
- return \"mfcr %4\;{rlinm.|rlwinm.} %4,%4,%5,%6,%6\";
+ return \"mfcr %4%Q2\;{rlinm.|rlwinm.} %4,%4,%5,%6,%6\";
}"
[(set_attr "type" "delayed_compare")
(set_attr "length" "12,16")])
DONE;
}")
+(define_insn "*movesi_from_cr_one"
+ [(match_parallel 0 "mfcr_operation"
+ [(set (match_operand:SI 1 "gpc_reg_operand" "=r")
+ (unspec:SI [(match_operand:CC 2 "cc_reg_operand" "y")
+ (match_operand 3 "immediate_operand" "n")]
+ UNSPEC_MOVESI_FROM_CR))])]
+ "TARGET_MFCRF"
+ "*
+{
+ int mask = 0;
+ int i;
+ for (i = 0; i < XVECLEN (operands[0], 0); i++)
+ {
+ mask = INTVAL (XVECEXP (SET_SRC (XVECEXP (operands[0], 0, i)), 0, 1));
+ operands[4] = GEN_INT (mask);
+ output_asm_insn (\"mfcr %1,%4\", operands);
+ }
+ return \"\";
+}"
+ [(set_attr "type" "mfcrf")])
+
(define_insn "movesi_from_cr"
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
(unspec:SI [(reg:CC 68) (reg:CC 69) (reg:CC 70) (reg:CC 71)
if test "x$gcc_cv_as_ltoffx_ldxmov_relocs" = xyes; then
cat >> confdefs.h <<\EOF
#define HAVE_AS_LTOFFX_LDXMOV_RELOCS 1
+EOF
+
+ fi
+ ;;
+ powerpc*-*-*)
+ echo $ac_n "checking assembler supports mfcr field""... $ac_c" 1>&6
+echo "configure:8174: checking assembler supports mfcr field" >&5
+if eval "test \"`echo '$''{'gcc_cv_as_mfcrf'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+
+ gcc_cv_as_mfcrf=unknown
+ if test $in_tree_gas = yes ; then
+ if test $gcc_cv_gas_major_version -eq 2 \
+&& test $gcc_cv_gas_minor_version -ge 14 \
+|| test $gcc_cv_gas_major_version -gt 2 ; then
+
+
+ gcc_cv_as_mfcrf=yes
+
+
+fi
+
+ elif test x$gcc_cv_as != x; then
+ cat > conftest.s << 'EOF'
+ case "$target" in
+ *-*-aix*)
+ .csect .text[PR]
+ ;;
+ *)
+ .text
+ ;;
+ esac
+ mfcr 3,128
+EOF
+ if $gcc_cv_as -o conftest.o conftest.s > /dev/null 2>&1; then
+ gcc_cv_as_mfcrf=yes
+ else
+ gcc_cv_as_mfcrf=no
+ fi
+ rm -f conftest.s conftest.o
+ fi
+
+fi
+
+echo "$ac_t""$gcc_cv_as_mfcrf" 1>&6
+ if test "x$gcc_cv_as_mfcrf" = xyes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_AS_MFCRF 1
EOF
fi
[Define if your assembler supports ltoffx and ldxmov relocations.])
fi
;;
+ powerpc*-*-*)
+ AC_CACHE_CHECK([assembler supports mfcr field],
+ gcc_cv_as_mfcrf, [
+ gcc_cv_as_mfcrf=unknown
+ if test $in_tree_gas = yes ; then
+ gcc_GAS_VERSION_GTE_IFELSE(2,14,0,[
+ gcc_cv_as_mfcrf=yes
+ ])
+ elif test x$gcc_cv_as != x; then
+ cat > conftest.s << 'EOF'
+ case "$target" in
+changequote(,)dnl
+ *-*-aix*)
+ .csect .text[PR]
+ ;;
+ *)
+ .text
+ ;;
+ esac
+ mfcr 3,128
+EOF
+changequote([,])dnl
+ if $gcc_cv_as -o conftest.o conftest.s > /dev/null 2>&1; then
+ gcc_cv_as_mfcrf=yes
+ else
+ gcc_cv_as_mfcrf=no
+ fi
+ rm -f conftest.s conftest.o
+ fi
+ ])
+ if test "x$gcc_cv_as_mfcrf" = xyes; then
+ AC_DEFINE(HAVE_AS_MFCRF, 1,
+ [Define if your assembler supports mfcr field.])
+ fi
+ ;;
esac
AC_MSG_CHECKING(assembler dwarf2 debug_line support)