OSDN Git Service

* config/mips/pdp11.md (negsi2): Fix wrong code.
[pf3gnuchains/gcc-fork.git] / gcc / config / pdp11 / pdp11.md
index f07acef..2d4eb8a 100644 (file)
@@ -1,28 +1,58 @@
 ;;- Machine description for the pdp11 for GNU C compiler
-;; Copyright (C) 1994, 1995, 1997, 1999 Free Software Foundation, Inc.
+;; Copyright (C) 1994, 1995, 1997, 1998, 1999, 2000, 2001, 2004, 2005
+;; 2007, 2008, 2010 Free Software Foundation, Inc.
 ;; Contributed by Michael K. Gschwind (mike@vlsivie.tuwien.ac.at).
 
-;; This file is part of GNU CC.
+;; This file is part of GCC.
 
-;; GNU CC is free software; you can redistribute it and/or modify
+;; 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 1, or (at your option)
+;; the Free Software Foundation; either version 3, or (at your option)
 ;; any later version.
 
-;; GNU CC is distributed in the hope that it will be useful,
+;; 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 GNU CC; see the file COPYING.  If not, write to
-;; the Free Software Foundation, 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
+;; along with GCC; see the file COPYING3.  If not see
+;; <http://www.gnu.org/licenses/>.
+
+(include "predicates.md")
+(include "constraints.md")
+
+(define_constants
+  [
+   ;; Register numbers
+   (R0_REGNUM            0)
+   (RETVAL_REGNUM        0)
+   (HARD_FRAME_POINTER_REGNUM  5)
+   (STACK_POINTER_REGNUM  6)
+   (PC_REGNUM             7)
+   (AC0_REGNUM            8)
+   (AC3_REGNUM            11)
+   (AC4_REGNUM            12)
+   (AC5_REGNUM            13)
+   ;; The next two are not physical registers but are used for addressing
+   ;; arguments.
+   (FRAME_POINTER_REGNUM  14)
+   (ARG_POINTER_REGNUM    15)
+   (FIRST_PSEUDO_REGISTER 16)
+   ;; Branch offset limits, as byte offsets from instruction address
+   (MIN_BRANCH            -254)
+   (MAX_BRANCH            256)
+   (MIN_SOB               -126)
+   (MAX_SOB               0)])
 
 ;; HI is 16 bit
 ;; QI is 8 bit 
 
+;; Integer modes supported on the PDP11, with a mapping from machine mode
+;; to mnemonic suffix.  SImode and DImode always are special cases.
+(define_mode_iterator PDPint [QI HI])
+(define_mode_attr  isfx [(QI "b") (HI "")])
+
 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
 
 ;;- cpp macro #define NOTICE_UPDATE_CC in file tm.h handles condition code
 ;; default is arith
 (define_attr "type" "unknown,arith,fp" (const_string "arith"))
 
-;; length default is 1 word each
-(define_attr "length" "" (const_int 1))
+;; length default is 2 bytes each
+(define_attr "length" "" (const_int 2))
 
 ;; a user's asm statement
 (define_asm_attributes
   [(set_attr "type" "unknown")
-; all bets are off how long it is - make it 256, forces long jumps 
-; whenever jumping around it !!!
-   (set_attr "length" "256")])
+; length for asm is the max length per statement.  That would be
+; 5 words, for a floating point instruction with a literal constant
+; argument.
+   (set_attr "length" "10")])
 
 ;; define function units
 
 ;(define_function_unit "fpu" 1 1 (eq_attr "type" "fp") 0 0)
 
 ;; compare
-(define_insn "cmpdf"
+(define_insn "*cmpdf"
   [(set (cc0)
-       (compare (match_operand:DF 0 "general_operand" "fR,Q,F")
-                (match_operand:DF 1 "register_operand" "a,a,a")))]
+       (compare (match_operand:DF 0 "general_operand" "fR,fR,Q,Q,F")
+                (match_operand:DF 1 "register_or_const0_operand" "G,a,G,a,a")))]
   "TARGET_FPU"
   "*
 {
   cc_status.flags = CC_IN_FPU;
-  return \"{cmpd|cmpf} %0, %1\;cfcc\";
-}"
-  [(set_attr "length" "2,3,6")])
-
-;; a bit of brain damage, maybe inline later - 
-;; problem is - gcc seems to NEED SImode because 
-;; of the cmp weirdness - maybe change gcc to handle this?
-
-(define_expand "cmpsi"
-  [(set (reg:SI 0)
-       (match_operand:SI 0 "general_operand" "g"))
-   (set (reg:SI 2)
-       (match_operand:SI 1 "general_operand" "g"))
-   (parallel [(set (cc0)
-                  (compare (reg:SI 0)
-                           (reg:SI 2)))
-             (clobber (reg:SI 0))])]
-  "0" ;; disable for test
-  "")
-
-;; check for next insn for branch code - does this still
-;; work in gcc 2.* ?
-
-(define_insn ""
-  [(set (cc0)
-       (compare (reg:SI 0)
-                (reg:SI 2)))
-   (clobber (reg:SI 0))]
-  ""
-  "*
-{
-  rtx br_insn = NEXT_INSN (insn);
-  RTX_CODE br_code;
-
-  if (GET_CODE (br_insn) != JUMP_INSN)
-    abort();
-  br_code =  GET_CODE (XEXP (XEXP (PATTERN (br_insn), 1), 0));
-  
-  switch(br_code)
-  {
-    case GEU:
-    case LTU:
-    case GTU:
-    case LEU:
-      
-      return \"jsr pc, ___ucmpsi\;cmp $1,r0\";
-
-    case GE:
-    case LT:
-    case GT:
-    case LE:
-    case EQ:
-    case NE:
-
-      return \"jsr pc, ___cmpsi\;tst r0\";
-
-    default:
-
-      abort();
-  }
-}"
-  [(set_attr "length" "4")])
-
-
-(define_insn "cmphi"
-  [(set (cc0)
-       (compare (match_operand:HI 0 "general_operand" "rR,rR,Qi,Qi")
-                (match_operand:HI 1 "general_operand" "rR,Qi,rR,Qi")))]
-  ""
-  "cmp %0,%1"
-  [(set_attr "length" "1,2,2,3")])
-
-(define_insn "cmpqi"
-  [(set (cc0)
-       (compare (match_operand:QI 0 "general_operand" "rR,rR,Qi,Qi")
-                (match_operand:QI 1 "general_operand" "rR,Qi,rR,Qi")))]
-  ""
-  "cmpb %0,%1"
-  [(set_attr "length" "1,2,2,3")])
-                          
-
-;; We have to have this because cse can optimize the previous pattern
-;; into this one.
-
-(define_insn "tstdf"
-  [(set (cc0)
-       (match_operand:DF 0 "general_operand" "fR,Q"))]
-  "TARGET_FPU"
-  "*
-{
-  cc_status.flags = CC_IN_FPU;
-  return \"{tstd|tstf} %0\;cfcc\";
+  if (which_alternative == 0 || which_alternative == 2)
+    return \"{tstd|tstf} %0\;cfcc\";
+  else
+    return \"{cmpd|cmpf} %0, %1\;cfcc\";
 }"
-  [(set_attr "length" "2,3")])
-
-
-(define_expand "tstsi"
-  [(set (reg:SI 0)
-       (match_operand:SI 0 "general_operand" "g"))
-   (parallel [(set (cc0)
-                  (reg:SI 0))
-             (clobber (reg:SI 0))])]
-  "0" ;; disable for test
-  "")
-
-(define_insn ""
-  [(set (cc0)
-       (reg:SI 0))
-   (clobber (reg:SI 0))]
-  ""
-  "jsr pc, ___tstsi\;tst r0"
-  [(set_attr "length" "3")])
-
-
-(define_insn "tsthi"
-  [(set (cc0)
-       (match_operand:HI 0 "general_operand" "rR,Q"))]
-  ""
-  "tst %0"
-  [(set_attr "length" "1,2")])
+  [(set_attr "length" "4,4,6,6,12")]) 
 
-(define_insn "tstqi"
+(define_insn "*cmp<mode>"
   [(set (cc0)
-       (match_operand:QI 0 "general_operand" "rR,Q"))]
+       (compare (match_operand:PDPint 0 "general_operand" "rR,rR,rR,Q,Qi,Qi")
+                (match_operand:PDPint 1 "general_operand" "N,rR,Qi,N,rR,Qi")))]
   ""
-  "tstb %0"
-  [(set_attr "length" "1,2")])
+  "@
+   tst<PDPint:isfx> %0
+   cmp<PDPint:isfx> %0,%1
+   cmp<PDPint:isfx> %0,%1
+   tst<PDPint:isfx> %0
+   cmp<PDPint:isfx> %0,%1
+   cmp<PDPint:isfx> %0,%1"
+  [(set_attr "length" "2,2,4,4,4,6")])
 
 ;; sob instruction - we need an assembler which can make this instruction
 ;; valid under _all_ circumstances!
 (define_insn ""
   [(set (pc)
        (if_then_else
-        (ne (plus:HI (match_operand:HI 0 "register_operand" "r")
+        (ne (plus:HI (match_operand:HI 0 "register_operand" "+r")
                      (const_int -1))
             (const_int 0))
         (label_ref (match_operand 1 "" ""))
  static int labelcount = 0;
  static char buf[1000];
 
- if (get_attr_length (insn) == 1)
+ if (get_attr_length (insn) == 2)
     return \"sob %0, %l1\";
 
  /* emulate sob */
 
  return \"\";
 }"
-  [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
+  [(set (attr "length") (if_then_else (ior (lt (minus (match_dup 0)
                                                       (pc))
-                                               (const_int -256))
-                                          (ge (minus (match_dup 0)
+                                               (const_int MIN_SOB))
+                                          (gt (minus (match_dup 0)
                                                       (pc))
-                                               (const_int 0)))
-                                     (const_int 4)
-                                     (const_int 1)))])
+                                               (const_int MAX_SOB)))
+                                     (const_int 8)
+                                     (const_int 2)))])
 
 ;; These control RTL generation for conditional jump insns
 ;; and match them for register allocation.
 
