NetBSD/gnu/dist/gcc/config/convex/convex.md

1886 lines
54 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

;;- Machine description for GNU compiler, Convex Version
;; Copyright (C) 1988, 1994, 1995 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, 59 Temple Place - Suite 330,
;; Boston, MA 02111-1307, USA.
;; Attribute specifications
; Target CPU
(define_attr "cpu" "c1,c32,c34,c38"
(const (symbol_ref "(enum attr_cpu) target_cpu")))
;; Instruction classification
(define_attr "type"
"alu,xalu,mldw,mldl,mldb,mst,adds,addd,mulw,mull,muls,muld,divw,divl,divs,divd,shfw,shfl,cvts,cvtd"
(const_string "alu"))
;; Instruction times
(define_function_unit "mem" 1 0
(and (eq_attr "cpu" "c1") (eq_attr "type" "mldw")) 2 0)
(define_function_unit "mem" 1 0
(and (eq_attr "cpu" "c1") (eq_attr "type" "mldl")) 4 0)
(define_function_unit "mem" 1 0
(and (eq_attr "cpu" "c32") (eq_attr "type" "mldw,mldl")) 2 0)
(define_function_unit "mem" 1 0
(and (eq_attr "cpu" "c34") (eq_attr "type" "mldw,mldl")) 4 0)
(define_function_unit "mem" 1 0
(and (eq_attr "cpu" "c38") (eq_attr "type" "mldw,mldl")) 2 0)
(define_function_unit "mem" 1 0
(and (eq_attr "cpu" "c32") (eq_attr "type" "mldb")) 9 0)
(define_function_unit "mem" 1 0
(and (eq_attr "cpu" "c34") (eq_attr "type" "mldb")) 36 0)
(define_function_unit "mem" 1 0
(and (eq_attr "cpu" "c38") (eq_attr "type" "mldb")) 21 0)
(define_function_unit "mem" 1 0
(and (eq_attr "cpu" "c1") (eq_attr "type" "xalu")) 1 0)
(define_function_unit "mem" 1 0
(and (eq_attr "cpu" "c32") (eq_attr "type" "xalu")) 1 0)
(define_function_unit "mem" 1 0
(and (eq_attr "cpu" "c34") (eq_attr "type" "xalu")) 5 0)
(define_function_unit "mem" 1 0
(and (eq_attr "cpu" "c38") (eq_attr "type" "xalu")) 2 0)
(define_function_unit "add" 1 0
(and (eq_attr "cpu" "c1") (eq_attr "type" "adds,addd")) 3 2)
(define_function_unit "add" 1 0
(and (eq_attr "cpu" "c32") (eq_attr "type" "adds,addd")) 2 1)
(define_function_unit "add" 1 0
(and (eq_attr "cpu" "c34") (eq_attr "type" "adds,addd")) 5 2)
(define_function_unit "add" 1 0
(and (eq_attr "cpu" "c38") (eq_attr "type" "adds,addd")) 2 1)
(define_function_unit "mul" 1 0
(and (eq_attr "cpu" "c1") (eq_attr "type" "mulw,muls")) 3 2)
(define_function_unit "mul" 1 0
(and (eq_attr "cpu" "c32") (eq_attr "type" "mulw,muls")) 4 2)
(define_function_unit "mul" 1 0
(and (eq_attr "cpu" "c34") (eq_attr "type" "mulw,muls")) 6 2)
(define_function_unit "mul" 1 0
(and (eq_attr "cpu" "c38") (eq_attr "type" "mulw,muls")) 3 2)
(define_function_unit "mul" 1 0
(and (eq_attr "cpu" "c1") (eq_attr "type" "mull,muld")) 4 3)
(define_function_unit "mul" 1 0
(and (eq_attr "cpu" "c32") (eq_attr "type" "mull")) 10 7)
(define_function_unit "mul" 1 0
(and (eq_attr "cpu" "c32") (eq_attr "type" "muld")) 5 2)
(define_function_unit "mul" 1 0
(and (eq_attr "cpu" "c34") (eq_attr "type" "mull,muld")) 7 3)
(define_function_unit "mul" 1 0
(and (eq_attr "cpu" "c38") (eq_attr "type" "mull,muld")) 4 3)
(define_function_unit "div" 1 0
(and (eq_attr "cpu" "c1") (eq_attr "type" "divw")) 24 24)
(define_function_unit "div" 1 0
(and (eq_attr "cpu" "c32") (eq_attr "type" "divw")) 44 6)
(define_function_unit "div" 1 0
(and (eq_attr "cpu" "c34") (eq_attr "type" "divw")) 14 10)
(define_function_unit "div" 1 0
(and (eq_attr "cpu" "c38") (eq_attr "type" "divw")) 11 10)
(define_function_unit "div" 1 0
(and (eq_attr "cpu" "c1") (eq_attr "type" "divl")) 41 42)
(define_function_unit "div" 1 0
(and (eq_attr "cpu" "c32") (eq_attr "type" "divl")) 76 5)
(define_function_unit "div" 1 0
(and (eq_attr "cpu" "c34") (eq_attr "type" "divl")) 22 18)
(define_function_unit "div" 1 0
(and (eq_attr "cpu" "c38") (eq_attr "type" "divl")) 19 18)
(define_function_unit "div" 1 0
(and (eq_attr "cpu" "c1") (eq_attr "type" "divs")) 22 22)
(define_function_unit "div" 1 0
(and (eq_attr "cpu" "c32") (eq_attr "type" "divs")) 8 6)
(define_function_unit "div" 1 0
(and (eq_attr "cpu" "c34") (eq_attr "type" "divs")) 13 9)
(define_function_unit "div" 1 0
(and (eq_attr "cpu" "c38") (eq_attr "type" "divs")) 10 9)
(define_function_unit "div" 1 0
(and (eq_attr "cpu" "c1") (eq_attr "type" "divd")) 37 38)
(define_function_unit "div" 1 0
(and (eq_attr "cpu" "c32") (eq_attr "type" "divd")) 12 8)
(define_function_unit "div" 1 0
(and (eq_attr "cpu" "c34") (eq_attr "type" "divd")) 20 16)
(define_function_unit "div" 1 0
(and (eq_attr "cpu" "c38") (eq_attr "type" "divd")) 17 16)
(define_function_unit "misc" 1 0
(and (eq_attr "cpu" "c1") (eq_attr "type" "cvts,cvtd")) 4 3)
(define_function_unit "misc" 1 0
(and (eq_attr "cpu" "c32") (eq_attr "type" "cvts")) 9 7)
(define_function_unit "misc" 1 0
(and (eq_attr "cpu" "c32") (eq_attr "type" "cvtd")) 9 6)
(define_function_unit "misc" 1 0
(and (eq_attr "cpu" "c34") (eq_attr "type" "cvts")) 6 2)
(define_function_unit "misc" 1 0
(and (eq_attr "cpu" "c34") (eq_attr "type" "cvtd")) 6 1)
(define_function_unit "misc" 1 0
(and (eq_attr "cpu" "c38") (eq_attr "type" "cvts,cvtd")) 3 1)
(define_function_unit "misc" 1 0
(and (eq_attr "cpu" "c1") (eq_attr "type" "shfw,shfl")) 3 2)
(define_function_unit "misc" 1 0
(and (eq_attr "cpu" "c32") (eq_attr "type" "shfw")) 7 5)
(define_function_unit "misc" 1 0
(and (eq_attr "cpu" "c32") (eq_attr "type" "shfl")) 7 4)
(define_function_unit "misc" 1 0
(and (eq_attr "cpu" "c38") (eq_attr "type" "shfw,shfl")) 3 1)
(define_function_unit "mystery_latch" 1 1
(and (eq_attr "type" "!alu,mldw,mldl,adds,addd") (eq_attr "cpu" "c32")) 2 2)
;(define_function_unit "ip" 1 1
; (and (eq_attr "cpu" "c1")
; (eq_attr "type" "divw,divl,divs,divd,xalu")) 2 2)
;(define_function_unit "ip" 1 1
; (and (eq_attr "cpu" "c1")
; (eq_attr "type" "!divw,divl,divs,divd,xalu")) 1 1)
;(define_function_unit "ip" 1 1
; (and (eq_attr "cpu" "c32")
; (eq_attr "type" "mull,muld,divl,divd,shfl,cvtd,xalu")) 2 2)
;(define_function_unit "ip" 1 1
; (and (eq_attr "cpu" "c32")
; (eq_attr "type" "!mull,muld,divl,divd,shfl,cvtd,xalu")) 1 1)
;(define_function_unit "ip" 1 1
; (and (eq_attr "cpu" "c34")
; (eq_attr "type" "addd,mull,muld,divl,divd,cvtd,xalu")) 2 2)
;(define_function_unit "ip" 1 1
; (and (eq_attr "cpu" "c34")
; (eq_attr "type" "!addd,mull,muld,divl,divd,cvtd,xalu")) 1 1)
;; Make the first thing a real insn in case of genattrtab bug
(define_insn "nop"
[(const_int 0)]
""
"nop")
;; Moves
(define_expand "movdf"
[(set (match_operand:DF 0 "general_operand" "")
(match_operand:DF 1 "general_operand" ""))]
""
"if (GET_CODE (operands[0]) != REG)
operands[1] = force_reg (DFmode, operands[1]);")
(define_insn ""
[(set (match_operand:DF 0 "general_operand" "=d,d,d,d,d,<,m")
(match_operand:DF 1 "general_operand" "d,Q,m,G,H,d,d"))]
"register_operand (operands[0], DFmode)
|| register_operand (operands[1], DFmode)"
"@
mov %1,%0
ldb.d %1,%0
ld.d %1,%0
ld.d %u1,%0
ld.l %v1,%0
psh.l %1
st.d %1,%0"
[(set_attr "type" "alu,mldb,mldl,alu,alu,alu,mst")])
;; This is here so we can load any result of RTL constant folding
;; but do not use it on constants that can be loaded from memory.
;; It is never better and can be worse.
(define_insn ""
[(set (match_operand:DF 0 "register_operand" "=d")
(match_operand:DF 1 "const_double_operand" "F"))]
"CONST_DOUBLE_MEM (operands[1]) == const0_rtx"
"ld.u %u1,%0\;ld.w %v1,%0"
[(set_attr "type" "xalu")])
(define_expand "movsf"
[(set (match_operand:SF 0 "general_operand" "")
(match_operand:SF 1 "general_operand" ""))]
""
"if (GET_CODE (operands[0]) != REG)
operands[1] = force_reg (SFmode, operands[1]);")
(define_insn ""
[(set (match_operand:SF 0 "general_operand" "=d,d,d,d,<,m")
(match_operand:SF 1 "general_operand" "d,Q,m,F,d,d"))]
"register_operand (operands[0], SFmode)
|| register_operand (operands[1], SFmode)"
"@
mov.s %1,%0
ldb.s %1,%0
ld.s %1,%0
ld.s %1,%0
psh.w %1
st.s %1,%0"
[(set_attr "type" "alu,mldb,mldw,alu,alu,mst")])
(define_expand "movdi"
[(set (match_operand:DI 0 "general_operand" "")
(match_operand:DI 1 "general_operand" ""))]
""
"if (GET_CODE (operands[0]) != REG)
operands[1] = force_reg (DImode, operands[1]);")
(define_insn ""
[(set (match_operand:DI 0 "general_operand" "=d,d,d,d,d,<,m")
(match_operand:DI 1 "general_operand" "d,Q,m,G,HI,d,d"))]
"register_operand (operands[0], DImode)
|| register_operand (operands[1], DImode)"
"@
mov %1,%0
ldb.l %1,%0
ld.l %1,%0
ld.d %u1,%0
ld.l %1,%0
psh.l %1
st.l %1,%0"
[(set_attr "type" "alu,mldb,mldl,alu,alu,alu,mst")])
;; This is here so we can load any result of RTL constant folding
;; but do not use it on constants that can be loaded from memory.
;; It is never better and can be worse.
(define_insn ""
[(set (match_operand:DI 0 "register_operand" "=d")
(match_operand:DI 1 "const_double_operand" "F"))]
"CONST_DOUBLE_MEM (operands[1]) == const0_rtx"
"ld.u %u1,%0\;ld.w %v1,%0"
[(set_attr "type" "xalu")])
(define_expand "movsi"
[(set (match_operand:SI 0 "general_operand" "")
(match_operand:SI 1 "general_operand" ""))]
""
"if (GET_CODE (operands[0]) != REG)
operands[1] = force_reg (SImode, operands[1]);")
(define_insn ""
[(set (match_operand:SI 0 "push_operand" "=<,<")
(match_operand:SI 1 "nonmemory_operand" "Ad,i"))]
""
"@
psh.w %1
pshea %a1")
(define_insn ""
[(set (match_operand:SI 0 "general_operand" "=d,r,d,r,r,m")
(match_operand:SI 1 "general_operand" "d,r,Q,m,i,r"))]
"register_operand (operands[0], SImode)
|| register_operand (operands[1], SImode)"
"@
mov.w %1,%0
mov %1,%0
ldb.w %1,%0
ld.w %1,%0
ld.w %1,%0
st.w %1,%0"
[(set_attr "type" "alu,alu,mldb,mldw,alu,mst")])
(define_expand "movstrictsi"
[(set (strict_low_part (match_operand:SI 0 "general_operand" ""))
(match_operand:SI 1 "general_operand" ""))]
""
"if (GET_CODE (operands[0]) != REG)
operands[1] = force_reg (SImode, operands[1]);")
(define_insn ""
[(set (strict_low_part (match_operand:SI 0 "general_operand" "=d,r,d,r,r,m"))
(match_operand:SI 1 "general_operand" "d,r,Q,m,i,r"))]
"register_operand (operands[0], SImode)
|| register_operand (operands[1], SImode)"
"@
mov.w %1,%0
mov %1,%0
ldb.w %1,%0
ld.w %1,%0
ld.w %1,%0
st.w %1,%0"
[(set_attr "type" "alu,alu,mldb,mldw,alu,mst")])
(define_expand "movhi"
[(set (match_operand:HI 0 "general_operand" "")
(match_operand:HI 1 "general_operand" ""))]
""
"if (GET_CODE (operands[0]) != REG)
operands[1] = force_reg (HImode, operands[1]);")
(define_insn ""
[(set (match_operand:HI 0 "general_operand" "=d,r,d,r,r,<,m")
(match_operand:HI 1 "general_operand" "d,r,Q,m,i,Ad,r"))]
"register_operand (operands[0], HImode)
|| register_operand (operands[1], HImode)"
"@
mov.w %1,%0
mov %1,%0
ldb.h %1,%0
ld.h %1,%0
ld.w %1,%0
psh.w %1
st.h %1,%0"
[(set_attr "type" "alu,alu,mldb,mldw,alu,alu,mst")])
(define_expand "movqi"
[(set (match_operand:QI 0 "general_operand" "")
(match_operand:QI 1 "general_operand" ""))]
""
"if (GET_CODE (operands[0]) != REG)
operands[1] = force_reg (QImode, operands[1]);")
(define_insn ""
[(set (match_operand:QI 0 "general_operand" "=d,r,d,r,r,<,m")
(match_operand:QI 1 "general_operand" "d,r,Q,m,i,Ad,r"))]
"register_operand (operands[0], QImode)
|| register_operand (operands[1], QImode)"
"@
mov.w %1,%0
mov %1,%0
ldb.b %1,%0
ld.b %1,%0
ld.w %1,%0
psh.w %1
st.b %1,%0"
[(set_attr "type" "alu,alu,mldb,mldw,alu,alu,mst")])
;; Expand block moves manually to get code that pipelines the loads.
(define_expand "movstrsi"
[(set (match_operand:BLK 0 "memory_operand" "=m")
(match_operand:BLK 1 "memory_operand" "m"))
(use (match_operand:SI 2 "const_int_operand" "i"))
(use (match_operand:SI 3 "const_int_operand" "i"))]
""
" expand_movstr (operands); DONE; ")
;; Extension and truncation insns.
;; Those for integer source operand
;; are ordered widest source type first.
(define_insn "truncsiqi2"
[(set (match_operand:QI 0 "register_operand" "=d,a")
(truncate:QI (match_operand:SI 1 "register_operand" "d,a")))]
""
"cvtw.b %1,%0")
(define_insn "truncsihi2"
[(set (match_operand:HI 0 "register_operand" "=d,a")
(truncate:HI (match_operand:SI 1 "register_operand" "d,a")))]
""
"cvtw.h %1,%0")
(define_insn "trunchiqi2"
[(set (match_operand:QI 0 "register_operand" "=r")
(truncate:QI (match_operand:HI 1 "register_operand" "0")))]
""
"")
(define_insn "truncdisi2"
[(set (match_operand:SI 0 "register_operand" "=d")
(truncate:SI (match_operand:DI 1 "register_operand" "d")))]
""
"cvtl.w %1,%0")
(define_insn "extendsidi2"
[(set (match_operand:DI 0 "register_operand" "=d")
(sign_extend:DI (match_operand:SI 1 "register_operand" "d")))]
""
"cvtw.l %1,%0")
(define_insn "extendhisi2"
[(set (match_operand:SI 0 "register_operand" "=d,a")
(sign_extend:SI (match_operand:HI 1 "register_operand" "d,a")))]
""
"cvth.w %1,%0")
(define_insn "extendqihi2"
[(set (match_operand:HI 0 "register_operand" "=d,a")
(sign_extend:HI (match_operand:QI 1 "register_operand" "d,a")))]
""
"cvtb.w %1,%0")
(define_insn "extendqisi2"
[(set (match_operand:SI 0 "register_operand" "=d,a")
(sign_extend:SI (match_operand:QI 1 "register_operand" "d,a")))]
""
"cvtb.w %1,%0")
(define_insn "extendsfdf2"
[(set (match_operand:DF 0 "register_operand" "=d")
(float_extend:DF (match_operand:SF 1 "register_operand" "d")))]
""
"cvts.d %1,%0"
[(set_attr "type" "cvts")])
(define_insn "truncdfsf2"
[(set (match_operand:SF 0 "register_operand" "=d")
(float_truncate:SF (match_operand:DF 1 "register_operand" "d")))]
""
"cvtd.s %1,%0"
[(set_attr "type" "cvtd")])
(define_insn "zero_extendhisi2"
[(set (match_operand:SI 0 "register_operand" "=r")
(zero_extend:SI (match_operand:HI 1 "register_operand" "0")))]
""
"and #0xffff,%0")
(define_insn "zero_extendqihi2"
[(set (match_operand:HI 0 "register_operand" "=r")
(zero_extend:HI (match_operand:QI 1 "register_operand" "0")))]
""
"and #0xff,%0")
(define_insn "zero_extendqisi2"
[(set (match_operand:SI 0 "register_operand" "=r")
(zero_extend:SI (match_operand:QI 1 "register_operand" "0")))]
""
"and #0xff,%0")
(define_insn "zero_extendsidi2"
[(set (match_operand:DI 0 "register_operand" "=d")
(zero_extend:DI (match_operand:SI 1 "register_operand" "0")))]
""
"ld.u #0,%0")
;; Fix-to-float conversion insns.
;; Note that the ones that start with SImode come first.
;; That is so that an operand that is a CONST_INT
;; (and therefore lacks a specific machine mode).
;; will be recognized as SImode (which is always valid)
;; rather than as QImode or HImode.
(define_insn "floatsisf2"
[(set (match_operand:SF 0 "register_operand" "=d")
(float:SF (match_operand:SI 1 "register_operand" "d")))]
""
"cvtw.s %1,%0"
[(set_attr "type" "cvts")])
(define_insn "floatdisf2"
[(set (match_operand:SF 0 "register_operand" "=d")
(float:SF (match_operand:DI 1 "register_operand" "d")))]
""
"cvtl.s %1,%0"
[(set_attr "type" "cvtd")])
(define_insn "floatsidf2"
[(set (match_operand:DF 0 "register_operand" "=d")
(float:DF (match_operand:SI 1 "register_operand" "d")))]
"! TARGET_C1"
"cvtw.d %1,%0"
[(set_attr "type" "cvts")])
(define_insn "floatdidf2"
[(set (match_operand:DF 0 "register_operand" "=d")
(float:DF (match_operand:DI 1 "register_operand" "d")))]
""
"cvtl.d %1,%0"
[(set_attr "type" "cvtd")])
;; These are a little slower than gcc's normal way of doing unsigned
;; DI floats (if the DI number is "negative") but they avoid double
;; rounding and they avoid explicit constants.
(define_expand "floatunsdidf2"
[(set (match_operand:DF 0 "register_operand" "=d")
(float:DF (match_operand:DI 1 "register_operand" "d")))
(set (cc0) (compare:DI (match_dup 3) (match_dup 1)))
(set (pc)
(if_then_else (le (cc0) (const_int 0))
(label_ref (match_dup 4))
(pc)))
(set (match_dup 2) (lshiftrt:DI (match_dup 1) (const_int 1)))
(set (match_dup 0) (float:DF (match_dup 2)))
(set (match_dup 0) (plus:DF (match_dup 0) (match_dup 0)))
(match_dup 4)
(set (match_dup 0) (match_dup 0))]
""
"
{
operands[2] = gen_reg_rtx (DImode);
operands[3] = force_reg (DImode, const0_rtx);
operands[4] = gen_label_rtx ();
}")
(define_expand "floatunsdisf2"
[(set (match_operand:SF 0 "register_operand" "=d")
(float:SF (match_operand:DI 1 "register_operand" "d")))
(set (cc0) (compare:DI (match_dup 3) (match_dup 1)))
(set (pc)
(if_then_else (le (cc0) (const_int 0))
(label_ref (match_dup 4))
(pc)))
(set (match_dup 2) (lshiftrt:DI (match_dup 1) (const_int 1)))
(set (match_dup 0) (float:SF (match_dup 2)))
(set (match_dup 0) (plus:SF (match_dup 0) (match_dup 0)))
(match_dup 4)
(set (match_dup 0) (match_dup 0))]
""
"
{
operands[2] = gen_reg_rtx (DImode);
operands[3] = force_reg (DImode, const0_rtx);
operands[4] = gen_label_rtx ();
}")
;; These patterns are identical to gcc's default action
;; if DI->DF and DI->SF are not present. There are here
;; only to prevent SI->*F from promoting to DI->*F.
(define_expand "floatunssidf2"
[(set (match_dup 2)
(zero_extend:DI (match_operand:SI 1 "register_operand" "")))
(set (match_operand:DF 0 "register_operand" "")
(float:DF (match_dup 2)))]
""
"operands[2] = gen_reg_rtx (DImode);")
(define_expand "floatunssisf2"
[(set (match_dup 2)
(zero_extend:DI (match_operand:SI 1 "register_operand" "")))
(set (match_operand:SF 0 "register_operand" "")
(float:SF (match_dup 2)))]
""
"operands[2] = gen_reg_rtx (DImode);")
;; Float-to-fix conversion insns.
(define_insn "fix_truncsfsi2"
[(set (match_operand:SI 0 "register_operand" "=d")
(fix:SI (fix:SF (match_operand:SF 1 "register_operand" "d"))))]
""
"cvts.w %1,%0"
[(set_attr "type" "cvts")])
(define_insn "fix_truncsfdi2"
[(set (match_operand:DI 0 "register_operand" "=d")
(fix:DI (fix:SF (match_operand:SF 1 "register_operand" "d"))))]
""
"cvts.l %1,%0"
[(set_attr "type" "cvts")])
(define_insn "fix_truncdfsi2"
[(set (match_operand:SI 0 "register_operand" "=d")
(fix:SI (fix:DF (match_operand:DF 1 "register_operand" "d"))))]
""
"cvtd.l %1,%0"
[(set_attr "type" "cvtd")])
(define_insn "fix_truncdfdi2"
[(set (match_operand:DI 0 "register_operand" "=d")
(fix:DI (fix:DF (match_operand:DF 1 "register_operand" "d"))))]
""
"cvtd.l %1,%0"
[(set_attr "type" "cvtd")])
;;- All kinds of add instructions.
(define_insn "adddf3"
[(set (match_operand:DF 0 "register_operand" "=d")
(plus:DF (match_operand:DF 1 "register_operand" "%0")
(match_operand:DF 2 "register_operand" "d")))]
""
"add.d %2,%0"
[(set_attr "type" "addd")])
(define_insn "addsf3"
[(set (match_operand:SF 0 "register_operand" "=d")
(plus:SF (match_operand:SF 1 "register_operand" "%0")
(match_operand:SF 2 "nonmemory_operand" "dF")))]
""
"add.s %2,%0"
[(set_attr "type" "adds")])
(define_insn "adddi3"
[(set (match_operand:DI 0 "register_operand" "=d")
(plus:DI (match_operand:DI 1 "register_operand" "%0")
(match_operand:DI 2 "register_operand" "d")))]
""
"add.l %2,%0")
(define_expand "addsi3"
[(set (match_operand:SI 0 "register_operand" "")
(plus:SI (match_operand:SI 1 "register_operand" "")
(match_operand:SI 2 "nonmemory_operand" "")))]
""
"")
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=a")
(plus:SI (match_operand:SI 1 "register_operand" "%A")
(match_operand:SI 2 "immediate_operand" "i")))]
"operands[1] == frame_pointer_rtx || operands[1] == arg_pointer_rtx"
"ldea %a2(%1),%0")
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=a")
(plus:SI (match_operand:SI 1 "register_operand" "%a")
(match_operand:SI 2 "nonmemory_operand" "ri")))]
"operands[1] == stack_pointer_rtx && operands[0] != stack_pointer_rtx"
"mov %1,%0\;add.w %2,%0")
(define_insn ""
[(set (match_operand:SI 0 "push_operand" "=<")
(plus:SI (match_operand:SI 1 "register_operand" "A")
(match_operand:SI 2 "immediate_operand" "i")))]
"operands[1] != stack_pointer_rtx"
"pshea %a2(%1)"
[(set_attr "type" "mst")])
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=d,a,a")
(plus:SI (match_operand:SI 1 "register_operand" "%0,0,A")
(match_operand:SI 2 "nonmemory_operand" "di,ri,i")))]
"TARGET_C1"
"@
add.w %2,%0
add.w %2,%0
ldea %a2(%1),%0")
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=d,a,r")
(plus:SI (match_operand:SI 1 "register_operand" "%0,0,A")
(match_operand:SI 2 "nonmemory_operand" "di,ri,i")))]
""
"@
add.w %2,%0
add.w %2,%0
ldea %a2(%1),%0")
(define_insn "addhi3"
[(set (match_operand:HI 0 "register_operand" "=d,a")
(plus:HI (match_operand:HI 1 "register_operand" "%0,0")
(match_operand:HI 2 "nonmemory_operand" "di,ai")))]
""
"add.h %2,%0")
(define_insn "addqi3"
[(set (match_operand:QI 0 "register_operand" "=d,d")
(plus:QI (match_operand:QI 1 "register_operand" "%0,0")
(match_operand:QI 2 "nonmemory_operand" "d,i")))]
""
"@
add.b %2,%0
add.w %2,%0")
;;- All kinds of subtract instructions.
(define_insn "subdf3"
[(set (match_operand:DF 0 "register_operand" "=d")
(minus:DF (match_operand:DF 1 "register_operand" "0")
(match_operand:DF 2 "register_operand" "d")))]
""
"sub.d %2,%0"
[(set_attr "type" "addd")])
(define_insn "subsf3"
[(set (match_operand:SF 0 "register_operand" "=d")
(minus:SF (match_operand:SF 1 "register_operand" "0")
(match_operand:SF 2 "nonmemory_operand" "dF")))]
""
"sub.s %2,%0"
[(set_attr "type" "adds")])
(define_insn "subdi3"
[(set (match_operand:DI 0 "register_operand" "=d")
(minus:DI (match_operand:DI 1 "register_operand" "0")
(match_operand:DI 2 "register_operand" "d")))]
""
"sub.l %2,%0")
(define_insn "subsi3"
[(set (match_operand:SI 0 "register_operand" "=d,a,?d,?a")
(minus:SI (match_operand:SI 1 "nonmemory_operand" "0,0,di,ai")
(match_operand:SI 2 "nonmemory_operand" "di,ai,0,0")))]
""
"@
sub.w %2,%0
sub.w %2,%0
sub.w %1,%0\;neg.w %0,%0
sub.w %1,%0\;neg.w %0,%0")
(define_insn "subhi3"
[(set (match_operand:HI 0 "register_operand" "=d,a")
(minus:HI (match_operand:HI 1 "register_operand" "0,0")
(match_operand:HI 2 "nonmemory_operand" "di,ai")))]
""
"sub.h %2,%0")
(define_insn "subqi3"
[(set (match_operand:QI 0 "register_operand" "=d,d")
(minus:QI (match_operand:QI 1 "register_operand" "0,0")
(match_operand:QI 2 "nonmemory_operand" "d,i")))]
""
"@
sub.b %2,%0
sub.w %2,%0")
;;- Multiply instructions.
(define_insn "muldf3"
[(set (match_operand:DF 0 "register_operand" "=d")
(mult:DF (match_operand:DF 1 "register_operand" "%0")
(match_operand:DF 2 "register_operand" "d")))]
""
"mul.d %2,%0"
[(set_attr "type" "muld")])
(define_insn "mulsf3"
[(set (match_operand:SF 0 "register_operand" "=d")
(mult:SF (match_operand:SF 1 "register_operand" "%0")
(match_operand:SF 2 "nonmemory_operand" "dF")))]
""
"mul.s %2,%0"
[(set_attr "type" "muls")])
(define_insn "muldi3"
[(set (match_operand:DI 0 "register_operand" "=d")
(mult:DI (match_operand:DI 1 "register_operand" "%0")
(match_operand:DI 2 "register_operand" "d")))]
""
"mul.l %2,%0"
[(set_attr "type" "mull")])
(define_insn "mulsi3"
[(set (match_operand:SI 0 "register_operand" "=d,a")
(mult:SI (match_operand:SI 1 "register_operand" "%0,0")
(match_operand:SI 2 "nonmemory_operand" "di,ai")))]
""
"mul.w %2,%0"
[(set_attr "type" "mulw")])
(define_insn "mulhi3"
[(set (match_operand:HI 0 "register_operand" "=d,a")
(mult:HI (match_operand:HI 1 "register_operand" "%0,0")
(match_operand:HI 2 "nonmemory_operand" "di,ai")))]
""
"mul.h %2,%0"
[(set_attr "type" "mulw")])
(define_insn "mulqi3"
[(set (match_operand:QI 0 "register_operand" "=d,d")
(mult:QI (match_operand:QI 1 "register_operand" "%0,0")
(match_operand:QI 2 "nonmemory_operand" "d,i")))]
""
"@
mul.b %2,%0
mul.w %2,%0"
[(set_attr "type" "mulw,mulw")])
;;- Divide instructions.
(define_insn "divdf3"
[(set (match_operand:DF 0 "register_operand" "=d")
(div:DF (match_operand:DF 1 "register_operand" "0")
(match_operand:DF 2 "register_operand" "d")))]
""
"div.d %2,%0"
[(set_attr "type" "divd")])
(define_insn "divsf3"
[(set (match_operand:SF 0 "register_operand" "=d")
(div:SF (match_operand:SF 1 "register_operand" "0")
(match_operand:SF 2 "nonmemory_operand" "dF")))]
""
"div.s %2,%0"
[(set_attr "type" "divs")])
(define_insn "divdi3"
[(set (match_operand:DI 0 "register_operand" "=d")
(div:DI (match_operand:DI 1 "register_operand" "0")
(match_operand:DI 2 "register_operand" "d")))]
""
"div.l %2,%0"
[(set_attr "type" "divl")])
(define_expand "udivsi3"
[(set (match_dup 3)
(zero_extend:DI (match_operand:SI 1 "register_operand" "")))
(set (match_dup 4)
(zero_extend:DI (match_operand:SI 2 "register_operand" "")))
(set (match_dup 3)
(div:DI (match_dup 3) (match_dup 4)))
(set (match_operand:SI 0 "register_operand" "")
(subreg:SI (match_dup 3) 0))]
""
"operands[3] = gen_reg_rtx (DImode);
operands[4] = gen_reg_rtx (DImode); ")
(define_insn "udivdi3"
[(set (match_operand:DI 0 "register_operand" "=d")
(udiv:DI (match_operand:DI 1 "register_operand" "d")
(match_operand:DI 2 "register_operand" "d")))]
""
"psh.l %2\;psh.l %1\;callq udiv64\;pop.l %0\;add.w #8,sp")
(define_insn "divsi3"
[(set (match_operand:SI 0 "register_operand" "=d,a")
(div:SI (match_operand:SI 1 "register_operand" "0,0")
(match_operand:SI 2 "nonmemory_operand" "di,ai")))]
""
"div.w %2,%0"
[(set_attr "type" "divw")])
(define_insn "divhi3"
[(set (match_operand:HI 0 "register_operand" "=d,a")
(div:HI (match_operand:HI 1 "register_operand" "0,0")
(match_operand:HI 2 "nonmemory_operand" "di,ai")))]
""
"div.h %2,%0"
[(set_attr "type" "divw")])
(define_insn "divqi3"
[(set (match_operand:QI 0 "register_operand" "=d")
(div:QI (match_operand:QI 1 "register_operand" "0")
(match_operand:QI 2 "register_operand" "d")))]
""
"div.b %2,%0"
[(set_attr "type" "divw")])
;;- Bit clear instructions.
(define_insn ""
[(set (match_operand:DI 0 "register_operand" "=d")
(and:DI (match_operand:DI 1 "register_operand" "%0")
(match_operand:DI 2 "" "")))]
"(GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0)
|| (GET_CODE (operands[2]) == CONST_DOUBLE
&& CONST_DOUBLE_HIGH (operands[2]) == -1)"
"and %2,%0")
(define_insn "anddi3"
[(set (match_operand:DI 0 "register_operand" "=d")
(and:DI (match_operand:DI 1 "register_operand" "%0")
(match_operand:DI 2 "register_operand" "d")))]
""
"and %2,%0")
(define_insn "andsi3"
[(set (match_operand:SI 0 "register_operand" "=d,a")
(and:SI (match_operand:SI 1 "register_operand" "%0,0")
(match_operand:SI 2 "nonmemory_operand" "di,ai")))]
""
"and %2,%0")
(define_insn "andhi3"
[(set (match_operand:HI 0 "register_operand" "=d,a")
(and:HI (match_operand:HI 1 "register_operand" "%0,0")
(match_operand:HI 2 "nonmemory_operand" "di,ai")))]
""
"and %2,%0")
(define_insn "andqi3"
[(set (match_operand:QI 0 "register_operand" "=d,a")
(and:QI (match_operand:QI 1 "register_operand" "%0,0")
(match_operand:QI 2 "nonmemory_operand" "di,ai")))]
""
"and %2,%0")
;;- Bit set instructions.
(define_insn ""
[(set (match_operand:DI 0 "register_operand" "=d")
(ior:DI (match_operand:DI 1 "register_operand" "%0")
(match_operand:DI 2 "" "")))]
"(GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 0)
|| (GET_CODE (operands[2]) == CONST_DOUBLE
&& CONST_DOUBLE_HIGH (operands[2]) == 0)"
"or %2,%0")
(define_insn "iordi3"
[(set (match_operand:DI 0 "register_operand" "=d")
(ior:DI (match_operand:DI 1 "register_operand" "%0")
(match_operand:DI 2 "register_operand" "d")))]
""
"or %2,%0")
(define_insn "iorsi3"
[(set (match_operand:SI 0 "register_operand" "=d,a")
(ior:SI (match_operand:SI 1 "register_operand" "%0,0")
(match_operand:SI 2 "nonmemory_operand" "di,ai")))]
""
"or %2,%0")
(define_insn "iorhi3"
[(set (match_operand:HI 0 "register_operand" "=d,a")
(ior:HI (match_operand:HI 1 "register_operand" "%0,0")
(match_operand:HI 2 "nonmemory_operand" "di,ai")))]
""
"or %2,%0")
(define_insn "iorqi3"
[(set (match_operand:QI 0 "register_operand" "=d,a")
(ior:QI (match_operand:QI 1 "register_operand" "%0,0")
(match_operand:QI 2 "nonmemory_operand" "di,ai")))]
""
"or %2,%0")
;;- xor instructions.
(define_insn ""
[(set (match_operand:DI 0 "register_operand" "=d")
(xor:DI (match_operand:DI 1 "register_operand" "%0")
(match_operand:DI 2 "" "")))]
"(GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 0)
|| (GET_CODE (operands[2]) == CONST_DOUBLE
&& CONST_DOUBLE_HIGH (operands[2]) == 0)"
"xor %2,%0")
(define_insn "xordi3"
[(set (match_operand:DI 0 "register_operand" "=d")
(xor:DI (match_operand:DI 1 "register_operand" "%0")
(match_operand:DI 2 "register_operand" "d")))]
""
"xor %2,%0")
(define_insn "xorsi3"
[(set (match_operand:SI 0 "register_operand" "=d,a")
(xor:SI (match_operand:SI 1 "register_operand" "%0,0")
(match_operand:SI 2 "nonmemory_operand" "di,ai")))]
""
"xor %2,%0")
(define_insn "xorhi3"
[(set (match_operand:HI 0 "register_operand" "=d,a")
(xor:HI (match_operand:HI 1 "register_operand" "%0,0")
(match_operand:HI 2 "nonmemory_operand" "di,ai")))]
""
"xor %2,%0")
(define_insn "xorqi3"
[(set (match_operand:QI 0 "register_operand" "=d,a")
(xor:QI (match_operand:QI 1 "register_operand" "%0,0")
(match_operand:QI 2 "nonmemory_operand" "di,ai")))]
""
"xor %2,%0")
(define_insn "negdf2"
[(set (match_operand:DF 0 "register_operand" "=d")
(neg:DF (match_operand:DF 1 "register_operand" "d")))]
""
"neg.d %1,%0"
[(set_attr "type" "addd")])
(define_insn "negsf2"
[(set (match_operand:SF 0 "register_operand" "=d")
(neg:SF (match_operand:SF 1 "register_operand" "d")))]
""
"neg.s %1,%0"
[(set_attr "type" "adds")])
(define_insn "negdi2"
[(set (match_operand:DI 0 "register_operand" "=d")
(neg:DI (match_operand:DI 1 "register_operand" "d")))]
""
"neg.l %1,%0")
(define_insn "negsi2"
[(set (match_operand:SI 0 "register_operand" "=d,a")
(neg:SI (match_operand:SI 1 "register_operand" "d,a")))]
""
"neg.w %1,%0")
(define_insn "neghi2"
[(set (match_operand:HI 0 "register_operand" "=d,a")
(neg:HI (match_operand:HI 1 "register_operand" "d,a")))]
""
"neg.h %1,%0")
(define_insn "negqi2"
[(set (match_operand:QI 0 "register_operand" "=d")
(neg:QI (match_operand:QI 1 "register_operand" "d")))]
""
"neg.b %1,%0")
(define_insn "one_cmpldi2"
[(set (match_operand:DI 0 "register_operand" "=d")
(not:DI (match_operand:DI 1 "register_operand" "d")))]
""
"not %1,%0")
(define_insn "one_cmplsi2"
[(set (match_operand:SI 0 "register_operand" "=d,a")
(not:SI (match_operand:SI 1 "register_operand" "d,a")))]
""
"not %1,%0")
(define_insn "one_cmplhi2"
[(set (match_operand:HI 0 "register_operand" "=d,a")
(not:HI (match_operand:HI 1 "register_operand" "d,a")))]
""
"not %1,%0")
(define_insn "one_cmplqi2"
[(set (match_operand:QI 0 "register_operand" "=d,a")
(not:QI (match_operand:QI 1 "register_operand" "d,a")))]
""
"not %1,%0")
;;- Shifts
;;
;; The extreme profusion of patterns here is due to the different-speed
;; shifts on different machines, and the C1's lack of word shift S-register
;; instructions.
;; SImode
;; Arithmetic left 1, 1 cycle on all machines via add
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r")
(ashift:SI (match_operand:SI 1 "register_operand" "0")
(const_int 1)))]
""
"add.w %0,%0")
;; C34 general shift is 1 cycle
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=d,a")
(ashift:SI (match_operand:SI 1 "register_operand" "0,0")
(match_operand:SI 2 "nonmemory_operand" "di,ai")))]
"TARGET_C34"
"@
shf.w %2,%0
shf %2,%0"
[(set_attr "type" "shfw,shfw")])
;; else shift left 0..7 is 1 cycle if we use an A register
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=a,?d")
(ashift:SI (match_operand:SI 1 "register_operand" "0,0")
(match_operand:SI 2 "immediate_operand" "ai,di")))]
"TARGET_C1 && INTVAL (operands[2]) < (unsigned) 8"
"@
shf %2,%0
shf %2,%0"
[(set_attr "type" "alu,shfl")])
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=a,?d")
(ashift:SI (match_operand:SI 1 "register_operand" "0,0")
(match_operand:SI 2 "immediate_operand" "ai,di")))]
"INTVAL (operands[2]) < (unsigned) 8"
"@
shf %2,%0
shf.w %2,%0"
[(set_attr "type" "alu,shfw")])
;; else general left shift
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=d,a")
(ashift:SI (match_operand:SI 1 "register_operand" "0,0")
(match_operand:SI 2 "nonmemory_operand" "di,ai")))]
"TARGET_C1"
"@
shf %2,%0
shf %2,%0"
[(set_attr "type" "shfl,shfw")])
;; but C2 left shift by a constant is faster via multiply
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r")
(ashift:SI (match_operand:SI 1 "register_operand" "0")
(match_operand:SI 2 "const_int_operand" "i")))]
"TARGET_C2 && INTVAL (operands[2]) < (unsigned) 32"
"mul.w %z2,%0"
[(set_attr "type" "mulw")])
(define_insn "ashlsi3"
[(set (match_operand:SI 0 "register_operand" "=d,a")
(ashift:SI (match_operand:SI 1 "register_operand" "0,0")
(match_operand:SI 2 "nonmemory_operand" "di,ai")))]
""
"@
shf.w %2,%0
shf %2,%0"
[(set_attr "type" "shfw,shfw")])
;; Logical right, general
;; The hardware wants the negative of the shift count
(define_expand "lshrsi3"
[(set (match_operand:SI 0 "register_operand" "")
(lshiftrt:SI (match_operand:SI 1 "register_operand" "")
(neg:SI (match_operand:SI 2 "nonmemory_operand" ""))))]
""
"operands[2] = negate_rtx (SImode, operands[2]);")
;; C1 lacks word shift S reg
(define_insn ""
[(set
(match_operand:SI 0 "register_operand" "=a,?d")
(lshiftrt:SI (match_operand:SI 1 "register_operand" "0,0")
(neg:SI (match_operand:SI 2 "nonmemory_operand" "ai,di"))))]
"TARGET_C1"
"@
shf %2,%0
ld.u #0,%0\;shf %2,%0"
[(set_attr "type" "shfw,shfl")])
;; general case
(define_insn ""
[(set
(match_operand:SI 0 "register_operand" "=d,a")
(lshiftrt:SI (match_operand:SI 1 "register_operand" "0,0")
(neg:SI (match_operand:SI 2 "nonmemory_operand" "di,ai"))))]
""
"@
shf.w %2,%0
shf %2,%0"
[(set_attr "type" "shfw,shfw")])
;; Patterns without neg produced by constant folding
(define_insn ""
[(set
(match_operand:SI 0 "register_operand" "=a,?d")
(lshiftrt:SI (match_operand:SI 1 "register_operand" "0,0")
(match_operand:SI 2 "immediate_operand" "i,i")))]
"TARGET_C1"
"@
shf #%n2,%0
ld.u #0,%0\;shf #%n2,%0"
[(set_attr "type" "shfw,shfl")])
(define_insn ""
[(set
(match_operand:SI 0 "register_operand" "=d,a")
(lshiftrt:SI (match_operand:SI 1 "register_operand" "0,0")
(match_operand:SI 2 "immediate_operand" "i,i")))]
""
"@
shf.w #%n2,%0
shf #%n2,%0"
[(set_attr "type" "shfw,shfw")])
;; Arithmetic right, general
;; Sign-extend to 64 bits, then shift that. Works for 0..32.
(define_expand "ashrsi3"
[(set (match_operand:SI 0 "register_operand" "")
(ashiftrt:SI (match_operand:SI 1 "register_operand" "")
(neg:SI (match_operand:SI 2 "nonmemory_operand" ""))))]
""
"operands[2] = negate_rtx (SImode, operands[2]);")
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=d,&d")
(ashiftrt:SI (match_operand:SI 1 "register_operand" "0,d")
(neg:SI
(match_operand:SI 2 "nonmemory_operand" "di,di"))))]
""
"cvtw.l %1,%0\;shf %2,%0"
[(set_attr "type" "shfl,shfl")])
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=d")
(ashiftrt:SI (match_operand:SI 1 "register_operand" "d")
(match_operand:SI 2 "immediate_operand" "i")))]
""
"cvtw.l %1,%0\;shf #%n2,%0"
[(set_attr "type" "shfl")])
;; DImode
;; Arithmetic left, 1-cycle
(define_insn ""
[(set (match_operand:DI 0 "register_operand" "=d")
(ashift:DI (match_operand:DI 1 "register_operand" "0")
(const_int 1)))]
""
"add.l %0,%0")
;; Arithmetic left, general
(define_insn "ashldi3"
[(set (match_operand:DI 0 "register_operand" "=d")
(ashift:DI (match_operand:DI 1 "register_operand" "0")
(match_operand:SI 2 "nonmemory_operand" "di")))]
""
"shf %2,%0"
[(set_attr "type" "shfl")])
;; Can omit zero- or sign-extend if shift is 32 or more.
(define_insn ""
[(set (match_operand:DI 0 "register_operand" "=d")
(ashift:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "0"))
(match_operand:SI 2 "const_int_operand" "i")))]
"INTVAL (operands[2]) >= 32"
"shf %2,%0"
[(set_attr "type" "shfl")])
(define_insn ""
[(set (match_operand:DI 0 "register_operand" "=d")
(ashift:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "0"))
(match_operand:SI 2 "const_int_operand" "i")))]
"INTVAL (operands[2]) >= 32"
"shf %2,%0"
[(set_attr "type" "shfl")])
;; Logical right, general
(define_expand "lshrdi3"
[(set (match_operand:DI 0 "register_operand" "")
(lshiftrt:DI (match_operand:DI 1 "register_operand" "")
(neg:SI (match_operand:SI 2 "nonmemory_operand" ""))))]
""
"operands[2] = negate_rtx (SImode, operands[2]);")
(define_insn ""
[(set (match_operand:DI 0 "register_operand" "=d")
(lshiftrt:DI (match_operand:DI 1 "register_operand" "0")
(neg:SI (match_operand:SI 2 "nonmemory_operand" "di"))))]
""
"shf %2,%0"
[(set_attr "type" "shfl")])
(define_insn ""
[(set (match_operand:DI 0 "register_operand" "=d")
(lshiftrt:DI (match_operand:DI 1 "register_operand" "0")
(match_operand:SI 2 "immediate_operand" "i")))]
""
"shf #%n2,%0"
[(set_attr "type" "shfl")])
;; Arithmetic right, general
;; Use
;; ((a >> b) ^ signbit) - signbit
;; where signbit is (1 << 63) >> b
;; Works for 0..63. Does not work for 64; unfortunate but valid.
(define_expand "ashrdi3"
[(set (match_operand:DI 0 "register_operand" "")
(lshiftrt:DI (match_operand:DI 1 "register_operand" "")
(neg:SI (match_operand:SI 2 "nonmemory_operand" ""))))
(set (match_dup 3) (lshiftrt:DI (match_dup 3) (neg:SI (match_dup 2))))
(set (match_dup 0) (xor:DI (match_dup 0) (match_dup 3)))
(set (match_dup 0) (minus:DI (match_dup 0) (match_dup 3)))]
""
"
{
if (GET_CODE (operands[2]) == CONST_INT)
switch (INTVAL (operands[2]))
{
case 32:
emit_insn (gen_ashrdi3_32 (operands[0], operands[1]));
DONE;
}
operands[2] = negate_rtx (SImode, operands[2]);
operands[3] = force_reg (DImode, immed_double_const (0, 1 << 31, DImode));
}")
;; Arithmetic right 32, a common case that can save a couple of insns.
(define_expand "ashrdi3_32"
[(set (match_operand:DI 0 "register_operand" "")
(lshiftrt:DI (match_operand:DI 1 "register_operand" "")
(const_int 32)))
(set (match_dup 0)
(sign_extend:DI (subreg:SI (match_dup 0) 0)))]
""
"")
;; __builtin instructions
(define_insn "sqrtdf2"
[(set (match_operand:DF 0 "register_operand" "=d")
(sqrt:DF (match_operand:DF 1 "register_operand" "0")))]
"! TARGET_C1 && flag_fast_math"
"sqrt.d %0"
[(set_attr "type" "divd")])
(define_insn "sqrtsf2"
[(set (match_operand:SF 0 "register_operand" "=d")
(sqrt:SF (match_operand:SF 1 "register_operand" "0")))]
"! TARGET_C1 && flag_fast_math"
"sqrt.s %0"
[(set_attr "type" "divs")])
(define_insn "sindf2"
[(set (match_operand:DF 0 "register_operand" "=d")
(unspec:DF [(match_operand:DF 1 "register_operand" "0")] 1))]
"! TARGET_C1 && flag_fast_math"
"sin.d %0")
(define_insn "sinsf2"
[(set (match_operand:SF 0 "register_operand" "=d")
(unspec:SF [(match_operand:SF 1 "register_operand" "0")] 1))]
"! TARGET_C1 && flag_fast_math"
"sin.s %0")
(define_insn "cosdf2"
[(set (match_operand:DF 0 "register_operand" "=d")
(unspec:DF [(match_operand:DF 1 "register_operand" "0")] 2))]
"! TARGET_C1 && flag_fast_math"
"cos.d %0")
(define_insn "cossf2"
[(set (match_operand:SF 0 "register_operand" "=d")
(unspec:SF [(match_operand:SF 1 "register_operand" "0")] 2))]
"! TARGET_C1 && flag_fast_math"
"cos.s %0")
(define_insn "ftruncdf2"
[(set (match_operand:DF 0 "register_operand" "=d")
(fix:DF (match_operand:DF 1 "register_operand" "d")))]
"! TARGET_C1"
"frint.d %1,%0"
[(set_attr "type" "cvtd")])
(define_insn "ftruncsf2"
[(set (match_operand:SF 0 "register_operand" "=d")
(fix:SF (match_operand:SF 1 "register_operand" "d")))]
"! TARGET_C1"
"frint.s %1,%0"
[(set_attr "type" "cvts")])
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=d")
(minus:SI (ffs:SI (match_operand:SI 1 "register_operand" "d"))
(const_int 1)))]
""
"tzc %1,%0\;le.w #32,%0\;jbrs.f L0%=\;ld.w #-1,%0\\nL0%=:")
(define_expand "ffssi2"
[(set (match_operand:SI 0 "register_operand" "=d")
(minus:SI (ffs:SI (match_operand:SI 1 "register_operand" "d"))
(const_int 1)))
(set (match_dup 0)
(plus:SI (match_dup 0)
(const_int 1)))]
""
"")
(define_insn "abssf2"
[(set (match_operand:SF 0 "register_operand" "=d")
(abs:SF (match_operand:SF 1 "register_operand" "0")))]
""
"and #0x7fffffff,%0")
(define_expand "absdf2"
[(set (subreg:DI (match_operand:DF 0 "register_operand" "=d") 0)
(and:DI (subreg:DI (match_operand:DF 1 "register_operand" "d") 0)
(match_dup 2)))]
""
"operands[2] = force_reg (DImode,
immed_double_const (-1, 0x7fffffff, DImode));")
;;- Compares
(define_insn "cmpdi"
[(set (cc0)
(compare (match_operand:DI 0 "register_operand" "d")
(match_operand:DI 1 "register_operand" "d")))]
""
"* return output_cmp (operands[0], operands[1], 'l');")
(define_insn ""
[(set (cc0) (match_operand:DI 0 "register_operand" "d"))
(clobber (match_scratch:DI 1 "=d"))]
"next_insn_tests_no_inequality (insn)"
"* return output_cmp (operands[0], operands[1], 'L');")
(define_insn "cmpsi"
[(set (cc0)
(compare (match_operand:SI 0 "register_operand" "d,a")
(match_operand:SI 1 "nonmemory_operand" "di,ai")))]
""
"* return output_cmp (operands[0], operands[1], 'w');")
(define_insn "cmphi"
[(set (cc0)
(compare (match_operand:HI 0 "register_operand" "d,a")
(match_operand:HI 1 "nonmemory_operand" "di,ai")))]
""
"* return output_cmp (operands[0], operands[1], 'h');")
; cmpqi is intentionally omitted.
;
; gcc will sign-extend or zero-extend the operands to the next
; wider mode, HImode.
;
; For reg .cmp. constant, we just go with the halfword immediate
; instruction. Perhaps the widening insn can be cse'd or combined away.
; If not, we're still as good as loading a byte constant into a register
; to do a reg-reg byte compare.
;
; The following patterns pick up cases that can use reg .cmp. reg after all.
(define_insn ""
[(set (cc0)
(compare
(sign_extend:HI (match_operand:QI 0 "register_operand" "d"))
(sign_extend:HI (match_operand:QI 1 "register_operand" "d"))))]
""
"* return output_cmp (operands[0], operands[1], 'b');")
(define_insn ""
[(set (cc0)
(compare
(ashift:HI (subreg:HI (match_operand:QI 0 "register_operand" "d") 0)
(const_int 8))
(ashift:HI (subreg:HI (match_operand:QI 1 "register_operand" "d") 0)
(const_int 8))))]
""
"* return output_cmp (operands[0], operands[1], 'b');")
(define_insn ""
[(set (cc0)
(compare (match_operand:QI 0 "register_operand" "d")
(match_operand:QI 1 "register_operand" "d")))]
""
"* return output_cmp (operands[0], operands[1], 'b');")
(define_insn ""
[(set (cc0) (match_operand:QI 0 "register_operand" "d"))
(clobber (match_scratch:QI 1 "=d"))]
"next_insn_tests_no_inequality (insn)"
"* return output_cmp (operands[0], operands[1], 'B');")
(define_insn ""
[(set (cc0) (subreg (match_operand:QI 0 "register_operand" "d") 0))
(clobber (match_scratch:QI 1 "=d"))]
"next_insn_tests_no_inequality (insn)"
"* return output_cmp (operands[0], operands[1], 'B');")
(define_insn ""
[(set (cc0)
(zero_extend (subreg (match_operand:QI 0 "register_operand" "d") 0)))
(clobber (match_scratch:QI 1 "=d"))]
"next_insn_tests_no_inequality (insn)"
"* return output_cmp (operands[0], operands[1], 'B');")
(define_insn "cmpdf"
[(set (cc0)
(compare (match_operand:DF 0 "register_operand" "d")
(match_operand:DF 1 "register_operand" "d")))]
""
"* return output_cmp (operands[0], operands[1], 'd');")
(define_insn "cmpsf"
[(set (cc0)
(compare (match_operand:SF 0 "register_operand" "d")
(match_operand:SF 1 "nonmemory_cmpsf_operand" "dF")))]
""
"* return output_cmp (operands[0], operands[1], 's');")
;; decrement-and-set-cc0 insns.
;;
;; The most important case where we can use the carry bit from an
;; arithmetic insn to eliminate a redundant compare is the decrement in
;; constructs like while (n--) and while (--n >= 0).
;;
;; We do it with combine patterns instead of NOTICE_UPDATE_CC because
;; the decrement needs to be kept at the end of the block during scheduling.
;;
;; These patterns must have memory alternatives because reload refuses
;; to do output reloads for an insn that sets cc0 (since it does not
;; want to clobber cc0 with its moves). Convex moves do not clobber
;; cc0, but there is no evident way to get reload to know that.
(define_insn ""
[(set (cc0)
(match_operand:SI 0 "register_operand" "+r,*m"))
(set (match_dup 0)
(plus:SI (match_dup 0)
(const_int -1)))]
"next_insn_tests_no_inequality (insn)"
"*
{
if (which_alternative == 0)
{
output_cmp (operands[0], constm1_rtx, 'W');
return \"add.w #-1,%0\";
}
else
{
output_cmp (gen_rtx (REG, SImode, 7), constm1_rtx, 'W');
return \"psh.w s7\;ld.w %0,s7\;add.w #-1,s7\;st.w s7,%0\;pop.w s7\";
}
}")
(define_insn ""
[(set (cc0)
(plus:SI (match_operand:SI 0 "register_operand" "+r,*m")
(const_int -1)))
(set (match_dup 0)
(plus:SI (match_dup 0)
(const_int -1)))]
"find_reg_note (next_cc0_user (insn), REG_NONNEG, 0)"
"*
{
if (which_alternative == 0)
{
output_cmp (operands[0], const0_rtx, 'W');
return \"add.w #-1,%0\";
}
else
{
output_cmp (gen_rtx (REG, SImode, 7), const0_rtx, 'W');
return \"psh.w s7\;ld.w %0,s7\;add.w #-1,s7\;st.w s7,%0\;pop.w s7\";
}
}")
(define_insn ""
[(set (cc0)
(match_operand:HI 0 "register_operand" "+r,*m"))
(set (match_dup 0)
(plus:HI (match_dup 0)
(const_int -1)))]
"next_insn_tests_no_inequality (insn)"
"*
{
if (which_alternative == 0)
{
output_cmp (operands[0], constm1_rtx, 'H');
return \"add.h #-1,%0\";
}
else
{
output_cmp (gen_rtx (REG, HImode, 7), constm1_rtx, 'H');
return \"psh.w s7\;ld.h %0,s7\;add.h #-1,s7\;st.h s7,%0\;pop.w s7\";
}
}")
(define_insn ""
[(set (cc0)
(plus:HI (match_operand:HI 0 "register_operand" "+r,*m")
(const_int -1)))
(set (match_dup 0)
(plus:HI (match_dup 0)
(const_int -1)))]
"find_reg_note (next_cc0_user (insn), REG_NONNEG, 0)"
"*
{
if (which_alternative == 0)
{
output_cmp (operands[0], const0_rtx, 'H');
return \"add.h #-1,%0\";
}
else
{
output_cmp (gen_rtx (REG, HImode, 7), const0_rtx, 'H');
return \"psh.w s7\;ld.h %0,s7\;add.h #-1,s7\;st.h s7,%0\;pop.w s7\";
}
}")
;;- Jumps
(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)))]
""
"* return output_condjump (operands[0], \"eq\", 't'); ")
(define_insn "bne"
[(set (pc)
(if_then_else (ne (cc0)
(const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"* return output_condjump (operands[0], \"eq\", 'f'); ")
(define_insn "bgt"
[(set (pc)
(if_then_else (gt (cc0)
(const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"* return output_condjump (operands[0], \"le\", 'f'); ")
(define_insn "bgtu"
[(set (pc)
(if_then_else (gtu (cc0)
(const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"* return output_condjump (operands[0], \"leu\", 'f'); ")
(define_insn "blt"
[(set (pc)
(if_then_else (lt (cc0)
(const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"* return output_condjump (operands[0], \"lt\", 't'); ")
(define_insn "bltu"
[(set (pc)
(if_then_else (ltu (cc0)
(const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"* return output_condjump (operands[0], \"ltu\", 't'); ")
(define_insn "bge"
[(set (pc)
(if_then_else (ge (cc0)
(const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"* return output_condjump (operands[0], \"lt\", 'f'); ")
(define_insn "bgeu"
[(set (pc)
(if_then_else (geu (cc0)
(const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"* return output_condjump (operands[0], \"ltu\", 'f'); ")
(define_insn "ble"
[(set (pc)
(if_then_else (le (cc0)
(const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"* return output_condjump (operands[0], \"le\", 't'); ")
(define_insn "bleu"
[(set (pc)
(if_then_else (leu (cc0)
(const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"* return output_condjump (operands[0], \"leu\", 't'); ")
(define_insn ""
[(set (pc)
(if_then_else (eq (cc0)
(const_int 0))
(pc)
(label_ref (match_operand 0 "" ""))))]
""
"* return output_condjump (operands[0], \"eq\", 'f'); ")
(define_insn ""
[(set (pc)
(if_then_else (ne (cc0)
(const_int 0))
(pc)
(label_ref (match_operand 0 "" ""))))]
""
"* return output_condjump (operands[0], \"eq\", 't'); ")
(define_insn ""
[(set (pc)
(if_then_else (gt (cc0)
(const_int 0))
(pc)
(label_ref (match_operand 0 "" ""))))]
""
"* return output_condjump (operands[0], \"le\", 't'); ")
(define_insn ""
[(set (pc)
(if_then_else (gtu (cc0)
(const_int 0))
(pc)
(label_ref (match_operand 0 "" ""))))]
""
"* return output_condjump (operands[0], \"leu\", 't'); ")
(define_insn ""
[(set (pc)
(if_then_else (lt (cc0)
(const_int 0))
(pc)
(label_ref (match_operand 0 "" ""))))]
""
"* return output_condjump (operands[0], \"lt\", 'f'); ")
(define_insn ""
[(set (pc)
(if_then_else (ltu (cc0)
(const_int 0))
(pc)
(label_ref (match_operand 0 "" ""))))]
""
"* return output_condjump (operands[0], \"ltu\", 'f'); ")
(define_insn ""
[(set (pc)
(if_then_else (ge (cc0)
(const_int 0))
(pc)
(label_ref (match_operand 0 "" ""))))]
""
"* return output_condjump (operands[0], \"lt\", 't'); ")
(define_insn ""
[(set (pc)
(if_then_else (geu (cc0)
(const_int 0))
(pc)
(label_ref (match_operand 0 "" ""))))]
""
"* return output_condjump (operands[0], \"ltu\", 't'); ")
(define_insn ""
[(set (pc)
(if_then_else (le (cc0)
(const_int 0))
(pc)
(label_ref (match_operand 0 "" ""))))]
""
"* return output_condjump (operands[0], \"le\", 'f'); ")
(define_insn ""
[(set (pc)
(if_then_else (leu (cc0)
(const_int 0))
(pc)
(label_ref (match_operand 0 "" ""))))]
""
"* return output_condjump (operands[0], \"leu\", 'f'); ")
;;- Calls
(define_expand "call_pop"
[(parallel [(call (match_operand:QI 0 "memory_operand" "m")
(match_operand:SI 1 "const_int_operand" "i"))
(match_operand:SI 2 "const_int_operand" "i")
(match_operand:SI 3 "const_int_operand" "i")
(reg:SI 8)])]
""
"")
(define_insn ""
[(call (match_operand:QI 0 "memory_operand" "m")
(match_operand:SI 1 "const_int_operand" "i"))
(match_operand:SI 2 "const_int_operand" "i")
(match_operand:SI 3 "const_int_operand" "i")
(match_operand:SI 4 "" "")]
""
"* return output_call (insn, &operands[0]);")
(define_expand "call_value_pop"
[(parallel [(set (match_operand 0 "" "=g")
(call (match_operand:QI 1 "memory_operand" "m")
(match_operand:SI 2 "const_int_operand" "i")))
(match_operand:SI 3 "const_int_operand" "i")
(match_operand:SI 4 "const_int_operand" "i")
(reg:SI 8)])]
""
"")
(define_insn ""
[(set (match_operand 0 "" "=g")
(call (match_operand:QI 1 "memory_operand" "m")
(match_operand:SI 2 "const_int_operand" "i")))
(match_operand:SI 3 "const_int_operand" "i")
(match_operand:SI 4 "const_int_operand" "i")
(match_operand:SI 5 "" "")]
""
"* return output_call (insn, &operands[1]); ")
;; Call subroutine returning any type.
(define_expand "untyped_call"
[(parallel [(call (match_operand 0 "" "")
(const_int 0))
(match_operand 1 "" "")
(match_operand 2 "" "")])]
""
"
{
int i;
emit_call_insn (gen_call_pop (operands[0], const0_rtx,
const0_rtx, const0_rtx));
for (i = 0; i < XVECLEN (operands[2], 0); i++)
{
rtx set = XVECEXP (operands[2], 0, i);
emit_move_insn (SET_DEST (set), SET_SRC (set));
}
/* The optimizer does not know that the call sets the function value
registers we stored in the result block. We avoid problems by
claiming that all hard registers are used and clobbered at this
point. */
emit_insn (gen_blockage ());
DONE;
}")
;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
;; all of memory. This blocks insns from being moved across this point.
(define_insn "blockage"
[(unspec_volatile [(const_int 0)] 0)]
""
"")
(define_expand "return"
[(return)]
""
" replace_arg_pushes (); ")
(define_insn ""
[(return)]
""
"rtn")
(define_expand "prologue"
[(const_int 0)]
""
"
{
emit_ap_optimizations ();
DONE;
}")
(define_insn "tablejump"
[(set (pc) (match_operand:SI 0 "address_operand" "p"))
(use (label_ref (match_operand 1 "" "")))]
""
"jmp %a0")
(define_insn "indirect_jump"
[(set (pc) (match_operand:SI 0 "address_operand" "p"))]
""
"jmp %a0")