OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gcc-4.2.2/] [gcc/] [config/] [mcore/] [mcore.md] - Diff between revs 154 and 816

Only display areas with differences | Details | Blame | View Log

Rev 154 Rev 816
;;  Machine description the Motorola MCore
;;  Machine description the Motorola MCore
;;  Copyright (C) 1993, 1999, 2000, 2004, 2005, 2007
;;  Copyright (C) 1993, 1999, 2000, 2004, 2005, 2007
;;  Free Software Foundation, Inc.
;;  Free Software Foundation, Inc.
;;  Contributed by Motorola.
;;  Contributed by Motorola.
;; This file is part of GCC.
;; This file is part of GCC.
;; GCC 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
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 3, or (at your option)
;; the Free Software Foundation; either version 3, or (at your option)
;; any later version.
;; any later version.
;; GCC 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
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;; GNU General Public License for more details.
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; You should have received a copy of the GNU General Public License
;; along with GCC; see the file COPYING3.  If not see
;; along with GCC; see the file COPYING3.  If not see
;; .
;; .
;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
;; -------------------------------------------------------------------------
;; -------------------------------------------------------------------------
;; Attributes
;; Attributes
;; -------------------------------------------------------------------------
;; -------------------------------------------------------------------------
; Target CPU.
; Target CPU.
(define_attr "type" "brcond,branch,jmp,load,store,move,alu,shift"
(define_attr "type" "brcond,branch,jmp,load,store,move,alu,shift"
  (const_string "alu"))
  (const_string "alu"))
;; If a branch destination is within -2048..2047 bytes away from the
;; If a branch destination is within -2048..2047 bytes away from the
;; instruction it can be 2 bytes long.  All other conditional branches
;; instruction it can be 2 bytes long.  All other conditional branches
;; are 10 bytes long, and all other unconditional branches are 8 bytes.
;; are 10 bytes long, and all other unconditional branches are 8 bytes.
;;
;;
;; the assembler handles the long-branch span case for us if we use
;; the assembler handles the long-branch span case for us if we use
;; the "jb*" mnemonics for jumps/branches. This pushes the span
;; the "jb*" mnemonics for jumps/branches. This pushes the span
;; calculations and the literal table placement into the assembler,
;; calculations and the literal table placement into the assembler,
;; where their interactions can be managed in a single place.
;; where their interactions can be managed in a single place.
;; All MCORE instructions are two bytes long.
;; All MCORE instructions are two bytes long.
(define_attr "length" "" (const_int 2))
(define_attr "length" "" (const_int 2))
;; Scheduling.  We only model a simple load latency.
;; Scheduling.  We only model a simple load latency.
(define_insn_reservation "any_insn" 1
(define_insn_reservation "any_insn" 1
                         (eq_attr "type" "!load")
                         (eq_attr "type" "!load")
                         "nothing")
                         "nothing")
(define_insn_reservation "memory" 2
(define_insn_reservation "memory" 2
                         (eq_attr "type" "load")
                         (eq_attr "type" "load")
                         "nothing")
                         "nothing")
(include "predicates.md")
(include "predicates.md")
;; -------------------------------------------------------------------------
;; -------------------------------------------------------------------------
;; Test and bit test
;; Test and bit test
;; -------------------------------------------------------------------------
;; -------------------------------------------------------------------------
(define_insn ""
(define_insn ""
  [(set (reg:SI 17)
  [(set (reg:SI 17)
        (sign_extract:SI (match_operand:SI 0 "mcore_arith_reg_operand" "r")
        (sign_extract:SI (match_operand:SI 0 "mcore_arith_reg_operand" "r")
                         (const_int 1)
                         (const_int 1)
                         (match_operand:SI 1 "mcore_literal_K_operand" "K")))]
                         (match_operand:SI 1 "mcore_literal_K_operand" "K")))]
  ""
  ""
  "btsti        %0,%1"
  "btsti        %0,%1"
  [(set_attr "type" "shift")])
  [(set_attr "type" "shift")])
(define_insn ""
(define_insn ""
  [(set (reg:SI 17)
  [(set (reg:SI 17)
        (zero_extract:SI (match_operand:SI 0 "mcore_arith_reg_operand" "r")
        (zero_extract:SI (match_operand:SI 0 "mcore_arith_reg_operand" "r")
                         (const_int 1)
                         (const_int 1)
                         (match_operand:SI 1 "mcore_literal_K_operand" "K")))]
                         (match_operand:SI 1 "mcore_literal_K_operand" "K")))]
  ""
  ""
  "btsti        %0,%1"
  "btsti        %0,%1"
  [(set_attr "type" "shift")])
  [(set_attr "type" "shift")])
;;; This is created by combine.
;;; This is created by combine.
(define_insn ""
(define_insn ""
  [(set (reg:CC 17)
  [(set (reg:CC 17)
        (ne:CC (zero_extract:SI (match_operand:SI 0 "mcore_arith_reg_operand" "r")
        (ne:CC (zero_extract:SI (match_operand:SI 0 "mcore_arith_reg_operand" "r")
                                (const_int 1)
                                (const_int 1)
                                (match_operand:SI 1 "mcore_literal_K_operand" "K"))
                                (match_operand:SI 1 "mcore_literal_K_operand" "K"))
               (const_int 0)))]
               (const_int 0)))]
  ""
  ""
  "btsti        %0,%1"
  "btsti        %0,%1"
  [(set_attr "type" "shift")])
  [(set_attr "type" "shift")])
;; Created by combine from conditional patterns below (see sextb/btsti rx,31)
;; Created by combine from conditional patterns below (see sextb/btsti rx,31)
(define_insn ""
(define_insn ""
  [(set (reg:CC 17)
  [(set (reg:CC 17)
        (ne:CC (lshiftrt:SI (match_operand:SI 0 "mcore_arith_reg_operand" "r")
        (ne:CC (lshiftrt:SI (match_operand:SI 0 "mcore_arith_reg_operand" "r")
                            (const_int 7))
                            (const_int 7))
               (const_int 0)))]
               (const_int 0)))]
  "GET_CODE(operands[0]) == SUBREG &&
  "GET_CODE(operands[0]) == SUBREG &&
      GET_MODE(SUBREG_REG(operands[0])) == QImode"
      GET_MODE(SUBREG_REG(operands[0])) == QImode"
  "btsti        %0,7"
  "btsti        %0,7"
  [(set_attr "type" "shift")])
  [(set_attr "type" "shift")])
(define_insn ""
(define_insn ""
  [(set (reg:CC 17)
  [(set (reg:CC 17)
        (ne:CC (lshiftrt:SI (match_operand:SI 0 "mcore_arith_reg_operand" "r")
        (ne:CC (lshiftrt:SI (match_operand:SI 0 "mcore_arith_reg_operand" "r")
                            (const_int 15))
                            (const_int 15))
               (const_int 0)))]
               (const_int 0)))]
  "GET_CODE(operands[0]) == SUBREG &&
  "GET_CODE(operands[0]) == SUBREG &&
      GET_MODE(SUBREG_REG(operands[0])) == HImode"
      GET_MODE(SUBREG_REG(operands[0])) == HImode"
  "btsti        %0,15"
  "btsti        %0,15"
  [(set_attr "type" "shift")])
  [(set_attr "type" "shift")])
(define_split
(define_split
  [(set (pc)
  [(set (pc)
        (if_then_else (ne (eq:CC (zero_extract:SI
        (if_then_else (ne (eq:CC (zero_extract:SI
                                  (match_operand:SI 0 "mcore_arith_reg_operand" "")
                                  (match_operand:SI 0 "mcore_arith_reg_operand" "")
                                  (const_int 1)
                                  (const_int 1)
                                  (match_operand:SI 1 "mcore_literal_K_operand" ""))
                                  (match_operand:SI 1 "mcore_literal_K_operand" ""))
                                 (const_int 0))
                                 (const_int 0))
                          (const_int 0))
                          (const_int 0))
                      (label_ref (match_operand 2 "" ""))
                      (label_ref (match_operand 2 "" ""))
                      (pc)))]
                      (pc)))]
  ""
  ""
  [(set (reg:CC 17)
  [(set (reg:CC 17)
        (zero_extract:SI (match_dup 0) (const_int 1) (match_dup 1)))
        (zero_extract:SI (match_dup 0) (const_int 1) (match_dup 1)))
   (set (pc) (if_then_else (eq (reg:CC 17) (const_int 0))
   (set (pc) (if_then_else (eq (reg:CC 17) (const_int 0))
                           (label_ref (match_dup 2))
                           (label_ref (match_dup 2))
                           (pc)))]
                           (pc)))]
  "")
  "")
(define_split
(define_split
  [(set (pc)
  [(set (pc)
        (if_then_else (eq (ne:CC (zero_extract:SI
        (if_then_else (eq (ne:CC (zero_extract:SI
                                  (match_operand:SI 0 "mcore_arith_reg_operand" "")
                                  (match_operand:SI 0 "mcore_arith_reg_operand" "")
                                  (const_int 1)
                                  (const_int 1)
                                  (match_operand:SI 1 "mcore_literal_K_operand" ""))
                                  (match_operand:SI 1 "mcore_literal_K_operand" ""))
                                 (const_int 0))
                                 (const_int 0))
                          (const_int 0))
                          (const_int 0))
                      (label_ref (match_operand 2 "" ""))
                      (label_ref (match_operand 2 "" ""))
                      (pc)))]
                      (pc)))]
  ""
  ""
  [(set (reg:CC 17)
  [(set (reg:CC 17)
        (zero_extract:SI (match_dup 0) (const_int 1) (match_dup 1)))
        (zero_extract:SI (match_dup 0) (const_int 1) (match_dup 1)))
   (set (pc) (if_then_else (eq (reg:CC 17) (const_int 0))
   (set (pc) (if_then_else (eq (reg:CC 17) (const_int 0))
                           (label_ref (match_dup 2))
                           (label_ref (match_dup 2))
                           (pc)))]
                           (pc)))]
  "")
  "")
;; XXX - disabled by nickc because it fails on libiberty/fnmatch.c
;; XXX - disabled by nickc because it fails on libiberty/fnmatch.c
;;
;;
;; ; Experimental - relax immediates for and, andn, or, and tst to allow
;; ; Experimental - relax immediates for and, andn, or, and tst to allow
;; ;    any immediate value (or an immediate at all -- or, andn, & tst).
;; ;    any immediate value (or an immediate at all -- or, andn, & tst).
;; ;    This is done to allow bit field masks to fold together in combine.
;; ;    This is done to allow bit field masks to fold together in combine.
;; ;    The reload phase will force the immediate into a register at the
;; ;    The reload phase will force the immediate into a register at the
;; ;    very end.  This helps in some cases, but hurts in others: we'd
;; ;    very end.  This helps in some cases, but hurts in others: we'd
;; ;    really like to cse these immediates.  However, there is a phase
;; ;    really like to cse these immediates.  However, there is a phase
;; ;    ordering problem here.  cse picks up individual masks and cse's
;; ;    ordering problem here.  cse picks up individual masks and cse's
;; ;    those, but not folded masks (cse happens before combine).  It's
;; ;    those, but not folded masks (cse happens before combine).  It's
;; ;    not clear what the best solution is because we really want cse
;; ;    not clear what the best solution is because we really want cse
;; ;    before combine (leaving the bit field masks alone).   To pick up
;; ;    before combine (leaving the bit field masks alone).   To pick up
;; ;    relaxed immediates use -mrelax-immediates.  It might take some
;; ;    relaxed immediates use -mrelax-immediates.  It might take some
;; ;    experimenting to see which does better (i.e. regular imms vs.
;; ;    experimenting to see which does better (i.e. regular imms vs.
;; ;    arbitrary imms) for a particular code.   BRC
;; ;    arbitrary imms) for a particular code.   BRC
;;
;;
;; (define_insn ""
;; (define_insn ""
;;   [(set (reg:CC 17)
;;   [(set (reg:CC 17)
;;      (ne:CC (and:SI (match_operand:SI 0 "mcore_arith_reg_operand" "r")
;;      (ne:CC (and:SI (match_operand:SI 0 "mcore_arith_reg_operand" "r")
;;                     (match_operand:SI 1 "mcore_arith_any_imm_operand" "rI"))
;;                     (match_operand:SI 1 "mcore_arith_any_imm_operand" "rI"))
;;             (const_int 0)))]
;;             (const_int 0)))]
;;   "TARGET_RELAX_IMM"
;;   "TARGET_RELAX_IMM"
;;   "tst       %0,%1")
;;   "tst       %0,%1")
;;
;;
;; (define_insn ""
;; (define_insn ""
;;   [(set (reg:CC 17)
;;   [(set (reg:CC 17)
;;      (ne:CC (and:SI (match_operand:SI 0 "mcore_arith_reg_operand" "r")
;;      (ne:CC (and:SI (match_operand:SI 0 "mcore_arith_reg_operand" "r")
;;                     (match_operand:SI 1 "mcore_arith_M_operand" "r"))
;;                     (match_operand:SI 1 "mcore_arith_M_operand" "r"))
;;             (const_int 0)))]
;;             (const_int 0)))]
;;   "!TARGET_RELAX_IMM"
;;   "!TARGET_RELAX_IMM"
;;   "tst       %0,%1")
;;   "tst       %0,%1")
(define_insn ""
(define_insn ""
  [(set (reg:CC 17)
  [(set (reg:CC 17)
        (ne:CC (and:SI (match_operand:SI 0 "mcore_arith_reg_operand" "r")
        (ne:CC (and:SI (match_operand:SI 0 "mcore_arith_reg_operand" "r")
                       (match_operand:SI 1 "mcore_arith_M_operand" "r"))
                       (match_operand:SI 1 "mcore_arith_M_operand" "r"))
               (const_int 0)))]
               (const_int 0)))]
  ""
  ""
  "tst  %0,%1")
  "tst  %0,%1")
(define_split
(define_split
  [(parallel[
  [(parallel[
      (set (reg:CC 17)
      (set (reg:CC 17)
           (ne:CC (ne:SI (leu:CC (match_operand:SI 0 "mcore_arith_reg_operand" "r")
           (ne:CC (ne:SI (leu:CC (match_operand:SI 0 "mcore_arith_reg_operand" "r")
                                 (match_operand:SI 1 "mcore_arith_reg_operand" "r"))
                                 (match_operand:SI 1 "mcore_arith_reg_operand" "r"))
                         (const_int 0))
                         (const_int 0))
                  (const_int 0)))
                  (const_int 0)))
      (clobber (match_operand:CC 2 "mcore_arith_reg_operand" "=r"))])]
      (clobber (match_operand:CC 2 "mcore_arith_reg_operand" "=r"))])]
  ""
  ""
  [(set (reg:CC 17) (ne:SI (match_dup 0) (const_int 0)))
  [(set (reg:CC 17) (ne:SI (match_dup 0) (const_int 0)))
   (set (reg:CC 17) (leu:CC (match_dup 0) (match_dup 1)))])
   (set (reg:CC 17) (leu:CC (match_dup 0) (match_dup 1)))])
;; -------------------------------------------------------------------------
;; -------------------------------------------------------------------------
;; SImode signed integer comparisons
;; SImode signed integer comparisons
;; -------------------------------------------------------------------------
;; -------------------------------------------------------------------------
(define_insn "decne_t"
(define_insn "decne_t"
  [(set (reg:CC 17) (ne:CC (plus:SI (match_operand:SI 0 "mcore_arith_reg_operand" "+r")
  [(set (reg:CC 17) (ne:CC (plus:SI (match_operand:SI 0 "mcore_arith_reg_operand" "+r")
                                    (const_int -1))
                                    (const_int -1))
                           (const_int 0)))
                           (const_int 0)))
   (set (match_dup 0)
   (set (match_dup 0)
        (plus:SI (match_dup 0)
        (plus:SI (match_dup 0)
                 (const_int -1)))]
                 (const_int -1)))]
  ""
  ""
  "decne        %0")
  "decne        %0")
;; The combiner seems to prefer the following to the former.
;; The combiner seems to prefer the following to the former.
;;
;;
(define_insn ""
(define_insn ""
  [(set (reg:CC 17) (ne:CC (match_operand:SI 0 "mcore_arith_reg_operand" "+r")
  [(set (reg:CC 17) (ne:CC (match_operand:SI 0 "mcore_arith_reg_operand" "+r")
                           (const_int 1)))
                           (const_int 1)))
   (set (match_dup 0)
   (set (match_dup 0)
        (plus:SI (match_dup 0)
        (plus:SI (match_dup 0)
                 (const_int -1)))]
                 (const_int -1)))]
  ""
  ""
  "decne        %0")
  "decne        %0")
(define_insn "cmpnesi_t"
(define_insn "cmpnesi_t"
  [(set (reg:CC 17) (ne:CC (match_operand:SI 0 "mcore_arith_reg_operand" "r")
  [(set (reg:CC 17) (ne:CC (match_operand:SI 0 "mcore_arith_reg_operand" "r")
                           (match_operand:SI 1 "mcore_arith_reg_operand" "r")))]
                           (match_operand:SI 1 "mcore_arith_reg_operand" "r")))]
  ""
  ""
  "cmpne        %0,%1")
  "cmpne        %0,%1")
(define_insn "cmpneisi_t"
(define_insn "cmpneisi_t"
  [(set (reg:CC 17) (ne:CC (match_operand:SI 0 "mcore_arith_reg_operand" "r")
  [(set (reg:CC 17) (ne:CC (match_operand:SI 0 "mcore_arith_reg_operand" "r")
                           (match_operand:SI 1 "mcore_arith_K_operand" "K")))]
                           (match_operand:SI 1 "mcore_arith_K_operand" "K")))]
  ""
  ""
  "cmpnei       %0,%1")
  "cmpnei       %0,%1")
(define_insn "cmpgtsi_t"
(define_insn "cmpgtsi_t"
  [(set (reg:CC 17) (gt:CC (match_operand:SI 0 "mcore_arith_reg_operand" "r")
  [(set (reg:CC 17) (gt:CC (match_operand:SI 0 "mcore_arith_reg_operand" "r")
                           (match_operand:SI 1 "mcore_arith_reg_operand" "r")))]
                           (match_operand:SI 1 "mcore_arith_reg_operand" "r")))]
  ""
  ""
  "cmplt        %1,%0")
  "cmplt        %1,%0")
(define_insn ""
(define_insn ""
  [(set (reg:CC 17) (gt:CC (plus:SI
  [(set (reg:CC 17) (gt:CC (plus:SI
                            (match_operand:SI 0 "mcore_arith_reg_operand" "+r")
                            (match_operand:SI 0 "mcore_arith_reg_operand" "+r")
                            (const_int -1))
                            (const_int -1))
                           (const_int 0)))
                           (const_int 0)))
   (set (match_dup 0) (plus:SI (match_dup 0) (const_int -1)))]
   (set (match_dup 0) (plus:SI (match_dup 0) (const_int -1)))]
  ""
  ""
  "decgt        %0")
  "decgt        %0")
(define_insn "cmpltsi_t"
(define_insn "cmpltsi_t"
  [(set (reg:CC 17) (lt:CC (match_operand:SI 0 "mcore_arith_reg_operand" "r")
  [(set (reg:CC 17) (lt:CC (match_operand:SI 0 "mcore_arith_reg_operand" "r")
                           (match_operand:SI 1 "mcore_arith_reg_operand" "r")))]
                           (match_operand:SI 1 "mcore_arith_reg_operand" "r")))]
  ""
  ""
  "cmplt        %0,%1")
  "cmplt        %0,%1")
; cmplti is 1-32
; cmplti is 1-32
(define_insn "cmpltisi_t"
(define_insn "cmpltisi_t"
  [(set (reg:CC 17) (lt:CC (match_operand:SI 0 "mcore_arith_reg_operand" "r")
  [(set (reg:CC 17) (lt:CC (match_operand:SI 0 "mcore_arith_reg_operand" "r")
                           (match_operand:SI 1 "mcore_arith_J_operand" "J")))]
                           (match_operand:SI 1 "mcore_arith_J_operand" "J")))]
  ""
  ""
  "cmplti       %0,%1")
  "cmplti       %0,%1")
; covers cmplti x,0
; covers cmplti x,0
(define_insn ""
(define_insn ""
  [(set (reg:CC 17) (lt:CC (match_operand:SI 0 "mcore_arith_reg_operand" "r")
  [(set (reg:CC 17) (lt:CC (match_operand:SI 0 "mcore_arith_reg_operand" "r")
                         (const_int 0)))]
                         (const_int 0)))]
  ""
  ""
  "btsti        %0,31")
  "btsti        %0,31")
(define_insn ""
(define_insn ""
  [(set (reg:CC 17) (lt:CC (plus:SI
  [(set (reg:CC 17) (lt:CC (plus:SI
                            (match_operand:SI 0 "mcore_arith_reg_operand" "+r")
                            (match_operand:SI 0 "mcore_arith_reg_operand" "+r")
                            (const_int -1))
                            (const_int -1))
                           (const_int 0)))
                           (const_int 0)))
   (set (match_dup 0) (plus:SI (match_dup 0) (const_int -1)))]
   (set (match_dup 0) (plus:SI (match_dup 0) (const_int -1)))]
  ""
  ""
  "declt        %0")
  "declt        %0")
;; -------------------------------------------------------------------------
;; -------------------------------------------------------------------------
;; SImode unsigned integer comparisons
;; SImode unsigned integer comparisons
;; -------------------------------------------------------------------------
;; -------------------------------------------------------------------------
(define_insn "cmpgeusi_t"
(define_insn "cmpgeusi_t"
  [(set (reg:CC 17) (geu:CC (match_operand:SI 0 "mcore_arith_reg_operand" "r")
  [(set (reg:CC 17) (geu:CC (match_operand:SI 0 "mcore_arith_reg_operand" "r")
                            (match_operand:SI 1 "mcore_arith_reg_operand" "r")))]
                            (match_operand:SI 1 "mcore_arith_reg_operand" "r")))]
  ""
  ""
  "cmphs        %0,%1")
  "cmphs        %0,%1")
(define_insn "cmpgeusi_0"
(define_insn "cmpgeusi_0"
  [(set (reg:CC 17) (geu:CC (match_operand:SI 0 "mcore_arith_reg_operand" "r")
  [(set (reg:CC 17) (geu:CC (match_operand:SI 0 "mcore_arith_reg_operand" "r")
                            (const_int 0)))]
                            (const_int 0)))]
  ""
  ""
  "cmpnei       %0, 0")
  "cmpnei       %0, 0")
(define_insn "cmpleusi_t"
(define_insn "cmpleusi_t"
  [(set (reg:CC 17) (leu:CC (match_operand:SI 0 "mcore_arith_reg_operand" "r")
  [(set (reg:CC 17) (leu:CC (match_operand:SI 0 "mcore_arith_reg_operand" "r")
                            (match_operand:SI 1 "mcore_arith_reg_operand" "r")))]
                            (match_operand:SI 1 "mcore_arith_reg_operand" "r")))]
  ""
  ""
  "cmphs        %1,%0")
  "cmphs        %1,%0")
;; We save the compare operands in the cmpxx patterns and use them when
;; We save the compare operands in the cmpxx patterns and use them when
;; we generate the branch.
;; we generate the branch.
;; We accept constants here, in case we can modify them to ones which
;; We accept constants here, in case we can modify them to ones which
;; are more efficient to load.  E.g. change 'x <= 62' to 'x < 63'.
;; are more efficient to load.  E.g. change 'x <= 62' to 'x < 63'.
(define_expand "cmpsi"
(define_expand "cmpsi"
  [(set (reg:CC 17) (compare:CC (match_operand:SI 0 "mcore_compare_operand" "")
  [(set (reg:CC 17) (compare:CC (match_operand:SI 0 "mcore_compare_operand" "")
                                (match_operand:SI 1 "nonmemory_operand" "")))]
                                (match_operand:SI 1 "nonmemory_operand" "")))]
  ""
  ""
  "
  "
{ arch_compare_op0 = operands[0];
{ arch_compare_op0 = operands[0];
  arch_compare_op1 = operands[1];
  arch_compare_op1 = operands[1];
  DONE;
  DONE;
}")
}")
;; -------------------------------------------------------------------------
;; -------------------------------------------------------------------------
;; Logical operations
;; Logical operations
;; -------------------------------------------------------------------------
;; -------------------------------------------------------------------------
;; Logical AND clearing a single bit.  andsi3 knows that we have this
;; Logical AND clearing a single bit.  andsi3 knows that we have this
;; pattern and allows the constant literal pass through.
;; pattern and allows the constant literal pass through.
;;
;;
;; RBE 2/97: don't need this pattern any longer...
;; RBE 2/97: don't need this pattern any longer...
;; RBE: I don't think we need both "S" and exact_log2() clauses.
;; RBE: I don't think we need both "S" and exact_log2() clauses.
;;(define_insn ""
;;(define_insn ""
;;  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r")
;;  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r")
;;      (and:SI (match_operand:SI 1 "mcore_arith_reg_operand" "%0")
;;      (and:SI (match_operand:SI 1 "mcore_arith_reg_operand" "%0")
;;              (match_operand:SI 2 "const_int_operand" "S")))]
;;              (match_operand:SI 2 "const_int_operand" "S")))]
;;  "mcore_arith_S_operand (operands[2])"
;;  "mcore_arith_S_operand (operands[2])"
;;  "bclri      %0,%Q2")
;;  "bclri      %0,%Q2")
;;
;;
(define_insn "andnsi3"
(define_insn "andnsi3"
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r")
        (and:SI (not:SI (match_operand:SI 1 "mcore_arith_reg_operand" "r"))
        (and:SI (not:SI (match_operand:SI 1 "mcore_arith_reg_operand" "r"))
                (match_operand:SI 2 "mcore_arith_reg_operand" "0")))]
                (match_operand:SI 2 "mcore_arith_reg_operand" "0")))]
  ""
  ""
  "andn %0,%1")
  "andn %0,%1")
(define_expand "andsi3"
(define_expand "andsi3"
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "")
        (and:SI (match_operand:SI 1 "mcore_arith_reg_operand" "")
        (and:SI (match_operand:SI 1 "mcore_arith_reg_operand" "")
                (match_operand:SI 2 "nonmemory_operand" "")))]
                (match_operand:SI 2 "nonmemory_operand" "")))]
  ""
  ""
  "
  "
{
{
  if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0
  if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0
      && ! mcore_arith_S_operand (operands[2]))
      && ! mcore_arith_S_operand (operands[2]))
    {
    {
      int not_value = ~ INTVAL (operands[2]);
      int not_value = ~ INTVAL (operands[2]);
      if (   CONST_OK_FOR_I (not_value)
      if (   CONST_OK_FOR_I (not_value)
          || CONST_OK_FOR_M (not_value)
          || CONST_OK_FOR_M (not_value)
          || CONST_OK_FOR_N (not_value))
          || CONST_OK_FOR_N (not_value))
        {
        {
          operands[2] = copy_to_mode_reg (SImode, GEN_INT (not_value));
          operands[2] = copy_to_mode_reg (SImode, GEN_INT (not_value));
          emit_insn (gen_andnsi3 (operands[0], operands[2], operands[1]));
          emit_insn (gen_andnsi3 (operands[0], operands[2], operands[1]));
          DONE;
          DONE;
        }
        }
    }
    }
  if (! mcore_arith_K_S_operand (operands[2], SImode))
  if (! mcore_arith_K_S_operand (operands[2], SImode))
    operands[2] = copy_to_mode_reg (SImode, operands[2]);
    operands[2] = copy_to_mode_reg (SImode, operands[2]);
}")
}")
(define_insn ""
(define_insn ""
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r,r,r,r")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r,r,r,r")
        (and:SI (match_operand:SI 1 "mcore_arith_reg_operand" "0,0,r,0")
        (and:SI (match_operand:SI 1 "mcore_arith_reg_operand" "0,0,r,0")
                (match_operand:SI 2 "mcore_arith_any_imm_operand" "r,K,0,S")))]
                (match_operand:SI 2 "mcore_arith_any_imm_operand" "r,K,0,S")))]
  "TARGET_RELAX_IMM"
  "TARGET_RELAX_IMM"
  "*
  "*
{
{
   switch (which_alternative)
   switch (which_alternative)
     {
     {
     case 0: return \"and       %0,%2\";
     case 0: return \"and       %0,%2\";
     case 1: return \"andi      %0,%2\";
     case 1: return \"andi      %0,%2\";
     case 2: return \"and       %0,%1\";
     case 2: return \"and       %0,%1\";
     /* case -1: return \"bclri %0,%Q2\";        will not happen */
     /* case -1: return \"bclri %0,%Q2\";        will not happen */
     case 3: return mcore_output_bclri (operands[0], INTVAL (operands[2]));
     case 3: return mcore_output_bclri (operands[0], INTVAL (operands[2]));
     default: gcc_unreachable ();
     default: gcc_unreachable ();
     }
     }
}")
}")
;; This was the old "S" which was "!(2^n)" */
;; This was the old "S" which was "!(2^n)" */
;; case -1: return \"bclri      %0,%Q2\";        will not happen */
;; case -1: return \"bclri      %0,%Q2\";        will not happen */
(define_insn ""
(define_insn ""
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r,r,r,r")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r,r,r,r")
        (and:SI (match_operand:SI 1 "mcore_arith_reg_operand" "0,0,r,0")
        (and:SI (match_operand:SI 1 "mcore_arith_reg_operand" "0,0,r,0")
                (match_operand:SI 2 "mcore_arith_K_S_operand" "r,K,0,S")))]
                (match_operand:SI 2 "mcore_arith_K_S_operand" "r,K,0,S")))]
  "!TARGET_RELAX_IMM"
  "!TARGET_RELAX_IMM"
  "*
  "*
{
{
   switch (which_alternative)
   switch (which_alternative)
     {
     {
     case 0: return \"and       %0,%2\";
     case 0: return \"and       %0,%2\";
     case 1: return \"andi      %0,%2\";
     case 1: return \"andi      %0,%2\";
     case 2: return \"and       %0,%1\";
     case 2: return \"and       %0,%1\";
     case 3: return mcore_output_bclri (operands[0], INTVAL (operands[2]));
     case 3: return mcore_output_bclri (operands[0], INTVAL (operands[2]));
     default: gcc_unreachable ();
     default: gcc_unreachable ();
     }
     }
}")
}")
;(define_insn "iorsi3"
;(define_insn "iorsi3"
;  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r")
;  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r")
;       (ior:SI (match_operand:SI 1 "mcore_arith_reg_operand" "%0")
;       (ior:SI (match_operand:SI 1 "mcore_arith_reg_operand" "%0")
;               (match_operand:SI 2 "mcore_arith_reg_operand" "r")))]
;               (match_operand:SI 2 "mcore_arith_reg_operand" "r")))]
;  ""
;  ""
;  "or  %0,%2")
;  "or  %0,%2")
; need an expand to resolve ambiguity betw. the two iors below.
; need an expand to resolve ambiguity betw. the two iors below.
(define_expand "iorsi3"
(define_expand "iorsi3"
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "")
        (ior:SI (match_operand:SI 1 "mcore_arith_reg_operand" "")
        (ior:SI (match_operand:SI 1 "mcore_arith_reg_operand" "")
                (match_operand:SI 2 "nonmemory_operand" "")))]
                (match_operand:SI 2 "nonmemory_operand" "")))]
  ""
  ""
  "
  "
{
{
   if (! mcore_arith_M_operand (operands[2], SImode))
   if (! mcore_arith_M_operand (operands[2], SImode))
      operands[2] = copy_to_mode_reg (SImode, operands[2]);
      operands[2] = copy_to_mode_reg (SImode, operands[2]);
}")
}")
(define_insn ""
(define_insn ""
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r,r,r")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r,r,r")
        (ior:SI (match_operand:SI 1 "mcore_arith_reg_operand" "%0,0,0")
        (ior:SI (match_operand:SI 1 "mcore_arith_reg_operand" "%0,0,0")
                (match_operand:SI 2 "mcore_arith_any_imm_operand" "r,M,T")))]
                (match_operand:SI 2 "mcore_arith_any_imm_operand" "r,M,T")))]
  "TARGET_RELAX_IMM"
  "TARGET_RELAX_IMM"
  "*
  "*
{
{
   switch (which_alternative)
   switch (which_alternative)
     {
     {
     case 0: return \"or        %0,%2\";
     case 0: return \"or        %0,%2\";
     case 1: return \"bseti     %0,%P2\";
     case 1: return \"bseti     %0,%P2\";
     case 2: return mcore_output_bseti (operands[0], INTVAL (operands[2]));
     case 2: return mcore_output_bseti (operands[0], INTVAL (operands[2]));
     default: gcc_unreachable ();
     default: gcc_unreachable ();
     }
     }
}")
}")
(define_insn ""
(define_insn ""
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r,r,r")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r,r,r")
        (ior:SI (match_operand:SI 1 "mcore_arith_reg_operand" "%0,0,0")
        (ior:SI (match_operand:SI 1 "mcore_arith_reg_operand" "%0,0,0")
                (match_operand:SI 2 "mcore_arith_M_operand" "r,M,T")))]
                (match_operand:SI 2 "mcore_arith_M_operand" "r,M,T")))]
  "!TARGET_RELAX_IMM"
  "!TARGET_RELAX_IMM"
  "*
  "*
{
{
   switch (which_alternative)
   switch (which_alternative)
     {
     {
     case 0: return \"or        %0,%2\";
     case 0: return \"or        %0,%2\";
     case 1: return \"bseti     %0,%P2\";
     case 1: return \"bseti     %0,%P2\";
     case 2: return mcore_output_bseti (operands[0], INTVAL (operands[2]));
     case 2: return mcore_output_bseti (operands[0], INTVAL (operands[2]));
     default: gcc_unreachable ();
     default: gcc_unreachable ();
     }
     }
}")
}")
;(define_insn ""
;(define_insn ""
;  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r")
;  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r")
;       (ior:SI (match_operand:SI 1 "mcore_arith_reg_operand" "0")
;       (ior:SI (match_operand:SI 1 "mcore_arith_reg_operand" "0")
;               (match_operand:SI 2 "const_int_operand" "M")))]
;               (match_operand:SI 2 "const_int_operand" "M")))]
;  "exact_log2 (INTVAL (operands[2])) >= 0"
;  "exact_log2 (INTVAL (operands[2])) >= 0"
;  "bseti       %0,%P2")
;  "bseti       %0,%P2")
;(define_insn ""
;(define_insn ""
;  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r")
;  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r")
;       (ior:SI (match_operand:SI 1 "mcore_arith_reg_operand" "0")
;       (ior:SI (match_operand:SI 1 "mcore_arith_reg_operand" "0")
;               (match_operand:SI 2 "const_int_operand" "i")))]
;               (match_operand:SI 2 "const_int_operand" "i")))]
;  "mcore_num_ones (INTVAL (operands[2])) < 3"
;  "mcore_num_ones (INTVAL (operands[2])) < 3"
;  "* return mcore_output_bseti (operands[0], INTVAL (operands[2]));")
;  "* return mcore_output_bseti (operands[0], INTVAL (operands[2]));")
(define_insn "xorsi3"
(define_insn "xorsi3"
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r")
        (xor:SI (match_operand:SI 1 "mcore_arith_reg_operand" "%0")
        (xor:SI (match_operand:SI 1 "mcore_arith_reg_operand" "%0")
                (match_operand:SI 2 "mcore_arith_reg_operand" "r")))]
                (match_operand:SI 2 "mcore_arith_reg_operand" "r")))]
  ""
  ""
  "xor  %0,%2")
  "xor  %0,%2")