-;; problem with too short jump distance! we need an assembler which can 
-;; make this valid for all jump distances!
-;; e.g. gas!
-
-;; these must be changed to check for CC_IN_FCCR if float is to be 
-;; enabled
-
-(define_insn "beq"
-  [(set (pc)
-       (if_then_else (eq (cc0)
-                         (const_int 0))
-                     (label_ref (match_operand 0 "" ""))
-                     (pc)))]
-  ""
-  "* return output_jump(\"beq\", \"bne\", get_attr_length(insn));"
-  [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
-                                                     (pc))
-                                              (const_int -128))
-                                          (ge (minus (match_dup 0)
-                                                     (pc))
-                                              (const_int 128)))
-                                     (const_int 3)
-                                     (const_int 1)))])
-
-
-(define_insn "bne"
-  [(set (pc)
-       (if_then_else (ne (cc0)
-                         (const_int 0))
-                     (label_ref (match_operand 0 "" ""))
-                     (pc)))]
-  ""
-  "* return output_jump(\"bne\", \"beq\", get_attr_length(insn));"
-  [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
-                                                     (pc))
-                                              (const_int -128))
-                                          (ge (minus (match_dup 0)
-                                                     (pc))
-                                              (const_int 128)))
-                                     (const_int 3)
-                                     (const_int 1)))])
-
-(define_insn "bgt"
-  [(set (pc)
-       (if_then_else (gt (cc0)
-                         (const_int 0))
-                     (label_ref (match_operand 0 "" ""))
-                     (pc)))]
-  ""
-  "* return output_jump(\"bgt\", \"ble\", get_attr_length(insn));"
-  [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
-                                                     (pc))
-                                              (const_int -128))
-                                          (ge (minus (match_dup 0)
-                                                     (pc))
-                                              (const_int 128)))
-                                     (const_int 3)
-                                     (const_int 1)))])
-
-(define_insn "bgtu"
-  [(set (pc)
-       (if_then_else (gtu (cc0)
-                          (const_int 0))
-                     (label_ref (match_operand 0 "" ""))
-                     (pc)))]
-  ""
-  "* return output_jump(\"bhi\", \"blos\", get_attr_length(insn));"
-  [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
-                                                     (pc))
-                                              (const_int -128))
-                                          (ge (minus (match_dup 0)
-                                                     (pc))
-                                              (const_int 128)))
-                                     (const_int 3)
-                                     (const_int 1)))])
-
-(define_insn "blt"
-  [(set (pc)
-       (if_then_else (lt (cc0)
-                         (const_int 0))
-                     (label_ref (match_operand 0 "" ""))
+(define_expand "cbranchdf4"
+  [(set (cc0)
+        (compare (match_operand:DF 1 "general_operand")
+                (match_operand:DF 2 "register_or_const0_operand")))
+   (set (pc)
+       (if_then_else (match_operator 0 "ordered_comparison_operator"
+                      [(cc0) (const_int 0)])
+                     (label_ref (match_operand 3 "" ""))
                      (pc)))]
-  ""
-  "* return output_jump(\"blt\", \"bge\", get_attr_length(insn));"
-  [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
-                                                     (pc))
-                                              (const_int -128))
-                                          (ge (minus (match_dup 0)
-                                                     (pc))
-                                              (const_int 128)))
-                                     (const_int 3)
-                                     (const_int 1)))])
-
+  "TARGET_FPU"
+  "")
 
-(define_insn "bltu"
-  [(set (pc)
-       (if_then_else (ltu (cc0)
-                          (const_int 0))
-                     (label_ref (match_operand 0 "" ""))
+(define_expand "cbranch<mode>4"
+  [(set (cc0)
+        (compare (match_operand:PDPint 1 "general_operand")
+                (match_operand:PDPint 2 "general_operand")))
+   (set (pc)
+       (if_then_else (match_operator 0 "ordered_comparison_operator"
+                      [(cc0) (const_int 0)])
+                     (label_ref (match_operand 3 "" ""))
                      (pc)))]
   ""
-  "* return output_jump(\"blo\", \"bhis\", get_attr_length(insn));"
-  [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
-                                                     (pc))
-                                              (const_int -128))
-                                          (ge (minus (match_dup 0)
-                                                     (pc))
-                                              (const_int 128)))
-                                     (const_int 3)
-                                     (const_int 1)))])
+  "")
 
-(define_insn "bge"
-  [(set (pc)
-       (if_then_else (ge (cc0)
-                         (const_int 0))
-                     (label_ref (match_operand 0 "" ""))
-                     (pc)))]
-  ""
-  "* return output_jump(\"bge\", \"blt\", get_attr_length(insn));"
-  [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
-                                                     (pc))
-                                              (const_int -128))
-                                          (ge (minus (match_dup 0)
-                                                     (pc))
-                                              (const_int 128)))
-                                     (const_int 3)
-                                     (const_int 1)))])
+;; problem with too short jump distance! we need an assembler which can 
+;; make this valid for all jump distances!
+;; e.g. gas!
 
-(define_insn "bgeu"
-  [(set (pc)
-       (if_then_else (geu (cc0)
-                          (const_int 0))
-                     (label_ref (match_operand 0 "" ""))
-                     (pc)))]
-  ""
-  "* return output_jump(\"bhis\", \"blo\", get_attr_length(insn));"
-  [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
-                                                     (pc))
-                                              (const_int -128))
-                                          (ge (minus (match_dup 0)
-                                                     (pc))
-                                              (const_int 128)))
-                                     (const_int 3)
-                                     (const_int 1)))])
+;; these must be changed to check for CC_IN_FCCR if float is to be 
+;; enabled
 
-(define_insn "ble"
+(define_insn "*branch"
   [(set (pc)
-       (if_then_else (le (cc0)
-                         (const_int 0))
-                     (label_ref (match_operand 0 "" ""))
+       (if_then_else (match_operator 0 "ordered_comparison_operator"
+                      [(cc0) (const_int 0)])
+                     (label_ref (match_operand 1 "" ""))
                      (pc)))]
   ""
-  "* return output_jump(\"ble\", \"bgt\", get_attr_length(insn));"
-  [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
+  "* return output_jump(GET_CODE (operands[0]), 0, get_attr_length(insn));"
+  [(set (attr "length") (if_then_else (ior (lt (minus (match_dup 1)
                                                      (pc))
-                                              (const_int -128))
-                                          (ge (minus (match_dup 0)
+                                              (const_int MIN_BRANCH))
+                                          (gt (minus (match_dup 1)
                                                      (pc))
-                                              (const_int 128)))
-                                     (const_int 3)
-                                     (const_int 1)))])
+                                              (const_int MAX_BRANCH)))
+                                     (const_int 6)
+                                     (const_int 2)))])
 
-(define_insn "bleu"
-  [(set (pc)
-       (if_then_else (leu (cc0)
-                          (const_int 0))
-                     (label_ref (match_operand 0 "" ""))
-                     (pc)))]
-  ""
-  "* return output_jump(\"blos\", \"bhi\", get_attr_length(insn));"
-  [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
-                                                     (pc))
-                                              (const_int -128))
-                                          (ge (minus (match_dup 0)
-                                                     (pc))
-                                              (const_int 128)))
-                                     (const_int 3)
-                                     (const_int 1)))])
 
-\f
 ;; These match inverted jump insns for register allocation.
 
-(define_insn ""
-  [(set (pc)
-       (if_then_else (eq (cc0)
-                         (const_int 0))
-                     (pc)
-                     (label_ref (match_operand 0 "" ""))))]
-  ""
-  "* return output_jump(\"bne\", \"beq\", get_attr_length(insn));"
-  [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
-                                                     (pc))
-                                              (const_int -128))
-                                          (ge (minus (match_dup 0)
-                                                     (pc))
-                                              (const_int 128)))
-                                     (const_int 3)
-                                     (const_int 1)))])
-
-(define_insn ""
-  [(set (pc)
-       (if_then_else (ne (cc0)
-                         (const_int 0))
-                     (pc)
-                     (label_ref (match_operand 0 "" ""))))]
-  ""
-  "* return output_jump(\"beq\", \"bne\", get_attr_length(insn));"
-  [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
-                                                     (pc))
-                                              (const_int -128))
-                                          (ge (minus (match_dup 0)
-                                                     (pc))
-                                              (const_int 128)))
-                                     (const_int 3)
-                                     (const_int 1)))])
-
-(define_insn ""
-  [(set (pc)
-       (if_then_else (gt (cc0)
-                         (const_int 0))
-                     (pc)
-                     (label_ref (match_operand 0 "" ""))))]
-  ""
-  "* return output_jump(\"ble\", \"bgt\", get_attr_length(insn));"
-  [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
-                                                     (pc))
-                                              (const_int -128))
-                                          (ge (minus (match_dup 0)
-                                                     (pc))
-                                              (const_int 128)))
-                                     (const_int 3)
-                                     (const_int 1)))])
-
-(define_insn ""
-  [(set (pc)
-       (if_then_else (gtu (cc0)
-                          (const_int 0))
-                     (pc)
-                     (label_ref (match_operand 0 "" ""))))]
-  ""
-  "* return output_jump(\"blos\", \"bhi\", get_attr_length(insn));"
-  [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
-                                                     (pc))
-                                              (const_int -128))
-                                          (ge (minus (match_dup 0)
-                                                     (pc))
-                                              (const_int 128)))
-                                     (const_int 3)
-                                     (const_int 1)))])
-
-(define_insn ""
-  [(set (pc)
-       (if_then_else (lt (cc0)
-                         (const_int 0))
-                     (pc)
-                     (label_ref (match_operand 0 "" ""))))]
-  ""
-  "* return output_jump(\"bge\", \"blt\", get_attr_length(insn));"
-  [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
-                                                     (pc))
-                                              (const_int -128))
-                                          (ge (minus (match_dup 0)
-                                                     (pc))
-                                              (const_int 128)))
-                                     (const_int 3)
-                                     (const_int 1)))])
-
-(define_insn ""
+(define_insn "*branch_inverted"
   [(set (pc)
-       (if_then_else (ltu (cc0)
-                          (const_int 0))
+       (if_then_else (match_operator 0 "ordered_comparison_operator"
+                      [(cc0) (const_int 0)])
                      (pc)
-                     (label_ref (match_operand 0 "" ""))))]
+                     (label_ref (match_operand 1 "" ""))))]
   ""
