diff gcc/config/rx/rx.md @ 55:77e2b8dfacca gcc-4.4.5

update it from 4.4.3 to 4.5.0
author ryoma <e075725@ie.u-ryukyu.ac.jp>
date Fri, 12 Feb 2010 23:39:51 +0900
parents
children b7f97abdc517
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gcc/config/rx/rx.md	Fri Feb 12 23:39:51 2010 +0900
@@ -0,0 +1,1794 @@
+;;  Machine Description for Renesas RX processors
+;;  Copyright (C) 2008, 2009 Free Software Foundation, Inc.
+;;  Contributed by Red Hat.
+
+;; This file is part of GCC.
+
+;; GCC is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3, or (at your option)
+;; any later version.
+
+;; GCC is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING3.  If not see
+;; <http://www.gnu.org/licenses/>.
+
+
+;; This code iterator allows all branch instructions to
+;; be generated from a single define_expand template.
+(define_code_iterator most_cond [eq ne gt ge lt le gtu geu ltu leu
+				 unordered ordered ])
+
+;; This code iterator is used for sign- and zero- extensions.
+(define_mode_iterator small_int_modes [(HI "") (QI "")])
+
+;; We do not handle DFmode here because it is either
+;; the same as SFmode, or if -m64bit-doubles is active
+;; then all operations on doubles have to be handled by
+;; library functions.
+(define_mode_iterator register_modes
+  [(SF "ALLOW_RX_FPU_INSNS") (SI "") (HI "") (QI "")])
+
+
+;; Used to map RX condition names to GCC
+;; condition names for builtin instructions.
+(define_code_iterator gcc_conds [eq ne gt ge lt le gtu geu ltu leu
+				unge unlt uneq ltgt])
+(define_code_attr rx_conds [(eq "eq") (ne "ne") (gt "gt") (ge "ge") (lt "lt")
+			    (le "le") (gtu "gtu") (geu "geu") (ltu "ltu")
+			    (leu "leu") (unge "pz") (unlt "n") (uneq "o")
+			    (ltgt "no")])
+
+(define_constants
+  [
+   (SP_REG 0)
+
+   (UNSPEC_LOW_REG         0)
+   (UNSPEC_HIGH_REG        1)
+
+   (UNSPEC_RTE             10)
+   (UNSPEC_RTFI            11)
+   (UNSPEC_NAKED           12)
+   
+   (UNSPEC_MOVSTR          20)
+   (UNSPEC_MOVMEM          21)
+   (UNSPEC_SETMEM          22)
+   (UNSPEC_STRLEN          23)
+   (UNSPEC_CMPSTRN         24)
+
+   (UNSPEC_BUILTIN_BRK     30)
+   (UNSPEC_BUILTIN_CLRPSW  31)
+   (UNSPEC_BUILTIN_INT     32)
+   (UNSPEC_BUILTIN_MACHI   33)
+   (UNSPEC_BUILTIN_MACLO   34)
+   (UNSPEC_BUILTIN_MULHI   35)
+   (UNSPEC_BUILTIN_MULLO   36)
+   (UNSPEC_BUILTIN_MVFACHI 37)
+   (UNSPEC_BUILTIN_MVFACMI 38)
+   (UNSPEC_BUILTIN_MVFC    39)
+   (UNSPEC_BUILTIN_MVFCP   40)
+   (UNSPEC_BUILTIN_MVTACHI 41)
+   (UNSPEC_BUILTIN_MVTACLO 42)
+   (UNSPEC_BUILTIN_MVTC    43)
+   (UNSPEC_BUILTIN_MVTIPL  44)
+   (UNSPEC_BUILTIN_RACW	   45)
+   (UNSPEC_BUILTIN_REVW    46)
+   (UNSPEC_BUILTIN_RMPA	   47)
+   (UNSPEC_BUILTIN_ROUND   48)
+   (UNSPEC_BUILTIN_SAT     49)
+   (UNSPEC_BUILTIN_SETPSW  50)
+   (UNSPEC_BUILTIN_WAIT	   51)
+  ]
+)
+
+;; Condition code settings:
+;;   none     - insn does not affect the condition code bits
+;;   set_zs   - insn sets z,s to usable values;
+;;   set_zso  - insn sets z,s,o to usable values;
+;;   set_zsoc - insn sets z,s,o,c to usable values;
+;;   clobber  - value of cc0 is unknown
+(define_attr "cc" "none,set_zs,set_zso,set_zsoc,clobber" (const_string "none"))
+
+(define_attr "length" "" (const_int 8))
+
+(include "predicates.md")
+(include "constraints.md")
+
+;; Pipeline description.
+
+;; The RX only has a single pipeline.  It has five stages (fetch,
+;; decode, execute, memory access, writeback) each of which normally
+;; takes a single CPU clock cycle.
+
+;; The timings attribute consists of two numbers, the first is the
+;; throughput, which is the number of cycles the instruction takes
+;; to execute and generate a result.  The second is the latency
+;; which is the effective number of cycles the instruction takes to
+;; execute if its result is used by the following instruction.  The
+;; latency is always greater than or equal to the throughput.
+;; These values were taken from tables 2.13 and 2.14 in section 2.8
+;; of the RX610 Group Hardware Manual v0.11
+
+;; Note - it would be nice to use strings rather than integers for
+;; the possible values of this attribute, so that we can have the
+;; gcc build mechanism check for values that are not supported by
+;; the reservations below.  But this will not work because the code
+;; in rx_adjust_sched_cost() needs integers not strings.
+
+(define_attr "timings" "" (const_int 11))
+
+(define_automaton "pipelining")
+(define_cpu_unit "throughput" "pipelining")
+
+(define_insn_reservation "throughput__1_latency__1"  1
+  (eq_attr "timings" "11") "throughput")
+(define_insn_reservation "throughput__1_latency__2"  2
+  (eq_attr "timings" "12") "throughput,nothing")
+(define_insn_reservation "throughput__2_latency__2"  1
+  (eq_attr "timings" "22") "throughput*2")
+(define_insn_reservation "throughput__3_latency__3"  1
+  (eq_attr "timings" "33") "throughput*3")
+(define_insn_reservation "throughput__3_latency__4"  2
+  (eq_attr "timings" "34") "throughput*3,nothing")
+(define_insn_reservation "throughput__4_latency__4"  1
+  (eq_attr "timings" "44") "throughput*4")
+(define_insn_reservation "throughput__4_latency__5"  2
+  (eq_attr "timings" "45") "throughput*4,nothing")
+(define_insn_reservation "throughput__5_latency__5"  1
+  (eq_attr "timings" "55") "throughput*5")
+(define_insn_reservation "throughput__5_latency__6"  2
+  (eq_attr "timings" "56") "throughput*5,nothing")
+(define_insn_reservation "throughput__6_latency__6"  1
+  (eq_attr "timings" "66") "throughput*6")
+(define_insn_reservation "throughput_10_latency_10"  1
+  (eq_attr "timings" "1010") "throughput*10")
+(define_insn_reservation "throughput_11_latency_11"  1
+  (eq_attr "timings" "1111") "throughput*11")
+(define_insn_reservation "throughput_16_latency_16"  1
+  (eq_attr "timings" "1616") "throughput*16")
+(define_insn_reservation "throughput_18_latency_18"  1
+  (eq_attr "timings" "1818") "throughput*18")
+
+;; Comparisons
+
+(define_expand "cbranchsi4"
+  [(set (cc0) (compare:CC (match_operand:SI 1 "register_operand")
+			  (match_operand:SI 2 "rx_source_operand")))
+   (set (pc)
+	(if_then_else (match_operator:SI  0 "comparison_operator"
+					  [(cc0) (const_int 0)])
+		      (label_ref (match_operand 3 ""))
+		      (pc)))]
+  ""
+  ""
+)
+
+(define_expand "cbranchsf4"
+  [(set (cc0) (compare:CC (match_operand:SF 1 "register_operand")
+			  (match_operand:SF 2 "rx_source_operand")))
+   (set (pc)
+	(if_then_else (match_operator:SI  0 "comparison_operator"
+					  [(cc0) (const_int 0)])
+		      (label_ref (match_operand 3 ""))
+		      (pc)))]
+  "ALLOW_RX_FPU_INSNS && ! flag_non_call_exceptions"
+  ""
+)
+
+;; The TST instruction is not used as it does not set the Carry flag,
+;; so for example, the LessThan comparison cannot be tested.
+;;
+;; (define_insn "tstsi"
+;;   [(set (cc0)
+;;         (match_operand:SI 0 "rx_source_operand"  "r,i,Q")))]
+;;   ""
+;;   {
+;;     rx_float_compare_mode = false;
+;;     return "tst\t%Q0";
+;;   }
+;;   [(set_attr "cc" "set_zs")
+;;    (set_attr "timings" "11,11,33")
+;;    (set_attr "length" "3,7,6")]
+;; )
+
+(define_insn "cmpsi"
+  [(set (cc0) (compare:CC
+	       (match_operand:SI 0 "register_operand"  "r,r,r,r,r,r,r")
+	       (match_operand:SI 1 "rx_source_operand"
+				 "r,Uint04,Int08,Sint16,Sint24,i,Q")))]
+  ""
+  {
+    rx_float_compare_mode = false;
+    return "cmp\t%Q1, %Q0";
+  }
+  [(set_attr "cc" "set_zsoc")
+   (set_attr "timings" "11,11,11,11,11,11,33")
+   (set_attr "length"  "2,2,3,4,5,6,5")]
+)
+
+;; This pattern is disabled when -fnon-call-exceptions is active because
+;; it could generate a floating point exception, which would introduce an
+;; edge into the flow graph between this insn and the conditional branch
+;; insn to follow, thus breaking the cc0 relationship.  Run the g++ test
+;; g++.dg/eh/080514-1.C to see this happen.
+(define_insn "cmpsf"
+  [(set (cc0)
+	(compare:CC (match_operand:SF 0 "register_operand"  "r,r,r")
+		    (match_operand:SF 1 "rx_source_operand" "r,i,Q")))]
+  "ALLOW_RX_FPU_INSNS && ! flag_non_call_exceptions"
+  {
+    rx_float_compare_mode = true;
+    return "fcmp\t%1, %0";
+  }
+  [(set_attr "cc" "set_zso")
+   (set_attr "timings" "11,11,33")
+   (set_attr "length" "3,7,5")]
+)
+
+;; Flow Control Instructions:
+
+(define_expand "b<code>"
+  [(set (pc)
+        (if_then_else (most_cond (cc0) (const_int 0))
+                      (label_ref (match_operand 0))
+                      (pc)))]
+  ""
+  ""
+)
+
+(define_insn "*conditional_branch"
+  [(set (pc)
+	(if_then_else (match_operator           1 "comparison_operator"
+						[(cc0) (const_int 0)])
+		      (label_ref (match_operand 0 "" ""))
+		      (pc)))]
+  ""
+  {
+    return rx_gen_cond_branch_template (operands[1], false);
+  }
+  [(set_attr "length" "8")    ;; This length is wrong, but it is
+                              ;; too hard to compute statically.
+   (set_attr "timings" "33")  ;; The timing assumes that the branch is taken.
+   (set_attr "cc" "clobber")] ;; FIXME: This clobber is wrong.
+)
+
+(define_insn "*reveresed_conditional_branch"
+  [(set (pc)
+	(if_then_else (match_operator 1 "comparison_operator"
+				      [(cc0) (const_int 0)])
+		      (pc)
+		      (label_ref (match_operand 0 "" ""))))]
+  ""
+  {
+    return rx_gen_cond_branch_template (operands[1], true);
+  }
+  [(set_attr "length" "8")    ;; This length is wrong, but it is
+                              ;; too hard to compute statically.
+   (set_attr "timings" "33")  ;; The timing assumes that the branch is taken.
+   (set_attr "cc" "clobber")] ;; FIXME: This clobber is wrong.
+)
+
+(define_insn "jump"
+  [(set (pc) (label_ref (match_operand 0 "" "")))]
+  ""
+  "bra\t%0"
+  [(set_attr "length" "4")
+   (set_attr "timings" "33")
+   (set_attr "cc" "clobber")] ;; FIXME: This clobber is wrong.
+)
+
+(define_insn "indirect_jump"
+  [(set (pc) (match_operand:SI 0 "register_operand" "r"))]
+  ""
+  "jmp\t%0"
+  [(set_attr "length" "2")
+   (set_attr "timings" "33")
+   (set_attr "cc" "clobber")] ;; FIXME: This clobber is wrong.
+)
+
+(define_insn "tablejump"
+  [(set (pc) (match_operand:SI     0 "register_operand" "r"))
+   (use (label_ref (match_operand  1 "" "")))]
+  ""
+  { return flag_pic ? (TARGET_AS100_SYNTAX ? "\n?:\tbra\t%0"
+					   : "\n1:\tbra\t%0")
+	                                   : "jmp\t%0";
+  }
+  [(set_attr "cc" "clobber") ;; FIXME: This clobber is wrong.
+   (set_attr "timings" "33")
+   (set_attr "length" "2")]
+)
+
+(define_insn "simple_return"
+  [(return)]
+  ""
+  "rts"
+  [(set_attr "length" "1")
+   (set_attr "timings" "55")]
+)
+
+(define_insn "deallocate_and_return"
+  [(set (reg:SI SP_REG)
+	(plus:SI (reg:SI SP_REG)
+		 (match_operand:SI 0 "immediate_operand" "i")))
+   (return)]
+  ""
+  "rtsd\t%0"
+  [(set_attr "length" "2")
+   (set_attr "timings" "55")]
+)
+
+(define_insn "pop_and_return"
+  [(match_parallel                    1 "rx_rtsd_vector"
+		   [(set:SI (reg:SI SP_REG)
+			    (plus:SI (reg:SI SP_REG)
+				     (match_operand:SI
+				      0 "const_int_operand" "n")))])]
+  "reload_completed"
+  {
+    rx_emit_stack_popm (operands, false);
+    return "";
+  }
+  [(set_attr "length" "3")
+   (set_attr "timings" "56")]
+)
+
+(define_insn "fast_interrupt_return"
+  [(unspec_volatile [(return)] UNSPEC_RTFI) ]
+  ""
+  "rtfi"
+  [(set_attr "length" "2")
+   (set_attr "timings" "33")]
+)
+
+(define_insn "exception_return"
+  [(unspec_volatile [(return)] UNSPEC_RTE) ]
+  ""
+  "rte"
+  [(set_attr "length" "2")
+   (set_attr "timings" "66")]
+)
+
+(define_insn "naked_return"
+  [(unspec_volatile [(return)] UNSPEC_NAKED) ]
+  ""
+  "; Naked function: epilogue provided by programmer."
+)
+
+
+;; Note - the following set of patterns do not use the "memory_operand"
+;; predicate or an "m" constraint because we do not allow symbol_refs
+;; or label_refs as legitmate memory addresses.  This matches the
+;; behaviour of most of the RX instructions.  Only the call/branch
+;; instructions are allowed to refer to symbols/labels directly.
+;; The call operands are in QImode because that is the value of
+;; FUNCTION_MODE
+
+(define_expand "call"
+  [(call (match_operand:QI 0 "general_operand")
+	 (match_operand:SI 1 "general_operand"))]
+  ""
+  {
+    rtx dest = XEXP (operands[0], 0);
+
+    if (! rx_call_operand (dest, Pmode))
+      dest = force_reg (Pmode, dest);
+    emit_call_insn (gen_call_internal (dest, operands[1]));
+    DONE;
+  }
+)
+
+(define_insn "call_internal"
+  [(call (mem:QI (match_operand:SI 0 "rx_call_operand" "r,Symbol"))
+	 (match_operand:SI         1 "general_operand" "g,g"))]
+  ""
+  "@
+  jsr\t%0
+  bsr\t%A0"
+  [(set_attr "length" "2,4")
+   (set_attr "timings" "33")]
+)
+
+(define_expand "call_value"
+  [(set (match_operand          0 "register_operand")
+	(call (match_operand:QI 1 "general_operand")
+	      (match_operand:SI 2 "general_operand")))]
+  ""
+  {
+    rtx dest = XEXP (operands[1], 0);
+
+    if (! rx_call_operand (dest, Pmode))
+      dest = force_reg (Pmode, dest);
+    emit_call_insn (gen_call_value_internal (operands[0], dest, operands[2]));
+    DONE;
+  }
+)
+
+(define_insn "call_value_internal"
+  [(set (match_operand                  0 "register_operand" "=r,r")
+	(call (mem:QI (match_operand:SI 1 "rx_call_operand"   "r,Symbol"))
+	      (match_operand:SI         2 "general_operand"   "g,g")))]
+  ""
+  "@
+  jsr\t%1
+  bsr\t%A1"
+  [(set_attr "length" "2,4")
+   (set_attr "timings" "33")]
+)
+
+;; Note - we do not allow indirect sibcalls (with the address
+;; held in a register) because we cannot guarantee that the register
+;; chosen will be a call-used one.  If it is a call-saved register,
+;; then the epilogue code will corrupt it by popping the saved value
+;; off of the stack.
+(define_expand "sibcall"
+  [(parallel
+    [(call (mem:QI (match_operand:SI 0 "rx_symbolic_call_operand"))
+	   (match_operand:SI         1 "general_operand"))
+     (return)])]
+  ""
+  {
+    if (MEM_P (operands[0]))
+      operands[0] = XEXP (operands[0], 0);
+  }
+)
+
+(define_insn "sibcall_internal"
+  [(call (mem:QI (match_operand:SI 0 "rx_symbolic_call_operand" "Symbol"))
+	 (match_operand:SI         1 "general_operand"          "g"))
+   (return)]
+  ""
+  "bra\t%A0"
+  [(set_attr "length"  "4")
+   (set_attr "timings" "33")]
+)
+
+(define_expand "sibcall_value"
+ [(parallel
+   [(set (match_operand                  0 "register_operand")
+	 (call (mem:QI (match_operand:SI 1 "rx_symbolic_call_operand"))
+	       (match_operand:SI         2 "general_operand")))
+    (return)])]
+  ""
+  {
+    if (MEM_P (operands[1]))
+      operands[1] = XEXP (operands[1], 0);
+  }
+)
+
+(define_insn "sibcall_value_internal"
+ [(set (match_operand                  0 "register_operand"         "=r")
+       (call (mem:QI (match_operand:SI 1 "rx_symbolic_call_operand" "Symbol"))
+	     (match_operand:SI         2 "general_operand"          "g")))
+  (return)]
+  ""
+  "bra\t%A1"
+  [(set_attr "length"  "4")
+   (set_attr "timings" "33")]
+)
+
+;; Function Prologue/Epilogue Instructions
+
+(define_expand "prologue"
+  [(const_int 0)]
+  ""
+  "rx_expand_prologue (); DONE;"
+)
+
+(define_expand "epilogue"
+  [(return)]
+  ""
+  "rx_expand_epilogue (false); DONE;"
+)
+
+(define_expand "sibcall_epilogue"
+  [(return)]
+  ""
+  "rx_expand_epilogue (true); DONE;"
+)
+
+;; Move Instructions
+
+;; Note - we do not allow memory to memory moves, even though the ISA
+;; supports them.  The reason is that the conditions on such moves are
+;; too restrictive, specifically the source addressing mode is limited
+;; by the destination addressing mode and vice versa.  (For example it
+;; is not possible to use indexed register indirect addressing for one
+;; of the operands if the other operand is anything other than a register,
+;; but it is possible to use register relative addressing when the other
+;; operand also uses register relative or register indirect addressing).
+;;
+;; GCC does not support computing legitimate addresses based on the
+;; nature of other operands involved in the instruction, and reload is
+;; not smart enough to cope with a whole variety of different memory
+;; addressing constraints, so it is simpler and safer to just refuse
+;; to support memory to memory moves.
+
+(define_expand "mov<register_modes:mode>"
+  [(set (match_operand:register_modes 0 "general_operand")
+	(match_operand:register_modes 1 "general_operand"))]
+  ""
+  {
+    if (MEM_P (operand0) && MEM_P (operand1))
+      operands[1] = copy_to_mode_reg (<register_modes:MODE>mode, operand1);
+  }
+)
+
+(define_insn "*mov<register_modes:mode>_internal"
+  [(set (match_operand:register_modes
+	 0 "nonimmediate_operand" "=r,r,r,r,r,r,m,Q,Q,Q,Q")
+	(match_operand:register_modes
+	 1 "general_operand" "Int08,Sint16,Sint24,i,r,m,r,Int08,Sint16,Sint24,i"))]
+  ""
+  { return rx_gen_move_template (operands, false); }
+  [(set_attr "length" "3,4,5,6,2,4,6,5,6,7,8")
+   (set_attr "timings" "11,11,11,11,11,12,11,11,11,11,11")]
+)
+
+(define_insn "extend<small_int_modes:mode>si2"
+  [(set (match_operand:SI 0 "register_operand"    "=r,r")
+        (sign_extend:SI (match_operand:small_int_modes
+			  1 "nonimmediate_operand" "r,m")))]
+  ""
+  { return rx_gen_move_template (operands, false); }
+  [(set_attr "length" "2,6")
+   (set_attr "timings" "11,12")]
+)
+
+(define_insn "zero_extend<small_int_modes:mode>si2"
+  [(set (match_operand:SI 0 "register_operand"     "=r,r")
+        (zero_extend:SI (match_operand:small_int_modes
+			  1 "nonimmediate_operand"  "r,m")))]
+  ""
+  { return rx_gen_move_template (operands, true); }
+  [(set_attr "length" "2,4")
+   (set_attr "timings" "11,12")]
+)
+
+(define_insn "stack_push"
+  [(set:SI (reg:SI SP_REG)
+	   (minus:SI (reg:SI SP_REG)
+		     (const_int 4)))
+   (set:SI (mem:SI (reg:SI SP_REG))
+	   (match_operand:SI 0 "register_operand" "r"))]
+  ""
+  "push.l\t%0"
+  [(set_attr "length" "2")]
+)
+
+(define_insn "stack_pushm"
+  [(match_parallel                     1 "rx_store_multiple_vector"
+		   [(set:SI (reg:SI SP_REG)
+			    (minus:SI (reg:SI SP_REG)
+				      (match_operand:SI
+				       0 "const_int_operand" "n")))])]
+  "reload_completed"
+  {
+    rx_emit_stack_pushm (operands);
+    return "";
+  }
+  [(set_attr "length" "2")
+   (set_attr "timings" "44")] ;; The timing is a guesstimate average timing.
+)
+
+(define_insn "stack_pop"
+  [(set:SI (match_operand:SI 0 "register_operand" "=r")
+	   (mem:SI (reg:SI SP_REG)))
+   (set:SI (reg:SI SP_REG)
+	   (plus:SI (reg:SI SP_REG)
+		    (const_int 4)))]
+  ""
+  "pop\t%0"
+  [(set_attr "length" "2")
+   (set_attr "timings" "12")]
+)
+
+(define_insn "stack_popm"
+  [(match_parallel                     1 "rx_load_multiple_vector"
+		   [(set:SI (reg:SI SP_REG)
+			    (plus:SI (reg:SI SP_REG)
+				     (match_operand:SI
+				      0 "const_int_operand" "n")))])]
+  "reload_completed"
+  {
+    rx_emit_stack_popm (operands, true);
+    return "";
+  }
+  [(set_attr "length" "2")
+   (set_attr "timings" "45")] ;; The timing is a guesstimate average timing.
+)
+
+(define_insn "cstoresi4"
+  [(set (match_operand:SI  0 "register_operand" "=r,r,r,r,r,r,r")
+	(match_operator:SI
+	 1 "comparison_operator"
+	 [(match_operand:SI
+	   2 "register_operand"  "r,r,r,r,r,r,r")
+	  (match_operand:SI
+	   3 "rx_source_operand" "r,Uint04,Int08,Sint16,Sint24,i,Q")]))]
+  ""
+  {
+    rx_float_compare_mode = false;
+    return "cmp\t%Q3, %Q2\n\tsc%B1.L\t%0";
+  }
+  [(set_attr "cc" "set_zsoc")
+   (set_attr "timings" "22,22,22,22,22,22,44")
+   (set_attr "length"  "5,5,6,7,8,9,8")]
+)
+
+(define_expand "movsicc"
+  [(set (match_operand:SI                   0 "register_operand")
+        (if_then_else:SI (match_operand:SI 1 "comparison_operator")
+			 (match_operand:SI  2 "nonmemory_operand")
+			 (match_operand:SI  3 "immediate_operand")))]
+  ""
+  {
+    if (GET_CODE (operands[1]) != EQ && GET_CODE (operands[1]) != NE)
+      FAIL;
+    if (! CONST_INT_P (operands[3]))
+      FAIL;
+  }
+)
+
+(define_insn "*movsieq"
+  [(set (match_operand:SI     0 "register_operand" "=r,r,r")
+	(if_then_else:SI (eq (match_operand:SI
+			      3 "register_operand"  "r,r,r")
+			     (match_operand:SI
+			      4 "rx_source_operand" "riQ,riQ,riQ"))
+			 (match_operand:SI
+			  1 "nonmemory_operand"     "0,i,r")
+			 (match_operand:SI
+			  2 "immediate_operand"     "i,i,i")))]
+  ""
+  "@
+  cmp\t%Q4, %Q3\n\tstnz\t%2, %0
+  cmp\t%Q4, %Q3\n\tmov.l\t%2, %0\n\tstz\t%1, %0
+  cmp\t%Q4, %Q3\n\tmov.l\t%1, %0\n\tstnz\t%2, %0"
+  [(set_attr "cc"      "set_zsoc")
+   (set_attr "length"  "13,19,15")
+   (set_attr "timings" "22,33,33")]
+)
+
+(define_insn "*movsine"
+  [(set (match_operand:SI                      0 "register_operand" "=r,r,r")
+	(if_then_else:SI (ne (match_operand:SI 3 "register_operand"  "r,r,r")
+			     (match_operand:SI 4 "rx_source_operand" "riQ,riQ,riQ"))
+			 (match_operand:SI     1 "nonmemory_operand" "0,i,r")
+			 (match_operand:SI     2 "immediate_operand" "i,i,i")))]
+  ""
+  "@
+  cmp\t%Q4, %Q3\n\tstz\t%2, %0
+  cmp\t%Q4, %Q3\n\tmov.l\t%2, %0\n\tstnz\t%1, %0
+  cmp\t%Q4, %Q3\n\tmov.l\t%1, %0\n\tstz\t%2, %0"
+  [(set_attr "cc"      "set_zsoc")
+   (set_attr "length"  "13,19,15")
+   (set_attr "timings" "22,33,33")]
+)
+
+;; Arithmetic Instructions
+
+(define_insn "abssi2"
+  [(set (match_operand:SI         0 "register_operand" "=r,r")
+        (abs:SI (match_operand:SI 1 "register_operand"  "0,r")))]
+  ""
+  "@
+  abs\t%0
+  abs\t%1, %0"
+  [(set_attr "cc" "set_zso")
+   (set_attr "length" "2,3")]
+)
+
+(define_insn "addsi3"
+  [(set (match_operand:SI 0 "register_operand"
+			  "=r,r,r,r,r,r,r,r,r,r,r,r")
+	(plus:SI (match_operand:SI
+		  1 "register_operand"
+		  "%0,0,0,0,0,0,r,r,r,r,r,0")
+		 (match_operand:SI
+		  2 "rx_source_operand"
+		  "r,Uint04,Sint08,Sint16,Sint24,i,r,Sint08,Sint16,Sint24,i,Q")))]
+  ""
+  "@
+  add\t%2, %0
+  add\t%2, %0
+  add\t%2, %0
+  add\t%2, %0
+  add\t%2, %0
+  add\t%2, %0
+  add\t%2, %1, %0
+  add\t%2, %1, %0
+  add\t%2, %1, %0
+  add\t%2, %1, %0
+  add\t%2, %1, %0
+  add\t%Q2, %0"
+  [(set_attr "cc" "set_zsoc")
+   (set_attr "timings" "11,11,11,11,11,11,11,11,11,11,11,33")
+   (set_attr "length" "2,2,3,4,5,6,3,3,4,5,6,5")]
+)
+
+(define_insn "adddi3"
+  [(set (match_operand:DI          0 "register_operand" "=r,r,r,r,r,r")
+	(plus:DI (match_operand:DI 1 "register_operand" "%0,0,0,0,0,0")
+		 (match_operand:DI 2 "rx_source_operand"
+				   "r,Sint08,Sint16,Sint24,i,Q")))]
+  ""
+  "add\t%L2, %L0\n\tadc\t%H2, %H0"
+  [(set_attr "cc" "set_zsoc")
+   (set_attr "timings" "22,22,22,22,22,44")
+   (set_attr "length" "5,7,9,11,13,11")]
+)
+
+(define_insn "andsi3"
+  [(set (match_operand:SI         0 "register_operand"  "=r,r,r,r,r,r,r,r,r")
+	(and:SI (match_operand:SI 1 "register_operand"  "%0,0,0,0,0,0,r,0,Q")
+		(match_operand:SI
+		 2 "rx_source_operand"
+		 "r,Uint04,Sint08,Sint16,Sint24,i,r,Q,0")))]
+  ""
+  "@
+  and\t%2, %0
+  and\t%2, %0
+  and\t%2, %0
+  and\t%2, %0
+  and\t%2, %0
+  and\t%2, %0
+  and\t%2, %1, %0
+  and\t%Q2, %0
+  and\t%Q1, %0"
+  [(set_attr "cc" "set_zs")
+   (set_attr "timings" "11,11,11,11,11,11,11,33,33")
+   (set_attr "length" "2,2,3,4,5,6,3,5,5")]
+)
+
+;; Byte swap (single 32-bit value).
+(define_insn "bswapsi2"
+  [(set (match_operand:SI           0 "register_operand" "+r")
+	(bswap:SI (match_operand:SI 1 "register_operand"  "r")))]
+  ""
+  "revl\t%1, %0"
+  [(set_attr "length" "3")]
+)
+
+;; Byte swap (single 16-bit value).  Note - we ignore the swapping of the high 16-bits.
+(define_insn "bswaphi2"
+  [(set (match_operand:HI           0 "register_operand" "+r")
+	(bswap:HI (match_operand:HI 1 "register_operand"  "r")))]
+  ""
+  "revw\t%1, %0"
+  [(set_attr "length" "3")]
+)
+
+(define_insn "divsi3"
+  [(set (match_operand:SI         0 "register_operand" "=r,r,r,r,r,r")
+	(div:SI (match_operand:SI 1 "register_operand"  "0,0,0,0,0,0")
+		(match_operand:SI
+		 2 "rx_source_operand" "r,Sint08,Sint16,Sint24,i,Q")))]
+  ""
+  "div\t%Q2, %0"
+  [(set_attr "cc" "clobber")
+   (set_attr "timings" "1111") ;; Strictly speaking the timing should be
+                               ;; 2222, but that is a worst case sceanario.
+   (set_attr "length" "3,4,5,6,7,6")]
+)
+
+(define_insn "udivsi3"
+  [(set (match_operand:SI          0 "register_operand"  "=r,r,r,r,r,r")
+	(udiv:SI (match_operand:SI 1 "register_operand"   "0,0,0,0,0,0")
+		 (match_operand:SI
+		  2 "rx_source_operand"  "r,Sint08,Sint16,Sint24,i,Q")))]
+  ""
+  "divu\t%Q2, %0"
+  [(set_attr "cc" "clobber")
+   (set_attr "timings" "1010") ;; Strictly speaking the timing should be
+                               ;; 2020, but that is a worst case sceanario.
+   (set_attr "length" "3,4,5,6,7,6")]
+)
+
+;; Note - these patterns are suppressed in big-endian mode because they
+;; generate a little endian result.  ie the most significant word of the
+;; result is placed in the higher numbered register of the destination
+;; register pair.
+
+(define_insn "mulsidi3"
+  [(set (match_operand:DI          0 "register_operand"  "=r,r,r,r,r,r")
+        (mult:DI (sign_extend:DI (match_operand:SI
+				  1 "register_operand"  "%0,0,0,0,0,0"))
+                 (sign_extend:DI (match_operand:SI
+				  2 "rx_source_operand"
+				  "r,Sint08,Sint16,Sint24,i,Q"))))]
+  "! TARGET_BIG_ENDIAN_DATA"
+  "@
+  emul\t%Q2, %0
+  emul\t%Q2, %0
+  emul\t%Q2, %0
+  emul\t%Q2, %0
+  emul\t%Q2, %0
+  emul\t%Q2, %0"
+  [(set_attr "length" "3,4,5,6,7,6")   
+   (set_attr "timings" "22,22,22,22,22,44")]
+)
+
+;; See comment for mulsidi3.
+;; Note - the zero_extends are to distinguish this pattern from the
+;; mulsidi3 pattern.  Immediate mode addressing is not supported
+;; because gcc cannot handle the expression: (zero_extend (const_int)).
+(define_insn "umulsidi3"
+  [(set (match_operand:DI                          0 "register_operand"
+						   "=r,r")
+        (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand"
+						   "%0,0"))
+                 (zero_extend:DI (match_operand:SI 2 "rx_compare_operand"
+						   "r,Q"))))]
+  "! TARGET_BIG_ENDIAN_DATA"
+  "@
+  emulu\t%Q2, %0
+  emulu\t%Q2, %0"
+  [(set_attr "length" "3,6")
+   (set_attr "timings" "22,44")]
+)
+
+(define_insn "smaxsi3"
+  [(set (match_operand:SI          0 "register_operand" "=r,r,r,r,r,r")
+	(smax:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0")
+		 (match_operand:SI 2 "rx_source_operand"
+				   "r,Sint08,Sint16,Sint24,i,Q")))]
+  ""
+  "max\t%Q2, %0"
+  [(set_attr "length" "3,4,5,6,7,6")
+   (set_attr "timings" "11,11,11,11,11,33")]
+)
+
+(define_insn "sminsi3"
+  [(set (match_operand:SI          0 "register_operand" "=r,r,r,r,r,r,r")
+	(smin:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0,r")
+		 (match_operand:SI 2 "rx_source_operand"
+				   "r,Sint08,Sint16,Sint24,i,Q,r")))]
+  ""
+  "@
+  min\t%Q2, %0
+  min\t%Q2, %0
+  min\t%Q2, %0
+  min\t%Q2, %0
+  min\t%Q2, %0
+  min\t%Q2, %0
+  mov.l\t%1,%0\n\tmin\t%Q2, %0"
+  [(set_attr "length"  "3,4,5,6,7,6,5")
+   (set_attr "timings" "11,11,11,11,11,33,22")]
+)
+
+(define_insn "mulsi3"
+  [(set (match_operand:SI          0 "register_operand" "=r,r,r,r,r,r,r,r,r")
+        (mult:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0,0,Q,r")
+                 (match_operand:SI 2 "rx_source_operand"
+				   "r,Uint04,Sint08,Sint16,Sint24,i,Q,0,r")))]
+  ""
+  "@
+  mul\t%Q2, %0
+  mul\t%Q2, %0
+  mul\t%Q2, %0
+  mul\t%Q2, %0
+  mul\t%Q2, %0
+  mul\t%Q2, %0
+  mul\t%Q2, %0
+  mul\t%Q1, %0
+  mul\t%Q2, %1, %0"
+  [(set_attr "length"  "2,2,3,4,5,6,5,5,3")
+   (set_attr "timings" "11,11,11,11,11,11,33,33,11")]
+)
+
+(define_insn "negsi2"
+  [(set (match_operand:SI         0 "register_operand" "=r,r")
+        (neg:SI (match_operand:SI 1 "register_operand"  "0,r")))]
+  ;; The NEG instruction does not comply with -fwrapv semantics.
+  ;; See gcc.c-torture/execute/pr22493-1.c for an example of this.
+  "! flag_wrapv"
+  "@
+  neg\t%0
+  neg\t%1, %0"
+  [(set_attr "length" "2,3")]
+)
+
+(define_insn "one_cmplsi2"
+  [(set (match_operand:SI         0 "register_operand" "=r,r")
+	(not:SI (match_operand:SI 1 "register_operand"  "0,r")))]
+  ""
+  "@
+  not\t%0
+  not\t%1, %0"
+  [(set_attr "cc" "set_zs")
+   (set_attr "length" "2,3")]
+)
+
+(define_insn "iorsi3"
+  [(set (match_operand:SI         0 "register_operand" "=r,r,r,r,r,r,r,r,r")
+	(ior:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0,r,0,Q")
+	        (match_operand:SI 2 "rx_source_operand"
+				  "r,Uint04,Sint08,Sint16,Sint24,i,r,Q,0")))]
+  ""
+  "@
+  or\t%2, %0
+  or\t%2, %0
+  or\t%2, %0
+  or\t%2, %0
+  or\t%2, %0
+  or\t%2, %0
+  or\t%2, %1, %0
+  or\t%Q2, %0
+  or\t%Q1, %0"
+  [(set_attr "cc" "set_zs")
+   (set_attr "timings" "11,11,11,11,11,11,11,33,33")
+   (set_attr "length"  "2,2,3,4,5,6,3,5,5")]
+)
+
+(define_insn "rotlsi3"
+  [(set (match_operand:SI            0 "register_operand" "=r")
+	(rotate:SI (match_operand:SI 1 "register_operand"  "0")
+		   (match_operand:SI 2 "rx_shift_operand" "rn")))]
+  ""
+  "rotl\t%2, %0"
+  [(set_attr "cc" "set_zs")
+   (set_attr "length" "3")]
+)
+
+(define_insn "rotrsi3"
+  [(set (match_operand:SI              0 "register_operand" "=r")
+	(rotatert:SI (match_operand:SI 1 "register_operand"  "0")
+		     (match_operand:SI 2 "rx_shift_operand" "rn")))]
+  ""
+  "rotr\t%2, %0"
+  [(set_attr "cc" "set_zs")
+   (set_attr "length" "3")]
+)
+
+(define_insn "ashrsi3"
+  [(set (match_operand:SI              0 "register_operand" "=r,r,r")
+	(ashiftrt:SI (match_operand:SI 1 "register_operand"  "0,0,r")
+		     (match_operand:SI 2 "rx_shift_operand"  "r,n,n")))]
+  ""
+  "@
+  shar\t%2, %0
+  shar\t%2, %0
+  shar\t%2, %1, %0"
+  [(set_attr "cc" "set_zsoc")
+   (set_attr "length" "3,2,3")]
+)
+
+(define_insn "lshrsi3"
+  [(set (match_operand:SI              0 "register_operand" "=r,r,r")
+	(lshiftrt:SI (match_operand:SI 1 "register_operand"  "0,0,r")
+		     (match_operand:SI 2 "rx_shift_operand"  "r,n,n")))]
+  ""
+  "@
+  shlr\t%2, %0
+  shlr\t%2, %0
+  shlr\t%2, %1, %0"
+  [(set_attr "cc" "set_zsoc")
+   (set_attr "length" "3,2,3")]
+)
+
+(define_insn "ashlsi3"
+  [(set (match_operand:SI            0 "register_operand" "=r,r,r")
+	(ashift:SI (match_operand:SI 1 "register_operand"  "0,0,r")
+	           (match_operand:SI 2 "rx_shift_operand"  "r,n,n")))]
+  ""
+  "@
+  shll\t%2, %0
+  shll\t%2, %0
+  shll\t%2, %1, %0"
+  [(set_attr "cc" "set_zsoc")
+   (set_attr "length" "3,2,3")]
+)
+
+(define_insn "subsi3"
+  [(set (match_operand:SI           0 "register_operand" "=r,r,r,r,r")
+	(minus:SI (match_operand:SI 1 "register_operand"  "0,0,0,r,0")
+		  (match_operand:SI 2 "rx_source_operand" "r,Uint04,n,r,Q")))]
+  ""
+  "@
+  sub\t%2, %0
+  sub\t%2, %0
+  add\t%N2, %0
+  sub\t%2, %1, %0
+  sub\t%Q2, %0"
+  [(set_attr "cc" "set_zsoc")
+   (set_attr "timings" "11,11,11,11,33")
+   (set_attr "length" "2,2,6,3,5")]
+)
+
+(define_insn "subdi3"
+  [(set (match_operand:DI           0 "register_operand" "=r,r")
+	(minus:DI (match_operand:DI 1 "register_operand"  "0,0")
+		  (match_operand:DI 2 "rx_source_operand" "r,Q")))]
+  ""
+  "sub\t%L2, %L0\n\tsbb\t%H2, %H0"
+  [(set_attr "cc" "set_zsoc")
+   (set_attr "timings" "22,44")
+   (set_attr "length" "5,11")]
+)
+
+(define_insn "xorsi3"
+  [(set (match_operand:SI         0 "register_operand" "=r,r,r,r,r,r")
+	(xor:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0")
+	        (match_operand:SI 2 "rx_source_operand"
+				  "r,Sint08,Sint16,Sint24,i,Q")))]
+  ""
+  "@
+  xor\t%Q2, %0
+  xor\t%Q2, %0
+  xor\t%Q2, %0
+  xor\t%Q2, %0
+  xor\t%Q2, %0
+  xor\t%Q2, %0"
+  [(set_attr "cc" "set_zs")
+   (set_attr "timings" "11,11,11,11,11,33")
+   (set_attr "length" "3,4,5,6,7,6")]
+)
+
+;; Floating Point Instructions
+
+(define_insn "addsf3"
+  [(set (match_operand:SF          0 "register_operand"  "=r,r,r")
+	(plus:SF (match_operand:SF 1 "register_operand"  "%0,0,0")
+		 (match_operand:SF 2 "rx_source_operand"  "r,F,Q")))]
+  "ALLOW_RX_FPU_INSNS"
+  "@
+  fadd\t%2, %0
+  fadd\t%2, %0
+  fadd\t%2, %0"
+  [(set_attr "cc" "set_zs")
+   (set_attr "timings" "44,44,66")
+   (set_attr "length" "3,7,5")]
+)
+
+(define_insn "divsf3"
+  [(set (match_operand:SF         0 "register_operand" "=r,r,r")
+	(div:SF (match_operand:SF 1 "register_operand"  "0,0,0")
+		(match_operand:SF 2 "rx_source_operand" "r,F,Q")))]
+  "ALLOW_RX_FPU_INSNS"
+  "fdiv\t%2, %0"
+  [(set_attr "cc" "set_zs")
+   (set_attr "timings" "1616,1616,1818")
+   (set_attr "length" "3,7,5")]
+)
+
+(define_insn "mulsf3"
+  [(set (match_operand:SF          0 "register_operand" "=r,r,r")
+	(mult:SF (match_operand:SF 1 "register_operand" "%0,0,0")
+		(match_operand:SF  2 "rx_source_operand" "r,F,Q")))]
+  "ALLOW_RX_FPU_INSNS"
+  "@
+  fmul\t%2, %0
+  fmul\t%2, %0
+  fmul\t%2, %0"
+  [(set_attr "cc" "set_zs")
+   (set_attr "timings" "33,33,55")
+   (set_attr "length"  "3,7,5")]
+)
+
+(define_insn "subsf3"
+  [(set (match_operand:SF           0 "register_operand" "=r,r,r")
+	(minus:SF (match_operand:SF 1 "register_operand"  "0,0,0")
+		  (match_operand:SF 2 "rx_source_operand" "r,F,Q")))]
+  "ALLOW_RX_FPU_INSNS"
+  "fsub\t%2, %0"
+  [(set_attr "cc" "set_zs")
+   (set_attr "timings" "44,44,66")
+   (set_attr "length" "3,7,5")]
+)
+
+(define_insn "fix_truncsfsi2"
+  [(set (match_operand:SI         0 "register_operand"  "=r,r")
+	(fix:SI (match_operand:SF 1 "rx_compare_operand" "r,Q")))]
+  "ALLOW_RX_FPU_INSNS"
+  "ftoi\t%1, %0"
+  [(set_attr "cc" "set_zs")
+   (set_attr "timings" "22,44")
+   (set_attr "length" "3,5")]
+)
+
+(define_insn "floatsisf2"
+  [(set (match_operand:SF           0 "register_operand"  "=r,r")
+	(float:SF (match_operand:SI 1 "rx_compare_operand" "r,Q")))]
+  "ALLOW_RX_FPU_INSNS"
+  "itof\t%1, %0"
+  [(set_attr "cc" "set_zs")
+   (set_attr "timings" "22,44")
+   (set_attr "length" "3,6")]
+)
+
+;; Bit manipulation instructions.
+;; Note - there are two versions of each pattern because the memory
+;; accessing versions use QImode whilst the register accessing
+;; versions use SImode.
+;; The peephole are here because the combiner only looks at a maximum
+;; of three instructions at a time.
+
+(define_insn "bitset"
+  [(set:SI (match_operand:SI 0 "register_operand" "+r")
+	   (ior:SI (match_operand:SI 1 "register_operand" "0")
+		   (ashift:SI (const_int 1)
+			      (match_operand:SI 2 "nonmemory_operand" "ri"))))]
+  ""
+  "bset\t%2, %0"
+  [(set_attr "length" "3")]
+)
+
+(define_insn "bitset_in_memory"
+  [(set:QI (match_operand:QI 0 "memory_operand" "+m")
+	   (ior:QI (match_operand:QI 1 "memory_operand" "0")
+		   (ashift:QI (const_int 1)
+			      (match_operand:QI 2 "nonmemory_operand" "ri"))))]
+  ""
+  "bset\t%2, %0.B"
+  [(set_attr "length" "3")
+   (set_attr "timings" "34")]
+)
+
+;; (set (reg A) (const_int 1))
+;; (set (reg A) (ashift (reg A) (reg B)))
+;; (set (reg C) (ior (reg A) (reg C)))
+(define_peephole2
+  [(set:SI (match_operand:SI 0 "register_operand" "")
+	   (const_int 1))
+   (set:SI (match_dup 0)
+	   (ashift:SI (match_dup 0)
+		      (match_operand:SI 1 "register_operand" "")))
+   (set:SI (match_operand:SI 2 "register_operand" "")
+	   (ior:SI (match_dup 0)
+		   (match_dup 2)))]
+  "dead_or_set_p (insn, operands[0])"
+  [(set:SI (match_dup 2)
+	   (ior:SI (match_dup 2)
+		   (ashift:SI (const_int 1)
+			      (match_dup 1))))]
+)
+  
+;; (set (reg A) (const_int 1))
+;; (set (reg A) (ashift (reg A) (reg B)))
+;; (set (reg A) (ior (reg A) (reg C)))
+;; (set (reg C) (reg A)
+(define_peephole2
+  [(set:SI (match_operand:SI 0 "register_operand" "")
+	   (const_int 1))
+   (set:SI (match_dup 0)
+	   (ashift:SI (match_dup 0)
+		      (match_operand:SI 1 "register_operand" "")))
+   (set:SI (match_dup 0)
+	   (ior:SI (match_dup 0)
+		   (match_operand:SI 2 "register_operand" "")))
+   (set:SI (match_dup 2) (match_dup 0))]
+  "dead_or_set_p (insn, operands[0])"
+  [(set:SI (match_dup 2)
+	   (ior:SI (match_dup 2)
+		   (ashift:SI (const_int 1)
+			      (match_dup 1))))]
+)
+  
+(define_insn "bitinvert"
+  [(set:SI (match_operand:SI 0 "register_operand" "+r")
+	   (xor:SI (match_operand:SI 1 "register_operand" "0")
+		   (ashift:SI (const_int 1)
+			      (match_operand:SI 2 "nonmemory_operand" "ri"))))]
+  ""
+  "bnot\t%2, %0"
+  [(set_attr "length" "3")]
+)
+
+(define_insn "bitinvert_in_memory"
+  [(set:QI (match_operand:QI 0 "memory_operand" "+m")
+	   (xor:QI (match_operand:QI 1 "register_operand" "0")
+		   (ashift:QI (const_int 1)
+			      (match_operand:QI 2 "nonmemory_operand" "ri"))))]
+  ""
+  "bnot\t%2, %0.B"
+  [(set_attr "length" "5")
+   (set_attr "timings" "33")]
+)
+
+;; (set (reg A) (const_int 1))
+;; (set (reg A) (ashift (reg A) (reg B)))
+;; (set (reg C) (xor (reg A) (reg C)))
+(define_peephole2
+  [(set:SI (match_operand:SI 0 "register_operand" "")
+	   (const_int 1))
+   (set:SI (match_dup 0)
+	   (ashift:SI (match_dup 0)
+		      (match_operand:SI 1 "register_operand" "")))
+   (set:SI (match_operand:SI 2 "register_operand" "")
+	   (xor:SI (match_dup 0)
+		   (match_dup 2)))]
+  "dead_or_set_p (insn, operands[0])"
+  [(set:SI (match_dup 2)
+	   (xor:SI (match_dup 2)
+		   (ashift:SI (const_int 1)
+			      (match_dup 1))))]
+  ""
+)
+  
+;; (set (reg A) (const_int 1))
+;; (set (reg A) (ashift (reg A) (reg B)))
+;; (set (reg A) (xor (reg A) (reg C)))
+;; (set (reg C) (reg A))
+(define_peephole2
+  [(set:SI (match_operand:SI 0 "register_operand" "")
+	   (const_int 1))
+   (set:SI (match_dup 0)
+	   (ashift:SI (match_dup 0)
+		      (match_operand:SI 1 "register_operand" "")))
+   (set:SI (match_dup 0)
+	   (xor:SI (match_dup 0)
+		   (match_operand:SI 2 "register_operand" "")))
+   (set:SI (match_dup 2) (match_dup 0))]
+  "dead_or_set_p (insn, operands[0])"
+  [(set:SI (match_dup 2)
+	   (xor:SI (match_dup 2)
+		   (ashift:SI (const_int 1)
+			      (match_dup 1))))]
+  ""
+)
+
+(define_insn "bitclr"
+  [(set:SI (match_operand:SI 0 "register_operand" "+r")
+	   (and:SI (match_operand:SI 1 "register_operand" "0")
+		   (not:SI (ashift:SI (const_int 1)
+				      (match_operand:SI 2 "nonmemory_operand" "ri")))))]
+  ""
+  "bclr\t%2, %0"
+  [(set_attr "length" "3")]
+)
+
+(define_insn "bitclr_in_memory"
+  [(set:QI (match_operand:QI 0 "memory_operand" "+m")
+	   (and:QI (match_operand:QI 1 "memory_operand" "0")
+		   (not:QI (ashift:QI (const_int 1)
+				      (match_operand:QI 2 "nonmemory_operand" "ri")))))]
+  ""
+  "bclr\t%2, %0.B"
+  [(set_attr "length" "3")
+   (set_attr "timings" "34")]
+)
+
+;; (set (reg A) (const_int -2))
+;; (set (reg A) (rotate (reg A) (reg B)))
+;; (set (reg C) (and (reg A) (reg C)))
+(define_peephole2
+  [(set:SI (match_operand:SI 0 "register_operand" "")
+	   (const_int -2))
+   (set:SI (match_dup 0)
+	   (rotate:SI (match_dup 0)
+		      (match_operand:SI 1 "register_operand" "")))
+   (set:SI (match_operand:SI 2 "register_operand" "")
+	   (and:SI (match_dup 0)
+		   (match_dup 2)))]
+  "dead_or_set_p (insn, operands[0])"
+  [(set:SI (match_dup 2)
+	   (and:SI (match_dup 2)
+		   (not:SI (ashift:SI (const_int 1)
+				      (match_dup 1)))))]
+)
+  
+;; (set (reg A) (const_int -2))
+;; (set (reg A) (rotate (reg A) (reg B)))
+;; (set (reg A) (and (reg A) (reg C)))
+;; (set (reg C) (reg A)
+(define_peephole2
+  [(set:SI (match_operand:SI 0 "register_operand" "")
+	   (const_int -2))
+   (set:SI (match_dup 0)
+	   (rotate:SI (match_dup 0)
+		      (match_operand:SI 1 "register_operand" "")))
+   (set:SI (match_dup 0)
+	   (and:SI (match_dup 0)
+		   (match_operand:SI 2 "register_operand" "")))
+   (set:SI (match_dup 2) (match_dup 0))]
+  "dead_or_set_p (insn, operands[0])"
+  [(set:SI (match_dup 2)
+	   (and:SI (match_dup 2)
+		   (not:SI (ashift:SI (const_int 1)
+				      (match_dup 1)))))]
+)
+
+(define_expand "insv"
+  [(set:SI (zero_extract:SI (match_operand:SI
+			     0 "nonimmediate_operand") ;; Destination
+		            (match_operand
+			     1 "immediate_operand")    ;; # of bits to set
+			    (match_operand
+			     2 "immediate_operand"))   ;; Starting bit
+	   (match_operand
+	    3 "immediate_operand"))]  ;; Bits to insert
+  ""
+  {
+    if (rx_expand_insv (operands))
+      DONE;
+    FAIL;
+  }
+)   
+
+;; Atomic exchange operation.
+
+(define_insn "sync_lock_test_and_setsi"
+  [(set:SI (match_operand:SI 0 "register_operand"   "=r,r")
+	   (match_operand:SI 1 "rx_compare_operand" "=r,Q"))
+   (set:SI (match_dup 1)
+	   (match_operand:SI 2 "register_operand"    "0,0"))]
+  ""
+  "xchg\t%1, %0"
+  [(set_attr "length" "3,6")
+   (set_attr "timings" "22")]
+)
+
+;; Block move functions.
+
+(define_expand "movstr"
+  [(set:SI (match_operand:BLK 1 "memory_operand")    ;; Dest
+	   (match_operand:BLK 2 "memory_operand"))   ;; Source
+   (use (match_operand:SI     0 "register_operand")) ;; Updated Dest
+  ]
+  ""
+  {
+    rtx addr1 = gen_rtx_REG (SImode, 1);
+    rtx addr2 = gen_rtx_REG (SImode, 2);
+    rtx len   = gen_rtx_REG (SImode, 3);
+    rtx dest_copy = gen_reg_rtx (SImode);
+
+    emit_move_insn (len, GEN_INT (-1));
+    emit_move_insn (addr1, force_operand (XEXP (operands[1], 0), NULL_RTX));
+    emit_move_insn (addr2, force_operand (XEXP (operands[2], 0), NULL_RTX));
+    operands[1] = replace_equiv_address_nv (operands[1], addr1);
+    operands[2] = replace_equiv_address_nv (operands[2], addr2);
+    emit_move_insn (dest_copy, addr1);
+    emit_insn (gen_rx_movstr ());
+    emit_move_insn (len, GEN_INT (-1));
+    emit_insn (gen_rx_strend (operands[0], dest_copy));
+    DONE;
+  }
+)
+
+(define_insn "rx_movstr"
+  [(set:SI (mem:BLK (reg:SI 1))
+	   (mem:BLK (reg:SI 2)))
+   (unspec_volatile:BLK [(reg:SI 1) (reg:SI 2) (reg:SI 3)] UNSPEC_MOVSTR)
+   (clobber (reg:SI 1))
+   (clobber (reg:SI 2))
+   (clobber (reg:SI 3))
+  ]
+  ""
+  "smovu"
+  [(set_attr "length" "2")
+   (set_attr "timings" "1111")] ;; The timing is a guesstimate.
+)
+
+(define_insn "rx_strend"
+  [(set:SI (match_operand:SI                      0 "register_operand" "=r")
+	   (unspec_volatile:SI [(match_operand:SI 1 "register_operand"  "r")
+				(reg:SI 3)] UNSPEC_STRLEN))
+   (clobber (reg:SI 1))
+   (clobber (reg:SI 2))
+   (clobber (reg:SI 3))
+  ]
+  ""
+  "mov\t%1, r1\n\tmov\t#0, r2\n\tsuntil.b\n\tmov\tr1, %0\n\tsub\t#1, %0"
+  [(set_attr "length" "10")
+   (set_attr "cc" "clobber")
+   (set_attr "timings" "1111")] ;; The timing is a guesstimate.
+)
+
+(define_expand "movmemsi"
+  [(parallel
+    [(set (match_operand:BLK 0 "memory_operand")    ;; Dest
+	  (match_operand:BLK 1 "memory_operand"))   ;; Source
+     (use (match_operand:SI  2 "register_operand")) ;; Length in bytes
+     (match_operand          3 "immediate_operand") ;; Align
+     (unspec_volatile:BLK [(reg:SI 1) (reg:SI 2) (reg:SI 3)] UNSPEC_MOVMEM)]
+    )]
+  ""
+  {
+    rtx addr1 = gen_rtx_REG (SImode, 1);
+    rtx addr2 = gen_rtx_REG (SImode, 2);
+    rtx len   = gen_rtx_REG (SImode, 3);
+
+    if (REG_P (operands[0]) && (REGNO (operands[0]) == 2
+				      || REGNO (operands[0]) == 3))
+      FAIL;
+    if (REG_P (operands[1]) && (REGNO (operands[1]) == 1
+				      || REGNO (operands[1]) == 3))
+      FAIL;
+    if (REG_P (operands[2]) && (REGNO (operands[2]) == 1
+				      || REGNO (operands[2]) == 2))
+      FAIL;
+    emit_move_insn (addr1, force_operand (XEXP (operands[0], 0), NULL_RTX));
+    emit_move_insn (addr2, force_operand (XEXP (operands[1], 0), NULL_RTX));
+    emit_move_insn (len, force_operand (operands[2], NULL_RTX));
+    operands[0] = replace_equiv_address_nv (operands[0], addr1);
+    operands[1] = replace_equiv_address_nv (operands[1], addr2);
+    emit_insn (gen_rx_movmem ());
+    DONE;
+  }
+)
+
+(define_insn "rx_movmem"
+  [(set (mem:BLK (reg:SI 1))
+	(mem:BLK (reg:SI 2)))
+   (use (reg:SI 3))
+   (unspec_volatile:BLK [(reg:SI 1) (reg:SI 2) (reg:SI 3)] UNSPEC_MOVMEM)
+   (clobber (reg:SI 1))
+   (clobber (reg:SI 2))
+   (clobber (reg:SI 3))]
+  ""
+  "smovf"
+  [(set_attr "length" "2")
+   (set_attr "timings" "1111")] ;; The timing is a guesstimate.
+)
+
+(define_expand "setmemsi"
+  [(set (match_operand:BLK 0 "memory_operand")     ;; Dest
+        (match_operand:QI  2 "nonmemory_operand")) ;; Value
+   (use (match_operand:SI  1 "nonmemory_operand")) ;; Length
+   (match_operand          3 "immediate_operand")  ;; Align
+   (unspec_volatile:BLK [(reg:SI 1) (reg:SI 2) (reg:SI 3)] UNSPEC_SETMEM)]
+  ""
+  {
+    rtx addr = gen_rtx_REG (SImode, 1);
+    rtx val  = gen_rtx_REG (QImode, 2);
+    rtx len  = gen_rtx_REG (SImode, 3);
+
+    emit_move_insn (addr, force_operand (XEXP (operands[0], 0), NULL_RTX));
+    emit_move_insn (len, force_operand (operands[1], NULL_RTX));
+    emit_move_insn (val, operands[2]);
+    emit_insn (gen_rx_setmem ());
+    DONE;
+  }
+)
+
+(define_insn "rx_setmem"
+  [(set:BLK (mem:BLK (reg:SI 1)) (reg 2))
+   (unspec_volatile:BLK [(reg:SI 1) (reg:SI 2) (reg:SI 3)] UNSPEC_SETMEM)
+   (clobber (reg:SI 1))
+   (clobber (reg:SI 3))]
+  ""
+  "sstr.b"
+  [(set_attr "length" "2")
+   (set_attr "timings" "1111")] ;; The timing is a guesstimate.
+)
+
+(define_expand "cmpstrnsi"
+  [(set (match_operand:SI
+	 0 "register_operand") ;; Result
+	(unspec_volatile:SI [(match_operand:BLK
+			      1 "memory_operand") ;; String1
+			     (match_operand:BLK
+			      2 "memory_operand")] ;; String2
+			    UNSPEC_CMPSTRN))
+   (use (match_operand:SI
+	 3 "register_operand")) ;; Max Length
+   (match_operand:SI
+    4 "immediate_operand")] ;; Known Align
+  ""
+  {
+    rtx str1 = gen_rtx_REG (SImode, 1);
+    rtx str2 = gen_rtx_REG (SImode, 2);
+    rtx len  = gen_rtx_REG (SImode, 3);
+  
+    emit_move_insn (str1, force_operand (XEXP (operands[1], 0), NULL_RTX));
+    emit_move_insn (str2, force_operand (XEXP (operands[2], 0), NULL_RTX));
+    emit_move_insn (len, force_operand (operands[3], NULL_RTX));
+
+    emit_insn (gen_rx_cmpstrn (operands[0], operands[1], operands[2]));
+    DONE;
+  }
+)
+
+(define_expand "cmpstrsi"
+  [(set (match_operand:SI
+	 0 "register_operand") ;; Result
+	(unspec_volatile:SI [(match_operand:BLK
+			      1 "memory_operand")  ;; String1
+			     (match_operand:BLK
+			      2 "memory_operand")] ;; String2
+			    UNSPEC_CMPSTRN))
+   (match_operand:SI
+    3 "immediate_operand")] ;; Known Align
+  ""
+  {
+    rtx str1 = gen_rtx_REG (SImode, 1);
+    rtx str2 = gen_rtx_REG (SImode, 2);
+    rtx len  = gen_rtx_REG (SImode, 3);
+  
+    emit_move_insn (str1, force_reg (SImode, XEXP (operands[1], 0)));
+    emit_move_insn (str2, force_reg (SImode, XEXP (operands[2], 0)));
+    emit_move_insn (len, GEN_INT (-1));
+
+    emit_insn (gen_rx_cmpstrn (operands[0], operands[1], operands[2]));
+    DONE;
+  }
+)
+
+(define_insn "rx_cmpstrn"
+  [(set:SI (match_operand:SI 0 "register_operand" "=r")
+	   (unspec_volatile:SI [(reg:SI 1) (reg:SI 2) (reg:SI 3)]
+			       UNSPEC_CMPSTRN))
+   (use (match_operand:BLK   1 "memory_operand" "m"))
+   (use (match_operand:BLK   2 "memory_operand" "m"))
+   (clobber (reg:SI 1))
+   (clobber (reg:SI 2))
+   (clobber (reg:SI 3))]
+  ""
+  "scmpu		; Perform the string comparison
+   mov     #-1, %0      ; Set up -1 result (which cannot be created
+                        ; by the SC insn)
+   bnc	   ?+		; If Carry is not set skip over
+   scne.L  %0		; Set result based on Z flag
+?:              	
+"
+  [(set_attr "length" "9")
+   (set_attr "timings" "1111")] ;; The timing is a guesstimate.
+)
+
+;;   Builtin Functions
+;;
+;; GCC does not have the ability to generate the following instructions
+;; on its own so they are provided as builtins instead.  To use them from
+;; a program for example invoke them as __builtin_rx_<insn_name>.  For
+;; example:
+;;
+;;    int short_byte_swap (int arg) { return __builtin_rx_revw (arg); }
+
+;;---------- Accumulator Support ------------------------
+
+;; Multiply & Accumulate (high)
+(define_insn "machi"
+  [(unspec:SI [(match_operand:SI 0 "register_operand" "r")
+	       (match_operand:SI 1 "register_operand" "r")]
+	      UNSPEC_BUILTIN_MACHI)]
+  ""
+  "machi\t%0, %1"
+  [(set_attr "length" "3")]
+)
+
+;; Multiply & Accumulate (low)
+(define_insn "maclo"
+  [(unspec:SI [(match_operand:SI 0 "register_operand" "r")
+	       (match_operand:SI 1 "register_operand" "r")]
+	      UNSPEC_BUILTIN_MACLO)]
+  ""
+  "maclo\t%0, %1"
+  [(set_attr "length" "3")]
+)
+
+;; Multiply (high)
+(define_insn "mulhi"
+  [(unspec:SI [(match_operand:SI 0 "register_operand" "r")
+	       (match_operand:SI 1 "register_operand" "r")]
+	      UNSPEC_BUILTIN_MULHI)]
+  ""
+  "mulhi\t%0, %1"
+  [(set_attr "length" "3")]
+)
+
+;; Multiply (low)
+(define_insn "mullo"
+  [(unspec:SI [(match_operand:SI 0 "register_operand" "r")
+	       (match_operand:SI 1 "register_operand" "r")]
+	      UNSPEC_BUILTIN_MULLO)]
+  ""
+  "mullo\t%0, %1"
+  [(set_attr "length" "3")]
+)
+
+;; Move from Accumulator (high)
+(define_insn "mvfachi"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(unspec:SI [(const_int 0)]
+		   UNSPEC_BUILTIN_MVFACHI))]
+  ""
+  "mvfachi\t%0"
+  [(set_attr "length" "3")]
+)
+
+;; Move from Accumulator (middle)
+(define_insn "mvfacmi"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(unspec:SI [(const_int 0)]
+		   UNSPEC_BUILTIN_MVFACMI))]
+  ""
+  "mvfacmi\t%0"
+  [(set_attr "length" "3")]
+)
+
+;; Move to Accumulator (high)
+(define_insn "mvtachi"
+  [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")]
+		       UNSPEC_BUILTIN_MVTACHI)]
+  ""
+  "mvtachi\t%0"
+  [(set_attr "length" "3")]
+)
+
+;; Move to Accumulator (low)
+(define_insn "mvtaclo"
+  [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")]
+		       UNSPEC_BUILTIN_MVTACLO)]
+  ""
+  "mvtaclo\t%0"
+  [(set_attr "length" "3")]
+)
+
+;; Round Accumulator
+(define_insn "racw"
+  [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i")]
+		       UNSPEC_BUILTIN_RACW)]
+  ""
+  "racw\t%0"
+  [(set_attr "length" "3")]
+)
+
+;; Repeat multiply and accumulate
+(define_insn "rmpa"
+  [(unspec:SI [(const_int 0) (reg:SI 1) (reg:SI 2) (reg:SI 3)
+	       (reg:SI 4) (reg:SI 5) (reg:SI 6)]
+	      UNSPEC_BUILTIN_RMPA)
+  (clobber (reg:SI 1))
+  (clobber (reg:SI 2))
+  (clobber (reg:SI 3))]
+  ""
+  "rmpa"
+  [(set_attr "length" "2")
+   (set_attr "timings" "1010")]
+)
+
+;;---------- Arithmetic ------------------------
+
+;; Byte swap (two 16-bit values).
+(define_insn "revw"
+  [(set (match_operand:SI             0 "register_operand" "+r")
+	(unspec:SI [(match_operand:SI 1 "register_operand"  "r")]
+		   UNSPEC_BUILTIN_REVW))]
+  ""
+  "revw\t%1, %0"
+  [(set_attr "length" "3")]
+)
+
+;; Round to integer.
+(define_insn "lrintsf2"
+  [(set (match_operand:SI             0 "register_operand"  "=r,r")
+	(unspec:SI [(match_operand:SF 1 "rx_compare_operand" "r,Q")]
+		   UNSPEC_BUILTIN_ROUND))]
+  ""
+  "round\t%1, %0"
+  [(set_attr "cc" "set_zs")
+   (set_attr "timings" "22,44")   
+   (set_attr "length" "3,5")]
+)
+
+;; Saturate to 32-bits
+(define_insn "sat"
+  [(set (match_operand:SI             0 "register_operand" "=r")
+	(unspec:SI [(match_operand:SI 1 "register_operand"  "0")]
+		   UNSPEC_BUILTIN_SAT))]
+  ""
+  "sat\t%0"
+  [(set_attr "length" "2")]
+)
+
+;;---------- Control Registers ------------------------
+
+;; Clear Processor Status Word
+(define_insn "clrpsw"
+  [(unspec:SI [(match_operand:SI 0 "immediate_operand" "i")]
+	      UNSPEC_BUILTIN_CLRPSW)
+   (clobber (cc0))]
+  ""
+  "clrpsw\t%F0"
+  [(set_attr "length" "2")
+   (set_attr "cc" "clobber")]
+)
+
+;; Set Processor Status Word
+(define_insn "setpsw"
+  [(unspec:SI [(match_operand:SI 0 "immediate_operand" "i")]
+	      UNSPEC_BUILTIN_SETPSW)
+   (clobber (cc0))]
+  ""
+  "setpsw\t%F0"
+  [(set_attr "length" "2")
+   (set_attr "cc" "clobber")]
+)
+
+;; Move from control register
+(define_insn "mvfc"
+  [(set (match_operand:SI             0 "register_operand" "=r")
+	(unspec:SI [(match_operand:SI 1 "immediate_operand" "i")]
+		   UNSPEC_BUILTIN_MVFC))]
+  ""
+  "mvfc\t%C1, %0"
+  [(set_attr "length" "3")]
+)
+
+;; Move to control register
+(define_insn "mvtc"
+  [(unspec:SI [(match_operand:SI 0 "immediate_operand" "i,i")
+	       (match_operand:SI 1 "nonmemory_operand" "r,i")]
+	      UNSPEC_BUILTIN_MVTC)]
+  ""
+  "mvtc\t%1, %C0"
+  [(set_attr "length" "3,7")]
+  ;; Ignore possible clobbering of the comparison flags in the
+  ;; PSW register.  This is a cc0 target so any cc0 setting
+  ;; instruction will always be paired with a cc0 user, without
+  ;; the possibility of this instruction being placed in between
+  ;; them.
+)
+
+;; Move to interrupt priority level
+(define_insn "mvtipl"
+  [(unspec:SI [(match_operand:SI 0 "immediate_operand" "Uint04")]
+	      UNSPEC_BUILTIN_MVTIPL)]
+  ""
+  "mvtipl\t%0"
+  [(set_attr "length" "3")]
+)
+
+;;---------- Interrupts ------------------------
+
+;; Break
+(define_insn "brk"
+  [(unspec_volatile [(const_int 0)]
+		    UNSPEC_BUILTIN_BRK)]
+  ""
+  "brk"
+  [(set_attr "length" "1")
+   (set_attr "timings" "66")]
+)
+
+;; Interrupt
+(define_insn "int"
+  [(unspec_volatile:SI [(match_operand:SI 0 "immediate_operand" "i")]
+		       UNSPEC_BUILTIN_INT)]
+  ""
+  "int\t%0"
+  [(set_attr "length" "3")]
+)
+
+;; Wait
+(define_insn "wait"
+  [(unspec_volatile [(const_int 0)]
+		    UNSPEC_BUILTIN_WAIT)]
+  ""
+  "wait"
+  [(set_attr "length" "2")]
+)
+
+;;---------- CoProcessor Support ------------------------
+
+;; FIXME: The instructions are currently commented out because
+;; the bit patterns have not been finalized, so the assembler
+;; does not support them.  Once they are decided and the assembler
+;; supports them, enable the instructions here.
+
+;; Move from co-processor register
+(define_insn "mvfcp"
+  [(set (match_operand:SI             0 "register_operand" "=r")
+	(unspec:SI [(match_operand:SI 1 "immediate_operand" "i")
+		    (match_operand:SI 2 "immediate_operand" "i")]
+		   UNSPEC_BUILTIN_MVFCP))]
+  ""
+  "; mvfcp\t%1, %0, %2"
+  [(set_attr "length" "5")]
+)
+
+;;---------- Misc ------------------------
+
+;; Required by cfglayout.c...
+(define_insn "nop"
+  [(const_int 0)]
+  ""
+  "nop"
+  [(set_attr "length" "1")]
+)