OSDN Git Service

Add NIOS2 support. Code from SourceyG++.
[pf3gnuchains/gcc-fork.git] / gcc / config / nios2 / nios2.md
1 ;; Machine Description for Altera Nios II.
2 ;; Copyright (C) 2012 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
24 ;; Enumeration of UNSPECs
25
26 (define_c_enum "unspecv" [
27   UNSPECV_BLOCKAGE
28   UNSPECV_WRCTL
29   UNSPECV_RDCTL
30   UNSPECV_TRAP
31   UNSPECV_STACK_OVERFLOW_DETECT_AND_TRAP
32   UNSPECV_FWRX
33   UNSPECV_FWRY
34   UNSPECV_FRDXLO
35   UNSPECV_FRDXHI
36   UNSPECV_FRDY
37   UNSPECV_CUSTOM_NXX
38   UNSPECV_CUSTOM_XNXX
39   UNSPECV_LDXIO
40   UNSPECV_STXIO
41 ])
42
43 (define_c_enum "unspec" [
44   UNSPEC_FCOS
45   UNSPEC_FSIN
46   UNSPEC_FTAN
47   UNSPEC_FATAN
48   UNSPEC_FEXP
49   UNSPEC_FLOG
50   UNSPEC_LOAD_GOT_REGISTER
51   UNSPEC_PIC_SYM
52   UNSPEC_PIC_CALL_SYM
53   UNSPEC_TLS
54   UNSPEC_TLS_LDM
55   UNSPEC_LOAD_TLS_IE
56   UNSPEC_ADD_TLS_LE
57   UNSPEC_ADD_TLS_GD
58   UNSPEC_ADD_TLS_LDM
59   UNSPEC_ADD_TLS_LDO
60   UNSPEC_EH_RETURN
61   UNSPEC_SYNC
62 ])
63
64 \f
65 ;;  Instruction scheduler
66
67 ; No schedule info is currently available, using an assumption that no
68 ; instruction can use the results of the previous instruction without
69 ; incuring a stall.
70
71 ; length of an instruction (in bytes)
72 (define_attr "length" "" (const_int 4))
73 (define_attr "type" 
74   "unknown,complex,control,alu,cond_alu,st,ld,shift,mul,div,custom" 
75   (const_string "complex"))
76
77 (define_asm_attributes
78  [(set_attr "length" "4")
79   (set_attr "type" "complex")])
80
81 (define_automaton "nios2")
82 (automata_option "v")
83 ;(automata_option "no-minimization")
84 (automata_option "ndfa")
85
86 ; The nios2 pipeline is fairly straightforward for the fast model.
87 ; Every alu operation is pipelined so that an instruction can
88 ; be issued every cycle. However, there are still potential
89 ; stalls which this description tries to deal with.
90
91 (define_cpu_unit "cpu" "nios2")
92
93 (define_insn_reservation "complex" 1
94   (eq_attr "type" "complex")
95   "cpu")
96
97 (define_insn_reservation "control" 1
98   (eq_attr "type" "control")
99   "cpu")
100
101 (define_insn_reservation "alu" 1
102   (eq_attr "type" "alu")
103   "cpu")
104
105 (define_insn_reservation "cond_alu" 1
106   (eq_attr "type" "cond_alu")
107   "cpu")
108
109 (define_insn_reservation "st" 1
110   (eq_attr "type" "st")
111   "cpu")
112   
113 (define_insn_reservation "custom" 1
114   (eq_attr "type" "custom")
115   "cpu")
116
117 ; shifts, muls and lds have three cycle latency
118 (define_insn_reservation "ld" 3
119   (eq_attr "type" "ld")
120   "cpu")
121
122 (define_insn_reservation "shift" 3
123   (eq_attr "type" "shift")
124   "cpu")
125
126 (define_insn_reservation "mul" 3
127   (eq_attr "type" "mul")
128   "cpu")
129
130 (define_insn_reservation "div" 1
131   (eq_attr "type" "div")
132   "cpu")
133
134 (include "predicates.md")
135 (include "constraints.md")
136
137 \f
138 ;; Move instructions
139
140 (define_mode_iterator M [QI HI SI])
141
142 (define_expand "mov<mode>"
143   [(set (match_operand:M 0 "nonimmediate_operand" "")
144         (match_operand:M 1 "general_operand" ""))]
145   ""
146 {
147   if (nios2_emit_move_sequence (operands, <MODE>mode))
148     DONE;
149 })
150
151 (define_insn "movqi_internal"
152   [(set (match_operand:QI 0 "nonimmediate_operand" "=m, r,r, r")
153         (match_operand:QI 1 "general_operand"       "rM,m,rM,I"))]
154   "(register_operand (operands[0], QImode)
155     || reg_or_0_operand (operands[1], QImode))"
156   "@
157     stb%o0\\t%z1, %0
158     ldbu%o1\\t%0, %1
159     mov\\t%0, %z1
160     movi\\t%0, %1"
161   [(set_attr "type" "st,ld,alu,alu")])
162
163 (define_insn "movhi_internal"
164   [(set (match_operand:HI 0 "nonimmediate_operand" "=m, r,r, r,r")
165         (match_operand:HI 1 "general_operand"       "rM,m,rM,I,J"))]
166   "(register_operand (operands[0], HImode)
167     || reg_or_0_operand (operands[1], HImode))"
168   "@
169     sth%o0\\t%z1, %0
170     ldhu%o1\\t%0, %1
171     mov\\t%0, %z1
172     movi\\t%0, %1
173     movui\\t%0, %1"
174   [(set_attr "type" "st,ld,alu,alu,alu")])
175
176 (define_insn "movsi_internal"
177   [(set (match_operand:SI 0 "nonimmediate_operand" "=m, r,r, r,r,r,r,r")
178         (match_operand:SI 1 "general_operand"       "rM,m,rM,I,J,K,S,i"))]
179   "(register_operand (operands[0], SImode)
180     || reg_or_0_operand (operands[1], SImode))"
181   "@
182     stw%o0\\t%z1, %0
183     ldw%o1\\t%0, %1
184     mov\\t%0, %z1
185     movi\\t%0, %1
186     movui\\t%0, %1
187     movhi\\t%0, %H1
188     addi\\t%0, gp, %%gprel(%1)
189     movhi\\t%0, %H1\;addi\\t%0, %0, %L1"
190   [(set_attr "type" "st,ld,alu,alu,alu,alu,alu,alu")
191    (set_attr "length" "4,4,4,4,4,4,4,8")])
192
193
194 (define_mode_iterator BH [QI HI])
195 (define_mode_iterator BHW [QI HI SI])
196 (define_mode_attr bh [(QI "b") (HI "h")])
197 (define_mode_attr bhw [(QI "b") (HI "h") (SI "w")])
198 (define_mode_attr bhw_uns [(QI "bu") (HI "hu") (SI "w")])
199
200 (define_insn "ld<bhw_uns>io"
201   [(set (match_operand:BHW 0 "register_operand" "=r")
202         (unspec_volatile:BHW
203           [(match_operand:BHW 1 "memory_operand" "m")] UNSPECV_LDXIO))]
204   ""
205   "ld<bhw_uns>io\\t%0, %1"
206   [(set_attr "type" "ld")])
207
208 (define_expand "ld<bh>io"
209   [(set (match_operand:BH 0 "register_operand" "=r")
210         (match_operand:BH 1 "memory_operand" "m"))]
211   ""
212 {
213   rtx tmp = gen_reg_rtx (SImode);
214   emit_insn (gen_ld<bh>io_signed (tmp, operands[1]));
215   emit_insn (gen_mov<mode> (operands[0], gen_lowpart (<MODE>mode, tmp)));
216   DONE;
217 })
218
219 (define_insn "ld<bh>io_signed"
220   [(set (match_operand:SI 0 "register_operand" "=r")
221         (sign_extend:SI
222           (unspec_volatile:BH
223             [(match_operand:BH 1 "memory_operand" "m")] UNSPECV_LDXIO)))]
224   ""
225   "ld<bh>io\\t%0, %1"
226   [(set_attr "type" "ld")])
227
228 (define_insn "st<bhw>io"
229   [(set (match_operand:BHW 0 "memory_operand" "=m")
230         (unspec_volatile:BHW
231           [(match_operand:BHW 1 "reg_or_0_operand" "rM")] UNSPECV_STXIO))]
232   ""
233   "st<bhw>io\\t%z1, %0"
234   [(set_attr "type" "st")])
235
236 \f
237 ;; QI to [HI, SI] extension patterns are collected together
238 (define_mode_iterator QX [HI SI])
239
240 ;; Zero extension patterns
241 (define_insn "zero_extendhisi2"
242   [(set (match_operand:SI 0 "register_operand" "=r,r")
243         (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
244   ""
245   "@
246     andi\\t%0, %1, 0xffff
247     ldhu%o1\\t%0, %1"
248   [(set_attr "type"     "alu,ld")])
249
250 (define_insn "zero_extendqi<mode>2"
251   [(set (match_operand:QX 0 "register_operand" "=r,r")
252         (zero_extend:QX (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
253   ""
254   "@
255     andi\\t%0, %1, 0xff
256     ldbu%o1\\t%0, %1"
257   [(set_attr "type"     "alu,ld")])
258
259 ;; Sign extension patterns
260
261 (define_insn "extendhisi2"
262   [(set (match_operand:SI 0 "register_operand"                     "=r,r")
263         (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand"  "r,m")))]
264   ""
265   "@
266    #
267    ldh%o1\\t%0, %1"
268   [(set_attr "type" "alu,ld")])
269
270 (define_insn "extendqi<mode>2"
271   [(set (match_operand:QX 0 "register_operand"                     "=r,r")
272         (sign_extend:QX (match_operand:QI 1 "nonimmediate_operand"  "r,m")))]
273   ""
274   "@
275    #
276    ldb%o1\\t%0, %1"
277   [(set_attr "type" "alu,ld")])
278
279 ;; Split patterns for register alternative cases.
280 (define_split
281   [(set (match_operand:SI 0 "register_operand" "")
282         (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
283   "reload_completed"
284   [(set (match_dup 0)
285         (and:SI (match_dup 1) (const_int 65535)))
286    (set (match_dup 0)
287         (xor:SI (match_dup 0) (const_int 32768)))
288    (set (match_dup 0)
289         (plus:SI (match_dup 0) (const_int -32768)))]
290   "operands[1] = gen_lowpart (SImode, operands[1]);")
291
292 (define_split
293   [(set (match_operand:QX 0 "register_operand" "")
294         (sign_extend:QX (match_operand:QI 1 "register_operand" "")))]
295   "reload_completed"
296   [(set (match_dup 0)
297         (and:SI (match_dup 1) (const_int 255)))
298    (set (match_dup 0)
299         (xor:SI (match_dup 0) (const_int 128)))
300    (set (match_dup 0)
301         (plus:SI (match_dup 0) (const_int -128)))]
302   "operands[0] = gen_lowpart (SImode, operands[0]);
303    operands[1] = gen_lowpart (SImode, operands[1]);")
304
305 \f
306 ;; Arithmetic Operations
307
308 (define_insn "addsi3"
309   [(set (match_operand:SI 0 "register_operand"          "=r")
310         (plus:SI (match_operand:SI 1 "register_operand" "%r")
311                  (match_operand:SI 2 "arith_operand"    "rI")))]
312   ""
313   "add%i2\\t%0, %1, %z2"
314   [(set_attr "type" "alu")])
315
316 (define_insn "subsi3"
317   [(set (match_operand:SI 0 "register_operand"           "=r")
318         (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rM")
319                   (match_operand:SI 2 "register_operand" "r")))]
320   ""
321   "sub\\t%0, %z1, %2"
322   [(set_attr "type" "alu")])
323
324 (define_insn "mulsi3"
325   [(set (match_operand:SI 0 "register_operand"          "=r")
326         (mult:SI (match_operand:SI 1 "register_operand" "%r")
327                  (match_operand:SI 2 "arith_operand"    "rI")))]
328   "TARGET_HAS_MUL"
329   "mul%i2\\t%0, %1, %z2"
330   [(set_attr "type" "mul")])
331
332 (define_expand "divsi3"
333   [(set (match_operand:SI 0 "register_operand"          "=r")
334         (div:SI (match_operand:SI 1 "register_operand"   "r")
335                 (match_operand:SI 2 "register_operand"   "r")))]
336   ""
337 {
338   if (!TARGET_HAS_DIV)
339     {
340       if (!TARGET_FAST_SW_DIV)
341         FAIL;
342       else
343         {
344           if (nios2_emit_expensive_div (operands, SImode))
345             DONE;
346         }
347     }
348 })
349
350 (define_insn "divsi3_insn"
351   [(set (match_operand:SI 0 "register_operand"            "=r")
352         (div:SI (match_operand:SI 1 "register_operand"     "r")
353                 (match_operand:SI 2 "register_operand"     "r")))]
354   "TARGET_HAS_DIV"
355   "div\\t%0, %1, %2"
356   [(set_attr "type" "div")])
357
358 (define_insn "udivsi3"
359   [(set (match_operand:SI 0 "register_operand"            "=r")
360         (udiv:SI (match_operand:SI 1 "register_operand"    "r")
361                  (match_operand:SI 2 "register_operand"    "r")))]
362   "TARGET_HAS_DIV"
363   "divu\\t%0, %1, %2"
364   [(set_attr "type" "div")])
365
366 (define_code_iterator EXTEND [sign_extend zero_extend])
367 (define_code_attr us [(sign_extend "s") (zero_extend "u")])
368 (define_code_attr mul [(sign_extend "mul") (zero_extend "umul")])
369
370 (define_insn "<us>mulsi3_highpart"
371   [(set (match_operand:SI 0 "register_operand"                       "=r")
372         (truncate:SI
373          (lshiftrt:DI
374           (mult:DI (EXTEND:DI (match_operand:SI 1 "register_operand"  "r"))
375                    (EXTEND:DI (match_operand:SI 2 "register_operand"  "r")))
376           (const_int 32))))]
377   "TARGET_HAS_MULX"
378   "mulx<us><us>\\t%0, %1, %2"
379   [(set_attr "type" "mul")])
380
381 (define_expand "<mul>sidi3"
382   [(set (match_operand:DI 0 "register_operand" "")
383         (mult:DI (EXTEND:DI (match_operand:SI 1 "register_operand" ""))
384                  (EXTEND:DI (match_operand:SI 2 "register_operand" ""))))]
385   "TARGET_HAS_MULX"
386 {
387   rtx hi = gen_reg_rtx (SImode);
388   rtx lo = gen_reg_rtx (SImode);
389
390   emit_insn (gen_<us>mulsi3_highpart (hi, operands[1], operands[2]));
391   emit_insn (gen_mulsi3 (lo, operands[1], operands[2]));
392   emit_move_insn (gen_lowpart (SImode, operands[0]), lo);
393   emit_move_insn (gen_highpart (SImode, operands[0]), hi);
394   DONE;
395 })
396
397 \f
398 ;;  Negate and ones complement
399
400 (define_insn "negsi2"
401   [(set (match_operand:SI 0 "register_operand"        "=r")
402         (neg:SI (match_operand:SI 1 "register_operand" "r")))]
403   ""
404   "sub\\t%0, zero, %1"
405   [(set_attr "type" "alu")])
406
407 (define_insn "one_cmplsi2"
408   [(set (match_operand:SI 0 "register_operand"        "=r")
409         (not:SI (match_operand:SI 1 "register_operand" "r")))]
410   ""
411   "nor\\t%0, zero, %1"
412   [(set_attr "type" "alu")])
413
414 \f
415 ;;  Integer logical Operations
416
417 (define_code_iterator LOGICAL [and ior xor])
418 (define_code_attr logical_asm [(and "and") (ior "or") (xor "xor")])
419
420 (define_insn "<code>si3"
421   [(set (match_operand:SI 0 "register_operand"             "=r,r,r")
422         (LOGICAL:SI (match_operand:SI 1 "register_operand" "%r,r,r")
423                     (match_operand:SI 2 "logical_operand"  "rM,J,K")))]
424   ""
425   "@
426     <logical_asm>\\t%0, %1, %z2
427     <logical_asm>%i2\\t%0, %1, %2
428     <logical_asm>h%i2\\t%0, %1, %U2"
429   [(set_attr "type" "alu")])
430
431 (define_insn "*norsi3"
432   [(set (match_operand:SI 0 "register_operand"                  "=r")
433         (and:SI (not:SI (match_operand:SI 1 "register_operand"  "%r"))
434                 (not:SI (match_operand:SI 2 "reg_or_0_operand"  "rM"))))]
435   ""
436   "nor\\t%0, %1, %z2"
437   [(set_attr "type" "alu")])
438
439 \f
440 ;;  Shift instructions
441
442 (define_code_iterator SHIFT  [ashift ashiftrt lshiftrt rotate])
443 (define_code_attr shift_op   [(ashift "ashl") (ashiftrt "ashr")
444                               (lshiftrt "lshr") (rotate "rotl")])
445 (define_code_attr shift_asm  [(ashift "sll") (ashiftrt "sra")
446                               (lshiftrt "srl") (rotate "rol")])
447
448 (define_insn "<shift_op>si3"
449   [(set (match_operand:SI 0 "register_operand"          "=r")
450         (SHIFT:SI (match_operand:SI 1 "register_operand" "r")
451                   (match_operand:SI 2 "shift_operand"    "rL")))]
452   ""
453   "<shift_asm>%i2\\t%0, %1, %z2"
454   [(set_attr "type" "shift")])
455
456 (define_insn "rotrsi3"
457   [(set (match_operand:SI 0 "register_operand"             "=r")
458         (rotatert:SI (match_operand:SI 1 "register_operand" "r")
459                      (match_operand:SI 2 "register_operand" "r")))]
460   ""
461   "ror\\t%0, %1, %2"
462   [(set_attr "type" "shift")])
463
464
465 \f
466 ;; Floating point instructions
467
468 ;; Mode iterator for single/double float
469 (define_mode_iterator F [SF DF])
470 (define_mode_attr f [(SF "s") (DF "d")])
471
472 ;; Basic arithmetic instructions
473 (define_code_iterator FOP3 [plus minus mult div])
474 (define_code_attr fop3 [(plus "add") (minus "sub") (mult "mul") (div "div")])
475
476 (define_insn "<fop3><mode>3"
477   [(set (match_operand:F 0 "register_operand"        "=r")
478         (FOP3:F (match_operand:F 1 "register_operand" "r")
479                 (match_operand:F 2 "register_operand" "r")))]
480   "nios2_fpu_insn_enabled (n2fpu_f<fop3><f>)"
481   "* return nios2_fpu_insn_asm (n2fpu_f<fop3><f>);"
482   [(set_attr "type" "custom")])
483
484 ;; Floating point min/max operations
485 (define_code_iterator SMINMAX [smin smax])
486 (define_code_attr minmax [(smin "min") (smax "max")])
487 (define_insn "<code><mode>3"
488   [(set (match_operand:F 0 "register_operand" "=r")
489         (SMINMAX:F (match_operand:F 1 "register_operand" "r")
490                    (match_operand:F 2 "register_operand" "r")))]
491   "nios2_fpu_insn_enabled (n2fpu_f<minmax><f>)"
492   "* return nios2_fpu_insn_asm (n2fpu_f<minmax><f>);"
493   [(set_attr "type" "custom")])
494
495 ;; These 2-operand FP operations can be collected together
496 (define_code_iterator FOP2 [abs neg sqrt])
497 (define_insn "<code><mode>2"
498   [(set (match_operand:F 0 "register_operand" "=r")
499         (FOP2:F (match_operand:F 1 "register_operand" "r")))]
500   "nios2_fpu_insn_enabled (n2fpu_f<code><f>)"
501   "* return nios2_fpu_insn_asm (n2fpu_f<code><f>);"
502   [(set_attr "type" "custom")])
503
504 ;; X, Y register access instructions
505 (define_insn "nios2_fwrx"
506   [(unspec_volatile [(match_operand:DF 0 "register_operand" "r")] UNSPECV_FWRX)]
507   "nios2_fpu_insn_enabled (n2fpu_fwrx)"
508   "* return nios2_fpu_insn_asm (n2fpu_fwrx);"
509   [(set_attr "type" "custom")])
510
511 (define_insn "nios2_fwry"
512   [(unspec_volatile [(match_operand:SF 0 "register_operand" "r")] UNSPECV_FWRY)]
513   "nios2_fpu_insn_enabled (n2fpu_fwry)"
514   "* return nios2_fpu_insn_asm (n2fpu_fwry);"
515   [(set_attr "type" "custom")])
516
517 ;; The X, Y read insns uses an int iterator
518 (define_int_iterator UNSPEC_READ_XY [UNSPECV_FRDXLO UNSPECV_FRDXHI
519                                      UNSPECV_FRDY])
520 (define_int_attr read_xy [(UNSPECV_FRDXLO "frdxlo") (UNSPECV_FRDXHI "frdxhi")
521                           (UNSPECV_FRDY "frdy")])
522 (define_insn "nios2_<read_xy>"
523   [(set (match_operand:SF 0 "register_operand" "=r")
524         (unspec_volatile:SF [(const_int 0)] UNSPEC_READ_XY))]
525   "nios2_fpu_insn_enabled (n2fpu_<read_xy>)"
526   "* return nios2_fpu_insn_asm (n2fpu_<read_xy>);"
527   [(set_attr "type" "custom")])
528
529 ;; Various math functions
530 (define_int_iterator MATHFUNC
531   [UNSPEC_FCOS UNSPEC_FSIN UNSPEC_FTAN UNSPEC_FATAN UNSPEC_FEXP UNSPEC_FLOG])
532 (define_int_attr mathfunc [(UNSPEC_FCOS "cos") (UNSPEC_FSIN "sin")
533                            (UNSPEC_FTAN "tan") (UNSPEC_FATAN "atan")
534                            (UNSPEC_FEXP "exp") (UNSPEC_FLOG "log")])
535
536 (define_insn "<mathfunc><mode>2"
537   [(set (match_operand:F 0 "register_operand" "=r")
538         (unspec:F [(match_operand:F 1 "register_operand" "r")] MATHFUNC))]
539   "nios2_fpu_insn_enabled (n2fpu_f<mathfunc><f>)"
540   "* return nios2_fpu_insn_asm (n2fpu_f<mathfunc><f>);"
541   [(set_attr "type" "custom")])
542
543 ;; Converting between floating point and fixed point
544
545 (define_code_iterator FLOAT [float unsigned_float])
546 (define_code_iterator FIX [fix unsigned_fix])
547
548 (define_code_attr conv_op [(float "float") (unsigned_float "floatuns")
549                            (fix "fix") (unsigned_fix "fixuns")])
550 (define_code_attr i [(float "i") (unsigned_float "u")
551                      (fix "i") (unsigned_fix "u")])
552
553 ;; Integer to float conversions
554 (define_insn "<conv_op>si<mode>2"
555   [(set (match_operand:F 0 "register_operand" "=r")
556         (FLOAT:F (match_operand:SI 1 "register_operand" "r")))]
557   "nios2_fpu_insn_enabled (n2fpu_float<i><f>)"
558   "* return nios2_fpu_insn_asm (n2fpu_float<i><f>);"
559   [(set_attr "type" "custom")])
560
561 ;; Float to integer conversions
562 (define_insn "<conv_op>_trunc<mode>si2"
563   [(set (match_operand:SI 0 "register_operand" "=r")
564         (FIX:SI (match_operand:F 1 "general_operand" "r")))]
565   "nios2_fpu_insn_enabled (n2fpu_fix<f><i>)"
566   "* return nios2_fpu_insn_asm (n2fpu_fix<f><i>);"
567   [(set_attr "type" "custom")])
568
569 (define_insn "extendsfdf2"
570   [(set (match_operand:DF 0 "register_operand" "=r")
571         (float_extend:DF (match_operand:SF 1 "general_operand" "r")))]
572   "nios2_fpu_insn_enabled (n2fpu_fextsd)"
573   "* return nios2_fpu_insn_asm (n2fpu_fextsd);"
574   [(set_attr "type" "custom")])
575
576 (define_insn "truncdfsf2"
577   [(set (match_operand:SF 0 "register_operand" "=r")
578         (float_truncate:SF (match_operand:DF 1 "general_operand" "r")))]
579   "nios2_fpu_insn_enabled (n2fpu_ftruncds)"
580   "* return nios2_fpu_insn_asm (n2fpu_ftruncds);"
581   [(set_attr "type" "custom")])
582
583
584 \f
585 ;; Prologue, Epilogue and Return
586
587 (define_expand "prologue"
588   [(const_int 1)]
589   ""
590 {
591   expand_prologue ();
592   DONE;
593 })
594
595 (define_expand "epilogue"
596   [(return)]
597   ""
598 {
599   expand_epilogue (false);
600   DONE;
601 })
602
603 (define_expand "sibcall_epilogue"
604   [(return)]
605   ""
606 {
607   expand_epilogue (true);
608   DONE;
609 })
610
611 (define_insn "return"
612   [(return)]
613   "nios2_can_use_return_insn ()"
614   "ret"
615 )
616
617 (define_insn "return_from_epilogue"
618   [(use (match_operand 0 "pmode_register_operand" ""))
619    (return)]
620   "reload_completed"
621   "ret"
622 )
623
624 ;; Block any insns from being moved before this point, since the
625 ;; profiling call to mcount can use various registers that aren't
626 ;; saved or used to pass arguments.
627
628 (define_insn "blockage"
629   [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
630   ""
631   ""
632   [(set_attr "type" "unknown")
633    (set_attr "length" "0")])
634
635 ;; This is used in compiling the unwind routines.
636 (define_expand "eh_return"
637   [(use (match_operand 0 "general_operand"))]
638   ""
639 {
640   if (GET_MODE (operands[0]) != Pmode)
641     operands[0] = convert_to_mode (Pmode, operands[0], 0);
642   emit_insn (gen_eh_set_ra (operands[0]));
643
644   DONE;
645 })
646
647 ;; Clobber the return address on the stack.  We can't expand this
648 ;; until we know where it will be put in the stack frame.
649
650 (define_insn "eh_set_ra"
651   [(unspec [(match_operand:SI 0 "register_operand" "r")] UNSPEC_EH_RETURN)
652    (clobber (match_scratch:SI 1 "=&r"))]
653  ""
654   "#")
655
656 (define_split
657   [(unspec [(match_operand 0 "register_operand")] UNSPEC_EH_RETURN)
658    (clobber (match_scratch 1))]
659   "reload_completed"
660   [(const_int 0)]
661 {
662   nios2_set_return_address (operands[0], operands[1]);
663   DONE;
664 })
665
666 \f
667 ;;  Jumps and calls
668
669 ; Note that the assembler fixes up any out-of-range branch instructions not
670 ; caught by the compiler branch shortening code.  The sequence emitted by
671 ; the assembler can be very inefficient, but it is correct for PIC code.
672 ; For non-PIC we are better off converting to an absolute JMPI.
673 ;
674 ; Direct calls and sibcalls use the CALL and JMPI instructions, respectively.
675 ; These instructions have an immediate operand that specifies the low 28 bits
676 ; of the PC, effectively allowing direct calls within a 256MB memory segment.
677 ; Per the Nios II Processor Reference Handbook, the linker is not required to
678 ; check or adjust for overflow.
679
680 (define_insn "indirect_jump"
681   [(set (pc) (match_operand:SI 0 "register_operand" "r"))]
682   ""
683   "jmp\\t%0"
684   [(set_attr "type" "control")])
685
686 (define_insn "jump"
687   [(set (pc)
688         (label_ref (match_operand 0 "" "")))]
689   ""
690   {
691     if (flag_pic || get_attr_length (insn) == 4)
692       return "br\\t%0";
693     else
694       return "jmpi\\t%0";
695   }
696   [(set_attr "type" "control")
697    (set (attr "length") 
698         (if_then_else
699             (and (ge (minus (match_dup 0) (pc)) (const_int -32768))
700                  (le (minus (match_dup 0) (pc)) (const_int 32764)))
701             (const_int 4)
702             (const_int 8)))])
703
704
705 (define_expand "call"
706   [(parallel [(call (match_operand 0 "" "")
707                     (match_operand 1 "" ""))
708               (clobber (reg:SI 31))])]
709   ""
710   "nios2_adjust_call_address (&XEXP (operands[0], 0));"
711 )
712
713 (define_expand "call_value"
714   [(parallel [(set (match_operand 0 "" "")
715                    (call (match_operand 1 "" "")
716                          (match_operand 2 "" "")))
717               (clobber (reg:SI 31))])]
718   ""
719   "nios2_adjust_call_address (&XEXP (operands[1], 0));"
720 )
721
722 (define_insn "*call"
723   [(call (mem:QI (match_operand:SI 0 "call_operand" "i,r"))
724          (match_operand 1 "" ""))
725    (clobber (reg:SI 31))]
726   ""
727   "@
728    call\\t%0
729    callr\\t%0"
730   [(set_attr "type" "control,control")])
731
732 (define_insn "*call_value"
733   [(set (match_operand 0 "" "")
734         (call (mem:QI (match_operand:SI 1 "call_operand" "i,r"))
735               (match_operand 2 "" "")))
736    (clobber (reg:SI 31))]
737   ""
738   "@
739    call\\t%1
740    callr\\t%1"
741   [(set_attr "type" "control,control")])
742
743 (define_expand "sibcall"
744   [(parallel [(call (match_operand 0 "" "")
745                     (match_operand 1 "" ""))
746               (return)])]
747   ""
748   "nios2_adjust_call_address (&XEXP (operands[0], 0));"
749 )
750
751 (define_expand "sibcall_value"
752   [(parallel [(set (match_operand 0 "" "")
753                    (call (match_operand 1 "" "")
754                          (match_operand 2 "" "")))
755               (return)])]
756   ""
757   "nios2_adjust_call_address (&XEXP (operands[1], 0));"
758 )
759
760 (define_insn "*sibcall"
761  [(call (mem:QI (match_operand:SI 0 "call_operand" "i,j"))
762         (match_operand 1 "" ""))
763   (return)]
764   ""
765   "@
766    jmpi\\t%0
767    jmp\\t%0"
768 )
769
770 (define_insn "*sibcall_value"
771  [(set (match_operand 0 "register_operand" "")
772        (call (mem:QI (match_operand:SI 1 "call_operand" "i,j"))
773              (match_operand 2 "" "")))
774   (return)]
775   ""
776   "@
777    jmpi\\t%1
778    jmp\\t%1"
779 )
780
781 (define_expand "tablejump"
782   [(parallel [(set (pc) (match_operand 0 "register_operand" "r"))
783               (use (label_ref (match_operand 1 "" "")))])]
784   ""
785   {
786     if (flag_pic)
787       {
788         /* Hopefully, CSE will eliminate this copy.  */
789         rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
790         rtx reg2 = gen_reg_rtx (SImode);
791
792         emit_insn (gen_addsi3 (reg2, operands[0], reg1));
793         operands[0] = reg2;
794       }
795   }
796 )
797
798 (define_insn "*tablejump"
799   [(set (pc)
800         (match_operand:SI 0 "register_operand" "r"))
801    (use (label_ref (match_operand 1 "" "")))]
802   ""
803   "jmp\\t%0"
804   [(set_attr "type" "control")])
805
806
807 \f
808 ;; cstore, cbranch patterns
809
810 (define_mode_iterator CM [SI SF DF])
811
812 (define_expand "cstore<mode>4"
813   [(set (match_operand:SI 0 "register_operand" "=r")
814         (match_operator:SI 1 "ordered_comparison_operator"
815           [(match_operand:CM 2 "register_operand")
816            (match_operand:CM 3 "nonmemory_operand")]))]
817   "nios2_supported_compare_p (<MODE>mode)"
818   {
819     if (!nios2_validate_compare (<MODE>mode, &operands[1], &operands[2],
820                                  &operands[3]))
821       FAIL;
822   })
823
824 (define_expand "cbranch<mode>4"
825   [(set (pc)
826      (if_then_else
827        (match_operator 0 "ordered_comparison_operator"
828          [(match_operand:CM 1 "register_operand")
829           (match_operand:CM 2 "nonmemory_operand")])
830        (label_ref (match_operand 3 ""))
831        (pc)))]
832   "nios2_supported_compare_p (<MODE>mode)"
833   {
834     if (!nios2_validate_compare (<MODE>mode, &operands[0], &operands[1],
835                                  &operands[2]))
836       FAIL;
837     if (GET_MODE_CLASS (<MODE>mode) == MODE_FLOAT
838         || !reg_or_0_operand (operands[2], <MODE>mode))
839       {
840         rtx condreg = gen_reg_rtx (SImode);
841         emit_insn (gen_cstore<mode>4
842                     (condreg, operands[0], operands[1], operands[2]));
843         operands[1] = condreg;
844         operands[2] = const0_rtx;
845         operands[0] = gen_rtx_fmt_ee (NE, VOIDmode, condreg, const0_rtx);
846       }
847   })
848
849 (define_insn "nios2_cbranch"
850   [(set (pc)
851      (if_then_else
852        (match_operator 0 "ordered_comparison_operator"
853          [(match_operand:SI 1 "reg_or_0_operand" "rM")
854           (match_operand:SI 2 "reg_or_0_operand" "rM")])
855        (label_ref (match_operand 3 "" ""))
856        (pc)))]
857   ""
858   {
859     if (flag_pic || get_attr_length (insn) == 4)
860       return "b%0\t%z1, %z2, %l3";
861     else
862       return "b%R0\t%z1, %z2, .+8;jmpi\t%l3";
863   }
864   [(set_attr "type" "control")
865    (set (attr "length") 
866         (if_then_else
867             (and (ge (minus (match_dup 1) (pc)) (const_int -32768))
868                  (le (minus (match_dup 1) (pc)) (const_int 32764)))
869             (const_int 4) (const_int 8)))])
870
871 ;; Floating point comparisons
872 (define_code_iterator FCMP [eq ne gt ge le lt])
873 (define_insn "nios2_s<code><mode>"
874   [(set (match_operand:SI 0 "register_operand"        "=r")
875         (FCMP:SI (match_operand:F 1 "register_operand" "r")
876                  (match_operand:F 2 "register_operand" "r")))]
877   "nios2_fpu_insn_enabled (n2fpu_fcmp<code><f>)"
878   "* return nios2_fpu_insn_asm (n2fpu_fcmp<code><f>);"
879   [(set_attr "type" "custom")])
880
881 ;; Integer comparisons
882
883 (define_code_iterator EQNE [eq ne])
884 (define_insn "nios2_cmp<code>"
885   [(set (match_operand:SI 0 "register_operand"           "=r")
886         (EQNE:SI (match_operand:SI 1 "reg_or_0_operand" "%rM")
887                  (match_operand:SI 2 "arith_operand"     "rI")))]
888   ""
889   "cmp<code>%i2\\t%0, %z1, %z2"
890   [(set_attr "type" "alu")])
891
892 (define_code_iterator SCMP [ge lt])
893 (define_insn "nios2_cmp<code>"
894   [(set (match_operand:SI 0 "register_operand"           "=r")
895         (SCMP:SI (match_operand:SI 1 "reg_or_0_operand"  "rM")
896                  (match_operand:SI 2 "arith_operand"     "rI")))]
897   ""
898   "cmp<code>%i2\\t%0, %z1, %z2"
899   [(set_attr "type" "alu")])
900
901 (define_code_iterator UCMP [geu ltu])
902 (define_insn "nios2_cmp<code>"
903   [(set (match_operand:SI 0 "register_operand"           "=r")
904         (UCMP:SI (match_operand:SI 1 "reg_or_0_operand"  "rM")
905                  (match_operand:SI 2 "uns_arith_operand" "rJ")))]
906   ""
907   "cmp<code>%i2\\t%0, %z1, %z2"
908   [(set_attr "type" "alu")])
909
910
911 \f
912 ;; Custom instruction patterns. The operands are intentionally
913 ;; mode-less, to serve as generic carriers of all Altera defined
914 ;; built-in instruction/function types.
915
916 (define_insn "custom_nxx"
917   [(unspec_volatile [(match_operand 0 "custom_insn_opcode" "N")
918                      (match_operand 1 "reg_or_0_operand"  "rM")
919                      (match_operand 2 "reg_or_0_operand"  "rM")]
920     UNSPECV_CUSTOM_NXX)]
921   ""
922   "custom\\t%0, zero, %z1, %z2"
923   [(set_attr "type" "custom")])
924
925 (define_insn "custom_xnxx"
926   [(set (match_operand 0 "register_operand"   "=r")
927         (unspec_volatile [(match_operand 1 "custom_insn_opcode" "N")
928                           (match_operand 2 "reg_or_0_operand"  "rM")
929                           (match_operand 3 "reg_or_0_operand"  "rM")] 
930          UNSPECV_CUSTOM_XNXX))]
931   ""
932   "custom\\t%1, %0, %z2, %z3"
933   [(set_attr "type" "custom")])
934
935 \f
936 ;;  Misc. patterns
937
938 (define_insn "nop"
939   [(const_int 0)]
940   ""
941   "nop"
942   [(set_attr "type" "alu")])
943
944 ;; Connect 'sync' to 'memory_barrier' standard expand name
945 (define_expand "memory_barrier"
946   [(const_int 0)]
947   ""
948 {
949   emit_insn (gen_sync ());
950   DONE;
951 })
952
953 ;; For the nios2 __builtin_sync built-in function
954 (define_expand "sync"
955   [(set (match_dup 0)
956         (unspec:BLK [(match_dup 0)] UNSPEC_SYNC))]
957   ""
958 {
959   operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
960   MEM_VOLATILE_P (operands[0]) = 1;
961 })
962
963 (define_insn "*sync_insn"
964   [(set (match_operand:BLK 0 "" "")
965         (unspec:BLK [(match_dup 0)] UNSPEC_SYNC))]
966   ""
967   "sync"
968   [(set_attr "type" "control")])
969
970 (define_insn "rdctl"
971   [(set (match_operand:SI 0 "register_operand" "=r")
972         (unspec_volatile:SI [(match_operand:SI 1 "rdwrctl_operand" "O")] 
973          UNSPECV_RDCTL))]
974   ""
975   "rdctl\\t%0, ctl%1"
976   [(set_attr "type" "control")])
977
978 (define_insn "wrctl"
979   [(unspec_volatile:SI [(match_operand:SI 0 "rdwrctl_operand"  "O")
980                         (match_operand:SI 1 "reg_or_0_operand" "rM")] 
981     UNSPECV_WRCTL)]
982   ""
983   "wrctl\\tctl%0, %z1"
984   [(set_attr "type" "control")])
985
986 ;; Used to signal a stack overflow 
987 (define_insn "trap"
988   [(unspec_volatile [(const_int 0)] UNSPECV_TRAP)]
989   ""
990   "break\\t3"
991   [(set_attr "type" "control")])
992   
993 (define_insn "stack_overflow_detect_and_trap"
994   [(unspec_volatile [(const_int 0)] UNSPECV_STACK_OVERFLOW_DETECT_AND_TRAP)]
995   ""
996   "bgeu\\tsp, et, 1f\;break\\t3\;1:"
997   [(set_attr "type" "control")
998    (set_attr "length" "8")])
999
1000 ;; Load the GOT register.
1001 (define_insn "load_got_register"
1002   [(set (match_operand:SI 0 "register_operand" "=&r")
1003          (unspec:SI [(const_int 0)] UNSPEC_LOAD_GOT_REGISTER))
1004    (set (match_operand:SI 1 "register_operand" "=r")
1005          (unspec:SI [(const_int 0)] UNSPEC_LOAD_GOT_REGISTER))]
1006   ""
1007   "nextpc\\t%0
1008 \\t1:
1009 \\tmovhi\\t%1, %%hiadj(_GLOBAL_OFFSET_TABLE_ - 1b)
1010 \\taddi\\t%1, %1, %%lo(_GLOBAL_OFFSET_TABLE_ - 1b)"
1011   [(set_attr "length" "12")])
1012
1013 ;; When generating pic, we need to load the symbol offset into a register.
1014 ;; So that the optimizer does not confuse this with a normal symbol load
1015 ;; we use an unspec.  The offset will be loaded from a constant pool entry,
1016 ;; since that is the only type of relocation we can use.
1017
1018 ;; The rather odd constraints on the following are to force reload to leave
1019 ;; the insn alone, and to force the minipool generation pass to then move
1020 ;; the GOT symbol to memory.
1021
1022 (define_insn "pic_load_addr"
1023   [(set (match_operand:SI 0 "register_operand" "=r")
1024         (unspec:SI [(match_operand:SI 1 "register_operand" "r")
1025                     (match_operand:SI 2 "" "mX")] UNSPEC_PIC_SYM))]
1026   "flag_pic && TARGET_LINUX_ABI"
1027   "ldw\\t%0, %%got(%2)(%1)")
1028
1029 (define_insn "pic_load_call_addr"
1030   [(set (match_operand:SI 0 "register_operand" "=r")
1031         (unspec:SI [(match_operand:SI 1 "register_operand" "r")
1032                     (match_operand:SI 2 "" "mX")] UNSPEC_PIC_CALL_SYM))]
1033   "flag_pic && TARGET_LINUX_ABI"
1034   "ldw\\t%0, %%call(%2)(%1)")
1035
1036 ;; TLS support
1037
1038 (define_insn "add_tls_gd"
1039   [(set (match_operand:SI 0 "register_operand" "=r")
1040         (unspec:SI [(match_operand:SI 1 "register_operand" "r")
1041                    (match_operand:SI 2 "" "mX")] UNSPEC_ADD_TLS_GD))]
1042   "TARGET_LINUX_ABI"
1043   "addi\t%0, %1, %%tls_gd(%2)")
1044
1045 (define_insn "load_tls_ie"
1046   [(set (match_operand:SI 0 "register_operand" "=r")
1047         (unspec:SI [(match_operand:SI 1 "register_operand" "r")
1048                     (match_operand:SI 2 "" "mX")] UNSPEC_LOAD_TLS_IE))]
1049   "TARGET_LINUX_ABI"
1050   "ldw\t%0, %%tls_ie(%2)(%1)")
1051
1052 (define_insn "add_tls_ldm"
1053   [(set (match_operand:SI 0 "register_operand" "=r")
1054         (unspec:SI [(match_operand:SI 1 "register_operand" "r")
1055                     (match_operand:SI 2 "" "mX")] UNSPEC_ADD_TLS_LDM))]
1056   "TARGET_LINUX_ABI"
1057   "addi\t%0, %1, %%tls_ldm(%2)")
1058
1059 (define_insn "add_tls_ldo"
1060   [(set (match_operand:SI 0 "register_operand" "=r")
1061         (unspec:SI [(match_operand:SI 1 "register_operand" "r")
1062                     (match_operand:SI 2 "" "mX")] UNSPEC_ADD_TLS_LDO))]
1063   "TARGET_LINUX_ABI"
1064   "addi\t%0, %1, %%tls_ldo(%2)")
1065
1066 (define_insn "add_tls_le"
1067   [(set (match_operand:SI 0 "register_operand" "=r")
1068         (unspec:SI [(match_operand:SI 1 "register_operand" "r")
1069                     (match_operand:SI 2 "" "mX")] UNSPEC_ADD_TLS_LE))]
1070   "TARGET_LINUX_ABI"
1071   "addi\t%0, %1, %%tls_le(%2)")
1072