-  "* return output_jump(\"bhis\", \"blo\", get_attr_length(insn));"
-  [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
-                                                     (pc))
-                                              (const_int -128))
-                                          (ge (minus (match_dup 0)
-                                                     (pc))
-                                              (const_int 128)))
-                                     (const_int 3)
-                                     (const_int 1)))])
-
-(define_insn ""
-  [(set (pc)
-       (if_then_else (ge (cc0)
-                         (const_int 0))
-                     (pc)
-                     (label_ref (match_operand 0 "" ""))))]
-  ""  
-  "* return output_jump(\"blt\", \"bge\", get_attr_length(insn));"
-  [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
-                                                     (pc))
-                                              (const_int -128))
-                                          (ge (minus (match_dup 0)
+  "* return output_jump(GET_CODE (operands[0]), 1, get_attr_length(insn));"
+  [(set (attr "length") (if_then_else (ior (lt (minus (match_dup 1)
                                                      (pc))
-                                              (const_int 128)))
-                                     (const_int 3)
-                                     (const_int 1)))])
-
-(define_insn ""
-  [(set (pc)
-       (if_then_else (geu (cc0)
-                          (const_int 0))
-                     (pc)
-                     (label_ref (match_operand 0 "" ""))))]
-  ""
-  "* return output_jump(\"blo\", \"bhis\", get_attr_length(insn));"
-  [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
-                                                     (pc))
-                                              (const_int -128))
-                                          (ge (minus (match_dup 0)
-                                                     (pc))
-                                              (const_int 128)))
-                                     (const_int 3)
-                                     (const_int 1)))])
-
-(define_insn ""
-  [(set (pc)
-       (if_then_else (le (cc0)
-                         (const_int 0))
-                     (pc)
-                     (label_ref (match_operand 0 "" ""))))]
-  ""
-  "* return output_jump(\"bgt\", \"ble\", get_attr_length(insn));"
-  [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
+                                              (const_int MIN_BRANCH))
+                                          (gt (minus (match_dup 1)
                                                      (pc))
-                                              (const_int -128))
-                                          (ge (minus (match_dup 0)
-                                                     (pc))
-                                              (const_int 128)))
-                                     (const_int 3)
-                                     (const_int 1)))])
-
-(define_insn ""
-  [(set (pc)
-       (if_then_else (leu (cc0)
-                          (const_int 0))
-                     (pc)
-                     (label_ref (match_operand 0 "" ""))))]
-  ""
-  "* return output_jump(\"bhi\", \"blos\", get_attr_length(insn));"
-  [(set (attr "length") (if_then_else (ior (le (minus (match_dup 0)
-                                                     (pc))
-                                              (const_int -128))
-                                          (ge (minus (match_dup 0)
-                                                     (pc))
-                                              (const_int 128)))
-                                     (const_int 3)
-                                     (const_int 1)))])
+                                              (const_int MAX_BRANCH)))
+                                     (const_int 6)
+                                     (const_int 2)))])
 \f
 ;; Move instructions
 
 (define_insn "movdi"
-  [(set (match_operand:DI 0 "general_operand" "=g")
-       (match_operand:DI 1 "general_operand" "g"))]
+  [(set (match_operand:DI 0 "nonimmediate_operand" "=g,rm,o")
+       (match_operand:DI 1 "general_operand" "m,r,a"))]
   ""
   "* return output_move_quad (operands);"
 ;; what's the mose expensive code - say twice movsi = 16
-  [(set_attr "length" "16")])
+  [(set_attr "length" "32,32,32")])
 
 (define_insn "movsi"
-  [(set (match_operand:SI 0 "general_operand" "=r,r,r,rm,m")
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,rm,m")
        (match_operand:SI 1 "general_operand" "rN,IJ,K,m,r"))]
   ""
   "* return output_move_double (operands);"
 ;; what's the most expensive code ? - I think 8!
 ;; we could split it up and make several sub-cases...
-  [(set_attr "length" "2,3,4,8,8")])
-
-(define_insn "movhi"
-  [(set (match_operand:HI 0 "general_operand" "=rR,rR,Q,Q")
-       (match_operand:HI 1 "general_operand" "rRN,Qi,rRN,Qi"))]
-  ""
-  "*
-{
-  if (operands[1] == const0_rtx)
-    return \"clr %0\";
-
-  return \"mov %1, %0\";
-}"
-  [(set_attr "length" "1,2,2,3")])
+  [(set_attr "length" "4,6,8,16,16")])
 
-(define_insn "movqi"
-  [(set (match_operand:QI 0 "general_operand" "=rR,rR,Q,Q")
-       (match_operand:QI 1 "general_operand" "rRN,Qi,rRN,Qi"))]
+(define_insn "mov<mode>"
+  [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,rR,Q,Q")
+       (match_operand:PDPint 1 "general_operand" "rRN,Qi,rRN,Qi"))]
   ""
   "*
 {
   if (operands[1] == const0_rtx)
-    return \"clrb %0\";
+    return \"clr<PDPint:isfx> %0\";
 
-  return \"movb %1, %0\";
+  return \"mov<PDPint:isfx> %1, %0\";
 }"
-  [(set_attr "length" "1,2,2,3")])
+  [(set_attr "length" "2,4,4,6")])
 
-;; do we have to supply all these moves? e.g. to 
-;; NO_LOAD_FPU_REGs ? 
 (define_insn "movdf"
-  [(set (match_operand:DF 0 "general_operand" "=f,R,f,Q,f,m")
-        (match_operand:DF 1 "general_operand" "fR,f,Q,f,F,m"))]
-  ""
-  "* return output_move_quad (operands);"
+  [(set (match_operand:DF 0 "float_nonimm_operand" "=a,fR,a,Q,g")
+        (match_operand:DF 1 "float_operand" "fFR,a,Q,a,g"))]
+  "TARGET_FPU"
+  "* if (which_alternative ==0 || which_alternative == 2)
+       return \"ldd %1, %0\";
+     else if (which_alternative == 1 || which_alternative == 3)
+       return \"std %1, %0\";
+     else 
+       return output_move_quad (operands); "
 ;; just a guess..
-  [(set_attr "length" "1,1,2,2,5,16")])
+  [(set_attr "length" "2,2,10,10,32")])
 
 (define_insn "movsf"
-  [(set (match_operand:SF 0 "general_operand" "=g,r,g")
-        (match_operand:SF 1 "general_operand" "r,rmF,g"))]
+  [(set (match_operand:SF 0 "float_nonimm_operand" "=a,fR,a,Q,g")
+        (match_operand:SF 1 "float_operand" "fFR,a,Q,a,g"))]
   "TARGET_FPU"
-  "* return output_move_double (operands);"
-  [(set_attr "length" "8,8,8")])
+  "* if (which_alternative ==0 || which_alternative == 2)
+       return \"{ldcfd|movof} %1, %0\";
+     else if (which_alternative == 1 || which_alternative == 3)
+       return \"{stcdf|movfo} %1, %0\";
+     else 
+       return output_move_double (operands); "
+;; just a guess..
+  [(set_attr "length" "2,2,10,10,16")])
 
 ;; maybe fiddle a bit with move_ratio, then 
 ;; let constraints only accept a register ...
 
