1;; Intrinsic patterns description of Andes NDS32 cpu for GNU compiler
2;; Copyright (C) 2012-2019 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;; ------------------------------------------------------------------------
22
23;; Register Transfer.
24
25(define_insn "unspec_volatile_mfsr"
26  [(set (match_operand:SI 0 "register_operand" "=r")
27	(unspec_volatile:SI [(match_operand:SI 1 "immediate_operand" "i")] UNSPEC_VOLATILE_MFSR))]
28  ""
29  "mfsr\t%0, %V1"
30  [(set_attr "type"   "misc")
31   (set_attr "length"    "4")]
32)
33
34(define_insn "unspec_volatile_mfusr"
35  [(set (match_operand:SI 0 "register_operand" "=r")
36	(unspec_volatile:SI [(match_operand:SI 1 "immediate_operand" "i")] UNSPEC_VOLATILE_MFUSR))]
37  ""
38  "mfusr\t%0, %V1"
39  [(set_attr "type"   "misc")
40   (set_attr "length"    "4")]
41)
42
43(define_expand "mtsr_isb"
44  [(set (match_operand:SI 0 "register_operand" "")
45	(match_operand:SI 1 "immediate_operand" ""))]
46  ""
47{
48  emit_insn (gen_unspec_volatile_mtsr (operands[0], operands[1]));
49  emit_insn (gen_unspec_volatile_isb());
50  DONE;
51})
52
53(define_expand "mtsr_dsb"
54  [(set (match_operand:SI 0 "register_operand" "")
55	(match_operand:SI 1 "immediate_operand" ""))]
56  ""
57{
58  emit_insn (gen_unspec_volatile_mtsr (operands[0], operands[1]));
59  emit_insn (gen_unspec_dsb());
60  DONE;
61})
62
63(define_insn "unspec_volatile_mtsr"
64  [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")
65			(match_operand:SI 1 "immediate_operand" "i")] UNSPEC_VOLATILE_MTSR)]
66  ""
67  "mtsr\t%0, %V1"
68  [(set_attr "type"   "misc")
69   (set_attr "length"    "4")]
70)
71
72(define_insn "unspec_volatile_mtusr"
73  [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")
74			(match_operand:SI 1 "immediate_operand" "i")] UNSPEC_VOLATILE_MTUSR)]
75  ""
76  "mtusr\t%0, %V1"
77  [(set_attr "type"   "misc")
78   (set_attr "length"    "4")]
79)
80
81;; FPU Register Transfer.
82
83(define_insn "unspec_fcpynsd"
84   [(set (match_operand:DF 0 "register_operand" "=f")
85	 (unspec:DF [(match_operand:DF 1 "register_operand" "f")
86		     (match_operand:DF 2 "register_operand" "f")] UNSPEC_FCPYNSD))]
87  ""
88  "fcpynsd\t%0, %1, %2"
89  [(set_attr "type"   "misc")
90   (set_attr "length"    "4")]
91)
92
93(define_insn "unspec_fcpynss"
94   [(set (match_operand:SF 0 "register_operand" "=f")
95	 (unspec:SF [(match_operand:SF 1 "register_operand" "f")
96		     (match_operand:SF 2 "register_operand" "f")] UNSPEC_FCPYNSS))]
97  ""
98  "fcpynss\t%0, %1, %2"
99  [(set_attr "type"   "misc")
100   (set_attr "length"    "4")]
101)
102
103(define_insn "unspec_fcpysd"
104   [(set (match_operand:DF 0 "register_operand" "=f")
105	 (unspec:DF [(match_operand:DF 1 "register_operand" "f")
106		     (match_operand:DF 2 "register_operand" "f")] UNSPEC_FCPYSD))]
107  ""
108  "fcpysd\t%0, %1, %2"
109  [(set_attr "type"   "misc")
110   (set_attr "length"    "4")]
111)
112
113(define_insn "unspec_fcpyss"
114   [(set (match_operand:SF 0 "register_operand" "=f")
115	 (unspec:SF [(match_operand:SF 1 "register_operand" "f")
116		     (match_operand:SF 2 "register_operand" "f")] UNSPEC_FCPYSS))]
117  ""
118  "fcpyss\t%0, %1, %2"
119  [(set_attr "type"   "misc")
120   (set_attr "length"    "4")]
121)
122
123(define_insn "unspec_fmfcsr"
124   [(set (match_operand:SI 0 "register_operand" "=r")
125	 (unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_FMFCSR))]
126  ""
127  "fmfcsr\t%0"
128  [(set_attr "type"   "misc")
129   (set_attr "length"    "4")]
130)
131
132(define_insn "unspec_fmtcsr"
133  [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")] UNSPEC_VOLATILE_FMTCSR)]
134  ""
135  "fmtcsr\t%0"
136  [(set_attr "type"   "misc")
137   (set_attr "length"    "4")]
138)
139
140(define_insn "unspec_fmfcfg"
141  [(set (match_operand:SI 0 "register_operand" "=r")
142	(unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_FMFCFG))]
143  ""
144  "fmfcfg\t%0"
145  [(set_attr "type"   "misc")
146   (set_attr "length"    "4")]
147)
148
149;; ------------------------------------------------------------------------
150
151;; Interrupt Instructions.
152
153(define_insn "unspec_volatile_setgie_en"
154  [(unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_SETGIE_EN)]
155  ""
156  "setgie.e"
157  [(set_attr "type" "misc")]
158)
159
160(define_insn "unspec_volatile_setgie_dis"
161  [(unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_SETGIE_DIS)]
162  ""
163  "setgie.d"
164  [(set_attr "type" "misc")]
165)
166
167(define_expand "unspec_enable_int"
168  [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "")] UNSPEC_VOLATILE_ENABLE_INT)]
169  ""
170{
171  rtx system_reg;
172  rtx temp_reg = gen_reg_rtx (SImode);
173
174  /* Set system register form nds32_intrinsic_register_names[].  */
175  if ((INTVAL (operands[0]) >= NDS32_INT_H16)
176      && (INTVAL (operands[0]) <= NDS32_INT_H31))
177    {
178      system_reg =  GEN_INT (__NDS32_REG_INT_MASK2__);
179      operands[0] = GEN_INT (1 << (INTVAL (operands[0])));
180    }
181  else if ((INTVAL (operands[0]) >= NDS32_INT_H32)
182	   && (INTVAL (operands[0]) <= NDS32_INT_H63))
183    {
184      system_reg =  GEN_INT (__NDS32_REG_INT_MASK3__);
185      operands[0] = GEN_INT (1 << (INTVAL (operands[0]) - 32));
186    }
187  else
188    {
189      system_reg =  GEN_INT (__NDS32_REG_INT_MASK__);
190
191      if (INTVAL (operands[0]) == NDS32_INT_SWI)
192        operands[0] = GEN_INT (1 << 16);
193      else if ((INTVAL (operands[0]) >= NDS32_INT_ALZ)
194	       && (INTVAL (operands[0]) <= NDS32_INT_DSSIM))
195	operands[0] = GEN_INT (1 << (INTVAL (operands[0]) - 4));
196      else
197	operands[0] = GEN_INT (1 << (INTVAL (operands[0])));
198    }
199
200  emit_insn (gen_unspec_volatile_mfsr (temp_reg, system_reg));
201  emit_insn (gen_iorsi3 (temp_reg, temp_reg, operands[0]));
202  emit_insn (gen_unspec_volatile_mtsr (temp_reg, system_reg));
203  emit_insn (gen_unspec_dsb ());
204  DONE;
205})
206
207(define_expand "unspec_disable_int"
208  [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "")] UNSPEC_VOLATILE_DISABLE_INT)]
209  ""
210{
211  rtx system_reg;
212  rtx temp_reg = gen_reg_rtx (SImode);
213
214  /* Set system register form nds32_intrinsic_register_names[].  */
215  if ((INTVAL (operands[0]) >= NDS32_INT_H16)
216      && (INTVAL (operands[0]) <= NDS32_INT_H31))
217    {
218      system_reg =  GEN_INT (__NDS32_REG_INT_MASK2__);
219      operands[0] = GEN_INT (~(1 << INTVAL (operands[0])));
220    }
221  else if ((INTVAL (operands[0]) >= NDS32_INT_H32)
222	   && (INTVAL (operands[0]) <= NDS32_INT_H63))
223    {
224      system_reg =  GEN_INT (__NDS32_REG_INT_MASK3__);
225      operands[0] = GEN_INT (~(1 << (INTVAL (operands[0]) - 32)));
226    }
227  else
228    {
229      system_reg =  GEN_INT (__NDS32_REG_INT_MASK__);
230
231      if (INTVAL (operands[0]) == NDS32_INT_SWI)
232        operands[0] = GEN_INT (~(1 << 16));
233      else if ((INTVAL (operands[0]) >= NDS32_INT_ALZ)
234	       && (INTVAL (operands[0]) <= NDS32_INT_DSSIM))
235	operands[0] = GEN_INT (~(1 << (INTVAL (operands[0]) - 4)));
236      else
237	operands[0] = GEN_INT (~(1 << INTVAL (operands[0])));
238    }
239
240  emit_insn (gen_unspec_volatile_mfsr (temp_reg, system_reg));
241  emit_insn (gen_andsi3 (temp_reg, temp_reg, operands[0]));
242  emit_insn (gen_unspec_volatile_mtsr (temp_reg, system_reg));
243  emit_insn (gen_unspec_dsb ());
244  DONE;
245})
246
247(define_expand "unspec_set_pending_swint"
248  [(unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_SET_PENDING_SWINT)]
249  ""
250{
251  /* Get $INT_PEND system register form nds32_intrinsic_register_names[]  */
252  rtx system_reg =  GEN_INT (__NDS32_REG_INT_PEND__);
253  rtx temp_reg = gen_reg_rtx (SImode);
254
255  emit_insn (gen_unspec_volatile_mfsr (temp_reg, system_reg));
256  emit_insn (gen_iorsi3 (temp_reg, temp_reg, GEN_INT (65536)));
257  emit_insn (gen_unspec_volatile_mtsr (temp_reg, system_reg));
258  emit_insn (gen_unspec_dsb ());
259  DONE;
260})
261
262(define_expand "unspec_clr_pending_swint"
263  [(unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_CLR_PENDING_SWINT)]
264  ""
265{
266  /* Get $INT_PEND system register form nds32_intrinsic_register_names[]  */
267  rtx system_reg =  GEN_INT (__NDS32_REG_INT_PEND__);
268  rtx temp_reg = gen_reg_rtx (SImode);
269
270  emit_insn (gen_unspec_volatile_mfsr (temp_reg, system_reg));
271  emit_insn (gen_andsi3 (temp_reg, temp_reg, GEN_INT (~(1 << 16))));
272  emit_insn (gen_unspec_volatile_mtsr (temp_reg, system_reg));
273  emit_insn (gen_unspec_dsb ());
274  DONE;
275})
276
277(define_expand "unspec_clr_pending_hwint"
278  [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "")] UNSPEC_VOLATILE_CLR_PENDING_HWINT)]
279  ""
280{
281  rtx system_reg = NULL_RTX;
282  rtx temp_reg = gen_reg_rtx (SImode);
283  rtx clr_hwint;
284  unsigned offset = 0;
285
286  /* Set system register form nds32_intrinsic_register_names[].  */
287  if ((INTVAL (operands[0]) >= NDS32_INT_H0)
288      && (INTVAL (operands[0]) <= NDS32_INT_H15))
289    {
290      system_reg = GEN_INT (__NDS32_REG_INT_PEND__);
291    }
292  else if ((INTVAL (operands[0]) >= NDS32_INT_H16)
293	   && (INTVAL (operands[0]) <= NDS32_INT_H31))
294    {
295      system_reg = GEN_INT (__NDS32_REG_INT_PEND2__);
296    }
297  else if ((INTVAL (operands[0]) >= NDS32_INT_H32)
298	   && (INTVAL (operands[0]) <= NDS32_INT_H63))
299    {
300      system_reg = GEN_INT (__NDS32_REG_INT_PEND3__);
301      offset = 32;
302    }
303  else
304    error ("__nds32__clr_pending_hwint not support NDS32_INT_SWI,"
305	   " NDS32_INT_ALZ, NDS32_INT_IDIVZE, NDS32_INT_DSSIM");
306
307  /* $INT_PEND type is write one clear.  */
308  clr_hwint = GEN_INT (1 << (INTVAL (operands[0]) - offset));
309
310  if (system_reg != NULL_RTX)
311    {
312      emit_move_insn (temp_reg, clr_hwint);
313      emit_insn (gen_unspec_volatile_mtsr (temp_reg, system_reg));
314      emit_insn (gen_unspec_dsb ());
315    }
316  DONE;
317})
318
319(define_expand "unspec_get_all_pending_int"
320  [(set (match_operand:SI 0 "register_operand" "")
321	(unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_GET_ALL_PENDING_INT))]
322  ""
323{
324  rtx system_reg = GEN_INT (__NDS32_REG_INT_PEND__);
325  emit_insn (gen_unspec_volatile_mfsr (operands[0], system_reg));
326  emit_insn (gen_unspec_dsb ());
327  DONE;
328})
329
330(define_expand "unspec_get_pending_int"
331  [(set (match_operand:SI 0 "register_operand" "")
332	(unspec_volatile:SI [(match_operand:SI 1 "immediate_operand" "")] UNSPEC_VOLATILE_GET_PENDING_INT))]
333  ""
334{
335  rtx system_reg = NULL_RTX;
336
337  /* Set system register form nds32_intrinsic_register_names[].  */
338  if ((INTVAL (operands[1]) >= NDS32_INT_H0)
339      && (INTVAL (operands[1]) <= NDS32_INT_H15))
340    {
341      system_reg = GEN_INT (__NDS32_REG_INT_PEND__);
342      operands[2] = GEN_INT (31 - INTVAL (operands[1]));
343    }
344  else if (INTVAL (operands[1]) == NDS32_INT_SWI)
345    {
346      system_reg = GEN_INT (__NDS32_REG_INT_PEND__);
347      operands[2] = GEN_INT (15);
348    }
349  else if ((INTVAL (operands[1]) >= NDS32_INT_H16)
350	   && (INTVAL (operands[1]) <= NDS32_INT_H31))
351    {
352      system_reg = GEN_INT (__NDS32_REG_INT_PEND2__);
353      operands[2] = GEN_INT (31 - INTVAL (operands[1]));
354    }
355  else if ((INTVAL (operands[1]) >= NDS32_INT_H32)
356	   && (INTVAL (operands[1]) <= NDS32_INT_H63))
357    {
358      system_reg = GEN_INT (__NDS32_REG_INT_PEND3__);
359      operands[2] = GEN_INT (31 - (INTVAL (operands[1]) - 32));
360    }
361  else
362    error ("get_pending_int not support NDS32_INT_ALZ,"
363	   " NDS32_INT_IDIVZE, NDS32_INT_DSSIM");
364
365  /* mfsr op0, sytem_reg  */
366  if (system_reg != NULL_RTX)
367    {
368      emit_insn (gen_unspec_volatile_mfsr (operands[0], system_reg));
369      emit_insn (gen_ashlsi3 (operands[0], operands[0], operands[2]));
370      emit_insn (gen_lshrsi3 (operands[0], operands[0], GEN_INT (31)));
371      emit_insn (gen_unspec_dsb ());
372    }
373  DONE;
374})
375
376(define_expand "unspec_set_int_priority"
377  [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "")
378			(match_operand:SI 1 "immediate_operand" "")] UNSPEC_VOLATILE_SET_INT_PRIORITY)]
379  ""
380{
381  rtx system_reg = NULL_RTX;
382  rtx priority = NULL_RTX;
383  rtx mask = NULL_RTX;
384  rtx temp_reg = gen_reg_rtx (SImode);
385  rtx mask_reg = gen_reg_rtx (SImode);
386  rtx set_reg = gen_reg_rtx (SImode);
387  unsigned offset = 0;
388
389  /* Get system register form nds32_intrinsic_register_names[].  */
390  if (INTVAL (operands[0]) <= NDS32_INT_H15)
391    {
392      system_reg =  GEN_INT (__NDS32_REG_INT_PRI__);
393      offset = 0;
394    }
395  else if (INTVAL (operands[0]) >= NDS32_INT_H16
396	   && INTVAL (operands[0]) <= NDS32_INT_H31)
397    {
398      system_reg =  GEN_INT (__NDS32_REG_INT_PRI2__);
399      /* The $INT_PRI2 first bit correspond to H16, so need
400	 subtract 16.  */
401      offset = 16;
402    }
403  else if (INTVAL (operands[0]) >= NDS32_INT_H32
404	   && INTVAL (operands[0]) <= NDS32_INT_H47)
405    {
406      system_reg =  GEN_INT (__NDS32_REG_INT_PRI3__);
407      /* The $INT_PRI3 first bit correspond to H32, so need
408	 subtract 32.  */
409      offset = 32;
410    }
411  else if (INTVAL (operands[0]) >= NDS32_INT_H48
412	   && INTVAL (operands[0]) <= NDS32_INT_H63)
413    {
414      system_reg =  GEN_INT (__NDS32_REG_INT_PRI4__);
415      /* The $INT_PRI3 first bit correspond to H48, so need
416	 subtract 48.  */
417      offset = 48;
418    }
419  else
420    error ("set_int_priority not support NDS32_INT_SWI,"
421	   " NDS32_INT_ALZ, NDS32_INT_IDIVZE, NDS32_INT_DSSIM");
422
423  mask = GEN_INT (~(3 << 2 * (INTVAL (operands[0]) - offset)));
424  priority = GEN_INT ((int) (INTVAL (operands[1])
425			     << ((INTVAL (operands[0]) - offset) * 2)));
426
427  if (system_reg != NULL_RTX)
428    {
429      emit_move_insn (mask_reg, mask);
430      emit_move_insn (set_reg, priority);
431      emit_insn (gen_unspec_volatile_mfsr (temp_reg, system_reg));
432      emit_insn (gen_andsi3 (temp_reg, temp_reg, mask_reg));
433      emit_insn (gen_iorsi3 (temp_reg, temp_reg, set_reg));
434      emit_insn (gen_unspec_volatile_mtsr (temp_reg, system_reg));
435      emit_insn (gen_unspec_dsb ());
436    }
437  DONE;
438})
439
440(define_expand "unspec_get_int_priority"
441  [(set (match_operand:SI 0 "register_operand" "")
442	(unspec_volatile:SI [(match_operand:SI 1 "immediate_operand" "")] UNSPEC_VOLATILE_GET_INT_PRIORITY))]
443  ""
444{
445  rtx system_reg = NULL_RTX;
446  rtx priority = NULL_RTX;
447  unsigned offset = 0;
448
449  /* Get system register form nds32_intrinsic_register_names[]  */
450  if (INTVAL (operands[1]) <= NDS32_INT_H15)
451    {
452      system_reg =  GEN_INT (__NDS32_REG_INT_PRI__);
453      offset = 0;
454    }
455  else if (INTVAL (operands[1]) >= NDS32_INT_H16
456	   && INTVAL (operands[1]) <= NDS32_INT_H31)
457    {
458      system_reg =  GEN_INT (__NDS32_REG_INT_PRI2__);
459      /* The $INT_PRI2 first bit correspond to H16, so need
460	 subtract 16.  */
461      offset = 16;
462    }
463  else if (INTVAL (operands[1]) >= NDS32_INT_H32
464	   && INTVAL (operands[1]) <= NDS32_INT_H47)
465    {
466      system_reg =  GEN_INT (__NDS32_REG_INT_PRI3__);
467      /* The $INT_PRI3 first bit correspond to H32, so need
468	 subtract 32.  */
469      offset = 32;
470    }
471  else if (INTVAL (operands[1]) >= NDS32_INT_H48
472	   && INTVAL (operands[1]) <= NDS32_INT_H63)
473    {
474      system_reg =  GEN_INT (__NDS32_REG_INT_PRI4__);
475      /* The $INT_PRI4 first bit correspond to H48, so need
476	 subtract 48.  */
477      offset = 48;
478    }
479  else
480    error ("set_int_priority not support NDS32_INT_SWI,"
481	   " NDS32_INT_ALZ, NDS32_INT_IDIVZE, NDS32_INT_DSSIM");
482
483  priority = GEN_INT (31 - 2 * (INTVAL (operands[1]) - offset));
484
485  if (system_reg != NULL_RTX)
486    {
487      emit_insn (gen_unspec_volatile_mfsr (operands[0], system_reg));
488      emit_insn (gen_ashlsi3 (operands[0], operands[0], priority));
489      emit_insn (gen_lshrsi3 (operands[0], operands[0], GEN_INT (30)));
490      emit_insn (gen_unspec_dsb ());
491    }
492  DONE;
493})
494
495(define_expand "unspec_set_trig_level"
496  [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "")] UNSPEC_VOLATILE_SET_TRIG_LEVEL)]
497  ""
498{
499  rtx system_reg = NULL_RTX;
500  rtx temp_reg = gen_reg_rtx (SImode);
501  rtx set_level;
502  unsigned offset = 0;
503
504  if (INTVAL (operands[0]) >= NDS32_INT_H0
505      && INTVAL (operands[0]) <= NDS32_INT_H31)
506    {
507      system_reg = GEN_INT (__NDS32_REG_INT_TRIGGER__);
508      offset = 0;
509    }
510  else if (INTVAL (operands[0]) >= NDS32_INT_H32
511	   && INTVAL (operands[0]) <= NDS32_INT_H63)
512    {
513      system_reg = GEN_INT (__NDS32_REG_INT_TRIGGER2__);
514      offset = 32;
515    }
516  else
517    error ("__nds32__set_trig_type_level not support NDS32_INT_SWI,"
518	   " NDS32_INT_ALZ, NDS32_INT_IDIVZE, NDS32_INT_DSSIM");
519
520  if (system_reg != NULL_RTX)
521    {
522      /* TRIGGER register, 0 mean level triggered and 1 mean edge triggered. */
523      set_level = GEN_INT (~(1 << (INTVAL (operands[0]) - offset)));
524
525      emit_insn (gen_unspec_volatile_mfsr (temp_reg, system_reg));
526      emit_insn (gen_andsi3 (temp_reg, temp_reg, set_level));
527      emit_insn (gen_unspec_volatile_mtsr (temp_reg, system_reg));
528    }
529  DONE;
530})
531
532(define_expand "unspec_set_trig_edge"
533  [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "")] UNSPEC_VOLATILE_SET_TRIG_EDGE)]
534  ""
535{
536  rtx system_reg = NULL_RTX;
537  rtx temp_reg = gen_reg_rtx (SImode);
538  rtx set_level;
539  unsigned offset = 0;
540
541  if (INTVAL (operands[0]) >= NDS32_INT_H0
542      && INTVAL (operands[0]) <= NDS32_INT_H31)
543    {
544      system_reg = GEN_INT (__NDS32_REG_INT_TRIGGER__);
545      offset = 0;
546    }
547  else if (INTVAL (operands[0]) >= NDS32_INT_H32
548	   && INTVAL (operands[0]) <= NDS32_INT_H63)
549    {
550      system_reg = GEN_INT (__NDS32_REG_INT_TRIGGER2__);
551      offset = 32;
552    }
553  else
554    error ("__nds32__set_trig_type_edge not support NDS32_INT_SWI,"
555	   " NDS32_INT_ALZ, NDS32_INT_IDIVZE, NDS32_INT_DSSIM");
556
557  if (system_reg != NULL_RTX)
558    {
559      /* TRIGGER register, 0 mean level triggered and 1 mean edge triggered. */
560      set_level = GEN_INT ((1 << (INTVAL (operands[0]) - offset)));
561
562      emit_insn (gen_unspec_volatile_mfsr (temp_reg, system_reg));
563      emit_insn (gen_iorsi3 (temp_reg, temp_reg, set_level));
564      emit_insn (gen_unspec_volatile_mtsr (temp_reg, system_reg));
565    }
566  DONE;
567})
568
569(define_expand "unspec_get_trig_type"
570  [(set (match_operand:SI 0 "register_operand" "")
571	(unspec_volatile:SI [(match_operand:SI 1 "immediate_operand" "")] UNSPEC_VOLATILE_GET_TRIG_TYPE))]
572  ""
573{
574  rtx system_reg = NULL_RTX;
575  rtx trig_type;
576  unsigned offset = 0;
577
578  if (INTVAL (operands[1]) >= NDS32_INT_H0
579      && INTVAL (operands[1]) <= NDS32_INT_H31)
580    {
581      system_reg = GEN_INT (__NDS32_REG_INT_TRIGGER__);
582      offset = 0;
583    }
584  else if (INTVAL (operands[1]) >= NDS32_INT_H32
585	   && INTVAL (operands[1]) <= NDS32_INT_H63)
586    {
587      system_reg = GEN_INT (__NDS32_REG_INT_TRIGGER2__);
588      offset = 32;
589    }
590  else
591    error ("__nds32__get_trig_type not support NDS32_INT_SWI,"
592	   " NDS32_INT_ALZ, NDS32_INT_IDIVZE, NDS32_INT_DSSIM");
593
594  if (system_reg != NULL_RTX)
595    {
596      trig_type = GEN_INT (31 - (INTVAL (operands[1]) - offset));
597
598      emit_insn (gen_unspec_volatile_mfsr (operands[0], system_reg));
599      emit_insn (gen_ashlsi3 (operands[0], operands[0], trig_type));
600      emit_insn (gen_lshrsi3 (operands[0], operands[0], GEN_INT (31)));
601      emit_insn (gen_unspec_dsb ());
602    }
603  DONE;
604})
605
606;; ------------------------------------------------------------------------
607
608;; Cache Synchronization Instructions
609
610(define_insn "unspec_volatile_isync"
611  [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")] UNSPEC_VOLATILE_ISYNC)]
612  ""
613  "isync\t%0"
614  [(set_attr "type" "misc")]
615)
616
617(define_insn "unspec_volatile_isb"
618  [(unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_ISB)]
619  ""
620  "isb"
621  [(set_attr "type" "misc")]
622)
623
624(define_insn "unspec_dsb"
625  [(unspec_volatile [(const_int 0)] UNSPEC_VOLATILE_DSB)]
626  ""
627  "dsb"
628  [(set_attr "type" "misc")]
629)
630
631(define_insn "unspec_msync"
632  [(unspec_volatile [(match_operand:SI 0 "immediate_operand" "i")] UNSPEC_VOLATILE_MSYNC)]
633  ""
634  "msync\t%0"
635  [(set_attr "type" "misc")]
636)
637
638(define_insn "unspec_msync_all"
639  [(unspec_volatile [(const_int 0)] UNSPEC_VOLATILE_MSYNC_ALL)]
640  ""
641  "msync\tall"
642  [(set_attr "type" "misc")]
643)
644
645(define_insn "unspec_msync_store"
646  [(unspec_volatile [(const_int 0)] UNSPEC_VOLATILE_MSYNC_STORE)]
647  ""
648  "msync\tstore"
649  [(set_attr "type" "misc")]
650)
651
652;; Load and Store
653
654(define_insn "unspec_volatile_llw"
655  [(set (match_operand:SI 0 "register_operand" "=r")
656	(unspec_volatile:SI [(mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
657					      (match_operand:SI 2 "register_operand" "r")))] UNSPEC_VOLATILE_LLW))]
658  ""
659  "llw\t%0, [%1 + %2]"
660  [(set_attr "length"    "4")]
661)
662
663(define_insn "unspec_lwup"
664  [(set (match_operand:SI 0 "register_operand" "=r")
665	(unspec_volatile:SI [(mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
666					      (match_operand:SI 2 "register_operand" "r")))] UNSPEC_LWUP))]
667  ""
668  "lwup\t%0, [%1 + %2]"
669  [(set_attr "length"    "4")]
670)
671
672(define_insn "unspec_lbup"
673  [(set (match_operand:SI 0 "register_operand" "=r")
674	(unspec_volatile:SI [(mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
675					      (match_operand:SI 2 "register_operand" "r")))] UNSPEC_LBUP))]
676  ""
677  "lbup\t%0, [%1 + %2]"
678  [(set_attr "length"    "4")]
679)
680
681(define_insn "unspec_volatile_scw"
682  [(set (match_operand:SI 0 "register_operand" "=r")
683	(unspec_volatile:SI [(mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
684					      (match_operand:SI 2 "register_operand" "r")))
685			     (match_operand:SI 3 "register_operand" "0")] UNSPEC_VOLATILE_SCW))]
686  ""
687  "scw\t%0, [%1 + %2]"
688  [(set_attr "length"     "4")]
689)
690
691(define_insn "unspec_swup"
692  [(set (mem:SI (plus:SI (match_operand:SI 0 "register_operand" "r")
693			 (match_operand:SI 1 "register_operand" "r")))
694	(unspec:SI [(match_operand:SI 2 "register_operand" "r")] UNSPEC_SWUP))]
695  ""
696  "swup\t%2, [%0 + %1]"
697  [(set_attr "length"     "4")]
698)
699
700(define_insn "unspec_sbup"
701  [(set (mem:SI (plus:SI (match_operand:SI 0 "register_operand" "r")
702			 (match_operand:SI 1 "register_operand" "r")))
703	(unspec:SI [(match_operand:SI 2 "register_operand" "r")] UNSPEC_SBUP))]
704  ""
705  "sbup\t%2, [%0 + %1]"
706  [(set_attr "length"     "4")]
707)
708
709;; CCTL
710
711(define_insn "cctl_l1d_invalall"
712  [(unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_CCTL_L1D_INVALALL)]
713  ""
714  "cctl\tL1D_INVALALL"
715  [(set_attr "type" "mmu")]
716)
717
718(define_insn "cctl_l1d_wball_alvl"
719  [(unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_CCTL_L1D_WBALL_ALVL)]
720  ""
721  "cctl\tL1D_WBALL, alevel"
722  [(set_attr "type" "mmu")]
723)
724
725(define_insn "cctl_l1d_wball_one_lvl"
726  [(unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_CCTL_L1D_WBALL_ONE_LVL)]
727  ""
728  "cctl\tL1D_WBALL, 1level"
729  [(set_attr "type" "mmu")]
730)
731
732(define_insn "cctl_idx_read"
733  [(set (match_operand:SI 0 "register_operand" "=r")
734	(unspec_volatile:SI [(match_operand:SI 1 "immediate_operand" "i")
735			     (match_operand:SI 2 "register_operand" "r")] UNSPEC_VOLATILE_CCTL_IDX_READ))]
736  ""
737  "cctl\t%0, %2, %X1"
738  [(set_attr "type" "mmu")]
739)
740
741(define_insn "cctl_idx_write"
742  [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i")
743			(match_operand:SI 1 "register_operand" "r")
744			(match_operand:SI 2 "register_operand" "r")] UNSPEC_VOLATILE_CCTL_IDX_WRITE)]
745  ""
746  "cctl\t%1, %2, %W0"
747  [(set_attr "type" "mmu")]
748)
749
750(define_insn "cctl_va_wbinval_l1"
751  [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i")
752			(match_operand:SI 1 "register_operand" "r")] UNSPEC_VOLATILE_CCTL_VA_WBINVAL_L1)]
753  ""
754  "cctl\t%1, %U0, 1level"
755  [(set_attr "type" "mmu")]
756)
757
758(define_insn "cctl_va_wbinval_la"
759  [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i")
760			(match_operand:SI 1 "register_operand" "r")] UNSPEC_VOLATILE_CCTL_VA_WBINVAL_LA)]
761  ""
762  "cctl\t%1, %U0, alevel"
763  [(set_attr "type" "mmu")]
764)
765
766(define_insn "cctl_idx_wbinval"
767  [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i")
768			(match_operand:SI 1 "register_operand" "r")] UNSPEC_VOLATILE_CCTL_IDX_WBINVAL)]
769  ""
770  "cctl\t%1, %T0"
771  [(set_attr "type" "mmu")]
772)
773
774(define_insn "cctl_va_lck"
775  [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i")
776			(match_operand:SI 1 "register_operand" "r")] UNSPEC_VOLATILE_CCTL_VA_LCK)]
777  ""
778  "cctl\t%1, %R0"
779  [(set_attr "type" "mmu")]
780)
781
782;;PREFETCH
783
784(define_insn "prefetch_qw"
785  [(unspec_volatile:QI [(match_operand:SI 0 "register_operand" "r")
786			(match_operand:SI 1 "nonmemory_operand" "r")
787			(match_operand:SI 2 "immediate_operand" "i")] UNSPEC_VOLATILE_DPREF_QW)]
788  ""
789  "dpref\t%Z2, [%0 + %1]"
790  [(set_attr "type" "misc")]
791)
792
793(define_insn "prefetch_hw"
794  [(unspec_volatile:HI [(match_operand:SI 0 "register_operand" "r")
795			(match_operand:SI 1 "nonmemory_operand" "r")
796			(match_operand:SI 2 "immediate_operand" "i")] UNSPEC_VOLATILE_DPREF_HW)]
797  ""
798  "dpref\t%Z2, [%0 + (%1<<1)]"
799  [(set_attr "type" "misc")]
800)
801
802(define_insn "prefetch_w"
803  [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "    r, r")
804			(match_operand:SI 1 "nonmemory_operand" "Is15, r")
805			(match_operand:SI 2 "immediate_operand" "   i, i")] UNSPEC_VOLATILE_DPREF_W)]
806  ""
807  "@
808  dprefi.w\t%Z2, [%0 + %1]
809  dpref\t%Z2, [%0 + (%1<<2)]"
810  [(set_attr "type" "misc")]
811)
812
813(define_insn "prefetch_dw"
814  [(unspec_volatile:DI [(match_operand:SI 0 "register_operand"  "   r, r")
815			(match_operand:SI 1 "nonmemory_operand" "Is15, r")
816			(match_operand:SI 2 "immediate_operand" "   i, i")] UNSPEC_VOLATILE_DPREF_DW)]
817  ""
818  "@
819  dprefi.d\t%Z2, [%0 + %1]
820  dpref\t%Z2, [%0 + (%1<<3)]"
821  [(set_attr "type" "misc")]
822)
823
824;; Performance Extension
825
826(define_expand "unspec_ave"
827  [(match_operand:SI 0 "register_operand" "")
828   (match_operand:SI 1 "register_operand" "")
829   (match_operand:SI 2 "register_operand" "")]
830  ""
831{
832  emit_insn (gen_ave (operands[0], operands[1], operands[2]));
833  DONE;
834})
835
836(define_expand "unspec_bclr"
837  [(match_operand:SI 0 "register_operand" "")
838   (match_operand:SI 1 "register_operand" "")
839   (match_operand:SI 2 "immediate_operand" "")]
840  ""
841{
842  unsigned HOST_WIDE_INT val = ~(1u << UINTVAL (operands[2]));
843  emit_insn (gen_andsi3 (operands[0], operands[1], gen_int_mode (val, SImode)));
844  DONE;
845})
846
847(define_expand "unspec_bset"
848  [(match_operand:SI 0 "register_operand" "")
849   (match_operand:SI 1 "register_operand" "")
850   (match_operand:SI 2 "immediate_operand" "")]
851  ""
852{
853  unsigned HOST_WIDE_INT val = 1u << UINTVAL (operands[2]);
854  emit_insn (gen_iorsi3 (operands[0], operands[1], gen_int_mode (val, SImode)));
855  DONE;
856})
857
858(define_expand "unspec_btgl"
859  [(match_operand:SI 0 "register_operand" "")
860   (match_operand:SI 1 "register_operand" "")
861   (match_operand:SI 2 "immediate_operand" "")]
862  ""
863{
864  unsigned HOST_WIDE_INT val = 1u << UINTVAL (operands[2]);
865  emit_insn (gen_xorsi3 (operands[0], operands[1], gen_int_mode (val, SImode)));
866  DONE;
867})
868
869(define_expand "unspec_btst"
870  [(match_operand:SI 0 "register_operand" "")
871   (match_operand:SI 1 "register_operand" "")
872   (match_operand:SI 2 "immediate_operand" "")]
873  ""
874{
875  emit_insn (gen_btst (operands[0], operands[1], operands[2]));
876  DONE;
877})
878
879(define_insn "unspec_clip"
880  [(set (match_operand:SI 0 "register_operand" "=r")
881	(unspec:SI [(match_operand:SI 1 "register_operand" "r")
882		    (match_operand:SI 2 "immediate_operand" "i")] UNSPEC_CLIP))]
883  ""
884  "clip\t%0, %1, %2"
885  [(set_attr "type" "alu")
886   (set_attr "length" "4")]
887)
888
889(define_insn "unspec_clips"
890  [(set (match_operand:SI 0 "register_operand" "=r")
891	(unspec:SI [(match_operand:SI 1 "register_operand" "r")
892		    (match_operand:SI 2 "immediate_operand" "i")] UNSPEC_CLIPS))]
893  ""
894  "clips\t%0, %1, %2"
895  [(set_attr "type" "alu")
896   (set_attr "length" "4")]
897)
898
899(define_insn "unspec_clo"
900  [(set (match_operand:SI 0 "register_operand" "=r")
901	(unspec:SI [(match_operand:SI 1 "register_operand" "r")] UNSPEC_CLO))]
902  ""
903  "clo\t%0, %1"
904  [(set_attr "type" "alu")
905   (set_attr "length" "4")]
906)
907
908(define_insn "unspec_ssabssi2"
909  [(set (match_operand:SI 0 "register_operand" "=r")
910	(ss_abs:SI (match_operand:SI 1 "register_operand" "r")))]
911  ""
912  "abs\t%0, %1"
913  [(set_attr "type" "alu")
914   (set_attr "length" "4")]
915)
916
917;; Performance extension 2
918
919(define_insn "unspec_pbsad"
920  [(set (match_operand:SI 0 "register_operand" "=r")
921	(unspec:SI [(match_operand:SI 1 "register_operand" "r")
922		    (match_operand:SI 2 "register_operand" "r")] UNSPEC_PBSAD))]
923  ""
924  "pbsad\t%0, %1, %2"
925  [(set_attr "type" "pbsad")
926   (set_attr "length"   "4")]
927)
928
929(define_insn "unspec_pbsada"
930  [(set (match_operand:SI 0 "register_operand" "=r")
931	(unspec:SI [(match_operand:SI 1 "register_operand" "0")
932		    (match_operand:SI 2 "register_operand" "r")
933		    (match_operand:SI 3 "register_operand" "r")] UNSPEC_PBSADA))]
934  ""
935  "pbsada\t%0, %2, %3"
936  [(set_attr "type" "pbsada")
937   (set_attr "length"    "4")]
938)
939
940(define_expand "bse"
941  [(match_operand:SI 0 "register_operand" "")
942   (match_operand:SI 1 "register_operand" "")
943   (match_operand:SI 2 "register_operand" "")]
944  ""
945  {
946    rtx temp0 = gen_reg_rtx (SImode);
947    rtx temp2 = gen_reg_rtx (SImode);
948
949    emit_move_insn (temp0, gen_rtx_MEM (Pmode, operands[0]));
950    emit_move_insn (temp2, gen_rtx_MEM (Pmode, operands[2]));
951    emit_insn (gen_unspec_bse (temp0, operands[1], temp2, temp0, temp2));
952    emit_move_insn (gen_rtx_MEM (Pmode, operands[0]), temp0);
953    emit_move_insn (gen_rtx_MEM (Pmode, operands[2]), temp2);
954    DONE;
955  }
956)
957
958(define_insn "unspec_bse"
959  [(set (match_operand:SI 0 "register_operand" "=r")
960	(unspec:SI [(match_operand:SI 1 "register_operand" "r")
961		    (match_operand:SI 2 "register_operand" "r")
962		    (match_operand:SI 3 "register_operand" "0")] UNSPEC_BSE))
963   (set (match_operand:SI 4 "register_operand" "=2")
964	(unspec:SI [(match_dup 1)
965		    (match_dup 2)
966		    (match_dup 0)] UNSPEC_BSE_2))]
967  ""
968  "bse\t%0, %1, %2"
969  [(set_attr "type" "alu")
970   (set_attr "length" "4")]
971)
972
973(define_expand "bsp"
974  [(match_operand:SI 0 "register_operand" "")
975   (match_operand:SI 1 "register_operand" "")
976   (match_operand:SI 2 "register_operand" "")]
977  ""
978  {
979    rtx temp0 = gen_reg_rtx (SImode);
980    rtx temp2 = gen_reg_rtx (SImode);
981
982    emit_move_insn (temp0, gen_rtx_MEM (Pmode, operands[0]));
983    emit_move_insn (temp2, gen_rtx_MEM (Pmode, operands[2]));
984    emit_insn (gen_unspec_bsp (temp0, operands[1], temp2, temp0, temp2));
985    emit_move_insn (gen_rtx_MEM (Pmode, operands[0]), temp0);
986    emit_move_insn (gen_rtx_MEM (Pmode, operands[2]), temp2);
987    DONE;
988  }
989)
990
991(define_insn "unspec_bsp"
992  [(set (match_operand:SI 0 "register_operand" "=r")
993	(unspec:SI [(match_operand:SI 1 "register_operand" "r")
994		    (match_operand:SI 2 "register_operand" "r")
995		    (match_operand:SI 3 "register_operand" "0")] UNSPEC_BSP))
996   (set (match_operand:SI 4 "register_operand" "=2")
997	(unspec:SI [(match_dup 1)
998		    (match_dup 2)
999		    (match_dup 0)] UNSPEC_BSP_2))]
1000  ""
1001  "bsp\t%0, %1, %2"
1002  [(set_attr "type" "alu")
1003   (set_attr "length" "4")]
1004)
1005
1006;; String Extension
1007
1008(define_insn "unspec_ffb"
1009  [(set (match_operand:SI 0 "register_operand" "=r, r")
1010	(unspec:SI [(match_operand:SI 1 "register_operand" "r, r")
1011		    (match_operand:SI 2 "nonmemory_operand" "Iu08, r")] UNSPEC_FFB))]
1012  ""
1013  "@
1014  ffbi\t%0, %1, %2
1015  ffb\t%0, %1, %2"
1016  [(set_attr "type" "alu")
1017   (set_attr "length" "4")]
1018)
1019
1020(define_insn "unspec_ffmism"
1021  [(set (match_operand:SI 0 "register_operand" "=r")
1022	(unspec:SI [(match_operand:SI 1 "register_operand" "r")
1023		    (match_operand:SI 2 "register_operand" "r")] UNSPEC_FFMISM))]
1024  ""
1025  "ffmism\t%0, %1, %2"
1026  [(set_attr "type" "alu")
1027   (set_attr "length" "4")]
1028)
1029
1030(define_insn "unspec_flmism"
1031  [(set (match_operand:SI 0 "register_operand" "=r")
1032	(unspec:SI [(match_operand:SI 1 "register_operand" "r")
1033		    (match_operand:SI 2 "register_operand" "r")] UNSPEC_FLMISM))]
1034  ""
1035  "flmism\t%0, %1, %2"
1036  [(set_attr "type" "alu")
1037   (set_attr "length" "4")]
1038)
1039
1040;; SATURATION
1041
1042(define_insn "unspec_kaddw"
1043  [(set (match_operand:SI 0 "register_operand" "=r")
1044	(ss_plus:SI (match_operand:SI 1 "register_operand" "r")
1045		    (match_operand:SI 2 "register_operand" "r")))]
1046  ""
1047  "kaddw\t%0, %1, %2"
1048  [(set_attr "type"    "alu")
1049   (set_attr "length"    "4")]
1050)
1051
1052(define_insn "unspec_ksubw"
1053  [(set (match_operand:SI 0 "register_operand" "=r")
1054	(ss_minus:SI (match_operand:SI 1 "register_operand" "r")
1055		     (match_operand:SI 2 "register_operand" "r")))]
1056  ""
1057  "ksubw\t%0, %1, %2"
1058  [(set_attr "type"    "alu")
1059   (set_attr "length"    "4")]
1060)
1061
1062(define_insn "unspec_kaddh"
1063  [(set (match_operand:SI 0 "register_operand" "=r")
1064	(unspec:SI [(match_operand:SI 1 "register_operand" "r")
1065		    (match_operand:SI 2 "register_operand" "r")] UNSPEC_KADDH))]
1066  ""
1067  "kaddh\t%0, %1, %2"
1068  [(set_attr "type"    "alu")
1069   (set_attr "length"    "4")]
1070)
1071
1072(define_insn "unspec_ksubh"
1073  [(set (match_operand:SI 0 "register_operand" "=r")
1074	(unspec:SI [(match_operand:SI 1 "register_operand" "r")
1075		    (match_operand:SI 2 "register_operand" "r")] UNSPEC_KSUBH))]
1076  ""
1077  "ksubh\t%0, %1, %2"
1078  [(set_attr "type"    "alu")
1079   (set_attr "length"    "4")]
1080)
1081
1082(define_insn "unspec_kaddh_dsp"
1083  [(set (match_operand:SI 0 "register_operand" "=r")
1084	(unspec:SI [(plus:SI (match_operand:SI 1 "register_operand" "r")
1085			     (match_operand:SI 2 "register_operand" "r"))
1086		    (const_int 15)] UNSPEC_CLIPS))]
1087  "NDS32_EXT_DSP_P ()"
1088  "kaddh\t%0, %1, %2"
1089  [(set_attr "type"    "alu")
1090   (set_attr "length"    "4")]
1091)
1092
1093(define_insn "unspec_ksubh_dsp"
1094  [(set (match_operand:SI 0 "register_operand" "=r")
1095	(unspec:SI [(minus:SI (match_operand:SI 1 "register_operand" "r")
1096			      (match_operand:SI 2 "register_operand" "r"))
1097		    (const_int 15)] UNSPEC_CLIPS))]
1098  "NDS32_EXT_DSP_P ()"
1099  "ksubh\t%0, %1, %2"
1100  [(set_attr "type"    "alu")
1101   (set_attr "length"    "4")]
1102)
1103
1104(define_insn "unspec_kdmbb"
1105  [(set (match_operand:V2HI 0 "register_operand" "=r")
1106	(unspec:V2HI [(match_operand:V2HI 1 "register_operand" "r")
1107		      (match_operand:V2HI 2 "register_operand" "r")] UNSPEC_KDMBB))]
1108  ""
1109  "kdmbb\t%0, %1, %2"
1110  [(set_attr "type"    "mul")
1111   (set_attr "length"    "4")]
1112)
1113
1114(define_insn "unspec_kdmbt"
1115  [(set (match_operand:V2HI 0 "register_operand" "=r")
1116	(unspec:V2HI [(match_operand:V2HI 1 "register_operand" "r")
1117		      (match_operand:V2HI 2 "register_operand" "r")] UNSPEC_KDMBT))]
1118  ""
1119  "kdmbt\t%0, %1, %2"
1120  [(set_attr "type"    "mul")
1121   (set_attr "length"    "4")]
1122)
1123
1124(define_insn "unspec_kdmtb"
1125  [(set (match_operand:V2HI 0 "register_operand" "=r")
1126	(unspec:V2HI [(match_operand:V2HI 1 "register_operand" "r")
1127		      (match_operand:V2HI 2 "register_operand" "r")] UNSPEC_KDMTB))]
1128  ""
1129  "kdmtb\t%0, %1, %2"
1130  [(set_attr "type"    "mul")
1131   (set_attr "length"    "4")]
1132)
1133
1134(define_insn "unspec_kdmtt"
1135  [(set (match_operand:V2HI 0 "register_operand" "=r")
1136	(unspec:V2HI [(match_operand:V2HI 1 "register_operand" "r")
1137		      (match_operand:V2HI 2 "register_operand" "r")] UNSPEC_KDMTT))]
1138  ""
1139  "kdmtt\t%0, %1, %2"
1140  [(set_attr "type"    "mul")
1141   (set_attr "length"    "4")]
1142)
1143
1144(define_insn "unspec_khmbb"
1145  [(set (match_operand:V2HI 0 "register_operand" "=r")
1146	(unspec:V2HI [(match_operand:V2HI 1 "register_operand" "r")
1147		      (match_operand:V2HI 2 "register_operand" "r")] UNSPEC_KHMBB))]
1148  ""
1149  "khmbb\t%0, %1, %2"
1150  [(set_attr "type"    "mul")
1151   (set_attr "length"    "4")]
1152)
1153
1154(define_insn "unspec_khmbt"
1155  [(set (match_operand:V2HI 0 "register_operand" "=r")
1156	(unspec:V2HI [(match_operand:V2HI 1 "register_operand" "r")
1157		      (match_operand:V2HI 2 "register_operand" "r")] UNSPEC_KHMBT))]
1158  ""
1159  "khmbt\t%0, %1, %2"
1160  [(set_attr "type"    "mul")
1161   (set_attr "length"    "4")]
1162)
1163
1164(define_insn "unspec_khmtb"
1165  [(set (match_operand:V2HI 0 "register_operand" "=r")
1166	(unspec:V2HI [(match_operand:V2HI 1 "register_operand" "r")
1167		      (match_operand:V2HI 2 "register_operand" "r")] UNSPEC_KHMTB))]
1168  ""
1169  "khmtb\t%0, %1, %2"
1170  [(set_attr "type"    "mul")
1171   (set_attr "length"    "4")]
1172)
1173
1174(define_insn "unspec_khmtt"
1175  [(set (match_operand:V2HI 0 "register_operand" "=r")
1176	(unspec:V2HI [(match_operand:V2HI 1 "register_operand" "r")
1177		      (match_operand:V2HI 2 "register_operand" "r")] UNSPEC_KHMTT))]
1178  ""
1179  "khmtt\t%0, %1, %2"
1180  [(set_attr "type"    "mul")
1181   (set_attr "length"    "4")]
1182)
1183
1184(define_insn "unspec_kslraw"
1185  [(set (match_operand:SI 0 "register_operand" "=r")
1186	(unspec:SI [(match_operand:SI 1 "register_operand" "r")
1187		    (match_operand:SI 2 "register_operand" "r")] UNSPEC_KSLRAW))]
1188  ""
1189  "kslraw\t%0, %1, %2"
1190  [(set_attr "type"    "alu")
1191   (set_attr "length"    "4")]
1192)
1193
1194(define_insn "unspec_kslrawu"
1195  [(set (match_operand:SI 0 "register_operand" "=r")
1196	(unspec:SI [(match_operand:SI 1 "register_operand" "r")
1197		    (match_operand:SI 2 "register_operand" "r")] UNSPEC_KSLRAWU))]
1198  ""
1199  "kslraw.u\t%0, %1, %2"
1200  [(set_attr "type"    "alu")
1201   (set_attr "length"    "4")]
1202)
1203
1204(define_insn "unspec_volatile_rdov"
1205  [(set (match_operand:SI 0 "register_operand" "=r")
1206	(unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_RDOV))]
1207  ""
1208  "rdov\t%0"
1209  [(set_attr "type"   "misc")
1210   (set_attr "length"    "4")]
1211)
1212
1213(define_insn "unspec_volatile_clrov"
1214  [(unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_CLROV)]
1215  ""
1216  "clrov"
1217  [(set_attr "type"   "misc")
1218   (set_attr "length"    "4")]
1219)
1220
1221;; System
1222
1223(define_insn "unspec_sva"
1224  [(set (match_operand:SI 0 "register_operand" "=r")
1225	(unspec:SI [(match_operand:SI 1 "register_operand" "r")
1226		    (match_operand:SI 2 "register_operand" "r")] UNSPEC_SVA))]
1227  ""
1228  "sva\t%0, %1, %2"
1229  [(set_attr "type"    "alu")
1230   (set_attr "length"    "4")]
1231)
1232
1233(define_insn "unspec_svs"
1234  [(set (match_operand:SI 0 "register_operand" "=r")
1235	(unspec:SI [(match_operand:SI 1 "register_operand" "r")
1236		    (match_operand:SI 2 "register_operand" "r")] UNSPEC_SVS))]
1237  ""
1238  "svs\t%0, %1, %2"
1239  [(set_attr "type"    "alu")
1240   (set_attr "length"    "4")]
1241)
1242
1243(define_insn "unspec_jr_itoff"
1244  [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")] UNSPEC_VOLATILE_JR_ITOFF)]
1245  ""
1246  "jr.itoff\t%0"
1247  [(set_attr "type" "misc")]
1248)
1249
1250(define_insn "unspec_jr_toff"
1251  [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")] UNSPEC_VOLATILE_JR_TOFF)]
1252  ""
1253  "jr.toff\t%0"
1254  [(set_attr "type" "branch")]
1255)
1256
1257(define_insn "unspec_jral_iton"
1258  [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")] UNSPEC_VOLATILE_JRAL_ITON)]
1259  ""
1260  "jral.iton\t%0"
1261  [(set_attr "type" "branch")]
1262)
1263
1264(define_insn "unspec_jral_ton"
1265  [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")] UNSPEC_VOLATILE_JRAL_TON)]
1266  ""
1267  "jral.ton\t%0"
1268  [(set_attr "type" "branch")]
1269)
1270
1271(define_insn "unspec_ret_itoff"
1272  [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")] UNSPEC_VOLATILE_RET_ITOFF)]
1273  ""
1274  "ret.itoff\t%0"
1275  [(set_attr "type" "branch")]
1276)
1277
1278(define_insn "unspec_ret_toff"
1279  [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")] UNSPEC_VOLATILE_RET_TOFF)]
1280  ""
1281  "ret.toff\t%0"
1282  [(set_attr "type" "branch")]
1283)
1284
1285(define_insn "unspec_standby_no_wake_grant"
1286  [(unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_STANDBY_NO_WAKE_GRANT)]
1287  ""
1288  "standby\tno_wake_grant"
1289  [(set_attr "type" "misc")]
1290)
1291
1292(define_insn "unspec_standby_wake_grant"
1293  [(unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_STANDBY_WAKE_GRANT)]
1294  ""
1295  "standby\twake_grant"
1296  [(set_attr "type" "misc")]
1297)
1298
1299(define_insn "unspec_standby_wait_done"
1300  [(unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_STANDBY_WAKE_DONE)]
1301  ""
1302  "standby\twait_done"
1303  [(set_attr "type" "misc")]
1304)
1305
1306(define_insn "unspec_teqz"
1307  [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")
1308			(match_operand:SI 1 "immediate_operand" "i")] UNSPEC_VOLATILE_TEQZ)]
1309  ""
1310  "teqz\t%0, %1"
1311  [(set_attr "type" "misc")]
1312)
1313
1314(define_insn "unspec_tnez"
1315  [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")
1316			(match_operand:SI 1 "immediate_operand" "i")] UNSPEC_VOLATILE_TNEZ)]
1317  ""
1318  "tnez\t%0, %1"
1319  [(set_attr "type" "misc")]
1320)
1321
1322(define_insn "unspec_trap"
1323  [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i")] UNSPEC_VOLATILE_TRAP)]
1324  ""
1325  "trap\t%0"
1326  [(set_attr "type" "misc")]
1327)
1328
1329(define_insn "unspec_setend_big"
1330  [(unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_SETEND_BIG)]
1331  ""
1332  "setend.b"
1333  [(set_attr "type" "misc")]
1334)
1335
1336(define_insn "unspec_setend_little"
1337  [(unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_SETEND_LITTLE)]
1338  ""
1339  "setend.l"
1340  [(set_attr "type" "misc")]
1341)
1342
1343(define_insn "unspec_break"
1344  [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i")] UNSPEC_VOLATILE_BREAK)]
1345  ""
1346  "break\t%0"
1347  [(set_attr "type" "misc")]
1348)
1349
1350(define_insn "unspec_syscall"
1351  [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i")] UNSPEC_VOLATILE_SYSCALL)]
1352  ""
1353  "syscall\t%0"
1354  [(set_attr "type" "misc")]
1355)
1356
1357(define_insn "unspec_nop"
1358  [(unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_NOP)]
1359  ""
1360  "nop"
1361  [(set_attr "type" "misc")]
1362)
1363
1364(define_expand "unspec_get_current_sp"
1365  [(match_operand:SI 0 "register_operand" "")]
1366  ""
1367{
1368  emit_move_insn (operands[0], gen_rtx_REG (SImode, SP_REGNUM));
1369  DONE;
1370})
1371
1372(define_expand "unspec_set_current_sp"
1373  [(match_operand:SI 0 "register_operand" "")]
1374  ""
1375{
1376  emit_move_insn (gen_rtx_REG (SImode, SP_REGNUM), operands[0]);
1377  DONE;
1378})
1379
1380(define_expand "unspec_return_address"
1381  [(match_operand:SI 0 "register_operand" "")]
1382  ""
1383{
1384  emit_move_insn (operands[0], gen_rtx_REG (SImode, LP_REGNUM));
1385  DONE;
1386})
1387
1388;; Swap
1389
1390(define_insn "unspec_wsbh"
1391  [(set (match_operand:SI 0 "register_operand" "=r")
1392	(unspec:SI [(match_operand:SI 1 "register_operand" "r")] UNSPEC_WSBH))]
1393  ""
1394  "wsbh\t%0, %1"
1395  [(set_attr "type"    "alu")
1396   (set_attr "length"    "4")]
1397)
1398
1399;; TLBOP Intrinsic
1400
1401(define_insn "unspec_tlbop_trd"
1402  [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")] UNSPEC_VOLATILE_TLBOP_TRD)]
1403  ""
1404  "tlbop\t%0, TRD"
1405  [(set_attr "type" "mmu")]
1406)
1407
1408(define_insn "unspec_tlbop_twr"
1409  [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")] UNSPEC_VOLATILE_TLBOP_TWR)]
1410  ""
1411  "tlbop\t%0, TWR"
1412  [(set_attr "type" "mmu")]
1413)
1414
1415(define_insn "unspec_tlbop_rwr"
1416  [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")] UNSPEC_VOLATILE_TLBOP_RWR)]
1417  ""
1418  "tlbop\t%0, RWR"
1419  [(set_attr "type" "mmu")]
1420)
1421
1422(define_insn "unspec_tlbop_rwlk"
1423  [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")] UNSPEC_VOLATILE_TLBOP_RWLK)]
1424  ""
1425  "tlbop\t%0, RWLK"
1426  [(set_attr "type" "mmu")]
1427)
1428
1429(define_insn "unspec_tlbop_unlk"
1430  [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")] UNSPEC_VOLATILE_TLBOP_UNLK)]
1431  ""
1432  "tlbop\t%0, UNLK"
1433  [(set_attr "type" "mmu")]
1434)
1435
1436(define_insn "unspec_tlbop_pb"
1437  [(set (match_operand:SI 0 "register_operand" "=r")
1438	(unspec_volatile:SI [(match_operand:SI 1 "register_operand" "r")] UNSPEC_VOLATILE_TLBOP_PB))]
1439  ""
1440  "tlbop\t%0, %1, PB"
1441  [(set_attr "type" "mmu")]
1442)
1443
1444(define_insn "unspec_tlbop_inv"
1445  [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")] UNSPEC_VOLATILE_TLBOP_INV)]
1446  ""
1447  "tlbop\t%0, INV"
1448  [(set_attr "type" "mmu")]
1449)
1450
1451(define_insn "unspec_tlbop_flua"
1452  [(unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_TLBOP_FLUA)]
1453  ""
1454  "tlbop\tFLUA"
1455  [(set_attr "type" "mmu")]
1456)
1457
1458;;Unaligned Load/Store
1459
1460(define_expand "unaligned_load_hw"
1461  [(set (match_operand:HI 0 "register_operand" "")
1462	(unspec:HI [(mem:HI (match_operand:SI 1 "register_operand" ""))] UNSPEC_UALOAD_HW))]
1463  ""
1464{
1465  operands[0] = simplify_gen_subreg (SImode, operands[0],
1466				     GET_MODE (operands[0]), 0);
1467  if (TARGET_ISA_V3M)
1468    {
1469      nds32_expand_unaligned_load (operands, HImode);
1470    }
1471  else
1472    {
1473      emit_insn (gen_unaligned_load_w (operands[0],
1474				       gen_rtx_MEM (SImode, operands[1])));
1475
1476      if (WORDS_BIG_ENDIAN)
1477	emit_insn (gen_lshrsi3 (operands[0], operands[0], GEN_INT(16)));
1478      else
1479	emit_insn (gen_andsi3 (operands[0], operands[0], GEN_INT (0xffff)));
1480    }
1481
1482  DONE;
1483})
1484
1485(define_expand "unaligned_loadsi"
1486  [(set (match_operand:SI 0 "register_operand" "=r")
1487	(unspec:SI [(mem:SI (match_operand:SI 1 "register_operand" "r"))] UNSPEC_UALOAD_W))]
1488  ""
1489{
1490  if (flag_unaligned_access)
1491    {
1492      rtx mem = gen_rtx_MEM (SImode, operands[1]);
1493      emit_move_insn (operands[0], mem);
1494    }
1495  else
1496    {
1497      if (TARGET_ISA_V3M)
1498	nds32_expand_unaligned_load (operands, SImode);
1499      else
1500	emit_insn (gen_unaligned_load_w (operands[0],
1501					 gen_rtx_MEM (SImode, (operands[1]))));
1502    }
1503  DONE;
1504})
1505
1506(define_insn "unaligned_load_w"
1507  [(set (match_operand:SI 0 "register_operand"                       "=  r")
1508	(unspec:SI [(match_operand:SI 1 "nds32_lmw_smw_base_operand" " Umw")] UNSPEC_UALOAD_W))]
1509  ""
1510{
1511  return nds32_output_lmw_single_word (operands);
1512}
1513  [(set_attr "type"   "load")
1514   (set_attr "length"    "4")]
1515)
1516
1517(define_expand "unaligned_loaddi"
1518  [(set (match_operand:DI 0 "register_operand" "=r")
1519	(unspec:DI [(mem:DI (match_operand:SI 1 "register_operand" "r"))] UNSPEC_UALOAD_DW))]
1520  ""
1521{
1522  if (TARGET_ISA_V3M)
1523    {
1524      nds32_expand_unaligned_load (operands, DImode);
1525    }
1526  else
1527    emit_insn (gen_unaligned_load_dw (operands[0], operands[1]));
1528  DONE;
1529})
1530
1531(define_insn "unaligned_load_dw"
1532  [(set (match_operand:DI 0 "register_operand" "=r")
1533	(unspec:DI [(mem:DI (match_operand:SI 1 "register_operand" "r"))] UNSPEC_UALOAD_DW))]
1534  ""
1535{
1536  rtx otherops[3];
1537  otherops[0] = gen_rtx_REG (SImode, REGNO (operands[0]));
1538  otherops[1] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
1539  otherops[2] = operands[1];
1540
1541  output_asm_insn ("lmw.bi\t%0, [%2], %1, 0", otherops);
1542  return "";
1543}
1544  [(set_attr "type"   "load")
1545   (set_attr "length"    "4")]
1546)
1547
1548(define_expand "unaligned_store_hw"
1549  [(set (mem:SI (match_operand:SI 0 "register_operand" ""))
1550	(unspec:HI [(match_operand:HI 1 "register_operand" "")] UNSPEC_UASTORE_HW))]
1551  ""
1552{
1553  operands[1] = simplify_gen_subreg (SImode, operands[1],
1554				     GET_MODE (operands[1]), 0);
1555  nds32_expand_unaligned_store (operands, HImode);
1556  DONE;
1557})
1558
1559(define_expand "unaligned_storesi"
1560  [(set (mem:SI (match_operand:SI 0 "register_operand" "r"))
1561	(unspec:SI [(match_operand:SI 1 "register_operand" "r")] UNSPEC_UASTORE_W))]
1562  ""
1563{
1564  if (flag_unaligned_access)
1565    {
1566      rtx mem = gen_rtx_MEM (SImode, operands[0]);
1567      emit_move_insn (mem, operands[1]);
1568    }
1569  else
1570    {
1571      if (TARGET_ISA_V3M)
1572	nds32_expand_unaligned_store (operands, SImode);
1573      else
1574	emit_insn (gen_unaligned_store_w (gen_rtx_MEM (SImode, operands[0]),
1575					  operands[1]));
1576    }
1577  DONE;
1578})
1579
1580(define_insn "unaligned_store_w"
1581  [(set (match_operand:SI 0 "nds32_lmw_smw_base_operand"   "=Umw")
1582	(unspec:SI [(match_operand:SI 1 "register_operand" "   r")] UNSPEC_UASTORE_W))]
1583  ""
1584{
1585  return nds32_output_smw_single_word (operands);
1586}
1587  [(set_attr "type"   "store")
1588   (set_attr "length"     "4")]
1589)
1590
1591(define_expand "unaligned_storedi"
1592  [(set (mem:DI (match_operand:SI 0 "register_operand" "r"))
1593	(unspec:DI [(match_operand:DI 1 "register_operand" "r")] UNSPEC_UASTORE_DW))]
1594  ""
1595{
1596  if (TARGET_ISA_V3M)
1597    nds32_expand_unaligned_store (operands, DImode);
1598  else
1599    emit_insn (gen_unaligned_store_dw (gen_rtx_MEM (DImode, operands[0]),
1600				       operands[1]));
1601  DONE;
1602})
1603
1604(define_insn "unaligned_store_dw"
1605  [(set (match_operand:DI 0 "nds32_lmw_smw_base_operand"   "=Umw")
1606	(unspec:DI [(match_operand:DI 1 "register_operand" "   r")] UNSPEC_UASTORE_DW))]
1607  ""
1608{
1609  return nds32_output_smw_double_word (operands);
1610}
1611  [(set_attr "type"   "store")
1612   (set_attr "length"     "4")]
1613)
1614
1615(define_expand "unspec_unaligned_feature"
1616  [(set (match_operand:SI 0 "register_operand" "")
1617	(unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_UNALIGNED_FEATURE))]
1618  ""
1619{
1620  /* Get $MMU_CTL system register form nds32_intrinsic_register_names[]  */
1621  rtx system_reg =  GEN_INT (__NDS32_REG_MMU_CTL__);
1622  rtx temp_reg = gen_reg_rtx (SImode);
1623  rtx temp2_reg = gen_reg_rtx (SImode);
1624
1625  emit_insn (gen_unspec_volatile_mfsr (operands[0], system_reg));
1626  emit_move_insn (temp_reg, operands[0]);
1627  emit_move_insn (temp2_reg, GEN_INT (0x800 << 12));
1628  emit_insn (gen_iorsi3 (operands[0], operands[0], temp2_reg));
1629  emit_insn (gen_unspec_volatile_mtsr (operands[0], system_reg));
1630  emit_insn (gen_unspec_dsb ());
1631
1632  emit_insn (gen_unspec_volatile_mfsr (operands[0], system_reg));
1633  emit_insn (gen_unspec_volatile_mtsr (temp_reg, system_reg));
1634  emit_insn (gen_unspec_dsb ());
1635
1636  emit_insn (gen_ashlsi3 (operands[0], operands[0], GEN_INT (8)));
1637  emit_insn (gen_lshrsi3 (operands[0], operands[0], GEN_INT (31)));
1638  DONE;
1639})
1640
1641(define_expand "unspec_enable_unaligned"
1642  [(unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_UNALIGNED_FEATURE)]
1643  ""
1644{
1645  /* Get $MMU_CTL system register form nds32_intrinsic_register_names[]  */
1646  rtx system_reg =  GEN_INT (__NDS32_REG_MMU_CTL__);
1647  rtx temp_reg = gen_reg_rtx (SImode);
1648  rtx temp2_reg = gen_reg_rtx (SImode);
1649  emit_insn (gen_unspec_volatile_mfsr (temp_reg, system_reg));
1650  emit_move_insn (temp2_reg, GEN_INT (0x800 << 12));
1651  emit_insn (gen_iorsi3 (temp_reg, temp_reg, temp2_reg));
1652  emit_insn (gen_unspec_volatile_mtsr (temp_reg, system_reg));
1653  emit_insn (gen_unspec_dsb ());
1654  DONE;
1655})
1656
1657(define_expand "unspec_disable_unaligned"
1658  [(unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_UNALIGNED_FEATURE)]
1659  ""
1660{
1661  /* Get $MMU_CTL system register form nds32_intrinsic_register_names[]  */
1662  rtx system_reg =  GEN_INT (__NDS32_REG_MMU_CTL__);
1663  rtx temp_reg = gen_reg_rtx (SImode);
1664  rtx temp2_reg = gen_reg_rtx (SImode);
1665  emit_insn (gen_unspec_volatile_mfsr (temp_reg, system_reg));
1666  emit_move_insn (temp2_reg, GEN_INT (0x800 << 12));
1667  emit_insn (gen_one_cmplsi2 (temp2_reg, temp2_reg));
1668  emit_insn (gen_andsi3 (temp_reg, temp_reg, temp2_reg));
1669  emit_insn (gen_unspec_volatile_mtsr (temp_reg, system_reg));
1670  emit_insn (gen_unspec_dsb ());
1671  DONE;
1672})
1673
1674;; abs alias kabs
1675
1676(define_insn "unspec_kabs"
1677  [(set (match_operand:SI 0 "register_operand" "=r")
1678	(unspec:SI [(match_operand:SI 1 "register_operand" "r")] UNSPEC_KABS))]
1679  ""
1680  "kabs\t%0, %1"
1681  [(set_attr "type" "alu")
1682   (set_attr "length" "4")]
1683)
1684
1685;; ------------------------------------------------------------------------
1686