Use GEN_INT when appropriate.
authorRichard Kenner <kenner@gcc.gnu.org>
Tue, 13 Oct 1992 23:08:44 +0000 (19:08 -0400)
committerRichard Kenner <kenner@gcc.gnu.org>
Tue, 13 Oct 1992 23:08:44 +0000 (19:08 -0400)
(define_attr type): New types for SQRT.
(call patterns): Use SCRATCH for LR0.
Use new predicate call_operand so that some integers can be
used as addresses; fix CALLI so it doesn't accept constant.
(EXBYTE, EXTHW, INBYTE, INHW): Use ZERO_EXTEND instead of AND
when combine will make it.
Use PSImode for BP value and don't reference BP explicitly.
Clean up define_expands for these operations.
(rotlsi3): Use PSImode pseudo for FC.
(sign_extend): Sign extension insns clobber BP.
({load,store}_multiple): Use PSImode pseudo for CR.
(MTSR): Add pattern for TRUNCATE from SImode to PSImode.
(sqrtsf2, sqrtdf2, movpsi): New patterns.
(load/store bytes/halfword): Clean up to accept temporaries as
input and use PSImode when required.
(movhi, movqi): Allocate temporaries here.
(reload_inqi, reload_outqi, reload_inhi, reload_outhi): New patterns.
(movdf, movdi, movti): Use SCRATCH for BP register.
(reload_{in,out}{df,di,ti}): New patterns.

From-SVN: r2445

gcc/config/a29k/a29k.md

index 06fe6f177eb3296cb6055fbd1d76500527665024..c99fa01dce182ea0f8ed8a42af77593fb04dacfb 100644 (file)
@@ -1,5 +1,5 @@
 ;;- Machine description for AMD Am29000 for GNU C compiler
-;;   Copyright (C) 1991 Free Software Foundation, Inc.
+;;   Copyright (C) 1991, 1992 Free Software Foundation, Inc.
 ;;   Contributed by Richard Kenner (kenner@nyu.edu)
 
 ;; This file is part of GNU CC.
@@ -31,7 +31,7 @@
 ;; Everything else is miscellaneous.
 
 (define_attr "type"
-  "call,branch,load,store,fadd,fmul,fam,fdiv,dmul,dam,ddiv,multi,misc"
+  "call,branch,load,store,fadd,fmul,fam,fdiv,fsqrt,dmul,dam,ddiv,dsqrt,multi,misc"
   (const_string "misc"))
 
 ;; ASM insns cannot go into a delay slot, so call them "multi".
@@ -69,7 +69,9 @@
 (define_function_unit "adder" 1 0 (eq_attr "type" "fadd,fam,dam") 3 0)
 
 (define_function_unit "divider" 1 0 (eq_attr "type" "fdiv") 11 10)
+(define_function_unit "divider" 1 0 (eq_attr "type" "fsqrt") 28 27)
 (define_function_unit "divider" 1 0 (eq_attr "type" "ddiv") 18 17)
+(define_function_unit "divider" 1 0 (eq_attr "type" "dsqrt") 57 56)
 \f
 ;; ADD
 (define_insn "addsi3"
   DONE;
 }")
 
+;; We indicate that LR0 is clobbered in the CALL_INSN itself.  Otherwise,
+;; reorg will think it is just clobbered by the called function.
+
 (define_expand "call"
   [(parallel [(call (match_operand:SI 0 "" "")
                    (match_operand 1 "" ""))
-             (clobber (reg:SI 32))])
+             (clobber (scratch:SI))])
    (match_operand 2 "" "")]
   ""
   "
   if (GET_CODE (operands[0]) != MEM)
     abort ();
 
-  if (! TARGET_SMALL_MEMORY
-      && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF)
-    operands[0] = gen_rtx (MEM, GET_MODE (operands[0]),
+  if (! call_operand (XEXP (operands[0], 0), SImode))
+    operands[0] = gen_rtx (MEM, SImode,
                           force_reg (Pmode, XEXP (operands[0], 0)));
 
   operands[2] = gen_clobbers_to (operands[2]);
 }")
  
-(define_insn ""
-  [(call (match_operand:SI 0 "memory_operand" "m")
-        (match_operand 1 "" ""))
-   (clobber (reg:SI 32))]
-  ""
-  "calli lr0,%0%#"
-  [(set_attr "type" "call")])
-
 (define_expand "call_value"
   [(parallel [(set (match_operand:SI 0 "gpc_reg_operand" "")
                   (call (match_operand:SI 1 "" "")
                         (match_operand 2 "" "")))
-                  (clobber (reg:SI 32))])
+                  (clobber (scratch:SI))])
    (match_operand 3 "" "")]
   ""
   "
   if (GET_CODE (operands[1]) != MEM)
     abort ();
 
-  if (! TARGET_SMALL_MEMORY
-      && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
-    operands[1] = gen_rtx (MEM, GET_MODE (operands[1]),
+  if (! call_operand (XEXP (operands[1], 0), SImode))
+    operands[1] = gen_rtx (MEM, SImode,
                           force_reg (Pmode, XEXP (operands[1], 0)));
 
   operands[3] = gen_clobbers_to (operands[3]);
 }")
  
 (define_insn ""
-  [(set (match_operand 0 "gpc_reg_operand" "=r")
-       (call (match_operand:SI 1 "memory_operand" "m")
-             (match_operand 2 "" "")))
-   (clobber (reg:SI 32))]
-  ""
-  "calli lr0,%1%#"
+  [(call (match_operand:SI 0 "memory_operand" "m")
+        (match_operand 1 "" ""))
+   (clobber (match_scratch:SI 2 "=l"))]
+  "GET_CODE (XEXP (operands[0], 0)) != CONST_INT"
+  "calli lr0,%0%#"
   [(set_attr "type" "call")])
 
 (define_insn ""
-  [(call (mem:SI (match_operand:SI 0 "immediate_operand" "i"))
+  [(call (mem:SI (match_operand:SI 0 "call_operand" "i"))
         (match_operand:SI 1 "general_operand" "g"))
-   (clobber (reg:SI 32))]
-  "GET_CODE (operands[0]) == SYMBOL_REF
-   && (TARGET_SMALL_MEMORY
-       || ! strcmp (XSTR (operands[0], 0), current_function_name))"
+   (clobber (match_scratch:SI 2 "=l"))]
+  ""
   "call lr0,%F0"
   [(set_attr "type" "call")])
 
 (define_insn ""
   [(set (match_operand 0 "gpc_reg_operand" "=r")
-       (call (mem:SI (match_operand:SI 1 "immediate_operand" "i"))
+       (call (match_operand:SI 1 "memory_operand" "m")
+             (match_operand 2 "" "")))
+   (clobber (match_scratch:SI 3 "=l"))]
+  "GET_CODE (XEXP (operands[1], 0)) != CONST_INT"
+  "calli lr0,%1%#"
+  [(set_attr "type" "call")])
+
+(define_insn ""
+  [(set (match_operand 0 "gpc_reg_operand" "=r")
+       (call (mem:SI (match_operand:SI 1 "call_operand" "i"))
              (match_operand:SI 2 "general_operand" "g")))
-   (clobber (reg:SI 32))]
-  "GET_CODE (operands[1]) == SYMBOL_REF
-   && (TARGET_SMALL_MEMORY
-       || ! strcmp (XSTR (operands[1], 0), current_function_name))"
+   (clobber (match_scratch:SI 3 "=l"))]
+  ""
   "call lr0,%F1"
   [(set_attr "type" "call")])
 
 (define_insn ""
   [(set (zero_extract:SI (match_operand:SI 0 "gpc_reg_operand" "+r")
                         (const_int 16)
-                        (match_operand:SI 1 "const_0_operand" ""))
+                        (match_operand:SI 1 "const_0_operand" "I"))
        (match_operand:SI 2 "cint_16_operand" "J"))]
   ""
-  "*
-{ operands[2] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) << 16);
-  return \"consth %0,%2\";
-}")
+  "consth %0,%m2")
 
 (define_insn ""
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
-       (ior:SI (and:SI (match_operand:SI 1 "gpc_reg_operand" "0")
-                       (const_int 65535))
+       (ior:SI (zero_extend:SI (match_operand:HI 1 "gpc_reg_operand" "0"))
                (match_operand:SI 2 "const_int_operand" "n")))]
-  "(INTVAL (operands[1]) & 0xffff) == 0"
+  "(INTVAL (operands[2]) & 0xffff) == 0"
   "consth %0,%2")
 
 (define_insn ""
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
-       (ior:SI (and:SI (match_operand:SI 1 "gpc_reg_operand" "0")
-                       (const_int 65535))
+       (ior:SI (zero_extend:SI (match_operand:HI 1 "gpc_reg_operand" "0"))
                (and:SI (match_operand:SI 2 "immediate_operand" "i")
                        (const_int -65536))))]
   ""
   "consth %0,%2")
-
 \f
 ;; CONVERT
 (define_insn "fix_truncsfsi2"
                        (const_int -256))
                (zero_extract:SI (match_operand:SI 2 "gpc_reg_operand" "r")
                                 (const_int 8)
-                                (ashift:SI (match_operand:SI 3 "register_operand" "b")
-                                           (const_int 3)))))]
+                                (ashift:PSI
+                                 (match_operand:PSI 3 "register_operand" "b")
+                                 (const_int 3)))))]
   ""
   "exbyte %0,%2,%1")
 
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
        (zero_extract:SI (match_operand:SI 1 "gpc_reg_operand" "r")
                         (const_int 8)
-                        (ashift:SI (match_operand:SI 2 "register_operand" "b")
-                                   (const_int 3))))]
+                        (ashift:PSI
+                         (match_operand:PSI 2 "register_operand" "b")
+                         (const_int 3))))]
   ""
   "exbyte %0,%1,0")
 
 (define_insn ""
   [(set (zero_extract:SI (match_operand:SI 0 "gpc_reg_operand" "+r")
                         (const_int 8)
-                        (match_operand:SI 1 "const_24_operand" ""))
+                        (match_operand:PSI 1 "const_24_operand" ""))
        (zero_extract:SI (match_operand:SI 2 "gpc_reg_operand" "r")
                         (const_int 8)
-                        (ashift:SI (match_operand:SI 3 "register_operand" "b")
-                                   (const_int 3))))]
+                        (ashift:PSI
+                         (match_operand:PSI 3 "register_operand" "b")
+                         (const_int 3))))]
   ""
   "exbyte %0,%2,%0")
 
 
   size = INTVAL (operands[2]);
   pos = INTVAL (operands[3]);
-  if ((size != 8 && size != 16) || pos % size != 0)
-    FAIL;
 
-  operands[3] = gen_rtx (ASHIFT, SImode,
-                        force_reg (SImode,
-                                   gen_rtx (CONST_INT, VOIDmode, pos / 8)),
-                        gen_rtx (CONST_INT, VOIDmode, 3));
-}")
-
-(define_expand "extv"
-  [(set (match_operand:SI 0 "gpc_reg_operand" "")
-       (zero_extract:SI (match_operand:SI 1 "gpc_reg_operand" "")
-                        (match_operand:SI 2 "general_operand" "")
-                        (match_operand:SI 3 "general_operand" "")))]
-  ""
-  "
-{
-  int pos;
+  /* Can't do this unless a byte extraction.  If extracting the high
+     or low byte, don't do this because a shift or AND is shorter.
+     Don't do 16-bit extracts, since the only two are the high and low
+     ends, and it is faster to do them with CONSTH and SRL.  */
 
-  if (GET_CODE (operands[2]) != CONST_INT
-      || GET_CODE (operands[3]) != CONST_INT)
+  if (size != 8 || (pos != 8 && pos != 16))
     FAIL;
 
-  pos = INTVAL (operands[3]);
-  if (INTVAL (operands[2]) != 16 || pos % 16 != 0)
-    FAIL;
+  operands[3] = gen_rtx (ASHIFT, PSImode,
+                        force_reg (PSImode, GEN_INT (pos / 8)),
+                        GEN_INT (3));
 
-  operands[3] = gen_rtx (ASHIFT, SImode,
-                        force_reg (SImode,
-                                   gen_rtx (CONST_INT, VOIDmode, pos / 8)),
-                        gen_rtx (CONST_INT, VOIDmode, 3));
 }")
 
 ;; EXHW
                (const_int -65536))
                (zero_extract:SI (match_operand:SI 2 "gpc_reg_operand" "r")
                                 (const_int 16)
-                                (ashift:SI (match_operand:SI 3 "register_operand" "b")
-                                           (const_int 3)))))]
+                                (ashift:PSI
+                                 (match_operand:PSI 3 "register_operand" "b")
+                                 (const_int 3)))))]
   ""
   "exhw %0,%2,%1")
 
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
        (zero_extract:SI (match_operand:SI 1 "gpc_reg_operand" "r")
                         (const_int 16)
-                        (ashift:SI (match_operand:SI 2 "register_operand" "b")
-                                   (const_int 3))))]
+                        (ashift:PSI
+                         (match_operand:PSI 2 "register_operand" "b")
+                         (const_int 3))))]
   ""
   "exhw %0,%1,0")
 
 (define_insn ""
   [(set (zero_extract:SI (match_operand:SI 0 "gpc_reg_operand" "+r")
                         (const_int 16)
-                        (match_operand:SI 1 "const_16_operand" ""))
+                        (match_operand:PSI 1 "const_16_operand" ""))
        (zero_extract:SI (match_operand:SI 2 "gpc_reg_operand" "r")
                         (const_int 16)
-                        (ashift:SI (match_operand:SI 3 "register_operand" "b")
-                                   (const_int 3))))]
+                        (ashift:PSI
+                         (match_operand:PSI 3 "register_operand" "b")
+                         (const_int 3))))]
   ""
   "exhw %0,%2,%0")
 
 ;; EXHWS
+;;
+;; This is probably unused.  The high-order 16-bits are obtained with an SRA
+;; insn.  The low-order 16 bits are a sign-extend, which is a pair of
+;; shifts.  Setting BP followed by the insn is equivalent, so we don't
+;; bother going to any trouble to generate this insn.
+
 (define_insn ""
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
        (sign_extract:SI (match_operand:SI 1 "gpc_reg_operand" "r")
                         (const_int 16)
-                        (ashift:SI (match_operand:SI 2 "register_operand" "b")
-                                   (const_int 3))))]
+                        (ashift:PSI
+                         (match_operand:PSI 2 "register_operand" "b")
+                         (const_int 3))))]
   ""
   "exhws %0,%1")
 \f
 (define_insn ""
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
        (rotate:SI (match_operand:SI 1 "gpc_reg_operand" "r")
-                  (reg:QI 178)))]
+                  (match_operand:PSI 2 "register_operand" "f")))]
   ""
   "extract %0,%1,%1")
 
 (define_expand "rotlsi3"
-  [(set (reg:QI 178)
-       (match_operand: SI 2 "gpc_reg_or_immediate_operand" ""))
+  [(set (match_dup 3)
+       (match_operand:SI 2 "gpc_reg_or_immediate_operand" ""))
    (set (match_operand:SI 0 "gpc_reg_operand" "")
        (rotate:SI (match_operand:SI 1 "gpc_reg_operand" "")
-                  (reg:QI 178)))]
+                  (match_dup 3)))]
   ""
   "
