OSDN Git Service

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