OSDN Git Service

* decl2.c (is_late_template_attribute): Don't defer attribute
[pf3gnuchains/gcc-fork.git] / gcc / config / c4x / c4x.md
index 89fe2d0..364457d 100644 (file)
@@ -1,26 +1,25 @@
-;; Machine description for the TMS320C[34]x for GNU C compiler
+;; Machine description for the TMS320C[34]x for GCC
 ;; Copyright (C) 1994, 1995, 1996, 1997, 1998,
-;; 1999, 2000 Free Software Foundation, Inc.
+;; 1999, 2000, 2002, 2004, 2005, 2007 Free Software Foundation, Inc.
 
 ;; Contributed by Michael Hayes (m.hayes@elec.canterbury.ac.nz)
 ;;            and Herman Ten Brugge (Haj.Ten.Brugge@net.HCC.nl)
 
-;; 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 2, 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/>.
 
 ;
 ; TODO :
 ;        for QImode and Pmode, whether Pmode was QImode or PQImode.
 ;        For addresses we wouldn't have to have a clobber of the CC
 ;        associated with each insn and we could use MPYI in address
-;        calculations without having to synthesise a proper 32 bit multiply.
+;        calculations without having to synthesize a proper 32-bit multiply.
 
 ; Additional C30/C40 instructions not coded:
 ; CALLcond, IACK, IDLE, LDE, LDFI, LDII, LDM, NORM, RETIcond
-; ROLC, RORC, SIGI, STFI, STII, SUBC, SWI, TRAPcond
+; ROLC, RORC, SIGI, STFI, STII, SUBC, SWI
 
 ; Additional C40 instructions not coded:
-; LDEP, LDPE, LWRct, FRIEEE, TOIEEE, LAJcond, LATcond, RETIcondD
+; LDEP, LDPE, LWRct, LAJcond, RETIcondD
 
 ;
 ; C4x MODES
 ; L   unsigned 16-bit
 ; M   unsigned 8-bit  (C4x only)
 ; N   ones complement of unsigned 16-bit
-; O   16 bit high constant
+; O   16-bit high constant
 ; Q   ARx + 9-bit signed disp
 ; R   ARx + 5-bit unsigned disp  (C4x only)
 ; S   ARx + 0, 1, IRx disp
 ;  not for 'c'.
 
 ;  The 'f' constraint is only for float register operands---when 
-;  a register satisying the 'f' constraint is used as a dst operand,
+;  a register satisfying the 'f' constraint is used as a dst operand,
 ;  the CC gets clobbered (except for LDFcond).
 
-;  The ! in front of the 'b' constaint says to GCC to disparage the
+;  The ! in front of the 'b' constraint says to GCC to disparage the
 ;  use of this constraint.  The 'b' constraint applies only to the SP.
 
 ;  Note that we deal with the condition code CC like some of the RISC
 ;  delayed branch slots.
 
 ;  Since the C[34]x has many instructions that set the CC, we pay the
-;  price of having to explicity define which insns clobber the CC
+;  price of having to explicitly define which insns clobber the CC
 ;  (rather than using the macro NOTICE_UPDATE_CC). 
 
 ;  Note that many patterns say that the CC is clobbered when in fact
 ;  copied about, then we could store the CC in a pseudo register and
 ;  use constructs such as (clobber (match_scratch:CC N "&y,X")) to
 ;  indicate that the 'y' class (ST register) is clobbered for the
-;  first combination of operands, but not with the second.
+;  first combination of operands but not with the second.
 ;  I tried this approach for a while but reload got unhappy since I
 ;  didn't allow it to move the CC around.
 
 ;  Note that fundamental operations, such as moves, must not clobber the
-;  CC.  Thus movqi choses a move instruction that doesn't clobber the CC.
+;  CC.  Thus movqi chooses a move instruction that doesn't clobber the CC.
 ;  If GCC wants to combine a move with a compare, it is smart enough to
 ;  chose the move instruction that sets the CC.
 
 ;  a new spill register.
 
 ;  Note that the floating point representation of 0.0 on the C4x
-;  is 0x80000000 (-2147483648).  This value produces an warning
+;  is 0x80000000 (-2147483648).  This value produces a warning
 ;  message on 32-bit machines about the decimal constant being so large
 ;  that it is unsigned.
 
 ;        op3             fetch executed
 ; This means that we can allow any instruction in the last delay slot
 ; and only instructions which modify registers in the first two. 
-; lda can not be executed in the first delay slot 
-; and ldpk can not be executed in the first two delay slots.
+; lda cannot be executed in the first delay slot 
+; and ldpk cannot be executed in the first two delay slots.
 
 (define_attr "onlyreg" "false,true"
        (cond [(eq_attr "type" "unary,unarycc")
                (const_string "true")
                (const_string "false")))
 
+/* Disable ldp because the c4x contains a bug. The ldp insn modifies
+   the dp register when the insn is anulled or not.
+   Also disable autoincrement insns because of a silicon bug.  */
 (define_attr "in_annul_slot_3" "false,true"
-  (if_then_else (and (eq_attr "cpu" "c4x")
-                    (eq_attr "type" "!jump,call,rets,jmpc,db,dbc,repeat,repeat_top,laj,push,pop,multi"))
+  (if_then_else (and (and (eq_attr "cpu" "c4x")
+                         (eq_attr "type" "!jump,call,rets,jmpc,db,dbc,repeat,repeat_top,laj,push,pop,ldp,multi"))
+                    (eq_attr "onlyreg_nomod" "true"))
                (const_string "true")
                (const_string "false")))
 
 ;
 ; C4x UNSPEC NUMBERS
 ;
-;  1 BU/BUD
-;  2 RPTS
-;  3 LSH
-;  4 cmphi
-;  5 RCPF
-;  6 RND
-;  7 repeat block filler
-;  8 loadhf_int
-;  9 storehf_int
-; 10 RSQRF
-; 11 loadqf_int
-; 12 storeqf_int
-; 13 Conditional load on overflow
-; 22 rptb_init
-
-;
-; C4x FUNCTIONAL UNITS
-;
-; Define functional units for instruction scheduling to minimise
-; pipeline conflicts.
+(define_constants
+  [
+   (UNSPEC_BU                  1)
+   (UNSPEC_RPTS                        2)
+   (UNSPEC_LSH                 3)
+   (UNSPEC_CMPHI               4)
+   (UNSPEC_RCPF                        5)
+   (UNSPEC_RND                 6)
+   (UNSPEC_RPTB_FILL           7)
+   (UNSPEC_LOADHF_INT          8)
+   (UNSPEC_STOREHF_INT         9)
+   (UNSPEC_RSQRF               10)
+   (UNSPEC_LOADQF_INT          11)
+   (UNSPEC_STOREQF_INT         12)
+   (UNSPEC_LDIV                        13)
+   (UNSPEC_PUSH_ST             14)
+   (UNSPEC_POP_ST              15)
+   (UNSPEC_PUSH_DP             16)
+   (UNSPEC_POP_DP              17)
+   (UNSPEC_POPQI               18)
+   (UNSPEC_POPQF               19)
+   (UNSPEC_ANDN_ST             20)
+   (UNSPEC_RPTB_INIT           22)
+   (UNSPEC_TOIEEE              23)
+   (UNSPEC_FRIEEE              24)
+  ])
+
+;
+; C4x PIPELINE MODEL
 ;
 ; With the C3x, an external memory write (with no wait states) takes
 ; two cycles and an external memory read (with no wait states) takes
 ; one cycle.  However, an external read following an external write
 ; takes two cycles.  With internal memory, reads and writes take
 ; half a cycle.
-;
 ; When a C4x address register is loaded it will not be available for
 ; an extra machine cycle.  Calculating with a C4x address register
-; makes it unavailable for 2 machine cycles.  To notify GCC of these
-; pipeline delays, each of the auxiliary and index registers are declared
-; as separate functional units.
+; makes it unavailable for 2 machine cycles.
 ;
-; (define_function_unit NAME MULTIPLICITY SIMULTANEITY
-;                      TEST READY-DELAY ISSUE-DELAY [CONFLICT-LIST])
-;
-; MULTIPLICITY 1 (C4x has no independent identical function units)
-; SIMULTANEITY 0 (C4x is pipelined)
-; READY_DELAY  1 (Results usually ready after every cyle)
-; ISSUE_DELAY  1 (Can issue insns every cycle)
-
 ; Just some dummy definitions. The real work is done in c4x_adjust_cost.
 ; These are needed so the min/max READY_DELAY is known.
 
-(define_function_unit "dummy" 1 0 (const_int 0) 1 1)
-(define_function_unit "dummy" 1 0 (const_int 0) 2 1)
-(define_function_unit "dummy" 1 0 (const_int 0) 3 1)
-
-;(define_function_unit "ar0" 1 0
-;       (and (eq_attr "cpu" "c4x")
-;            (and (eq_attr "setar0" "1")
-;                 (eq_attr "usear0" "1")))
-;       3 1 )
-
-;(define_function_unit "ar0" 1 0
-;       (and (eq_attr "cpu" "c4x")
-;            (and (eq_attr "setlda_ar0" "1")
-;                 (eq_attr "usear0" "1")))
-;       2 1 )
-
-;(define_function_unit "ar0" 1 0
-;       (and (eq_attr "cpu" "c4x")
-;            (and (eq_attr "usear0" "1")
-;                 (eq_attr "readar0" "1")))
-;       2 1 )
+(define_insn_reservation "any_insn" 1 (const_int 1) "nothing")
+(define_insn_reservation "slowest_insn" 3 (const_int 0) "nothing")
 
 ; The attribute setar0 is set to 1 for insns where ar0 is a dst operand.
 ; Note that the attributes unarycc and binarycc do not apply
                                      (const_int 1) (const_int 0))]
              (const_int 0)))
 
-;(define_function_unit "ar1" 1 0
-;       (and (eq_attr "cpu" "c4x")
-;            (and (eq_attr "setar1" "1")
-;                 (eq_attr "usear1" "1")))
-;       3 1 )
-
-;(define_function_unit "ar1" 1 0
-;       (and (eq_attr "cpu" "c4x")
-;            (and (eq_attr "setlda_ar1" "1")
-;                 (eq_attr "usear1" "1")))
-;       2 1 )
-
-;(define_function_unit "ar1" 1 0
-;       (and (eq_attr "cpu" "c4x")
-;            (and (eq_attr "usear1" "1")
-;                 (eq_attr "readar1" "1")))
-;       2 1 )
-
 (define_attr "setar1" ""
        (cond [(eq_attr "type" "unary,binary")
                        (if_then_else (match_operand 0 "ar1_reg_operand" "")
                                      (const_int 1) (const_int 0))]
              (const_int 0)))
 
-;(define_function_unit "ar2" 1 0
-;       (and (eq_attr "cpu" "c4x")
-;            (and (eq_attr "setar2" "1")
-;                 (eq_attr "usear2" "1")))
-;       3 1 )
-
-;(define_function_unit "ar2" 1 0
-;       (and (eq_attr "cpu" "c4x")
-;            (and (eq_attr "setlda_ar2" "1")
-;                 (eq_attr "usear2" "1")))
-;       2 1 )
-
-;(define_function_unit "ar2" 1 0
-;       (and (eq_attr "cpu" "c4x")
-;            (and (eq_attr "usear2" "1")
-;                 (eq_attr "readar2" "1")))
-;       2 1 )
-
 (define_attr "setar2" ""
        (cond [(eq_attr "type" "unary,binary")
                        (if_then_else (match_operand 0 "ar2_reg_operand" "")
                                      (const_int 1) (const_int 0))]
              (const_int 0)))
 
-;(define_function_unit "ar3" 1 0
-;       (and (eq_attr "cpu" "c4x")
-;            (and (eq_attr "setar3" "1")
-;                 (eq_attr "usear3" "1")))
-;       3 1 )
-
-;(define_function_unit "ar3" 1 0
-;       (and (eq_attr "cpu" "c4x")
-;            (and (eq_attr "setlda_ar3" "1")
-;                 (eq_attr "usear3" "1")))
-;       2 1 )
-
-;(define_function_unit "ar3" 1 0
-;       (and (eq_attr "cpu" "c4x")
-;            (and (eq_attr "usear3" "1")
-;                 (eq_attr "readar3" "1")))
-;       2 1 )
-
 (define_attr "setar3" ""
        (cond [(eq_attr "type" "unary,binary")
                        (if_then_else (match_operand 0 "ar3_reg_operand" "")
                                      (const_int 1) (const_int 0))]
              (const_int 0)))
 
-;(define_function_unit "ar4" 1 0
-;       (and (eq_attr "cpu" "c4x")
-;            (and (eq_attr "setar4" "1")
-;                 (eq_attr "usear4" "1")))
-;       3 1 )
-
-;(define_function_unit "ar4" 1 0
-;       (and (eq_attr "cpu" "c4x")
-;            (and (eq_attr "setlda_ar4" "1")
-;                 (eq_attr "usear4" "1")))
-;       2 1 )
-
-;(define_function_unit "ar4" 1 0
-;       (and (eq_attr "cpu" "c4x")
-;            (and (eq_attr "usear4" "1")
-;                 (eq_attr "readar4" "1")))
-;       2 1 )
-
 (define_attr "setar4" ""
        (cond [(eq_attr "type" "unary,binary")
                        (if_then_else (match_operand 0 "ar4_reg_operand" "")
                                      (const_int 1) (const_int 0))]
              (const_int 0)))
 
