OSDN Git Service

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