1 ;; Machine Description for Altera Nios II.
2 ;; Copyright (C) 2012-2018 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.
7 ;; This file is part of GCC.
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)
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/>.
26 (FIRST_RETVAL_REGNO 2) ; Return value registers
27 (LAST_RETVAL_REGNO 3) ;
28 (FIRST_ARG_REGNO 4) ; Argument registers
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)
44 (FRAME_POINTER_REGNUM 38)
45 (ARG_POINTER_REGNUM 39)
46 (FIRST_PSEUDO_REGISTER 40)
50 ;; Enumeration of UNSPECs
52 (define_c_enum "unspecv" [
76 (define_c_enum "unspec" [
84 UNSPEC_LOAD_GOT_REGISTER
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
104 ; length of an instruction (in bytes)
105 (define_attr "length" ""
106 (if_then_else (match_test "nios2_cdx_narrow_form_p (insn)")
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")
135 (define_insn_reservation "control" 1
136 (eq_attr "type" "control,pop")
139 (define_insn_reservation "alu" 1
140 (eq_attr "type" "alu,add,sub,mov,and,or,xor,neg,not")
143 (define_insn_reservation "cond_alu" 1
144 (eq_attr "type" "cond_alu")
147 (define_insn_reservation "st" 1
148 (eq_attr "type" "st,stwm,push")
151 (define_insn_reservation "custom" 1
152 (eq_attr "type" "custom")
155 ; shifts, muls and lds have three cycle latency
156 (define_insn_reservation "ld" 3
157 (eq_attr "type" "ld,ldwm")
160 (define_insn_reservation "shift" 3
161 (eq_attr "type" "sll,srl,sra,rol,ror")
164 (define_insn_reservation "mul" 3
165 (eq_attr "type" "mul")
168 (define_insn_reservation "div" 1
169 (eq_attr "type" "div")
172 (include "predicates.md")
173 (include "constraints.md")
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" ""))]
185 if (nios2_emit_move_sequence (operands, <MODE>mode))
190 [(set (match_operand:SI 0 "register_operand" "=r")
191 (high:SI (match_operand:SI 1 "immediate_operand" "i")))]
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")))]
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))"
210 switch (which_alternative)
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";
218 return "stb.n\\t%z1, %0";
220 return "ldbu%o1%.\\t%0, %1";
222 return "mov%i1%.\\t%0, %z1";
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))]
231 if (nios2_large_constant_memory_operand_p (operands[0]))
232 operands[0] = nios2_split_large_constant_memory_operand (operands[0]);
234 operands[1] = nios2_split_large_constant_memory_operand (operands[1]);
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))"
244 switch (which_alternative)
247 return "sth%o0%.\\t%z1, %0";
249 return "ldhu%o1%.\\t%0, %1";
251 return "mov%i1%.\\t%0, %z1";
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))]
260 if (nios2_large_constant_memory_operand_p (operands[0]))
261 operands[0] = nios2_split_large_constant_memory_operand (operands[0]);
263 operands[1] = nios2_split_large_constant_memory_operand (operands[1]);
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))"
273 switch (which_alternative)
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";
283 return "stw.n\\t%z1, %0";
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";
290 return "ldw.n\\t%0, %1";
292 return "mov%i1%.\\t%0, %z1";
294 return "addi\\t%0, gp, %%gprel(%1)";
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 && !SMALL_INT_UNSIGNED (INTVAL (operands[1]))
303 && !UPPER16_INT (INTVAL (operands[1]))))"
304 [(set (match_dup 0) (match_dup 1))]
306 if (nios2_large_constant_memory_operand_p (operands[0]))
307 operands[0] = nios2_split_large_constant_memory_operand (operands[0]);
308 else if (nios2_large_constant_memory_operand_p (operands[1]))
309 operands[1] = nios2_split_large_constant_memory_operand (operands[1]);
311 operands[1] = nios2_split_large_constant (operands[1], operands[0]);
313 [(set_attr "type" "st,ld,mov,alu")])
315 (define_mode_iterator BH [QI HI])
316 (define_mode_iterator BHW [QI HI SI])
317 (define_mode_attr bh [(QI "b") (HI "h")])
318 (define_mode_attr bhw [(QI "b") (HI "h") (SI "w")])
319 (define_mode_attr bhw_uns [(QI "bu") (HI "hu") (SI "w")])
321 (define_insn_and_split "ld<bhw_uns>io"
322 [(set (match_operand:BHW 0 "register_operand" "=r")
324 [(match_operand:BHW 1 "ldstio_memory_operand" "w")] UNSPECV_LDXIO))]
326 "ld<bhw_uns>io\\t%0, %1"
327 "nios2_large_constant_memory_operand_p (operands[1])"
329 (unspec_volatile:BHW [(match_dup 1)] UNSPECV_LDXIO))]
331 operands[1] = nios2_split_large_constant_memory_operand (operands[1]);
333 [(set_attr "type" "ld")])
335 (define_expand "ld<bh>io"
336 [(set (match_operand:BH 0 "register_operand" "=r")
337 (match_operand:BH 1 "ldstio_memory_operand" "w"))]
340 rtx tmp = gen_reg_rtx (SImode);
341 emit_insn (gen_ld<bh>io_signed (tmp, operands[1]));
342 emit_insn (gen_mov<mode> (operands[0], gen_lowpart (<MODE>mode, tmp)));
346 (define_insn_and_split "ld<bh>io_signed"
347 [(set (match_operand:SI 0 "register_operand" "=r")
350 [(match_operand:BH 1 "ldstio_memory_operand" "w")] UNSPECV_LDXIO)))]
353 "nios2_large_constant_memory_operand_p (operands[1])"
355 (sign_extend:SI (unspec_volatile:BH [(match_dup 1)] UNSPECV_LDXIO)))]
357 operands[1] = nios2_split_large_constant_memory_operand (operands[1]);
359 [(set_attr "type" "ld")])
361 (define_insn_and_split "st<bhw>io"
362 [(set (match_operand:BHW 0 "ldstio_memory_operand" "=w")
364 [(match_operand:BHW 1 "reg_or_0_operand" "rM")] UNSPECV_STXIO))]
366 "st<bhw>io\\t%z1, %0"
367 "nios2_large_constant_memory_operand_p (operands[0])"
368 [(set (match_dup 0) (unspec_volatile:BHW [(match_dup 1)] UNSPECV_STXIO))]
370 operands[0] = nios2_split_large_constant_memory_operand (operands[0]);
372 [(set_attr "type" "st")])
375 ;; QI to [HI, SI] extension patterns are collected together
376 (define_mode_iterator QX [HI SI])
378 ;; Zero extension patterns
379 (define_insn_and_split "zero_extendhisi2"
380 [(set (match_operand:SI 0 "register_operand" "=r,r")
381 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
384 andi%.\\t%0, %1, 0xffff
386 "nios2_large_constant_memory_operand_p (operands[1])"
387 [(set (match_dup 0) (zero_extend:SI (match_dup 1)))]
389 operands[1] = nios2_split_large_constant_memory_operand (operands[1]);
391 [(set_attr "type" "and,ld")])
393 (define_insn_and_split "zero_extendqi<mode>2"
394 [(set (match_operand:QX 0 "register_operand" "=r,r")
395 (zero_extend:QX (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
398 andi%.\\t%0, %1, 0xff
400 "nios2_large_constant_memory_operand_p (operands[1])"
401 [(set (match_dup 0) (zero_extend:QX (match_dup 1)))]
403 operands[1] = nios2_split_large_constant_memory_operand (operands[1]);
405 [(set_attr "type" "and,ld")])
407 ;; Sign extension patterns
409 (define_insn_and_split "extendhisi2"
410 [(set (match_operand:SI 0 "register_operand" "=r,r")
411 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
416 "nios2_large_constant_memory_operand_p (operands[1])"
417 [(set (match_dup 0) (sign_extend:SI (match_dup 1)))]
419 operands[1] = nios2_split_large_constant_memory_operand (operands[1]);
421 [(set_attr "type" "alu,ld")])
423 (define_insn_and_split "extendqi<mode>2"
424 [(set (match_operand:QX 0 "register_operand" "=r,r")
425 (sign_extend:QX (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
430 "nios2_large_constant_memory_operand_p (operands[1])"
431 [(set (match_dup 0) (sign_extend:QX (match_dup 1)))]
433 operands[1] = nios2_split_large_constant_memory_operand (operands[1]);
435 [(set_attr "type" "alu,ld")])
437 ;; Split patterns for register alternative cases.
439 [(set (match_operand:SI 0 "register_operand" "")
440 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
443 (and:SI (match_dup 1) (const_int 65535)))
445 (xor:SI (match_dup 0) (const_int 32768)))
447 (plus:SI (match_dup 0) (const_int -32768)))]
448 "operands[1] = gen_lowpart (SImode, operands[1]);")
451 [(set (match_operand:QX 0 "register_operand" "")
452 (sign_extend:QX (match_operand:QI 1 "register_operand" "")))]
455 (and:SI (match_dup 1) (const_int 255)))
457 (xor:SI (match_dup 0) (const_int 128)))
459 (plus:SI (match_dup 0) (const_int -128)))]
460 "operands[0] = gen_lowpart (SImode, operands[0]);
461 operands[1] = gen_lowpart (SImode, operands[1]);")
464 ;; Arithmetic Operations
466 (define_insn "addsi3"
467 [(set (match_operand:SI 0 "register_operand" "=r")
468 (plus:SI (match_operand:SI 1 "register_operand" "%r")
469 (match_operand:SI 2 "add_regimm_operand" "rIT")))]
472 return nios2_add_insn_asm (insn, operands);
474 [(set_attr "type" "add")])
476 (define_insn "subsi3"
477 [(set (match_operand:SI 0 "register_operand" "=r")
478 (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rM")
479 (match_operand:SI 2 "register_operand" "r")))]
481 "sub%.\\t%0, %z1, %2"
482 [(set_attr "type" "sub")])
484 (define_insn "mulsi3"
485 [(set (match_operand:SI 0 "register_operand" "=r")
486 (mult:SI (match_operand:SI 1 "register_operand" "%r")
487 (match_operand:SI 2 "arith_operand" "rI")))]
489 "mul%i2\\t%0, %1, %z2"
490 [(set_attr "type" "mul")])
492 (define_expand "divsi3"
493 [(set (match_operand:SI 0 "register_operand" "=r")
494 (div:SI (match_operand:SI 1 "register_operand" "r")
495 (match_operand:SI 2 "register_operand" "r")))]
500 if (TARGET_FAST_SW_DIV)
502 nios2_emit_expensive_div (operands, SImode);
510 (define_insn "divsi3_insn"
511 [(set (match_operand:SI 0 "register_operand" "=r")
512 (div:SI (match_operand:SI 1 "register_operand" "r")
513 (match_operand:SI 2 "register_operand" "r")))]
516 [(set_attr "type" "div")])
518 (define_insn "udivsi3"
519 [(set (match_operand:SI 0 "register_operand" "=r")
520 (udiv:SI (match_operand:SI 1 "register_operand" "r")
521 (match_operand:SI 2 "register_operand" "r")))]
524 [(set_attr "type" "div")])
526 (define_code_iterator EXTEND [sign_extend zero_extend])
527 (define_code_attr us [(sign_extend "s") (zero_extend "u")])
528 (define_code_attr mul [(sign_extend "mul") (zero_extend "umul")])
530 (define_insn "<us>mulsi3_highpart"
531 [(set (match_operand:SI 0 "register_operand" "=r")
534 (mult:DI (EXTEND:DI (match_operand:SI 1 "register_operand" "r"))
535 (EXTEND:DI (match_operand:SI 2 "register_operand" "r")))
538 "mulx<us><us>\\t%0, %1, %2"
539 [(set_attr "type" "mul")])
541 (define_expand "<mul>sidi3"
542 [(set (match_operand:DI 0 "register_operand" "")
543 (mult:DI (EXTEND:DI (match_operand:SI 1 "register_operand" ""))
544 (EXTEND:DI (match_operand:SI 2 "register_operand" ""))))]
547 rtx hi = gen_reg_rtx (SImode);
548 rtx lo = gen_reg_rtx (SImode);
550 emit_insn (gen_<us>mulsi3_highpart (hi, operands[1], operands[2]));
551 emit_insn (gen_mulsi3 (lo, operands[1], operands[2]));
552 emit_move_insn (gen_lowpart (SImode, operands[0]), lo);
553 emit_move_insn (gen_highpart (SImode, operands[0]), hi);
558 ;; Negate and ones complement
560 (define_insn "negsi2"
561 [(set (match_operand:SI 0 "register_operand" "=r")
562 (neg:SI (match_operand:SI 1 "register_operand" "r")))]
565 if (get_attr_length (insn) == 2)
566 return "neg.n\\t%0, %1";
568 return "sub\\t%0, zero, %1";
570 [(set_attr "type" "neg")])
572 (define_insn "one_cmplsi2"
573 [(set (match_operand:SI 0 "register_operand" "=r")
574 (not:SI (match_operand:SI 1 "register_operand" "r")))]
577 if (get_attr_length (insn) == 2)
578 return "not.n\\t%0, %1";
580 return "nor\\t%0, zero, %1";
582 [(set_attr "type" "not")])
585 ;; Integer logical Operations
587 (define_insn "andsi3"
588 [(set (match_operand:SI 0 "register_operand" "=r")
589 (and:SI (match_operand:SI 1 "register_operand" "%r")
590 (match_operand:SI 2 "and_operand" "rJKP")))]
592 "and%x2%.\\t%0, %1, %y2"
593 [(set_attr "type" "and")])
595 (define_code_iterator LOGICAL [ior xor])
596 (define_code_attr logical_asm [(ior "or") (xor "xor")])
598 (define_insn "<code>si3"
599 [(set (match_operand:SI 0 "register_operand" "=r")
600 (LOGICAL:SI (match_operand:SI 1 "register_operand" "%r")
601 (match_operand:SI 2 "logical_operand" "rJK")))]
603 "<logical_asm>%x2%.\\t%0, %1, %y2"
604 [(set_attr "type" "<logical_asm>")])
606 (define_insn "*norsi3"
607 [(set (match_operand:SI 0 "register_operand" "=r")
608 (and:SI (not:SI (match_operand:SI 1 "register_operand" "%r"))
609 (not:SI (match_operand:SI 2 "register_operand" "r"))))]
612 [(set_attr "type" "alu")])
615 ;; Shift instructions
617 (define_code_iterator SHIFT [ashift ashiftrt lshiftrt rotate])
618 (define_code_attr shift_op [(ashift "ashl") (ashiftrt "ashr")
619 (lshiftrt "lshr") (rotate "rotl")])
620 (define_code_attr shift_asm [(ashift "sll") (ashiftrt "sra")
621 (lshiftrt "srl") (rotate "rol")])
623 (define_insn "<shift_op>si3"
624 [(set (match_operand:SI 0 "register_operand" "=r")
625 (SHIFT:SI (match_operand:SI 1 "register_operand" "r")
626 (match_operand:SI 2 "shift_operand" "rL")))]
628 "<shift_asm>%i2%.\\t%0, %1, %z2"
629 [(set_attr "type" "<shift_asm>")])
631 (define_insn "rotrsi3"
632 [(set (match_operand:SI 0 "register_operand" "=r")
633 (rotatert:SI (match_operand:SI 1 "register_operand" "r")
634 (match_operand:SI 2 "register_operand" "r")))]
637 [(set_attr "type" "ror")])
639 ;; Nios II R2 Bit Manipulation Extension (BMX), provides
640 ;; bit merge/insertion/extraction instructions.
642 (define_insn "*merge"
643 [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r")
644 (match_operand:SI 1 "const_shift_operand" "L")
645 (match_operand:SI 2 "const_shift_operand" "L"))
646 (zero_extract:SI (match_operand:SI 3 "register_operand" "r")
647 (match_dup 1) (match_dup 2)))]
650 operands[4] = GEN_INT (INTVAL (operands[1]) + INTVAL (operands[2]) - 1);
651 return "merge\\t%0, %3, %4, %2";
653 [(set_attr "type" "alu")])
656 [(set (match_operand:SI 0 "register_operand" "=r")
657 (zero_extract:SI (match_operand:SI 1 "register_operand" "r")
658 (match_operand:SI 2 "const_shift_operand" "L")
659 (match_operand:SI 3 "const_shift_operand" "L")))]
662 operands[4] = GEN_INT (INTVAL (operands[2]) + INTVAL (operands[3]) - 1);
663 return "extract\\t%0, %1, %4, %3";
665 [(set_attr "type" "alu")])
668 [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r")
669 (match_operand:SI 1 "const_shift_operand" "L")
670 (match_operand:SI 2 "const_shift_operand" "L"))
671 (match_operand:SI 3 "reg_or_0_operand" "rM"))]
674 operands[4] = GEN_INT (INTVAL (operands[1]) + INTVAL (operands[2]) - 1);
675 return "insert\\t%0, %z3, %4, %2";
677 [(set_attr "type" "alu")])
681 ;; Floating point instructions
683 ;; Mode iterator for single/double float
684 (define_mode_iterator F [SF DF])
685 (define_mode_attr f [(SF "s") (DF "d")])
687 ;; Basic arithmetic instructions
688 (define_code_iterator FOP3 [plus minus mult div])
689 (define_code_attr fop3 [(plus "add") (minus "sub") (mult "mul") (div "div")])
691 (define_insn "<fop3><mode>3"
692 [(set (match_operand:F 0 "register_operand" "=r")
693 (FOP3:F (match_operand:F 1 "register_operand" "r")
694 (match_operand:F 2 "register_operand" "r")))]
695 "nios2_fpu_insn_enabled (n2fpu_f<fop3><f>)"
696 { return nios2_fpu_insn_asm (n2fpu_f<fop3><f>); }
697 [(set_attr "type" "custom")])
699 ;; Floating point min/max operations
700 (define_code_iterator SMINMAX [smin smax])
701 (define_code_attr minmax [(smin "min") (smax "max")])
702 (define_insn "<code><mode>3"
703 [(set (match_operand:F 0 "register_operand" "=r")
704 (SMINMAX:F (match_operand:F 1 "register_operand" "r")
705 (match_operand:F 2 "register_operand" "r")))]
706 "nios2_fpu_insn_enabled (n2fpu_f<minmax><f>)"
707 { return nios2_fpu_insn_asm (n2fpu_f<minmax><f>); }
708 [(set_attr "type" "custom")])
710 ;; These 2-operand FP operations can be collected together
711 (define_code_iterator FOP2 [abs neg sqrt])
712 (define_insn "<code><mode>2"
713 [(set (match_operand:F 0 "register_operand" "=r")
714 (FOP2:F (match_operand:F 1 "register_operand" "r")))]
715 "nios2_fpu_insn_enabled (n2fpu_f<code><f>)"
716 { return nios2_fpu_insn_asm (n2fpu_f<code><f>); }
717 [(set_attr "type" "custom")])
719 ;; X, Y register access instructions
720 (define_insn "nios2_fwrx"
721 [(unspec_volatile [(match_operand:DF 0 "register_operand" "r")] UNSPECV_FWRX)]
722 "nios2_fpu_insn_enabled (n2fpu_fwrx)"
723 { return nios2_fpu_insn_asm (n2fpu_fwrx); }
724 [(set_attr "type" "custom")])
726 (define_insn "nios2_fwry"
727 [(unspec_volatile [(match_operand:SF 0 "register_operand" "r")] UNSPECV_FWRY)]
728 "nios2_fpu_insn_enabled (n2fpu_fwry)"
729 { return nios2_fpu_insn_asm (n2fpu_fwry); }
730 [(set_attr "type" "custom")])
732 ;; The X, Y read insns uses an int iterator
733 (define_int_iterator UNSPEC_READ_XY [UNSPECV_FRDXLO UNSPECV_FRDXHI
735 (define_int_attr read_xy [(UNSPECV_FRDXLO "frdxlo") (UNSPECV_FRDXHI "frdxhi")
736 (UNSPECV_FRDY "frdy")])
737 (define_insn "nios2_<read_xy>"
738 [(set (match_operand:SF 0 "register_operand" "=r")
739 (unspec_volatile:SF [(const_int 0)] UNSPEC_READ_XY))]
740 "nios2_fpu_insn_enabled (n2fpu_<read_xy>)"
741 { return nios2_fpu_insn_asm (n2fpu_<read_xy>); }
742 [(set_attr "type" "custom")])
744 ;; Various math functions
745 (define_int_iterator MATHFUNC
746 [UNSPEC_FCOS UNSPEC_FSIN UNSPEC_FTAN UNSPEC_FATAN UNSPEC_FEXP UNSPEC_FLOG])
747 (define_int_attr mathfunc [(UNSPEC_FCOS "cos") (UNSPEC_FSIN "sin")
748 (UNSPEC_FTAN "tan") (UNSPEC_FATAN "atan")
749 (UNSPEC_FEXP "exp") (UNSPEC_FLOG "log")])
751 (define_insn "<mathfunc><mode>2"
752 [(set (match_operand:F 0 "register_operand" "=r")
753 (unspec:F [(match_operand:F 1 "register_operand" "r")] MATHFUNC))]
754 "nios2_fpu_insn_enabled (n2fpu_f<mathfunc><f>)"
755 { return nios2_fpu_insn_asm (n2fpu_f<mathfunc><f>); }
756 [(set_attr "type" "custom")])
758 ;; Converting between floating point and fixed point
760 (define_code_iterator FLOAT [float unsigned_float])
761 (define_code_iterator FIX [fix unsigned_fix])
763 (define_code_attr conv_op [(float "float") (unsigned_float "floatuns")
764 (fix "fix") (unsigned_fix "fixuns")])
765 (define_code_attr i [(float "i") (unsigned_float "u")
766 (fix "i") (unsigned_fix "u")])
768 ;; Integer to float conversions
769 (define_insn "<conv_op>si<mode>2"
770 [(set (match_operand:F 0 "register_operand" "=r")
771 (FLOAT:F (match_operand:SI 1 "register_operand" "r")))]
772 "nios2_fpu_insn_enabled (n2fpu_float<i><f>)"
773 { return nios2_fpu_insn_asm (n2fpu_float<i><f>); }
774 [(set_attr "type" "custom")])
776 ;; Float to integer conversions
777 (define_insn "<conv_op>_trunc<mode>si2"
778 [(set (match_operand:SI 0 "register_operand" "=r")
779 (FIX:SI (match_operand:F 1 "general_operand" "r")))]
780 "nios2_fpu_insn_enabled (n2fpu_fix<f><i>)"
781 { return nios2_fpu_insn_asm (n2fpu_fix<f><i>); }
782 [(set_attr "type" "custom")])
784 (define_insn "lroundsfsi2"
785 [(set (match_operand:SI 0 "register_operand" "=r")
786 (unspec:SI [(match_operand:SF 1 "general_operand" "r")] UNSPEC_ROUND))]
787 "nios2_fpu_insn_enabled (n2fpu_round)"
788 { return nios2_fpu_insn_asm (n2fpu_round); }
789 [(set_attr "type" "custom")])
791 (define_insn "extendsfdf2"
792 [(set (match_operand:DF 0 "register_operand" "=r")
793 (float_extend:DF (match_operand:SF 1 "general_operand" "r")))]
794 "nios2_fpu_insn_enabled (n2fpu_fextsd)"
795 { return nios2_fpu_insn_asm (n2fpu_fextsd); }
796 [(set_attr "type" "custom")])
798 (define_insn "truncdfsf2"
799 [(set (match_operand:SF 0 "register_operand" "=r")
800 (float_truncate:SF (match_operand:DF 1 "general_operand" "r")))]
801 "nios2_fpu_insn_enabled (n2fpu_ftruncds)"
802 { return nios2_fpu_insn_asm (n2fpu_ftruncds); }
803 [(set_attr "type" "custom")])
807 ;; Prologue, Epilogue and Return
809 (define_expand "prologue"
813 nios2_expand_prologue ();
817 (define_expand "epilogue"
821 nios2_expand_epilogue (false);
825 (define_expand "sibcall_epilogue"
829 nios2_expand_epilogue (true);
833 (define_expand "return"
835 "nios2_can_use_return_insn ()"
837 if (nios2_expand_return ())
841 (define_insn "simple_return"
845 [(set_attr "type" "control")])
847 ;; Block any insns from being moved before this point, since the
848 ;; profiling call to mcount can use various registers that aren't
849 ;; saved or used to pass arguments.
851 (define_insn "blockage"
852 [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
855 [(set_attr "type" "unknown")
856 (set_attr "length" "0")])
858 ;; This is used in compiling the unwind routines.
859 (define_expand "eh_return"
860 [(use (match_operand 0 "general_operand"))]
863 if (GET_MODE (operands[0]) != Pmode)
864 operands[0] = convert_to_mode (Pmode, operands[0], 0);
865 emit_insn (gen_eh_set_ra (operands[0]));
869 ;; Modify the return address for EH return. We can't expand this
870 ;; until we know where it will be put in the stack frame.
872 (define_insn_and_split "eh_set_ra"
873 [(unspec [(match_operand:SI 0 "register_operand" "r")] UNSPEC_EH_RETURN)
874 (clobber (match_scratch:SI 1 "=&r"))]
880 nios2_set_return_address (operands[0], operands[1]);
887 ; Note that the assembler fixes up any out-of-range branch instructions not
888 ; caught by the compiler branch shortening code. The sequence emitted by
889 ; the assembler can be very inefficient, but it is correct for PIC code.
890 ; For non-PIC we are better off converting to an absolute JMPI.
892 ; Direct calls and sibcalls use the CALL and JMPI instructions, respectively.
893 ; These instructions have an immediate operand that specifies the low 28 bits
894 ; of the PC, effectively allowing direct calls within a 256MB memory segment.
895 ; Per the Nios II Processor Reference Handbook, the linker is not required to
896 ; check or adjust for overflow.
898 (define_insn "indirect_jump"
899 [(set (pc) (match_operand:SI 0 "register_operand" "c"))]
902 [(set_attr "type" "control")])
906 (label_ref (match_operand 0 "" "")))]
909 if (get_attr_length (insn) == 2)
911 else if (get_attr_length (insn) == 4)
916 [(set_attr "type" "control")
919 (and (match_test "TARGET_HAS_CDX")
920 (and (ge (minus (match_dup 0) (pc)) (const_int -1022))
921 (le (minus (match_dup 0) (pc)) (const_int 1022))))
924 (ior (match_test "flag_pic")
925 (and (ge (minus (match_dup 0) (pc)) (const_int -32764))
926 (le (minus (match_dup 0) (pc)) (const_int 32764))))
930 (define_expand "call"
931 [(parallel [(call (match_operand 0 "" "")
932 (match_operand 1 "" ""))
933 (clobber (reg:SI RA_REGNO))])]
935 "nios2_adjust_call_address (&operands[0], NULL_RTX);")
937 (define_expand "call_value"
938 [(parallel [(set (match_operand 0 "" "")
939 (call (match_operand 1 "" "")
940 (match_operand 2 "" "")))
941 (clobber (reg:SI RA_REGNO))])]
943 "nios2_adjust_call_address (&operands[1], NULL_RTX);")
946 [(call (mem:QI (match_operand:SI 0 "call_operand" "i,r"))
947 (match_operand 1 "" ""))
948 (clobber (reg:SI RA_REGNO))]
953 [(set_attr "type" "control")])
955 (define_insn "*call_value"
956 [(set (match_operand 0 "" "")
957 (call (mem:QI (match_operand:SI 1 "call_operand" "i,r"))
958 (match_operand 2 "" "")))
959 (clobber (reg:SI RA_REGNO))]
964 [(set_attr "type" "control")])
966 (define_expand "sibcall"
967 [(parallel [(call (match_operand 0 "" "")
968 (match_operand 1 "" ""))
971 "nios2_adjust_call_address (&operands[0], NULL_RTX);")
973 (define_expand "sibcall_value"
974 [(parallel [(set (match_operand 0 "" "")
975 (call (match_operand 1 "" "")
976 (match_operand 2 "" "")))
979 "nios2_adjust_call_address (&operands[1], NULL_RTX);")
981 (define_insn "sibcall_internal"
982 [(call (mem:QI (match_operand:SI 0 "call_operand" "i,j"))
983 (match_operand 1 "" ""))
989 [(set_attr "type" "control")])
991 (define_insn "sibcall_value_internal"
992 [(set (match_operand 0 "register_operand" "")
993 (call (mem:QI (match_operand:SI 1 "call_operand" "i,j"))
994 (match_operand 2 "" "")))
1000 [(set_attr "type" "control")])
1002 (define_expand "tablejump"
1003 [(parallel [(set (pc) (match_operand 0 "register_operand" "r"))
1004 (use (label_ref (match_operand 1 "" "")))])]
1009 /* Hopefully, CSE will eliminate this copy. */
1010 rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
1011 rtx reg2 = gen_reg_rtx (SImode);
1013 emit_insn (gen_addsi3 (reg2, operands[0], reg1));
1018 (define_insn "*tablejump"
1020 (match_operand:SI 0 "register_operand" "c"))
1021 (use (label_ref (match_operand 1 "" "")))]
1024 [(set_attr "type" "control")])
1027 ;; cstore, cbranch patterns
1029 (define_mode_iterator CM [SI SF DF])
1031 (define_expand "cstore<mode>4"
1032 [(set (match_operand:SI 0 "register_operand" "=r")
1033 (match_operator:SI 1 "expandable_comparison_operator"
1034 [(match_operand:CM 2 "register_operand")
1035 (match_operand:CM 3 "nonmemory_operand")]))]
1038 if (!nios2_validate_compare (<MODE>mode, &operands[1], &operands[2],
1043 (define_expand "cbranch<mode>4"
1046 (match_operator 0 "expandable_comparison_operator"
1047 [(match_operand:CM 1 "register_operand")
1048 (match_operand:CM 2 "nonmemory_operand")])
1049 (label_ref (match_operand 3 ""))
1053 if (!nios2_validate_compare (<MODE>mode, &operands[0], &operands[1],
1056 if (GET_MODE_CLASS (<MODE>mode) == MODE_FLOAT
1057 || !reg_or_0_operand (operands[2], <MODE>mode))
1059 rtx condreg = gen_reg_rtx (SImode);
1060 emit_insn (gen_cstore<mode>4
1061 (condreg, operands[0], operands[1], operands[2]));
1062 operands[1] = condreg;
1063 operands[2] = const0_rtx;
1064 operands[0] = gen_rtx_fmt_ee (NE, VOIDmode, condreg, const0_rtx);
1068 (define_insn "nios2_cbranch"
1071 (match_operator 0 "ordered_comparison_operator"
1072 [(match_operand:SI 1 "reg_or_0_operand" "rM")
1073 (match_operand:SI 2 "reg_or_0_operand" "rM")])
1074 (label_ref (match_operand 3 "" ""))
1078 if (get_attr_length (insn) == 2)
1079 return "b%0z.n\t%z1, %l3";
1080 else if (get_attr_length (insn) == 4)
1081 return "b%0\t%z1, %z2, %l3";
1082 else if (get_attr_length (insn) == 6)
1083 return "b%R0z.n\t%z1, .+6;jmpi\t%l3";
1085 return "b%R0\t%z1, %z2, .+8;jmpi\t%l3";
1087 [(set_attr "type" "control")
1088 (set (attr "length")
1090 [(and (match_test "nios2_cdx_narrow_form_p (insn)")
1091 (ge (minus (match_dup 3) (pc)) (const_int -126))
1092 (le (minus (match_dup 3) (pc)) (const_int 126)))
1094 (ior (match_test "flag_pic")
1095 (and (ge (minus (match_dup 3) (pc)) (const_int -32764))
1096 (le (minus (match_dup 3) (pc)) (const_int 32764))))
1098 (match_test "nios2_cdx_narrow_form_p (insn)")
1102 ;; Floating point comparisons
1103 (define_code_iterator FCMP [eq ne gt ge le lt])
1104 (define_insn "nios2_s<code><mode>"
1105 [(set (match_operand:SI 0 "register_operand" "=r")
1106 (FCMP:SI (match_operand:F 1 "register_operand" "r")
1107 (match_operand:F 2 "register_operand" "r")))]
1108 "nios2_fpu_insn_enabled (n2fpu_fcmp<code><f>)"
1109 { return nios2_fpu_insn_asm (n2fpu_fcmp<code><f>); }
1110 [(set_attr "type" "custom")])
1112 ;; Integer comparisons
1114 (define_code_iterator EQNE [eq ne])
1115 (define_insn "nios2_cmp<code>"
1116 [(set (match_operand:SI 0 "register_operand" "=r")
1117 (EQNE:SI (match_operand:SI 1 "register_operand" "%r")
1118 (match_operand:SI 2 "arith_operand" "rI")))]
1120 "cmp<code>%i2\\t%0, %1, %z2"
1121 [(set_attr "type" "alu")])
1123 (define_code_iterator SCMP [ge lt])
1124 (define_insn "nios2_cmp<code>"
1125 [(set (match_operand:SI 0 "register_operand" "=r")
1126 (SCMP:SI (match_operand:SI 1 "reg_or_0_operand" "rM")
1127 (match_operand:SI 2 "arith_operand" "rI")))]
1129 "cmp<code>%i2\\t%0, %z1, %z2"
1130 [(set_attr "type" "alu")])
1132 (define_code_iterator UCMP [geu ltu])
1133 (define_insn "nios2_cmp<code>"
1134 [(set (match_operand:SI 0 "register_operand" "=r")
1135 (UCMP:SI (match_operand:SI 1 "reg_or_0_operand" "rM")
1136 (match_operand:SI 2 "uns_arith_operand" "rJ")))]
1138 "cmp<code>%u2\\t%0, %z1, %z2"
1139 [(set_attr "type" "alu")])
1143 ;; Custom instruction patterns. The operands are intentionally
1144 ;; mode-less, to serve as generic carriers of all Altera defined
1145 ;; built-in instruction/function types.
1147 (define_insn "custom_nxx"
1148 [(unspec_volatile [(match_operand 0 "custom_insn_opcode" "N")
1149 (match_operand 1 "reg_or_0_operand" "rM")
1150 (match_operand 2 "reg_or_0_operand" "rM")]
1151 UNSPECV_CUSTOM_NXX)]
1153 "custom\\t%0, zero, %z1, %z2"
1154 [(set_attr "type" "custom")])
1156 (define_insn "custom_xnxx"
1157 [(set (match_operand 0 "register_operand" "=r")
1158 (unspec_volatile [(match_operand 1 "custom_insn_opcode" "N")
1159 (match_operand 2 "reg_or_0_operand" "rM")
1160 (match_operand 3 "reg_or_0_operand" "rM")]
1161 UNSPECV_CUSTOM_XNXX))]
1163 "custom\\t%1, %0, %z2, %z3"
1164 [(set_attr "type" "custom")])
1173 [(set_attr "type" "nop")])
1175 ;; Connect 'sync' to 'memory_barrier' standard expand name
1176 (define_expand "memory_barrier"
1180 emit_insn (gen_sync ());
1184 ;; For the nios2 __builtin_sync built-in function
1185 (define_expand "sync"
1187 (unspec:BLK [(match_dup 0)] UNSPEC_SYNC))]
1190 operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
1191 MEM_VOLATILE_P (operands[0]) = 1;
1194 (define_insn "*sync_insn"
1195 [(set (match_operand:BLK 0 "" "")
1196 (unspec:BLK [(match_dup 0)] UNSPEC_SYNC))]
1199 [(set_attr "type" "control")])
1201 (define_insn "rdctl"
1202 [(set (match_operand:SI 0 "register_operand" "=r")
1203 (unspec_volatile:SI [(match_operand:SI 1 "rdwrctl_operand" "O")]
1207 [(set_attr "type" "control")])
1209 (define_insn "wrctl"
1210 [(unspec_volatile:SI [(match_operand:SI 0 "rdwrctl_operand" "O")
1211 (match_operand:SI 1 "reg_or_0_operand" "rM")]
1214 "wrctl\\tctl%0, %z1"
1215 [(set_attr "type" "control")])
1217 (define_insn "rdprs"
1218 [(set (match_operand:SI 0 "register_operand" "=r")
1219 (unspec_volatile:SI [(match_operand:SI 1 "rdwrctl_operand" "O")
1220 (match_operand:SI 2 "arith_operand" "U")]
1223 "rdprs\\t%0, %1, %2"
1224 [(set_attr "type" "control")])
1226 ;; Cache Instructions
1228 (define_insn "flushd"
1229 [(unspec_volatile:SI [(match_operand:SI 0 "ldstio_memory_operand" "w")]
1233 [(set_attr "type" "control")])
1235 (define_insn "flushda"
1236 [(unspec_volatile:SI [(match_operand:SI 0 "ldstio_memory_operand" "w")]
1240 [(set_attr "type" "control")])
1244 (define_insn "wrpie"
1245 [(set (match_operand:SI 0 "register_operand" "=r")
1246 (unspec_volatile:SI [(match_operand:SI 1 "register_operand" "r")]
1250 [(set_attr "type" "control")])
1253 [(unspec:VOID [(match_operand 0 "const_int_operand" "i")]
1257 [(set_attr "type" "control")])
1261 [(trap_if (const_int 1) (const_int 3))]
1264 [(set_attr "type" "control")])
1266 (define_insn "ctrapsi4"
1267 [(trap_if (match_operator 0 "ordered_comparison_operator"
1268 [(match_operand:SI 1 "reg_or_0_operand" "rM")
1269 (match_operand:SI 2 "reg_or_0_operand" "rM")])
1270 (match_operand 3 "const_int_operand" "i"))]
1273 if (get_attr_length (insn) == 6)
1274 return "b%R0\\t%z1, %z2, 1f\;trap.n\\t%3\;1:";
1276 return "b%R0\\t%z1, %z2, 1f\;trap\\t%3\;1:";
1278 [(set_attr "type" "control")
1279 (set (attr "length")
1280 (if_then_else (match_test "nios2_cdx_narrow_form_p (insn)")
1281 (const_int 6) (const_int 8)))])
1283 ;; Load the GOT register.
1284 (define_insn "load_got_register"
1285 [(set (match_operand:SI 0 "register_operand" "=&r")
1286 (unspec:SI [(const_int 0)] UNSPEC_LOAD_GOT_REGISTER))
1287 (set (match_operand:SI 1 "register_operand" "=r")
1288 (unspec:SI [(const_int 0)] UNSPEC_LOAD_GOT_REGISTER))]
1292 \\tmovhi\\t%1, %%hiadj(_gp_got - 1b)
1293 \\taddi\\t%1, %1, %%lo(_gp_got - 1b)"
1294 [(set_attr "length" "12")])
1296 ;; Read thread pointer register
1297 (define_expand "get_thread_pointersi"
1298 [(match_operand:SI 0 "register_operand" "=r")]
1301 emit_move_insn (operands[0], gen_rtx_REG (Pmode, TP_REGNO));
1305 ;; Synchronization Primitives
1308 ;; Include the ldwm/stwm/push.n/pop.n patterns and peepholes.
1309 (include "ldstwm.md")