]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/nios2/nios2.md
Update copyright years.
[thirdparty/gcc.git] / gcc / config / nios2 / nios2.md
CommitLineData
e430824f 1;; Machine Description for Altera Nios II.
8d9254fc 2;; Copyright (C) 2012-2020 Free Software Foundation, Inc.
e430824f
CLT
3;; Contributed by Jonah Graham (jgraham@altera.com) and
4;; Will Reece (wreece@altera.com).
5;; Contributed by Mentor Graphics, Inc.
6;;
7;; This file is part of GCC.
8;;
9;; GCC is free software; you can redistribute it and/or modify
10;; it under the terms of the GNU General Public License as published by
11;; the Free Software Foundation; either version 3, or (at your option)
12;; any later version.
13;;
14;; GCC is distributed in the hope that it will be useful,
15;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17;; GNU General Public License for more details.
18;;
19;; You should have received a copy of the GNU General Public License
20;; along with GCC; see the file COPYING3. If not see
21;; <http://www.gnu.org/licenses/>.
22
23;; Register numbers
24(define_constants
25 [
26 (FIRST_RETVAL_REGNO 2) ; Return value registers
27 (LAST_RETVAL_REGNO 3) ;
28 (FIRST_ARG_REGNO 4) ; Argument registers
29 (LAST_ARG_REGNO 7) ;
30
31 (TP_REGNO 23) ; Thread pointer register
32 (GP_REGNO 26) ; Global pointer register
3bbbe009 33 (SP_REGNO 27) ; Stack pointer register
e430824f
CLT
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
38
39 ;; Target register definitions
40 (STATIC_CHAIN_REGNUM 12)
41 (STACK_POINTER_REGNUM 27)
42 (HARD_FRAME_POINTER_REGNUM 28)
43 (PC_REGNUM 37)
44 (FRAME_POINTER_REGNUM 38)
45 (ARG_POINTER_REGNUM 39)
46 (FIRST_PSEUDO_REGISTER 40)
47 ]
48)
49
50;; Enumeration of UNSPECs
51
52(define_c_enum "unspecv" [
53 UNSPECV_BLOCKAGE
54 UNSPECV_WRCTL
55 UNSPECV_RDCTL
56 UNSPECV_FWRX
57 UNSPECV_FWRY
58 UNSPECV_FRDXLO
59 UNSPECV_FRDXHI
60 UNSPECV_FRDY
61 UNSPECV_CUSTOM_NXX
62 UNSPECV_CUSTOM_XNXX
63 UNSPECV_LDXIO
64 UNSPECV_STXIO
524d2e49
SL
65 UNSPECV_RDPRS
66 UNSPECV_FLUSHD
67 UNSPECV_FLUSHDA
68 UNSPECV_WRPIE
69 UNSPECV_ENI
70 UNSPECV_LDEX
71 UNSPECV_LDSEX
72 UNSPECV_STEX
73 UNSPECV_STSEX
e430824f
CLT
74])
75
76(define_c_enum "unspec" [
77 UNSPEC_FCOS
78 UNSPEC_FSIN
79 UNSPEC_FTAN
80 UNSPEC_FATAN
81 UNSPEC_FEXP
82 UNSPEC_FLOG
aa221564 83 UNSPEC_ROUND
e430824f
CLT
84 UNSPEC_LOAD_GOT_REGISTER
85 UNSPEC_PIC_SYM
86 UNSPEC_PIC_CALL_SYM
95ce7613 87 UNSPEC_PIC_GOTOFF_SYM
e430824f
CLT
88 UNSPEC_LOAD_TLS_IE
89 UNSPEC_ADD_TLS_LE
90 UNSPEC_ADD_TLS_GD
91 UNSPEC_ADD_TLS_LDM
92 UNSPEC_ADD_TLS_LDO
93 UNSPEC_EH_RETURN
94 UNSPEC_SYNC
95])
96
97\f
98;; Instruction scheduler
99
100; No schedule info is currently available, using an assumption that no
101; instruction can use the results of the previous instruction without
102; incuring a stall.
103
104; length of an instruction (in bytes)
3bbbe009
SL
105(define_attr "length" ""
106 (if_then_else (match_test "nios2_cdx_narrow_form_p (insn)")
107 (const_int 2)
108 (const_int 4)))
109
e430824f 110(define_attr "type"
3bbbe009
SL
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"
e430824f
CLT
113 (const_string "complex"))
114
115(define_asm_attributes
116 [(set_attr "length" "4")
117 (set_attr "type" "complex")])
118
119(define_automaton "nios2")
120(automata_option "v")
121;(automata_option "no-minimization")
122(automata_option "ndfa")
123
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.
128
129(define_cpu_unit "cpu" "nios2")
130
131(define_insn_reservation "complex" 1
132 (eq_attr "type" "complex")
133 "cpu")
134
135(define_insn_reservation "control" 1
3bbbe009 136 (eq_attr "type" "control,pop")
e430824f
CLT
137 "cpu")
138
139(define_insn_reservation "alu" 1
3bbbe009 140 (eq_attr "type" "alu,add,sub,mov,and,or,xor,neg,not")
e430824f
CLT
141 "cpu")
142
143(define_insn_reservation "cond_alu" 1
144 (eq_attr "type" "cond_alu")
145 "cpu")
146
147(define_insn_reservation "st" 1
3bbbe009 148 (eq_attr "type" "st,stwm,push")
e430824f
CLT
149 "cpu")
150
151(define_insn_reservation "custom" 1
152 (eq_attr "type" "custom")
153 "cpu")
154
155; shifts, muls and lds have three cycle latency
156(define_insn_reservation "ld" 3
3bbbe009 157 (eq_attr "type" "ld,ldwm")
e430824f
CLT
158 "cpu")
159
160(define_insn_reservation "shift" 3
3bbbe009 161 (eq_attr "type" "sll,srl,sra,rol,ror")
e430824f
CLT
162 "cpu")
163
164(define_insn_reservation "mul" 3
165 (eq_attr "type" "mul")
166 "cpu")
167
168(define_insn_reservation "div" 1
169 (eq_attr "type" "div")
170 "cpu")
171
172(include "predicates.md")
173(include "constraints.md")
174
175\f
176;; Move instructions
177
178(define_mode_iterator M [QI HI SI])
179
180(define_expand "mov<mode>"
181 [(set (match_operand:M 0 "nonimmediate_operand" "")
182 (match_operand:M 1 "general_operand" ""))]
183 ""
184{
185 if (nios2_emit_move_sequence (operands, <MODE>mode))
186 DONE;
187})
188
3bbbe009
SL
189(define_insn "*high"
190 [(set (match_operand:SI 0 "register_operand" "=r")
191 (high:SI (match_operand:SI 1 "immediate_operand" "i")))]
192 ""
193 "movhi\\t%0, %H1"
194 [(set_attr "type" "alu")])
195
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")))]
200 ""
201 "addi\\t%0, %1, %L2"
202 [(set_attr "type" "alu")])
203
82348675 204(define_insn_and_split "movqi_internal"
3bbbe009
SL
205 [(set (match_operand:QI 0 "nonimmediate_operand" "=m, r,r")
206 (match_operand:QI 1 "general_operand" "rM,m,rI"))]
e430824f
CLT
207 "(register_operand (operands[0], QImode)
208 || reg_or_0_operand (operands[1], QImode))"
3bbbe009
SL
209 {
210 switch (which_alternative)
211 {
212 case 0:
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";
217 else
218 return "stb.n\\t%z1, %0";
219 case 1:
220 return "ldbu%o1%.\\t%0, %1";
221 case 2:
222 return "mov%i1%.\\t%0, %z1";
223 default:
224 gcc_unreachable ();
225 }
226 }
df8ceba6
SL
227 "(nios2_large_constant_memory_operand_p (operands[0])
228 || nios2_large_constant_memory_operand_p (operands[1]))"
82348675
SL
229 [(set (match_dup 0) (match_dup 1))]
230 {
df8ceba6
SL
231 if (nios2_large_constant_memory_operand_p (operands[0]))
232 operands[0] = nios2_split_large_constant_memory_operand (operands[0]);
82348675 233 else
df8ceba6 234 operands[1] = nios2_split_large_constant_memory_operand (operands[1]);
82348675 235 }
3bbbe009 236 [(set_attr "type" "st,ld,mov")])
e430824f 237
82348675 238(define_insn_and_split "movhi_internal"
3bbbe009
SL
239 [(set (match_operand:HI 0 "nonimmediate_operand" "=m, r,r")
240 (match_operand:HI 1 "general_operand" "rM,m,rI"))]
e430824f
CLT
241 "(register_operand (operands[0], HImode)
242 || reg_or_0_operand (operands[1], HImode))"
82348675
SL
243 {
244 switch (which_alternative)
245 {
246 case 0:
247 return "sth%o0%.\\t%z1, %0";
248 case 1:
249 return "ldhu%o1%.\\t%0, %1";
250 case 2:
251 return "mov%i1%.\\t%0, %z1";
252 default:
253 gcc_unreachable ();
254 }
255 }
df8ceba6
SL
256 "(nios2_large_constant_memory_operand_p (operands[0])
257 || nios2_large_constant_memory_operand_p (operands[1]))"
82348675
SL
258 [(set (match_dup 0) (match_dup 1))]
259 {
df8ceba6
SL
260 if (nios2_large_constant_memory_operand_p (operands[0]))
261 operands[0] = nios2_split_large_constant_memory_operand (operands[0]);
82348675 262 else
df8ceba6 263 operands[1] = nios2_split_large_constant_memory_operand (operands[1]);
82348675 264 }
3bbbe009 265 [(set_attr "type" "st,ld,mov")])
e430824f 266
82348675 267(define_insn_and_split "movsi_internal"
3bbbe009
SL
268 [(set (match_operand:SI 0 "nonimmediate_operand" "=m, r,r, r")
269 (match_operand:SI 1 "general_operand" "rM,m,rIJK,S"))]
e430824f
CLT
270 "(register_operand (operands[0], SImode)
271 || reg_or_0_operand (operands[1], SImode))"
3bbbe009
SL
272 {
273 switch (which_alternative)
274 {
275 case 0:
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";
282 else
283 return "stw.n\\t%z1, %0";
284 case 1:
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";
289 else
290 return "ldw.n\\t%0, %1";
291 case 2:
292 return "mov%i1%.\\t%0, %z1";
293 case 3:
294 return "addi\\t%0, gp, %%gprel(%1)";
295 default:
296 gcc_unreachable ();
297 }
298 }
df8ceba6
SL
299 "(nios2_large_constant_memory_operand_p (operands[0])
300 || nios2_large_constant_memory_operand_p (operands[1])
94223579
SL
301 || (nios2_large_constant_p (operands[1])
302 && !(CONST_INT_P (operands[1])
303 && (SMALL_INT_UNSIGNED (INTVAL (operands[1]))
304 || UPPER16_INT (INTVAL (operands[1]))))))"
82348675
SL
305 [(set (match_dup 0) (match_dup 1))]
306 {
df8ceba6
SL
307 if (nios2_large_constant_memory_operand_p (operands[0]))
308 operands[0] = nios2_split_large_constant_memory_operand (operands[0]);
309 else if (nios2_large_constant_memory_operand_p (operands[1]))
310 operands[1] = nios2_split_large_constant_memory_operand (operands[1]);
82348675
SL
311 else
312 operands[1] = nios2_split_large_constant (operands[1], operands[0]);
313 }
3bbbe009 314 [(set_attr "type" "st,ld,mov,alu")])
e430824f
CLT
315
316(define_mode_iterator BH [QI HI])
317(define_mode_iterator BHW [QI HI SI])
318(define_mode_attr bh [(QI "b") (HI "h")])
319(define_mode_attr bhw [(QI "b") (HI "h") (SI "w")])
320(define_mode_attr bhw_uns [(QI "bu") (HI "hu") (SI "w")])
321
e0727ae5 322(define_insn_and_split "ld<bhw_uns>io"
e430824f
CLT
323 [(set (match_operand:BHW 0 "register_operand" "=r")
324 (unspec_volatile:BHW
42e6ab74 325 [(match_operand:BHW 1 "ldstio_memory_operand" "w")] UNSPECV_LDXIO))]
e430824f
CLT
326 ""
327 "ld<bhw_uns>io\\t%0, %1"
e0727ae5
SL
328 "nios2_large_constant_memory_operand_p (operands[1])"
329 [(set (match_dup 0)
330 (unspec_volatile:BHW [(match_dup 1)] UNSPECV_LDXIO))]
331 {
332 operands[1] = nios2_split_large_constant_memory_operand (operands[1]);
333 }
e430824f
CLT
334 [(set_attr "type" "ld")])
335
336(define_expand "ld<bh>io"
337 [(set (match_operand:BH 0 "register_operand" "=r")
42e6ab74 338 (match_operand:BH 1 "ldstio_memory_operand" "w"))]
e430824f
CLT
339 ""
340{
341 rtx tmp = gen_reg_rtx (SImode);
342 emit_insn (gen_ld<bh>io_signed (tmp, operands[1]));
343 emit_insn (gen_mov<mode> (operands[0], gen_lowpart (<MODE>mode, tmp)));
344 DONE;
345})
346
e0727ae5 347(define_insn_and_split "ld<bh>io_signed"
e430824f
CLT
348 [(set (match_operand:SI 0 "register_operand" "=r")
349 (sign_extend:SI
350 (unspec_volatile:BH
42e6ab74 351 [(match_operand:BH 1 "ldstio_memory_operand" "w")] UNSPECV_LDXIO)))]
e430824f
CLT
352 ""
353 "ld<bh>io\\t%0, %1"
e0727ae5
SL
354 "nios2_large_constant_memory_operand_p (operands[1])"
355 [(set (match_dup 0)
356 (sign_extend:SI (unspec_volatile:BH [(match_dup 1)] UNSPECV_LDXIO)))]
357 {
358 operands[1] = nios2_split_large_constant_memory_operand (operands[1]);
359 }
e430824f
CLT
360 [(set_attr "type" "ld")])
361
e0727ae5 362(define_insn_and_split "st<bhw>io"
42e6ab74 363 [(set (match_operand:BHW 0 "ldstio_memory_operand" "=w")
e430824f
CLT
364 (unspec_volatile:BHW
365 [(match_operand:BHW 1 "reg_or_0_operand" "rM")] UNSPECV_STXIO))]
366 ""
367 "st<bhw>io\\t%z1, %0"
e0727ae5
SL
368 "nios2_large_constant_memory_operand_p (operands[0])"
369 [(set (match_dup 0) (unspec_volatile:BHW [(match_dup 1)] UNSPECV_STXIO))]
370 {
371 operands[0] = nios2_split_large_constant_memory_operand (operands[0]);
372 }
e430824f
CLT
373 [(set_attr "type" "st")])
374
375\f
376;; QI to [HI, SI] extension patterns are collected together
377(define_mode_iterator QX [HI SI])
378
379;; Zero extension patterns
82348675 380(define_insn_and_split "zero_extendhisi2"
e430824f
CLT
381 [(set (match_operand:SI 0 "register_operand" "=r,r")
382 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
383 ""
384 "@
3bbbe009
SL
385 andi%.\\t%0, %1, 0xffff
386 ldhu%o1%.\\t%0, %1"
df8ceba6 387 "nios2_large_constant_memory_operand_p (operands[1])"
82348675
SL
388 [(set (match_dup 0) (zero_extend:SI (match_dup 1)))]
389 {
df8ceba6 390 operands[1] = nios2_split_large_constant_memory_operand (operands[1]);
82348675 391 }
3bbbe009 392 [(set_attr "type" "and,ld")])
e430824f 393
82348675 394(define_insn_and_split "zero_extendqi<mode>2"
e430824f
CLT
395 [(set (match_operand:QX 0 "register_operand" "=r,r")
396 (zero_extend:QX (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
397 ""
398 "@
3bbbe009
SL
399 andi%.\\t%0, %1, 0xff
400 ldbu%o1%.\\t%0, %1"
df8ceba6 401 "nios2_large_constant_memory_operand_p (operands[1])"
82348675
SL
402 [(set (match_dup 0) (zero_extend:QX (match_dup 1)))]
403 {
df8ceba6 404 operands[1] = nios2_split_large_constant_memory_operand (operands[1]);
82348675 405 }
3bbbe009 406 [(set_attr "type" "and,ld")])
e430824f
CLT
407
408;; Sign extension patterns
409
82348675 410(define_insn_and_split "extendhisi2"
e430824f
CLT
411 [(set (match_operand:SI 0 "register_operand" "=r,r")
412 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
413 ""
414 "@
415 #
3bbbe009 416 ldh%o1%.\\t%0, %1"
df8ceba6 417 "nios2_large_constant_memory_operand_p (operands[1])"
82348675
SL
418 [(set (match_dup 0) (sign_extend:SI (match_dup 1)))]
419 {
df8ceba6 420 operands[1] = nios2_split_large_constant_memory_operand (operands[1]);
82348675 421 }
e430824f
CLT
422 [(set_attr "type" "alu,ld")])
423
82348675 424(define_insn_and_split "extendqi<mode>2"
e430824f
CLT
425 [(set (match_operand:QX 0 "register_operand" "=r,r")
426 (sign_extend:QX (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
427 ""
428 "@
429 #
3bbbe009 430 ldb%o1%.\\t%0, %1"
df8ceba6 431 "nios2_large_constant_memory_operand_p (operands[1])"
82348675
SL
432 [(set (match_dup 0) (sign_extend:QX (match_dup 1)))]
433 {
df8ceba6 434 operands[1] = nios2_split_large_constant_memory_operand (operands[1]);
82348675 435 }
e430824f
CLT
436 [(set_attr "type" "alu,ld")])
437
438;; Split patterns for register alternative cases.
439(define_split
440 [(set (match_operand:SI 0 "register_operand" "")
441 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
442 "reload_completed"
443 [(set (match_dup 0)
444 (and:SI (match_dup 1) (const_int 65535)))
445 (set (match_dup 0)
446 (xor:SI (match_dup 0) (const_int 32768)))
447 (set (match_dup 0)
448 (plus:SI (match_dup 0) (const_int -32768)))]
449 "operands[1] = gen_lowpart (SImode, operands[1]);")
450
451(define_split
452 [(set (match_operand:QX 0 "register_operand" "")
453 (sign_extend:QX (match_operand:QI 1 "register_operand" "")))]
454 "reload_completed"
455 [(set (match_dup 0)
456 (and:SI (match_dup 1) (const_int 255)))
457 (set (match_dup 0)
458 (xor:SI (match_dup 0) (const_int 128)))
459 (set (match_dup 0)
460 (plus:SI (match_dup 0) (const_int -128)))]
461 "operands[0] = gen_lowpart (SImode, operands[0]);
462 operands[1] = gen_lowpart (SImode, operands[1]);")
463
464\f
465;; Arithmetic Operations
466
467(define_insn "addsi3"
468 [(set (match_operand:SI 0 "register_operand" "=r")
469 (plus:SI (match_operand:SI 1 "register_operand" "%r")
470 (match_operand:SI 2 "add_regimm_operand" "rIT")))]
471 ""
3bbbe009
SL
472{
473 return nios2_add_insn_asm (insn, operands);
474}
475 [(set_attr "type" "add")])
e430824f
CLT
476
477(define_insn "subsi3"
478 [(set (match_operand:SI 0 "register_operand" "=r")
479 (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rM")
480 (match_operand:SI 2 "register_operand" "r")))]
481 ""
3bbbe009
SL
482 "sub%.\\t%0, %z1, %2"
483 [(set_attr "type" "sub")])
e430824f
CLT
484
485(define_insn "mulsi3"
486 [(set (match_operand:SI 0 "register_operand" "=r")
487 (mult:SI (match_operand:SI 1 "register_operand" "%r")
488 (match_operand:SI 2 "arith_operand" "rI")))]
489 "TARGET_HAS_MUL"
490 "mul%i2\\t%0, %1, %z2"
491 [(set_attr "type" "mul")])
492
493(define_expand "divsi3"
494 [(set (match_operand:SI 0 "register_operand" "=r")
495 (div:SI (match_operand:SI 1 "register_operand" "r")
496 (match_operand:SI 2 "register_operand" "r")))]
497 ""
498{
499 if (!TARGET_HAS_DIV)
500 {
501 if (TARGET_FAST_SW_DIV)
502 {
503 nios2_emit_expensive_div (operands, SImode);
504 DONE;
505 }
506 else
507 FAIL;
508 }
509})
510
511(define_insn "divsi3_insn"
512 [(set (match_operand:SI 0 "register_operand" "=r")
513 (div:SI (match_operand:SI 1 "register_operand" "r")
514 (match_operand:SI 2 "register_operand" "r")))]
515 "TARGET_HAS_DIV"
516 "div\\t%0, %1, %2"
517 [(set_attr "type" "div")])
518
519(define_insn "udivsi3"
520 [(set (match_operand:SI 0 "register_operand" "=r")
521 (udiv:SI (match_operand:SI 1 "register_operand" "r")
522 (match_operand:SI 2 "register_operand" "r")))]
523 "TARGET_HAS_DIV"
524 "divu\\t%0, %1, %2"
525 [(set_attr "type" "div")])
526
527(define_code_iterator EXTEND [sign_extend zero_extend])
528(define_code_attr us [(sign_extend "s") (zero_extend "u")])
529(define_code_attr mul [(sign_extend "mul") (zero_extend "umul")])
530
531(define_insn "<us>mulsi3_highpart"
532 [(set (match_operand:SI 0 "register_operand" "=r")
533 (truncate:SI
534 (lshiftrt:DI
535 (mult:DI (EXTEND:DI (match_operand:SI 1 "register_operand" "r"))
536 (EXTEND:DI (match_operand:SI 2 "register_operand" "r")))
537 (const_int 32))))]
538 "TARGET_HAS_MULX"
539 "mulx<us><us>\\t%0, %1, %2"
540 [(set_attr "type" "mul")])
541
542(define_expand "<mul>sidi3"
543 [(set (match_operand:DI 0 "register_operand" "")
544 (mult:DI (EXTEND:DI (match_operand:SI 1 "register_operand" ""))
545 (EXTEND:DI (match_operand:SI 2 "register_operand" ""))))]
546 "TARGET_HAS_MULX"
547{
548 rtx hi = gen_reg_rtx (SImode);
549 rtx lo = gen_reg_rtx (SImode);
550
551 emit_insn (gen_<us>mulsi3_highpart (hi, operands[1], operands[2]));
552 emit_insn (gen_mulsi3 (lo, operands[1], operands[2]));
553 emit_move_insn (gen_lowpart (SImode, operands[0]), lo);
554 emit_move_insn (gen_highpart (SImode, operands[0]), hi);
555 DONE;
556})
557
558\f
559;; Negate and ones complement
560
561(define_insn "negsi2"
562 [(set (match_operand:SI 0 "register_operand" "=r")
563 (neg:SI (match_operand:SI 1 "register_operand" "r")))]
564 ""
3bbbe009
SL
565{
566 if (get_attr_length (insn) == 2)
567 return "neg.n\\t%0, %1";
568 else
569 return "sub\\t%0, zero, %1";
570}
571 [(set_attr "type" "neg")])
e430824f
CLT
572
573(define_insn "one_cmplsi2"
574 [(set (match_operand:SI 0 "register_operand" "=r")
575 (not:SI (match_operand:SI 1 "register_operand" "r")))]
576 ""
3bbbe009
SL
577{
578 if (get_attr_length (insn) == 2)
579 return "not.n\\t%0, %1";
580 else
581 return "nor\\t%0, zero, %1";
582}
583 [(set_attr "type" "not")])
e430824f
CLT
584
585\f
586;; Integer logical Operations
587
3bbbe009
SL
588(define_insn "andsi3"
589 [(set (match_operand:SI 0 "register_operand" "=r")
590 (and:SI (match_operand:SI 1 "register_operand" "%r")
591 (match_operand:SI 2 "and_operand" "rJKP")))]
592 ""
593 "and%x2%.\\t%0, %1, %y2"
594 [(set_attr "type" "and")])
595
596(define_code_iterator LOGICAL [ior xor])
597(define_code_attr logical_asm [(ior "or") (xor "xor")])
e430824f
CLT
598
599(define_insn "<code>si3"
3bbbe009
SL
600 [(set (match_operand:SI 0 "register_operand" "=r")
601 (LOGICAL:SI (match_operand:SI 1 "register_operand" "%r")
602 (match_operand:SI 2 "logical_operand" "rJK")))]
e430824f 603 ""
3bbbe009
SL
604 "<logical_asm>%x2%.\\t%0, %1, %y2"
605 [(set_attr "type" "<logical_asm>")])
e430824f
CLT
606
607(define_insn "*norsi3"
608 [(set (match_operand:SI 0 "register_operand" "=r")
609 (and:SI (not:SI (match_operand:SI 1 "register_operand" "%r"))
610 (not:SI (match_operand:SI 2 "register_operand" "r"))))]
611 ""
612 "nor\\t%0, %1, %2"
613 [(set_attr "type" "alu")])
614
615\f
616;; Shift instructions
617
618(define_code_iterator SHIFT [ashift ashiftrt lshiftrt rotate])
619(define_code_attr shift_op [(ashift "ashl") (ashiftrt "ashr")
620 (lshiftrt "lshr") (rotate "rotl")])
621(define_code_attr shift_asm [(ashift "sll") (ashiftrt "sra")
622 (lshiftrt "srl") (rotate "rol")])
623
624(define_insn "<shift_op>si3"
625 [(set (match_operand:SI 0 "register_operand" "=r")
626 (SHIFT:SI (match_operand:SI 1 "register_operand" "r")
627 (match_operand:SI 2 "shift_operand" "rL")))]
628 ""
3bbbe009
SL
629 "<shift_asm>%i2%.\\t%0, %1, %z2"
630 [(set_attr "type" "<shift_asm>")])
e430824f
CLT
631
632(define_insn "rotrsi3"
633 [(set (match_operand:SI 0 "register_operand" "=r")
634 (rotatert:SI (match_operand:SI 1 "register_operand" "r")
635 (match_operand:SI 2 "register_operand" "r")))]
636 ""
637 "ror\\t%0, %1, %2"
3bbbe009
SL
638 [(set_attr "type" "ror")])
639
640;; Nios II R2 Bit Manipulation Extension (BMX), provides
641;; bit merge/insertion/extraction instructions.
642
643(define_insn "*merge"
644 [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r")
645 (match_operand:SI 1 "const_shift_operand" "L")
646 (match_operand:SI 2 "const_shift_operand" "L"))
647 (zero_extract:SI (match_operand:SI 3 "register_operand" "r")
648 (match_dup 1) (match_dup 2)))]
649 "TARGET_HAS_BMX"
650{
651 operands[4] = GEN_INT (INTVAL (operands[1]) + INTVAL (operands[2]) - 1);
652 return "merge\\t%0, %3, %4, %2";
653}
654 [(set_attr "type" "alu")])
655
656(define_insn "extzv"
657 [(set (match_operand:SI 0 "register_operand" "=r")
658 (zero_extract:SI (match_operand:SI 1 "register_operand" "r")
659 (match_operand:SI 2 "const_shift_operand" "L")
660 (match_operand:SI 3 "const_shift_operand" "L")))]
661 "TARGET_HAS_BMX"
662{
663 operands[4] = GEN_INT (INTVAL (operands[2]) + INTVAL (operands[3]) - 1);
664 return "extract\\t%0, %1, %4, %3";
665}
666 [(set_attr "type" "alu")])
667
668(define_insn "insv"
669 [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r")
670 (match_operand:SI 1 "const_shift_operand" "L")
671 (match_operand:SI 2 "const_shift_operand" "L"))
672 (match_operand:SI 3 "reg_or_0_operand" "rM"))]
673 "TARGET_HAS_BMX"
674{
675 operands[4] = GEN_INT (INTVAL (operands[1]) + INTVAL (operands[2]) - 1);
676 return "insert\\t%0, %z3, %4, %2";
677}
678 [(set_attr "type" "alu")])
679
e430824f
CLT
680
681\f
682;; Floating point instructions
683
684;; Mode iterator for single/double float
685(define_mode_iterator F [SF DF])
686(define_mode_attr f [(SF "s") (DF "d")])
687
688;; Basic arithmetic instructions
689(define_code_iterator FOP3 [plus minus mult div])
690(define_code_attr fop3 [(plus "add") (minus "sub") (mult "mul") (div "div")])
691
692(define_insn "<fop3><mode>3"
693 [(set (match_operand:F 0 "register_operand" "=r")
694 (FOP3:F (match_operand:F 1 "register_operand" "r")
695 (match_operand:F 2 "register_operand" "r")))]
696 "nios2_fpu_insn_enabled (n2fpu_f<fop3><f>)"
697 { return nios2_fpu_insn_asm (n2fpu_f<fop3><f>); }
698 [(set_attr "type" "custom")])
699
700;; Floating point min/max operations
701(define_code_iterator SMINMAX [smin smax])
702(define_code_attr minmax [(smin "min") (smax "max")])
703(define_insn "<code><mode>3"
704 [(set (match_operand:F 0 "register_operand" "=r")
705 (SMINMAX:F (match_operand:F 1 "register_operand" "r")
706 (match_operand:F 2 "register_operand" "r")))]
707 "nios2_fpu_insn_enabled (n2fpu_f<minmax><f>)"
708 { return nios2_fpu_insn_asm (n2fpu_f<minmax><f>); }
709 [(set_attr "type" "custom")])
710
711;; These 2-operand FP operations can be collected together
712(define_code_iterator FOP2 [abs neg sqrt])
713(define_insn "<code><mode>2"
714 [(set (match_operand:F 0 "register_operand" "=r")
715 (FOP2:F (match_operand:F 1 "register_operand" "r")))]
716 "nios2_fpu_insn_enabled (n2fpu_f<code><f>)"
717 { return nios2_fpu_insn_asm (n2fpu_f<code><f>); }
718 [(set_attr "type" "custom")])
719
720;; X, Y register access instructions
721(define_insn "nios2_fwrx"
722 [(unspec_volatile [(match_operand:DF 0 "register_operand" "r")] UNSPECV_FWRX)]
723 "nios2_fpu_insn_enabled (n2fpu_fwrx)"
724 { return nios2_fpu_insn_asm (n2fpu_fwrx); }
725 [(set_attr "type" "custom")])
726
727(define_insn "nios2_fwry"
728 [(unspec_volatile [(match_operand:SF 0 "register_operand" "r")] UNSPECV_FWRY)]
729 "nios2_fpu_insn_enabled (n2fpu_fwry)"
730 { return nios2_fpu_insn_asm (n2fpu_fwry); }
731 [(set_attr "type" "custom")])
732
733;; The X, Y read insns uses an int iterator
734(define_int_iterator UNSPEC_READ_XY [UNSPECV_FRDXLO UNSPECV_FRDXHI
735 UNSPECV_FRDY])
736(define_int_attr read_xy [(UNSPECV_FRDXLO "frdxlo") (UNSPECV_FRDXHI "frdxhi")
737 (UNSPECV_FRDY "frdy")])
738(define_insn "nios2_<read_xy>"
739 [(set (match_operand:SF 0 "register_operand" "=r")
740 (unspec_volatile:SF [(const_int 0)] UNSPEC_READ_XY))]
741 "nios2_fpu_insn_enabled (n2fpu_<read_xy>)"
742 { return nios2_fpu_insn_asm (n2fpu_<read_xy>); }
743 [(set_attr "type" "custom")])
744
745;; Various math functions
746(define_int_iterator MATHFUNC
747 [UNSPEC_FCOS UNSPEC_FSIN UNSPEC_FTAN UNSPEC_FATAN UNSPEC_FEXP UNSPEC_FLOG])
748(define_int_attr mathfunc [(UNSPEC_FCOS "cos") (UNSPEC_FSIN "sin")
749 (UNSPEC_FTAN "tan") (UNSPEC_FATAN "atan")
750 (UNSPEC_FEXP "exp") (UNSPEC_FLOG "log")])
751
752(define_insn "<mathfunc><mode>2"
753 [(set (match_operand:F 0 "register_operand" "=r")
754 (unspec:F [(match_operand:F 1 "register_operand" "r")] MATHFUNC))]
755 "nios2_fpu_insn_enabled (n2fpu_f<mathfunc><f>)"
756 { return nios2_fpu_insn_asm (n2fpu_f<mathfunc><f>); }
757 [(set_attr "type" "custom")])
758
759;; Converting between floating point and fixed point
760
761(define_code_iterator FLOAT [float unsigned_float])
762(define_code_iterator FIX [fix unsigned_fix])
763
764(define_code_attr conv_op [(float "float") (unsigned_float "floatuns")
765 (fix "fix") (unsigned_fix "fixuns")])
766(define_code_attr i [(float "i") (unsigned_float "u")
767 (fix "i") (unsigned_fix "u")])
768
769;; Integer to float conversions
770(define_insn "<conv_op>si<mode>2"
771 [(set (match_operand:F 0 "register_operand" "=r")
772 (FLOAT:F (match_operand:SI 1 "register_operand" "r")))]
773 "nios2_fpu_insn_enabled (n2fpu_float<i><f>)"
774 { return nios2_fpu_insn_asm (n2fpu_float<i><f>); }
775 [(set_attr "type" "custom")])
776
777;; Float to integer conversions
778(define_insn "<conv_op>_trunc<mode>si2"
779 [(set (match_operand:SI 0 "register_operand" "=r")
780 (FIX:SI (match_operand:F 1 "general_operand" "r")))]
781 "nios2_fpu_insn_enabled (n2fpu_fix<f><i>)"
782 { return nios2_fpu_insn_asm (n2fpu_fix<f><i>); }
783 [(set_attr "type" "custom")])
aa221564
SL
784
785(define_insn "lroundsfsi2"
786 [(set (match_operand:SI 0 "register_operand" "=r")
787 (unspec:SI [(match_operand:SF 1 "general_operand" "r")] UNSPEC_ROUND))]
788 "nios2_fpu_insn_enabled (n2fpu_round)"
789 { return nios2_fpu_insn_asm (n2fpu_round); }
790 [(set_attr "type" "custom")])
e430824f
CLT
791
792(define_insn "extendsfdf2"
793 [(set (match_operand:DF 0 "register_operand" "=r")
794 (float_extend:DF (match_operand:SF 1 "general_operand" "r")))]
795 "nios2_fpu_insn_enabled (n2fpu_fextsd)"
796 { return nios2_fpu_insn_asm (n2fpu_fextsd); }
797 [(set_attr "type" "custom")])
798
799(define_insn "truncdfsf2"
800 [(set (match_operand:SF 0 "register_operand" "=r")
801 (float_truncate:SF (match_operand:DF 1 "general_operand" "r")))]
802 "nios2_fpu_insn_enabled (n2fpu_ftruncds)"
803 { return nios2_fpu_insn_asm (n2fpu_ftruncds); }
804 [(set_attr "type" "custom")])
805
806
807\f
808;; Prologue, Epilogue and Return
809
810(define_expand "prologue"
811 [(const_int 1)]
812 ""
813{
814 nios2_expand_prologue ();
815 DONE;
816})
817
818(define_expand "epilogue"
819 [(return)]
820 ""
821{
822 nios2_expand_epilogue (false);
823 DONE;
824})
825
826(define_expand "sibcall_epilogue"
827 [(return)]
828 ""
829{
830 nios2_expand_epilogue (true);
831 DONE;
832})
833
3bbbe009 834(define_expand "return"
e430824f
CLT
835 [(simple_return)]
836 "nios2_can_use_return_insn ()"
c3ff2812
SL
837{
838 if (nios2_expand_return ())
839 DONE;
840})
e430824f
CLT
841
842(define_insn "simple_return"
843 [(simple_return)]
844 ""
3bbbe009
SL
845 "ret%."
846 [(set_attr "type" "control")])
e430824f
CLT
847
848;; Block any insns from being moved before this point, since the
849;; profiling call to mcount can use various registers that aren't
850;; saved or used to pass arguments.
851
852(define_insn "blockage"
853 [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
854 ""
855 ""
856 [(set_attr "type" "unknown")
857 (set_attr "length" "0")])
858
859;; This is used in compiling the unwind routines.
860(define_expand "eh_return"
861 [(use (match_operand 0 "general_operand"))]
862 ""
863{
864 if (GET_MODE (operands[0]) != Pmode)
865 operands[0] = convert_to_mode (Pmode, operands[0], 0);
866 emit_insn (gen_eh_set_ra (operands[0]));
867 DONE;
868})
869
870;; Modify the return address for EH return. We can't expand this
871;; until we know where it will be put in the stack frame.
872
873(define_insn_and_split "eh_set_ra"
874 [(unspec [(match_operand:SI 0 "register_operand" "r")] UNSPEC_EH_RETURN)
875 (clobber (match_scratch:SI 1 "=&r"))]
876 ""
877 "#"
878 "reload_completed"
879 [(const_int 0)]
880{
881 nios2_set_return_address (operands[0], operands[1]);
882 DONE;
883})
884
885\f
886;; Jumps and calls
887
888; Note that the assembler fixes up any out-of-range branch instructions not
889; caught by the compiler branch shortening code. The sequence emitted by
890; the assembler can be very inefficient, but it is correct for PIC code.
891; For non-PIC we are better off converting to an absolute JMPI.
892;
893; Direct calls and sibcalls use the CALL and JMPI instructions, respectively.
894; These instructions have an immediate operand that specifies the low 28 bits
895; of the PC, effectively allowing direct calls within a 256MB memory segment.
896; Per the Nios II Processor Reference Handbook, the linker is not required to
897; check or adjust for overflow.
898
899(define_insn "indirect_jump"
3c8c9f0d 900 [(set (pc) (match_operand:SI 0 "register_operand" "c"))]
e430824f 901 ""
3bbbe009 902 "jmp%!\\t%0"
e430824f
CLT
903 [(set_attr "type" "control")])
904
905(define_insn "jump"
906 [(set (pc)
907 (label_ref (match_operand 0 "" "")))]
908 ""
909 {
3bbbe009
SL
910 if (get_attr_length (insn) == 2)
911 return "br.n\\t%0";
912 else if (get_attr_length (insn) == 4)
e430824f
CLT
913 return "br\\t%0";
914 else
915 return "jmpi\\t%0";
916 }
917 [(set_attr "type" "control")
918 (set (attr "length")
919 (if_then_else
3bbbe009
SL
920 (and (match_test "TARGET_HAS_CDX")
921 (and (ge (minus (match_dup 0) (pc)) (const_int -1022))
922 (le (minus (match_dup 0) (pc)) (const_int 1022))))
923 (const_int 2)
924 (if_then_else
925 (ior (match_test "flag_pic")
926 (and (ge (minus (match_dup 0) (pc)) (const_int -32764))
927 (le (minus (match_dup 0) (pc)) (const_int 32764))))
928 (const_int 4)
929 (const_int 8))))])
e430824f
CLT
930
931(define_expand "call"
932 [(parallel [(call (match_operand 0 "" "")
933 (match_operand 1 "" ""))
934 (clobber (reg:SI RA_REGNO))])]
935 ""
a866d527 936 "nios2_adjust_call_address (&operands[0], NULL_RTX);")
e430824f
CLT
937
938(define_expand "call_value"
939 [(parallel [(set (match_operand 0 "" "")
940 (call (match_operand 1 "" "")
941 (match_operand 2 "" "")))
942 (clobber (reg:SI RA_REGNO))])]
943 ""
a866d527 944 "nios2_adjust_call_address (&operands[1], NULL_RTX);")
e430824f
CLT
945
946(define_insn "*call"
947 [(call (mem:QI (match_operand:SI 0 "call_operand" "i,r"))
948 (match_operand 1 "" ""))
949 (clobber (reg:SI RA_REGNO))]
950 ""
951 "@
952 call\\t%0
3bbbe009 953 callr%.\\t%0"
e430824f
CLT
954 [(set_attr "type" "control")])
955
956(define_insn "*call_value"
957 [(set (match_operand 0 "" "")
958 (call (mem:QI (match_operand:SI 1 "call_operand" "i,r"))
959 (match_operand 2 "" "")))
960 (clobber (reg:SI RA_REGNO))]
961 ""
962 "@
963 call\\t%1
3bbbe009 964 callr%.\\t%1"
e430824f
CLT
965 [(set_attr "type" "control")])
966
967(define_expand "sibcall"
968 [(parallel [(call (match_operand 0 "" "")
969 (match_operand 1 "" ""))
970 (return)])]
971 ""
a866d527 972 "nios2_adjust_call_address (&operands[0], NULL_RTX);")
e430824f
CLT
973
974(define_expand "sibcall_value"
975 [(parallel [(set (match_operand 0 "" "")
976 (call (match_operand 1 "" "")
977 (match_operand 2 "" "")))
978 (return)])]
979 ""
a866d527 980 "nios2_adjust_call_address (&operands[1], NULL_RTX);")
e430824f 981
a866d527 982(define_insn "sibcall_internal"
e430824f
CLT
983 [(call (mem:QI (match_operand:SI 0 "call_operand" "i,j"))
984 (match_operand 1 "" ""))
985 (return)]
986 ""
987 "@
988 jmpi\\t%0
3bbbe009 989 jmp%!\\t%0"
e430824f
CLT
990 [(set_attr "type" "control")])
991
a866d527 992(define_insn "sibcall_value_internal"
e430824f
CLT
993 [(set (match_operand 0 "register_operand" "")
994 (call (mem:QI (match_operand:SI 1 "call_operand" "i,j"))
995 (match_operand 2 "" "")))
996 (return)]
997 ""
998 "@
999 jmpi\\t%1
3bbbe009 1000 jmp%!\\t%1"
e430824f
CLT
1001 [(set_attr "type" "control")])
1002
1003(define_expand "tablejump"
1004 [(parallel [(set (pc) (match_operand 0 "register_operand" "r"))
1005 (use (label_ref (match_operand 1 "" "")))])]
1006 ""
1007{
1008 if (flag_pic)
1009 {
1010 /* Hopefully, CSE will eliminate this copy. */
1011 rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
1012 rtx reg2 = gen_reg_rtx (SImode);
1013
1014 emit_insn (gen_addsi3 (reg2, operands[0], reg1));
1015 operands[0] = reg2;
1016 }
1017})
1018
1019(define_insn "*tablejump"
1020 [(set (pc)
3c8c9f0d 1021 (match_operand:SI 0 "register_operand" "c"))
e430824f
CLT
1022 (use (label_ref (match_operand 1 "" "")))]
1023 ""
3bbbe009 1024 "jmp%!\\t%0"
e430824f
CLT
1025 [(set_attr "type" "control")])
1026
1027\f
1028;; cstore, cbranch patterns
1029
1030(define_mode_iterator CM [SI SF DF])
1031
1032(define_expand "cstore<mode>4"
1033 [(set (match_operand:SI 0 "register_operand" "=r")
1034 (match_operator:SI 1 "expandable_comparison_operator"
1035 [(match_operand:CM 2 "register_operand")
1036 (match_operand:CM 3 "nonmemory_operand")]))]
1037 ""
1038{
1039 if (!nios2_validate_compare (<MODE>mode, &operands[1], &operands[2],
1040 &operands[3]))
1041 FAIL;
1042})
1043
1044(define_expand "cbranch<mode>4"
1045 [(set (pc)
1046 (if_then_else
1047 (match_operator 0 "expandable_comparison_operator"
1048 [(match_operand:CM 1 "register_operand")
1049 (match_operand:CM 2 "nonmemory_operand")])
1050 (label_ref (match_operand 3 ""))
1051 (pc)))]
1052 ""
1053{
1054 if (!nios2_validate_compare (<MODE>mode, &operands[0], &operands[1],
1055 &operands[2]))
1056 FAIL;
1057 if (GET_MODE_CLASS (<MODE>mode) == MODE_FLOAT
1058 || !reg_or_0_operand (operands[2], <MODE>mode))
1059 {
1060 rtx condreg = gen_reg_rtx (SImode);
1061 emit_insn (gen_cstore<mode>4
1062 (condreg, operands[0], operands[1], operands[2]));
1063 operands[1] = condreg;
1064 operands[2] = const0_rtx;
1065 operands[0] = gen_rtx_fmt_ee (NE, VOIDmode, condreg, const0_rtx);
1066 }
1067})
1068
1069(define_insn "nios2_cbranch"
1070 [(set (pc)
1071 (if_then_else
1072 (match_operator 0 "ordered_comparison_operator"
1073 [(match_operand:SI 1 "reg_or_0_operand" "rM")
1074 (match_operand:SI 2 "reg_or_0_operand" "rM")])
1075 (label_ref (match_operand 3 "" ""))
1076 (pc)))]
1077 ""
3bbbe009
SL
1078{
1079 if (get_attr_length (insn) == 2)
1080 return "b%0z.n\t%z1, %l3";
1081 else if (get_attr_length (insn) == 4)
1082 return "b%0\t%z1, %z2, %l3";
1083 else if (get_attr_length (insn) == 6)
1084 return "b%R0z.n\t%z1, .+6;jmpi\t%l3";
1085 else
1086 return "b%R0\t%z1, %z2, .+8;jmpi\t%l3";
1087}
e430824f
CLT
1088 [(set_attr "type" "control")
1089 (set (attr "length")
3bbbe009
SL
1090 (cond
1091 [(and (match_test "nios2_cdx_narrow_form_p (insn)")
1092 (ge (minus (match_dup 3) (pc)) (const_int -126))
1093 (le (minus (match_dup 3) (pc)) (const_int 126)))
1094 (const_int 2)
1095 (ior (match_test "flag_pic")
1096 (and (ge (minus (match_dup 3) (pc)) (const_int -32764))
1097 (le (minus (match_dup 3) (pc)) (const_int 32764))))
1098 (const_int 4)
1099 (match_test "nios2_cdx_narrow_form_p (insn)")
1100 (const_int 6)]
1101 (const_int 8)))])
e430824f
CLT
1102
1103;; Floating point comparisons
1104(define_code_iterator FCMP [eq ne gt ge le lt])
1105(define_insn "nios2_s<code><mode>"
1106 [(set (match_operand:SI 0 "register_operand" "=r")
1107 (FCMP:SI (match_operand:F 1 "register_operand" "r")
1108 (match_operand:F 2 "register_operand" "r")))]
1109 "nios2_fpu_insn_enabled (n2fpu_fcmp<code><f>)"
1110 { return nios2_fpu_insn_asm (n2fpu_fcmp<code><f>); }
1111 [(set_attr "type" "custom")])
1112
1113;; Integer comparisons
1114
1115(define_code_iterator EQNE [eq ne])
1116(define_insn "nios2_cmp<code>"
1117 [(set (match_operand:SI 0 "register_operand" "=r")
1118 (EQNE:SI (match_operand:SI 1 "register_operand" "%r")
1119 (match_operand:SI 2 "arith_operand" "rI")))]
1120 ""
1121 "cmp<code>%i2\\t%0, %1, %z2"
1122 [(set_attr "type" "alu")])
1123
1124(define_code_iterator SCMP [ge lt])
1125(define_insn "nios2_cmp<code>"
1126 [(set (match_operand:SI 0 "register_operand" "=r")
1127 (SCMP:SI (match_operand:SI 1 "reg_or_0_operand" "rM")
1128 (match_operand:SI 2 "arith_operand" "rI")))]
1129 ""
1130 "cmp<code>%i2\\t%0, %z1, %z2"
1131 [(set_attr "type" "alu")])
1132
1133(define_code_iterator UCMP [geu ltu])
1134(define_insn "nios2_cmp<code>"
1135 [(set (match_operand:SI 0 "register_operand" "=r")
1136 (UCMP:SI (match_operand:SI 1 "reg_or_0_operand" "rM")
1137 (match_operand:SI 2 "uns_arith_operand" "rJ")))]
1138 ""
3bbbe009 1139 "cmp<code>%u2\\t%0, %z1, %z2"
e430824f
CLT
1140 [(set_attr "type" "alu")])
1141
1142
1143\f
1144;; Custom instruction patterns. The operands are intentionally
1145;; mode-less, to serve as generic carriers of all Altera defined
1146;; built-in instruction/function types.
1147
1148(define_insn "custom_nxx"
1149 [(unspec_volatile [(match_operand 0 "custom_insn_opcode" "N")
1150 (match_operand 1 "reg_or_0_operand" "rM")
1151 (match_operand 2 "reg_or_0_operand" "rM")]
1152 UNSPECV_CUSTOM_NXX)]
1153 ""
1154 "custom\\t%0, zero, %z1, %z2"
1155 [(set_attr "type" "custom")])
1156
1157(define_insn "custom_xnxx"
1158 [(set (match_operand 0 "register_operand" "=r")
1159 (unspec_volatile [(match_operand 1 "custom_insn_opcode" "N")
1160 (match_operand 2 "reg_or_0_operand" "rM")
1161 (match_operand 3 "reg_or_0_operand" "rM")]
1162 UNSPECV_CUSTOM_XNXX))]
1163 ""
1164 "custom\\t%1, %0, %z2, %z3"
1165 [(set_attr "type" "custom")])
1166
1167\f
1168;; Misc. patterns
1169
1170(define_insn "nop"
1171 [(const_int 0)]
1172 ""
3bbbe009
SL
1173 "nop%."
1174 [(set_attr "type" "nop")])
e430824f
CLT
1175
1176;; Connect 'sync' to 'memory_barrier' standard expand name
1177(define_expand "memory_barrier"
1178 [(const_int 0)]
1179 ""
1180{
1181 emit_insn (gen_sync ());
1182 DONE;
1183})
1184
1185;; For the nios2 __builtin_sync built-in function
1186(define_expand "sync"
1187 [(set (match_dup 0)
1188 (unspec:BLK [(match_dup 0)] UNSPEC_SYNC))]
1189 ""
1190{
1191 operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
1192 MEM_VOLATILE_P (operands[0]) = 1;
1193})
1194
1195(define_insn "*sync_insn"
1196 [(set (match_operand:BLK 0 "" "")
1197 (unspec:BLK [(match_dup 0)] UNSPEC_SYNC))]
1198 ""
1199 "sync"
1200 [(set_attr "type" "control")])
1201
1202(define_insn "rdctl"
1203 [(set (match_operand:SI 0 "register_operand" "=r")
1204 (unspec_volatile:SI [(match_operand:SI 1 "rdwrctl_operand" "O")]
1205 UNSPECV_RDCTL))]
1206 ""
1207 "rdctl\\t%0, ctl%1"
1208 [(set_attr "type" "control")])
1209
1210(define_insn "wrctl"
1211 [(unspec_volatile:SI [(match_operand:SI 0 "rdwrctl_operand" "O")
1212 (match_operand:SI 1 "reg_or_0_operand" "rM")]
1213 UNSPECV_WRCTL)]
1214 ""
1215 "wrctl\\tctl%0, %z1"
1216 [(set_attr "type" "control")])
1217
524d2e49
SL
1218(define_insn "rdprs"
1219 [(set (match_operand:SI 0 "register_operand" "=r")
1220 (unspec_volatile:SI [(match_operand:SI 1 "rdwrctl_operand" "O")
1221 (match_operand:SI 2 "arith_operand" "U")]
1222 UNSPECV_RDPRS))]
1223 ""
1224 "rdprs\\t%0, %1, %2"
1225 [(set_attr "type" "control")])
1226
1227;; Cache Instructions
1228
1229(define_insn "flushd"
1230 [(unspec_volatile:SI [(match_operand:SI 0 "ldstio_memory_operand" "w")]
1231 UNSPECV_FLUSHD)]
1232 ""
1233 "flushd\\t%0"
1234 [(set_attr "type" "control")])
1235
1236(define_insn "flushda"
1237 [(unspec_volatile:SI [(match_operand:SI 0 "ldstio_memory_operand" "w")]
1238 UNSPECV_FLUSHDA)]
1239 ""
1240 "flushda\\t%0"
1241 [(set_attr "type" "control")])
1242
1243;; R2 Instructions
1244
1245(define_insn "wrpie"
1246 [(set (match_operand:SI 0 "register_operand" "=r")
1247 (unspec_volatile:SI [(match_operand:SI 1 "register_operand" "r")]
1248 UNSPECV_WRPIE))]
1249 "TARGET_ARCH_R2"
1250 "wrpie\\t%0, %1"
1251 [(set_attr "type" "control")])
1252
1253(define_insn "eni"
1254 [(unspec:VOID [(match_operand 0 "const_int_operand" "i")]
1255 UNSPECV_ENI)]
1256 "TARGET_ARCH_R2"
1257 "eni\\t%0"
1258 [(set_attr "type" "control")])
1259
e430824f
CLT
1260;; Trap patterns
1261(define_insn "trap"
1262 [(trap_if (const_int 1) (const_int 3))]
1263 ""
3bbbe009 1264 "trap%.\\t3"
e430824f
CLT
1265 [(set_attr "type" "control")])
1266
1267(define_insn "ctrapsi4"
1268 [(trap_if (match_operator 0 "ordered_comparison_operator"
1269 [(match_operand:SI 1 "reg_or_0_operand" "rM")
1270 (match_operand:SI 2 "reg_or_0_operand" "rM")])
1271 (match_operand 3 "const_int_operand" "i"))]
1272 ""
3bbbe009
SL
1273{
1274 if (get_attr_length (insn) == 6)
1275 return "b%R0\\t%z1, %z2, 1f\;trap.n\\t%3\;1:";
1276 else
1277 return "b%R0\\t%z1, %z2, 1f\;trap\\t%3\;1:";
1278}
e430824f 1279 [(set_attr "type" "control")
3bbbe009
SL
1280 (set (attr "length")
1281 (if_then_else (match_test "nios2_cdx_narrow_form_p (insn)")
1282 (const_int 6) (const_int 8)))])
e430824f
CLT
1283
1284;; Load the GOT register.
1285(define_insn "load_got_register"
1286 [(set (match_operand:SI 0 "register_operand" "=&r")
1287 (unspec:SI [(const_int 0)] UNSPEC_LOAD_GOT_REGISTER))
1288 (set (match_operand:SI 1 "register_operand" "=r")
1289 (unspec:SI [(const_int 0)] UNSPEC_LOAD_GOT_REGISTER))]
1290 ""
1291 "nextpc\\t%0
1292\\t1:
02b67731
SL
1293\\tmovhi\\t%1, %%hiadj(_gp_got - 1b)
1294\\taddi\\t%1, %1, %%lo(_gp_got - 1b)"
e430824f
CLT
1295 [(set_attr "length" "12")])
1296
1297;; Read thread pointer register
1298(define_expand "get_thread_pointersi"
1299 [(match_operand:SI 0 "register_operand" "=r")]
1300 "TARGET_LINUX_ABI"
1301{
1302 emit_move_insn (operands[0], gen_rtx_REG (Pmode, TP_REGNO));
1303 DONE;
1304})
524d2e49
SL
1305
1306;; Synchronization Primitives
1307(include "sync.md")
1308
aa32db37
SL
1309;; Include the ldwm/stwm/push.n/pop.n patterns and peepholes.
1310(include "ldstwm.md")
1311