; these patterns give better code then gcc invents if
; these patterns give better code then gcc invents if
; left to its own devices
; left to its own devices
(define_insn "anddi3"
(define_insn "anddi3"
  [(set (match_operand:DI 0 "mcore_arith_reg_operand" "=r")
  [(set (match_operand:DI 0 "mcore_arith_reg_operand" "=r")
        (and:DI (match_operand:DI 1 "mcore_arith_reg_operand" "%0")
        (and:DI (match_operand:DI 1 "mcore_arith_reg_operand" "%0")
                (match_operand:DI 2 "mcore_arith_reg_operand" "r")))]
                (match_operand:DI 2 "mcore_arith_reg_operand" "r")))]
  ""
  ""
  "and  %0,%2\;and      %R0,%R2"
  "and  %0,%2\;and      %R0,%R2"
  [(set_attr "length" "4")])
  [(set_attr "length" "4")])
(define_insn "iordi3"
(define_insn "iordi3"
  [(set (match_operand:DI 0 "mcore_arith_reg_operand" "=r")
  [(set (match_operand:DI 0 "mcore_arith_reg_operand" "=r")
        (ior:DI (match_operand:DI 1 "mcore_arith_reg_operand" "%0")
        (ior:DI (match_operand:DI 1 "mcore_arith_reg_operand" "%0")
                (match_operand:DI 2 "mcore_arith_reg_operand" "r")))]
                (match_operand:DI 2 "mcore_arith_reg_operand" "r")))]
  ""
  ""
  "or   %0,%2\;or       %R0,%R2"
  "or   %0,%2\;or       %R0,%R2"
  [(set_attr "length" "4")])
  [(set_attr "length" "4")])
(define_insn "xordi3"
(define_insn "xordi3"
  [(set (match_operand:DI 0 "mcore_arith_reg_operand" "=r")
  [(set (match_operand:DI 0 "mcore_arith_reg_operand" "=r")
        (xor:DI (match_operand:DI 1 "mcore_arith_reg_operand" "%0")
        (xor:DI (match_operand:DI 1 "mcore_arith_reg_operand" "%0")
                (match_operand:DI 2 "mcore_arith_reg_operand" "r")))]
                (match_operand:DI 2 "mcore_arith_reg_operand" "r")))]
  ""
  ""
  "xor  %0,%2\;xor      %R0,%R2"
  "xor  %0,%2\;xor      %R0,%R2"
  [(set_attr "length" "4")])
  [(set_attr "length" "4")])
;; -------------------------------------------------------------------------
;; -------------------------------------------------------------------------
;; Shifts and rotates
;; Shifts and rotates
;; -------------------------------------------------------------------------
;; -------------------------------------------------------------------------
;; Only allow these if the shift count is a convenient constant.
;; Only allow these if the shift count is a convenient constant.
(define_expand "rotlsi3"
(define_expand "rotlsi3"
  [(set (match_operand:SI            0 "mcore_arith_reg_operand" "")
  [(set (match_operand:SI            0 "mcore_arith_reg_operand" "")
        (rotate:SI (match_operand:SI 1 "mcore_arith_reg_operand" "")
        (rotate:SI (match_operand:SI 1 "mcore_arith_reg_operand" "")
                   (match_operand:SI 2 "nonmemory_operand" "")))]
                   (match_operand:SI 2 "nonmemory_operand" "")))]
  ""
  ""
  "if (! mcore_literal_K_operand (operands[2], SImode))
  "if (! mcore_literal_K_operand (operands[2], SImode))
         FAIL;
         FAIL;
  ")
  ")
;; We can only do constant rotates, which is what this pattern provides.
;; We can only do constant rotates, which is what this pattern provides.
;; The combiner will put it together for us when we do:
;; The combiner will put it together for us when we do:
;;      (x << N) | (x >> (32 - N))
;;      (x << N) | (x >> (32 - N))
(define_insn ""
(define_insn ""
  [(set (match_operand:SI              0 "mcore_arith_reg_operand" "=r")
  [(set (match_operand:SI              0 "mcore_arith_reg_operand" "=r")
        (rotate:SI (match_operand:SI   1 "mcore_arith_reg_operand"  "0")
        (rotate:SI (match_operand:SI   1 "mcore_arith_reg_operand"  "0")
                     (match_operand:SI 2 "mcore_literal_K_operand"  "K")))]
                     (match_operand:SI 2 "mcore_literal_K_operand"  "K")))]
  ""
  ""
  "rotli        %0,%2"
  "rotli        %0,%2"
  [(set_attr "type" "shift")])
  [(set_attr "type" "shift")])
(define_insn "ashlsi3"
(define_insn "ashlsi3"
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r,r")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r,r")
        (ashift:SI (match_operand:SI 1 "mcore_arith_reg_operand" "0,0")
        (ashift:SI (match_operand:SI 1 "mcore_arith_reg_operand" "0,0")
                   (match_operand:SI 2 "mcore_arith_K_operand_not_0" "r,K")))]
                   (match_operand:SI 2 "mcore_arith_K_operand_not_0" "r,K")))]
  ""
  ""
  "@
  "@
        lsl     %0,%2
        lsl     %0,%2
        lsli    %0,%2"
        lsli    %0,%2"
  [(set_attr "type" "shift")])
  [(set_attr "type" "shift")])
(define_insn ""
(define_insn ""
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r")
        (ashift:SI (const_int 1)
        (ashift:SI (const_int 1)
                   (match_operand:SI 1 "mcore_arith_reg_operand" "r")))]
                   (match_operand:SI 1 "mcore_arith_reg_operand" "r")))]
  ""
  ""
  "bgenr        %0,%1"
  "bgenr        %0,%1"
  [(set_attr "type" "shift")])
  [(set_attr "type" "shift")])
(define_insn "ashrsi3"
(define_insn "ashrsi3"
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r,r")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r,r")
        (ashiftrt:SI (match_operand:SI 1 "mcore_arith_reg_operand" "0,0")
        (ashiftrt:SI (match_operand:SI 1 "mcore_arith_reg_operand" "0,0")
                     (match_operand:SI 2 "mcore_arith_K_operand_not_0" "r,K")))]
                     (match_operand:SI 2 "mcore_arith_K_operand_not_0" "r,K")))]
  ""
  ""
  "@
  "@
        asr     %0,%2
        asr     %0,%2
        asri    %0,%2"
        asri    %0,%2"
  [(set_attr "type" "shift")])
  [(set_attr "type" "shift")])
(define_insn "lshrsi3"
(define_insn "lshrsi3"
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r,r")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r,r")
        (lshiftrt:SI (match_operand:SI 1 "mcore_arith_reg_operand" "0,0")
        (lshiftrt:SI (match_operand:SI 1 "mcore_arith_reg_operand" "0,0")
                     (match_operand:SI 2 "mcore_arith_K_operand_not_0" "r,K")))]
                     (match_operand:SI 2 "mcore_arith_K_operand_not_0" "r,K")))]
  ""
  ""
  "@
  "@
        lsr     %0,%2
        lsr     %0,%2
        lsri    %0,%2"
        lsri    %0,%2"
  [(set_attr "type" "shift")])
  [(set_attr "type" "shift")])
;(define_expand "ashldi3"
;(define_expand "ashldi3"
;  [(parallel[(set (match_operand:DI 0 "mcore_arith_reg_operand" "")
;  [(parallel[(set (match_operand:DI 0 "mcore_arith_reg_operand" "")
;                 (ashift:DI (match_operand:DI 1 "mcore_arith_reg_operand" "")
;                 (ashift:DI (match_operand:DI 1 "mcore_arith_reg_operand" "")
;                            (match_operand:DI 2 "immediate_operand" "")))
;                            (match_operand:DI 2 "immediate_operand" "")))
;
;
;            (clobber (reg:CC 17))])]
;            (clobber (reg:CC 17))])]
;
;
;  ""
;  ""
;  "
;  "
;{
;{
;  if (GET_CODE (operands[2]) != CONST_INT
;  if (GET_CODE (operands[2]) != CONST_INT
;      || INTVAL (operands[2]) != 1)
;      || INTVAL (operands[2]) != 1)
;    FAIL;
;    FAIL;
;}")
;}")
;
;
;(define_insn ""
;(define_insn ""
;  [(set (match_operand:DI 0 "mcore_arith_reg_operand" "=r")
;  [(set (match_operand:DI 0 "mcore_arith_reg_operand" "=r")
;       (ashift:DI (match_operand:DI 1 "mcore_arith_reg_operand" "0")
;       (ashift:DI (match_operand:DI 1 "mcore_arith_reg_operand" "0")
;                    (const_int 1)))
;                    (const_int 1)))
;   (clobber (reg:CC 17))]
;   (clobber (reg:CC 17))]
;  ""
;  ""
;  "lsli        %R0,0\;rotli    %0,0"
;  "lsli        %R0,0\;rotli    %0,0"
;  [(set_attr "length" "4") (set_attr "type" "shift")])
;  [(set_attr "length" "4") (set_attr "type" "shift")])
;; -------------------------------------------------------------------------
;; -------------------------------------------------------------------------
;; Index instructions
;; Index instructions
;; -------------------------------------------------------------------------
;; -------------------------------------------------------------------------
;; The second of each set of patterns is borrowed from the alpha.md file.
;; The second of each set of patterns is borrowed from the alpha.md file.
;; These variants of the above insns can occur if the second operand
;; These variants of the above insns can occur if the second operand
;; is the frame pointer.  This is a kludge, but there doesn't
;; is the frame pointer.  This is a kludge, but there doesn't
;; seem to be a way around it.  Only recognize them while reloading.
;; seem to be a way around it.  Only recognize them while reloading.
;; We must use reload_operand for some operands in case frame pointer
;; We must use reload_operand for some operands in case frame pointer
;; elimination put a MEM with invalid address there.  Otherwise,
;; elimination put a MEM with invalid address there.  Otherwise,
;; the result of the substitution will not match this pattern, and reload
;; the result of the substitution will not match this pattern, and reload
;; will not be able to correctly fix the result.
;; will not be able to correctly fix the result.
;; indexing longlongs or doubles (8 bytes)
;; indexing longlongs or doubles (8 bytes)
(define_insn "indexdi_t"
(define_insn "indexdi_t"
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r")
        (plus:SI (mult:SI (match_operand:SI 1 "mcore_arith_reg_operand" "r")
        (plus:SI (mult:SI (match_operand:SI 1 "mcore_arith_reg_operand" "r")
                          (const_int 8))
                          (const_int 8))
                 (match_operand:SI 2 "mcore_arith_reg_operand" "0")))]
                 (match_operand:SI 2 "mcore_arith_reg_operand" "0")))]
  ""
  ""
  "*
  "*
    if (! mcore_is_same_reg (operands[1], operands[2]))
    if (! mcore_is_same_reg (operands[1], operands[2]))
      {
      {
        output_asm_insn (\"ixw\\t%0,%1\", operands);
        output_asm_insn (\"ixw\\t%0,%1\", operands);
        output_asm_insn (\"ixw\\t%0,%1\", operands);
        output_asm_insn (\"ixw\\t%0,%1\", operands);
      }
      }
    else
    else
      {
      {
        output_asm_insn (\"ixh\\t%0,%1\", operands);
        output_asm_insn (\"ixh\\t%0,%1\", operands);
        output_asm_insn (\"ixh\\t%0,%1\", operands);
        output_asm_insn (\"ixh\\t%0,%1\", operands);
      }
      }
    return \"\";
    return \"\";
  "
  "
;; if operands[1] == operands[2], the first option above is wrong! -- dac
;; if operands[1] == operands[2], the first option above is wrong! -- dac
;; was this... -- dac
;; was this... -- dac
;; ixw  %0,%1\;ixw      %0,%1"
;; ixw  %0,%1\;ixw      %0,%1"
  [(set_attr "length" "4")])
  [(set_attr "length" "4")])
(define_insn ""
(define_insn ""
  [(set (match_operand:SI 0 "mcore_reload_operand" "=r,r,r")
  [(set (match_operand:SI 0 "mcore_reload_operand" "=r,r,r")
        (plus:SI (plus:SI (mult:SI (match_operand:SI 1 "mcore_reload_operand" "r,r,r")
        (plus:SI (plus:SI (mult:SI (match_operand:SI 1 "mcore_reload_operand" "r,r,r")
                                   (const_int 8))
                                   (const_int 8))
                          (match_operand:SI 2 "mcore_arith_reg_operand" "0,0,0"))
                          (match_operand:SI 2 "mcore_arith_reg_operand" "0,0,0"))
                 (match_operand:SI 3 "mcore_addsub_operand" "r,J,L")))]
                 (match_operand:SI 3 "mcore_addsub_operand" "r,J,L")))]
  "reload_in_progress"
  "reload_in_progress"
  "@
  "@
        ixw     %0,%1\;ixw      %0,%1\;addu     %0,%3
        ixw     %0,%1\;ixw      %0,%1\;addu     %0,%3
        ixw     %0,%1\;ixw      %0,%1\;addi     %0,%3
        ixw     %0,%1\;ixw      %0,%1\;addi     %0,%3
        ixw     %0,%1\;ixw      %0,%1\;subi     %0,%M3"
        ixw     %0,%1\;ixw      %0,%1\;subi     %0,%M3"
  [(set_attr "length" "6")])
  [(set_attr "length" "6")])
;; indexing longs (4 bytes)
;; indexing longs (4 bytes)
(define_insn "indexsi_t"
(define_insn "indexsi_t"
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r")
        (plus:SI (mult:SI (match_operand:SI 1 "mcore_arith_reg_operand" "r")
        (plus:SI (mult:SI (match_operand:SI 1 "mcore_arith_reg_operand" "r")
                          (const_int 4))
                          (const_int 4))
                 (match_operand:SI 2 "mcore_arith_reg_operand" "0")))]
                 (match_operand:SI 2 "mcore_arith_reg_operand" "0")))]
  ""
  ""
  "ixw  %0,%1")
  "ixw  %0,%1")
(define_insn ""
(define_insn ""
  [(set (match_operand:SI 0 "mcore_reload_operand" "=r,r,r")
  [(set (match_operand:SI 0 "mcore_reload_operand" "=r,r,r")
        (plus:SI (plus:SI (mult:SI (match_operand:SI 1 "mcore_reload_operand" "r,r,r")
        (plus:SI (plus:SI (mult:SI (match_operand:SI 1 "mcore_reload_operand" "r,r,r")
                                   (const_int 4))
                                   (const_int 4))
                          (match_operand:SI 2 "mcore_arith_reg_operand" "0,0,0"))
                          (match_operand:SI 2 "mcore_arith_reg_operand" "0,0,0"))
                 (match_operand:SI 3 "mcore_addsub_operand" "r,J,L")))]
                 (match_operand:SI 3 "mcore_addsub_operand" "r,J,L")))]
  "reload_in_progress"
  "reload_in_progress"
  "@
  "@
        ixw     %0,%1\;addu     %0,%3
        ixw     %0,%1\;addu     %0,%3
        ixw     %0,%1\;addi     %0,%3
        ixw     %0,%1\;addi     %0,%3
        ixw     %0,%1\;subi     %0,%M3"
        ixw     %0,%1\;subi     %0,%M3"
  [(set_attr "length" "4")])
  [(set_attr "length" "4")])
;; indexing shorts (2 bytes)
;; indexing shorts (2 bytes)
(define_insn "indexhi_t"
(define_insn "indexhi_t"
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r")
        (plus:SI (mult:SI (match_operand:SI 1 "mcore_arith_reg_operand" "r")
        (plus:SI (mult:SI (match_operand:SI 1 "mcore_arith_reg_operand" "r")
                          (const_int 2))
                          (const_int 2))
                 (match_operand:SI 2 "mcore_arith_reg_operand" "0")))]
                 (match_operand:SI 2 "mcore_arith_reg_operand" "0")))]
  ""
  ""
  "ixh  %0,%1")
  "ixh  %0,%1")
(define_insn ""
(define_insn ""
  [(set (match_operand:SI 0 "mcore_reload_operand" "=r,r,r")
  [(set (match_operand:SI 0 "mcore_reload_operand" "=r,r,r")
        (plus:SI (plus:SI (mult:SI (match_operand:SI 1 "mcore_reload_operand" "r,r,r")
        (plus:SI (plus:SI (mult:SI (match_operand:SI 1 "mcore_reload_operand" "r,r,r")
                                   (const_int 2))
                                   (const_int 2))
                          (match_operand:SI 2 "mcore_arith_reg_operand" "0,0,0"))
                          (match_operand:SI 2 "mcore_arith_reg_operand" "0,0,0"))
                 (match_operand:SI 3 "mcore_addsub_operand" "r,J,L")))]
                 (match_operand:SI 3 "mcore_addsub_operand" "r,J,L")))]
  "reload_in_progress"
  "reload_in_progress"
  "@
  "@
        ixh     %0,%1\;addu     %0,%3
        ixh     %0,%1\;addu     %0,%3
        ixh     %0,%1\;addi     %0,%3
        ixh     %0,%1\;addi     %0,%3
        ixh     %0,%1\;subi     %0,%M3"
        ixh     %0,%1\;subi     %0,%M3"
  [(set_attr "length" "4")])
  [(set_attr "length" "4")])
;;
;;
;; Other sizes may be handy for indexing.
;; Other sizes may be handy for indexing.
;; the tradeoffs to consider when adding these are
;; the tradeoffs to consider when adding these are
;;      code size, execution time [vs. mul it is easy to win],
;;      code size, execution time [vs. mul it is easy to win],
;;      and register pressure -- these patterns don't use an extra
;;      and register pressure -- these patterns don't use an extra
;;      register to build the offset from the base
;;      register to build the offset from the base
;;      and whether the compiler will not come up with some other idiom.
;;      and whether the compiler will not come up with some other idiom.
;;
;;
;; -------------------------------------------------------------------------
;; -------------------------------------------------------------------------
;; Addition, Subtraction instructions
;; Addition, Subtraction instructions
;; -------------------------------------------------------------------------
;; -------------------------------------------------------------------------
(define_expand "addsi3"
(define_expand "addsi3"
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "")
        (plus:SI (match_operand:SI 1 "mcore_arith_reg_operand" "")
        (plus:SI (match_operand:SI 1 "mcore_arith_reg_operand" "")
                 (match_operand:SI 2 "nonmemory_operand" "")))]
                 (match_operand:SI 2 "nonmemory_operand" "")))]
  ""
  ""
  "
  "
{
{
  extern int flag_omit_frame_pointer;
  extern int flag_omit_frame_pointer;
  /* If this is an add to the frame pointer, then accept it as is so
  /* If this is an add to the frame pointer, then accept it as is so
     that we can later fold in the fp/sp offset from frame pointer
     that we can later fold in the fp/sp offset from frame pointer
     elimination.  */
     elimination.  */
  if (flag_omit_frame_pointer
  if (flag_omit_frame_pointer
      && GET_CODE (operands[1]) == REG
      && GET_CODE (operands[1]) == REG
      && (REGNO (operands[1]) == VIRTUAL_STACK_VARS_REGNUM
      && (REGNO (operands[1]) == VIRTUAL_STACK_VARS_REGNUM
          || REGNO (operands[1]) == FRAME_POINTER_REGNUM))
          || REGNO (operands[1]) == FRAME_POINTER_REGNUM))
    {
    {
      emit_insn (gen_addsi3_fp (operands[0], operands[1], operands[2]));
      emit_insn (gen_addsi3_fp (operands[0], operands[1], operands[2]));
      DONE;
      DONE;
    }
    }
  /* Convert adds to subtracts if this makes loading the constant cheaper.
  /* Convert adds to subtracts if this makes loading the constant cheaper.
     But only if we are allowed to generate new pseudos.  */
     But only if we are allowed to generate new pseudos.  */
  if (! (reload_in_progress || reload_completed)
  if (! (reload_in_progress || reload_completed)
      && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < -32)
      && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < -32)
    {
    {
      int neg_value = - INTVAL (operands[2]);
      int neg_value = - INTVAL (operands[2]);
      if (   CONST_OK_FOR_I (neg_value)
      if (   CONST_OK_FOR_I (neg_value)
          || CONST_OK_FOR_M (neg_value)
          || CONST_OK_FOR_M (neg_value)
          || CONST_OK_FOR_N (neg_value))
          || CONST_OK_FOR_N (neg_value))
        {
        {
          operands[2] = copy_to_mode_reg (SImode, GEN_INT (neg_value));
          operands[2] = copy_to_mode_reg (SImode, GEN_INT (neg_value));
          emit_insn (gen_subsi3 (operands[0], operands[1], operands[2]));
          emit_insn (gen_subsi3 (operands[0], operands[1], operands[2]));
          DONE;
          DONE;
        }
        }
    }
    }
  if (! mcore_addsub_operand (operands[2], SImode))
  if (! mcore_addsub_operand (operands[2], SImode))
    operands[2] = copy_to_mode_reg (SImode, operands[2]);
    operands[2] = copy_to_mode_reg (SImode, operands[2]);
}")
}")
;; RBE: for some constants which are not in the range which allows
;; RBE: for some constants which are not in the range which allows
;; us to do a single operation, we will try a paired addi/addi instead
;; us to do a single operation, we will try a paired addi/addi instead
;; of a movi/addi. This relieves some register pressure at the expense
;; of a movi/addi. This relieves some register pressure at the expense
;; of giving away some potential constant reuse.
;; of giving away some potential constant reuse.
;;
;;
;; RBE 6/17/97: this didn't buy us anything, but I keep the pattern
;; RBE 6/17/97: this didn't buy us anything, but I keep the pattern
;; for later reference
;; for later reference
;;
;;
;; (define_insn "addsi3_i2"
;; (define_insn "addsi3_i2"
;;   [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r")
;;   [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r")
;;      (plus:SI (match_operand:SI 1 "mcore_arith_reg_operand" "%0")
;;      (plus:SI (match_operand:SI 1 "mcore_arith_reg_operand" "%0")
;;               (match_operand:SI 2 "const_int_operand" "g")))]
;;               (match_operand:SI 2 "const_int_operand" "g")))]
;;   "GET_CODE(operands[2]) == CONST_INT
;;   "GET_CODE(operands[2]) == CONST_INT
;;    && ((INTVAL (operands[2]) > 32 && INTVAL(operands[2]) <= 64)
;;    && ((INTVAL (operands[2]) > 32 && INTVAL(operands[2]) <= 64)
;;        || (INTVAL (operands[2]) < -32 && INTVAL(operands[2]) >= -64))"
;;        || (INTVAL (operands[2]) < -32 && INTVAL(operands[2]) >= -64))"
;;   "*
;;   "*
;; {
;; {
;;    int n = INTVAL(operands[2]);
;;    int n = INTVAL(operands[2]);
;;    if (n > 0)
;;    if (n > 0)
;;      {
;;      {
;;        operands[2] = GEN_INT(n - 32);
;;        operands[2] = GEN_INT(n - 32);
;;        return \"addi\\t%0,32\;addi\\t%0,%2\";
;;        return \"addi\\t%0,32\;addi\\t%0,%2\";
;;      }
;;      }
;;    else
;;    else
;;      {
;;      {
;;        n = (-n);
;;        n = (-n);
;;        operands[2] = GEN_INT(n - 32);
;;        operands[2] = GEN_INT(n - 32);
;;        return \"subi\\t%0,32\;subi\\t%0,%2\";
;;        return \"subi\\t%0,32\;subi\\t%0,%2\";
;;      }
;;      }
;; }"
;; }"
;;  [(set_attr "length" "4")])
;;  [(set_attr "length" "4")])
(define_insn "addsi3_i"
(define_insn "addsi3_i"
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r,r,r")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r,r,r")
        (plus:SI (match_operand:SI 1 "mcore_arith_reg_operand" "%0,0,0")
        (plus:SI (match_operand:SI 1 "mcore_arith_reg_operand" "%0,0,0")
                 (match_operand:SI 2 "mcore_addsub_operand" "r,J,L")))]
                 (match_operand:SI 2 "mcore_addsub_operand" "r,J,L")))]
  ""
  ""
  "@
  "@
        addu    %0,%2
        addu    %0,%2
        addi    %0,%2
        addi    %0,%2
        subi    %0,%M2")
        subi    %0,%M2")
;; This exists so that address computations based on the frame pointer
;; This exists so that address computations based on the frame pointer
;; can be folded in when frame pointer elimination occurs.  Ordinarily
;; can be folded in when frame pointer elimination occurs.  Ordinarily
;; this would be bad because it allows insns which would require reloading,
;; this would be bad because it allows insns which would require reloading,
;; but without it, we get multiple adds where one would do.
;; but without it, we get multiple adds where one would do.
(define_insn "addsi3_fp"
(define_insn "addsi3_fp"
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r,r,r")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r,r,r")
        (plus:SI (match_operand:SI 1 "mcore_arith_reg_operand" "%0,0,0")
        (plus:SI (match_operand:SI 1 "mcore_arith_reg_operand" "%0,0,0")
                 (match_operand:SI 2 "immediate_operand" "r,J,L")))]
                 (match_operand:SI 2 "immediate_operand" "r,J,L")))]
  "flag_omit_frame_pointer
  "flag_omit_frame_pointer
   && (reload_in_progress || reload_completed || REGNO (operands[1]) == FRAME_POINTER_REGNUM)"
   && (reload_in_progress || reload_completed || REGNO (operands[1]) == FRAME_POINTER_REGNUM)"
  "@
  "@
        addu    %0,%2
        addu    %0,%2
        addi    %0,%2
        addi    %0,%2
        subi    %0,%M2")
        subi    %0,%M2")
