1;; Machine description of the Synopsys DesignWare ARC cpu Floating Point
2;; extensions for GNU C compiler
3;; Copyright (C) 2007-2020 Free Software Foundation, Inc.
4
5;; This file is part of GCC.
6
7;; GCC is free software; you can redistribute it and/or modify
8;; it under the terms of the GNU General Public License as published by
9;; the Free Software Foundation; either version 3, or (at your option)
10;; any later version.
11
12;; GCC is distributed in the hope that it will be useful,
13;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15;; GNU General Public License for more details.
16
17;; You should have received a copy of the GNU General Public License
18;; along with GCC; see the file COPYING3.  If not see
19;; <http://www.gnu.org/licenses/>.
20
21;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
22;; TODOs:
23;;        dpfp blocks?
24;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
25;; Scheduler descriptions for the fpx instructions
26(define_insn_reservation "spfp_compact" 3
27  (and (match_test "TARGET_SPFP_COMPACT_SET")
28       (eq_attr "type" "spfp"))
29  "issue+core, nothing*2, write_port")
30
31(define_insn_reservation "spfp_fast" 6
32  (and (match_test "TARGET_SPFP_FAST_SET")
33       (eq_attr "type" "spfp"))
34  "issue+core, nothing*5, write_port")
35
36(define_insn_reservation "dpfp_compact_mult" 7
37  (and (match_test "TARGET_DPFP_COMPACT_SET")
38       (eq_attr "type" "dpfp_mult"))
39  "issue+core, nothing*6, write_port")
40
41(define_insn_reservation "dpfp_compact_addsub" 5
42  (and (match_test "TARGET_DPFP_COMPACT_SET")
43       (eq_attr "type" "dpfp_addsub"))
44  "issue+core, nothing*4, write_port")
45
46(define_insn_reservation "dpfp_fast" 5
47  (and (match_test "TARGET_DPFP_FAST_SET")
48       (eq_attr "type" "dpfp_mult,dpfp_addsub"))
49  "issue+core, nothing*4, write_port")
50
51;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
52
53(define_insn "*addsf3_fpx"
54  [(set (match_operand:SF 0 "register_operand"          "=r,r,r,r,r ")
55	(plus:SF (match_operand:SF 1 "nonmemory_operand" "0,r,GCal,r,0")
56		 (match_operand:SF 2 "nonmemory_operand" "I,rL,r,GCal,LrCal")))]
57;  "(TARGET_ARC700 || TARGET_ARC600) && TARGET_SPFP_SET";Add flag for float
58  "TARGET_SPFP"
59  "@
60   fadd %0,%1,%2
61   fadd %0,%1,%2
62   fadd   %0,%1,%2
63   fadd   %0,%1,%2
64   fadd%? %0,%1,%2"
65  [(set_attr "type" "spfp")
66  (set_attr "length" "4,4,8,8,8")])
67
68(define_insn "*subsf3_fpx"
69  [(set (match_operand:SF 0 "register_operand"          "=r,r,r,r,r ")
70	(minus:SF (match_operand:SF 1 "nonmemory_operand" "r,0,GCal,r,0")
71		 (match_operand:SF 2 "nonmemory_operand" "rL,I,r,GCal,LrCal")))]
72  ;"(TARGET_ARC700 || TARGET_ARC600) && TARGET_SPFP_SET";Add flag for float
73  "TARGET_SPFP"
74  "@
75   fsub %0,%1,%2
76   fsub %0,%1,%2
77   fsub   %0,%1,%2
78   fsub   %0,%1,%2
79   fsub%? %0,%1,%2"
80  [(set_attr "type" "spfp")
81  (set_attr "length" "4,4,8,8,8")])
82
83(define_insn "*mulsf3_fpx"
84  [(set (match_operand:SF 0 "register_operand"          "=r,r,r,r,r ")
85	(mult:SF (match_operand:SF 1 "nonmemory_operand" "r,0,GCal,r,0")
86		 (match_operand:SF 2 "nonmemory_operand" "rL,I,r,GCal,LrCal")))]
87;  "(TARGET_ARC700 || TARGET_ARC600) && TARGET_SPFP_SET"	;Add flag for float
88  "TARGET_SPFP"
89  "@
90   fmul %0,%1,%2
91   fmul %0,%1,%2
92   fmul   %0,%1,%2
93   fmul   %0,%1,%2
94   fmul%? %0,%1,%2"
95  [(set_attr "type" "spfp")
96  (set_attr "length" "4,4,8,8,8")])
97
98
99;; For comparisons, we can avoid storing the top half of the result into
100;; a register since '.f' lets us set the Z bit for the conditional
101;; branch insns.
102
103;; ??? FIXME (x-y)==0 is not a correct comparison for floats:
104;;     http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
105(define_insn "cmpsfpx_raw"
106  [(set (reg:CC_FPX 61)
107	(compare:CC_FPX (match_operand:SF 0 "register_operand" "r")
108			 (match_operand:SF 1 "register_operand" "r")))]
109  "TARGET_ARGONAUT_SET && TARGET_SPFP"
110  "fsub.f 0,%0,%1"
111  [(set_attr "type" "spfp")
112   (set_attr "length" "4")])
113
114;; ??? FIXME (x-y)==0 is not a correct comparison for floats:
115;;     http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
116;; ??? FIXME we claim to clobber operand 2, yet the two numbers appended
117;; to the actual instructions are incorrect.  The result of the d*subh
118;; insn is stored in the Dx register specified by that first number.
119(define_insn "cmpdfpx_raw"
120  [(set (reg:CC_FPX 61)
121	(compare:CC_FPX (match_operand:DF 0 "nonmemory_operand" "D,r")
122			 (match_operand:DF 1 "nonmemory_operand" "r,D")))
123   (clobber (match_scratch:DF 2 "=D,D"))]
124  "TARGET_ARGONAUT_SET && TARGET_DPFP"
125  "@
126   dsubh%F0%F1.f 0,%H2,%L2
127   drsubh%F0%F2.f 0,%H1,%L1"
128  [(set_attr "type" "dpfp_addsub")
129   (set_attr "length" "4")])
130
131;; ??? FIXME subtraction is not a correct comparison for floats:
132;;     http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
133(define_insn "*cmpfpx_gt"
134  [(set (reg:CC_FP_GT 61) (compare:CC_FP_GT (reg:CC_FPX 61) (const_int 0)))]
135  "TARGET_ARGONAUT_SET"
136  "cmp.ls pcl,pcl"
137  [(set_attr "type" "compare")
138   (set_attr "length" "4")])
139
140;; ??? FIXME subtraction is not a correct comparison for floats:
141;;     http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
142(define_insn "*cmpfpx_ge"
143  [(set (reg:CC_FP_GE 61) (compare:CC_FP_GE (reg:CC_FPX 61) (const_int 0)))]
144  "TARGET_ARGONAUT_SET"
145  "rcmp.pnz pcl,0"
146  [(set_attr "type" "compare")
147   (set_attr "length" "4")])
148
149;; DPFP instructions begin...
150
151;; op0_reg = D1_reg.low
152(define_insn "*lr_double_lower"
153  [(set (match_operand:SI 0 "register_operand" "=r")
154	(unspec_volatile:SI [(match_operand:DF 1 "arc_double_register_operand" "D")] VUNSPEC_ARC_LR ))]
155 "TARGET_DPFP && !TARGET_DPFP_DISABLE_LRSR"
156"lr %0, [%1l] ; *lr_double_lower"
157[(set_attr "length" "8")
158(set_attr "type" "lr")]
159)
160
161(define_insn "*lr_double_higher"
162  [(set (match_operand:SI 0 "register_operand" "=r")
163	(unspec_volatile:SI [(match_operand:DF 1 "arc_double_register_operand" "D")]
164			    VUNSPEC_ARC_LR_HIGH ))]
165 "TARGET_DPFP && !TARGET_DPFP_DISABLE_LRSR"
166"lr %0, [%1h] ; *lr_double_higher"
167[(set_attr "length" "8")
168(set_attr "type" "lr")]
169)
170
171(define_insn "*dexcl_3op_peep2_insn"
172  [(set (match_operand:SI 0 "dest_reg_operand" "=r") ; not register_operand, to accept SUBREG
173	(unspec_volatile:SI
174	 [(match_operand:SI 1 "shouldbe_register_operand" "r") ; r1
175	  (match_operand:SI 2 "shouldbe_register_operand" "r") ; r0
176	  ] VUNSPEC_ARC_DEXCL ))
177   (clobber (match_operand:DF 3 "arc_double_register_operand" "=&D"))]
178  "TARGET_DPFP"
179  "dexcl%F3 %0, %1, %2"
180  [(set_attr "type" "move")
181   (set_attr "length" "4")]
182)
183
184;; version which will not overwrite operand0
185(define_insn "dexcl_2op"
186  [(set (match_operand:DF 0 "arc_double_register_operand" "=D")
187	(unspec_volatile:DF
188	 [(match_operand:SI 1 "shouldbe_register_operand" "r") ; r1
189	  (match_operand:SI 2 "shouldbe_register_operand" "r") ; r0
190	  ] VUNSPEC_ARC_DEXCL_NORES))
191  ]
192  "TARGET_DPFP"
193  "dexcl%F0 0, %1, %2"
194  [(set_attr "type" "move")
195   (set_attr "length" "4")]
196)
197
198;; dexcl a,b,c pattern generated by the peephole2 above
199(define_insn "*dexcl_3op_peep2_insn_lr"
200  [(parallel [(set (match_operand:SI 0 "register_operand" "=r")
201		   (unspec_volatile:SI [(match_operand:DF 1 "arc_double_register_operand" "=D")] VUNSPEC_ARC_LR ))
202	     (set (match_dup 1) (match_operand:DF 2 "register_operand" "r"))]
203	    )
204  ]
205  "TARGET_DPFP && !TARGET_DPFP_DISABLE_LRSR"
206  "dexcl%F1 %0, %H2, %L2"
207  [(set_attr "type" "move")
208   (set_attr "length" "4")]
209)
210
211
212;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
213;;                             doubles support for ARC
214;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
215
216;; D0 = D1+{reg_pair}2
217;; (define_expand "adddf3"
218;;   [(set (match_operand:DF 0 "arc_double_register_operand"          "")
219;; 	(plus:DF (match_operand:DF 1 "arc_double_register_operand" "")
220;; 		 (match_operand:DF 2 "nonmemory_operand" "")))]
221;;  "TARGET_DPFP"
222;;  " "
223;; )
224;; daddh{0}{1} 0, {reg_pair}2.hi, {reg_pair}2.lo
225;; OR
226;; daddh{0}{1} 0, reg3, limm2.lo
227;; daddh{0}{1} 0, {reg_pair}2.hi, {reg_pair}2.lo  /* operand 4 = 1*/
228;; OR
229;; daddh{0}{1} 0, reg3, limm2.lo /* operand 4 = 0 */
230;;
231(define_insn "adddf3_insn"
232  [(set (match_operand:DF 0 "arc_double_register_operand"          "=D,D")
233	(plus:DF (match_operand:DF 1 "arc_double_register_operand" "D,D")
234		 (match_operand:DF 2 "nonmemory_operand" "!r,G")))
235  (use (match_operand:SI 3 "" "N,r"))
236  (use (match_operand:SI 4 "" "N,Q"))
237  ; Prevent can_combine_p from combining muldf3_insn patterns with
238  ; different USE pairs.
239  (use (match_dup 2))
240  ]
241  "TARGET_DPFP &&
242   !(GET_CODE(operands[2]) == CONST_DOUBLE && GET_CODE(operands[3]) == CONST_INT)"
243  "@
244     daddh%F0%F1 0,%H2,%L2
245     daddh%F0%F1 0,%3,%L2"
246  [(set_attr "type" "dpfp_addsub")
247  (set_attr "length" "4,8")])
248
249;; dmulh{0}{1} 0, {reg_pair}2.hi, {reg_pair}2.lo
250;; OR
251;; dmulh{0}{1} 0, reg3, limm2.lo
252;; dmulh{0}{1} 0, {reg_pair}2.hi, {reg_pair}2.lo /* operand 4 = 1*/
253;; OR
254;; dmulh{0}{1} 0, reg3, limm2.lo /* operand 4 = 0*/
255(define_insn "muldf3_insn"
256  [(set (match_operand:DF 0 "arc_double_register_operand"          "=D,D")
257	(mult:DF (match_operand:DF 1 "arc_double_register_operand" "D,D")
258		 (match_operand:DF 2 "nonmemory_operand" "!r,G")))
259  (use (match_operand:SI 3 "" "N,!r"))
260  (use (match_operand:SI 4 "" "N,Q"))
261  ; Prevent can_combine_p from combining muldf3_insn patterns with
262  ; different USE pairs.
263  (use (match_dup 2))
264  ]
265  "TARGET_DPFP &&
266   !(GET_CODE(operands[2]) == CONST_DOUBLE && GET_CODE(operands[3]) == CONST_INT)"
267  "@
268    dmulh%F0%F1 0,%H2,%L2
269    dmulh%F0%F1 0,%3, %L2"
270  [(set_attr "type" "dpfp_mult")
271  (set_attr "length" "4,8")])
272
273;; dsubh{0}{1} 0, {reg_pair}2.hi, {reg_pair}2.lo
274;; OR
275;; dsubh{0}{1} 0, reg3, limm2.lo
276;; OR
277;; drsubh{0}{2} 0, {reg_pair}1.hi, {reg_pair}1.lo
278;; OR
279;; drsubh{0}{2} 0, reg3, limm1.lo
280;; dsubh{0}{1} 0, {reg_pair}2.hi, {reg_pair}2.lo /* operand 4 = 1 */
281;; OR
282;; dsubh{0}{1} 0, reg3, limm2.lo /* operand 4 = 0*/
283;; OR
284;; drsubh{0}{2} 0, {reg_pair}1.hi, {reg_pair}1.lo /* operand 4 = 1 */
285;; OR
286;; drsubh{0}{2} 0, reg3, limm1.lo /* operand 4 = 0*/
287(define_insn "subdf3_insn"
288  [(set (match_operand:DF 0 "arc_double_register_operand"          "=D,D,D,D")
289		   (minus:DF (match_operand:DF 1 "nonmemory_operand" "D,D,!r,G")
290			    (match_operand:DF 2 "nonmemory_operand" "!r,G,D,D")))
291  (use (match_operand:SI 3 "" "N,r,N,r"))
292  (use (match_operand:SI 4 "" "N,Q,N,Q"))
293  ; Prevent can_combine_p from combining muldf3_insn patterns with
294  ; different USE pairs.
295  (use (match_dup 2))]
296  "TARGET_DPFP &&
297   !(GET_CODE(operands[2]) == CONST_DOUBLE && GET_CODE(operands[3]) == CONST_INT) &&
298   !(GET_CODE(operands[1]) == CONST_DOUBLE && GET_CODE(operands[3]) == CONST_INT)"
299  "@
300     dsubh%F0%F1 0,%H2,%L2
301     dsubh%F0%F1 0,%3,%L2
302     drsubh%F0%F2 0,%H1,%L1
303     drsubh%F0%F2 0,%3,%L1"
304  [(set_attr "type" "dpfp_addsub")
305   (set_attr "length" "4,8,4,8")
306   (set_attr "cpu_facility" "*,*,fpx,fpx")])
307
308;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
309;; ;; Peephole for following conversion
310;; ;;                    D0 = D2<op>{reg_pair}3
311;; ;;                    {reg_pair}5 = D0
312;; ;;                    D0 = {reg_pair}6
313;; ;;                            |
314;; ;;                            V
315;; ;;            _________________________________________________________
316;; ;;           / D0             = D2 <op> {regpair3_or_limmreg34}
317;; ;;    ---- +   {reg_pair}5.hi = ( D2<op>{regpair3_or_limmreg34} ).hi
318;; ;;   |       \_________________________________________________________
319;; ;;   |
320;; ;;   |         ________________________________________________________
321;; ;;   |      / {reg_pair}5.lo  = ( D2<op>{regpair3_or_limmreg34} ).lo
322;; ;;   +-----+  D0              = {reg_pair}6
323;; ;;          \ _________________________________________________________
324;; ;;                            ||
325;; ;;                            ||
326;; ;;                            \/
327;; ;;  d<op>{0}{2}h {reg_pair}5.hi, {regpair3_or_limmreg34}.lo, {regpair3_or_limmreg34}.hi
328;; ;;  dexcl{0}    {reg_pair}5.lo, {reg_pair}6.lo, {reg_pair}6.hi
329;; ;; -----------------------------------------------------------------------------------------
330;; ;;  where <op> is one of {+,*,-}
331;; ;;        <opname> is {add,mult,sub}
332;; ;;
333;; ;; NOTE: For rsub insns D2 and {regpair3_or_limmreg34} get interchanged as
334;; ;;       {regpair2_or_limmreg24} and D3
335;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
336;; (define_peephole2
337;;   [(parallel [(set (match_operand:DF 0 "register_operand"          "")
338;; 	(match_operator:DF 1 "arc_dpfp_operator" [(match_operand:DF 2 "nonmemory_operand" "")
339;; 			   (match_operand:DF 3 "nonmemory_operand" "")]))
340;; 	     (use (match_operand:SI 4 "" ""))])
341;;   (set (match_operand:DF 5 "register_operand" "")
342;;        (match_dup 0))
343;;   (set (match_dup 0)
344;;        (match_operand:DF 6 "register_operand" ""))
345;;   ]
346;;   "TARGET_DPFP"
347;;   [
348;;   (parallel [(set (match_dup 0)
349;; 		  (match_op_dup:DF 1 [(match_dup 2)
350;; 				   (match_dup 3)]))
351;; 	    (use (match_dup 4))
352;;             (set (match_dup 5)
353;; 		 (match_op_dup:DF  1 [(match_dup 2)
354;; 				   (match_dup 3)]))])
355;;   (parallel [
356;; ;;	    (set (subreg:SI (match_dup 5) 0)
357;; 	    (set (match_dup 7)
358;; 		 (unspec_volatile [(match_dup 0)] VUNSPEC_ARC_LR ))
359;; 	    (set (match_dup 0) (match_dup 6))]
360;; 	    )
361;;   ]
362;;   "operands[7] = simplify_gen_subreg(SImode,operands[5],DFmode,0);"
363;;   )
364;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
365;; Peephole for following conversion
366;;                    D0 = D2<op>{reg_pair}3
367;;                    {reg_pair}6 = D0
368;;                    D0 = {reg_pair}7
369;;                            |
370;;                            V
371;;            _________________________________________________________
372;;           / D0             = D2 <op> {regpair3_or_limmreg34}
373;;    ---- +   {reg_pair}6.hi = ( D2<op>{regpair3_or_limmreg34} ).hi
374;;   |       \_________________________________________________________
375;;   |
376;;   |         ________________________________________________________
377;;   |      / {reg_pair}6.lo  = ( D2<op>{regpair3_or_limmreg34} ).lo
378;;   +-----+  D0              = {reg_pair}7
379;;          \ _________________________________________________________
380;;                            ||
381;;                            ||
382;;                            \/
383;;  d<op>{0}{2}h {reg_pair}6.hi, {regpair3_or_limmreg34}.lo, {regpair3_or_limmreg34}.hi
384;;  dexcl{0}    {reg_pair}6.lo, {reg_pair}7.lo, {reg_pair}7.hi
385;; -----------------------------------------------------------------------------------------
386;;  where <op> is one of {+,*,-}
387;;        <opname> is {add,mult,sub}
388;;
389;; NOTE: For rsub insns D2 and {regpair3_or_limmreg34} get interchanged as
390;;       {regpair2_or_limmreg24} and D3
391;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
392(define_peephole2
393  [(parallel [(set (match_operand:DF 0 "register_operand"          "")
394	(match_operator:DF 1 "arc_dpfp_operator" [(match_operand:DF 2 "nonmemory_operand" "")
395			   (match_operand:DF 3 "nonmemory_operand" "")]))
396	     (use (match_operand:SI 4 "" ""))
397	     (use (match_operand:SI 5 "" ""))
398	     (use (match_operand:SI 6 "" ""))])
399  (set (match_operand:DF 7 "register_operand" "")
400       (match_dup 0))
401  (set (match_dup 0)
402       (match_operand:DF 8 "register_operand" ""))
403  ]
404  "TARGET_DPFP && !TARGET_DPFP_DISABLE_LRSR"
405  [
406  (parallel [(set (match_dup 0)
407		  (match_op_dup:DF 1 [(match_dup 2)
408				   (match_dup 3)]))
409	    (use (match_dup 4))
410	    (use (match_dup 5))
411            (set (match_dup 7)
412		 (match_op_dup:DF  1 [(match_dup 2)
413				   (match_dup 3)]))])
414  (parallel [
415;;	    (set (subreg:SI (match_dup 7) 0)
416	    (set (match_dup 9)
417		 (unspec_volatile:SI [(match_dup 0)] VUNSPEC_ARC_LR ))
418	    (set (match_dup 0) (match_dup 8))]
419	    )
420  ]
421  "operands[9] = simplify_gen_subreg(SImode,operands[7],DFmode,0);"
422  )
423
424;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
425;; ;; Peephole to generate d<opname>{ij}h a,b,c instructions
426;; ;;                    D0 = D2<op>{reg_pair}3
427;; ;;                    {reg_pair}5 = D0
428;; ;;                            |
429;; ;;                            V
430;; ;;            __________________________________________
431;; ;;           / D0             = D2 <op> {regpair3_or_limmreg34}
432;; ;;    ---- +   {reg_pair}5.hi = ( D2<op>{regpair3_or_limmreg34} ).hi
433;; ;;   |       \__________________________________________
434;; ;;   |
435;; ;;   + ---    {reg_pair}5.lo     = ( D2<op>{regpair3_or_limmreg34} ).lo
436;; ;;                            ||
437;; ;;                            ||
438;; ;;                            \/
439;; ;;  d<op>{0}{2}h {reg_pair}4.hi, {regpair3_or_limmreg34}.lo, {regpair3_or_limmreg34}.hi
440;; ;;  lr    {reg_pair}4.lo, {D2l}
441;; ;; ----------------------------------------------------------------------------------------
442;; ;;  where <op> is one of {+,*,-}
443;; ;;        <opname> is {add,mult,sub}
444;; ;;
445;; ;; NOTE: For rsub insns D2 and {regpair3_or_limmreg34} get interchanged as
446;; ;;       {regpair2_or_limmreg24} and D3
447;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
448;; (define_peephole2
449;;   [(parallel [(set (match_operand:DF 0 "register_operand"          "")
450;; 		   (match_operator:DF 1 "arc_dpfp_operator" [(match_operand:DF 2 "nonmemory_operand" "")
451;; 				      (match_operand:DF 3 "nonmemory_operand" "")]))
452;; 	     (use (match_operand:SI 4 "" ""))])
453;;   (set (match_operand:DF 5 "register_operand" "")
454;;        (match_dup 0))
455;;   ]
456;;   "TARGET_DPFP"
457;;   [
458;;   (parallel [(set (match_dup 0)
459;; 		  (match_op_dup:DF 1 [(match_dup 2)
460;; 				   (match_dup 3)]))
461;; 	    (use (match_dup 4))
462;;             (set (match_dup 5)
463;; 		 (match_op_dup:DF  1 [(match_dup 2)
464;; 				   (match_dup 3)]))])
465;; ;  (set (subreg:SI (match_dup 5) 0)
466;;   (set (match_dup 6)
467;;        (unspec_volatile [(match_dup 0)] VUNSPEC_ARC_LR ))
468;;   ]
469;;   "operands[6] = simplify_gen_subreg(SImode,operands[5],DFmode,0);"
470;;   )
471;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
472;; Peephole to generate d<opname>{ij}h a,b,c instructions
473;;                    D0 = D2<op>{reg_pair}3
474;;                    {reg_pair}6 = D0
475;;                            |
476;;                            V
477;;            __________________________________________
478;;           / D0             = D2 <op> {regpair3_or_limmreg34}
479;;    ---- +   {reg_pair}6.hi = ( D2<op>{regpair3_or_limmreg34} ).hi
480;;   |       \__________________________________________
481;;   |
482;;   + ---    {reg_pair}6.lo     = ( D2<op>{regpair3_or_limmreg34} ).lo
483;;                            ||
484;;                            ||
485;;                            \/
486;;  d<op>{0}{2}h {reg_pair}4.hi, {regpair3_or_limmreg34}.lo, {regpair3_or_limmreg34}.hi
487;;  lr    {reg_pair}4.lo, {D2l}
488;; ----------------------------------------------------------------------------------------
489;;  where <op> is one of {+,*,-}
490;;        <opname> is {add,mult,sub}
491;;
492;; NOTE: For rsub insns D2 and {regpair3_or_limmreg34} get interchanged as
493;;       {regpair2_or_limmreg24} and D3
494;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
495(define_peephole2
496  [(parallel [(set (match_operand:DF 0 "register_operand"          "")
497		   (match_operator:DF 1 "arc_dpfp_operator" [(match_operand:DF 2 "nonmemory_operand" "")
498				      (match_operand:DF 3 "nonmemory_operand" "")]))
499	     (use (match_operand:SI 4 "" ""))
500	     (use (match_operand:SI 5 "" ""))
501	     (use (match_operand:SI 6 "" ""))])
502  (set (match_operand:DF 7 "register_operand" "")
503       (match_dup 0))
504  ]
505  "TARGET_DPFP  && !TARGET_DPFP_DISABLE_LRSR"
506  [
507  (parallel [(set (match_dup 0)
508		  (match_op_dup:DF 1 [(match_dup 2)
509				   (match_dup 3)]))
510	    (use (match_dup 4))
511	    (use (match_dup 5))
512            (set (match_dup 7)
513		 (match_op_dup:DF  1 [(match_dup 2)
514				   (match_dup 3)]))])
515;  (set (subreg:SI (match_dup 7) 0)
516  (set (match_dup 8)
517       (unspec_volatile:SI [(match_dup 0)] VUNSPEC_ARC_LR ))
518  ]
519  "operands[8] = simplify_gen_subreg(SImode,operands[7],DFmode,0);"
520  )
521
522;; ;;            _______________________________________________________
523;; ;;           / D0             = D1 + {regpair2_or_limmreg23}
524;; ;;         +   {reg_pair}4.hi = ( D1 + {regpair2_or_limmreg23} ).hi
525;; ;;           \_______________________________________________________
526;; (define_insn "*daddh_peep2_insn"
527;;   [(parallel [(set (match_operand:DF 0 "arc_double_register_operand" "=D,D")
528;; 		   (plus:DF (match_operand:DF 1 "arc_double_register_operand" "D,D")
529;; 			    (match_operand:DF 2 "nonmemory_operand" "r,G")))
530;; 	     (use (match_operand:SI 3 "" "N,r"))
531;; 	     (set (match_operand:DF 4 "register_operand" "=r,r")
532;; 		  (plus:DF (match_dup 1)
533;; 			   (match_dup 2)))])]
534;;  "TARGET_DPFP"
535;;  "@
536;;     daddh%F0%F1 %H4, %H2, %L2
537;;     daddh%F0%F1 %H4, %3, %L2"
538;;  [(set_attr "type" "dpfp_addsub")
539;;  (set_attr "length" "4,8")]
540;; )
541;;            _______________________________________________________
542;;           / D0             = D1 + {regpair2_or_limmreg23}
543;;         +   {reg_pair}5.hi = ( D1 + {regpair2_or_limmreg23} ).hi
544;;           \_______________________________________________________
545(define_insn "*daddh_peep2_insn"
546  [(parallel [(set (match_operand:DF 0 "arc_double_register_operand" "=D,D")
547		   (plus:DF (match_operand:DF 1 "arc_double_register_operand" "D,D")
548			    (match_operand:DF 2 "nonmemory_operand" "r,G")))
549	     (use (match_operand:SI 3 "" "N,r"))
550	     (use (match_operand:SI 4 "" "N,Q"))
551	     (use (match_operand:SI 5 "" ""))
552	     (set (match_operand:DF 6 "register_operand" "=r,r")
553		  (plus:DF (match_dup 1)
554			   (match_dup 2)))])]
555 "TARGET_DPFP &&
556   !(GET_CODE(operands[2]) == CONST_DOUBLE && GET_CODE(operands[3]) == CONST_INT)"
557 "@
558    daddh%F0%F1 %H6, %H2, %L2
559    daddh%F0%F1 %H6, %3, %L2"
560 [(set_attr "type" "dpfp_addsub")
561 (set_attr "length" "4,8")]
562)
563
564;;            _______________________________________________________
565;;           / D0             = D1 * {regpair2_or_limmreg23}
566;;         +   {reg_pair}5.hi = ( D1 * {regpair2_or_limmreg23} ).hi
567;;           \_______________________________________________________
568(define_insn "*dmulh_peep2_insn"
569  [(parallel [(set (match_operand:DF 0 "arc_double_register_operand" "=D,D")
570		   (mult:DF (match_operand:DF 1 "arc_double_register_operand" "D,D")
571			    (match_operand:DF 2 "nonmemory_operand" "r,G")))
572	     (use (match_operand:SI 3 "" "N,r"))
573	     (use (match_operand:SI 4 "" "N,Q"))
574	     (use (match_operand:SI 5 "" ""))
575	     (set (match_operand:DF 6 "register_operand" "=r,r")
576		  (mult:DF (match_dup 1)
577				      (match_dup 2)))])]
578 "TARGET_DPFP &&
579   !(GET_CODE(operands[2]) == CONST_DOUBLE && GET_CODE(operands[3]) == CONST_INT)"
580 "@
581    dmulh%F0%F1 %H6, %H2, %L2
582    dmulh%F0%F1 %H6, %3, %L2"
583 [(set_attr "type" "dpfp_mult")
584 (set_attr "length" "4,8")]
585)
586
587;;            _______________________________________________________
588;;           / D0             = D1 - {regpair2_or_limmreg23}
589;;         +   {reg_pair}5.hi = ( D1 - {regpair2_or_limmreg23} ).hi
590;;           \_______________________________________________________
591;;  OR
592;;            _______________________________________________________
593;;           / D0             = {regpair1_or_limmreg13} - D2
594;;         +   {reg_pair}5.hi = ( {regpair1_or_limmreg13} ).hi - D2
595;;           \_______________________________________________________
596(define_insn "*dsubh_peep2_insn"
597  [(parallel [(set (match_operand:DF 0 "arc_double_register_operand" "=D,D,D,D")
598		   (minus:DF (match_operand:DF 1 "nonmemory_operand" "D,D,r,G")
599			     (match_operand:DF 2 "nonmemory_operand" "r,G,D,D")))
600	     (use (match_operand:SI 3 "" "N,r,N,r"))
601	     (use (match_operand:SI 4 "" "N,Q,N,Q"))
602	     (use (match_operand:SI 5 "" ""))
603	     (set (match_operand:DF 6 "register_operand" "=r,r,r,r")
604		  (minus:DF (match_dup 1)
605				      (match_dup 2)))])]
606 "TARGET_DPFP &&
607   !(GET_CODE(operands[2]) == CONST_DOUBLE && GET_CODE(operands[3]) == CONST_INT)  &&
608   !(GET_CODE(operands[1]) == CONST_DOUBLE && GET_CODE(operands[3]) == CONST_INT)"
609 "@
610  dsubh%F0%F1 %H6, %H2, %L2
611  dsubh%F0%F1 %H6, %3, %L2
612  drsubh%F0%F2 %H6, %H1, %L1
613  drsubh%F0%F2 %H6, %3, %L1"
614 [(set_attr "type" "dpfp_addsub")
615  (set_attr "length" "4,8,4,8")
616  (set_attr "cpu_facility" "*,*,fpx,fpx")])
617
618;; Intel QUARK SE extensions
619(define_mode_iterator QUARK_CMP [CC_FP_GT CC_FP_GE])
620(define_mode_attr quark_cmp [(CC_FP_GT "gt") (CC_FP_GE "ge")])
621
622(define_expand "cmp_quark"
623  [(parallel [(set (match_operand 0 "")
624		   (match_operand 1 ""))
625	      (clobber (match_scratch:SI 2 ""))])]
626  ""
627  "")
628
629(define_insn "*cmpsf_quark_<quark_cmp>"
630  [(set (reg:QUARK_CMP CC_REG)
631	(compare:QUARK_CMP (match_operand:SF 0 "register_operand" "r")
632			   (match_operand:SF 1 "register_operand" "r")))
633   (clobber (match_scratch:SI 2 "=&r"))]
634  "TARGET_FPX_QUARK"
635  "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"
636  [(set_attr "length" "16")
637   (set_attr "cond" "set")
638   (set_attr "predicable" "no")
639   (set_attr "cond" "nocond")])
640
641(define_insn "*cmpsf_quark_ord"
642  [(set (reg:CC_FP_ORD CC_REG)
643	(compare:CC_FP_ORD (match_operand:SF 0 "register_operand" "r")
644			   (match_operand:SF 1 "register_operand" "r")))
645   (clobber (match_scratch:SI 2 "=&r"))]
646  "TARGET_FPX_QUARK"
647  "dsp_fp_cmp\\t%2,%0,%1\\n\\tadd.f\\t%2,%2,-8"
648  [(set_attr "length" "8")
649   (set_attr "cond" "set")
650   (set_attr "predicable" "no")
651   (set_attr "cond" "nocond")])
652
653(define_insn "*cmpsf_quark_uneq"
654  [(set (reg:CC_FP_UNEQ CC_REG)
655	(compare:CC_FP_UNEQ (match_operand:SF 0 "register_operand" "r")
656			    (match_operand:SF 1 "register_operand" "r")))
657   (clobber (match_scratch:SI 2 "=&r"))]
658  "TARGET_FPX_QUARK"
659  "dsp_fp_cmp\\t%2,%0,%1\\n\\ttst\\t%2,6"
660  [(set_attr "length" "8")
661   (set_attr "cond" "set")
662   (set_attr "predicable" "no")
663   (set_attr "cond" "nocond")])
664
665(define_insn "*cmpsf_quark_eq"
666  [(set (reg:CC_Z CC_REG)
667	(compare:CC_Z (match_operand:SF 0 "register_operand" "r")
668		      (match_operand:SF 1 "register_operand" "r")))
669   (clobber (match_scratch:SI 2 "=&r"))]
670  "TARGET_FPX_QUARK"
671  "dsp_fp_cmp\\t%2,%0,%1\\n\\ttst\\t%2,0x0E"
672  [(set_attr "length" "8")
673   (set_attr "cond" "set")
674   (set_attr "predicable" "no")
675   (set_attr "cond" "nocond")])
676
677(define_insn "*divsf3_quark"
678  [(set (match_operand:SF 0 "register_operand"        "=r")
679	(div:SF (match_operand:SF 1 "register_operand" "r")
680		(match_operand:SF 2 "register_operand" "r")))]
681  "TARGET_FPX_QUARK"
682  "dsp_fp_div\\t%0,%1,%2"
683  [(set_attr "length" "4")
684   (set_attr "predicable" "no")
685   (set_attr "cond" "nocond")])
686
687(define_insn "*sqrtsf2_quark"
688  [(set (match_operand:SF 0 "register_operand"          "=r")
689	(sqrt:SF (match_operand:SF 1 "register_operand" "r")))]
690  "TARGET_FPX_QUARK"
691  "dsp_fp_sqrt\\t%0,%1"
692  [(set_attr "length" "4")
693   (set_attr "predicable" "no")
694   (set_attr "cond" "nocond")])
695
696;; SF->SI (using rounding towards zero)
697(define_insn "*fix_truncsfsi2_quark"
698  [(set (match_operand:SI 0 "register_operand"                "=r")
699	(fix:SI (fix:SF (match_operand:SF 1 "register_operand" "r"))))]
700  "TARGET_FPX_QUARK"
701  "dsp_fp_flt2i\\t%0,%1"
702  [(set_attr "length" "4")
703   (set_attr "predicable" "no")
704   (set_attr "cond" "nocond")])
705
706;; SI->SF
707(define_insn "*floatsisf2_quark"
708  [(set (match_operand:SF 0 "register_operand"          "=r")
709	(float:SF (match_operand:SI 1 "register_operand" "r")))]
710  "TARGET_FPX_QUARK"
711  "dsp_fp_i2flt\\t%0,%1"
712  [(set_attr "length" "4")
713   (set_attr "predicable" "no")
714   (set_attr "cond" "nocond")])
715
716