-(define_expand "movstrhi"
+(define_expand "movmemhi"
   [(parallel [(set (match_operand:BLK 0 "general_operand" "=g,g")
                   (match_operand:BLK 1 "general_operand" "g,g"))
-             (use (match_operand:HI 2 "arith_operand" "n,&mr"))
+             (use (match_operand:HI 2 "general_operand" "n,&mr"))
              (use (match_operand:HI 3 "immediate_operand" "i,i"))
              (clobber (match_scratch:HI 4 "=&r,X"))
              (clobber (match_dup 5))
   "
 {
   operands[0]
-    = change_address (operands[0], VOIDmode,
-                     copy_to_mode_reg (Pmode, XEXP (operands[0], 0)));
+    = replace_equiv_address (operands[0],
+                            copy_to_mode_reg (Pmode, XEXP (operands[0], 0)));
   operands[1]
-    = change_address (operands[1], VOIDmode,
-                     copy_to_mode_reg (Pmode, XEXP (operands[1], 0)));
+    = replace_equiv_address (operands[1],
+                            copy_to_mode_reg (Pmode, XEXP (operands[1], 0)));
 
   operands[5] = XEXP (operands[0], 0);
   operands[6] = XEXP (operands[1], 0);
 }")
 
 
-(define_insn "" ; "movstrhi"
-  [(set (mem:BLK (match_operand:HI 0 "general_operand" "=r,r"))
-       (mem:BLK (match_operand:HI 1 "general_operand" "r,r")))
-   (use (match_operand:HI 2 "arith_operand" "n,&r"))
+(define_insn "" ; "movmemhi"
+  [(set (mem:BLK (match_operand 0 "pmode_register_operand" "+r,r"))
+       (mem:BLK (match_operand 1 "pmode_register_operand" "+r,r")))
+   (use (match_operand:HI 2 "general_operand" "+n,&r"))
    (use (match_operand:HI 3 "immediate_operand" "i,i"))
    (clobber (match_scratch:HI 4 "=&r,X"))
    (clobber (match_dup 0))
   "(TARGET_BCOPY_BUILTIN)"
   "* return output_block_move (operands);"
 ;;; just a guess
-  [(set_attr "length" "40")])
+  [(set_attr "length" "80")])
    
 
 \f
 ;;- truncation instructions
 
 (define_insn  "truncdfsf2"
-  [(set (match_operand:SF 0 "general_operand" "=r,R,Q")
-       (float_truncate:SF (match_operand:DF 1 "register_operand" "a,a,a")))]
+  [(set (match_operand:SF 0 "float_nonimm_operand" "=f,R,Q")
+       (float_truncate:SF (match_operand:DF 1 "register_operand" "f,a,a")))]
   "TARGET_FPU"
   "* if (which_alternative ==0)
      {
-       output_asm_insn(\"{stcdf|movfo} %1, -(sp)\", operands);
-       output_asm_insn(\"mov (sp)+, %0\", operands);
-       operands[0] = gen_rtx(REG, HImode, REGNO (operands[0])+1);
-       output_asm_insn(\"mov (sp)+, %0\", operands);
        return \"\";
      }
      else if (which_alternative == 1)
      else 
        return \"{stcdf|movfo} %1, %0\";
   "
-  [(set_attr "length" "3,1,2")])
+  [(set_attr "length" "0,2,4")])
 
 
 (define_expand "truncsihi2"
-  [(set (match_operand:HI 0 "general_operand" "=g")
+  [(set (match_operand:HI 0 "nonimmediate_operand" "=g")
        (subreg:HI 
          (match_operand:SI 1 "general_operand" "or")
           0))]
 ;;- zero extension instructions
 
 (define_insn "zero_extendqihi2"
-  [(set (match_operand:HI 0 "general_operand" "=r")
-       (zero_extend:HI (match_operand:QI 1 "general_operand" "0")))]
+  [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
+       (zero_extend:HI (match_operand:QI 1 "general_operand" "0,0")))]
   ""
-  "bic $(256*255), %0"
-  [(set_attr "length" "2")])
+  "bic $0177400, %0"
+  [(set_attr "length" "4,6")])
                         
 (define_expand "zero_extendhisi2"
   [(set (subreg:HI 
           (match_dup 0)
-          1)
+          2)
         (match_operand:HI 1 "register_operand" "r"))
    (set (subreg:HI 
           (match_operand:SI 0 "register_operand" "=r")
 ;;- sign extension instructions
 
 (define_insn "extendsfdf2"
-  [(set (match_operand:DF 0 "register_operand" "=a,a,a")
-       (float_extend:DF (match_operand:SF 1 "general_operand" "r,R,Q")))]
+  [(set (match_operand:DF 0 "register_operand" "=f,a,a")
+       (float_extend:DF (match_operand:SF 1 "float_operand" "f,R,Q")))]
   "TARGET_FPU"
   "@
-   mov %1, -(sp)\;{ldcfd|movof} (sp)+,%0
+   /* nothing */
    {ldcfd|movof} %1, %0
    {ldcfd|movof} %1, %0"
-  [(set_attr "length" "2,1,2")])
+  [(set_attr "length" "0,2,4")])
 
 ;; does movb sign extend in register-to-register move?
 (define_insn "extendqihi2"
        (sign_extend:HI (match_operand:QI 1 "general_operand" "rR,Q")))]
   ""
   "movb %1, %0"
-  [(set_attr "length" "1,2")])
+  [(set_attr "length" "2,4")])
 
 (define_insn "extendqisi2"
   [(set (match_operand:SI 0 "register_operand" "=r,r")
 
   /* make register pair available */
   latehalf[0] = operands[0];
-  operands[0] = gen_rtx(REG, HImode, REGNO (operands[0])+1);
-    
+  operands[0] = gen_rtx_REG (HImode, REGNO (operands[0])+ 1);
+
   output_asm_insn(\"movb %1, %0\", operands);
   output_asm_insn(\"sxt %0\", latehalf);
     
   return \"\";
 }"
-  [(set_attr "length" "2,3")])
+  [(set_attr "length" "4,6")])
 
 ;; maybe we have to use define_expand to say that we have the instruction,
 ;; unconditionally, and then match dependent on CPU type:
 
 (define_expand "extendhisi2"
-  [(set (match_operand:SI 0 "general_operand" "=g")
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
        (sign_extend:SI (match_operand:HI 1 "general_operand" "g")))]
   ""
   "")
   
 (define_insn "" ; "extendhisi2"
-  [(set (match_operand:SI 0 "general_operand" "=o,<,r")
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=o,<,r")
        (sign_extend:SI (match_operand:HI 1 "general_operand" "g,g,g")))]
   "TARGET_40_PLUS"
   "*
 
   /* we don't want to mess with auto increment */
   
-  switch(which_alternative)
+  switch (which_alternative)
   {
     case 0:
 
       latehalf[0] = operands[0];
-      operands[0] = adj_offsettable_operand(operands[0], 2);
+      operands[0] = adjust_address(operands[0], HImode, 2);
   
       output_asm_insn(\"mov %1, %0\", operands);
       output_asm_insn(\"sxt %0\", latehalf);
 
       /* make register pair available */
       latehalf[0] = operands[0];
-      operands[0] = gen_rtx(REG, HImode, REGNO (operands[0])+1);
+      operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
 
       output_asm_insn(\"mov %1, %0\", operands);
       output_asm_insn(\"sxt %0\", latehalf);
 
     default:
 
-      abort();
+      gcc_unreachable ();
   }
 }"
-  [(set_attr "length" "5,3,3")])
+  [(set_attr "length" "10,6,6")])
 
 
 (define_insn ""
   rtx lateoperands[2];
 
   lateoperands[0] = operands[0];
-  operands[0] = gen_rtx(REG, HImode, REGNO (operands[0])+1);
+  operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
 
   output_asm_insn(\"tst %0\", operands);
   sprintf(buf, \"bge extendhisi%d\", count);
 
   return \"\";
 }"
-  [(set_attr "length" "6")])
+  [(set_attr "length" "12")])
 
 ;; make float to int and vice versa 
 ;; using the cc_status.flag field we could probably cut down
        rtx latehalf[2];
 
        latehalf[0] = NULL; 
-       latehalf[1] = gen_rtx(REG, HImode, REGNO (operands[0])+1);
+       latehalf[1] = gen_rtx_REG (HImode, REGNO (operands[1]) + 1);
        output_asm_insn(\"mov %1, -(sp)\", latehalf);
        output_asm_insn(\"mov %1, -(sp)\", operands);
        
      else 
        return \"setl\;{ldcld|movif} %1, %0\;seti\";
   "
-  [(set_attr "length" "5,3,4")])
+  [(set_attr "length" "10,6,8")])
 
 (define_insn "floathidf2"
   [(set (match_operand:DF 0 "register_operand" "=a,a")
        (float:DF (match_operand:HI 1 "general_operand" "rR,Qi")))]
   "TARGET_FPU"
   "{ldcid|movif} %1, %0"
-  [(set_attr "length" "1,2")])
+  [(set_attr "length" "2,4")])
        
 ;; cut float to int
 (define_insn "fix_truncdfsi2"
-  [(set (match_operand:SI 0 "general_operand" "=r,R,Q")
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=r,R,Q")
        (fix:SI (fix:DF (match_operand:DF 1 "register_operand" "a,a,a"))))]
   "TARGET_FPU"
   "* if (which_alternative ==0)
        output_asm_insn(\"{stcdl|movfi} %1, -(sp)\", operands);
        output_asm_insn(\"seti\", operands);
        output_asm_insn(\"mov (sp)+, %0\", operands);
-       operands[0] = gen_rtx(REG, HImode, REGNO (operands[0])+1);
+       operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
        output_asm_insn(\"mov (sp)+, %0\", operands);
        return \"\";
      }
      else 
        return \"setl\;{stcdl|movfi} %1, %0\;seti\";
   "
-  [(set_attr "length" "5,3,4")])
+  [(set_attr "length" "10,6,8")])
 
 (define_insn "fix_truncdfhi2"
-  [(set (match_operand:HI 0 "general_operand" "=rR,Q")
+  [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
        (fix:HI (fix:DF (match_operand:DF 1 "register_operand" "a,a"))))]
   "TARGET_FPU"
   "{stcdi|movfi} %1, %0"
-  [(set_attr "length" "1,2")])
+  [(set_attr "length" "2,4")])
 
 \f
 ;;- arithmetic instructions
                 (match_operand:DF 2 "general_operand" "fR,Q,F")))]
   "TARGET_FPU"
   "{addd|addf} %2, %0"
-  [(set_attr "length" "1,2,5")])
+  [(set_attr "length" "2,4,10")])
 
 (define_insn "addsi3"
-  [(set (match_operand:SI 0 "general_operand" "=r,r,o,o,r,r,r,o,o,o")
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,o,o,r,r,r,o,o,o")
        (plus:SI (match_operand:SI 1 "general_operand" "%0,0,0,0,0,0,0,0,0,0")
                 (match_operand:SI 2 "general_operand" "r,o,r,o,I,J,K,I,J,K")))]
   ""
 
      or is lateoperands the low word?? - looks like it! */
 
-  unsigned int i;
   rtx lateoperands[3];
   
   lateoperands[0] = operands[0];
 
   if (REG_P (operands[0]))
-    operands[0] = gen_rtx(REG, HImode, REGNO(operands[0]) + 1);
+    operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
   else
-    operands[0] = adj_offsettable_operand (operands[0], 2);
+    operands[0] = adjust_address (operands[0], HImode, 2);
   
   if (! CONSTANT_P(operands[2]))
   {
     lateoperands[2] = operands[2];
 
     if (REG_P (operands[2]))
-      operands[2] = gen_rtx(REG, HImode, REGNO(operands[2]) + 1);
+      operands[2] = gen_rtx_REG (HImode, REGNO (operands[2]) + 1);
     else
-      operands[2] = adj_offsettable_operand(operands[2], 2);
+      operands[2] = adjust_address (operands[2], HImode, 2);
 
     output_asm_insn (\"add %2, %0\", operands);
     output_asm_insn (\"adc %0\", lateoperands);
     return \"\";
   }
 
-  lateoperands[2] = GEN_INT ((INTVAL(operands[2]) >> 16) & 0xffff);
-  operands[2] = GEN_INT (INTVAL(operands[2]) & 0xffff);
+  lateoperands[2] = GEN_INT ((INTVAL (operands[2]) >> 16) & 0xffff);
+  operands[2] = GEN_INT (INTVAL (operands[2]) & 0xffff);
   
   if (INTVAL(operands[2]))
   { 
 
   return \"\";
 }"
-  [(set_attr "length" "3,5,6,8,3,1,5,5,3,8")])
+  [(set_attr "length" "6,10,12,16,6,2,10,10,6,16")])
 
 (define_insn "addhi3"
-  [(set (match_operand:HI 0 "general_operand" "=rR,rR,Q,Q")
+  [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,rR,Q,Q")
        (plus:HI (match_operand:HI 1 "general_operand" "%0,0,0,0")
                 (match_operand:HI 2 "general_operand" "rRLM,Qi,rRLM,Qi")))]
   ""
 
   return \"add %2, %0\";
 }"
-  [(set_attr "length" "1,2,2,3")])
-
-(define_insn "addqi3"
-  [(set (match_operand:QI 0 "general_operand" "=rR,rR,Q,Q")
-       (plus:QI (match_operand:QI 1 "general_operand" "%0,0,0,0")
-                (match_operand:QI 2 "general_operand" "rRLM,Qi,rRLM,Qi")))]
-  ""
-  "*
-{
-  if (GET_CODE (operands[2]) == CONST_INT)
-    {
-      if (INTVAL(operands[2]) == 1)
-       return \"incb %0\";
-      else if (INTVAL(operands[2]) == -1)
-       return \"decb %0\";
-    }
-
-  return \"addb %2, %0\";
-}"
-  [(set_attr "length" "1,2,2,3")])
+  [(set_attr "length" "2,4,4,6")])
 
 \f
 ;;- subtract instructions
                  (match_operand:DF 2 "general_operand" "fR,Q")))]
   "TARGET_FPU"
   "{subd|subf} %2, %0"
-  [(set_attr "length" "1,2")])
+  [(set_attr "length" "2,4")])
 
 (define_insn "subsi3"
-  [(set (match_operand:SI 0 "general_operand" "=r,r,o,o")
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,o,o")
         (minus:SI (match_operand:SI 1 "general_operand" "0,0,0,0")
                   (match_operand:SI 2 "general_operand" "r,o,r,o")))]
   ""
 
      or is lateoperands the low word?? - looks like it! */
 
-  unsigned int i;
   rtx lateoperands[3];
   
   lateoperands[0] = operands[0];
 
   if (REG_P (operands[0]))
-    operands[0] = gen_rtx(REG, HImode, REGNO(operands[0]) + 1);
+    operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
   else
-    operands[0] = adj_offsettable_operand (operands[0], 2);
+    operands[0] = adjust_address (operands[0], HImode, 2);
   
   lateoperands[2] = operands[2];
 
   if (REG_P (operands[2]))
-    operands[2] = gen_rtx(REG, HImode, REGNO(operands[2]) + 1);
+    operands[2] = gen_rtx_REG (HImode, REGNO (operands[2]) + 1);
   else
-    operands[2] = adj_offsettable_operand(operands[2], 2);
+    operands[2] = adjust_address (operands[2], HImode, 2);
 
   output_asm_insn (\"sub %2, %0\", operands);
   output_asm_insn (\"sbc %0\", lateoperands);
   return \"\";
 }"
 ;; offsettable memory addresses always are expensive!!!
-  [(set_attr "length" "3,5,6,8")])
+  [(set_attr "length" "6,10,12,16")])
 
 (define_insn "subhi3"
-  [(set (match_operand:HI 0 "general_operand" "=rR,rR,Q,Q")
+  [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,rR,Q,Q")
        (minus:HI (match_operand:HI 1 "general_operand" "0,0,0,0")
                  (match_operand:HI 2 "general_operand" "rR,Qi,rR,Qi")))]
   ""
   "*
 {
-  if (GET_CODE (operands[2]) == CONST_INT)
-    abort();
+  gcc_assert (GET_CODE (operands[2]) != CONST_INT);
 
   return \"sub %2, %0\";
 }"
-  [(set_attr "length" "1,2,2,3")])
-
-(define_insn "subqi3"
-  [(set (match_operand:QI 0 "general_operand" "=rR,rR,Q,Q")
-       (minus:QI (match_operand:QI 1 "general_operand" "0,0,0,0")
-                 (match_operand:QI 2 "general_operand" "rR,Qi,rR,Qi")))]
-  ""
-  "*
-{
-  if (GET_CODE (operands[2]) == CONST_INT)
-    abort();
-
-  return \"subb %2, %0\";
-}"
-  [(set_attr "length" "1,2,2,3")])
+  [(set_attr "length" "2,4,4,6")])
 
 ;;;;- and instructions
-;; Bit-and on the pdp (like on the vax) is done with a clear-bits insn.
-(define_expand "andsi3"
-  [(set (match_operand:SI 0 "general_operand" "=g")
-       (and:SI (match_operand:SI 1 "general_operand" "0")
-               (not:SI (match_operand:SI 2 "general_operand" "g"))))]
-  ""
-  "
-{
-  extern rtx expand_unop ();
-  if (GET_CODE (operands[2]) == CONST_INT)
-    operands[2] = GEN_INT (~INTVAL (operands[2]));
-  else
-    operands[2] = expand_unop (SImode, one_cmpl_optab, operands[2], 0, 1);
-}")
-
-(define_expand "andhi3"
-  [(set (match_operand:HI 0 "general_operand" "=g")
-       (and:HI (match_operand:HI 1 "general_operand" "0")
-               (not:HI (match_operand:HI 2 "general_operand" "g"))))]
-  ""
-  "
-{
-  extern rtx expand_unop ();
-  if (GET_CODE (operands[2]) == CONST_INT)
-    operands[2] = GEN_INT (~INTVAL (operands[2]));
-  else
-    operands[2] = expand_unop (HImode, one_cmpl_optab, operands[2], 0, 1);
-}")
+;; Bit-and on the pdp (like on the VAX) is done with a clear-bits insn.
 
-(define_expand "andqi3"
-  [(set (match_operand:QI 0 "general_operand" "=g")
-       (and:QI (match_operand:QI 1 "general_operand" "0")
-               (not:QI (match_operand:QI 2 "general_operand" "g"))))]
+(define_expand "and<mode>3"
+  [(set (match_operand:PDPint 0 "nonimmediate_operand" "")
+       (and:PDPint (not:PDPint (match_operand:PDPint 1 "general_operand" ""))
+                  (match_operand:PDPint 2 "general_operand" "")))]
   ""
   "
 {
-  extern rtx expand_unop ();
-  rtx op = operands[2];
-  if (GET_CODE (op) == CONST_INT)
-    operands[2] = GEN_INT (((1 << 8) - 1) & ~INTVAL (op));
-  else
-    operands[2] = expand_unop (QImode, one_cmpl_optab, op, 0, 1);
-}")
-
-(define_insn "andcbsi3"
-  [(set (match_operand:SI 0 "general_operand" "=r,r,o,o,r,r,r,o,o,o")
-        (and:SI (match_operand:SI 1 "general_operand" "%0,0,0,0,0,0,0,0,0,0")
-                (not:SI (match_operand:SI 2 "general_operand" "r,o,r,o,I,J,K,I,J,K"))))]
-  ""
-  "*
-{ /* Here we trust that operands don't overlap 
-
-     or is lateoperands the low word?? - looks like it! */
+  rtx op1 = operands[1];
 
-  unsigned int i;
-  rtx lateoperands[3];
-  
-  lateoperands[0] = operands[0];
+  /* If there is a constant argument, complement that one.
+     Similarly, if one of the inputs is the same as the output,
+     complement the other input.  */
+  if ((CONST_INT_P (operands[2]) && ! CONST_INT_P (op1)) ||
+      rtx_equal_p (operands[0], operands[1]))
+    {
+      operands[1] = operands[2];
+      operands[2] = op1;
+      op1 = operands[1];
+    }
 
-  if (REG_P (operands[0]))
-    operands[0] = gen_rtx(REG, HImode, REGNO(operands[0]) + 1);
+  if (CONST_INT_P (op1))
+    operands[1] = GEN_INT (~INTVAL (op1));
   else
-    operands[0] = adj_offsettable_operand (operands[0], 2);
-  
-  if (! CONSTANT_P(operands[2]))
-  {
-    lateoperands[2] = operands[2];
-
-    if (REG_P (operands[2]))
-      operands[2] = gen_rtx(REG, HImode, REGNO(operands[2]) + 1);
-    else
-      operands[2] = adj_offsettable_operand(operands[2], 2);
-
-    output_asm_insn (\"bic %2, %0\", operands);
-    output_asm_insn (\"bic %2, %0\", lateoperands);
-    return \"\";
-  }
-
-  lateoperands[2] = GEN_INT ((INTVAL(operands[2]) >> 16) & 0xffff);
-  operands[2] = GEN_INT (INTVAL(operands[2]) & 0xffff);
-  
-  /* these have different lengths, so we should have 
-     different constraints! */
-  if (INTVAL(operands[2]))
-    output_asm_insn (\"bic %2, %0\", operands);
-
-  if (INTVAL(lateoperands[2]))
-    output_asm_insn (\"bic %2, %0\", lateoperands);
-
-  return \"\";
-}"
-  [(set_attr "length" "2,4,4,6,2,2,4,3,3,6")])
-
-(define_insn "andcbhi3"
-  [(set (match_operand:HI 0 "general_operand" "=rR,rR,Q,Q")
-       (and:HI (match_operand:HI 1 "general_operand" "0,0,0,0")
-               (not:HI (match_operand:HI 2 "general_operand" "rR,Qi,rR,Qi"))))]
-  ""
-  "bic %2, %0"
-  [(set_attr "length" "1,2,2,3")])
+    operands[1] = expand_unop (<MODE>mode, one_cmpl_optab, op1, 0, 1);
+}")
 
-(define_insn "andcbqi3"
-  [(set (match_operand:QI 0 "general_operand" "=rR,rR,Q,Q")
-       (and:QI (match_operand:QI 1 "general_operand" "0,0,0,0")
-               (not:QI (match_operand:QI 2 "general_operand" "rR,Qi,rR,Qi"))))]
+(define_insn "*bic<mode>"
+  [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,rR,Q,Q")
+       (and:PDPint
+            (not: PDPint (match_operand:PDPint 1 "general_operand" "rR,Qi,rR,Qi"))
+            (match_operand:PDPint 2 "general_operand" "0,0,0,0")))]
   ""
-  "bicb %2, %0"
-  [(set_attr "length" "1,2,2,3")])
+  "bic<PDPint:isfx> %1, %0"
+  [(set_attr "length" "2,4,4,6")])
 
 ;;- Bit set (inclusive or) instructions
-(define_insn "iorsi3"
-  [(set (match_operand:SI 0 "general_operand" "=r,r,o,o,r,r,r,o,o,o")
-        (ior:SI (match_operand:SI 1 "general_operand" "%0,0,0,0,0,0,0,0,0,0")
-                  (match_operand:SI 2 "general_operand" "r,o,r,o,I,J,K,I,J,K")))]
-  ""
-  "*
-{ /* Here we trust that operands don't overlap 
-
-     or is lateoperands the low word?? - looks like it! */
-
-  unsigned int i;
-  rtx lateoperands[3];
-  
-  lateoperands[0] = operands[0];
-
-  if (REG_P (operands[0]))
-    operands[0] = gen_rtx(REG, HImode, REGNO(operands[0]) + 1);
-  else
-    operands[0] = adj_offsettable_operand (operands[0], 2);
-  
-  if (! CONSTANT_P(operands[2]))
-  {
-    lateoperands[2] = operands[2];
-
-    if (REG_P (operands[2]))
-      operands[2] = gen_rtx(REG, HImode, REGNO(operands[2]) + 1);
-    else
-      operands[2] = adj_offsettable_operand(operands[2], 2);
-
-    output_asm_insn (\"bis %2, %0\", operands);
-    output_asm_insn (\"bis %2, %0\", lateoperands);
-    return \"\";
-  }
-
-  lateoperands[2] = GEN_INT ((INTVAL(operands[2]) >> 16) & 0xffff);
-  operands[2] = GEN_INT (INTVAL(operands[2]) & 0xffff);
-  
-  /* these have different lengths, so we should have 
-     different constraints! */
-  if (INTVAL(operands[2]))
-    output_asm_insn (\"bis %2, %0\", operands);
-
-  if (INTVAL(lateoperands[2]))
-    output_asm_insn (\"bis %2, %0\", lateoperands);
-
-  return \"\";
-}"
-  [(set_attr "length" "2,4,4,6,2,2,4,3,3,6")])
-
-(define_insn "iorhi3"
-  [(set (match_operand:HI 0 "general_operand" "=rR,rR,Q,Q")
-       (ior:HI (match_operand:HI 1 "general_operand" "%0,0,0,0")
-               (match_operand:HI 2 "general_operand" "rR,Qi,rR,Qi")))]
+(define_insn "ior<mode>3"
+  [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,rR,Q,Q")
+       (ior:PDPint (match_operand:PDPint 1 "general_operand" "%0,0,0,0")
+               (match_operand:PDPint 2 "general_operand" "rR,Qi,rR,Qi")))]
   ""
-  "bis %2, %0"
-  [(set_attr "length" "1,2,2,3")])
-
-(define_insn "iorqi3"
-  [(set (match_operand:QI 0 "general_operand" "=rR,rR,Q,Q")
-       (ior:QI (match_operand:QI 1 "general_operand" "%0,0,0,0")
-               (match_operand:QI 2 "general_operand" "rR,Qi,rR,Qi")))]
-  ""
-  "bisb %2, %0")
+  "bis<PDPint:isfx> %2, %0"
+  [(set_attr "length" "2,4,4,6")])
 
 ;;- xor instructions
-(define_insn "xorsi3"
-  [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
-        (xor:SI (match_operand:SI 1 "register_operand" "%0,0,0,0")
-                  (match_operand:SI 2 "arith_operand" "r,I,J,K")))]
-  "TARGET_40_PLUS"
-  "*
-{ /* Here we trust that operands don't overlap */
-
-  unsigned int i;
-  rtx lateoperands[3];
-
-  lateoperands[0] = operands[0];
-  operands[0] = gen_rtx(REG, HImode, REGNO(operands[0]) + 1);
-
-  if (REG_P(operands[2]))
-  {
-    lateoperands[2] = operands[2];
-    operands[2] = gen_rtx(REG, HImode, REGNO(operands[2]) + 1);
-    
-    output_asm_insn (\"xor %2, %0\", operands);
-    output_asm_insn (\"xor %2, %0\", lateoperands);
-
-    return \"\";
-  }
-
-  lateoperands[2] = GEN_INT ((INTVAL(operands[2]) >> 16) & 0xffff);
-  operands[2] = GEN_INT (INTVAL(operands[2]) & 0xffff);
-  
-  if (INTVAL(operands[2]))
-    output_asm_insn (\"xor %2, %0\", operands);
-
-  if (INTVAL(lateoperands[2]))
-    output_asm_insn (\"xor %2, %0\", lateoperands);
-
-  return \"\";
-}"
-  [(set_attr "length" "2,1,1,2")])
-
 (define_insn "xorhi3"
-  [(set (match_operand:HI 0 "general_operand" "=rR,Q")
+  [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
        (xor:HI (match_operand:HI 1 "general_operand" "%0,0")
                (match_operand:HI 2 "register_operand" "r,r")))]
   "TARGET_40_PLUS"
   "xor %2, %0"
-  [(set_attr "length" "1,2")])
+  [(set_attr "length" "2,4")])
 
 ;;- one complement instructions
 
-(define_insn "one_cmplhi2"
-  [(set (match_operand:HI 0 "general_operand" "=rR,Q")
-        (not:HI (match_operand:HI 1 "general_operand" "0,0")))]
+(define_insn "one_cmpl<mode>2"
+  [(set (match_operand:PDPint 0 "nonimmediate_operand" "=rR,Q")
+        (not:PDPint (match_operand:PDPint 1 "general_operand" "0,0")))]
   ""
-  "com %0"
-  [(set_attr "length" "1,2")])
-
-(define_insn "one_cmplqi2"
-  [(set (match_operand:QI 0 "general_operand" "=rR,Q")
-        (not:QI (match_operand:QI 1 "general_operand" "0,0")))]
-  ""
-  "comb %0"
-  [(set_attr "length" "1,2")])
+  "com<PDPint:isfx> %0"
+  [(set_attr "length" "2,4")])
 
 ;;- arithmetic shift instructions
 (define_insn "ashlsi3"
   [(set (match_operand:SI 0 "register_operand" "=r,r")
        (ashift:SI (match_operand:SI 1 "register_operand" "0,0")
                   (match_operand:HI 2 "general_operand" "rR,Qi")))]
-  "TARGET_45"
+  "TARGET_40_PLUS"
   "ashc %2,%0"
-  [(set_attr "length" "1,2")])
+  [(set_attr "length" "2,4")])
 
 ;; Arithmetic right shift on the pdp works by negating the shift count.
 (define_expand "ashrsi3"
 
 ;; asl 
 (define_insn "" 
-  [(set (match_operand:HI 0 "general_operand" "=rR,Q")
+  [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
        (ashift:HI (match_operand:HI 1 "general_operand" "0,0")
                   (const_int 1)))]
   ""
   "asl %0"
-  [(set_attr "length" "1,2")])
+  [(set_attr "length" "2,4")])
 
 ;; and another possibility for asr is << -1
 ;; might cause problems since -1 can also be encoded as 65535!
 
 ;; asr
 (define_insn "" 
-  [(set (match_operand:HI 0 "general_operand" "=rR,Q")
+  [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
        (ashift:HI (match_operand:HI 1 "general_operand" "0,0")
                   (const_int -1)))]
   ""
   "asr %0"
-  [(set_attr "length" "1,2")])
+  [(set_attr "length" "2,4")])
+
+;; lsr
+(define_insn "lsrhi1" 
+  [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
+       (lshiftrt:HI (match_operand:HI 1 "general_operand" "0,0")
+                  (const_int 1)))]
+  ""
+  "clc\;ror %0"
+  [(set_attr "length" "2,4")])
+
+(define_insn "lsrsi1"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (lshiftrt:SI (match_operand:SI 1 "general_operand" "0")
+                   (const_int 1)))]
+  ""
+{
+
+  rtx lateoperands[2];
+
+  lateoperands[0] = operands[0];
+  operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
+
+  lateoperands[1] = operands[1];
+  operands[1] = gen_rtx_REG (HImode, REGNO (operands[1]) + 1);
+
+  output_asm_insn (\"clc\", operands);
+  output_asm_insn (\"ror %0\", lateoperands);
+  output_asm_insn (\"ror %0\", operands);
+
+  return \"\";
+}
+  [(set_attr "length" "10")])
+
+(define_expand "lshrsi3"
+  [(match_operand:SI 0 "register_operand" "")
+   (match_operand:SI 1 "register_operand" "0")
+   (match_operand:HI 2 "general_operand" "")]
+  ""
+  "
+{
+  rtx r;
+
+  if (!TARGET_40_PLUS &&
+      (GET_CODE (operands[2]) != CONST_INT ||
+       (unsigned) INTVAL (operands[2]) > 3))
+    FAIL;
+  emit_insn (gen_lsrsi1 (operands[0], operands[1]));
+  if (GET_CODE (operands[2]) != CONST_INT)
+    {
+      r = gen_reg_rtx (HImode);
+      emit_insn (gen_addhi3 (r, operands [2], GEN_INT (-1)));
+      emit_insn (gen_ashrsi3 (operands[0], operands[0], r));
+    }
+  else if ((unsigned) INTVAL (operands[2]) != 1)
+    {
+      emit_insn (gen_ashlsi3 (operands[0], operands[0],
+                              GEN_INT (1 - INTVAL (operands[2]))));
+    }
+  DONE;
+}
+"
+)
 
 ;; shift is by arbitrary count is expensive, 
 ;; shift by one cheap - so let's do that, if
 ;; space doesn't matter
 (define_insn "" 
-  [(set (match_operand:HI 0 "general_operand" "=r")
+  [(set (match_operand:HI 0 "nonimmediate_operand" "=r")
        (ashift:HI (match_operand:HI 1 "general_operand" "0")
                   (match_operand:HI 2 "expand_shift_operand" "O")))]
   "! optimize_size"
   return \"\";
 }"
 ;; longest is 4
-  [(set (attr "length") (const_int 4))])
+  [(set (attr "length") (const_int 8))])
 
 ;; aslb
 (define_insn "" 
-  [(set (match_operand:QI 0 "general_operand" "=r,o")
+  [(set (match_operand:QI 0 "nonimmediate_operand" "=r,o")
        (ashift:QI (match_operand:QI 1 "general_operand" "0,0")
-                  (match_operand:HI 2 "const_immediate_operand" "n,n")))]
+                  (match_operand:HI 2 "const_int_operand" "n,n")))]
   ""
   "*
 { /* allowing predec or post_inc is possible, but hairy! */
 }"
 ;; set attribute length ( match_dup 2 & 7 ) *(1 or 2) !!!
   [(set_attr_alternative "length" 
-                         [(const_int 7)
-                          (const_int 14)])])
+                         [(const_int 14)
+                          (const_int 28)])])
 
 ;;; asr 
 ;(define_insn "" 
-;  [(set (match_operand:HI 0 "general_operand" "=rR,Q")
+;  [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
 ;      (ashiftrt:HI (match_operand:HI 1 "general_operand" "0,0")
 ;                   (const_int 1)))]
 ;  ""
 ;  "asr %0"
-;  [(set_attr "length" "1,2")])
+;  [(set_attr "length" "2,4")])
 
 ;; asrb
 (define_insn "" 
-  [(set (match_operand:QI 0 "general_operand" "=r,o")
+  [(set (match_operand:QI 0 "nonimmediate_operand" "=r,o")
        (ashiftrt:QI (match_operand:QI 1 "general_operand" "0,0")
-                    (match_operand:HI 2 "const_immediate_operand" "n,n")))]
+                    (match_operand:HI 2 "const_int_operand" "n,n")))]
   ""
   "*
 { /* allowing predec or post_inc is possible, but hairy! */
   return \"\";
 }"
   [(set_attr_alternative "length" 
-                         [(const_int 7)
-                          (const_int 14)])])
+                         [(const_int 14)
+                          (const_int 28)])])
 
 ;; the following is invalid - too complex!!! - just say 14 !!!
 ;  [(set (attr "length") (plus (and (match_dup 2)
-;                                   (const_int 7))
+;                                   (const_int 14))
 ;                              (and (match_dup 2)
-;                                   (const_int 7))))])
+;                                   (const_int 14))))])
 
 
 
   [(set (match_operand:HI 0 "register_operand" "=r,r")
        (ashift:HI (match_operand:HI 1 "register_operand" "0,0")
                   (match_operand:HI 2 "general_operand" "rR,Qi")))]
-  ""
+  "TARGET_40_PLUS"
   "*
 {
   if (GET_CODE(operands[2]) == CONST_INT)
 
   return \"ash %2,%0\";
 }"
-  [(set_attr "length" "1,2")])
+  [(set_attr "length" "2,4")])
 
 ;; Arithmetic right shift on the pdp works by negating the shift count.
 (define_expand "ashrhi3"
   operands[2] = negate_rtx (HImode, operands[2]);
 }")
 
