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