-{ operands[2] = gen_lowpart (QImode, operands[2]); }")
+{ operands[2] = gen_lowpart (PSImode, operands[2]);
+  operands[3] = gen_reg_rtx (PSImode);
+}")
+
+;; It would be nice to be able to have a define_split corresponding to the
+;; above, but there is no way to tell combine we need a PSImode temporary.
+;; If we put a (clobber (scratch:PSI)) there, combine would merge the above
+;; two insns.  This is bad because it then thinks only one insn is needed.
 \f
 ;; FADD
 (define_expand "addsf3"
 (define_insn ""
   [(set (zero_extract:SI (match_operand:SI 0 "gpc_reg_operand" "+r")
                         (const_int 8)
-                        (ashift:SI (match_operand:SI 2 "register_operand" "b")
-                                   (const_int 3)))
+                        (ashift:PSI
+                         (match_operand:PSI 2 "register_operand" "b")
+                         (const_int 3)))
        (match_operand:SI 1 "srcb_operand" "rI"))]
   ""
   "inbyte %0,%0,%1")
 
 (define_insn ""
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
-       (ior:SI (and:SI (not:SI (ashift:SI (const_int 255)
-                                          (ashift:SI (match_operand:SI 3 "register_operand" "b")
-                                                     (const_int 3))))
-                       (match_operand:SI 1 "gpc_reg_operand" "r"))
-               (ashift:SI (and:SI (match_operand:SI 2 "srcb_operand" "rI")
-                                  (const_int 255))
-                          (match_operand:SI 4 "const_24_operand" ""))))]
-  ""
-  "inbyte %0,%1,%2")
-
-(define_insn ""
-  [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
-       (ior:SI (and:SI (not:SI (ashift:SI (const_int 255)
-                                          (ashift:SI (match_operand:SI 3 "register_operand" "b")
-                                                     (const_int 3))))
-                       (match_operand:SI 1 "gpc_reg_operand" "r"))
-               (ashift:SI (match_operand:SI 2 "srcb_operand" "rI")
-                          (match_operand:SI 4 "const_24_operand" ""))))]
+       (ior:SI (and:SI
+                (not:SI
+                 (ashift:SI (const_int 255)
+                            (ashift:PSI
+                             (match_operand:PSI 3 "register_operand" "b")
+                             (const_int 3))))
+                (match_operand:SI 1 "gpc_reg_operand" "r"))
+               (ashift:SI (zero_extend:SI
+                           (match_operand:QI 2 "srcb_operand" "rI"))
+                          (ashift:PSI (match_dup 3) (const_int 3)))))]
   ""
   "inbyte %0,%1,%2")
 
 (define_insn ""
   [(set (zero_extract:SI (match_operand:SI 0 "gpc_reg_operand" "+r")
                         (const_int 16)
-                        (ashift:SI (match_operand:SI 2 "register_operand" "b")
-                                   (const_int 3)))
+                        (ashift:PSI
+                         (match_operand:PSI 2 "register_operand" "b")
+                         (const_int 3)))
        (match_operand:SI 1 "srcb_operand" "rI"))]
   ""
   "inhw %0,%0,%1")
 
 (define_insn ""
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
-       (ior:SI (and:SI (not:SI (ashift:SI (const_int 65535)
-                                          (ashift:SI (match_operand:SI 3 "register_operand" "b")
-                                                     (const_int 3))))
-                       (match_operand:SI 1 "gpc_reg_operand" "r"))
-               (ashift:SI (and:SI (match_operand:SI 2 "srcb_operand" "rI")
-                                  (const_int 65535))
-                          (match_operand:SI 4 "const_24_operand" ""))))]
-  ""
-  "inhw %0,%1,%2")
-
-(define_insn ""
-  [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
-       (ior:SI (and:SI (not:SI (ashift:SI (const_int 65535)
-                                          (ashift:SI (match_operand:SI 3 "register_operand" "b")
-                                                     (const_int 3))))
-                       (match_operand:SI 1 "gpc_reg_operand" "r"))
-               (ashift:SI (match_operand:SI 2 "srcb_operand" "rI")
-                          (match_operand:SI 4 "const_24_operand" ""))))]
+       (ior:SI (and:SI
+                (not:SI
+                 (ashift:SI (const_int 65535)
+                            (ashift:PSI
+                             (match_operand:PSI 3 "register_operand" "b")
+                             (const_int 3))))
+                (match_operand:SI 1 "gpc_reg_operand" "r"))
+               (ashift:SI (zero_extend:SI
+                           (match_operand:HI 2 "srcb_operand" "rI"))
+                          (ashift:PSI (match_dup 3) (const_int 3)))))]
   ""
   "inhw %0,%1,%2")
 
   if ((size != 8 && size != 16) || pos % size != 0)
     FAIL;
 
-  operands[2] = gen_rtx (ASHIFT, SImode,
-                        force_reg (SImode,
-                                   gen_rtx (CONST_INT, VOIDmode, pos / 8)),
-                        gen_rtx (CONST_INT, VOIDmode, 3));
+  operands[2] = gen_rtx (ASHIFT, PSImode,
+                        force_reg (PSImode, GEN_INT (pos / 8)),
+                        GEN_INT (3));
 }")
 \f
 ;; LOAD (also used by move insn).
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
        (mem:SI (and:SI (match_operand:SI 1 "gpc_reg_operand" "r")
                        (const_int -4))))
-   (set (reg:SI 177)
-       (and:SI (match_dup 1)
-               (const_int 3)))]
+   (set (match_operand:PSI 2 "register_operand" "=b")
+       (truncate:PSI (match_dup 1)))]
   "! TARGET_DW_ENABLE"
-  "load 0,17,%0,%1"
+  "load 0,16,%0,%1"
   [(set_attr "type" "load")])
 
 (define_insn ""
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
-       (mem:SI (and:SI (match_operand:SI 1 "gpc_reg_operand" "r")
-                       (const_int -4))))
-   (set (reg:SI 177)
-       (and:SI (match_dup 1)
-               (const_int 2)))]
-  "! TARGET_DW_ENABLE"
-  "load 0,18,%0,%1"
+       (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
+  "TARGET_DW_ENABLE"
+  "load 0,1,%0,%1"
   [(set_attr "type" "load")])
 
 (define_insn ""
-  [(set (match_operand 0 "gpc_reg_operand" "=r")
-       (match_operator 2 "extend_operator"
-                       [(match_operand 1 "memory_operand" "m")]))]
-  "TARGET_DW_ENABLE && GET_MODE (operands[0]) == GET_MODE (operands[2])"
-  "load 0,%X2,%0,%1"
+  [(set (match_operand:HI 0 "gpc_reg_operand" "=r")
+       (zero_extend:HI (match_operand:QI 1 "memory_operand" "m")))]
+  "TARGET_DW_ENABLE"
+  "load 0,1,%0,%1"
+  [(set_attr "type" "load")])
+
+(define_insn ""
+  [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+       (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
+  "TARGET_DW_ENABLE"
+  "load 0,2,%0,%1"
+  [(set_attr "type" "load")])
+
+(define_insn ""
+  [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+       (sign_extend:SI (match_operand:QI 1 "memory_operand" "m")))
+   (clobber (match_scratch:PSI 2 "=b"))]
+  "TARGET_DW_ENABLE"
+  "load 0,17,%0,%1"
+  [(set_attr "type" "load")])
+
+(define_insn ""
+  [(set (match_operand:HI 0 "gpc_reg_operand" "=r")
+       (sign_extend:HI (match_operand:QI 1 "memory_operand" "m")))
+   (clobber (match_scratch:PSI 2 "=b"))]
+  "TARGET_DW_ENABLE"
+  "load 0,17,%0,%1"
+  [(set_attr "type" "load")])
+
+(define_insn ""
+  [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+       (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
+   (clobber (match_scratch:PSI 2 "=b"))]
+  "TARGET_DW_ENABLE"
+  "load 0,18,%0,%1"
   [(set_attr "type" "load")])
 \f
 ;; LOADM
 (define_expand "load_multiple"
-  [(set (reg:SI 179)
-       (match_operand:SI 2 "const_int_operand" ""))
+  [(set (match_dup 4)
+       (match_operand:PSI 2 "const_int_operand" ""))
    (match_par_dup 3 [(set (match_operand:SI 0 "" "")
                          (match_operand:SI 1 "" ""))])]
   ""
   regno = REGNO (operands[0]);
 
   /* CR gets set to the number of registers minus one.  */
-  operands[2] = gen_rtx (CONST_INT, VOIDmode, count - 1);
+  operands[2] = GEN_INT(count - 1);
 
   operands[3] = gen_rtx (PARALLEL, VOIDmode, rtvec_alloc (count + 2));
   from = memory_address (SImode, XEXP (operands[1], 0));
   XVECEXP (operands[3], 0, 0) = gen_rtx (SET, VOIDmode,
                                         gen_rtx (REG, SImode, regno),
                                         gen_rtx (MEM, SImode, from));
-  XVECEXP (operands[3], 0, 1)
-    = gen_rtx (USE, VOIDmode, gen_rtx (REG, SImode, R_CR));
-  XVECEXP (operands[3], 0, 2)
-    = gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, SImode, R_CR));
+  operands[4] = gen_reg_rtx (PSImode);
+
+  XVECEXP (operands[3], 0, 1) = gen_rtx (USE, VOIDmode, operands[4]);
+  XVECEXP (operands[3], 0, 2) = gen_rtx (CLOBBER, VOIDmode, operands[4]);
 
   for (i = 1; i < count; i++)
     XVECEXP (operands[3], 0, i + 2)
 (define_insn ""
   [(set (match_operand 0 "gpc_reg_operand" "=r")
        (match_operand 1 "memory_operand" "m"))
-   (use (reg:SI 179))
-   (clobber (reg:SI 179))]
+   (use (match_operand:PSI 2 "register_operand" "+c"))
+   (clobber (match_dup 2))]
   "GET_MODE (operands[0]) == GET_MODE (operands[1])
    && GET_MODE_SIZE (GET_MODE (operands[0])) > UNITS_PER_WORD
    && ! TARGET_29050"
 (define_insn ""
   [(set (match_operand 0 "gpc_reg_operand" "=&r")
        (match_operand 1 "memory_operand" "m"))
-   (use (reg:SI 179))
-   (clobber (reg:SI 179))]
+   (use (match_operand:PSI 2 "register_operand" "+c"))
+   (clobber (match_dup 2))]
   "GET_MODE (operands[0]) == GET_MODE (operands[1])
    && GET_MODE_SIZE (GET_MODE (operands[0])) > UNITS_PER_WORD
    && TARGET_29050"
   [(match_parallel 0 "load_multiple_operation"
                   [(set (match_operand:SI 1 "gpc_reg_operand" "=r")
                         (match_operand:SI 2 "memory_operand" "m"))
-                   (use (reg:SI 179))
-                   (clobber (reg:SI 179))])]
+                   (use (match_operand:PSI 3 "register_operand" "+c"))
+                   (clobber (match_dup 3))])]
   "! TARGET_29050"
   "loadm 0,0,%1,%2"
   [(set_attr "type" "load")])
   [(match_parallel 0 "load_multiple_operation"
                   [(set (match_operand:SI 1 "gpc_reg_operand" "=&r")
                         (match_operand:SI 2 "memory_operand" "m"))
-                   (use (reg:SI 179))
-                   (clobber (reg:SI 179))])]
+                   (use (match_operand:PSI 3 "register_operand" "+c"))
+                   (clobber (match_dup 3))])]
   "TARGET_29050"
   "loadm 0,0,%1,%2"
   [(set_attr "type" "load")])
   "@
    mtsr %0,%1
    mtsrim %0,%1")