-;;;;- logical shift instructions
-;;(define_insn "lshrsi3"
-;;  [(set (match_operand:HI 0 "register_operand" "=r")
-;;     (lshiftrt:HI (match_operand:HI 1 "register_operand" "0")
-;;                  (match_operand:HI 2 "arith_operand" "rI")))]
-;;  ""
-;;  "srl %0,%2")
+(define_expand "lshrhi3"
+  [(match_operand:HI 0 "register_operand" "")
+   (match_operand:HI 1 "register_operand" "")
+   (match_operand:HI 2 "general_operand" "")]
+  ""
+  "
+{
+  rtx r;
+
+  if (!TARGET_40_PLUS &&
+      (GET_CODE (operands[2]) != CONST_INT ||
+       (unsigned) INTVAL (operands[2]) > 3))
+    FAIL;
+  emit_insn (gen_lsrhi1 (operands[0], operands[1]));
+  if (GET_CODE (operands[2]) != CONST_INT)
+    {
+      r = gen_reg_rtx (HImode);
+      emit_insn (gen_addhi3 (r, operands [2], GEN_INT (-1)));
+      emit_insn (gen_ashrhi3 (operands[0], operands[0], r));
+    }
+  else if ((unsigned) INTVAL (operands[2]) != 1)
+    {
+      emit_insn (gen_ashlhi3 (operands[0], operands[0],
+                              GEN_INT (1 - INTVAL (operands[2]))));
+    }
+  DONE;
+}
+"
+)
 
 ;; absolute 
 
 (define_insn "absdf2"
-  [(set (match_operand:DF 0 "general_operand" "=fR,Q")
+  [(set (match_operand:DF 0 "nonimmediate_operand" "=fR,Q")
        (abs:DF (match_operand:DF 1 "general_operand" "0,0")))]
   "TARGET_FPU"
   "{absd|absf} %0"
-  [(set_attr "length" "1,2")])
+  [(set_attr "length" "2,4")])
 
 (define_insn "abshi2"
-  [(set (match_operand:HI 0 "general_operand" "=r,o")
+  [(set (match_operand:HI 0 "nonimmediate_operand" "=r,o")
        (abs:HI (match_operand:HI 1 "general_operand" "0,0")))]
-  "TARGET_ABSHI_BUILTIN"
+  ""
   "*
 {
   static int count = 0;
 
   return \"\";
 }"
-  [(set_attr "length" "3,5")])
+  [(set_attr "length" "6,10")])
 
 
 ;; define expand abshi - is much better !!! - but
 ; -- just a thought - don't have time to check 
 ;
 ;(define_expand "abshi2"
-;  [(match_operand:HI 0 "general_operand" "")
+;  [(match_operand:HI 0 "nonimmediate_operand" "")
 ;   (match_operand:HI 1 "general_operand" "")]
 ;  ""
 ;  "
 ;
 ;  /* allow REG_NOTES to be set on last insn (labels don't have enough
 ;     fields, and can't be used for REG_NOTES anyway).  */
-;  emit_insn (gen_rtx (USE, VOIDmode, stack_pointer_rtx));
+;  emit_use (stack_pointer_rtx);
 ;  DONE;
 ;}")
 
 ;; negate insns
 
 (define_insn "negdf2"
-  [(set (match_operand:DF 0 "general_operand" "=fR,Q")
+  [(set (match_operand:DF 0 "float_nonimm_operand" "=fR,Q")
        (neg:DF (match_operand:DF 1 "register_operand" "0,0")))]
   "TARGET_FPU"
   "{negd|negf} %0"
-  [(set_attr "length" "1,2")])
+  [(set_attr "length" "2,4")])
+
+(define_insn "negsi2"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (neg:SI (match_operand:SI 1 "general_operand" "0")))]
+  ""
+{
+
+  rtx lateoperands[2];
+
+  lateoperands[0] = operands[0];
+  operands[0] = gen_rtx_REG (HImode, REGNO (operands[0]) + 1);
+
+  lateoperands[1] = operands[1];
+  operands[1] = gen_rtx_REG (HImode, REGNO (operands[1]) + 1);
+
+  output_asm_insn (\"com %0\", lateoperands);
+  output_asm_insn (\"com %0\", operands);
+  output_asm_insn (\"add $1, %0\", operands);
+  output_asm_insn (\"adc %0\", lateoperands);
+
+  return \"\";
+}
+  [(set_attr "length" "14")])
 
 (define_insn "neghi2"
-  [(set (match_operand:HI 0 "general_operand" "=rR,Q")
+  [(set (match_operand:HI 0 "nonimmediate_operand" "=rR,Q")
        (neg:HI (match_operand:HI 1 "general_operand" "0,0")))]
   ""
   "neg %0"
-  [(set_attr "length" "1,2")])
+  [(set_attr "length" "2,4")])
 
 (define_insn "negqi2"
-  [(set (match_operand:QI 0 "general_operand" "=rR,Q")
+  [(set (match_operand:QI 0 "nonimmediate_operand" "=rR,Q")
        (neg:QI (match_operand:QI 1 "general_operand" "0,0")))]
   ""
   "negb %0"
-  [(set_attr "length" "1,2")])
+  [(set_attr "length" "2,4")])
 
 
 ;; Unconditional and other jump instructions
   [(set (pc)
        (label_ref (match_operand 0 "" "")))]
   ""
-  "jmp %l0"
-  [(set_attr "length" "2")])
+  "*
+{
+ if (get_attr_length (insn) == 2)
+    return \"br %l0\";
+ return \"jmp %l0\";
+}"
+  [(set (attr "length") (if_then_else (ior (lt (minus (match_dup 0)
+                                                     (pc))
+                                              (const_int MIN_BRANCH))
+                                          (gt (minus (match_dup 0)
+                                                     (pc))
+                                              (const_int MAX_BRANCH)))
+                                     (const_int 4)
+                                     (const_int 2)))])
 
 (define_insn ""
   [(set (pc)
    (clobber (const_int 1))]
   ""
   "jmp %l0"
-  [(set_attr "length" "2")])
+  [(set_attr "length" "4")])
 
 (define_insn "tablejump"
   [(set (pc) (match_operand:HI 0 "general_operand" "rR,Q"))
    (use (label_ref (match_operand 1 "" "")))]
   ""
   "jmp %0"
-  [(set_attr "length" "1,2")])
+  [(set_attr "length" "2,4")])
 
 ;; indirect jump - let's be conservative!
 ;; allow only register_operand, even though we could also 
 ;;- jump to subroutine
 
 (define_insn "call"
-  [(call (match_operand:HI 0 "general_operand" "R,Q")
+  [(call (match_operand:HI 0 "general_operand" "rR,Q")
         (match_operand:HI 1 "general_operand" "g,g"))
 ;;   (use (reg:HI 0)) what was that ???
   ]
   ;;- Don't use operand 1 for most machines.
   ""
   "jsr pc, %0"
-  [(set_attr "length" "1,2")])
+  [(set_attr "length" "2,4")])
 
 ;;- jump to subroutine
 (define_insn "call_value"
   [(set (match_operand 0 "" "")
-       (call (match_operand:HI 1 "general_operand" "R,Q")
+       (call (match_operand:HI 1 "general_operand" "rR,Q")
              (match_operand:HI 2 "general_operand" "g,g")))
 ;;   (use (reg:HI 0)) - what was that ????
   ]
   ;;- Don't use operand 2 for most machines.
   ""
   "jsr pc, %1"
-  [(set_attr "length" "1,2")])
+  [(set_attr "length" "2,4")])
 
 ;;- nop instruction
 (define_insn "nop"
 (define_insn "muldf3"
   [(set (match_operand:DF 0 "register_operand" "=a,a,a")
        (mult:DF (match_operand:DF 1 "register_operand" "%0,0,0")
-                (match_operand:DF 2 "general_operand" "fR,Q,F")))]
+                (match_operand:DF 2 "float_operand" "fR,Q,F")))]
   "TARGET_FPU"
   "{muld|mulf} %2, %0"
-  [(set_attr "length" "1,2,5")])
+  [(set_attr "length" "2,4,10")])
 
 ;; 16 bit result multiply:
 ;; currently we multiply only into odd registers, so we don't use two 
 (define_insn "mulhi3"
   [(set (match_operand:HI 0 "register_operand" "=d,d") ; multiply regs
        (mult:HI (match_operand:HI 1 "register_operand" "%0,0")
-                (match_operand:HI 2 "general_operand" "rR,Qi")))]
-  "TARGET_45"
+                (match_operand:HI 2 "float_operand" "rR,Qi")))]
+  "TARGET_40_PLUS"
   "mul %2, %0"
-  [(set_attr "length" "1,2")])
+  [(set_attr "length" "2,4")])
 
 ;; 32 bit result
 (define_expand "mulhisi3"
   [(set (match_dup 3)
-       (match_operand:HI 1 "general_operand" "g,g"))
+       (match_operand:HI 1 "nonimmediate_operand" "g,g"))
    (set (match_operand:SI 0 "register_operand" "=r,r") ; even numbered!
        (mult:SI (truncate:HI 
                   (match_dup 0))
                 (match_operand:HI 2 "general_operand" "rR,Qi")))]
