tree-optimization/115652 - amend last fix
[official-gcc.git] / gcc / config / rx / rx.md
blobf5857cb616e7a027b816c11a8417dc14364c83ed
1 ;;  Machine Description for Renesas RX processors
2 ;;  Copyright (C) 2008-2024 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_CPYMEM          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_PC              1)
81    (CTRLREG_USP             2)
82    (CTRLREG_FPSW            3)
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 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   /* Make sure that we have an integer comparison...  */
743   if (GET_MODE (XEXP (operands[1], 0)) != CCmode
744       && GET_MODE (XEXP (operands[1], 0)) != SImode)
745     FAIL;
747   /* One operand must be a constant or a register, the other must be a register.  */
748   if (   ! CONSTANT_P (operands[2])
749       && ! CONSTANT_P (operands[3])
750       && ! (REG_P (operands[2]) && REG_P (operands[3])))
751     FAIL;
754 (define_insn_and_split "*movsicc"
755   [(set (match_operand:SI     0 "register_operand" "=r,r,r")
756         (if_then_else:SI
757           (match_operator     5 "comparison_operator"
758            [(match_operand:SI 3 "register_operand"  "r,r,r")
759             (match_operand:SI 4 "rx_source_operand" "riQ,riQ,riQ")])
760           (match_operand:SI   1 "nonmemory_operand" "i,ri,r")
761           (match_operand:SI   2 "nonmemory_operand" "ri,i,r")))
762    (clobber (reg:CC CC_REG))]
763   "(CONSTANT_P (operands[1]) || CONSTANT_P (operands[2]))
764     || (REG_P (operands[1]) && REG_P (operands[2]))"
765   "#"
766   "&& reload_completed"
767   [(const_int 0)]
769   rtx x, flags, op0, op1, op2;
770   enum rtx_code cmp_code;
772   flags = gen_rtx_REG (CCmode, CC_REG);
773   x = gen_rtx_COMPARE (CCmode, operands[3], operands[4]);
774   emit_insn (gen_rtx_SET (flags, x));
776   cmp_code = GET_CODE (operands[5]);
777   op0 = operands[0];
778   op1 = operands[1];
779   op2 = operands[2];
781   /* If OP2 is the constant, reverse the sense of the move.
782      Likewise if both operands are registers but OP1 == OP0.  */
783   if ((! CONSTANT_P (operands[1]) && CONSTANT_P (operands[2]))
784       || (REG_P (operands[1]) && REG_P (operands[2])
785           && rtx_equal_p (op0, op1)))
786     {
787       x = op1, op1 = op2, op2 = x;
788       cmp_code = reverse_condition (cmp_code);
789     }
791   /* If OP2 does not match the output, copy it into place.  We have allowed
792      these alternatives so that the destination can legitimately be one of
793      the comparison operands without increasing register pressure.  */
794   if (! rtx_equal_p (op0, op2))
795     emit_move_insn (op0, op2);
797   x = gen_rtx_fmt_ee (cmp_code, VOIDmode, flags, const0_rtx);
798   x = gen_rtx_IF_THEN_ELSE (SImode, x, op1, op0);
799   emit_insn (gen_rtx_SET (op0, x));
800   DONE;
803 (define_insn "*stcc"
804   [(set (match_operand:SI 0 "register_operand" "+r,r,r,r")
805         (if_then_else:SI
806           (match_operator 2 "rx_z_comparison_operator"
807             [(reg CC_REG) (const_int 0)])
808           (match_operand:SI 1 "immediate_operand" "Sint08,Sint16,Sint24,i")
809           (match_dup 0)))]
810   "reload_completed
811    && ((GET_CODE (operands[2]) == EQ) || (GET_CODE (operands[2]) == NE))"
812   {
813     if (GET_CODE (operands[2]) == EQ)
814       return "stz\t%1, %0";
815     else
816      return "stnz\t%1, %0";
817   }
818   [(set_attr "length" "4,5,6,7")]
821 (define_insn "*stcc_reg"
822   [(set (match_operand:SI 0 "register_operand" "+r,r,r,r,r,r")
823         (if_then_else:SI
824           (match_operator 2 "comparison_operator"
825             [(reg CC_REG) (const_int 0)])
826           (match_operand:SI 1 "nonmemory_operand"
827                               "r,Uint04,Sint08,Sint16,Sint24,i")
828           (match_dup 0)))]
829   "reload_completed"
830   {
831     PUT_CODE (operands[2], reverse_condition (GET_CODE (operands[2])));
832     return "b%B2 1f\n\tmov %1, %0\n1:";
833   }
834   [(set_attr "length" "3,3,4,5,6,7")]
837 ;; Arithmetic Instructions
839 (define_insn "abssi2"
840   [(set (match_operand:SI         0 "register_operand" "=r,r")
841         (abs:SI (match_operand:SI 1 "register_operand"  "0,r")))
842    (clobber (reg:CC CC_REG))]
843   ""
844   "@
845   abs\t%0
846   abs\t%1, %0"
847   [(set_attr "length" "2,3")]
850 (define_insn "*abssi2_flags"
851   [(set (reg CC_REG)
852         (compare (abs:SI (match_operand:SI 1 "register_operand"  "0,r"))
853                  (const_int 0)))
854    (set (match_operand:SI                  0 "register_operand" "=r,r")
855         (abs:SI (match_dup 1)))]
856   ;; Note - although the ABS instruction does set the O bit in the processor
857   ;; status word, it does not do so in a way that is comparable with the CMP
858   ;; instruction.  Hence we use CC_ZSmode rather than CC_ZSOmode.
859   "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
860   "@
861   abs\t%0
862   abs\t%1, %0"
863   [(set_attr "length" "2,3")]
866 (define_expand "addsi3"
867   [(parallel [(set (match_operand:SI          0 "register_operand"  "")
868         (plus:SI (match_operand:SI 1 "register_operand"  "")
869                  (match_operand:SI 2 "rx_source_operand" "")))
870     (clobber (reg:CC CC_REG))])]
871   ""
872   "
873       operands[0] = rx_maybe_pidify_operand (operands[0], 1);
874       operands[1] = rx_maybe_pidify_operand (operands[1], 1);
875       operands[2] = rx_maybe_pidify_operand (operands[2], 1);
876   "
879 (define_insn "addsi3_internal"
880   [(set (match_operand:SI          0 "register_operand"  "=r,r,r,r,r,r,r,r,r,r,r,r,r,r")
881         (plus:SI (match_operand:SI 1 "register_operand"  "%0,0,0,0,0,0,0,r,r,r,r,r,r,0")
882                  (match_operand:SI 2 "rx_source_operand" "r,Uint04,NEGint4,Sint08,Sint16,Sint24,i,0,r,Sint08,Sint16,Sint24,i,Q")))
883    (clobber (reg:CC CC_REG))]
884   ""
885   "@
886   add\t%2, %0
887   add\t%2, %0
888   sub\t%N2, %0
889   add\t%2, %0
890   add\t%2, %0
891   add\t%2, %0
892   add\t%2, %0
893   add\t%1, %0
894   add\t%2, %1, %0
895   add\t%2, %1, %0
896   add\t%2, %1, %0
897   add\t%2, %1, %0
898   add\t%2, %1, %0
899   add\t%Q2, %0"
900   [(set_attr "timings" "11,11,11,11,11,11,11,11,11,11,11,11,11,33")
901    (set_attr "length"   "2,2,2,3,4,5,6,2,3,3,4,5,6,5")]
904 (define_insn "*addsi3_flags"
905   [(set (reg CC_REG)
906         (compare (plus:SI (match_operand:SI 1 "register_operand"  "%0,0,0,0,0,0,0,r,r,r,r,r,r,0")
907                           (match_operand:SI 2 "rx_source_operand" "r,Uint04,NEGint4,Sint08,Sint16,Sint24,i,0,r,Sint08,Sint16,Sint24,i,Q"))
908                  (const_int 0)))
909    (set (match_operand:SI                   0 "register_operand"  "=r,r,r,r,r,r,r,r,r,r,r,r,r,r")
910         (plus:SI (match_dup 1) (match_dup 2)))]
911   "reload_completed && rx_match_ccmode (insn, CC_ZSCmode)"
912   "@
913   add\t%2, %0
914   add\t%2, %0
915   sub\t%N2, %0
916   add\t%2, %0
917   add\t%2, %0
918   add\t%2, %0
919   add\t%2, %0
920   add\t%1, %0
921   add\t%2, %1, %0
922   add\t%2, %1, %0
923   add\t%2, %1, %0
924   add\t%2, %1, %0
925   add\t%2, %1, %0
926   add\t%Q2, %0"
927   [(set_attr "timings" "11,11,11,11,11,11,11,11,11,11,11,11,11,33")
928    (set_attr "length"   "2,2,2,3,4,5,6,2,3,3,4,5,6,5")]
931 ;; A helper to expand the above with the CC_MODE filled in.
932 (define_expand "addsi3_flags"
933   [(parallel [(set (reg:CC_ZSC CC_REG)
934                    (compare:CC_ZSC
935                      (plus:SI (match_operand:SI 1 "register_operand")
936                               (match_operand:SI 2 "rx_source_operand"))
937                      (const_int 0)))
938               (set (match_operand:SI 0 "register_operand")
939                    (plus:SI (match_dup 1) (match_dup 2)))])]
942 (define_insn "adc_internal"
943   [(set (match_operand:SI     0 "register_operand"  "=r,r,r,r,r,r")
944         (plus:SI
945           (plus:SI
946             (ltu:SI (reg:CC CC_REG) (const_int 0))
947             (match_operand:SI 1 "register_operand"  "%0,0,0,0,0,0"))
948           (match_operand:SI   2 "rx_source_operand" "r,Sint08,Sint16,Sint24,i,Q")))
949     (clobber (reg:CC CC_REG))]
950   "reload_completed"
951   "adc\t%2, %0"
952   [(set_attr "timings" "11,11,11,11,11,33")
953    (set_attr "length"   "3,4,5,6,7,6")]
956 (define_insn "*adc_flags"
957   [(set (reg CC_REG)
958         (compare
959           (plus:SI
960             (plus:SI
961               (ltu:SI (reg:CC CC_REG) (const_int 0))
962               (match_operand:SI 1 "register_operand"  "%0,0,0,0,0,0"))
963             (match_operand:SI   2 "rx_source_operand" "r,Sint08,Sint16,Sint24,i,Q"))
964           (const_int 0)))
965    (set (match_operand:SI       0 "register_operand"  "=r,r,r,r,r,r")
966         (plus:SI
967           (plus:SI
968             (ltu:SI (reg:CC CC_REG) (const_int 0))
969             (match_dup 1))
970           (match_dup 2)))]
971   "reload_completed && rx_match_ccmode (insn, CC_ZSCmode)"
972   "adc\t%2, %0"
973   [(set_attr "timings" "11,11,11,11,11,33")
974    (set_attr "length"   "3,4,5,6,7,6")]
977 ;; Peepholes to match:
978 ;;   (set (reg A) (reg B))
979 ;;   (set (CC) (compare:CC (reg A/reg B) (const_int 0)))
980 ;; and replace them with the addsi3_flags pattern, using an add
981 ;; of zero to copy the register and set the condition code bits.
982 (define_peephole2
983   [(set (match_operand:SI 0 "register_operand")
984         (match_operand:SI 1 "register_operand"))
985    (set (reg:CC CC_REG)
986         (compare:CC (match_dup 0)
987                     (const_int 0)))]
988   ""
989   [(parallel [(set (reg:CC_ZSC CC_REG)
990                    (compare:CC_ZSC (plus:SI (match_dup 1) (const_int 0))
991                                    (const_int 0)))
992               (set (match_dup 0)
993                    (plus:SI (match_dup 1) (const_int 0))) ])]
996 (define_peephole2
997   [(set (match_operand:SI 0 "register_operand")
998         (match_operand:SI 1 "register_operand"))
999    (set (reg:CC CC_REG)
1000         (compare:CC (match_dup 1)
1001                     (const_int 0)))]
1002   ""
1003   [(parallel [(set (reg:CC_ZSC CC_REG)
1004                    (compare:CC_ZSC (plus:SI (match_dup 1) (const_int 0))
1005                                    (const_int 0)))
1006               (set (match_dup 0)
1007                    (plus:SI (match_dup 1) (const_int 0)))])]
1010 (define_expand "adddi3"
1011   [(set (match_operand:DI          0 "register_operand")
1012         (plus:DI (match_operand:DI 1 "register_operand")
1013                  (match_operand:DI 2 "rx_source_operand")))]
1014   ""
1016   rtx op0l, op0h, op1l, op1h, op2l, op2h;
1018   op0l = gen_lowpart (SImode, operands[0]);
1019   op1l = gen_lowpart (SImode, operands[1]);
1020   op2l = gen_lowpart (SImode, operands[2]);
1021   op0h = gen_highpart (SImode, operands[0]);
1022   op1h = gen_highpart (SImode, operands[1]);
1023   op2h = gen_highpart_mode (SImode, DImode, operands[2]);
1025   emit_insn (gen_adddi3_internal (op0l, op0h, op1l, op2l, op1h, op2h));
1026   DONE;
1029 (define_insn_and_split "adddi3_internal"
1030   [(set (match_operand:SI          0 "register_operand"  "=&r")
1031         (plus:SI (match_operand:SI 2 "register_operand"  "r")
1032                  (match_operand:SI 3 "rx_source_operand" "riQ")))
1033    (set (match_operand:SI          1 "register_operand"  "=r")
1034         (plus:SI
1035           (plus:SI
1036             (ltu:SI (plus:SI (match_dup 2) (match_dup 3)) (match_dup 2))
1037             (match_operand:SI      4 "register_operand"  "%1"))
1038           (match_operand:SI        5 "rx_source_operand" "riQ")))
1039    (clobber (match_scratch:SI      6                     "=&r"))
1040    (clobber (reg:CC CC_REG))]
1041   ""
1042   "#"
1043   "reload_completed"
1044   [(const_int 0)]
1046   rtx op0l = operands[0];
1047   rtx op0h = operands[1];
1048   rtx op1l = operands[2];
1049   rtx op2l = operands[3];
1050   rtx op1h = operands[4];
1051   rtx op2h = operands[5];
1052   rtx scratch = operands[6];
1053   rtx x;
1055   if (reg_overlap_mentioned_p (op0l, op1h))
1056     {
1057       emit_move_insn (scratch, op0l);
1058       op1h = scratch;
1059       if (reg_overlap_mentioned_p (op0l, op2h))
1060         op2h = scratch;
1061     }
1062   else if (reg_overlap_mentioned_p (op0l, op2h))
1063     {
1064       emit_move_insn (scratch, op0l);
1065       op2h = scratch;
1066     }
1068   if (rtx_equal_p (op0l, op1l))
1069     ;
1070   /* It is preferable that op0l == op1l...  */
1071   else if (rtx_equal_p (op0l, op2l))
1072     x = op1l, op1l = op2l, op2l = x;
1073   /* ... but it is only a requirement if op2l == MEM.  */
1074   else if (MEM_P (op2l))
1075     {
1076       /* Let's hope that we still have a scratch register free.  */
1077       gcc_assert (op1h != scratch);
1078       emit_move_insn (scratch, op2l);
1079       op2l = scratch;
1080     }
1082   emit_insn (gen_addsi3_flags (op0l, op1l, op2l));
1084   if (rtx_equal_p (op0h, op1h))
1085     ;
1086   else if (rtx_equal_p (op0h, op2h))
1087     x = op1h, op1h = op2h, op2h = x;
1088   else
1089     {
1090       emit_move_insn (op0h, op1h);
1091       op1h = op0h;
1092     }
1093   emit_insn (gen_adc_internal (op0h, op1h, op2h));
1094   DONE;
1097 (define_insn_and_split "andsi3"
1098   [(set (match_operand:SI         0 "register_operand"  "=r,r,r,r,r,r,r,r,r")
1099         (and:SI (match_operand:SI 1 "register_operand"  "%0,0,0,0,0,0,r,r,0")
1100                 (match_operand:SI 2 "rx_source_operand" "r,Uint04,Sint08,Sint16,Sint24,i,0,r,Q")))
1101    (clobber (reg:CC CC_REG))]
1102   ""
1103   "@
1104   and\t%2, %0
1105   and\t%2, %0
1106   and\t%2, %0
1107   and\t%2, %0
1108   and\t%2, %0
1109   and\t%2, %0
1110   and\t%1, %0
1111   and\t%2, %1, %0
1112   and\t%Q2, %0"
1113   "&& RX_REG_P (operands[1]) && CONST_INT_P (operands[2])
1114    && pow2p_hwi (~UINTVAL (operands[2]))"
1115  [(const_int 0)]
1117   /* For negated single bit constants use the bclr insn for smaller code.  */
1119   if (!rx_reg_dead_or_unused_after_insn (curr_insn, CC_REG))
1120     FAIL;
1122   rx_copy_reg_dead_or_unused_notes (operands[1], curr_insn,
1123     emit_insn (gen_bitclr (operands[0],
1124                            GEN_INT (exact_log2 (~UINTVAL (operands[2]))),
1125                            operands[1])));
1126   DONE;
1128   [(set_attr "timings" "11,11,11,11,11,11,11,11,33")
1129    (set_attr "length" "2,2,3,4,5,6,2,5,5")]
1132 (define_insn "*andsi3_flags"
1133   [(set (reg CC_REG)
1134         (compare (and:SI (match_operand:SI 1 "register_operand"  "%0,0,0,0,0,0,r,r,0")
1135                          (match_operand:SI 2 "rx_source_operand" "r,Uint04,Sint08,Sint16,Sint24,i,0,r,Q"))
1136                  (const_int 0)))
1137    (set (match_operand:SI                  0 "register_operand"  "=r,r,r,r,r,r,r,r,r")
1138         (and:SI (match_dup 1) (match_dup 2)))]
1139   "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1140   "@
1141   and\t%2, %0
1142   and\t%2, %0
1143   and\t%2, %0
1144   and\t%2, %0
1145   and\t%2, %0
1146   and\t%2, %0
1147   and\t%1, %0
1148   and\t%2, %1, %0
1149   and\t%Q2, %0"
1150   [(set_attr "timings" "11,11,11,11,11,11,11,11,33")
1151    (set_attr "length" "2,2,3,4,5,6,2,5,5")]
1154 ;; Byte swap (single 32-bit value).
1155 (define_insn "bswapsi2"
1156   [(set (match_operand:SI           0 "register_operand" "=r")
1157         (bswap:SI (match_operand:SI 1 "register_operand"  "r")))]
1158   ""
1159   "revl\t%1, %0"
1160   [(set_attr "length" "3")]
1163 ;; Byte swap (single 16-bit value).  Note - we ignore the swapping of the high 16-bits.
1164 (define_insn "bswaphi2"
1165   [(set (match_operand:HI           0 "register_operand" "=r")
1166         (bswap:HI (match_operand:HI 1 "register_operand"  "r")))]
1167   ""
1168   "revw\t%1, %0"
1169   [(set_attr "length" "3")]
1172 (define_insn "divsi3"
1173   [(set (match_operand:SI         0 "register_operand" "=r,r,r,r,r,r")
1174         (div:SI (match_operand:SI 1 "register_operand"  "0,0,0,0,0,0")
1175                 (match_operand:SI 2 "rx_source_operand" "r,Sint08,Sint16,Sint24,i,Q")))
1176    (clobber (reg:CC CC_REG))]
1177   ""
1178   "div\t%Q2, %0"
1179   [(set_attr "timings" "1111") ;; Strictly speaking the timing should be
1180                                ;; 2222, but that is a worst case sceanario.
1181    (set_attr "length" "3,4,5,6,7,6")]
1184 (define_insn "udivsi3"
1185   [(set (match_operand:SI          0 "register_operand"  "=r,r,r,r,r,r")
1186         (udiv:SI (match_operand:SI 1 "register_operand"   "0,0,0,0,0,0")
1187                  (match_operand:SI 2 "rx_source_operand"  "r,Sint08,Sint16,Sint24,i,Q")))
1188    (clobber (reg:CC CC_REG))]
1189   ""
1190   "divu\t%Q2, %0"
1191   [(set_attr "timings" "1010") ;; Strictly speaking the timing should be
1192                                ;; 2020, but that is a worst case sceanario.
1193    (set_attr "length" "3,4,5,6,7,6")]
1196 ;; Note - these patterns are suppressed in big-endian mode because they
1197 ;; generate a little endian result.  ie the most significant word of the
1198 ;; result is placed in the higher numbered register of the destination
1199 ;; register pair.
1201 (define_insn "mulsidi3"
1202   [(set (match_operand:DI          0 "register_operand"  "=r,r,r,r,r,r")
1203         (mult:DI (sign_extend:DI (match_operand:SI
1204                                   1 "register_operand"  "%0,0,0,0,0,0"))
1205                  (sign_extend:DI (match_operand:SI
1206                                   2 "rx_source_operand"
1207                                   "r,Sint08,Sint16,Sint24,i,Q"))))]
1208   "! TARGET_BIG_ENDIAN_DATA"
1209   "emul\t%Q2, %0"
1210   [(set_attr "length" "3,4,5,6,7,6")   
1211    (set_attr "timings" "22,22,22,22,22,44")]
1214 ;; See comment for mulsidi3.
1215 ;; Note - the zero_extends are to distinguish this pattern from the
1216 ;; mulsidi3 pattern.  Immediate mode addressing is not supported
1217 ;; because gcc cannot handle the expression: (zero_extend (const_int)).
1218 (define_insn "umulsidi3"
1219   [(set (match_operand:DI                          0 "register_operand"  "=r,r")
1220         (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand"  "%0,0"))
1221                  (zero_extend:DI (match_operand:SI 2 "rx_compare_operand" "r,Q"))))]
1222   "! TARGET_BIG_ENDIAN_DATA"
1223   "emulu\t%Q2, %0"
1224   [(set_attr "length" "3,6")
1225    (set_attr "timings" "22,44")]
1228 (define_insn "smaxsi3"
1229   [(set (match_operand:SI          0 "register_operand" "=r,r,r,r,r,r")
1230         (smax:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0")
1231                  (match_operand:SI 2 "rx_source_operand"
1232                                    "r,Sint08,Sint16,Sint24,i,Q")))]
1233   ""
1234   "max\t%Q2, %0"
1235   [(set_attr "length" "3,4,5,6,7,6")
1236    (set_attr "timings" "11,11,11,11,11,33")]
1239 (define_insn "sminsi3"
1240   [(set (match_operand:SI          0 "register_operand" "=r,r,r,r,r,r")
1241         (smin:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0")
1242                  (match_operand:SI 2 "rx_source_operand"
1243                                    "r,Sint08,Sint16,Sint24,i,Q")))]
1244   ""
1245   "min\t%Q2, %0"
1246   [(set_attr "length"  "3,4,5,6,7,6")
1247    (set_attr "timings" "11,11,11,11,11,33")]
1250 (define_insn "umax<small_int_modes:mode>3_u"
1251   [(set (match_operand:SI          0 "register_operand" "=r,r,r,r,r,r")
1252         (smax:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0")
1253                  (zero_extend:SI (match_operand:small_int_modes 2 "rx_minmaxex_operand"
1254                                                                 "r,Sint08,Sint16,Sint24,i,Q"))))]
1255   ""
1256   "max\t%R2, %0"
1257   [(set_attr "length"  "3,4,5,6,7,6")
1258    (set_attr "timings" "11,11,11,11,11,33")]
1261 (define_insn "umin<small_int_modes:mode>3_ur"
1262   [(set (match_operand:SI          0 "register_operand" "=r,r,r,r,r,r")
1263         (smin:SI (zero_extend:SI (match_operand:small_int_modes 2 "rx_minmaxex_operand"
1264                                                                 "r,Sint08,Sint16,Sint24,i,Q"))
1265                  (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0")))]
1266   ""
1267   "min\t%R2, %0"
1268   [(set_attr "length"  "3,4,5,6,7,6")
1269    (set_attr "timings" "11,11,11,11,11,33")]
1272 (define_insn "umax<small_int_modes:mode>3_ur"
1273   [(set (match_operand:SI          0 "register_operand" "=r,r,r,r,r,r")
1274         (smax:SI (zero_extend:SI (match_operand:small_int_modes 2 "rx_minmaxex_operand"
1275                                                                 "r,Sint08,Sint16,Sint24,i,Q"))
1276                  (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0")))]
1277   ""
1278   "max\t%R2, %0"
1279   [(set_attr "length"  "3,4,5,6,7,6")
1280    (set_attr "timings" "11,11,11,11,11,33")]
1283 (define_expand "umax<small_int_modes:mode>3"
1284   [(set (match_dup 4)
1285         (zero_extend:SI (match_operand:small_int_modes 1 "register_operand" "%0,0,0,0,0,0")))
1286    (set (match_dup 3)
1287         (smax:SI (match_dup 4)
1288                  (match_operand:small_int_modes 2 "rx_source_operand"
1289                                                 "r,Sint08,Sint16,Sint24,i,Q")))
1290    (set (match_operand:small_int_modes          0 "register_operand" "=r,r,r,r,r,r")
1291         (match_dup 6))
1292    ]
1293   ""
1294   "operands[3] = gen_reg_rtx (SImode);
1295    operands[4] = gen_reg_rtx (SImode);
1296    operands[5] = gen_reg_rtx (SImode);
1297    operands[6] = gen_rtx_SUBREG (GET_MODE (operands[0]), operands[3],
1298      TARGET_BIG_ENDIAN_DATA ? (GET_MODE (operands[0]) == HImode ? 2 : 3) : 0);
1299    if (GET_CODE (operands[2]) != CONST_INT)
1300      {
1301        emit_move_insn (operands[5], gen_rtx_ZERO_EXTEND (SImode, operands[2]));
1302        operands[2] = operands[5];
1303      }
1304   "
1307 (define_expand "umin<small_int_modes:mode>3"
1308   [(set (match_dup 4)
1309         (zero_extend:SI (match_operand:small_int_modes 1 "register_operand" "%0,0,0,0,0,0")))
1310    (set (match_dup 3)
1311         (smin:SI (match_dup 4)
1312                  (match_operand:small_int_modes 2 "rx_source_operand"
1313                                                 "r,Sint08,Sint16,Sint24,i,Q")))
1314    (set (match_operand:small_int_modes          0 "register_operand" "=r,r,r,r,r,r")
1315         (match_dup 6))
1316    ]
1317   ""
1318   "operands[3] = gen_reg_rtx (SImode);
1319    operands[4] = gen_reg_rtx (SImode);
1320    operands[5] = gen_reg_rtx (SImode);
1321    operands[6] = gen_rtx_SUBREG (GET_MODE (operands[0]), operands[3],
1322      TARGET_BIG_ENDIAN_DATA ? (GET_MODE (operands[0]) == HImode ? 2 : 3) : 0);
1323    if (GET_CODE (operands[2]) != CONST_INT)
1324      {
1325        emit_move_insn (operands[5], gen_rtx_ZERO_EXTEND (SImode, operands[2]));
1326        operands[2] = operands[5];
1327      }
1328    "
1331 (define_insn "mulsi3"
1332   [(set (match_operand:SI          0 "register_operand" "=r,r,r,r,r,r,r,r,r")
1333         (mult:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0,0,r,r")
1334                  (match_operand:SI 2 "rx_source_operand"
1335                                    "r,Uint04,Sint08,Sint16,Sint24,i,Q,0,r")))]
1336   ""
1337   "@
1338   mul\t%2, %0
1339   mul\t%2, %0
1340   mul\t%2, %0
1341   mul\t%2, %0
1342   mul\t%2, %0
1343   mul\t%Q2, %0
1344   mul\t%Q2, %0
1345   mul\t%1, %0
1346   mul\t%2, %1, %0"
1347   [(set_attr "length"  "2,2,3,4,5,6,5,2,3")
1348    (set_attr "timings" "11,11,11,11,11,11,33,11,11")]
1351 (define_insn "negsi2"
1352   [(set (match_operand:SI         0 "register_operand" "=r,r")
1353         (neg:SI (match_operand:SI 1 "register_operand"  "0,r")))
1354    (clobber (reg:CC CC_REG))]
1355   ""
1356   "@
1357   neg\t%0
1358   neg\t%1, %0"
1359   [(set_attr "length" "2,3")]
1362 ;; Note that the O and C flags are not set as per a normal compare,
1363 ;; and thus are unusable in that context.
1364 (define_insn "*negsi2_flags"
1365   [(set (reg CC_REG)
1366         (compare (neg:SI (match_operand:SI 1 "register_operand"  "0,r"))
1367                  (const_int 0)))
1368    (set (match_operand:SI                  0 "register_operand" "=r,r")
1369         (neg:SI (match_dup 1)))]
1370   "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1371   "@
1372   neg\t%0
1373   neg\t%1, %0"
1374   [(set_attr "length" "2,3")]
1377 (define_insn "one_cmplsi2"
1378   [(set (match_operand:SI         0 "register_operand" "=r,r")
1379         (not:SI (match_operand:SI 1 "register_operand"  "0,r")))
1380    (clobber (reg:CC CC_REG))]
1381   ""
1382   "@
1383   not\t%0
1384   not\t%1, %0"
1385   [(set_attr "length" "2,3")]
1388 (define_insn "*one_cmplsi2_flags"
1389   [(set (reg CC_REG)
1390         (compare (not:SI (match_operand:SI 1 "register_operand"  "0,r"))
1391                  (const_int 0)))
1392    (set (match_operand:SI                  0 "register_operand" "=r,r")
1393         (not:SI (match_dup 1)))]
1394   "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1395   "@
1396   not\t%0
1397   not\t%1, %0"
1398   [(set_attr "length" "2,3")]
1401 (define_insn_and_split "iorsi3"
1402   [(set (match_operand:SI         0 "register_operand" "=r,r,r,r,r,r,r,r,r")
1403         (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    (clobber (reg:CC CC_REG))]
1406   ""
1407   "@
1408   or\t%2, %0
1409   or\t%2, %0
1410   or\t%2, %0
1411   or\t%2, %0
1412   or\t%2, %0
1413   or\t%Q2, %0
1414   or\t%1, %0
1415   or\t%2, %1, %0
1416   or\t%Q2, %0"
1417   "&& RX_REG_P (operands[1]) && CONST_INT_P (operands[2])
1418    && pow2p_hwi (UINTVAL (operands[2]))"
1419   [(const_int 0)]
1421   /* For single bit constants use the bset insn for smaller code.  */
1423   if (!rx_reg_dead_or_unused_after_insn (curr_insn, CC_REG))
1424     FAIL;
1426   rx_copy_reg_dead_or_unused_notes (operands[1], curr_insn,
1427     emit_insn (gen_bitset (operands[0],
1428                            GEN_INT (exact_log2 (UINTVAL (operands[2]))),
1429                            operands[1])));
1430   DONE;
1432   [(set_attr "timings" "11,11,11,11,11,11,11,11,33")
1433    (set_attr "length"  "2,2,3,4,5,6,2,3,5")]
1436 (define_insn "*iorsi3_flags"
1437   [(set (reg CC_REG)
1438         (compare (ior:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0,r,r,0")
1439                          (match_operand:SI 2 "rx_source_operand" "r,Uint04,Sint08,Sint16,Sint24,i,0,r,Q"))
1440                  (const_int 0)))
1441    (set (match_operand:SI                  0 "register_operand" "=r,r,r,r,r,r,r,r,r")
1442         (ior:SI (match_dup 1) (match_dup 2)))]
1443   "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1444   "@
1445   or\t%2, %0
1446   or\t%2, %0
1447   or\t%2, %0
1448   or\t%2, %0
1449   or\t%2, %0
1450   or\t%Q2, %0
1451   or\t%1, %0
1452   or\t%2, %1, %0
1453   or\t%Q2, %0"
1454   [(set_attr "timings" "11,11,11,11,11,11,11,11,33")
1455    (set_attr "length"  "2,2,3,4,5,6,2,3,5")]
1458 (define_insn "rotlsi3"
1459   [(set (match_operand:SI            0 "register_operand" "=r")
1460         (rotate:SI (match_operand:SI 1 "register_operand"  "0")
1461                    (match_operand:SI 2 "rx_shift_operand" "rn")))
1462    (clobber (reg:CC CC_REG))]
1463   ""
1464   "rotl\t%2, %0"
1465   [(set_attr "length" "3")]
1468 (define_insn "*rotlsi3_flags"
1469   [(set (reg CC_REG)
1470         (compare (rotate:SI (match_operand:SI 1 "register_operand"  "0")
1471                             (match_operand:SI 2 "rx_shift_operand" "rn"))
1472                  (const_int 0)))
1473    (set (match_operand:SI                     0 "register_operand" "=r")
1474         (rotate:SI (match_dup 1) (match_dup 2)))]
1475   "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1476   "rotl\t%2, %0"
1477   [(set_attr "length" "3")]
1480 (define_insn "rotrsi3"
1481   [(set (match_operand:SI              0 "register_operand" "=r")
1482         (rotatert:SI (match_operand:SI 1 "register_operand"  "0")
1483                      (match_operand:SI 2 "rx_shift_operand" "rn")))
1484    (clobber (reg:CC CC_REG))]
1485   ""
1486   "rotr\t%2, %0"
1487   [(set_attr "length" "3")]
1490 (define_insn "*rotrsi3_flags"
1491   [(set (reg CC_REG)
1492         (compare (rotatert:SI (match_operand:SI 1 "register_operand"  "0")
1493                               (match_operand:SI 2 "rx_shift_operand" "rn"))
1494                  (const_int 0)))
1495    (set (match_operand:SI                       0 "register_operand" "=r")
1496         (rotatert:SI (match_dup 1) (match_dup 2)))]
1497   "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1498   "rotr\t%2, %0"
1499   [(set_attr "length" "3")]
1502 (define_insn "ashrsi3"
1503   [(set (match_operand:SI              0 "register_operand" "=r,r,r")
1504         (ashiftrt:SI (match_operand:SI 1 "register_operand"  "0,0,r")
1505                      (match_operand:SI 2 "rx_shift_operand"  "r,n,n")))
1506    (clobber (reg:CC CC_REG))]
1507   ""
1508   "@
1509   shar\t%2, %0
1510   shar\t%2, %0
1511   shar\t%2, %1, %0"
1512   [(set_attr "length" "3,2,3")]
1515 (define_insn "*ashrsi3_flags"
1516   [(set (reg CC_REG)
1517         (compare (ashiftrt:SI (match_operand:SI 1 "register_operand"  "0,0,r")
1518                               (match_operand:SI 2 "rx_shift_operand"  "r,n,n"))
1519                  (const_int 0)))
1520    (set (match_operand:SI              0 "register_operand" "=r,r,r")
1521         (ashiftrt:SI (match_dup 1) (match_dup 2)))]
1522   "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1523   "@
1524   shar\t%2, %0
1525   shar\t%2, %0
1526   shar\t%2, %1, %0"
1527   [(set_attr "length" "3,2,3")]
1530 (define_insn "lshrsi3"
1531   [(set (match_operand:SI              0 "register_operand" "=r,r,r")
1532         (lshiftrt:SI (match_operand:SI 1 "register_operand"  "0,0,r")
1533                      (match_operand:SI 2 "rx_shift_operand"  "r,n,n")))
1534    (clobber (reg:CC CC_REG))]
1535   ""
1536   "@
1537   shlr\t%2, %0
1538   shlr\t%2, %0
1539   shlr\t%2, %1, %0"
1540   [(set_attr "length" "3,2,3")]
1543 (define_insn "*lshrsi3_flags"
1544   [(set (reg CC_REG)
1545         (compare (lshiftrt:SI (match_operand:SI 1 "register_operand"  "0,0,r")
1546                               (match_operand:SI 2 "rx_shift_operand"  "r,n,n"))
1547                  (const_int 0)))
1548    (set (match_operand:SI                       0 "register_operand" "=r,r,r")
1549         (lshiftrt:SI (match_dup 1) (match_dup 2)))]
1550   "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1551   "@
1552   shlr\t%2, %0
1553   shlr\t%2, %0
1554   shlr\t%2, %1, %0"
1555   [(set_attr "length" "3,2,3")]
1558 (define_insn "ashlsi3"
1559   [(set (match_operand:SI            0 "register_operand" "=r,r,r")
1560         (ashift:SI (match_operand:SI 1 "register_operand"  "0,0,r")
1561                    (match_operand:SI 2 "rx_shift_operand"  "r,n,n")))
1562    (clobber (reg:CC CC_REG))]
1563   ""
1564   "@
1565   shll\t%2, %0
1566   shll\t%2, %0
1567   shll\t%2, %1, %0"
1568   [(set_attr "length" "3,2,3")]
1571 (define_insn "*ashlsi3_flags"
1572   [(set (reg CC_REG)
1573         (compare (ashift:SI (match_operand:SI 1 "register_operand"  "0,0,r")
1574                             (match_operand:SI 2 "rx_shift_operand"  "r,n,n"))
1575                  (const_int 0)))
1576    (set (match_operand:SI                     0 "register_operand" "=r,r,r")
1577         (ashift:SI (match_dup 1) (match_dup 2)))]
1578   "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1579   "@
1580   shll\t%2, %0
1581   shll\t%2, %0
1582   shll\t%2, %1, %0"
1583   [(set_attr "length" "3,2,3")]
1586 ;; Saturate to 32-bits
1587 (define_insn_and_split "ssaddsi3"
1588   [(set (match_operand:SI             0 "register_operand" "=r")
1589         (ss_plus:SI (match_operand:SI 1 "register_operand"  "r")
1590                     (match_operand:SI 2 "rx_source_operand" "riQ")))
1591    (clobber (reg:CC CC_REG))]
1592   ""
1593   "#"
1594   "reload_completed"
1595   [(parallel [(set (reg:CC_ZSC CC_REG)
1596                    (compare:CC_ZSC
1597                      (plus:SI (match_dup 1) (match_dup 2))
1598                      (const_int 0)))
1599               (set (match_dup 0)
1600                    (plus:SI (match_dup 1) (match_dup 2)))])
1601    (set (match_dup 0)
1602         (unspec:SI [(match_dup 0) (reg:CC CC_REG)] 
1603                    UNSPEC_BUILTIN_SAT))]
1604    ""
1607 (define_insn "*sat"
1608   [(set (match_operand:SI             0 "register_operand" "=r")
1609         (unspec:SI [(match_operand:SI 1 "register_operand"  "0")
1610                     (reg:CC CC_REG)]
1611                    UNSPEC_BUILTIN_SAT))]
1612   "reload_completed"
1613   "sat\t%0"
1614   [(set_attr "length" "2")]
1617 (define_insn "subsi3"
1618   [(set (match_operand:SI           0 "register_operand" "=r,r,r,r,r")
1619         (minus:SI (match_operand:SI 1 "register_operand"  "0,0,0,r,0")
1620                   (match_operand:SI 2 "rx_source_operand" "r,Uint04,n,r,Q")))
1621    (clobber (reg:CC CC_REG))]
1622   ""
1623   "@
1624   sub\t%2, %0
1625   sub\t%2, %0
1626   add\t%N2, %0
1627   sub\t%2, %1, %0
1628   sub\t%Q2, %0"
1629   [(set_attr "timings" "11,11,11,11,33")
1630    (set_attr "length" "2,2,6,3,5")]
1633 ;; Note that the O flag is set as if (compare op1 op2) not for
1634 ;; what is described here, (compare op0 0).
1635 (define_insn "*subsi3_flags"
1636   [(set (reg CC_REG)
1637         (compare (minus:SI (match_operand:SI 1 "register_operand"  "0,0,0,r,0")
1638                            (match_operand:SI 2 "rx_source_operand" "r,Uint04,n,r,Q"))
1639                  (const_int 0)))
1640    (set (match_operand:SI                    0 "register_operand" "=r,r,r,r,r")
1641         (minus:SI (match_dup 1) (match_dup 2)))]
1642   "reload_completed && rx_match_ccmode (insn, CC_ZSCmode)"
1643   "@
1644   sub\t%2, %0
1645   sub\t%2, %0
1646   add\t%N2, %0
1647   sub\t%2, %1, %0
1648   sub\t%Q2, %0"
1649   [(set_attr "timings" "11,11,11,11,33")
1650    (set_attr "length" "2,2,6,3,5")]
1653 ;; A helper to expand the above with the CC_MODE filled in.
1654 (define_expand "subsi3_flags"
1655   [(parallel [(set (reg:CC_ZSC CC_REG)
1656                    (compare:CC_ZSC
1657                      (minus:SI (match_operand:SI 1 "register_operand")
1658                                (match_operand:SI 2 "rx_source_operand"))
1659                      (const_int 0)))
1660               (set (match_operand:SI 0 "register_operand")
1661                    (minus:SI (match_dup 1) (match_dup 2)))])]
1664 (define_insn "sbb_internal"
1665   [(set (match_operand:SI     0 "register_operand"   "=r,r")
1666         (minus:SI
1667           (minus:SI
1668             (match_operand:SI 1 "register_operand"   " 0,0")
1669             (match_operand:SI 2 "rx_compare_operand" " r,Q"))
1670           (geu:SI (reg:CC CC_REG) (const_int 0))))
1671     (clobber (reg:CC CC_REG))]
1672   "reload_completed"
1673   "sbb\t%2, %0"
1674   [(set_attr "timings" "11,33")
1675    (set_attr "length"  "3,6")]
1678 (define_insn "*sbb_flags"
1679   [(set (reg CC_REG)
1680         (compare
1681           (minus:SI
1682             (minus:SI
1683               (match_operand:SI 1 "register_operand"   " 0,0")
1684               (match_operand:SI 2 "rx_compare_operand" " r,Q"))
1685             (geu:SI (reg:CC CC_REG) (const_int 0)))
1686           (const_int 0)))
1687    (set (match_operand:SI       0 "register_operand"   "=r,r")
1688         (minus:SI
1689           (minus:SI (match_dup 1) (match_dup 2))
1690           (geu:SI (reg:CC CC_REG) (const_int 0))))]
1691   "reload_completed"
1692   "sbb\t%2, %0"
1693   [(set_attr "timings" "11,33")
1694    (set_attr "length"  "3,6")]
1697 (define_expand "subdi3"
1698   [(set (match_operand:DI           0 "register_operand")
1699         (minus:DI (match_operand:DI 1 "register_operand")
1700                   (match_operand:DI 2 "register_operand")))]
1701   ""
1703   rtx op0l, op0h, op1l, op1h, op2l, op2h;
1705   op0l = gen_lowpart (SImode, operands[0]);
1706   op1l = gen_lowpart (SImode, operands[1]);
1707   op2l = gen_lowpart (SImode, operands[2]);
1708   op0h = gen_highpart (SImode, operands[0]);
1709   op1h = gen_highpart (SImode, operands[1]);
1710   op2h = gen_highpart_mode (SImode, DImode, operands[2]);
1712   emit_insn (gen_subdi3_internal (op0l, op0h, op1l, op2l, op1h, op2h));
1713   DONE;
1716 (define_insn_and_split "subdi3_internal"
1717   [(set (match_operand:SI          0 "register_operand"   "=&r,&r")
1718         (minus:SI (match_operand:SI 2 "register_operand"  "  0, r")
1719                   (match_operand:SI 3 "rx_compare_operand" "rQ, r")))
1720    (set (match_operand:SI          1 "register_operand"   "= r, r")
1721         (minus:SI
1722           (minus:SI
1723             (match_operand:SI      4 "register_operand"   "  1, 1")
1724             (match_operand:SI      5 "rx_compare_operand" " rQ,rQ"))
1725           (gtu:SI (match_dup 3) (match_dup 2))))
1726    (clobber (reg:CC CC_REG))]
1727   ""
1728   "#"
1729   "reload_completed"
1730   [(const_int 0)]
1732   emit_insn (gen_subsi3_flags (operands[0], operands[2], operands[3]));
1733   emit_insn (gen_sbb_internal (operands[1], operands[4], operands[5]));
1734   DONE;
1737 (define_insn_and_split "xorsi3"
1738   [(set (match_operand:SI         0 "register_operand" "=r,r,r,r,r,r")
1739         (xor:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0")
1740                 (match_operand:SI 2 "rx_source_operand"
1741                                   "r,Sint08,Sint16,Sint24,i,Q")))
1742    (clobber (reg:CC CC_REG))]
1743   ""
1744   "xor\t%Q2, %0"
1745   "&& RX_REG_P (operands[1]) && CONST_INT_P (operands[2])
1746    && pow2p_hwi (UINTVAL (operands[2]))"
1747   [(const_int 0)]
1749   /* For single bit constants use the bnot insn for smaller code.  */
1751   if (!rx_reg_dead_or_unused_after_insn (curr_insn, CC_REG))
1752     FAIL;
1754   rx_copy_reg_dead_or_unused_notes (operands[1], curr_insn,
1755     emit_insn (gen_bitinvert (operands[0],
1756                               GEN_INT (exact_log2 (UINTVAL (operands[2]))),
1757                               operands[1])));
1758   DONE;
1760   [(set_attr "timings" "11,11,11,11,11,33")
1761    (set_attr "length" "3,4,5,6,7,6")]
1764 (define_insn "*xorsi3_flags"
1765   [(set (reg CC_REG)
1766         (compare (xor:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0")
1767                          (match_operand:SI 2 "rx_source_operand"
1768                                                 "r,Sint08,Sint16,Sint24,i,Q"))
1769                  (const_int 0)))
1770    (set (match_operand:SI                  0 "register_operand" "=r,r,r,r,r,r")
1771         (xor:SI (match_dup 1) (match_dup 2)))]
1772   "reload_completed && rx_match_ccmode (insn, CC_ZSmode)"
1773   "xor\t%Q2, %0"
1774   [(set_attr "timings" "11,11,11,11,11,33")
1775    (set_attr "length" "3,4,5,6,7,6")]
1778 ;; A set of peepholes to catch extending loads followed by arithmetic operations.
1779 ;; We use iterators where possible to reduce the amount of typing and hence the
1780 ;; possibilities for typos.
1782 (define_code_iterator extend_types [(zero_extend "") (sign_extend "")])
1783 (define_code_attr     letter       [(zero_extend "R") (sign_extend "Q")])
1785 (define_code_iterator memex_commutative [(plus "") (and "") (ior "") (xor "")])
1786 (define_code_iterator memex_noncomm     [(div "") (udiv "") (minus "")])
1787 (define_code_iterator memex_nocc        [(smax "") (smin "") (mult "")])
1789 (define_code_attr     op                [(plus "add") (and "and") (div "div") (udiv "divu") (smax "max") (smin "min") (mult "mul") (ior "or") (minus "sub") (xor "xor")])
1791 (define_peephole2
1792   [(set (match_operand:SI                               0 "register_operand")
1793         (extend_types:SI (match_operand:small_int_modes 1 "rx_restricted_mem_operand")))
1794    (parallel [(set (match_operand:SI                    2 "register_operand")
1795                    (memex_commutative:SI (match_dup 0)
1796                                          (match_dup 2)))
1797               (clobber (reg:CC CC_REG))])]
1798   "peep2_regno_dead_p (2, REGNO (operands[0])) && (optimize < 3 || optimize_size)"
1799   [(parallel [(set (match_dup 2)
1800                    (memex_commutative:SI (match_dup 2)
1801                                          (extend_types:SI (match_dup 1))))
1802               (clobber (reg:CC CC_REG))])]
1805 (define_peephole2
1806   [(set (match_operand:SI                               0 "register_operand")
1807         (extend_types:SI (match_operand:small_int_modes 1 "rx_restricted_mem_operand")))
1808    (parallel [(set (match_operand:SI                    2 "register_operand")
1809                    (memex_commutative:SI (match_dup 2)
1810                                          (match_dup 0)))
1811               (clobber (reg:CC CC_REG))])]
1812   "peep2_regno_dead_p (2, REGNO (operands[0])) && (optimize < 3 || optimize_size)"
1813   [(parallel [(set (match_dup 2)
1814                    (memex_commutative:SI (match_dup 2)
1815                                          (extend_types:SI (match_dup 1))))
1816               (clobber (reg:CC CC_REG))])]
1819 (define_peephole2
1820   [(set (match_operand:SI                               0 "register_operand")
1821         (extend_types:SI (match_operand:small_int_modes 1 "rx_restricted_mem_operand")))
1822    (parallel [(set (match_operand:SI                    2 "register_operand")
1823                    (memex_noncomm:SI (match_dup 2)
1824                                      (match_dup 0)))
1825               (clobber (reg:CC CC_REG))])]
1826   "peep2_regno_dead_p (2, REGNO (operands[0])) && (optimize < 3 || optimize_size)"
1827   [(parallel [(set (match_dup 2)
1828                    (memex_noncomm:SI (match_dup 2)
1829                                      (extend_types:SI (match_dup 1))))
1830               (clobber (reg:CC CC_REG))])]
1833 (define_peephole2
1834   [(set (match_operand:SI                               0 "register_operand")
1835         (extend_types:SI (match_operand:small_int_modes 1 "rx_restricted_mem_operand")))
1836    (set (match_operand:SI                               2 "register_operand")
1837         (memex_nocc:SI (match_dup 0)
1838                        (match_dup 2)))]
1839   "peep2_regno_dead_p (2, REGNO (operands[0])) && (optimize < 3 || optimize_size)"
1840   [(set (match_dup 2)
1841         (memex_nocc:SI (match_dup 2)
1842                        (extend_types:SI (match_dup 1))))]
1845 (define_peephole2
1846   [(set (match_operand:SI                               0 "register_operand")
1847         (extend_types:SI (match_operand:small_int_modes 1 "rx_restricted_mem_operand")))
1848    (set (match_operand:SI                               2 "register_operand")
1849         (memex_nocc:SI (match_dup 2)
1850                        (match_dup 0)))]
1851   "peep2_regno_dead_p (2, REGNO (operands[0])) && (optimize < 3 || optimize_size)"
1852   [(set (match_dup 2)
1853         (memex_nocc:SI (match_dup 2)
1854                        (extend_types:SI (match_dup 1))))]
1857 (define_insn "<memex_commutative:code>si3_<extend_types:code><small_int_modes:mode>"
1858   [(set (match_operand:SI                                                     0 "register_operand" "=r")
1859         (memex_commutative:SI (match_operand:SI                               1 "register_operand" "%0")
1860                               (extend_types:SI (match_operand:small_int_modes 2 "rx_restricted_mem_operand" "Q"))))
1861    (clobber (reg:CC CC_REG))]
1862   "(optimize < 3 || optimize_size)"
1863   "<memex_commutative:op>\t%<extend_types:letter>2, %0"
1864   [(set_attr "timings" "33")
1865    (set_attr "length"  "5")] ;; This length is corrected in rx_adjust_insn_length
1868 (define_insn "<memex_noncomm:code>si3_<extend_types:code><small_int_modes:mode>"
1869   [(set (match_operand:SI                                                 0 "register_operand" "=r")
1870         (memex_noncomm:SI (match_operand:SI                               1 "register_operand" "0")
1871                           (extend_types:SI (match_operand:small_int_modes 2 "rx_restricted_mem_operand" "Q"))))
1872    (clobber (reg:CC CC_REG))]
1873   "(optimize < 3 || optimize_size)"
1874   "<memex_noncomm:op>\t%<extend_types:letter>2, %0"
1875   [(set_attr "timings" "33")
1876    (set_attr "length"  "5")] ;; This length is corrected in rx_adjust_insn_length
1879 (define_insn "<memex_nocc:code>si3_<extend_types:code><small_int_modes:mode>"
1880   [(set (match_operand:SI                                              0 "register_operand" "=r")
1881         (memex_nocc:SI (match_operand:SI                               1 "register_operand" "%0")
1882                        (extend_types:SI (match_operand:small_int_modes 2 "rx_restricted_mem_operand" "Q"))))]
1883   "(optimize < 3 || optimize_size)"
1884   "<memex_nocc:op>\t%<extend_types:letter>2, %0"
1885   [(set_attr "timings" "33")
1886    (set_attr "length"  "5")] ;; This length is corrected in rx_adjust_insn_length
1889 (define_peephole2
1890   [(set (match_operand:SI                               0 "register_operand")
1891         (extend_types:SI (match_operand:small_int_modes 1 "rx_restricted_mem_operand")))
1892    (set (reg:CC CC_REG)
1893         (compare:CC (match_operand:SI                   2 "register_operand")
1894                     (match_dup 0)))]
1895   "peep2_regno_dead_p (2, REGNO (operands[0])) && (optimize < 3 || optimize_size)"
1896   [(set (reg:CC CC_REG)
1897         (compare:CC (match_dup 2)
1898                     (extend_types:SI (match_dup 1))))]
1901 ;; Convert:
1902 ;;   (set (reg1) (sign_extend (mem))
1903 ;;   (set (reg2) (zero_extend (reg1))
1904 ;; into
1905 ;;   (set (reg2) (zero_extend (mem)))
1906 (define_peephole2
1907   [(set (match_operand:SI                              0 "register_operand")
1908         (sign_extend:SI (match_operand:small_int_modes 1 "memory_operand")))
1909    (set (match_operand:SI                              2 "register_operand")
1910         (zero_extend:SI (match_operand:small_int_modes 3 "register_operand")))]
1911   "REGNO (operands[0]) == REGNO (operands[3])
1912    && (REGNO (operands[0]) == REGNO (operands[2])
1913        || peep2_regno_dead_p (2, REGNO (operands[0])))"
1914   [(set (match_dup 2)
1915         (zero_extend:SI (match_dup 1)))]
1918 ;; Remove the redundant sign extension from:
1919 ;;   (set (reg) (extend (mem)))
1920 ;;   (set (reg) (extend (reg)))
1921 (define_peephole2
1922   [(set (match_operand:SI                               0 "register_operand")
1923         (extend_types:SI (match_operand:small_int_modes 1 "memory_operand")))
1924    (set (match_dup 0)
1925         (extend_types:SI (match_operand:small_int_modes 2 "register_operand")))]
1926   "REGNO (operands[0]) == REGNO (operands[2])"
1927   [(set (match_dup 0) (extend_types:SI (match_dup 1)))]
1930 (define_insn "comparesi3_<extend_types:code><small_int_modes:mode>"
1931   [(set (reg:CC CC_REG)
1932         (compare:CC (match_operand:SI                               0 "register_operand" "r")
1933                     (extend_types:SI (match_operand:small_int_modes 1 "rx_restricted_mem_operand" "Q"))))]
1934   "(optimize < 3 || optimize_size)"
1935   "cmp\t%<extend_types:letter>1, %0"
1936   [(set_attr "timings" "33")
1937    (set_attr "length"  "5")] ;; This length is corrected in rx_adjust_insn_length
1940 ;; Floating Point Instructions
1942 (define_insn "addsf3"
1943   [(set (match_operand:SF          0 "register_operand"  "=r,r,r")
1944         (plus:SF (match_operand:SF 1 "register_operand"  "%0,0,0")
1945                  (match_operand:SF 2 "rx_source_operand"  "r,F,Q")))
1946    (clobber (reg:CC CC_REG))]
1947   "ALLOW_RX_FPU_INSNS"
1948   "fadd\t%2, %0"
1949   [(set_attr "timings" "44,44,66")
1950    (set_attr "length" "3,7,5")]
1953 (define_insn "divsf3"
1954   [(set (match_operand:SF         0 "register_operand" "=r,r,r")
1955         (div:SF (match_operand:SF 1 "register_operand"  "0,0,0")
1956                 (match_operand:SF 2 "rx_source_operand" "r,F,Q")))
1957    (clobber (reg:CC CC_REG))]
1958   "ALLOW_RX_FPU_INSNS"
1959   "fdiv\t%2, %0"
1960   [(set_attr "timings" "1616,1616,1818")
1961    (set_attr "length" "3,7,5")]
1964 (define_insn "mulsf3"
1965   [(set (match_operand:SF          0 "register_operand" "=r,r,r")
1966         (mult:SF (match_operand:SF 1 "register_operand" "%0,0,0")
1967                 (match_operand:SF  2 "rx_source_operand" "r,F,Q")))
1968    (clobber (reg:CC CC_REG))]
1969   "ALLOW_RX_FPU_INSNS"
1970   "fmul\t%2, %0"
1971   [(set_attr "timings" "33,33,55")
1972    (set_attr "length"  "3,7,5")]
1975 (define_insn "subsf3"
1976   [(set (match_operand:SF           0 "register_operand" "=r,r,r")
1977         (minus:SF (match_operand:SF 1 "register_operand"  "0,0,0")
1978                   (match_operand:SF 2 "rx_source_operand" "r,F,Q")))
1979    (clobber (reg:CC CC_REG))]
1980   "ALLOW_RX_FPU_INSNS"
1981   "fsub\t%Q2, %0"
1982   [(set_attr "timings" "44,44,66")
1983    (set_attr "length" "3,7,5")]
1986 (define_insn "fix_truncsfsi2"
1987   [(set (match_operand:SI         0 "register_operand"  "=r,r")
1988         (fix:SI (match_operand:SF 1 "rx_compare_operand" "r,Q")))
1989    (clobber (reg:CC CC_REG))]
1990   "ALLOW_RX_FPU_INSNS"
1991   "ftoi\t%Q1, %0"
1992   [(set_attr "timings" "22,44")
1993    (set_attr "length" "3,5")]
1996 (define_insn "floatsisf2"
1997   [(set (match_operand:SF           0 "register_operand"  "=r,r")
1998         (float:SF (match_operand:SI 1 "rx_compare_operand" "r,Q")))
1999    (clobber (reg:CC CC_REG))]
2000   "ALLOW_RX_FPU_INSNS"
2001   "itof\t%Q1, %0"
2002   [(set_attr "timings" "22,44")
2003    (set_attr "length" "3,6")]
2006 ;; Bit manipulation instructions.
2008 ;; The *_in_memory patterns will not be matched automatically, not even with
2009 ;; combiner bridge patterns.  Especially when the memory operands have a
2010 ;; displacement, the resulting patterns look too complex.
2011 ;; Instead we manually look around the matched insn to see if there is a
2012 ;; preceeding memory load and a following memory store of the modified register
2013 ;; which can be fused into the single *_in_memory insn.
2014 ;; Do that before register allocation, as it can eliminate one temporary
2015 ;; register that needs to be allocated.
2017 (define_insn_and_split "bitset"
2018   [(set (match_operand:SI                    0 "register_operand" "=r")
2019         (ior:SI (ashift:SI (const_int 1)
2020                            (match_operand:SI 1 "rx_shift_operand" "ri"))
2021                 (match_operand:SI            2 "register_operand" "0")))]
2022   ""
2023   "bset\t%1, %0"
2024   "&& can_create_pseudo_p ()"
2025   [(const_int 0)]
2027   if (rx_fuse_in_memory_bitop (operands, curr_insn, &gen_bitset_in_memory))
2028     DONE;
2029   else
2030     FAIL;
2032   [(set_attr "length" "3")]
2035 (define_insn "bitset_in_memory"
2036   [(set (match_operand:QI                    0 "rx_restricted_mem_operand" "+Q")
2037         (ior:QI (ashift:QI (const_int 1)
2038                            (match_operand:QI 1 "nonmemory_operand" "ri"))
2039                 (match_dup 0)))]
2040   ""
2041   "bset\t%1, %0.B"
2042   [(set_attr "length" "5")
2043    (set_attr "timings" "33")]
2046 (define_insn_and_split "bitinvert"
2047   [(set (match_operand:SI 0 "register_operand" "=r")
2048         (xor:SI (ashift:SI (const_int 1)
2049                            (match_operand:SI 1 "rx_shift_operand" "ri"))
2050                 (match_operand:SI 2 "register_operand" "0")))]
2051   ""
2052   "bnot\t%1, %0"
2053   "&& can_create_pseudo_p ()"
2054   [(const_int 0)]
2056   if (rx_fuse_in_memory_bitop (operands, curr_insn, &gen_bitinvert_in_memory))
2057     DONE;
2058   else
2059     FAIL;
2061   [(set_attr "length" "3")]
2064 (define_insn "bitinvert_in_memory"
2065   [(set (match_operand:QI 0 "rx_restricted_mem_operand" "+Q")
2066         (xor:QI (ashift:QI (const_int 1)
2067                            (match_operand:QI 1 "nonmemory_operand" "ri"))
2068                 (match_dup 0)))]
2069   ""
2070   "bnot\t%1, %0.B"
2071   [(set_attr "length" "5")
2072    (set_attr "timings" "33")]
2075 (define_insn_and_split "bitclr"
2076   [(set (match_operand:SI 0 "register_operand" "=r")
2077         (and:SI (not:SI
2078                   (ashift:SI
2079                     (const_int 1)
2080                     (match_operand:SI 1 "rx_shift_operand" "ri")))
2081                 (match_operand:SI 2 "register_operand" "0")))]
2082   ""
2083   "bclr\t%1, %0"
2084   "&& can_create_pseudo_p ()"
2085   [(const_int 0)]
2087   if (rx_fuse_in_memory_bitop (operands, curr_insn, &gen_bitclr_in_memory))
2088     DONE;
2089   else
2090     FAIL;
2092   [(set_attr "length" "3")]
2095 (define_insn "bitclr_in_memory"
2096   [(set (match_operand:QI 0 "rx_restricted_mem_operand" "+Q")
2097         (and:QI (not:QI
2098                   (ashift:QI
2099                     (const_int 1)
2100                     (match_operand:QI 1 "nonmemory_operand" "ri")))
2101                 (match_dup 0)))]
2102   ""
2103   "bclr\t%1, %0.B"
2104   [(set_attr "length" "5")
2105    (set_attr "timings" "33")]
2108 (define_insn "*insv_imm"
2109   [(set (zero_extract:SI
2110           (match_operand:SI 0 "register_operand" "+r")
2111           (const_int 1)
2112           (match_operand:SI 1 "rx_shift_operand" "ri"))
2113         (match_operand:SI 2 "const_int_operand" ""))]
2114   ""
2116   if (INTVAL (operands[2]) & 1)
2117     return "bset\t%1, %0";
2118   else
2119     return "bclr\t%1, %0";
2121   [(set_attr "length" "3")]
2124 (define_insn_and_split "rx_insv_reg"
2125   [(set (zero_extract:SI
2126           (match_operand:SI 0 "register_operand" "+r")
2127           (const_int 1)
2128           (match_operand:SI 1 "const_int_operand" ""))
2129         (match_operand:SI 2 "register_operand" "r"))
2130    (clobber (reg:CC CC_REG))]
2131   ""
2132   "#"
2133   "reload_completed"
2134   [(set (zero_extract:SI (match_dup 0) (const_int 1) (match_dup 1))
2135         (match_dup 3))]
2137   rtx flags, x;
2139   /* Emit tst #1, op2.  */
2140   flags = gen_rtx_REG (CC_ZSmode, CC_REG);
2141   x = gen_rtx_AND (SImode, operands[2], const1_rtx);
2142   x = gen_rtx_COMPARE (CC_ZSmode, x, const0_rtx);
2143   x = gen_rtx_SET (flags, x);
2144   emit_insn (x);
2146   /* Emit bmne.  */
2147   operands[3] = gen_rtx_NE (SImode, flags, const0_rtx);
2150 (define_insn_and_split "*insv_cond"
2151   [(set (zero_extract:SI
2152           (match_operand:SI 0 "register_operand" "+r")
2153           (const_int 1)
2154           (match_operand:SI 1 "const_int_operand" ""))
2155         (match_operator:SI 4 "comparison_operator"
2156           [(match_operand:SI 2 "register_operand" "r")
2157            (match_operand:SI 3 "rx_source_operand" "riQ")]))
2158    (clobber (reg:CC CC_REG))]
2159   ""
2160   "#"
2161   "reload_completed"
2162   [(set (zero_extract:SI (match_dup 0) (const_int 1) (match_dup 1))
2163         (match_dup 4))]
2165   rtx flags, x;
2167   flags = gen_rtx_REG (CCmode, CC_REG);
2168   x = gen_rtx_COMPARE (CCmode, operands[2], operands[3]);
2169   x = gen_rtx_SET (flags, x);
2170   emit_insn (x);
2172   operands[4] = gen_rtx_fmt_ee (GET_CODE (operands[4]), SImode,
2173                                 flags, const0_rtx);
2176 (define_insn "*bmcc"
2177   [(set (zero_extract:SI
2178           (match_operand:SI 0 "register_operand" "+r")
2179           (const_int 1)
2180           (match_operand:SI 1 "const_int_operand" ""))
2181         (match_operator:SI 2 "comparison_operator"
2182           [(reg CC_REG) (const_int 0)]))]
2183   "reload_completed"
2184   "bm%B2\t%1, %0"
2185   [(set_attr "length" "3")]
2188 ;; Work around the fact that X=Y<0 is preferentially expanded as a shift.
2189 (define_insn_and_split "*insv_cond_lt"
2190   [(set (zero_extract:SI
2191           (match_operand:SI 0 "register_operand" "+r")
2192           (const_int 1)
2193           (match_operand:SI 1 "const_int_operand" ""))
2194         (match_operator:SI 3 "rshift_operator"
2195           [(match_operand:SI 2 "register_operand" "r")
2196            (const_int 31)]))
2197    (clobber (reg:CC CC_REG))]
2198   ""
2199   "#"
2200   ""
2201   [(parallel [(set (zero_extract:SI (match_dup 0) (const_int 1) (match_dup 1))
2202                    (lt:SI (match_dup 2) (const_int 0)))
2203               (clobber (reg:CC CC_REG))])]
2204   ""
2207 (define_expand "insv"
2208   [(set (zero_extract:SI
2209           (match_operand:SI 0 "register_operand")       ;; Destination
2210           (match_operand:SI 1 "const_int_operand")      ;; # of bits to set
2211           (match_operand:SI 2 "nonmemory_operand"))     ;; Starting bit
2212         (match_operand:SI   3 "nonmemory_operand"))]    ;; Bits to insert
2213   ""
2215   /* We only handle single-bit inserts.  */
2216   if (!CONST_INT_P (operands[1]) || INTVAL (operands[1]) != 1)
2217     FAIL;
2219   /* Either the bit to insert or the position must be constant.  */
2220   if (CONST_INT_P (operands[3]))
2221     operands[3] = GEN_INT (INTVAL (operands[3]) & 1);
2222   else if (CONST_INT_P (operands[2]))
2223     {
2224       emit_insn (gen_rx_insv_reg (operands[0], operands[2], operands[3]));
2225       DONE;
2226     }
2227   else
2228     FAIL;
2231 ;; Atomic operations.
2233 (define_code_iterator FETCHOP [plus minus ior xor and])
2234 (define_code_iterator FETCHOP_NO_MINUS [plus ior xor and])
2236 (define_code_attr fetchop_name
2237   [(plus "add") (minus "sub") (ior "or") (xor "xor") (and "and")])
2239 (define_code_attr fetchop_name2
2240   [(plus "add") (minus "sub") (ior "ior") (xor "xor") (and "and")])
2242 (define_mode_iterator QIHI [QI HI])
2243 (define_mode_attr BW [(QI "B") (HI "W")])
2245 (define_insn "sync_lock_test_and_setsi"
2246   [(set (match_operand:SI 0 "register_operand"   "=r,r")
2247         (match_operand:SI 1 "rx_compare_operand" "=r,Q"))
2248    (set (match_dup 1)
2249         (match_operand:SI 2 "register_operand"    "0,0"))]
2250   ""
2251   "xchg\t%1, %0"
2252   [(set_attr "length" "3,6")
2253    (set_attr "timings" "22")]
2256 (define_expand "atomic_exchange<mode>"
2257   [(match_operand:QIHI 0 "register_operand")            ;; oldval output
2258    (match_operand:QIHI 1 "rx_restricted_mem_operand")   ;; memory
2259    (match_operand:QIHI 2 "register_operand")            ;; newval input
2260    (match_operand:QIHI 3 "const_int_operand")]          ;; memory model
2261   ""
2263   emit_insn (gen_xchg_mem<mode> (operands[0], operands[1], operands[2]));
2264   DONE;
2267 (define_expand "atomic_exchangesi"
2268   [(match_operand:SI 0 "register_operand")              ;; oldval output
2269    (match_operand:SI 1 "rx_restricted_mem_operand")     ;; memory
2270    (match_operand:SI 2 "register_operand")              ;; newval input
2271    (match_operand:SI 3 "const_int_operand")]            ;; memory model
2272   ""
2274   emit_insn (gen_sync_lock_test_and_setsi (operands[0], operands[1],
2275                                            operands[2]));
2276   DONE;
2279 (define_insn "xchg_mem<mode>"
2280   [(set (match_operand:QIHI 0 "register_operand"   "=r")
2281         (match_operand:QIHI 1 "rx_compare_operand" "=Q"))
2282    (set (match_dup 1)
2283         (match_operand:QIHI 2 "register_operand"    "0"))]
2284   ""
2285   "xchg\t%1.<BW>, %0"
2286   [(set_attr "length" "6")
2287    (set_attr "timings" "22")]
2290 ;; read - modify - write - return old value
2291 (define_expand "atomic_fetch_<fetchop_name>si"
2292   [(set (match_operand:SI 0 "register_operand")
2293         (match_operand:SI 1 "memory_operand"))
2294    (set (match_dup 1)
2295         (FETCHOP:SI (match_dup 1) (match_operand:SI 2 "rx_source_operand")))
2296    (match_operand:SI 3 "const_int_operand")]            ;; memory model
2297   ""
2299   {
2300     rx_atomic_sequence seq (current_function_decl);
2302     emit_move_insn (operands[0], operands[1]);
2304     rtx tmp = gen_reg_rtx (SImode);
2305     emit_insn (gen_<fetchop_name2>si3 (tmp, operands[0], operands[2]));
2307     emit_move_insn (operands[1], tmp);
2308   }
2309   DONE;
2312 (define_expand "atomic_fetch_nandsi"
2313   [(set (match_operand:SI 0 "register_operand")
2314         (match_operand:SI 1 "memory_operand"))
2315    (set (match_dup 1)
2316         (not:SI (and:SI (match_dup 1)
2317                         (match_operand:SI 2 "rx_source_operand"))))
2318    (match_operand:SI 3 "const_int_operand")]            ;; memory model
2319   ""
2321   {
2322     rx_atomic_sequence seq (current_function_decl);
2324     emit_move_insn (operands[0], operands[1]);
2326     rtx tmp = gen_reg_rtx (SImode);
2327     emit_insn (gen_andsi3 (tmp, operands[0], operands[2]));
2328     emit_insn (gen_one_cmplsi2 (tmp, tmp));
2330     emit_move_insn (operands[1], tmp);
2331   }
2332   DONE;
2335 ;; read - modify - write - return new value
2336 ;; Because subtraction is not commutative we need to specify a different
2337 ;; set of patterns for it.
2338 (define_expand "atomic_<fetchop_name>_fetchsi"
2339   [(set (match_operand:SI 0 "register_operand")
2340         (FETCHOP_NO_MINUS:SI (match_operand:SI 1 "rx_restricted_mem_operand")
2341                              (match_operand:SI 2 "register_operand")))
2342    (set (match_dup 1)
2343         (FETCHOP_NO_MINUS:SI (match_dup 1) (match_dup 2)))
2344    (match_operand:SI 3 "const_int_operand")]            ;; memory model
2345   ""
2347   {
2348     rx_atomic_sequence seq (current_function_decl);
2350     emit_move_insn (operands[0], operands[2]);
2351     emit_insn (gen_<fetchop_name2>si3 (operands[0], operands[0], operands[1]));
2352     emit_move_insn (operands[1], operands[0]);
2353   }
2354   DONE;
2357 (define_expand "atomic_sub_fetchsi"
2358   [(set (match_operand:SI 0 "register_operand")
2359         (minus:SI (match_operand:SI 1 "rx_restricted_mem_operand")
2360                   (match_operand:SI 2 "rx_source_operand")))
2361    (set (match_dup 1)
2362         (minus:SI (match_dup 1) (match_dup 2)))
2363    (match_operand:SI 3 "const_int_operand")]            ;; memory model
2364   ""
2366   {
2367     rx_atomic_sequence seq (current_function_decl);
2369     emit_move_insn (operands[0], operands[1]);
2370     emit_insn (gen_subsi3 (operands[0], operands[0], operands[2]));
2371     emit_move_insn (operands[1], operands[0]);
2372   }
2373   DONE;
2376 (define_expand "atomic_nand_fetchsi"
2377   [(set (match_operand:SI 0 "register_operand")
2378         (not:SI (and:SI (match_operand:SI 1 "rx_restricted_mem_operand")
2379                         (match_operand:SI 2 "register_operand"))))
2380    (set (match_dup 1)
2381         (not:SI (and:SI (match_dup 1) (match_dup 2))))
2382    (match_operand:SI 3 "const_int_operand")]            ;; memory model
2383   ""
2385   {
2386     rx_atomic_sequence seq (current_function_decl);
2388     emit_move_insn (operands[0], operands[2]);
2389     emit_insn (gen_andsi3 (operands[0], operands[0], operands[1]));
2390     emit_insn (gen_one_cmplsi2 (operands[0], operands[0]));
2391     emit_move_insn (operands[1], operands[0]);
2392   }
2393   DONE;
2397 ;; Block move functions.
2399 (define_expand "movstr"
2400   [(set (match_operand:BLK 1 "memory_operand")    ;; Dest
2401         (match_operand:BLK 2 "memory_operand"))   ;; Source
2402    (use (match_operand:SI  0 "register_operand")) ;; Updated Dest
2403   ]
2404   "rx_allow_string_insns"
2405   {
2406     rtx addr1 = gen_rtx_REG (SImode, 1);
2407     rtx addr2 = gen_rtx_REG (SImode, 2);
2408     rtx len   = gen_rtx_REG (SImode, 3);
2409     rtx dest_copy = gen_reg_rtx (SImode);
2411     emit_move_insn (len, GEN_INT (-1));
2412     emit_move_insn (addr1, force_operand (XEXP (operands[1], 0), NULL_RTX));
2413     emit_move_insn (addr2, force_operand (XEXP (operands[2], 0), NULL_RTX));
2414     operands[1] = replace_equiv_address_nv (operands[1], addr1);
2415     operands[2] = replace_equiv_address_nv (operands[2], addr2);
2416     emit_move_insn (dest_copy, addr1);
2417     emit_insn (gen_rx_movstr ());
2418     emit_move_insn (len, GEN_INT (-1));
2419     emit_insn (gen_rx_strend (operands[0], dest_copy));
2420     DONE;
2421   }
2424 (define_insn "rx_movstr"
2425   [(set (mem:BLK (reg:SI 1))
2426         (mem:BLK (reg:SI 2)))
2427    (unspec_volatile:BLK [(reg:SI 1) (reg:SI 2) (reg:SI 3)] UNSPEC_MOVSTR)
2428    (clobber (reg:SI 1))
2429    (clobber (reg:SI 2))
2430    (clobber (reg:SI 3))]
2431   "rx_allow_string_insns"
2432   "smovu"
2433   [(set_attr "length" "2")
2434    (set_attr "timings" "1111")] ;; The timing is a guesstimate.
2437 (define_insn "rx_strend"
2438   [(set (match_operand:SI                      0 "register_operand" "=r")
2439         (unspec_volatile:SI [(match_operand:SI 1 "register_operand"  "r")
2440                                 (reg:SI 3)] UNSPEC_STRLEN))
2441    (clobber (reg:SI 1))
2442    (clobber (reg:SI 2))
2443    (clobber (reg:SI 3))
2444    (clobber (reg:CC CC_REG))
2445    ]
2446   "rx_allow_string_insns"
2447   "mov\t%1, r1\n\tmov\t#0, r2\n\tsuntil.b\n\tmov\tr1, %0\n\tsub\t#1, %0"
2448   [(set_attr "length" "10")
2449    (set_attr "timings" "1111")] ;; The timing is a guesstimate.
2452 (define_expand "cpymemsi"
2453   [(parallel
2454     [(set (match_operand:BLK 0 "memory_operand")    ;; Dest
2455           (match_operand:BLK 1 "memory_operand"))   ;; Source
2456      (use (match_operand:SI  2 "register_operand")) ;; Length in bytes
2457      (match_operand          3 "immediate_operand") ;; Align
2458      (unspec_volatile:BLK [(reg:SI 1) (reg:SI 2) (reg:SI 3)] UNSPEC_CPYMEM)]
2459     )]
2460   "rx_allow_string_insns"
2461   {
2462     rtx addr1 = gen_rtx_REG (SImode, 1);
2463     rtx addr2 = gen_rtx_REG (SImode, 2);
2464     rtx len   = gen_rtx_REG (SImode, 3);
2466     /* Do not use when the source or destination are volatile - the SMOVF
2467        instruction will read and write in word sized blocks, which may be
2468        outside of the valid address range.  */
2469     if (MEM_P (operands[0]) && MEM_VOLATILE_P (operands[0]))
2470       FAIL;
2471     if (MEM_P (operands[1]) && MEM_VOLATILE_P (operands[1]))
2472       FAIL;
2474     if (REG_P (operands[0]) && (REGNO (operands[0]) == 2
2475                                       || REGNO (operands[0]) == 3))
2476       FAIL;
2477     if (REG_P (operands[1]) && (REGNO (operands[1]) == 1
2478                                       || REGNO (operands[1]) == 3))
2479       FAIL;
2480     if (REG_P (operands[2]) && (REGNO (operands[2]) == 1
2481                                       || REGNO (operands[2]) == 2))
2482       FAIL;
2484     emit_move_insn (addr1, force_operand (XEXP (operands[0], 0), NULL_RTX));
2485     emit_move_insn (addr2, force_operand (XEXP (operands[1], 0), NULL_RTX));
2486     emit_move_insn (len, force_operand (operands[2], NULL_RTX));
2487     operands[0] = replace_equiv_address_nv (operands[0], addr1);
2488     operands[1] = replace_equiv_address_nv (operands[1], addr2);
2489     emit_insn (gen_rx_cpymem ());
2490     DONE;
2491   }
2494 (define_insn "rx_cpymem"
2495   [(set (mem:BLK (reg:SI 1))
2496         (mem:BLK (reg:SI 2)))
2497    (use (reg:SI 3))
2498    (unspec_volatile:BLK [(reg:SI 1) (reg:SI 2) (reg:SI 3)] UNSPEC_CPYMEM)
2499    (clobber (reg:SI 1))
2500    (clobber (reg:SI 2))
2501    (clobber (reg:SI 3))]
2502   "rx_allow_string_insns"
2503   "smovf"
2504   [(set_attr "length" "2")
2505    (set_attr "timings" "1111")] ;; The timing is a guesstimate.
2508 (define_expand "setmemsi"
2509   [(set (match_operand:BLK 0 "memory_operand")     ;; Dest
2510         (match_operand:QI  2 "nonmemory_operand")) ;; Value
2511    (use (match_operand:SI  1 "nonmemory_operand")) ;; Length
2512    (match_operand          3 "immediate_operand")  ;; Align
2513    (unspec_volatile:BLK [(reg:SI 1) (reg:SI 2) (reg:SI 3)] UNSPEC_SETMEM)]
2514   "rx_allow_string_insns"
2515   {
2516     rtx addr = gen_rtx_REG (SImode, 1);
2517     rtx val  = gen_rtx_REG (QImode, 2);
2518     rtx len  = gen_rtx_REG (SImode, 3);
2520     emit_move_insn (addr, force_operand (XEXP (operands[0], 0), NULL_RTX));
2521     emit_move_insn (len, force_operand (operands[1], NULL_RTX));
2522     emit_move_insn (val, operands[2]);
2523     emit_insn (gen_rx_setmem ());
2524     DONE;
2525   }
2528 (define_insn "rx_setmem"
2529   [(set (mem:BLK (reg:SI 1))
2530         (unspec_volatile:BLK [(reg:SI 1) (reg:SI 2) (reg:SI 3)] UNSPEC_SETMEM))
2531    (clobber (reg:SI 1))
2532    (clobber (reg:SI 3))]
2533   "rx_allow_string_insns"
2534   "sstr.b"
2535   [(set_attr "length" "2")
2536    (set_attr "timings" "1111")] ;; The timing is a guesstimate.
2539 (define_expand "cmpstrnsi"
2540   [(set (match_operand:SI                       0 "register_operand")   ;; Result
2541         (unspec_volatile:SI [(match_operand:BLK 1 "memory_operand")     ;; String1
2542                              (match_operand:BLK 2 "memory_operand")]    ;; String2
2543                             UNSPEC_CMPSTRN))
2544    (use (match_operand:SI                       3 "register_operand"))  ;; Max Length
2545    (match_operand:SI                            4 "immediate_operand")] ;; Known Align
2546   "rx_allow_string_insns"
2547   {
2548     rtx str1 = gen_rtx_REG (SImode, 1);
2549     rtx str2 = gen_rtx_REG (SImode, 2);
2550     rtx len  = gen_rtx_REG (SImode, 3);
2551   
2552     emit_move_insn (str1, force_operand (XEXP (operands[1], 0), NULL_RTX));
2553     emit_move_insn (str2, force_operand (XEXP (operands[2], 0), NULL_RTX));
2554     emit_move_insn (len, operands[3]);
2556     emit_insn (gen_rx_cmpstrn (operands[0], operands[1], operands[2]));
2557     DONE;
2558   }
2561 (define_expand "cmpstrsi"
2562   [(set (match_operand:SI                       0 "register_operand")   ;; Result
2563         (unspec_volatile:SI [(match_operand:BLK 1 "memory_operand")     ;; String1
2564                              (match_operand:BLK 2 "memory_operand")]    ;; String2
2565                             UNSPEC_CMPSTRN))
2566    (match_operand:SI                            3 "immediate_operand")] ;; Known Align
2567   "rx_allow_string_insns"
2568   {
2569     rtx str1 = gen_rtx_REG (SImode, 1);
2570     rtx str2 = gen_rtx_REG (SImode, 2);
2571     rtx len  = gen_rtx_REG (SImode, 3);
2572   
2573     emit_move_insn (str1, force_reg (SImode, XEXP (operands[1], 0)));
2574     emit_move_insn (str2, force_reg (SImode, XEXP (operands[2], 0)));
2575     emit_move_insn (len, GEN_INT (-1));
2577     emit_insn (gen_rx_cmpstrn (operands[0], operands[1], operands[2]));
2578     DONE;
2579   }
2582 (define_insn "rx_cmpstrn"
2583   [(set (match_operand:SI 0 "register_operand" "=r")
2584         (unspec_volatile:SI [(reg:SI 1) (reg:SI 2) (reg:SI 3)]
2585                             UNSPEC_CMPSTRN))
2586    (use (match_operand:BLK 1 "memory_operand" "m"))
2587    (use (match_operand:BLK 2 "memory_operand" "m"))
2588    (clobber (reg:SI 1))
2589    (clobber (reg:SI 2))
2590    (clobber (reg:SI 3))
2591    (clobber (reg:CC CC_REG))]
2592   "rx_allow_string_insns"
2593   "scmpu                ; Perform the string comparison
2594    mov     #-1, %0      ; Set up -1 result (which cannot be created
2595                         ; by the SC insn)
2596    bnc     ?+           ; If Carry is not set skip over
2597    scne.L  %0           ; Set result based on Z flag
2598 ?:                      
2600   [(set_attr "length" "9")
2601    (set_attr "timings" "1111")] ;; The timing is a guesstimate.
2604 ;;   Builtin Functions
2606 ;; GCC does not have the ability to generate the following instructions
2607 ;; on its own so they are provided as builtins instead.  To use them from
2608 ;; a program for example invoke them as __builtin_rx_<insn_name>.  For
2609 ;; example:
2611 ;;    int short_byte_swap (int arg) { return __builtin_rx_revw (arg); }
2613 ;;---------- Accumulator Support ------------------------
2615 ;; Multiply & Accumulate (high)
2616 (define_insn "machi"
2617   [(unspec:SI [(match_operand:SI 0 "register_operand" "r")
2618                (match_operand:SI 1 "register_operand" "r")]
2619               UNSPEC_BUILTIN_MACHI)]
2620   ""
2621   "machi\t%0, %1"
2622   [(set_attr "length" "3")]
2625 ;; Multiply & Accumulate (low)
2626 (define_insn "maclo"
2627   [(unspec:SI [(match_operand:SI 0 "register_operand" "r")
2628                (match_operand:SI 1 "register_operand" "r")]
2629               UNSPEC_BUILTIN_MACLO)]
2630   ""
2631   "maclo\t%0, %1"
2632   [(set_attr "length" "3")]
2635 ;; Multiply (high)
2636 (define_insn "mulhi"
2637   [(unspec:SI [(match_operand:SI 0 "register_operand" "r")
2638                (match_operand:SI 1 "register_operand" "r")]
2639               UNSPEC_BUILTIN_MULHI)]
2640   ""
2641   "mulhi\t%0, %1"
2642   [(set_attr "length" "3")]
2645 ;; Multiply (low)
2646 (define_insn "mullo"
2647   [(unspec:SI [(match_operand:SI 0 "register_operand" "r")
2648                (match_operand:SI 1 "register_operand" "r")]
2649               UNSPEC_BUILTIN_MULLO)]
2650   ""
2651   "mullo\t%0, %1"
2652   [(set_attr "length" "3")]
2655 ;; Move from Accumulator (high)
2656 (define_insn "mvfachi"
2657   [(set (match_operand:SI 0 "register_operand" "=r")
2658         (unspec:SI [(const_int 0)]
2659                    UNSPEC_BUILTIN_MVFACHI))]
2660   ""
2661   "mvfachi\t%0"
2662   [(set_attr "length" "3")]
2665 ;; Move from Accumulator (middle)
2666 (define_insn "mvfacmi"
2667   [(set (match_operand:SI 0 "register_operand" "=r")
2668         (unspec:SI [(const_int 0)]
2669                    UNSPEC_BUILTIN_MVFACMI))]
2670   ""
2671   "mvfacmi\t%0"
2672   [(set_attr "length" "3")]
2675 ;; Move to Accumulator (high)
2676 (define_insn "mvtachi"
2677   [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")]
2678                        UNSPEC_BUILTIN_MVTACHI)]
2679   ""
2680   "mvtachi\t%0"
2681   [(set_attr "length" "3")]
2684 ;; Move to Accumulator (low)
2685 (define_insn "mvtaclo"
2686   [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")]
2687                        UNSPEC_BUILTIN_MVTACLO)]
2688   ""
2689   "mvtaclo\t%0"
2690   [(set_attr "length" "3")]
2693 ;; Round Accumulator
2694 (define_insn "racw"
2695   [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i")]
2696                        UNSPEC_BUILTIN_RACW)]
2697   ""
2698   "racw\t%0"
2699   [(set_attr "length" "3")]
2702 ;; Repeat multiply and accumulate
2703 (define_insn "rmpa"
2704   [(unspec:SI [(const_int 0) (reg:SI 1) (reg:SI 2) (reg:SI 3)
2705                (reg:SI 4) (reg:SI 5) (reg:SI 6)]
2706               UNSPEC_BUILTIN_RMPA)
2707   (clobber (reg:SI 1))
2708   (clobber (reg:SI 2))
2709   (clobber (reg:SI 3))]
2710   "rx_allow_string_insns"
2711   "rmpa"
2712   [(set_attr "length" "2")
2713    (set_attr "timings" "1010")]
2716 ;;---------- Arithmetic ------------------------
2718 ;; Byte swap (two 16-bit values).
2719 (define_insn "revw"
2720   [(set (match_operand:SI             0 "register_operand" "=r")
2721         (unspec:SI [(match_operand:SI 1 "register_operand"  "r")]
2722                    UNSPEC_BUILTIN_REVW))]
2723   ""
2724   "revw\t%1, %0"
2725   [(set_attr "length" "3")]
2728 ;; Round to integer.
2729 (define_insn "lrintsf2"
2730   [(set (match_operand:SI             0 "register_operand"  "=r,r")
2731         (unspec:SI [(match_operand:SF 1 "rx_compare_operand" "r,Q")]
2732                    UNSPEC_BUILTIN_ROUND))
2733    (clobber (reg:CC CC_REG))]
2734   ""
2735   "round\t%1, %0"
2736   [(set_attr "timings" "22,44")   
2737    (set_attr "length" "3,5")]
2740 ;;---------- Control Registers ------------------------
2742 ;; Clear Processor Status Word
2743 (define_insn "clrpsw"
2744   [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i")]
2745               UNSPEC_BUILTIN_CLRPSW)
2746    (clobber (reg:CC CC_REG))]
2747   ""
2748   "clrpsw\t%F0"
2749   [(set_attr "length" "2")]
2752 ;; Set Processor Status Word
2753 (define_insn "setpsw"
2754   [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i")]
2755               UNSPEC_BUILTIN_SETPSW)
2756    (clobber (reg:CC CC_REG))]
2757   ""
2758   "setpsw\t%F0"
2759   [(set_attr "length" "2")]
2762 ;; Move from control register
2763 (define_insn "mvfc"
2764   [(set (match_operand:SI             0 "register_operand" "=r")
2765         (unspec_volatile:SI [(match_operand:SI 1 "immediate_operand" "i")]
2766                    UNSPEC_BUILTIN_MVFC))]
2767   ""
2768   "mvfc\t%C1, %0"
2769   [(set_attr "length" "3")]
2772 ;; Move to control register
2773 ;; This insn can be used in atomic sequences to restore the previous PSW
2774 ;; and re-enable interrupts.  Because of that it always clobbers the CC_REG.
2775 (define_insn "mvtc"
2776   [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i,i")
2777                (match_operand:SI 1 "nonmemory_operand" "r,i")]
2778               UNSPEC_BUILTIN_MVTC)
2779    (clobber (reg:CC CC_REG))]
2780   ""
2781   "mvtc\t%1, %C0"
2782   [(set_attr "length" "3,7")]
2785 ;; Move to interrupt priority level
2786 (define_insn "mvtipl"
2787   [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "Uint04")]
2788               UNSPEC_BUILTIN_MVTIPL)]
2789   ""
2790   "mvtipl\t%0"
2791   [(set_attr "length" "3")]
2794 ;;---------- Interrupts ------------------------
2796 ;; Break
2797 (define_insn "brk"
2798   [(unspec_volatile [(const_int 0)]
2799                     UNSPEC_BUILTIN_BRK)]
2800   ""
2801   "brk"
2802   [(set_attr "length" "1")
2803    (set_attr "timings" "66")]
2806 ;; Interrupt
2807 (define_insn "int"
2808   [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i")]
2809                        UNSPEC_BUILTIN_INT)]
2810   ""
2811   "int\t%0"
2812   [(set_attr "length" "3")]
2815 ;; Wait
2816 (define_insn "wait"
2817   [(unspec_volatile [(const_int 0)]
2818                     UNSPEC_BUILTIN_WAIT)]
2819   ""
2820   "wait"
2821   [(set_attr "length" "2")]
2824 ;;---------- CoProcessor Support ------------------------
2826 ;; FIXME: The instructions are currently commented out because
2827 ;; the bit patterns have not been finalized, so the assembler
2828 ;; does not support them.  Once they are decided and the assembler
2829 ;; supports them, enable the instructions here.
2831 ;; Move from co-processor register
2832 (define_insn "mvfcp"
2833   [(set (match_operand:SI             0 "register_operand" "=r")
2834         (unspec:SI [(match_operand:SI 1 "immediate_operand" "i")
2835                     (match_operand:SI 2 "immediate_operand" "i")]
2836                    UNSPEC_BUILTIN_MVFCP))]
2837   ""
2838   "; mvfcp\t%1, %0, %2"
2839   [(set_attr "length" "5")]
2842 ;;---------- Misc ------------------------
2844 ;; Required by cfglayout.c...
2845 (define_insn "nop"
2846   [(const_int 0)]
2847   ""
2848   "nop"
2849   [(set_attr "length" "1")]
2852 (define_expand "pid_addr"
2853   [(plus:SI (match_operand:SI 0)
2854             (const:SI (unspec:SI [(match_operand:SI 1)] UNSPEC_PID_ADDR)))]
2855   ""
2856   ""
2859 (define_insn "movdi"
2860   [(set (match_operand:DI 0 "nonimmediate_operand" "=rm")
2861         (match_operand:DI 1 "general_operand"      "rmi"))]
2862   "TARGET_ENABLE_LRA"
2863   { return rx_gen_move_template (operands, false); }
2864   [(set_attr "length" "16")
2865    (set_attr "timings" "22")]
2868 (define_insn "movdf"
2869   [(set (match_operand:DF 0 "nonimmediate_operand" "=rm")
2870         (match_operand:DF 1 "general_operand"      "rmi"))]
2871   "TARGET_ENABLE_LRA"
2872   { return rx_gen_move_template (operands, false); }
2873   [(set_attr "length" "16")
2874    (set_attr "timings" "22")]