Reverting merge from trunk
[official-gcc.git] / gcc / config / arc / fpx.md
blob10a5dcd3b66a447dc3c36e7c4f377fc75b56443d
1 ;; Machine description of the Synopsys DesignWare ARC cpu Floating Point
2 ;; extensions for GNU C compiler
3 ;; Copyright (C) 2007-2013 Free Software Foundation, Inc.
5 ;; This file is part of GCC.
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.
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.
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/>.
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")
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")
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")
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")
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")
51 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
53 (define_insn "addsf3"
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,%S1,%2
63    fadd   %0,%1,%S2
64    fadd%? %0,%1,%S2"
65   [(set_attr "type" "spfp")
66   (set_attr "length" "4,4,8,8,8")])
68 (define_insn "subsf3"
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,%S1,%2
78    fsub   %0,%1,%S2
79    fsub%? %0,%1,%S2"
80   [(set_attr "type" "spfp")
81   (set_attr "length" "4,4,8,8,8")])
83 (define_insn "mulsf3"
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,%S1,%2
93    fmul   %0,%1,%S2
94    fmul%? %0,%1,%S2"
95   [(set_attr "type" "spfp")
96   (set_attr "length" "4,4,8,8,8")])
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.
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")])
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")])
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")])
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")])
149 ;; DPFP instructions begin...
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_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")]
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")] VUNSPEC_LR_HIGH ))]
164  "TARGET_DPFP && !TARGET_DPFP_DISABLE_LRSR"
165 "lr %0, [%1h] ; *lr_double_higher"
166 [(set_attr "length" "8")
167 (set_attr "type" "lr")]
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:DF 1 "arc_double_register_operand" "D")
175                                         (match_operand:SI 2 "shouldbe_register_operand" "r")  ; r1
176                                         (match_operand:SI 3 "shouldbe_register_operand" "r") ; r0
177                                         ] VUNSPEC_DEXCL ))
178   ]
179   "TARGET_DPFP"
180   "dexcl%F1 %0, %2, %3"
181   [(set_attr "type" "move")
182    (set_attr "length" "4")]
185 ;; version which will not overwrite operand0
186 (define_insn "*dexcl_3op_peep2_insn_nores"
187   [   (unspec_volatile:SI [
188                                         (match_operand:DF 0 "arc_double_register_operand" "D")
189                                         (match_operand:SI 1 "shouldbe_register_operand" "r")  ; r1
190                                         (match_operand:SI 2 "shouldbe_register_operand" "r") ; r0
191                                         ] VUNSPEC_DEXCL_NORES )
192   ]
193   "TARGET_DPFP"
194   "dexcl%F0 0, %1, %2"
195   [(set_attr "type" "move")
196    (set_attr "length" "4")]
199 ;; dexcl a,b,c pattern generated by the peephole2 above
200 (define_insn "*dexcl_3op_peep2_insn_lr"
201   [(parallel [(set (match_operand:SI 0 "register_operand" "=r")
202                    (unspec_volatile:SI [(match_operand:DF 1 "arc_double_register_operand" "=D")] VUNSPEC_LR ))
203              (set (match_dup 1) (match_operand:DF 2 "register_operand" "r"))]
204             )
205   ]
206   "TARGET_DPFP && !TARGET_DPFP_DISABLE_LRSR"
207   "dexcl%F1 %0, %H2, %L2"
208   [(set_attr "type" "move")
209    (set_attr "length" "4")]
213 ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
214 ;;                             doubles support for ARC
215 ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
217 ;; D0 = D1+{reg_pair}2
218 ;; (define_expand "adddf3"
219 ;;   [(set (match_operand:DF 0 "arc_double_register_operand"          "")
220 ;;      (plus:DF (match_operand:DF 1 "arc_double_register_operand" "")
221 ;;               (match_operand:DF 2 "nonmemory_operand" "")))]
222 ;;  "TARGET_DPFP"
223 ;;  " "
224 ;; )
225 ;; daddh{0}{1} 0, {reg_pair}2.hi, {reg_pair}2.lo
226 ;; OR
227 ;; daddh{0}{1} 0, reg3, limm2.lo
228 (define_expand "adddf3"
229   [(set (match_operand:DF 0 "arc_double_register_operand"          "")
230         (plus:DF (match_operand:DF 1 "arc_double_register_operand" "")
231                  (match_operand:DF 2 "nonmemory_operand" "")))
232      ]
233  "TARGET_DPFP"
234  " if (GET_CODE (operands[2]) == CONST_DOUBLE)
235      {
236         rtx high, low, tmp;
237         split_double (operands[2], &low, &high);
238         tmp = force_reg (SImode, high);
239         emit_insn(gen_adddf3_insn(operands[0], operands[1], operands[2],tmp,const0_rtx));
240      }
241    else
242      emit_insn(gen_adddf3_insn(operands[0], operands[1], operands[2],const1_rtx,const1_rtx));
243      DONE;
247 ;; daddh{0}{1} 0, {reg_pair}2.hi, {reg_pair}2.lo  /* operand 4 = 1*/
248 ;; OR
249 ;; daddh{0}{1} 0, reg3, limm2.lo /* operand 4 = 0 */
251 (define_insn "adddf3_insn"
252   [(set (match_operand:DF 0 "arc_double_register_operand"          "=D,D")
253         (plus:DF (match_operand:DF 1 "arc_double_register_operand" "D,D")
254                  (match_operand:DF 2 "nonmemory_operand" "!r,G")))
255   (use (match_operand:SI 3 "" "N,r"))
256   (use (match_operand:SI 4 "" "N,Q"))
257   ; Prevent can_combine_p from combining muldf3_insn patterns with
258   ; different USE pairs.
259   (use (match_dup 2))
260   ]
261   "TARGET_DPFP &&
262    !(GET_CODE(operands[2]) == CONST_DOUBLE && GET_CODE(operands[3]) == CONST_INT)"
263   "@
264      daddh%F0%F1 0,%H2,%L2
265      daddh%F0%F1 0,%3,%L2"
266   [(set_attr "type" "dpfp_addsub")
267   (set_attr "length" "4,8")])
269 ;; dmulh{0}{1} 0, {reg_pair}2.hi, {reg_pair}2.lo
270 ;; OR
271 ;; dmulh{0}{1} 0, reg3, limm2.lo
272 (define_expand "muldf3"
273   [(set (match_operand:DF 0 "arc_double_register_operand"          "")
274         (mult:DF (match_operand:DF 1 "arc_double_register_operand" "")
275                  (match_operand:DF 2 "nonmemory_operand" "")))]
276 "TARGET_DPFP"
277 "  if (GET_CODE (operands[2]) == CONST_DOUBLE)
278      {
279         rtx high, low, tmp;
280         split_double (operands[2], &low, &high);
281         tmp = force_reg (SImode, high);
282         emit_insn(gen_muldf3_insn(operands[0], operands[1], operands[2],tmp,const0_rtx));
283      }
284    else
285      emit_insn(gen_muldf3_insn(operands[0], operands[1], operands[2],const1_rtx,const1_rtx));
287   DONE;
288  ")
291 ;; dmulh{0}{1} 0, {reg_pair}2.hi, {reg_pair}2.lo /* operand 4 = 1*/
292 ;; OR
293 ;; dmulh{0}{1} 0, reg3, limm2.lo /* operand 4 = 0*/
294 (define_insn "muldf3_insn"
295   [(set (match_operand:DF 0 "arc_double_register_operand"          "=D,D")
296         (mult:DF (match_operand:DF 1 "arc_double_register_operand" "D,D")
297                  (match_operand:DF 2 "nonmemory_operand" "!r,G")))
298   (use (match_operand:SI 3 "" "N,!r"))
299   (use (match_operand:SI 4 "" "N,Q"))
300   ; Prevent can_combine_p from combining muldf3_insn patterns with
301   ; different USE pairs.
302   (use (match_dup 2))
303   ]
304   "TARGET_DPFP &&
305    !(GET_CODE(operands[2]) == CONST_DOUBLE && GET_CODE(operands[3]) == CONST_INT)"
306   "@
307     dmulh%F0%F1 0,%H2,%L2
308     dmulh%F0%F1 0,%3, %L2"
309   [(set_attr "type" "dpfp_mult")
310   (set_attr "length" "4,8")])
312 ;; dsubh{0}{1} 0, {reg_pair}2.hi, {reg_pair}2.lo
313 ;; OR
314 ;; dsubh{0}{1} 0, reg3, limm2.lo
315 ;; OR
316 ;; drsubh{0}{2} 0, {reg_pair}1.hi, {reg_pair}1.lo
317 ;; OR
318 ;; drsubh{0}{2} 0, reg3, limm1.lo
319 (define_expand "subdf3"
320   [(set (match_operand:DF 0 "arc_double_register_operand"          "")
321                     (minus:DF (match_operand:DF 1 "nonmemory_operand" "")
322                                   (match_operand:DF 2 "nonmemory_operand" "")))]
323 "TARGET_DPFP"
324 "   if (GET_CODE (operands[1]) == CONST_DOUBLE || GET_CODE (operands[2]) == CONST_DOUBLE)
325      {
326         rtx high, low, tmp;
327         int const_index = ((GET_CODE (operands[1]) == CONST_DOUBLE) ? 1: 2);
328         split_double (operands[const_index], &low, &high);
329         tmp = force_reg (SImode, high);
330         emit_insn(gen_subdf3_insn(operands[0], operands[1], operands[2],tmp,const0_rtx));
331      }
332    else
333      emit_insn(gen_subdf3_insn(operands[0], operands[1], operands[2],const1_rtx,const1_rtx));
335    DONE;
336   "
339 ;; dsubh{0}{1} 0, {reg_pair}2.hi, {reg_pair}2.lo /* operand 4 = 1 */
340 ;; OR
341 ;; dsubh{0}{1} 0, reg3, limm2.lo /* operand 4 = 0*/
342 ;; OR
343 ;; drsubh{0}{2} 0, {reg_pair}1.hi, {reg_pair}1.lo /* operand 4 = 1 */
344 ;; OR
345 ;; drsubh{0}{2} 0, reg3, limm1.lo /* operand 4 = 0*/
346 (define_insn "subdf3_insn"
347   [(set (match_operand:DF 0 "arc_double_register_operand"          "=D,D,D,D")
348                    (minus:DF (match_operand:DF 1 "nonmemory_operand" "D,D,!r,G")
349                             (match_operand:DF 2 "nonmemory_operand" "!r,G,D,D")))
350   (use (match_operand:SI 3 "" "N,r,N,r"))
351   (use (match_operand:SI 4 "" "N,Q,N,Q"))
352   ; Prevent can_combine_p from combining muldf3_insn patterns with
353   ; different USE pairs.
354   (use (match_dup 2))]
355   "TARGET_DPFP &&
356    !(GET_CODE(operands[2]) == CONST_DOUBLE && GET_CODE(operands[3]) == CONST_INT) &&
357    !(GET_CODE(operands[1]) == CONST_DOUBLE && GET_CODE(operands[3]) == CONST_INT)"
358   "@
359      dsubh%F0%F1 0,%H2,%L2
360      dsubh%F0%F1 0,%3,%L2
361      drsubh%F0%F2 0,%H1,%L1
362      drsubh%F0%F2 0,%3,%L1"
363   [(set_attr "type" "dpfp_addsub")
364   (set_attr "length" "4,8,4,8")])
366 ;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
367 ;; ;; Peephole for following conversion
368 ;; ;;                    D0 = D2<op>{reg_pair}3
369 ;; ;;                    {reg_pair}5 = D0
370 ;; ;;                    D0 = {reg_pair}6
371 ;; ;;                            |
372 ;; ;;                            V
373 ;; ;;            _________________________________________________________
374 ;; ;;           / D0             = D2 <op> {regpair3_or_limmreg34}
375 ;; ;;    ---- +   {reg_pair}5.hi = ( D2<op>{regpair3_or_limmreg34} ).hi
376 ;; ;;   |       \_________________________________________________________
377 ;; ;;   |
378 ;; ;;   |         ________________________________________________________
379 ;; ;;   |      / {reg_pair}5.lo  = ( D2<op>{regpair3_or_limmreg34} ).lo
380 ;; ;;   +-----+  D0              = {reg_pair}6
381 ;; ;;          \ _________________________________________________________
382 ;; ;;                            ||
383 ;; ;;                            ||
384 ;; ;;                            \/
385 ;; ;;  d<op>{0}{2}h {reg_pair}5.hi, {regpair3_or_limmreg34}.lo, {regpair3_or_limmreg34}.hi
386 ;; ;;  dexcl{0}    {reg_pair}5.lo, {reg_pair}6.lo, {reg_pair}6.hi
387 ;; ;; -----------------------------------------------------------------------------------------
388 ;; ;;  where <op> is one of {+,*,-}
389 ;; ;;        <opname> is {add,mult,sub}
390 ;; ;;
391 ;; ;; NOTE: For rsub insns D2 and {regpair3_or_limmreg34} get interchanged as
392 ;; ;;       {regpair2_or_limmreg24} and D3
393 ;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
394 ;; (define_peephole2
395 ;;   [(parallel [(set (match_operand:DF 0 "register_operand"          "")
396 ;;      (match_operator:DF 1 "arc_dpfp_operator" [(match_operand:DF 2 "nonmemory_operand" "")
397 ;;                         (match_operand:DF 3 "nonmemory_operand" "")]))
398 ;;           (use (match_operand:SI 4 "" ""))])
399 ;;   (set (match_operand:DF 5 "register_operand" "")
400 ;;        (match_dup 0))
401 ;;   (set (match_dup 0)
402 ;;        (match_operand:DF 6 "register_operand" ""))
403 ;;   ]
404 ;;   "TARGET_DPFP"
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 ;;             (set (match_dup 5)
411 ;;               (match_op_dup:DF  1 [(match_dup 2)
412 ;;                                 (match_dup 3)]))])
413 ;;   (parallel [
414 ;; ;;       (set (subreg:SI (match_dup 5) 0)
415 ;;          (set (match_dup 7)
416 ;;               (unspec_volatile [(match_dup 0)] VUNSPEC_LR ))
417 ;;          (set (match_dup 0) (match_dup 6))]
418 ;;          )
419 ;;   ]
420 ;;   "operands[7] = simplify_gen_subreg(SImode,operands[5],DFmode,0);"
421 ;;   )
422 ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
423 ;; Peephole for following conversion
424 ;;                    D0 = D2<op>{reg_pair}3
425 ;;                    {reg_pair}6 = D0
426 ;;                    D0 = {reg_pair}7
427 ;;                            |
428 ;;                            V
429 ;;            _________________________________________________________
430 ;;           / D0             = D2 <op> {regpair3_or_limmreg34}
431 ;;    ---- +   {reg_pair}6.hi = ( D2<op>{regpair3_or_limmreg34} ).hi
432 ;;   |       \_________________________________________________________
433 ;;   |
434 ;;   |         ________________________________________________________
435 ;;   |      / {reg_pair}6.lo  = ( D2<op>{regpair3_or_limmreg34} ).lo
436 ;;   +-----+  D0              = {reg_pair}7
437 ;;          \ _________________________________________________________
438 ;;                            ||
439 ;;                            ||
440 ;;                            \/
441 ;;  d<op>{0}{2}h {reg_pair}6.hi, {regpair3_or_limmreg34}.lo, {regpair3_or_limmreg34}.hi
442 ;;  dexcl{0}    {reg_pair}6.lo, {reg_pair}7.lo, {reg_pair}7.hi
443 ;; -----------------------------------------------------------------------------------------
444 ;;  where <op> is one of {+,*,-}
445 ;;        <opname> is {add,mult,sub}
447 ;; NOTE: For rsub insns D2 and {regpair3_or_limmreg34} get interchanged as
448 ;;       {regpair2_or_limmreg24} and D3
449 ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
450 (define_peephole2
451   [(parallel [(set (match_operand:DF 0 "register_operand"          "")
452         (match_operator:DF 1 "arc_dpfp_operator" [(match_operand:DF 2 "nonmemory_operand" "")
453                            (match_operand:DF 3 "nonmemory_operand" "")]))
454              (use (match_operand:SI 4 "" ""))
455              (use (match_operand:SI 5 "" ""))
456              (use (match_operand:SI 6 "" ""))])
457   (set (match_operand:DF 7 "register_operand" "")
458        (match_dup 0))
459   (set (match_dup 0)
460        (match_operand:DF 8 "register_operand" ""))
461   ]
462   "TARGET_DPFP && !TARGET_DPFP_DISABLE_LRSR"
463   [
464   (parallel [(set (match_dup 0)
465                   (match_op_dup:DF 1 [(match_dup 2)
466                                    (match_dup 3)]))
467             (use (match_dup 4))
468             (use (match_dup 5))
469             (set (match_dup 7)
470                  (match_op_dup:DF  1 [(match_dup 2)
471                                    (match_dup 3)]))])
472   (parallel [
473 ;;          (set (subreg:SI (match_dup 7) 0)
474             (set (match_dup 9)
475                  (unspec_volatile:SI [(match_dup 0)] VUNSPEC_LR ))
476             (set (match_dup 0) (match_dup 8))]
477             )
478   ]
479   "operands[9] = simplify_gen_subreg(SImode,operands[7],DFmode,0);"
480   )
482 ;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
483 ;; ;; Peephole to generate d<opname>{ij}h a,b,c instructions
484 ;; ;;                    D0 = D2<op>{reg_pair}3
485 ;; ;;                    {reg_pair}5 = D0
486 ;; ;;                            |
487 ;; ;;                            V
488 ;; ;;            __________________________________________
489 ;; ;;           / D0             = D2 <op> {regpair3_or_limmreg34}
490 ;; ;;    ---- +   {reg_pair}5.hi = ( D2<op>{regpair3_or_limmreg34} ).hi
491 ;; ;;   |       \__________________________________________
492 ;; ;;   |
493 ;; ;;   + ---    {reg_pair}5.lo     = ( D2<op>{regpair3_or_limmreg34} ).lo
494 ;; ;;                            ||
495 ;; ;;                            ||
496 ;; ;;                            \/
497 ;; ;;  d<op>{0}{2}h {reg_pair}4.hi, {regpair3_or_limmreg34}.lo, {regpair3_or_limmreg34}.hi
498 ;; ;;  lr    {reg_pair}4.lo, {D2l}
499 ;; ;; ----------------------------------------------------------------------------------------
500 ;; ;;  where <op> is one of {+,*,-}
501 ;; ;;        <opname> is {add,mult,sub}
502 ;; ;;
503 ;; ;; NOTE: For rsub insns D2 and {regpair3_or_limmreg34} get interchanged as
504 ;; ;;       {regpair2_or_limmreg24} and D3
505 ;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
506 ;; (define_peephole2
507 ;;   [(parallel [(set (match_operand:DF 0 "register_operand"          "")
508 ;;                 (match_operator:DF 1 "arc_dpfp_operator" [(match_operand:DF 2 "nonmemory_operand" "")
509 ;;                                    (match_operand:DF 3 "nonmemory_operand" "")]))
510 ;;           (use (match_operand:SI 4 "" ""))])
511 ;;   (set (match_operand:DF 5 "register_operand" "")
512 ;;        (match_dup 0))
513 ;;   ]
514 ;;   "TARGET_DPFP"
515 ;;   [
516 ;;   (parallel [(set (match_dup 0)
517 ;;                (match_op_dup:DF 1 [(match_dup 2)
518 ;;                                 (match_dup 3)]))
519 ;;          (use (match_dup 4))
520 ;;             (set (match_dup 5)
521 ;;               (match_op_dup:DF  1 [(match_dup 2)
522 ;;                                 (match_dup 3)]))])
523 ;; ;  (set (subreg:SI (match_dup 5) 0)
524 ;;   (set (match_dup 6)
525 ;;        (unspec_volatile [(match_dup 0)] VUNSPEC_LR ))
526 ;;   ]
527 ;;   "operands[6] = simplify_gen_subreg(SImode,operands[5],DFmode,0);"
528 ;;   )
529 ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
530 ;; Peephole to generate d<opname>{ij}h a,b,c instructions
531 ;;                    D0 = D2<op>{reg_pair}3
532 ;;                    {reg_pair}6 = D0
533 ;;                            |
534 ;;                            V
535 ;;            __________________________________________
536 ;;           / D0             = D2 <op> {regpair3_or_limmreg34}
537 ;;    ---- +   {reg_pair}6.hi = ( D2<op>{regpair3_or_limmreg34} ).hi
538 ;;   |       \__________________________________________
539 ;;   |
540 ;;   + ---    {reg_pair}6.lo     = ( D2<op>{regpair3_or_limmreg34} ).lo
541 ;;                            ||
542 ;;                            ||
543 ;;                            \/
544 ;;  d<op>{0}{2}h {reg_pair}4.hi, {regpair3_or_limmreg34}.lo, {regpair3_or_limmreg34}.hi
545 ;;  lr    {reg_pair}4.lo, {D2l}
546 ;; ----------------------------------------------------------------------------------------
547 ;;  where <op> is one of {+,*,-}
548 ;;        <opname> is {add,mult,sub}
550 ;; NOTE: For rsub insns D2 and {regpair3_or_limmreg34} get interchanged as
551 ;;       {regpair2_or_limmreg24} and D3
552 ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
553 (define_peephole2
554   [(parallel [(set (match_operand:DF 0 "register_operand"          "")
555                    (match_operator:DF 1 "arc_dpfp_operator" [(match_operand:DF 2 "nonmemory_operand" "")
556                                       (match_operand:DF 3 "nonmemory_operand" "")]))
557              (use (match_operand:SI 4 "" ""))
558              (use (match_operand:SI 5 "" ""))
559              (use (match_operand:SI 6 "" ""))])
560   (set (match_operand:DF 7 "register_operand" "")
561        (match_dup 0))
562   ]
563   "TARGET_DPFP  && !TARGET_DPFP_DISABLE_LRSR"
564   [
565   (parallel [(set (match_dup 0)
566                   (match_op_dup:DF 1 [(match_dup 2)
567                                    (match_dup 3)]))
568             (use (match_dup 4))
569             (use (match_dup 5))
570             (set (match_dup 7)
571                  (match_op_dup:DF  1 [(match_dup 2)
572                                    (match_dup 3)]))])
573 ;  (set (subreg:SI (match_dup 7) 0)
574   (set (match_dup 8)
575        (unspec_volatile:SI [(match_dup 0)] VUNSPEC_LR ))
576   ]
577   "operands[8] = simplify_gen_subreg(SImode,operands[7],DFmode,0);"
578   )
580 ;; ;;            _______________________________________________________
581 ;; ;;           / D0             = D1 + {regpair2_or_limmreg23}
582 ;; ;;         +   {reg_pair}4.hi = ( D1 + {regpair2_or_limmreg23} ).hi
583 ;; ;;           \_______________________________________________________
584 ;; (define_insn "*daddh_peep2_insn"
585 ;;   [(parallel [(set (match_operand:DF 0 "arc_double_register_operand" "=D,D")
586 ;;                 (plus:DF (match_operand:DF 1 "arc_double_register_operand" "D,D")
587 ;;                          (match_operand:DF 2 "nonmemory_operand" "r,G")))
588 ;;           (use (match_operand:SI 3 "" "N,r"))
589 ;;           (set (match_operand:DF 4 "register_operand" "=r,r")
590 ;;                (plus:DF (match_dup 1)
591 ;;                         (match_dup 2)))])]
592 ;;  "TARGET_DPFP"
593 ;;  "@
594 ;;     daddh%F0%F1 %H4, %H2, %L2
595 ;;     daddh%F0%F1 %H4, %3, %L2"
596 ;;  [(set_attr "type" "dpfp_addsub")
597 ;;  (set_attr "length" "4,8")]
598 ;; )
599 ;;            _______________________________________________________
600 ;;           / D0             = D1 + {regpair2_or_limmreg23}
601 ;;         +   {reg_pair}5.hi = ( D1 + {regpair2_or_limmreg23} ).hi
602 ;;           \_______________________________________________________
603 (define_insn "*daddh_peep2_insn"
604   [(parallel [(set (match_operand:DF 0 "arc_double_register_operand" "=D,D")
605                    (plus:DF (match_operand:DF 1 "arc_double_register_operand" "D,D")
606                             (match_operand:DF 2 "nonmemory_operand" "r,G")))
607              (use (match_operand:SI 3 "" "N,r"))
608              (use (match_operand:SI 4 "" "N,Q"))
609              (use (match_operand:SI 5 "" ""))
610              (set (match_operand:DF 6 "register_operand" "=r,r")
611                   (plus:DF (match_dup 1)
612                            (match_dup 2)))])]
613  "TARGET_DPFP &&
614    !(GET_CODE(operands[2]) == CONST_DOUBLE && GET_CODE(operands[3]) == CONST_INT)"
615  "@
616     daddh%F0%F1 %H6, %H2, %L2
617     daddh%F0%F1 %H6, %3, %L2"
618  [(set_attr "type" "dpfp_addsub")
619  (set_attr "length" "4,8")]
622 ;;            _______________________________________________________
623 ;;           / D0             = D1 * {regpair2_or_limmreg23}
624 ;;         +   {reg_pair}5.hi = ( D1 * {regpair2_or_limmreg23} ).hi
625 ;;           \_______________________________________________________
626 (define_insn "*dmulh_peep2_insn"
627   [(parallel [(set (match_operand:DF 0 "arc_double_register_operand" "=D,D")
628                    (mult:DF (match_operand:DF 1 "arc_double_register_operand" "D,D")
629                             (match_operand:DF 2 "nonmemory_operand" "r,G")))
630              (use (match_operand:SI 3 "" "N,r"))
631              (use (match_operand:SI 4 "" "N,Q"))
632              (use (match_operand:SI 5 "" ""))
633              (set (match_operand:DF 6 "register_operand" "=r,r")
634                   (mult:DF (match_dup 1)
635                                       (match_dup 2)))])]
636  "TARGET_DPFP &&
637    !(GET_CODE(operands[2]) == CONST_DOUBLE && GET_CODE(operands[3]) == CONST_INT)"
638  "@
639     dmulh%F0%F1 %H6, %H2, %L2
640     dmulh%F0%F1 %H6, %3, %L2"
641  [(set_attr "type" "dpfp_mult")
642  (set_attr "length" "4,8")]
645 ;;            _______________________________________________________
646 ;;           / D0             = D1 - {regpair2_or_limmreg23}
647 ;;         +   {reg_pair}5.hi = ( D1 - {regpair2_or_limmreg23} ).hi
648 ;;           \_______________________________________________________
649 ;;  OR
650 ;;            _______________________________________________________
651 ;;           / D0             = {regpair1_or_limmreg13} - D2
652 ;;         +   {reg_pair}5.hi = ( {regpair1_or_limmreg13} ).hi - D2
653 ;;           \_______________________________________________________
654 (define_insn "*dsubh_peep2_insn"
655   [(parallel [(set (match_operand:DF 0 "arc_double_register_operand" "=D,D,D,D")
656                    (minus:DF (match_operand:DF 1 "nonmemory_operand" "D,D,r,G")
657                              (match_operand:DF 2 "nonmemory_operand" "r,G,D,D")))
658              (use (match_operand:SI 3 "" "N,r,N,r"))
659              (use (match_operand:SI 4 "" "N,Q,N,Q"))
660              (use (match_operand:SI 5 "" ""))
661              (set (match_operand:DF 6 "register_operand" "=r,r,r,r")
662                   (minus:DF (match_dup 1)
663                                       (match_dup 2)))])]
664  "TARGET_DPFP &&
665    !(GET_CODE(operands[2]) == CONST_DOUBLE && GET_CODE(operands[3]) == CONST_INT)  &&
666    !(GET_CODE(operands[1]) == CONST_DOUBLE && GET_CODE(operands[3]) == CONST_INT)"
667  "@
668   dsubh%F0%F1 %H6, %H2, %L2
669   dsubh%F0%F1 %H6, %3, %L2
670   drsubh%F0%F2 %H6, %H1, %L1
671   drsubh%F0%F2 %H6, %3, %L1"
672  [(set_attr "type" "dpfp_addsub")
673   (set_attr "length" "4,8,4,8")]