2018-07-13 Richard Biener <rguenther@suse.de>
[official-gcc.git] / gcc / config / nds32 / nds32-fpu.md
blob9b844021a24f71c940f1f7746dd07353213b2a38
1 ;; Machine description of Andes NDS32 cpu for GNU compiler
2 ;; Copyright (C) 2012-2018 Free Software Foundation, Inc.
3 ;; Contributed by Andes Technology Corporation.
4 ;;
5 ;; This file is part of GCC.
6 ;;
7 ;; GCC is free software; you can redistribute it and/or modify it
8 ;; under the terms of the GNU General Public License as published
9 ;; by the Free Software Foundation; either version 3, or (at your
10 ;; option) any later version.
12 ;; GCC is distributed in the hope that it will be useful, but WITHOUT
13 ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 ;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
15 ;; 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 ;;SFmode moves
23 (define_expand "movsf"
24   [(set (match_operand:SF 0 "general_operand" "")
25         (match_operand:SF 1 "general_operand" ""))]
26   ""
28   /* Need to force register if mem <- !reg.  */
29   if (MEM_P (operands[0]) && !REG_P (operands[1]))
30     operands[1] = force_reg (SFmode, operands[1]);
31   if (CONST_DOUBLE_P (operands[1])
32       && !satisfies_constraint_Cs20 (operands[1]))
33     {
34       const REAL_VALUE_TYPE *r;
35       unsigned long l;
37       r = CONST_DOUBLE_REAL_VALUE (operands[1]);
38       REAL_VALUE_TO_TARGET_SINGLE (*r, l);
40       emit_move_insn (operands[0], gen_rtx_HIGH (SFmode, operands[1]));
42       if ((l & 0xFFF) != 0)
43         emit_insn (gen_movsf_lo (operands[0], operands[0], operands[1]));
44       DONE;
45     }
48 (define_insn "movsf_lo"
49   [(set (match_operand:SF 0 "register_operand" "=r")
50         (lo_sum:SF (match_operand:SF 1 "register_operand" "r")
51                    (match_operand:SF 2 "immediate_operand" "i")))]
52   ""
53   "ori\t%0, %1, lo12(%2)"
54   [(set_attr "type"   "alu")
55    (set_attr "length"   "4")]
58 (define_insn "*movsf"
59   [(set (match_operand:SF 0 "nonimmediate_operand" "=r, r, U45, U33, U37, U45, m,   l,   l,   l,   d, r, f, *f, *r, f, Q,   r,   r,    r")
60         (match_operand:SF 1 "general_operand"      " r, r,   l,   l,   l,   d, r, U45, U33, U37, U45, m, f, *r, *f, Q, f,Cs05,Cs20, Chig"))]
61   "(register_operand(operands[0], SFmode)
62     || register_operand(operands[1], SFmode))"
64   switch (which_alternative)
65     {
66     case 0:
67       return "mov55\t%0, %1";
68     case 1:
69       return "ori\t%0, %1, 0";
70     case 2:
71     case 3:
72     case 4:
73     case 5:
74       return nds32_output_16bit_store (operands, 4);
75     case 6:
76       return nds32_output_32bit_store (operands, 4);
77     case 7:
78     case 8:
79     case 9:
80     case 10:
81       return nds32_output_16bit_load (operands, 4);
82     case 11:
83       return nds32_output_32bit_load (operands, 4);
84     case 12:
85       if (TARGET_FPU_SINGLE)
86         return "fcpyss\t%0, %1, %1";
87       else
88         return "#";
89     case 13:
90       return "fmtsr\t%1, %0";
91     case 14:
92       return "fmfsr\t%0, %1";
93     case 15:
94       return nds32_output_float_load (operands);
95     case 16:
96       return nds32_output_float_store (operands);
97     case 17:
98       return "movi55\t%0, %1";
99     case 18:
100       return "movi\t%0, %1";
101     case 19:
102       return "sethi\t%0, %1";
103     default:
104       gcc_unreachable ();
105     }
107   [(set_attr "type"    "alu,alu,store,store,store,store,store,load,load,load,load,load,fcpy,fmtsr,fmfsr,fload,fstore,alu,alu,alu")
108    (set_attr "length"  "  2,  4,    2,    2,    2,    2,    4,   2,   2,   2,   2,   4,   4,    4,    4,    4,     4,  2,  4,  4")
109    (set_attr "feature" " v1, v1,   v1,   v1,   v1,   v1,   v1,  v1,  v1,  v1,  v1,  v1, fpu,  fpu,  fpu,  fpu,   fpu, v1, v1, v1")])
111 ;; Conditional Move Instructions
113 (define_expand "mov<mode>cc"
114   [(set (match_operand:ANYF 0 "register_operand" "")
115         (if_then_else:ANYF (match_operand 1 "nds32_float_comparison_operator" "")
116                            (match_operand:ANYF 2 "register_operand" "")
117                            (match_operand:ANYF 3 "register_operand" "")))]
118   ""
120   if (nds32_cond_move_p (operands[1]))
121     {
122       /* Operands[1] condition code is UNORDERED or ORDERED, and
123          sub-operands[1] MODE isn't SFmode or SFmode, return FAIL
124          for gcc, because we don't using slt compare instruction
125          to generate UNORDERED and ORDERED condition.  */
126       FAIL;
127     }
128   else
129     nds32_expand_float_movcc (operands);
132 (define_insn "fcmov<mode>_eq"
133   [(set (match_operand:ANYF 0 "register_operand" "=f, f")
134         (if_then_else:ANYF (eq (match_operand:SI 1 "register_operand" "f, f")
135                                (const_int 0))
136                            (match_operand:ANYF 2 "register_operand" "f, 0")
137                            (match_operand:ANYF 3 "register_operand" "0, f")))]
138   ""
139   "@
140    fcmovz<size>\t%0,%2,%1
141    fcmovn<size>\t%0,%3,%1"
142   [(set_attr "type"  "fcmov")
143    (set_attr "length" "4")]
146 (define_insn "fcmov<mode>_ne"
147   [(set (match_operand:ANYF 0 "register_operand" "=f, f")
148         (if_then_else:ANYF (ne (match_operand:SI 1 "register_operand" "f, f")
149                                (const_int 0))
150                            (match_operand:ANYF 2 "register_operand" "f, 0")
151                            (match_operand:ANYF 3 "register_operand" "0, f")))]
152   ""
153   "@
154    fcmovn<size>\t%0,%2,%1
155    fcmovz<size>\t%0,%3,%1"
156   [(set_attr "type"  "fcmov")
157    (set_attr "length" "4")]
160 ;; Arithmetic instructions.
162 (define_insn "add<mode>3"
163   [(set (match_operand:ANYF 0 "register_operand" "=f")
164         (plus:ANYF (match_operand:ANYF 1 "register_operand" "f")
165                    (match_operand:ANYF 2 "register_operand" "f")))]
166   ""
167   "fadd<size>\t %0, %1, %2"
168   [(set_attr "type"   "falu")
169    (set_attr "length" "4")]
172 (define_insn "sub<mode>3"
173   [(set (match_operand:ANYF 0 "register_operand" "=f")
174         (minus:ANYF (match_operand:ANYF 1 "register_operand" "f")
175                     (match_operand:ANYF 2 "register_operand" "f")))]
176   ""
177   "fsub<size>\t %0, %1, %2"
178   [(set_attr "type"   "falu")
179    (set_attr "length" "4")]
182 ;; Multiplication insns.
184 (define_insn "mul<mode>3"
185   [(set (match_operand:ANYF 0 "register_operand" "=f")
186         (mult:ANYF (match_operand:ANYF 1 "register_operand" "f")
187                    (match_operand:ANYF 2 "register_operand" "f")))]
188   ""
189   "fmul<size>\t %0, %1, %2"
190   [(set_attr "type"   "fmul<size>")
191    (set_attr "length" "4")]
194 (define_insn "fma<mode>4"
195   [(set (match_operand:ANYF 0 "register_operand" "=f")
196         (fma:ANYF (match_operand:ANYF 1 "register_operand" "f")
197                   (match_operand:ANYF 2 "register_operand" "f")
198                   (match_operand:ANYF 3 "register_operand" "0")))]
199   "TARGET_EXT_FPU_FMA"
200   "fmadd<size>\t%0, %1, %2"
201   [(set_attr "type"   "fmac<size>")
202    (set_attr "length" "4")]
205 (define_insn "fnma<mode>4"
206   [(set (match_operand:ANYF 0 "register_operand" "=f")
207         (fma:ANYF (neg:ANYF (match_operand:ANYF 1 "register_operand" "f"))
208                   (match_operand:ANYF 2 "register_operand" "f")
209                   (match_operand:ANYF 3 "register_operand" "0")))]
210   "TARGET_EXT_FPU_FMA"
211   "fmsub<size>\t%0, %1, %2"
212   [(set_attr "type"   "fmac<size>")
213    (set_attr "length" "4")]
216 (define_insn "fms<mode>4"
217   [(set (match_operand:ANYF 0 "register_operand" "=f")
218         (fma:ANYF (match_operand:ANYF 1 "register_operand" "f")
219                   (match_operand:ANYF 2 "register_operand" "f")
220                   (neg:ANYF (match_operand:ANYF 3 "register_operand" "0"))))]
221   "TARGET_EXT_FPU_FMA"
222   "fnmsub<size>\t%0, %1, %2"
223   [(set_attr "type"   "fmac<size>")
224    (set_attr "length" "4")]
227 (define_insn "fnms<mode>4"
228   [(set (match_operand:ANYF 0 "register_operand" "=f")
229         (fma:ANYF (neg:ANYF (match_operand:ANYF 1 "register_operand" "f"))
230                   (match_operand:ANYF 2 "register_operand" "f")
231                   (neg:ANYF (match_operand:ANYF 3 "register_operand" "0"))))]
232   "TARGET_EXT_FPU_FMA"
233   "fnmadd<size>\t%0, %1, %2"
234   [(set_attr "type"   "fmac<size>")
235    (set_attr "length" "4")]
238 ;; Div Instructions.
240 (define_insn "div<mode>3"
241   [(set (match_operand:ANYF 0 "register_operand" "=f")
242         (div:ANYF (match_operand:ANYF 1 "register_operand" "f")
243                   (match_operand:ANYF 2 "register_operand" "f")))]
244   ""
245   "fdiv<size>\t %0, %1, %2"
246   [(set_attr "type"   "fdiv<size>")
247    (set_attr "length" "4")]
250 (define_insn "sqrt<mode>2"
251   [(set (match_operand:ANYF 0 "register_operand" "=f")
252         (sqrt:ANYF (match_operand:ANYF 1 "register_operand" "f")))]
253   ""
254   "fsqrt<size>\t %0, %1"
255   [(set_attr "type"   "fsqrt<size>")
256    (set_attr "length" "4")]
259 ;; Conditional Branch patterns
261 (define_expand "cstore<mode>4"
262   [(set (match_operand:SI 0 "register_operand" "")
263         (match_operator:SI 1 "nds32_float_comparison_operator"
264          [(match_operand:ANYF 2 "register_operand" "")
265           (match_operand:ANYF 3 "register_operand" "")]))]
266   ""
268   nds32_expand_float_cstore (operands);
269   DONE;
272 (define_expand "cbranch<mode>4"
273   [(set (pc)
274         (if_then_else (match_operator 0 "nds32_float_comparison_operator"
275                        [(match_operand:ANYF 1 "register_operand" "")
276                         (match_operand:ANYF 2 "register_operand" "")])
277                       (label_ref (match_operand 3 "" ""))
278                       (pc)))]
279   ""
281   nds32_expand_float_cbranch (operands);
282   DONE;
285 ;; Copysign Instructions.
287 (define_insn "copysignsf3"
288   [(set (match_operand:SF 0 "register_operand" "=f")
289         (unspec:SF [(match_operand:SF 1 "register_operand" "f")
290                     (match_operand:SF 2 "register_operand" "f")]
291                      UNSPEC_COPYSIGN))]
292   "TARGET_FPU_SINGLE"
293   "fcpyss\t%0,%1,%2"
294   [(set_attr "type"   "fcpy")
295    (set_attr "length" "4")]
298 (define_insn "copysigndf3"
299   [(set (match_operand:DF 0 "register_operand" "=f")
300         (unspec:DF [(match_operand:DF 1 "register_operand" "f")
301                     (match_operand:DF 2 "register_operand" "f")]
302                      UNSPEC_COPYSIGN))]
303   "TARGET_FPU_SINGLE || TARGET_FPU_DOUBLE"
304   "fcpysd\t%0,%1,%2"
305   [(set_attr "type"   "fcpy")
306    (set_attr "length" "4")]
309 (define_insn "*ncopysign<mode>3"
310   [(set (match_operand:ANYF 0 "register_operand" "=f")
311         (neg:ANYF (unspec:ANYF [(match_operand:ANYF 1 "register_operand" "f")
312                                 (match_operand:ANYF 2 "register_operand" "f")]
313                                 UNSPEC_COPYSIGN)))]
314   ""
315   "fcpyns<size>\t%0,%1,%2"
316   [(set_attr "type"   "fcpy")
317    (set_attr "length" "4")]
320 ;; Absolute Instructions
322 (define_insn "abssf2"
323   [(set (match_operand:SF 0 "register_operand" "=f, r")
324         (abs:SF (match_operand:SF 1 "register_operand" "f, r")))]
325   "TARGET_FPU_SINGLE || TARGET_EXT_PERF"
326   "@
327    fabss\t%0, %1
328    bclr\t%0, %1, 31"
329   [(set_attr "type"    "fabs,alu")
330    (set_attr "length"  "4")
331    (set_attr "feature" "fpu,pe1")]
334 (define_insn "absdf2"
335   [(set (match_operand:DF 0 "register_operand" "=f")
336         (abs:DF (match_operand:DF 1 "register_operand" "f")))]
337   "TARGET_FPU_DOUBLE"
338   "fabsd\t%0, %1"
339   [(set_attr "type"   "fabs")
340    (set_attr "length" "4")]
343 ;; Negation Instructions
345 (define_insn "*negsf2"
346   [(set (match_operand:SF 0 "register_operand" "=f, r")
347         (neg:SF (match_operand:SF 1 "register_operand" "f, r")))]
348   "TARGET_FPU_SINGLE || TARGET_EXT_PERF"
349   "@
350    fcpynss\t%0, %1, %1
351    btgl\t%0, %1, 31"
352   [(set_attr "type"    "fcpy,alu")
353    (set_attr "length"  "4")
354    (set_attr "feature" "fpu,pe1")]
357 (define_insn "*negdf2"
358   [(set (match_operand:DF 0 "register_operand" "=f")
359         (neg:DF (match_operand:DF 1 "register_operand" "f")))]
360   "TARGET_FPU_DOUBLE"
361   "fcpynsd\t%0, %1, %1"
362   [(set_attr "type"   "fcpy")
363    (set_attr "length" "4")]
366 ;; Data Format Conversion Instructions
368 (define_insn "floatunssi<mode>2"
369   [(set (match_operand:ANYF 0 "register_operand" "=f")
370         (unsigned_float:ANYF (match_operand:SI 1 "register_operand" "f")))]
371   ""
372   "fui2<size>\t %0, %1"
373   [(set_attr "type"   "falu")
374    (set_attr "length" "4")]
377 (define_insn "floatsi<mode>2"
378   [(set (match_operand:ANYF 0 "register_operand" "=f")
379         (float:ANYF (match_operand:SI 1 "register_operand" "f")))]
380   ""
381   "fsi2<size>\t %0, %1"
382   [(set_attr "type"   "falu")
383    (set_attr "length" "4")]
386 (define_insn "fixuns_trunc<mode>si2"
387   [(set (match_operand:SI 0 "register_operand" "=f")
388         (unsigned_fix:SI (fix:ANYF (match_operand:ANYF 1 "register_operand" "f"))))]
389   ""
390   "f<size>2ui.z\t %0, %1"
391   [(set_attr "type"   "falu")
392    (set_attr "length" "4")]
395 (define_insn "fix_trunc<mode>si2"
396   [(set (match_operand:SI 0 "register_operand" "=f")
397         (fix:SI (fix:ANYF (match_operand:ANYF 1 "register_operand" "f"))))]
398   ""
399   "f<size>2si.z\t %0, %1"
400   [(set_attr "type"   "falu")
401    (set_attr "length" "4")]
404 (define_insn "extendsfdf2"
405   [(set (match_operand:DF 0 "register_operand" "=f")
406         (float_extend:DF (match_operand:SF 1 "register_operand" "f")))]
407   "TARGET_FPU_SINGLE && TARGET_FPU_DOUBLE"
408   "fs2d\t%0, %1"
409   [(set_attr "type"   "falu")
410    (set_attr "length" "4")]
413 (define_insn "truncdfsf2"
414   [(set (match_operand:SF 0 "register_operand" "=f")
415         (float_truncate:SF (match_operand:DF 1 "register_operand" "f")))]
416   "TARGET_FPU_SINGLE && TARGET_FPU_DOUBLE"
417   "fd2s\t%0, %1"
418   [(set_attr "type"   "falu")
419    (set_attr "length" "4")]
422 ;; Compare Instructions
424 (define_insn "cmp<mode>_eq"
425   [(set (match_operand:SI 0 "register_operand" "=f")
426         (eq:SI (match_operand:ANYF 1 "register_operand" "f")
427                (match_operand:ANYF 2 "register_operand" "f")))]
428   ""
429   {
430     if (NDS32_EXT_FPU_DOT_E)
431       return "fcmpeq<size>.e %0, %1, %2";
432     else
433       return "fcmpeq<size>\t%0, %1, %2";
434   }
435   [(set_attr "type"   "fcmp")
436    (set_attr "length" "4")]
439 (define_insn "cmp<mode>_lt"
440   [(set (match_operand:SI 0 "register_operand" "=f")
441         (lt:SI (match_operand:ANYF 1 "register_operand" "f")
442                (match_operand:ANYF 2 "register_operand" "f")))]
443   ""
445   if (NDS32_EXT_FPU_DOT_E)
446     return "fcmplt<size>.e %0, %1, %2";
447   else
448     return "fcmplt<size>\t%0, %1, %2";
450   [(set_attr "type"   "fcmp")
451    (set_attr "length" "4")]
454 (define_insn "cmp<mode>_le"
455   [(set (match_operand:SI 0 "register_operand" "=f")
456         (le:SI (match_operand:ANYF 1 "register_operand" "f")
457                (match_operand:ANYF 2 "register_operand" "f")))]
458   ""
460   if (NDS32_EXT_FPU_DOT_E)
461     return "fcmple<size>.e %0, %1, %2";
462   else
463     return "fcmple<size>\t%0, %1, %2";
465   [(set_attr "type"   "fcmp")
466    (set_attr "length" "4")]
469 (define_insn "cmp<mode>_un"
470   [(set (match_operand:SI 0 "register_operand" "=f")
471         (unordered:SI (match_operand:ANYF 1 "register_operand" "f")
472                       (match_operand:ANYF 2 "register_operand" "f")))]
473   ""
475   if (NDS32_EXT_FPU_DOT_E)
476     return "fcmpun<size>.e %0, %1, %2";
477   else
478     return "fcmpun<size>\t%0, %1, %2";
480   [(set_attr "type"   "fcmp")
481    (set_attr "length" "4")]
484 (define_split
485   [(set (match_operand:SF 0 "register_operand" "")
486         (match_operand:SF 1 "register_operand" ""))]
487   "!TARGET_FPU_SINGLE
488    && NDS32_IS_FPR_REGNUM (REGNO (operands[0]))
489    && NDS32_IS_FPR_REGNUM (REGNO (operands[1]))"
490   [(set (match_dup 2) (match_dup 1))
491    (set (match_dup 0) (match_dup 2))]
493   operands[2] = gen_rtx_REG (SFmode, TA_REGNUM);
496 (define_split
497   [(set (match_operand:SF 0 "register_operand" "")
498         (match_operand:SF 1 "const_double_operand" ""))]
499   "!satisfies_constraint_Cs20 (operands[1])
500    && !satisfies_constraint_Chig (operands[1])"
501   [(set (match_dup 0) (high:SF (match_dup 1)))
502    (set (match_dup 0) (lo_sum:SF (match_dup 0) (match_dup 1)))])
503 ;; ----------------------------------------------------------------------------