;; RBE: for some constants which are not in the range which allows
;; RBE: for some constants which are not in the range which allows
;; us to do a single operation, we will try a paired addi/addi instead
;; us to do a single operation, we will try a paired addi/addi instead
;; of a movi/addi. This relieves some register pressure at the expense
;; of a movi/addi. This relieves some register pressure at the expense
;; of giving away some potential constant reuse.
;; of giving away some potential constant reuse.
;;
;;
;; RBE 6/17/97: this didn't buy us anything, but I keep the pattern
;; RBE 6/17/97: this didn't buy us anything, but I keep the pattern
;; for later reference
;; for later reference
;;
;;
;; (define_insn "subsi3_i2"
;; (define_insn "subsi3_i2"
;;   [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r")
;;   [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r")
;;      (plus:SI (match_operand:SI 1 "mcore_arith_reg_operand" "%0")
;;      (plus:SI (match_operand:SI 1 "mcore_arith_reg_operand" "%0")
;;               (match_operand:SI 2 "const_int_operand" "g")))]
;;               (match_operand:SI 2 "const_int_operand" "g")))]
;;   "TARGET_RBETEST && GET_CODE(operands[2]) == CONST_INT
;;   "TARGET_RBETEST && GET_CODE(operands[2]) == CONST_INT
;;    && ((INTVAL (operands[2]) > 32 && INTVAL(operands[2]) <= 64)
;;    && ((INTVAL (operands[2]) > 32 && INTVAL(operands[2]) <= 64)
;;        || (INTVAL (operands[2]) < -32 && INTVAL(operands[2]) >= -64))"
;;        || (INTVAL (operands[2]) < -32 && INTVAL(operands[2]) >= -64))"
;;   "*
;;   "*
;; {
;; {
;;    int n = INTVAL(operands[2]);
;;    int n = INTVAL(operands[2]);
;;    if ( n > 0)
;;    if ( n > 0)
;;      {
;;      {
;;        operands[2] = GEN_INT( n - 32);
;;        operands[2] = GEN_INT( n - 32);
;;        return \"subi\\t%0,32\;subi\\t%0,%2\";
;;        return \"subi\\t%0,32\;subi\\t%0,%2\";
;;      }
;;      }
;;    else
;;    else
;;      {
;;      {
;;        n = (-n);
;;        n = (-n);
;;        operands[2] = GEN_INT(n - 32);
;;        operands[2] = GEN_INT(n - 32);
;;        return \"addi\\t%0,32\;addi\\t%0,%2\";
;;        return \"addi\\t%0,32\;addi\\t%0,%2\";
;;      }
;;      }
;; }"
;; }"
;;   [(set_attr "length" "4")])
;;   [(set_attr "length" "4")])
;(define_insn "subsi3"
;(define_insn "subsi3"
;  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r,r,r,r")
;  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r,r,r,r")
;       (minus:SI (match_operand:SI 1 "mcore_arith_K_operand" "0,0,r,K")
;       (minus:SI (match_operand:SI 1 "mcore_arith_K_operand" "0,0,r,K")
;                 (match_operand:SI 2 "mcore_arith_J_operand" "r,J,0,0")))]
;                 (match_operand:SI 2 "mcore_arith_J_operand" "r,J,0,0")))]
;  ""
;  ""
;  "@
;  "@
;       sub     %0,%2
;       sub     %0,%2
;       subi    %0,%2
;       subi    %0,%2
;       rsub    %0,%1
;       rsub    %0,%1
;       rsubi   %0,%1")
;       rsubi   %0,%1")
(define_insn "subsi3"
(define_insn "subsi3"
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r,r,r")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r,r,r")
        (minus:SI (match_operand:SI 1 "mcore_arith_reg_operand" "0,0,r")
        (minus:SI (match_operand:SI 1 "mcore_arith_reg_operand" "0,0,r")
                  (match_operand:SI 2 "mcore_arith_J_operand" "r,J,0")))]
                  (match_operand:SI 2 "mcore_arith_J_operand" "r,J,0")))]
  ""
  ""
  "@
  "@
        subu    %0,%2
        subu    %0,%2
        subi    %0,%2
        subi    %0,%2
        rsub    %0,%1")
        rsub    %0,%1")
(define_insn ""
(define_insn ""
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r")
        (minus:SI (match_operand:SI 1 "mcore_literal_K_operand" "K")
        (minus:SI (match_operand:SI 1 "mcore_literal_K_operand" "K")
                  (match_operand:SI 2 "mcore_arith_reg_operand" "0")))]
                  (match_operand:SI 2 "mcore_arith_reg_operand" "0")))]
  ""
  ""
  "rsubi        %0,%1")
  "rsubi        %0,%1")
(define_insn "adddi3"
(define_insn "adddi3"
  [(set (match_operand:DI 0 "mcore_arith_reg_operand" "=&r")
  [(set (match_operand:DI 0 "mcore_arith_reg_operand" "=&r")
        (plus:DI (match_operand:DI 1 "mcore_arith_reg_operand" "%0")
        (plus:DI (match_operand:DI 1 "mcore_arith_reg_operand" "%0")
                 (match_operand:DI 2 "mcore_arith_reg_operand" "r")))
                 (match_operand:DI 2 "mcore_arith_reg_operand" "r")))
   (clobber (reg:CC 17))]
   (clobber (reg:CC 17))]
  ""
  ""
  "*
  "*
  {
  {
    if (TARGET_LITTLE_END)
    if (TARGET_LITTLE_END)
      return \"cmplt    %0,%0\;addc     %0,%2\;addc     %R0,%R2\";
      return \"cmplt    %0,%0\;addc     %0,%2\;addc     %R0,%R2\";
    return \"cmplt      %R0,%R0\;addc   %R0,%R2\;addc   %0,%2\";
    return \"cmplt      %R0,%R0\;addc   %R0,%R2\;addc   %0,%2\";
  }"
  }"
  [(set_attr "length" "6")])
  [(set_attr "length" "6")])
;; special case for "longlong += 1"
;; special case for "longlong += 1"
(define_insn ""
(define_insn ""
  [(set (match_operand:DI 0 "mcore_arith_reg_operand" "=&r")
  [(set (match_operand:DI 0 "mcore_arith_reg_operand" "=&r")
        (plus:DI (match_operand:DI 1 "mcore_arith_reg_operand" "0")
        (plus:DI (match_operand:DI 1 "mcore_arith_reg_operand" "0")
                 (const_int 1)))
                 (const_int 1)))
   (clobber (reg:CC 17))]
   (clobber (reg:CC 17))]
  ""
  ""
  "*
  "*
  {
  {
   if (TARGET_LITTLE_END)
   if (TARGET_LITTLE_END)
      return \"addi     %0,1\;cmpnei %0,0\;incf %R0\";
      return \"addi     %0,1\;cmpnei %0,0\;incf %R0\";
    return \"addi       %R0,1\;cmpnei %R0,0\;incf       %0\";
    return \"addi       %R0,1\;cmpnei %R0,0\;incf       %0\";
  }"
  }"
  [(set_attr "length" "6")])
  [(set_attr "length" "6")])
;; special case for "longlong -= 1"
;; special case for "longlong -= 1"
(define_insn ""
(define_insn ""
  [(set (match_operand:DI 0 "mcore_arith_reg_operand" "=&r")
  [(set (match_operand:DI 0 "mcore_arith_reg_operand" "=&r")
        (plus:DI (match_operand:DI 1 "mcore_arith_reg_operand" "0")
        (plus:DI (match_operand:DI 1 "mcore_arith_reg_operand" "0")
                 (const_int -1)))
                 (const_int -1)))
   (clobber (reg:CC 17))]
   (clobber (reg:CC 17))]
  ""
  ""
  "*
  "*
  {
  {
    if (TARGET_LITTLE_END)
    if (TARGET_LITTLE_END)
       return \"cmpnei %0,0\;decf       %R0\;subi       %0,1\";
       return \"cmpnei %0,0\;decf       %R0\;subi       %0,1\";
    return \"cmpnei %R0,0\;decf %0\;subi        %R0,1\";
    return \"cmpnei %R0,0\;decf %0\;subi        %R0,1\";
  }"
  }"
  [(set_attr "length" "6")])
  [(set_attr "length" "6")])
;; special case for "longlong += const_int"
;; special case for "longlong += const_int"
;; we have to use a register for the const_int because we don't
;; we have to use a register for the const_int because we don't
;; have an unsigned compare immediate... only +/- 1 get to
;; have an unsigned compare immediate... only +/- 1 get to
;; play the no-extra register game because they compare with 0.
;; play the no-extra register game because they compare with 0.
;; This winds up working out for any literal that is synthesized
;; This winds up working out for any literal that is synthesized
;; with a single instruction. The more complicated ones look
;; with a single instruction. The more complicated ones look
;; like the get broken into subreg's to get initialized too soon
;; like the get broken into subreg's to get initialized too soon
;; for us to catch here. -- RBE 4/25/96
;; for us to catch here. -- RBE 4/25/96
;; only allow for-sure positive values.
;; only allow for-sure positive values.
(define_insn ""
(define_insn ""
  [(set (match_operand:DI 0 "mcore_arith_reg_operand" "=&r")
  [(set (match_operand:DI 0 "mcore_arith_reg_operand" "=&r")
        (plus:DI (match_operand:DI 1 "mcore_arith_reg_operand" "0")
        (plus:DI (match_operand:DI 1 "mcore_arith_reg_operand" "0")
                 (match_operand:SI 2 "const_int_operand" "r")))
                 (match_operand:SI 2 "const_int_operand" "r")))
   (clobber (reg:CC 17))]
   (clobber (reg:CC 17))]
  "GET_CODE (operands[2]) == CONST_INT
  "GET_CODE (operands[2]) == CONST_INT
   && INTVAL (operands[2]) > 0 && ! (INTVAL (operands[2]) & 0x80000000)"
   && INTVAL (operands[2]) > 0 && ! (INTVAL (operands[2]) & 0x80000000)"
  "*
  "*
{
{
  gcc_assert (GET_MODE (operands[2]) == SImode);
  gcc_assert (GET_MODE (operands[2]) == SImode);
  if (TARGET_LITTLE_END)
  if (TARGET_LITTLE_END)
    return \"addu       %0,%2\;cmphs    %0,%2\;incf     %R0\";
    return \"addu       %0,%2\;cmphs    %0,%2\;incf     %R0\";
  return \"addu %R0,%2\;cmphs   %R0,%2\;incf    %0\";
  return \"addu %R0,%2\;cmphs   %R0,%2\;incf    %0\";
}"
}"
  [(set_attr "length" "6")])
  [(set_attr "length" "6")])
;; optimize "long long" + "unsigned long"
;; optimize "long long" + "unsigned long"
;; won't trigger because of how the extension is expanded upstream.
;; won't trigger because of how the extension is expanded upstream.
;; (define_insn ""
;; (define_insn ""
;;   [(set (match_operand:DI 0 "mcore_arith_reg_operand" "=&r")
;;   [(set (match_operand:DI 0 "mcore_arith_reg_operand" "=&r")
;;      (plus:DI (match_operand:DI 1 "mcore_arith_reg_operand" "%0")
;;      (plus:DI (match_operand:DI 1 "mcore_arith_reg_operand" "%0")
;;               (zero_extend:DI (match_operand:SI 2 "mcore_arith_reg_operand" "r"))))
;;               (zero_extend:DI (match_operand:SI 2 "mcore_arith_reg_operand" "r"))))
;;    (clobber (reg:CC 17))]
;;    (clobber (reg:CC 17))]
;;   "0"
;;   "0"
;;   "cmplt     %R0,%R0\;addc   %R0,%2\;inct    %0"
;;   "cmplt     %R0,%R0\;addc   %R0,%2\;inct    %0"
;;   [(set_attr "length" "6")])
;;   [(set_attr "length" "6")])
;; optimize "long long" + "signed long"
;; optimize "long long" + "signed long"
;; won't trigger because of how the extension is expanded upstream.
;; won't trigger because of how the extension is expanded upstream.
;; (define_insn ""
;; (define_insn ""
;;   [(set (match_operand:DI 0 "mcore_arith_reg_operand" "=&r")
;;   [(set (match_operand:DI 0 "mcore_arith_reg_operand" "=&r")
;;      (plus:DI (match_operand:DI 1 "mcore_arith_reg_operand" "%0")
;;      (plus:DI (match_operand:DI 1 "mcore_arith_reg_operand" "%0")
;;               (sign_extend:DI (match_operand:SI 2 "mcore_arith_reg_operand" "r"))))
;;               (sign_extend:DI (match_operand:SI 2 "mcore_arith_reg_operand" "r"))))
;;    (clobber (reg:CC 17))]
;;    (clobber (reg:CC 17))]
;;   "0"
;;   "0"
;;   "cmplt     %R0,%R0\;addc   %R0,%2\;inct    %0\;btsti       %2,31\;dect     %0"
;;   "cmplt     %R0,%R0\;addc   %R0,%2\;inct    %0\;btsti       %2,31\;dect     %0"
;;   [(set_attr "length" "6")])
;;   [(set_attr "length" "6")])
(define_insn "subdi3"
(define_insn "subdi3"
  [(set (match_operand:DI 0 "mcore_arith_reg_operand" "=&r")
  [(set (match_operand:DI 0 "mcore_arith_reg_operand" "=&r")
        (minus:DI (match_operand:DI 1 "mcore_arith_reg_operand" "0")
        (minus:DI (match_operand:DI 1 "mcore_arith_reg_operand" "0")
                  (match_operand:DI 2 "mcore_arith_reg_operand" "r")))
                  (match_operand:DI 2 "mcore_arith_reg_operand" "r")))
   (clobber (reg:CC 17))]
   (clobber (reg:CC 17))]
  ""
  ""
  "*
  "*
  {
  {
    if (TARGET_LITTLE_END)
    if (TARGET_LITTLE_END)
      return \"cmphs    %0,%0\;subc     %0,%2\;subc     %R0,%R2\";
      return \"cmphs    %0,%0\;subc     %0,%2\;subc     %R0,%R2\";
    return \"cmphs      %R0,%R0\;subc   %R0,%R2\;subc   %0,%2\";
    return \"cmphs      %R0,%R0\;subc   %R0,%R2\;subc   %0,%2\";
  }"
  }"
  [(set_attr "length" "6")])
  [(set_attr "length" "6")])
;; -------------------------------------------------------------------------
;; -------------------------------------------------------------------------
;; Multiplication instructions
;; Multiplication instructions
;; -------------------------------------------------------------------------
;; -------------------------------------------------------------------------
(define_insn "mulsi3"
(define_insn "mulsi3"
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r")
        (mult:SI (match_operand:SI 1 "mcore_arith_reg_operand" "%0")
        (mult:SI (match_operand:SI 1 "mcore_arith_reg_operand" "%0")
                 (match_operand:SI 2 "mcore_arith_reg_operand" "r")))]
                 (match_operand:SI 2 "mcore_arith_reg_operand" "r")))]
  ""
  ""
  "mult %0,%2")
  "mult %0,%2")
;;
;;
;; 32/32 signed division -- added to the MCORE instruction set spring 1997
;; 32/32 signed division -- added to the MCORE instruction set spring 1997
;;
;;
;; Different constraints based on the architecture revision...
;; Different constraints based on the architecture revision...
;;
;;
(define_expand "divsi3"
(define_expand "divsi3"
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "")
        (div:SI (match_operand:SI 1 "mcore_arith_reg_operand" "")
        (div:SI (match_operand:SI 1 "mcore_arith_reg_operand" "")
                (match_operand:SI 2 "mcore_arith_reg_operand" "")))]
                (match_operand:SI 2 "mcore_arith_reg_operand" "")))]
  "TARGET_DIV"
  "TARGET_DIV"
  "")
  "")
;; MCORE Revision 1.50: restricts the divisor to be in r1. (6/97)
;; MCORE Revision 1.50: restricts the divisor to be in r1. (6/97)
;;
;;
(define_insn ""
(define_insn ""
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r")
        (div:SI (match_operand:SI 1 "mcore_arith_reg_operand" "0")
        (div:SI (match_operand:SI 1 "mcore_arith_reg_operand" "0")
                (match_operand:SI 2 "mcore_arith_reg_operand" "b")))]
                (match_operand:SI 2 "mcore_arith_reg_operand" "b")))]
  "TARGET_DIV"
  "TARGET_DIV"
  "divs %0,%2")
  "divs %0,%2")
;;
;;
;; 32/32 signed division -- added to the MCORE instruction set spring 1997
;; 32/32 signed division -- added to the MCORE instruction set spring 1997
;;
;;
;; Different constraints based on the architecture revision...
;; Different constraints based on the architecture revision...
;;
;;
(define_expand "udivsi3"
(define_expand "udivsi3"
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "")
        (udiv:SI (match_operand:SI 1 "mcore_arith_reg_operand" "")
        (udiv:SI (match_operand:SI 1 "mcore_arith_reg_operand" "")
                 (match_operand:SI 2 "mcore_arith_reg_operand" "")))]
                 (match_operand:SI 2 "mcore_arith_reg_operand" "")))]
  "TARGET_DIV"
  "TARGET_DIV"
  "")
  "")
;; MCORE Revision 1.50: restricts the divisor to be in r1. (6/97)
;; MCORE Revision 1.50: restricts the divisor to be in r1. (6/97)
(define_insn ""
(define_insn ""
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r")
        (udiv:SI (match_operand:SI 1 "mcore_arith_reg_operand" "0")
        (udiv:SI (match_operand:SI 1 "mcore_arith_reg_operand" "0")
                 (match_operand:SI 2 "mcore_arith_reg_operand" "b")))]
                 (match_operand:SI 2 "mcore_arith_reg_operand" "b")))]
  "TARGET_DIV"
  "TARGET_DIV"
  "divu %0,%2")
  "divu %0,%2")
;; -------------------------------------------------------------------------
;; -------------------------------------------------------------------------
;; Unary arithmetic
;; Unary arithmetic
;; -------------------------------------------------------------------------
;; -------------------------------------------------------------------------
(define_insn "negsi2"
(define_insn "negsi2"
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r")
        (neg:SI (match_operand:SI 1 "mcore_arith_reg_operand" "0")))]
        (neg:SI (match_operand:SI 1 "mcore_arith_reg_operand" "0")))]
  ""
  ""
  "*
  "*
{
{
   return \"rsubi       %0,0\";
   return \"rsubi       %0,0\";
}")
}")
(define_insn "abssi2"
(define_insn "abssi2"
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r")
        (abs:SI (match_operand:SI 1 "mcore_arith_reg_operand" "0")))]
        (abs:SI (match_operand:SI 1 "mcore_arith_reg_operand" "0")))]
  ""
  ""
  "abs  %0")
  "abs  %0")
(define_insn "negdi2"
(define_insn "negdi2"
  [(set (match_operand:DI 0 "mcore_arith_reg_operand" "=&r")
  [(set (match_operand:DI 0 "mcore_arith_reg_operand" "=&r")
        (neg:DI (match_operand:DI 1 "mcore_arith_reg_operand" "0")))
        (neg:DI (match_operand:DI 1 "mcore_arith_reg_operand" "0")))
   (clobber (reg:CC 17))]
   (clobber (reg:CC 17))]
  ""
  ""
  "*
  "*
{
{
   if (TARGET_LITTLE_END)
   if (TARGET_LITTLE_END)
     return \"cmpnei    %0,0\\n\\trsubi %0,0\\n\\tnot   %R0\\n\\tincf   %R0\";
     return \"cmpnei    %0,0\\n\\trsubi %0,0\\n\\tnot   %R0\\n\\tincf   %R0\";
   return \"cmpnei      %R0,0\\n\\trsubi        %R0,0\\n\\tnot  %0\\n\\tincf    %0\";
   return \"cmpnei      %R0,0\\n\\trsubi        %R0,0\\n\\tnot  %0\\n\\tincf    %0\";
}"
}"
  [(set_attr "length" "8")])
  [(set_attr "length" "8")])
(define_insn "one_cmplsi2"
(define_insn "one_cmplsi2"
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r")
        (not:SI (match_operand:SI 1 "mcore_arith_reg_operand" "0")))]
        (not:SI (match_operand:SI 1 "mcore_arith_reg_operand" "0")))]
  ""
  ""
  "not  %0")
  "not  %0")
;; -------------------------------------------------------------------------
;; -------------------------------------------------------------------------
;; Zero extension instructions
;; Zero extension instructions
;; -------------------------------------------------------------------------
;; -------------------------------------------------------------------------
(define_expand "zero_extendhisi2"
(define_expand "zero_extendhisi2"
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "")
        (zero_extend:SI (match_operand:HI 1 "mcore_arith_reg_operand" "")))]
        (zero_extend:SI (match_operand:HI 1 "mcore_arith_reg_operand" "")))]
  ""
  ""
  "")
  "")
(define_insn ""
(define_insn ""
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r,r")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r,r")
        (zero_extend:SI (match_operand:HI 1 "general_operand" "0,m")))]
        (zero_extend:SI (match_operand:HI 1 "general_operand" "0,m")))]
  ""
  ""
  "@
  "@
        zexth   %0
        zexth   %0
        ld.h    %0,%1"
        ld.h    %0,%1"
  [(set_attr "type" "shift,load")])
  [(set_attr "type" "shift,load")])
;; ldh gives us a free zero-extension. The combiner picks up on this.
;; ldh gives us a free zero-extension. The combiner picks up on this.
(define_insn ""
(define_insn ""
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r")
        (zero_extend:SI (mem:HI (match_operand:SI 1 "mcore_arith_reg_operand" "r"))))]
        (zero_extend:SI (mem:HI (match_operand:SI 1 "mcore_arith_reg_operand" "r"))))]
  ""
  ""
  "ld.h %0,(%1)"
  "ld.h %0,(%1)"
  [(set_attr "type" "load")])
  [(set_attr "type" "load")])
(define_insn ""
(define_insn ""
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r")
        (zero_extend:SI (mem:HI (plus:SI (match_operand:SI 1 "mcore_arith_reg_operand" "r")
        (zero_extend:SI (mem:HI (plus:SI (match_operand:SI 1 "mcore_arith_reg_operand" "r")
                                         (match_operand:SI 2 "const_int_operand" "")))))]
                                         (match_operand:SI 2 "const_int_operand" "")))))]
  "(INTVAL (operands[2]) >= 0) &&
  "(INTVAL (operands[2]) >= 0) &&
   (INTVAL (operands[2]) < 32) &&
   (INTVAL (operands[2]) < 32) &&
   ((INTVAL (operands[2])&1) == 0)"
   ((INTVAL (operands[2])&1) == 0)"
  "ld.h %0,(%1,%2)"
  "ld.h %0,(%1,%2)"
  [(set_attr "type" "load")])
  [(set_attr "type" "load")])
(define_expand "zero_extendqisi2"
(define_expand "zero_extendqisi2"
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "")
        (zero_extend:SI (match_operand:QI 1 "general_operand" "")))]
        (zero_extend:SI (match_operand:QI 1 "general_operand" "")))]
  ""
  ""
  "")
  "")
;; RBE: XXX: we don't recognize that the xtrb3 kills the CC register.
;; RBE: XXX: we don't recognize that the xtrb3 kills the CC register.
(define_insn ""
(define_insn ""
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r,b,r")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r,b,r")
        (zero_extend:SI (match_operand:QI 1 "general_operand" "0,r,m")))]
        (zero_extend:SI (match_operand:QI 1 "general_operand" "0,r,m")))]
  ""
  ""
  "@
  "@
        zextb   %0
        zextb   %0
        xtrb3   %0,%1
        xtrb3   %0,%1
        ld.b    %0,%1"
        ld.b    %0,%1"
  [(set_attr "type" "shift,shift,load")])
  [(set_attr "type" "shift,shift,load")])
;; ldb gives us a free zero-extension. The combiner picks up on this.
;; ldb gives us a free zero-extension. The combiner picks up on this.
(define_insn ""
(define_insn ""
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r")
        (zero_extend:SI (mem:QI (match_operand:SI 1 "mcore_arith_reg_operand" "r"))))]
        (zero_extend:SI (mem:QI (match_operand:SI 1 "mcore_arith_reg_operand" "r"))))]
  ""
  ""
  "ld.b %0,(%1)"
  "ld.b %0,(%1)"
  [(set_attr "type" "load")])
  [(set_attr "type" "load")])
(define_insn ""
(define_insn ""
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r")
        (zero_extend:SI (mem:QI (plus:SI (match_operand:SI 1 "mcore_arith_reg_operand" "r")
        (zero_extend:SI (mem:QI (plus:SI (match_operand:SI 1 "mcore_arith_reg_operand" "r")
                                         (match_operand:SI 2 "const_int_operand" "")))))]
                                         (match_operand:SI 2 "const_int_operand" "")))))]
  "(INTVAL (operands[2]) >= 0) &&
  "(INTVAL (operands[2]) >= 0) &&
   (INTVAL (operands[2]) < 16)"
   (INTVAL (operands[2]) < 16)"
  "ld.b %0,(%1,%2)"
  "ld.b %0,(%1,%2)"
  [(set_attr "type" "load")])
  [(set_attr "type" "load")])
(define_expand "zero_extendqihi2"
(define_expand "zero_extendqihi2"
  [(set (match_operand:HI 0 "mcore_arith_reg_operand" "")
  [(set (match_operand:HI 0 "mcore_arith_reg_operand" "")
        (zero_extend:HI (match_operand:QI 1 "general_operand" "")))]
        (zero_extend:HI (match_operand:QI 1 "general_operand" "")))]
  ""
  ""
  "")
  "")
;; RBE: XXX: we don't recognize that the xtrb3 kills the CC register.
;; RBE: XXX: we don't recognize that the xtrb3 kills the CC register.
(define_insn ""
(define_insn ""
  [(set (match_operand:HI 0 "mcore_arith_reg_operand" "=r,b,r")
  [(set (match_operand:HI 0 "mcore_arith_reg_operand" "=r,b,r")
        (zero_extend:HI (match_operand:QI 1 "general_operand" "0,r,m")))]
        (zero_extend:HI (match_operand:QI 1 "general_operand" "0,r,m")))]
  ""
  ""
  "@
  "@
        zextb   %0
        zextb   %0
        xtrb3   %0,%1
        xtrb3   %0,%1
        ld.b    %0,%1"
        ld.b    %0,%1"
  [(set_attr "type" "shift,shift,load")])
  [(set_attr "type" "shift,shift,load")])
;; ldb gives us a free zero-extension. The combiner picks up on this.
;; ldb gives us a free zero-extension. The combiner picks up on this.
;; this doesn't catch references that are into a structure.
;; this doesn't catch references that are into a structure.
;; note that normally the compiler uses the above insn, unless it turns
;; note that normally the compiler uses the above insn, unless it turns
;; out that we're dealing with a volatile...
;; out that we're dealing with a volatile...
(define_insn ""
(define_insn ""
  [(set (match_operand:HI 0 "mcore_arith_reg_operand" "=r")
  [(set (match_operand:HI 0 "mcore_arith_reg_operand" "=r")
        (zero_extend:HI (mem:QI (match_operand:SI 1 "mcore_arith_reg_operand" "r"))))]
        (zero_extend:HI (mem:QI (match_operand:SI 1 "mcore_arith_reg_operand" "r"))))]
  ""
  ""
  "ld.b %0,(%1)"
  "ld.b %0,(%1)"
  [(set_attr "type" "load")])
  [(set_attr "type" "load")])
(define_insn ""
(define_insn ""
  [(set (match_operand:HI 0 "mcore_arith_reg_operand" "=r")
  [(set (match_operand:HI 0 "mcore_arith_reg_operand" "=r")
        (zero_extend:HI (mem:QI (plus:SI (match_operand:SI 1 "mcore_arith_reg_operand" "r")
        (zero_extend:HI (mem:QI (plus:SI (match_operand:SI 1 "mcore_arith_reg_operand" "r")
                                         (match_operand:SI 2 "const_int_operand" "")))))]
                                         (match_operand:SI 2 "const_int_operand" "")))))]
  "(INTVAL (operands[2]) >= 0) &&
  "(INTVAL (operands[2]) >= 0) &&
   (INTVAL (operands[2]) < 16)"
   (INTVAL (operands[2]) < 16)"
  "ld.b %0,(%1,%2)"
  "ld.b %0,(%1,%2)"
  [(set_attr "type" "load")])
  [(set_attr "type" "load")])
;; -------------------------------------------------------------------------
;; -------------------------------------------------------------------------
;; Sign extension instructions
;; Sign extension instructions
;; -------------------------------------------------------------------------
;; -------------------------------------------------------------------------
(define_expand "extendsidi2"
(define_expand "extendsidi2"
  [(set (match_operand:DI 0 "mcore_arith_reg_operand" "=r")
  [(set (match_operand:DI 0 "mcore_arith_reg_operand" "=r")
        (match_operand:SI 1 "mcore_arith_reg_operand" "r"))]
        (match_operand:SI 1 "mcore_arith_reg_operand" "r"))]
  ""
  ""
  "
  "
  {
  {
    int low, high;
    int low, high;
    if (TARGET_LITTLE_END)
    if (TARGET_LITTLE_END)
      low = 0, high = 4;
      low = 0, high = 4;
    else
    else
      low = 4, high = 0;
      low = 4, high = 0;
    emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_SUBREG (SImode, operands[0], low),
    emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_SUBREG (SImode, operands[0], low),
              operands[1]));
              operands[1]));
    emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_SUBREG (SImode, operands[0], high),
    emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_SUBREG (SImode, operands[0], high),
              gen_rtx_ASHIFTRT (SImode,
              gen_rtx_ASHIFTRT (SImode,
                               gen_rtx_SUBREG (SImode, operands[0], low),
                               gen_rtx_SUBREG (SImode, operands[0], low),
                               GEN_INT (31))));
                               GEN_INT (31))));
    DONE;
    DONE;
  }"
  }"
)
)
(define_insn "extendhisi2"
(define_insn "extendhisi2"
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r")
        (sign_extend:SI (match_operand:HI 1 "mcore_arith_reg_operand" "0")))]
        (sign_extend:SI (match_operand:HI 1 "mcore_arith_reg_operand" "0")))]
  ""
  ""
  "sexth        %0")
  "sexth        %0")
(define_insn "extendqisi2"
(define_insn "extendqisi2"
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r")
        (sign_extend:SI (match_operand:QI 1 "mcore_arith_reg_operand" "0")))]
        (sign_extend:SI (match_operand:QI 1 "mcore_arith_reg_operand" "0")))]
  ""
  ""
  "sextb        %0")
  "sextb        %0")
(define_insn "extendqihi2"
(define_insn "extendqihi2"
  [(set (match_operand:HI 0 "mcore_arith_reg_operand" "=r")
  [(set (match_operand:HI 0 "mcore_arith_reg_operand" "=r")
        (sign_extend:HI (match_operand:QI 1 "mcore_arith_reg_operand" "0")))]
        (sign_extend:HI (match_operand:QI 1 "mcore_arith_reg_operand" "0")))]
  ""
  ""
  "sextb        %0")
  "sextb        %0")