-  "TARGET_45"
+  "TARGET_40_PLUS"
   "operands[3] = gen_lowpart(HImode, operands[1]);")
 
 (define_insn ""
        (mult:SI (truncate:HI 
                   (match_operand:SI 1 "register_operand" "%0,0"))
                 (match_operand:HI 2 "general_operand" "rR,Qi")))]
-  "TARGET_45"
+  "TARGET_40_PLUS"
   "mul %2, %0"
-  [(set_attr "length" "1,2")])
+  [(set_attr "length" "2,4")])
 
 ;(define_insn "mulhisi3"
 ;  [(set (match_operand:SI 0 "register_operand" "=r,r") ; even numbered!
 ;      (mult:SI (truncate:HI 
 ;                  (match_operand:SI 1 "register_operand" "%0,0"))
 ;               (match_operand:HI 2 "general_operand" "rR,Qi")))]
-;  "TARGET_45"
+;  "TARGET_40_PLUS"
 ;  "mul %2, %0"
-;  [(set_attr "length" "1,2")])
+;  [(set_attr "length" "2,4")])
 
 ;;- divide
 (define_insn "divdf3"
                (match_operand:DF 2 "general_operand" "fR,Q,F")))]
   "TARGET_FPU"
   "{divd|divf} %2, %0"
