1;; Machine Description for Altera Nios II.
2;; Copyright (C) 2012-2022 Free Software Foundation, Inc.
3;; Contributed by Jonah Graham (jgraham@altera.com) and
4;; Will Reece (wreece@altera.com).
5;; Contributed by Mentor Graphics, Inc.
6;;
7;; This file is part of GCC.
8;;
9;; GCC is free software; you can redistribute it and/or modify
10;; it under the terms of the GNU General Public License as published by
11;; the Free Software Foundation; either version 3, or (at your option)
12;; any later version.
13;;
14;; GCC is distributed in the hope that it will be useful,
15;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17;; GNU General Public License for more details.
18;;
19;; You should have received a copy of the GNU General Public License
20;; along with GCC; see the file COPYING3.  If not see
21;; <http://www.gnu.org/licenses/>.
22
23;; Register numbers
24(define_constants
25  [
26   (FIRST_RETVAL_REGNO     2)	; Return value registers
27   (LAST_RETVAL_REGNO      3)	;
28   (FIRST_ARG_REGNO        4)	; Argument registers
29   (LAST_ARG_REGNO         7)	;
30
31   (TP_REGNO              23)	; Thread pointer register
32   (GP_REGNO	          26)	; Global pointer register
33   (SP_REGNO	          27)	; Stack pointer register
34   (FP_REGNO	          28)	; Frame pointer register
35   (EA_REGNO	          29)	; Exception return address register
36   (RA_REGNO              31)	; Return address register
37   (LAST_GP_REG           31)	; Last general purpose register
38
39   ;; Target register definitions
40   (STATIC_CHAIN_REGNUM        12)
41   (STACK_POINTER_REGNUM       27)
42   (HARD_FRAME_POINTER_REGNUM  28)
43   (PC_REGNUM                  37)
44   (FRAME_POINTER_REGNUM       38)
45   (ARG_POINTER_REGNUM         39)
46   (FIRST_PSEUDO_REGISTER      40)
47  ]
48)
49
50;; Enumeration of UNSPECs
51
52(define_c_enum "unspecv" [
53  UNSPECV_BLOCKAGE
54  UNSPECV_WRCTL
55  UNSPECV_RDCTL
56  UNSPECV_FWRX
57  UNSPECV_FWRY
58  UNSPECV_FRDXLO
59  UNSPECV_FRDXHI
60  UNSPECV_FRDY
61  UNSPECV_CUSTOM_NXX
62  UNSPECV_CUSTOM_XNXX
63  UNSPECV_LDXIO
64  UNSPECV_STXIO
65  UNSPECV_RDPRS
66  UNSPECV_FLUSHD
67  UNSPECV_FLUSHDA
68  UNSPECV_WRPIE
69  UNSPECV_ENI
70  UNSPECV_LDEX
71  UNSPECV_LDSEX
72  UNSPECV_STEX
73  UNSPECV_STSEX
74])
75
76(define_c_enum "unspec" [
77  UNSPEC_FCOS
78  UNSPEC_FSIN
79  UNSPEC_FTAN
80  UNSPEC_FATAN
81  UNSPEC_FEXP
82  UNSPEC_FLOG
83  UNSPEC_ROUND
84  UNSPEC_LOAD_GOT_REGISTER
85  UNSPEC_PIC_SYM
86  UNSPEC_PIC_CALL_SYM
87  UNSPEC_PIC_GOTOFF_SYM
88  UNSPEC_LOAD_TLS_IE
89  UNSPEC_ADD_TLS_LE
90  UNSPEC_ADD_TLS_GD
91  UNSPEC_ADD_TLS_LDM
92  UNSPEC_ADD_TLS_LDO
93  UNSPEC_EH_RETURN
94  UNSPEC_SYNC
95])
96
97
98;;  Instruction scheduler
99
100; No schedule info is currently available, using an assumption that no
101; instruction can use the results of the previous instruction without
102; incuring a stall.
103
104; length of an instruction (in bytes)
105(define_attr "length" ""
106  (if_then_else (match_test "nios2_cdx_narrow_form_p (insn)")
107    (const_int 2)
108    (const_int 4)))
109
110(define_attr "type"
111  "unknown,complex,control,alu,cond_alu,st,ld,stwm,ldwm,push,pop,mul,div,\
112   custom,add,sub,mov,and,or,xor,neg,not,sll,srl,sra,rol,ror,nop"
113  (const_string "complex"))
114
115(define_asm_attributes
116 [(set_attr "length" "4")
117  (set_attr "type" "complex")])
118
119(define_automaton "nios2")
120(automata_option "v")
121;(automata_option "no-minimization")
122(automata_option "ndfa")
123
124; The nios2 pipeline is fairly straightforward for the fast model.
125; Every alu operation is pipelined so that an instruction can
126; be issued every cycle.  However, there are still potential
127; stalls which this description tries to deal with.
128
129(define_cpu_unit "cpu" "nios2")
130
131(define_insn_reservation "complex" 1
132  (eq_attr "type" "complex")
133  "cpu")
134
135(define_insn_reservation "control" 1
136  (eq_attr "type" "control,pop")
137  "cpu")
138
139(define_insn_reservation "alu" 1
140  (eq_attr "type" "alu,add,sub,mov,and,or,xor,neg,not")
141  "cpu")
142
143(define_insn_reservation "cond_alu" 1
144  (eq_attr "type" "cond_alu")
145  "cpu")
146
147(define_insn_reservation "st" 1
148  (eq_attr "type" "st,stwm,push")
149  "cpu")
150
151(define_insn_reservation "custom" 1
152  (eq_attr "type" "custom")
153  "cpu")
154
155; shifts, muls and lds have three cycle latency
156(define_insn_reservation "ld" 3
157  (eq_attr "type" "ld,ldwm")
158  "cpu")
159
160(define_insn_reservation "shift" 3
161  (eq_attr "type" "sll,srl,sra,rol,ror")
162  "cpu")
163
164(define_insn_reservation "mul" 3
165  (eq_attr "type" "mul")
166  "cpu")
167
168(define_insn_reservation "div" 1
169  (eq_attr "type" "div")
170  "cpu")
171
172(include "predicates.md")
173(include "constraints.md")
174
175
176;; Move instructions
177
178(define_mode_iterator M [QI HI SI])
179
180(define_expand "mov<mode>"
181  [(set (match_operand:M 0 "nonimmediate_operand" "")
182        (match_operand:M 1 "general_operand" ""))]
183  ""
184{
185  if (nios2_emit_move_sequence (operands, <MODE>mode))
186    DONE;
187})
188
189(define_insn "*high"
190  [(set (match_operand:SI 0 "register_operand" "=r")
191        (high:SI (match_operand:SI 1 "immediate_operand" "i")))]
192  ""
193  "movhi\\t%0, %H1"
194  [(set_attr "type" "alu")])
195
196(define_insn "*lo_sum"
197  [(set (match_operand:SI 0 "register_operand" "=r")
198        (lo_sum:SI (match_operand:SI 1 "register_operand"  "r")
199                   (match_operand:SI 2 "immediate_operand" "i")))]
200  ""
201  "addi\\t%0, %1, %L2"
202  [(set_attr "type" "alu")])
203
204(define_insn_and_split "movqi_internal"
205  [(set (match_operand:QI 0 "nonimmediate_operand" "=m, r,r")
206        (match_operand:QI 1 "general_operand"       "rM,m,rI"))]
207  "(register_operand (operands[0], QImode)
208    || reg_or_0_operand (operands[1], QImode))"
209  {
210    switch (which_alternative)
211      {
212      case 0:
213	if (get_attr_length (insn) != 2)
214	  return "stb%o0\\t%z1, %0";
215	else if (const_0_operand (operands[1], QImode))
216	  return "stbz.n\\t%z1, %0";
217	else
218	  return "stb.n\\t%z1, %0";
219      case 1:
220	return "ldbu%o1%.\\t%0, %1";
221      case 2:
222	return "mov%i1%.\\t%0, %z1";
223      default:
224	gcc_unreachable ();
225      }
226  }
227  "(nios2_large_constant_memory_operand_p (operands[0])
228   || nios2_large_constant_memory_operand_p (operands[1]))"
229  [(set (match_dup 0) (match_dup 1))]
230  {
231    if (nios2_large_constant_memory_operand_p (operands[0]))
232      operands[0] = nios2_split_large_constant_memory_operand (operands[0]);
233    else
234      operands[1] = nios2_split_large_constant_memory_operand (operands[1]);
235  }
236  [(set_attr "type" "st,ld,mov")])
237
238(define_insn_and_split "movhi_internal"
239  [(set (match_operand:HI 0 "nonimmediate_operand" "=m, r,r")
240        (match_operand:HI 1 "general_operand"       "rM,m,rI"))]
241  "(register_operand (operands[0], HImode)
242    || reg_or_0_operand (operands[1], HImode))"
243  {
244    switch (which_alternative)
245      {
246      case 0:
247        return "sth%o0%.\\t%z1, %0";
248      case 1:
249        return "ldhu%o1%.\\t%0, %1";
250      case 2:
251        return "mov%i1%.\\t%0, %z1";
252      default:
253	gcc_unreachable ();
254      }
255  }
256  "(nios2_large_constant_memory_operand_p (operands[0])
257   || nios2_large_constant_memory_operand_p (operands[1]))"
258  [(set (match_dup 0) (match_dup 1))]
259  {
260    if (nios2_large_constant_memory_operand_p (operands[0]))
261      operands[0] = nios2_split_large_constant_memory_operand (operands[0]);
262    else
263      operands[1] = nios2_split_large_constant_memory_operand (operands[1]);
264  }
265  [(set_attr "type" "st,ld,mov")])
266
267(define_insn_and_split "movsi_internal"
268  [(set (match_operand:SI 0 "nonimmediate_operand" "=m, r,r,   r")
269        (match_operand:SI 1 "general_operand"       "rM,m,rIJK,S"))]
270  "(register_operand (operands[0], SImode)
271    || reg_or_0_operand (operands[1], SImode))"
272  {
273    switch (which_alternative)
274      {
275      case 0:
276	if (get_attr_length (insn) != 2)
277	  return "stw%o0\\t%z1, %0";
278	else if (stack_memory_operand (operands[0], SImode))
279	  return "stwsp.n\\t%z1, %0";
280	else if (const_0_operand (operands[1], SImode))
281	  return "stwz.n\\t%z1, %0";
282	else
283	  return "stw.n\\t%z1, %0";
284      case 1:
285	if (get_attr_length (insn) != 2)
286	  return "ldw%o1\\t%0, %1";
287	else if (stack_memory_operand (operands[1], SImode))
288	  return "ldwsp.n\\t%0, %1";
289	else
290	  return "ldw.n\\t%0, %1";
291      case 2:
292	return "mov%i1%.\\t%0, %z1";
293      case 3:
294	return "addi\\t%0, gp, %%gprel(%1)";
295      default:
296	gcc_unreachable ();
297      }
298  }
299  "(nios2_large_constant_memory_operand_p (operands[0])
300    || nios2_large_constant_memory_operand_p (operands[1])
301    || (nios2_large_constant_p (operands[1])
302        && !(CONST_INT_P (operands[1])
303	     && (SMALL_INT_UNSIGNED (INTVAL (operands[1]))
304	     	 || UPPER16_INT (INTVAL (operands[1]))))))"
305  [(set (match_dup 0) (match_dup 1))]
306  {
307    if (nios2_large_constant_memory_operand_p (operands[0]))
308      operands[0] = nios2_split_large_constant_memory_operand (operands[0]);
309    else if (nios2_large_constant_memory_operand_p (operands[1]))
310      operands[1] = nios2_split_large_constant_memory_operand (operands[1]);
311    else
312      operands[1] = nios2_split_large_constant (operands[1], operands[0]);
313  }
314  [(set_attr "type" "st,ld,mov,alu")])
315
316(define_mode_iterator BH [QI HI])
317(define_mode_iterator BHW [QI HI SI])
318(define_mode_attr bh [(QI "b") (HI "h")])
319(define_mode_attr bhw [(QI "b") (HI "h") (SI "w")])
320(define_mode_attr bhw_uns [(QI "bu") (HI "hu") (SI "w")])
321
322(define_insn_and_split "ld<bhw_uns>io"
323  [(set (match_operand:BHW 0 "register_operand" "=r")
324        (unspec_volatile:BHW
325          [(match_operand:BHW 1 "ldstio_memory_operand" "w")] UNSPECV_LDXIO))]
326  ""
327  "ld<bhw_uns>io\\t%0, %1"
328  "nios2_large_constant_memory_operand_p (operands[1])"
329  [(set (match_dup 0)
330        (unspec_volatile:BHW [(match_dup 1)] UNSPECV_LDXIO))]
331  {
332    operands[1] = nios2_split_large_constant_memory_operand (operands[1]);
333  }
334  [(set_attr "type" "ld")])
335
336(define_expand "ld<bh>io"
337  [(set (match_operand:BH 0 "register_operand" "=r")
338        (match_operand:BH 1 "ldstio_memory_operand" "w"))]
339  ""
340{
341  rtx tmp = gen_reg_rtx (SImode);
342  emit_insn (gen_ld<bh>io_signed (tmp, operands[1]));
343  emit_insn (gen_mov<mode> (operands[0], gen_lowpart (<MODE>mode, tmp)));
344  DONE;
345})
346
347(define_insn_and_split "ld<bh>io_signed"
348  [(set (match_operand:SI 0 "register_operand" "=r")
349        (sign_extend:SI
350          (unspec_volatile:BH
351            [(match_operand:BH 1 "ldstio_memory_operand" "w")] UNSPECV_LDXIO)))]
352  ""
353  "ld<bh>io\\t%0, %1"
354  "nios2_large_constant_memory_operand_p (operands[1])"
355  [(set (match_dup 0)
356        (sign_extend:SI (unspec_volatile:BH [(match_dup 1)] UNSPECV_LDXIO)))]
357  {
358    operands[1] = nios2_split_large_constant_memory_operand (operands[1]);
359  }
360  [(set_attr "type" "ld")])
361
362(define_insn_and_split "st<bhw>io"
363  [(set (match_operand:BHW 0 "ldstio_memory_operand" "=w")
364        (unspec_volatile:BHW
365          [(match_operand:BHW 1 "reg_or_0_operand" "rM")] UNSPECV_STXIO))]
366  ""
367  "st<bhw>io\\t%z1, %0"
368  "nios2_large_constant_memory_operand_p (operands[0])"
369  [(set (match_dup 0) (unspec_volatile:BHW [(match_dup 1)] UNSPECV_STXIO))]
370  {
371    operands[0] = nios2_split_large_constant_memory_operand (operands[0]);
372  }
373  [(set_attr "type" "st")])
374
375
376;; QI to [HI, SI] extension patterns are collected together
377(define_mode_iterator QX [HI SI])
378
379;; Zero extension patterns
380(define_insn_and_split "zero_extendhisi2"
381  [(set (match_operand:SI 0 "register_operand" "=r,r")
382        (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
383  ""
384  "@
385    andi%.\\t%0, %1, 0xffff
386    ldhu%o1%.\\t%0, %1"
387  "nios2_large_constant_memory_operand_p (operands[1])"
388  [(set (match_dup 0) (zero_extend:SI (match_dup 1)))]
389  {
390    operands[1] = nios2_split_large_constant_memory_operand (operands[1]);
391  }
392  [(set_attr "type"     "and,ld")])
393
394(define_insn_and_split "zero_extendqi<mode>2"
395  [(set (match_operand:QX 0 "register_operand" "=r,r")
396        (zero_extend:QX (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
397  ""
398  "@
399    andi%.\\t%0, %1, 0xff
400    ldbu%o1%.\\t%0, %1"
401  "nios2_large_constant_memory_operand_p (operands[1])"
402  [(set (match_dup 0) (zero_extend:QX (match_dup 1)))]
403  {
404    operands[1] = nios2_split_large_constant_memory_operand (operands[1]);
405  }
406  [(set_attr "type"     "and,ld")])
407
408;; Sign extension patterns
409
410(define_insn_and_split "extendhisi2"
411  [(set (match_operand:SI 0 "register_operand"                     "=r,r")
412        (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand"  "r,m")))]
413  ""
414  "@
415   #
416   ldh%o1%.\\t%0, %1"
417  "nios2_large_constant_memory_operand_p (operands[1])"
418  [(set (match_dup 0) (sign_extend:SI (match_dup 1)))]
419  {
420    operands[1] = nios2_split_large_constant_memory_operand (operands[1]);
421  }
422  [(set_attr "type" "alu,ld")])
423
424(define_insn_and_split "extendqi<mode>2"
425  [(set (match_operand:QX 0 "register_operand"                     "=r,r")
426        (sign_extend:QX (match_operand:QI 1 "nonimmediate_operand"  "r,m")))]
427  ""
428  "@
429   #
430   ldb%o1%.\\t%0, %1"
431  "nios2_large_constant_memory_operand_p (operands[1])"
432  [(set (match_dup 0) (sign_extend:QX (match_dup 1)))]
433  {
434    operands[1] = nios2_split_large_constant_memory_operand (operands[1]);
435  }
436  [(set_attr "type" "alu,ld")])
437
438;; Split patterns for register alternative cases.
439(define_split
440  [(set (match_operand:SI 0 "register_operand" "")
441        (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
442  "reload_completed"
443  [(set (match_dup 0)
444        (and:SI (match_dup 1) (const_int 65535)))
445   (set (match_dup 0)
446        (xor:SI (match_dup 0) (const_int 32768)))
447   (set (match_dup 0)
448        (plus:SI (match_dup 0) (const_int -32768)))]
449  "operands[1] = gen_lowpart (SImode, operands[1]);")
450
451(define_split
452  [(set (match_operand:QX 0 "register_operand" "")
453        (sign_extend:QX (match_operand:QI 1 "register_operand" "")))]
454  "reload_completed"
455  [(set (match_dup 0)
456        (and:SI (match_dup 1) (const_int 255)))
457   (set (match_dup 0)
458        (xor:SI (match_dup 0) (const_int 128)))
459   (set (match_dup 0)
460        (plus:SI (match_dup 0) (const_int -128)))]
461  "operands[0] = gen_lowpart (SImode, operands[0]);
462   operands[1] = gen_lowpart (SImode, operands[1]);")
463
464
465;; Arithmetic Operations
466
467(define_insn "addsi3"
468  [(set (match_operand:SI 0 "register_operand"            "=r")
469        (plus:SI (match_operand:SI 1 "register_operand"   "%r")
470                 (match_operand:SI 2 "add_regimm_operand" "rIT")))]
471  ""
472{
473  return nios2_add_insn_asm (insn, operands);
474}
475  [(set_attr "type" "add")])
476
477(define_insn "subsi3"
478  [(set (match_operand:SI 0 "register_operand"           "=r")
479        (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rM")
480                  (match_operand:SI 2 "register_operand" "r")))]
481  ""
482  "sub%.\\t%0, %z1, %2"
483  [(set_attr "type" "sub")])
484
485(define_insn "mulsi3"
486  [(set (match_operand:SI 0 "register_operand"          "=r")
487        (mult:SI (match_operand:SI 1 "register_operand" "%r")
488                 (match_operand:SI 2 "arith_operand"    "rI")))]
489  "TARGET_HAS_MUL"
490  "mul%i2\\t%0, %1, %z2"
491  [(set_attr "type" "mul")])
492
493(define_expand "divsi3"
494  [(set (match_operand:SI 0 "register_operand"          "=r")
495        (div:SI (match_operand:SI 1 "register_operand"   "r")
496                (match_operand:SI 2 "register_operand"   "r")))]
497  ""
498{
499  if (!TARGET_HAS_DIV)
500    {
501      if (TARGET_FAST_SW_DIV)
502        {
503          nios2_emit_expensive_div (operands, SImode);
504          DONE;
505        }
506      else
507        FAIL;
508    }
509})
510
511(define_insn "divsi3_insn"
512  [(set (match_operand:SI 0 "register_operand"            "=r")
513        (div:SI (match_operand:SI 1 "register_operand"     "r")
514                (match_operand:SI 2 "register_operand"     "r")))]
515  "TARGET_HAS_DIV"
516  "div\\t%0, %1, %2"
517  [(set_attr "type" "div")])
518
519(define_insn "udivsi3"
520  [(set (match_operand:SI 0 "register_operand"            "=r")
521        (udiv:SI (match_operand:SI 1 "register_operand"    "r")
522                 (match_operand:SI 2 "register_operand"    "r")))]
523  "TARGET_HAS_DIV"
524  "divu\\t%0, %1, %2"
525  [(set_attr "type" "div")])
526
527(define_code_iterator EXTEND [sign_extend zero_extend])
528(define_code_attr us [(sign_extend "s") (zero_extend "u")])
529(define_code_attr mul [(sign_extend "mul") (zero_extend "umul")])
530
531(define_insn "<us>mulsi3_highpart"
532  [(set (match_operand:SI 0 "register_operand"                       "=r")
533        (truncate:SI
534         (lshiftrt:DI
535          (mult:DI (EXTEND:DI (match_operand:SI 1 "register_operand"  "r"))
536                   (EXTEND:DI (match_operand:SI 2 "register_operand"  "r")))
537          (const_int 32))))]
538  "TARGET_HAS_MULX"
539  "mulx<us><us>\\t%0, %1, %2"
540  [(set_attr "type" "mul")])
541
542(define_expand "<mul>sidi3"
543  [(set (match_operand:DI 0 "register_operand" "")
544	(mult:DI (EXTEND:DI (match_operand:SI 1 "register_operand" ""))
545		 (EXTEND:DI (match_operand:SI 2 "register_operand" ""))))]
546  "TARGET_HAS_MULX"
547{
548  rtx hi = gen_reg_rtx (SImode);
549  rtx lo = gen_reg_rtx (SImode);
550
551  emit_insn (gen_<us>mulsi3_highpart (hi, operands[1], operands[2]));
552  emit_insn (gen_mulsi3 (lo, operands[1], operands[2]));
553  emit_move_insn (gen_lowpart (SImode, operands[0]), lo);
554  emit_move_insn (gen_highpart (SImode, operands[0]), hi);
555  DONE;
556})
557
558
559;;  Negate and ones complement
560
561(define_insn "negsi2"
562  [(set (match_operand:SI 0 "register_operand"        "=r")
563        (neg:SI (match_operand:SI 1 "register_operand" "r")))]
564  ""
565{
566  if (get_attr_length (insn) == 2)
567    return "neg.n\\t%0, %1";
568  else
569    return "sub\\t%0, zero, %1";
570}
571  [(set_attr "type" "neg")])
572
573(define_insn "one_cmplsi2"
574  [(set (match_operand:SI 0 "register_operand"        "=r")
575        (not:SI (match_operand:SI 1 "register_operand" "r")))]
576  ""
577{
578  if (get_attr_length (insn) == 2)
579    return "not.n\\t%0, %1";
580  else
581    return "nor\\t%0, zero, %1";
582}
583  [(set_attr "type" "not")])
584
585
586;;  Integer logical Operations
587
588(define_insn "andsi3"
589  [(set (match_operand:SI 0 "register_operand"          "=r")
590        (and:SI (match_operand:SI 1 "register_operand"  "%r")
591                (match_operand:SI 2 "and_operand"     "rJKP")))]
592  ""
593  "and%x2%.\\t%0, %1, %y2"
594  [(set_attr "type" "and")])
595
596(define_code_iterator LOGICAL [ior xor])
597(define_code_attr logical_asm [(ior "or") (xor "xor")])
598
599(define_insn "<code>si3"
600  [(set (match_operand:SI 0 "register_operand"             "=r")
601        (LOGICAL:SI (match_operand:SI 1 "register_operand" "%r")
602                    (match_operand:SI 2 "logical_operand" "rJK")))]
603  ""
604  "<logical_asm>%x2%.\\t%0, %1, %y2"
605  [(set_attr "type" "<logical_asm>")])
606
607(define_insn "*norsi3"
608  [(set (match_operand:SI 0 "register_operand"                 "=r")
609        (and:SI (not:SI (match_operand:SI 1 "register_operand" "%r"))
610                (not:SI (match_operand:SI 2 "register_operand"  "r"))))]
611  ""
612  "nor\\t%0, %1, %2"
613  [(set_attr "type" "alu")])
614
615
616;;  Shift instructions
617
618(define_code_iterator SHIFT  [ashift ashiftrt lshiftrt rotate])
619(define_code_attr shift_op   [(ashift "ashl") (ashiftrt "ashr")
620                              (lshiftrt "lshr") (rotate "rotl")])
621(define_code_attr shift_asm  [(ashift "sll") (ashiftrt "sra")
622                              (lshiftrt "srl") (rotate "rol")])
623
624(define_insn "<shift_op>si3"
625  [(set (match_operand:SI 0 "register_operand"          "=r")
626        (SHIFT:SI (match_operand:SI 1 "register_operand" "r")
627                  (match_operand:SI 2 "shift_operand"    "rL")))]
628  ""
629  "<shift_asm>%i2%.\\t%0, %1, %z2"
630  [(set_attr "type" "<shift_asm>")])
631
632(define_insn "rotrsi3"
633  [(set (match_operand:SI 0 "register_operand"             "=r")
634        (rotatert:SI (match_operand:SI 1 "register_operand" "r")
635                     (match_operand:SI 2 "register_operand" "r")))]
636  ""
637  "ror\\t%0, %1, %2"
638  [(set_attr "type" "ror")])
639
640;; Nios II R2 Bit Manipulation Extension (BMX), provides
641;; bit merge/insertion/extraction instructions.
642
643(define_insn "*merge"
644  [(set (zero_extract:SI (match_operand:SI 0 "register_operand"   "+r")
645			 (match_operand:SI 1 "const_shift_operand" "L")
646			 (match_operand:SI 2 "const_shift_operand" "L"))
647        (zero_extract:SI (match_operand:SI 3 "register_operand"    "r")
648                         (match_dup 1) (match_dup 2)))]
649  "TARGET_HAS_BMX"
650{
651  operands[4] = GEN_INT (INTVAL (operands[1]) + INTVAL (operands[2]) - 1);
652  return "merge\\t%0, %3, %4, %2";
653}
654  [(set_attr "type" "alu")])
655
656(define_insn "extzv"
657  [(set (match_operand:SI 0 "register_operand" "=r")
658        (zero_extract:SI (match_operand:SI 1 "register_operand"    "r")
659                         (match_operand:SI 2 "const_shift_operand" "L")
660                         (match_operand:SI 3 "const_shift_operand" "L")))]
661  "TARGET_HAS_BMX"
662{
663  operands[4] = GEN_INT (INTVAL (operands[2]) + INTVAL (operands[3]) - 1);
664  return "extract\\t%0, %1, %4, %3";
665}
666  [(set_attr "type" "alu")])
667
668(define_insn "insv"
669  [(set (zero_extract:SI (match_operand:SI 0 "register_operand"   "+r")
670			 (match_operand:SI 1 "const_shift_operand" "L")
671			 (match_operand:SI 2 "const_shift_operand" "L"))
672	(match_operand:SI 3 "reg_or_0_operand" "rM"))]
673  "TARGET_HAS_BMX"
674{
675  operands[4] = GEN_INT (INTVAL (operands[1]) + INTVAL (operands[2]) - 1);
676  return "insert\\t%0, %z3, %4, %2";
677}
678  [(set_attr "type" "alu")])
679
680
681
682;; Floating point instructions
683
684;; Mode iterator for single/double float
685(define_mode_iterator F [SF DF])
686(define_mode_attr f [(SF "s") (DF "d")])
687
688;; Basic arithmetic instructions
689(define_code_iterator FOP3 [plus minus mult div])
690(define_code_attr fop3 [(plus "add") (minus "sub") (mult "mul") (div "div")])
691
692(define_insn "<fop3><mode>3"
693  [(set (match_operand:F 0 "register_operand"        "=r")
694        (FOP3:F (match_operand:F 1 "register_operand" "r")
695                (match_operand:F 2 "register_operand" "r")))]
696  "nios2_fpu_insn_enabled (n2fpu_f<fop3><f>)"
697  { return nios2_fpu_insn_asm (n2fpu_f<fop3><f>); }
698  [(set_attr "type" "custom")])
699
700;; Floating point min/max operations
701(define_code_iterator SMINMAX [smin smax])
702(define_code_attr minmax [(smin "min") (smax "max")])
703(define_insn "<code><mode>3"
704  [(set (match_operand:F 0 "register_operand" "=r")
705        (SMINMAX:F (match_operand:F 1 "register_operand" "r")
706                   (match_operand:F 2 "register_operand" "r")))]
707  "nios2_fpu_insn_enabled (n2fpu_f<minmax><f>)"
708  { return nios2_fpu_insn_asm (n2fpu_f<minmax><f>); }
709  [(set_attr "type" "custom")])
710
711;; These 2-operand FP operations can be collected together
712(define_code_iterator FOP2 [abs neg sqrt])
713(define_insn "<code><mode>2"
714  [(set (match_operand:F 0 "register_operand" "=r")
715        (FOP2:F (match_operand:F 1 "register_operand" "r")))]
716  "nios2_fpu_insn_enabled (n2fpu_f<code><f>)"
717  { return nios2_fpu_insn_asm (n2fpu_f<code><f>); }
718  [(set_attr "type" "custom")])
719
720;; X, Y register access instructions
721(define_insn "nios2_fwrx"
722  [(unspec_volatile [(match_operand:DF 0 "register_operand" "r")] UNSPECV_FWRX)]
723  "nios2_fpu_insn_enabled (n2fpu_fwrx)"
724  { return nios2_fpu_insn_asm (n2fpu_fwrx); }
725  [(set_attr "type" "custom")])
726
727(define_insn "nios2_fwry"
728  [(unspec_volatile [(match_operand:SF 0 "register_operand" "r")] UNSPECV_FWRY)]
729  "nios2_fpu_insn_enabled (n2fpu_fwry)"
730  { return nios2_fpu_insn_asm (n2fpu_fwry); }
731  [(set_attr "type" "custom")])
732
733;; The X, Y read insns uses an int iterator
734(define_int_iterator UNSPEC_READ_XY [UNSPECV_FRDXLO UNSPECV_FRDXHI
735                                     UNSPECV_FRDY])
736(define_int_attr read_xy [(UNSPECV_FRDXLO "frdxlo") (UNSPECV_FRDXHI "frdxhi")
737                          (UNSPECV_FRDY "frdy")])
738(define_insn "nios2_<read_xy>"
739  [(set (match_operand:SF 0 "register_operand" "=r")
740        (unspec_volatile:SF [(const_int 0)] UNSPEC_READ_XY))]
741  "nios2_fpu_insn_enabled (n2fpu_<read_xy>)"
742  { return nios2_fpu_insn_asm (n2fpu_<read_xy>); }
743  [(set_attr "type" "custom")])
744
745;; Various math functions
746(define_int_iterator MATHFUNC
747  [UNSPEC_FCOS UNSPEC_FSIN UNSPEC_FTAN UNSPEC_FATAN UNSPEC_FEXP UNSPEC_FLOG])
748(define_int_attr mathfunc [(UNSPEC_FCOS "cos") (UNSPEC_FSIN "sin")
749                           (UNSPEC_FTAN "tan") (UNSPEC_FATAN "atan")
750                           (UNSPEC_FEXP "exp") (UNSPEC_FLOG "log")])
751
752(define_insn "<mathfunc><mode>2"
753  [(set (match_operand:F 0 "register_operand" "=r")
754        (unspec:F [(match_operand:F 1 "register_operand" "r")] MATHFUNC))]
755  "nios2_fpu_insn_enabled (n2fpu_f<mathfunc><f>)"
756  { return nios2_fpu_insn_asm (n2fpu_f<mathfunc><f>); }
757  [(set_attr "type" "custom")])
758
759;; Converting between floating point and fixed point
760
761(define_code_iterator FLOAT [float unsigned_float])
762(define_code_iterator FIX [fix unsigned_fix])
763
764(define_code_attr conv_op [(float "float") (unsigned_float "floatuns")
765                           (fix "fix") (unsigned_fix "fixuns")])
766(define_code_attr i [(float "i") (unsigned_float "u")
767                     (fix "i") (unsigned_fix "u")])
768
769;; Integer to float conversions
770(define_insn "<conv_op>si<mode>2"
771  [(set (match_operand:F 0 "register_operand" "=r")
772        (FLOAT:F (match_operand:SI 1 "register_operand" "r")))]
773  "nios2_fpu_insn_enabled (n2fpu_float<i><f>)"
774  { return nios2_fpu_insn_asm (n2fpu_float<i><f>); }
775  [(set_attr "type" "custom")])
776
777;; Float to integer conversions
778(define_insn "<conv_op>_trunc<mode>si2"
779  [(set (match_operand:SI 0 "register_operand" "=r")
780        (FIX:SI (match_operand:F 1 "general_operand" "r")))]
781  "nios2_fpu_insn_enabled (n2fpu_fix<f><i>)"
782  { return nios2_fpu_insn_asm (n2fpu_fix<f><i>); }
783  [(set_attr "type" "custom")])
784
785(define_insn "lroundsfsi2"
786  [(set (match_operand:SI 0 "register_operand" "=r")
787        (unspec:SI [(match_operand:SF 1 "general_operand" "r")] UNSPEC_ROUND))]
788  "nios2_fpu_insn_enabled (n2fpu_round)"
789  { return nios2_fpu_insn_asm (n2fpu_round); }
790  [(set_attr "type" "custom")])
791
792(define_insn "extendsfdf2"
793  [(set (match_operand:DF 0 "register_operand" "=r")
794        (float_extend:DF (match_operand:SF 1 "general_operand" "r")))]
795  "nios2_fpu_insn_enabled (n2fpu_fextsd)"
796  { return nios2_fpu_insn_asm (n2fpu_fextsd); }
797  [(set_attr "type" "custom")])
798
799(define_insn "truncdfsf2"
800  [(set (match_operand:SF 0 "register_operand" "=r")
801        (float_truncate:SF (match_operand:DF 1 "general_operand" "r")))]
802  "nios2_fpu_insn_enabled (n2fpu_ftruncds)"
803  { return nios2_fpu_insn_asm (n2fpu_ftruncds); }
804  [(set_attr "type" "custom")])
805
806
807
808;; Prologue, Epilogue and Return
809
810(define_expand "prologue"
811  [(const_int 1)]
812  ""
813{
814  nios2_expand_prologue ();
815  DONE;
816})
817
818(define_expand "epilogue"
819  [(return)]
820  ""
821{
822  nios2_expand_epilogue (false);
823  DONE;
824})
825
826(define_expand "sibcall_epilogue"
827  [(return)]
828  ""
829{
830  nios2_expand_epilogue (true);
831  DONE;
832})
833
834(define_expand "return"
835  [(simple_return)]
836  "nios2_can_use_return_insn ()"
837{
838  if (nios2_expand_return ())
839    DONE;
840})
841
842(define_insn "simple_return"
843  [(simple_return)]
844  ""
845  "ret%."
846  [(set_attr "type" "control")])
847
848;; Block any insns from being moved before this point, since the
849;; profiling call to mcount can use various registers that aren't
850;; saved or used to pass arguments.
851
852(define_insn "blockage"
853  [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
854  ""
855  ""
856  [(set_attr "type" "unknown")
857   (set_attr "length" "0")])
858
859;; This is used in compiling the unwind routines.
860(define_expand "eh_return"
861  [(use (match_operand 0 "general_operand"))]
862  ""
863{
864  if (GET_MODE (operands[0]) != Pmode)
865    operands[0] = convert_to_mode (Pmode, operands[0], 0);
866  emit_insn (gen_eh_set_ra (operands[0]));
867  DONE;
868})
869
870;; Modify the return address for EH return.  We can't expand this
871;; until we know where it will be put in the stack frame.
872
873(define_insn_and_split "eh_set_ra"
874  [(unspec [(match_operand:SI 0 "register_operand" "r")] UNSPEC_EH_RETURN)
875   (clobber (match_scratch:SI 1 "=&r"))]
876  ""
877  "#"
878  "reload_completed"
879  [(const_int 0)]
880{
881  nios2_set_return_address (operands[0], operands[1]);
882  DONE;
883})
884
885
886;;  Jumps and calls
887
888; Note that the assembler fixes up any out-of-range branch instructions not
889; caught by the compiler branch shortening code.  The sequence emitted by
890; the assembler can be very inefficient, but it is correct for PIC code.
891; For non-PIC we are better off converting to an absolute JMPI.
892;
893; Direct calls and sibcalls use the CALL and JMPI instructions, respectively.
894; These instructions have an immediate operand that specifies the low 28 bits
895; of the PC, effectively allowing direct calls within a 256MB memory segment.
896; Per the Nios II Processor Reference Handbook, the linker is not required to
897; check or adjust for overflow.
898
899(define_insn "indirect_jump"
900  [(set (pc) (match_operand:SI 0 "register_operand" "c"))]
901  ""
902  "jmp%!\\t%0"
903  [(set_attr "type" "control")])
904
905(define_insn "jump"
906  [(set (pc)
907        (label_ref (match_operand 0 "" "")))]
908  ""
909  {
910    if (get_attr_length (insn) == 2)
911      return "br.n\\t%0";
912    else if (get_attr_length (insn) == 4)
913      return "br\\t%0";
914    else
915      return "jmpi\\t%0";
916  }
917  [(set_attr "type" "control")
918   (set (attr "length")
919        (if_then_else
920	    (and (match_test "TARGET_HAS_CDX")
921	         (and (ge (minus (match_dup 0) (pc)) (const_int -1022))
922	              (le (minus (match_dup 0) (pc)) (const_int 1022))))
923	    (const_int 2)
924	    (if_then_else
925	        (ior (match_test "flag_pic")
926	             (and (ge (minus (match_dup 0) (pc)) (const_int -32764))
927	                  (le (minus (match_dup 0) (pc)) (const_int 32764))))
928	        (const_int 4)
929	        (const_int 8))))])
930
931(define_expand "call"
932  [(parallel [(call (match_operand 0 "" "")
933                    (match_operand 1 "" ""))
934              (clobber (reg:SI RA_REGNO))])]
935  ""
936  "nios2_adjust_call_address (&operands[0], NULL_RTX);")
937
938(define_expand "call_value"
939  [(parallel [(set (match_operand 0 "" "")
940                   (call (match_operand 1 "" "")
941                         (match_operand 2 "" "")))
942              (clobber (reg:SI RA_REGNO))])]
943  ""
944  "nios2_adjust_call_address (&operands[1], NULL_RTX);")
945
946(define_insn "*call"
947  [(call (mem:QI (match_operand:SI 0 "call_operand" "i,r"))
948         (match_operand 1 "" ""))
949   (clobber (reg:SI RA_REGNO))]
950  ""
951  "@
952   call\\t%0
953   callr%.\\t%0"
954  [(set_attr "type" "control")])
955
956(define_insn "*call_value"
957  [(set (match_operand 0 "" "")
958        (call (mem:QI (match_operand:SI 1 "call_operand" "i,r"))
959              (match_operand 2 "" "")))
960   (clobber (reg:SI RA_REGNO))]
961  ""
962  "@
963   call\\t%1
964   callr%.\\t%1"
965  [(set_attr "type" "control")])
966
967(define_expand "sibcall"
968  [(parallel [(call (match_operand 0 "" "")
969                    (match_operand 1 "" ""))
970              (return)])]
971  ""
972  "nios2_adjust_call_address (&operands[0], NULL_RTX);")
973
974(define_expand "sibcall_value"
975  [(parallel [(set (match_operand 0 "" "")
976                   (call (match_operand 1 "" "")
977                         (match_operand 2 "" "")))
978              (return)])]
979  ""
980  "nios2_adjust_call_address (&operands[1], NULL_RTX);")
981
982(define_insn "sibcall_internal"
983 [(call (mem:QI (match_operand:SI 0 "call_operand" "i,j"))
984        (match_operand 1 "" ""))
985  (return)]
986  ""
987  "@
988   jmpi\\t%0
989   jmp%!\\t%0"
990  [(set_attr "type" "control")])
991
992(define_insn "sibcall_value_internal"
993 [(set (match_operand 0 "register_operand" "")
994       (call (mem:QI (match_operand:SI 1 "call_operand" "i,j"))
995             (match_operand 2 "" "")))
996  (return)]
997  ""
998  "@
999   jmpi\\t%1
1000   jmp%!\\t%1"
1001  [(set_attr "type" "control")])
1002
1003(define_expand "tablejump"
1004  [(parallel [(set (pc) (match_operand 0 "register_operand" "r"))
1005              (use (label_ref (match_operand 1 "" "")))])]
1006  ""
1007{
1008  if (flag_pic)
1009    {
1010      /* Hopefully, CSE will eliminate this copy.  */
1011      rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
1012      rtx reg2 = gen_reg_rtx (SImode);
1013
1014      emit_insn (gen_addsi3 (reg2, operands[0], reg1));
1015      operands[0] = reg2;
1016    }
1017})
1018
1019(define_insn "*tablejump"
1020  [(set (pc)
1021        (match_operand:SI 0 "register_operand" "c"))
1022   (use (label_ref (match_operand 1 "" "")))]
1023  ""
1024  "jmp%!\\t%0"
1025  [(set_attr "type" "control")])
1026
1027
1028;; cstore, cbranch patterns
1029
1030(define_mode_iterator CM [SI SF DF])
1031
1032(define_expand "cstore<mode>4"
1033  [(set (match_operand:SI 0 "register_operand" "=r")
1034        (match_operator:SI 1 "expandable_comparison_operator"
1035	  [(match_operand:CM 2 "register_operand")
1036	   (match_operand:CM 3 "nonmemory_operand")]))]
1037  ""
1038{
1039  if (!nios2_validate_compare (<MODE>mode, &operands[1], &operands[2],
1040                               &operands[3]))
1041    FAIL;
1042})
1043
1044(define_expand "cbranch<mode>4"
1045  [(set (pc)
1046     (if_then_else
1047       (match_operator 0 "expandable_comparison_operator"
1048         [(match_operand:CM 1 "register_operand")
1049          (match_operand:CM 2 "nonmemory_operand")])
1050       (label_ref (match_operand 3 ""))
1051       (pc)))]
1052  ""
1053{
1054  if (!nios2_validate_compare (<MODE>mode, &operands[0], &operands[1],
1055                               &operands[2]))
1056    FAIL;
1057  if (GET_MODE_CLASS (<MODE>mode) == MODE_FLOAT
1058      || !reg_or_0_operand (operands[2], <MODE>mode))
1059    {
1060      rtx condreg = gen_reg_rtx (SImode);
1061      emit_insn (gen_cstore<mode>4
1062                  (condreg, operands[0], operands[1], operands[2]));
1063      operands[1] = condreg;
1064      operands[2] = const0_rtx;
1065      operands[0] = gen_rtx_fmt_ee (NE, VOIDmode, condreg, const0_rtx);
1066    }
1067})
1068
1069(define_insn "nios2_cbranch"
1070  [(set (pc)
1071     (if_then_else
1072       (match_operator 0 "ordered_comparison_operator"
1073         [(match_operand:SI 1 "reg_or_0_operand" "rM")
1074          (match_operand:SI 2 "reg_or_0_operand" "rM")])
1075       (label_ref (match_operand 3 "" ""))
1076       (pc)))]
1077  ""
1078{
1079  if (get_attr_length (insn) == 2)
1080    return "b%0z.n\t%z1, %l3";
1081  else if (get_attr_length (insn) == 4)
1082    return "b%0\t%z1, %z2, %l3";
1083  else if (get_attr_length (insn) == 6)
1084    return "b%R0z.n\t%z1, .+6;jmpi\t%l3";
1085  else
1086    return "b%R0\t%z1, %z2, .+8;jmpi\t%l3";
1087}
1088  [(set_attr "type" "control")
1089   (set (attr "length")
1090        (cond
1091         [(and (match_test "nios2_cdx_narrow_form_p (insn)")
1092               (ge (minus (match_dup 3) (pc)) (const_int -126))
1093               (le (minus (match_dup 3) (pc)) (const_int 126)))
1094          (const_int 2)
1095          (ior (match_test "flag_pic")
1096               (and (ge (minus (match_dup 3) (pc)) (const_int -32764))
1097                    (le (minus (match_dup 3) (pc)) (const_int 32764))))
1098          (const_int 4)
1099          (match_test "nios2_cdx_narrow_form_p (insn)")
1100          (const_int 6)]
1101         (const_int 8)))])
1102
1103;; Floating point comparisons
1104(define_code_iterator FCMP [eq ne gt ge le lt])
1105(define_insn "nios2_s<code><mode>"
1106  [(set (match_operand:SI 0 "register_operand"        "=r")
1107        (FCMP:SI (match_operand:F 1 "register_operand" "r")
1108                 (match_operand:F 2 "register_operand" "r")))]
1109  "nios2_fpu_insn_enabled (n2fpu_fcmp<code><f>)"
1110  { return nios2_fpu_insn_asm (n2fpu_fcmp<code><f>); }
1111  [(set_attr "type" "custom")])
1112
1113;; Integer comparisons
1114
1115(define_code_iterator EQNE [eq ne])
1116(define_insn "nios2_cmp<code>"
1117  [(set (match_operand:SI 0 "register_operand"           "=r")
1118        (EQNE:SI (match_operand:SI 1 "register_operand"  "%r")
1119                 (match_operand:SI 2 "arith_operand"     "rI")))]
1120  ""
1121  "cmp<code>%i2\\t%0, %1, %z2"
1122  [(set_attr "type" "alu")])
1123
1124(define_code_iterator SCMP [ge lt])
1125(define_insn "nios2_cmp<code>"
1126  [(set (match_operand:SI 0 "register_operand"           "=r")
1127        (SCMP:SI (match_operand:SI 1 "reg_or_0_operand"  "rM")
1128                 (match_operand:SI 2 "arith_operand"     "rI")))]
1129  ""
1130  "cmp<code>%i2\\t%0, %z1, %z2"
1131  [(set_attr "type" "alu")])
1132
1133(define_code_iterator UCMP [geu ltu])
1134(define_insn "nios2_cmp<code>"
1135  [(set (match_operand:SI 0 "register_operand"           "=r")
1136        (UCMP:SI (match_operand:SI 1 "reg_or_0_operand"  "rM")
1137                 (match_operand:SI 2 "uns_arith_operand" "rJ")))]
1138  ""
1139  "cmp<code>%u2\\t%0, %z1, %z2"
1140  [(set_attr "type" "alu")])
1141
1142
1143
1144;; Custom instruction patterns.  The operands are intentionally
1145;; mode-less, to serve as generic carriers of all Altera defined
1146;; built-in instruction/function types.
1147
1148(define_insn "custom_nxx"
1149  [(unspec_volatile [(match_operand 0 "custom_insn_opcode" "N")
1150                     (match_operand 1 "reg_or_0_operand"  "rM")
1151                     (match_operand 2 "reg_or_0_operand"  "rM")]
1152    UNSPECV_CUSTOM_NXX)]
1153  ""
1154  "custom\\t%0, zero, %z1, %z2"
1155  [(set_attr "type" "custom")])
1156
1157(define_insn "custom_xnxx"
1158  [(set (match_operand 0 "register_operand"   "=r")
1159        (unspec_volatile [(match_operand 1 "custom_insn_opcode" "N")
1160                          (match_operand 2 "reg_or_0_operand"  "rM")
1161                          (match_operand 3 "reg_or_0_operand"  "rM")]
1162	 UNSPECV_CUSTOM_XNXX))]
1163  ""
1164  "custom\\t%1, %0, %z2, %z3"
1165  [(set_attr "type" "custom")])
1166
1167
1168;;  Misc. patterns
1169
1170(define_insn "nop"
1171  [(const_int 0)]
1172  ""
1173  "nop%."
1174  [(set_attr "type" "nop")])
1175
1176;; Connect 'sync' to 'memory_barrier' standard expand name
1177(define_expand "memory_barrier"
1178  [(const_int 0)]
1179  ""
1180{
1181  emit_insn (gen_sync ());
1182  DONE;
1183})
1184
1185;; For the nios2 __builtin_sync built-in function
1186(define_expand "sync"
1187  [(set (match_dup 0)
1188	(unspec:BLK [(match_dup 0)] UNSPEC_SYNC))]
1189  ""
1190{
1191  operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
1192  MEM_VOLATILE_P (operands[0]) = 1;
1193})
1194
1195(define_insn "*sync_insn"
1196  [(set (match_operand:BLK 0 "" "")
1197	(unspec:BLK [(match_dup 0)] UNSPEC_SYNC))]
1198  ""
1199  "sync"
1200  [(set_attr "type" "control")])
1201
1202(define_insn "rdctl"
1203  [(set (match_operand:SI 0 "register_operand" "=r")
1204        (unspec_volatile:SI [(match_operand:SI 1 "rdwrctl_operand" "O")]
1205	 UNSPECV_RDCTL))]
1206  ""
1207  "rdctl\\t%0, ctl%1"
1208  [(set_attr "type" "control")])
1209
1210(define_insn "wrctl"
1211  [(unspec_volatile:SI [(match_operand:SI 0 "rdwrctl_operand"  "O")
1212                        (match_operand:SI 1 "reg_or_0_operand" "rM")]
1213    UNSPECV_WRCTL)]
1214  ""
1215  "wrctl\\tctl%0, %z1"
1216  [(set_attr "type" "control")])
1217
1218(define_insn "rdprs"
1219  [(set (match_operand:SI 0 "register_operand" "=r")
1220        (unspec_volatile:SI [(match_operand:SI 1 "rdwrctl_operand" "O")
1221                             (match_operand:SI 2 "arith_operand"   "U")]
1222         UNSPECV_RDPRS))]
1223  ""
1224  "rdprs\\t%0, %1, %2"
1225  [(set_attr "type" "control")])
1226
1227;; Cache Instructions
1228
1229(define_insn "flushd"
1230  [(unspec_volatile:SI [(match_operand:SI 0 "ldstio_memory_operand" "w")]
1231  		        UNSPECV_FLUSHD)]
1232  ""
1233  "flushd\\t%0"
1234  [(set_attr "type" "control")])
1235
1236(define_insn "flushda"
1237  [(unspec_volatile:SI [(match_operand:SI 0 "ldstio_memory_operand" "w")]
1238  		        UNSPECV_FLUSHDA)]
1239  ""
1240  "flushda\\t%0"
1241  [(set_attr "type" "control")])
1242
1243;; R2 Instructions
1244
1245(define_insn "wrpie"
1246  [(set (match_operand:SI 0 "register_operand" "=r")
1247        (unspec_volatile:SI [(match_operand:SI 1 "register_operand" "r")]
1248		 	     UNSPECV_WRPIE))]
1249  "TARGET_ARCH_R2"
1250  "wrpie\\t%0, %1"
1251  [(set_attr "type" "control")])
1252
1253(define_insn "eni"
1254  [(unspec:VOID [(match_operand 0 "const_int_operand" "i")]
1255  		 UNSPECV_ENI)]
1256  "TARGET_ARCH_R2"
1257  "eni\\t%0"
1258  [(set_attr "type" "control")])
1259
1260;; Trap patterns
1261(define_insn "trap"
1262  [(trap_if (const_int 1) (const_int 3))]
1263  ""
1264  "trap%.\\t3"
1265  [(set_attr "type" "control")])
1266
1267(define_insn "ctrapsi4"
1268  [(trap_if (match_operator 0 "ordered_comparison_operator"
1269              [(match_operand:SI 1 "reg_or_0_operand" "rM")
1270               (match_operand:SI 2 "reg_or_0_operand" "rM")])
1271            (match_operand 3 "const_int_operand" "i"))]
1272  ""
1273{
1274  if (get_attr_length (insn) == 6)
1275    return "b%R0\\t%z1, %z2, 1f\;trap.n\\t%3\;1:";
1276  else
1277    return "b%R0\\t%z1, %z2, 1f\;trap\\t%3\;1:";
1278}
1279  [(set_attr "type" "control")
1280   (set (attr "length")
1281        (if_then_else (match_test "nios2_cdx_narrow_form_p (insn)")
1282                      (const_int 6) (const_int 8)))])
1283
1284;; Load the GOT register.
1285(define_insn "load_got_register"
1286  [(set (match_operand:SI 0 "register_operand" "=&r")
1287	 (unspec:SI [(const_int 0)] UNSPEC_LOAD_GOT_REGISTER))
1288   (set (match_operand:SI 1 "register_operand" "=r")
1289	 (unspec:SI [(const_int 0)] UNSPEC_LOAD_GOT_REGISTER))]
1290  ""
1291  "nextpc\\t%0
1292\\t1:
1293\\tmovhi\\t%1, %%hiadj(_gp_got - 1b)
1294\\taddi\\t%1, %1, %%lo(_gp_got - 1b)"
1295  [(set_attr "length" "12")])
1296
1297;; Read thread pointer register
1298(define_expand "get_thread_pointersi"
1299  [(match_operand:SI 0 "register_operand" "=r")]
1300  "TARGET_LINUX_ABI"
1301{
1302  emit_move_insn (operands[0], gen_rtx_REG (Pmode, TP_REGNO));
1303  DONE;
1304})
1305
1306;; Synchronization Primitives
1307(include "sync.md")
1308
1309;; Include the ldwm/stwm/push.n/pop.n patterns and peepholes.
1310(include "ldstwm.md")
1311
1312