aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Edelsohn <edelsohn@gnu.org>1996-01-22 19:12:22 +0000
committerDavid Edelsohn <edelsohn@gnu.org>1996-01-22 19:12:22 +0000
commit266eb58af385276cae6011361178c827f812e40f (patch)
tree382790b806b4e17f58fda855220b86cf0b6480d5
parentb73fd26c62b8c663b36f7953c4b35d60c07dbdcf (diff)
downloadgcc-266eb58af385276cae6011361178c827f812e40f.zip
gcc-266eb58af385276cae6011361178c827f812e40f.tar.gz
gcc-266eb58af385276cae6011361178c827f812e40f.tar.bz2
PowerPC64 DImode patterns
From-SVN: r11080
-rw-r--r--gcc/config/rs6000/rs6000.md818
1 files changed, 792 insertions, 26 deletions
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index 8920c8a..bd8c0d2 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -3618,7 +3618,7 @@
;; (for example, having an input in 7,8 and an output in 6,7). We
;; also allow for the the output being the same as one of the inputs.
-(define_insn "adddi3"
+(define_insn "*adddi3_noppc64"
[(set (match_operand:DI 0 "gpc_reg_operand" "=&r,&r,r,r")
(plus:DI (match_operand:DI 1 "gpc_reg_operand" "%r,r,0,0")
(match_operand:DI 2 "reg_or_short_operand" "r,I,r,I")))]
@@ -3636,11 +3636,11 @@
}"
[(set_attr "length" "8")])
-(define_insn "subddi3"
+(define_insn "*subdi3_noppc64"
[(set (match_operand:DI 0 "gpc_reg_operand" "=&r,&r,r,r,r")
(minus:DI (match_operand:DI 1 "reg_or_short_operand" "r,I,0,r,I")
(match_operand:DI 2 "gpc_reg_operand" "r,r,r,0,0")))]
- "TARGET_POWER && ! TARGET_POWERPC64"
+ "! TARGET_POWERPC64"
"*
{
if (WORDS_BIG_ENDIAN)
@@ -3654,13 +3654,7 @@
}"
[(set_attr "length" "8")])
-(define_expand "negdi2"
- [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
- (neg:DI (match_operand:DI 1 "gpc_reg_operand" "r")))]
- ""
- "")
-
-(define_insn ""
+(define_insn "*negdi2_noppc64"
[(set (match_operand:DI 0 "gpc_reg_operand" "=&r,r")
(neg:DI (match_operand:DI 1 "gpc_reg_operand" "r,0")))]
"! TARGET_POWERPC64"
@@ -3846,7 +3840,7 @@
;; If operands 0 and 2 are in the same register, we have a problem. But
;; operands 0 and 1 (the usual case) can be in the same register. That's
;; why we have the strange constraints below.
-(define_insn "ashldi3"
+(define_insn "ashldi3_power"
[(set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r,&r")
(ashift:DI (match_operand:DI 1 "gpc_reg_operand" "r,r,0,r")
(match_operand:SI 2 "reg_or_cint_operand" "M,i,r,r")))
@@ -3859,7 +3853,7 @@
sl%I2q %L0,%L1,%h2\;sll%I2q %0,%1,%h2"
[(set_attr "length" "8")])
-(define_insn "lshrdi3"
+(define_insn "lshrdi3_power"
[(set (match_operand:DI 0 "gpc_reg_operand" "=&r,r,r,&r")
(lshiftrt:DI (match_operand:DI 1 "gpc_reg_operand" "r,r,0,r")
(match_operand:SI 2 "reg_or_cint_operand" "M,i,r,r")))
@@ -3874,19 +3868,7 @@
;; Shift by a variable amount is too complex to be worth open-coding. We
;; just handle shifts by constants.
-
-(define_expand "ashrdi3"
- [(parallel [(set (match_operand:DI 0 "gpc_reg_operand" "")
- (ashiftrt:DI (match_operand:DI 1 "gpc_reg_operand" "")
- (match_operand:SI 2 "general_operand" "")))
- (clobber (match_scratch:SI 3 ""))])]
- "TARGET_POWER"
- "
-{ if (GET_CODE (operands[2]) != CONST_INT)
- FAIL;
-}")
-
-(define_insn ""
+(define_insn "ashrdi3_power"
[(set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
(ashiftrt:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
(match_operand:SI 2 "const_int_operand" "M,i")))
@@ -3899,6 +3881,216 @@
;; PowerPC64 DImode operations.
+(define_expand "adddi3"
+ [(set (match_operand:DI 0 "gpc_reg_operand" "")
+ (plus:DI (match_operand:DI 1 "gpc_reg_operand" "")
+ (match_operand:DI 2 "add_operand" "")))]
+ ""
+ "
+{
+ if (! TARGET_POWERPC64 && non_add_cint_operand (operands[2], DImode))
+ FAIL;
+}")
+
+;; Discourage ai/addic because of carry but provide it in an alternative
+;; allowing register zero as source.
+
+(define_insn ""
+ [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r,?r,r")
+ (plus:DI (match_operand:DI 1 "gpc_reg_operand" "%r,b,r,b")
+ (match_operand:DI 2 "add_operand" "r,I,I,J")))]
+ "TARGET_POWERPC64"
+ "@
+ add %0,%1,%2
+ addi %0,%1,%2
+ addic %0,%1,%2
+ addis %0,%1,%u2")
+
+(define_insn ""
+ [(set (match_operand:CC 0 "cc_reg_operand" "=x,x")
+ (compare:CC (plus:DI (match_operand:DI 1 "gpc_reg_operand" "%r,r")
+ (match_operand:DI 2 "reg_or_short_operand" "r,I"))
+ (const_int 0)))
+ (clobber (match_scratch:DI 3 "=r,r"))]
+ "TARGET_POWERPC64"
+ "@
+ add. %3,%1,%2
+ addic. %3,%1,%2"
+ [(set_attr "type" "compare")])
+
+(define_insn ""
+ [(set (match_operand:CC 3 "cc_reg_operand" "=x,x")
+ (compare:CC (plus:DI (match_operand:DI 1 "gpc_reg_operand" "%r,r")
+ (match_operand:DI 2 "reg_or_short_operand" "r,I"))
+ (const_int 0)))
+ (set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
+ (plus:DI (match_dup 1) (match_dup 2)))]
+ "TARGET_POWERPC64"
+ "@
+ add. %0,%1,%2
+ addic. %0,%1,%2"
+ [(set_attr "type" "compare")])
+
+;; Split an add that we can't do in one insn into two insns, each of which
+;; does one 16-bit part. This is used by combine. Note that the low-order
+;; add should be last in case the result gets used in an address.
+
+(define_split
+ [(set (match_operand:DI 0 "gpc_reg_operand" "")
+ (plus:DI (match_operand:DI 1 "gpc_reg_operand" "")
+ (match_operand:DI 2 "non_add_cint_operand" "")))]
+ "TARGET_POWERPC64"
+ [(set (match_dup 0) (plus:DI (match_dup 1) (match_dup 3)))
+ (set (match_dup 0) (plus:DI (match_dup 0) (match_dup 4)))]
+"
+{
+ int low = INTVAL (operands[2]) & 0xffff;
+ int high = (unsigned) INTVAL (operands[2]) >> 16;
+
+ if (low & 0x8000)
+ high++, low |= 0xffff0000;
+
+ operands[3] = gen_rtx (CONST_INT, VOIDmode, high << 16);
+ operands[4] = gen_rtx (CONST_INT, VOIDmode, low);
+}")
+
+(define_insn "one_cmpldi2"
+ [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
+ (not:DI (match_operand:DI 1 "gpc_reg_operand" "r")))]
+ "TARGET_POWERPC64"
+ "nor %0,%1,%1")
+
+(define_insn ""
+ [(set (match_operand:CC 0 "cc_reg_operand" "=x")
+ (compare:CC (not:DI (match_operand:DI 1 "gpc_reg_operand" "r"))
+ (const_int 0)))
+ (clobber (match_scratch:DI 2 "=r"))]
+ "TARGET_POWERPC64"
+ "nor. %2,%1,%1"
+ [(set_attr "type" "compare")])
+
+(define_insn ""
+ [(set (match_operand:CC 2 "cc_reg_operand" "=x")
+ (compare:CC (not:DI (match_operand:DI 1 "gpc_reg_operand" "r"))
+ (const_int 0)))
+ (set (match_operand:DI 0 "gpc_reg_operand" "=r")
+ (not:DI (match_dup 1)))]
+ "TARGET_POWERPC64"
+ "nor. %0,%2,%1"
+ [(set_attr "type" "compare")])
+
+(define_insn ""
+ [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
+ (minus:DI (match_operand:DI 1 "reg_or_short_operand" "r,I")
+ (match_operand:DI 2 "gpc_reg_operand" "r,r")))]
+ "TARGET_POWERPC64"
+ "@
+ subf %0,%2,%1
+ subfic %0,%2,%1")
+
+(define_insn ""
+ [(set (match_operand:CC 0 "cc_reg_operand" "=x")
+ (compare:CC (minus:DI (match_operand:DI 1 "gpc_reg_operand" "r")
+ (match_operand:DI 2 "gpc_reg_operand" "r"))
+ (const_int 0)))
+ (clobber (match_scratch:DI 3 "=r"))]
+ "TARGET_POWERPC64"
+ "subf. %3,%2,%1"
+ [(set_attr "type" "compare")])
+
+(define_insn ""
+ [(set (match_operand:CC 3 "cc_reg_operand" "=x")
+ (compare:CC (minus:DI (match_operand:DI 1 "gpc_reg_operand" "r")
+ (match_operand:DI 2 "gpc_reg_operand" "r"))
+ (const_int 0)))
+ (set (match_operand:DI 0 "gpc_reg_operand" "=r")
+ (minus:DI (match_dup 1) (match_dup 2)))]
+ "TARGET_POWERPC64"
+ "subf. %0,%2,%1"
+ [(set_attr "type" "compare")])
+
+(define_expand "subdi3"
+ [(set (match_operand:DI 0 "gpc_reg_operand" "")
+ (minus:DI (match_operand:DI 1 "reg_or_short_operand" "")
+ (match_operand:DI 2 "reg_or_cint_operand" "")))]
+ ""
+ "
+{
+ if (GET_CODE (operands[2]) == CONST_INT)
+ {
+ emit_insn (gen_adddi3 (operands[0], operands[1],
+ negate_rtx (DImode, operands[2])));
+ DONE;
+ }
+}")
+
+(define_insn "absdi2"
+ [(set (match_operand:DI 0 "gpc_reg_operand" "=&r,r")
+ (abs:DI (match_operand:DI 1 "gpc_reg_operand" "r,0")))
+ (clobber (match_scratch:DI 2 "=&r,&r"))]
+ "TARGET_POWERPC64"
+ "sradi %2,%1,31\;xor %0,%2,%1\;subf %0,%2,%0"
+ [(set_attr "length" "12")])
+
+(define_split
+ [(set (match_operand:DI 0 "gpc_reg_operand" "=&r,r")
+ (abs:DI (match_operand:DI 1 "gpc_reg_operand" "r,0")))
+ (clobber (match_scratch:DI 2 "=&r,&r"))]
+ "TARGET_POWERPC64 && reload_completed"
+ [(set (match_dup 2) (ashiftrt:DI (match_dup 1) (const_int 31)))
+ (set (match_dup 0) (xor:DI (match_dup 2) (match_dup 1)))
+ (set (match_dup 0) (minus:DI (match_dup 2) (match_dup 0)))]
+ "")
+
+(define_insn ""
+ [(set (match_operand:DI 0 "gpc_reg_operand" "=&r,r")
+ (neg:DI (abs:DI (match_operand:DI 1 "gpc_reg_operand" "r,0"))))
+ (clobber (match_scratch:DI 2 "=&r,&r"))]
+ "TARGET_POWERPC64"
+ "sradi %2,%1,31\;xor %0,%2,%1\;subf %0,%0,%2"
+ [(set_attr "length" "12")])
+
+(define_split
+ [(set (match_operand:DI 0 "gpc_reg_operand" "=&r,r")
+ (neg:DI (abs:DI (match_operand:DI 1 "gpc_reg_operand" "r,0"))))
+ (clobber (match_scratch:DI 2 "=&r,&r"))]
+ "TARGET_POWERPC64 && reload_completed"
+ [(set (match_dup 2) (ashiftrt:DI (match_dup 1) (const_int 31)))
+ (set (match_dup 0) (xor:DI (match_dup 2) (match_dup 1)))
+ (set (match_dup 0) (minus:DI (match_dup 0) (match_dup 2)))]
+ "")
+
+(define_expand "negdi2"
+ [(set (match_operand:DI 0 "gpc_reg_operand" "")
+ (neg:DI (match_operand:DI 1 "gpc_reg_operand" "")))]
+ ""
+ "")
+
+(define_insn ""
+ [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
+ (neg:DI (match_operand:DI 1 "gpc_reg_operand" "r")))]
+ "TARGET_POWERPC64"
+ "neg %0,%1")
+
+(define_insn ""
+ [(set (match_operand:CC 0 "cc_reg_operand" "=x")
+ (compare:CC (neg:DI (match_operand:DI 1 "gpc_reg_operand" "r"))
+ (const_int 0)))
+ (clobber (match_scratch:DI 2 "=r"))]
+ "TARGET_POWERPC64"
+ "neg. %2,%1"
+ [(set_attr "type" "compare")])
+
+(define_insn ""
+ [(set (match_operand:CC 2 "cc_reg_operand" "=x")
+ (compare:CC (neg:DI (match_operand:DI 1 "gpc_reg_operand" "r"))
+ (const_int 0)))
+ (set (match_operand:DI 0 "gpc_reg_operand" "=r")
+ (neg:DI (match_dup 1)))]
+ "TARGET_POWERPC64"
+ "neg. %0,%1"
+ [(set_attr "type" "compare")])
+
(define_insn "ffsdi2"
[(set (match_operand:DI 0 "gpc_reg_operand" "=&r")
(ffs:DI (match_operand:DI 1 "gpc_reg_operand" "r")))]
@@ -3938,7 +4130,75 @@
"mulhdu %0,%1,%2"
[(set_attr "type" "imul")])
-(define_insn "divdi3"
+(define_expand "divdi3"
+ [(set (match_operand:DI 0 "gpc_reg_operand" "")
+ (div:DI (match_operand:DI 1 "gpc_reg_operand" "")
+ (match_operand:DI 2 "reg_or_cint_operand" "")))]
+ "TARGET_POWERPC64"
+ "
+{
+ if (GET_CODE (operands[2]) == CONST_INT
+ && exact_log2 (INTVAL (operands[2])) >= 0)
+ ;
+ else
+ operands[2] = force_reg (DImode, operands[2]);
+}")
+
+(define_expand "moddi3"
+ [(use (match_operand:DI 0 "gpc_reg_operand" ""))
+ (use (match_operand:DI 1 "gpc_reg_operand" ""))
+ (use (match_operand:DI 2 "reg_or_cint_operand" ""))]
+ "TARGET_POWERPC64"
+ "
+{
+ int i = exact_log2 (INTVAL (operands[2]));
+ rtx temp1;
+ rtx temp2;
+
+ if (GET_CODE (operands[2]) != CONST_INT || i < 0)
+ FAIL;
+
+ temp1 = gen_reg_rtx (DImode);
+ temp2 = gen_reg_rtx (DImode);
+
+ emit_insn (gen_divdi3 (temp1, operands[1], operands[2]));
+ emit_insn (gen_ashldi3 (temp2, temp1, GEN_INT (i)));
+ emit_insn (gen_subdi3 (operands[0], operands[1], temp2));
+ DONE;
+}")
+
+(define_insn ""
+ [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
+ (div:DI (match_operand:DI 1 "gpc_reg_operand" "r")
+ (match_operand:DI 2 "const_int_operand" "N")))]
+ "TARGET_POWERPC64 && exact_log2 (INTVAL (operands[2])) >= 0"
+ "sradi %0,%1,%p2\;addze %0,%0"
+ [(set_attr "length" "8")])
+
+(define_insn ""
+ [(set (match_operand:CC 0 "cc_reg_operand" "=x")
+ (compare:CC (div:DI (match_operand:DI 1 "gpc_reg_operand" "r")
+ (match_operand:DI 2 "const_int_operand" "N"))
+ (const_int 0)))
+ (clobber (match_scratch:DI 3 "=r"))]
+ "TARGET_POWERPC64 && exact_log2 (INTVAL (operands[2])) >= 0"
+ "sradi %3,%1,%p2\;addze. %3,%3"
+ [(set_attr "type" "compare")
+ (set_attr "length" "8")])
+
+(define_insn ""
+ [(set (match_operand:CC 3 "cc_reg_operand" "=x")
+ (compare:CC (div:DI (match_operand:DI 1 "gpc_reg_operand" "r")
+ (match_operand:DI 2 "const_int_operand" "N"))
+ (const_int 0)))
+ (set (match_operand:DI 0 "gpc_reg_operand" "=r")
+ (div:DI (match_dup 1) (match_dup 2)))]
+ "TARGET_POWERPC64 && exact_log2 (INTVAL (operands[2])) >= 0"
+ "sradi %0,%1,%p2\;addze. %0,%0"
+ [(set_attr "type" "compare")
+ (set_attr "length" "8")])
+
+(define_insn ""
[(set (match_operand:DI 0 "gpc_reg_operand" "=r")
(div:DI (match_operand:DI 1 "gpc_reg_operand" "r")
(match_operand:DI 2 "gpc_reg_operand" "r")))]
@@ -3981,6 +4241,459 @@
"TARGET_POWERPC64"
"rld%I2cl. %0,%1,%h2,0"
[(set_attr "type" "delayed_compare")])
+
+(define_expand "ashldi3"
+ [(set (match_operand:DI 0 "gpc_reg_operand" "")
+ (ashift:DI (match_operand:DI 1 "gpc_reg_operand" "")
+ (match_operand:SI 2 "reg_or_cint_operand" "")))]
+ "TARGET_POWERPC64 || TARGET_POWER"
+ "
+{
+ if (TARGET_POWERPC64)
+ ;
+ else if (TARGET_POWER)
+ {
+ emit_insn (gen_ashldi3_power (operands[0], operands[1], operands[2]));
+ DONE;
+ }
+ else
+ FAIL;
+}")
+
+(define_insn ""
+ [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
+ (ashift:DI (match_operand:DI 1 "gpc_reg_operand" "r")
+ (match_operand:SI 2 "reg_or_cint_operand" "ri")))]
+ "TARGET_POWERPC64"
+ "sld%I2 %0,%1,%2"
+ [(set_attr "length" "8")])
+
+(define_insn ""
+ [(set (match_operand:CC 0 "cc_reg_operand" "=x")
+ (compare:CC (ashift:DI (match_operand:DI 1 "gpc_reg_operand" "r")
+ (match_operand:SI 2 "reg_or_cint_operand" "ri"))
+ (const_int 0)))
+ (clobber (match_scratch:DI 3 "=r"))]
+ "TARGET_POWERPC64"
+ "sld%I2. %3,%1,%2"
+ [(set_attr "type" "delayed_compare")])
+
+(define_insn ""
+ [(set (match_operand:CC 3 "cc_reg_operand" "=x")
+ (compare:CC (ashift:DI (match_operand:DI 1 "gpc_reg_operand" "r")
+ (match_operand:SI 2 "reg_or_cint_operand" "ri"))
+ (const_int 0)))
+ (set (match_operand:DI 0 "gpc_reg_operand" "=r")
+ (ashift:DI (match_dup 1) (match_dup 2)))]
+ "TARGET_POWERPC64"
+ "sld%I2. %0,%1,%2"
+ [(set_attr "type" "delayed_compare")])
+
+(define_expand "lshrdi3"
+ [(set (match_operand:DI 0 "gpc_reg_operand" "")
+ (lshiftrt:DI (match_operand:DI 1 "gpc_reg_operand" "")
+ (match_operand:SI 2 "reg_or_cint_operand" "")))]
+ "TARGET_POWERPC64 || TARGET_POWER"
+ "
+{
+ if (TARGET_POWERPC64)
+ ;
+ else if (TARGET_POWER)
+ {
+ emit_insn (gen_lshrdi3_power (operands[0], operands[1], operands[2]));
+ DONE;
+ }
+ else
+ FAIL;
+}")
+
+(define_insn ""
+ [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
+ (lshiftrt:DI (match_operand:DI 1 "gpc_reg_operand" "r")
+ (match_operand:SI 2 "reg_or_cint_operand" "ri")))]
+ "TARGET_POWERPC64"
+ "srd%I2 %0,%1,%2")
+
+(define_insn ""
+ [(set (match_operand:CC 0 "cc_reg_operand" "=x")
+ (compare:CC (lshiftrt:DI (match_operand:DI 1 "gpc_reg_operand" "r")
+ (match_operand:SI 2 "reg_or_cint_operand" "ri"))
+ (const_int 0)))
+ (clobber (match_scratch:DI 3 "=r"))]
+ "TARGET_POWERPC64"
+ "srd%I2. %3,%1,%2"
+ [(set_attr "type" "delayed_compare")])
+
+(define_insn ""
+ [(set (match_operand:CC 3 "cc_reg_operand" "=x")
+ (compare:CC (lshiftrt:DI (match_operand:DI 1 "gpc_reg_operand" "r")
+ (match_operand:SI 2 "reg_or_cint_operand" "ri"))
+ (const_int 0)))
+ (set (match_operand:DI 0 "gpc_reg_operand" "=r")
+ (lshiftrt:DI (match_dup 1) (match_dup 2)))]
+ "TARGET_POWERPC64"
+ "srd%I2. %0,%1,%2"
+ [(set_attr "type" "delayed_compare")])
+
+(define_expand "ashrdi3"
+ [(set (match_operand:DI 0 "gpc_reg_operand" "")
+ (ashiftrt:DI (match_operand:DI 1 "gpc_reg_operand" "")
+ (match_operand:SI 2 "reg_or_cint_operand" "")))]
+ "TARGET_POWERPC64 || TARGET_POWER"
+ "
+{
+ if (TARGET_POWERPC64)
+ ;
+ else if (TARGET_POWER && GET_CODE (operands[2]) == CONST_INT)
+ {
+ emit_insn (gen_ashrdi3_power (operands[0], operands[1], operands[2]));
+ DONE;
+ }
+ else
+ FAIL;
+}")
+
+(define_insn ""
+ [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
+ (ashiftrt:DI (match_operand:DI 1 "gpc_reg_operand" "r")
+ (match_operand:SI 2 "reg_or_cint_operand" "ri")))]
+ "TARGET_POWERPC64"
+ "srad%I2 %0,%1,%2")
+
+(define_insn ""
+ [(set (match_operand:CC 0 "cc_reg_operand" "=x")
+ (compare:CC (ashiftrt:DI (match_operand:DI 1 "gpc_reg_operand" "r")
+ (match_operand:SI 2 "reg_or_cint_operand" "ri"))
+ (const_int 0)))
+ (clobber (match_scratch:DI 3 "=r"))]
+ "TARGET_POWERPC64"
+ "srad%I2. %3,%1,%2"
+ [(set_attr "type" "delayed_compare")])
+
+(define_insn ""
+ [(set (match_operand:CC 3 "cc_reg_operand" "=x")
+ (compare:CC (ashiftrt:DI (match_operand:DI 1 "gpc_reg_operand" "r")
+ (match_operand:SI 2 "reg_or_cint_operand" "ri"))
+ (const_int 0)))
+ (set (match_operand:DI 0 "gpc_reg_operand" "=r")
+ (ashiftrt:DI (match_dup 1) (match_dup 2)))]
+ "TARGET_POWERPC64"
+ "srad%I2. %0,%1,%2"
+ [(set_attr "type" "delayed_compare")])
+
+(define_insn "anddi3"
+ [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r")
+ (and:DI (match_operand:DI 1 "gpc_reg_operand" "%r,r,r")
+ (match_operand:DI 2 "and_operand" "?r,K,J")))
+ (clobber (match_scratch:CC 3 "=X,x,x"))]
+ "TARGET_POWERPC64"
+ "@
+ and %0,%1,%2
+ andi. %0,%1,%b2
+ andis. %0,%1,%u2")
+
+(define_insn ""
+ [(set (match_operand:CC 0 "cc_reg_operand" "=x,x,x")
+ (compare:CC (and:DI (match_operand:DI 1 "gpc_reg_operand" "%r,r,r")
+ (match_operand:DI 2 "and_operand" "r,K,J"))
+ (const_int 0)))
+ (clobber (match_scratch:DI 3 "=r,r,r"))]
+ "TARGET_POWERPC64"
+ "@
+ and. %3,%1,%2
+ andi. %3,%1,%b2
+ andis. %3,%1,%u2"
+ [(set_attr "type" "compare,compare,compare")])
+
+(define_insn ""
+ [(set (match_operand:CC 3 "cc_reg_operand" "=x,x,x")
+ (compare:CC (and:DI (match_operand:DI 1 "gpc_reg_operand" "%r,r,r")
+ (match_operand:DI 2 "and_operand" "r,K,J"))
+ (const_int 0)))
+ (set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r")
+ (and:DI (match_dup 1) (match_dup 2)))]
+ "TARGET_POWERPC64"
+ "@
+ and. %0,%1,%2
+ andi. %0,%1,%b2
+ andis. %0,%1,%u2"
+ [(set_attr "type" "compare,compare,compare")])
+
+;; Take a AND with a constant that cannot be done in a single insn and try to
+;; split it into two insns. This does not verify that the insns are valid
+;; since this need not be done as combine will do it.
+
+(define_split
+ [(set (match_operand:DI 0 "gpc_reg_operand" "")
+ (and:DI (match_operand:DI 1 "gpc_reg_operand" "")
+ (match_operand:DI 2 "non_and_cint_operand" "")))]
+ "TARGET_POWERPC64"
+ [(set (match_dup 0) (and:DI (match_dup 1) (match_dup 3)))
+ (set (match_dup 0) (and:DI (match_dup 0) (match_dup 4)))]
+ "
+{
+ int maskval = INTVAL (operands[2]);
+ int i, transitions, last_bit_value;
+ int orig = maskval, first_c = maskval, second_c;
+
+ /* We know that MASKVAL must have more than 2 bit-transitions. Start at
+ the low-order bit and count for the third transition. When we get there,
+ make a first mask that has everything to the left of that position
+ a one. Then make the second mask to turn off whatever else is needed. */
+
+ for (i = 1, transitions = 0, last_bit_value = maskval & 1; i < 32; i++)
+ {
+ if (((maskval >>= 1) & 1) != last_bit_value)
+ last_bit_value ^= 1, transitions++;
+
+ if (transitions > 2)
+ {
+ first_c |= (~0) << i;
+ break;
+ }
+ }
+
+ second_c = orig | ~ first_c;
+
+ operands[3] = gen_rtx (CONST_INT, VOIDmode, first_c);
+ operands[4] = gen_rtx (CONST_INT, VOIDmode, second_c);
+}")
+
+(define_insn "iordi3"
+ [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r")
+ (ior:DI (match_operand:DI 1 "gpc_reg_operand" "%r,r,r")
+ (match_operand:DI 2 "logical_operand" "r,K,J")))]
+ "TARGET_POWERPC64"
+ "@
+ or %0,%1,%2
+ ori %0,%1,%b2
+ oris %0,%1,%u2")
+
+(define_insn ""
+ [(set (match_operand:CC 0 "cc_reg_operand" "=x")
+ (compare:CC (ior:DI (match_operand:DI 1 "gpc_reg_operand" "%r")
+ (match_operand:DI 2 "gpc_reg_operand" "r"))
+ (const_int 0)))
+ (clobber (match_scratch:DI 3 "=r"))]
+ "TARGET_POWERPC64"
+ "or. %3,%1,%2"
+ [(set_attr "type" "compare")])
+
+(define_insn ""
+ [(set (match_operand:CC 3 "cc_reg_operand" "=x")
+ (compare:CC (ior:DI (match_operand:DI 1 "gpc_reg_operand" "%r")
+ (match_operand:DI 2 "gpc_reg_operand" "r"))
+ (const_int 0)))
+ (set (match_operand:DI 0 "gpc_reg_operand" "=r")
+ (ior:DI (match_dup 1) (match_dup 2)))]
+ "TARGET_POWERPC64"
+ "or. %0,%1,%2"
+ [(set_attr "type" "compare")])
+
+;; Split an IOR that we can't do in one insn into two insns, each of which
+;; does one 16-bit part. This is used by combine.
+
+(define_split
+ [(set (match_operand:DI 0 "gpc_reg_operand" "")
+ (ior:DI (match_operand:DI 1 "gpc_reg_operand" "")
+ (match_operand:DI 2 "non_logical_cint_operand" "")))]
+ "TARGET_POWERPC64"
+ [(set (match_dup 0) (ior:DI (match_dup 1) (match_dup 3)))
+ (set (match_dup 0) (ior:DI (match_dup 0) (match_dup 4)))]
+"
+{
+ operands[3] = gen_rtx (CONST_INT, VOIDmode,
+ INTVAL (operands[2]) & 0xffff0000);
+ operands[4] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) & 0xffff);
+}")
+
+(define_insn "xordi3"
+ [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r")
+ (xor:DI (match_operand:DI 1 "gpc_reg_operand" "%r,r,r")
+ (match_operand:DI 2 "logical_operand" "r,K,J")))]
+ "TARGET_POWERPC64"
+ "@
+ xor %0,%1,%2
+ xori %0,%1,%b2
+ xoris %0,%1,%u2")
+
+(define_insn ""
+ [(set (match_operand:CC 0 "cc_reg_operand" "=x")
+ (compare:CC (xor:DI (match_operand:DI 1 "gpc_reg_operand" "%r")
+ (match_operand:DI 2 "gpc_reg_operand" "r"))
+ (const_int 0)))
+ (clobber (match_scratch:DI 3 "=r"))]
+ "TARGET_POWERPC64"
+ "xor. %3,%1,%2"
+ [(set_attr "type" "compare")])
+
+(define_insn ""
+ [(set (match_operand:CC 3 "cc_reg_operand" "=x")
+ (compare:CC (xor:DI (match_operand:DI 1 "gpc_reg_operand" "%r")
+ (match_operand:DI 2 "gpc_reg_operand" "r"))
+ (const_int 0)))
+ (set (match_operand:DI 0 "gpc_reg_operand" "=r")
+ (xor:DI (match_dup 1) (match_dup 2)))]
+ "TARGET_POWERPC64"
+ "xor. %0,%1,%2"
+ [(set_attr "type" "compare")])
+
+;; Split an XOR that we can't do in one insn into two insns, each of which
+;; does one 16-bit part. This is used by combine.
+
+(define_split
+ [(set (match_operand:DI 0 "gpc_reg_operand" "")
+ (xor:DI (match_operand:DI 1 "gpc_reg_operand" "")
+ (match_operand:DI 2 "non_logical_cint_operand" "")))]
+ "TARGET_POWERPC64"
+ [(set (match_dup 0) (xor:DI (match_dup 1) (match_dup 3)))
+ (set (match_dup 0) (xor:DI (match_dup 0) (match_dup 4)))]
+"
+{
+ operands[3] = gen_rtx (CONST_INT, VOIDmode,
+ INTVAL (operands[2]) & 0xffff0000);
+ operands[4] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) & 0xffff);
+}")
+
+(define_insn ""
+ [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
+ (not:DI (xor:DI (match_operand:DI 1 "gpc_reg_operand" "%r")
+ (match_operand:DI 2 "gpc_reg_operand" "r"))))]
+ "TARGET_POWERPC64"
+ "eqv %0,%1,%2")
+
+(define_insn ""
+ [(set (match_operand:CC 0 "cc_reg_operand" "=x")
+ (compare:CC (not:DI (xor:DI (match_operand:DI 1 "gpc_reg_operand" "%r")
+ (match_operand:DI 2 "gpc_reg_operand" "r")))
+ (const_int 0)))
+ (clobber (match_scratch:DI 3 "=r"))]
+ "TARGET_POWERPC64"
+ "eqv. %3,%1,%2"
+ [(set_attr "type" "compare")])
+
+(define_insn ""
+ [(set (match_operand:CC 3 "cc_reg_operand" "=x")
+ (compare:CC (not:DI (xor:DI (match_operand:DI 1 "gpc_reg_operand" "%r")
+ (match_operand:DI 2 "gpc_reg_operand" "r")))
+ (const_int 0)))
+ (set (match_operand:DI 0 "gpc_reg_operand" "=r")
+ (not:DI (xor:DI (match_dup 1) (match_dup 2))))]
+ "TARGET_POWERPC64"
+ "eqv. %0,%1,%2"
+ [(set_attr "type" "compare")])
+
+(define_insn ""
+ [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
+ (and:DI (not:DI (match_operand:DI 1 "gpc_reg_operand" "r"))
+ (match_operand:DI 2 "gpc_reg_operand" "r")))]
+ "TARGET_POWERPC64"
+ "andc %0,%2,%1")
+
+(define_insn ""
+ [(set (match_operand:CC 0 "cc_reg_operand" "=x")
+ (compare:CC (and:DI (not:DI (match_operand:DI 1 "gpc_reg_operand" "r"))
+ (match_operand:DI 2 "gpc_reg_operand" "r"))
+ (const_int 0)))
+ (clobber (match_scratch:DI 3 "=r"))]
+ "TARGET_POWERPC64"
+ "andc. %3,%2,%1"
+ [(set_attr "type" "compare")])
+
+(define_insn ""
+ [(set (match_operand:CC 3 "cc_reg_operand" "=x")
+ (compare:CC (and:DI (not:DI (match_operand:DI 1 "gpc_reg_operand" "r"))
+ (match_operand:DI 2 "gpc_reg_operand" "r"))
+ (const_int 0)))
+ (set (match_operand:DI 0 "gpc_reg_operand" "=r")
+ (and:DI (not:DI (match_dup 1)) (match_dup 2)))]
+ "TARGET_POWERPC64"
+ "andc. %0,%2,%1"
+ [(set_attr "type" "compare")])
+
+(define_insn ""
+ [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
+ (ior:DI (not:DI (match_operand:DI 1 "gpc_reg_operand" "r"))
+ (match_operand:DI 2 "gpc_reg_operand" "r")))]
+ "TARGET_POWERPC64"
+ "orc %0,%2,%1")
+
+(define_insn ""
+ [(set (match_operand:CC 0 "cc_reg_operand" "=x")
+ (compare:CC (ior:DI (not:DI (match_operand:DI 1 "gpc_reg_operand" "r"))
+ (match_operand:DI 2 "gpc_reg_operand" "r"))
+ (const_int 0)))
+ (clobber (match_scratch:DI 3 "=r"))]
+ "TARGET_POWERPC64"
+ "orc. %3,%2,%1"
+ [(set_attr "type" "compare")])
+
+(define_insn ""
+ [(set (match_operand:CC 3 "cc_reg_operand" "=x")
+ (compare:CC (ior:DI (not:DI (match_operand:DI 1 "gpc_reg_operand" "r"))
+ (match_operand:DI 2 "gpc_reg_operand" "r"))
+ (const_int 0)))
+ (set (match_operand:DI 0 "gpc_reg_operand" "=r")
+ (ior:DI (not:DI (match_dup 1)) (match_dup 2)))]
+ "TARGET_POWERPC64"
+ "orc. %0,%2,%1"
+ [(set_attr "type" "compare")])
+
+(define_insn ""
+ [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
+ (ior:DI (not:DI (match_operand:DI 1 "gpc_reg_operand" "%r"))
+ (not:DI (match_operand:DI 2 "gpc_reg_operand" "r"))))]
+ "TARGET_POWERPC64"
+ "nand %0,%1,%2")
+
+(define_insn ""
+ [(set (match_operand:CC 0 "cc_reg_operand" "=x")
+ (compare:CC (ior:DI (not:DI (match_operand:DI 1 "gpc_reg_operand" "%r"))
+ (not:DI (match_operand:DI 2 "gpc_reg_operand" "r")))
+ (const_int 0)))
+ (clobber (match_scratch:DI 3 "=r"))]
+ "TARGET_POWERPC64"
+ "nand. %3,%1,%2"
+ [(set_attr "type" "compare")])
+
+(define_insn ""
+ [(set (match_operand:CC 3 "cc_reg_operand" "=x")
+ (compare:CC (ior:DI (not:DI (match_operand:DI 1 "gpc_reg_operand" "%r"))
+ (not:DI (match_operand:DI 2 "gpc_reg_operand" "r")))
+ (const_int 0)))
+ (set (match_operand:DI 0 "gpc_reg_operand" "=r")
+ (ior:DI (not:DI (match_dup 1)) (not:DI (match_dup 2))))]
+ "TARGET_POWERPC64"
+ "nand. %0,%1,%2"
+ [(set_attr "type" "compare")])
+
+(define_insn ""
+ [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
+ (and:DI (not:DI (match_operand:DI 1 "gpc_reg_operand" "%r"))
+ (not:DI (match_operand:DI 2 "gpc_reg_operand" "r"))))]
+ "TARGET_POWERPC64"
+ "nor %0,%1,%2")
+
+(define_insn ""
+ [(set (match_operand:CC 0 "cc_reg_operand" "=x")
+ (compare:CC (and:DI (not:DI (match_operand:DI 1 "gpc_reg_operand" "%r"))
+ (not:DI (match_operand:DI 2 "gpc_reg_operand" "r")))
+ (const_int 0)))
+ (clobber (match_scratch:DI 3 "=r"))]
+ "TARGET_POWERPC64"
+ "nor. %3,%1,%2"
+ [(set_attr "type" "compare")])
+
+(define_insn ""
+ [(set (match_operand:CC 3 "cc_reg_operand" "=x")
+ (compare:CC (and:DI (not:DI (match_operand:DI 1 "gpc_reg_operand" "%r"))
+ (not:DI (match_operand:DI 2 "gpc_reg_operand" "r")))
+ (const_int 0)))
+ (set (match_operand:DI 0 "gpc_reg_operand" "=r")
+ (and:DI (not:DI (match_dup 1)) (not:DI (match_dup 2))))]
+ "TARGET_POWERPC64"
+ "nor. %0,%1,%2"
+ [(set_attr "type" "compare")])
;; Now define ways of moving data around.
@@ -6002,6 +6715,25 @@
DONE;
}")
+(define_expand "cmpdi"
+ [(set (cc0)
+ (compare (match_operand:DI 0 "gpc_reg_operand" "")
+ (match_operand:DI 1 "reg_or_short_operand" "")))]
+ "TARGET_POWERPC64"
+ "
+{
+ /* Take care of the possibility that operands[1] might be negative but
+ this might be a logical operation. That insn doesn't exist. */
+ if (GET_CODE (operands[1]) == CONST_INT
+ && INTVAL (operands[1]) < 0)
+ operands[1] = force_reg (DImode, operands[1]);
+
+ rs6000_compare_op0 = operands[0];
+ rs6000_compare_op1 = operands[1];
+ rs6000_compare_fp_p = 0;
+ DONE;
+}")
+
(define_expand "cmpsf"
[(set (cc0) (compare (match_operand:SF 0 "gpc_reg_operand" "")
(match_operand:SF 1 "gpc_reg_operand" "")))]
@@ -6319,6 +7051,14 @@
"{cmp%I2|cmpw%I2} %0,%1,%2"
[(set_attr "type" "compare")])
+(define_insn ""
+ [(set (match_operand:CC 0 "cc_reg_operand" "=y")
+ (compare:CC (match_operand:DI 1 "gpc_reg_operand" "r")
+ (match_operand:DI 2 "reg_or_short_operand" "rI")))]
+ "TARGET_POWERPC64"
+ "cmpd%I2 %0,%1,%2"
+ [(set_attr "type" "compare")])
+
;; If we are comparing a register for equality with a large constant,
;; we can do this with an XOR followed by a compare. But we need a scratch
;; register for the result of the XOR.
@@ -6355,6 +7095,14 @@
"{cmpl%I2|cmplw%I2} %0,%1,%W2"
[(set_attr "type" "compare")])
+(define_insn ""
+ [(set (match_operand:CCUNS 0 "cc_reg_operand" "=y")
+ (compare:CCUNS (match_operand:DI 1 "gpc_reg_operand" "r")
+ (match_operand:DI 2 "reg_or_u_short_operand" "rI")))]
+ ""
+ "cmpld%I2 %0,%1,%W2"
+ [(set_attr "type" "compare")])
+
;; The following two insns don't exist as single insns, but if we provide
;; them, we can swap an add and compare, which will enable us to overlap more
;; of the required delay between a compare and branch. We generate code for
@@ -7606,6 +8354,14 @@
{br|blr}"
[(set_attr "type" "jmpreg")])
+(define_insn ""
+ [(set (pc) (match_operand:DI 0 "register_operand" "c,l"))]
+ "TARGET_POWERPC64"
+ "@
+ bctr
+ {br|blr}"
+ [(set_attr "type" "jmpreg")])
+
;; Table jump for switch statements:
(define_expand "tablejump"
[(set (match_dup 3)
@@ -7630,6 +8386,16 @@
{br|blr}"
[(set_attr "type" "jmpreg")])
+(define_insn ""
+ [(set (pc)
+ (match_operand:DI 0 "register_operand" "c,l"))
+ (use (label_ref (match_operand 1 "" "")))]
+ "TARGET_POWERPC64"
+ "@
+ bctr
+ {br|blr}"
+ [(set_attr "type" "jmpreg")])
+
(define_insn "nop"
[(const_int 0)]
""