-;(define_function_unit "ar5" 1 0
-;       (and (eq_attr "cpu" "c4x")
-;            (and (eq_attr "setar5" "1")
-;                 (eq_attr "usear5" "1")))
-;       3 1 )
-
-;(define_function_unit "ar5" 1 0
-;       (and (eq_attr "cpu" "c4x")
-;            (and (eq_attr "setlda_ar5" "1")
-;                 (eq_attr "usear5" "1")))
-;       2 1 )
-
-;(define_function_unit "ar5" 1 0
-;       (and (eq_attr "cpu" "c4x")
-;            (and (eq_attr "usear5" "1")
-;                 (eq_attr "readar5" "1")))
-;       2 1 )
-
 (define_attr "setar5" ""
        (cond [(eq_attr "type" "unary,binary")
                        (if_then_else (match_operand 0 "ar5_reg_operand" "")
                                      (const_int 1) (const_int 0))]
              (const_int 0)))
 
-;(define_function_unit "ar6" 1 0
-;       (and (eq_attr "cpu" "c4x")
-;            (and (eq_attr "setar6" "1")
-;                 (eq_attr "usear6" "1")))
-;       3 1 )
-
-;(define_function_unit "ar6" 1 0
-;       (and (eq_attr "cpu" "c4x")
-;            (and (eq_attr "setlda_ar6" "1")
-;                 (eq_attr "usear6" "1")))
-;       2 1 )
-
-;(define_function_unit "ar6" 1 0
-;       (and (eq_attr "cpu" "c4x")
-;            (and (eq_attr "usear6" "1")
-;                 (eq_attr "readar6" "1")))
-;       2 1 )
-
 (define_attr "setar6" ""
        (cond [(eq_attr "type" "unary,binary")
                        (if_then_else (match_operand 0 "ar6_reg_operand" "")
                                      (const_int 1) (const_int 0))]
              (const_int 0)))
 
-;(define_function_unit "ar7" 1 0
-;       (and (eq_attr "cpu" "c4x")
-;            (and (eq_attr "setar7" "1")
-;                 (eq_attr "usear7" "1")))
-;       3 1 )
-
-;(define_function_unit "ar7" 1 0
-;       (and (eq_attr "cpu" "c4x")
-;            (and (eq_attr "setlda_ar7" "1")
-;                 (eq_attr "usear7" "1")))
-;       2 1 )
-
-;(define_function_unit "ar7" 1 0
-;       (and (eq_attr "cpu" "c4x")
-;            (and (eq_attr "usear7" "1")
-;                 (eq_attr "readar7" "1")))
-;       2 1 )
-
 (define_attr "setar7" ""
        (cond [(eq_attr "type" "unary,binary")
                        (if_then_else (match_operand 0 "ar7_reg_operand" "")
                                      (const_int 1) (const_int 0))]
              (const_int 0)))
 
-;(define_function_unit "ir0" 1 0
-;       (and (eq_attr "cpu" "c4x")
-;            (and (eq_attr "setir0" "1")
-;                 (eq_attr "useir0" "1")))
-;       3 1 )
-
-;(define_function_unit "ir0" 1 0
-;       (and (eq_attr "cpu" "c4x")
-;            (and (eq_attr "setlda_ir0" "1")
-;                 (eq_attr "useir0" "1")))
-;       2 1 )
-
 (define_attr "setir0" ""
        (cond [(eq_attr "type" "unary,binary")
                        (if_then_else (match_operand 0 "ir0_reg_operand" "")
                                      (const_int 1) (const_int 0))]
              (const_int 0)))
 
-;(define_function_unit "ir1" 1 0
-;       (and (eq_attr "cpu" "c4x")
-;            (and (eq_attr "setir1" "1")
-;                 (eq_attr "useir1" "1")))
-;       3 1 )
-
-;(define_function_unit "ir1" 1 0
-;       (and (eq_attr "cpu" "c4x")
-;            (and (eq_attr "setlda_ir1" "1")
-;                 (eq_attr "useir1" "1")))
-;       2 1 )
-
 (define_attr "setir1" ""
        (cond [(eq_attr "type" "unary,binary")
                        (if_then_else (match_operand 0 "ir1_reg_operand" "")
                                      (const_int 1) (const_int 0))]
              (const_int 0)))
 
-; With the C3x, things are simpler, but slower, i.e. more pipeline conflicts :(
+; With the C3x, things are simpler but slower, i.e. more pipeline conflicts :(
 ; There are three functional groups:
 ; (1) AR0-AR7, IR0-IR1, BK
 ; (2) DP
 ; Let's ignore functional groups 2 and 3 for now, since they are not
 ; so important.
 
-;(define_function_unit "group1" 1 0
-;       (and (eq_attr "cpu" "c3x")
-;            (and (eq_attr "setgroup1" "1")
-;                 (eq_attr "usegroup1" "1")))
-;       3 1)
-
-;(define_function_unit "group1" 1 0
-;       (and (eq_attr "cpu" "c3x")
-;            (and (eq_attr "usegroup1" "1")
-;                 (eq_attr "readarx" "1")))
-;       2 1)
-
 (define_attr "setgroup1" ""
        (cond [(eq_attr "type" "lda,unary,binary")
                   (if_then_else (match_operand 0 "group1_reg_operand" "")
                             (const_int 1) (const_int 0))]
              (const_int 0)))
 
+(include "predicates.md")
 
 ;
 ; C4x INSN PATTERNS:
   "* return (TARGET_C3X) ? \"ldp\\t%A1\" : \"ldpk\\t%A1\";"
   [(set_attr "type" "ldp")])
 
+(define_insn "set_ldp_prologue"
+  [(set (match_operand:QI 0 "dp_reg_operand" "=z")
+        (high:QI (match_operand:QI 1 "" "")))]
+  "TARGET_SMALL && TARGET_PARANOID"
+  "* return (TARGET_C3X) ? \"ldp\\t@data_sec\" : \"ldpk\\t@data_sec\";"
+  [(set_attr "type" "ldp")])
+
 (define_insn "set_high"
   [(set (match_operand:QI 0 "std_reg_operand" "=c")
         (high:QI (match_operand:QI 1 "symbolic_address_operand" "")))]
   [(set_attr "type" "unary")])
 
 (define_insn "set_lo_sum"
-  [(set (match_operand:QI 0 "std_reg_operand" "=c")
+  [(set (match_operand:QI 0 "std_reg_operand" "+c")
         (lo_sum:QI (match_dup 0)
                    (match_operand:QI 1 "symbolic_address_operand" "")))]
   "! TARGET_TI"
 (define_split
   [(set (match_operand:QI 0 "std_reg_operand" "")
         (match_operand:QI 1 "symbolic_address_operand" ""))]
-  "! TARGET_C3X && ! TARGET_TI"
+  "reload_completed && ! TARGET_C3X && ! TARGET_TI"
   [(set (match_dup 0) (high:QI (match_dup 1)))
    (set (match_dup 0) (lo_sum:QI (match_dup 0) (match_dup 1)))]
   "")
 
 (define_split
   [(set (match_operand:QI 0 "reg_operand" "")
-       (match_operand:QI 1 "const_int_operand" ""))]
+       (match_operand:QI 1 "const_int_operand" ""))
+   (clobber (reg:QI 16))]
   "! TARGET_C3X
    && ! IS_INT16_CONST (INTVAL (operands[1]))
    && ! IS_HIGH_CONST (INTVAL (operands[1]))
    (set (match_dup 0) (ior:QI (match_dup 0) (match_dup 3)))]
   "
 {
-   operands[2] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[1]) & ~0xffff);
-   operands[3] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[1]) & 0xffff);
+   operands[2] = GEN_INT (INTVAL (operands[1]) & ~0xffff);
+   operands[3] = GEN_INT (INTVAL (operands[1]) & 0xffff);
 }")
 
 (define_split
   [(set (match_operand:QI 0 "reg_operand" "")
        (match_operand:QI 1 "const_int_operand" ""))]
+  "! TARGET_C3X
+   && ! IS_INT16_CONST (INTVAL (operands[1]))
+   && ! IS_HIGH_CONST (INTVAL (operands[1]))
+   && reload_completed
+   && std_reg_operand (operands[0], QImode)"
+  [(set (match_dup 0) (match_dup 2))
+   (set (match_dup 0) (ior:QI (match_dup 0) (match_dup 3)))]
+  "
+{
+   operands[2] = GEN_INT (INTVAL (operands[1]) & ~0xffff);
+   operands[3] = GEN_INT (INTVAL (operands[1]) & 0xffff);
+}")
+
+(define_split
+  [(set (match_operand:QI 0 "reg_operand" "")
+       (match_operand:QI 1 "const_int_operand" ""))
+   (clobber (reg:QI 16))]
   "TARGET_C3X && ! TARGET_SMALL
    && ! IS_INT16_CONST (INTVAL (operands[1]))
    && reload_completed
   "
 {
    /* Generate two's complement value of 16 MSBs.  */
-   operands[2] = gen_rtx (CONST_INT, VOIDmode,
-                         (((INTVAL (operands[1]) >> 16) & 0xffff)
+   operands[2] = GEN_INT ((((INTVAL (operands[1]) >> 16) & 0xffff)
                           - 0x8000) ^ ~0x7fff);
-   operands[3] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[1]) & 0xffff);
-   operands[4] = gen_rtx (CONST_INT, VOIDmode, 16);
+   operands[3] = GEN_INT (INTVAL (operands[1]) & 0xffff);
+   operands[4] = GEN_INT (16);
 }")
 
 (define_split
   [(set (match_operand:QI 0 "reg_operand" "")
        (match_operand:QI 1 "const_int_operand" ""))]
+  "TARGET_C3X && ! TARGET_SMALL
+   && ! IS_INT16_CONST (INTVAL (operands[1]))
+   && reload_completed
+   && std_reg_operand (operands[0], QImode)
+   && c4x_shiftable_constant (operands[1]) < 0"
+  [(set (match_dup 0) (match_dup 2))
+   (set (match_dup 0) (ashift:QI (match_dup 0) (match_dup 4)))
+   (set (match_dup 0) (ior:QI (match_dup 0) (match_dup 3)))]
+  "
+{
+   /* Generate two's complement value of 16 MSBs.  */
+   operands[2] = GEN_INT ((((INTVAL (operands[1]) >> 16) & 0xffff)
+                          - 0x8000) ^ ~0x7fff);
+   operands[3] = GEN_INT (INTVAL (operands[1]) & 0xffff);
+   operands[4] = GEN_INT (16);
+}")
+
+(define_split
+  [(set (match_operand:QI 0 "reg_operand" "")
+       (match_operand:QI 1 "const_int_operand" ""))
+   (clobber (reg:QI 16))]
   "TARGET_C3X
    && ! IS_INT16_CONST (INTVAL (operands[1]))
    && reload_completed
    /* Generate two's complement value of MSBs.  */
    int shift = c4x_shiftable_constant (operands[1]);
 
-   operands[2] = gen_rtx (CONST_INT, VOIDmode,
-                         (((INTVAL (operands[1]) >> shift) & 0xffff)
+   operands[2] = GEN_INT ((((INTVAL (operands[1]) >> shift) & 0xffff)
                           - 0x8000) ^ ~0x7fff);
-   operands[3] = gen_rtx (CONST_INT, VOIDmode, shift);
+   operands[3] = GEN_INT (shift);
 }")
 
 (define_split
   [(set (match_operand:QI 0 "reg_operand" "")
        (match_operand:QI 1 "const_int_operand" ""))]
+  "TARGET_C3X
+   && ! IS_INT16_CONST (INTVAL (operands[1]))
+   && reload_completed
+   && std_reg_operand (operands[0], QImode)
+   && c4x_shiftable_constant (operands[1]) >= 0"
+  [(set (match_dup 0) (match_dup 2))
+   (set (match_dup 0) (ashift:QI (match_dup 0) (match_dup 3)))]
+  "
+{
+   /* Generate two's complement value of MSBs.  */
+   int shift = c4x_shiftable_constant (operands[1]);
+
+   operands[2] = GEN_INT ((((INTVAL (operands[1]) >> shift) & 0xffff)
+                           - 0x8000) ^ ~0x7fff);
+   operands[3] = GEN_INT (shift);
+}")
+
+(define_split
+  [(set (match_operand:QI 0 "reg_operand" "")
+       (match_operand:QI 1 "const_int_operand" ""))
+   (clobber (reg:QI 16))]
   "! TARGET_SMALL
    && ! IS_INT16_CONST (INTVAL (operands[1]))
    && ! IS_HIGH_CONST (INTVAL (operands[1]))
 (define_split
   [(set (match_operand:QI 0 "reg_operand" "")
        (match_operand:QI 1 "const_int_operand" ""))]
+  "! TARGET_SMALL
+   && ! IS_INT16_CONST (INTVAL (operands[1]))
+   && ! IS_HIGH_CONST (INTVAL (operands[1]))
+   && reload_completed
+   && ! std_reg_operand (operands[0], QImode)"
+  [(set (match_dup 2) (high:QI (match_dup 3)))
+   (set (match_dup 0) (match_dup 4))
+   (use (match_dup 1))]
+  "
+{
+   rtx dp_reg = gen_rtx_REG (Pmode, DP_REGNO);
+   operands[2] = dp_reg;
+   operands[3] = force_const_mem (Pmode, operands[1]);
+   operands[4] = change_address (operands[3], QImode,
+                                gen_rtx_LO_SUM (Pmode, dp_reg,
+                                                 XEXP (operands[3], 0)));
+   operands[3] = XEXP (operands[3], 0);
+}")
+
+(define_split
+  [(set (match_operand:QI 0 "reg_operand" "")
+       (match_operand:QI 1 "const_int_operand" ""))
+   (clobber (reg:QI 16))]
+  "TARGET_SMALL
+   && ! IS_INT16_CONST (INTVAL (operands[1]))
+   && ! IS_HIGH_CONST (INTVAL (operands[1]))
+   && reload_completed
+   && ((TARGET_C3X && c4x_shiftable_constant (operands[1]) < 0)
+       || ! std_reg_operand (operands[0], QImode))"
+  [(set (match_dup 0) (match_dup 2))
+   (use (match_dup 1))]
+  "
+{
+   rtx dp_reg = gen_rtx_REG (Pmode, DP_REGNO);
+   operands[2] = force_const_mem (Pmode, operands[1]);
+   operands[2] = change_address (operands[2], QImode,
+                                gen_rtx_LO_SUM (Pmode, dp_reg,
+                                                 XEXP (operands[2], 0)));
+}")
+
+(define_split
+  [(set (match_operand:QI 0 "reg_operand" "")
+       (match_operand:QI 1 "const_int_operand" ""))]
   "TARGET_SMALL
    && ! IS_INT16_CONST (INTVAL (operands[1]))
    && ! IS_HIGH_CONST (INTVAL (operands[1]))
 
 (define_split
   [(set (match_operand:HI 0 "reg_operand" "")
-       (match_operand:HI 1 "const_int_operand" ""))]
+       (match_operand:HI 1 "const_int_operand" ""))
+   (clobber (reg:QI 16))]
   "reload_completed"
   [(set (match_dup 2) (match_dup 4))
    (set (match_dup 3) (match_dup 5))]
   [(set (match_operand:QI 0 "std_reg_operand" "")
         (match_operand:QI 1 "symbolic_address_operand" ""))
    (clobber (reg:QI 16))]
-  "! TARGET_C3X && ! TARGET_TI"
+  "reload_completed && ! TARGET_C3X && ! TARGET_TI"
   [(set (match_dup 0) (high:QI (match_dup 1)))
    (set (match_dup 0) (lo_sum:QI (match_dup 0) (match_dup 1)))]
   "")
   [(set (match_operand:QI 0 "reg_operand" "")
         (match_operand:QI 1 "symbolic_address_operand" ""))
    (clobber (reg:QI 16))]
-  "! TARGET_SMALL 
-   && (TARGET_C3X || TARGET_TI
-       || (reload_completed
-           && ! std_reg_operand (operands[0], QImode)))"
+  "reload_completed
+   && ! TARGET_SMALL 
+   && (TARGET_C3X || TARGET_TI || ! std_reg_operand (operands[0], QImode))"
   [(set (match_dup 2) (high:QI (match_dup 3)))
    (set (match_dup 0) (match_dup 4))
    (use (match_dup 1))]
   [(set (match_operand:QI 0 "reg_operand" "")
         (match_operand:QI 1 "symbolic_address_operand" ""))
    (clobber (reg:QI 16))]
-  "TARGET_SMALL
-   && (TARGET_C3X || TARGET_TI
-       || (reload_completed
-           && ! std_reg_operand (operands[0], QImode)))"
+  "reload_completed
+   && TARGET_SMALL
+   && (TARGET_C3X || TARGET_TI || ! std_reg_operand (operands[0], QImode))"
   [(set (match_dup 0) (match_dup 2))
    (use (match_dup 1))]
   "
 
 (define_insn "loadhi_big_constant"
   [(set (match_operand:HI 0 "reg_operand" "=c*d")
-        (match_operand:HI 1 "const_int_operand" ""))]
+        (match_operand:HI 1 "const_int_operand" ""))
+   (clobber (reg:QI 16))]
   ""
   "#"
   [(set_attr "type" "multi")])
 
 (define_insn "loadqi_big_constant"
   [(set (match_operand:QI 0 "reg_operand" "=c*d")
-        (match_operand:QI 1 "const_int_operand" ""))]
+        (match_operand:QI 1 "const_int_operand" ""))
+   (clobber (reg:QI 16))]
   "! IS_INT16_CONST (INTVAL (operands[1]))
    && ! IS_HIGH_CONST (INTVAL (operands[1]))"
   "#"
    (set (reg:CC 21)
         (compare:CC (match_dup 0) (const_int 0)))]
   ""
-  "@
-  ldi\\t%1,%0"
+  "ldi\\t%1,%0"
   [(set_attr "type" "unarycc")
    (set_attr "data" "int16")])
 
    (set (match_operand:QI 0 "ext_reg_operand" "=d")
         (match_dup 1))]
   ""
-  "@
-  ldi\\t%1,%0"
+  "ldi\\t%1,%0"
   [(set_attr "type" "unarycc")
    (set_attr "data" "int16")])
 
 ;  If one of the operands is not a register, then we should
 ;  emit two insns, using a scratch register.  This will produce
 ;  better code in loops if the source operand is invariant, since
-;  the source reload can be optimised out.  During reload we cannot
+;  the source reload can be optimized out.  During reload we cannot
 ;  use change_address or force_reg which will allocate new pseudo regs.
 
 ;  Unlike most other insns, the move insns can't be split with
 }")
 
 
+; As far as GCC is concerned, the moves are performed in parallel
+; thus it must be convinced that there is no aliasing.
+; It also assumes that the input operands are simultaneously loaded
+; and then the output operands are simultaneously stored.
+; With the C4x, if there are parallel stores to the same address
+; both stores are executed.
+; If there is a parallel load and store to the same address,
+; the load is performed first.
+; The problem with this pattern is that reload can spoil
+; the show when it eliminates a reference to the frame pointer.
+; This can invalidate the memory addressing mode, i.e., when
+; the displacement is greater than 1.
 (define_insn "movqi_parallel"
   [(set (match_operand:QI 0 "parallel_operand" "=q,S<>!V,q,S<>!V")
         (match_operand:QI 1 "parallel_operand" "S<>!V,q,S<>!V,q"))
 ;
 ; PUSH/POP
 ;
-(define_insn "*pushqi"
+(define_insn "pushqi"
   [(set (mem:QI (pre_inc:QI (reg:QI 20)))
         (match_operand:QI 0 "reg_operand" "r"))]
   ""
   "push\\t%0"
   [(set_attr "type" "push")])
 
-(define_insn "*popqi"
+(define_insn "push_st"
+  [(set (mem:QI (pre_inc:QI (reg:QI 20)))
+        (unspec:QI [(reg:QI 21)] UNSPEC_PUSH_ST))
+   (use (reg:QI 21))]
+  ""
+  "push\\tst"
+  [(set_attr "type" "push")])
+
+(define_insn "push_dp"
+  [(set (mem:QI (pre_inc:QI (reg:QI 20))) 
+        (unspec:QI [(reg:QI 16)] UNSPEC_PUSH_DP))
+   (use (reg:QI 16))]
+  ""
+  "push\\tdp"
+  [(set_attr "type" "push")])
+
+(define_insn "popqi"
   [(set (match_operand:QI 0 "reg_operand" "=r")
         (mem:QI (post_dec:QI (reg:QI 20))))
    (clobber (reg:CC 21))]
   "pop\\t%0"
   [(set_attr "type" "pop")])
 
+(define_insn "pop_st"
+  [(set (unspec:QI [(reg:QI 21)] UNSPEC_POP_ST) 
+        (mem:QI (post_dec:QI (reg:QI 20))))
+   (clobber (reg:CC 21))]
+  ""
+  "pop\\tst"
+  [(set_attr "type" "pop")])
+
+(define_insn "pop_dp"
+  [(set (unspec:QI [(reg:QI 16)] UNSPEC_POP_DP)
+        (mem:QI (post_dec:QI (reg:QI 20))))
+   (clobber (reg:CC 16))]
+  ""
+  "pop\\tdp"
+  [(set_attr "type" "pop")])
+
+(define_insn "popqi_unspec"
+  [(set (unspec:QI [(match_operand:QI 0 "reg_operand" "=r")] UNSPEC_POPQI)
+        (mem:QI (post_dec:QI (reg:QI 20))))
+   (clobber (match_dup 0))
+   (clobber (reg:CC 21))]
+  ""
+  "pop\\t%0"
+  [(set_attr "type" "pop")])
+
 ;
 ; ABSI
 ;
       DONE;
    }")
 
+; This pattern is required primarily for manipulating the stack pointer
+; where GCC doesn't expect CC to be clobbered or for calculating
+; addresses during reload.  Since this is a more specific pattern
+; it needs to go first (otherwise we get into problems trying to decide
+; to add clobbers).
+(define_insn "addqi3_noclobber"
+  [(set (match_operand:QI 0 "std_reg_operand" "=c,c,c")
+        (plus:QI (match_operand:QI 1 "src_operand" "%0,rR,rS<>")
+                 (match_operand:QI 2 "src_operand" "rIm,JR,rS<>")))]
+  "valid_operands (PLUS, operands, QImode)"
+  "@
+   addi\\t%2,%0
+   addi3\\t%2,%1,%0
+   addi3\\t%2,%1,%0"
+  [(set_attr "type" "binary,binary,binary")])
+; Default to int16 data attr.
+
 (define_insn "*addqi3_clobber"
   [(set (match_operand:QI 0 "reg_operand" "=d,d,?d,c,c,?c")
         (plus:QI (match_operand:QI 1 "src_operand" "%0,rR,rS<>,0,rR,rS<>")
   [(set_attr "type" "binarycc,binarycc,binarycc")])
 ; Default to int16 data attr.
 
-; This pattern is required primarily for manipulating the stack pointer
-; where GCC doesn't expect CC to be clobbered or for calculating
-; addresses during reload.
-(define_insn "addqi3_noclobber"
-  [(set (match_operand:QI 0 "std_reg_operand" "=c,c,c")
-        (plus:QI (match_operand:QI 1 "src_operand" "%0,rR,rS<>")
-                 (match_operand:QI 2 "src_operand" "rIm,JR,rS<>")))]
-  "valid_operands (PLUS, operands, QImode)"
-  "@
-   addi\\t%2,%0
-   addi3\\t%2,%1,%0
-   addi3\\t%2,%1,%0"
-  [(set_attr "type" "binary,binary,binary")])
-; Default to int16 data attr.
-
 
 ; This pattern is required during reload when eliminate_regs_in_insn
 ; effectively converts a move insn into an add insn when the src
      {        
        if (GET_CODE (operands[2]) == CONST_INT)
          {
-          /* Let GCC try to synthesise the multiplication using shifts
+          /* Let GCC try to synthesize the multiplication using shifts
              and adds.  In most cases this will be more profitable than
              using the C3x MPYI.  */
             FAIL;
                                           operands[2]));
             DONE;
          }
-       c4x_emit_libcall3 (smul_optab->handlers[(int) QImode].libfunc,
+       c4x_emit_libcall3 (optab_libfunc (smul_optab, QImode),
                          MULT, QImode, operands);
        DONE;
      }
 
 ; The C3x multiply instruction assumes 24-bit signed integer operands
 ; and the 48-bit result is truncated to 32-bits.
-(define_insn "*mulqi3_24_clobber"
+(define_insn "mulqi3_24_clobber"
   [(set (match_operand:QI 0 "reg_operand" "=d,d,?d,c,c,?c")
         (mult:QI
          (sign_extend:QI
                (truncate:QI
                 (lshiftrt:HI
                  (mult:HI
-                  (zero_extend:HI (match_operand:QI 1 "src_operand" ""))
-                  (zero_extend:HI (match_operand:QI 2 "lsrc_operand" "")))
+                  (zero_extend:HI (match_operand:QI 1
+                                  "nonimmediate_src_operand" ""))
+                  (zero_extend:HI (match_operand:QI 2
+                                  "nonimmediate_lsrc_operand" "")))
                  (const_int 32))))
               (clobber (reg:CC_NOOV 21))])]
  ""
         (truncate:QI
          (lshiftrt:HI
           (mult:HI 
-           (zero_extend:HI (match_operand:QI 1 "src_operand" "%0,rR,rS<>,0,rR,rS<>"))
-           (zero_extend:HI (match_operand:QI 2 "lsrc_operand" "rLm,JR,rS<>,rLm,JR,rS<>")))
+           (zero_extend:HI (match_operand:QI 1
+                           "nonimmediate_src_operand" "%0,rR,rS<>,0,rR,rS<>"))
+           (zero_extend:HI (match_operand:QI 2
+                           "nonimmediate_lsrc_operand" "rm,R,rS<>,rm,R,rS<>")))
           (const_int 32))))
    (clobber (reg:CC_NOOV 21))]
   "! TARGET_C3X && valid_operands (MULT, operands, QImode)"
         (truncate:QI
          (lshiftrt:HI
           (mult:HI 
-           (zero_extend:HI (match_operand:QI 1 "src_operand" "0,rR,rS<>"))
-           (zero_extend:HI (match_operand:QI 2 "lsrc_operand" "rLm,JR,rS<>")))
+           (zero_extend:HI (match_operand:QI 1
+                           "nonimmediate_src_operand" "0,rR,rS<>"))
+           (zero_extend:HI (match_operand:QI 2
+                           "nonimmediate_lsrc_operand" "rm,R,rS<>")))
           (const_int 32))))]
   "! TARGET_C3X && valid_operands (MULT, operands, QImode)"
   "@
   [(set_attr "type" "binary,binary,binary,binary")
    (set_attr "data" "not_uint16,uint16,int16,uint16")])
 
