Mercurial > hg > CbC > CbC_gcc
comparison gcc/config/nios2/nios2.md @ 111:04ced10e8804
gcc 7
author | kono |
---|---|
date | Fri, 27 Oct 2017 22:46:09 +0900 |
parents | |
children | 84e7813d76e9 |
comparison
equal
deleted
inserted
replaced
68:561a7518be6b | 111:04ced10e8804 |
---|---|
1 ;; Machine Description for Altera Nios II. | |
2 ;; Copyright (C) 2012-2017 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 (SP_REGNO 27) ; Stack pointer register | |
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 | |
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 | |
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 | |
83 UNSPEC_ROUND | |
84 UNSPEC_LOAD_GOT_REGISTER | |
85 UNSPEC_PIC_SYM | |
86 UNSPEC_PIC_CALL_SYM | |
87 UNSPEC_PIC_GOTOFF_SYM | |
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 | |
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) | |
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 | |
110 (define_attr "type" | |
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" | |
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 | |
136 (eq_attr "type" "control,pop") | |
137 "cpu") | |
138 | |
139 (define_insn_reservation "alu" 1 | |
140 (eq_attr "type" "alu,add,sub,mov,and,or,xor,neg,not") | |
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 | |
148 (eq_attr "type" "st,stwm,push") | |
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 | |
157 (eq_attr "type" "ld,ldwm") | |
158 "cpu") | |
159 | |
160 (define_insn_reservation "shift" 3 | |
161 (eq_attr "type" "sll,srl,sra,rol,ror") | |
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 | |
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 | |
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 | |
204 (define_insn_and_split "movqi_internal" | |
205 [(set (match_operand:QI 0 "nonimmediate_operand" "=m, r,r") | |
206 (match_operand:QI 1 "general_operand" "rM,m,rI"))] | |
207 "(register_operand (operands[0], QImode) | |
208 || reg_or_0_operand (operands[1], QImode))" | |
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 } | |
227 "(nios2_symbolic_memory_operand_p (operands[0]) | |
228 || nios2_symbolic_memory_operand_p (operands[1]))" | |
229 [(set (match_dup 0) (match_dup 1))] | |
230 { | |
231 if (nios2_symbolic_memory_operand_p (operands[0])) | |
232 operands[0] = nios2_split_symbolic_memory_operand (operands[0]); | |
233 else | |
234 operands[1] = nios2_split_symbolic_memory_operand (operands[1]); | |
235 } | |
236 [(set_attr "type" "st,ld,mov")]) | |
237 | |
238 (define_insn_and_split "movhi_internal" | |
239 [(set (match_operand:HI 0 "nonimmediate_operand" "=m, r,r") | |
240 (match_operand:HI 1 "general_operand" "rM,m,rI"))] | |
241 "(register_operand (operands[0], HImode) | |
242 || reg_or_0_operand (operands[1], HImode))" | |
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 } | |
256 "(nios2_symbolic_memory_operand_p (operands[0]) | |
257 || nios2_symbolic_memory_operand_p (operands[1]))" | |
258 [(set (match_dup 0) (match_dup 1))] | |
259 { | |
260 if (nios2_symbolic_memory_operand_p (operands[0])) | |
261 operands[0] = nios2_split_symbolic_memory_operand (operands[0]); | |
262 else | |
263 operands[1] = nios2_split_symbolic_memory_operand (operands[1]); | |
264 } | |
265 [(set_attr "type" "st,ld,mov")]) | |
266 | |
267 (define_insn_and_split "movsi_internal" | |
268 [(set (match_operand:SI 0 "nonimmediate_operand" "=m, r,r, r") | |
269 (match_operand:SI 1 "general_operand" "rM,m,rIJK,S"))] | |
270 "(register_operand (operands[0], SImode) | |
271 || reg_or_0_operand (operands[1], SImode))" | |
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 } | |
299 "(nios2_symbolic_memory_operand_p (operands[0]) | |
300 || nios2_symbolic_memory_operand_p (operands[1]) | |
301 || nios2_large_constant_p (operands[1]))" | |
302 [(set (match_dup 0) (match_dup 1))] | |
303 { | |
304 if (nios2_symbolic_memory_operand_p (operands[0])) | |
305 operands[0] = nios2_split_symbolic_memory_operand (operands[0]); | |
306 else if (nios2_symbolic_memory_operand_p (operands[1])) | |
307 operands[1] = nios2_split_symbolic_memory_operand (operands[1]); | |
308 else | |
309 operands[1] = nios2_split_large_constant (operands[1], operands[0]); | |
310 } | |
311 [(set_attr "type" "st,ld,mov,alu")]) | |
312 | |
313 (define_mode_iterator BH [QI HI]) | |
314 (define_mode_iterator BHW [QI HI SI]) | |
315 (define_mode_attr bh [(QI "b") (HI "h")]) | |
316 (define_mode_attr bhw [(QI "b") (HI "h") (SI "w")]) | |
317 (define_mode_attr bhw_uns [(QI "bu") (HI "hu") (SI "w")]) | |
318 | |
319 (define_insn "ld<bhw_uns>io" | |
320 [(set (match_operand:BHW 0 "register_operand" "=r") | |
321 (unspec_volatile:BHW | |
322 [(match_operand:BHW 1 "ldstio_memory_operand" "w")] UNSPECV_LDXIO))] | |
323 "" | |
324 "ld<bhw_uns>io\\t%0, %1" | |
325 [(set_attr "type" "ld")]) | |
326 | |
327 (define_expand "ld<bh>io" | |
328 [(set (match_operand:BH 0 "register_operand" "=r") | |
329 (match_operand:BH 1 "ldstio_memory_operand" "w"))] | |
330 "" | |
331 { | |
332 rtx tmp = gen_reg_rtx (SImode); | |
333 emit_insn (gen_ld<bh>io_signed (tmp, operands[1])); | |
334 emit_insn (gen_mov<mode> (operands[0], gen_lowpart (<MODE>mode, tmp))); | |
335 DONE; | |
336 }) | |
337 | |
338 (define_insn "ld<bh>io_signed" | |
339 [(set (match_operand:SI 0 "register_operand" "=r") | |
340 (sign_extend:SI | |
341 (unspec_volatile:BH | |
342 [(match_operand:BH 1 "ldstio_memory_operand" "w")] UNSPECV_LDXIO)))] | |
343 "" | |
344 "ld<bh>io\\t%0, %1" | |
345 [(set_attr "type" "ld")]) | |
346 | |
347 (define_insn "st<bhw>io" | |
348 [(set (match_operand:BHW 0 "ldstio_memory_operand" "=w") | |
349 (unspec_volatile:BHW | |
350 [(match_operand:BHW 1 "reg_or_0_operand" "rM")] UNSPECV_STXIO))] | |
351 "" | |
352 "st<bhw>io\\t%z1, %0" | |
353 [(set_attr "type" "st")]) | |
354 | |
355 | |
356 ;; QI to [HI, SI] extension patterns are collected together | |
357 (define_mode_iterator QX [HI SI]) | |
358 | |
359 ;; Zero extension patterns | |
360 (define_insn_and_split "zero_extendhisi2" | |
361 [(set (match_operand:SI 0 "register_operand" "=r,r") | |
362 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))] | |
363 "" | |
364 "@ | |
365 andi%.\\t%0, %1, 0xffff | |
366 ldhu%o1%.\\t%0, %1" | |
367 "nios2_symbolic_memory_operand_p (operands[1])" | |
368 [(set (match_dup 0) (zero_extend:SI (match_dup 1)))] | |
369 { | |
370 operands[1] = nios2_split_symbolic_memory_operand (operands[1]); | |
371 } | |
372 [(set_attr "type" "and,ld")]) | |
373 | |
374 (define_insn_and_split "zero_extendqi<mode>2" | |
375 [(set (match_operand:QX 0 "register_operand" "=r,r") | |
376 (zero_extend:QX (match_operand:QI 1 "nonimmediate_operand" "r,m")))] | |
377 "" | |
378 "@ | |
379 andi%.\\t%0, %1, 0xff | |
380 ldbu%o1%.\\t%0, %1" | |
381 "nios2_symbolic_memory_operand_p (operands[1])" | |
382 [(set (match_dup 0) (zero_extend:QX (match_dup 1)))] | |
383 { | |
384 operands[1] = nios2_split_symbolic_memory_operand (operands[1]); | |
385 } | |
386 [(set_attr "type" "and,ld")]) | |
387 | |
388 ;; Sign extension patterns | |
389 | |
390 (define_insn_and_split "extendhisi2" | |
391 [(set (match_operand:SI 0 "register_operand" "=r,r") | |
392 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))] | |
393 "" | |
394 "@ | |
395 # | |
396 ldh%o1%.\\t%0, %1" | |
397 "nios2_symbolic_memory_operand_p (operands[1])" | |
398 [(set (match_dup 0) (sign_extend:SI (match_dup 1)))] | |
399 { | |
400 operands[1] = nios2_split_symbolic_memory_operand (operands[1]); | |
401 } | |
402 [(set_attr "type" "alu,ld")]) | |
403 | |
404 (define_insn_and_split "extendqi<mode>2" | |
405 [(set (match_operand:QX 0 "register_operand" "=r,r") | |
406 (sign_extend:QX (match_operand:QI 1 "nonimmediate_operand" "r,m")))] | |
407 "" | |
408 "@ | |
409 # | |
410 ldb%o1%.\\t%0, %1" | |
411 "nios2_symbolic_memory_operand_p (operands[1])" | |
412 [(set (match_dup 0) (sign_extend:QX (match_dup 1)))] | |
413 { | |
414 operands[1] = nios2_split_symbolic_memory_operand (operands[1]); | |
415 } | |
416 [(set_attr "type" "alu,ld")]) | |
417 | |
418 ;; Split patterns for register alternative cases. | |
419 (define_split | |
420 [(set (match_operand:SI 0 "register_operand" "") | |
421 (sign_extend:SI (match_operand:HI 1 "register_operand" "")))] | |
422 "reload_completed" | |
423 [(set (match_dup 0) | |
424 (and:SI (match_dup 1) (const_int 65535))) | |
425 (set (match_dup 0) | |
426 (xor:SI (match_dup 0) (const_int 32768))) | |
427 (set (match_dup 0) | |
428 (plus:SI (match_dup 0) (const_int -32768)))] | |
429 "operands[1] = gen_lowpart (SImode, operands[1]);") | |
430 | |
431 (define_split | |
432 [(set (match_operand:QX 0 "register_operand" "") | |
433 (sign_extend:QX (match_operand:QI 1 "register_operand" "")))] | |
434 "reload_completed" | |
435 [(set (match_dup 0) | |
436 (and:SI (match_dup 1) (const_int 255))) | |
437 (set (match_dup 0) | |
438 (xor:SI (match_dup 0) (const_int 128))) | |
439 (set (match_dup 0) | |
440 (plus:SI (match_dup 0) (const_int -128)))] | |
441 "operands[0] = gen_lowpart (SImode, operands[0]); | |
442 operands[1] = gen_lowpart (SImode, operands[1]);") | |
443 | |
444 | |
445 ;; Arithmetic Operations | |
446 | |
447 (define_insn "addsi3" | |
448 [(set (match_operand:SI 0 "register_operand" "=r") | |
449 (plus:SI (match_operand:SI 1 "register_operand" "%r") | |
450 (match_operand:SI 2 "add_regimm_operand" "rIT")))] | |
451 "" | |
452 { | |
453 return nios2_add_insn_asm (insn, operands); | |
454 } | |
455 [(set_attr "type" "add")]) | |
456 | |
457 (define_insn "subsi3" | |
458 [(set (match_operand:SI 0 "register_operand" "=r") | |
459 (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rM") | |
460 (match_operand:SI 2 "register_operand" "r")))] | |
461 "" | |
462 "sub%.\\t%0, %z1, %2" | |
463 [(set_attr "type" "sub")]) | |
464 | |
465 (define_insn "mulsi3" | |
466 [(set (match_operand:SI 0 "register_operand" "=r") | |
467 (mult:SI (match_operand:SI 1 "register_operand" "%r") | |
468 (match_operand:SI 2 "arith_operand" "rI")))] | |
469 "TARGET_HAS_MUL" | |
470 "mul%i2\\t%0, %1, %z2" | |
471 [(set_attr "type" "mul")]) | |
472 | |
473 (define_expand "divsi3" | |
474 [(set (match_operand:SI 0 "register_operand" "=r") | |
475 (div:SI (match_operand:SI 1 "register_operand" "r") | |
476 (match_operand:SI 2 "register_operand" "r")))] | |
477 "" | |
478 { | |
479 if (!TARGET_HAS_DIV) | |
480 { | |
481 if (TARGET_FAST_SW_DIV) | |
482 { | |
483 nios2_emit_expensive_div (operands, SImode); | |
484 DONE; | |
485 } | |
486 else | |
487 FAIL; | |
488 } | |
489 }) | |
490 | |
491 (define_insn "divsi3_insn" | |
492 [(set (match_operand:SI 0 "register_operand" "=r") | |
493 (div:SI (match_operand:SI 1 "register_operand" "r") | |
494 (match_operand:SI 2 "register_operand" "r")))] | |
495 "TARGET_HAS_DIV" | |
496 "div\\t%0, %1, %2" | |
497 [(set_attr "type" "div")]) | |
498 | |
499 (define_insn "udivsi3" | |
500 [(set (match_operand:SI 0 "register_operand" "=r") | |
501 (udiv:SI (match_operand:SI 1 "register_operand" "r") | |
502 (match_operand:SI 2 "register_operand" "r")))] | |
503 "TARGET_HAS_DIV" | |
504 "divu\\t%0, %1, %2" | |
505 [(set_attr "type" "div")]) | |
506 | |
507 (define_code_iterator EXTEND [sign_extend zero_extend]) | |
508 (define_code_attr us [(sign_extend "s") (zero_extend "u")]) | |
509 (define_code_attr mul [(sign_extend "mul") (zero_extend "umul")]) | |
510 | |
511 (define_insn "<us>mulsi3_highpart" | |
512 [(set (match_operand:SI 0 "register_operand" "=r") | |
513 (truncate:SI | |
514 (lshiftrt:DI | |
515 (mult:DI (EXTEND:DI (match_operand:SI 1 "register_operand" "r")) | |
516 (EXTEND:DI (match_operand:SI 2 "register_operand" "r"))) | |
517 (const_int 32))))] | |
518 "TARGET_HAS_MULX" | |
519 "mulx<us><us>\\t%0, %1, %2" | |
520 [(set_attr "type" "mul")]) | |
521 | |
522 (define_expand "<mul>sidi3" | |
523 [(set (match_operand:DI 0 "register_operand" "") | |
524 (mult:DI (EXTEND:DI (match_operand:SI 1 "register_operand" "")) | |
525 (EXTEND:DI (match_operand:SI 2 "register_operand" ""))))] | |
526 "TARGET_HAS_MULX" | |
527 { | |
528 rtx hi = gen_reg_rtx (SImode); | |
529 rtx lo = gen_reg_rtx (SImode); | |
530 | |
531 emit_insn (gen_<us>mulsi3_highpart (hi, operands[1], operands[2])); | |
532 emit_insn (gen_mulsi3 (lo, operands[1], operands[2])); | |
533 emit_move_insn (gen_lowpart (SImode, operands[0]), lo); | |
534 emit_move_insn (gen_highpart (SImode, operands[0]), hi); | |
535 DONE; | |
536 }) | |
537 | |
538 | |
539 ;; Negate and ones complement | |
540 | |
541 (define_insn "negsi2" | |
542 [(set (match_operand:SI 0 "register_operand" "=r") | |
543 (neg:SI (match_operand:SI 1 "register_operand" "r")))] | |
544 "" | |
545 { | |
546 if (get_attr_length (insn) == 2) | |
547 return "neg.n\\t%0, %1"; | |
548 else | |
549 return "sub\\t%0, zero, %1"; | |
550 } | |
551 [(set_attr "type" "neg")]) | |
552 | |
553 (define_insn "one_cmplsi2" | |
554 [(set (match_operand:SI 0 "register_operand" "=r") | |
555 (not:SI (match_operand:SI 1 "register_operand" "r")))] | |
556 "" | |
557 { | |
558 if (get_attr_length (insn) == 2) | |
559 return "not.n\\t%0, %1"; | |
560 else | |
561 return "nor\\t%0, zero, %1"; | |
562 } | |
563 [(set_attr "type" "not")]) | |
564 | |
565 | |
566 ;; Integer logical Operations | |
567 | |
568 (define_insn "andsi3" | |
569 [(set (match_operand:SI 0 "register_operand" "=r") | |
570 (and:SI (match_operand:SI 1 "register_operand" "%r") | |
571 (match_operand:SI 2 "and_operand" "rJKP")))] | |
572 "" | |
573 "and%x2%.\\t%0, %1, %y2" | |
574 [(set_attr "type" "and")]) | |
575 | |
576 (define_code_iterator LOGICAL [ior xor]) | |
577 (define_code_attr logical_asm [(ior "or") (xor "xor")]) | |
578 | |
579 (define_insn "<code>si3" | |
580 [(set (match_operand:SI 0 "register_operand" "=r") | |
581 (LOGICAL:SI (match_operand:SI 1 "register_operand" "%r") | |
582 (match_operand:SI 2 "logical_operand" "rJK")))] | |
583 "" | |
584 "<logical_asm>%x2%.\\t%0, %1, %y2" | |
585 [(set_attr "type" "<logical_asm>")]) | |
586 | |
587 (define_insn "*norsi3" | |
588 [(set (match_operand:SI 0 "register_operand" "=r") | |
589 (and:SI (not:SI (match_operand:SI 1 "register_operand" "%r")) | |
590 (not:SI (match_operand:SI 2 "register_operand" "r"))))] | |
591 "" | |
592 "nor\\t%0, %1, %2" | |
593 [(set_attr "type" "alu")]) | |
594 | |
595 | |
596 ;; Shift instructions | |
597 | |
598 (define_code_iterator SHIFT [ashift ashiftrt lshiftrt rotate]) | |
599 (define_code_attr shift_op [(ashift "ashl") (ashiftrt "ashr") | |
600 (lshiftrt "lshr") (rotate "rotl")]) | |
601 (define_code_attr shift_asm [(ashift "sll") (ashiftrt "sra") | |
602 (lshiftrt "srl") (rotate "rol")]) | |
603 | |
604 (define_insn "<shift_op>si3" | |
605 [(set (match_operand:SI 0 "register_operand" "=r") | |
606 (SHIFT:SI (match_operand:SI 1 "register_operand" "r") | |
607 (match_operand:SI 2 "shift_operand" "rL")))] | |
608 "" | |
609 "<shift_asm>%i2%.\\t%0, %1, %z2" | |
610 [(set_attr "type" "<shift_asm>")]) | |
611 | |
612 (define_insn "rotrsi3" | |
613 [(set (match_operand:SI 0 "register_operand" "=r") | |
614 (rotatert:SI (match_operand:SI 1 "register_operand" "r") | |
615 (match_operand:SI 2 "register_operand" "r")))] | |
616 "" | |
617 "ror\\t%0, %1, %2" | |
618 [(set_attr "type" "ror")]) | |
619 | |
620 ;; Nios II R2 Bit Manipulation Extension (BMX), provides | |
621 ;; bit merge/insertion/extraction instructions. | |
622 | |
623 (define_insn "*merge" | |
624 [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r") | |
625 (match_operand:SI 1 "const_shift_operand" "L") | |
626 (match_operand:SI 2 "const_shift_operand" "L")) | |
627 (zero_extract:SI (match_operand:SI 3 "register_operand" "r") | |
628 (match_dup 1) (match_dup 2)))] | |
629 "TARGET_HAS_BMX" | |
630 { | |
631 operands[4] = GEN_INT (INTVAL (operands[1]) + INTVAL (operands[2]) - 1); | |
632 return "merge\\t%0, %3, %4, %2"; | |
633 } | |
634 [(set_attr "type" "alu")]) | |
635 | |
636 (define_insn "extzv" | |
637 [(set (match_operand:SI 0 "register_operand" "=r") | |
638 (zero_extract:SI (match_operand:SI 1 "register_operand" "r") | |
639 (match_operand:SI 2 "const_shift_operand" "L") | |
640 (match_operand:SI 3 "const_shift_operand" "L")))] | |
641 "TARGET_HAS_BMX" | |
642 { | |
643 operands[4] = GEN_INT (INTVAL (operands[2]) + INTVAL (operands[3]) - 1); | |
644 return "extract\\t%0, %1, %4, %3"; | |
645 } | |
646 [(set_attr "type" "alu")]) | |
647 | |
648 (define_insn "insv" | |
649 [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r") | |
650 (match_operand:SI 1 "const_shift_operand" "L") | |
651 (match_operand:SI 2 "const_shift_operand" "L")) | |
652 (match_operand:SI 3 "reg_or_0_operand" "rM"))] | |
653 "TARGET_HAS_BMX" | |
654 { | |
655 operands[4] = GEN_INT (INTVAL (operands[1]) + INTVAL (operands[2]) - 1); | |
656 return "insert\\t%0, %z3, %4, %2"; | |
657 } | |
658 [(set_attr "type" "alu")]) | |
659 | |
660 | |
661 | |
662 ;; Floating point instructions | |
663 | |
664 ;; Mode iterator for single/double float | |
665 (define_mode_iterator F [SF DF]) | |
666 (define_mode_attr f [(SF "s") (DF "d")]) | |
667 | |
668 ;; Basic arithmetic instructions | |
669 (define_code_iterator FOP3 [plus minus mult div]) | |
670 (define_code_attr fop3 [(plus "add") (minus "sub") (mult "mul") (div "div")]) | |
671 | |
672 (define_insn "<fop3><mode>3" | |
673 [(set (match_operand:F 0 "register_operand" "=r") | |
674 (FOP3:F (match_operand:F 1 "register_operand" "r") | |
675 (match_operand:F 2 "register_operand" "r")))] | |
676 "nios2_fpu_insn_enabled (n2fpu_f<fop3><f>)" | |
677 { return nios2_fpu_insn_asm (n2fpu_f<fop3><f>); } | |
678 [(set_attr "type" "custom")]) | |
679 | |
680 ;; Floating point min/max operations | |
681 (define_code_iterator SMINMAX [smin smax]) | |
682 (define_code_attr minmax [(smin "min") (smax "max")]) | |
683 (define_insn "<code><mode>3" | |
684 [(set (match_operand:F 0 "register_operand" "=r") | |
685 (SMINMAX:F (match_operand:F 1 "register_operand" "r") | |
686 (match_operand:F 2 "register_operand" "r")))] | |
687 "nios2_fpu_insn_enabled (n2fpu_f<minmax><f>)" | |
688 { return nios2_fpu_insn_asm (n2fpu_f<minmax><f>); } | |
689 [(set_attr "type" "custom")]) | |
690 | |
691 ;; These 2-operand FP operations can be collected together | |
692 (define_code_iterator FOP2 [abs neg sqrt]) | |
693 (define_insn "<code><mode>2" | |
694 [(set (match_operand:F 0 "register_operand" "=r") | |
695 (FOP2:F (match_operand:F 1 "register_operand" "r")))] | |
696 "nios2_fpu_insn_enabled (n2fpu_f<code><f>)" | |
697 { return nios2_fpu_insn_asm (n2fpu_f<code><f>); } | |
698 [(set_attr "type" "custom")]) | |
699 | |
700 ;; X, Y register access instructions | |
701 (define_insn "nios2_fwrx" | |
702 [(unspec_volatile [(match_operand:DF 0 "register_operand" "r")] UNSPECV_FWRX)] | |
703 "nios2_fpu_insn_enabled (n2fpu_fwrx)" | |
704 { return nios2_fpu_insn_asm (n2fpu_fwrx); } | |
705 [(set_attr "type" "custom")]) | |
706 | |
707 (define_insn "nios2_fwry" | |
708 [(unspec_volatile [(match_operand:SF 0 "register_operand" "r")] UNSPECV_FWRY)] | |
709 "nios2_fpu_insn_enabled (n2fpu_fwry)" | |
710 { return nios2_fpu_insn_asm (n2fpu_fwry); } | |
711 [(set_attr "type" "custom")]) | |
712 | |
713 ;; The X, Y read insns uses an int iterator | |
714 (define_int_iterator UNSPEC_READ_XY [UNSPECV_FRDXLO UNSPECV_FRDXHI | |
715 UNSPECV_FRDY]) | |
716 (define_int_attr read_xy [(UNSPECV_FRDXLO "frdxlo") (UNSPECV_FRDXHI "frdxhi") | |
717 (UNSPECV_FRDY "frdy")]) | |
718 (define_insn "nios2_<read_xy>" | |
719 [(set (match_operand:SF 0 "register_operand" "=r") | |
720 (unspec_volatile:SF [(const_int 0)] UNSPEC_READ_XY))] | |
721 "nios2_fpu_insn_enabled (n2fpu_<read_xy>)" | |
722 { return nios2_fpu_insn_asm (n2fpu_<read_xy>); } | |
723 [(set_attr "type" "custom")]) | |
724 | |
725 ;; Various math functions | |
726 (define_int_iterator MATHFUNC | |
727 [UNSPEC_FCOS UNSPEC_FSIN UNSPEC_FTAN UNSPEC_FATAN UNSPEC_FEXP UNSPEC_FLOG]) | |
728 (define_int_attr mathfunc [(UNSPEC_FCOS "cos") (UNSPEC_FSIN "sin") | |
729 (UNSPEC_FTAN "tan") (UNSPEC_FATAN "atan") | |
730 (UNSPEC_FEXP "exp") (UNSPEC_FLOG "log")]) | |
731 | |
732 (define_insn "<mathfunc><mode>2" | |
733 [(set (match_operand:F 0 "register_operand" "=r") | |
734 (unspec:F [(match_operand:F 1 "register_operand" "r")] MATHFUNC))] | |
735 "nios2_fpu_insn_enabled (n2fpu_f<mathfunc><f>)" | |
736 { return nios2_fpu_insn_asm (n2fpu_f<mathfunc><f>); } | |
737 [(set_attr "type" "custom")]) | |
738 | |
739 ;; Converting between floating point and fixed point | |
740 | |
741 (define_code_iterator FLOAT [float unsigned_float]) | |
742 (define_code_iterator FIX [fix unsigned_fix]) | |
743 | |
744 (define_code_attr conv_op [(float "float") (unsigned_float "floatuns") | |
745 (fix "fix") (unsigned_fix "fixuns")]) | |
746 (define_code_attr i [(float "i") (unsigned_float "u") | |
747 (fix "i") (unsigned_fix "u")]) | |
748 | |
749 ;; Integer to float conversions | |
750 (define_insn "<conv_op>si<mode>2" | |
751 [(set (match_operand:F 0 "register_operand" "=r") | |
752 (FLOAT:F (match_operand:SI 1 "register_operand" "r")))] | |
753 "nios2_fpu_insn_enabled (n2fpu_float<i><f>)" | |
754 { return nios2_fpu_insn_asm (n2fpu_float<i><f>); } | |
755 [(set_attr "type" "custom")]) | |
756 | |
757 ;; Float to integer conversions | |
758 (define_insn "<conv_op>_trunc<mode>si2" | |
759 [(set (match_operand:SI 0 "register_operand" "=r") | |
760 (FIX:SI (match_operand:F 1 "general_operand" "r")))] | |
761 "nios2_fpu_insn_enabled (n2fpu_fix<f><i>)" | |
762 { return nios2_fpu_insn_asm (n2fpu_fix<f><i>); } | |
763 [(set_attr "type" "custom")]) | |
764 | |
765 (define_insn "lroundsfsi2" | |
766 [(set (match_operand:SI 0 "register_operand" "=r") | |
767 (unspec:SI [(match_operand:SF 1 "general_operand" "r")] UNSPEC_ROUND))] | |
768 "nios2_fpu_insn_enabled (n2fpu_round)" | |
769 { return nios2_fpu_insn_asm (n2fpu_round); } | |
770 [(set_attr "type" "custom")]) | |
771 | |
772 (define_insn "extendsfdf2" | |
773 [(set (match_operand:DF 0 "register_operand" "=r") | |
774 (float_extend:DF (match_operand:SF 1 "general_operand" "r")))] | |
775 "nios2_fpu_insn_enabled (n2fpu_fextsd)" | |
776 { return nios2_fpu_insn_asm (n2fpu_fextsd); } | |
777 [(set_attr "type" "custom")]) | |
778 | |
779 (define_insn "truncdfsf2" | |
780 [(set (match_operand:SF 0 "register_operand" "=r") | |
781 (float_truncate:SF (match_operand:DF 1 "general_operand" "r")))] | |
782 "nios2_fpu_insn_enabled (n2fpu_ftruncds)" | |
783 { return nios2_fpu_insn_asm (n2fpu_ftruncds); } | |
784 [(set_attr "type" "custom")]) | |
785 | |
786 | |
787 | |
788 ;; Prologue, Epilogue and Return | |
789 | |
790 (define_expand "prologue" | |
791 [(const_int 1)] | |
792 "" | |
793 { | |
794 nios2_expand_prologue (); | |
795 DONE; | |
796 }) | |
797 | |
798 (define_expand "epilogue" | |
799 [(return)] | |
800 "" | |
801 { | |
802 nios2_expand_epilogue (false); | |
803 DONE; | |
804 }) | |
805 | |
806 (define_expand "sibcall_epilogue" | |
807 [(return)] | |
808 "" | |
809 { | |
810 nios2_expand_epilogue (true); | |
811 DONE; | |
812 }) | |
813 | |
814 (define_expand "return" | |
815 [(simple_return)] | |
816 "nios2_can_use_return_insn ()" | |
817 { | |
818 if (nios2_expand_return ()) | |
819 DONE; | |
820 }) | |
821 | |
822 (define_insn "simple_return" | |
823 [(simple_return)] | |
824 "" | |
825 "ret%." | |
826 [(set_attr "type" "control")]) | |
827 | |
828 ;; Block any insns from being moved before this point, since the | |
829 ;; profiling call to mcount can use various registers that aren't | |
830 ;; saved or used to pass arguments. | |
831 | |
832 (define_insn "blockage" | |
833 [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)] | |
834 "" | |
835 "" | |
836 [(set_attr "type" "unknown") | |
837 (set_attr "length" "0")]) | |
838 | |
839 ;; This is used in compiling the unwind routines. | |
840 (define_expand "eh_return" | |
841 [(use (match_operand 0 "general_operand"))] | |
842 "" | |
843 { | |
844 if (GET_MODE (operands[0]) != Pmode) | |
845 operands[0] = convert_to_mode (Pmode, operands[0], 0); | |
846 emit_insn (gen_eh_set_ra (operands[0])); | |
847 DONE; | |
848 }) | |
849 | |
850 ;; Modify the return address for EH return. We can't expand this | |
851 ;; until we know where it will be put in the stack frame. | |
852 | |
853 (define_insn_and_split "eh_set_ra" | |
854 [(unspec [(match_operand:SI 0 "register_operand" "r")] UNSPEC_EH_RETURN) | |
855 (clobber (match_scratch:SI 1 "=&r"))] | |
856 "" | |
857 "#" | |
858 "reload_completed" | |
859 [(const_int 0)] | |
860 { | |
861 nios2_set_return_address (operands[0], operands[1]); | |
862 DONE; | |
863 }) | |
864 | |
865 | |
866 ;; Jumps and calls | |
867 | |
868 ; Note that the assembler fixes up any out-of-range branch instructions not | |
869 ; caught by the compiler branch shortening code. The sequence emitted by | |
870 ; the assembler can be very inefficient, but it is correct for PIC code. | |
871 ; For non-PIC we are better off converting to an absolute JMPI. | |
872 ; | |
873 ; Direct calls and sibcalls use the CALL and JMPI instructions, respectively. | |
874 ; These instructions have an immediate operand that specifies the low 28 bits | |
875 ; of the PC, effectively allowing direct calls within a 256MB memory segment. | |
876 ; Per the Nios II Processor Reference Handbook, the linker is not required to | |
877 ; check or adjust for overflow. | |
878 | |
879 (define_insn "indirect_jump" | |
880 [(set (pc) (match_operand:SI 0 "register_operand" "c"))] | |
881 "" | |
882 "jmp%!\\t%0" | |
883 [(set_attr "type" "control")]) | |
884 | |
885 (define_insn "jump" | |
886 [(set (pc) | |
887 (label_ref (match_operand 0 "" "")))] | |
888 "" | |
889 { | |
890 if (get_attr_length (insn) == 2) | |
891 return "br.n\\t%0"; | |
892 else if (get_attr_length (insn) == 4) | |
893 return "br\\t%0"; | |
894 else | |
895 return "jmpi\\t%0"; | |
896 } | |
897 [(set_attr "type" "control") | |
898 (set (attr "length") | |
899 (if_then_else | |
900 (and (match_test "TARGET_HAS_CDX") | |
901 (and (ge (minus (match_dup 0) (pc)) (const_int -1022)) | |
902 (le (minus (match_dup 0) (pc)) (const_int 1022)))) | |
903 (const_int 2) | |
904 (if_then_else | |
905 (ior (match_test "flag_pic") | |
906 (and (ge (minus (match_dup 0) (pc)) (const_int -32764)) | |
907 (le (minus (match_dup 0) (pc)) (const_int 32764)))) | |
908 (const_int 4) | |
909 (const_int 8))))]) | |
910 | |
911 (define_expand "call" | |
912 [(parallel [(call (match_operand 0 "" "") | |
913 (match_operand 1 "" "")) | |
914 (clobber (reg:SI RA_REGNO))])] | |
915 "" | |
916 "nios2_adjust_call_address (&operands[0], NULL_RTX);") | |
917 | |
918 (define_expand "call_value" | |
919 [(parallel [(set (match_operand 0 "" "") | |
920 (call (match_operand 1 "" "") | |
921 (match_operand 2 "" ""))) | |
922 (clobber (reg:SI RA_REGNO))])] | |
923 "" | |
924 "nios2_adjust_call_address (&operands[1], NULL_RTX);") | |
925 | |
926 (define_insn "*call" | |
927 [(call (mem:QI (match_operand:SI 0 "call_operand" "i,r")) | |
928 (match_operand 1 "" "")) | |
929 (clobber (reg:SI RA_REGNO))] | |
930 "" | |
931 "@ | |
932 call\\t%0 | |
933 callr%.\\t%0" | |
934 [(set_attr "type" "control")]) | |
935 | |
936 (define_insn "*call_value" | |
937 [(set (match_operand 0 "" "") | |
938 (call (mem:QI (match_operand:SI 1 "call_operand" "i,r")) | |
939 (match_operand 2 "" ""))) | |
940 (clobber (reg:SI RA_REGNO))] | |
941 "" | |
942 "@ | |
943 call\\t%1 | |
944 callr%.\\t%1" | |
945 [(set_attr "type" "control")]) | |
946 | |
947 (define_expand "sibcall" | |
948 [(parallel [(call (match_operand 0 "" "") | |
949 (match_operand 1 "" "")) | |
950 (return)])] | |
951 "" | |
952 "nios2_adjust_call_address (&operands[0], NULL_RTX);") | |
953 | |
954 (define_expand "sibcall_value" | |
955 [(parallel [(set (match_operand 0 "" "") | |
956 (call (match_operand 1 "" "") | |
957 (match_operand 2 "" ""))) | |
958 (return)])] | |
959 "" | |
960 "nios2_adjust_call_address (&operands[1], NULL_RTX);") | |
961 | |
962 (define_insn "sibcall_internal" | |
963 [(call (mem:QI (match_operand:SI 0 "call_operand" "i,j")) | |
964 (match_operand 1 "" "")) | |
965 (return)] | |
966 "" | |
967 "@ | |
968 jmpi\\t%0 | |
969 jmp%!\\t%0" | |
970 [(set_attr "type" "control")]) | |
971 | |
972 (define_insn "sibcall_value_internal" | |
973 [(set (match_operand 0 "register_operand" "") | |
974 (call (mem:QI (match_operand:SI 1 "call_operand" "i,j")) | |
975 (match_operand 2 "" ""))) | |
976 (return)] | |
977 "" | |
978 "@ | |
979 jmpi\\t%1 | |
980 jmp%!\\t%1" | |
981 [(set_attr "type" "control")]) | |
982 | |
983 (define_expand "tablejump" | |
984 [(parallel [(set (pc) (match_operand 0 "register_operand" "r")) | |
985 (use (label_ref (match_operand 1 "" "")))])] | |
986 "" | |
987 { | |
988 if (flag_pic) | |
989 { | |
990 /* Hopefully, CSE will eliminate this copy. */ | |
991 rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1])); | |
992 rtx reg2 = gen_reg_rtx (SImode); | |
993 | |
994 emit_insn (gen_addsi3 (reg2, operands[0], reg1)); | |
995 operands[0] = reg2; | |
996 } | |
997 }) | |
998 | |
999 (define_insn "*tablejump" | |
1000 [(set (pc) | |
1001 (match_operand:SI 0 "register_operand" "c")) | |
1002 (use (label_ref (match_operand 1 "" "")))] | |
1003 "" | |
1004 "jmp%!\\t%0" | |
1005 [(set_attr "type" "control")]) | |
1006 | |
1007 | |
1008 ;; cstore, cbranch patterns | |
1009 | |
1010 (define_mode_iterator CM [SI SF DF]) | |
1011 | |
1012 (define_expand "cstore<mode>4" | |
1013 [(set (match_operand:SI 0 "register_operand" "=r") | |
1014 (match_operator:SI 1 "expandable_comparison_operator" | |
1015 [(match_operand:CM 2 "register_operand") | |
1016 (match_operand:CM 3 "nonmemory_operand")]))] | |
1017 "" | |
1018 { | |
1019 if (!nios2_validate_compare (<MODE>mode, &operands[1], &operands[2], | |
1020 &operands[3])) | |
1021 FAIL; | |
1022 }) | |
1023 | |
1024 (define_expand "cbranch<mode>4" | |
1025 [(set (pc) | |
1026 (if_then_else | |
1027 (match_operator 0 "expandable_comparison_operator" | |
1028 [(match_operand:CM 1 "register_operand") | |
1029 (match_operand:CM 2 "nonmemory_operand")]) | |
1030 (label_ref (match_operand 3 "")) | |
1031 (pc)))] | |
1032 "" | |
1033 { | |
1034 if (!nios2_validate_compare (<MODE>mode, &operands[0], &operands[1], | |
1035 &operands[2])) | |
1036 FAIL; | |
1037 if (GET_MODE_CLASS (<MODE>mode) == MODE_FLOAT | |
1038 || !reg_or_0_operand (operands[2], <MODE>mode)) | |
1039 { | |
1040 rtx condreg = gen_reg_rtx (SImode); | |
1041 emit_insn (gen_cstore<mode>4 | |
1042 (condreg, operands[0], operands[1], operands[2])); | |
1043 operands[1] = condreg; | |
1044 operands[2] = const0_rtx; | |
1045 operands[0] = gen_rtx_fmt_ee (NE, VOIDmode, condreg, const0_rtx); | |
1046 } | |
1047 }) | |
1048 | |
1049 (define_insn "nios2_cbranch" | |
1050 [(set (pc) | |
1051 (if_then_else | |
1052 (match_operator 0 "ordered_comparison_operator" | |
1053 [(match_operand:SI 1 "reg_or_0_operand" "rM") | |
1054 (match_operand:SI 2 "reg_or_0_operand" "rM")]) | |
1055 (label_ref (match_operand 3 "" "")) | |
1056 (pc)))] | |
1057 "" | |
1058 { | |
1059 if (get_attr_length (insn) == 2) | |
1060 return "b%0z.n\t%z1, %l3"; | |
1061 else if (get_attr_length (insn) == 4) | |
1062 return "b%0\t%z1, %z2, %l3"; | |
1063 else if (get_attr_length (insn) == 6) | |
1064 return "b%R0z.n\t%z1, .+6;jmpi\t%l3"; | |
1065 else | |
1066 return "b%R0\t%z1, %z2, .+8;jmpi\t%l3"; | |
1067 } | |
1068 [(set_attr "type" "control") | |
1069 (set (attr "length") | |
1070 (cond | |
1071 [(and (match_test "nios2_cdx_narrow_form_p (insn)") | |
1072 (ge (minus (match_dup 3) (pc)) (const_int -126)) | |
1073 (le (minus (match_dup 3) (pc)) (const_int 126))) | |
1074 (const_int 2) | |
1075 (ior (match_test "flag_pic") | |
1076 (and (ge (minus (match_dup 3) (pc)) (const_int -32764)) | |
1077 (le (minus (match_dup 3) (pc)) (const_int 32764)))) | |
1078 (const_int 4) | |
1079 (match_test "nios2_cdx_narrow_form_p (insn)") | |
1080 (const_int 6)] | |
1081 (const_int 8)))]) | |
1082 | |
1083 ;; Floating point comparisons | |
1084 (define_code_iterator FCMP [eq ne gt ge le lt]) | |
1085 (define_insn "nios2_s<code><mode>" | |
1086 [(set (match_operand:SI 0 "register_operand" "=r") | |
1087 (FCMP:SI (match_operand:F 1 "register_operand" "r") | |
1088 (match_operand:F 2 "register_operand" "r")))] | |
1089 "nios2_fpu_insn_enabled (n2fpu_fcmp<code><f>)" | |
1090 { return nios2_fpu_insn_asm (n2fpu_fcmp<code><f>); } | |
1091 [(set_attr "type" "custom")]) | |
1092 | |
1093 ;; Integer comparisons | |
1094 | |
1095 (define_code_iterator EQNE [eq ne]) | |
1096 (define_insn "nios2_cmp<code>" | |
1097 [(set (match_operand:SI 0 "register_operand" "=r") | |
1098 (EQNE:SI (match_operand:SI 1 "register_operand" "%r") | |
1099 (match_operand:SI 2 "arith_operand" "rI")))] | |
1100 "" | |
1101 "cmp<code>%i2\\t%0, %1, %z2" | |
1102 [(set_attr "type" "alu")]) | |
1103 | |
1104 (define_code_iterator SCMP [ge lt]) | |
1105 (define_insn "nios2_cmp<code>" | |
1106 [(set (match_operand:SI 0 "register_operand" "=r") | |
1107 (SCMP:SI (match_operand:SI 1 "reg_or_0_operand" "rM") | |
1108 (match_operand:SI 2 "arith_operand" "rI")))] | |
1109 "" | |
1110 "cmp<code>%i2\\t%0, %z1, %z2" | |
1111 [(set_attr "type" "alu")]) | |
1112 | |
1113 (define_code_iterator UCMP [geu ltu]) | |
1114 (define_insn "nios2_cmp<code>" | |
1115 [(set (match_operand:SI 0 "register_operand" "=r") | |
1116 (UCMP:SI (match_operand:SI 1 "reg_or_0_operand" "rM") | |
1117 (match_operand:SI 2 "uns_arith_operand" "rJ")))] | |
1118 "" | |
1119 "cmp<code>%u2\\t%0, %z1, %z2" | |
1120 [(set_attr "type" "alu")]) | |
1121 | |
1122 | |
1123 | |
1124 ;; Custom instruction patterns. The operands are intentionally | |
1125 ;; mode-less, to serve as generic carriers of all Altera defined | |
1126 ;; built-in instruction/function types. | |
1127 | |
1128 (define_insn "custom_nxx" | |
1129 [(unspec_volatile [(match_operand 0 "custom_insn_opcode" "N") | |
1130 (match_operand 1 "reg_or_0_operand" "rM") | |
1131 (match_operand 2 "reg_or_0_operand" "rM")] | |
1132 UNSPECV_CUSTOM_NXX)] | |
1133 "" | |
1134 "custom\\t%0, zero, %z1, %z2" | |
1135 [(set_attr "type" "custom")]) | |
1136 | |
1137 (define_insn "custom_xnxx" | |
1138 [(set (match_operand 0 "register_operand" "=r") | |
1139 (unspec_volatile [(match_operand 1 "custom_insn_opcode" "N") | |
1140 (match_operand 2 "reg_or_0_operand" "rM") | |
1141 (match_operand 3 "reg_or_0_operand" "rM")] | |
1142 UNSPECV_CUSTOM_XNXX))] | |
1143 "" | |
1144 "custom\\t%1, %0, %z2, %z3" | |
1145 [(set_attr "type" "custom")]) | |
1146 | |
1147 | |
1148 ;; Misc. patterns | |
1149 | |
1150 (define_insn "nop" | |
1151 [(const_int 0)] | |
1152 "" | |
1153 "nop%." | |
1154 [(set_attr "type" "nop")]) | |
1155 | |
1156 ;; Connect 'sync' to 'memory_barrier' standard expand name | |
1157 (define_expand "memory_barrier" | |
1158 [(const_int 0)] | |
1159 "" | |
1160 { | |
1161 emit_insn (gen_sync ()); | |
1162 DONE; | |
1163 }) | |
1164 | |
1165 ;; For the nios2 __builtin_sync built-in function | |
1166 (define_expand "sync" | |
1167 [(set (match_dup 0) | |
1168 (unspec:BLK [(match_dup 0)] UNSPEC_SYNC))] | |
1169 "" | |
1170 { | |
1171 operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode)); | |
1172 MEM_VOLATILE_P (operands[0]) = 1; | |
1173 }) | |
1174 | |
1175 (define_insn "*sync_insn" | |
1176 [(set (match_operand:BLK 0 "" "") | |
1177 (unspec:BLK [(match_dup 0)] UNSPEC_SYNC))] | |
1178 "" | |
1179 "sync" | |
1180 [(set_attr "type" "control")]) | |
1181 | |
1182 (define_insn "rdctl" | |
1183 [(set (match_operand:SI 0 "register_operand" "=r") | |
1184 (unspec_volatile:SI [(match_operand:SI 1 "rdwrctl_operand" "O")] | |
1185 UNSPECV_RDCTL))] | |
1186 "" | |
1187 "rdctl\\t%0, ctl%1" | |
1188 [(set_attr "type" "control")]) | |
1189 | |
1190 (define_insn "wrctl" | |
1191 [(unspec_volatile:SI [(match_operand:SI 0 "rdwrctl_operand" "O") | |
1192 (match_operand:SI 1 "reg_or_0_operand" "rM")] | |
1193 UNSPECV_WRCTL)] | |
1194 "" | |
1195 "wrctl\\tctl%0, %z1" | |
1196 [(set_attr "type" "control")]) | |
1197 | |
1198 (define_insn "rdprs" | |
1199 [(set (match_operand:SI 0 "register_operand" "=r") | |
1200 (unspec_volatile:SI [(match_operand:SI 1 "rdwrctl_operand" "O") | |
1201 (match_operand:SI 2 "arith_operand" "U")] | |
1202 UNSPECV_RDPRS))] | |
1203 "" | |
1204 "rdprs\\t%0, %1, %2" | |
1205 [(set_attr "type" "control")]) | |
1206 | |
1207 ;; Cache Instructions | |
1208 | |
1209 (define_insn "flushd" | |
1210 [(unspec_volatile:SI [(match_operand:SI 0 "ldstio_memory_operand" "w")] | |
1211 UNSPECV_FLUSHD)] | |
1212 "" | |
1213 "flushd\\t%0" | |
1214 [(set_attr "type" "control")]) | |
1215 | |
1216 (define_insn "flushda" | |
1217 [(unspec_volatile:SI [(match_operand:SI 0 "ldstio_memory_operand" "w")] | |
1218 UNSPECV_FLUSHDA)] | |
1219 "" | |
1220 "flushda\\t%0" | |
1221 [(set_attr "type" "control")]) | |
1222 | |
1223 ;; R2 Instructions | |
1224 | |
1225 (define_insn "wrpie" | |
1226 [(set (match_operand:SI 0 "register_operand" "=r") | |
1227 (unspec_volatile:SI [(match_operand:SI 1 "register_operand" "r")] | |
1228 UNSPECV_WRPIE))] | |
1229 "TARGET_ARCH_R2" | |
1230 "wrpie\\t%0, %1" | |
1231 [(set_attr "type" "control")]) | |
1232 | |
1233 (define_insn "eni" | |
1234 [(unspec:VOID [(match_operand 0 "const_int_operand" "i")] | |
1235 UNSPECV_ENI)] | |
1236 "TARGET_ARCH_R2" | |
1237 "eni\\t%0" | |
1238 [(set_attr "type" "control")]) | |
1239 | |
1240 ;; Trap patterns | |
1241 (define_insn "trap" | |
1242 [(trap_if (const_int 1) (const_int 3))] | |
1243 "" | |
1244 "trap%.\\t3" | |
1245 [(set_attr "type" "control")]) | |
1246 | |
1247 (define_insn "ctrapsi4" | |
1248 [(trap_if (match_operator 0 "ordered_comparison_operator" | |
1249 [(match_operand:SI 1 "reg_or_0_operand" "rM") | |
1250 (match_operand:SI 2 "reg_or_0_operand" "rM")]) | |
1251 (match_operand 3 "const_int_operand" "i"))] | |
1252 "" | |
1253 { | |
1254 if (get_attr_length (insn) == 6) | |
1255 return "b%R0\\t%z1, %z2, 1f\;trap.n\\t%3\;1:"; | |
1256 else | |
1257 return "b%R0\\t%z1, %z2, 1f\;trap\\t%3\;1:"; | |
1258 } | |
1259 [(set_attr "type" "control") | |
1260 (set (attr "length") | |
1261 (if_then_else (match_test "nios2_cdx_narrow_form_p (insn)") | |
1262 (const_int 6) (const_int 8)))]) | |
1263 | |
1264 ;; Load the GOT register. | |
1265 (define_insn "load_got_register" | |
1266 [(set (match_operand:SI 0 "register_operand" "=&r") | |
1267 (unspec:SI [(const_int 0)] UNSPEC_LOAD_GOT_REGISTER)) | |
1268 (set (match_operand:SI 1 "register_operand" "=r") | |
1269 (unspec:SI [(const_int 0)] UNSPEC_LOAD_GOT_REGISTER))] | |
1270 "" | |
1271 "nextpc\\t%0 | |
1272 \\t1: | |
1273 \\tmovhi\\t%1, %%hiadj(_gp_got - 1b) | |
1274 \\taddi\\t%1, %1, %%lo(_gp_got - 1b)" | |
1275 [(set_attr "length" "12")]) | |
1276 | |
1277 ;; Read thread pointer register | |
1278 (define_expand "get_thread_pointersi" | |
1279 [(match_operand:SI 0 "register_operand" "=r")] | |
1280 "TARGET_LINUX_ABI" | |
1281 { | |
1282 emit_move_insn (operands[0], gen_rtx_REG (Pmode, TP_REGNO)); | |
1283 DONE; | |
1284 }) | |
1285 | |
1286 ;; Synchronization Primitives | |
1287 (include "sync.md") | |
1288 | |
1289 ;; Include the ldwm/stwm/push.n/pop.n patterns and peepholes. | |
1290 (include "ldstwm.md") | |
1291 |