1 ;; Machine Description for Renesas RX processors
2 ;; Copyright (C) 2008-2014 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 "") (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)
81 (define_attr "length" "" (const_int 8))
83 (include "predicates.md")
84 (include "constraints.md")
86 ;; Pipeline description.
88 ;; The RX only has a single pipeline. It has five stages (fetch,
89 ;; decode, execute, memory access, writeback) each of which normally
90 ;; takes a single CPU clock cycle.
92 ;; The timings attribute consists of two numbers, the first is the
93 ;; throughput, which is the number of cycles the instruction takes
94 ;; to execute and generate a result. The second is the latency
95 ;; which is the effective number of cycles the instruction takes to
96 ;; execute if its result is used by the following instruction. The
97 ;; latency is always greater than or equal to the throughput.
98 ;; These values were taken from tables 2.13 and 2.14 in section 2.8
99 ;; of the RX610 Group Hardware Manual v0.11
101 ;; Note - it would be nice to use strings rather than integers for
102 ;; the possible values of this attribute, so that we can have the
103 ;; gcc build mechanism check for values that are not supported by
104 ;; the reservations below. But this will not work because the code
105 ;; in rx_adjust_sched_cost() needs integers not strings.
107 (define_attr "timings" "" (const_int 11))
109 (define_automaton "pipelining")
110 (define_cpu_unit "throughput" "pipelining")
112 (define_insn_reservation "throughput__1_latency__1" 1
113 (eq_attr "timings" "11") "throughput")
114 (define_insn_reservation "throughput__1_latency__2" 2
115 (eq_attr "timings" "12") "throughput,nothing")
116 (define_insn_reservation "throughput__2_latency__2" 1
117 (eq_attr "timings" "22") "throughput*2")
118 (define_insn_reservation "throughput__3_latency__3" 1
119 (eq_attr "timings" "33") "throughput*3")
120 (define_insn_reservation "throughput__3_latency__4" 2
121 (eq_attr "timings" "34") "throughput*3,nothing")
122 (define_insn_reservation "throughput__4_latency__4" 1
123 (eq_attr "timings" "44") "throughput*4")
124 (define_insn_reservation "throughput__4_latency__5" 2
125 (eq_attr "timings" "45") "throughput*4,nothing")
126 (define_insn_reservation "throughput__5_latency__5" 1
127 (eq_attr "timings" "55") "throughput*5")
128 (define_insn_reservation "throughput__5_latency__6" 2
129 (eq_attr "timings" "56") "throughput*5,nothing")
130 (define_insn_reservation "throughput__6_latency__6" 1
131 (eq_attr "timings" "66") "throughput*6")
132 (define_insn_reservation "throughput_10_latency_10" 1
133 (eq_attr "timings" "1010") "throughput*10")
134 (define_insn_reservation "throughput_11_latency_11" 1
135 (eq_attr "timings" "1111") "throughput*11")
136 (define_insn_reservation "throughput_16_latency_16" 1
137 (eq_attr "timings" "1616") "throughput*16")
138 (define_insn_reservation "throughput_18_latency_18" 1
139 (eq_attr "timings" "1818") "throughput*18")
141 ;; ----------------------------------------------------------------------------
145 ;; Note - we do not specify the two instructions necessary to perform
146 ;; a compare-and-branch in the cbranchsi4 pattern because that would
147 ;; allow the comparison to be moved away from the jump before the reload
148 ;; pass has completed. That would be problematical because reload can
149 ;; generate ADDSI3 instructions which would corrupt the PSW flags.
151 (define_expand "cbranchsi4"
154 (match_operator 0 "comparison_operator"
155 [(match_operand:SI 1 "register_operand")
156 (match_operand:SI 2 "rx_source_operand")])
157 (label_ref (match_operand 3 ""))
162 (define_insn_and_split "*cbranchsi4"
165 (match_operator 3 "comparison_operator"
166 [(match_operand:SI 0 "register_operand" "r")
167 (match_operand:SI 1 "rx_source_operand" "riQ")])
168 (match_operand 2 "label_ref_operand" "")
175 rx_split_cbranch (CCmode, GET_CODE (operands[3]),
176 operands[0], operands[1], operands[2]);
180 (define_insn "*cmpsi"
181 [(set (reg:CC CC_REG)
182 (compare:CC (match_operand:SI 0 "register_operand" "r,r,r,r,r,r,r")
183 (match_operand:SI 1 "rx_source_operand" "r,Uint04,Int08,Sint16,Sint24,i,Q")))]
186 [(set_attr "timings" "11,11,11,11,11,11,33")
187 (set_attr "length" "2,2,3,4,5,6,5")]
190 ;; Canonical method for representing TST.
191 (define_insn_and_split "*cbranchsi4_tst"
194 (match_operator 3 "rx_zs_comparison_operator"
195 [(and:SI (match_operand:SI 0 "register_operand" "r")
196 (match_operand:SI 1 "rx_source_operand" "riQ"))
198 (match_operand 2 "label_ref_operand" "")
205 rx_split_cbranch (CC_ZSmode, GET_CODE (operands[3]),
206 XEXP (operands[3], 0), XEXP (operands[3], 1),
211 ;; Various other ways that GCC codes "var & const"
212 (define_insn_and_split "*cbranchsi4_tst_ext"
215 (match_operator 4 "rx_z_comparison_operator"
217 (match_operand:SI 0 "register_operand" "r")
218 (match_operand:SI 1 "rx_constshift_operand" "")
219 (match_operand:SI 2 "rx_constshift_operand" ""))
221 (match_operand 3 "label_ref_operand" "")
232 mask <<= INTVAL (operands[1]);
234 mask <<= INTVAL (operands[2]);
235 x = gen_rtx_AND (SImode, operands[0], gen_int_mode (mask, SImode));
237 rx_split_cbranch (CC_ZSmode, GET_CODE (operands[4]),
238 x, const0_rtx, operands[3]);
242 (define_insn "*tstsi"
243 [(set (reg:CC_ZS CC_REG)
245 (and:SI (match_operand:SI 0 "register_operand" "r,r,r")
246 (match_operand:SI 1 "rx_source_operand" "r,i,Q"))
250 [(set_attr "timings" "11,11,33")
251 (set_attr "length" "3,7,6")]
254 (define_expand "cbranchsf4"
257 (match_operator 0 "rx_fp_comparison_operator"
258 [(match_operand:SF 1 "register_operand")
259 (match_operand:SF 2 "rx_source_operand")])
260 (label_ref (match_operand 3 ""))
265 (define_insn_and_split "*cbranchsf4"
268 (match_operator 3 "rx_fp_comparison_operator"
269 [(match_operand:SF 0 "register_operand" "r")
270 (match_operand:SF 1 "rx_source_operand" "rFQ")])
271 (match_operand 2 "label_ref_operand" "")
275 "&& reload_completed"
278 rx_split_cbranch (CC_Fmode, GET_CODE (operands[3]),
279 operands[0], operands[1], operands[2]);
283 (define_insn "*cmpsf"
284 [(set (reg:CC_F CC_REG)
286 (match_operand:SF 0 "register_operand" "r,r,r")
287 (match_operand:SF 1 "rx_source_operand" "r,F,Q")))]
288 "ALLOW_RX_FPU_INSNS && reload_completed"
290 [(set_attr "timings" "11,11,33")
291 (set_attr "length" "3,7,5")]
294 ;; Flow Control Instructions:
296 (define_insn "*conditional_branch"
299 (match_operator 1 "comparison_operator"
300 [(reg CC_REG) (const_int 0)])
301 (label_ref (match_operand 0 "" ""))
305 [(set_attr "length" "8") ;; This length is wrong, but it is
306 ;; too hard to compute statically.
307 (set_attr "timings" "33")] ;; The timing assumes that the branch is taken.
310 ;; ----------------------------------------------------------------------------
314 (label_ref (match_operand 0 "" "")))]
317 [(set_attr "length" "4")
318 (set_attr "timings" "33")]
321 (define_insn "indirect_jump"
323 (match_operand:SI 0 "register_operand" "r"))]
326 [(set_attr "length" "2")
327 (set_attr "timings" "33")]
330 (define_insn "tablejump"
332 (match_operand:SI 0 "register_operand" "r"))
333 (use (label_ref (match_operand 1 "" "")))]
335 { return TARGET_PID ? (TARGET_AS100_SYNTAX ? "\n?:\tbra\t%0"
339 [(set_attr "timings" "33")
340 (set_attr "length" "2")]
343 (define_expand "return"
345 "rx_can_use_simple_return ()"
346 "rx_expand_epilogue (false); DONE;"
349 (define_insn "simple_return"
353 [(set_attr "length" "1")
354 (set_attr "timings" "55")]
357 ;; Unspec used so that the constant will not be invalid
358 ;; if -mmax-constant-size has been specified.
359 (define_insn "deallocate_and_return"
360 [(set (reg:SI SP_REG)
361 (plus:SI (reg:SI SP_REG)
362 (const:SI (unspec:SI [(match_operand 0 "const_int_operand" "n")] UNSPEC_CONST))))
366 [(set_attr "length" "2")
367 (set_attr "timings" "55")]
370 (define_insn "pop_and_return"
371 [(match_parallel 1 "rx_rtsd_vector"
372 [(set (reg:SI SP_REG)
373 (plus:SI (reg:SI SP_REG)
374 (match_operand:SI 0 "const_int_operand" "n")))])
378 rx_emit_stack_popm (operands, false);
381 [(set_attr "length" "3")
382 (set_attr "timings" "56")]
385 (define_insn "fast_interrupt_return"
386 [(unspec_volatile [(return)] UNSPEC_RTFI) ]
389 [(set_attr "length" "2")
390 (set_attr "timings" "33")]
393 (define_insn "exception_return"
394 [(unspec_volatile [(return)] UNSPEC_RTE) ]
397 [(set_attr "length" "2")
398 (set_attr "timings" "66")]
401 (define_insn "naked_return"
402 [(unspec_volatile [(return)] UNSPEC_NAKED) ]
404 "; Naked function: epilogue provided by programmer."
408 ;; Note - the following set of patterns do not use the "memory_operand"
409 ;; predicate or an "m" constraint because we do not allow symbol_refs
410 ;; or label_refs as legitimate memory addresses. This matches the
411 ;; behaviour of most of the RX instructions. Only the call/branch
412 ;; instructions are allowed to refer to symbols/labels directly.
413 ;; The call operands are in QImode because that is the value of
416 (define_expand "call"
417 [(call (match_operand:QI 0 "general_operand")
418 (match_operand:SI 1 "general_operand"))]
421 rtx dest = XEXP (operands[0], 0);
423 if (! rx_call_operand (dest, Pmode))
424 dest = force_reg (Pmode, dest);
425 emit_call_insn (gen_call_internal (dest));
430 (define_insn "call_internal"
431 [(call (mem:QI (match_operand:SI 0 "rx_call_operand" "r,Symbol"))
433 (clobber (reg:CC CC_REG))]
438 [(set_attr "length" "2,4")
439 (set_attr "timings" "33")]
442 (define_expand "call_value"
443 [(set (match_operand 0 "register_operand")
444 (call (match_operand:QI 1 "general_operand")
445 (match_operand:SI 2 "general_operand")))]
448 rtx dest = XEXP (operands[1], 0);
450 if (! rx_call_operand (dest, Pmode))
451 dest = force_reg (Pmode, dest);
452 emit_call_insn (gen_call_value_internal (operands[0], dest));
457 (define_insn "call_value_internal"
458 [(set (match_operand 0 "register_operand" "=r,r")
459 (call (mem:QI (match_operand:SI 1 "rx_call_operand" "r,Symbol"))
461 (clobber (reg:CC CC_REG))]
466 [(set_attr "length" "2,4")
467 (set_attr "timings" "33")]
470 ;; Note - we do not allow indirect sibcalls (with the address
471 ;; held in a register) because we cannot guarantee that the register
472 ;; chosen will be a call-used one. If it is a call-saved register,
473 ;; then the epilogue code will corrupt it by popping the saved value
475 (define_expand "sibcall"
477 [(call (mem:QI (match_operand:SI 0 "rx_symbolic_call_operand"))
478 (match_operand:SI 1 "general_operand"))
482 if (MEM_P (operands[0]))
483 operands[0] = XEXP (operands[0], 0);
484 emit_call_insn (gen_sibcall_internal (operands[0]));
489 (define_insn "sibcall_internal"
490 [(call (mem:QI (match_operand:SI 0 "rx_symbolic_call_operand" "Symbol"))
495 [(set_attr "length" "4")
496 (set_attr "timings" "33")]
499 (define_expand "sibcall_value"
501 [(set (match_operand 0 "register_operand")
502 (call (mem:QI (match_operand:SI 1 "rx_symbolic_call_operand"))
503 (match_operand:SI 2 "general_operand")))
507 if (MEM_P (operands[1]))
508 operands[1] = XEXP (operands[1], 0);
509 emit_call_insn (gen_sibcall_value_internal (operands[0], operands[1]));
514 (define_insn "sibcall_value_internal"
515 [(set (match_operand 0 "register_operand" "=r")
516 (call (mem:QI (match_operand:SI 1 "rx_symbolic_call_operand" "Symbol"))
521 [(set_attr "length" "4")
522 (set_attr "timings" "33")]
525 ;; Function Prologue/Epilogue Instructions
527 (define_expand "prologue"
530 "rx_expand_prologue (); DONE;"
533 (define_expand "epilogue"
536 "rx_expand_epilogue (false); DONE;"
539 (define_expand "sibcall_epilogue"
542 "rx_expand_epilogue (true); DONE;"
547 ;; Note - we do not allow memory to memory moves, even though the ISA
548 ;; supports them. The reason is that the conditions on such moves are
549 ;; too restrictive, specifically the source addressing mode is limited
550 ;; by the destination addressing mode and vice versa. (For example it
551 ;; is not possible to use indexed register indirect addressing for one
552 ;; of the operands if the other operand is anything other than a register,
553 ;; but it is possible to use register relative addressing when the other
554 ;; operand also uses register relative or register indirect addressing).
556 ;; GCC does not support computing legitimate addresses based on the
557 ;; nature of other operands involved in the instruction, and reload is
558 ;; not smart enough to cope with a whole variety of different memory
559 ;; addressing constraints, so it is simpler and safer to just refuse
560 ;; to support memory to memory moves.
562 (define_expand "mov<register_modes:mode>"
563 [(set (match_operand:register_modes 0 "general_operand")
564 (match_operand:register_modes 1 "general_operand"))]
567 if (MEM_P (operands[0]) && MEM_P (operands[1]))
568 operands[1] = copy_to_mode_reg (<register_modes:MODE>mode, operands[1]);
569 operands[0] = rx_maybe_pidify_operand (operands[0], 0);
570 operands[1] = rx_maybe_pidify_operand (operands[1], 0);
571 if (GET_CODE (operands[0]) != REG
572 && GET_CODE (operands[1]) == PLUS)
573 operands[1] = copy_to_mode_reg (<register_modes:MODE>mode, operands[1]);
574 if (GET_CODE (operands[1]) == PLUS && GET_MODE (operands[1]) == SImode)
576 emit_insn (gen_addsi3 (operands[0], XEXP (operands[1], 0), XEXP (operands[1], 1)));
579 if (CONST_INT_P (operand1)
580 && ! rx_is_legitimate_constant (<register_modes:MODE>mode, operand1))
585 (define_insn "*mov<register_modes:mode>_internal"
586 [(set (match_operand:register_modes
587 0 "nonimmediate_operand" "=r,r,r,r,r,r,m,Q,Q,Q,Q,r")
588 (match_operand:register_modes
589 1 "general_operand" "Int08,Sint16,Sint24,i,r,m,r,Int08,Sint16,Sint24,i,RpdaRpid"))]
591 { return rx_gen_move_template (operands, false); }
592 [(set_attr "length" "3,4,5,6,2,4,6,5,6,7,8,8")
593 (set_attr "timings" "11,11,11,11,11,12,11,11,11,11,11,11")]
596 (define_insn "extend<small_int_modes:mode>si2"
597 [(set (match_operand:SI 0 "register_operand" "=r,r")
598 (sign_extend:SI (match_operand:small_int_modes
599 1 "nonimmediate_operand" "r,m")))]
601 { return rx_gen_move_template (operands, false); }
602 [(set_attr "length" "2,6")
603 (set_attr "timings" "11,12")]
606 (define_insn "zero_extend<small_int_modes:mode>si2"
607 [(set (match_operand:SI 0 "register_operand" "=r,r")
608 (zero_extend:SI (match_operand:small_int_modes
609 1 "nonimmediate_operand" "r,m")))]
611 { return rx_gen_move_template (operands, true); }
612 [(set_attr "length" "2,4")
613 (set_attr "timings" "11,12")]
616 (define_insn "stack_push"
617 [(set (reg:SI SP_REG)
618 (minus:SI (reg:SI SP_REG)
620 (set (mem:SI (minus:SI (reg:SI SP_REG) (const_int 4)))
621 (match_operand:SI 0 "register_operand" "r"))]
624 [(set_attr "length" "2")]
627 (define_insn "stack_pushm"
628 [(match_parallel 1 "rx_store_multiple_vector"
629 [(set (reg:SI SP_REG)
630 (minus:SI (reg:SI SP_REG)
631 (match_operand:SI 0 "const_int_operand" "n")))])]
634 rx_emit_stack_pushm (operands);
637 [(set_attr "length" "2")
638 (set_attr "timings" "44")] ;; The timing is a guesstimate average timing.
641 (define_insn "stack_pop"
642 [(set (match_operand:SI 0 "register_operand" "=r")
643 (mem:SI (reg:SI SP_REG)))
645 (plus:SI (reg:SI SP_REG)
649 [(set_attr "length" "2")
650 (set_attr "timings" "12")]
653 (define_insn "stack_popm"
654 [(match_parallel 1 "rx_load_multiple_vector"
655 [(set (reg:SI SP_REG)
656 (plus:SI (reg:SI SP_REG)
657 (match_operand:SI 0 "const_int_operand" "n")))])]
660 rx_emit_stack_popm (operands, true);
663 [(set_attr "length" "2")
664 (set_attr "timings" "45")] ;; The timing is a guesstimate average timing.
667 (define_insn_and_split "cstoresi4"
668 [(set (match_operand:SI 0 "register_operand" "=r")
669 (match_operator:SI 1 "comparison_operator"
670 [(match_operand:SI 2 "register_operand" "r")
671 (match_operand:SI 3 "rx_source_operand" "riQ")]))
672 (clobber (reg:CC CC_REG))]
680 flags = gen_rtx_REG (CCmode, CC_REG);
681 x = gen_rtx_COMPARE (CCmode, operands[2], operands[3]);
682 x = gen_rtx_SET (VOIDmode, flags, x);
685 x = gen_rtx_fmt_ee (GET_CODE (operands[1]), SImode, flags, const0_rtx);
686 x = gen_rtx_SET (VOIDmode, operands[0], x);
692 [(set (match_operand:SI 0 "register_operand" "=r")
693 (match_operator:SI 1 "comparison_operator"
694 [(reg CC_REG) (const_int 0)]))]
697 [(set_attr "length" "3")]
700 (define_insn_and_split "cstoresf4"
701 [(set (match_operand:SI 0 "register_operand" "=r")
702 (match_operator:SI 1 "rx_fp_comparison_operator"
703 [(match_operand:SF 2 "register_operand" "r")
704 (match_operand:SF 3 "rx_source_operand" "rFQ")]))]
712 flags = gen_rtx_REG (CC_Fmode, CC_REG);
713 x = gen_rtx_COMPARE (CC_Fmode, operands[2], operands[3]);
714 x = gen_rtx_SET (VOIDmode, flags, x);
717 x = gen_rtx_fmt_ee (GET_CODE (operands[1]), SImode, flags, const0_rtx);
718 x = gen_rtx_SET (VOIDmode, operands[0], x);
723 (define_expand "movsicc"
725 [(set (match_operand:SI 0 "register_operand")
726 (if_then_else:SI (match_operand:SI 1 "comparison_operator")
727 (match_operand:SI 2 "nonmemory_operand")
728 (match_operand:SI 3 "nonmemory_operand")))
729 (clobber (reg:CC CC_REG))])]
732 /* One operand must be a constant or a register, the other must be a register. */
733 if ( ! CONSTANT_P (operands[2])
734 && ! CONSTANT_P (operands[3])
735 && ! (REG_P (operands[2]) && REG_P (operands[3])))
739 (define_insn_and_split "*movsicc"
740 [(set (match_operand:SI 0 "register_operand" "=r,r,r")
742 (match_operator 5 "comparison_operator"
743 [(match_operand:SI 3 "register_operand" "r,r,r")
744 (match_operand:SI 4 "rx_source_operand" "riQ,riQ,riQ")])
745 (match_operand:SI 1 "nonmemory_operand" "i,ri,r")
746 (match_operand:SI 2 "nonmemory_operand" "ri,i,r")))
747 (clobber (reg:CC CC_REG))]
748 "(CONSTANT_P (operands[1]) || CONSTANT_P (operands[2]))
749 || (REG_P (operands[1]) && REG_P (operands[2]))"
751 "&& reload_completed"
754 rtx x, flags, op0, op1, op2;
755 enum rtx_code cmp_code;
757 flags = gen_rtx_REG (CCmode, CC_REG);
758 x = gen_rtx_COMPARE (CCmode, operands[3], operands[4]);
759 emit_insn (gen_rtx_SET (VOIDmode, flags, x));
761 cmp_code = GET_CODE (operands[5]);
766 /* If OP2 is the constant, reverse the sense of the move.
767 Likewise if both operands are registers but OP1 == OP0. */
768 if ((! CONSTANT_P (operands[1]) && CONSTANT_P (operands[2]))
769 || (REG_P (operands[1]) && REG_P (operands[2])
770 && rtx_equal_p (op0, op1)))
772 x = op1, op1 = op2, op2 = x;
773 cmp_code = reverse_condition (cmp_code);
776 /* If OP2 does not match the output, copy it into place. We have allowed
777 these alternatives so that the destination can legitimately be one of
778 the comparison operands without increasing register pressure. */
779 if (! rtx_equal_p (op0, op2))
780 emit_move_insn (op0, op2);
782 x = gen_rtx_fmt_ee (cmp_code, VOIDmode, flags, const0_rtx);
783 x = gen_rtx_IF_THEN_ELSE (SImode, x, op1, op0);
784 emit_insn (gen_rtx_SET (VOIDmode, op0, x));
789 [(set (match_operand:SI 0 "register_operand" "+r,r,r,r")
791 (match_operator 2 "rx_z_comparison_operator"
792 [(reg CC_REG) (const_int 0)])
793 (match_operand:SI 1 "immediate_operand" "Sint08,Sint16,Sint24,i")
796 && ((GET_CODE (operands[2]) == EQ) || (GET_CODE (operands[2]) == NE))"
798 if (GET_CODE (operands[2]) == EQ)
799 return "stz\t%1, %0";
801 return "stnz\t%1, %0";
803 [(set_attr "length" "4,5,6,7")]
806 (define_insn "*stcc_reg"
807 [(set (match_operand:SI 0 "register_operand" "+r,r,r,r,r,r")
809 (match_operator 2 "comparison_operator"
810 [(reg CC_REG) (const_int 0)])
811 (match_operand:SI 1 "nonmemory_operand"
812 "r,Uint04,Sint08,Sint16,Sint24,i")
816 PUT_CODE (operands[2], reverse_condition (GET_CODE (operands[2])));
817 return "b%B2 1f\n\tmov %1, %0\n1:";
819 [(set_attr "length" "3,3,4,5,6,7")]
822 ;; Arithmetic Instructions
824 (define_insn "abssi2"
825 [(set (match_operand:SI 0 "register_operand" "=r,r")
826 (abs:SI (match_operand:SI 1 "register_operand" "0,r")))
827 (clobber (reg:CC CC_REG))]
832 [(set_attr "length" "2,3")]
835 (define_insn "*abssi2_flags"
836 [(set (match_operand:SI 0 "register_operand" "=r,r")
837 (abs:SI (match_operand:SI 1 "register_operand" "0,r")))
839 (compare (abs:SI (match_dup 1))
841 ;; Note - although the ABS instruction does set the O bit in the processor
842 ;; status word, it does not do so in a way that is comparable with the CMP
843 ;; instruction. Hence we use CC_ZSmode rather than CC_ZSOmode.
844 "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
848 [(set_attr "length" "2,3")]
851 (define_expand "addsi3"
852 [(parallel [(set (match_operand:SI 0 "register_operand" "")
853 (plus:SI (match_operand:SI 1 "register_operand" "")
854 (match_operand:SI 2 "rx_source_operand" "")))
855 (clobber (reg:CC CC_REG))])]
858 operands[0] = rx_maybe_pidify_operand (operands[0], 1);
859 operands[1] = rx_maybe_pidify_operand (operands[1], 1);
860 operands[2] = rx_maybe_pidify_operand (operands[2], 1);
864 (define_insn "addsi3_internal"
865 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r,r,r,r,r,r,r,r")
866 (plus:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0,0,r,r,r,r,r,r,0")
867 (match_operand:SI 2 "rx_source_operand" "r,Uint04,NEGint4,Sint08,Sint16,Sint24,i,0,r,Sint08,Sint16,Sint24,i,Q")))
868 (clobber (reg:CC CC_REG))]
885 [(set_attr "timings" "11,11,11,11,11,11,11,11,11,11,11,11,11,33")
886 (set_attr "length" "2,2,2,3,4,5,6,2,3,3,4,5,6,5")]
889 (define_insn "*addsi3_flags"
890 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r,r,r,r,r,r,r,r")
891 (plus:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0,0,r,r,r,r,r,r,0")
892 (match_operand:SI 2 "rx_source_operand" "r,Uint04,NEGint4,Sint08,Sint16,Sint24,i,0,r,Sint08,Sint16,Sint24,i,Q")))
894 (compare (plus:SI (match_dup 1) (match_dup 2))
896 "reload_completed && rx_match_ccmode (insn, CC_ZSCmode)"
912 [(set_attr "timings" "11,11,11,11,11,11,11,11,11,11,11,11,11,33")
913 (set_attr "length" "2,2,2,3,4,5,6,2,3,3,4,5,6,5")]
916 ;; A helper to expand the above with the CC_MODE filled in.
917 (define_expand "addsi3_flags"
918 [(parallel [(set (match_operand:SI 0 "register_operand")
919 (plus:SI (match_operand:SI 1 "register_operand")
920 (match_operand:SI 2 "rx_source_operand")))
921 (set (reg:CC_ZSC CC_REG)
922 (compare:CC_ZSC (plus:SI (match_dup 1) (match_dup 2))
926 (define_insn "adc_internal"
927 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r")
930 (ltu:SI (reg:CC CC_REG) (const_int 0))
931 (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0"))
932 (match_operand:SI 2 "rx_source_operand" "r,Sint08,Sint16,Sint24,i,Q")))
933 (clobber (reg:CC CC_REG))]
936 [(set_attr "timings" "11,11,11,11,11,33")
937 (set_attr "length" "3,4,5,6,7,6")]
940 (define_insn "*adc_flags"
941 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r")
944 (ltu:SI (reg:CC CC_REG) (const_int 0))
945 (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0"))
946 (match_operand:SI 2 "rx_source_operand" "r,Sint08,Sint16,Sint24,i,Q")))
951 (ltu:SI (reg:CC CC_REG) (const_int 0))
955 "reload_completed && rx_match_ccmode (insn, CC_ZSCmode)"
957 [(set_attr "timings" "11,11,11,11,11,33")
958 (set_attr "length" "3,4,5,6,7,6")]
961 ;; Peepholes to match:
962 ;; (set (reg A) (reg B))
963 ;; (set (CC) (compare:CC (reg A/reg B) (const_int 0)))
964 ;; and replace them with the addsi3_flags pattern, using an add
965 ;; of zero to copy the register and set the condition code bits.
967 [(set (match_operand:SI 0 "register_operand")
968 (match_operand:SI 1 "register_operand"))
970 (compare:CC (match_dup 0)
973 [(parallel [(set (match_dup 0)
974 (plus:SI (match_dup 1) (const_int 0)))
975 (set (reg:CC_ZSC CC_REG)
976 (compare:CC_ZSC (plus:SI (match_dup 1) (const_int 0))
981 [(set (match_operand:SI 0 "register_operand")
982 (match_operand:SI 1 "register_operand"))
984 (compare:CC (match_dup 1)
987 [(parallel [(set (match_dup 0)
988 (plus:SI (match_dup 1) (const_int 0)))
989 (set (reg:CC_ZSC CC_REG)
990 (compare:CC_ZSC (plus:SI (match_dup 1) (const_int 0))
994 (define_expand "adddi3"
995 [(set (match_operand:DI 0 "register_operand")
996 (plus:DI (match_operand:DI 1 "register_operand")
997 (match_operand:DI 2 "rx_source_operand")))]
1000 rtx op0l, op0h, op1l, op1h, op2l, op2h;
1002 op0l = gen_lowpart (SImode, operands[0]);
1003 op1l = gen_lowpart (SImode, operands[1]);
1004 op2l = gen_lowpart (SImode, operands[2]);
1005 op0h = gen_highpart (SImode, operands[0]);
1006 op1h = gen_highpart (SImode, operands[1]);
1007 op2h = gen_highpart_mode (SImode, DImode, operands[2]);
1009 emit_insn (gen_adddi3_internal (op0l, op0h, op1l, op2l, op1h, op2h));
1013 (define_insn_and_split "adddi3_internal"
1014 [(set (match_operand:SI 0 "register_operand" "=&r")
1015 (plus:SI (match_operand:SI 2 "register_operand" "r")
1016 (match_operand:SI 3 "rx_source_operand" "riQ")))
1017 (set (match_operand:SI 1 "register_operand" "=r")
1020 (ltu:SI (plus:SI (match_dup 2) (match_dup 3)) (match_dup 2))
1021 (match_operand:SI 4 "register_operand" "%1"))
1022 (match_operand:SI 5 "rx_source_operand" "riQ")))
1023 (clobber (match_scratch:SI 6 "=&r"))
1024 (clobber (reg:CC CC_REG))]
1030 rtx op0l = operands[0];
1031 rtx op0h = operands[1];
1032 rtx op1l = operands[2];
1033 rtx op2l = operands[3];
1034 rtx op1h = operands[4];
1035 rtx op2h = operands[5];
1036 rtx scratch = operands[6];
1039 if (reg_overlap_mentioned_p (op0l, op1h))
1041 emit_move_insn (scratch, op0l);
1043 if (reg_overlap_mentioned_p (op0l, op2h))
1046 else if (reg_overlap_mentioned_p (op0l, op2h))
1048 emit_move_insn (scratch, op0l);
1052 if (rtx_equal_p (op0l, op1l))
1054 /* It is preferable that op0l == op1l... */
1055 else if (rtx_equal_p (op0l, op2l))
1056 x = op1l, op1l = op2l, op2l = x;
1057 /* ... but it is only a requirement if op2l == MEM. */
1058 else if (MEM_P (op2l))
1060 /* Let's hope that we still have a scratch register free. */
1061 gcc_assert (op1h != scratch);
1062 emit_move_insn (scratch, op2l);
1066 emit_insn (gen_addsi3_flags (op0l, op1l, op2l));
1068 if (rtx_equal_p (op0h, op1h))
1070 else if (rtx_equal_p (op0h, op2h))
1071 x = op1h, op1h = op2h, op2h = x;
1074 emit_move_insn (op0h, op1h);
1077 emit_insn (gen_adc_internal (op0h, op1h, op2h));
1081 (define_insn "andsi3"
1082 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r,r,r")
1083 (and:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0,r,r,0")
1084 (match_operand:SI 2 "rx_source_operand" "r,Uint04,Sint08,Sint16,Sint24,i,0,r,Q")))
1085 (clobber (reg:CC CC_REG))]
1097 [(set_attr "timings" "11,11,11,11,11,11,11,11,33")
1098 (set_attr "length" "2,2,3,4,5,6,2,5,5")]
1101 (define_insn "*andsi3_flags"
1102 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r,r,r")
1103 (and:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0,r,r,0")
1104 (match_operand:SI 2 "rx_source_operand" "r,Uint04,Sint08,Sint16,Sint24,i,0,r,Q")))
1106 (compare (and:SI (match_dup 1) (match_dup 2))
1108 "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1119 [(set_attr "timings" "11,11,11,11,11,11,11,11,33")
1120 (set_attr "length" "2,2,3,4,5,6,2,5,5")]
1123 ;; Byte swap (single 32-bit value).
1124 (define_insn "bswapsi2"
1125 [(set (match_operand:SI 0 "register_operand" "=r")
1126 (bswap:SI (match_operand:SI 1 "register_operand" "r")))]
1129 [(set_attr "length" "3")]
1132 ;; Byte swap (single 16-bit value). Note - we ignore the swapping of the high 16-bits.
1133 (define_insn "bswaphi2"
1134 [(set (match_operand:HI 0 "register_operand" "=r")
1135 (bswap:HI (match_operand:HI 1 "register_operand" "r")))]
1138 [(set_attr "length" "3")]
1141 (define_insn "divsi3"
1142 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r")
1143 (div:SI (match_operand:SI 1 "register_operand" "0,0,0,0,0,0")
1144 (match_operand:SI 2 "rx_source_operand" "r,Sint08,Sint16,Sint24,i,Q")))
1145 (clobber (reg:CC CC_REG))]
1148 [(set_attr "timings" "1111") ;; Strictly speaking the timing should be
1149 ;; 2222, but that is a worst case sceanario.
1150 (set_attr "length" "3,4,5,6,7,6")]
1153 (define_insn "udivsi3"
1154 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r")
1155 (udiv:SI (match_operand:SI 1 "register_operand" "0,0,0,0,0,0")
1156 (match_operand:SI 2 "rx_source_operand" "r,Sint08,Sint16,Sint24,i,Q")))
1157 (clobber (reg:CC CC_REG))]
1160 [(set_attr "timings" "1010") ;; Strictly speaking the timing should be
1161 ;; 2020, but that is a worst case sceanario.
1162 (set_attr "length" "3,4,5,6,7,6")]
1165 ;; Note - these patterns are suppressed in big-endian mode because they
1166 ;; generate a little endian result. ie the most significant word of the
1167 ;; result is placed in the higher numbered register of the destination
1170 (define_insn "mulsidi3"
1171 [(set (match_operand:DI 0 "register_operand" "=r,r,r,r,r,r")
1172 (mult:DI (sign_extend:DI (match_operand:SI
1173 1 "register_operand" "%0,0,0,0,0,0"))
1174 (sign_extend:DI (match_operand:SI
1175 2 "rx_source_operand"
1176 "r,Sint08,Sint16,Sint24,i,Q"))))]
1177 "! TARGET_BIG_ENDIAN_DATA"
1179 [(set_attr "length" "3,4,5,6,7,6")
1180 (set_attr "timings" "22,22,22,22,22,44")]
1183 ;; See comment for mulsidi3.
1184 ;; Note - the zero_extends are to distinguish this pattern from the
1185 ;; mulsidi3 pattern. Immediate mode addressing is not supported
1186 ;; because gcc cannot handle the expression: (zero_extend (const_int)).
1187 (define_insn "umulsidi3"
1188 [(set (match_operand:DI 0 "register_operand" "=r,r")
1189 (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "%0,0"))
1190 (zero_extend:DI (match_operand:SI 2 "rx_compare_operand" "r,Q"))))]
1191 "! TARGET_BIG_ENDIAN_DATA"
1193 [(set_attr "length" "3,6")
1194 (set_attr "timings" "22,44")]
1197 (define_insn "smaxsi3"
1198 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r")
1199 (smax:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0")
1200 (match_operand:SI 2 "rx_source_operand"
1201 "r,Sint08,Sint16,Sint24,i,Q")))]
1204 [(set_attr "length" "3,4,5,6,7,6")
1205 (set_attr "timings" "11,11,11,11,11,33")]
1208 (define_insn "sminsi3"
1209 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r")
1210 (smin:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0")
1211 (match_operand:SI 2 "rx_source_operand"
1212 "r,Sint08,Sint16,Sint24,i,Q")))]
1215 [(set_attr "length" "3,4,5,6,7,6")
1216 (set_attr "timings" "11,11,11,11,11,33")]
1219 (define_insn "umax<small_int_modes:mode>3_u"
1220 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r")
1221 (smax:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0")
1222 (zero_extend:SI (match_operand:small_int_modes 2 "rx_minmaxex_operand"
1223 "r,Sint08,Sint16,Sint24,i,Q"))))]
1226 [(set_attr "length" "3,4,5,6,7,6")
1227 (set_attr "timings" "11,11,11,11,11,33")]
1230 (define_insn "umin<small_int_modes:mode>3_ur"
1231 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r")
1232 (smin:SI (zero_extend:SI (match_operand:small_int_modes 2 "rx_minmaxex_operand"
1233 "r,Sint08,Sint16,Sint24,i,Q"))
1234 (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0")))]
1237 [(set_attr "length" "3,4,5,6,7,6")
1238 (set_attr "timings" "11,11,11,11,11,33")]
1241 (define_insn "umax<small_int_modes:mode>3_ur"
1242 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r")
1243 (smax:SI (zero_extend:SI (match_operand:small_int_modes 2 "rx_minmaxex_operand"
1244 "r,Sint08,Sint16,Sint24,i,Q"))
1245 (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0")))]
1248 [(set_attr "length" "3,4,5,6,7,6")
1249 (set_attr "timings" "11,11,11,11,11,33")]
1252 (define_expand "umax<small_int_modes:mode>3"
1254 (zero_extend:SI (match_operand:small_int_modes 1 "register_operand" "%0,0,0,0,0,0")))
1256 (smax:SI (match_dup 4)
1257 (match_operand:small_int_modes 2 "rx_source_operand"
1258 "r,Sint08,Sint16,Sint24,i,Q")))
1259 (set (match_operand:small_int_modes 0 "register_operand" "=r,r,r,r,r,r")
1263 "operands[3] = gen_reg_rtx (SImode);
1264 operands[4] = gen_reg_rtx (SImode);
1265 operands[5] = gen_reg_rtx (SImode);
1266 operands[6] = gen_rtx_SUBREG (GET_MODE (operands[0]), operands[3],
1267 TARGET_BIG_ENDIAN_DATA ? (GET_MODE (operands[0]) == HImode ? 2 : 3) : 0);
1268 if (GET_CODE (operands[2]) != CONST_INT)
1270 emit_move_insn (operands[5], gen_rtx_ZERO_EXTEND (SImode, operands[2]));
1271 operands[2] = operands[5];
1276 (define_expand "umin<small_int_modes:mode>3"
1278 (zero_extend:SI (match_operand:small_int_modes 1 "register_operand" "%0,0,0,0,0,0")))
1280 (smin:SI (match_dup 4)
1281 (match_operand:small_int_modes 2 "rx_source_operand"
1282 "r,Sint08,Sint16,Sint24,i,Q")))
1283 (set (match_operand:small_int_modes 0 "register_operand" "=r,r,r,r,r,r")
1287 "operands[3] = gen_reg_rtx (SImode);
1288 operands[4] = gen_reg_rtx (SImode);
1289 operands[5] = gen_reg_rtx (SImode);
1290 operands[6] = gen_rtx_SUBREG (GET_MODE (operands[0]), operands[3],
1291 TARGET_BIG_ENDIAN_DATA ? (GET_MODE (operands[0]) == HImode ? 2 : 3) : 0);
1292 if (GET_CODE (operands[2]) != CONST_INT)
1294 emit_move_insn (operands[5], gen_rtx_ZERO_EXTEND (SImode, operands[2]));
1295 operands[2] = operands[5];
1300 (define_insn "mulsi3"
1301 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r,r,r")
1302 (mult:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0,0,r,r")
1303 (match_operand:SI 2 "rx_source_operand"
1304 "r,Uint04,Sint08,Sint16,Sint24,i,Q,0,r")))]
1316 [(set_attr "length" "2,2,3,4,5,6,5,2,3")
1317 (set_attr "timings" "11,11,11,11,11,11,33,11,11")]
1320 (define_insn "negsi2"
1321 [(set (match_operand:SI 0 "register_operand" "=r,r")
1322 (neg:SI (match_operand:SI 1 "register_operand" "0,r")))
1323 (clobber (reg:CC CC_REG))]
1328 [(set_attr "length" "2,3")]
1331 ;; Note that the O and C flags are not set as per a normal compare,
1332 ;; and thus are unusable in that context.
1333 (define_insn "*negsi2_flags"
1334 [(set (match_operand:SI 0 "register_operand" "=r,r")
1335 (neg:SI (match_operand:SI 1 "register_operand" "0,r")))
1337 (compare (neg:SI (match_dup 1))
1339 "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1343 [(set_attr "length" "2,3")]
1346 (define_insn "one_cmplsi2"
1347 [(set (match_operand:SI 0 "register_operand" "=r,r")
1348 (not:SI (match_operand:SI 1 "register_operand" "0,r")))
1349 (clobber (reg:CC CC_REG))]
1354 [(set_attr "length" "2,3")]
1357 (define_insn "*one_cmplsi2_flags"
1358 [(set (match_operand:SI 0 "register_operand" "=r,r")
1359 (not:SI (match_operand:SI 1 "register_operand" "0,r")))
1361 (compare (not:SI (match_dup 1))
1363 "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1367 [(set_attr "length" "2,3")]
1370 (define_insn "iorsi3"
1371 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r,r,r")
1372 (ior:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0,r,r,0")
1373 (match_operand:SI 2 "rx_source_operand" "r,Uint04,Sint08,Sint16,Sint24,i,0,r,Q")))
1374 (clobber (reg:CC CC_REG))]
1386 [(set_attr "timings" "11,11,11,11,11,11,11,11,33")
1387 (set_attr "length" "2,2,3,4,5,6,2,3,5")]
1390 (define_insn "*iorsi3_flags"
1391 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r,r,r,r")
1392 (ior:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0,r,r,0")
1393 (match_operand:SI 2 "rx_source_operand" "r,Uint04,Sint08,Sint16,Sint24,i,0,r,Q")))
1395 (compare (ior:SI (match_dup 1) (match_dup 2))
1397 "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1408 [(set_attr "timings" "11,11,11,11,11,11,11,11,33")
1409 (set_attr "length" "2,2,3,4,5,6,2,3,5")]
1412 (define_insn "rotlsi3"
1413 [(set (match_operand:SI 0 "register_operand" "=r")
1414 (rotate:SI (match_operand:SI 1 "register_operand" "0")
1415 (match_operand:SI 2 "rx_shift_operand" "rn")))
1416 (clobber (reg:CC CC_REG))]
1419 [(set_attr "length" "3")]
1422 (define_insn "*rotlsi3_flags"
1423 [(set (match_operand:SI 0 "register_operand" "=r")
1424 (rotate:SI (match_operand:SI 1 "register_operand" "0")
1425 (match_operand:SI 2 "rx_shift_operand" "rn")))
1427 (compare (rotate:SI (match_dup 1) (match_dup 2))
1429 "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1431 [(set_attr "length" "3")]
1434 (define_insn "rotrsi3"
1435 [(set (match_operand:SI 0 "register_operand" "=r")
1436 (rotatert:SI (match_operand:SI 1 "register_operand" "0")
1437 (match_operand:SI 2 "rx_shift_operand" "rn")))
1438 (clobber (reg:CC CC_REG))]
1441 [(set_attr "length" "3")]
1444 (define_insn "*rotrsi3_flags"
1445 [(set (match_operand:SI 0 "register_operand" "=r")
1446 (rotatert:SI (match_operand:SI 1 "register_operand" "0")
1447 (match_operand:SI 2 "rx_shift_operand" "rn")))
1449 (compare (rotatert:SI (match_dup 1) (match_dup 2))
1451 "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1453 [(set_attr "length" "3")]
1456 (define_insn "ashrsi3"
1457 [(set (match_operand:SI 0 "register_operand" "=r,r,r")
1458 (ashiftrt:SI (match_operand:SI 1 "register_operand" "0,0,r")
1459 (match_operand:SI 2 "rx_shift_operand" "r,n,n")))
1460 (clobber (reg:CC CC_REG))]
1466 [(set_attr "length" "3,2,3")]
1469 (define_insn "*ashrsi3_flags"
1470 [(set (match_operand:SI 0 "register_operand" "=r,r,r")
1471 (ashiftrt:SI (match_operand:SI 1 "register_operand" "0,0,r")
1472 (match_operand:SI 2 "rx_shift_operand" "r,n,n")))
1474 (compare (ashiftrt:SI (match_dup 1) (match_dup 2))
1476 "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1481 [(set_attr "length" "3,2,3")]
1484 (define_insn "lshrsi3"
1485 [(set (match_operand:SI 0 "register_operand" "=r,r,r")
1486 (lshiftrt:SI (match_operand:SI 1 "register_operand" "0,0,r")
1487 (match_operand:SI 2 "rx_shift_operand" "r,n,n")))
1488 (clobber (reg:CC CC_REG))]
1494 [(set_attr "length" "3,2,3")]
1497 (define_insn "*lshrsi3_flags"
1498 [(set (match_operand:SI 0 "register_operand" "=r,r,r")
1499 (lshiftrt:SI (match_operand:SI 1 "register_operand" "0,0,r")
1500 (match_operand:SI 2 "rx_shift_operand" "r,n,n")))
1502 (compare (lshiftrt:SI (match_dup 1) (match_dup 2))
1504 "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1509 [(set_attr "length" "3,2,3")]
1512 (define_insn "ashlsi3"
1513 [(set (match_operand:SI 0 "register_operand" "=r,r,r")
1514 (ashift:SI (match_operand:SI 1 "register_operand" "0,0,r")
1515 (match_operand:SI 2 "rx_shift_operand" "r,n,n")))
1516 (clobber (reg:CC CC_REG))]
1522 [(set_attr "length" "3,2,3")]
1525 (define_insn "*ashlsi3_flags"
1526 [(set (match_operand:SI 0 "register_operand" "=r,r,r")
1527 (ashift:SI (match_operand:SI 1 "register_operand" "0,0,r")
1528 (match_operand:SI 2 "rx_shift_operand" "r,n,n")))
1530 (compare (ashift:SI (match_dup 1) (match_dup 2))
1532 "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1537 [(set_attr "length" "3,2,3")]
1540 ;; Saturate to 32-bits
1541 (define_insn_and_split "ssaddsi3"
1542 [(set (match_operand:SI 0 "register_operand" "=r")
1543 (ss_plus:SI (match_operand:SI 1 "register_operand" "r")
1544 (match_operand:SI 2 "rx_source_operand" "riQ")))
1545 (clobber (reg:CC CC_REG))]
1549 [(parallel [(set (match_dup 0)
1550 (plus:SI (match_dup 1) (match_dup 2)))
1551 (set (reg:CC_ZSC CC_REG)
1553 (plus:SI (match_dup 1) (match_dup 2))
1556 (unspec:SI [(match_dup 0) (reg:CC CC_REG)]
1557 UNSPEC_BUILTIN_SAT))]
1562 [(set (match_operand:SI 0 "register_operand" "=r")
1563 (unspec:SI [(match_operand:SI 1 "register_operand" "0")
1565 UNSPEC_BUILTIN_SAT))]
1568 [(set_attr "length" "2")]
1571 (define_insn "subsi3"
1572 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r")
1573 (minus:SI (match_operand:SI 1 "register_operand" "0,0,0,r,0")
1574 (match_operand:SI 2 "rx_source_operand" "r,Uint04,n,r,Q")))
1575 (clobber (reg:CC CC_REG))]
1583 [(set_attr "timings" "11,11,11,11,33")
1584 (set_attr "length" "2,2,6,3,5")]
1587 ;; Note that the O flag is set as if (compare op1 op2) not for
1588 ;; what is described here, (compare op0 0).
1589 (define_insn "*subsi3_flags"
1590 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r")
1591 (minus:SI (match_operand:SI 1 "register_operand" "0,0,0,r,0")
1592 (match_operand:SI 2 "rx_source_operand" "r,Uint04,n,r,Q")))
1594 (compare (minus:SI (match_dup 1) (match_dup 2))
1596 "reload_completed && rx_match_ccmode (insn, CC_ZSCmode)"
1603 [(set_attr "timings" "11,11,11,11,33")
1604 (set_attr "length" "2,2,6,3,5")]
1607 ;; A helper to expand the above with the CC_MODE filled in.
1608 (define_expand "subsi3_flags"
1609 [(parallel [(set (match_operand:SI 0 "register_operand")
1610 (minus:SI (match_operand:SI 1 "register_operand")
1611 (match_operand:SI 2 "rx_source_operand")))
1612 (set (reg:CC_ZSC CC_REG)
1613 (compare:CC_ZSC (minus:SI (match_dup 1) (match_dup 2))
1617 (define_insn "sbb_internal"
1618 [(set (match_operand:SI 0 "register_operand" "=r,r")
1621 (match_operand:SI 1 "register_operand" " 0,0")
1622 (match_operand:SI 2 "rx_compare_operand" " r,Q"))
1623 (geu:SI (reg:CC CC_REG) (const_int 0))))
1624 (clobber (reg:CC CC_REG))]
1627 [(set_attr "timings" "11,33")
1628 (set_attr "length" "3,6")]
1631 (define_insn "*sbb_flags"
1632 [(set (match_operand:SI 0 "register_operand" "=r,r")
1635 (match_operand:SI 1 "register_operand" " 0,0")
1636 (match_operand:SI 2 "rx_compare_operand" " r,Q"))
1637 (geu:SI (reg:CC CC_REG) (const_int 0))))
1641 (minus:SI (match_dup 1) (match_dup 2))
1642 (geu:SI (reg:CC CC_REG) (const_int 0)))
1646 [(set_attr "timings" "11,33")
1647 (set_attr "length" "3,6")]
1650 (define_expand "subdi3"
1651 [(set (match_operand:DI 0 "register_operand")
1652 (minus:DI (match_operand:DI 1 "register_operand")
1653 (match_operand:DI 2 "register_operand")))]
1656 rtx op0l, op0h, op1l, op1h, op2l, op2h;
1658 op0l = gen_lowpart (SImode, operands[0]);
1659 op1l = gen_lowpart (SImode, operands[1]);
1660 op2l = gen_lowpart (SImode, operands[2]);
1661 op0h = gen_highpart (SImode, operands[0]);
1662 op1h = gen_highpart (SImode, operands[1]);
1663 op2h = gen_highpart_mode (SImode, DImode, operands[2]);
1665 emit_insn (gen_subdi3_internal (op0l, op0h, op1l, op2l, op1h, op2h));
1669 (define_insn_and_split "subdi3_internal"
1670 [(set (match_operand:SI 0 "register_operand" "=&r,&r")
1671 (minus:SI (match_operand:SI 2 "register_operand" " 0, r")
1672 (match_operand:SI 3 "rx_compare_operand" "rQ, r")))
1673 (set (match_operand:SI 1 "register_operand" "= r, r")
1676 (match_operand:SI 4 "register_operand" " 1, 1")
1677 (match_operand:SI 5 "rx_compare_operand" " rQ,rQ"))
1678 (geu:SI (match_dup 2) (match_dup 3))))
1679 (clobber (reg:CC CC_REG))]
1685 emit_insn (gen_subsi3_flags (operands[0], operands[2], operands[3]));
1686 emit_insn (gen_sbb_internal (operands[1], operands[4], operands[5]));
1690 (define_insn "xorsi3"
1691 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r")
1692 (xor:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0")
1693 (match_operand:SI 2 "rx_source_operand"
1694 "r,Sint08,Sint16,Sint24,i,Q")))
1695 (clobber (reg:CC CC_REG))]
1698 [(set_attr "timings" "11,11,11,11,11,33")
1699 (set_attr "length" "3,4,5,6,7,6")]
1702 (define_insn "*xorsi3_flags"
1703 [(set (match_operand:SI 0 "register_operand" "=r,r,r,r,r,r")
1704 (xor:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0")
1705 (match_operand:SI 2 "rx_source_operand"
1706 "r,Sint08,Sint16,Sint24,i,Q")))
1708 (compare (xor:SI (match_dup 1) (match_dup 2))
1710 "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1712 [(set_attr "timings" "11,11,11,11,11,33")
1713 (set_attr "length" "3,4,5,6,7,6")]
1716 ;; A set of peepholes to catch extending loads followed by arithmetic operations.
1717 ;; We use iterators where possible to reduce the amount of typing and hence the
1718 ;; possibilities for typos.
1720 (define_code_iterator extend_types [(zero_extend "") (sign_extend "")])
1721 (define_code_attr letter [(zero_extend "R") (sign_extend "Q")])
1723 (define_code_iterator memex_commutative [(plus "") (and "") (ior "") (xor "")])
1724 (define_code_iterator memex_noncomm [(div "") (udiv "") (minus "")])
1725 (define_code_iterator memex_nocc [(smax "") (smin "") (mult "")])
1727 (define_code_attr op [(plus "add") (and "and") (div "div") (udiv "divu") (smax "max") (smin "min") (mult "mul") (ior "or") (minus "sub") (xor "xor")])
1730 [(set (match_operand:SI 0 "register_operand")
1731 (extend_types:SI (match_operand:small_int_modes 1 "rx_restricted_mem_operand")))
1732 (parallel [(set (match_operand:SI 2 "register_operand")
1733 (memex_commutative:SI (match_dup 0)
1735 (clobber (reg:CC CC_REG))])]
1736 "peep2_regno_dead_p (2, REGNO (operands[0])) && (optimize < 3 || optimize_size)"
1737 [(parallel [(set:SI (match_dup 2)
1738 (memex_commutative:SI (match_dup 2)
1739 (extend_types:SI (match_dup 1))))
1740 (clobber (reg:CC CC_REG))])]
1744 [(set (match_operand:SI 0 "register_operand")
1745 (extend_types:SI (match_operand:small_int_modes 1 "rx_restricted_mem_operand")))
1746 (parallel [(set (match_operand:SI 2 "register_operand")
1747 (memex_commutative:SI (match_dup 2)
1749 (clobber (reg:CC CC_REG))])]
1750 "peep2_regno_dead_p (2, REGNO (operands[0])) && (optimize < 3 || optimize_size)"
1751 [(parallel [(set:SI (match_dup 2)
1752 (memex_commutative:SI (match_dup 2)
1753 (extend_types:SI (match_dup 1))))
1754 (clobber (reg:CC CC_REG))])]
1758 [(set (match_operand:SI 0 "register_operand")
1759 (extend_types:SI (match_operand:small_int_modes 1 "rx_restricted_mem_operand")))
1760 (parallel [(set (match_operand:SI 2 "register_operand")
1761 (memex_noncomm:SI (match_dup 2)
1763 (clobber (reg:CC CC_REG))])]
1764 "peep2_regno_dead_p (2, REGNO (operands[0])) && (optimize < 3 || optimize_size)"
1765 [(parallel [(set:SI (match_dup 2)
1766 (memex_noncomm:SI (match_dup 2)
1767 (extend_types:SI (match_dup 1))))
1768 (clobber (reg:CC CC_REG))])]
1772 [(set (match_operand:SI 0 "register_operand")
1773 (extend_types:SI (match_operand:small_int_modes 1 "rx_restricted_mem_operand")))
1774 (set (match_operand:SI 2 "register_operand")
1775 (memex_nocc:SI (match_dup 0)
1777 "peep2_regno_dead_p (2, REGNO (operands[0])) && (optimize < 3 || optimize_size)"
1778 [(set:SI (match_dup 2)
1779 (memex_nocc:SI (match_dup 2)
1780 (extend_types:SI (match_dup 1))))]
1784 [(set (match_operand:SI 0 "register_operand")
1785 (extend_types:SI (match_operand:small_int_modes 1 "rx_restricted_mem_operand")))
1786 (set (match_operand:SI 2 "register_operand")
1787 (memex_nocc:SI (match_dup 2)
1789 "peep2_regno_dead_p (2, REGNO (operands[0])) && (optimize < 3 || optimize_size)"
1790 [(set:SI (match_dup 2)
1791 (memex_nocc:SI (match_dup 2)
1792 (extend_types:SI (match_dup 1))))]
1795 (define_insn "<memex_commutative:code>si3_<extend_types:code><small_int_modes:mode>"
1796 [(set (match_operand:SI 0 "register_operand" "=r")
1797 (memex_commutative:SI (match_operand:SI 1 "register_operand" "%0")
1798 (extend_types:SI (match_operand:small_int_modes 2 "rx_restricted_mem_operand" "Q"))))
1799 (clobber (reg:CC CC_REG))]
1800 "(optimize < 3 || optimize_size)"
1801 "<memex_commutative:op>\t%<extend_types:letter>2, %0"
1802 [(set_attr "timings" "33")
1803 (set_attr "length" "5")] ;; This length is corrected in rx_adjust_insn_length
1806 (define_insn "<memex_noncomm:code>si3_<extend_types:code><small_int_modes:mode>"
1807 [(set (match_operand:SI 0 "register_operand" "=r")
1808 (memex_noncomm:SI (match_operand:SI 1 "register_operand" "0")
1809 (extend_types:SI (match_operand:small_int_modes 2 "rx_restricted_mem_operand" "Q"))))
1810 (clobber (reg:CC CC_REG))]
1811 "(optimize < 3 || optimize_size)"
1812 "<memex_noncomm:op>\t%<extend_types:letter>2, %0"
1813 [(set_attr "timings" "33")
1814 (set_attr "length" "5")] ;; This length is corrected in rx_adjust_insn_length
1817 (define_insn "<memex_nocc:code>si3_<extend_types:code><small_int_modes:mode>"
1818 [(set (match_operand:SI 0 "register_operand" "=r")
1819 (memex_nocc:SI (match_operand:SI 1 "register_operand" "%0")
1820 (extend_types:SI (match_operand:small_int_modes 2 "rx_restricted_mem_operand" "Q"))))]
1821 "(optimize < 3 || optimize_size)"
1822 "<memex_nocc:op>\t%<extend_types:letter>2, %0"
1823 [(set_attr "timings" "33")
1824 (set_attr "length" "5")] ;; This length is corrected in rx_adjust_insn_length
1828 [(set (match_operand:SI 0 "register_operand")
1829 (extend_types:SI (match_operand:small_int_modes 1 "rx_restricted_mem_operand")))
1830 (set (reg:CC CC_REG)
1831 (compare:CC (match_operand:SI 2 "register_operand")
1833 "peep2_regno_dead_p (2, REGNO (operands[0])) && (optimize < 3 || optimize_size)"
1834 [(set (reg:CC CC_REG)
1835 (compare:CC (match_dup 2)
1836 (extend_types:SI (match_dup 1))))]
1840 ;; (set (reg1) (sign_extend (mem))
1841 ;; (set (reg2) (zero_extend (reg1))
1843 ;; (set (reg2) (zero_extend (mem)))
1845 [(set (match_operand:SI 0 "register_operand")
1846 (sign_extend:SI (match_operand:small_int_modes 1 "memory_operand")))
1847 (set (match_operand:SI 2 "register_operand")
1848 (zero_extend:SI (match_operand:small_int_modes 3 "register_operand")))]
1849 "REGNO (operands[0]) == REGNO (operands[3])
1850 && (REGNO (operands[0]) == REGNO (operands[2])
1851 || peep2_regno_dead_p (2, REGNO (operands[0])))"
1853 (zero_extend:SI (match_dup 1)))]
1856 ;; Remove the redundant sign extension from:
1857 ;; (set (reg) (extend (mem)))
1858 ;; (set (reg) (extend (reg)))
1860 [(set (match_operand:SI 0 "register_operand")
1861 (extend_types:SI (match_operand:small_int_modes 1 "memory_operand")))
1863 (extend_types:SI (match_operand:small_int_modes 2 "register_operand")))]
1864 "REGNO (operands[0]) == REGNO (operands[2])"
1865 [(set (match_dup 0) (extend_types:SI (match_dup 1)))]
1868 (define_insn "comparesi3_<extend_types:code><small_int_modes:mode>"
1869 [(set (reg:CC CC_REG)
1870 (compare:CC (match_operand:SI 0 "register_operand" "r")
1871 (extend_types:SI (match_operand:small_int_modes 1 "rx_restricted_mem_operand" "Q"))))]
1872 "(optimize < 3 || optimize_size)"
1873 "cmp\t%<extend_types:letter>1, %0"
1874 [(set_attr "timings" "33")
1875 (set_attr "length" "5")] ;; This length is corrected in rx_adjust_insn_length
1878 ;; Floating Point Instructions
1880 (define_insn "addsf3"
1881 [(set (match_operand:SF 0 "register_operand" "=r,r,r")
1882 (plus:SF (match_operand:SF 1 "register_operand" "%0,0,0")
1883 (match_operand:SF 2 "rx_source_operand" "r,F,Q")))
1884 (clobber (reg:CC CC_REG))]
1885 "ALLOW_RX_FPU_INSNS"
1887 [(set_attr "timings" "44,44,66")
1888 (set_attr "length" "3,7,5")]
1891 (define_insn "divsf3"
1892 [(set (match_operand:SF 0 "register_operand" "=r,r,r")
1893 (div:SF (match_operand:SF 1 "register_operand" "0,0,0")
1894 (match_operand:SF 2 "rx_source_operand" "r,F,Q")))
1895 (clobber (reg:CC CC_REG))]
1896 "ALLOW_RX_FPU_INSNS"
1898 [(set_attr "timings" "1616,1616,1818")
1899 (set_attr "length" "3,7,5")]
1902 (define_insn "mulsf3"
1903 [(set (match_operand:SF 0 "register_operand" "=r,r,r")
1904 (mult:SF (match_operand:SF 1 "register_operand" "%0,0,0")
1905 (match_operand:SF 2 "rx_source_operand" "r,F,Q")))
1906 (clobber (reg:CC CC_REG))]
1907 "ALLOW_RX_FPU_INSNS"
1909 [(set_attr "timings" "33,33,55")
1910 (set_attr "length" "3,7,5")]
1913 (define_insn "subsf3"
1914 [(set (match_operand:SF 0 "register_operand" "=r,r,r")
1915 (minus:SF (match_operand:SF 1 "register_operand" "0,0,0")
1916 (match_operand:SF 2 "rx_source_operand" "r,F,Q")))
1917 (clobber (reg:CC CC_REG))]
1918 "ALLOW_RX_FPU_INSNS"
1920 [(set_attr "timings" "44,44,66")
1921 (set_attr "length" "3,7,5")]
1924 (define_insn "fix_truncsfsi2"
1925 [(set (match_operand:SI 0 "register_operand" "=r,r")
1926 (fix:SI (match_operand:SF 1 "rx_compare_operand" "r,Q")))
1927 (clobber (reg:CC CC_REG))]
1928 "ALLOW_RX_FPU_INSNS"
1930 [(set_attr "timings" "22,44")
1931 (set_attr "length" "3,5")]
1934 (define_insn "floatsisf2"
1935 [(set (match_operand:SF 0 "register_operand" "=r,r")
1936 (float:SF (match_operand:SI 1 "rx_compare_operand" "r,Q")))
1937 (clobber (reg:CC CC_REG))]
1938 "ALLOW_RX_FPU_INSNS"
1940 [(set_attr "timings" "22,44")
1941 (set_attr "length" "3,6")]
1944 ;; Bit manipulation instructions.
1946 ;; ??? The *_in_memory patterns will not be matched without further help.
1947 ;; At one time we had the insv expander generate them, but I suspect that
1948 ;; in general we get better performance by exposing the register load to
1951 ;; An alternate solution would be to re-organize these patterns such
1952 ;; that allow both register and memory operands. This would allow the
1953 ;; register allocator to spill and not load the register operand. This
1954 ;; would be possible only for operations for which we have a constant
1955 ;; bit offset, so that we can adjust the address by ofs/8 and replace
1956 ;; the offset in the insn by ofs%8.
1958 (define_insn "*bitset"
1959 [(set (match_operand:SI 0 "register_operand" "=r")
1960 (ior:SI (ashift:SI (const_int 1)
1961 (match_operand:SI 1 "rx_shift_operand" "ri"))
1962 (match_operand:SI 2 "register_operand" "0")))]
1965 [(set_attr "length" "3")]
1968 (define_insn "*bitset_in_memory"
1969 [(set (match_operand:QI 0 "rx_restricted_mem_operand" "+Q")
1970 (ior:QI (ashift:QI (const_int 1)
1971 (match_operand:QI 1 "nonmemory_operand" "ri"))
1975 [(set_attr "length" "3")
1976 (set_attr "timings" "33")]
1979 (define_insn "*bitinvert"
1980 [(set (match_operand:SI 0 "register_operand" "=r")
1981 (xor:SI (ashift:SI (const_int 1)
1982 (match_operand:SI 1 "rx_shift_operand" "ri"))
1983 (match_operand:SI 2 "register_operand" "0")))]
1986 [(set_attr "length" "3")]
1989 (define_insn "*bitinvert_in_memory"
1990 [(set (match_operand:QI 0 "rx_restricted_mem_operand" "+Q")
1991 (xor:QI (ashift:QI (const_int 1)
1992 (match_operand:QI 1 "nonmemory_operand" "ri"))
1996 [(set_attr "length" "5")
1997 (set_attr "timings" "33")]
2000 (define_insn "*bitclr"
2001 [(set (match_operand:SI 0 "register_operand" "=r")
2005 (match_operand:SI 1 "rx_shift_operand" "ri")))
2006 (match_operand:SI 2 "register_operand" "0")))]
2009 [(set_attr "length" "3")]
2012 (define_insn "*bitclr_in_memory"
2013 [(set (match_operand:QI 0 "rx_restricted_mem_operand" "+Q")
2017 (match_operand:QI 1 "nonmemory_operand" "ri")))
2021 [(set_attr "length" "3")
2022 (set_attr "timings" "33")]
2025 (define_insn "*insv_imm"
2026 [(set (zero_extract:SI
2027 (match_operand:SI 0 "register_operand" "+r")
2029 (match_operand:SI 1 "rx_shift_operand" "ri"))
2030 (match_operand:SI 2 "const_int_operand" ""))]
2033 if (INTVAL (operands[2]) & 1)
2034 return "bset\t%1, %0";
2036 return "bclr\t%1, %0";
2038 [(set_attr "length" "3")]
2041 (define_insn_and_split "rx_insv_reg"
2042 [(set (zero_extract:SI
2043 (match_operand:SI 0 "register_operand" "+r")
2045 (match_operand:SI 1 "const_int_operand" ""))
2046 (match_operand:SI 2 "register_operand" "r"))
2047 (clobber (reg:CC CC_REG))]
2051 [(set (zero_extract:SI (match_dup 0) (const_int 1) (match_dup 1))
2056 /* Emit tst #1, op2. */
2057 flags = gen_rtx_REG (CC_ZSmode, CC_REG);
2058 x = gen_rtx_AND (SImode, operands[2], const1_rtx);
2059 x = gen_rtx_COMPARE (CC_ZSmode, x, const0_rtx);
2060 x = gen_rtx_SET (VOIDmode, flags, x);
2064 operands[3] = gen_rtx_NE (SImode, flags, const0_rtx);
2067 (define_insn_and_split "*insv_cond"
2068 [(set (zero_extract:SI
2069 (match_operand:SI 0 "register_operand" "+r")
2071 (match_operand:SI 1 "const_int_operand" ""))
2072 (match_operator:SI 4 "comparison_operator"
2073 [(match_operand:SI 2 "register_operand" "r")
2074 (match_operand:SI 3 "rx_source_operand" "riQ")]))
2075 (clobber (reg:CC CC_REG))]
2079 [(set (zero_extract:SI (match_dup 0) (const_int 1) (match_dup 1))
2084 flags = gen_rtx_REG (CCmode, CC_REG);
2085 x = gen_rtx_COMPARE (CCmode, operands[2], operands[3]);
2086 x = gen_rtx_SET (VOIDmode, flags, x);
2089 operands[4] = gen_rtx_fmt_ee (GET_CODE (operands[4]), SImode,
2093 (define_insn "*bmcc"
2094 [(set (zero_extract:SI
2095 (match_operand:SI 0 "register_operand" "+r")
2097 (match_operand:SI 1 "const_int_operand" ""))
2098 (match_operator:SI 2 "comparison_operator"
2099 [(reg CC_REG) (const_int 0)]))]
2102 [(set_attr "length" "3")]
2105 ;; Work around the fact that X=Y<0 is preferentially expanded as a shift.
2106 (define_insn_and_split "*insv_cond_lt"
2107 [(set (zero_extract:SI
2108 (match_operand:SI 0 "register_operand" "+r")
2110 (match_operand:SI 1 "const_int_operand" ""))
2111 (match_operator:SI 3 "rshift_operator"
2112 [(match_operand:SI 2 "register_operand" "r")
2114 (clobber (reg:CC CC_REG))]
2118 [(parallel [(set (zero_extract:SI (match_dup 0) (const_int 1) (match_dup 1))
2119 (lt:SI (match_dup 2) (const_int 0)))
2120 (clobber (reg:CC CC_REG))])]
2124 (define_expand "insv"
2125 [(set (zero_extract:SI
2126 (match_operand:SI 0 "register_operand") ;; Destination
2127 (match_operand:SI 1 "const_int_operand") ;; # of bits to set
2128 (match_operand:SI 2 "nonmemory_operand")) ;; Starting bit
2129 (match_operand:SI 3 "nonmemory_operand"))] ;; Bits to insert
2132 /* We only handle single-bit inserts. */
2133 if (!CONST_INT_P (operands[1]) || INTVAL (operands[1]) != 1)
2136 /* Either the bit to insert or the position must be constant. */
2137 if (CONST_INT_P (operands[3]))
2138 operands[3] = GEN_INT (INTVAL (operands[3]) & 1);
2139 else if (CONST_INT_P (operands[2]))
2141 emit_insn (gen_rx_insv_reg (operands[0], operands[2], operands[3]));
2148 ;; Atomic exchange operation.
2150 (define_insn "sync_lock_test_and_setsi"
2151 [(set (match_operand:SI 0 "register_operand" "=r,r")
2152 (match_operand:SI 1 "rx_compare_operand" "=r,Q"))
2154 (match_operand:SI 2 "register_operand" "0,0"))]
2157 [(set_attr "length" "3,6")
2158 (set_attr "timings" "22")]
2161 ;; Block move functions.
2163 (define_expand "movstr"
2164 [(set (match_operand:BLK 1 "memory_operand") ;; Dest
2165 (match_operand:BLK 2 "memory_operand")) ;; Source
2166 (use (match_operand:SI 0 "register_operand")) ;; Updated Dest
2170 rtx addr1 = gen_rtx_REG (SImode, 1);
2171 rtx addr2 = gen_rtx_REG (SImode, 2);
2172 rtx len = gen_rtx_REG (SImode, 3);
2173 rtx dest_copy = gen_reg_rtx (SImode);
2175 emit_move_insn (len, GEN_INT (-1));
2176 emit_move_insn (addr1, force_operand (XEXP (operands[1], 0), NULL_RTX));
2177 emit_move_insn (addr2, force_operand (XEXP (operands[2], 0), NULL_RTX));
2178 operands[1] = replace_equiv_address_nv (operands[1], addr1);
2179 operands[2] = replace_equiv_address_nv (operands[2], addr2);
2180 emit_move_insn (dest_copy, addr1);
2181 emit_insn (gen_rx_movstr ());
2182 emit_move_insn (len, GEN_INT (-1));
2183 emit_insn (gen_rx_strend (operands[0], dest_copy));
2188 (define_insn "rx_movstr"
2189 [(set (mem:BLK (reg:SI 1))
2190 (mem:BLK (reg:SI 2)))
2191 (unspec_volatile:BLK [(reg:SI 1) (reg:SI 2) (reg:SI 3)] UNSPEC_MOVSTR)
2192 (clobber (reg:SI 1))
2193 (clobber (reg:SI 2))
2194 (clobber (reg:SI 3))]
2197 [(set_attr "length" "2")
2198 (set_attr "timings" "1111")] ;; The timing is a guesstimate.
2201 (define_insn "rx_strend"
2202 [(set (match_operand:SI 0 "register_operand" "=r")
2203 (unspec_volatile:SI [(match_operand:SI 1 "register_operand" "r")
2204 (reg:SI 3)] UNSPEC_STRLEN))
2205 (clobber (reg:SI 1))
2206 (clobber (reg:SI 2))
2207 (clobber (reg:SI 3))
2208 (clobber (reg:CC CC_REG))
2211 "mov\t%1, r1\n\tmov\t#0, r2\n\tsuntil.b\n\tmov\tr1, %0\n\tsub\t#1, %0"
2212 [(set_attr "length" "10")
2213 (set_attr "timings" "1111")] ;; The timing is a guesstimate.
2216 (define_expand "movmemsi"
2218 [(set (match_operand:BLK 0 "memory_operand") ;; Dest
2219 (match_operand:BLK 1 "memory_operand")) ;; Source
2220 (use (match_operand:SI 2 "register_operand")) ;; Length in bytes
2221 (match_operand 3 "immediate_operand") ;; Align
2222 (unspec_volatile:BLK [(reg:SI 1) (reg:SI 2) (reg:SI 3)] UNSPEC_MOVMEM)]
2226 rtx addr1 = gen_rtx_REG (SImode, 1);
2227 rtx addr2 = gen_rtx_REG (SImode, 2);
2228 rtx len = gen_rtx_REG (SImode, 3);
2230 /* Do not use when the source or destination are volatile - the SMOVF
2231 instruction will read and write in word sized blocks, which may be
2232 outside of the valid address range. */
2233 if (MEM_P (operands[0]) && MEM_VOLATILE_P (operands[0]))
2235 if (MEM_P (operands[1]) && MEM_VOLATILE_P (operands[1]))
2238 if (REG_P (operands[0]) && (REGNO (operands[0]) == 2
2239 || REGNO (operands[0]) == 3))
2241 if (REG_P (operands[1]) && (REGNO (operands[1]) == 1
2242 || REGNO (operands[1]) == 3))
2244 if (REG_P (operands[2]) && (REGNO (operands[2]) == 1
2245 || REGNO (operands[2]) == 2))
2248 emit_move_insn (addr1, force_operand (XEXP (operands[0], 0), NULL_RTX));
2249 emit_move_insn (addr2, force_operand (XEXP (operands[1], 0), NULL_RTX));
2250 emit_move_insn (len, force_operand (operands[2], NULL_RTX));
2251 operands[0] = replace_equiv_address_nv (operands[0], addr1);
2252 operands[1] = replace_equiv_address_nv (operands[1], addr2);
2253 emit_insn (gen_rx_movmem ());
2258 (define_insn "rx_movmem"
2259 [(set (mem:BLK (reg:SI 1))
2260 (mem:BLK (reg:SI 2)))
2262 (unspec_volatile:BLK [(reg:SI 1) (reg:SI 2) (reg:SI 3)] UNSPEC_MOVMEM)
2263 (clobber (reg:SI 1))
2264 (clobber (reg:SI 2))
2265 (clobber (reg:SI 3))]
2268 [(set_attr "length" "2")
2269 (set_attr "timings" "1111")] ;; The timing is a guesstimate.
2272 (define_expand "setmemsi"
2273 [(set (match_operand:BLK 0 "memory_operand") ;; Dest
2274 (match_operand:QI 2 "nonmemory_operand")) ;; Value
2275 (use (match_operand:SI 1 "nonmemory_operand")) ;; Length
2276 (match_operand 3 "immediate_operand") ;; Align
2277 (unspec_volatile:BLK [(reg:SI 1) (reg:SI 2) (reg:SI 3)] UNSPEC_SETMEM)]
2280 rtx addr = gen_rtx_REG (SImode, 1);
2281 rtx val = gen_rtx_REG (QImode, 2);
2282 rtx len = gen_rtx_REG (SImode, 3);
2284 emit_move_insn (addr, force_operand (XEXP (operands[0], 0), NULL_RTX));
2285 emit_move_insn (len, force_operand (operands[1], NULL_RTX));
2286 emit_move_insn (val, operands[2]);
2287 emit_insn (gen_rx_setmem ());
2292 (define_insn "rx_setmem"
2293 [(set (mem:BLK (reg:SI 1))
2294 (unspec_volatile:BLK [(reg:SI 1) (reg:SI 2) (reg:SI 3)] UNSPEC_SETMEM))
2295 (clobber (reg:SI 1))
2296 (clobber (reg:SI 3))]
2299 [(set_attr "length" "2")
2300 (set_attr "timings" "1111")] ;; The timing is a guesstimate.
2303 (define_expand "cmpstrnsi"
2304 [(set (match_operand:SI 0 "register_operand") ;; Result
2305 (unspec_volatile:SI [(match_operand:BLK 1 "memory_operand") ;; String1
2306 (match_operand:BLK 2 "memory_operand")] ;; String2
2308 (use (match_operand:SI 3 "register_operand")) ;; Max Length
2309 (match_operand:SI 4 "immediate_operand")] ;; Known Align
2312 rtx str1 = gen_rtx_REG (SImode, 1);
2313 rtx str2 = gen_rtx_REG (SImode, 2);
2314 rtx len = gen_rtx_REG (SImode, 3);
2316 emit_move_insn (str1, force_operand (XEXP (operands[1], 0), NULL_RTX));
2317 emit_move_insn (str2, force_operand (XEXP (operands[2], 0), NULL_RTX));
2318 emit_move_insn (len, force_operand (operands[3], NULL_RTX));
2320 emit_insn (gen_rx_cmpstrn (operands[0], operands[1], operands[2]));
2325 (define_expand "cmpstrsi"
2326 [(set (match_operand:SI 0 "register_operand") ;; Result
2327 (unspec_volatile:SI [(match_operand:BLK 1 "memory_operand") ;; String1
2328 (match_operand:BLK 2 "memory_operand")] ;; String2
2330 (match_operand:SI 3 "immediate_operand")] ;; Known Align
2333 rtx str1 = gen_rtx_REG (SImode, 1);
2334 rtx str2 = gen_rtx_REG (SImode, 2);
2335 rtx len = gen_rtx_REG (SImode, 3);
2337 emit_move_insn (str1, force_reg (SImode, XEXP (operands[1], 0)));
2338 emit_move_insn (str2, force_reg (SImode, XEXP (operands[2], 0)));
2339 emit_move_insn (len, GEN_INT (-1));
2341 emit_insn (gen_rx_cmpstrn (operands[0], operands[1], operands[2]));
2346 (define_insn "rx_cmpstrn"
2347 [(set (match_operand:SI 0 "register_operand" "=r")
2348 (unspec_volatile:SI [(reg:SI 1) (reg:SI 2) (reg:SI 3)]
2350 (use (match_operand:BLK 1 "memory_operand" "m"))
2351 (use (match_operand:BLK 2 "memory_operand" "m"))
2352 (clobber (reg:SI 1))
2353 (clobber (reg:SI 2))
2354 (clobber (reg:SI 3))
2355 (clobber (reg:CC CC_REG))]
2357 "scmpu ; Perform the string comparison
2358 mov #-1, %0 ; Set up -1 result (which cannot be created
2360 bnc ?+ ; If Carry is not set skip over
2361 scne.L %0 ; Set result based on Z flag
2364 [(set_attr "length" "9")
2365 (set_attr "timings" "1111")] ;; The timing is a guesstimate.
2368 ;; Builtin Functions
2370 ;; GCC does not have the ability to generate the following instructions
2371 ;; on its own so they are provided as builtins instead. To use them from
2372 ;; a program for example invoke them as __builtin_rx_<insn_name>. For
2375 ;; int short_byte_swap (int arg) { return __builtin_rx_revw (arg); }
2377 ;;---------- Accumulator Support ------------------------
2379 ;; Multiply & Accumulate (high)
2380 (define_insn "machi"
2381 [(unspec:SI [(match_operand:SI 0 "register_operand" "r")
2382 (match_operand:SI 1 "register_operand" "r")]
2383 UNSPEC_BUILTIN_MACHI)]
2386 [(set_attr "length" "3")]
2389 ;; Multiply & Accumulate (low)
2390 (define_insn "maclo"
2391 [(unspec:SI [(match_operand:SI 0 "register_operand" "r")
2392 (match_operand:SI 1 "register_operand" "r")]
2393 UNSPEC_BUILTIN_MACLO)]
2396 [(set_attr "length" "3")]
2400 (define_insn "mulhi"
2401 [(unspec:SI [(match_operand:SI 0 "register_operand" "r")
2402 (match_operand:SI 1 "register_operand" "r")]
2403 UNSPEC_BUILTIN_MULHI)]
2406 [(set_attr "length" "3")]
2410 (define_insn "mullo"
2411 [(unspec:SI [(match_operand:SI 0 "register_operand" "r")
2412 (match_operand:SI 1 "register_operand" "r")]
2413 UNSPEC_BUILTIN_MULLO)]
2416 [(set_attr "length" "3")]
2419 ;; Move from Accumulator (high)
2420 (define_insn "mvfachi"
2421 [(set (match_operand:SI 0 "register_operand" "=r")
2422 (unspec:SI [(const_int 0)]
2423 UNSPEC_BUILTIN_MVFACHI))]
2426 [(set_attr "length" "3")]
2429 ;; Move from Accumulator (middle)
2430 (define_insn "mvfacmi"
2431 [(set (match_operand:SI 0 "register_operand" "=r")
2432 (unspec:SI [(const_int 0)]
2433 UNSPEC_BUILTIN_MVFACMI))]
2436 [(set_attr "length" "3")]
2439 ;; Move to Accumulator (high)
2440 (define_insn "mvtachi"
2441 [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")]
2442 UNSPEC_BUILTIN_MVTACHI)]
2445 [(set_attr "length" "3")]
2448 ;; Move to Accumulator (low)
2449 (define_insn "mvtaclo"
2450 [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")]
2451 UNSPEC_BUILTIN_MVTACLO)]
2454 [(set_attr "length" "3")]
2457 ;; Round Accumulator
2459 [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i")]
2460 UNSPEC_BUILTIN_RACW)]
2463 [(set_attr "length" "3")]
2466 ;; Repeat multiply and accumulate
2468 [(unspec:SI [(const_int 0) (reg:SI 1) (reg:SI 2) (reg:SI 3)
2469 (reg:SI 4) (reg:SI 5) (reg:SI 6)]
2470 UNSPEC_BUILTIN_RMPA)
2471 (clobber (reg:SI 1))
2472 (clobber (reg:SI 2))
2473 (clobber (reg:SI 3))]
2476 [(set_attr "length" "2")
2477 (set_attr "timings" "1010")]
2480 ;;---------- Arithmetic ------------------------
2482 ;; Byte swap (two 16-bit values).
2484 [(set (match_operand:SI 0 "register_operand" "=r")
2485 (unspec:SI [(match_operand:SI 1 "register_operand" "r")]
2486 UNSPEC_BUILTIN_REVW))]
2489 [(set_attr "length" "3")]
2492 ;; Round to integer.
2493 (define_insn "lrintsf2"
2494 [(set (match_operand:SI 0 "register_operand" "=r,r")
2495 (unspec:SI [(match_operand:SF 1 "rx_compare_operand" "r,Q")]
2496 UNSPEC_BUILTIN_ROUND))
2497 (clobber (reg:CC CC_REG))]
2500 [(set_attr "timings" "22,44")
2501 (set_attr "length" "3,5")]
2504 ;;---------- Control Registers ------------------------
2506 ;; Clear Processor Status Word
2507 (define_insn "clrpsw"
2508 [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i")]
2509 UNSPEC_BUILTIN_CLRPSW)
2510 (clobber (reg:CC CC_REG))]
2513 [(set_attr "length" "2")]
2516 ;; Set Processor Status Word
2517 (define_insn "setpsw"
2518 [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i")]
2519 UNSPEC_BUILTIN_SETPSW)
2520 (clobber (reg:CC CC_REG))]
2523 [(set_attr "length" "2")]
2526 ;; Move from control register
2528 [(set (match_operand:SI 0 "register_operand" "=r")
2529 (unspec_volatile:SI [(match_operand:SI 1 "immediate_operand" "i")]
2530 UNSPEC_BUILTIN_MVFC))]
2533 [(set_attr "length" "3")]
2536 ;; Move to control register
2538 [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i,i")
2539 (match_operand:SI 1 "nonmemory_operand" "r,i")]
2540 UNSPEC_BUILTIN_MVTC)]
2543 [(set_attr "length" "3,7")]
2544 ;; Ignore possible clobbering of the comparison flags in the
2545 ;; PSW register. This is a cc0 target so any cc0 setting
2546 ;; instruction will always be paired with a cc0 user, without
2547 ;; the possibility of this instruction being placed in between
2551 ;; Move to interrupt priority level
2552 (define_insn "mvtipl"
2553 [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "Uint04")]
2554 UNSPEC_BUILTIN_MVTIPL)]
2557 [(set_attr "length" "3")]
2560 ;;---------- Interrupts ------------------------
2564 [(unspec_volatile [(const_int 0)]
2565 UNSPEC_BUILTIN_BRK)]
2568 [(set_attr "length" "1")
2569 (set_attr "timings" "66")]
2574 [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i")]
2575 UNSPEC_BUILTIN_INT)]
2578 [(set_attr "length" "3")]
2583 [(unspec_volatile [(const_int 0)]
2584 UNSPEC_BUILTIN_WAIT)]
2587 [(set_attr "length" "2")]
2590 ;;---------- CoProcessor Support ------------------------
2592 ;; FIXME: The instructions are currently commented out because
2593 ;; the bit patterns have not been finalized, so the assembler
2594 ;; does not support them. Once they are decided and the assembler
2595 ;; supports them, enable the instructions here.
2597 ;; Move from co-processor register
2598 (define_insn "mvfcp"
2599 [(set (match_operand:SI 0 "register_operand" "=r")
2600 (unspec:SI [(match_operand:SI 1 "immediate_operand" "i")
2601 (match_operand:SI 2 "immediate_operand" "i")]
2602 UNSPEC_BUILTIN_MVFCP))]
2604 "; mvfcp\t%1, %0, %2"
2605 [(set_attr "length" "5")]
2608 ;;---------- Misc ------------------------
2610 ;; Required by cfglayout.c...
2615 [(set_attr "length" "1")]
2618 (define_expand "pid_addr"
2619 [(plus:SI (match_operand:SI 0)
2620 (const:SI (unspec:SI [(match_operand:SI 1)] UNSPEC_PID_ADDR)))]
2625 (define_insn "movdi"
2626 [(set:DI (match_operand:DI 0 "nonimmediate_operand" "=rm")
2627 (match_operand:DI 1 "general_operand" "rmi"))]
2629 { return rx_gen_move_template (operands, false); }
2630 [(set_attr "length" "16")
2631 (set_attr "timings" "22")]
2634 (define_insn "movdf"
2635 [(set:DF (match_operand:DF 0 "nonimmediate_operand" "=rm")
2636 (match_operand:DF 1 "general_operand" "rmi"))]
2638 { return rx_gen_move_template (operands, false); }
2639 [(set_attr "length" "16")
2640 (set_attr "timings" "22")]