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