1 ;; Machine Description for Renesas RX processors
2 ;; Copyright (C) 2008, 2009, 2010, 2011, 2012
3 ;; Free Software Foundation, Inc.
4 ;; Contributed by Red Hat.
6 ;; This file is part of GCC.
8 ;; GCC is free software; you can redistribute it and/or modify
9 ;; it under the terms of the GNU General Public License as published by
10 ;; the Free Software Foundation; either version 3, or (at your option)
13 ;; GCC is distributed in the hope that it will be useful,
14 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
15 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 ;; GNU General Public License for more details.
18 ;; You should have received a copy of the GNU General Public License
19 ;; along with GCC; see the file COPYING3. If not see
20 ;; <http://www.gnu.org/licenses/>.
23 ;; This code iterator is used for sign- and zero- extensions.
24 (define_mode_iterator small_int_modes [(HI "") (QI "")])
26 ;; This code iterator is used for max and min operations.
27 (define_mode_iterator int_modes [(SI "") (HI "") (QI "")])
29 ;; We do not handle DFmode here because it is either
30 ;; the same as SFmode, or if -m64bit-doubles is active
31 ;; then all operations on doubles have to be handled by
33 (define_mode_iterator register_modes
34 [(SF "ALLOW_RX_FPU_INSNS") (SI "") (HI "") (QI "")])
55 (UNSPEC_BUILTIN_BRK 30)
56 (UNSPEC_BUILTIN_CLRPSW 31)
57 (UNSPEC_BUILTIN_INT 32)
58 (UNSPEC_BUILTIN_MACHI 33)
59 (UNSPEC_BUILTIN_MACLO 34)
60 (UNSPEC_BUILTIN_MULHI 35)
61 (UNSPEC_BUILTIN_MULLO 36)
62 (UNSPEC_BUILTIN_MVFACHI 37)
63 (UNSPEC_BUILTIN_MVFACMI 38)
64 (UNSPEC_BUILTIN_MVFC 39)
65 (UNSPEC_BUILTIN_MVFCP 40)
66 (UNSPEC_BUILTIN_MVTACHI 41)
67 (UNSPEC_BUILTIN_MVTACLO 42)
68 (UNSPEC_BUILTIN_MVTC 43)
69 (UNSPEC_BUILTIN_MVTIPL 44)
70 (UNSPEC_BUILTIN_RACW 45)
71 (UNSPEC_BUILTIN_REVW 46)
72 (UNSPEC_BUILTIN_RMPA 47)
73 (UNSPEC_BUILTIN_ROUND 48)
74 (UNSPEC_BUILTIN_SAT 49)
75 (UNSPEC_BUILTIN_SETPSW 50)
76 (UNSPEC_BUILTIN_WAIT 51)
82 (define_attr "length" "" (const_int 8))
84 (include "predicates.md")
85 (include "constraints.md")
87 ;; Pipeline description.
89 ;; The RX only has a single pipeline. It has five stages (fetch,
90 ;; decode, execute, memory access, writeback) each of which normally
91 ;; takes a single CPU clock cycle.
93 ;; The timings attribute consists of two numbers, the first is the
94 ;; throughput, which is the number of cycles the instruction takes
95 ;; to execute and generate a result. The second is the latency
96 ;; which is the effective number of cycles the instruction takes to
97 ;; execute if its result is used by the following instruction. The
98 ;; latency is always greater than or equal to the throughput.
99 ;; These values were taken from tables 2.13 and 2.14 in section 2.8
100 ;; of the RX610 Group Hardware Manual v0.11
102 ;; Note - it would be nice to use strings rather than integers for
103 ;; the possible values of this attribute, so that we can have the
104 ;; gcc build mechanism check for values that are not supported by
105 ;; the reservations below. But this will not work because the code
106 ;; in rx_adjust_sched_cost() needs integers not strings.
108 (define_attr "timings" "" (const_int 11))
110 (define_automaton "pipelining")
111 (define_cpu_unit "throughput" "pipelining")
113 (define_insn_reservation "throughput__1_latency__1" 1
114 (eq_attr "timings" "11") "throughput")
115 (define_insn_reservation "throughput__1_latency__2" 2
116 (eq_attr "timings" "12") "throughput,nothing")
117 (define_insn_reservation "throughput__2_latency__2" 1
118 (eq_attr "timings" "22") "throughput*2")
119 (define_insn_reservation "throughput__3_latency__3" 1
120 (eq_attr "timings" "33") "throughput*3")
121 (define_insn_reservation "throughput__3_latency__4" 2
122 (eq_attr "timings" "34") "throughput*3,nothing")
123 (define_insn_reservation "throughput__4_latency__4" 1
124 (eq_attr "timings" "44") "throughput*4")
125 (define_insn_reservation "throughput__4_latency__5" 2
126 (eq_attr "timings" "45") "throughput*4,nothing")
127 (define_insn_reservation "throughput__5_latency__5" 1
128 (eq_attr "timings" "55") "throughput*5")
129 (define_insn_reservation "throughput__5_latency__6" 2
130 (eq_attr "timings" "56") "throughput*5,nothing")
131 (define_insn_reservation "throughput__6_latency__6" 1
132 (eq_attr "timings" "66") "throughput*6")
133 (define_insn_reservation "throughput_10_latency_10" 1
134 (eq_attr "timings" "1010") "throughput*10")
135 (define_insn_reservation "throughput_11_latency_11" 1
136 (eq_attr "timings" "1111") "throughput*11")
137 (define_insn_reservation "throughput_16_latency_16" 1
138 (eq_attr "timings" "1616") "throughput*16")
139 (define_insn_reservation "throughput_18_latency_18" 1
140 (eq_attr "timings" "1818") "throughput*18")
142 ;; ----------------------------------------------------------------------------
146 ;; Note - we do not specify the two instructions necessary to perform
147 ;; a compare-and-branch in the cbranchsi4 pattern because that would
148 ;; allow the comparison to be moved away from the jump before the reload
149 ;; pass has completed. That would be problematical because reload can
150 ;; generate ADDSI3 instructions which would corrupt the PSW flags.
152 (define_expand "cbranchsi4"
155 (match_operator 0 "comparison_operator"
156 [(match_operand:SI 1 "register_operand")
157 (match_operand:SI 2 "rx_source_operand")])
158 (label_ref (match_operand 3 ""))
163 (define_insn_and_split "*cbranchsi4"
166 (match_operator 3 "comparison_operator"
167 [(match_operand:SI 0 "register_operand" "r")
168 (match_operand:SI 1 "rx_source_operand" "riQ")])
169 (match_operand 2 "label_ref_operand" "")
176 rx_split_cbranch (CCmode, GET_CODE (operands[3]),
177 operands[0], operands[1], operands[2]);
181 (define_insn "*cmpsi"
182 [(set (reg:CC CC_REG)
183 (compare:CC (match_operand:SI 0 "register_operand" "r,r,r,r,r,r,r")
184 (match_operand:SI 1 "rx_source_operand" "r,Uint04,Int08,Sint16,Sint24,i,Q")))]
187 [(set_attr "timings" "11,11,11,11,11,11,33")
188 (set_attr "length" "2,2,3,4,5,6,5")]
191 ;; Canonical method for representing TST.
192 (define_insn_and_split "*cbranchsi4_tst"
195 (match_operator 3 "rx_zs_comparison_operator"
196 [(and:SI (match_operand:SI 0 "register_operand" "r")
197 (match_operand:SI 1 "rx_source_operand" "riQ"))
199 (match_operand 2 "label_ref_operand" "")
206 rx_split_cbranch (CC_ZSmode, GET_CODE (operands[3]),
207 XEXP (operands[3], 0), XEXP (operands[3], 1),
212 ;; Various other ways that GCC codes "var & const"
213 (define_insn_and_split "*cbranchsi4_tst_ext"
216 (match_operator 4 "rx_z_comparison_operator"
218 (match_operand:SI 0 "register_operand" "r")
219 (match_operand:SI 1 "rx_constshift_operand" "")
220 (match_operand:SI 2 "rx_constshift_operand" ""))
222 (match_operand 3 "label_ref_operand" "")
233 mask <<= INTVAL (operands[1]);
235 mask <<= INTVAL (operands[2]);
236 x = gen_rtx_AND (SImode, operands[0], gen_int_mode (mask, SImode));
238 rx_split_cbranch (CC_ZSmode, GET_CODE (operands[4]),
239 x, const0_rtx, operands[3]);
243 (define_insn "*tstsi"
244 [(set (reg:CC_ZS CC_REG)
246 (and:SI (match_operand:SI 0 "register_operand" "r,r,r")
247 (match_operand:SI 1 "rx_source_operand" "r,i,Q"))
251 [(set_attr "timings" "11,11,33")
252 (set_attr "length" "3,7,6")]
255 (define_expand "cbranchsf4"
258 (match_operator 0 "rx_fp_comparison_operator"
259 [(match_operand:SF 1 "register_operand")
260 (match_operand:SF 2 "rx_source_operand")])
261 (label_ref (match_operand 3 ""))
266 (define_insn_and_split "*cbranchsf4"
269 (match_operator 3 "rx_fp_comparison_operator"
270 [(match_operand:SF 0 "register_operand" "r")
271 (match_operand:SF 1 "rx_source_operand" "rFQ")])
272 (match_operand 2 "label_ref_operand" "")
276 "&& reload_completed"
279 rx_split_cbranch (CC_Fmode, GET_CODE (operands[3]),
280 operands[0], operands[1], operands[2]);
284 (define_insn "*cmpsf"
285 [(set (reg:CC_F CC_REG)
287 (match_operand:SF 0 "register_operand" "r,r,r")
288 (match_operand:SF 1 "rx_source_operand" "r,F,Q")))]
289 "ALLOW_RX_FPU_INSNS && reload_completed"
291 [(set_attr "timings" "11,11,33")
292 (set_attr "length" "3,7,5")]
295 ;; Flow Control Instructions:
297 (define_insn "*conditional_branch"
300 (match_operator 1 "comparison_operator"
301 [(reg CC_REG) (const_int 0)])
302 (label_ref (match_operand 0 "" ""))
306 [(set_attr "length" "8") ;; This length is wrong, but it is
307 ;; too hard to compute statically.
308 (set_attr "timings" "33")] ;; The timing assumes that the branch is taken.
311 ;; ----------------------------------------------------------------------------
315 (label_ref (match_operand 0 "" "")))]
318 [(set_attr "length" "4")
319 (set_attr "timings" "33")]
322 (define_insn "indirect_jump"
324 (match_operand:SI 0 "register_operand" "r"))]
327 [(set_attr "length" "2")
328 (set_attr "timings" "33")]
331 (define_insn "tablejump"
333 (match_operand:SI 0 "register_operand" "r"))
334 (use (label_ref (match_operand 1 "" "")))]
336 { return TARGET_PID ? (TARGET_AS100_SYNTAX ? "\n?:\tbra\t%0"
340 [(set_attr "timings" "33")
341 (set_attr "length" "2")]
344 (define_expand "return"
346 "rx_can_use_simple_return ()"
347 "rx_expand_epilogue (false); DONE;"
350 (define_insn "simple_return"
354 [(set_attr "length" "1")
355 (set_attr "timings" "55")]
358 ;; Unspec used so that the constant will not be invalid
359 ;; if -mmax-constant-size has been specified.
360 (define_insn "deallocate_and_return"
361 [(set (reg:SI SP_REG)
362 (plus:SI (reg:SI SP_REG)
363 (const:SI (unspec:SI [(match_operand 0 "const_int_operand" "n")] UNSPEC_CONST))))
367 [(set_attr "length" "2")
368 (set_attr "timings" "55")]
371 (define_insn "pop_and_return"
372 [(match_parallel 1 "rx_rtsd_vector"
373 [(set (reg:SI SP_REG)
374 (plus:SI (reg:SI SP_REG)
375 (match_operand:SI 0 "const_int_operand" "n")))])
379 rx_emit_stack_popm (operands, false);
382 [(set_attr "length" "3")
383 (set_attr "timings" "56")]
386 (define_insn "fast_interrupt_return"
387 [(unspec_volatile [(return)] UNSPEC_RTFI) ]
390 [(set_attr "length" "2")
391 (set_attr "timings" "33")]
394 (define_insn "exception_return"
395 [(unspec_volatile [(return)] UNSPEC_RTE) ]
398 [(set_attr "length" "2")
399 (set_attr "timings" "66")]
402 (define_insn "naked_return"
403 [(unspec_volatile [(return)] UNSPEC_NAKED) ]
405 "; Naked function: epilogue provided by programmer."
409 ;; Note - the following set of patterns do not use the "memory_operand"
410 ;; predicate or an "m" constraint because we do not allow symbol_refs
411 ;; or label_refs as legitmate memory addresses. This matches the
412 ;; behaviour of most of the RX instructions. Only the call/branch
413 ;; instructions are allowed to refer to symbols/labels directly.
414 ;; The call operands are in QImode because that is the value of
417 (define_expand "call"
418 [(call (match_operand:QI 0 "general_operand")
419 (match_operand:SI 1 "general_operand"))]
422 rtx dest = XEXP (operands[0], 0);
424 if (! rx_call_operand (dest, Pmode))
425 dest = force_reg (Pmode, dest);
426 emit_call_insn (gen_call_internal (dest));
431 (define_insn "call_internal"
432 [(call (mem:QI (match_operand:SI 0 "rx_call_operand" "r,Symbol"))
434 (clobber (reg:CC CC_REG))]
439 [(set_attr "length" "2,4")
440 (set_attr "timings" "33")]
443 (define_expand "call_value"
444 [(set (match_operand 0 "register_operand")
445 (call (match_operand:QI 1 "general_operand")
446 (match_operand:SI 2 "general_operand")))]
449 rtx dest = XEXP (operands[1], 0);
451 if (! rx_call_operand (dest, Pmode))
452 dest = force_reg (Pmode, dest);
453 emit_call_insn (gen_call_value_internal (operands[0], dest));
458 (define_insn "call_value_internal"
459 [(set (match_operand 0 "register_operand" "=r,r")
460 (call (mem:QI (match_operand:SI 1 "rx_call_operand" "r,Symbol"))
462 (clobber (reg:CC CC_REG))]
467 [(set_attr "length" "2,4")
468 (set_attr "timings" "33")]
471 ;; Note - we do not allow indirect sibcalls (with the address
472 ;; held in a register) because we cannot guarantee that the register
473 ;; chosen will be a call-used one. If it is a call-saved register,
474 ;; then the epilogue code will corrupt it by popping the saved value
476 (define_expand "sibcall"
478 [(call (mem:QI (match_operand:SI 0 "rx_symbolic_call_operand"))
479 (match_operand:SI 1 "general_operand"))
483 if (MEM_P (operands[0]))
484 operands[0] = XEXP (operands[0], 0);
485 emit_call_insn (gen_sibcall_internal (operands[0]));
490 (define_insn "sibcall_internal"
491 [(call (mem:QI (match_operand:SI 0 "rx_symbolic_call_operand" "Symbol"))
496 [(set_attr "length" "4")
497 (set_attr "timings" "33")]
500 (define_expand "sibcall_value"
502 [(set (match_operand 0 "register_operand")
503 (call (mem:QI (match_operand:SI 1 "rx_symbolic_call_operand"))
504 (match_operand:SI 2 "general_operand")))
508 if (MEM_P (operands[1]))
509 operands[1] = XEXP (operands[1], 0);
510 emit_call_insn (gen_sibcall_value_internal (operands[0], operands[1]));
515 (define_insn "sibcall_value_internal"
516 [(set (match_operand 0 "register_operand" "=r")
517 (call (mem:QI (match_operand:SI 1 "rx_symbolic_call_operand" "Symbol"))
522 [(set_attr "length" "4")
523 (set_attr "timings" "33")]
526 ;; Function Prologue/Epilogue Instructions
528 (define_expand "prologue"
531 "rx_expand_prologue (); DONE;"
534 (define_expand "epilogue"
537 "rx_expand_epilogue (false); DONE;"
540 (define_expand "sibcall_epilogue"
543 "rx_expand_epilogue (true); DONE;"
548 ;; Note - we do not allow memory to memory moves, even though the ISA
549 ;; supports them. The reason is that the conditions on such moves are
550 ;; too restrictive, specifically the source addressing mode is limited
551 ;; by the destination addressing mode and vice versa. (For example it
552 ;; is not possible to use indexed register indirect addressing for one
553 ;; of the operands if the other operand is anything other than a register,
554 ;; but it is possible to use register relative addressing when the other
555 ;; operand also uses register relative or register indirect addressing).
557 ;; GCC does not support computing legitimate addresses based on the
558 ;; nature of other operands involved in the instruction, and reload is
559 ;; not smart enough to cope with a whole variety of different memory
560 ;; addressing constraints, so it is simpler and safer to just refuse
561 ;; to support memory to memory moves.
563 (define_expand "mov<register_modes:mode>"
564 [(set (match_operand:register_modes 0 "general_operand")
565 (match_operand:register_modes 1 "general_operand"))]
568 if (MEM_P (operands[0]) && MEM_P (operands[1]))
569 operands[1] = copy_to_mode_reg (<register_modes:MODE>mode, operands[1]);
570 operands[0] = rx_maybe_pidify_operand (operands[0], 0);
571 operands[1] = rx_maybe_pidify_operand (operands[1], 0);
572 if (GET_CODE (operands[0]) != REG
573 && GET_CODE (operands[1]) == PLUS)
574 operands[1] = copy_to_mode_reg (<register_modes:MODE>mode, operands[1]);
575 if (GET_CODE (operands[1]) == PLUS && GET_MODE (operands[1]) == SImode)
577 emit_insn (gen_addsi3 (operands[0], XEXP (operands[1], 0), XEXP (operands[1], 1)));
580 if (CONST_INT_P (operand1)
581 && ! rx_is_legitimate_constant (<register_modes:MODE>mode, operand1))
586 (define_insn "*mov<register_modes:mode>_internal"
587 [(set (match_operand:register_modes
588 0 "nonimmediate_operand" "=r,r,r,r,r,r,m,Q,Q,Q,Q,r")
589 (match_operand:register_modes
590 1 "general_operand" "Int08,Sint16,Sint24,i,r,m,r,Int08,Sint16,Sint24,i,RpdaRpid"))]
592 { return rx_gen_move_template (operands, false); }
593 [(set_attr "length" "3,4,5,6,2,4,6,5,6,7,8,8")
594 (set_attr "timings" "11,11,11,11,11,12,11,11,11,11,11,11")]
597 (define_insn "extend<small_int_modes:mode>si2"
598 [(set (match_operand:SI 0 "register_operand" "=r,r")
599 (sign_extend:SI (match_operand:small_int_modes
600 1 "nonimmediate_operand" "r,m")))]
602 { return rx_gen_move_template (operands, false); }
603 [(set_attr "length" "2,6")
604 (set_attr "timings" "11,12")]
607 (define_insn "zero_extend<small_int_modes:mode>si2"
608 [(set (match_operand:SI 0 "register_operand" "=r,r")
609 (zero_extend:SI (match_operand:small_int_modes
610 1 "nonimmediate_operand" "r,m")))]
612 { return rx_gen_move_template (operands, true); }
613 [(set_attr "length" "2,4")
614 (set_attr "timings" "11,12")]
617 (define_insn "stack_push"
618 [(set (reg:SI SP_REG)
619 (minus:SI (reg:SI SP_REG)
621 (set (mem:SI (reg:SI SP_REG))
622 (match_operand:SI 0 "register_operand" "r"))]
625 [(set_attr "length" "2")]
628 (define_insn "stack_pushm"
629 [(match_parallel 1 "rx_store_multiple_vector"
630 [(set (reg:SI SP_REG)
631 (minus:SI (reg:SI SP_REG)
632 (match_operand:SI 0 "const_int_operand" "n")))])]
635 rx_emit_stack_pushm (operands);
638 [(set_attr "length" "2")
639 (set_attr "timings" "44")] ;; The timing is a guesstimate average timing.
642 (define_insn "stack_pop"
643 [(set (match_operand:SI 0 "register_operand" "=r")
644 (mem:SI (reg:SI SP_REG)))
646 (plus:SI (reg:SI SP_REG)
650 [(set_attr "length" "2")
651 (set_attr "timings" "12")]
654 (define_insn "stack_popm"
655 [(match_parallel 1 "rx_load_multiple_vector"
656 [(set (reg:SI SP_REG)
657 (plus:SI (reg:SI SP_REG)
658 (match_operand:SI 0 "const_int_operand" "n")))])]
661 rx_emit_stack_popm (operands, true);
664 [(set_attr "length" "2")
665 (set_attr "timings" "45")] ;; The timing is a guesstimate average timing.
668 (define_insn_and_split "cstoresi4"
669 [(set (match_operand:SI 0 "register_operand" "=r")
670 (match_operator:SI 1 "comparison_operator"
671 [(match_operand:SI 2 "register_operand" "r")
672 (match_operand:SI 3 "rx_source_operand" "riQ")]))
673 (clobber (reg:CC CC_REG))]
681 flags = gen_rtx_REG (CCmode, CC_REG);
682 x = gen_rtx_COMPARE (CCmode, operands[2], operands[3]);
683 x = gen_rtx_SET (VOIDmode, flags, x);
686 x = gen_rtx_fmt_ee (GET_CODE (operands[1]), SImode, flags, const0_rtx);
687 x = gen_rtx_SET (VOIDmode, operands[0], x);
693 [(set (match_operand:SI 0 "register_operand" "=r")
694 (match_operator:SI 1 "comparison_operator"
695 [(reg CC_REG) (const_int 0)]))]
698 [(set_attr "length" "3")]
701 (define_insn_and_split "cstoresf4"
702 [(set (match_operand:SI 0 "register_operand" "=r")
703 (match_operator:SI 1 "rx_fp_comparison_operator"
704 [(match_operand:SF 2 "register_operand" "r")
705 (match_operand:SF 3 "rx_source_operand" "rFQ")]))]
713 flags = gen_rtx_REG (CC_Fmode, CC_REG);
714 x = gen_rtx_COMPARE (CC_Fmode, operands[2], operands[3]);
715 x = gen_rtx_SET (VOIDmode, flags, x);
718 x = gen_rtx_fmt_ee (GET_CODE (operands[1]), SImode, flags, const0_rtx);
719 x = gen_rtx_SET (VOIDmode, operands[0], x);
724 (define_expand "movsicc"
726 [(set (match_operand:SI 0 "register_operand")
727 (if_then_else:SI (match_operand:SI 1 "comparison_operator")
728 (match_operand:SI 2 "nonmemory_operand")
729 (match_operand:SI 3 "nonmemory_operand")))
730 (clobber (reg:CC CC_REG))])]
733 /* One operand must be a constant or a register, the other must be a register. */
734 if ( ! CONSTANT_P (operands[2])
735 && ! CONSTANT_P (operands[3])
736 && ! (REG_P (operands[2]) && REG_P (operands[3])))
740 (define_insn_and_split "*movsicc"
741 [(set (match_operand:SI 0 "register_operand" "=r,r,r")
743 (match_operator 5 "comparison_operator"
744 [(match_operand:SI 3 "register_operand" "r,r,r")
745 (match_operand:SI 4 "rx_source_operand" "riQ,riQ,riQ")])
746 (match_operand:SI 1 "nonmemory_operand" "i,ri,r")
747 (match_operand:SI 2 "nonmemory_operand" "ri,i,r")))
748 (clobber (reg:CC CC_REG))]
749 "(CONSTANT_P (operands[1]) || CONSTANT_P (operands[2]))
750 || (REG_P (operands[1]) && REG_P (operands[2]))"
752 "&& reload_completed"
755 rtx x, flags, op0, op1, op2;
756 enum rtx_code cmp_code;
758 flags = gen_rtx_REG (CCmode, CC_REG);
759 x = gen_rtx_COMPARE (CCmode, operands[3], operands[4]);
760 emit_insn (gen_rtx_SET (VOIDmode, flags, x));
762 cmp_code = GET_CODE (operands[5]);
767 /* If OP2 is the constant, reverse the sense of the move.
768 Likewise if both operands are registers but OP1 == OP0. */
769 if ((! CONSTANT_P (operands[1]) && CONSTANT_P (operands[2]))
770 || (REG_P (operands[1]) && REG_P (operands[2])
771 && rtx_equal_p (op0, op1)))
773 x = op1, op1 = op2, op2 = x;
774 cmp_code = reverse_condition (cmp_code);
777 /* If OP2 does not match the output, copy it into place. We have allowed
778 these alternatives so that the destination can legitimately be one of
779 the comparison operands without increasing register pressure. */
780 if (! rtx_equal_p (op0, op2))
781 emit_move_insn (op0, op2);
783 x = gen_rtx_fmt_ee (cmp_code, VOIDmode, flags, const0_rtx);
784 x = gen_rtx_IF_THEN_ELSE (SImode, x, op1, op0);
785 emit_insn (gen_rtx_SET (VOIDmode, op0, x));
790 [(set (match_operand:SI 0 "register_operand" "+r,r,r,r")
792 (match_operator 2 "rx_z_comparison_operator"
793 [(reg CC_REG) (const_int 0)])
794 (match_operand:SI 1 "immediate_operand" "Sint08,Sint16,Sint24,i")
797 && ((GET_CODE (operands[2]) == EQ) || (GET_CODE (operands[2]) == NE))"
799 if (GET_CODE (operands[2]) == EQ)
800 return "stz\t%1, %0";
802 return "stnz\t%1, %0";
804 [(set_attr "length" "4,5,6,7")]
807 (define_insn "*stcc_reg"
808 [(set (match_operand:SI 0 "register_operand" "+r,r,r,r,r,r")
810 (match_operator 2 "comparison_operator"
811 [(reg CC_REG) (const_int 0)])
812 (match_operand:SI 1 "nonmemory_operand"
813 "r,Uint04,Sint08,Sint16,Sint24,i")
817 PUT_CODE (operands[2], reverse_condition (GET_CODE (operands[2])));
818 return "b%B2 1f\n\tmov %1, %0\n1:";
820 [(set_attr "length" "3,3,4,5,6,7")]
823 ;; Arithmetic Instructions
825 (define_insn "abssi2"
826 [(set (match_operand:SI 0 "register_operand" "=r,r")
827 (abs:SI (match_operand:SI 1 "register_operand" "0,r")))
828 (clobber (reg:CC CC_REG))]
833 [(set_attr "length" "2,3")]
836 (define_insn "*abssi2_flags"
837 [(set (match_operand:SI 0 "register_operand" "=r,r")
838 (abs:SI (match_operand:SI 1 "register_operand" "0,r")))
840 (compare (abs:SI (match_dup 1))
842 ;; Note - although the ABS instruction does set the O bit in the processor
843 ;; status word, it does not do so in a way that is comparable with the CMP
844 ;; instruction. Hence we use CC_ZSmode rather than CC_ZSOmode.
845 "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
849 [(set_attr "length" "2,3")]
852 (define_expand "addsi3"
853 [(parallel [(set (match_operand:SI 0 "register_operand" "")
854 (plus:SI (match_operand:SI 1 "register_operand" "")
855 (match_operand:SI 2 "rx_source_operand" "")))
856 (clobber (reg:CC CC_REG))])]
859 operands[0] = rx_maybe_pidify_operand (operands[0], 1);
860 operands[1] = rx_maybe_pidify_operand (operands[1], 1);
861 operands[2] = rx_maybe_pidify_operand (operands[2], 1);
865 (define_insn "addsi3_internal"
866 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r,r,r,r,r,r,r,r")
867 (plus:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0,0,r,r,r,r,r,r,0")
868 (match_operand:SI 2 "rx_source_operand" "r,Uint04,NEGint4,Sint08,Sint16,Sint24,i,0,r,Sint08,Sint16,Sint24,i,Q")))
869 (clobber (reg:CC CC_REG))]
886 [(set_attr "timings" "11,11,11,11,11,11,11,11,11,11,11,11,11,33")
887 (set_attr "length" "2,2,2,3,4,5,6,2,3,3,4,5,6,5")]
890 (define_insn "*addsi3_flags"
891 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r,r,r,r,r,r,r,r")
892 (plus:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0,0,r,r,r,r,r,r,0")
893 (match_operand:SI 2 "rx_source_operand" "r,Uint04,NEGint4,Sint08,Sint16,Sint24,i,0,r,Sint08,Sint16,Sint24,i,Q")))
895 (compare (plus:SI (match_dup 1) (match_dup 2))
897 "reload_completed && rx_match_ccmode (insn, CC_ZSCmode)"
913 [(set_attr "timings" "11,11,11,11,11,11,11,11,11,11,11,11,11,33")
914 (set_attr "length" "2,2,2,3,4,5,6,2,3,3,4,5,6,5")]
917 ;; A helper to expand the above with the CC_MODE filled in.
918 (define_expand "addsi3_flags"
919 [(parallel [(set (match_operand:SI 0 "register_operand")
920 (plus:SI (match_operand:SI 1 "register_operand")
921 (match_operand:SI 2 "rx_source_operand")))
922 (set (reg:CC_ZSC CC_REG)
923 (compare:CC_ZSC (plus:SI (match_dup 1) (match_dup 2))
927 (define_insn "adc_internal"
928 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r")
931 (ltu:SI (reg:CC CC_REG) (const_int 0))
932 (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0"))
933 (match_operand:SI 2 "rx_source_operand" "r,Sint08,Sint16,Sint24,i,Q")))
934 (clobber (reg:CC CC_REG))]
937 [(set_attr "timings" "11,11,11,11,11,33")
938 (set_attr "length" "3,4,5,6,7,6")]
941 (define_insn "*adc_flags"
942 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r")
945 (ltu:SI (reg:CC CC_REG) (const_int 0))
946 (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0"))
947 (match_operand:SI 2 "rx_source_operand" "r,Sint08,Sint16,Sint24,i,Q")))
952 (ltu:SI (reg:CC CC_REG) (const_int 0))
956 "reload_completed && rx_match_ccmode (insn, CC_ZSCmode)"
958 [(set_attr "timings" "11,11,11,11,11,33")
959 (set_attr "length" "3,4,5,6,7,6")]
962 ;; Peepholes to match:
963 ;; (set (reg A) (reg B))
964 ;; (set (CC) (compare:CC (reg A/reg B) (const_int 0)))
965 ;; and replace them with the addsi3_flags pattern, using an add
966 ;; of zero to copy the register and set the condition code bits.
968 [(set (match_operand:SI 0 "register_operand")
969 (match_operand:SI 1 "register_operand"))
971 (compare:CC (match_dup 0)
974 [(parallel [(set (match_dup 0)
975 (plus:SI (match_dup 1) (const_int 0)))
976 (set (reg:CC_ZSC CC_REG)
977 (compare:CC_ZSC (plus:SI (match_dup 1) (const_int 0))
982 [(set (match_operand:SI 0 "register_operand")
983 (match_operand:SI 1 "register_operand"))
985 (compare:CC (match_dup 1)
988 [(parallel [(set (match_dup 0)
989 (plus:SI (match_dup 1) (const_int 0)))
990 (set (reg:CC_ZSC CC_REG)
991 (compare:CC_ZSC (plus:SI (match_dup 1) (const_int 0))
995 (define_expand "adddi3"
996 [(set (match_operand:DI 0 "register_operand")
997 (plus:DI (match_operand:DI 1 "register_operand")
998 (match_operand:DI 2 "rx_source_operand")))]
1001 rtx op0l, op0h, op1l, op1h, op2l, op2h;
1003 op0l = gen_lowpart (SImode, operands[0]);
1004 op1l = gen_lowpart (SImode, operands[1]);
1005 op2l = gen_lowpart (SImode, operands[2]);
1006 op0h = gen_highpart (SImode, operands[0]);
1007 op1h = gen_highpart (SImode, operands[1]);
1008 op2h = gen_highpart_mode (SImode, DImode, operands[2]);
1010 emit_insn (gen_adddi3_internal (op0l, op0h, op1l, op2l, op1h, op2h));
1014 (define_insn_and_split "adddi3_internal"
1015 [(set (match_operand:SI 0 "register_operand" "=&r")
1016 (plus:SI (match_operand:SI 2 "register_operand" "r")
1017 (match_operand:SI 3 "rx_source_operand" "riQ")))
1018 (set (match_operand:SI 1 "register_operand" "=r")
1021 (ltu:SI (plus:SI (match_dup 2) (match_dup 3)) (match_dup 2))
1022 (match_operand:SI 4 "register_operand" "%1"))
1023 (match_operand:SI 5 "rx_source_operand" "riQ")))
1024 (clobber (match_scratch:SI 6 "=&r"))
1025 (clobber (reg:CC CC_REG))]
1031 rtx op0l = operands[0];
1032 rtx op0h = operands[1];
1033 rtx op1l = operands[2];
1034 rtx op2l = operands[3];
1035 rtx op1h = operands[4];
1036 rtx op2h = operands[5];
1037 rtx scratch = operands[6];
1040 if (reg_overlap_mentioned_p (op0l, op1h))
1042 emit_move_insn (scratch, op0l);
1044 if (reg_overlap_mentioned_p (op0l, op2h))
1047 else if (reg_overlap_mentioned_p (op0l, op2h))
1049 emit_move_insn (scratch, op0l);
1053 if (rtx_equal_p (op0l, op1l))
1055 /* It is preferable that op0l == op1l... */
1056 else if (rtx_equal_p (op0l, op2l))
1057 x = op1l, op1l = op2l, op2l = x;
1058 /* ... but it is only a requirement if op2l == MEM. */
1059 else if (MEM_P (op2l))
1061 /* Let's hope that we still have a scratch register free. */
1062 gcc_assert (op1h != scratch);
1063 emit_move_insn (scratch, op2l);
1067 emit_insn (gen_addsi3_flags (op0l, op1l, op2l));
1069 if (rtx_equal_p (op0h, op1h))
1071 else if (rtx_equal_p (op0h, op2h))
1072 x = op1h, op1h = op2h, op2h = x;
1075 emit_move_insn (op0h, op1h);
1078 emit_insn (gen_adc_internal (op0h, op1h, op2h));
1082 (define_insn "andsi3"
1083 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r,r,r")
1084 (and:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0,r,r,0")
1085 (match_operand:SI 2 "rx_source_operand" "r,Uint04,Sint08,Sint16,Sint24,i,0,r,Q")))
1086 (clobber (reg:CC CC_REG))]
1098 [(set_attr "timings" "11,11,11,11,11,11,11,11,33")
1099 (set_attr "length" "2,2,3,4,5,6,2,5,5")]
1102 (define_insn "*andsi3_flags"
1103 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r,r,r")
1104 (and:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0,r,r,0")
1105 (match_operand:SI 2 "rx_source_operand" "r,Uint04,Sint08,Sint16,Sint24,i,0,r,Q")))
1107 (compare (and:SI (match_dup 1) (match_dup 2))
1109 "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1120 [(set_attr "timings" "11,11,11,11,11,11,11,11,33")
1121 (set_attr "length" "2,2,3,4,5,6,2,5,5")]
1124 ;; Byte swap (single 32-bit value).
1125 (define_insn "bswapsi2"
1126 [(set (match_operand:SI 0 "register_operand" "=r")
1127 (bswap:SI (match_operand:SI 1 "register_operand" "r")))]
1130 [(set_attr "length" "3")]
1133 ;; Byte swap (single 16-bit value). Note - we ignore the swapping of the high 16-bits.
1134 (define_insn "bswaphi2"
1135 [(set (match_operand:HI 0 "register_operand" "=r")
1136 (bswap:HI (match_operand:HI 1 "register_operand" "r")))]
1139 [(set_attr "length" "3")]
1142 (define_insn "divsi3"
1143 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r")
1144 (div:SI (match_operand:SI 1 "register_operand" "0,0,0,0,0,0")
1145 (match_operand:SI 2 "rx_source_operand" "r,Sint08,Sint16,Sint24,i,Q")))
1146 (clobber (reg:CC CC_REG))]
1149 [(set_attr "timings" "1111") ;; Strictly speaking the timing should be
1150 ;; 2222, but that is a worst case sceanario.
1151 (set_attr "length" "3,4,5,6,7,6")]
1154 (define_insn "udivsi3"
1155 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r")
1156 (udiv:SI (match_operand:SI 1 "register_operand" "0,0,0,0,0,0")
1157 (match_operand:SI 2 "rx_source_operand" "r,Sint08,Sint16,Sint24,i,Q")))
1158 (clobber (reg:CC CC_REG))]
1161 [(set_attr "timings" "1010") ;; Strictly speaking the timing should be
1162 ;; 2020, but that is a worst case sceanario.
1163 (set_attr "length" "3,4,5,6,7,6")]
1166 ;; Note - these patterns are suppressed in big-endian mode because they
1167 ;; generate a little endian result. ie the most significant word of the
1168 ;; result is placed in the higher numbered register of the destination
1171 (define_insn "mulsidi3"
1172 [(set (match_operand:DI 0 "register_operand" "=r,r,r,r,r,r")
1173 (mult:DI (sign_extend:DI (match_operand:SI
1174 1 "register_operand" "%0,0,0,0,0,0"))
1175 (sign_extend:DI (match_operand:SI
1176 2 "rx_source_operand"
1177 "r,Sint08,Sint16,Sint24,i,Q"))))]
1178 "! TARGET_BIG_ENDIAN_DATA"
1180 [(set_attr "length" "3,4,5,6,7,6")
1181 (set_attr "timings" "22,22,22,22,22,44")]
1184 ;; See comment for mulsidi3.
1185 ;; Note - the zero_extends are to distinguish this pattern from the
1186 ;; mulsidi3 pattern. Immediate mode addressing is not supported
1187 ;; because gcc cannot handle the expression: (zero_extend (const_int)).
1188 (define_insn "umulsidi3"
1189 [(set (match_operand:DI 0 "register_operand" "=r,r")
1190 (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "%0,0"))
1191 (zero_extend:DI (match_operand:SI 2 "rx_compare_operand" "r,Q"))))]
1192 "! TARGET_BIG_ENDIAN_DATA"
1194 [(set_attr "length" "3,6")
1195 (set_attr "timings" "22,44")]
1198 (define_insn "smaxsi3"
1199 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r")
1200 (smax:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0")
1201 (match_operand:SI 2 "rx_source_operand"
1202 "r,Sint08,Sint16,Sint24,i,Q")))]
1205 [(set_attr "length" "3,4,5,6,7,6")
1206 (set_attr "timings" "11,11,11,11,11,33")]
1209 (define_insn "sminsi3"
1210 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r")
1211 (smin:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0")
1212 (match_operand:SI 2 "rx_source_operand"
1213 "r,Sint08,Sint16,Sint24,i,Q")))]
1216 [(set_attr "length" "3,4,5,6,7,6")
1217 (set_attr "timings" "11,11,11,11,11,33")]
1220 (define_insn "umax<small_int_modes:mode>3_u"
1221 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r")
1222 (smax:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0")
1223 (zero_extend:SI (match_operand:small_int_modes 2 "rx_minmaxex_operand"
1224 "r,Sint08,Sint16,Sint24,i,Q"))))]
1227 [(set_attr "length" "3,4,5,6,7,6")
1228 (set_attr "timings" "11,11,11,11,11,33")]
1231 (define_insn "umin<small_int_modes:mode>3_ur"
1232 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r")
1233 (smin:SI (zero_extend:SI (match_operand:small_int_modes 2 "rx_minmaxex_operand"
1234 "r,Sint08,Sint16,Sint24,i,Q"))
1235 (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0")))]
1238 [(set_attr "length" "3,4,5,6,7,6")
1239 (set_attr "timings" "11,11,11,11,11,33")]
1242 (define_insn "umax<small_int_modes:mode>3_ur"
1243 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r")
1244 (smax:SI (zero_extend:SI (match_operand:small_int_modes 2 "rx_minmaxex_operand"
1245 "r,Sint08,Sint16,Sint24,i,Q"))
1246 (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0")))]
1249 [(set_attr "length" "3,4,5,6,7,6")
1250 (set_attr "timings" "11,11,11,11,11,33")]
1253 (define_expand "umax<small_int_modes:mode>3"
1255 (zero_extend:SI (match_operand:small_int_modes 1 "register_operand" "%0,0,0,0,0,0")))
1257 (smax:SI (match_dup 4)
1258 (match_operand:small_int_modes 2 "rx_source_operand"
1259 "r,Sint08,Sint16,Sint24,i,Q")))
1260 (set (match_operand:small_int_modes 0 "register_operand" "=r,r,r,r,r,r")
1264 "operands[3] = gen_reg_rtx (SImode);
1265 operands[4] = gen_reg_rtx (SImode);
1266 operands[5] = gen_reg_rtx (SImode);
1267 operands[6] = gen_rtx_SUBREG (GET_MODE (operands[0]), operands[3],
1268 TARGET_BIG_ENDIAN_DATA ? (GET_MODE (operands[0]) == HImode ? 2 : 3) : 0);
1269 if (GET_CODE (operands[2]) != CONST_INT)
1271 emit_move_insn (operands[5], gen_rtx_ZERO_EXTEND (SImode, operands[2]));
1272 operands[2] = operands[5];
1277 (define_expand "umin<small_int_modes:mode>3"
1279 (zero_extend:SI (match_operand:small_int_modes 1 "register_operand" "%0,0,0,0,0,0")))
1281 (smin:SI (match_dup 4)
1282 (match_operand:small_int_modes 2 "rx_source_operand"
1283 "r,Sint08,Sint16,Sint24,i,Q")))
1284 (set (match_operand:small_int_modes 0 "register_operand" "=r,r,r,r,r,r")
1288 "operands[3] = gen_reg_rtx (SImode);
1289 operands[4] = gen_reg_rtx (SImode);
1290 operands[5] = gen_reg_rtx (SImode);
1291 operands[6] = gen_rtx_SUBREG (GET_MODE (operands[0]), operands[3],
1292 TARGET_BIG_ENDIAN_DATA ? (GET_MODE (operands[0]) == HImode ? 2 : 3) : 0);
1293 if (GET_CODE (operands[2]) != CONST_INT)
1295 emit_move_insn (operands[5], gen_rtx_ZERO_EXTEND (SImode, operands[2]));
1296 operands[2] = operands[5];
1301 (define_insn "mulsi3"
1302 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r,r,r")
1303 (mult:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0,0,r,r")
1304 (match_operand:SI 2 "rx_source_operand"
1305 "r,Uint04,Sint08,Sint16,Sint24,i,Q,0,r")))]
1317 [(set_attr "length" "2,2,3,4,5,6,5,2,3")
1318 (set_attr "timings" "11,11,11,11,11,11,33,11,11")]
1321 (define_insn "negsi2"
1322 [(set (match_operand:SI 0 "register_operand" "=r,r")
1323 (neg:SI (match_operand:SI 1 "register_operand" "0,r")))
1324 (clobber (reg:CC CC_REG))]
1329 [(set_attr "length" "2,3")]
1332 ;; Note that the O and C flags are not set as per a normal compare,
1333 ;; and thus are unusable in that context.
1334 (define_insn "*negsi2_flags"
1335 [(set (match_operand:SI 0 "register_operand" "=r,r")
1336 (neg:SI (match_operand:SI 1 "register_operand" "0,r")))
1338 (compare (neg:SI (match_dup 1))
1340 "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1344 [(set_attr "length" "2,3")]
1347 (define_insn "one_cmplsi2"
1348 [(set (match_operand:SI 0 "register_operand" "=r,r")
1349 (not:SI (match_operand:SI 1 "register_operand" "0,r")))
1350 (clobber (reg:CC CC_REG))]
1355 [(set_attr "length" "2,3")]
1358 (define_insn "*one_cmplsi2_flags"
1359 [(set (match_operand:SI 0 "register_operand" "=r,r")
1360 (not:SI (match_operand:SI 1 "register_operand" "0,r")))
1362 (compare (not:SI (match_dup 1))
1364 "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1368 [(set_attr "length" "2,3")]
1371 (define_insn "iorsi3"
1372 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r,r,r")
1373 (ior:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0,r,r,0")
1374 (match_operand:SI 2 "rx_source_operand" "r,Uint04,Sint08,Sint16,Sint24,i,0,r,Q")))
1375 (clobber (reg:CC CC_REG))]
1387 [(set_attr "timings" "11,11,11,11,11,11,11,11,33")
1388 (set_attr "length" "2,2,3,4,5,6,2,3,5")]
1391 (define_insn "*iorsi3_flags"
1392 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r,r,r")
1393 (ior:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0,r,r,0")
1394 (match_operand:SI 2 "rx_source_operand" "r,Uint04,Sint08,Sint16,Sint24,i,0,r,Q")))
1396 (compare (ior:SI (match_dup 1) (match_dup 2))
1398 "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1409 [(set_attr "timings" "11,11,11,11,11,11,11,11,33")
1410 (set_attr "length" "2,2,3,4,5,6,2,3,5")]
1413 (define_insn "rotlsi3"
1414 [(set (match_operand:SI 0 "register_operand" "=r")
1415 (rotate:SI (match_operand:SI 1 "register_operand" "0")
1416 (match_operand:SI 2 "rx_shift_operand" "rn")))
1417 (clobber (reg:CC CC_REG))]
1420 [(set_attr "length" "3")]
1423 (define_insn "*rotlsi3_flags"
1424 [(set (match_operand:SI 0 "register_operand" "=r")
1425 (rotate:SI (match_operand:SI 1 "register_operand" "0")
1426 (match_operand:SI 2 "rx_shift_operand" "rn")))
1428 (compare (rotate:SI (match_dup 1) (match_dup 2))
1430 "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1432 [(set_attr "length" "3")]
1435 (define_insn "rotrsi3"
1436 [(set (match_operand:SI 0 "register_operand" "=r")
1437 (rotatert:SI (match_operand:SI 1 "register_operand" "0")
1438 (match_operand:SI 2 "rx_shift_operand" "rn")))
1439 (clobber (reg:CC CC_REG))]
1442 [(set_attr "length" "3")]
1445 (define_insn "*rotrsi3_flags"
1446 [(set (match_operand:SI 0 "register_operand" "=r")
1447 (rotatert:SI (match_operand:SI 1 "register_operand" "0")
1448 (match_operand:SI 2 "rx_shift_operand" "rn")))
1450 (compare (rotatert:SI (match_dup 1) (match_dup 2))
1452 "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1454 [(set_attr "length" "3")]
1457 (define_insn "ashrsi3"
1458 [(set (match_operand:SI 0 "register_operand" "=r,r,r")
1459 (ashiftrt:SI (match_operand:SI 1 "register_operand" "0,0,r")
1460 (match_operand:SI 2 "rx_shift_operand" "r,n,n")))
1461 (clobber (reg:CC CC_REG))]
1467 [(set_attr "length" "3,2,3")]
1470 (define_insn "*ashrsi3_flags"
1471 [(set (match_operand:SI 0 "register_operand" "=r,r,r")
1472 (ashiftrt:SI (match_operand:SI 1 "register_operand" "0,0,r")
1473 (match_operand:SI 2 "rx_shift_operand" "r,n,n")))
1475 (compare (ashiftrt:SI (match_dup 1) (match_dup 2))
1477 "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1482 [(set_attr "length" "3,2,3")]
1485 (define_insn "lshrsi3"
1486 [(set (match_operand:SI 0 "register_operand" "=r,r,r")
1487 (lshiftrt:SI (match_operand:SI 1 "register_operand" "0,0,r")
1488 (match_operand:SI 2 "rx_shift_operand" "r,n,n")))
1489 (clobber (reg:CC CC_REG))]
1495 [(set_attr "length" "3,2,3")]
1498 (define_insn "*lshrsi3_flags"
1499 [(set (match_operand:SI 0 "register_operand" "=r,r,r")
1500 (lshiftrt:SI (match_operand:SI 1 "register_operand" "0,0,r")
1501 (match_operand:SI 2 "rx_shift_operand" "r,n,n")))
1503 (compare (lshiftrt:SI (match_dup 1) (match_dup 2))
1505 "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1510 [(set_attr "length" "3,2,3")]
1513 (define_insn "ashlsi3"
1514 [(set (match_operand:SI 0 "register_operand" "=r,r,r")
1515 (ashift:SI (match_operand:SI 1 "register_operand" "0,0,r")
1516 (match_operand:SI 2 "rx_shift_operand" "r,n,n")))
1517 (clobber (reg:CC CC_REG))]
1523 [(set_attr "length" "3,2,3")]
1526 (define_insn "*ashlsi3_flags"
1527 [(set (match_operand:SI 0 "register_operand" "=r,r,r")
1528 (ashift:SI (match_operand:SI 1 "register_operand" "0,0,r")
1529 (match_operand:SI 2 "rx_shift_operand" "r,n,n")))
1531 (compare (ashift:SI (match_dup 1) (match_dup 2))
1533 "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1538 [(set_attr "length" "3,2,3")]
1541 ;; Saturate to 32-bits
1542 (define_insn_and_split "ssaddsi3"
1543 [(set (match_operand:SI 0 "register_operand" "=r")
1544 (ss_plus:SI (match_operand:SI 1 "register_operand" "r")
1545 (match_operand:SI 2 "rx_source_operand" "riQ")))
1546 (clobber (reg:CC CC_REG))]
1550 [(parallel [(set (match_dup 0)
1551 (plus:SI (match_dup 1) (match_dup 2)))
1552 (set (reg:CC_ZSC CC_REG)
1554 (plus:SI (match_dup 1) (match_dup 2))
1557 (unspec:SI [(match_dup 0) (reg:CC CC_REG)]
1558 UNSPEC_BUILTIN_SAT))]
1563 [(set (match_operand:SI 0 "register_operand" "=r")
1564 (unspec:SI [(match_operand:SI 1 "register_operand" "0")
1566 UNSPEC_BUILTIN_SAT))]
1569 [(set_attr "length" "2")]
1572 (define_insn "subsi3"
1573 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r")
1574 (minus:SI (match_operand:SI 1 "register_operand" "0,0,0,r,0")
1575 (match_operand:SI 2 "rx_source_operand" "r,Uint04,n,r,Q")))
1576 (clobber (reg:CC CC_REG))]
1584 [(set_attr "timings" "11,11,11,11,33")
1585 (set_attr "length" "2,2,6,3,5")]
1588 ;; Note that the O flag is set as if (compare op1 op2) not for
1589 ;; what is described here, (compare op0 0).
1590 (define_insn "*subsi3_flags"
1591 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r")
1592 (minus:SI (match_operand:SI 1 "register_operand" "0,0,0,r,0")
1593 (match_operand:SI 2 "rx_source_operand" "r,Uint04,n,r,Q")))
1595 (compare (minus:SI (match_dup 1) (match_dup 2))
1597 "reload_completed && rx_match_ccmode (insn, CC_ZSCmode)"
1604 [(set_attr "timings" "11,11,11,11,33")
1605 (set_attr "length" "2,2,6,3,5")]
1608 ;; A helper to expand the above with the CC_MODE filled in.
1609 (define_expand "subsi3_flags"
1610 [(parallel [(set (match_operand:SI 0 "register_operand")
1611 (minus:SI (match_operand:SI 1 "register_operand")
1612 (match_operand:SI 2 "rx_source_operand")))
1613 (set (reg:CC_ZSC CC_REG)
1614 (compare:CC_ZSC (minus:SI (match_dup 1) (match_dup 2))
1618 (define_insn "sbb_internal"
1619 [(set (match_operand:SI 0 "register_operand" "=r,r")
1622 (match_operand:SI 1 "register_operand" " 0,0")
1623 (match_operand:SI 2 "rx_compare_operand" " r,Q"))
1624 (geu:SI (reg:CC CC_REG) (const_int 0))))
1625 (clobber (reg:CC CC_REG))]
1628 [(set_attr "timings" "11,33")
1629 (set_attr "length" "3,6")]
1632 (define_insn "*sbb_flags"
1633 [(set (match_operand:SI 0 "register_operand" "=r,r")
1636 (match_operand:SI 1 "register_operand" " 0,0")
1637 (match_operand:SI 2 "rx_compare_operand" " r,Q"))
1638 (geu:SI (reg:CC CC_REG) (const_int 0))))
1642 (minus:SI (match_dup 1) (match_dup 2))
1643 (geu:SI (reg:CC CC_REG) (const_int 0)))
1647 [(set_attr "timings" "11,33")
1648 (set_attr "length" "3,6")]
1651 (define_expand "subdi3"
1652 [(set (match_operand:DI 0 "register_operand")
1653 (minus:DI (match_operand:DI 1 "register_operand")
1654 (match_operand:DI 2 "rx_compare_operand")))]
1657 rtx op0l, op0h, op1l, op1h, op2l, op2h;
1659 op0l = gen_lowpart (SImode, operands[0]);
1660 op1l = gen_lowpart (SImode, operands[1]);
1661 op2l = gen_lowpart (SImode, operands[2]);
1662 op0h = gen_highpart (SImode, operands[0]);
1663 op1h = gen_highpart (SImode, operands[1]);
1664 op2h = gen_highpart_mode (SImode, DImode, operands[2]);
1666 emit_insn (gen_subdi3_internal (op0l, op0h, op1l, op2l, op1h, op2h));
1670 (define_insn_and_split "subdi3_internal"
1671 [(set (match_operand:SI 0 "register_operand" "=&r,&r")
1672 (minus:SI (match_operand:SI 2 "register_operand" " 0, r")
1673 (match_operand:SI 3 "rx_compare_operand" "rQ, r")))
1674 (set (match_operand:SI 1 "register_operand" "= r, r")
1677 (match_operand:SI 4 "register_operand" " 1, 1")
1678 (match_operand:SI 5 "rx_compare_operand" " rQ,rQ"))
1679 (geu:SI (match_dup 2) (match_dup 3))))
1680 (clobber (reg:CC CC_REG))]
1686 emit_insn (gen_subsi3_flags (operands[0], operands[2], operands[3]));
1687 emit_insn (gen_sbb_internal (operands[1], operands[4], operands[5]));
1691 (define_insn "xorsi3"
1692 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r")
1693 (xor:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0")
1694 (match_operand:SI 2 "rx_source_operand"
1695 "r,Sint08,Sint16,Sint24,i,Q")))
1696 (clobber (reg:CC CC_REG))]
1699 [(set_attr "timings" "11,11,11,11,11,33")
1700 (set_attr "length" "3,4,5,6,7,6")]
1703 (define_insn "*xorsi3_flags"
1704 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r")
1705 (xor:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0")
1706 (match_operand:SI 2 "rx_source_operand"
1707 "r,Sint08,Sint16,Sint24,i,Q")))
1709 (compare (xor:SI (match_dup 1) (match_dup 2))
1711 "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1713 [(set_attr "timings" "11,11,11,11,11,33")
1714 (set_attr "length" "3,4,5,6,7,6")]
1717 ;; A set of peepholes to catch extending loads followed by arithmetic operations.
1718 ;; We use iterators where possible to reduce the amount of typing and hence the
1719 ;; possibilities for typos.
1721 (define_code_iterator extend_types [(zero_extend "") (sign_extend "")])
1722 (define_code_attr letter [(zero_extend "R") (sign_extend "Q")])
1724 (define_code_iterator memex_commutative [(plus "") (and "") (ior "") (xor "")])
1725 (define_code_iterator memex_noncomm [(div "") (udiv "") (minus "")])
1726 (define_code_iterator memex_nocc [(smax "") (smin "") (mult "")])
1728 (define_code_attr op [(plus "add") (and "and") (div "div") (udiv "divu") (smax "max") (smin "min") (mult "mul") (ior "or") (minus "sub") (xor "xor")])
1731 [(set (match_operand:SI 0 "register_operand")
1732 (extend_types:SI (match_operand:small_int_modes 1 "rx_restricted_mem_operand")))
1733 (parallel [(set (match_operand:SI 2 "register_operand")
1734 (memex_commutative:SI (match_dup 0)
1736 (clobber (reg:CC CC_REG))])]
1737 "peep2_regno_dead_p (2, REGNO (operands[0])) && (optimize < 3 || optimize_size)"
1738 [(parallel [(set:SI (match_dup 2)
1739 (memex_commutative:SI (match_dup 2)
1740 (extend_types:SI (match_dup 1))))
1741 (clobber (reg:CC CC_REG))])]
1745 [(set (match_operand:SI 0 "register_operand")
1746 (extend_types:SI (match_operand:small_int_modes 1 "rx_restricted_mem_operand")))
1747 (parallel [(set (match_operand:SI 2 "register_operand")
1748 (memex_commutative:SI (match_dup 2)
1750 (clobber (reg:CC CC_REG))])]
1751 "peep2_regno_dead_p (2, REGNO (operands[0])) && (optimize < 3 || optimize_size)"
1752 [(parallel [(set:SI (match_dup 2)
1753 (memex_commutative:SI (match_dup 2)
1754 (extend_types:SI (match_dup 1))))
1755 (clobber (reg:CC CC_REG))])]
1759 [(set (match_operand:SI 0 "register_operand")
1760 (extend_types:SI (match_operand:small_int_modes 1 "rx_restricted_mem_operand")))
1761 (parallel [(set (match_operand:SI 2 "register_operand")
1762 (memex_noncomm:SI (match_dup 2)
1764 (clobber (reg:CC CC_REG))])]
1765 "peep2_regno_dead_p (2, REGNO (operands[0])) && (optimize < 3 || optimize_size)"
1766 [(parallel [(set:SI (match_dup 2)
1767 (memex_noncomm:SI (match_dup 2)
1768 (extend_types:SI (match_dup 1))))
1769 (clobber (reg:CC CC_REG))])]
1773 [(set (match_operand:SI 0 "register_operand")
1774 (extend_types:SI (match_operand:small_int_modes 1 "rx_restricted_mem_operand")))
1775 (set (match_operand:SI 2 "register_operand")
1776 (memex_nocc:SI (match_dup 0)
1778 "peep2_regno_dead_p (2, REGNO (operands[0])) && (optimize < 3 || optimize_size)"
1779 [(set:SI (match_dup 2)
1780 (memex_nocc:SI (match_dup 2)
1781 (extend_types:SI (match_dup 1))))]
1785 [(set (match_operand:SI 0 "register_operand")
1786 (extend_types:SI (match_operand:small_int_modes 1 "rx_restricted_mem_operand")))
1787 (set (match_operand:SI 2 "register_operand")
1788 (memex_nocc:SI (match_dup 2)
1790 "peep2_regno_dead_p (2, REGNO (operands[0])) && (optimize < 3 || optimize_size)"
1791 [(set:SI (match_dup 2)
1792 (memex_nocc:SI (match_dup 2)
1793 (extend_types:SI (match_dup 1))))]
1796 (define_insn "<memex_commutative:code>si3_<extend_types:code><small_int_modes:mode>"
1797 [(set (match_operand:SI 0 "register_operand" "=r")
1798 (memex_commutative:SI (match_operand:SI 1 "register_operand" "%0")
1799 (extend_types:SI (match_operand:small_int_modes 2 "rx_restricted_mem_operand" "Q"))))
1800 (clobber (reg:CC CC_REG))]
1801 "(optimize < 3 || optimize_size)"
1802 "<memex_commutative:op>\t%<extend_types:letter>2, %0"
1803 [(set_attr "timings" "33")
1804 (set_attr "length" "5")] ;; This length is corrected in rx_adjust_insn_length
1807 (define_insn "<memex_noncomm:code>si3_<extend_types:code><small_int_modes:mode>"
1808 [(set (match_operand:SI 0 "register_operand" "=r")
1809 (memex_noncomm:SI (match_operand:SI 1 "register_operand" "0")
1810 (extend_types:SI (match_operand:small_int_modes 2 "rx_restricted_mem_operand" "Q"))))
1811 (clobber (reg:CC CC_REG))]
1812 "(optimize < 3 || optimize_size)"
1813 "<memex_noncomm:op>\t%<extend_types:letter>2, %0"
1814 [(set_attr "timings" "33")
1815 (set_attr "length" "5")] ;; This length is corrected in rx_adjust_insn_length
1818 (define_insn "<memex_nocc:code>si3_<extend_types:code><small_int_modes:mode>"
1819 [(set (match_operand:SI 0 "register_operand" "=r")
1820 (memex_nocc:SI (match_operand:SI 1 "register_operand" "%0")
1821 (extend_types:SI (match_operand:small_int_modes 2 "rx_restricted_mem_operand" "Q"))))]
1822 "(optimize < 3 || optimize_size)"
1823 "<memex_nocc:op>\t%<extend_types:letter>2, %0"
1824 [(set_attr "timings" "33")
1825 (set_attr "length" "5")] ;; This length is corrected in rx_adjust_insn_length
1829 [(set (match_operand:SI 0 "register_operand")
1830 (extend_types:SI (match_operand:small_int_modes 1 "rx_restricted_mem_operand")))
1831 (set (reg:CC CC_REG)
1832 (compare:CC (match_operand:SI 2 "register_operand")
1834 "peep2_regno_dead_p (2, REGNO (operands[0])) && (optimize < 3 || optimize_size)"
1835 [(set (reg:CC CC_REG)
1836 (compare:CC (match_dup 2)
1837 (extend_types:SI (match_dup 1))))]
1841 ;; (set (reg1) (sign_extend (mem))
1842 ;; (set (reg2) (zero_extend (reg1))
1844 ;; (set (reg2) (zero_extend (mem)))
1846 [(set (match_operand:SI 0 "register_operand")
1847 (sign_extend:SI (match_operand:small_int_modes 1 "memory_operand")))
1848 (set (match_operand:SI 2 "register_operand")
1849 (zero_extend:SI (match_operand:small_int_modes 3 "register_operand")))]
1850 "REGNO (operands[0]) == REGNO (operands[3])
1851 && (REGNO (operands[0]) == REGNO (operands[2])
1852 || peep2_regno_dead_p (2, REGNO (operands[0])))"
1854 (zero_extend:SI (match_dup 1)))]
1857 ;; Remove the redundant sign extension from:
1858 ;; (set (reg) (extend (mem)))
1859 ;; (set (reg) (extend (reg)))
1861 [(set (match_operand:SI 0 "register_operand")
1862 (extend_types:SI (match_operand:small_int_modes 1 "memory_operand")))
1864 (extend_types:SI (match_operand:small_int_modes 2 "register_operand")))]
1865 "REGNO (operands[0]) == REGNO (operands[2])"
1866 [(set (match_dup 0) (extend_types:SI (match_dup 1)))]
1869 (define_insn "comparesi3_<extend_types:code><small_int_modes:mode>"
1870 [(set (reg:CC CC_REG)
1871 (compare:CC (match_operand:SI 0 "register_operand" "=r")
1872 (extend_types:SI (match_operand:small_int_modes 1 "rx_restricted_mem_operand" "Q"))))]
1873 "(optimize < 3 || optimize_size)"
1874 "cmp\t%<extend_types:letter>1, %0"
1875 [(set_attr "timings" "33")
1876 (set_attr "length" "5")] ;; This length is corrected in rx_adjust_insn_length
1879 ;; Floating Point Instructions
1881 (define_insn "addsf3"
1882 [(set (match_operand:SF 0 "register_operand" "=r,r,r")
1883 (plus:SF (match_operand:SF 1 "register_operand" "%0,0,0")
1884 (match_operand:SF 2 "rx_source_operand" "r,F,Q")))
1885 (clobber (reg:CC CC_REG))]
1886 "ALLOW_RX_FPU_INSNS"
1888 [(set_attr "timings" "44,44,66")
1889 (set_attr "length" "3,7,5")]
1892 (define_insn "divsf3"
1893 [(set (match_operand:SF 0 "register_operand" "=r,r,r")
1894 (div:SF (match_operand:SF 1 "register_operand" "0,0,0")
1895 (match_operand:SF 2 "rx_source_operand" "r,F,Q")))
1896 (clobber (reg:CC CC_REG))]
1897 "ALLOW_RX_FPU_INSNS"
1899 [(set_attr "timings" "1616,1616,1818")
1900 (set_attr "length" "3,7,5")]
1903 (define_insn "mulsf3"
1904 [(set (match_operand:SF 0 "register_operand" "=r,r,r")
1905 (mult:SF (match_operand:SF 1 "register_operand" "%0,0,0")
1906 (match_operand:SF 2 "rx_source_operand" "r,F,Q")))
1907 (clobber (reg:CC CC_REG))]
1908 "ALLOW_RX_FPU_INSNS"
1910 [(set_attr "timings" "33,33,55")
1911 (set_attr "length" "3,7,5")]
1914 (define_insn "subsf3"
1915 [(set (match_operand:SF 0 "register_operand" "=r,r,r")
1916 (minus:SF (match_operand:SF 1 "register_operand" "0,0,0")
1917 (match_operand:SF 2 "rx_source_operand" "r,F,Q")))
1918 (clobber (reg:CC CC_REG))]
1919 "ALLOW_RX_FPU_INSNS"
1921 [(set_attr "timings" "44,44,66")
1922 (set_attr "length" "3,7,5")]
1925 (define_insn "fix_truncsfsi2"
1926 [(set (match_operand:SI 0 "register_operand" "=r,r")
1927 (fix:SI (match_operand:SF 1 "rx_compare_operand" "r,Q")))
1928 (clobber (reg:CC CC_REG))]
1929 "ALLOW_RX_FPU_INSNS"
1931 [(set_attr "timings" "22,44")
1932 (set_attr "length" "3,5")]
1935 (define_insn "floatsisf2"
1936 [(set (match_operand:SF 0 "register_operand" "=r,r")
1937 (float:SF (match_operand:SI 1 "rx_compare_operand" "r,Q")))
1938 (clobber (reg:CC CC_REG))]
1939 "ALLOW_RX_FPU_INSNS"
1941 [(set_attr "timings" "22,44")
1942 (set_attr "length" "3,6")]
1945 ;; Bit manipulation instructions.
1947 ;; ??? The *_in_memory patterns will not be matched without further help.
1948 ;; At one time we had the insv expander generate them, but I suspect that
1949 ;; in general we get better performance by exposing the register load to
1952 ;; An alternate solution would be to re-organize these patterns such
1953 ;; that allow both register and memory operands. This would allow the
1954 ;; register allocator to spill and not load the register operand. This
1955 ;; would be possible only for operations for which we have a constant
1956 ;; bit offset, so that we can adjust the address by ofs/8 and replace
1957 ;; the offset in the insn by ofs%8.
1959 (define_insn "*bitset"
1960 [(set (match_operand:SI 0 "register_operand" "=r")
1961 (ior:SI (ashift:SI (const_int 1)
1962 (match_operand:SI 1 "rx_shift_operand" "ri"))
1963 (match_operand:SI 2 "register_operand" "0")))]
1966 [(set_attr "length" "3")]
1969 (define_insn "*bitset_in_memory"
1970 [(set (match_operand:QI 0 "rx_restricted_mem_operand" "+Q")
1971 (ior:QI (ashift:QI (const_int 1)
1972 (match_operand:QI 1 "nonmemory_operand" "ri"))
1976 [(set_attr "length" "3")
1977 (set_attr "timings" "33")]
1980 (define_insn "*bitinvert"
1981 [(set (match_operand:SI 0 "register_operand" "=r")
1982 (xor:SI (ashift:SI (const_int 1)
1983 (match_operand:SI 1 "rx_shift_operand" "ri"))
1984 (match_operand:SI 2 "register_operand" "0")))]
1987 [(set_attr "length" "3")]
1990 (define_insn "*bitinvert_in_memory"
1991 [(set (match_operand:QI 0 "rx_restricted_mem_operand" "+Q")
1992 (xor:QI (ashift:QI (const_int 1)
1993 (match_operand:QI 1 "nonmemory_operand" "ri"))
1997 [(set_attr "length" "5")
1998 (set_attr "timings" "33")]
2001 (define_insn "*bitclr"
2002 [(set (match_operand:SI 0 "register_operand" "=r")
2006 (match_operand:SI 1 "rx_shift_operand" "ri")))
2007 (match_operand:SI 2 "register_operand" "0")))]
2010 [(set_attr "length" "3")]
2013 (define_insn "*bitclr_in_memory"
2014 [(set (match_operand:QI 0 "rx_restricted_mem_operand" "+Q")
2018 (match_operand:QI 1 "nonmemory_operand" "ri")))
2022 [(set_attr "length" "3")
2023 (set_attr "timings" "33")]
2026 (define_insn "*insv_imm"
2027 [(set (zero_extract:SI
2028 (match_operand:SI 0 "register_operand" "+r")
2030 (match_operand:SI 1 "rx_shift_operand" "ri"))
2031 (match_operand:SI 2 "const_int_operand" ""))]
2034 if (INTVAL (operands[2]) & 1)
2035 return "bset\t%1, %0";
2037 return "bclr\t%1, %0";
2039 [(set_attr "length" "3")]
2042 (define_insn_and_split "rx_insv_reg"
2043 [(set (zero_extract:SI
2044 (match_operand:SI 0 "register_operand" "+r")
2046 (match_operand:SI 1 "const_int_operand" ""))
2047 (match_operand:SI 2 "register_operand" "r"))
2048 (clobber (reg:CC CC_REG))]
2052 [(set (zero_extract:SI (match_dup 0) (const_int 1) (match_dup 1))
2057 /* Emit tst #1, op2. */
2058 flags = gen_rtx_REG (CC_ZSmode, CC_REG);
2059 x = gen_rtx_AND (SImode, operands[2], const1_rtx);
2060 x = gen_rtx_COMPARE (CC_ZSmode, x, const0_rtx);
2061 x = gen_rtx_SET (VOIDmode, flags, x);
2065 operands[3] = gen_rtx_NE (SImode, flags, const0_rtx);
2068 (define_insn_and_split "*insv_cond"
2069 [(set (zero_extract:SI
2070 (match_operand:SI 0 "register_operand" "+r")
2072 (match_operand:SI 1 "const_int_operand" ""))
2073 (match_operator:SI 4 "comparison_operator"
2074 [(match_operand:SI 2 "register_operand" "r")
2075 (match_operand:SI 3 "rx_source_operand" "riQ")]))
2076 (clobber (reg:CC CC_REG))]
2080 [(set (zero_extract:SI (match_dup 0) (const_int 1) (match_dup 1))
2085 flags = gen_rtx_REG (CCmode, CC_REG);
2086 x = gen_rtx_COMPARE (CCmode, operands[2], operands[3]);
2087 x = gen_rtx_SET (VOIDmode, flags, x);
2090 operands[4] = gen_rtx_fmt_ee (GET_CODE (operands[4]), SImode,
2094 (define_insn "*bmcc"
2095 [(set (zero_extract:SI
2096 (match_operand:SI 0 "register_operand" "+r")
2098 (match_operand:SI 1 "const_int_operand" ""))
2099 (match_operator:SI 2 "comparison_operator"
2100 [(reg CC_REG) (const_int 0)]))]
2103 [(set_attr "length" "3")]
2106 ;; Work around the fact that X=Y<0 is preferentially expanded as a shift.
2107 (define_insn_and_split "*insv_cond_lt"
2108 [(set (zero_extract:SI
2109 (match_operand:SI 0 "register_operand" "+r")
2111 (match_operand:SI 1 "const_int_operand" ""))
2112 (match_operator:SI 3 "rshift_operator"
2113 [(match_operand:SI 2 "register_operand" "r")
2115 (clobber (reg:CC CC_REG))]
2119 [(parallel [(set (zero_extract:SI (match_dup 0) (const_int 1) (match_dup 1))
2120 (lt:SI (match_dup 2) (const_int 0)))
2121 (clobber (reg:CC CC_REG))])]
2125 (define_expand "insv"
2126 [(set (zero_extract:SI
2127 (match_operand:SI 0 "register_operand") ;; Destination
2128 (match_operand:SI 1 "const_int_operand") ;; # of bits to set
2129 (match_operand:SI 2 "nonmemory_operand")) ;; Starting bit
2130 (match_operand:SI 3 "nonmemory_operand"))] ;; Bits to insert
2133 /* We only handle single-bit inserts. */
2134 if (!CONST_INT_P (operands[1]) || INTVAL (operands[1]) != 1)
2137 /* Either the bit to insert or the position must be constant. */
2138 if (CONST_INT_P (operands[3]))
2139 operands[3] = GEN_INT (INTVAL (operands[3]) & 1);
2140 else if (CONST_INT_P (operands[2]))
2142 emit_insn (gen_rx_insv_reg (operands[0], operands[2], operands[3]));
2149 ;; Atomic exchange operation.
2151 (define_insn "sync_lock_test_and_setsi"
2152 [(set (match_operand:SI 0 "register_operand" "=r,r")
2153 (match_operand:SI 1 "rx_compare_operand" "=r,Q"))
2155 (match_operand:SI 2 "register_operand" "0,0"))]
2158 [(set_attr "length" "3,6")
2159 (set_attr "timings" "22")]
2162 ;; Block move functions.
2164 (define_expand "movstr"
2165 [(set (match_operand:BLK 1 "memory_operand") ;; Dest
2166 (match_operand:BLK 2 "memory_operand")) ;; Source
2167 (use (match_operand:SI 0 "register_operand")) ;; Updated Dest
2171 rtx addr1 = gen_rtx_REG (SImode, 1);
2172 rtx addr2 = gen_rtx_REG (SImode, 2);
2173 rtx len = gen_rtx_REG (SImode, 3);
2174 rtx dest_copy = gen_reg_rtx (SImode);
2176 emit_move_insn (len, GEN_INT (-1));
2177 emit_move_insn (addr1, force_operand (XEXP (operands[1], 0), NULL_RTX));
2178 emit_move_insn (addr2, force_operand (XEXP (operands[2], 0), NULL_RTX));
2179 operands[1] = replace_equiv_address_nv (operands[1], addr1);
2180 operands[2] = replace_equiv_address_nv (operands[2], addr2);
2181 emit_move_insn (dest_copy, addr1);
2182 emit_insn (gen_rx_movstr ());
2183 emit_move_insn (len, GEN_INT (-1));
2184 emit_insn (gen_rx_strend (operands[0], dest_copy));
2189 (define_insn "rx_movstr"
2190 [(set (mem:BLK (reg:SI 1))
2191 (mem:BLK (reg:SI 2)))
2192 (unspec_volatile:BLK [(reg:SI 1) (reg:SI 2) (reg:SI 3)] UNSPEC_MOVSTR)
2193 (clobber (reg:SI 1))
2194 (clobber (reg:SI 2))
2195 (clobber (reg:SI 3))]
2198 [(set_attr "length" "2")
2199 (set_attr "timings" "1111")] ;; The timing is a guesstimate.
2202 (define_insn "rx_strend"
2203 [(set (match_operand:SI 0 "register_operand" "=r")
2204 (unspec_volatile:SI [(match_operand:SI 1 "register_operand" "r")
2205 (reg:SI 3)] UNSPEC_STRLEN))
2206 (clobber (reg:SI 1))
2207 (clobber (reg:SI 2))
2208 (clobber (reg:SI 3))
2209 (clobber (reg:CC CC_REG))
2212 "mov\t%1, r1\n\tmov\t#0, r2\n\tsuntil.b\n\tmov\tr1, %0\n\tsub\t#1, %0"
2213 [(set_attr "length" "10")
2214 (set_attr "timings" "1111")] ;; The timing is a guesstimate.
2217 (define_expand "movmemsi"
2219 [(set (match_operand:BLK 0 "memory_operand") ;; Dest
2220 (match_operand:BLK 1 "memory_operand")) ;; Source
2221 (use (match_operand:SI 2 "register_operand")) ;; Length in bytes
2222 (match_operand 3 "immediate_operand") ;; Align
2223 (unspec_volatile:BLK [(reg:SI 1) (reg:SI 2) (reg:SI 3)] UNSPEC_MOVMEM)]
2227 rtx addr1 = gen_rtx_REG (SImode, 1);
2228 rtx addr2 = gen_rtx_REG (SImode, 2);
2229 rtx len = gen_rtx_REG (SImode, 3);
2231 /* Do not use when the source or destination are volatile - the SMOVF
2232 instruction will read and write in word sized blocks, which may be
2233 outside of the valid address range. */
2234 if (MEM_P (operands[0]) && MEM_VOLATILE_P (operands[0]))
2236 if (MEM_P (operands[1]) && MEM_VOLATILE_P (operands[1]))
2239 if (REG_P (operands[0]) && (REGNO (operands[0]) == 2
2240 || REGNO (operands[0]) == 3))
2242 if (REG_P (operands[1]) && (REGNO (operands[1]) == 1
2243 || REGNO (operands[1]) == 3))
2245 if (REG_P (operands[2]) && (REGNO (operands[2]) == 1
2246 || REGNO (operands[2]) == 2))
2249 emit_move_insn (addr1, force_operand (XEXP (operands[0], 0), NULL_RTX));
2250 emit_move_insn (addr2, force_operand (XEXP (operands[1], 0), NULL_RTX));
2251 emit_move_insn (len, force_operand (operands[2], NULL_RTX));
2252 operands[0] = replace_equiv_address_nv (operands[0], addr1);
2253 operands[1] = replace_equiv_address_nv (operands[1], addr2);
2254 emit_insn (gen_rx_movmem ());
2259 (define_insn "rx_movmem"
2260 [(set (mem:BLK (reg:SI 1))
2261 (mem:BLK (reg:SI 2)))
2263 (unspec_volatile:BLK [(reg:SI 1) (reg:SI 2) (reg:SI 3)] UNSPEC_MOVMEM)
2264 (clobber (reg:SI 1))
2265 (clobber (reg:SI 2))
2266 (clobber (reg:SI 3))]
2269 [(set_attr "length" "2")
2270 (set_attr "timings" "1111")] ;; The timing is a guesstimate.
2273 (define_expand "setmemsi"
2274 [(set (match_operand:BLK 0 "memory_operand") ;; Dest
2275 (match_operand:QI 2 "nonmemory_operand")) ;; Value
2276 (use (match_operand:SI 1 "nonmemory_operand")) ;; Length
2277 (match_operand 3 "immediate_operand") ;; Align
2278 (unspec_volatile:BLK [(reg:SI 1) (reg:SI 2) (reg:SI 3)] UNSPEC_SETMEM)]
2281 rtx addr = gen_rtx_REG (SImode, 1);
2282 rtx val = gen_rtx_REG (QImode, 2);
2283 rtx len = gen_rtx_REG (SImode, 3);
2285 emit_move_insn (addr, force_operand (XEXP (operands[0], 0), NULL_RTX));
2286 emit_move_insn (len, force_operand (operands[1], NULL_RTX));
2287 emit_move_insn (val, operands[2]);
2288 emit_insn (gen_rx_setmem ());
2293 (define_insn "rx_setmem"
2294 [(set (mem:BLK (reg:SI 1))
2295 (unspec_volatile:BLK [(reg:SI 1) (reg:SI 2) (reg:SI 3)] UNSPEC_SETMEM))
2296 (clobber (reg:SI 1))
2297 (clobber (reg:SI 3))]
2300 [(set_attr "length" "2")
2301 (set_attr "timings" "1111")] ;; The timing is a guesstimate.
2304 (define_expand "cmpstrnsi"
2305 [(set (match_operand:SI 0 "register_operand") ;; Result
2306 (unspec_volatile:SI [(match_operand:BLK 1 "memory_operand") ;; String1
2307 (match_operand:BLK 2 "memory_operand")] ;; String2
2309 (use (match_operand:SI 3 "register_operand")) ;; Max Length
2310 (match_operand:SI 4 "immediate_operand")] ;; Known Align
2313 rtx str1 = gen_rtx_REG (SImode, 1);
2314 rtx str2 = gen_rtx_REG (SImode, 2);
2315 rtx len = gen_rtx_REG (SImode, 3);
2317 emit_move_insn (str1, force_operand (XEXP (operands[1], 0), NULL_RTX));
2318 emit_move_insn (str2, force_operand (XEXP (operands[2], 0), NULL_RTX));
2319 emit_move_insn (len, force_operand (operands[3], NULL_RTX));
2321 emit_insn (gen_rx_cmpstrn (operands[0], operands[1], operands[2]));
2326 (define_expand "cmpstrsi"
2327 [(set (match_operand:SI 0 "register_operand") ;; Result
2328 (unspec_volatile:SI [(match_operand:BLK 1 "memory_operand") ;; String1
2329 (match_operand:BLK 2 "memory_operand")] ;; String2
2331 (match_operand:SI 3 "immediate_operand")] ;; Known Align
2334 rtx str1 = gen_rtx_REG (SImode, 1);
2335 rtx str2 = gen_rtx_REG (SImode, 2);
2336 rtx len = gen_rtx_REG (SImode, 3);
2338 emit_move_insn (str1, force_reg (SImode, XEXP (operands[1], 0)));
2339 emit_move_insn (str2, force_reg (SImode, XEXP (operands[2], 0)));
2340 emit_move_insn (len, GEN_INT (-1));
2342 emit_insn (gen_rx_cmpstrn (operands[0], operands[1], operands[2]));
2347 (define_insn "rx_cmpstrn"
2348 [(set (match_operand:SI 0 "register_operand" "=r")
2349 (unspec_volatile:SI [(reg:SI 1) (reg:SI 2) (reg:SI 3)]
2351 (use (match_operand:BLK 1 "memory_operand" "m"))
2352 (use (match_operand:BLK 2 "memory_operand" "m"))
2353 (clobber (reg:SI 1))
2354 (clobber (reg:SI 2))
2355 (clobber (reg:SI 3))
2356 (clobber (reg:CC CC_REG))]
2358 "scmpu ; Perform the string comparison
2359 mov #-1, %0 ; Set up -1 result (which cannot be created
2361 bnc ?+ ; If Carry is not set skip over
2362 scne.L %0 ; Set result based on Z flag
2365 [(set_attr "length" "9")
2366 (set_attr "timings" "1111")] ;; The timing is a guesstimate.
2369 ;; Builtin Functions
2371 ;; GCC does not have the ability to generate the following instructions
2372 ;; on its own so they are provided as builtins instead. To use them from
2373 ;; a program for example invoke them as __builtin_rx_<insn_name>. For
2376 ;; int short_byte_swap (int arg) { return __builtin_rx_revw (arg); }
2378 ;;---------- Accumulator Support ------------------------
2380 ;; Multiply & Accumulate (high)
2381 (define_insn "machi"
2382 [(unspec:SI [(match_operand:SI 0 "register_operand" "r")
2383 (match_operand:SI 1 "register_operand" "r")]
2384 UNSPEC_BUILTIN_MACHI)]
2387 [(set_attr "length" "3")]
2390 ;; Multiply & Accumulate (low)
2391 (define_insn "maclo"
2392 [(unspec:SI [(match_operand:SI 0 "register_operand" "r")
2393 (match_operand:SI 1 "register_operand" "r")]
2394 UNSPEC_BUILTIN_MACLO)]
2397 [(set_attr "length" "3")]
2401 (define_insn "mulhi"
2402 [(unspec:SI [(match_operand:SI 0 "register_operand" "r")
2403 (match_operand:SI 1 "register_operand" "r")]
2404 UNSPEC_BUILTIN_MULHI)]
2407 [(set_attr "length" "3")]
2411 (define_insn "mullo"
2412 [(unspec:SI [(match_operand:SI 0 "register_operand" "r")
2413 (match_operand:SI 1 "register_operand" "r")]
2414 UNSPEC_BUILTIN_MULLO)]
2417 [(set_attr "length" "3")]
2420 ;; Move from Accumulator (high)
2421 (define_insn "mvfachi"
2422 [(set (match_operand:SI 0 "register_operand" "=r")
2423 (unspec:SI [(const_int 0)]
2424 UNSPEC_BUILTIN_MVFACHI))]
2427 [(set_attr "length" "3")]
2430 ;; Move from Accumulator (middle)
2431 (define_insn "mvfacmi"
2432 [(set (match_operand:SI 0 "register_operand" "=r")
2433 (unspec:SI [(const_int 0)]
2434 UNSPEC_BUILTIN_MVFACMI))]
2437 [(set_attr "length" "3")]
2440 ;; Move to Accumulator (high)
2441 (define_insn "mvtachi"
2442 [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")]
2443 UNSPEC_BUILTIN_MVTACHI)]
2446 [(set_attr "length" "3")]
2449 ;; Move to Accumulator (low)
2450 (define_insn "mvtaclo"
2451 [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")]
2452 UNSPEC_BUILTIN_MVTACLO)]
2455 [(set_attr "length" "3")]
2458 ;; Round Accumulator
2460 [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i")]
2461 UNSPEC_BUILTIN_RACW)]
2464 [(set_attr "length" "3")]
2467 ;; Repeat multiply and accumulate
2469 [(unspec:SI [(const_int 0) (reg:SI 1) (reg:SI 2) (reg:SI 3)
2470 (reg:SI 4) (reg:SI 5) (reg:SI 6)]
2471 UNSPEC_BUILTIN_RMPA)
2472 (clobber (reg:SI 1))
2473 (clobber (reg:SI 2))
2474 (clobber (reg:SI 3))]
2477 [(set_attr "length" "2")
2478 (set_attr "timings" "1010")]
2481 ;;---------- Arithmetic ------------------------
2483 ;; Byte swap (two 16-bit values).
2485 [(set (match_operand:SI 0 "register_operand" "=r")
2486 (unspec:SI [(match_operand:SI 1 "register_operand" "r")]
2487 UNSPEC_BUILTIN_REVW))]
2490 [(set_attr "length" "3")]
2493 ;; Round to integer.
2494 (define_insn "lrintsf2"
2495 [(set (match_operand:SI 0 "register_operand" "=r,r")
2496 (unspec:SI [(match_operand:SF 1 "rx_compare_operand" "r,Q")]
2497 UNSPEC_BUILTIN_ROUND))
2498 (clobber (reg:CC CC_REG))]
2501 [(set_attr "timings" "22,44")
2502 (set_attr "length" "3,5")]
2505 ;;---------- Control Registers ------------------------
2507 ;; Clear Processor Status Word
2508 (define_insn "clrpsw"
2509 [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i")]
2510 UNSPEC_BUILTIN_CLRPSW)
2511 (clobber (reg:CC CC_REG))]
2514 [(set_attr "length" "2")]
2517 ;; Set Processor Status Word
2518 (define_insn "setpsw"
2519 [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i")]
2520 UNSPEC_BUILTIN_SETPSW)
2521 (clobber (reg:CC CC_REG))]
2524 [(set_attr "length" "2")]
2527 ;; Move from control register
2529 [(set (match_operand:SI 0 "register_operand" "=r")
2530 (unspec_volatile:SI [(match_operand:SI 1 "immediate_operand" "i")]
2531 UNSPEC_BUILTIN_MVFC))]
2534 [(set_attr "length" "3")]
2537 ;; Move to control register
2539 [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i,i")
2540 (match_operand:SI 1 "nonmemory_operand" "r,i")]
2541 UNSPEC_BUILTIN_MVTC)]
2544 [(set_attr "length" "3,7")]
2545 ;; Ignore possible clobbering of the comparison flags in the
2546 ;; PSW register. This is a cc0 target so any cc0 setting
2547 ;; instruction will always be paired with a cc0 user, without
2548 ;; the possibility of this instruction being placed in between
2552 ;; Move to interrupt priority level
2553 (define_insn "mvtipl"
2554 [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "Uint04")]
2555 UNSPEC_BUILTIN_MVTIPL)]
2558 [(set_attr "length" "3")]
2561 ;;---------- Interrupts ------------------------
2565 [(unspec_volatile [(const_int 0)]
2566 UNSPEC_BUILTIN_BRK)]
2569 [(set_attr "length" "1")
2570 (set_attr "timings" "66")]
2575 [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i")]
2576 UNSPEC_BUILTIN_INT)]
2579 [(set_attr "length" "3")]
2584 [(unspec_volatile [(const_int 0)]
2585 UNSPEC_BUILTIN_WAIT)]
2588 [(set_attr "length" "2")]
2591 ;;---------- CoProcessor Support ------------------------
2593 ;; FIXME: The instructions are currently commented out because
2594 ;; the bit patterns have not been finalized, so the assembler
2595 ;; does not support them. Once they are decided and the assembler
2596 ;; supports them, enable the instructions here.
2598 ;; Move from co-processor register
2599 (define_insn "mvfcp"
2600 [(set (match_operand:SI 0 "register_operand" "=r")
2601 (unspec:SI [(match_operand:SI 1 "immediate_operand" "i")
2602 (match_operand:SI 2 "immediate_operand" "i")]
2603 UNSPEC_BUILTIN_MVFCP))]
2605 "; mvfcp\t%1, %0, %2"
2606 [(set_attr "length" "5")]
2609 ;;---------- Misc ------------------------
2611 ;; Required by cfglayout.c...
2616 [(set_attr "length" "1")]
2619 (define_expand "pid_addr"
2620 [(plus:SI (match_operand:SI 0)
2621 (const:SI (unspec:SI [(match_operand:SI 1)] UNSPEC_PID_ADDR)))]