09e47daf1d1e67f5cf1516cd9f9e4941a7adf242
[gcc.git] / gcc / config / arc / arc.md
1 ;; Machine description of the Argonaut ARC cpu for GNU C compiler
2 ;; Copyright (C) 1994, 1997, 1998, 1999, 2000, 2004, 2005, 2007, 2008
3 ;; Free Software Foundation, Inc.
4
5 ;; This file is part of GCC.
6
7 ;; GCC is free software; you can redistribute it and/or modify
8 ;; it under the terms of the GNU General Public License as published by
9 ;; the Free Software Foundation; either version 3, or (at your option)
10 ;; any later version.
11
12 ;; GCC is distributed in the hope that it will be useful,
13 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 ;; GNU General Public License for more details.
16
17 ;; You should have received a copy of the GNU General Public License
18 ;; along with GCC; see the file COPYING3. If not see
19 ;; <http://www.gnu.org/licenses/>.
20
21 ;; See file "rtl.def" for documentation on define_insn, match_*, et. al.
22
23 ;; ??? This is an old port, and is undoubtedly suffering from bit rot.
24 \f
25 ;; Insn type. Used to default other attribute values.
26
27 (define_attr "type"
28 "move,load,store,cmove,unary,binary,compare,shift,mul,uncond_branch,branch,call,call_no_delay_slot,multi,misc"
29 (const_string "binary"))
30
31 ;; Length (in # of insns, long immediate constants counted too).
32 ;; ??? There's a nasty interaction between the conditional execution fsm
33 ;; and insn lengths: insns with shimm values cannot be conditionally executed.
34 (define_attr "length" ""
35 (cond [(eq_attr "type" "load")
36 (if_then_else (match_operand 1 "long_immediate_loadstore_operand" "")
37 (const_int 2) (const_int 1))
38
39 (eq_attr "type" "store")
40 (if_then_else (match_operand 0 "long_immediate_loadstore_operand" "")
41 (const_int 2) (const_int 1))
42
43 (eq_attr "type" "move,unary,compare")
44 (if_then_else (match_operand 1 "long_immediate_operand" "")
45 (const_int 2) (const_int 1))
46
47 (eq_attr "type" "binary,mul")
48 (if_then_else (match_operand 2 "long_immediate_operand" "")
49 (const_int 2) (const_int 1))
50
51 (eq_attr "type" "cmove")
52 (if_then_else (match_operand 2 "register_operand" "")
53 (const_int 1) (const_int 2))
54
55 (eq_attr "type" "multi") (const_int 2)
56 ]
57
58 (const_int 1)))
59
60 ;; The length here is the length of a single asm. Unfortunately it might be
61 ;; 1 or 2 so we must allow for 2. That's ok though. How often will users
62 ;; lament asm's not being put in delay slots?
63 (define_asm_attributes
64 [(set_attr "length" "2")
65 (set_attr "type" "multi")])
66
67 ;; Condition codes: this one is used by final_prescan_insn to speed up
68 ;; conditionalizing instructions. It saves having to scan the rtl to see if
69 ;; it uses or alters the condition codes.
70
71 ;; USE: This insn uses the condition codes (e.g.: a conditional branch).
72 ;; CANUSE: This insn can use the condition codes (for conditional execution).
73 ;; SET: All condition codes are set by this insn.
74 ;; SET_ZN: the Z and N flags are set by this insn.
75 ;; SET_ZNC: the Z, N, and C flags are set by this insn.
76 ;; CLOB: The condition codes are set to unknown values by this insn.
77 ;; NOCOND: This insn can't use and doesn't affect the condition codes.
78
79 (define_attr "cond" "use,canuse,set,set_zn,set_znc,clob,nocond"
80 (cond [(and (eq_attr "type" "unary,binary,move")
81 (eq_attr "length" "1"))
82 (const_string "canuse")
83
84 (eq_attr "type" "compare")
85 (const_string "set")
86
87 (eq_attr "type" "cmove,branch")
88 (const_string "use")
89
90 (eq_attr "type" "multi,misc")
91 (const_string "clob")
92 ]
93
94 (const_string "nocond")))
95 \f
96 ;; Delay slots.
97
98 (define_attr "in_delay_slot" "false,true"
99 (cond [(eq_attr "type" "uncond_branch,branch,call,call_no_delay_slot,multi")
100 (const_string "false")
101 ]
102
103 (if_then_else (eq_attr "length" "1")
104 (const_string "true")
105 (const_string "false"))))
106
107 (define_delay (eq_attr "type" "call")
108 [(eq_attr "in_delay_slot" "true")
109 (eq_attr "in_delay_slot" "true")
110 (eq_attr "in_delay_slot" "true")])
111
112 (define_delay (eq_attr "type" "branch,uncond_branch")
113 [(eq_attr "in_delay_slot" "true")
114 (eq_attr "in_delay_slot" "true")
115 (eq_attr "in_delay_slot" "true")])
116 \f
117 ;; Scheduling description for the ARC
118
119 (define_cpu_unit "branch")
120
121 (define_insn_reservation "any_insn" 1 (eq_attr "type" "!load,compare,branch")
122 "nothing")
123
124 ;; 1) A conditional jump cannot immediately follow the insn setting the flags.
125 ;; This isn't a complete solution as it doesn't come with guarantees. That
126 ;; is done in the branch patterns and in arc_print_operand. This exists to
127 ;; avoid inserting a nop when we can.
128
129 (define_insn_reservation "compare" 1 (eq_attr "type" "compare")
130 "nothing,branch")
131
132 (define_insn_reservation "branch" 1 (eq_attr "type" "branch")
133 "branch")
134
135 ;; 2) References to loaded registers should wait a cycle.
136
137 ;; Memory with load-delay of 1 (i.e., 2 cycle load).
138
139 (define_insn_reservation "memory" 2 (eq_attr "type" "load")
140 "nothing")
141 \f
142 ;; Move instructions.
143
144 (define_expand "movqi"
145 [(set (match_operand:QI 0 "general_operand" "")
146 (match_operand:QI 1 "general_operand" ""))]
147 ""
148 "
149 {
150 /* Everything except mem = const or mem = mem can be done easily. */
151
152 if (GET_CODE (operands[0]) == MEM)
153 operands[1] = force_reg (QImode, operands[1]);
154 }")
155
156 (define_insn "*movqi_insn"
157 [(set (match_operand:QI 0 "move_dest_operand" "=r,r,r,m")
158 (match_operand:QI 1 "move_src_operand" "rI,Ji,m,r"))]
159 ;; ??? Needed?
160 "register_operand (operands[0], QImode)
161 || register_operand (operands[1], QImode)"
162 "@
163 mov%? %0,%1
164 mov%? %0,%1
165 ldb%U1%V1 %0,%1
166 stb%U0%V0 %1,%0"
167 [(set_attr "type" "move,move,load,store")])
168
169 ;; ??? This may never match since there's no cmpqi insn.
170
171 (define_insn "*movqi_set_cc_insn"
172 [(set (reg:CCZN 61) (compare:CCZN
173 (sign_extend:SI (match_operand:QI 1 "move_src_operand" "rIJi"))
174 (const_int 0)))
175 (set (match_operand:QI 0 "move_dest_operand" "=r")
176 (match_dup 1))]
177 ""
178 "mov%?.f %0,%1"
179 [(set_attr "type" "move")
180 (set_attr "cond" "set_zn")])
181
182 (define_expand "movhi"
183 [(set (match_operand:HI 0 "general_operand" "")
184 (match_operand:HI 1 "general_operand" ""))]
185 ""
186 "
187 {
188 /* Everything except mem = const or mem = mem can be done easily. */
189
190 if (GET_CODE (operands[0]) == MEM)
191 operands[1] = force_reg (HImode, operands[1]);
192 }")
193
194 (define_insn "*movhi_insn"
195 [(set (match_operand:HI 0 "move_dest_operand" "=r,r,r,m")
196 (match_operand:HI 1 "move_src_operand" "rI,Ji,m,r"))]
197 "register_operand (operands[0], HImode)
198 || register_operand (operands[1], HImode)"
199 "@
200 mov%? %0,%1
201 mov%? %0,%1
202 ldw%U1%V1 %0,%1
203 stw%U0%V0 %1,%0"
204 [(set_attr "type" "move,move,load,store")])
205
206 ;; ??? Will this ever match?
207
208 (define_insn "*movhi_set_cc_insn"
209 [(set (reg:CCZN 61) (compare:CCZN
210 (sign_extend:SI (match_operand:HI 1 "move_src_operand" "rIJi"))
211 (const_int 0)))
212 (set (match_operand:HI 0 "move_dest_operand" "=r")
213 (match_dup 1))]
214 ;; ??? Needed?
215 "register_operand (operands[0], HImode)
216 || register_operand (operands[1], HImode)"
217 "mov%?.f %0,%1"
218 [(set_attr "type" "move")
219 (set_attr "cond" "set_zn")])
220
221 (define_expand "movsi"
222 [(set (match_operand:SI 0 "general_operand" "")
223 (match_operand:SI 1 "general_operand" ""))]
224 ""
225 "
226 {
227 /* Everything except mem = const or mem = mem can be done easily. */
228
229 if (GET_CODE (operands[0]) == MEM)
230 operands[1] = force_reg (SImode, operands[1]);
231 }")
232
233 (define_insn "*movsi_insn"
234 [(set (match_operand:SI 0 "move_dest_operand" "=r,r,r,m")
235 (match_operand:SI 1 "move_src_operand" "rI,GJi,m,r"))]
236 "register_operand (operands[0], SImode)
237 || register_operand (operands[1], SImode)"
238 "@
239 mov%? %0,%1
240 mov%? %0,%S1
241 ld%U1%V1 %0,%1
242 st%U0%V0 %1,%0"
243 [(set_attr "type" "move,move,load,store")])
244
245 (define_insn "*movsi_set_cc_insn"
246 [(set (reg:CCZN 61) (compare:CCZN
247 (match_operand:SI 1 "move_src_operand" "rIJi")
248 (const_int 0)))
249 (set (match_operand:SI 0 "move_dest_operand" "=r")
250 (match_dup 1))]
251 "register_operand (operands[0], SImode)
252 || register_operand (operands[1], SImode)"
253 "mov%?.f %0,%S1"
254 [(set_attr "type" "move")
255 (set_attr "cond" "set_zn")])
256
257 (define_expand "movdi"
258 [(set (match_operand:DI 0 "general_operand" "")
259 (match_operand:DI 1 "general_operand" ""))]
260 ""
261 "
262 {
263 /* Everything except mem = const or mem = mem can be done easily. */
264
265 if (GET_CODE (operands[0]) == MEM)
266 operands[1] = force_reg (DImode, operands[1]);
267 }")
268
269 (define_insn "*movdi_insn"
270 [(set (match_operand:DI 0 "move_dest_operand" "=r,r,r,m")
271 (match_operand:DI 1 "move_double_src_operand" "r,HK,m,r"))]
272 "register_operand (operands[0], DImode)
273 || register_operand (operands[1], DImode)"
274 "*
275 {
276 switch (which_alternative)
277 {
278 case 0 :
279 /* We normally copy the low-numbered register first. However, if
280 the first register operand 0 is the same as the second register of
281 operand 1, we must copy in the opposite order. */
282 if (REGNO (operands[0]) == REGNO (operands[1]) + 1)
283 return \"mov %R0,%R1\;mov %0,%1\";
284 else
285 return \"mov %0,%1\;mov %R0,%R1\";
286 case 1 :
287 return \"mov %0,%L1\;mov %R0,%H1\";
288 case 2 :
289 /* If the low-address word is used in the address, we must load it
290 last. Otherwise, load it first. Note that we cannot have
291 auto-increment in that case since the address register is known to be
292 dead. */
293 if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1,
294 operands [1], 0))
295 return \"ld%V1 %R0,%R1\;ld%V1 %0,%1\";
296 else
297 return \"ld%V1 %0,%1\;ld%V1 %R0,%R1\";
298 case 3 :
299 return \"st%V0 %1,%0\;st%V0 %R1,%R0\";
300 default:
301 gcc_unreachable ();
302 }
303 }"
304 [(set_attr "type" "move,move,load,store")
305 ;; ??? The ld/st values could be 4 if it's [reg,bignum].
306 (set_attr "length" "2,4,2,2")])
307
308 ;(define_expand "movdi"
309 ; [(set (match_operand:DI 0 "general_operand" "")
310 ; (match_operand:DI 1 "general_operand" ""))]
311 ; ""
312 ; "
313 ;{
314 ; /* Flow doesn't understand that this is effectively a DFmode move.
315 ; It doesn't know that all of `operands[0]' is set. */
316 ; emit_clobber (operands[0]);
317 ;
318 ; /* Emit insns that movsi_insn can handle. */
319 ; emit_insn (gen_movsi (operand_subword (operands[0], 0, 0, DImode),
320 ; operand_subword (operands[1], 0, 0, DImode)));
321 ; emit_insn (gen_movsi (operand_subword (operands[0], 1, 0, DImode),
322 ; operand_subword (operands[1], 1, 0, DImode)));
323 ; DONE;
324 ;}")
325 \f
326 ;; Floating point move insns.
327
328 (define_expand "movsf"
329 [(set (match_operand:SF 0 "general_operand" "")
330 (match_operand:SF 1 "general_operand" ""))]
331 ""
332 "
333 {
334 /* Everything except mem = const or mem = mem can be done easily. */
335 if (GET_CODE (operands[0]) == MEM)
336 operands[1] = force_reg (SFmode, operands[1]);
337 }")
338
339 (define_insn "*movsf_insn"
340 [(set (match_operand:SF 0 "move_dest_operand" "=r,r,r,m")
341 (match_operand:SF 1 "move_src_operand" "r,E,m,r"))]
342 "register_operand (operands[0], SFmode)
343 || register_operand (operands[1], SFmode)"
344 "@
345 mov%? %0,%1
346 mov%? %0,%1 ; %A1
347 ld%U1%V1 %0,%1
348 st%U0%V0 %1,%0"
349 [(set_attr "type" "move,move,load,store")])
350
351 (define_expand "movdf"
352 [(set (match_operand:DF 0 "general_operand" "")
353 (match_operand:DF 1 "general_operand" ""))]
354 ""
355 "
356 {
357 /* Everything except mem = const or mem = mem can be done easily. */
358 if (GET_CODE (operands[0]) == MEM)
359 operands[1] = force_reg (DFmode, operands[1]);
360 }")
361
362 (define_insn "*movdf_insn"
363 [(set (match_operand:DF 0 "move_dest_operand" "=r,r,r,m")
364 (match_operand:DF 1 "move_double_src_operand" "r,E,m,r"))]
365 "register_operand (operands[0], DFmode)
366 || register_operand (operands[1], DFmode)"
367 "*
368 {
369 switch (which_alternative)
370 {
371 case 0 :
372 /* We normally copy the low-numbered register first. However, if
373 the first register operand 0 is the same as the second register of
374 operand 1, we must copy in the opposite order. */
375 if (REGNO (operands[0]) == REGNO (operands[1]) + 1)
376 return \"mov %R0,%R1\;mov %0,%1\";
377 else
378 return \"mov %0,%1\;mov %R0,%R1\";
379 case 1 :
380 return \"mov %0,%L1\;mov %R0,%H1 ; %A1\";
381 case 2 :
382 /* If the low-address word is used in the address, we must load it
383 last. Otherwise, load it first. Note that we cannot have
384 auto-increment in that case since the address register is known to be
385 dead. */
386 if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1,
387 operands [1], 0))
388 return \"ld%V1 %R0,%R1\;ld%V1 %0,%1\";
389 else
390 return \"ld%V1 %0,%1\;ld%V1 %R0,%R1\";
391 case 3 :
392 return \"st%V0 %1,%0\;st%V0 %R1,%R0\";
393 default:
394 gcc_unreachable ();
395 }
396 }"
397 [(set_attr "type" "move,move,load,store")
398 ;; ??? The ld/st values could be 4 if it's [reg,bignum].
399 (set_attr "length" "2,4,2,2")])
400
401 ;(define_expand "movdf"
402 ; [(set (match_operand:DF 0 "general_operand" "")
403 ; (match_operand:DF 1 "general_operand" ""))]
404 ; ""
405 ; "
406 ;{
407 ; /* Flow doesn't understand that this is effectively a DFmode move.
408 ; It doesn't know that all of `operands[0]' is set. */
409 ; emit_clobber (operands[0]);
410 ;
411 ; /* Emit insns that movsi_insn can handle. */
412 ; emit_insn (gen_movsi (operand_subword (operands[0], 0, 0, DFmode),
413 ; operand_subword (operands[1], 0, 0, DFmode)));
414 ; emit_insn (gen_movsi (operand_subword (operands[0], 1, 0, DFmode),
415 ; operand_subword (operands[1], 1, 0, DFmode)));
416 ; DONE;
417 ;}")
418 \f
419 ;; Load/Store with update instructions.
420 ;;
421 ;; Some of these we can get by using pre-decrement or pre-increment, but the
422 ;; hardware can also do cases where the increment is not the size of the
423 ;; object.
424 ;;
425 ;; In all these cases, we use operands 0 and 1 for the register being
426 ;; incremented because those are the operands that local-alloc will
427 ;; tie and these are the pair most likely to be tieable (and the ones
428 ;; that will benefit the most).
429 ;;
430 ;; We use match_operator here because we need to know whether the memory
431 ;; object is volatile or not.
432
433 (define_insn "*loadqi_update"
434 [(set (match_operand:QI 3 "register_operand" "=r,r")
435 (match_operator:QI 4 "load_update_operand"
436 [(match_operand:SI 1 "register_operand" "0,0")
437 (match_operand:SI 2 "nonmemory_operand" "rI,J")]))
438 (set (match_operand:SI 0 "register_operand" "=r,r")
439 (plus:SI (match_dup 1) (match_dup 2)))]
440 ""
441 "ldb.a%V4 %3,[%0,%2]"
442 [(set_attr "type" "load,load")
443 (set_attr "length" "1,2")])
444
445 (define_insn "*load_zeroextendqisi_update"
446 [(set (match_operand:SI 3 "register_operand" "=r,r")
447 (zero_extend:SI (match_operator:QI 4 "load_update_operand"
448 [(match_operand:SI 1 "register_operand" "0,0")
449 (match_operand:SI 2 "nonmemory_operand" "rI,J")])))
450 (set (match_operand:SI 0 "register_operand" "=r,r")
451 (plus:SI (match_dup 1) (match_dup 2)))]
452 ""
453 "ldb.a%V4 %3,[%0,%2]"
454 [(set_attr "type" "load,load")
455 (set_attr "length" "1,2")])
456
457 (define_insn "*load_signextendqisi_update"
458 [(set (match_operand:SI 3 "register_operand" "=r,r")
459 (sign_extend:SI (match_operator:QI 4 "load_update_operand"
460 [(match_operand:SI 1 "register_operand" "0,0")
461 (match_operand:SI 2 "nonmemory_operand" "rI,J")])))
462 (set (match_operand:SI 0 "register_operand" "=r,r")
463 (plus:SI (match_dup 1) (match_dup 2)))]
464 ""
465 "ldb.x.a%V4 %3,[%0,%2]"
466 [(set_attr "type" "load,load")
467 (set_attr "length" "1,2")])
468
469 (define_insn "*storeqi_update"
470 [(set (match_operator:QI 4 "store_update_operand"
471 [(match_operand:SI 1 "register_operand" "0")
472 (match_operand:SI 2 "short_immediate_operand" "I")])
473 (match_operand:QI 3 "register_operand" "r"))
474 (set (match_operand:SI 0 "register_operand" "=r")
475 (plus:SI (match_dup 1) (match_dup 2)))]
476 ""
477 "stb.a%V4 %3,[%0,%2]"
478 [(set_attr "type" "store")
479 (set_attr "length" "1")])
480
481 (define_insn "*loadhi_update"
482 [(set (match_operand:HI 3 "register_operand" "=r,r")
483 (match_operator:HI 4 "load_update_operand"
484 [(match_operand:SI 1 "register_operand" "0,0")
485 (match_operand:SI 2 "nonmemory_operand" "rI,J")]))
486 (set (match_operand:SI 0 "register_operand" "=r,r")
487 (plus:SI (match_dup 1) (match_dup 2)))]
488 ""
489 "ldw.a%V4 %3,[%0,%2]"
490 [(set_attr "type" "load,load")
491 (set_attr "length" "1,2")])
492
493 (define_insn "*load_zeroextendhisi_update"
494 [(set (match_operand:SI 3 "register_operand" "=r,r")
495 (zero_extend:SI (match_operator:HI 4 "load_update_operand"
496 [(match_operand:SI 1 "register_operand" "0,0")
497 (match_operand:SI 2 "nonmemory_operand" "rI,J")])))
498 (set (match_operand:SI 0 "register_operand" "=r,r")
499 (plus:SI (match_dup 1) (match_dup 2)))]
500 ""
501 "ldw.a%V4 %3,[%0,%2]"
502 [(set_attr "type" "load,load")
503 (set_attr "length" "1,2")])
504
505 (define_insn "*load_signextendhisi_update"
506 [(set (match_operand:SI 3 "register_operand" "=r,r")
507 (sign_extend:SI (match_operator:HI 4 "load_update_operand"
508 [(match_operand:SI 1 "register_operand" "0,0")
509 (match_operand:SI 2 "nonmemory_operand" "rI,J")])))
510 (set (match_operand:SI 0 "register_operand" "=r,r")
511 (plus:SI (match_dup 1) (match_dup 2)))]
512 ""
513 "ldw.x.a%V4 %3,[%0,%2]"
514 [(set_attr "type" "load,load")
515 (set_attr "length" "1,2")])
516
517 (define_insn "*storehi_update"
518 [(set (match_operator:HI 4 "store_update_operand"
519 [(match_operand:SI 1 "register_operand" "0")
520 (match_operand:SI 2 "short_immediate_operand" "I")])
521 (match_operand:HI 3 "register_operand" "r"))
522 (set (match_operand:SI 0 "register_operand" "=r")
523 (plus:SI (match_dup 1) (match_dup 2)))]
524 ""
525 "stw.a%V4 %3,[%0,%2]"
526 [(set_attr "type" "store")
527 (set_attr "length" "1")])
528
529 (define_insn "*loadsi_update"
530 [(set (match_operand:SI 3 "register_operand" "=r,r")
531 (match_operator:SI 4 "load_update_operand"
532 [(match_operand:SI 1 "register_operand" "0,0")
533 (match_operand:SI 2 "nonmemory_operand" "rI,J")]))
534 (set (match_operand:SI 0 "register_operand" "=r,r")
535 (plus:SI (match_dup 1) (match_dup 2)))]
536 ""
537 "ld.a%V4 %3,[%0,%2]"
538 [(set_attr "type" "load,load")
539 (set_attr "length" "1,2")])
540
541 (define_insn "*storesi_update"
542 [(set (match_operator:SI 4 "store_update_operand"
543 [(match_operand:SI 1 "register_operand" "0")
544 (match_operand:SI 2 "short_immediate_operand" "I")])
545 (match_operand:SI 3 "register_operand" "r"))
546 (set (match_operand:SI 0 "register_operand" "=r")
547 (plus:SI (match_dup 1) (match_dup 2)))]
548 ""
549 "st.a%V4 %3,[%0,%2]"
550 [(set_attr "type" "store")
551 (set_attr "length" "1")])
552
553 (define_insn "*loadsf_update"
554 [(set (match_operand:SF 3 "register_operand" "=r,r")
555 (match_operator:SF 4 "load_update_operand"
556 [(match_operand:SI 1 "register_operand" "0,0")
557 (match_operand:SI 2 "nonmemory_operand" "rI,J")]))
558 (set (match_operand:SI 0 "register_operand" "=r,r")
559 (plus:SI (match_dup 1) (match_dup 2)))]
560 ""
561 "ld.a%V4 %3,[%0,%2]"
562 [(set_attr "type" "load,load")
563 (set_attr "length" "1,2")])
564
565 (define_insn "*storesf_update"
566 [(set (match_operator:SF 4 "store_update_operand"
567 [(match_operand:SI 1 "register_operand" "0")
568 (match_operand:SI 2 "short_immediate_operand" "I")])
569 (match_operand:SF 3 "register_operand" "r"))
570 (set (match_operand:SI 0 "register_operand" "=r")
571 (plus:SI (match_dup 1) (match_dup 2)))]
572 ""
573 "st.a%V4 %3,[%0,%2]"
574 [(set_attr "type" "store")
575 (set_attr "length" "1")])
576 \f
577 ;; Conditional move instructions.
578
579 (define_expand "movsicc"
580 [(set (match_operand:SI 0 "register_operand" "")
581 (if_then_else:SI (match_operand 1 "comparison_operator" "")
582 (match_operand:SI 2 "nonmemory_operand" "")
583 (match_operand:SI 3 "register_operand" "")))]
584 ""
585 "
586 {
587 enum rtx_code code = GET_CODE (operands[1]);
588 rtx cc_reg = gen_compare_reg (code, XEXP (operands[1], 0),
589 XEXP (operands[1], 1));
590 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, cc_reg, const0_rtx);
591 }")
592
593 (define_expand "movsfcc"
594 [(set (match_operand:SF 0 "register_operand" "")
595 (if_then_else:SF (match_operand 1 "comparison_operator" "")
596 (match_operand:SF 2 "nonmemory_operand" "")
597 (match_operand:SF 3 "register_operand" "")))]
598 ""
599 "
600 {
601 enum rtx_code code = GET_CODE (operands[1]);
602 rtx cc_reg = gen_compare_reg (code, XEXP (operands[1], 0),
603 XEXP (operands[1], 1));
604 operands[1] = gen_rtx_fmt_ee (code, VOIDmode, cc_reg, const0_rtx);
605 }")
606
607 (define_insn "*movsicc_insn"
608 [(set (match_operand:SI 0 "register_operand" "=r")
609 (if_then_else:SI (match_operand 1 "comparison_operator" "")
610 (match_operand:SI 2 "nonmemory_operand" "rJi")
611 (match_operand:SI 3 "register_operand" "0")))]
612 ""
613 "mov.%d1 %0,%S2"
614 [(set_attr "type" "cmove")])
615
616 (define_insn "*movsfcc_insn"
617 [(set (match_operand:SF 0 "register_operand" "=r,r")
618 (if_then_else:SF (match_operand 1 "comparison_operator" "")
619 (match_operand:SF 2 "nonmemory_operand" "r,E")
620 (match_operand:SF 3 "register_operand" "0,0")))]
621 ""
622 "@
623 mov.%d1 %0,%2
624 mov.%d1 %0,%2 ; %A2"
625 [(set_attr "type" "cmove,cmove")])
626
627 \f
628 ;; Zero extension instructions.
629 ;; ??? We don't support volatile memrefs here, but I'm not sure why.
630
631 (define_insn "zero_extendqihi2"
632 [(set (match_operand:HI 0 "register_operand" "=r,r")
633 (zero_extend:HI (match_operand:QI 1 "nonvol_nonimm_operand" "r,m")))]
634 ""
635 "@
636 extb%? %0,%1
637 ldb%U1 %0,%1"
638 [(set_attr "type" "unary,load")])
639
640 (define_insn "*zero_extendqihi2_set_cc_insn"
641 [(set (reg:CCZN 61) (compare:CCZN
642 (zero_extend:SI (match_operand:QI 1 "register_operand" "r"))
643 (const_int 0)))
644 (set (match_operand:HI 0 "register_operand" "=r")
645 (zero_extend:HI (match_dup 1)))]
646 ""
647 "extb%?.f %0,%1"
648 [(set_attr "type" "unary")
649 (set_attr "cond" "set_zn")])
650
651 (define_insn "zero_extendqisi2"
652 [(set (match_operand:SI 0 "register_operand" "=r,r")
653 (zero_extend:SI (match_operand:QI 1 "nonvol_nonimm_operand" "r,m")))]
654 ""
655 "@
656 extb%? %0,%1
657 ldb%U1 %0,%1"
658 [(set_attr "type" "unary,load")])
659
660 (define_insn "*zero_extendqisi2_set_cc_insn"
661 [(set (reg:CCZN 61) (compare:CCZN
662 (zero_extend:SI (match_operand:QI 1 "register_operand" "r"))
663 (const_int 0)))
664 (set (match_operand:SI 0 "register_operand" "=r")
665 (zero_extend:SI (match_dup 1)))]
666 ""
667 "extb%?.f %0,%1"
668 [(set_attr "type" "unary")
669 (set_attr "cond" "set_zn")])
670
671 (define_insn "zero_extendhisi2"
672 [(set (match_operand:SI 0 "register_operand" "=r,r")
673 (zero_extend:SI (match_operand:HI 1 "nonvol_nonimm_operand" "r,m")))]
674 ""
675 "@
676 extw%? %0,%1
677 ldw%U1 %0,%1"
678 [(set_attr "type" "unary,load")])
679
680 (define_insn "*zero_extendhisi2_set_cc_insn"
681 [(set (reg:CCZN 61) (compare:CCZN
682 (zero_extend:SI (match_operand:HI 1 "register_operand" "r"))
683 (const_int 0)))
684 (set (match_operand:SI 0 "register_operand" "=r")
685 (zero_extend:SI (match_dup 1)))]
686 ""
687 "extw%?.f %0,%1"
688 [(set_attr "type" "unary")
689 (set_attr "cond" "set_zn")])
690 \f
691 ;; Sign extension instructions.
692
693 (define_insn "extendqihi2"
694 [(set (match_operand:HI 0 "register_operand" "=r,r")
695 (sign_extend:HI (match_operand:QI 1 "nonvol_nonimm_operand" "r,m")))]
696 ""
697 "@
698 sexb%? %0,%1
699 ldb.x%U1 %0,%1"
700 [(set_attr "type" "unary,load")])
701
702 (define_insn "*extendqihi2_set_cc_insn"
703 [(set (reg:CCZN 61) (compare:CCZN
704 (sign_extend:SI (match_operand:QI 1 "register_operand" "r"))
705 (const_int 0)))
706 (set (match_operand:HI 0 "register_operand" "=r")
707 (sign_extend:HI (match_dup 1)))]
708 ""
709 "sexb%?.f %0,%1"
710 [(set_attr "type" "unary")
711 (set_attr "cond" "set_zn")])
712
713 (define_insn "extendqisi2"
714 [(set (match_operand:SI 0 "register_operand" "=r,r")
715 (sign_extend:SI (match_operand:QI 1 "nonvol_nonimm_operand" "r,m")))]
716 ""
717 "@
718 sexb%? %0,%1
719 ldb.x%U1 %0,%1"
720 [(set_attr "type" "unary,load")])
721
722 (define_insn "*extendqisi2_set_cc_insn"
723 [(set (reg:CCZN 61) (compare:CCZN
724 (sign_extend:SI (match_operand:QI 1 "register_operand" "r"))
725 (const_int 0)))
726 (set (match_operand:SI 0 "register_operand" "=r")
727 (sign_extend:SI (match_dup 1)))]
728 ""
729 "sexb%?.f %0,%1"
730 [(set_attr "type" "unary")
731 (set_attr "cond" "set_zn")])
732
733 (define_insn "extendhisi2"
734 [(set (match_operand:SI 0 "register_operand" "=r,r")
735 (sign_extend:SI (match_operand:HI 1 "nonvol_nonimm_operand" "r,m")))]
736 ""
737 "@
738 sexw%? %0,%1
739 ldw.x%U1 %0,%1"
740 [(set_attr "type" "unary,load")])
741
742 (define_insn "*extendhisi2_set_cc_insn"
743 [(set (reg:CCZN 61) (compare:CCZN
744 (sign_extend:SI (match_operand:HI 1 "register_operand" "r"))
745 (const_int 0)))
746 (set (match_operand:SI 0 "register_operand" "=r")
747 (sign_extend:SI (match_dup 1)))]
748 ""
749 "sexw%?.f %0,%1"
750 [(set_attr "type" "unary")
751 (set_attr "cond" "set_zn")])
752 \f
753 ;; Arithmetic instructions.
754
755 (define_insn "addsi3"
756 [(set (match_operand:SI 0 "register_operand" "=r")
757 (plus:SI (match_operand:SI 1 "register_operand" "%r")
758 (match_operand:SI 2 "nonmemory_operand" "rIJ")))]
759 ""
760 "add%? %0,%1,%2")
761
762 (define_insn "*addsi3_set_cc_insn"
763 [(set (reg:CC 61) (compare:CC
764 (plus:SI (match_operand:SI 1 "register_operand" "%r")
765 (match_operand:SI 2 "nonmemory_operand" "rIJ"))
766 (const_int 0)))
767 (set (match_operand:SI 0 "register_operand" "=r")
768 (plus:SI (match_dup 1)
769 (match_dup 2)))]
770 ""
771 "add%?.f %0,%1,%2"
772 [(set_attr "cond" "set")])
773
774 (define_insn "adddi3"
775 [(set (match_operand:DI 0 "register_operand" "=r")
776 (plus:DI (match_operand:DI 1 "nonmemory_operand" "%r")
777 (match_operand:DI 2 "nonmemory_operand" "ri")))
778 (clobber (reg:CC 61))]
779 ""
780 "*
781 {
782 rtx op2 = operands[2];
783
784 if (GET_CODE (op2) == CONST_INT)
785 {
786 int sign = INTVAL (op2);
787 if (sign < 0)
788 return \"add.f %L0,%L1,%2\;adc %H0,%H1,-1\";
789 else
790 return \"add.f %L0,%L1,%2\;adc %H0,%H1,0\";
791 }
792 else
793 return \"add.f %L0,%L1,%L2\;adc %H0,%H1,%H2\";
794 }"
795 [(set_attr "length" "2")])
796
797 (define_insn "subsi3"
798 [(set (match_operand:SI 0 "register_operand" "=r")
799 (minus:SI (match_operand:SI 1 "register_operand" "r")
800 (match_operand:SI 2 "nonmemory_operand" "rIJ")))]
801 ""
802 "sub%? %0,%1,%2")
803
804 (define_insn "*subsi3_set_cc_insn"
805 [(set (reg:CC 61) (compare:CC
806 (minus:SI (match_operand:SI 1 "register_operand" "%r")
807 (match_operand:SI 2 "nonmemory_operand" "rIJ"))
808 (const_int 0)))
809 (set (match_operand:SI 0 "register_operand" "=r")
810 (minus:SI (match_dup 1)
811 (match_dup 2)))]
812 ""
813 "sub%?.f %0,%1,%2"
814 [(set_attr "cond" "set")])
815
816 (define_insn "subdi3"
817 [(set (match_operand:DI 0 "register_operand" "=r")
818 (minus:DI (match_operand:DI 1 "nonmemory_operand" "r")
819 (match_operand:DI 2 "nonmemory_operand" "ri")))
820 (clobber (reg:CC 61))]
821 ""
822 "*
823 {
824 rtx op2 = operands[2];
825
826 if (GET_CODE (op2) == CONST_INT)
827 {
828 int sign = INTVAL (op2);
829 if (sign < 0)
830 return \"sub.f %L0,%L1,%2\;sbc %H0,%H1,-1\";
831 else
832 return \"sub.f %L0,%L1,%2\;sbc %H0,%H1,0\";
833 }
834 else
835 return \"sub.f %L0,%L1,%L2\;sbc %H0,%H1,%H2\";
836 }"
837 [(set_attr "length" "2")])
838 \f
839 ;; Boolean instructions.
840 ;;
841 ;; We don't define the DImode versions as expand_binop does a good enough job.
842
843 (define_insn "andsi3"
844 [(set (match_operand:SI 0 "register_operand" "=r")
845 (and:SI (match_operand:SI 1 "register_operand" "%r")
846 (match_operand:SI 2 "nonmemory_operand" "rIJ")))]
847 ""
848 "and%? %0,%1,%2")
849
850 (define_insn "*andsi3_set_cc_insn"
851 [(set (reg:CCZN 61) (compare:CCZN
852 (and:SI (match_operand:SI 1 "register_operand" "%r")
853 (match_operand:SI 2 "nonmemory_operand" "rIJ"))
854 (const_int 0)))
855 (set (match_operand:SI 0 "register_operand" "=r")
856 (and:SI (match_dup 1)
857 (match_dup 2)))]
858 ""
859 "and%?.f %0,%1,%2"
860 [(set_attr "cond" "set_zn")])
861
862 (define_insn "*bicsi3_insn"
863 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
864 (and:SI (match_operand:SI 1 "nonmemory_operand" "r,r,I,J")
865 (not:SI (match_operand:SI 2 "nonmemory_operand" "rI,J,r,r"))))]
866 ""
867 "bic%? %0,%1,%2"
868 [(set_attr "length" "1,2,1,2")])
869
870 (define_insn "*bicsi3_set_cc_insn"
871 [(set (reg:CCZN 61) (compare:CCZN
872 (and:SI (match_operand:SI 1 "register_operand" "%r")
873 (not:SI (match_operand:SI 2 "nonmemory_operand" "rIJ")))
874 (const_int 0)))
875 (set (match_operand:SI 0 "register_operand" "=r")
876 (and:SI (match_dup 1)
877 (not:SI (match_dup 2))))]
878 ""
879 "bic%?.f %0,%1,%2"
880 [(set_attr "cond" "set_zn")])
881
882 (define_insn "iorsi3"
883 [(set (match_operand:SI 0 "register_operand" "=r")
884 (ior:SI (match_operand:SI 1 "register_operand" "%r")
885 (match_operand:SI 2 "nonmemory_operand" "rIJ")))]
886 ""
887 "or%? %0,%1,%2")
888
889 (define_insn "*iorsi3_set_cc_insn"
890 [(set (reg:CCZN 61) (compare:CCZN
891 (ior:SI (match_operand:SI 1 "register_operand" "%r")
892 (match_operand:SI 2 "nonmemory_operand" "rIJ"))
893 (const_int 0)))
894 (set (match_operand:SI 0 "register_operand" "=r")
895 (ior:SI (match_dup 1)
896 (match_dup 2)))]
897 ""
898 "or%?.f %0,%1,%2"
899 [(set_attr "cond" "set_zn")])
900
901 (define_insn "xorsi3"
902 [(set (match_operand:SI 0 "register_operand" "=r")
903 (xor:SI (match_operand:SI 1 "register_operand" "%r")
904 (match_operand:SI 2 "nonmemory_operand" "rIJ")))]
905 ""
906 "xor%? %0,%1,%2")
907
908 (define_insn "*xorsi3_set_cc_insn"
909 [(set (reg:CCZN 61) (compare:CCZN
910 (xor:SI (match_operand:SI 1 "register_operand" "%r")
911 (match_operand:SI 2 "nonmemory_operand" "rIJ"))
912 (const_int 0)))
913 (set (match_operand:SI 0 "register_operand" "=r")
914 (xor:SI (match_dup 1)
915 (match_dup 2)))]
916 ""
917 "xor%?.f %0,%1,%2"
918 [(set_attr "cond" "set_zn")])
919
920 (define_insn "negsi2"
921 [(set (match_operand:SI 0 "register_operand" "=r")
922 (neg:SI (match_operand:SI 1 "register_operand" "r")))]
923 ""
924 "sub%? %0,0,%1"
925 [(set_attr "type" "unary")])
926
927 (define_insn "*negsi2_set_cc_insn"
928 [(set (reg:CC 61) (compare:CC
929 (neg:SI (match_operand:SI 1 "register_operand" "r"))
930 (const_int 0)))
931 (set (match_operand:SI 0 "register_operand" "=r")
932 (neg:SI (match_dup 1)))]
933 ""
934 "sub%?.f %0,0,%1"
935 [(set_attr "type" "unary")
936 (set_attr "cond" "set")])
937
938 (define_insn "negdi2"
939 [(set (match_operand:DI 0 "register_operand" "=r")
940 (neg:DI (match_operand:DI 1 "register_operand" "r")))
941 (clobber (reg:SI 61))]
942 ""
943 "sub.f %L0,0,%L1\;sbc %H0,0,%H1"
944 [(set_attr "type" "unary")
945 (set_attr "length" "2")])
946
947 (define_insn "one_cmplsi2"
948 [(set (match_operand:SI 0 "register_operand" "=r")
949 (not:SI (match_operand:SI 1 "register_operand" "r")))]
950 ""
951 "xor%? %0,%1,-1"
952 [(set_attr "type" "unary")])
953
954 (define_insn "*one_cmplsi2_set_cc_insn"
955 [(set (reg:CCZN 61) (compare:CCZN
956 (not:SI (match_operand:SI 1 "register_operand" "r"))
957 (const_int 0)))
958 (set (match_operand:SI 0 "register_operand" "=r")
959 (not:SI (match_dup 1)))]
960 ""
961 "xor%?.f %0,%1,-1"
962 [(set_attr "type" "unary")
963 (set_attr "cond" "set_zn")])
964 \f
965 ;; Shift instructions.
966
967 (define_expand "ashlsi3"
968 [(set (match_operand:SI 0 "register_operand" "")
969 (ashift:SI (match_operand:SI 1 "register_operand" "")
970 (match_operand:SI 2 "nonmemory_operand" "")))]
971 ""
972 "
973 {
974 if (! TARGET_SHIFTER)
975 {
976 emit_insn (gen_rtx_PARALLEL
977 (VOIDmode,
978 gen_rtvec (2,
979 gen_rtx_SET (VOIDmode, operands[0],
980 gen_rtx_ASHIFT (SImode, operands[1],
981 operands[2])),
982 gen_rtx_CLOBBER (VOIDmode,
983 gen_rtx_SCRATCH (SImode)))));
984 DONE;
985 }
986 }")
987
988 (define_expand "ashrsi3"
989 [(set (match_operand:SI 0 "register_operand" "")
990 (ashiftrt:SI (match_operand:SI 1 "register_operand" "")
991 (match_operand:SI 2 "nonmemory_operand" "")))]
992 ""
993 "
994 {
995 if (! TARGET_SHIFTER)
996 {
997 emit_insn (gen_rtx_PARALLEL
998 (VOIDmode,
999 gen_rtvec (2,
1000 gen_rtx_SET (VOIDmode, operands[0],
1001 gen_rtx_ASHIFTRT (SImode,
1002 operands[1],
1003 operands[2])),
1004 gen_rtx_CLOBBER (VOIDmode,
1005 gen_rtx_SCRATCH (SImode)))));
1006 DONE;
1007 }
1008 }")
1009
1010 (define_expand "lshrsi3"
1011 [(set (match_operand:SI 0 "register_operand" "")
1012 (lshiftrt:SI (match_operand:SI 1 "register_operand" "")
1013 (match_operand:SI 2 "nonmemory_operand" "")))]
1014 ""
1015 "
1016 {
1017 if (! TARGET_SHIFTER)
1018 {
1019 emit_insn (gen_rtx_PARALLEL
1020 (VOIDmode,
1021 gen_rtvec (2,
1022 gen_rtx_SET (VOIDmode, operands[0],
1023 gen_rtx_LSHIFTRT (SImode,
1024 operands[1],
1025 operands[2])),
1026 gen_rtx_CLOBBER (VOIDmode,
1027 gen_rtx_SCRATCH (SImode)))));
1028 DONE;
1029 }
1030 }")
1031
1032 (define_insn "*ashlsi3_insn"
1033 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
1034 (ashift:SI (match_operand:SI 1 "nonmemory_operand" "r,r,I,J")
1035 (match_operand:SI 2 "nonmemory_operand" "rI,J,r,r")))]
1036 "TARGET_SHIFTER"
1037 "asl%? %0,%1,%2"
1038 [(set_attr "type" "shift")
1039 (set_attr "length" "1,2,1,2")])
1040
1041 (define_insn "*ashrsi3_insn"
1042 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
1043 (ashiftrt:SI (match_operand:SI 1 "nonmemory_operand" "r,r,I,J")
1044 (match_operand:SI 2 "nonmemory_operand" "rI,J,r,r")))]
1045 "TARGET_SHIFTER"
1046 "asr%? %0,%1,%2"
1047 [(set_attr "type" "shift")
1048 (set_attr "length" "1,2,1,2")])
1049
1050 (define_insn "*lshrsi3_insn"
1051 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
1052 (lshiftrt:SI (match_operand:SI 1 "nonmemory_operand" "r,r,I,J")
1053 (match_operand:SI 2 "nonmemory_operand" "rI,J,r,r")))]
1054 "TARGET_SHIFTER"
1055 "lsr%? %0,%1,%2"
1056 [(set_attr "type" "shift")
1057 (set_attr "length" "1,2,1,2")])
1058
1059 (define_insn "*shift_si3"
1060 [(set (match_operand:SI 0 "register_operand" "=r")
1061 (match_operator:SI 3 "shift_operator"
1062 [(match_operand:SI 1 "register_operand" "0")
1063 (match_operand:SI 2 "nonmemory_operand" "rIJ")]))
1064 (clobber (match_scratch:SI 4 "=&r"))]
1065 "! TARGET_SHIFTER"
1066 "* return output_shift (operands);"
1067 [(set_attr "type" "shift")
1068 (set_attr "length" "8")])
1069 \f
1070 ;; Compare instructions.
1071 ;; This controls RTL generation and register allocation.
1072
1073 ;; ??? We may be able to relax this a bit by adding a new constant 'K' for 0.
1074 ;; This assumes sub.f 0,symbol,0 is a valid insn.
1075 ;; Note that "sub.f 0,r0,1" is an 8 byte insn. To avoid unnecessarily
1076 ;; creating 8 byte insns we duplicate %1 in the destination reg of the insn
1077 ;; if it's a small constant.
1078
1079 (define_insn "*cmpsi_cc_insn"
1080 [(set (reg:CC 61)
1081 (compare:CC (match_operand:SI 0 "register_operand" "r,r,r")
1082 (match_operand:SI 1 "nonmemory_operand" "r,I,J")))]
1083 ""
1084 "@
1085 sub.f 0,%0,%1
1086 sub.f %1,%0,%1
1087 sub.f 0,%0,%1"
1088 [(set_attr "type" "compare,compare,compare")])
1089
1090 (define_insn "*cmpsi_cczn_insn"
1091 [(set (reg:CCZN 61)
1092 (compare:CCZN (match_operand:SI 0 "register_operand" "r,r,r")
1093 (match_operand:SI 1 "nonmemory_operand" "r,I,J")))]
1094 ""
1095 "@
1096 sub.f 0,%0,%1
1097 sub.f %1,%0,%1
1098 sub.f 0,%0,%1"
1099 [(set_attr "type" "compare,compare,compare")])
1100
1101 (define_insn "*cmpsi_ccznc_insn"
1102 [(set (reg:CCZNC 61)
1103 (compare:CCZNC (match_operand:SI 0 "register_operand" "r,r,r")
1104 (match_operand:SI 1 "nonmemory_operand" "r,I,J")))]
1105 ""
1106 "@
1107 sub.f 0,%0,%1
1108 sub.f %1,%0,%1
1109 sub.f 0,%0,%1"
1110 [(set_attr "type" "compare,compare,compare")])
1111
1112 ;; Next come the scc insn and its expander.
1113
1114 (define_expand "cstoresi4"
1115 [(set (match_dup 4)
1116 (match_op_dup 5
1117 [(match_operand:SI 2 "register_operand" "")
1118 (match_operand:SI 3 "nonmemory_operand" "")]))
1119 (set (match_operand:SI 0 "register_operand")
1120 (match_operator:SI 1 "ordered_comparison_operator"
1121 [(match_dup 4)
1122 (const_int 0)]))]
1123 ""
1124 "
1125 {
1126 operands[4] = gen_compare_reg (GET_CODE (operands[1]),
1127 operands[2], operands[3]);
1128 operands[5] = gen_rtx_fmt_ee (COMPARE,
1129 GET_MODE (operands[4]),
1130 operands[2], operands[3]);
1131 }")
1132
1133 (define_insn "*scc_insn"
1134 [(set (match_operand:SI 0 "register_operand" "=r")
1135 (match_operator:SI 1 "comparison_operator" [(reg 61) (const_int 0)]))]
1136 ""
1137 "mov %0,1\;sub.%D1 %0,%0,%0"
1138 [(set_attr "type" "unary")
1139 (set_attr "length" "2")])
1140
1141 ;; ??? Look up negscc insn. See pa.md for example.
1142 (define_insn "*neg_scc_insn"
1143 [(set (match_operand:SI 0 "register_operand" "=r")
1144 (neg:SI (match_operator:SI 1 "comparison_operator"
1145 [(reg 61) (const_int 0)])))]
1146 ""
1147 "mov %0,-1\;sub.%D1 %0,%0,%0"
1148 [(set_attr "type" "unary")
1149 (set_attr "length" "2")])
1150
1151 (define_insn "*not_scc_insn"
1152 [(set (match_operand:SI 0 "register_operand" "=r")
1153 (not:SI (match_operator:SI 1 "comparison_operator"
1154 [(reg 61) (const_int 0)])))]
1155 ""
1156 "mov %0,1\;sub.%d1 %0,%0,%0"
1157 [(set_attr "type" "unary")
1158 (set_attr "length" "2")])
1159 \f
1160 ;; These control RTL generation for conditional jump insns
1161
1162 (define_expand "cbranchsi4"
1163 [(set (match_dup 4)
1164 (match_op_dup 5
1165 [(match_operand:SI 1 "register_operand" "")
1166 (match_operand:SI 2 "nonmemory_operand" "")]))
1167 (set (pc)
1168 (if_then_else
1169 (match_operator 0 "ordered_comparison_operator"
1170 [(match_dup 4)
1171 (const_int 0)])
1172 (label_ref (match_operand 3 "" ""))
1173 (pc)))]
1174 ""
1175 "
1176 {
1177 operands[4] = gen_compare_reg (GET_CODE (operands[0]),
1178 operands[1], operands[2]);
1179 operands[5] = gen_rtx_fmt_ee (COMPARE,
1180 GET_MODE (operands[4]),
1181 operands[1], operands[2]);
1182 }")
1183
1184 ;; Now match both normal and inverted jump.
1185
1186 (define_insn "*branch_insn"
1187 [(set (pc)
1188 (if_then_else (match_operator 1 "proper_comparison_operator"
1189 [(reg 61) (const_int 0)])
1190 (label_ref (match_operand 0 "" ""))
1191 (pc)))]
1192 ""
1193 "*
1194 {
1195 if (arc_ccfsm_branch_deleted_p ())
1196 {
1197 arc_ccfsm_record_branch_deleted ();
1198 return \"; branch deleted, next insns conditionalized\";
1199 }
1200 else
1201 return \"%~b%d1%# %l0\";
1202 }"
1203 [(set_attr "type" "branch")])
1204
1205 (define_insn "*rev_branch_insn"
1206 [(set (pc)
1207 (if_then_else (match_operator 1 "proper_comparison_operator"
1208 [(reg 61) (const_int 0)])
1209 (pc)
1210 (label_ref (match_operand 0 "" ""))))]
1211 "REVERSIBLE_CC_MODE (GET_MODE (XEXP (operands[1], 0)))"
1212 "*
1213 {
1214 if (arc_ccfsm_branch_deleted_p ())
1215 {
1216 arc_ccfsm_record_branch_deleted ();
1217 return \"; branch deleted, next insns conditionalized\";
1218 }
1219 else
1220 return \"%~b%D1%# %l0\";
1221 }"
1222 [(set_attr "type" "branch")])
1223 \f
1224 ;; Unconditional and other jump instructions.
1225
1226 (define_insn "jump"
1227 [(set (pc) (label_ref (match_operand 0 "" "")))]
1228 ""
1229 "b%* %l0"
1230 [(set_attr "type" "uncond_branch")])
1231
1232 (define_insn "indirect_jump"
1233 [(set (pc) (match_operand:SI 0 "address_operand" "p"))]
1234 ""
1235 "j%* %a0"
1236 [(set_attr "type" "uncond_branch")])
1237
1238 ;; Implement a switch statement.
1239 ;; This wouldn't be necessary in the non-pic case if we could distinguish
1240 ;; label refs of the jump table from other label refs. The problem is that
1241 ;; label refs are output as "%st(.LL42)" but we don't want the %st - we want
1242 ;; the real address since it's the address of the table.
1243
1244 (define_expand "casesi"
1245 [(set (match_dup 5)
1246 (minus:SI (match_operand:SI 0 "register_operand" "")
1247 (match_operand:SI 1 "nonmemory_operand" "")))
1248 (set (reg:CC 61)
1249 (compare:CC (match_dup 5)
1250 (match_operand:SI 2 "nonmemory_operand" "")))
1251 (set (pc)
1252 (if_then_else (gtu (reg:CC 61)
1253 (const_int 0))
1254 (label_ref (match_operand 4 "" ""))
1255 (pc)))
1256 (parallel
1257 [(set (pc)
1258 (mem:SI (plus:SI (mult:SI (match_dup 5)
1259 (const_int 4))
1260 (label_ref (match_operand 3 "" "")))))
1261 (clobber (match_scratch:SI 6 ""))
1262 (clobber (match_scratch:SI 7 ""))])]
1263 ""
1264 "
1265 {
1266 operands[5] = gen_reg_rtx (SImode);
1267 }")
1268
1269 (define_insn "*casesi_insn"
1270 [(set (pc)
1271 (mem:SI (plus:SI (mult:SI (match_operand:SI 0 "register_operand" "r")
1272 (const_int 4))
1273 (label_ref (match_operand 1 "" "")))))
1274 (clobber (match_scratch:SI 2 "=r"))
1275 (clobber (match_scratch:SI 3 "=r"))]
1276 ""
1277 "*
1278 {
1279 output_asm_insn (\"mov %2,%1\", operands);
1280 if (TARGET_SHIFTER)
1281 output_asm_insn (\"asl %3,%0,2\", operands);
1282 else
1283 output_asm_insn (\"asl %3,%0\;asl %3,%3\", operands);
1284 output_asm_insn (\"ld %2,[%2,%3]\", operands);
1285 output_asm_insn (\"j.nd %a2\", operands);
1286 return \"\";
1287 }"
1288 [(set_attr "type" "uncond_branch")
1289 (set_attr "length" "6")])
1290
1291 (define_insn "tablejump"
1292 [(set (pc) (match_operand:SI 0 "address_operand" "p"))
1293 (use (label_ref (match_operand 1 "" "")))]
1294 "0 /* disabled -> using casesi now */"
1295 "j%* %a0"
1296 [(set_attr "type" "uncond_branch")])
1297
1298 (define_expand "call"
1299 ;; operands[1] is stack_size_rtx
1300 ;; operands[2] is next_arg_register
1301 [(parallel [(call (match_operand:SI 0 "call_operand" "")
1302 (match_operand 1 "" ""))
1303 (clobber (reg:SI 31))])]
1304 ""
1305 "")
1306
1307 (define_insn "*call_via_reg"
1308 [(call (mem:SI (match_operand:SI 0 "register_operand" "r"))
1309 (match_operand 1 "" ""))
1310 (clobber (reg:SI 31))]
1311 ""
1312 "lr blink,[status]\;j.d %0\;add blink,blink,2"
1313 [(set_attr "type" "call_no_delay_slot")
1314 (set_attr "length" "3")])
1315
1316 (define_insn "*call_via_label"
1317 [(call (mem:SI (match_operand:SI 0 "call_address_operand" ""))
1318 (match_operand 1 "" ""))
1319 (clobber (reg:SI 31))]
1320 ""
1321 ; The %~ is necessary in case this insn gets conditionalized and the previous
1322 ; insn is the cc setter.
1323 "%~bl%!%* %0"
1324 [(set_attr "type" "call")
1325 (set_attr "cond" "canuse")])
1326
1327 (define_expand "call_value"
1328 ;; operand 2 is stack_size_rtx
1329 ;; operand 3 is next_arg_register
1330 [(parallel [(set (match_operand 0 "register_operand" "=r")
1331 (call (match_operand:SI 1 "call_operand" "")
1332 (match_operand 2 "" "")))
1333 (clobber (reg:SI 31))])]
1334 ""
1335 "")
1336
1337 (define_insn "*call_value_via_reg"
1338 [(set (match_operand 0 "register_operand" "=r")
1339 (call (mem:SI (match_operand:SI 1 "register_operand" "r"))
1340 (match_operand 2 "" "")))
1341 (clobber (reg:SI 31))]
1342 ""
1343 "lr blink,[status]\;j.d %1\;add blink,blink,2"
1344 [(set_attr "type" "call_no_delay_slot")
1345 (set_attr "length" "3")])
1346
1347 (define_insn "*call_value_via_label"
1348 [(set (match_operand 0 "register_operand" "=r")
1349 (call (mem:SI (match_operand:SI 1 "call_address_operand" ""))
1350 (match_operand 2 "" "")))
1351 (clobber (reg:SI 31))]
1352 ""
1353 ; The %~ is necessary in case this insn gets conditionalized and the previous
1354 ; insn is the cc setter.
1355 "%~bl%!%* %1"
1356 [(set_attr "type" "call")
1357 (set_attr "cond" "canuse")])
1358 \f
1359 (define_insn "nop"
1360 [(const_int 0)]
1361 ""
1362 "nop"
1363 [(set_attr "type" "misc")])
1364
1365 ;; Special pattern to flush the icache.
1366 ;; ??? Not sure what to do here. Some ARC's are known to support this.
1367
1368 (define_insn "flush_icache"
1369 [(unspec_volatile [(match_operand 0 "memory_operand" "m")] 0)]
1370 ""
1371 "* return \"\";"
1372 [(set_attr "type" "misc")])
1373 \f
1374 ;; Split up troublesome insns for better scheduling.
1375 \f
1376 ;; Peepholes go at the end.