--- gcc/config/alpha/alpha.md 2018/04/24 18:10:26 1.1.1.1 +++ gcc/config/alpha/alpha.md 2018/04/24 18:30:13 1.1.1.4 @@ -1,6 +1,6 @@ -;;- Machine description for DEC Alpha for GNU C compiler -;; Copyright (C) 1992 Free Software Foundation, Inc. -;; Contributed by Richard Kenner (kenner@nyu.edu) +;; Machine description for DEC Alpha for GNU C compiler +;; Copyright (C) 1992, 1993, 1994, 1995 Free Software Foundation, Inc. +;; Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu) ;; This file is part of GNU CC. @@ -16,7 +16,8 @@ ;; You should have received a copy of the GNU General Public License ;; along with GNU CC; see the file COPYING. If not, write to -;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +;; the Free Software Foundation, 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al. @@ -26,7 +27,7 @@ ;; separately. (define_attr "type" - "ld,st,ibr,fbr,jsr,iaddlog,shiftcm,icmp,imull,imulq,fpop,fdivs,fdivt,ldsym" + "ld,st,ibr,fbr,jsr,iaddlog,shiftcm,icmp,imull,imulq,fpop,fdivs,fdivt,ldsym,isubr" (const_string "shiftcm")) ;; We include four function units: ABOX, which computes the address, @@ -85,9 +86,25 @@ cvtql %1,%0\;cvtlq %0,%0" [(set_attr "type" "iaddlog,ld,fpop")]) -(define_insn "addsi3" +;; Do addsi3 the way expand_binop would do if we didn't have one. This +;; generates better code. We have the anonymous addsi3 pattern below in +;; case combine wants to make it. +(define_expand "addsi3" + [(set (match_operand:SI 0 "register_operand" "") + (plus:SI (match_operand:SI 1 "reg_or_0_operand" "") + (match_operand:SI 2 "add_operand" "")))] + "" + " +{ emit_insn (gen_rtx (SET, VOIDmode, gen_lowpart (DImode, operands[0]), + gen_rtx (PLUS, DImode, + gen_lowpart (DImode, operands[1]), + gen_lowpart (DImode, operands[2])))); + DONE; +} ") + +(define_insn "" [(set (match_operand:SI 0 "register_operand" "=r,r,r,r") - (plus:SI (match_operand:SI 1 "reg_or_0_operand" "%rJ,%rJ,%rJ,%rJ") + (plus:SI (match_operand:SI 1 "reg_or_0_operand" "%rJ,rJ,rJ,rJ") (match_operand:SI 2 "add_operand" "rI,O,K,L")))] "" "@ @@ -149,9 +166,27 @@ operands[5] = GEN_INT (mult); }") +(define_split + [(set (match_operand:DI 0 "register_operand" "") + (sign_extend:DI + (plus:SI (match_operator:SI 1 "comparison_operator" + [(match_operand 2 "" "") + (match_operand 3 "" "")]) + (match_operand:SI 4 "add_operand" "")))) + (clobber (match_operand:DI 5 "register_operand" ""))] + "" + [(set (match_dup 5) (match_dup 6)) + (set (match_dup 0) (sign_extend:DI (plus:SI (match_dup 7) (match_dup 4))))] + " +{ + operands[6] = gen_rtx (GET_CODE (operands[1]), DImode, + operands[2], operands[3]); + operands[7] = gen_lowpart (SImode, operands[5]); +}") + (define_insn "adddi3" [(set (match_operand:DI 0 "register_operand" "=r,r,r,r") - (plus:DI (match_operand:DI 1 "reg_or_0_operand" "%rJ,%rJ,%rJ,%rJ") + (plus:DI (match_operand:DI 1 "reg_or_0_operand" "%rJ,rJ,rJ,rJ") (match_operand:DI 2 "add_operand" "rI,O,K,L")))] "" "@ @@ -204,6 +239,27 @@ s%2subl %r1,%n3,%0" [(set_attr "type" "iaddlog")]) +(define_split + [(set (match_operand:DI 0 "register_operand" "") + (sign_extend:DI + (plus:SI (mult:SI (match_operator:SI 1 "comparison_operator" + [(match_operand 2 "" "") + (match_operand 3 "" "")]) + (match_operand:SI 4 "const48_operand" "")) + (match_operand:SI 5 "add_operand" "")))) + (clobber (match_operand:DI 6 "register_operand" ""))] + "" + [(set (match_dup 6) (match_dup 7)) + (set (match_dup 0) + (sign_extend:DI (plus:SI (mult:SI (match_dup 8) (match_dup 4)) + (match_dup 5))))] + " +{ + operands[7] = gen_rtx (GET_CODE (operands[1]), DImode, + operands[2], operands[3]); + operands[8] = gen_lowpart (SImode, operands[6]); +}") + (define_insn "" [(set (match_operand:DI 0 "register_operand" "=r,r") (plus:DI (mult:DI (match_operand:DI 1 "reg_or_0_operand" "rJ,rJ") @@ -220,37 +276,96 @@ ;; seem to be a way around it. Only recognize them while reloading. (define_insn "" - [(set (match_operand:SI 0 "register_operand" "=&r") - (plus:SI (plus:SI (mult:SI (match_operand:SI 1 "reg_or_0_operand" "rJ") + [(set (match_operand:DI 0 "some_operand" "=&r") + (plus:DI (plus:DI (match_operand:DI 1 "some_operand" "r") + (match_operand:DI 2 "some_operand" "r")) + (match_operand:DI 3 "some_operand" "rIOKL")))] + "reload_in_progress" + "#" + [(set_attr "type" "iaddlog")]) + +(define_split + [(set (match_operand:DI 0 "register_operand" "") + (plus:DI (plus:DI (match_operand:DI 1 "register_operand" "") + (match_operand:DI 2 "register_operand" "")) + (match_operand:DI 3 "add_operand" "")))] + "reload_completed" + [(set (match_dup 0) (plus:DI (match_dup 1) (match_dup 2))) + (set (match_dup 0) (plus:DI (match_dup 0) (match_dup 3)))] + "") + +(define_insn "" + [(set (match_operand:SI 0 "some_operand" "=&r") + (plus:SI (plus:SI (mult:SI (match_operand:SI 1 "some_operand" "rJ") (match_operand:SI 2 "const48_operand" "I")) - (match_operand:SI 3 "register_operand" "r")) - (match_operand:SI 4 "const_int_operand" "rI")))] + (match_operand:SI 3 "some_operand" "r")) + (match_operand:SI 4 "some_operand" "rIOKL")))] "reload_in_progress" - "s%2addl %r1,%3,%0\;addl %0,%4,%0" + "#" [(set_attr "type" "iaddlog")]) +(define_split + [(set (match_operand:SI 0 "register_operand" "r") + (plus:SI (plus:SI (mult:SI (match_operand:SI 1 "reg_or_0_operand" "") + (match_operand:SI 2 "const48_operand" "")) + (match_operand:SI 3 "register_operand" "")) + (match_operand:SI 4 "add_operand" "rIOKL")))] + "reload_completed" + [(set (match_dup 0) + (plus:SI (mult:SI (match_dup 1) (match_dup 2)) (match_dup 3))) + (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 4)))] + "") + (define_insn "" - [(set (match_operand:DI 0 "register_operand" "=&r") + [(set (match_operand:DI 0 "some_operand" "=&r") (sign_extend:DI (plus:SI (plus:SI - (mult:SI (match_operand:SI 1 "reg_or_0_operand" "rJ") + (mult:SI (match_operand:SI 1 "some_operand" "rJ") (match_operand:SI 2 "const48_operand" "I")) - (match_operand:SI 3 "register_operand" "r")) - (match_operand:SI 4 "const_int_operand" "rI"))))] + (match_operand:SI 3 "some_operand" "r")) + (match_operand:SI 4 "some_operand" "rIOKL"))))] "reload_in_progress" - "s%2addl %r1,%3,%0\;addl %0,%4,%0" + "#" [(set_attr "type" "iaddlog")]) +(define_split + [(set (match_operand:DI 0 "register_operand" "") + (sign_extend:DI + (plus:SI (plus:SI + (mult:SI (match_operand:SI 1 "reg_or_0_operand" "") + (match_operand:SI 2 "const48_operand" "")) + (match_operand:SI 3 "register_operand" "")) + (match_operand:SI 4 "add_operand" ""))))] + "reload_completed" + [(set (match_dup 5) + (plus:SI (mult:SI (match_dup 1) (match_dup 2)) (match_dup 3))) + (set (match_dup 0) (sign_extend:DI (plus:SI (match_dup 5) (match_dup 4))))] + " +{ operands[5] = gen_lowpart (SImode, operands[0]); +}") + (define_insn "" - [(set (match_operand:DI 0 "register_operand" "=&r") - (plus:DI (plus:DI (mult:DI (match_operand:DI 1 "reg_or_0_operand" "rJ") + [(set (match_operand:DI 0 "some_operand" "=&r") + (plus:DI (plus:DI (mult:DI (match_operand:DI 1 "some_operand" "rJ") (match_operand:DI 2 "const48_operand" "I")) - (match_operand:DI 3 "register_operand" "r")) - (match_operand:DI 4 "const_int_operand" "rI")))] + (match_operand:DI 3 "some_operand" "r")) + (match_operand:DI 4 "some_operand" "rIOKL")))] "reload_in_progress" - "s%2addq %r1,%3,%0\;addq %0,%4,%0" + "#" [(set_attr "type" "iaddlog")]) +(define_split + [(set (match_operand:DI 0 "register_operand" "=") + (plus:DI (plus:DI (mult:DI (match_operand:DI 1 "reg_or_0_operand" "") + (match_operand:DI 2 "const48_operand" "")) + (match_operand:DI 3 "register_operand" "")) + (match_operand:DI 4 "add_operand" "")))] + "reload_completed" + [(set (match_dup 0) + (plus:DI (mult:DI (match_dup 1) (match_dup 2)) (match_dup 3))) + (set (match_dup 0) (plus:DI (match_dup 0) (match_dup 4)))] + "") + (define_insn "negsi2" [(set (match_operand:SI 0 "register_operand" "=r") (neg:SI (match_operand:SI 1 "reg_or_8bit_operand" "rI")))] @@ -273,7 +388,21 @@ "subq $31,%1,%0" [(set_attr "type" "iaddlog")]) -(define_insn "subsi3" +(define_expand "subsi3" + [(set (match_operand:SI 0 "register_operand" "") + (minus:SI (match_operand:SI 1 "reg_or_0_operand" "") + (match_operand:SI 2 "reg_or_8bit_operand" "")))] + "" + " +{ emit_insn (gen_rtx (SET, VOIDmode, gen_lowpart (DImode, operands[0]), + gen_rtx (MINUS, DImode, + gen_lowpart (DImode, operands[1]), + gen_lowpart (DImode, operands[2])))); + DONE; + +} ") + +(define_insn "" [(set (match_operand:SI 0 "register_operand" "=r") (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rJ") (match_operand:SI 2 "reg_or_8bit_operand" "rI")))] @@ -328,173 +457,155 @@ (define_insn "mulsi3" [(set (match_operand:SI 0 "register_operand" "=r") (mult:SI (match_operand:SI 1 "reg_or_0_operand" "%rJ") - (match_operand:SI 2 "reg_or_8bit_operand" "rI")))] + (match_operand:SI 2 "reg_or_0_operand" "rJ")))] "" - "mull %r1,%2,%0" + "mull %r1,%r2,%0" [(set_attr "type" "imull")]) (define_insn "" [(set (match_operand:DI 0 "register_operand" "=r") (sign_extend:DI (mult:SI (match_operand:SI 1 "reg_or_0_operand" "%rJ") - (match_operand:SI 2 "reg_or_8bit_operand" "rI"))))] + (match_operand:SI 2 "reg_or_0_operand" "rJ"))))] "" - "mull %r1,%2,%0" + "mull %r1,%r2,%0" [(set_attr "type" "imull")]) (define_insn "muldi3" [(set (match_operand:DI 0 "register_operand" "=r") (mult:DI (match_operand:DI 1 "reg_or_0_operand" "%rJ") - (match_operand:DI 2 "reg_or_8bit_operand" "rI")))] + (match_operand:DI 2 "reg_or_0_operand" "rJ")))] + "" + "mulq %r1,%r2,%0" + [(set_attr "type" "imulq")]) + +(define_insn "umuldi3_highpart" + [(set (match_operand:DI 0 "register_operand" "=r") + (truncate:DI + (lshiftrt:TI + (mult:TI (zero_extend:TI (match_operand:DI 1 "register_operand" "r")) + (zero_extend:TI (match_operand:DI 2 "register_operand" "r"))) + (const_int 64))))] + "" + "umulh %1,%2,%0" + [(set_attr "type" "imulq")]) + +(define_insn "" + [(set (match_operand:DI 0 "register_operand" "=r") + (truncate:DI + (lshiftrt:TI + (mult:TI (zero_extend:TI (match_operand:DI 1 "register_operand" "r")) + (match_operand:TI 2 "cint8_operand" "I")) + (const_int 64))))] "" - "mulq %r1,%2,%0" + "umulh %1,%2,%0" [(set_attr "type" "imulq")]) ;; The divide and remainder operations always take their inputs from ;; r24 and r25, put their output in r27, and clobber r23 and r28. (define_expand "divsi3" - [(parallel [(set (reg:SI 27) - (div:SI (match_operand:SI 1 "general_operand" "") - (match_operand:SI 2 "general_operand" ""))) + [(set (reg:SI 24) (match_operand:SI 1 "input_operand" "")) + (set (reg:SI 25) (match_operand:SI 2 "input_operand" "")) + (parallel [(set (reg:SI 27) + (div:SI (reg:SI 24) + (reg:SI 25))) (clobber (reg:DI 23)) (clobber (reg:DI 28))]) (set (match_operand:SI 0 "general_operand" "") (reg:SI 27))] "" - " -{ rtx in0 = gen_rtx (REG, SImode, 24); - rtx in1 = gen_rtx (REG, SImode, 25); - - emit_move_insn (in0, operands[1]); - emit_move_insn (in1, operands[2]); - operands[1] = in0, operands[2] = in1; -}") + "") (define_expand "udivsi3" - [(parallel [(set (reg:SI 27) - (udiv:SI (match_operand:SI 1 "general_operand" "") - (match_operand:SI 2 "general_operand" ""))) + [(set (reg:SI 24) (match_operand:SI 1 "input_operand" "")) + (set (reg:SI 25) (match_operand:SI 2 "input_operand" "")) + (parallel [(set (reg:SI 27) + (udiv:SI (reg:SI 24) + (reg:SI 25))) (clobber (reg:DI 23)) (clobber (reg:DI 28))]) (set (match_operand:SI 0 "general_operand" "") (reg:SI 27))] "" - " -{ rtx in0 = gen_rtx (REG, SImode, 24); - rtx in1 = gen_rtx (REG, SImode, 25); - - emit_move_insn (in0, operands[1]); - emit_move_insn (in1, operands[2]); - operands[1] = in0, operands[2] = in1; -}") + "") (define_expand "modsi3" - [(parallel [(set (reg:SI 27) - (mod:SI (match_operand:SI 1 "general_operand" "") - (match_operand:SI 2 "general_operand" ""))) + [(set (reg:SI 24) (match_operand:SI 1 "input_operand" "")) + (set (reg:SI 25) (match_operand:SI 2 "input_operand" "")) + (parallel [(set (reg:SI 27) + (mod:SI (reg:SI 24) + (reg:SI 25))) (clobber (reg:DI 23)) (clobber (reg:DI 28))]) (set (match_operand:SI 0 "general_operand" "") (reg:SI 27))] "" - " -{ rtx in0 = gen_rtx (REG, SImode, 24); - rtx in1 = gen_rtx (REG, SImode, 25); - - emit_move_insn (in0, operands[1]); - emit_move_insn (in1, operands[2]); - operands[1] = in0, operands[2] = in1; -}") + "") (define_expand "umodsi3" - [(parallel [(set (reg:SI 27) - (umod:SI (match_operand:SI 1 "general_operand" "") - (match_operand:SI 2 "general_operand" ""))) + [(set (reg:SI 24) (match_operand:SI 1 "input_operand" "")) + (set (reg:SI 25) (match_operand:SI 2 "input_operand" "")) + (parallel [(set (reg:SI 27) + (umod:SI (reg:SI 24) + (reg:SI 25))) (clobber (reg:DI 23)) (clobber (reg:DI 28))]) (set (match_operand:SI 0 "general_operand" "") (reg:SI 27))] "" - " -{ rtx in0 = gen_rtx (REG, SImode, 24); - rtx in1 = gen_rtx (REG, SImode, 25); - - emit_move_insn (in0, operands[1]); - emit_move_insn (in1, operands[2]); - operands[1] = in0, operands[2] = in1; -}") + "") (define_expand "divdi3" - [(parallel [(set (reg:DI 27) - (div:DI (match_operand:DI 1 "general_operand" "") - (match_operand:DI 2 "general_operand" ""))) + [(set (reg:DI 24) (match_operand:DI 1 "input_operand" "")) + (set (reg:DI 25) (match_operand:DI 2 "input_operand" "")) + (parallel [(set (reg:DI 27) + (div:DI (reg:DI 24) + (reg:DI 25))) (clobber (reg:DI 23)) (clobber (reg:DI 28))]) (set (match_operand:DI 0 "general_operand" "") (reg:DI 27))] "" - " -{ rtx in0 = gen_rtx (REG, DImode, 24); - rtx in1 = gen_rtx (REG, DImode, 25); - - emit_move_insn (in0, operands[1]); - emit_move_insn (in1, operands[2]); - operands[1] = in0, operands[2] = in1; -}") + "") (define_expand "udivdi3" - [(parallel [(set (reg:DI 27) - (udiv:DI (match_operand:DI 1 "general_operand" "") - (match_operand:DI 2 "general_operand" ""))) + [(set (reg:DI 24) (match_operand:DI 1 "input_operand" "")) + (set (reg:DI 25) (match_operand:DI 2 "input_operand" "")) + (parallel [(set (reg:DI 27) + (udiv:DI (reg:DI 24) + (reg:DI 25))) (clobber (reg:DI 23)) (clobber (reg:DI 28))]) (set (match_operand:DI 0 "general_operand" "") (reg:DI 27))] "" - " -{ rtx in0 = gen_rtx (REG, DImode, 24); - rtx in1 = gen_rtx (REG, DImode, 25); - - emit_move_insn (in0, operands[1]); - emit_move_insn (in1, operands[2]); - operands[1] = in0, operands[2] = in1; -}") + "") (define_expand "moddi3" - [(parallel [(set (reg:DI 27) - (mod:DI (match_operand:DI 1 "general_operand" "") - (match_operand:DI 2 "general_operand" ""))) + [(set (reg:DI 24) (match_operand:DI 1 "input_operand" "")) + (set (reg:DI 25) (match_operand:DI 2 "input_operand" "")) + (parallel [(set (reg:DI 27) + (mod:DI (reg:DI 24) + (reg:DI 25))) (clobber (reg:DI 23)) (clobber (reg:DI 28))]) (set (match_operand:DI 0 "general_operand" "") (reg:DI 27))] "" - " -{ rtx in0 = gen_rtx (REG, DImode, 24); - rtx in1 = gen_rtx (REG, DImode, 25); - - emit_move_insn (in0, operands[1]); - emit_move_insn (in1, operands[2]); - operands[1] = in0, operands[2] = in1; -}") + "") (define_expand "umoddi3" - [(parallel [(set (reg:DI 27) - (umod:DI (match_operand:DI 1 "general_operand" "") - (match_operand:DI 2 "general_operand" ""))) + [(set (reg:DI 24) (match_operand:DI 1 "input_operand" "")) + (set (reg:DI 25) (match_operand:DI 2 "input_operand" "")) + (parallel [(set (reg:DI 27) + (umod:DI (reg:DI 24) + (reg:DI 25))) (clobber (reg:DI 23)) (clobber (reg:DI 28))]) (set (match_operand:DI 0 "general_operand" "") (reg:DI 27))] "" - " -{ rtx in0 = gen_rtx (REG, DImode, 24); - rtx in1 = gen_rtx (REG, DImode, 25); - - emit_move_insn (in0, operands[1]); - emit_move_insn (in1, operands[2]); - operands[1] = in0, operands[2] = in1; -}") + "") (define_insn "" [(set (reg:SI 27) @@ -503,7 +614,8 @@ (clobber (reg:DI 23)) (clobber (reg:DI 28))] "" - "%E1 $24,$25,$27") + "%E1 $24,$25,$27" + [(set_attr "type" "isubr")]) (define_insn "" [(set (reg:DI 27) @@ -512,7 +624,8 @@ (clobber (reg:DI 23)) (clobber (reg:DI 28))] "" - "%E1 $24,$25,$27") + "%E1 $24,$25,$27" + [(set_attr "type" "isubr")]) ;; Next are the basic logical operations. These only exist in DImode. @@ -609,11 +722,13 @@ [(set_attr "type" "iaddlog")]) (define_insn "iordi3" - [(set (match_operand:DI 0 "register_operand" "=r") - (ior:DI (match_operand:DI 1 "reg_or_0_operand" "%rJ") - (match_operand:DI 2 "reg_or_8bit_operand" "rI")))] + [(set (match_operand:DI 0 "register_operand" "=r,r") + (ior:DI (match_operand:DI 1 "reg_or_0_operand" "%rJ,rJ") + (match_operand:DI 2 "or_operand" "rI,N")))] "" - "bis %r1,%2,%0" + "@ + bis %r1,%2,%0 + ornot %r1,%N2,%0" [(set_attr "type" "iaddlog")]) (define_insn "one_cmpldi2" @@ -632,17 +747,19 @@ [(set_attr "type" "iaddlog")]) (define_insn "xordi3" - [(set (match_operand:DI 0 "register_operand" "=r") - (xor:DI (match_operand:DI 1 "reg_or_0_operand" "rJ") - (match_operand:DI 2 "reg_or_8bit_operand" "rI")))] + [(set (match_operand:DI 0 "register_operand" "=r,r") + (xor:DI (match_operand:DI 1 "reg_or_0_operand" "%rJ,rJ") + (match_operand:DI 2 "or_operand" "rI,N")))] "" - "xor %r1,%2,%0" + "@ + xor %r1,%2,%0 + eqv %r1,%N2,%0" [(set_attr "type" "iaddlog")]) (define_insn "" [(set (match_operand:DI 0 "register_operand" "=r") - (not:DI (xor:DI (match_operand:DI 1 "reg_or_0_operand" "rJ") - (match_operand:DI 2 "reg_or_8bit_operand" "rI"))))] + (not:DI (xor:DI (match_operand:DI 1 "register_operand" "%rJ") + (match_operand:DI 2 "register_operand" "rI"))))] "" "eqv %r1,%2,%0" [(set_attr "type" "iaddlog")]) @@ -652,7 +769,7 @@ (define_insn "ashldi3" [(set (match_operand:DI 0 "register_operand" "=r,r") (ashift:DI (match_operand:DI 1 "reg_or_0_operand" "rJ,rJ") - (match_operand:DI 2 "reg_or_8bit_operand" "P,rI")))] + (match_operand:DI 2 "reg_or_6bit_operand" "P,rI")))] "" "* { @@ -669,40 +786,36 @@ }" [(set_attr "type" "iaddlog,shiftcm")]) -;; This is the same as (sign_extend (shift X [123])). -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=r") - (ashiftrt:DI (ashift:DI (match_operand:DI 1 "reg_or_0_operand" "rJ") - (match_operand:DI 2 "const_int_operand" "i")) - (const_int 32)))] - "INTVAL (operands[2]) >= 33 && INTVAL (operands[2]) <= 35" - "* -{ - switch (INTVAL (operands[2])) - { - case 33: - return \"addl %r1,%r1,%0\"; - case 34: - return \"s4addl %r1,0,%0\"; - case 35: - return \"s8addl %r1,0,%0\"; - default: - abort (); - } -}" - [(set_attr "type" "iaddlog")]) +;; ??? The following pattern is made by combine, but earlier phases +;; (specifically flow) can't handle it. This occurs in jump.c. Deal +;; with this in a better way at some point. +;;(define_insn "" +;; [(set (match_operand:DI 0 "register_operand" "=r") +;; (sign_extend:DI +;; (subreg:SI (ashift:DI (match_operand:DI 1 "reg_or_0_operand" "rJ") +;; (match_operand:DI 2 "const_int_operand" "P")) +;; 0)))] +;; "INTVAL (operands[2]) >= 1 && INTVAL (operands[2]) <= 3" +;; "* +;;{ +;; if (operands[2] == const1_rtx) +;; return \"addl %r1,%r1,%0\"; +;; else +;; return \"s%P2addl %r1,0,%0\"; +;; }" +;; [(set_attr "type" "iaddlog")]) (define_insn "lshrdi3" [(set (match_operand:DI 0 "register_operand" "=r") (lshiftrt:DI (match_operand:DI 1 "reg_or_0_operand" "rJ") - (match_operand:DI 2 "reg_or_8bit_operand" "rI")))] + (match_operand:DI 2 "reg_or_6bit_operand" "rI")))] "" "srl %r1,%2,%0") (define_insn "ashrdi3" [(set (match_operand:DI 0 "register_operand" "=r") (ashiftrt:DI (match_operand:DI 1 "reg_or_0_operand" "rJ") - (match_operand:DI 2 "reg_or_8bit_operand" "rI")))] + (match_operand:DI 2 "reg_or_6bit_operand" "rI")))] "" "sra %r1,%2,%0") @@ -909,10 +1022,11 @@ (define_insn "" [(set (match_operand:DI 0 "register_operand" "=r") - (and:DI (ashift:DI - (match_operand:DI 2 "mode_mask_operand" "n") - (ashift:DI (match_operand:DI 3 "reg_or_8bit_operand" "rI") - (const_int 3))) + (and:DI (not:DI (ashift:DI + (match_operand:DI 2 "mode_mask_operand" "n") + (ashift:DI + (match_operand:DI 3 "reg_or_8bit_operand" "rI") + (const_int 3)))) (match_operand:DI 1 "reg_or_0_operand" "rJ")))] "" "msk%U2l %r1,%3,%0") @@ -942,14 +1056,14 @@ [(set (match_operand:SF 0 "register_operand" "=f") (neg:SF (match_operand:SF 1 "reg_or_fp0_operand" "fG")))] "TARGET_FP" - "cpysn %1,%R1,%0" + "cpysn %R1,%R1,%0" [(set_attr "type" "fpop")]) (define_insn "negdf2" [(set (match_operand:DF 0 "register_operand" "=f") (neg:DF (match_operand:DF 1 "reg_or_fp0_operand" "fG")))] "TARGET_FP" - "cpysn %1,%R1,%0" + "cpysn %R1,%R1,%0" [(set_attr "type" "fpop")]) (define_insn "addsf3" @@ -971,7 +1085,7 @@ (define_insn "" [(set (match_operand:DF 0 "register_operand" "=f") (plus:DF (float_extend:DF - (match_operand:SF 1 "reg_or_fp0_operand" "%fG")) + (match_operand:SF 1 "reg_or_fp0_operand" "fG")) (match_operand:DF 2 "reg_or_fp0_operand" "fG")))] "TARGET_FP" "addt %R1,%R2,%0" @@ -1075,7 +1189,7 @@ (define_insn "mulsf3" [(set (match_operand:SF 0 "register_operand" "=f") - (mult:SF (match_operand:SF 1 "reg_or_fp0_operand" "fG") + (mult:SF (match_operand:SF 1 "reg_or_fp0_operand" "%fG") (match_operand:SF 2 "reg_or_fp0_operand" "fG")))] "TARGET_FP" "muls %R1,%R2,%0" @@ -1083,7 +1197,7 @@ (define_insn "muldf3" [(set (match_operand:DF 0 "register_operand" "=f") - (mult:DF (match_operand:DF 1 "reg_or_fp0_operand" "fG") + (mult:DF (match_operand:DF 1 "reg_or_fp0_operand" "%fG") (match_operand:DF 2 "reg_or_fp0_operand" "fG")))] "TARGET_FP" "mult %R1,%R2,%0" @@ -1101,7 +1215,7 @@ (define_insn "" [(set (match_operand:DF 0 "register_operand" "=f") (mult:DF (float_extend:DF - (match_operand:SF 1 "reg_or_fp0_operand" "fG")) + (match_operand:SF 1 "reg_or_fp0_operand" "%fG")) (float_extend:DF (match_operand:SF 2 "reg_or_fp0_operand" "fG"))))] "TARGET_FP" @@ -1110,7 +1224,7 @@ (define_insn "subsf3" [(set (match_operand:SF 0 "register_operand" "=f") - (minus:SF (match_operand:SF 1 "reg_or_fp0_operand" "%fG") + (minus:SF (match_operand:SF 1 "reg_or_fp0_operand" "fG") (match_operand:SF 2 "reg_or_fp0_operand" "fG")))] "TARGET_FP" "subs %R1,%R2,%0" @@ -1118,7 +1232,7 @@ (define_insn "subdf3" [(set (match_operand:DF 0 "register_operand" "=f") - (minus:DF (match_operand:DF 1 "reg_or_fp0_operand" "%fG") + (minus:DF (match_operand:DF 1 "reg_or_fp0_operand" "fG") (match_operand:DF 2 "reg_or_fp0_operand" "fG")))] "TARGET_FP" "subt %R1,%R2,%0" @@ -1127,7 +1241,7 @@ (define_insn "" [(set (match_operand:DF 0 "register_operand" "=f") (minus:DF (float_extend:DF - (match_operand:SF 1 "reg_or_fp0_operand" "%fG")) + (match_operand:SF 1 "reg_or_fp0_operand" "fG")) (match_operand:DF 2 "reg_or_fp0_operand" "fG")))] "TARGET_FP" "subt %R1,%R2,%0" @@ -1135,7 +1249,7 @@ (define_insn "" [(set (match_operand:DF 0 "register_operand" "=f") - (minus:DF (match_operand:DF 1 "reg_or_fp0_operand" "%fG") + (minus:DF (match_operand:DF 1 "reg_or_fp0_operand" "fG") (float_extend:DF (match_operand:SF 2 "reg_or_fp0_operand" "fG"))))] "TARGET_FP" @@ -1145,7 +1259,7 @@ (define_insn "" [(set (match_operand:DF 0 "register_operand" "=f") (minus:DF (float_extend:DF - (match_operand:SF 1 "reg_or_fp0_operand" "%fG")) + (match_operand:SF 1 "reg_or_fp0_operand" "fG")) (float_extend:DF (match_operand:SF 2 "reg_or_fp0_operand" "fG"))))] "TARGET_FP" @@ -1191,18 +1305,38 @@ "cmple $31,%1,%0" [(set_attr "type" "icmp")]) +;; This pattern exists so conditional moves of SImode values are handled. +;; Comparisons are still done in DImode though. + (define_insn "" - [(set (match_operand:DI 0 "register_operand" "=r,r") + [(set (match_operand:SI 0 "register_operand" "=r,r,r,r") (if_then_else:DI (match_operator 2 "signed_comparison_operator" - [(match_operand:DI 3 "reg_or_0_operand" "rJ,rJ") - (const_int 0)]) - (match_operand:DI 1 "reg_or_8bit_operand" "rI,0") - (match_operand:DI 4 "reg_or_8bit_operand" "0,rI")))] - "" + [(match_operand:DI 3 "reg_or_0_operand" "rJ,rJ,J,J") + (match_operand:DI 4 "reg_or_0_operand" "J,J,rJ,rJ")]) + (match_operand:SI 1 "reg_or_8bit_operand" "rI,0,rI,0") + (match_operand:SI 5 "reg_or_8bit_operand" "0,rI,0,rI")))] + "operands[3] == const0_rtx || operands[4] == const0_rtx" + "@ + cmov%C2 %r3,%1,%0 + cmov%D2 %r3,%5,%0 + cmov%c2 %r4,%1,%0 + cmov%d2 %r4,%5,%0") + +(define_insn "" + [(set (match_operand:DI 0 "register_operand" "=r,r,r,r") + (if_then_else:DI + (match_operator 2 "signed_comparison_operator" + [(match_operand:DI 3 "reg_or_0_operand" "rJ,rJ,J,J") + (match_operand:DI 4 "reg_or_0_operand" "J,J,rJ,rJ")]) + (match_operand:DI 1 "reg_or_8bit_operand" "rI,0,rI,0") + (match_operand:DI 5 "reg_or_8bit_operand" "0,rI,0,rI")))] + "operands[3] == const0_rtx || operands[4] == const0_rtx" "@ cmov%C2 %r3,%1,%0 - cmov%D2 %r3,%4,%0") + cmov%D2 %r3,%5,%0 + cmov%c2 %r4,%1,%0 + cmov%d2 %r4,%5,%0") (define_insn "" [(set (match_operand:DI 0 "register_operand" "=r,r") @@ -1366,7 +1500,7 @@ (match_dup 0) (match_dup 1)))] "") -(define_expand "maxdi3" +(define_expand "smaxdi3" [(set (match_dup 3) (le:DI (match_operand:DI 1 "reg_or_0_operand" "") (match_operand:DI 2 "reg_or_8bit_operand" ""))) @@ -1671,11 +1805,12 @@ (le:DF (match_operand:DF 1 "reg_or_fp0_operand" "") (match_operand:DF 2 "reg_or_fp0_operand" ""))) (set (match_operand:DF 0 "register_operand" "") - (if_then_else:DF (eq (match_dup 3) (const_int 0)) + (if_then_else:DF (eq (match_dup 3) (match_dup 4)) (match_dup 1) (match_dup 2)))] "TARGET_FP" " { operands[3] = gen_reg_rtx (DFmode); + operands[4] = CONST0_RTX (DFmode); }") (define_expand "mindf3" @@ -1683,35 +1818,38 @@ (lt:DF (match_operand:DF 1 "reg_or_fp0_operand" "") (match_operand:DF 2 "reg_or_fp0_operand" ""))) (set (match_operand:DF 0 "register_operand" "") - (if_then_else:DF (ne (match_dup 3) (const_int 0)) + (if_then_else:DF (ne (match_dup 3) (match_dup 4)) (match_dup 1) (match_dup 2)))] "TARGET_FP" " { operands[3] = gen_reg_rtx (DFmode); + operands[4] = CONST0_RTX (DFmode); }") (define_expand "maxsf3" [(set (match_dup 3) - (le:DF (match_operand:SF 1 "reg_or_fp0_operand" "") + (le:DF (float_extend:DF (match_operand:SF 1 "reg_or_fp0_operand" "")) (float_extend:DF (match_operand:SF 2 "reg_or_fp0_operand" "")))) (set (match_operand:SF 0 "register_operand" "") - (if_then_else:SF (eq (match_dup 3) (const_int 0)) + (if_then_else:SF (eq (match_dup 3) (match_dup 4)) (match_dup 1) (match_dup 2)))] "TARGET_FP" " -{ operands[3] = gen_reg_rtx (SFmode); +{ operands[3] = gen_reg_rtx (DFmode); + operands[4] = CONST0_RTX (DFmode); }") (define_expand "minsf3" [(set (match_dup 3) - (lt:DF (match_operand:SF 1 "reg_or_fp0_operand" "") + (lt:DF (float_extend:DF (match_operand:SF 1 "reg_or_fp0_operand" "")) (float_extend:DF (match_operand:SF 2 "reg_or_fp0_operand" "")))) (set (match_operand:SF 0 "register_operand" "") - (if_then_else:SF (ne (match_dup 3) (const_int 0)) + (if_then_else:SF (ne (match_dup 3) (match_dup 4)) (match_dup 1) (match_dup 2)))] "TARGET_FP" " -{ operands[3] = gen_reg_rtx (SFmode); +{ operands[3] = gen_reg_rtx (DFmode); + operands[4] = CONST0_RTX (DFmode); }") (define_insn "" @@ -1745,7 +1883,7 @@ (define_expand "cmpdf" [(set (cc0) (compare (match_operand:DF 0 "reg_or_fp0_operand" "") (match_operand:DF 1 "reg_or_fp0_operand" "")))] - "" + "TARGET_FP" " { alpha_compare_op0 = operands[0]; @@ -2085,6 +2223,182 @@ alpha_compare_op0); }") +;; These are the main define_expand's used to make conditional moves. + +(define_expand "movsicc" + [(set (match_dup 4) (match_operand 1 "comparison_operator" "")) + (set (match_operand:SI 0 "register_operand" "") + (if_then_else:DI (match_dup 5) + (match_operand:SI 2 "reg_or_8bit_operand" "") + (match_operand:SI 3 "reg_or_8bit_operand" "")))] + "" + " +{ + rtx op0,op1; + enum rtx_code code = GET_CODE (operands[1]), code2 = NE; + + if (alpha_compare_fp_p) + FAIL; + switch (code) + { + case EQ: case LE: case LT: + op0 = alpha_compare_op0; + op1 = alpha_compare_op1; + break; + case NE: + code = code2 = EQ; + op0 = alpha_compare_op0; + op1 = alpha_compare_op1; + break; + case GE: + code = LE; + op0 = force_reg (DImode, alpha_compare_op1); + op1 = alpha_compare_op0; + break; + case GT: + code = LT; + op0 = force_reg (DImode, alpha_compare_op1); + op1 = alpha_compare_op0; + break; + default: + FAIL; + } + operands[1] = gen_rtx (code, DImode, op0, op1); + operands[4] = gen_reg_rtx (DImode); + operands[5] = gen_rtx (code2, VOIDmode, operands[4], CONST0_RTX (DImode)); +}") + +(define_expand "movdicc" + [(set (match_dup 4) (match_operand 1 "comparison_operator" "")) + (set (match_operand:DI 0 "register_operand" "") + (if_then_else:DI (match_dup 5) + (match_operand:DI 2 "reg_or_8bit_operand" "") + (match_operand:DI 3 "reg_or_8bit_operand" "")))] + "" + " +{ + rtx op0,op1; + enum rtx_code code = GET_CODE (operands[1]), code2 = NE; + + if (alpha_compare_fp_p) + FAIL; + switch (code) + { + case EQ: case LE: case LT: + op0 = alpha_compare_op0; + op1 = alpha_compare_op1; + break; + case NE: + code = code2 = EQ; + op0 = alpha_compare_op0; + op1 = alpha_compare_op1; + break; + case GE: + code = LE; + op0 = force_reg (DImode, alpha_compare_op1); + op1 = alpha_compare_op0; + break; + case GT: + code = LT; + op0 = force_reg (DImode, alpha_compare_op1); + op1 = alpha_compare_op0; + break; + default: + FAIL; + } + operands[1] = gen_rtx (code, DImode, op0, op1); + operands[4] = gen_reg_rtx (DImode); + operands[5] = gen_rtx (code2, VOIDmode, operands[4], CONST0_RTX (DImode)); +}") + +(define_expand "movsfcc" + [(set (match_dup 4) (match_operand 1 "comparison_operator" "")) + (set (match_operand:SF 0 "register_operand" "") + (if_then_else:SF (match_dup 5) + (match_operand:SF 2 "reg_or_fp0_operand" "") + (match_operand:SF 3 "reg_or_fp0_operand" "")))] + "" + " +{ + rtx op0,op1; + enum rtx_code code = GET_CODE (operands[1]), code2 = NE; + + if (!alpha_compare_fp_p) + FAIL; + switch (code) + { + case EQ: case LE: case LT: + op0 = alpha_compare_op0; + op1 = alpha_compare_op1; + break; + case NE: + /* There isn't a cmptne insn. */ + code = code2 = EQ; + op0 = alpha_compare_op0; + op1 = alpha_compare_op1; + break; + case GE: + code = LE; + op0 = force_reg (DFmode, alpha_compare_op1); + op1 = alpha_compare_op0; + break; + case GT: + code = LT; + op0 = force_reg (DFmode, alpha_compare_op1); + op1 = alpha_compare_op0; + break; + default: + FAIL; + } + operands[1] = gen_rtx (code, DFmode, op0, op1); + operands[4] = gen_reg_rtx (DFmode); + operands[5] = gen_rtx (code2, VOIDmode, operands[4], CONST0_RTX (DFmode)); +}") + +(define_expand "movdfcc" + [(set (match_dup 4) (match_operand 1 "comparison_operator" "")) + (set (match_operand:DF 0 "register_operand" "") + (if_then_else:DF (match_dup 5) + (match_operand:DF 2 "reg_or_fp0_operand" "") + (match_operand:DF 3 "reg_or_fp0_operand" "")))] + "" + " +{ + rtx op0,op1; + enum rtx_code code = GET_CODE (operands[1]), code2 = NE; + + if (!alpha_compare_fp_p) + FAIL; + switch (code) + { + case EQ: case LE: case LT: + op0 = alpha_compare_op0; + op1 = alpha_compare_op1; + break; + case NE: + /* There isn't a cmptne insn. */ + code = code2 = EQ; + op0 = alpha_compare_op0; + op1 = alpha_compare_op1; + break; + case GE: + code = LE; + op0 = force_reg (DFmode, alpha_compare_op1); + op1 = alpha_compare_op0; + break; + case GT: + code = LT; + op0 = force_reg (DFmode, alpha_compare_op1); + op1 = alpha_compare_op0; + break; + default: + FAIL; + } + operands[1] = gen_rtx (code, DFmode, op0, op1); + operands[4] = gen_reg_rtx (DFmode); + operands[5] = gen_rtx (code2, VOIDmode, operands[4], CONST0_RTX (DFmode)); +}") + ;; These define_split definitions are used in cases when comparisons have ;; not be stated in the correct way and we need to reverse the second ;; comparison. For example, x >= 7 has to be done as x < 6 with the @@ -2263,32 +2577,107 @@ operands[6] = gen_rtx (GET_CODE (operands[1]), VOIDmode, operands[4], const0_rtx); }") + +;; We can convert such things as "a > 0xffff" to "t = a & ~ 0xffff; t != 0". +;; This eliminates one, and sometimes two, insns when the AND can be done +;; with a ZAP. +(define_split + [(set (match_operand:DI 0 "register_operand" "") + (match_operator 1 "comparison_operator" + [(match_operand:DI 2 "register_operand" "") + (match_operand:DI 3 "const_int_operand" "")])) + (clobber (match_operand:DI 4 "register_operand" ""))] + "exact_log2 (INTVAL (operands[3]) + 1) >= 0 + && (GET_CODE (operands[1]) == GTU + || GET_CODE (operands[1]) == LEU + || ((GET_CODE (operands[1]) == GT || GET_CODE (operands[1]) == LE) + && extended_count (operands[2], DImode, 1) > 0))" + [(set (match_dup 4) (and:DI (match_dup 2) (match_dup 5))) + (set (match_dup 0) (match_dup 6))] + " +{ + operands[5] = GEN_INT (~ INTVAL (operands[3])); + operands[6] = gen_rtx (((GET_CODE (operands[1]) == GTU + || GET_CODE (operands[1]) == GT) + ? NE : EQ), + DImode, operands[4], const0_rtx); +}") -;; Here are the CALL and unconditional branch insns. +;; Here are the CALL and unconditional branch insns. Calls on NT and OSF +;; work differently, so we have different patterns for each. (define_expand "call" - [(parallel [(call (mem:DI (match_dup 2)) + [(use (match_operand:DI 0 "" "")) + (use (match_operand 1 "" ""))] + "" + " +{ if (WINDOWS_NT) + emit_call_insn (gen_call_nt (operands[0], operands[1])); + else + emit_call_insn (gen_call_osf (operands[0], operands[1])); + + DONE; +}") + +(define_expand "call_osf" + [(parallel [(call (mem:DI (match_operand 0 "" "")) (match_operand 1 "" "")) - (use (match_operand:DI 0 "" "")) + (clobber (reg:DI 27)) (clobber (reg:DI 26))])] "" " { if (GET_CODE (operands[0]) != MEM) abort (); + operands[0] = XEXP (operands[0], 0); - operands[2] = gen_rtx (REG, DImode, 27); - emit_move_insn (operands[2], operands[0]); + if (GET_CODE (operands[0]) != SYMBOL_REF + && ! (GET_CODE (operands[0]) == REG && REGNO (operands[0]) == 27)) + { + rtx tem = gen_rtx (REG, DImode, 27); + emit_move_insn (tem, operands[0]); + operands[0] = tem; + } +}") - if (GET_CODE (operands[0]) != SYMBOL_REF) - operands[0] = const0_rtx; +(define_expand "call_nt" + [(parallel [(call (mem:DI (match_operand:DI 0 "" "")) + (match_operand 1 "" "")) + (clobber (reg:DI 26))])] + "" + " +{ if (GET_CODE (operands[0]) != MEM) + abort (); + operands[0] = XEXP (operands[0], 0); + + if (GET_CODE (operands[1]) != SYMBOL_REF + && ! (GET_CODE (operands[1]) == REG && REGNO (operands[1]) == 27)) + { + rtx tem = gen_rtx (REG, DImode, 27); + emit_move_insn (tem, operands[1]); + operands[1] = tem; + } }") (define_expand "call_value" + [(use (match_operand 0 "" "")) + (use (match_operand:DI 1 "" "")) + (use (match_operand 2 "" ""))] + "" + " +{ if (WINDOWS_NT) + emit_call_insn (gen_call_value_nt (operands[0], operands[1], operands[2])); + else + emit_call_insn (gen_call_value_osf (operands[0], operands[1], + operands[2])); + DONE; +}") + +(define_expand "call_value_osf" [(parallel [(set (match_operand 0 "" "") - (call (mem:DI (match_dup 3)) + (call (mem:DI (match_operand 1 "" "")) (match_operand 2 "" ""))) - (use (match_operand:DI 1 "" "")) + (clobber (reg:DI 27)) (clobber (reg:DI 26))])] "" " @@ -2297,50 +2686,80 @@ operands[1] = XEXP (operands[1], 0); - operands[3] = gen_rtx (REG, DImode, 27); - emit_move_insn (operands[3], operands[1]); + if (GET_CODE (operands[1]) != SYMBOL_REF + && ! (GET_CODE (operands[1]) == REG && REGNO (operands[1]) == 27)) + { + rtx tem = gen_rtx (REG, DImode, 27); + emit_move_insn (tem, operands[1]); + operands[1] = tem; + } +}") - if (GET_CODE (operands[1]) != SYMBOL_REF) - operands[1] = const0_rtx; +(define_expand "call_value_nt" + [(parallel [(set (match_operand 0 "" "") + (call (mem:DI (match_operand:DI 1 "" "")) + (match_operand 2 "" ""))) + (clobber (reg:DI 26))])] + "" + " +{ if (GET_CODE (operands[1]) != MEM) + abort (); + + operands[1] = XEXP (operands[1], 0); + if (GET_CODE (operands[1]) != SYMBOL_REF + && ! (GET_CODE (operands[1]) == REG && REGNO (operands[1]) == 27)) + { + rtx tem = gen_rtx (REG, DImode, 27); + emit_move_insn (tem, operands[1]); + operands[1] = tem; + } }") (define_insn "" - [(call (mem:DI (reg:DI 27)) - (match_operand 0 "" "")) - (use (match_operand:DI 1 "" "")) + [(call (mem:DI (match_operand:DI 0 "call_operand" "r,R,i")) + (match_operand 1 "" "")) + (clobber (reg:DI 27)) (clobber (reg:DI 26))] - "" - "jsr $26,($27),%1\;ldgp $29,0($26)" - [(set_attr "type" "jsr")]) + "! WINDOWS_NT" + "@ + jsr $26,($27),0\;ldgp $29,0($26) + bsr $26,%0..ng + jsr $26,%0\;ldgp $29,0($26)" + [(set_attr "type" "jsr,jsr,ibr")]) (define_insn "" - [(set (match_operand 0 "register_operand" "=rf") - (call (mem:DI (reg:DI 27)) - (match_operand 1 "" ""))) - (use (match_operand:DI 2 "" "")) + [(call (mem:DI (match_operand:DI 0 "call_operand" "r,i")) + (match_operand 1 "" "")) (clobber (reg:DI 26))] - "" - "jsr $26,($27),%2\;ldgp $29,0($26)" + "WINDOWS_NT" + "@ + jsr $26,(%0) + bsr $26,%0" [(set_attr "type" "jsr")]) - + (define_insn "" - [(call (mem:DI (match_operand 1 "current_file_function_operand" "i")) - (match_operand 0 "" "")) - (use (match_dup 1)) + [(set (match_operand 0 "register_operand" "=rf,rf,rf") + (call (mem:DI (match_operand:DI 1 "call_operand" "r,R,i")) + (match_operand 2 "" ""))) + (clobber (reg:DI 27)) (clobber (reg:DI 26))] - "" - "bsr $26,%1..ng" - [(set_attr "type" "ibr")]) - + "! WINDOWS_NT" + "@ + jsr $26,($27),0\;ldgp $29,0($26) + bsr $26,%1..ng + jsr $26,%1\;ldgp $29,0($26)" + [(set_attr "type" "jsr,jsr,ibr")]) + (define_insn "" - [(set (match_operand 0 "register_operand" "=rf") - (call (mem:DI (match_operand 1 "current_file_function_operand" "i")) + [(set (match_operand 0 "register_operand" "=rf,rf") + (call (mem:DI (match_operand:DI 1 "call_operand" "r,i")) (match_operand 2 "" ""))) - (use (match_dup 1)) (clobber (reg:DI 26))] - "" - "bsr $26,%1..ng" - [(set_attr "type" "ibr")]) + "WINDOWS_NT" + "@ + jsr $26,(%1) + bsr $26,%1" + [(set_attr "type" "jsr")]) ;; Call subroutine returning any type. @@ -2405,31 +2824,57 @@ [(set_attr "type" "iaddlog")]) (define_expand "tablejump" + [(use (match_operand:SI 0 "register_operand" "")) + (use (match_operand:SI 1 "" ""))] + "" + " +{ + if (WINDOWS_NT) + emit_jump_insn (gen_tablejump_nt (operands[0], operands[1])); + else + emit_jump_insn (gen_tablejump_osf (operands[0], operands[1])); + + DONE; +}") + +(define_expand "tablejump_osf" [(set (match_dup 3) (sign_extend:DI (match_operand:SI 0 "register_operand" ""))) - (parallel [(set (pc) (plus:DI (match_dup 3) (reg:DI 29))) - (use (label_ref (match_operand 1 "" ""))) + (parallel [(set (pc) + (plus:DI (match_dup 3) + (label_ref:DI (match_operand 1 "" "")))) (clobber (match_scratch:DI 2 "=r"))])] "" " { operands[3] = gen_reg_rtx (DImode); }") +(define_expand "tablejump_nt" + [(set (match_dup 3) + (sign_extend:DI (match_operand:SI 0 "register_operand" ""))) + (parallel [(set (pc) + (match_dup 3)) + (use (label_ref (match_operand 1 "" "")))])] + "" + " +{ operands[3] = gen_reg_rtx (DImode); }") + (define_insn "" [(set (pc) (plus:DI (match_operand:DI 0 "register_operand" "r") - (reg:DI 29))) - (use (label_ref (match_operand 1 "" ""))) + (label_ref:DI (match_operand 1 "" "")))) (clobber (match_scratch:DI 2 "=r"))] - "" + "! WINDOWS_NT && next_active_insn (insn) != 0 + && GET_CODE (PATTERN (next_active_insn (insn))) == ADDR_DIFF_VEC + && PREV_INSN (next_active_insn (insn)) == operands[1]" "* { rtx best_label = 0; rtx jump_table_insn = next_active_insn (operands[1]); if (GET_CODE (jump_table_insn) == JUMP_INSN - && GET_CODE (PATTERN (jump_table_insn)) == ADDR_VEC) + && GET_CODE (PATTERN (jump_table_insn)) == ADDR_DIFF_VEC) { rtx jump_table = PATTERN (jump_table_insn); - int n_labels = XVECLEN (jump_table, 0); + int n_labels = XVECLEN (jump_table, 1); int best_count = -1; int i, j; @@ -2438,12 +2883,12 @@ int count = 1; for (j = i + 1; j < n_labels; j++) - if (XEXP (XVECEXP (jump_table, 0, i), 0) - == XEXP (XVECEXP (jump_table, 0, j), 0)) + if (XEXP (XVECEXP (jump_table, 1, i), 0) + == XEXP (XVECEXP (jump_table, 1, j), 0)) count++; if (count > best_count) - best_count = count, best_label = XVECEXP (jump_table, 0, i); + best_count = count, best_label = XVECEXP (jump_table, 1, i); } } @@ -2457,6 +2902,49 @@ }" [(set_attr "type" "ibr")]) +(define_insn "" + [(set (pc) + (match_operand:DI 0 "register_operand" "r")) + (use (label_ref (match_operand 1 "" "")))] + "WINDOWS_NT && next_active_insn (insn) != 0 + && GET_CODE (PATTERN (next_active_insn (insn))) == ADDR_DIFF_VEC + && PREV_INSN (next_active_insn (insn)) == operands[1]" + "* +{ rtx best_label = 0; + rtx jump_table_insn = next_active_insn (operands[1]); + + if (GET_CODE (jump_table_insn) == JUMP_INSN + && GET_CODE (PATTERN (jump_table_insn)) == ADDR_DIFF_VEC) + { + rtx jump_table = PATTERN (jump_table_insn); + int n_labels = XVECLEN (jump_table, 1); + int best_count = -1; + int i, j; + + for (i = 0; i < n_labels; i++) + { + int count = 1; + + for (j = i + 1; j < n_labels; j++) + if (XEXP (XVECEXP (jump_table, 1, i), 0) + == XEXP (XVECEXP (jump_table, 1, j), 0)) + count++; + + if (count > best_count) + best_count = count, best_label = XVECEXP (jump_table, 1, i); + } + } + + if (best_label) + { + operands[2] = best_label; + return \"jmp $31,(%0),%2\"; + } + else + return \"jmp $31,(%0),0\"; +}" + [(set_attr "type" "ibr")]) + ;; Cache flush. Used by INITIALIZE_TRAMPOLINE. 0x86 is PAL_imb, but we don't ;; want to have to include pal.h in our .s file. (define_insn "" @@ -2470,11 +2958,11 @@ (define_insn "" [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m,f,f,f,m") - (match_operand:SF 1 "input_operand" "r,m,rG,f,G,m,fG"))] + (match_operand:SF 1 "input_operand" "rG,m,rG,f,G,m,fG"))] "register_operand (operands[0], SFmode) || reg_or_fp0_operand (operands[1], SFmode)" "@ - bis %1,%1,%0 + bis %r1,%r1,%0 ldl %0,%1 stl %r1,%0 cpys %1,%1,%0 @@ -2485,11 +2973,11 @@ (define_insn "" [(set (match_operand:DF 0 "nonimmediate_operand" "=r,r,m,f,f,f,m") - (match_operand:DF 1 "input_operand" "r,m,rG,f,G,m,fG"))] + (match_operand:DF 1 "input_operand" "rG,m,rG,f,G,m,fG"))] "register_operand (operands[0], DFmode) || reg_or_fp0_operand (operands[1], DFmode)" "@ - bis %1,%1,%0 + bis %r1,%r1,%0 ldq %0,%1 stq %r1,%0 cpys %1,%1,%0 @@ -2520,30 +3008,44 @@ operands[1] = force_reg (DFmode, operands[1]); }") -;; There is a problem with 32-bit values in FP registers. We keep such -;; values in the register as a quadword. This is done on loads by using -;; the cvtlq instruction. On stores, we can't do anything directly from -;; floating-point registers. Disallow such an operation and let reload -;; use an integer register instead. Don't encourage 32-bit values to -;; be placed in FP registers at all. +(define_insn "" + [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,r,r,r,m,f,f,f,m") + (match_operand:SI 1 "input_operand" "r,J,I,K,L,m,rJ,f,J,m,fG"))] + "! WINDOWS_NT && (register_operand (operands[0], SImode) + || reg_or_0_operand (operands[1], SImode))" + "@ + bis %1,%1,%0 + bis $31,$31,%0 + bis $31,%1,%0 + lda %0,%1 + ldah %0,%h1 + ldl %0,%1 + stl %r1,%0 + cpys %1,%1,%0 + cpys $f31,$f31,%0 + lds %0,%1 + sts %R1,%0" + [(set_attr "type" "iaddlog,iaddlog,iaddlog,iaddlog,iaddlog,ld,st,fpop,fpop,ld,st")]) (define_insn "" - [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,r,r,r,m,*f,*f,*f") - (match_operand:SI 1 "input_operand" "r,J,I,K,L,m,rJ,*f,J,m"))] - "register_operand (operands[0], SImode) - || reg_or_0_operand (operands[1], SImode)" + [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,r,r,r,r,m,f,f,f,m") + (match_operand:SI 1 "input_operand" "r,J,I,K,L,s,m,rJ,f,J,m,fG"))] + "WINDOWS_NT && (register_operand (operands[0], SImode) + || reg_or_0_operand (operands[1], SImode))" "@ bis %1,%1,%0 bis $31,$31,%0 bis $31,%1,%0 lda %0,%1 ldah %0,%h1 + lda %0,%1 ldl %0,%1 stl %r1,%0 cpys %1,%1,%0 cpys $f31,$f31,%0 - lds %0,%1\;cvtlq %0,%0" - [(set_attr "type" "iaddlog,iaddlog,iaddlog,iaddlog,iaddlog,ld,st,fpop,fpop,ld")]) + lds %0,%1 + sts %R1,%0" + [(set_attr "type" "iaddlog,iaddlog,iaddlog,iaddlog,iaddlog,ldsym,ld,st,fpop,fpop,ld,st")]) (define_insn "" [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r,r,f,f") @@ -2590,10 +3092,10 @@ ; else if (GET_CODE (operands[1]) == CONST_INT) { - if (alpha_emit_set_const (operands[0], INTVAL (operands[1]), 3)) + operands[1] + = alpha_emit_set_const (operands[0], SImode, INTVAL (operands[1]), 3); + if (rtx_equal_p (operands[0], operands[1])) DONE; - else - abort (); } }") @@ -2607,15 +3109,18 @@ [(set (match_dup 0) (match_dup 2)) (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 3)))] " -{ if (alpha_emit_set_const (operands[0], INTVAL (operands[1]), 2)) +{ rtx tem + = alpha_emit_set_const (operands[0], SImode, INTVAL (operands[1]), 2); + + if (tem == operands[0]) DONE; else FAIL; }") (define_insn "" - [(set (match_operand:DI 0 "general_operand" "=r,r,r,r,r,r,r,m,f,f,f,m") - (match_operand:DI 1 "input_operand" "r,J,I,K,L,s,m,rJ,f,J,m,fG"))] + [(set (match_operand:DI 0 "general_operand" "=r,r,r,r,r,r,r,m,f,f,f,Q") + (match_operand:DI 1 "input_operand" "r,J,I,K,L,s,m,rJ,f,J,Q,fG"))] "register_operand (operands[0], DImode) || reg_or_0_operand (operands[1], DImode)" "@ @@ -2642,6 +3147,8 @@ "" " { + rtx tem; + if (GET_CODE (operands[0]) == MEM && ! reg_or_0_operand (operands[1], DImode)) operands[1] = force_reg (DImode, operands[1]); @@ -2649,14 +3156,21 @@ if (! CONSTANT_P (operands[1]) || input_operand (operands[1], DImode)) ; else if (GET_CODE (operands[1]) == CONST_INT - && alpha_emit_set_const (operands[0], INTVAL (operands[1]), 3)) - DONE; + && (tem = alpha_emit_set_const (operands[0], DImode, + INTVAL (operands[1]), 3)) != 0) + { + if (rtx_equal_p (tem, operands[0])) + DONE; + else + operands[1] = tem; + } else if (CONSTANT_P (operands[1])) { operands[1] = force_const_mem (DImode, operands[1]); if (reload_in_progress) { emit_move_insn (operands[0], XEXP (operands[1], 0)); + operands[1] = copy_rtx (operands[1]); XEXP (operands[1], 0) = operands[0]; } else @@ -2676,7 +3190,10 @@ [(set (match_dup 0) (match_dup 2)) (set (match_dup 0) (plus:DI (match_dup 0) (match_dup 3)))] " -{ if (alpha_emit_set_const (operands[0], INTVAL (operands[1]), 2)) +{ rtx tem + = alpha_emit_set_const (operands[0], DImode, INTVAL (operands[1]), 2); + + if (tem == operands[0]) DONE; else FAIL; @@ -2749,10 +3266,12 @@ (const_int -7))) (set (match_operand:DI 3 "register_operand" "") (mem:DI (match_dup 2))) + (set (match_operand:DI 4 "register_operand" "") + (and:DI (match_dup 1) (const_int -2))) (set (subreg:DI (match_operand:HI 0 "register_operand" "") 0) (zero_extract:DI (match_dup 3) (const_int 16) - (ashift:DI (match_dup 1) (const_int 3))))] + (ashift:DI (match_dup 4) (const_int 3))))] "" "") @@ -2781,7 +3300,7 @@ ;; For the unaligned byte case, we use code similar to that in the ;; Architecture book, but reordered to lower the number of registers ;; required. Operand 0 is the address. Operand 1 is the data to store. -;; Operands 2, 3, and 4 are DImode temporaries, where the last two may +;; Operands 2, 3, and 4 are DImode temporaries, where operands 2 and 4 may ;; be the same temporary, if desired. If the address is in a register, ;; operand 2 can be that register. @@ -2792,8 +3311,8 @@ (set (match_operand:DI 2 "register_operand" "") (match_dup 0)) (set (match_dup 3) - (and:DI (ashift:DI (const_int 255) - (ashift:DI (match_dup 2) (const_int 3))) + (and:DI (not:DI (ashift:DI (const_int 255) + (ashift:DI (match_dup 2) (const_int 3)))) (match_dup 3))) (set (match_operand:DI 4 "register_operand" "") (ashift:DI (zero_extend:DI (match_operand:QI 1 "register_operand" "")) @@ -2825,13 +3344,15 @@ (and:DI (match_dup 2) (const_int -7))) (set (match_operand:DI 4 "register_operand" "") (mem:DI (match_dup 3))) + (set (match_operand:DI 10 "register_operand" "") + (and:DI (match_dup 2) (const_int -2))) (set (match_operand:DI 5 "register_operand" "") - (and:DI (ashift:DI (const_int 65535) - (ashift:DI (match_dup 2) (const_int 3))) + (and:DI (not:DI (ashift:DI (const_int 65535) + (ashift:DI (match_dup 10) (const_int 3)))) (match_dup 4))) (set (match_operand:DI 6 "register_operand" "") (ashift:DI (zero_extend:DI (match_operand:HI 1 "register_operand" "")) - (ashift:DI (match_dup 2) (const_int 3)))) + (ashift:DI (match_dup 10) (const_int 3)))) (set (match_operand:DI 7 "register_operand" "") (ior:DI (match_dup 5) (match_dup 6))) (set (match_operand:DI 8 "register_operand" "") (match_dup 0)) @@ -2979,8 +3500,10 @@ NULL_RTX)); rtx scratch1 = gen_reg_rtx (DImode); rtx scratch2 = gen_reg_rtx (DImode); + rtx scratch3 = gen_reg_rtx (DImode); + rtx seq = gen_unaligned_loadhi (operands[0], addr, scratch1, - scratch2); + scratch2, scratch3); alpha_set_memflags (seq, operands[1]); emit_insn (seq); @@ -3019,9 +3542,12 @@ rtx temp6 = gen_reg_rtx (DImode); rtx temp7 = gen_reg_rtx (DImode); rtx temp8 = gen_reg_rtx (DImode); + rtx temp9 = gen_reg_rtx (DImode); + rtx seq = gen_unaligned_storehi (get_unaligned_address (operands[0]), operands[1], temp1, temp2,temp3, - temp4, temp5, temp6,temp7, temp8); + temp4, temp5, temp6,temp7, + temp8, temp9); alpha_set_memflags (seq, operands[0]); emit_insn (seq); @@ -3038,12 +3564,18 @@ (define_expand "reload_inqi" [(parallel [(match_operand:QI 0 "register_operand" "=r") (match_operand:QI 1 "unaligned_memory_operand" "m") - (match_operand:DI 2 "register_operand" "=&r")])] + (match_operand:TI 2 "register_operand" "=&r")])] "" " { extern rtx get_unaligned_address (); rtx addr = get_unaligned_address (operands[1]); - rtx seq = gen_unaligned_loadqi (operands[0], addr, operands[2], + /* It is possible that one of the registers we got for operands[2] + might coincide with that of operands[0] (which is why we made + it TImode). Pick the other one to use as our scratch. */ + rtx scratch = gen_rtx (REG, DImode, + REGNO (operands[0]) == REGNO (operands[2]) + ? REGNO (operands[2]) + 1 : REGNO (operands[2])); + rtx seq = gen_unaligned_loadqi (operands[0], addr, scratch, gen_rtx (REG, DImode, REGNO (operands[0]))); alpha_set_memflags (seq, operands[1]); @@ -3069,7 +3601,7 @@ addr = scratch2; } - seq = gen_unaligned_loadhi (operands[0], addr, scratch1, scratch1); + seq = gen_unaligned_loadhi (operands[0], addr, scratch1, scratch1, scratch2); alpha_set_memflags (seq, operands[1]); emit_insn (seq); DONE; @@ -3099,13 +3631,14 @@ rtx addr = get_unaligned_address (operands[0]); rtx scratch1 = gen_rtx (REG, DImode, REGNO (operands[2])); rtx scratch2 = gen_rtx (REG, DImode, REGNO (operands[2]) + 1); + rtx scratch3 = scratch1; rtx seq; if (GET_CODE (addr) == REG) scratch1 = addr; seq = gen_unaligned_storeqi (addr, operands[1], scratch1, - scratch2, scratch2); + scratch2, scratch3); alpha_set_memflags (seq, operands[0]); emit_insn (seq); } @@ -3143,7 +3676,7 @@ seq = gen_unaligned_storehi (addr, operands[1], scratch_a, scratch2, scratch2, scratch2, scratch1, scratch2, scratch_a, - scratch1); + scratch1, scratch_a); alpha_set_memflags (seq, operands[0]); emit_insn (seq); } @@ -3157,11 +3690,11 @@ "" " { - operands[0] = gen_rtx (MEM, DImode, plus_constant (stack_pointer_rtx, + operands[1] = gen_rtx (MEM, DImode, plus_constant (stack_pointer_rtx, INTVAL (operands[0]))); - MEM_VOLATILE_P (operands[0]) = 1; + MEM_VOLATILE_P (operands[1]) = 1; - operands[1] = gen_reg_rtx (DImode); + operands[0] = const0_rtx; }") ;; This is how we allocate stack space. If we are allocating a @@ -3192,7 +3725,7 @@ emit_insn (gen_probe_stack (GEN_INT (- (probed += 8192)))); if (probed + 4096 < INTVAL (operands[0])) - emit_insn (gen_probe_stack (GEN_INT (- (probed += 4096)))); + emit_insn (gen_probe_stack (GEN_INT (- INTVAL(operands[0])))); } operands[0] = GEN_INT (- INTVAL (operands[0])); @@ -3201,56 +3734,36 @@ { rtx out_label = 0; rtx loop_label = gen_label_rtx (); - rtx count = gen_reg_rtx (DImode); - rtx access = gen_reg_rtx (Pmode); - rtx memref = gen_rtx (MEM, DImode, access); + rtx want = gen_reg_rtx (Pmode); + rtx tmp = gen_reg_rtx (Pmode); + rtx memref; - MEM_VOLATILE_P (memref) = 1; - - /* If the amount to be allocated is not a constant, we only need to - do something special if it is >= 4096. */ + emit_insn (gen_subdi3 (want, stack_pointer_rtx, + force_reg (Pmode, operands[0]))); + emit_insn (gen_adddi3 (tmp, stack_pointer_rtx, GEN_INT (-4096))); if (GET_CODE (operands[0]) != CONST_INT) { - operands[0] = force_reg (DImode, operands[0]); out_label = gen_label_rtx (); - emit_insn (gen_cmpdi (operands[0], - force_reg (DImode, GEN_INT (4096)))); - emit_jump_insn (gen_ble (out_label)); - - /* Compute COUNT = (N + 4096) / 8192. N is known positive. */ - emit_insn (gen_adddi3 (count, operands[0], GEN_INT (4096))); - emit_insn (gen_lshrdi3 (count, count, GEN_INT (13))); + emit_insn (gen_cmpdi (want, tmp)); + emit_jump_insn (gen_bgeu (out_label)); } - else - emit_move_insn (count, GEN_INT ((INTVAL (operands[0]) + 4096) >> 13)); - /* ACCESS = SP + 4096. */ - emit_insn (gen_adddi3 (access, stack_pointer_rtx, GEN_INT (4096))); emit_label (loop_label); - - /* Each iteration subtracts 8192 from ACCESS and references it. */ - emit_insn (gen_adddi3 (count, count, constm1_rtx)); - emit_insn (gen_adddi3 (access, access, GEN_INT (-8192))); - emit_move_insn (gen_reg_rtx (DImode), memref); - emit_insn (gen_cmpdi (count, const0_rtx)); - emit_jump_insn (gen_bgt (loop_label)); + memref = gen_rtx (MEM, DImode, tmp); + MEM_VOLATILE_P (memref) = 1; + emit_move_insn (memref, const0_rtx); + emit_insn (gen_adddi3 (tmp, tmp, GEN_INT(-8192))); + emit_insn (gen_cmpdi (tmp, want)); + emit_jump_insn (gen_bgtu (loop_label)); + memref = gen_rtx (MEM, DImode, want); + MEM_VOLATILE_P (memref) = 1; + emit_move_insn (memref, const0_rtx); if (out_label) emit_label (out_label); - /* We need to subtract operands[0] from SP. We know it isn't a - constant less than 32768, so we know we have to load it into - a register. */ - - emit_insn (gen_subdi3 (stack_pointer_rtx, stack_pointer_rtx, - force_reg (Pmode, operands[0]))); - - /* Now, unless we have a constant and we know that we are within - 4096 from the end, we need to access sp + 4096. */ - if (! (GET_CODE (operands[0]) == CONST_INT - && (INTVAL (operands[0]) % 8192) < 4096)) - emit_insn (gen_probe_stack (GEN_INT (4096))); + emit_move_insn (stack_pointer_rtx, want); DONE; }