Initial revision
authorTorbjorn Granlund <tege@gnu.org>
Sat, 14 Mar 1992 05:15:35 +0000 (05:15 +0000)
committerTorbjorn Granlund <tege@gnu.org>
Sat, 14 Mar 1992 05:15:35 +0000 (05:15 +0000)
From-SVN: r474

gcc/config/gmicro/gmicro.md [new file with mode: 0644]

diff --git a/gcc/config/gmicro/gmicro.md b/gcc/config/gmicro/gmicro.md
new file mode 100644 (file)
index 0000000..deb929a
--- /dev/null
@@ -0,0 +1,2660 @@
+;;- Machine description for GNU compiler
+;;- Fujitsu Gmicro Version
+;;- Ported by M.Yuhara, Fujitsu Laboratories LTD.
+;;
+;;   Copyright (C) 1990 Free Software Foundation, Inc.
+
+;; This file is part of GNU CC.
+
+;; GNU CC 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 2, or (at your option)
+;; any later version.
+
+;; GNU CC 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.
+;; Among other things, the copyright
+;; notice and this notice must be preserved on all copies.
+
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU CC; see the file COPYING.  If not, write to
+;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+
+;;- instruction definitions
+
+;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
+
+;;- When naming insn's (operand 0 of define_insn) be careful about using
+;;- names from other targets machine descriptions.
+
+;;- cpp macro #define NOTICE_UPDATE_CC is essentially a no-op for the 
+;;- gmicro; no compares are eliminated.
+
+;;- The original structure of this file is m68k.md.
+
+;; ??? Work to be done:
+;; Add patterns for ACB and SCB instructions.
+;; Add define_insn patterns to recognize the insns that extend a byte
+;; to a word and add it into a word, etc.
+
+;;- Some of these insn's are composites of several Gmicro op codes.
+;;- The assembler (or final @@??) insures that the appropriate one is
+;;- selected.
+\f
+(define_insn ""
+  [(set (match_operand:DF 0 "push_operand" "=m")
+       (match_operand:DF 1 "general_operand" "rmfF"))]
+  ""
+  "*
+{
+  if (FPU_REG_P (operands[1]))
+    return \"fmov.d %f1,%0\";
+  return output_move_double (operands);
+}")
+
+(define_insn ""
+  [(set (match_operand:DI 0 "push_operand" "=m")
+       (match_operand:DF 1 "general_operand" "rmF"))]
+  ""
+  "*
+{
+  return output_move_double (operands);
+}")
+\f
+;; We don't want to allow a constant operand for test insns because
+;; (set (cc0) (const_int foo)) has no mode information.  Such insns will
+;; be folded while optimizing anyway.
+
+(define_insn "tstsi"
+  [(set (cc0)
+       (match_operand:SI 0 "nonimmediate_operand" "rm"))]
+  ""
+  "cmp:z.w #0,%0")
+
+(define_insn "tsthi"
+  [(set (cc0)
+       (match_operand:HI 0 "nonimmediate_operand" "rm"))]
+  ""
+  "cmp:z.h #0,%0")
+
+(define_insn "tstqi"
+  [(set (cc0)
+       (match_operand:QI 0 "nonimmediate_operand" "rm"))]
+  ""
+  "cmp:z.b #0,%0")
+  
+
+(define_insn "tstsf"
+  [(set (cc0)
+       (match_operand:SF 0 "general_operand" "fmF"))]
+  "TARGET_FPU"
+  "*
+{
+  cc_status.flags = CC_IN_FPU;
+  return \"ftst.s %0\";
+}")
+
+
+(define_insn "tstdf"
+  [(set (cc0)
+       (match_operand:DF 0 "general_operand" "fmF"))]
+  "TARGET_FPU"
+  "*
+{
+  cc_status.flags = CC_IN_FPU;
+  return \"ftst.d %0\";
+}")
+\f
+;; compare instructions.
+
+;; (operand0 - operand1)
+(define_insn "cmpsi"
+  [(set (cc0)
+       (compare (match_operand:SI 0 "nonimmediate_operand" "ri,rm")
+                (match_operand:SI 1 "general_operand" "rm,rmi")))]
+  ""
+  "*
+{
+  int signed_flag = my_signed_comp (insn);
+
+  if (which_alternative == 0)
+    {
+      cc_status.flags |= CC_REVERSED;
+      if (signed_flag && GET_CODE (operands[0]) == CONST_INT)
+       {
+         register rtx xfoo;
+         xfoo = operands[1];
+         operands[0] = operands[1];
+         operands[1] = xfoo;
+         return cmp_imm_word (INTVAL (operands[1]), operands[0]);
+       }
+      if (signed_flag)
+       return \"cmp.w %0,%1\"; 
+      return \"cmpu.w %0,%1\"; 
+    }
+  if (signed_flag)
+    {
+      if (GET_CODE (operands[1]) == CONST_INT)
+       return cmp_imm_word (INTVAL (operands[1]), operands[0]);
+      return \"cmp.w %1,%0\"; 
+    }
+  else
+    return \"cmpu.w %1,%0\"; 
+}")
+
+(define_insn "cmphi"
+  [(set (cc0)
+       (compare (match_operand:HI 0 "nonimmediate_operand" "ri,rm")
+                (match_operand:HI 1 "general_operand" "rm,rmi")))]
+  ""
+  "*
+{
+  int signed_flag = my_signed_comp (insn);
+
+  if (which_alternative == 0)
+    {
+      cc_status.flags |= CC_REVERSED;
+      if (signed_flag)
+       return \"cmp.h %0,%1\"; 
+      return \"cmpu.h %0,%1\"; 
+    }
+  if (signed_flag)
+    return \"cmp.h %1,%0\"; 
+  return \"cmpu.h %1,%0\"; 
+}")
+
+(define_insn "cmpqi"
+  [(set (cc0)
+       (compare (match_operand:QI 0 "nonimmediate_operand" "ri,rm")
+                (match_operand:QI 1 "general_operand" "rm,rmi")))]
+  ""
+  "*
+{
+  int signed_flag = my_signed_comp (insn);
+
+  if (which_alternative == 0)
+    {
+      cc_status.flags |= CC_REVERSED;
+      if (signed_flag)
+       return \"cmp.b %0,%1\"; 
+      return \"cmpu.b %0,%1\"; 
+    }
+  if (signed_flag)
+    return \"cmp.b %1,%0\"; 
+  return \"cmpu.b %1,%0\"; 
+}")
+
+
+(define_insn "cmpdf"
+  [(set (cc0)
+       (compare (match_operand:DF 0 "general_operand" "f,mG")
+                (match_operand:DF 1 "general_operand" "fmG,f")))]
+  "TARGET_FPU"
+  "*
+{
+  cc_status.flags = CC_IN_FPU;
+
+  if (FPU_REG_P (operands[0]))
+    return \"fcmp.d %f1,%f0\";
+  cc_status.flags |= CC_REVERSED;
+  return \"fcmp.d %f0,%f1\";
+}")
+
+
+(define_insn "cmpsf"
+  [(set (cc0)
+       (compare (match_operand:SF 0 "general_operand" "f,mG")
+                (match_operand:SF 1 "general_operand" "fmG,f")))]
+  "TARGET_FPU"
+  "*
+{
+  cc_status.flags = CC_IN_FPU;
+  if (FPU_REG_P (operands[0]))
+    return \"fcmp.s %f1,%0\";
+  cc_status.flags |= CC_REVERSED;
+  return \"fcmp.s %f0,%1\";
+}")
+\f
+;; Recognizers for btst instructions.
+
+(define_insn ""
+  [(set (cc0) (zero_extract (match_operand:QI 0 "nonimmediate_operand" "rm")
+                           (const_int 1)
+                           (match_operand:SI 1 "general_operand" "rmi")))]
+  ""
+  "btst %1.w,%0.b")
+
+(define_insn ""
+  [(set (cc0) (zero_extract (match_operand:HI 0 "nonimmediate_operand" "rm")
+                           (const_int 1)
+                           (match_operand:SI 1 "general_operand" "rmi")))]
+  ""
+  "btst %1.w,%0.h")
+
+(define_insn ""
+  [(set (cc0) (zero_extract (match_operand:SI 0 "nonimmediate_operand" "rm")
+                           (const_int 1)
+                           (match_operand:SI 1 "general_operand" "rmi")))]
+  ""
+  "btst %1.w,%0.w")
+
+;; The following two patterns are like the previous two
+;; except that they use the fact that bit-number operands (offset)
+;; are automatically masked to 3 or 5 bits when the base is a register.
+
+(define_insn ""
+  [(set (cc0) (zero_extract (match_operand:QI 0 "nonimmediate_operand" "r")
+                           (const_int 1)
+                           (and:SI
+                              (match_operand:SI 1 "general_operand" "rmi")
+                              (const_int 7))))]
+  ""
+  "btst %1.w,%0.b")
+
+(define_insn ""
+  [(set (cc0) (zero_extract (match_operand:SI 0 "nonimmediate_operand" "r")
+                           (const_int 1)
+                           (and:SI
+                              (match_operand:SI 1 "general_operand" "rmi")
+                              (const_int 31))))]
+  ""
+  "btst %1.w,%0.w")
+
+; More various size-patterns are allowed for btst, but not
+; included yet.  M.Yuhara
+
+
+(define_insn ""
+  [(set (cc0) (and:SI (sign_extend:SI (sign_extend:HI (match_operand:QI 0 "nonimmediate_operand" "rm")))
+                     (match_operand:SI 1 "general_operand" "i")))]
+  "(GET_CODE (operands[1]) == CONST_INT
+    && (unsigned) INTVAL (operands[1]) < 0x100
+    && exact_log2 (INTVAL (operands[1])) >= 0)"
+  "*
+{
+  register int log = exact_log2 (INTVAL (operands[1]));
+  operands[1] = gen_rtx (CONST_INT, VOIDmode, log);
+  return \"btst %1,%0.b\";
+}")
+
+; I can add more patterns like above. But not yet.  M.Yuhara
+
+
+; mtst is supported only by G/300.
+
+(define_insn ""
+  [(set (cc0) 
+       (and:SI (match_operand:SI 0 "general_operand" "%rmi")
+               (match_operand:SI 1 "general_operand" "rm")))]
+  "TARGET_G300"
+  "*
+{
+  if (GET_CODE (operands[0]) == CONST_INT)
+    return \"mtst.w %0,%1\";
+  return \"mtst.w %1,%0\";
+}")
+
+(define_insn ""
+  [(set (cc0) 
+       (and:HI (match_operand:HI 0 "general_operand" "%rmi")
+               (match_operand:HI 1 "general_operand" "rm")))]
+  "TARGET_G300"
+  "*
+{
+  if (GET_CODE (operands[0]) == CONST_INT)
+    return \"mtst.h %0,%1\";
+  return \"mtst.h %1,%0\";
+}")
+
+(define_insn ""
+  [(set (cc0) 
+       (and:QI (match_operand:QI 0 "general_operand" "%rmi")
+               (match_operand:QI 1 "general_operand" "rm")))]
+  "TARGET_G300"
+  "*
+{
+  if (GET_CODE (operands[0]) == CONST_INT)
+    return \"mtst.b %0,%1\";
+  return \"mtst.b %1,%0\";
+}")
+
+
+\f
+;; move instructions
+
+/* added by M.Yuhara */
+;; 1.35.04 89.08.28 modification start
+;; register_operand -> general_operand
+;; ashift -> mult 
+
+(define_insn ""
+  [(set (mem:SI (plus:SI
+                 (match_operand:SI 0 "general_operand" "r")
+                 (ashift:SI
+                     (match_operand:SI 1 "general_operand" "r")
+                     (const_int 2))))
+       (match_operand:SI 2 "general_operand" "rmi"))]
+  ""
+  "*
+{
+  return \"mov.w %2,@(%0:b,%1*4)\";
+}")
+
+(define_insn ""
+  [(set (mem:SI (plus:SI
+                 (ashift:SI
+                     (match_operand:SI 0 "general_operand" "r")
+                     (const_int 2))
+                 (match_operand:SI 1 "general_operand" "r")))
+       (match_operand:SI 2 "general_operand" "rmi"))]
+  ""
+  "*
+{
+  return \"mov.w %2,@(%1:b,%0*4)\";
+}")
+
+
+(define_insn ""
+  [(set (mem:SI (plus:SI
+                 (match_operand:SI 0 "register_operand" "r")
+                 (mult:SI
+                     (match_operand:SI 1 "register_operand" "r")
+                     (const_int 4))))
+       (match_operand:SI 2 "general_operand" "rmi"))]
+  ""
+  "*
+{
+  return \"mov.w %2,@(%0:b,%1*4)\";
+}")
+
+(define_insn ""
+  [(set (mem:SI (plus:SI
+                 (mult:SI
+                     (match_operand:SI 0 "register_operand" "r")
+                     (const_int 4))
+                 (match_operand:SI 1 "register_operand" "r")))
+       (match_operand:SI 2 "general_operand" "rmi"))]
+  ""
+  "*
+{
+  return \"mov.w %2,@(%1:b,%0*4)\";
+}")
+
+
+(define_insn ""
+  [(set (mem:SI (plus:SI
+                 (match_operand:SI 0 "general_operand" "r")
+                 (plus:SI
+                     (match_operand:SI 1 "register_operand" "r")
+                     (match_operand:SI 2 "register_operand" "i"))))
+       (match_operand:SI 3 "general_operand" "rmi"))]
+  ""
+  "*
+{
+  return \"mov.w %3,@(%c2,%0,%1)\";
+}")
+
+(define_insn ""
+  [(set (mem:SI (plus:SI
+                 (plus:SI
+                     (match_operand:SI 0 "register_operand" "r")
+                     (match_operand:SI 1 "register_operand" "r"))
+                 (match_operand:SI 2 "general_operand" "i")))
+       (match_operand:SI 3 "general_operand" "rmi"))]
+  ""
+  "*
+{
+  return \"mov.w %3,@(%c2,%0,%1)\";
+}")
+
+
+(define_insn ""
+  [(set (mem:SI (plus:SI
+                 (match_operand:SI 0 "general_operand" "i")
+                 (plus:SI
+                     (match_operand:SI 1 "register_operand" "r")
+                     (mult:SI
+                         (match_operand:SI 2 "register_operand" "r")
+                         (const_int 4)))))
+       (match_operand:SI 3 "general_operand" "rmi"))]
+  ""
+  "*
+{
+  return \"mov.w %3,@(%1:b,%0,%2*4)\";
+}")
+
+;; 89.08.28 1.35.04 modification end
+
+;; Should add "!" to op2 ??
+
+;; General move-address-to-operand should handle these.
+;; If that does not work, please figure out why.
+
+;(define_insn ""
+;  [(set (match_operand:SI 0 "push_operand" "=m")
+;      (plus:SI
+;          (match_operand:SI 1 "immediate_operand" "i")
+;          (match_operand:SI 2 "general_operand" "r")))]
+;  ""
+;  "mova.w @(%c1,%2),%-")
+
+;(define_insn ""
+;  [(set (match_operand:SI 0 "push_operand" "=m")
+;      (plus:SI
+;          (match_operand:SI 1 "general_operand" "r")
+;          (match_operand:SI 2 "immediate_operand" "i")))]
+;  ""
+;  "mova.w @(%c2,%1),%-")
+
+
+(define_insn ""
+  [(set (match_operand:SI 0 "push_operand" "=m")
+       (minus:SI
+           (match_operand:SI 1 "general_operand" "r")
+           (match_operand:SI 2 "immediate_operand" "i")))]
+  ""
+  "mova.w @(%n2,%1),%-")
+
+
+
+;; General case of fullword move.
+
+(define_insn "movsi"
+  [(set (match_operand:SI 0 "general_operand" "=rm")
+       (match_operand:SI 1 "general_operand" "rmi"))]
+  ""
+  "*
+{
+  if (GET_CODE (operands[1]) == CONST_INT)
+    return mov_imm_word (INTVAL (operands[1]), operands[0]);
+  /* if (address_operand (operands[1], SImode))
+     return \"mova.w %1,%0\"; */
+  if (push_operand (operands[0], SImode))
+    return \"mov.w %1,%-\";
+  return \"mov.w %1,%0\";
+}")
+
+/* pushsi 89.08.10 for test M.Yuhara */
+/*
+(define_insn ""
+  [(set (match_operand:SI 0 "push_operand" "=m")
+       (match_operand:SI 1 "general_operand" "rmi"))]
+  ""
+  "*
+{
+  if (GET_CODE (operands[1]) == CONST_INT)
+    return mov_imm_word (INTVAL (operands[1]), operands[0]);
+  if (push_operand (operands[0], SImode))
+    return \"mov.w %1,%-\";
+  return \"mov.w %1,%0\";
+}")
+*/
+
+
+(define_insn "movhi"
+  [(set (match_operand:HI 0 "general_operand" "=rm")
+       (match_operand:HI 1 "general_operand" "rmi"))]
+  ""
+  "*
+{
+  if (push_operand (operands[0], SImode))
+    return \"mov.h %1,%-\";
+  return \"mov.h %1,%0\";
+}")
+
+;; Is the operand constraint "+" necessary ????
+;; Should I check push_operand ????
+
+(define_insn "movstricthi"
+  [(set (strict_low_part (match_operand:HI 0 "general_operand" "+rm"))
+       (match_operand:HI 1 "general_operand" "rmi"))]
+  ""
+  "mov.h %1,%0");
+
+(define_insn "movqi"
+  [(set (match_operand:QI 0 "general_operand" "=rm")
+       (match_operand:QI 1 "general_operand" "rmi"))]
+  ""
+  "*
+{
+  if (GREG_P (operands[0]))
+    {
+      if (CONSTANT_P (operands[1]))
+       return \"mov:l %1,%0.w\";
+      else
+       return \"mov:l %1.b,%0.w\";
+    }
+  if (GREG_P (operands[1]))
+    return \"mov:s %1.w,%0.b\";
+  return \"mov.b %1,%0\";
+}")
+
+(define_insn "movstrictqi"
+  [(set (strict_low_part (match_operand:QI 0 "general_operand" "+rm"))
+       (match_operand:QI 1 "general_operand" "rmi"))]
+  ""
+  "mov.b %1,%0")
+
+
+(define_insn "movsf"
+  [(set (match_operand:SF 0 "general_operand" "=f,mf,rm,fr")
+       (match_operand:SF 1 "general_operand" "mfF,f,rmF,fr"))]
+  ""
+  "*
+{
+  switch (which_alternative)
+    {
+    case 0:
+      if (GET_CODE (operands[1]) == CONST_DOUBLE)
+       return output_move_const_single (operands);
+      return \"fmov.s %1,%0\";
+    case 1:
+      return \"fmov.s %1,%0\";
+    case 2:
+      if (GET_CODE (operands[1]) == CONST_DOUBLE)
+       return output_move_const_single (operands);
+      return \"mov.w %1,%0\";
+    case 3:
+      if (FPU_REG_P (operands[0]))
+       return \"mov.w %1,%-\\n\\tfmov.s %+,%0\";
+      return \"fmov.s %1,%-\\n\\tmov.w %+,%0\";
+    }
+}")
+
+(define_insn "movdf"
+  [(set (match_operand:DF 0 "general_operand" "=f,mf,rm,fr")
+       (match_operand:DF 1 "general_operand" "mfF,f,rmF,fr"))]
+  ""
+  "*
+{
+  switch (which_alternative)
+    {
+    case 0:
+      if (GET_CODE (operands[1]) == CONST_DOUBLE)
+       return output_move_const_double (operands);
+      return \"fmov.d %1,%0\";
+    case 1:
+      return \"fmov.d %1,%0\";
+    case 2:
+      if (GET_CODE (operands[1]) == CONST_DOUBLE)
+       return output_move_const_double (operands);
+      return output_move_double (operands);
+    case 3:
+      if (FPU_REG_P (operands[0]))
+       {
+         rtx xoperands[2];
+         xoperands[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
+         output_asm_insn (\"mov.w %1,%-\", xoperands);
+         output_asm_insn (\"mov.w %1,%-\", operands);
+         return \"fmov.d %+,%0\";
+       }
+      else
+       {
+         output_asm_insn (\"fmov.d %f1,%-\", operands);
+         output_asm_insn (\"mov.w %+,%0\", operands);
+         operands[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
+         return \"mov.w %+,%0\";
+       }
+    }
+}")
+
+
+;; movdi can apply to fp regs in some cases
+;; Must check again.  you can use fsti/fldi, etc.
+;; FPU reg should be included ??
+;; 89.12.13 for test
+
+(define_insn "movdi"
+  ;; Let's see if it really still needs to handle fp regs, and, if so, why.
+  [(set (match_operand:DI 0 "general_operand" "=rm,&r,&ro")
+       (match_operand:DI 1 "general_operand" "rF,m,roiF"))]
+  ""
+  "*
+{
+  if (FPU_REG_P (operands[0]))
+    {
+      if (FPU_REG_P (operands[1]))
+       return \"fmov.d %1,%0\";
+      if (REG_P (operands[1]))
+       {
+         rtx xoperands[2];
+         xoperands[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
+         output_asm_insn (\"mov.w %1,%-\", xoperands);
+         output_asm_insn (\"mov.w %1,%-\", operands);
+         return \"fmov.d %+,%0\";
+       }
+      if (GET_CODE (operands[1]) == CONST_DOUBLE)
+       return output_move_const_double (operands);
+      return \"fmov.d %f1,%0\";
+    }
+  else if (FPU_REG_P (operands[1]))
+    {
+      if (REG_P (operands[0]))
+       {
+         output_asm_insn (\"fmov.d %f1,%-\;mov.w %+,%0\", operands);
+         operands[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
+         return \"mov.w %+,%0\";
+       }
+      else
+        return \"fmov.d %f1,%0\";
+    }
+  return output_move_double (operands);
+}
+")
+
+
+;; The definition of this insn does not really explain what it does,
+;; but it should suffice
+;; that anything generated as this insn will be recognized as one
+;; and that it won't successfully combine with anything.
+
+;; This is dangerous when %0 and %1 overlapped !!!!!
+;; Ugly code...
+
+(define_insn "movstrhi"
+  [(set (match_operand:BLK 0 "general_operand" "=m")
+       (match_operand:BLK 1 "general_operand" "m"))
+   (use (match_operand:HI 2 "general_operand" "rmi"))
+   (clobber (reg:SI 0))
+   (clobber (reg:SI 1))
+   (clobber (reg:SI 2))]
+  ""
+  "*
+{
+  int op2const;
+  rtx tmpx;
+
+  if (CONSTANT_P (operands[1]))
+    {
+      fprintf (stderr, \"smov 1 const err \");
+      abort ();
+    }
+  else if (GET_CODE (operands[1]) == REG)
+    {
+      fprintf (stderr, \"smov 1 reg err \");
+      abort ();
+    }
+  else if (GET_CODE (operands[1]) == MEM)
+    {
+      tmpx = XEXP (operands[1], 0);
+      if (CONSTANT_ADDRESS_P (tmpx) || GREG_P (tmpx))
+       {
+         operands[1] = tmpx;
+         output_asm_insn (\"mov.w %1,r0\", operands);
+       }
+      else
+       {
+         output_asm_insn (\"mova %1,r0\", operands);
+       }
+    }
+  else
+    {
+      fprintf (stderr, \"smov 1 else err \");
+      abort ();
+      output_asm_insn (\"mova.w %p1,r0\", operands);
+    }
+    
+  if (CONSTANT_P (operands[0]))
+    {
+      fprintf (stderr, \"smov 0 const err \");
+      abort ();
+    }
+  else if (GET_CODE (operands[0]) == REG)
+    {
+      fprintf (stderr, \"smov 0 reg err \");
+      abort ();
+    }
+  else if (GET_CODE (operands[0]) == MEM)
+    {
+      tmpx = XEXP (operands[0], 0);
+      if (CONSTANT_ADDRESS_P (tmpx) || GREG_P (tmpx))
+       {
+         operands[0] = tmpx;
+         output_asm_insn (\"mov.w %0,r1\", operands);
+       }
+      else
+       {
+         output_asm_insn (\"mova %0,r1\", operands);
+       }
+    }
+  else
+    {
+      fprintf (stderr, \"smov 0 else err \");
+      abort ();
+    }
+    
+  if (GET_CODE (operands[2]) == CONST_INT)
+    {
+      op2const = INTVAL (operands[2]);
+      if (op2const % 4 != 0)
+       {
+         output_asm_insn (\"mov.w %2,r2\", operands);
+         return \"smov/n/f.b\";
+       }
+      op2const = op2const / 4;
+      if (op2const <= 4)
+       {
+         if (op2const == 0)
+           abort (0);
+         if (op2const == 1)
+           return \"mov.w @r0,@r1\";
+         output_asm_insn (\"mov.w @r0,@r1\", operands);
+         if (op2const == 2)
+           return \"mov.w @(4,r0),@(4,r1)\";
+         output_asm_insn (\"mov.w @(4,r0),@(4,r1)\", operands);
+         if (op2const == 3)
+           return \"mov.w @(8,r0),@(8,r1)\";
+         output_asm_insn (\"mov.w @(8,r0),@(8,r1)\", operands);
+         return \"mov.w @(12,r0),@(12,r1)\";
+       }
+           
+      operands[2] =
+       gen_rtx (CONST_INT, VOIDmode, op2const);
+      output_asm_insn (\"mov.w %2,r2\", operands);
+      return \"smov/n/f.w\";
+    }
+  else
+    {
+      fprintf (stderr, \"smov 0 else err \");
+      abort ();
+      output_asm_insn (\"mov %2.h,r2.w\", operands);
+      return \"smov/n/f.b\";
+    }
+
+}")
+\f
+;; M.Yuhara 89.08.24
+;; experiment on the built-in strcpy (__builtin_smov)
+;;
+;; len = 0 means unknown string length.
+;;
+;; mem:SI is dummy. Necessary so as not to be deleted by optimization.
+;; Use of BLKmode would be better...
+;;
+;;
+(define_insn "smovsi"
+  [(set (mem:SI (match_operand:SI 0 "general_operand" "=rm"))
+       (mem:SI (match_operand:SI 1 "general_operand" "rm")))
+   (use (match_operand:SI 2 "general_operand" "i"))
+   (clobber (reg:SI 0))
+   (clobber (reg:SI 1))
+   (clobber (reg:SI 2))
+   (clobber (reg:SI 3))]
+  ""
+  "*
+{
+  int len, wlen, blen, offset;
+  char tmpstr[128];
+  rtx xoperands[1];
+
+  len = INTVAL (operands[2]);
+  output_asm_insn (\"mov.w %1,r0\\t; begin built-in strcpy\", operands);
+  output_asm_insn (\"mov.w %0,r1\", operands);
+
+  if (len == 0)
+    {
+      output_asm_insn (\"mov:z.w #0,r2\", operands);
+      output_asm_insn (\"mov:z.w #0,r3\", operands);
+      return \"smov/eq/f.b\\t; end built-in strcpy\";
+    }
+
+  wlen = len / 4;
+  blen = len - wlen * 4;
+
+  if (wlen > 0)
+    {
+      if (len <= 40 && !TARGET_FORCE_SMOV)
+       {
+         output_asm_insn (\"mov.w @r0,@r1\", operands);
+         offset = 4;
+         while ( (blen = len - offset) > 0)
+           {
+             if (blen >= 4)
+               {
+                 sprintf (tmpstr, \"mov.w @(%d,r0),@(%d,r1)\",
+                          offset, offset);
+                 output_asm_insn (tmpstr, operands);
+                 offset += 4;
+               }
+             else if (blen >= 2)
+               {
+                 sprintf (tmpstr, \"mov.h @(%d,r0),@(%d,r1)\",
+                          offset, offset);
+                 output_asm_insn (tmpstr, operands);
+                 offset += 2;
+               }
+             else
+               {
+                 sprintf (tmpstr, \"mov.b @(%d,r0),@(%d,r1)\",
+                          offset, offset);
+                 output_asm_insn (tmpstr, operands);
+                 offset++;
+               }
+           }
+         return \"\\t\\t; end built-in strcpy\";
+       }
+      else
+       {
+         xoperands[0] = gen_rtx (CONST_INT, VOIDmode, wlen);
+         output_asm_insn (\"mov.w %0,r2\", xoperands);
+         output_asm_insn (\"smov/n/f.w\", operands);
+       }
+    }
+
+  if (blen >= 2)
+    {
+      output_asm_insn (\"mov.h @r0,@r1\", operands);
+      if (blen == 3)
+       output_asm_insn (\"mov.b @(2,r0),@(2,r1)\", operands);
+    }
+  else if (blen == 1)
+    {
+      output_asm_insn (\"mov.b @r0,@r1\", operands);
+    }
+
+  return \"\\t\\t; end built-in strcpy\";
+}")
+\f
+;; truncation instructions
+(define_insn "truncsiqi2"
+  [(set (match_operand:QI 0 "general_operand" "=rm")
+       (truncate:QI
+        (match_operand:SI 1 "general_operand" "rmi")))]
+  ""
+  "mov %1.w,%0.b")
+;  "*
+;{
+;  if (GET_CODE (operands[0]) == REG)
+;    return \"mov.w %1,%0\";
+;  if (GET_CODE (operands[1]) == MEM)
+;    operands[1] = adj_offsettable_operand (operands[1], 3);
+;  return \"mov.b %1,%0\";
+;}")
+
+(define_insn "trunchiqi2"
+  [(set (match_operand:QI 0 "general_operand" "=rm")
+       (truncate:QI
+        (match_operand:HI 1 "general_operand" "rmi")))]
+  ""
+  "mov %1.h,%0.b")
+;  "*
+;{
+;  if (GET_CODE (operands[0]) == REG)
+;    return \"mov.h %1,%0\";
+;  if (GET_CODE (operands[1]) == MEM)
+;    operands[1] = adj_offsettable_operand (operands[1], 1);
+;  return \"mov.b %1,%0\";
+;}")
+
+(define_insn "truncsihi2"
+  [(set (match_operand:HI 0 "general_operand" "=rm")
+       (truncate:HI
+        (match_operand:SI 1 "general_operand" "rmi")))]
+  ""
+  "mov %1.w,%0.h")
+;  "*
+;{
+;  if (GET_CODE (operands[0]) == REG)
+;    return \"mov.w %1,%0\";
+;  if (GET_CODE (operands[1]) == MEM)
+;    operands[1] = adj_offsettable_operand (operands[1], 2);
+;  return \"mov.h %1,%0\";
+;}")
+\f
+;; zero extension instructions
+;; define_expand (68k) -> define_insn (Gmicro)
+
+(define_insn "zero_extendhisi2"
+  [(set (match_operand:SI 0 "general_operand" "=rm")
+        (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "rm")))]
+  ""
+  "movu %1.h,%0.w")
+
+
+(define_insn "zero_extendqihi2"
+  [(set (match_operand:HI 0 "general_operand" "=rm")
+        (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "rm")))]
+  ""
+  "movu %1.b,%0.h")
+
+(define_insn "zero_extendqisi2"
+  [(set (match_operand:SI 0 "general_operand" "=rm")
+        (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "rm")))]
+  ""
+  "movu %1.b,%0.w")
+
+\f
+;; sign extension instructions
+
+(define_insn "extendhisi2"
+  [(set (match_operand:SI 0 "general_operand" "=rm")
+        (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "rm")))]
+  ""
+  "mov %1.h,%0.w")
+
+
+(define_insn "extendqihi2"
+  [(set (match_operand:HI 0 "general_operand" "=rm")
+        (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "rm")))]
+  ""
+  "mov %1.b,%0.h")
+
+(define_insn "extendqisi2"
+  [(set (match_operand:SI 0 "general_operand" "=rm")
+        (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "rm")))]
+  ""
+  "mov %1.b,%0.w")
+
+
+\f
+;; Conversions between float and double.
+
+(define_insn "extendsfdf2"
+  [(set (match_operand:DF 0 "general_operand" "=*frm,f")
+       (float_extend:DF
+         (match_operand:SF 1 "general_operand" "f,rmF")))]
+  "TARGET_FPU"
+  "*
+{
+  if (FPU_REG_P (operands[0]))
+    {
+      if (GET_CODE (operands[1]) == CONST_DOUBLE)
+       return output_move_const_double (operands);
+      if (GREG_P (operands[1]))
+       {
+         output_asm_insn (\"mov.w %1,%-\", operands);
+         return \"fmov %+.s,%0.d\";
+       }
+      return \"fmov %1.s,%0.d\";
+    }
+  else
+    {
+      if (GREG_P (operands[0]))
+       {
+         output_asm_insn (\"fmov %1.s,%-.d\", operands);
+         output_asm_insn (\"mov.w %+,%0\", operands);
+         operands[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
+         return \"mov.w %+,%0\";
+       }
+      return \"fmov %1.s,%0.d\";
+    }
+}")
+
+
+(define_insn "truncdfsf2"
+  [(set (match_operand:SF 0 "general_operand" "=rfm")
+       (float_truncate:SF
+         (match_operand:DF 1 "general_operand" "f")))]
+  "TARGET_FPU"
+  "*
+{
+  if (GREG_P (operands[0]))
+    {
+      output_asm_insn (\"fmov %1.d,%-.s\", operands);
+      return \"mov.w %+,%0\";
+    }
+  return \"fmov %1.d,%0.s\";
+}")
+\f
+;; Conversion between fixed point and floating point.
+;; Note that among the fix-to-float insns
+;; the ones that start with SImode come first.
+;; That is so that an operand that is a CONST_INT
+;; (and therefore lacks a specific machine mode).
+;; will be recognized as SImode (which is always valid)
+;; rather than as QImode or HImode.
+
+
+(define_insn "floatsisf2"
+  [(set (match_operand:SF 0 "general_operand" "=f")
+       (float:SF (match_operand:SI 1 "general_operand" "rmi")))]
+  "TARGET_FPU"
+  "fldi %1.w,%0.s")
+
+(define_insn "floatsidf2"
+  [(set (match_operand:DF 0 "general_operand" "=f")
+       (float:DF (match_operand:SI 1 "general_operand" "rmi")))]
+  "TARGET_FPU"
+  "fldi %1.w,%0.d")
+
+(define_insn "floathisf2"
+  [(set (match_operand:SF 0 "general_operand" "=f")
+       (float:SF (match_operand:HI 1 "general_operand" "rmi")))]
+  "TARGET_FPU"
+  "fldi %1.h,%0.s")
+
+(define_insn "floathidf2"
+  [(set (match_operand:DF 0 "general_operand" "=f")
+       (float:DF (match_operand:HI 1 "general_operand" "rmi")))]
+  "TARGET_FPU"
+  "fldi %1.h,%0.d")
+
+(define_insn "floatqisf2"
+  [(set (match_operand:SF 0 "general_operand" "=f")
+       (float:SF (match_operand:QI 1 "general_operand" "rmi")))]
+  "TARGET_FPU"
+  "fldi %1.b,%0.s")
+
+(define_insn "floatqidf2"
+  [(set (match_operand:DF 0 "general_operand" "=f")
+       (float:DF (match_operand:QI 1 "general_operand" "rmi")))]
+  "TARGET_FPU"
+  "fldi %1.b,%0.d")
+
+;;; Convert a float to a float whose value is an integer.
+;;; This is the first stage of converting it to an integer type.
+;
+;(define_insn "ftruncdf2"
+;  [(set (match_operand:DF 0 "general_operand" "=f")
+;      (fix:DF (match_operand:DF 1 "general_operand" "fFm")))]
+;  "TARGET_FPU"
+;  "*
+;{
+;  return \"fintrz.d %f1,%0\";
+;}")
+;
+;(define_insn "ftruncsf2"
+;  [(set (match_operand:SF 0 "general_operand" "=f")
+;      (fix:SF (match_operand:SF 1 "general_operand" "fFm")))]
+;  "TARGET_FPU"
+;  "*
+;{
+;  return \"fintrz.s %f1,%0\";
+;}")
+
+;; Convert a float to an integer.
+
+(define_insn "fix_truncsfqi2"
+  [(set (match_operand:QI 0 "general_operand" "=rm")
+       (fix:QI (fix:SF (match_operand:SF 1 "general_operand" "f"))))]
+  "TARGET_FPU"
+  "fsti %1.s,%0.b")
+
+(define_insn "fix_truncsfhi2"
+  [(set (match_operand:HI 0 "general_operand" "=rm")
+       (fix:HI (fix:SF (match_operand:SF 1 "general_operand" "f"))))]
+  "TARGET_FPU"
+  "fsti %1.s,%0.h")
+
+(define_insn "fix_truncsfsi2"
+  [(set (match_operand:SI 0 "general_operand" "=rm")
+       (fix:SI (fix:SF (match_operand:SF 1 "general_operand" "f"))))]
+  "TARGET_FPU"
+  "fsti %1.s,%0.w")
+
+(define_insn "fix_truncdfqi2"
+  [(set (match_operand:QI 0 "general_operand" "=rm")
+       (fix:QI (fix:DF (match_operand:DF 1 "general_operand" "f"))))]
+  "TARGET_FPU"
+  "fsti %1.d,%0.b")
+
+(define_insn "fix_truncdfhi2"
+  [(set (match_operand:HI 0 "general_operand" "=rm")
+       (fix:HI (fix:DF (match_operand:DF 1 "general_operand" "f"))))]
+  "TARGET_FPU"
+  "fsti %1.d,%0.h")
+
+(define_insn "fix_truncdfsi2"
+  [(set (match_operand:SI 0 "general_operand" "=rm")
+       (fix:SI (fix:DF (match_operand:DF 1 "general_operand" "f"))))]
+  "TARGET_FPU"
+  "fsti %1.d,%0.w")
+
+\f
+;;; Special add patterns
+;;; 89.09.28
+
+;; This should be redundant; please find out why regular addsi3
+;; fails to match this case.
+
+;(define_insn ""
+;  [(set (mem:SI (plus:SI
+;                  (plus:SI (match_operand 0 "general_operand" "r")
+;                           (match_operand 1 "general_operand" "r"))
+;                  (match_operand 2 "general_operand" "i")))
+;      (plus:SI
+;          (mem:SI (plus:SI
+;                      (plus:SI (match_dup 0)
+;                               (match_dup 1))
+;                      (match_dup 2)))
+;          (match_operand 3 "general_operand" "rmi")))]
+;  ""
+;  "add.w %3,@(%c2,%0,%1)")
+
+\f
+;; add instructions
+
+;; Note that the last two alternatives are near-duplicates
+;; in order to handle insns generated by reload.
+;; This is needed since they are not themselves reloaded,
+;; so commutativity won't apply to them.
+
+(define_insn "addsi3"
+  [(set (match_operand:SI 0 "general_operand" "=rm,!r,!r")
+       (plus:SI (match_operand:SI 1 "general_operand" "%0,r,ri")
+                (match_operand:SI 2 "general_operand" "rmi,ri,r")))]
+  ""
+  "*
+{
+  if (which_alternative == 0)
+    {
+      if (GET_CODE (operands[2]) == CONST_INT)
+       {
+         operands[1] = operands[2];
+         return add_imm_word (INTVAL (operands[1]), operands[0], &operands[1]);
+       }
+      else
+       return \"add.w %2,%0\";
+    }
+  else
+    {
+      if (GET_CODE (operands[1]) == REG
+         && REGNO (operands[0]) == REGNO (operands[1]))
+       return \"add.w %2,%0\";
+      if (GET_CODE (operands[2]) == REG
+         && REGNO (operands[0]) == REGNO (operands[2]))
+       return \"add.w %1,%0\";
+
+      if (GET_CODE (operands[1]) == REG)
+       {
+         if (GET_CODE (operands[2]) == REG)
+           return \"mova.w @(%1,%2),%0\";
+         else
+           return \"mova.w @(%c2,%1),%0\";
+       }
+      else
+       return \"mova.w @(%c1,%2),%0\";
+    }
+}")
+
+(define_insn ""
+  [(set (match_operand:SI 0 "general_operand" "=rm")
+       (plus:SI (match_operand:SI 1 "general_operand" "0")
+                (sign_extend:SI (match_operand:HI 2 "nonimmediate_operand" "rmi"))))]
+  ""
+  "*
+{
+  if (CONSTANT_P (operands[2]))
+    {
+      operands[1] = operands[2];
+      return add_imm_word (INTVAL (operands[1]), operands[0], &operands[1]);
+    }
+  else
+    return \"add %2.h,%0.w\";
+}")
+
+(define_insn "addhi3"
+  [(set (match_operand:HI 0 "general_operand" "=rm")
+       (plus:HI (match_operand:HI 1 "general_operand" "%0")
+                (match_operand:HI 2 "general_operand" "rmi")))]
+  ""
+  "*
+{
+  if (GET_CODE (operands[2]) == CONST_INT
+      && INTVAL (operands[2]) < 0)
+    return \"sub.h #%n2,%0\";
+  if (GREG_P (operands[0]))
+    {
+      if (CONSTANT_P (operands[2]))
+       return \"add:l %2,%0.w\";
+      else
+       return \"add:l %2.h,%0.w\";
+    }
+  return \"add.h %2,%0\";
+}")
+
+(define_insn ""
+  [(set (strict_low_part (match_operand:HI 0 "general_operand" "+rm"))
+       (plus:HI (match_dup 0)
+                (match_operand:HI 1 "general_operand" "rmi")))]
+  ""
+  "add.h %1,%0")
+
+(define_insn "addqi3"
+  [(set (match_operand:QI 0 "general_operand" "=rm")
+       (plus:QI (match_operand:QI 1 "general_operand" "%0")
+                (match_operand:QI 2 "general_operand" "rmi")))]
+  ""
+  "*
+{
+  if (GET_CODE (operands[2]) == CONST_INT
+      && INTVAL (operands[2]) < 0)
+    return \"sub.b #%n2,%0\";
+  if (GREG_P (operands[0]))
+    {
+      if (CONSTANT_P (operands[2]))
+       return \"add:l %2,%0.w\";
+      else
+       return \"add:l %2.b,%0.w\";
+    }
+  return \"add.b %2,%0\";
+}")
+
+(define_insn ""
+  [(set (strict_low_part (match_operand:QI 0 "general_operand" "+rm"))
+       (plus:QI (match_dup 0)
+                (match_operand:QI 1 "general_operand" "rmi")))]
+  ""
+  "add.b %1,%0")
+
+(define_insn "adddf3"
+  [(set (match_operand:DF 0 "general_operand" "=f")
+       (plus:DF (match_operand:DF 1 "general_operand" "%0")
+                (match_operand:DF 2 "general_operand" "fmG")))]
+  "TARGET_FPU"
+  "fadd.d %f2,%0")
+
+(define_insn "addsf3"
+  [(set (match_operand:SF 0 "general_operand" "=f")
+       (plus:SF (match_operand:SF 1 "general_operand" "%0")
+                (match_operand:SF 2 "general_operand" "fmG")))]
+  "TARGET_FPU"
+  "fadd.s %f2,%0")
+\f
+;; subtract instructions
+
+(define_insn "subsi3"
+  [(set (match_operand:SI 0 "general_operand" "=rm,!r")
+       (minus:SI (match_operand:SI 1 "general_operand" "0,r")
+                 (match_operand:SI 2 "general_operand" "rmi,i")))]
+  ""
+  "*
+{
+  if (which_alternative == 0
+      || (GET_CODE (operands[1]) == REG
+         && REGNO (operands[0]) == REGNO (operands[1])))
+    {
+      if (GET_CODE (operands[2]) == CONST_INT)
+       {
+         operands[1] = operands[2];
+         return sub_imm_word (INTVAL (operands[1]),
+                              operands[0], &operands[1]);
+       }
+      else
+       return \"sub.w %2,%0\";
+    }
+  else
+    return \"mova.w @(%n2,%1),%0\";
+}")
+
+(define_insn ""
+  [(set (match_operand:SI 0 "general_operand" "=rm")
+       (minus:SI (match_operand:SI 1 "general_operand" "0")
+                 (sign_extend:SI (match_operand:HI 2 "nonimmediate_operand" "rmi"))))]
+  ""
+  "sub %2.h,%0.w")
+
+(define_insn "subhi3"
+  [(set (match_operand:HI 0 "general_operand" "=rm")
+       (minus:HI (match_operand:HI 1 "general_operand" "0")
+                 (match_operand:HI 2 "general_operand" "rmi")))]
+  ""
+  "*
+{
+  if (GET_CODE (operands[2]) == CONST_INT
+      && INTVAL (operands[2]) < 0
+      && INTVAL (operands[2]) != 0x8000)
+    return \"add.h #%n2,%0\";
+  return \"sub.h %2,%0\";
+}")
+
+(define_insn ""
+  [(set (strict_low_part (match_operand:HI 0 "general_operand" "+rm"))
+       (minus:HI (match_dup 0)
+                 (match_operand:HI 1 "general_operand" "rmi")))]
+  ""
+  "sub.h %1,%0")
+
+(define_insn "subqi3"
+  [(set (match_operand:QI 0 "general_operand" "=rm")
+       (minus:QI (match_operand:QI 1 "general_operand" "0")
+                 (match_operand:QI 2 "general_operand" "rmi")))]
+  ""
+  "*
+{
+  if (GET_CODE (operands[2]) == CONST_INT
+      && INTVAL (operands[2]) < 0
+      && INTVAL (operands[2]) != 0x80)
+    return \"add.b #%n2,%0\";
+  return \"sub.b %2,%0\";
+}")
+
+(define_insn ""
+  [(set (strict_low_part (match_operand:QI 0 "general_operand" "+rm"))
+       (minus:QI (match_dup 0)
+                 (match_operand:QI 1 "general_operand" "rmi")))]
+  ""
+  "sub.b %1,%0")
+
+(define_insn "subdf3"
+  [(set (match_operand:DF 0 "general_operand" "=f")
+       (minus:DF (match_operand:DF 1 "general_operand" "0")
+                 (match_operand:DF 2 "general_operand" "fmG")))]
+  "TARGET_FPU"
+  "fsub.d %f2,%0")
+
+(define_insn "subsf3"
+  [(set (match_operand:SF 0 "general_operand" "=f")
+       (minus:SF (match_operand:SF 1 "general_operand" "0")
+                 (match_operand:SF 2 "general_operand" "fmG")))]
+  "TARGET_FPU"
+  "fsub.s %f2,%0")
+
+\f
+;; multiply instructions
+
+(define_insn "mulqi3"
+  [(set (match_operand:QI 0 "general_operand" "=rm")
+       (mult:QI (match_operand:QI 1 "general_operand" "%0")
+                (match_operand:QI 2 "general_operand" "rmi")))]
+  ""
+  "mul.b %2,%0")
+
+
+(define_insn "mulhi3"
+  [(set (match_operand:HI 0 "general_operand" "=rm")
+       (mult:HI (match_operand:HI 1 "general_operand" "%0")
+                (match_operand:HI 2 "general_operand" "rmi")))]
+  ""
+  "mul.h %2,%0")
+
+;; define_insn "mulhisi3"
+
+(define_insn "mulsi3"
+  [(set (match_operand:SI 0 "general_operand" "=rm")
+       (mult:SI (match_operand:SI 1 "general_operand" "%0")
+                (match_operand:SI 2 "general_operand" "rmi")))]
+  ""
+  "mul.w %2,%0")
+
+(define_insn "muldf3"
+  [(set (match_operand:DF 0 "general_operand" "=f")
+       (mult:DF (match_operand:DF 1 "general_operand" "%0")
+                (match_operand:DF 2 "general_operand" "fmG")))]
+  "TARGET_FPU"
+  "fmul.d %f2,%0")
+
+(define_insn "mulsf3"
+  [(set (match_operand:SF 0 "general_operand" "=f")
+       (mult:SF (match_operand:SF 1 "general_operand" "%0")
+                (match_operand:SF 2 "general_operand" "fmG")))]
+  "TARGET_FPU"
+  "fmul.s %f2,%0")
+
+\f
+;; divide instructions
+
+(define_insn "divqi3"
+  [(set (match_operand:QI 0 "general_operand" "=rm")
+       (div:QI (match_operand:QI 1 "general_operand" "0")
+               (match_operand:QI 2 "general_operand" "rmi")))]
+  ""
+  "div.b %2,%0")
+
+(define_insn "divhi3"
+  [(set (match_operand:HI 0 "general_operand" "=rm")
+       (div:HI (match_operand:HI 1 "general_operand" "0")
+               (match_operand:HI 2 "general_operand" "rmi")))]
+  ""
+  "div.h %2,%0")
+
+(define_insn "divhisi3"
+  [(set (match_operand:HI 0 "general_operand" "=r")
+       (div:HI (match_operand:SI 1 "general_operand" "0")
+               (match_operand:HI 2 "general_operand" "rmi")))]
+  ""
+  "div %2.h,%0.w")
+
+(define_insn "divsi3"
+  [(set (match_operand:SI 0 "general_operand" "=rm")
+       (div:SI (match_operand:SI 1 "general_operand" "0")
+               (match_operand:SI 2 "general_operand" "rmi")))]
+  ""
+  "div.w %2,%0")
+
+(define_insn "udivqi3"
+  [(set (match_operand:QI 0 "general_operand" "=rm")
+       (udiv:QI (match_operand:QI 1 "general_operand" "0")
+                (match_operand:QI 2 "general_operand" "rmi")))]
+  ""
+  "divu.b %2,%0")
+
+(define_insn "udivhi3"
+  [(set (match_operand:HI 0 "general_operand" "=rm")
+       (udiv:HI (match_operand:HI 1 "general_operand" "0")
+                (match_operand:HI 2 "general_operand" "rmi")))]
+  ""
+  "divu.h %2,%0")
+
+(define_insn "udivhisi3"
+  [(set (match_operand:HI 0 "general_operand" "=r")
+       (udiv:HI (match_operand:SI 1 "general_operand" "0")
+                (match_operand:HI 2 "general_operand" "rmi")))]
+  ""
+  "divu %2.h,%0.w")
+
+(define_insn "udivsi3"
+  [(set (match_operand:SI 0 "general_operand" "=rm")
+       (udiv:SI (match_operand:SI 1 "general_operand" "0")
+                (match_operand:SI 2 "general_operand" "rmi")))]
+  ""
+  "divu.w %2,%0")
+
+(define_insn "divdf3"
+  [(set (match_operand:DF 0 "general_operand" "=f")
+       (div:DF (match_operand:DF 1 "general_operand" "0")
+               (match_operand:DF 2 "general_operand" "fmG")))]
+  "TARGET_FPU"
+  "fdiv.d %f2,%0")
+
+(define_insn "divsf3"
+  [(set (match_operand:SF 0 "general_operand" "=f")
+       (div:SF (match_operand:SF 1 "general_operand" "0")
+               (match_operand:SF 2 "general_operand" "fmG")))]
+  "TARGET_FPU"
+  "fdiv.s %f2,%0")
+\f
+;; Remainder instructions.
+
+(define_insn "modqi3"
+  [(set (match_operand:QI 0 "general_operand" "=rm")
+       (mod:QI (match_operand:QI 1 "general_operand" "0")
+               (match_operand:QI 2 "general_operand" "rmi")))]
+  ""
+  "rem.b %2,%0")
+
+(define_insn "modhisi3"
+  [(set (match_operand:HI 0 "general_operand" "=r")
+       (mod:HI (match_operand:SI 1 "general_operand" "0")
+               (match_operand:HI 2 "general_operand" "rmi")))]
+  ""
+  "rem.h %2,%0")
+
+(define_insn "umodqi3"
+  [(set (match_operand:QI 0 "general_operand" "=rm")
+       (umod:QI (match_operand:QI 1 "general_operand" "0")
+                (match_operand:QI 2 "general_operand" "rmi")))]
+  ""
+  "remu.b %2,%0")
+
+(define_insn "umodhi3"
+  [(set (match_operand:HI 0 "general_operand" "=rm")
+       (umod:HI (match_operand:HI 1 "general_operand" "0")
+                (match_operand:HI 2 "general_operand" "rmi")))]
+  ""
+  "remu.h %2,%0")
+
+(define_insn "umodhisi3"
+  [(set (match_operand:HI 0 "general_operand" "=r")
+       (umod:HI (match_operand:SI 1 "general_operand" "0")
+                (match_operand:HI 2 "general_operand" "rmi")))]
+  ""
+  "remu %2.h,%0.w")
+
+;; define_insn "divmodsi4"
+
+(define_insn "udivmodsi4"
+  [(set (match_operand:SI 0 "general_operand" "=rm")
+       (udiv:SI (match_operand:SI 1 "general_operand" "0")
+                (match_operand:SI 2 "general_operand" "rmi")))
+   (set (match_operand:SI 3 "general_operand" "=r")
+       (umod:SI (match_dup 1) (match_dup 2)))]
+  ""
+  "mov.w #0,%3;divx.w %2,%0,%3")
+\f
+;; logical-and instructions
+
+(define_insn "andsi3"
+  [(set (match_operand:SI 0 "general_operand" "=rm")
+       (and:SI (match_operand:SI 1 "general_operand" "%0")
+               (match_operand:SI 2 "general_operand" "rmi")))]
+  ""
+  "*
+{
+  if (GET_CODE (operands[2]) == CONST_INT
+      && (INTVAL (operands[2]) | 0xffff) == 0xffffffff
+      && (GREG_P (operands[0])
+         || offsettable_memref_p (operands[0])))
+   
+    { 
+      if (GET_CODE (operands[0]) != REG)
+        operands[0] = adj_offsettable_operand (operands[0], 2);
+      operands[2] = gen_rtx (CONST_INT, VOIDmode,
+                            INTVAL (operands[2]) & 0xffff);
+      /* Do not delete a following tstl %0 insn; that would be incorrect.  */
+      CC_STATUS_INIT;
+      return \"and.h %2,%0\";
+    }
+  return \"and.w %2,%0\";
+}")
+
+(define_insn "andhi3"
+  [(set (match_operand:HI 0 "general_operand" "=rm")
+       (and:HI (match_operand:HI 1 "general_operand" "%0")
+               (match_operand:HI 2 "general_operand" "rmi")))]
+  ""
+  "and.h %2,%0")
+
+(define_insn "andqi3"
+  [(set (match_operand:QI 0 "general_operand" "=rm")
+       (and:QI (match_operand:QI 1 "general_operand" "%0")
+               (match_operand:QI 2 "general_operand" "rmi")))]
+  ""
+  "and.b %2,%0")
+
+(define_insn ""
+  [(set (match_operand:SI 0 "general_operand" "=r")
+       (and:SI (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "rm"))
+               (match_operand:SI 2 "general_operand" "0")))]
+  ""
+  "*
+{
+  if (GET_CODE (operands[1]) == CONST_INT)
+    return \"and %1,%0.w\";
+  return \"and %1.h,%0.w\";
+}")
+
+
+(define_insn ""
+  [(set (match_operand:SI 0 "general_operand" "=r")
+       (and:SI (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "rm"))
+               (match_operand:SI 2 "general_operand" "0")))]
+  ""
+  "*
+{
+  if (GET_CODE (operands[1]) == CONST_INT)
+    return \"and %1,%0.w\";
+  return \"and %1.b,%0.w\";
+}")
+\f
+;; inclusive-or instructions
+
+(define_insn "iorsi3"
+  [(set (match_operand:SI 0 "general_operand" "=rm")
+       (ior:SI (match_operand:SI 1 "general_operand" "%0")
+               (match_operand:SI 2 "general_operand" "rmi")))]
+  ""
+  "*
+{
+  register int logval;
+  if (GET_CODE (operands[2]) == CONST_INT
+      && INTVAL (operands[2]) >> 16 == 0
+      && (GREG_P (operands[0])
+         || offsettable_memref_p (operands[0])))
+    { 
+      if (GET_CODE (operands[0]) != REG)
+        operands[0] = adj_offsettable_operand (operands[0], 2);
+      /* Do not delete a following tstl %0 insn; that would be incorrect.  */
+      CC_STATUS_INIT;
+      return \"or.h %2,%0\";
+    }
+  if (GET_CODE (operands[2]) == CONST_INT
+      && (logval = exact_log2 (INTVAL (operands[2]))) >= 0
+      && (GREG_P (operands[0])
+         || offsettable_memref_p (operands[0])))
+    { 
+      if (GREG_P (operands[0]))
+       {
+         if (logval < 7)
+           {
+             operands[1] = gen_rtx (CONST_INT, VOIDmode, 7 - logval);
+             return \"bset.b %1,%0\";
+           }
+         operands[1] = gen_rtx (CONST_INT, VOIDmode, 31 - logval);
+         return \"bset.w %1,%0\";
+       }
+      else
+        {
+         operands[0] = adj_offsettable_operand (operands[0], 3 - (logval / 8));
+         operands[1] = gen_rtx (CONST_INT, VOIDmode, 7 - (logval % 8));
+       }
+      return \"bset.b %1,%0\";
+    }
+  return \"or.w %2,%0\";
+}")
+
+(define_insn "iorhi3"
+  [(set (match_operand:HI 0 "general_operand" "=rm")
+       (ior:HI (match_operand:HI 1 "general_operand" "%0")
+               (match_operand:HI 2 "general_operand" "rmi")))]
+  ""
+  "or.h %2,%0")
+
+(define_insn "iorqi3"
+  [(set (match_operand:QI 0 "general_operand" "=rm")
+       (ior:QI (match_operand:QI 1 "general_operand" "%0")
+               (match_operand:QI 2 "general_operand" "rmi")))]
+  ""
+  "or.b %2,%0")
+\f
+;; xor instructions
+
+(define_insn "xorsi3"
+  [(set (match_operand:SI 0 "general_operand" "=rm")
+       (xor:SI (match_operand:SI 1 "general_operand" "%0")
+               (match_operand:SI 2 "general_operand" "rmi")))]
+  ""
+  "*
+{
+  if (GET_CODE (operands[2]) == CONST_INT
+      && INTVAL (operands[2]) >> 16 == 0
+      && (offsettable_memref_p (operands[0]) || GREG_P (operands[0])))
+    { 
+      if (! GREG_P (operands[0]))
+       operands[0] = adj_offsettable_operand (operands[0], 2);
+      /* Do not delete a following tstl %0 insn; that would be incorrect.  */
+      CC_STATUS_INIT;
+      return \"xor.h %2,%0\";
+    }
+  return \"xor.w %2,%0\";
+}")
+
+(define_insn "xorhi3"
+  [(set (match_operand:HI 0 "general_operand" "=rm")
+       (xor:HI (match_operand:HI 1 "general_operand" "%0")
+               (match_operand:HI 2 "general_operand" "rmi")))]
+  ""
+  "xor.h %2,%0")
+
+(define_insn "xorqi3"
+  [(set (match_operand:QI 0 "general_operand" "=rm")
+       (xor:QI (match_operand:QI 1 "general_operand" "%0")
+               (match_operand:QI 2 "general_operand" "rmi")))]
+  ""
+  "xor.b %2,%0")
+\f
+;; negation instructions
+
+(define_insn "negsi2"
+  [(set (match_operand:SI 0 "general_operand" "=rm")
+       (neg:SI (match_operand:SI 1 "general_operand" "0")))]
+  ""
+  "neg.w %0")
+
+(define_insn "neghi2"
+  [(set (match_operand:HI 0 "general_operand" "=rm")
+       (neg:HI (match_operand:HI 1 "general_operand" "0")))]
+  ""
+  "neg.h %0")
+
+(define_insn "negqi2"
+  [(set (match_operand:QI 0 "general_operand" "=rm")
+       (neg:QI (match_operand:QI 1 "general_operand" "0")))]
+  ""
+  "neg.b %0")
+
+(define_insn "negsf2"
+  [(set (match_operand:SF 0 "general_operand" "f")
+       (neg:SF (match_operand:SF 1 "general_operand" "fmF")))]
+  "TARGET_FPU"
+  "fneg.s %f1,%0")
+
+
+(define_insn "negdf2"
+  [(set (match_operand:DF 0 "general_operand" "f")
+       (neg:DF (match_operand:DF 1 "general_operand" "fmF")))]
+  "TARGET_FPU"
+  "fneg.d %f1,%0")
+
+\f
+;; Absolute value instructions
+
+(define_insn "abssf2"
+  [(set (match_operand:SF 0 "general_operand" "f")
+       (abs:SF (match_operand:SF 1 "general_operand" "fmF")))]
+  "TARGET_FPU"
+  "fabs.s %f1,%0")
+
+(define_insn "absdf2"
+  [(set (match_operand:DF 0 "general_operand" "f")
+       (abs:DF (match_operand:DF 1 "general_operand" "fmF")))]
+  "TARGET_FPU"
+  "fabs.d %f1,%0")
+
+\f
+;; one complement instructions
+
+(define_insn "one_cmplsi2"
+  [(set (match_operand:SI 0 "general_operand" "=rm")
+       (not:SI (match_operand:SI 1 "general_operand" "0")))]
+  ""
+  "not.w %0")
+
+(define_insn "one_cmplhi2"
+  [(set (match_operand:HI 0 "general_operand" "=rm")
+       (not:HI (match_operand:HI 1 "general_operand" "0")))]
+  ""
+  "not.h %0")
+
+(define_insn "one_cmplqi2"
+  [(set (match_operand:QI 0 "general_operand" "=rm")
+       (not:QI (match_operand:QI 1 "general_operand" "0")))]
+  ""
+  "not.b %0")
+\f
+;; Optimized special case of shifting.
+;; Must precede the general case.
+
+(define_insn ""
+  [(set (match_operand:SI 0 "general_operand" "=r")
+       (ashiftrt:SI (match_operand:SI 1 "memory_operand" "m")
+                    (const_int 24)))]
+  "GET_CODE (XEXP (operands[1], 0)) != POST_INC
+   && GET_CODE (XEXP (operands[1], 0)) != PRE_DEC"
+  "mov:l %1.b,%0.w")
+
+(define_insn ""
+  [(set (match_operand:SI 0 "general_operand" "=r")
+       (lshiftrt:SI (match_operand:SI 1 "memory_operand" "m")
+                    (const_int 24)))]
+  "GET_CODE (XEXP (operands[1], 0)) != POST_INC
+   && GET_CODE (XEXP (operands[1], 0)) != PRE_DEC"
+  "movu %1.b,%0.w")
+
+(define_insn ""
+  [(set (cc0) (compare (match_operand:QI 0 "general_operand" "i")
+                      (lshiftrt:SI (match_operand:SI 1 "memory_operand" "m")
+                                   (const_int 24))))]
+  "(GET_CODE (operands[0]) == CONST_INT
+    && (INTVAL (operands[0]) & ~0xff) == 0)"
+  "*
+{
+  cc_status.flags |= CC_REVERSED;
+  if (my_signed_comp (insn))
+    return \"cmp.b %0,%1\";
+  return \"cmpu.b %0,%1\";
+}")
+
+(define_insn ""
+  [(set (cc0) (compare (lshiftrt:SI (match_operand:SI 0 "memory_operand" "m")
+                                   (const_int 24))
+                      (match_operand:QI 1 "general_operand" "i")))]
+  "(GET_CODE (operands[1]) == CONST_INT
+    && (INTVAL (operands[1]) & ~0xff) == 0)"
+  "*
+  if (my_signed_comp (insn))
+       return \"cmp.b %1,%0\";
+  return \"cmpu.b %1,%0\";
+")
+
+(define_insn ""
+  [(set (cc0) (compare (match_operand:QI 0 "general_operand" "i")
+                      (ashiftrt:SI (match_operand:SI 1 "memory_operand" "m")
+                                   (const_int 24))))]
+  "(GET_CODE (operands[0]) == CONST_INT
+    && ((INTVAL (operands[0]) + 0x80) & ~0xff) == 0)"
+  "*
+  cc_status.flags |= CC_REVERSED;
+  if (my_signed_comp (insn))
+       return \"cmp.b %0,%1\";
+  return \"cmpu.b %0,%1\";
+")
+
+(define_insn ""
+  [(set (cc0) (compare (ashiftrt:SI (match_operand:SI 0 "memory_operand" "m")
+                                   (const_int 24))
+                      (match_operand:QI 1 "general_operand" "i")))]
+  "(GET_CODE (operands[1]) == CONST_INT
+    && ((INTVAL (operands[1]) + 0x80) & ~0xff) == 0)"
+  "*
+  if (my_signed_comp (insn))
+       return \"cmp.b %1,%0\";
+  return \"cmpu.b %1,%0\";
+")
+\f
+;; arithmetic shift instructions
+;; We don't need the shift memory by 1 bit instruction
+
+(define_insn "ashlsi3"
+  [(set (match_operand:SI 0 "general_operand" "=rm")
+       (ashift:SI (match_operand:SI 1 "general_operand" "0")
+                  (match_operand:SI 2 "general_operand" "rmi")))]
+  ""
+  "sha.w %2,%0")
+
+(define_insn "ashlhi3"
+  [(set (match_operand:HI 0 "general_operand" "=rm")
+       (ashift:HI (match_operand:HI 1 "general_operand" "0")
+                  (match_operand:HI 2 "general_operand" "rmi")))]
+  ""
+  "sha.h %2,%0")
+
+(define_insn "ashlqi3"
+  [(set (match_operand:QI 0 "general_operand" "=rm")
+       (ashift:QI (match_operand:QI 1 "general_operand" "0")
+                  (match_operand:QI 2 "general_operand" "rmi")))]
+  ""
+  "sha.b %2,%0")
+
+;; Arithmetic right shift on the Gmicro works by negating the shift count
+
+;; ashiftrt -> ashift
+(define_expand "ashrsi3"
+  [(set (match_operand:SI 0 "general_operand" "=rm")
+       (ashift:SI (match_operand:SI 1 "general_operand" "0")
+                    (match_operand:SI 2 "general_operand" "rmi")))]
+  ""
+  "{ operands[2] = negate_rtx (SImode, operands[2]); }")
+
+;; ashiftrt -> ashift
+(define_expand "ashrhi3"
+  [(set (match_operand:HI 0 "general_operand" "=rm")
+       (ashift:HI (match_operand:HI 1 "general_operand" "0")
+                    (match_operand:HI 2 "general_operand" "rmi")))]
+  ""
+  " { operands[2] = negate_rtx (HImode, operands[2]); }")
+
+;; ashiftrt -> ashift
+(define_expand "ashrqi3"
+  [(set (match_operand:QI 0 "general_operand" "=rm")
+       (ashift:QI (match_operand:QI 1 "general_operand" "0")
+                    (match_operand:QI 2 "general_operand" "rmi")))]
+  ""
+  " { operands[2] = negate_rtx (QImode, operands[2]); }")
+\f
+;; logical shift instructions
+
+(define_insn "lshlsi3"
+  [(set (match_operand:SI 0 "general_operand" "=rm")
+       (lshift:SI (match_operand:SI 1 "general_operand" "0")
+                  (match_operand:SI 2 "general_operand" "rmi")))]
+  ""
+  "shl.w %2,%0")
+
+(define_insn "lshlhi3"
+  [(set (match_operand:HI 0 "general_operand" "=rm")
+       (lshift:HI (match_operand:HI 1 "general_operand" "0")
+                  (match_operand:HI 2 "general_operand" "rmi")))]
+  ""
+  "shl.h %2,%0")
+
+(define_insn "lshlqi3"
+  [(set (match_operand:QI 0 "general_operand" "=rm")
+       (lshift:QI (match_operand:QI 1 "general_operand" "0")
+                  (match_operand:QI 2 "general_operand" "rmi")))]
+  ""
+  "shl.b %2,%0")
+
+;; lshiftrt -> lshift
+(define_expand "lshrsi3"
+  [(set (match_operand:SI 0 "general_operand" "=rm")
+       (lshift:SI (match_operand:SI 1 "general_operand" "0")
+                    (match_operand:SI 2 "general_operand" "rmi")))]
+  ""
+  " { operands[2] = negate_rtx (SImode, operands[2]); }")
+
+;; lshiftrt -> lshift
+(define_expand "lshrhi3"
+  [(set (match_operand:HI 0 "general_operand" "=rm")
+       (lshift:HI (match_operand:HI 1 "general_operand" "0")
+                    (match_operand:HI 2 "general_operand" "rmi")))]
+  ""
+  " { operands[2] = negate_rtx (HImode, operands[2]); }")
+
+;; lshiftrt -> lshift
+(define_expand "lshrqi3"
+  [(set (match_operand:QI 0 "general_operand" "=rm")
+       (lshift:QI (match_operand:QI 1 "general_operand" "0")
+                    (match_operand:QI 2 "general_operand" "rmi")))]
+  ""
+  " { operands[2] = negate_rtx (QImode, operands[2]); }")
+\f
+;; rotate instructions
+
+(define_insn "rotlsi3"
+  [(set (match_operand:SI 0 "general_operand" "=rm")
+       (rotate:SI (match_operand:SI 1 "general_operand" "0")
+                  (match_operand:SI 2 "general_operand" "rmi")))]
+  ""
+  "rol.w %2,%0")
+
+(define_insn "rotlhi3"
+  [(set (match_operand:HI 0 "general_operand" "=rm")
+       (rotate:HI (match_operand:HI 1 "general_operand" "0")
+                  (match_operand:HI 2 "general_operand" "rmi")))]
+  ""
+  "rol.h %2,%0")
+
+(define_insn "rotlqi3"
+  [(set (match_operand:QI 0 "general_operand" "=rm")
+       (rotate:QI (match_operand:QI 1 "general_operand" "0")
+                  (match_operand:QI 2 "general_operand" "rmi")))]
+  ""
+  "rol.b %2,%0")
+
+(define_expand "rotrsi3"
+  [(set (match_operand:SI 0 "general_operand" "=rm")
+       (rotatert:SI (match_operand:SI 1 "general_operand" "0")
+                    (match_operand:SI 2 "general_operand" "rmi")))]
+  ""
+  " { operands[2] = negate_rtx (SImode, operands[2]); }")
+
+(define_expand "rotrhi3"
+  [(set (match_operand:HI 0 "general_operand" "=rm")
+       (rotatert:HI (match_operand:HI 1 "general_operand" "0")
+                    (match_operand:HI 2 "general_operand" "rmi")))]
+  ""
+  " { operands[2] = negate_rtx (HImode, operands[2]); }")
+
+(define_expand "rotrqi3"
+  [(set (match_operand:QI 0 "general_operand" "=rm")
+       (rotatert:QI (match_operand:QI 1 "general_operand" "0")
+                    (match_operand:QI 2 "general_operand" "rmi")))]
+  ""
+  " { operands[2] = negate_rtx (QImode, operands[2]); }")
+\f
+;; Special cases of bit-field insns which we should
+;; recognize in preference to the general case.
+;; These handle aligned 8-bit and 16-bit fields,
+;; which can usually be done with move instructions.
+
+;; Should I add  mode_dependent_address_p ????
+
+(define_insn ""
+  [(set (zero_extract:SI (match_operand:SI 0 "nonimmediate_operand" "+rm")
+                        (match_operand:SI 1 "immediate_operand" "i")
+                        (match_operand:SI 2 "immediate_operand" "i"))
+       (match_operand:SI 3 "general_operand" "rm"))]
+  "TARGET_BITFIELD
+   && GET_CODE (operands[1]) == CONST_INT
+   && (INTVAL (operands[1]) == 8 || INTVAL (operands[1]) == 16)
+   && GET_CODE (operands[2]) == CONST_INT
+   && INTVAL (operands[2]) % INTVAL (operands[1]) == 0
+   && (GET_CODE (operands[0]) != REG
+       || ( INTVAL (operands[1]) + INTVAL (operands[2]) == 32))"
+  "*
+{
+  if (GET_CODE (operands[3]) == MEM)
+    operands[3] = adj_offsettable_operand (operands[3],
+                                          (32 - INTVAL (operands[1])) / 8);
+
+  if (GET_CODE (operands[0]) == REG)
+    {
+      if (INTVAL (operands[1]) == 8)
+       return \"movu %3.b,%0.w\";
+      return \"movu %3.h,%0.w\";
+    }
+  else
+    {
+      operands[0]
+       = adj_offsettable_operand (operands[0], INTVAL (operands[2]) / 8);
+      if (INTVAL (operands[1]) == 8)
+       return \"mov.b %3,%0\";
+      return \"mov.h %3,%0\";
+    }
+}")
+
+(define_insn ""
+  [(set (match_operand:SI 0 "general_operand" "=&r")
+       (zero_extract:SI (match_operand:SI 1 "nonimmediate_operand" "rm")
+                        (match_operand:SI 2 "immediate_operand" "i")
+                        (match_operand:SI 3 "immediate_operand" "i")))]
+  "TARGET_BITFIELD
+   && GET_CODE (operands[2]) == CONST_INT
+   && (INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 16)
+   && GET_CODE (operands[3]) == CONST_INT
+   && INTVAL (operands[3]) % INTVAL (operands[2]) == 0"
+  "*
+{
+  if (!REG_P (operands[1]))
+    operands[1]
+      = adj_offsettable_operand (operands[1], INTVAL (operands[3]) / 8);
+
+  if (REG_P (operands[0]))
+    {
+      if (REG_P (operands[1]))
+       {
+         if (INTVAL (operands[2]) == 8)
+           {                   /* width == 8 */
+             switch (INTVAL (operands[3]))
+               {
+               case 0:
+                 return \"mov.w %1,%0;shl.w #-24,%0\";
+                 break;
+               case 8:
+                 return \"mov.w %1,%0;shl.w #8,%0;shl.w #-24,%0\";
+                 break;
+               case 16:
+                 return \"mov.w %1,%0;shl.w #16,%0;shl.w #-24,%0\";
+                 break;
+               case 24:
+                 return \"movu %1.b,%0.w\";
+                 break;
+               default:
+                 myabort (2);
+               }
+           }
+         else
+           {
+             switch (INTVAL (operands[3]))
+               {
+               case 0:
+                 return \"mov.w %1,%0;shl.w #-16,%0\";
+                 break;
+               case 16:
+                 return \"movu %1.h,%0.w\";
+                 break;
+               default:
+                 myabort (3);
+               }
+           }
+       }
+      else
+       {
+         if (INTVAL (operands[2]) == 8)
+           return \"movu %1.h,%0.w\";
+         else
+           return \"movu %1.b,%0.w\";
+       }
+    }
+  else
+    {                          /* op[0] == MEM */
+      if (INTVAL (operands[2]) == 8)
+       return \"movu %1.b,%0.w\";
+      return \"movu %1.h,%0.w\";
+    }
+}")
+
+(define_insn ""
+  [(set (match_operand:SI 0 "general_operand" "=r")
+       (sign_extract:SI (match_operand:SI 1 "nonimmediate_operand" "ro")
+                        (match_operand:SI 2 "immediate_operand" "i")
+                        (match_operand:SI 3 "immediate_operand" "i")))]
+  "TARGET_BITFIELD
+   && GET_CODE (operands[2]) == CONST_INT
+   && (INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 16)
+   && GET_CODE (operands[3]) == CONST_INT
+   && INTVAL (operands[3]) % INTVAL (operands[2]) == 0"
+  "*
+{
+  if (!REG_P (operands[1]))
+    operands[1]
+      = adj_offsettable_operand (operands[1], INTVAL (operands[3]) / 8);
+
+  if (REG_P (operands[0]))
+    {
+      if (REG_P (operands[1]))
+       {
+         if (INTVAL (operands[2]) == 8)
+           {                   /* width == 8 */
+             switch (INTVAL (operands[3]))
+               {
+               case 0:
+                 return \"mov.w %1,%0;sha.w #-24,%0\";
+                 break;
+               case 8:
+                 return \"mov.w %1,%0;shl.w #8,%0;sha.w #-24,%0\";
+                 break;
+               case 16:
+                 return \"mov.w %1,%0;shl.w #16,%0;sha.w #-24,%0\";
+                 break;
+               case 24:
+                 return \"mov %1.b,%0.w\";
+                 break;
+               default:
+                 myabort (4);
+               }
+           }
+         else
+           {
+             switch (INTVAL (operands[3]))
+               {
+               case 0:
+                 return \"mov.w %1,%0;sha.w #-16,%0\";
+                 break;
+               case 16:
+                 return \"mov %1.h,%0.w\";
+                 break;
+               default:
+                 myabort (5);
+               }
+           }
+       }
+      else
+       {
+         if (INTVAL (operands[2]) == 8)
+           return \"mov %1.h,%0.w\";
+         else
+           return \"mov %1.b,%0.w\";
+       }
+    }
+  else
+    {                          /* op[0] == MEM */
+      if (INTVAL (operands[2]) == 8)
+       return \"mov %1.b,%0.w\";
+      return \"mov %1.h,%0.w\";
+    }
+}")
+\f
+;; Bit field instructions, general cases.
+;; "o,d" constraint causes a nonoffsettable memref to match the "o"
+;; so that its address is reloaded.
+
+;; extv dest:SI src(:QI/:SI) width:SI pos:SI
+;;        r.w    m            r.w/#    rmi  
+;;        %0     %1           %2       %3
+
+(define_insn "extv"
+  [(set (match_operand:SI 0 "general_operand" "=r")
+       (sign_extract:SI (match_operand:QI 1 "nonimmediate_operand" "m")
+                        (match_operand:SI 2 "general_operand" "ri")
+                        (match_operand:SI 3 "general_operand" "rmi")))]
+  "TARGET_BITFIELD"
+  "bfext %3,%2,%1,%0")
+
+
+(define_insn "extzv"
+  [(set (match_operand:SI 0 "general_operand" "=r")
+       (zero_extract:SI (match_operand:QI 1 "nonimmediate_operand" "m")
+                        (match_operand:SI 2 "general_operand" "ri")
+                        (match_operand:SI 3 "general_operand" "rmi")))]
+  "TARGET_BITFIELD"
+  "bfextu %3,%2,%1,%0")
+
+;; There is no insn on the Gmicro to NOT/SET/CLR bitfield.
+
+
+;; insv dest(BF):QI/SI  width:SI  pos:SI  src:SI
+;;        m                r.w      rmi     r.w/i
+;;        0                1        2       3
+
+
+(define_insn "insv"
+  [(set (zero_extract:SI (match_operand:QI 0 "nonimmediate_operand" "+m,m")
+                        (match_operand:SI 1 "general_operand" "r,i")
+                        (match_operand:SI 2 "general_operand" "rmi,i"))
+       (match_operand:SI 3 "general_operand" "ri,ri"))]
+  "TARGET_BITFIELD"
+  "bfinsu %3,%2,%1,%0")
+;;; bfins/bfinsu ????????
+
+;; == == == == == == == == == == == == == 
+
+;; Now recognize bit field insns that operate on registers
+;; (or at least were intended to do so).
+
+;; On the Gmicro/300,
+;; bitfield instructions are not applicable to registers ;-<
+;; But I write the register cases, because without them the gcc
+;; seems to use "and" instruction with some other instructions
+;; instead of using a shift instruction.
+;; It is because on many processors shift instructions are slower.
+;; On the Gmicro/300 which has a barrel shifter,
+;; it is faster to use a shift instruction.
+;;
+;; Restricts width and offset to be immediates.
+;;
+(define_insn ""
+  [(set (match_operand:SI 0 "general_operand" "=r")
+       (sign_extract:SI (match_operand:SI 1 "nonimmediate_operand" "r")
+                        (match_operand:SI 2 "immediate_operand" "i")
+                        (match_operand:SI 3 "immediate_operand" "i")))]
+  "TARGET_BITFIELD"
+  "*
+{
+  if (REGNO (operands[0]) != REGNO (operands[1]))
+    output_asm_insn (\"mov.w %1,%0\", operands);
+  if (INTVAL (operands[3]) != 0)
+    output_asm_insn (\"shl.w %3,%0\", operands);
+  operands[2] = gen_rtx (CONST_INT, VOIDmode, -(32 - INTVAL (operands[2])));
+  return \"sha.w %3,%0\";
+}")
+    
+
+(define_insn ""
+  [(set (match_operand:SI 0 "general_operand" "=r")
+       (zero_extract:SI (match_operand:SI 1 "nonimmediate_operand" "r")
+                        (match_operand:SI 2 "immediate_operand" "i")
+                        (match_operand:SI 3 "immediate_operand" "i")))]
+  "TARGET_BITFIELD"
+  "*
+{
+  if (REGNO (operands[0]) != REGNO (operands[1]))
+    output_asm_insn (\"mov.w %1,%0\", operands);
+  if (INTVAL (operands[3]) != 0)
+    output_asm_insn (\"shl.w %3,%0\", operands);
+  operands[2] = gen_rtx (CONST_INT, VOIDmode, -(32 - INTVAL (operands[2])));
+  return \"shl.w %3,%0\";
+}")
+
+
+;; There are more descriptions for m68k, but not yet for the Gmicro.
+;;
+\f
+;; Basic conditional jump instructions.
+
+
+(define_insn "beq"
+  [(set (pc)
+       (if_then_else (eq (cc0)
+                         (const_int 0))
+                     (label_ref (match_operand 0 "" ""))
+                     (pc)))]
+  ""
+  "*
+{
+  OUTPUT_JUMP (\"beq %b0\", \"fbeq %b0\", \"beq %b0\");
+}")
+
+(define_insn "bne"
+  [(set (pc)
+       (if_then_else (ne (cc0)
+                         (const_int 0))
+                     (label_ref (match_operand 0 "" ""))
+                     (pc)))]
+  ""
+  "*
+{
+  OUTPUT_JUMP (\"bne %b0\", \"fbne %b0\", \"bne %b0\");
+}")
+
+(define_insn "bgt"
+  [(set (pc)
+       (if_then_else (gt (cc0)
+                         (const_int 0))
+                     (label_ref (match_operand 0 "" ""))
+                     (pc)))]
+  ""
+  "*
+  OUTPUT_JUMP (\"bgt %b0\", \"fbgt %b0\", 0);
+")
+
+(define_insn "bgtu"
+  [(set (pc)
+       (if_then_else (gtu (cc0)
+                          (const_int 0))
+                     (label_ref (match_operand 0 "" ""))
+                     (pc)))]
+  ""
+  "bgt %b0")
+
+(define_insn "blt"
+  [(set (pc)
+       (if_then_else (lt (cc0)
+                         (const_int 0))
+                     (label_ref (match_operand 0 "" ""))
+                     (pc)))]
+  ""
+  "*
+  OUTPUT_JUMP (\"blt %b0\", \"fblt %b0\", \"bms %b0\");
+")
+
+;; bms ?????
+;; 
+
+(define_insn "bltu"
+  [(set (pc)
+       (if_then_else (ltu (cc0)
+                          (const_int 0))
+                     (label_ref (match_operand 0 "" ""))
+                     (pc)))]
+  ""
+  "blt %b0")
+
+(define_insn "bge"
+  [(set (pc)
+       (if_then_else (ge (cc0)
+                         (const_int 0))
+                     (label_ref (match_operand 0 "" ""))
+                     (pc)))]
+  ""
+  "*
+  OUTPUT_JUMP (\"bge %b0\", \"fbge %b0\", \"bmc %b0\");
+")
+
+;; bmc ??
+
+(define_insn "bgeu"
+  [(set (pc)
+       (if_then_else (geu (cc0)
+                          (const_int 0))
+                     (label_ref (match_operand 0 "" ""))
+                     (pc)))]
+  ""
+  "bge %b0")
+
+(define_insn "ble"
+  [(set (pc)
+       (if_then_else (le (cc0)
+                         (const_int 0))
+                     (label_ref (match_operand 0 "" ""))
+                     (pc)))]
+  ""
+  "ble %b0")
+
+(define_insn "bleu"
+  [(set (pc)
+       (if_then_else (leu (cc0)
+                          (const_int 0))
+                     (label_ref (match_operand 0 "" ""))
+                     (pc)))]
+  ""
+  "ble %b0")
+\f
+;; Negated conditional jump instructions.
+
+(define_insn ""
+  [(set (pc)
+       (if_then_else (eq (cc0)
+                         (const_int 0))
+                     (pc)
+                     (label_ref (match_operand 0 "" ""))))]
+  ""
+  "*
+{
+  OUTPUT_JUMP (\"bne %b0\", \"fbne %b0\", \"bne %b0\");
+}")
+
+(define_insn ""
+  [(set (pc)
+       (if_then_else (ne (cc0)
+                         (const_int 0))
+                     (pc)
+                     (label_ref (match_operand 0 "" ""))))]
+  ""
+  "*
+{
+  OUTPUT_JUMP (\"beq %b0\", \"fbeq %b0\", \"beq %b0\");
+}")
+
+(define_insn ""
+  [(set (pc)
+       (if_then_else (gt (cc0)
+                         (const_int 0))
+                     (pc)
+                     (label_ref (match_operand 0 "" ""))))]
+  ""
+  "*
+  OUTPUT_JUMP (\"ble %b0\", \"fbngt %b0\", 0);
+")
+;; fbngt ???
+
+(define_insn ""
+  [(set (pc)
+       (if_then_else (gtu (cc0)
+                          (const_int 0))
+                     (pc)
+                     (label_ref (match_operand 0 "" ""))))]
+  ""
+  "ble %b0")
+
+(define_insn ""
+  [(set (pc)
+       (if_then_else (lt (cc0)
+                         (const_int 0))
+                     (pc)
+                     (label_ref (match_operand 0 "" ""))))]
+  ""
+  "*
+  OUTPUT_JUMP (\"bge %b0\", \"fbnlt %b0\", \"jbmc %b0\");
+")
+
+(define_insn ""
+  [(set (pc)
+       (if_then_else (ltu (cc0)
+                          (const_int 0))
+                     (pc)
+                     (label_ref (match_operand 0 "" ""))))]
+  ""
+  "blt %b0")
+
+(define_insn ""
+  [(set (pc)
+       (if_then_else (ge (cc0)
+                         (const_int 0))
+                     (pc)
+                     (label_ref (match_operand 0 "" ""))))]
+  ""
+  "*
+  OUTPUT_JUMP (\"blt %b0\", \"fbnge %b0\", \"jbms %b0\");
+")
+
+(define_insn ""
+  [(set (pc)
+       (if_then_else (geu (cc0)
+                          (const_int 0))
+                     (pc)
+                     (label_ref (match_operand 0 "" ""))))]
+  ""
+  "blt %b0")
+;; ????
+
+(define_insn ""
+  [(set (pc)
+       (if_then_else (le (cc0)
+                         (const_int 0))
+                     (pc)
+                     (label_ref (match_operand 0 "" ""))))]
+  ""
+  "*
+  OUTPUT_JUMP (\"bgt %b0\", \"fbnle %b0\", 0);
+")
+
+(define_insn ""
+  [(set (pc)
+       (if_then_else (leu (cc0)
+                          (const_int 0))
+                     (pc)
+                     (label_ref (match_operand 0 "" ""))))]
+  ""
+  "bgt %b0")
+\f
+;; Unconditional and other jump instructions
+(define_insn "jump"
+  [(set (pc)
+       (label_ref (match_operand 0 "" "")))]
+  ""
+  "bra %b0")
+
+(define_insn "tablejump"
+  [(set (pc)
+       (plus:SI (pc) (match_operand:SI 0 "general_operand" "r")))
+   (use (label_ref (match_operand 1 "" "")))]
+  ""
+  "jmp @(pc:b,4:4,%0)")
+
+;;
+;; Should Add code for "ACB", "SCB". !!! ????
+;; See m68k.h (dbra)
+;;
+
+;; Call subroutine with no return value.
+(define_insn "call"
+  [(call (match_operand:QI 0 "general_operand" "m")
+        (match_operand:SI 1 "general_operand" "rmi"))]
+  ;; Operand 1 not really used on the Gmicro.
+
+  ""
+  "*
+{
+  if (GET_CODE (operands[0]) == MEM
+      && GET_CODE (XEXP (operands[0],0)) == SYMBOL_REF)
+    return \"bsr %b0\";
+  return \"jsr %0\";
+}")
+
+;; Call subroutine, returning value in operand 0
+;; (which must be a hard register).
+(define_insn "call_value"
+  [(set (match_operand 0 "" "=rf")
+       (call (match_operand:QI 1 "general_operand" "m")
+             (match_operand:SI 2 "general_operand" "rmi")))]
+  ;; Operand 2 not really used on the Gmicro.
+  ""
+  "*
+{
+  if (GET_CODE (operands[1]) == MEM
+      && GET_CODE (XEXP (operands[1],0)) == SYMBOL_REF)
+    return \"bsr %b1\";
+  return \"jsr %1\";
+}")
+
+(define_insn "nop"
+  [(const_int 0)]
+    ""
+    "nop")
+\f
+;; Turned off because the general move-an-address pattern handles it.
+;; 
+;; Thus goes after the move instructions
+;; because the move instructions are better (require no spilling)
+;; when they can apply. 
+;; After add/sub now !!
+
+;(define_insn "pushasi"
+;  [(set (match_operand:SI 0 "push_operand" "=m")
+;      (match_operand:SI 1 "address_operand" "p"))]
+;  ""
+;  "*
+;{
+;  if (GET_CODE (operands[1]) == CONST_INT)
+;    return push_imm_word (INTVAL (operands[1]), operands[0]);
+;  if (CONSTANT_P (operands[1]))
+;    return \"mov.w %1,%-\";
+;  if (GET_CODE (operands[1]) == REG)
+;    return \"mov.w %1,%-\";
+;  else if (GET_CODE (operands[1]) == MEM)
+;    {
+;      return \"mov.w %1,%-\";
+;    }
+;  else
+;    return \"mova.w %p1,%-\";
+;}")
+\f
+;; This should not be used unless the add/sub insns can't be.
+
+/* mova.[whq] 89.08.11 for test M.Yuhara */
+;(define_insn ""
+;  [(set (match_operand:SI 0 "general_operand" "=rm")
+;      (address (match_operand:SI 1 "address_operand" "p")))]
+;  ""
+;  "*
+;{
+;    if (GET_CODE (operands[1]) == CONST_INT)
+;        return mov_imm_word (INTVAL (operands[1]), operands[0]);
+;    if (CONSTANT_P (operands[1]))
+;        return \"mov.w %1,%0\";
+;    if (GET_CODE (operands[1]) == REG)
+;        return \"mov.w %1,%0\";
+;    else  if (GET_CODE (operands[1]) == MEM) {
+;      operands[1] = XEXP (operands[1],0);
+;        return \"mov.w %1,%0\";
+;    }
+;    else
+;        return \"mova.w %p1,%0\";
+;}")
+
+
+(define_insn ""
+  [(set (match_operand:SI 0 "general_operand" "=rm")
+       (address (match_operand:HI 1 "address_operand" "")))]
+  ""
+  "*
+{
+  if (GET_CODE (operands[1]) == CONST_INT)
+    return mov_imm_word (INTVAL (operands[1]), operands[0]);
+  if (CONSTANT_P (operands[1]))
+    return \"mov.w %1,%0\";
+  if (GET_CODE (operands[1]) == REG)
+    return \"mov.w %1,%0\";
+  else  if (GET_CODE (operands[1]) == MEM)
+    {
+      operands[1] = XEXP (operands[1],0);
+      return \"mov.w %1,%0\";  /* OK ? */
+    }
+  else
+    return \"mova.w %p1,%0\";
+}")
+
+;(define_insn ""
+;  [(set (match_operand:SI 0 "general_operand" "=rm")
+;      (match_operand:QI 1 "address_operand" "p"))]
+;  ""
+;  "*
+;{
+;  if (push_operand (operands[0], SImode))
+;    return \"mova %1,%-\";
+;  return \"mova %1,%0\";
+;}")
+
+;(define_insn ""
+;  [(set (match_operand:SI 0 "general_operand" "=rm")
+;      (match_operand:QI 1 "address_operand" "p"))]
+;  ""
+;  "*
+;{
+;  if (CONSTANT_P (operands[1]))
+;    return \"mov.w %1,%0\";
+;  else if (GET_CODE (operands[1]) == REG)
+;    return \"mov.w %1,%0\";
+;  else if (GET_CODE (operands[1]) == MEM)
+;    {
+;      operands[1] = XEXP (operands[1],0);
+;      return \"mov.w %1,%0 ; OK?\";
+;    }
+;  else if (GET_CODE (operands[0]) == REG
+;         && GET_CODE (operands[1]) == PLUS)
+;    {
+;      rtx xreg, xdisp;
+;
+;      if (GET_CODE (XEXP (operands[1], 0)) == REG 
+;        && REGNO (XEXP (operands[1], 0)) == REGNO (operands[0]))
+;      {
+;        xreg = XEXP (operands[1], 0);
+;        xdisp = XEXP (operands[1],1);
+;      }
+;      else
+;      {
+;        xreg = XEXP (operands[1], 1);
+;        xdisp = XEXP (operands[1],0);
+;      }
+;
+;      if (GET_CODE (xreg) == REG
+;        && REGNO (xreg) == REGNO (operands[0])
+;        && (CONSTANT_P (xdisp) || GET_CODE (xdisp) == REG))
+;      {
+;        operands[1] = xdisp;
+;        if (CONSTANT_P (xdisp))
+;          return add_imm_word (INTVAL (xdisp), xreg, &operands[1]);
+;        else
+;          return \"add.w %1,%0\";
+;      }
+;    }
+;  return \"mova.w %p1,%0\";
+;}")
+\f
+;; This is the first machine-dependent peephole optimization.
+;; It is useful when a floating value is returned from a function call
+;; and then is moved into an FP register.
+;; But it is mainly intended to test the support for these optimizations.
+
+(define_peephole
+  [(set (reg:SI 15) (plus:SI (reg:SI 15) (const_int 4)))
+   (set (match_operand:DF 0 "register_operand" "f")
+       (match_operand:DF 1 "register_operand" "r"))]
+  "FPU_REG_P (operands[0]) && ! FPU_REG_P (operands[1])"
+  "*
+{
+  rtx xoperands[2];
+  xoperands[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
+  output_asm_insn (\"mov.w %1,@sp\", xoperands);
+  output_asm_insn (\"mov.w %1,%-\", operands);
+  return \"fmov.d %+,%0\";
+}
+")
+\f
+
+;;- Local variables:
+;;- mode:emacs-lisp
+;;- comment-start: ";;- "
+;;- comment-start-skip: ";+- *"
+;;- eval: (set-syntax-table (copy-sequence (syntax-table)))
+;;- eval: (modify-syntax-entry ?[ "(]")
+;;- eval: (modify-syntax-entry ?] ")[")
+;;- eval: (modify-syntax-entry ?{ "(}")
+;;- eval: (modify-syntax-entry ?} "){")
+;;- End: