163d1a8abSmrg;; Machine Description for Altera Nios II.
2*ec02198aSmrg;; Copyright (C) 2012-2020 Free Software Foundation, Inc.
363d1a8abSmrg;; Contributed by Jonah Graham (jgraham@altera.com) and
463d1a8abSmrg;; Will Reece (wreece@altera.com).
563d1a8abSmrg;; Contributed by Mentor Graphics, Inc.
663d1a8abSmrg;;
763d1a8abSmrg;; This file is part of GCC.
863d1a8abSmrg;;
963d1a8abSmrg;; GCC is free software; you can redistribute it and/or modify
1063d1a8abSmrg;; it under the terms of the GNU General Public License as published by
1163d1a8abSmrg;; the Free Software Foundation; either version 3, or (at your option)
1263d1a8abSmrg;; any later version.
1363d1a8abSmrg;;
1463d1a8abSmrg;; GCC is distributed in the hope that it will be useful,
1563d1a8abSmrg;; but WITHOUT ANY WARRANTY; without even the implied warranty of
1663d1a8abSmrg;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1763d1a8abSmrg;; GNU General Public License for more details.
1863d1a8abSmrg;;
1963d1a8abSmrg;; You should have received a copy of the GNU General Public License
2063d1a8abSmrg;; along with GCC; see the file COPYING3.  If not see
2163d1a8abSmrg;; <http://www.gnu.org/licenses/>.
2263d1a8abSmrg
2363d1a8abSmrg;; Register numbers
2463d1a8abSmrg(define_constants
2563d1a8abSmrg  [
2663d1a8abSmrg   (FIRST_RETVAL_REGNO     2)	; Return value registers
2763d1a8abSmrg   (LAST_RETVAL_REGNO      3)	;
2863d1a8abSmrg   (FIRST_ARG_REGNO        4)	; Argument registers
2963d1a8abSmrg   (LAST_ARG_REGNO         7)	;
3063d1a8abSmrg
3163d1a8abSmrg   (TP_REGNO              23)	; Thread pointer register
3263d1a8abSmrg   (GP_REGNO	          26)	; Global pointer register
3363d1a8abSmrg   (SP_REGNO	          27)	; Stack pointer register
3463d1a8abSmrg   (FP_REGNO	          28)	; Frame pointer register
3563d1a8abSmrg   (EA_REGNO	          29)	; Exception return address register
3663d1a8abSmrg   (RA_REGNO              31)	; Return address register
3763d1a8abSmrg   (LAST_GP_REG           31)	; Last general purpose register
3863d1a8abSmrg
3963d1a8abSmrg   ;; Target register definitions
4063d1a8abSmrg   (STATIC_CHAIN_REGNUM        12)
4163d1a8abSmrg   (STACK_POINTER_REGNUM       27)
4263d1a8abSmrg   (HARD_FRAME_POINTER_REGNUM  28)
4363d1a8abSmrg   (PC_REGNUM                  37)
4463d1a8abSmrg   (FRAME_POINTER_REGNUM       38)
4563d1a8abSmrg   (ARG_POINTER_REGNUM         39)
4663d1a8abSmrg   (FIRST_PSEUDO_REGISTER      40)
4763d1a8abSmrg  ]
4863d1a8abSmrg)
4963d1a8abSmrg
5063d1a8abSmrg;; Enumeration of UNSPECs
5163d1a8abSmrg
5263d1a8abSmrg(define_c_enum "unspecv" [
5363d1a8abSmrg  UNSPECV_BLOCKAGE
5463d1a8abSmrg  UNSPECV_WRCTL
5563d1a8abSmrg  UNSPECV_RDCTL
5663d1a8abSmrg  UNSPECV_FWRX
5763d1a8abSmrg  UNSPECV_FWRY
5863d1a8abSmrg  UNSPECV_FRDXLO
5963d1a8abSmrg  UNSPECV_FRDXHI
6063d1a8abSmrg  UNSPECV_FRDY
6163d1a8abSmrg  UNSPECV_CUSTOM_NXX
6263d1a8abSmrg  UNSPECV_CUSTOM_XNXX
6363d1a8abSmrg  UNSPECV_LDXIO
6463d1a8abSmrg  UNSPECV_STXIO
6563d1a8abSmrg  UNSPECV_RDPRS
6663d1a8abSmrg  UNSPECV_FLUSHD
6763d1a8abSmrg  UNSPECV_FLUSHDA
6863d1a8abSmrg  UNSPECV_WRPIE
6963d1a8abSmrg  UNSPECV_ENI
7063d1a8abSmrg  UNSPECV_LDEX
7163d1a8abSmrg  UNSPECV_LDSEX
7263d1a8abSmrg  UNSPECV_STEX
7363d1a8abSmrg  UNSPECV_STSEX
7463d1a8abSmrg])
7563d1a8abSmrg
7663d1a8abSmrg(define_c_enum "unspec" [
7763d1a8abSmrg  UNSPEC_FCOS
7863d1a8abSmrg  UNSPEC_FSIN
7963d1a8abSmrg  UNSPEC_FTAN
8063d1a8abSmrg  UNSPEC_FATAN
8163d1a8abSmrg  UNSPEC_FEXP
8263d1a8abSmrg  UNSPEC_FLOG
8363d1a8abSmrg  UNSPEC_ROUND
8463d1a8abSmrg  UNSPEC_LOAD_GOT_REGISTER
8563d1a8abSmrg  UNSPEC_PIC_SYM
8663d1a8abSmrg  UNSPEC_PIC_CALL_SYM
8763d1a8abSmrg  UNSPEC_PIC_GOTOFF_SYM
8863d1a8abSmrg  UNSPEC_LOAD_TLS_IE
8963d1a8abSmrg  UNSPEC_ADD_TLS_LE
9063d1a8abSmrg  UNSPEC_ADD_TLS_GD
9163d1a8abSmrg  UNSPEC_ADD_TLS_LDM
9263d1a8abSmrg  UNSPEC_ADD_TLS_LDO
9363d1a8abSmrg  UNSPEC_EH_RETURN
9463d1a8abSmrg  UNSPEC_SYNC
9563d1a8abSmrg])
9663d1a8abSmrg
9763d1a8abSmrg
9863d1a8abSmrg;;  Instruction scheduler
9963d1a8abSmrg
10063d1a8abSmrg; No schedule info is currently available, using an assumption that no
10163d1a8abSmrg; instruction can use the results of the previous instruction without
10263d1a8abSmrg; incuring a stall.
10363d1a8abSmrg
10463d1a8abSmrg; length of an instruction (in bytes)
10563d1a8abSmrg(define_attr "length" ""
10663d1a8abSmrg  (if_then_else (match_test "nios2_cdx_narrow_form_p (insn)")
10763d1a8abSmrg    (const_int 2)
10863d1a8abSmrg    (const_int 4)))
10963d1a8abSmrg
11063d1a8abSmrg(define_attr "type"
11163d1a8abSmrg  "unknown,complex,control,alu,cond_alu,st,ld,stwm,ldwm,push,pop,mul,div,\
11263d1a8abSmrg   custom,add,sub,mov,and,or,xor,neg,not,sll,srl,sra,rol,ror,nop"
11363d1a8abSmrg  (const_string "complex"))
11463d1a8abSmrg
11563d1a8abSmrg(define_asm_attributes
11663d1a8abSmrg [(set_attr "length" "4")
11763d1a8abSmrg  (set_attr "type" "complex")])
11863d1a8abSmrg
11963d1a8abSmrg(define_automaton "nios2")
12063d1a8abSmrg(automata_option "v")
12163d1a8abSmrg;(automata_option "no-minimization")
12263d1a8abSmrg(automata_option "ndfa")
12363d1a8abSmrg
12463d1a8abSmrg; The nios2 pipeline is fairly straightforward for the fast model.
12563d1a8abSmrg; Every alu operation is pipelined so that an instruction can
12663d1a8abSmrg; be issued every cycle.  However, there are still potential
12763d1a8abSmrg; stalls which this description tries to deal with.
12863d1a8abSmrg
12963d1a8abSmrg(define_cpu_unit "cpu" "nios2")
13063d1a8abSmrg
13163d1a8abSmrg(define_insn_reservation "complex" 1
13263d1a8abSmrg  (eq_attr "type" "complex")
13363d1a8abSmrg  "cpu")
13463d1a8abSmrg
13563d1a8abSmrg(define_insn_reservation "control" 1
13663d1a8abSmrg  (eq_attr "type" "control,pop")
13763d1a8abSmrg  "cpu")
13863d1a8abSmrg
13963d1a8abSmrg(define_insn_reservation "alu" 1
14063d1a8abSmrg  (eq_attr "type" "alu,add,sub,mov,and,or,xor,neg,not")
14163d1a8abSmrg  "cpu")
14263d1a8abSmrg
14363d1a8abSmrg(define_insn_reservation "cond_alu" 1
14463d1a8abSmrg  (eq_attr "type" "cond_alu")
14563d1a8abSmrg  "cpu")
14663d1a8abSmrg
14763d1a8abSmrg(define_insn_reservation "st" 1
14863d1a8abSmrg  (eq_attr "type" "st,stwm,push")
14963d1a8abSmrg  "cpu")
15063d1a8abSmrg
15163d1a8abSmrg(define_insn_reservation "custom" 1
15263d1a8abSmrg  (eq_attr "type" "custom")
15363d1a8abSmrg  "cpu")
15463d1a8abSmrg
15563d1a8abSmrg; shifts, muls and lds have three cycle latency
15663d1a8abSmrg(define_insn_reservation "ld" 3
15763d1a8abSmrg  (eq_attr "type" "ld,ldwm")
15863d1a8abSmrg  "cpu")
15963d1a8abSmrg
16063d1a8abSmrg(define_insn_reservation "shift" 3
16163d1a8abSmrg  (eq_attr "type" "sll,srl,sra,rol,ror")
16263d1a8abSmrg  "cpu")
16363d1a8abSmrg
16463d1a8abSmrg(define_insn_reservation "mul" 3
16563d1a8abSmrg  (eq_attr "type" "mul")
16663d1a8abSmrg  "cpu")
16763d1a8abSmrg
16863d1a8abSmrg(define_insn_reservation "div" 1
16963d1a8abSmrg  (eq_attr "type" "div")
17063d1a8abSmrg  "cpu")
17163d1a8abSmrg
17263d1a8abSmrg(include "predicates.md")
17363d1a8abSmrg(include "constraints.md")
17463d1a8abSmrg
17563d1a8abSmrg
17663d1a8abSmrg;; Move instructions
17763d1a8abSmrg
17863d1a8abSmrg(define_mode_iterator M [QI HI SI])
17963d1a8abSmrg
18063d1a8abSmrg(define_expand "mov<mode>"
18163d1a8abSmrg  [(set (match_operand:M 0 "nonimmediate_operand" "")
18263d1a8abSmrg        (match_operand:M 1 "general_operand" ""))]
18363d1a8abSmrg  ""
18463d1a8abSmrg{
18563d1a8abSmrg  if (nios2_emit_move_sequence (operands, <MODE>mode))
18663d1a8abSmrg    DONE;
18763d1a8abSmrg})
18863d1a8abSmrg
18963d1a8abSmrg(define_insn "*high"
19063d1a8abSmrg  [(set (match_operand:SI 0 "register_operand" "=r")
19163d1a8abSmrg        (high:SI (match_operand:SI 1 "immediate_operand" "i")))]
19263d1a8abSmrg  ""
19363d1a8abSmrg  "movhi\\t%0, %H1"
19463d1a8abSmrg  [(set_attr "type" "alu")])
19563d1a8abSmrg
19663d1a8abSmrg(define_insn "*lo_sum"
19763d1a8abSmrg  [(set (match_operand:SI 0 "register_operand" "=r")
19863d1a8abSmrg        (lo_sum:SI (match_operand:SI 1 "register_operand"  "r")
19963d1a8abSmrg                   (match_operand:SI 2 "immediate_operand" "i")))]
20063d1a8abSmrg  ""
20163d1a8abSmrg  "addi\\t%0, %1, %L2"
20263d1a8abSmrg  [(set_attr "type" "alu")])
20363d1a8abSmrg
204c7a68eb7Smrg(define_insn_and_split "movqi_internal"
20563d1a8abSmrg  [(set (match_operand:QI 0 "nonimmediate_operand" "=m, r,r")
20663d1a8abSmrg        (match_operand:QI 1 "general_operand"       "rM,m,rI"))]
20763d1a8abSmrg  "(register_operand (operands[0], QImode)
20863d1a8abSmrg    || reg_or_0_operand (operands[1], QImode))"
20963d1a8abSmrg  {
21063d1a8abSmrg    switch (which_alternative)
21163d1a8abSmrg      {
21263d1a8abSmrg      case 0:
21363d1a8abSmrg	if (get_attr_length (insn) != 2)
21463d1a8abSmrg	  return "stb%o0\\t%z1, %0";
21563d1a8abSmrg	else if (const_0_operand (operands[1], QImode))
21663d1a8abSmrg	  return "stbz.n\\t%z1, %0";
21763d1a8abSmrg	else
21863d1a8abSmrg	  return "stb.n\\t%z1, %0";
21963d1a8abSmrg      case 1:
22063d1a8abSmrg	return "ldbu%o1%.\\t%0, %1";
22163d1a8abSmrg      case 2:
22263d1a8abSmrg	return "mov%i1%.\\t%0, %z1";
22363d1a8abSmrg      default:
22463d1a8abSmrg	gcc_unreachable ();
22563d1a8abSmrg      }
22663d1a8abSmrg  }
227c7a68eb7Smrg  "(nios2_large_constant_memory_operand_p (operands[0])
228c7a68eb7Smrg   || nios2_large_constant_memory_operand_p (operands[1]))"
229c7a68eb7Smrg  [(set (match_dup 0) (match_dup 1))]
230c7a68eb7Smrg  {
231c7a68eb7Smrg    if (nios2_large_constant_memory_operand_p (operands[0]))
232c7a68eb7Smrg      operands[0] = nios2_split_large_constant_memory_operand (operands[0]);
233c7a68eb7Smrg    else
234c7a68eb7Smrg      operands[1] = nios2_split_large_constant_memory_operand (operands[1]);
235c7a68eb7Smrg  }
23663d1a8abSmrg  [(set_attr "type" "st,ld,mov")])
23763d1a8abSmrg
238c7a68eb7Smrg(define_insn_and_split "movhi_internal"
23963d1a8abSmrg  [(set (match_operand:HI 0 "nonimmediate_operand" "=m, r,r")
24063d1a8abSmrg        (match_operand:HI 1 "general_operand"       "rM,m,rI"))]
24163d1a8abSmrg  "(register_operand (operands[0], HImode)
24263d1a8abSmrg    || reg_or_0_operand (operands[1], HImode))"
243c7a68eb7Smrg  {
244c7a68eb7Smrg    switch (which_alternative)
245c7a68eb7Smrg      {
246c7a68eb7Smrg      case 0:
247c7a68eb7Smrg        return "sth%o0%.\\t%z1, %0";
248c7a68eb7Smrg      case 1:
249c7a68eb7Smrg        return "ldhu%o1%.\\t%0, %1";
250c7a68eb7Smrg      case 2:
251c7a68eb7Smrg        return "mov%i1%.\\t%0, %z1";
252c7a68eb7Smrg      default:
253c7a68eb7Smrg	gcc_unreachable ();
254c7a68eb7Smrg      }
255c7a68eb7Smrg  }
256c7a68eb7Smrg  "(nios2_large_constant_memory_operand_p (operands[0])
257c7a68eb7Smrg   || nios2_large_constant_memory_operand_p (operands[1]))"
258c7a68eb7Smrg  [(set (match_dup 0) (match_dup 1))]
259c7a68eb7Smrg  {
260c7a68eb7Smrg    if (nios2_large_constant_memory_operand_p (operands[0]))
261c7a68eb7Smrg      operands[0] = nios2_split_large_constant_memory_operand (operands[0]);
262c7a68eb7Smrg    else
263c7a68eb7Smrg      operands[1] = nios2_split_large_constant_memory_operand (operands[1]);
264c7a68eb7Smrg  }
26563d1a8abSmrg  [(set_attr "type" "st,ld,mov")])
26663d1a8abSmrg
267c7a68eb7Smrg(define_insn_and_split "movsi_internal"
26863d1a8abSmrg  [(set (match_operand:SI 0 "nonimmediate_operand" "=m, r,r,   r")
26963d1a8abSmrg        (match_operand:SI 1 "general_operand"       "rM,m,rIJK,S"))]
27063d1a8abSmrg  "(register_operand (operands[0], SImode)
27163d1a8abSmrg    || reg_or_0_operand (operands[1], SImode))"
27263d1a8abSmrg  {
27363d1a8abSmrg    switch (which_alternative)
27463d1a8abSmrg      {
27563d1a8abSmrg      case 0:
27663d1a8abSmrg	if (get_attr_length (insn) != 2)
27763d1a8abSmrg	  return "stw%o0\\t%z1, %0";
27863d1a8abSmrg	else if (stack_memory_operand (operands[0], SImode))
27963d1a8abSmrg	  return "stwsp.n\\t%z1, %0";
28063d1a8abSmrg	else if (const_0_operand (operands[1], SImode))
28163d1a8abSmrg	  return "stwz.n\\t%z1, %0";
28263d1a8abSmrg	else
28363d1a8abSmrg	  return "stw.n\\t%z1, %0";
28463d1a8abSmrg      case 1:
28563d1a8abSmrg	if (get_attr_length (insn) != 2)
28663d1a8abSmrg	  return "ldw%o1\\t%0, %1";
28763d1a8abSmrg	else if (stack_memory_operand (operands[1], SImode))
28863d1a8abSmrg	  return "ldwsp.n\\t%0, %1";
28963d1a8abSmrg	else
29063d1a8abSmrg	  return "ldw.n\\t%0, %1";
29163d1a8abSmrg      case 2:
29263d1a8abSmrg	return "mov%i1%.\\t%0, %z1";
29363d1a8abSmrg      case 3:
29463d1a8abSmrg	return "addi\\t%0, gp, %%gprel(%1)";
29563d1a8abSmrg      default:
29663d1a8abSmrg	gcc_unreachable ();
29763d1a8abSmrg      }
29863d1a8abSmrg  }
299c7a68eb7Smrg  "(nios2_large_constant_memory_operand_p (operands[0])
300c7a68eb7Smrg    || nios2_large_constant_memory_operand_p (operands[1])
301c7a68eb7Smrg    || (nios2_large_constant_p (operands[1])
302c7a68eb7Smrg        && !(CONST_INT_P (operands[1])
303c7a68eb7Smrg	     && (SMALL_INT_UNSIGNED (INTVAL (operands[1]))
304c7a68eb7Smrg	     	 || UPPER16_INT (INTVAL (operands[1]))))))"
305c7a68eb7Smrg  [(set (match_dup 0) (match_dup 1))]
306c7a68eb7Smrg  {
307c7a68eb7Smrg    if (nios2_large_constant_memory_operand_p (operands[0]))
308c7a68eb7Smrg      operands[0] = nios2_split_large_constant_memory_operand (operands[0]);
309c7a68eb7Smrg    else if (nios2_large_constant_memory_operand_p (operands[1]))
310c7a68eb7Smrg      operands[1] = nios2_split_large_constant_memory_operand (operands[1]);
311c7a68eb7Smrg    else
312c7a68eb7Smrg      operands[1] = nios2_split_large_constant (operands[1], operands[0]);
313c7a68eb7Smrg  }
31463d1a8abSmrg  [(set_attr "type" "st,ld,mov,alu")])
31563d1a8abSmrg
31663d1a8abSmrg(define_mode_iterator BH [QI HI])
31763d1a8abSmrg(define_mode_iterator BHW [QI HI SI])
31863d1a8abSmrg(define_mode_attr bh [(QI "b") (HI "h")])
31963d1a8abSmrg(define_mode_attr bhw [(QI "b") (HI "h") (SI "w")])
32063d1a8abSmrg(define_mode_attr bhw_uns [(QI "bu") (HI "hu") (SI "w")])
32163d1a8abSmrg
322c7a68eb7Smrg(define_insn_and_split "ld<bhw_uns>io"
32363d1a8abSmrg  [(set (match_operand:BHW 0 "register_operand" "=r")
32463d1a8abSmrg        (unspec_volatile:BHW
32563d1a8abSmrg          [(match_operand:BHW 1 "ldstio_memory_operand" "w")] UNSPECV_LDXIO))]
32663d1a8abSmrg  ""
32763d1a8abSmrg  "ld<bhw_uns>io\\t%0, %1"
328c7a68eb7Smrg  "nios2_large_constant_memory_operand_p (operands[1])"
329c7a68eb7Smrg  [(set (match_dup 0)
330c7a68eb7Smrg        (unspec_volatile:BHW [(match_dup 1)] UNSPECV_LDXIO))]
331c7a68eb7Smrg  {
332c7a68eb7Smrg    operands[1] = nios2_split_large_constant_memory_operand (operands[1]);
333c7a68eb7Smrg  }
33463d1a8abSmrg  [(set_attr "type" "ld")])
33563d1a8abSmrg
33663d1a8abSmrg(define_expand "ld<bh>io"
33763d1a8abSmrg  [(set (match_operand:BH 0 "register_operand" "=r")
33863d1a8abSmrg        (match_operand:BH 1 "ldstio_memory_operand" "w"))]
33963d1a8abSmrg  ""
34063d1a8abSmrg{
34163d1a8abSmrg  rtx tmp = gen_reg_rtx (SImode);
34263d1a8abSmrg  emit_insn (gen_ld<bh>io_signed (tmp, operands[1]));
34363d1a8abSmrg  emit_insn (gen_mov<mode> (operands[0], gen_lowpart (<MODE>mode, tmp)));
34463d1a8abSmrg  DONE;
34563d1a8abSmrg})
34663d1a8abSmrg
347c7a68eb7Smrg(define_insn_and_split "ld<bh>io_signed"
34863d1a8abSmrg  [(set (match_operand:SI 0 "register_operand" "=r")
34963d1a8abSmrg        (sign_extend:SI
35063d1a8abSmrg          (unspec_volatile:BH
35163d1a8abSmrg            [(match_operand:BH 1 "ldstio_memory_operand" "w")] UNSPECV_LDXIO)))]
35263d1a8abSmrg  ""
35363d1a8abSmrg  "ld<bh>io\\t%0, %1"
354c7a68eb7Smrg  "nios2_large_constant_memory_operand_p (operands[1])"
355c7a68eb7Smrg  [(set (match_dup 0)
356c7a68eb7Smrg        (sign_extend:SI (unspec_volatile:BH [(match_dup 1)] UNSPECV_LDXIO)))]
357c7a68eb7Smrg  {
358c7a68eb7Smrg    operands[1] = nios2_split_large_constant_memory_operand (operands[1]);
359c7a68eb7Smrg  }
36063d1a8abSmrg  [(set_attr "type" "ld")])
36163d1a8abSmrg
362c7a68eb7Smrg(define_insn_and_split "st<bhw>io"
36363d1a8abSmrg  [(set (match_operand:BHW 0 "ldstio_memory_operand" "=w")
36463d1a8abSmrg        (unspec_volatile:BHW
36563d1a8abSmrg          [(match_operand:BHW 1 "reg_or_0_operand" "rM")] UNSPECV_STXIO))]
36663d1a8abSmrg  ""
36763d1a8abSmrg  "st<bhw>io\\t%z1, %0"
368c7a68eb7Smrg  "nios2_large_constant_memory_operand_p (operands[0])"
369c7a68eb7Smrg  [(set (match_dup 0) (unspec_volatile:BHW [(match_dup 1)] UNSPECV_STXIO))]
370c7a68eb7Smrg  {
371c7a68eb7Smrg    operands[0] = nios2_split_large_constant_memory_operand (operands[0]);
372c7a68eb7Smrg  }
37363d1a8abSmrg  [(set_attr "type" "st")])
37463d1a8abSmrg
37563d1a8abSmrg
37663d1a8abSmrg;; QI to [HI, SI] extension patterns are collected together
37763d1a8abSmrg(define_mode_iterator QX [HI SI])
37863d1a8abSmrg
37963d1a8abSmrg;; Zero extension patterns
380c7a68eb7Smrg(define_insn_and_split "zero_extendhisi2"
38163d1a8abSmrg  [(set (match_operand:SI 0 "register_operand" "=r,r")
38263d1a8abSmrg        (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
38363d1a8abSmrg  ""
38463d1a8abSmrg  "@
38563d1a8abSmrg    andi%.\\t%0, %1, 0xffff
38663d1a8abSmrg    ldhu%o1%.\\t%0, %1"
387c7a68eb7Smrg  "nios2_large_constant_memory_operand_p (operands[1])"
388c7a68eb7Smrg  [(set (match_dup 0) (zero_extend:SI (match_dup 1)))]
389c7a68eb7Smrg  {
390c7a68eb7Smrg    operands[1] = nios2_split_large_constant_memory_operand (operands[1]);
391c7a68eb7Smrg  }
39263d1a8abSmrg  [(set_attr "type"     "and,ld")])
39363d1a8abSmrg
394c7a68eb7Smrg(define_insn_and_split "zero_extendqi<mode>2"
39563d1a8abSmrg  [(set (match_operand:QX 0 "register_operand" "=r,r")
39663d1a8abSmrg        (zero_extend:QX (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
39763d1a8abSmrg  ""
39863d1a8abSmrg  "@
39963d1a8abSmrg    andi%.\\t%0, %1, 0xff
40063d1a8abSmrg    ldbu%o1%.\\t%0, %1"
401c7a68eb7Smrg  "nios2_large_constant_memory_operand_p (operands[1])"
402c7a68eb7Smrg  [(set (match_dup 0) (zero_extend:QX (match_dup 1)))]
403c7a68eb7Smrg  {
404c7a68eb7Smrg    operands[1] = nios2_split_large_constant_memory_operand (operands[1]);
405c7a68eb7Smrg  }
40663d1a8abSmrg  [(set_attr "type"     "and,ld")])
40763d1a8abSmrg
40863d1a8abSmrg;; Sign extension patterns
40963d1a8abSmrg
410c7a68eb7Smrg(define_insn_and_split "extendhisi2"
41163d1a8abSmrg  [(set (match_operand:SI 0 "register_operand"                     "=r,r")
41263d1a8abSmrg        (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand"  "r,m")))]
41363d1a8abSmrg  ""
41463d1a8abSmrg  "@
41563d1a8abSmrg   #
41663d1a8abSmrg   ldh%o1%.\\t%0, %1"
417c7a68eb7Smrg  "nios2_large_constant_memory_operand_p (operands[1])"
418c7a68eb7Smrg  [(set (match_dup 0) (sign_extend:SI (match_dup 1)))]
419c7a68eb7Smrg  {
420c7a68eb7Smrg    operands[1] = nios2_split_large_constant_memory_operand (operands[1]);
421c7a68eb7Smrg  }
42263d1a8abSmrg  [(set_attr "type" "alu,ld")])
42363d1a8abSmrg
424c7a68eb7Smrg(define_insn_and_split "extendqi<mode>2"
42563d1a8abSmrg  [(set (match_operand:QX 0 "register_operand"                     "=r,r")
42663d1a8abSmrg        (sign_extend:QX (match_operand:QI 1 "nonimmediate_operand"  "r,m")))]
42763d1a8abSmrg  ""
42863d1a8abSmrg  "@
42963d1a8abSmrg   #
43063d1a8abSmrg   ldb%o1%.\\t%0, %1"
431c7a68eb7Smrg  "nios2_large_constant_memory_operand_p (operands[1])"
432c7a68eb7Smrg  [(set (match_dup 0) (sign_extend:QX (match_dup 1)))]
433c7a68eb7Smrg  {
434c7a68eb7Smrg    operands[1] = nios2_split_large_constant_memory_operand (operands[1]);
435c7a68eb7Smrg  }
43663d1a8abSmrg  [(set_attr "type" "alu,ld")])
43763d1a8abSmrg
43863d1a8abSmrg;; Split patterns for register alternative cases.
43963d1a8abSmrg(define_split
44063d1a8abSmrg  [(set (match_operand:SI 0 "register_operand" "")
44163d1a8abSmrg        (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
44263d1a8abSmrg  "reload_completed"
44363d1a8abSmrg  [(set (match_dup 0)
44463d1a8abSmrg        (and:SI (match_dup 1) (const_int 65535)))
44563d1a8abSmrg   (set (match_dup 0)
44663d1a8abSmrg        (xor:SI (match_dup 0) (const_int 32768)))
44763d1a8abSmrg   (set (match_dup 0)
44863d1a8abSmrg        (plus:SI (match_dup 0) (const_int -32768)))]
44963d1a8abSmrg  "operands[1] = gen_lowpart (SImode, operands[1]);")
45063d1a8abSmrg
45163d1a8abSmrg(define_split
45263d1a8abSmrg  [(set (match_operand:QX 0 "register_operand" "")
45363d1a8abSmrg        (sign_extend:QX (match_operand:QI 1 "register_operand" "")))]
45463d1a8abSmrg  "reload_completed"
45563d1a8abSmrg  [(set (match_dup 0)
45663d1a8abSmrg        (and:SI (match_dup 1) (const_int 255)))
45763d1a8abSmrg   (set (match_dup 0)
45863d1a8abSmrg        (xor:SI (match_dup 0) (const_int 128)))
45963d1a8abSmrg   (set (match_dup 0)
46063d1a8abSmrg        (plus:SI (match_dup 0) (const_int -128)))]
46163d1a8abSmrg  "operands[0] = gen_lowpart (SImode, operands[0]);
46263d1a8abSmrg   operands[1] = gen_lowpart (SImode, operands[1]);")
46363d1a8abSmrg
46463d1a8abSmrg
46563d1a8abSmrg;; Arithmetic Operations
46663d1a8abSmrg
46763d1a8abSmrg(define_insn "addsi3"
46863d1a8abSmrg  [(set (match_operand:SI 0 "register_operand"            "=r")
46963d1a8abSmrg        (plus:SI (match_operand:SI 1 "register_operand"   "%r")
47063d1a8abSmrg                 (match_operand:SI 2 "add_regimm_operand" "rIT")))]
47163d1a8abSmrg  ""
47263d1a8abSmrg{
47363d1a8abSmrg  return nios2_add_insn_asm (insn, operands);
47463d1a8abSmrg}
47563d1a8abSmrg  [(set_attr "type" "add")])
47663d1a8abSmrg
47763d1a8abSmrg(define_insn "subsi3"
47863d1a8abSmrg  [(set (match_operand:SI 0 "register_operand"           "=r")
47963d1a8abSmrg        (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rM")
48063d1a8abSmrg                  (match_operand:SI 2 "register_operand" "r")))]
48163d1a8abSmrg  ""
48263d1a8abSmrg  "sub%.\\t%0, %z1, %2"
48363d1a8abSmrg  [(set_attr "type" "sub")])
48463d1a8abSmrg
48563d1a8abSmrg(define_insn "mulsi3"
48663d1a8abSmrg  [(set (match_operand:SI 0 "register_operand"          "=r")
48763d1a8abSmrg        (mult:SI (match_operand:SI 1 "register_operand" "%r")
48863d1a8abSmrg                 (match_operand:SI 2 "arith_operand"    "rI")))]
48963d1a8abSmrg  "TARGET_HAS_MUL"
49063d1a8abSmrg  "mul%i2\\t%0, %1, %z2"
49163d1a8abSmrg  [(set_attr "type" "mul")])
49263d1a8abSmrg
49363d1a8abSmrg(define_expand "divsi3"
49463d1a8abSmrg  [(set (match_operand:SI 0 "register_operand"          "=r")
49563d1a8abSmrg        (div:SI (match_operand:SI 1 "register_operand"   "r")
49663d1a8abSmrg                (match_operand:SI 2 "register_operand"   "r")))]
49763d1a8abSmrg  ""
49863d1a8abSmrg{
49963d1a8abSmrg  if (!TARGET_HAS_DIV)
50063d1a8abSmrg    {
50163d1a8abSmrg      if (TARGET_FAST_SW_DIV)
50263d1a8abSmrg        {
50363d1a8abSmrg          nios2_emit_expensive_div (operands, SImode);
50463d1a8abSmrg          DONE;
50563d1a8abSmrg        }
50663d1a8abSmrg      else
50763d1a8abSmrg        FAIL;
50863d1a8abSmrg    }
50963d1a8abSmrg})
51063d1a8abSmrg
51163d1a8abSmrg(define_insn "divsi3_insn"
51263d1a8abSmrg  [(set (match_operand:SI 0 "register_operand"            "=r")
51363d1a8abSmrg        (div:SI (match_operand:SI 1 "register_operand"     "r")
51463d1a8abSmrg                (match_operand:SI 2 "register_operand"     "r")))]
51563d1a8abSmrg  "TARGET_HAS_DIV"
51663d1a8abSmrg  "div\\t%0, %1, %2"
51763d1a8abSmrg  [(set_attr "type" "div")])
51863d1a8abSmrg
51963d1a8abSmrg(define_insn "udivsi3"
52063d1a8abSmrg  [(set (match_operand:SI 0 "register_operand"            "=r")
52163d1a8abSmrg        (udiv:SI (match_operand:SI 1 "register_operand"    "r")
52263d1a8abSmrg                 (match_operand:SI 2 "register_operand"    "r")))]
52363d1a8abSmrg  "TARGET_HAS_DIV"
52463d1a8abSmrg  "divu\\t%0, %1, %2"
52563d1a8abSmrg  [(set_attr "type" "div")])
52663d1a8abSmrg
52763d1a8abSmrg(define_code_iterator EXTEND [sign_extend zero_extend])
52863d1a8abSmrg(define_code_attr us [(sign_extend "s") (zero_extend "u")])
52963d1a8abSmrg(define_code_attr mul [(sign_extend "mul") (zero_extend "umul")])
53063d1a8abSmrg
53163d1a8abSmrg(define_insn "<us>mulsi3_highpart"
53263d1a8abSmrg  [(set (match_operand:SI 0 "register_operand"                       "=r")
53363d1a8abSmrg        (truncate:SI
53463d1a8abSmrg         (lshiftrt:DI
53563d1a8abSmrg          (mult:DI (EXTEND:DI (match_operand:SI 1 "register_operand"  "r"))
53663d1a8abSmrg                   (EXTEND:DI (match_operand:SI 2 "register_operand"  "r")))
53763d1a8abSmrg          (const_int 32))))]
53863d1a8abSmrg  "TARGET_HAS_MULX"
53963d1a8abSmrg  "mulx<us><us>\\t%0, %1, %2"
54063d1a8abSmrg  [(set_attr "type" "mul")])
54163d1a8abSmrg
54263d1a8abSmrg(define_expand "<mul>sidi3"
54363d1a8abSmrg  [(set (match_operand:DI 0 "register_operand" "")
54463d1a8abSmrg	(mult:DI (EXTEND:DI (match_operand:SI 1 "register_operand" ""))
54563d1a8abSmrg		 (EXTEND:DI (match_operand:SI 2 "register_operand" ""))))]
54663d1a8abSmrg  "TARGET_HAS_MULX"
54763d1a8abSmrg{
54863d1a8abSmrg  rtx hi = gen_reg_rtx (SImode);
54963d1a8abSmrg  rtx lo = gen_reg_rtx (SImode);
55063d1a8abSmrg
55163d1a8abSmrg  emit_insn (gen_<us>mulsi3_highpart (hi, operands[1], operands[2]));
55263d1a8abSmrg  emit_insn (gen_mulsi3 (lo, operands[1], operands[2]));
55363d1a8abSmrg  emit_move_insn (gen_lowpart (SImode, operands[0]), lo);
55463d1a8abSmrg  emit_move_insn (gen_highpart (SImode, operands[0]), hi);
55563d1a8abSmrg  DONE;
55663d1a8abSmrg})
55763d1a8abSmrg
55863d1a8abSmrg
55963d1a8abSmrg;;  Negate and ones complement
56063d1a8abSmrg
56163d1a8abSmrg(define_insn "negsi2"
56263d1a8abSmrg  [(set (match_operand:SI 0 "register_operand"        "=r")
56363d1a8abSmrg        (neg:SI (match_operand:SI 1 "register_operand" "r")))]
56463d1a8abSmrg  ""
56563d1a8abSmrg{
56663d1a8abSmrg  if (get_attr_length (insn) == 2)
56763d1a8abSmrg    return "neg.n\\t%0, %1";
56863d1a8abSmrg  else
56963d1a8abSmrg    return "sub\\t%0, zero, %1";
57063d1a8abSmrg}
57163d1a8abSmrg  [(set_attr "type" "neg")])
57263d1a8abSmrg
57363d1a8abSmrg(define_insn "one_cmplsi2"
57463d1a8abSmrg  [(set (match_operand:SI 0 "register_operand"        "=r")
57563d1a8abSmrg        (not:SI (match_operand:SI 1 "register_operand" "r")))]
57663d1a8abSmrg  ""
57763d1a8abSmrg{
57863d1a8abSmrg  if (get_attr_length (insn) == 2)
57963d1a8abSmrg    return "not.n\\t%0, %1";
58063d1a8abSmrg  else
58163d1a8abSmrg    return "nor\\t%0, zero, %1";
58263d1a8abSmrg}
58363d1a8abSmrg  [(set_attr "type" "not")])
58463d1a8abSmrg
58563d1a8abSmrg
58663d1a8abSmrg;;  Integer logical Operations
58763d1a8abSmrg
58863d1a8abSmrg(define_insn "andsi3"
58963d1a8abSmrg  [(set (match_operand:SI 0 "register_operand"          "=r")
59063d1a8abSmrg        (and:SI (match_operand:SI 1 "register_operand"  "%r")
59163d1a8abSmrg                (match_operand:SI 2 "and_operand"     "rJKP")))]
59263d1a8abSmrg  ""
59363d1a8abSmrg  "and%x2%.\\t%0, %1, %y2"
59463d1a8abSmrg  [(set_attr "type" "and")])
59563d1a8abSmrg
59663d1a8abSmrg(define_code_iterator LOGICAL [ior xor])
59763d1a8abSmrg(define_code_attr logical_asm [(ior "or") (xor "xor")])
59863d1a8abSmrg
59963d1a8abSmrg(define_insn "<code>si3"
60063d1a8abSmrg  [(set (match_operand:SI 0 "register_operand"             "=r")
60163d1a8abSmrg        (LOGICAL:SI (match_operand:SI 1 "register_operand" "%r")
60263d1a8abSmrg                    (match_operand:SI 2 "logical_operand" "rJK")))]
60363d1a8abSmrg  ""
60463d1a8abSmrg  "<logical_asm>%x2%.\\t%0, %1, %y2"
60563d1a8abSmrg  [(set_attr "type" "<logical_asm>")])
60663d1a8abSmrg
60763d1a8abSmrg(define_insn "*norsi3"
60863d1a8abSmrg  [(set (match_operand:SI 0 "register_operand"                 "=r")
60963d1a8abSmrg        (and:SI (not:SI (match_operand:SI 1 "register_operand" "%r"))
61063d1a8abSmrg                (not:SI (match_operand:SI 2 "register_operand"  "r"))))]
61163d1a8abSmrg  ""
61263d1a8abSmrg  "nor\\t%0, %1, %2"
61363d1a8abSmrg  [(set_attr "type" "alu")])
61463d1a8abSmrg
61563d1a8abSmrg
61663d1a8abSmrg;;  Shift instructions
61763d1a8abSmrg
61863d1a8abSmrg(define_code_iterator SHIFT  [ashift ashiftrt lshiftrt rotate])
61963d1a8abSmrg(define_code_attr shift_op   [(ashift "ashl") (ashiftrt "ashr")
62063d1a8abSmrg                              (lshiftrt "lshr") (rotate "rotl")])
62163d1a8abSmrg(define_code_attr shift_asm  [(ashift "sll") (ashiftrt "sra")
62263d1a8abSmrg                              (lshiftrt "srl") (rotate "rol")])
62363d1a8abSmrg
62463d1a8abSmrg(define_insn "<shift_op>si3"
62563d1a8abSmrg  [(set (match_operand:SI 0 "register_operand"          "=r")
62663d1a8abSmrg        (SHIFT:SI (match_operand:SI 1 "register_operand" "r")
62763d1a8abSmrg                  (match_operand:SI 2 "shift_operand"    "rL")))]
62863d1a8abSmrg  ""
62963d1a8abSmrg  "<shift_asm>%i2%.\\t%0, %1, %z2"
63063d1a8abSmrg  [(set_attr "type" "<shift_asm>")])
63163d1a8abSmrg
63263d1a8abSmrg(define_insn "rotrsi3"
63363d1a8abSmrg  [(set (match_operand:SI 0 "register_operand"             "=r")
63463d1a8abSmrg        (rotatert:SI (match_operand:SI 1 "register_operand" "r")
63563d1a8abSmrg                     (match_operand:SI 2 "register_operand" "r")))]
63663d1a8abSmrg  ""
63763d1a8abSmrg  "ror\\t%0, %1, %2"
63863d1a8abSmrg  [(set_attr "type" "ror")])
63963d1a8abSmrg
64063d1a8abSmrg;; Nios II R2 Bit Manipulation Extension (BMX), provides
64163d1a8abSmrg;; bit merge/insertion/extraction instructions.
64263d1a8abSmrg
64363d1a8abSmrg(define_insn "*merge"
64463d1a8abSmrg  [(set (zero_extract:SI (match_operand:SI 0 "register_operand"   "+r")
64563d1a8abSmrg			 (match_operand:SI 1 "const_shift_operand" "L")
64663d1a8abSmrg			 (match_operand:SI 2 "const_shift_operand" "L"))
64763d1a8abSmrg        (zero_extract:SI (match_operand:SI 3 "register_operand"    "r")
64863d1a8abSmrg                         (match_dup 1) (match_dup 2)))]
64963d1a8abSmrg  "TARGET_HAS_BMX"
65063d1a8abSmrg{
65163d1a8abSmrg  operands[4] = GEN_INT (INTVAL (operands[1]) + INTVAL (operands[2]) - 1);
65263d1a8abSmrg  return "merge\\t%0, %3, %4, %2";
65363d1a8abSmrg}
65463d1a8abSmrg  [(set_attr "type" "alu")])
65563d1a8abSmrg
65663d1a8abSmrg(define_insn "extzv"
65763d1a8abSmrg  [(set (match_operand:SI 0 "register_operand" "=r")
65863d1a8abSmrg        (zero_extract:SI (match_operand:SI 1 "register_operand"    "r")
65963d1a8abSmrg                         (match_operand:SI 2 "const_shift_operand" "L")
66063d1a8abSmrg                         (match_operand:SI 3 "const_shift_operand" "L")))]
66163d1a8abSmrg  "TARGET_HAS_BMX"
66263d1a8abSmrg{
66363d1a8abSmrg  operands[4] = GEN_INT (INTVAL (operands[2]) + INTVAL (operands[3]) - 1);
66463d1a8abSmrg  return "extract\\t%0, %1, %4, %3";
66563d1a8abSmrg}
66663d1a8abSmrg  [(set_attr "type" "alu")])
66763d1a8abSmrg
66863d1a8abSmrg(define_insn "insv"
66963d1a8abSmrg  [(set (zero_extract:SI (match_operand:SI 0 "register_operand"   "+r")
67063d1a8abSmrg			 (match_operand:SI 1 "const_shift_operand" "L")
67163d1a8abSmrg			 (match_operand:SI 2 "const_shift_operand" "L"))
67263d1a8abSmrg	(match_operand:SI 3 "reg_or_0_operand" "rM"))]
67363d1a8abSmrg  "TARGET_HAS_BMX"
67463d1a8abSmrg{
67563d1a8abSmrg  operands[4] = GEN_INT (INTVAL (operands[1]) + INTVAL (operands[2]) - 1);
67663d1a8abSmrg  return "insert\\t%0, %z3, %4, %2";
67763d1a8abSmrg}
67863d1a8abSmrg  [(set_attr "type" "alu")])
67963d1a8abSmrg
68063d1a8abSmrg
68163d1a8abSmrg
68263d1a8abSmrg;; Floating point instructions
68363d1a8abSmrg
68463d1a8abSmrg;; Mode iterator for single/double float
68563d1a8abSmrg(define_mode_iterator F [SF DF])
68663d1a8abSmrg(define_mode_attr f [(SF "s") (DF "d")])
68763d1a8abSmrg
68863d1a8abSmrg;; Basic arithmetic instructions
68963d1a8abSmrg(define_code_iterator FOP3 [plus minus mult div])
69063d1a8abSmrg(define_code_attr fop3 [(plus "add") (minus "sub") (mult "mul") (div "div")])
69163d1a8abSmrg
69263d1a8abSmrg(define_insn "<fop3><mode>3"
69363d1a8abSmrg  [(set (match_operand:F 0 "register_operand"        "=r")
69463d1a8abSmrg        (FOP3:F (match_operand:F 1 "register_operand" "r")
69563d1a8abSmrg                (match_operand:F 2 "register_operand" "r")))]
69663d1a8abSmrg  "nios2_fpu_insn_enabled (n2fpu_f<fop3><f>)"
69763d1a8abSmrg  { return nios2_fpu_insn_asm (n2fpu_f<fop3><f>); }
69863d1a8abSmrg  [(set_attr "type" "custom")])
69963d1a8abSmrg
70063d1a8abSmrg;; Floating point min/max operations
70163d1a8abSmrg(define_code_iterator SMINMAX [smin smax])
70263d1a8abSmrg(define_code_attr minmax [(smin "min") (smax "max")])
70363d1a8abSmrg(define_insn "<code><mode>3"
70463d1a8abSmrg  [(set (match_operand:F 0 "register_operand" "=r")
70563d1a8abSmrg        (SMINMAX:F (match_operand:F 1 "register_operand" "r")
70663d1a8abSmrg                   (match_operand:F 2 "register_operand" "r")))]
70763d1a8abSmrg  "nios2_fpu_insn_enabled (n2fpu_f<minmax><f>)"
70863d1a8abSmrg  { return nios2_fpu_insn_asm (n2fpu_f<minmax><f>); }
70963d1a8abSmrg  [(set_attr "type" "custom")])
71063d1a8abSmrg
71163d1a8abSmrg;; These 2-operand FP operations can be collected together
71263d1a8abSmrg(define_code_iterator FOP2 [abs neg sqrt])
71363d1a8abSmrg(define_insn "<code><mode>2"
71463d1a8abSmrg  [(set (match_operand:F 0 "register_operand" "=r")
71563d1a8abSmrg        (FOP2:F (match_operand:F 1 "register_operand" "r")))]
71663d1a8abSmrg  "nios2_fpu_insn_enabled (n2fpu_f<code><f>)"
71763d1a8abSmrg  { return nios2_fpu_insn_asm (n2fpu_f<code><f>); }
71863d1a8abSmrg  [(set_attr "type" "custom")])
71963d1a8abSmrg
72063d1a8abSmrg;; X, Y register access instructions
72163d1a8abSmrg(define_insn "nios2_fwrx"
72263d1a8abSmrg  [(unspec_volatile [(match_operand:DF 0 "register_operand" "r")] UNSPECV_FWRX)]
72363d1a8abSmrg  "nios2_fpu_insn_enabled (n2fpu_fwrx)"
72463d1a8abSmrg  { return nios2_fpu_insn_asm (n2fpu_fwrx); }
72563d1a8abSmrg  [(set_attr "type" "custom")])
72663d1a8abSmrg
72763d1a8abSmrg(define_insn "nios2_fwry"
72863d1a8abSmrg  [(unspec_volatile [(match_operand:SF 0 "register_operand" "r")] UNSPECV_FWRY)]
72963d1a8abSmrg  "nios2_fpu_insn_enabled (n2fpu_fwry)"
73063d1a8abSmrg  { return nios2_fpu_insn_asm (n2fpu_fwry); }
73163d1a8abSmrg  [(set_attr "type" "custom")])
73263d1a8abSmrg
73363d1a8abSmrg;; The X, Y read insns uses an int iterator
73463d1a8abSmrg(define_int_iterator UNSPEC_READ_XY [UNSPECV_FRDXLO UNSPECV_FRDXHI
73563d1a8abSmrg                                     UNSPECV_FRDY])
73663d1a8abSmrg(define_int_attr read_xy [(UNSPECV_FRDXLO "frdxlo") (UNSPECV_FRDXHI "frdxhi")
73763d1a8abSmrg                          (UNSPECV_FRDY "frdy")])
73863d1a8abSmrg(define_insn "nios2_<read_xy>"
73963d1a8abSmrg  [(set (match_operand:SF 0 "register_operand" "=r")
74063d1a8abSmrg        (unspec_volatile:SF [(const_int 0)] UNSPEC_READ_XY))]
74163d1a8abSmrg  "nios2_fpu_insn_enabled (n2fpu_<read_xy>)"
74263d1a8abSmrg  { return nios2_fpu_insn_asm (n2fpu_<read_xy>); }
74363d1a8abSmrg  [(set_attr "type" "custom")])
74463d1a8abSmrg
74563d1a8abSmrg;; Various math functions
74663d1a8abSmrg(define_int_iterator MATHFUNC
74763d1a8abSmrg  [UNSPEC_FCOS UNSPEC_FSIN UNSPEC_FTAN UNSPEC_FATAN UNSPEC_FEXP UNSPEC_FLOG])
74863d1a8abSmrg(define_int_attr mathfunc [(UNSPEC_FCOS "cos") (UNSPEC_FSIN "sin")
74963d1a8abSmrg                           (UNSPEC_FTAN "tan") (UNSPEC_FATAN "atan")
75063d1a8abSmrg                           (UNSPEC_FEXP "exp") (UNSPEC_FLOG "log")])
75163d1a8abSmrg
75263d1a8abSmrg(define_insn "<mathfunc><mode>2"
75363d1a8abSmrg  [(set (match_operand:F 0 "register_operand" "=r")
75463d1a8abSmrg        (unspec:F [(match_operand:F 1 "register_operand" "r")] MATHFUNC))]
75563d1a8abSmrg  "nios2_fpu_insn_enabled (n2fpu_f<mathfunc><f>)"
75663d1a8abSmrg  { return nios2_fpu_insn_asm (n2fpu_f<mathfunc><f>); }
75763d1a8abSmrg  [(set_attr "type" "custom")])
75863d1a8abSmrg
75963d1a8abSmrg;; Converting between floating point and fixed point
76063d1a8abSmrg
76163d1a8abSmrg(define_code_iterator FLOAT [float unsigned_float])
76263d1a8abSmrg(define_code_iterator FIX [fix unsigned_fix])
76363d1a8abSmrg
76463d1a8abSmrg(define_code_attr conv_op [(float "float") (unsigned_float "floatuns")
76563d1a8abSmrg                           (fix "fix") (unsigned_fix "fixuns")])
76663d1a8abSmrg(define_code_attr i [(float "i") (unsigned_float "u")
76763d1a8abSmrg                     (fix "i") (unsigned_fix "u")])
76863d1a8abSmrg
76963d1a8abSmrg;; Integer to float conversions
77063d1a8abSmrg(define_insn "<conv_op>si<mode>2"
77163d1a8abSmrg  [(set (match_operand:F 0 "register_operand" "=r")
77263d1a8abSmrg        (FLOAT:F (match_operand:SI 1 "register_operand" "r")))]
77363d1a8abSmrg  "nios2_fpu_insn_enabled (n2fpu_float<i><f>)"
77463d1a8abSmrg  { return nios2_fpu_insn_asm (n2fpu_float<i><f>); }
77563d1a8abSmrg  [(set_attr "type" "custom")])
77663d1a8abSmrg
77763d1a8abSmrg;; Float to integer conversions
77863d1a8abSmrg(define_insn "<conv_op>_trunc<mode>si2"
77963d1a8abSmrg  [(set (match_operand:SI 0 "register_operand" "=r")
78063d1a8abSmrg        (FIX:SI (match_operand:F 1 "general_operand" "r")))]
78163d1a8abSmrg  "nios2_fpu_insn_enabled (n2fpu_fix<f><i>)"
78263d1a8abSmrg  { return nios2_fpu_insn_asm (n2fpu_fix<f><i>); }
78363d1a8abSmrg  [(set_attr "type" "custom")])
78463d1a8abSmrg
78563d1a8abSmrg(define_insn "lroundsfsi2"
78663d1a8abSmrg  [(set (match_operand:SI 0 "register_operand" "=r")
78763d1a8abSmrg        (unspec:SI [(match_operand:SF 1 "general_operand" "r")] UNSPEC_ROUND))]
78863d1a8abSmrg  "nios2_fpu_insn_enabled (n2fpu_round)"
78963d1a8abSmrg  { return nios2_fpu_insn_asm (n2fpu_round); }
79063d1a8abSmrg  [(set_attr "type" "custom")])
79163d1a8abSmrg
79263d1a8abSmrg(define_insn "extendsfdf2"
79363d1a8abSmrg  [(set (match_operand:DF 0 "register_operand" "=r")
79463d1a8abSmrg        (float_extend:DF (match_operand:SF 1 "general_operand" "r")))]
79563d1a8abSmrg  "nios2_fpu_insn_enabled (n2fpu_fextsd)"
79663d1a8abSmrg  { return nios2_fpu_insn_asm (n2fpu_fextsd); }
79763d1a8abSmrg  [(set_attr "type" "custom")])
79863d1a8abSmrg
79963d1a8abSmrg(define_insn "truncdfsf2"
80063d1a8abSmrg  [(set (match_operand:SF 0 "register_operand" "=r")
80163d1a8abSmrg        (float_truncate:SF (match_operand:DF 1 "general_operand" "r")))]
80263d1a8abSmrg  "nios2_fpu_insn_enabled (n2fpu_ftruncds)"
80363d1a8abSmrg  { return nios2_fpu_insn_asm (n2fpu_ftruncds); }
80463d1a8abSmrg  [(set_attr "type" "custom")])
80563d1a8abSmrg
80663d1a8abSmrg
80763d1a8abSmrg
80863d1a8abSmrg;; Prologue, Epilogue and Return
80963d1a8abSmrg
81063d1a8abSmrg(define_expand "prologue"
81163d1a8abSmrg  [(const_int 1)]
81263d1a8abSmrg  ""
81363d1a8abSmrg{
81463d1a8abSmrg  nios2_expand_prologue ();
81563d1a8abSmrg  DONE;
81663d1a8abSmrg})
81763d1a8abSmrg
81863d1a8abSmrg(define_expand "epilogue"
81963d1a8abSmrg  [(return)]
82063d1a8abSmrg  ""
82163d1a8abSmrg{
82263d1a8abSmrg  nios2_expand_epilogue (false);
82363d1a8abSmrg  DONE;
82463d1a8abSmrg})
82563d1a8abSmrg
82663d1a8abSmrg(define_expand "sibcall_epilogue"
82763d1a8abSmrg  [(return)]
82863d1a8abSmrg  ""
82963d1a8abSmrg{
83063d1a8abSmrg  nios2_expand_epilogue (true);
83163d1a8abSmrg  DONE;
83263d1a8abSmrg})
83363d1a8abSmrg
83463d1a8abSmrg(define_expand "return"
83563d1a8abSmrg  [(simple_return)]
83663d1a8abSmrg  "nios2_can_use_return_insn ()"
83763d1a8abSmrg{
83863d1a8abSmrg  if (nios2_expand_return ())
83963d1a8abSmrg    DONE;
84063d1a8abSmrg})
84163d1a8abSmrg
84263d1a8abSmrg(define_insn "simple_return"
84363d1a8abSmrg  [(simple_return)]
84463d1a8abSmrg  ""
84563d1a8abSmrg  "ret%."
84663d1a8abSmrg  [(set_attr "type" "control")])
84763d1a8abSmrg
84863d1a8abSmrg;; Block any insns from being moved before this point, since the
84963d1a8abSmrg;; profiling call to mcount can use various registers that aren't
85063d1a8abSmrg;; saved or used to pass arguments.
85163d1a8abSmrg
85263d1a8abSmrg(define_insn "blockage"
85363d1a8abSmrg  [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
85463d1a8abSmrg  ""
85563d1a8abSmrg  ""
85663d1a8abSmrg  [(set_attr "type" "unknown")
85763d1a8abSmrg   (set_attr "length" "0")])
85863d1a8abSmrg
85963d1a8abSmrg;; This is used in compiling the unwind routines.
86063d1a8abSmrg(define_expand "eh_return"
86163d1a8abSmrg  [(use (match_operand 0 "general_operand"))]
86263d1a8abSmrg  ""
86363d1a8abSmrg{
86463d1a8abSmrg  if (GET_MODE (operands[0]) != Pmode)
86563d1a8abSmrg    operands[0] = convert_to_mode (Pmode, operands[0], 0);
86663d1a8abSmrg  emit_insn (gen_eh_set_ra (operands[0]));
86763d1a8abSmrg  DONE;
86863d1a8abSmrg})
86963d1a8abSmrg
87063d1a8abSmrg;; Modify the return address for EH return.  We can't expand this
87163d1a8abSmrg;; until we know where it will be put in the stack frame.
87263d1a8abSmrg
87363d1a8abSmrg(define_insn_and_split "eh_set_ra"
87463d1a8abSmrg  [(unspec [(match_operand:SI 0 "register_operand" "r")] UNSPEC_EH_RETURN)
87563d1a8abSmrg   (clobber (match_scratch:SI 1 "=&r"))]
87663d1a8abSmrg  ""
87763d1a8abSmrg  "#"
87863d1a8abSmrg  "reload_completed"
87963d1a8abSmrg  [(const_int 0)]
88063d1a8abSmrg{
88163d1a8abSmrg  nios2_set_return_address (operands[0], operands[1]);
88263d1a8abSmrg  DONE;
88363d1a8abSmrg})
88463d1a8abSmrg
88563d1a8abSmrg
88663d1a8abSmrg;;  Jumps and calls
88763d1a8abSmrg
88863d1a8abSmrg; Note that the assembler fixes up any out-of-range branch instructions not
88963d1a8abSmrg; caught by the compiler branch shortening code.  The sequence emitted by
89063d1a8abSmrg; the assembler can be very inefficient, but it is correct for PIC code.
89163d1a8abSmrg; For non-PIC we are better off converting to an absolute JMPI.
89263d1a8abSmrg;
89363d1a8abSmrg; Direct calls and sibcalls use the CALL and JMPI instructions, respectively.
89463d1a8abSmrg; These instructions have an immediate operand that specifies the low 28 bits
89563d1a8abSmrg; of the PC, effectively allowing direct calls within a 256MB memory segment.
89663d1a8abSmrg; Per the Nios II Processor Reference Handbook, the linker is not required to
89763d1a8abSmrg; check or adjust for overflow.
89863d1a8abSmrg
89963d1a8abSmrg(define_insn "indirect_jump"
90063d1a8abSmrg  [(set (pc) (match_operand:SI 0 "register_operand" "c"))]
90163d1a8abSmrg  ""
90263d1a8abSmrg  "jmp%!\\t%0"
90363d1a8abSmrg  [(set_attr "type" "control")])
90463d1a8abSmrg
90563d1a8abSmrg(define_insn "jump"
90663d1a8abSmrg  [(set (pc)
90763d1a8abSmrg        (label_ref (match_operand 0 "" "")))]
90863d1a8abSmrg  ""
90963d1a8abSmrg  {
91063d1a8abSmrg    if (get_attr_length (insn) == 2)
91163d1a8abSmrg      return "br.n\\t%0";
91263d1a8abSmrg    else if (get_attr_length (insn) == 4)
91363d1a8abSmrg      return "br\\t%0";
91463d1a8abSmrg    else
91563d1a8abSmrg      return "jmpi\\t%0";
91663d1a8abSmrg  }
91763d1a8abSmrg  [(set_attr "type" "control")
91863d1a8abSmrg   (set (attr "length")
91963d1a8abSmrg        (if_then_else
92063d1a8abSmrg	    (and (match_test "TARGET_HAS_CDX")
92163d1a8abSmrg	         (and (ge (minus (match_dup 0) (pc)) (const_int -1022))
92263d1a8abSmrg	              (le (minus (match_dup 0) (pc)) (const_int 1022))))
92363d1a8abSmrg	    (const_int 2)
92463d1a8abSmrg	    (if_then_else
92563d1a8abSmrg	        (ior (match_test "flag_pic")
92663d1a8abSmrg	             (and (ge (minus (match_dup 0) (pc)) (const_int -32764))
92763d1a8abSmrg	                  (le (minus (match_dup 0) (pc)) (const_int 32764))))
92863d1a8abSmrg	        (const_int 4)
92963d1a8abSmrg	        (const_int 8))))])
93063d1a8abSmrg
93163d1a8abSmrg(define_expand "call"
93263d1a8abSmrg  [(parallel [(call (match_operand 0 "" "")
93363d1a8abSmrg                    (match_operand 1 "" ""))
93463d1a8abSmrg              (clobber (reg:SI RA_REGNO))])]
93563d1a8abSmrg  ""
93663d1a8abSmrg  "nios2_adjust_call_address (&operands[0], NULL_RTX);")
93763d1a8abSmrg
93863d1a8abSmrg(define_expand "call_value"
93963d1a8abSmrg  [(parallel [(set (match_operand 0 "" "")
94063d1a8abSmrg                   (call (match_operand 1 "" "")
94163d1a8abSmrg                         (match_operand 2 "" "")))
94263d1a8abSmrg              (clobber (reg:SI RA_REGNO))])]
94363d1a8abSmrg  ""
94463d1a8abSmrg  "nios2_adjust_call_address (&operands[1], NULL_RTX);")
94563d1a8abSmrg
94663d1a8abSmrg(define_insn "*call"
94763d1a8abSmrg  [(call (mem:QI (match_operand:SI 0 "call_operand" "i,r"))
94863d1a8abSmrg         (match_operand 1 "" ""))
94963d1a8abSmrg   (clobber (reg:SI RA_REGNO))]
95063d1a8abSmrg  ""
95163d1a8abSmrg  "@
95263d1a8abSmrg   call\\t%0
95363d1a8abSmrg   callr%.\\t%0"
95463d1a8abSmrg  [(set_attr "type" "control")])
95563d1a8abSmrg
95663d1a8abSmrg(define_insn "*call_value"
95763d1a8abSmrg  [(set (match_operand 0 "" "")
95863d1a8abSmrg        (call (mem:QI (match_operand:SI 1 "call_operand" "i,r"))
95963d1a8abSmrg              (match_operand 2 "" "")))
96063d1a8abSmrg   (clobber (reg:SI RA_REGNO))]
96163d1a8abSmrg  ""
96263d1a8abSmrg  "@
96363d1a8abSmrg   call\\t%1
96463d1a8abSmrg   callr%.\\t%1"
96563d1a8abSmrg  [(set_attr "type" "control")])
96663d1a8abSmrg
96763d1a8abSmrg(define_expand "sibcall"
96863d1a8abSmrg  [(parallel [(call (match_operand 0 "" "")
96963d1a8abSmrg                    (match_operand 1 "" ""))
97063d1a8abSmrg              (return)])]
97163d1a8abSmrg  ""
97263d1a8abSmrg  "nios2_adjust_call_address (&operands[0], NULL_RTX);")
97363d1a8abSmrg
97463d1a8abSmrg(define_expand "sibcall_value"
97563d1a8abSmrg  [(parallel [(set (match_operand 0 "" "")
97663d1a8abSmrg                   (call (match_operand 1 "" "")
97763d1a8abSmrg                         (match_operand 2 "" "")))
97863d1a8abSmrg              (return)])]
97963d1a8abSmrg  ""
98063d1a8abSmrg  "nios2_adjust_call_address (&operands[1], NULL_RTX);")
98163d1a8abSmrg
98263d1a8abSmrg(define_insn "sibcall_internal"
98363d1a8abSmrg [(call (mem:QI (match_operand:SI 0 "call_operand" "i,j"))
98463d1a8abSmrg        (match_operand 1 "" ""))
98563d1a8abSmrg  (return)]
98663d1a8abSmrg  ""
98763d1a8abSmrg  "@
98863d1a8abSmrg   jmpi\\t%0
98963d1a8abSmrg   jmp%!\\t%0"
99063d1a8abSmrg  [(set_attr "type" "control")])
99163d1a8abSmrg
99263d1a8abSmrg(define_insn "sibcall_value_internal"
99363d1a8abSmrg [(set (match_operand 0 "register_operand" "")
99463d1a8abSmrg       (call (mem:QI (match_operand:SI 1 "call_operand" "i,j"))
99563d1a8abSmrg             (match_operand 2 "" "")))
99663d1a8abSmrg  (return)]
99763d1a8abSmrg  ""
99863d1a8abSmrg  "@
99963d1a8abSmrg   jmpi\\t%1
100063d1a8abSmrg   jmp%!\\t%1"
100163d1a8abSmrg  [(set_attr "type" "control")])
100263d1a8abSmrg
100363d1a8abSmrg(define_expand "tablejump"
100463d1a8abSmrg  [(parallel [(set (pc) (match_operand 0 "register_operand" "r"))
100563d1a8abSmrg              (use (label_ref (match_operand 1 "" "")))])]
100663d1a8abSmrg  ""
100763d1a8abSmrg{
100863d1a8abSmrg  if (flag_pic)
100963d1a8abSmrg    {
101063d1a8abSmrg      /* Hopefully, CSE will eliminate this copy.  */
101163d1a8abSmrg      rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
101263d1a8abSmrg      rtx reg2 = gen_reg_rtx (SImode);
101363d1a8abSmrg
101463d1a8abSmrg      emit_insn (gen_addsi3 (reg2, operands[0], reg1));
101563d1a8abSmrg      operands[0] = reg2;
101663d1a8abSmrg    }
101763d1a8abSmrg})
101863d1a8abSmrg
101963d1a8abSmrg(define_insn "*tablejump"
102063d1a8abSmrg  [(set (pc)
102163d1a8abSmrg        (match_operand:SI 0 "register_operand" "c"))
102263d1a8abSmrg   (use (label_ref (match_operand 1 "" "")))]
102363d1a8abSmrg  ""
102463d1a8abSmrg  "jmp%!\\t%0"
102563d1a8abSmrg  [(set_attr "type" "control")])
102663d1a8abSmrg
102763d1a8abSmrg
102863d1a8abSmrg;; cstore, cbranch patterns
102963d1a8abSmrg
103063d1a8abSmrg(define_mode_iterator CM [SI SF DF])
103163d1a8abSmrg
103263d1a8abSmrg(define_expand "cstore<mode>4"
103363d1a8abSmrg  [(set (match_operand:SI 0 "register_operand" "=r")
103463d1a8abSmrg        (match_operator:SI 1 "expandable_comparison_operator"
103563d1a8abSmrg	  [(match_operand:CM 2 "register_operand")
103663d1a8abSmrg	   (match_operand:CM 3 "nonmemory_operand")]))]
103763d1a8abSmrg  ""
103863d1a8abSmrg{
103963d1a8abSmrg  if (!nios2_validate_compare (<MODE>mode, &operands[1], &operands[2],
104063d1a8abSmrg                               &operands[3]))
104163d1a8abSmrg    FAIL;
104263d1a8abSmrg})
104363d1a8abSmrg
104463d1a8abSmrg(define_expand "cbranch<mode>4"
104563d1a8abSmrg  [(set (pc)
104663d1a8abSmrg     (if_then_else
104763d1a8abSmrg       (match_operator 0 "expandable_comparison_operator"
104863d1a8abSmrg         [(match_operand:CM 1 "register_operand")
104963d1a8abSmrg          (match_operand:CM 2 "nonmemory_operand")])
105063d1a8abSmrg       (label_ref (match_operand 3 ""))
105163d1a8abSmrg       (pc)))]
105263d1a8abSmrg  ""
105363d1a8abSmrg{
105463d1a8abSmrg  if (!nios2_validate_compare (<MODE>mode, &operands[0], &operands[1],
105563d1a8abSmrg                               &operands[2]))
105663d1a8abSmrg    FAIL;
105763d1a8abSmrg  if (GET_MODE_CLASS (<MODE>mode) == MODE_FLOAT
105863d1a8abSmrg      || !reg_or_0_operand (operands[2], <MODE>mode))
105963d1a8abSmrg    {
106063d1a8abSmrg      rtx condreg = gen_reg_rtx (SImode);
106163d1a8abSmrg      emit_insn (gen_cstore<mode>4
106263d1a8abSmrg                  (condreg, operands[0], operands[1], operands[2]));
106363d1a8abSmrg      operands[1] = condreg;
106463d1a8abSmrg      operands[2] = const0_rtx;
106563d1a8abSmrg      operands[0] = gen_rtx_fmt_ee (NE, VOIDmode, condreg, const0_rtx);
106663d1a8abSmrg    }
106763d1a8abSmrg})
106863d1a8abSmrg
106963d1a8abSmrg(define_insn "nios2_cbranch"
107063d1a8abSmrg  [(set (pc)
107163d1a8abSmrg     (if_then_else
107263d1a8abSmrg       (match_operator 0 "ordered_comparison_operator"
107363d1a8abSmrg         [(match_operand:SI 1 "reg_or_0_operand" "rM")
107463d1a8abSmrg          (match_operand:SI 2 "reg_or_0_operand" "rM")])
107563d1a8abSmrg       (label_ref (match_operand 3 "" ""))
107663d1a8abSmrg       (pc)))]
107763d1a8abSmrg  ""
107863d1a8abSmrg{
107963d1a8abSmrg  if (get_attr_length (insn) == 2)
108063d1a8abSmrg    return "b%0z.n\t%z1, %l3";
108163d1a8abSmrg  else if (get_attr_length (insn) == 4)
108263d1a8abSmrg    return "b%0\t%z1, %z2, %l3";
108363d1a8abSmrg  else if (get_attr_length (insn) == 6)
108463d1a8abSmrg    return "b%R0z.n\t%z1, .+6;jmpi\t%l3";
108563d1a8abSmrg  else
108663d1a8abSmrg    return "b%R0\t%z1, %z2, .+8;jmpi\t%l3";
108763d1a8abSmrg}
108863d1a8abSmrg  [(set_attr "type" "control")
108963d1a8abSmrg   (set (attr "length")
109063d1a8abSmrg        (cond
109163d1a8abSmrg         [(and (match_test "nios2_cdx_narrow_form_p (insn)")
109263d1a8abSmrg               (ge (minus (match_dup 3) (pc)) (const_int -126))
109363d1a8abSmrg               (le (minus (match_dup 3) (pc)) (const_int 126)))
109463d1a8abSmrg          (const_int 2)
109563d1a8abSmrg          (ior (match_test "flag_pic")
109663d1a8abSmrg               (and (ge (minus (match_dup 3) (pc)) (const_int -32764))
109763d1a8abSmrg                    (le (minus (match_dup 3) (pc)) (const_int 32764))))
109863d1a8abSmrg          (const_int 4)
109963d1a8abSmrg          (match_test "nios2_cdx_narrow_form_p (insn)")
110063d1a8abSmrg          (const_int 6)]
110163d1a8abSmrg         (const_int 8)))])
110263d1a8abSmrg
110363d1a8abSmrg;; Floating point comparisons
110463d1a8abSmrg(define_code_iterator FCMP [eq ne gt ge le lt])
110563d1a8abSmrg(define_insn "nios2_s<code><mode>"
110663d1a8abSmrg  [(set (match_operand:SI 0 "register_operand"        "=r")
110763d1a8abSmrg        (FCMP:SI (match_operand:F 1 "register_operand" "r")
110863d1a8abSmrg                 (match_operand:F 2 "register_operand" "r")))]
110963d1a8abSmrg  "nios2_fpu_insn_enabled (n2fpu_fcmp<code><f>)"
111063d1a8abSmrg  { return nios2_fpu_insn_asm (n2fpu_fcmp<code><f>); }
111163d1a8abSmrg  [(set_attr "type" "custom")])
111263d1a8abSmrg
111363d1a8abSmrg;; Integer comparisons
111463d1a8abSmrg
111563d1a8abSmrg(define_code_iterator EQNE [eq ne])
111663d1a8abSmrg(define_insn "nios2_cmp<code>"
111763d1a8abSmrg  [(set (match_operand:SI 0 "register_operand"           "=r")
111863d1a8abSmrg        (EQNE:SI (match_operand:SI 1 "register_operand"  "%r")
111963d1a8abSmrg                 (match_operand:SI 2 "arith_operand"     "rI")))]
112063d1a8abSmrg  ""
112163d1a8abSmrg  "cmp<code>%i2\\t%0, %1, %z2"
112263d1a8abSmrg  [(set_attr "type" "alu")])
112363d1a8abSmrg
112463d1a8abSmrg(define_code_iterator SCMP [ge lt])
112563d1a8abSmrg(define_insn "nios2_cmp<code>"
112663d1a8abSmrg  [(set (match_operand:SI 0 "register_operand"           "=r")
112763d1a8abSmrg        (SCMP:SI (match_operand:SI 1 "reg_or_0_operand"  "rM")
112863d1a8abSmrg                 (match_operand:SI 2 "arith_operand"     "rI")))]
112963d1a8abSmrg  ""
113063d1a8abSmrg  "cmp<code>%i2\\t%0, %z1, %z2"
113163d1a8abSmrg  [(set_attr "type" "alu")])
113263d1a8abSmrg
113363d1a8abSmrg(define_code_iterator UCMP [geu ltu])
113463d1a8abSmrg(define_insn "nios2_cmp<code>"
113563d1a8abSmrg  [(set (match_operand:SI 0 "register_operand"           "=r")
113663d1a8abSmrg        (UCMP:SI (match_operand:SI 1 "reg_or_0_operand"  "rM")
113763d1a8abSmrg                 (match_operand:SI 2 "uns_arith_operand" "rJ")))]
113863d1a8abSmrg  ""
113963d1a8abSmrg  "cmp<code>%u2\\t%0, %z1, %z2"
114063d1a8abSmrg  [(set_attr "type" "alu")])
114163d1a8abSmrg
114263d1a8abSmrg
114363d1a8abSmrg
114463d1a8abSmrg;; Custom instruction patterns.  The operands are intentionally
114563d1a8abSmrg;; mode-less, to serve as generic carriers of all Altera defined
114663d1a8abSmrg;; built-in instruction/function types.
114763d1a8abSmrg
114863d1a8abSmrg(define_insn "custom_nxx"
114963d1a8abSmrg  [(unspec_volatile [(match_operand 0 "custom_insn_opcode" "N")
115063d1a8abSmrg                     (match_operand 1 "reg_or_0_operand"  "rM")
115163d1a8abSmrg                     (match_operand 2 "reg_or_0_operand"  "rM")]
115263d1a8abSmrg    UNSPECV_CUSTOM_NXX)]
115363d1a8abSmrg  ""
115463d1a8abSmrg  "custom\\t%0, zero, %z1, %z2"
115563d1a8abSmrg  [(set_attr "type" "custom")])
115663d1a8abSmrg
115763d1a8abSmrg(define_insn "custom_xnxx"
115863d1a8abSmrg  [(set (match_operand 0 "register_operand"   "=r")
115963d1a8abSmrg        (unspec_volatile [(match_operand 1 "custom_insn_opcode" "N")
116063d1a8abSmrg                          (match_operand 2 "reg_or_0_operand"  "rM")
116163d1a8abSmrg                          (match_operand 3 "reg_or_0_operand"  "rM")]
116263d1a8abSmrg	 UNSPECV_CUSTOM_XNXX))]
116363d1a8abSmrg  ""
116463d1a8abSmrg  "custom\\t%1, %0, %z2, %z3"
116563d1a8abSmrg  [(set_attr "type" "custom")])
116663d1a8abSmrg
116763d1a8abSmrg
116863d1a8abSmrg;;  Misc. patterns
116963d1a8abSmrg
117063d1a8abSmrg(define_insn "nop"
117163d1a8abSmrg  [(const_int 0)]
117263d1a8abSmrg  ""
117363d1a8abSmrg  "nop%."
117463d1a8abSmrg  [(set_attr "type" "nop")])
117563d1a8abSmrg
117663d1a8abSmrg;; Connect 'sync' to 'memory_barrier' standard expand name
117763d1a8abSmrg(define_expand "memory_barrier"
117863d1a8abSmrg  [(const_int 0)]
117963d1a8abSmrg  ""
118063d1a8abSmrg{
118163d1a8abSmrg  emit_insn (gen_sync ());
118263d1a8abSmrg  DONE;
118363d1a8abSmrg})
118463d1a8abSmrg
118563d1a8abSmrg;; For the nios2 __builtin_sync built-in function
118663d1a8abSmrg(define_expand "sync"
118763d1a8abSmrg  [(set (match_dup 0)
118863d1a8abSmrg	(unspec:BLK [(match_dup 0)] UNSPEC_SYNC))]
118963d1a8abSmrg  ""
119063d1a8abSmrg{
119163d1a8abSmrg  operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
119263d1a8abSmrg  MEM_VOLATILE_P (operands[0]) = 1;
119363d1a8abSmrg})
119463d1a8abSmrg
119563d1a8abSmrg(define_insn "*sync_insn"
119663d1a8abSmrg  [(set (match_operand:BLK 0 "" "")
119763d1a8abSmrg	(unspec:BLK [(match_dup 0)] UNSPEC_SYNC))]
119863d1a8abSmrg  ""
119963d1a8abSmrg  "sync"
120063d1a8abSmrg  [(set_attr "type" "control")])
120163d1a8abSmrg
120263d1a8abSmrg(define_insn "rdctl"
120363d1a8abSmrg  [(set (match_operand:SI 0 "register_operand" "=r")
120463d1a8abSmrg        (unspec_volatile:SI [(match_operand:SI 1 "rdwrctl_operand" "O")]
120563d1a8abSmrg	 UNSPECV_RDCTL))]
120663d1a8abSmrg  ""
120763d1a8abSmrg  "rdctl\\t%0, ctl%1"
120863d1a8abSmrg  [(set_attr "type" "control")])
120963d1a8abSmrg
121063d1a8abSmrg(define_insn "wrctl"
121163d1a8abSmrg  [(unspec_volatile:SI [(match_operand:SI 0 "rdwrctl_operand"  "O")
121263d1a8abSmrg                        (match_operand:SI 1 "reg_or_0_operand" "rM")]
121363d1a8abSmrg    UNSPECV_WRCTL)]
121463d1a8abSmrg  ""
121563d1a8abSmrg  "wrctl\\tctl%0, %z1"
121663d1a8abSmrg  [(set_attr "type" "control")])
121763d1a8abSmrg
121863d1a8abSmrg(define_insn "rdprs"
121963d1a8abSmrg  [(set (match_operand:SI 0 "register_operand" "=r")
122063d1a8abSmrg        (unspec_volatile:SI [(match_operand:SI 1 "rdwrctl_operand" "O")
122163d1a8abSmrg                             (match_operand:SI 2 "arith_operand"   "U")]
122263d1a8abSmrg         UNSPECV_RDPRS))]
122363d1a8abSmrg  ""
122463d1a8abSmrg  "rdprs\\t%0, %1, %2"
122563d1a8abSmrg  [(set_attr "type" "control")])
122663d1a8abSmrg
122763d1a8abSmrg;; Cache Instructions
122863d1a8abSmrg
122963d1a8abSmrg(define_insn "flushd"
123063d1a8abSmrg  [(unspec_volatile:SI [(match_operand:SI 0 "ldstio_memory_operand" "w")]
123163d1a8abSmrg  		        UNSPECV_FLUSHD)]
123263d1a8abSmrg  ""
123363d1a8abSmrg  "flushd\\t%0"
123463d1a8abSmrg  [(set_attr "type" "control")])
123563d1a8abSmrg
123663d1a8abSmrg(define_insn "flushda"
123763d1a8abSmrg  [(unspec_volatile:SI [(match_operand:SI 0 "ldstio_memory_operand" "w")]
123863d1a8abSmrg  		        UNSPECV_FLUSHDA)]
123963d1a8abSmrg  ""
124063d1a8abSmrg  "flushda\\t%0"
124163d1a8abSmrg  [(set_attr "type" "control")])
124263d1a8abSmrg
124363d1a8abSmrg;; R2 Instructions
124463d1a8abSmrg
124563d1a8abSmrg(define_insn "wrpie"
124663d1a8abSmrg  [(set (match_operand:SI 0 "register_operand" "=r")
124763d1a8abSmrg        (unspec_volatile:SI [(match_operand:SI 1 "register_operand" "r")]
124863d1a8abSmrg		 	     UNSPECV_WRPIE))]
124963d1a8abSmrg  "TARGET_ARCH_R2"
125063d1a8abSmrg  "wrpie\\t%0, %1"
125163d1a8abSmrg  [(set_attr "type" "control")])
125263d1a8abSmrg
125363d1a8abSmrg(define_insn "eni"
125463d1a8abSmrg  [(unspec:VOID [(match_operand 0 "const_int_operand" "i")]
125563d1a8abSmrg  		 UNSPECV_ENI)]
125663d1a8abSmrg  "TARGET_ARCH_R2"
125763d1a8abSmrg  "eni\\t%0"
125863d1a8abSmrg  [(set_attr "type" "control")])
125963d1a8abSmrg
126063d1a8abSmrg;; Trap patterns
126163d1a8abSmrg(define_insn "trap"
126263d1a8abSmrg  [(trap_if (const_int 1) (const_int 3))]
126363d1a8abSmrg  ""
126463d1a8abSmrg  "trap%.\\t3"
126563d1a8abSmrg  [(set_attr "type" "control")])
126663d1a8abSmrg
126763d1a8abSmrg(define_insn "ctrapsi4"
126863d1a8abSmrg  [(trap_if (match_operator 0 "ordered_comparison_operator"
126963d1a8abSmrg              [(match_operand:SI 1 "reg_or_0_operand" "rM")
127063d1a8abSmrg               (match_operand:SI 2 "reg_or_0_operand" "rM")])
127163d1a8abSmrg            (match_operand 3 "const_int_operand" "i"))]
127263d1a8abSmrg  ""
127363d1a8abSmrg{
127463d1a8abSmrg  if (get_attr_length (insn) == 6)
127563d1a8abSmrg    return "b%R0\\t%z1, %z2, 1f\;trap.n\\t%3\;1:";
127663d1a8abSmrg  else
127763d1a8abSmrg    return "b%R0\\t%z1, %z2, 1f\;trap\\t%3\;1:";
127863d1a8abSmrg}
127963d1a8abSmrg  [(set_attr "type" "control")
128063d1a8abSmrg   (set (attr "length")
128163d1a8abSmrg        (if_then_else (match_test "nios2_cdx_narrow_form_p (insn)")
128263d1a8abSmrg                      (const_int 6) (const_int 8)))])
128363d1a8abSmrg
128463d1a8abSmrg;; Load the GOT register.
128563d1a8abSmrg(define_insn "load_got_register"
128663d1a8abSmrg  [(set (match_operand:SI 0 "register_operand" "=&r")
128763d1a8abSmrg	 (unspec:SI [(const_int 0)] UNSPEC_LOAD_GOT_REGISTER))
128863d1a8abSmrg   (set (match_operand:SI 1 "register_operand" "=r")
128963d1a8abSmrg	 (unspec:SI [(const_int 0)] UNSPEC_LOAD_GOT_REGISTER))]
129063d1a8abSmrg  ""
129163d1a8abSmrg  "nextpc\\t%0
129263d1a8abSmrg\\t1:
129363d1a8abSmrg\\tmovhi\\t%1, %%hiadj(_gp_got - 1b)
129463d1a8abSmrg\\taddi\\t%1, %1, %%lo(_gp_got - 1b)"
129563d1a8abSmrg  [(set_attr "length" "12")])
129663d1a8abSmrg
129763d1a8abSmrg;; Read thread pointer register
129863d1a8abSmrg(define_expand "get_thread_pointersi"
129963d1a8abSmrg  [(match_operand:SI 0 "register_operand" "=r")]
130063d1a8abSmrg  "TARGET_LINUX_ABI"
130163d1a8abSmrg{
130263d1a8abSmrg  emit_move_insn (operands[0], gen_rtx_REG (Pmode, TP_REGNO));
130363d1a8abSmrg  DONE;
130463d1a8abSmrg})
130563d1a8abSmrg
130663d1a8abSmrg;; Synchronization Primitives
130763d1a8abSmrg(include "sync.md")
130863d1a8abSmrg
130963d1a8abSmrg;; Include the ldwm/stwm/push.n/pop.n patterns and peepholes.
131063d1a8abSmrg(include "ldstwm.md")
131163d1a8abSmrg
1312