+
+(define_insn ""
+  [(set (match_operand:PSI 0 "register_operand" "=h,h")
+       (truncate:PSI
+        (match_operand:SI 1 "gpc_reg_or_immediate_operand" "r,i")))]
+  ""
+  "@
+   mtsr %0,%1
+   mtsrim %0,%1")
 \f
 ;; MULTIPLY, MULTM, MULTMU
 (define_insn "mulsi3"
   ""
   "sll %0,%1,%Q2")
 
+;; SQRT
+(define_insn "sqrtsf2"
+  [(set (match_operand:SF 0 "gpc_reg_operand" "=r")
+       (sqrt:SF (match_operand:SF 1 "gpc_reg_operand" "r")))]
+  "TARGET_29050"
+  "sqrt %0,%1,1"
+  [(set_attr "type" "fsqrt")])
+
+(define_insn "sqrtdf2"
+  [(set (match_operand:DF 0 "gpc_reg_operand" "=r")
+       (sqrt:DF (match_operand:DF 1 "gpc_reg_operand" "r")))]
+  "TARGET_29050"
+  "sqrt %0,%1,2"
+  [(set_attr "type" "dsqrt")])
+
 ;; SRA
 (define_insn "ashrsi3"
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
 }")
 
 (define_expand "store_multiple_no_bug"
-  [(set (reg:SI 179)
-       (match_operand:SI 2 "const_int_operand" ""))
+  [(set (match_dup 4)
+       (match_operand:PSI 2 "const_int_operand" ""))
    (match_par_dup 3 [(set (match_operand:SI 0 "" "")
                          (match_operand:SI 1 "" ""))])]
   ""
   regno = REGNO (operands[1]);
 
   /* CR gets set to the number of registers minus one.  */
-  operands[2] = gen_rtx (CONST_INT, VOIDmode, count - 1);
+  operands[2] = GEN_INT(count - 1);
 
   operands[3] = gen_rtx (PARALLEL, VOIDmode, rtvec_alloc (count + 2));
   from = memory_address (SImode, XEXP (operands[0], 0));
   XVECEXP (operands[3], 0, 0) = gen_rtx (SET, VOIDmode,
                                         gen_rtx (MEM, SImode, from),
                                         gen_rtx (REG, SImode, regno));
-  XVECEXP (operands[3], 0, 1)
-    = gen_rtx (USE, VOIDmode, gen_rtx (REG, SImode, R_CR));
-  XVECEXP (operands[3], 0, 2)
-    = gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, SImode, R_CR));
+  operands[4] = gen_reg_rtx (PSImode);
+  XVECEXP (operands[3], 0, 1) = gen_rtx (USE, VOIDmode, operands[4]);
+  XVECEXP (operands[3], 0, 2) = gen_rtx (CLOBBER, VOIDmode, operands[4]);
 
   for (i = 1; i < count; i++)
     XVECEXP (operands[3], 0, i + 2)
                                         gen_rtx (MEM, SImode, from),
                                         gen_rtx (REG, SImode, regno));
   XVECEXP (operands[3], 0, 1)
-    = gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, SImode, R_CR));
+    = gen_rtx (CLOBBER, VOIDmode, gen_rtx (SCRATCH, PSImode));
 
   for (i = 1; i < count; i++)
     XVECEXP (operands[3], 0, i + 1)
 (define_insn ""
   [(set (match_operand 0 "memory_operand" "=m")
        (match_operand 1 "gpc_reg_operand" "r"))
-   (clobber (reg:SI 179))]
+   (clobber (match_scratch:PSI 2 "=c"))]
   "!TARGET_NO_STOREM_BUG
    && GET_MODE (operands[0]) == GET_MODE (operands[1])
    && GET_MODE_SIZE (GET_MODE (operands[0])) > UNITS_PER_WORD"
   [(match_parallel 0 "store_multiple_operation"
                   [(set (match_operand:SI 1 "memory_operand" "=m")
                         (match_operand:SI 2 "gpc_reg_operand" "r"))
-                   (clobber (reg:SI 179))])]
+                   (clobber (match_scratch:PSI 3 "=c"))])]
   "!TARGET_NO_STOREM_BUG"
   "mtsrim cr,%V0\;storem 0,0,%2,%1"
   [(set_attr "type" "multi")])
 (define_insn ""
   [(set (match_operand 0 "memory_operand" "=m")
        (match_operand 1 "gpc_reg_operand" "r"))
-   (use (reg:SI 179))
-   (clobber (reg:SI 179))]
+   (use (match_operand:PSI 2 "register_operand" "+c"))
+   (clobber (match_dup 2))]
   "TARGET_NO_STOREM_BUG
    && GET_MODE (operands[0]) == GET_MODE (operands[1])
    && GET_MODE_SIZE (GET_MODE (operands[0])) > UNITS_PER_WORD"
   [(match_parallel 0 "store_multiple_operation"
                   [(set (match_operand:SI 1 "memory_operand" "=m")
                         (match_operand:SI 2 "gpc_reg_operand" "r"))
-                   (use (reg:SI 179))
-                   (clobber (reg:SI 179))])]
+                   (use (match_operand:PSI 3 "register_operand" "+c"))
+                   (clobber (match_dup 3))])]
   "TARGET_NO_STOREM_BUG"
   "storem 0,0,%2,%1"
   [(set_attr "type" "store")])
       target = operand_subword_force (operands[0], 0, SFmode);
       result = expand_binop (SImode, xor_optab,
                             operand_subword_force (operands[1], 0, SFmode),
-                            gen_rtx (CONST_INT, VOIDmode, 0x80000000),
-                            target, 0, OPTAB_WIDEN);
+                            GEN_INT(0x80000000), target, 0, OPTAB_WIDEN);
       if (result == 0)
        abort ();
 
       target = operand_subword (operands[0], 0, 1, DFmode);
       result = expand_binop (SImode, xor_optab,
                             operand_subword_force (operands[1], 0, DFmode),
-                            gen_rtx (CONST_INT, VOIDmode, 0x80000000),
-                            target, 0, OPTAB_WIDEN);
+                            GEN_INT(0x80000000), target, 0, OPTAB_WIDEN);
       if (result == 0)
        abort ();
 
     operands[1] = force_reg (SImode, operands[1]);
 }")
 
+(define_expand "movpsi"
+  [(set (match_operand:PSI 0 "general_operand" "")
+       (match_operand:PSI 1 "general_operand" ""))]
+  ""
+  "
+{
+  if (GET_CODE (operands[0]) == MEM
+      && ! gpc_reg_operand (operands[1], PSImode))
+    operands[1] = copy_to_mode_reg (PSImode, operands[1]);
+  else if (spec_reg_operand (operands[0], PSImode)
+          && ! (register_operand (operands[1], PSImode)
+                || cint_16_operand (operands[1], PSImode)))
+    operands[1] = force_reg (PSImode, operands[1]);
+}")
+
 (define_split
   [(set (match_operand:SI 0 "gpc_reg_operand" "")
        (match_operand:SI 1 "long_const_operand" ""))]
        (and:SI (match_dup 1)
                (const_int 65535)))
    (set (match_dup 0)
-       (ior:SI (and:SI (match_dup 0)
-                       (const_int 65535))
+       (ior:SI (zero_extend:SI (subreg:HI (match_dup 0) 0))
                (and:SI (match_dup 1)
                        (const_int -65536))))]
   "")
 \f
