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