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 ;; We do not handle DFmode here because it is either
26 ;; the same as SFmode, or if -m64bit-doubles is active
27 ;; then all operations on doubles have to be handled by
29 (define_mode_iterator register_modes
30 [(SF "ALLOW_RX_FPU_INSNS") (SI "") (HI "") (QI "")])
51 (UNSPEC_BUILTIN_BRK 30)
52 (UNSPEC_BUILTIN_CLRPSW 31)
53 (UNSPEC_BUILTIN_INT 32)
54 (UNSPEC_BUILTIN_MACHI 33)
55 (UNSPEC_BUILTIN_MACLO 34)
56 (UNSPEC_BUILTIN_MULHI 35)
57 (UNSPEC_BUILTIN_MULLO 36)
58 (UNSPEC_BUILTIN_MVFACHI 37)
59 (UNSPEC_BUILTIN_MVFACMI 38)
60 (UNSPEC_BUILTIN_MVFC 39)
61 (UNSPEC_BUILTIN_MVFCP 40)
62 (UNSPEC_BUILTIN_MVTACHI 41)
63 (UNSPEC_BUILTIN_MVTACLO 42)
64 (UNSPEC_BUILTIN_MVTC 43)
65 (UNSPEC_BUILTIN_MVTIPL 44)
66 (UNSPEC_BUILTIN_RACW 45)
67 (UNSPEC_BUILTIN_REVW 46)
68 (UNSPEC_BUILTIN_RMPA 47)
69 (UNSPEC_BUILTIN_ROUND 48)
70 (UNSPEC_BUILTIN_SAT 49)
71 (UNSPEC_BUILTIN_SETPSW 50)
72 (UNSPEC_BUILTIN_WAIT 51)
76 (define_attr "length" "" (const_int 8))
78 (include "predicates.md")
79 (include "constraints.md")
81 ;; Pipeline description.
83 ;; The RX only has a single pipeline. It has five stages (fetch,
84 ;; decode, execute, memory access, writeback) each of which normally
85 ;; takes a single CPU clock cycle.
87 ;; The timings attribute consists of two numbers, the first is the
88 ;; throughput, which is the number of cycles the instruction takes
89 ;; to execute and generate a result. The second is the latency
90 ;; which is the effective number of cycles the instruction takes to
91 ;; execute if its result is used by the following instruction. The
92 ;; latency is always greater than or equal to the throughput.
93 ;; These values were taken from tables 2.13 and 2.14 in section 2.8
94 ;; of the RX610 Group Hardware Manual v0.11
96 ;; Note - it would be nice to use strings rather than integers for
97 ;; the possible values of this attribute, so that we can have the
98 ;; gcc build mechanism check for values that are not supported by
99 ;; the reservations below. But this will not work because the code
100 ;; in rx_adjust_sched_cost() needs integers not strings.
102 (define_attr "timings" "" (const_int 11))
104 (define_automaton "pipelining")
105 (define_cpu_unit "throughput" "pipelining")
107 (define_insn_reservation "throughput__1_latency__1" 1
108 (eq_attr "timings" "11") "throughput")
109 (define_insn_reservation "throughput__1_latency__2" 2
110 (eq_attr "timings" "12") "throughput,nothing")
111 (define_insn_reservation "throughput__2_latency__2" 1
112 (eq_attr "timings" "22") "throughput*2")
113 (define_insn_reservation "throughput__3_latency__3" 1
114 (eq_attr "timings" "33") "throughput*3")
115 (define_insn_reservation "throughput__3_latency__4" 2
116 (eq_attr "timings" "34") "throughput*3,nothing")
117 (define_insn_reservation "throughput__4_latency__4" 1
118 (eq_attr "timings" "44") "throughput*4")
119 (define_insn_reservation "throughput__4_latency__5" 2
120 (eq_attr "timings" "45") "throughput*4,nothing")
121 (define_insn_reservation "throughput__5_latency__5" 1
122 (eq_attr "timings" "55") "throughput*5")
123 (define_insn_reservation "throughput__5_latency__6" 2
124 (eq_attr "timings" "56") "throughput*5,nothing")
125 (define_insn_reservation "throughput__6_latency__6" 1
126 (eq_attr "timings" "66") "throughput*6")
127 (define_insn_reservation "throughput_10_latency_10" 1
128 (eq_attr "timings" "1010") "throughput*10")
129 (define_insn_reservation "throughput_11_latency_11" 1
130 (eq_attr "timings" "1111") "throughput*11")
131 (define_insn_reservation "throughput_16_latency_16" 1
132 (eq_attr "timings" "1616") "throughput*16")
133 (define_insn_reservation "throughput_18_latency_18" 1
134 (eq_attr "timings" "1818") "throughput*18")
136 ;; ----------------------------------------------------------------------------
140 ;; Note - we do not specify the two instructions necessary to perform
141 ;; a compare-and-branch in the cbranchsi4 pattern because that would
142 ;; allow the comparison to be moved away from the jump before the reload
143 ;; pass has completed. That would be problematical because reload can
144 ;; generate ADDSI3 instructions which would corrupt the PSW flags.
146 (define_expand "cbranchsi4"
149 (match_operator 0 "comparison_operator"
150 [(match_operand:SI 1 "register_operand")
151 (match_operand:SI 2 "rx_source_operand")])
152 (label_ref (match_operand 3 ""))
157 (define_insn_and_split "*cbranchsi4"
160 (match_operator 3 "comparison_operator"
161 [(match_operand:SI 0 "register_operand" "r")
162 (match_operand:SI 1 "rx_source_operand" "riQ")])
163 (match_operand 2 "label_ref_operand" "")
170 rx_split_cbranch (CCmode, GET_CODE (operands[3]),
171 operands[0], operands[1], operands[2]);
175 (define_insn "*cmpsi"
176 [(set (reg:CC CC_REG)
177 (compare:CC (match_operand:SI 0 "register_operand" "r,r,r,r,r,r,r")
178 (match_operand:SI 1 "rx_source_operand" "r,Uint04,Int08,Sint16,Sint24,i,Q")))]
181 [(set_attr "timings" "11,11,11,11,11,11,33")
182 (set_attr "length" "2,2,3,4,5,6,5")]
185 ;; Canonical method for representing TST.
186 (define_insn_and_split "*cbranchsi4_tst"
189 (match_operator 3 "rx_zs_comparison_operator"
190 [(and:SI (match_operand:SI 0 "register_operand" "r")
191 (match_operand:SI 1 "rx_source_operand" "riQ"))
193 (match_operand 2 "label_ref_operand" "")
200 rx_split_cbranch (CC_ZSmode, GET_CODE (operands[3]),
201 XEXP (operands[3], 0), XEXP (operands[3], 1),
206 ;; Various other ways that GCC codes "var & const"
207 (define_insn_and_split "*cbranchsi4_tst_ext"
210 (match_operator 4 "rx_z_comparison_operator"
212 (match_operand:SI 0 "register_operand" "r")
213 (match_operand:SI 1 "rx_constshift_operand" "")
214 (match_operand:SI 2 "rx_constshift_operand" ""))
216 (match_operand 3 "label_ref_operand" "")
227 mask <<= INTVAL (operands[1]);
229 mask <<= INTVAL (operands[2]);
230 x = gen_rtx_AND (SImode, operands[0], gen_int_mode (mask, SImode));
232 rx_split_cbranch (CC_ZSmode, GET_CODE (operands[4]),
233 x, const0_rtx, operands[3]);
237 (define_insn "*tstsi"
238 [(set (reg:CC_ZS CC_REG)
240 (and:SI (match_operand:SI 0 "register_operand" "r,r,r")
241 (match_operand:SI 1 "rx_source_operand" "r,i,Q"))
245 [(set_attr "timings" "11,11,33")
246 (set_attr "length" "3,7,6")]
249 (define_expand "cbranchsf4"
252 (match_operator 0 "rx_fp_comparison_operator"
253 [(match_operand:SF 1 "register_operand")
254 (match_operand:SF 2 "rx_source_operand")])
255 (label_ref (match_operand 3 ""))
260 (define_insn_and_split "*cbranchsf4"
263 (match_operator 3 "rx_fp_comparison_operator"
264 [(match_operand:SF 0 "register_operand" "r")
265 (match_operand:SF 1 "rx_source_operand" "rFQ")])
266 (match_operand 2 "label_ref_operand" "")
270 "&& reload_completed"
273 rx_split_cbranch (CC_Fmode, GET_CODE (operands[3]),
274 operands[0], operands[1], operands[2]);
278 (define_insn "*cmpsf"
279 [(set (reg:CC_F CC_REG)
281 (match_operand:SF 0 "register_operand" "r,r,r")
282 (match_operand:SF 1 "rx_source_operand" "r,F,Q")))]
283 "ALLOW_RX_FPU_INSNS && reload_completed"
285 [(set_attr "timings" "11,11,33")
286 (set_attr "length" "3,7,5")]
289 ;; Flow Control Instructions:
291 (define_insn "*conditional_branch"
294 (match_operator 1 "comparison_operator"
295 [(reg CC_REG) (const_int 0)])
296 (label_ref (match_operand 0 "" ""))
300 [(set_attr "length" "8") ;; This length is wrong, but it is
301 ;; too hard to compute statically.
302 (set_attr "timings" "33")] ;; The timing assumes that the branch is taken.
305 ;; ----------------------------------------------------------------------------
309 (label_ref (match_operand 0 "" "")))]
312 [(set_attr "length" "4")
313 (set_attr "timings" "33")]
316 (define_insn "indirect_jump"
318 (match_operand:SI 0 "register_operand" "r"))]
321 [(set_attr "length" "2")
322 (set_attr "timings" "33")]
325 (define_insn "tablejump"
327 (match_operand:SI 0 "register_operand" "r"))
328 (use (label_ref (match_operand 1 "" "")))]
330 { return flag_pic ? (TARGET_AS100_SYNTAX ? "\n?:\tbra\t%0"
334 [(set_attr "timings" "33")
335 (set_attr "length" "2")]
338 (define_insn "simple_return"
342 [(set_attr "length" "1")
343 (set_attr "timings" "55")]
346 ;; Unspec used so that the constant will not be invalid
347 ;; if -mmax-constant-size has been specified.
348 (define_insn "deallocate_and_return"
349 [(set (reg:SI SP_REG)
350 (plus:SI (reg:SI SP_REG)
351 (const:SI (unspec:SI [(match_operand 0 "const_int_operand" "n")] UNSPEC_CONST))))
355 [(set_attr "length" "2")
356 (set_attr "timings" "55")]
359 (define_insn "pop_and_return"
360 [(match_parallel 1 "rx_rtsd_vector"
361 [(set (reg:SI SP_REG)
362 (plus:SI (reg:SI SP_REG)
363 (match_operand:SI 0 "const_int_operand" "n")))])
367 rx_emit_stack_popm (operands, false);
370 [(set_attr "length" "3")
371 (set_attr "timings" "56")]
374 (define_insn "fast_interrupt_return"
375 [(unspec_volatile [(return)] UNSPEC_RTFI) ]
378 [(set_attr "length" "2")
379 (set_attr "timings" "33")]
382 (define_insn "exception_return"
383 [(unspec_volatile [(return)] UNSPEC_RTE) ]
386 [(set_attr "length" "2")
387 (set_attr "timings" "66")]
390 (define_insn "naked_return"
391 [(unspec_volatile [(return)] UNSPEC_NAKED) ]
393 "; Naked function: epilogue provided by programmer."
397 ;; Note - the following set of patterns do not use the "memory_operand"
398 ;; predicate or an "m" constraint because we do not allow symbol_refs
399 ;; or label_refs as legitmate memory addresses. This matches the
400 ;; behaviour of most of the RX instructions. Only the call/branch
401 ;; instructions are allowed to refer to symbols/labels directly.
402 ;; The call operands are in QImode because that is the value of
405 (define_expand "call"
406 [(call (match_operand:QI 0 "general_operand")
407 (match_operand:SI 1 "general_operand"))]
410 rtx dest = XEXP (operands[0], 0);
412 if (! rx_call_operand (dest, Pmode))
413 dest = force_reg (Pmode, dest);
414 emit_call_insn (gen_call_internal (dest));
419 (define_insn "call_internal"
420 [(call (mem:QI (match_operand:SI 0 "rx_call_operand" "r,Symbol"))
422 (clobber (reg:CC CC_REG))]
427 [(set_attr "length" "2,4")
428 (set_attr "timings" "33")]
431 (define_expand "call_value"
432 [(set (match_operand 0 "register_operand")
433 (call (match_operand:QI 1 "general_operand")
434 (match_operand:SI 2 "general_operand")))]
437 rtx dest = XEXP (operands[1], 0);
439 if (! rx_call_operand (dest, Pmode))
440 dest = force_reg (Pmode, dest);
441 emit_call_insn (gen_call_value_internal (operands[0], dest));
446 (define_insn "call_value_internal"
447 [(set (match_operand 0 "register_operand" "=r,r")
448 (call (mem:QI (match_operand:SI 1 "rx_call_operand" "r,Symbol"))
450 (clobber (reg:CC CC_REG))]
455 [(set_attr "length" "2,4")
456 (set_attr "timings" "33")]
459 ;; Note - we do not allow indirect sibcalls (with the address
460 ;; held in a register) because we cannot guarantee that the register
461 ;; chosen will be a call-used one. If it is a call-saved register,
462 ;; then the epilogue code will corrupt it by popping the saved value
464 (define_expand "sibcall"
466 [(call (mem:QI (match_operand:SI 0 "rx_symbolic_call_operand"))
467 (match_operand:SI 1 "general_operand"))
471 if (MEM_P (operands[0]))
472 operands[0] = XEXP (operands[0], 0);
473 emit_call_insn (gen_sibcall_internal (operands[0]));
478 (define_insn "sibcall_internal"
479 [(call (mem:QI (match_operand:SI 0 "rx_symbolic_call_operand" "Symbol"))
484 [(set_attr "length" "4")
485 (set_attr "timings" "33")]
488 (define_expand "sibcall_value"
490 [(set (match_operand 0 "register_operand")
491 (call (mem:QI (match_operand:SI 1 "rx_symbolic_call_operand"))
492 (match_operand:SI 2 "general_operand")))
496 if (MEM_P (operands[1]))
497 operands[1] = XEXP (operands[1], 0);
498 emit_call_insn (gen_sibcall_value_internal (operands[0], operands[1]));
503 (define_insn "sibcall_value_internal"
504 [(set (match_operand 0 "register_operand" "=r")
505 (call (mem:QI (match_operand:SI 1 "rx_symbolic_call_operand" "Symbol"))
510 [(set_attr "length" "4")
511 (set_attr "timings" "33")]
514 ;; Function Prologue/Epilogue Instructions
516 (define_expand "prologue"
519 "rx_expand_prologue (); DONE;"
522 (define_expand "epilogue"
525 "rx_expand_epilogue (false); DONE;"
528 (define_expand "sibcall_epilogue"
531 "rx_expand_epilogue (true); DONE;"
536 ;; Note - we do not allow memory to memory moves, even though the ISA
537 ;; supports them. The reason is that the conditions on such moves are
538 ;; too restrictive, specifically the source addressing mode is limited
539 ;; by the destination addressing mode and vice versa. (For example it
540 ;; is not possible to use indexed register indirect addressing for one
541 ;; of the operands if the other operand is anything other than a register,
542 ;; but it is possible to use register relative addressing when the other
543 ;; operand also uses register relative or register indirect addressing).
545 ;; GCC does not support computing legitimate addresses based on the
546 ;; nature of other operands involved in the instruction, and reload is
547 ;; not smart enough to cope with a whole variety of different memory
548 ;; addressing constraints, so it is simpler and safer to just refuse
549 ;; to support memory to memory moves.
551 (define_expand "mov<register_modes:mode>"
552 [(set (match_operand:register_modes 0 "general_operand")
553 (match_operand:register_modes 1 "general_operand"))]
556 if (MEM_P (operand0) && MEM_P (operand1))
557 operands[1] = copy_to_mode_reg (<register_modes:MODE>mode, operand1);
558 if (CONST_INT_P (operand1)
559 && ! rx_is_legitimate_constant (<register_modes:MODE>mode, operand1))
564 (define_insn "*mov<register_modes:mode>_internal"
565 [(set (match_operand:register_modes
566 0 "nonimmediate_operand" "=r,r,r,r,r,r,m,Q,Q,Q,Q")
567 (match_operand:register_modes
568 1 "general_operand" "Int08,Sint16,Sint24,i,r,m,r,Int08,Sint16,Sint24,i"))]
570 { return rx_gen_move_template (operands, false); }
571 [(set_attr "length" "3,4,5,6,2,4,6,5,6,7,8")
572 (set_attr "timings" "11,11,11,11,11,12,11,11,11,11,11")]
575 (define_insn "extend<small_int_modes:mode>si2"
576 [(set (match_operand:SI 0 "register_operand" "=r,r")
577 (sign_extend:SI (match_operand:small_int_modes
578 1 "nonimmediate_operand" "r,m")))]
580 { return rx_gen_move_template (operands, false); }
581 [(set_attr "length" "2,6")
582 (set_attr "timings" "11,12")]
585 (define_insn "zero_extend<small_int_modes:mode>si2"
586 [(set (match_operand:SI 0 "register_operand" "=r,r")
587 (zero_extend:SI (match_operand:small_int_modes
588 1 "nonimmediate_operand" "r,m")))]
590 { return rx_gen_move_template (operands, true); }
591 [(set_attr "length" "2,4")
592 (set_attr "timings" "11,12")]
595 (define_insn "stack_push"
596 [(set (reg:SI SP_REG)
597 (minus:SI (reg:SI SP_REG)
599 (set (mem:SI (reg:SI SP_REG))
600 (match_operand:SI 0 "register_operand" "r"))]
603 [(set_attr "length" "2")]
606 (define_insn "stack_pushm"
607 [(match_parallel 1 "rx_store_multiple_vector"
608 [(set (reg:SI SP_REG)
609 (minus:SI (reg:SI SP_REG)
610 (match_operand:SI 0 "const_int_operand" "n")))])]
613 rx_emit_stack_pushm (operands);
616 [(set_attr "length" "2")
617 (set_attr "timings" "44")] ;; The timing is a guesstimate average timing.
620 (define_insn "stack_pop"
621 [(set (match_operand:SI 0 "register_operand" "=r")
622 (mem:SI (reg:SI SP_REG)))
624 (plus:SI (reg:SI SP_REG)
628 [(set_attr "length" "2")
629 (set_attr "timings" "12")]
632 (define_insn "stack_popm"
633 [(match_parallel 1 "rx_load_multiple_vector"
634 [(set (reg:SI SP_REG)
635 (plus:SI (reg:SI SP_REG)
636 (match_operand:SI 0 "const_int_operand" "n")))])]
639 rx_emit_stack_popm (operands, true);
642 [(set_attr "length" "2")
643 (set_attr "timings" "45")] ;; The timing is a guesstimate average timing.
646 (define_insn_and_split "cstoresi4"
647 [(set (match_operand:SI 0 "register_operand" "=r")
648 (match_operator:SI 1 "comparison_operator"
649 [(match_operand:SI 2 "register_operand" "r")
650 (match_operand:SI 3 "rx_source_operand" "riQ")]))
651 (clobber (reg:CC CC_REG))]
659 flags = gen_rtx_REG (CCmode, CC_REG);
660 x = gen_rtx_COMPARE (CCmode, operands[2], operands[3]);
661 x = gen_rtx_SET (VOIDmode, flags, x);
664 x = gen_rtx_fmt_ee (GET_CODE (operands[1]), SImode, flags, const0_rtx);
665 x = gen_rtx_SET (VOIDmode, operands[0], x);
671 [(set (match_operand:SI 0 "register_operand" "=r")
672 (match_operator:SI 1 "comparison_operator"
673 [(reg CC_REG) (const_int 0)]))]
676 [(set_attr "length" "3")]
679 (define_insn_and_split "cstoresf4"
680 [(set (match_operand:SI 0 "register_operand" "=r")
681 (match_operator:SI 1 "rx_fp_comparison_operator"
682 [(match_operand:SF 2 "register_operand" "r")
683 (match_operand:SF 3 "rx_source_operand" "rFQ")]))]
691 flags = gen_rtx_REG (CC_Fmode, CC_REG);
692 x = gen_rtx_COMPARE (CC_Fmode, operands[2], operands[3]);
693 x = gen_rtx_SET (VOIDmode, flags, x);
696 x = gen_rtx_fmt_ee (GET_CODE (operands[1]), SImode, flags, const0_rtx);
697 x = gen_rtx_SET (VOIDmode, operands[0], x);
702 (define_expand "movsicc"
704 [(set (match_operand:SI 0 "register_operand")
705 (if_then_else:SI (match_operand:SI 1 "comparison_operator")
706 (match_operand:SI 2 "nonmemory_operand")
707 (match_operand:SI 3 "nonmemory_operand")))
708 (clobber (reg:CC CC_REG))])]
711 /* ??? Support other conditions via cstore into a temporary? */
712 if (GET_CODE (operands[1]) != EQ && GET_CODE (operands[1]) != NE)
714 /* One operand must be a constant. */
715 if (!CONSTANT_P (operands[2]) && !CONSTANT_P (operands[3]))
719 (define_insn_and_split "*movsicc"
720 [(set (match_operand:SI 0 "register_operand" "=r,r")
722 (match_operator 5 "rx_z_comparison_operator"
723 [(match_operand:SI 3 "register_operand" "r,r")
724 (match_operand:SI 4 "rx_source_operand" "riQ,riQ")])
725 (match_operand:SI 1 "nonmemory_operand" "i,ri")
726 (match_operand:SI 2 "nonmemory_operand" "ri,i")))
727 (clobber (reg:CC CC_REG))]
728 "CONSTANT_P (operands[1]) || CONSTANT_P (operands[2])"
730 "&& reload_completed"
733 rtx x, flags, op0, op1, op2;
734 enum rtx_code cmp_code;
736 flags = gen_rtx_REG (CCmode, CC_REG);
737 x = gen_rtx_COMPARE (CCmode, operands[3], operands[4]);
738 emit_insn (gen_rtx_SET (VOIDmode, flags, x));
740 cmp_code = GET_CODE (operands[5]);
745 /* If OP2 is the constant, reverse the sense of the move. */
746 if (!CONSTANT_P (operands[1]))
748 x = op1, op1 = op2, op2 = x;
749 cmp_code = reverse_condition (cmp_code);
752 /* If OP2 does not match the output, copy it into place. We have allowed
753 these alternatives so that the destination can legitimately be one of
754 the comparison operands without increasing register pressure. */
755 if (!rtx_equal_p (op0, op2))
756 emit_move_insn (op0, op2);
758 x = gen_rtx_fmt_ee (cmp_code, VOIDmode, flags, const0_rtx);
759 x = gen_rtx_IF_THEN_ELSE (SImode, x, op1, op0);
760 emit_insn (gen_rtx_SET (VOIDmode, op0, x));
765 [(set (match_operand:SI 0 "register_operand" "+r,r,r,r")
767 (match_operator 2 "rx_z_comparison_operator"
768 [(reg CC_REG) (const_int 0)])
769 (match_operand:SI 1 "immediate_operand" "Sint08,Sint16,Sint24,i")
773 if (GET_CODE (operands[2]) == EQ)
774 return "stz\t%1, %0";
776 return "stnz\t%1, %0";
778 [(set_attr "length" "4,5,6,7")]
781 ;; Arithmetic Instructions
783 (define_insn "abssi2"
784 [(set (match_operand:SI 0 "register_operand" "=r,r")
785 (abs:SI (match_operand:SI 1 "register_operand" "0,r")))
786 (clobber (reg:CC CC_REG))]
791 [(set_attr "length" "2,3")]
794 (define_insn "*abssi2_flags"
795 [(set (match_operand:SI 0 "register_operand" "=r,r")
796 (abs:SI (match_operand:SI 1 "register_operand" "0,r")))
798 (compare (abs:SI (match_dup 1))
800 ;; Note - although the ABS instruction does set the O bit in the processor
801 ;; status word, it does not do so in a way that is comparable with the CMP
802 ;; instruction. Hence we use CC_ZSmode rather than CC_ZSOmode.
803 "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
807 [(set_attr "length" "2,3")]
810 (define_insn "addsi3"
811 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r,r,r,r,r,r,r,r")
812 (plus:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0,0,r,r,r,r,r,r,0")
813 (match_operand:SI 2 "rx_source_operand" "r,Uint04,NEGint4,Sint08,Sint16,Sint24,i,0,r,Sint08,Sint16,Sint24,i,Q")))
814 (clobber (reg:CC CC_REG))]
831 [(set_attr "timings" "11,11,11,11,11,11,11,11,11,11,11,11,11,33")
832 (set_attr "length" "2,2,2,3,4,5,6,2,3,3,4,5,6,5")]
835 (define_insn "*addsi3_flags"
836 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r,r,r,r,r,r,r,r")
837 (plus:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0,0,r,r,r,r,r,r,0")
838 (match_operand:SI 2 "rx_source_operand" "r,Uint04,NEGint4,Sint08,Sint16,Sint24,i,0,r,Sint08,Sint16,Sint24,i,Q")))
840 (compare (plus:SI (match_dup 1) (match_dup 2))
842 "reload_completed && rx_match_ccmode (insn, CC_ZSCmode)"
858 [(set_attr "timings" "11,11,11,11,11,11,11,11,11,11,11,11,11,33")
859 (set_attr "length" "2,2,2,3,4,5,6,2,3,3,4,5,6,5")]
862 ;; A helper to expand the above with the CC_MODE filled in.
863 (define_expand "addsi3_flags"
864 [(parallel [(set (match_operand:SI 0 "register_operand")
865 (plus:SI (match_operand:SI 1 "register_operand")
866 (match_operand:SI 2 "rx_source_operand")))
867 (set (reg:CC_ZSC CC_REG)
868 (compare:CC_ZSC (plus:SI (match_dup 1) (match_dup 2))
872 (define_insn "adc_internal"
873 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r")
876 (ltu:SI (reg:CC CC_REG) (const_int 0))
877 (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0"))
878 (match_operand:SI 2 "rx_source_operand" "r,Sint08,Sint16,Sint24,i,Q")))
879 (clobber (reg:CC CC_REG))]
882 [(set_attr "timings" "11,11,11,11,11,33")
883 (set_attr "length" "3,4,5,6,7,6")]
886 (define_insn "*adc_flags"
887 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r")
890 (ltu:SI (reg:CC CC_REG) (const_int 0))
891 (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0"))
892 (match_operand:SI 2 "rx_source_operand" "r,Sint08,Sint16,Sint24,i,Q")))
897 (ltu:SI (reg:CC CC_REG) (const_int 0))
901 "reload_completed && rx_match_ccmode (insn, CC_ZSCmode)"
903 [(set_attr "timings" "11,11,11,11,11,33")
904 (set_attr "length" "3,4,5,6,7,6")]
907 ;; Peepholes to match:
908 ;; (set (reg A) (reg B))
909 ;; (set (CC) (compare:CC (reg A/reg B) (const_int 0)))
910 ;; and replace them with the addsi3_flags pattern, using an add
911 ;; of zero to copy the register and set the condition code bits.
913 [(set (match_operand:SI 0 "register_operand")
914 (match_operand:SI 1 "register_operand"))
916 (compare:CC (match_dup 0)
919 [(parallel [(set (match_dup 0)
920 (plus:SI (match_dup 1) (const_int 0)))
921 (set (reg:CC_ZSC CC_REG)
922 (compare:CC_ZSC (plus:SI (match_dup 1) (const_int 0))
927 [(set (match_operand:SI 0 "register_operand")
928 (match_operand:SI 1 "register_operand"))
930 (compare:CC (match_dup 1)
933 [(parallel [(set (match_dup 0)
934 (plus:SI (match_dup 1) (const_int 0)))
935 (set (reg:CC_ZSC CC_REG)
936 (compare:CC_ZSC (plus:SI (match_dup 1) (const_int 0))
940 (define_expand "adddi3"
941 [(set (match_operand:DI 0 "register_operand")
942 (plus:DI (match_operand:DI 1 "register_operand")
943 (match_operand:DI 2 "rx_source_operand")))]
946 rtx op0l, op0h, op1l, op1h, op2l, op2h;
948 op0l = gen_lowpart (SImode, operands[0]);
949 op1l = gen_lowpart (SImode, operands[1]);
950 op2l = gen_lowpart (SImode, operands[2]);
951 op0h = gen_highpart (SImode, operands[0]);
952 op1h = gen_highpart (SImode, operands[1]);
953 op2h = gen_highpart_mode (SImode, DImode, operands[2]);
955 emit_insn (gen_adddi3_internal (op0l, op0h, op1l, op2l, op1h, op2h));
959 (define_insn_and_split "adddi3_internal"
960 [(set (match_operand:SI 0 "register_operand" "=r")
961 (plus:SI (match_operand:SI 2 "register_operand" "r")
962 (match_operand:SI 3 "rx_source_operand" "riQ")))
963 (set (match_operand:SI 1 "register_operand" "=r")
966 (ltu:SI (plus:SI (match_dup 2) (match_dup 3)) (match_dup 2))
967 (match_operand:SI 4 "register_operand" "%1"))
968 (match_operand:SI 5 "rx_source_operand" "riQ")))
969 (clobber (match_scratch:SI 6 "=&r"))
970 (clobber (reg:CC CC_REG))]
976 rtx op0l = operands[0];
977 rtx op0h = operands[1];
978 rtx op1l = operands[2];
979 rtx op2l = operands[3];
980 rtx op1h = operands[4];
981 rtx op2h = operands[5];
982 rtx scratch = operands[6];
985 if (reg_overlap_mentioned_p (op0l, op1h))
987 emit_move_insn (scratch, op0l);
989 if (reg_overlap_mentioned_p (op0l, op2h))
992 else if (reg_overlap_mentioned_p (op0l, op2h))
994 emit_move_insn (scratch, op0l);
998 if (rtx_equal_p (op0l, op1l))
1000 /* It is preferable that op0l == op1l... */
1001 else if (rtx_equal_p (op0l, op2l))
1002 x = op1l, op1l = op2l, op2l = x;
1003 /* ... but it is only a requirement if op2l == MEM. */
1004 else if (MEM_P (op2l))
1006 /* Let's hope that we still have a scratch register free. */
1007 gcc_assert (op1h != scratch);
1008 emit_move_insn (scratch, op2l);
1012 emit_insn (gen_addsi3_flags (op0l, op1l, op2l));
1014 if (rtx_equal_p (op0h, op1h))
1016 else if (rtx_equal_p (op0h, op2h))
1017 x = op1h, op1h = op2h, op2h = x;
1020 emit_move_insn (op0h, op1h);
1023 emit_insn (gen_adc_internal (op0h, op1h, op2h));
1027 (define_insn "andsi3"
1028 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r,r,r")
1029 (and:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0,r,r,0")
1030 (match_operand:SI 2 "rx_source_operand" "r,Uint04,Sint08,Sint16,Sint24,i,0,r,Q")))
1031 (clobber (reg:CC CC_REG))]
1043 [(set_attr "timings" "11,11,11,11,11,11,11,11,33")
1044 (set_attr "length" "2,2,3,4,5,6,2,5,5")]
1047 (define_insn "*andsi3_flags"
1048 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r,r,r")
1049 (and:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0,r,r,0")
1050 (match_operand:SI 2 "rx_source_operand" "r,Uint04,Sint08,Sint16,Sint24,i,0,r,Q")))
1052 (compare (and:SI (match_dup 1) (match_dup 2))
1054 "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1065 [(set_attr "timings" "11,11,11,11,11,11,11,11,33")
1066 (set_attr "length" "2,2,3,4,5,6,2,5,5")]
1069 ;; Byte swap (single 32-bit value).
1070 (define_insn "bswapsi2"
1071 [(set (match_operand:SI 0 "register_operand" "=r")
1072 (bswap:SI (match_operand:SI 1 "register_operand" "r")))]
1075 [(set_attr "length" "3")]
1078 ;; Byte swap (single 16-bit value). Note - we ignore the swapping of the high 16-bits.
1079 (define_insn "bswaphi2"
1080 [(set (match_operand:HI 0 "register_operand" "=r")
1081 (bswap:HI (match_operand:HI 1 "register_operand" "r")))]
1084 [(set_attr "length" "3")]
1087 (define_insn "divsi3"
1088 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r")
1089 (div:SI (match_operand:SI 1 "register_operand" "0,0,0,0,0,0")
1090 (match_operand:SI 2 "rx_source_operand" "r,Sint08,Sint16,Sint24,i,Q")))
1091 (clobber (reg:CC CC_REG))]
1094 [(set_attr "timings" "1111") ;; Strictly speaking the timing should be
1095 ;; 2222, but that is a worst case sceanario.
1096 (set_attr "length" "3,4,5,6,7,6")]
1099 (define_insn "udivsi3"
1100 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r")
1101 (udiv:SI (match_operand:SI 1 "register_operand" "0,0,0,0,0,0")
1102 (match_operand:SI 2 "rx_source_operand" "r,Sint08,Sint16,Sint24,i,Q")))
1103 (clobber (reg:CC CC_REG))]
1106 [(set_attr "timings" "1010") ;; Strictly speaking the timing should be
1107 ;; 2020, but that is a worst case sceanario.
1108 (set_attr "length" "3,4,5,6,7,6")]
1111 ;; Note - these patterns are suppressed in big-endian mode because they
1112 ;; generate a little endian result. ie the most significant word of the
1113 ;; result is placed in the higher numbered register of the destination
1116 (define_insn "mulsidi3"
1117 [(set (match_operand:DI 0 "register_operand" "=r,r,r,r,r,r")
1118 (mult:DI (sign_extend:DI (match_operand:SI
1119 1 "register_operand" "%0,0,0,0,0,0"))
1120 (sign_extend:DI (match_operand:SI
1121 2 "rx_source_operand"
1122 "r,Sint08,Sint16,Sint24,i,Q"))))]
1123 "! TARGET_BIG_ENDIAN_DATA"
1125 [(set_attr "length" "3,4,5,6,7,6")
1126 (set_attr "timings" "22,22,22,22,22,44")]
1129 ;; See comment for mulsidi3.
1130 ;; Note - the zero_extends are to distinguish this pattern from the
1131 ;; mulsidi3 pattern. Immediate mode addressing is not supported
1132 ;; because gcc cannot handle the expression: (zero_extend (const_int)).
1133 (define_insn "umulsidi3"
1134 [(set (match_operand:DI 0 "register_operand" "=r,r")
1135 (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "%0,0"))
1136 (zero_extend:DI (match_operand:SI 2 "rx_compare_operand" "r,Q"))))]
1137 "! TARGET_BIG_ENDIAN_DATA"
1139 [(set_attr "length" "3,6")
1140 (set_attr "timings" "22,44")]
1143 (define_insn "smaxsi3"
1144 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r")
1145 (smax:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0")
1146 (match_operand:SI 2 "rx_source_operand"
1147 "r,Sint08,Sint16,Sint24,i,Q")))]
1150 [(set_attr "length" "3,4,5,6,7,6")
1151 (set_attr "timings" "11,11,11,11,11,33")]
1154 (define_insn "sminsi3"
1155 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r")
1156 (smin:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0")
1157 (match_operand:SI 2 "rx_source_operand"
1158 "r,Sint08,Sint16,Sint24,i,Q")))]
1161 [(set_attr "length" "3,4,5,6,7,6")
1162 (set_attr "timings" "11,11,11,11,11,33")]
1165 (define_insn "mulsi3"
1166 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r,r,r")
1167 (mult:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0,0,r,r")
1168 (match_operand:SI 2 "rx_source_operand"
1169 "r,Uint04,Sint08,Sint16,Sint24,i,Q,0,r")))]
1181 [(set_attr "length" "2,2,3,4,5,6,5,2,3")
1182 (set_attr "timings" "11,11,11,11,11,11,33,11,11")]
1185 (define_insn "negsi2"
1186 [(set (match_operand:SI 0 "register_operand" "=r,r")
1187 (neg:SI (match_operand:SI 1 "register_operand" "0,r")))
1188 (clobber (reg:CC CC_REG))]
1193 [(set_attr "length" "2,3")]
1196 ;; Note that the O and C flags are not set as per a normal compare,
1197 ;; and thus are unusable in that context.
1198 (define_insn "*negsi2_flags"
1199 [(set (match_operand:SI 0 "register_operand" "=r,r")
1200 (neg:SI (match_operand:SI 1 "register_operand" "0,r")))
1202 (compare (neg:SI (match_dup 1))
1204 "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1208 [(set_attr "length" "2,3")]
1211 (define_insn "one_cmplsi2"
1212 [(set (match_operand:SI 0 "register_operand" "=r,r")
1213 (not:SI (match_operand:SI 1 "register_operand" "0,r")))
1214 (clobber (reg:CC CC_REG))]
1219 [(set_attr "length" "2,3")]
1222 (define_insn "*one_cmplsi2_flags"
1223 [(set (match_operand:SI 0 "register_operand" "=r,r")
1224 (not:SI (match_operand:SI 1 "register_operand" "0,r")))
1226 (compare (not:SI (match_dup 1))
1228 "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1232 [(set_attr "length" "2,3")]
1235 (define_insn "iorsi3"
1236 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r,r,r")
1237 (ior:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0,r,r,0")
1238 (match_operand:SI 2 "rx_source_operand" "r,Uint04,Sint08,Sint16,Sint24,i,0,r,Q")))
1239 (clobber (reg:CC CC_REG))]
1251 [(set_attr "timings" "11,11,11,11,11,11,11,11,33")
1252 (set_attr "length" "2,2,3,4,5,6,2,3,5")]
1255 (define_insn "*iorsi3_flags"
1256 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r,r,r")
1257 (ior:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0,r,r,0")
1258 (match_operand:SI 2 "rx_source_operand" "r,Uint04,Sint08,Sint16,Sint24,i,0,r,Q")))
1260 (compare (ior:SI (match_dup 1) (match_dup 2))
1262 "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1273 [(set_attr "timings" "11,11,11,11,11,11,11,11,33")
1274 (set_attr "length" "2,2,3,4,5,6,2,3,5")]
1277 (define_insn "rotlsi3"
1278 [(set (match_operand:SI 0 "register_operand" "=r")
1279 (rotate:SI (match_operand:SI 1 "register_operand" "0")
1280 (match_operand:SI 2 "rx_shift_operand" "rn")))
1281 (clobber (reg:CC CC_REG))]
1284 [(set_attr "length" "3")]
1287 (define_insn "*rotlsi3_flags"
1288 [(set (match_operand:SI 0 "register_operand" "=r")
1289 (rotate:SI (match_operand:SI 1 "register_operand" "0")
1290 (match_operand:SI 2 "rx_shift_operand" "rn")))
1292 (compare (rotate:SI (match_dup 1) (match_dup 2))
1294 "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1296 [(set_attr "length" "3")]
1299 (define_insn "rotrsi3"
1300 [(set (match_operand:SI 0 "register_operand" "=r")
1301 (rotatert:SI (match_operand:SI 1 "register_operand" "0")
1302 (match_operand:SI 2 "rx_shift_operand" "rn")))
1303 (clobber (reg:CC CC_REG))]
1306 [(set_attr "length" "3")]
1309 (define_insn "*rotrsi3_flags"
1310 [(set (match_operand:SI 0 "register_operand" "=r")
1311 (rotatert:SI (match_operand:SI 1 "register_operand" "0")
1312 (match_operand:SI 2 "rx_shift_operand" "rn")))
1314 (compare (rotatert:SI (match_dup 1) (match_dup 2))
1316 "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1318 [(set_attr "length" "3")]
1321 (define_insn "ashrsi3"
1322 [(set (match_operand:SI 0 "register_operand" "=r,r,r")
1323 (ashiftrt:SI (match_operand:SI 1 "register_operand" "0,0,r")
1324 (match_operand:SI 2 "rx_shift_operand" "r,n,n")))
1325 (clobber (reg:CC CC_REG))]
1331 [(set_attr "length" "3,2,3")]
1334 (define_insn "*ashrsi3_flags"
1335 [(set (match_operand:SI 0 "register_operand" "=r,r,r")
1336 (ashiftrt:SI (match_operand:SI 1 "register_operand" "0,0,r")
1337 (match_operand:SI 2 "rx_shift_operand" "r,n,n")))
1339 (compare (ashiftrt:SI (match_dup 1) (match_dup 2))
1341 "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1346 [(set_attr "length" "3,2,3")]
1349 (define_insn "lshrsi3"
1350 [(set (match_operand:SI 0 "register_operand" "=r,r,r")
1351 (lshiftrt:SI (match_operand:SI 1 "register_operand" "0,0,r")
1352 (match_operand:SI 2 "rx_shift_operand" "r,n,n")))
1353 (clobber (reg:CC CC_REG))]
1359 [(set_attr "length" "3,2,3")]
1362 (define_insn "*lshrsi3_flags"
1363 [(set (match_operand:SI 0 "register_operand" "=r,r,r")
1364 (lshiftrt:SI (match_operand:SI 1 "register_operand" "0,0,r")
1365 (match_operand:SI 2 "rx_shift_operand" "r,n,n")))
1367 (compare (lshiftrt:SI (match_dup 1) (match_dup 2))
1369 "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1374 [(set_attr "length" "3,2,3")]
1377 (define_insn "ashlsi3"
1378 [(set (match_operand:SI 0 "register_operand" "=r,r,r")
1379 (ashift:SI (match_operand:SI 1 "register_operand" "0,0,r")
1380 (match_operand:SI 2 "rx_shift_operand" "r,n,n")))
1381 (clobber (reg:CC CC_REG))]
1387 [(set_attr "length" "3,2,3")]
1390 (define_insn "*ashlsi3_flags"
1391 [(set (match_operand:SI 0 "register_operand" "=r,r,r")
1392 (ashift:SI (match_operand:SI 1 "register_operand" "0,0,r")
1393 (match_operand:SI 2 "rx_shift_operand" "r,n,n")))
1395 (compare (ashift:SI (match_dup 1) (match_dup 2))
1397 "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1402 [(set_attr "length" "3,2,3")]
1405 ;; Saturate to 32-bits
1406 (define_insn_and_split "ssaddsi3"
1407 [(set (match_operand:SI 0 "register_operand" "=r")
1408 (ss_plus:SI (match_operand:SI 1 "register_operand" "r")
1409 (match_operand:SI 2 "rx_source_operand" "riQ")))
1410 (clobber (reg:CC CC_REG))]
1414 [(parallel [(set (match_dup 0)
1415 (plus:SI (match_dup 1) (match_dup 2)))
1416 (set (reg:CC_ZSC CC_REG)
1418 (plus:SI (match_dup 1) (match_dup 2))
1421 (unspec:SI [(match_dup 0) (reg:CC CC_REG)]
1422 UNSPEC_BUILTIN_SAT))]
1427 [(set (match_operand:SI 0 "register_operand" "=r")
1428 (unspec:SI [(match_operand:SI 1 "register_operand" "0")
1430 UNSPEC_BUILTIN_SAT))]
1433 [(set_attr "length" "2")]
1436 (define_insn "subsi3"
1437 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r")
1438 (minus:SI (match_operand:SI 1 "register_operand" "0,0,0,r,0")
1439 (match_operand:SI 2 "rx_source_operand" "r,Uint04,n,r,Q")))
1440 (clobber (reg:CC CC_REG))]
1448 [(set_attr "timings" "11,11,11,11,33")
1449 (set_attr "length" "2,2,6,3,5")]
1452 ;; Note that the O flag is set as if (compare op1 op2) not for
1453 ;; what is described here, (compare op0 0).
1454 (define_insn "*subsi3_flags"
1455 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r")
1456 (minus:SI (match_operand:SI 1 "register_operand" "0,0,0,r,0")
1457 (match_operand:SI 2 "rx_source_operand" "r,Uint04,n,r,Q")))
1459 (compare (minus:SI (match_dup 1) (match_dup 2))
1461 "reload_completed && rx_match_ccmode (insn, CC_ZSCmode)"
1468 [(set_attr "timings" "11,11,11,11,33")
1469 (set_attr "length" "2,2,6,3,5")]
1472 ;; A helper to expand the above with the CC_MODE filled in.
1473 (define_expand "subsi3_flags"
1474 [(parallel [(set (match_operand:SI 0 "register_operand")
1475 (minus:SI (match_operand:SI 1 "register_operand")
1476 (match_operand:SI 2 "rx_source_operand")))
1477 (set (reg:CC_ZSC CC_REG)
1478 (compare:CC_ZSC (minus:SI (match_dup 1) (match_dup 2))
1482 (define_insn "sbb_internal"
1483 [(set (match_operand:SI 0 "register_operand" "=r,r")
1486 (match_operand:SI 1 "register_operand" " 0,0")
1487 (match_operand:SI 2 "rx_compare_operand" " r,Q"))
1488 (geu:SI (reg:CC CC_REG) (const_int 0))))
1489 (clobber (reg:CC CC_REG))]
1492 [(set_attr "timings" "11,33")
1493 (set_attr "length" "3,6")]
1496 (define_insn "*sbb_flags"
1497 [(set (match_operand:SI 0 "register_operand" "=r,r")
1500 (match_operand:SI 1 "register_operand" " 0,0")
1501 (match_operand:SI 2 "rx_compare_operand" " r,Q"))
1502 (geu:SI (reg:CC CC_REG) (const_int 0))))
1506 (minus:SI (match_dup 1) (match_dup 2))
1507 (geu:SI (reg:CC CC_REG) (const_int 0)))
1511 [(set_attr "timings" "11,33")
1512 (set_attr "length" "3,6")]
1515 (define_expand "subdi3"
1516 [(set (match_operand:DI 0 "register_operand")
1517 (minus:DI (match_operand:DI 1 "register_operand")
1518 (match_operand:DI 2 "rx_compare_operand")))]
1521 rtx op0l, op0h, op1l, op1h, op2l, op2h;
1523 op0l = gen_lowpart (SImode, operands[0]);
1524 op1l = gen_lowpart (SImode, operands[1]);
1525 op2l = gen_lowpart (SImode, operands[2]);
1526 op0h = gen_highpart (SImode, operands[0]);
1527 op1h = gen_highpart (SImode, operands[1]);
1528 op2h = gen_highpart_mode (SImode, DImode, operands[2]);
1530 emit_insn (gen_subdi3_internal (op0l, op0h, op1l, op2l, op1h, op2h));
1534 (define_insn_and_split "subdi3_internal"
1535 [(set (match_operand:SI 0 "register_operand" "=&r,&r")
1536 (minus:SI (match_operand:SI 2 "register_operand" " 0, r")
1537 (match_operand:SI 3 "rx_compare_operand" "rQ, r")))
1538 (set (match_operand:SI 1 "register_operand" "= r, r")
1541 (match_operand:SI 4 "register_operand" " 1, 1")
1542 (match_operand:SI 5 "rx_compare_operand" " rQ,rQ"))
1543 (geu:SI (match_dup 2) (match_dup 3))))
1544 (clobber (reg:CC CC_REG))]
1550 emit_insn (gen_subsi3_flags (operands[0], operands[2], operands[3]));
1551 emit_insn (gen_sbb_internal (operands[1], operands[4], operands[5]));
1555 (define_insn "xorsi3"
1556 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r")
1557 (xor:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0")
1558 (match_operand:SI 2 "rx_source_operand"
1559 "r,Sint08,Sint16,Sint24,i,Q")))
1560 (clobber (reg:CC CC_REG))]
1563 [(set_attr "timings" "11,11,11,11,11,33")
1564 (set_attr "length" "3,4,5,6,7,6")]
1567 (define_insn "*xorsi3_flags"
1568 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r")
1569 (xor:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0")
1570 (match_operand:SI 2 "rx_source_operand"
1571 "r,Sint08,Sint16,Sint24,i,Q")))
1573 (compare (xor:SI (match_dup 1) (match_dup 2))
1575 "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1577 [(set_attr "timings" "11,11,11,11,11,33")
1578 (set_attr "length" "3,4,5,6,7,6")]
1581 ;; A set of peepholes to catch extending loads followed by arithmetic operations.
1582 ;; We use iterators where possible to reduce the amount of typing and hence the
1583 ;; possibilities for typos.
1585 (define_code_iterator extend_types [(zero_extend "") (sign_extend "")])
1586 (define_code_attr letter [(zero_extend "R") (sign_extend "Q")])
1588 (define_code_iterator memex_commutative [(plus "") (and "") (ior "") (xor "")])
1589 (define_code_iterator memex_noncomm [(div "") (udiv "") (minus "")])
1590 (define_code_iterator memex_nocc [(smax "") (smin "") (mult "")])
1592 (define_code_attr op [(plus "add") (and "and") (div "div") (udiv "divu") (smax "max") (smin "min") (mult "mul") (ior "or") (minus "sub") (xor "xor")])
1595 [(set (match_operand:SI 0 "register_operand")
1596 (extend_types:SI (match_operand:small_int_modes 1 "rx_restricted_mem_operand")))
1597 (parallel [(set (match_operand:SI 2 "register_operand")
1598 (memex_commutative:SI (match_dup 0)
1600 (clobber (reg:CC CC_REG))])]
1601 "peep2_regno_dead_p (2, REGNO (operands[0]))"
1602 [(parallel [(set:SI (match_dup 2)
1603 (memex_commutative:SI (match_dup 2)
1604 (extend_types:SI (match_dup 1))))
1605 (clobber (reg:CC CC_REG))])]
1609 [(set (match_operand:SI 0 "register_operand")
1610 (extend_types:SI (match_operand:small_int_modes 1 "rx_restricted_mem_operand")))
1611 (parallel [(set (match_operand:SI 2 "register_operand")
1612 (memex_commutative:SI (match_dup 2)
1614 (clobber (reg:CC CC_REG))])]
1615 "peep2_regno_dead_p (2, REGNO (operands[0]))"
1616 [(parallel [(set:SI (match_dup 2)
1617 (memex_commutative:SI (match_dup 2)
1618 (extend_types:SI (match_dup 1))))
1619 (clobber (reg:CC CC_REG))])]
1623 [(set (match_operand:SI 0 "register_operand")
1624 (extend_types:SI (match_operand:small_int_modes 1 "rx_restricted_mem_operand")))
1625 (parallel [(set (match_operand:SI 2 "register_operand")
1626 (memex_noncomm:SI (match_dup 2)
1628 (clobber (reg:CC CC_REG))])]
1629 "peep2_regno_dead_p (2, REGNO (operands[0]))"
1630 [(parallel [(set:SI (match_dup 2)
1631 (memex_noncomm:SI (match_dup 2)
1632 (extend_types:SI (match_dup 1))))
1633 (clobber (reg:CC CC_REG))])]
1637 [(set (match_operand:SI 0 "register_operand")
1638 (extend_types:SI (match_operand:small_int_modes 1 "rx_restricted_mem_operand")))
1639 (set (match_operand:SI 2 "register_operand")
1640 (memex_nocc:SI (match_dup 0)
1642 "peep2_regno_dead_p (2, REGNO (operands[0]))"
1643 [(set:SI (match_dup 2)
1644 (memex_nocc:SI (match_dup 2)
1645 (extend_types:SI (match_dup 1))))]
1649 [(set (match_operand:SI 0 "register_operand")
1650 (extend_types:SI (match_operand:small_int_modes 1 "rx_restricted_mem_operand")))
1651 (set (match_operand:SI 2 "register_operand")
1652 (memex_nocc:SI (match_dup 2)
1654 "peep2_regno_dead_p (2, REGNO (operands[0]))"
1655 [(set:SI (match_dup 2)
1656 (memex_nocc:SI (match_dup 2)
1657 (extend_types:SI (match_dup 1))))]
1660 (define_insn "<memex_commutative:code>si3_<extend_types:code><small_int_modes:mode>"
1661 [(set (match_operand:SI 0 "register_operand" "=r")
1662 (memex_commutative:SI (match_operand:SI 1 "register_operand" "%0")
1663 (extend_types:SI (match_operand:small_int_modes 2 "rx_restricted_mem_operand" "Q"))))
1664 (clobber (reg:CC CC_REG))]
1666 "<memex_commutative:op>\t%<extend_types:letter>2, %0"
1667 [(set_attr "timings" "33")
1668 (set_attr "length" "5")] ;; This length is corrected in rx_adjust_insn_length
1671 (define_insn "<memex_noncomm:code>si3_<extend_types:code><small_int_modes:mode>"
1672 [(set (match_operand:SI 0 "register_operand" "=r")
1673 (memex_noncomm:SI (match_operand:SI 1 "register_operand" "0")
1674 (extend_types:SI (match_operand:small_int_modes 2 "rx_restricted_mem_operand" "Q"))))
1675 (clobber (reg:CC CC_REG))]
1677 "<memex_noncomm:op>\t%<extend_types:letter>2, %0"
1678 [(set_attr "timings" "33")
1679 (set_attr "length" "5")] ;; This length is corrected in rx_adjust_insn_length
1682 (define_insn "<memex_nocc:code>si3_<extend_types:code><small_int_modes:mode>"
1683 [(set (match_operand:SI 0 "register_operand" "=r")
1684 (memex_nocc:SI (match_operand:SI 1 "register_operand" "%0")
1685 (extend_types:SI (match_operand:small_int_modes 2 "rx_restricted_mem_operand" "Q"))))]
1687 "<memex_nocc:op>\t%<extend_types:letter>2, %0"
1688 [(set_attr "timings" "33")
1689 (set_attr "length" "5")] ;; This length is corrected in rx_adjust_insn_length
1693 [(set (match_operand:SI 0 "register_operand")
1694 (extend_types:SI (match_operand:small_int_modes 1 "rx_restricted_mem_operand")))
1695 (set (reg:CC CC_REG)
1696 (compare:CC (match_operand:SI 2 "register_operand")
1698 "peep2_regno_dead_p (2, REGNO (operands[0]))"
1699 [(set (reg:CC CC_REG)
1700 (compare:CC (match_dup 2)
1701 (extend_types:SI (match_dup 1))))]
1705 ;; (set (reg1) (sign_extend (mem))
1706 ;; (set (reg2) (zero_extend (reg1))
1708 ;; (set (reg2) (zero_extend (mem)))
1710 [(set (match_operand:SI 0 "register_operand")
1711 (sign_extend:SI (match_operand:small_int_modes 1 "memory_operand")))
1712 (set (match_operand:SI 2 "register_operand")
1713 (zero_extend:SI (match_operand:small_int_modes 3 "register_operand")))]
1714 "REGNO (operands[0]) == REGNO (operands[3])
1715 && (REGNO (operands[0]) == REGNO (operands[2])
1716 || peep2_regno_dead_p (2, REGNO (operands[0])))"
1718 (zero_extend:SI (match_dup 1)))]
1721 ;; Remove the redundant sign extension from:
1722 ;; (set (reg) (extend (mem)))
1723 ;; (set (reg) (extend (reg)))
1725 [(set (match_operand:SI 0 "register_operand")
1726 (extend_types:SI (match_operand:small_int_modes 1 "memory_operand")))
1728 (extend_types:SI (match_operand:small_int_modes 2 "register_operand")))]
1729 "REGNO (operands[0]) == REGNO (operands[2])"
1730 [(set (match_dup 0) (extend_types:SI (match_dup 1)))]
1733 (define_insn "comparesi3_<extend_types:code><small_int_modes:mode>"
1734 [(set (reg:CC CC_REG)
1735 (compare:CC (match_operand:SI 0 "register_operand" "=r")
1736 (extend_types:SI (match_operand:small_int_modes 1 "rx_restricted_mem_operand" "Q"))))]
1738 "cmp\t%<extend_types:letter>1, %0"
1739 [(set_attr "timings" "33")
1740 (set_attr "length" "5")] ;; This length is corrected in rx_adjust_insn_length
1743 ;; Floating Point Instructions
1745 (define_insn "addsf3"
1746 [(set (match_operand:SF 0 "register_operand" "=r,r,r")
1747 (plus:SF (match_operand:SF 1 "register_operand" "%0,0,0")
1748 (match_operand:SF 2 "rx_source_operand" "r,F,Q")))
1749 (clobber (reg:CC CC_REG))]
1750 "ALLOW_RX_FPU_INSNS"
1752 [(set_attr "timings" "44,44,66")
1753 (set_attr "length" "3,7,5")]
1756 (define_insn "divsf3"
1757 [(set (match_operand:SF 0 "register_operand" "=r,r,r")
1758 (div:SF (match_operand:SF 1 "register_operand" "0,0,0")
1759 (match_operand:SF 2 "rx_source_operand" "r,F,Q")))
1760 (clobber (reg:CC CC_REG))]
1761 "ALLOW_RX_FPU_INSNS"
1763 [(set_attr "timings" "1616,1616,1818")
1764 (set_attr "length" "3,7,5")]
1767 (define_insn "mulsf3"
1768 [(set (match_operand:SF 0 "register_operand" "=r,r,r")
1769 (mult:SF (match_operand:SF 1 "register_operand" "%0,0,0")
1770 (match_operand:SF 2 "rx_source_operand" "r,F,Q")))
1771 (clobber (reg:CC CC_REG))]
1772 "ALLOW_RX_FPU_INSNS"
1774 [(set_attr "timings" "33,33,55")
1775 (set_attr "length" "3,7,5")]
1778 (define_insn "subsf3"
1779 [(set (match_operand:SF 0 "register_operand" "=r,r,r")
1780 (minus:SF (match_operand:SF 1 "register_operand" "0,0,0")
1781 (match_operand:SF 2 "rx_source_operand" "r,F,Q")))
1782 (clobber (reg:CC CC_REG))]
1783 "ALLOW_RX_FPU_INSNS"
1785 [(set_attr "timings" "44,44,66")
1786 (set_attr "length" "3,7,5")]
1789 (define_insn "fix_truncsfsi2"
1790 [(set (match_operand:SI 0 "register_operand" "=r,r")
1791 (fix:SI (match_operand:SF 1 "rx_compare_operand" "r,Q")))
1792 (clobber (reg:CC CC_REG))]
1793 "ALLOW_RX_FPU_INSNS"
1795 [(set_attr "timings" "22,44")
1796 (set_attr "length" "3,5")]
1799 (define_insn "floatsisf2"
1800 [(set (match_operand:SF 0 "register_operand" "=r,r")
1801 (float:SF (match_operand:SI 1 "rx_compare_operand" "r,Q")))
1802 (clobber (reg:CC CC_REG))]
1803 "ALLOW_RX_FPU_INSNS"
1805 [(set_attr "timings" "22,44")
1806 (set_attr "length" "3,6")]
1809 ;; Bit manipulation instructions.
1811 ;; ??? The *_in_memory patterns will not be matched without further help.
1812 ;; At one time we had the insv expander generate them, but I suspect that
1813 ;; in general we get better performance by exposing the register load to
1816 ;; An alternate solution would be to re-organize these patterns such
1817 ;; that allow both register and memory operands. This would allow the
1818 ;; register allocator to spill and not load the register operand. This
1819 ;; would be possible only for operations for which we have a constant
1820 ;; bit offset, so that we can adjust the address by ofs/8 and replace
1821 ;; the offset in the insn by ofs%8.
1823 (define_insn "*bitset"
1824 [(set (match_operand:SI 0 "register_operand" "=r")
1825 (ior:SI (ashift:SI (const_int 1)
1826 (match_operand:SI 1 "rx_shift_operand" "ri"))
1827 (match_operand:SI 2 "register_operand" "0")))]
1830 [(set_attr "length" "3")]
1833 (define_insn "*bitset_in_memory"
1834 [(set (match_operand:QI 0 "rx_restricted_mem_operand" "+Q")
1835 (ior:QI (ashift:QI (const_int 1)
1836 (match_operand:QI 1 "nonmemory_operand" "ri"))
1840 [(set_attr "length" "3")
1841 (set_attr "timings" "33")]
1844 (define_insn "*bitinvert"
1845 [(set (match_operand:SI 0 "register_operand" "=r")
1846 (xor:SI (ashift:SI (const_int 1)
1847 (match_operand:SI 1 "rx_shift_operand" "ri"))
1848 (match_operand:SI 2 "register_operand" "0")))]
1851 [(set_attr "length" "3")]
1854 (define_insn "*bitinvert_in_memory"
1855 [(set (match_operand:QI 0 "rx_restricted_mem_operand" "+Q")
1856 (xor:QI (ashift:QI (const_int 1)
1857 (match_operand:QI 1 "nonmemory_operand" "ri"))
1861 [(set_attr "length" "5")
1862 (set_attr "timings" "33")]
1865 (define_insn "*bitclr"
1866 [(set (match_operand:SI 0 "register_operand" "=r")
1870 (match_operand:SI 1 "rx_shift_operand" "ri")))
1871 (match_operand:SI 2 "register_operand" "0")))]
1874 [(set_attr "length" "3")]
1877 (define_insn "*bitclr_in_memory"
1878 [(set (match_operand:QI 0 "rx_restricted_mem_operand" "+Q")
1882 (match_operand:QI 1 "nonmemory_operand" "ri")))
1886 [(set_attr "length" "3")
1887 (set_attr "timings" "33")]
1890 (define_insn "*insv_imm"
1891 [(set (zero_extract:SI
1892 (match_operand:SI 0 "register_operand" "+r")
1894 (match_operand:SI 1 "rx_shift_operand" "ri"))
1895 (match_operand:SI 2 "const_int_operand" ""))]
1898 if (INTVAL (operands[2]) & 1)
1899 return "bset\t%1, %0";
1901 return "bclr\t%1, %0";
1903 [(set_attr "length" "3")]
1906 (define_insn_and_split "rx_insv_reg"
1907 [(set (zero_extract:SI
1908 (match_operand:SI 0 "register_operand" "+r")
1910 (match_operand:SI 1 "const_int_operand" ""))
1911 (match_operand:SI 2 "register_operand" "r"))
1912 (clobber (reg:CC CC_REG))]
1916 [(set (zero_extract:SI (match_dup 0) (const_int 1) (match_dup 1))
1921 /* Emit tst #1, op2. */
1922 flags = gen_rtx_REG (CC_ZSmode, CC_REG);
1923 x = gen_rtx_AND (SImode, operands[2], const1_rtx);
1924 x = gen_rtx_COMPARE (CC_ZSmode, x, const0_rtx);
1925 x = gen_rtx_SET (VOIDmode, flags, x);
1929 operands[3] = gen_rtx_NE (SImode, flags, const0_rtx);
1932 (define_insn_and_split "*insv_cond"
1933 [(set (zero_extract:SI
1934 (match_operand:SI 0 "register_operand" "+r")
1936 (match_operand:SI 1 "const_int_operand" ""))
1937 (match_operator:SI 4 "comparison_operator"
1938 [(match_operand:SI 2 "register_operand" "r")
1939 (match_operand:SI 3 "rx_source_operand" "riQ")]))
1940 (clobber (reg:CC CC_REG))]
1944 [(set (zero_extract:SI (match_dup 0) (const_int 1) (match_dup 1))
1949 flags = gen_rtx_REG (CCmode, CC_REG);
1950 x = gen_rtx_COMPARE (CCmode, operands[2], operands[3]);
1951 x = gen_rtx_SET (VOIDmode, flags, x);
1954 operands[4] = gen_rtx_fmt_ee (GET_CODE (operands[4]), SImode,
1958 (define_insn "*bmcc"
1959 [(set (zero_extract:SI
1960 (match_operand:SI 0 "register_operand" "+r")
1962 (match_operand:SI 1 "const_int_operand" ""))
1963 (match_operator:SI 2 "comparison_operator"
1964 [(reg CC_REG) (const_int 0)]))]
1967 [(set_attr "length" "3")]
1970 ;; Work around the fact that X=Y<0 is preferentially expanded as a shift.
1971 (define_insn_and_split "*insv_cond_lt"
1972 [(set (zero_extract:SI
1973 (match_operand:SI 0 "register_operand" "+r")
1975 (match_operand:SI 1 "const_int_operand" ""))
1976 (match_operator:SI 3 "rshift_operator"
1977 [(match_operand:SI 2 "register_operand" "r")
1979 (clobber (reg:CC CC_REG))]
1983 [(parallel [(set (zero_extract:SI (match_dup 0) (const_int 1) (match_dup 1))
1984 (lt:SI (match_dup 2) (const_int 0)))
1985 (clobber (reg:CC CC_REG))])]
1989 (define_expand "insv"
1990 [(set (zero_extract:SI
1991 (match_operand:SI 0 "register_operand") ;; Destination
1992 (match_operand:SI 1 "const_int_operand") ;; # of bits to set
1993 (match_operand:SI 2 "nonmemory_operand")) ;; Starting bit
1994 (match_operand:SI 3 "nonmemory_operand"))] ;; Bits to insert
1997 /* We only handle single-bit inserts. */
1998 if (!CONST_INT_P (operands[1]) || INTVAL (operands[1]) != 1)
2001 /* Either the bit to insert or the position must be constant. */
2002 if (CONST_INT_P (operands[3]))
2003 operands[3] = GEN_INT (INTVAL (operands[3]) & 1);
2004 else if (CONST_INT_P (operands[2]))
2006 emit_insn (gen_rx_insv_reg (operands[0], operands[2], operands[3]));
2013 ;; Atomic exchange operation.
2015 (define_insn "sync_lock_test_and_setsi"
2016 [(set (match_operand:SI 0 "register_operand" "=r,r")
2017 (match_operand:SI 1 "rx_compare_operand" "=r,Q"))
2019 (match_operand:SI 2 "register_operand" "0,0"))]
2022 [(set_attr "length" "3,6")
2023 (set_attr "timings" "22")]
2026 ;; Block move functions.
2028 (define_expand "movstr"
2029 [(set (match_operand:BLK 1 "memory_operand") ;; Dest
2030 (match_operand:BLK 2 "memory_operand")) ;; Source
2031 (use (match_operand:SI 0 "register_operand")) ;; Updated Dest
2035 rtx addr1 = gen_rtx_REG (SImode, 1);
2036 rtx addr2 = gen_rtx_REG (SImode, 2);
2037 rtx len = gen_rtx_REG (SImode, 3);
2038 rtx dest_copy = gen_reg_rtx (SImode);
2040 emit_move_insn (len, GEN_INT (-1));
2041 emit_move_insn (addr1, force_operand (XEXP (operands[1], 0), NULL_RTX));
2042 emit_move_insn (addr2, force_operand (XEXP (operands[2], 0), NULL_RTX));
2043 operands[1] = replace_equiv_address_nv (operands[1], addr1);
2044 operands[2] = replace_equiv_address_nv (operands[2], addr2);
2045 emit_move_insn (dest_copy, addr1);
2046 emit_insn (gen_rx_movstr ());
2047 emit_move_insn (len, GEN_INT (-1));
2048 emit_insn (gen_rx_strend (operands[0], dest_copy));
2053 (define_insn "rx_movstr"
2054 [(set (mem:BLK (reg:SI 1))
2055 (mem:BLK (reg:SI 2)))
2056 (unspec_volatile:BLK [(reg:SI 1) (reg:SI 2) (reg:SI 3)] UNSPEC_MOVSTR)
2057 (clobber (reg:SI 1))
2058 (clobber (reg:SI 2))
2059 (clobber (reg:SI 3))]
2062 [(set_attr "length" "2")
2063 (set_attr "timings" "1111")] ;; The timing is a guesstimate.
2066 (define_insn "rx_strend"
2067 [(set (match_operand:SI 0 "register_operand" "=r")
2068 (unspec_volatile:SI [(match_operand:SI 1 "register_operand" "r")
2069 (reg:SI 3)] UNSPEC_STRLEN))
2070 (clobber (reg:SI 1))
2071 (clobber (reg:SI 2))
2072 (clobber (reg:SI 3))
2073 (clobber (reg:CC CC_REG))
2076 "mov\t%1, r1\n\tmov\t#0, r2\n\tsuntil.b\n\tmov\tr1, %0\n\tsub\t#1, %0"
2077 [(set_attr "length" "10")
2078 (set_attr "timings" "1111")] ;; The timing is a guesstimate.
2081 (define_expand "movmemsi"
2083 [(set (match_operand:BLK 0 "memory_operand") ;; Dest
2084 (match_operand:BLK 1 "memory_operand")) ;; Source
2085 (use (match_operand:SI 2 "register_operand")) ;; Length in bytes
2086 (match_operand 3 "immediate_operand") ;; Align
2087 (unspec_volatile:BLK [(reg:SI 1) (reg:SI 2) (reg:SI 3)] UNSPEC_MOVMEM)]
2091 rtx addr1 = gen_rtx_REG (SImode, 1);
2092 rtx addr2 = gen_rtx_REG (SImode, 2);
2093 rtx len = gen_rtx_REG (SImode, 3);
2095 /* Do not use when the source or destination are volatile - the SMOVF
2096 instruction will read and write in word sized blocks, which may be
2097 outside of the valid address range. */
2098 if (MEM_P (operands[0]) && MEM_VOLATILE_P (operands[0]))
2100 if (MEM_P (operands[1]) && MEM_VOLATILE_P (operands[1]))
2103 if (REG_P (operands[0]) && (REGNO (operands[0]) == 2
2104 || REGNO (operands[0]) == 3))
2106 if (REG_P (operands[1]) && (REGNO (operands[1]) == 1
2107 || REGNO (operands[1]) == 3))
2109 if (REG_P (operands[2]) && (REGNO (operands[2]) == 1
2110 || REGNO (operands[2]) == 2))
2113 emit_move_insn (addr1, force_operand (XEXP (operands[0], 0), NULL_RTX));
2114 emit_move_insn (addr2, force_operand (XEXP (operands[1], 0), NULL_RTX));
2115 emit_move_insn (len, force_operand (operands[2], NULL_RTX));
2116 operands[0] = replace_equiv_address_nv (operands[0], addr1);
2117 operands[1] = replace_equiv_address_nv (operands[1], addr2);
2118 emit_insn (gen_rx_movmem ());
2123 (define_insn "rx_movmem"
2124 [(set (mem:BLK (reg:SI 1))
2125 (mem:BLK (reg:SI 2)))
2127 (unspec_volatile:BLK [(reg:SI 1) (reg:SI 2) (reg:SI 3)] UNSPEC_MOVMEM)
2128 (clobber (reg:SI 1))
2129 (clobber (reg:SI 2))
2130 (clobber (reg:SI 3))]
2133 [(set_attr "length" "2")
2134 (set_attr "timings" "1111")] ;; The timing is a guesstimate.
2137 (define_expand "setmemsi"
2138 [(set (match_operand:BLK 0 "memory_operand") ;; Dest
2139 (match_operand:QI 2 "nonmemory_operand")) ;; Value
2140 (use (match_operand:SI 1 "nonmemory_operand")) ;; Length
2141 (match_operand 3 "immediate_operand") ;; Align
2142 (unspec_volatile:BLK [(reg:SI 1) (reg:SI 2) (reg:SI 3)] UNSPEC_SETMEM)]
2145 rtx addr = gen_rtx_REG (SImode, 1);
2146 rtx val = gen_rtx_REG (QImode, 2);
2147 rtx len = gen_rtx_REG (SImode, 3);
2149 emit_move_insn (addr, force_operand (XEXP (operands[0], 0), NULL_RTX));
2150 emit_move_insn (len, force_operand (operands[1], NULL_RTX));
2151 emit_move_insn (val, operands[2]);
2152 emit_insn (gen_rx_setmem ());
2157 (define_insn "rx_setmem"
2158 [(set (mem:BLK (reg:SI 1))
2159 (unspec_volatile:BLK [(reg:SI 1) (reg:SI 2) (reg:SI 3)] UNSPEC_SETMEM))
2160 (clobber (reg:SI 1))
2161 (clobber (reg:SI 3))]
2164 [(set_attr "length" "2")
2165 (set_attr "timings" "1111")] ;; The timing is a guesstimate.
2168 (define_expand "cmpstrnsi"
2169 [(set (match_operand:SI 0 "register_operand") ;; Result
2170 (unspec_volatile:SI [(match_operand:BLK 1 "memory_operand") ;; String1
2171 (match_operand:BLK 2 "memory_operand")] ;; String2
2173 (use (match_operand:SI 3 "register_operand")) ;; Max Length
2174 (match_operand:SI 4 "immediate_operand")] ;; Known Align
2177 rtx str1 = gen_rtx_REG (SImode, 1);
2178 rtx str2 = gen_rtx_REG (SImode, 2);
2179 rtx len = gen_rtx_REG (SImode, 3);
2181 emit_move_insn (str1, force_operand (XEXP (operands[1], 0), NULL_RTX));
2182 emit_move_insn (str2, force_operand (XEXP (operands[2], 0), NULL_RTX));
2183 emit_move_insn (len, force_operand (operands[3], NULL_RTX));
2185 emit_insn (gen_rx_cmpstrn (operands[0], operands[1], operands[2]));
2190 (define_expand "cmpstrsi"
2191 [(set (match_operand:SI 0 "register_operand") ;; Result
2192 (unspec_volatile:SI [(match_operand:BLK 1 "memory_operand") ;; String1
2193 (match_operand:BLK 2 "memory_operand")] ;; String2
2195 (match_operand:SI 3 "immediate_operand")] ;; Known Align
2198 rtx str1 = gen_rtx_REG (SImode, 1);
2199 rtx str2 = gen_rtx_REG (SImode, 2);
2200 rtx len = gen_rtx_REG (SImode, 3);
2202 emit_move_insn (str1, force_reg (SImode, XEXP (operands[1], 0)));
2203 emit_move_insn (str2, force_reg (SImode, XEXP (operands[2], 0)));
2204 emit_move_insn (len, GEN_INT (-1));
2206 emit_insn (gen_rx_cmpstrn (operands[0], operands[1], operands[2]));
2211 (define_insn "rx_cmpstrn"
2212 [(set (match_operand:SI 0 "register_operand" "=r")
2213 (unspec_volatile:SI [(reg:SI 1) (reg:SI 2) (reg:SI 3)]
2215 (use (match_operand:BLK 1 "memory_operand" "m"))
2216 (use (match_operand:BLK 2 "memory_operand" "m"))
2217 (clobber (reg:SI 1))
2218 (clobber (reg:SI 2))
2219 (clobber (reg:SI 3))
2220 (clobber (reg:CC CC_REG))]
2222 "scmpu ; Perform the string comparison
2223 mov #-1, %0 ; Set up -1 result (which cannot be created
2225 bnc ?+ ; If Carry is not set skip over
2226 scne.L %0 ; Set result based on Z flag
2229 [(set_attr "length" "9")
2230 (set_attr "timings" "1111")] ;; The timing is a guesstimate.
2233 ;; Builtin Functions
2235 ;; GCC does not have the ability to generate the following instructions
2236 ;; on its own so they are provided as builtins instead. To use them from
2237 ;; a program for example invoke them as __builtin_rx_<insn_name>. For
2240 ;; int short_byte_swap (int arg) { return __builtin_rx_revw (arg); }
2242 ;;---------- Accumulator Support ------------------------
2244 ;; Multiply & Accumulate (high)
2245 (define_insn "machi"
2246 [(unspec:SI [(match_operand:SI 0 "register_operand" "r")
2247 (match_operand:SI 1 "register_operand" "r")]
2248 UNSPEC_BUILTIN_MACHI)]
2251 [(set_attr "length" "3")]
2254 ;; Multiply & Accumulate (low)
2255 (define_insn "maclo"
2256 [(unspec:SI [(match_operand:SI 0 "register_operand" "r")
2257 (match_operand:SI 1 "register_operand" "r")]
2258 UNSPEC_BUILTIN_MACLO)]
2261 [(set_attr "length" "3")]
2265 (define_insn "mulhi"
2266 [(unspec:SI [(match_operand:SI 0 "register_operand" "r")
2267 (match_operand:SI 1 "register_operand" "r")]
2268 UNSPEC_BUILTIN_MULHI)]
2271 [(set_attr "length" "3")]
2275 (define_insn "mullo"
2276 [(unspec:SI [(match_operand:SI 0 "register_operand" "r")
2277 (match_operand:SI 1 "register_operand" "r")]
2278 UNSPEC_BUILTIN_MULLO)]
2281 [(set_attr "length" "3")]
2284 ;; Move from Accumulator (high)
2285 (define_insn "mvfachi"
2286 [(set (match_operand:SI 0 "register_operand" "=r")
2287 (unspec:SI [(const_int 0)]
2288 UNSPEC_BUILTIN_MVFACHI))]
2291 [(set_attr "length" "3")]
2294 ;; Move from Accumulator (middle)
2295 (define_insn "mvfacmi"
2296 [(set (match_operand:SI 0 "register_operand" "=r")
2297 (unspec:SI [(const_int 0)]
2298 UNSPEC_BUILTIN_MVFACMI))]
2301 [(set_attr "length" "3")]
2304 ;; Move to Accumulator (high)
2305 (define_insn "mvtachi"
2306 [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")]
2307 UNSPEC_BUILTIN_MVTACHI)]
2310 [(set_attr "length" "3")]
2313 ;; Move to Accumulator (low)
2314 (define_insn "mvtaclo"
2315 [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")]
2316 UNSPEC_BUILTIN_MVTACLO)]
2319 [(set_attr "length" "3")]
2322 ;; Round Accumulator
2324 [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i")]
2325 UNSPEC_BUILTIN_RACW)]
2328 [(set_attr "length" "3")]
2331 ;; Repeat multiply and accumulate
2333 [(unspec:SI [(const_int 0) (reg:SI 1) (reg:SI 2) (reg:SI 3)
2334 (reg:SI 4) (reg:SI 5) (reg:SI 6)]
2335 UNSPEC_BUILTIN_RMPA)
2336 (clobber (reg:SI 1))
2337 (clobber (reg:SI 2))
2338 (clobber (reg:SI 3))]
2341 [(set_attr "length" "2")
2342 (set_attr "timings" "1010")]
2345 ;;---------- Arithmetic ------------------------
2347 ;; Byte swap (two 16-bit values).
2349 [(set (match_operand:SI 0 "register_operand" "=r")
2350 (unspec:SI [(match_operand:SI 1 "register_operand" "r")]
2351 UNSPEC_BUILTIN_REVW))]
2354 [(set_attr "length" "3")]
2357 ;; Round to integer.
2358 (define_insn "lrintsf2"
2359 [(set (match_operand:SI 0 "register_operand" "=r,r")
2360 (unspec:SI [(match_operand:SF 1 "rx_compare_operand" "r,Q")]
2361 UNSPEC_BUILTIN_ROUND))
2362 (clobber (reg:CC CC_REG))]
2365 [(set_attr "timings" "22,44")
2366 (set_attr "length" "3,5")]
2369 ;;---------- Control Registers ------------------------
2371 ;; Clear Processor Status Word
2372 (define_insn "clrpsw"
2373 [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i")]
2374 UNSPEC_BUILTIN_CLRPSW)
2375 (clobber (reg:CC CC_REG))]
2378 [(set_attr "length" "2")]
2381 ;; Set Processor Status Word
2382 (define_insn "setpsw"
2383 [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i")]
2384 UNSPEC_BUILTIN_SETPSW)
2385 (clobber (reg:CC CC_REG))]
2388 [(set_attr "length" "2")]
2391 ;; Move from control register
2393 [(set (match_operand:SI 0 "register_operand" "=r")
2394 (unspec_volatile:SI [(match_operand:SI 1 "immediate_operand" "i")]
2395 UNSPEC_BUILTIN_MVFC))]
2398 [(set_attr "length" "3")]
2401 ;; Move to control register
2403 [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i,i")
2404 (match_operand:SI 1 "nonmemory_operand" "r,i")]
2405 UNSPEC_BUILTIN_MVTC)]
2408 [(set_attr "length" "3,7")]
2409 ;; Ignore possible clobbering of the comparison flags in the
2410 ;; PSW register. This is a cc0 target so any cc0 setting
2411 ;; instruction will always be paired with a cc0 user, without
2412 ;; the possibility of this instruction being placed in between
2416 ;; Move to interrupt priority level
2417 (define_insn "mvtipl"
2418 [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "Uint04")]
2419 UNSPEC_BUILTIN_MVTIPL)]
2422 [(set_attr "length" "3")]
2425 ;;---------- Interrupts ------------------------
2429 [(unspec_volatile [(const_int 0)]
2430 UNSPEC_BUILTIN_BRK)]
2433 [(set_attr "length" "1")
2434 (set_attr "timings" "66")]
2439 [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i")]
2440 UNSPEC_BUILTIN_INT)]
2443 [(set_attr "length" "3")]
2448 [(unspec_volatile [(const_int 0)]
2449 UNSPEC_BUILTIN_WAIT)]
2452 [(set_attr "length" "2")]
2455 ;;---------- CoProcessor Support ------------------------
2457 ;; FIXME: The instructions are currently commented out because
2458 ;; the bit patterns have not been finalized, so the assembler
2459 ;; does not support them. Once they are decided and the assembler
2460 ;; supports them, enable the instructions here.
2462 ;; Move from co-processor register
2463 (define_insn "mvfcp"
2464 [(set (match_operand:SI 0 "register_operand" "=r")
2465 (unspec:SI [(match_operand:SI 1 "immediate_operand" "i")
2466 (match_operand:SI 2 "immediate_operand" "i")]
2467 UNSPEC_BUILTIN_MVFCP))]
2469 "; mvfcp\t%1, %0, %2"
2470 [(set_attr "length" "5")]
2473 ;;---------- Misc ------------------------
2475 ;; Required by cfglayout.c...
2480 [(set_attr "length" "1")]