1 ;; Machine Description for Renesas RX processors
2 ;; Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
3 ;; Contributed by Red Hat.
5 ;; This file is part of GCC.
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)
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.
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/>.
22 ;; This code iterator is used for sign- and zero- extensions.
23 (define_mode_iterator small_int_modes [(HI "") (QI "")])
25 ;; This code iterator is used for max and min operations.
26 (define_mode_iterator int_modes [(SI "") (HI "") (QI "")])
28 ;; We do not handle DFmode here because it is either
29 ;; the same as SFmode, or if -m64bit-doubles is active
30 ;; then all operations on doubles have to be handled by
32 (define_mode_iterator register_modes
33 [(SF "ALLOW_RX_FPU_INSNS") (SI "") (HI "") (QI "")])
54 (UNSPEC_BUILTIN_BRK 30)
55 (UNSPEC_BUILTIN_CLRPSW 31)
56 (UNSPEC_BUILTIN_INT 32)
57 (UNSPEC_BUILTIN_MACHI 33)
58 (UNSPEC_BUILTIN_MACLO 34)
59 (UNSPEC_BUILTIN_MULHI 35)
60 (UNSPEC_BUILTIN_MULLO 36)
61 (UNSPEC_BUILTIN_MVFACHI 37)
62 (UNSPEC_BUILTIN_MVFACMI 38)
63 (UNSPEC_BUILTIN_MVFC 39)
64 (UNSPEC_BUILTIN_MVFCP 40)
65 (UNSPEC_BUILTIN_MVTACHI 41)
66 (UNSPEC_BUILTIN_MVTACLO 42)
67 (UNSPEC_BUILTIN_MVTC 43)
68 (UNSPEC_BUILTIN_MVTIPL 44)
69 (UNSPEC_BUILTIN_RACW 45)
70 (UNSPEC_BUILTIN_REVW 46)
71 (UNSPEC_BUILTIN_RMPA 47)
72 (UNSPEC_BUILTIN_ROUND 48)
73 (UNSPEC_BUILTIN_SAT 49)
74 (UNSPEC_BUILTIN_SETPSW 50)
75 (UNSPEC_BUILTIN_WAIT 51)
79 (define_attr "length" "" (const_int 8))
81 (include "predicates.md")
82 (include "constraints.md")
84 ;; Pipeline description.
86 ;; The RX only has a single pipeline. It has five stages (fetch,
87 ;; decode, execute, memory access, writeback) each of which normally
88 ;; takes a single CPU clock cycle.
90 ;; The timings attribute consists of two numbers, the first is the
91 ;; throughput, which is the number of cycles the instruction takes
92 ;; to execute and generate a result. The second is the latency
93 ;; which is the effective number of cycles the instruction takes to
94 ;; execute if its result is used by the following instruction. The
95 ;; latency is always greater than or equal to the throughput.
96 ;; These values were taken from tables 2.13 and 2.14 in section 2.8
97 ;; of the RX610 Group Hardware Manual v0.11
99 ;; Note - it would be nice to use strings rather than integers for
100 ;; the possible values of this attribute, so that we can have the
101 ;; gcc build mechanism check for values that are not supported by
102 ;; the reservations below. But this will not work because the code
103 ;; in rx_adjust_sched_cost() needs integers not strings.
105 (define_attr "timings" "" (const_int 11))
107 (define_automaton "pipelining")
108 (define_cpu_unit "throughput" "pipelining")
110 (define_insn_reservation "throughput__1_latency__1" 1
111 (eq_attr "timings" "11") "throughput")
112 (define_insn_reservation "throughput__1_latency__2" 2
113 (eq_attr "timings" "12") "throughput,nothing")
114 (define_insn_reservation "throughput__2_latency__2" 1
115 (eq_attr "timings" "22") "throughput*2")
116 (define_insn_reservation "throughput__3_latency__3" 1
117 (eq_attr "timings" "33") "throughput*3")
118 (define_insn_reservation "throughput__3_latency__4" 2
119 (eq_attr "timings" "34") "throughput*3,nothing")
120 (define_insn_reservation "throughput__4_latency__4" 1
121 (eq_attr "timings" "44") "throughput*4")
122 (define_insn_reservation "throughput__4_latency__5" 2
123 (eq_attr "timings" "45") "throughput*4,nothing")
124 (define_insn_reservation "throughput__5_latency__5" 1
125 (eq_attr "timings" "55") "throughput*5")
126 (define_insn_reservation "throughput__5_latency__6" 2
127 (eq_attr "timings" "56") "throughput*5,nothing")
128 (define_insn_reservation "throughput__6_latency__6" 1
129 (eq_attr "timings" "66") "throughput*6")
130 (define_insn_reservation "throughput_10_latency_10" 1
131 (eq_attr "timings" "1010") "throughput*10")
132 (define_insn_reservation "throughput_11_latency_11" 1
133 (eq_attr "timings" "1111") "throughput*11")
134 (define_insn_reservation "throughput_16_latency_16" 1
135 (eq_attr "timings" "1616") "throughput*16")
136 (define_insn_reservation "throughput_18_latency_18" 1
137 (eq_attr "timings" "1818") "throughput*18")
139 ;; ----------------------------------------------------------------------------
143 ;; Note - we do not specify the two instructions necessary to perform
144 ;; a compare-and-branch in the cbranchsi4 pattern because that would
145 ;; allow the comparison to be moved away from the jump before the reload
146 ;; pass has completed. That would be problematical because reload can
147 ;; generate ADDSI3 instructions which would corrupt the PSW flags.
149 (define_expand "cbranchsi4"
152 (match_operator 0 "comparison_operator"
153 [(match_operand:SI 1 "register_operand")
154 (match_operand:SI 2 "rx_source_operand")])
155 (label_ref (match_operand 3 ""))
160 (define_insn_and_split "*cbranchsi4"
163 (match_operator 3 "comparison_operator"
164 [(match_operand:SI 0 "register_operand" "r")
165 (match_operand:SI 1 "rx_source_operand" "riQ")])
166 (match_operand 2 "label_ref_operand" "")
173 rx_split_cbranch (CCmode, GET_CODE (operands[3]),
174 operands[0], operands[1], operands[2]);
178 (define_insn "*cmpsi"
179 [(set (reg:CC CC_REG)
180 (compare:CC (match_operand:SI 0 "register_operand" "r,r,r,r,r,r,r")
181 (match_operand:SI 1 "rx_source_operand" "r,Uint04,Int08,Sint16,Sint24,i,Q")))]
184 [(set_attr "timings" "11,11,11,11,11,11,33")
185 (set_attr "length" "2,2,3,4,5,6,5")]
188 ;; Canonical method for representing TST.
189 (define_insn_and_split "*cbranchsi4_tst"
192 (match_operator 3 "rx_zs_comparison_operator"
193 [(and:SI (match_operand:SI 0 "register_operand" "r")
194 (match_operand:SI 1 "rx_source_operand" "riQ"))
196 (match_operand 2 "label_ref_operand" "")
203 rx_split_cbranch (CC_ZSmode, GET_CODE (operands[3]),
204 XEXP (operands[3], 0), XEXP (operands[3], 1),
209 ;; Various other ways that GCC codes "var & const"
210 (define_insn_and_split "*cbranchsi4_tst_ext"
213 (match_operator 4 "rx_z_comparison_operator"
215 (match_operand:SI 0 "register_operand" "r")
216 (match_operand:SI 1 "rx_constshift_operand" "")
217 (match_operand:SI 2 "rx_constshift_operand" ""))
219 (match_operand 3 "label_ref_operand" "")
230 mask <<= INTVAL (operands[1]);
232 mask <<= INTVAL (operands[2]);
233 x = gen_rtx_AND (SImode, operands[0], gen_int_mode (mask, SImode));
235 rx_split_cbranch (CC_ZSmode, GET_CODE (operands[4]),
236 x, const0_rtx, operands[3]);
240 (define_insn "*tstsi"
241 [(set (reg:CC_ZS CC_REG)
243 (and:SI (match_operand:SI 0 "register_operand" "r,r,r")
244 (match_operand:SI 1 "rx_source_operand" "r,i,Q"))
248 [(set_attr "timings" "11,11,33")
249 (set_attr "length" "3,7,6")]
252 (define_expand "cbranchsf4"
255 (match_operator 0 "rx_fp_comparison_operator"
256 [(match_operand:SF 1 "register_operand")
257 (match_operand:SF 2 "rx_source_operand")])
258 (label_ref (match_operand 3 ""))
263 (define_insn_and_split "*cbranchsf4"
266 (match_operator 3 "rx_fp_comparison_operator"
267 [(match_operand:SF 0 "register_operand" "r")
268 (match_operand:SF 1 "rx_source_operand" "rFQ")])
269 (match_operand 2 "label_ref_operand" "")
273 "&& reload_completed"
276 rx_split_cbranch (CC_Fmode, GET_CODE (operands[3]),
277 operands[0], operands[1], operands[2]);
281 (define_insn "*cmpsf"
282 [(set (reg:CC_F CC_REG)
284 (match_operand:SF 0 "register_operand" "r,r,r")
285 (match_operand:SF 1 "rx_source_operand" "r,F,Q")))]
286 "ALLOW_RX_FPU_INSNS && reload_completed"
288 [(set_attr "timings" "11,11,33")
289 (set_attr "length" "3,7,5")]
292 ;; Flow Control Instructions:
294 (define_insn "*conditional_branch"
297 (match_operator 1 "comparison_operator"
298 [(reg CC_REG) (const_int 0)])
299 (label_ref (match_operand 0 "" ""))
303 [(set_attr "length" "8") ;; This length is wrong, but it is
304 ;; too hard to compute statically.
305 (set_attr "timings" "33")] ;; The timing assumes that the branch is taken.
308 ;; ----------------------------------------------------------------------------
312 (label_ref (match_operand 0 "" "")))]
315 [(set_attr "length" "4")
316 (set_attr "timings" "33")]
319 (define_insn "indirect_jump"
321 (match_operand:SI 0 "register_operand" "r"))]
324 [(set_attr "length" "2")
325 (set_attr "timings" "33")]
328 (define_insn "tablejump"
330 (match_operand:SI 0 "register_operand" "r"))
331 (use (label_ref (match_operand 1 "" "")))]
333 { return flag_pic ? (TARGET_AS100_SYNTAX ? "\n?:\tbra\t%0"
337 [(set_attr "timings" "33")
338 (set_attr "length" "2")]
341 (define_insn "simple_return"
345 [(set_attr "length" "1")
346 (set_attr "timings" "55")]
349 ;; Unspec used so that the constant will not be invalid
350 ;; if -mmax-constant-size has been specified.
351 (define_insn "deallocate_and_return"
352 [(set (reg:SI SP_REG)
353 (plus:SI (reg:SI SP_REG)
354 (const:SI (unspec:SI [(match_operand 0 "const_int_operand" "n")] UNSPEC_CONST))))
358 [(set_attr "length" "2")
359 (set_attr "timings" "55")]
362 (define_insn "pop_and_return"
363 [(match_parallel 1 "rx_rtsd_vector"
364 [(set (reg:SI SP_REG)
365 (plus:SI (reg:SI SP_REG)
366 (match_operand:SI 0 "const_int_operand" "n")))])
370 rx_emit_stack_popm (operands, false);
373 [(set_attr "length" "3")
374 (set_attr "timings" "56")]
377 (define_insn "fast_interrupt_return"
378 [(unspec_volatile [(return)] UNSPEC_RTFI) ]
381 [(set_attr "length" "2")
382 (set_attr "timings" "33")]
385 (define_insn "exception_return"
386 [(unspec_volatile [(return)] UNSPEC_RTE) ]
389 [(set_attr "length" "2")
390 (set_attr "timings" "66")]
393 (define_insn "naked_return"
394 [(unspec_volatile [(return)] UNSPEC_NAKED) ]
396 "; Naked function: epilogue provided by programmer."
400 ;; Note - the following set of patterns do not use the "memory_operand"
401 ;; predicate or an "m" constraint because we do not allow symbol_refs
402 ;; or label_refs as legitmate memory addresses. This matches the
403 ;; behaviour of most of the RX instructions. Only the call/branch
404 ;; instructions are allowed to refer to symbols/labels directly.
405 ;; The call operands are in QImode because that is the value of
408 (define_expand "call"
409 [(call (match_operand:QI 0 "general_operand")
410 (match_operand:SI 1 "general_operand"))]
413 rtx dest = XEXP (operands[0], 0);
415 if (! rx_call_operand (dest, Pmode))
416 dest = force_reg (Pmode, dest);
417 emit_call_insn (gen_call_internal (dest));
422 (define_insn "call_internal"
423 [(call (mem:QI (match_operand:SI 0 "rx_call_operand" "r,Symbol"))
425 (clobber (reg:CC CC_REG))]
430 [(set_attr "length" "2,4")
431 (set_attr "timings" "33")]
434 (define_expand "call_value"
435 [(set (match_operand 0 "register_operand")
436 (call (match_operand:QI 1 "general_operand")
437 (match_operand:SI 2 "general_operand")))]
440 rtx dest = XEXP (operands[1], 0);
442 if (! rx_call_operand (dest, Pmode))
443 dest = force_reg (Pmode, dest);
444 emit_call_insn (gen_call_value_internal (operands[0], dest));
449 (define_insn "call_value_internal"
450 [(set (match_operand 0 "register_operand" "=r,r")
451 (call (mem:QI (match_operand:SI 1 "rx_call_operand" "r,Symbol"))
453 (clobber (reg:CC CC_REG))]
458 [(set_attr "length" "2,4")
459 (set_attr "timings" "33")]
462 ;; Note - we do not allow indirect sibcalls (with the address
463 ;; held in a register) because we cannot guarantee that the register
464 ;; chosen will be a call-used one. If it is a call-saved register,
465 ;; then the epilogue code will corrupt it by popping the saved value
467 (define_expand "sibcall"
469 [(call (mem:QI (match_operand:SI 0 "rx_symbolic_call_operand"))
470 (match_operand:SI 1 "general_operand"))
474 if (MEM_P (operands[0]))
475 operands[0] = XEXP (operands[0], 0);
476 emit_call_insn (gen_sibcall_internal (operands[0]));
481 (define_insn "sibcall_internal"
482 [(call (mem:QI (match_operand:SI 0 "rx_symbolic_call_operand" "Symbol"))
487 [(set_attr "length" "4")
488 (set_attr "timings" "33")]
491 (define_expand "sibcall_value"
493 [(set (match_operand 0 "register_operand")
494 (call (mem:QI (match_operand:SI 1 "rx_symbolic_call_operand"))
495 (match_operand:SI 2 "general_operand")))
499 if (MEM_P (operands[1]))
500 operands[1] = XEXP (operands[1], 0);
501 emit_call_insn (gen_sibcall_value_internal (operands[0], operands[1]));
506 (define_insn "sibcall_value_internal"
507 [(set (match_operand 0 "register_operand" "=r")
508 (call (mem:QI (match_operand:SI 1 "rx_symbolic_call_operand" "Symbol"))
513 [(set_attr "length" "4")
514 (set_attr "timings" "33")]
517 ;; Function Prologue/Epilogue Instructions
519 (define_expand "prologue"
522 "rx_expand_prologue (); DONE;"
525 (define_expand "epilogue"
528 "rx_expand_epilogue (false); DONE;"
531 (define_expand "sibcall_epilogue"
534 "rx_expand_epilogue (true); DONE;"
539 ;; Note - we do not allow memory to memory moves, even though the ISA
540 ;; supports them. The reason is that the conditions on such moves are
541 ;; too restrictive, specifically the source addressing mode is limited
542 ;; by the destination addressing mode and vice versa. (For example it
543 ;; is not possible to use indexed register indirect addressing for one
544 ;; of the operands if the other operand is anything other than a register,
545 ;; but it is possible to use register relative addressing when the other
546 ;; operand also uses register relative or register indirect addressing).
548 ;; GCC does not support computing legitimate addresses based on the
549 ;; nature of other operands involved in the instruction, and reload is
550 ;; not smart enough to cope with a whole variety of different memory
551 ;; addressing constraints, so it is simpler and safer to just refuse
552 ;; to support memory to memory moves.
554 (define_expand "mov<register_modes:mode>"
555 [(set (match_operand:register_modes 0 "general_operand")
556 (match_operand:register_modes 1 "general_operand"))]
559 if (MEM_P (operand0) && MEM_P (operand1))
560 operands[1] = copy_to_mode_reg (<register_modes:MODE>mode, operand1);
561 if (CONST_INT_P (operand1)
562 && ! rx_is_legitimate_constant (<register_modes:MODE>mode, operand1))
567 (define_insn "*mov<register_modes:mode>_internal"
568 [(set (match_operand:register_modes
569 0 "nonimmediate_operand" "=r,r,r,r,r,r,m,Q,Q,Q,Q")
570 (match_operand:register_modes
571 1 "general_operand" "Int08,Sint16,Sint24,i,r,m,r,Int08,Sint16,Sint24,i"))]
573 { return rx_gen_move_template (operands, false); }
574 [(set_attr "length" "3,4,5,6,2,4,6,5,6,7,8")
575 (set_attr "timings" "11,11,11,11,11,12,11,11,11,11,11")]
578 (define_insn "extend<small_int_modes:mode>si2"
579 [(set (match_operand:SI 0 "register_operand" "=r,r")
580 (sign_extend:SI (match_operand:small_int_modes
581 1 "nonimmediate_operand" "r,m")))]
583 { return rx_gen_move_template (operands, false); }
584 [(set_attr "length" "2,6")
585 (set_attr "timings" "11,12")]
588 (define_insn "zero_extend<small_int_modes:mode>si2"
589 [(set (match_operand:SI 0 "register_operand" "=r,r")
590 (zero_extend:SI (match_operand:small_int_modes
591 1 "nonimmediate_operand" "r,m")))]
593 { return rx_gen_move_template (operands, true); }
594 [(set_attr "length" "2,4")
595 (set_attr "timings" "11,12")]
598 (define_insn "stack_push"
599 [(set (reg:SI SP_REG)
600 (minus:SI (reg:SI SP_REG)
602 (set (mem:SI (reg:SI SP_REG))
603 (match_operand:SI 0 "register_operand" "r"))]
606 [(set_attr "length" "2")]
609 (define_insn "stack_pushm"
610 [(match_parallel 1 "rx_store_multiple_vector"
611 [(set (reg:SI SP_REG)
612 (minus:SI (reg:SI SP_REG)
613 (match_operand:SI 0 "const_int_operand" "n")))])]
616 rx_emit_stack_pushm (operands);
619 [(set_attr "length" "2")
620 (set_attr "timings" "44")] ;; The timing is a guesstimate average timing.
623 (define_insn "stack_pop"
624 [(set (match_operand:SI 0 "register_operand" "=r")
625 (mem:SI (reg:SI SP_REG)))
627 (plus:SI (reg:SI SP_REG)
631 [(set_attr "length" "2")
632 (set_attr "timings" "12")]
635 (define_insn "stack_popm"
636 [(match_parallel 1 "rx_load_multiple_vector"
637 [(set (reg:SI SP_REG)
638 (plus:SI (reg:SI SP_REG)
639 (match_operand:SI 0 "const_int_operand" "n")))])]
642 rx_emit_stack_popm (operands, true);
645 [(set_attr "length" "2")
646 (set_attr "timings" "45")] ;; The timing is a guesstimate average timing.
649 (define_insn_and_split "cstoresi4"
650 [(set (match_operand:SI 0 "register_operand" "=r")
651 (match_operator:SI 1 "comparison_operator"
652 [(match_operand:SI 2 "register_operand" "r")
653 (match_operand:SI 3 "rx_source_operand" "riQ")]))
654 (clobber (reg:CC CC_REG))]
662 flags = gen_rtx_REG (CCmode, CC_REG);
663 x = gen_rtx_COMPARE (CCmode, operands[2], operands[3]);
664 x = gen_rtx_SET (VOIDmode, flags, x);
667 x = gen_rtx_fmt_ee (GET_CODE (operands[1]), SImode, flags, const0_rtx);
668 x = gen_rtx_SET (VOIDmode, operands[0], x);
674 [(set (match_operand:SI 0 "register_operand" "=r")
675 (match_operator:SI 1 "comparison_operator"
676 [(reg CC_REG) (const_int 0)]))]
679 [(set_attr "length" "3")]
682 (define_insn_and_split "cstoresf4"
683 [(set (match_operand:SI 0 "register_operand" "=r")
684 (match_operator:SI 1 "rx_fp_comparison_operator"
685 [(match_operand:SF 2 "register_operand" "r")
686 (match_operand:SF 3 "rx_source_operand" "rFQ")]))]
694 flags = gen_rtx_REG (CC_Fmode, CC_REG);
695 x = gen_rtx_COMPARE (CC_Fmode, operands[2], operands[3]);
696 x = gen_rtx_SET (VOIDmode, flags, x);
699 x = gen_rtx_fmt_ee (GET_CODE (operands[1]), SImode, flags, const0_rtx);
700 x = gen_rtx_SET (VOIDmode, operands[0], x);
705 (define_expand "movsicc"
707 [(set (match_operand:SI 0 "register_operand")
708 (if_then_else:SI (match_operand:SI 1 "comparison_operator")
709 (match_operand:SI 2 "nonmemory_operand")
710 (match_operand:SI 3 "nonmemory_operand")))
711 (clobber (reg:CC CC_REG))])]
714 /* One operand must be a constant or a register, the other must be a register. */
715 if ( ! CONSTANT_P (operands[2])
716 && ! CONSTANT_P (operands[3])
717 && ! (REG_P (operands[2]) && REG_P (operands[3])))
721 (define_insn_and_split "*movsicc"
722 [(set (match_operand:SI 0 "register_operand" "=r,r,r")
724 (match_operator 5 "comparison_operator"
725 [(match_operand:SI 3 "register_operand" "r,r,r")
726 (match_operand:SI 4 "rx_source_operand" "riQ,riQ,riQ")])
727 (match_operand:SI 1 "nonmemory_operand" "i,ri,r")
728 (match_operand:SI 2 "nonmemory_operand" "ri,i,r")))
729 (clobber (reg:CC CC_REG))]
730 "(CONSTANT_P (operands[1]) || CONSTANT_P (operands[2]))
731 || (REG_P (operands[1]) && REG_P (operands[2]))"
733 "&& reload_completed"
736 rtx x, flags, op0, op1, op2;
737 enum rtx_code cmp_code;
739 flags = gen_rtx_REG (CCmode, CC_REG);
740 x = gen_rtx_COMPARE (CCmode, operands[3], operands[4]);
741 emit_insn (gen_rtx_SET (VOIDmode, flags, x));
743 cmp_code = GET_CODE (operands[5]);
748 /* If OP2 is the constant, reverse the sense of the move.
749 Likewise if both operands are registers but OP1 == OP0. */
750 if ((! CONSTANT_P (operands[1]) && CONSTANT_P (operands[2]))
751 || (REG_P (operands[1]) && REG_P (operands[2])
752 && rtx_equal_p (op0, op1)))
754 x = op1, op1 = op2, op2 = x;
755 cmp_code = reverse_condition (cmp_code);
758 /* If OP2 does not match the output, copy it into place. We have allowed
759 these alternatives so that the destination can legitimately be one of
760 the comparison operands without increasing register pressure. */
761 if (! rtx_equal_p (op0, op2))
762 emit_move_insn (op0, op2);
764 x = gen_rtx_fmt_ee (cmp_code, VOIDmode, flags, const0_rtx);
765 x = gen_rtx_IF_THEN_ELSE (SImode, x, op1, op0);
766 emit_insn (gen_rtx_SET (VOIDmode, op0, x));
771 [(set (match_operand:SI 0 "register_operand" "+r,r,r,r")
773 (match_operator 2 "rx_z_comparison_operator"
774 [(reg CC_REG) (const_int 0)])
775 (match_operand:SI 1 "immediate_operand" "Sint08,Sint16,Sint24,i")
778 && ((GET_CODE (operands[2]) == EQ) || (GET_CODE (operands[2]) == NE))"
780 if (GET_CODE (operands[2]) == EQ)
781 return "stz\t%1, %0";
783 return "stnz\t%1, %0";
785 [(set_attr "length" "4,5,6,7")]
788 (define_insn "*stcc_reg"
789 [(set (match_operand:SI 0 "register_operand" "+r,r,r,r,r,r")
791 (match_operator 2 "comparison_operator"
792 [(reg CC_REG) (const_int 0)])
793 (match_operand:SI 1 "nonmemory_operand"
794 "r,Uint04,Sint08,Sint16,Sint24,i")
798 PUT_CODE (operands[2], reverse_condition (GET_CODE (operands[2])));
799 return "b%B2 1f\n\tmov %1, %0\n1:";
801 [(set_attr "length" "3,3,4,5,6,7")]
804 ;; Arithmetic Instructions
806 (define_insn "abssi2"
807 [(set (match_operand:SI 0 "register_operand" "=r,r")
808 (abs:SI (match_operand:SI 1 "register_operand" "0,r")))
809 (clobber (reg:CC CC_REG))]
814 [(set_attr "length" "2,3")]
817 (define_insn "*abssi2_flags"
818 [(set (match_operand:SI 0 "register_operand" "=r,r")
819 (abs:SI (match_operand:SI 1 "register_operand" "0,r")))
821 (compare (abs:SI (match_dup 1))
823 ;; Note - although the ABS instruction does set the O bit in the processor
824 ;; status word, it does not do so in a way that is comparable with the CMP
825 ;; instruction. Hence we use CC_ZSmode rather than CC_ZSOmode.
826 "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
830 [(set_attr "length" "2,3")]
833 (define_insn "addsi3"
834 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r,r,r,r,r,r,r,r")
835 (plus:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0,0,r,r,r,r,r,r,0")
836 (match_operand:SI 2 "rx_source_operand" "r,Uint04,NEGint4,Sint08,Sint16,Sint24,i,0,r,Sint08,Sint16,Sint24,i,Q")))
837 (clobber (reg:CC CC_REG))]
854 [(set_attr "timings" "11,11,11,11,11,11,11,11,11,11,11,11,11,33")
855 (set_attr "length" "2,2,2,3,4,5,6,2,3,3,4,5,6,5")]
858 (define_insn "*addsi3_flags"
859 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r,r,r,r,r,r,r,r")
860 (plus:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0,0,r,r,r,r,r,r,0")
861 (match_operand:SI 2 "rx_source_operand" "r,Uint04,NEGint4,Sint08,Sint16,Sint24,i,0,r,Sint08,Sint16,Sint24,i,Q")))
863 (compare (plus:SI (match_dup 1) (match_dup 2))
865 "reload_completed && rx_match_ccmode (insn, CC_ZSCmode)"
881 [(set_attr "timings" "11,11,11,11,11,11,11,11,11,11,11,11,11,33")
882 (set_attr "length" "2,2,2,3,4,5,6,2,3,3,4,5,6,5")]
885 ;; A helper to expand the above with the CC_MODE filled in.
886 (define_expand "addsi3_flags"
887 [(parallel [(set (match_operand:SI 0 "register_operand")
888 (plus:SI (match_operand:SI 1 "register_operand")
889 (match_operand:SI 2 "rx_source_operand")))
890 (set (reg:CC_ZSC CC_REG)
891 (compare:CC_ZSC (plus:SI (match_dup 1) (match_dup 2))
895 (define_insn "adc_internal"
896 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r")
899 (ltu:SI (reg:CC CC_REG) (const_int 0))
900 (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0"))
901 (match_operand:SI 2 "rx_source_operand" "r,Sint08,Sint16,Sint24,i,Q")))
902 (clobber (reg:CC CC_REG))]
905 [(set_attr "timings" "11,11,11,11,11,33")
906 (set_attr "length" "3,4,5,6,7,6")]
909 (define_insn "*adc_flags"
910 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r")
913 (ltu:SI (reg:CC CC_REG) (const_int 0))
914 (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0"))
915 (match_operand:SI 2 "rx_source_operand" "r,Sint08,Sint16,Sint24,i,Q")))
920 (ltu:SI (reg:CC CC_REG) (const_int 0))
924 "reload_completed && rx_match_ccmode (insn, CC_ZSCmode)"
926 [(set_attr "timings" "11,11,11,11,11,33")
927 (set_attr "length" "3,4,5,6,7,6")]
930 ;; Peepholes to match:
931 ;; (set (reg A) (reg B))
932 ;; (set (CC) (compare:CC (reg A/reg B) (const_int 0)))
933 ;; and replace them with the addsi3_flags pattern, using an add
934 ;; of zero to copy the register and set the condition code bits.
936 [(set (match_operand:SI 0 "register_operand")
937 (match_operand:SI 1 "register_operand"))
939 (compare:CC (match_dup 0)
942 [(parallel [(set (match_dup 0)
943 (plus:SI (match_dup 1) (const_int 0)))
944 (set (reg:CC_ZSC CC_REG)
945 (compare:CC_ZSC (plus:SI (match_dup 1) (const_int 0))
950 [(set (match_operand:SI 0 "register_operand")
951 (match_operand:SI 1 "register_operand"))
953 (compare:CC (match_dup 1)
956 [(parallel [(set (match_dup 0)
957 (plus:SI (match_dup 1) (const_int 0)))
958 (set (reg:CC_ZSC CC_REG)
959 (compare:CC_ZSC (plus:SI (match_dup 1) (const_int 0))
963 (define_expand "adddi3"
964 [(set (match_operand:DI 0 "register_operand")
965 (plus:DI (match_operand:DI 1 "register_operand")
966 (match_operand:DI 2 "rx_source_operand")))]
969 rtx op0l, op0h, op1l, op1h, op2l, op2h;
971 op0l = gen_lowpart (SImode, operands[0]);
972 op1l = gen_lowpart (SImode, operands[1]);
973 op2l = gen_lowpart (SImode, operands[2]);
974 op0h = gen_highpart (SImode, operands[0]);
975 op1h = gen_highpart (SImode, operands[1]);
976 op2h = gen_highpart_mode (SImode, DImode, operands[2]);
978 emit_insn (gen_adddi3_internal (op0l, op0h, op1l, op2l, op1h, op2h));
982 (define_insn_and_split "adddi3_internal"
983 [(set (match_operand:SI 0 "register_operand" "=&r")
984 (plus:SI (match_operand:SI 2 "register_operand" "r")
985 (match_operand:SI 3 "rx_source_operand" "riQ")))
986 (set (match_operand:SI 1 "register_operand" "=r")
989 (ltu:SI (plus:SI (match_dup 2) (match_dup 3)) (match_dup 2))
990 (match_operand:SI 4 "register_operand" "%1"))
991 (match_operand:SI 5 "rx_source_operand" "riQ")))
992 (clobber (match_scratch:SI 6 "=&r"))
993 (clobber (reg:CC CC_REG))]
999 rtx op0l = operands[0];
1000 rtx op0h = operands[1];
1001 rtx op1l = operands[2];
1002 rtx op2l = operands[3];
1003 rtx op1h = operands[4];
1004 rtx op2h = operands[5];
1005 rtx scratch = operands[6];
1008 if (reg_overlap_mentioned_p (op0l, op1h))
1010 emit_move_insn (scratch, op0l);
1012 if (reg_overlap_mentioned_p (op0l, op2h))
1015 else if (reg_overlap_mentioned_p (op0l, op2h))
1017 emit_move_insn (scratch, op0l);
1021 if (rtx_equal_p (op0l, op1l))
1023 /* It is preferable that op0l == op1l... */
1024 else if (rtx_equal_p (op0l, op2l))
1025 x = op1l, op1l = op2l, op2l = x;
1026 /* ... but it is only a requirement if op2l == MEM. */
1027 else if (MEM_P (op2l))
1029 /* Let's hope that we still have a scratch register free. */
1030 gcc_assert (op1h != scratch);
1031 emit_move_insn (scratch, op2l);
1035 emit_insn (gen_addsi3_flags (op0l, op1l, op2l));
1037 if (rtx_equal_p (op0h, op1h))
1039 else if (rtx_equal_p (op0h, op2h))
1040 x = op1h, op1h = op2h, op2h = x;
1043 emit_move_insn (op0h, op1h);
1046 emit_insn (gen_adc_internal (op0h, op1h, op2h));
1050 (define_insn "andsi3"
1051 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r,r,r")
1052 (and:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0,r,r,0")
1053 (match_operand:SI 2 "rx_source_operand" "r,Uint04,Sint08,Sint16,Sint24,i,0,r,Q")))
1054 (clobber (reg:CC CC_REG))]
1066 [(set_attr "timings" "11,11,11,11,11,11,11,11,33")
1067 (set_attr "length" "2,2,3,4,5,6,2,5,5")]
1070 (define_insn "*andsi3_flags"
1071 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r,r,r")
1072 (and:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0,r,r,0")
1073 (match_operand:SI 2 "rx_source_operand" "r,Uint04,Sint08,Sint16,Sint24,i,0,r,Q")))
1075 (compare (and:SI (match_dup 1) (match_dup 2))
1077 "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1088 [(set_attr "timings" "11,11,11,11,11,11,11,11,33")
1089 (set_attr "length" "2,2,3,4,5,6,2,5,5")]
1092 ;; Byte swap (single 32-bit value).
1093 (define_insn "bswapsi2"
1094 [(set (match_operand:SI 0 "register_operand" "=r")
1095 (bswap:SI (match_operand:SI 1 "register_operand" "r")))]
1098 [(set_attr "length" "3")]
1101 ;; Byte swap (single 16-bit value). Note - we ignore the swapping of the high 16-bits.
1102 (define_insn "bswaphi2"
1103 [(set (match_operand:HI 0 "register_operand" "=r")
1104 (bswap:HI (match_operand:HI 1 "register_operand" "r")))]
1107 [(set_attr "length" "3")]
1110 (define_insn "divsi3"
1111 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r")
1112 (div:SI (match_operand:SI 1 "register_operand" "0,0,0,0,0,0")
1113 (match_operand:SI 2 "rx_source_operand" "r,Sint08,Sint16,Sint24,i,Q")))
1114 (clobber (reg:CC CC_REG))]
1117 [(set_attr "timings" "1111") ;; Strictly speaking the timing should be
1118 ;; 2222, but that is a worst case sceanario.
1119 (set_attr "length" "3,4,5,6,7,6")]
1122 (define_insn "udivsi3"
1123 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r")
1124 (udiv:SI (match_operand:SI 1 "register_operand" "0,0,0,0,0,0")
1125 (match_operand:SI 2 "rx_source_operand" "r,Sint08,Sint16,Sint24,i,Q")))
1126 (clobber (reg:CC CC_REG))]
1129 [(set_attr "timings" "1010") ;; Strictly speaking the timing should be
1130 ;; 2020, but that is a worst case sceanario.
1131 (set_attr "length" "3,4,5,6,7,6")]
1134 ;; Note - these patterns are suppressed in big-endian mode because they
1135 ;; generate a little endian result. ie the most significant word of the
1136 ;; result is placed in the higher numbered register of the destination
1139 (define_insn "mulsidi3"
1140 [(set (match_operand:DI 0 "register_operand" "=r,r,r,r,r,r")
1141 (mult:DI (sign_extend:DI (match_operand:SI
1142 1 "register_operand" "%0,0,0,0,0,0"))
1143 (sign_extend:DI (match_operand:SI
1144 2 "rx_source_operand"
1145 "r,Sint08,Sint16,Sint24,i,Q"))))]
1146 "! TARGET_BIG_ENDIAN_DATA"
1148 [(set_attr "length" "3,4,5,6,7,6")
1149 (set_attr "timings" "22,22,22,22,22,44")]
1152 ;; See comment for mulsidi3.
1153 ;; Note - the zero_extends are to distinguish this pattern from the
1154 ;; mulsidi3 pattern. Immediate mode addressing is not supported
1155 ;; because gcc cannot handle the expression: (zero_extend (const_int)).
1156 (define_insn "umulsidi3"
1157 [(set (match_operand:DI 0 "register_operand" "=r,r")
1158 (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "%0,0"))
1159 (zero_extend:DI (match_operand:SI 2 "rx_compare_operand" "r,Q"))))]
1160 "! TARGET_BIG_ENDIAN_DATA"
1162 [(set_attr "length" "3,6")
1163 (set_attr "timings" "22,44")]
1166 (define_insn "smaxsi3"
1167 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r")
1168 (smax:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0")
1169 (match_operand:SI 2 "rx_source_operand"
1170 "r,Sint08,Sint16,Sint24,i,Q")))]
1173 [(set_attr "length" "3,4,5,6,7,6")
1174 (set_attr "timings" "11,11,11,11,11,33")]
1177 (define_insn "smin<int_modes:mode>3"
1178 [(set (match_operand:int_modes 0 "register_operand" "=r,r,r,r,r,r")
1179 (smin:int_modes (match_operand:int_modes 1 "register_operand" "%0,0,0,0,0,0")
1180 (match_operand:int_modes 2 "rx_source_operand"
1181 "r,Sint08,Sint16,Sint24,i,Q")))]
1184 [(set_attr "length" "3,4,5,6,7,6")
1185 (set_attr "timings" "11,11,11,11,11,33")]
1188 (define_insn "umax<small_int_modes:mode>3_u"
1189 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r")
1190 (smax:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0")
1191 (zero_extend:SI (match_operand:small_int_modes 2 "rx_minmaxex_operand"
1192 "r,Sint08,Sint16,Sint24,i,Q"))))]
1195 [(set_attr "length" "3,4,5,6,7,6")
1196 (set_attr "timings" "11,11,11,11,11,33")]
1199 (define_insn "umin<small_int_modes:mode>3_ur"
1200 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r")
1201 (smin:SI (zero_extend:SI (match_operand:small_int_modes 2 "rx_minmaxex_operand"
1202 "r,Sint08,Sint16,Sint24,i,Q"))
1203 (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0")))]
1206 [(set_attr "length" "3,4,5,6,7,6")
1207 (set_attr "timings" "11,11,11,11,11,33")]
1210 (define_insn "umax<small_int_modes:mode>3_ur"
1211 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r")
1212 (smax:SI (zero_extend:SI (match_operand:small_int_modes 2 "rx_minmaxex_operand"
1213 "r,Sint08,Sint16,Sint24,i,Q"))
1214 (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0")))]
1217 [(set_attr "length" "3,4,5,6,7,6")
1218 (set_attr "timings" "11,11,11,11,11,33")]
1221 (define_expand "umax<small_int_modes:mode>3"
1223 (zero_extend:SI (match_operand:small_int_modes 1 "register_operand" "%0,0,0,0,0,0")))
1225 (smax:SI (match_dup 4)
1226 (match_operand:small_int_modes 2 "rx_source_operand"
1227 "r,Sint08,Sint16,Sint24,i,Q")))
1228 (set (match_operand:small_int_modes 0 "register_operand" "=r,r,r,r,r,r")
1232 "operands[3] = gen_reg_rtx (SImode);
1233 operands[4] = gen_reg_rtx (SImode);
1234 operands[5] = gen_reg_rtx (SImode);
1235 operands[6] = gen_rtx_SUBREG (GET_MODE (operands[0]), operands[3],
1236 TARGET_BIG_ENDIAN_DATA ? (GET_MODE (operands[0]) == HImode ? 2 : 3) : 0);
1237 if (GET_CODE (operands[2]) != CONST_INT)
1239 emit_move_insn (operands[5], gen_rtx_ZERO_EXTEND (SImode, operands[2]));
1240 operands[2] = operands[5];
1245 (define_expand "umin<small_int_modes:mode>3"
1247 (zero_extend:SI (match_operand:small_int_modes 1 "register_operand" "%0,0,0,0,0,0")))
1249 (smin:SI (match_dup 4)
1250 (match_operand:small_int_modes 2 "rx_source_operand"
1251 "r,Sint08,Sint16,Sint24,i,Q")))
1252 (set (match_operand:small_int_modes 0 "register_operand" "=r,r,r,r,r,r")
1256 "operands[3] = gen_reg_rtx (SImode);
1257 operands[4] = gen_reg_rtx (SImode);
1258 operands[5] = gen_reg_rtx (SImode);
1259 operands[6] = gen_rtx_SUBREG (GET_MODE (operands[0]), operands[3],
1260 TARGET_BIG_ENDIAN_DATA ? (GET_MODE (operands[0]) == HImode ? 2 : 3) : 0);
1261 if (GET_CODE (operands[2]) != CONST_INT)
1263 emit_move_insn (operands[5], gen_rtx_ZERO_EXTEND (SImode, operands[2]));
1264 operands[2] = operands[5];
1269 (define_insn "mulsi3"
1270 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r,r,r")
1271 (mult:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0,0,r,r")
1272 (match_operand:SI 2 "rx_source_operand"
1273 "r,Uint04,Sint08,Sint16,Sint24,i,Q,0,r")))]
1285 [(set_attr "length" "2,2,3,4,5,6,5,2,3")
1286 (set_attr "timings" "11,11,11,11,11,11,33,11,11")]
1289 (define_insn "negsi2"
1290 [(set (match_operand:SI 0 "register_operand" "=r,r")
1291 (neg:SI (match_operand:SI 1 "register_operand" "0,r")))
1292 (clobber (reg:CC CC_REG))]
1297 [(set_attr "length" "2,3")]
1300 ;; Note that the O and C flags are not set as per a normal compare,
1301 ;; and thus are unusable in that context.
1302 (define_insn "*negsi2_flags"
1303 [(set (match_operand:SI 0 "register_operand" "=r,r")
1304 (neg:SI (match_operand:SI 1 "register_operand" "0,r")))
1306 (compare (neg:SI (match_dup 1))
1308 "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1312 [(set_attr "length" "2,3")]
1315 (define_insn "one_cmplsi2"
1316 [(set (match_operand:SI 0 "register_operand" "=r,r")
1317 (not:SI (match_operand:SI 1 "register_operand" "0,r")))
1318 (clobber (reg:CC CC_REG))]
1323 [(set_attr "length" "2,3")]
1326 (define_insn "*one_cmplsi2_flags"
1327 [(set (match_operand:SI 0 "register_operand" "=r,r")
1328 (not:SI (match_operand:SI 1 "register_operand" "0,r")))
1330 (compare (not:SI (match_dup 1))
1332 "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1336 [(set_attr "length" "2,3")]
1339 (define_insn "iorsi3"
1340 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r,r,r")
1341 (ior:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0,r,r,0")
1342 (match_operand:SI 2 "rx_source_operand" "r,Uint04,Sint08,Sint16,Sint24,i,0,r,Q")))
1343 (clobber (reg:CC CC_REG))]
1355 [(set_attr "timings" "11,11,11,11,11,11,11,11,33")
1356 (set_attr "length" "2,2,3,4,5,6,2,3,5")]
1359 (define_insn "*iorsi3_flags"
1360 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r,r,r")
1361 (ior:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0,r,r,0")
1362 (match_operand:SI 2 "rx_source_operand" "r,Uint04,Sint08,Sint16,Sint24,i,0,r,Q")))
1364 (compare (ior:SI (match_dup 1) (match_dup 2))
1366 "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1377 [(set_attr "timings" "11,11,11,11,11,11,11,11,33")
1378 (set_attr "length" "2,2,3,4,5,6,2,3,5")]
1381 (define_insn "rotlsi3"
1382 [(set (match_operand:SI 0 "register_operand" "=r")
1383 (rotate:SI (match_operand:SI 1 "register_operand" "0")
1384 (match_operand:SI 2 "rx_shift_operand" "rn")))
1385 (clobber (reg:CC CC_REG))]
1388 [(set_attr "length" "3")]
1391 (define_insn "*rotlsi3_flags"
1392 [(set (match_operand:SI 0 "register_operand" "=r")
1393 (rotate:SI (match_operand:SI 1 "register_operand" "0")
1394 (match_operand:SI 2 "rx_shift_operand" "rn")))
1396 (compare (rotate:SI (match_dup 1) (match_dup 2))
1398 "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1400 [(set_attr "length" "3")]
1403 (define_insn "rotrsi3"
1404 [(set (match_operand:SI 0 "register_operand" "=r")
1405 (rotatert:SI (match_operand:SI 1 "register_operand" "0")
1406 (match_operand:SI 2 "rx_shift_operand" "rn")))
1407 (clobber (reg:CC CC_REG))]
1410 [(set_attr "length" "3")]
1413 (define_insn "*rotrsi3_flags"
1414 [(set (match_operand:SI 0 "register_operand" "=r")
1415 (rotatert:SI (match_operand:SI 1 "register_operand" "0")
1416 (match_operand:SI 2 "rx_shift_operand" "rn")))
1418 (compare (rotatert:SI (match_dup 1) (match_dup 2))
1420 "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1422 [(set_attr "length" "3")]
1425 (define_insn "ashrsi3"
1426 [(set (match_operand:SI 0 "register_operand" "=r,r,r")
1427 (ashiftrt:SI (match_operand:SI 1 "register_operand" "0,0,r")
1428 (match_operand:SI 2 "rx_shift_operand" "r,n,n")))
1429 (clobber (reg:CC CC_REG))]
1435 [(set_attr "length" "3,2,3")]
1438 (define_insn "*ashrsi3_flags"
1439 [(set (match_operand:SI 0 "register_operand" "=r,r,r")
1440 (ashiftrt:SI (match_operand:SI 1 "register_operand" "0,0,r")
1441 (match_operand:SI 2 "rx_shift_operand" "r,n,n")))
1443 (compare (ashiftrt:SI (match_dup 1) (match_dup 2))
1445 "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1450 [(set_attr "length" "3,2,3")]
1453 (define_insn "lshrsi3"
1454 [(set (match_operand:SI 0 "register_operand" "=r,r,r")
1455 (lshiftrt:SI (match_operand:SI 1 "register_operand" "0,0,r")
1456 (match_operand:SI 2 "rx_shift_operand" "r,n,n")))
1457 (clobber (reg:CC CC_REG))]
1463 [(set_attr "length" "3,2,3")]
1466 (define_insn "*lshrsi3_flags"
1467 [(set (match_operand:SI 0 "register_operand" "=r,r,r")
1468 (lshiftrt:SI (match_operand:SI 1 "register_operand" "0,0,r")
1469 (match_operand:SI 2 "rx_shift_operand" "r,n,n")))
1471 (compare (lshiftrt:SI (match_dup 1) (match_dup 2))
1473 "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1478 [(set_attr "length" "3,2,3")]
1481 (define_insn "ashlsi3"
1482 [(set (match_operand:SI 0 "register_operand" "=r,r,r")
1483 (ashift:SI (match_operand:SI 1 "register_operand" "0,0,r")
1484 (match_operand:SI 2 "rx_shift_operand" "r,n,n")))
1485 (clobber (reg:CC CC_REG))]
1491 [(set_attr "length" "3,2,3")]
1494 (define_insn "*ashlsi3_flags"
1495 [(set (match_operand:SI 0 "register_operand" "=r,r,r")
1496 (ashift:SI (match_operand:SI 1 "register_operand" "0,0,r")
1497 (match_operand:SI 2 "rx_shift_operand" "r,n,n")))
1499 (compare (ashift:SI (match_dup 1) (match_dup 2))
1501 "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1506 [(set_attr "length" "3,2,3")]
1509 ;; Saturate to 32-bits
1510 (define_insn_and_split "ssaddsi3"
1511 [(set (match_operand:SI 0 "register_operand" "=r")
1512 (ss_plus:SI (match_operand:SI 1 "register_operand" "r")
1513 (match_operand:SI 2 "rx_source_operand" "riQ")))
1514 (clobber (reg:CC CC_REG))]
1518 [(parallel [(set (match_dup 0)
1519 (plus:SI (match_dup 1) (match_dup 2)))
1520 (set (reg:CC_ZSC CC_REG)
1522 (plus:SI (match_dup 1) (match_dup 2))
1525 (unspec:SI [(match_dup 0) (reg:CC CC_REG)]
1526 UNSPEC_BUILTIN_SAT))]
1531 [(set (match_operand:SI 0 "register_operand" "=r")
1532 (unspec:SI [(match_operand:SI 1 "register_operand" "0")
1534 UNSPEC_BUILTIN_SAT))]
1537 [(set_attr "length" "2")]
1540 (define_insn "subsi3"
1541 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r")
1542 (minus:SI (match_operand:SI 1 "register_operand" "0,0,0,r,0")
1543 (match_operand:SI 2 "rx_source_operand" "r,Uint04,n,r,Q")))
1544 (clobber (reg:CC CC_REG))]
1552 [(set_attr "timings" "11,11,11,11,33")
1553 (set_attr "length" "2,2,6,3,5")]
1556 ;; Note that the O flag is set as if (compare op1 op2) not for
1557 ;; what is described here, (compare op0 0).
1558 (define_insn "*subsi3_flags"
1559 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r")
1560 (minus:SI (match_operand:SI 1 "register_operand" "0,0,0,r,0")
1561 (match_operand:SI 2 "rx_source_operand" "r,Uint04,n,r,Q")))
1563 (compare (minus:SI (match_dup 1) (match_dup 2))
1565 "reload_completed && rx_match_ccmode (insn, CC_ZSCmode)"
1572 [(set_attr "timings" "11,11,11,11,33")
1573 (set_attr "length" "2,2,6,3,5")]
1576 ;; A helper to expand the above with the CC_MODE filled in.
1577 (define_expand "subsi3_flags"
1578 [(parallel [(set (match_operand:SI 0 "register_operand")
1579 (minus:SI (match_operand:SI 1 "register_operand")
1580 (match_operand:SI 2 "rx_source_operand")))
1581 (set (reg:CC_ZSC CC_REG)
1582 (compare:CC_ZSC (minus:SI (match_dup 1) (match_dup 2))
1586 (define_insn "sbb_internal"
1587 [(set (match_operand:SI 0 "register_operand" "=r,r")
1590 (match_operand:SI 1 "register_operand" " 0,0")
1591 (match_operand:SI 2 "rx_compare_operand" " r,Q"))
1592 (geu:SI (reg:CC CC_REG) (const_int 0))))
1593 (clobber (reg:CC CC_REG))]
1596 [(set_attr "timings" "11,33")
1597 (set_attr "length" "3,6")]
1600 (define_insn "*sbb_flags"
1601 [(set (match_operand:SI 0 "register_operand" "=r,r")
1604 (match_operand:SI 1 "register_operand" " 0,0")
1605 (match_operand:SI 2 "rx_compare_operand" " r,Q"))
1606 (geu:SI (reg:CC CC_REG) (const_int 0))))
1610 (minus:SI (match_dup 1) (match_dup 2))
1611 (geu:SI (reg:CC CC_REG) (const_int 0)))
1615 [(set_attr "timings" "11,33")
1616 (set_attr "length" "3,6")]
1619 (define_expand "subdi3"
1620 [(set (match_operand:DI 0 "register_operand")
1621 (minus:DI (match_operand:DI 1 "register_operand")
1622 (match_operand:DI 2 "rx_compare_operand")))]
1625 rtx op0l, op0h, op1l, op1h, op2l, op2h;
1627 op0l = gen_lowpart (SImode, operands[0]);
1628 op1l = gen_lowpart (SImode, operands[1]);
1629 op2l = gen_lowpart (SImode, operands[2]);
1630 op0h = gen_highpart (SImode, operands[0]);
1631 op1h = gen_highpart (SImode, operands[1]);
1632 op2h = gen_highpart_mode (SImode, DImode, operands[2]);
1634 emit_insn (gen_subdi3_internal (op0l, op0h, op1l, op2l, op1h, op2h));
1638 (define_insn_and_split "subdi3_internal"
1639 [(set (match_operand:SI 0 "register_operand" "=&r,&r")
1640 (minus:SI (match_operand:SI 2 "register_operand" " 0, r")
1641 (match_operand:SI 3 "rx_compare_operand" "rQ, r")))
1642 (set (match_operand:SI 1 "register_operand" "= r, r")
1645 (match_operand:SI 4 "register_operand" " 1, 1")
1646 (match_operand:SI 5 "rx_compare_operand" " rQ,rQ"))
1647 (geu:SI (match_dup 2) (match_dup 3))))
1648 (clobber (reg:CC CC_REG))]
1654 emit_insn (gen_subsi3_flags (operands[0], operands[2], operands[3]));
1655 emit_insn (gen_sbb_internal (operands[1], operands[4], operands[5]));
1659 (define_insn "xorsi3"
1660 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r")
1661 (xor:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0")
1662 (match_operand:SI 2 "rx_source_operand"
1663 "r,Sint08,Sint16,Sint24,i,Q")))
1664 (clobber (reg:CC CC_REG))]
1667 [(set_attr "timings" "11,11,11,11,11,33")
1668 (set_attr "length" "3,4,5,6,7,6")]
1671 (define_insn "*xorsi3_flags"
1672 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r")
1673 (xor:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0")
1674 (match_operand:SI 2 "rx_source_operand"
1675 "r,Sint08,Sint16,Sint24,i,Q")))
1677 (compare (xor:SI (match_dup 1) (match_dup 2))
1679 "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1681 [(set_attr "timings" "11,11,11,11,11,33")
1682 (set_attr "length" "3,4,5,6,7,6")]
1685 ;; A set of peepholes to catch extending loads followed by arithmetic operations.
1686 ;; We use iterators where possible to reduce the amount of typing and hence the
1687 ;; possibilities for typos.
1689 (define_code_iterator extend_types [(zero_extend "") (sign_extend "")])
1690 (define_code_attr letter [(zero_extend "R") (sign_extend "Q")])
1692 (define_code_iterator memex_commutative [(plus "") (and "") (ior "") (xor "")])
1693 (define_code_iterator memex_noncomm [(div "") (udiv "") (minus "")])
1694 (define_code_iterator memex_nocc [(smax "") (smin "") (mult "")])
1696 (define_code_attr op [(plus "add") (and "and") (div "div") (udiv "divu") (smax "max") (smin "min") (mult "mul") (ior "or") (minus "sub") (xor "xor")])
1699 [(set (match_operand:SI 0 "register_operand")
1700 (extend_types:SI (match_operand:small_int_modes 1 "rx_restricted_mem_operand")))
1701 (parallel [(set (match_operand:SI 2 "register_operand")
1702 (memex_commutative:SI (match_dup 0)
1704 (clobber (reg:CC CC_REG))])]
1705 "peep2_regno_dead_p (2, REGNO (operands[0])) && (optimize < 3 || optimize_size)"
1706 [(parallel [(set:SI (match_dup 2)
1707 (memex_commutative:SI (match_dup 2)
1708 (extend_types:SI (match_dup 1))))
1709 (clobber (reg:CC CC_REG))])]
1713 [(set (match_operand:SI 0 "register_operand")
1714 (extend_types:SI (match_operand:small_int_modes 1 "rx_restricted_mem_operand")))
1715 (parallel [(set (match_operand:SI 2 "register_operand")
1716 (memex_commutative:SI (match_dup 2)
1718 (clobber (reg:CC CC_REG))])]
1719 "peep2_regno_dead_p (2, REGNO (operands[0])) && (optimize < 3 || optimize_size)"
1720 [(parallel [(set:SI (match_dup 2)
1721 (memex_commutative:SI (match_dup 2)
1722 (extend_types:SI (match_dup 1))))
1723 (clobber (reg:CC CC_REG))])]
1727 [(set (match_operand:SI 0 "register_operand")
1728 (extend_types:SI (match_operand:small_int_modes 1 "rx_restricted_mem_operand")))
1729 (parallel [(set (match_operand:SI 2 "register_operand")
1730 (memex_noncomm:SI (match_dup 2)
1732 (clobber (reg:CC CC_REG))])]
1733 "peep2_regno_dead_p (2, REGNO (operands[0])) && (optimize < 3 || optimize_size)"
1734 [(parallel [(set:SI (match_dup 2)
1735 (memex_noncomm:SI (match_dup 2)
1736 (extend_types:SI (match_dup 1))))
1737 (clobber (reg:CC CC_REG))])]
1741 [(set (match_operand:SI 0 "register_operand")
1742 (extend_types:SI (match_operand:small_int_modes 1 "rx_restricted_mem_operand")))
1743 (set (match_operand:SI 2 "register_operand")
1744 (memex_nocc:SI (match_dup 0)
1746 "peep2_regno_dead_p (2, REGNO (operands[0])) && (optimize < 3 || optimize_size)"
1747 [(set:SI (match_dup 2)
1748 (memex_nocc:SI (match_dup 2)
1749 (extend_types:SI (match_dup 1))))]
1753 [(set (match_operand:SI 0 "register_operand")
1754 (extend_types:SI (match_operand:small_int_modes 1 "rx_restricted_mem_operand")))
1755 (set (match_operand:SI 2 "register_operand")
1756 (memex_nocc:SI (match_dup 2)
1758 "peep2_regno_dead_p (2, REGNO (operands[0])) && (optimize < 3 || optimize_size)"
1759 [(set:SI (match_dup 2)
1760 (memex_nocc:SI (match_dup 2)
1761 (extend_types:SI (match_dup 1))))]
1764 (define_insn "<memex_commutative:code>si3_<extend_types:code><small_int_modes:mode>"
1765 [(set (match_operand:SI 0 "register_operand" "=r")
1766 (memex_commutative:SI (match_operand:SI 1 "register_operand" "%0")
1767 (extend_types:SI (match_operand:small_int_modes 2 "rx_restricted_mem_operand" "Q"))))
1768 (clobber (reg:CC CC_REG))]
1769 "(optimize < 3 || optimize_size)"
1770 "<memex_commutative:op>\t%<extend_types:letter>2, %0"
1771 [(set_attr "timings" "33")
1772 (set_attr "length" "5")] ;; This length is corrected in rx_adjust_insn_length
1775 (define_insn "<memex_noncomm:code>si3_<extend_types:code><small_int_modes:mode>"
1776 [(set (match_operand:SI 0 "register_operand" "=r")
1777 (memex_noncomm:SI (match_operand:SI 1 "register_operand" "0")
1778 (extend_types:SI (match_operand:small_int_modes 2 "rx_restricted_mem_operand" "Q"))))
1779 (clobber (reg:CC CC_REG))]
1780 "(optimize < 3 || optimize_size)"
1781 "<memex_noncomm:op>\t%<extend_types:letter>2, %0"
1782 [(set_attr "timings" "33")
1783 (set_attr "length" "5")] ;; This length is corrected in rx_adjust_insn_length
1786 (define_insn "<memex_nocc:code>si3_<extend_types:code><small_int_modes:mode>"
1787 [(set (match_operand:SI 0 "register_operand" "=r")
1788 (memex_nocc:SI (match_operand:SI 1 "register_operand" "%0")
1789 (extend_types:SI (match_operand:small_int_modes 2 "rx_restricted_mem_operand" "Q"))))]
1790 "(optimize < 3 || optimize_size)"
1791 "<memex_nocc:op>\t%<extend_types:letter>2, %0"
1792 [(set_attr "timings" "33")
1793 (set_attr "length" "5")] ;; This length is corrected in rx_adjust_insn_length
1797 [(set (match_operand:SI 0 "register_operand")
1798 (extend_types:SI (match_operand:small_int_modes 1 "rx_restricted_mem_operand")))
1799 (set (reg:CC CC_REG)
1800 (compare:CC (match_operand:SI 2 "register_operand")
1802 "peep2_regno_dead_p (2, REGNO (operands[0])) && (optimize < 3 || optimize_size)"
1803 [(set (reg:CC CC_REG)
1804 (compare:CC (match_dup 2)
1805 (extend_types:SI (match_dup 1))))]
1809 ;; (set (reg1) (sign_extend (mem))
1810 ;; (set (reg2) (zero_extend (reg1))
1812 ;; (set (reg2) (zero_extend (mem)))
1814 [(set (match_operand:SI 0 "register_operand")
1815 (sign_extend:SI (match_operand:small_int_modes 1 "memory_operand")))
1816 (set (match_operand:SI 2 "register_operand")
1817 (zero_extend:SI (match_operand:small_int_modes 3 "register_operand")))]
1818 "REGNO (operands[0]) == REGNO (operands[3])
1819 && (REGNO (operands[0]) == REGNO (operands[2])
1820 || peep2_regno_dead_p (2, REGNO (operands[0])))"
1822 (zero_extend:SI (match_dup 1)))]
1825 ;; Remove the redundant sign extension from:
1826 ;; (set (reg) (extend (mem)))
1827 ;; (set (reg) (extend (reg)))
1829 [(set (match_operand:SI 0 "register_operand")
1830 (extend_types:SI (match_operand:small_int_modes 1 "memory_operand")))
1832 (extend_types:SI (match_operand:small_int_modes 2 "register_operand")))]
1833 "REGNO (operands[0]) == REGNO (operands[2])"
1834 [(set (match_dup 0) (extend_types:SI (match_dup 1)))]
1837 (define_insn "comparesi3_<extend_types:code><small_int_modes:mode>"
1838 [(set (reg:CC CC_REG)
1839 (compare:CC (match_operand:SI 0 "register_operand" "=r")
1840 (extend_types:SI (match_operand:small_int_modes 1 "rx_restricted_mem_operand" "Q"))))]
1841 "(optimize < 3 || optimize_size)"
1842 "cmp\t%<extend_types:letter>1, %0"
1843 [(set_attr "timings" "33")
1844 (set_attr "length" "5")] ;; This length is corrected in rx_adjust_insn_length
1847 ;; Floating Point Instructions
1849 (define_insn "addsf3"
1850 [(set (match_operand:SF 0 "register_operand" "=r,r,r")
1851 (plus:SF (match_operand:SF 1 "register_operand" "%0,0,0")
1852 (match_operand:SF 2 "rx_source_operand" "r,F,Q")))
1853 (clobber (reg:CC CC_REG))]
1854 "ALLOW_RX_FPU_INSNS"
1856 [(set_attr "timings" "44,44,66")
1857 (set_attr "length" "3,7,5")]
1860 (define_insn "divsf3"
1861 [(set (match_operand:SF 0 "register_operand" "=r,r,r")
1862 (div:SF (match_operand:SF 1 "register_operand" "0,0,0")
1863 (match_operand:SF 2 "rx_source_operand" "r,F,Q")))
1864 (clobber (reg:CC CC_REG))]
1865 "ALLOW_RX_FPU_INSNS"
1867 [(set_attr "timings" "1616,1616,1818")
1868 (set_attr "length" "3,7,5")]
1871 (define_insn "mulsf3"
1872 [(set (match_operand:SF 0 "register_operand" "=r,r,r")
1873 (mult:SF (match_operand:SF 1 "register_operand" "%0,0,0")
1874 (match_operand:SF 2 "rx_source_operand" "r,F,Q")))
1875 (clobber (reg:CC CC_REG))]
1876 "ALLOW_RX_FPU_INSNS"
1878 [(set_attr "timings" "33,33,55")
1879 (set_attr "length" "3,7,5")]
1882 (define_insn "subsf3"
1883 [(set (match_operand:SF 0 "register_operand" "=r,r,r")
1884 (minus:SF (match_operand:SF 1 "register_operand" "0,0,0")
1885 (match_operand:SF 2 "rx_source_operand" "r,F,Q")))
1886 (clobber (reg:CC CC_REG))]
1887 "ALLOW_RX_FPU_INSNS"
1889 [(set_attr "timings" "44,44,66")
1890 (set_attr "length" "3,7,5")]
1893 (define_insn "fix_truncsfsi2"
1894 [(set (match_operand:SI 0 "register_operand" "=r,r")
1895 (fix:SI (match_operand:SF 1 "rx_compare_operand" "r,Q")))
1896 (clobber (reg:CC CC_REG))]
1897 "ALLOW_RX_FPU_INSNS"
1899 [(set_attr "timings" "22,44")
1900 (set_attr "length" "3,5")]
1903 (define_insn "floatsisf2"
1904 [(set (match_operand:SF 0 "register_operand" "=r,r")
1905 (float:SF (match_operand:SI 1 "rx_compare_operand" "r,Q")))
1906 (clobber (reg:CC CC_REG))]
1907 "ALLOW_RX_FPU_INSNS"
1909 [(set_attr "timings" "22,44")
1910 (set_attr "length" "3,6")]
1913 ;; Bit manipulation instructions.
1915 ;; ??? The *_in_memory patterns will not be matched without further help.
1916 ;; At one time we had the insv expander generate them, but I suspect that
1917 ;; in general we get better performance by exposing the register load to
1920 ;; An alternate solution would be to re-organize these patterns such
1921 ;; that allow both register and memory operands. This would allow the
1922 ;; register allocator to spill and not load the register operand. This
1923 ;; would be possible only for operations for which we have a constant
1924 ;; bit offset, so that we can adjust the address by ofs/8 and replace
1925 ;; the offset in the insn by ofs%8.
1927 (define_insn "*bitset"
1928 [(set (match_operand:SI 0 "register_operand" "=r")
1929 (ior:SI (ashift:SI (const_int 1)
1930 (match_operand:SI 1 "rx_shift_operand" "ri"))
1931 (match_operand:SI 2 "register_operand" "0")))]
1934 [(set_attr "length" "3")]
1937 (define_insn "*bitset_in_memory"
1938 [(set (match_operand:QI 0 "rx_restricted_mem_operand" "+Q")
1939 (ior:QI (ashift:QI (const_int 1)
1940 (match_operand:QI 1 "nonmemory_operand" "ri"))
1944 [(set_attr "length" "3")
1945 (set_attr "timings" "33")]
1948 (define_insn "*bitinvert"
1949 [(set (match_operand:SI 0 "register_operand" "=r")
1950 (xor:SI (ashift:SI (const_int 1)
1951 (match_operand:SI 1 "rx_shift_operand" "ri"))
1952 (match_operand:SI 2 "register_operand" "0")))]
1955 [(set_attr "length" "3")]
1958 (define_insn "*bitinvert_in_memory"
1959 [(set (match_operand:QI 0 "rx_restricted_mem_operand" "+Q")
1960 (xor:QI (ashift:QI (const_int 1)
1961 (match_operand:QI 1 "nonmemory_operand" "ri"))
1965 [(set_attr "length" "5")
1966 (set_attr "timings" "33")]
1969 (define_insn "*bitclr"
1970 [(set (match_operand:SI 0 "register_operand" "=r")
1974 (match_operand:SI 1 "rx_shift_operand" "ri")))
1975 (match_operand:SI 2 "register_operand" "0")))]
1978 [(set_attr "length" "3")]
1981 (define_insn "*bitclr_in_memory"
1982 [(set (match_operand:QI 0 "rx_restricted_mem_operand" "+Q")
1986 (match_operand:QI 1 "nonmemory_operand" "ri")))
1990 [(set_attr "length" "3")
1991 (set_attr "timings" "33")]
1994 (define_insn "*insv_imm"
1995 [(set (zero_extract:SI
1996 (match_operand:SI 0 "register_operand" "+r")
1998 (match_operand:SI 1 "rx_shift_operand" "ri"))
1999 (match_operand:SI 2 "const_int_operand" ""))]
2002 if (INTVAL (operands[2]) & 1)
2003 return "bset\t%1, %0";
2005 return "bclr\t%1, %0";
2007 [(set_attr "length" "3")]
2010 (define_insn_and_split "rx_insv_reg"
2011 [(set (zero_extract:SI
2012 (match_operand:SI 0 "register_operand" "+r")
2014 (match_operand:SI 1 "const_int_operand" ""))
2015 (match_operand:SI 2 "register_operand" "r"))
2016 (clobber (reg:CC CC_REG))]
2020 [(set (zero_extract:SI (match_dup 0) (const_int 1) (match_dup 1))
2025 /* Emit tst #1, op2. */
2026 flags = gen_rtx_REG (CC_ZSmode, CC_REG);
2027 x = gen_rtx_AND (SImode, operands[2], const1_rtx);
2028 x = gen_rtx_COMPARE (CC_ZSmode, x, const0_rtx);
2029 x = gen_rtx_SET (VOIDmode, flags, x);
2033 operands[3] = gen_rtx_NE (SImode, flags, const0_rtx);
2036 (define_insn_and_split "*insv_cond"
2037 [(set (zero_extract:SI
2038 (match_operand:SI 0 "register_operand" "+r")
2040 (match_operand:SI 1 "const_int_operand" ""))
2041 (match_operator:SI 4 "comparison_operator"
2042 [(match_operand:SI 2 "register_operand" "r")
2043 (match_operand:SI 3 "rx_source_operand" "riQ")]))
2044 (clobber (reg:CC CC_REG))]
2048 [(set (zero_extract:SI (match_dup 0) (const_int 1) (match_dup 1))
2053 flags = gen_rtx_REG (CCmode, CC_REG);
2054 x = gen_rtx_COMPARE (CCmode, operands[2], operands[3]);
2055 x = gen_rtx_SET (VOIDmode, flags, x);
2058 operands[4] = gen_rtx_fmt_ee (GET_CODE (operands[4]), SImode,
2062 (define_insn "*bmcc"
2063 [(set (zero_extract:SI
2064 (match_operand:SI 0 "register_operand" "+r")
2066 (match_operand:SI 1 "const_int_operand" ""))
2067 (match_operator:SI 2 "comparison_operator"
2068 [(reg CC_REG) (const_int 0)]))]
2071 [(set_attr "length" "3")]
2074 ;; Work around the fact that X=Y<0 is preferentially expanded as a shift.
2075 (define_insn_and_split "*insv_cond_lt"
2076 [(set (zero_extract:SI
2077 (match_operand:SI 0 "register_operand" "+r")
2079 (match_operand:SI 1 "const_int_operand" ""))
2080 (match_operator:SI 3 "rshift_operator"
2081 [(match_operand:SI 2 "register_operand" "r")
2083 (clobber (reg:CC CC_REG))]
2087 [(parallel [(set (zero_extract:SI (match_dup 0) (const_int 1) (match_dup 1))
2088 (lt:SI (match_dup 2) (const_int 0)))
2089 (clobber (reg:CC CC_REG))])]
2093 (define_expand "insv"
2094 [(set (zero_extract:SI
2095 (match_operand:SI 0 "register_operand") ;; Destination
2096 (match_operand:SI 1 "const_int_operand") ;; # of bits to set
2097 (match_operand:SI 2 "nonmemory_operand")) ;; Starting bit
2098 (match_operand:SI 3 "nonmemory_operand"))] ;; Bits to insert
2101 /* We only handle single-bit inserts. */
2102 if (!CONST_INT_P (operands[1]) || INTVAL (operands[1]) != 1)
2105 /* Either the bit to insert or the position must be constant. */
2106 if (CONST_INT_P (operands[3]))
2107 operands[3] = GEN_INT (INTVAL (operands[3]) & 1);
2108 else if (CONST_INT_P (operands[2]))
2110 emit_insn (gen_rx_insv_reg (operands[0], operands[2], operands[3]));
2117 ;; Atomic exchange operation.
2119 (define_insn "sync_lock_test_and_setsi"
2120 [(set (match_operand:SI 0 "register_operand" "=r,r")
2121 (match_operand:SI 1 "rx_compare_operand" "=r,Q"))
2123 (match_operand:SI 2 "register_operand" "0,0"))]
2126 [(set_attr "length" "3,6")
2127 (set_attr "timings" "22")]
2130 ;; Block move functions.
2132 (define_expand "movstr"
2133 [(set (match_operand:BLK 1 "memory_operand") ;; Dest
2134 (match_operand:BLK 2 "memory_operand")) ;; Source
2135 (use (match_operand:SI 0 "register_operand")) ;; Updated Dest
2139 rtx addr1 = gen_rtx_REG (SImode, 1);
2140 rtx addr2 = gen_rtx_REG (SImode, 2);
2141 rtx len = gen_rtx_REG (SImode, 3);
2142 rtx dest_copy = gen_reg_rtx (SImode);
2144 emit_move_insn (len, GEN_INT (-1));
2145 emit_move_insn (addr1, force_operand (XEXP (operands[1], 0), NULL_RTX));
2146 emit_move_insn (addr2, force_operand (XEXP (operands[2], 0), NULL_RTX));
2147 operands[1] = replace_equiv_address_nv (operands[1], addr1);
2148 operands[2] = replace_equiv_address_nv (operands[2], addr2);
2149 emit_move_insn (dest_copy, addr1);
2150 emit_insn (gen_rx_movstr ());
2151 emit_move_insn (len, GEN_INT (-1));
2152 emit_insn (gen_rx_strend (operands[0], dest_copy));
2157 (define_insn "rx_movstr"
2158 [(set (mem:BLK (reg:SI 1))
2159 (mem:BLK (reg:SI 2)))
2160 (unspec_volatile:BLK [(reg:SI 1) (reg:SI 2) (reg:SI 3)] UNSPEC_MOVSTR)
2161 (clobber (reg:SI 1))
2162 (clobber (reg:SI 2))
2163 (clobber (reg:SI 3))]
2166 [(set_attr "length" "2")
2167 (set_attr "timings" "1111")] ;; The timing is a guesstimate.
2170 (define_insn "rx_strend"
2171 [(set (match_operand:SI 0 "register_operand" "=r")
2172 (unspec_volatile:SI [(match_operand:SI 1 "register_operand" "r")
2173 (reg:SI 3)] UNSPEC_STRLEN))
2174 (clobber (reg:SI 1))
2175 (clobber (reg:SI 2))
2176 (clobber (reg:SI 3))
2177 (clobber (reg:CC CC_REG))
2180 "mov\t%1, r1\n\tmov\t#0, r2\n\tsuntil.b\n\tmov\tr1, %0\n\tsub\t#1, %0"
2181 [(set_attr "length" "10")
2182 (set_attr "timings" "1111")] ;; The timing is a guesstimate.
2185 (define_expand "movmemsi"
2187 [(set (match_operand:BLK 0 "memory_operand") ;; Dest
2188 (match_operand:BLK 1 "memory_operand")) ;; Source
2189 (use (match_operand:SI 2 "register_operand")) ;; Length in bytes
2190 (match_operand 3 "immediate_operand") ;; Align
2191 (unspec_volatile:BLK [(reg:SI 1) (reg:SI 2) (reg:SI 3)] UNSPEC_MOVMEM)]
2195 rtx addr1 = gen_rtx_REG (SImode, 1);
2196 rtx addr2 = gen_rtx_REG (SImode, 2);
2197 rtx len = gen_rtx_REG (SImode, 3);
2199 /* Do not use when the source or destination are volatile - the SMOVF
2200 instruction will read and write in word sized blocks, which may be
2201 outside of the valid address range. */
2202 if (MEM_P (operands[0]) && MEM_VOLATILE_P (operands[0]))
2204 if (MEM_P (operands[1]) && MEM_VOLATILE_P (operands[1]))
2207 if (REG_P (operands[0]) && (REGNO (operands[0]) == 2
2208 || REGNO (operands[0]) == 3))
2210 if (REG_P (operands[1]) && (REGNO (operands[1]) == 1
2211 || REGNO (operands[1]) == 3))
2213 if (REG_P (operands[2]) && (REGNO (operands[2]) == 1
2214 || REGNO (operands[2]) == 2))
2217 emit_move_insn (addr1, force_operand (XEXP (operands[0], 0), NULL_RTX));
2218 emit_move_insn (addr2, force_operand (XEXP (operands[1], 0), NULL_RTX));
2219 emit_move_insn (len, force_operand (operands[2], NULL_RTX));
2220 operands[0] = replace_equiv_address_nv (operands[0], addr1);
2221 operands[1] = replace_equiv_address_nv (operands[1], addr2);
2222 emit_insn (gen_rx_movmem ());
2227 (define_insn "rx_movmem"
2228 [(set (mem:BLK (reg:SI 1))
2229 (mem:BLK (reg:SI 2)))
2231 (unspec_volatile:BLK [(reg:SI 1) (reg:SI 2) (reg:SI 3)] UNSPEC_MOVMEM)
2232 (clobber (reg:SI 1))
2233 (clobber (reg:SI 2))
2234 (clobber (reg:SI 3))]
2237 [(set_attr "length" "2")
2238 (set_attr "timings" "1111")] ;; The timing is a guesstimate.
2241 (define_expand "setmemsi"
2242 [(set (match_operand:BLK 0 "memory_operand") ;; Dest
2243 (match_operand:QI 2 "nonmemory_operand")) ;; Value
2244 (use (match_operand:SI 1 "nonmemory_operand")) ;; Length
2245 (match_operand 3 "immediate_operand") ;; Align
2246 (unspec_volatile:BLK [(reg:SI 1) (reg:SI 2) (reg:SI 3)] UNSPEC_SETMEM)]
2249 rtx addr = gen_rtx_REG (SImode, 1);
2250 rtx val = gen_rtx_REG (QImode, 2);
2251 rtx len = gen_rtx_REG (SImode, 3);
2253 emit_move_insn (addr, force_operand (XEXP (operands[0], 0), NULL_RTX));
2254 emit_move_insn (len, force_operand (operands[1], NULL_RTX));
2255 emit_move_insn (val, operands[2]);
2256 emit_insn (gen_rx_setmem ());
2261 (define_insn "rx_setmem"
2262 [(set (mem:BLK (reg:SI 1))
2263 (unspec_volatile:BLK [(reg:SI 1) (reg:SI 2) (reg:SI 3)] UNSPEC_SETMEM))
2264 (clobber (reg:SI 1))
2265 (clobber (reg:SI 3))]
2268 [(set_attr "length" "2")
2269 (set_attr "timings" "1111")] ;; The timing is a guesstimate.
2272 (define_expand "cmpstrnsi"
2273 [(set (match_operand:SI 0 "register_operand") ;; Result
2274 (unspec_volatile:SI [(match_operand:BLK 1 "memory_operand") ;; String1
2275 (match_operand:BLK 2 "memory_operand")] ;; String2
2277 (use (match_operand:SI 3 "register_operand")) ;; Max Length
2278 (match_operand:SI 4 "immediate_operand")] ;; Known Align
2281 rtx str1 = gen_rtx_REG (SImode, 1);
2282 rtx str2 = gen_rtx_REG (SImode, 2);
2283 rtx len = gen_rtx_REG (SImode, 3);
2285 emit_move_insn (str1, force_operand (XEXP (operands[1], 0), NULL_RTX));
2286 emit_move_insn (str2, force_operand (XEXP (operands[2], 0), NULL_RTX));
2287 emit_move_insn (len, force_operand (operands[3], NULL_RTX));
2289 emit_insn (gen_rx_cmpstrn (operands[0], operands[1], operands[2]));
2294 (define_expand "cmpstrsi"
2295 [(set (match_operand:SI 0 "register_operand") ;; Result
2296 (unspec_volatile:SI [(match_operand:BLK 1 "memory_operand") ;; String1
2297 (match_operand:BLK 2 "memory_operand")] ;; String2
2299 (match_operand:SI 3 "immediate_operand")] ;; Known Align
2302 rtx str1 = gen_rtx_REG (SImode, 1);
2303 rtx str2 = gen_rtx_REG (SImode, 2);
2304 rtx len = gen_rtx_REG (SImode, 3);
2306 emit_move_insn (str1, force_reg (SImode, XEXP (operands[1], 0)));
2307 emit_move_insn (str2, force_reg (SImode, XEXP (operands[2], 0)));
2308 emit_move_insn (len, GEN_INT (-1));
2310 emit_insn (gen_rx_cmpstrn (operands[0], operands[1], operands[2]));
2315 (define_insn "rx_cmpstrn"
2316 [(set (match_operand:SI 0 "register_operand" "=r")
2317 (unspec_volatile:SI [(reg:SI 1) (reg:SI 2) (reg:SI 3)]
2319 (use (match_operand:BLK 1 "memory_operand" "m"))
2320 (use (match_operand:BLK 2 "memory_operand" "m"))
2321 (clobber (reg:SI 1))
2322 (clobber (reg:SI 2))
2323 (clobber (reg:SI 3))
2324 (clobber (reg:CC CC_REG))]
2326 "scmpu ; Perform the string comparison
2327 mov #-1, %0 ; Set up -1 result (which cannot be created
2329 bnc ?+ ; If Carry is not set skip over
2330 scne.L %0 ; Set result based on Z flag
2333 [(set_attr "length" "9")
2334 (set_attr "timings" "1111")] ;; The timing is a guesstimate.
2337 ;; Builtin Functions
2339 ;; GCC does not have the ability to generate the following instructions
2340 ;; on its own so they are provided as builtins instead. To use them from
2341 ;; a program for example invoke them as __builtin_rx_<insn_name>. For
2344 ;; int short_byte_swap (int arg) { return __builtin_rx_revw (arg); }
2346 ;;---------- Accumulator Support ------------------------
2348 ;; Multiply & Accumulate (high)
2349 (define_insn "machi"
2350 [(unspec:SI [(match_operand:SI 0 "register_operand" "r")
2351 (match_operand:SI 1 "register_operand" "r")]
2352 UNSPEC_BUILTIN_MACHI)]
2355 [(set_attr "length" "3")]
2358 ;; Multiply & Accumulate (low)
2359 (define_insn "maclo"
2360 [(unspec:SI [(match_operand:SI 0 "register_operand" "r")
2361 (match_operand:SI 1 "register_operand" "r")]
2362 UNSPEC_BUILTIN_MACLO)]
2365 [(set_attr "length" "3")]
2369 (define_insn "mulhi"
2370 [(unspec:SI [(match_operand:SI 0 "register_operand" "r")
2371 (match_operand:SI 1 "register_operand" "r")]
2372 UNSPEC_BUILTIN_MULHI)]
2375 [(set_attr "length" "3")]
2379 (define_insn "mullo"
2380 [(unspec:SI [(match_operand:SI 0 "register_operand" "r")
2381 (match_operand:SI 1 "register_operand" "r")]
2382 UNSPEC_BUILTIN_MULLO)]
2385 [(set_attr "length" "3")]
2388 ;; Move from Accumulator (high)
2389 (define_insn "mvfachi"
2390 [(set (match_operand:SI 0 "register_operand" "=r")
2391 (unspec:SI [(const_int 0)]
2392 UNSPEC_BUILTIN_MVFACHI))]
2395 [(set_attr "length" "3")]
2398 ;; Move from Accumulator (middle)
2399 (define_insn "mvfacmi"
2400 [(set (match_operand:SI 0 "register_operand" "=r")
2401 (unspec:SI [(const_int 0)]
2402 UNSPEC_BUILTIN_MVFACMI))]
2405 [(set_attr "length" "3")]
2408 ;; Move to Accumulator (high)
2409 (define_insn "mvtachi"
2410 [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")]
2411 UNSPEC_BUILTIN_MVTACHI)]
2414 [(set_attr "length" "3")]
2417 ;; Move to Accumulator (low)
2418 (define_insn "mvtaclo"
2419 [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")]
2420 UNSPEC_BUILTIN_MVTACLO)]
2423 [(set_attr "length" "3")]
2426 ;; Round Accumulator
2428 [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i")]
2429 UNSPEC_BUILTIN_RACW)]
2432 [(set_attr "length" "3")]
2435 ;; Repeat multiply and accumulate
2437 [(unspec:SI [(const_int 0) (reg:SI 1) (reg:SI 2) (reg:SI 3)
2438 (reg:SI 4) (reg:SI 5) (reg:SI 6)]
2439 UNSPEC_BUILTIN_RMPA)
2440 (clobber (reg:SI 1))
2441 (clobber (reg:SI 2))
2442 (clobber (reg:SI 3))]
2445 [(set_attr "length" "2")
2446 (set_attr "timings" "1010")]
2449 ;;---------- Arithmetic ------------------------
2451 ;; Byte swap (two 16-bit values).
2453 [(set (match_operand:SI 0 "register_operand" "=r")
2454 (unspec:SI [(match_operand:SI 1 "register_operand" "r")]
2455 UNSPEC_BUILTIN_REVW))]
2458 [(set_attr "length" "3")]
2461 ;; Round to integer.
2462 (define_insn "lrintsf2"
2463 [(set (match_operand:SI 0 "register_operand" "=r,r")
2464 (unspec:SI [(match_operand:SF 1 "rx_compare_operand" "r,Q")]
2465 UNSPEC_BUILTIN_ROUND))
2466 (clobber (reg:CC CC_REG))]
2469 [(set_attr "timings" "22,44")
2470 (set_attr "length" "3,5")]
2473 ;;---------- Control Registers ------------------------
2475 ;; Clear Processor Status Word
2476 (define_insn "clrpsw"
2477 [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i")]
2478 UNSPEC_BUILTIN_CLRPSW)
2479 (clobber (reg:CC CC_REG))]
2482 [(set_attr "length" "2")]
2485 ;; Set Processor Status Word
2486 (define_insn "setpsw"
2487 [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i")]
2488 UNSPEC_BUILTIN_SETPSW)
2489 (clobber (reg:CC CC_REG))]
2492 [(set_attr "length" "2")]
2495 ;; Move from control register
2497 [(set (match_operand:SI 0 "register_operand" "=r")
2498 (unspec_volatile:SI [(match_operand:SI 1 "immediate_operand" "i")]
2499 UNSPEC_BUILTIN_MVFC))]
2502 [(set_attr "length" "3")]
2505 ;; Move to control register
2507 [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i,i")
2508 (match_operand:SI 1 "nonmemory_operand" "r,i")]
2509 UNSPEC_BUILTIN_MVTC)]
2512 [(set_attr "length" "3,7")]
2513 ;; Ignore possible clobbering of the comparison flags in the
2514 ;; PSW register. This is a cc0 target so any cc0 setting
2515 ;; instruction will always be paired with a cc0 user, without
2516 ;; the possibility of this instruction being placed in between
2520 ;; Move to interrupt priority level
2521 (define_insn "mvtipl"
2522 [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "Uint04")]
2523 UNSPEC_BUILTIN_MVTIPL)]
2526 [(set_attr "length" "3")]
2529 ;;---------- Interrupts ------------------------
2533 [(unspec_volatile [(const_int 0)]
2534 UNSPEC_BUILTIN_BRK)]
2537 [(set_attr "length" "1")
2538 (set_attr "timings" "66")]
2543 [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i")]
2544 UNSPEC_BUILTIN_INT)]
2547 [(set_attr "length" "3")]
2552 [(unspec_volatile [(const_int 0)]
2553 UNSPEC_BUILTIN_WAIT)]
2556 [(set_attr "length" "2")]
2559 ;;---------- CoProcessor Support ------------------------
2561 ;; FIXME: The instructions are currently commented out because
2562 ;; the bit patterns have not been finalized, so the assembler
2563 ;; does not support them. Once they are decided and the assembler
2564 ;; supports them, enable the instructions here.
2566 ;; Move from co-processor register
2567 (define_insn "mvfcp"
2568 [(set (match_operand:SI 0 "register_operand" "=r")
2569 (unspec:SI [(match_operand:SI 1 "immediate_operand" "i")
2570 (match_operand:SI 2 "immediate_operand" "i")]
2571 UNSPEC_BUILTIN_MVFCP))]
2573 "; mvfcp\t%1, %0, %2"
2574 [(set_attr "length" "5")]
2577 ;;---------- Misc ------------------------
2579 ;; Required by cfglayout.c...
2584 [(set_attr "length" "1")]