]>
Commit | Line | Data |
---|---|---|
aa4945c1 JB |
1 | ;; Machine description of the Lattice Mico32 architecture for GNU C compiler. |
2 | ;; Contributed by Jon Beniston <jon@beniston.com> | |
3 | ||
a5544970 | 4 | ;; Copyright (C) 2009-2019 Free Software Foundation, Inc. |
aa4945c1 JB |
5 | |
6 | ;; This file is part of GCC. | |
7 | ||
8 | ;; GCC is free software; you can redistribute it and/or modify it | |
9 | ;; under the terms of the GNU General Public License as published | |
10 | ;; by the Free Software Foundation; either version 3, or (at your | |
11 | ;; option) any later version. | |
12 | ||
13 | ;; GCC is distributed in the hope that it will be useful, but WITHOUT | |
14 | ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | |
15 | ;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public | |
16 | ;; License for more details. | |
17 | ||
18 | ;; You should have received a copy of the GNU General Public License | |
19 | ;; along with GCC; see the file COPYING3. If not see | |
20 | ;; <http://www.gnu.org/licenses/>. | |
21 | ||
22 | ;; Include predicate and constraint definitions | |
23 | (include "predicates.md") | |
24 | (include "constraints.md") | |
25 | ||
26 | ||
27 | ;; Register numbers | |
28 | (define_constants | |
29 | [(RA_REGNUM 29) ; return address register. | |
30 | ] | |
31 | ) | |
32 | ||
33 | ;; LM32 specific volatile operations | |
34 | (define_constants | |
35 | [(UNSPECV_BLOCKAGE 1)] ; prevent scheduling across pro/epilog boundaries | |
36 | ) | |
37 | ||
38 | ;; LM32 specific operations | |
39 | (define_constants | |
40 | [(UNSPEC_GOT 2) | |
41 | (UNSPEC_GOTOFF_HI16 3) | |
42 | (UNSPEC_GOTOFF_LO16 4)] | |
43 | ) | |
44 | ||
45 | ;; --------------------------------- | |
46 | ;; instruction types | |
47 | ;; --------------------------------- | |
48 | ||
49 | (define_attr "type" | |
50 | "unknown,load,store,arith,compare,shift,multiply,divide,call,icall,ubranch,uibranch,cbranch" | |
51 | (const_string "unknown")) | |
52 | ||
53 | ;; --------------------------------- | |
54 | ;; instruction lengths | |
55 | ;; --------------------------------- | |
56 | ||
57 | ; All instructions are 4 bytes | |
58 | ; Except for branches that are out of range, and have to be implemented | |
59 | ; as two instructions | |
60 | (define_attr "length" "" | |
61 | (cond [ | |
62 | (eq_attr "type" "cbranch") | |
63 | (if_then_else | |
64 | (lt (abs (minus (match_dup 2) (pc))) | |
65 | (const_int 32768) | |
66 | ) | |
67 | (const_int 4) | |
68 | (const_int 8) | |
69 | ) | |
70 | ] | |
71 | (const_int 4)) | |
72 | ) | |
73 | ||
74 | ;; --------------------------------- | |
75 | ;; scheduling | |
76 | ;; --------------------------------- | |
77 | ||
78 | (define_automaton "lm32") | |
79 | ||
80 | (define_cpu_unit "x" "lm32") | |
81 | (define_cpu_unit "m" "lm32") | |
82 | (define_cpu_unit "w" "lm32") | |
83 | ||
84 | (define_insn_reservation "singlecycle" 1 | |
85 | (eq_attr "type" "store,arith,call,icall,ubranch,uibranch,cbranch") | |
86 | "x") | |
87 | ||
88 | (define_insn_reservation "twocycle" 2 | |
89 | (eq_attr "type" "compare,shift,divide") | |
90 | "x,m") | |
91 | ||
92 | (define_insn_reservation "threecycle" 3 | |
93 | (eq_attr "type" "load,multiply") | |
94 | "x,m,w") | |
95 | ||
96 | ;; --------------------------------- | |
97 | ;; mov | |
98 | ;; --------------------------------- | |
99 | ||
100 | (define_expand "movqi" | |
101 | [(set (match_operand:QI 0 "general_operand" "") | |
102 | (match_operand:QI 1 "general_operand" ""))] | |
103 | "" | |
104 | " | |
105 | { | |
106 | if (can_create_pseudo_p ()) | |
107 | { | |
108 | if (GET_CODE (operand0) == MEM) | |
109 | { | |
110 | /* Source operand for store must be in a register. */ | |
111 | operands[1] = force_reg (QImode, operands[1]); | |
112 | } | |
113 | } | |
114 | }") | |
115 | ||
116 | (define_expand "movhi" | |
117 | [(set (match_operand:HI 0 "general_operand" "") | |
118 | (match_operand:HI 1 "general_operand" ""))] | |
119 | "" | |
120 | " | |
121 | { | |
122 | if (can_create_pseudo_p ()) | |
123 | { | |
124 | if (GET_CODE (operands[0]) == MEM) | |
125 | { | |
126 | /* Source operand for store must be in a register. */ | |
127 | operands[1] = force_reg (HImode, operands[1]); | |
128 | } | |
129 | } | |
130 | }") | |
131 | ||
132 | (define_expand "movsi" | |
133 | [(set (match_operand:SI 0 "general_operand" "") | |
134 | (match_operand:SI 1 "general_operand" ""))] | |
135 | "" | |
136 | " | |
137 | { | |
138 | if (can_create_pseudo_p ()) | |
139 | { | |
140 | if (GET_CODE (operands[0]) == MEM | |
141 | || (GET_CODE (operands[0]) == SUBREG | |
142 | && GET_CODE (SUBREG_REG (operands[0])) == MEM)) | |
143 | { | |
144 | /* Source operand for store must be in a register. */ | |
145 | operands[1] = force_reg (SImode, operands[1]); | |
146 | } | |
147 | } | |
148 | ||
149 | if (flag_pic && symbolic_operand (operands[1], SImode)) | |
150 | { | |
151 | if (GET_CODE (operands[1]) == LABEL_REF | |
152 | || (GET_CODE (operands[1]) == SYMBOL_REF | |
153 | && SYMBOL_REF_LOCAL_P (operands[1]) | |
154 | && !SYMBOL_REF_WEAK (operands[1]))) | |
155 | { | |
156 | emit_insn (gen_movsi_gotoff_hi16 (operands[0], operands[1])); | |
157 | emit_insn (gen_addsi3 (operands[0], | |
158 | operands[0], | |
159 | pic_offset_table_rtx)); | |
160 | emit_insn (gen_movsi_gotoff_lo16 (operands[0], | |
161 | operands[0], | |
162 | operands[1])); | |
163 | } | |
164 | else | |
165 | emit_insn (gen_movsi_got (operands[0], operands[1])); | |
166 | crtl->uses_pic_offset_table = 1; | |
167 | DONE; | |
168 | } | |
169 | else if (flag_pic && GET_CODE (operands[1]) == CONST) | |
170 | { | |
171 | rtx op = XEXP (operands[1], 0); | |
172 | if (GET_CODE (op) == PLUS) | |
173 | { | |
174 | rtx arg0 = XEXP (op, 0); | |
175 | rtx arg1 = XEXP (op, 1); | |
176 | if (GET_CODE (arg0) == LABEL_REF | |
177 | || (GET_CODE (arg0) == SYMBOL_REF | |
178 | && SYMBOL_REF_LOCAL_P (arg0) | |
179 | && !SYMBOL_REF_WEAK (arg0))) | |
180 | { | |
181 | emit_insn (gen_movsi_gotoff_hi16 (operands[0], arg0)); | |
182 | emit_insn (gen_addsi3 (operands[0], | |
183 | operands[0], | |
184 | pic_offset_table_rtx)); | |
185 | emit_insn (gen_movsi_gotoff_lo16 (operands[0], | |
186 | operands[0], | |
187 | arg0)); | |
188 | } | |
189 | else | |
190 | emit_insn (gen_movsi_got (operands[0], arg0)); | |
191 | emit_insn (gen_addsi3 (operands[0], operands[0], arg1)); | |
192 | crtl->uses_pic_offset_table = 1; | |
193 | DONE; | |
194 | } | |
195 | } | |
196 | else if (!flag_pic && reloc_operand (operands[1], GET_MODE (operands[1]))) | |
197 | { | |
f7df4a84 RS |
198 | emit_insn (gen_rtx_SET (operands[0], gen_rtx_HIGH (SImode, operands[1]))); |
199 | emit_insn (gen_rtx_SET (operands[0], gen_rtx_LO_SUM (SImode, operands[0], | |
200 | operands[1]))); | |
aa4945c1 JB |
201 | DONE; |
202 | } | |
203 | else if (GET_CODE (operands[1]) == CONST_INT) | |
204 | { | |
205 | if (!(satisfies_constraint_K (operands[1]) | |
206 | || satisfies_constraint_L (operands[1]) | |
207 | || satisfies_constraint_U (operands[1]))) | |
208 | { | |
209 | emit_insn (gen_movsi_insn (operands[0], | |
210 | GEN_INT (INTVAL (operands[1]) & ~0xffff))); | |
211 | emit_insn (gen_iorsi3 (operands[0], | |
212 | operands[0], | |
213 | GEN_INT (INTVAL (operands[1]) & 0xffff))); | |
214 | DONE; | |
215 | } | |
216 | } | |
217 | }") | |
218 | ||
76715c32 | 219 | (define_expand "cpymemsi" |
aa4945c1 JB |
220 | [(parallel [(set (match_operand:BLK 0 "general_operand" "") |
221 | (match_operand:BLK 1 "general_operand" "")) | |
222 | (use (match_operand:SI 2 "" "")) | |
223 | (use (match_operand:SI 3 "const_int_operand" ""))])] | |
224 | "" | |
225 | { | |
226 | if (!lm32_expand_block_move (operands)) | |
227 | FAIL; | |
228 | DONE; | |
229 | }) | |
230 | ||
231 | ;; --------------------------------- | |
232 | ;; load/stores/moves | |
233 | ;; --------------------------------- | |
234 | ||
235 | (define_insn "movsi_got" | |
236 | [(set (match_operand:SI 0 "register_operand" "=r") | |
237 | (unspec:SI [(match_operand 1 "" "")] UNSPEC_GOT))] | |
238 | "flag_pic" | |
239 | "lw %0, (gp+got(%1))" | |
240 | [(set_attr "type" "load")] | |
241 | ) | |
242 | ||
243 | (define_insn "movsi_gotoff_hi16" | |
244 | [(set (match_operand:SI 0 "register_operand" "=r") | |
245 | (unspec:SI [(match_operand 1 "" "")] UNSPEC_GOTOFF_HI16))] | |
246 | "flag_pic" | |
247 | "orhi %0, r0, gotoffhi16(%1)" | |
248 | [(set_attr "type" "load")] | |
249 | ) | |
250 | ||
251 | (define_insn "movsi_gotoff_lo16" | |
252 | [(set (match_operand:SI 0 "register_operand" "=r") | |
253 | (unspec:SI [(plus:SI (match_operand:SI 1 "register_operand" "0") | |
254 | (match_operand 2 "" ""))] UNSPEC_GOTOFF_LO16))] | |
255 | "flag_pic" | |
256 | "addi %0, %1, gotofflo16(%2)" | |
257 | [(set_attr "type" "arith")] | |
258 | ) | |
259 | ||
260 | (define_insn "*movsi_lo_sum" | |
261 | [(set (match_operand:SI 0 "register_operand" "=r") | |
262 | (lo_sum:SI (match_operand:SI 1 "register_operand" "0") | |
263 | (match_operand:SI 2 "reloc_operand" "i")))] | |
264 | "!flag_pic" | |
265 | "ori %0, %0, lo(%2)" | |
266 | [(set_attr "type" "arith")] | |
267 | ) | |
268 | ||
269 | (define_insn "*movqi_insn" | |
270 | [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,m,m,r") | |
271 | (match_operand:QI 1 "general_operand" "m,r,r,J,n"))] | |
272 | "lm32_move_ok (QImode, operands)" | |
273 | "@ | |
274 | lbu %0, %1 | |
275 | or %0, %1, r0 | |
276 | sb %0, %1 | |
277 | sb %0, r0 | |
278 | addi %0, r0, %1" | |
279 | [(set_attr "type" "load,arith,store,store,arith")] | |
280 | ) | |
281 | ||
282 | (define_insn "*movhi_insn" | |
283 | [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,m,r,r") | |
284 | (match_operand:HI 1 "general_operand" "m,r,r,J,K,L"))] | |
285 | "lm32_move_ok (HImode, operands)" | |
286 | "@ | |
287 | lhu %0, %1 | |
288 | or %0, %1, r0 | |
289 | sh %0, %1 | |
290 | sh %0, r0 | |
291 | addi %0, r0, %1 | |
292 | ori %0, r0, %1" | |
293 | [(set_attr "type" "load,arith,store,store,arith,arith")] | |
294 | ) | |
295 | ||
296 | (define_insn "movsi_insn" | |
9b0af790 JB |
297 | [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,m,m,r,r,r,r,r,r") |
298 | (match_operand:SI 1 "general_operand" "m,r,r,J,K,L,U,S,Y,n"))] | |
aa4945c1 JB |
299 | "lm32_move_ok (SImode, operands)" |
300 | "@ | |
301 | lw %0, %1 | |
302 | or %0, %1, r0 | |
303 | sw %0, %1 | |
304 | sw %0, r0 | |
305 | addi %0, r0, %1 | |
306 | ori %0, r0, %1 | |
307 | orhi %0, r0, hi(%1) | |
308 | mva %0, gp(%1) | |
9b0af790 JB |
309 | orhi %0, r0, hi(%1) |
310 | ori %0, r0, lo(%1); orhi %0, %0, hi(%1)" | |
311 | [(set_attr "type" "load,arith,store,store,arith,arith,arith,arith,arith,arith")] | |
aa4945c1 JB |
312 | ) |
313 | ||
314 | ;; --------------------------------- | |
315 | ;; sign and zero extension | |
316 | ;; --------------------------------- | |
317 | ||
318 | (define_insn "*extendqihi2" | |
319 | [(set (match_operand:HI 0 "register_operand" "=r,r") | |
320 | (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "m,r")))] | |
321 | "TARGET_SIGN_EXTEND_ENABLED || (GET_CODE (operands[1]) != REG)" | |
322 | "@ | |
323 | lb %0, %1 | |
324 | sextb %0, %1" | |
325 | [(set_attr "type" "load,arith")] | |
326 | ) | |
327 | ||
328 | (define_insn "zero_extendqihi2" | |
329 | [(set (match_operand:HI 0 "register_operand" "=r,r") | |
330 | (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "m,r")))] | |
331 | "" | |
332 | "@ | |
333 | lbu %0, %1 | |
334 | andi %0, %1, 0xff" | |
335 | [(set_attr "type" "load,arith")] | |
336 | ) | |
337 | ||
338 | (define_insn "*extendqisi2" | |
339 | [(set (match_operand:SI 0 "register_operand" "=r,r") | |
340 | (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "m,r")))] | |
341 | "TARGET_SIGN_EXTEND_ENABLED || (GET_CODE (operands[1]) != REG)" | |
342 | "@ | |
343 | lb %0, %1 | |
344 | sextb %0, %1" | |
345 | [(set_attr "type" "load,arith")] | |
346 | ) | |
347 | ||
348 | (define_insn "zero_extendqisi2" | |
349 | [(set (match_operand:SI 0 "register_operand" "=r,r") | |
350 | (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "m,r")))] | |
351 | "" | |
352 | "@ | |
353 | lbu %0, %1 | |
354 | andi %0, %1, 0xff" | |
355 | [(set_attr "type" "load,arith")] | |
356 | ) | |
357 | ||
358 | (define_insn "*extendhisi2" | |
359 | [(set (match_operand:SI 0 "register_operand" "=r,r") | |
360 | (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "m,r")))] | |
361 | "TARGET_SIGN_EXTEND_ENABLED || (GET_CODE (operands[1]) != REG)" | |
362 | "@ | |
363 | lh %0, %1 | |
364 | sexth %0, %1" | |
365 | [(set_attr "type" "load,arith")] | |
366 | ) | |
367 | ||
368 | (define_insn "zero_extendhisi2" | |
369 | [(set (match_operand:SI 0 "register_operand" "=r,r") | |
370 | (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "m,r")))] | |
371 | "" | |
372 | "@ | |
373 | lhu %0, %1 | |
374 | andi %0, %1, 0xffff" | |
375 | [(set_attr "type" "load,arith")] | |
376 | ) | |
377 | ||
378 | ;; --------------------------------- | |
379 | ;; compare | |
380 | ;; --------------------------------- | |
381 | ||
382 | (define_expand "cstoresi4" | |
383 | [(set (match_operand:SI 0 "register_operand") | |
384 | (match_operator:SI 1 "ordered_comparison_operator" | |
385 | [(match_operand:SI 2 "register_operand") | |
386 | (match_operand:SI 3 "register_or_int_operand")]))] | |
387 | "" | |
388 | { | |
389 | lm32_expand_scc (operands); | |
390 | DONE; | |
391 | }) | |
392 | ||
393 | (define_insn "*seq" | |
394 | [(set (match_operand:SI 0 "register_operand" "=r,r") | |
395 | (eq:SI (match_operand:SI 1 "register_or_zero_operand" "%rJ,rJ") | |
396 | (match_operand:SI 2 "register_or_K_operand" "r,K")))] | |
397 | "" | |
398 | "@ | |
399 | cmpe %0, %z1, %2 | |
400 | cmpei %0, %z1, %2" | |
401 | [(set_attr "type" "compare")] | |
402 | ) | |
403 | ||
404 | (define_insn "*sne" | |
405 | [(set (match_operand:SI 0 "register_operand" "=r,r") | |
406 | (ne:SI (match_operand:SI 1 "register_or_zero_operand" "%rJ,rJ") | |
407 | (match_operand:SI 2 "register_or_K_operand" "r,K")))] | |
408 | "" | |
409 | "@ | |
410 | cmpne %0, %z1, %2 | |
411 | cmpnei %0, %z1, %2" | |
412 | [(set_attr "type" "compare")] | |
413 | ) | |
414 | ||
415 | (define_insn "*sgt" | |
416 | [(set (match_operand:SI 0 "register_operand" "=r,r") | |
417 | (gt:SI (match_operand:SI 1 "register_or_zero_operand" "rJ,rJ") | |
418 | (match_operand:SI 2 "register_or_K_operand" "r,K")))] | |
419 | "" | |
420 | "@ | |
421 | cmpg %0, %z1, %2 | |
422 | cmpgi %0, %z1, %2" | |
423 | [(set_attr "type" "compare")] | |
424 | ) | |
425 | ||
426 | (define_insn "*sge" | |
427 | [(set (match_operand:SI 0 "register_operand" "=r,r") | |
428 | (ge:SI (match_operand:SI 1 "register_or_zero_operand" "rJ,rJ") | |
429 | (match_operand:SI 2 "register_or_K_operand" "r,K")))] | |
430 | "" | |
431 | "@ | |
432 | cmpge %0, %z1, %2 | |
433 | cmpgei %0, %z1, %2" | |
434 | [(set_attr "type" "compare")] | |
435 | ) | |
436 | ||
437 | (define_insn "*sgtu" | |
438 | [(set (match_operand:SI 0 "register_operand" "=r,r") | |
439 | (gtu:SI (match_operand:SI 1 "register_or_zero_operand" "rJ,rJ") | |
440 | (match_operand:SI 2 "register_or_L_operand" "r,L")))] | |
441 | "" | |
442 | "@ | |
443 | cmpgu %0, %z1, %2 | |
444 | cmpgui %0, %z1, %2" | |
445 | [(set_attr "type" "compare")] | |
446 | ) | |
447 | ||
448 | (define_insn "*sgeu" | |
449 | [(set (match_operand:SI 0 "register_operand" "=r,r") | |
450 | (geu:SI (match_operand:SI 1 "register_or_zero_operand" "rJ,rJ") | |
451 | (match_operand:SI 2 "register_or_L_operand" "r,L")))] | |
452 | "" | |
453 | "@ | |
454 | cmpgeu %0, %z1, %2 | |
455 | cmpgeui %0, %z1, %2" | |
456 | [(set_attr "type" "compare")] | |
457 | ) | |
458 | ||
459 | ;; --------------------------------- | |
460 | ;; unconditional branch | |
461 | ;; --------------------------------- | |
462 | ||
463 | (define_insn "jump" | |
464 | [(set (pc) (label_ref (match_operand 0 "" "")))] | |
465 | "" | |
466 | "bi %0" | |
467 | [(set_attr "type" "ubranch")] | |
468 | ) | |
469 | ||
470 | (define_insn "indirect_jump" | |
471 | [(set (pc) (match_operand:SI 0 "register_operand" "r"))] | |
472 | "" | |
473 | "b %0" | |
474 | [(set_attr "type" "uibranch")] | |
475 | ) | |
476 | ||
477 | ;; --------------------------------- | |
478 | ;; conditional branch | |
479 | ;; --------------------------------- | |
480 | ||
481 | (define_expand "cbranchsi4" | |
482 | [(set (pc) | |
483 | (if_then_else (match_operator 0 "comparison_operator" | |
484 | [(match_operand:SI 1 "register_operand") | |
485 | (match_operand:SI 2 "nonmemory_operand")]) | |
486 | (label_ref (match_operand 3 "" "")) | |
487 | (pc)))] | |
488 | "" | |
489 | " | |
490 | { | |
491 | lm32_expand_conditional_branch (operands); | |
492 | DONE; | |
493 | }") | |
494 | ||
495 | (define_insn "*beq" | |
496 | [(set (pc) | |
497 | (if_then_else (eq:SI (match_operand:SI 0 "register_or_zero_operand" "rJ") | |
498 | (match_operand:SI 1 "register_or_zero_operand" "rJ")) | |
499 | (label_ref (match_operand 2 "" "")) | |
500 | (pc)))] | |
501 | "" | |
502 | { | |
503 | return get_attr_length (insn) == 4 | |
504 | ? "be %z0,%z1,%2" | |
505 | : "bne %z0,%z1,8\n\tbi %2"; | |
506 | } | |
507 | [(set_attr "type" "cbranch")]) | |
508 | ||
509 | (define_insn "*bne" | |
510 | [(set (pc) | |
511 | (if_then_else (ne:SI (match_operand:SI 0 "register_or_zero_operand" "rJ") | |
512 | (match_operand:SI 1 "register_or_zero_operand" "rJ")) | |
513 | (label_ref (match_operand 2 "" "")) | |
514 | (pc)))] | |
515 | "" | |
516 | { | |
517 | return get_attr_length (insn) == 4 | |
518 | ? "bne %z0,%z1,%2" | |
519 | : "be %z0,%z1,8\n\tbi %2"; | |
520 | } | |
521 | [(set_attr "type" "cbranch")]) | |
522 | ||
523 | (define_insn "*bgt" | |
524 | [(set (pc) | |
525 | (if_then_else (gt:SI (match_operand:SI 0 "register_or_zero_operand" "rJ") | |
526 | (match_operand:SI 1 "register_or_zero_operand" "rJ")) | |
527 | (label_ref (match_operand 2 "" "")) | |
528 | (pc)))] | |
529 | "" | |
530 | { | |
531 | return get_attr_length (insn) == 4 | |
532 | ? "bg %z0,%z1,%2" | |
533 | : "bge %z1,%z0,8\n\tbi %2"; | |
534 | } | |
535 | [(set_attr "type" "cbranch")]) | |
536 | ||
537 | (define_insn "*bge" | |
538 | [(set (pc) | |
539 | (if_then_else (ge:SI (match_operand:SI 0 "register_or_zero_operand" "rJ") | |
540 | (match_operand:SI 1 "register_or_zero_operand" "rJ")) | |
541 | (label_ref (match_operand 2 "" "")) | |
542 | (pc)))] | |
543 | "" | |
544 | { | |
545 | return get_attr_length (insn) == 4 | |
546 | ? "bge %z0,%z1,%2" | |
547 | : "bg %z1,%z0,8\n\tbi %2"; | |
548 | } | |
549 | [(set_attr "type" "cbranch")]) | |
550 | ||
551 | (define_insn "*bgtu" | |
552 | [(set (pc) | |
553 | (if_then_else (gtu:SI (match_operand:SI 0 "register_or_zero_operand" "rJ") | |
554 | (match_operand:SI 1 "register_or_zero_operand" "rJ")) | |
555 | (label_ref (match_operand 2 "" "")) | |
556 | (pc)))] | |
557 | "" | |
558 | { | |
559 | return get_attr_length (insn) == 4 | |
560 | ? "bgu %z0,%z1,%2" | |
561 | : "bgeu %z1,%z0,8\n\tbi %2"; | |
562 | } | |
563 | [(set_attr "type" "cbranch")]) | |
564 | ||
565 | (define_insn "*bgeu" | |
566 | [(set (pc) | |
567 | (if_then_else (geu:SI (match_operand:SI 0 "register_or_zero_operand" "rJ") | |
568 | (match_operand:SI 1 "register_or_zero_operand" "rJ")) | |
569 | (label_ref (match_operand 2 "" "")) | |
570 | (pc)))] | |
571 | "" | |
572 | { | |
573 | return get_attr_length (insn) == 4 | |
574 | ? "bgeu %z0,%z1,%2" | |
575 | : "bgu %z1,%z0,8\n\tbi %2"; | |
576 | } | |
577 | [(set_attr "type" "cbranch")]) | |
578 | ||
579 | ;; --------------------------------- | |
580 | ;; call | |
581 | ;; --------------------------------- | |
582 | ||
583 | (define_expand "call" | |
584 | [(parallel [(call (match_operand 0 "" "") | |
585 | (match_operand 1 "" "")) | |
586 | (clobber (reg:SI RA_REGNUM)) | |
587 | ])] | |
588 | "" | |
589 | " | |
590 | { | |
591 | rtx addr = XEXP (operands[0], 0); | |
592 | if (!CONSTANT_ADDRESS_P (addr)) | |
593 | XEXP (operands[0], 0) = force_reg (Pmode, addr); | |
594 | }") | |
595 | ||
596 | (define_insn "*call" | |
597 | [(call (mem:SI (match_operand:SI 0 "call_operand" "r,s")) | |
598 | (match_operand 1 "" "")) | |
599 | (clobber (reg:SI RA_REGNUM))] | |
600 | "" | |
601 | "@ | |
602 | call %0 | |
603 | calli %0" | |
604 | [(set_attr "type" "call,icall")] | |
605 | ) | |
606 | ||
607 | (define_expand "call_value" | |
608 | [(parallel [(set (match_operand 0 "" "") | |
609 | (call (match_operand 1 "" "") | |
610 | (match_operand 2 "" ""))) | |
611 | (clobber (reg:SI RA_REGNUM)) | |
612 | ])] | |
613 | "" | |
614 | " | |
615 | { | |
616 | rtx addr = XEXP (operands[1], 0); | |
617 | if (!CONSTANT_ADDRESS_P (addr)) | |
618 | XEXP (operands[1], 0) = force_reg (Pmode, addr); | |
619 | }") | |
620 | ||
621 | (define_insn "*call_value" | |
622 | [(set (match_operand 0 "register_operand" "=r,r") | |
623 | (call (mem:SI (match_operand:SI 1 "call_operand" "r,s")) | |
624 | (match_operand 2 "" ""))) | |
625 | (clobber (reg:SI RA_REGNUM))] | |
626 | "" | |
627 | "@ | |
628 | call %1 | |
629 | calli %1" | |
630 | [(set_attr "type" "call,icall")] | |
631 | ) | |
632 | ||
633 | (define_insn "return_internal" | |
634 | [(use (match_operand:SI 0 "register_operand" "r")) | |
635 | (return)] | |
636 | "" | |
637 | "b %0" | |
638 | [(set_attr "type" "uibranch")] | |
639 | ) | |
640 | ||
9b0af790 | 641 | (define_expand "return" |
aa4945c1 JB |
642 | [(return)] |
643 | "lm32_can_use_return ()" | |
9b0af790 JB |
644 | "" |
645 | ) | |
646 | ||
647 | (define_expand "simple_return" | |
648 | [(simple_return)] | |
649 | "" | |
650 | "" | |
651 | ) | |
652 | ||
653 | (define_insn "*return" | |
654 | [(return)] | |
655 | "reload_completed" | |
656 | "ret" | |
657 | [(set_attr "type" "uibranch")] | |
658 | ) | |
659 | ||
660 | (define_insn "*simple_return" | |
661 | [(simple_return)] | |
662 | "" | |
aa4945c1 JB |
663 | "ret" |
664 | [(set_attr "type" "uibranch")] | |
665 | ) | |
666 | ||
667 | ;; --------------------------------- | |
668 | ;; switch/case statements | |
669 | ;; --------------------------------- | |
670 | ||
671 | (define_expand "tablejump" | |
672 | [(set (pc) (match_operand 0 "register_operand" "")) | |
673 | (use (label_ref (match_operand 1 "" "")))] | |
674 | "" | |
675 | " | |
676 | { | |
677 | rtx target = operands[0]; | |
678 | if (flag_pic) | |
679 | { | |
680 | /* For PIC, the table entry is relative to the start of the table. */ | |
681 | rtx label = gen_reg_rtx (SImode); | |
682 | target = gen_reg_rtx (SImode); | |
683 | emit_move_insn (label, gen_rtx_LABEL_REF (SImode, operands[1])); | |
684 | emit_insn (gen_addsi3 (target, operands[0], label)); | |
685 | } | |
686 | emit_jump_insn (gen_tablejumpsi (target, operands[1])); | |
687 | DONE; | |
688 | }") | |
689 | ||
690 | (define_insn "tablejumpsi" | |
691 | [(set (pc) (match_operand:SI 0 "register_operand" "r")) | |
692 | (use (label_ref (match_operand 1 "" "")))] | |
693 | "" | |
694 | "b %0" | |
695 | [(set_attr "type" "ubranch")] | |
696 | ) | |
697 | ||
698 | ;; --------------------------------- | |
699 | ;; arithmetic | |
700 | ;; --------------------------------- | |
701 | ||
702 | (define_insn "addsi3" | |
703 | [(set (match_operand:SI 0 "register_operand" "=r,r") | |
704 | (plus:SI (match_operand:SI 1 "register_or_zero_operand" "%rJ,rJ") | |
705 | (match_operand:SI 2 "register_or_K_operand" "r,K")))] | |
706 | "" | |
707 | "@ | |
708 | add %0, %z1, %2 | |
709 | addi %0, %z1, %2" | |
710 | [(set_attr "type" "arith")] | |
711 | ) | |
712 | ||
713 | (define_insn "subsi3" | |
714 | [(set (match_operand:SI 0 "register_operand" "=r") | |
715 | (minus:SI (match_operand:SI 1 "register_or_zero_operand" "rJ") | |
716 | (match_operand:SI 2 "register_or_zero_operand" "rJ")))] | |
717 | "" | |
718 | "sub %0, %z1, %z2" | |
719 | [(set_attr "type" "arith")] | |
720 | ) | |
721 | ||
722 | (define_insn "mulsi3" | |
723 | [(set (match_operand:SI 0 "register_operand" "=r,r") | |
724 | (mult:SI (match_operand:SI 1 "register_or_zero_operand" "%rJ,rJ") | |
725 | (match_operand:SI 2 "register_or_K_operand" "r,K")))] | |
726 | "TARGET_MULTIPLY_ENABLED" | |
727 | "@ | |
728 | mul %0, %z1, %2 | |
729 | muli %0, %z1, %2" | |
730 | [(set_attr "type" "multiply")] | |
731 | ) | |
732 | ||
733 | (define_insn "udivsi3" | |
734 | [(set (match_operand:SI 0 "register_operand" "=r") | |
735 | (udiv:SI (match_operand:SI 1 "register_or_zero_operand" "rJ") | |
736 | (match_operand:SI 2 "register_operand" "r")))] | |
737 | "TARGET_DIVIDE_ENABLED" | |
738 | "divu %0, %z1, %2" | |
739 | [(set_attr "type" "divide")] | |
740 | ) | |
741 | ||
742 | (define_insn "umodsi3" | |
743 | [(set (match_operand:SI 0 "register_operand" "=r") | |
744 | (umod:SI (match_operand:SI 1 "register_or_zero_operand" "rJ") | |
745 | (match_operand:SI 2 "register_operand" "r")))] | |
746 | "TARGET_DIVIDE_ENABLED" | |
747 | "modu %0, %z1, %2" | |
748 | [(set_attr "type" "divide")] | |
749 | ) | |
750 | ||
751 | ;; --------------------------------- | |
752 | ;; negation and inversion | |
753 | ;; --------------------------------- | |
754 | ||
755 | (define_insn "negsi2" | |
756 | [(set (match_operand:SI 0 "register_operand" "=r") | |
757 | (neg:SI (match_operand:SI 1 "register_or_zero_operand" "rJ")))] | |
758 | "" | |
759 | "sub %0, r0, %z1" | |
760 | [(set_attr "type" "arith")] | |
761 | ) | |
762 | ||
763 | (define_insn "one_cmplsi2" | |
764 | [(set (match_operand:SI 0 "register_operand" "=r") | |
765 | (not:SI (match_operand:SI 1 "register_or_zero_operand" "rJ")))] | |
766 | "" | |
767 | "not %0, %z1" | |
768 | [(set_attr "type" "arith")] | |
769 | ) | |
770 | ||
771 | ;; --------------------------------- | |
772 | ;; logical | |
773 | ;; --------------------------------- | |
774 | ||
775 | (define_insn "andsi3" | |
776 | [(set (match_operand:SI 0 "register_operand" "=r,r") | |
777 | (and:SI (match_operand:SI 1 "register_or_zero_operand" "%rJ,rJ") | |
778 | (match_operand:SI 2 "register_or_L_operand" "r,L")))] | |
779 | "" | |
780 | "@ | |
781 | and %0, %z1, %2 | |
782 | andi %0, %z1, %2" | |
783 | [(set_attr "type" "arith")] | |
784 | ) | |
785 | ||
786 | (define_insn "iorsi3" | |
787 | [(set (match_operand:SI 0 "register_operand" "=r,r") | |
788 | (ior:SI (match_operand:SI 1 "register_or_zero_operand" "%rJ,rJ") | |
789 | (match_operand:SI 2 "register_or_L_operand" "r,L")))] | |
790 | "" | |
791 | "@ | |
792 | or %0, %z1, %2 | |
793 | ori %0, %z1, %2" | |
794 | [(set_attr "type" "arith")] | |
795 | ) | |
796 | ||
797 | (define_insn "xorsi3" | |
798 | [(set (match_operand:SI 0 "register_operand" "=r,r") | |
799 | (xor:SI (match_operand:SI 1 "register_or_zero_operand" "%rJ,rJ") | |
800 | (match_operand:SI 2 "register_or_L_operand" "r,L")))] | |
801 | "" | |
802 | "@ | |
803 | xor %0, %z1, %2 | |
804 | xori %0, %z1, %2" | |
805 | [(set_attr "type" "arith")] | |
806 | ) | |
807 | ||
808 | (define_insn "*norsi3" | |
809 | [(set (match_operand:SI 0 "register_operand" "=r,r") | |
810 | (not:SI (ior:SI (match_operand:SI 1 "register_or_zero_operand" "%rJ,rJ") | |
811 | (match_operand:SI 2 "register_or_L_operand" "r,L"))))] | |
812 | "" | |
813 | "@ | |
814 | nor %0, %z1, %2 | |
815 | nori %0, %z1, %2" | |
816 | [(set_attr "type" "arith")] | |
817 | ) | |
818 | ||
819 | (define_insn "*xnorsi3" | |
820 | [(set (match_operand:SI 0 "register_operand" "=r,r") | |
821 | (not:SI (xor:SI (match_operand:SI 1 "register_or_zero_operand" "%rJ,rJ") | |
822 | (match_operand:SI 2 "register_or_L_operand" "r,L"))))] | |
823 | "" | |
824 | "@ | |
825 | xnor %0, %z1, %2 | |
826 | xnori %0, %z1, %2" | |
827 | [(set_attr "type" "arith")] | |
828 | ) | |
829 | ||
830 | ;; --------------------------------- | |
831 | ;; shifts | |
832 | ;; --------------------------------- | |
833 | ||
834 | (define_expand "ashlsi3" | |
835 | [(set (match_operand:SI 0 "register_operand" "") | |
836 | (ashift:SI (match_operand:SI 1 "register_or_zero_operand" "") | |
837 | (match_operand:SI 2 "register_or_L_operand" "")))] | |
838 | "" | |
839 | { | |
840 | if (!TARGET_BARREL_SHIFT_ENABLED) | |
841 | { | |
842 | if (!optimize_size | |
843 | && satisfies_constraint_L (operands[2]) | |
844 | && INTVAL (operands[2]) <= 8) | |
845 | { | |
846 | int i; | |
847 | int shifts = INTVAL (operands[2]); | |
aa4945c1 JB |
848 | |
849 | if (shifts == 0) | |
850 | emit_move_insn (operands[0], operands[1]); | |
851 | else | |
852 | emit_insn (gen_addsi3 (operands[0], operands[1], operands[1])); | |
853 | for (i = 1; i < shifts; i++) | |
854 | emit_insn (gen_addsi3 (operands[0], operands[0], operands[0])); | |
855 | DONE; | |
856 | } | |
857 | else | |
858 | FAIL; | |
859 | } | |
860 | }) | |
861 | ||
862 | (define_insn "*ashlsi3" | |
863 | [(set (match_operand:SI 0 "register_operand" "=r,r") | |
864 | (ashift:SI (match_operand:SI 1 "register_or_zero_operand" "rJ,rJ") | |
865 | (match_operand:SI 2 "register_or_L_operand" "r,L")))] | |
866 | "TARGET_BARREL_SHIFT_ENABLED" | |
867 | "@ | |
868 | sl %0, %z1, %2 | |
869 | sli %0, %z1, %2" | |
870 | [(set_attr "type" "shift")] | |
871 | ) | |
872 | ||
873 | (define_expand "ashrsi3" | |
874 | [(set (match_operand:SI 0 "register_operand" "") | |
875 | (ashiftrt:SI (match_operand:SI 1 "register_or_zero_operand" "") | |
876 | (match_operand:SI 2 "register_or_L_operand" "")))] | |
877 | "" | |
878 | { | |
879 | if (!TARGET_BARREL_SHIFT_ENABLED) | |
880 | { | |
881 | if (!optimize_size | |
882 | && satisfies_constraint_L (operands[2]) | |
883 | && INTVAL (operands[2]) <= 8) | |
884 | { | |
885 | int i; | |
886 | int shifts = INTVAL (operands[2]); | |
887 | rtx one = GEN_INT (1); | |
888 | ||
889 | if (shifts == 0) | |
890 | emit_move_insn (operands[0], operands[1]); | |
891 | else | |
892 | emit_insn (gen_ashrsi3_1bit (operands[0], operands[1], one)); | |
893 | for (i = 1; i < shifts; i++) | |
894 | emit_insn (gen_ashrsi3_1bit (operands[0], operands[0], one)); | |
895 | DONE; | |
896 | } | |
897 | else | |
898 | FAIL; | |
899 | } | |
900 | }) | |
901 | ||
902 | (define_insn "*ashrsi3" | |
903 | [(set (match_operand:SI 0 "register_operand" "=r,r") | |
904 | (ashiftrt:SI (match_operand:SI 1 "register_or_zero_operand" "rJ,rJ") | |
905 | (match_operand:SI 2 "register_or_L_operand" "r,L")))] | |
906 | "TARGET_BARREL_SHIFT_ENABLED" | |
907 | "@ | |
908 | sr %0, %z1, %2 | |
909 | sri %0, %z1, %2" | |
910 | [(set_attr "type" "shift")] | |
911 | ) | |
912 | ||
913 | (define_insn "ashrsi3_1bit" | |
914 | [(set (match_operand:SI 0 "register_operand" "=r") | |
915 | (ashiftrt:SI (match_operand:SI 1 "register_or_zero_operand" "rJ") | |
916 | (match_operand:SI 2 "constant_M_operand" "M")))] | |
917 | "!TARGET_BARREL_SHIFT_ENABLED" | |
918 | "sri %0, %z1, %2" | |
919 | [(set_attr "type" "shift")] | |
920 | ) | |
921 | ||
922 | (define_expand "lshrsi3" | |
923 | [(set (match_operand:SI 0 "register_operand" "") | |
924 | (lshiftrt:SI (match_operand:SI 1 "register_or_zero_operand" "") | |
925 | (match_operand:SI 2 "register_or_L_operand" "")))] | |
926 | "" | |
927 | { | |
928 | if (!TARGET_BARREL_SHIFT_ENABLED) | |
929 | { | |
930 | if (!optimize_size | |
931 | && satisfies_constraint_L (operands[2]) | |
932 | && INTVAL (operands[2]) <= 8) | |
933 | { | |
934 | int i; | |
935 | int shifts = INTVAL (operands[2]); | |
936 | rtx one = GEN_INT (1); | |
937 | ||
938 | if (shifts == 0) | |
939 | emit_move_insn (operands[0], operands[1]); | |
940 | else | |
941 | emit_insn (gen_lshrsi3_1bit (operands[0], operands[1], one)); | |
942 | for (i = 1; i < shifts; i++) | |
943 | emit_insn (gen_lshrsi3_1bit (operands[0], operands[0], one)); | |
944 | DONE; | |
945 | } | |
946 | else | |
947 | FAIL; | |
948 | } | |
949 | }) | |
950 | ||
951 | (define_insn "*lshrsi3" | |
952 | [(set (match_operand:SI 0 "register_operand" "=r,r") | |
953 | (lshiftrt:SI (match_operand:SI 1 "register_or_zero_operand" "rJ,rJ") | |
954 | (match_operand:SI 2 "register_or_L_operand" "r,L")))] | |
955 | "TARGET_BARREL_SHIFT_ENABLED" | |
956 | "@ | |
957 | sru %0, %z1, %2 | |
958 | srui %0, %z1, %2" | |
959 | [(set_attr "type" "shift")] | |
960 | ) | |
961 | ||
962 | (define_insn "lshrsi3_1bit" | |
963 | [(set (match_operand:SI 0 "register_operand" "=r") | |
964 | (lshiftrt:SI (match_operand:SI 1 "register_or_zero_operand" "rJ") | |
965 | (match_operand:SI 2 "constant_M_operand" "M")))] | |
966 | "!TARGET_BARREL_SHIFT_ENABLED" | |
967 | "srui %0, %z1, %2" | |
968 | [(set_attr "type" "shift")] | |
969 | ) | |
970 | ||
971 | ;; --------------------------------- | |
972 | ;; function entry / exit | |
973 | ;; --------------------------------- | |
974 | ||
975 | (define_expand "prologue" | |
976 | [(const_int 1)] | |
977 | "" | |
978 | " | |
979 | { | |
980 | lm32_expand_prologue (); | |
981 | DONE; | |
982 | }") | |
983 | ||
984 | (define_expand "epilogue" | |
985 | [(return)] | |
986 | "" | |
987 | " | |
988 | { | |
989 | lm32_expand_epilogue (); | |
990 | DONE; | |
991 | }") | |
992 | ||
993 | ;; --------------------------------- | |
994 | ;; nop | |
995 | ;; --------------------------------- | |
996 | ||
997 | (define_insn "nop" | |
998 | [(const_int 0)] | |
999 | "" | |
1000 | "nop" | |
1001 | [(set_attr "type" "arith")] | |
1002 | ) | |
1003 | ||
1004 | ;; --------------------------------- | |
1005 | ;; blockage | |
1006 | ;; --------------------------------- | |
1007 | ||
1008 | ;; used to stop the scheduler from | |
1009 | ;; scheduling code across certain boundaries | |
1010 | ||
1011 | (define_insn "blockage" | |
1012 | [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)] | |
1013 | "" | |
1014 | "" | |
1015 | [(set_attr "length" "0")] | |
1016 | ) |