;; -------------------------------------------------------------------------
;; -------------------------------------------------------------------------
;; Move instructions
;; Move instructions
;; -------------------------------------------------------------------------
;; -------------------------------------------------------------------------
;; SImode
;; SImode
(define_expand "movsi"
(define_expand "movsi"
  [(set (match_operand:SI 0 "general_operand" "")
  [(set (match_operand:SI 0 "general_operand" "")
        (match_operand:SI 1 "general_operand" ""))]
        (match_operand:SI 1 "general_operand" ""))]
  ""
  ""
  "
  "
{
{
  if (GET_CODE (operands[0]) == MEM)
  if (GET_CODE (operands[0]) == MEM)
    operands[1] = force_reg (SImode, operands[1]);
    operands[1] = force_reg (SImode, operands[1]);
}")
}")
(define_insn ""
(define_insn ""
  [(set (match_operand:SI 0 "mcore_general_movdst_operand" "=r,r,a,r,a,r,m")
  [(set (match_operand:SI 0 "mcore_general_movdst_operand" "=r,r,a,r,a,r,m")
        (match_operand:SI 1 "mcore_general_movsrc_operand"  "r,P,i,c,R,m,r"))]
        (match_operand:SI 1 "mcore_general_movsrc_operand"  "r,P,i,c,R,m,r"))]
  "(register_operand (operands[0], SImode)
  "(register_operand (operands[0], SImode)
    || register_operand (operands[1], SImode))"
    || register_operand (operands[1], SImode))"
  "* return mcore_output_move (insn, operands, SImode);"
  "* return mcore_output_move (insn, operands, SImode);"
  [(set_attr "type" "move,move,move,move,load,load,store")])
  [(set_attr "type" "move,move,move,move,load,load,store")])
;;
;;
;; HImode
;; HImode
;;
;;
(define_expand "movhi"
(define_expand "movhi"
  [(set (match_operand:HI 0 "general_operand" "")
  [(set (match_operand:HI 0 "general_operand" "")
        (match_operand:HI 1 "general_operand"  ""))]
        (match_operand:HI 1 "general_operand"  ""))]
  ""
  ""
  "
  "
{
{
  if (GET_CODE (operands[0]) == MEM)
  if (GET_CODE (operands[0]) == MEM)
    operands[1] = force_reg (HImode, operands[1]);
    operands[1] = force_reg (HImode, operands[1]);
  else if (CONSTANT_P (operands[1])
  else if (CONSTANT_P (operands[1])
           && (GET_CODE (operands[1]) != CONST_INT
           && (GET_CODE (operands[1]) != CONST_INT
               || (! CONST_OK_FOR_I (INTVAL (operands[1]))
               || (! CONST_OK_FOR_I (INTVAL (operands[1]))
                   && ! CONST_OK_FOR_M (INTVAL (operands[1]))
                   && ! CONST_OK_FOR_M (INTVAL (operands[1]))
                   && ! CONST_OK_FOR_N (INTVAL (operands[1]))))
                   && ! CONST_OK_FOR_N (INTVAL (operands[1]))))
           && ! reload_completed && ! reload_in_progress)
           && ! reload_completed && ! reload_in_progress)
    {
    {
      rtx reg = gen_reg_rtx (SImode);
      rtx reg = gen_reg_rtx (SImode);
      emit_insn (gen_movsi (reg, operands[1]));
      emit_insn (gen_movsi (reg, operands[1]));
      operands[1] = gen_lowpart (HImode, reg);
      operands[1] = gen_lowpart (HImode, reg);
    }
    }
}")
}")
(define_insn ""
(define_insn ""
  [(set (match_operand:HI 0 "mcore_general_movdst_operand" "=r,r,a,r,r,m")
  [(set (match_operand:HI 0 "mcore_general_movdst_operand" "=r,r,a,r,r,m")
        (match_operand:HI 1 "mcore_general_movsrc_operand"  "r,P,i,c,m,r"))]
        (match_operand:HI 1 "mcore_general_movsrc_operand"  "r,P,i,c,m,r"))]
  "(register_operand (operands[0], HImode)
  "(register_operand (operands[0], HImode)
    || register_operand (operands[1], HImode))"
    || register_operand (operands[1], HImode))"
  "* return mcore_output_move (insn, operands, HImode);"
  "* return mcore_output_move (insn, operands, HImode);"
  [(set_attr "type" "move,move,move,move,load,store")])
  [(set_attr "type" "move,move,move,move,load,store")])
;;
;;
;; QImode
;; QImode
;;
;;
(define_expand "movqi"
(define_expand "movqi"
  [(set (match_operand:QI 0 "general_operand" "")
  [(set (match_operand:QI 0 "general_operand" "")
        (match_operand:QI 1 "general_operand"  ""))]
        (match_operand:QI 1 "general_operand"  ""))]
  ""
  ""
  "
  "
{
{
  if (GET_CODE (operands[0]) == MEM)
  if (GET_CODE (operands[0]) == MEM)
    operands[1] = force_reg (QImode, operands[1]);
    operands[1] = force_reg (QImode, operands[1]);
  else if (CONSTANT_P (operands[1])
  else if (CONSTANT_P (operands[1])
           && (GET_CODE (operands[1]) != CONST_INT
           && (GET_CODE (operands[1]) != CONST_INT
               || (! CONST_OK_FOR_I (INTVAL (operands[1]))
               || (! CONST_OK_FOR_I (INTVAL (operands[1]))
                   && ! CONST_OK_FOR_M (INTVAL (operands[1]))
                   && ! CONST_OK_FOR_M (INTVAL (operands[1]))
                   && ! CONST_OK_FOR_N (INTVAL (operands[1]))))
                   && ! CONST_OK_FOR_N (INTVAL (operands[1]))))
           && ! reload_completed && ! reload_in_progress)
           && ! reload_completed && ! reload_in_progress)
    {
    {
      rtx reg = gen_reg_rtx (SImode);
      rtx reg = gen_reg_rtx (SImode);
      emit_insn (gen_movsi (reg, operands[1]));
      emit_insn (gen_movsi (reg, operands[1]));
      operands[1] = gen_lowpart (QImode, reg);
      operands[1] = gen_lowpart (QImode, reg);
    }
    }
}")
}")
(define_insn ""
(define_insn ""
  [(set (match_operand:QI 0 "mcore_general_movdst_operand" "=r,r,a,r,r,m")
  [(set (match_operand:QI 0 "mcore_general_movdst_operand" "=r,r,a,r,r,m")
        (match_operand:QI 1 "mcore_general_movsrc_operand"  "r,P,i,c,m,r"))]
        (match_operand:QI 1 "mcore_general_movsrc_operand"  "r,P,i,c,m,r"))]
  "(register_operand (operands[0], QImode)
  "(register_operand (operands[0], QImode)
    || register_operand (operands[1], QImode))"
    || register_operand (operands[1], QImode))"
  "* return mcore_output_move (insn, operands, QImode);"
  "* return mcore_output_move (insn, operands, QImode);"
   [(set_attr "type" "move,move,move,move,load,store")])
   [(set_attr "type" "move,move,move,move,load,store")])
;; DImode
;; DImode
(define_expand "movdi"
(define_expand "movdi"
  [(set (match_operand:DI 0 "general_operand" "")
  [(set (match_operand:DI 0 "general_operand" "")
        (match_operand:DI 1 "general_operand" ""))]
        (match_operand:DI 1 "general_operand" ""))]
  ""
  ""
  "
  "
{
{
  if (GET_CODE (operands[0]) == MEM)
  if (GET_CODE (operands[0]) == MEM)
    operands[1] = force_reg (DImode, operands[1]);
    operands[1] = force_reg (DImode, operands[1]);
  else if (GET_CODE (operands[1]) == CONST_INT
  else if (GET_CODE (operands[1]) == CONST_INT
           && ! CONST_OK_FOR_I (INTVAL (operands[1]))
           && ! CONST_OK_FOR_I (INTVAL (operands[1]))
           && ! CONST_OK_FOR_M (INTVAL (operands[1]))
           && ! CONST_OK_FOR_M (INTVAL (operands[1]))
           && ! CONST_OK_FOR_N (INTVAL (operands[1])))
           && ! CONST_OK_FOR_N (INTVAL (operands[1])))
    {
    {
      int i;
      int i;
      for (i = 0; i < UNITS_PER_WORD * 2; i += UNITS_PER_WORD)
      for (i = 0; i < UNITS_PER_WORD * 2; i += UNITS_PER_WORD)
        emit_move_insn (simplify_gen_subreg (SImode, operands[0], DImode, i),
        emit_move_insn (simplify_gen_subreg (SImode, operands[0], DImode, i),
                        simplify_gen_subreg (SImode, operands[1], DImode, i));
                        simplify_gen_subreg (SImode, operands[1], DImode, i));
      DONE;
      DONE;
    }
    }
}")
}")
(define_insn "movdi_i"
(define_insn "movdi_i"
  [(set (match_operand:DI 0 "general_operand" "=r,r,r,r,a,r,m")
  [(set (match_operand:DI 0 "general_operand" "=r,r,r,r,a,r,m")
        (match_operand:DI 1 "mcore_general_movsrc_operand" "I,M,N,r,R,m,r"))]
        (match_operand:DI 1 "mcore_general_movsrc_operand" "I,M,N,r,R,m,r"))]
  ""
  ""
  "* return mcore_output_movedouble (operands, DImode);"
  "* return mcore_output_movedouble (operands, DImode);"
  [(set_attr "length" "4") (set_attr "type" "move,move,move,move,load,load,store")])
  [(set_attr "length" "4") (set_attr "type" "move,move,move,move,load,load,store")])
;; SFmode
;; SFmode
(define_expand "movsf"
(define_expand "movsf"
  [(set (match_operand:SF 0 "general_operand" "")
  [(set (match_operand:SF 0 "general_operand" "")
        (match_operand:SF 1 "general_operand" ""))]
        (match_operand:SF 1 "general_operand" ""))]
  ""
  ""
  "
  "
{
{
  if (GET_CODE (operands[0]) == MEM)
  if (GET_CODE (operands[0]) == MEM)
    operands[1] = force_reg (SFmode, operands[1]);
    operands[1] = force_reg (SFmode, operands[1]);
}")
}")
(define_insn "movsf_i"
(define_insn "movsf_i"
  [(set (match_operand:SF 0 "general_operand" "=r,r,m")
  [(set (match_operand:SF 0 "general_operand" "=r,r,m")
        (match_operand:SF 1 "general_operand"  "r,m,r"))]
        (match_operand:SF 1 "general_operand"  "r,m,r"))]
  ""
  ""
  "@
  "@
        mov     %0,%1
        mov     %0,%1
        ld.w    %0,%1
        ld.w    %0,%1
        st.w    %1,%0"
        st.w    %1,%0"
  [(set_attr "type" "move,load,store")])
  [(set_attr "type" "move,load,store")])
;; DFmode
;; DFmode
(define_expand "movdf"
(define_expand "movdf"
  [(set (match_operand:DF 0 "general_operand" "")
  [(set (match_operand:DF 0 "general_operand" "")
        (match_operand:DF 1 "general_operand" ""))]
        (match_operand:DF 1 "general_operand" ""))]
  ""
  ""
  "
  "
{
{
  if (GET_CODE (operands[0]) == MEM)
  if (GET_CODE (operands[0]) == MEM)
    operands[1] = force_reg (DFmode, operands[1]);
    operands[1] = force_reg (DFmode, operands[1]);
}")
}")
(define_insn "movdf_k"
(define_insn "movdf_k"
  [(set (match_operand:DF 0 "general_operand" "=r,r,m")
  [(set (match_operand:DF 0 "general_operand" "=r,r,m")
        (match_operand:DF 1 "general_operand" "r,m,r"))]
        (match_operand:DF 1 "general_operand" "r,m,r"))]
  ""
  ""
  "* return mcore_output_movedouble (operands, DFmode);"
  "* return mcore_output_movedouble (operands, DFmode);"
  [(set_attr "length" "4") (set_attr "type" "move,load,store")])
  [(set_attr "length" "4") (set_attr "type" "move,load,store")])
;; Load/store multiple
;; Load/store multiple
;; ??? This is not currently used.
;; ??? This is not currently used.
(define_insn "ldm"
(define_insn "ldm"
  [(set (match_operand:TI 0 "mcore_arith_reg_operand" "=r")
  [(set (match_operand:TI 0 "mcore_arith_reg_operand" "=r")
        (mem:TI (match_operand:SI 1 "mcore_arith_reg_operand" "r")))]
        (mem:TI (match_operand:SI 1 "mcore_arith_reg_operand" "r")))]
  ""
  ""
  "ldq  %U0,(%1)")
  "ldq  %U0,(%1)")
;; ??? This is not currently used.
;; ??? This is not currently used.
(define_insn "stm"
(define_insn "stm"
  [(set (mem:TI (match_operand:SI 0 "mcore_arith_reg_operand" "r"))
  [(set (mem:TI (match_operand:SI 0 "mcore_arith_reg_operand" "r"))
        (match_operand:TI 1 "mcore_arith_reg_operand" "r"))]
        (match_operand:TI 1 "mcore_arith_reg_operand" "r"))]
  ""
  ""
  "stq  %U1,(%0)")
  "stq  %U1,(%0)")
(define_expand "load_multiple"
(define_expand "load_multiple"
  [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
  [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
                          (match_operand:SI 1 "" ""))
                          (match_operand:SI 1 "" ""))
                     (use (match_operand:SI 2 "" ""))])]
                     (use (match_operand:SI 2 "" ""))])]
  ""
  ""
  "
  "
{
{
  int regno, count, i;
  int regno, count, i;
  /* Support only loading a constant number of registers from memory and
  /* Support only loading a constant number of registers from memory and
     only if at least two registers.  The last register must be r15.  */
     only if at least two registers.  The last register must be r15.  */
  if (GET_CODE (operands[2]) != CONST_INT
  if (GET_CODE (operands[2]) != CONST_INT
      || INTVAL (operands[2]) < 2
      || INTVAL (operands[2]) < 2
      || GET_CODE (operands[1]) != MEM
      || GET_CODE (operands[1]) != MEM
      || XEXP (operands[1], 0) != stack_pointer_rtx
      || XEXP (operands[1], 0) != stack_pointer_rtx
      || GET_CODE (operands[0]) != REG
      || GET_CODE (operands[0]) != REG
      || REGNO (operands[0]) + INTVAL (operands[2]) != 16)
      || REGNO (operands[0]) + INTVAL (operands[2]) != 16)
    FAIL;
    FAIL;
  count = INTVAL (operands[2]);
  count = INTVAL (operands[2]);
  regno = REGNO (operands[0]);
  regno = REGNO (operands[0]);
  operands[3] = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count));
  operands[3] = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count));
  for (i = 0; i < count; i++)
  for (i = 0; i < count; i++)
    XVECEXP (operands[3], 0, i)
    XVECEXP (operands[3], 0, i)
      = gen_rtx_SET (VOIDmode,
      = gen_rtx_SET (VOIDmode,
                 gen_rtx_REG (SImode, regno + i),
                 gen_rtx_REG (SImode, regno + i),
                 gen_rtx_MEM (SImode, plus_constant (stack_pointer_rtx,
                 gen_rtx_MEM (SImode, plus_constant (stack_pointer_rtx,
                                                      i * 4)));
                                                      i * 4)));
}")
}")
(define_insn ""
(define_insn ""
  [(match_parallel 0 "mcore_load_multiple_operation"
  [(match_parallel 0 "mcore_load_multiple_operation"
                   [(set (match_operand:SI 1 "mcore_arith_reg_operand" "=r")
                   [(set (match_operand:SI 1 "mcore_arith_reg_operand" "=r")
                         (mem:SI (match_operand:SI 2 "register_operand" "r")))])]
                         (mem:SI (match_operand:SI 2 "register_operand" "r")))])]
  "GET_CODE (operands[2]) == REG && REGNO (operands[2]) == STACK_POINTER_REGNUM"
  "GET_CODE (operands[2]) == REG && REGNO (operands[2]) == STACK_POINTER_REGNUM"
  "ldm  %1-r15,(%2)")
  "ldm  %1-r15,(%2)")
(define_expand "store_multiple"
(define_expand "store_multiple"
  [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
  [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
                          (match_operand:SI 1 "" ""))
                          (match_operand:SI 1 "" ""))
                     (use (match_operand:SI 2 "" ""))])]
                     (use (match_operand:SI 2 "" ""))])]
  ""
  ""
  "
  "
{
{
  int regno, count, i;
  int regno, count, i;
  /* Support only storing a constant number of registers to memory and
  /* Support only storing a constant number of registers to memory and
     only if at least two registers.  The last register must be r15.  */
     only if at least two registers.  The last register must be r15.  */
  if (GET_CODE (operands[2]) != CONST_INT
  if (GET_CODE (operands[2]) != CONST_INT
      || INTVAL (operands[2]) < 2
      || INTVAL (operands[2]) < 2
      || GET_CODE (operands[0]) != MEM
      || GET_CODE (operands[0]) != MEM
      || XEXP (operands[0], 0) != stack_pointer_rtx
      || XEXP (operands[0], 0) != stack_pointer_rtx
      || GET_CODE (operands[1]) != REG
      || GET_CODE (operands[1]) != REG
      || REGNO (operands[1]) + INTVAL (operands[2]) != 16)
      || REGNO (operands[1]) + INTVAL (operands[2]) != 16)
    FAIL;
    FAIL;
  count = INTVAL (operands[2]);
  count = INTVAL (operands[2]);
  regno = REGNO (operands[1]);
  regno = REGNO (operands[1]);
  operands[3] = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count));
  operands[3] = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count));
  for (i = 0; i < count; i++)
  for (i = 0; i < count; i++)
    XVECEXP (operands[3], 0, i)
    XVECEXP (operands[3], 0, i)
      = gen_rtx_SET (VOIDmode,
      = gen_rtx_SET (VOIDmode,
                 gen_rtx_MEM (SImode, plus_constant (stack_pointer_rtx,
                 gen_rtx_MEM (SImode, plus_constant (stack_pointer_rtx,
                                                      i * 4)),
                                                      i * 4)),
                 gen_rtx_REG (SImode, regno + i));
                 gen_rtx_REG (SImode, regno + i));
}")
}")
(define_insn ""
(define_insn ""
  [(match_parallel 0 "mcore_store_multiple_operation"
  [(match_parallel 0 "mcore_store_multiple_operation"
                   [(set (mem:SI (match_operand:SI 2 "register_operand" "r"))
                   [(set (mem:SI (match_operand:SI 2 "register_operand" "r"))
                         (match_operand:SI 1 "mcore_arith_reg_operand" "r"))])]
                         (match_operand:SI 1 "mcore_arith_reg_operand" "r"))])]
  "GET_CODE (operands[2]) == REG && REGNO (operands[2]) == STACK_POINTER_REGNUM"
  "GET_CODE (operands[2]) == REG && REGNO (operands[2]) == STACK_POINTER_REGNUM"
  "stm  %1-r15,(%2)")
  "stm  %1-r15,(%2)")
;; ------------------------------------------------------------------------
;; ------------------------------------------------------------------------
;; Define the real conditional branch instructions.
;; Define the real conditional branch instructions.
;; ------------------------------------------------------------------------
;; ------------------------------------------------------------------------
(define_insn "branch_true"
(define_insn "branch_true"
  [(set (pc) (if_then_else (ne (reg:CC 17) (const_int 0))
  [(set (pc) (if_then_else (ne (reg:CC 17) (const_int 0))
                           (label_ref (match_operand 0 "" ""))
                           (label_ref (match_operand 0 "" ""))
                           (pc)))]
                           (pc)))]
  ""
  ""
  "jbt  %l0"
  "jbt  %l0"
  [(set_attr "type" "brcond")])
  [(set_attr "type" "brcond")])
(define_insn "branch_false"
(define_insn "branch_false"
  [(set (pc) (if_then_else (eq (reg:CC 17) (const_int 0))
  [(set (pc) (if_then_else (eq (reg:CC 17) (const_int 0))
                           (label_ref (match_operand 0 "" ""))
                           (label_ref (match_operand 0 "" ""))
                           (pc)))]
                           (pc)))]
  ""
  ""
  "jbf  %l0"
  "jbf  %l0"
  [(set_attr "type" "brcond")])
  [(set_attr "type" "brcond")])
(define_insn "inverse_branch_true"
(define_insn "inverse_branch_true"
  [(set (pc) (if_then_else (ne (reg:CC 17) (const_int 0))
  [(set (pc) (if_then_else (ne (reg:CC 17) (const_int 0))
                           (pc)
                           (pc)
                           (label_ref (match_operand 0 "" ""))))]
                           (label_ref (match_operand 0 "" ""))))]
  ""
  ""
  "jbf  %l0"
  "jbf  %l0"
  [(set_attr "type" "brcond")])
  [(set_attr "type" "brcond")])
(define_insn "inverse_branch_false"
(define_insn "inverse_branch_false"
  [(set (pc) (if_then_else (eq (reg:CC 17) (const_int 0))
  [(set (pc) (if_then_else (eq (reg:CC 17) (const_int 0))
                           (pc)
                           (pc)
                           (label_ref (match_operand 0 "" ""))))]
                           (label_ref (match_operand 0 "" ""))))]
  ""
  ""
  "jbt  %l0"
  "jbt  %l0"
  [(set_attr "type" "brcond")])
  [(set_attr "type" "brcond")])
