Skip analyzer strndup test on hppa*-*-hpux*
[official-gcc.git] / gcc / config / nios2 / nios2.md
blob7cd940e5ff035c455b732fe46a70e2341b5b9a8d
1 ;; Machine Description for Altera Nios II.
2 ;; Copyright (C) 2012-2023 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.
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.
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/>.
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)   ;
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
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   ]
50 ;; Enumeration of UNSPECs
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
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
98 ;;  Instruction scheduler
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.
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)))
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"))
115 (define_asm_attributes
116  [(set_attr "length" "4")
117   (set_attr "type" "complex")])
119 (define_automaton "nios2")
120 (automata_option "v")
121 ;(automata_option "no-minimization")
122 (automata_option "ndfa")
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.
129 (define_cpu_unit "cpu" "nios2")
131 (define_insn_reservation "complex" 1
132   (eq_attr "type" "complex")
133   "cpu")
135 (define_insn_reservation "control" 1
136   (eq_attr "type" "control,pop")
137   "cpu")
139 (define_insn_reservation "alu" 1
140   (eq_attr "type" "alu,add,sub,mov,and,or,xor,neg,not")
141   "cpu")
143 (define_insn_reservation "cond_alu" 1
144   (eq_attr "type" "cond_alu")
145   "cpu")
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")
155 ; shifts, muls and lds have three cycle latency
156 (define_insn_reservation "ld" 3
157   (eq_attr "type" "ld,ldwm")
158   "cpu")
160 (define_insn_reservation "shift" 3
161   (eq_attr "type" "sll,srl,sra,rol,ror")
162   "cpu")
164 (define_insn_reservation "mul" 3
165   (eq_attr "type" "mul")
166   "cpu")
168 (define_insn_reservation "div" 1
169   (eq_attr "type" "div")
170   "cpu")
172 (include "predicates.md")
173 (include "constraints.md")
176 ;; Move instructions
178 (define_mode_iterator M [QI HI SI])
180 (define_expand "mov<mode>"
181   [(set (match_operand:M 0 "nonimmediate_operand" "")
182         (match_operand:M 1 "general_operand" ""))]
183   ""
185   if (nios2_emit_move_sequence (operands, <MODE>mode))
186     DONE;
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")])
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")])
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")])
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")])
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")])
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")])
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")])
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   ""
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;
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")])
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")])
376 ;; QI to [HI, SI] extension patterns are collected together
377 (define_mode_iterator QX [HI SI])
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")])
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")])
408 ;; Sign extension patterns
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")])
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")])
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]);")
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]);")
465 ;; Arithmetic Operations
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   ""
473   return nios2_add_insn_asm (insn, operands);
475   [(set_attr "type" "add")])
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")])
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")])
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   ""
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     }
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")])
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")])
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")])
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")])
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"
548   rtx hi = gen_reg_rtx (SImode);
549   rtx lo = gen_reg_rtx (SImode);
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;
559 ;;  Negate and ones complement
561 (define_insn "negsi2"
562   [(set (match_operand:SI 0 "register_operand"        "=r")
563         (neg:SI (match_operand:SI 1 "register_operand" "r")))]
564   ""
566   if (get_attr_length (insn) == 2)
567     return "neg.n\\t%0, %1";
568   else
569     return "sub\\t%0, zero, %1";
571   [(set_attr "type" "neg")])
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   ""
578   if (get_attr_length (insn) == 2)
579     return "not.n\\t%0, %1";
580   else
581     return "nor\\t%0, zero, %1";
583   [(set_attr "type" "not")])
586 ;;  Integer logical Operations
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")])
596 (define_code_iterator LOGICAL [ior xor])
597 (define_code_attr logical_asm [(ior "or") (xor "xor")])
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>")])
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")])
616 ;;  Shift instructions
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")])
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>")])
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")])
640 ;; Nios II R2 Bit Manipulation Extension (BMX), provides
641 ;; bit merge/insertion/extraction instructions.
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"
651   operands[4] = GEN_INT (INTVAL (operands[1]) + INTVAL (operands[2]) - 1);
652   return "merge\\t%0, %3, %4, %2";
654   [(set_attr "type" "alu")])
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"
663   operands[4] = GEN_INT (INTVAL (operands[2]) + INTVAL (operands[3]) - 1);
664   return "extract\\t%0, %1, %4, %3";
666   [(set_attr "type" "alu")])
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"
675   operands[4] = GEN_INT (INTVAL (operands[1]) + INTVAL (operands[2]) - 1);
676   return "insert\\t%0, %z3, %4, %2";
678   [(set_attr "type" "alu")])
682 ;; Floating point instructions
684 ;; Mode iterator for single/double float
685 (define_mode_iterator F [SF DF])
686 (define_mode_attr f [(SF "s") (DF "d")])
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")])
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")])
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")])
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")])
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")])
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")])
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")])
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")])
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")])
759 ;; Converting between floating point and fixed point
761 (define_code_iterator FLOAT [float unsigned_float])
762 (define_code_iterator FIX [fix unsigned_fix])
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")])
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")])
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")])
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")])
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")])
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")])
808 ;; Prologue, Epilogue and Return
810 (define_expand "prologue"
811   [(const_int 1)]
812   ""
814   nios2_expand_prologue ();
815   DONE;
818 (define_expand "epilogue"
819   [(return)]
820   ""
822   nios2_expand_epilogue (false);
823   DONE;
826 (define_expand "sibcall_epilogue"
827   [(return)]
828   ""
830   nios2_expand_epilogue (true);
831   DONE;
834 (define_expand "return"
835   [(simple_return)]
836   "nios2_can_use_return_insn ()"
838   if (nios2_expand_return ())
839     DONE;
842 (define_insn "simple_return"
843   [(simple_return)]
844   ""
845   "ret%."
846   [(set_attr "type" "control")])
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.
852 (define_insn "blockage"
853   [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
854   ""
855   ""
856   [(set_attr "type" "unknown")
857    (set_attr "length" "0")])
859 ;; This is used in compiling the unwind routines.
860 (define_expand "eh_return"
861   [(use (match_operand 0 "general_operand"))]
862   ""
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;
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.
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)]
881   nios2_set_return_address (operands[0], operands[1]);
882   DONE;
886 ;;  Jumps and calls
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.
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.
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")])
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))))])
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);")
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);")
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")])
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")])
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);")
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);")
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")])
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")])
1003 (define_expand "tablejump"
1004   [(parallel [(set (pc) (match_operand 0 "register_operand" "r"))
1005               (use (label_ref (match_operand 1 "" "")))])]
1006   ""
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);
1014       emit_insn (gen_addsi3 (reg2, operands[0], reg1));
1015       operands[0] = reg2;
1016     }
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")])
1028 ;; cstore, cbranch patterns
1030 (define_mode_iterator CM [SI SF DF])
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   ""
1039   if (!nios2_validate_compare (<MODE>mode, &operands[1], &operands[2],
1040                                &operands[3]))
1041     FAIL;
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   ""
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     }
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   ""
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";
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)))])
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")])
1113 ;; Integer comparisons
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")])
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")])
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")])
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.
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")])
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")])
1168 ;;  Misc. patterns
1170 (define_insn "nop"
1171   [(const_int 0)]
1172   ""
1173   "nop%."
1174   [(set_attr "type" "nop")])
1176 ;; Connect 'sync' to 'memory_barrier' standard expand name
1177 (define_expand "memory_barrier"
1178   [(const_int 0)]
1179   ""
1181   emit_insn (gen_sync ());
1182   DONE;
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   ""
1191   operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
1192   MEM_VOLATILE_P (operands[0]) = 1;
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")])
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")])
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")])
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")])
1227 ;; Cache Instructions
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")])
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")])
1243 ;; R2 Instructions
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")])
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")])
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")])
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   ""
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:";
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")])
1297 ;; Read thread pointer register
1298 (define_expand "get_thread_pointersi"
1299   [(match_operand:SI 0 "register_operand" "=r")]
1300   "TARGET_LINUX_ABI"
1302   emit_move_insn (operands[0], gen_rtx_REG (Pmode, TP_REGNO));
1303   DONE;
1306 ;; Synchronization Primitives
1307 (include "sync.md")
1309 ;; Include the ldwm/stwm/push.n/pop.n patterns and peepholes.
1310 (include "ldstwm.md")