Rebase.
[official-gcc.git] / gcc / config / rx / rx.md
blob65e9ab92607e076bc6fcd99f77a52b887e8a3fe3
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)
10 ;; any later version.
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
31 ;; library functions.
32 (define_mode_iterator register_modes
33   [(SF "") (SI "") (HI "") (QI "")])
35 (define_constants
36   [
37    (SP_REG 0)
38    (CC_REG                 16)
40    (UNSPEC_LOW_REG         0)
41    (UNSPEC_HIGH_REG        1)
43    (UNSPEC_RTE             10)
44    (UNSPEC_RTFI            11)
45    (UNSPEC_NAKED           12)
46    (UNSPEC_CONST           13)
47    
48    (UNSPEC_MOVSTR          20)
49    (UNSPEC_MOVMEM          21)
50    (UNSPEC_SETMEM          22)
51    (UNSPEC_STRLEN          23)
52    (UNSPEC_CMPSTRN         24)
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)
77    (UNSPEC_PID_ADDR        52)
78   ]
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 ;; ----------------------------------------------------------------------------
143 ;; Comparisons
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"
152   [(set (pc)
153         (if_then_else
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 ""))
158           (pc)))]
159   ""
162 (define_insn_and_split "*cbranchsi4"
163   [(set (pc)
164         (if_then_else
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" "")
169           (pc)))]
170   ""
171   "#"
172   "reload_completed"
173   [(const_int 0)]
175   rx_split_cbranch (CCmode, GET_CODE (operands[3]),
176                     operands[0], operands[1], operands[2]);
177   DONE;
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")))]
184   "reload_completed"
185   "cmp\t%Q1, %0"
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"
192   [(set (pc)
193         (if_then_else
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"))
197              (const_int 0)])
198           (match_operand 2 "label_ref_operand" "")
199           (pc)))]
200   ""
201   "#"
202   "reload_completed"
203   [(const_int 0)]
205   rx_split_cbranch (CC_ZSmode, GET_CODE (operands[3]),
206                     XEXP (operands[3], 0), XEXP (operands[3], 1),
207                     operands[2]);
208   DONE;
211 ;; Various other ways that GCC codes "var & const"
212 (define_insn_and_split "*cbranchsi4_tst_ext"
213   [(set (pc)
214         (if_then_else
215           (match_operator 4 "rx_z_comparison_operator"
216             [(zero_extract:SI
217                 (match_operand:SI 0 "register_operand" "r")
218                 (match_operand:SI 1 "rx_constshift_operand" "")
219                 (match_operand:SI 2 "rx_constshift_operand" ""))
220              (const_int 0)])
221           (match_operand 3 "label_ref_operand" "")
222           (pc)))]
223   ""
224   "#"
225   "reload_completed"
226   [(const_int 0)]
228   HOST_WIDE_INT mask;
229   rtx x;
231   mask = 1;
232   mask <<= INTVAL (operands[1]);
233   mask -= 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]);
239   DONE;
242 (define_insn "*tstsi"
243   [(set (reg:CC_ZS CC_REG)
244         (compare:CC_ZS
245           (and:SI (match_operand:SI 0 "register_operand"  "r,r,r")
246                   (match_operand:SI 1 "rx_source_operand" "r,i,Q"))
247           (const_int 0)))]
248   "reload_completed"
249   "tst\t%Q1, %0"
250   [(set_attr "timings" "11,11,33")
251    (set_attr "length"  "3,7,6")]
254 (define_expand "cbranchsf4"
255   [(set (pc)
256         (if_then_else
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 ""))
261           (pc)))]
262   "ALLOW_RX_FPU_INSNS"
265 (define_insn_and_split "*cbranchsf4"
266   [(set (pc)
267         (if_then_else
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" "")
272           (pc)))]
273   "ALLOW_RX_FPU_INSNS"
274   "#"
275   "&& reload_completed"
276   [(const_int 0)]
278   rx_split_cbranch (CC_Fmode, GET_CODE (operands[3]),
279                     operands[0], operands[1], operands[2]);
280   DONE;
283 (define_insn "*cmpsf"
284   [(set (reg:CC_F CC_REG)
285         (compare:CC_F
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"
289   "fcmp\t%1, %0"
290   [(set_attr "timings" "11,11,33")
291    (set_attr "length" "3,7,5")]
294 ;; Flow Control Instructions:
296 (define_insn "*conditional_branch"
297   [(set (pc)
298         (if_then_else
299           (match_operator 1 "comparison_operator"
300             [(reg CC_REG) (const_int 0)])
301           (label_ref (match_operand 0 "" ""))
302           (pc)))]
303   "reload_completed"
304   "b%B1\t%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 ;; ----------------------------------------------------------------------------
312 (define_insn "jump"
313   [(set (pc)
314         (label_ref (match_operand 0 "" "")))]
315   ""
316   "bra\t%0"
317   [(set_attr "length" "4")
318    (set_attr "timings" "33")]
321 (define_insn "indirect_jump"
322   [(set (pc)
323         (match_operand:SI 0 "register_operand" "r"))]
324   ""
325   "jmp\t%0"
326   [(set_attr "length" "2")
327    (set_attr "timings" "33")]
330 (define_insn "tablejump"
331   [(set (pc)
332         (match_operand:SI          0 "register_operand" "r"))
333    (use (label_ref (match_operand  1 "" "")))]
334   ""
335   { return TARGET_PID ? (TARGET_AS100_SYNTAX ? "\n?:\tbra\t%0"
336                                              : "\n1:\tbra\t%0")
337                                              : "\n1:jmp\t%0";
338   }
339   [(set_attr "timings" "33")
340    (set_attr "length" "2")]
343 (define_expand "return"
344   [(return)]
345   "rx_can_use_simple_return ()"
346   "rx_expand_epilogue (false); DONE;"
349 (define_insn "simple_return"
350   [(simple_return)]
351   ""
352   "rts"
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))))
363    (return)]
364   ""
365   "rtsd\t%0"
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")))])
375    (return)]
376   "reload_completed"
377   {
378     rx_emit_stack_popm (operands, false);
379     return "";
380   }
381   [(set_attr "length" "3")
382    (set_attr "timings" "56")]
385 (define_insn "fast_interrupt_return"
386   [(unspec_volatile [(return)] UNSPEC_RTFI) ]
387   ""
388   "rtfi"
389   [(set_attr "length" "2")
390    (set_attr "timings" "33")]
393 (define_insn "exception_return"
394   [(unspec_volatile [(return)] UNSPEC_RTE) ]
395   ""
396   "rte"
397   [(set_attr "length" "2")
398    (set_attr "timings" "66")]
401 (define_insn "naked_return"
402   [(unspec_volatile [(return)] UNSPEC_NAKED) ]
403   ""
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
414 ;; FUNCTION_MODE
416 (define_expand "call"
417   [(call (match_operand:QI 0 "general_operand")
418          (match_operand:SI 1 "general_operand"))]
419   ""
420   {
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));
426     DONE;
427   }
430 (define_insn "call_internal"
431   [(call (mem:QI (match_operand:SI 0 "rx_call_operand" "r,Symbol"))
432          (const_int 0))
433    (clobber (reg:CC CC_REG))]
434   ""
435   "@
436   jsr\t%0
437   bsr\t%A0"
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")))]
446   ""
447   {
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));
453     DONE;
454   }
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"))
460               (const_int 0)))
461    (clobber (reg:CC CC_REG))]
462   ""
463   "@
464   jsr\t%1
465   bsr\t%A1"
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
474 ;; off of the stack.
475 (define_expand "sibcall"
476   [(parallel
477     [(call (mem:QI (match_operand:SI 0 "rx_symbolic_call_operand"))
478            (match_operand:SI         1 "general_operand"))
479      (return)])]
480   ""
481   {
482     if (MEM_P (operands[0]))
483       operands[0] = XEXP (operands[0], 0);
484     emit_call_insn (gen_sibcall_internal (operands[0]));
485     DONE;
486   }
489 (define_insn "sibcall_internal"
490   [(call (mem:QI (match_operand:SI 0 "rx_symbolic_call_operand" "Symbol"))
491          (const_int 0))
492    (return)]
493   ""
494   "bra\t%A0"
495   [(set_attr "length"  "4")
496    (set_attr "timings" "33")]
499 (define_expand "sibcall_value"
500  [(parallel
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")))
504     (return)])]
505   ""
506   {
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]));
510     DONE;
511   }
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"))
517              (const_int 0)))
518   (return)]
519   ""
520   "bra\t%A1"
521   [(set_attr "length"  "4")
522    (set_attr "timings" "33")]
525 ;; Function Prologue/Epilogue Instructions
527 (define_expand "prologue"
528   [(const_int 0)]
529   ""
530   "rx_expand_prologue (); DONE;"
533 (define_expand "epilogue"
534   [(return)]
535   ""
536   "rx_expand_epilogue (false); DONE;"
539 (define_expand "sibcall_epilogue"
540   [(return)]
541   ""
542   "rx_expand_epilogue (true); DONE;"
545 ;; Move Instructions
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"))]
565   ""
566   {
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)
575       {
576         emit_insn (gen_addsi3 (operands[0], XEXP (operands[1], 0), XEXP (operands[1], 1)));
577         DONE;
578       }
579     if (CONST_INT_P (operand1)
580         && ! rx_is_legitimate_constant (<register_modes:MODE>mode, operand1))
581       FAIL;
582   }
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"))]
590   ""
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")))]
600   ""
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")))]
610   ""
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)
619                   (const_int 4)))
620    (set (mem:SI (minus:SI (reg:SI SP_REG) (const_int 4)))
621         (match_operand:SI 0 "register_operand" "r"))]
622   ""
623   "push.l\t%0"
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")))])]
632   "reload_completed"
633   {
634     rx_emit_stack_pushm (operands);
635     return "";
636   }
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)))
644    (set (reg:SI SP_REG)
645         (plus:SI (reg:SI SP_REG)
646                  (const_int 4)))]
647   ""
648   "pop\t%0"
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")))])]
658   "reload_completed"
659   {
660     rx_emit_stack_popm (operands, true);
661     return "";
662   }
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))]
673   ""
674   "#"
675   "reload_completed"
676   [(const_int 0)]
678   rtx flags, x;
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);
683   emit_insn (x);
685   x = gen_rtx_fmt_ee (GET_CODE (operands[1]), SImode, flags, const0_rtx);
686   x = gen_rtx_SET (VOIDmode, operands[0], x);
687   emit_insn (x);
688   DONE;
691 (define_insn "*sccc"
692   [(set (match_operand:SI 0 "register_operand" "=r")
693         (match_operator:SI 1 "comparison_operator"
694           [(reg CC_REG) (const_int 0)]))]
695   "reload_completed"
696   "sc%B1.L\t%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")]))]
705   "ALLOW_RX_FPU_INSNS"
706   "#"
707   "reload_completed"
708   [(const_int 0)]
710   rtx flags, x;
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);
715   emit_insn (x);
717   x = gen_rtx_fmt_ee (GET_CODE (operands[1]), SImode, flags, const0_rtx);
718   x = gen_rtx_SET (VOIDmode, operands[0], x);
719   emit_insn (x);
720   DONE;
723 (define_expand "movsicc"
724   [(parallel
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))])]
730   ""
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])))
736     FAIL;
739 (define_insn_and_split "*movsicc"
740   [(set (match_operand:SI     0 "register_operand" "=r,r,r")
741         (if_then_else:SI
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]))"
750   "#"
751   "&& reload_completed"
752   [(const_int 0)]
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]);
762   op0 = operands[0];
763   op1 = operands[1];
764   op2 = operands[2];
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)))
771     {
772       x = op1, op1 = op2, op2 = x;
773       cmp_code = reverse_condition (cmp_code);
774     }
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));
785   DONE;
788 (define_insn "*stcc"
789   [(set (match_operand:SI 0 "register_operand" "+r,r,r,r")
790         (if_then_else:SI
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")
794           (match_dup 0)))]
795   "reload_completed
796    && ((GET_CODE (operands[2]) == EQ) || (GET_CODE (operands[2]) == NE))"
797   {
798     if (GET_CODE (operands[2]) == EQ)
799       return "stz\t%1, %0";
800     else
801      return "stnz\t%1, %0";
802   }
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")
808         (if_then_else:SI
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")
813           (match_dup 0)))]
814   "reload_completed"
815   {
816     PUT_CODE (operands[2], reverse_condition (GET_CODE (operands[2])));
817     return "b%B2 1f\n\tmov %1, %0\n1:";
818   }
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))]
828   ""
829   "@
830   abs\t%0
831   abs\t%1, %0"
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")))
838    (set (reg CC_REG)
839         (compare (abs:SI (match_dup 1))
840                  (const_int 0)))]
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)"
845   "@
846   abs\t%0
847   abs\t%1, %0"
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))])]
856   ""
857   "
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);
861   "
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))]
869   ""
870   "@
871   add\t%2, %0
872   add\t%2, %0
873   sub\t%N2, %0
874   add\t%2, %0
875   add\t%2, %0
876   add\t%2, %0
877   add\t%2, %0
878   add\t%1, %0
879   add\t%2, %1, %0
880   add\t%2, %1, %0
881   add\t%2, %1, %0
882   add\t%2, %1, %0
883   add\t%2, %1, %0
884   add\t%Q2, %0"
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")))
893    (set (reg CC_REG)
894         (compare (plus:SI (match_dup 1) (match_dup 2))
895                  (const_int 0)))]
896   "reload_completed && rx_match_ccmode (insn, CC_ZSCmode)"
897   "@
898   add\t%2, %0
899   add\t%2, %0
900   sub\t%N2, %0
901   add\t%2, %0
902   add\t%2, %0
903   add\t%2, %0
904   add\t%2, %0
905   add\t%1, %0
906   add\t%2, %1, %0
907   add\t%2, %1, %0
908   add\t%2, %1, %0
909   add\t%2, %1, %0
910   add\t%2, %1, %0
911   add\t%Q2, %0"
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))
923                                    (const_int 0)))])]
926 (define_insn "adc_internal"
927   [(set (match_operand:SI     0 "register_operand"  "=r,r,r,r,r,r")
928         (plus:SI
929           (plus:SI
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))]
934   "reload_completed"
935   "adc\t%2, %0"
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")
942         (plus:SI
943           (plus:SI
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")))
947    (set (reg CC_REG)
948         (compare 
949           (plus:SI
950             (plus:SI
951               (ltu:SI (reg:CC CC_REG) (const_int 0))
952               (match_dup 1))
953             (match_dup 2))
954           (const_int 0)))]
955   "reload_completed && rx_match_ccmode (insn, CC_ZSCmode)"
956   "adc\t%2, %0"
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.
966 (define_peephole2
967   [(set (match_operand:SI 0 "register_operand")
968         (match_operand:SI 1 "register_operand"))
969    (set (reg:CC CC_REG)
970         (compare:CC (match_dup 0)
971                     (const_int 0)))]
972   ""
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))
977                                    (const_int 0)))])]
980 (define_peephole2
981   [(set (match_operand:SI 0 "register_operand")
982         (match_operand:SI 1 "register_operand"))
983    (set (reg:CC CC_REG)
984         (compare:CC (match_dup 1)
985                     (const_int 0)))]
986   ""
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))
991                                    (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")))]
998   ""
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));
1010   DONE;
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")
1018         (plus:SI
1019           (plus:SI
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))]
1025   ""
1026   "#"
1027   "reload_completed"
1028   [(const_int 0)]
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];
1037   rtx x;
1039   if (reg_overlap_mentioned_p (op0l, op1h))
1040     {
1041       emit_move_insn (scratch, op0l);
1042       op1h = scratch;
1043       if (reg_overlap_mentioned_p (op0l, op2h))
1044         op2h = scratch;
1045     }
1046   else if (reg_overlap_mentioned_p (op0l, op2h))
1047     {
1048       emit_move_insn (scratch, op0l);
1049       op2h = scratch;
1050     }
1052   if (rtx_equal_p (op0l, op1l))
1053     ;
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))
1059     {
1060       /* Let's hope that we still have a scratch register free.  */
1061       gcc_assert (op1h != scratch);
1062       emit_move_insn (scratch, op2l);
1063       op2l = scratch;
1064     }
1066   emit_insn (gen_addsi3_flags (op0l, op1l, op2l));
1068   if (rtx_equal_p (op0h, op1h))
1069     ;
1070   else if (rtx_equal_p (op0h, op2h))
1071     x = op1h, op1h = op2h, op2h = x;
1072   else
1073     {
1074       emit_move_insn (op0h, op1h);
1075       op1h = op0h;
1076     }
1077   emit_insn (gen_adc_internal (op0h, op1h, op2h));
1078   DONE;
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))]
1086   ""
1087   "@
1088   and\t%2, %0
1089   and\t%2, %0
1090   and\t%2, %0
1091   and\t%2, %0
1092   and\t%2, %0
1093   and\t%2, %0
1094   and\t%1, %0
1095   and\t%2, %1, %0
1096   and\t%Q2, %0"
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")))
1105    (set (reg CC_REG)
1106         (compare (and:SI (match_dup 1) (match_dup 2))
1107                  (const_int 0)))]
1108   "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1109   "@
1110   and\t%2, %0
1111   and\t%2, %0
1112   and\t%2, %0
1113   and\t%2, %0
1114   and\t%2, %0
1115   and\t%2, %0
1116   and\t%1, %0
1117   and\t%2, %1, %0
1118   and\t%Q2, %0"
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")))]
1127   ""
1128   "revl\t%1, %0"
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")))]
1136   ""
1137   "revw\t%1, %0"
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))]
1146   ""
1147   "div\t%Q2, %0"
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))]
1158   ""
1159   "divu\t%Q2, %0"
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
1168 ;; register pair.
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"
1178   "emul\t%Q2, %0"
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"
1192   "emulu\t%Q2, %0"
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")))]
1202   ""
1203   "max\t%Q2, %0"
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")))]
1213   ""
1214   "min\t%Q2, %0"
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"))))]
1224   ""
1225   "max\t%R2, %0"
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")))]
1235   ""
1236   "min\t%R2, %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")))]
1246   ""
1247   "max\t%R2, %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"
1253   [(set (match_dup 4)
1254         (zero_extend:SI (match_operand:small_int_modes 1 "register_operand" "%0,0,0,0,0,0")))
1255    (set (match_dup 3)
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")
1260         (match_dup 6))
1261    ]
1262   ""
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)
1269      {
1270        emit_move_insn (operands[5], gen_rtx_ZERO_EXTEND (SImode, operands[2]));
1271        operands[2] = operands[5];
1272      }
1273   "
1276 (define_expand "umin<small_int_modes:mode>3"
1277   [(set (match_dup 4)
1278         (zero_extend:SI (match_operand:small_int_modes 1 "register_operand" "%0,0,0,0,0,0")))
1279    (set (match_dup 3)
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")
1284         (match_dup 6))
1285    ]
1286   ""
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)
1293      {
1294        emit_move_insn (operands[5], gen_rtx_ZERO_EXTEND (SImode, operands[2]));
1295        operands[2] = operands[5];
1296      }
1297    "
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")))]
1305   ""
1306   "@
1307   mul\t%2, %0
1308   mul\t%2, %0
1309   mul\t%2, %0
1310   mul\t%2, %0
1311   mul\t%2, %0
1312   mul\t%Q2, %0
1313   mul\t%Q2, %0
1314   mul\t%1, %0
1315   mul\t%2, %1, %0"
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))]
1324   ""
1325   "@
1326   neg\t%0
1327   neg\t%1, %0"
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")))
1336    (set (reg CC_REG)
1337         (compare (neg:SI (match_dup 1))
1338                  (const_int 0)))]
1339   "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1340   "@
1341   neg\t%0
1342   neg\t%1, %0"
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))]
1350   ""
1351   "@
1352   not\t%0
1353   not\t%1, %0"
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")))
1360    (set (reg CC_REG)
1361         (compare (not:SI (match_dup 1))
1362                  (const_int 0)))]
1363   "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1364   "@
1365   not\t%0
1366   not\t%1, %0"
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))]
1375   ""
1376   "@
1377   or\t%2, %0
1378   or\t%2, %0
1379   or\t%2, %0
1380   or\t%2, %0
1381   or\t%2, %0
1382   or\t%Q2, %0
1383   or\t%1, %0
1384   or\t%2, %1, %0
1385   or\t%Q2, %0"
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")))
1394    (set (reg CC_REG)
1395         (compare (ior:SI (match_dup 1) (match_dup 2))
1396                  (const_int 0)))]
1397   "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1398   "@
1399   or\t%2, %0
1400   or\t%2, %0
1401   or\t%2, %0
1402   or\t%2, %0
1403   or\t%2, %0
1404   or\t%Q2, %0
1405   or\t%1, %0
1406   or\t%2, %1, %0
1407   or\t%Q2, %0"
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))]
1417   ""
1418   "rotl\t%2, %0"
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")))
1426    (set (reg CC_REG)
1427         (compare (rotate:SI (match_dup 1) (match_dup 2))
1428                  (const_int 0)))]
1429   "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1430   "rotl\t%2, %0"
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))]
1439   ""
1440   "rotr\t%2, %0"
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")))
1448    (set (reg CC_REG)
1449         (compare (rotatert:SI (match_dup 1) (match_dup 2))
1450                  (const_int 0)))]
1451   "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1452   "rotr\t%2, %0"
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))]
1461   ""
1462   "@
1463   shar\t%2, %0
1464   shar\t%2, %0
1465   shar\t%2, %1, %0"
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")))
1473    (set (reg CC_REG)
1474         (compare (ashiftrt:SI (match_dup 1) (match_dup 2))
1475                  (const_int 0)))]
1476   "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1477   "@
1478   shar\t%2, %0
1479   shar\t%2, %0
1480   shar\t%2, %1, %0"
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))]
1489   ""
1490   "@
1491   shlr\t%2, %0
1492   shlr\t%2, %0
1493   shlr\t%2, %1, %0"
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")))
1501    (set (reg CC_REG)
1502         (compare (lshiftrt:SI (match_dup 1) (match_dup 2))
1503                  (const_int 0)))]
1504   "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1505   "@
1506   shlr\t%2, %0
1507   shlr\t%2, %0
1508   shlr\t%2, %1, %0"
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))]
1517   ""
1518   "@
1519   shll\t%2, %0
1520   shll\t%2, %0
1521   shll\t%2, %1, %0"
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")))
1529    (set (reg CC_REG)
1530         (compare (ashift:SI (match_dup 1) (match_dup 2))
1531                  (const_int 0)))]
1532   "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1533   "@
1534   shll\t%2, %0
1535   shll\t%2, %0
1536   shll\t%2, %1, %0"
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))]
1546   ""
1547   "#"
1548   "reload_completed"
1549   [(parallel [(set (match_dup 0)
1550                    (plus:SI (match_dup 1) (match_dup 2)))
1551               (set (reg:CC_ZSC CC_REG)
1552                    (compare:CC_ZSC
1553                      (plus:SI (match_dup 1) (match_dup 2))
1554                      (const_int 0)))])
1555    (set (match_dup 0)
1556         (unspec:SI [(match_dup 0) (reg:CC CC_REG)] 
1557                    UNSPEC_BUILTIN_SAT))]
1558    ""
1561 (define_insn "*sat"
1562   [(set (match_operand:SI             0 "register_operand" "=r")
1563         (unspec:SI [(match_operand:SI 1 "register_operand"  "0")
1564                     (reg:CC CC_REG)]
1565                    UNSPEC_BUILTIN_SAT))]
1566   "reload_completed"
1567   "sat\t%0"
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))]
1576   ""
1577   "@
1578   sub\t%2, %0
1579   sub\t%2, %0
1580   add\t%N2, %0
1581   sub\t%2, %1, %0
1582   sub\t%Q2, %0"
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")))
1593    (set (reg CC_REG)
1594         (compare (minus:SI (match_dup 1) (match_dup 2))
1595                  (const_int 0)))]
1596   "reload_completed && rx_match_ccmode (insn, CC_ZSCmode)"
1597   "@
1598   sub\t%2, %0
1599   sub\t%2, %0
1600   add\t%N2, %0
1601   sub\t%2, %1, %0
1602   sub\t%Q2, %0"
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))
1614                                    (const_int 0)))])]
1617 (define_insn "sbb_internal"
1618   [(set (match_operand:SI     0 "register_operand"   "=r,r")
1619         (minus:SI
1620           (minus:SI
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))]
1625   "reload_completed"
1626   "sbb\t%2, %0"
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")
1633         (minus:SI
1634           (minus:SI
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))))
1638    (set (reg CC_REG)
1639         (compare
1640           (minus:SI
1641             (minus:SI (match_dup 1) (match_dup 2))
1642             (geu:SI (reg:CC CC_REG) (const_int 0)))
1643           (const_int 0)))]
1644   "reload_completed"
1645   "sbb\t%2, %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")))]
1654   ""
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));
1666   DONE;
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")
1674         (minus:SI
1675           (minus:SI
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))]
1680   ""
1681   "#"
1682   "reload_completed"
1683   [(const_int 0)]
1685   emit_insn (gen_subsi3_flags (operands[0], operands[2], operands[3]));
1686   emit_insn (gen_sbb_internal (operands[1], operands[4], operands[5]));
1687   DONE;
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))]
1696   ""
1697   "xor\t%Q2, %0"
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")))
1707    (set (reg CC_REG)
1708         (compare (xor:SI (match_dup 1) (match_dup 2))
1709                  (const_int 0)))]
1710   "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1711   "xor\t%Q2, %0"
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")])
1729 (define_peephole2
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)
1734                                          (match_dup 2)))
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))])]
1743 (define_peephole2
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)
1748                                          (match_dup 0)))
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))])]
1757 (define_peephole2
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)
1762                                      (match_dup 0)))
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))])]
1771 (define_peephole2
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)
1776                        (match_dup 2)))]
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))))]
1783 (define_peephole2
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)
1788                        (match_dup 0)))]
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
1827 (define_peephole2
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")
1832                     (match_dup 0)))]
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))))]
1839 ;; Convert:
1840 ;;   (set (reg1) (sign_extend (mem))
1841 ;;   (set (reg2) (zero_extend (reg1))
1842 ;; into
1843 ;;   (set (reg2) (zero_extend (mem)))
1844 (define_peephole2
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])))"
1852   [(set (match_dup 2)
1853         (zero_extend:SI (match_dup 1)))]
1856 ;; Remove the redundant sign extension from:
1857 ;;   (set (reg) (extend (mem)))
1858 ;;   (set (reg) (extend (reg)))
1859 (define_peephole2
1860   [(set (match_operand:SI                               0 "register_operand")
1861         (extend_types:SI (match_operand:small_int_modes 1 "memory_operand")))
1862    (set (match_dup 0)
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"
1886   "fadd\t%2, %0"
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"
1897   "fdiv\t%2, %0"
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"
1908   "fmul\t%2, %0"
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"
1919   "fsub\t%Q2, %0"
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"
1929   "ftoi\t%Q1, %0"
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"
1939   "itof\t%Q1, %0"
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
1949 ;; the optimizers.
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")))]
1963   ""
1964   "bset\t%1, %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"))
1972                 (match_dup 0)))]
1973   ""
1974   "bset\t%1, %0.B"
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")))]
1984   ""
1985   "bnot\t%1, %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"))
1993                 (match_dup 0)))]
1994   ""
1995   "bnot\t%1, %0.B"
1996   [(set_attr "length" "5")
1997    (set_attr "timings" "33")]
2000 (define_insn "*bitclr"
2001   [(set (match_operand:SI 0 "register_operand" "=r")
2002         (and:SI (not:SI
2003                   (ashift:SI
2004                     (const_int 1)
2005                     (match_operand:SI 1 "rx_shift_operand" "ri")))
2006                 (match_operand:SI 2 "register_operand" "0")))]
2007   ""
2008   "bclr\t%1, %0"
2009   [(set_attr "length" "3")]
2012 (define_insn "*bitclr_in_memory"
2013   [(set (match_operand:QI 0 "rx_restricted_mem_operand" "+Q")
2014         (and:QI (not:QI
2015                   (ashift:QI
2016                     (const_int 1)
2017                     (match_operand:QI 1 "nonmemory_operand" "ri")))
2018                 (match_dup 0)))]
2019   ""
2020   "bclr\t%1, %0.B"
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")
2028           (const_int 1)
2029           (match_operand:SI 1 "rx_shift_operand" "ri"))
2030         (match_operand:SI 2 "const_int_operand" ""))]
2031   ""
2033   if (INTVAL (operands[2]) & 1)
2034     return "bset\t%1, %0";
2035   else
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")
2044           (const_int 1)
2045           (match_operand:SI 1 "const_int_operand" ""))
2046         (match_operand:SI 2 "register_operand" "r"))
2047    (clobber (reg:CC CC_REG))]
2048   ""
2049   "#"
2050   "reload_completed"
2051   [(set (zero_extract:SI (match_dup 0) (const_int 1) (match_dup 1))
2052         (match_dup 3))]
2054   rtx flags, x;
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);
2061   emit_insn (x);
2063   /* Emit bmne.  */
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")
2070           (const_int 1)
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))]
2076   ""
2077   "#"
2078   "reload_completed"
2079   [(set (zero_extract:SI (match_dup 0) (const_int 1) (match_dup 1))
2080         (match_dup 4))]
2082   rtx flags, x;
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);
2087   emit_insn (x);
2089   operands[4] = gen_rtx_fmt_ee (GET_CODE (operands[4]), SImode,
2090                                 flags, const0_rtx);
2093 (define_insn "*bmcc"
2094   [(set (zero_extract:SI
2095           (match_operand:SI 0 "register_operand" "+r")
2096           (const_int 1)
2097           (match_operand:SI 1 "const_int_operand" ""))
2098         (match_operator:SI 2 "comparison_operator"
2099           [(reg CC_REG) (const_int 0)]))]
2100   "reload_completed"
2101   "bm%B2\t%1, %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")
2109           (const_int 1)
2110           (match_operand:SI 1 "const_int_operand" ""))
2111         (match_operator:SI 3 "rshift_operator"
2112           [(match_operand:SI 2 "register_operand" "r")
2113            (const_int 31)]))
2114    (clobber (reg:CC CC_REG))]
2115   ""
2116   "#"
2117   ""
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))])]
2121   ""
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
2130   ""
2132   /* We only handle single-bit inserts.  */
2133   if (!CONST_INT_P (operands[1]) || INTVAL (operands[1]) != 1)
2134     FAIL;
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]))
2140     {
2141       emit_insn (gen_rx_insv_reg (operands[0], operands[2], operands[3]));
2142       DONE;
2143     }
2144   else
2145     FAIL;
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"))
2153    (set (match_dup 1)
2154         (match_operand:SI 2 "register_operand"    "0,0"))]
2155   ""
2156   "xchg\t%1, %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
2167   ]
2168   ""
2169   {
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));
2184     DONE;
2185   }
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))]
2195   ""
2196   "smovu"
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))
2209    ]
2210   ""
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"
2217   [(parallel
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)]
2223     )]
2224   ""
2225   {
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]))
2234       FAIL;
2235     if (MEM_P (operands[1]) && MEM_VOLATILE_P (operands[1]))
2236       FAIL;
2238     if (REG_P (operands[0]) && (REGNO (operands[0]) == 2
2239                                       || REGNO (operands[0]) == 3))
2240       FAIL;
2241     if (REG_P (operands[1]) && (REGNO (operands[1]) == 1
2242                                       || REGNO (operands[1]) == 3))
2243       FAIL;
2244     if (REG_P (operands[2]) && (REGNO (operands[2]) == 1
2245                                       || REGNO (operands[2]) == 2))
2246       FAIL;
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 ());
2254     DONE;
2255   }
2258 (define_insn "rx_movmem"
2259   [(set (mem:BLK (reg:SI 1))
2260         (mem:BLK (reg:SI 2)))
2261    (use (reg:SI 3))
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))]
2266   ""
2267   "smovf"
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)]
2278   ""
2279   {
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 ());
2288     DONE;
2289   }
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))]
2297   ""
2298   "sstr.b"
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
2307                             UNSPEC_CMPSTRN))
2308    (use (match_operand:SI                       3 "register_operand"))  ;; Max Length
2309    (match_operand:SI                            4 "immediate_operand")] ;; Known Align
2310   ""
2311   {
2312     rtx str1 = gen_rtx_REG (SImode, 1);
2313     rtx str2 = gen_rtx_REG (SImode, 2);
2314     rtx len  = gen_rtx_REG (SImode, 3);
2315   
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]));
2321     DONE;
2322   }
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
2329                             UNSPEC_CMPSTRN))
2330    (match_operand:SI                            3 "immediate_operand")] ;; Known Align
2331   ""
2332   {
2333     rtx str1 = gen_rtx_REG (SImode, 1);
2334     rtx str2 = gen_rtx_REG (SImode, 2);
2335     rtx len  = gen_rtx_REG (SImode, 3);
2336   
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]));
2342     DONE;
2343   }
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)]
2349                             UNSPEC_CMPSTRN))
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))]
2356   ""
2357   "scmpu                ; Perform the string comparison
2358    mov     #-1, %0      ; Set up -1 result (which cannot be created
2359                         ; by the SC insn)
2360    bnc     ?+           ; If Carry is not set skip over
2361    scne.L  %0           ; Set result based on Z flag
2362 ?:                      
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
2373 ;; example:
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)]
2384   ""
2385   "machi\t%0, %1"
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)]
2394   ""
2395   "maclo\t%0, %1"
2396   [(set_attr "length" "3")]
2399 ;; Multiply (high)
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)]
2404   ""
2405   "mulhi\t%0, %1"
2406   [(set_attr "length" "3")]
2409 ;; Multiply (low)
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)]
2414   ""
2415   "mullo\t%0, %1"
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))]
2424   ""
2425   "mvfachi\t%0"
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))]
2434   ""
2435   "mvfacmi\t%0"
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)]
2443   ""
2444   "mvtachi\t%0"
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)]
2452   ""
2453   "mvtaclo\t%0"
2454   [(set_attr "length" "3")]
2457 ;; Round Accumulator
2458 (define_insn "racw"
2459   [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i")]
2460                        UNSPEC_BUILTIN_RACW)]
2461   ""
2462   "racw\t%0"
2463   [(set_attr "length" "3")]
2466 ;; Repeat multiply and accumulate
2467 (define_insn "rmpa"
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))]
2474   ""
2475   "rmpa"
2476   [(set_attr "length" "2")
2477    (set_attr "timings" "1010")]
2480 ;;---------- Arithmetic ------------------------
2482 ;; Byte swap (two 16-bit values).
2483 (define_insn "revw"
2484   [(set (match_operand:SI             0 "register_operand" "=r")
2485         (unspec:SI [(match_operand:SI 1 "register_operand"  "r")]
2486                    UNSPEC_BUILTIN_REVW))]
2487   ""
2488   "revw\t%1, %0"
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))]
2498   ""
2499   "round\t%1, %0"
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))]
2511   ""
2512   "clrpsw\t%F0"
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))]
2521   ""
2522   "setpsw\t%F0"
2523   [(set_attr "length" "2")]
2526 ;; Move from control register
2527 (define_insn "mvfc"
2528   [(set (match_operand:SI             0 "register_operand" "=r")
2529         (unspec_volatile:SI [(match_operand:SI 1 "immediate_operand" "i")]
2530                    UNSPEC_BUILTIN_MVFC))]
2531   ""
2532   "mvfc\t%C1, %0"
2533   [(set_attr "length" "3")]
2536 ;; Move to control register
2537 (define_insn "mvtc"
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)]
2541   ""
2542   "mvtc\t%1, %C0"
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
2548   ;; them.
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)]
2555   ""
2556   "mvtipl\t%0"
2557   [(set_attr "length" "3")]
2560 ;;---------- Interrupts ------------------------
2562 ;; Break
2563 (define_insn "brk"
2564   [(unspec_volatile [(const_int 0)]
2565                     UNSPEC_BUILTIN_BRK)]
2566   ""
2567   "brk"
2568   [(set_attr "length" "1")
2569    (set_attr "timings" "66")]
2572 ;; Interrupt
2573 (define_insn "int"
2574   [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i")]
2575                        UNSPEC_BUILTIN_INT)]
2576   ""
2577   "int\t%0"
2578   [(set_attr "length" "3")]
2581 ;; Wait
2582 (define_insn "wait"
2583   [(unspec_volatile [(const_int 0)]
2584                     UNSPEC_BUILTIN_WAIT)]
2585   ""
2586   "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))]
2603   ""
2604   "; mvfcp\t%1, %0, %2"
2605   [(set_attr "length" "5")]
2608 ;;---------- Misc ------------------------
2610 ;; Required by cfglayout.c...
2611 (define_insn "nop"
2612   [(const_int 0)]
2613   ""
2614   "nop"
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)))]
2621   ""
2622   ""
2625 (define_insn "movdi"
2626   [(set:DI (match_operand:DI 0 "nonimmediate_operand" "=rm")
2627            (match_operand:DI 1 "general_operand"      "rmi"))]
2628   "TARGET_ENABLE_LRA"
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"))]
2637   "TARGET_ENABLE_LRA"
2638   { return rx_gen_move_template (operands, false); }
2639   [(set_attr "length" "16")
2640    (set_attr "timings" "22")]