;; Conditional branch insns
;; Conditional branch insns
;; At top-level, condition test are eq/ne, because we
;; At top-level, condition test are eq/ne, because we
;; are comparing against the condition register (which
;; are comparing against the condition register (which
;; has the result of the true relational test
;; has the result of the true relational test
; There is no beq compare, so we reverse the branch arms.
; There is no beq compare, so we reverse the branch arms.
(define_expand "beq"
(define_expand "beq"
  [(set (pc) (if_then_else (ne (match_dup 1) (const_int 0))
  [(set (pc) (if_then_else (ne (match_dup 1) (const_int 0))
                           (pc)
                           (pc)
                           (label_ref (match_operand 0 "" ""))))]
                           (label_ref (match_operand 0 "" ""))))]
  ""
  ""
  "
  "
{
{
  operands[1] = mcore_gen_compare_reg (EQ);
  operands[1] = mcore_gen_compare_reg (EQ);
}")
}")
(define_expand "bne"
(define_expand "bne"
  [(set (pc) (if_then_else (ne (match_dup 1) (const_int 0))
  [(set (pc) (if_then_else (ne (match_dup 1) (const_int 0))
                           (label_ref (match_operand 0 "" ""))
                           (label_ref (match_operand 0 "" ""))
                           (pc)))]
                           (pc)))]
  ""
  ""
  "
  "
{
{
  operands[1] = mcore_gen_compare_reg (NE);
  operands[1] = mcore_gen_compare_reg (NE);
}")
}")
; check whether (GT A imm) can become (LE A imm) with the branch reversed.
; check whether (GT A imm) can become (LE A imm) with the branch reversed.
; if so, emit a (LT A imm + 1) in place of the (LE A imm).  BRC
; if so, emit a (LT A imm + 1) in place of the (LE A imm).  BRC
(define_expand "bgt"
(define_expand "bgt"
  [(set (pc) (if_then_else (ne (match_dup 1) (const_int 0))
  [(set (pc) (if_then_else (ne (match_dup 1) (const_int 0))
                           (label_ref (match_operand 0 "" ""))
                           (label_ref (match_operand 0 "" ""))
                           (pc)))]
                           (pc)))]
  ""
  ""
  "
  "
{
{
  if (mcore_modify_comparison (LE))
  if (mcore_modify_comparison (LE))
    {
    {
      emit_jump_insn (gen_reverse_blt (operands[0]));
      emit_jump_insn (gen_reverse_blt (operands[0]));
      DONE;
      DONE;
    }
    }
  operands[1] = mcore_gen_compare_reg (GT);
  operands[1] = mcore_gen_compare_reg (GT);
}")
}")
; There is no ble compare, so we reverse the branch arms.
; There is no ble compare, so we reverse the branch arms.
; reversed the condition and branch arms for ble -- the check_dbra_loop()
; reversed the condition and branch arms for ble -- the check_dbra_loop()
; transformation assumes that ble uses a branch-true with the label as
; transformation assumes that ble uses a branch-true with the label as
; as the target. BRC
; as the target. BRC
; check whether (LE A imm) can become (LT A imm + 1).
; check whether (LE A imm) can become (LT A imm + 1).
(define_expand "ble"
(define_expand "ble"
  [(set (pc) (if_then_else (eq (match_dup 1) (const_int 0))
  [(set (pc) (if_then_else (eq (match_dup 1) (const_int 0))
                           (label_ref (match_operand 0 "" ""))
                           (label_ref (match_operand 0 "" ""))
                           (pc)))]
                           (pc)))]
  ""
  ""
  "
  "
{
{
  if (mcore_modify_comparison (LE))
  if (mcore_modify_comparison (LE))
    {
    {
      emit_jump_insn (gen_blt (operands[0]));
      emit_jump_insn (gen_blt (operands[0]));
      DONE;
      DONE;
    }
    }
  operands[1] = mcore_gen_compare_reg (LE);
  operands[1] = mcore_gen_compare_reg (LE);
}")
}")
; make generating a reversed blt simple
; make generating a reversed blt simple
(define_expand "reverse_blt"
(define_expand "reverse_blt"
  [(set (pc) (if_then_else (ne (match_dup 1) (const_int 0))
  [(set (pc) (if_then_else (ne (match_dup 1) (const_int 0))
                           (pc)
                           (pc)
                           (label_ref (match_operand 0 "" ""))))]
                           (label_ref (match_operand 0 "" ""))))]
  ""
  ""
  "
  "
{
{
  operands[1] = mcore_gen_compare_reg (LT);
  operands[1] = mcore_gen_compare_reg (LT);
}")
}")
(define_expand "blt"
(define_expand "blt"
  [(set (pc) (if_then_else (ne (match_dup 1) (const_int 0))
  [(set (pc) (if_then_else (ne (match_dup 1) (const_int 0))
                           (label_ref (match_operand 0 "" ""))
                           (label_ref (match_operand 0 "" ""))
                           (pc)))]
                           (pc)))]
  ""
  ""
  "
  "
{
{
  operands[1] = mcore_gen_compare_reg (LT);
  operands[1] = mcore_gen_compare_reg (LT);
}")
}")
; There is no bge compare, so we reverse the branch arms.
; There is no bge compare, so we reverse the branch arms.
(define_expand "bge"
(define_expand "bge"
  [(set (pc) (if_then_else (ne (match_dup 1) (const_int 0))
  [(set (pc) (if_then_else (ne (match_dup 1) (const_int 0))
                           (pc)
                           (pc)
                           (label_ref (match_operand 0 "" ""))))]
                           (label_ref (match_operand 0 "" ""))))]
  ""
  ""
  "
  "
{
{
  operands[1] = mcore_gen_compare_reg (GE);
  operands[1] = mcore_gen_compare_reg (GE);
}")
}")
; There is no gtu compare, so we reverse the branch arms
; There is no gtu compare, so we reverse the branch arms
;(define_expand "bgtu"
;(define_expand "bgtu"
;  [(set (pc) (if_then_else (ne (match_dup 1) (const_int 0))
;  [(set (pc) (if_then_else (ne (match_dup 1) (const_int 0))
;                          (pc)
;                          (pc)
;                          (label_ref (match_operand 0 "" ""))))]
;                          (label_ref (match_operand 0 "" ""))))]
;  ""
;  ""
;  "
;  "
;{
;{
;  if (GET_CODE (arch_compare_op1) == CONST_INT
;  if (GET_CODE (arch_compare_op1) == CONST_INT
;      && INTVAL (arch_compare_op1) == 0)
;      && INTVAL (arch_compare_op1) == 0)
;    operands[1] = mcore_gen_compare_reg (NE);
;    operands[1] = mcore_gen_compare_reg (NE);
;  else
;  else
;    { if (mcore_modify_comparison (GTU))
;    { if (mcore_modify_comparison (GTU))
;       {
;       {
;         emit_jump_insn (gen_bgeu (operands[0]));
;         emit_jump_insn (gen_bgeu (operands[0]));
;         DONE;
;         DONE;
;       }
;       }
;      operands[1] = mcore_gen_compare_reg (LEU);
;      operands[1] = mcore_gen_compare_reg (LEU);
;    }
;    }
;}")
;}")
(define_expand "bgtu"
(define_expand "bgtu"
  [(set (pc) (if_then_else (ne (match_dup 1) (const_int 0))
  [(set (pc) (if_then_else (ne (match_dup 1) (const_int 0))
                           (pc)
                           (pc)
                           (label_ref (match_operand 0 "" ""))))]
                           (label_ref (match_operand 0 "" ""))))]
  ""
  ""
  "
  "
{
{
  if (GET_CODE (arch_compare_op1) == CONST_INT
  if (GET_CODE (arch_compare_op1) == CONST_INT
      && INTVAL (arch_compare_op1) == 0)
      && INTVAL (arch_compare_op1) == 0)
    {
    {
      /* The inverse of '> 0' for an unsigned test is
      /* The inverse of '> 0' for an unsigned test is
         '== 0' but we do not have such an instruction available.
         '== 0' but we do not have such an instruction available.
         Instead we must reverse the branch (back to the normal
         Instead we must reverse the branch (back to the normal
         ordering) and test '!= 0'.  */
         ordering) and test '!= 0'.  */
      operands[1] = mcore_gen_compare_reg (NE);
      operands[1] = mcore_gen_compare_reg (NE);
      emit_jump_insn (gen_rtx_SET (VOIDmode,
      emit_jump_insn (gen_rtx_SET (VOIDmode,
        pc_rtx,
        pc_rtx,
        gen_rtx_IF_THEN_ELSE (VOIDmode,
        gen_rtx_IF_THEN_ELSE (VOIDmode,
        gen_rtx_NE (VOIDmode,
        gen_rtx_NE (VOIDmode,
        operands[1],
        operands[1],
        const0_rtx),
        const0_rtx),
        gen_rtx_LABEL_REF (VOIDmode,operands[0]),
        gen_rtx_LABEL_REF (VOIDmode,operands[0]),
        pc_rtx)));
        pc_rtx)));
      DONE;
      DONE;
    }
    }
  operands[1] = mcore_gen_compare_reg (GTU);
  operands[1] = mcore_gen_compare_reg (GTU);
}")
}")
(define_expand "bleu"
(define_expand "bleu"
  [(set (pc) (if_then_else (ne (match_dup 1) (const_int 0))
  [(set (pc) (if_then_else (ne (match_dup 1) (const_int 0))
                           (label_ref (match_operand 0 "" ""))
                           (label_ref (match_operand 0 "" ""))
                           (pc)))]
                           (pc)))]
  ""
  ""
  "
  "
{
{
  operands[1] = mcore_gen_compare_reg (LEU);
  operands[1] = mcore_gen_compare_reg (LEU);
}")
}")
; There is no bltu compare, so we reverse the branch arms
; There is no bltu compare, so we reverse the branch arms
(define_expand "bltu"
(define_expand "bltu"
  [(set (pc) (if_then_else (ne (match_dup 1) (const_int 0))
  [(set (pc) (if_then_else (ne (match_dup 1) (const_int 0))
                           (pc)
                           (pc)
                           (label_ref (match_operand 0 "" ""))))]
                           (label_ref (match_operand 0 "" ""))))]
  ""
  ""
  "
  "
{
{
  operands[1] = mcore_gen_compare_reg (LTU);
  operands[1] = mcore_gen_compare_reg (LTU);
}")
}")
(define_expand "bgeu"
(define_expand "bgeu"
  [(set (pc) (if_then_else (ne (match_dup 1) (const_int 0))
  [(set (pc) (if_then_else (ne (match_dup 1) (const_int 0))
                           (label_ref (match_operand 0 "" ""))
                           (label_ref (match_operand 0 "" ""))
                           (pc)))]
                           (pc)))]
  ""
  ""
  "
  "
{
{
  operands[1] = mcore_gen_compare_reg (GEU);
  operands[1] = mcore_gen_compare_reg (GEU);
}")
}")
;; ------------------------------------------------------------------------
;; ------------------------------------------------------------------------
;; Jump and linkage insns
;; Jump and linkage insns
;; ------------------------------------------------------------------------
;; ------------------------------------------------------------------------
(define_insn "jump_real"
(define_insn "jump_real"
  [(set (pc)
  [(set (pc)
        (label_ref (match_operand 0 "" "")))]
        (label_ref (match_operand 0 "" "")))]
  ""
  ""
  "jbr  %l0"
  "jbr  %l0"
  [(set_attr "type" "branch")])
  [(set_attr "type" "branch")])
(define_expand "jump"
(define_expand "jump"
 [(set (pc) (label_ref (match_operand 0 "" "")))]
 [(set (pc) (label_ref (match_operand 0 "" "")))]
 ""
 ""
 "
 "
{
{
  emit_jump_insn (gen_jump_real (operand0));
  emit_jump_insn (gen_jump_real (operand0));
  DONE;
  DONE;
}
}
")
")
(define_insn "indirect_jump"
(define_insn "indirect_jump"
  [(set (pc)
  [(set (pc)
        (match_operand:SI 0 "mcore_arith_reg_operand" "r"))]
        (match_operand:SI 0 "mcore_arith_reg_operand" "r"))]
  ""
  ""
  "jmp  %0"
  "jmp  %0"
  [(set_attr "type" "jmp")])
  [(set_attr "type" "jmp")])
(define_expand "call"
(define_expand "call"
  [(parallel[(call (match_operand:SI 0 "" "")
  [(parallel[(call (match_operand:SI 0 "" "")
                   (match_operand 1 "" ""))
                   (match_operand 1 "" ""))
             (clobber (reg:SI 15))])]
             (clobber (reg:SI 15))])]
  ""
  ""
  "
  "
{
{
  if (GET_CODE (operands[0]) == MEM
  if (GET_CODE (operands[0]) == MEM
      && ! register_operand (XEXP (operands[0], 0), SImode)
      && ! register_operand (XEXP (operands[0], 0), SImode)
      && ! mcore_symbolic_address_p (XEXP (operands[0], 0)))
      && ! mcore_symbolic_address_p (XEXP (operands[0], 0)))
    operands[0] = gen_rtx_MEM (GET_MODE (operands[0]),
    operands[0] = gen_rtx_MEM (GET_MODE (operands[0]),
                           force_reg (Pmode, XEXP (operands[0], 0)));
                           force_reg (Pmode, XEXP (operands[0], 0)));
}")
}")
(define_insn "call_internal"
(define_insn "call_internal"
  [(call (mem:SI (match_operand:SI 0 "mcore_call_address_operand" "riR"))
  [(call (mem:SI (match_operand:SI 0 "mcore_call_address_operand" "riR"))
         (match_operand 1 "" ""))
         (match_operand 1 "" ""))
   (clobber (reg:SI 15))]
   (clobber (reg:SI 15))]
  ""
  ""
  "* return mcore_output_call (operands, 0);")
  "* return mcore_output_call (operands, 0);")
(define_expand "call_value"
(define_expand "call_value"
  [(parallel[(set (match_operand 0 "register_operand" "")
  [(parallel[(set (match_operand 0 "register_operand" "")
                  (call (match_operand:SI 1 "" "")
                  (call (match_operand:SI 1 "" "")
                        (match_operand 2 "" "")))
                        (match_operand 2 "" "")))
             (clobber (reg:SI 15))])]
             (clobber (reg:SI 15))])]
  ""
  ""
  "
  "
{
{
  if (GET_CODE (operands[0]) == MEM
  if (GET_CODE (operands[0]) == MEM
      && ! register_operand (XEXP (operands[0], 0), SImode)
      && ! register_operand (XEXP (operands[0], 0), SImode)
      && ! mcore_symbolic_address_p (XEXP (operands[0], 0)))
      && ! mcore_symbolic_address_p (XEXP (operands[0], 0)))
    operands[1] = gen_rtx_MEM (GET_MODE (operands[1]),
    operands[1] = gen_rtx_MEM (GET_MODE (operands[1]),
                           force_reg (Pmode, XEXP (operands[1], 0)));
                           force_reg (Pmode, XEXP (operands[1], 0)));
}")
}")
(define_insn "call_value_internal"
(define_insn "call_value_internal"
  [(set (match_operand 0 "register_operand" "=r")
  [(set (match_operand 0 "register_operand" "=r")
        (call (mem:SI (match_operand:SI 1 "mcore_call_address_operand" "riR"))
        (call (mem:SI (match_operand:SI 1 "mcore_call_address_operand" "riR"))
              (match_operand 2 "" "")))
              (match_operand 2 "" "")))
   (clobber (reg:SI 15))]
   (clobber (reg:SI 15))]
  ""
  ""
  "* return mcore_output_call (operands, 1);")
  "* return mcore_output_call (operands, 1);")
(define_insn "call_value_struct"
(define_insn "call_value_struct"
  [(parallel [(set (match_parallel 0 ""
  [(parallel [(set (match_parallel 0 ""
                     [(expr_list (match_operand 3 "register_operand" "") (match_operand 4 "immediate_operand" ""))
                     [(expr_list (match_operand 3 "register_operand" "") (match_operand 4 "immediate_operand" ""))
                      (expr_list (match_operand 5 "register_operand" "") (match_operand 6 "immediate_operand" ""))])
                      (expr_list (match_operand 5 "register_operand" "") (match_operand 6 "immediate_operand" ""))])
                  (call (match_operand:SI 1 "" "")
                  (call (match_operand:SI 1 "" "")
                        (match_operand 2 "" "")))
                        (match_operand 2 "" "")))
             (clobber (reg:SI 15))])]
             (clobber (reg:SI 15))])]
  ""
  ""
  "* return mcore_output_call (operands, 1);"
  "* return mcore_output_call (operands, 1);"
)
)
;; ------------------------------------------------------------------------
;; ------------------------------------------------------------------------
;; Misc insns
;; Misc insns
;; ------------------------------------------------------------------------
;; ------------------------------------------------------------------------
(define_insn "nop"
(define_insn "nop"
  [(const_int 0)]
  [(const_int 0)]
  ""
  ""
  "or   r0,r0")
  "or   r0,r0")
(define_insn "tablejump"
(define_insn "tablejump"
  [(set (pc)
  [(set (pc)
        (match_operand:SI 0 "mcore_arith_reg_operand" "r"))
        (match_operand:SI 0 "mcore_arith_reg_operand" "r"))
   (use (label_ref (match_operand 1 "" "")))]
   (use (label_ref (match_operand 1 "" "")))]
  ""
  ""
  "jmp  %0"
  "jmp  %0"
  [(set_attr "type" "jmp")])
  [(set_attr "type" "jmp")])
(define_insn "*return"
(define_insn "*return"
 [(return)]
 [(return)]
 "reload_completed && ! mcore_naked_function_p ()"
 "reload_completed && ! mcore_naked_function_p ()"
 "jmp   r15"
 "jmp   r15"
 [(set_attr "type" "jmp")])
 [(set_attr "type" "jmp")])
(define_insn "*no_return"
(define_insn "*no_return"
 [(return)]
 [(return)]
 "reload_completed && mcore_naked_function_p ()"
 "reload_completed && mcore_naked_function_p ()"
 ""
 ""
 [(set_attr "length" "0")]
 [(set_attr "length" "0")]
)
)
(define_expand "prologue"
(define_expand "prologue"
  [(const_int 0)]
  [(const_int 0)]
  ""
  ""
  "mcore_expand_prolog (); DONE;")
  "mcore_expand_prolog (); DONE;")
(define_expand "epilogue"
(define_expand "epilogue"
  [(return)]
  [(return)]
  ""
  ""
  "mcore_expand_epilog ();")
  "mcore_expand_epilog ();")
;; ------------------------------------------------------------------------
;; ------------------------------------------------------------------------
;; Scc instructions
;; Scc instructions
;; ------------------------------------------------------------------------
;; ------------------------------------------------------------------------
(define_insn "mvc"
(define_insn "mvc"
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r")
        (ne:SI (reg:CC 17) (const_int 0)))]
        (ne:SI (reg:CC 17) (const_int 0)))]
  ""
  ""
  "mvc  %0"
  "mvc  %0"
  [(set_attr "type" "move")])
  [(set_attr "type" "move")])
(define_insn "mvcv"
(define_insn "mvcv"
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r")
        (eq:SI (reg:CC 17) (const_int 0)))]
        (eq:SI (reg:CC 17) (const_int 0)))]
  ""
  ""
  "mvcv %0"
  "mvcv %0"
  [(set_attr "type" "move")])
  [(set_attr "type" "move")])
; in 0.97 use (LE 0) with (LT 1) and complement c.  BRC
; in 0.97 use (LE 0) with (LT 1) and complement c.  BRC
(define_split
(define_split
  [(parallel[
  [(parallel[
     (set (match_operand:SI 0 "mcore_arith_reg_operand" "")
     (set (match_operand:SI 0 "mcore_arith_reg_operand" "")
          (ne:SI (gt:CC (match_operand:SI 1 "mcore_arith_reg_operand" "")
          (ne:SI (gt:CC (match_operand:SI 1 "mcore_arith_reg_operand" "")
                        (const_int 0))
                        (const_int 0))
                 (const_int 0)))
                 (const_int 0)))
     (clobber (reg:SI 17))])]
     (clobber (reg:SI 17))])]
  ""
  ""
  [(set (reg:CC 17)
  [(set (reg:CC 17)
        (lt:CC (match_dup 1) (const_int 1)))
        (lt:CC (match_dup 1) (const_int 1)))
   (set (match_dup 0) (eq:SI (reg:CC 17) (const_int 0)))])
   (set (match_dup 0) (eq:SI (reg:CC 17) (const_int 0)))])
(define_expand "seq"
(define_expand "seq"
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "")
        (eq:SI (match_dup 1) (const_int 0)))]
        (eq:SI (match_dup 1) (const_int 0)))]
  ""
  ""
  "
  "
{
{
  operands[1] = mcore_gen_compare_reg (NE);
  operands[1] = mcore_gen_compare_reg (NE);
}")
}")
(define_expand "sne"
(define_expand "sne"
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "")
        (ne:SI (match_dup 1) (const_int 0)))]
        (ne:SI (match_dup 1) (const_int 0)))]
  ""
  ""
  "
  "
{
{
  operands[1] = mcore_gen_compare_reg (NE);
  operands[1] = mcore_gen_compare_reg (NE);
}")
}")
(define_expand "slt"
(define_expand "slt"
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "")
        (ne:SI (match_dup 1) (const_int 0)))]
        (ne:SI (match_dup 1) (const_int 0)))]
  ""
  ""
  "
  "
{
{
  operands[1] = mcore_gen_compare_reg (LT);
  operands[1] = mcore_gen_compare_reg (LT);
}")
}")
; make generating a LT with the comparison reversed easy.  BRC
; make generating a LT with the comparison reversed easy.  BRC
(define_expand "reverse_slt"
(define_expand "reverse_slt"
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "")
        (eq:SI (match_dup 1) (const_int 0)))]
        (eq:SI (match_dup 1) (const_int 0)))]
  ""
  ""
  "
  "
{
{
  operands[1] = mcore_gen_compare_reg (LT);
  operands[1] = mcore_gen_compare_reg (LT);
}")
}")
(define_expand "sge"
(define_expand "sge"
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "")
        (eq:SI (match_dup 1) (const_int 0)))]
        (eq:SI (match_dup 1) (const_int 0)))]
  ""
  ""
  "
  "
{
{
  operands[1] = mcore_gen_compare_reg (LT);
  operands[1] = mcore_gen_compare_reg (LT);
}")
}")
; check whether (GT A imm) can become (LE A imm) with the comparison
; check whether (GT A imm) can become (LE A imm) with the comparison
; reversed.  if so, emit a (LT A imm + 1) in place of the (LE A imm).  BRC
; reversed.  if so, emit a (LT A imm + 1) in place of the (LE A imm).  BRC
(define_expand "sgt"
(define_expand "sgt"
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "")
        (ne:SI (match_dup 1) (const_int 0)))]
        (ne:SI (match_dup 1) (const_int 0)))]
  ""
  ""
  "
  "
{
{
  if (mcore_modify_comparison (LE))
  if (mcore_modify_comparison (LE))
    {
    {
      emit_insn (gen_reverse_slt (operands[0]));
      emit_insn (gen_reverse_slt (operands[0]));
      DONE;
      DONE;
    }
    }
  operands[1] = mcore_gen_compare_reg (GT);
  operands[1] = mcore_gen_compare_reg (GT);
}")
}")
(define_expand "sle"
(define_expand "sle"
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "")
        (eq:SI (match_dup 1) (const_int 0)))]
        (eq:SI (match_dup 1) (const_int 0)))]
  ""
  ""
  "
  "
{
{
  if (mcore_modify_comparison (LE))
  if (mcore_modify_comparison (LE))
    {
    {
      emit_insn (gen_slt (operands[0]));
      emit_insn (gen_slt (operands[0]));
      DONE;
      DONE;
    }
    }
  operands[1] = mcore_gen_compare_reg (GT);
  operands[1] = mcore_gen_compare_reg (GT);
}")
}")
(define_expand "sltu"
(define_expand "sltu"
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "")
        (eq:SI (match_dup 1) (const_int 0)))]
        (eq:SI (match_dup 1) (const_int 0)))]
  ""
  ""
  "
  "
{
{
  operands[1] = mcore_gen_compare_reg (GEU);
  operands[1] = mcore_gen_compare_reg (GEU);
}")
}")
(define_expand "sgeu"
(define_expand "sgeu"
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "")
        (ne:SI (match_dup 1) (const_int 0)))]
        (ne:SI (match_dup 1) (const_int 0)))]
  ""
  ""
  "
  "
{
{
  operands[1] = mcore_gen_compare_reg (GEU);
  operands[1] = mcore_gen_compare_reg (GEU);
}")
}")
(define_expand "sgtu"
(define_expand "sgtu"
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "")
        (eq:SI (match_dup 1) (const_int 0)))]
        (eq:SI (match_dup 1) (const_int 0)))]
  ""
  ""
  "
  "
{
{
  operands[1] = mcore_gen_compare_reg (LEU);
  operands[1] = mcore_gen_compare_reg (LEU);
}")
}")
(define_expand "sleu"
(define_expand "sleu"
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "")
        (ne:SI (match_dup 1) (const_int 0)))]
        (ne:SI (match_dup 1) (const_int 0)))]
  ""
  ""
  "
  "
{
{
  operands[1] = mcore_gen_compare_reg (LEU);
  operands[1] = mcore_gen_compare_reg (LEU);
}")
}")
(define_insn "incscc"
(define_insn "incscc"
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r")
        (plus:SI (ne (reg:CC 17) (const_int 0))
        (plus:SI (ne (reg:CC 17) (const_int 0))
                 (match_operand:SI 1 "mcore_arith_reg_operand" "0")))]
                 (match_operand:SI 1 "mcore_arith_reg_operand" "0")))]
  ""
  ""
  "inct %0")
  "inct %0")
(define_insn "incscc_false"
(define_insn "incscc_false"
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r")
        (plus:SI (eq (reg:CC 17) (const_int 0))
        (plus:SI (eq (reg:CC 17) (const_int 0))
                 (match_operand:SI 1 "mcore_arith_reg_operand" "0")))]
                 (match_operand:SI 1 "mcore_arith_reg_operand" "0")))]
  ""
  ""
  "incf %0")
  "incf %0")
(define_insn "decscc"
(define_insn "decscc"
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r")
        (minus:SI (match_operand:SI 1 "mcore_arith_reg_operand" "0")
        (minus:SI (match_operand:SI 1 "mcore_arith_reg_operand" "0")
                  (ne (reg:CC 17) (const_int 0))))]
                  (ne (reg:CC 17) (const_int 0))))]
  ""
  ""
  "dect %0")
  "dect %0")
(define_insn "decscc_false"
(define_insn "decscc_false"
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r")
        (minus:SI (match_operand:SI 1 "mcore_arith_reg_operand" "0")
        (minus:SI (match_operand:SI 1 "mcore_arith_reg_operand" "0")
                  (eq (reg:CC 17) (const_int 0))))]
                  (eq (reg:CC 17) (const_int 0))))]
  ""
  ""
  "decf %0")
  "decf %0")
;; ------------------------------------------------------------------------
;; ------------------------------------------------------------------------
;; Conditional move patterns.
;; Conditional move patterns.
;; ------------------------------------------------------------------------
;; ------------------------------------------------------------------------
(define_expand "smaxsi3"
(define_expand "smaxsi3"
  [(set (reg:CC 17)
  [(set (reg:CC 17)
        (lt:CC (match_operand:SI 1 "mcore_arith_reg_operand" "")
        (lt:CC (match_operand:SI 1 "mcore_arith_reg_operand" "")
               (match_operand:SI 2 "mcore_arith_reg_operand" "")))
               (match_operand:SI 2 "mcore_arith_reg_operand" "")))
   (set (match_operand:SI 0 "mcore_arith_reg_operand" "")
   (set (match_operand:SI 0 "mcore_arith_reg_operand" "")
        (if_then_else:SI (eq (reg:CC 17) (const_int 0))
        (if_then_else:SI (eq (reg:CC 17) (const_int 0))
                         (match_dup 1) (match_dup 2)))]
                         (match_dup 1) (match_dup 2)))]
  ""
  ""
  "")
  "")
(define_split
(define_split
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "")
        (smax:SI (match_operand:SI 1 "mcore_arith_reg_operand" "")
        (smax:SI (match_operand:SI 1 "mcore_arith_reg_operand" "")
                 (match_operand:SI 2 "mcore_arith_reg_operand" "")))]
                 (match_operand:SI 2 "mcore_arith_reg_operand" "")))]
  ""
  ""
  [(set (reg:CC 17)
  [(set (reg:CC 17)
        (lt:SI (match_dup 1) (match_dup 2)))
        (lt:SI (match_dup 1) (match_dup 2)))
   (set (match_dup 0)
   (set (match_dup 0)
        (if_then_else:SI (eq (reg:CC 17) (const_int 0))
        (if_then_else:SI (eq (reg:CC 17) (const_int 0))
                         (match_dup 1) (match_dup 2)))]
                         (match_dup 1) (match_dup 2)))]
  "")
  "")
; no tstgt in 0.97, so just use cmplti (btsti x,31) and reverse move
; no tstgt in 0.97, so just use cmplti (btsti x,31) and reverse move
; condition  BRC
; condition  BRC
(define_split
(define_split
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "")
        (smax:SI (match_operand:SI 1 "mcore_arith_reg_operand" "")
        (smax:SI (match_operand:SI 1 "mcore_arith_reg_operand" "")
                 (const_int 0)))]
                 (const_int 0)))]
  ""
  ""
  [(set (reg:CC 17)
  [(set (reg:CC 17)
        (lt:CC (match_dup 1) (const_int 0)))
        (lt:CC (match_dup 1) (const_int 0)))
   (set (match_dup 0)
   (set (match_dup 0)
        (if_then_else:SI (eq (reg:CC 17) (const_int 0))
        (if_then_else:SI (eq (reg:CC 17) (const_int 0))
                         (match_dup 1) (const_int 0)))]
                         (match_dup 1) (const_int 0)))]
  "")
  "")
(define_expand "sminsi3"
(define_expand "sminsi3"
  [(set (reg:CC 17)
  [(set (reg:CC 17)
        (lt:CC (match_operand:SI 1 "mcore_arith_reg_operand" "")
        (lt:CC (match_operand:SI 1 "mcore_arith_reg_operand" "")
               (match_operand:SI 2 "mcore_arith_reg_operand" "")))
               (match_operand:SI 2 "mcore_arith_reg_operand" "")))
   (set (match_operand:SI 0 "mcore_arith_reg_operand" "")
   (set (match_operand:SI 0 "mcore_arith_reg_operand" "")
        (if_then_else:SI (ne (reg:CC 17) (const_int 0))
        (if_then_else:SI (ne (reg:CC 17) (const_int 0))
                         (match_dup 1) (match_dup 2)))]
                         (match_dup 1) (match_dup 2)))]
  ""
  ""
  "")
  "")
(define_split
(define_split
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "")
        (smin:SI (match_operand:SI 1 "mcore_arith_reg_operand" "")
        (smin:SI (match_operand:SI 1 "mcore_arith_reg_operand" "")
                 (match_operand:SI 2 "mcore_arith_reg_operand" "")))]
                 (match_operand:SI 2 "mcore_arith_reg_operand" "")))]
  ""
  ""
  [(set (reg:CC 17)
  [(set (reg:CC 17)
        (lt:SI (match_dup 1) (match_dup 2)))
        (lt:SI (match_dup 1) (match_dup 2)))
   (set (match_dup 0)
   (set (match_dup 0)
        (if_then_else:SI (ne (reg:CC 17) (const_int 0))
        (if_then_else:SI (ne (reg:CC 17) (const_int 0))
                         (match_dup 1) (match_dup 2)))]
                         (match_dup 1) (match_dup 2)))]
  "")
  "")
;(define_split
;(define_split
;  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "")
;  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "")
;        (smin:SI (match_operand:SI 1 "mcore_arith_reg_operand" "")
;        (smin:SI (match_operand:SI 1 "mcore_arith_reg_operand" "")
;                 (const_int 0)))]
;                 (const_int 0)))]
;  ""
;  ""
;  [(set (reg:CC 17)
;  [(set (reg:CC 17)
;        (gt:CC (match_dup 1) (const_int 0)))
;        (gt:CC (match_dup 1) (const_int 0)))
;   (set (match_dup 0)
;   (set (match_dup 0)
;        (if_then_else:SI (eq (reg:CC 17) (const_int 0))
;        (if_then_else:SI (eq (reg:CC 17) (const_int 0))
;                         (match_dup 1) (const_int 0)))]
;                         (match_dup 1) (const_int 0)))]
;  "")
;  "")
; changed these unsigned patterns to use geu instead of ltu.  it appears
; changed these unsigned patterns to use geu instead of ltu.  it appears
; that the c-torture & ssrl test suites didn't catch these!  only showed
; that the c-torture & ssrl test suites didn't catch these!  only showed
; up in friedman's clib work.   BRC 7/7/95
; up in friedman's clib work.   BRC 7/7/95
(define_expand "umaxsi3"
(define_expand "umaxsi3"
  [(set (reg:CC 17)
  [(set (reg:CC 17)
        (geu:CC (match_operand:SI 1 "mcore_arith_reg_operand" "")
        (geu:CC (match_operand:SI 1 "mcore_arith_reg_operand" "")
                (match_operand:SI 2 "mcore_arith_reg_operand" "")))
                (match_operand:SI 2 "mcore_arith_reg_operand" "")))
   (set (match_operand:SI 0 "mcore_arith_reg_operand" "")
   (set (match_operand:SI 0 "mcore_arith_reg_operand" "")
        (if_then_else:SI (eq (reg:CC 17) (const_int 0))
        (if_then_else:SI (eq (reg:CC 17) (const_int 0))
                         (match_dup 2) (match_dup 1)))]
                         (match_dup 2) (match_dup 1)))]
  ""
  ""
  "")
  "")
(define_split
(define_split
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "")
        (umax:SI (match_operand:SI 1 "mcore_arith_reg_operand" "")
        (umax:SI (match_operand:SI 1 "mcore_arith_reg_operand" "")
                 (match_operand:SI 2 "mcore_arith_reg_operand" "")))]
                 (match_operand:SI 2 "mcore_arith_reg_operand" "")))]
  ""
  ""
  [(set (reg:CC 17)
  [(set (reg:CC 17)
        (geu:SI (match_dup 1) (match_dup 2)))
        (geu:SI (match_dup 1) (match_dup 2)))
   (set (match_dup 0)
   (set (match_dup 0)
        (if_then_else:SI (eq (reg:CC 17) (const_int 0))
        (if_then_else:SI (eq (reg:CC 17) (const_int 0))
                         (match_dup 2) (match_dup 1)))]
                         (match_dup 2) (match_dup 1)))]
  "")
  "")
(define_expand "uminsi3"
(define_expand "uminsi3"
  [(set (reg:CC 17)
  [(set (reg:CC 17)
        (geu:CC (match_operand:SI 1 "mcore_arith_reg_operand" "")
        (geu:CC (match_operand:SI 1 "mcore_arith_reg_operand" "")
                (match_operand:SI 2 "mcore_arith_reg_operand" "")))
                (match_operand:SI 2 "mcore_arith_reg_operand" "")))
   (set (match_operand:SI 0 "mcore_arith_reg_operand" "")
   (set (match_operand:SI 0 "mcore_arith_reg_operand" "")
        (if_then_else:SI (ne (reg:CC 17) (const_int 0))
        (if_then_else:SI (ne (reg:CC 17) (const_int 0))
                         (match_dup 2) (match_dup 1)))]
                         (match_dup 2) (match_dup 1)))]
  ""
  ""
  "")
  "")
(define_split
(define_split
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "")
        (umin:SI (match_operand:SI 1 "mcore_arith_reg_operand" "")
        (umin:SI (match_operand:SI 1 "mcore_arith_reg_operand" "")
                 (match_operand:SI 2 "mcore_arith_reg_operand" "")))]
                 (match_operand:SI 2 "mcore_arith_reg_operand" "")))]
  ""
  ""
  [(set (reg:CC 17)
  [(set (reg:CC 17)
        (geu:SI (match_dup 1) (match_dup 2)))
        (geu:SI (match_dup 1) (match_dup 2)))
   (set (match_dup 0)
   (set (match_dup 0)
        (if_then_else:SI (ne (reg:CC 17) (const_int 0))
        (if_then_else:SI (ne (reg:CC 17) (const_int 0))
                         (match_dup 2) (match_dup 1)))]
                         (match_dup 2) (match_dup 1)))]
  "")
  "")
;; ------------------------------------------------------------------------
;; ------------------------------------------------------------------------
;; conditional move patterns really start here
;; conditional move patterns really start here
;; ------------------------------------------------------------------------
;; ------------------------------------------------------------------------
;; the "movtK" patterns are experimental.  they are intended to account for
;; the "movtK" patterns are experimental.  they are intended to account for
;; gcc's mucking on code such as:
;; gcc's mucking on code such as:
;;
;;
;;            free_ent = ((block_compress) ? 257 : 256 );
;;            free_ent = ((block_compress) ? 257 : 256 );
;;
;;
;; these patterns help to get a tstne/bgeni/inct (or equivalent) sequence
;; these patterns help to get a tstne/bgeni/inct (or equivalent) sequence
;; when both arms have constants that are +/- 1 of each other.
;; when both arms have constants that are +/- 1 of each other.
;;
;;
;; note in the following patterns that the "movtK" ones should be the first
;; note in the following patterns that the "movtK" ones should be the first
;; one defined in each sequence.  this is because the general pattern also
;; one defined in each sequence.  this is because the general pattern also
;; matches, so use ordering to determine priority (it's easier this way than
;; matches, so use ordering to determine priority (it's easier this way than
;; adding conditions to the general patterns).   BRC
;; adding conditions to the general patterns).   BRC
;;
;;
;; the U and Q constraints are necessary to ensure that reload does the
;; the U and Q constraints are necessary to ensure that reload does the
;; 'right thing'.  U constrains the operand to 0 and Q to 1 for use in the
;; 'right thing'.  U constrains the operand to 0 and Q to 1 for use in the
;; clrt & clrf and clrt/inct & clrf/incf patterns.    BRC 6/26
;; clrt & clrf and clrt/inct & clrf/incf patterns.    BRC 6/26
;;
;;
;; ??? there appears to be some problems with these movtK patterns for ops
;; ??? there appears to be some problems with these movtK patterns for ops
;; other than eq & ne.  need to fix.  6/30 BRC
;; other than eq & ne.  need to fix.  6/30 BRC
;; ------------------------------------------------------------------------
;; ------------------------------------------------------------------------
;; ne
;; ne
;; ------------------------------------------------------------------------
;; ------------------------------------------------------------------------
; experimental conditional move with two constants +/- 1  BRC
; experimental conditional move with two constants +/- 1  BRC
(define_insn "movtK_1"
(define_insn "movtK_1"
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r")
        (if_then_else:SI
        (if_then_else:SI
            (ne (reg:CC 17) (const_int 0))
            (ne (reg:CC 17) (const_int 0))
          (match_operand:SI 1 "mcore_arith_O_operand" "O")
          (match_operand:SI 1 "mcore_arith_O_operand" "O")
          (match_operand:SI 2 "mcore_arith_O_operand" "O")))]
          (match_operand:SI 2 "mcore_arith_O_operand" "O")))]
  "  GET_CODE (operands[1]) == CONST_INT
  "  GET_CODE (operands[1]) == CONST_INT
  && GET_CODE (operands[2]) == CONST_INT
  && GET_CODE (operands[2]) == CONST_INT
  && (   (INTVAL (operands[1]) - INTVAL (operands[2]) == 1)
  && (   (INTVAL (operands[1]) - INTVAL (operands[2]) == 1)
      || (INTVAL (operands[2]) - INTVAL (operands[1]) == 1))"
      || (INTVAL (operands[2]) - INTVAL (operands[1]) == 1))"
  "* return mcore_output_cmov (operands, 1, NULL);"
  "* return mcore_output_cmov (operands, 1, NULL);"
  [(set_attr "length" "4")])
  [(set_attr "length" "4")])
(define_insn "movt0"
(define_insn "movt0"
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r,r,r,r")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r,r,r,r")
        (if_then_else:SI
        (if_then_else:SI
         (ne (reg:CC 17) (const_int 0))
         (ne (reg:CC 17) (const_int 0))
         (match_operand:SI 1 "mcore_arith_imm_operand" "r,0,U,0")
         (match_operand:SI 1 "mcore_arith_imm_operand" "r,0,U,0")
         (match_operand:SI 2 "mcore_arith_imm_operand" "0,r,0,U")))]
         (match_operand:SI 2 "mcore_arith_imm_operand" "0,r,0,U")))]
  ""
  ""
  "@
  "@
    movt        %0,%1
    movt        %0,%1
    movf        %0,%2
    movf        %0,%2
    clrt        %0
    clrt        %0
    clrf        %0")
    clrf        %0")
