1;; Machine description of Andes NDS32 cpu for GNU compiler
2;; Copyright (C) 2012-2020 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;; ----------------------------------------------------------------------------
504