-;; Subroutines to load/store halfwords.  Use TAV (gr121) as scratch.  We have
-;; two versions of storehi, one when halfword writes are supported and one
-;; where they aren't.
+;; Subroutines to load/store halfwords.  Operands 0 and 1 are the output and
+;; input, respectively, except that the address is passed for a MEM instead 
+;; of the MEM itself and the short item is passed in QImode.
+;;
+;; Operand 2 is a scratch general register and operand 3 is a scratch register
+;; used for BP.  When called before reload, pseudos are passed for both
+;; operands.  During reload, R_TAV is used for the general register, and
+;; a reload register of class BR_REGS (R_VP) for BP.
+;;
+;; We have two versions of the store operations, for when halfword writes are
+;; supported and when they are not.
 (define_expand "loadhi"
-  [(parallel [(set (match_dup 2)
-                  (mem:SI (and:SI (match_operand:SI 0 "gpc_reg_operand" "")
+  [(parallel [(set (match_operand:SI 2 "gpc_reg_operand" "")
+                  (mem:SI (and:SI (match_operand:SI 1 "gpc_reg_operand" "")
                                   (const_int -4))))
-             (set (reg:SI 177)
-                  (and:SI (match_dup 0)
-                          (const_int 2)))])
-   (set (match_operand:HI 1 "gpc_reg_operand" "")
+             (set (match_operand:PSI 3 "register_operand" "")
+                  (truncate:PSI (match_dup 1)))])
+   (set (match_operand:SI 0 "gpc_reg_operand" "")
        (zero_extract:SI (match_dup 2)
                         (const_int 16)
-                        (ashift:SI (reg:SI 177)
-                                   (const_int 3))))]
+                        (ashift:PSI (match_dup 3) (const_int 3))))]
   ""
-  "
-{ operands[1] = gen_lowpart (SImode, operands[1]);
-
-  if (reload_in_progress)
-    operands[2] = gen_rtx (REG, SImode, R_TAV);
-  else
-    operands[2] = gen_reg_rtx (SImode);
-}")
+  "")
 
 (define_expand "storehinhww"
 [(parallel [(set (match_dup 2)
[(parallel [(set (match_operand:SI 2 "gpc_reg_operand" "")
                   (mem:SI (and:SI (match_operand:SI 0 "gpc_reg_operand" "")
                                   (const_int -4))))
-             (set (reg:SI 177)
-                  (and:SI (match_dup 0)
-                            (const_int 2)))])
+             (set (match_operand:PSI 3 "register_operand" "")
+                  (truncate:PSI (match_dup 0)))])
    (set (zero_extract:SI (match_dup 2)
                         (const_int 16)
-                        (ashift:SI (reg:SI 177)
-                                   (const_int 3)))
-       (match_operand:HI 1 "gpc_reg_operand" ""))
+                        (ashift:PSI (match_dup 3) (const_int 3)))
+       (match_operand:SI 1 "gpc_reg_operand" ""))
    (set (mem:SI (match_dup 0))
        (match_dup 2))]
   ""
-  "
-{ operands[1] = gen_lowpart (SImode, operands[1]);
-
-  if (reload_in_progress)
-    operands[2] = gen_rtx (REG, SImode, R_TAV);
-  else
-    operands[2] = gen_reg_rtx (SImode);
-}")
+  "")
 
 (define_expand "storehihww"
-  [(set (reg:SI 177)
-       (and:SI (match_operand:SI 0 "gpc_reg_operand" "")
-               (const_int 3)))
-   (set (match_dup 2)
+  [(set (match_operand:PSI 3 "register_operand" "")
+       (truncate:PSI (match_operand:SI 0 "gpc_reg_operand" "")))
+   (set (match_operand:SI 2 "gpc_reg_operand" "")
        (ior:SI (and:SI (not:SI (ashift:SI (const_int 65535)
-                                          (ashift:SI (reg:SI 177)
-                                                     (const_int 3))))
-                       (match_operand:HI 1 "gpc_reg_operand" ""))
-               (ashift:SI (and:SI (match_dup 1)
-                                  (const_int 65535))
-                          (ashift:SI (reg:SI 177)
-                                     (const_int 3)))))
+                                          (ashift:PSI (match_dup 3)
+                                                      (const_int 3))))
+                       (match_operand:SI 1 "gpc_reg_operand" ""))
+               (ashift:SI (zero_extend:SI (match_dup 4))
+                          (ashift:PSI (match_dup 3) (const_int 3)))))
    (set (mem:SI (and:SI (match_dup 0)
                        (const_int -3)))
        (match_dup 2))]
   ""
   "