;; ------------------------------------------------------------------------
;; ------------------------------------------------------------------------
;; eq
;; eq
;; ------------------------------------------------------------------------
;; ------------------------------------------------------------------------
; experimental conditional move with two constants +/- 1  BRC
; experimental conditional move with two constants +/- 1  BRC
(define_insn "movtK_2"
(define_insn "movtK_2"
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r")
        (if_then_else:SI
        (if_then_else:SI
            (eq (reg:CC 17) (const_int 0))
            (eq (reg:CC 17) (const_int 0))
          (match_operand:SI 1 "mcore_arith_O_operand" "O")
          (match_operand:SI 1 "mcore_arith_O_operand" "O")
          (match_operand:SI 2 "mcore_arith_O_operand" "O")))]
          (match_operand:SI 2 "mcore_arith_O_operand" "O")))]
  "  GET_CODE (operands[1]) == CONST_INT
  "  GET_CODE (operands[1]) == CONST_INT
  && GET_CODE (operands[2]) == CONST_INT
  && GET_CODE (operands[2]) == CONST_INT
  && (   (INTVAL (operands[1]) - INTVAL (operands[2]) == 1)
  && (   (INTVAL (operands[1]) - INTVAL (operands[2]) == 1)
      || (INTVAL (operands[2]) - INTVAL (operands[1]) == 1))"
      || (INTVAL (operands[2]) - INTVAL (operands[1]) == 1))"
  "* return mcore_output_cmov (operands, 0, NULL);"
  "* return mcore_output_cmov (operands, 0, NULL);"
  [(set_attr "length" "4")])
  [(set_attr "length" "4")])
(define_insn "movf0"
(define_insn "movf0"
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r,r,r,r")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r,r,r,r")
        (if_then_else:SI
        (if_then_else:SI
         (eq (reg:CC 17) (const_int 0))
         (eq (reg:CC 17) (const_int 0))
         (match_operand:SI 1 "mcore_arith_imm_operand" "r,0,U,0")
         (match_operand:SI 1 "mcore_arith_imm_operand" "r,0,U,0")
         (match_operand:SI 2 "mcore_arith_imm_operand" "0,r,0,U")))]
         (match_operand:SI 2 "mcore_arith_imm_operand" "0,r,0,U")))]
  ""
  ""
  "@
  "@
    movf        %0,%1
    movf        %0,%1
    movt        %0,%2
    movt        %0,%2
    clrf        %0
    clrf        %0
    clrt        %0")
    clrt        %0")
; turns lsli rx,imm/btsti rx,31 into btsti rx,imm.  not done by a peephole
; turns lsli rx,imm/btsti rx,31 into btsti rx,imm.  not done by a peephole
; because the instructions are not adjacent (peepholes are related by posn -
; because the instructions are not adjacent (peepholes are related by posn -
; not by dataflow).   BRC
; not by dataflow).   BRC
(define_insn ""
(define_insn ""
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r,r,r,r")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r,r,r,r")
        (if_then_else:SI (eq (zero_extract:SI
        (if_then_else:SI (eq (zero_extract:SI
                              (match_operand:SI 1 "mcore_arith_reg_operand" "r,r,r,r")
                              (match_operand:SI 1 "mcore_arith_reg_operand" "r,r,r,r")
                              (const_int 1)
                              (const_int 1)
                              (match_operand:SI 2 "mcore_literal_K_operand" "K,K,K,K"))
                              (match_operand:SI 2 "mcore_literal_K_operand" "K,K,K,K"))
                             (const_int 0))
                             (const_int 0))
                         (match_operand:SI 3 "mcore_arith_imm_operand" "r,0,U,0")
                         (match_operand:SI 3 "mcore_arith_imm_operand" "r,0,U,0")
                         (match_operand:SI 4 "mcore_arith_imm_operand" "0,r,0,U")))]
                         (match_operand:SI 4 "mcore_arith_imm_operand" "0,r,0,U")))]
  ""
  ""
  "@
  "@
    btsti       %1,%2\;movf     %0,%3
    btsti       %1,%2\;movf     %0,%3
    btsti       %1,%2\;movt     %0,%4
    btsti       %1,%2\;movt     %0,%4
    btsti       %1,%2\;clrf     %0
    btsti       %1,%2\;clrf     %0
    btsti       %1,%2\;clrt     %0"
    btsti       %1,%2\;clrt     %0"
  [(set_attr "length" "4")])
  [(set_attr "length" "4")])
; turns sextb rx/btsti rx,31 into btsti rx,7.  must be QImode to be safe.  BRC
; turns sextb rx/btsti rx,31 into btsti rx,7.  must be QImode to be safe.  BRC
(define_insn ""
(define_insn ""
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r,r,r,r")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r,r,r,r")
        (if_then_else:SI (eq (lshiftrt:SI
        (if_then_else:SI (eq (lshiftrt:SI
                              (match_operand:SI 1 "mcore_arith_reg_operand" "r,r,r,r")
                              (match_operand:SI 1 "mcore_arith_reg_operand" "r,r,r,r")
                              (const_int 7))
                              (const_int 7))
                             (const_int 0))
                             (const_int 0))
                         (match_operand:SI 2 "mcore_arith_imm_operand" "r,0,U,0")
                         (match_operand:SI 2 "mcore_arith_imm_operand" "r,0,U,0")
                         (match_operand:SI 3 "mcore_arith_imm_operand" "0,r,0,U")))]
                         (match_operand:SI 3 "mcore_arith_imm_operand" "0,r,0,U")))]
  "GET_CODE (operands[1]) == SUBREG &&
  "GET_CODE (operands[1]) == SUBREG &&
      GET_MODE (SUBREG_REG (operands[1])) == QImode"
      GET_MODE (SUBREG_REG (operands[1])) == QImode"
  "@
  "@
    btsti       %1,7\;movf      %0,%2
    btsti       %1,7\;movf      %0,%2
    btsti       %1,7\;movt      %0,%3
    btsti       %1,7\;movt      %0,%3
    btsti       %1,7\;clrf      %0
    btsti       %1,7\;clrf      %0
    btsti       %1,7\;clrt      %0"
    btsti       %1,7\;clrt      %0"
  [(set_attr "length" "4")])
  [(set_attr "length" "4")])
;; ------------------------------------------------------------------------
;; ------------------------------------------------------------------------
;; ne
;; ne
;; ------------------------------------------------------------------------
;; ------------------------------------------------------------------------
;; Combine creates this from an andn instruction in a scc sequence.
;; Combine creates this from an andn instruction in a scc sequence.
;; We must recognize it to get conditional moves generated.
;; We must recognize it to get conditional moves generated.
; experimental conditional move with two constants +/- 1  BRC
; experimental conditional move with two constants +/- 1  BRC
(define_insn "movtK_3"
(define_insn "movtK_3"
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r")
        (if_then_else:SI
        (if_then_else:SI
            (ne (match_operand:SI 1 "mcore_arith_reg_operand" "r")
            (ne (match_operand:SI 1 "mcore_arith_reg_operand" "r")
                (const_int 0))
                (const_int 0))
          (match_operand:SI 2 "mcore_arith_O_operand" "O")
          (match_operand:SI 2 "mcore_arith_O_operand" "O")
          (match_operand:SI 3 "mcore_arith_O_operand" "O")))]
          (match_operand:SI 3 "mcore_arith_O_operand" "O")))]
  "  GET_CODE (operands[2]) == CONST_INT
  "  GET_CODE (operands[2]) == CONST_INT
  && GET_CODE (operands[3]) == CONST_INT
  && GET_CODE (operands[3]) == CONST_INT
  && (   (INTVAL (operands[2]) - INTVAL (operands[3]) == 1)
  && (   (INTVAL (operands[2]) - INTVAL (operands[3]) == 1)
      || (INTVAL (operands[3]) - INTVAL (operands[2]) == 1))"
      || (INTVAL (operands[3]) - INTVAL (operands[2]) == 1))"
  "*
  "*
{
{
  rtx out_operands[4];
  rtx out_operands[4];
  out_operands[0] = operands[0];
  out_operands[0] = operands[0];
  out_operands[1] = operands[2];
  out_operands[1] = operands[2];
  out_operands[2] = operands[3];
  out_operands[2] = operands[3];
  out_operands[3] = operands[1];
  out_operands[3] = operands[1];
  return mcore_output_cmov (out_operands, 1, \"cmpnei   %3,0\");
  return mcore_output_cmov (out_operands, 1, \"cmpnei   %3,0\");
}"
}"
  [(set_attr "length" "6")])
  [(set_attr "length" "6")])
(define_insn "movt2"
(define_insn "movt2"
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r,r,r,r")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r,r,r,r")
        (if_then_else:SI (ne (match_operand:SI 1 "mcore_arith_reg_operand" "r,r,r,r")
        (if_then_else:SI (ne (match_operand:SI 1 "mcore_arith_reg_operand" "r,r,r,r")
                             (const_int 0))
                             (const_int 0))
                         (match_operand:SI 2 "mcore_arith_imm_operand" "r,0,U,0")
                         (match_operand:SI 2 "mcore_arith_imm_operand" "r,0,U,0")
                         (match_operand:SI 3 "mcore_arith_imm_operand" "0,r,0,U")))]
                         (match_operand:SI 3 "mcore_arith_imm_operand" "0,r,0,U")))]
  ""
  ""
  "@
  "@
    cmpnei      %1,0\;movt      %0,%2
    cmpnei      %1,0\;movt      %0,%2
    cmpnei      %1,0\;movf      %0,%3
    cmpnei      %1,0\;movf      %0,%3
    cmpnei      %1,0\;clrt      %0
    cmpnei      %1,0\;clrt      %0
    cmpnei      %1,0\;clrf      %0"
    cmpnei      %1,0\;clrf      %0"
  [(set_attr "length" "4")])
  [(set_attr "length" "4")])
; turns lsli rx,imm/btsti rx,31 into btsti rx,imm.  not done by a peephole
; turns lsli rx,imm/btsti rx,31 into btsti rx,imm.  not done by a peephole
; because the instructions are not adjacent (peepholes are related by posn -
; because the instructions are not adjacent (peepholes are related by posn -
; not by dataflow).   BRC
; not by dataflow).   BRC
(define_insn ""
(define_insn ""
 [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r,r,r,r")
 [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r,r,r,r")
        (if_then_else:SI (ne (zero_extract:SI
        (if_then_else:SI (ne (zero_extract:SI
                              (match_operand:SI 1 "mcore_arith_reg_operand" "r,r,r,r")
                              (match_operand:SI 1 "mcore_arith_reg_operand" "r,r,r,r")
                              (const_int 1)
                              (const_int 1)
                              (match_operand:SI 2 "mcore_literal_K_operand" "K,K,K,K"))
                              (match_operand:SI 2 "mcore_literal_K_operand" "K,K,K,K"))
                             (const_int 0))
                             (const_int 0))
                         (match_operand:SI 3 "mcore_arith_imm_operand" "r,0,U,0")
                         (match_operand:SI 3 "mcore_arith_imm_operand" "r,0,U,0")
                         (match_operand:SI 4 "mcore_arith_imm_operand" "0,r,0,U")))]
                         (match_operand:SI 4 "mcore_arith_imm_operand" "0,r,0,U")))]
  ""
  ""
  "@
  "@
    btsti       %1,%2\;movt     %0,%3
    btsti       %1,%2\;movt     %0,%3
    btsti       %1,%2\;movf     %0,%4
    btsti       %1,%2\;movf     %0,%4
    btsti       %1,%2\;clrt     %0
    btsti       %1,%2\;clrt     %0
    btsti       %1,%2\;clrf     %0"
    btsti       %1,%2\;clrf     %0"
  [(set_attr "length" "4")])
  [(set_attr "length" "4")])
; turns sextb rx/btsti rx,31 into btsti rx,7.  must be QImode to be safe.  BRC
; turns sextb rx/btsti rx,31 into btsti rx,7.  must be QImode to be safe.  BRC
(define_insn ""
(define_insn ""
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r,r,r,r")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r,r,r,r")
        (if_then_else:SI (ne (lshiftrt:SI
        (if_then_else:SI (ne (lshiftrt:SI
                              (match_operand:SI 1 "mcore_arith_reg_operand" "r,r,r,r")
                              (match_operand:SI 1 "mcore_arith_reg_operand" "r,r,r,r")
                              (const_int 7))
                              (const_int 7))
                             (const_int 0))
                             (const_int 0))
                         (match_operand:SI 2 "mcore_arith_imm_operand" "r,0,U,0")
                         (match_operand:SI 2 "mcore_arith_imm_operand" "r,0,U,0")
                         (match_operand:SI 3 "mcore_arith_imm_operand" "0,r,0,U")))]
                         (match_operand:SI 3 "mcore_arith_imm_operand" "0,r,0,U")))]
  "GET_CODE (operands[1]) == SUBREG &&
  "GET_CODE (operands[1]) == SUBREG &&
      GET_MODE (SUBREG_REG (operands[1])) == QImode"
      GET_MODE (SUBREG_REG (operands[1])) == QImode"
  "@
  "@
    btsti       %1,7\;movt      %0,%2
    btsti       %1,7\;movt      %0,%2
    btsti       %1,7\;movf      %0,%3
    btsti       %1,7\;movf      %0,%3
    btsti       %1,7\;clrt      %0
    btsti       %1,7\;clrt      %0
    btsti       %1,7\;clrf      %0"
    btsti       %1,7\;clrf      %0"
  [(set_attr "length" "4")])
  [(set_attr "length" "4")])
;; ------------------------------------------------------------------------
;; ------------------------------------------------------------------------
;; eq/eq
;; eq/eq
;; ------------------------------------------------------------------------
;; ------------------------------------------------------------------------
; experimental conditional move with two constants +/- 1  BRC
; experimental conditional move with two constants +/- 1  BRC
(define_insn "movtK_4"
(define_insn "movtK_4"
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r")
        (if_then_else:SI
        (if_then_else:SI
            (eq (eq:SI (reg:CC 17) (const_int 0)) (const_int 0))
            (eq (eq:SI (reg:CC 17) (const_int 0)) (const_int 0))
          (match_operand:SI 1 "mcore_arith_O_operand" "O")
          (match_operand:SI 1 "mcore_arith_O_operand" "O")
          (match_operand:SI 2 "mcore_arith_O_operand" "O")))]
          (match_operand:SI 2 "mcore_arith_O_operand" "O")))]
  "GET_CODE (operands[1]) == CONST_INT &&
  "GET_CODE (operands[1]) == CONST_INT &&
   GET_CODE (operands[2]) == CONST_INT &&
   GET_CODE (operands[2]) == CONST_INT &&
   ((INTVAL (operands[1]) - INTVAL (operands[2]) == 1) ||
   ((INTVAL (operands[1]) - INTVAL (operands[2]) == 1) ||
   (INTVAL (operands[2]) - INTVAL (operands[1]) == 1))"
   (INTVAL (operands[2]) - INTVAL (operands[1]) == 1))"
  "* return mcore_output_cmov(operands, 1, NULL);"
  "* return mcore_output_cmov(operands, 1, NULL);"
  [(set_attr "length" "4")])
  [(set_attr "length" "4")])
(define_insn "movt3"
(define_insn "movt3"
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r,r,r,r")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r,r,r,r")
        (if_then_else:SI
        (if_then_else:SI
         (eq (eq:SI (reg:CC 17) (const_int 0)) (const_int 0))
         (eq (eq:SI (reg:CC 17) (const_int 0)) (const_int 0))
         (match_operand:SI 1 "mcore_arith_imm_operand" "r,0,U,0")
         (match_operand:SI 1 "mcore_arith_imm_operand" "r,0,U,0")
         (match_operand:SI 2 "mcore_arith_imm_operand" "0,r,0,U")))]
         (match_operand:SI 2 "mcore_arith_imm_operand" "0,r,0,U")))]
  ""
  ""
  "@
  "@
    movt        %0,%1
    movt        %0,%1
    movf        %0,%2
    movf        %0,%2
    clrt        %0
    clrt        %0
    clrf        %0")
    clrf        %0")
;; ------------------------------------------------------------------------
;; ------------------------------------------------------------------------
;; eq/ne
;; eq/ne
;; ------------------------------------------------------------------------
;; ------------------------------------------------------------------------
; experimental conditional move with two constants +/- 1  BRC
; experimental conditional move with two constants +/- 1  BRC
(define_insn "movtK_5"
(define_insn "movtK_5"
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r")
        (if_then_else:SI
        (if_then_else:SI
            (eq (ne:SI (reg:CC 17) (const_int 0)) (const_int 0))
            (eq (ne:SI (reg:CC 17) (const_int 0)) (const_int 0))
          (match_operand:SI 1 "mcore_arith_O_operand" "O")
          (match_operand:SI 1 "mcore_arith_O_operand" "O")
          (match_operand:SI 2 "mcore_arith_O_operand" "O")))]
          (match_operand:SI 2 "mcore_arith_O_operand" "O")))]
  "GET_CODE (operands[1]) == CONST_INT &&
  "GET_CODE (operands[1]) == CONST_INT &&
   GET_CODE (operands[2]) == CONST_INT &&
   GET_CODE (operands[2]) == CONST_INT &&
   ((INTVAL (operands[1]) - INTVAL (operands[2]) == 1) ||
   ((INTVAL (operands[1]) - INTVAL (operands[2]) == 1) ||
    (INTVAL (operands[2]) - INTVAL (operands[1]) == 1))"
    (INTVAL (operands[2]) - INTVAL (operands[1]) == 1))"
  "* return mcore_output_cmov (operands, 0, NULL);"
  "* return mcore_output_cmov (operands, 0, NULL);"
  [(set_attr "length" "4")])
  [(set_attr "length" "4")])
(define_insn "movf1"
(define_insn "movf1"
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r,r,r,r")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r,r,r,r")
        (if_then_else:SI
        (if_then_else:SI
         (eq (ne:SI (reg:CC 17) (const_int 0)) (const_int 0))
         (eq (ne:SI (reg:CC 17) (const_int 0)) (const_int 0))
         (match_operand:SI 1 "mcore_arith_imm_operand" "r,0,U,0")
         (match_operand:SI 1 "mcore_arith_imm_operand" "r,0,U,0")
         (match_operand:SI 2 "mcore_arith_imm_operand" "0,r,0,U")))]
         (match_operand:SI 2 "mcore_arith_imm_operand" "0,r,0,U")))]
  ""
  ""
  "@
  "@
    movf        %0,%1
    movf        %0,%1
    movt        %0,%2
    movt        %0,%2
    clrf        %0
    clrf        %0
    clrt        %0")
    clrt        %0")
;; ------------------------------------------------------------------------
;; ------------------------------------------------------------------------
;; eq
;; eq
;; ------------------------------------------------------------------------
;; ------------------------------------------------------------------------
;; Combine creates this from an andn instruction in a scc sequence.
;; Combine creates this from an andn instruction in a scc sequence.
;; We must recognize it to get conditional moves generated.
;; We must recognize it to get conditional moves generated.
; experimental conditional move with two constants +/- 1  BRC
; experimental conditional move with two constants +/- 1  BRC
(define_insn "movtK_6"
(define_insn "movtK_6"
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r")
        (if_then_else:SI
        (if_then_else:SI
            (eq (match_operand:SI 1 "mcore_arith_reg_operand" "r")
            (eq (match_operand:SI 1 "mcore_arith_reg_operand" "r")
                (const_int 0))
                (const_int 0))
          (match_operand:SI 2 "mcore_arith_O_operand" "O")
          (match_operand:SI 2 "mcore_arith_O_operand" "O")
          (match_operand:SI 3 "mcore_arith_O_operand" "O")))]
          (match_operand:SI 3 "mcore_arith_O_operand" "O")))]
  "GET_CODE (operands[1]) == CONST_INT &&
  "GET_CODE (operands[1]) == CONST_INT &&
   GET_CODE (operands[2]) == CONST_INT &&
   GET_CODE (operands[2]) == CONST_INT &&
   ((INTVAL (operands[2]) - INTVAL (operands[3]) == 1) ||
   ((INTVAL (operands[2]) - INTVAL (operands[3]) == 1) ||
    (INTVAL (operands[3]) - INTVAL (operands[2]) == 1))"
    (INTVAL (operands[3]) - INTVAL (operands[2]) == 1))"
  "*
  "*
{
{
   rtx out_operands[4];
   rtx out_operands[4];
   out_operands[0] = operands[0];
   out_operands[0] = operands[0];
   out_operands[1] = operands[2];
   out_operands[1] = operands[2];
   out_operands[2] = operands[3];
   out_operands[2] = operands[3];
   out_operands[3] = operands[1];
   out_operands[3] = operands[1];
   return mcore_output_cmov (out_operands, 0, \"cmpnei  %3,0\");
   return mcore_output_cmov (out_operands, 0, \"cmpnei  %3,0\");
}"
}"
  [(set_attr "length" "6")])
  [(set_attr "length" "6")])
(define_insn "movf3"
(define_insn "movf3"
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r,r,r,r")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r,r,r,r")
        (if_then_else:SI (eq (match_operand:SI 1 "mcore_arith_reg_operand" "r,r,r,r")
        (if_then_else:SI (eq (match_operand:SI 1 "mcore_arith_reg_operand" "r,r,r,r")
                             (const_int 0))
                             (const_int 0))
                         (match_operand:SI 2 "mcore_arith_imm_operand" "r,0,U,0")
                         (match_operand:SI 2 "mcore_arith_imm_operand" "r,0,U,0")
                         (match_operand:SI 3 "mcore_arith_imm_operand" "0,r,0,U")))]
                         (match_operand:SI 3 "mcore_arith_imm_operand" "0,r,0,U")))]
  ""
  ""
  "@
  "@
    cmpnei      %1,0\;movf      %0,%2
    cmpnei      %1,0\;movf      %0,%2
    cmpnei      %1,0\;movt      %0,%3
    cmpnei      %1,0\;movt      %0,%3
    cmpnei      %1,0\;clrf      %0
    cmpnei      %1,0\;clrf      %0
    cmpnei      %1,0\;clrt      %0"
    cmpnei      %1,0\;clrt      %0"
  [(set_attr "length" "4")])
  [(set_attr "length" "4")])
;; ------------------------------------------------------------------------
;; ------------------------------------------------------------------------
;; ne/eq
;; ne/eq
;; ------------------------------------------------------------------------
;; ------------------------------------------------------------------------
; experimental conditional move with two constants +/- 1  BRC
; experimental conditional move with two constants +/- 1  BRC
(define_insn "movtK_7"
(define_insn "movtK_7"
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r")
        (if_then_else:SI
        (if_then_else:SI
            (ne (eq:SI (reg:CC 17) (const_int 0)) (const_int 0))
            (ne (eq:SI (reg:CC 17) (const_int 0)) (const_int 0))
          (match_operand:SI 1 "mcore_arith_O_operand" "O")
          (match_operand:SI 1 "mcore_arith_O_operand" "O")
          (match_operand:SI 2 "mcore_arith_O_operand" "O")))]
          (match_operand:SI 2 "mcore_arith_O_operand" "O")))]
  "GET_CODE (operands[1]) == CONST_INT &&
  "GET_CODE (operands[1]) == CONST_INT &&
   GET_CODE (operands[2]) == CONST_INT &&
   GET_CODE (operands[2]) == CONST_INT &&
   ((INTVAL (operands[1]) - INTVAL (operands[2]) == 1) ||
   ((INTVAL (operands[1]) - INTVAL (operands[2]) == 1) ||
    (INTVAL (operands[2]) - INTVAL (operands[1]) == 1))"
    (INTVAL (operands[2]) - INTVAL (operands[1]) == 1))"
  "* return mcore_output_cmov (operands, 0, NULL);"
  "* return mcore_output_cmov (operands, 0, NULL);"
  [(set_attr "length" "4")])
  [(set_attr "length" "4")])
(define_insn "movf4"
(define_insn "movf4"
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r,r,r,r")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r,r,r,r")
        (if_then_else:SI
        (if_then_else:SI
         (ne (eq:SI (reg:CC 17) (const_int 0)) (const_int 0))
         (ne (eq:SI (reg:CC 17) (const_int 0)) (const_int 0))
         (match_operand:SI 1 "mcore_arith_imm_operand" "r,0,U,0")
         (match_operand:SI 1 "mcore_arith_imm_operand" "r,0,U,0")
         (match_operand:SI 2 "mcore_arith_imm_operand" "0,r,0,U")))]
         (match_operand:SI 2 "mcore_arith_imm_operand" "0,r,0,U")))]
  ""
  ""
  "@
  "@
    movf        %0,%1
    movf        %0,%1
    movt        %0,%2
    movt        %0,%2
    clrf        %0
    clrf        %0
    clrt        %0")
    clrt        %0")
;; ------------------------------------------------------------------------
;; ------------------------------------------------------------------------
;; ne/ne
;; ne/ne
;; ------------------------------------------------------------------------
;; ------------------------------------------------------------------------
; experimental conditional move with two constants +/- 1  BRC
; experimental conditional move with two constants +/- 1  BRC
(define_insn "movtK_8"
(define_insn "movtK_8"
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r")
        (if_then_else:SI
        (if_then_else:SI
            (ne (ne:SI (reg:CC 17) (const_int 0)) (const_int 0))
            (ne (ne:SI (reg:CC 17) (const_int 0)) (const_int 0))
          (match_operand:SI 1 "mcore_arith_O_operand" "O")
          (match_operand:SI 1 "mcore_arith_O_operand" "O")
          (match_operand:SI 2 "mcore_arith_O_operand" "O")))]
          (match_operand:SI 2 "mcore_arith_O_operand" "O")))]
  "GET_CODE (operands[1]) == CONST_INT &&
  "GET_CODE (operands[1]) == CONST_INT &&
   GET_CODE (operands[2]) == CONST_INT &&
   GET_CODE (operands[2]) == CONST_INT &&
   ((INTVAL (operands[1]) - INTVAL (operands[2]) == 1) ||
   ((INTVAL (operands[1]) - INTVAL (operands[2]) == 1) ||
    (INTVAL (operands[2]) - INTVAL (operands[1]) == 1))"
    (INTVAL (operands[2]) - INTVAL (operands[1]) == 1))"
  "* return mcore_output_cmov (operands, 1, NULL);"
  "* return mcore_output_cmov (operands, 1, NULL);"
  [(set_attr "length" "4")])
  [(set_attr "length" "4")])
(define_insn "movt4"
(define_insn "movt4"
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r,r,r,r")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r,r,r,r")
        (if_then_else:SI
        (if_then_else:SI
         (ne (ne:SI (reg:CC 17) (const_int 0)) (const_int 0))
         (ne (ne:SI (reg:CC 17) (const_int 0)) (const_int 0))
         (match_operand:SI 1 "mcore_arith_imm_operand" "r,0,U,0")
         (match_operand:SI 1 "mcore_arith_imm_operand" "r,0,U,0")
         (match_operand:SI 2 "mcore_arith_imm_operand" "0,r,0,U")))]
         (match_operand:SI 2 "mcore_arith_imm_operand" "0,r,0,U")))]
  ""
  ""
  "@
  "@
    movt        %0,%1
    movt        %0,%1
    movf        %0,%2
    movf        %0,%2
    clrt        %0
    clrt        %0
    clrf        %0")
    clrf        %0")
;; Also need patterns to recognize lt/ge, since otherwise the compiler will
;; Also need patterns to recognize lt/ge, since otherwise the compiler will
;; try to output not/asri/tstne/movf.
;; try to output not/asri/tstne/movf.
;; ------------------------------------------------------------------------
;; ------------------------------------------------------------------------
;; lt
;; lt
;; ------------------------------------------------------------------------
;; ------------------------------------------------------------------------
; experimental conditional move with two constants +/- 1  BRC
; experimental conditional move with two constants +/- 1  BRC
(define_insn "movtK_9"
(define_insn "movtK_9"
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r")
        (if_then_else:SI
        (if_then_else:SI
            (lt (match_operand:SI 1 "mcore_arith_reg_operand" "r")
            (lt (match_operand:SI 1 "mcore_arith_reg_operand" "r")
                (const_int 0))
                (const_int 0))
          (match_operand:SI 2 "mcore_arith_O_operand" "O")
          (match_operand:SI 2 "mcore_arith_O_operand" "O")
          (match_operand:SI 3 "mcore_arith_O_operand" "O")))]
          (match_operand:SI 3 "mcore_arith_O_operand" "O")))]
  "GET_CODE (operands[2]) == CONST_INT &&
  "GET_CODE (operands[2]) == CONST_INT &&
   GET_CODE (operands[3]) == CONST_INT &&
   GET_CODE (operands[3]) == CONST_INT &&
   ((INTVAL (operands[2]) - INTVAL (operands[3]) == 1) ||
   ((INTVAL (operands[2]) - INTVAL (operands[3]) == 1) ||
    (INTVAL (operands[3]) - INTVAL (operands[2]) == 1))"
    (INTVAL (operands[3]) - INTVAL (operands[2]) == 1))"
  "*
  "*
{
{
   rtx out_operands[4];
   rtx out_operands[4];
   out_operands[0] = operands[0];
   out_operands[0] = operands[0];
   out_operands[1] = operands[2];
   out_operands[1] = operands[2];
   out_operands[2] = operands[3];
   out_operands[2] = operands[3];
   out_operands[3] = operands[1];
   out_operands[3] = operands[1];
   return mcore_output_cmov (out_operands, 1, \"btsti   %3,31\");
   return mcore_output_cmov (out_operands, 1, \"btsti   %3,31\");
}"
}"
  [(set_attr "length" "6")])
  [(set_attr "length" "6")])
(define_insn "movt5"
(define_insn "movt5"
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r,r,r,r")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r,r,r,r")
        (if_then_else:SI (lt (match_operand:SI 1 "mcore_arith_reg_operand" "r,r,r,r")
        (if_then_else:SI (lt (match_operand:SI 1 "mcore_arith_reg_operand" "r,r,r,r")
                             (const_int 0))
                             (const_int 0))
                         (match_operand:SI 2 "mcore_arith_imm_operand" "r,0,U,0")
                         (match_operand:SI 2 "mcore_arith_imm_operand" "r,0,U,0")
                         (match_operand:SI 3 "mcore_arith_imm_operand" "0,r,0,U")))]
                         (match_operand:SI 3 "mcore_arith_imm_operand" "0,r,0,U")))]
  ""
  ""
  "@
  "@
    btsti       %1,31\;movt     %0,%2
    btsti       %1,31\;movt     %0,%2
    btsti       %1,31\;movf     %0,%3
    btsti       %1,31\;movf     %0,%3
    btsti       %1,31\;clrt     %0
    btsti       %1,31\;clrt     %0
    btsti       %1,31\;clrf     %0"
    btsti       %1,31\;clrf     %0"
  [(set_attr "length" "4")])
  [(set_attr "length" "4")])
;; ------------------------------------------------------------------------
;; ------------------------------------------------------------------------
;; ge
;; ge
;; ------------------------------------------------------------------------
;; ------------------------------------------------------------------------
; experimental conditional move with two constants +/- 1  BRC
; experimental conditional move with two constants +/- 1  BRC
(define_insn "movtK_10"
(define_insn "movtK_10"
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r")
        (if_then_else:SI
        (if_then_else:SI
            (ge (match_operand:SI 1 "mcore_arith_reg_operand" "r")
            (ge (match_operand:SI 1 "mcore_arith_reg_operand" "r")
                (const_int 0))
                (const_int 0))
          (match_operand:SI 2 "mcore_arith_O_operand" "O")
          (match_operand:SI 2 "mcore_arith_O_operand" "O")
          (match_operand:SI 3 "mcore_arith_O_operand" "O")))]
          (match_operand:SI 3 "mcore_arith_O_operand" "O")))]
  "GET_CODE (operands[2]) == CONST_INT &&
  "GET_CODE (operands[2]) == CONST_INT &&
   GET_CODE (operands[3]) == CONST_INT &&
   GET_CODE (operands[3]) == CONST_INT &&
   ((INTVAL (operands[2]) - INTVAL (operands[3]) == 1) ||
   ((INTVAL (operands[2]) - INTVAL (operands[3]) == 1) ||
    (INTVAL (operands[3]) - INTVAL (operands[2]) == 1))"
    (INTVAL (operands[3]) - INTVAL (operands[2]) == 1))"
  "*
  "*
{
{
  rtx out_operands[4];
  rtx out_operands[4];
  out_operands[0] = operands[0];
  out_operands[0] = operands[0];
  out_operands[1] = operands[2];
  out_operands[1] = operands[2];
  out_operands[2] = operands[3];
  out_operands[2] = operands[3];
  out_operands[3] = operands[1];
  out_operands[3] = operands[1];
   return mcore_output_cmov (out_operands, 0, \"btsti   %3,31\");
   return mcore_output_cmov (out_operands, 0, \"btsti   %3,31\");
}"
}"
  [(set_attr "length" "6")])
  [(set_attr "length" "6")])
(define_insn "movf5"
(define_insn "movf5"
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r,r,r,r")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r,r,r,r")
        (if_then_else:SI (ge (match_operand:SI 1 "mcore_arith_reg_operand" "r,r,r,r")
        (if_then_else:SI (ge (match_operand:SI 1 "mcore_arith_reg_operand" "r,r,r,r")
                             (const_int 0))
                             (const_int 0))
                         (match_operand:SI 2 "mcore_arith_imm_operand" "r,0,U,0")
                         (match_operand:SI 2 "mcore_arith_imm_operand" "r,0,U,0")
                         (match_operand:SI 3 "mcore_arith_imm_operand" "0,r,0,U")))]
                         (match_operand:SI 3 "mcore_arith_imm_operand" "0,r,0,U")))]
  ""
  ""
  "@
  "@
    btsti       %1,31\;movf     %0,%2
    btsti       %1,31\;movf     %0,%2
    btsti       %1,31\;movt     %0,%3
    btsti       %1,31\;movt     %0,%3
    btsti       %1,31\;clrf     %0
    btsti       %1,31\;clrf     %0
    btsti       %1,31\;clrt     %0"
    btsti       %1,31\;clrt     %0"
  [(set_attr "length" "4")])
  [(set_attr "length" "4")])
;; ------------------------------------------------------------------------
;; ------------------------------------------------------------------------
;; Bitfield extract (xtrbN)
;; Bitfield extract (xtrbN)
;; ------------------------------------------------------------------------
;; ------------------------------------------------------------------------
; sometimes we're better off using QI/HI mode and letting the machine indep.
; sometimes we're better off using QI/HI mode and letting the machine indep.
; part expand insv and extv.
; part expand insv and extv.
;
;
; e.g., sequences like:a        [an insertion]
; e.g., sequences like:a        [an insertion]
;
;
;      ldw r8,(r6)
;      ldw r8,(r6)
;      movi r7,0x00ffffff
;      movi r7,0x00ffffff
;      and r8,r7                 r7 dead
;      and r8,r7                 r7 dead
;      stw r8,(r6)                r8 dead
;      stw r8,(r6)                r8 dead
;
;
; become:
; become:
;
;
;      movi r8,0
;      movi r8,0
;      stb r8,(r6)              r8 dead
;      stb r8,(r6)              r8 dead
;
;
; it looks like always using SI mode is a win except in this type of code
; it looks like always using SI mode is a win except in this type of code
; (when adjacent bit fields collapse on a byte or halfword boundary).  when
; (when adjacent bit fields collapse on a byte or halfword boundary).  when
; expanding with SI mode, non-adjacent bit field masks fold, but with QI/HI
; expanding with SI mode, non-adjacent bit field masks fold, but with QI/HI
; mode, they do not.  one thought is to add some peepholes to cover cases
; mode, they do not.  one thought is to add some peepholes to cover cases
; like the above, but this is not a general solution.
; like the above, but this is not a general solution.
;
;
; -mword-bitfields expands/inserts using SI mode.  otherwise, do it with
; -mword-bitfields expands/inserts using SI mode.  otherwise, do it with
; the smallest mode possible (using the machine indep. expansions).  BRC
; the smallest mode possible (using the machine indep. expansions).  BRC
;(define_expand "extv"
;(define_expand "extv"
;  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "")
;  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "")
;       (sign_extract:SI (match_operand:SI 1 "mcore_arith_reg_operand" "")
;       (sign_extract:SI (match_operand:SI 1 "mcore_arith_reg_operand" "")
;                        (match_operand:SI 2 "const_int_operand" "")
;                        (match_operand:SI 2 "const_int_operand" "")
;                        (match_operand:SI 3 "const_int_operand" "")))
;                        (match_operand:SI 3 "const_int_operand" "")))
;   (clobber (reg:CC 17))]
;   (clobber (reg:CC 17))]
;  ""
;  ""
;  "
;  "
;{
;{
;  if (INTVAL (operands[1]) != 8 || INTVAL (operands[2]) % 8 != 0)
;  if (INTVAL (operands[1]) != 8 || INTVAL (operands[2]) % 8 != 0)
;    {
;    {
;     if (TARGET_W_FIELD)
;     if (TARGET_W_FIELD)
;       {
;       {
;        rtx lshft = GEN_INT (32 - (INTVAL (operands[2]) + INTVAL (operands[3])));
;        rtx lshft = GEN_INT (32 - (INTVAL (operands[2]) + INTVAL (operands[3])));
;        rtx rshft = GEN_INT (32 - INTVAL (operands[2]));
;        rtx rshft = GEN_INT (32 - INTVAL (operands[2]));
;
;
;        emit_insn (gen_rtx_SET (SImode, operands[0], operands[1]));
;        emit_insn (gen_rtx_SET (SImode, operands[0], operands[1]));
;        emit_insn (gen_rtx_SET (SImode, operands[0],
;        emit_insn (gen_rtx_SET (SImode, operands[0],
;                            gen_rtx_ASHIFT (SImode, operands[0], lshft)));
;                            gen_rtx_ASHIFT (SImode, operands[0], lshft)));
;        emit_insn (gen_rtx_SET (SImode, operands[0],
;        emit_insn (gen_rtx_SET (SImode, operands[0],
;                            gen_rtx_ASHIFTRT (SImode, operands[0], rshft)));
;                            gen_rtx_ASHIFTRT (SImode, operands[0], rshft)));
;        DONE;
;        DONE;
;     }
;     }
;     else
;     else
;        FAIL;
;        FAIL;
;  }
;  }
;}")
;}")
(define_expand "extv"
(define_expand "extv"
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "")
        (sign_extract:SI (match_operand:SI 1 "mcore_arith_reg_operand" "")
        (sign_extract:SI (match_operand:SI 1 "mcore_arith_reg_operand" "")
                         (match_operand:SI 2 "const_int_operand" "")
                         (match_operand:SI 2 "const_int_operand" "")
                         (match_operand:SI 3 "const_int_operand" "")))
                         (match_operand:SI 3 "const_int_operand" "")))
   (clobber (reg:CC 17))]
   (clobber (reg:CC 17))]
  ""
  ""
  "
  "
{
{
  if (INTVAL (operands[2]) == 8 && INTVAL (operands[3]) % 8 == 0)
  if (INTVAL (operands[2]) == 8 && INTVAL (operands[3]) % 8 == 0)
    {
    {
       /* 8 bit field, aligned properly, use the xtrb[0123]+sext sequence.  */
       /* 8 bit field, aligned properly, use the xtrb[0123]+sext sequence.  */
       /* not DONE, not FAIL, but let the RTL get generated....  */
       /* not DONE, not FAIL, but let the RTL get generated....  */
    }
    }
  else if (TARGET_W_FIELD)
  else if (TARGET_W_FIELD)
    {
    {
      /* Arbitrary placement; note that the tree->rtl generator will make
      /* Arbitrary placement; note that the tree->rtl generator will make
         something close to this if we return FAIL  */
         something close to this if we return FAIL  */
      rtx lshft = GEN_INT (32 - (INTVAL (operands[2]) + INTVAL (operands[3])));
      rtx lshft = GEN_INT (32 - (INTVAL (operands[2]) + INTVAL (operands[3])));
      rtx rshft = GEN_INT (32 - INTVAL (operands[2]));
      rtx rshft = GEN_INT (32 - INTVAL (operands[2]));
      rtx tmp1 = gen_reg_rtx (SImode);
      rtx tmp1 = gen_reg_rtx (SImode);
      rtx tmp2 = gen_reg_rtx (SImode);
      rtx tmp2 = gen_reg_rtx (SImode);
      emit_insn (gen_rtx_SET (SImode, tmp1, operands[1]));
      emit_insn (gen_rtx_SET (SImode, tmp1, operands[1]));
      emit_insn (gen_rtx_SET (SImode, tmp2,
      emit_insn (gen_rtx_SET (SImode, tmp2,
                         gen_rtx_ASHIFT (SImode, tmp1, lshft)));
                         gen_rtx_ASHIFT (SImode, tmp1, lshft)));
      emit_insn (gen_rtx_SET (SImode, operands[0],
      emit_insn (gen_rtx_SET (SImode, operands[0],
                         gen_rtx_ASHIFTRT (SImode, tmp2, rshft)));
                         gen_rtx_ASHIFTRT (SImode, tmp2, rshft)));
      DONE;
      DONE;
    }
    }
  else
  else
    {
    {
      /* Let the caller choose an alternate sequence.  */
      /* Let the caller choose an alternate sequence.  */
      FAIL;
      FAIL;
    }
    }
}")
}")
(define_expand "extzv"
(define_expand "extzv"
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "")
        (zero_extract:SI (match_operand:SI 1 "mcore_arith_reg_operand" "")
        (zero_extract:SI (match_operand:SI 1 "mcore_arith_reg_operand" "")
                         (match_operand:SI 2 "const_int_operand" "")
                         (match_operand:SI 2 "const_int_operand" "")
                         (match_operand:SI 3 "const_int_operand" "")))
                         (match_operand:SI 3 "const_int_operand" "")))
   (clobber (reg:CC 17))]
   (clobber (reg:CC 17))]
  ""
  ""
  "
  "
{
{
  if (INTVAL (operands[2]) == 8 && INTVAL (operands[3]) % 8 == 0)
  if (INTVAL (operands[2]) == 8 && INTVAL (operands[3]) % 8 == 0)
    {
    {
       /* 8 bit field, aligned properly, use the xtrb[0123] sequence.  */
       /* 8 bit field, aligned properly, use the xtrb[0123] sequence.  */
       /* Let the template generate some RTL....  */
       /* Let the template generate some RTL....  */
    }
    }
  else if (CONST_OK_FOR_K ((1 << INTVAL (operands[2])) - 1))
  else if (CONST_OK_FOR_K ((1 << INTVAL (operands[2])) - 1))
    {
    {
      /* A narrow bit-field (<=5 bits) means we can do a shift to put
      /* A narrow bit-field (<=5 bits) means we can do a shift to put
         it in place and then use an andi to extract it.
         it in place and then use an andi to extract it.
         This is as good as a shiftleft/shiftright.  */
         This is as good as a shiftleft/shiftright.  */
      rtx shifted;
      rtx shifted;
      rtx mask = GEN_INT ((1 << INTVAL (operands[2])) - 1);
      rtx mask = GEN_INT ((1 << INTVAL (operands[2])) - 1);
      if (INTVAL (operands[3]) == 0)
      if (INTVAL (operands[3]) == 0)
        {
        {
          shifted = operands[1];
          shifted = operands[1];
        }
        }
      else
      else
        {
        {
          rtx rshft = GEN_INT (INTVAL (operands[3]));
          rtx rshft = GEN_INT (INTVAL (operands[3]));
          shifted = gen_reg_rtx (SImode);
          shifted = gen_reg_rtx (SImode);
          emit_insn (gen_rtx_SET (SImode, shifted,
          emit_insn (gen_rtx_SET (SImode, shifted,
                         gen_rtx_LSHIFTRT (SImode, operands[1], rshft)));
                         gen_rtx_LSHIFTRT (SImode, operands[1], rshft)));
        }
        }
     emit_insn (gen_rtx_SET (SImode, operands[0],
     emit_insn (gen_rtx_SET (SImode, operands[0],
                       gen_rtx_AND (SImode, shifted, mask)));
                       gen_rtx_AND (SImode, shifted, mask)));
     DONE;
     DONE;
   }
   }
 else if (TARGET_W_FIELD)
 else if (TARGET_W_FIELD)
   {
   {
     /* Arbitrary pattern; play shift/shift games to get it.
     /* Arbitrary pattern; play shift/shift games to get it.
      * this is pretty much what the caller will do if we say FAIL */
      * this is pretty much what the caller will do if we say FAIL */
     rtx lshft = GEN_INT (32 - (INTVAL (operands[2]) + INTVAL (operands[3])));
     rtx lshft = GEN_INT (32 - (INTVAL (operands[2]) + INTVAL (operands[3])));
     rtx rshft = GEN_INT (32 - INTVAL (operands[2]));
     rtx rshft = GEN_INT (32 - INTVAL (operands[2]));
     rtx tmp1 = gen_reg_rtx (SImode);
     rtx tmp1 = gen_reg_rtx (SImode);
     rtx tmp2 = gen_reg_rtx (SImode);
     rtx tmp2 = gen_reg_rtx (SImode);
     emit_insn (gen_rtx_SET (SImode, tmp1, operands[1]));
     emit_insn (gen_rtx_SET (SImode, tmp1, operands[1]));
     emit_insn (gen_rtx_SET (SImode, tmp2,
     emit_insn (gen_rtx_SET (SImode, tmp2,
                         gen_rtx_ASHIFT (SImode, tmp1, lshft)));
                         gen_rtx_ASHIFT (SImode, tmp1, lshft)));
     emit_insn (gen_rtx_SET (SImode, operands[0],
     emit_insn (gen_rtx_SET (SImode, operands[0],
                       gen_rtx_LSHIFTRT (SImode, tmp2, rshft)));
                       gen_rtx_LSHIFTRT (SImode, tmp2, rshft)));
     DONE;
     DONE;
   }
   }
 else
 else
   {
   {
     /* Make the compiler figure out some alternative mechanism.  */
     /* Make the compiler figure out some alternative mechanism.  */
     FAIL;
     FAIL;
   }
   }
 /* Emit the RTL pattern; something will match it later.  */
 /* Emit the RTL pattern; something will match it later.  */
}")
}")
(define_expand "insv"
(define_expand "insv"
  [(set (zero_extract:SI (match_operand:SI 0 "mcore_arith_reg_operand" "")
  [(set (zero_extract:SI (match_operand:SI 0 "mcore_arith_reg_operand" "")
                         (match_operand:SI 1 "const_int_operand" "")
                         (match_operand:SI 1 "const_int_operand" "")
                         (match_operand:SI 2 "const_int_operand" ""))
                         (match_operand:SI 2 "const_int_operand" ""))
        (match_operand:SI 3 "general_operand" ""))
        (match_operand:SI 3 "general_operand" ""))
   (clobber (reg:CC 17))]
   (clobber (reg:CC 17))]
  ""
  ""
  "
  "
{
{
  if (mcore_expand_insv (operands))
  if (mcore_expand_insv (operands))
    {
    {
      DONE;
      DONE;
    }
    }
  else
  else
    {
    {
      FAIL;
      FAIL;
    }
    }
}")
}")
;;
;;
;; the xtrb[0123] instructions handily get at 8-bit fields on nice boundaries.
;; the xtrb[0123] instructions handily get at 8-bit fields on nice boundaries.
;; but then, they do force you through r1.
;; but then, they do force you through r1.
;;
;;
;; the combiner will build such patterns for us, so we'll make them available
;; the combiner will build such patterns for us, so we'll make them available
;; for its use.
;; for its use.
;;
;;
;; Note that we have both SIGNED and UNSIGNED versions of these...
;; Note that we have both SIGNED and UNSIGNED versions of these...
;;
;;
;;
;;
;; These no longer worry about the clobbering of CC bit; not sure this is
;; These no longer worry about the clobbering of CC bit; not sure this is
;; good...
;; good...
;;
;;
;; the SIGNED versions of these
;; the SIGNED versions of these
;;
;;
(define_insn ""
(define_insn ""
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r,b")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r,b")
        (sign_extract:SI (match_operand:SI 1 "mcore_arith_reg_operand" "0,r") (const_int 8) (const_int 24)))]
        (sign_extract:SI (match_operand:SI 1 "mcore_arith_reg_operand" "0,r") (const_int 8) (const_int 24)))]
  ""
  ""
  "@
  "@
        asri    %0,24
        asri    %0,24
        xtrb0   %0,%1\;sextb    %0"
        xtrb0   %0,%1\;sextb    %0"
  [(set_attr "type" "shift")])
  [(set_attr "type" "shift")])
(define_insn ""
(define_insn ""
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=b")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=b")
        (sign_extract:SI (match_operand:SI 1 "mcore_arith_reg_operand" "r") (const_int 8) (const_int 16)))]
        (sign_extract:SI (match_operand:SI 1 "mcore_arith_reg_operand" "r") (const_int 8) (const_int 16)))]
  ""
  ""
  "xtrb1        %0,%1\;sextb    %0"
  "xtrb1        %0,%1\;sextb    %0"
  [(set_attr "type" "shift")])
  [(set_attr "type" "shift")])
(define_insn ""
(define_insn ""
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=b")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=b")
        (sign_extract:SI (match_operand:SI 1 "mcore_arith_reg_operand" "r") (const_int 8) (const_int 8)))]
        (sign_extract:SI (match_operand:SI 1 "mcore_arith_reg_operand" "r") (const_int 8) (const_int 8)))]
  ""
  ""
  "xtrb2        %0,%1\;sextb    %0"
  "xtrb2        %0,%1\;sextb    %0"
  [(set_attr "type" "shift")])
  [(set_attr "type" "shift")])
(define_insn ""
(define_insn ""
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r")
        (sign_extract:SI (match_operand:SI 1 "mcore_arith_reg_operand" "0") (const_int 8) (const_int 0)))]
        (sign_extract:SI (match_operand:SI 1 "mcore_arith_reg_operand" "0") (const_int 8) (const_int 0)))]
  ""
  ""
  "sextb        %0"
  "sextb        %0"
  [(set_attr "type" "shift")])
  [(set_attr "type" "shift")])
;; the UNSIGNED uses of xtrb[0123]
;; the UNSIGNED uses of xtrb[0123]
;;
;;
(define_insn ""
(define_insn ""
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r,b")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r,b")
        (zero_extract:SI (match_operand:SI 1 "mcore_arith_reg_operand" "0,r") (const_int 8) (const_int 24)))]
        (zero_extract:SI (match_operand:SI 1 "mcore_arith_reg_operand" "0,r") (const_int 8) (const_int 24)))]
  ""
  ""
  "@
  "@
        lsri    %0,24
        lsri    %0,24
        xtrb0   %0,%1"
        xtrb0   %0,%1"
  [(set_attr "type" "shift")])
  [(set_attr "type" "shift")])
(define_insn ""
(define_insn ""
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=b")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=b")
        (zero_extract:SI (match_operand:SI 1 "mcore_arith_reg_operand" "r") (const_int 8) (const_int 16)))]
        (zero_extract:SI (match_operand:SI 1 "mcore_arith_reg_operand" "r") (const_int 8) (const_int 16)))]
  ""
  ""
  "xtrb1        %0,%1"
  "xtrb1        %0,%1"
  [(set_attr "type" "shift")])
  [(set_attr "type" "shift")])
(define_insn ""
(define_insn ""
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=b")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=b")
        (zero_extract:SI (match_operand:SI 1 "mcore_arith_reg_operand" "r") (const_int 8) (const_int 8)))]
        (zero_extract:SI (match_operand:SI 1 "mcore_arith_reg_operand" "r") (const_int 8) (const_int 8)))]
  ""
  ""
  "xtrb2        %0,%1"
  "xtrb2        %0,%1"
  [(set_attr "type" "shift")])
  [(set_attr "type" "shift")])
;; This can be peepholed if it follows a ldb ...
;; This can be peepholed if it follows a ldb ...
(define_insn ""
(define_insn ""
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r,b")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r,b")
        (zero_extract:SI (match_operand:SI 1 "mcore_arith_reg_operand" "0,r") (const_int 8) (const_int 0)))]
        (zero_extract:SI (match_operand:SI 1 "mcore_arith_reg_operand" "0,r") (const_int 8) (const_int 0)))]
  ""
  ""
  "@
  "@
        zextb   %0
        zextb   %0
        xtrb3   %0,%1\;zextb    %0"
        xtrb3   %0,%1\;zextb    %0"
  [(set_attr "type" "shift")])
  [(set_attr "type" "shift")])
;; ------------------------------------------------------------------------
;; ------------------------------------------------------------------------
;; Block move - adapted from m88k.md
;; Block move - adapted from m88k.md
;; ------------------------------------------------------------------------
;; ------------------------------------------------------------------------
(define_expand "movmemsi"
(define_expand "movmemsi"
  [(parallel [(set (mem:BLK (match_operand:BLK 0 "" ""))
  [(parallel [(set (mem:BLK (match_operand:BLK 0 "" ""))
                   (mem:BLK (match_operand:BLK 1 "" "")))
                   (mem:BLK (match_operand:BLK 1 "" "")))
              (use (match_operand:SI 2 "general_operand" ""))
              (use (match_operand:SI 2 "general_operand" ""))
              (use (match_operand:SI 3 "immediate_operand" ""))])]
              (use (match_operand:SI 3 "immediate_operand" ""))])]
  ""
  ""
  "
  "
{
{
  if (mcore_expand_block_move (operands))
  if (mcore_expand_block_move (operands))
    DONE;
    DONE;
  else
  else
    FAIL;
    FAIL;
}")
}")
;; ;;; ??? These patterns are meant to be generated from expand_block_move,
;; ;;; ??? These patterns are meant to be generated from expand_block_move,
;; ;;; but they currently are not.
;; ;;; but they currently are not.
;;
;;
;; (define_insn ""
;; (define_insn ""
;;   [(set (match_operand:QI 0 "mcore_arith_reg_operand" "=r")
;;   [(set (match_operand:QI 0 "mcore_arith_reg_operand" "=r")
;;      (match_operand:BLK 1 "mcore_general_movsrc_operand" "m"))]
;;      (match_operand:BLK 1 "mcore_general_movsrc_operand" "m"))]
;;   ""
;;   ""
;;   "ld.b      %0,%1"
;;   "ld.b      %0,%1"
;;   [(set_attr "type" "load")])
;;   [(set_attr "type" "load")])
;;
;;
;; (define_insn ""
;; (define_insn ""
;;   [(set (match_operand:HI 0 "mcore_arith_reg_operand" "=r")
;;   [(set (match_operand:HI 0 "mcore_arith_reg_operand" "=r")
;;      (match_operand:BLK 1 "mcore_general_movsrc_operand" "m"))]
;;      (match_operand:BLK 1 "mcore_general_movsrc_operand" "m"))]
;;   ""
;;   ""
;;   "ld.h      %0,%1"
;;   "ld.h      %0,%1"
;;   [(set_attr "type" "load")])
;;   [(set_attr "type" "load")])
;;
;;
;; (define_insn ""
;; (define_insn ""
;;   [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r")
;;   [(set (match_operand:SI 0 "mcore_arith_reg_operand" "=r")
;;      (match_operand:BLK 1 "mcore_general_movsrc_operand" "m"))]
;;      (match_operand:BLK 1 "mcore_general_movsrc_operand" "m"))]
;;   ""
;;   ""
;;   "ld.w      %0,%1"
;;   "ld.w      %0,%1"
;;   [(set_attr "type" "load")])
;;   [(set_attr "type" "load")])
;;
;;
;; (define_insn ""
;; (define_insn ""
;;   [(set (match_operand:BLK 0 "mcore_general_movdst_operand" "=m")
;;   [(set (match_operand:BLK 0 "mcore_general_movdst_operand" "=m")
;;      (match_operand:QI 1 "mcore_arith_reg_operand" "r"))]
;;      (match_operand:QI 1 "mcore_arith_reg_operand" "r"))]
;;   ""
;;   ""
;;   "st.b      %1,%0"
;;   "st.b      %1,%0"
;;   [(set_attr "type" "store")])
;;   [(set_attr "type" "store")])
;;
;;
;; (define_insn ""
;; (define_insn ""
;;   [(set (match_operand:BLK 0 "mcore_general_movdst_operand" "=m")
;;   [(set (match_operand:BLK 0 "mcore_general_movdst_operand" "=m")
;;      (match_operand:HI 1 "mcore_arith_reg_operand" "r"))]
;;      (match_operand:HI 1 "mcore_arith_reg_operand" "r"))]
;;   ""
;;   ""
;;   "st.h      %1,%0"
;;   "st.h      %1,%0"
;;   [(set_attr "type" "store")])
;;   [(set_attr "type" "store")])
;;
;;
;; (define_insn ""
;; (define_insn ""
;;   [(set (match_operand:BLK 0 "mcore_general_movdst_operand" "=m")
;;   [(set (match_operand:BLK 0 "mcore_general_movdst_operand" "=m")
;;      (match_operand:SI 1 "mcore_arith_reg_operand" "r"))]
;;      (match_operand:SI 1 "mcore_arith_reg_operand" "r"))]
;;   ""
;;   ""
;;   "st.w      %1,%0"
;;   "st.w      %1,%0"
;;   [(set_attr "type" "store")])
;;   [(set_attr "type" "store")])


;; ------------------------------------------------------------------------
;; ------------------------------------------------------------------------
;; Misc Optimizing quirks
;; Misc Optimizing quirks
;; ------------------------------------------------------------------------
;; ------------------------------------------------------------------------
;; pair to catch constructs like:  (int *)((p+=4)-4) which happen
;; pair to catch constructs like:  (int *)((p+=4)-4) which happen
;; in stdarg/varargs traversal. This changes a 3 insn sequence to a 2
;; in stdarg/varargs traversal. This changes a 3 insn sequence to a 2
;; insn sequence. -- RBE 11/30/95
;; insn sequence. -- RBE 11/30/95
(define_insn ""
(define_insn ""
  [(parallel[
  [(parallel[
      (set (match_operand:SI 0 "mcore_arith_reg_operand" "=r")
      (set (match_operand:SI 0 "mcore_arith_reg_operand" "=r")
           (match_operand:SI 1 "mcore_arith_reg_operand" "+r"))
           (match_operand:SI 1 "mcore_arith_reg_operand" "+r"))
      (set (match_dup 1) (plus:SI (match_dup 1) (match_operand 2 "mcore_arith_any_imm_operand" "")))])]
      (set (match_dup 1) (plus:SI (match_dup 1) (match_operand 2 "mcore_arith_any_imm_operand" "")))])]
  "GET_CODE(operands[2]) == CONST_INT"
  "GET_CODE(operands[2]) == CONST_INT"
  "#"
  "#"
  [(set_attr "length" "4")])
  [(set_attr "length" "4")])
(define_split
(define_split
  [(parallel[
  [(parallel[
      (set (match_operand:SI 0 "mcore_arith_reg_operand" "")
      (set (match_operand:SI 0 "mcore_arith_reg_operand" "")
           (match_operand:SI 1 "mcore_arith_reg_operand" ""))
           (match_operand:SI 1 "mcore_arith_reg_operand" ""))
      (set (match_dup 1) (plus:SI (match_dup 1) (match_operand 2 "mcore_arith_any_imm_operand" "")))])]
      (set (match_dup 1) (plus:SI (match_dup 1) (match_operand 2 "mcore_arith_any_imm_operand" "")))])]
  "GET_CODE(operands[2]) == CONST_INT &&
  "GET_CODE(operands[2]) == CONST_INT &&
   operands[0] != operands[1]"
   operands[0] != operands[1]"
  [(set (match_dup 0) (match_dup 1))
  [(set (match_dup 0) (match_dup 1))
   (set (match_dup 1) (plus:SI (match_dup 1) (match_dup 2)))])
   (set (match_dup 1) (plus:SI (match_dup 1) (match_dup 2)))])


;;; Peepholes
;;; Peepholes
; note: in the following patterns, use mcore_is_dead() to ensure that the
; note: in the following patterns, use mcore_is_dead() to ensure that the
; reg we may be trashing really is dead.  reload doesn't always mark
; reg we may be trashing really is dead.  reload doesn't always mark
; deaths, so mcore_is_dead() (see mcore.c) scans forward to find its death.  BRC
; deaths, so mcore_is_dead() (see mcore.c) scans forward to find its death.  BRC
;;; A peephole to convert the 3 instruction sequence generated by reload
;;; A peephole to convert the 3 instruction sequence generated by reload
;;; to load a FP-offset address into a 2 instruction sequence.
;;; to load a FP-offset address into a 2 instruction sequence.
;;; ??? This probably never matches anymore.
;;; ??? This probably never matches anymore.
(define_peephole
(define_peephole
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "r")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "r")
        (match_operand:SI 1 "const_int_operand" "J"))
        (match_operand:SI 1 "const_int_operand" "J"))
   (set (match_dup 0) (neg:SI (match_dup 0)))
   (set (match_dup 0) (neg:SI (match_dup 0)))
   (set (match_dup 0)
   (set (match_dup 0)
        (plus:SI (match_dup 0)
        (plus:SI (match_dup 0)
                 (match_operand:SI 2 "mcore_arith_reg_operand" "r")))]
                 (match_operand:SI 2 "mcore_arith_reg_operand" "r")))]
  "CONST_OK_FOR_J (INTVAL (operands[1]))"
  "CONST_OK_FOR_J (INTVAL (operands[1]))"
  "error\;mov   %0,%2\;subi     %0,%1")
  "error\;mov   %0,%2\;subi     %0,%1")
