diff options
author | David Edelsohn <edelsohn@gnu.org> | 1996-01-22 19:12:22 +0000 |
---|---|---|
committer | David Edelsohn <edelsohn@gnu.org> | 1996-01-22 19:12:22 +0000 |
commit | 266eb58af385276cae6011361178c827f812e40f (patch) | |
tree | 382790b806b4e17f58fda855220b86cf0b6480d5 | |
parent | b73fd26c62b8c663b36f7953c4b35d60c07dbdcf (diff) | |
download | gcc-266eb58af385276cae6011361178c827f812e40f.zip gcc-266eb58af385276cae6011361178c827f812e40f.tar.gz gcc-266eb58af385276cae6011361178c827f812e40f.tar.bz2 |
PowerPC64 DImode patterns
From-SVN: r11080
-rw-r--r-- | gcc/config/rs6000/rs6000.md | 818 |
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)] "" |