aboutsummaryrefslogtreecommitdiffstats
path: root/gcc-4.9/gcc/config/arc/fpx.md
diff options
context:
space:
mode:
Diffstat (limited to 'gcc-4.9/gcc/config/arc/fpx.md')
-rw-r--r--gcc-4.9/gcc/config/arc/fpx.md674
1 files changed, 674 insertions, 0 deletions
diff --git a/gcc-4.9/gcc/config/arc/fpx.md b/gcc-4.9/gcc/config/arc/fpx.md
new file mode 100644
index 000000000..4eee6aff9
--- /dev/null
+++ b/gcc-4.9/gcc/config/arc/fpx.md
@@ -0,0 +1,674 @@
+;; Machine description of the Synopsys DesignWare ARC cpu Floating Point
+;; extensions for GNU C compiler
+;; Copyright (C) 2007-2014 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
+;; <http://www.gnu.org/licenses/>.
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; 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"
+ [(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,%S1,%2
+ fadd %0,%1,%S2
+ fadd%? %0,%1,%S2"
+ [(set_attr "type" "spfp")
+ (set_attr "length" "4,4,8,8,8")])
+
+(define_insn "subsf3"
+ [(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,%S1,%2
+ fsub %0,%1,%S2
+ fsub%? %0,%1,%S2"
+ [(set_attr "type" "spfp")
+ (set_attr "length" "4,4,8,8,8")])
+
+(define_insn "mulsf3"
+ [(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,%S1,%2
+ fmul %0,%1,%S2
+ fmul%? %0,%1,%S2"
+ [(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_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_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:DF 1 "arc_double_register_operand" "D")
+ (match_operand:SI 2 "shouldbe_register_operand" "r") ; r1
+ (match_operand:SI 3 "shouldbe_register_operand" "r") ; r0
+ ] VUNSPEC_DEXCL ))
+ ]
+ "TARGET_DPFP"
+ "dexcl%F1 %0, %2, %3"
+ [(set_attr "type" "move")
+ (set_attr "length" "4")]
+)
+
+;; version which will not overwrite operand0
+(define_insn "*dexcl_3op_peep2_insn_nores"
+ [ (unspec_volatile:SI [
+ (match_operand:DF 0 "arc_double_register_operand" "D")
+ (match_operand:SI 1 "shouldbe_register_operand" "r") ; r1
+ (match_operand:SI 2 "shouldbe_register_operand" "r") ; r0
+ ] VUNSPEC_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_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
+(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"
+ " if (GET_CODE (operands[2]) == CONST_DOUBLE)
+ {
+ rtx high, low, tmp;
+ split_double (operands[2], &low, &high);
+ tmp = force_reg (SImode, high);
+ emit_insn(gen_adddf3_insn(operands[0], operands[1], operands[2],tmp,const0_rtx));
+ }
+ else
+ emit_insn(gen_adddf3_insn(operands[0], operands[1], operands[2],const1_rtx,const1_rtx));
+ DONE;
+ "
+)
+
+;; 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
+(define_expand "muldf3"
+ [(set (match_operand:DF 0 "arc_double_register_operand" "")
+ (mult:DF (match_operand:DF 1 "arc_double_register_operand" "")
+ (match_operand:DF 2 "nonmemory_operand" "")))]
+"TARGET_DPFP"
+" if (GET_CODE (operands[2]) == CONST_DOUBLE)
+ {
+ rtx high, low, tmp;
+ split_double (operands[2], &low, &high);
+ tmp = force_reg (SImode, high);
+ emit_insn(gen_muldf3_insn(operands[0], operands[1], operands[2],tmp,const0_rtx));
+ }
+ else
+ emit_insn(gen_muldf3_insn(operands[0], operands[1], operands[2],const1_rtx,const1_rtx));
+
+ DONE;
+ ")
+
+
+;; 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
+(define_expand "subdf3"
+ [(set (match_operand:DF 0 "arc_double_register_operand" "")
+ (minus:DF (match_operand:DF 1 "nonmemory_operand" "")
+ (match_operand:DF 2 "nonmemory_operand" "")))]
+"TARGET_DPFP"
+" if (GET_CODE (operands[1]) == CONST_DOUBLE || GET_CODE (operands[2]) == CONST_DOUBLE)
+ {
+ rtx high, low, tmp;
+ int const_index = ((GET_CODE (operands[1]) == CONST_DOUBLE) ? 1: 2);
+ split_double (operands[const_index], &low, &high);
+ tmp = force_reg (SImode, high);
+ emit_insn(gen_subdf3_insn(operands[0], operands[1], operands[2],tmp,const0_rtx));
+ }
+ else
+ emit_insn(gen_subdf3_insn(operands[0], operands[1], operands[2],const1_rtx,const1_rtx));
+
+ DONE;
+ "
+)
+
+;; 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")])
+
+;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; ;; Peephole for following conversion
+;; ;; D0 = D2<op>{reg_pair}3
+;; ;; {reg_pair}5 = D0
+;; ;; D0 = {reg_pair}6
+;; ;; |
+;; ;; V
+;; ;; _________________________________________________________
+;; ;; / D0 = D2 <op> {regpair3_or_limmreg34}
+;; ;; ---- + {reg_pair}5.hi = ( D2<op>{regpair3_or_limmreg34} ).hi
+;; ;; | \_________________________________________________________
+;; ;; |
+;; ;; | ________________________________________________________
+;; ;; | / {reg_pair}5.lo = ( D2<op>{regpair3_or_limmreg34} ).lo
+;; ;; +-----+ D0 = {reg_pair}6
+;; ;; \ _________________________________________________________
+;; ;; ||
+;; ;; ||
+;; ;; \/
+;; ;; d<op>{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 <op> is one of {+,*,-}
+;; ;; <opname> 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_LR ))
+;; (set (match_dup 0) (match_dup 6))]
+;; )
+;; ]
+;; "operands[7] = simplify_gen_subreg(SImode,operands[5],DFmode,0);"
+;; )
+;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Peephole for following conversion
+;; D0 = D2<op>{reg_pair}3
+;; {reg_pair}6 = D0
+;; D0 = {reg_pair}7
+;; |
+;; V
+;; _________________________________________________________
+;; / D0 = D2 <op> {regpair3_or_limmreg34}
+;; ---- + {reg_pair}6.hi = ( D2<op>{regpair3_or_limmreg34} ).hi
+;; | \_________________________________________________________
+;; |
+;; | ________________________________________________________
+;; | / {reg_pair}6.lo = ( D2<op>{regpair3_or_limmreg34} ).lo
+;; +-----+ D0 = {reg_pair}7
+;; \ _________________________________________________________
+;; ||
+;; ||
+;; \/
+;; d<op>{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 <op> is one of {+,*,-}
+;; <opname> 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_LR ))
+ (set (match_dup 0) (match_dup 8))]
+ )
+ ]
+ "operands[9] = simplify_gen_subreg(SImode,operands[7],DFmode,0);"
+ )
+
+;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; ;; Peephole to generate d<opname>{ij}h a,b,c instructions
+;; ;; D0 = D2<op>{reg_pair}3
+;; ;; {reg_pair}5 = D0
+;; ;; |
+;; ;; V
+;; ;; __________________________________________
+;; ;; / D0 = D2 <op> {regpair3_or_limmreg34}
+;; ;; ---- + {reg_pair}5.hi = ( D2<op>{regpair3_or_limmreg34} ).hi
+;; ;; | \__________________________________________
+;; ;; |
+;; ;; + --- {reg_pair}5.lo = ( D2<op>{regpair3_or_limmreg34} ).lo
+;; ;; ||
+;; ;; ||
+;; ;; \/
+;; ;; d<op>{0}{2}h {reg_pair}4.hi, {regpair3_or_limmreg34}.lo, {regpair3_or_limmreg34}.hi
+;; ;; lr {reg_pair}4.lo, {D2l}
+;; ;; ----------------------------------------------------------------------------------------
+;; ;; where <op> is one of {+,*,-}
+;; ;; <opname> 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_LR ))
+;; ]
+;; "operands[6] = simplify_gen_subreg(SImode,operands[5],DFmode,0);"
+;; )
+;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Peephole to generate d<opname>{ij}h a,b,c instructions
+;; D0 = D2<op>{reg_pair}3
+;; {reg_pair}6 = D0
+;; |
+;; V
+;; __________________________________________
+;; / D0 = D2 <op> {regpair3_or_limmreg34}
+;; ---- + {reg_pair}6.hi = ( D2<op>{regpair3_or_limmreg34} ).hi
+;; | \__________________________________________
+;; |
+;; + --- {reg_pair}6.lo = ( D2<op>{regpair3_or_limmreg34} ).lo
+;; ||
+;; ||
+;; \/
+;; d<op>{0}{2}h {reg_pair}4.hi, {regpair3_or_limmreg34}.lo, {regpair3_or_limmreg34}.hi
+;; lr {reg_pair}4.lo, {D2l}
+;; ----------------------------------------------------------------------------------------
+;; where <op> is one of {+,*,-}
+;; <opname> 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_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")]
+)