070f248bbdf44b7e46a788a68f6d9ccc0f41c9c9
[gcc.git] / gcc / config / rx / rx.md
1 ;; Machine Description for Renesas RX processors
2 ;; Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
3 ;; Contributed by Red Hat.
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 \f
21
22 ;; This code iterator is used for sign- and zero- extensions.
23 (define_mode_iterator small_int_modes [(HI "") (QI "")])
24
25 ;; We do not handle DFmode here because it is either
26 ;; the same as SFmode, or if -m64bit-doubles is active
27 ;; then all operations on doubles have to be handled by
28 ;; library functions.
29 (define_mode_iterator register_modes
30 [(SF "ALLOW_RX_FPU_INSNS") (SI "") (HI "") (QI "")])
31
32 (define_constants
33 [
34 (SP_REG 0)
35 (CC_REG 16)
36
37 (UNSPEC_LOW_REG 0)
38 (UNSPEC_HIGH_REG 1)
39
40 (UNSPEC_RTE 10)
41 (UNSPEC_RTFI 11)
42 (UNSPEC_NAKED 12)
43 (UNSPEC_CONST 13)
44
45 (UNSPEC_MOVSTR 20)
46 (UNSPEC_MOVMEM 21)
47 (UNSPEC_SETMEM 22)
48 (UNSPEC_STRLEN 23)
49 (UNSPEC_CMPSTRN 24)
50
51 (UNSPEC_BUILTIN_BRK 30)
52 (UNSPEC_BUILTIN_CLRPSW 31)
53 (UNSPEC_BUILTIN_INT 32)
54 (UNSPEC_BUILTIN_MACHI 33)
55 (UNSPEC_BUILTIN_MACLO 34)
56 (UNSPEC_BUILTIN_MULHI 35)
57 (UNSPEC_BUILTIN_MULLO 36)
58 (UNSPEC_BUILTIN_MVFACHI 37)
59 (UNSPEC_BUILTIN_MVFACMI 38)
60 (UNSPEC_BUILTIN_MVFC 39)
61 (UNSPEC_BUILTIN_MVFCP 40)
62 (UNSPEC_BUILTIN_MVTACHI 41)
63 (UNSPEC_BUILTIN_MVTACLO 42)
64 (UNSPEC_BUILTIN_MVTC 43)
65 (UNSPEC_BUILTIN_MVTIPL 44)
66 (UNSPEC_BUILTIN_RACW 45)
67 (UNSPEC_BUILTIN_REVW 46)
68 (UNSPEC_BUILTIN_RMPA 47)
69 (UNSPEC_BUILTIN_ROUND 48)
70 (UNSPEC_BUILTIN_SAT 49)
71 (UNSPEC_BUILTIN_SETPSW 50)
72 (UNSPEC_BUILTIN_WAIT 51)
73 ]
74 )
75
76 (define_attr "length" "" (const_int 8))
77
78 (include "predicates.md")
79 (include "constraints.md")
80
81 ;; Pipeline description.
82
83 ;; The RX only has a single pipeline. It has five stages (fetch,
84 ;; decode, execute, memory access, writeback) each of which normally
85 ;; takes a single CPU clock cycle.
86
87 ;; The timings attribute consists of two numbers, the first is the
88 ;; throughput, which is the number of cycles the instruction takes
89 ;; to execute and generate a result. The second is the latency
90 ;; which is the effective number of cycles the instruction takes to
91 ;; execute if its result is used by the following instruction. The
92 ;; latency is always greater than or equal to the throughput.
93 ;; These values were taken from tables 2.13 and 2.14 in section 2.8
94 ;; of the RX610 Group Hardware Manual v0.11
95
96 ;; Note - it would be nice to use strings rather than integers for
97 ;; the possible values of this attribute, so that we can have the
98 ;; gcc build mechanism check for values that are not supported by
99 ;; the reservations below. But this will not work because the code
100 ;; in rx_adjust_sched_cost() needs integers not strings.
101
102 (define_attr "timings" "" (const_int 11))
103
104 (define_automaton "pipelining")
105 (define_cpu_unit "throughput" "pipelining")
106
107 (define_insn_reservation "throughput__1_latency__1" 1
108 (eq_attr "timings" "11") "throughput")
109 (define_insn_reservation "throughput__1_latency__2" 2
110 (eq_attr "timings" "12") "throughput,nothing")
111 (define_insn_reservation "throughput__2_latency__2" 1
112 (eq_attr "timings" "22") "throughput*2")
113 (define_insn_reservation "throughput__3_latency__3" 1
114 (eq_attr "timings" "33") "throughput*3")
115 (define_insn_reservation "throughput__3_latency__4" 2
116 (eq_attr "timings" "34") "throughput*3,nothing")
117 (define_insn_reservation "throughput__4_latency__4" 1
118 (eq_attr "timings" "44") "throughput*4")
119 (define_insn_reservation "throughput__4_latency__5" 2
120 (eq_attr "timings" "45") "throughput*4,nothing")
121 (define_insn_reservation "throughput__5_latency__5" 1
122 (eq_attr "timings" "55") "throughput*5")
123 (define_insn_reservation "throughput__5_latency__6" 2
124 (eq_attr "timings" "56") "throughput*5,nothing")
125 (define_insn_reservation "throughput__6_latency__6" 1
126 (eq_attr "timings" "66") "throughput*6")
127 (define_insn_reservation "throughput_10_latency_10" 1
128 (eq_attr "timings" "1010") "throughput*10")
129 (define_insn_reservation "throughput_11_latency_11" 1
130 (eq_attr "timings" "1111") "throughput*11")
131 (define_insn_reservation "throughput_16_latency_16" 1
132 (eq_attr "timings" "1616") "throughput*16")
133 (define_insn_reservation "throughput_18_latency_18" 1
134 (eq_attr "timings" "1818") "throughput*18")
135
136 ;; ----------------------------------------------------------------------------
137
138 ;; Comparisons
139
140 ;; Note - we do not specify the two instructions necessary to perform
141 ;; a compare-and-branch in the cbranchsi4 pattern because that would
142 ;; allow the comparison to be moved away from the jump before the reload
143 ;; pass has completed. That would be problematical because reload can
144 ;; generate ADDSI3 instructions which would corrupt the PSW flags.
145
146 (define_expand "cbranchsi4"
147 [(set (pc)
148 (if_then_else
149 (match_operator 0 "comparison_operator"
150 [(match_operand:SI 1 "register_operand")
151 (match_operand:SI 2 "rx_source_operand")])
152 (label_ref (match_operand 3 ""))
153 (pc)))]
154 ""
155 )
156
157 (define_insn_and_split "*cbranchsi4"
158 [(set (pc)
159 (if_then_else
160 (match_operator 3 "comparison_operator"
161 [(match_operand:SI 0 "register_operand" "r")
162 (match_operand:SI 1 "rx_source_operand" "riQ")])
163 (match_operand 2 "label_ref_operand" "")
164 (pc)))]
165 ""
166 "#"
167 "reload_completed"
168 [(const_int 0)]
169 {
170 rx_split_cbranch (CCmode, GET_CODE (operands[3]),
171 operands[0], operands[1], operands[2]);
172 DONE;
173 })
174
175 (define_insn "*cmpsi"
176 [(set (reg:CC CC_REG)
177 (compare:CC (match_operand:SI 0 "register_operand" "r,r,r,r,r,r,r")
178 (match_operand:SI 1 "rx_source_operand" "r,Uint04,Int08,Sint16,Sint24,i,Q")))]
179 "reload_completed"
180 "cmp\t%Q1, %0"
181 [(set_attr "timings" "11,11,11,11,11,11,33")
182 (set_attr "length" "2,2,3,4,5,6,5")]
183 )
184
185 ;; Canonical method for representing TST.
186 (define_insn_and_split "*cbranchsi4_tst"
187 [(set (pc)
188 (if_then_else
189 (match_operator 3 "rx_zs_comparison_operator"
190 [(and:SI (match_operand:SI 0 "register_operand" "r")
191 (match_operand:SI 1 "rx_source_operand" "riQ"))
192 (const_int 0)])
193 (match_operand 2 "label_ref_operand" "")
194 (pc)))]
195 ""
196 "#"
197 "reload_completed"
198 [(const_int 0)]
199 {
200 rx_split_cbranch (CC_ZSmode, GET_CODE (operands[3]),
201 XEXP (operands[3], 0), XEXP (operands[3], 1),
202 operands[2]);
203 DONE;
204 })
205
206 ;; Various other ways that GCC codes "var & const"
207 (define_insn_and_split "*cbranchsi4_tst_ext"
208 [(set (pc)
209 (if_then_else
210 (match_operator 4 "rx_z_comparison_operator"
211 [(zero_extract:SI
212 (match_operand:SI 0 "register_operand" "r")
213 (match_operand:SI 1 "rx_constshift_operand" "")
214 (match_operand:SI 2 "rx_constshift_operand" ""))
215 (const_int 0)])
216 (match_operand 3 "label_ref_operand" "")
217 (pc)))]
218 ""
219 "#"
220 "reload_completed"
221 [(const_int 0)]
222 {
223 HOST_WIDE_INT mask;
224 rtx x;
225
226 mask = 1;
227 mask <<= INTVAL (operands[1]);
228 mask -= 1;
229 mask <<= INTVAL (operands[2]);
230 x = gen_rtx_AND (SImode, operands[0], gen_int_mode (mask, SImode));
231
232 rx_split_cbranch (CC_ZSmode, GET_CODE (operands[4]),
233 x, const0_rtx, operands[3]);
234 DONE;
235 })
236
237 (define_insn "*tstsi"
238 [(set (reg:CC_ZS CC_REG)
239 (compare:CC_ZS
240 (and:SI (match_operand:SI 0 "register_operand" "r,r,r")
241 (match_operand:SI 1 "rx_source_operand" "r,i,Q"))
242 (const_int 0)))]
243 "reload_completed"
244 "tst\t%Q1, %0"
245 [(set_attr "timings" "11,11,33")
246 (set_attr "length" "3,7,6")]
247 )
248
249 (define_expand "cbranchsf4"
250 [(set (pc)
251 (if_then_else
252 (match_operator 0 "rx_fp_comparison_operator"
253 [(match_operand:SF 1 "register_operand")
254 (match_operand:SF 2 "rx_source_operand")])
255 (label_ref (match_operand 3 ""))
256 (pc)))]
257 "ALLOW_RX_FPU_INSNS"
258 )
259
260 (define_insn_and_split "*cbranchsf4"
261 [(set (pc)
262 (if_then_else
263 (match_operator 3 "rx_fp_comparison_operator"
264 [(match_operand:SF 0 "register_operand" "r")
265 (match_operand:SF 1 "rx_source_operand" "rFQ")])
266 (match_operand 2 "label_ref_operand" "")
267 (pc)))]
268 "ALLOW_RX_FPU_INSNS"
269 "#"
270 "&& reload_completed"
271 [(const_int 0)]
272 {
273 rx_split_cbranch (CC_Fmode, GET_CODE (operands[3]),
274 operands[0], operands[1], operands[2]);
275 DONE;
276 })
277
278 (define_insn "*cmpsf"
279 [(set (reg:CC_F CC_REG)
280 (compare:CC_F
281 (match_operand:SF 0 "register_operand" "r,r,r")
282 (match_operand:SF 1 "rx_source_operand" "r,F,Q")))]
283 "ALLOW_RX_FPU_INSNS && reload_completed"
284 "fcmp\t%1, %0"
285 [(set_attr "timings" "11,11,33")
286 (set_attr "length" "3,7,5")]
287 )
288
289 ;; Flow Control Instructions:
290
291 (define_insn "*conditional_branch"
292 [(set (pc)
293 (if_then_else
294 (match_operator 1 "comparison_operator"
295 [(reg CC_REG) (const_int 0)])
296 (label_ref (match_operand 0 "" ""))
297 (pc)))]
298 "reload_completed"
299 "b%B1\t%0"
300 [(set_attr "length" "8") ;; This length is wrong, but it is
301 ;; too hard to compute statically.
302 (set_attr "timings" "33")] ;; The timing assumes that the branch is taken.
303 )
304
305 ;; ----------------------------------------------------------------------------
306
307 (define_insn "jump"
308 [(set (pc)
309 (label_ref (match_operand 0 "" "")))]
310 ""
311 "bra\t%0"
312 [(set_attr "length" "4")
313 (set_attr "timings" "33")]
314 )
315
316 (define_insn "indirect_jump"
317 [(set (pc)
318 (match_operand:SI 0 "register_operand" "r"))]
319 ""
320 "jmp\t%0"
321 [(set_attr "length" "2")
322 (set_attr "timings" "33")]
323 )
324
325 (define_insn "tablejump"
326 [(set (pc)
327 (match_operand:SI 0 "register_operand" "r"))
328 (use (label_ref (match_operand 1 "" "")))]
329 ""
330 { return flag_pic ? (TARGET_AS100_SYNTAX ? "\n?:\tbra\t%0"
331 : "\n1:\tbra\t%0")
332 : "jmp\t%0";
333 }
334 [(set_attr "timings" "33")
335 (set_attr "length" "2")]
336 )
337
338 (define_insn "simple_return"
339 [(return)]
340 ""
341 "rts"
342 [(set_attr "length" "1")
343 (set_attr "timings" "55")]
344 )
345
346 ;; Unspec used so that the constant will not be invalid
347 ;; if -mmax-constant-size has been specified.
348 (define_insn "deallocate_and_return"
349 [(set (reg:SI SP_REG)
350 (plus:SI (reg:SI SP_REG)
351 (const:SI (unspec:SI [(match_operand 0 "const_int_operand" "n")] UNSPEC_CONST))))
352 (return)]
353 ""
354 "rtsd\t%0"
355 [(set_attr "length" "2")
356 (set_attr "timings" "55")]
357 )
358
359 (define_insn "pop_and_return"
360 [(match_parallel 1 "rx_rtsd_vector"
361 [(set (reg:SI SP_REG)
362 (plus:SI (reg:SI SP_REG)
363 (match_operand:SI 0 "const_int_operand" "n")))])
364 (return)]
365 "reload_completed"
366 {
367 rx_emit_stack_popm (operands, false);
368 return "";
369 }
370 [(set_attr "length" "3")
371 (set_attr "timings" "56")]
372 )
373
374 (define_insn "fast_interrupt_return"
375 [(unspec_volatile [(return)] UNSPEC_RTFI) ]
376 ""
377 "rtfi"
378 [(set_attr "length" "2")
379 (set_attr "timings" "33")]
380 )
381
382 (define_insn "exception_return"
383 [(unspec_volatile [(return)] UNSPEC_RTE) ]
384 ""
385 "rte"
386 [(set_attr "length" "2")
387 (set_attr "timings" "66")]
388 )
389
390 (define_insn "naked_return"
391 [(unspec_volatile [(return)] UNSPEC_NAKED) ]
392 ""
393 "; Naked function: epilogue provided by programmer."
394 )
395
396
397 ;; Note - the following set of patterns do not use the "memory_operand"
398 ;; predicate or an "m" constraint because we do not allow symbol_refs
399 ;; or label_refs as legitmate memory addresses. This matches the
400 ;; behaviour of most of the RX instructions. Only the call/branch
401 ;; instructions are allowed to refer to symbols/labels directly.
402 ;; The call operands are in QImode because that is the value of
403 ;; FUNCTION_MODE
404
405 (define_expand "call"
406 [(call (match_operand:QI 0 "general_operand")
407 (match_operand:SI 1 "general_operand"))]
408 ""
409 {
410 rtx dest = XEXP (operands[0], 0);
411
412 if (! rx_call_operand (dest, Pmode))
413 dest = force_reg (Pmode, dest);
414 emit_call_insn (gen_call_internal (dest));
415 DONE;
416 }
417 )
418
419 (define_insn "call_internal"
420 [(call (mem:QI (match_operand:SI 0 "rx_call_operand" "r,Symbol"))
421 (const_int 0))
422 (clobber (reg:CC CC_REG))]
423 ""
424 "@
425 jsr\t%0
426 bsr\t%A0"
427 [(set_attr "length" "2,4")
428 (set_attr "timings" "33")]
429 )
430
431 (define_expand "call_value"
432 [(set (match_operand 0 "register_operand")
433 (call (match_operand:QI 1 "general_operand")
434 (match_operand:SI 2 "general_operand")))]
435 ""
436 {
437 rtx dest = XEXP (operands[1], 0);
438
439 if (! rx_call_operand (dest, Pmode))
440 dest = force_reg (Pmode, dest);
441 emit_call_insn (gen_call_value_internal (operands[0], dest));
442 DONE;
443 }
444 )
445
446 (define_insn "call_value_internal"
447 [(set (match_operand 0 "register_operand" "=r,r")
448 (call (mem:QI (match_operand:SI 1 "rx_call_operand" "r,Symbol"))
449 (const_int 0)))
450 (clobber (reg:CC CC_REG))]
451 ""
452 "@
453 jsr\t%1
454 bsr\t%A1"
455 [(set_attr "length" "2,4")
456 (set_attr "timings" "33")]
457 )
458
459 ;; Note - we do not allow indirect sibcalls (with the address
460 ;; held in a register) because we cannot guarantee that the register
461 ;; chosen will be a call-used one. If it is a call-saved register,
462 ;; then the epilogue code will corrupt it by popping the saved value
463 ;; off of the stack.
464 (define_expand "sibcall"
465 [(parallel
466 [(call (mem:QI (match_operand:SI 0 "rx_symbolic_call_operand"))
467 (match_operand:SI 1 "general_operand"))
468 (return)])]
469 ""
470 {
471 if (MEM_P (operands[0]))
472 operands[0] = XEXP (operands[0], 0);
473 emit_call_insn (gen_sibcall_internal (operands[0]));
474 DONE;
475 }
476 )
477
478 (define_insn "sibcall_internal"
479 [(call (mem:QI (match_operand:SI 0 "rx_symbolic_call_operand" "Symbol"))
480 (const_int 0))
481 (return)]
482 ""
483 "bra\t%A0"
484 [(set_attr "length" "4")
485 (set_attr "timings" "33")]
486 )
487
488 (define_expand "sibcall_value"
489 [(parallel
490 [(set (match_operand 0 "register_operand")
491 (call (mem:QI (match_operand:SI 1 "rx_symbolic_call_operand"))
492 (match_operand:SI 2 "general_operand")))
493 (return)])]
494 ""
495 {
496 if (MEM_P (operands[1]))
497 operands[1] = XEXP (operands[1], 0);
498 emit_call_insn (gen_sibcall_value_internal (operands[0], operands[1]));
499 DONE;
500 }
501 )
502
503 (define_insn "sibcall_value_internal"
504 [(set (match_operand 0 "register_operand" "=r")
505 (call (mem:QI (match_operand:SI 1 "rx_symbolic_call_operand" "Symbol"))
506 (const_int 0)))
507 (return)]
508 ""
509 "bra\t%A1"
510 [(set_attr "length" "4")
511 (set_attr "timings" "33")]
512 )
513
514 ;; Function Prologue/Epilogue Instructions
515
516 (define_expand "prologue"
517 [(const_int 0)]
518 ""
519 "rx_expand_prologue (); DONE;"
520 )
521
522 (define_expand "epilogue"
523 [(return)]
524 ""
525 "rx_expand_epilogue (false); DONE;"
526 )
527
528 (define_expand "sibcall_epilogue"
529 [(return)]
530 ""
531 "rx_expand_epilogue (true); DONE;"
532 )
533
534 ;; Move Instructions
535
536 ;; Note - we do not allow memory to memory moves, even though the ISA
537 ;; supports them. The reason is that the conditions on such moves are
538 ;; too restrictive, specifically the source addressing mode is limited
539 ;; by the destination addressing mode and vice versa. (For example it
540 ;; is not possible to use indexed register indirect addressing for one
541 ;; of the operands if the other operand is anything other than a register,
542 ;; but it is possible to use register relative addressing when the other
543 ;; operand also uses register relative or register indirect addressing).
544 ;;
545 ;; GCC does not support computing legitimate addresses based on the
546 ;; nature of other operands involved in the instruction, and reload is
547 ;; not smart enough to cope with a whole variety of different memory
548 ;; addressing constraints, so it is simpler and safer to just refuse
549 ;; to support memory to memory moves.
550
551 (define_expand "mov<register_modes:mode>"
552 [(set (match_operand:register_modes 0 "general_operand")
553 (match_operand:register_modes 1 "general_operand"))]
554 ""
555 {
556 if (MEM_P (operand0) && MEM_P (operand1))
557 operands[1] = copy_to_mode_reg (<register_modes:MODE>mode, operand1);
558 if (CONST_INT_P (operand1)
559 && ! rx_is_legitimate_constant (<register_modes:MODE>mode, operand1))
560 FAIL;
561 }
562 )
563
564 (define_insn "*mov<register_modes:mode>_internal"
565 [(set (match_operand:register_modes
566 0 "nonimmediate_operand" "=r,r,r,r,r,r,m,Q,Q,Q,Q")
567 (match_operand:register_modes
568 1 "general_operand" "Int08,Sint16,Sint24,i,r,m,r,Int08,Sint16,Sint24,i"))]
569 ""
570 { return rx_gen_move_template (operands, false); }
571 [(set_attr "length" "3,4,5,6,2,4,6,5,6,7,8")
572 (set_attr "timings" "11,11,11,11,11,12,11,11,11,11,11")]
573 )
574
575 (define_insn "extend<small_int_modes:mode>si2"
576 [(set (match_operand:SI 0 "register_operand" "=r,r")
577 (sign_extend:SI (match_operand:small_int_modes
578 1 "nonimmediate_operand" "r,m")))]
579 ""
580 { return rx_gen_move_template (operands, false); }
581 [(set_attr "length" "2,6")
582 (set_attr "timings" "11,12")]
583 )
584
585 (define_insn "zero_extend<small_int_modes:mode>si2"
586 [(set (match_operand:SI 0 "register_operand" "=r,r")
587 (zero_extend:SI (match_operand:small_int_modes
588 1 "nonimmediate_operand" "r,m")))]
589 ""
590 { return rx_gen_move_template (operands, true); }
591 [(set_attr "length" "2,4")
592 (set_attr "timings" "11,12")]
593 )
594
595 (define_insn "stack_push"
596 [(set (reg:SI SP_REG)
597 (minus:SI (reg:SI SP_REG)
598 (const_int 4)))
599 (set (mem:SI (reg:SI SP_REG))
600 (match_operand:SI 0 "register_operand" "r"))]
601 ""
602 "push.l\t%0"
603 [(set_attr "length" "2")]
604 )
605
606 (define_insn "stack_pushm"
607 [(match_parallel 1 "rx_store_multiple_vector"
608 [(set (reg:SI SP_REG)
609 (minus:SI (reg:SI SP_REG)
610 (match_operand:SI 0 "const_int_operand" "n")))])]
611 "reload_completed"
612 {
613 rx_emit_stack_pushm (operands);
614 return "";
615 }
616 [(set_attr "length" "2")
617 (set_attr "timings" "44")] ;; The timing is a guesstimate average timing.
618 )
619
620 (define_insn "stack_pop"
621 [(set (match_operand:SI 0 "register_operand" "=r")
622 (mem:SI (reg:SI SP_REG)))
623 (set (reg:SI SP_REG)
624 (plus:SI (reg:SI SP_REG)
625 (const_int 4)))]
626 ""
627 "pop\t%0"
628 [(set_attr "length" "2")
629 (set_attr "timings" "12")]
630 )
631
632 (define_insn "stack_popm"
633 [(match_parallel 1 "rx_load_multiple_vector"
634 [(set (reg:SI SP_REG)
635 (plus:SI (reg:SI SP_REG)
636 (match_operand:SI 0 "const_int_operand" "n")))])]
637 "reload_completed"
638 {
639 rx_emit_stack_popm (operands, true);
640 return "";
641 }
642 [(set_attr "length" "2")
643 (set_attr "timings" "45")] ;; The timing is a guesstimate average timing.
644 )
645
646 (define_insn_and_split "cstoresi4"
647 [(set (match_operand:SI 0 "register_operand" "=r")
648 (match_operator:SI 1 "comparison_operator"
649 [(match_operand:SI 2 "register_operand" "r")
650 (match_operand:SI 3 "rx_source_operand" "riQ")]))
651 (clobber (reg:CC CC_REG))]
652 ""
653 "#"
654 "reload_completed"
655 [(const_int 0)]
656 {
657 rtx flags, x;
658
659 flags = gen_rtx_REG (CCmode, CC_REG);
660 x = gen_rtx_COMPARE (CCmode, operands[2], operands[3]);
661 x = gen_rtx_SET (VOIDmode, flags, x);
662 emit_insn (x);
663
664 x = gen_rtx_fmt_ee (GET_CODE (operands[1]), SImode, flags, const0_rtx);
665 x = gen_rtx_SET (VOIDmode, operands[0], x);
666 emit_insn (x);
667 DONE;
668 })
669
670 (define_insn "*sccc"
671 [(set (match_operand:SI 0 "register_operand" "=r")
672 (match_operator:SI 1 "comparison_operator"
673 [(reg CC_REG) (const_int 0)]))]
674 "reload_completed"
675 "sc%B1.L\t%0"
676 [(set_attr "length" "3")]
677 )
678
679 (define_insn_and_split "cstoresf4"
680 [(set (match_operand:SI 0 "register_operand" "=r")
681 (match_operator:SI 1 "rx_fp_comparison_operator"
682 [(match_operand:SF 2 "register_operand" "r")
683 (match_operand:SF 3 "rx_source_operand" "rFQ")]))]
684 "ALLOW_RX_FPU_INSNS"
685 "#"
686 "reload_completed"
687 [(const_int 0)]
688 {
689 rtx flags, x;
690
691 flags = gen_rtx_REG (CC_Fmode, CC_REG);
692 x = gen_rtx_COMPARE (CC_Fmode, operands[2], operands[3]);
693 x = gen_rtx_SET (VOIDmode, flags, x);
694 emit_insn (x);
695
696 x = gen_rtx_fmt_ee (GET_CODE (operands[1]), SImode, flags, const0_rtx);
697 x = gen_rtx_SET (VOIDmode, operands[0], x);
698 emit_insn (x);
699 DONE;
700 })
701
702 (define_expand "movsicc"
703 [(parallel
704 [(set (match_operand:SI 0 "register_operand")
705 (if_then_else:SI (match_operand:SI 1 "comparison_operator")
706 (match_operand:SI 2 "nonmemory_operand")
707 (match_operand:SI 3 "nonmemory_operand")))
708 (clobber (reg:CC CC_REG))])]
709 ""
710 {
711 /* ??? Support other conditions via cstore into a temporary? */
712 if (GET_CODE (operands[1]) != EQ && GET_CODE (operands[1]) != NE)
713 FAIL;
714 /* One operand must be a constant. */
715 if (!CONSTANT_P (operands[2]) && !CONSTANT_P (operands[3]))
716 FAIL;
717 })
718
719 (define_insn_and_split "*movsicc"
720 [(set (match_operand:SI 0 "register_operand" "=r,r")
721 (if_then_else:SI
722 (match_operator 5 "rx_z_comparison_operator"
723 [(match_operand:SI 3 "register_operand" "r,r")
724 (match_operand:SI 4 "rx_source_operand" "riQ,riQ")])
725 (match_operand:SI 1 "nonmemory_operand" "i,ri")
726 (match_operand:SI 2 "nonmemory_operand" "ri,i")))
727 (clobber (reg:CC CC_REG))]
728 "CONSTANT_P (operands[1]) || CONSTANT_P (operands[2])"
729 "#"
730 "&& reload_completed"
731 [(const_int 0)]
732 {
733 rtx x, flags, op0, op1, op2;
734 enum rtx_code cmp_code;
735
736 flags = gen_rtx_REG (CCmode, CC_REG);
737 x = gen_rtx_COMPARE (CCmode, operands[3], operands[4]);
738 emit_insn (gen_rtx_SET (VOIDmode, flags, x));
739
740 cmp_code = GET_CODE (operands[5]);
741 op0 = operands[0];
742 op1 = operands[1];
743 op2 = operands[2];
744
745 /* If OP2 is the constant, reverse the sense of the move. */
746 if (!CONSTANT_P (operands[1]))
747 {
748 x = op1, op1 = op2, op2 = x;
749 cmp_code = reverse_condition (cmp_code);
750 }
751
752 /* If OP2 does not match the output, copy it into place. We have allowed
753 these alternatives so that the destination can legitimately be one of
754 the comparison operands without increasing register pressure. */
755 if (!rtx_equal_p (op0, op2))
756 emit_move_insn (op0, op2);
757
758 x = gen_rtx_fmt_ee (cmp_code, VOIDmode, flags, const0_rtx);
759 x = gen_rtx_IF_THEN_ELSE (SImode, x, op1, op0);
760 emit_insn (gen_rtx_SET (VOIDmode, op0, x));
761 DONE;
762 })
763
764 (define_insn "*stcc"
765 [(set (match_operand:SI 0 "register_operand" "+r,r,r,r")
766 (if_then_else:SI
767 (match_operator 2 "rx_z_comparison_operator"
768 [(reg CC_REG) (const_int 0)])
769 (match_operand:SI 1 "immediate_operand" "Sint08,Sint16,Sint24,i")
770 (match_dup 0)))]
771 "reload_completed"
772 {
773 if (GET_CODE (operands[2]) == EQ)
774 return "stz\t%1, %0";
775 else
776 return "stnz\t%1, %0";
777 }
778 [(set_attr "length" "4,5,6,7")]
779 )
780
781 ;; Arithmetic Instructions
782
783 (define_insn "abssi2"
784 [(set (match_operand:SI 0 "register_operand" "=r,r")
785 (abs:SI (match_operand:SI 1 "register_operand" "0,r")))
786 (clobber (reg:CC CC_REG))]
787 ""
788 "@
789 abs\t%0
790 abs\t%1, %0"
791 [(set_attr "length" "2,3")]
792 )
793
794 (define_insn "*abssi2_flags"
795 [(set (match_operand:SI 0 "register_operand" "=r,r")
796 (abs:SI (match_operand:SI 1 "register_operand" "0,r")))
797 (set (reg CC_REG)
798 (compare (abs:SI (match_dup 1))
799 (const_int 0)))]
800 ;; Note - although the ABS instruction does set the O bit in the processor
801 ;; status word, it does not do so in a way that is comparable with the CMP
802 ;; instruction. Hence we use CC_ZSmode rather than CC_ZSOmode.
803 "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
804 "@
805 abs\t%0
806 abs\t%1, %0"
807 [(set_attr "length" "2,3")]
808 )
809
810 (define_insn "addsi3"
811 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r,r,r,r,r,r,r,r")
812 (plus:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0,0,r,r,r,r,r,r,0")
813 (match_operand:SI 2 "rx_source_operand" "r,Uint04,NEGint4,Sint08,Sint16,Sint24,i,0,r,Sint08,Sint16,Sint24,i,Q")))
814 (clobber (reg:CC CC_REG))]
815 ""
816 "@
817 add\t%2, %0
818 add\t%2, %0
819 sub\t%N2, %0
820 add\t%2, %0
821 add\t%2, %0
822 add\t%2, %0
823 add\t%2, %0
824 add\t%1, %0
825 add\t%2, %1, %0
826 add\t%2, %1, %0
827 add\t%2, %1, %0
828 add\t%2, %1, %0
829 add\t%2, %1, %0
830 add\t%Q2, %0"
831 [(set_attr "timings" "11,11,11,11,11,11,11,11,11,11,11,11,11,33")
832 (set_attr "length" "2,2,2,3,4,5,6,2,3,3,4,5,6,5")]
833 )
834
835 (define_insn "*addsi3_flags"
836 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r,r,r,r,r,r,r,r")
837 (plus:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0,0,r,r,r,r,r,r,0")
838 (match_operand:SI 2 "rx_source_operand" "r,Uint04,NEGint4,Sint08,Sint16,Sint24,i,0,r,Sint08,Sint16,Sint24,i,Q")))
839 (set (reg CC_REG)
840 (compare (plus:SI (match_dup 1) (match_dup 2))
841 (const_int 0)))]
842 "reload_completed && rx_match_ccmode (insn, CC_ZSCmode)"
843 "@
844 add\t%2, %0
845 add\t%2, %0
846 sub\t%N2, %0
847 add\t%2, %0
848 add\t%2, %0
849 add\t%2, %0
850 add\t%2, %0
851 add\t%1, %0
852 add\t%2, %1, %0
853 add\t%2, %1, %0
854 add\t%2, %1, %0
855 add\t%2, %1, %0
856 add\t%2, %1, %0
857 add\t%Q2, %0"
858 [(set_attr "timings" "11,11,11,11,11,11,11,11,11,11,11,11,11,33")
859 (set_attr "length" "2,2,2,3,4,5,6,2,3,3,4,5,6,5")]
860 )
861
862 ;; A helper to expand the above with the CC_MODE filled in.
863 (define_expand "addsi3_flags"
864 [(parallel [(set (match_operand:SI 0 "register_operand")
865 (plus:SI (match_operand:SI 1 "register_operand")
866 (match_operand:SI 2 "rx_source_operand")))
867 (set (reg:CC_ZSC CC_REG)
868 (compare:CC_ZSC (plus:SI (match_dup 1) (match_dup 2))
869 (const_int 0)))])]
870 )
871
872 (define_insn "adc_internal"
873 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r")
874 (plus:SI
875 (plus:SI
876 (ltu:SI (reg:CC CC_REG) (const_int 0))
877 (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0"))
878 (match_operand:SI 2 "rx_source_operand" "r,Sint08,Sint16,Sint24,i,Q")))
879 (clobber (reg:CC CC_REG))]
880 "reload_completed"
881 "adc %2,%0"
882 [(set_attr "timings" "11,11,11,11,11,33")
883 (set_attr "length" "3,4,5,6,7,6")]
884 )
885
886 (define_insn "*adc_flags"
887 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r")
888 (plus:SI
889 (plus:SI
890 (ltu:SI (reg:CC CC_REG) (const_int 0))
891 (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0"))
892 (match_operand:SI 2 "rx_source_operand" "r,Sint08,Sint16,Sint24,i,Q")))
893 (set (reg CC_REG)
894 (compare
895 (plus:SI
896 (plus:SI
897 (ltu:SI (reg:CC CC_REG) (const_int 0))
898 (match_dup 1))
899 (match_dup 2))
900 (const_int 0)))]
901 "reload_completed && rx_match_ccmode (insn, CC_ZSCmode)"
902 "adc %2,%0"
903 [(set_attr "timings" "11,11,11,11,11,33")
904 (set_attr "length" "3,4,5,6,7,6")]
905 )
906
907 ;; Peepholes to match:
908 ;; (set (reg A) (reg B))
909 ;; (set (CC) (compare:CC (reg A/reg B) (const_int 0)))
910 ;; and replace them with the addsi3_flags pattern, using an add
911 ;; of zero to copy the register and set the condition code bits.
912 (define_peephole2
913 [(set (match_operand:SI 0 "register_operand")
914 (match_operand:SI 1 "register_operand"))
915 (set (reg:CC CC_REG)
916 (compare:CC (match_dup 0)
917 (const_int 0)))]
918 ""
919 [(parallel [(set (match_dup 0)
920 (plus:SI (match_dup 1) (const_int 0)))
921 (set (reg:CC_ZSC CC_REG)
922 (compare:CC_ZSC (plus:SI (match_dup 1) (const_int 0))
923 (const_int 0)))])]
924 )
925
926 (define_peephole2
927 [(set (match_operand:SI 0 "register_operand")
928 (match_operand:SI 1 "register_operand"))
929 (set (reg:CC CC_REG)
930 (compare:CC (match_dup 1)
931 (const_int 0)))]
932 ""
933 [(parallel [(set (match_dup 0)
934 (plus:SI (match_dup 1) (const_int 0)))
935 (set (reg:CC_ZSC CC_REG)
936 (compare:CC_ZSC (plus:SI (match_dup 1) (const_int 0))
937 (const_int 0)))])]
938 )
939
940 (define_expand "adddi3"
941 [(set (match_operand:DI 0 "register_operand")
942 (plus:DI (match_operand:DI 1 "register_operand")
943 (match_operand:DI 2 "rx_source_operand")))]
944 ""
945 {
946 rtx op0l, op0h, op1l, op1h, op2l, op2h;
947
948 op0l = gen_lowpart (SImode, operands[0]);
949 op1l = gen_lowpart (SImode, operands[1]);
950 op2l = gen_lowpart (SImode, operands[2]);
951 op0h = gen_highpart (SImode, operands[0]);
952 op1h = gen_highpart (SImode, operands[1]);
953 op2h = gen_highpart_mode (SImode, DImode, operands[2]);
954
955 emit_insn (gen_adddi3_internal (op0l, op0h, op1l, op2l, op1h, op2h));
956 DONE;
957 })
958
959 (define_insn_and_split "adddi3_internal"
960 [(set (match_operand:SI 0 "register_operand" "=r")
961 (plus:SI (match_operand:SI 2 "register_operand" "r")
962 (match_operand:SI 3 "rx_source_operand" "riQ")))
963 (set (match_operand:SI 1 "register_operand" "=r")
964 (plus:SI
965 (plus:SI
966 (ltu:SI (plus:SI (match_dup 2) (match_dup 3)) (match_dup 2))
967 (match_operand:SI 4 "register_operand" "%1"))
968 (match_operand:SI 5 "rx_source_operand" "riQ")))
969 (clobber (match_scratch:SI 6 "=&r"))
970 (clobber (reg:CC CC_REG))]
971 ""
972 "#"
973 "reload_completed"
974 [(const_int 0)]
975 {
976 rtx op0l = operands[0];
977 rtx op0h = operands[1];
978 rtx op1l = operands[2];
979 rtx op2l = operands[3];
980 rtx op1h = operands[4];
981 rtx op2h = operands[5];
982 rtx scratch = operands[6];
983 rtx x;
984
985 if (reg_overlap_mentioned_p (op0l, op1h))
986 {
987 emit_move_insn (scratch, op0l);
988 op1h = scratch;
989 if (reg_overlap_mentioned_p (op0l, op2h))
990 op2h = scratch;
991 }
992 else if (reg_overlap_mentioned_p (op0l, op2h))
993 {
994 emit_move_insn (scratch, op0l);
995 op2h = scratch;
996 }
997
998 if (rtx_equal_p (op0l, op1l))
999 ;
1000 /* It is preferable that op0l == op1l... */
1001 else if (rtx_equal_p (op0l, op2l))
1002 x = op1l, op1l = op2l, op2l = x;
1003 /* ... but it is only a requirement if op2l == MEM. */
1004 else if (MEM_P (op2l))
1005 {
1006 /* Let's hope that we still have a scratch register free. */
1007 gcc_assert (op1h != scratch);
1008 emit_move_insn (scratch, op2l);
1009 op2l = scratch;
1010 }
1011
1012 emit_insn (gen_addsi3_flags (op0l, op1l, op2l));
1013
1014 if (rtx_equal_p (op0h, op1h))
1015 ;
1016 else if (rtx_equal_p (op0h, op2h))
1017 x = op1h, op1h = op2h, op2h = x;
1018 else
1019 {
1020 emit_move_insn (op0h, op1h);
1021 op1h = op0h;
1022 }
1023 emit_insn (gen_adc_internal (op0h, op1h, op2h));
1024 DONE;
1025 })
1026
1027 (define_insn "andsi3"
1028 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r,r,r")
1029 (and:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0,r,r,0")
1030 (match_operand:SI 2 "rx_source_operand" "r,Uint04,Sint08,Sint16,Sint24,i,0,r,Q")))
1031 (clobber (reg:CC CC_REG))]
1032 ""
1033 "@
1034 and\t%2, %0
1035 and\t%2, %0
1036 and\t%2, %0
1037 and\t%2, %0
1038 and\t%2, %0
1039 and\t%2, %0
1040 and\t%1, %0
1041 and\t%2, %1, %0
1042 and\t%Q2, %0"
1043 [(set_attr "timings" "11,11,11,11,11,11,11,11,33")
1044 (set_attr "length" "2,2,3,4,5,6,2,5,5")]
1045 )
1046
1047 (define_insn "*andsi3_flags"
1048 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r,r,r")
1049 (and:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0,r,r,0")
1050 (match_operand:SI 2 "rx_source_operand" "r,Uint04,Sint08,Sint16,Sint24,i,0,r,Q")))
1051 (set (reg CC_REG)
1052 (compare (and:SI (match_dup 1) (match_dup 2))
1053 (const_int 0)))]
1054 "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1055 "@
1056 and\t%2, %0
1057 and\t%2, %0
1058 and\t%2, %0
1059 and\t%2, %0
1060 and\t%2, %0
1061 and\t%2, %0
1062 and\t%1, %0
1063 and\t%2, %1, %0
1064 and\t%Q2, %0"
1065 [(set_attr "timings" "11,11,11,11,11,11,11,11,33")
1066 (set_attr "length" "2,2,3,4,5,6,2,5,5")]
1067 )
1068
1069 ;; Byte swap (single 32-bit value).
1070 (define_insn "bswapsi2"
1071 [(set (match_operand:SI 0 "register_operand" "=r")
1072 (bswap:SI (match_operand:SI 1 "register_operand" "r")))]
1073 ""
1074 "revl\t%1, %0"
1075 [(set_attr "length" "3")]
1076 )
1077
1078 ;; Byte swap (single 16-bit value). Note - we ignore the swapping of the high 16-bits.
1079 (define_insn "bswaphi2"
1080 [(set (match_operand:HI 0 "register_operand" "=r")
1081 (bswap:HI (match_operand:HI 1 "register_operand" "r")))]
1082 ""
1083 "revw\t%1, %0"
1084 [(set_attr "length" "3")]
1085 )
1086
1087 (define_insn "divsi3"
1088 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r")
1089 (div:SI (match_operand:SI 1 "register_operand" "0,0,0,0,0,0")
1090 (match_operand:SI 2 "rx_source_operand" "r,Sint08,Sint16,Sint24,i,Q")))
1091 (clobber (reg:CC CC_REG))]
1092 ""
1093 "div\t%Q2, %0"
1094 [(set_attr "timings" "1111") ;; Strictly speaking the timing should be
1095 ;; 2222, but that is a worst case sceanario.
1096 (set_attr "length" "3,4,5,6,7,6")]
1097 )
1098
1099 (define_insn "udivsi3"
1100 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r")
1101 (udiv:SI (match_operand:SI 1 "register_operand" "0,0,0,0,0,0")
1102 (match_operand:SI 2 "rx_source_operand" "r,Sint08,Sint16,Sint24,i,Q")))
1103 (clobber (reg:CC CC_REG))]
1104 ""
1105 "divu\t%Q2, %0"
1106 [(set_attr "timings" "1010") ;; Strictly speaking the timing should be
1107 ;; 2020, but that is a worst case sceanario.
1108 (set_attr "length" "3,4,5,6,7,6")]
1109 )
1110
1111 ;; Note - these patterns are suppressed in big-endian mode because they
1112 ;; generate a little endian result. ie the most significant word of the
1113 ;; result is placed in the higher numbered register of the destination
1114 ;; register pair.
1115
1116 (define_insn "mulsidi3"
1117 [(set (match_operand:DI 0 "register_operand" "=r,r,r,r,r,r")
1118 (mult:DI (sign_extend:DI (match_operand:SI
1119 1 "register_operand" "%0,0,0,0,0,0"))
1120 (sign_extend:DI (match_operand:SI
1121 2 "rx_source_operand"
1122 "r,Sint08,Sint16,Sint24,i,Q"))))]
1123 "! TARGET_BIG_ENDIAN_DATA"
1124 "emul\t%Q2, %0"
1125 [(set_attr "length" "3,4,5,6,7,6")
1126 (set_attr "timings" "22,22,22,22,22,44")]
1127 )
1128
1129 ;; See comment for mulsidi3.
1130 ;; Note - the zero_extends are to distinguish this pattern from the
1131 ;; mulsidi3 pattern. Immediate mode addressing is not supported
1132 ;; because gcc cannot handle the expression: (zero_extend (const_int)).
1133 (define_insn "umulsidi3"
1134 [(set (match_operand:DI 0 "register_operand" "=r,r")
1135 (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "%0,0"))
1136 (zero_extend:DI (match_operand:SI 2 "rx_compare_operand" "r,Q"))))]
1137 "! TARGET_BIG_ENDIAN_DATA"
1138 "emulu\t%Q2, %0"
1139 [(set_attr "length" "3,6")
1140 (set_attr "timings" "22,44")]
1141 )
1142
1143 (define_insn "smaxsi3"
1144 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r")
1145 (smax:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0")
1146 (match_operand:SI 2 "rx_source_operand"
1147 "r,Sint08,Sint16,Sint24,i,Q")))]
1148 ""
1149 "max\t%Q2, %0"
1150 [(set_attr "length" "3,4,5,6,7,6")
1151 (set_attr "timings" "11,11,11,11,11,33")]
1152 )
1153
1154 (define_insn "sminsi3"
1155 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r")
1156 (smin:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0")
1157 (match_operand:SI 2 "rx_source_operand"
1158 "r,Sint08,Sint16,Sint24,i,Q")))]
1159 ""
1160 "min\t%Q2, %0"
1161 [(set_attr "length" "3,4,5,6,7,6")
1162 (set_attr "timings" "11,11,11,11,11,33")]
1163 )
1164
1165 (define_insn "mulsi3"
1166 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r,r,r")
1167 (mult:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0,0,r,r")
1168 (match_operand:SI 2 "rx_source_operand"
1169 "r,Uint04,Sint08,Sint16,Sint24,i,Q,0,r")))]
1170 ""
1171 "@
1172 mul\t%2, %0
1173 mul\t%2, %0
1174 mul\t%2, %0
1175 mul\t%2, %0
1176 mul\t%2, %0
1177 mul\t%Q2, %0
1178 mul\t%Q2, %0
1179 mul\t%1, %0
1180 mul\t%2, %1, %0"
1181 [(set_attr "length" "2,2,3,4,5,6,5,2,3")
1182 (set_attr "timings" "11,11,11,11,11,11,33,11,11")]
1183 )
1184
1185 (define_insn "negsi2"
1186 [(set (match_operand:SI 0 "register_operand" "=r,r")
1187 (neg:SI (match_operand:SI 1 "register_operand" "0,r")))
1188 (clobber (reg:CC CC_REG))]
1189 ""
1190 "@
1191 neg\t%0
1192 neg\t%1, %0"
1193 [(set_attr "length" "2,3")]
1194 )
1195
1196 ;; Note that the O and C flags are not set as per a normal compare,
1197 ;; and thus are unusable in that context.
1198 (define_insn "*negsi2_flags"
1199 [(set (match_operand:SI 0 "register_operand" "=r,r")
1200 (neg:SI (match_operand:SI 1 "register_operand" "0,r")))
1201 (set (reg CC_REG)
1202 (compare (neg:SI (match_dup 1))
1203 (const_int 0)))]
1204 "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1205 "@
1206 neg\t%0
1207 neg\t%1, %0"
1208 [(set_attr "length" "2,3")]
1209 )
1210
1211 (define_insn "one_cmplsi2"
1212 [(set (match_operand:SI 0 "register_operand" "=r,r")
1213 (not:SI (match_operand:SI 1 "register_operand" "0,r")))
1214 (clobber (reg:CC CC_REG))]
1215 ""
1216 "@
1217 not\t%0
1218 not\t%1, %0"
1219 [(set_attr "length" "2,3")]
1220 )
1221
1222 (define_insn "*one_cmplsi2_flags"
1223 [(set (match_operand:SI 0 "register_operand" "=r,r")
1224 (not:SI (match_operand:SI 1 "register_operand" "0,r")))
1225 (set (reg CC_REG)
1226 (compare (not:SI (match_dup 1))
1227 (const_int 0)))]
1228 "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1229 "@
1230 not\t%0
1231 not\t%1, %0"
1232 [(set_attr "length" "2,3")]
1233 )
1234
1235 (define_insn "iorsi3"
1236 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r,r,r")
1237 (ior:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0,r,r,0")
1238 (match_operand:SI 2 "rx_source_operand" "r,Uint04,Sint08,Sint16,Sint24,i,0,r,Q")))
1239 (clobber (reg:CC CC_REG))]
1240 ""
1241 "@
1242 or\t%2, %0
1243 or\t%2, %0
1244 or\t%2, %0
1245 or\t%2, %0
1246 or\t%2, %0
1247 or\t%Q2, %0
1248 or\t%1, %0
1249 or\t%2, %1, %0
1250 or\t%Q2, %0"
1251 [(set_attr "timings" "11,11,11,11,11,11,11,11,33")
1252 (set_attr "length" "2,2,3,4,5,6,2,3,5")]
1253 )
1254
1255 (define_insn "*iorsi3_flags"
1256 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r,r,r")
1257 (ior:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0,r,r,0")
1258 (match_operand:SI 2 "rx_source_operand" "r,Uint04,Sint08,Sint16,Sint24,i,0,r,Q")))
1259 (set (reg CC_REG)
1260 (compare (ior:SI (match_dup 1) (match_dup 2))
1261 (const_int 0)))]
1262 "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1263 "@
1264 or\t%2, %0
1265 or\t%2, %0
1266 or\t%2, %0
1267 or\t%2, %0
1268 or\t%2, %0
1269 or\t%Q2, %0
1270 or\t%1, %0
1271 or\t%2, %1, %0
1272 or\t%Q2, %0"
1273 [(set_attr "timings" "11,11,11,11,11,11,11,11,33")
1274 (set_attr "length" "2,2,3,4,5,6,2,3,5")]
1275 )
1276
1277 (define_insn "rotlsi3"
1278 [(set (match_operand:SI 0 "register_operand" "=r")
1279 (rotate:SI (match_operand:SI 1 "register_operand" "0")
1280 (match_operand:SI 2 "rx_shift_operand" "rn")))
1281 (clobber (reg:CC CC_REG))]
1282 ""
1283 "rotl\t%2, %0"
1284 [(set_attr "length" "3")]
1285 )
1286
1287 (define_insn "*rotlsi3_flags"
1288 [(set (match_operand:SI 0 "register_operand" "=r")
1289 (rotate:SI (match_operand:SI 1 "register_operand" "0")
1290 (match_operand:SI 2 "rx_shift_operand" "rn")))
1291 (set (reg CC_REG)
1292 (compare (rotate:SI (match_dup 1) (match_dup 2))
1293 (const_int 0)))]
1294 "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1295 "rotl\t%2, %0"
1296 [(set_attr "length" "3")]
1297 )
1298
1299 (define_insn "rotrsi3"
1300 [(set (match_operand:SI 0 "register_operand" "=r")
1301 (rotatert:SI (match_operand:SI 1 "register_operand" "0")
1302 (match_operand:SI 2 "rx_shift_operand" "rn")))
1303 (clobber (reg:CC CC_REG))]
1304 ""
1305 "rotr\t%2, %0"
1306 [(set_attr "length" "3")]
1307 )
1308
1309 (define_insn "*rotrsi3_flags"
1310 [(set (match_operand:SI 0 "register_operand" "=r")
1311 (rotatert:SI (match_operand:SI 1 "register_operand" "0")
1312 (match_operand:SI 2 "rx_shift_operand" "rn")))
1313 (set (reg CC_REG)
1314 (compare (rotatert:SI (match_dup 1) (match_dup 2))
1315 (const_int 0)))]
1316 "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1317 "rotr\t%2, %0"
1318 [(set_attr "length" "3")]
1319 )
1320
1321 (define_insn "ashrsi3"
1322 [(set (match_operand:SI 0 "register_operand" "=r,r,r")
1323 (ashiftrt:SI (match_operand:SI 1 "register_operand" "0,0,r")
1324 (match_operand:SI 2 "rx_shift_operand" "r,n,n")))
1325 (clobber (reg:CC CC_REG))]
1326 ""
1327 "@
1328 shar\t%2, %0
1329 shar\t%2, %0
1330 shar\t%2, %1, %0"
1331 [(set_attr "length" "3,2,3")]
1332 )
1333
1334 (define_insn "*ashrsi3_flags"
1335 [(set (match_operand:SI 0 "register_operand" "=r,r,r")
1336 (ashiftrt:SI (match_operand:SI 1 "register_operand" "0,0,r")
1337 (match_operand:SI 2 "rx_shift_operand" "r,n,n")))
1338 (set (reg CC_REG)
1339 (compare (ashiftrt:SI (match_dup 1) (match_dup 2))
1340 (const_int 0)))]
1341 "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1342 "@
1343 shar\t%2, %0
1344 shar\t%2, %0
1345 shar\t%2, %1, %0"
1346 [(set_attr "length" "3,2,3")]
1347 )
1348
1349 (define_insn "lshrsi3"
1350 [(set (match_operand:SI 0 "register_operand" "=r,r,r")
1351 (lshiftrt:SI (match_operand:SI 1 "register_operand" "0,0,r")
1352 (match_operand:SI 2 "rx_shift_operand" "r,n,n")))
1353 (clobber (reg:CC CC_REG))]
1354 ""
1355 "@
1356 shlr\t%2, %0
1357 shlr\t%2, %0
1358 shlr\t%2, %1, %0"
1359 [(set_attr "length" "3,2,3")]
1360 )
1361
1362 (define_insn "*lshrsi3_flags"
1363 [(set (match_operand:SI 0 "register_operand" "=r,r,r")
1364 (lshiftrt:SI (match_operand:SI 1 "register_operand" "0,0,r")
1365 (match_operand:SI 2 "rx_shift_operand" "r,n,n")))
1366 (set (reg CC_REG)
1367 (compare (lshiftrt:SI (match_dup 1) (match_dup 2))
1368 (const_int 0)))]
1369 "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1370 "@
1371 shlr\t%2, %0
1372 shlr\t%2, %0
1373 shlr\t%2, %1, %0"
1374 [(set_attr "length" "3,2,3")]
1375 )
1376
1377 (define_insn "ashlsi3"
1378 [(set (match_operand:SI 0 "register_operand" "=r,r,r")
1379 (ashift:SI (match_operand:SI 1 "register_operand" "0,0,r")
1380 (match_operand:SI 2 "rx_shift_operand" "r,n,n")))
1381 (clobber (reg:CC CC_REG))]
1382 ""
1383 "@
1384 shll\t%2, %0
1385 shll\t%2, %0
1386 shll\t%2, %1, %0"
1387 [(set_attr "length" "3,2,3")]
1388 )
1389
1390 (define_insn "*ashlsi3_flags"
1391 [(set (match_operand:SI 0 "register_operand" "=r,r,r")
1392 (ashift:SI (match_operand:SI 1 "register_operand" "0,0,r")
1393 (match_operand:SI 2 "rx_shift_operand" "r,n,n")))
1394 (set (reg CC_REG)
1395 (compare (ashift:SI (match_dup 1) (match_dup 2))
1396 (const_int 0)))]
1397 "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1398 "@
1399 shll\t%2, %0
1400 shll\t%2, %0
1401 shll\t%2, %1, %0"
1402 [(set_attr "length" "3,2,3")]
1403 )
1404
1405 ;; Saturate to 32-bits
1406 (define_insn_and_split "ssaddsi3"
1407 [(set (match_operand:SI 0 "register_operand" "=r")
1408 (ss_plus:SI (match_operand:SI 1 "register_operand" "r")
1409 (match_operand:SI 2 "rx_source_operand" "riQ")))
1410 (clobber (reg:CC CC_REG))]
1411 ""
1412 "#"
1413 "reload_completed"
1414 [(parallel [(set (match_dup 0)
1415 (plus:SI (match_dup 1) (match_dup 2)))
1416 (set (reg:CC_ZSC CC_REG)
1417 (compare:CC_ZSC
1418 (plus:SI (match_dup 1) (match_dup 2))
1419 (const_int 0)))])
1420 (set (match_dup 0)
1421 (unspec:SI [(match_dup 0) (reg:CC CC_REG)]
1422 UNSPEC_BUILTIN_SAT))]
1423 ""
1424 )
1425
1426 (define_insn "*sat"
1427 [(set (match_operand:SI 0 "register_operand" "=r")
1428 (unspec:SI [(match_operand:SI 1 "register_operand" "0")
1429 (reg:CC CC_REG)]
1430 UNSPEC_BUILTIN_SAT))]
1431 "reload_completed"
1432 "sat\t%0"
1433 [(set_attr "length" "2")]
1434 )
1435
1436 (define_insn "subsi3"
1437 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r")
1438 (minus:SI (match_operand:SI 1 "register_operand" "0,0,0,r,0")
1439 (match_operand:SI 2 "rx_source_operand" "r,Uint04,n,r,Q")))
1440 (clobber (reg:CC CC_REG))]
1441 ""
1442 "@
1443 sub\t%2, %0
1444 sub\t%2, %0
1445 add\t%N2, %0
1446 sub\t%2, %1, %0
1447 sub\t%Q2, %0"
1448 [(set_attr "timings" "11,11,11,11,33")
1449 (set_attr "length" "2,2,6,3,5")]
1450 )
1451
1452 ;; Note that the O flag is set as if (compare op1 op2) not for
1453 ;; what is described here, (compare op0 0).
1454 (define_insn "*subsi3_flags"
1455 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r")
1456 (minus:SI (match_operand:SI 1 "register_operand" "0,0,0,r,0")
1457 (match_operand:SI 2 "rx_source_operand" "r,Uint04,n,r,Q")))
1458 (set (reg CC_REG)
1459 (compare (minus:SI (match_dup 1) (match_dup 2))
1460 (const_int 0)))]
1461 "reload_completed && rx_match_ccmode (insn, CC_ZSCmode)"
1462 "@
1463 sub\t%2, %0
1464 sub\t%2, %0
1465 add\t%N2, %0
1466 sub\t%2, %1, %0
1467 sub\t%Q2, %0"
1468 [(set_attr "timings" "11,11,11,11,33")
1469 (set_attr "length" "2,2,6,3,5")]
1470 )
1471
1472 ;; A helper to expand the above with the CC_MODE filled in.
1473 (define_expand "subsi3_flags"
1474 [(parallel [(set (match_operand:SI 0 "register_operand")
1475 (minus:SI (match_operand:SI 1 "register_operand")
1476 (match_operand:SI 2 "rx_source_operand")))
1477 (set (reg:CC_ZSC CC_REG)
1478 (compare:CC_ZSC (minus:SI (match_dup 1) (match_dup 2))
1479 (const_int 0)))])]
1480 )
1481
1482 (define_insn "sbb_internal"
1483 [(set (match_operand:SI 0 "register_operand" "=r,r")
1484 (minus:SI
1485 (minus:SI
1486 (match_operand:SI 1 "register_operand" " 0,0")
1487 (match_operand:SI 2 "rx_compare_operand" " r,Q"))
1488 (geu:SI (reg:CC CC_REG) (const_int 0))))
1489 (clobber (reg:CC CC_REG))]
1490 "reload_completed"
1491 "sbb\t%2, %0"
1492 [(set_attr "timings" "11,33")
1493 (set_attr "length" "3,6")]
1494 )
1495
1496 (define_insn "*sbb_flags"
1497 [(set (match_operand:SI 0 "register_operand" "=r,r")
1498 (minus:SI
1499 (minus:SI
1500 (match_operand:SI 1 "register_operand" " 0,0")
1501 (match_operand:SI 2 "rx_compare_operand" " r,Q"))
1502 (geu:SI (reg:CC CC_REG) (const_int 0))))
1503 (set (reg CC_REG)
1504 (compare
1505 (minus:SI
1506 (minus:SI (match_dup 1) (match_dup 2))
1507 (geu:SI (reg:CC CC_REG) (const_int 0)))
1508 (const_int 0)))]
1509 "reload_completed"
1510 "sbb\t%2, %0"
1511 [(set_attr "timings" "11,33")
1512 (set_attr "length" "3,6")]
1513 )
1514
1515 (define_expand "subdi3"
1516 [(set (match_operand:DI 0 "register_operand")
1517 (minus:DI (match_operand:DI 1 "register_operand")
1518 (match_operand:DI 2 "rx_compare_operand")))]
1519 ""
1520 {
1521 rtx op0l, op0h, op1l, op1h, op2l, op2h;
1522
1523 op0l = gen_lowpart (SImode, operands[0]);
1524 op1l = gen_lowpart (SImode, operands[1]);
1525 op2l = gen_lowpart (SImode, operands[2]);
1526 op0h = gen_highpart (SImode, operands[0]);
1527 op1h = gen_highpart (SImode, operands[1]);
1528 op2h = gen_highpart_mode (SImode, DImode, operands[2]);
1529
1530 emit_insn (gen_subdi3_internal (op0l, op0h, op1l, op2l, op1h, op2h));
1531 DONE;
1532 })
1533
1534 (define_insn_and_split "subdi3_internal"
1535 [(set (match_operand:SI 0 "register_operand" "=&r,&r")
1536 (minus:SI (match_operand:SI 2 "register_operand" " 0, r")
1537 (match_operand:SI 3 "rx_compare_operand" "rQ, r")))
1538 (set (match_operand:SI 1 "register_operand" "= r, r")
1539 (minus:SI
1540 (minus:SI
1541 (match_operand:SI 4 "register_operand" " 1, 1")
1542 (match_operand:SI 5 "rx_compare_operand" " rQ,rQ"))
1543 (geu:SI (match_dup 2) (match_dup 3))))
1544 (clobber (reg:CC CC_REG))]
1545 ""
1546 "#"
1547 "reload_completed"
1548 [(const_int 0)]
1549 {
1550 emit_insn (gen_subsi3_flags (operands[0], operands[2], operands[3]));
1551 emit_insn (gen_sbb_internal (operands[1], operands[4], operands[5]));
1552 DONE;
1553 })
1554
1555 (define_insn "xorsi3"
1556 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r")
1557 (xor:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0")
1558 (match_operand:SI 2 "rx_source_operand"
1559 "r,Sint08,Sint16,Sint24,i,Q")))
1560 (clobber (reg:CC CC_REG))]
1561 ""
1562 "xor\t%Q2, %0"
1563 [(set_attr "timings" "11,11,11,11,11,33")
1564 (set_attr "length" "3,4,5,6,7,6")]
1565 )
1566
1567 (define_insn "*xorsi3_flags"
1568 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r")
1569 (xor:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0")
1570 (match_operand:SI 2 "rx_source_operand"
1571 "r,Sint08,Sint16,Sint24,i,Q")))
1572 (set (reg CC_REG)
1573 (compare (xor:SI (match_dup 1) (match_dup 2))
1574 (const_int 0)))]
1575 "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1576 "xor\t%Q2, %0"
1577 [(set_attr "timings" "11,11,11,11,11,33")
1578 (set_attr "length" "3,4,5,6,7,6")]
1579 )
1580 \f
1581 ;; A set of peepholes to catch extending loads followed by arithmetic operations.
1582 ;; We use iterators where possible to reduce the amount of typing and hence the
1583 ;; possibilities for typos.
1584
1585 (define_code_iterator extend_types [(zero_extend "") (sign_extend "")])
1586 (define_code_attr letter [(zero_extend "R") (sign_extend "Q")])
1587
1588 (define_code_iterator memex_commutative [(plus "") (and "") (ior "") (xor "")])
1589 (define_code_iterator memex_noncomm [(div "") (udiv "") (minus "")])
1590 (define_code_iterator memex_nocc [(smax "") (smin "") (mult "")])
1591
1592 (define_code_attr op [(plus "add") (and "and") (div "div") (udiv "divu") (smax "max") (smin "min") (mult "mul") (ior "or") (minus "sub") (xor "xor")])
1593
1594 (define_peephole2
1595 [(set (match_operand:SI 0 "register_operand")
1596 (extend_types:SI (match_operand:small_int_modes 1 "rx_restricted_mem_operand")))
1597 (parallel [(set (match_operand:SI 2 "register_operand")
1598 (memex_commutative:SI (match_dup 0)
1599 (match_dup 2)))
1600 (clobber (reg:CC CC_REG))])]
1601 "peep2_regno_dead_p (2, REGNO (operands[0]))"
1602 [(parallel [(set:SI (match_dup 2)
1603 (memex_commutative:SI (match_dup 2)
1604 (extend_types:SI (match_dup 1))))
1605 (clobber (reg:CC CC_REG))])]
1606 )
1607
1608 (define_peephole2
1609 [(set (match_operand:SI 0 "register_operand")
1610 (extend_types:SI (match_operand:small_int_modes 1 "rx_restricted_mem_operand")))
1611 (parallel [(set (match_operand:SI 2 "register_operand")
1612 (memex_commutative:SI (match_dup 2)
1613 (match_dup 0)))
1614 (clobber (reg:CC CC_REG))])]
1615 "peep2_regno_dead_p (2, REGNO (operands[0]))"
1616 [(parallel [(set:SI (match_dup 2)
1617 (memex_commutative:SI (match_dup 2)
1618 (extend_types:SI (match_dup 1))))
1619 (clobber (reg:CC CC_REG))])]
1620 )
1621
1622 (define_peephole2
1623 [(set (match_operand:SI 0 "register_operand")
1624 (extend_types:SI (match_operand:small_int_modes 1 "rx_restricted_mem_operand")))
1625 (parallel [(set (match_operand:SI 2 "register_operand")
1626 (memex_noncomm:SI (match_dup 2)
1627 (match_dup 0)))
1628 (clobber (reg:CC CC_REG))])]
1629 "peep2_regno_dead_p (2, REGNO (operands[0]))"
1630 [(parallel [(set:SI (match_dup 2)
1631 (memex_noncomm:SI (match_dup 2)
1632 (extend_types:SI (match_dup 1))))
1633 (clobber (reg:CC CC_REG))])]
1634 )
1635
1636 (define_peephole2
1637 [(set (match_operand:SI 0 "register_operand")
1638 (extend_types:SI (match_operand:small_int_modes 1 "rx_restricted_mem_operand")))
1639 (set (match_operand:SI 2 "register_operand")
1640 (memex_nocc:SI (match_dup 0)
1641 (match_dup 2)))]
1642 "peep2_regno_dead_p (2, REGNO (operands[0]))"
1643 [(set:SI (match_dup 2)
1644 (memex_nocc:SI (match_dup 2)
1645 (extend_types:SI (match_dup 1))))]
1646 )
1647
1648 (define_peephole2
1649 [(set (match_operand:SI 0 "register_operand")
1650 (extend_types:SI (match_operand:small_int_modes 1 "rx_restricted_mem_operand")))
1651 (set (match_operand:SI 2 "register_operand")
1652 (memex_nocc:SI (match_dup 2)
1653 (match_dup 0)))]
1654 "peep2_regno_dead_p (2, REGNO (operands[0]))"
1655 [(set:SI (match_dup 2)
1656 (memex_nocc:SI (match_dup 2)
1657 (extend_types:SI (match_dup 1))))]
1658 )
1659
1660 (define_insn "<memex_commutative:code>si3_<extend_types:code><small_int_modes:mode>"
1661 [(set (match_operand:SI 0 "register_operand" "=r")
1662 (memex_commutative:SI (match_operand:SI 1 "register_operand" "%0")
1663 (extend_types:SI (match_operand:small_int_modes 2 "rx_restricted_mem_operand" "Q"))))
1664 (clobber (reg:CC CC_REG))]
1665 ""
1666 "<memex_commutative:op>\t%<extend_types:letter>2, %0"
1667 [(set_attr "timings" "33")
1668 (set_attr "length" "5")] ;; This length is corrected in rx_adjust_insn_length
1669 )
1670
1671 (define_insn "<memex_noncomm:code>si3_<extend_types:code><small_int_modes:mode>"
1672 [(set (match_operand:SI 0 "register_operand" "=r")
1673 (memex_noncomm:SI (match_operand:SI 1 "register_operand" "0")
1674 (extend_types:SI (match_operand:small_int_modes 2 "rx_restricted_mem_operand" "Q"))))
1675 (clobber (reg:CC CC_REG))]
1676 ""
1677 "<memex_noncomm:op>\t%<extend_types:letter>2, %0"
1678 [(set_attr "timings" "33")
1679 (set_attr "length" "5")] ;; This length is corrected in rx_adjust_insn_length
1680 )
1681
1682 (define_insn "<memex_nocc:code>si3_<extend_types:code><small_int_modes:mode>"
1683 [(set (match_operand:SI 0 "register_operand" "=r")
1684 (memex_nocc:SI (match_operand:SI 1 "register_operand" "%0")
1685 (extend_types:SI (match_operand:small_int_modes 2 "rx_restricted_mem_operand" "Q"))))]
1686 ""
1687 "<memex_nocc:op>\t%<extend_types:letter>2, %0"
1688 [(set_attr "timings" "33")
1689 (set_attr "length" "5")] ;; This length is corrected in rx_adjust_insn_length
1690 )
1691
1692 (define_peephole2
1693 [(set (match_operand:SI 0 "register_operand")
1694 (extend_types:SI (match_operand:small_int_modes 1 "rx_restricted_mem_operand")))
1695 (set (reg:CC CC_REG)
1696 (compare:CC (match_operand:SI 2 "register_operand")
1697 (match_dup 0)))]
1698 "peep2_regno_dead_p (2, REGNO (operands[0]))"
1699 [(set (reg:CC CC_REG)
1700 (compare:CC (match_dup 2)
1701 (extend_types:SI (match_dup 1))))]
1702 )
1703
1704 ;; Convert:
1705 ;; (set (reg1) (sign_extend (mem))
1706 ;; (set (reg2) (zero_extend (reg1))
1707 ;; into
1708 ;; (set (reg2) (zero_extend (mem)))
1709 (define_peephole2
1710 [(set (match_operand:SI 0 "register_operand")
1711 (sign_extend:SI (match_operand:small_int_modes 1 "memory_operand")))
1712 (set (match_operand:SI 2 "register_operand")
1713 (zero_extend:SI (match_operand:small_int_modes 3 "register_operand")))]
1714 "REGNO (operands[0]) == REGNO (operands[3])
1715 && (REGNO (operands[0]) == REGNO (operands[2])
1716 || peep2_regno_dead_p (2, REGNO (operands[0])))"
1717 [(set (match_dup 2)
1718 (zero_extend:SI (match_dup 1)))]
1719 )
1720
1721 ;; Remove the redundant sign extension from:
1722 ;; (set (reg) (extend (mem)))
1723 ;; (set (reg) (extend (reg)))
1724 (define_peephole2
1725 [(set (match_operand:SI 0 "register_operand")
1726 (extend_types:SI (match_operand:small_int_modes 1 "memory_operand")))
1727 (set (match_dup 0)
1728 (extend_types:SI (match_operand:small_int_modes 2 "register_operand")))]
1729 "REGNO (operands[0]) == REGNO (operands[2])"
1730 [(set (match_dup 0) (extend_types:SI (match_dup 1)))]
1731 )
1732
1733 (define_insn "comparesi3_<extend_types:code><small_int_modes:mode>"
1734 [(set (reg:CC CC_REG)
1735 (compare:CC (match_operand:SI 0 "register_operand" "=r")
1736 (extend_types:SI (match_operand:small_int_modes 1 "rx_restricted_mem_operand" "Q"))))]
1737 ""
1738 "cmp\t%<extend_types:letter>1, %0"
1739 [(set_attr "timings" "33")
1740 (set_attr "length" "5")] ;; This length is corrected in rx_adjust_insn_length
1741 )
1742 \f
1743 ;; Floating Point Instructions
1744
1745 (define_insn "addsf3"
1746 [(set (match_operand:SF 0 "register_operand" "=r,r,r")
1747 (plus:SF (match_operand:SF 1 "register_operand" "%0,0,0")
1748 (match_operand:SF 2 "rx_source_operand" "r,F,Q")))
1749 (clobber (reg:CC CC_REG))]
1750 "ALLOW_RX_FPU_INSNS"
1751 "fadd\t%2, %0"
1752 [(set_attr "timings" "44,44,66")
1753 (set_attr "length" "3,7,5")]
1754 )
1755
1756 (define_insn "divsf3"
1757 [(set (match_operand:SF 0 "register_operand" "=r,r,r")
1758 (div:SF (match_operand:SF 1 "register_operand" "0,0,0")
1759 (match_operand:SF 2 "rx_source_operand" "r,F,Q")))
1760 (clobber (reg:CC CC_REG))]
1761 "ALLOW_RX_FPU_INSNS"
1762 "fdiv\t%2, %0"
1763 [(set_attr "timings" "1616,1616,1818")
1764 (set_attr "length" "3,7,5")]
1765 )
1766
1767 (define_insn "mulsf3"
1768 [(set (match_operand:SF 0 "register_operand" "=r,r,r")
1769 (mult:SF (match_operand:SF 1 "register_operand" "%0,0,0")
1770 (match_operand:SF 2 "rx_source_operand" "r,F,Q")))
1771 (clobber (reg:CC CC_REG))]
1772 "ALLOW_RX_FPU_INSNS"
1773 "fmul\t%2, %0"
1774 [(set_attr "timings" "33,33,55")
1775 (set_attr "length" "3,7,5")]
1776 )
1777
1778 (define_insn "subsf3"
1779 [(set (match_operand:SF 0 "register_operand" "=r,r,r")
1780 (minus:SF (match_operand:SF 1 "register_operand" "0,0,0")
1781 (match_operand:SF 2 "rx_source_operand" "r,F,Q")))
1782 (clobber (reg:CC CC_REG))]
1783 "ALLOW_RX_FPU_INSNS"
1784 "fsub\t%Q2, %0"
1785 [(set_attr "timings" "44,44,66")
1786 (set_attr "length" "3,7,5")]
1787 )
1788
1789 (define_insn "fix_truncsfsi2"
1790 [(set (match_operand:SI 0 "register_operand" "=r,r")
1791 (fix:SI (match_operand:SF 1 "rx_compare_operand" "r,Q")))
1792 (clobber (reg:CC CC_REG))]
1793 "ALLOW_RX_FPU_INSNS"
1794 "ftoi\t%Q1, %0"
1795 [(set_attr "timings" "22,44")
1796 (set_attr "length" "3,5")]
1797 )
1798
1799 (define_insn "floatsisf2"
1800 [(set (match_operand:SF 0 "register_operand" "=r,r")
1801 (float:SF (match_operand:SI 1 "rx_compare_operand" "r,Q")))
1802 (clobber (reg:CC CC_REG))]
1803 "ALLOW_RX_FPU_INSNS"
1804 "itof\t%Q1, %0"
1805 [(set_attr "timings" "22,44")
1806 (set_attr "length" "3,6")]
1807 )
1808 \f
1809 ;; Bit manipulation instructions.
1810
1811 ;; ??? The *_in_memory patterns will not be matched without further help.
1812 ;; At one time we had the insv expander generate them, but I suspect that
1813 ;; in general we get better performance by exposing the register load to
1814 ;; the optimizers.
1815 ;;
1816 ;; An alternate solution would be to re-organize these patterns such
1817 ;; that allow both register and memory operands. This would allow the
1818 ;; register allocator to spill and not load the register operand. This
1819 ;; would be possible only for operations for which we have a constant
1820 ;; bit offset, so that we can adjust the address by ofs/8 and replace
1821 ;; the offset in the insn by ofs%8.
1822
1823 (define_insn "*bitset"
1824 [(set (match_operand:SI 0 "register_operand" "=r")
1825 (ior:SI (ashift:SI (const_int 1)
1826 (match_operand:SI 1 "rx_shift_operand" "ri"))
1827 (match_operand:SI 2 "register_operand" "0")))]
1828 ""
1829 "bset\t%1, %0"
1830 [(set_attr "length" "3")]
1831 )
1832
1833 (define_insn "*bitset_in_memory"
1834 [(set (match_operand:QI 0 "rx_restricted_mem_operand" "+Q")
1835 (ior:QI (ashift:QI (const_int 1)
1836 (match_operand:QI 1 "nonmemory_operand" "ri"))
1837 (match_dup 0)))]
1838 ""
1839 "bset\t%1, %0.B"
1840 [(set_attr "length" "3")
1841 (set_attr "timings" "33")]
1842 )
1843
1844 (define_insn "*bitinvert"
1845 [(set (match_operand:SI 0 "register_operand" "=r")
1846 (xor:SI (ashift:SI (const_int 1)
1847 (match_operand:SI 1 "rx_shift_operand" "ri"))
1848 (match_operand:SI 2 "register_operand" "0")))]
1849 ""
1850 "bnot\t%1, %0"
1851 [(set_attr "length" "3")]
1852 )
1853
1854 (define_insn "*bitinvert_in_memory"
1855 [(set (match_operand:QI 0 "rx_restricted_mem_operand" "+Q")
1856 (xor:QI (ashift:QI (const_int 1)
1857 (match_operand:QI 1 "nonmemory_operand" "ri"))
1858 (match_dup 0)))]
1859 ""
1860 "bnot\t%1, %0.B"
1861 [(set_attr "length" "5")
1862 (set_attr "timings" "33")]
1863 )
1864
1865 (define_insn "*bitclr"
1866 [(set (match_operand:SI 0 "register_operand" "=r")
1867 (and:SI (not:SI
1868 (ashift:SI
1869 (const_int 1)
1870 (match_operand:SI 1 "rx_shift_operand" "ri")))
1871 (match_operand:SI 2 "register_operand" "0")))]
1872 ""
1873 "bclr\t%1, %0"
1874 [(set_attr "length" "3")]
1875 )
1876
1877 (define_insn "*bitclr_in_memory"
1878 [(set (match_operand:QI 0 "rx_restricted_mem_operand" "+Q")
1879 (and:QI (not:QI
1880 (ashift:QI
1881 (const_int 1)
1882 (match_operand:QI 1 "nonmemory_operand" "ri")))
1883 (match_dup 0)))]
1884 ""
1885 "bclr\t%1, %0.B"
1886 [(set_attr "length" "3")
1887 (set_attr "timings" "33")]
1888 )
1889
1890 (define_insn "*insv_imm"
1891 [(set (zero_extract:SI
1892 (match_operand:SI 0 "register_operand" "+r")
1893 (const_int 1)
1894 (match_operand:SI 1 "rx_shift_operand" "ri"))
1895 (match_operand:SI 2 "const_int_operand" ""))]
1896 ""
1897 {
1898 if (INTVAL (operands[2]) & 1)
1899 return "bset\t%1, %0";
1900 else
1901 return "bclr\t%1, %0";
1902 }
1903 [(set_attr "length" "3")]
1904 )
1905
1906 (define_insn_and_split "rx_insv_reg"
1907 [(set (zero_extract:SI
1908 (match_operand:SI 0 "register_operand" "+r")
1909 (const_int 1)
1910 (match_operand:SI 1 "const_int_operand" ""))
1911 (match_operand:SI 2 "register_operand" "r"))
1912 (clobber (reg:CC CC_REG))]
1913 ""
1914 "#"
1915 "reload_completed"
1916 [(set (zero_extract:SI (match_dup 0) (const_int 1) (match_dup 1))
1917 (match_dup 3))]
1918 {
1919 rtx flags, x;
1920
1921 /* Emit tst #1, op2. */
1922 flags = gen_rtx_REG (CC_ZSmode, CC_REG);
1923 x = gen_rtx_AND (SImode, operands[2], const1_rtx);
1924 x = gen_rtx_COMPARE (CC_ZSmode, x, const0_rtx);
1925 x = gen_rtx_SET (VOIDmode, flags, x);
1926 emit_insn (x);
1927
1928 /* Emit bmne. */
1929 operands[3] = gen_rtx_NE (SImode, flags, const0_rtx);
1930 })
1931
1932 (define_insn_and_split "*insv_cond"
1933 [(set (zero_extract:SI
1934 (match_operand:SI 0 "register_operand" "+r")
1935 (const_int 1)
1936 (match_operand:SI 1 "const_int_operand" ""))
1937 (match_operator:SI 4 "comparison_operator"
1938 [(match_operand:SI 2 "register_operand" "r")
1939 (match_operand:SI 3 "rx_source_operand" "riQ")]))
1940 (clobber (reg:CC CC_REG))]
1941 ""
1942 "#"
1943 "reload_completed"
1944 [(set (zero_extract:SI (match_dup 0) (const_int 1) (match_dup 1))
1945 (match_dup 4))]
1946 {
1947 rtx flags, x;
1948
1949 flags = gen_rtx_REG (CCmode, CC_REG);
1950 x = gen_rtx_COMPARE (CCmode, operands[2], operands[3]);
1951 x = gen_rtx_SET (VOIDmode, flags, x);
1952 emit_insn (x);
1953
1954 operands[4] = gen_rtx_fmt_ee (GET_CODE (operands[4]), SImode,
1955 flags, const0_rtx);
1956 })
1957
1958 (define_insn "*bmcc"
1959 [(set (zero_extract:SI
1960 (match_operand:SI 0 "register_operand" "+r")
1961 (const_int 1)
1962 (match_operand:SI 1 "const_int_operand" ""))
1963 (match_operator:SI 2 "comparison_operator"
1964 [(reg CC_REG) (const_int 0)]))]
1965 "reload_completed"
1966 "bm%B2\t%1, %0"
1967 [(set_attr "length" "3")]
1968 )
1969
1970 ;; Work around the fact that X=Y<0 is preferentially expanded as a shift.
1971 (define_insn_and_split "*insv_cond_lt"
1972 [(set (zero_extract:SI
1973 (match_operand:SI 0 "register_operand" "+r")
1974 (const_int 1)
1975 (match_operand:SI 1 "const_int_operand" ""))
1976 (match_operator:SI 3 "rshift_operator"
1977 [(match_operand:SI 2 "register_operand" "r")
1978 (const_int 31)]))
1979 (clobber (reg:CC CC_REG))]
1980 ""
1981 "#"
1982 ""
1983 [(parallel [(set (zero_extract:SI (match_dup 0) (const_int 1) (match_dup 1))
1984 (lt:SI (match_dup 2) (const_int 0)))
1985 (clobber (reg:CC CC_REG))])]
1986 ""
1987 )
1988
1989 (define_expand "insv"
1990 [(set (zero_extract:SI
1991 (match_operand:SI 0 "register_operand") ;; Destination
1992 (match_operand:SI 1 "const_int_operand") ;; # of bits to set
1993 (match_operand:SI 2 "nonmemory_operand")) ;; Starting bit
1994 (match_operand:SI 3 "nonmemory_operand"))] ;; Bits to insert
1995 ""
1996 {
1997 /* We only handle single-bit inserts. */
1998 if (!CONST_INT_P (operands[1]) || INTVAL (operands[1]) != 1)
1999 FAIL;
2000
2001 /* Either the bit to insert or the position must be constant. */
2002 if (CONST_INT_P (operands[3]))
2003 operands[3] = GEN_INT (INTVAL (operands[3]) & 1);
2004 else if (CONST_INT_P (operands[2]))
2005 {
2006 emit_insn (gen_rx_insv_reg (operands[0], operands[2], operands[3]));
2007 DONE;
2008 }
2009 else
2010 FAIL;
2011 })
2012 \f
2013 ;; Atomic exchange operation.
2014
2015 (define_insn "sync_lock_test_and_setsi"
2016 [(set (match_operand:SI 0 "register_operand" "=r,r")
2017 (match_operand:SI 1 "rx_compare_operand" "=r,Q"))
2018 (set (match_dup 1)
2019 (match_operand:SI 2 "register_operand" "0,0"))]
2020 ""
2021 "xchg\t%1, %0"
2022 [(set_attr "length" "3,6")
2023 (set_attr "timings" "22")]
2024 )
2025 \f
2026 ;; Block move functions.
2027
2028 (define_expand "movstr"
2029 [(set (match_operand:BLK 1 "memory_operand") ;; Dest
2030 (match_operand:BLK 2 "memory_operand")) ;; Source
2031 (use (match_operand:SI 0 "register_operand")) ;; Updated Dest
2032 ]
2033 ""
2034 {
2035 rtx addr1 = gen_rtx_REG (SImode, 1);
2036 rtx addr2 = gen_rtx_REG (SImode, 2);
2037 rtx len = gen_rtx_REG (SImode, 3);
2038 rtx dest_copy = gen_reg_rtx (SImode);
2039
2040 emit_move_insn (len, GEN_INT (-1));
2041 emit_move_insn (addr1, force_operand (XEXP (operands[1], 0), NULL_RTX));
2042 emit_move_insn (addr2, force_operand (XEXP (operands[2], 0), NULL_RTX));
2043 operands[1] = replace_equiv_address_nv (operands[1], addr1);
2044 operands[2] = replace_equiv_address_nv (operands[2], addr2);
2045 emit_move_insn (dest_copy, addr1);
2046 emit_insn (gen_rx_movstr ());
2047 emit_move_insn (len, GEN_INT (-1));
2048 emit_insn (gen_rx_strend (operands[0], dest_copy));
2049 DONE;
2050 }
2051 )
2052
2053 (define_insn "rx_movstr"
2054 [(set (mem:BLK (reg:SI 1))
2055 (mem:BLK (reg:SI 2)))
2056 (unspec_volatile:BLK [(reg:SI 1) (reg:SI 2) (reg:SI 3)] UNSPEC_MOVSTR)
2057 (clobber (reg:SI 1))
2058 (clobber (reg:SI 2))
2059 (clobber (reg:SI 3))]
2060 ""
2061 "smovu"
2062 [(set_attr "length" "2")
2063 (set_attr "timings" "1111")] ;; The timing is a guesstimate.
2064 )
2065
2066 (define_insn "rx_strend"
2067 [(set (match_operand:SI 0 "register_operand" "=r")
2068 (unspec_volatile:SI [(match_operand:SI 1 "register_operand" "r")
2069 (reg:SI 3)] UNSPEC_STRLEN))
2070 (clobber (reg:SI 1))
2071 (clobber (reg:SI 2))
2072 (clobber (reg:SI 3))
2073 (clobber (reg:CC CC_REG))
2074 ]
2075 ""
2076 "mov\t%1, r1\n\tmov\t#0, r2\n\tsuntil.b\n\tmov\tr1, %0\n\tsub\t#1, %0"
2077 [(set_attr "length" "10")
2078 (set_attr "timings" "1111")] ;; The timing is a guesstimate.
2079 )
2080
2081 (define_expand "movmemsi"
2082 [(parallel
2083 [(set (match_operand:BLK 0 "memory_operand") ;; Dest
2084 (match_operand:BLK 1 "memory_operand")) ;; Source
2085 (use (match_operand:SI 2 "register_operand")) ;; Length in bytes
2086 (match_operand 3 "immediate_operand") ;; Align
2087 (unspec_volatile:BLK [(reg:SI 1) (reg:SI 2) (reg:SI 3)] UNSPEC_MOVMEM)]
2088 )]
2089 ""
2090 {
2091 rtx addr1 = gen_rtx_REG (SImode, 1);
2092 rtx addr2 = gen_rtx_REG (SImode, 2);
2093 rtx len = gen_rtx_REG (SImode, 3);
2094
2095 /* Do not use when the source or destination are volatile - the SMOVF
2096 instruction will read and write in word sized blocks, which may be
2097 outside of the valid address range. */
2098 if (MEM_P (operands[0]) && MEM_VOLATILE_P (operands[0]))
2099 FAIL;
2100 if (MEM_P (operands[1]) && MEM_VOLATILE_P (operands[1]))
2101 FAIL;
2102
2103 if (REG_P (operands[0]) && (REGNO (operands[0]) == 2
2104 || REGNO (operands[0]) == 3))
2105 FAIL;
2106 if (REG_P (operands[1]) && (REGNO (operands[1]) == 1
2107 || REGNO (operands[1]) == 3))
2108 FAIL;
2109 if (REG_P (operands[2]) && (REGNO (operands[2]) == 1
2110 || REGNO (operands[2]) == 2))
2111 FAIL;
2112
2113 emit_move_insn (addr1, force_operand (XEXP (operands[0], 0), NULL_RTX));
2114 emit_move_insn (addr2, force_operand (XEXP (operands[1], 0), NULL_RTX));
2115 emit_move_insn (len, force_operand (operands[2], NULL_RTX));
2116 operands[0] = replace_equiv_address_nv (operands[0], addr1);
2117 operands[1] = replace_equiv_address_nv (operands[1], addr2);
2118 emit_insn (gen_rx_movmem ());
2119 DONE;
2120 }
2121 )
2122
2123 (define_insn "rx_movmem"
2124 [(set (mem:BLK (reg:SI 1))
2125 (mem:BLK (reg:SI 2)))
2126 (use (reg:SI 3))
2127 (unspec_volatile:BLK [(reg:SI 1) (reg:SI 2) (reg:SI 3)] UNSPEC_MOVMEM)
2128 (clobber (reg:SI 1))
2129 (clobber (reg:SI 2))
2130 (clobber (reg:SI 3))]
2131 ""
2132 "smovf"
2133 [(set_attr "length" "2")
2134 (set_attr "timings" "1111")] ;; The timing is a guesstimate.
2135 )
2136
2137 (define_expand "setmemsi"
2138 [(set (match_operand:BLK 0 "memory_operand") ;; Dest
2139 (match_operand:QI 2 "nonmemory_operand")) ;; Value
2140 (use (match_operand:SI 1 "nonmemory_operand")) ;; Length
2141 (match_operand 3 "immediate_operand") ;; Align
2142 (unspec_volatile:BLK [(reg:SI 1) (reg:SI 2) (reg:SI 3)] UNSPEC_SETMEM)]
2143 ""
2144 {
2145 rtx addr = gen_rtx_REG (SImode, 1);
2146 rtx val = gen_rtx_REG (QImode, 2);
2147 rtx len = gen_rtx_REG (SImode, 3);
2148
2149 emit_move_insn (addr, force_operand (XEXP (operands[0], 0), NULL_RTX));
2150 emit_move_insn (len, force_operand (operands[1], NULL_RTX));
2151 emit_move_insn (val, operands[2]);
2152 emit_insn (gen_rx_setmem ());
2153 DONE;
2154 }
2155 )
2156
2157 (define_insn "rx_setmem"
2158 [(set (mem:BLK (reg:SI 1))
2159 (unspec_volatile:BLK [(reg:SI 1) (reg:SI 2) (reg:SI 3)] UNSPEC_SETMEM))
2160 (clobber (reg:SI 1))
2161 (clobber (reg:SI 3))]
2162 ""
2163 "sstr.b"
2164 [(set_attr "length" "2")
2165 (set_attr "timings" "1111")] ;; The timing is a guesstimate.
2166 )
2167
2168 (define_expand "cmpstrnsi"
2169 [(set (match_operand:SI 0 "register_operand") ;; Result
2170 (unspec_volatile:SI [(match_operand:BLK 1 "memory_operand") ;; String1
2171 (match_operand:BLK 2 "memory_operand")] ;; String2
2172 UNSPEC_CMPSTRN))
2173 (use (match_operand:SI 3 "register_operand")) ;; Max Length
2174 (match_operand:SI 4 "immediate_operand")] ;; Known Align
2175 ""
2176 {
2177 rtx str1 = gen_rtx_REG (SImode, 1);
2178 rtx str2 = gen_rtx_REG (SImode, 2);
2179 rtx len = gen_rtx_REG (SImode, 3);
2180
2181 emit_move_insn (str1, force_operand (XEXP (operands[1], 0), NULL_RTX));
2182 emit_move_insn (str2, force_operand (XEXP (operands[2], 0), NULL_RTX));
2183 emit_move_insn (len, force_operand (operands[3], NULL_RTX));
2184
2185 emit_insn (gen_rx_cmpstrn (operands[0], operands[1], operands[2]));
2186 DONE;
2187 }
2188 )
2189
2190 (define_expand "cmpstrsi"
2191 [(set (match_operand:SI 0 "register_operand") ;; Result
2192 (unspec_volatile:SI [(match_operand:BLK 1 "memory_operand") ;; String1
2193 (match_operand:BLK 2 "memory_operand")] ;; String2
2194 UNSPEC_CMPSTRN))
2195 (match_operand:SI 3 "immediate_operand")] ;; Known Align
2196 ""
2197 {
2198 rtx str1 = gen_rtx_REG (SImode, 1);
2199 rtx str2 = gen_rtx_REG (SImode, 2);
2200 rtx len = gen_rtx_REG (SImode, 3);
2201
2202 emit_move_insn (str1, force_reg (SImode, XEXP (operands[1], 0)));
2203 emit_move_insn (str2, force_reg (SImode, XEXP (operands[2], 0)));
2204 emit_move_insn (len, GEN_INT (-1));
2205
2206 emit_insn (gen_rx_cmpstrn (operands[0], operands[1], operands[2]));
2207 DONE;
2208 }
2209 )
2210
2211 (define_insn "rx_cmpstrn"
2212 [(set (match_operand:SI 0 "register_operand" "=r")
2213 (unspec_volatile:SI [(reg:SI 1) (reg:SI 2) (reg:SI 3)]
2214 UNSPEC_CMPSTRN))
2215 (use (match_operand:BLK 1 "memory_operand" "m"))
2216 (use (match_operand:BLK 2 "memory_operand" "m"))
2217 (clobber (reg:SI 1))
2218 (clobber (reg:SI 2))
2219 (clobber (reg:SI 3))
2220 (clobber (reg:CC CC_REG))]
2221 ""
2222 "scmpu ; Perform the string comparison
2223 mov #-1, %0 ; Set up -1 result (which cannot be created
2224 ; by the SC insn)
2225 bnc ?+ ; If Carry is not set skip over
2226 scne.L %0 ; Set result based on Z flag
2227 ?:
2228 "
2229 [(set_attr "length" "9")
2230 (set_attr "timings" "1111")] ;; The timing is a guesstimate.
2231 )
2232 \f
2233 ;; Builtin Functions
2234 ;;
2235 ;; GCC does not have the ability to generate the following instructions
2236 ;; on its own so they are provided as builtins instead. To use them from
2237 ;; a program for example invoke them as __builtin_rx_<insn_name>. For
2238 ;; example:
2239 ;;
2240 ;; int short_byte_swap (int arg) { return __builtin_rx_revw (arg); }
2241
2242 ;;---------- Accumulator Support ------------------------
2243
2244 ;; Multiply & Accumulate (high)
2245 (define_insn "machi"
2246 [(unspec:SI [(match_operand:SI 0 "register_operand" "r")
2247 (match_operand:SI 1 "register_operand" "r")]
2248 UNSPEC_BUILTIN_MACHI)]
2249 ""
2250 "machi\t%0, %1"
2251 [(set_attr "length" "3")]
2252 )
2253
2254 ;; Multiply & Accumulate (low)
2255 (define_insn "maclo"
2256 [(unspec:SI [(match_operand:SI 0 "register_operand" "r")
2257 (match_operand:SI 1 "register_operand" "r")]
2258 UNSPEC_BUILTIN_MACLO)]
2259 ""
2260 "maclo\t%0, %1"
2261 [(set_attr "length" "3")]
2262 )
2263
2264 ;; Multiply (high)
2265 (define_insn "mulhi"
2266 [(unspec:SI [(match_operand:SI 0 "register_operand" "r")
2267 (match_operand:SI 1 "register_operand" "r")]
2268 UNSPEC_BUILTIN_MULHI)]
2269 ""
2270 "mulhi\t%0, %1"
2271 [(set_attr "length" "3")]
2272 )
2273
2274 ;; Multiply (low)
2275 (define_insn "mullo"
2276 [(unspec:SI [(match_operand:SI 0 "register_operand" "r")
2277 (match_operand:SI 1 "register_operand" "r")]
2278 UNSPEC_BUILTIN_MULLO)]
2279 ""
2280 "mullo\t%0, %1"
2281 [(set_attr "length" "3")]
2282 )
2283
2284 ;; Move from Accumulator (high)
2285 (define_insn "mvfachi"
2286 [(set (match_operand:SI 0 "register_operand" "=r")
2287 (unspec:SI [(const_int 0)]
2288 UNSPEC_BUILTIN_MVFACHI))]
2289 ""
2290 "mvfachi\t%0"
2291 [(set_attr "length" "3")]
2292 )
2293
2294 ;; Move from Accumulator (middle)
2295 (define_insn "mvfacmi"
2296 [(set (match_operand:SI 0 "register_operand" "=r")
2297 (unspec:SI [(const_int 0)]
2298 UNSPEC_BUILTIN_MVFACMI))]
2299 ""
2300 "mvfacmi\t%0"
2301 [(set_attr "length" "3")]
2302 )
2303
2304 ;; Move to Accumulator (high)
2305 (define_insn "mvtachi"
2306 [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")]
2307 UNSPEC_BUILTIN_MVTACHI)]
2308 ""
2309 "mvtachi\t%0"
2310 [(set_attr "length" "3")]
2311 )
2312
2313 ;; Move to Accumulator (low)
2314 (define_insn "mvtaclo"
2315 [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")]
2316 UNSPEC_BUILTIN_MVTACLO)]
2317 ""
2318 "mvtaclo\t%0"
2319 [(set_attr "length" "3")]
2320 )
2321
2322 ;; Round Accumulator
2323 (define_insn "racw"
2324 [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i")]
2325 UNSPEC_BUILTIN_RACW)]
2326 ""
2327 "racw\t%0"
2328 [(set_attr "length" "3")]
2329 )
2330
2331 ;; Repeat multiply and accumulate
2332 (define_insn "rmpa"
2333 [(unspec:SI [(const_int 0) (reg:SI 1) (reg:SI 2) (reg:SI 3)
2334 (reg:SI 4) (reg:SI 5) (reg:SI 6)]
2335 UNSPEC_BUILTIN_RMPA)
2336 (clobber (reg:SI 1))
2337 (clobber (reg:SI 2))
2338 (clobber (reg:SI 3))]
2339 ""
2340 "rmpa"
2341 [(set_attr "length" "2")
2342 (set_attr "timings" "1010")]
2343 )
2344
2345 ;;---------- Arithmetic ------------------------
2346
2347 ;; Byte swap (two 16-bit values).
2348 (define_insn "revw"
2349 [(set (match_operand:SI 0 "register_operand" "=r")
2350 (unspec:SI [(match_operand:SI 1 "register_operand" "r")]
2351 UNSPEC_BUILTIN_REVW))]
2352 ""
2353 "revw\t%1, %0"
2354 [(set_attr "length" "3")]
2355 )
2356
2357 ;; Round to integer.
2358 (define_insn "lrintsf2"
2359 [(set (match_operand:SI 0 "register_operand" "=r,r")
2360 (unspec:SI [(match_operand:SF 1 "rx_compare_operand" "r,Q")]
2361 UNSPEC_BUILTIN_ROUND))
2362 (clobber (reg:CC CC_REG))]
2363 ""
2364 "round\t%1, %0"
2365 [(set_attr "timings" "22,44")
2366 (set_attr "length" "3,5")]
2367 )
2368
2369 ;;---------- Control Registers ------------------------
2370
2371 ;; Clear Processor Status Word
2372 (define_insn "clrpsw"
2373 [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i")]
2374 UNSPEC_BUILTIN_CLRPSW)
2375 (clobber (reg:CC CC_REG))]
2376 ""
2377 "clrpsw\t%F0"
2378 [(set_attr "length" "2")]
2379 )
2380
2381 ;; Set Processor Status Word
2382 (define_insn "setpsw"
2383 [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i")]
2384 UNSPEC_BUILTIN_SETPSW)
2385 (clobber (reg:CC CC_REG))]
2386 ""
2387 "setpsw\t%F0"
2388 [(set_attr "length" "2")]
2389 )
2390
2391 ;; Move from control register
2392 (define_insn "mvfc"
2393 [(set (match_operand:SI 0 "register_operand" "=r")
2394 (unspec_volatile:SI [(match_operand:SI 1 "immediate_operand" "i")]
2395 UNSPEC_BUILTIN_MVFC))]
2396 ""
2397 "mvfc\t%C1, %0"
2398 [(set_attr "length" "3")]
2399 )
2400
2401 ;; Move to control register
2402 (define_insn "mvtc"
2403 [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i,i")
2404 (match_operand:SI 1 "nonmemory_operand" "r,i")]
2405 UNSPEC_BUILTIN_MVTC)]
2406 ""
2407 "mvtc\t%1, %C0"
2408 [(set_attr "length" "3,7")]
2409 ;; Ignore possible clobbering of the comparison flags in the
2410 ;; PSW register. This is a cc0 target so any cc0 setting
2411 ;; instruction will always be paired with a cc0 user, without
2412 ;; the possibility of this instruction being placed in between
2413 ;; them.
2414 )
2415
2416 ;; Move to interrupt priority level
2417 (define_insn "mvtipl"
2418 [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "Uint04")]
2419 UNSPEC_BUILTIN_MVTIPL)]
2420 ""
2421 "mvtipl\t%0"
2422 [(set_attr "length" "3")]
2423 )
2424
2425 ;;---------- Interrupts ------------------------
2426
2427 ;; Break
2428 (define_insn "brk"
2429 [(unspec_volatile [(const_int 0)]
2430 UNSPEC_BUILTIN_BRK)]
2431 ""
2432 "brk"
2433 [(set_attr "length" "1")
2434 (set_attr "timings" "66")]
2435 )
2436
2437 ;; Interrupt
2438 (define_insn "int"
2439 [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i")]
2440 UNSPEC_BUILTIN_INT)]
2441 ""
2442 "int\t%0"
2443 [(set_attr "length" "3")]
2444 )
2445
2446 ;; Wait
2447 (define_insn "wait"
2448 [(unspec_volatile [(const_int 0)]
2449 UNSPEC_BUILTIN_WAIT)]
2450 ""
2451 "wait"
2452 [(set_attr "length" "2")]
2453 )
2454
2455 ;;---------- CoProcessor Support ------------------------
2456
2457 ;; FIXME: The instructions are currently commented out because
2458 ;; the bit patterns have not been finalized, so the assembler
2459 ;; does not support them. Once they are decided and the assembler
2460 ;; supports them, enable the instructions here.
2461
2462 ;; Move from co-processor register
2463 (define_insn "mvfcp"
2464 [(set (match_operand:SI 0 "register_operand" "=r")
2465 (unspec:SI [(match_operand:SI 1 "immediate_operand" "i")
2466 (match_operand:SI 2 "immediate_operand" "i")]
2467 UNSPEC_BUILTIN_MVFCP))]
2468 ""
2469 "; mvfcp\t%1, %0, %2"
2470 [(set_attr "length" "5")]
2471 )
2472
2473 ;;---------- Misc ------------------------
2474
2475 ;; Required by cfglayout.c...
2476 (define_insn "nop"
2477 [(const_int 0)]
2478 ""
2479 "nop"
2480 [(set_attr "length" "1")]
2481 )