From-SVN: r387
50 KiB
;;- Machine description for GNU compiler, Vax Version ;; Copyright (C) 1987, 1988, 1991 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 2, 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.
;; We don't want to allow a constant operand for test insns because ;; (set (cc0) (const_int foo)) has no mode information. Such insns will ;; be folded while optimizing anyway.
(define_insn "tstsi" [(set (cc0) (match_operand:SI 0 "nonimmediate_operand" "g"))] "" "tstl %0")
(define_insn "tsthi" [(set (cc0) (match_operand:HI 0 "nonimmediate_operand" "g"))] "" "tstw %0")
(define_insn "tstqi" [(set (cc0) (match_operand:QI 0 "nonimmediate_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")
(define_insn "cmpsi" [(set (cc0) (compare (match_operand:SI 0 "nonimmediate_operand" "g") (match_operand:SI 1 "general_operand" "g")))] "" "cmpl %0,%1")
(define_insn "cmphi" [(set (cc0) (compare (match_operand:HI 0 "nonimmediate_operand" "g") (match_operand:HI 1 "general_operand" "g")))] "" "cmpw %0,%1")
(define_insn "cmpqi" [(set (cc0) (compare (match_operand:QI 0 "nonimmediate_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")
;; The vax has no sltu or sgeu patterns, but does have two-operand ;; add/subtract with carry. This is still better than the alternative. ;; Since the cc0-using insn cannot be separated from the cc0-setting insn, ;; and the two are created independently, we can't just use a define_expand ;; to try to optimize this. (The "movl" and "clrl" insns alter the cc0 ;; flags, but leave the carry flag alone, but that can't easily be expressed.) ;; ;; Several two-operator combinations could be added to make slightly more ;; optimal code, but they'd have to cover all combinations of plus and minus ;; using match_dup. If you want to do this, I'd suggest changing the "sgeu" ;; pattern to something like (minus (const_int 1) (ltu ...)), so fewer ;; patterns need to be recognized. ;; -- Ken Raeburn (Raeburn@Watch.COM) 24 August 1991.
(define_insn "sltu" [(set (match_operand:SI 0 "general_operand" "=ro") (ltu (cc0) (const_int 0)))] "" "clrl %0;adwc $0,%0")
(define_insn "sgeu" [(set (match_operand:SI 0 "general_operand" "=ro") (geu (cc0) (const_int 0)))] "" "movl $1,%0;sbwc $0,%0") (define_insn "movdf" [(set (match_operand:DF 0 "general_operand" "=g,g") (match_operand:DF 1 "general_operand" "G,gF"))] "" "@ clr%# %0 mov%# %1,%0")
(define_insn "movsf" [(set (match_operand:SF 0 "general_operand" "=g,g") (match_operand:SF 1 "general_operand" "G,gF"))] "" "@ clrf %0 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,g") (match_operand:DI 1 "general_operand" "I,g"))] "" "@ clrq %0 movq %1,%0")
(define_insn "movsi" [(set (match_operand:SI 0 "general_operand" "=g") (match_operand:SI 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. / && ! INSN_DELETED_P (XEXP (link, 0)) && 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. / && ! INSN_DELETED_P (XEXP (link, 0)) && 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"; } } 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.
(define_insn "truncsiqi2" [(set (match_operand:QI 0 "general_operand" "=g") (truncate:QI (match_operand:SI 1 "nonimmediate_operand" "g")))] "" "cvtlb %1,%0")
(define_insn "truncsihi2" [(set (match_operand:HI 0 "general_operand" "=g") (truncate:HI (match_operand:SI 1 "nonimmediate_operand" "g")))] "" "cvtlw %1,%0")
(define_insn "trunchiqi2" [(set (match_operand:QI 0 "general_operand" "=g") (truncate:QI (match_operand:HI 1 "nonimmediate_operand" "g")))] "" "cvtwb %1,%0")
(define_insn "extendhisi2" [(set (match_operand:SI 0 "general_operand" "=g") (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "g")))] "" "cvtwl %1,%0")
(define_insn "extendqihi2" [(set (match_operand:HI 0 "general_operand" "=g") (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "g")))] "" "cvtbw %1,%0")
(define_insn "extendqisi2" [(set (match_operand:SI 0 "general_operand" "=g") (sign_extend:SI (match_operand:QI 1 "nonimmediate_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 "nonimmediate_operand" "g")))] "" "movzwl %1,%0")
(define_insn "zero_extendqihi2" [(set (match_operand:HI 0 "general_operand" "=g") (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "g")))] "" "movzbw %1,%0")
(define_insn "zero_extendqisi2" [(set (match_operand:SI 0 "general_operand" "=g") (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "g")))] "" "movzbl %1,%0") ;; Fix-to-float conversion insns.
(define_insn "floatsisf2" [(set (match_operand:SF 0 "general_operand" "=g") (float:SF (match_operand:SI 1 "nonimmediate_operand" "g")))] "" "cvtlf %1,%0")
(define_insn "floatsidf2" [(set (match_operand:DF 0 "general_operand" "=g") (float:DF (match_operand:SI 1 "nonimmediate_operand" "g")))] "" "cvtl%# %1,%0")
(define_insn "floathisf2" [(set (match_operand:SF 0 "general_operand" "=g") (float:SF (match_operand:HI 1 "nonimmediate_operand" "g")))] "" "cvtwf %1,%0")
(define_insn "floathidf2" [(set (match_operand:DF 0 "general_operand" "=g") (float:DF (match_operand:HI 1 "nonimmediate_operand" "g")))] "" "cvtw%# %1,%0")
(define_insn "floatqisf2" [(set (match_operand:SF 0 "general_operand" "=g") (float:SF (match_operand:QI 1 "nonimmediate_operand" "g")))] "" "cvtbf %1,%0")
(define_insn "floatqidf2" [(set (match_operand:DF 0 "general_operand" "=g") (float:DF (match_operand:QI 1 "nonimmediate_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,g,g") (plus:DF (match_operand:DF 1 "general_operand" "0,gF,gF") (match_operand:DF 2 "general_operand" "gF,0,gF")))] "" "@ add%#2 %2,%0 add%#2 %1,%0 add%#3 %1,%2,%0")
(define_insn "addsf3" [(set (match_operand:SF 0 "general_operand" "=g,g,g") (plus:SF (match_operand:SF 1 "general_operand" "0,gF,gF") (match_operand:SF 2 "general_operand" "gF,0,gF")))] "" "@ addf2 %2,%0 addf2 %1,%0 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 (operands[2] == constm1_rtx) 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 (operands[2] == constm1_rtx) 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 (operands[2] == constm1_rtx) 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"; }")
;; The add-with-carry (adwc) instruction only accepts two operands. (define_insn "adddi3" [(set (match_operand:DI 0 "general_operand" "=ro>,ro>") (plus:DI (match_operand:DI 1 "general_operand" "%0,ro>") (match_operand:DI 2 "general_operand" "Fro,F")))] "" "* { rtx low[3]; char *pattern; int carry = 1;
split_quadword_operands (operands, low, 3); /* Add low parts. / if (rtx_equal_p (operands[0], operands[1])) { if (low[2] == const0_rtx) / Should examine operand, punt if not POST_INC. / pattern = "tstl %0", carry = 0; else if (low[2] == const1_rtx) pattern = "incl %0"; else pattern = "addl2 %2,%0"; } else { if (low[2] == const0_rtx) pattern = "movl %1,%0", carry = 0; else pattern = "addl3 %2,%1,%0"; } if (pattern) output_asm_insn (pattern, low); if (!carry) / If CARRY is 0, we don't have any carry value to worry about. / return OUT_FCN (CODE_FOR_addsi3) (operands, insn); / %0 = C + %1 + %2 */ if (!rtx_equal_p (operands[0], operands[1])) output_asm_insn ((operands[1] == const0_rtx ? "clrl %0" : "movl %1,%0"), operands); return "adwc %2,%0"; }") ;;- All kinds of subtract instructions.
(define_insn "subdf3" [(set (match_operand:DF 0 "general_operand" "=g,g") (minus:DF (match_operand:DF 1 "general_operand" "0,gF") (match_operand:DF 2 "general_operand" "gF,gF")))] "" "@ sub%#2 %2,%0 sub%#3 %2,%1,%0")
(define_insn "subsf3" [(set (match_operand:SF 0 "general_operand" "=g,g") (minus:SF (match_operand:SF 1 "general_operand" "0,gF") (match_operand:SF 2 "general_operand" "gF,gF")))] "" "@ subf2 %2,%0 subf3 %2,%1,%0")
(define_insn "subsi3" [(set (match_operand:SI 0 "general_operand" "=g,g") (minus:SI (match_operand:SI 1 "general_operand" "0,g") (match_operand:SI 2 "general_operand" "g,g")))] "" "@ subl2 %2,%0 subl3 %2,%1,%0")
(define_insn "subhi3" [(set (match_operand:HI 0 "general_operand" "=g,g") (minus:HI (match_operand:HI 1 "general_operand" "0,g") (match_operand:HI 2 "general_operand" "g,g")))] "" "@ subw2 %2,%0 subw3 %2,%1,%0")
(define_insn "subqi3" [(set (match_operand:QI 0 "general_operand" "=g,g") (minus:QI (match_operand:QI 1 "general_operand" "0,g") (match_operand:QI 2 "general_operand" "g,g")))] "" "@ subb2 %2,%0 subb3 %2,%1,%0")
;; The subtract-with-carry (sbwc) instruction only takes two operands. (define_insn "subdi3" [(set (match_operand:DI 0 "general_operand" "=or>,or>") (minus:DI (match_operand:DI 1 "general_operand" "0,or>") (match_operand:DI 2 "general_operand" "For,F")))] "" "* { rtx low[3]; char *pattern; int carry = 1;
split_quadword_operands (operands, low, 3); /* Subtract low parts. / if (rtx_equal_p (operands[0], operands[1])) { if (low[2] == const0_rtx) pattern = 0, carry = 0; else if (low[2] == constm1_rtx) pattern = "decl %0"; else pattern = "subl2 %2,%0"; } else { if (low[2] == constm1_rtx) pattern = "decl %0"; else if (low[2] == const0_rtx) pattern = OUT_FCN (CODE_FOR_movsi) (low, insn), carry = 0; else pattern = "subl3 %2,%1,%0"; } if (pattern) output_asm_insn (pattern, low); if (carry) { if (!rtx_equal_p (operands[0], operands[1])) return "movl %1,%0;sbwc %2,%0"; return "sbwc %2,%0"; / %0 = %2 - %1 - C */ } return OUT_FCN (CODE_FOR_subsi3) (operands, insn); }") ;;- Multiply instructions.
(define_insn "muldf3" [(set (match_operand:DF 0 "general_operand" "=g,g,g") (mult:DF (match_operand:DF 1 "general_operand" "0,gF,gF") (match_operand:DF 2 "general_operand" "gF,0,gF")))] "" "@ mul%#2 %2,%0 mul%#2 %1,%0 mul%#3 %1,%2,%0")
(define_insn "mulsf3" [(set (match_operand:SF 0 "general_operand" "=g,g,g") (mult:SF (match_operand:SF 1 "general_operand" "0,gF,gF") (match_operand:SF 2 "general_operand" "gF,0,gF")))] "" "@ mulf2 %2,%0 mulf2 %1,%0 mulf3 %1,%2,%0")
(define_insn "mulsi3" [(set (match_operand:SI 0 "general_operand" "=g,g,g") (mult:SI (match_operand:SI 1 "general_operand" "0,g,g") (match_operand:SI 2 "general_operand" "g,0,g")))] "" "@ mull2 %2,%0 mull2 %1,%0 mull3 %1,%2,%0")
(define_insn "mulhi3" [(set (match_operand:HI 0 "general_operand" "=g,g,") (mult:HI (match_operand:HI 1 "general_operand" "0,g,g") (match_operand:HI 2 "general_operand" "g,0,g")))] "" "@ mulw2 %2,%0 mulw2 %1,%0 mulw3 %1,%2,%0")
(define_insn "mulqi3" [(set (match_operand:QI 0 "general_operand" "=g,g,g") (mult:QI (match_operand:QI 1 "general_operand" "0,g,g") (match_operand:QI 2 "general_operand" "g,0,g")))] "" "@ mulb2 %2,%0 mulb2 %1,%0 mulb3 %1,%2,%0")
(define_insn "mulsidi3" [(set (match_operand:DI 0 "general_operand" "=g") (mult:DI (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "g")) (sign_extend:DI (match_operand:SI 2 "nonimmediate_operand" "g"))))] "" "emul %1,%2,$0,%0")
(define_insn "" [(set (match_operand:DI 0 "general_operand" "=g") (plus:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "g")) (sign_extend:DI (match_operand:SI 2 "nonimmediate_operand" "g"))) (sign_extend:DI (match_operand:SI 3 "nonimmediate_operand" "g"))))] "" "emul %1,%2,%3,%0")
;; 'F' constraint means type CONST_DOUBLE (define_insn "" [(set (match_operand:DI 0 "general_operand" "=g") (plus:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "g")) (sign_extend:DI (match_operand:SI 2 "nonimmediate_operand" "g"))) (match_operand:DI 3 "immediate_operand" "F")))] "GET_CODE (operands[3]) == CONST_DOUBLE && CONST_DOUBLE_HIGH (operands[3]) == (CONST_DOUBLE_LOW (operands[3]) >> 31)" "* { if (CONST_DOUBLE_HIGH (operands[3])) operands[3] = gen_rtx (CONST_INT, VOIDmode, CONST_DOUBLE_LOW (operands[3])); return "emul %1,%2,%3,%0"; }") ;;- Divide instructions.
(define_insn "divdf3" [(set (match_operand:DF 0 "general_operand" "=g,g") (div:DF (match_operand:DF 1 "general_operand" "0,gF") (match_operand:DF 2 "general_operand" "gF,gF")))] "" "@ div%#2 %2,%0 div%#3 %2,%1,%0")
(define_insn "divsf3" [(set (match_operand:SF 0 "general_operand" "=g,g") (div:SF (match_operand:SF 1 "general_operand" "0,gF") (match_operand:SF 2 "general_operand" "gF,gF")))] "" "@ divf2 %2,%0 divf3 %2,%1,%0")
(define_insn "divsi3" [(set (match_operand:SI 0 "general_operand" "=g,g") (div:SI (match_operand:SI 1 "general_operand" "0,g") (match_operand:SI 2 "general_operand" "g,g")))] "" "@ divl2 %2,%0 divl3 %2,%1,%0")
(define_insn "divhi3" [(set (match_operand:HI 0 "general_operand" "=g,g") (div:HI (match_operand:HI 1 "general_operand" "0,g") (match_operand:HI 2 "general_operand" "g,g")))] "" "@ divw2 %2,%0 divw3 %2,%1,%0")
(define_insn "divqi3" [(set (match_operand:QI 0 "general_operand" "=g,g") (div:QI (match_operand:QI 1 "general_operand" "0,g") (match_operand:QI 2 "general_operand" "g,g")))] "" "@ divb2 %2,%0 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 (not:SI (match_operand:SI 1 "general_operand" "g")) (match_operand:SI 2 "general_operand" "g")))] "" " { if (GET_CODE (operands[1]) == CONST_INT) operands[1] = gen_rtx (CONST_INT, VOIDmode, ~INTVAL (operands[1])); else operands[1] = expand_unop (SImode, one_cmpl_optab, operands[1], 0, 1); }")
(define_expand "andhi3" [(set (match_operand:HI 0 "general_operand" "=g") (and:HI (not:HI (match_operand:HI 1 "general_operand" "g")) (match_operand:HI 2 "general_operand" "g")))] "" " { rtx op = operands[1]; if (GET_CODE (op) == CONST_INT) operands[1] = gen_rtx (CONST_INT, VOIDmode, ((1 << 16) - 1) & ~INTVAL (op)); else operands[1] = expand_unop (HImode, one_cmpl_optab, op, 0, 1); }")
(define_expand "andqi3" [(set (match_operand:QI 0 "general_operand" "=g") (and:QI (not:QI (match_operand:QI 1 "general_operand" "g")) (match_operand:QI 2 "general_operand" "g")))] "" " { rtx op = operands[1]; if (GET_CODE (op) == CONST_INT) operands[1] = gen_rtx (CONST_INT, VOIDmode, ((1 << 8) - 1) & ~INTVAL (op)); else operands[1] = expand_unop (QImode, one_cmpl_optab, op, 0, 1); }")
(define_insn "" [(set (match_operand:SI 0 "general_operand" "=g,g") (and:SI (not:SI (match_operand:SI 1 "general_operand" "g,g")) (match_operand:SI 2 "general_operand" "0,g")))] "" "@ bicl2 %1,%0 bicl3 %1,%2,%0")
(define_insn "" [(set (match_operand:HI 0 "general_operand" "=g,g") (and:HI (not:HI (match_operand:HI 1 "general_operand" "g,g")) (match_operand:HI 2 "general_operand" "0,g")))] "" "@ bicw2 %1,%0 bicw3 %1,%2,%0")
(define_insn "" [(set (match_operand:QI 0 "general_operand" "=g,g") (and:QI (not:QI (match_operand:QI 1 "general_operand" "g,g")) (match_operand:QI 2 "general_operand" "0,g")))] "" "@ bicb2 %1,%0 bicb3 %1,%2,%0")
;; The following used to be needed because constant propagation can ;; create them starting from the bic insn patterns above. This is no ;; longer a problem. However, having these patterns allows optimization ;; opportunities in combine.c.
(define_insn "" [(set (match_operand:SI 0 "general_operand" "=g,g") (and:SI (match_operand:SI 1 "general_operand" "0,g") (match_operand:SI 2 "const_int_operand" "n,n")))] "" "@ bicl2 %N2,%0 bicl3 %N2,%1,%0")
(define_insn "" [(set (match_operand:HI 0 "general_operand" "=g,g") (and:HI (match_operand:HI 1 "general_operand" "0,g") (match_operand:HI 2 "const_int_operand" "n,n")))] "" "@ bicw2 %H2,%0 bicw3 %H2,%1,%0")
(define_insn "" [(set (match_operand:QI 0 "general_operand" "=g,g") (and:QI (match_operand:QI 1 "general_operand" "0,g") (match_operand:QI 2 "const_int_operand" "n,n")))] "" "@ bicb2 %B2,%0 bicb3 %B2,%1,%0") ;;- Bit set instructions.
(define_insn "iorsi3" [(set (match_operand:SI 0 "general_operand" "=g,g,g") (ior:SI (match_operand:SI 1 "general_operand" "0,g,g") (match_operand:SI 2 "general_operand" "g,0,g")))] "" "@ bisl2 %2,%0 bisl2 %1,%0 bisl3 %2,%1,%0")
(define_insn "iorhi3" [(set (match_operand:HI 0 "general_operand" "=g,g,g") (ior:HI (match_operand:HI 1 "general_operand" "0,g,g") (match_operand:HI 2 "general_operand" "g,0,g")))] "" "@ bisw2 %2,%0 bisw2 %1,%0 bisw3 %2,%1,%0")
(define_insn "iorqi3" [(set (match_operand:QI 0 "general_operand" "=g,g,g") (ior:QI (match_operand:QI 1 "general_operand" "0,g,g") (match_operand:QI 2 "general_operand" "g,0,g")))] "" "@ bisb2 %2,%0 bisb2 %1,%0 bisb3 %2,%1,%0")
;;- xor instructions.
(define_insn "xorsi3" [(set (match_operand:SI 0 "general_operand" "=g,g,g") (xor:SI (match_operand:SI 1 "general_operand" "0,g,g") (match_operand:SI 2 "general_operand" "g,0,g")))] "" "@ xorl2 %2,%0 xorl2 %1,%0 xorl3 %2,%1,%0")
(define_insn "xorhi3" [(set (match_operand:HI 0 "general_operand" "=g,g,g") (xor:HI (match_operand:HI 1 "general_operand" "0,g,g") (match_operand:HI 2 "general_operand" "g,0,g")))] "" "@ xorw2 %2,%0 xorw2 %1,%0 xorw3 %2,%1,%0")
(define_insn "xorqi3" [(set (match_operand:QI 0 "general_operand" "=g,g,g") (xor:QI (match_operand:QI 1 "general_operand" "0,g,g") (match_operand:QI 2 "general_operand" "g,0,g")))] "" "@ xorb2 %2,%0 xorb2 %1,%0 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, ;; then emitting a right shift with the shift count negated. This means ;; that all actual shift counts in the RTL will be positive. This ;; prevents converting shifts to ZERO_EXTRACTs with negative positions, ;; which isn't valid. (define_expand "ashrsi3" [(set (match_operand:SI 0 "general_operand" "=g") (ashiftrt:SI (match_operand:SI 1 "general_operand" "g") (match_operand:QI 2 "general_operand" "g")))] "" " { if (GET_CODE (operands[2]) != CONST_INT) operands[2] = gen_rtx (NEG, QImode, negate_rtx (QImode, operands[2])); }")
(define_insn "" [(set (match_operand:SI 0 "general_operand" "=g") (ashiftrt:SI (match_operand:SI 1 "general_operand" "g") (match_operand:QI 2 "const_int_operand" "n")))] "" "ashl $%n2,%1,%0")
(define_insn "" [(set (match_operand:SI 0 "general_operand" "=g") (ashiftrt:SI (match_operand:SI 1 "general_operand" "g") (neg:QI (match_operand:QI 2 "general_operand" "g"))))] "" "ashl %2,%1,%0")
(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") (ashiftrt:DI (match_operand:DI 1 "general_operand" "g") (match_operand:QI 2 "general_operand" "g")))] "" " { operands[2] = gen_rtx (NEG, QImode, 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")
(define_insn "" [(set (match_operand:DI 0 "general_operand" "=g") (ashiftrt:DI (match_operand:DI 1 "general_operand" "g") (neg:QI (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") (rotatert:SI (match_operand:SI 1 "general_operand" "g") (match_operand:QI 2 "general_operand" "g")))] "" " { if (GET_CODE (operands[2]) != CONST_INT) operands[2] = gen_rtx (NEG, QImode, 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")
(define_insn "" [(set (match_operand:SI 0 "general_operand" "=g") (rotatert:SI (match_operand:SI 1 "general_operand" "g") (match_operand:QI 2 "const_int_operand" "n")))] "" "rotl $%R2,%1,%0")
(define_insn "" [(set (match_operand:SI 0 "general_operand" "=g") (rotatert:SI (match_operand:SI 1 "general_operand" "g") (neg:QI (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:QI 1 "const_int_operand" "n") (match_operand:SI 2 "const_int_operand" "n")) (match_operand:SI 3 "general_operand" "g"))] "(INTVAL (operands[1]) == 8 || INTVAL (operands[1]) == 16) && 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:QI 2 "const_int_operand" "n") (match_operand:SI 3 "const_int_operand" "n")))] "(INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 16) && 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:QI 2 "const_int_operand" "n") (match_operand:SI 3 "const_int_operand" "n")))] "(INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 16) && 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 "nonmemory_operand" "r") (match_operand:QI 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 "nonmemory_operand" "r") (match_operand:QI 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 "nonmemory_operand" "r") (match_operand:QI 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 "nonmemory_operand" "r") (match_operand:QI 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:QI 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:QI 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:QI 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:QI 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:QI 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:QI 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")
;; Recognize reversed jumps. (define_insn "" [(set (pc) (if_then_else (match_operator 0 "comparison_operator" [(cc0) (const_int 0)]) (pc) (label_ref (match_operand 1 "" ""))))] "" "j%C0 %l1") ; %C0 negates condition ;; Recognize jbs, jlbs, jbc and jlbc instructions. Note that the operand ;; of jlbs and jlbc insns are SImode in the hardware. However, if it is ;; memory, we use QImode in the insn. So we can't use those instructions ;; for mode-dependent addresses.
(define_insn "" [(set (pc) (if_then_else (ne (zero_extract:SI (match_operand:QI 0 "nonimmediate_operand" "rQ,g") (const_int 1) (match_operand:SI 1 "general_operand" "I,g")) (const_int 0)) (label_ref (match_operand 2 "" "")) (pc)))] "" "@ jlbs %0,%l2 jbs %1,%0,%l2")
(define_insn "" [(set (pc) (if_then_else (eq (zero_extract:SI (match_operand:QI 0 "nonimmediate_operand" "rQ,g") (const_int 1) (match_operand:SI 1 "general_operand" "I,g")) (const_int 0)) (label_ref (match_operand 2 "" "")) (pc)))] "" "@ jlbc %0,%l2 jbc %1,%0,%l2")
(define_insn "" [(set (pc) (if_then_else (ne (zero_extract:SI (match_operand:SI 0 "register_operand" "r,r") (const_int 1) (match_operand:SI 1 "general_operand" "I,g")) (const_int 0)) (label_ref (match_operand 2 "" "")) (pc)))] "" "@ jlbs %0,%l2 jbs %1,%0,%l2")
(define_insn "" [(set (pc) (if_then_else (eq (zero_extract:SI (match_operand:SI 0 "register_operand" "r,r") (const_int 1) (match_operand:SI 1 "general_operand" "I,g")) (const_int 0)) (label_ref (match_operand 2 "" "")) (pc)))] "" "@ jlbc %0,%l2 jbc %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")
;; Normal aob insns. Define a version for when operands[1] is a constant. (define_insn "" [(set (pc) (if_then_else (lt (plus:SI (match_operand:SI 0 "general_operand" "+g") (const_int 1)) (match_operand:SI 1 "general_operand" "g")) (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 (lt (match_operand:SI 0 "general_operand" "+g") (match_operand:SI 1 "general_operand" "g")) (label_ref (match_operand 2 "" "")) (pc))) (set (match_dup 0) (plus:SI (match_dup 0) (const_int 1)))] "!TARGET_UNIX_ASM && GET_CODE (operands[1]) == CONST_INT" "jaoblss %P1,%0,%l2")
(define_insn "" [(set (pc) (if_then_else (le (plus:SI (match_operand:SI 0 "general_operand" "+g") (const_int 1)) (match_operand:SI 1 "general_operand" "g")) (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")
(define_insn "" [(set (pc) (if_then_else (le (match_operand:SI 0 "general_operand" "+g") (match_operand:SI 1 "general_operand" "g")) (label_ref (match_operand 2 "" "")) (pc))) (set (match_dup 0) (plus:SI (match_dup 0) (const_int 1)))] "!TARGET_UNIX_ASM && GET_CODE (operands[1]) == CONST_INT" "jaobleq %P1,%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 (match_operand:SI 0 "general_operand" "g") (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_pop" [(call (match_operand:QI 0 "memory_operand" "m") (match_operand:QI 1 "general_operand" "g")) (set (reg:SI 14) (plus:SI (reg:SI 14) (match_operand:SI 3 "immediate_operand" "i")))] "" "* if (GET_CODE (operands[1]) != CONST_INT || 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_pop" [(set (match_operand 0 "" "=g") (call (match_operand:QI 1 "memory_operand" "m") (match_operand:QI 2 "general_operand" "g"))) (set (reg:SI 14) (plus:SI (reg:SI 14) (match_operand:SI 4 "immediate_operand" "i")))] "" "* if (GET_CODE (operands[2]) != CONST_INT || 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 another set of these for the case of functions with no ;; operands. In that case, combine may simplify the adjustment of sp. (define_insn "" [(call (match_operand:QI 0 "memory_operand" "m") (match_operand:QI 1 "general_operand" "g")) (set (reg:SI 14) (reg:SI 14))] "" "* if (GET_CODE (operands[1]) != CONST_INT || 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 "" [(set (match_operand 0 "" "=g") (call (match_operand:QI 1 "memory_operand" "m") (match_operand:QI 2 "general_operand" "g"))) (set (reg:SI 14) (reg:SI 14))] "" "* if (GET_CODE (operands[2]) != CONST_INT || 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 "indirect_jump" [(set (pc) (match_operand:SI 0 "general_operand" "r"))] "(GET_CODE (operands[0]) != MEM || offsettable_memref_p (operands[0]))" "jmp (%0)")
(define_insn "casesi" [(set (pc) (if_then_else (leu (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) (mult:SI (minus:SI (match_dup 0) (match_dup 1)) (const_int 2))))) (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 (leu (match_operand:SI 0 "general_operand" "g") (match_operand:SI 1 "general_operand" "g")) (plus:SI (sign_extend:SI (mem:HI (plus:SI (pc) (mult:SI (minus:SI (match_dup 0) (const_int 0)) (const_int 2))))) (label_ref:SI (match_operand 3 "" ""))) (pc)))] "" "casel %0,$0,%1") ;;- 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,p"))] "" "@ pushab %a1 movab %a1,%0")
(define_insn "" [(set (match_operand:SI 0 "general_operand" "=<,g") (match_operand:HI 1 "address_operand" "p,p"))] "" "@ pushaw %a1 movaw %a1,%0")
(define_insn "" [(set (match_operand:SI 0 "general_operand" "=<,g") (match_operand:SI 1 "address_operand" "p,p"))] "" "@ pushal %a1 moval %a1,%0")
(define_insn "" [(set (match_operand:SI 0 "general_operand" "=<,g") (match_operand:DI 1 "address_operand" "p,p"))] "" "@ pushaq %a1 movaq %a1,%0")
(define_insn "" [(set (match_operand:SI 0 "general_operand" "=<,g") (match_operand:SF 1 "address_operand" "p,p"))] "" "@ pushaf %a1 movaf %a1,%0")
(define_insn "" [(set (match_operand:SI 0 "general_operand" "=<,g") (match_operand:DF 1 "address_operand" "p,p"))] "" "@ pushad %a1 movad %a1,%0") ;; These used to be peepholes, but it is more straightforward to do them ;; as single insns. However, we must force the output to be a register ;; if it is not an offsettable address so that we know that we can assign ;; to it twice.
;; If we had a good way of evaluating the relative costs, these could be ;; machine-independent.
;; Optimize extzv ...,z; andl2 ...,z ;; or ashl ...,z; andl2 ...,z ;; with other operands constant. This is what the combiner converts the ;; above sequences to before attempting to recognize the new insn.
(define_insn "" [(set (match_operand:SI 0 "general_operand" "=ro") (and:SI (ashiftrt:SI (match_operand:SI 1 "general_operand" "g") (match_operand:QI 2 "const_int_operand" "n")) (match_operand:SI 3 "const_int_operand" "n")))] "(INTVAL (operands[3]) & ~((1 << (32 - INTVAL (operands[2]))) - 1)) == 0" "* { unsigned long mask1 = INTVAL (operands[3]); unsigned long mask2 = (1 << (32 - INTVAL (operands[2]))) - 1;
if ((mask1 & mask2) != mask1) operands[3] = gen_rtx (CONST_INT, VOIDmode, mask1 & mask2);
return "rotl %R2,%1,%0;bicl2 %N3,%0"; }")
;; left-shift and mask ;; The only case where `ashl' is better is if the mask only turns off ;; bits that the ashl would anyways, in which case it should have been ;; optimized away.
(define_insn "" [(set (match_operand:SI 0 "general_operand" "=ro") (and:SI (ashift:SI (match_operand:SI 1 "general_operand" "g") (match_operand:QI 2 "const_int_operand" "n")) (match_operand:SI 3 "const_int_operand" "n")))] "" "* { operands[3] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[3]) & ~((1 << INTVAL (operands[2])) - 1)); return "rotl %2,%1,%0;bicl2 %N3,%0"; }") ;;- 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: