1;; Machine description of Andes NDS32 cpu for GNU compiler
2;; Copyright (C) 2012-2021 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;; See file "rtl.def" for documentation on define_insn, match_*, et. al.
22
23;; Include predicates definition.
24(include "predicates.md")
25
26;; Include constraints definition.
27(include "constraints.md")
28
29;; Include iterators definition.
30(include "iterators.md")
31
32;; Include pipelines definition.
33(include "pipelines.md")
34
35
36;; Include constants definition.
37(include "constants.md")
38
39
40;; Include intrinsic functions definition.
41(include "nds32-intrinsic.md")
42
43;; Include block move for nds32 multiple load/store behavior.
44(include "nds32-multiple.md")
45
46;; Include DImode/DFmode operations.
47(include "nds32-doubleword.md")
48
49;; Include floating-point patterns.
50(include "nds32-fpu.md")
51
52;; Include peephole patterns.
53(include "nds32-peephole2.md")
54
55
56;; ------------------------------------------------------------------------
57
58;; CPU pipeline model.
59(define_attr "pipeline_model" "n7,n8,e8,n9,n10,graywolf,n13,simple"
60  (const
61    (cond [(match_test "nds32_cpu_option == CPU_N7")  (const_string "n7")
62	   (match_test "nds32_cpu_option == CPU_E8")  (const_string "e8")
63	   (match_test "nds32_cpu_option == CPU_N6 || nds32_cpu_option == CPU_N8")  (const_string "n8")
64	   (match_test "nds32_cpu_option == CPU_N9")  (const_string "n9")
65	   (match_test "nds32_cpu_option == CPU_N10") (const_string "n10")
66	   (match_test "nds32_cpu_option == CPU_GRAYWOLF") (const_string "graywolf")
67	   (match_test "nds32_cpu_option == CPU_N12") (const_string "n13")
68	   (match_test "nds32_cpu_option == CPU_N13") (const_string "n13")
69	   (match_test "nds32_cpu_option == CPU_SIMPLE") (const_string "simple")]
70	  (const_string "n9"))))
71
72;; Insn type, it is used to default other attribute values.
73(define_attr "type"
74  "unknown,load,store,load_multiple,store_multiple,alu,alu_shift,pbsad,pbsada,mul,mac,div,branch,mmu,misc,\
75   falu,fmuls,fmuld,fmacs,fmacd,fdivs,fdivd,fsqrts,fsqrtd,fcmp,fabs,fcpy,fcmov,fmfsr,fmfdr,fmtsr,fmtdr,fload,fstore,\
76   dalu,dalu64,daluround,dcmp,dclip,dmul,dmac,dinsb,dpack,dbpick,dwext"
77  (const_string "unknown"))
78
79;; Insn sub-type
80(define_attr "subtype"
81  "simple,shift,saturation"
82  (const_string "simple"))
83
84;; Length, in bytes, default is 4-bytes.
85(define_attr "length" "" (const_int 4))
86
87;; Indicate the amount of micro instructions.
88(define_attr "combo"
89  "0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25"
90  (const_string "1"))
91
92;; Insn in which feature set, it is used to enable/disable insn alternatives.
93;; v1  : Baseline Instructions
94;; v2  : Baseline Version 2 Instructions
95;; v3m : Baseline Version 3m Instructions
96;; v3  : Baseline Version 3 Instructions
97;; pe1 : Performance Extension Instructions
98;; pe2 : Performance Extension Version 2 Instructions
99;; se  : String Extension instructions
100(define_attr "feature"
101  "v1,v2,v3m,v3,pe1,pe2,se,fpu"
102  (const_string "v1"))
103
104;; Enabled, which is used to enable/disable insn alternatives.
105;; Note that we use length and TARGET_16_BIT here as criteria.
106;; If the instruction pattern already check TARGET_16_BIT to determine
107;; the length by itself, its enabled attribute should be customized to
108;; avoid the conflict between length attribute and this default setting.
109(define_attr "enabled" "no,yes"
110  (if_then_else
111    (and (eq_attr "length" "2")
112	 (match_test "!TARGET_16_BIT"))
113    (const_string "no")
114    (cond [(eq_attr "feature" "v1")   (const_string "yes")
115	   (eq_attr "feature" "v2")   (if_then_else (match_test "TARGET_ISA_V2 || TARGET_ISA_V3 || TARGET_ISA_V3M")
116						    (const_string "yes")
117						    (const_string "no"))
118	   (eq_attr "feature" "v3")   (if_then_else (match_test "TARGET_ISA_V3")
119						    (const_string "yes")
120						    (const_string "no"))
121	   (eq_attr "feature" "v3m")  (if_then_else (match_test "TARGET_ISA_V3 || TARGET_ISA_V3M")
122						    (const_string "yes")
123						    (const_string "no"))
124	   (eq_attr "feature" "pe1")  (if_then_else (match_test "TARGET_EXT_PERF")
125						    (const_string "yes")
126						    (const_string "no"))
127	   (eq_attr "feature" "pe2")  (if_then_else (match_test "TARGET_EXT_PERF2")
128						    (const_string "yes")
129						    (const_string "no"))
130	   (eq_attr "feature" "se")   (if_then_else (match_test "TARGET_EXT_STRING")
131						    (const_string "yes")
132						    (const_string "no"))
133	   (eq_attr "feature" "fpu")  (if_then_else (match_test "TARGET_FPU_SINGLE || TARGET_FPU_DOUBLE")
134						    (const_string "yes")
135						    (const_string "no"))]
136	   (const_string "yes"))))
137
138
139;; ----------------------------------------------------------------------------
140
141(include "nds32-dspext.md")
142
143;; Move instructions.
144
145;; For QImode and HImode, the immediate value can be fit in imm20s.
146;; So there is no need to split rtx for QI and HI patterns.
147
148(define_expand "mov<mode>"
149  [(set (match_operand:QIHI 0 "general_operand" "")
150	(match_operand:QIHI 1 "general_operand" ""))]
151  ""
152{
153  /* Need to force register if mem <- !reg.  */
154  if (MEM_P (operands[0]) && !REG_P (operands[1]))
155    operands[1] = force_reg (<MODE>mode, operands[1]);
156
157  if (MEM_P (operands[1]) && optimize > 0)
158    {
159      rtx reg = gen_reg_rtx (SImode);
160
161      emit_insn (gen_zero_extend<mode>si2 (reg, operands[1]));
162      operands[1] = gen_lowpart (<MODE>mode, reg);
163    }
164})
165
166(define_expand "movmisalign<mode>"
167  [(set (match_operand:SIDI 0 "general_operand" "")
168	(match_operand:SIDI 1 "general_operand" ""))]
169  ""
170{
171  rtx addr;
172  if (MEM_P (operands[0]) && !REG_P (operands[1]))
173    operands[1] = force_reg (<MODE>mode, operands[1]);
174
175  if (MEM_P (operands[0]))
176    {
177      addr = force_reg (Pmode, XEXP (operands[0], 0));
178      emit_insn (gen_unaligned_store<mode> (addr, operands[1]));
179    }
180  else
181    {
182      addr = force_reg (Pmode, XEXP (operands[1], 0));
183      emit_insn (gen_unaligned_load<mode> (operands[0], addr));
184    }
185  DONE;
186})
187
188(define_expand "movsi"
189  [(set (match_operand:SI 0 "general_operand" "")
190	(match_operand:SI 1 "general_operand" ""))]
191  ""
192{
193  /* Need to force register if mem <- !reg.  */
194  if (MEM_P (operands[0]) && !REG_P (operands[1]))
195    operands[1] = force_reg (SImode, operands[1]);
196
197  /* If operands[1] is a large constant and cannot be performed
198     by a single instruction, we need to split it.  */
199  if (CONST_INT_P (operands[1])
200      && !satisfies_constraint_Is20 (operands[1])
201      && !satisfies_constraint_Ihig (operands[1]))
202    {
203      rtx high20_rtx;
204      HOST_WIDE_INT low12_int;
205      rtx tmp_rtx;
206
207      tmp_rtx = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
208
209      high20_rtx = gen_int_mode ((INTVAL (operands[1]) >> 12) << 12, SImode);
210      low12_int = INTVAL (operands[1]) & 0xfff;
211
212      emit_move_insn (tmp_rtx, high20_rtx);
213      emit_move_insn (operands[0], plus_constant (SImode,
214						  tmp_rtx,
215						  low12_int));
216      DONE;
217    }
218
219  if ((REG_P (operands[0]) || GET_CODE (operands[0]) == SUBREG)
220       && SYMBOLIC_CONST_P (operands[1]))
221    {
222      if (TARGET_ICT_MODEL_LARGE
223	  && nds32_indirect_call_referenced_p (operands[1]))
224	{
225	  nds32_expand_ict_move (operands);
226	  DONE;
227	}
228      else if (nds32_tls_referenced_p (operands [1]))
229	{
230	  nds32_expand_tls_move (operands);
231	  DONE;
232	}
233      else if (flag_pic)
234	{
235	  nds32_expand_pic_move (operands);
236	  DONE;
237	}
238    }
239})
240
241(define_insn "*mov<mode>"
242  [(set (match_operand:QIHISI 0 "nonimmediate_operand" "=r, r,U45,U33,U37,U45, m,  l,  l,  l,  d,  d, r,   d,    r,    r,    r, *f, *f,  r, *f,  Q")
243	(match_operand:QIHISI 1 "nds32_move_operand"   " r, r,  l,  l,  l,  d, r,U45,U33,U37,U45,Ufe, m,Ip05, Is05, Is20, Ihig, *f,  r, *f,  Q, *f"))]
244  "register_operand(operands[0], <MODE>mode)
245   || register_operand(operands[1], <MODE>mode)"
246{
247  switch (which_alternative)
248    {
249    case 0:
250      return "mov55\t%0, %1";
251    case 1:
252      return "ori\t%0, %1, 0";
253    case 2:
254    case 3:
255    case 4:
256    case 5:
257      return nds32_output_16bit_store (operands, <byte>);
258    case 6:
259      return nds32_output_32bit_store (operands, <byte>);
260    case 7:
261    case 8:
262    case 9:
263    case 10:
264    case 11:
265      return nds32_output_16bit_load (operands, <byte>);
266    case 12:
267      return nds32_output_32bit_load (operands, <byte>);
268    case 13:
269      return "movpi45\t%0, %1";
270    case 14:
271      return "movi55\t%0, %1";
272    case 15:
273      return "movi\t%0, %1";
274    case 16:
275      return "sethi\t%0, hi20(%1)";
276    case 17:
277      if (TARGET_FPU_SINGLE)
278	return "fcpyss\t%0, %1, %1";
279      else
280	return "#";
281    case 18:
282      return "fmtsr\t%1, %0";
283    case 19:
284      return "fmfsr\t%0, %1";
285    case 20:
286      return nds32_output_float_load (operands);
287    case 21:
288      return nds32_output_float_store (operands);
289    default:
290      gcc_unreachable ();
291    }
292}
293  [(set_attr "type"    "alu,alu,store,store,store,store,store,load,load,load,load,load,load,alu,alu,alu,alu,fcpy,fmtsr,fmfsr,fload,fstore")
294   (set_attr "length"  "  2,  4,    2,    2,    2,    2,    4,   2,   2,   2,   2,   2,   4,  2,  2,  4,  4,   4,    4,    4,    4,     4")
295   (set_attr "feature" " v1, v1,   v1,   v1,   v1,   v1,   v1,  v1,  v1,  v1,  v1, v3m,  v1, v1, v1, v1, v1, fpu,  fpu,  fpu,  fpu,   fpu")])
296
297
298;; We use nds32_symbolic_operand to limit that only CONST/SYMBOL_REF/LABEL_REF
299;; are able to match such instruction template.
300(define_insn "move_addr"
301  [(set (match_operand:SI 0 "nds32_general_register_operand"   "=l, r")
302	(match_operand:SI 1 "nds32_nonunspec_symbolic_operand" " i, i"))]
303  ""
304  "la\t%0, %1"
305  [(set_attr "type"  "alu")
306   (set_attr "length"  "8")])
307
308
309(define_insn "sethi"
310  [(set (match_operand:SI 0 "register_operand"                "=r")
311	(high:SI (match_operand:SI 1 "nds32_symbolic_operand" " i")))]
312  ""
313  "sethi\t%0, hi20(%1)"
314  [(set_attr "type" "alu")
315   (set_attr "length" "4")])
316
317
318(define_insn "lo_sum"
319  [(set (match_operand:SI 0 "register_operand"                  "=r")
320	(lo_sum:SI (match_operand:SI 1 "register_operand"       " r")
321		   (match_operand:SI 2 "nds32_symbolic_operand" " i")))]
322  ""
323  "ori\t%0, %1, lo12(%2)"
324  [(set_attr "type" "alu")
325   (set_attr "length" "4")])
326
327
328;; ----------------------------------------------------------------------------
329
330;; Zero extension instructions.
331
332(define_insn "zero_extend<mode>si2"
333  [(set (match_operand:SI 0 "register_operand"                       "=l, r,   l, *r")
334	(zero_extend:SI (match_operand:QIHI 1 "nonimmediate_operand" " l, r, U33,  m")))]
335  ""
336{
337  switch (which_alternative)
338    {
339    case 0:
340      return "ze<size>33\t%0, %1";
341    case 1:
342      return "ze<size>\t%0, %1";
343    case 2:
344      return nds32_output_16bit_load (operands, <byte>);
345    case 3:
346      return nds32_output_32bit_load (operands, <byte>);
347
348    default:
349      gcc_unreachable ();
350    }
351}
352  [(set_attr "type"   "alu,alu,load,load")
353   (set_attr "length" "  2,  4,   2,   4")])
354
355
356;; Sign extension instructions.
357
358(define_insn "extend<mode>si2"
359  [(set (match_operand:SI 0 "register_operand"                       "=l, r, r")
360	(sign_extend:SI (match_operand:QIHI 1 "nonimmediate_operand" " l, r, m")))]
361  ""
362{
363  switch (which_alternative)
364    {
365    case 0:
366      return "se<size>33\t%0, %1";
367    case 1:
368      return "se<size>\t%0, %1";
369    case 2:
370      return nds32_output_32bit_load_s (operands, <byte>);
371
372    default:
373      gcc_unreachable ();
374    }
375}
376  [(set_attr "type"   "alu,alu,load")
377   (set_attr "length" "  2,  4,   4")])
378
379
380;; ----------------------------------------------------------------------------
381(define_expand "extv"
382  [(set (match_operand 0 "register_operand" "")
383        (sign_extract (match_operand 1 "nonimmediate_operand" "")
384                      (match_operand 2 "const_int_operand" "")
385                      (match_operand 3 "const_int_operand" "")))]
386  ""
387{
388  enum nds32_expand_result_type result = nds32_expand_extv (operands);
389  switch (result)
390    {
391    case EXPAND_DONE:
392      DONE;
393      break;
394    case EXPAND_FAIL:
395      FAIL;
396      break;
397    case EXPAND_CREATE_TEMPLATE:
398      break;
399    default:
400      gcc_unreachable ();
401    }
402})
403
404(define_expand "insv"
405  [(set (zero_extract (match_operand 0 "nonimmediate_operand" "")
406                      (match_operand 1 "const_int_operand" "")
407                      (match_operand 2 "const_int_operand" ""))
408        (match_operand 3 "register_operand" ""))]
409  ""
410{
411  enum nds32_expand_result_type result = nds32_expand_insv (operands);
412  switch (result)
413    {
414    case EXPAND_DONE:
415      DONE;
416      break;
417    case EXPAND_FAIL:
418      FAIL;
419      break;
420    case EXPAND_CREATE_TEMPLATE:
421      break;
422    default:
423      gcc_unreachable ();
424    }
425})
426
427;; Arithmetic instructions.
428
429(define_insn "addsi3"
430  [(set (match_operand:SI 0 "register_operand"               "=   d,   l,   d,   l, d, l,   k,   l,    r, r")
431	(plus:SI (match_operand:SI 1 "register_operand"      "%   0,   l,   0,   l, 0, l,   0,   k,    r, r")
432		 (match_operand:SI 2 "nds32_rimm15s_operand" " In05,In03,Iu05,Iu03, r, l,Is10,IU06, Is15, r")))]
433  ""
434{
435  switch (which_alternative)
436    {
437    case 0:
438      /* addi Rt4,Rt4,-x  ==>  subi45 Rt4,x
439	 where 0 <= x <= 31 */
440      operands[2] = gen_int_mode (-INTVAL (operands[2]), SImode);
441      return "subi45\t%0, %2";
442    case 1:
443      /* addi Rt3,Ra3,-x  ==>  subi333 Rt3,Ra3,x
444	 where 0 <= x <= 7 */
445      operands[2] = gen_int_mode (-INTVAL (operands[2]), SImode);
446      return "subi333\t%0, %1, %2";
447    case 2:
448      return "addi45\t%0, %2";
449    case 3:
450      return "addi333\t%0, %1, %2";
451    case 4:
452      return "add45\t%0, %2";
453    case 5:
454      return "add333\t%0, %1, %2";
455    case 6:
456      return "addi10.sp\t%2";
457    case 7:
458      return "addri36.sp\t%0, %2";
459    case 8:
460      return "addi\t%0, %1, %2";
461    case 9:
462      return "add\t%0, %1, %2";
463
464    default:
465      gcc_unreachable ();
466    }
467}
468  [(set_attr "type"    "alu,alu,alu,alu,alu,alu,alu,alu,alu,alu")
469   (set_attr "length"  "  2,  2,  2,  2,  2,  2,  2,  2,  4,  4")
470   (set_attr "feature" " v1, v1, v1, v1, v1, v1, v2, v1, v1, v1")])
471
472(define_insn "subsi3"
473  [(set (match_operand:SI 0 "register_operand"                "=d, l,    r, r")
474	(minus:SI (match_operand:SI 1 "nds32_rimm15s_operand" " 0, l, Is15, r")
475		  (match_operand:SI 2 "register_operand"      " r, l,    r, r")))]
476  ""
477  "@
478   sub45\t%0, %2
479   sub333\t%0, %1, %2
480   subri\t%0, %2, %1
481   sub\t%0, %1, %2"
482  [(set_attr "type"   "alu,alu,alu,alu")
483   (set_attr "length" "  2,  2,  4,  4")])
484
485
486;; GCC intends to simplify (plus (ashift ...) (reg))
487;; into (plus (mult ...) (reg)), so our matching pattern takes 'mult'
488;; and needs to ensure it is exact_log2 value.
489(define_insn "*add_slli"
490  [(set (match_operand:SI 0 "register_operand"                    "=r")
491	(plus:SI (mult:SI (match_operand:SI 1 "register_operand"  " r")
492			  (match_operand:SI 2 "immediate_operand" " i"))
493		 (match_operand:SI 3 "register_operand"           " r")))]
494  "TARGET_ISA_V3 && optimize_size
495   && (exact_log2 (INTVAL (operands[2])) != -1)
496   && (exact_log2 (INTVAL (operands[2])) <= 31)"
497{
498  /* Get floor_log2 of the immediate value
499     so that we can generate 'add_slli' instruction.  */
500  operands[2] = GEN_INT (floor_log2 (INTVAL (operands[2])));
501
502  return "add_slli\t%0, %3, %1, %2";
503}
504  [(set_attr "type" "alu_shift")
505   (set_attr "combo"        "2")
506   (set_attr "length"       "4")])
507
508(define_insn "*add_srli"
509  [(set (match_operand:SI 0 "register_operand"                          "=   r")
510	(plus:SI (lshiftrt:SI (match_operand:SI 1 "register_operand"    "    r")
511			      (match_operand:SI 2 "nds32_imm5u_operand" " Iu05"))
512		 (match_operand:SI 3 "register_operand"                 "    r")))]
513  "TARGET_ISA_V3 && optimize_size"
514  "add_srli\t%0, %3, %1, %2"
515  [(set_attr "type" "alu_shift")
516   (set_attr "combo"        "2")
517   (set_attr "length"       "4")])
518
519
520;; GCC intends to simplify (minus (reg) (ashift ...))
521;; into (minus (reg) (mult ...)), so our matching pattern takes 'mult'
522;; and needs to ensure it is exact_log2 value.
523(define_insn "*sub_slli"
524  [(set (match_operand:SI 0 "register_operand"                     "=r")
525	(minus:SI (match_operand:SI 1 "register_operand"           " r")
526		  (mult:SI (match_operand:SI 2 "register_operand"  " r")
527			   (match_operand:SI 3 "immediate_operand" " i"))))]
528  "TARGET_ISA_V3 && optimize_size
529   && (exact_log2 (INTVAL (operands[3])) != -1)
530   && (exact_log2 (INTVAL (operands[3])) <= 31)"
531{
532  /* Get floor_log2 of the immediate value
533     so that we can generate 'sub_slli' instruction.  */
534  operands[3] = GEN_INT (floor_log2 (INTVAL (operands[3])));
535
536  return "sub_slli\t%0, %1, %2, %3";
537}
538  [(set_attr "type" "alu_shift")
539   (set_attr "combo"        "2")
540   (set_attr "length"       "4")])
541
542(define_insn "*sub_srli"
543  [(set (match_operand:SI 0 "register_operand"                           "=   r")
544	(minus:SI (match_operand:SI 1 "register_operand"                 "    r")
545		  (lshiftrt:SI (match_operand:SI 2 "register_operand"    "    r")
546			       (match_operand:SI 3 "nds32_imm5u_operand" " Iu05"))))]
547  "TARGET_ISA_V3 && optimize_size"
548  "sub_srli\t%0, %1, %2, %3"
549  [(set_attr "type" "alu_shift")
550   (set_attr "combo"        "2")
551   (set_attr "length"       "4")])
552
553
554;; Multiplication instructions.
555
556(define_insn "mulsi3"
557  [(set (match_operand:SI 0 "register_operand"          "=w, r")
558	(mult:SI (match_operand:SI 1 "register_operand" "%0, r")
559		 (match_operand:SI 2 "register_operand" " w, r")))]
560  ""
561  "@
562   mul33\t%0, %2
563   mul\t%0, %1, %2"
564  [(set_attr "type"    "mul,mul")
565   (set_attr "length"  "  2,  4")
566   (set_attr "feature" "v3m, v1")])
567
568(define_insn "mulsidi3"
569  [(set (match_operand:DI 0 "register_operand"                          "=r")
570	(mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" " r"))
571		 (sign_extend:DI (match_operand:SI 2 "register_operand" " r"))))]
572  "TARGET_ISA_V2 || TARGET_ISA_V3"
573  "mulsr64\t%0, %1, %2"
574  [(set_attr "type"   "mul")
575   (set_attr "length"   "4")])
576
577(define_insn "umulsidi3"
578  [(set (match_operand:DI 0 "register_operand"                          "=r")
579	(mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" " r"))
580		 (zero_extend:DI (match_operand:SI 2 "register_operand" " r"))))]
581  "TARGET_ISA_V2 || TARGET_ISA_V3"
582  "mulr64\t%0, %1, %2"
583  [(set_attr "type"   "mul")
584   (set_attr "length"   "4")])
585
586
587;; Multiply-accumulate instructions.
588
589(define_insn "*maddr32_0"
590  [(set (match_operand:SI 0 "register_operand"                   "=r")
591	(plus:SI (match_operand:SI 3 "register_operand"          " 0")
592		 (mult:SI (match_operand:SI 1 "register_operand" " r")
593			  (match_operand:SI 2 "register_operand" " r"))))]
594  ""
595  "maddr32\t%0, %1, %2"
596  [(set_attr "type"   "mac")
597   (set_attr "length"   "4")])
598
599(define_insn "*maddr32_1"
600  [(set (match_operand:SI 0 "register_operand"                   "=r")
601	(plus:SI (mult:SI (match_operand:SI 1 "register_operand" " r")
602			  (match_operand:SI 2 "register_operand" " r"))
603		 (match_operand:SI 3 "register_operand"          " 0")))]
604  ""
605  "maddr32\t%0, %1, %2"
606  [(set_attr "type"   "mac")
607   (set_attr "length"   "4")])
608
609(define_insn "*msubr32"
610  [(set (match_operand:SI 0 "register_operand"                    "=r")
611	(minus:SI (match_operand:SI 3 "register_operand"          " 0")
612		  (mult:SI (match_operand:SI 1 "register_operand" " r")
613			   (match_operand:SI 2 "register_operand" " r"))))]
614  ""
615  "msubr32\t%0, %1, %2"
616  [(set_attr "type"   "mac")
617   (set_attr "length"   "4")])
618
619
620;; Div Instructions.
621
622(define_insn "divmodsi4"
623  [(set (match_operand:SI 0 "register_operand"         "=r")
624	(div:SI (match_operand:SI 1 "register_operand" " r")
625		(match_operand:SI 2 "register_operand" " r")))
626   (set (match_operand:SI 3 "register_operand"         "=r")
627	(mod:SI (match_dup 1) (match_dup 2)))]
628  ""
629  "divsr\t%0, %3, %1, %2"
630  [(set_attr "type"   "div")
631   (set_attr "length"   "4")])
632
633(define_insn "udivmodsi4"
634  [(set (match_operand:SI 0 "register_operand"          "=r")
635	(udiv:SI (match_operand:SI 1 "register_operand" " r")
636		 (match_operand:SI 2 "register_operand"  " r")))
637   (set (match_operand:SI 3 "register_operand"          "=r")
638	(umod:SI (match_dup 1) (match_dup 2)))]
639  ""
640  "divr\t%0, %3, %1, %2"
641  [(set_attr "type"   "div")
642   (set_attr "length"   "4")])
643
644;; divsr/divr will keep quotient only when quotient and remainder is the same
645;; register in our ISA spec, it's can reduce 1 register presure if we don't
646;; want remainder.
647(define_insn "divsi4"
648  [(set (match_operand:SI 0 "register_operand"         "=r")
649	(div:SI (match_operand:SI 1 "register_operand" " r")
650		(match_operand:SI 2 "register_operand" " r")))]
651  ""
652  "divsr\t%0, %0, %1, %2"
653  [(set_attr "type"   "div")
654   (set_attr "length"   "4")])
655
656(define_insn "udivsi4"
657  [(set (match_operand:SI 0 "register_operand"          "=r")
658	(udiv:SI (match_operand:SI 1 "register_operand" " r")
659		 (match_operand:SI 2 "register_operand"  " r")))]
660  ""
661  "divr\t%0, %0, %1, %2"
662  [(set_attr "type"   "div")
663   (set_attr "length"   "4")])
664
665;; ----------------------------------------------------------------------------
666
667;; Boolean instructions.
668;; Note: We define the DImode versions in nds32-doubleword.md.
669
670;; ----------------------------------------------------------------------------
671;; 'AND' operation
672;; ----------------------------------------------------------------------------
673
674(define_insn "bitc"
675  [(set (match_operand:SI 0 "register_operand"                 "=r")
676	(and:SI (not:SI (match_operand:SI 1 "register_operand" " r"))
677		(match_operand:SI 2 "register_operand"         " r")))]
678  "TARGET_ISA_V3"
679  "bitc\t%0, %2, %1"
680  [(set_attr "type" "alu")
681   (set_attr "length" "4")]
682)
683
684(define_expand "andsi3"
685  [(set (match_operand:SI 0 "register_operand" "")
686	(and:SI (match_operand:SI 1 "register_operand" "")
687		(match_operand:SI 2 "nds32_reg_constant_operand" "")))]
688  ""
689{
690  if (CONST_INT_P (operands[2])
691      && !nds32_and_operand (operands[2], SImode))
692    {
693      nds32_expand_constant (SImode, INTVAL (operands[2]),
694			     operands[0], operands[1]);
695      DONE;
696    }
697})
698
699(define_insn "*andsi3"
700  [(set (match_operand:SI 0 "register_operand"          "=l, r,   l,   l,   l,   l,   l,   l,    r,   r,     r,    r,    r")
701	(and:SI (match_operand:SI 1 "register_operand"  "%0, r,   l,   l,   l,   l,   0,   0,    r,   r,     r,    r,    r")
702		(match_operand:SI 2 "nds32_and_operand" " l, r,Izeb,Izeh,Ixls,Ix11,Ibms,Ifex, Izeb, Izeh, Iu15, Ii15, Ic15")))]
703  ""
704{
705  HOST_WIDE_INT mask = INTVAL (operands[2]);
706
707  /* 16-bit andi instructions:
708     andi Rt3,Ra3,0xff   -> zeb33  Rt3,Ra3
709     andi Rt3,Ra3,0xffff -> zeh33  Rt3,Ra3
710     andi Rt3,Ra3,0x01   -> xlsb33 Rt3,Ra3
711     andi Rt3,Ra3,0x7ff  -> x11b33 Rt3,Ra3
712     andi Rt3,Rt3,2^imm3u          -> bmski33 Rt3,imm3u
713     andi Rt3,Rt3,(2^(imm3u+1))-1  -> fexti33 Rt3,imm3u.  */
714
715  switch (which_alternative)
716    {
717    case 0:
718      return "and33\t%0, %2";
719    case 1:
720      return "and\t%0, %1, %2";
721    case 2:
722      return "zeb33\t%0, %1";
723    case 3:
724      return "zeh33\t%0, %1";
725    case 4:
726      return "xlsb33\t%0, %1";
727    case 5:
728      return "x11b33\t%0, %1";
729    case 6:
730      return "bmski33\t%0, %B2";
731    case 7:
732      operands[2] = GEN_INT (floor_log2 (mask + 1) - 1);
733      return "fexti33\t%0, %2";
734    case 8:
735      return "zeb\t%0, %1";
736    case 9:
737      return "zeh\t%0, %1";
738    case 10:
739      return "andi\t%0, %1, %2";
740    case 11:
741      operands[2] = GEN_INT (~mask);
742      return "bitci\t%0, %1, %2";
743    case 12:
744      return "bclr\t%0, %1, %b2";
745
746    default:
747      gcc_unreachable ();
748    }
749}
750  [(set_attr "type"    "alu,alu,alu,alu,alu,alu,alu,alu,alu,alu,alu,alu,alu")
751   (set_attr "length"  "  2,  4,  2,  2,  2,  2,  2,  2,  4,  4,  4,  4,  4")
752   (set_attr "feature" "v3m, v1, v1, v1, v1, v1,v3m,v3m, v1, v1, v1, v3,pe1")])
753
754(define_insn "*and_slli"
755  [(set (match_operand:SI 0 "register_operand"                        "=   r")
756	(and:SI (ashift:SI (match_operand:SI 1 "register_operand"     "    r")
757			    (match_operand:SI 2 "nds32_imm5u_operand" " Iu05"))
758		(match_operand:SI 3 "register_operand"                "    r")))]
759  "TARGET_ISA_V3 && optimize_size"
760  "and_slli\t%0, %3, %1, %2"
761  [(set_attr "type" "alu_shift")
762   (set_attr "length"       "4")])
763
764(define_insn "*and_srli"
765  [(set (match_operand:SI 0 "register_operand"                         "=   r")
766	(and:SI (lshiftrt:SI (match_operand:SI 1 "register_operand"    "    r")
767			     (match_operand:SI 2 "nds32_imm5u_operand" " Iu05"))
768		(match_operand:SI 3 "register_operand"                 "    r")))]
769  "TARGET_ISA_V3 && optimize_size"
770  "and_srli\t%0, %3, %1, %2"
771  [(set_attr "type" "alu_shift")
772   (set_attr "length"       "4")])
773
774
775;; ----------------------------------------------------------------------------
776;; 'OR' operation
777;; ----------------------------------------------------------------------------
778
779;; For V3/V3M ISA, we have 'or33' instruction.
780;; So we can identify 'or Rt3,Rt3,Ra3' case and set its length to be 2.
781
782(define_expand "iorsi3"
783  [(set (match_operand:SI 0 "register_operand"         "")
784	(ior:SI (match_operand:SI 1 "register_operand" "")
785		(match_operand:SI 2 "general_operand"  "")))]
786  ""
787{
788  if (!nds32_ior_operand (operands[2], SImode))
789    operands[2] = force_reg (SImode, operands[2]);
790})
791
792(define_insn "*iorsi3"
793  [(set (match_operand:SI 0 "register_operand"          "=l, r,    r,    r")
794	(ior:SI (match_operand:SI 1 "register_operand"  "%0, r,    r,    r")
795		(match_operand:SI 2 "nds32_ior_operand" " l, r, Iu15, Ie15")))]
796  ""
797  "@
798   or33\t%0, %2
799   or\t%0, %1, %2
800   ori\t%0, %1, %2
801   bset\t%0, %1, %B2"
802  [(set_attr "type"    "alu,alu,alu,alu")
803   (set_attr "length"  "  2,  4,  4,  4")
804   (set_attr "feature" "v3m, v1, v1,pe1")])
805
806(define_insn "*or_slli"
807  [(set (match_operand:SI 0 "register_operand"                       "=   r")
808	(ior:SI (ashift:SI (match_operand:SI 1 "register_operand"    "    r")
809			   (match_operand:SI 2 "nds32_imm5u_operand" " Iu05"))
810		(match_operand:SI 3 "register_operand"               "    r")))]
811  "TARGET_ISA_V3 && optimize_size"
812  "or_slli\t%0, %3, %1, %2"
813  [(set_attr "type" "alu_shift")
814   (set_attr "length"       "4")])
815
816(define_insn "*or_srli"
817  [(set (match_operand:SI 0 "register_operand"                         "=   r")
818	(ior:SI (lshiftrt:SI (match_operand:SI 1 "register_operand"    "    r")
819			     (match_operand:SI 2 "nds32_imm5u_operand" " Iu05"))
820		(match_operand:SI 3 "register_operand"                 "    r")))]
821  "TARGET_ISA_V3 && optimize_size"
822  "or_srli\t%0, %3, %1, %2"
823  [(set_attr "type" "alu_shift")
824   (set_attr "length"       "4")])
825
826
827;; ----------------------------------------------------------------------------
828;; 'XOR' operation
829;; ----------------------------------------------------------------------------
830
831;; For V3/V3M ISA, we have 'xor33' instruction.
832;; So we can identify 'xor Rt3,Rt3,Ra3' case and set its length to be 2.
833
834(define_expand "xorsi3"
835  [(set (match_operand:SI 0 "register_operand"         "")
836	(xor:SI (match_operand:SI 1 "register_operand" "")
837		(match_operand:SI 2 "general_operand"  "")))]
838  ""
839{
840  if (!nds32_xor_operand (operands[2], SImode))
841    operands[2] = force_reg (SImode, operands[2]);
842})
843
844(define_insn "*xorsi3"
845  [(set (match_operand:SI 0 "register_operand"          "=l, r,    r,    r")
846	(xor:SI (match_operand:SI 1 "register_operand"  "%0, r,    r,    r")
847		(match_operand:SI 2 "nds32_xor_operand" " l, r, Iu15, It15")))]
848  ""
849  "@
850   xor33\t%0, %2
851   xor\t%0, %1, %2
852   xori\t%0, %1, %2
853   btgl\t%0, %1, %B2"
854  [(set_attr "type"    "alu,alu,alu,alu")
855   (set_attr "length"  "  2,  4,  4,  4")
856   (set_attr "feature" "v3m, v1, v1,pe1")])
857
858(define_insn "*xor_slli"
859  [(set (match_operand:SI 0 "register_operand"                     "=   r")
860	(xor:SI (ashift:SI (match_operand:SI 1 "register_operand"  "    r")
861			   (match_operand:SI 2 "nds32_imm5u_operand" " Iu05"))
862		(match_operand:SI 3 "register_operand"             "    r")))]
863  "TARGET_ISA_V3 && optimize_size"
864  "xor_slli\t%0, %3, %1, %2"
865  [(set_attr "type" "alu_shift")
866   (set_attr "length"       "4")])
867
868(define_insn "*xor_srli"
869  [(set (match_operand:SI 0 "register_operand"                         "=   r")
870	(xor:SI (lshiftrt:SI (match_operand:SI 1 "register_operand"    "    r")
871			     (match_operand:SI 2 "nds32_imm5u_operand" " Iu05"))
872		(match_operand:SI 3 "register_operand"                 "    r")))]
873  "TARGET_ISA_V3 && optimize_size"
874  "xor_srli\t%0, %3, %1, %2"
875  [(set_attr "type" "alu_shift")
876   (set_attr "length"       "4")])
877
878;; Rotate Right Instructions.
879
880(define_insn "*rotrsi3"
881  [(set (match_operand:SI 0 "register_operand"                    "=   r, r")
882	  (rotatert:SI (match_operand:SI 1 "register_operand"     "    r, r")
883		       (match_operand:SI 2 "nds32_rimm5u_operand" " Iu05, r")))]
884  ""
885  "@
886   rotri\t%0, %1, %2
887   rotr\t%0, %1, %2"
888  [(set_attr "type"    "  alu,  alu")
889   (set_attr "subtype" "shift,shift")
890   (set_attr "length"  "    4,    4")])
891
892
893;; ----------------------------------------------------------------------------
894;; 'NEG' operation
895;; ----------------------------------------------------------------------------
896
897;; For V3/V3M ISA, we have 'neg33' instruction.
898;; So we can identify 'xor Rt3,Ra3' case and set its length to be 2.
899;; And for V2 ISA, there is NO 'neg33' instruction.
900;; The only option is to use 'subri A,B,0' (its semantic is 'A = 0 - B').
901(define_insn "negsi2"
902  [(set (match_operand:SI 0 "register_operand"         "=l, r")
903	(neg:SI (match_operand:SI 1 "register_operand" " l, r")))]
904  ""
905  "@
906   neg33\t%0, %1
907   subri\t%0, %1, 0"
908  [(set_attr "type"    "alu,alu")
909   (set_attr "length"  "  2,  4")
910   (set_attr "feature" "v3m, v1")])
911
912(define_expand "negsf2"
913  [(set (match_operand:SF 0 "register_operand" "")
914	(neg:SF (match_operand:SF 1 "register_operand" "")))]
915  ""
916{
917  if (!TARGET_FPU_SINGLE && !TARGET_EXT_PERF)
918    {
919      rtx new_dst = simplify_gen_subreg (SImode, operands[0], SFmode, 0);
920      rtx new_src = simplify_gen_subreg (SImode, operands[1], SFmode, 0);
921
922      emit_insn (gen_xorsi3 (new_dst,
923			     new_src,
924			     gen_int_mode (0x80000000, SImode)));
925
926      DONE;
927    }
928})
929
930(define_expand "negdf2"
931  [(set (match_operand:DF 0 "register_operand" "")
932	(neg:DF (match_operand:DF 1 "register_operand" "")))]
933  ""
934{
935})
936
937(define_insn_and_split "soft_negdf2"
938  [(set (match_operand:DF 0 "register_operand" "")
939	(neg:DF (match_operand:DF 1 "register_operand" "")))]
940  "!TARGET_FPU_DOUBLE"
941  "#"
942  "!TARGET_FPU_DOUBLE"
943  [(const_int 1)]
944{
945    rtx src = operands[1];
946    rtx dst = operands[0];
947    rtx ori_dst = operands[0];
948
949    bool need_extra_move_for_dst_p;
950    /* FPU register can't change mode to SI directly, so we need create a
951       tmp register to handle it, and FPU register can't do `xor` or btgl.  */
952    if (HARD_REGISTER_P (src)
953	&& TEST_HARD_REG_BIT (reg_class_contents[FP_REGS], REGNO (src)))
954      {
955	rtx tmp = gen_reg_rtx (DFmode);
956	emit_move_insn (tmp, src);
957	src = tmp;
958      }
959
960    if (HARD_REGISTER_P (dst)
961	&& TEST_HARD_REG_BIT (reg_class_contents[FP_REGS], REGNO (dst)))
962      {
963	need_extra_move_for_dst_p = true;
964	rtx tmp = gen_reg_rtx (DFmode);
965	dst = tmp;
966      }
967
968    rtx dst_high_part = simplify_gen_subreg (
969			  SImode, dst,
970			  DFmode, subreg_highpart_offset (SImode, DFmode));
971    rtx dst_low_part = simplify_gen_subreg (
972			  SImode, dst,
973			  DFmode, subreg_lowpart_offset (SImode, DFmode));
974    rtx src_high_part = simplify_gen_subreg (
975			  SImode, src,
976			  DFmode, subreg_highpart_offset (SImode, DFmode));
977    rtx src_low_part = simplify_gen_subreg (
978			  SImode, src,
979			  DFmode, subreg_lowpart_offset (SImode, DFmode));
980
981    emit_insn (gen_xorsi3 (dst_high_part,
982			   src_high_part,
983			   gen_int_mode (0x80000000, SImode)));
984    emit_move_insn (dst_low_part, src_low_part);
985
986    if (need_extra_move_for_dst_p)
987      emit_move_insn (ori_dst, dst);
988
989    DONE;
990})
991
992
993;; ----------------------------------------------------------------------------
994;; 'ONE_COMPLIMENT' operation
995;; ----------------------------------------------------------------------------
996
997;; For V3/V3M ISA, we have 'not33' instruction.
998;; So we can identify 'not Rt3,Ra3' case and set its length to be 2.
999(define_insn "one_cmplsi2"
1000  [(set (match_operand:SI 0 "register_operand"         "=w, r")
1001	(not:SI (match_operand:SI 1 "register_operand" " w, r")))]
1002  ""
1003  "@
1004   not33\t%0, %1
1005   nor\t%0, %1, %1"
1006  [(set_attr "type"    "alu,alu")
1007   (set_attr "length"  "  2,  4")
1008   (set_attr "feature" "v3m, v1")])
1009
1010
1011;; ----------------------------------------------------------------------------
1012
1013;; Shift instructions.
1014
1015(define_expand "<shift>si3"
1016  [(set (match_operand:SI 0 "register_operand"                      "")
1017	(shift_rotate:SI (match_operand:SI 1 "register_operand"     "")
1018			 (match_operand:SI 2 "nds32_rimm5u_operand" "")))]
1019  ""
1020{
1021  if (operands[2] == const0_rtx)
1022    {
1023      emit_move_insn (operands[0], operands[1]);
1024      DONE;
1025    }
1026})
1027
1028(define_insn "*ashlsi3"
1029  [(set (match_operand:SI 0 "register_operand"                "=   l,    r, r")
1030	(ashift:SI (match_operand:SI 1 "register_operand"     "    l,    r, r")
1031		   (match_operand:SI 2 "nds32_rimm5u_operand" " Iu03, Iu05, r")))]
1032  ""
1033  "@
1034   slli333\t%0, %1, %2
1035   slli\t%0, %1, %2
1036   sll\t%0, %1, %2"
1037  [(set_attr "type"    "  alu,  alu,  alu")
1038   (set_attr "subtype" "shift,shift,shift")
1039   (set_attr "length"  "    2,    4,    4")])
1040
1041(define_insn "*ashrsi3"
1042  [(set (match_operand:SI 0 "register_operand"                  "=   d,    r, r")
1043	(ashiftrt:SI (match_operand:SI 1 "register_operand"     "    0,    r, r")
1044		     (match_operand:SI 2 "nds32_rimm5u_operand" " Iu05, Iu05, r")))]
1045  ""
1046  "@
1047   srai45\t%0, %2
1048   srai\t%0, %1, %2
1049   sra\t%0, %1, %2"
1050  [(set_attr "type"    "  alu,  alu,  alu")
1051   (set_attr "subtype" "shift,shift,shift")
1052   (set_attr "length"  "    2,    4,    4")])
1053
1054(define_insn "*lshrsi3"
1055  [(set (match_operand:SI 0 "register_operand"                  "=   d,    r, r")
1056	(lshiftrt:SI (match_operand:SI 1 "register_operand"     "    0,    r, r")
1057		     (match_operand:SI 2 "nds32_rimm5u_operand" " Iu05, Iu05, r")))]
1058  ""
1059  "@
1060   srli45\t%0, %2
1061   srli\t%0, %1, %2
1062   srl\t%0, %1, %2"
1063  [(set_attr "type"    "  alu,  alu,  alu")
1064   (set_attr "subtype" "shift,shift,shift")
1065   (set_attr "length"  "    2,    4,    4")])
1066
1067
1068;; ----------------------------------------------------------------------------
1069
1070;; ----------------------------------------------------------------------------
1071;; Conditional Move patterns
1072;; ----------------------------------------------------------------------------
1073
1074(define_expand "mov<mode>cc"
1075  [(set (match_operand:QIHISI 0 "register_operand" "")
1076	(if_then_else:QIHISI (match_operand 1 "nds32_movecc_comparison_operator" "")
1077			 (match_operand:QIHISI 2 "register_operand" "")
1078			 (match_operand:QIHISI 3 "register_operand" "")))]
1079  "TARGET_CMOV && !optimize_size"
1080{
1081  enum nds32_expand_result_type result = nds32_expand_movcc (operands);
1082  switch (result)
1083    {
1084    case EXPAND_DONE:
1085      DONE;
1086      break;
1087    case EXPAND_FAIL:
1088      FAIL;
1089      break;
1090    case EXPAND_CREATE_TEMPLATE:
1091      break;
1092    default:
1093      gcc_unreachable ();
1094    }
1095})
1096
1097(define_insn "cmovz<mode>"
1098  [(set (match_operand:QIHISI 0 "register_operand"                      "=r, r")
1099	(if_then_else:QIHISI (eq (match_operand:SI 1 "register_operand" " r, r")
1100			     (const_int 0))
1101			 (match_operand:QIHISI 2 "register_operand"     " r, 0")
1102			 (match_operand:QIHISI 3 "register_operand"     " 0, r")))]
1103  "TARGET_CMOV"
1104  "@
1105   cmovz\t%0, %2, %1
1106   cmovn\t%0, %3, %1"
1107  [(set_attr "type"  "alu")
1108   (set_attr "length"  "4")])
1109
1110(define_insn "cmovn<mode>"
1111  [(set (match_operand:QIHISI 0 "register_operand"                      "=r, r")
1112	(if_then_else:QIHISI (ne (match_operand:SI 1 "register_operand" " r, r")
1113			     (const_int 0))
1114			 (match_operand:QIHISI 2 "register_operand"     " r, 0")
1115			 (match_operand:QIHISI 3 "register_operand"     " 0, r")))]
1116  "TARGET_CMOV"
1117  "@
1118   cmovn\t%0, %2, %1
1119   cmovz\t%0, %3, %1"
1120  [(set_attr "type"  "alu")
1121   (set_attr "length"  "4")])
1122
1123;; A hotfix to help RTL combiner to merge a cmovn insn and a zero_extend insn.
1124;; It should be removed once after we change the expansion form of the cmovn.
1125(define_insn "*cmovn_simplified_<mode>"
1126  [(set (match_operand:QIHISI 0 "register_operand" "=r")
1127	(if_then_else:QIHISI (match_operand:SI 1 "register_operand" "r")
1128			 (match_operand:QIHISI 2 "register_operand" "r")
1129			 (match_operand:QIHISI 3 "register_operand" "0")))]
1130  ""
1131  "cmovn\t%0, %2, %1"
1132  [(set_attr "type" "alu")])
1133
1134;; ----------------------------------------------------------------------------
1135;; Conditional Branch patterns
1136;; ----------------------------------------------------------------------------
1137
1138(define_expand "cbranchsi4"
1139  [(set (pc)
1140	(if_then_else (match_operator 0 "comparison_operator"
1141			[(match_operand:SI 1 "register_operand"           "")
1142			 (match_operand:SI 2 "nds32_reg_constant_operand" "")])
1143		      (label_ref (match_operand 3 "" ""))
1144		      (pc)))]
1145  ""
1146{
1147  enum nds32_expand_result_type result = nds32_expand_cbranch (operands);
1148  switch (result)
1149    {
1150    case EXPAND_DONE:
1151      DONE;
1152      break;
1153    case EXPAND_FAIL:
1154      FAIL;
1155      break;
1156    case EXPAND_CREATE_TEMPLATE:
1157      break;
1158    default:
1159      gcc_unreachable ();
1160    }
1161})
1162
1163
1164(define_insn "cbranchsi4_equality_zero"
1165  [(set (pc)
1166	(if_then_else (match_operator 0 "nds32_equality_comparison_operator"
1167			[(match_operand:SI 1 "register_operand"  "t,l, r")
1168			 (const_int 0)])
1169		      (label_ref (match_operand 2 "" ""))
1170		      (pc)))]
1171  ""
1172{
1173  return nds32_output_cbranchsi4_equality_zero (insn, operands);
1174}
1175  [(set_attr "type" "branch")
1176   (set_attr_alternative "enabled"
1177     [
1178       ;; Alternative 0
1179       (if_then_else (match_test "TARGET_16_BIT")
1180		     (const_string "yes")
1181		     (const_string "no"))
1182       ;; Alternative 1
1183       (if_then_else (match_test "TARGET_16_BIT")
1184		     (const_string "yes")
1185		     (const_string "no"))
1186       ;; Alternative 2
1187       (const_string "yes")
1188     ])
1189   (set_attr_alternative "length"
1190     [
1191       ;; Alternative 0
1192       (if_then_else (match_test "!CROSSING_JUMP_P (insn)")
1193		     (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -250))
1194					(le (minus (match_dup 2) (pc)) (const_int  250)))
1195				   (if_then_else (match_test "TARGET_16_BIT")
1196						 (const_int 2)
1197						 (const_int 4))
1198				   (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -65500))
1199						      (le (minus (match_dup 2) (pc)) (const_int  65500)))
1200						 (const_int 4)
1201						 (if_then_else (match_test "TARGET_16_BIT")
1202							       (const_int 8)
1203							       (const_int 10))))
1204		     (const_int 10))
1205       ;; Alternative 1
1206       (if_then_else (match_test "!CROSSING_JUMP_P (insn)")
1207		     (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -250))
1208					(le (minus (match_dup 2) (pc)) (const_int  250)))
1209				   (if_then_else (match_test "TARGET_16_BIT")
1210						 (const_int 2)
1211						 (const_int 4))
1212				   (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -65500))
1213						      (le (minus (match_dup 2) (pc)) (const_int  65500)))
1214						 (const_int 4)
1215						 (if_then_else (match_test "TARGET_16_BIT")
1216							       (const_int 8)
1217							       (const_int 10))))
1218		     (const_int 10))
1219       ;; Alternative 2
1220       (if_then_else (match_test "!CROSSING_JUMP_P (insn)")
1221		     (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -65500))
1222					(le (minus (match_dup 2) (pc)) (const_int  65500)))
1223				   (const_int 4)
1224				   (const_int 10))
1225		     (const_int 10))
1226     ])])
1227
1228
1229;; This pattern is dedicated to V2 ISA,
1230;; because V2 DOES NOT HAVE beqc/bnec instruction.
1231(define_insn "cbranchsi4_equality_reg"
1232  [(set (pc)
1233	(if_then_else (match_operator 0 "nds32_equality_comparison_operator"
1234			[(match_operand:SI 1 "register_operand" "v, r")
1235			 (match_operand:SI 2 "register_operand" "l, r")])
1236		      (label_ref (match_operand 3 "" ""))
1237		      (pc)))]
1238  "TARGET_ISA_V2"
1239{
1240  return nds32_output_cbranchsi4_equality_reg (insn, operands);
1241}
1242  [(set_attr "type"   "branch")
1243   (set_attr_alternative "enabled"
1244     [
1245       ;; Alternative 0
1246       (if_then_else (match_test "TARGET_16_BIT")
1247		     (const_string "yes")
1248		     (const_string "no"))
1249       ;; Alternative 1
1250       (const_string "yes")
1251     ])
1252   (set_attr_alternative "length"
1253     [
1254       ;; Alternative 0
1255       (if_then_else (match_test "!CROSSING_JUMP_P (insn)")
1256		     (if_then_else (and (ge (minus (match_dup 3) (pc)) (const_int -250))
1257					(le (minus (match_dup 3) (pc)) (const_int  250)))
1258				   (const_int 2)
1259				   (if_then_else (and (ge (minus (match_dup 3) (pc))
1260							  (const_int -16350))
1261						      (le (minus (match_dup 3) (pc))
1262							  (const_int  16350)))
1263						 (const_int 4)
1264						 (const_int 8)))
1265		     (const_int 8))
1266       ;; Alternative 1
1267       (if_then_else (match_test "!CROSSING_JUMP_P (insn)")
1268		     (if_then_else (and (ge (minus (match_dup 3) (pc)) (const_int -16350))
1269					(le (minus (match_dup 3) (pc)) (const_int  16350)))
1270				   (const_int 4)
1271				   (const_int 10))
1272		     (const_int 10))
1273     ])])
1274
1275
1276;; This pattern is dedicated to V3/V3M,
1277;; because V3/V3M DO HAVE beqc/bnec instruction.
1278(define_insn "cbranchsi4_equality_reg_or_const_int"
1279  [(set (pc)
1280	(if_then_else (match_operator 0 "nds32_equality_comparison_operator"
1281			[(match_operand:SI 1 "register_operand"      "v, r,    r")
1282			 (match_operand:SI 2 "nds32_rimm11s_operand" "l, r, Is11")])
1283		      (label_ref (match_operand 3 "" ""))
1284		      (pc)))]
1285  "TARGET_ISA_V3 || TARGET_ISA_V3M"
1286{
1287  return nds32_output_cbranchsi4_equality_reg_or_const_int (insn, operands);
1288}
1289  [(set_attr "type"   "branch")
1290   (set_attr_alternative "enabled"
1291     [
1292       ;; Alternative 0
1293       (if_then_else (match_test "TARGET_16_BIT")
1294		     (const_string "yes")
1295		     (const_string "no"))
1296       ;; Alternative 1
1297       (const_string "yes")
1298       ;; Alternative 2
1299       (const_string "yes")
1300     ])
1301   (set_attr_alternative "length"
1302     [
1303       ;; Alternative 0
1304       (if_then_else (match_test "!CROSSING_JUMP_P (insn)")
1305		     (if_then_else (and (ge (minus (match_dup 3) (pc)) (const_int -250))
1306					(le (minus (match_dup 3) (pc)) (const_int  250)))
1307				   (const_int 2)
1308				   (if_then_else (and (ge (minus (match_dup 3) (pc))
1309							  (const_int -16350))
1310						      (le (minus (match_dup 3) (pc))
1311							  (const_int  16350)))
1312						 (const_int 4)
1313						 (const_int 8)))
1314		    (const_int 8))
1315       ;; Alternative 1
1316       (if_then_else (match_test "!CROSSING_JUMP_P (insn)")
1317		     (if_then_else (and (ge (minus (match_dup 3) (pc)) (const_int -16350))
1318					(le (minus (match_dup 3) (pc)) (const_int  16350)))
1319				   (const_int 4)
1320				   (const_int 10))
1321		    (const_int 10))
1322       ;; Alternative 2
1323       (if_then_else (match_test "!CROSSING_JUMP_P (insn)")
1324		     (if_then_else (and (ge (minus (match_dup 3) (pc)) (const_int -250))
1325					(le (minus (match_dup 3) (pc)) (const_int  250)))
1326				   (const_int 4)
1327				   (const_int 10))
1328		    (const_int 10))
1329     ])])
1330
1331
1332(define_insn "*cbranchsi4_greater_less_zero"
1333  [(set (pc)
1334	(if_then_else (match_operator 0 "nds32_greater_less_comparison_operator"
1335			[(match_operand:SI 1 "register_operand" "r")
1336			 (const_int 0)])
1337		      (label_ref (match_operand 2 "" ""))
1338		      (pc)))]
1339  ""
1340{
1341  return nds32_output_cbranchsi4_greater_less_zero (insn, operands);
1342}
1343  [(set_attr "type"   "branch")
1344   (set (attr "length")
1345	(if_then_else (match_test "!CROSSING_JUMP_P (insn)")
1346		      (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -65500))
1347					 (le (minus (match_dup 2) (pc)) (const_int  65500)))
1348				    (const_int 4)
1349				    (const_int 10))
1350		      (const_int 10)))])
1351
1352
1353(define_expand "cstoresi4"
1354  [(set (match_operand:SI 0 "register_operand" "")
1355	(match_operator:SI 1 "comparison_operator"
1356	  [(match_operand:SI 2 "register_operand" "")
1357	   (match_operand:SI 3 "nonmemory_operand" "")]))]
1358  ""
1359{
1360  enum nds32_expand_result_type result = nds32_expand_cstore (operands);
1361  switch (result)
1362    {
1363    case EXPAND_DONE:
1364      DONE;
1365      break;
1366    case EXPAND_FAIL:
1367      FAIL;
1368      break;
1369    case EXPAND_CREATE_TEMPLATE:
1370      break;
1371    default:
1372      gcc_unreachable ();
1373    }
1374})
1375
1376
1377(define_expand "slts_compare"
1378  [(set (match_operand:SI 0 "register_operand"       "")
1379	(lt:SI (match_operand:SI 1 "general_operand" "")
1380	       (match_operand:SI 2 "general_operand" "")))]
1381  ""
1382{
1383  if (!REG_P (operands[1]))
1384    operands[1] = force_reg (SImode, operands[1]);
1385
1386  if (!REG_P (operands[2]) && !satisfies_constraint_Is15 (operands[2]))
1387    operands[2] = force_reg (SImode, operands[2]);
1388})
1389
1390(define_insn "slts_compare_impl"
1391  [(set (match_operand:SI 0 "register_operand"             "=t,   t, r,    r")
1392	(lt:SI (match_operand:SI 1 "register_operand"      " d,   d, r,    r")
1393	       (match_operand:SI 2 "nds32_rimm15s_operand" " r,Iu05, r, Is15")))]
1394  ""
1395  "@
1396   slts45\t%1, %2
1397   sltsi45\t%1, %2
1398   slts\t%0, %1, %2
1399   sltsi\t%0, %1, %2"
1400  [(set_attr "type"   "alu,    alu,    alu,    alu")
1401   (set_attr "length" "  2,      2,      4,      4")])
1402
1403(define_insn "slt_eq0"
1404  [(set (match_operand:SI 0 "register_operand"        "=t, r")
1405	(eq:SI (match_operand:SI 1 "register_operand" " d, r")
1406	       (const_int 0)))]
1407  ""
1408  "@
1409   slti45\t%1, 1
1410   slti\t%0, %1, 1"
1411  [(set_attr "type"   "alu, alu")
1412   (set_attr "length" "  2,   4")])
1413
1414(define_expand "slt_compare"
1415  [(set (match_operand:SI 0 "register_operand"        "")
1416	(ltu:SI (match_operand:SI 1 "general_operand" "")
1417		(match_operand:SI 2 "general_operand" "")))]
1418  ""
1419{
1420  if (!REG_P (operands[1]))
1421    operands[1] = force_reg (SImode, operands[1]);
1422
1423  if (!REG_P (operands[2]) && !satisfies_constraint_Is15 (operands[2]))
1424    operands[2] = force_reg (SImode, operands[2]);
1425})
1426
1427(define_insn "slt_compare_impl"
1428  [(set (match_operand:SI 0 "register_operand"              "=t,    t, r,    r")
1429	(ltu:SI (match_operand:SI 1 "register_operand"      " d,    d, r,    r")
1430		(match_operand:SI 2 "nds32_rimm15s_operand" " r, Iu05, r, Is15")))]
1431  ""
1432  "@
1433   slt45\t%1, %2
1434   slti45\t%1, %2
1435   slt\t%0, %1, %2
1436   slti\t%0, %1, %2"
1437  [(set_attr "type"   "alu,    alu,    alu,    alu")
1438   (set_attr "length" "  2,      2,      4,      4")])
1439
1440
1441;; ----------------------------------------------------------------------------
1442
1443;; Unconditional and other jump instructions.
1444
1445(define_insn "jump"
1446  [(set (pc) (label_ref (match_operand 0 "" "")))]
1447  ""
1448{
1449  /* This unconditional jump has two forms:
1450       32-bit instruction => j   imm24s << 1
1451       16-bit instruction => j8  imm8s << 1
1452
1453     For 32-bit case,
1454     we assume it is always reachable.
1455     For 16-bit case,
1456     it must satisfy { 255 >= (label - pc) >= -256 } condition.
1457     However, since the $pc for nds32 is at the beginning of the instruction,
1458     we should leave some length space for current insn.
1459     So we use range -250 ~ 250.  */
1460  switch (get_attr_length (insn))
1461    {
1462    case 2:
1463      return "j8\t%0";
1464    case 4:
1465      return "j\t%0";
1466    default:
1467      gcc_unreachable ();
1468    }
1469}
1470  [(set_attr "type" "branch")
1471   (set_attr "enabled" "yes")
1472   (set (attr "length")
1473	(if_then_else (match_test "!CROSSING_JUMP_P (insn)")
1474		      (if_then_else (and (ge (minus (match_dup 0) (pc)) (const_int -250))
1475					 (le (minus (match_dup 0) (pc)) (const_int  250)))
1476				    (if_then_else (match_test "TARGET_16_BIT")
1477						  (const_int 2)
1478						  (const_int 4))
1479				    (const_int 4))
1480		      (const_int 4)))])
1481
1482(define_insn "indirect_jump"
1483  [(set (pc) (match_operand:SI 0 "register_operand" "r, r"))]
1484  ""
1485  "@
1486   jr5\t%0
1487   jr\t%0"
1488  [(set_attr "type"   "branch,branch")
1489   (set_attr "length" "     2,     4")])
1490
1491;; Subroutine call instruction returning no value.
1492;;   operands[0]: It should be a mem RTX whose address is
1493;;                the address of the function.
1494;;   operands[1]: It is the number of bytes of arguments pushed as a const_int.
1495;;   operands[2]: It is the number of registers used as operands.
1496
1497(define_expand "call"
1498  [(parallel [(call (match_operand 0 "memory_operand" "")
1499		    (match_operand 1))
1500	      (clobber (reg:SI LP_REGNUM))
1501	      (clobber (reg:SI TA_REGNUM))])]
1502  ""
1503  {
1504    rtx insn;
1505    rtx sym = XEXP (operands[0], 0);
1506
1507    if (TARGET_ICT_MODEL_LARGE
1508	&& nds32_indirect_call_referenced_p (sym))
1509      {
1510	rtx reg = gen_reg_rtx (Pmode);
1511	emit_move_insn (reg, sym);
1512	operands[0] = gen_const_mem (Pmode, reg);
1513      }
1514
1515    if (flag_pic)
1516      {
1517	insn = emit_call_insn (gen_call_internal
1518			       (XEXP (operands[0], 0), GEN_INT (0)));
1519	use_reg (&CALL_INSN_FUNCTION_USAGE (insn), pic_offset_table_rtx);
1520	DONE;
1521      }
1522  }
1523)
1524
1525(define_insn "call_internal"
1526  [(parallel [(call (mem:SI (match_operand:SI 0 "nds32_call_address_operand" "r, S"))
1527		    (match_operand 1))
1528	      (clobber (reg:SI LP_REGNUM))
1529	      (clobber (reg:SI TA_REGNUM))])]
1530  ""
1531{
1532  rtx_insn *next_insn = next_active_insn (insn);
1533  bool align_p = (!(next_insn && get_attr_length (next_insn) == 2))
1534		 && NDS32_ALIGN_P ();
1535  switch (which_alternative)
1536    {
1537    case 0:
1538      if (TARGET_16_BIT)
1539	{
1540	  if (align_p)
1541	    return "jral5\t%0\;.align 2";
1542	  else
1543	    return "jral5\t%0";
1544	}
1545      else
1546	{
1547	  if (align_p)
1548	    return "jral\t%0\;.align 2";
1549	  else
1550	    return "jral\t%0";
1551	}
1552    case 1:
1553      return nds32_output_call (insn, operands, operands[0],
1554				"bal\t%0", "jal\t%0", align_p);
1555    default:
1556      gcc_unreachable ();
1557    }
1558}
1559  [(set_attr "enabled" "yes")
1560   (set_attr "type" "branch")
1561   (set_attr_alternative "length"
1562     [
1563       ;; Alternative 0
1564       (if_then_else (match_test "TARGET_16_BIT")
1565		     (const_int 2)
1566		     (const_int 4))
1567       ;; Alternative 1
1568       (if_then_else (match_test "flag_pic")
1569		     (const_int 16)
1570		     (if_then_else (match_test "nds32_long_call_p (operands[0])")
1571				   (const_int 12)
1572				   (const_int 4)))
1573     ])]
1574)
1575
1576;; Subroutine call instruction returning a value.
1577;;   operands[0]: It is the hard regiser in which the value is returned.
1578;;   The rest three operands are the same as the
1579;;   three operands of the 'call' instruction.
1580;;   (but with numbers increased by one)
1581
1582(define_expand "call_value"
1583  [(parallel [(set (match_operand 0)
1584		   (call (match_operand 1 "memory_operand" "")
1585		         (match_operand 2)))
1586	      (clobber (reg:SI LP_REGNUM))
1587	      (clobber (reg:SI TA_REGNUM))])]
1588  ""
1589  {
1590    rtx insn;
1591    rtx sym = XEXP (operands[1], 0);
1592
1593    if (TARGET_ICT_MODEL_LARGE
1594	&& nds32_indirect_call_referenced_p (sym))
1595      {
1596	rtx reg = gen_reg_rtx (Pmode);
1597	emit_move_insn (reg, sym);
1598	operands[1] = gen_const_mem (Pmode, reg);
1599      }
1600
1601    if (flag_pic)
1602      {
1603	insn =
1604	  emit_call_insn (gen_call_value_internal
1605			  (operands[0], XEXP (operands[1], 0), GEN_INT (0)));
1606	use_reg (&CALL_INSN_FUNCTION_USAGE (insn), pic_offset_table_rtx);
1607	DONE;
1608      }
1609  }
1610)
1611
1612(define_insn "call_value_internal"
1613  [(parallel [(set (match_operand 0)
1614		   (call (mem:SI (match_operand:SI 1 "nds32_call_address_operand" "r, S"))
1615		         (match_operand 2)))
1616	      (clobber (reg:SI LP_REGNUM))
1617	      (clobber (reg:SI TA_REGNUM))])]
1618  ""
1619{
1620  rtx_insn *next_insn = next_active_insn (insn);
1621  bool align_p = (!(next_insn && get_attr_length (next_insn) == 2))
1622		 && NDS32_ALIGN_P ();
1623  switch (which_alternative)
1624    {
1625    case 0:
1626      if (TARGET_16_BIT)
1627	{
1628	  if (align_p)
1629	    return "jral5\t%1\;.align 2";
1630	  else
1631	    return "jral5\t%1";
1632	}
1633      else
1634	{
1635	  if (align_p)
1636	    return "jral\t%1\;.align 2";
1637	  else
1638	    return "jral\t%1";
1639	}
1640    case 1:
1641      return nds32_output_call (insn, operands, operands[1],
1642				"bal\t%1", "jal\t%1", align_p);
1643    default:
1644      gcc_unreachable ();
1645    }
1646}
1647  [(set_attr "enabled" "yes")
1648   (set_attr "type" "branch")
1649   (set_attr_alternative "length"
1650     [
1651       ;; Alternative 0
1652       (if_then_else (match_test "TARGET_16_BIT")
1653		     (const_int 2)
1654		     (const_int 4))
1655       ;; Alternative 1
1656       (if_then_else (match_test "flag_pic")
1657		     (const_int 16)
1658		     (if_then_else (match_test "nds32_long_call_p (operands[1])")
1659				   (const_int 12)
1660				   (const_int 4)))
1661     ])]
1662)
1663
1664;; Call subroutine returning any type.
1665
1666(define_expand "untyped_call"
1667  [(parallel [(call (match_operand 0 "" "")
1668		    (const_int 0))
1669	      (match_operand 1 "" "")
1670	      (match_operand 2 "" "")])]
1671  ""
1672{
1673  int i;
1674
1675  emit_call_insn (gen_call (operands[0], const0_rtx));
1676
1677  for (i = 0; i < XVECLEN (operands[2], 0); i++)
1678    {
1679      rtx set = XVECEXP (operands[2], 0, i);
1680      emit_move_insn (SET_DEST (set), SET_SRC (set));
1681    }
1682
1683  /* The optimizer does not know that the call sets the function value
1684     registers we stored in the result block.  We avoid problems by
1685     claiming that all hard registers are used and clobbered at this
1686     point.  */
1687  emit_insn (gen_blockage ());
1688  DONE;
1689})
1690
1691;; ----------------------------------------------------------------------------
1692
1693;; The sibcall patterns.
1694
1695;; sibcall
1696;; sibcall_internal
1697
1698(define_expand "sibcall"
1699  [(parallel [(call (match_operand 0 "memory_operand" "")
1700		    (const_int 0))
1701	      (clobber (reg:SI TA_REGNUM))
1702	      (return)])]
1703  ""
1704{
1705    rtx sym = XEXP (operands[0], 0);
1706
1707    if (TARGET_ICT_MODEL_LARGE
1708	&& nds32_indirect_call_referenced_p (sym))
1709      {
1710	rtx reg = gen_reg_rtx (Pmode);
1711	emit_move_insn (reg, sym);
1712	operands[0] = gen_const_mem (Pmode, reg);
1713      }
1714})
1715
1716(define_insn "sibcall_internal"
1717  [(parallel [(call (mem:SI (match_operand:SI 0 "nds32_call_address_operand" "r, S"))
1718		    (match_operand 1))
1719	      (clobber (reg:SI TA_REGNUM))
1720	      (return)])]
1721  ""
1722{
1723  switch (which_alternative)
1724    {
1725    case 0:
1726      if (TARGET_16_BIT)
1727	return "jr5\t%0";
1728      else
1729	return "jr\t%0";
1730    case 1:
1731      if (nds32_long_call_p (operands[0]))
1732	return "b\t%0";
1733      else
1734	return "j\t%0";
1735    default:
1736      gcc_unreachable ();
1737    }
1738}
1739  [(set_attr "enabled" "yes")
1740   (set_attr "type" "branch")
1741   (set_attr_alternative "length"
1742     [
1743       ;; Alternative 0
1744       (if_then_else (match_test "TARGET_16_BIT")
1745		     (const_int 2)
1746		     (const_int 4))
1747       ;; Alternative 1
1748       (if_then_else (match_test "flag_pic")
1749		     (const_int 16)
1750		     (if_then_else (match_test "nds32_long_call_p (operands[0])")
1751				   (const_int 12)
1752				   (const_int 4)))
1753     ])]
1754)
1755
1756;; sibcall_value
1757;; sibcall_value_internal
1758;; sibcall_value_immediate
1759
1760(define_expand "sibcall_value"
1761  [(parallel [(set (match_operand 0)
1762		   (call (match_operand 1 "memory_operand" "")
1763			 (const_int 0)))
1764	      (clobber (reg:SI TA_REGNUM))
1765	      (return)])]
1766  ""
1767{
1768    rtx sym = XEXP (operands[1], 0);
1769
1770    if (TARGET_ICT_MODEL_LARGE
1771	&& nds32_indirect_call_referenced_p (sym))
1772      {
1773	rtx reg = gen_reg_rtx (Pmode);
1774	emit_move_insn (reg, sym);
1775	operands[1] = gen_const_mem (Pmode, reg);
1776      }
1777})
1778
1779(define_insn "sibcall_value_internal"
1780  [(parallel [(set (match_operand 0)
1781		   (call (mem:SI (match_operand:SI 1 "nds32_call_address_operand" "r, S"))
1782			 (match_operand 2)))
1783	      (clobber (reg:SI TA_REGNUM))
1784	      (return)])]
1785  ""
1786{
1787  switch (which_alternative)
1788    {
1789    case 0:
1790      if (TARGET_16_BIT)
1791	return "jr5\t%1";
1792      else
1793	return "jr\t%1";
1794    case 1:
1795      if (nds32_long_call_p (operands[1]))
1796	return "b\t%1";
1797      else
1798	return "j\t%1";
1799    default:
1800      gcc_unreachable ();
1801    }
1802}
1803  [(set_attr "enabled" "yes")
1804   (set_attr "type" "branch")
1805   (set_attr_alternative "length"
1806     [
1807       ;; Alternative 0
1808       (if_then_else (match_test "TARGET_16_BIT")
1809		     (const_int 2)
1810		     (const_int 4))
1811       ;; Alternative 1
1812       (if_then_else (match_test "flag_pic")
1813		     (const_int 16)
1814		     (if_then_else (match_test "nds32_long_call_p (operands[1])")
1815				   (const_int 12)
1816				   (const_int 4)))
1817     ])]
1818)
1819
1820;; ----------------------------------------------------------------------------
1821
1822;; prologue and epilogue.
1823
1824(define_expand "prologue" [(const_int 0)]
1825  ""
1826{
1827  /* Note that only under V3/V3M ISA, we could use v3push prologue.
1828     In addition, we need to check if v3push is indeed available.  */
1829  if (NDS32_V3PUSH_AVAILABLE_P)
1830    nds32_expand_prologue_v3push ();
1831  else
1832    nds32_expand_prologue ();
1833
1834  /* If cfun->machine->fp_as_gp_p is true, we can generate special
1835     directive to guide linker doing fp-as-gp optimization.
1836     However, for a naked function, which means
1837     it should not have prologue/epilogue,
1838     using fp-as-gp still requires saving $fp by push/pop behavior and
1839     there is no benefit to use fp-as-gp on such small function.
1840     So we need to make sure this function is NOT naked as well.  */
1841  if (cfun->machine->fp_as_gp_p && !cfun->machine->naked_p)
1842    emit_insn (gen_omit_fp_begin (gen_rtx_REG (SImode, FP_REGNUM)));
1843
1844  DONE;
1845})
1846
1847(define_expand "epilogue" [(const_int 0)]
1848  ""
1849{
1850  /* If cfun->machine->fp_as_gp_p is true, we can generate special
1851     directive to guide linker doing fp-as-gp optimization.
1852     However, for a naked function, which means
1853     it should not have prologue/epilogue,
1854     using fp-as-gp still requires saving $fp by push/pop behavior and
1855     there is no benefit to use fp-as-gp on such small function.
1856     So we need to make sure this function is NOT naked as well.  */
1857  if (cfun->machine->fp_as_gp_p && !cfun->machine->naked_p)
1858    emit_insn (gen_omit_fp_end (gen_rtx_REG (SImode, FP_REGNUM)));
1859
1860  /* Note that only under V3/V3M ISA, we could use v3pop epilogue.
1861     In addition, we need to check if v3push is indeed available.  */
1862  if (NDS32_V3PUSH_AVAILABLE_P)
1863    nds32_expand_epilogue_v3pop (false);
1864  else
1865    nds32_expand_epilogue (false);
1866  DONE;
1867})
1868
1869(define_expand "sibcall_epilogue" [(const_int 0)]
1870  ""
1871{
1872  /* Pass true to indicate that this is sibcall epilogue and
1873     exit from a function without the final branch back to the
1874     calling function.  */
1875  nds32_expand_epilogue (true);
1876
1877  DONE;
1878})
1879
1880
1881;; nop instruction.
1882
1883(define_insn "nop"
1884  [(const_int 0)]
1885  ""
1886{
1887  if (TARGET_16_BIT)
1888    return "nop16";
1889  else
1890    return "nop";
1891}
1892  [(set_attr "type" "misc")
1893   (set_attr "enabled" "yes")
1894   (set (attr "length")
1895	(if_then_else (match_test "TARGET_16_BIT")
1896		      (const_int 2)
1897		      (const_int 4)))])
1898
1899
1900;; ----------------------------------------------------------------------------
1901;; Stack push/pop operations
1902;; ----------------------------------------------------------------------------
1903
1904;; The pattern for stack push.
1905;; Both stack_push_multiple and stack_v3push use the following pattern.
1906;; So we need to use TARGET_V3PUSH to determine the instruction length.
1907(define_insn "*stack_push"
1908  [(match_parallel 0 "nds32_stack_push_operation"
1909     [(set (mem:SI (plus:SI (reg:SI SP_REGNUM)
1910			    (match_operand:SI 1 "const_int_operand" "")))
1911	   (match_operand:SI 2 "register_operand" ""))
1912     ])]
1913  ""
1914{
1915  return nds32_output_stack_push (operands[0]);
1916}
1917  [(set_attr "type" "store_multiple")
1918   (set_attr "combo" "12")
1919   (set_attr "enabled" "yes")
1920   (set (attr "length")
1921	(if_then_else (match_test "NDS32_V3PUSH_AVAILABLE_P")
1922		      (const_int 2)
1923		      (const_int 4)))])
1924
1925
1926;; The pattern for stack pop.
1927;; Both stack_pop_multiple and stack_v3pop use the following pattern.
1928;; So we need to use TARGET_V3PUSH to determine the instruction length.
1929(define_insn "*stack_pop"
1930  [(match_parallel 0 "nds32_stack_pop_operation"
1931     [(set (match_operand:SI 1 "register_operand" "")
1932	   (mem:SI (reg:SI SP_REGNUM)))
1933     ])]
1934  ""
1935{
1936  return nds32_output_stack_pop (operands[0]);
1937}
1938  [(set_attr "type" "load_multiple")
1939   (set_attr "combo" "12")
1940   (set_attr "enabled" "yes")
1941   (set (attr "length")
1942	(if_then_else (match_test "NDS32_V3PUSH_AVAILABLE_P")
1943		      (const_int 2)
1944		      (const_int 4)))])
1945
1946
1947;; ----------------------------------------------------------------------------
1948;; Return operation patterns
1949;; ----------------------------------------------------------------------------
1950
1951;; Use this pattern to expand a return instruction
1952;; with simple_return rtx if no epilogue is required.
1953(define_expand "return"
1954  [(parallel [(return)
1955              (clobber (reg:SI FP_REGNUM))])]
1956  "nds32_can_use_return_insn ()"
1957{
1958  /* Emit as the simple return.  */
1959  if (!cfun->machine->fp_as_gp_p
1960      && cfun->machine->naked_p
1961      && (cfun->machine->va_args_size == 0))
1962    {
1963      emit_jump_insn (gen_return_internal ());
1964      DONE;
1965    }
1966})
1967
1968;; This pattern is expanded only by the shrink-wrapping optimization
1969;; on paths where the function prologue has not been executed.
1970;; However, such optimization may reorder the prologue/epilogue blocks
1971;; together with basic blocks within function body.
1972;; So we must disable this pattern if we have already decided
1973;; to perform fp_as_gp optimization, which requires prologue to be
1974;; first block and epilogue to be last block.
1975(define_expand "simple_return"
1976  [(simple_return)]
1977  "!cfun->machine->fp_as_gp_p"
1978  ""
1979)
1980
1981(define_insn "*nds32_return"
1982  [(parallel [(return)
1983   (clobber (reg:SI FP_REGNUM))])]
1984  ""
1985{
1986  return nds32_output_return ();
1987}
1988  [(set_attr "type" "branch")
1989   (set_attr "enabled" "yes")
1990   (set_attr "length" "4")])
1991
1992(define_insn "return_internal"
1993  [(simple_return)]
1994  ""
1995{
1996  if (nds32_isr_function_critical_p (current_function_decl))
1997    return "iret";
1998
1999  if (TARGET_16_BIT)
2000    return "ret5";
2001  else
2002    return "ret";
2003}
2004  [(set_attr "type" "branch")
2005   (set_attr "enabled" "yes")
2006   (set (attr "length")
2007	(if_then_else (match_test "nds32_isr_function_critical_p (current_function_decl)")
2008		      (const_int 4)
2009		      (if_then_else (match_test "TARGET_16_BIT")
2010				    (const_int 2)
2011				    (const_int 4))))])
2012
2013
2014;; ----------------------------------------------------------------------------
2015;; Jump Table patterns
2016;; ----------------------------------------------------------------------------
2017;; Need to implement ASM_OUTPUT_ADDR_VEC_ELT (for normal jump table)
2018;; or ASM_OUTPUT_ADDR_DIFF_ELT (for pc relative jump table) as well.
2019;;
2020;; operands[0]: The index to dispatch on.
2021;; operands[1]: The lower bound for indices in the table.
2022;; operands[2]: The total range of indices int the table.
2023;;              i.e. The largest index minus the smallest one.
2024;; operands[3]: A label that precedes the table itself.
2025;; operands[4]: A label to jump to if the index has a value outside the bounds.
2026;;
2027;; We need to create following sequences for jump table code generation:
2028;;   A) k <-- (plus (operands[0]) (-operands[1]))
2029;;   B) if (gtu k operands[2]) then goto operands[4]
2030;;   C) t <-- operands[3]
2031;;   D) z <-- (mem (plus (k << 0 or 1 or 2) t))
2032;;   E) z <-- t + z (NOTE: This is only required for pc relative jump table.)
2033;;   F) jump to target with register t or z
2034;;
2035;; The steps C, D, E, and F are performed by casesi_internal pattern.
2036(define_expand "casesi"
2037  [(match_operand:SI 0 "register_operand"  "r") ; index to jump on
2038   (match_operand:SI 1 "immediate_operand" "i") ; lower bound
2039   (match_operand:SI 2 "immediate_operand" "i") ; total range
2040   (match_operand:SI 3 "" "")                   ; table label
2041   (match_operand:SI 4 "" "")]                  ; Out of range label
2042  ""
2043{
2044  rtx add_tmp;
2045  rtx reg, test;
2046  rtx tmp_reg;
2047
2048  /* Step A: "k <-- (plus (operands[0]) (-operands[1]))".  */
2049  if (operands[1] != const0_rtx)
2050    {
2051      reg = gen_reg_rtx (SImode);
2052      add_tmp = gen_int_mode (-INTVAL (operands[1]), SImode);
2053
2054      /* If the integer value is not in the range of imm15s,
2055	 we need to force register first because our addsi3 pattern
2056	 only accept nds32_rimm15s_operand predicate.  */
2057      add_tmp = force_reg (SImode, add_tmp);
2058
2059      emit_insn (gen_addsi3 (reg, operands[0], add_tmp));
2060      operands[0] = reg;
2061    }
2062
2063  /* Step B: "if (gtu k operands[2]) then goto operands[4]".  */
2064  test = gen_rtx_GTU (VOIDmode, operands[0], operands[2]);
2065  emit_jump_insn (gen_cbranchsi4 (test, operands[0], operands[2],
2066				  operands[4]));
2067
2068  tmp_reg = gen_reg_rtx (SImode);
2069  /* Step C, D, E, and F, using another temporary register tmp_reg.  */
2070  if (flag_pic)
2071    emit_use (pic_offset_table_rtx);
2072
2073  emit_jump_insn (gen_casesi_internal (operands[0],
2074				       operands[3],
2075				       tmp_reg));
2076  DONE;
2077})
2078
2079;; We are receiving operands from casesi pattern:
2080;;
2081;; operands[0]: The index that have been substracted with lower bound.
2082;; operands[1]: A label that precedes the table itself.
2083;; operands[2]: A temporary register to retrieve value in table.
2084;;
2085;; We need to perform steps C, D, E, and F:
2086;;
2087;;   C) t <-- operands[1]
2088;;   D) z <-- (mem (plus (operands[0] << m) t))
2089;;            m is 2 for normal jump table.
2090;;            m is 0, 1, or 2 for pc relative jump table based on diff size.
2091;;   E) t <-- z + t (NOTE: This is only required for pc relative jump table.)
2092;;   F) Jump to target with register t or z.
2093;;
2094;; The USE in this pattern is needed to tell flow analysis that this is
2095;; a CASESI insn.  It has no other purpose.
2096(define_insn "casesi_internal"
2097  [(parallel [(set (pc)
2098		   (mem:SI (plus:SI (mult:SI (match_operand:SI 0 "register_operand" "r")
2099					     (const_int 4))
2100				    (label_ref (match_operand 1 "" "")))))
2101	      (use (label_ref (match_dup 1)))
2102	      (clobber (match_operand:SI 2 "register_operand" "=r"))
2103	      (clobber (reg:SI TA_REGNUM))])]
2104  ""
2105{
2106  if (CASE_VECTOR_PC_RELATIVE)
2107    return nds32_output_casesi_pc_relative (operands);
2108  else
2109    return nds32_output_casesi (operands);
2110}
2111  [(set_attr "type" "branch")
2112   (set (attr "length")
2113	(if_then_else (match_test "flag_pic")
2114		      (const_int 28)
2115		      (const_int 20)))])
2116
2117;; ----------------------------------------------------------------------------
2118
2119;; Performance Extension
2120
2121; If -fwrapv option is issued, GCC expects there will be
2122; signed overflow situation.  So the ABS(INT_MIN) is still INT_MIN
2123; (e.g. ABS(0x80000000)=0x80000000).
2124; However, the hardware ABS instruction of nds32 target
2125; always performs saturation: abs 0x80000000 -> 0x7fffffff.
2126; So that we can only enable abssi2 pattern if flag_wrapv is NOT presented.
2127(define_insn "abssi2"
2128  [(set (match_operand:SI 0 "register_operand"         "=r")
2129	(abs:SI (match_operand:SI 1 "register_operand" " r")))]
2130  "TARGET_EXT_PERF && TARGET_HW_ABS && !flag_wrapv"
2131  "abs\t%0, %1"
2132  [(set_attr "type" "alu")
2133   (set_attr "length" "4")])
2134
2135(define_insn "clzsi2"
2136  [(set (match_operand:SI 0 "register_operand"         "=r")
2137	(clz:SI (match_operand:SI 1 "register_operand" " r")))]
2138  "TARGET_EXT_PERF"
2139  "clz\t%0, %1"
2140  [(set_attr "type" "alu")
2141   (set_attr "length" "4")])
2142
2143(define_insn "smaxsi3"
2144  [(set (match_operand:SI 0 "register_operand"          "=r")
2145	(smax:SI (match_operand:SI 1 "register_operand" " r")
2146		 (match_operand:SI 2 "register_operand" " r")))]
2147  "TARGET_EXT_PERF"
2148  "max\t%0, %1, %2"
2149  [(set_attr "type" "alu")
2150   (set_attr "length" "4")])
2151
2152(define_insn "sminsi3"
2153  [(set (match_operand:SI 0 "register_operand"          "=r")
2154	(smin:SI (match_operand:SI 1 "register_operand" " r")
2155		 (match_operand:SI 2 "register_operand" " r")))]
2156  "TARGET_EXT_PERF"
2157  "min\t%0, %1, %2"
2158  [(set_attr "type" "alu")
2159   (set_attr "length" "4")])
2160
2161(define_insn "btst"
2162  [(set (match_operand:SI 0 "register_operand"                     "=   r")
2163	(zero_extract:SI (match_operand:SI 1 "register_operand"    "    r")
2164			 (const_int 1)
2165			 (match_operand:SI 2 "nds32_imm5u_operand" " Iu05")))]
2166  "TARGET_EXT_PERF"
2167  "btst\t%0, %1, %2"
2168  [(set_attr "type" "alu")
2169   (set_attr "length" "4")])
2170
2171(define_insn "ave"
2172  [(set (match_operand:SI 0 "register_operand" "=r")
2173	(truncate:SI
2174	  (ashiftrt:DI
2175	    (plus:DI
2176	      (plus:DI
2177		(sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
2178		(sign_extend:DI (match_operand:SI 2 "register_operand" "r")))
2179	      (const_int 1))
2180	  (const_int 1))))]
2181  "TARGET_EXT_PERF"
2182  "ave\t%0, %1, %2"
2183  [(set_attr "type" "alu")
2184   (set_attr "length" "4")])
2185
2186;; ----------------------------------------------------------------------------
2187
2188;; Pseudo NOPs
2189
2190(define_insn "relax_group"
2191  [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "i")] UNSPEC_VOLATILE_RELAX_GROUP)]
2192  ""
2193  ".relax_hint %0"
2194  [(set_attr "length" "0")]
2195)
2196
2197;; Output .omit_fp_begin for fp-as-gp optimization.
2198;; Also we have to set $fp register.
2199(define_insn "omit_fp_begin"
2200  [(set (match_operand:SI 0 "register_operand" "=x")
2201	(unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_OMIT_FP_BEGIN))]
2202  ""
2203  "! -----\;.omit_fp_begin\;la\t$fp,_FP_BASE_\;! -----"
2204  [(set_attr "length" "8")]
2205)
2206
2207;; Output .omit_fp_end for fp-as-gp optimization.
2208;; Claim that we have to use $fp register.
2209(define_insn "omit_fp_end"
2210  [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "x")] UNSPEC_VOLATILE_OMIT_FP_END)]
2211  ""
2212  "! -----\;.omit_fp_end\;! -----"
2213  [(set_attr "length" "0")]
2214)
2215
2216(define_insn "pop25return"
2217  [(return)
2218   (unspec_volatile:SI [(reg:SI LP_REGNUM)] UNSPEC_VOLATILE_POP25_RETURN)]
2219  ""
2220  "! return for pop 25"
2221  [(set_attr "length" "0")]
2222)
2223
2224;; Add pc
2225(define_insn "add_pc"
2226  [(set (match_operand:SI 0 "register_operand"          "=r")
2227	(plus:SI (match_operand:SI 1 "register_operand"  "0")
2228		 (pc)))]
2229  "TARGET_LINUX_ABI || flag_pic"
2230  "add5.pc\t%0"
2231  [(set_attr "type"    "alu")
2232   (set_attr "length"    "4")]
2233)
2234
2235(define_expand "bswapsi2"
2236  [(set (match_operand:SI 0 "register_operand" "=r")
2237	(bswap:SI (match_operand:SI 1 "register_operand" "r")))]
2238  ""
2239{
2240  emit_insn (gen_unspec_wsbh (operands[0], operands[1]));
2241  emit_insn (gen_rotrsi3 (operands[0], operands[0], GEN_INT (16)));
2242  DONE;
2243})
2244
2245(define_insn "bswaphi2"
2246  [(set (match_operand:HI 0 "register_operand" "=r")
2247	(bswap:HI (match_operand:HI 1 "register_operand" "r")))]
2248  ""
2249  "wsbh\t%0, %1"
2250  [(set_attr "type"    "alu")
2251   (set_attr "length"    "4")]
2252)
2253
2254;; ----------------------------------------------------------------------------
2255
2256;; Patterns for exception handling
2257
2258(define_expand "eh_return"
2259  [(use (match_operand 0 "general_operand"))]
2260  ""
2261{
2262  emit_insn (gen_nds32_eh_return (operands[0]));
2263  DONE;
2264})
2265
2266(define_insn_and_split "nds32_eh_return"
2267  [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")] UNSPEC_VOLATILE_EH_RETURN)]
2268  ""
2269  "#"
2270  "reload_completed"
2271  [(const_int 0)]
2272{
2273  rtx place;
2274  rtx addr;
2275
2276  /* The operands[0] is the handler address.  We need to assign it
2277     to return address rtx so that we can jump to exception handler
2278     when returning from current function.  */
2279
2280  if (cfun->machine->lp_size == 0)
2281    {
2282      /* If $lp is not saved in the stack frame, we can take $lp directly.  */
2283      place = gen_rtx_REG (SImode, LP_REGNUM);
2284    }
2285  else
2286    {
2287      /* Otherwise, we need to locate the stack slot of return address.
2288	 The return address is generally saved in [$fp-4] location.
2289	 However, DSE (dead store elimination) does not detect an alias
2290	 between [$fp-x] and [$sp+y].  This can result in a store to save
2291	 $lp introduced by builtin_eh_return() being incorrectly deleted
2292	 if it is based on $fp.  The solution we take here is to compute
2293	 the offset relative to stack pointer and then use $sp to access
2294	 location so that the alias can be detected.
2295	 FIXME: What if the immediate value "offset" is too large to be
2296	        fit in a single addi instruction?  */
2297      HOST_WIDE_INT offset;
2298
2299      offset = (cfun->machine->fp_size
2300		+ cfun->machine->gp_size
2301		+ cfun->machine->lp_size
2302		+ cfun->machine->callee_saved_gpr_regs_size
2303		+ cfun->machine->callee_saved_area_gpr_padding_bytes
2304		+ cfun->machine->callee_saved_fpr_regs_size
2305		+ cfun->machine->eh_return_data_regs_size
2306		+ cfun->machine->local_size
2307		+ cfun->machine->out_args_size);
2308
2309      addr = plus_constant (Pmode, stack_pointer_rtx, offset - 4);
2310      place = gen_frame_mem (SImode, addr);
2311    }
2312
2313  emit_move_insn (place, operands[0]);
2314  DONE;
2315})
2316
2317;; ----------------------------------------------------------------------------
2318
2319;; Patterns for __builtin_trap.
2320(define_insn "trap"
2321  [(trap_if (const_int 1) (const_int 0))]
2322  ""
2323  "trap\t0")
2324
2325;; ----------------------------------------------------------------------------
2326
2327;; Patterns for TLS.
2328;; The following two tls patterns don't be expanded directly because the
2329;; intermediate value may be spilled into the stack.  As a result, it is
2330;; hard to analyze the define-use chain in the relax_opt pass.
2331
2332
2333;; There is a unspec operand to record RELAX_GROUP number because each
2334;; emitted instruction need a relax_hint above it.
2335(define_insn "tls_desc"
2336  [(set (reg:SI 0)
2337	(call (unspec_volatile:SI [(match_operand:SI 0 "nds32_symbolic_operand" "i")] UNSPEC_TLS_DESC)
2338	      (const_int 1)))
2339   (use (unspec [(match_operand:SI 1 "immediate_operand" "i")] UNSPEC_VOLATILE_RELAX_GROUP))
2340   (use (reg:SI GP_REGNUM))
2341   (clobber (reg:SI LP_REGNUM))
2342   (clobber (reg:SI TA_REGNUM))]
2343  ""
2344  {
2345    return nds32_output_tls_desc (operands);
2346  }
2347  [(set_attr "length" "20")
2348   (set_attr "type" "branch")]
2349)
2350
2351;; There is a unspec operand to record RELAX_GROUP number because each
2352;; emitted instruction need a relax_hint above it.
2353(define_insn "tls_ie"
2354  [(set (match_operand:SI 0 "register_operand" "=r")
2355	(unspec:SI [(match_operand:SI 1 "nds32_symbolic_operand" "i")] UNSPEC_TLS_IE))
2356   (use (unspec [(match_operand:SI 2 "immediate_operand" "i")] UNSPEC_VOLATILE_RELAX_GROUP))
2357   (use (reg:SI GP_REGNUM))]
2358  ""
2359  {
2360    return nds32_output_tls_ie (operands);
2361  }
2362  [(set (attr "length") (if_then_else (match_test "flag_pic")
2363				      (const_int 12)
2364				      (const_int 8)))
2365   (set_attr "type" "misc")]
2366)
2367
2368;; There is a unspec operand to record RELAX_GROUP number because each
2369;; emitted instruction need a relax_hint above it.
2370(define_insn "tls_le"
2371  [(set (match_operand:SI 0 "register_operand" "=r")
2372	(unspec:SI [(match_operand:SI 1 "nds32_symbolic_operand" "i")] UNSPEC_TLS_IE))
2373   (use (unspec [(match_operand:SI 2 "immediate_operand" "i")] UNSPEC_VOLATILE_RELAX_GROUP))]
2374  ""
2375  {
2376    return nds32_output_symrel (operands);
2377  }
2378  [(set_attr "length" "8")
2379   (set_attr "type"   "misc")]
2380)
2381
2382;; The pattern is for some relaxation groups that have to keep addsi3 in 32-bit mode.
2383(define_insn "addsi3_32bit"
2384  [(set (match_operand:SI 0 "register_operand"             "=r")
2385	(unspec:SI [(match_operand:SI 1 "register_operand" "%r")
2386		    (match_operand:SI 2 "register_operand" " r")] UNSPEC_ADD32))]
2387  ""
2388  "add\t%0, %1, %2";
2389  [(set_attr "type"    "alu")
2390   (set_attr "length"  "4")
2391   (set_attr "feature" "v1")])
2392
2393;; Patterns for PIC.
2394(define_insn "sym_got"
2395  [(set (match_operand:SI 0 "register_operand" "=r")
2396	(unspec:SI [(match_operand:SI 1 "nds32_symbolic_operand" "i")] UNSPEC_GOT))
2397   (use (unspec [(match_operand:SI 2 "immediate_operand" "i")] UNSPEC_VOLATILE_RELAX_GROUP))]
2398  ""
2399  {
2400    return nds32_output_symrel (operands);
2401  }
2402  [(set_attr "length" "8")
2403   (set_attr "type"   "misc")]
2404)
2405
2406;; ----------------------------------------------------------------------------
2407