[NDS32] Implement n7 pipeline.
[official-gcc.git] / gcc / config / nds32 / nds32.md
blob3b8107e8fbf98c4525cff6d4c3f00acaa7c25198
1 ;; Machine description of Andes NDS32 cpu for GNU compiler
2 ;; Copyright (C) 2012-2018 Free Software Foundation, Inc.
3 ;; Contributed by Andes Technology Corporation.
4 ;;
5 ;; This file is part of GCC.
6 ;;
7 ;; GCC is free software; you can redistribute it and/or modify it
8 ;; under the terms of the GNU General Public License as published
9 ;; by the Free Software Foundation; either version 3, or (at your
10 ;; option) any later version.
12 ;; GCC is distributed in the hope that it will be useful, but WITHOUT
13 ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 ;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
15 ;; License for more details.
17 ;; You should have received a copy of the GNU General Public License
18 ;; along with GCC; see the file COPYING3.  If not see
19 ;; <http://www.gnu.org/licenses/>.
21 ;; See file "rtl.def" for documentation on define_insn, match_*, et. al.
23 ;; Include predicates definition.
24 (include "predicates.md")
26 ;; Include constraints definition.
27 (include "constraints.md")
29 ;; Include iterators definition.
30 (include "iterators.md")
32 ;; Include pipelines definition.
33 (include "pipelines.md")
36 ;; Include constants definition.
37 (include "constants.md")
40 ;; Include intrinsic functions definition.
41 (include "nds32-intrinsic.md")
43 ;; Include block move for nds32 multiple load/store behavior.
44 (include "nds32-multiple.md")
46 ;; Include DImode/DFmode operations.
47 (include "nds32-doubleword.md")
49 ;; Include floating-point patterns.
50 (include "nds32-fpu.md")
52 ;; Include peephole patterns.
53 (include "nds32-peephole2.md")
56 ;; ------------------------------------------------------------------------
58 ;; CPU pipeline model.
59 (define_attr "pipeline_model" "n7,n8,e8,n9,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_SIMPLE") (const_string "simple")]
66           (const_string "n9"))))
68 ;; Insn type, it is used to default other attribute values.
69 (define_attr "type"
70   "unknown,load,store,load_multiple,store_multiple,alu,alu_shift,pbsad,pbsada,mul,mac,div,branch,mmu,misc,\
71    falu,fmuls,fmuld,fmacs,fmacd,fdivs,fdivd,fsqrts,fsqrtd,fcmp,fabs,fcpy,fcmov,fmfsr,fmfdr,fmtsr,fmtdr,fload,fstore"
72   (const_string "unknown"))
74 ;; Insn sub-type
75 (define_attr "subtype"
76   "simple,shift"
77   (const_string "simple"))
79 ;; Length, in bytes, default is 4-bytes.
80 (define_attr "length" "" (const_int 4))
82 ;; Indicate the amount of micro instructions.
83 (define_attr "combo"
84   "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"
85   (const_string "1"))
87 ;; Insn in which feature set, it is used to enable/disable insn alternatives.
88 ;; v1  : Baseline Instructions
89 ;; v2  : Baseline Version 2 Instructions
90 ;; v3m : Baseline Version 3m Instructions
91 ;; v3  : Baseline Version 3 Instructions
92 ;; pe1 : Performance Extension Instructions
93 ;; pe2 : Performance Extension Version 2 Instructions
94 ;; se  : String Extension instructions
95 (define_attr "feature"
96   "v1,v2,v3m,v3,pe1,pe2,se,fpu"
97   (const_string "v1"))
99 ;; Enabled, which is used to enable/disable insn alternatives.
100 ;; Note that we use length and TARGET_16_BIT here as criteria.
101 ;; If the instruction pattern already check TARGET_16_BIT to determine
102 ;; the length by itself, its enabled attribute should be customized to
103 ;; avoid the conflict between length attribute and this default setting.
104 (define_attr "enabled" "no,yes"
105   (if_then_else
106     (and (eq_attr "length" "2")
107          (match_test "!TARGET_16_BIT"))
108     (const_string "no")
109     (cond [(eq_attr "feature" "v1")   (const_string "yes")
110            (eq_attr "feature" "v2")   (if_then_else (match_test "TARGET_ISA_V2 || TARGET_ISA_V3 || TARGET_ISA_V3M")
111                                                     (const_string "yes")
112                                                     (const_string "no"))
113            (eq_attr "feature" "v3")   (if_then_else (match_test "TARGET_ISA_V3")
114                                                     (const_string "yes")
115                                                     (const_string "no"))
116            (eq_attr "feature" "v3m")  (if_then_else (match_test "TARGET_ISA_V3 || TARGET_ISA_V3M")
117                                                     (const_string "yes")
118                                                     (const_string "no"))
119            (eq_attr "feature" "pe1")  (if_then_else (match_test "TARGET_EXT_PERF")
120                                                     (const_string "yes")
121                                                     (const_string "no"))
122            (eq_attr "feature" "pe2")  (if_then_else (match_test "TARGET_EXT_PERF2")
123                                                     (const_string "yes")
124                                                     (const_string "no"))
125            (eq_attr "feature" "se")   (if_then_else (match_test "TARGET_EXT_STRING")
126                                                     (const_string "yes")
127                                                     (const_string "no"))
128            (eq_attr "feature" "fpu")  (if_then_else (match_test "TARGET_FPU_SINGLE || TARGET_FPU_DOUBLE")
129                                                     (const_string "yes")
130                                                     (const_string "no"))]
131            (const_string "yes"))))
134 ;; ----------------------------------------------------------------------------
137 ;; Move instructions.
139 ;; For QImode and HImode, the immediate value can be fit in imm20s.
140 ;; So there is no need to split rtx for QI and HI patterns.
142 (define_expand "mov<mode>"
143   [(set (match_operand:QIHI 0 "general_operand" "")
144         (match_operand:QIHI 1 "general_operand" ""))]
145   ""
147   /* Need to force register if mem <- !reg.  */
148   if (MEM_P (operands[0]) && !REG_P (operands[1]))
149     operands[1] = force_reg (<MODE>mode, operands[1]);
151   if (MEM_P (operands[1]) && optimize > 0)
152     {
153       rtx reg = gen_reg_rtx (SImode);
155       emit_insn (gen_zero_extend<mode>si2 (reg, operands[1]));
156       operands[1] = gen_lowpart (<MODE>mode, reg);
157     }
160 (define_expand "movmisalign<mode>"
161   [(set (match_operand:SIDI 0 "general_operand" "")
162         (match_operand:SIDI 1 "general_operand" ""))]
163   ""
165   rtx addr;
166   if (MEM_P (operands[0]) && !REG_P (operands[1]))
167     operands[1] = force_reg (<MODE>mode, operands[1]);
169   if (MEM_P (operands[0]))
170     {
171       addr = force_reg (Pmode, XEXP (operands[0], 0));
172       emit_insn (gen_unaligned_store<mode> (addr, operands[1]));
173     }
174   else
175     {
176       addr = force_reg (Pmode, XEXP (operands[1], 0));
177       emit_insn (gen_unaligned_load<mode> (operands[0], addr));
178     }
179   DONE;
182 (define_expand "movsi"
183   [(set (match_operand:SI 0 "general_operand" "")
184         (match_operand:SI 1 "general_operand" ""))]
185   ""
187   /* Need to force register if mem <- !reg.  */
188   if (MEM_P (operands[0]) && !REG_P (operands[1]))
189     operands[1] = force_reg (SImode, operands[1]);
191   /* If operands[1] is a large constant and cannot be performed
192      by a single instruction, we need to split it.  */
193   if (CONST_INT_P (operands[1])
194       && !satisfies_constraint_Is20 (operands[1])
195       && !satisfies_constraint_Ihig (operands[1]))
196     {
197       rtx high20_rtx;
198       HOST_WIDE_INT low12_int;
199       rtx tmp_rtx;
201       tmp_rtx = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0];
203       high20_rtx = gen_int_mode ((INTVAL (operands[1]) >> 12) << 12, SImode);
204       low12_int = INTVAL (operands[1]) & 0xfff;
206       emit_move_insn (tmp_rtx, high20_rtx);
207       emit_move_insn (operands[0], plus_constant (SImode,
208                                                   tmp_rtx,
209                                                   low12_int));
210       DONE;
211     }
214 (define_insn "*mov<mode>"
215   [(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")
216         (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"))]
217   "register_operand(operands[0], <MODE>mode)
218    || register_operand(operands[1], <MODE>mode)"
220   switch (which_alternative)
221     {
222     case 0:
223       return "mov55\t%0, %1";
224     case 1:
225       return "ori\t%0, %1, 0";
226     case 2:
227     case 3:
228     case 4:
229     case 5:
230       return nds32_output_16bit_store (operands, <byte>);
231     case 6:
232       return nds32_output_32bit_store (operands, <byte>);
233     case 7:
234     case 8:
235     case 9:
236     case 10:
237     case 11:
238       return nds32_output_16bit_load (operands, <byte>);
239     case 12:
240       return nds32_output_32bit_load (operands, <byte>);
241     case 13:
242       return "movpi45\t%0, %1";
243     case 14:
244       return "movi55\t%0, %1";
245     case 15:
246       return "movi\t%0, %1";
247     case 16:
248       return "sethi\t%0, hi20(%1)";
249     case 17:
250       if (TARGET_FPU_SINGLE)
251         return "fcpyss\t%0, %1, %1";
252       else
253         return "#";
254     case 18:
255       return "fmtsr\t%1, %0";
256     case 19:
257       return "fmfsr\t%0, %1";
258     case 20:
259       return nds32_output_float_load (operands);
260     case 21:
261       return nds32_output_float_store (operands);
262     default:
263       gcc_unreachable ();
264     }
266   [(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")
267    (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")
268    (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")])
271 ;; We use nds32_symbolic_operand to limit that only CONST/SYMBOL_REF/LABEL_REF
272 ;; are able to match such instruction template.
273 (define_insn "move_addr"
274   [(set (match_operand:SI 0 "register_operand"       "=l, r")
275         (match_operand:SI 1 "nds32_symbolic_operand" " i, i"))]
276   ""
277   "la\t%0, %1"
278   [(set_attr "type"  "alu")
279    (set_attr "length"  "8")])
282 (define_insn "sethi"
283   [(set (match_operand:SI 0 "register_operand"                "=r")
284         (high:SI (match_operand:SI 1 "nds32_symbolic_operand" " i")))]
285   ""
286   "sethi\t%0, hi20(%1)"
287   [(set_attr "type" "alu")
288    (set_attr "length" "4")])
291 (define_insn "lo_sum"
292   [(set (match_operand:SI 0 "register_operand"                  "=r")
293         (lo_sum:SI (match_operand:SI 1 "register_operand"       " r")
294                    (match_operand:SI 2 "nds32_symbolic_operand" " i")))]
295   ""
296   "ori\t%0, %1, lo12(%2)"
297   [(set_attr "type" "alu")
298    (set_attr "length" "4")])
301 ;; ----------------------------------------------------------------------------
303 ;; Zero extension instructions.
305 (define_insn "zero_extend<mode>si2"
306   [(set (match_operand:SI 0 "register_operand"                       "=l, r,   l, *r")
307         (zero_extend:SI (match_operand:QIHI 1 "nonimmediate_operand" " l, r, U33,  m")))]
308   ""
310   switch (which_alternative)
311     {
312     case 0:
313       return "ze<size>33\t%0, %1";
314     case 1:
315       return "ze<size>\t%0, %1";
316     case 2:
317       return nds32_output_16bit_load (operands, <byte>);
318     case 3:
319       return nds32_output_32bit_load (operands, <byte>);
321     default:
322       gcc_unreachable ();
323     }
325   [(set_attr "type"   "alu,alu,load,load")
326    (set_attr "length" "  2,  4,   2,   4")])
329 ;; Sign extension instructions.
331 (define_insn "extend<mode>si2"
332   [(set (match_operand:SI 0 "register_operand"                       "=l, r, r")
333         (sign_extend:SI (match_operand:QIHI 1 "nonimmediate_operand" " l, r, m")))]
334   ""
336   switch (which_alternative)
337     {
338     case 0:
339       return "se<size>33\t%0, %1";
340     case 1:
341       return "se<size>\t%0, %1";
342     case 2:
343       return nds32_output_32bit_load_s (operands, <byte>);
345     default:
346       gcc_unreachable ();
347     }
349   [(set_attr "type"   "alu,alu,load")
350    (set_attr "length" "  2,  4,   4")])
353 ;; ----------------------------------------------------------------------------
355 ;; Arithmetic instructions.
357 (define_insn "addsi3"
358   [(set (match_operand:SI 0 "register_operand"               "=   d,   l,   d,   l, d, l,   k,   l,    r, r")
359         (plus:SI (match_operand:SI 1 "register_operand"      "%   0,   l,   0,   l, 0, l,   0,   k,    r, r")
360                  (match_operand:SI 2 "nds32_rimm15s_operand" " In05,In03,Iu05,Iu03, r, l,Is10,Iu06, Is15, r")))]
361   ""
363   switch (which_alternative)
364     {
365     case 0:
366       /* addi Rt4,Rt4,-x  ==>  subi45 Rt4,x
367          where 0 <= x <= 31 */
368       operands[2] = gen_int_mode (-INTVAL (operands[2]), SImode);
369       return "subi45\t%0, %2";
370     case 1:
371       /* addi Rt3,Ra3,-x  ==>  subi333 Rt3,Ra3,x
372          where 0 <= x <= 7 */
373       operands[2] = gen_int_mode (-INTVAL (operands[2]), SImode);
374       return "subi333\t%0, %1, %2";
375     case 2:
376       return "addi45\t%0, %2";
377     case 3:
378       return "addi333\t%0, %1, %2";
379     case 4:
380       return "add45\t%0, %2";
381     case 5:
382       return "add333\t%0, %1, %2";
383     case 6:
384       return "addi10.sp\t%2";
385     case 7:
386       return "addri36.sp\t%0, %2";
387     case 8:
388       return "addi\t%0, %1, %2";
389     case 9:
390       return "add\t%0, %1, %2";
392     default:
393       gcc_unreachable ();
394     }
396   [(set_attr "type"    "alu,alu,alu,alu,alu,alu,alu,alu,alu,alu")
397    (set_attr "length"  "  2,  2,  2,  2,  2,  2,  2,  2,  4,  4")
398    (set_attr "feature" " v1, v1, v1, v1, v1, v1, v2, v1, v1, v1")])
400 (define_insn "subsi3"
401   [(set (match_operand:SI 0 "register_operand"                "=d, l,    r, r")
402         (minus:SI (match_operand:SI 1 "nds32_rimm15s_operand" " 0, l, Is15, r")
403                   (match_operand:SI 2 "register_operand"      " r, l,    r, r")))]
404   ""
405   "@
406    sub45\t%0, %2
407    sub333\t%0, %1, %2
408    subri\t%0, %2, %1
409    sub\t%0, %1, %2"
410   [(set_attr "type"   "alu,alu,alu,alu")
411    (set_attr "length" "  2,  2,  4,  4")])
414 ;; GCC intends to simplify (plus (ashift ...) (reg))
415 ;; into (plus (mult ...) (reg)), so our matching pattern takes 'mult'
416 ;; and needs to ensure it is exact_log2 value.
417 (define_insn "*add_slli"
418   [(set (match_operand:SI 0 "register_operand"                    "=r")
419         (plus:SI (mult:SI (match_operand:SI 1 "register_operand"  " r")
420                           (match_operand:SI 2 "immediate_operand" " i"))
421                  (match_operand:SI 3 "register_operand"           " r")))]
422   "TARGET_ISA_V3 && optimize_size
423    && (exact_log2 (INTVAL (operands[2])) != -1)
424    && (exact_log2 (INTVAL (operands[2])) <= 31)"
426   /* Get floor_log2 of the immediate value
427      so that we can generate 'add_slli' instruction.  */
428   operands[2] = GEN_INT (floor_log2 (INTVAL (operands[2])));
430   return "add_slli\t%0, %3, %1, %2";
432   [(set_attr "type" "alu_shift")
433    (set_attr "combo"        "2")
434    (set_attr "length"       "4")])
436 (define_insn "*add_srli"
437   [(set (match_operand:SI 0 "register_operand"                          "=   r")
438         (plus:SI (lshiftrt:SI (match_operand:SI 1 "register_operand"    "    r")
439                               (match_operand:SI 2 "nds32_imm5u_operand" " Iu05"))
440                  (match_operand:SI 3 "register_operand"                 "    r")))]
441   "TARGET_ISA_V3 && optimize_size"
442   "add_srli\t%0, %3, %1, %2"
443   [(set_attr "type" "alu_shift")
444    (set_attr "combo"        "2")
445    (set_attr "length"       "4")])
448 ;; GCC intends to simplify (minus (reg) (ashift ...))
449 ;; into (minus (reg) (mult ...)), so our matching pattern takes 'mult'
450 ;; and needs to ensure it is exact_log2 value.
451 (define_insn "*sub_slli"
452   [(set (match_operand:SI 0 "register_operand"                     "=r")
453         (minus:SI (match_operand:SI 1 "register_operand"           " r")
454                   (mult:SI (match_operand:SI 2 "register_operand"  " r")
455                            (match_operand:SI 3 "immediate_operand" " i"))))]
456   "TARGET_ISA_V3 && optimize_size
457    && (exact_log2 (INTVAL (operands[3])) != -1)
458    && (exact_log2 (INTVAL (operands[3])) <= 31)"
460   /* Get floor_log2 of the immediate value
461      so that we can generate 'sub_slli' instruction.  */
462   operands[3] = GEN_INT (floor_log2 (INTVAL (operands[3])));
464   return "sub_slli\t%0, %1, %2, %3";
466   [(set_attr "type" "alu_shift")
467    (set_attr "combo"        "2")
468    (set_attr "length"       "4")])
470 (define_insn "*sub_srli"
471   [(set (match_operand:SI 0 "register_operand"                           "=   r")
472         (minus:SI (match_operand:SI 1 "register_operand"                 "    r")
473                   (lshiftrt:SI (match_operand:SI 2 "register_operand"    "    r")
474                                (match_operand:SI 3 "nds32_imm5u_operand" " Iu05"))))]
475   "TARGET_ISA_V3 && optimize_size"
476   "sub_srli\t%0, %1, %2, %3"
477   [(set_attr "type" "alu_shift")
478    (set_attr "combo"        "2")
479    (set_attr "length"       "4")])
482 ;; Multiplication instructions.
484 (define_insn "mulsi3"
485   [(set (match_operand:SI 0 "register_operand"          "=w, r")
486         (mult:SI (match_operand:SI 1 "register_operand" "%0, r")
487                  (match_operand:SI 2 "register_operand" " w, r")))]
488   ""
489   "@
490    mul33\t%0, %2
491    mul\t%0, %1, %2"
492   [(set_attr "type"    "mul,mul")
493    (set_attr "length"  "  2,  4")
494    (set_attr "feature" "v3m, v1")])
496 (define_insn "mulsidi3"
497   [(set (match_operand:DI 0 "register_operand"                          "=r")
498         (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" " r"))
499                  (sign_extend:DI (match_operand:SI 2 "register_operand" " r"))))]
500   "TARGET_ISA_V2 || TARGET_ISA_V3"
501   "mulsr64\t%0, %1, %2"
502   [(set_attr "type"   "mul")
503    (set_attr "length"   "4")])
505 (define_insn "umulsidi3"
506   [(set (match_operand:DI 0 "register_operand"                          "=r")
507         (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" " r"))
508                  (zero_extend:DI (match_operand:SI 2 "register_operand" " r"))))]
509   "TARGET_ISA_V2 || TARGET_ISA_V3"
510   "mulr64\t%0, %1, %2"
511   [(set_attr "type"   "mul")
512    (set_attr "length"   "4")])
515 ;; Multiply-accumulate instructions.
517 (define_insn "*maddr32_0"
518   [(set (match_operand:SI 0 "register_operand"                   "=r")
519         (plus:SI (match_operand:SI 3 "register_operand"          " 0")
520                  (mult:SI (match_operand:SI 1 "register_operand" " r")
521                           (match_operand:SI 2 "register_operand" " r"))))]
522   ""
523   "maddr32\t%0, %1, %2"
524   [(set_attr "type"   "mac")
525    (set_attr "length"   "4")])
527 (define_insn "*maddr32_1"
528   [(set (match_operand:SI 0 "register_operand"                   "=r")
529         (plus:SI (mult:SI (match_operand:SI 1 "register_operand" " r")
530                           (match_operand:SI 2 "register_operand" " r"))
531                  (match_operand:SI 3 "register_operand"          " 0")))]
532   ""
533   "maddr32\t%0, %1, %2"
534   [(set_attr "type"   "mac")
535    (set_attr "length"   "4")])
537 (define_insn "*msubr32"
538   [(set (match_operand:SI 0 "register_operand"                    "=r")
539         (minus:SI (match_operand:SI 3 "register_operand"          " 0")
540                   (mult:SI (match_operand:SI 1 "register_operand" " r")
541                            (match_operand:SI 2 "register_operand" " r"))))]
542   ""
543   "msubr32\t%0, %1, %2"
544   [(set_attr "type"   "mac")
545    (set_attr "length"   "4")])
548 ;; Div Instructions.
550 (define_insn "divmodsi4"
551   [(set (match_operand:SI 0 "register_operand"         "=r")
552         (div:SI (match_operand:SI 1 "register_operand" " r")
553                 (match_operand:SI 2 "register_operand" " r")))
554    (set (match_operand:SI 3 "register_operand"         "=r")
555         (mod:SI (match_dup 1) (match_dup 2)))]
556   ""
557   "divsr\t%0, %3, %1, %2"
558   [(set_attr "type"   "div")
559    (set_attr "length"   "4")])
561 (define_insn "udivmodsi4"
562   [(set (match_operand:SI 0 "register_operand"          "=r")
563         (udiv:SI (match_operand:SI 1 "register_operand" " r")
564                  (match_operand:SI 2 "register_operand"  " r")))
565    (set (match_operand:SI 3 "register_operand"          "=r")
566         (umod:SI (match_dup 1) (match_dup 2)))]
567   ""
568   "divr\t%0, %3, %1, %2"
569   [(set_attr "type"   "div")
570    (set_attr "length"   "4")])
572 ;; divsr/divr will keep quotient only when quotient and remainder is the same
573 ;; register in our ISA spec, it's can reduce 1 register presure if we don't
574 ;; want remainder.
575 (define_insn "divsi4"
576   [(set (match_operand:SI 0 "register_operand"         "=r")
577         (div:SI (match_operand:SI 1 "register_operand" " r")
578                 (match_operand:SI 2 "register_operand" " r")))]
579   ""
580   "divsr\t%0, %0, %1, %2"
581   [(set_attr "type"   "div")
582    (set_attr "length"   "4")])
584 (define_insn "udivsi4"
585   [(set (match_operand:SI 0 "register_operand"          "=r")
586         (udiv:SI (match_operand:SI 1 "register_operand" " r")
587                  (match_operand:SI 2 "register_operand"  " r")))]
588   ""
589   "divr\t%0, %0, %1, %2"
590   [(set_attr "type"   "div")
591    (set_attr "length"   "4")])
593 ;; ----------------------------------------------------------------------------
595 ;; Boolean instructions.
596 ;; Note: We define the DImode versions in nds32-doubleword.md.
598 ;; ----------------------------------------------------------------------------
599 ;; 'AND' operation
600 ;; ----------------------------------------------------------------------------
602 (define_insn "bitc"
603   [(set (match_operand:SI 0 "register_operand"                 "=r")
604         (and:SI (not:SI (match_operand:SI 1 "register_operand" " r"))
605                 (match_operand:SI 2 "register_operand"         " r")))]
606   "TARGET_ISA_V3"
607   "bitc\t%0, %2, %1"
608   [(set_attr "type" "alu")
609    (set_attr "length" "4")]
612 (define_expand "andsi3"
613   [(set (match_operand:SI 0 "register_operand" "")
614         (and:SI (match_operand:SI 1 "register_operand" "")
615                 (match_operand:SI 2 "nds32_reg_constant_operand" "")))]
616   ""
618   if (CONST_INT_P (operands[2])
619       && !nds32_and_operand (operands[2], SImode))
620     {
621       nds32_expand_constant (SImode, INTVAL (operands[2]),
622                              operands[0], operands[1]);
623       DONE;
624     }
627 (define_insn "*andsi3"
628   [(set (match_operand:SI 0 "register_operand"          "=l, r,   l,   l,   l,   l,   l,   l,    r,   r,     r,    r,    r")
629         (and:SI (match_operand:SI 1 "register_operand"  "%0, r,   l,   l,   l,   l,   0,   0,    r,   r,     r,    r,    r")
630                 (match_operand:SI 2 "nds32_and_operand" " l, r,Izeb,Izeh,Ixls,Ix11,Ibms,Ifex, Izeb, Izeh, Iu15, Ii15, Ic15")))]
631   ""
633   HOST_WIDE_INT mask = INTVAL (operands[2]);
635   /* 16-bit andi instructions:
636      andi Rt3,Ra3,0xff   -> zeb33  Rt3,Ra3
637      andi Rt3,Ra3,0xffff -> zeh33  Rt3,Ra3
638      andi Rt3,Ra3,0x01   -> xlsb33 Rt3,Ra3
639      andi Rt3,Ra3,0x7ff  -> x11b33 Rt3,Ra3
640      andi Rt3,Rt3,2^imm3u          -> bmski33 Rt3,imm3u
641      andi Rt3,Rt3,(2^(imm3u+1))-1  -> fexti33 Rt3,imm3u.  */
643   switch (which_alternative)
644     {
645     case 0:
646       return "and33\t%0, %2";
647     case 1:
648       return "and\t%0, %1, %2";
649     case 2:
650       return "zeb33\t%0, %1";
651     case 3:
652       return "zeh33\t%0, %1";
653     case 4:
654       return "xlsb33\t%0, %1";
655     case 5:
656       return "x11b33\t%0, %1";
657     case 6:
658       return "bmski33\t%0, %B2";
659     case 7:
660       operands[2] = GEN_INT (floor_log2 (mask + 1) - 1);
661       return "fexti33\t%0, %2";
662     case 8:
663       return "zeb\t%0, %1";
664     case 9:
665       return "zeh\t%0, %1";
666     case 10:
667       return "andi\t%0, %1, %2";
668     case 11:
669       operands[2] = GEN_INT (~mask);
670       return "bitci\t%0, %1, %2";
671     case 12:
672       return "bclr\t%0, %1, %b2";
674     default:
675       gcc_unreachable ();
676     }
678   [(set_attr "type"    "alu,alu,alu,alu,alu,alu,alu,alu,alu,alu,alu,alu,alu")
679    (set_attr "length"  "  2,  4,  2,  2,  2,  2,  2,  2,  4,  4,  4,  4,  4")
680    (set_attr "feature" "v3m, v1, v1, v1, v1, v1,v3m,v3m, v1, v1, v1, v3,pe1")])
682 (define_insn "*and_slli"
683   [(set (match_operand:SI 0 "register_operand"                        "=   r")
684         (and:SI (ashift:SI (match_operand:SI 1 "register_operand"     "    r")
685                             (match_operand:SI 2 "nds32_imm5u_operand" " Iu05"))
686                 (match_operand:SI 3 "register_operand"                "    r")))]
687   "TARGET_ISA_V3 && optimize_size"
688   "and_slli\t%0, %3, %1, %2"
689   [(set_attr "type" "alu_shift")
690    (set_attr "length"       "4")])
692 (define_insn "*and_srli"
693   [(set (match_operand:SI 0 "register_operand"                         "=   r")
694         (and:SI (lshiftrt:SI (match_operand:SI 1 "register_operand"    "    r")
695                              (match_operand:SI 2 "nds32_imm5u_operand" " Iu05"))
696                 (match_operand:SI 3 "register_operand"                 "    r")))]
697   "TARGET_ISA_V3 && optimize_size"
698   "and_srli\t%0, %3, %1, %2"
699   [(set_attr "type" "alu_shift")
700    (set_attr "length"       "4")])
703 ;; ----------------------------------------------------------------------------
704 ;; 'OR' operation
705 ;; ----------------------------------------------------------------------------
707 ;; For V3/V3M ISA, we have 'or33' instruction.
708 ;; So we can identify 'or Rt3,Rt3,Ra3' case and set its length to be 2.
710 (define_expand "iorsi3"
711   [(set (match_operand:SI 0 "register_operand"         "")
712         (ior:SI (match_operand:SI 1 "register_operand" "")
713                 (match_operand:SI 2 "general_operand"  "")))]
714   ""
716   if (!nds32_ior_operand (operands[2], SImode))
717     operands[2] = force_reg (SImode, operands[2]);
720 (define_insn "*iorsi3"
721   [(set (match_operand:SI 0 "register_operand"          "=l, r,    r,    r")
722         (ior:SI (match_operand:SI 1 "register_operand"  "%0, r,    r,    r")
723                 (match_operand:SI 2 "nds32_ior_operand" " l, r, Iu15, Ie15")))]
724   ""
725   "@
726    or33\t%0, %2
727    or\t%0, %1, %2
728    ori\t%0, %1, %2
729    bset\t%0, %1, %B2"
730   [(set_attr "type"    "alu,alu,alu,alu")
731    (set_attr "length"  "  2,  4,  4,  4")
732    (set_attr "feature" "v3m, v1, v1,pe1")])
734 (define_insn "*or_slli"
735   [(set (match_operand:SI 0 "register_operand"                       "=   r")
736         (ior:SI (ashift:SI (match_operand:SI 1 "register_operand"    "    r")
737                            (match_operand:SI 2 "nds32_imm5u_operand" " Iu05"))
738                 (match_operand:SI 3 "register_operand"               "    r")))]
739   "TARGET_ISA_V3 && optimize_size"
740   "or_slli\t%0, %3, %1, %2"
741   [(set_attr "type" "alu_shift")
742    (set_attr "length"       "4")])
744 (define_insn "*or_srli"
745   [(set (match_operand:SI 0 "register_operand"                         "=   r")
746         (ior:SI (lshiftrt:SI (match_operand:SI 1 "register_operand"    "    r")
747                              (match_operand:SI 2 "nds32_imm5u_operand" " Iu05"))
748                 (match_operand:SI 3 "register_operand"                 "    r")))]
749   "TARGET_ISA_V3 && optimize_size"
750   "or_srli\t%0, %3, %1, %2"
751   [(set_attr "type" "alu_shift")
752    (set_attr "length"       "4")])
755 ;; ----------------------------------------------------------------------------
756 ;; 'XOR' operation
757 ;; ----------------------------------------------------------------------------
759 ;; For V3/V3M ISA, we have 'xor33' instruction.
760 ;; So we can identify 'xor Rt3,Rt3,Ra3' case and set its length to be 2.
762 (define_expand "xorsi3"
763   [(set (match_operand:SI 0 "register_operand"         "")
764         (xor:SI (match_operand:SI 1 "register_operand" "")
765                 (match_operand:SI 2 "general_operand"  "")))]
766   ""
768   if (!nds32_xor_operand (operands[2], SImode))
769     operands[2] = force_reg (SImode, operands[2]);
772 (define_insn "*xorsi3"
773   [(set (match_operand:SI 0 "register_operand"          "=l, r,    r,    r")
774         (xor:SI (match_operand:SI 1 "register_operand"  "%0, r,    r,    r")
775                 (match_operand:SI 2 "nds32_xor_operand" " l, r, Iu15, It15")))]
776   ""
777   "@
778    xor33\t%0, %2
779    xor\t%0, %1, %2
780    xori\t%0, %1, %2
781    btgl\t%0, %1, %B2"
782   [(set_attr "type"    "alu,alu,alu,alu")
783    (set_attr "length"  "  2,  4,  4,  4")
784    (set_attr "feature" "v3m, v1, v1,pe1")])
786 (define_insn "*xor_slli"
787   [(set (match_operand:SI 0 "register_operand"                     "=   r")
788         (xor:SI (ashift:SI (match_operand:SI 1 "register_operand"  "    r")
789                            (match_operand:SI 2 "nds32_imm5u_operand" " Iu05"))
790                 (match_operand:SI 3 "register_operand"             "    r")))]
791   "TARGET_ISA_V3 && optimize_size"
792   "xor_slli\t%0, %3, %1, %2"
793   [(set_attr "type" "alu_shift")
794    (set_attr "length"       "4")])
796 (define_insn "*xor_srli"
797   [(set (match_operand:SI 0 "register_operand"                         "=   r")
798         (xor:SI (lshiftrt:SI (match_operand:SI 1 "register_operand"    "    r")
799                              (match_operand:SI 2 "nds32_imm5u_operand" " Iu05"))
800                 (match_operand:SI 3 "register_operand"                 "    r")))]
801   "TARGET_ISA_V3 && optimize_size"
802   "xor_srli\t%0, %3, %1, %2"
803   [(set_attr "type" "alu_shift")
804    (set_attr "length"       "4")])
806 ;; Rotate Right Instructions.
808 (define_insn "*rotrsi3"
809   [(set (match_operand:SI 0 "register_operand"                    "=   r, r")
810           (rotatert:SI (match_operand:SI 1 "register_operand"     "    r, r")
811                        (match_operand:SI 2 "nds32_rimm5u_operand" " Iu05, r")))]
812   ""
813   "@
814    rotri\t%0, %1, %2
815    rotr\t%0, %1, %2"
816   [(set_attr "type"    "  alu,  alu")
817    (set_attr "subtype" "shift,shift")
818    (set_attr "length"  "    4,    4")])
821 ;; ----------------------------------------------------------------------------
822 ;; 'NEG' operation
823 ;; ----------------------------------------------------------------------------
825 ;; For V3/V3M ISA, we have 'neg33' instruction.
826 ;; So we can identify 'xor Rt3,Ra3' case and set its length to be 2.
827 ;; And for V2 ISA, there is NO 'neg33' instruction.
828 ;; The only option is to use 'subri A,B,0' (its semantic is 'A = 0 - B').
829 (define_insn "negsi2"
830   [(set (match_operand:SI 0 "register_operand"         "=l, r")
831         (neg:SI (match_operand:SI 1 "register_operand" " l, r")))]
832   ""
833   "@
834    neg33\t%0, %1
835    subri\t%0, %1, 0"
836   [(set_attr "type"    "alu,alu")
837    (set_attr "length"  "  2,  4")
838    (set_attr "feature" "v3m, v1")])
840 (define_expand "negsf2"
841   [(set (match_operand:SF 0 "register_operand" "")
842         (neg:SF (match_operand:SF 1 "register_operand" "")))]
843   ""
845   if (!TARGET_FPU_SINGLE && !TARGET_EXT_PERF)
846     {
847       rtx new_dst = simplify_gen_subreg (SImode, operands[0], SFmode, 0);
848       rtx new_src = simplify_gen_subreg (SImode, operands[1], SFmode, 0);
850       emit_insn (gen_xorsi3 (new_dst,
851                              new_src,
852                              gen_int_mode (0x80000000, SImode)));
854       DONE;
855     }
858 (define_expand "negdf2"
859   [(set (match_operand:DF 0 "register_operand" "")
860         (neg:DF (match_operand:DF 1 "register_operand" "")))]
861   ""
865 (define_insn_and_split "soft_negdf2"
866   [(set (match_operand:DF 0 "register_operand" "")
867         (neg:DF (match_operand:DF 1 "register_operand" "")))]
868   "!TARGET_FPU_DOUBLE"
869   "#"
870   "!TARGET_FPU_DOUBLE"
871   [(const_int 1)]
873     rtx src = operands[1];
874     rtx dst = operands[0];
875     rtx ori_dst = operands[0];
877     bool need_extra_move_for_dst_p;
878     /* FPU register can't change mode to SI directly, so we need create a
879        tmp register to handle it, and FPU register can't do `xor` or btgl.  */
880     if (HARD_REGISTER_P (src)
881         && TEST_HARD_REG_BIT (reg_class_contents[FP_REGS], REGNO (src)))
882       {
883         rtx tmp = gen_reg_rtx (DFmode);
884         emit_move_insn (tmp, src);
885         src = tmp;
886       }
888     if (HARD_REGISTER_P (dst)
889         && TEST_HARD_REG_BIT (reg_class_contents[FP_REGS], REGNO (dst)))
890       {
891         need_extra_move_for_dst_p = true;
892         rtx tmp = gen_reg_rtx (DFmode);
893         dst = tmp;
894       }
896     rtx dst_high_part = simplify_gen_subreg (
897                           SImode, dst,
898                           DFmode, subreg_highpart_offset (SImode, DFmode));
899     rtx dst_low_part = simplify_gen_subreg (
900                           SImode, dst,
901                           DFmode, subreg_lowpart_offset (SImode, DFmode));
902     rtx src_high_part = simplify_gen_subreg (
903                           SImode, src,
904                           DFmode, subreg_highpart_offset (SImode, DFmode));
905     rtx src_low_part = simplify_gen_subreg (
906                           SImode, src,
907                           DFmode, subreg_lowpart_offset (SImode, DFmode));
909     emit_insn (gen_xorsi3 (dst_high_part,
910                            src_high_part,
911                            gen_int_mode (0x80000000, SImode)));
912     emit_move_insn (dst_low_part, src_low_part);
914     if (need_extra_move_for_dst_p)
915       emit_move_insn (ori_dst, dst);
917     DONE;
921 ;; ----------------------------------------------------------------------------
922 ;; 'ONE_COMPLIMENT' operation
923 ;; ----------------------------------------------------------------------------
925 ;; For V3/V3M ISA, we have 'not33' instruction.
926 ;; So we can identify 'not Rt3,Ra3' case and set its length to be 2.
927 (define_insn "one_cmplsi2"
928   [(set (match_operand:SI 0 "register_operand"         "=w, r")
929         (not:SI (match_operand:SI 1 "register_operand" " w, r")))]
930   ""
931   "@
932    not33\t%0, %1
933    nor\t%0, %1, %1"
934   [(set_attr "type"    "alu,alu")
935    (set_attr "length"  "  2,  4")
936    (set_attr "feature" "v3m, v1")])
939 ;; ----------------------------------------------------------------------------
941 ;; Shift instructions.
943 (define_expand "<shift>si3"
944   [(set (match_operand:SI 0 "register_operand"                      "")
945         (shift_rotate:SI (match_operand:SI 1 "register_operand"     "")
946                          (match_operand:SI 2 "nds32_rimm5u_operand" "")))]
947   ""
949   if (operands[2] == const0_rtx)
950     {
951       emit_move_insn (operands[0], operands[1]);
952       DONE;
953     }
956 (define_insn "*ashlsi3"
957   [(set (match_operand:SI 0 "register_operand"                "=   l,    r, r")
958         (ashift:SI (match_operand:SI 1 "register_operand"     "    l,    r, r")
959                    (match_operand:SI 2 "nds32_rimm5u_operand" " Iu03, Iu05, r")))]
960   ""
961   "@
962    slli333\t%0, %1, %2
963    slli\t%0, %1, %2
964    sll\t%0, %1, %2"
965   [(set_attr "type"    "  alu,  alu,  alu")
966    (set_attr "subtype" "shift,shift,shift")
967    (set_attr "length"  "    2,    4,    4")])
969 (define_insn "*ashrsi3"
970   [(set (match_operand:SI 0 "register_operand"                  "=   d,    r, r")
971         (ashiftrt:SI (match_operand:SI 1 "register_operand"     "    0,    r, r")
972                      (match_operand:SI 2 "nds32_rimm5u_operand" " Iu05, Iu05, r")))]
973   ""
974   "@
975    srai45\t%0, %2
976    srai\t%0, %1, %2
977    sra\t%0, %1, %2"
978   [(set_attr "type"    "  alu,  alu,  alu")
979    (set_attr "subtype" "shift,shift,shift")
980    (set_attr "length"  "    2,    4,    4")])
982 (define_insn "*lshrsi3"
983   [(set (match_operand:SI 0 "register_operand"                  "=   d,    r, r")
984         (lshiftrt:SI (match_operand:SI 1 "register_operand"     "    0,    r, r")
985                      (match_operand:SI 2 "nds32_rimm5u_operand" " Iu05, Iu05, r")))]
986   ""
987   "@
988    srli45\t%0, %2
989    srli\t%0, %1, %2
990    srl\t%0, %1, %2"
991   [(set_attr "type"    "  alu,  alu,  alu")
992    (set_attr "subtype" "shift,shift,shift")
993    (set_attr "length"  "    2,    4,    4")])
996 ;; ----------------------------------------------------------------------------
998 ;; ----------------------------------------------------------------------------
999 ;; Conditional Move patterns
1000 ;; ----------------------------------------------------------------------------
1002 (define_expand "mov<mode>cc"
1003   [(set (match_operand:QIHISI 0 "register_operand" "")
1004         (if_then_else:QIHISI (match_operand 1 "nds32_movecc_comparison_operator" "")
1005                          (match_operand:QIHISI 2 "register_operand" "")
1006                          (match_operand:QIHISI 3 "register_operand" "")))]
1007   "TARGET_CMOV && !optimize_size"
1009   enum nds32_expand_result_type result = nds32_expand_movcc (operands);
1010   switch (result)
1011     {
1012     case EXPAND_DONE:
1013       DONE;
1014       break;
1015     case EXPAND_FAIL:
1016       FAIL;
1017       break;
1018     case EXPAND_CREATE_TEMPLATE:
1019       break;
1020     default:
1021       gcc_unreachable ();
1022     }
1025 (define_insn "cmovz<mode>"
1026   [(set (match_operand:QIHISI 0 "register_operand"                      "=r, r")
1027         (if_then_else:QIHISI (eq (match_operand:SI 1 "register_operand" " r, r")
1028                              (const_int 0))
1029                          (match_operand:QIHISI 2 "register_operand"     " r, 0")
1030                          (match_operand:QIHISI 3 "register_operand"     " 0, r")))]
1031   "TARGET_CMOV"
1032   "@
1033    cmovz\t%0, %2, %1
1034    cmovn\t%0, %3, %1"
1035   [(set_attr "type"  "alu")
1036    (set_attr "length"  "4")])
1038 (define_insn "cmovn<mode>"
1039   [(set (match_operand:QIHISI 0 "register_operand"                      "=r, r")
1040         (if_then_else:QIHISI (ne (match_operand:SI 1 "register_operand" " r, r")
1041                              (const_int 0))
1042                          (match_operand:QIHISI 2 "register_operand"     " r, 0")
1043                          (match_operand:QIHISI 3 "register_operand"     " 0, r")))]
1044   "TARGET_CMOV"
1045   "@
1046    cmovn\t%0, %2, %1
1047    cmovz\t%0, %3, %1"
1048   [(set_attr "type"  "alu")
1049    (set_attr "length"  "4")])
1051 ;; A hotfix to help RTL combiner to merge a cmovn insn and a zero_extend insn.
1052 ;; It should be removed once after we change the expansion form of the cmovn.
1053 (define_insn "*cmovn_simplified_<mode>"
1054   [(set (match_operand:QIHISI 0 "register_operand" "=r")
1055         (if_then_else:QIHISI (match_operand:SI 1 "register_operand" "r")
1056                          (match_operand:QIHISI 2 "register_operand" "r")
1057                          (match_operand:QIHISI 3 "register_operand" "0")))]
1058   ""
1059   "cmovn\t%0, %2, %1"
1060   [(set_attr "type" "alu")])
1062 ;; ----------------------------------------------------------------------------
1063 ;; Conditional Branch patterns
1064 ;; ----------------------------------------------------------------------------
1066 (define_expand "cbranchsi4"
1067   [(set (pc)
1068         (if_then_else (match_operator 0 "comparison_operator"
1069                         [(match_operand:SI 1 "register_operand"           "")
1070                          (match_operand:SI 2 "nds32_reg_constant_operand" "")])
1071                       (label_ref (match_operand 3 "" ""))
1072                       (pc)))]
1073   ""
1075   enum nds32_expand_result_type result = nds32_expand_cbranch (operands);
1076   switch (result)
1077     {
1078     case EXPAND_DONE:
1079       DONE;
1080       break;
1081     case EXPAND_FAIL:
1082       FAIL;
1083       break;
1084     case EXPAND_CREATE_TEMPLATE:
1085       break;
1086     default:
1087       gcc_unreachable ();
1088     }
1092 (define_insn "cbranchsi4_equality_zero"
1093   [(set (pc)
1094         (if_then_else (match_operator 0 "nds32_equality_comparison_operator"
1095                         [(match_operand:SI 1 "register_operand"  "t,l, r")
1096                          (const_int 0)])
1097                       (label_ref (match_operand 2 "" ""))
1098                       (pc)))]
1099   ""
1101   return nds32_output_cbranchsi4_equality_zero (insn, operands);
1103   [(set_attr "type" "branch")
1104    (set_attr_alternative "enabled"
1105      [
1106        ;; Alternative 0
1107        (if_then_else (match_test "TARGET_16_BIT")
1108                      (const_string "yes")
1109                      (const_string "no"))
1110        ;; Alternative 1
1111        (if_then_else (match_test "TARGET_16_BIT")
1112                      (const_string "yes")
1113                      (const_string "no"))
1114        ;; Alternative 2
1115        (const_string "yes")
1116      ])
1117    (set_attr_alternative "length"
1118      [
1119        ;; Alternative 0
1120        (if_then_else (match_test "!CROSSING_JUMP_P (insn)")
1121                      (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -250))
1122                                         (le (minus (match_dup 2) (pc)) (const_int  250)))
1123                                    (if_then_else (match_test "TARGET_16_BIT")
1124                                                  (const_int 2)
1125                                                  (const_int 4))
1126                                    (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -65500))
1127                                                       (le (minus (match_dup 2) (pc)) (const_int  65500)))
1128                                                  (const_int 4)
1129                                                  (if_then_else (match_test "TARGET_16_BIT")
1130                                                                (const_int 8)
1131                                                                (const_int 10))))
1132                      (const_int 10))
1133        ;; Alternative 1
1134        (if_then_else (match_test "!CROSSING_JUMP_P (insn)")
1135                      (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -250))
1136                                         (le (minus (match_dup 2) (pc)) (const_int  250)))
1137                                    (if_then_else (match_test "TARGET_16_BIT")
1138                                                  (const_int 2)
1139                                                  (const_int 4))
1140                                    (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -65500))
1141                                                       (le (minus (match_dup 2) (pc)) (const_int  65500)))
1142                                                  (const_int 4)
1143                                                  (if_then_else (match_test "TARGET_16_BIT")
1144                                                                (const_int 8)
1145                                                                (const_int 10))))
1146                      (const_int 10))
1147        ;; Alternative 2
1148        (if_then_else (match_test "!CROSSING_JUMP_P (insn)")
1149                      (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -65500))
1150                                         (le (minus (match_dup 2) (pc)) (const_int  65500)))
1151                                    (const_int 4)
1152                                    (const_int 10))
1153                      (const_int 10))
1154      ])])
1157 ;; This pattern is dedicated to V2 ISA,
1158 ;; because V2 DOES NOT HAVE beqc/bnec instruction.
1159 (define_insn "cbranchsi4_equality_reg"
1160   [(set (pc)
1161         (if_then_else (match_operator 0 "nds32_equality_comparison_operator"
1162                         [(match_operand:SI 1 "register_operand" "v, r")
1163                          (match_operand:SI 2 "register_operand" "l, r")])
1164                       (label_ref (match_operand 3 "" ""))
1165                       (pc)))]
1166   "TARGET_ISA_V2"
1168   return nds32_output_cbranchsi4_equality_reg (insn, operands);
1170   [(set_attr "type"   "branch")
1171    (set_attr_alternative "enabled"
1172      [
1173        ;; Alternative 0
1174        (if_then_else (match_test "TARGET_16_BIT")
1175                      (const_string "yes")
1176                      (const_string "no"))
1177        ;; Alternative 1
1178        (const_string "yes")
1179      ])
1180    (set_attr_alternative "length"
1181      [
1182        ;; Alternative 0
1183        (if_then_else (match_test "!CROSSING_JUMP_P (insn)")
1184                      (if_then_else (and (ge (minus (match_dup 3) (pc)) (const_int -250))
1185                                         (le (minus (match_dup 3) (pc)) (const_int  250)))
1186                                    (const_int 2)
1187                                    (if_then_else (and (ge (minus (match_dup 3) (pc))
1188                                                           (const_int -16350))
1189                                                       (le (minus (match_dup 3) (pc))
1190                                                           (const_int  16350)))
1191                                                  (const_int 4)
1192                                                  (const_int 8)))
1193                      (const_int 8))
1194        ;; Alternative 1
1195        (if_then_else (match_test "!CROSSING_JUMP_P (insn)")
1196                      (if_then_else (and (ge (minus (match_dup 3) (pc)) (const_int -16350))
1197                                         (le (minus (match_dup 3) (pc)) (const_int  16350)))
1198                                    (const_int 4)
1199                                    (const_int 10))
1200                      (const_int 10))
1201      ])])
1204 ;; This pattern is dedicated to V3/V3M,
1205 ;; because V3/V3M DO HAVE beqc/bnec instruction.
1206 (define_insn "cbranchsi4_equality_reg_or_const_int"
1207   [(set (pc)
1208         (if_then_else (match_operator 0 "nds32_equality_comparison_operator"
1209                         [(match_operand:SI 1 "register_operand"      "v, r,    r")
1210                          (match_operand:SI 2 "nds32_rimm11s_operand" "l, r, Is11")])
1211                       (label_ref (match_operand 3 "" ""))
1212                       (pc)))]
1213   "TARGET_ISA_V3 || TARGET_ISA_V3M"
1215   return nds32_output_cbranchsi4_equality_reg_or_const_int (insn, operands);
1217   [(set_attr "type"   "branch")
1218    (set_attr_alternative "enabled"
1219      [
1220        ;; Alternative 0
1221        (if_then_else (match_test "TARGET_16_BIT")
1222                      (const_string "yes")
1223                      (const_string "no"))
1224        ;; Alternative 1
1225        (const_string "yes")
1226        ;; Alternative 2
1227        (const_string "yes")
1228      ])
1229    (set_attr_alternative "length"
1230      [
1231        ;; Alternative 0
1232        (if_then_else (match_test "!CROSSING_JUMP_P (insn)")
1233                      (if_then_else (and (ge (minus (match_dup 3) (pc)) (const_int -250))
1234                                         (le (minus (match_dup 3) (pc)) (const_int  250)))
1235                                    (const_int 2)
1236                                    (if_then_else (and (ge (minus (match_dup 3) (pc))
1237                                                           (const_int -16350))
1238                                                       (le (minus (match_dup 3) (pc))
1239                                                           (const_int  16350)))
1240                                                  (const_int 4)
1241                                                  (const_int 8)))
1242                     (const_int 8))
1243        ;; Alternative 1
1244        (if_then_else (match_test "!CROSSING_JUMP_P (insn)")
1245                      (if_then_else (and (ge (minus (match_dup 3) (pc)) (const_int -16350))
1246                                         (le (minus (match_dup 3) (pc)) (const_int  16350)))
1247                                    (const_int 4)
1248                                    (const_int 10))
1249                     (const_int 10))
1250        ;; Alternative 2
1251        (if_then_else (match_test "!CROSSING_JUMP_P (insn)")
1252                      (if_then_else (and (ge (minus (match_dup 3) (pc)) (const_int -250))
1253                                         (le (minus (match_dup 3) (pc)) (const_int  250)))
1254                                    (const_int 4)
1255                                    (const_int 10))
1256                     (const_int 10))
1257      ])])
1260 (define_insn "*cbranchsi4_greater_less_zero"
1261   [(set (pc)
1262         (if_then_else (match_operator 0 "nds32_greater_less_comparison_operator"
1263                         [(match_operand:SI 1 "register_operand" "r")
1264                          (const_int 0)])
1265                       (label_ref (match_operand 2 "" ""))
1266                       (pc)))]
1267   ""
1269   return nds32_output_cbranchsi4_greater_less_zero (insn, operands);
1271   [(set_attr "type"   "branch")
1272    (set (attr "length")
1273         (if_then_else (match_test "!CROSSING_JUMP_P (insn)")
1274                       (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -65500))
1275                                          (le (minus (match_dup 2) (pc)) (const_int  65500)))
1276                                     (const_int 4)
1277                                     (const_int 10))
1278                       (const_int 10)))])
1281 (define_expand "cstoresi4"
1282   [(set (match_operand:SI 0 "register_operand" "")
1283         (match_operator:SI 1 "comparison_operator"
1284           [(match_operand:SI 2 "register_operand" "")
1285            (match_operand:SI 3 "nonmemory_operand" "")]))]
1286   ""
1288   enum nds32_expand_result_type result = nds32_expand_cstore (operands);
1289   switch (result)
1290     {
1291     case EXPAND_DONE:
1292       DONE;
1293       break;
1294     case EXPAND_FAIL:
1295       FAIL;
1296       break;
1297     case EXPAND_CREATE_TEMPLATE:
1298       break;
1299     default:
1300       gcc_unreachable ();
1301     }
1305 (define_expand "slts_compare"
1306   [(set (match_operand:SI 0 "register_operand"       "")
1307         (lt:SI (match_operand:SI 1 "general_operand" "")
1308                (match_operand:SI 2 "general_operand" "")))]
1309   ""
1311   if (!REG_P (operands[1]))
1312     operands[1] = force_reg (SImode, operands[1]);
1314   if (!REG_P (operands[2]) && !satisfies_constraint_Is15 (operands[2]))
1315     operands[2] = force_reg (SImode, operands[2]);
1318 (define_insn "slts_compare_impl"
1319   [(set (match_operand:SI 0 "register_operand"             "=t,   t, r,    r")
1320         (lt:SI (match_operand:SI 1 "register_operand"      " d,   d, r,    r")
1321                (match_operand:SI 2 "nds32_rimm15s_operand" " r,Iu05, r, Is15")))]
1322   ""
1323   "@
1324    slts45\t%1, %2
1325    sltsi45\t%1, %2
1326    slts\t%0, %1, %2
1327    sltsi\t%0, %1, %2"
1328   [(set_attr "type"   "alu,    alu,    alu,    alu")
1329    (set_attr "length" "  2,      2,      4,      4")])
1331 (define_insn "slt_eq0"
1332   [(set (match_operand:SI 0 "register_operand"        "=t, r")
1333         (eq:SI (match_operand:SI 1 "register_operand" " d, r")
1334                (const_int 0)))]
1335   ""
1336   "@
1337    slti45\t%1, 1
1338    slti\t%0, %1, 1"
1339   [(set_attr "type"   "alu, alu")
1340    (set_attr "length" "  2,   4")])
1342 (define_expand "slt_compare"
1343   [(set (match_operand:SI 0 "register_operand"        "")
1344         (ltu:SI (match_operand:SI 1 "general_operand" "")
1345                 (match_operand:SI 2 "general_operand" "")))]
1346   ""
1348   if (!REG_P (operands[1]))
1349     operands[1] = force_reg (SImode, operands[1]);
1351   if (!REG_P (operands[2]) && !satisfies_constraint_Is15 (operands[2]))
1352     operands[2] = force_reg (SImode, operands[2]);
1355 (define_insn "slt_compare_impl"
1356   [(set (match_operand:SI 0 "register_operand"              "=t,    t, r,    r")
1357         (ltu:SI (match_operand:SI 1 "register_operand"      " d,    d, r,    r")
1358                 (match_operand:SI 2 "nds32_rimm15s_operand" " r, Iu05, r, Is15")))]
1359   ""
1360   "@
1361    slt45\t%1, %2
1362    slti45\t%1, %2
1363    slt\t%0, %1, %2
1364    slti\t%0, %1, %2"
1365   [(set_attr "type"   "alu,    alu,    alu,    alu")
1366    (set_attr "length" "  2,      2,      4,      4")])
1369 ;; ----------------------------------------------------------------------------
1371 ;; Unconditional and other jump instructions.
1373 (define_insn "jump"
1374   [(set (pc) (label_ref (match_operand 0 "" "")))]
1375   ""
1377   /* This unconditional jump has two forms:
1378        32-bit instruction => j   imm24s << 1
1379        16-bit instruction => j8  imm8s << 1
1381      For 32-bit case,
1382      we assume it is always reachable.
1383      For 16-bit case,
1384      it must satisfy { 255 >= (label - pc) >= -256 } condition.
1385      However, since the $pc for nds32 is at the beginning of the instruction,
1386      we should leave some length space for current insn.
1387      So we use range -250 ~ 250.  */
1388   switch (get_attr_length (insn))
1389     {
1390     case 2:
1391       return "j8\t%0";
1392     case 4:
1393       return "j\t%0";
1394     default:
1395       gcc_unreachable ();
1396     }
1398   [(set_attr "type" "branch")
1399    (set_attr "enabled" "yes")
1400    (set (attr "length")
1401         (if_then_else (match_test "!CROSSING_JUMP_P (insn)")
1402                       (if_then_else (and (ge (minus (match_dup 0) (pc)) (const_int -250))
1403                                          (le (minus (match_dup 0) (pc)) (const_int  250)))
1404                                     (if_then_else (match_test "TARGET_16_BIT")
1405                                                   (const_int 2)
1406                                                   (const_int 4))
1407                                     (const_int 4))
1408                       (const_int 4)))])
1410 (define_insn "indirect_jump"
1411   [(set (pc) (match_operand:SI 0 "register_operand" "r, r"))]
1412   ""
1413   "@
1414    jr5\t%0
1415    jr\t%0"
1416   [(set_attr "type"   "branch,branch")
1417    (set_attr "length" "     2,     4")])
1419 ;; Subroutine call instruction returning no value.
1420 ;;   operands[0]: It should be a mem RTX whose address is
1421 ;;                the address of the function.
1422 ;;   operands[1]: It is the number of bytes of arguments pushed as a const_int.
1423 ;;   operands[2]: It is the number of registers used as operands.
1425 (define_expand "call"
1426   [(parallel [(call (match_operand 0 "memory_operand" "")
1427                     (match_operand 1))
1428               (clobber (reg:SI LP_REGNUM))
1429               (clobber (reg:SI TA_REGNUM))])]
1430   ""
1431   ""
1434 (define_insn "call_internal"
1435   [(parallel [(call (mem (match_operand:SI 0 "nds32_call_address_operand" "r, i"))
1436                     (match_operand 1))
1437               (clobber (reg:SI LP_REGNUM))
1438               (clobber (reg:SI TA_REGNUM))])]
1439   ""
1441   rtx_insn *next_insn = next_active_insn (insn);
1442   bool align_p = (!(next_insn && get_attr_length (next_insn) == 2))
1443                  && NDS32_ALIGN_P ();
1444   switch (which_alternative)
1445     {
1446     case 0:
1447       if (TARGET_16_BIT)
1448         {
1449           if (align_p)
1450             return "jral5\t%0\;.align 2";
1451           else
1452             return "jral5\t%0";
1453         }
1454       else
1455         {
1456           if (align_p)
1457             return "jral\t%0\;.align 2";
1458           else
1459             return "jral\t%0";
1460         }
1461     case 1:
1462       return nds32_output_call (insn, operands, operands[0],
1463                                 "bal\t%0", "jal\t%0", align_p);
1464     default:
1465       gcc_unreachable ();
1466     }
1468   [(set_attr "enabled" "yes")
1469    (set_attr "type" "branch")
1470    (set_attr_alternative "length"
1471      [
1472        ;; Alternative 0
1473        (if_then_else (match_test "TARGET_16_BIT")
1474                      (const_int 2)
1475                      (const_int 4))
1476        ;; Alternative 1
1477        (if_then_else (match_test "nds32_long_call_p (operands[0])")
1478                      (const_int 12)
1479                      (const_int 4))
1480      ])]
1483 ;; Subroutine call instruction returning a value.
1484 ;;   operands[0]: It is the hard regiser in which the value is returned.
1485 ;;   The rest three operands are the same as the
1486 ;;   three operands of the 'call' instruction.
1487 ;;   (but with numbers increased by one)
1489 (define_expand "call_value"
1490   [(parallel [(set (match_operand 0)
1491                    (call (match_operand 1 "memory_operand" "")
1492                          (match_operand 2)))
1493               (clobber (reg:SI LP_REGNUM))
1494               (clobber (reg:SI TA_REGNUM))])]
1495   "")
1497 (define_insn "call_value_internal"
1498   [(parallel [(set (match_operand 0)
1499                    (call (mem (match_operand:SI 1 "nds32_call_address_operand" "r, i"))
1500                          (match_operand 2)))
1501               (clobber (reg:SI LP_REGNUM))
1502               (clobber (reg:SI TA_REGNUM))])]
1503   ""
1505   rtx_insn *next_insn = next_active_insn (insn);
1506   bool align_p = (!(next_insn && get_attr_length (next_insn) == 2))
1507                  && NDS32_ALIGN_P ();
1508   switch (which_alternative)
1509     {
1510     case 0:
1511       if (TARGET_16_BIT)
1512         {
1513           if (align_p)
1514             return "jral5\t%1\;.align 2";
1515           else
1516             return "jral5\t%1";
1517         }
1518       else
1519         {
1520           if (align_p)
1521             return "jral\t%1\;.align 2";
1522           else
1523             return "jral\t%1";
1524         }
1525     case 1:
1526       return nds32_output_call (insn, operands, operands[1],
1527                                 "bal\t%1", "jal\t%1", align_p);
1528     default:
1529       gcc_unreachable ();
1530     }
1532   [(set_attr "enabled" "yes")
1533    (set_attr "type" "branch")
1534    (set_attr_alternative "length"
1535      [
1536        ;; Alternative 0
1537        (if_then_else (match_test "TARGET_16_BIT")
1538                      (const_int 2)
1539                      (const_int 4))
1540        ;; Alternative 1
1541        (if_then_else (match_test "nds32_long_call_p (operands[1])")
1542                      (const_int 12)
1543                      (const_int 4))
1544      ])]
1547 ;; Call subroutine returning any type.
1549 (define_expand "untyped_call"
1550   [(parallel [(call (match_operand 0 "" "")
1551                     (const_int 0))
1552               (match_operand 1 "" "")
1553               (match_operand 2 "" "")])]
1554   ""
1556   int i;
1558   emit_call_insn (gen_call (operands[0], const0_rtx));
1560   for (i = 0; i < XVECLEN (operands[2], 0); i++)
1561     {
1562       rtx set = XVECEXP (operands[2], 0, i);
1563       emit_move_insn (SET_DEST (set), SET_SRC (set));
1564     }
1566   /* The optimizer does not know that the call sets the function value
1567      registers we stored in the result block.  We avoid problems by
1568      claiming that all hard registers are used and clobbered at this
1569      point.  */
1570   emit_insn (gen_blockage ());
1571   DONE;
1574 ;; ----------------------------------------------------------------------------
1576 ;; The sibcall patterns.
1578 ;; sibcall
1579 ;; sibcall_internal
1581 (define_expand "sibcall"
1582   [(parallel [(call (match_operand 0 "memory_operand" "")
1583                     (const_int 0))
1584               (clobber (reg:SI TA_REGNUM))
1585               (return)])]
1586   "")
1588 (define_insn "sibcall_internal"
1589   [(parallel [(call (mem (match_operand:SI 0 "nds32_call_address_operand" "r, i"))
1590                     (match_operand 1))
1591               (clobber (reg:SI TA_REGNUM))
1592               (return)])]
1593   ""
1595   switch (which_alternative)
1596     {
1597     case 0:
1598       if (TARGET_16_BIT)
1599         return "jr5\t%0";
1600       else
1601         return "jr\t%0";
1602     case 1:
1603       if (nds32_long_call_p (operands[0]))
1604         return "b\t%0";
1605       else
1606         return "j\t%0";
1607     default:
1608       gcc_unreachable ();
1609     }
1611   [(set_attr "enabled" "yes")
1612    (set_attr "type" "branch")
1613    (set_attr_alternative "length"
1614      [
1615        ;; Alternative 0
1616        (if_then_else (match_test "TARGET_16_BIT")
1617                      (const_int 2)
1618                      (const_int 4))
1619        ;; Alternative 1
1620        (if_then_else (match_test "nds32_long_call_p (operands[0])")
1621                      (const_int 12)
1622                      (const_int 4))
1623      ])]
1626 ;; sibcall_value
1627 ;; sibcall_value_internal
1628 ;; sibcall_value_immediate
1630 (define_expand "sibcall_value"
1631   [(parallel [(set (match_operand 0)
1632                    (call (match_operand 1 "memory_operand" "")
1633                          (const_int 0)))
1634               (clobber (reg:SI TA_REGNUM))
1635               (return)])]
1636   "")
1638 (define_insn "sibcall_value_internal"
1639   [(parallel [(set (match_operand 0)
1640                    (call (mem (match_operand:SI 1 "nds32_call_address_operand" "r, i"))
1641                          (match_operand 2)))
1642               (clobber (reg:SI TA_REGNUM))
1643               (return)])]
1644   ""
1646   switch (which_alternative)
1647     {
1648     case 0:
1649       if (TARGET_16_BIT)
1650         return "jr5\t%1";
1651       else
1652         return "jr\t%1";
1653     case 1:
1654       if (nds32_long_call_p (operands[1]))
1655         return "b\t%1";
1656       else
1657         return "j\t%1";
1658     default:
1659       gcc_unreachable ();
1660     }
1662   [(set_attr "enabled" "yes")
1663    (set_attr "type" "branch")
1664    (set_attr_alternative "length"
1665      [
1666        ;; Alternative 0
1667        (if_then_else (match_test "TARGET_16_BIT")
1668                      (const_int 2)
1669                      (const_int 4))
1670        ;; Alternative 1
1671        (if_then_else (match_test "nds32_long_call_p (operands[1])")
1672                      (const_int 12)
1673                      (const_int 4))
1674      ])]
1677 ;; ----------------------------------------------------------------------------
1679 ;; prologue and epilogue.
1681 (define_expand "prologue" [(const_int 0)]
1682   ""
1684   /* Note that only under V3/V3M ISA, we could use v3push prologue.
1685      In addition, we need to check if v3push is indeed available.  */
1686   if (NDS32_V3PUSH_AVAILABLE_P)
1687     nds32_expand_prologue_v3push ();
1688   else
1689     nds32_expand_prologue ();
1690   DONE;
1693 (define_expand "epilogue" [(const_int 0)]
1694   ""
1696   /* Note that only under V3/V3M ISA, we could use v3pop epilogue.
1697      In addition, we need to check if v3push is indeed available.  */
1698   if (NDS32_V3PUSH_AVAILABLE_P)
1699     nds32_expand_epilogue_v3pop (false);
1700   else
1701     nds32_expand_epilogue (false);
1702   DONE;
1705 (define_expand "sibcall_epilogue" [(const_int 0)]
1706   ""
1708   /* Pass true to indicate that this is sibcall epilogue and
1709      exit from a function without the final branch back to the
1710      calling function.  */
1711   nds32_expand_epilogue (true);
1713   DONE;
1717 ;; nop instruction.
1719 (define_insn "nop"
1720   [(const_int 0)]
1721   ""
1723   if (TARGET_16_BIT)
1724     return "nop16";
1725   else
1726     return "nop";
1728   [(set_attr "type" "misc")
1729    (set_attr "enabled" "yes")
1730    (set (attr "length")
1731         (if_then_else (match_test "TARGET_16_BIT")
1732                       (const_int 2)
1733                       (const_int 4)))])
1736 ;; ----------------------------------------------------------------------------
1737 ;; Stack push/pop operations
1738 ;; ----------------------------------------------------------------------------
1740 ;; The pattern for stack push.
1741 ;; Both stack_push_multiple and stack_v3push use the following pattern.
1742 ;; So we need to use TARGET_V3PUSH to determine the instruction length.
1743 (define_insn "*stack_push"
1744   [(match_parallel 0 "nds32_stack_push_operation"
1745      [(set (mem:SI (plus:SI (reg:SI SP_REGNUM)
1746                             (match_operand:SI 1 "const_int_operand" "")))
1747            (match_operand:SI 2 "register_operand" ""))
1748      ])]
1749   ""
1751   return nds32_output_stack_push (operands[0]);
1753   [(set_attr "type" "store_multiple")
1754    (set_attr "combo" "12")
1755    (set_attr "enabled" "yes")
1756    (set (attr "length")
1757         (if_then_else (match_test "NDS32_V3PUSH_AVAILABLE_P")
1758                       (const_int 2)
1759                       (const_int 4)))])
1762 ;; The pattern for stack pop.
1763 ;; Both stack_pop_multiple and stack_v3pop use the following pattern.
1764 ;; So we need to use TARGET_V3PUSH to determine the instruction length.
1765 (define_insn "*stack_pop"
1766   [(match_parallel 0 "nds32_stack_pop_operation"
1767      [(set (match_operand:SI 1 "register_operand" "")
1768            (mem:SI (reg:SI SP_REGNUM)))
1769      ])]
1770   ""
1772   return nds32_output_stack_pop (operands[0]);
1774   [(set_attr "type" "load_multiple")
1775    (set_attr "combo" "12")
1776    (set_attr "enabled" "yes")
1777    (set (attr "length")
1778         (if_then_else (match_test "NDS32_V3PUSH_AVAILABLE_P")
1779                       (const_int 2)
1780                       (const_int 4)))])
1783 ;; ----------------------------------------------------------------------------
1784 ;; Return operation patterns
1785 ;; ----------------------------------------------------------------------------
1787 ;; Use this pattern to expand a return instruction
1788 ;; with simple_return rtx if no epilogue is required.
1789 (define_expand "return"
1790   [(parallel [(return)
1791               (clobber (reg:SI FP_REGNUM))])]
1792   "nds32_can_use_return_insn ()"
1794   /* Emit as the simple return.  */
1795   if (cfun->machine->naked_p
1796       && (cfun->machine->va_args_size == 0))
1797     {
1798       emit_jump_insn (gen_return_internal ());
1799       DONE;
1800     }
1803 ;; This pattern is expanded only by the shrink-wrapping optimization
1804 ;; on paths where the function prologue has not been executed.
1805 (define_expand "simple_return"
1806   [(simple_return)]
1807   ""
1808   ""
1811 (define_insn "*nds32_return"
1812   [(parallel [(return)
1813    (clobber (reg:SI FP_REGNUM))])]
1814   ""
1816   return nds32_output_return ();
1818   [(set_attr "type" "branch")
1819    (set_attr "enabled" "yes")
1820    (set_attr "length" "4")])
1822 (define_insn "return_internal"
1823   [(simple_return)]
1824   ""
1826   if (TARGET_16_BIT)
1827     return "ret5";
1828   else
1829     return "ret";
1831   [(set_attr "type" "branch")
1832    (set_attr "enabled" "yes")
1833    (set (attr "length")
1834         (if_then_else (match_test "TARGET_16_BIT")
1835                       (const_int 2)
1836                       (const_int 4)))])
1839 ;; ----------------------------------------------------------------------------
1840 ;; Jump Table patterns
1841 ;; ----------------------------------------------------------------------------
1842 ;; Need to implement ASM_OUTPUT_ADDR_VEC_ELT (for normal jump table)
1843 ;; or ASM_OUTPUT_ADDR_DIFF_ELT (for pc relative jump table) as well.
1845 ;; operands[0]: The index to dispatch on.
1846 ;; operands[1]: The lower bound for indices in the table.
1847 ;; operands[2]: The total range of indices int the table.
1848 ;;              i.e. The largest index minus the smallest one.
1849 ;; operands[3]: A label that precedes the table itself.
1850 ;; operands[4]: A label to jump to if the index has a value outside the bounds.
1852 ;; We need to create following sequences for jump table code generation:
1853 ;;   A) k <-- (plus (operands[0]) (-operands[1]))
1854 ;;   B) if (gtu k operands[2]) then goto operands[4]
1855 ;;   C) t <-- operands[3]
1856 ;;   D) z <-- (mem (plus (k << 0 or 1 or 2) t))
1857 ;;   E) z <-- t + z (NOTE: This is only required for pc relative jump table.)
1858 ;;   F) jump to target with register t or z
1860 ;; The steps C, D, E, and F are performed by casesi_internal pattern.
1861 (define_expand "casesi"
1862   [(match_operand:SI 0 "register_operand"  "r") ; index to jump on
1863    (match_operand:SI 1 "immediate_operand" "i") ; lower bound
1864    (match_operand:SI 2 "immediate_operand" "i") ; total range
1865    (match_operand:SI 3 "" "")                   ; table label
1866    (match_operand:SI 4 "" "")]                  ; Out of range label
1867   ""
1869   rtx add_tmp;
1870   rtx reg, test;
1872   /* Step A: "k <-- (plus (operands[0]) (-operands[1]))".  */
1873   if (operands[1] != const0_rtx)
1874     {
1875       reg = gen_reg_rtx (SImode);
1876       add_tmp = gen_int_mode (-INTVAL (operands[1]), SImode);
1878       /* If the integer value is not in the range of imm15s,
1879          we need to force register first because our addsi3 pattern
1880          only accept nds32_rimm15s_operand predicate.  */
1881       add_tmp = force_reg (SImode, add_tmp);
1883       emit_insn (gen_addsi3 (reg, operands[0], add_tmp));
1884       operands[0] = reg;
1885     }
1887   /* Step B: "if (gtu k operands[2]) then goto operands[4]".  */
1888   test = gen_rtx_GTU (VOIDmode, operands[0], operands[2]);
1889   emit_jump_insn (gen_cbranchsi4 (test, operands[0], operands[2],
1890                                   operands[4]));
1892   /* Step C, D, E, and F, using another temporary register.  */
1893   rtx tmp = gen_reg_rtx (SImode);
1894   emit_jump_insn (gen_casesi_internal (operands[0], operands[3], tmp));
1895   DONE;
1898 ;; We are receiving operands from casesi pattern:
1900 ;; operands[0]: The index that have been substracted with lower bound.
1901 ;; operands[1]: A label that precedes the table itself.
1902 ;; operands[2]: A temporary register to retrieve value in table.
1904 ;; We need to perform steps C, D, E, and F:
1906 ;;   C) t <-- operands[1]
1907 ;;   D) z <-- (mem (plus (operands[0] << m) t))
1908 ;;            m is 2 for normal jump table.
1909 ;;            m is 0, 1, or 2 for pc relative jump table based on diff size.
1910 ;;   E) t <-- z + t (NOTE: This is only required for pc relative jump table.)
1911 ;;   F) Jump to target with register t or z.
1913 ;; The USE in this pattern is needed to tell flow analysis that this is
1914 ;; a CASESI insn.  It has no other purpose.
1915 (define_insn "casesi_internal"
1916   [(parallel [(set (pc)
1917                    (mem:SI (plus:SI (mult:SI (match_operand:SI 0 "register_operand" "r")
1918                                              (const_int 4))
1919                                     (label_ref (match_operand 1 "" "")))))
1920               (use (label_ref (match_dup 1)))
1921               (clobber (match_operand:SI 2 "register_operand" "=r"))
1922               (clobber (reg:SI TA_REGNUM))])]
1923   ""
1925   if (CASE_VECTOR_PC_RELATIVE)
1926     return nds32_output_casesi_pc_relative (operands);
1927   else
1928     return nds32_output_casesi (operands);
1930   [(set_attr "length" "20")
1931    (set_attr "type" "branch")])
1933 ;; ----------------------------------------------------------------------------
1935 ;; Performance Extension
1937 (define_insn "clzsi2"
1938   [(set (match_operand:SI 0 "register_operand"         "=r")
1939         (clz:SI (match_operand:SI 1 "register_operand" " r")))]
1940   "TARGET_EXT_PERF"
1941   "clz\t%0, %1"
1942   [(set_attr "type" "alu")
1943    (set_attr "length" "4")])
1945 (define_insn "smaxsi3"
1946   [(set (match_operand:SI 0 "register_operand"          "=r")
1947         (smax:SI (match_operand:SI 1 "register_operand" " r")
1948                  (match_operand:SI 2 "register_operand" " r")))]
1949   "TARGET_EXT_PERF"
1950   "max\t%0, %1, %2"
1951   [(set_attr "type" "alu")
1952    (set_attr "length" "4")])
1954 (define_insn "sminsi3"
1955   [(set (match_operand:SI 0 "register_operand"          "=r")
1956         (smin:SI (match_operand:SI 1 "register_operand" " r")
1957                  (match_operand:SI 2 "register_operand" " r")))]
1958   "TARGET_EXT_PERF"
1959   "min\t%0, %1, %2"
1960   [(set_attr "type" "alu")
1961    (set_attr "length" "4")])
1963 (define_insn "btst"
1964   [(set (match_operand:SI 0 "register_operand"                     "=   r")
1965         (zero_extract:SI (match_operand:SI 1 "register_operand"    "    r")
1966                          (const_int 1)
1967                          (match_operand:SI 2 "nds32_imm5u_operand" " Iu05")))]
1968   "TARGET_EXT_PERF"
1969   "btst\t%0, %1, %2"
1970   [(set_attr "type" "alu")
1971    (set_attr "length" "4")])
1973 (define_insn "ave"
1974   [(set (match_operand:SI 0 "register_operand" "=r")
1975         (truncate:SI
1976           (ashiftrt:DI
1977             (plus:DI
1978               (plus:DI
1979                 (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
1980                 (sign_extend:DI (match_operand:SI 2 "register_operand" "r")))
1981               (const_int 1))
1982           (const_int 1))))]
1983   "TARGET_EXT_PERF"
1984   "ave\t%0, %1, %2"
1985   [(set_attr "type" "alu")
1986    (set_attr "length" "4")])
1988 ;; ----------------------------------------------------------------------------
1990 ;; Pseudo NOPs
1992 (define_insn "relax_group"
1993   [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "i")] UNSPEC_VOLATILE_RELAX_GROUP)]
1994   ""
1995   ".relax_hint %0"
1996   [(set_attr "length" "0")]
1999 (define_insn "pop25return"
2000   [(return)
2001    (unspec_volatile:SI [(reg:SI LP_REGNUM)] UNSPEC_VOLATILE_POP25_RETURN)]
2002   ""
2003   "! return for pop 25"
2004   [(set_attr "length" "0")]
2007 ;; ----------------------------------------------------------------------------
2009 ;; Patterns for exception handling
2011 (define_expand "eh_return"
2012   [(use (match_operand 0 "general_operand"))]
2013   ""
2015   emit_insn (gen_nds32_eh_return (operands[0]));
2016   DONE;
2019 (define_insn_and_split "nds32_eh_return"
2020   [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")] UNSPEC_VOLATILE_EH_RETURN)]
2021   ""
2022   "#"
2023   "reload_completed"
2024   [(const_int 0)]
2026   rtx place;
2027   rtx addr;
2029   /* The operands[0] is the handler address.  We need to assign it
2030      to return address rtx so that we can jump to exception handler
2031      when returning from current function.  */
2033   if (cfun->machine->lp_size == 0)
2034     {
2035       /* If $lp is not saved in the stack frame, we can take $lp directly.  */
2036       place = gen_rtx_REG (SImode, LP_REGNUM);
2037     }
2038   else
2039     {
2040       /* Otherwise, we need to locate the stack slot of return address.
2041          The return address is generally saved in [$fp-4] location.
2042          However, DSE (dead store elimination) does not detect an alias
2043          between [$fp-x] and [$sp+y].  This can result in a store to save
2044          $lp introduced by builtin_eh_return() being incorrectly deleted
2045          if it is based on $fp.  The solution we take here is to compute
2046          the offset relative to stack pointer and then use $sp to access
2047          location so that the alias can be detected.
2048          FIXME: What if the immediate value "offset" is too large to be
2049                 fit in a single addi instruction?  */
2050       HOST_WIDE_INT offset;
2052       offset = (cfun->machine->fp_size
2053                 + cfun->machine->gp_size
2054                 + cfun->machine->lp_size
2055                 + cfun->machine->callee_saved_gpr_regs_size
2056                 + cfun->machine->callee_saved_area_gpr_padding_bytes
2057                 + cfun->machine->callee_saved_fpr_regs_size
2058                 + cfun->machine->eh_return_data_regs_size
2059                 + cfun->machine->local_size
2060                 + cfun->machine->out_args_size);
2062       addr = plus_constant (Pmode, stack_pointer_rtx, offset - 4);
2063       place = gen_frame_mem (SImode, addr);
2064     }
2066   emit_move_insn (place, operands[0]);
2067   DONE;
2070 ;; ----------------------------------------------------------------------------