]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/config/nds32/nds32-fpu.md
Update copyright years.
[thirdparty/gcc.git] / gcc / config / nds32 / nds32-fpu.md
1 ;; Machine description of Andes NDS32 cpu for GNU compiler
2 ;; Copyright (C) 2012-2023 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.
11 ;;
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.
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 ;;SFmode moves
22
23 (define_expand "movsf"
24 [(set (match_operand:SF 0 "general_operand" "")
25 (match_operand:SF 1 "general_operand" ""))]
26 ""
27 {
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;
36
37 r = CONST_DOUBLE_REAL_VALUE (operands[1]);
38 REAL_VALUE_TO_TARGET_SINGLE (*r, l);
39
40 emit_move_insn (operands[0], gen_rtx_HIGH (SFmode, operands[1]));
41
42 if ((l & 0xFFF) != 0)
43 emit_insn (gen_movsf_lo (operands[0], operands[0], operands[1]));
44 DONE;
45 }
46 })
47
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")]
56 )
57
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))"
63 {
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 }
106 }
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")])
110
111 ;; Conditional Move Instructions
112
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 ""
119 {
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);
130 })
131
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")]
144 )
145
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")]
158 )
159
160 ;; Arithmetic instructions.
161
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")]
170 )
171
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")]
180 )
181
182 ;; Multiplication insns.
183
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")]
192 )
193
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")]
203 )
204
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")]
214 )
215
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")]
225 )
226
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")]
236 )
237
238 ;; Div Instructions.
239
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")]
248 )
249
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")]
257 )
258
259 ;; Conditional Branch patterns
260
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 ""
267 {
268 nds32_expand_float_cstore (operands);
269 DONE;
270 })
271
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 ""
280 {
281 nds32_expand_float_cbranch (operands);
282 DONE;
283 })
284
285 ;; Copysign Instructions.
286
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")]
296 )
297
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")]
307 )
308
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")]
318 )
319
320 ;; Absolute Instructions
321
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")]
332 )
333
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")]
341 )
342
343 ;; Negation Instructions
344
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")]
355 )
356
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")]
364 )
365
366 ;; Data Format Conversion Instructions
367
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")]
375 )
376
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")]
384 )
385
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")]
393 )
394
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")]
402 )
403
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")]
411 )
412
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")]
420 )
421
422 ;; Compare Instructions
423
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")]
437 )
438
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 ""
444 {
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";
449 }
450 [(set_attr "type" "fcmp")
451 (set_attr "length" "4")]
452 )
453
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 ""
459 {
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";
464 }
465 [(set_attr "type" "fcmp")
466 (set_attr "length" "4")]
467 )
468
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 ""
474 {
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";
479 }
480 [(set_attr "type" "fcmp")
481 (set_attr "length" "4")]
482 )
483
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))]
492 {
493 operands[2] = gen_rtx_REG (SFmode, TA_REGNUM);
494 })
495
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 ;; ----------------------------------------------------------------------------