;; Machine description for GNU compiler, VAX Version
;; Copyright (C) 1987-2022 Free Software Foundation, Inc.
;; This file is part of GCC.
;; GCC 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 3, or (at your option)
;; any later version.
;; GCC 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 GCC; see the file COPYING3. If not see
;; .
;;- 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.
;; UNSPEC_VOLATILE usage:
(define_c_enum "unspecv" [
VUNSPEC_BLOCKAGE ; 'blockage' insn to prevent scheduling across an
; insn in the code.
VUNSPEC_SYNC_ISTREAM ; sequence of insns to sync the I-stream
VUNSPEC_PEM ; 'procedure_entry_mask' insn.
])
;; UNSPEC usage:
(define_c_enum "unspec" [
UNSPEC_SETMEM_FILL ; 'fill' operand to 'setmem' insn.
])
(define_constants
[(VAX_AP_REGNUM 12) ; Register 12 contains the argument pointer
(VAX_FP_REGNUM 13) ; Register 13 contains the frame pointer
(VAX_SP_REGNUM 14) ; Register 14 contains the stack pointer
(VAX_PC_REGNUM 15) ; Register 15 contains the program counter
(VAX_PSL_REGNUM 16) ; Register 16 contains the processor status
; and condition codes in particular
]
)
;; Integer modes supported on VAX, with a mapping from machine mode
;; to mnemonic suffix. DImode is always a special case.
(define_mode_iterator VAXint [QI HI SI])
(define_mode_iterator VAXintQH [QI HI])
(define_mode_iterator VAXintQHSD [QI HI SI DI])
(define_mode_attr isfx [(QI "b") (HI "w") (SI "l") (DI "q")])
;; Similar for float modes supported on VAX.
(define_mode_iterator VAXfp [SF DF])
(define_mode_attr fsfx [(SF "f") (DF "%#")])
;; Some output patterns want integer immediates with a prefix...
(define_mode_attr iprefx [(QI "B") (HI "H") (SI "N")])
(define_mode_iterator VAXcc [CC CCN CCNZ CCZ])
(define_mode_iterator VAXccnz [CCN CCNZ CCZ])
(define_code_iterator any_extract [sign_extract zero_extract])
;;
(include "constraints.md")
(include "predicates.md")
;; Make instructions that set the N, N+Z, and Z condition codes respectively.
(define_subst "subst_"
[(set (match_operand 0 "")
(match_operand 1 ""))
(clobber (reg:CC VAX_PSL_REGNUM))]
""
[(set (reg:VAXccnz VAX_PSL_REGNUM)
(compare:VAXccnz (match_dup 1)
(const_int 0)))
(set (match_dup 0)
(match_dup 1))])
(define_subst "subst_f"
[(set (match_operand:VAXfp 0 "")
(match_operand:VAXfp 1 ""))
(clobber (reg:CC VAX_PSL_REGNUM))]
""
[(set (reg:VAXccnz VAX_PSL_REGNUM)
(compare:VAXccnz (match_dup 1)
(const_double_zero:VAXfp)))
(set (match_dup 0)
(match_dup 1))])
;; Select all from the attributes below that apply to a given insn that
;; has a clobber on CC for the comparison elimination pass to use it in
;; place of a subsequent comparison instruction matching the mode used
;; by a comparison operator in branch.
;;
;; For example a branch doing `eq' in SImode will use `*cmpsi_ccz', so
;; to eliminate it a `*movsi_ccz', etc. pattern will be required via the
;; `ccz' substitution. Analogously for the other CC modes.
;;
;; The general `cc' mode, which sets all of the C, N, V and Z condition
;; codes, has to be handled specially as it makes no sense for the usual
;; comparison against zero, so no substitution has been defined for it.
(define_subst_attr "ccn" "subst_ccn" "" "_ccn")
(define_subst_attr "ccnz" "subst_ccnz" "" "_ccnz")
(define_subst_attr "ccz" "subst_ccz" "" "_ccz")
(define_subst_attr "fccn" "subst_fccn" "" "_ccn")
(define_subst_attr "fccnz" "subst_fccnz" "" "_ccnz")
(define_subst_attr "fccz" "subst_fccz" "" "_ccz")
(define_insn "*cmp_"
[(set (reg:VAXcc VAX_PSL_REGNUM)
(compare:VAXcc (match_operand:VAXint 0 "general_operand" "nrmT,nrmT")
(match_operand:VAXint 1 "general_operand" "I,nrmT")))]
"reload_completed"
"@
tst %0
cmp %0,%1")
;; We don't have a CMPQ instruction, but we can set the N and Z condition
;; codes with MOVQ, and also this comparison can be folded into a preceding
;; operation by the post-reload comparison elimination pass.
(define_insn "*cmpdi_"
[(set (reg:VAXccnz VAX_PSL_REGNUM)
(compare:VAXccnz (match_operand:DI 0 "general_operand" "r,nmT")
(match_operand:DI 1 "const_zero_operand" "I,I")))
(clobber (match_scratch:DI 2 "=X,r"))]
"reload_completed"
"@
movq %0,%0
movq %0,%2")
(define_insn "*cmp_"
[(set (reg:VAXccnz VAX_PSL_REGNUM)
(compare:VAXccnz (match_operand:VAXfp 0 "general_operand" "gF,gF")
(match_operand:VAXfp 1 "general_operand" "G,gF")))]
"reload_completed"
"@
tst %0
cmp %0,%1")
(define_insn "*bit_"
[(set (reg:VAXccnz VAX_PSL_REGNUM)
(compare:VAXccnz
(and:VAXint (match_operand:VAXint 0 "general_operand" "nrmT")
(match_operand:VAXint 1 "general_operand" "nrmT"))
(const_int 0)))]
"reload_completed"
"bit %0,%1")
;; The VAX has no sCOND insns. It does have add/subtract with carry
;; which could be used to implement the sltu and sgeu patterns. However,
;; to do this properly requires a complete rewrite of the compare insns
;; to keep them together with the sltu/sgeu insns until after the
;; reload pass is complete. The previous implementation didn't do this
;; and has been deleted.
(define_insn_and_split "mov"
[(set (match_operand:VAXfp 0 "nonimmediate_operand" "=g,g")
(match_operand:VAXfp 1 "general_operand" "G,gF"))]
""
"#"
"reload_completed"
[(parallel
[(set (match_dup 0)
(match_dup 1))
(clobber (reg:CC VAX_PSL_REGNUM))])]
"")
(define_insn "*mov"
[(set (match_operand:VAXfp 0 "nonimmediate_operand" "=g,g")
(match_operand:VAXfp 1 "general_operand" "G,gF"))
(clobber (reg:CC VAX_PSL_REGNUM))]
"reload_completed"
"@
clr %0
mov %1,%0")
;; Some VAXen don't support this instruction.
;;(define_insn_and_split "movti"
;; [(set (match_operand:TI 0 "nonimmediate_operand" "=g")
;; (match_operand:TI 1 "general_operand" "g"))]
;; ""
;; "#"
;; "reload_completed"
;; [(parallel
;; [(set (match_dup 0)
;; (match_dup 1))
;; (clobber (reg:CC VAX_PSL_REGNUM))])]
;; "")
;;
;;(define_insn "*movti"
;; [(set (match_operand:TI 0 "nonimmediate_operand" "=g")
;; (match_operand:TI 1 "general_operand" "g"))
;; (clobber (reg:CC VAX_PSL_REGNUM))]
;; "reload_completed"
;; "movo %1,%0")
(define_insn_and_split "movdi"
[(set (match_operand:DI 0 "nonimmediate_operand" "=g")
(match_operand:DI 1 "general_operand" "g"))]
""
"#"
"reload_completed"
[(parallel
[(set (match_dup 0)
(match_dup 1))
(clobber (reg:CC VAX_PSL_REGNUM))])]
"")
;; In some cases `vax_output_int_move' splits a `DImode' move into a pair
;; of `SImode' moves, in which case the flags aren't usefully set. Have
;; separate patterns then, for the cases where the move may and may not be
;; split each. We use the outer condition only so in some cases we will
;; fail to notice the move does not actually get split, but this is OK.
(define_insn "*movdi_maybe_split"
[(set (match_operand:DI 0 "nonimmediate_operand" "=g")
(match_operand:DI 1 "general_operand" "g"))
(clobber (reg:CC VAX_PSL_REGNUM))]
"reload_completed && vax_maybe_split_dimode_move (operands)"
"* return vax_output_int_move (insn, operands, DImode);")
(define_insn "*movdi_unsplit"
[(set (match_operand:DI 0 "nonimmediate_operand" "=g")
(match_operand:DI 1 "general_operand" "g"))
(clobber (reg:CC VAX_PSL_REGNUM))]
"reload_completed && !vax_maybe_split_dimode_move (operands)"
"* return vax_output_int_move (insn, operands, DImode);")
;; The VAX move instructions have space-time tradeoffs. On a MicroVAX
;; register-register mov instructions take 3 bytes and 2 CPU cycles. clrl
;; takes 2 bytes and 3 cycles. mov from constant to register takes 2 cycles
;; if the constant is smaller than 4 bytes, 3 cycles for a longword
;; constant. movz, mneg, and mcom are as fast as mov, so movzwl is faster
;; than movl for positive constants that fit in 16 bits but not 6 bits. cvt
;; instructions take 4 cycles. inc takes 3 cycles. The machine description
;; is willing to trade 1 byte for 1 cycle (clrl instead of movl $0; cvtwl
;; instead of movl).
;; Cycle counts for other models may vary (on a VAX 750 they are similar,
;; but on a VAX 9000 most move and add instructions with one constant
;; operand take 1 cycle).
;; Loads of constants between 64 and 128 used to be done with
;; "addl3 $63,#,dst" but this is slower than movzbl and takes as much space.
(define_expand "movsi"
[(set (match_operand:SI 0 "nonimmediate_operand" "")
(match_operand:SI 1 "general_operand" ""))]
""
"
{
#ifdef NO_EXTERNAL_INDIRECT_ADDRESS
if (flag_pic
&& GET_CODE (operands[1]) == CONST
&& GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == SYMBOL_REF
&& !SYMBOL_REF_LOCAL_P (XEXP (XEXP (operands[1], 0), 0)))
{
rtx symbol_ref = XEXP (XEXP (operands[1], 0), 0);
rtx const_int = XEXP (XEXP (operands[1], 0), 1);
rtx temp = reload_in_progress ? operands[0] : gen_reg_rtx (Pmode);
emit_move_insn (temp, symbol_ref);
emit_move_insn (operands[0], gen_rtx_PLUS (SImode, temp, const_int));
DONE;
}
#endif
}")
(define_insn_and_split "movsi_2"
[(set (match_operand:SI 0 "nonimmediate_operand" "=g")
(match_operand:SI 1 "nonsymbolic_operand" "nrmT"))]
""
"#"
"reload_completed"
[(parallel
[(set (match_dup 0)
(match_dup 1))
(clobber (reg:CC VAX_PSL_REGNUM))])]
"")
(define_insn "*movsi_2"
[(set (match_operand:SI 0 "nonimmediate_operand" "=g")
(match_operand:SI 1 "nonsymbolic_operand" "nrmT"))
(clobber (reg:CC VAX_PSL_REGNUM))]
"reload_completed"
"* return vax_output_int_move (insn, operands, SImode);")
(define_insn_and_split "mov"
[(set (match_operand:VAXintQH 0 "nonimmediate_operand" "=g")
(match_operand:VAXintQH 1 "general_operand" "g"))]
""
"#"
"reload_completed"
[(parallel
[(set (match_dup 0)
(match_dup 1))
(clobber (reg:CC VAX_PSL_REGNUM))])]
"")
(define_insn "*mov"
[(set (match_operand:VAXintQH 0 "nonimmediate_operand" "=g")
(match_operand:VAXintQH 1 "general_operand" "g"))
(clobber (reg:CC VAX_PSL_REGNUM))]
"reload_completed"
"* return vax_output_int_move (insn, operands, mode);")
(define_insn_and_split "movstricthi"
[(set (strict_low_part (match_operand:HI 0 "register_operand" "+r"))
(match_operand:HI 1 "general_operand" "g"))]
""
"#"
"reload_completed"
[(parallel
[(set (strict_low_part (match_dup 0))
(match_dup 1))
(clobber (reg:CC VAX_PSL_REGNUM))])]
"")
(define_insn "*movstricthi"
[(set (strict_low_part (match_operand:HI 0 "register_operand" "+r"))
(match_operand:HI 1 "general_operand" "g"))
(clobber (reg:CC VAX_PSL_REGNUM))]
"reload_completed"
"*
{
if (CONST_INT_P (operands[1]))
{
int i = INTVAL (operands[1]);
if (i == 0)
return \"clrw %0\";
else if ((unsigned int)i < 64)
return \"movw %1,%0\";
else if ((unsigned int)~i < 64)
return \"mcomw %H1,%0\";
else if ((unsigned int)i < 256)
return \"movzbw %1,%0\";
}
return \"movw %1,%0\";
}")
(define_insn_and_split "movstrictqi"
[(set (strict_low_part (match_operand:QI 0 "register_operand" "+r"))
(match_operand:QI 1 "general_operand" "g"))]
""
"#"
"reload_completed"
[(parallel
[(set (strict_low_part (match_dup 0))
(match_dup 1))
(clobber (reg:CC VAX_PSL_REGNUM))])]
"")
(define_insn "*movstrictqi"
[(set (strict_low_part (match_operand:QI 0 "register_operand" "+r"))
(match_operand:QI 1 "general_operand" "g"))
(clobber (reg:CC VAX_PSL_REGNUM))]
"reload_completed"
"*
{
if (CONST_INT_P (operands[1]))
{
int i = INTVAL (operands[1]);
if (i == 0)
return \"clrb %0\";
else if ((unsigned int)~i < 64)
return \"mcomb %B1,%0\";
}
return \"movb %1,%0\";
}")
;; This is here to accept 4 arguments and pass the first 3 along
;; to the movmemhi1 pattern that really does the work.
(define_expand "cpymemhi"
[(set (match_operand:BLK 0 "memory_operand" "")
(match_operand:BLK 1 "memory_operand" ""))
(use (match_operand:HI 2 "general_operand" ""))
(match_operand 3 "" "")]
""
"
{
emit_insn (gen_movmemhi1 (operands[0], operands[1], operands[2]));
DONE;
}")
(define_expand "movmemhi"
[(set (match_operand:BLK 0 "memory_operand" "")
(match_operand:BLK 1 "memory_operand" ""))
(use (match_operand:HI 2 "general_operand" ""))
(match_operand 3 "" "")]
""
"
{
emit_insn (gen_movmemhi1 (operands[0], operands[1], operands[2]));
DONE;
}")
;; 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_and_split "movmemhi1"
[(set (match_operand:BLK 0 "memory_operand" "=o")
(match_operand:BLK 1 "memory_operand" "o"))
(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))]
""
"#"
"reload_completed"
[(parallel
[(set (match_dup 0)
(match_dup 1))
(use (match_dup 2))
(clobber (reg:SI 0))
(clobber (reg:SI 1))
(clobber (reg:SI 2))
(clobber (reg:SI 3))
(clobber (reg:SI 4))
(clobber (reg:SI 5))
(clobber (reg:CC VAX_PSL_REGNUM))])]
"")
(define_insn "*movmemhi1"
[(set (match_operand:BLK 0 "memory_operand" "=o")
(match_operand:BLK 1 "memory_operand" "o"))
(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))
(clobber (reg:CC VAX_PSL_REGNUM))]
"reload_completed"
"movc3 %2,%1,%0")
;; This is here to accept 4 arguments and pass the first 3 along
;; to the setmemhi1 pattern that really does the work.
(define_expand "setmemhi"
[(set (match_operand:BLK 0 "memory_operand" "")
(match_operand:QI 2 "general_operand" ""))
(use (match_operand:HI 1 "general_operand" ""))
(match_operand 3 "" "")]
""
"
{
emit_insn (gen_setmemhi1 (operands[0], operands[1], operands[2]));
DONE;
}")
;; The srcaddr operand of MOVC5 is not dereferenced if srclen is zero, so we
;; set it to (%ap) somewhat arbitrarily chosen for the shortest encoding.
(define_insn_and_split "setmemhi1"
[(set (match_operand:BLK 0 "memory_operand" "=o")
(unspec:BLK [(use (match_operand:QI 2 "general_operand" "g"))]
UNSPEC_SETMEM_FILL))
(use (match_operand:HI 1 "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))]
""
"#"
"reload_completed"
[(parallel
[(set (match_dup 0)
(unspec:BLK [(use (match_dup 2))] UNSPEC_SETMEM_FILL))
(use (match_dup 1))
(clobber (reg:SI 0))
(clobber (reg:SI 1))
(clobber (reg:SI 2))
(clobber (reg:SI 3))
(clobber (reg:SI 4))
(clobber (reg:SI 5))
(clobber (reg:CC VAX_PSL_REGNUM))])]
"")
(define_insn "*setmemhi1"
[(set (match_operand:BLK 0 "memory_operand" "=o")
(unspec:BLK [(use (match_operand:QI 2 "general_operand" "g"))]
UNSPEC_SETMEM_FILL))
(use (match_operand:HI 1 "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))
(clobber (reg:CC VAX_PSL_REGNUM))]
"reload_completed"
"movc5 $0,(%%ap),%2,%1,%0")
;; Extension and truncation insns.
(define_insn_and_split "truncsiqi2"
[(set (match_operand:QI 0 "nonimmediate_operand" "=g")
(truncate:QI (match_operand:SI 1 "nonimmediate_operand" "nrmT")))]
""
"#"
"reload_completed"
[(parallel
[(set (match_dup 0)
(truncate:QI (match_dup 1)))
(clobber (reg:CC VAX_PSL_REGNUM))])]
"")
(define_insn "*truncsiqi2"
[(set (match_operand:QI 0 "nonimmediate_operand" "=g")
(truncate:QI (match_operand:SI 1 "nonimmediate_operand" "nrmT")))
(clobber (reg:CC VAX_PSL_REGNUM))]
"reload_completed"
"cvtlb %1,%0")
(define_insn_and_split "truncsihi2"
[(set (match_operand:HI 0 "nonimmediate_operand" "=g")
(truncate:HI (match_operand:SI 1 "nonimmediate_operand" "nrmT")))]
""
"#"
"reload_completed"
[(parallel
[(set (match_dup 0)
(truncate:HI (match_dup 1)))
(clobber (reg:CC VAX_PSL_REGNUM))])]
"")
(define_insn "*truncsihi2"
[(set (match_operand:HI 0 "nonimmediate_operand" "=g")
(truncate:HI (match_operand:SI 1 "nonimmediate_operand" "nrmT")))
(clobber (reg:CC VAX_PSL_REGNUM))]
"reload_completed"
"cvtlw %1,%0")
(define_insn_and_split "trunchiqi2"
[(set (match_operand:QI 0 "nonimmediate_operand" "=g")
(truncate:QI (match_operand:HI 1 "nonimmediate_operand" "g")))]
""
"#"
"reload_completed"
[(parallel
[(set (match_dup 0)
(truncate:QI (match_dup 1)))
(clobber (reg:CC VAX_PSL_REGNUM))])]
"")
(define_insn "*trunchiqi2"
[(set (match_operand:QI 0 "nonimmediate_operand" "=g")
(truncate:QI (match_operand:HI 1 "nonimmediate_operand" "g")))
(clobber (reg:CC VAX_PSL_REGNUM))]
"reload_completed"
"cvtwb %1,%0")
(define_insn_and_split "extendhisi2"
[(set (match_operand:SI 0 "nonimmediate_operand" "=g")
(sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "g")))]
""
"#"
"reload_completed"
[(parallel
[(set (match_dup 0)
(sign_extend:SI (match_dup 1)))
(clobber (reg:CC VAX_PSL_REGNUM))])]
"")
(define_insn "*extendhisi2"
[(set (match_operand:SI 0 "nonimmediate_operand" "=g")
(sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "g")))
(clobber (reg:CC VAX_PSL_REGNUM))]
"reload_completed"
"cvtwl %1,%0")
(define_insn_and_split "extendqihi2"
[(set (match_operand:HI 0 "nonimmediate_operand" "=g")
(sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "g")))]
""
"#"
"reload_completed"
[(parallel
[(set (match_dup 0)
(sign_extend:HI (match_dup 1)))
(clobber (reg:CC VAX_PSL_REGNUM))])]
"")
(define_insn "*extendqihi2"
[(set (match_operand:HI 0 "nonimmediate_operand" "=g")
(sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "g")))
(clobber (reg:CC VAX_PSL_REGNUM))]
"reload_completed"
"cvtbw %1,%0")
(define_insn_and_split "extendqisi2"
[(set (match_operand:SI 0 "nonimmediate_operand" "=g")
(sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "g")))]
""
"#"
"reload_completed"
[(parallel
[(set (match_dup 0)
(sign_extend:SI (match_dup 1)))
(clobber (reg:CC VAX_PSL_REGNUM))])]
"")
(define_insn "*extendqisi2"
[(set (match_operand:SI 0 "nonimmediate_operand" "=g")
(sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "g")))
(clobber (reg:CC VAX_PSL_REGNUM))]
"reload_completed"
"cvtbl %1,%0")
(define_insn_and_split "extendsfdf2"
[(set (match_operand:DF 0 "nonimmediate_operand" "=g")
(float_extend:DF (match_operand:SF 1 "general_operand" "gF")))]
""
"#"
"reload_completed"
[(parallel
[(set (match_dup 0)
(float_extend:DF (match_dup 1)))
(clobber (reg:CC VAX_PSL_REGNUM))])]
"")
(define_insn "*extendsfdf2"
[(set (match_operand:DF 0 "nonimmediate_operand" "=g")
(float_extend:DF (match_operand:SF 1 "general_operand" "gF")))
(clobber (reg:CC VAX_PSL_REGNUM))]
"reload_completed"
"cvtf%# %1,%0")
(define_insn_and_split "truncdfsf2"
[(set (match_operand:SF 0 "nonimmediate_operand" "=g")
(float_truncate:SF (match_operand:DF 1 "general_operand" "gF")))]
""
"#"
"reload_completed"
[(parallel
[(set (match_dup 0)
(float_truncate:SF (match_dup 1)))
(clobber (reg:CC VAX_PSL_REGNUM))])]
"")
(define_insn "*truncdfsf2"
[(set (match_operand:SF 0 "nonimmediate_operand" "=g")
(float_truncate:SF (match_operand:DF 1 "general_operand" "gF")))
(clobber (reg:CC VAX_PSL_REGNUM))]
"reload_completed"
"cvt%#f %1,%0")
(define_insn_and_split "zero_extendhisi2"
[(set (match_operand:SI 0 "nonimmediate_operand" "=g")
(zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "g")))]
""
"#"
"reload_completed"
[(parallel
[(set (match_dup 0)
(zero_extend:SI (match_dup 1)))
(clobber (reg:CC VAX_PSL_REGNUM))])]
"")
(define_insn "*zero_extendhisi2"
[(set (match_operand:SI 0 "nonimmediate_operand" "=g")
(zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "g")))
(clobber (reg:CC VAX_PSL_REGNUM))]
"reload_completed"
"movzwl %1,%0")
(define_insn_and_split "zero_extendqihi2"
[(set (match_operand:HI 0 "nonimmediate_operand" "=g")
(zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "g")))]
""
"#"
"reload_completed"
[(parallel
[(set (match_dup 0)
(zero_extend:HI (match_dup 1)))
(clobber (reg:CC VAX_PSL_REGNUM))])]
"")
(define_insn "*zero_extendqihi2"
[(set (match_operand:HI 0 "nonimmediate_operand" "=g")
(zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "g")))
(clobber (reg:CC VAX_PSL_REGNUM))]
"reload_completed"
"movzbw %1,%0")
(define_insn_and_split "zero_extendqisi2"
[(set (match_operand:SI 0 "nonimmediate_operand" "=g")
(zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "g")))]
""
"#"
"reload_completed"
[(parallel
[(set (match_dup 0)
(zero_extend:SI (match_dup 1)))
(clobber (reg:CC VAX_PSL_REGNUM))])]
"")
(define_insn "*zero_extendqisi2"
[(set (match_operand:SI 0 "nonimmediate_operand" "=g")
(zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "g")))
(clobber (reg:CC VAX_PSL_REGNUM))]
"reload_completed"
"movzbl %1,%0")
;; Fix-to-float conversion insns.
(define_insn_and_split "float2"
[(set (match_operand:VAXfp 0 "nonimmediate_operand" "=g")
(float:VAXfp (match_operand:VAXint 1 "nonimmediate_operand" "g")))]
""
"#"
"reload_completed"
[(parallel
[(set (match_dup 0)
(float:VAXfp (match_dup 1)))
(clobber (reg:CC VAX_PSL_REGNUM))])]
"")
(define_insn "*float2"
[(set (match_operand:VAXfp 0 "nonimmediate_operand" "=g")
(float:VAXfp (match_operand:VAXint 1 "nonimmediate_operand" "g")))
(clobber (reg:CC VAX_PSL_REGNUM))]
"reload_completed"
"cvt %1,%0")
;; Float-to-fix conversion insns.
(define_insn_and_split "fix_trunc2"
[(set (match_operand:VAXint 0 "nonimmediate_operand" "=g")
(fix:VAXint (match_operand:VAXfp 1 "general_operand" "gF")))]
""
"#"
"reload_completed"
[(parallel
[(set (match_dup 0)
(fix:VAXint (match_dup 1)))
(clobber (reg:CC VAX_PSL_REGNUM))])]
"")
(define_insn "*fix_trunc2"
[(set (match_operand:VAXint 0 "nonimmediate_operand" "=g")
(fix:VAXint (match_operand:VAXfp 1 "general_operand" "gF")))
(clobber (reg:CC VAX_PSL_REGNUM))]
"reload_completed"
"cvt %1,%0")
(define_expand "fixuns_trunc2"
[(set (match_operand:VAXint 0 "nonimmediate_operand" "")
(fix:VAXint (match_operand:VAXfp 1 "general_operand")))]
"")
;;- All kinds of add instructions.
(define_insn_and_split "add3"
[(set (match_operand:VAXfp 0 "nonimmediate_operand" "=g,g,g")
(plus:VAXfp (match_operand:VAXfp 1 "general_operand" "0,gF,gF")
(match_operand:VAXfp 2 "general_operand" "gF,0,gF")))]
""
"#"
"reload_completed"
[(parallel
[(set (match_dup 0)
(plus:VAXfp (match_dup 1)
(match_dup 2)))
(clobber (reg:CC VAX_PSL_REGNUM))])]
"")
(define_insn "*add3"
[(set (match_operand:VAXfp 0 "nonimmediate_operand" "=g,g,g")
(plus:VAXfp (match_operand:VAXfp 1 "general_operand" "0,gF,gF")
(match_operand:VAXfp 2 "general_operand" "gF,0,gF")))
(clobber (reg:CC VAX_PSL_REGNUM))]
"reload_completed"
"@
add2 %2,%0
add2 %1,%0
add3 %1,%2,%0")
(define_insn_and_split "add3"
[(set (match_operand:VAXint 0 "nonimmediate_operand" "=g")
(plus:VAXint (match_operand:VAXint 1 "general_operand" "nrmT")
(match_operand:VAXint 2 "general_operand" "nrmT")))]
""
"#"
"reload_completed"
[(parallel
[(set (match_dup 0)
(plus:VAXint (match_dup 1)
(match_dup 2)))
(clobber (reg:CC VAX_PSL_REGNUM))])]
"")
(define_insn "*add3"
[(set (match_operand:VAXint 0 "nonimmediate_operand" "=g")
(plus:VAXint (match_operand:VAXint 1 "general_operand" "nrmT")
(match_operand:VAXint 2 "general_operand" "nrmT")))
(clobber (reg:CC VAX_PSL_REGNUM))]
"reload_completed"
"* return vax_output_int_add (insn, operands, mode);")
(define_expand "adddi3"
[(set (match_operand:DI 0 "nonimmediate_operand" "=g")
(plus:DI (match_operand:DI 1 "general_operand" "g")
(match_operand:DI 2 "general_operand" "g")))]
"!reload_in_progress"
"vax_expand_addsub_di_operands (operands, PLUS); DONE;")
(define_insn_and_split "adcdi3"
[(set (match_operand:DI 0 "nonimmediate_addsub_di_operand" "=Rr")
(plus:DI (match_operand:DI 1 "general_addsub_di_operand" "%0")
(match_operand:DI 2 "general_addsub_di_operand" "nRr")))]
"TARGET_QMATH"
"#"
"&& reload_completed"
[(parallel
[(set (match_dup 0)
(plus:DI (match_dup 1)
(match_dup 2)))
(clobber (reg:CC VAX_PSL_REGNUM))])]
"")
(define_insn "*adcdi3"
[(set (match_operand:DI 0 "nonimmediate_addsub_di_operand" "=Rr")
(plus:DI (match_operand:DI 1 "general_addsub_di_operand" "%0")
(match_operand:DI 2 "general_addsub_di_operand" "nRr")))
(clobber (reg:CC VAX_PSL_REGNUM))]
"TARGET_QMATH && reload_completed"
"* return vax_output_int_add (insn, operands, DImode);")
;; The add-with-carry (adwc) instruction only accepts two operands.
(define_insn_and_split "adddi3_old"
[(set (match_operand:DI 0 "nonimmediate_operand" "=ro>,ro>")
(plus:DI (match_operand:DI 1 "general_operand" "%0,ro>")
(match_operand:DI 2 "general_operand" "Fsro,Fs")))]
"!TARGET_QMATH"
"#"
"&& reload_completed"
[(parallel
[(set (match_dup 0)
(plus:DI (match_dup 1)
(match_dup 2)))
(clobber (reg:CC VAX_PSL_REGNUM))])]
"")
(define_insn "*adddi3_old"
[(set (match_operand:DI 0 "nonimmediate_operand" "=ro>,ro>")
(plus:DI (match_operand:DI 1 "general_operand" "%0,ro>")
(match_operand:DI 2 "general_operand" "Fsro,Fs")))
(clobber (reg:CC VAX_PSL_REGNUM))]
"!TARGET_QMATH && reload_completed"
"* return vax_output_int_add (insn, operands, DImode);")
;;- All kinds of subtract instructions.
(define_insn_and_split "sub3"
[(set (match_operand:VAXfp 0 "nonimmediate_operand" "=g,g")
(minus:VAXfp (match_operand:VAXfp 1 "general_operand" "0,gF")
(match_operand:VAXfp 2 "general_operand" "gF,gF")))]
""
"#"
"reload_completed"
[(parallel
[(set (match_dup 0)
(minus:VAXfp (match_dup 1)
(match_dup 2)))
(clobber (reg:CC VAX_PSL_REGNUM))])]
"")
(define_insn "*sub3"
[(set (match_operand:VAXfp 0 "nonimmediate_operand" "=g,g")
(minus:VAXfp (match_operand:VAXfp 1 "general_operand" "0,gF")
(match_operand:VAXfp 2 "general_operand" "gF,gF")))
(clobber (reg:CC VAX_PSL_REGNUM))]
"reload_completed"
"@
sub2 %2,%0
sub3 %2,%1,%0")
(define_insn_and_split "sub3"
[(set (match_operand:VAXint 0 "nonimmediate_operand" "=g,g")
(minus:VAXint (match_operand:VAXint 1 "general_operand" "0,nrmT")
(match_operand:VAXint 2 "general_operand" "nrmT,nrmT")))]
""
"#"
"reload_completed"
[(parallel
[(set (match_dup 0)
(minus:VAXint (match_dup 1)
(match_dup 2)))
(clobber (reg:CC VAX_PSL_REGNUM))])]
"")
(define_insn "*sub3"
[(set (match_operand:VAXint 0 "nonimmediate_operand" "=g,g")
(minus:VAXint (match_operand:VAXint 1 "general_operand" "0,nrmT")
(match_operand:VAXint 2 "general_operand" "nrmT,nrmT")))
(clobber (reg:CC VAX_PSL_REGNUM))]
"reload_completed"
"@
sub2 %2,%0
sub3 %2,%1,%0")
(define_insn "*sub3_cc"
[(set (reg:CC VAX_PSL_REGNUM)
(compare:CC (match_operand:VAXint 1 "general_operand" "0,nrmT")
(match_operand:VAXint 2 "general_operand" "nrmT,nrmT")))
(set (match_operand:VAXint 0 "nonimmediate_operand" "=g,g")
(minus:VAXint (match_dup 1)
(match_dup 2)))]
"reload_completed"
"@
sub2 %2,%0
sub3 %2,%1,%0")
(define_expand "subdi3"
[(set (match_operand:DI 0 "nonimmediate_operand" "=g")
(minus:DI (match_operand:DI 1 "general_operand" "g")
(match_operand:DI 2 "general_operand" "g")))]
"!reload_in_progress"
"vax_expand_addsub_di_operands (operands, MINUS); DONE;")
(define_insn_and_split "sbcdi3"
[(set (match_operand:DI 0 "nonimmediate_addsub_di_operand" "=Rr,Rr")
(minus:DI (match_operand:DI 1 "general_addsub_di_operand" "0,I")
(match_operand:DI 2 "general_addsub_di_operand" "nRr,Rr")))]
"TARGET_QMATH"
"#"
"&& reload_completed"
[(parallel
[(set (match_dup 0)
(minus:DI (match_dup 1)
(match_dup 2)))
(clobber (reg:CC VAX_PSL_REGNUM))])]
"")
(define_insn "*sbcdi3"
[(set (match_operand:DI 0 "nonimmediate_addsub_di_operand" "=Rr,Rr")
(minus:DI (match_operand:DI 1 "general_addsub_di_operand" "0,I")
(match_operand:DI 2 "general_addsub_di_operand" "nRr,Rr")))
(clobber (reg:CC VAX_PSL_REGNUM))]
"TARGET_QMATH && reload_completed"
"* return vax_output_int_subtract (insn, operands, DImode);")
;; The subtract-with-carry (sbwc) instruction only takes two operands.
(define_insn_and_split "subdi3_old"
[(set (match_operand:DI 0 "nonimmediate_operand" "=or>,or>")
(minus:DI (match_operand:DI 1 "general_operand" "0,or>")
(match_operand:DI 2 "general_operand" "Fsor,Fs")))]
"!TARGET_QMATH"
"#"
"&& reload_completed"
[(parallel
[(set (match_dup 0)
(minus:DI (match_dup 1)
(match_dup 2)))
(clobber (reg:CC VAX_PSL_REGNUM))])]
"")
(define_insn "*subdi3_old"
[(set (match_operand:DI 0 "nonimmediate_operand" "=or>,or>")
(minus:DI (match_operand:DI 1 "general_operand" "0,or>")
(match_operand:DI 2 "general_operand" "Fsor,Fs")))
(clobber (reg:CC VAX_PSL_REGNUM))]
"!TARGET_QMATH && reload_completed"
"* return vax_output_int_subtract (insn, operands, DImode);")
;;- Multiply instructions.
(define_insn_and_split "mul3"
[(set (match_operand:VAXfp 0 "nonimmediate_operand" "=g,g,g")
(mult:VAXfp (match_operand:VAXfp 1 "general_operand" "0,gF,gF")
(match_operand:VAXfp 2 "general_operand" "gF,0,gF")))]
""
"#"
"reload_completed"
[(parallel
[(set (match_dup 0)
(mult:VAXfp (match_dup 1)
(match_dup 2)))
(clobber (reg:CC VAX_PSL_REGNUM))])]
"")
(define_insn "*mul3"
[(set (match_operand:VAXfp 0 "nonimmediate_operand" "=g,g,g")
(mult:VAXfp (match_operand:VAXfp 1 "general_operand" "0,gF,gF")
(match_operand:VAXfp 2 "general_operand" "gF,0,gF")))
(clobber (reg:CC VAX_PSL_REGNUM))]
"reload_completed"
"@
mul2 %2,%0
mul2 %1,%0
mul3 %1,%2,%0")
(define_insn_and_split "mul3"
[(set (match_operand:VAXint 0 "nonimmediate_operand" "=g,g,g")
(mult:VAXint (match_operand:VAXint 1 "general_operand" "0,nrmT,nrmT")
(match_operand:VAXint 2 "general_operand" "nrmT,0,nrmT")))]
""
"#"
"reload_completed"
[(parallel
[(set (match_dup 0)
(mult:VAXint (match_dup 1)
(match_dup 2)))
(clobber (reg:CC VAX_PSL_REGNUM))])]
"")
(define_insn "*mul3"
[(set (match_operand:VAXint 0 "nonimmediate_operand" "=g,g,g")
(mult:VAXint (match_operand:VAXint 1 "general_operand" "0,nrmT,nrmT")
(match_operand:VAXint 2 "general_operand" "nrmT,0,nrmT")))
(clobber (reg:CC VAX_PSL_REGNUM))]
"reload_completed"
"@
mul2 %2,%0
mul2 %1,%0
mul3 %1,%2,%0")
(define_insn_and_split "mulsidi3"
[(set (match_operand:DI 0 "nonimmediate_operand" "=g")
(mult:DI
(sign_extend:DI (match_operand:SI 1 "general_operand" "nrmT"))
(sign_extend:DI (match_operand:SI 2 "general_operand" "nrmT"))))]
""
"#"
"reload_completed"
[(parallel
[(set (match_dup 0)
(mult:DI
(sign_extend:DI (match_dup 1))
(sign_extend:DI (match_dup 2))))
(clobber (reg:CC VAX_PSL_REGNUM))])]
"")
(define_insn "*mulsidi3"
[(set (match_operand:DI 0 "nonimmediate_operand" "=g")
(mult:DI
(sign_extend:DI (match_operand:SI 1 "general_operand" "nrmT"))
(sign_extend:DI (match_operand:SI 2 "general_operand" "nrmT"))))
(clobber (reg:CC VAX_PSL_REGNUM))]
"reload_completed"
"emul %1,%2,$0,%0")
(define_insn_and_split "*maddsidi4"
[(set (match_operand:DI 0 "nonimmediate_operand" "=g")
(plus:DI
(mult:DI
(sign_extend:DI (match_operand:SI 1 "general_operand" "nrmT"))
(sign_extend:DI (match_operand:SI 2 "general_operand" "nrmT")))
(sign_extend:DI (match_operand:SI 3 "general_operand" "g"))))]
""
"#"
"reload_completed"
[(parallel
[(set (match_dup 0)
(plus:DI
(mult:DI
(sign_extend:DI (match_dup 1))
(sign_extend:DI (match_dup 2)))
(sign_extend:DI (match_dup 3))))
(clobber (reg:CC VAX_PSL_REGNUM))])]
"")
(define_insn "*maddsidi4_2"
[(set (match_operand:DI 0 "nonimmediate_operand" "=g")
(plus:DI
(mult:DI
(sign_extend:DI (match_operand:SI 1 "general_operand" "nrmT"))
(sign_extend:DI (match_operand:SI 2 "general_operand" "nrmT")))
(sign_extend:DI (match_operand:SI 3 "nonimmediate_operand" "g"))))
(clobber (reg:CC VAX_PSL_REGNUM))]
"reload_completed"
"emul %1,%2,%3,%0")
;; 'F' constraint means type CONST_DOUBLE
(define_insn_and_split "*maddsidi4_const"
[(set (match_operand:DI 0 "nonimmediate_operand" "=g")
(plus:DI
(mult:DI
(sign_extend:DI (match_operand:SI 1 "general_operand" "nrmT"))
(sign_extend:DI (match_operand:SI 2 "general_operand" "nrmT")))
(match_operand:DI 3 "immediate_operand" "F")))]
"GET_CODE (operands[3]) == CONST_DOUBLE
&& CONST_DOUBLE_HIGH (operands[3]) == (CONST_DOUBLE_LOW (operands[3]) >> 31)"
"#"
"&& reload_completed"
[(parallel
[(set (match_dup 0)
(plus:DI
(mult:DI
(sign_extend:DI (match_dup 1))
(sign_extend:DI (match_dup 2)))
(match_dup 3)))
(clobber (reg:CC VAX_PSL_REGNUM))])]
"")
(define_insn "*maddsidi4_const_2"
[(set (match_operand:DI 0 "nonimmediate_operand" "=g")
(plus:DI
(mult:DI
(sign_extend:DI (match_operand:SI 1 "general_operand" "nrmT"))
(sign_extend:DI (match_operand:SI 2 "general_operand" "nrmT")))
(match_operand:DI 3 "immediate_operand" "F")))
(clobber (reg:CC VAX_PSL_REGNUM))]
"GET_CODE (operands[3]) == CONST_DOUBLE
&& CONST_DOUBLE_HIGH (operands[3]) == (CONST_DOUBLE_LOW (operands[3]) >> 31)
&& reload_completed"
"*
{
if (CONST_DOUBLE_HIGH (operands[3]))
operands[3] = GEN_INT (CONST_DOUBLE_LOW (operands[3]));
return \"emul %1,%2,%3,%0\";
}")
;;- Divide instructions.
(define_insn_and_split "div3"
[(set (match_operand:VAXfp 0 "nonimmediate_operand" "=g,g")
(div:VAXfp (match_operand:VAXfp 1 "general_operand" "0,gF")
(match_operand:VAXfp 2 "general_operand" "gF,gF")))]
""
"#"
"reload_completed"
[(parallel
[(set (match_dup 0)
(div:VAXfp (match_dup 1)
(match_dup 2)))
(clobber (reg:CC VAX_PSL_REGNUM))])]
"")
(define_insn "*div3"
[(set (match_operand:VAXfp 0 "nonimmediate_operand" "=g,g")
(div:VAXfp (match_operand:VAXfp 1 "general_operand" "0,gF")
(match_operand:VAXfp 2 "general_operand" "gF,gF")))
(clobber (reg:CC VAX_PSL_REGNUM))]
"reload_completed"
"@
div2 %2,%0
div3 %2,%1,%0")
(define_insn_and_split "div3"
[(set (match_operand:VAXint 0 "nonimmediate_operand" "=g,g")
(div:VAXint (match_operand:VAXint 1 "general_operand" "0,nrmT")
(match_operand:VAXint 2 "general_operand" "nrmT,nrmT")))]
""
"#"
"reload_completed"
[(parallel
[(set (match_dup 0)
(div:VAXint (match_dup 1)
(match_dup 2)))
(clobber (reg:CC VAX_PSL_REGNUM))])]
"")
(define_insn "*div3"
[(set (match_operand:VAXint 0 "nonimmediate_operand" "=g,g")
(div:VAXint (match_operand:VAXint 1 "general_operand" "0,nrmT")
(match_operand:VAXint 2 "general_operand" "nrmT,nrmT")))
(clobber (reg:CC VAX_PSL_REGNUM))]
"reload_completed"
"@
div2 %2,%0
div3 %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_and_split "divmoddisi4"
;; [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
;; (div:SI (match_operand:DI 1 "general_operand" "g")
;; (match_operand:SI 2 "general_operand" "g")))
;; (set (match_operand:SI 3 "nonimmediate_operand" "=g")
;; (mod:SI (match_dup 1)
;; (match_dup 2)))]
;; ""
;; "#"
;; "reload_completed"
;; [(parallel
;; [(set (match_dup 0)
;; (div:SI (match_dup 1)
;; (match_dup 2)))
;; (set (match_dup 3)
;; (mod:SI (match_dup 1)
;; (match_dup 2)))
;; (clobber (reg:CC VAX_PSL_REGNUM))])]
;; "")
;;
;;(define_insn "*divmoddisi4"
;; [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
;; (div:SI (match_operand:DI 1 "general_operand" "g")
;; (match_operand:SI 2 "general_operand" "g")))
;; (set (match_operand:SI 3 "nonimmediate_operand" "=g")
;; (mod:SI (match_dup 1)
;; (match_dup 2)))
;; (clobber (reg:CC VAX_PSL_REGNUM))]
;; "reload_completed"
;; "ediv %2,%1,%0,%3")
;; Bit-and on the VAX is done with a clear-bits insn.
(define_expand "and3"
[(set (match_operand:VAXint 0 "nonimmediate_operand" "")
(and:VAXint (not:VAXint (match_operand:VAXint 1 "general_operand" ""))
(match_operand:VAXint 2 "general_operand" "")))]
""
"
{
rtx op1 = operands[1];
/* If there is a constant argument, complement that one. */
if (CONST_INT_P (operands[2]) && ! CONST_INT_P (op1))
{
operands[1] = operands[2];
operands[2] = op1;
op1 = operands[1];
}
if (CONST_INT_P (op1))
operands[1] = GEN_INT (~INTVAL (op1));
else
operands[1] = expand_unop (mode, one_cmpl_optab, op1, 0, 1);
}")
(define_insn_and_split "*and3"
[(set (match_operand:VAXint 0 "nonimmediate_operand" "=g,g")
(and:VAXint (not:VAXint
(match_operand:VAXint 1 "general_operand" "nrmT,nrmT"))
(match_operand:VAXint 2 "general_operand" "0,nrmT")))]
""
"#"
"reload_completed"
[(parallel
[(set (match_dup 0)
(and:VAXint (not:VAXint
(match_dup 1))
(match_dup 2)))
(clobber (reg:CC VAX_PSL_REGNUM))])]
"")
(define_insn "*and3_2"
[(set (match_operand:VAXint 0 "nonimmediate_operand" "=g,g")
(and:VAXint (not:VAXint
(match_operand:VAXint 1 "general_operand" "nrmT,nrmT"))
(match_operand:VAXint 2 "general_operand" "0,nrmT")))
(clobber (reg:CC VAX_PSL_REGNUM))]
"reload_completed"
"@
bic2 %1,%0
bic3 %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.cc.
(define_insn_and_split "*and3_const_int"
[(set (match_operand:VAXint 0 "nonimmediate_operand" "=g,g")
(and:VAXint (match_operand:VAXint 1 "general_operand" "0,nrmT")
(match_operand:VAXint 2 "const_int_operand" "n,n")))]
""
"#"
"reload_completed"
[(parallel
[(set (match_dup 0)
(and:VAXint (match_dup 1)
(match_dup 2)))
(clobber (reg:CC VAX_PSL_REGNUM))])]
"")
(define_insn "*and3_2_const_int"
[(set (match_operand:VAXint 0 "nonimmediate_operand" "=g,g")
(and:VAXint (match_operand:VAXint 1 "general_operand" "0,nrmT")
(match_operand:VAXint 2 "const_int_operand" "n,n")))
(clobber (reg:CC VAX_PSL_REGNUM))]
"reload_completed"
"@
bic2 %2,%0
bic3 %2,%1,%0")
;; We have no direct AND operation and consequently the RTL sequence
;; the "and3" pattern produces does not match the instruction
;; the "*bit" pattern does for the purpose of the compare
;; elimination pass. Try to get rid of the extra operation by hand
;; and where the sequence is used to set the condition codes only
;; convert MCOM/BIC => BIT.
(define_peephole2
[(parallel
[(set (match_operand:VAXint 0 "register_operand")
(not:VAXint (match_operand:VAXint 1 "general_operand")))
(clobber (reg:CC VAX_PSL_REGNUM))])
(parallel
[(set (reg:VAXccnz VAX_PSL_REGNUM)
(compare:VAXccnz
(and:VAXint (not:VAXint (match_dup 0))
(match_operand:VAXint 3 "general_operand"))
(const_int 0)))
(set (match_operand:VAXint 2 "register_operand")
(and:VAXint (not:VAXint (match_dup 0))
(match_dup 3)))])]
"peep2_reg_dead_p (2, operands[0]) && peep2_reg_dead_p (2, operands[2])"
[(set (reg:VAXccnz VAX_PSL_REGNUM)
(compare:VAXccnz
(and:VAXint (match_dup 1)
(match_dup 3))
(const_int 0)))]
"")
;;- Bit set instructions.
(define_insn_and_split "ior3"
[(set (match_operand:VAXint 0 "nonimmediate_operand" "=g,g,g")
(ior:VAXint (match_operand:VAXint 1 "general_operand" "0,nrmT,nrmT")
(match_operand:VAXint 2 "general_operand" "nrmT,0,nrmT")))]
""
"#"
"reload_completed"
[(parallel
[(set (match_dup 0)
(ior:VAXint (match_dup 1)
(match_dup 2)))
(clobber (reg:CC VAX_PSL_REGNUM))])]
"")
(define_insn "*ior3"
[(set (match_operand:VAXint 0 "nonimmediate_operand" "=g,g,g")
(ior:VAXint (match_operand:VAXint 1 "general_operand" "0,nrmT,nrmT")
(match_operand:VAXint 2 "general_operand" "nrmT,0,nrmT")))
(clobber (reg:CC VAX_PSL_REGNUM))]
"reload_completed"
"@
bis2 %2,%0
bis2 %1,%0
bis3 %2,%1,%0")
;;- xor instructions.
(define_insn_and_split "xor3"
[(set (match_operand:VAXint 0 "nonimmediate_operand" "=g,g,g")
(xor:VAXint (match_operand:VAXint 1 "general_operand" "0,nrmT,nrmT")
(match_operand:VAXint 2 "general_operand" "nrmT,0,nrmT")))]
""
"#"
"reload_completed"
[(parallel
[(set (match_dup 0)
(xor:VAXint (match_dup 1)
(match_dup 2)))
(clobber (reg:CC VAX_PSL_REGNUM))])]
"")
(define_insn "*xor3"
[(set (match_operand:VAXint 0 "nonimmediate_operand" "=g,g,g")
(xor:VAXint (match_operand:VAXint 1 "general_operand" "0,nrmT,nrmT")
(match_operand:VAXint 2 "general_operand" "nrmT,0,nrmT")))
(clobber (reg:CC VAX_PSL_REGNUM))]
"reload_completed"
"@
xor2 %2,%0
xor2 %1,%0
xor3 %2,%1,%0")
(define_insn_and_split "neg2"
[(set (match_operand:VAXfp 0 "nonimmediate_operand" "=g")
(neg:VAXfp (match_operand:VAXfp 1 "general_operand" "gF")))]
""
"#"
"reload_completed"
[(parallel
[(set (match_dup 0)
(neg:VAXfp (match_dup 1)))
(clobber (reg:CC VAX_PSL_REGNUM))])]
"")
(define_insn "*neg2"
[(set (match_operand:VAXfp 0 "nonimmediate_operand" "=g")
(neg:VAXfp (match_operand:VAXfp 1 "general_operand" "gF")))
(clobber (reg:CC VAX_PSL_REGNUM))]
"reload_completed"
"mneg %1,%0")
(define_insn_and_split "neg2"
[(set (match_operand:VAXint 0 "nonimmediate_operand" "=g")
(neg:VAXint (match_operand:VAXint 1 "general_operand" "nrmT")))]
""
"#"
"reload_completed"
[(parallel
[(set (match_dup 0)
(neg:VAXint (match_dup 1)))
(clobber (reg:CC VAX_PSL_REGNUM))])]
"")
(define_insn "*neg2"
[(set (match_operand:VAXint 0 "nonimmediate_operand" "=g")
(neg:VAXint (match_operand:VAXint 1 "general_operand" "nrmT")))
(clobber (reg:CC VAX_PSL_REGNUM))]
"reload_completed"
"mneg %1,%0")
(define_insn "*neg2_cc"
[(set (reg:CC VAX_PSL_REGNUM)
(compare:CC (const_int 0)
(neg:VAXint
(match_operand:VAXint 1 "general_operand" "0,nrmT"))))
(set (match_operand:VAXint 0 "nonimmediate_operand" "=g,g")
(neg:VAXint (match_dup 1)))]
"reload_completed"
"mneg %1,%0")
(define_insn_and_split "one_cmpl2"
[(set (match_operand:VAXint 0 "nonimmediate_operand" "=g")
(not:VAXint (match_operand:VAXint 1 "general_operand" "nrmT")))]
""
"#"
"reload_completed"
[(parallel
[(set (match_dup 0)
(not:VAXint (match_dup 1)))
(clobber (reg:CC VAX_PSL_REGNUM))])]
"")
(define_insn "*one_cmpl2"
[(set (match_operand:VAXint 0 "nonimmediate_operand" "=g")
(not:VAXint (match_operand:VAXint 1 "general_operand" "nrmT")))
(clobber (reg:CC VAX_PSL_REGNUM))]
"reload_completed"
"mcom %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 (! CONST_INT_P(operands[2]))
operands[2] = gen_rtx_NEG (QImode, negate_rtx (QImode, operands[2]));
}")
(define_insn_and_split "*ashlnegsi3_const_int"
[(set (match_operand:SI 0 "nonimmediate_operand" "=g")
(ashiftrt:SI (match_operand:SI 1 "general_operand" "nrmT")
(match_operand:QI 2 "const_int_operand" "n")))]
""
"#"
"reload_completed"
[(parallel
[(set (match_dup 0)
(ashiftrt:SI (match_dup 1)
(match_dup 2)))
(clobber (reg:CC VAX_PSL_REGNUM))])]
"")
(define_insn "*ashlnegsi3_const_int_2"
[(set (match_operand:SI 0 "nonimmediate_operand" "=g")
(ashiftrt:SI (match_operand:SI 1 "general_operand" "nrmT")
(match_operand:QI 2 "const_int_operand" "n")))
(clobber (reg:CC VAX_PSL_REGNUM))]
"reload_completed"
"ashl $%n2,%1,%0")
(define_insn_and_split "*ashlnegsi3"
[(set (match_operand:SI 0 "nonimmediate_operand" "=g")
(ashiftrt:SI (match_operand:SI 1 "general_operand" "nrmT")
(neg:QI (match_operand:QI 2 "general_operand" "g"))))]
""
"#"
"reload_completed"
[(parallel
[(set (match_dup 0)
(ashiftrt:SI (match_dup 1)
(neg:QI (match_dup 2))))
(clobber (reg:CC VAX_PSL_REGNUM))])]
"")
(define_insn "*ashlnegsi3_2"
[(set (match_operand:SI 0 "nonimmediate_operand" "=g")
(ashiftrt:SI (match_operand:SI 1 "general_operand" "nrmT")
(neg:QI (match_operand:QI 2 "general_operand" "g"))))
(clobber (reg:CC VAX_PSL_REGNUM))]
"reload_completed"
"ashl %2,%1,%0")
(define_insn_and_split "ashlsi3"
[(set (match_operand:SI 0 "nonimmediate_operand" "=g")
(ashift:SI (match_operand:SI 1 "general_operand" "nrmT")
(match_operand:QI 2 "general_operand" "g")))]
""
"#"
"reload_completed"
[(parallel
[(set (match_dup 0)
(ashift:SI (match_dup 1)
(match_dup 2)))
(clobber (reg:CC VAX_PSL_REGNUM))])]
"")
(define_insn "*ashlsi3"
[(set (match_operand:SI 0 "nonimmediate_operand" "=g")
(ashift:SI (match_operand:SI 1 "general_operand" "nrmT")
(match_operand:QI 2 "general_operand" "g")))
(clobber (reg:CC VAX_PSL_REGNUM))]
"reload_completed"
"*
{
if (operands[2] == const1_rtx && rtx_equal_p (operands[0], operands[1]))
return \"addl2 %0,%0\";
if (REG_P (operands[1]) && CONST_INT_P (operands[2]))
{
int i = INTVAL (operands[2]);
if (i == 1)
return \"addl3 %1,%1,%0\";
if (i == 2 && !optimize_size)
{
if (push_operand (operands[0], SImode))
return \"pushal 0[%1]\";
return \"moval 0[%1],%0\";
}
if (i == 3 && !optimize_size)
{
if (push_operand (operands[0], SImode))
return \"pushaq 0[%1]\";
return \"movaq 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_and_split "ashldi3"
[(set (match_operand:DI 0 "nonimmediate_operand" "=g")
(ashift:DI (match_operand:DI 1 "general_operand" "g")
(match_operand:QI 2 "general_operand" "g")))]
""
"#"
"reload_completed"
[(parallel
[(set (match_dup 0)
(ashift:DI (match_dup 1)
(match_dup 2)))
(clobber (reg:CC VAX_PSL_REGNUM))])]
"")
(define_insn "*ashldi3"
[(set (match_operand:DI 0 "nonimmediate_operand" "=g")
(ashift:DI (match_operand:DI 1 "general_operand" "g")
(match_operand:QI 2 "general_operand" "g")))
(clobber (reg:CC VAX_PSL_REGNUM))]
"reload_completed"
"ashq %2,%D1,%0")
(define_insn_and_split "*ashlnegdi3"
[(set (match_operand:DI 0 "nonimmediate_operand" "=g")
(ashiftrt:DI (match_operand:DI 1 "general_operand" "g")
(neg:QI (match_operand:QI 2 "general_operand" "g"))))]
""
"#"
"reload_completed"
[(parallel
[(set (match_dup 0)
(ashiftrt:DI (match_dup 1)
(neg:QI (match_dup 2))))
(clobber (reg:CC VAX_PSL_REGNUM))])]
"")
(define_insn "*ashlnegdi3_2"
[(set (match_operand:DI 0 "nonimmediate_operand" "=g")
(ashiftrt:DI (match_operand:DI 1 "general_operand" "g")
(neg:QI (match_operand:QI 2 "general_operand" "g"))))
(clobber (reg:CC VAX_PSL_REGNUM))]
"reload_completed"
"ashq %2,%D1,%0")
;; We used to have expand_shift handle logical right shifts by using extzv,
;; but this make it very difficult to do lshrdi3. Since the VAX is the
;; only machine with this kludge, it's better to just do this with a
;; define_expand and remove that case from expand_shift.
(define_expand "lshrsi3"
[(set (match_dup 3)
(minus:QI (const_int 32)
(match_dup 4)))
(set (match_operand:SI 0 "nonimmediate_operand" "=g")
(zero_extract:SI (match_operand:SI 1 "register_operand" "r")
(match_dup 3)
(match_operand:SI 2 "register_operand" "g")))]
""
"
{
operands[3] = gen_reg_rtx (QImode);
operands[4] = gen_lowpart (QImode, operands[2]);
}")
;; 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 (! CONST_INT_P (operands[2]))
operands[2] = gen_rtx_NEG (QImode, negate_rtx (QImode, operands[2]));
}")
(define_insn_and_split "rotlsi3"
[(set (match_operand:SI 0 "nonimmediate_operand" "=g")
(rotate:SI (match_operand:SI 1 "general_operand" "nrmT")
(match_operand:QI 2 "general_operand" "g")))]
""
"#"
"reload_completed"
[(parallel
[(set (match_dup 0)
(rotate:SI (match_dup 1)
(match_dup 2)))
(clobber (reg:CC VAX_PSL_REGNUM))])]
"")
(define_insn "*rotlsi3"
[(set (match_operand:SI 0 "nonimmediate_operand" "=g")
(rotate:SI (match_operand:SI 1 "general_operand" "nrmT")
(match_operand:QI 2 "general_operand" "g")))
(clobber (reg:CC VAX_PSL_REGNUM))]
"reload_completed"
"rotl %2,%1,%0")
(define_insn_and_split "*rotrsi3_const_int"
[(set (match_operand:SI 0 "nonimmediate_operand" "=g")
(rotatert:SI (match_operand:SI 1 "general_operand" "nrmT")
(match_operand:QI 2 "const_int_operand" "n")))]
""
"#"
"reload_completed"
[(parallel
[(set (match_dup 0)
(rotatert:SI (match_dup 1)
(match_dup 2)))
(clobber (reg:CC VAX_PSL_REGNUM))])]
"")
(define_insn "*rotrsi3_const_int_2"
[(set (match_operand:SI 0 "nonimmediate_operand" "=g")
(rotatert:SI (match_operand:SI 1 "general_operand" "nrmT")
(match_operand:QI 2 "const_int_operand" "n")))
(clobber (reg:CC VAX_PSL_REGNUM))]
"reload_completed"
"rotl %R2,%1,%0")
(define_insn_and_split "*rotrnegsi3"
[(set (match_operand:SI 0 "nonimmediate_operand" "=g")
(rotatert:SI (match_operand:SI 1 "general_operand" "nrmT")
(neg:QI (match_operand:QI 2 "general_operand" "g"))))]
""
"#"
"reload_completed"
[(parallel
[(set (match_dup 0)
(rotatert:SI (match_dup 1)
(neg:QI (match_dup 2))))
(clobber (reg:CC VAX_PSL_REGNUM))])]
"")
(define_insn "*rotrnegsi3_2"
[(set (match_operand:SI 0 "nonimmediate_operand" "=g")
(rotatert:SI (match_operand:SI 1 "general_operand" "nrmT")
(neg:QI (match_operand:QI 2 "general_operand" "g"))))
(clobber (reg:CC VAX_PSL_REGNUM))]
"reload_completed"
"rotl %2,%1,%0")
;; This insn is probably slower than a multiply and an add.
;;(define_insn_and_split "*amulsi4"
;; [(set (match_operand:SI 0 "nonimmediate_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")))]
;; ""
;; "#"
;; "reload_completed"
;; [(parallel
;; [(set (match_dup 0)
;; (mult:SI (plus:SI (match_dup 1)
;; (match_dup 2))
;; (match_dup 3)))
;; (clobber (reg:CC VAX_PSL_REGNUM))])]
;; "")
;;
;;(define_insn "*amulsi4_2