-{ operands[1] = gen_lowpart (SImode, operands[1]);
-
-  if (reload_in_progress)
-    operands[2] = gen_rtx (REG, SImode, R_TAV);
-  else
-    operands[2] = gen_reg_rtx (SImode);
-}")
+{ operands[4] = gen_lowpart (HImode, operands[1]); }")
 
 (define_expand "movhi"
   [(set (match_operand:HI 0 "general_operand" "")
        operands[1] = copy_to_mode_reg (HImode, operands[1]);
       if (! TARGET_DW_ENABLE)
        {
+         rtx general = gen_reg_rtx (SImode);
+         rtx bp = gen_reg_rtx (PSImode);
+
          if (TARGET_BYTE_WRITES)
-           emit_insn (gen_storehihww (XEXP (operands[0], 0), operands[1]));
+           emit_insn (gen_storehihww (XEXP (operands[0], 0),
+                                      gen_lowpart (SImode, operands[1]),
+                                      general, bp));
          else
-           emit_insn (gen_storehinhww (XEXP (operands[0], 0), operands[1]));
+           emit_insn (gen_storehinhww (XEXP (operands[0], 0),
+                                       gen_lowpart (SImode, operands[1]),
+                                       general, bp));
          DONE;
        }
     }
     {
       if (! TARGET_DW_ENABLE)
        {
-         emit_insn (gen_loadhi (XEXP (operands[1], 0), operands[0]));
+         rtx general = gen_reg_rtx (SImode);
+         rtx bp = gen_reg_rtx (PSImode);
+
+         emit_insn (gen_loadqi (gen_lowpart (SImode, operands[0]),
+                                XEXP (operands[1], 0), general, bp));
          DONE;
        }
     }
 }")
+
+(define_expand "reload_inhi"
+  [(parallel [(match_operand:SI 0 "register_operand" "=r")
+             (match_operand:SI 1 "reload_memory_operand" "m")
+             (match_operand:PSI 2 "register_operand" "=b")])]
+  "! TARGET_DW_ENABLE"
+  "
+{ emit_insn (gen_loadhi (gen_lowpart (SImode, operands[0]),
+                        a29k_get_reloaded_address (operands[1]),
+                        gen_rtx (REG, SImode, R_TAV),
+                        operands[2]));
+  DONE;
+}")
+
+(define_expand "reload_outhi"
+  [(parallel [(match_operand:SI 0 "reload_memory_operand" "=m")
+             (match_operand:SI 1 "register_operand" "m")
+             (match_operand:PSI 2 "register_operand" "=b")])]
+  "! TARGET_DW_ENABLE"
+  "
+{ if (TARGET_BYTE_WRITES)
+    emit_insn (gen_storehihww (a29k_get_reloaded_address (operands[0]),
+                              gen_lowpart (SImode, operands[1]),
+                              gen_rtx (REG, SImode, R_TAV),
+                              operands[2]));
+  else
+    emit_insn (gen_storehinhww (a29k_get_reloaded_address (operands[0]),
+                               gen_lowpart (SImode, operands[1]),
+                               gen_rtx (REG, SImode, R_TAV),
+                               operands[2]));
+  DONE;
+}")
 \f
-;; Subroutines to load/store bytes.  Use TAV (gr121) as scratch.
+;; Subroutines to load/store bytes.  Operands 0 and 1 are the output and
+;; input, respectively, except that the address is passed for a MEM instead 
+;; of the MEM itself and the short item is passed in QImode.
+;;
+;; Operand 2 is a scratch general register and operand 3 is a scratch register
+;; used for BP.  When called before reload, pseudos are passed for both
+;; operands.  During reload, R_TAV is used for the general register, and
+;; a reload register of class BR_REGS (R_VP) for BP.
+;;
+;; We have two versions of the store operations, for when byte writes are
+;; supported and when they are not.
 (define_expand "loadqi"
-  [(parallel [(set (match_dup 2)
-                  (mem:SI (and:SI (match_operand:SI 0 "gpc_reg_operand" "")
+  [(parallel [(set (match_operand:SI 2 "gpc_reg_operand" "")
+                  (mem:SI (and:SI (match_operand:SI 1 "gpc_reg_operand" "")
                                   (const_int -4))))
-             (set (reg:SI 177)
-                  (and:SI (match_dup 0)
-                          (const_int 3)))])
-   (set (match_operand:QI 1 "gpc_reg_operand" "")
+             (set (match_operand:PSI 3 "register_operand" "")
+                  (truncate:PSI (match_dup 1)))])
+   (set (match_operand:SI 0 "gpc_reg_operand" "")
        (zero_extract:SI (match_dup 2)
                         (const_int 8)
-                        (ashift:SI (reg:SI 177)
-                                   (const_int 3))))]
+                        (ashift:PSI (match_dup 3) (const_int 3))))]
   ""
-  "
-{ operands[1] = gen_lowpart (SImode, operands[1]);
-
-  if (reload_in_progress)
-    operands[2] = gen_rtx (REG, SImode, R_TAV);
-  else
-    operands[2] = gen_reg_rtx (SImode);
-}")
+  "")
 
 (define_expand "storeqinhww"
-  [(parallel [(set (match_dup 2)
+  [(parallel [(set (match_operand:SI 2 "gpc_reg_operand" "")
                   (mem:SI (and:SI (match_operand:SI 0 "gpc_reg_operand" "")
                                   (const_int -4))))
-             (set (reg:SI 177)
-                  (and:SI (match_dup 0)
-                          (const_int 3)))])
+             (set (match_operand:PSI 3 "register_operand" "")
+                  (truncate:PSI (match_dup 0)))])
    (set (zero_extract:SI (match_dup 2)
                         (const_int 8)
-                        (ashift:SI (reg:SI 177)
-                                   (const_int 3)))
-       (match_operand:QI 1 "gpc_reg_operand" ""))
+                        (ashift:PSI (match_dup 3)
+                                    (const_int 3)))
+       (match_operand:SI 1 "gpc_reg_operand" ""))
    (set (mem:SI (match_dup 0))
        (match_dup 2))]
   ""
-  "
-{ operands[1] = gen_lowpart (SImode, operands[1]);
-
-  if (reload_in_progress)
-    operands[2] = gen_rtx (REG, SImode, R_TAV);
-  else
-    operands[2] = gen_reg_rtx (SImode);
-}")
+  "")
 
 (define_expand "storeqihww"
-  [(set (reg:SI 177)
-       (and:SI (match_operand:SI 0 "gpc_reg_operand" "")
-               (const_int 3)))
-   (set (match_dup 2)
+  [(set (match_operand:PSI 3 "register_operand" "")
+       (truncate:PSI (match_operand:SI 0 "gpc_reg_operand" "")))
+   (set (match_operand:SI 2 "gpc_reg_operand" "")
        (ior:SI (and:SI (not:SI (ashift:SI (const_int 255)
-                                          (ashift:SI (reg:SI 177)
-                                                     (const_int 3))))
-                       (match_operand:HI 1 "gpc_reg_operand" ""))
-               (ashift:SI (and:SI (match_dup 1)
-                                  (const_int 255))
-                          (ashift:SI (reg:SI 177)
-                                     (const_int 3)))))
+                                          (ashift:PSI (match_dup 3)
+                                                      (const_int 3))))
+                       (match_operand:SI 1 "gpc_reg_operand" ""))
+               (ashift:SI (zero_extend:SI (match_dup 4))
+                          (ashift:PSI (match_dup 3)
+                                      (const_int 3)))))
    (set (mem:SI (and:SI (match_dup 0)
                        (const_int -4)))
        (match_dup 2))]
   ""
   "
-{ operands[1] = gen_lowpart (SImode, operands[1]);
-
-  if (reload_in_progress)
-    operands[2] = gen_rtx (REG, SImode, R_TAV);
-  else
-    operands[2] = gen_reg_rtx (SImode);
-}")
+{ operands[4] = gen_lowpart (QImode, operands[1]); }")
 \f
 (define_expand "movqi"
   [(set (match_operand:QI 0 "general_operand" "")
        operands[1] = copy_to_mode_reg (QImode, operands[1]);
       if (! TARGET_DW_ENABLE)
        {
+         rtx general = gen_reg_rtx (SImode);
+         rtx bp = gen_reg_rtx (PSImode);
+
          if (TARGET_BYTE_WRITES)
-           emit_insn (gen_storeqihww (XEXP (operands[0], 0), operands[1]));
+           emit_insn (gen_storeqihww (XEXP (operands[0], 0),
+                                      gen_lowpart (SImode, operands[1]),
+                                      general, bp));
          else
-           emit_insn (gen_storeqinhww (XEXP (operands[0], 0), operands[1]));
+           emit_insn (gen_storeqinhww (XEXP (operands[0], 0),
+                                       gen_lowpart (SImode, operands[1]),
+                                       general, bp));
          DONE;
        }
     }
     {
       if (! TARGET_DW_ENABLE)
        {
-         emit_insn (gen_loadqi (XEXP (operands[1], 0), operands[0]));
+         rtx general = gen_reg_rtx (SImode);
+         rtx bp = gen_reg_rtx (PSImode);
+
+         emit_insn (gen_loadqi (gen_lowpart (SImode, operands[0]),
+                                XEXP (operands[1], 0), general, bp));
          DONE;
        }
     }
 }")
+
+(define_expand "reload_inqi"
+  [(parallel [(match_operand:SI 0 "register_operand" "=r")
+             (match_operand:SI 1 "reload_memory_operand" "m")
+             (match_operand:PSI 2 "register_operand" "=b")])]
+  "! TARGET_DW_ENABLE"
+  "
+{ emit_insn (gen_loadqi (gen_lowpart (SImode, operands[0]),
+                        a29k_get_reloaded_address (operands[1]),
+                        gen_rtx (REG, SImode, R_TAV),
+                        operands[2]));
+  DONE;
+}")
+
+(define_expand "reload_outqi"
+  [(parallel [(match_operand:SI 0 "reload_memory_operand" "=m")
+             (match_operand:SI 1 "register_operand" "m")
+             (match_operand:PSI 2 "register_operand" "=b")])]
+  "! TARGET_DW_ENABLE"
+  "
+{ if (TARGET_BYTE_WRITES)
+    emit_insn (gen_storeqihww (a29k_get_reloaded_address (operands[0]),
+                              gen_lowpart (SImode, operands[1]),
+                              gen_rtx (REG, SImode, R_TAV),
+                              operands[2]));
+  else
+    emit_insn (gen_storeqinhww (a29k_get_reloaded_address (operands[0]),
+                               gen_lowpart (SImode, operands[1]),
+                               gen_rtx (REG, SImode, R_TAV),
+                               operands[2]));
+  DONE;
+}")
 \f
 ;; Now the actual insns used to move data around.  We include here the
 ;; DEFINE_SPLITs that may be needed.  In some cases these will be
 }")
 
 (define_insn ""
-  [(set (match_operand:DF 0 "out_operand" "=r,r,r,m")
+  [(set (match_operand:DF 0 "out_operand" "=?r,?r,r,m")
        (match_operand:DF 1 "in_operand" "rE,F,m,r"))
-   (clobber (reg:SI 179))]
+   (clobber (match_scratch:PSI 2 "=X,X,&c,&c"))]
   "(gpc_reg_operand (operands[0], DFmode)
     || gpc_reg_operand (operands[1], DFmode))
    && ! TARGET_29050"
   [(set_attr "type" "multi")])
 
 (define_insn ""
-  [(set (match_operand:DF 0 "out_operand" "=r,r,&r,m,*a,r")
+  [(set (match_operand:DF 0 "out_operand" "=?r,?r,&r,m,?*a,?r")
        (match_operand:DF 1 "in_operand" "rE,F,m,r,r,*a"))
-   (clobber (reg:SI 179))]
+   (clobber (match_scratch:PSI 2 "=X,X,&c,&c,X,X"))]
   "(gpc_reg_operand (operands[0], DFmode)
     || gpc_reg_operand (operands[1], DFmode))
    && TARGET_29050"
 (define_split
   [(set (match_operand:DF 0 "gpc_reg_operand" "")
        (match_operand:DF 1 "gpc_reg_or_float_constant_operand" ""))
-   (clobber (reg:SI 179))]
+   (clobber (match_scratch:PSI 2 ""))]
   "reload_completed"
-  [(set (match_dup 2) (match_dup 3))
-   (set (match_dup 4) (match_dup 5))]
+  [(set (match_dup 3) (match_dup 4))
+   (set (match_dup 5) (match_dup 6))]
   "
 { if (GET_CODE (operands[1]) == REG
       && REGNO (operands[0]) == REGNO (operands[1]) + 1)
     {
-      operands[2] = operand_subword (operands[0], 1, 1, DFmode);
-      operands[3] = operand_subword (operands[1], 1, 1, DFmode);
-      operands[4] = operand_subword (operands[0], 0, 1, DFmode);
-      operands[5] = operand_subword (operands[1], 0, 1, DFmode);
+      operands[3] = operand_subword (operands[0], 1, 1, DFmode);
+      operands[4] = operand_subword (operands[1], 1, 1, DFmode);
+      operands[5] = operand_subword (operands[0], 0, 1, DFmode);
+      operands[6] = operand_subword (operands[1], 0, 1, DFmode);
     }
   else
     {
-      operands[2] = operand_subword (operands[0], 0, 1, DFmode);
-      operands[3] = operand_subword (operands[1], 0, 1, DFmode);
-      operands[4] = operand_subword (operands[0], 1, 1, DFmode);
-      operands[5] = operand_subword (operands[1], 1, 1, DFmode);
+      operands[3] = operand_subword (operands[0], 0, 1, DFmode);
+      operands[4] = operand_subword (operands[1], 0, 1, DFmode);
+      operands[5] = operand_subword (operands[0], 1, 1, DFmode);
+      operands[6] = operand_subword (operands[1], 1, 1, DFmode);
     }
 
-  if (operands[2] == 0 || operands[3] == 0
-      || operands[4] == 0 || operands[5] == 0)
+  if (operands[3] == 0 || operands[4] == 0
+      || operands[5] == 0 || operands[6] == 0)
     FAIL;
 }")
 
 (define_split
   [(set (match_operand:DF 0 "out_operand" "")
        (match_operand:DF 1 "in_operand" ""))
-   (clobber (reg:SI 179))]
+   (clobber (reg:PSI 179))]
   "TARGET_NO_STOREM_BUG
    && (memory_operand (operands[0], DFmode)
        || memory_operand (operands[1], DFmode))"
-  [(set (reg:SI 179) (const_int 1))
+  [(set (reg:PSI 179) (const_int 1))
    (parallel [(set (match_dup 0) (match_dup 1))
-             (use (reg:SI 179))
-             (clobber (reg:SI 179))])]
+             (use (reg:PSI 179))
+             (clobber (reg:PSI 179))])]
   "")
 
 ;; DI move is similar to DF move.
 (define_insn ""
-  [(set (match_operand:DI 0 "out_operand" "=r,r,m")
+  [(set (match_operand:DI 0 "out_operand" "=?r,r,m")
        (match_operand:DI 1 "in_operand" "rn,m,r"))
-   (clobber (reg:SI 179))]
+   (clobber (match_scratch:PSI 2 "=X,&c,&c"))]
   "(gpc_reg_operand (operands[0], DImode)
      || gpc_reg_operand (operands[1], DImode))
    && ! TARGET_29050"
   [(set_attr "type" "multi")])
 
 (define_insn ""
-  [(set (match_operand:DI 0 "out_operand" "=r,&r,m")
+  [(set (match_operand:DI 0 "out_operand" "=?r,&r,m")
        (match_operand:DI 1 "in_operand" "rn,m,r"))
-   (clobber (reg:SI 179))]
+   (clobber (match_scratch:PSI 2 "=X,&c,&c"))]
   "(gpc_reg_operand (operands[0], DImode)
      || gpc_reg_operand (operands[1], DImode))
    && TARGET_29050"
 (define_split
   [(set (match_operand:DI 0 "gpc_reg_operand" "")
        (match_operand:DI 1 "gpc_reg_or_integer_constant_operand" ""))
-   (clobber (reg:SI 179))]
+   (clobber (match_scratch:PSI 2 ""))]
   "reload_completed"
-  [(set (match_dup 2) (match_dup 3))
-   (set (match_dup 4) (match_dup 5))]
+  [(set (match_dup 3) (match_dup 4))
+   (set (match_dup 5) (match_dup 6))]
   "
 { if (GET_CODE (operands[1]) == REG
       && REGNO (operands[0]) == REGNO (operands[1]) + 1)
     {
-      operands[2] = operand_subword (operands[0], 1, 1, DImode);
-      operands[3] = operand_subword (operands[1], 1, 1, DImode);
-      operands[4] = operand_subword (operands[0], 0, 1, DImode);
-      operands[5] = operand_subword (operands[1], 0, 1, DImode);
+      operands[3] = operand_subword (operands[0], 1, 1, DImode);
+      operands[4] = operand_subword (operands[1], 1, 1, DImode);
+      operands[5] = operand_subword (operands[0], 0, 1, DImode);
+      operands[6] = operand_subword (operands[1], 0, 1, DImode);
     }
   else
     {
-      operands[2] = operand_subword (operands[0], 0, 1, DImode);
-      operands[3] = operand_subword (operands[1], 0, 1, DImode);
-      operands[4] = operand_subword (operands[0], 1, 1, DImode);
-      operands[5] = operand_subword (operands[1], 1, 1, DImode);
+      operands[3] = operand_subword (operands[0], 0, 1, DImode);
+      operands[4] = operand_subword (operands[1], 0, 1, DImode);
+      operands[5] = operand_subword (operands[0], 1, 1, DImode);
+      operands[6] = operand_subword (operands[1], 1, 1, DImode);
     }
 }")
 
 (define_split
   [(set (match_operand:DI 0 "out_operand" "")
        (match_operand:DI 1 "in_operand" ""))
-   (clobber (reg:SI 179))]
+   (clobber (reg:PSI 179))]
   "TARGET_NO_STOREM_BUG
    && (memory_operand (operands[0], DImode)
        || memory_operand (operands[1], DImode))"
-  [(set (reg:SI 179) (const_int 1))
+  [(set (reg:PSI 179) (const_int 1))
    (parallel [(set (match_dup 0) (match_dup 1))
-             (use (reg:SI 179))
-             (clobber (reg:SI 179))])]
+             (use (reg:PSI 179))
+             (clobber (reg:PSI 179))])]
   "")
 
 ;; TImode moves are very similar to DImode moves, except that we can't
 ;; have constants.
 (define_insn ""
-  [(set (match_operand:TI 0 "out_operand" "=r,r,m")
+  [(set (match_operand:TI 0 "out_operand" "=?r,r,m")
        (match_operand:TI 1 "in_operand" "r,m,r"))
-   (clobber (reg:SI 179))]
+   (clobber (match_scratch:PSI 2 "=X,&c,&c"))]
   "(gpc_reg_operand (operands[0], TImode)
     || gpc_reg_operand (operands[1], TImode))
    && ! TARGET_29050"
   [(set_attr "type" "multi,multi,multi")])
 
 (define_insn ""
-  [(set (match_operand:TI 0 "out_operand" "=r,&r,m")
+  [(set (match_operand:TI 0 "out_operand" "=?r,&r,m")
        (match_operand:TI 1 "in_operand" "r,m,r"))
-   (clobber (reg:SI 179))]
+   (clobber (match_scratch:PSI 2 "=X,&c,&c"))]
   "(gpc_reg_operand (operands[0], TImode)
     || gpc_reg_operand (operands[1], TImode))
    && TARGET_29050"
 (define_split
   [(set (match_operand:TI 0 "gpc_reg_operand" "")
        (match_operand:TI 1 "gpc_reg_operand" ""))
-   (clobber (reg:SI 179))]
+   (clobber (match_scratch:PSI 2 ""))]
   "reload_completed"
-  [(set (match_dup 2) (match_dup 3))
-   (set (match_dup 4) (match_dup 5))
-   (set (match_dup 6) (match_dup 7))
-   (set (match_dup 8) (match_dup 9))]
+  [(set (match_dup 3) (match_dup 4))
+   (set (match_dup 5) (match_dup 6))
+   (set (match_dup 7) (match_dup 8))
+   (set (match_dup 9) (match_dup 10))]
   "
 {
   if (REGNO (operands[0]) >= REGNO (operands[1]) + 1
       && REGNO (operands[0]) <= REGNO (operands[1]) + 3)
     {
-      operands[2] = gen_rtx (REG, SImode, REGNO (operands[0]) + 3);
-      operands[3] = gen_rtx (REG, SImode, REGNO (operands[1]) + 3);
-      operands[4] = gen_rtx (REG, SImode, REGNO (operands[0]) + 2);
-      operands[5] = gen_rtx (REG, SImode, REGNO (operands[1]) + 2);
-      operands[6] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
-      operands[7] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
-      operands[8] = gen_rtx (REG, SImode, REGNO (operands[0]));
-      operands[9] = gen_rtx (REG, SImode, REGNO (operands[1]));
+      operands[3] = gen_rtx (REG, SImode, REGNO (operands[0]) + 3);
+      operands[4] = gen_rtx (REG, SImode, REGNO (operands[1]) + 3);
+      operands[5] = gen_rtx (REG, SImode, REGNO (operands[0]) + 2);
+      operands[6] = gen_rtx (REG, SImode, REGNO (operands[1]) + 2);
+      operands[7] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
+      operands[8] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
+      operands[9] = gen_rtx (REG, SImode, REGNO (operands[0]));
+      operands[10] = gen_rtx (REG, SImode, REGNO (operands[1]));
     }
   else
     {
-      operands[2] = gen_rtx (REG, SImode, REGNO (operands[0]));
-      operands[3] = gen_rtx (REG, SImode, REGNO (operands[1]));
-      operands[4] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
-      operands[5] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
-      operands[6] = gen_rtx (REG, SImode, REGNO (operands[0]) + 2);
-      operands[7] = gen_rtx (REG, SImode, REGNO (operands[1]) + 2);
-      operands[8] = gen_rtx (REG, SImode, REGNO (operands[0]) + 3);
-      operands[9] = gen_rtx (REG, SImode, REGNO (operands[1]) + 3); 
+      operands[3] = gen_rtx (REG, SImode, REGNO (operands[0]));
+      operands[4] = gen_rtx (REG, SImode, REGNO (operands[1]));
+      operands[5] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
+      operands[6] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
+      operands[7] = gen_rtx (REG, SImode, REGNO (operands[0]) + 2);
+      operands[8] = gen_rtx (REG, SImode, REGNO (operands[1]) + 2);
+      operands[9] = gen_rtx (REG, SImode, REGNO (operands[0]) + 3);
+      operands[10] = gen_rtx (REG, SImode, REGNO (operands[1]) + 3); 
     }
 }")
 
 (define_split
   [(set (match_operand:TI 0 "out_operand" "")
        (match_operand:TI 1 "in_operand" ""))
-   (clobber (reg:SI 179))]
+   (clobber (reg:PSI 179))]
   "TARGET_NO_STOREM_BUG
    && (memory_operand (operands[0], TImode)
        || memory_operand (operands[1], TImode))"
-  [(set (reg:SI 179) (const_int 1))
+  [(set (reg:PSI 179) (const_int 1))
    (parallel [(set (match_dup 0) (match_dup 1))
-             (use (reg:SI 179))
-             (clobber (reg:SI 179))])]
+             (use (reg:PSI 179))
+             (clobber (reg:PSI 179))])]
   "")
 
 (define_insn ""
    mtsrim %0,%1"
   [(set_attr "type" "misc,misc,misc,misc,multi,load,misc,store,misc,misc")])
 
