Mercurial > hg > CbC > CbC_gcc
comparison gcc/config/lm32/lm32.md @ 55:77e2b8dfacca gcc-4.4.5
update it from 4.4.3 to 4.5.0
author | ryoma <e075725@ie.u-ryukyu.ac.jp> |
---|---|
date | Fri, 12 Feb 2010 23:39:51 +0900 |
parents | |
children | f6334be47118 |
comparison
equal
deleted
inserted
replaced
52:c156f1bd5cd9 | 55:77e2b8dfacca |
---|---|
1 ;; Machine description of the Lattice Mico32 architecture for GNU C compiler. | |
2 ;; Contributed by Jon Beniston <jon@beniston.com> | |
3 | |
4 ;; Copyright (C) 2009 Free Software Foundation, Inc. | |
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 { | |
198 emit_insn (gen_rtx_SET (SImode, operands[0], gen_rtx_HIGH (SImode, operands[1]))); | |
199 emit_insn (gen_rtx_SET (SImode, operands[0], gen_rtx_LO_SUM (SImode, operands[0], operands[1]))); | |
200 DONE; | |
201 } | |
202 else if (GET_CODE (operands[1]) == CONST_INT) | |
203 { | |
204 if (!(satisfies_constraint_K (operands[1]) | |
205 || satisfies_constraint_L (operands[1]) | |
206 || satisfies_constraint_U (operands[1]))) | |
207 { | |
208 emit_insn (gen_movsi_insn (operands[0], | |
209 GEN_INT (INTVAL (operands[1]) & ~0xffff))); | |
210 emit_insn (gen_iorsi3 (operands[0], | |
211 operands[0], | |
212 GEN_INT (INTVAL (operands[1]) & 0xffff))); | |
213 DONE; | |
214 } | |
215 } | |
216 }") | |
217 | |
218 (define_expand "movmemsi" | |
219 [(parallel [(set (match_operand:BLK 0 "general_operand" "") | |
220 (match_operand:BLK 1 "general_operand" "")) | |
221 (use (match_operand:SI 2 "" "")) | |
222 (use (match_operand:SI 3 "const_int_operand" ""))])] | |
223 "" | |
224 { | |
225 if (!lm32_expand_block_move (operands)) | |
226 FAIL; | |
227 DONE; | |
228 }) | |
229 | |
230 ;; --------------------------------- | |
231 ;; load/stores/moves | |
232 ;; --------------------------------- | |
233 | |
234 (define_insn "movsi_got" | |
235 [(set (match_operand:SI 0 "register_operand" "=r") | |
236 (unspec:SI [(match_operand 1 "" "")] UNSPEC_GOT))] | |
237 "flag_pic" | |
238 "lw %0, (gp+got(%1))" | |
239 [(set_attr "type" "load")] | |
240 ) | |
241 | |
242 (define_insn "movsi_gotoff_hi16" | |
243 [(set (match_operand:SI 0 "register_operand" "=r") | |
244 (unspec:SI [(match_operand 1 "" "")] UNSPEC_GOTOFF_HI16))] | |
245 "flag_pic" | |
246 "orhi %0, r0, gotoffhi16(%1)" | |
247 [(set_attr "type" "load")] | |
248 ) | |
249 | |
250 (define_insn "movsi_gotoff_lo16" | |
251 [(set (match_operand:SI 0 "register_operand" "=r") | |
252 (unspec:SI [(plus:SI (match_operand:SI 1 "register_operand" "0") | |
253 (match_operand 2 "" ""))] UNSPEC_GOTOFF_LO16))] | |
254 "flag_pic" | |
255 "addi %0, %1, gotofflo16(%2)" | |
256 [(set_attr "type" "arith")] | |
257 ) | |
258 | |
259 (define_insn "*movsi_lo_sum" | |
260 [(set (match_operand:SI 0 "register_operand" "=r") | |
261 (lo_sum:SI (match_operand:SI 1 "register_operand" "0") | |
262 (match_operand:SI 2 "reloc_operand" "i")))] | |
263 "!flag_pic" | |
264 "ori %0, %0, lo(%2)" | |
265 [(set_attr "type" "arith")] | |
266 ) | |
267 | |
268 (define_insn "*movqi_insn" | |
269 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,m,m,r") | |
270 (match_operand:QI 1 "general_operand" "m,r,r,J,n"))] | |
271 "lm32_move_ok (QImode, operands)" | |
272 "@ | |
273 lbu %0, %1 | |
274 or %0, %1, r0 | |
275 sb %0, %1 | |
276 sb %0, r0 | |
277 addi %0, r0, %1" | |
278 [(set_attr "type" "load,arith,store,store,arith")] | |
279 ) | |
280 | |
281 (define_insn "*movhi_insn" | |
282 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,m,r,r") | |
283 (match_operand:HI 1 "general_operand" "m,r,r,J,K,L"))] | |
284 "lm32_move_ok (HImode, operands)" | |
285 "@ | |
286 lhu %0, %1 | |
287 or %0, %1, r0 | |
288 sh %0, %1 | |
289 sh %0, r0 | |
290 addi %0, r0, %1 | |
291 ori %0, r0, %1" | |
292 [(set_attr "type" "load,arith,store,store,arith,arith")] | |
293 ) | |
294 | |
295 (define_insn "movsi_insn" | |
296 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,m,m,r,r,r,r,r") | |
297 (match_operand:SI 1 "movsi_rhs_operand" "m,r,r,J,K,L,U,S,Y"))] | |
298 "lm32_move_ok (SImode, operands)" | |
299 "@ | |
300 lw %0, %1 | |
301 or %0, %1, r0 | |
302 sw %0, %1 | |
303 sw %0, r0 | |
304 addi %0, r0, %1 | |
305 ori %0, r0, %1 | |
306 orhi %0, r0, hi(%1) | |
307 mva %0, gp(%1) | |
308 orhi %0, r0, hi(%1)" | |
309 [(set_attr "type" "load,arith,store,store,arith,arith,arith,arith,arith")] | |
310 ) | |
311 | |
312 ;; --------------------------------- | |
313 ;; sign and zero extension | |
314 ;; --------------------------------- | |
315 | |
316 (define_insn "*extendqihi2" | |
317 [(set (match_operand:HI 0 "register_operand" "=r,r") | |
318 (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "m,r")))] | |
319 "TARGET_SIGN_EXTEND_ENABLED || (GET_CODE (operands[1]) != REG)" | |
320 "@ | |
321 lb %0, %1 | |
322 sextb %0, %1" | |
323 [(set_attr "type" "load,arith")] | |
324 ) | |
325 | |
326 (define_insn "zero_extendqihi2" | |
327 [(set (match_operand:HI 0 "register_operand" "=r,r") | |
328 (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "m,r")))] | |
329 "" | |
330 "@ | |
331 lbu %0, %1 | |
332 andi %0, %1, 0xff" | |
333 [(set_attr "type" "load,arith")] | |
334 ) | |
335 | |
336 (define_insn "*extendqisi2" | |
337 [(set (match_operand:SI 0 "register_operand" "=r,r") | |
338 (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "m,r")))] | |
339 "TARGET_SIGN_EXTEND_ENABLED || (GET_CODE (operands[1]) != REG)" | |
340 "@ | |
341 lb %0, %1 | |
342 sextb %0, %1" | |
343 [(set_attr "type" "load,arith")] | |
344 ) | |
345 | |
346 (define_insn "zero_extendqisi2" | |
347 [(set (match_operand:SI 0 "register_operand" "=r,r") | |
348 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "m,r")))] | |
349 "" | |
350 "@ | |
351 lbu %0, %1 | |
352 andi %0, %1, 0xff" | |
353 [(set_attr "type" "load,arith")] | |
354 ) | |
355 | |
356 (define_insn "*extendhisi2" | |
357 [(set (match_operand:SI 0 "register_operand" "=r,r") | |
358 (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "m,r")))] | |
359 "TARGET_SIGN_EXTEND_ENABLED || (GET_CODE (operands[1]) != REG)" | |
360 "@ | |
361 lh %0, %1 | |
362 sexth %0, %1" | |
363 [(set_attr "type" "load,arith")] | |
364 ) | |
365 | |
366 (define_insn "zero_extendhisi2" | |
367 [(set (match_operand:SI 0 "register_operand" "=r,r") | |
368 (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "m,r")))] | |
369 "" | |
370 "@ | |
371 lhu %0, %1 | |
372 andi %0, %1, 0xffff" | |
373 [(set_attr "type" "load,arith")] | |
374 ) | |
375 | |
376 ;; --------------------------------- | |
377 ;; compare | |
378 ;; --------------------------------- | |
379 | |
380 (define_expand "cstoresi4" | |
381 [(set (match_operand:SI 0 "register_operand") | |
382 (match_operator:SI 1 "ordered_comparison_operator" | |
383 [(match_operand:SI 2 "register_operand") | |
384 (match_operand:SI 3 "register_or_int_operand")]))] | |
385 "" | |
386 { | |
387 lm32_expand_scc (operands); | |
388 DONE; | |
389 }) | |
390 | |
391 (define_insn "*seq" | |
392 [(set (match_operand:SI 0 "register_operand" "=r,r") | |
393 (eq:SI (match_operand:SI 1 "register_or_zero_operand" "%rJ,rJ") | |
394 (match_operand:SI 2 "register_or_K_operand" "r,K")))] | |
395 "" | |
396 "@ | |
397 cmpe %0, %z1, %2 | |
398 cmpei %0, %z1, %2" | |
399 [(set_attr "type" "compare")] | |
400 ) | |
401 | |
402 (define_insn "*sne" | |
403 [(set (match_operand:SI 0 "register_operand" "=r,r") | |
404 (ne:SI (match_operand:SI 1 "register_or_zero_operand" "%rJ,rJ") | |
405 (match_operand:SI 2 "register_or_K_operand" "r,K")))] | |
406 "" | |
407 "@ | |
408 cmpne %0, %z1, %2 | |
409 cmpnei %0, %z1, %2" | |
410 [(set_attr "type" "compare")] | |
411 ) | |
412 | |
413 (define_insn "*sgt" | |
414 [(set (match_operand:SI 0 "register_operand" "=r,r") | |
415 (gt:SI (match_operand:SI 1 "register_or_zero_operand" "rJ,rJ") | |
416 (match_operand:SI 2 "register_or_K_operand" "r,K")))] | |
417 "" | |
418 "@ | |
419 cmpg %0, %z1, %2 | |
420 cmpgi %0, %z1, %2" | |
421 [(set_attr "type" "compare")] | |
422 ) | |
423 | |
424 (define_insn "*sge" | |
425 [(set (match_operand:SI 0 "register_operand" "=r,r") | |
426 (ge:SI (match_operand:SI 1 "register_or_zero_operand" "rJ,rJ") | |
427 (match_operand:SI 2 "register_or_K_operand" "r,K")))] | |
428 "" | |
429 "@ | |
430 cmpge %0, %z1, %2 | |
431 cmpgei %0, %z1, %2" | |
432 [(set_attr "type" "compare")] | |
433 ) | |
434 | |
435 (define_insn "*sgtu" | |
436 [(set (match_operand:SI 0 "register_operand" "=r,r") | |
437 (gtu:SI (match_operand:SI 1 "register_or_zero_operand" "rJ,rJ") | |
438 (match_operand:SI 2 "register_or_L_operand" "r,L")))] | |
439 "" | |
440 "@ | |
441 cmpgu %0, %z1, %2 | |
442 cmpgui %0, %z1, %2" | |
443 [(set_attr "type" "compare")] | |
444 ) | |
445 | |
446 (define_insn "*sgeu" | |
447 [(set (match_operand:SI 0 "register_operand" "=r,r") | |
448 (geu:SI (match_operand:SI 1 "register_or_zero_operand" "rJ,rJ") | |
449 (match_operand:SI 2 "register_or_L_operand" "r,L")))] | |
450 "" | |
451 "@ | |
452 cmpgeu %0, %z1, %2 | |
453 cmpgeui %0, %z1, %2" | |
454 [(set_attr "type" "compare")] | |
455 ) | |
456 | |
457 ;; --------------------------------- | |
458 ;; unconditional branch | |
459 ;; --------------------------------- | |
460 | |
461 (define_insn "jump" | |
462 [(set (pc) (label_ref (match_operand 0 "" "")))] | |
463 "" | |
464 "bi %0" | |
465 [(set_attr "type" "ubranch")] | |
466 ) | |
467 | |
468 (define_insn "indirect_jump" | |
469 [(set (pc) (match_operand:SI 0 "register_operand" "r"))] | |
470 "" | |
471 "b %0" | |
472 [(set_attr "type" "uibranch")] | |
473 ) | |
474 | |
475 ;; --------------------------------- | |
476 ;; conditional branch | |
477 ;; --------------------------------- | |
478 | |
479 (define_expand "cbranchsi4" | |
480 [(set (pc) | |
481 (if_then_else (match_operator 0 "comparison_operator" | |
482 [(match_operand:SI 1 "register_operand") | |
483 (match_operand:SI 2 "nonmemory_operand")]) | |
484 (label_ref (match_operand 3 "" "")) | |
485 (pc)))] | |
486 "" | |
487 " | |
488 { | |
489 lm32_expand_conditional_branch (operands); | |
490 DONE; | |
491 }") | |
492 | |
493 (define_insn "*beq" | |
494 [(set (pc) | |
495 (if_then_else (eq:SI (match_operand:SI 0 "register_or_zero_operand" "rJ") | |
496 (match_operand:SI 1 "register_or_zero_operand" "rJ")) | |
497 (label_ref (match_operand 2 "" "")) | |
498 (pc)))] | |
499 "" | |
500 { | |
501 return get_attr_length (insn) == 4 | |
502 ? "be %z0,%z1,%2" | |
503 : "bne %z0,%z1,8\n\tbi %2"; | |
504 } | |
505 [(set_attr "type" "cbranch")]) | |
506 | |
507 (define_insn "*bne" | |
508 [(set (pc) | |
509 (if_then_else (ne:SI (match_operand:SI 0 "register_or_zero_operand" "rJ") | |
510 (match_operand:SI 1 "register_or_zero_operand" "rJ")) | |
511 (label_ref (match_operand 2 "" "")) | |
512 (pc)))] | |
513 "" | |
514 { | |
515 return get_attr_length (insn) == 4 | |
516 ? "bne %z0,%z1,%2" | |
517 : "be %z0,%z1,8\n\tbi %2"; | |
518 } | |
519 [(set_attr "type" "cbranch")]) | |
520 | |
521 (define_insn "*bgt" | |
522 [(set (pc) | |
523 (if_then_else (gt:SI (match_operand:SI 0 "register_or_zero_operand" "rJ") | |
524 (match_operand:SI 1 "register_or_zero_operand" "rJ")) | |
525 (label_ref (match_operand 2 "" "")) | |
526 (pc)))] | |
527 "" | |
528 { | |
529 return get_attr_length (insn) == 4 | |
530 ? "bg %z0,%z1,%2" | |
531 : "bge %z1,%z0,8\n\tbi %2"; | |
532 } | |
533 [(set_attr "type" "cbranch")]) | |
534 | |
535 (define_insn "*bge" | |
536 [(set (pc) | |
537 (if_then_else (ge:SI (match_operand:SI 0 "register_or_zero_operand" "rJ") | |
538 (match_operand:SI 1 "register_or_zero_operand" "rJ")) | |
539 (label_ref (match_operand 2 "" "")) | |
540 (pc)))] | |
541 "" | |
542 { | |
543 return get_attr_length (insn) == 4 | |
544 ? "bge %z0,%z1,%2" | |
545 : "bg %z1,%z0,8\n\tbi %2"; | |
546 } | |
547 [(set_attr "type" "cbranch")]) | |
548 | |
549 (define_insn "*bgtu" | |
550 [(set (pc) | |
551 (if_then_else (gtu:SI (match_operand:SI 0 "register_or_zero_operand" "rJ") | |
552 (match_operand:SI 1 "register_or_zero_operand" "rJ")) | |
553 (label_ref (match_operand 2 "" "")) | |
554 (pc)))] | |
555 "" | |
556 { | |
557 return get_attr_length (insn) == 4 | |
558 ? "bgu %z0,%z1,%2" | |
559 : "bgeu %z1,%z0,8\n\tbi %2"; | |
560 } | |
561 [(set_attr "type" "cbranch")]) | |
562 | |
563 (define_insn "*bgeu" | |
564 [(set (pc) | |
565 (if_then_else (geu:SI (match_operand:SI 0 "register_or_zero_operand" "rJ") | |
566 (match_operand:SI 1 "register_or_zero_operand" "rJ")) | |
567 (label_ref (match_operand 2 "" "")) | |
568 (pc)))] | |
569 "" | |
570 { | |
571 return get_attr_length (insn) == 4 | |
572 ? "bgeu %z0,%z1,%2" | |
573 : "bgu %z1,%z0,8\n\tbi %2"; | |
574 } | |
575 [(set_attr "type" "cbranch")]) | |
576 | |
577 ;; --------------------------------- | |
578 ;; call | |
579 ;; --------------------------------- | |
580 | |
581 (define_expand "call" | |
582 [(parallel [(call (match_operand 0 "" "") | |
583 (match_operand 1 "" "")) | |
584 (clobber (reg:SI RA_REGNUM)) | |
585 ])] | |
586 "" | |
587 " | |
588 { | |
589 rtx addr = XEXP (operands[0], 0); | |
590 if (!CONSTANT_ADDRESS_P (addr)) | |
591 XEXP (operands[0], 0) = force_reg (Pmode, addr); | |
592 }") | |
593 | |
594 (define_insn "*call" | |
595 [(call (mem:SI (match_operand:SI 0 "call_operand" "r,s")) | |
596 (match_operand 1 "" "")) | |
597 (clobber (reg:SI RA_REGNUM))] | |
598 "" | |
599 "@ | |
600 call %0 | |
601 calli %0" | |
602 [(set_attr "type" "call,icall")] | |
603 ) | |
604 | |
605 (define_expand "call_value" | |
606 [(parallel [(set (match_operand 0 "" "") | |
607 (call (match_operand 1 "" "") | |
608 (match_operand 2 "" ""))) | |
609 (clobber (reg:SI RA_REGNUM)) | |
610 ])] | |
611 "" | |
612 " | |
613 { | |
614 rtx addr = XEXP (operands[1], 0); | |
615 if (!CONSTANT_ADDRESS_P (addr)) | |
616 XEXP (operands[1], 0) = force_reg (Pmode, addr); | |
617 }") | |
618 | |
619 (define_insn "*call_value" | |
620 [(set (match_operand 0 "register_operand" "=r,r") | |
621 (call (mem:SI (match_operand:SI 1 "call_operand" "r,s")) | |
622 (match_operand 2 "" ""))) | |
623 (clobber (reg:SI RA_REGNUM))] | |
624 "" | |
625 "@ | |
626 call %1 | |
627 calli %1" | |
628 [(set_attr "type" "call,icall")] | |
629 ) | |
630 | |
631 (define_insn "return_internal" | |
632 [(use (match_operand:SI 0 "register_operand" "r")) | |
633 (return)] | |
634 "" | |
635 "b %0" | |
636 [(set_attr "type" "uibranch")] | |
637 ) | |
638 | |
639 (define_insn "return" | |
640 [(return)] | |
641 "lm32_can_use_return ()" | |
642 "ret" | |
643 [(set_attr "type" "uibranch")] | |
644 ) | |
645 | |
646 ;; --------------------------------- | |
647 ;; switch/case statements | |
648 ;; --------------------------------- | |
649 | |
650 (define_expand "tablejump" | |
651 [(set (pc) (match_operand 0 "register_operand" "")) | |
652 (use (label_ref (match_operand 1 "" "")))] | |
653 "" | |
654 " | |
655 { | |
656 rtx target = operands[0]; | |
657 if (flag_pic) | |
658 { | |
659 /* For PIC, the table entry is relative to the start of the table. */ | |
660 rtx label = gen_reg_rtx (SImode); | |
661 target = gen_reg_rtx (SImode); | |
662 emit_move_insn (label, gen_rtx_LABEL_REF (SImode, operands[1])); | |
663 emit_insn (gen_addsi3 (target, operands[0], label)); | |
664 } | |
665 emit_jump_insn (gen_tablejumpsi (target, operands[1])); | |
666 DONE; | |
667 }") | |
668 | |
669 (define_insn "tablejumpsi" | |
670 [(set (pc) (match_operand:SI 0 "register_operand" "r")) | |
671 (use (label_ref (match_operand 1 "" "")))] | |
672 "" | |
673 "b %0" | |
674 [(set_attr "type" "ubranch")] | |
675 ) | |
676 | |
677 ;; --------------------------------- | |
678 ;; arithmetic | |
679 ;; --------------------------------- | |
680 | |
681 (define_insn "addsi3" | |
682 [(set (match_operand:SI 0 "register_operand" "=r,r") | |
683 (plus:SI (match_operand:SI 1 "register_or_zero_operand" "%rJ,rJ") | |
684 (match_operand:SI 2 "register_or_K_operand" "r,K")))] | |
685 "" | |
686 "@ | |
687 add %0, %z1, %2 | |
688 addi %0, %z1, %2" | |
689 [(set_attr "type" "arith")] | |
690 ) | |
691 | |
692 (define_insn "subsi3" | |
693 [(set (match_operand:SI 0 "register_operand" "=r") | |
694 (minus:SI (match_operand:SI 1 "register_or_zero_operand" "rJ") | |
695 (match_operand:SI 2 "register_or_zero_operand" "rJ")))] | |
696 "" | |
697 "sub %0, %z1, %z2" | |
698 [(set_attr "type" "arith")] | |
699 ) | |
700 | |
701 (define_insn "mulsi3" | |
702 [(set (match_operand:SI 0 "register_operand" "=r,r") | |
703 (mult:SI (match_operand:SI 1 "register_or_zero_operand" "%rJ,rJ") | |
704 (match_operand:SI 2 "register_or_K_operand" "r,K")))] | |
705 "TARGET_MULTIPLY_ENABLED" | |
706 "@ | |
707 mul %0, %z1, %2 | |
708 muli %0, %z1, %2" | |
709 [(set_attr "type" "multiply")] | |
710 ) | |
711 | |
712 (define_insn "udivsi3" | |
713 [(set (match_operand:SI 0 "register_operand" "=r") | |
714 (udiv:SI (match_operand:SI 1 "register_or_zero_operand" "rJ") | |
715 (match_operand:SI 2 "register_operand" "r")))] | |
716 "TARGET_DIVIDE_ENABLED" | |
717 "divu %0, %z1, %2" | |
718 [(set_attr "type" "divide")] | |
719 ) | |
720 | |
721 (define_insn "umodsi3" | |
722 [(set (match_operand:SI 0 "register_operand" "=r") | |
723 (umod:SI (match_operand:SI 1 "register_or_zero_operand" "rJ") | |
724 (match_operand:SI 2 "register_operand" "r")))] | |
725 "TARGET_DIVIDE_ENABLED" | |
726 "modu %0, %z1, %2" | |
727 [(set_attr "type" "divide")] | |
728 ) | |
729 | |
730 ;; --------------------------------- | |
731 ;; negation and inversion | |
732 ;; --------------------------------- | |
733 | |
734 (define_insn "negsi2" | |
735 [(set (match_operand:SI 0 "register_operand" "=r") | |
736 (neg:SI (match_operand:SI 1 "register_or_zero_operand" "rJ")))] | |
737 "" | |
738 "sub %0, r0, %z1" | |
739 [(set_attr "type" "arith")] | |
740 ) | |
741 | |
742 (define_insn "one_cmplsi2" | |
743 [(set (match_operand:SI 0 "register_operand" "=r") | |
744 (not:SI (match_operand:SI 1 "register_or_zero_operand" "rJ")))] | |
745 "" | |
746 "not %0, %z1" | |
747 [(set_attr "type" "arith")] | |
748 ) | |
749 | |
750 ;; --------------------------------- | |
751 ;; logical | |
752 ;; --------------------------------- | |
753 | |
754 (define_insn "andsi3" | |
755 [(set (match_operand:SI 0 "register_operand" "=r,r") | |
756 (and:SI (match_operand:SI 1 "register_or_zero_operand" "%rJ,rJ") | |
757 (match_operand:SI 2 "register_or_L_operand" "r,L")))] | |
758 "" | |
759 "@ | |
760 and %0, %z1, %2 | |
761 andi %0, %z1, %2" | |
762 [(set_attr "type" "arith")] | |
763 ) | |
764 | |
765 (define_insn "iorsi3" | |
766 [(set (match_operand:SI 0 "register_operand" "=r,r") | |
767 (ior:SI (match_operand:SI 1 "register_or_zero_operand" "%rJ,rJ") | |
768 (match_operand:SI 2 "register_or_L_operand" "r,L")))] | |
769 "" | |
770 "@ | |
771 or %0, %z1, %2 | |
772 ori %0, %z1, %2" | |
773 [(set_attr "type" "arith")] | |
774 ) | |
775 | |
776 (define_insn "xorsi3" | |
777 [(set (match_operand:SI 0 "register_operand" "=r,r") | |
778 (xor:SI (match_operand:SI 1 "register_or_zero_operand" "%rJ,rJ") | |
779 (match_operand:SI 2 "register_or_L_operand" "r,L")))] | |
780 "" | |
781 "@ | |
782 xor %0, %z1, %2 | |
783 xori %0, %z1, %2" | |
784 [(set_attr "type" "arith")] | |
785 ) | |
786 | |
787 (define_insn "*norsi3" | |
788 [(set (match_operand:SI 0 "register_operand" "=r,r") | |
789 (not:SI (ior:SI (match_operand:SI 1 "register_or_zero_operand" "%rJ,rJ") | |
790 (match_operand:SI 2 "register_or_L_operand" "r,L"))))] | |
791 "" | |
792 "@ | |
793 nor %0, %z1, %2 | |
794 nori %0, %z1, %2" | |
795 [(set_attr "type" "arith")] | |
796 ) | |
797 | |
798 (define_insn "*xnorsi3" | |
799 [(set (match_operand:SI 0 "register_operand" "=r,r") | |
800 (not:SI (xor:SI (match_operand:SI 1 "register_or_zero_operand" "%rJ,rJ") | |
801 (match_operand:SI 2 "register_or_L_operand" "r,L"))))] | |
802 "" | |
803 "@ | |
804 xnor %0, %z1, %2 | |
805 xnori %0, %z1, %2" | |
806 [(set_attr "type" "arith")] | |
807 ) | |
808 | |
809 ;; --------------------------------- | |
810 ;; shifts | |
811 ;; --------------------------------- | |
812 | |
813 (define_expand "ashlsi3" | |
814 [(set (match_operand:SI 0 "register_operand" "") | |
815 (ashift:SI (match_operand:SI 1 "register_or_zero_operand" "") | |
816 (match_operand:SI 2 "register_or_L_operand" "")))] | |
817 "" | |
818 { | |
819 if (!TARGET_BARREL_SHIFT_ENABLED) | |
820 { | |
821 if (!optimize_size | |
822 && satisfies_constraint_L (operands[2]) | |
823 && INTVAL (operands[2]) <= 8) | |
824 { | |
825 int i; | |
826 int shifts = INTVAL (operands[2]); | |
827 rtx one = GEN_INT (1); | |
828 | |
829 if (shifts == 0) | |
830 emit_move_insn (operands[0], operands[1]); | |
831 else | |
832 emit_insn (gen_addsi3 (operands[0], operands[1], operands[1])); | |
833 for (i = 1; i < shifts; i++) | |
834 emit_insn (gen_addsi3 (operands[0], operands[0], operands[0])); | |
835 DONE; | |
836 } | |
837 else | |
838 FAIL; | |
839 } | |
840 }) | |
841 | |
842 (define_insn "*ashlsi3" | |
843 [(set (match_operand:SI 0 "register_operand" "=r,r") | |
844 (ashift:SI (match_operand:SI 1 "register_or_zero_operand" "rJ,rJ") | |
845 (match_operand:SI 2 "register_or_L_operand" "r,L")))] | |
846 "TARGET_BARREL_SHIFT_ENABLED" | |
847 "@ | |
848 sl %0, %z1, %2 | |
849 sli %0, %z1, %2" | |
850 [(set_attr "type" "shift")] | |
851 ) | |
852 | |
853 (define_expand "ashrsi3" | |
854 [(set (match_operand:SI 0 "register_operand" "") | |
855 (ashiftrt:SI (match_operand:SI 1 "register_or_zero_operand" "") | |
856 (match_operand:SI 2 "register_or_L_operand" "")))] | |
857 "" | |
858 { | |
859 if (!TARGET_BARREL_SHIFT_ENABLED) | |
860 { | |
861 if (!optimize_size | |
862 && satisfies_constraint_L (operands[2]) | |
863 && INTVAL (operands[2]) <= 8) | |
864 { | |
865 int i; | |
866 int shifts = INTVAL (operands[2]); | |
867 rtx one = GEN_INT (1); | |
868 | |
869 if (shifts == 0) | |
870 emit_move_insn (operands[0], operands[1]); | |
871 else | |
872 emit_insn (gen_ashrsi3_1bit (operands[0], operands[1], one)); | |
873 for (i = 1; i < shifts; i++) | |
874 emit_insn (gen_ashrsi3_1bit (operands[0], operands[0], one)); | |
875 DONE; | |
876 } | |
877 else | |
878 FAIL; | |
879 } | |
880 }) | |
881 | |
882 (define_insn "*ashrsi3" | |
883 [(set (match_operand:SI 0 "register_operand" "=r,r") | |
884 (ashiftrt:SI (match_operand:SI 1 "register_or_zero_operand" "rJ,rJ") | |
885 (match_operand:SI 2 "register_or_L_operand" "r,L")))] | |
886 "TARGET_BARREL_SHIFT_ENABLED" | |
887 "@ | |
888 sr %0, %z1, %2 | |
889 sri %0, %z1, %2" | |
890 [(set_attr "type" "shift")] | |
891 ) | |
892 | |
893 (define_insn "ashrsi3_1bit" | |
894 [(set (match_operand:SI 0 "register_operand" "=r") | |
895 (ashiftrt:SI (match_operand:SI 1 "register_or_zero_operand" "rJ") | |
896 (match_operand:SI 2 "constant_M_operand" "M")))] | |
897 "!TARGET_BARREL_SHIFT_ENABLED" | |
898 "sri %0, %z1, %2" | |
899 [(set_attr "type" "shift")] | |
900 ) | |
901 | |
902 (define_expand "lshrsi3" | |
903 [(set (match_operand:SI 0 "register_operand" "") | |
904 (lshiftrt:SI (match_operand:SI 1 "register_or_zero_operand" "") | |
905 (match_operand:SI 2 "register_or_L_operand" "")))] | |
906 "" | |
907 { | |
908 if (!TARGET_BARREL_SHIFT_ENABLED) | |
909 { | |
910 if (!optimize_size | |
911 && satisfies_constraint_L (operands[2]) | |
912 && INTVAL (operands[2]) <= 8) | |
913 { | |
914 int i; | |
915 int shifts = INTVAL (operands[2]); | |
916 rtx one = GEN_INT (1); | |
917 | |
918 if (shifts == 0) | |
919 emit_move_insn (operands[0], operands[1]); | |
920 else | |
921 emit_insn (gen_lshrsi3_1bit (operands[0], operands[1], one)); | |
922 for (i = 1; i < shifts; i++) | |
923 emit_insn (gen_lshrsi3_1bit (operands[0], operands[0], one)); | |
924 DONE; | |
925 } | |
926 else | |
927 FAIL; | |
928 } | |
929 }) | |
930 | |
931 (define_insn "*lshrsi3" | |
932 [(set (match_operand:SI 0 "register_operand" "=r,r") | |
933 (lshiftrt:SI (match_operand:SI 1 "register_or_zero_operand" "rJ,rJ") | |
934 (match_operand:SI 2 "register_or_L_operand" "r,L")))] | |
935 "TARGET_BARREL_SHIFT_ENABLED" | |
936 "@ | |
937 sru %0, %z1, %2 | |
938 srui %0, %z1, %2" | |
939 [(set_attr "type" "shift")] | |
940 ) | |
941 | |
942 (define_insn "lshrsi3_1bit" | |
943 [(set (match_operand:SI 0 "register_operand" "=r") | |
944 (lshiftrt:SI (match_operand:SI 1 "register_or_zero_operand" "rJ") | |
945 (match_operand:SI 2 "constant_M_operand" "M")))] | |
946 "!TARGET_BARREL_SHIFT_ENABLED" | |
947 "srui %0, %z1, %2" | |
948 [(set_attr "type" "shift")] | |
949 ) | |
950 | |
951 ;; --------------------------------- | |
952 ;; function entry / exit | |
953 ;; --------------------------------- | |
954 | |
955 (define_expand "prologue" | |
956 [(const_int 1)] | |
957 "" | |
958 " | |
959 { | |
960 lm32_expand_prologue (); | |
961 DONE; | |
962 }") | |
963 | |
964 (define_expand "epilogue" | |
965 [(return)] | |
966 "" | |
967 " | |
968 { | |
969 lm32_expand_epilogue (); | |
970 DONE; | |
971 }") | |
972 | |
973 ;; --------------------------------- | |
974 ;; nop | |
975 ;; --------------------------------- | |
976 | |
977 (define_insn "nop" | |
978 [(const_int 0)] | |
979 "" | |
980 "nop" | |
981 [(set_attr "type" "arith")] | |
982 ) | |
983 | |
984 ;; --------------------------------- | |
985 ;; blockage | |
986 ;; --------------------------------- | |
987 | |
988 ;; used to stop the scheduler from | |
989 ;; scheduling code across certain boundaries | |
990 | |
991 (define_insn "blockage" | |
992 [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)] | |
993 "" | |
994 "" | |
995 [(set_attr "length" "0")] | |
996 ) |