diff options
Diffstat (limited to 'gcc-1.40/config/vax.md')
| -rw-r--r-- | gcc-1.40/config/vax.md | 2166 |
1 files changed, 2166 insertions, 0 deletions
diff --git a/gcc-1.40/config/vax.md b/gcc-1.40/config/vax.md new file mode 100644 index 0000000..ae8611c --- /dev/null +++ b/gcc-1.40/config/vax.md @@ -0,0 +1,2166 @@ + +;;- Machine description for GNU compiler +;;- Vax Version +;; Copyright (C) 1987, 1988 Free Software Foundation, Inc. + +;; This file is part of GNU CC. + +;; GNU CC is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 1, or (at your option) +;; any later version. + +;; GNU CC is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; 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. + + +;;- Instruction patterns. When multiple patterns apply, +;;- the first one in the file is chosen. +;;- +;;- See file "rtl.def" for documentation on define_insn, match_*, et. al. +;;- +;;- cpp macro #define NOTICE_UPDATE_CC in file tm.h handles condition code +;;- updates for most instructions. + +; tstsi is first test insn so that it is the one to match +; a constant argument. + +(define_insn "tstsi" + [(set (cc0) + (match_operand:SI 0 "general_operand" "g"))] + "" + "tstl %0") + +(define_insn "tsthi" + [(set (cc0) + (match_operand:HI 0 "general_operand" "g"))] + "" + "tstw %0") + +(define_insn "tstqi" + [(set (cc0) + (match_operand:QI 0 "general_operand" "g"))] + "" + "tstb %0") + +(define_insn "tstdf" + [(set (cc0) + (match_operand:DF 0 "general_operand" "gF"))] + "" + "tst%# %0") + +(define_insn "tstsf" + [(set (cc0) + (match_operand:SF 0 "general_operand" "gF"))] + "" + "tstf %0") + +;; Put cmpsi first among compare insns so it matches two CONST_INT operands. + +(define_insn "cmpsi" + [(set (cc0) + (compare (match_operand:SI 0 "general_operand" "g") + (match_operand:SI 1 "general_operand" "g")))] + "" + "cmpl %0,%1") + +(define_insn "cmphi" + [(set (cc0) + (compare (match_operand:HI 0 "general_operand" "g") + (match_operand:HI 1 "general_operand" "g")))] + "" + "cmpw %0,%1") + +(define_insn "cmpqi" + [(set (cc0) + (compare (match_operand:QI 0 "general_operand" "g") + (match_operand:QI 1 "general_operand" "g")))] + "" + "cmpb %0,%1") + +(define_insn "cmpdf" + [(set (cc0) + (compare (match_operand:DF 0 "general_operand" "gF") + (match_operand:DF 1 "general_operand" "gF")))] + "" + "cmp%# %0,%1") + +(define_insn "cmpsf" + [(set (cc0) + (compare (match_operand:SF 0 "general_operand" "gF") + (match_operand:SF 1 "general_operand" "gF")))] + "" + "cmpf %0,%1") + +(define_insn "" + [(set (cc0) + (and:SI (match_operand:SI 0 "general_operand" "g") + (match_operand:SI 1 "general_operand" "g")))] + "" + "bitl %0,%1") + +(define_insn "" + [(set (cc0) + (and:HI (match_operand:HI 0 "general_operand" "g") + (match_operand:HI 1 "general_operand" "g")))] + "" + "bitw %0,%1") + +(define_insn "" + [(set (cc0) + (and:QI (match_operand:QI 0 "general_operand" "g") + (match_operand:QI 1 "general_operand" "g")))] + "" + "bitb %0,%1") + +(define_insn "movdf" + [(set (match_operand:DF 0 "general_operand" "=g") + (match_operand:DF 1 "general_operand" "gF"))] + "" + "* +{ + if (operands[1] == dconst0_rtx) + return \"clr%# %0\"; + return \"mov%# %1,%0\"; +}") + +(define_insn "movsf" + [(set (match_operand:SF 0 "general_operand" "=g") + (match_operand:SF 1 "general_operand" "gF"))] + "" + "* +{ + if (operands[1] == fconst0_rtx) + return \"clrf %0\"; + return \"movf %1,%0\"; +}") + +;; Some vaxes don't support this instruction. +;;(define_insn "movti" +;; [(set (match_operand:TI 0 "general_operand" "=g") +;; (match_operand:TI 1 "general_operand" "g"))] +;; "" +;; "movh %1,%0") + +(define_insn "movdi" + [(set (match_operand:DI 0 "general_operand" "=g") + (match_operand:DI 1 "general_operand" "g"))] + "" + "movq %1,%0") + +;; This handles constants which are not legitimate +;; for the sake of shared libraries on VMS. +(define_insn "" + [(set (match_operand:SI 0 "general_operand" "=g") + (match_operand:SI 1 "" "i"))] + "CONSTANT_P (operands[1]) && ! LEGITIMATE_CONSTANT_P (operands[1])" + "* +{ + operands[2] = XEXP (XEXP (operands[1], 0), 0); + operands[1] = XEXP (XEXP (operands[1], 0), 1); + return \"movl %2,%0\;addl2 %1,%0\"; +}") + +(define_insn "movsi" + [(set (match_operand:SI 0 "general_operand" "=g") + (match_operand:SI 1 "supergeneral_operand" "g"))] + "" + "* +{ + rtx link; + if (operands[1] == const1_rtx + && (link = find_reg_note (insn, REG_WAS_0, 0)) + /* Make sure the insn that stored the 0 is still present. */ + && ! XEXP (link, 0)->volatil + && GET_CODE (XEXP (link, 0)) != NOTE + /* Make sure cross jumping didn't happen here. */ + && no_labels_between_p (XEXP (link, 0), insn)) + /* Fastest way to change a 0 to a 1. */ + return \"incl %0\"; + if (GET_CODE (operands[1]) == SYMBOL_REF || GET_CODE (operands[1]) == CONST) + { + if (push_operand (operands[0], SImode)) + return \"pushab %a1\"; + return \"movab %a1,%0\"; + } + /* this is slower than a movl, except when pushing an operand */ + if (operands[1] == const0_rtx) + return \"clrl %0\"; + if (GET_CODE (operands[1]) == CONST_INT + && (unsigned) INTVAL (operands[1]) >= 64) + { + int i = INTVAL (operands[1]); + if ((unsigned)(~i) < 64) + { + operands[1] = gen_rtx (CONST_INT, VOIDmode, ~i); + return \"mcoml %1,%0\"; + } + if ((unsigned)i < 127) + { + operands[1] = gen_rtx (CONST_INT, VOIDmode, 63); + operands[2] = gen_rtx (CONST_INT, VOIDmode, i-63); + return \"addl3 %2,%1,%0\"; + } + /* trading speed for space */ + if ((unsigned)i < 0x100) + return \"movzbl %1,%0\"; + if (i >= -0x80 && i < 0) + return \"cvtbl %1,%0\"; + if ((unsigned)i < 0x10000) + return \"movzwl %1,%0\"; + if (i >= -0x8000 && i < 0) + return \"cvtwl %1,%0\"; + } + if (push_operand (operands[0], SImode)) + return \"pushl %1\"; + return \"movl %1,%0\"; +}") + +(define_insn "movhi" + [(set (match_operand:HI 0 "general_operand" "=g") + (match_operand:HI 1 "general_operand" "g"))] + "" + "* +{ + rtx link; + if (operands[1] == const1_rtx + && (link = find_reg_note (insn, REG_WAS_0, 0)) + /* Make sure the insn that stored the 0 is still present. */ + && ! XEXP (link, 0)->volatil + && GET_CODE (XEXP (link, 0)) != NOTE + /* Make sure cross jumping didn't happen here. */ + && no_labels_between_p (XEXP (link, 0), insn)) + /* Fastest way to change a 0 to a 1. */ + return \"incw %0\"; + if (operands[1] == const0_rtx) + return \"clrw %0\"; + if (GET_CODE (operands[1]) == CONST_INT + && (unsigned) INTVAL (operands[1]) >= 64) + { + int i = INTVAL (operands[1]); + if ((unsigned)((~i) & 0xffff) < 64) + { + operands[1] = gen_rtx (CONST_INT, VOIDmode, (~i) & 0xffff); + return \"mcomw %1,%0\"; + } + if ((unsigned)(i & 0xffff) < 127) + { + operands[1] = gen_rtx (CONST_INT, VOIDmode, 63); + operands[2] = gen_rtx (CONST_INT, VOIDmode, (i-63) & 0xffff); + return \"addw3 %2,%1,%0\"; + } + /* this is a lot slower, and only saves 1 measly byte! */ + /* if ((unsigned)i < 0x100) + return \"movzbw %1,%0\"; */ + /* if (i >= -0x80 && i < 0) + return \"cvtbw %1,%0\"; */ + } + return \"movw %1,%0\"; +}") + +(define_insn "movqi" + [(set (match_operand:QI 0 "general_operand" "=g") + (match_operand:QI 1 "general_operand" "g"))] + "" + "* +{ + if (operands[1] == const0_rtx) + return \"clrb %0\"; + if (GET_CODE (operands[1]) == CONST_INT + && (unsigned) INTVAL (operands[1]) >= 64) + { + int i = INTVAL (operands[1]); + if ((unsigned)((~i) & 0xff) < 64) + { + operands[1] = gen_rtx (CONST_INT, VOIDmode, (~i) & 0xff); + return \"mcomb %1,%0\"; + } +#if 0 + /* ASCII alphabetics */ + if (((unsigned) INTVAL (operands[1]) &0xff) < 127) + { + operands[1] = gen_rtx (CONST_INT, VOIDmode, 63); + operands[2] = gen_rtx (CONST_INT, VOIDmode, i-63); + return \"addb3 %2,%1,%0\"; + } +#endif + } + return \"movb %1,%0\"; +}") + +;; The definition of this insn does not really explain what it does, +;; but it should suffice +;; that anything generated as this insn will be recognized as one +;; and that it won't successfully combine with anything. +(define_insn "movstrhi" + [(set (match_operand:BLK 0 "general_operand" "=g") + (match_operand:BLK 1 "general_operand" "g")) + (use (match_operand:HI 2 "general_operand" "g")) + (clobber (reg:SI 0)) + (clobber (reg:SI 1)) + (clobber (reg:SI 2)) + (clobber (reg:SI 3)) + (clobber (reg:SI 4)) + (clobber (reg:SI 5))] + "" + "movc3 %2,%1,%0") + +;; Extension and truncation insns. +;; Those for integer source operand +;; are ordered widest source type first. + +(define_insn "truncsiqi2" + [(set (match_operand:QI 0 "general_operand" "=g") + (truncate:QI (match_operand:SI 1 "general_operand" "g")))] + "" + "cvtlb %1,%0") + +(define_insn "truncsihi2" + [(set (match_operand:HI 0 "general_operand" "=g") + (truncate:HI (match_operand:SI 1 "general_operand" "g")))] + "" + "cvtlw %1,%0") + +(define_insn "trunchiqi2" + [(set (match_operand:QI 0 "general_operand" "=g") + (truncate:QI (match_operand:HI 1 "general_operand" "g")))] + "" + "cvtwb %1,%0") + +(define_insn "extendhisi2" + [(set (match_operand:SI 0 "general_operand" "=g") + (sign_extend:SI (match_operand:HI 1 "general_operand" "g")))] + "" + "cvtwl %1,%0") + +(define_insn "extendqihi2" + [(set (match_operand:HI 0 "general_operand" "=g") + (sign_extend:HI (match_operand:QI 1 "general_operand" "g")))] + "" + "cvtbw %1,%0") + +(define_insn "extendqisi2" + [(set (match_operand:SI 0 "general_operand" "=g") + (sign_extend:SI (match_operand:QI 1 "general_operand" "g")))] + "" + "cvtbl %1,%0") + +(define_insn "extendsfdf2" + [(set (match_operand:DF 0 "general_operand" "=g") + (float_extend:DF (match_operand:SF 1 "general_operand" "gF")))] + "" + "cvtf%# %1,%0") + +(define_insn "truncdfsf2" + [(set (match_operand:SF 0 "general_operand" "=g") + (float_truncate:SF (match_operand:DF 1 "general_operand" "gF")))] + "" + "cvt%#f %1,%0") + +(define_insn "zero_extendhisi2" + [(set (match_operand:SI 0 "general_operand" "=g") + (zero_extend:SI (match_operand:HI 1 "general_operand" "g")))] + "" + "movzwl %1,%0") + +(define_insn "zero_extendqihi2" + [(set (match_operand:HI 0 "general_operand" "=g") + (zero_extend:HI (match_operand:QI 1 "general_operand" "g")))] + "" + "movzbw %1,%0") + +(define_insn "zero_extendqisi2" + [(set (match_operand:SI 0 "general_operand" "=g") + (zero_extend:SI (match_operand:QI 1 "general_operand" "g")))] + "" + "movzbl %1,%0") + +;; Fix-to-float conversion insns. +;; Note that the ones that start with SImode come first. +;; That is so that an operand that is a CONST_INT +;; (and therefore lacks a specific machine mode). +;; will be recognized as SImode (which is always valid) +;; rather than as QImode or HImode. + +(define_insn "floatsisf2" + [(set (match_operand:SF 0 "general_operand" "=g") + (float:SF (match_operand:SI 1 "general_operand" "g")))] + "" + "cvtlf %1,%0") + +(define_insn "floatsidf2" + [(set (match_operand:DF 0 "general_operand" "=g") + (float:DF (match_operand:SI 1 "general_operand" "g")))] + "" + "cvtl%# %1,%0") + +(define_insn "floathisf2" + [(set (match_operand:SF 0 "general_operand" "=g") + (float:SF (match_operand:HI 1 "general_operand" "g")))] + "" + "cvtwf %1,%0") + +(define_insn "floathidf2" + [(set (match_operand:DF 0 "general_operand" "=g") + (float:DF (match_operand:HI 1 "general_operand" "g")))] + "" + "cvtw%# %1,%0") + +(define_insn "floatqisf2" + [(set (match_operand:SF 0 "general_operand" "=g") + (float:SF (match_operand:QI 1 "general_operand" "g")))] + "" + "cvtbf %1,%0") + +(define_insn "floatqidf2" + [(set (match_operand:DF 0 "general_operand" "=g") + (float:DF (match_operand:QI 1 "general_operand" "g")))] + "" + "cvtb%# %1,%0") + +;; Float-to-fix conversion insns. + +(define_insn "fix_truncsfqi2" + [(set (match_operand:QI 0 "general_operand" "=g") + (fix:QI (fix:SF (match_operand:SF 1 "general_operand" "gF"))))] + "" + "cvtfb %1,%0") + +(define_insn "fix_truncsfhi2" + [(set (match_operand:HI 0 "general_operand" "=g") + (fix:HI (fix:SF (match_operand:SF 1 "general_operand" "gF"))))] + "" + "cvtfw %1,%0") + +(define_insn "fix_truncsfsi2" + [(set (match_operand:SI 0 "general_operand" "=g") + (fix:SI (fix:SF (match_operand:SF 1 "general_operand" "gF"))))] + "" + "cvtfl %1,%0") + +(define_insn "fix_truncdfqi2" + [(set (match_operand:QI 0 "general_operand" "=g") + (fix:QI (fix:DF (match_operand:DF 1 "general_operand" "gF"))))] + "" + "cvt%#b %1,%0") + +(define_insn "fix_truncdfhi2" + [(set (match_operand:HI 0 "general_operand" "=g") + (fix:HI (fix:DF (match_operand:DF 1 "general_operand" "gF"))))] + "" + "cvt%#w %1,%0") + +(define_insn "fix_truncdfsi2" + [(set (match_operand:SI 0 "general_operand" "=g") + (fix:SI (fix:DF (match_operand:DF 1 "general_operand" "gF"))))] + "" + "cvt%#l %1,%0") + +;;- All kinds of add instructions. + +(define_insn "adddf3" + [(set (match_operand:DF 0 "general_operand" "=g") + (plus:DF (match_operand:DF 1 "general_operand" "gF") + (match_operand:DF 2 "general_operand" "gF")))] + "" + "* +{ + if (rtx_equal_p (operands[0], operands[1])) + return \"add%#2 %2,%0\"; + if (rtx_equal_p (operands[0], operands[2])) + return \"add%#2 %1,%0\"; + return \"add%#3 %1,%2,%0\"; +}") + +(define_insn "addsf3" + [(set (match_operand:SF 0 "general_operand" "=g") + (plus:SF (match_operand:SF 1 "general_operand" "gF") + (match_operand:SF 2 "general_operand" "gF")))] + "" + "* +{ + if (rtx_equal_p (operands[0], operands[1])) + return \"addf2 %2,%0\"; + if (rtx_equal_p (operands[0], operands[2])) + return \"addf2 %1,%0\"; + return \"addf3 %1,%2,%0\"; +}") + +(define_insn "addsi3" + [(set (match_operand:SI 0 "general_operand" "=g") + (plus:SI (match_operand:SI 1 "general_operand" "g") + (match_operand:SI 2 "general_operand" "g")))] + "" + "* +{ + if (rtx_equal_p (operands[0], operands[1])) + { + if (operands[2] == const1_rtx) + return \"incl %0\"; + if (GET_CODE (operands[2]) == CONST_INT + && INTVAL (operands[2]) == -1) + return \"decl %0\"; + if (GET_CODE (operands[2]) == CONST_INT + && (unsigned) (- INTVAL (operands[2])) < 64) + return \"subl2 $%n2,%0\"; + if (GET_CODE (operands[2]) == CONST_INT + && (unsigned) INTVAL (operands[2]) >= 64 + && GET_CODE (operands[1]) == REG) + return \"movab %c2(%1),%0\"; + return \"addl2 %2,%0\"; + } + if (rtx_equal_p (operands[0], operands[2])) + return \"addl2 %1,%0\"; + if (GET_CODE (operands[2]) == CONST_INT + && (unsigned) (- INTVAL (operands[2])) < 64) + return \"subl3 $%n2,%1,%0\"; + if (GET_CODE (operands[2]) == CONST_INT + && (unsigned) INTVAL (operands[2]) >= 64 + && GET_CODE (operands[1]) == REG) + { + if (push_operand (operands[0], SImode)) + return \"pushab %c2(%1)\"; + return \"movab %c2(%1),%0\"; + } + return \"addl3 %1,%2,%0\"; +}") + +(define_insn "addhi3" + [(set (match_operand:HI 0 "general_operand" "=g") + (plus:HI (match_operand:HI 1 "general_operand" "g") + (match_operand:HI 2 "general_operand" "g")))] + "" + "* +{ + if (rtx_equal_p (operands[0], operands[1])) + { + if (operands[2] == const1_rtx) + return \"incw %0\"; + if (GET_CODE (operands[1]) == CONST_INT + && INTVAL (operands[1]) == -1) + return \"decw %0\"; + if (GET_CODE (operands[2]) == CONST_INT + && (unsigned) (- INTVAL (operands[2])) < 64) + return \"subw2 $%n2,%0\"; + return \"addw2 %2,%0\"; + } + if (rtx_equal_p (operands[0], operands[2])) + return \"addw2 %1,%0\"; + if (GET_CODE (operands[2]) == CONST_INT + && (unsigned) (- INTVAL (operands[2])) < 64) + return \"subw3 $%n2,%1,%0\"; + return \"addw3 %1,%2,%0\"; +}") + +(define_insn "addqi3" + [(set (match_operand:QI 0 "general_operand" "=g") + (plus:QI (match_operand:QI 1 "general_operand" "g") + (match_operand:QI 2 "general_operand" "g")))] + "" + "* +{ + if (rtx_equal_p (operands[0], operands[1])) + { + if (operands[2] == const1_rtx) + return \"incb %0\"; + if (GET_CODE (operands[1]) == CONST_INT + && INTVAL (operands[1]) == -1) + return \"decb %0\"; + if (GET_CODE (operands[2]) == CONST_INT + && (unsigned) (- INTVAL (operands[2])) < 64) + return \"subb2 $%n2,%0\"; + return \"addb2 %2,%0\"; + } + if (rtx_equal_p (operands[0], operands[2])) + return \"addb2 %1,%0\"; + if (GET_CODE (operands[2]) == CONST_INT + && (unsigned) (- INTVAL (operands[2])) < 64) + return \"subb3 $%n2,%1,%0\"; + return \"addb3 %1,%2,%0\"; +}") + +;;- All kinds of subtract instructions. + +(define_insn "subdf3" + [(set (match_operand:DF 0 "general_operand" "=g") + (minus:DF (match_operand:DF 1 "general_operand" "gF") + (match_operand:DF 2 "general_operand" "gF")))] + "" + "* +{ + if (rtx_equal_p (operands[0], operands[1])) + return \"sub%#2 %2,%0\"; + return \"sub%#3 %2,%1,%0\"; +}") + +(define_insn "subsf3" + [(set (match_operand:SF 0 "general_operand" "=g") + (minus:SF (match_operand:SF 1 "general_operand" "gF") + (match_operand:SF 2 "general_operand" "gF")))] + "" + "* +{ + if (rtx_equal_p (operands[0], operands[1])) + return \"subf2 %2,%0\"; + return \"subf3 %2,%1,%0\"; +}") + +(define_insn "subsi3" + [(set (match_operand:SI 0 "general_operand" "=g") + (minus:SI (match_operand:SI 1 "general_operand" "g") + (match_operand:SI 2 "general_operand" "g")))] + "" + "* +{ + if (rtx_equal_p (operands[0], operands[1])) + { + if (operands[2] == const1_rtx) + return \"decl %0\"; + return \"subl2 %2,%0\"; + } + return \"subl3 %2,%1,%0\"; +}") + +(define_insn "subhi3" + [(set (match_operand:HI 0 "general_operand" "=g") + (minus:HI (match_operand:HI 1 "general_operand" "g") + (match_operand:HI 2 "general_operand" "g")))] + "" + "* +{ + if (rtx_equal_p (operands[0], operands[1])) + { + if (operands[2] == const1_rtx) + return \"decw %0\"; + return \"subw2 %2,%0\"; + } + return \"subw3 %2,%1,%0\"; +}") + +(define_insn "subqi3" + [(set (match_operand:QI 0 "general_operand" "=g") + (minus:QI (match_operand:QI 1 "general_operand" "g") + (match_operand:QI 2 "general_operand" "g")))] + "" + "* +{ + if (rtx_equal_p (operands[0], operands[1])) + { + if (operands[2] == const1_rtx) + return \"decb %0\"; + return \"subb2 %2,%0\"; + } + return \"subb3 %2,%1,%0\"; +}") + +;;- Multiply instructions. + +(define_insn "muldf3" + [(set (match_operand:DF 0 "general_operand" "=g") + (mult:DF (match_operand:DF 1 "general_operand" "gF") + (match_operand:DF 2 "general_operand" "gF")))] + "" + "* +{ + if (rtx_equal_p (operands[0], operands[1])) + return \"mul%#2 %2,%0\"; + if (rtx_equal_p (operands[0], operands[2])) + return \"mul%#2 %1,%0\"; + return \"mul%#3 %1,%2,%0\"; +}") + +(define_insn "mulsf3" + [(set (match_operand:SF 0 "general_operand" "=g") + (mult:SF (match_operand:SF 1 "general_operand" "gF") + (match_operand:SF 2 "general_operand" "gF")))] + "" + "* +{ + if (rtx_equal_p (operands[0], operands[1])) + return \"mulf2 %2,%0\"; + if (rtx_equal_p (operands[0], operands[2])) + return \"mulf2 %1,%0\"; + return \"mulf3 %1,%2,%0\"; +}") + +(define_insn "mulsi3" + [(set (match_operand:SI 0 "general_operand" "=g") + (mult:SI (match_operand:SI 1 "general_operand" "g") + (match_operand:SI 2 "general_operand" "g")))] + "" + "* +{ + if (rtx_equal_p (operands[0], operands[1])) + return \"mull2 %2,%0\"; + if (rtx_equal_p (operands[0], operands[2])) + return \"mull2 %1,%0\"; + return \"mull3 %1,%2,%0\"; +}") + +(define_insn "mulhi3" + [(set (match_operand:HI 0 "general_operand" "=g") + (mult:HI (match_operand:HI 1 "general_operand" "g") + (match_operand:HI 2 "general_operand" "g")))] + "" + "* +{ + if (rtx_equal_p (operands[0], operands[1])) + return \"mulw2 %2,%0\"; + if (rtx_equal_p (operands[0], operands[2])) + return \"mulw2 %1,%0\"; + return \"mulw3 %1,%2,%0\"; +}") + +(define_insn "mulqi3" + [(set (match_operand:QI 0 "general_operand" "=g") + (mult:QI (match_operand:QI 1 "general_operand" "g") + (match_operand:QI 2 "general_operand" "g")))] + "" + "* +{ + if (rtx_equal_p (operands[0], operands[1])) + return \"mulb2 %2,%0\"; + if (rtx_equal_p (operands[0], operands[2])) + return \"mulb2 %1,%0\"; + return \"mulb3 %1,%2,%0\"; +}") + +;;- Divide instructions. + +(define_insn "divdf3" + [(set (match_operand:DF 0 "general_operand" "=g") + (div:DF (match_operand:DF 1 "general_operand" "gF") + (match_operand:DF 2 "general_operand" "gF")))] + "" + "* +{ + if (rtx_equal_p (operands[0], operands[1])) + return \"div%#2 %2,%0\"; + return \"div%#3 %2,%1,%0\"; +}") + +(define_insn "divsf3" + [(set (match_operand:SF 0 "general_operand" "=g") + (div:SF (match_operand:SF 1 "general_operand" "gF") + (match_operand:SF 2 "general_operand" "gF")))] + "" + "* +{ + if (rtx_equal_p (operands[0], operands[1])) + return \"divf2 %2,%0\"; + return \"divf3 %2,%1,%0\"; +}") + +(define_insn "divsi3" + [(set (match_operand:SI 0 "general_operand" "=g") + (div:SI (match_operand:SI 1 "general_operand" "g") + (match_operand:SI 2 "general_operand" "g")))] + "" + "* +{ + if (rtx_equal_p (operands[0], operands[1])) + return \"divl2 %2,%0\"; + return \"divl3 %2,%1,%0\"; +}") + +(define_insn "divhi3" + [(set (match_operand:HI 0 "general_operand" "=g") + (div:HI (match_operand:HI 1 "general_operand" "g") + (match_operand:HI 2 "general_operand" "g")))] + "" + "* +{ + if (rtx_equal_p (operands[0], operands[1])) + return \"divw2 %2,%0\"; + return \"divw3 %2,%1,%0\"; +}") + +(define_insn "divqi3" + [(set (match_operand:QI 0 "general_operand" "=g") + (div:QI (match_operand:QI 1 "general_operand" "g") + (match_operand:QI 2 "general_operand" "g")))] + "" + "* +{ + if (rtx_equal_p (operands[0], operands[1])) + return \"divb2 %2,%0\"; + return \"divb3 %2,%1,%0\"; +}") + +;This is left out because it is very slow; +;we are better off programming around the "lack" of this insn. +;(define_insn "divmoddisi4" +; [(set (match_operand:SI 0 "general_operand" "=g") +; (div:SI (match_operand:DI 1 "general_operand" "g") +; (match_operand:SI 2 "general_operand" "g"))) +; (set (match_operand:SI 3 "general_operand" "=g") +; (mod:SI (match_operand:DI 1 "general_operand" "g") +; (match_operand:SI 2 "general_operand" "g")))] +; "" +; "ediv %2,%1,%0,%3") + +;; Bit-and on the vax is done with a clear-bits insn. +(define_expand "andsi3" + [(set (match_operand:SI 0 "general_operand" "=g") + (and:SI (match_operand:SI 1 "general_operand" "g") + (not:SI (match_operand:SI 2 "general_operand" "g"))))] + "" + " +{ + extern rtx expand_unop (); + if (GET_CODE (operands[2]) == CONST_INT) + operands[2] = gen_rtx (CONST_INT, VOIDmode, ~INTVAL (operands[2])); + else + operands[2] = expand_unop (SImode, one_cmpl_optab, operands[2], 0, 1); +}") + +(define_expand "andhi3" + [(set (match_operand:HI 0 "general_operand" "=g") + (and:HI (match_operand:HI 1 "general_operand" "g") + (not:HI (match_operand:HI 2 "general_operand" "g"))))] + "" + " +{ + extern rtx expand_unop (); + rtx op = operands[2]; + if (GET_CODE (op) == CONST_INT) + operands[2] = gen_rtx (CONST_INT, VOIDmode, + ((1 << 16) - 1) & ~INTVAL (op)); + else + operands[2] = expand_unop (HImode, one_cmpl_optab, op, 0, 1); +}") + +(define_expand "andqi3" + [(set (match_operand:QI 0 "general_operand" "=g") + (and:QI (match_operand:QI 1 "general_operand" "g") + (not:QI (match_operand:QI 2 "general_operand" "g"))))] + "" + " +{ + extern rtx expand_unop (); + rtx op = operands[2]; + if (GET_CODE (op) == CONST_INT) + operands[2] = gen_rtx (CONST_INT, VOIDmode, + ((1 << 8) - 1) & ~INTVAL (op)); + else + operands[2] = expand_unop (QImode, one_cmpl_optab, op, 0, 1); +}") + +(define_insn "andcbsi3" + [(set (match_operand:SI 0 "general_operand" "=g") + (and:SI (match_operand:SI 1 "general_operand" "g") + (not:SI (match_operand:SI 2 "general_operand" "g"))))] + "" + "* +{ + if (rtx_equal_p (operands[0], operands[1])) + return \"bicl2 %2,%0\"; + return \"bicl3 %2,%1,%0\"; +}") + +(define_insn "andcbhi3" + [(set (match_operand:HI 0 "general_operand" "=g") + (and:HI (match_operand:HI 1 "general_operand" "g") + (not:HI (match_operand:HI 2 "general_operand" "g"))))] + "" + "* +{ + if (rtx_equal_p (operands[0], operands[1])) + return \"bicw2 %2,%0\"; + return \"bicw3 %2,%1,%0\"; +}") + +(define_insn "andcbqi3" + [(set (match_operand:QI 0 "general_operand" "=g") + (and:QI (match_operand:QI 1 "general_operand" "g") + (not:QI (match_operand:QI 2 "general_operand" "g"))))] + "" + "* +{ + if (rtx_equal_p (operands[0], operands[1])) + return \"bicb2 %2,%0\"; + return \"bicb3 %2,%1,%0\"; +}") + +;; The following are needed because constant propagation can +;; create them starting from the bic insn patterns above. + +(define_insn "" + [(set (match_operand:SI 0 "general_operand" "=g") + (and:SI (match_operand:SI 1 "general_operand" "g") + (match_operand:SI 2 "general_operand" "g")))] + "GET_CODE (operands[2]) == CONST_INT" + "* +{ operands[2] = gen_rtx (CONST_INT, VOIDmode, ~INTVAL (operands[2])); + if (rtx_equal_p (operands[1], operands[0])) + return \"bicl2 %2,%0\"; + return \"bicl3 %2,%1,%0\"; +}") + +(define_insn "" + [(set (match_operand:HI 0 "general_operand" "=g") + (and:HI (match_operand:HI 1 "general_operand" "g") + (match_operand:HI 2 "general_operand" "g")))] + "GET_CODE (operands[2]) == CONST_INT" + "* +{ operands[2] = gen_rtx (CONST_INT, VOIDmode, 0xffff & ~INTVAL (operands[2])); + if (rtx_equal_p (operands[1], operands[0])) + return \"bicw2 %2,%0\"; + return \"bicw3 %2,%1,%0\"; +}") + +(define_insn "" + [(set (match_operand:QI 0 "general_operand" "=g") + (and:QI (match_operand:QI 1 "general_operand" "g") + (match_operand:QI 2 "general_operand" "g")))] + "GET_CODE (operands[2]) == CONST_INT" + "* +{ operands[2] = gen_rtx (CONST_INT, VOIDmode, 0xff & ~INTVAL (operands[2])); + if (rtx_equal_p (operands[1], operands[0])) + return \"bicb2 %2,%0\"; + return \"bicb3 %2,%1,%0\"; +}") + +;;- Bit set instructions. + +(define_insn "iorsi3" + [(set (match_operand:SI 0 "general_operand" "=g") + (ior:SI (match_operand:SI 1 "general_operand" "g") + (match_operand:SI 2 "general_operand" "g")))] + "" + "* +{ + if (rtx_equal_p (operands[0], operands[1])) + return \"bisl2 %2,%0\"; + if (rtx_equal_p (operands[0], operands[2])) + return \"bisl2 %1,%0\"; + return \"bisl3 %2,%1,%0\"; +}") + +(define_insn "iorhi3" + [(set (match_operand:HI 0 "general_operand" "=g") + (ior:HI (match_operand:HI 1 "general_operand" "g") + (match_operand:HI 2 "general_operand" "g")))] + "" + "* +{ + if (rtx_equal_p (operands[0], operands[1])) + return \"bisw2 %2,%0\"; + if (rtx_equal_p (operands[0], operands[2])) + return \"bisw2 %1,%0\"; + return \"bisw3 %2,%1,%0\"; +}") + +(define_insn "iorqi3" + [(set (match_operand:QI 0 "general_operand" "=g") + (ior:QI (match_operand:QI 1 "general_operand" "g") + (match_operand:QI 2 "general_operand" "g")))] + "" + "* +{ + if (rtx_equal_p (operands[0], operands[1])) + return \"bisb2 %2,%0\"; + if (rtx_equal_p (operands[0], operands[2])) + return \"bisb2 %1,%0\"; + return \"bisb3 %2,%1,%0\"; +}") + +;;- xor instructions. + +(define_insn "xorsi3" + [(set (match_operand:SI 0 "general_operand" "=g") + (xor:SI (match_operand:SI 1 "general_operand" "g") + (match_operand:SI 2 "general_operand" "g")))] + "" + "* +{ + if (rtx_equal_p (operands[0], operands[1])) + return \"xorl2 %2,%0\"; + if (rtx_equal_p (operands[0], operands[2])) + return \"xorl2 %1,%0\"; + return \"xorl3 %2,%1,%0\"; +}") + +(define_insn "xorhi3" + [(set (match_operand:HI 0 "general_operand" "=g") + (xor:HI (match_operand:HI 1 "general_operand" "g") + (match_operand:HI 2 "general_operand" "g")))] + "" + "* +{ + if (rtx_equal_p (operands[0], operands[1])) + return \"xorw2 %2,%0\"; + if (rtx_equal_p (operands[0], operands[2])) + return \"xorw2 %1,%0\"; + return \"xorw3 %2,%1,%0\"; +}") + +(define_insn "xorqi3" + [(set (match_operand:QI 0 "general_operand" "=g") + (xor:QI (match_operand:QI 1 "general_operand" "g") + (match_operand:QI 2 "general_operand" "g")))] + "" + "* +{ + if (rtx_equal_p (operands[0], operands[1])) + return \"xorb2 %2,%0\"; + if (rtx_equal_p (operands[0], operands[2])) + return \"xorb2 %1,%0\"; + return \"xorb3 %2,%1,%0\"; +}") + +(define_insn "negdf2" + [(set (match_operand:DF 0 "general_operand" "=g") + (neg:DF (match_operand:DF 1 "general_operand" "gF")))] + "" + "mneg%# %1,%0") + +(define_insn "negsf2" + [(set (match_operand:SF 0 "general_operand" "=g") + (neg:SF (match_operand:SF 1 "general_operand" "gF")))] + "" + "mnegf %1,%0") + +(define_insn "negsi2" + [(set (match_operand:SI 0 "general_operand" "=g") + (neg:SI (match_operand:SI 1 "general_operand" "g")))] + "" + "mnegl %1,%0") + +(define_insn "neghi2" + [(set (match_operand:HI 0 "general_operand" "=g") + (neg:HI (match_operand:HI 1 "general_operand" "g")))] + "" + "mnegw %1,%0") + +(define_insn "negqi2" + [(set (match_operand:QI 0 "general_operand" "=g") + (neg:QI (match_operand:QI 1 "general_operand" "g")))] + "" + "mnegb %1,%0") + +(define_insn "one_cmplsi2" + [(set (match_operand:SI 0 "general_operand" "=g") + (not:SI (match_operand:SI 1 "general_operand" "g")))] + "" + "mcoml %1,%0") + +(define_insn "one_cmplhi2" + [(set (match_operand:HI 0 "general_operand" "=g") + (not:HI (match_operand:HI 1 "general_operand" "g")))] + "" + "mcomw %1,%0") + +(define_insn "one_cmplqi2" + [(set (match_operand:QI 0 "general_operand" "=g") + (not:QI (match_operand:QI 1 "general_operand" "g")))] + "" + "mcomb %1,%0") + +;; Arithmetic right shift on the vax works by negating the shift count. +(define_expand "ashrsi3" + [(set (match_operand:SI 0 "general_operand" "=g") + (ashift:SI (match_operand:SI 1 "general_operand" "g") + (match_operand:QI 2 "general_operand" "g")))] + "" + " +{ + operands[2] = negate_rtx (QImode, operands[2]); +}") + +(define_insn "ashlsi3" + [(set (match_operand:SI 0 "general_operand" "=g") + (ashift:SI (match_operand:SI 1 "general_operand" "g") + (match_operand:QI 2 "general_operand" "g")))] + "" + "* +{ + if (operands[2] == const1_rtx && rtx_equal_p (operands[0], operands[1])) + return \"addl2 %0,%0\"; + if (GET_CODE (operands[1]) == REG + && GET_CODE (operands[2]) == CONST_INT) + { + int i = INTVAL (operands[2]); + if (i == 1) + return \"addl3 %1,%1,%0\"; + if (i == 2) + return \"moval 0[%1],%0\"; + if (i == 3) + return \"movad 0[%1],%0\"; + } + return \"ashl %2,%1,%0\"; +}") + +;; Arithmetic right shift on the vax works by negating the shift count. +(define_expand "ashrdi3" + [(set (match_operand:DI 0 "general_operand" "=g") + (ashift:DI (match_operand:DI 1 "general_operand" "g") + (match_operand:QI 2 "general_operand" "g")))] + "" + " +{ + operands[2] = negate_rtx (QImode, operands[2]); +}") + +(define_insn "ashldi3" + [(set (match_operand:DI 0 "general_operand" "=g") + (ashift:DI (match_operand:DI 1 "general_operand" "g") + (match_operand:QI 2 "general_operand" "g")))] + "" + "ashq %2,%1,%0") + +;; Rotate right on the vax works by negating the shift count. +(define_expand "rotrsi3" + [(set (match_operand:SI 0 "general_operand" "=g") + (rotate:SI (match_operand:SI 1 "general_operand" "g") + (match_operand:QI 2 "general_operand" "g")))] + "" + " +{ + operands[2] = negate_rtx (QImode, operands[2]); +}") + +(define_insn "rotlsi3" + [(set (match_operand:SI 0 "general_operand" "=g") + (rotate:SI (match_operand:SI 1 "general_operand" "g") + (match_operand:QI 2 "general_operand" "g")))] + "" + "rotl %2,%1,%0") + +;This insn is probably slower than a multiply and an add. +;(define_insn "" +; [(set (match_operand:SI 0 "general_operand" "=g") +; (mult:SI (plus:SI (match_operand:SI 1 "general_operand" "g") +; (match_operand:SI 2 "general_operand" "g")) +; (match_operand:SI 3 "general_operand" "g")))] +; "" +; "index %1,$0x80000000,$0x7fffffff,%3,%2,%0") + +;; Special cases of bit-field insns which we should +;; recognize in preference to the general case. +;; These handle aligned 8-bit and 16-bit fields, +;; which can usually be done with move instructions. + +(define_insn "" + [(set (zero_extract:SI (match_operand:SI 0 "general_operand" "+ro") + (match_operand:SI 1 "immediate_operand" "i") + (match_operand:SI 2 "immediate_operand" "i")) + (match_operand:SI 3 "general_operand" "g"))] + "GET_CODE (operands[1]) == CONST_INT + && (INTVAL (operands[1]) == 8 || INTVAL (operands[1]) == 16) + && GET_CODE (operands[2]) == CONST_INT + && INTVAL (operands[2]) % INTVAL (operands[1]) == 0 + && (GET_CODE (operands[0]) == REG + || ! mode_dependent_address_p (XEXP (operands[0], 0)))" + "* +{ + if (REG_P (operands[0])) + { + if (INTVAL (operands[2]) != 0) + return \"insv %3,%2,%1,%0\"; + } + else + operands[0] + = adj_offsettable_operand (operands[0], INTVAL (operands[2]) / 8); + + if (INTVAL (operands[1]) == 8) + return \"movb %3,%0\"; + return \"movw %3,%0\"; +}") + +(define_insn "" + [(set (match_operand:SI 0 "general_operand" "=&g") + (zero_extract:SI (match_operand:SI 1 "general_operand" "ro") + (match_operand:SI 2 "immediate_operand" "i") + (match_operand:SI 3 "immediate_operand" "i")))] + "GET_CODE (operands[2]) == CONST_INT + && (INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 16) + && GET_CODE (operands[3]) == CONST_INT + && INTVAL (operands[3]) % INTVAL (operands[2]) == 0 + && (GET_CODE (operands[1]) == REG + || ! mode_dependent_address_p (XEXP (operands[1], 0)))" + "* +{ + if (REG_P (operands[1])) + { + if (INTVAL (operands[3]) != 0) + return \"extzv %3,%2,%1,%0\"; + } + else + operands[1] + = adj_offsettable_operand (operands[1], INTVAL (operands[3]) / 8); + + if (INTVAL (operands[2]) == 8) + return \"movzbl %1,%0\"; + return \"movzwl %1,%0\"; +}") + +(define_insn "" + [(set (match_operand:SI 0 "general_operand" "=g") + (sign_extract:SI (match_operand:SI 1 "general_operand" "ro") + (match_operand:SI 2 "immediate_operand" "i") + (match_operand:SI 3 "immediate_operand" "i")))] + "GET_CODE (operands[2]) == CONST_INT + && (INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 16) + && GET_CODE (operands[3]) == CONST_INT + && INTVAL (operands[3]) % INTVAL (operands[2]) == 0 + && (GET_CODE (operands[1]) == REG + || ! mode_dependent_address_p (XEXP (operands[1], 0)))" + "* +{ + if (REG_P (operands[1])) + { + if (INTVAL (operands[3]) != 0) + return \"extv %3,%2,%1,%0\"; + } + else + operands[1] + = adj_offsettable_operand (operands[1], INTVAL (operands[3]) / 8); + + if (INTVAL (operands[2]) == 8) + return \"cvtbl %1,%0\"; + return \"cvtwl %1,%0\"; +}") + +;; Register-only SImode cases of bit-field insns. + +(define_insn "" + [(set (cc0) + (compare + (sign_extract:SI (match_operand:SI 0 "general_operand" "r") + (match_operand:SI 1 "general_operand" "g") + (match_operand:SI 2 "general_operand" "g")) + (match_operand:SI 3 "general_operand" "g")))] + "" + "cmpv %2,%1,%0,%3") + +(define_insn "" + [(set (cc0) + (compare + (zero_extract:SI (match_operand:SI 0 "general_operand" "r") + (match_operand:SI 1 "general_operand" "g") + (match_operand:SI 2 "general_operand" "g")) + (match_operand:SI 3 "general_operand" "g")))] + "" + "cmpzv %2,%1,%0,%3") + +(define_insn "" + [(set (match_operand:SI 0 "general_operand" "=g") + (sign_extract:SI (match_operand:SI 1 "general_operand" "r") + (match_operand:SI 2 "general_operand" "g") + (match_operand:SI 3 "general_operand" "g")))] + "" + "extv %3,%2,%1,%0") + +(define_insn "" + [(set (match_operand:SI 0 "general_operand" "=g") + (zero_extract:SI (match_operand:SI 1 "general_operand" "r") + (match_operand:SI 2 "general_operand" "g") + (match_operand:SI 3 "general_operand" "g")))] + "" + "extzv %3,%2,%1,%0") + +;; Non-register cases. +;; nonimmediate_operand is used to make sure that mode-ambiguous cases +;; don't match these (and therefore match the cases above instead). + +(define_insn "" + [(set (cc0) + (compare + (sign_extract:SI (match_operand:QI 0 "nonimmediate_operand" "rm") + (match_operand:SI 1 "general_operand" "g") + (match_operand:SI 2 "general_operand" "g")) + (match_operand:SI 3 "general_operand" "g")))] + "" + "cmpv %2,%1,%0,%3") + +(define_insn "" + [(set (cc0) + (compare + (zero_extract:SI (match_operand:QI 0 "nonimmediate_operand" "rm") + (match_operand:SI 1 "general_operand" "g") + (match_operand:SI 2 "general_operand" "g")) + (match_operand:SI 3 "general_operand" "g")))] + "" + "cmpzv %2,%1,%0,%3") + +(define_insn "extv" + [(set (match_operand:SI 0 "general_operand" "=g") + (sign_extract:SI (match_operand:QI 1 "nonimmediate_operand" "rm") + (match_operand:SI 2 "general_operand" "g") + (match_operand:SI 3 "general_operand" "g")))] + "" + "extv %3,%2,%1,%0") + +(define_insn "extzv" + [(set (match_operand:SI 0 "general_operand" "=g") + (zero_extract:SI (match_operand:QI 1 "nonimmediate_operand" "rm") + (match_operand:SI 2 "general_operand" "g") + (match_operand:SI 3 "general_operand" "g")))] + "" + "extzv %3,%2,%1,%0") + +(define_insn "insv" + [(set (zero_extract:SI (match_operand:QI 0 "general_operand" "+g") + (match_operand:SI 1 "general_operand" "g") + (match_operand:SI 2 "general_operand" "g")) + (match_operand:SI 3 "general_operand" "g"))] + "" + "insv %3,%2,%1,%0") + +(define_insn "" + [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r") + (match_operand:SI 1 "general_operand" "g") + (match_operand:SI 2 "general_operand" "g")) + (match_operand:SI 3 "general_operand" "g"))] + "" + "insv %3,%2,%1,%0") + +(define_insn "jump" + [(set (pc) + (label_ref (match_operand 0 "" "")))] + "" + "jbr %l0") + +(define_insn "beq" + [(set (pc) + (if_then_else (eq (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "jeql %l0") + +(define_insn "bne" + [(set (pc) + (if_then_else (ne (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "jneq %l0") + +(define_insn "bgt" + [(set (pc) + (if_then_else (gt (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "jgtr %l0") + +(define_insn "bgtu" + [(set (pc) + (if_then_else (gtu (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "jgtru %l0") + +(define_insn "blt" + [(set (pc) + (if_then_else (lt (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "jlss %l0") + +(define_insn "bltu" + [(set (pc) + (if_then_else (ltu (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "jlssu %l0") + +(define_insn "bge" + [(set (pc) + (if_then_else (ge (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "jgeq %l0") + +(define_insn "bgeu" + [(set (pc) + (if_then_else (geu (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "jgequ %l0") + +(define_insn "ble" + [(set (pc) + (if_then_else (le (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "jleq %l0") + +(define_insn "bleu" + [(set (pc) + (if_then_else (leu (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "jlequ %l0") + +(define_insn "" + [(set (pc) + (if_then_else (eq (cc0) + (const_int 0)) + (pc) + (label_ref (match_operand 0 "" ""))))] + "" + "jneq %l0") + +(define_insn "" + [(set (pc) + (if_then_else (ne (cc0) + (const_int 0)) + (pc) + (label_ref (match_operand 0 "" ""))))] + "" + "jeql %l0") + +(define_insn "" + [(set (pc) + (if_then_else (gt (cc0) + (const_int 0)) + (pc) + (label_ref (match_operand 0 "" ""))))] + "" + "jleq %l0") + +(define_insn "" + [(set (pc) + (if_then_else (gtu (cc0) + (const_int 0)) + (pc) + (label_ref (match_operand 0 "" ""))))] + "" + "jlequ %l0") + +(define_insn "" + [(set (pc) + (if_then_else (lt (cc0) + (const_int 0)) + (pc) + (label_ref (match_operand 0 "" ""))))] + "" + "jgeq %l0") + +(define_insn "" + [(set (pc) + (if_then_else (ltu (cc0) + (const_int 0)) + (pc) + (label_ref (match_operand 0 "" ""))))] + "" + "jgequ %l0") + +(define_insn "" + [(set (pc) + (if_then_else (ge (cc0) + (const_int 0)) + (pc) + (label_ref (match_operand 0 "" ""))))] + "" + "jlss %l0") + +(define_insn "" + [(set (pc) + (if_then_else (geu (cc0) + (const_int 0)) + (pc) + (label_ref (match_operand 0 "" ""))))] + "" + "jlssu %l0") + +(define_insn "" + [(set (pc) + (if_then_else (le (cc0) + (const_int 0)) + (pc) + (label_ref (match_operand 0 "" ""))))] + "" + "jgtr %l0") + +(define_insn "" + [(set (pc) + (if_then_else (leu (cc0) + (const_int 0)) + (pc) + (label_ref (match_operand 0 "" ""))))] + "" + "jgtru %l0") + +;; Recognize jlbs and jlbc insns. +;; These come before the jbc and jbs recognizers so these will be preferred. + +(define_insn "" + [(set (pc) + (if_then_else + (ne (and:SI (match_operand:SI 0 "general_operand" "g") + (const_int 1)) + (const_int 0)) + (label_ref (match_operand 1 "" "")) + (pc)))] + "GET_CODE (operands[0]) != MEM + || ! mode_dependent_address_p (XEXP (operands[0], 0))" + "jlbs %0,%l1") + +(define_insn "" + [(set (pc) + (if_then_else + (eq (and:SI (match_operand:SI 0 "general_operand" "g") + (const_int 1)) + (const_int 0)) + (label_ref (match_operand 1 "" "")) + (pc)))] + "GET_CODE (operands[0]) != MEM + || ! mode_dependent_address_p (XEXP (operands[0], 0))" + "jlbc %0,%l1") + +(define_insn "" + [(set (pc) + (if_then_else + (ne (and:SI (match_operand:SI 0 "general_operand" "g") + (const_int 1)) + (const_int 0)) + (pc) + (label_ref (match_operand 1 "" ""))))] + "GET_CODE (operands[0]) != MEM + || ! mode_dependent_address_p (XEXP (operands[0], 0))" + "jlbc %0,%l1") + +(define_insn "" + [(set (pc) + (if_then_else + (eq (and:SI (match_operand:SI 0 "general_operand" "g") + (const_int 1)) + (const_int 0)) + (pc) + (label_ref (match_operand 1 "" ""))))] + "GET_CODE (operands[0]) != MEM + || ! mode_dependent_address_p (XEXP (operands[0], 0))" + "jlbs %0,%l1") + +;; These four entries allow a jlbc or jlbs to be made +;; by combination with a bic. +(define_insn "" + [(set (pc) + (if_then_else + (ne (and:SI (match_operand:SI 0 "general_operand" "g") + (not:SI (const_int -2))) + (const_int 0)) + (label_ref (match_operand 1 "" "")) + (pc)))] + "GET_CODE (operands[0]) != MEM + || ! mode_dependent_address_p (XEXP (operands[0], 0))" + "jlbs %0,%l1") + +(define_insn "" + [(set (pc) + (if_then_else + (eq (and:SI (match_operand:SI 0 "general_operand" "g") + (not:SI (const_int -2))) + (const_int 0)) + (label_ref (match_operand 1 "" "")) + (pc)))] + "GET_CODE (operands[0]) != MEM + || ! mode_dependent_address_p (XEXP (operands[0], 0))" + "jlbc %0,%l1") + +(define_insn "" + [(set (pc) + (if_then_else + (ne (and:SI (match_operand:SI 0 "general_operand" "g") + (not:SI (const_int -2))) + (const_int 0)) + (pc) + (label_ref (match_operand 1 "" ""))))] + "GET_CODE (operands[0]) != MEM + || ! mode_dependent_address_p (XEXP (operands[0], 0))" + "jlbc %0,%l1") + +(define_insn "" + [(set (pc) + (if_then_else + (eq (and:SI (match_operand:SI 0 "general_operand" "g") + (not:SI (const_int -2))) + (const_int 0)) + (pc) + (label_ref (match_operand 1 "" ""))))] + "GET_CODE (operands[0]) != MEM + || ! mode_dependent_address_p (XEXP (operands[0], 0))" + "jlbs %0,%l1") + +;; Recognize jbs and jbc instructions. + +(define_insn "" + [(set (pc) + (if_then_else + (ne (sign_extract:SI (match_operand:QI 0 "general_operand" "g") + (const_int 1) + (match_operand:SI 1 "general_operand" "g")) + (const_int 0)) + (label_ref (match_operand 2 "" "")) + (pc)))] + "" + "jbs %1,%0,%l2") + +(define_insn "" + [(set (pc) + (if_then_else + (eq (sign_extract:SI (match_operand:QI 0 "general_operand" "g") + (const_int 1) + (match_operand:SI 1 "general_operand" "g")) + (const_int 0)) + (label_ref (match_operand 2 "" "")) + (pc)))] + "" + "jbc %1,%0,%l2") + +(define_insn "" + [(set (pc) + (if_then_else + (ne (sign_extract:SI (match_operand:QI 0 "general_operand" "g") + (const_int 1) + (match_operand:SI 1 "general_operand" "g")) + (const_int 0)) + (pc) + (label_ref (match_operand 2 "" ""))))] + "" + "jbc %1,%0,%l2") + +(define_insn "" + [(set (pc) + (if_then_else + (eq (sign_extract:SI (match_operand:QI 0 "general_operand" "g") + (const_int 1) + (match_operand:SI 1 "general_operand" "g")) + (const_int 0)) + (pc) + (label_ref (match_operand 2 "" ""))))] + "" + "jbs %1,%0,%l2") + +(define_insn "" + [(set (pc) + (if_then_else + (ne (sign_extract:SI (match_operand:SI 0 "general_operand" "r") + (const_int 1) + (match_operand:SI 1 "general_operand" "g")) + (const_int 0)) + (label_ref (match_operand 2 "" "")) + (pc)))] + "GET_CODE (operands[0]) != MEM + || ! mode_dependent_address_p (XEXP (operands[0], 0))" + "jbs %1,%0,%l2") + +(define_insn "" + [(set (pc) + (if_then_else + (eq (sign_extract:SI (match_operand:SI 0 "general_operand" "r") + (const_int 1) + (match_operand:SI 1 "general_operand" "g")) + (const_int 0)) + (label_ref (match_operand 2 "" "")) + (pc)))] + "GET_CODE (operands[0]) != MEM + || ! mode_dependent_address_p (XEXP (operands[0], 0))" + "jbc %1,%0,%l2") + +(define_insn "" + [(set (pc) + (if_then_else + (eq (and:SI (match_operand:SI 0 "general_operand" "g") + (match_operand:SI 1 "general_operand" "g")) + (const_int 0)) + (pc) + (label_ref (match_operand 2 "" ""))))] + "GET_CODE (operands[1]) == CONST_INT + && exact_log2 (INTVAL (operands[1])) >= 0 + && (GET_CODE (operands[0]) != MEM + || ! mode_dependent_address_p (XEXP (operands[0], 0)))" + "* +{ + operands[1] + = gen_rtx (CONST_INT, VOIDmode, exact_log2 (INTVAL (operands[1]))); + return \"jbs %1,%0,%l2\"; +}") + +(define_insn "" + [(set (pc) + (if_then_else + (eq (and:SI (match_operand:SI 0 "general_operand" "g") + (match_operand:SI 1 "general_operand" "g")) + (const_int 0)) + (label_ref (match_operand 2 "" "")) + (pc)))] + "GET_CODE (operands[1]) == CONST_INT + && exact_log2 (INTVAL (operands[1])) >= 0 + && (GET_CODE (operands[0]) != MEM + || ! mode_dependent_address_p (XEXP (operands[0], 0)))" + "* +{ + operands[1] + = gen_rtx (CONST_INT, VOIDmode, exact_log2 (INTVAL (operands[1]))); + return \"jbc %1,%0,%l2\"; +}") + +(define_insn "" + [(set (pc) + (if_then_else + (ne (and:SI (match_operand:SI 0 "general_operand" "g") + (match_operand:SI 1 "general_operand" "g")) + (const_int 0)) + (pc) + (label_ref (match_operand 2 "" ""))))] + "GET_CODE (operands[1]) == CONST_INT + && exact_log2 (INTVAL (operands[1])) >= 0 + && (GET_CODE (operands[0]) != MEM + || ! mode_dependent_address_p (XEXP (operands[0], 0)))" + "* +{ + operands[1] + = gen_rtx (CONST_INT, VOIDmode, exact_log2 (INTVAL (operands[1]))); + return \"jbc %1,%0,%l2\"; +}") + +(define_insn "" + [(set (pc) + (if_then_else + (ne (and:SI (match_operand:SI 0 "general_operand" "g") + (match_operand:SI 1 "general_operand" "g")) + (const_int 0)) + (label_ref (match_operand 2 "" "")) + (pc)))] + "GET_CODE (operands[1]) == CONST_INT + && exact_log2 (INTVAL (operands[1])) >= 0 + && (GET_CODE (operands[0]) != MEM + || ! mode_dependent_address_p (XEXP (operands[0], 0)))" + "* +{ + operands[1] + = gen_rtx (CONST_INT, VOIDmode, exact_log2 (INTVAL (operands[1]))); + return \"jbs %1,%0,%l2\"; +}") + +(define_insn "" + [(set (pc) + (if_then_else + (ne (sign_extract:SI (match_operand:SI 0 "general_operand" "r") + (const_int 1) + (match_operand:SI 1 "general_operand" "g")) + (const_int 0)) + (pc) + (label_ref (match_operand 2 "" ""))))] + "GET_CODE (operands[0]) != MEM + || ! mode_dependent_address_p (XEXP (operands[0], 0))" + "jbc %1,%0,%l2") + +(define_insn "" + [(set (pc) + (if_then_else + (eq (sign_extract:SI (match_operand:SI 0 "general_operand" "r") + (const_int 1) + (match_operand:SI 1 "general_operand" "g")) + (const_int 0)) + (pc) + (label_ref (match_operand 2 "" ""))))] + "GET_CODE (operands[0]) != MEM + || ! mode_dependent_address_p (XEXP (operands[0], 0))" + "jbs %1,%0,%l2") + +;; Subtract-and-jump and Add-and-jump insns. +;; These are not used when output is for the Unix assembler +;; because it does not know how to modify them to reach far. + +;; Normal sob insns. + +(define_insn "" + [(set (pc) + (if_then_else + (gt (plus:SI (match_operand:SI 0 "general_operand" "+g") + (const_int -1)) + (const_int 0)) + (label_ref (match_operand 1 "" "")) + (pc))) + (set (match_dup 0) + (plus:SI (match_dup 0) + (const_int -1)))] + "!TARGET_UNIX_ASM" + "jsobgtr %0,%l1") + +(define_insn "" + [(set (pc) + (if_then_else + (ge (plus:SI (match_operand:SI 0 "general_operand" "+g") + (const_int -1)) + (const_int 0)) + (label_ref (match_operand 1 "" "")) + (pc))) + (set (match_dup 0) + (plus:SI (match_dup 0) + (const_int -1)))] + "!TARGET_UNIX_ASM" + "jsobgeq %0,%l1") + +;; Reversed sob insns. + +(define_insn "" + [(set (pc) + (if_then_else + (le (plus:SI (match_operand:SI 0 "general_operand" "+g") + (const_int -1)) + (const_int 0)) + (pc) + (label_ref (match_operand 1 "" "")))) + (set (match_dup 0) + (plus:SI (match_dup 0) + (const_int -1)))] + "!TARGET_UNIX_ASM" + "jsobgtr %0,%l1") + +(define_insn "" + [(set (pc) + (if_then_else + (lt (plus:SI (match_operand:SI 0 "general_operand" "+g") + (const_int -1)) + (const_int 0)) + (pc) + (label_ref (match_operand 1 "" "")))) + (set (match_dup 0) + (plus:SI (match_dup 0) + (const_int -1)))] + "!TARGET_UNIX_ASM" + "jsobgeq %0,%l1") + +;; Normal aob insns. +(define_insn "" + [(set (pc) + (if_then_else + (lt (compare (plus:SI (match_operand:SI 0 "general_operand" "+g") + (const_int 1)) + (match_operand:SI 1 "general_operand" "g")) + (const_int 0)) + (label_ref (match_operand 2 "" "")) + (pc))) + (set (match_dup 0) + (plus:SI (match_dup 0) + (const_int 1)))] + "!TARGET_UNIX_ASM" + "jaoblss %1,%0,%l2") + +(define_insn "" + [(set (pc) + (if_then_else + (le (compare (plus:SI (match_operand:SI 0 "general_operand" "+g") + (const_int 1)) + (match_operand:SI 1 "general_operand" "g")) + (const_int 0)) + (label_ref (match_operand 2 "" "")) + (pc))) + (set (match_dup 0) + (plus:SI (match_dup 0) + (const_int 1)))] + "!TARGET_UNIX_ASM" + "jaobleq %1,%0,%l2") + +;; Reverse aob insns. +(define_insn "" + [(set (pc) + (if_then_else + (ge (compare (plus:SI (match_operand:SI 0 "general_operand" "+g") + (const_int 1)) + (match_operand:SI 1 "general_operand" "g")) + (const_int 0)) + (pc) + (label_ref (match_operand 2 "" "")))) + (set (match_dup 0) + (plus:SI (match_dup 0) + (const_int 1)))] + "!TARGET_UNIX_ASM" + "jaoblss %1,%0,%l2") + +(define_insn "" + [(set (pc) + (if_then_else + (gt (compare (plus:SI (match_operand:SI 0 "general_operand" "+g") + (const_int 1)) + (match_operand:SI 1 "general_operand" "g")) + (const_int 0)) + (pc) + (label_ref (match_operand 2 "" "")))) + (set (match_dup 0) + (plus:SI (match_dup 0) + (const_int 1)))] + "!TARGET_UNIX_ASM" + "jaobleq %1,%0,%l2") + +;; Something like a sob insn, but compares against -1. +;; This finds `while (foo--)' which was changed to `while (--foo != -1)'. + +(define_insn "" + [(set (pc) + (if_then_else + (ne (compare (plus:SI (match_operand:SI 0 "general_operand" "g") + (const_int -1)) + (const_int -1)) + (const_int 0)) + (label_ref (match_operand 1 "" "")) + (pc))) + (set (match_dup 0) + (plus:SI (match_dup 0) + (const_int -1)))] + "" + "decl %0\;jgequ %l1") + +;; Note that operand 1 is total size of args, in bytes, +;; and what the call insn wants is the number of words. +(define_insn "call" + [(call (match_operand:QI 0 "general_operand" "g") + (match_operand:QI 1 "general_operand" "g"))] + "" + "* + if (INTVAL (operands[1]) > 255 * 4) + /* Vax `calls' really uses only one byte of #args, so pop explicitly. */ + return \"calls $0,%0\;addl2 %1,sp\"; + operands[1] = gen_rtx (CONST_INT, VOIDmode, (INTVAL (operands[1]) + 3)/ 4); + return \"calls %1,%0\"; +") + +(define_insn "call_value" + [(set (match_operand 0 "" "=g") + (call (match_operand:QI 1 "general_operand" "g") + (match_operand:QI 2 "general_operand" "g")))] + "" + "* + if (INTVAL (operands[2]) > 255 * 4) + /* Vax `calls' really uses only one byte of #args, so pop explicitly. */ + return \"calls $0,%1\;addl2 %2,sp\"; + operands[2] = gen_rtx (CONST_INT, VOIDmode, (INTVAL (operands[2]) + 3)/ 4); + return \"calls %2,%1\"; +") + +(define_insn "return" + [(return)] + "" + "ret") + +(define_insn "nop" + [(const_int 0)] + "" + "nop") + +(define_insn "casesi" + [(set (pc) + (if_then_else (le (minus:SI (match_operand:SI 0 "general_operand" "g") + (match_operand:SI 1 "general_operand" "g")) + (match_operand:SI 2 "general_operand" "g")) + (plus:SI (sign_extend:SI + (mem:HI (plus:SI (pc) + (minus:SI (match_dup 0) + (match_dup 1))))) + (label_ref:SI (match_operand 3 "" ""))) + (pc)))] + "" + "casel %0,%1,%2") + +;; This used to arise from the preceding by simplification +;; if operand 1 is zero. Perhaps it is no longer necessary. +(define_insn "" + [(set (pc) + (if_then_else (le (match_operand:SI 0 "general_operand" "g") + (match_operand:SI 1 "general_operand" "g")) + (plus:SI (sign_extend:SI + (mem:HI (plus:SI (pc) + (minus:SI (match_dup 0) + (const_int 0))))) + (label_ref:SI (match_operand 3 "" ""))) + (pc)))] + "" + "casel %0,$0,%1") + +;; This arises from the preceding by simplification if operand 1 is zero. +(define_insn "" + [(set (pc) + (if_then_else (le (match_operand:SI 0 "general_operand" "g") + (match_operand:SI 1 "general_operand" "g")) + (plus:SI (sign_extend:SI + (mem:HI (plus:SI (pc) + (match_dup 0)))) + (label_ref:SI (match_operand 3 "" ""))) + (pc)))] + "" + "casel %0,$0,%1") + +;; This arises from casesi if operand 0 is a constant, in range. +(define_insn "" + [(set (pc) + (plus:SI (sign_extend:SI + (mem:HI (plus:SI (pc) + (match_operand:SI 0 "general_operand" "g")))) + (label_ref:SI (match_operand 3 "" ""))))] + "" + "casel %0,$0,%0") + +;; This arises from the above if both operands are the same. +(define_insn "" + [(set (pc) + (plus:SI (sign_extend:SI (mem:HI (pc))) + (label_ref:SI (match_operand 3 "" ""))))] + "" + "casel $0,$0,$0") + +;;- load or push effective address +;; These come after the move and add/sub patterns +;; because we don't want pushl $1 turned into pushad 1. +;; or addl3 r1,r2,r3 turned into movab 0(r1)[r2],r3. + +(define_insn "" + [(set (match_operand:SI 0 "general_operand" "=g") + (match_operand:QI 1 "address_operand" "p"))] + "" + "* +{ + if (push_operand (operands[0], SImode)) + return \"pushab %a1\"; + return \"movab %a1,%0\"; +}") + +(define_insn "" + [(set (match_operand:SI 0 "general_operand" "=g") + (match_operand:HI 1 "address_operand" "p"))] + "" + "* +{ + if (push_operand (operands[0], SImode)) + return \"pushaw %a1\"; + return \"movaw %a1,%0\"; +}") + +(define_insn "" + [(set (match_operand:SI 0 "general_operand" "=g") + (match_operand:SI 1 "address_operand" "p"))] + "" + "* +{ + if (push_operand (operands[0], SImode)) + return \"pushal %a1\"; + return \"moval %a1,%0\"; +}") + +(define_insn "" + [(set (match_operand:SI 0 "general_operand" "=g") + (match_operand:SF 1 "address_operand" "p"))] + "" + "* +{ + if (push_operand (operands[0], SImode)) + return \"pushaf %a1\"; + return \"movaf %a1,%0\"; +}") + +(define_insn "" + [(set (match_operand:SI 0 "general_operand" "=g") + (match_operand:DF 1 "address_operand" "p"))] + "" + "* +{ + if (push_operand (operands[0], SImode)) + return \"pushad %a1\"; + return \"movad %a1,%0\"; +}") + +;; Optimize extzv ...,z; andl2 ...,z +;; with other operands constant. +(define_peephole + [(set (match_operand:SI 0 "general_operand" "g") + (zero_extract:SI (match_operand:SI 1 "general_operand" "g") + (match_operand:SI 2 "general_operand" "g") + (match_operand:SI 3 "general_operand" "g"))) + (set (match_operand:SI 4 "general_operand" "g") + (and:SI (match_dup 0) + (match_operand:SI 5 "general_operand" "g")))] + "GET_CODE (operands[2]) == CONST_INT + && GET_CODE (operands[3]) == CONST_INT + && (INTVAL (operands[2]) + INTVAL (operands[3])) == 32 + && GET_CODE (operands[5]) == CONST_INT + && dead_or_set_p (insn, operands[0])" + "* +{ + unsigned long mask = INTVAL (operands[5]); + operands[3] = gen_rtx (CONST_INT, VOIDmode, -INTVAL (operands[3])); + + if ((floor_log2 (mask) + 1) >= INTVAL (operands[2])) + mask &= ((1 << INTVAL (operands[2])) - 1); + + operands[5] = gen_rtx (CONST_INT, VOIDmode, ~mask); + if (push_operand (operands[4], SImode)) + { + output_asm_insn (\"rotl %3,%1,%0\", operands); + return \"bicl3 %5,%0,%4\"; + } + else + { + output_asm_insn (\"rotl %3,%1,%4\", operands); + return \"bicl2 %5,%4\"; + } +}") + +;; Optimize andl3 x,y,z; extzv z,....,z + +(define_peephole + [(set (match_operand:SI 0 "general_operand" "g") + (and:SI (match_operand:SI 1 "general_operand" "g") + (match_operand:SI 2 "general_operand" "g"))) + (set (match_operand 3 "general_operand" "g") + (zero_extract:SI (match_dup 0) + (match_operand:SI 4 "general_operand" "g") + (match_operand:SI 5 "general_operand" "g")))] + "GET_CODE (operands[2]) == CONST_INT + && GET_CODE (operands[4]) == CONST_INT + && GET_CODE (operands[5]) == CONST_INT + && (INTVAL (operands[4]) + INTVAL (operands[5])) == 32 + && dead_or_set_p (insn, operands[0])" + "* +{ + unsigned long mask = INTVAL (operands[2]); + + mask &= ~((1 << INTVAL (operands[5])) - 1); + operands[2] = gen_rtx (CONST_INT, VOIDmode, ~mask); + + operands[5] = gen_rtx (CONST_INT, VOIDmode, -INTVAL (operands[5])); + + if (rtx_equal_p (operands[0], operands[1])) + output_asm_insn (\"bicl2 %2,%0\", operands); + else + output_asm_insn (\"bicl3 %2,%1,%0\", operands); + return \"rotl %5,%0,%3\"; +}") + +;;- Local variables: +;;- mode:emacs-lisp +;;- comment-start: ";;- " +;;- eval: (set-syntax-table (copy-sequence (syntax-table))) +;;- eval: (modify-syntax-entry ?[ "(]") +;;- eval: (modify-syntax-entry ?] ")[") +;;- eval: (modify-syntax-entry ?{ "(}") +;;- eval: (modify-syntax-entry ?} "){") +;;- End: |
