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