;; Moves of inlinable constants are done late, so when a 'not' is generated
;; Moves of inlinable constants are done late, so when a 'not' is generated
;; it is never combined with the following 'and' to generate an 'andn' b/c
;; it is never combined with the following 'and' to generate an 'andn' b/c
;; the combiner never sees it.  use a peephole to pick up this case (happens
;; the combiner never sees it.  use a peephole to pick up this case (happens
;; mostly with bitfields)  BRC
;; mostly with bitfields)  BRC
(define_peephole
(define_peephole
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "r")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "r")
        (match_operand:SI 1 "const_int_operand" "i"))
        (match_operand:SI 1 "const_int_operand" "i"))
   (set (match_operand:SI 2 "mcore_arith_reg_operand" "r")
   (set (match_operand:SI 2 "mcore_arith_reg_operand" "r")
        (and:SI (match_dup 2) (match_dup 0)))]
        (and:SI (match_dup 2) (match_dup 0)))]
  "mcore_const_trick_uses_not (INTVAL (operands[1])) &&
  "mcore_const_trick_uses_not (INTVAL (operands[1])) &&
        operands[0] != operands[2] &&
        operands[0] != operands[2] &&
        mcore_is_dead (insn, operands[0])"
        mcore_is_dead (insn, operands[0])"
  "* return mcore_output_andn (insn, operands);")
  "* return mcore_output_andn (insn, operands);")
; when setting or clearing just two bits, it's cheapest to use two bseti's
; when setting or clearing just two bits, it's cheapest to use two bseti's
; or bclri's.  only happens when relaxing immediates.  BRC
; or bclri's.  only happens when relaxing immediates.  BRC
(define_peephole
(define_peephole
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "")
        (match_operand:SI 1 "const_int_operand" ""))
        (match_operand:SI 1 "const_int_operand" ""))
   (set (match_operand:SI 2 "mcore_arith_reg_operand" "")
   (set (match_operand:SI 2 "mcore_arith_reg_operand" "")
        (ior:SI (match_dup 2) (match_dup 0)))]
        (ior:SI (match_dup 2) (match_dup 0)))]
  "TARGET_HARDLIT && mcore_num_ones (INTVAL (operands[1])) == 2 &&
  "TARGET_HARDLIT && mcore_num_ones (INTVAL (operands[1])) == 2 &&
       mcore_is_dead (insn, operands[0])"
       mcore_is_dead (insn, operands[0])"
  "* return mcore_output_bseti (operands[2], INTVAL (operands[1]));")
  "* return mcore_output_bseti (operands[2], INTVAL (operands[1]));")
(define_peephole
(define_peephole
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "")
        (match_operand:SI 1 "const_int_operand" ""))
        (match_operand:SI 1 "const_int_operand" ""))
   (set (match_operand:SI 2 "mcore_arith_reg_operand" "")
   (set (match_operand:SI 2 "mcore_arith_reg_operand" "")
        (and:SI (match_dup 2) (match_dup 0)))]
        (and:SI (match_dup 2) (match_dup 0)))]
  "TARGET_HARDLIT && mcore_num_zeros (INTVAL (operands[1])) == 2 &&
  "TARGET_HARDLIT && mcore_num_zeros (INTVAL (operands[1])) == 2 &&
       mcore_is_dead (insn, operands[0])"
       mcore_is_dead (insn, operands[0])"
  "* return mcore_output_bclri (operands[2], INTVAL (operands[1]));")
  "* return mcore_output_bclri (operands[2], INTVAL (operands[1]));")
; change an and with a mask that has a single cleared bit into a bclri.  this
; change an and with a mask that has a single cleared bit into a bclri.  this
; handles QI and HI mode values using the knowledge that the most significant
; handles QI and HI mode values using the knowledge that the most significant
; bits don't matter.
; bits don't matter.
(define_peephole
(define_peephole
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "")
        (match_operand:SI 1 "const_int_operand" ""))
        (match_operand:SI 1 "const_int_operand" ""))
   (set (match_operand:SI 2 "mcore_arith_reg_operand" "")
   (set (match_operand:SI 2 "mcore_arith_reg_operand" "")
        (and:SI (match_operand:SI 3 "mcore_arith_reg_operand" "")
        (and:SI (match_operand:SI 3 "mcore_arith_reg_operand" "")
                (match_dup 0)))]
                (match_dup 0)))]
  "GET_CODE (operands[3]) == SUBREG &&
  "GET_CODE (operands[3]) == SUBREG &&
      GET_MODE (SUBREG_REG (operands[3])) == QImode &&
      GET_MODE (SUBREG_REG (operands[3])) == QImode &&
      mcore_num_zeros (INTVAL (operands[1]) | 0xffffff00) == 1 &&
      mcore_num_zeros (INTVAL (operands[1]) | 0xffffff00) == 1 &&
      mcore_is_dead (insn, operands[0])"
      mcore_is_dead (insn, operands[0])"
"*
"*
  if (! mcore_is_same_reg (operands[2], operands[3]))
  if (! mcore_is_same_reg (operands[2], operands[3]))
    output_asm_insn (\"mov\\t%2,%3\", operands);
    output_asm_insn (\"mov\\t%2,%3\", operands);
  return mcore_output_bclri (operands[2], INTVAL (operands[1]) | 0xffffff00);")
  return mcore_output_bclri (operands[2], INTVAL (operands[1]) | 0xffffff00);")
/* Do not fold these together -- mode is lost at final output phase.  */
/* Do not fold these together -- mode is lost at final output phase.  */
(define_peephole
(define_peephole
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "")
        (match_operand:SI 1 "const_int_operand" ""))
        (match_operand:SI 1 "const_int_operand" ""))
   (set (match_operand:SI 2 "mcore_arith_reg_operand" "")
   (set (match_operand:SI 2 "mcore_arith_reg_operand" "")
        (and:SI (match_operand:SI 3 "mcore_arith_reg_operand" "")
        (and:SI (match_operand:SI 3 "mcore_arith_reg_operand" "")
                (match_dup 0)))]
                (match_dup 0)))]
  "GET_CODE (operands[3]) == SUBREG &&
  "GET_CODE (operands[3]) == SUBREG &&
      GET_MODE (SUBREG_REG (operands[3])) == HImode &&
      GET_MODE (SUBREG_REG (operands[3])) == HImode &&
      mcore_num_zeros (INTVAL (operands[1]) | 0xffff0000) == 1 &&
      mcore_num_zeros (INTVAL (operands[1]) | 0xffff0000) == 1 &&
      operands[2] == operands[3] &&
      operands[2] == operands[3] &&
      mcore_is_dead (insn, operands[0])"
      mcore_is_dead (insn, operands[0])"
"*
"*
  if (! mcore_is_same_reg (operands[2], operands[3]))
  if (! mcore_is_same_reg (operands[2], operands[3]))
    output_asm_insn (\"mov\\t%2,%3\", operands);
    output_asm_insn (\"mov\\t%2,%3\", operands);
  return mcore_output_bclri (operands[2], INTVAL (operands[1]) | 0xffff0000);")
  return mcore_output_bclri (operands[2], INTVAL (operands[1]) | 0xffff0000);")
; This peephole helps when using -mwide-bitfields to widen fields so they
; This peephole helps when using -mwide-bitfields to widen fields so they
; collapse.   This, however, has the effect that a narrower mode is not used
; collapse.   This, however, has the effect that a narrower mode is not used
; when desirable.
; when desirable.
;
;
; e.g., sequences like:
; e.g., sequences like:
;
;
;      ldw r8,(r6)
;      ldw r8,(r6)
;      movi r7,0x00ffffff
;      movi r7,0x00ffffff
;      and r8,r7                 r7 dead
;      and r8,r7                 r7 dead
;      stw r8,(r6)                r8 dead
;      stw r8,(r6)                r8 dead
;
;
; get peepholed to become:
; get peepholed to become:
;
;
;      movi r8,0
;      movi r8,0
;      stb r8,(r6)              r8 dead
;      stb r8,(r6)              r8 dead
;
;
; Do only easy addresses that have no offset.  This peephole is also applied
; Do only easy addresses that have no offset.  This peephole is also applied
; to halfwords.  We need to check that the load is non-volatile before we get
; to halfwords.  We need to check that the load is non-volatile before we get
; rid of it.
; rid of it.
(define_peephole
(define_peephole
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "")
        (match_operand:SI 1 "memory_operand" ""))
        (match_operand:SI 1 "memory_operand" ""))
   (set (match_operand:SI 2 "mcore_arith_reg_operand" "")
   (set (match_operand:SI 2 "mcore_arith_reg_operand" "")
        (match_operand:SI 3 "const_int_operand" ""))
        (match_operand:SI 3 "const_int_operand" ""))
   (set (match_dup 0) (and:SI (match_dup 0) (match_dup 2)))
   (set (match_dup 0) (and:SI (match_dup 0) (match_dup 2)))
   (set (match_operand:SI 4 "memory_operand" "") (match_dup 0))]
   (set (match_operand:SI 4 "memory_operand" "") (match_dup 0))]
  "mcore_is_dead (insn, operands[0]) &&
  "mcore_is_dead (insn, operands[0]) &&
   ! MEM_VOLATILE_P (operands[1]) &&
   ! MEM_VOLATILE_P (operands[1]) &&
   mcore_is_dead (insn, operands[2]) &&
   mcore_is_dead (insn, operands[2]) &&
   (mcore_byte_offset (INTVAL (operands[3])) > -1 ||
   (mcore_byte_offset (INTVAL (operands[3])) > -1 ||
    mcore_halfword_offset (INTVAL (operands[3])) > -1) &&
    mcore_halfword_offset (INTVAL (operands[3])) > -1) &&
   ! MEM_VOLATILE_P (operands[4]) &&
   ! MEM_VOLATILE_P (operands[4]) &&
   GET_CODE (XEXP (operands[4], 0)) == REG"
   GET_CODE (XEXP (operands[4], 0)) == REG"
"*
"*
{
{
   int ofs;
   int ofs;
   enum machine_mode mode;
   enum machine_mode mode;
   rtx base_reg = XEXP (operands[4], 0);
   rtx base_reg = XEXP (operands[4], 0);
   if ((ofs = mcore_byte_offset (INTVAL (operands[3]))) > -1)
   if ((ofs = mcore_byte_offset (INTVAL (operands[3]))) > -1)
      mode = QImode;
      mode = QImode;
   else if ((ofs = mcore_halfword_offset (INTVAL (operands[3]))) > -1)
   else if ((ofs = mcore_halfword_offset (INTVAL (operands[3]))) > -1)
      mode = HImode;
      mode = HImode;
   else
   else
      gcc_unreachable ();
      gcc_unreachable ();
   if (ofs > 0)
   if (ofs > 0)
      operands[4] = gen_rtx_MEM (mode,
      operands[4] = gen_rtx_MEM (mode,
                              gen_rtx_PLUS (SImode, base_reg, GEN_INT(ofs)));
                              gen_rtx_PLUS (SImode, base_reg, GEN_INT(ofs)));
   else
   else
      operands[4] = gen_rtx_MEM (mode, base_reg);
      operands[4] = gen_rtx_MEM (mode, base_reg);
   if (mode == QImode)
   if (mode == QImode)
      return \"movi     %0,0\\n\\tst.b  %0,%4\";
      return \"movi     %0,0\\n\\tst.b  %0,%4\";
   return \"movi        %0,0\\n\\tst.h  %0,%4\";
   return \"movi        %0,0\\n\\tst.h  %0,%4\";
}")
}")
; from sop11. get btsti's for (LT A 0) where A is a QI or HI value
; from sop11. get btsti's for (LT A 0) where A is a QI or HI value
(define_peephole
(define_peephole
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "r")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "r")
        (sign_extend:SI (match_operand:QI 1 "mcore_arith_reg_operand" "0")))
        (sign_extend:SI (match_operand:QI 1 "mcore_arith_reg_operand" "0")))
   (set (reg:CC 17)
   (set (reg:CC 17)
        (lt:CC (match_dup 0)
        (lt:CC (match_dup 0)
            (const_int 0)))]
            (const_int 0)))]
  "mcore_is_dead (insn, operands[0])"
  "mcore_is_dead (insn, operands[0])"
  "btsti        %0,7")
  "btsti        %0,7")
(define_peephole
(define_peephole
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "r")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "r")
        (sign_extend:SI (match_operand:HI 1 "mcore_arith_reg_operand" "0")))
        (sign_extend:SI (match_operand:HI 1 "mcore_arith_reg_operand" "0")))
   (set (reg:CC 17)
   (set (reg:CC 17)
        (lt:CC (match_dup 0)
        (lt:CC (match_dup 0)
            (const_int 0)))]
            (const_int 0)))]
  "mcore_is_dead (insn, operands[0])"
  "mcore_is_dead (insn, operands[0])"
  "btsti        %0,15")
  "btsti        %0,15")
; Pick up a tst.  This combination happens because the immediate is not
; Pick up a tst.  This combination happens because the immediate is not
; allowed to fold into one of the operands of the tst.  Does not happen
; allowed to fold into one of the operands of the tst.  Does not happen
; when relaxing immediates.  BRC
; when relaxing immediates.  BRC
(define_peephole
(define_peephole
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "")
        (match_operand:SI 1 "mcore_arith_reg_operand" ""))
        (match_operand:SI 1 "mcore_arith_reg_operand" ""))
   (set (match_dup 0)
   (set (match_dup 0)
        (and:SI (match_dup 0)
        (and:SI (match_dup 0)
                (match_operand:SI 2 "mcore_literal_K_operand" "")))
                (match_operand:SI 2 "mcore_literal_K_operand" "")))
   (set (reg:CC 17) (ne:CC (match_dup 0) (const_int 0)))]
   (set (reg:CC 17) (ne:CC (match_dup 0) (const_int 0)))]
  "mcore_is_dead (insn, operands[0])"
  "mcore_is_dead (insn, operands[0])"
  "movi %0,%2\;tst      %1,%0")
  "movi %0,%2\;tst      %1,%0")
(define_peephole
(define_peephole
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "")
  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "")
        (if_then_else:SI (ne (zero_extract:SI
        (if_then_else:SI (ne (zero_extract:SI
                                (match_operand:SI 1 "mcore_arith_reg_operand" "")
                                (match_operand:SI 1 "mcore_arith_reg_operand" "")
                                (const_int 1)
                                (const_int 1)
                                (match_operand:SI 2 "mcore_literal_K_operand" ""))
                                (match_operand:SI 2 "mcore_literal_K_operand" ""))
                             (const_int 0))
                             (const_int 0))
           (match_operand:SI 3 "mcore_arith_imm_operand" "")
           (match_operand:SI 3 "mcore_arith_imm_operand" "")
           (match_operand:SI 4 "mcore_arith_imm_operand" "")))
           (match_operand:SI 4 "mcore_arith_imm_operand" "")))
    (set (reg:CC 17) (ne:CC (match_dup 0) (const_int 0)))]
    (set (reg:CC 17) (ne:CC (match_dup 0) (const_int 0)))]
  ""
  ""
"*
"*
{
{
  unsigned int op0 = REGNO (operands[0]);
  unsigned int op0 = REGNO (operands[0]);
  if (GET_CODE (operands[3]) == REG)
  if (GET_CODE (operands[3]) == REG)
    {
    {
     if (REGNO (operands[3]) == op0 && GET_CODE (operands[4]) == CONST_INT
     if (REGNO (operands[3]) == op0 && GET_CODE (operands[4]) == CONST_INT
         && INTVAL (operands[4]) == 0)
         && INTVAL (operands[4]) == 0)
        return \"btsti  %1,%2\\n\\tclrf %0\";
        return \"btsti  %1,%2\\n\\tclrf %0\";
     else if (GET_CODE (operands[4]) == REG)
     else if (GET_CODE (operands[4]) == REG)
       {
       {
        if (REGNO (operands[4]) == op0)
        if (REGNO (operands[4]) == op0)
           return \"btsti       %1,%2\\n\\tmovf %0,%3\";
           return \"btsti       %1,%2\\n\\tmovf %0,%3\";
        else if (REGNO (operands[3]) == op0)
        else if (REGNO (operands[3]) == op0)
           return \"btsti       %1,%2\\n\\tmovt %0,%4\";
           return \"btsti       %1,%2\\n\\tmovt %0,%4\";
       }
       }
     gcc_unreachable ();
     gcc_unreachable ();
    }
    }
  else if (GET_CODE (operands[3]) == CONST_INT
  else if (GET_CODE (operands[3]) == CONST_INT
           && INTVAL (operands[3]) == 0
           && INTVAL (operands[3]) == 0
           && GET_CODE (operands[4]) == REG)
           && GET_CODE (operands[4]) == REG)
     return \"btsti     %1,%2\\n\\tclrt %0\";
     return \"btsti     %1,%2\\n\\tclrt %0\";
  gcc_unreachable ();
  gcc_unreachable ();
}")
}")
; experimental - do the constant folding ourselves.  note that this isn't
; experimental - do the constant folding ourselves.  note that this isn't
;   re-applied like we'd really want.  i.e., four ands collapse into two
;   re-applied like we'd really want.  i.e., four ands collapse into two
;   instead of one.  this is because peepholes are applied as a sliding
;   instead of one.  this is because peepholes are applied as a sliding
;   window.  the peephole does not generate new rtl's, but instead slides
;   window.  the peephole does not generate new rtl's, but instead slides
;   across the rtl's generating machine instructions.  it would be nice
;   across the rtl's generating machine instructions.  it would be nice
;   if the peephole optimizer is changed to re-apply patterns and to gen
;   if the peephole optimizer is changed to re-apply patterns and to gen
;   new rtl's.  this is more flexible.  the pattern below helps when we're
;   new rtl's.  this is more flexible.  the pattern below helps when we're
;   not using relaxed immediates.   BRC
;   not using relaxed immediates.   BRC
;(define_peephole
;(define_peephole
;  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "")
;  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "")
;        (match_operand:SI 1 "const_int_operand" ""))
;        (match_operand:SI 1 "const_int_operand" ""))
;   (set (match_operand:SI 2 "mcore_arith_reg_operand" "")
;   (set (match_operand:SI 2 "mcore_arith_reg_operand" "")
;          (and:SI (match_dup 2) (match_dup 0)))
;          (and:SI (match_dup 2) (match_dup 0)))
;   (set (match_dup 0)
;   (set (match_dup 0)
;        (match_operand:SI 3 "const_int_operand" ""))
;        (match_operand:SI 3 "const_int_operand" ""))
;   (set (match_dup 2)
;   (set (match_dup 2)
;           (and:SI (match_dup 2) (match_dup 0)))]
;           (and:SI (match_dup 2) (match_dup 0)))]
;  "!TARGET_RELAX_IMM && mcore_is_dead (insn, operands[0]) &&
;  "!TARGET_RELAX_IMM && mcore_is_dead (insn, operands[0]) &&
;       mcore_const_ok_for_inline (INTVAL (operands[1]) & INTVAL (operands[3]))"
;       mcore_const_ok_for_inline (INTVAL (operands[1]) & INTVAL (operands[3]))"
;  "*
;  "*
;{
;{
;  rtx out_operands[2];
;  rtx out_operands[2];
;  out_operands[0] = operands[0];
;  out_operands[0] = operands[0];
;  out_operands[1] = GEN_INT (INTVAL (operands[1]) & INTVAL (operands[3]));
;  out_operands[1] = GEN_INT (INTVAL (operands[1]) & INTVAL (operands[3]));
;
;
;  output_inline_const (SImode, out_operands);
;  output_inline_const (SImode, out_operands);
;
;
;  output_asm_insn (\"and       %2,%0\", operands);
;  output_asm_insn (\"and       %2,%0\", operands);
;
;
;  return \"\";
;  return \"\";
;}")
;}")
; BRC: for inlining get rid of extra test - experimental
; BRC: for inlining get rid of extra test - experimental
;(define_peephole
;(define_peephole
;  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "r")
;  [(set (match_operand:SI 0 "mcore_arith_reg_operand" "r")
;          (ne:SI (reg:CC 17) (const_int 0)))
;          (ne:SI (reg:CC 17) (const_int 0)))
;   (set (reg:CC 17) (ne:CC (match_dup 0) (const_int 0)))
;   (set (reg:CC 17) (ne:CC (match_dup 0) (const_int 0)))
;   (set (pc)
;   (set (pc)
;       (if_then_else (eq (reg:CC 17) (const_int 0))
;       (if_then_else (eq (reg:CC 17) (const_int 0))
;         (label_ref (match_operand 1 "" ""))
;         (label_ref (match_operand 1 "" ""))
;         (pc)))]
;         (pc)))]
;   ""
;   ""
;   "*
;   "*
;{
;{
;  if (get_attr_length (insn) == 10)
;  if (get_attr_length (insn) == 10)
;    {
;    {
;      output_asm_insn (\"bt    2f\\n\\tjmpi    [1f]\", operands);
;      output_asm_insn (\"bt    2f\\n\\tjmpi    [1f]\", operands);
;      output_asm_insn (\".align        2\\n1:\", operands);
;      output_asm_insn (\".align        2\\n1:\", operands);
;      output_asm_insn (\".long %1\\n2:\", operands);
;      output_asm_insn (\".long %1\\n2:\", operands);
;      return \"\";
;      return \"\";
;    }
;    }
;  return \"bf  %l1\";
;  return \"bf  %l1\";
;}")
;}")


;;; Special patterns for dealing with the constant pool.
;;; Special patterns for dealing with the constant pool.
;;; 4 byte integer in line.
;;; 4 byte integer in line.
(define_insn "consttable_4"
(define_insn "consttable_4"
 [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")] 0)]
 [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")] 0)]
 ""
 ""
 "*
 "*
{
{
  assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
  assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
  return \"\";
  return \"\";
}"
}"
 [(set_attr "length" "4")])
 [(set_attr "length" "4")])
;;; align to a four byte boundary.
;;; align to a four byte boundary.
(define_insn "align_4"
(define_insn "align_4"
 [(unspec_volatile [(const_int 0)] 1)]
 [(unspec_volatile [(const_int 0)] 1)]
 ""
 ""
 ".align 2")
 ".align 2")
;;; Handle extra constant pool entries created during final pass.
;;; Handle extra constant pool entries created during final pass.
(define_insn "consttable_end"
(define_insn "consttable_end"
  [(unspec_volatile [(const_int 0)] 2)]
  [(unspec_volatile [(const_int 0)] 2)]
  ""
  ""
  "* return mcore_output_jump_label_table ();")
  "* return mcore_output_jump_label_table ();")


;;
;;
;; Stack allocation -- in particular, for alloca().
;; Stack allocation -- in particular, for alloca().
;; this is *not* what we use for entry into functions.
;; this is *not* what we use for entry into functions.
;;
;;
;; This is how we allocate stack space.  If we are allocating a
;; This is how we allocate stack space.  If we are allocating a
;; constant amount of space and we know it is less than 4096
;; constant amount of space and we know it is less than 4096
;; bytes, we need do nothing.
;; bytes, we need do nothing.
;;
;;
;; If it is more than 4096 bytes, we need to probe the stack
;; If it is more than 4096 bytes, we need to probe the stack
;; periodically.
;; periodically.
;;
;;
;; operands[1], the distance is a POSITIVE number indicating that we
;; operands[1], the distance is a POSITIVE number indicating that we
;; are allocating stack space
;; are allocating stack space
;;
;;
(define_expand "allocate_stack"
(define_expand "allocate_stack"
  [(set (reg:SI 0)
  [(set (reg:SI 0)
        (plus:SI (reg:SI 0)
        (plus:SI (reg:SI 0)
                 (match_operand:SI 1 "general_operand" "")))
                 (match_operand:SI 1 "general_operand" "")))
   (set (match_operand:SI 0 "register_operand" "=r")
   (set (match_operand:SI 0 "register_operand" "=r")
        (match_dup 2))]
        (match_dup 2))]
  ""
  ""
  "
  "
{
{
  /* If he wants no probing, just do it for him.  */
  /* If he wants no probing, just do it for him.  */
  if (mcore_stack_increment == 0)
  if (mcore_stack_increment == 0)
    {
    {
      emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,operands[1]));
      emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,operands[1]));
;;      emit_move_insn (operands[0], virtual_stack_dynamic_rtx);
;;      emit_move_insn (operands[0], virtual_stack_dynamic_rtx);
      DONE;
      DONE;
    }
    }
  /* For small constant growth, we unroll the code.  */
  /* For small constant growth, we unroll the code.  */
  if (GET_CODE (operands[1]) == CONST_INT
  if (GET_CODE (operands[1]) == CONST_INT
      && INTVAL (operands[1]) < 8 * STACK_UNITS_MAXSTEP)
      && INTVAL (operands[1]) < 8 * STACK_UNITS_MAXSTEP)
    {
    {
      int left = INTVAL(operands[1]);
      int left = INTVAL(operands[1]);
      /* If it's a long way, get close enough for a last shot.  */
      /* If it's a long way, get close enough for a last shot.  */
      if (left >= STACK_UNITS_MAXSTEP)
      if (left >= STACK_UNITS_MAXSTEP)
        {
        {
          rtx tmp = gen_reg_rtx (Pmode);
          rtx tmp = gen_reg_rtx (Pmode);
          emit_insn (gen_movsi (tmp, GEN_INT (STACK_UNITS_MAXSTEP)));
          emit_insn (gen_movsi (tmp, GEN_INT (STACK_UNITS_MAXSTEP)));
          do
          do
            {
            {
              rtx memref = gen_rtx_MEM (SImode, stack_pointer_rtx);
              rtx memref = gen_rtx_MEM (SImode, stack_pointer_rtx);
              MEM_VOLATILE_P (memref) = 1;
              MEM_VOLATILE_P (memref) = 1;
              emit_insn (gen_subsi3 (stack_pointer_rtx, stack_pointer_rtx, tmp));
              emit_insn (gen_subsi3 (stack_pointer_rtx, stack_pointer_rtx, tmp));
              emit_insn (gen_movsi (memref, stack_pointer_rtx));
              emit_insn (gen_movsi (memref, stack_pointer_rtx));
              left -= STACK_UNITS_MAXSTEP;
              left -= STACK_UNITS_MAXSTEP;
            }
            }
          while (left > STACK_UNITS_MAXSTEP);
          while (left > STACK_UNITS_MAXSTEP);
        }
        }
      /* Perform the final adjustment.  */
      /* Perform the final adjustment.  */
      emit_insn (gen_addsi3 (stack_pointer_rtx,stack_pointer_rtx,GEN_INT(-left)));
      emit_insn (gen_addsi3 (stack_pointer_rtx,stack_pointer_rtx,GEN_INT(-left)));
;;      emit_move_insn (operands[0], virtual_stack_dynamic_rtx);
;;      emit_move_insn (operands[0], virtual_stack_dynamic_rtx);
      DONE;
      DONE;
    }
    }
  else
  else
    {
    {
      rtx out_label = 0;
      rtx out_label = 0;
      rtx loop_label = gen_label_rtx ();
      rtx loop_label = gen_label_rtx ();
      rtx step = gen_reg_rtx (Pmode);
      rtx step = gen_reg_rtx (Pmode);
      rtx tmp = gen_reg_rtx (Pmode);
      rtx tmp = gen_reg_rtx (Pmode);
      rtx memref;
      rtx memref;
#if 1
#if 1
      emit_insn (gen_movsi (tmp, operands[1]));
      emit_insn (gen_movsi (tmp, operands[1]));
      emit_insn (gen_movsi (step, GEN_INT(STACK_UNITS_MAXSTEP)));
      emit_insn (gen_movsi (step, GEN_INT(STACK_UNITS_MAXSTEP)));
      if (GET_CODE (operands[1]) != CONST_INT)
      if (GET_CODE (operands[1]) != CONST_INT)
        {
        {
          out_label = gen_label_rtx ();
          out_label = gen_label_rtx ();
          emit_insn (gen_cmpsi (step, tmp));            /* quick out */
          emit_insn (gen_cmpsi (step, tmp));            /* quick out */
          emit_jump_insn (gen_bgeu (out_label));
          emit_jump_insn (gen_bgeu (out_label));
        }
        }
      /* Run a loop that steps it incrementally.  */
      /* Run a loop that steps it incrementally.  */
      emit_label (loop_label);
      emit_label (loop_label);
      /* Extend a step, probe, and adjust remaining count.  */
      /* Extend a step, probe, and adjust remaining count.  */
      emit_insn(gen_subsi3(stack_pointer_rtx, stack_pointer_rtx, step));
      emit_insn(gen_subsi3(stack_pointer_rtx, stack_pointer_rtx, step));
      memref = gen_rtx_MEM (SImode, stack_pointer_rtx);
      memref = gen_rtx_MEM (SImode, stack_pointer_rtx);
      MEM_VOLATILE_P (memref) = 1;
      MEM_VOLATILE_P (memref) = 1;
      emit_insn(gen_movsi(memref, stack_pointer_rtx));
      emit_insn(gen_movsi(memref, stack_pointer_rtx));
      emit_insn(gen_subsi3(tmp, tmp, step));
      emit_insn(gen_subsi3(tmp, tmp, step));
      /* Loop condition -- going back up.  */
      /* Loop condition -- going back up.  */
      emit_insn (gen_cmpsi (step, tmp));
      emit_insn (gen_cmpsi (step, tmp));
      emit_jump_insn (gen_bltu (loop_label));
      emit_jump_insn (gen_bltu (loop_label));
      if (out_label)
      if (out_label)
        emit_label (out_label);
        emit_label (out_label);
      /* Bump the residual.  */
      /* Bump the residual.  */
      emit_insn (gen_subsi3 (stack_pointer_rtx, stack_pointer_rtx, tmp));
      emit_insn (gen_subsi3 (stack_pointer_rtx, stack_pointer_rtx, tmp));
;;      emit_move_insn (operands[0], virtual_stack_dynamic_rtx);
;;      emit_move_insn (operands[0], virtual_stack_dynamic_rtx);
      DONE;
      DONE;
#else
#else
      /* simple one-shot -- ensure register and do a subtract.
      /* simple one-shot -- ensure register and do a subtract.
       * This does NOT comply with the ABI.  */
       * This does NOT comply with the ABI.  */
      emit_insn (gen_movsi (tmp, operands[1]));
      emit_insn (gen_movsi (tmp, operands[1]));
      emit_insn (gen_subsi3 (stack_pointer_rtx, stack_pointer_rtx, tmp));
      emit_insn (gen_subsi3 (stack_pointer_rtx, stack_pointer_rtx, tmp));
;;      emit_move_insn (operands[0], virtual_stack_dynamic_rtx);
;;      emit_move_insn (operands[0], virtual_stack_dynamic_rtx);
      DONE;
      DONE;
#endif
#endif
    }
    }
}")
}")
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.