+(define_insn ""
+  [(set (match_operand:PSI 0 "out_operand" "=*r,*r,*r,*r,m,h,h")
+        (match_operand:PSI 1 "in_operand" "r,i,m,h,r,r,J"))]
+  "(gpc_reg_operand (operands[0], PSImode)
+    || gpc_reg_operand (operands[1], PSImode)
+    || (spec_reg_operand (operands[0], PSImode)
+        && cint_16_operand (operands[1], PSImode)))"
+  "@
+   sll %0,%1,0
+   const %0,%1
+   load 0,0,%0,%1
+   mfsr %0,%1
+   store 0,0,%1,%0
+   mtsr %0,%1
+   mtsrim %0,%1"
+  [(set_attr "type" "misc,multi,load,misc,store,misc,misc")])
+
 (define_insn ""
   [(set (match_operand:HI 0 "out_operand" "=r,r,r,m,r,*h,*h")
         (match_operand:HI 1 "in_operand" "r,i,m,r,*h,r,i"))]
   "gpc_reg_operand (operands[0], HImode)
-   || gpc_reg_operand (operands[1], HImode)"
+   || gpc_reg_operand (operands[1], HImode)
+   || (spec_reg_operand (operands[0], HImode)
+       && cint_16_operand (operands[1], HImode))"
   "@
    sll %0,%1,0
    const %0,%1
   [(set (match_operand:QI 0 "out_operand" "=r,r,r,m,r,*h,*h")
         (match_operand:QI 1 "in_operand" "r,i,m,r,*h,r,i"))]
   "gpc_reg_operand (operands[0], QImode)
-   || gpc_reg_operand (operands[1], QImode)"
+   || gpc_reg_operand (operands[1], QImode)
+   || (spec_reg_operand (operands[0], HImode)
+       && cint_16_operand (operands[1], HImode))"
   "@
    sll %0,%1,0
    const %0,%1
 ;;
 ;; In other cases, handle similarly to SImode moves.
 ;;
-;; However, indicate that DI, TI, and DF moves (can) clobber CR (reg 179).
+;; However, indicate that DI, TI, and DF moves may clobber CR (reg 179).
 (define_expand "movdi"
   [(parallel [(set (match_operand:DI 0 "general_operand" "")
                   (match_operand:DI 1 "general_operand" ""))
-             (clobber (reg:SI 179))])]
+             (clobber (scratch:PSI))])]
   ""
   "
 {
 (define_expand "movdf"
   [(parallel [(set (match_operand:DF 0 "general_operand" "")
                   (match_operand:DF 1 "general_operand" ""))
-             (clobber (reg:SI 179))])]
+             (clobber (scratch:PSI))])]
   ""
   "
 { if (GET_CODE (operands[0]) == MEM)
 (define_expand "movti"
   [(parallel [(set (match_operand:TI 0 "general_operand" "")
                   (match_operand:TI 1 "general_operand" ""))
-             (clobber (reg:SI 179))])]
+             (clobber (scratch:PSI))])]
   ""
   "
 {
     }
 }")
 \f
