;; Machine description of the Synopsys DesignWare ARC cpu Floating Point
;; extensions for GNU C compiler
;; Copyright (C) 2007-2024 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
;; .
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; TODOs:
;; dpfp blocks?
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Scheduler descriptions for the fpx instructions
(define_insn_reservation "spfp_compact" 3
(and (match_test "TARGET_SPFP_COMPACT_SET")
(eq_attr "type" "spfp"))
"issue+core, nothing*2, write_port")
(define_insn_reservation "spfp_fast" 6
(and (match_test "TARGET_SPFP_FAST_SET")
(eq_attr "type" "spfp"))
"issue+core, nothing*5, write_port")
(define_insn_reservation "dpfp_compact_mult" 7
(and (match_test "TARGET_DPFP_COMPACT_SET")
(eq_attr "type" "dpfp_mult"))
"issue+core, nothing*6, write_port")
(define_insn_reservation "dpfp_compact_addsub" 5
(and (match_test "TARGET_DPFP_COMPACT_SET")
(eq_attr "type" "dpfp_addsub"))
"issue+core, nothing*4, write_port")
(define_insn_reservation "dpfp_fast" 5
(and (match_test "TARGET_DPFP_FAST_SET")
(eq_attr "type" "dpfp_mult,dpfp_addsub"))
"issue+core, nothing*4, write_port")
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define_insn "*addsf3_fpx"
[(set (match_operand:SF 0 "register_operand" "=r,r,r,r,r ")
(plus:SF (match_operand:SF 1 "nonmemory_operand" "0,r,GCal,r,0")
(match_operand:SF 2 "nonmemory_operand" "I,rL,r,GCal,LrCal")))]
; "(TARGET_ARC700 || TARGET_ARC600) && TARGET_SPFP_SET";Add flag for float
"TARGET_SPFP"
"@
fadd %0,%1,%2
fadd %0,%1,%2
fadd %0,%1,%2
fadd %0,%1,%2
fadd%? %0,%1,%2"
[(set_attr "type" "spfp")
(set_attr "length" "4,4,8,8,8")])
(define_insn "*subsf3_fpx"
[(set (match_operand:SF 0 "register_operand" "=r,r,r,r,r ")
(minus:SF (match_operand:SF 1 "nonmemory_operand" "r,0,GCal,r,0")
(match_operand:SF 2 "nonmemory_operand" "rL,I,r,GCal,LrCal")))]
;"(TARGET_ARC700 || TARGET_ARC600) && TARGET_SPFP_SET";Add flag for float
"TARGET_SPFP"
"@
fsub %0,%1,%2
fsub %0,%1,%2
fsub %0,%1,%2
fsub %0,%1,%2
fsub%? %0,%1,%2"
[(set_attr "type" "spfp")
(set_attr "length" "4,4,8,8,8")])
(define_insn "*mulsf3_fpx"
[(set (match_operand:SF 0 "register_operand" "=r,r,r,r,r ")
(mult:SF (match_operand:SF 1 "nonmemory_operand" "r,0,GCal,r,0")
(match_operand:SF 2 "nonmemory_operand" "rL,I,r,GCal,LrCal")))]
; "(TARGET_ARC700 || TARGET_ARC600) && TARGET_SPFP_SET" ;Add flag for float
"TARGET_SPFP"
"@
fmul %0,%1,%2
fmul %0,%1,%2
fmul %0,%1,%2
fmul %0,%1,%2
fmul%? %0,%1,%2"
[(set_attr "type" "spfp")
(set_attr "length" "4,4,8,8,8")])
;; For comparisons, we can avoid storing the top half of the result into
;; a register since '.f' lets us set the Z bit for the conditional
;; branch insns.
;; ??? FIXME (x-y)==0 is not a correct comparison for floats:
;; http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
(define_insn "cmpsfpx_raw"
[(set (reg:CC_FPX 61)
(compare:CC_FPX (match_operand:SF 0 "register_operand" "r")
(match_operand:SF 1 "register_operand" "r")))]
"TARGET_ARGONAUT_SET && TARGET_SPFP"
"fsub.f 0,%0,%1"
[(set_attr "type" "spfp")
(set_attr "length" "4")])
;; ??? FIXME (x-y)==0 is not a correct comparison for floats:
;; http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
;; ??? FIXME we claim to clobber operand 2, yet the two numbers appended
;; to the actual instructions are incorrect. The result of the d*subh
;; insn is stored in the Dx register specified by that first number.
(define_insn "cmpdfpx_raw"
[(set (reg:CC_FPX 61)
(compare:CC_FPX (match_operand:DF 0 "nonmemory_operand" "D,r")
(match_operand:DF 1 "nonmemory_operand" "r,D")))
(clobber (match_scratch:DF 2 "=D,D"))]
"TARGET_ARGONAUT_SET && TARGET_DPFP"
"@
dsubh%F0%F1.f 0,%H2,%L2
drsubh%F0%F2.f 0,%H1,%L1"
[(set_attr "type" "dpfp_addsub")
(set_attr "length" "4")])
;; ??? FIXME subtraction is not a correct comparison for floats:
;; http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
(define_insn "*cmpfpx_gt"
[(set (reg:CC_FP_GT 61) (compare:CC_FP_GT (reg:CC_FPX 61) (const_int 0)))]
"TARGET_ARGONAUT_SET"
"cmp.ls pcl,pcl"
[(set_attr "type" "compare")
(set_attr "length" "4")])
;; ??? FIXME subtraction is not a correct comparison for floats:
;; http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
(define_insn "*cmpfpx_ge"
[(set (reg:CC_FP_GE 61) (compare:CC_FP_GE (reg:CC_FPX 61) (const_int 0)))]
"TARGET_ARGONAUT_SET"
"rcmp.pnz pcl,0"
[(set_attr "type" "compare")
(set_attr "length" "4")])
;; DPFP instructions begin...
;; op0_reg = D1_reg.low
(define_insn "*lr_double_lower"
[(set (match_operand:SI 0 "register_operand" "=r")
(unspec_volatile:SI [(match_operand:DF 1 "arc_double_register_operand" "D")] VUNSPEC_ARC_LR ))]
"TARGET_DPFP && !TARGET_DPFP_DISABLE_LRSR"
"lr %0, [%1l] ; *lr_double_lower"
[(set_attr "length" "8")
(set_attr "type" "lr")]
)
(define_insn "*lr_double_higher"
[(set (match_operand:SI 0 "register_operand" "=r")
(unspec_volatile:SI [(match_operand:DF 1 "arc_double_register_operand" "D")]
VUNSPEC_ARC_LR_HIGH ))]
"TARGET_DPFP && !TARGET_DPFP_DISABLE_LRSR"
"lr %0, [%1h] ; *lr_double_higher"
[(set_attr "length" "8")
(set_attr "type" "lr")]
)
(define_insn "*dexcl_3op_peep2_insn"
[(set (match_operand:SI 0 "dest_reg_operand" "=r") ; not register_operand, to accept SUBREG
(unspec_volatile:SI
[(match_operand:SI 1 "shouldbe_register_operand" "r") ; r1
(match_operand:SI 2 "shouldbe_register_operand" "r") ; r0
] VUNSPEC_ARC_DEXCL ))
(clobber (match_operand:DF 3 "arc_double_register_operand" "=&D"))]
"TARGET_DPFP"
"dexcl%F3 %0, %1, %2"
[(set_attr "type" "move")
(set_attr "length" "4")]
)
;; version which will not overwrite operand0
(define_insn "dexcl_2op"
[(set (match_operand:DF 0 "arc_double_register_operand" "=D")
(unspec_volatile:DF
[(match_operand:SI 1 "shouldbe_register_operand" "r") ; r1
(match_operand:SI 2 "shouldbe_register_operand" "r") ; r0
] VUNSPEC_ARC_DEXCL_NORES))
]
"TARGET_DPFP"
"dexcl%F0 0, %1, %2"
[(set_attr "type" "move")
(set_attr "length" "4")]
)
;; dexcl a,b,c pattern generated by the peephole2 above
(define_insn "*dexcl_3op_peep2_insn_lr"
[(parallel [(set (match_operand:SI 0 "register_operand" "=r")
(unspec_volatile:SI [(match_operand:DF 1 "arc_double_register_operand" "=D")] VUNSPEC_ARC_LR ))
(set (match_dup 1) (match_operand:DF 2 "register_operand" "r"))]
)
]
"TARGET_DPFP && !TARGET_DPFP_DISABLE_LRSR"
"dexcl%F1 %0, %H2, %L2"
[(set_attr "type" "move")
(set_attr "length" "4")]
)
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; doubles support for ARC
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; D0 = D1+{reg_pair}2
;; (define_expand "adddf3"
;; [(set (match_operand:DF 0 "arc_double_register_operand" "")
;; (plus:DF (match_operand:DF 1 "arc_double_register_operand" "")
;; (match_operand:DF 2 "nonmemory_operand" "")))]
;; "TARGET_DPFP"
;; " "
;; )
;; daddh{0}{1} 0, {reg_pair}2.hi, {reg_pair}2.lo
;; OR
;; daddh{0}{1} 0, reg3, limm2.lo
;; daddh{0}{1} 0, {reg_pair}2.hi, {reg_pair}2.lo /* operand 4 = 1*/
;; OR
;; daddh{0}{1} 0, reg3, limm2.lo /* operand 4 = 0 */
;;
(define_insn "adddf3_insn"
[(set (match_operand:DF 0 "arc_double_register_operand" "=D,D")
(plus:DF (match_operand:DF 1 "arc_double_register_operand" "D,D")
(match_operand:DF 2 "nonmemory_operand" "!r,G")))
(use (match_operand:SI 3 "" "N,r"))
(use (match_operand:SI 4 "" "N,Q"))
; Prevent can_combine_p from combining muldf3_insn patterns with
; different USE pairs.
(use (match_dup 2))
]
"TARGET_DPFP &&
!(GET_CODE(operands[2]) == CONST_DOUBLE && GET_CODE(operands[3]) == CONST_INT)"
"@
daddh%F0%F1 0,%H2,%L2
daddh%F0%F1 0,%3,%L2"
[(set_attr "type" "dpfp_addsub")
(set_attr "length" "4,8")])
;; dmulh{0}{1} 0, {reg_pair}2.hi, {reg_pair}2.lo
;; OR
;; dmulh{0}{1} 0, reg3, limm2.lo
;; dmulh{0}{1} 0, {reg_pair}2.hi, {reg_pair}2.lo /* operand 4 = 1*/
;; OR
;; dmulh{0}{1} 0, reg3, limm2.lo /* operand 4 = 0*/
(define_insn "muldf3_insn"
[(set (match_operand:DF 0 "arc_double_register_operand" "=D,D")
(mult:DF (match_operand:DF 1 "arc_double_register_operand" "D,D")
(match_operand:DF 2 "nonmemory_operand" "!r,G")))
(use (match_operand:SI 3 "" "N,!r"))
(use (match_operand:SI 4 "" "N,Q"))
; Prevent can_combine_p from combining muldf3_insn patterns with
; different USE pairs.
(use (match_dup 2))
]
"TARGET_DPFP &&
!(GET_CODE(operands[2]) == CONST_DOUBLE && GET_CODE(operands[3]) == CONST_INT)"
"@
dmulh%F0%F1 0,%H2,%L2
dmulh%F0%F1 0,%3, %L2"
[(set_attr "type" "dpfp_mult")
(set_attr "length" "4,8")])
;; dsubh{0}{1} 0, {reg_pair}2.hi, {reg_pair}2.lo
;; OR
;; dsubh{0}{1} 0, reg3, limm2.lo
;; OR
;; drsubh{0}{2} 0, {reg_pair}1.hi, {reg_pair}1.lo
;; OR
;; drsubh{0}{2} 0, reg3, limm1.lo
;; dsubh{0}{1} 0, {reg_pair}2.hi, {reg_pair}2.lo /* operand 4 = 1 */
;; OR
;; dsubh{0}{1} 0, reg3, limm2.lo /* operand 4 = 0*/
;; OR
;; drsubh{0}{2} 0, {reg_pair}1.hi, {reg_pair}1.lo /* operand 4 = 1 */
;; OR
;; drsubh{0}{2} 0, reg3, limm1.lo /* operand 4 = 0*/
(define_insn "subdf3_insn"
[(set (match_operand:DF 0 "arc_double_register_operand" "=D,D,D,D")
(minus:DF (match_operand:DF 1 "nonmemory_operand" "D,D,!r,G")
(match_operand:DF 2 "nonmemory_operand" "!r,G,D,D")))
(use (match_operand:SI 3 "" "N,r,N,r"))
(use (match_operand:SI 4 "" "N,Q,N,Q"))
; Prevent can_combine_p from combining muldf3_insn patterns with
; different USE pairs.
(use (match_dup 2))]
"TARGET_DPFP &&
!(GET_CODE(operands[2]) == CONST_DOUBLE && GET_CODE(operands[3]) == CONST_INT) &&
!(GET_CODE(operands[1]) == CONST_DOUBLE && GET_CODE(operands[3]) == CONST_INT)"
"@
dsubh%F0%F1 0,%H2,%L2
dsubh%F0%F1 0,%3,%L2
drsubh%F0%F2 0,%H1,%L1
drsubh%F0%F2 0,%3,%L1"
[(set_attr "type" "dpfp_addsub")
(set_attr "length" "4,8,4,8")
(set_attr "cpu_facility" "*,*,fpx,fpx")])
;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;; Peephole for following conversion
;; ;; D0 = D2{reg_pair}3
;; ;; {reg_pair}5 = D0
;; ;; D0 = {reg_pair}6
;; ;; |
;; ;; V
;; ;; _________________________________________________________
;; ;; / D0 = D2 {regpair3_or_limmreg34}
;; ;; ---- + {reg_pair}5.hi = ( D2{regpair3_or_limmreg34} ).hi
;; ;; | \_________________________________________________________
;; ;; |
;; ;; | ________________________________________________________
;; ;; | / {reg_pair}5.lo = ( D2{regpair3_or_limmreg34} ).lo
;; ;; +-----+ D0 = {reg_pair}6
;; ;; \ _________________________________________________________
;; ;; ||
;; ;; ||
;; ;; \/
;; ;; d{0}{2}h {reg_pair}5.hi, {regpair3_or_limmreg34}.lo, {regpair3_or_limmreg34}.hi
;; ;; dexcl{0} {reg_pair}5.lo, {reg_pair}6.lo, {reg_pair}6.hi
;; ;; -----------------------------------------------------------------------------------------
;; ;; where is one of {+,*,-}
;; ;; is {add,mult,sub}
;; ;;
;; ;; NOTE: For rsub insns D2 and {regpair3_or_limmreg34} get interchanged as
;; ;; {regpair2_or_limmreg24} and D3
;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; (define_peephole2
;; [(parallel [(set (match_operand:DF 0 "register_operand" "")
;; (match_operator:DF 1 "arc_dpfp_operator" [(match_operand:DF 2 "nonmemory_operand" "")
;; (match_operand:DF 3 "nonmemory_operand" "")]))
;; (use (match_operand:SI 4 "" ""))])
;; (set (match_operand:DF 5 "register_operand" "")
;; (match_dup 0))
;; (set (match_dup 0)
;; (match_operand:DF 6 "register_operand" ""))
;; ]
;; "TARGET_DPFP"
;; [
;; (parallel [(set (match_dup 0)
;; (match_op_dup:DF 1 [(match_dup 2)
;; (match_dup 3)]))
;; (use (match_dup 4))
;; (set (match_dup 5)
;; (match_op_dup:DF 1 [(match_dup 2)
;; (match_dup 3)]))])
;; (parallel [
;; ;; (set (subreg:SI (match_dup 5) 0)
;; (set (match_dup 7)
;; (unspec_volatile [(match_dup 0)] VUNSPEC_ARC_LR ))
;; (set (match_dup 0) (match_dup 6))]
;; )
;; ]
;; "operands[7] = simplify_gen_subreg(SImode,operands[5],DFmode,0);"
;; )
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Peephole for following conversion
;; D0 = D2{reg_pair}3
;; {reg_pair}6 = D0
;; D0 = {reg_pair}7
;; |
;; V
;; _________________________________________________________
;; / D0 = D2 {regpair3_or_limmreg34}
;; ---- + {reg_pair}6.hi = ( D2{regpair3_or_limmreg34} ).hi
;; | \_________________________________________________________
;; |
;; | ________________________________________________________
;; | / {reg_pair}6.lo = ( D2{regpair3_or_limmreg34} ).lo
;; +-----+ D0 = {reg_pair}7
;; \ _________________________________________________________
;; ||
;; ||
;; \/
;; d{0}{2}h {reg_pair}6.hi, {regpair3_or_limmreg34}.lo, {regpair3_or_limmreg34}.hi
;; dexcl{0} {reg_pair}6.lo, {reg_pair}7.lo, {reg_pair}7.hi
;; -----------------------------------------------------------------------------------------
;; where is one of {+,*,-}
;; is {add,mult,sub}
;;
;; NOTE: For rsub insns D2 and {regpair3_or_limmreg34} get interchanged as
;; {regpair2_or_limmreg24} and D3
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define_peephole2
[(parallel [(set (match_operand:DF 0 "register_operand" "")
(match_operator:DF 1 "arc_dpfp_operator" [(match_operand:DF 2 "nonmemory_operand" "")
(match_operand:DF 3 "nonmemory_operand" "")]))
(use (match_operand:SI 4 "" ""))
(use (match_operand:SI 5 "" ""))
(use (match_operand:SI 6 "" ""))])
(set (match_operand:DF 7 "register_operand" "")
(match_dup 0))
(set (match_dup 0)
(match_operand:DF 8 "register_operand" ""))
]
"TARGET_DPFP && !TARGET_DPFP_DISABLE_LRSR"
[
(parallel [(set (match_dup 0)
(match_op_dup:DF 1 [(match_dup 2)
(match_dup 3)]))
(use (match_dup 4))
(use (match_dup 5))
(set (match_dup 7)
(match_op_dup:DF 1 [(match_dup 2)
(match_dup 3)]))])
(parallel [
;; (set (subreg:SI (match_dup 7) 0)
(set (match_dup 9)
(unspec_volatile:SI [(match_dup 0)] VUNSPEC_ARC_LR ))
(set (match_dup 0) (match_dup 8))]
)
]
"operands[9] = simplify_gen_subreg(SImode,operands[7],DFmode,0);"
)
;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;; Peephole to generate d{ij}h a,b,c instructions
;; ;; D0 = D2{reg_pair}3
;; ;; {reg_pair}5 = D0
;; ;; |
;; ;; V
;; ;; __________________________________________
;; ;; / D0 = D2 {regpair3_or_limmreg34}
;; ;; ---- + {reg_pair}5.hi = ( D2{regpair3_or_limmreg34} ).hi
;; ;; | \__________________________________________
;; ;; |
;; ;; + --- {reg_pair}5.lo = ( D2{regpair3_or_limmreg34} ).lo
;; ;; ||
;; ;; ||
;; ;; \/
;; ;; d{0}{2}h {reg_pair}4.hi, {regpair3_or_limmreg34}.lo, {regpair3_or_limmreg34}.hi
;; ;; lr {reg_pair}4.lo, {D2l}
;; ;; ----------------------------------------------------------------------------------------
;; ;; where is one of {+,*,-}
;; ;; is {add,mult,sub}
;; ;;
;; ;; NOTE: For rsub insns D2 and {regpair3_or_limmreg34} get interchanged as
;; ;; {regpair2_or_limmreg24} and D3
;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; (define_peephole2
;; [(parallel [(set (match_operand:DF 0 "register_operand" "")
;; (match_operator:DF 1 "arc_dpfp_operator" [(match_operand:DF 2 "nonmemory_operand" "")
;; (match_operand:DF 3 "nonmemory_operand" "")]))
;; (use (match_operand:SI 4 "" ""))])
;; (set (match_operand:DF 5 "register_operand" "")
;; (match_dup 0))
;; ]
;; "TARGET_DPFP"
;; [
;; (parallel [(set (match_dup 0)
;; (match_op_dup:DF 1 [(match_dup 2)
;; (match_dup 3)]))
;; (use (match_dup 4))
;; (set (match_dup 5)
;; (match_op_dup:DF 1 [(match_dup 2)
;; (match_dup 3)]))])
;; ; (set (subreg:SI (match_dup 5) 0)
;; (set (match_dup 6)
;; (unspec_volatile [(match_dup 0)] VUNSPEC_ARC_LR ))
;; ]
;; "operands[6] = simplify_gen_subreg(SImode,operands[5],DFmode,0);"
;; )
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Peephole to generate d{ij}h a,b,c instructions
;; D0 = D2{reg_pair}3
;; {reg_pair}6 = D0
;; |
;; V
;; __________________________________________
;; / D0 = D2 {regpair3_or_limmreg34}
;; ---- + {reg_pair}6.hi = ( D2{regpair3_or_limmreg34} ).hi
;; | \__________________________________________
;; |
;; + --- {reg_pair}6.lo = ( D2{regpair3_or_limmreg34} ).lo
;; ||
;; ||
;; \/
;; d{0}{2}h {reg_pair}4.hi, {regpair3_or_limmreg34}.lo, {regpair3_or_limmreg34}.hi
;; lr {reg_pair}4.lo, {D2l}
;; ----------------------------------------------------------------------------------------
;; where is one of {+,*,-}
;; is {add,mult,sub}
;;
;; NOTE: For rsub insns D2 and {regpair3_or_limmreg34} get interchanged as
;; {regpair2_or_limmreg24} and D3
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define_peephole2
[(parallel [(set (match_operand:DF 0 "register_operand" "")
(match_operator:DF 1 "arc_dpfp_operator" [(match_operand:DF 2 "nonmemory_operand" "")
(match_operand:DF 3 "nonmemory_operand" "")]))
(use (match_operand:SI 4 "" ""))
(use (match_operand:SI 5 "" ""))
(use (match_operand:SI 6 "" ""))])
(set (match_operand:DF 7 "register_operand" "")
(match_dup 0))
]
"TARGET_DPFP && !TARGET_DPFP_DISABLE_LRSR"
[
(parallel [(set (match_dup 0)
(match_op_dup:DF 1 [(match_dup 2)
(match_dup 3)]))
(use (match_dup 4))
(use (match_dup 5))
(set (match_dup 7)
(match_op_dup:DF 1 [(match_dup 2)
(match_dup 3)]))])
; (set (subreg:SI (match_dup 7) 0)
(set (match_dup 8)
(unspec_volatile:SI [(match_dup 0)] VUNSPEC_ARC_LR ))
]
"operands[8] = simplify_gen_subreg(SImode,operands[7],DFmode,0);"
)
;; ;; _______________________________________________________
;; ;; / D0 = D1 + {regpair2_or_limmreg23}
;; ;; + {reg_pair}4.hi = ( D1 + {regpair2_or_limmreg23} ).hi
;; ;; \_______________________________________________________
;; (define_insn "*daddh_peep2_insn"
;; [(parallel [(set (match_operand:DF 0 "arc_double_register_operand" "=D,D")
;; (plus:DF (match_operand:DF 1 "arc_double_register_operand" "D,D")
;; (match_operand:DF 2 "nonmemory_operand" "r,G")))
;; (use (match_operand:SI 3 "" "N,r"))
;; (set (match_operand:DF 4 "register_operand" "=r,r")
;; (plus:DF (match_dup 1)
;; (match_dup 2)))])]
;; "TARGET_DPFP"
;; "@
;; daddh%F0%F1 %H4, %H2, %L2
;; daddh%F0%F1 %H4, %3, %L2"
;; [(set_attr "type" "dpfp_addsub")
;; (set_attr "length" "4,8")]
;; )
;; _______________________________________________________
;; / D0 = D1 + {regpair2_or_limmreg23}
;; + {reg_pair}5.hi = ( D1 + {regpair2_or_limmreg23} ).hi
;; \_______________________________________________________
(define_insn "*daddh_peep2_insn"
[(parallel [(set (match_operand:DF 0 "arc_double_register_operand" "=D,D")
(plus:DF (match_operand:DF 1 "arc_double_register_operand" "D,D")
(match_operand:DF 2 "nonmemory_operand" "r,G")))
(use (match_operand:SI 3 "" "N,r"))
(use (match_operand:SI 4 "" "N,Q"))
(use (match_operand:SI 5 "" ""))
(set (match_operand:DF 6 "register_operand" "=r,r")
(plus:DF (match_dup 1)
(match_dup 2)))])]
"TARGET_DPFP &&
!(GET_CODE(operands[2]) == CONST_DOUBLE && GET_CODE(operands[3]) == CONST_INT)"
"@
daddh%F0%F1 %H6, %H2, %L2
daddh%F0%F1 %H6, %3, %L2"
[(set_attr "type" "dpfp_addsub")
(set_attr "length" "4,8")]
)
;; _______________________________________________________
;; / D0 = D1 * {regpair2_or_limmreg23}
;; + {reg_pair}5.hi = ( D1 * {regpair2_or_limmreg23} ).hi
;; \_______________________________________________________
(define_insn "*dmulh_peep2_insn"
[(parallel [(set (match_operand:DF 0 "arc_double_register_operand" "=D,D")
(mult:DF (match_operand:DF 1 "arc_double_register_operand" "D,D")
(match_operand:DF 2 "nonmemory_operand" "r,G")))
(use (match_operand:SI 3 "" "N,r"))
(use (match_operand:SI 4 "" "N,Q"))
(use (match_operand:SI 5 "" ""))
(set (match_operand:DF 6 "register_operand" "=r,r")
(mult:DF (match_dup 1)
(match_dup 2)))])]
"TARGET_DPFP &&
!(GET_CODE(operands[2]) == CONST_DOUBLE && GET_CODE(operands[3]) == CONST_INT)"
"@
dmulh%F0%F1 %H6, %H2, %L2
dmulh%F0%F1 %H6, %3, %L2"
[(set_attr "type" "dpfp_mult")
(set_attr "length" "4,8")]
)
;; _______________________________________________________
;; / D0 = D1 - {regpair2_or_limmreg23}
;; + {reg_pair}5.hi = ( D1 - {regpair2_or_limmreg23} ).hi
;; \_______________________________________________________
;; OR
;; _______________________________________________________
;; / D0 = {regpair1_or_limmreg13} - D2
;; + {reg_pair}5.hi = ( {regpair1_or_limmreg13} ).hi - D2
;; \_______________________________________________________
(define_insn "*dsubh_peep2_insn"
[(parallel [(set (match_operand:DF 0 "arc_double_register_operand" "=D,D,D,D")
(minus:DF (match_operand:DF 1 "nonmemory_operand" "D,D,r,G")
(match_operand:DF 2 "nonmemory_operand" "r,G,D,D")))
(use (match_operand:SI 3 "" "N,r,N,r"))
(use (match_operand:SI 4 "" "N,Q,N,Q"))
(use (match_operand:SI 5 "" ""))
(set (match_operand:DF 6 "register_operand" "=r,r,r,r")
(minus:DF (match_dup 1)
(match_dup 2)))])]
"TARGET_DPFP &&
!(GET_CODE(operands[2]) == CONST_DOUBLE && GET_CODE(operands[3]) == CONST_INT) &&
!(GET_CODE(operands[1]) == CONST_DOUBLE && GET_CODE(operands[3]) == CONST_INT)"
"@
dsubh%F0%F1 %H6, %H2, %L2
dsubh%F0%F1 %H6, %3, %L2
drsubh%F0%F2 %H6, %H1, %L1
drsubh%F0%F2 %H6, %3, %L1"
[(set_attr "type" "dpfp_addsub")
(set_attr "length" "4,8,4,8")
(set_attr "cpu_facility" "*,*,fpx,fpx")])
;; Intel QUARK SE extensions
(define_mode_iterator QUARK_CMP [CC_FP_GT CC_FP_GE])
(define_mode_attr quark_cmp [(CC_FP_GT "gt") (CC_FP_GE "ge")])
(define_expand "cmp_quark"
[(parallel [(set (match_operand 0 "")
(match_operand 1 ""))
(clobber (match_scratch:SI 2 ""))])]
""
"")
(define_insn "*cmpsf_quark_"
[(set (reg:QUARK_CMP CC_REG)
(compare:QUARK_CMP (match_operand:SF 0 "register_operand" "r")
(match_operand:SF 1 "register_operand" "r")))
(clobber (match_scratch:SI 2 "=&r"))]
"TARGET_FPX_QUARK"
"dsp_fp_cmp\\t%2,%0,%1\\n\\trsub.f\\t0,%2,7\\n\\tcmp.nc\\t%2,1\\n\\tcmp.hi\\t%2,3"
[(set_attr "length" "16")
(set_attr "cond" "set")
(set_attr "predicable" "no")
(set_attr "cond" "nocond")])
(define_insn "*cmpsf_quark_ord"
[(set (reg:CC_FP_ORD CC_REG)
(compare:CC_FP_ORD (match_operand:SF 0 "register_operand" "r")
(match_operand:SF 1 "register_operand" "r")))
(clobber (match_scratch:SI 2 "=&r"))]
"TARGET_FPX_QUARK"
"dsp_fp_cmp\\t%2,%0,%1\\n\\tadd.f\\t%2,%2,-8"
[(set_attr "length" "8")
(set_attr "cond" "set")
(set_attr "predicable" "no")
(set_attr "cond" "nocond")])
(define_insn "*cmpsf_quark_uneq"
[(set (reg:CC_FP_UNEQ CC_REG)
(compare:CC_FP_UNEQ (match_operand:SF 0 "register_operand" "r")
(match_operand:SF 1 "register_operand" "r")))
(clobber (match_scratch:SI 2 "=&r"))]
"TARGET_FPX_QUARK"
"dsp_fp_cmp\\t%2,%0,%1\\n\\ttst\\t%2,6"
[(set_attr "length" "8")
(set_attr "cond" "set")
(set_attr "predicable" "no")
(set_attr "cond" "nocond")])
(define_insn "*cmpsf_quark_eq"
[(set (reg:CC_Z CC_REG)
(compare:CC_Z (match_operand:SF 0 "register_operand" "r")
(match_operand:SF 1 "register_operand" "r")))
(clobber (match_scratch:SI 2 "=&r"))]
"TARGET_FPX_QUARK"
"dsp_fp_cmp\\t%2,%0,%1\\n\\ttst\\t%2,0x0E"
[(set_attr "length" "8")
(set_attr "cond" "set")
(set_attr "predicable" "no")
(set_attr "cond" "nocond")])
(define_insn "*divsf3_quark"
[(set (match_operand:SF 0 "register_operand" "=r")
(div:SF (match_operand:SF 1 "register_operand" "r")
(match_operand:SF 2 "register_operand" "r")))]
"TARGET_FPX_QUARK"
"dsp_fp_div\\t%0,%1,%2"
[(set_attr "length" "4")
(set_attr "predicable" "no")
(set_attr "cond" "nocond")])
(define_insn "*sqrtsf2_quark"
[(set (match_operand:SF 0 "register_operand" "=r")
(sqrt:SF (match_operand:SF 1 "register_operand" "r")))]
"TARGET_FPX_QUARK"
"dsp_fp_sqrt\\t%0,%1"
[(set_attr "length" "4")
(set_attr "predicable" "no")
(set_attr "cond" "nocond")])
;; SF->SI (using rounding towards zero)
(define_insn "*fix_truncsfsi2_quark"
[(set (match_operand:SI 0 "register_operand" "=r")
(fix:SI (fix:SF (match_operand:SF 1 "register_operand" "r"))))]
"TARGET_FPX_QUARK"
"dsp_fp_flt2i\\t%0,%1"
[(set_attr "length" "4")
(set_attr "predicable" "no")
(set_attr "cond" "nocond")])
;; SI->SF
(define_insn "*floatsisf2_quark"
[(set (match_operand:SF 0 "register_operand" "=r")
(float:SF (match_operand:SI 1 "register_operand" "r")))]
"TARGET_FPX_QUARK"
"dsp_fp_i2flt\\t%0,%1"
[(set_attr "length" "4")
(set_attr "predicable" "no")
(set_attr "cond" "nocond")])