;; 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 ;; . ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; 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{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_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_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_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_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")] )