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.
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 (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
38 ;; Target register definitions
39 (STATIC_CHAIN_REGNUM 12)
40 (STACK_POINTER_REGNUM 27)
41 (HARD_FRAME_POINTER_REGNUM 28)
43 (FRAME_POINTER_REGNUM 38)
44 (ARG_POINTER_REGNUM 39)
45 (FIRST_PSEUDO_REGISTER 40)
49 ;; Enumeration of UNSPECs
51 (define_c_enum "unspecv" [
66 (define_c_enum "unspec" [
74 UNSPEC_LOAD_GOT_REGISTER
88 ;; Instruction scheduler
90 ; No schedule info is currently available, using an assumption that no
91 ; instruction can use the results of the previous instruction without
94 ; length of an instruction (in bytes)
95 (define_attr "length" "" (const_int 4))
97 "unknown,complex,control,alu,cond_alu,st,ld,shift,mul,div,custom"
98 (const_string "complex"))
100 (define_asm_attributes
101 [(set_attr "length" "4")
102 (set_attr "type" "complex")])
104 (define_automaton "nios2")
105 (automata_option "v")
106 ;(automata_option "no-minimization")
107 (automata_option "ndfa")
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.
114 (define_cpu_unit "cpu" "nios2")
116 (define_insn_reservation "complex" 1
117 (eq_attr "type" "complex")
120 (define_insn_reservation "control" 1
121 (eq_attr "type" "control")
124 (define_insn_reservation "alu" 1
125 (eq_attr "type" "alu")
128 (define_insn_reservation "cond_alu" 1
129 (eq_attr "type" "cond_alu")
132 (define_insn_reservation "st" 1
133 (eq_attr "type" "st")
136 (define_insn_reservation "custom" 1
137 (eq_attr "type" "custom")
140 ; shifts, muls and lds have three cycle latency
141 (define_insn_reservation "ld" 3
142 (eq_attr "type" "ld")
145 (define_insn_reservation "shift" 3
146 (eq_attr "type" "shift")
149 (define_insn_reservation "mul" 3
150 (eq_attr "type" "mul")
153 (define_insn_reservation "div" 1
154 (eq_attr "type" "div")
157 (include "predicates.md")
158 (include "constraints.md")
163 (define_mode_iterator M [QI HI SI])
165 (define_expand "mov<mode>"
166 [(set (match_operand:M 0 "nonimmediate_operand" "")
167 (match_operand:M 1 "general_operand" ""))]
170 if (nios2_emit_move_sequence (operands, <MODE>mode))
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))"
184 [(set_attr "type" "st,ld,alu,alu")])
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))"
196 [(set_attr "type" "st,ld,alu,alu")])
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))"
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")])
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")])
221 (define_insn "ld<bhw_uns>io"
222 [(set (match_operand:BHW 0 "register_operand" "=r")
224 [(match_operand:BHW 1 "memory_operand" "m")] UNSPECV_LDXIO))]
226 "ld<bhw_uns>io\\t%0, %1"
227 [(set_attr "type" "ld")])
229 (define_expand "ld<bh>io"
230 [(set (match_operand:BH 0 "register_operand" "=r")
231 (match_operand:BH 1 "memory_operand" "m"))]
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)));
240 (define_insn "ld<bh>io_signed"
241 [(set (match_operand:SI 0 "register_operand" "=r")
244 [(match_operand:BH 1 "memory_operand" "m")] UNSPECV_LDXIO)))]
247 [(set_attr "type" "ld")])
249 (define_insn "st<bhw>io"
250 [(set (match_operand:BHW 0 "memory_operand" "=m")
252 [(match_operand:BHW 1 "reg_or_0_operand" "rM")] UNSPECV_STXIO))]
254 "st<bhw>io\\t%z1, %0"
255 [(set_attr "type" "st")])
258 ;; QI to [HI, SI] extension patterns are collected together
259 (define_mode_iterator QX [HI SI])
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")))]
267 andi\\t%0, %1, 0xffff
269 [(set_attr "type" "alu,ld")])
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")))]
278 [(set_attr "type" "alu,ld")])
280 ;; Sign extension patterns
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")))]
289 [(set_attr "type" "alu,ld")])
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")))]
298 [(set_attr "type" "alu,ld")])
300 ;; Split patterns for register alternative cases.
302 [(set (match_operand:SI 0 "register_operand" "")
303 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
306 (and:SI (match_dup 1) (const_int 65535)))
308 (xor:SI (match_dup 0) (const_int 32768)))
310 (plus:SI (match_dup 0) (const_int -32768)))]
311 "operands[1] = gen_lowpart (SImode, operands[1]);")
314 [(set (match_operand:QX 0 "register_operand" "")
315 (sign_extend:QX (match_operand:QI 1 "register_operand" "")))]
318 (and:SI (match_dup 1) (const_int 255)))
320 (xor:SI (match_dup 0) (const_int 128)))
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]);")
327 ;; Arithmetic Operations
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")))]
334 "add%i2\\t%0, %1, %z2"
335 [(set_attr "type" "alu")])
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")))]
343 [(set_attr "type" "alu")])
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")))]
350 "mul%i2\\t%0, %1, %z2"
351 [(set_attr "type" "mul")])
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")))]
361 if (TARGET_FAST_SW_DIV)
363 nios2_emit_expensive_div (operands, SImode);
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")))]
377 [(set_attr "type" "div")])
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")))]
385 [(set_attr "type" "div")])
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")])
391 (define_insn "<us>mulsi3_highpart"
392 [(set (match_operand:SI 0 "register_operand" "=r")
395 (mult:DI (EXTEND:DI (match_operand:SI 1 "register_operand" "r"))
396 (EXTEND:DI (match_operand:SI 2 "register_operand" "r")))
399 "mulx<us><us>\\t%0, %1, %2"
400 [(set_attr "type" "mul")])
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" ""))))]
408 rtx hi = gen_reg_rtx (SImode);
409 rtx lo = gen_reg_rtx (SImode);
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);
419 ;; Negate and ones complement
421 (define_insn "negsi2"
422 [(set (match_operand:SI 0 "register_operand" "=r")
423 (neg:SI (match_operand:SI 1 "register_operand" "r")))]
426 [(set_attr "type" "alu")])
428 (define_insn "one_cmplsi2"
429 [(set (match_operand:SI 0 "register_operand" "=r")
430 (not:SI (match_operand:SI 1 "register_operand" "r")))]
433 [(set_attr "type" "alu")])
436 ;; Integer logical Operations
438 (define_code_iterator LOGICAL [and ior xor])
439 (define_code_attr logical_asm [(and "and") (ior "or") (xor "xor")])
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")))]
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")])
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"))))]
458 [(set_attr "type" "alu")])
461 ;; Shift instructions
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")])
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")))]
474 "<shift_asm>%i2\\t%0, %1, %z2"
475 [(set_attr "type" "shift")])
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")))]
483 [(set_attr "type" "shift")])
486 ;; Floating point instructions
488 ;; Mode iterator for single/double float
489 (define_mode_iterator F [SF DF])
490 (define_mode_attr f [(SF "s") (DF "d")])
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")])
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")])
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")])
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")])
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")])
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")])
537 ;; The X, Y read insns uses an int iterator
538 (define_int_iterator UNSPEC_READ_XY [UNSPECV_FRDXLO UNSPECV_FRDXHI
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")])
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")])
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")])
563 ;; Converting between floating point and fixed point
565 (define_code_iterator FLOAT [float unsigned_float])
566 (define_code_iterator FIX [fix unsigned_fix])
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")])
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")])
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")])
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")])
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")])
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")])
612 ;; Prologue, Epilogue and Return
614 (define_expand "prologue"
618 nios2_expand_prologue ();
622 (define_expand "epilogue"
626 nios2_expand_epilogue (false);
630 (define_expand "sibcall_epilogue"
634 nios2_expand_epilogue (true);
638 (define_insn "return"
640 "nios2_can_use_return_insn ()"
643 (define_insn "simple_return"
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.
652 (define_insn "blockage"
653 [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
656 [(set_attr "type" "unknown")
657 (set_attr "length" "0")])
659 ;; This is used in compiling the unwind routines.
660 (define_expand "eh_return"
661 [(use (match_operand 0 "general_operand"))]
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]));
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.
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"))]
681 nios2_set_return_address (operands[0], operands[1]);
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.
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.
699 (define_insn "indirect_jump"
700 [(set (pc) (match_operand:SI 0 "register_operand" "r"))]
703 [(set_attr "type" "control")])
707 (label_ref (match_operand 0 "" "")))]
710 if (flag_pic || get_attr_length (insn) == 4)
715 [(set_attr "type" "control")
718 (and (ge (minus (match_dup 0) (pc)) (const_int -32768))
719 (le (minus (match_dup 0) (pc)) (const_int 32764)))
724 (define_expand "call"
725 [(parallel [(call (match_operand 0 "" "")
726 (match_operand 1 "" ""))
727 (clobber (reg:SI RA_REGNO))])]
729 "nios2_adjust_call_address (&operands[0]);")
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))])]
737 "nios2_adjust_call_address (&operands[1]);")
740 [(call (mem:QI (match_operand:SI 0 "call_operand" "i,r"))
741 (match_operand 1 "" ""))
742 (clobber (reg:SI RA_REGNO))]
747 [(set_attr "type" "control")])
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))]
758 [(set_attr "type" "control")])
760 (define_expand "sibcall"
761 [(parallel [(call (match_operand 0 "" "")
762 (match_operand 1 "" ""))
765 "nios2_adjust_call_address (&operands[0]);")
767 (define_expand "sibcall_value"
768 [(parallel [(set (match_operand 0 "" "")
769 (call (match_operand 1 "" "")
770 (match_operand 2 "" "")))
773 "nios2_adjust_call_address (&operands[1]);")
775 (define_insn "*sibcall"
776 [(call (mem:QI (match_operand:SI 0 "call_operand" "i,j"))
777 (match_operand 1 "" ""))
783 [(set_attr "type" "control")])
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 "" "")))
794 [(set_attr "type" "control")])
796 (define_expand "tablejump"
797 [(parallel [(set (pc) (match_operand 0 "register_operand" "r"))
798 (use (label_ref (match_operand 1 "" "")))])]
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);
807 emit_insn (gen_addsi3 (reg2, operands[0], reg1));
812 (define_insn "*tablejump"
814 (match_operand:SI 0 "register_operand" "r"))
815 (use (label_ref (match_operand 1 "" "")))]
818 [(set_attr "type" "control")])
821 ;; cstore, cbranch patterns
823 (define_mode_iterator CM [SI SF DF])
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")]))]
832 if (!nios2_validate_compare (<MODE>mode, &operands[1], &operands[2],
837 (define_expand "cbranch<mode>4"
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 ""))
847 if (!nios2_validate_compare (<MODE>mode, &operands[0], &operands[1],
850 if (GET_MODE_CLASS (<MODE>mode) == MODE_FLOAT
851 || !reg_or_0_operand (operands[2], <MODE>mode))
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);
862 (define_insn "nios2_cbranch"
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 "" ""))
872 if (flag_pic || get_attr_length (insn) == 4)
873 return "b%0\t%z1, %z2, %l3";
875 return "b%R0\t%z1, %z2, .+8;jmpi\t%l3";
877 [(set_attr "type" "control")
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)))])
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")])
894 ;; Integer comparisons
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")))]
902 "cmp<code>%i2\\t%0, %1, %z2"
903 [(set_attr "type" "alu")])
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")))]
911 "cmp<code>%i2\\t%0, %z1, %z2"
912 [(set_attr "type" "alu")])
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")))]
920 "cmp<code>%i2\\t%0, %z1, %z2"
921 [(set_attr "type" "alu")])
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.
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")]
935 "custom\\t%0, zero, %z1, %z2"
936 [(set_attr "type" "custom")])
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))]
945 "custom\\t%1, %0, %z2, %z3"
946 [(set_attr "type" "custom")])
955 [(set_attr "type" "alu")])
957 ;; Connect 'sync' to 'memory_barrier' standard expand name
958 (define_expand "memory_barrier"
962 emit_insn (gen_sync ());
966 ;; For the nios2 __builtin_sync built-in function
967 (define_expand "sync"
969 (unspec:BLK [(match_dup 0)] UNSPEC_SYNC))]
972 operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
973 MEM_VOLATILE_P (operands[0]) = 1;
976 (define_insn "*sync_insn"
977 [(set (match_operand:BLK 0 "" "")
978 (unspec:BLK [(match_dup 0)] UNSPEC_SYNC))]
981 [(set_attr "type" "control")])
984 [(set (match_operand:SI 0 "register_operand" "=r")
985 (unspec_volatile:SI [(match_operand:SI 1 "rdwrctl_operand" "O")]
989 [(set_attr "type" "control")])
992 [(unspec_volatile:SI [(match_operand:SI 0 "rdwrctl_operand" "O")
993 (match_operand:SI 1 "reg_or_0_operand" "rM")]
997 [(set_attr "type" "control")])
1001 [(trap_if (const_int 1) (const_int 3))]
1004 [(set_attr "type" "control")])
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"))]
1012 "b%R0\\t%z1, %z2, 1f\;break\\t%3\;1:"
1013 [(set_attr "type" "control")
1014 (set_attr "length" "8")])
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))]
1025 \\tmovhi\\t%1, %%hiadj(_gp_got - 1b)
1026 \\taddi\\t%1, %1, %%lo(_gp_got - 1b)"
1027 [(set_attr "length" "12")])
1029 ;; Read thread pointer register
1030 (define_expand "get_thread_pointersi"
1031 [(match_operand:SI 0 "register_operand" "=r")]
1034 emit_move_insn (operands[0], gen_rtx_REG (Pmode, TP_REGNO));