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