-  [(set_attr "length" "1,2,5")])
+  [(set_attr "length" "2,4,10")])
 
         
 (define_expand "divhi3"
   [(set (subreg:HI (match_dup 1) 0)
-       (div:HI (match_operand:SI 1 "general_operand" "0")
+       (div:HI (match_operand:SI 1 "register_operand" "0")
                (match_operand:HI 2 "general_operand" "g")))
-   (set (match_operand:HI 0 "general_operand" "=r")
+   (set (match_operand:HI 0 "register_operand" "=r")
         (subreg:HI (match_dup 1) 0))]
-  "TARGET_45"
+  "TARGET_40_PLUS"
   "")
 
 (define_insn ""
-  [(set (subreg:HI (match_operand:SI 0 "general_operand" "=r") 0)
+  [(set (subreg:HI (match_operand:SI 0 "register_operand" "=r") 0)
        (div:HI (match_operand:SI 1 "general_operand" "0")
                (match_operand:HI 2 "general_operand" "g")))]
-  "TARGET_45"
+  "TARGET_40_PLUS"
   "div %2,%0"
-  [(set_attr "length" "2")])
+  [(set_attr "length" "4")])
 
 (define_expand "modhi3"
-  [(set (subreg:HI (match_dup 1) 1)
-       (mod:HI (match_operand:SI 1 "general_operand" "0")
+  [(set (subreg:HI (match_dup 1) 2)
+       (mod:HI (match_operand:SI 1 "register_operand" "0")
                (match_operand:HI 2 "general_operand" "g")))
-   (set (match_operand:HI 0 "general_operand" "=r")
-        (subreg:HI (match_dup 1) 1))]
-  "TARGET_45"
+   (set (match_operand:HI 0 "register_operand" "=r")
+        (subreg:HI (match_dup 1) 2))]
+  "TARGET_40_PLUS"
   "")
 
 (define_insn ""
-  [(set (subreg:HI (match_operand:SI 0 "general_operand" "=r") 1)
+  [(set (subreg:HI (match_operand:SI 0 "register_operand" "=r") 2)
        (mod:HI (match_operand:SI 1 "general_operand" "0")
                (match_operand:HI 2 "general_operand" "g")))]
-  "TARGET_45"
+  "TARGET_40_PLUS"
   "div %2,%0"
-  [(set_attr "length" "2")])
+  [(set_attr "length" "4")])
 
 ;(define_expand "divmodhi4"
 ;  [(parallel [(set (subreg:HI (match_dup 1) 0)
-;                 (div:HI (match_operand:SI 1 "general_operand" "0")
+;                 (div:HI (match_operand:SI 1 "register_operand" "0")
 ;                         (match_operand:HI 2 "general_operand" "g")))
-;              (set (subreg:HI (match_dup 1) 1)
+;              (set (subreg:HI (match_dup 1) 2)
 ;                 (mod:HI (match_dup 1)
 ;                         (match_dup 2)))])
-;   (set (match_operand:HI 3 "general_operand" "=r")
-;        (subreg:HI (match_dup 1) 1))
-;   (set (match_operand:HI 0 "general_operand" "=r")
+;   (set (match_operand:HI 3 "register_operand" "=r")
+;        (subreg:HI (match_dup 1) 2))
+;   (set (match_operand:HI 0 "register_operand" "=r")
 ;        (subreg:HI (match_dup 1) 0))]
-;  "TARGET_45"
+;  "TARGET_40_PLUS"
 ;  "")
 ;
 ;(define_insn ""
-;  [(set (subreg:HI (match_operand:SI 0 "general_operand" "=r") 0)
+;  [(set (subreg:HI (match_operand:SI 0 "register_operand" "=r") 0)
 ;                 (div:HI (match_operand:SI 1 "general_operand" "0")
 ;                         (match_operand:HI 2 "general_operand" "g")))
-;   (set (subreg:HI (match_dup 0) 1)
+;   (set (subreg:HI (match_dup 0) 2)
 ;                 (mod:HI (match_dup 1)
 ;                         (match_dup 2)))]
-;  "TARGET_45"
+;  "TARGET_40_PLUS"
 ;  "div %2, %0")
 ;