+(define_insn "andn_st"
+  [(set (unspec:QI [(reg:QI 21)] 20)
+        (and:QI (unspec:QI [(reg:QI 21)] UNSPEC_ANDN_ST)
+                (match_operand:QI 0 "" "N")))
+   (use (match_dup 0))
+   (use (reg:CC 21))
+   (clobber (reg:CC 21))]
+  ""
+  "andn\\t%N0,st"
+  [(set_attr "type" "misc")
+   (set_attr "data" "not_uint16")])
+
 (define_split
   [(set (match_operand:QI 0 "std_reg_operand" "")
         (and:QI (match_operand:QI 1 "src_operand" "")
 (define_insn "*lshlqi3_clobber"
   [(set (match_operand:QI 0 "reg_operand" "=d,d,?d,c,c,?c")
         (ashift:QI (match_operand:QI 1 "src_operand" "0,rR,rS<>,0,rR,rS<>")
-                   (unspec:QI [(match_operand:QI 2 "src_operand" "rIm,JR,rS<>,rIm,JR,rS<>")] 3)))
+                   (unspec:QI [(match_operand:QI 2 "src_operand" "rIm,JR,rS<>,rIm,JR,rS<>")] UNSPEC_LSH)))
    (clobber (reg:CC 21))]
   "valid_operands (ASHIFT, operands, QImode)"
   "@
 ; Unfortunately the C40 doesn't allow cmpi3 7, *ar0++ so the next best
 ; thing would be to get the small constant loaded into a register (say r0)
 ; so that it could be hoisted out of the loop so that we only
-; would need to do cmpi3 *ar0++, r0.  Now the loop optimisation pass
+; would need to do cmpi3 *ar0++, r0.  Now the loop optimization pass
 ; comes before the flow pass (which finds autoincrements) so we're stuck.
-; Ideally, GCC requires another loop optimisation pass (preferably after
+; Ideally, GCC requires another loop optimization pass (preferably after
 ; reload) so that it can hoist invariants out of loops.
 ; The current solution modifies legitimize_operands () so that small
 ; constants are forced into a pseudo register.
  ")
 
 (define_insn "*insv_clobber"
-  [(set (zero_extract:QI (match_operand:QI 0 "reg_operand" "=d,c")
+  [(set (zero_extract:QI (match_operand:QI 0 "reg_operand" "+d,c")
                          (match_operand:QI 1 "const_int_operand" "n,n")
                          (match_operand:QI 2 "const_int_operand" "n,n"))
         (match_operand:QI 3 "src_operand" "rLm,rLm"))
    (set_attr "data" "uint16,uint16")])
 
 (define_peephole
-  [(parallel [(set (zero_extract:QI (match_operand:QI 0 "ext_reg_operand" "=d")
+  [(parallel [(set (zero_extract:QI (match_operand:QI 0 "ext_reg_operand" "+d")
                                     (match_operand:QI 1 "const_int_operand" "n")
                                     (match_operand:QI 2 "const_int_operand" "n"))
                    (match_operand:QI 3 "src_operand" "rLm"))
 ;  If one of the operands is not a register, then we should
 ;  emit two insns, using a scratch register.  This will produce
 ;  better code in loops if the source operand is invariant, since
-;  the source reload can be optimised out.  During reload we cannot
+;  the source reload can be optimized out.  During reload we cannot
 ;  use change_address or force_reg.
 (define_expand "movqf"
   [(set (match_operand:QF 0 "src_operand" "")
 
 ; This can generate invalid stack slot displacements
 (define_split
- [(set (match_operand:QI 0 "reg_operand" "=r")
-       (unspec:QI [(match_operand:QF 1 "reg_operand" "f")] 12))]
+ [(set (match_operand:QI 0 "reg_operand" "")
+       (unspec:QI [(match_operand:QF 1 "reg_operand" "")] UNSPEC_STOREQF_INT))]
   "reload_completed"
   [(set (match_dup 3) (match_dup 1))
    (set (match_dup 0) (match_dup 2))]
 
 (define_insn "storeqf_int"
  [(set (match_operand:QI 0 "reg_operand" "=r")
-       (unspec:QI [(match_operand:QF 1 "reg_operand" "f")] 12))]
+       (unspec:QI [(match_operand:QF 1 "reg_operand" "f")] UNSPEC_STOREQF_INT))]
  ""
  "#"
   [(set_attr "type" "multi")])
 
 (define_split
- [(parallel [(set (match_operand:QI 0 "reg_operand" "=r")
-                  (unspec:QI [(match_operand:QF 1 "reg_operand" "f")] 12))
+ [(parallel [(set (match_operand:QI 0 "reg_operand" "")
+                  (unspec:QI [(match_operand:QF 1 "reg_operand" "")] UNSPEC_STOREQF_INT))
              (clobber (reg:CC 21))])]
   "reload_completed"
   [(set (mem:QF (pre_inc:QI (reg:QI 20)))
 
 (define_insn "storeqf_int_clobber"
  [(parallel [(set (match_operand:QI 0 "reg_operand" "=r")
-                  (unspec:QI [(match_operand:QF 1 "reg_operand" "f")] 12))
+                  (unspec:QI [(match_operand:QF 1 "reg_operand" "f")] UNSPEC_STOREQF_INT))
              (clobber (reg:CC 21))])]
  ""
  "#"
 
 ; This can generate invalid stack slot displacements
 (define_split
- [(set (match_operand:QF 0 "reg_operand" "=f")
-       (unspec:QF [(match_operand:QI 1 "reg_operand" "r")] 11))]
+ [(set (match_operand:QF 0 "reg_operand" "")
+       (unspec:QF [(match_operand:QI 1 "reg_operand" "")] UNSPEC_LOADQF_INT))]
   "reload_completed"
   [(set (match_dup 2) (match_dup 1))
    (set (match_dup 0) (match_dup 3))]
 
 (define_insn "loadqf_int"
  [(set (match_operand:QF 0 "reg_operand" "=f")
-       (unspec:QF [(match_operand:QI 1 "reg_operand" "r")] 11))]
+       (unspec:QF [(match_operand:QI 1 "reg_operand" "r")] UNSPEC_LOADQF_INT))]
  ""
  "#"
   [(set_attr "type" "multi")])
 
 (define_split
- [(parallel [(set (match_operand:QF 0 "reg_operand" "=f")
-                  (unspec:QF [(match_operand:QI 1 "reg_operand" "r")] 11))
+ [(parallel [(set (match_operand:QF 0 "reg_operand" "")
+                  (unspec:QF [(match_operand:QI 1 "reg_operand" "")] UNSPEC_LOADQF_INT))
              (clobber (reg:CC 21))])]
   "reload_completed"
   [(set (mem:QI (pre_inc:QI (reg:QI 20)))
 
 (define_insn "loadqf_int_clobber"
  [(parallel [(set (match_operand:QF 0 "reg_operand" "=f")
-                  (unspec:QF [(match_operand:QI 1 "reg_operand" "r")] 11))
+                  (unspec:QF [(match_operand:QI 1 "reg_operand" "r")] UNSPEC_LOADQF_INT))
              (clobber (reg:CC 21))])]
  ""
  "#"
 ;
 ; PUSH/POP
 ;
-(define_insn "*pushqf"
+(define_insn "pushqf"
   [(set (mem:QF (pre_inc:QI (reg:QI 20)))
         (match_operand:QF 0 "reg_operand" "f"))]
  ""
  "pushf\\t%0"
  [(set_attr "type" "push")])
 
-(define_insn "*popqf"
+(define_insn "popqf"
   [(set (match_operand:QF 0 "reg_operand" "=f")
         (mem:QF (post_dec:QI (reg:QI 20))))
    (clobber (reg:CC 21))]
  "popf\\t%0"
  [(set_attr "type" "pop")])
 
+(define_insn "popqf_unspec"
+  [(set (unspec:QF [(match_operand:QF 0 "reg_operand" "=f")] UNSPEC_POPQF)
+        (mem:QF (post_dec:QI (reg:QI 20))))
+   (clobber (match_dup 0))
+   (clobber (reg:CC 21))]
+ ""
+ "popf\\t%0"
+ [(set_attr "type" "pop")])
 
 ;
 ; ABSF
                               (match_dup 3)))
              (set (match_dup 4)
                   (float:QF (match_dup 1)))])
-  (set (match_dup 6)
+  (set (match_dup 2)
        (if_then_else:QF (lt (reg:CC 21) (const_int 0))
                         (match_dup 5)
                         (match_dup 2)))
   (parallel [(set (match_operand:QF 0 "reg_operand" "")
-                  (plus:QF (match_dup 6) (match_dup 4)))
+                  (plus:QF (match_dup 2) (match_dup 4)))
              (clobber (reg:CC_NOOV 21))])]
  ""
  "operands[2] = gen_reg_rtx (QFmode);
   operands[3] = CONST0_RTX (QFmode); 
   operands[4] = gen_reg_rtx (QFmode);
   operands[5] = gen_reg_rtx (QFmode);
-  operands[6] = gen_reg_rtx (QFmode);
-  emit_move_insn (operands[5], 
-   immed_real_const_1 (REAL_VALUE_ATOF (\"4294967296.0\", QFmode), QFmode));")
+  emit_move_insn (operands[5], CONST_DOUBLE_ATOF (\"4294967296.0\", QFmode));")
+
+(define_expand "floatunsqihf2"
+ [(set (match_dup 2) (match_dup 3))
+  (parallel [(set (reg:CC 21)
+                  (compare:CC (float:HF (match_operand:QI 1 "src_operand" ""))
+                              (match_dup 3)))
+             (set (match_dup 4)
+                  (float:HF (match_dup 1)))])
+  (set (match_dup 2)
+       (if_then_else:HF (lt (reg:CC 21) (const_int 0))
+                        (match_dup 5)
+                        (match_dup 2)))
+  (parallel [(set (match_operand:HF 0 "reg_operand" "")
+                  (plus:HF (match_dup 2) (match_dup 4)))
+             (clobber (reg:CC_NOOV 21))])]
+ ""
+ "operands[2] = gen_reg_rtx (HFmode);
+  operands[3] = CONST0_RTX (HFmode); 
+  operands[4] = gen_reg_rtx (HFmode);
+  operands[5] = gen_reg_rtx (HFmode);
+  emit_move_insn (operands[5], CONST_DOUBLE_ATOF (\"4294967296.0\", HFmode));")
 
 (define_insn "floatqihf2"
   [(set (match_operand:HF 0 "reg_operand" "=h")
  "float\\t%1,%0"
   [(set_attr "type" "unarycc")])
 
+(define_insn "*floatqihf2_set"
+  [(set (reg:CC 21)
+       (compare:CC (float:HF (match_operand:QI 1 "src_operand" "rIm"))
+                    (match_operand:QF 2 "fp_zero_operand" "G")))
+   (set (match_operand:HF 0 "reg_operand" "=h")
+        (float:HF (match_dup 1)))]
+ ""
+ "float\\t%1,%0"
+  [(set_attr "type" "unarycc")])
+
 ;
 ; FIX
 ;
                              (const_int 0)))
             (set (match_dup 4)
                  (fix:QI (match_dup 3)))])
-  (parallel [(set (match_dup 4) (unspec:QI [(match_dup 2)] 13))
+  (parallel [(set (match_dup 4) (unspec:QI [(match_dup 2)] UNSPEC_LDIV))
              (use (reg:CC 21))])
   (set (match_operand:QI 0 "reg_operand" "=r") (match_dup 4))]
  ""
   operands[3] = gen_reg_rtx (QFmode);
   operands[4] = gen_reg_rtx (QImode);
   operands[5] = gen_reg_rtx (QFmode);
-  emit_move_insn (operands[5],
-   immed_real_const_1 (REAL_VALUE_ATOF (\"4294967296.0\", QFmode), QFmode));")
+  emit_move_insn (operands[5], CONST_DOUBLE_ATOF (\"4294967296.0\", QFmode));")
 
 (define_expand "fixuns_truncqfhi2"
   [(parallel [(set (match_operand:HI 0 "reg_operand" "")
 ;
 ; RCPF
 ;
-(define_insn "*rcpfqf_clobber"
+(define_insn "rcpfqf_clobber"
   [(set (match_operand:QF 0 "reg_operand" "=f")
-        (unspec:QF [(match_operand:QF 1 "src_operand" "fHm")] 5))
+        (unspec:QF [(match_operand:QF 1 "src_operand" "fHm")] UNSPEC_RCPF))
    (clobber (reg:CC_NOOV 21))]
   "! TARGET_C3X"
   "rcpf\\t%1,%0"
 ;
 (define_insn "*rsqrfqf_clobber"
   [(set (match_operand:QF 0 "reg_operand" "=f")
-        (unspec:QF [(match_operand:QF 1 "src_operand" "fHm")] 10))
+        (unspec:QF [(match_operand:QF 1 "src_operand" "fHm")] UNSPEC_RSQRF))
    (clobber (reg:CC_NOOV 21))]
   "! TARGET_C3X"
   "rsqrf\\t%1,%0"
 ;
 (define_insn "*rndqf_clobber"
   [(set (match_operand:QF 0 "reg_operand" "=f")
-        (unspec:QF [(match_operand:QF 1 "src_operand" "fHm")] 6))
+        (unspec:QF [(match_operand:QF 1 "src_operand" "fHm")] UNSPEC_RND))
    (clobber (reg:CC_NOOV 21))]
   "! TARGET_C3X"
   "rnd\\t%1,%0"
 ; Inlined float square root for C4x
 (define_expand "sqrtqf2_inline"
   [(parallel [(set (match_dup 2)
-                  (unspec:QF [(match_operand:QF 1 "src_operand" "")] 10))
+                  (unspec:QF [(match_operand:QF 1 "src_operand" "")] UNSPEC_RSQRF))
              (clobber (reg:CC_NOOV 21))])
    (parallel [(set (match_dup 3) (mult:QF (match_dup 5) (match_dup 1)))
              (clobber (reg:CC_NOOV 21))])
    (parallel [(set (match_dup 4) (mult:QF (match_dup 2) (match_dup 1)))
              (clobber (reg:CC_NOOV 21))])
    (parallel [(set (match_operand:QF 0 "reg_operand" "")
-                  (unspec:QF [(match_dup 4)] 6))
+                  (unspec:QF [(match_dup 4)] UNSPEC_RND))
              (clobber (reg:CC_NOOV 21))])]
   "! TARGET_C3X"
   "if (! reload_in_progress
    operands[2] = gen_reg_rtx (QFmode);
    operands[3] = gen_reg_rtx (QFmode);
    operands[4] = gen_reg_rtx (QFmode);
-   operands[5] = immed_real_const_1 (REAL_VALUE_ATOF (\"0.5\", QFmode),
-                                     QFmode);
-   operands[6] = immed_real_const_1 (REAL_VALUE_ATOF (\"1.5\", QFmode),
-                                     QFmode);")
+   operands[5] = CONST_DOUBLE_ATOF (\"0.5\", QFmode);
+   operands[6] = CONST_DOUBLE_ATOF (\"1.5\", QFmode);")
 
 (define_expand "sqrtqf2"
   [(parallel [(set (match_operand:QF 0 "reg_operand" "")
    DONE;")
 
 ;
+; TOIEEE / FRIEEE
+;
+(define_insn "toieee"
+  [(set (match_operand:QF 0 "reg_operand" "=f")
+        (unspec:QF [(match_operand:QF 1 "src_operand" "fHm")] UNSPEC_TOIEEE))
+   (clobber (reg:CC 21))]
+ ""
+ "toieee\\t%1,%0")
+
+(define_insn "frieee"
+  [(set (match_operand:QF 0 "reg_operand" "=f")
+        (unspec:QF [(match_operand:QF 1 "memory_operand" "m")] UNSPEC_FRIEEE))
+   (clobber (reg:CC 21))]
+ ""
+ "frieee\\t%1,%0")
+
+;
 ; THREE OPERAND FLOAT INSTRUCTIONS
 ;
 
 ; Inlined float divide for C4x
 (define_expand "divqf3_inline"
   [(parallel [(set (match_dup 3)
-                  (unspec:QF [(match_operand:QF 2 "src_operand" "")] 5))
+                  (unspec:QF [(match_operand:QF 2 "src_operand" "")] UNSPEC_RCPF))
              (clobber (reg:CC_NOOV 21))])
    (parallel [(set (match_dup 4) (mult:QF (match_dup 2) (match_dup 3)))
              (clobber (reg:CC_NOOV 21))])
                            (match_dup 3)))
              (clobber (reg:CC_NOOV 21))])
    (parallel [(set (match_operand:QF 0 "reg_operand" "")
-                  (unspec:QF [(match_dup 3)] 6))
+                  (unspec:QF [(match_dup 3)] UNSPEC_RND))
              (clobber (reg:CC_NOOV 21))])]
   "! TARGET_C3X"
   "if (! reload_in_progress
                           [(reg:CC 21) (const_int 0)])
                          (match_operand:QI 2 "src_operand" "rIm,0")
                          (match_operand:QI 3 "src_operand" "0,rIm")))]
- ""
+ "valid_operands (IF_THEN_ELSE, operands, QImode)"
  "@
   ldi%1\\t%2,%0
   ldi%I1\\t%3,%0"
  "GET_CODE (operands[1]) != LE
   && GET_CODE (operands[1]) != GE
   && GET_CODE (operands[1]) != LT
-  && GET_CODE (operands[1]) != GT"
+  && GET_CODE (operands[1]) != GT
+  && valid_operands (IF_THEN_ELSE, operands, QImode)"
  "@
   ldi%1\\t%2,%0
   ldi%I1\\t%3,%0"
 
 (define_insn "*ldi_on_overflow"
   [(set (match_operand:QI 0 "reg_operand" "=r")
-       (unspec:QI [(match_operand:QI 1 "src_operand" "rIm")] 13))
+       (unspec:QI [(match_operand:QI 1 "src_operand" "rIm")] UNSPEC_LDIV))
    (use (reg:CC 21))]
   ""
-  "@
-   ldiv\\t%1,%0"
-  [(set_attr "type" "binary")])
+  "ldiv\\t%1,%0"
+  [(set_attr "type" "unary")])
 
 ; Move operand 2 to operand 0 if condition (operand 1) is true
 ; else move operand 3 to operand 0.
     if (ccreg == NULL_RTX) FAIL;
     emit_insn (gen_rtx_SET (QImode, operands[0],
                             gen_rtx_IF_THEN_ELSE (QImode,
-                                 gen_rtx (code, VOIDmode, ccreg, const0_rtx),
-                                          operands[2], operands[3])));
+                                 gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx),
+                                                operands[2], operands[3])));
     DONE;}")
                       
 (define_insn "*ldf_conditional"
                           [(reg:CC 21) (const_int 0)])
                          (match_operand:QF 2 "src_operand" "fHm,0")
                          (match_operand:QF 3 "src_operand" "0,fHm")))]
- ""
+ "valid_operands (IF_THEN_ELSE, operands, QFmode)"
  "@
   ldf%1\\t%2,%0
   ldf%I1\\t%3,%0"
  "GET_CODE (operands[1]) != LE
   && GET_CODE (operands[1]) != GE
   && GET_CODE (operands[1]) != LT
-  && GET_CODE (operands[1]) != GT"
+  && GET_CODE (operands[1]) != GT
+  && valid_operands (IF_THEN_ELSE, operands, QFmode)"
  "@
   ldf%1\\t%2,%0
   ldf%I1\\t%3,%0"
     if (ccreg == NULL_RTX) FAIL;
     emit_insn (gen_rtx_SET (QFmode, operands[0],
                             gen_rtx_IF_THEN_ELSE (QFmode,
-                                 gen_rtx (code, VOIDmode, ccreg, const0_rtx),
-                                          operands[2], operands[3])));
+                                 gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx),
+                                                operands[2], operands[3])));
+    DONE;}")
+
+(define_insn "*ldhf_conditional"
+  [(set (match_operand:HF 0 "reg_operand" "=h,h")
+        (if_then_else:HF (match_operator 1 "comparison_operator"
+                          [(reg:CC 21) (const_int 0)])
+                         (match_operand:HF 2 "src_operand" "hH,0")
+                         (match_operand:HF 3 "src_operand" "0,hH")))]
+ ""
+ "@
+  ldf%1\\t%2,%0
+  ldf%I1\\t%3,%0"
+ [(set_attr "type" "binary")])
+
+(define_insn "*ldhf_conditional_noov"
+  [(set (match_operand:HF 0 "reg_operand" "=h,h")
+        (if_then_else:HF (match_operator 1 "comparison_operator"
+                          [(reg:CC_NOOV 21) (const_int 0)])
+                         (match_operand:HF 2 "src_operand" "hH,0")
+                         (match_operand:HF 3 "src_operand" "0,hH")))]
+ "GET_CODE (operands[1]) != LE
+  && GET_CODE (operands[1]) != GE
+  && GET_CODE (operands[1]) != LT
+  && GET_CODE (operands[1]) != GT"
+ "@
+  ldf%1\\t%2,%0
+  ldf%I1\\t%3,%0"
+ [(set_attr "type" "binary")])
+
+(define_expand "movhfcc"
+  [(set (match_operand:HF 0 "reg_operand" "")
+        (if_then_else:HF (match_operand 1 "comparison_operator" "")
+                         (match_operand:HF 2 "src_operand" "")
+                         (match_operand:HF 3 "src_operand" "")))]
+ ""
+ "{ 
+    enum rtx_code code = GET_CODE (operands[1]);
+    rtx ccreg = c4x_gen_compare_reg (code, c4x_compare_op0, c4x_compare_op1);
+    if (ccreg == NULL_RTX) FAIL;
+    emit_insn (gen_rtx_SET (HFmode, operands[0],
+                            gen_rtx_IF_THEN_ELSE (HFmode,
+                                 gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx),
+                                                operands[2], operands[3])));
     DONE;}")
 
 (define_expand "seq"
 
 (define_insn "*bu"
   [(set (pc)
-        (unspec [(match_operand:QI 0 "reg_operand" "r")] 1))]
+        (unspec [(match_operand:QI 0 "reg_operand" "r")] UNSPEC_BU))]
   ""
   "bu%#\\t%0"
   [(set_attr "type" "jump")])
   [(set_attr "type" "binarycc")])
 
 ;
+; TOIEEE/STF
+;
+
+(define_insn "*toieee_movqf_clobber"
+  [(set (match_operand:QF 0 "ext_low_reg_operand" "=q")
+       (unspec:QF [(match_operand:QF 1 "par_ind_operand" "S<>")] UNSPEC_TOIEEE))
+   (set (match_operand:QF 2 "par_ind_operand" "=S<>")
+        (match_operand:QF 3 "ext_low_reg_operand" "q"))
+   (clobber (reg:CC 21))]
+  "TARGET_PARALLEL && valid_parallel_operands_4 (operands, QFmode)"
+  "toieee\\t%1,%0\\n||\\tstf\\t%3,%2"
+  [(set_attr "type" "binarycc")])
+
+;
+; FRIEEE/STF
+;
+
+(define_insn "*frieee_movqf_clobber"
+  [(set (match_operand:QF 0 "ext_low_reg_operand" "=q")
+       (unspec:QF [(match_operand:QF 1 "par_ind_operand" "S<>")] UNSPEC_FRIEEE))
+   (set (match_operand:QF 2 "par_ind_operand" "=S<>")
+        (match_operand:QF 3 "ext_low_reg_operand" "q"))
+   (clobber (reg:CC 21))]
+  "TARGET_PARALLEL && valid_parallel_operands_4 (operands, QFmode)"
+  "frieee\\t%1,%0\\n||\\tstf\\t%3,%2"
+  [(set_attr "type" "binarycc")])
+
+;
 ; PARALLEL INTEGER INSTRUCTIONS
 ;
 
   "! TARGET_C3X"
   "*
    if (final_sequence)
-     return \"laj%U0\\t%C0\";
+     return c4x_check_laj_p (insn)
+        ? \"nop\\n\\tlaj%U0\\t%C0\" : \"laj%U0\\t%C0\";
    else
      return \"call%U0\\t%C0\";"
   [(set_attr "type" "laj")])
                               force_reg (Pmode, XEXP (operands[0], 0)));
 }")
 
+(define_insn "nodb_call"
+ [(call (mem:QI (match_operand:QI 0 "call_address_operand" "Ur"))
+       (const_int 0))]
+  ""
+  "call%U0\\t%C0"
+  [(set_attr "type" "call")])
+
 (define_insn "*callv_c3x"
  [(set (match_operand 0 "" "=r")
        (call (mem:QI (match_operand:QI 1 "call_address_operand" "Ur"))
   "! TARGET_C3X"
   "*
    if (final_sequence)
-     return \"laj%U1\\t%C1\";
+     return c4x_check_laj_p (insn)
+        ? \"nop\\n\\tlaj%U1\\t%C1\" : \"laj%U1\\t%C1\";
    else
      return \"call%U1\\t%C1\";"
   [(set_attr "type" "laj")])
 
 (define_insn "return"
   [(return)]
-  "c4x_null_epilogue_p ()"
+  "c4x_null_epilogue_p ()"
   "rets"
   [(set_attr "type" "rets")])
 
+(define_insn "return_from_epilogue"
+  [(return)]
+  "reload_completed && ! c4x_interrupt_function_p ()"
+  "rets"
+  [(set_attr "type" "rets")])
+
+(define_insn "return_from_interrupt_epilogue"
+  [(return)]
+  "reload_completed && c4x_interrupt_function_p ()"
+  "reti"
+  [(set_attr "type" "rets")])
+
 (define_insn "*return_cc"
   [(set (pc)
         (if_then_else (match_operator 0 "comparison_operator"
                       [(reg:CC 21) (const_int 0)])
                       (return)
                        (pc)))]
-  "c4x_null_epilogue_p ()"
+  "c4x_null_epilogue_p ()"
   "rets%0"
   [(set_attr "type" "rets")])
 
    && GET_CODE (operands[0]) != GE
    && GET_CODE (operands[0]) != LT
    && GET_CODE (operands[0]) != GT
-   && c4x_null_epilogue_p ()"
+   && c4x_null_epilogue_p ()"
   "rets%0"
   [(set_attr "type" "rets")])
 
                       [(reg:CC 21) (const_int 0)])
                        (pc)
                       (return)))]
-  "c4x_null_epilogue_p ()"
+  "c4x_null_epilogue_p ()"
   "rets%I0"
   [(set_attr "type" "rets")])
 
    && GET_CODE (operands[0]) != GE
    && GET_CODE (operands[0]) != LT
    && GET_CODE (operands[0]) != GT
-   && c4x_null_epilogue_p ()"
+   && c4x_null_epilogue_p ()"
   "rets%I0"
   [(set_attr "type" "rets")])
 
   "br%#\\t%l0"
   [(set_attr "type" "jump")])
 
+(define_insn "trap"
+  [(trap_if (const_int 1) (const_int 31))]
+  ""
+  "trapu\\t31"
+  [(set_attr "type" "call")])
+
+(define_expand "conditional_trap"
+ [(trap_if (match_operand 0 "comparison_operator" "")
+          (match_operand 1 "const_int_operand" ""))]
+ ""
+ "{
+    enum rtx_code code = GET_CODE (operands[1]);
+    rtx ccreg = c4x_gen_compare_reg (code, c4x_compare_op0, c4x_compare_op1);
+    if (ccreg == NULL_RTX) FAIL;
+    if (GET_MODE (ccreg) == CCmode)
+      emit_insn (gen_cond_trap_cc (operands[0], operands[1]));
+    else 
+      emit_insn (gen_cond_trap_cc_noov (operands[0], operands[1]));
+    DONE;}")
+
+(define_insn "cond_trap_cc"
+  [(trap_if (match_operator 0 "comparison_operator"
+            [(reg:CC 21) (const_int 0)])
+           (match_operand 1 "const_int_operand" ""))]
+  ""
+  "trap%0\\t31"
+  [(set_attr "type" "call")])
+
+(define_insn "cond_trap_cc_noov"
+  [(trap_if (match_operator 0 "comparison_operator"
+            [(reg:CC_NOOV 21) (const_int 0)])
+           (match_operand 1 "const_int_operand" ""))]
+  "GET_CODE (operands[0]) != LE
+   && GET_CODE (operands[0]) != GE
+   && GET_CODE (operands[0]) != LT
+   && GET_CODE (operands[0]) != GT"
+  "trap%0\\t31"
+  [(set_attr "type" "call")])
+
 ;
 ; DBcond
 ;
 ; Note we have to emit a dbu instruction if there are no delay slots
 ; to fill.
 ; Also note that GCC will try to reverse a loop to see if it can
-; utilise this instruction.  However, if there are more than one
+; utilize this instruction.  However, if there are more than one
 ; memory reference in the loop, it cannot guarantee that reversing
 ; the loop will work :(  (see check_dbra_loop() in loop.c)
 ; Note that the C3x only decrements the 24 LSBs of the address register
    (set (match_dup 0)
         (plus:QI (match_dup 0)
                  (const_int -1)))
+   (use (reg:QI 20))
    (clobber (reg:CC_NOOV 21))]
   "TARGET_DB && TARGET_LOOP_UNSIGNED"
   "*
    (set (match_dup 0)
         (plus:QI (match_dup 0)
                  (const_int -1)))
+   (use (reg:QI 20))
    (clobber (reg:CC_NOOV 21))]
   "reload_completed && TARGET_DB && TARGET_LOOP_UNSIGNED"
   [(parallel [(set (pc)
    (set (match_dup 0)
         (plus:QI (match_dup 0)
                  (const_int -1)))
+   (use (reg:QI 20))
    (clobber (reg:CC_NOOV 21))]
   "TARGET_DB && (find_reg_note (insn, REG_NONNEG, 0) || TARGET_LOOP_UNSIGNED)"
   "*
    (set (match_dup 0)
         (plus:QI (match_dup 0)
                  (const_int -1)))
+   (use (reg:QI 20))
    (clobber (reg:CC_NOOV 21))]
   "reload_completed && TARGET_DB && TARGET_LOOP_UNSIGNED"
   [(parallel [(set (pc)
   "nop")
 ; Default to misc type attr.
 
+(define_insn "return_indirect_internal"
+  [(return)
+   (use (match_operand:QI 0 "reg_operand" ""))]
+  "reload_completed"                           
+  "bu%#\\t%0"
+  [(set_attr "type" "jump")])
+
+(define_expand "prologue"
+  [(const_int 1)]
+  ""                           
+  "c4x_expand_prologue (); DONE;")
+
+(define_expand "epilogue"
+  [(const_int 1)]
+  ""
+  "c4x_expand_epilogue (); DONE;")
 
 ;
 ; RPTB
 
 (define_insn "rpts_top"
   [(unspec [(use (label_ref (match_operand 0 "" "")))
-            (use (label_ref (match_operand 1 "" "")))] 2)
+            (use (label_ref (match_operand 1 "" "")))] UNSPEC_RPTS)
    (clobber (reg:QI 25))
    (clobber (reg:QI 26))]
   ""
 ; This pattern needs to be emitted at the start of the loop to
 ; say that RS and RE are loaded.
 (define_insn "rptb_init"
-  [(unspec [(match_operand:QI 0 "register_operand" "va")] 22)
+  [(unspec [(match_operand:QI 0 "register_operand" "va")] UNSPEC_RPTB_INIT)
    (clobber (reg:QI 25))
    (clobber (reg:QI 26))]
   ""
                  (const_int -1)))
    (use (reg:QI 25))
    (use (reg:QI 26))
+   (use (reg:QI 20))
    (clobber (reg:CC_NOOV 21))]
   ""
   "*
    (use (match_operand:QI 4 "const_int_operand" ""))
    (use (reg:QI 25))
    (use (reg:QI 26))
+   (use (reg:QI 20))
    (clobber (reg:CC_NOOV 21))]
   "reload_completed"
   [(parallel [(set (pc)
    (use (label_ref (match_operand 4 "" "")))]
   ""
   "if (! TARGET_LOOP_UNSIGNED 
-       && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) > (1U << 31))
+       && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) > ((unsigned) 1 << 31))
      FAIL;
    if (INTVAL (operands[3]) > 1 || ! TARGET_RPTB)
      {
     DONE;
   ")
 
-; The current low overhead looping code is naff and is not failsafe
-; If you want RTPB instructions to be generated, apply the patches
-; from www.elec.canterbury.ac.nz/c4x.  This will utilise the
-; doloop_begin and doloop_end patterns in this MD.
 (define_expand "decrement_and_branch_on_count"
   [(parallel [(set (pc)
                    (if_then_else (ge (match_operand:QI 0 "register_operand" "")
   "0"
   "")
 
-(define_expand "movstrqi_small2"
+(define_expand "movmemqi_small"
   [(parallel [(set (mem:BLK (match_operand:BLK 0 "src_operand" ""))
                    (mem:BLK (match_operand:BLK 1 "src_operand" "")))
               (use (match_operand:QI 2 "immediate_operand" ""))
 ; BLOCK MOVE
 ; We should probably get RC loaded when using RPTB automagically...
 ; There's probably no need to call _memcpy() if we don't get
-; a immediate operand for the size.  We could do a better job here
+; an immediate operand for the size.  We could do a better job here
 ; than most memcpy() implementations.
 ; operand 2 is the number of bytes
 ; operand 3 is the shared alignment
 ; operand 4 is a scratch register
 
-(define_insn "movstrqi_small"
-  [(set (mem:BLK (match_operand:QI 0 "addr_reg_operand" "+a"))
-        (mem:BLK (match_operand:QI 1 "addr_reg_operand" "+a")))
+(define_insn "movmemqi_large"
+  [(set (mem:BLK (match_operand:QI 0 "addr_reg_operand" "a"))
+        (mem:BLK (match_operand:QI 1 "addr_reg_operand" "a")))
    (use (match_operand:QI 2 "immediate_operand" "i"))
    (use (match_operand:QI 3 "immediate_operand" ""))
    (clobber (match_operand:QI 4 "ext_low_reg_operand" "=&q"))
-   (clobber (match_dup 0))
-   (clobber (match_dup 1))]
-  ""
-  "*
- {
-   int i;
-   int len = INTVAL (operands[2]);
-   int first = 1;
-
-   for (i = 0; i < len; i++)
-    {
-      if (first)
-        output_asm_insn (\"ldiu\\t*%1++,%4\", operands);
-      else
-        output_asm_insn (\"|| ldi\\t*%1++,%4\", operands);
-      output_asm_insn (\"sti\\t%4,*%0++\", operands);
-      first = 0;
-    } 
-  return \"\";
-  }
-  "
-  [(set_attr "type" "multi")])
-
-(define_insn "movstrqi_large"
-  [(set (mem:BLK (match_operand:QI 0 "addr_reg_operand" "+a"))
-        (mem:BLK (match_operand:QI 1 "addr_reg_operand" "+a")))
-   (use (match_operand:QI 2 "immediate_operand" "i"))
-   (use (match_operand:QI 3 "immediate_operand" ""))
-   (clobber (match_operand:QI 4 "ext_low_reg_operand" "=&q"))
-   (clobber (match_dup 0))
-   (clobber (match_dup 1))
+   (clobber (match_scratch:QI 5 "=0"))
+   (clobber (match_scratch:QI 6 "=1"))
    (clobber (reg:QI 25))
    (clobber (reg:QI 26))
    (clobber (reg:QI 27))]
   ""
   "*
  {
+   int i;
    int len = INTVAL (operands[2]);
 
    output_asm_insn (\"ldiu\\t*%1++,%4\", operands);
-   if (TARGET_RPTS_CYCLES (len))
+   if (len < 8)
      {
-        output_asm_insn (\"rpts\\t%2-2\", operands);  
-        output_asm_insn (\"sti\\t%4,*%0++\", operands);
-        output_asm_insn (\"|| ldi\\t*%1++,%4\", operands);
-        return \"sti\\t%4,*%0++\";
+       for (i = 1; i < len; i++)
+        {
+           output_asm_insn (\"sti\\t%4,*%0++\", operands);
+           output_asm_insn (\"|| ldi\\t*%1++,%4\", operands);
+         } 
      }
    else
      {
-        output_asm_insn (\"ldiu\\t%2-2,rc\", operands);
-        output_asm_insn (\"rptb\\t$+1\", operands);  
-        output_asm_insn (\"sti\\t%4,*%0++\", operands);
-        output_asm_insn (\"|| ldi\\t*%1++,%4\", operands);
-
-        return \"sti\\t%4,*%0++\";
+       if (TARGET_RPTS_CYCLES (len))
+         {
+           output_asm_insn (\"rpts\\t%2-2\", operands);  
+           output_asm_insn (\"sti\\t%4,*%0++\", operands);
+           output_asm_insn (\"|| ldi\\t*%1++,%4\", operands);
+         }
+       else
+         {
+           output_asm_insn (\"ldiu\\t%2-2,rc\", operands);
+           output_asm_insn (\"rptb\\t$+1\", operands);  
+           output_asm_insn (\"sti\\t%4,*%0++\", operands);
+           output_asm_insn (\"|| ldi\\t*%1++,%4\", operands);
+        }
      }
-  }
 "
 [(set_attr "type" "multi")])
+   return \"sti\\t%4,*%0++\";
}"
+ [(set_attr "type" "multi")])
 
 ; Operand 2 is the count, operand 3 is the alignment.
-(define_expand "movstrqi"
+(define_expand "movmemqi"
   [(parallel [(set (mem:BLK (match_operand:BLK 0 "src_operand" ""))
                    (mem:BLK (match_operand:BLK 1 "src_operand" "")))
               (use (match_operand:QI 2 "immediate_operand" ""))
    operands[0] = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
    operands[1] = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
    tmp = gen_reg_rtx (QImode);
-   if (INTVAL (operands[2]) < 8)
-     emit_insn (gen_movstrqi_small2 (operands[0], operands[1], operands[2],
+   /* Disabled because of reload problems.  */
+   if (0 && INTVAL (operands[2]) < 8)
+     emit_insn (gen_movmemqi_small (operands[0], operands[1], operands[2],
                                     operands[3], tmp));
    else
      {
-      emit_insn (gen_movstrqi_large (operands[0], operands[1], operands[2],
+      emit_insn (gen_movmemqi_large (operands[0], operands[1], operands[2],
                                      operands[3], tmp));
      }
    DONE;
  }")
 
 
-(define_insn "*cmpstrqi"
+(define_insn "*cmpstrnqi"
   [(set (match_operand:QI 0 "ext_reg_operand" "=d")
         (compare:QI (mem:BLK (match_operand:QI 1 "addr_reg_operand" "+a"))
                     (mem:BLK (match_operand:QI 2 "addr_reg_operand" "+a"))))
     return \"\";
  }")
 
-(define_expand "cmpstrqi"
+(define_expand "cmpstrnqi"
   [(parallel [(set (match_operand:QI 0 "reg_operand" "")
                    (compare:QI (match_operand:BLK 1 "general_operand" "")
                                (match_operand:BLK 2 "general_operand" "")))
  "reload_completed"
  [(set (match_dup 0) (float_extend:HF (match_dup 2)))
   (set (match_dup 0) (unspec:HF [(subreg:QI (match_dup 0) 0)
-                                            (match_dup 3)] 8))]
+                                            (match_dup 3)] UNSPEC_LOADHF_INT))]
  "operands[2] = c4x_operand_subword (operands[1], 0, 1, HFmode);
   operands[3] = c4x_operand_subword (operands[1], 1, 1, HFmode);
   PUT_MODE (operands[2], QFmode);
  "reload_completed && 0"
  [(set (match_dup 0) (float_extend:HF (match_dup 2)))
   (set (match_dup 0) (unspec:HF [(subreg:QI (match_dup 0) 0)
-                                            (match_dup 3)] 8))]
+                                            (match_dup 3)] UNSPEC_LOADHF_INT))]
  "operands[2] = c4x_operand_subword (operands[1], 0, 1, HFmode);
   operands[3] = c4x_operand_subword (operands[1], 1, 1, HFmode);
   PUT_MODE (operands[2], QFmode);
        (match_operand:HF 1 "reg_operand" ""))]
   "reload_completed"
   [(set (match_dup 2) (float_truncate:QF (match_dup 1)))
-   (set (match_dup 3) (unspec:QI [(match_dup 1)] 9))]
+   (set (match_dup 3) (unspec:QI [(match_dup 1)] UNSPEC_STOREHF_INT))]
  "operands[2] = c4x_operand_subword (operands[0], 0, 1, HFmode);
   operands[3] = c4x_operand_subword (operands[0], 1, 1, HFmode);
   PUT_MODE (operands[2], QFmode);
  [(set (match_operand:HF 0 "reg_operand" "=h")
        (float_extend:HF (match_operand:QF 1 "src_operand" "fHm")))]
  ""
- "@
-  ldfu\\t%1,%0"
+ "ldfu\\t%1,%0"
   [(set_attr "type" "unary")])
 
 (define_insn "*loadhf_int"
- [(set (match_operand:HF 0 "reg_operand" "=h")
+ [(set (match_operand:HF 0 "reg_operand" "+h")
        (unspec:HF [(subreg:QI (match_dup 0) 0)
-                   (match_operand:QI 1 "src_operand" "rIm")] 8))]
+                   (match_operand:QI 1 "src_operand" "rIm")] UNSPEC_LOADHF_INT))]
  ""
- "@
-  ldiu\\t%1,%0"
+ "ldiu\\t%1,%0"
   [(set_attr "type" "unary")])
 
 (define_insn "*storehf_float"
 
 (define_insn "*storehf_int"
  [(set (match_operand:QI 0 "memory_operand" "=m")
-       (unspec:QI [(match_operand:HF 1 "reg_operand" "h")] 9))]
+       (unspec:QI [(match_operand:HF 1 "reg_operand" "h")] UNSPEC_STOREHF_INT))]
  ""
- "@
-  sti\\t%1,%0"
+ "sti\\t%1,%0"
   [(set_attr "type" "store")])
 
 (define_insn "extendqfhf2"
 ;
 ; PUSH/POP
 ;
-(define_insn "*pushhf"
+(define_insn "pushhf"
   [(set (mem:HF (pre_inc:QI (reg:QI 20)))
         (match_operand:HF 0 "reg_operand" "h"))]
  ""
   [(set (mem:QF (pre_inc:QI (reg:QI 20)))
         (float_truncate:QF (match_dup 0)))
    (set (mem:QI (pre_inc:QI (reg:QI 20)))
-        (unspec:QI [(match_dup 0)] 9))]
+        (unspec:QI [(match_dup 0)] UNSPEC_STOREHF_INT))]
  "")
 
 (define_insn "pushhf_trunc"
 
 (define_insn "pushhf_int"
   [(set (mem:QI (pre_inc:QI (reg:QI 20)))
-        (unspec:QI [(match_operand:HF 0 "reg_operand" "h")] 9))]
+        (unspec:QI [(match_operand:HF 0 "reg_operand" "h")] UNSPEC_STOREHF_INT))]
  ""
  "push\\t%0"
  [(set_attr "type" "push")])
 
-; we can not use this because the popf will destroy the low 8 bits
-;(define_insn "*pophf"
+; we cannot use this because the popf will destroy the low 8 bits
+;(define_insn "pophf"
 ;  [(set (match_operand:HF 0 "reg_operand" "=h")
 ;        (mem:HF (post_dec:QI (reg:QI 20))))
 ;   (clobber (reg:CC 21))]
               (clobber (reg:CC 21))])
    (parallel [(set (match_dup 0)
                    (unspec:HF [(subreg:QI (match_dup 0) 0)
-                   (mem:QI (post_dec:QI (reg:QI 20)))] 8))
+                   (mem:QI (post_dec:QI (reg:QI 20)))] UNSPEC_LOADHF_INT))
               (clobber (reg:CC 21))])]
  "")
 
 (define_insn "*pophf_int"
- [(set (match_operand:HF 0 "reg_operand" "=h")
+ [(set (match_operand:HF 0 "reg_operand" "+h")
        (unspec:HF [(subreg:QI (match_dup 0) 0)
-                   (mem:QI (post_dec:QI (reg:QI 20)))] 8))
+                   (mem:QI (post_dec:QI (reg:QI 20)))] UNSPEC_LOADHF_INT))
   (clobber (reg:CC 21))]
  ""
- "@
-  pop\\t%0"
+ "pop\\t%0"
   [(set_attr "type" "pop")])
 
 (define_insn "*pophf_float"
        (float_extend:HF (mem:QF (post_dec:QI (reg:QI 20)))))
   (clobber (reg:CC 21))]
  ""
- "@
-  popf\\t%0"
-  [(set_attr "type" "unary")])
+ "popf\\t%0"
+  [(set_attr "type" "pop")])
 
 ;
 ; FIX
 ;
+(define_expand "fixuns_trunchfqi2"
+ [(parallel [(set (match_dup 2)
+                 (fix:QI (match_operand:HF 1 "reg_or_const_operand" "hH")))
+            (clobber (reg:CC 21))])
+  (parallel [(set (match_dup 3)
+                 (minus:HF (match_dup 1) (match_dup 5)))
+            (clobber (reg:CC_NOOV 21))])
+  (parallel [(set (reg:CC 21)
+                 (compare:CC (fix:QI (match_dup 3))
+                             (const_int 0)))
+            (set (match_dup 4)
+                 (fix:QI (match_dup 3)))])
+  (parallel [(set (match_dup 4) (unspec:QI [(match_dup 2)] UNSPEC_LDIV))
+             (use (reg:CC 21))])
+  (set (match_operand:QI 0 "reg_operand" "=r") (match_dup 4))]
+ ""
+ "operands[2] = gen_reg_rtx (QImode);
+  operands[3] = gen_reg_rtx (HFmode);
+  operands[4] = gen_reg_rtx (QImode);
+  operands[5] = gen_reg_rtx (HFmode);
+  emit_move_insn (operands[5], CONST_DOUBLE_ATOF (\"4294967296.0\", HFmode));")
+
+(define_expand "fix_trunchfqi2"
+  [(parallel [(set (match_dup 2)
+                   (fix:QI (match_operand:HF 1 "reg_or_const_operand" "")))
+              (clobber (reg:CC 21))])
+   (parallel [(set (match_dup 3) (neg:HF (match_dup 1)))
+              (clobber (reg:CC_NOOV 21))])
+   (parallel [(set (match_dup 4) (fix:QI (match_dup 3)))
+              (clobber (reg:CC 21))])
+   (parallel [(set (reg:CC_NOOV 21)
+                   (compare:CC_NOOV (neg:QI (match_dup 4)) (const_int 0)))
+              (set (match_dup 5) (neg:QI (match_dup 4)))])
+   (set (match_dup 2)
+        (if_then_else:QI (le (reg:CC 21) (const_int 0))
+                         (match_dup 5)
+                         (match_dup 2)))
+   (set (match_operand:QI 0 "reg_operand" "=r") (match_dup 2))]
+ ""
+ "if (TARGET_FAST_FIX)
+    {
+       emit_insn (gen_fixhfqi_clobber (operands[0], operands[1]));
+       DONE;
+    }
+  operands[2] = gen_reg_rtx (QImode);
+  operands[3] = gen_reg_rtx (HFmode);
+  operands[4] = gen_reg_rtx (QImode);
+  operands[5] = gen_reg_rtx (QImode);
+ ")
+
+(define_insn "*fixhfqi_set"
+  [(set (reg:CC 21)
+        (compare:CC (fix:QI (match_operand:HF 1 "reg_or_const_operand" "hH"))
+                    (const_int 0)))
+   (set (match_operand:QI 0 "ext_reg_operand" "=d")
+        (fix:QI (match_dup 1)))]
+ ""
+ "fix\\t%1,%0"
+  [(set_attr "type" "unarycc")])
+
 (define_insn "fixhfqi_clobber"
   [(set (match_operand:QI 0 "reg_operand" "=dc")
         (fix:QI (match_operand:HF 1 "reg_or_const_operand" "hH")))
  "fix\\t%1,%0"
   [(set_attr "type" "unarycc")])
 
+(define_expand "fix_trunchfhi2"
+  [(parallel [(set (match_operand:HI 0 "reg_operand" "")
+                   (fix:HI (match_operand:HF 1 "reg_operand" "")))
+              (clobber (reg:CC 21))])]
+  ""
+  "c4x_emit_libcall (fix_trunchfhi2_libfunc, FIX, HImode, HFmode, 2, operands);
+   DONE;")
+
+(define_expand "fixuns_trunchfhi2"
+  [(parallel [(set (match_operand:HI 0 "reg_operand" "")
+                   (unsigned_fix:HI (match_operand:HF 1 "reg_operand" "")))
+              (clobber (reg:CC 21))])]
+  ""
+  "c4x_emit_libcall (fixuns_trunchfhi2_libfunc, UNSIGNED_FIX, 
+                     HImode, HFmode, 2, operands);
+   DONE;")
+
 ;
 ; ABSF
 ;
 (define_expand "neghf2"
   [(parallel [(set (match_operand:HF 0 "reg_operand" "")
                    (neg:HF (match_operand:HF 1 "reg_or_const_operand" "")))
-              (clobber (reg:CC 21))])]
+              (clobber (reg:CC_NOOV 21))])]
 ""
 "")
 
 (define_insn "*neghf2_clobber"
   [(set (match_operand:HF 0 "reg_operand" "=h")
         (neg:HF (match_operand:HF 1 "reg_or_const_operand" "hH")))
-   (clobber (reg:CC 21))]
+   (clobber (reg:CC_NOOV 21))]
   ""
   "negf\\t%1,%0"
   [(set_attr "type" "unarycc")])
 
 (define_insn "*neghf2_test"
-  [(set (reg:CC 21)
-        (compare:CC (neg:HF (match_operand:HF 1 "reg_or_const_operand" "hH"))
-                    (match_operand:HF 2 "fp_zero_operand" "G")))
+  [(set (reg:CC_NOOV 21)
+        (compare:CC_NOOV (neg:HF (match_operand:HF 1 "reg_or_const_operand" "hH"))
+                         (match_operand:HF 2 "fp_zero_operand" "G")))
    (clobber (match_scratch:HF 0 "=h"))]
   ""
   "negf\\t%1,%0"
   [(set_attr "type" "unarycc")])
 
 (define_insn "*neghf2_set"
-  [(set (reg:CC 21)
-        (compare:CC (neg:HF (match_operand:HF 1 "reg_or_const_operand" "hH"))
-                    (match_operand:HF 2 "fp_zero_operand" "G")))
+  [(set (reg:CC_NOOV 21)
+        (compare:CC_NOOV (neg:HF (match_operand:HF 1 "reg_or_const_operand" "hH"))
+                         (match_operand:HF 2 "fp_zero_operand" "G")))
    (set (match_operand:HF 0 "reg_operand" "=h")
         (neg:HF (match_dup 1)))]
   ""
 ;
 (define_insn "*rcpfhf_clobber"
   [(set (match_operand:HF 0 "reg_operand" "=h")
-        (unspec:HF [(match_operand:HF 1 "reg_or_const_operand" "hH")] 5))
+        (unspec:HF [(match_operand:HF 1 "reg_or_const_operand" "hH")] UNSPEC_RCPF))
    (clobber (reg:CC_NOOV 21))]
   "! TARGET_C3X"
   "rcpf\\t%1,%0"
 ;
 (define_insn "*rsqrfhf_clobber"
   [(set (match_operand:HF 0 "reg_operand" "=h")
-        (unspec:HF [(match_operand:HF 1 "reg_or_const_operand" "hH")] 10))
+        (unspec:HF [(match_operand:HF 1 "reg_or_const_operand" "hH")] UNSPEC_RSQRF))
    (clobber (reg:CC_NOOV 21))]
   "! TARGET_C3X"
   "rsqrf\\t%1,%0"
 ;
 (define_insn "*rndhf_clobber"
   [(set (match_operand:HF 0 "reg_operand" "=h")
-        (unspec:HF [(match_operand:HF 1 "reg_or_const_operand" "hH")] 6))
+        (unspec:HF [(match_operand:HF 1 "reg_or_const_operand" "hH")] UNSPEC_RND))
    (clobber (reg:CC_NOOV 21))]
   "! TARGET_C3X"
   "rnd\\t%1,%0"
 ; Inlined float square root for C4x
 (define_expand "sqrthf2_inline"
   [(parallel [(set (match_dup 2)
-                  (unspec:HF [(match_operand:HF 1 "reg_operand" "")] 10))
+                  (unspec:HF [(match_operand:HF 1 "reg_operand" "")] UNSPEC_RSQRF))
              (clobber (reg:CC_NOOV 21))])
    (parallel [(set (match_dup 3) (mult:HF (match_dup 5) (match_dup 1)))
              (clobber (reg:CC_NOOV 21))])
   operands[2] = gen_reg_rtx (HFmode);
   operands[3] = gen_reg_rtx (HFmode);
   operands[4] = gen_reg_rtx (HFmode);
-  operands[5] = immed_real_const_1 (REAL_VALUE_ATOF (\"0.5\", HFmode), HFmode);
-  operands[6] = immed_real_const_1 (REAL_VALUE_ATOF (\"1.5\", HFmode), HFmode);
+  operands[5] = CONST_DOUBLE_ATOF (\"0.5\", HFmode);
+  operands[6] = CONST_DOUBLE_ATOF (\"1.5\", HFmode);
   ")
 
 
   "emit_insn (gen_sqrthf2_inline (operands[0], operands[1]));
    DONE;")
 
-
-(define_expand "fix_trunchfhi2"
-  [(parallel [(set (match_operand:HI 0 "reg_operand" "")
-                   (fix:HI (match_operand:HF 1 "reg_operand" "")))
-              (clobber (reg:CC 21))])]
-  ""
-  "c4x_emit_libcall (fix_trunchfhi2_libfunc, FIX, HImode, HFmode, 2, operands);
-   DONE;")
-
-(define_expand "fixuns_trunchfhi2"
-  [(parallel [(set (match_operand:HI 0 "reg_operand" "")
-                   (unsigned_fix:HI (match_operand:HF 1 "reg_operand" "")))
-              (clobber (reg:CC 21))])]
-  ""
-  "c4x_emit_libcall (fixuns_trunchfhi2_libfunc, UNSIGNED_FIX, 
-                     HImode, HFmode, 2, operands);
-   DONE;")
-
 ;
 ; THREE OPERAND LONG DOUBLE INSTRUCTIONS
 ;
 ;
 ; MULF
 ;
-; The C3x MPYF only uses 24 bit precision while the C4x uses 32 bit precison.
+; The C3x MPYF only uses 24-bit precision while the C4x uses 32-bit precision.
 ;
 (define_expand "mulhf3"
   [(parallel [(set (match_operand:HF 0 "reg_operand" "=h")
 ; Inlined float divide for C4x
 (define_expand "divhf3_inline"
   [(parallel [(set (match_dup 3)
-                  (unspec:HF [(match_operand:HF 2 "reg_operand" "")] 5))
+                  (unspec:HF [(match_operand:HF 2 "reg_operand" "")] UNSPEC_RCPF))
              (clobber (reg:CC_NOOV 21))])
    (parallel [(set (match_dup 4) (mult:HF (match_dup 2) (match_dup 3)))
              (clobber (reg:CC_NOOV 21))])
   [(set_attr "type" "multi")])
 
 (define_split
-  [(set (match_operand:HI 0 "reg_operand" "=?dc")
-        (sign_extend:HI (match_operand:QI 1 "src_operand" "rIm")))
+  [(set (match_operand:HI 0 "reg_operand" "")
+        (sign_extend:HI (match_operand:QI 1 "src_operand" "")))
    (clobber (reg:CC 21))]
   "reload_completed && TARGET_C3X"
   [(set (match_dup 2) (match_dup 1))
    operands[3] = c4x_operand_subword (operands[0], 1, 0, HImode);")
 
 (define_split
-  [(set (match_operand:HI 0 "reg_operand" "=?dc")
-        (sign_extend:HI (match_operand:QI 1 "src_operand" "rIm")))
+  [(set (match_operand:HI 0 "reg_operand" "")
+        (sign_extend:HI (match_operand:QI 1 "src_operand" "")))
    (clobber (reg:CC 21))]
   "reload_completed && ! TARGET_C3X"
   [(set (match_dup 2) (match_dup 1))
 
 (define_insn "zero_extendqihi2"
   [(set (match_operand:HI 0 "reg_operand" "=?dc")
-        (zero_extend:HI (match_operand:QI 1 "src_operand" "rIm")))
+        (zero_extend:HI (match_operand:QI 1 "nonimmediate_src_operand" "rm")))
    (clobber (reg:CC 21))]
   ""
   "#"
 ; If operand0 and operand1 are the same register we don't need
 ; the first set.
 (define_split
-  [(set (match_operand:HI 0 "reg_operand" "=?dc")
-        (zero_extend:HI (match_operand:QI 1 "src_operand" "rIm")))
+  [(set (match_operand:HI 0 "reg_operand" "")
+        (zero_extend:HI (match_operand:QI 1 "nonimmediate_src_operand" "")))
    (clobber (reg:CC 21))]
   "reload_completed"
   [(set (match_dup 2) (match_dup 1))
   /* If the shift count is greater than 32 this will do an arithmetic
      right shift.  However, we need a logical right shift.  */
   (parallel [(set (match_dup 9)
-                  (ashift:QI (match_dup 4) (unspec:QI [(match_dup 10)] 3)))
+                  (ashift:QI (match_dup 4) (unspec:QI [(match_dup 10)] UNSPEC_LSH)))
              (clobber (reg:CC 21))])
   (set (match_dup 6) (match_dup 8))
   (parallel [(set (match_dup 5)
    c4x_compare_op1 = operands[1];
    DONE;")
 
+(define_insn "*cmphi_cc"
+  [(set (reg:CC 21)
+        (compare:CC (match_operand:HI 0 "src_operand" "rR,rS<>")
+                    (match_operand:HI 1 "src_operand" "R,rS<>")))]
+  "valid_operands (COMPARE, operands, HImode)"
+  "#"
+  [(set_attr "type" "multi")])
+
+(define_insn "*cmphi_cc_noov"
+  [(set (reg:CC_NOOV 21)
+        (compare:CC_NOOV (match_operand:HI 0 "src_operand" "rR,rS<>")
+                         (match_operand:HI 1 "src_operand" "R,rS<>")))]
+  "valid_operands (COMPARE, operands, HImode)"
+  "#"
+  [(set_attr "type" "multi")])
+
 ; This works only before reload because we need 2 extra registers.
 ; Use unspec to avoid recursive split.
 (define_split
   "! reload_completed"
   [(parallel [(set (reg:CC 21)
                    (unspec:CC [(compare:CC (match_dup 0)
-                                           (match_dup 1))] 4))
+                                           (match_dup 1))] UNSPEC_CMPHI))
               (clobber (match_scratch:QI 2 ""))
              (clobber (match_scratch:QI 3 ""))])]
   "")
   "! reload_completed"
   [(parallel [(set (reg:CC_NOOV 21)
                    (unspec:CC_NOOV [(compare:CC_NOOV (match_dup 0)
-                                                     (match_dup 1))] 4))
+                                                     (match_dup 1))] UNSPEC_CMPHI))
               (clobber (match_scratch:QI 2 ""))
              (clobber (match_scratch:QI 3 ""))])]
   "")
 
 ; This is normally not used. The define splits above are used first.
+(define_split
+  [(set (reg:CC 21)
+        (compare:CC (match_operand:HI 0 "src_operand" "")
+                    (match_operand:HI 1 "src_operand" "")))]
+  "reload_completed"
+  [(parallel [(set (reg:CC 21)
+                   (compare:CC (match_dup 0) (match_dup 1)))
+              (use (reg:QI 20))])]
+  "")
+
+(define_split
+  [(set (reg:CC_NOOV 21)
+        (compare:CC_NOOV (match_operand:HI 0 "src_operand" "")
+                         (match_operand:HI 1 "src_operand" "")))]
+  "reload_completed"
+  [(parallel [(set (reg:CC_NOOV 21)
+                   (compare:CC_NOOV (match_dup 0) (match_dup 1)))
+              (use (reg:QI 20))])]
+  "")
+
 (define_insn "*cmphi"
   [(set (reg:CC 21)
         (compare:CC (match_operand:HI 0 "src_operand" "rR,rS<>")
-                    (match_operand:HI 1 "src_operand" "R,rS<>")))]
+                    (match_operand:HI 1 "src_operand" "R,rS<>")))
+   (use (reg:QI 20))]
   "valid_operands (COMPARE, operands, HImode)"
   "*
    {
 (define_insn "*cmphi_noov"
   [(set (reg:CC_NOOV 21)
         (compare:CC_NOOV (match_operand:HI 0 "src_operand" "rR,rS<>")
-                    (match_operand:HI 1 "src_operand" "R,rS<>")))]
+                         (match_operand:HI 1 "src_operand" "R,rS<>")))
+   (use (reg:QI 20))]
   "valid_operands (COMPARE, operands, HImode)"
   "*
    {
 (define_insn "cmphi_cc"
   [(set (reg:CC 21)
         (unspec:CC [(compare:CC (match_operand:HI 0 "src_operand" "rR,rS<>")
-                                (match_operand:HI 1 "src_operand" "R,rS<>"))] 4))
+                                (match_operand:HI 1 "src_operand" "R,rS<>"))] UNSPEC_CMPHI))
    (clobber (match_scratch:QI 2 "=&d,&d"))
    (clobber (match_scratch:QI 3 "=&c,&c"))]
   "valid_operands (COMPARE, operands, HImode)"
 (define_insn "cmphi_cc_noov"
   [(set (reg:CC_NOOV 21)
         (unspec:CC_NOOV [(compare:CC_NOOV (match_operand:HI 0 "src_operand" "rR,rS<>")
-                                     (match_operand:HI 1 "src_operand" "R,rS<>"))] 4))
+                                     (match_operand:HI 1 "src_operand" "R,rS<>"))] UNSPEC_CMPHI))
    (clobber (match_scratch:QI 2 "=&d,&d"))
    (clobber (match_scratch:QI 3 "=&c,&c"))]
   "valid_operands (COMPARE, operands, HImode)"
                             (match_operand:HI 2 "src_operand" "")))
               (clobber (reg:CC 21))])]
   ""
-  "c4x_emit_libcall3 (smul_optab->handlers[(int) HImode].libfunc,
+  "c4x_emit_libcall3 (optab_libfunc (smul_optab, HImode),
                      MULT, HImode, operands);
    DONE;")
 
      (set (match_dup 0)
           (plus:QI (match_dup 0)
                    (const_int -1)))
+     (use (reg:QI 20))
      (clobber (reg:CC_NOOV 21))])]
   "! c4x_label_conflict (insn, operands[2], operands[1])"
   "db%I3\\t%0,%l1\\n\\tb%3\\t%l2"
                     (match_operand:QI 1 "general_operand" ""))
               (clobber (reg:QI 31))])
    (return)]
-  "c4x_null_epilogue_p ()"
+  "c4x_null_epilogue_p ()"
   "*
    if (REG_P (operands[0]))
      return \"bu%#\\t%C0\";
                          (match_operand:QI 2 "general_operand" "")))
               (clobber (reg:QI 31))])
    (return)]
-  "c4x_null_epilogue_p ()"
+  "c4x_null_epilogue_p ()"
   "*
    if (REG_P (operands[1]))
      return \"bu%#\\t%C1\";
  "stf\\t%1,*%0++\\n\\tstf\\t%2,*%0++")
 
 
-; The following two peepholes remove an unecessary load
+; The following two peepholes remove an unnecessary load
 ; often found at the end of a function.  These peepholes
-; could be generalised to other binary operators.  They shouldn't
+; could be generalized to other binary operators.  They shouldn't
 ; be required if we run a post reload mop-up pass.
 (define_peephole
  [(parallel [(set (match_operand:QF 0 "ext_reg_operand" "")