2018-02-09 Sebastian Perta <sebastian.perta@renesas.com>
[official-gcc.git] / gcc / config / rx / rx.md
blob35263b1adc7d513a56e96c35c6bc1ac32770d765
1 ;;  Machine Description for Renesas RX processors
2 ;;  Copyright (C) 2008-2018 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)
79    (CTRLREG_PSW             0)
80    (CTRLREG_USP             2)
81    (CTRLREG_FPSW            3)
82    (CTRLREG_CPEN            4)
83    (CTRLREG_BPSW            8)
84    (CTRLREG_BPC             9)
85    (CTRLREG_ISP            10)
86    (CTRLREG_FINTV          11)
87    (CTRLREG_INTB           12)
88   ]
91 (define_attr "length" "" (const_int 8))
93 (include "predicates.md")
94 (include "constraints.md")
96 ;; Pipeline description.
98 ;; The RX only has a single pipeline.  It has five stages (fetch,
99 ;; decode, execute, memory access, writeback) each of which normally
100 ;; takes a single CPU clock cycle.
102 ;; The timings attribute consists of two numbers, the first is the
103 ;; throughput, which is the number of cycles the instruction takes
104 ;; to execute and generate a result.  The second is the latency
105 ;; which is the effective number of cycles the instruction takes to
106 ;; execute if its result is used by the following instruction.  The
107 ;; latency is always greater than or equal to the throughput.
108 ;; These values were taken from tables 2.13 and 2.14 in section 2.8
109 ;; of the RX610 Group Hardware Manual v0.11
111 ;; Note - it would be nice to use strings rather than integers for
112 ;; the possible values of this attribute, so that we can have the
113 ;; gcc build mechanism check for values that are not supported by
114 ;; the reservations below.  But this will not work because the code
115 ;; in rx_adjust_sched_cost() needs integers not strings.
117 (define_attr "timings" "" (const_int 11))
119 (define_automaton "pipelining")
120 (define_cpu_unit "throughput" "pipelining")
122 (define_insn_reservation "throughput__1_latency__1"  1
123   (eq_attr "timings" "11") "throughput")
124 (define_insn_reservation "throughput__1_latency__2"  2
125   (eq_attr "timings" "12") "throughput,nothing")
126 (define_insn_reservation "throughput__2_latency__2"  1
127   (eq_attr "timings" "22") "throughput*2")
128 (define_insn_reservation "throughput__3_latency__3"  1
129   (eq_attr "timings" "33") "throughput*3")
130 (define_insn_reservation "throughput__3_latency__4"  2
131   (eq_attr "timings" "34") "throughput*3,nothing")
132 (define_insn_reservation "throughput__4_latency__4"  1
133   (eq_attr "timings" "44") "throughput*4")
134 (define_insn_reservation "throughput__4_latency__5"  2
135   (eq_attr "timings" "45") "throughput*4,nothing")
136 (define_insn_reservation "throughput__5_latency__5"  1
137   (eq_attr "timings" "55") "throughput*5")
138 (define_insn_reservation "throughput__5_latency__6"  2
139   (eq_attr "timings" "56") "throughput*5,nothing")
140 (define_insn_reservation "throughput__6_latency__6"  1
141   (eq_attr "timings" "66") "throughput*6")
142 (define_insn_reservation "throughput_10_latency_10"  1
143   (eq_attr "timings" "1010") "throughput*10")
144 (define_insn_reservation "throughput_11_latency_11"  1
145   (eq_attr "timings" "1111") "throughput*11")
146 (define_insn_reservation "throughput_16_latency_16"  1
147   (eq_attr "timings" "1616") "throughput*16")
148 (define_insn_reservation "throughput_18_latency_18"  1
149   (eq_attr "timings" "1818") "throughput*18")
151 ;; ----------------------------------------------------------------------------
153 ;; Comparisons
155 ;; Note - we do not specify the two instructions necessary to perform
156 ;; a compare-and-branch in the cbranchsi4 pattern because that would
157 ;; allow the comparison to be moved away from the jump before the reload
158 ;; pass has completed.  That would be problematical because reload can
159 ;; generate ADDSI3 instructions which would corrupt the PSW flags.
161 (define_expand "cbranchsi4"
162   [(set (pc)
163         (if_then_else
164           (match_operator 0 "comparison_operator"
165             [(match_operand:SI 1 "register_operand")
166              (match_operand:SI 2 "rx_source_operand")])
167           (label_ref (match_operand 3 ""))
168           (pc)))]
169   ""
172 (define_insn_and_split "*cbranchsi4"
173   [(set (pc)
174         (if_then_else
175           (match_operator 3 "comparison_operator"
176             [(match_operand:SI  0 "register_operand"  "r")
177              (match_operand:SI  1 "rx_source_operand" "riQ")])
178           (match_operand        2 "label_ref_operand" "")
179           (pc)))]
180   ""
181   "#"
182   "reload_completed"
183   [(const_int 0)]
185   rx_split_cbranch (CCmode, GET_CODE (operands[3]),
186                     operands[0], operands[1], operands[2]);
187   DONE;
190 (define_insn "*cmpsi"
191   [(set (reg:CC CC_REG)
192         (compare:CC (match_operand:SI 0 "register_operand"  "r,r,r,r,r,r,r")
193                     (match_operand:SI 1 "rx_source_operand" "r,Uint04,Int08,Sint16,Sint24,i,Q")))]
194   "reload_completed"
195   "cmp\t%Q1, %0"
196   [(set_attr "timings" "11,11,11,11,11,11,33")
197    (set_attr "length"  "2,2,3,4,5,6,5")]
200 ;; Canonical method for representing TST.
201 (define_insn_and_split "*cbranchsi4_tst"
202   [(set (pc)
203         (if_then_else
204           (match_operator 3 "rx_zs_comparison_operator"
205             [(and:SI (match_operand:SI  0 "register_operand"  "r")
206                      (match_operand:SI  1 "rx_source_operand" "riQ"))
207              (const_int 0)])
208           (match_operand 2 "label_ref_operand" "")
209           (pc)))]
210   ""
211   "#"
212   "reload_completed"
213   [(const_int 0)]
215   rx_split_cbranch (CC_ZSmode, GET_CODE (operands[3]),
216                     XEXP (operands[3], 0), XEXP (operands[3], 1),
217                     operands[2]);
218   DONE;
221 ;; Various other ways that GCC codes "var & const"
222 (define_insn_and_split "*cbranchsi4_tst_ext"
223   [(set (pc)
224         (if_then_else
225           (match_operator 4 "rx_z_comparison_operator"
226             [(zero_extract:SI
227                 (match_operand:SI 0 "register_operand" "r")
228                 (match_operand:SI 1 "rx_constshift_operand" "")
229                 (match_operand:SI 2 "rx_constshift_operand" ""))
230              (const_int 0)])
231           (match_operand 3 "label_ref_operand" "")
232           (pc)))]
233   ""
234   "#"
235   "reload_completed"
236   [(const_int 0)]
238   HOST_WIDE_INT mask;
239   rtx x;
241   mask = 1;
242   mask <<= INTVAL (operands[1]);
243   mask -= 1;
244   mask <<= INTVAL (operands[2]);
245   x = gen_rtx_AND (SImode, operands[0], gen_int_mode (mask, SImode));
247   rx_split_cbranch (CC_ZSmode, GET_CODE (operands[4]),
248                     x, const0_rtx, operands[3]);
249   DONE;
252 (define_insn "*tstsi"
253   [(set (reg:CC_ZS CC_REG)
254         (compare:CC_ZS
255           (and:SI (match_operand:SI 0 "register_operand"  "r,r,r")
256                   (match_operand:SI 1 "rx_source_operand" "r,i,Q"))
257           (const_int 0)))]
258   "reload_completed"
259   "tst\t%Q1, %0"
260   [(set_attr "timings" "11,11,33")
261    (set_attr "length"  "3,7,6")]
264 (define_expand "cbranchsf4"
265   [(set (pc)
266         (if_then_else
267           (match_operator 0 "rx_fp_comparison_operator"
268             [(match_operand:SF 1 "register_operand")
269              (match_operand:SF 2 "rx_source_operand")])
270           (label_ref (match_operand 3 ""))
271           (pc)))]
272   "ALLOW_RX_FPU_INSNS"
275 (define_insn_and_split "*cbranchsf4"
276   [(set (pc)
277         (if_then_else
278           (match_operator 3 "rx_fp_comparison_operator"
279             [(match_operand:SF  0 "register_operand"  "r")
280              (match_operand:SF  1 "rx_source_operand" "rFQ")])
281           (match_operand        2 "label_ref_operand" "")
282           (pc)))]
283   "ALLOW_RX_FPU_INSNS"
284   "#"
285   "&& reload_completed"
286   [(const_int 0)]
288   rx_split_cbranch (CC_Fmode, GET_CODE (operands[3]),
289                     operands[0], operands[1], operands[2]);
290   DONE;
293 (define_insn "*cmpsf"
294   [(set (reg:CC_F CC_REG)
295         (compare:CC_F
296           (match_operand:SF 0 "register_operand"  "r,r,r")
297           (match_operand:SF 1 "rx_source_operand" "r,F,Q")))]
298   "ALLOW_RX_FPU_INSNS && reload_completed"
299   "fcmp\t%1, %0"
300   [(set_attr "timings" "11,11,33")
301    (set_attr "length" "3,7,5")]
304 ;; Flow Control Instructions:
306 (define_insn "*conditional_branch"
307   [(set (pc)
308         (if_then_else
309           (match_operator 1 "comparison_operator"
310             [(reg CC_REG) (const_int 0)])
311           (label_ref (match_operand 0 "" ""))
312           (pc)))]
313   "reload_completed"
314   "b%B1\t%0"
315   [(set_attr "length" "8")    ;; This length is wrong, but it is
316                               ;; too hard to compute statically.
317    (set_attr "timings" "33")] ;; The timing assumes that the branch is taken.
320 ;; ----------------------------------------------------------------------------
322 (define_insn "jump"
323   [(set (pc)
324         (label_ref (match_operand 0 "" "")))]
325   ""
326   "bra\t%0"
327   [(set_attr "length" "4")
328    (set_attr "timings" "33")]
331 (define_insn "indirect_jump"
332   [(set (pc)
333         (match_operand:SI 0 "register_operand" "r"))]
334   ""
335   "jmp\t%0"
336   [(set_attr "length" "2")
337    (set_attr "timings" "33")]
340 (define_insn "tablejump"
341   [(set (pc)
342         (match_operand:SI          0 "register_operand" "r"))
343    (use (label_ref (match_operand  1 "" "")))]
344   ""
345   { return TARGET_PID ? (TARGET_AS100_SYNTAX ? "\n?:\tbra\t%0"
346                                              : "\n1:\tbra\t%0")
347                                              : "\n1:jmp\t%0";
348   }
349   [(set_attr "timings" "33")
350    (set_attr "length" "2")]
353 (define_expand "return"
354   [(return)]
355   "rx_can_use_simple_return ()"
356   "rx_expand_epilogue (false); DONE;"
359 (define_insn "simple_return"
360   [(simple_return)]
361   ""
362   "rts"
363   [(set_attr "length" "1")
364    (set_attr "timings" "55")]
367 ;; Unspec used so that the constant will not be invalid
368 ;; if -mmax-constant-size has been specified.
369 (define_insn "deallocate_and_return"
370   [(set (reg:SI SP_REG)
371         (plus:SI (reg:SI SP_REG)
372                  (const:SI (unspec:SI [(match_operand 0 "const_int_operand" "n")] UNSPEC_CONST))))
373    (return)]
374   ""
375   "rtsd\t%0"
376   [(set_attr "length" "2")
377    (set_attr "timings" "55")]
380 (define_insn "pop_and_return"
381   [(match_parallel 1 "rx_rtsd_vector"
382      [(set (reg:SI SP_REG)
383            (plus:SI (reg:SI SP_REG)
384                     (match_operand:SI 0 "const_int_operand" "n")))])
385    (return)]
386   "reload_completed"
387   {
388     rx_emit_stack_popm (operands, false);
389     return "";
390   }
391   [(set_attr "length" "3")
392    (set_attr "timings" "56")]
395 (define_insn "fast_interrupt_return"
396   [(unspec_volatile [(return)] UNSPEC_RTFI) ]
397   ""
398   "rtfi"
399   [(set_attr "length" "2")
400    (set_attr "timings" "33")]
403 (define_insn "exception_return"
404   [(unspec_volatile [(return)] UNSPEC_RTE) ]
405   ""
406   "rte"
407   [(set_attr "length" "2")
408    (set_attr "timings" "66")]
411 (define_insn "naked_return"
412   [(unspec_volatile [(return)] UNSPEC_NAKED) ]
413   ""
414   "; Naked function: epilogue provided by programmer."
418 ;; Note - the following set of patterns do not use the "memory_operand"
419 ;; predicate or an "m" constraint because we do not allow symbol_refs
420 ;; or label_refs as legitimate memory addresses.  This matches the
421 ;; behavior of most of the RX instructions.  Only the call/branch
422 ;; instructions are allowed to refer to symbols/labels directly.
423 ;; The call operands are in QImode because that is the value of
424 ;; FUNCTION_MODE
426 (define_expand "call"
427   [(call (match_operand:QI 0 "general_operand")
428          (match_operand:SI 1 "general_operand"))]
429   ""
430   {
431     rtx dest = XEXP (operands[0], 0);
433     if (! rx_call_operand (dest, Pmode))
434       dest = force_reg (Pmode, dest);
435     emit_call_insn (gen_call_internal (dest));
436     DONE;
437   }
440 (define_insn "call_internal"
441   [(call (mem:QI (match_operand:SI 0 "rx_call_operand" "r,CALL_OP_SYMBOL_REF"))
442          (const_int 0))
443    (clobber (reg:CC CC_REG))]
444   ""
445   "@
446   jsr\t%0
447   bsr\t%A0"
448   [(set_attr "length" "2,4")
449    (set_attr "timings" "33")]
452 (define_expand "call_value"
453   [(set (match_operand          0 "register_operand")
454         (call (match_operand:QI 1 "general_operand")
455               (match_operand:SI 2 "general_operand")))]
456   ""
457   {
458     rtx dest = XEXP (operands[1], 0);
460     if (! rx_call_operand (dest, Pmode))
461       dest = force_reg (Pmode, dest);
462     emit_call_insn (gen_call_value_internal (operands[0], dest));
463     DONE;
464   }
467 (define_insn "call_value_internal"
468   [(set (match_operand                  0 "register_operand" "=r,r")
469         (call (mem:QI (match_operand:SI 1 "rx_call_operand"   "r,CALL_OP_SYMBOL_REF"))
470               (const_int 0)))
471    (clobber (reg:CC CC_REG))]
472   ""
473   "@
474   jsr\t%1
475   bsr\t%A1"
476   [(set_attr "length" "2,4")
477    (set_attr "timings" "33")]
480 ;; Note - we do not allow indirect sibcalls (with the address
481 ;; held in a register) because we cannot guarantee that the register
482 ;; chosen will be a call-used one.  If it is a call-saved register,
483 ;; then the epilogue code will corrupt it by popping the saved value
484 ;; off of the stack.
485 (define_expand "sibcall"
486   [(parallel
487     [(call (mem:QI (match_operand:SI 0 "rx_symbolic_call_operand"))
488            (match_operand:SI         1 "general_operand"))
489      (return)])]
490   ""
491   {
492     if (MEM_P (operands[0]))
493       operands[0] = XEXP (operands[0], 0);
494     emit_call_insn (gen_sibcall_internal (operands[0]));
495     DONE;
496   }
499 (define_insn "sibcall_internal"
500   [(call (mem:QI (match_operand:SI 0 "rx_symbolic_call_operand" "Symbol"))
501          (const_int 0))
502    (return)]
503   ""
504   "bra\t%A0"
505   [(set_attr "length"  "4")
506    (set_attr "timings" "33")]
509 (define_expand "sibcall_value"
510  [(parallel
511    [(set (match_operand                  0 "register_operand")
512          (call (mem:QI (match_operand:SI 1 "rx_symbolic_call_operand"))
513                (match_operand:SI         2 "general_operand")))
514     (return)])]
515   ""
516   {
517     if (MEM_P (operands[1]))
518       operands[1] = XEXP (operands[1], 0);
519     emit_call_insn (gen_sibcall_value_internal (operands[0], operands[1]));
520     DONE;
521   }
524 (define_insn "sibcall_value_internal"
525  [(set (match_operand                  0 "register_operand"         "=r")
526        (call (mem:QI (match_operand:SI 1 "rx_symbolic_call_operand" "Symbol"))
527              (const_int 0)))
528   (return)]
529   ""
530   "bra\t%A1"
531   [(set_attr "length"  "4")
532    (set_attr "timings" "33")]
535 ;; Function Prologue/Epilogue Instructions
537 (define_expand "prologue"
538   [(const_int 0)]
539   ""
540   "rx_expand_prologue (); DONE;"
543 (define_expand "epilogue"
544   [(return)]
545   ""
546   "rx_expand_epilogue (false); DONE;"
549 (define_expand "sibcall_epilogue"
550   [(return)]
551   ""
552   "rx_expand_epilogue (true); DONE;"
555 ;; Move Instructions
557 ;; Note - we do not allow memory to memory moves, even though the ISA
558 ;; supports them.  The reason is that the conditions on such moves are
559 ;; too restrictive, specifically the source addressing mode is limited
560 ;; by the destination addressing mode and vice versa.  (For example it
561 ;; is not possible to use indexed register indirect addressing for one
562 ;; of the operands if the other operand is anything other than a register,
563 ;; but it is possible to use register relative addressing when the other
564 ;; operand also uses register relative or register indirect addressing).
566 ;; GCC does not support computing legitimate addresses based on the
567 ;; nature of other operands involved in the instruction, and reload is
568 ;; not smart enough to cope with a whole variety of different memory
569 ;; addressing constraints, so it is simpler and safer to just refuse
570 ;; to support memory to memory moves.
572 (define_expand "mov<register_modes:mode>"
573   [(set (match_operand:register_modes 0 "general_operand")
574         (match_operand:register_modes 1 "general_operand"))]
575   ""
576   {
577     if (MEM_P (operands[0]) && MEM_P (operands[1]))
578       operands[1] = copy_to_mode_reg (<register_modes:MODE>mode, operands[1]);
579     operands[0] = rx_maybe_pidify_operand (operands[0], 0);
580     operands[1] = rx_maybe_pidify_operand (operands[1], 0);
581     if (GET_CODE (operands[0]) != REG
582         && GET_CODE (operands[1]) == PLUS)
583       operands[1] = copy_to_mode_reg (<register_modes:MODE>mode, operands[1]);
584     if (GET_CODE (operands[1]) == PLUS && GET_MODE (operands[1]) == SImode)
585       {
586         emit_insn (gen_addsi3 (operands[0], XEXP (operands[1], 0), XEXP (operands[1], 1)));
587         DONE;
588       }
589     if (CONST_INT_P (operand1)
590         && ! rx_is_legitimate_constant (<register_modes:MODE>mode, operand1))
591       FAIL;
592   }
595 (define_insn "*mov<register_modes:mode>_internal"
596   [(set (match_operand:register_modes
597          0 "nonimmediate_operand" "=r,r,r,r,r,r,m,Q,Q,Q,Q,r")
598         (match_operand:register_modes
599          1 "general_operand" "Int08,Sint16,Sint24,i,r,m,r,Int08,Sint16,Sint24,i,RpdaRpid"))]
600   ""
601   { return rx_gen_move_template (operands, false); }
602   [(set_attr "length" "3,4,5,6,2,4,6,5,6,7,8,8")
603    (set_attr "timings" "11,11,11,11,11,12,11,11,11,11,11,11")]
606 (define_insn "extend<small_int_modes:mode>si2"
607   [(set (match_operand:SI 0 "register_operand"    "=r,r")
608         (sign_extend:SI (match_operand:small_int_modes
609                           1 "nonimmediate_operand" "r,m")))]
610   ""
611   { return rx_gen_move_template (operands, false); }
612   [(set_attr "length" "2,6")
613    (set_attr "timings" "11,12")]
616 (define_insn "zero_extend<small_int_modes:mode>si2"
617   [(set (match_operand:SI 0 "register_operand"     "=r,r")
618         (zero_extend:SI (match_operand:small_int_modes
619                           1 "nonimmediate_operand"  "r,m")))]
620   ""
621   { return rx_gen_move_template (operands, true); }
622   [(set_attr "length" "2,4")
623    (set_attr "timings" "11,12")]
626 (define_insn "stack_push"
627   [(set (reg:SI SP_REG)
628         (minus:SI (reg:SI SP_REG)
629                   (const_int 4)))
630    (set (mem:SI (minus:SI (reg:SI SP_REG) (const_int 4)))
631         (match_operand:SI 0 "register_operand" "r"))]
632   ""
633   "push.l\t%0"
634   [(set_attr "length" "2")]
637 (define_insn "stack_pushm"
638   [(match_parallel 1 "rx_store_multiple_vector"
639      [(set (reg:SI SP_REG)
640            (minus:SI (reg:SI SP_REG)
641                      (match_operand:SI 0 "const_int_operand" "n")))])]
642   "reload_completed"
643   {
644     rx_emit_stack_pushm (operands);
645     return "";
646   }
647   [(set_attr "length" "2")
648    (set_attr "timings" "44")] ;; The timing is a guesstimate average timing.
651 (define_insn "stack_pop"
652   [(set (match_operand:SI 0 "register_operand" "=r")
653         (mem:SI (reg:SI SP_REG)))
654    (set (reg:SI SP_REG)
655         (plus:SI (reg:SI SP_REG)
656                  (const_int 4)))]
657   ""
658   "pop\t%0"
659   [(set_attr "length" "2")
660    (set_attr "timings" "12")]
663 (define_insn "stack_popm"
664   [(match_parallel 1 "rx_load_multiple_vector"
665      [(set (reg:SI SP_REG)
666            (plus:SI (reg:SI SP_REG)
667                     (match_operand:SI 0 "const_int_operand" "n")))])]
668   "reload_completed"
669   {
670     rx_emit_stack_popm (operands, true);
671     return "";
672   }
673   [(set_attr "length" "2")
674    (set_attr "timings" "45")] ;; The timing is a guesstimate average timing.
677 (define_insn_and_split "cstoresi4"
678   [(set (match_operand:SI   0 "register_operand" "=r")
679         (match_operator:SI  1 "comparison_operator"
680           [(match_operand:SI 2 "register_operand"  "r")
681            (match_operand:SI 3 "rx_source_operand" "riQ")]))
682    (clobber (reg:CC CC_REG))]
683   ""
684   "#"
685   "reload_completed"
686   [(const_int 0)]
688   rtx flags, x;
690   flags = gen_rtx_REG (CCmode, CC_REG);
691   x = gen_rtx_COMPARE (CCmode, operands[2], operands[3]);
692   x = gen_rtx_SET (flags, x);
693   emit_insn (x);
695   x = gen_rtx_fmt_ee (GET_CODE (operands[1]), SImode, flags, const0_rtx);
696   x = gen_rtx_SET (operands[0], x);
697   emit_insn (x);
698   DONE;
701 (define_insn "*sccc"
702   [(set (match_operand:SI 0 "register_operand" "=r")
703         (match_operator:SI 1 "comparison_operator"
704           [(reg CC_REG) (const_int 0)]))]
705   "reload_completed"
706   "sc%B1.L\t%0"
707   [(set_attr "length" "3")]
710 (define_insn_and_split "cstoresf4"
711   [(set (match_operand:SI 0 "register_operand" "=r")
712         (match_operator:SI 1 "rx_fp_comparison_operator"
713          [(match_operand:SF 2 "register_operand" "r")
714           (match_operand:SF 3 "rx_source_operand" "rFQ")]))]
715   "ALLOW_RX_FPU_INSNS"
716   "#"
717   "reload_completed"
718   [(const_int 0)]
720   rtx flags, x;
722   flags = gen_rtx_REG (CC_Fmode, CC_REG);
723   x = gen_rtx_COMPARE (CC_Fmode, operands[2], operands[3]);
724   x = gen_rtx_SET (flags, x);
725   emit_insn (x);
727   x = gen_rtx_fmt_ee (GET_CODE (operands[1]), SImode, flags, const0_rtx);
728   x = gen_rtx_SET (operands[0], x);
729   emit_insn (x);
730   DONE;
733 (define_expand "movsicc"
734   [(parallel
735     [(set (match_operand:SI                  0 "register_operand")
736           (if_then_else:SI (match_operand:SI 1 "comparison_operator")
737                            (match_operand:SI 2 "nonmemory_operand")
738                            (match_operand:SI 3 "nonmemory_operand")))
739      (clobber (reg:CC CC_REG))])]
740   ""
742   /* One operand must be a constant or a register, the other must be a register.  */
743   if (   ! CONSTANT_P (operands[2])
744       && ! CONSTANT_P (operands[3])
745       && ! (REG_P (operands[2]) && REG_P (operands[3])))
746     FAIL;
749 (define_insn_and_split "*movsicc"
750   [(set (match_operand:SI     0 "register_operand" "=r,r,r")
751         (if_then_else:SI
752           (match_operator     5 "comparison_operator"
753            [(match_operand:SI 3 "register_operand"  "r,r,r")
754             (match_operand:SI 4 "rx_source_operand" "riQ,riQ,riQ")])
755           (match_operand:SI   1 "nonmemory_operand" "i,ri,r")
756           (match_operand:SI   2 "nonmemory_operand" "ri,i,r")))
757    (clobber (reg:CC CC_REG))]
758   "(CONSTANT_P (operands[1]) || CONSTANT_P (operands[2]))
759     || (REG_P (operands[1]) && REG_P (operands[2]))"
760   "#"
761   "&& reload_completed"
762   [(const_int 0)]
764   rtx x, flags, op0, op1, op2;
765   enum rtx_code cmp_code;
767   flags = gen_rtx_REG (CCmode, CC_REG);
768   x = gen_rtx_COMPARE (CCmode, operands[3], operands[4]);
769   emit_insn (gen_rtx_SET (flags, x));
771   cmp_code = GET_CODE (operands[5]);
772   op0 = operands[0];
773   op1 = operands[1];
774   op2 = operands[2];
776   /* If OP2 is the constant, reverse the sense of the move.
777      Likewise if both operands are registers but OP1 == OP0.  */
778   if ((! CONSTANT_P (operands[1]) && CONSTANT_P (operands[2]))
779       || (REG_P (operands[1]) && REG_P (operands[2])
780           && rtx_equal_p (op0, op1)))
781     {
782       x = op1, op1 = op2, op2 = x;
783       cmp_code = reverse_condition (cmp_code);
784     }
786   /* If OP2 does not match the output, copy it into place.  We have allowed
787      these alternatives so that the destination can legitimately be one of
788      the comparison operands without increasing register pressure.  */
789   if (! rtx_equal_p (op0, op2))
790     emit_move_insn (op0, op2);
792   x = gen_rtx_fmt_ee (cmp_code, VOIDmode, flags, const0_rtx);
793   x = gen_rtx_IF_THEN_ELSE (SImode, x, op1, op0);
794   emit_insn (gen_rtx_SET (op0, x));
795   DONE;
798 (define_insn "*stcc"
799   [(set (match_operand:SI 0 "register_operand" "+r,r,r,r")
800         (if_then_else:SI
801           (match_operator 2 "rx_z_comparison_operator"
802             [(reg CC_REG) (const_int 0)])
803           (match_operand:SI 1 "immediate_operand" "Sint08,Sint16,Sint24,i")
804           (match_dup 0)))]
805   "reload_completed
806    && ((GET_CODE (operands[2]) == EQ) || (GET_CODE (operands[2]) == NE))"
807   {
808     if (GET_CODE (operands[2]) == EQ)
809       return "stz\t%1, %0";
810     else
811      return "stnz\t%1, %0";
812   }
813   [(set_attr "length" "4,5,6,7")]
816 (define_insn "*stcc_reg"
817   [(set (match_operand:SI 0 "register_operand" "+r,r,r,r,r,r")
818         (if_then_else:SI
819           (match_operator 2 "comparison_operator"
820             [(reg CC_REG) (const_int 0)])
821           (match_operand:SI 1 "nonmemory_operand"
822                               "r,Uint04,Sint08,Sint16,Sint24,i")
823           (match_dup 0)))]
824   "reload_completed"
825   {
826     PUT_CODE (operands[2], reverse_condition (GET_CODE (operands[2])));
827     return "b%B2 1f\n\tmov %1, %0\n1:";
828   }
829   [(set_attr "length" "3,3,4,5,6,7")]
832 ;; Arithmetic Instructions
834 (define_insn "abssi2"
835   [(set (match_operand:SI         0 "register_operand" "=r,r")
836         (abs:SI (match_operand:SI 1 "register_operand"  "0,r")))
837    (clobber (reg:CC CC_REG))]
838   ""
839   "@
840   abs\t%0
841   abs\t%1, %0"
842   [(set_attr "length" "2,3")]
845 (define_insn "*abssi2_flags"
846   [(set (reg CC_REG)
847         (compare (abs:SI (match_operand:SI 1 "register_operand"  "0,r"))
848                  (const_int 0)))
849    (set (match_operand:SI                  0 "register_operand" "=r,r")
850         (abs:SI (match_dup 1)))]
851   ;; Note - although the ABS instruction does set the O bit in the processor
852   ;; status word, it does not do so in a way that is comparable with the CMP
853   ;; instruction.  Hence we use CC_ZSmode rather than CC_ZSOmode.
854   "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
855   "@
856   abs\t%0
857   abs\t%1, %0"
858   [(set_attr "length" "2,3")]
861 (define_expand "addsi3"
862   [(parallel [(set (match_operand:SI          0 "register_operand"  "")
863         (plus:SI (match_operand:SI 1 "register_operand"  "")
864                  (match_operand:SI 2 "rx_source_operand" "")))
865     (clobber (reg:CC CC_REG))])]
866   ""
867   "
868       operands[0] = rx_maybe_pidify_operand (operands[0], 1);
869       operands[1] = rx_maybe_pidify_operand (operands[1], 1);
870       operands[2] = rx_maybe_pidify_operand (operands[2], 1);
871   "
874 (define_insn "addsi3_internal"
875   [(set (match_operand:SI          0 "register_operand"  "=r,r,r,r,r,r,r,r,r,r,r,r,r,r")
876         (plus:SI (match_operand:SI 1 "register_operand"  "%0,0,0,0,0,0,0,r,r,r,r,r,r,0")
877                  (match_operand:SI 2 "rx_source_operand" "r,Uint04,NEGint4,Sint08,Sint16,Sint24,i,0,r,Sint08,Sint16,Sint24,i,Q")))
878    (clobber (reg:CC CC_REG))]
879   ""
880   "@
881   add\t%2, %0
882   add\t%2, %0
883   sub\t%N2, %0
884   add\t%2, %0
885   add\t%2, %0
886   add\t%2, %0
887   add\t%2, %0
888   add\t%1, %0
889   add\t%2, %1, %0
890   add\t%2, %1, %0
891   add\t%2, %1, %0
892   add\t%2, %1, %0
893   add\t%2, %1, %0
894   add\t%Q2, %0"
895   [(set_attr "timings" "11,11,11,11,11,11,11,11,11,11,11,11,11,33")
896    (set_attr "length"   "2,2,2,3,4,5,6,2,3,3,4,5,6,5")]
899 (define_insn "*addsi3_flags"
900   [(set (reg CC_REG)
901         (compare (plus:SI (match_operand:SI 1 "register_operand"  "%0,0,0,0,0,0,0,r,r,r,r,r,r,0")
902                           (match_operand:SI 2 "rx_source_operand" "r,Uint04,NEGint4,Sint08,Sint16,Sint24,i,0,r,Sint08,Sint16,Sint24,i,Q"))
903                  (const_int 0)))
904    (set (match_operand:SI                   0 "register_operand"  "=r,r,r,r,r,r,r,r,r,r,r,r,r,r")
905         (plus:SI (match_dup 1) (match_dup 2)))]
906   "reload_completed && rx_match_ccmode (insn, CC_ZSCmode)"
907   "@
908   add\t%2, %0
909   add\t%2, %0
910   sub\t%N2, %0
911   add\t%2, %0
912   add\t%2, %0
913   add\t%2, %0
914   add\t%2, %0
915   add\t%1, %0
916   add\t%2, %1, %0
917   add\t%2, %1, %0
918   add\t%2, %1, %0
919   add\t%2, %1, %0
920   add\t%2, %1, %0
921   add\t%Q2, %0"
922   [(set_attr "timings" "11,11,11,11,11,11,11,11,11,11,11,11,11,33")
923    (set_attr "length"   "2,2,2,3,4,5,6,2,3,3,4,5,6,5")]
926 ;; A helper to expand the above with the CC_MODE filled in.
927 (define_expand "addsi3_flags"
928   [(parallel [(set (reg:CC_ZSC CC_REG)
929                    (compare:CC_ZSC
930                      (plus:SI (match_operand:SI 1 "register_operand")
931                               (match_operand:SI 2 "rx_source_operand"))
932                      (const_int 0)))
933               (set (match_operand:SI 0 "register_operand")
934                    (plus:SI (match_dup 1) (match_dup 2)))])]
937 (define_insn "adc_internal"
938   [(set (match_operand:SI     0 "register_operand"  "=r,r,r,r,r,r")
939         (plus:SI
940           (plus:SI
941             (ltu:SI (reg:CC CC_REG) (const_int 0))
942             (match_operand:SI 1 "register_operand"  "%0,0,0,0,0,0"))
943           (match_operand:SI   2 "rx_source_operand" "r,Sint08,Sint16,Sint24,i,Q")))
944     (clobber (reg:CC CC_REG))]
945   "reload_completed"
946   "adc\t%2, %0"
947   [(set_attr "timings" "11,11,11,11,11,33")
948    (set_attr "length"   "3,4,5,6,7,6")]
951 (define_insn "*adc_flags"
952   [(set (reg CC_REG)
953         (compare
954           (plus:SI
955             (plus:SI
956               (ltu:SI (reg:CC CC_REG) (const_int 0))
957               (match_operand:SI 1 "register_operand"  "%0,0,0,0,0,0"))
958             (match_operand:SI   2 "rx_source_operand" "r,Sint08,Sint16,Sint24,i,Q"))
959           (const_int 0)))
960    (set (match_operand:SI       0 "register_operand"  "=r,r,r,r,r,r")
961         (plus:SI
962           (plus:SI
963             (ltu:SI (reg:CC CC_REG) (const_int 0))
964             (match_dup 1))
965           (match_dup 2)))]
966   "reload_completed && rx_match_ccmode (insn, CC_ZSCmode)"
967   "adc\t%2, %0"
968   [(set_attr "timings" "11,11,11,11,11,33")
969    (set_attr "length"   "3,4,5,6,7,6")]
972 ;; Peepholes to match:
973 ;;   (set (reg A) (reg B))
974 ;;   (set (CC) (compare:CC (reg A/reg B) (const_int 0)))
975 ;; and replace them with the addsi3_flags pattern, using an add
976 ;; of zero to copy the register and set the condition code bits.
977 (define_peephole2
978   [(set (match_operand:SI 0 "register_operand")
979         (match_operand:SI 1 "register_operand"))
980    (set (reg:CC CC_REG)
981         (compare:CC (match_dup 0)
982                     (const_int 0)))]
983   ""
984   [(parallel [(set (reg:CC_ZSC CC_REG)
985                    (compare:CC_ZSC (plus:SI (match_dup 1) (const_int 0))
986                                    (const_int 0)))
987               (set (match_dup 0)
988                    (plus:SI (match_dup 1) (const_int 0))) ])]
991 (define_peephole2
992   [(set (match_operand:SI 0 "register_operand")
993         (match_operand:SI 1 "register_operand"))
994    (set (reg:CC CC_REG)
995         (compare:CC (match_dup 1)
996                     (const_int 0)))]
997   ""
998   [(parallel [(set (reg:CC_ZSC CC_REG)
999                    (compare:CC_ZSC (plus:SI (match_dup 1) (const_int 0))
1000                                    (const_int 0)))
1001               (set (match_dup 0)
1002                    (plus:SI (match_dup 1) (const_int 0)))])]
1005 (define_expand "adddi3"
1006   [(set (match_operand:DI          0 "register_operand")
1007         (plus:DI (match_operand:DI 1 "register_operand")
1008                  (match_operand:DI 2 "rx_source_operand")))]
1009   ""
1011   rtx op0l, op0h, op1l, op1h, op2l, op2h;
1013   op0l = gen_lowpart (SImode, operands[0]);
1014   op1l = gen_lowpart (SImode, operands[1]);
1015   op2l = gen_lowpart (SImode, operands[2]);
1016   op0h = gen_highpart (SImode, operands[0]);
1017   op1h = gen_highpart (SImode, operands[1]);
1018   op2h = gen_highpart_mode (SImode, DImode, operands[2]);
1020   emit_insn (gen_adddi3_internal (op0l, op0h, op1l, op2l, op1h, op2h));
1021   DONE;
1024 (define_insn_and_split "adddi3_internal"
1025   [(set (match_operand:SI          0 "register_operand"  "=&r")
1026         (plus:SI (match_operand:SI 2 "register_operand"  "r")
1027                  (match_operand:SI 3 "rx_source_operand" "riQ")))
1028    (set (match_operand:SI          1 "register_operand"  "=r")
1029         (plus:SI
1030           (plus:SI
1031             (ltu:SI (plus:SI (match_dup 2) (match_dup 3)) (match_dup 2))
1032             (match_operand:SI      4 "register_operand"  "%1"))
1033           (match_operand:SI        5 "rx_source_operand" "riQ")))
1034    (clobber (match_scratch:SI      6                     "=&r"))
1035    (clobber (reg:CC CC_REG))]
1036   ""
1037   "#"
1038   "reload_completed"
1039   [(const_int 0)]
1041   rtx op0l = operands[0];
1042   rtx op0h = operands[1];
1043   rtx op1l = operands[2];
1044   rtx op2l = operands[3];
1045   rtx op1h = operands[4];
1046   rtx op2h = operands[5];
1047   rtx scratch = operands[6];
1048   rtx x;
1050   if (reg_overlap_mentioned_p (op0l, op1h))
1051     {
1052       emit_move_insn (scratch, op0l);
1053       op1h = scratch;
1054       if (reg_overlap_mentioned_p (op0l, op2h))
1055         op2h = scratch;
1056     }
1057   else if (reg_overlap_mentioned_p (op0l, op2h))
1058     {
1059       emit_move_insn (scratch, op0l);
1060       op2h = scratch;
1061     }
1063   if (rtx_equal_p (op0l, op1l))
1064     ;
1065   /* It is preferable that op0l == op1l...  */
1066   else if (rtx_equal_p (op0l, op2l))
1067     x = op1l, op1l = op2l, op2l = x;
1068   /* ... but it is only a requirement if op2l == MEM.  */
1069   else if (MEM_P (op2l))
1070     {
1071       /* Let's hope that we still have a scratch register free.  */
1072       gcc_assert (op1h != scratch);
1073       emit_move_insn (scratch, op2l);
1074       op2l = scratch;
1075     }
1077   emit_insn (gen_addsi3_flags (op0l, op1l, op2l));
1079   if (rtx_equal_p (op0h, op1h))
1080     ;
1081   else if (rtx_equal_p (op0h, op2h))
1082     x = op1h, op1h = op2h, op2h = x;
1083   else
1084     {
1085       emit_move_insn (op0h, op1h);
1086       op1h = op0h;
1087     }
1088   emit_insn (gen_adc_internal (op0h, op1h, op2h));
1089   DONE;
1092 (define_insn "andsi3"
1093   [(set (match_operand:SI         0 "register_operand"  "=r,r,r,r,r,r,r,r,r")
1094         (and:SI (match_operand:SI 1 "register_operand"  "%0,0,0,0,0,0,r,r,0")
1095                 (match_operand:SI 2 "rx_source_operand" "r,Uint04,Sint08,Sint16,Sint24,i,0,r,Q")))
1096    (clobber (reg:CC CC_REG))]
1097   ""
1098   "@
1099   and\t%2, %0
1100   and\t%2, %0
1101   and\t%2, %0
1102   and\t%2, %0
1103   and\t%2, %0
1104   and\t%2, %0
1105   and\t%1, %0
1106   and\t%2, %1, %0
1107   and\t%Q2, %0"
1108   [(set_attr "timings" "11,11,11,11,11,11,11,11,33")
1109    (set_attr "length" "2,2,3,4,5,6,2,5,5")]
1112 (define_insn "*andsi3_flags"
1113   [(set (reg CC_REG)
1114         (compare (and:SI (match_operand:SI 1 "register_operand"  "%0,0,0,0,0,0,r,r,0")
1115                          (match_operand:SI 2 "rx_source_operand" "r,Uint04,Sint08,Sint16,Sint24,i,0,r,Q"))
1116                  (const_int 0)))
1117    (set (match_operand:SI                  0 "register_operand"  "=r,r,r,r,r,r,r,r,r")
1118         (and:SI (match_dup 1) (match_dup 2)))]
1119   "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1120   "@
1121   and\t%2, %0
1122   and\t%2, %0
1123   and\t%2, %0
1124   and\t%2, %0
1125   and\t%2, %0
1126   and\t%2, %0
1127   and\t%1, %0
1128   and\t%2, %1, %0
1129   and\t%Q2, %0"
1130   [(set_attr "timings" "11,11,11,11,11,11,11,11,33")
1131    (set_attr "length" "2,2,3,4,5,6,2,5,5")]
1134 ;; Byte swap (single 32-bit value).
1135 (define_insn "bswapsi2"
1136   [(set (match_operand:SI           0 "register_operand" "=r")
1137         (bswap:SI (match_operand:SI 1 "register_operand"  "r")))]
1138   ""
1139   "revl\t%1, %0"
1140   [(set_attr "length" "3")]
1143 ;; Byte swap (single 16-bit value).  Note - we ignore the swapping of the high 16-bits.
1144 (define_insn "bswaphi2"
1145   [(set (match_operand:HI           0 "register_operand" "=r")
1146         (bswap:HI (match_operand:HI 1 "register_operand"  "r")))]
1147   ""
1148   "revw\t%1, %0"
1149   [(set_attr "length" "3")]
1152 (define_insn "divsi3"
1153   [(set (match_operand:SI         0 "register_operand" "=r,r,r,r,r,r")
1154         (div:SI (match_operand:SI 1 "register_operand"  "0,0,0,0,0,0")
1155                 (match_operand:SI 2 "rx_source_operand" "r,Sint08,Sint16,Sint24,i,Q")))
1156    (clobber (reg:CC CC_REG))]
1157   ""
1158   "div\t%Q2, %0"
1159   [(set_attr "timings" "1111") ;; Strictly speaking the timing should be
1160                                ;; 2222, but that is a worst case sceanario.
1161    (set_attr "length" "3,4,5,6,7,6")]
1164 (define_insn "udivsi3"
1165   [(set (match_operand:SI          0 "register_operand"  "=r,r,r,r,r,r")
1166         (udiv:SI (match_operand:SI 1 "register_operand"   "0,0,0,0,0,0")
1167                  (match_operand:SI 2 "rx_source_operand"  "r,Sint08,Sint16,Sint24,i,Q")))
1168    (clobber (reg:CC CC_REG))]
1169   ""
1170   "divu\t%Q2, %0"
1171   [(set_attr "timings" "1010") ;; Strictly speaking the timing should be
1172                                ;; 2020, but that is a worst case sceanario.
1173    (set_attr "length" "3,4,5,6,7,6")]
1176 ;; Note - these patterns are suppressed in big-endian mode because they
1177 ;; generate a little endian result.  ie the most significant word of the
1178 ;; result is placed in the higher numbered register of the destination
1179 ;; register pair.
1181 (define_insn "mulsidi3"
1182   [(set (match_operand:DI          0 "register_operand"  "=r,r,r,r,r,r")
1183         (mult:DI (sign_extend:DI (match_operand:SI
1184                                   1 "register_operand"  "%0,0,0,0,0,0"))
1185                  (sign_extend:DI (match_operand:SI
1186                                   2 "rx_source_operand"
1187                                   "r,Sint08,Sint16,Sint24,i,Q"))))]
1188   "! TARGET_BIG_ENDIAN_DATA"
1189   "emul\t%Q2, %0"
1190   [(set_attr "length" "3,4,5,6,7,6")   
1191    (set_attr "timings" "22,22,22,22,22,44")]
1194 ;; See comment for mulsidi3.
1195 ;; Note - the zero_extends are to distinguish this pattern from the
1196 ;; mulsidi3 pattern.  Immediate mode addressing is not supported
1197 ;; because gcc cannot handle the expression: (zero_extend (const_int)).
1198 (define_insn "umulsidi3"
1199   [(set (match_operand:DI                          0 "register_operand"  "=r,r")
1200         (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand"  "%0,0"))
1201                  (zero_extend:DI (match_operand:SI 2 "rx_compare_operand" "r,Q"))))]
1202   "! TARGET_BIG_ENDIAN_DATA"
1203   "emulu\t%Q2, %0"
1204   [(set_attr "length" "3,6")
1205    (set_attr "timings" "22,44")]
1208 (define_insn "smaxsi3"
1209   [(set (match_operand:SI          0 "register_operand" "=r,r,r,r,r,r")
1210         (smax: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   "max\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 "sminsi3"
1220   [(set (match_operand:SI          0 "register_operand" "=r,r,r,r,r,r")
1221         (smin:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0")
1222                  (match_operand:SI 2 "rx_source_operand"
1223                                    "r,Sint08,Sint16,Sint24,i,Q")))]
1224   ""
1225   "min\t%Q2, %0"
1226   [(set_attr "length"  "3,4,5,6,7,6")
1227    (set_attr "timings" "11,11,11,11,11,33")]
1230 (define_insn "umax<small_int_modes:mode>3_u"
1231   [(set (match_operand:SI          0 "register_operand" "=r,r,r,r,r,r")
1232         (smax:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0")
1233                  (zero_extend:SI (match_operand:small_int_modes 2 "rx_minmaxex_operand"
1234                                                                 "r,Sint08,Sint16,Sint24,i,Q"))))]
1235   ""
1236   "max\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 "umin<small_int_modes:mode>3_ur"
1242   [(set (match_operand:SI          0 "register_operand" "=r,r,r,r,r,r")
1243         (smin: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   "min\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_insn "umax<small_int_modes:mode>3_ur"
1253   [(set (match_operand:SI          0 "register_operand" "=r,r,r,r,r,r")
1254         (smax:SI (zero_extend:SI (match_operand:small_int_modes 2 "rx_minmaxex_operand"
1255                                                                 "r,Sint08,Sint16,Sint24,i,Q"))
1256                  (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0")))]
1257   ""
1258   "max\t%R2, %0"
1259   [(set_attr "length"  "3,4,5,6,7,6")
1260    (set_attr "timings" "11,11,11,11,11,33")]
1263 (define_expand "umax<small_int_modes:mode>3"
1264   [(set (match_dup 4)
1265         (zero_extend:SI (match_operand:small_int_modes 1 "register_operand" "%0,0,0,0,0,0")))
1266    (set (match_dup 3)
1267         (smax:SI (match_dup 4)
1268                  (match_operand:small_int_modes 2 "rx_source_operand"
1269                                                 "r,Sint08,Sint16,Sint24,i,Q")))
1270    (set (match_operand:small_int_modes          0 "register_operand" "=r,r,r,r,r,r")
1271         (match_dup 6))
1272    ]
1273   ""
1274   "operands[3] = gen_reg_rtx (SImode);
1275    operands[4] = gen_reg_rtx (SImode);
1276    operands[5] = gen_reg_rtx (SImode);
1277    operands[6] = gen_rtx_SUBREG (GET_MODE (operands[0]), operands[3],
1278      TARGET_BIG_ENDIAN_DATA ? (GET_MODE (operands[0]) == HImode ? 2 : 3) : 0);
1279    if (GET_CODE (operands[2]) != CONST_INT)
1280      {
1281        emit_move_insn (operands[5], gen_rtx_ZERO_EXTEND (SImode, operands[2]));
1282        operands[2] = operands[5];
1283      }
1284   "
1287 (define_expand "umin<small_int_modes:mode>3"
1288   [(set (match_dup 4)
1289         (zero_extend:SI (match_operand:small_int_modes 1 "register_operand" "%0,0,0,0,0,0")))
1290    (set (match_dup 3)
1291         (smin:SI (match_dup 4)
1292                  (match_operand:small_int_modes 2 "rx_source_operand"
1293                                                 "r,Sint08,Sint16,Sint24,i,Q")))
1294    (set (match_operand:small_int_modes          0 "register_operand" "=r,r,r,r,r,r")
1295         (match_dup 6))
1296    ]
1297   ""
1298   "operands[3] = gen_reg_rtx (SImode);
1299    operands[4] = gen_reg_rtx (SImode);
1300    operands[5] = gen_reg_rtx (SImode);
1301    operands[6] = gen_rtx_SUBREG (GET_MODE (operands[0]), operands[3],
1302      TARGET_BIG_ENDIAN_DATA ? (GET_MODE (operands[0]) == HImode ? 2 : 3) : 0);
1303    if (GET_CODE (operands[2]) != CONST_INT)
1304      {
1305        emit_move_insn (operands[5], gen_rtx_ZERO_EXTEND (SImode, operands[2]));
1306        operands[2] = operands[5];
1307      }
1308    "
1311 (define_insn "mulsi3"
1312   [(set (match_operand:SI          0 "register_operand" "=r,r,r,r,r,r,r,r,r")
1313         (mult:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0,0,r,r")
1314                  (match_operand:SI 2 "rx_source_operand"
1315                                    "r,Uint04,Sint08,Sint16,Sint24,i,Q,0,r")))]
1316   ""
1317   "@
1318   mul\t%2, %0
1319   mul\t%2, %0
1320   mul\t%2, %0
1321   mul\t%2, %0
1322   mul\t%2, %0
1323   mul\t%Q2, %0
1324   mul\t%Q2, %0
1325   mul\t%1, %0
1326   mul\t%2, %1, %0"
1327   [(set_attr "length"  "2,2,3,4,5,6,5,2,3")
1328    (set_attr "timings" "11,11,11,11,11,11,33,11,11")]
1331 (define_insn "negsi2"
1332   [(set (match_operand:SI         0 "register_operand" "=r,r")
1333         (neg:SI (match_operand:SI 1 "register_operand"  "0,r")))
1334    (clobber (reg:CC CC_REG))]
1335   ""
1336   "@
1337   neg\t%0
1338   neg\t%1, %0"
1339   [(set_attr "length" "2,3")]
1342 ;; Note that the O and C flags are not set as per a normal compare,
1343 ;; and thus are unusable in that context.
1344 (define_insn "*negsi2_flags"
1345   [(set (reg CC_REG)
1346         (compare (neg:SI (match_operand:SI 1 "register_operand"  "0,r"))
1347                  (const_int 0)))
1348    (set (match_operand:SI                  0 "register_operand" "=r,r")
1349         (neg:SI (match_dup 1)))]
1350   "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1351   "@
1352   neg\t%0
1353   neg\t%1, %0"
1354   [(set_attr "length" "2,3")]
1357 (define_insn "one_cmplsi2"
1358   [(set (match_operand:SI         0 "register_operand" "=r,r")
1359         (not:SI (match_operand:SI 1 "register_operand"  "0,r")))
1360    (clobber (reg:CC CC_REG))]
1361   ""
1362   "@
1363   not\t%0
1364   not\t%1, %0"
1365   [(set_attr "length" "2,3")]
1368 (define_insn "*one_cmplsi2_flags"
1369   [(set (reg CC_REG)
1370         (compare (not:SI (match_operand:SI 1 "register_operand"  "0,r"))
1371                  (const_int 0)))
1372    (set (match_operand:SI                  0 "register_operand" "=r,r")
1373         (not:SI (match_dup 1)))]
1374   "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1375   "@
1376   not\t%0
1377   not\t%1, %0"
1378   [(set_attr "length" "2,3")]
1381 (define_insn "iorsi3"
1382   [(set (match_operand:SI         0 "register_operand" "=r,r,r,r,r,r,r,r,r")
1383         (ior:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0,r,r,0")
1384                 (match_operand:SI 2 "rx_source_operand" "r,Uint04,Sint08,Sint16,Sint24,i,0,r,Q")))
1385    (clobber (reg:CC CC_REG))]
1386   ""
1387   "@
1388   or\t%2, %0
1389   or\t%2, %0
1390   or\t%2, %0
1391   or\t%2, %0
1392   or\t%2, %0
1393   or\t%Q2, %0
1394   or\t%1, %0
1395   or\t%2, %1, %0
1396   or\t%Q2, %0"
1397   [(set_attr "timings" "11,11,11,11,11,11,11,11,33")
1398    (set_attr "length"  "2,2,3,4,5,6,2,3,5")]
1401 (define_insn "*iorsi3_flags"
1402   [(set (reg CC_REG)
1403         (compare (ior:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0,r,r,0")
1404                          (match_operand:SI 2 "rx_source_operand" "r,Uint04,Sint08,Sint16,Sint24,i,0,r,Q"))
1405                  (const_int 0)))
1406    (set (match_operand:SI                  0 "register_operand" "=r,r,r,r,r,r,r,r,r")
1407         (ior:SI (match_dup 1) (match_dup 2)))]
1408   "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1409   "@
1410   or\t%2, %0
1411   or\t%2, %0
1412   or\t%2, %0
1413   or\t%2, %0
1414   or\t%2, %0
1415   or\t%Q2, %0
1416   or\t%1, %0
1417   or\t%2, %1, %0
1418   or\t%Q2, %0"
1419   [(set_attr "timings" "11,11,11,11,11,11,11,11,33")
1420    (set_attr "length"  "2,2,3,4,5,6,2,3,5")]
1423 (define_insn "rotlsi3"
1424   [(set (match_operand:SI            0 "register_operand" "=r")
1425         (rotate:SI (match_operand:SI 1 "register_operand"  "0")
1426                    (match_operand:SI 2 "rx_shift_operand" "rn")))
1427    (clobber (reg:CC CC_REG))]
1428   ""
1429   "rotl\t%2, %0"
1430   [(set_attr "length" "3")]
1433 (define_insn "*rotlsi3_flags"
1434   [(set (reg CC_REG)
1435         (compare (rotate:SI (match_operand:SI 1 "register_operand"  "0")
1436                             (match_operand:SI 2 "rx_shift_operand" "rn"))
1437                  (const_int 0)))
1438    (set (match_operand:SI                     0 "register_operand" "=r")
1439         (rotate:SI (match_dup 1) (match_dup 2)))]
1440   "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1441   "rotl\t%2, %0"
1442   [(set_attr "length" "3")]
1445 (define_insn "rotrsi3"
1446   [(set (match_operand:SI              0 "register_operand" "=r")
1447         (rotatert:SI (match_operand:SI 1 "register_operand"  "0")
1448                      (match_operand:SI 2 "rx_shift_operand" "rn")))
1449    (clobber (reg:CC CC_REG))]
1450   ""
1451   "rotr\t%2, %0"
1452   [(set_attr "length" "3")]
1455 (define_insn "*rotrsi3_flags"
1456   [(set (reg CC_REG)
1457         (compare (rotatert:SI (match_operand:SI 1 "register_operand"  "0")
1458                               (match_operand:SI 2 "rx_shift_operand" "rn"))
1459                  (const_int 0)))
1460    (set (match_operand:SI                       0 "register_operand" "=r")
1461         (rotatert:SI (match_dup 1) (match_dup 2)))]
1462   "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1463   "rotr\t%2, %0"
1464   [(set_attr "length" "3")]
1467 (define_insn "ashrsi3"
1468   [(set (match_operand:SI              0 "register_operand" "=r,r,r")
1469         (ashiftrt:SI (match_operand:SI 1 "register_operand"  "0,0,r")
1470                      (match_operand:SI 2 "rx_shift_operand"  "r,n,n")))
1471    (clobber (reg:CC CC_REG))]
1472   ""
1473   "@
1474   shar\t%2, %0
1475   shar\t%2, %0
1476   shar\t%2, %1, %0"
1477   [(set_attr "length" "3,2,3")]
1480 (define_insn "*ashrsi3_flags"
1481   [(set (reg CC_REG)
1482         (compare (ashiftrt:SI (match_operand:SI 1 "register_operand"  "0,0,r")
1483                               (match_operand:SI 2 "rx_shift_operand"  "r,n,n"))
1484                  (const_int 0)))
1485    (set (match_operand:SI              0 "register_operand" "=r,r,r")
1486         (ashiftrt:SI (match_dup 1) (match_dup 2)))]
1487   "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1488   "@
1489   shar\t%2, %0
1490   shar\t%2, %0
1491   shar\t%2, %1, %0"
1492   [(set_attr "length" "3,2,3")]
1495 (define_insn "lshrsi3"
1496   [(set (match_operand:SI              0 "register_operand" "=r,r,r")
1497         (lshiftrt:SI (match_operand:SI 1 "register_operand"  "0,0,r")
1498                      (match_operand:SI 2 "rx_shift_operand"  "r,n,n")))
1499    (clobber (reg:CC CC_REG))]
1500   ""
1501   "@
1502   shlr\t%2, %0
1503   shlr\t%2, %0
1504   shlr\t%2, %1, %0"
1505   [(set_attr "length" "3,2,3")]
1508 (define_insn "*lshrsi3_flags"
1509   [(set (reg CC_REG)
1510         (compare (lshiftrt:SI (match_operand:SI 1 "register_operand"  "0,0,r")
1511                               (match_operand:SI 2 "rx_shift_operand"  "r,n,n"))
1512                  (const_int 0)))
1513    (set (match_operand:SI                       0 "register_operand" "=r,r,r")
1514         (lshiftrt:SI (match_dup 1) (match_dup 2)))]
1515   "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1516   "@
1517   shlr\t%2, %0
1518   shlr\t%2, %0
1519   shlr\t%2, %1, %0"
1520   [(set_attr "length" "3,2,3")]
1523 (define_insn "ashlsi3"
1524   [(set (match_operand:SI            0 "register_operand" "=r,r,r")
1525         (ashift:SI (match_operand:SI 1 "register_operand"  "0,0,r")
1526                    (match_operand:SI 2 "rx_shift_operand"  "r,n,n")))
1527    (clobber (reg:CC CC_REG))]
1528   ""
1529   "@
1530   shll\t%2, %0
1531   shll\t%2, %0
1532   shll\t%2, %1, %0"
1533   [(set_attr "length" "3,2,3")]
1536 (define_insn "*ashlsi3_flags"
1537   [(set (reg CC_REG)
1538         (compare (ashift:SI (match_operand:SI 1 "register_operand"  "0,0,r")
1539                             (match_operand:SI 2 "rx_shift_operand"  "r,n,n"))
1540                  (const_int 0)))
1541    (set (match_operand:SI                     0 "register_operand" "=r,r,r")
1542         (ashift:SI (match_dup 1) (match_dup 2)))]
1543   "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1544   "@
1545   shll\t%2, %0
1546   shll\t%2, %0
1547   shll\t%2, %1, %0"
1548   [(set_attr "length" "3,2,3")]
1551 ;; Saturate to 32-bits
1552 (define_insn_and_split "ssaddsi3"
1553   [(set (match_operand:SI             0 "register_operand" "=r")
1554         (ss_plus:SI (match_operand:SI 1 "register_operand"  "r")
1555                     (match_operand:SI 2 "rx_source_operand" "riQ")))
1556    (clobber (reg:CC CC_REG))]
1557   ""
1558   "#"
1559   "reload_completed"
1560   [(parallel [(set (reg:CC_ZSC CC_REG)
1561                    (compare:CC_ZSC
1562                      (plus:SI (match_dup 1) (match_dup 2))
1563                      (const_int 0)))
1564               (set (match_dup 0)
1565                    (plus:SI (match_dup 1) (match_dup 2)))])
1566    (set (match_dup 0)
1567         (unspec:SI [(match_dup 0) (reg:CC CC_REG)] 
1568                    UNSPEC_BUILTIN_SAT))]
1569    ""
1572 (define_insn "*sat"
1573   [(set (match_operand:SI             0 "register_operand" "=r")
1574         (unspec:SI [(match_operand:SI 1 "register_operand"  "0")
1575                     (reg:CC CC_REG)]
1576                    UNSPEC_BUILTIN_SAT))]
1577   "reload_completed"
1578   "sat\t%0"
1579   [(set_attr "length" "2")]
1582 (define_insn "subsi3"
1583   [(set (match_operand:SI           0 "register_operand" "=r,r,r,r,r")
1584         (minus:SI (match_operand:SI 1 "register_operand"  "0,0,0,r,0")
1585                   (match_operand:SI 2 "rx_source_operand" "r,Uint04,n,r,Q")))
1586    (clobber (reg:CC CC_REG))]
1587   ""
1588   "@
1589   sub\t%2, %0
1590   sub\t%2, %0
1591   add\t%N2, %0
1592   sub\t%2, %1, %0
1593   sub\t%Q2, %0"
1594   [(set_attr "timings" "11,11,11,11,33")
1595    (set_attr "length" "2,2,6,3,5")]
1598 ;; Note that the O flag is set as if (compare op1 op2) not for
1599 ;; what is described here, (compare op0 0).
1600 (define_insn "*subsi3_flags"
1601   [(set (reg CC_REG)
1602         (compare (minus:SI (match_operand:SI 1 "register_operand"  "0,0,0,r,0")
1603                            (match_operand:SI 2 "rx_source_operand" "r,Uint04,n,r,Q"))
1604                  (const_int 0)))
1605    (set (match_operand:SI                    0 "register_operand" "=r,r,r,r,r")
1606         (minus:SI (match_dup 1) (match_dup 2)))]
1607   "reload_completed && rx_match_ccmode (insn, CC_ZSCmode)"
1608   "@
1609   sub\t%2, %0
1610   sub\t%2, %0
1611   add\t%N2, %0
1612   sub\t%2, %1, %0
1613   sub\t%Q2, %0"
1614   [(set_attr "timings" "11,11,11,11,33")
1615    (set_attr "length" "2,2,6,3,5")]
1618 ;; A helper to expand the above with the CC_MODE filled in.
1619 (define_expand "subsi3_flags"
1620   [(parallel [(set (reg:CC_ZSC CC_REG)
1621                    (compare:CC_ZSC
1622                      (minus:SI (match_operand:SI 1 "register_operand")
1623                                (match_operand:SI 2 "rx_source_operand"))
1624                      (const_int 0)))
1625               (set (match_operand:SI 0 "register_operand")
1626                    (minus:SI (match_dup 1) (match_dup 2)))])]
1629 (define_insn "sbb_internal"
1630   [(set (match_operand:SI     0 "register_operand"   "=r,r")
1631         (minus:SI
1632           (minus:SI
1633             (match_operand:SI 1 "register_operand"   " 0,0")
1634             (match_operand:SI 2 "rx_compare_operand" " r,Q"))
1635           (geu:SI (reg:CC CC_REG) (const_int 0))))
1636     (clobber (reg:CC CC_REG))]
1637   "reload_completed"
1638   "sbb\t%2, %0"
1639   [(set_attr "timings" "11,33")
1640    (set_attr "length"  "3,6")]
1643 (define_insn "*sbb_flags"
1644   [(set (reg CC_REG)
1645         (compare
1646           (minus:SI
1647             (minus:SI
1648               (match_operand:SI 1 "register_operand"   " 0,0")
1649               (match_operand:SI 2 "rx_compare_operand" " r,Q"))
1650             (geu:SI (reg:CC CC_REG) (const_int 0)))
1651           (const_int 0)))
1652    (set (match_operand:SI       0 "register_operand"   "=r,r")
1653         (minus:SI
1654           (minus:SI (match_dup 1) (match_dup 2))
1655           (geu:SI (reg:CC CC_REG) (const_int 0))))]
1656   "reload_completed"
1657   "sbb\t%2, %0"
1658   [(set_attr "timings" "11,33")
1659    (set_attr "length"  "3,6")]
1662 (define_expand "subdi3"
1663   [(set (match_operand:DI           0 "register_operand")
1664         (minus:DI (match_operand:DI 1 "register_operand")
1665                   (match_operand:DI 2 "register_operand")))]
1666   ""
1668   rtx op0l, op0h, op1l, op1h, op2l, op2h;
1670   op0l = gen_lowpart (SImode, operands[0]);
1671   op1l = gen_lowpart (SImode, operands[1]);
1672   op2l = gen_lowpart (SImode, operands[2]);
1673   op0h = gen_highpart (SImode, operands[0]);
1674   op1h = gen_highpart (SImode, operands[1]);
1675   op2h = gen_highpart_mode (SImode, DImode, operands[2]);
1677   emit_insn (gen_subdi3_internal (op0l, op0h, op1l, op2l, op1h, op2h));
1678   DONE;
1681 (define_insn_and_split "subdi3_internal"
1682   [(set (match_operand:SI          0 "register_operand"   "=&r,&r")
1683         (minus:SI (match_operand:SI 2 "register_operand"  "  0, r")
1684                   (match_operand:SI 3 "rx_compare_operand" "rQ, r")))
1685    (set (match_operand:SI          1 "register_operand"   "= r, r")
1686         (minus:SI
1687           (minus:SI
1688             (match_operand:SI      4 "register_operand"   "  1, 1")
1689             (match_operand:SI      5 "rx_compare_operand" " rQ,rQ"))
1690           (geu:SI (match_dup 2) (match_dup 3))))
1691    (clobber (reg:CC CC_REG))]
1692   ""
1693   "#"
1694   "reload_completed"
1695   [(const_int 0)]
1697   emit_insn (gen_subsi3_flags (operands[0], operands[2], operands[3]));
1698   emit_insn (gen_sbb_internal (operands[1], operands[4], operands[5]));
1699   DONE;
1702 (define_insn "xorsi3"
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    (clobber (reg:CC CC_REG))]
1708   ""
1709   "xor\t%Q2, %0"
1710   [(set_attr "timings" "11,11,11,11,11,33")
1711    (set_attr "length" "3,4,5,6,7,6")]
1714 (define_insn "*xorsi3_flags"
1715   [(set (reg CC_REG)
1716         (compare (xor:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0")
1717                          (match_operand:SI 2 "rx_source_operand"
1718                                                 "r,Sint08,Sint16,Sint24,i,Q"))
1719                  (const_int 0)))
1720    (set (match_operand:SI                  0 "register_operand" "=r,r,r,r,r,r")
1721         (xor:SI (match_dup 1) (match_dup 2)))]
1722   "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1723   "xor\t%Q2, %0"
1724   [(set_attr "timings" "11,11,11,11,11,33")
1725    (set_attr "length" "3,4,5,6,7,6")]
1728 ;; A set of peepholes to catch extending loads followed by arithmetic operations.
1729 ;; We use iterators where possible to reduce the amount of typing and hence the
1730 ;; possibilities for typos.
1732 (define_code_iterator extend_types [(zero_extend "") (sign_extend "")])
1733 (define_code_attr     letter       [(zero_extend "R") (sign_extend "Q")])
1735 (define_code_iterator memex_commutative [(plus "") (and "") (ior "") (xor "")])
1736 (define_code_iterator memex_noncomm     [(div "") (udiv "") (minus "")])
1737 (define_code_iterator memex_nocc        [(smax "") (smin "") (mult "")])
1739 (define_code_attr     op                [(plus "add") (and "and") (div "div") (udiv "divu") (smax "max") (smin "min") (mult "mul") (ior "or") (minus "sub") (xor "xor")])
1741 (define_peephole2
1742   [(set (match_operand:SI                               0 "register_operand")
1743         (extend_types:SI (match_operand:small_int_modes 1 "rx_restricted_mem_operand")))
1744    (parallel [(set (match_operand:SI                    2 "register_operand")
1745                    (memex_commutative:SI (match_dup 0)
1746                                          (match_dup 2)))
1747               (clobber (reg:CC CC_REG))])]
1748   "peep2_regno_dead_p (2, REGNO (operands[0])) && (optimize < 3 || optimize_size)"
1749   [(parallel [(set (match_dup 2)
1750                    (memex_commutative:SI (match_dup 2)
1751                                          (extend_types:SI (match_dup 1))))
1752               (clobber (reg:CC CC_REG))])]
1755 (define_peephole2
1756   [(set (match_operand:SI                               0 "register_operand")
1757         (extend_types:SI (match_operand:small_int_modes 1 "rx_restricted_mem_operand")))
1758    (parallel [(set (match_operand:SI                    2 "register_operand")
1759                    (memex_commutative:SI (match_dup 2)
1760                                          (match_dup 0)))
1761               (clobber (reg:CC CC_REG))])]
1762   "peep2_regno_dead_p (2, REGNO (operands[0])) && (optimize < 3 || optimize_size)"
1763   [(parallel [(set (match_dup 2)
1764                    (memex_commutative:SI (match_dup 2)
1765                                          (extend_types:SI (match_dup 1))))
1766               (clobber (reg:CC CC_REG))])]
1769 (define_peephole2
1770   [(set (match_operand:SI                               0 "register_operand")
1771         (extend_types:SI (match_operand:small_int_modes 1 "rx_restricted_mem_operand")))
1772    (parallel [(set (match_operand:SI                    2 "register_operand")
1773                    (memex_noncomm:SI (match_dup 2)
1774                                      (match_dup 0)))
1775               (clobber (reg:CC CC_REG))])]
1776   "peep2_regno_dead_p (2, REGNO (operands[0])) && (optimize < 3 || optimize_size)"
1777   [(parallel [(set (match_dup 2)
1778                    (memex_noncomm:SI (match_dup 2)
1779                                      (extend_types:SI (match_dup 1))))
1780               (clobber (reg:CC CC_REG))])]
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 0)
1788                        (match_dup 2)))]
1789   "peep2_regno_dead_p (2, REGNO (operands[0])) && (optimize < 3 || optimize_size)"
1790   [(set (match_dup 2)
1791         (memex_nocc:SI (match_dup 2)
1792                        (extend_types:SI (match_dup 1))))]
1795 (define_peephole2
1796   [(set (match_operand:SI                               0 "register_operand")
1797         (extend_types:SI (match_operand:small_int_modes 1 "rx_restricted_mem_operand")))
1798    (set (match_operand:SI                               2 "register_operand")
1799         (memex_nocc:SI (match_dup 2)
1800                        (match_dup 0)))]
1801   "peep2_regno_dead_p (2, REGNO (operands[0])) && (optimize < 3 || optimize_size)"
1802   [(set (match_dup 2)
1803         (memex_nocc:SI (match_dup 2)
1804                        (extend_types:SI (match_dup 1))))]
1807 (define_insn "<memex_commutative:code>si3_<extend_types:code><small_int_modes:mode>"
1808   [(set (match_operand:SI                                                     0 "register_operand" "=r")
1809         (memex_commutative:SI (match_operand:SI                               1 "register_operand" "%0")
1810                               (extend_types:SI (match_operand:small_int_modes 2 "rx_restricted_mem_operand" "Q"))))
1811    (clobber (reg:CC CC_REG))]
1812   "(optimize < 3 || optimize_size)"
1813   "<memex_commutative:op>\t%<extend_types:letter>2, %0"
1814   [(set_attr "timings" "33")
1815    (set_attr "length"  "5")] ;; This length is corrected in rx_adjust_insn_length
1818 (define_insn "<memex_noncomm:code>si3_<extend_types:code><small_int_modes:mode>"
1819   [(set (match_operand:SI                                                 0 "register_operand" "=r")
1820         (memex_noncomm:SI (match_operand:SI                               1 "register_operand" "0")
1821                           (extend_types:SI (match_operand:small_int_modes 2 "rx_restricted_mem_operand" "Q"))))
1822    (clobber (reg:CC CC_REG))]
1823   "(optimize < 3 || optimize_size)"
1824   "<memex_noncomm:op>\t%<extend_types:letter>2, %0"
1825   [(set_attr "timings" "33")
1826    (set_attr "length"  "5")] ;; This length is corrected in rx_adjust_insn_length
1829 (define_insn "<memex_nocc:code>si3_<extend_types:code><small_int_modes:mode>"
1830   [(set (match_operand:SI                                              0 "register_operand" "=r")
1831         (memex_nocc:SI (match_operand:SI                               1 "register_operand" "%0")
1832                        (extend_types:SI (match_operand:small_int_modes 2 "rx_restricted_mem_operand" "Q"))))]
1833   "(optimize < 3 || optimize_size)"
1834   "<memex_nocc:op>\t%<extend_types:letter>2, %0"
1835   [(set_attr "timings" "33")
1836    (set_attr "length"  "5")] ;; This length is corrected in rx_adjust_insn_length
1839 (define_peephole2
1840   [(set (match_operand:SI                               0 "register_operand")
1841         (extend_types:SI (match_operand:small_int_modes 1 "rx_restricted_mem_operand")))
1842    (set (reg:CC CC_REG)
1843         (compare:CC (match_operand:SI                   2 "register_operand")
1844                     (match_dup 0)))]
1845   "peep2_regno_dead_p (2, REGNO (operands[0])) && (optimize < 3 || optimize_size)"
1846   [(set (reg:CC CC_REG)
1847         (compare:CC (match_dup 2)
1848                     (extend_types:SI (match_dup 1))))]
1851 ;; Convert:
1852 ;;   (set (reg1) (sign_extend (mem))
1853 ;;   (set (reg2) (zero_extend (reg1))
1854 ;; into
1855 ;;   (set (reg2) (zero_extend (mem)))
1856 (define_peephole2
1857   [(set (match_operand:SI                              0 "register_operand")
1858         (sign_extend:SI (match_operand:small_int_modes 1 "memory_operand")))
1859    (set (match_operand:SI                              2 "register_operand")
1860         (zero_extend:SI (match_operand:small_int_modes 3 "register_operand")))]
1861   "REGNO (operands[0]) == REGNO (operands[3])
1862    && (REGNO (operands[0]) == REGNO (operands[2])
1863        || peep2_regno_dead_p (2, REGNO (operands[0])))"
1864   [(set (match_dup 2)
1865         (zero_extend:SI (match_dup 1)))]
1868 ;; Remove the redundant sign extension from:
1869 ;;   (set (reg) (extend (mem)))
1870 ;;   (set (reg) (extend (reg)))
1871 (define_peephole2
1872   [(set (match_operand:SI                               0 "register_operand")
1873         (extend_types:SI (match_operand:small_int_modes 1 "memory_operand")))
1874    (set (match_dup 0)
1875         (extend_types:SI (match_operand:small_int_modes 2 "register_operand")))]
1876   "REGNO (operands[0]) == REGNO (operands[2])"
1877   [(set (match_dup 0) (extend_types:SI (match_dup 1)))]
1880 (define_insn "comparesi3_<extend_types:code><small_int_modes:mode>"
1881   [(set (reg:CC CC_REG)
1882         (compare:CC (match_operand:SI                               0 "register_operand" "r")
1883                     (extend_types:SI (match_operand:small_int_modes 1 "rx_restricted_mem_operand" "Q"))))]
1884   "(optimize < 3 || optimize_size)"
1885   "cmp\t%<extend_types:letter>1, %0"
1886   [(set_attr "timings" "33")
1887    (set_attr "length"  "5")] ;; This length is corrected in rx_adjust_insn_length
1890 ;; Floating Point Instructions
1892 (define_insn "addsf3"
1893   [(set (match_operand:SF          0 "register_operand"  "=r,r,r")
1894         (plus:SF (match_operand:SF 1 "register_operand"  "%0,0,0")
1895                  (match_operand:SF 2 "rx_source_operand"  "r,F,Q")))
1896    (clobber (reg:CC CC_REG))]
1897   "ALLOW_RX_FPU_INSNS"
1898   "fadd\t%2, %0"
1899   [(set_attr "timings" "44,44,66")
1900    (set_attr "length" "3,7,5")]
1903 (define_insn "divsf3"
1904   [(set (match_operand:SF         0 "register_operand" "=r,r,r")
1905         (div:SF (match_operand:SF 1 "register_operand"  "0,0,0")
1906                 (match_operand:SF 2 "rx_source_operand" "r,F,Q")))
1907    (clobber (reg:CC CC_REG))]
1908   "ALLOW_RX_FPU_INSNS"
1909   "fdiv\t%2, %0"
1910   [(set_attr "timings" "1616,1616,1818")
1911    (set_attr "length" "3,7,5")]
1914 (define_insn "mulsf3"
1915   [(set (match_operand:SF          0 "register_operand" "=r,r,r")
1916         (mult:SF (match_operand:SF 1 "register_operand" "%0,0,0")
1917                 (match_operand:SF  2 "rx_source_operand" "r,F,Q")))
1918    (clobber (reg:CC CC_REG))]
1919   "ALLOW_RX_FPU_INSNS"
1920   "fmul\t%2, %0"
1921   [(set_attr "timings" "33,33,55")
1922    (set_attr "length"  "3,7,5")]
1925 (define_insn "subsf3"
1926   [(set (match_operand:SF           0 "register_operand" "=r,r,r")
1927         (minus:SF (match_operand:SF 1 "register_operand"  "0,0,0")
1928                   (match_operand:SF 2 "rx_source_operand" "r,F,Q")))
1929    (clobber (reg:CC CC_REG))]
1930   "ALLOW_RX_FPU_INSNS"
1931   "fsub\t%Q2, %0"
1932   [(set_attr "timings" "44,44,66")
1933    (set_attr "length" "3,7,5")]
1936 (define_insn "fix_truncsfsi2"
1937   [(set (match_operand:SI         0 "register_operand"  "=r,r")
1938         (fix:SI (match_operand:SF 1 "rx_compare_operand" "r,Q")))
1939    (clobber (reg:CC CC_REG))]
1940   "ALLOW_RX_FPU_INSNS"
1941   "ftoi\t%Q1, %0"
1942   [(set_attr "timings" "22,44")
1943    (set_attr "length" "3,5")]
1946 (define_insn "floatsisf2"
1947   [(set (match_operand:SF           0 "register_operand"  "=r,r")
1948         (float:SF (match_operand:SI 1 "rx_compare_operand" "r,Q")))
1949    (clobber (reg:CC CC_REG))]
1950   "ALLOW_RX_FPU_INSNS"
1951   "itof\t%Q1, %0"
1952   [(set_attr "timings" "22,44")
1953    (set_attr "length" "3,6")]
1956 ;; Bit manipulation instructions.
1958 ;; ??? The *_in_memory patterns will not be matched without further help.
1959 ;; At one time we had the insv expander generate them, but I suspect that
1960 ;; in general we get better performance by exposing the register load to
1961 ;; the optimizers.
1963 ;; An alternate solution would be to re-organize these patterns such
1964 ;; that allow both register and memory operands.  This would allow the
1965 ;; register allocator to spill and not load the register operand.  This
1966 ;; would be possible only for operations for which we have a constant
1967 ;; bit offset, so that we can adjust the address by ofs/8 and replace
1968 ;; the offset in the insn by ofs%8.
1970 (define_insn "*bitset"
1971   [(set (match_operand:SI                    0 "register_operand" "=r")
1972         (ior:SI (ashift:SI (const_int 1)
1973                            (match_operand:SI 1 "rx_shift_operand" "ri"))
1974                 (match_operand:SI            2 "register_operand" "0")))]
1975   ""
1976   "bset\t%1, %0"
1977   [(set_attr "length" "3")]
1980 (define_insn "*bitset_in_memory"
1981   [(set (match_operand:QI                    0 "rx_restricted_mem_operand" "+Q")
1982         (ior:QI (ashift:QI (const_int 1)
1983                            (match_operand:QI 1 "nonmemory_operand" "ri"))
1984                 (match_dup 0)))]
1985   ""
1986   "bset\t%1, %0.B"
1987   [(set_attr "length" "3")
1988    (set_attr "timings" "33")]
1991 (define_insn "*bitinvert"
1992   [(set (match_operand:SI 0 "register_operand" "=r")
1993         (xor:SI (ashift:SI (const_int 1)
1994                            (match_operand:SI 1 "rx_shift_operand" "ri"))
1995                 (match_operand:SI 2 "register_operand" "0")))]
1996   ""
1997   "bnot\t%1, %0"
1998   [(set_attr "length" "3")]
2001 (define_insn "*bitinvert_in_memory"
2002   [(set (match_operand:QI 0 "rx_restricted_mem_operand" "+Q")
2003         (xor:QI (ashift:QI (const_int 1)
2004                            (match_operand:QI 1 "nonmemory_operand" "ri"))
2005                 (match_dup 0)))]
2006   ""
2007   "bnot\t%1, %0.B"
2008   [(set_attr "length" "5")
2009    (set_attr "timings" "33")]
2012 (define_insn "*bitclr"
2013   [(set (match_operand:SI 0 "register_operand" "=r")
2014         (and:SI (not:SI
2015                   (ashift:SI
2016                     (const_int 1)
2017                     (match_operand:SI 1 "rx_shift_operand" "ri")))
2018                 (match_operand:SI 2 "register_operand" "0")))]
2019   ""
2020   "bclr\t%1, %0"
2021   [(set_attr "length" "3")]
2024 (define_insn "*bitclr_in_memory"
2025   [(set (match_operand:QI 0 "rx_restricted_mem_operand" "+Q")
2026         (and:QI (not:QI
2027                   (ashift:QI
2028                     (const_int 1)
2029                     (match_operand:QI 1 "nonmemory_operand" "ri")))
2030                 (match_dup 0)))]
2031   ""
2032   "bclr\t%1, %0.B"
2033   [(set_attr "length" "3")
2034    (set_attr "timings" "33")]
2037 (define_insn "*insv_imm"
2038   [(set (zero_extract:SI
2039           (match_operand:SI 0 "register_operand" "+r")
2040           (const_int 1)
2041           (match_operand:SI 1 "rx_shift_operand" "ri"))
2042         (match_operand:SI 2 "const_int_operand" ""))]
2043   ""
2045   if (INTVAL (operands[2]) & 1)
2046     return "bset\t%1, %0";
2047   else
2048     return "bclr\t%1, %0";
2050   [(set_attr "length" "3")]
2053 (define_insn_and_split "rx_insv_reg"
2054   [(set (zero_extract:SI
2055           (match_operand:SI 0 "register_operand" "+r")
2056           (const_int 1)
2057           (match_operand:SI 1 "const_int_operand" ""))
2058         (match_operand:SI 2 "register_operand" "r"))
2059    (clobber (reg:CC CC_REG))]
2060   ""
2061   "#"
2062   "reload_completed"
2063   [(set (zero_extract:SI (match_dup 0) (const_int 1) (match_dup 1))
2064         (match_dup 3))]
2066   rtx flags, x;
2068   /* Emit tst #1, op2.  */
2069   flags = gen_rtx_REG (CC_ZSmode, CC_REG);
2070   x = gen_rtx_AND (SImode, operands[2], const1_rtx);
2071   x = gen_rtx_COMPARE (CC_ZSmode, x, const0_rtx);
2072   x = gen_rtx_SET (flags, x);
2073   emit_insn (x);
2075   /* Emit bmne.  */
2076   operands[3] = gen_rtx_NE (SImode, flags, const0_rtx);
2079 (define_insn_and_split "*insv_cond"
2080   [(set (zero_extract:SI
2081           (match_operand:SI 0 "register_operand" "+r")
2082           (const_int 1)
2083           (match_operand:SI 1 "const_int_operand" ""))
2084         (match_operator:SI 4 "comparison_operator"
2085           [(match_operand:SI 2 "register_operand" "r")
2086            (match_operand:SI 3 "rx_source_operand" "riQ")]))
2087    (clobber (reg:CC CC_REG))]
2088   ""
2089   "#"
2090   "reload_completed"
2091   [(set (zero_extract:SI (match_dup 0) (const_int 1) (match_dup 1))
2092         (match_dup 4))]
2094   rtx flags, x;
2096   flags = gen_rtx_REG (CCmode, CC_REG);
2097   x = gen_rtx_COMPARE (CCmode, operands[2], operands[3]);
2098   x = gen_rtx_SET (flags, x);
2099   emit_insn (x);
2101   operands[4] = gen_rtx_fmt_ee (GET_CODE (operands[4]), SImode,
2102                                 flags, const0_rtx);
2105 (define_insn "*bmcc"
2106   [(set (zero_extract:SI
2107           (match_operand:SI 0 "register_operand" "+r")
2108           (const_int 1)
2109           (match_operand:SI 1 "const_int_operand" ""))
2110         (match_operator:SI 2 "comparison_operator"
2111           [(reg CC_REG) (const_int 0)]))]
2112   "reload_completed"
2113   "bm%B2\t%1, %0"
2114   [(set_attr "length" "3")]
2117 ;; Work around the fact that X=Y<0 is preferentially expanded as a shift.
2118 (define_insn_and_split "*insv_cond_lt"
2119   [(set (zero_extract:SI
2120           (match_operand:SI 0 "register_operand" "+r")
2121           (const_int 1)
2122           (match_operand:SI 1 "const_int_operand" ""))
2123         (match_operator:SI 3 "rshift_operator"
2124           [(match_operand:SI 2 "register_operand" "r")
2125            (const_int 31)]))
2126    (clobber (reg:CC CC_REG))]
2127   ""
2128   "#"
2129   ""
2130   [(parallel [(set (zero_extract:SI (match_dup 0) (const_int 1) (match_dup 1))
2131                    (lt:SI (match_dup 2) (const_int 0)))
2132               (clobber (reg:CC CC_REG))])]
2133   ""
2136 (define_expand "insv"
2137   [(set (zero_extract:SI
2138           (match_operand:SI 0 "register_operand")       ;; Destination
2139           (match_operand:SI 1 "const_int_operand")      ;; # of bits to set
2140           (match_operand:SI 2 "nonmemory_operand"))     ;; Starting bit
2141         (match_operand:SI   3 "nonmemory_operand"))]    ;; Bits to insert
2142   ""
2144   /* We only handle single-bit inserts.  */
2145   if (!CONST_INT_P (operands[1]) || INTVAL (operands[1]) != 1)
2146     FAIL;
2148   /* Either the bit to insert or the position must be constant.  */
2149   if (CONST_INT_P (operands[3]))
2150     operands[3] = GEN_INT (INTVAL (operands[3]) & 1);
2151   else if (CONST_INT_P (operands[2]))
2152     {
2153       emit_insn (gen_rx_insv_reg (operands[0], operands[2], operands[3]));
2154       DONE;
2155     }
2156   else
2157     FAIL;
2160 ;; Atomic operations.
2162 (define_code_iterator FETCHOP [plus minus ior xor and])
2163 (define_code_iterator FETCHOP_NO_MINUS [plus ior xor and])
2165 (define_code_attr fetchop_name
2166   [(plus "add") (minus "sub") (ior "or") (xor "xor") (and "and")])
2168 (define_code_attr fetchop_name2
2169   [(plus "add") (minus "sub") (ior "ior") (xor "xor") (and "and")])
2171 (define_mode_iterator QIHI [QI HI])
2172 (define_mode_attr BW [(QI "B") (HI "W")])
2174 (define_insn "sync_lock_test_and_setsi"
2175   [(set (match_operand:SI 0 "register_operand"   "=r,r")
2176         (match_operand:SI 1 "rx_compare_operand" "=r,Q"))
2177    (set (match_dup 1)
2178         (match_operand:SI 2 "register_operand"    "0,0"))]
2179   ""
2180   "xchg\t%1, %0"
2181   [(set_attr "length" "3,6")
2182    (set_attr "timings" "22")]
2185 (define_expand "atomic_exchange<mode>"
2186   [(match_operand:QIHI 0 "register_operand")            ;; oldval output
2187    (match_operand:QIHI 1 "rx_restricted_mem_operand")   ;; memory
2188    (match_operand:QIHI 2 "register_operand")            ;; newval input
2189    (match_operand:QIHI 3 "const_int_operand")]          ;; memory model
2190   ""
2192   emit_insn (gen_xchg_mem<mode> (operands[0], operands[1], operands[2]));
2193   DONE;
2196 (define_expand "atomic_exchangesi"
2197   [(match_operand:SI 0 "register_operand")              ;; oldval output
2198    (match_operand:SI 1 "rx_restricted_mem_operand")     ;; memory
2199    (match_operand:SI 2 "register_operand")              ;; newval input
2200    (match_operand:SI 3 "const_int_operand")]            ;; memory model
2201   ""
2203   emit_insn (gen_sync_lock_test_and_setsi (operands[0], operands[1],
2204                                            operands[2]));
2205   DONE;
2208 (define_insn "xchg_mem<mode>"
2209   [(set (match_operand:QIHI 0 "register_operand"   "=r")
2210         (match_operand:QIHI 1 "rx_compare_operand" "=Q"))
2211    (set (match_dup 1)
2212         (match_operand:QIHI 2 "register_operand"    "0"))]
2213   ""
2214   "xchg\t%1.<BW>, %0"
2215   [(set_attr "length" "6")
2216    (set_attr "timings" "22")]
2219 ;; read - modify - write - return old value
2220 (define_expand "atomic_fetch_<fetchop_name>si"
2221   [(set (match_operand:SI 0 "register_operand")
2222         (match_operand:SI 1 "memory_operand"))
2223    (set (match_dup 1)
2224         (FETCHOP:SI (match_dup 1) (match_operand:SI 2 "rx_source_operand")))
2225    (match_operand:SI 3 "const_int_operand")]            ;; memory model
2226   ""
2228   {
2229     rx_atomic_sequence seq (current_function_decl);
2231     emit_move_insn (operands[0], operands[1]);
2233     rtx tmp = gen_reg_rtx (SImode);
2234     emit_insn (gen_<fetchop_name2>si3 (tmp, operands[0], operands[2]));
2236     emit_move_insn (operands[1], tmp);
2237   }
2238   DONE;
2241 (define_expand "atomic_fetch_nandsi"
2242   [(set (match_operand:SI 0 "register_operand")
2243         (match_operand:SI 1 "memory_operand"))
2244    (set (match_dup 1)
2245         (not:SI (and:SI (match_dup 1)
2246                         (match_operand:SI 2 "rx_source_operand"))))
2247    (match_operand:SI 3 "const_int_operand")]            ;; memory model
2248   ""
2250   {
2251     rx_atomic_sequence seq (current_function_decl);
2253     emit_move_insn (operands[0], operands[1]);
2255     rtx tmp = gen_reg_rtx (SImode);
2256     emit_insn (gen_andsi3 (tmp, operands[0], operands[2]));
2257     emit_insn (gen_one_cmplsi2 (tmp, tmp));
2259     emit_move_insn (operands[1], tmp);
2260   }
2261   DONE;
2264 ;; read - modify - write - return new value
2265 ;; Because subtraction is not commutative we need to specify a different
2266 ;; set of patterns for it.
2267 (define_expand "atomic_<fetchop_name>_fetchsi"
2268   [(set (match_operand:SI 0 "register_operand")
2269         (FETCHOP_NO_MINUS:SI (match_operand:SI 1 "rx_restricted_mem_operand")
2270                              (match_operand:SI 2 "register_operand")))
2271    (set (match_dup 1)
2272         (FETCHOP_NO_MINUS:SI (match_dup 1) (match_dup 2)))
2273    (match_operand:SI 3 "const_int_operand")]            ;; memory model
2274   ""
2276   {
2277     rx_atomic_sequence seq (current_function_decl);
2279     emit_move_insn (operands[0], operands[2]);
2280     emit_insn (gen_<fetchop_name2>si3 (operands[0], operands[0], operands[1]));
2281     emit_move_insn (operands[1], operands[0]);
2282   }
2283   DONE;
2286 (define_expand "atomic_sub_fetchsi"
2287   [(set (match_operand:SI 0 "register_operand")
2288         (minus:SI (match_operand:SI 1 "rx_restricted_mem_operand")
2289                   (match_operand:SI 2 "rx_source_operand")))
2290    (set (match_dup 1)
2291         (minus:SI (match_dup 1) (match_dup 2)))
2292    (match_operand:SI 3 "const_int_operand")]            ;; memory model
2293   ""
2295   {
2296     rx_atomic_sequence seq (current_function_decl);
2298     emit_move_insn (operands[0], operands[1]);
2299     emit_insn (gen_subsi3 (operands[0], operands[0], operands[2]));
2300     emit_move_insn (operands[1], operands[0]);
2301   }
2302   DONE;
2305 (define_expand "atomic_nand_fetchsi"
2306   [(set (match_operand:SI 0 "register_operand")
2307         (not:SI (and:SI (match_operand:SI 1 "rx_restricted_mem_operand")
2308                         (match_operand:SI 2 "register_operand"))))
2309    (set (match_dup 1)
2310         (not:SI (and:SI (match_dup 1) (match_dup 2))))
2311    (match_operand:SI 3 "const_int_operand")]            ;; memory model
2312   ""
2314   {
2315     rx_atomic_sequence seq (current_function_decl);
2317     emit_move_insn (operands[0], operands[2]);
2318     emit_insn (gen_andsi3 (operands[0], operands[0], operands[1]));
2319     emit_insn (gen_one_cmplsi2 (operands[0], operands[0]));
2320     emit_move_insn (operands[1], operands[0]);
2321   }
2322   DONE;
2326 ;; Block move functions.
2328 (define_expand "movstr"
2329   [(set (match_operand:BLK 1 "memory_operand")    ;; Dest
2330         (match_operand:BLK 2 "memory_operand"))   ;; Source
2331    (use (match_operand:SI  0 "register_operand")) ;; Updated Dest
2332   ]
2333   "rx_allow_string_insns"
2334   {
2335     rtx addr1 = gen_rtx_REG (SImode, 1);
2336     rtx addr2 = gen_rtx_REG (SImode, 2);
2337     rtx len   = gen_rtx_REG (SImode, 3);
2338     rtx dest_copy = gen_reg_rtx (SImode);
2340     emit_move_insn (len, GEN_INT (-1));
2341     emit_move_insn (addr1, force_operand (XEXP (operands[1], 0), NULL_RTX));
2342     emit_move_insn (addr2, force_operand (XEXP (operands[2], 0), NULL_RTX));
2343     operands[1] = replace_equiv_address_nv (operands[1], addr1);
2344     operands[2] = replace_equiv_address_nv (operands[2], addr2);
2345     emit_move_insn (dest_copy, addr1);
2346     emit_insn (gen_rx_movstr ());
2347     emit_move_insn (len, GEN_INT (-1));
2348     emit_insn (gen_rx_strend (operands[0], dest_copy));
2349     DONE;
2350   }
2353 (define_insn "rx_movstr"
2354   [(set (mem:BLK (reg:SI 1))
2355         (mem:BLK (reg:SI 2)))
2356    (unspec_volatile:BLK [(reg:SI 1) (reg:SI 2) (reg:SI 3)] UNSPEC_MOVSTR)
2357    (clobber (reg:SI 1))
2358    (clobber (reg:SI 2))
2359    (clobber (reg:SI 3))]
2360   "rx_allow_string_insns"
2361   "smovu"
2362   [(set_attr "length" "2")
2363    (set_attr "timings" "1111")] ;; The timing is a guesstimate.
2366 (define_insn "rx_strend"
2367   [(set (match_operand:SI                      0 "register_operand" "=r")
2368         (unspec_volatile:SI [(match_operand:SI 1 "register_operand"  "r")
2369                                 (reg:SI 3)] UNSPEC_STRLEN))
2370    (clobber (reg:SI 1))
2371    (clobber (reg:SI 2))
2372    (clobber (reg:SI 3))
2373    (clobber (reg:CC CC_REG))
2374    ]
2375   "rx_allow_string_insns"
2376   "mov\t%1, r1\n\tmov\t#0, r2\n\tsuntil.b\n\tmov\tr1, %0\n\tsub\t#1, %0"
2377   [(set_attr "length" "10")
2378    (set_attr "timings" "1111")] ;; The timing is a guesstimate.
2381 (define_expand "movmemsi"
2382   [(parallel
2383     [(set (match_operand:BLK 0 "memory_operand")    ;; Dest
2384           (match_operand:BLK 1 "memory_operand"))   ;; Source
2385      (use (match_operand:SI  2 "register_operand")) ;; Length in bytes
2386      (match_operand          3 "immediate_operand") ;; Align
2387      (unspec_volatile:BLK [(reg:SI 1) (reg:SI 2) (reg:SI 3)] UNSPEC_MOVMEM)]
2388     )]
2389   "rx_allow_string_insns"
2390   {
2391     rtx addr1 = gen_rtx_REG (SImode, 1);
2392     rtx addr2 = gen_rtx_REG (SImode, 2);
2393     rtx len   = gen_rtx_REG (SImode, 3);
2395     /* Do not use when the source or destination are volatile - the SMOVF
2396        instruction will read and write in word sized blocks, which may be
2397        outside of the valid address range.  */
2398     if (MEM_P (operands[0]) && MEM_VOLATILE_P (operands[0]))
2399       FAIL;
2400     if (MEM_P (operands[1]) && MEM_VOLATILE_P (operands[1]))
2401       FAIL;
2403     if (REG_P (operands[0]) && (REGNO (operands[0]) == 2
2404                                       || REGNO (operands[0]) == 3))
2405       FAIL;
2406     if (REG_P (operands[1]) && (REGNO (operands[1]) == 1
2407                                       || REGNO (operands[1]) == 3))
2408       FAIL;
2409     if (REG_P (operands[2]) && (REGNO (operands[2]) == 1
2410                                       || REGNO (operands[2]) == 2))
2411       FAIL;
2413     emit_move_insn (addr1, force_operand (XEXP (operands[0], 0), NULL_RTX));
2414     emit_move_insn (addr2, force_operand (XEXP (operands[1], 0), NULL_RTX));
2415     emit_move_insn (len, force_operand (operands[2], NULL_RTX));
2416     operands[0] = replace_equiv_address_nv (operands[0], addr1);
2417     operands[1] = replace_equiv_address_nv (operands[1], addr2);
2418     emit_insn (gen_rx_movmem ());
2419     DONE;
2420   }
2423 (define_insn "rx_movmem"
2424   [(set (mem:BLK (reg:SI 1))
2425         (mem:BLK (reg:SI 2)))
2426    (use (reg:SI 3))
2427    (unspec_volatile:BLK [(reg:SI 1) (reg:SI 2) (reg:SI 3)] UNSPEC_MOVMEM)
2428    (clobber (reg:SI 1))
2429    (clobber (reg:SI 2))
2430    (clobber (reg:SI 3))]
2431   "rx_allow_string_insns"
2432   "smovf"
2433   [(set_attr "length" "2")
2434    (set_attr "timings" "1111")] ;; The timing is a guesstimate.
2437 (define_expand "setmemsi"
2438   [(set (match_operand:BLK 0 "memory_operand")     ;; Dest
2439         (match_operand:QI  2 "nonmemory_operand")) ;; Value
2440    (use (match_operand:SI  1 "nonmemory_operand")) ;; Length
2441    (match_operand          3 "immediate_operand")  ;; Align
2442    (unspec_volatile:BLK [(reg:SI 1) (reg:SI 2) (reg:SI 3)] UNSPEC_SETMEM)]
2443   ""
2444   {
2445     rtx addr = gen_rtx_REG (SImode, 1);
2446     rtx val  = gen_rtx_REG (QImode, 2);
2447     rtx len  = gen_rtx_REG (SImode, 3);
2449     emit_move_insn (addr, force_operand (XEXP (operands[0], 0), NULL_RTX));
2450     emit_move_insn (len, force_operand (operands[1], NULL_RTX));
2451     emit_move_insn (val, operands[2]);
2452     emit_insn (gen_rx_setmem ());
2453     DONE;
2454   }
2457 (define_insn "rx_setmem"
2458   [(set (mem:BLK (reg:SI 1))
2459         (unspec_volatile:BLK [(reg:SI 1) (reg:SI 2) (reg:SI 3)] UNSPEC_SETMEM))
2460    (clobber (reg:SI 1))
2461    (clobber (reg:SI 3))]
2462   ""
2463   "sstr.b"
2464   [(set_attr "length" "2")
2465    (set_attr "timings" "1111")] ;; The timing is a guesstimate.
2468 (define_expand "cmpstrnsi"
2469   [(set (match_operand:SI                       0 "register_operand")   ;; Result
2470         (unspec_volatile:SI [(match_operand:BLK 1 "memory_operand")     ;; String1
2471                              (match_operand:BLK 2 "memory_operand")]    ;; String2
2472                             UNSPEC_CMPSTRN))
2473    (use (match_operand:SI                       3 "register_operand"))  ;; Max Length
2474    (match_operand:SI                            4 "immediate_operand")] ;; Known Align
2475   "rx_allow_string_insns"
2476   {
2477     rtx str1 = gen_rtx_REG (SImode, 1);
2478     rtx str2 = gen_rtx_REG (SImode, 2);
2479     rtx len  = gen_rtx_REG (SImode, 3);
2480   
2481     emit_move_insn (str1, force_operand (XEXP (operands[1], 0), NULL_RTX));
2482     emit_move_insn (str2, force_operand (XEXP (operands[2], 0), NULL_RTX));
2483     emit_move_insn (len, operands[3]);
2485     emit_insn (gen_rx_cmpstrn (operands[0], operands[1], operands[2]));
2486     DONE;
2487   }
2490 (define_expand "cmpstrsi"
2491   [(set (match_operand:SI                       0 "register_operand")   ;; Result
2492         (unspec_volatile:SI [(match_operand:BLK 1 "memory_operand")     ;; String1
2493                              (match_operand:BLK 2 "memory_operand")]    ;; String2
2494                             UNSPEC_CMPSTRN))
2495    (match_operand:SI                            3 "immediate_operand")] ;; Known Align
2496   "rx_allow_string_insns"
2497   {
2498     rtx str1 = gen_rtx_REG (SImode, 1);
2499     rtx str2 = gen_rtx_REG (SImode, 2);
2500     rtx len  = gen_rtx_REG (SImode, 3);
2501   
2502     emit_move_insn (str1, force_reg (SImode, XEXP (operands[1], 0)));
2503     emit_move_insn (str2, force_reg (SImode, XEXP (operands[2], 0)));
2504     emit_move_insn (len, GEN_INT (-1));
2506     emit_insn (gen_rx_cmpstrn (operands[0], operands[1], operands[2]));
2507     DONE;
2508   }
2511 (define_insn "rx_cmpstrn"
2512   [(set (match_operand:SI 0 "register_operand" "=r")
2513         (unspec_volatile:SI [(reg:SI 1) (reg:SI 2) (reg:SI 3)]
2514                             UNSPEC_CMPSTRN))
2515    (use (match_operand:BLK 1 "memory_operand" "m"))
2516    (use (match_operand:BLK 2 "memory_operand" "m"))
2517    (clobber (reg:SI 1))
2518    (clobber (reg:SI 2))
2519    (clobber (reg:SI 3))
2520    (clobber (reg:CC CC_REG))]
2521   "rx_allow_string_insns"
2522   "scmpu                ; Perform the string comparison
2523    mov     #-1, %0      ; Set up -1 result (which cannot be created
2524                         ; by the SC insn)
2525    bnc     ?+           ; If Carry is not set skip over
2526    scne.L  %0           ; Set result based on Z flag
2527 ?:                      
2529   [(set_attr "length" "9")
2530    (set_attr "timings" "1111")] ;; The timing is a guesstimate.
2533 ;;   Builtin Functions
2535 ;; GCC does not have the ability to generate the following instructions
2536 ;; on its own so they are provided as builtins instead.  To use them from
2537 ;; a program for example invoke them as __builtin_rx_<insn_name>.  For
2538 ;; example:
2540 ;;    int short_byte_swap (int arg) { return __builtin_rx_revw (arg); }
2542 ;;---------- Accumulator Support ------------------------
2544 ;; Multiply & Accumulate (high)
2545 (define_insn "machi"
2546   [(unspec:SI [(match_operand:SI 0 "register_operand" "r")
2547                (match_operand:SI 1 "register_operand" "r")]
2548               UNSPEC_BUILTIN_MACHI)]
2549   ""
2550   "machi\t%0, %1"
2551   [(set_attr "length" "3")]
2554 ;; Multiply & Accumulate (low)
2555 (define_insn "maclo"
2556   [(unspec:SI [(match_operand:SI 0 "register_operand" "r")
2557                (match_operand:SI 1 "register_operand" "r")]
2558               UNSPEC_BUILTIN_MACLO)]
2559   ""
2560   "maclo\t%0, %1"
2561   [(set_attr "length" "3")]
2564 ;; Multiply (high)
2565 (define_insn "mulhi"
2566   [(unspec:SI [(match_operand:SI 0 "register_operand" "r")
2567                (match_operand:SI 1 "register_operand" "r")]
2568               UNSPEC_BUILTIN_MULHI)]
2569   ""
2570   "mulhi\t%0, %1"
2571   [(set_attr "length" "3")]
2574 ;; Multiply (low)
2575 (define_insn "mullo"
2576   [(unspec:SI [(match_operand:SI 0 "register_operand" "r")
2577                (match_operand:SI 1 "register_operand" "r")]
2578               UNSPEC_BUILTIN_MULLO)]
2579   ""
2580   "mullo\t%0, %1"
2581   [(set_attr "length" "3")]
2584 ;; Move from Accumulator (high)
2585 (define_insn "mvfachi"
2586   [(set (match_operand:SI 0 "register_operand" "=r")
2587         (unspec:SI [(const_int 0)]
2588                    UNSPEC_BUILTIN_MVFACHI))]
2589   ""
2590   "mvfachi\t%0"
2591   [(set_attr "length" "3")]
2594 ;; Move from Accumulator (middle)
2595 (define_insn "mvfacmi"
2596   [(set (match_operand:SI 0 "register_operand" "=r")
2597         (unspec:SI [(const_int 0)]
2598                    UNSPEC_BUILTIN_MVFACMI))]
2599   ""
2600   "mvfacmi\t%0"
2601   [(set_attr "length" "3")]
2604 ;; Move to Accumulator (high)
2605 (define_insn "mvtachi"
2606   [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")]
2607                        UNSPEC_BUILTIN_MVTACHI)]
2608   ""
2609   "mvtachi\t%0"
2610   [(set_attr "length" "3")]
2613 ;; Move to Accumulator (low)
2614 (define_insn "mvtaclo"
2615   [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")]
2616                        UNSPEC_BUILTIN_MVTACLO)]
2617   ""
2618   "mvtaclo\t%0"
2619   [(set_attr "length" "3")]
2622 ;; Round Accumulator
2623 (define_insn "racw"
2624   [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i")]
2625                        UNSPEC_BUILTIN_RACW)]
2626   ""
2627   "racw\t%0"
2628   [(set_attr "length" "3")]
2631 ;; Repeat multiply and accumulate
2632 (define_insn "rmpa"
2633   [(unspec:SI [(const_int 0) (reg:SI 1) (reg:SI 2) (reg:SI 3)
2634                (reg:SI 4) (reg:SI 5) (reg:SI 6)]
2635               UNSPEC_BUILTIN_RMPA)
2636   (clobber (reg:SI 1))
2637   (clobber (reg:SI 2))
2638   (clobber (reg:SI 3))]
2639   "rx_allow_string_insns"
2640   "rmpa"
2641   [(set_attr "length" "2")
2642    (set_attr "timings" "1010")]
2645 ;;---------- Arithmetic ------------------------
2647 ;; Byte swap (two 16-bit values).
2648 (define_insn "revw"
2649   [(set (match_operand:SI             0 "register_operand" "=r")
2650         (unspec:SI [(match_operand:SI 1 "register_operand"  "r")]
2651                    UNSPEC_BUILTIN_REVW))]
2652   ""
2653   "revw\t%1, %0"
2654   [(set_attr "length" "3")]
2657 ;; Round to integer.
2658 (define_insn "lrintsf2"
2659   [(set (match_operand:SI             0 "register_operand"  "=r,r")
2660         (unspec:SI [(match_operand:SF 1 "rx_compare_operand" "r,Q")]
2661                    UNSPEC_BUILTIN_ROUND))
2662    (clobber (reg:CC CC_REG))]
2663   ""
2664   "round\t%1, %0"
2665   [(set_attr "timings" "22,44")   
2666    (set_attr "length" "3,5")]
2669 ;;---------- Control Registers ------------------------
2671 ;; Clear Processor Status Word
2672 (define_insn "clrpsw"
2673   [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i")]
2674               UNSPEC_BUILTIN_CLRPSW)
2675    (clobber (reg:CC CC_REG))]
2676   ""
2677   "clrpsw\t%F0"
2678   [(set_attr "length" "2")]
2681 ;; Set Processor Status Word
2682 (define_insn "setpsw"
2683   [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i")]
2684               UNSPEC_BUILTIN_SETPSW)
2685    (clobber (reg:CC CC_REG))]
2686   ""
2687   "setpsw\t%F0"
2688   [(set_attr "length" "2")]
2691 ;; Move from control register
2692 (define_insn "mvfc"
2693   [(set (match_operand:SI             0 "register_operand" "=r")
2694         (unspec_volatile:SI [(match_operand:SI 1 "immediate_operand" "i")]
2695                    UNSPEC_BUILTIN_MVFC))]
2696   ""
2697   "mvfc\t%C1, %0"
2698   [(set_attr "length" "3")]
2701 ;; Move to control register
2702 ;; This insn can be used in atomic sequences to restore the previous PSW
2703 ;; and re-enable interrupts.  Because of that it always clobbers the CC_REG.
2704 (define_insn "mvtc"
2705   [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i,i")
2706                (match_operand:SI 1 "nonmemory_operand" "r,i")]
2707               UNSPEC_BUILTIN_MVTC)
2708    (clobber (reg:CC CC_REG))]
2709   ""
2710   "mvtc\t%1, %C0"
2711   [(set_attr "length" "3,7")]
2714 ;; Move to interrupt priority level
2715 (define_insn "mvtipl"
2716   [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "Uint04")]
2717               UNSPEC_BUILTIN_MVTIPL)]
2718   ""
2719   "mvtipl\t%0"
2720   [(set_attr "length" "3")]
2723 ;;---------- Interrupts ------------------------
2725 ;; Break
2726 (define_insn "brk"
2727   [(unspec_volatile [(const_int 0)]
2728                     UNSPEC_BUILTIN_BRK)]
2729   ""
2730   "brk"
2731   [(set_attr "length" "1")
2732    (set_attr "timings" "66")]
2735 ;; Interrupt
2736 (define_insn "int"
2737   [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i")]
2738                        UNSPEC_BUILTIN_INT)]
2739   ""
2740   "int\t%0"
2741   [(set_attr "length" "3")]
2744 ;; Wait
2745 (define_insn "wait"
2746   [(unspec_volatile [(const_int 0)]
2747                     UNSPEC_BUILTIN_WAIT)]
2748   ""
2749   "wait"
2750   [(set_attr "length" "2")]
2753 ;;---------- CoProcessor Support ------------------------
2755 ;; FIXME: The instructions are currently commented out because
2756 ;; the bit patterns have not been finalized, so the assembler
2757 ;; does not support them.  Once they are decided and the assembler
2758 ;; supports them, enable the instructions here.
2760 ;; Move from co-processor register
2761 (define_insn "mvfcp"
2762   [(set (match_operand:SI             0 "register_operand" "=r")
2763         (unspec:SI [(match_operand:SI 1 "immediate_operand" "i")
2764                     (match_operand:SI 2 "immediate_operand" "i")]
2765                    UNSPEC_BUILTIN_MVFCP))]
2766   ""
2767   "; mvfcp\t%1, %0, %2"
2768   [(set_attr "length" "5")]
2771 ;;---------- Misc ------------------------
2773 ;; Required by cfglayout.c...
2774 (define_insn "nop"
2775   [(const_int 0)]
2776   ""
2777   "nop"
2778   [(set_attr "length" "1")]
2781 (define_expand "pid_addr"
2782   [(plus:SI (match_operand:SI 0)
2783             (const:SI (unspec:SI [(match_operand:SI 1)] UNSPEC_PID_ADDR)))]
2784   ""
2785   ""
2788 (define_insn "movdi"
2789   [(set (match_operand:DI 0 "nonimmediate_operand" "=rm")
2790         (match_operand:DI 1 "general_operand"      "rmi"))]
2791   "TARGET_ENABLE_LRA"
2792   { return rx_gen_move_template (operands, false); }
2793   [(set_attr "length" "16")
2794    (set_attr "timings" "22")]
2797 (define_insn "movdf"
2798   [(set (match_operand:DF 0 "nonimmediate_operand" "=rm")
2799         (match_operand:DF 1 "general_operand"      "rmi"))]
2800   "TARGET_ENABLE_LRA"
2801   { return rx_gen_move_template (operands, false); }
2802   [(set_attr "length" "16")
2803    (set_attr "timings" "22")]