+;; Here are the variants of the above for use during reload.
+
+(define_expand "reload_indf"
+  [(parallel [(set (match_operand:DF 0 "register_operand" "=r")
+                  (match_operand:DF 1 "reload_memory_operand" "m"))
+             (clobber (match_operand:PSI 2 "register_operand" "=&b"))])]
+  ""
+  "")
+
+(define_expand "reload_outdf"
+  [(parallel [(set (match_operand:DF 0 "reload_memory_operand" "=m")
+                  (match_operand:DF 1 "register_operand" "r"))
+             (clobber (match_operand:PSI 2 "register_operand" "=&b"))])]
+  ""
+  "")
+
+(define_expand "reload_indi"
+  [(parallel [(set (match_operand:DI 0 "register_operand" "=r")
+                  (match_operand:DI 1 "reload_memory_operand" "m"))
+             (clobber (match_operand:PSI 2 "register_operand" "=&b"))])]
+  ""
+  "")
+
+(define_expand "reload_outdi"
+  [(parallel [(set (match_operand:DI 0 "reload_memory_operand" "=m")
+                  (match_operand:DI 1 "register_operand" "r"))
+             (clobber (match_operand:PSI 2 "register_operand" "=&b"))])]
+  ""
+  "")
+
+(define_expand "reload_inti"
+  [(parallel [(set (match_operand:TI 0 "register_operand" "=r")
+                  (match_operand:TI 1 "reload_memory_operand" "m"))
+             (clobber (match_operand:PSI 2 "register_operand" "=&b"))])]
+  ""
+  "")
+
+(define_expand "reload_outti"
+  [(parallel [(set (match_operand:TI 0 "reload_memory_operand" "=m")
+                  (match_operand:TI 1 "register_operand" "r"))
+             (clobber (match_operand:PSI 2 "register_operand" "=&b"))])]
+  ""
+  "")
+\f
 ;; For compare operations, we simply store the comparison operands and
 ;; do nothing else.  The following branch or scc insn will output whatever
 ;; is needed.