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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gcc-4.2.2/] [gcc/] [config/] [m68hc11/] [m68hc11.md] - Diff between revs 38 and 154

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

Rev 38 Rev 154
;;- Machine description file for Motorola 68HC11 and 68HC12.
;;- Machine description file for Motorola 68HC11 and 68HC12.
;;- Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007
;;- Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007
;;- Free Software Foundation, Inc.
;;- Free Software Foundation, Inc.
;;- Contributed by Stephane Carrez (stcarrez@nerim.fr)
;;- Contributed by Stephane Carrez (stcarrez@nerim.fr)
;; 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
;; .
;; .
;; Note:
;; Note:
;;   A first 68HC11 port was made by Otto Lind (otto@coactive.com)
;;   A first 68HC11 port was made by Otto Lind (otto@coactive.com)
;;   on gcc 2.6.3.  I have used it as a starting point for this port.
;;   on gcc 2.6.3.  I have used it as a starting point for this port.
;;   However, this new port is a complete re-write.  Its internal
;;   However, this new port is a complete re-write.  Its internal
;;   design is completely different.  The generated code is not
;;   design is completely different.  The generated code is not
;;   compatible with the gcc 2.6.3 port.
;;   compatible with the gcc 2.6.3 port.
;;
;;
;;   The gcc 2.6.3 port is available at:
;;   The gcc 2.6.3 port is available at:
;;
;;
;;   ftp.unina.it/pub/electronics/motorola/68hc11/gcc/gcc-6811-fsf.tar.gz
;;   ftp.unina.it/pub/electronics/motorola/68hc11/gcc/gcc-6811-fsf.tar.gz
;;
;;
;;- Instruction patterns.  When multiple patterns apply,
;;- Instruction patterns.  When multiple patterns apply,
;;- the first one in the file is chosen.
;;- the first one in the file is chosen.
;;-
;;-
;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
;;-
;;-
;;- cpp macro #define NOTICE_UPDATE_CC in file tm.h handles condition code
;;- cpp macro #define NOTICE_UPDATE_CC in file tm.h handles condition code
;;- updates for most instructions.
;;- updates for most instructions.
;;
;;
;; The following constraints are used:
;; The following constraints are used:
;;
;;
;; Single pair registers:
;; Single pair registers:
;; a    register 'a'                     8-bit
;; a    register 'a'                     8-bit
;; b    register 'b'                     8-bit
;; b    register 'b'                     8-bit
;; d    register 'd'                    16-bit
;; d    register 'd'                    16-bit
;; t    pseudo soft register 'TMP'      16-bit
;; t    pseudo soft register 'TMP'      16-bit
;; v    register 'd' for 68hc11,        16-bit
;; v    register 'd' for 68hc11,        16-bit
;;      NO_REG for 68hc12
;;      NO_REG for 68hc12
;;      (used for scratch register)
;;      (used for scratch register)
;; w    register 'sp'                   16-bit
;; w    register 'sp'                   16-bit
;; x    register 'x'                    16-bit
;; x    register 'x'                    16-bit
;; y    register 'y'                    16-bit
;; y    register 'y'                    16-bit
;; z    register 'z'                    16-bit  (fake r for 68HC11 and 68HC12)
;; z    register 'z'                    16-bit  (fake r for 68HC11 and 68HC12)
;; D    register 'd+x'                  32-bit
;; D    register 'd+x'                  32-bit
;;
;;
;; Group of registers:
;; Group of registers:
;; q    register 'a' or 'b' or 'd'       8-bit
;; q    register 'a' or 'b' or 'd'       8-bit
;; u    pseudo soft register            16-bit
;; u    pseudo soft register            16-bit
;; A    register 'x', 'y', 'z'          16-bit
;; A    register 'x', 'y', 'z'          16-bit
;; B    register 'x', 'y'               16-bit
;; B    register 'x', 'y'               16-bit
;; h    register 'd', 'x', 'y', 'z'     16-bit
;; h    register 'd', 'x', 'y', 'z'     16-bit
;;
;;
;; Other constraints:
;; Other constraints:
;;
;;
;; Q    an operand which is in memory but whose address is constant
;; Q    an operand which is in memory but whose address is constant
;;      (i.e., a (MEM (SYMBOL_REF x))).  This constraint is used by
;;      (i.e., a (MEM (SYMBOL_REF x))).  This constraint is used by
;;      bset/bclr instructions together with linker relaxation.  The
;;      bset/bclr instructions together with linker relaxation.  The
;;      operand can be translated to a page0 addressing mode if the
;;      operand can be translated to a page0 addressing mode if the
;;      symbol address is in page0 (0..255).
;;      symbol address is in page0 (0..255).
;;
;;
;; R    an operand which is in memory and whose address is expressed
;; R    an operand which is in memory and whose address is expressed
;;      with 68HC11/68HC12 indexed addressing mode.  In general this
;;      with 68HC11/68HC12 indexed addressing mode.  In general this
;;      is any valid (MEM) except a (MEM (SYMBOL_REF x)).
;;      is any valid (MEM) except a (MEM (SYMBOL_REF x)).
;;
;;
;; U    an operand which is in memory and if it uses the 68HC12 indexed
;; U    an operand which is in memory and if it uses the 68HC12 indexed
;;      addressing mode, the offset is in the range -16..+15.  This is
;;      addressing mode, the offset is in the range -16..+15.  This is
;;      used by 68HC12 movb/movw instructions since they do not accept
;;      used by 68HC12 movb/movw instructions since they do not accept
;;      the full 16-bit offset range (as other insn do).
;;      the full 16-bit offset range (as other insn do).
;;
;;
;;
;;
;; Immediate integer operand constraints:
;; Immediate integer operand constraints:
;;   `L' is for range -65536 to 65536
;;   `L' is for range -65536 to 65536
;;   `M' is for values whose 16-bit low part is 0
;;   `M' is for values whose 16-bit low part is 0
;;   'N' is for +1 or -1.
;;   'N' is for +1 or -1.
;;   'O' is for 16 (for rotate using swap).
;;   'O' is for 16 (for rotate using swap).
;;   'P' is for range -8 to 2 (used by addhi_sp)
;;   'P' is for range -8 to 2 (used by addhi_sp)
;;
;;
;; In many cases, it's not possible to use the 'g' or 'r' constraints.
;; In many cases, it's not possible to use the 'g' or 'r' constraints.
;;
;;
;; Operands modifiers:
;; Operands modifiers:
;;
;;
;;     %b       Get the low part of the operand (to obtain a QImode)
;;     %b       Get the low part of the operand (to obtain a QImode)
;;              This modifier must always be used for QImode operations
;;              This modifier must always be used for QImode operations
;;              because a correction must be applied when the operand
;;              because a correction must be applied when the operand
;;              is a soft register (ex: *ZD1). Otherwise, we generate
;;              is a soft register (ex: *ZD1). Otherwise, we generate
;;              *ZD1 and this is the high part of the register. For other
;;              *ZD1 and this is the high part of the register. For other
;;              kinds of operands, if the operand is already QImode, no
;;              kinds of operands, if the operand is already QImode, no
;;              additional correction is made.
;;              additional correction is made.
;;     %h       Get the high part of the operand (to obtain a QImode)
;;     %h       Get the high part of the operand (to obtain a QImode)
;;     %t       Represents the temporary/scratch register *_.tmp
;;     %t       Represents the temporary/scratch register *_.tmp
;;              The scratch register is used in some cases when GCC puts
;;              The scratch register is used in some cases when GCC puts
;;              some values in bad registers.
;;              some values in bad registers.
;;
;;
;; 32/64-bit Patterns:
;; 32/64-bit Patterns:
;;     The 68HC11 does not support 32/64-bit operations.  Most of the
;;     The 68HC11 does not support 32/64-bit operations.  Most of the
;;     32/64-bit patterns are defined to split the instruction in
;;     32/64-bit patterns are defined to split the instruction in
;;     16-bits patterns.  Providing split patterns generates better code
;;     16-bits patterns.  Providing split patterns generates better code
;;     than letting GCC implement the 32/64-bit operation itself.
;;     than letting GCC implement the 32/64-bit operation itself.
;;
;;
;;
;;
;; Notes:
;; Notes:
;;
;;
;; o For iorqi3, andqi3, xorqi3 patterns, we must accept the 'A' constraint
;; o For iorqi3, andqi3, xorqi3 patterns, we must accept the 'A' constraint
;;   otherwise some insn are not satisfied.
;;   otherwise some insn are not satisfied.
;;
;;
;; o Split patterns that create a swap_areg pattern (xgdx or xgdy) must
;; o Split patterns that create a swap_areg pattern (xgdx or xgdy) must
;;   be valid only when z_replacement_completed == 2 because once these
;;   be valid only when z_replacement_completed == 2 because once these
;;   swap instructions are generated, a flow/cse pass fails to handle
;;   swap instructions are generated, a flow/cse pass fails to handle
;;   them correctly (it would treat the X, Y or D register as dead sometimes).
;;   them correctly (it would treat the X, Y or D register as dead sometimes).
;;
;;
;; o Some split pattern generate instructions that operate on 'a' or 'b'
;; o Some split pattern generate instructions that operate on 'a' or 'b'
;;   register directly (high part and low part of D respectively).
;;   register directly (high part and low part of D respectively).
;;   Such split pattern must also be valid when z_replacement_completed == 2
;;   Such split pattern must also be valid when z_replacement_completed == 2
;;   because flow/cse is not aware that D is composed of {a, b}.
;;   because flow/cse is not aware that D is composed of {a, b}.
;;
;;
;; o Split patterns that generate a (mem:QI (symbol_reg _.dx)) to access
;; o Split patterns that generate a (mem:QI (symbol_reg _.dx)) to access
;;   the high part of a soft register must be expanded after z_replacement
;;   the high part of a soft register must be expanded after z_replacement
;;   pass.
;;   pass.
;;
;;
;;---------------------------------------------------------------------------
;;---------------------------------------------------------------------------
;; Constants
;; Constants
(define_constants [
(define_constants [
   ;; Register numbers
   ;; Register numbers
   (X_REGNUM        0)          ; Index X register
   (X_REGNUM        0)          ; Index X register
   (D_REGNUM        1)          ; Data register
   (D_REGNUM        1)          ; Data register
   (Y_REGNUM        2)          ; Index Y register
   (Y_REGNUM        2)          ; Index Y register
   (SP_REGNUM       3)          ; Stack pointer
   (SP_REGNUM       3)          ; Stack pointer
   (PC_REGNUM       4)          ; Program counter
   (PC_REGNUM       4)          ; Program counter
   (A_REGNUM        5)          ; A (high part of D)
   (A_REGNUM        5)          ; A (high part of D)
   (B_REGNUM        6)          ; B (low part of D)
   (B_REGNUM        6)          ; B (low part of D)
   (CC_REGNUM       7)          ; Condition code register
   (CC_REGNUM       7)          ; Condition code register
   (SOFT_TMP_REGNUM 10)         ; TMP soft register
   (SOFT_TMP_REGNUM 10)         ; TMP soft register
   (SOFT_Z_REGNUM   11)         ; Z soft register
   (SOFT_Z_REGNUM   11)         ; Z soft register
   (SOFT_XY_REGNUM  12)         ; XY soft register
   (SOFT_XY_REGNUM  12)         ; XY soft register
])
])
(include "predicates.md")
(include "predicates.md")
;;--------------------------------------------------------------------
;;--------------------------------------------------------------------
;;-  Test
;;-  Test
;;--------------------------------------------------------------------
;;--------------------------------------------------------------------
;;
;;
;; The test and compare insn must not accept a memory operand with
;; The test and compare insn must not accept a memory operand with
;; an auto-inc mode.  If we do this, the reload can emit move insns
;; an auto-inc mode.  If we do this, the reload can emit move insns
;; after the test or compare.  Such move will set the flags and therefore
;; after the test or compare.  Such move will set the flags and therefore
;; break the comparison.  This can happen if the auto-inc register
;; break the comparison.  This can happen if the auto-inc register
;; does not happen to be a hard register (i.e., reloading occurs).
;; does not happen to be a hard register (i.e., reloading occurs).
;; An offsetable memory operand should be ok.  The 'tst_operand' and
;; An offsetable memory operand should be ok.  The 'tst_operand' and
;; 'cmp_operand' predicates take care of this rule.
;; 'cmp_operand' predicates take care of this rule.
;;
;;
(define_expand "tstsi"
(define_expand "tstsi"
  [(set (cc0)
  [(set (cc0)
        (match_operand:SI 0 "tst_operand" ""))]
        (match_operand:SI 0 "tst_operand" ""))]
  ""
  ""
  "
  "
{
{
  m68hc11_compare_op0 = operands[0];
  m68hc11_compare_op0 = operands[0];
  m68hc11_compare_op1 = const0_rtx;
  m68hc11_compare_op1 = const0_rtx;
  DONE;
  DONE;
}")
}")
(define_expand "tsthi"
(define_expand "tsthi"
  [(set (cc0)
  [(set (cc0)
        (match_operand:HI 0 "tst_operand" ""))]
        (match_operand:HI 0 "tst_operand" ""))]
  ""
  ""
  "
  "
{
{
  m68hc11_compare_op0 = operands[0];
  m68hc11_compare_op0 = operands[0];
  m68hc11_compare_op1 = const0_rtx;
  m68hc11_compare_op1 = const0_rtx;
  DONE;
  DONE;
}")
}")
(define_insn "tsthi_1"
(define_insn "tsthi_1"
  [(set (cc0)
  [(set (cc0)
        (match_operand:HI 0 "tst_operand" "dx,*y"))]
        (match_operand:HI 0 "tst_operand" "dx,*y"))]
  ""
  ""
  "*
  "*
{
{
   if (D_REG_P (operands[0]) && !TARGET_M6812)
   if (D_REG_P (operands[0]) && !TARGET_M6812)
     return \"std\\t%t0\";
     return \"std\\t%t0\";
   else
   else
     return \"cp%0\\t#0\";
     return \"cp%0\\t#0\";
}")
}")
(define_expand "tstqi"
(define_expand "tstqi"
  [(set (cc0)
  [(set (cc0)
        (match_operand:QI 0 "tst_operand" ""))]
        (match_operand:QI 0 "tst_operand" ""))]
  ""
  ""
  "
  "
{
{
  m68hc11_compare_op0 = operands[0];
  m68hc11_compare_op0 = operands[0];
  m68hc11_compare_op1 = const0_rtx;
  m68hc11_compare_op1 = const0_rtx;
  DONE;
  DONE;
}")
}")
;;
;;
;; Split pattern for (tst:QI) on an address register.
;; Split pattern for (tst:QI) on an address register.
;;
;;
(define_split
(define_split
  [(set (cc0)
  [(set (cc0)
        (match_operand:QI 0 "hard_addr_reg_operand" ""))]
        (match_operand:QI 0 "hard_addr_reg_operand" ""))]
  "z_replacement_completed == 2 && GET_MODE (operands[0]) == QImode"
  "z_replacement_completed == 2 && GET_MODE (operands[0]) == QImode"
  [(parallel [(set (reg:HI D_REGNUM) (match_dup 1))
  [(parallel [(set (reg:HI D_REGNUM) (match_dup 1))
              (set (match_dup 1) (reg:HI D_REGNUM))])
              (set (match_dup 1) (reg:HI D_REGNUM))])
   (set (cc0) (reg:QI D_REGNUM))
   (set (cc0) (reg:QI D_REGNUM))
   (parallel [(set (reg:HI D_REGNUM) (match_dup 1))
   (parallel [(set (reg:HI D_REGNUM) (match_dup 1))
              (set (match_dup 1) (reg:HI D_REGNUM))])]
              (set (match_dup 1) (reg:HI D_REGNUM))])]
  "operands[1] = gen_rtx_REG (HImode, REGNO (operands[0]));")
  "operands[1] = gen_rtx_REG (HImode, REGNO (operands[0]));")
(define_insn "tstqi_1"
(define_insn "tstqi_1"
  [(set (cc0)
  [(set (cc0)
        (match_operand:QI 0 "tst_operand" "m,d,*A,!u"))]
        (match_operand:QI 0 "tst_operand" "m,d,*A,!u"))]
  ""
  ""
  "*
  "*
{
{
  if (A_REG_P (operands[0]))
  if (A_REG_P (operands[0]))
    return \"#\";
    return \"#\";
  else if (D_REG_P (operands[0]))
  else if (D_REG_P (operands[0]))
    return \"tstb\";
    return \"tstb\";
  else if (dead_register_here (insn, d_reg))
  else if (dead_register_here (insn, d_reg))
    return \"ldab\\t%b0\";
    return \"ldab\\t%b0\";
  else
  else
    return \"tst\\t%b0\";
    return \"tst\\t%b0\";
}")
}")
;;
;;
;; tstqi_z_used, cmpqi_z_used and cmphi_z_used are patterns generated
;; tstqi_z_used, cmpqi_z_used and cmphi_z_used are patterns generated
;; during the Z register replacement.  They are used when an operand
;; during the Z register replacement.  They are used when an operand
;; uses the Z register as an index register (i.e., (MEM:QI (REG:HI Z))).
;; uses the Z register as an index register (i.e., (MEM:QI (REG:HI Z))).
;; In that case, we have to preserve the values of the replacement
;; In that case, we have to preserve the values of the replacement
;; register (as well as the CC0 since the insns are compare insns).
;; register (as well as the CC0 since the insns are compare insns).
;; To do this, the replacement register is pushed on the stack and
;; To do this, the replacement register is pushed on the stack and
;; restored after the real compare.  A pattern+split is defined to
;; restored after the real compare.  A pattern+split is defined to
;; avoid problems with the flow+cse register pass which are made
;; avoid problems with the flow+cse register pass which are made
;; after Z register replacement.
;; after Z register replacement.
;;
;;
(define_insn_and_split "tstqi_z_used"
(define_insn_and_split "tstqi_z_used"
  [(set (cc0)
  [(set (cc0)
        (match_operand:QI 0 "tst_operand" "m"))
        (match_operand:QI 0 "tst_operand" "m"))
   (use (match_operand:HI 1 "hard_reg_operand" "dxy"))
   (use (match_operand:HI 1 "hard_reg_operand" "dxy"))
   (use (reg:HI SOFT_Z_REGNUM))]
   (use (reg:HI SOFT_Z_REGNUM))]
  ""
  ""
  "#"
  "#"
  "z_replacement_completed == 2"
  "z_replacement_completed == 2"
  [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 1))
  [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 1))
   (set (match_dup 1) (match_dup 2))
   (set (match_dup 1) (match_dup 2))
   (set (cc0) (match_dup 0))
   (set (cc0) (match_dup 0))
   (set (match_dup 1) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))]
   (set (match_dup 1) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))]
  "operands[2] = gen_rtx_REG (HImode, SOFT_Z_REGNUM);")
  "operands[2] = gen_rtx_REG (HImode, SOFT_Z_REGNUM);")
;;--------------------------------------------------------------------
;;--------------------------------------------------------------------
;;- Compare
;;- Compare
;;--------------------------------------------------------------------
;;--------------------------------------------------------------------
(define_expand "cmpsi"
(define_expand "cmpsi"
  [(set (cc0)
  [(set (cc0)
        (compare (match_operand:SI 0 "tst_operand" "")
        (compare (match_operand:SI 0 "tst_operand" "")
                 (match_operand:SI 1 "cmp_operand" "")))]
                 (match_operand:SI 1 "cmp_operand" "")))]
  ""
  ""
  "
  "
{
{
  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
    operands[0] = force_reg (SImode, operands[0]);
    operands[0] = force_reg (SImode, operands[0]);
  m68hc11_compare_op0 = operands[0];
  m68hc11_compare_op0 = operands[0];
  m68hc11_compare_op1 = operands[1];
  m68hc11_compare_op1 = operands[1];
  DONE;
  DONE;
}")
}")
;;
;;
;; Comparison of a hard register with another one is provided because
;; Comparison of a hard register with another one is provided because
;; it helps GCC to avoid to spill a pseudo hard register.
;; it helps GCC to avoid to spill a pseudo hard register.
;; We use a temporary in page 0, this is equivalent to a pseudo hard reg.
;; We use a temporary in page 0, this is equivalent to a pseudo hard reg.
;; (except that we loose the information that the value is saved in it).
;; (except that we loose the information that the value is saved in it).
;;
;;
;; The split pattern transforms the comparison into a save of one hard
;; The split pattern transforms the comparison into a save of one hard
;; register and a comparison with the temporary.
;; register and a comparison with the temporary.
;;
;;
(define_split
(define_split
  [(set (cc0)
  [(set (cc0)
        (compare (match_operand:HI 0 "hard_reg_operand" "")
        (compare (match_operand:HI 0 "hard_reg_operand" "")
                 (match_operand:HI 1 "hard_reg_operand" "")))]
                 (match_operand:HI 1 "hard_reg_operand" "")))]
  "TARGET_M6811
  "TARGET_M6811
   && reload_completed && !(Z_REG_P (operands[0]) || Z_REG_P (operands[1]))"
   && reload_completed && !(Z_REG_P (operands[0]) || Z_REG_P (operands[1]))"
  [(set (match_dup 2) (match_dup 1))
  [(set (match_dup 2) (match_dup 1))
   (set (cc0)
   (set (cc0)
        (compare (match_dup 0) (match_dup 2)))]
        (compare (match_dup 0) (match_dup 2)))]
  "operands[2] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);")
  "operands[2] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);")
(define_split
(define_split
  [(set (cc0)
  [(set (cc0)
        (compare (match_operand:HI 0 "hard_reg_operand" "")
        (compare (match_operand:HI 0 "hard_reg_operand" "")
                 (match_operand:HI 1 "hard_reg_operand" "")))]
                 (match_operand:HI 1 "hard_reg_operand" "")))]
  "0 && TARGET_M6812
  "0 && TARGET_M6812
   && reload_completed && !(Z_REG_P (operands[0]) || Z_REG_P (operands[1]))"
   && reload_completed && !(Z_REG_P (operands[0]) || Z_REG_P (operands[1]))"
  [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 1))
  [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 1))
   (set (cc0)
   (set (cc0)
        (compare (match_dup 0) (mem:HI (post_inc:HI (reg:HI SP_REGNUM)))))]
        (compare (match_dup 0) (mem:HI (post_inc:HI (reg:HI SP_REGNUM)))))]
  "")
  "")
(define_expand "cmphi"
(define_expand "cmphi"
  [(set (cc0)
  [(set (cc0)
        (compare (match_operand:HI 0 "tst_operand" "")
        (compare (match_operand:HI 0 "tst_operand" "")
                 (match_operand:HI 1 "cmp_operand" "")))]
                 (match_operand:HI 1 "cmp_operand" "")))]
  ""
  ""
  "
  "
{
{
  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
    operands[0] = force_reg (HImode, operands[0]);
    operands[0] = force_reg (HImode, operands[0]);
  m68hc11_compare_op0 = operands[0];
  m68hc11_compare_op0 = operands[0];
  m68hc11_compare_op1 = operands[1];
  m68hc11_compare_op1 = operands[1];
  DONE;
  DONE;
}")
}")
(define_insn "cmphi_1_hc12"
(define_insn "cmphi_1_hc12"
  [(set (cc0)
  [(set (cc0)
        (compare (match_operand:HI 0 "tst_operand"
        (compare (match_operand:HI 0 "tst_operand"
                                "d,?xy,xyd,?xy,d,m,!u,dxy,dxy")
                                "d,?xy,xyd,?xy,d,m,!u,dxy,dxy")
                 (match_operand:HI 1 "general_operand"
                 (match_operand:HI 1 "general_operand"
                                "i,i,!u,m,m,dxy,dxy,?*d*A,!*w")))]
                                "i,i,!u,m,m,dxy,dxy,?*d*A,!*w")))]
  "TARGET_M6812"
  "TARGET_M6812"
  "*
  "*
{
{
  if (H_REG_P (operands[1]) && !H_REG_P (operands[0]))
  if (H_REG_P (operands[1]) && !H_REG_P (operands[0]))
    {
    {
      cc_status.flags |= CC_REVERSED;
      cc_status.flags |= CC_REVERSED;
      return \"cp%1\\t%0\";
      return \"cp%1\\t%0\";
    }
    }
  else if (SP_REG_P (operands[1]))
  else if (SP_REG_P (operands[1]))
    return \"sts\\t2,-sp\n\\tcp%0\\t2,sp+\";
    return \"sts\\t2,-sp\n\\tcp%0\\t2,sp+\";
  else if (H_REG_P (operands[1]))
  else if (H_REG_P (operands[1]))
    return \"psh%1\n\\tcp%0\\t2,sp+\";
    return \"psh%1\n\\tcp%0\\t2,sp+\";
  else
  else
    return \"cp%0\\t%1\";
    return \"cp%0\\t%1\";
}")
}")
(define_insn "cmphi_1_hc11"
(define_insn "cmphi_1_hc11"
  [(set (cc0)
  [(set (cc0)
        (compare (match_operand:HI 0 "tst_operand"
        (compare (match_operand:HI 0 "tst_operand"
                                "dx,y,xyd,?xy,d,m,m,dxy,dxy,?u*z,dxy,*z")
                                "dx,y,xyd,?xy,d,m,m,dxy,dxy,?u*z,dxy,*z")
                 (match_operand:HI 1 "cmp_operand"
                 (match_operand:HI 1 "cmp_operand"
                                "i,i,!u,m,m,?xy,d,?*d*A,?u,dxy,!*w,i")))]
                                "i,i,!u,m,m,?xy,d,?*d*A,?u,dxy,!*w,i")))]
  "TARGET_M6811"
  "TARGET_M6811"
  "*
  "*
{
{
  if (H_REG_P (operands[1]) && !H_REG_P (operands[0]))
  if (H_REG_P (operands[1]) && !H_REG_P (operands[0]))
    {
    {
      cc_status.flags |= CC_REVERSED;
      cc_status.flags |= CC_REVERSED;
      return \"cp%1\\t%0\";
      return \"cp%1\\t%0\";
    }
    }
  else if (H_REG_P (operands[1]))
  else if (H_REG_P (operands[1]))
    return \"#\";
    return \"#\";
  else
  else
    return \"cp%0\\t%1\";
    return \"cp%0\\t%1\";
}")
}")
(define_insn_and_split "cmphi_z_used"
(define_insn_and_split "cmphi_z_used"
  [(set (cc0)
  [(set (cc0)
        (compare (match_operand:HI 0 "tst_operand" "dxy,m")
        (compare (match_operand:HI 0 "tst_operand" "dxy,m")
                 (match_operand:HI 1 "cmp_operand" "mi,dxy")))
                 (match_operand:HI 1 "cmp_operand" "mi,dxy")))
   (use (match_operand:HI 2 "hard_reg_operand" "dxy,dxy"))
   (use (match_operand:HI 2 "hard_reg_operand" "dxy,dxy"))
   (use (reg:HI SOFT_Z_REGNUM))]
   (use (reg:HI SOFT_Z_REGNUM))]
  ""
  ""
  "#"
  "#"
  "z_replacement_completed == 2"
  "z_replacement_completed == 2"
  [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 2))
  [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 2))
   (set (match_dup 2) (match_dup 3))
   (set (match_dup 2) (match_dup 3))
   (set (cc0) (compare (match_dup 0) (match_dup 1)))
   (set (cc0) (compare (match_dup 0) (match_dup 1)))
   (set (match_dup 2) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))]
   (set (match_dup 2) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))]
  "operands[3] = gen_rtx_REG (HImode, SOFT_Z_REGNUM);")
  "operands[3] = gen_rtx_REG (HImode, SOFT_Z_REGNUM);")
;;
;;
;; 8-bit comparison with address register.
;; 8-bit comparison with address register.
;; There is no such comparison instruction, we have to temporarily switch
;; There is no such comparison instruction, we have to temporarily switch
;; the address register and the D register and do the comparison with D.
;; the address register and the D register and do the comparison with D.
;; The xgdx and xgdy instructions preserve the flags.
;; The xgdx and xgdy instructions preserve the flags.
;;
;;
(define_split
(define_split
  [(set (cc0)
  [(set (cc0)
        (compare (match_operand:QI 0 "hard_addr_reg_operand" "")
        (compare (match_operand:QI 0 "hard_addr_reg_operand" "")
                 (match_operand:QI 1 "cmp_operand" "")))]
                 (match_operand:QI 1 "cmp_operand" "")))]
  "z_replacement_completed == 2 && GET_MODE (operands[0]) == QImode"
  "z_replacement_completed == 2 && GET_MODE (operands[0]) == QImode"
  [(parallel [(set (reg:HI D_REGNUM) (match_dup 3))
  [(parallel [(set (reg:HI D_REGNUM) (match_dup 3))
              (set (match_dup 3) (reg:HI D_REGNUM))])
              (set (match_dup 3) (reg:HI D_REGNUM))])
   (set (cc0)
   (set (cc0)
        (compare (reg:QI D_REGNUM) (match_dup 1)))
        (compare (reg:QI D_REGNUM) (match_dup 1)))
   (parallel [(set (reg:HI D_REGNUM) (match_dup 3))
   (parallel [(set (reg:HI D_REGNUM) (match_dup 3))
              (set (match_dup 3) (reg:HI D_REGNUM))])]
              (set (match_dup 3) (reg:HI D_REGNUM))])]
  "operands[3] = gen_rtx_REG (HImode, REGNO (operands[0]));")
  "operands[3] = gen_rtx_REG (HImode, REGNO (operands[0]));")
(define_split
(define_split
  [(set (cc0)
  [(set (cc0)
        (compare (match_operand:QI 0 "hard_reg_operand" "")
        (compare (match_operand:QI 0 "hard_reg_operand" "")
                 (match_operand:QI 1 "hard_reg_operand" "")))]
                 (match_operand:QI 1 "hard_reg_operand" "")))]
  "reload_completed"
  "reload_completed"
  [(set (match_dup 3) (match_dup 4))
  [(set (match_dup 3) (match_dup 4))
   (set (cc0)
   (set (cc0)
        (compare (match_dup 0) (match_dup 2)))]
        (compare (match_dup 0) (match_dup 2)))]
  "operands[2] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
  "operands[2] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
   operands[3] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
   operands[3] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
   operands[4] = gen_rtx_REG (HImode, REGNO (operands[1]));")
   operands[4] = gen_rtx_REG (HImode, REGNO (operands[1]));")
(define_expand "cmpqi"
(define_expand "cmpqi"
  [(set (cc0)
  [(set (cc0)
        (compare (match_operand:QI 0 "tst_operand" "")
        (compare (match_operand:QI 0 "tst_operand" "")
                 (match_operand:QI 1 "cmp_operand" "")))]
                 (match_operand:QI 1 "cmp_operand" "")))]
  ""
  ""
  "
  "
{
{
  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
    operands[0] = force_reg (QImode, operands[0]);
    operands[0] = force_reg (QImode, operands[0]);
  m68hc11_compare_op0 = operands[0];
  m68hc11_compare_op0 = operands[0];
  m68hc11_compare_op1 = operands[1];
  m68hc11_compare_op1 = operands[1];
  DONE;
  DONE;
}")
}")
(define_insn "bitcmpqi"
(define_insn "bitcmpqi"
  [(set (cc0)
  [(set (cc0)
        (and:QI (match_operand:QI 0 "tst_operand" "d,d,d,m,!u")
        (and:QI (match_operand:QI 0 "tst_operand" "d,d,d,m,!u")
                (match_operand:QI 1 "cmp_operand" "im,*B,u,d,d")))]
                (match_operand:QI 1 "cmp_operand" "im,*B,u,d,d")))]
  ""
  ""
  "@
  "@
   bitb\\t%b1
   bitb\\t%b1
   #
   #
   bitb\\t%b1
   bitb\\t%b1
   bitb\\t%b0
   bitb\\t%b0
   bitb\\t%b0")
   bitb\\t%b0")
(define_split /* "bitcmpqi" */
(define_split /* "bitcmpqi" */
  [(set (cc0)
  [(set (cc0)
        (and:QI (match_operand:QI 0 "tst_operand" "")
        (and:QI (match_operand:QI 0 "tst_operand" "")
                (match_operand:QI 1 "hard_addr_reg_operand" "")))]
                (match_operand:QI 1 "hard_addr_reg_operand" "")))]
  "z_replacement_completed == 2"
  "z_replacement_completed == 2"
  [(set (match_dup 3) (match_dup 2))
  [(set (match_dup 3) (match_dup 2))
   (set (cc0) (and:QI (match_dup 0) (match_dup 4)))]
   (set (cc0) (and:QI (match_dup 0) (match_dup 4)))]
  "operands[2] = gen_rtx_REG (HImode, REGNO (operands[1]));
  "operands[2] = gen_rtx_REG (HImode, REGNO (operands[1]));
   operands[3] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
   operands[3] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
   operands[4] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);")
   operands[4] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);")
(define_insn_and_split "bitcmpqi_z_used"
(define_insn_and_split "bitcmpqi_z_used"
  [(set (cc0)
  [(set (cc0)
        (and:QI (match_operand:QI 0 "tst_operand" "d,m")
        (and:QI (match_operand:QI 0 "tst_operand" "d,m")
                (match_operand:QI 1 "cmp_operand" "m,d")))
                (match_operand:QI 1 "cmp_operand" "m,d")))
   (use (match_operand:HI 2 "hard_reg_operand" "xy,xy"))
   (use (match_operand:HI 2 "hard_reg_operand" "xy,xy"))
   (use (reg:HI SOFT_Z_REGNUM))]
   (use (reg:HI SOFT_Z_REGNUM))]
  ""
  ""
  "#"
  "#"
  "z_replacement_completed == 2"
  "z_replacement_completed == 2"
  [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 2))
  [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 2))
   (set (match_dup 2) (match_dup 3))
   (set (match_dup 2) (match_dup 3))
   (set (cc0) (and:QI (match_dup 0) (match_dup 1)))
   (set (cc0) (and:QI (match_dup 0) (match_dup 1)))
   (set (match_dup 2) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))]
   (set (match_dup 2) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))]
  "operands[3] = gen_rtx_REG (HImode, SOFT_Z_REGNUM);")
  "operands[3] = gen_rtx_REG (HImode, SOFT_Z_REGNUM);")
(define_insn "bitcmphi"
(define_insn "bitcmphi"
  [(set (cc0)
  [(set (cc0)
        (and:HI (match_operand:HI 0 "tst_operand" "d")
        (and:HI (match_operand:HI 0 "tst_operand" "d")
                (match_operand:HI 1 "const_int_operand" "i")))]
                (match_operand:HI 1 "const_int_operand" "i")))]
  "(INTVAL (operands[1]) & 0x0ff) == 0
  "(INTVAL (operands[1]) & 0x0ff) == 0
   || (INTVAL (operands[1]) & 0x0ff00) == 0"
   || (INTVAL (operands[1]) & 0x0ff00) == 0"
  "*
  "*
{
{
   if ((INTVAL (operands[1]) & 0x0ff) == 0)
   if ((INTVAL (operands[1]) & 0x0ff) == 0)
     return \"bita\\t%h1\";
     return \"bita\\t%h1\";
   else
   else
     return \"bitb\\t%1\";
     return \"bitb\\t%1\";
}")
}")
(define_insn "bitcmpqi_12"
(define_insn "bitcmpqi_12"
  [(set (cc0)
  [(set (cc0)
        (zero_extract (match_operand:HI 0 "tst_operand" "d")
        (zero_extract (match_operand:HI 0 "tst_operand" "d")
                      (match_operand:HI 1 "const_int_operand" "i")
                      (match_operand:HI 1 "const_int_operand" "i")
                      (match_operand:HI 2 "const_int_operand" "i")))]
                      (match_operand:HI 2 "const_int_operand" "i")))]
  "(unsigned) (INTVAL (operands[2]) + INTVAL (operands[1])) <= 8
  "(unsigned) (INTVAL (operands[2]) + INTVAL (operands[1])) <= 8
   || (((unsigned) (INTVAL (operands[2]) + INTVAL (operands[1])) <= 16)
   || (((unsigned) (INTVAL (operands[2]) + INTVAL (operands[1])) <= 16)
       && (unsigned) INTVAL (operands[2]) >= 8)"
       && (unsigned) INTVAL (operands[2]) >= 8)"
  "*
  "*
{
{
   rtx ops[1];
   rtx ops[1];
   int mask;
   int mask;
   int startpos = INTVAL (operands[2]);
   int startpos = INTVAL (operands[2]);
   int bitsize = INTVAL (operands[1]);
   int bitsize = INTVAL (operands[1]);
   if (startpos >= 8)
   if (startpos >= 8)
     {
     {
       startpos -= 8;
       startpos -= 8;
       mask = (1 << (startpos + bitsize)) - 1;
       mask = (1 << (startpos + bitsize)) - 1;
       mask &= ~((1 << startpos) - 1);
       mask &= ~((1 << startpos) - 1);
       ops[0] = GEN_INT (mask);
       ops[0] = GEN_INT (mask);
       output_asm_insn (\"bita\\t%0\", ops);
       output_asm_insn (\"bita\\t%0\", ops);
     }
     }
   else
   else
     {
     {
       mask = (1 << (startpos + bitsize)) - 1;
       mask = (1 << (startpos + bitsize)) - 1;
       mask &= ~((1 << startpos) - 1);
       mask &= ~((1 << startpos) - 1);
       ops[0] = GEN_INT (mask);
       ops[0] = GEN_INT (mask);
       output_asm_insn (\"bitb\\t%0\", ops);
       output_asm_insn (\"bitb\\t%0\", ops);
     }
     }
   return \"\";
   return \"\";
}")
}")
(define_insn "cmpqi_1"
(define_insn "cmpqi_1"
  [(set (cc0)
  [(set (cc0)
        (compare (match_operand:QI 0 "tst_operand" "d,m,d,!u,*B,d*B")
        (compare (match_operand:QI 0 "tst_operand" "d,m,d,!u,*B,d*B")
                 (match_operand:QI 1 "cmp_operand" "im,d,!u,d,dim*A,*u")))]
                 (match_operand:QI 1 "cmp_operand" "im,d,!u,d,dim*A,*u")))]
  ""
  ""
  "*
  "*
{
{
   if (A_REG_P (operands[0]) || A_REG_P (operands[1]))
   if (A_REG_P (operands[0]) || A_REG_P (operands[1]))
     {
     {
        return \"#\";
        return \"#\";
     }
     }
   else if (D_REG_P (operands[0]))
   else if (D_REG_P (operands[0]))
     {
     {
        return \"cmpb\\t%b1\";
        return \"cmpb\\t%b1\";
     }
     }
   cc_status.flags |= CC_REVERSED;
   cc_status.flags |= CC_REVERSED;
   return \"cmpb\\t%b0\";
   return \"cmpb\\t%b0\";
}")
}")
(define_insn_and_split "cmpqi_z_used"
(define_insn_and_split "cmpqi_z_used"
  [(set (cc0)
  [(set (cc0)
        (compare (match_operand:QI 0 "tst_operand" "dxy,m")
        (compare (match_operand:QI 0 "tst_operand" "dxy,m")
                 (match_operand:QI 1 "cmp_operand" "m,dxy")))
                 (match_operand:QI 1 "cmp_operand" "m,dxy")))
   (use (match_operand:HI 2 "hard_reg_operand" "dxy,dxy"))
   (use (match_operand:HI 2 "hard_reg_operand" "dxy,dxy"))
   (use (reg:HI SOFT_Z_REGNUM))]
   (use (reg:HI SOFT_Z_REGNUM))]
  ""
  ""
  "#"
  "#"
  "z_replacement_completed == 2"
  "z_replacement_completed == 2"
  [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 2))
  [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 2))
   (set (match_dup 2) (match_dup 3))
   (set (match_dup 2) (match_dup 3))
   (set (cc0) (compare (match_dup 0) (match_dup 1)))
   (set (cc0) (compare (match_dup 0) (match_dup 1)))
   (set (match_dup 2) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))]
   (set (match_dup 2) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))]
  "operands[3] = gen_rtx_REG (HImode, SOFT_Z_REGNUM);")
  "operands[3] = gen_rtx_REG (HImode, SOFT_Z_REGNUM);")
;;--------------------------------------------------------------------
;;--------------------------------------------------------------------
;;-  Move strict_low_part
;;-  Move strict_low_part
;;--------------------------------------------------------------------
;;--------------------------------------------------------------------
;;
;;
;; The (strict_low_part ...) patterns are replaced by normal (set) patterns.
;; The (strict_low_part ...) patterns are replaced by normal (set) patterns.
;; The replacement must be made at the very end because we loose the
;; The replacement must be made at the very end because we loose the
;; (strict_low_part ...) information.  This is correct for our machine
;; (strict_low_part ...) information.  This is correct for our machine
;; description but not for GCC optimization passes.
;; description but not for GCC optimization passes.
;;
;;
(define_insn_and_split "movstrictsi"
(define_insn_and_split "movstrictsi"
  [(set (strict_low_part (match_operand:SI 0 "non_push_operand" "+um,D,D"))
  [(set (strict_low_part (match_operand:SI 0 "non_push_operand" "+um,D,D"))
        (match_operand:SI 1 "general_operand" "D,Dim,uD"))]
        (match_operand:SI 1 "general_operand" "D,Dim,uD"))]
  ""
  ""
  "#"
  "#"
  "z_replacement_completed == 2"
  "z_replacement_completed == 2"
  [(set (match_dup 0) (match_dup 1))]
  [(set (match_dup 0) (match_dup 1))]
  "")
  "")
(define_insn_and_split "movstricthi"
(define_insn_and_split "movstricthi"
  [(set (strict_low_part (match_operand:HI 0 "non_push_operand" "+um,dA,dA"))
  [(set (strict_low_part (match_operand:HI 0 "non_push_operand" "+um,dA,dA"))
        (match_operand:HI 1 "general_operand" "dA,dAim,u"))]
        (match_operand:HI 1 "general_operand" "dA,dAim,u"))]
  ""
  ""
  "#"
  "#"
  "z_replacement_completed == 2"
  "z_replacement_completed == 2"
  [(set (match_dup 0) (match_dup 1))]
  [(set (match_dup 0) (match_dup 1))]
  "")
  "")
(define_insn_and_split "movstrictqi"
(define_insn_and_split "movstrictqi"
  [(set (strict_low_part (match_operand:QI 0 "non_push_operand" "+mu,!dA"))
  [(set (strict_low_part (match_operand:QI 0 "non_push_operand" "+mu,!dA"))
        (match_operand:QI 1 "general_operand" "d,imudA"))]
        (match_operand:QI 1 "general_operand" "d,imudA"))]
  ""
  ""
  "#"
  "#"
  "z_replacement_completed == 2"
  "z_replacement_completed == 2"
  [(set (match_dup 0) (match_dup 1))]
  [(set (match_dup 0) (match_dup 1))]
  "")
  "")
;;--------------------------------------------------------------------
;;--------------------------------------------------------------------
;;- 64-bit Move Operations.
;;- 64-bit Move Operations.
;; The movdi and movdf patterns are identical except for the mode.
;; The movdi and movdf patterns are identical except for the mode.
;; They are also very similar to those for movsi and movsf.
;; They are also very similar to those for movsi and movsf.
;;
;;
;; For 68HC11, we need a scratch register (either D, X, Y)
;; For 68HC11, we need a scratch register (either D, X, Y)
;; because there is no memory->memory moves.  It must be defined with
;; because there is no memory->memory moves.  It must be defined with
;; earlyclobber (&) so that it does not appear in the source or destination
;; earlyclobber (&) so that it does not appear in the source or destination
;; address.  Providing patterns for movdi/movdf allows GCC to generate
;; address.  Providing patterns for movdi/movdf allows GCC to generate
;; better code.  [Until now, the scratch register is limited to D because
;; better code.  [Until now, the scratch register is limited to D because
;; otherwise we can run out of registers in the A_REGS class for reload].
;; otherwise we can run out of registers in the A_REGS class for reload].
;;
;;
;; For 68HC12, the scratch register is not necessary.  To use the same
;; For 68HC12, the scratch register is not necessary.  To use the same
;; pattern and same split, we use the 'v' constraint.  This tells the
;; pattern and same split, we use the 'v' constraint.  This tells the
;; reload to use the _.tmp register (which is not used at all).
;; reload to use the _.tmp register (which is not used at all).
;; The insn will be split in one or several memory moves (movw).
;; The insn will be split in one or several memory moves (movw).
;; [SCz: this does not work ?? So, I switched temporary to 'd' reg]
;; [SCz: this does not work ?? So, I switched temporary to 'd' reg]
;;--------------------------------------------------------------------
;;--------------------------------------------------------------------
(define_expand "movdi"
(define_expand "movdi"
  [(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "")
  [(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "")
                   (match_operand:DI 1 "general_operand" ""))
                   (match_operand:DI 1 "general_operand" ""))
              (clobber (match_scratch:HI 2 ""))])]
              (clobber (match_scratch:HI 2 ""))])]
  ""
  ""
  "
  "
  /* For push/pop, emit a REG_INC note to make sure the reload
  /* For push/pop, emit a REG_INC note to make sure the reload
     inheritance and reload CSE pass notice the change of the stack
     inheritance and reload CSE pass notice the change of the stack
     pointer.  */
     pointer.  */
  if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
  if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
    {
    {
      rtx insn;
      rtx insn;
      insn = emit_insn (gen_movdi_internal (operands[0], operands[1]));
      insn = emit_insn (gen_movdi_internal (operands[0], operands[1]));
      REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
      REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
                                          stack_pointer_rtx,
                                          stack_pointer_rtx,
                                          REG_NOTES (insn));
                                          REG_NOTES (insn));
      DONE;
      DONE;
    }
    }
")
")
;; Separate push from normal moves to avoid reloading problems
;; Separate push from normal moves to avoid reloading problems
;; The 'clr' is not able to push on 68HC11 so we really need a scratch.
;; The 'clr' is not able to push on 68HC11 so we really need a scratch.
;; We can also accept more scratch registers.
;; We can also accept more scratch registers.
(define_insn_and_split "*pushdi_internal"
(define_insn_and_split "*pushdi_internal"
  [(set (match_operand:DI 0 "push_operand" "=<,<,<,<")
  [(set (match_operand:DI 0 "push_operand" "=<,<,<,<")
        (match_operand:DI 1 "general_operand" "i,U,m,!u"))
        (match_operand:DI 1 "general_operand" "i,U,m,!u"))
   (clobber (match_scratch:HI 2 "=&dA,&d,&d,&dA"))]
   (clobber (match_scratch:HI 2 "=&dA,&d,&d,&dA"))]
  ""
  ""
  "#"
  "#"
  "reload_completed"
  "reload_completed"
  [(const_int 0)]
  [(const_int 0)]
  "m68hc11_split_move (operands[0], operands[1], operands[2]);
  "m68hc11_split_move (operands[0], operands[1], operands[2]);
   DONE;")
   DONE;")
(define_insn_and_split "movdi_internal"
(define_insn_and_split "movdi_internal"
  [(set (match_operand:DI 0 "non_push_operand" "=m!u,U,!u,U,m,m,!u")
  [(set (match_operand:DI 0 "non_push_operand" "=m!u,U,!u,U,m,m,!u")
        (match_operand:DI 1 "general_operand" "K,iU,iU,!u,mi,!u,!mu"))
        (match_operand:DI 1 "general_operand" "K,iU,iU,!u,mi,!u,!mu"))
   (clobber (match_scratch:HI 2 "=X,&d,&d,&d,&d,&d,&d"))]
   (clobber (match_scratch:HI 2 "=X,&d,&d,&d,&d,&d,&d"))]
  ""
  ""
  "#"
  "#"
  "reload_completed"
  "reload_completed"
  [(const_int 0)]
  [(const_int 0)]
  "m68hc11_split_move (operands[0], operands[1], operands[2]);
  "m68hc11_split_move (operands[0], operands[1], operands[2]);
   DONE;")
   DONE;")
(define_expand "movdf"
(define_expand "movdf"
  [(parallel [(set (match_operand:DF 0 "nonimmediate_operand" "")
  [(parallel [(set (match_operand:DF 0 "nonimmediate_operand" "")
                   (match_operand:DF 1 "general_operand" ""))
                   (match_operand:DF 1 "general_operand" ""))
              (clobber (match_scratch:HI 2 ""))])]
              (clobber (match_scratch:HI 2 ""))])]
  ""
  ""
  "/* For push/pop, emit a REG_INC note to make sure the reload
  "/* For push/pop, emit a REG_INC note to make sure the reload
      inheritance and reload CSE pass notice the change of the stack
      inheritance and reload CSE pass notice the change of the stack
      pointer.  */
      pointer.  */
  if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
  if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
    {
    {
      rtx insn;
      rtx insn;
      insn = emit_insn (gen_movdf_internal (operands[0], operands[1]));
      insn = emit_insn (gen_movdf_internal (operands[0], operands[1]));
      REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
      REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
                                          stack_pointer_rtx,
                                          stack_pointer_rtx,
                                          REG_NOTES (insn));
                                          REG_NOTES (insn));
      DONE;
      DONE;
    }
    }
")
")
;; See pushdi_internal
;; See pushdi_internal
(define_insn_and_split "*pushdf_internal"
(define_insn_and_split "*pushdf_internal"
  [(set (match_operand:DF 0 "push_operand" "=<,<,<,<")
  [(set (match_operand:DF 0 "push_operand" "=<,<,<,<")
        (match_operand:DF 1 "general_operand" "i,U,m,!u"))
        (match_operand:DF 1 "general_operand" "i,U,m,!u"))
   (clobber (match_scratch:HI 2 "=&dA,&d,&d,&dA"))]
   (clobber (match_scratch:HI 2 "=&dA,&d,&d,&dA"))]
  ""
  ""
  "#"
  "#"
  "reload_completed"
  "reload_completed"
  [(const_int 0)]
  [(const_int 0)]
  "m68hc11_split_move (operands[0], operands[1], operands[2]);
  "m68hc11_split_move (operands[0], operands[1], operands[2]);
   DONE;")
   DONE;")
(define_insn_and_split "movdf_internal"
(define_insn_and_split "movdf_internal"
  [(set (match_operand:DF 0 "non_push_operand" "=mu,U,m,!u,U,m,!u")
  [(set (match_operand:DF 0 "non_push_operand" "=mu,U,m,!u,U,m,!u")
        (match_operand:DF 1 "general_operand" "G,iU,mi,iU,!u,!u,!mu"))
        (match_operand:DF 1 "general_operand" "G,iU,mi,iU,!u,!u,!mu"))
   (clobber (match_scratch:HI 2 "=X,&d,&d,&d,&d,&d,&d"))]
   (clobber (match_scratch:HI 2 "=X,&d,&d,&d,&d,&d,&d"))]
  ""
  ""
  "#"
  "#"
  "reload_completed"
  "reload_completed"
  [(const_int 0)]
  [(const_int 0)]
  "m68hc11_split_move (operands[0], operands[1], operands[2]);
  "m68hc11_split_move (operands[0], operands[1], operands[2]);
   DONE;")
   DONE;")
;;--------------------------------------------------------------------
;;--------------------------------------------------------------------
;;- 32-bit Move Operations.
;;- 32-bit Move Operations.
;; The movsi and movsf patterns are identical except for the mode.
;; The movsi and movsf patterns are identical except for the mode.
;; When we move to/from a hard register (d+x), we don't need a scratch.
;; When we move to/from a hard register (d+x), we don't need a scratch.
;; Otherwise, a scratch register is used as intermediate register for
;; Otherwise, a scratch register is used as intermediate register for
;; the move.  The '&' constraint is necessary to make sure the reload
;; the move.  The '&' constraint is necessary to make sure the reload
;; pass does not give us a register that dies in the insn and is used
;; pass does not give us a register that dies in the insn and is used
;; for input/output operands.
;; for input/output operands.
;;--------------------------------------------------------------------
;;--------------------------------------------------------------------
(define_expand "movsi"
(define_expand "movsi"
  [(parallel [(set (match_operand:SI 0 "nonimmediate_operand" "")
  [(parallel [(set (match_operand:SI 0 "nonimmediate_operand" "")
                   (match_operand:SI 1 "general_operand" ""))
                   (match_operand:SI 1 "general_operand" ""))
              (clobber (match_scratch:HI 2 ""))])]
              (clobber (match_scratch:HI 2 ""))])]
  ""
  ""
  "/* For push/pop, emit a REG_INC note to make sure the reload
  "/* For push/pop, emit a REG_INC note to make sure the reload
      inheritance and reload CSE pass notice the change of the stack
      inheritance and reload CSE pass notice the change of the stack
      pointer.  */
      pointer.  */
  if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
  if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
    {
    {
      rtx insn;
      rtx insn;
      insn = emit_insn (gen_movsi_internal (operands[0], operands[1]));
      insn = emit_insn (gen_movsi_internal (operands[0], operands[1]));
      REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
      REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
                                          stack_pointer_rtx,
                                          stack_pointer_rtx,
                                          REG_NOTES (insn));
                                          REG_NOTES (insn));
      DONE;
      DONE;
    }
    }
")
")
(define_insn_and_split "*pushsi_internal"
(define_insn_and_split "*pushsi_internal"
  [(set (match_operand:SI 0 "push_operand" "=<,<,<,<,<")
  [(set (match_operand:SI 0 "push_operand" "=<,<,<,<,<")
        (match_operand:SI 1 "general_operand" "!D,i,U,m,!u"))
        (match_operand:SI 1 "general_operand" "!D,i,U,m,!u"))
   (clobber (match_scratch:HI 2 "=X,&dA,&d,&d,&dA"))]
   (clobber (match_scratch:HI 2 "=X,&dA,&d,&d,&dA"))]
  ""
  ""
  "#"
  "#"
  "reload_completed"
  "reload_completed"
  [(const_int 0)]
  [(const_int 0)]
  "m68hc11_split_move (operands[0], operands[1], operands[2]);
  "m68hc11_split_move (operands[0], operands[1], operands[2]);
   DONE;")
   DONE;")
(define_insn_and_split "movsi_internal"
(define_insn_and_split "movsi_internal"
  [(set (match_operand:SI 0 "nonimmediate_operand" "=mu,mu,?D,m,?D,?u,?u,!u,D")
  [(set (match_operand:SI 0 "nonimmediate_operand" "=mu,mu,?D,m,?D,?u,?u,!u,D")
        (match_operand:SI 1 "general_operand" "K,imu,im,?D,!u,?D,mi,!u,!D"))
        (match_operand:SI 1 "general_operand" "K,imu,im,?D,!u,?D,mi,!u,!D"))
   (clobber (match_scratch:HI 2               "=X,&d,X,X,X,X,&d,&d,X"))]
   (clobber (match_scratch:HI 2               "=X,&d,X,X,X,X,&d,&d,X"))]
  ""
  ""
  "#"
  "#"
  "reload_completed"
  "reload_completed"
  [(const_int 0)]
  [(const_int 0)]
  "m68hc11_split_move (operands[0], operands[1], operands[2]);
  "m68hc11_split_move (operands[0], operands[1], operands[2]);
   DONE;")
   DONE;")
(define_expand "movsf"
(define_expand "movsf"
  [(parallel [(set (match_operand:SF 0 "nonimmediate_operand" "")
  [(parallel [(set (match_operand:SF 0 "nonimmediate_operand" "")
                   (match_operand:SF 1 "general_operand" ""))
                   (match_operand:SF 1 "general_operand" ""))
              (clobber (match_scratch:HI 2 ""))])]
              (clobber (match_scratch:HI 2 ""))])]
  ""
  ""
  "/* For push/pop, emit a REG_INC note to make sure the reload
  "/* For push/pop, emit a REG_INC note to make sure the reload
      inheritance and reload CSE pass notice the change of the stack
      inheritance and reload CSE pass notice the change of the stack
      pointer.  */
      pointer.  */
  if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
  if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
    {
    {
      rtx insn;
      rtx insn;
      insn = emit_insn (gen_movsf_internal (operands[0], operands[1]));
      insn = emit_insn (gen_movsf_internal (operands[0], operands[1]));
      REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
      REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
                                          stack_pointer_rtx,
                                          stack_pointer_rtx,
                                          REG_NOTES (insn));
                                          REG_NOTES (insn));
      DONE;
      DONE;
    }
    }
")
")
(define_insn_and_split "*pushsf_internal"
(define_insn_and_split "*pushsf_internal"
  [(set (match_operand:SF 0 "push_operand" "=<,<,<,<,<")
  [(set (match_operand:SF 0 "push_operand" "=<,<,<,<,<")
        (match_operand:SF 1 "general_operand" "!D,i,U,m,!u"))
        (match_operand:SF 1 "general_operand" "!D,i,U,m,!u"))
   (clobber (match_scratch:HI 2 "=X,&dA,&d,&d,&dA"))]
   (clobber (match_scratch:HI 2 "=X,&dA,&d,&d,&dA"))]
  ""
  ""
  "#"
  "#"
  "reload_completed"
  "reload_completed"
  [(const_int 0)]
  [(const_int 0)]
  "m68hc11_split_move (operands[0], operands[1], operands[2]);
  "m68hc11_split_move (operands[0], operands[1], operands[2]);
   DONE;")
   DONE;")
(define_insn_and_split "movsf_internal"
(define_insn_and_split "movsf_internal"
  [(set (match_operand:SF 0 "nonimmediate_operand" "=m!u,m,D,m,D,!u,!u,!u,D")
  [(set (match_operand:SF 0 "nonimmediate_operand" "=m!u,m,D,m,D,!u,!u,!u,D")
        (match_operand:SF 1 "general_operand" "G,im,im,D,!u,D,mi,!u,!D"))
        (match_operand:SF 1 "general_operand" "G,im,im,D,!u,D,mi,!u,!D"))
   (clobber (match_scratch:HI 2 "=X,&d,X,X,X,X,&d,&d,X"))]
   (clobber (match_scratch:HI 2 "=X,&d,X,X,X,X,&d,&d,X"))]
  ""
  ""
  "#"
  "#"
  "reload_completed"
  "reload_completed"
  [(const_int 0)]
  [(const_int 0)]
  "m68hc11_split_move (operands[0], operands[1], operands[2]);
  "m68hc11_split_move (operands[0], operands[1], operands[2]);
   DONE;")
   DONE;")
;;--------------------------------------------------------------------
;;--------------------------------------------------------------------
;;- 16-bit Move Operations.
;;- 16-bit Move Operations.
;; We don't need a scratch register.
;; We don't need a scratch register.
;;--------------------------------------------------------------------
;;--------------------------------------------------------------------
(define_insn "*movhi2_push"
(define_insn "*movhi2_push"
  [(set (match_operand:HI 0 "push_operand" "=<,<,<")
  [(set (match_operand:HI 0 "push_operand" "=<,<,<")
        (match_operand:HI 1 "general_operand" "xy,?d,!z"))]
        (match_operand:HI 1 "general_operand" "xy,?d,!z"))]
  "TARGET_M6811 && !TARGET_M6812"
  "TARGET_M6811 && !TARGET_M6812"
  "*
  "*
{
{
  cc_status = cc_prev_status;
  cc_status = cc_prev_status;
  if (D_REG_P (operands[1]))
  if (D_REG_P (operands[1]))
    {
    {
      output_asm_insn (\"pshb\", operands);
      output_asm_insn (\"pshb\", operands);
      return \"psha\";
      return \"psha\";
    }
    }
  else if (X_REG_P (operands[1]))
  else if (X_REG_P (operands[1]))
    {
    {
      return \"pshx\";
      return \"pshx\";
    }
    }
  else if (Y_REG_P (operands[1]))
  else if (Y_REG_P (operands[1]))
    {
    {
      return \"pshy\";
      return \"pshy\";
    }
    }
  fatal_insn (\"Invalid register in the instruction\", insn);
  fatal_insn (\"Invalid register in the instruction\", insn);
}")
}")
(define_insn "*movhi2_pop"
(define_insn "*movhi2_pop"
  [(set (match_operand:HI 0 "nonimmediate_operand" "=xy,d")
  [(set (match_operand:HI 0 "nonimmediate_operand" "=xy,d")
        (match_operand:HI 1 "pop_operand" ">,>"))]
        (match_operand:HI 1 "pop_operand" ">,>"))]
  "TARGET_M6811"
  "TARGET_M6811"
  "*
  "*
{
{
  cc_status = cc_prev_status;
  cc_status = cc_prev_status;
  if (D_REG_P (operands[0]))
  if (D_REG_P (operands[0]))
    {
    {
      output_asm_insn (\"pula\", operands);
      output_asm_insn (\"pula\", operands);
      return \"pulb\";
      return \"pulb\";
    }
    }
  else if (X_REG_P (operands[0]))
  else if (X_REG_P (operands[0]))
    {
    {
      return \"pulx\";
      return \"pulx\";
    }
    }
  else if (Y_REG_P (operands[0]))
  else if (Y_REG_P (operands[0]))
    {
    {
      return \"puly\";
      return \"puly\";
    }
    }
  fatal_insn (\"Invalid register in the instruction\", insn);
  fatal_insn (\"Invalid register in the instruction\", insn);
}")
}")
(define_expand "movhi"
(define_expand "movhi"
  [(set (match_operand:HI 0 "nonimmediate_operand" "")
  [(set (match_operand:HI 0 "nonimmediate_operand" "")
        (match_operand:HI 1 "general_operand" ""))]
        (match_operand:HI 1 "general_operand" ""))]
  ""
  ""
  "
  "
{
{
  if (reload_in_progress)
  if (reload_in_progress)
    {
    {
      if (m68hc11_reload_operands (operands))
      if (m68hc11_reload_operands (operands))
        {
        {
          DONE;
          DONE;
        }
        }
    }
    }
  if (TARGET_M6811 && (reload_in_progress | reload_completed) == 0)
  if (TARGET_M6811 && (reload_in_progress | reload_completed) == 0)
    {
    {
      if (GET_CODE (operands[0]) == MEM &&
      if (GET_CODE (operands[0]) == MEM &&
          (GET_CODE (operands[1]) == MEM
          (GET_CODE (operands[1]) == MEM
           || GET_CODE (operands[1]) == CONST_INT))
           || GET_CODE (operands[1]) == CONST_INT))
        {
        {
          operands[1] = force_reg (HImode, operands[1]);
          operands[1] = force_reg (HImode, operands[1]);
        }
        }
      else if (IS_STACK_PUSH (operands[0])
      else if (IS_STACK_PUSH (operands[0])
               && GET_CODE (operands[1]) != REG)
               && GET_CODE (operands[1]) != REG)
        {
        {
          operands[1] = force_reg (HImode, operands[1]);
          operands[1] = force_reg (HImode, operands[1]);
        }
        }
    }
    }
  /* For push/pop, emit a REG_INC note to make sure the reload
  /* For push/pop, emit a REG_INC note to make sure the reload
     inheritance and reload CSE pass notice the change of the stack
     inheritance and reload CSE pass notice the change of the stack
     pointer.  */
     pointer.  */
  if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
  if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
    {
    {
      rtx insn;
      rtx insn;
      insn = emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
      insn = emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
      REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
      REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
                                          stack_pointer_rtx,
                                          stack_pointer_rtx,
                                          REG_NOTES (insn));
                                          REG_NOTES (insn));
      DONE;
      DONE;
    }
    }
}")
}")
(define_insn "*movhi_68hc12"
(define_insn "*movhi_68hc12"
  [(set (match_operand:HI 0 "nonimmediate_operand" "=U,dAw,dAw,m,U,U,m,!u")
  [(set (match_operand:HI 0 "nonimmediate_operand" "=U,dAw,dAw,m,U,U,m,!u")
        (match_operand:HI 1 "general_operand" "U,dAwim,!u,K,dAwi,!u,dAw,riU"))]
        (match_operand:HI 1 "general_operand" "U,dAwim,!u,K,dAwi,!u,dAw,riU"))]
  "TARGET_M6812"
  "TARGET_M6812"
  "*
  "*
{
{
  m68hc11_gen_movhi (insn, operands);
  m68hc11_gen_movhi (insn, operands);
  return \"\";
  return \"\";
}")
}")
(define_insn "movhi_const0"
(define_insn "movhi_const0"
  [(set (match_operand:HI 0 "nonimmediate_operand" "=d,A,um")
  [(set (match_operand:HI 0 "nonimmediate_operand" "=d,A,um")
        (const_int 0))]
        (const_int 0))]
  "TARGET_M6811"
  "TARGET_M6811"
  "@
  "@
   clra\\n\\tclrb
   clra\\n\\tclrb
   ld%0\\t#0
   ld%0\\t#0
   clr\\t%b0\\n\\tclr\\t%h0")
   clr\\t%b0\\n\\tclr\\t%h0")
(define_insn "*movhi_m68hc11"
(define_insn "*movhi_m68hc11"
  [(set (match_operand:HI 0 "nonimmediate_operand" "=dAw,!u,m,m,dAw,!*u")
  [(set (match_operand:HI 0 "nonimmediate_operand" "=dAw,!u,m,m,dAw,!*u")
        (match_operand:HI 1 "general_operand" "dAwim,dAw,dA,?Aw,!*u,dAw"))]
        (match_operand:HI 1 "general_operand" "dAwim,dAw,dA,?Aw,!*u,dAw"))]
  "TARGET_M6811"
  "TARGET_M6811"
  "*
  "*
{
{
  m68hc11_gen_movhi (insn, operands);
  m68hc11_gen_movhi (insn, operands);
  return \"\";
  return \"\";
}")
}")
;;--------------------------------------------------------------------
;;--------------------------------------------------------------------
;;- 8-bit Move Operations.
;;- 8-bit Move Operations.
;; We don't need a scratch register.
;; We don't need a scratch register.
;;--------------------------------------------------------------------
;;--------------------------------------------------------------------
;;
;;
;; The *a alternative also clears the high part of the register.
;; The *a alternative also clears the high part of the register.
;; This should be ok since this is not the (strict_low_part) set.
;; This should be ok since this is not the (strict_low_part) set.
;;
;;
(define_insn "movqi_const0"
(define_insn "movqi_const0"
  [(set (match_operand:QI 0 "non_push_operand" "=d,m,!u,*A,!*q")
  [(set (match_operand:QI 0 "non_push_operand" "=d,m,!u,*A,!*q")
        (const_int 0))]
        (const_int 0))]
  ""
  ""
  "@
  "@
   clrb
   clrb
   clr\\t%b0
   clr\\t%b0
   clr\\t%b0
   clr\\t%b0
   ld%0\\t#0
   ld%0\\t#0
   clr%0")
   clr%0")
;;
;;
;; 8-bit operations on address registers.
;; 8-bit operations on address registers.
;;
;;
;; Switch temporary to the D register and load the value in B.
;; Switch temporary to the D register and load the value in B.
;; This is possible as long as the address register does not
;; This is possible as long as the address register does not
;; appear in the source operand.
;; appear in the source operand.
;;
;;
(define_split
(define_split
  [(set (match_operand:QI 0 "hard_addr_reg_operand" "")
  [(set (match_operand:QI 0 "hard_addr_reg_operand" "")
        (match_operand:QI 1 "general_operand" ""))]
        (match_operand:QI 1 "general_operand" ""))]
  "z_replacement_completed == 2
  "z_replacement_completed == 2
   && !reg_mentioned_p (operands[0], operands[1])
   && !reg_mentioned_p (operands[0], operands[1])
   && !(D_REG_P (operands[1]) || Q_REG_P (operands[1]))"
   && !(D_REG_P (operands[1]) || Q_REG_P (operands[1]))"
  [(parallel [(set (reg:HI D_REGNUM) (match_dup 2))
  [(parallel [(set (reg:HI D_REGNUM) (match_dup 2))
              (set (match_dup 2) (reg:HI D_REGNUM))])
              (set (match_dup 2) (reg:HI D_REGNUM))])
   (set (reg:QI D_REGNUM) (match_dup 1))
   (set (reg:QI D_REGNUM) (match_dup 1))
   (parallel [(set (reg:HI D_REGNUM) (match_dup 2))
   (parallel [(set (reg:HI D_REGNUM) (match_dup 2))
              (set (match_dup 2) (reg:HI D_REGNUM))])]
              (set (match_dup 2) (reg:HI D_REGNUM))])]
  "operands[2] = gen_rtx_REG (HImode, REGNO (operands[0]));")
  "operands[2] = gen_rtx_REG (HImode, REGNO (operands[0]));")
;;
;;
;; 8-bit operations on address registers.
;; 8-bit operations on address registers.
;;
;;
(define_split
(define_split
  [(set (match_operand:QI 0 "nonimmediate_operand" "")
  [(set (match_operand:QI 0 "nonimmediate_operand" "")
        (match_operand:QI 1 "hard_addr_reg_operand" ""))]
        (match_operand:QI 1 "hard_addr_reg_operand" ""))]
  "z_replacement_completed == 2
  "z_replacement_completed == 2
   && !reg_mentioned_p (operands[1], operands[0])
   && !reg_mentioned_p (operands[1], operands[0])
   && !(D_REG_P (operands[0]) || Q_REG_P (operands[0]))"
   && !(D_REG_P (operands[0]) || Q_REG_P (operands[0]))"
  [(parallel [(set (reg:HI D_REGNUM) (match_dup 2))
  [(parallel [(set (reg:HI D_REGNUM) (match_dup 2))
              (set (match_dup 2) (reg:HI D_REGNUM))])
              (set (match_dup 2) (reg:HI D_REGNUM))])
   (set (match_dup 0) (reg:QI D_REGNUM))
   (set (match_dup 0) (reg:QI D_REGNUM))
   (parallel [(set (reg:HI D_REGNUM) (match_dup 2))
   (parallel [(set (reg:HI D_REGNUM) (match_dup 2))
              (set (match_dup 2) (reg:HI D_REGNUM))])]
              (set (match_dup 2) (reg:HI D_REGNUM))])]
  "operands[2] = gen_rtx_REG (HImode, REGNO (operands[1]));")
  "operands[2] = gen_rtx_REG (HImode, REGNO (operands[1]));")
(define_insn "*movqi2_push"
(define_insn "*movqi2_push"
  [(set (match_operand:QI 0 "push_operand" "=<,<")
  [(set (match_operand:QI 0 "push_operand" "=<,<")
        (match_operand:QI 1 "general_operand" "d,!*A"))]
        (match_operand:QI 1 "general_operand" "d,!*A"))]
  ""
  ""
  "*
  "*
{
{
  if (A_REG_P (operands[1]))
  if (A_REG_P (operands[1]))
    return \"#\";
    return \"#\";
  cc_status = cc_prev_status;
  cc_status = cc_prev_status;
  return \"pshb\";
  return \"pshb\";
}")
}")
(define_expand "movqi"
(define_expand "movqi"
  [(set (match_operand:QI 0 "nonimmediate_operand" "")
  [(set (match_operand:QI 0 "nonimmediate_operand" "")
        (match_operand:QI 1 "general_operand" ""))]
        (match_operand:QI 1 "general_operand" ""))]
  ""
  ""
  "
  "
{
{
  if (reload_in_progress)
  if (reload_in_progress)
    {
    {
      if (m68hc11_reload_operands (operands))
      if (m68hc11_reload_operands (operands))
        {
        {
          DONE;
          DONE;
        }
        }
    }
    }
  if (TARGET_M6811 && (reload_in_progress | reload_completed) == 0)
  if (TARGET_M6811 && (reload_in_progress | reload_completed) == 0)
    {
    {
      if (GET_CODE (operands[0]) == MEM
      if (GET_CODE (operands[0]) == MEM
          && (GET_CODE (operands[1]) == MEM
          && (GET_CODE (operands[1]) == MEM
              || GET_CODE (operands[1]) == CONST_INT))
              || GET_CODE (operands[1]) == CONST_INT))
        {
        {
          operands[1] = force_reg (QImode, operands[1]);
          operands[1] = force_reg (QImode, operands[1]);
        }
        }
      else if (IS_STACK_PUSH (operands[0])
      else if (IS_STACK_PUSH (operands[0])
               && GET_CODE (operands[1]) != REG)
               && GET_CODE (operands[1]) != REG)
        {
        {
          operands[1] = force_reg (QImode, operands[1]);
          operands[1] = force_reg (QImode, operands[1]);
        }
        }
    }
    }
  /* For push/pop, emit a REG_INC note to make sure the reload
  /* For push/pop, emit a REG_INC note to make sure the reload
     inheritance and reload CSE pass notice the change of the stack
     inheritance and reload CSE pass notice the change of the stack
     pointer.  */
     pointer.  */
  if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
  if (IS_STACK_PUSH (operands[0]) || IS_STACK_POP (operands[1]))
    {
    {
      rtx insn;
      rtx insn;
      insn = emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
      insn = emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
      REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
      REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC,
                                          stack_pointer_rtx,
                                          stack_pointer_rtx,
                                          REG_NOTES (insn));
                                          REG_NOTES (insn));
      DONE;
      DONE;
    }
    }
}")
}")
(define_insn "*movqi_68hc12"
(define_insn "*movqi_68hc12"
  [(set (match_operand:QI 0 "nonimmediate_operand"
  [(set (match_operand:QI 0 "nonimmediate_operand"
                                "=U,d*AU*q,d*A*qU,d*A*q,m,?*u,m")
                                "=U,d*AU*q,d*A*qU,d*A*q,m,?*u,m")
        (match_operand:QI 1 "general_operand"
        (match_operand:QI 1 "general_operand"
                                "U,*ri*q,U,m,d*q,*ri*qU,!*A"))]
                                "U,*ri*q,U,m,d*q,*ri*qU,!*A"))]
  "TARGET_M6812"
  "TARGET_M6812"
  "*
  "*
{
{
  m68hc11_gen_movqi (insn, operands);
  m68hc11_gen_movqi (insn, operands);
  return \"\";
  return \"\";
}")
}")
(define_insn "*movqi_m68hc11"
(define_insn "*movqi_m68hc11"
  [(set (match_operand:QI 0 "nonimmediate_operand" "=d*A*q,m,m,d*A*q,*u")
  [(set (match_operand:QI 0 "nonimmediate_operand" "=d*A*q,m,m,d*A*q,*u")
        (match_operand:QI 1 "general_operand" "d*Aim*q,d*q,!*A,*u,d*A*q"))]
        (match_operand:QI 1 "general_operand" "d*Aim*q,d*q,!*A,*u,d*A*q"))]
  "TARGET_M6811"
  "TARGET_M6811"
  "*
  "*
{
{
  m68hc11_gen_movqi (insn, operands);
  m68hc11_gen_movqi (insn, operands);
  return \"\";
  return \"\";
}")
}")
;;--------------------------------------------------------------------
;;--------------------------------------------------------------------
;;-  Swap registers
;;-  Swap registers
;;--------------------------------------------------------------------
;;--------------------------------------------------------------------
;; Swapping registers is used for split patterns.
;; Swapping registers is used for split patterns.
(define_insn "swap_areg"
(define_insn "swap_areg"
   [(set (match_operand:HI 0 "hard_reg_operand" "=d,A")
   [(set (match_operand:HI 0 "hard_reg_operand" "=d,A")
         (match_operand:HI 1 "hard_reg_operand" "=A,d"))
         (match_operand:HI 1 "hard_reg_operand" "=A,d"))
    (set (match_dup 1) (match_dup 0))]
    (set (match_dup 1) (match_dup 0))]
   ""
   ""
   "*
   "*
{
{
  m68hc11_output_swap (insn, operands);
  m68hc11_output_swap (insn, operands);
  return \"\";
  return \"\";
}")
}")
;;--------------------------------------------------------------------
;;--------------------------------------------------------------------
;;-  Truncation insns.
;;-  Truncation insns.
;;--------------------------------------------------------------------
;;--------------------------------------------------------------------
;;
;;
;; Truncation are not necessary because GCC knows how to truncate,
;; Truncation are not necessary because GCC knows how to truncate,
;; specially when values lie in consecutive registers.
;; specially when values lie in consecutive registers.
;;
;;
(define_expand "floatunssisf2"
(define_expand "floatunssisf2"
  [(set (match_operand:SF 0 "nonimmediate_operand" "")
  [(set (match_operand:SF 0 "nonimmediate_operand" "")
        (unsigned_float:SF (match_operand:SI 1 "general_operand" "")))]
        (unsigned_float:SF (match_operand:SI 1 "general_operand" "")))]
  ""
  ""
  "m68hc11_emit_libcall (\"__floatunsisf\", UNSIGNED_FLOAT,
  "m68hc11_emit_libcall (\"__floatunsisf\", UNSIGNED_FLOAT,
                         SFmode, SImode, 2, operands);
                         SFmode, SImode, 2, operands);
   DONE;")
   DONE;")
(define_expand "floatunssidf2"
(define_expand "floatunssidf2"
  [(set (match_operand:DF 0 "nonimmediate_operand" "")
  [(set (match_operand:DF 0 "nonimmediate_operand" "")
        (unsigned_float:DF (match_operand:SI 1 "general_operand" "")))]
        (unsigned_float:DF (match_operand:SI 1 "general_operand" "")))]
  ""
  ""
  "m68hc11_emit_libcall (\"__floatunsidf\", UNSIGNED_FLOAT,
  "m68hc11_emit_libcall (\"__floatunsidf\", UNSIGNED_FLOAT,
                         DFmode, SImode, 2, operands);
                         DFmode, SImode, 2, operands);
   DONE;")
   DONE;")
;;--------------------------------------------------------------------
;;--------------------------------------------------------------------
;;-  Zero extension insns.
;;-  Zero extension insns.
;;--------------------------------------------------------------------
;;--------------------------------------------------------------------
;;
;;
;; 64-bit extend.  The insn will be split into 16-bit instructions just
;; 64-bit extend.  The insn will be split into 16-bit instructions just
;; before the final pass.  We need a scratch register for the split.
;; before the final pass.  We need a scratch register for the split.
;; The final value can be generated on the stack directly.  This is more
;; The final value can be generated on the stack directly.  This is more
;; efficient and useful for conversions made during parameter passing rules.
;; efficient and useful for conversions made during parameter passing rules.
;;
;;
(define_insn "zero_extendqidi2"
(define_insn "zero_extendqidi2"
  [(set (match_operand:DI 0 "nonimmediate_operand" "=m,!u,m,!u")
  [(set (match_operand:DI 0 "nonimmediate_operand" "=m,!u,m,!u")
        (zero_extend:DI
        (zero_extend:DI
           (match_operand:QI 1 "nonimmediate_operand" "m,dmu,*B,*B")))
           (match_operand:QI 1 "nonimmediate_operand" "m,dmu,*B,*B")))
   (clobber (match_scratch:HI 2 "=&d,&dB,&d,&dB"))]
   (clobber (match_scratch:HI 2 "=&d,&dB,&d,&dB"))]
  ""
  ""
  "#")
  "#")
(define_split
(define_split
  [(set (match_operand:DI 0 "push_operand" "")
  [(set (match_operand:DI 0 "push_operand" "")
        (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "")))
        (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "")))
   (clobber (match_scratch:HI 2 "=&dB"))]
   (clobber (match_scratch:HI 2 "=&dB"))]
  "z_replacement_completed == 2"
  "z_replacement_completed == 2"
  [(const_int 0)]
  [(const_int 0)]
  "
  "
{
{
  rtx low  = m68hc11_gen_lowpart (SImode, operands[0]);
  rtx low  = m68hc11_gen_lowpart (SImode, operands[0]);
  rtx push = m68hc11_gen_lowpart (HImode, low);
  rtx push = m68hc11_gen_lowpart (HImode, low);
  rtx src  = operands[1];
  rtx src  = operands[1];
   /* Source operand must be in a hard register.  */
   /* Source operand must be in a hard register.  */
   if (!H_REG_P (src))
   if (!H_REG_P (src))
     {
     {
       src = gen_rtx_REG (QImode, REGNO (operands[2]));
       src = gen_rtx_REG (QImode, REGNO (operands[2]));
       emit_move_insn (src, operands[1]);
       emit_move_insn (src, operands[1]);
     }
     }
   /* Source is in D, we can push B then one word of 0 and we do
   /* Source is in D, we can push B then one word of 0 and we do
      a correction on the stack pointer.  */
      a correction on the stack pointer.  */
   if (D_REG_P (src))
   if (D_REG_P (src))
     {
     {
       emit_move_insn (m68hc11_gen_lowpart (QImode, push), src);
       emit_move_insn (m68hc11_gen_lowpart (QImode, push), src);
       emit_move_insn (operands[2], const0_rtx);
       emit_move_insn (operands[2], const0_rtx);
       if (D_REG_P (operands[2]))
       if (D_REG_P (operands[2]))
         {
         {
           emit_move_insn (m68hc11_gen_lowpart (QImode, push), src);
           emit_move_insn (m68hc11_gen_lowpart (QImode, push), src);
         }
         }
       else
       else
         {
         {
           emit_move_insn (push, operands[2]);
           emit_move_insn (push, operands[2]);
           emit_insn (gen_addhi3 (gen_rtx_REG (HImode, HARD_SP_REGNUM),
           emit_insn (gen_addhi3 (gen_rtx_REG (HImode, HARD_SP_REGNUM),
                                  gen_rtx_REG (HImode, HARD_SP_REGNUM),
                                  gen_rtx_REG (HImode, HARD_SP_REGNUM),
                                  const1_rtx));
                                  const1_rtx));
         }
         }
     }
     }
   else
   else
     {
     {
       /* Source is in X or Y.  It's better to push the 16-bit register
       /* Source is in X or Y.  It's better to push the 16-bit register
          and then to some stack adjustment.  */
          and then to some stack adjustment.  */
       src = gen_rtx_REG (HImode, REGNO (src));
       src = gen_rtx_REG (HImode, REGNO (src));
       emit_move_insn (push, src);
       emit_move_insn (push, src);
       emit_move_insn (operands[2], const0_rtx);
       emit_move_insn (operands[2], const0_rtx);
       emit_insn (gen_addhi3 (gen_rtx_REG (HImode, HARD_SP_REGNUM),
       emit_insn (gen_addhi3 (gen_rtx_REG (HImode, HARD_SP_REGNUM),
                              gen_rtx_REG (HImode, HARD_SP_REGNUM),
                              gen_rtx_REG (HImode, HARD_SP_REGNUM),
                              const1_rtx));
                              const1_rtx));
       emit_move_insn (push, operands[2]);
       emit_move_insn (push, operands[2]);
       emit_insn (gen_addhi3 (gen_rtx_REG (HImode, HARD_SP_REGNUM),
       emit_insn (gen_addhi3 (gen_rtx_REG (HImode, HARD_SP_REGNUM),
                              gen_rtx_REG (HImode, HARD_SP_REGNUM),
                              gen_rtx_REG (HImode, HARD_SP_REGNUM),
                              const1_rtx));
                              const1_rtx));
     }
     }
   emit_move_insn (push, operands[2]);
   emit_move_insn (push, operands[2]);
   emit_move_insn (push, operands[2]);
   emit_move_insn (push, operands[2]);
   emit_move_insn (push, operands[2]);
   emit_move_insn (push, operands[2]);
   DONE;
   DONE;
}")
}")
(define_split
(define_split
  [(set (match_operand:DI 0 "nonimmediate_operand" "")
  [(set (match_operand:DI 0 "nonimmediate_operand" "")
        (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "")))
        (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "")))
   (clobber (match_scratch:HI 2 "=&dB"))]
   (clobber (match_scratch:HI 2 "=&dB"))]
  "z_replacement_completed == 2"
  "z_replacement_completed == 2"
  [(const_int 0)]
  [(const_int 0)]
  "
  "
{
{
  rtx low  = m68hc11_gen_lowpart (SImode, operands[0]);
  rtx low  = m68hc11_gen_lowpart (SImode, operands[0]);
  rtx low2 = m68hc11_gen_lowpart (HImode, low);
  rtx low2 = m68hc11_gen_lowpart (HImode, low);
  rtx src  = operands[1];
  rtx src  = operands[1];
   /* Source operand must be in a hard register.  */
   /* Source operand must be in a hard register.  */
   if (!H_REG_P (src))
   if (!H_REG_P (src))
     {
     {
       src = gen_rtx_REG (QImode, REGNO (operands[2]));
       src = gen_rtx_REG (QImode, REGNO (operands[2]));
       emit_move_insn (src, operands[1]);
       emit_move_insn (src, operands[1]);
     }
     }
   emit_move_insn (m68hc11_gen_lowpart (QImode, low2), src);
   emit_move_insn (m68hc11_gen_lowpart (QImode, low2), src);
   emit_move_insn (operands[2], const0_rtx);
   emit_move_insn (operands[2], const0_rtx);
   src = gen_rtx_REG (QImode, REGNO (operands[2]));
   src = gen_rtx_REG (QImode, REGNO (operands[2]));
   emit_move_insn (m68hc11_gen_highpart (QImode, low2), src);
   emit_move_insn (m68hc11_gen_highpart (QImode, low2), src);
   emit_move_insn (m68hc11_gen_highpart (HImode, low), operands[2]);
   emit_move_insn (m68hc11_gen_highpart (HImode, low), operands[2]);
   low = m68hc11_gen_highpart (SImode, operands[0]);
   low = m68hc11_gen_highpart (SImode, operands[0]);
   emit_move_insn (m68hc11_gen_lowpart (HImode, low), operands[2]);
   emit_move_insn (m68hc11_gen_lowpart (HImode, low), operands[2]);
   emit_move_insn (m68hc11_gen_highpart (HImode, low), operands[2]);
   emit_move_insn (m68hc11_gen_highpart (HImode, low), operands[2]);
   DONE;
   DONE;
}")
}")
(define_insn "zero_extendhidi2"
(define_insn "zero_extendhidi2"
  [(set (match_operand:DI 0 "non_push_operand" "=m,m,m,m,!u,!u")
  [(set (match_operand:DI 0 "non_push_operand" "=m,m,m,m,!u,!u")
        (zero_extend:DI
        (zero_extend:DI
            (match_operand:HI 1 "nonimmediate_operand" "m,d,A,!u,dmA,!u")))
            (match_operand:HI 1 "nonimmediate_operand" "m,d,A,!u,dmA,!u")))
   (clobber (match_scratch:HI 2 "=&d,&B,&d,&dB,&dB,&dB"))]
   (clobber (match_scratch:HI 2 "=&d,&B,&d,&dB,&dB,&dB"))]
  ""
  ""
  "#")
  "#")
(define_split
(define_split
  [(set (match_operand:DI 0 "non_push_operand" "")
  [(set (match_operand:DI 0 "non_push_operand" "")
        (zero_extend:DI
        (zero_extend:DI
            (match_operand:HI 1 "nonimmediate_operand" "")))
            (match_operand:HI 1 "nonimmediate_operand" "")))
   (clobber (match_scratch:HI 2 ""))]
   (clobber (match_scratch:HI 2 ""))]
  "z_replacement_completed == 2"
  "z_replacement_completed == 2"
  [(const_int 0)]
  [(const_int 0)]
  "
  "
{
{
   rtx low  = m68hc11_gen_lowpart (SImode, operands[0]);
   rtx low  = m68hc11_gen_lowpart (SImode, operands[0]);
   rtx high = m68hc11_gen_highpart (SImode, operands[0]);
   rtx high = m68hc11_gen_highpart (SImode, operands[0]);
   rtx src  = operands[1];
   rtx src  = operands[1];
   /* Make sure the source is in a hard register.  */
   /* Make sure the source is in a hard register.  */
   if (!H_REG_P (src))
   if (!H_REG_P (src))
     {
     {
       src = operands[2];
       src = operands[2];
       emit_move_insn (src, operands[1]);
       emit_move_insn (src, operands[1]);
     }
     }
   /* Move the low part first for the push.  */
   /* Move the low part first for the push.  */
   emit_move_insn (m68hc11_gen_lowpart (HImode, low), src);
   emit_move_insn (m68hc11_gen_lowpart (HImode, low), src);
   /* Now, use the scratch register to fill in the zeros.  */
   /* Now, use the scratch register to fill in the zeros.  */
   emit_move_insn (operands[2], const0_rtx);
   emit_move_insn (operands[2], const0_rtx);
   emit_move_insn (m68hc11_gen_highpart (HImode, low), operands[2]);
   emit_move_insn (m68hc11_gen_highpart (HImode, low), operands[2]);
   emit_move_insn (m68hc11_gen_lowpart (HImode, high), operands[2]);
   emit_move_insn (m68hc11_gen_lowpart (HImode, high), operands[2]);
   emit_move_insn (m68hc11_gen_highpart (HImode, high), operands[2]);
   emit_move_insn (m68hc11_gen_highpart (HImode, high), operands[2]);
   DONE;
   DONE;
}")
}")
(define_insn "zero_extendsidi2"
(define_insn "zero_extendsidi2"
  [(set (match_operand:DI 0 "nonimmediate_operand" "=m,m,!u,!u")
  [(set (match_operand:DI 0 "nonimmediate_operand" "=m,m,!u,!u")
        (zero_extend:DI
        (zero_extend:DI
            (match_operand:SI 1 "nonimmediate_operand" "m,Du,m,Du")))
            (match_operand:SI 1 "nonimmediate_operand" "m,Du,m,Du")))
   (clobber (match_scratch:HI 2 "=d,d,d,d"))]
   (clobber (match_scratch:HI 2 "=d,d,d,d"))]
  ""
  ""
  "#")
  "#")
(define_split
(define_split
  [(set (match_operand:DI 0 "nonimmediate_operand" "")
  [(set (match_operand:DI 0 "nonimmediate_operand" "")
        (zero_extend:DI
        (zero_extend:DI
            (match_operand:SI 1 "nonimmediate_operand" "")))
            (match_operand:SI 1 "nonimmediate_operand" "")))
   (clobber (match_scratch:HI 2 ""))]
   (clobber (match_scratch:HI 2 ""))]
  "z_replacement_completed == 2"
  "z_replacement_completed == 2"
  [(const_int 0)]
  [(const_int 0)]
  "
  "
{
{
  rtx low  = m68hc11_gen_lowpart (SImode, operands[0]);
  rtx low  = m68hc11_gen_lowpart (SImode, operands[0]);
  rtx high = m68hc11_gen_highpart (SImode, operands[0]);
  rtx high = m68hc11_gen_highpart (SImode, operands[0]);
  /* Move the low part first so that this is ok for a push.  */
  /* Move the low part first so that this is ok for a push.  */
  m68hc11_split_move (low, operands[1], operands[2]);
  m68hc11_split_move (low, operands[1], operands[2]);
  /* Use the scratch register to clear the high part of the destination.  */
  /* Use the scratch register to clear the high part of the destination.  */
  emit_move_insn (operands[2], const0_rtx);
  emit_move_insn (operands[2], const0_rtx);
  emit_move_insn (m68hc11_gen_lowpart (HImode, high), operands[2]);
  emit_move_insn (m68hc11_gen_lowpart (HImode, high), operands[2]);
  emit_move_insn (m68hc11_gen_highpart (HImode, high), operands[2]);
  emit_move_insn (m68hc11_gen_highpart (HImode, high), operands[2]);
  DONE;
  DONE;
}")
}")
;;
;;
;; For 16->32bit unsigned extension, we don't allow generation on the stack
;; For 16->32bit unsigned extension, we don't allow generation on the stack
;; because it's less efficient.
;; because it's less efficient.
;;
;;
(define_insn "zero_extendhisi2"
(define_insn "zero_extendhisi2"
  [(set (match_operand:SI 0 "non_push_operand" "=D,m,u,m,m,!u,!u")
  [(set (match_operand:SI 0 "non_push_operand" "=D,m,u,m,m,!u,!u")
        (zero_extend:SI
        (zero_extend:SI
            (match_operand:HI 1 "nonimmediate_operand" "dAmu,dA,dA,m,!u,m,!u")))
            (match_operand:HI 1 "nonimmediate_operand" "dAmu,dA,dA,m,!u,m,!u")))
   (clobber (match_scratch:HI 2 "=X,X,X,&d,&dB,&dB,&dB"))]
   (clobber (match_scratch:HI 2 "=X,X,X,&d,&dB,&dB,&dB"))]
  ""
  ""
  "#")
  "#")
(define_split
(define_split
  [(set (match_operand:SI 0 "non_push_operand" "")
  [(set (match_operand:SI 0 "non_push_operand" "")
        (zero_extend:SI
        (zero_extend:SI
            (match_operand:HI 1 "nonimmediate_operand" "")))
            (match_operand:HI 1 "nonimmediate_operand" "")))
   (clobber (match_scratch:HI 2 ""))]
   (clobber (match_scratch:HI 2 ""))]
  "reload_completed"
  "reload_completed"
  [(const_int 0)]
  [(const_int 0)]
  "
  "
{
{
  rtx src = operands[1];
  rtx src = operands[1];
  if (!H_REG_P (src) && !H_REG_P (operands[0]))
  if (!H_REG_P (src) && !H_REG_P (operands[0]))
    {
    {
      src = operands[2];
      src = operands[2];
      emit_move_insn (src, operands[1]);
      emit_move_insn (src, operands[1]);
    }
    }
  emit_move_insn (m68hc11_gen_lowpart (HImode, operands[0]), src);
  emit_move_insn (m68hc11_gen_lowpart (HImode, operands[0]), src);
  emit_move_insn (m68hc11_gen_highpart (HImode, operands[0]), const0_rtx);
  emit_move_insn (m68hc11_gen_highpart (HImode, operands[0]), const0_rtx);
  DONE;
  DONE;
}")
}")
(define_insn "zero_extendqisi2"
(define_insn "zero_extendqisi2"
  [(set (match_operand:SI 0 "non_push_operand" "=D,D,m,m,u")
  [(set (match_operand:SI 0 "non_push_operand" "=D,D,m,m,u")
      (zero_extend:SI
      (zero_extend:SI
          (match_operand:QI 1 "nonimmediate_operand" "dmu,xy,d,xy,dxy")))]
          (match_operand:QI 1 "nonimmediate_operand" "dmu,xy,d,xy,dxy")))]
  ""
  ""
  "#")
  "#")
(define_split
(define_split
  [(set (match_operand:SI 0 "non_push_operand" "")
  [(set (match_operand:SI 0 "non_push_operand" "")
        (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
        (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
  "reload_completed && !X_REG_P (operands[0])"
  "reload_completed && !X_REG_P (operands[0])"
  [(set (match_dup 2) (zero_extend:HI (match_dup 1)))
  [(set (match_dup 2) (zero_extend:HI (match_dup 1)))
   (set (match_dup 3) (const_int 0))]
   (set (match_dup 3) (const_int 0))]
  "
  "
   operands[2] = m68hc11_gen_lowpart (HImode, operands[0]);
   operands[2] = m68hc11_gen_lowpart (HImode, operands[0]);
   operands[3] = m68hc11_gen_highpart (HImode, operands[0]);")
   operands[3] = m68hc11_gen_highpart (HImode, operands[0]);")
(define_split
(define_split
  [(set (match_operand:SI 0 "hard_reg_operand" "")
  [(set (match_operand:SI 0 "hard_reg_operand" "")
        (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
        (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
  "z_replacement_completed == 2 && X_REG_P (operands[0])"
  "z_replacement_completed == 2 && X_REG_P (operands[0])"
  [(set (match_dup 2) (match_dup 3))
  [(set (match_dup 2) (match_dup 3))
   (set (match_dup 4) (const_int 0))
   (set (match_dup 4) (const_int 0))
   (set (match_dup 5) (zero_extend:HI (match_dup 6)))]
   (set (match_dup 5) (zero_extend:HI (match_dup 6)))]
  "
  "
   if (X_REG_P (operands[1]))
   if (X_REG_P (operands[1]))
     {
     {
        emit_insn (gen_swap_areg (gen_rtx_REG (HImode, HARD_D_REGNUM),
        emit_insn (gen_swap_areg (gen_rtx_REG (HImode, HARD_D_REGNUM),
                                  gen_rtx_REG (HImode, HARD_X_REGNUM)));
                                  gen_rtx_REG (HImode, HARD_X_REGNUM)));
        emit_insn (gen_zero_extendqihi2 (gen_rtx_REG (HImode, HARD_D_REGNUM),
        emit_insn (gen_zero_extendqihi2 (gen_rtx_REG (HImode, HARD_D_REGNUM),
                                         gen_rtx_REG (QImode, HARD_D_REGNUM)));
                                         gen_rtx_REG (QImode, HARD_D_REGNUM)));
        emit_move_insn (gen_rtx_REG (HImode, HARD_X_REGNUM),
        emit_move_insn (gen_rtx_REG (HImode, HARD_X_REGNUM),
                        const0_rtx);
                        const0_rtx);
        DONE;
        DONE;
     }
     }
   if (reg_mentioned_p (gen_rtx_REG (HImode, HARD_X_REGNUM), operands[1]))
   if (reg_mentioned_p (gen_rtx_REG (HImode, HARD_X_REGNUM), operands[1]))
     {
     {
        emit_insn (gen_zero_extendqihi2 (m68hc11_gen_lowpart (HImode,
        emit_insn (gen_zero_extendqihi2 (m68hc11_gen_lowpart (HImode,
                                                              operands[0]),
                                                              operands[0]),
                                         operands[1]));
                                         operands[1]));
        emit_move_insn (gen_rtx_REG (HImode, HARD_X_REGNUM), const0_rtx);
        emit_move_insn (gen_rtx_REG (HImode, HARD_X_REGNUM), const0_rtx);
        DONE;
        DONE;
     }
     }
   operands[4] = m68hc11_gen_highpart (HImode, operands[0]);
   operands[4] = m68hc11_gen_highpart (HImode, operands[0]);
   operands[5] = m68hc11_gen_lowpart (HImode, operands[0]);
   operands[5] = m68hc11_gen_lowpart (HImode, operands[0]);
   if (A_REG_P (operands[1]))
   if (A_REG_P (operands[1]))
     {
     {
       operands[2] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
       operands[2] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
       operands[3] = gen_rtx_REG (HImode, REGNO (operands[1]));
       operands[3] = gen_rtx_REG (HImode, REGNO (operands[1]));
       operands[6] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
       operands[6] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
     }
     }
   else
   else
     {
     {
       operands[5] = operands[2] =
       operands[5] = operands[2] =
       operands[3] = gen_rtx_REG (HImode, HARD_D_REGNUM);
       operands[3] = gen_rtx_REG (HImode, HARD_D_REGNUM);
       operands[6] = operands[1];
       operands[6] = operands[1];
     }
     }
")
")
(define_insn "zero_extendqihi2"
(define_insn "zero_extendqihi2"
  [(set (match_operand:HI 0 "non_push_operand" "=dm,d,*A,!*u,d,m,!*u")
  [(set (match_operand:HI 0 "non_push_operand" "=dm,d,*A,!*u,d,m,!*u")
        (zero_extend:HI
        (zero_extend:HI
            (match_operand:QI 1 "nonimmediate_operand" "d,*A,d*Am,d,!um,*A,*A")))]
            (match_operand:QI 1 "nonimmediate_operand" "d,*A,d*Am,d,!um,*A,*A")))]
  ""
  ""
 "*
 "*
{
{
  if (A_REG_P (operands[0]))
  if (A_REG_P (operands[0]))
    return \"#\";
    return \"#\";
  if (H_REG_P (operands[0]))
  if (H_REG_P (operands[0]))
    {
    {
      output_asm_insn (\"clra\", operands);
      output_asm_insn (\"clra\", operands);
      if (operands[0] != operands[1]
      if (operands[0] != operands[1]
          && !(D_REG_P (operands[0]) && D_REG_P (operands[1])))
          && !(D_REG_P (operands[0]) && D_REG_P (operands[1])))
        {
        {
          if (X_REG_P (operands[1])
          if (X_REG_P (operands[1])
              || (D_REG_P (operands[1]) && X_REG_P (operands[0])))
              || (D_REG_P (operands[1]) && X_REG_P (operands[0])))
            {
            {
              output_asm_insn (\"stx\\t%t1\", operands);
              output_asm_insn (\"stx\\t%t1\", operands);
              output_asm_insn (\"ldab\\t%T0\", operands);
              output_asm_insn (\"ldab\\t%T0\", operands);
            }
            }
          else if (Y_REG_P (operands[1])
          else if (Y_REG_P (operands[1])
                   || (D_REG_P (operands[1]) && Y_REG_P (operands[0])))
                   || (D_REG_P (operands[1]) && Y_REG_P (operands[0])))
            {
            {
              output_asm_insn (\"sty\\t%t1\", operands);
              output_asm_insn (\"sty\\t%t1\", operands);
              output_asm_insn (\"ldab\\t%T0\", operands);
              output_asm_insn (\"ldab\\t%T0\", operands);
            }
            }
          else
          else
            {
            {
              output_asm_insn (\"ldab\\t%b1\", operands);
              output_asm_insn (\"ldab\\t%b1\", operands);
            }
            }
          cc_status.flags |= CC_NOT_NEGATIVE;
          cc_status.flags |= CC_NOT_NEGATIVE;
        }
        }
      else
      else
        {
        {
          /* Status refers to the clra insn. Status is ok for others
          /* Status refers to the clra insn. Status is ok for others
           * since we have loaded the value in B.
           * since we have loaded the value in B.
           */
           */
          CC_STATUS_INIT;
          CC_STATUS_INIT;
        }
        }
      return \"\";
      return \"\";
    }
    }
  if (A_REG_P (operands[1]))
  if (A_REG_P (operands[1]))
    {
    {
      output_asm_insn (\"st%1\\t%0\", operands);
      output_asm_insn (\"st%1\\t%0\", operands);
      output_asm_insn (\"clr\\t%h0\", operands);
      output_asm_insn (\"clr\\t%h0\", operands);
      CC_STATUS_INIT;
      CC_STATUS_INIT;
    }
    }
  else
  else
    {
    {
      output_asm_insn (\"clr\\t%h0\", operands);
      output_asm_insn (\"clr\\t%h0\", operands);
      output_asm_insn (\"stab\\t%b0\", operands);
      output_asm_insn (\"stab\\t%b0\", operands);
      cc_status.flags |= CC_NOT_NEGATIVE;
      cc_status.flags |= CC_NOT_NEGATIVE;
    }
    }
  return \"\";
  return \"\";
}")
}")
;;--------------------------------------------------------------------
;;--------------------------------------------------------------------
;;-  Sign extension insns.
;;-  Sign extension insns.
;;--------------------------------------------------------------------
;;--------------------------------------------------------------------
(define_insn "extendqisi2"
(define_insn "extendqisi2"
  [(set (match_operand:SI 0 "nonimmediate_operand" "=D,m,u")
  [(set (match_operand:SI 0 "nonimmediate_operand" "=D,m,u")
        (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "dmux,d,d")))]
        (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "dmux,d,d")))]
  ""
  ""
  "*
  "*
{
{
  rtx ops[3];
  rtx ops[3];
  int need_tst = 0;
  int need_tst = 0;
  /* The 68HC12 has a sign-extension instruction.  Use it when the
  /* The 68HC12 has a sign-extension instruction.  Use it when the
     destination is the register (X,D).  First sign-extend the low
     destination is the register (X,D).  First sign-extend the low
     part and fill X with the sign-extension of the high part.  */
     part and fill X with the sign-extension of the high part.  */
  if (TARGET_M6812 && X_REG_P (operands[0]))
  if (TARGET_M6812 && X_REG_P (operands[0]))
    {
    {
      if (!D_REG_P (operands[1]))
      if (!D_REG_P (operands[1]))
        {
        {
          ops[0] = gen_rtx_REG (QImode, HARD_D_REGNUM);
          ops[0] = gen_rtx_REG (QImode, HARD_D_REGNUM);
          ops[1] = operands[1];
          ops[1] = operands[1];
          m68hc11_gen_movqi (insn, ops);
          m68hc11_gen_movqi (insn, ops);
        }
        }
      return \"sex\\tb,d\\n\\tsex\\ta,x\";
      return \"sex\\tb,d\\n\\tsex\\ta,x\";
    }
    }
  ops[2] = gen_label_rtx ();
  ops[2] = gen_label_rtx ();
  if (X_REG_P (operands[1]))
  if (X_REG_P (operands[1]))
    {
    {
      output_asm_insn (\"xgdx\", operands);
      output_asm_insn (\"xgdx\", operands);
      need_tst = 1;
      need_tst = 1;
    }
    }
  else if (X_REG_P (operands[0]))
  else if (X_REG_P (operands[0]))
    {
    {
      /* X can be used as an indexed addressing in the source.
      /* X can be used as an indexed addressing in the source.
         Get the value before clearing it.  */
         Get the value before clearing it.  */
      if (reg_mentioned_p (ix_reg, operands[1]))
      if (reg_mentioned_p (ix_reg, operands[1]))
        {
        {
          output_asm_insn (\"ldab\\t%b1\", operands);
          output_asm_insn (\"ldab\\t%b1\", operands);
          need_tst = 1;
          need_tst = 1;
        }
        }
      output_asm_insn (\"ldx\\t#0\", operands);
      output_asm_insn (\"ldx\\t#0\", operands);
    }
    }
  output_asm_insn (\"clra\", operands);
  output_asm_insn (\"clra\", operands);
  if (!X_REG_P (operands[0]))
  if (!X_REG_P (operands[0]))
    {
    {
      ops[0] = m68hc11_gen_lowpart (HImode, operands[0]);
      ops[0] = m68hc11_gen_lowpart (HImode, operands[0]);
      ops[1] = m68hc11_gen_lowpart (QImode, ops[0]);
      ops[1] = m68hc11_gen_lowpart (QImode, ops[0]);
      if (IS_STACK_PUSH (operands[0]))
      if (IS_STACK_PUSH (operands[0]))
        {
        {
          output_asm_insn (\"pshb\", ops);
          output_asm_insn (\"pshb\", ops);
          output_asm_insn (\"tstb\", ops);
          output_asm_insn (\"tstb\", ops);
        }
        }
      else
      else
        {
        {
          output_asm_insn (\"stab\\t%b1\", ops);
          output_asm_insn (\"stab\\t%b1\", ops);
        }
        }
    }
    }
  else if (D_REG_P (operands[1]) || need_tst)
  else if (D_REG_P (operands[1]) || need_tst)
    {
    {
      output_asm_insn (\"tstb\", operands);
      output_asm_insn (\"tstb\", operands);
    }
    }
  else
  else
    {
    {
      output_asm_insn (\"ldab\\t%b1\", operands);
      output_asm_insn (\"ldab\\t%b1\", operands);
    }
    }
  output_asm_insn (\"bpl\\t%l2\", ops);
  output_asm_insn (\"bpl\\t%l2\", ops);
  output_asm_insn (\"deca\", operands);
  output_asm_insn (\"deca\", operands);
  if (X_REG_P (operands[0]))
  if (X_REG_P (operands[0]))
    output_asm_insn (\"dex\", operands);
    output_asm_insn (\"dex\", operands);
  (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[2]));
  (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[2]));
  if (!X_REG_P (operands[0]))
  if (!X_REG_P (operands[0]))
    {
    {
      if (IS_STACK_PUSH (operands[0]))
      if (IS_STACK_PUSH (operands[0]))
        {
        {
          output_asm_insn (\"psha\", ops);
          output_asm_insn (\"psha\", ops);
          output_asm_insn (\"psha\", ops);
          output_asm_insn (\"psha\", ops);
          output_asm_insn (\"psha\", ops);
          output_asm_insn (\"psha\", ops);
        }
        }
      else
      else
        {
        {
          output_asm_insn (\"staa\\t%h0\", ops);
          output_asm_insn (\"staa\\t%h0\", ops);
          ops[0] = m68hc11_gen_highpart (HImode, operands[0]);
          ops[0] = m68hc11_gen_highpart (HImode, operands[0]);
          if (dead_register_here (insn, d_reg))
          if (dead_register_here (insn, d_reg))
            {
            {
              output_asm_insn (\"tab\", ops);
              output_asm_insn (\"tab\", ops);
              output_asm_insn (\"std\\t%0\", ops);
              output_asm_insn (\"std\\t%0\", ops);
            }
            }
          else
          else
            {
            {
              output_asm_insn (\"staa\\t%b0\", ops);
              output_asm_insn (\"staa\\t%b0\", ops);
              output_asm_insn (\"staa\\t%h0\", ops);
              output_asm_insn (\"staa\\t%h0\", ops);
            }
            }
        }
        }
    }
    }
  CC_STATUS_INIT;
  CC_STATUS_INIT;
  return \"\";
  return \"\";
}")
}")
(define_insn "extendqihi2"
(define_insn "extendqihi2"
  [(set (match_operand:HI 0 "non_push_operand" "=d,*x*ym,u")
  [(set (match_operand:HI 0 "non_push_operand" "=d,*x*ym,u")
        (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "dum,0,0")))]
        (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "dum,0,0")))]
  ""
  ""
  "*
  "*
{
{
  rtx ops[2];
  rtx ops[2];
  if (A_REG_P (operands[0]))
  if (A_REG_P (operands[0]))
    return \"#\";
    return \"#\";
  ops[0] = gen_label_rtx ();
  ops[0] = gen_label_rtx ();
  if (D_REG_P (operands[0]))
  if (D_REG_P (operands[0]))
    {
    {
      if (TARGET_M6812)
      if (TARGET_M6812)
        {
        {
          if (!D_REG_P (operands[1]))
          if (!D_REG_P (operands[1]))
            {
            {
              ops[0] = gen_rtx_REG (QImode, HARD_D_REGNUM);
              ops[0] = gen_rtx_REG (QImode, HARD_D_REGNUM);
              ops[1] = operands[1];
              ops[1] = operands[1];
              m68hc11_gen_movqi (insn, ops);
              m68hc11_gen_movqi (insn, ops);
            }
            }
          return \"sex\\tb,d\";
          return \"sex\\tb,d\";
        }
        }
      output_asm_insn (\"clra\", operands);
      output_asm_insn (\"clra\", operands);
      if (H_REG_P (operands[1]))
      if (H_REG_P (operands[1]))
        {
        {
          output_asm_insn (\"tstb\", operands);
          output_asm_insn (\"tstb\", operands);
        }
        }
      else
      else
        {
        {
          output_asm_insn (\"ldab\\t%b1\", operands);
          output_asm_insn (\"ldab\\t%b1\", operands);
        }
        }
      output_asm_insn (\"bpl\\t%l0\", ops);
      output_asm_insn (\"bpl\\t%l0\", ops);
      output_asm_insn (\"deca\", operands);
      output_asm_insn (\"deca\", operands);
      (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
      (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
                                 CODE_LABEL_NUMBER (ops[0]));
                                 CODE_LABEL_NUMBER (ops[0]));
    }
    }
   else
   else
    {
    {
      output_asm_insn (\"clr\\t%h0\", operands);
      output_asm_insn (\"clr\\t%h0\", operands);
      if (m68hc11_register_indirect_p (operands[1], HImode))
      if (m68hc11_register_indirect_p (operands[1], HImode))
        {
        {
          ops[1] = operands[1];
          ops[1] = operands[1];
          output_asm_insn (\"brclr\\t%b1 #0x80 %l0\", ops);
          output_asm_insn (\"brclr\\t%b1 #0x80 %l0\", ops);
          CC_STATUS_INIT;
          CC_STATUS_INIT;
        }
        }
      else
      else
        {
        {
          output_asm_insn (\"tst\\t%b1\", operands);
          output_asm_insn (\"tst\\t%b1\", operands);
          output_asm_insn (\"bpl\\t%l0\", ops);
          output_asm_insn (\"bpl\\t%l0\", ops);
        }
        }
      output_asm_insn (\"dec\\t%h0\", operands);
      output_asm_insn (\"dec\\t%h0\", operands);
      (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
      (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
                                 CODE_LABEL_NUMBER (ops[0]));
                                 CODE_LABEL_NUMBER (ops[0]));
    }
    }
  return \"\";
  return \"\";
}")
}")
;;
;;
;; Split the special case where the source of the sign extend is
;; Split the special case where the source of the sign extend is
;; either Y or Z. In that case, we can't move the source in the D
;; either Y or Z. In that case, we can't move the source in the D
;; register directly. The movhi pattern handles this move by using
;; register directly. The movhi pattern handles this move by using
;; a temporary scratch memory location.
;; a temporary scratch memory location.
;;
;;
(define_split
(define_split
  [(set (match_operand:SI 0 "register_operand" "")
  [(set (match_operand:SI 0 "register_operand" "")
        (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
        (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
  "reload_completed && (Y_REG_P (operands[1]) || Z_REG_P (operands[1]))"
  "reload_completed && (Y_REG_P (operands[1]) || Z_REG_P (operands[1]))"
  [(set (reg:HI D_REGNUM) (match_dup 1))
  [(set (reg:HI D_REGNUM) (match_dup 1))
   (set (match_dup 0) (sign_extend:SI (reg:HI D_REGNUM)))]
   (set (match_dup 0) (sign_extend:SI (reg:HI D_REGNUM)))]
  "")
  "")
(define_insn "extendhisi2"
(define_insn "extendhisi2"
  [(set (match_operand:SI 0 "register_operand" "=D,D,D")
  [(set (match_operand:SI 0 "register_operand" "=D,D,D")
        (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "m,!r,dA")))]
        (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "m,!r,dA")))]
  ""
  ""
  "*
  "*
{
{
  rtx ops[2];
  rtx ops[2];
  int x_reg_used;
  int x_reg_used;
  if (Y_REG_P (operands[1]))
  if (Y_REG_P (operands[1]))
    return \"#\";
    return \"#\";
  if (X_REG_P (operands[1]))
  if (X_REG_P (operands[1]))
    {
    {
      output_asm_insn (\"xgdx\", operands);
      output_asm_insn (\"xgdx\", operands);
      x_reg_used = 1;
      x_reg_used = 1;
    }
    }
  else
  else
    {
    {
      /* X can be used as an indexed addressing in the source.
      /* X can be used as an indexed addressing in the source.
         Get the value before clearing it.  */
         Get the value before clearing it.  */
      x_reg_used = reg_mentioned_p (ix_reg, operands[1]);
      x_reg_used = reg_mentioned_p (ix_reg, operands[1]);
      if (x_reg_used)
      if (x_reg_used)
        {
        {
          ops[0] = gen_rtx_REG (HImode, HARD_D_REGNUM);
          ops[0] = gen_rtx_REG (HImode, HARD_D_REGNUM);
          ops[1] = operands[1];
          ops[1] = operands[1];
          m68hc11_gen_movhi (insn, ops);
          m68hc11_gen_movhi (insn, ops);
        }
        }
    }
    }
  CC_STATUS_INIT;
  CC_STATUS_INIT;
  if (TARGET_M6812 && 0)
  if (TARGET_M6812 && 0)
    {
    {
      /* This sequence of code is larger than the one for 68HC11.
      /* This sequence of code is larger than the one for 68HC11.
         Don't use it; keep it for documentation.  */
         Don't use it; keep it for documentation.  */
      if (!D_REG_P (operands[1]) && !x_reg_used)
      if (!D_REG_P (operands[1]) && !x_reg_used)
        {
        {
          ops[0] = gen_rtx_REG (HImode, HARD_D_REGNUM);
          ops[0] = gen_rtx_REG (HImode, HARD_D_REGNUM);
          ops[1] = operands[1];
          ops[1] = operands[1];
          m68hc11_gen_movhi (insn, ops);
          m68hc11_gen_movhi (insn, ops);
        }
        }
      output_asm_insn (\"sex\\ta,x\", operands);
      output_asm_insn (\"sex\\ta,x\", operands);
      output_asm_insn (\"xgdx\", operands);
      output_asm_insn (\"xgdx\", operands);
      output_asm_insn (\"sex\\ta,d\", operands);
      output_asm_insn (\"sex\\ta,d\", operands);
      return \"xgdx\";
      return \"xgdx\";
    }
    }
  output_asm_insn (\"ldx\\t#0\", operands);
  output_asm_insn (\"ldx\\t#0\", operands);
  if (D_REG_P (operands[1]) || x_reg_used)
  if (D_REG_P (operands[1]) || x_reg_used)
    {
    {
      output_asm_insn (\"tsta\", operands);
      output_asm_insn (\"tsta\", operands);
    }
    }
  else
  else
    {
    {
      ops[0] = gen_rtx_REG (HImode, HARD_D_REGNUM);
      ops[0] = gen_rtx_REG (HImode, HARD_D_REGNUM);
      ops[1] = operands[1];
      ops[1] = operands[1];
      m68hc11_gen_movhi (insn, ops);
      m68hc11_gen_movhi (insn, ops);
    }
    }
  ops[0] = gen_label_rtx ();
  ops[0] = gen_label_rtx ();
  output_asm_insn (\"bpl\\t%l0\", ops);
  output_asm_insn (\"bpl\\t%l0\", ops);
  output_asm_insn (\"dex\", operands);
  output_asm_insn (\"dex\", operands);
  (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0]));
  (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0]));
  return \"\";
  return \"\";
}")
}")
;;--------------------------------------------------------------------
;;--------------------------------------------------------------------
;;- Min and Max instructions (68HC12).
;;- Min and Max instructions (68HC12).
;;--------------------------------------------------------------------
;;--------------------------------------------------------------------
(define_insn "uminqi3"
(define_insn "uminqi3"
  [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m")
  [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m")
        (umin:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0")
        (umin:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0")
                 (match_operand:QI 2 "general_operand" "m,d")))]
                 (match_operand:QI 2 "general_operand" "m,d")))]
  "TARGET_M6812 && TARGET_MIN_MAX"
  "TARGET_M6812 && TARGET_MIN_MAX"
  "*
  "*
{
{
  /* Flags are set according to (sub:QI (operand 1) (operand2)).
  /* Flags are set according to (sub:QI (operand 1) (operand2)).
     The mina/minm use A as the source or destination.  This is the
     The mina/minm use A as the source or destination.  This is the
     high part of D.  There is no way to express that in the pattern
     high part of D.  There is no way to express that in the pattern
     so we must use 'exg a,b' to put the operand in the good register.  */
     so we must use 'exg a,b' to put the operand in the good register.  */
  CC_STATUS_INIT;
  CC_STATUS_INIT;
  if (D_REG_P (operands[0]))
  if (D_REG_P (operands[0]))
    {
    {
      return \"exg\\ta,b\\n\\tmina\\t%2\\n\\texg\\ta,b\";
      return \"exg\\ta,b\\n\\tmina\\t%2\\n\\texg\\ta,b\";
    }
    }
  else
  else
    {
    {
      return \"exg\\ta,b\\n\\tminm\\t%0\\n\\texg\\ta,b\";
      return \"exg\\ta,b\\n\\tminm\\t%0\\n\\texg\\ta,b\";
    }
    }
}")
}")
(define_insn "umaxqi3"
(define_insn "umaxqi3"
  [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m")
  [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m")
        (umax:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0")
        (umax:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0")
                 (match_operand:QI 2 "general_operand" "m,d")))]
                 (match_operand:QI 2 "general_operand" "m,d")))]
  "TARGET_M6812 && TARGET_MIN_MAX"
  "TARGET_M6812 && TARGET_MIN_MAX"
  "*
  "*
{
{
  /* Flags are set according to (sub:QI (operand 1) (operand2)).
  /* Flags are set according to (sub:QI (operand 1) (operand2)).
     The maxa/maxm use A as the source or destination.  This is the
     The maxa/maxm use A as the source or destination.  This is the
     high part of D.  There is no way to express that in the pattern
     high part of D.  There is no way to express that in the pattern
     so we must use 'exg a,b' to put the operand in the good register.  */
     so we must use 'exg a,b' to put the operand in the good register.  */
  CC_STATUS_INIT;
  CC_STATUS_INIT;
  if (D_REG_P (operands[0]))
  if (D_REG_P (operands[0]))
    {
    {
      return \"exg\\ta,b\\n\\tmaxa\\t%2\\n\\texg\\ta,b\";
      return \"exg\\ta,b\\n\\tmaxa\\t%2\\n\\texg\\ta,b\";
    }
    }
  else
  else
    {
    {
      return \"exg\\ta,b\\n\\tmaxm\\t%0\\n\\texg\\ta,b\";
      return \"exg\\ta,b\\n\\tmaxm\\t%0\\n\\texg\\ta,b\";
    }
    }
}")
}")
(define_insn "uminhi3"
(define_insn "uminhi3"
  [(set (match_operand:HI 0 "nonimmediate_operand" "=d,m")
  [(set (match_operand:HI 0 "nonimmediate_operand" "=d,m")
        (umin:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
        (umin:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
                 (match_operand:HI 2 "general_operand" "m,d")))]
                 (match_operand:HI 2 "general_operand" "m,d")))]
  "TARGET_M6812 && TARGET_MIN_MAX"
  "TARGET_M6812 && TARGET_MIN_MAX"
  "*
  "*
{
{
  /* Flags are set according to (sub:HI (operand 1) (operand2)).  */
  /* Flags are set according to (sub:HI (operand 1) (operand2)).  */
  CC_STATUS_INIT;
  CC_STATUS_INIT;
  if (D_REG_P (operands[0]))
  if (D_REG_P (operands[0]))
    {
    {
      return \"emind\\t%2\";
      return \"emind\\t%2\";
    }
    }
  else
  else
    {
    {
      return \"eminm\\t%0\";
      return \"eminm\\t%0\";
    }
    }
}")
}")
(define_insn "umaxhi3"
(define_insn "umaxhi3"
  [(set (match_operand:HI 0 "nonimmediate_operand" "=d,m")
  [(set (match_operand:HI 0 "nonimmediate_operand" "=d,m")
        (umax:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
        (umax:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
                 (match_operand:HI 2 "general_operand" "m,d")))]
                 (match_operand:HI 2 "general_operand" "m,d")))]
  "TARGET_M6812 && TARGET_MIN_MAX"
  "TARGET_M6812 && TARGET_MIN_MAX"
  "*
  "*
{
{
  /* Flags are set according to (sub:HI (operand 1) (operand2)).  */
  /* Flags are set according to (sub:HI (operand 1) (operand2)).  */
  CC_STATUS_INIT;
  CC_STATUS_INIT;
  if (D_REG_P (operands[0]))
  if (D_REG_P (operands[0]))
    {
    {
      return \"emaxd\\t%2\";
      return \"emaxd\\t%2\";
    }
    }
  else
  else
    {
    {
      return \"emaxm\\t%0\";
      return \"emaxm\\t%0\";
    }
    }
}")
}")
;;--------------------------------------------------------------------
;;--------------------------------------------------------------------
;;- Add instructions.
;;- Add instructions.
;;--------------------------------------------------------------------
;;--------------------------------------------------------------------
;; 64-bit: Use a library call because what GCC generates is huge.
;; 64-bit: Use a library call because what GCC generates is huge.
;;
;;
(define_expand "adddi3"
(define_expand "adddi3"
  [(set (match_operand:DI 0 "nonimmediate_operand" "")
  [(set (match_operand:DI 0 "nonimmediate_operand" "")
        (plus:DI (match_operand:DI 1 "general_operand" "")
        (plus:DI (match_operand:DI 1 "general_operand" "")
                 (match_operand:DI 2 "general_operand" "")))]
                 (match_operand:DI 2 "general_operand" "")))]
  ""
  ""
  "m68hc11_emit_libcall (\"___adddi3\", PLUS, DImode, DImode, 3, operands);
  "m68hc11_emit_libcall (\"___adddi3\", PLUS, DImode, DImode, 3, operands);
   DONE;")
   DONE;")
;;
;;
;; - 32-bit Add.
;; - 32-bit Add.
;;
;;
(define_expand "addsi3"
(define_expand "addsi3"
  [(parallel [(set (match_operand:SI 0 "register_operand" "")
  [(parallel [(set (match_operand:SI 0 "register_operand" "")
                     (plus:SI (match_operand:SI 1 "general_operand" "")
                     (plus:SI (match_operand:SI 1 "general_operand" "")
                              (match_operand:SI 2 "general_operand" "")))
                              (match_operand:SI 2 "general_operand" "")))
              (clobber (match_scratch:HI 3 ""))])]
              (clobber (match_scratch:HI 3 ""))])]
  ""
  ""
  "")
  "")
(define_insn "*addsi3_zero_extendhi"
(define_insn "*addsi3_zero_extendhi"
  [(set (match_operand:SI 0 "register_operand" "=D,D,D,D")
  [(set (match_operand:SI 0 "register_operand" "=D,D,D,D")
        (plus:SI (zero_extend:SI
        (plus:SI (zero_extend:SI
                 (match_operand:HI 1 "general_operand" "dxi,!u,mdxi,!u"))
                 (match_operand:HI 1 "general_operand" "dxi,!u,mdxi,!u"))
                 (match_operand:SI 2 "general_operand" "mi,mi,D?u,!Du")))
                 (match_operand:SI 2 "general_operand" "mi,mi,D?u,!Du")))
   (clobber (match_scratch:HI 3 "=X,X,X,X"))]
   (clobber (match_scratch:HI 3 "=X,X,X,X"))]
  ""
  ""
  "*
  "*
{
{
  rtx ops[3];
  rtx ops[3];
  if (X_REG_P (operands[2]))
  if (X_REG_P (operands[2]))
    {
    {
      ops[0] = operands[1];
      ops[0] = operands[1];
    }
    }
  else
  else
    {
    {
      if (X_REG_P (operands[1]))
      if (X_REG_P (operands[1]))
        {
        {
          output_asm_insn (\"xgdx\", ops);
          output_asm_insn (\"xgdx\", ops);
        }
        }
      else if (!D_REG_P (operands[1]))
      else if (!D_REG_P (operands[1]))
        {
        {
          ops[0] = gen_rtx_REG (HImode, HARD_D_REGNUM);
          ops[0] = gen_rtx_REG (HImode, HARD_D_REGNUM);
          ops[1] = operands[1];
          ops[1] = operands[1];
          m68hc11_gen_movhi (insn, ops);
          m68hc11_gen_movhi (insn, ops);
        }
        }
      ops[0] = m68hc11_gen_lowpart (HImode, operands[2]);
      ops[0] = m68hc11_gen_lowpart (HImode, operands[2]);
      ops[1] = m68hc11_gen_highpart (HImode, operands[2]);
      ops[1] = m68hc11_gen_highpart (HImode, operands[2]);
    }
    }
  ops[2] = gen_label_rtx ();
  ops[2] = gen_label_rtx ();
  /* ldx preserves the carry, propagate it by incrementing X directly.  */
  /* ldx preserves the carry, propagate it by incrementing X directly.  */
  output_asm_insn (\"addd\\t%0\", ops);
  output_asm_insn (\"addd\\t%0\", ops);
  if (!X_REG_P (operands[2]))
  if (!X_REG_P (operands[2]))
    output_asm_insn (\"ldx\\t%1\", ops);
    output_asm_insn (\"ldx\\t%1\", ops);
  output_asm_insn (\"bcc\\t%l2\", ops);
  output_asm_insn (\"bcc\\t%l2\", ops);
  output_asm_insn (\"inx\", ops);
  output_asm_insn (\"inx\", ops);
  CC_STATUS_INIT;
  CC_STATUS_INIT;
  (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[2]));
  (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[2]));
  return \"\";
  return \"\";
}")
}")
(define_split /* "*addsi3_zero_extendqi" */
(define_split /* "*addsi3_zero_extendqi" */
  [(set (match_operand:SI 0 "register_operand" "")
  [(set (match_operand:SI 0 "register_operand" "")
        (plus:SI (zero_extend:SI
        (plus:SI (zero_extend:SI
                   (match_operand:QI 1 "general_operand" ""))
                   (match_operand:QI 1 "general_operand" ""))
                 (match_operand:SI 2 "memory_operand" "")))
                 (match_operand:SI 2 "memory_operand" "")))
   (clobber (match_scratch:HI 3 "=X,X"))]
   (clobber (match_scratch:HI 3 "=X,X"))]
  "reload_completed"
  "reload_completed"
  [(set (reg:HI D_REGNUM) (zero_extend:HI (match_dup 1)))
  [(set (reg:HI D_REGNUM) (zero_extend:HI (match_dup 1)))
   (parallel [(set (match_dup 0)
   (parallel [(set (match_dup 0)
                   (plus:SI (zero_extend:SI (reg:HI D_REGNUM)) (match_dup 2)))
                   (plus:SI (zero_extend:SI (reg:HI D_REGNUM)) (match_dup 2)))
              (clobber (match_dup 3))])]
              (clobber (match_dup 3))])]
  "")
  "")
(define_insn "*addsi3_zero_extendqi"
(define_insn "*addsi3_zero_extendqi"
  [(set (match_operand:SI 0 "register_operand" "=D,D")
  [(set (match_operand:SI 0 "register_operand" "=D,D")
        (plus:SI (zero_extend:SI
        (plus:SI (zero_extend:SI
                   (match_operand:QI 1 "general_operand" "dAmi,!dAmiu"))
                   (match_operand:QI 1 "general_operand" "dAmi,!dAmiu"))
                 (match_operand:SI 2 "general_operand" "miD,!muiD")))
                 (match_operand:SI 2 "general_operand" "miD,!muiD")))
   (clobber (match_scratch:HI 3 "=X,X"))]
   (clobber (match_scratch:HI 3 "=X,X"))]
  ""
  ""
  "*
  "*
{
{
  rtx ops[4];
  rtx ops[4];
  if (GET_CODE (operands[2]) == MEM)
  if (GET_CODE (operands[2]) == MEM)
    return \"#\";
    return \"#\";
  if (X_REG_P (operands[2]))
  if (X_REG_P (operands[2]))
    {
    {
      if (H_REG_P (operands[1]))
      if (H_REG_P (operands[1]))
        {
        {
          ops[0] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
          ops[0] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
          ops[1] = gen_rtx_REG (HImode, REGNO (operands[1]));
          ops[1] = gen_rtx_REG (HImode, REGNO (operands[1]));
          m68hc11_gen_movhi (insn, ops);
          m68hc11_gen_movhi (insn, ops);
        }
        }
      else
      else
        {
        {
          ops[0] = operands[1];
          ops[0] = operands[1];
        }
        }
      ops[1] = const0_rtx;
      ops[1] = const0_rtx;
    }
    }
  else
  else
    {
    {
      if (X_REG_P (operands[1]))
      if (X_REG_P (operands[1]))
        {
        {
          output_asm_insn (\"xgdx\", ops);
          output_asm_insn (\"xgdx\", ops);
        }
        }
      else if (!D_REG_P (operands[1]))
      else if (!D_REG_P (operands[1]))
        {
        {
          ops[0] = gen_rtx_REG (QImode, HARD_D_REGNUM);
          ops[0] = gen_rtx_REG (QImode, HARD_D_REGNUM);
          ops[1] = operands[1];
          ops[1] = operands[1];
          m68hc11_gen_movqi (insn, ops);
          m68hc11_gen_movqi (insn, ops);
        }
        }
      ops[0] = m68hc11_gen_lowpart (HImode, operands[2]);
      ops[0] = m68hc11_gen_lowpart (HImode, operands[2]);
      ops[1] = ops[0];
      ops[1] = ops[0];
      ops[2] = m68hc11_gen_highpart (HImode, operands[2]);
      ops[2] = m68hc11_gen_highpart (HImode, operands[2]);
      output_asm_insn (\"clra\", ops);
      output_asm_insn (\"clra\", ops);
    }
    }
  /* ldx preserves the carry, propagate it by incrementing X directly.  */
  /* ldx preserves the carry, propagate it by incrementing X directly.  */
  output_asm_insn (\"addb\\t%b0\", ops);
  output_asm_insn (\"addb\\t%b0\", ops);
  output_asm_insn (\"adca\\t%h1\", ops);
  output_asm_insn (\"adca\\t%h1\", ops);
  if (!X_REG_P (operands[2]))
  if (!X_REG_P (operands[2]))
    output_asm_insn (\"ldx\\t%2\", ops);
    output_asm_insn (\"ldx\\t%2\", ops);
  /* If the above adca was adding some constant, we don't need to propagate
  /* If the above adca was adding some constant, we don't need to propagate
     the carry unless the constant was 0xff.  */
     the carry unless the constant was 0xff.  */
  if (X_REG_P (operands[2])
  if (X_REG_P (operands[2])
      || GET_CODE (ops[1]) != CONST_INT
      || GET_CODE (ops[1]) != CONST_INT
      || ((INTVAL (ops[1]) & 0x0ff00) == 0x0ff00))
      || ((INTVAL (ops[1]) & 0x0ff00) == 0x0ff00))
    {
    {
      ops[3] = gen_label_rtx ();
      ops[3] = gen_label_rtx ();
      output_asm_insn (\"bcc\\t%l3\", ops);
      output_asm_insn (\"bcc\\t%l3\", ops);
      output_asm_insn (\"inx\", ops);
      output_asm_insn (\"inx\", ops);
      (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
      (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
                                 CODE_LABEL_NUMBER (ops[3]));
                                 CODE_LABEL_NUMBER (ops[3]));
    }
    }
  CC_STATUS_INIT;
  CC_STATUS_INIT;
  return \"\";
  return \"\";
}")
}")
(define_insn "*addsi3"
(define_insn "*addsi3"
  [(set (match_operand:SI 0 "non_push_operand" "=o,D,!u,?D,D")
  [(set (match_operand:SI 0 "non_push_operand" "=o,D,!u,?D,D")
        (plus:SI (match_operand:SI 1 "non_push_operand" "%0,0,0,0,0")
        (plus:SI (match_operand:SI 1 "non_push_operand" "%0,0,0,0,0")
                 (match_operand:SI 2 "general_operand" "ML,i,ML,?D,?oiu")))
                 (match_operand:SI 2 "general_operand" "ML,i,ML,?D,?oiu")))
   (clobber (match_scratch:HI 3 "=d,X,d,X,X"))]
   (clobber (match_scratch:HI 3 "=d,X,d,X,X"))]
  ""
  ""
  "*
  "*
{
{
  rtx   ops[3];
  rtx   ops[3];
  const char* add_insn;
  const char* add_insn;
  const char* inc_insn;
  const char* inc_insn;
  const char* incb_mem;
  const char* incb_mem;
  const char* inch_mem;
  const char* inch_mem;
  HOST_WIDE_INT val;
  HOST_WIDE_INT val;
  if (which_alternative > 2)
  if (which_alternative > 2)
    {
    {
      return \"#\";
      return \"#\";
    }
    }
  val = INTVAL (operands[2]);
  val = INTVAL (operands[2]);
  if ((val & 0x0ffffL) == 0)
  if ((val & 0x0ffffL) == 0)
    {
    {
      if (!H_REG_P (operands[0]))
      if (!H_REG_P (operands[0]))
        {
        {
          ops[0] = m68hc11_gen_highpart (HImode, operands[0]);
          ops[0] = m68hc11_gen_highpart (HImode, operands[0]);
          ops[1] = m68hc11_gen_highpart (HImode, operands[2]);
          ops[1] = m68hc11_gen_highpart (HImode, operands[2]);
          output_asm_insn (\"ldd\\t%0\", ops);
          output_asm_insn (\"ldd\\t%0\", ops);
          output_asm_insn (\"addd\\t%1\", ops);
          output_asm_insn (\"addd\\t%1\", ops);
          output_asm_insn (\"std\\t%0\", ops);
          output_asm_insn (\"std\\t%0\", ops);
          return \"\";
          return \"\";
        }
        }
      else if (val == 1)
      else if (val == 1)
        {
        {
          return \"inx\";
          return \"inx\";
        }
        }
      else
      else
        {
        {
          return \"#\";
          return \"#\";
        }
        }
    }
    }
  if ((val & 0xffff0000L) != 0 && (val & 0xffff0000L) != 0xffff0000L)
  if ((val & 0xffff0000L) != 0 && (val & 0xffff0000L) != 0xffff0000L)
    {
    {
      return \"#\";
      return \"#\";
    }
    }
  if (val >= 0)
  if (val >= 0)
    {
    {
      ops[1]   = operands[2];
      ops[1]   = operands[2];
      add_insn = \"addd\\t%1\";
      add_insn = \"addd\\t%1\";
      inc_insn = \"inx\\t\";
      inc_insn = \"inx\\t\";
      incb_mem  = \"inc\\t%b1\";
      incb_mem  = \"inc\\t%b1\";
      inch_mem  = \"inc\\t%h1\";
      inch_mem  = \"inc\\t%h1\";
    }
    }
  else
  else
    {
    {
      ops[1] = GEN_INT (- val);
      ops[1] = GEN_INT (- val);
      add_insn = \"subd\\t%1\";
      add_insn = \"subd\\t%1\";
      inc_insn = \"dex\";
      inc_insn = \"dex\";
      incb_mem  = \"dec\\t%b1\";
      incb_mem  = \"dec\\t%b1\";
      inch_mem  = \"dec\\t%h1\";
      inch_mem  = \"dec\\t%h1\";
    }
    }
  ops[2] = gen_label_rtx ();
  ops[2] = gen_label_rtx ();
  if (!H_REG_P (operands[0]))
  if (!H_REG_P (operands[0]))
    {
    {
      ops[0] = m68hc11_gen_lowpart (HImode, operands[0]);
      ops[0] = m68hc11_gen_lowpart (HImode, operands[0]);
      output_asm_insn (\"ldd\\t%0\", ops);
      output_asm_insn (\"ldd\\t%0\", ops);
    }
    }
  output_asm_insn (add_insn, ops);
  output_asm_insn (add_insn, ops);
  if (!H_REG_P (operands[0]))
  if (!H_REG_P (operands[0]))
    {
    {
      output_asm_insn (\"std\\t%0\", ops);
      output_asm_insn (\"std\\t%0\", ops);
    }
    }
  output_asm_insn (\"bcc\\t%l2\", ops);
  output_asm_insn (\"bcc\\t%l2\", ops);
  if (H_REG_P (operands[0]))
  if (H_REG_P (operands[0]))
    {
    {
      output_asm_insn (inc_insn, ops);
      output_asm_insn (inc_insn, ops);
    }
    }
  else
  else
    {
    {
      ops[0] = m68hc11_gen_highpart (HImode, operands[0]);
      ops[0] = m68hc11_gen_highpart (HImode, operands[0]);
      ops[1] = ops[0];
      ops[1] = ops[0];
      if (INTVAL (operands[2]) < 0)
      if (INTVAL (operands[2]) < 0)
        {
        {
          output_asm_insn (\"ldd\\t%1\", ops);
          output_asm_insn (\"ldd\\t%1\", ops);
          output_asm_insn (\"addd\\t#-1\", ops);
          output_asm_insn (\"addd\\t#-1\", ops);
          output_asm_insn (\"std\\t%1\", ops);
          output_asm_insn (\"std\\t%1\", ops);
        }
        }
      else
      else
        {
        {
          output_asm_insn (incb_mem, ops);
          output_asm_insn (incb_mem, ops);
          output_asm_insn (\"bne\\t%l2\", ops);
          output_asm_insn (\"bne\\t%l2\", ops);
          output_asm_insn (inch_mem, ops);
          output_asm_insn (inch_mem, ops);
        }
        }
    }
    }
  (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[2]));
  (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[2]));
  CC_STATUS_INIT;
  CC_STATUS_INIT;
  return \"\";
  return \"\";
}")
}")
(define_split
(define_split
  [(set (match_operand:SI 0 "register_operand" "")
  [(set (match_operand:SI 0 "register_operand" "")
        (plus:SI (match_operand:SI 1 "register_operand" "")
        (plus:SI (match_operand:SI 1 "register_operand" "")
                 (match_operand:SI 2 "const_int_operand" "")))
                 (match_operand:SI 2 "const_int_operand" "")))
   (clobber (match_scratch:HI 3 ""))]
   (clobber (match_scratch:HI 3 ""))]
  "reload_completed && z_replacement_completed == 2
  "reload_completed && z_replacement_completed == 2
   && ((INTVAL (operands[2]) & 0x0FFFF) == 0)"
   && ((INTVAL (operands[2]) & 0x0FFFF) == 0)"
  [(set (match_dup 5) (match_dup 6))
  [(set (match_dup 5) (match_dup 6))
   (set (reg:HI 0) (plus:HI (reg:HI 0) (match_dup 4)))
   (set (reg:HI 0) (plus:HI (reg:HI 0) (match_dup 4)))
   (set (match_dup 6) (match_dup 5))]
   (set (match_dup 6) (match_dup 5))]
  "operands[4] = m68hc11_gen_highpart (HImode, operands[2]);
  "operands[4] = m68hc11_gen_highpart (HImode, operands[2]);
   if (X_REG_P (operands[0]))
   if (X_REG_P (operands[0]))
     {
     {
       operands[5] = operands[6] = gen_rtx_REG (HImode, HARD_D_REGNUM);
       operands[5] = operands[6] = gen_rtx_REG (HImode, HARD_D_REGNUM);
     }
     }
   else
   else
     {
     {
       operands[6] = m68hc11_gen_highpart (HImode, operands[1]);
       operands[6] = m68hc11_gen_highpart (HImode, operands[1]);
       operands[5] = operands[3];
       operands[5] = operands[3];
     }
     }
   ")
   ")
(define_split
(define_split
  [(set (match_operand:SI 0 "register_operand" "")
  [(set (match_operand:SI 0 "register_operand" "")
        (plus:SI (match_operand:SI 1 "register_operand" "")
        (plus:SI (match_operand:SI 1 "register_operand" "")
                 (match_operand:SI 2 "general_operand" "")))
                 (match_operand:SI 2 "general_operand" "")))
   (clobber (match_scratch:HI 3 "=X"))]
   (clobber (match_scratch:HI 3 "=X"))]
  "reload_completed && z_replacement_completed == 2
  "reload_completed && z_replacement_completed == 2
   && (GET_CODE (operands[2]) != CONST_INT ||
   && (GET_CODE (operands[2]) != CONST_INT ||
        (!(INTVAL (operands[2]) >= -65536 && INTVAL (operands[2]) <= 65535)))"
        (!(INTVAL (operands[2]) >= -65536 && INTVAL (operands[2]) <= 65535)))"
  [(set (reg:HI D_REGNUM) (plus:HI (reg:HI D_REGNUM) (match_dup 3)))
  [(set (reg:HI D_REGNUM) (plus:HI (reg:HI D_REGNUM) (match_dup 3)))
   (parallel [(set (reg:HI D_REGNUM) (reg:HI X_REGNUM))
   (parallel [(set (reg:HI D_REGNUM) (reg:HI X_REGNUM))
              (set (reg:HI X_REGNUM) (reg:HI D_REGNUM))])
              (set (reg:HI X_REGNUM) (reg:HI D_REGNUM))])
   (set (reg:QI B_REGNUM) (plus:QI (plus:QI (reg:QI CC_REGNUM) (reg:QI B_REGNUM)) (match_dup 4)))
   (set (reg:QI B_REGNUM) (plus:QI (plus:QI (reg:QI CC_REGNUM) (reg:QI B_REGNUM)) (match_dup 4)))
   (set (reg:QI A_REGNUM) (plus:QI (plus:QI (reg:QI CC_REGNUM) (reg:QI A_REGNUM)) (match_dup 5)))
   (set (reg:QI A_REGNUM) (plus:QI (plus:QI (reg:QI CC_REGNUM) (reg:QI A_REGNUM)) (match_dup 5)))
   (parallel [(set (reg:HI D_REGNUM) (reg:HI X_REGNUM))
   (parallel [(set (reg:HI D_REGNUM) (reg:HI X_REGNUM))
              (set (reg:HI X_REGNUM) (reg:HI D_REGNUM))])]
              (set (reg:HI X_REGNUM) (reg:HI D_REGNUM))])]
  "operands[3] = m68hc11_gen_lowpart (HImode, operands[2]);
  "operands[3] = m68hc11_gen_lowpart (HImode, operands[2]);
   operands[4] = m68hc11_gen_highpart (HImode, operands[2]);
   operands[4] = m68hc11_gen_highpart (HImode, operands[2]);
   operands[5] = m68hc11_gen_highpart (QImode, operands[4]);
   operands[5] = m68hc11_gen_highpart (QImode, operands[4]);
   operands[4] = m68hc11_gen_lowpart (QImode, operands[4]);")
   operands[4] = m68hc11_gen_lowpart (QImode, operands[4]);")
;;
;;
;; Instruction generated to propagate the carry of a 16-bit add
;; Instruction generated to propagate the carry of a 16-bit add
;; to the upper 16-bit part (in register X).
;; to the upper 16-bit part (in register X).
;;
;;
(define_insn "*addsi_carry"
(define_insn "*addsi_carry"
  [(set (match_operand:HI 0 "register_operand" "=x")
  [(set (match_operand:HI 0 "register_operand" "=x")
           (plus:HI (plus:HI (match_operand:HI 1 "register_operand" "0")
           (plus:HI (plus:HI (match_operand:HI 1 "register_operand" "0")
                             (const_int 0))
                             (const_int 0))
                    (reg:HI CC_REGNUM)))]
                    (reg:HI CC_REGNUM)))]
  ""
  ""
  "*
  "*
{
{
  rtx ops[2];
  rtx ops[2];
  ops[0] = gen_label_rtx ();
  ops[0] = gen_label_rtx ();
  output_asm_insn (\"bcc\\t%l0\", ops);
  output_asm_insn (\"bcc\\t%l0\", ops);
  output_asm_insn (\"in%0\", operands);
  output_asm_insn (\"in%0\", operands);
  (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0]));
  (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0]));
  CC_STATUS_INIT;
  CC_STATUS_INIT;
  return \"\";
  return \"\";
}")
}")
;;
;;
;; - 16-bit Add.
;; - 16-bit Add.
;;
;;
(define_expand "addhi3"
(define_expand "addhi3"
  [(set (match_operand:HI 0 "register_operand" "")
  [(set (match_operand:HI 0 "register_operand" "")
           (plus:HI (match_operand:HI 1 "register_operand" "")
           (plus:HI (match_operand:HI 1 "register_operand" "")
                    (match_operand:HI 2 "general_operand" "")))]
                    (match_operand:HI 2 "general_operand" "")))]
  ""
  ""
  "
  "
{
{
  if (TARGET_M6811 && SP_REG_P (operands[0]))
  if (TARGET_M6811 && SP_REG_P (operands[0]))
    {
    {
      emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2,
      emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2,
                         gen_rtx_SET (VOIDmode,
                         gen_rtx_SET (VOIDmode,
                                  operand0,
                                  operand0,
                                  gen_rtx_PLUS (HImode,
                                  gen_rtx_PLUS (HImode,
                                           operand1, operand2)),
                                           operand1, operand2)),
                        gen_rtx_CLOBBER (VOIDmode,
                        gen_rtx_CLOBBER (VOIDmode,
                                gen_rtx_SCRATCH (HImode)))));
                                gen_rtx_SCRATCH (HImode)))));
      DONE;
      DONE;
    }
    }
}")
}")
(define_insn "*addhi3_68hc12"
(define_insn "*addhi3_68hc12"
  [(set (match_operand:HI 0 "register_operand" "=d*A,d,xy*A*w,xy*A*w,xy*A")
  [(set (match_operand:HI 0 "register_operand" "=d*A,d,xy*A*w,xy*A*w,xy*A")
        (plus:HI (match_operand:HI 1 "register_operand" "%0,0,0,xy*Aw,0")
        (plus:HI (match_operand:HI 1 "register_operand" "%0,0,0,xy*Aw,0")
                 (match_operand:HI 2 "general_operand" "i,m*A*wu,id,id,!mu*A")))]
                 (match_operand:HI 2 "general_operand" "i,m*A*wu,id,id,!mu*A")))]
  "TARGET_M6812"
  "TARGET_M6812"
  "*
  "*
{
{
  int val;
  int val;
  const char* insn_code;
  const char* insn_code;
  if (which_alternative >= 4)
  if (which_alternative >= 4)
    {
    {
      if (A_REG_P (operands[2]))
      if (A_REG_P (operands[2]))
        {
        {
          CC_STATUS_INIT;
          CC_STATUS_INIT;
          output_asm_insn (\"xgd%2\", operands);
          output_asm_insn (\"xgd%2\", operands);
          output_asm_insn (\"lea%0 d,%0\", operands);
          output_asm_insn (\"lea%0 d,%0\", operands);
          return \"xgd%2\";
          return \"xgd%2\";
        }
        }
      return \"#\";
      return \"#\";
    }
    }
  if (D_REG_P (operands[0]))
  if (D_REG_P (operands[0]))
    {
    {
      if (X_REG_P (operands[2]))
      if (X_REG_P (operands[2]))
        {
        {
          m68hc11_notice_keep_cc (operands[0]);
          m68hc11_notice_keep_cc (operands[0]);
          output_asm_insn (\"xgdx\", operands);
          output_asm_insn (\"xgdx\", operands);
          output_asm_insn (\"leax\\td,%2\", operands);
          output_asm_insn (\"leax\\td,%2\", operands);
          return \"xgdx\";
          return \"xgdx\";
        }
        }
      else if (Y_REG_P (operands[2]))
      else if (Y_REG_P (operands[2]))
        {
        {
          m68hc11_notice_keep_cc (operands[0]);
          m68hc11_notice_keep_cc (operands[0]);
          output_asm_insn (\"xgdy\", operands);
          output_asm_insn (\"xgdy\", operands);
          output_asm_insn (\"leay\\td,%2\", operands);
          output_asm_insn (\"leay\\td,%2\", operands);
          return \"xgdy\";
          return \"xgdy\";
        }
        }
      else if (SP_REG_P (operands[2]))
      else if (SP_REG_P (operands[2]))
        {
        {
          output_asm_insn (\"sts\\t%t0\", operands);
          output_asm_insn (\"sts\\t%t0\", operands);
          return \"addd\\t%t0\";
          return \"addd\\t%t0\";
        }
        }
      return \"addd\\t%2\";
      return \"addd\\t%2\";
    }
    }
  if (GET_CODE (operands[2]) == CONST_INT)
  if (GET_CODE (operands[2]) == CONST_INT)
    val = INTVAL (operands[2]);
    val = INTVAL (operands[2]);
  else
  else
    val = 1000;
    val = 1000;
  if ((val != -1 && val != 1) || !rtx_equal_p (operands[0], operands[1]))
  if ((val != -1 && val != 1) || !rtx_equal_p (operands[0], operands[1]))
    {
    {
      m68hc11_notice_keep_cc (operands[0]);
      m68hc11_notice_keep_cc (operands[0]);
      switch (REGNO (operands[0]))
      switch (REGNO (operands[0]))
        {
        {
        case HARD_X_REGNUM:
        case HARD_X_REGNUM:
          return \"leax\\t%i2,%1\";
          return \"leax\\t%i2,%1\";
        case HARD_Y_REGNUM:
        case HARD_Y_REGNUM:
          return \"leay\\t%i2,%1\";
          return \"leay\\t%i2,%1\";
        case HARD_SP_REGNUM:
        case HARD_SP_REGNUM:
          return \"leas\\t%i2,%1\";
          return \"leas\\t%i2,%1\";
        default:
        default:
          fatal_insn (\"Invalid operands in the instruction\", insn);
          fatal_insn (\"Invalid operands in the instruction\", insn);
        }
        }
    }
    }
  if (val > 0)
  if (val > 0)
    {
    {
      insn_code = X_REG_P (operands[0]) ? \"inx\"
      insn_code = X_REG_P (operands[0]) ? \"inx\"
                : Y_REG_P (operands[0]) ? \"iny\" : \"ins\";
                : Y_REG_P (operands[0]) ? \"iny\" : \"ins\";
    }
    }
  else
  else
    {
    {
      val  = -val;
      val  = -val;
      insn_code = X_REG_P (operands[0]) ? \"dex\"
      insn_code = X_REG_P (operands[0]) ? \"dex\"
                : Y_REG_P (operands[0]) ? \"dey\" : \"des\";
                : Y_REG_P (operands[0]) ? \"dey\" : \"des\";
    }
    }
  /* For X and Y increment, the flags are not complete. Only the Z flag
  /* For X and Y increment, the flags are not complete. Only the Z flag
     is updated. For SP increment, flags are not changed.  */
     is updated. For SP increment, flags are not changed.  */
  if (SP_REG_P (operands[0]))
  if (SP_REG_P (operands[0]))
    {
    {
      cc_status = cc_prev_status;
      cc_status = cc_prev_status;
      if (INTVAL (operands[2]) < 0)
      if (INTVAL (operands[2]) < 0)
        {
        {
          while (val > 2)
          while (val > 2)
            {
            {
              output_asm_insn (\"pshx\", operands);
              output_asm_insn (\"pshx\", operands);
              val -= 2;
              val -= 2;
            }
            }
          if (val == 0)
          if (val == 0)
            return \"\";
            return \"\";
        }
        }
    }
    }
  else
  else
    {
    {
      CC_STATUS_INIT;
      CC_STATUS_INIT;
    }
    }
  while (val)
  while (val)
    {
    {
      output_asm_insn (insn_code, operands);
      output_asm_insn (insn_code, operands);
      val--;
      val--;
    }
    }
  return \"\";
  return \"\";
}")
}")
;;
;;
;; Specific pattern to add to the stack pointer.
;; Specific pattern to add to the stack pointer.
;; We also take care of the clobbering of the IY register.
;; We also take care of the clobbering of the IY register.
;;
;;
(define_insn "addhi_sp"
(define_insn "addhi_sp"
  [(set (match_operand:HI 0 "stack_register_operand" "=w,w,w,w")
  [(set (match_operand:HI 0 "stack_register_operand" "=w,w,w,w")
          (plus:HI (match_operand:HI 1 "stack_register_operand" "%0,0,0,0")
          (plus:HI (match_operand:HI 1 "stack_register_operand" "%0,0,0,0")
                   (match_operand:HI 2 "general_operand" "P,im,u,im")))
                   (match_operand:HI 2 "general_operand" "P,im,u,im")))
   (clobber (match_scratch:HI 3 "=X,&y,&y,!&x"))]
   (clobber (match_scratch:HI 3 "=X,&y,&y,!&x"))]
  "!TARGET_M6812"
  "!TARGET_M6812"
  "*
  "*
{
{
  HOST_WIDE_INT val;
  HOST_WIDE_INT val;
  if (optimize && Y_REG_P (operands[3])
  if (optimize && Y_REG_P (operands[3])
      && dead_register_here (insn, gen_rtx_REG (HImode, HARD_X_REGNUM)))
      && dead_register_here (insn, gen_rtx_REG (HImode, HARD_X_REGNUM)))
    operands[3] = gen_rtx_REG (HImode, HARD_X_REGNUM);
    operands[3] = gen_rtx_REG (HImode, HARD_X_REGNUM);
  if (GET_CODE (operands[2]) == CONST_INT
  if (GET_CODE (operands[2]) == CONST_INT
      && (val = INTVAL (operands[2])) != 0
      && (val = INTVAL (operands[2])) != 0
      && (CONST_OK_FOR_LETTER_P (val, 'P')
      && (CONST_OK_FOR_LETTER_P (val, 'P')
          || (val > 0 && val <= 8)))
          || (val > 0 && val <= 8)))
    {
    {
      while (val > 1 || val < -1)
      while (val > 1 || val < -1)
        {
        {
          if (val > 0)
          if (val > 0)
            {
            {
              if (!H_REG_P (operands[3]))
              if (!H_REG_P (operands[3]))
                break;
                break;
              output_asm_insn (\"pul%3\", operands);
              output_asm_insn (\"pul%3\", operands);
              val -= 2;
              val -= 2;
            }
            }
          else
          else
            {
            {
              output_asm_insn (\"pshx\", operands);
              output_asm_insn (\"pshx\", operands);
              val += 2;
              val += 2;
            }
            }
        }
        }
      while (val != 0)
      while (val != 0)
        {
        {
          if (val > 0)
          if (val > 0)
            {
            {
              output_asm_insn (\"ins\", operands);
              output_asm_insn (\"ins\", operands);
              val--;
              val--;
            }
            }
          else
          else
            {
            {
              output_asm_insn (\"des\", operands);
              output_asm_insn (\"des\", operands);
              val++;
              val++;
            }
            }
        }
        }
      cc_status = cc_prev_status;
      cc_status = cc_prev_status;
      return \"\";
      return \"\";
    }
    }
  /* Need to transfer to SP to X/Y and then to D register.
  /* Need to transfer to SP to X/Y and then to D register.
     Register X/Y is lost, this is specified by the (clobber) statement.  */
     Register X/Y is lost, this is specified by the (clobber) statement.  */
  output_asm_insn (\"ts%3\", operands);
  output_asm_insn (\"ts%3\", operands);
  if (GET_CODE (operands[2]) == CONST_INT
  if (GET_CODE (operands[2]) == CONST_INT
      && ((val = INTVAL (operands[2])) >= 0 && val < 0x100)
      && ((val = INTVAL (operands[2])) >= 0 && val < 0x100)
      && dead_register_here (insn, gen_rtx_REG (HImode, HARD_D_REGNUM)))
      && dead_register_here (insn, gen_rtx_REG (HImode, HARD_D_REGNUM)))
    {
    {
      output_asm_insn (\"ldab\\t%2\", operands);
      output_asm_insn (\"ldab\\t%2\", operands);
      output_asm_insn (\"ab%3\", operands);
      output_asm_insn (\"ab%3\", operands);
      CC_STATUS_INIT;
      CC_STATUS_INIT;
    }
    }
  else
  else
    {
    {
      output_asm_insn (\"xgd%3\", operands);
      output_asm_insn (\"xgd%3\", operands);
      output_asm_insn (\"addd\\t%2\", operands);
      output_asm_insn (\"addd\\t%2\", operands);
      output_asm_insn (\"xgd%3\", operands);
      output_asm_insn (\"xgd%3\", operands);
    }
    }
   /* The status flags correspond to the addd.  xgdy and tys do not
   /* The status flags correspond to the addd.  xgdy and tys do not
      modify the flags.  */
      modify the flags.  */
  return \"t%3s\";
  return \"t%3s\";
}")
}")
(define_insn "*addhi3"
(define_insn "*addhi3"
  [(set (match_operand:HI 0 "hard_reg_operand" "=A,dA,d,!A,d*A,d,!d*A")
  [(set (match_operand:HI 0 "hard_reg_operand" "=A,dA,d,!A,d*A,d,!d*A")
        (plus:HI (match_operand:HI 1 "general_operand" "%0,0,0,0,0,0,0")
        (plus:HI (match_operand:HI 1 "general_operand" "%0,0,0,0,0,0,0")
                 (match_operand:HI 2 "general_operand" "N,I,i,I,mi*A*d,*u,!u*d*w")))]
                 (match_operand:HI 2 "general_operand" "N,I,i,I,mi*A*d,*u,!u*d*w")))]
  "TARGET_M6811"
  "TARGET_M6811"
  "*
  "*
{
{
  const char* insn_code;
  const char* insn_code;
  int val;
  int val;
  if (D_REG_P (operands[0]) && SP_REG_P (operands[2]))
  if (D_REG_P (operands[0]) && SP_REG_P (operands[2]))
    {
    {
      output_asm_insn (\"sts\\t%t0\", operands);
      output_asm_insn (\"sts\\t%t0\", operands);
      output_asm_insn (\"addd\\t%t0\", operands);
      output_asm_insn (\"addd\\t%t0\", operands);
      return \"addd\\t#1\";
      return \"addd\\t#1\";
    }
    }
  if (GET_CODE (operands[2]) != CONST_INT)
  if (GET_CODE (operands[2]) != CONST_INT)
    {
    {
      /* Adding to an address register or with another/same register
      /* Adding to an address register or with another/same register
         is not possible. This must be replaced.  */
         is not possible. This must be replaced.  */
      if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
      if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
        return \"#\";
        return \"#\";
      return \"addd\\t%2\";
      return \"addd\\t%2\";
    }
    }
  val = INTVAL (operands[2]);
  val = INTVAL (operands[2]);
  if (!SP_REG_P (operands[0]))
  if (!SP_REG_P (operands[0]))
    {
    {
      if (D_REG_P (operands[0]))
      if (D_REG_P (operands[0]))
        {
        {
          if ((val & 0x0ff) == 0 && !next_insn_test_reg (insn, operands[0]))
          if ((val & 0x0ff) == 0 && !next_insn_test_reg (insn, operands[0]))
            {
            {
              CC_STATUS_INIT;
              CC_STATUS_INIT;
              return \"adda\\t%h2\";
              return \"adda\\t%h2\";
            }
            }
          else
          else
            {
            {
              return \"addd\\t%2\";
              return \"addd\\t%2\";
            }
            }
        }
        }
      else if (GET_CODE (operands[2]) != CONST_INT
      else if (GET_CODE (operands[2]) != CONST_INT
               || INTVAL (operands[2]) < -4
               || INTVAL (operands[2]) < -4
               || INTVAL (operands[2]) > 4)
               || INTVAL (operands[2]) > 4)
        return \"#\";
        return \"#\";
    }
    }
  if (val > 0)
  if (val > 0)
    {
    {
      insn_code = X_REG_P (operands[0]) ? \"inx\"
      insn_code = X_REG_P (operands[0]) ? \"inx\"
                    : Y_REG_P (operands[0]) ? \"iny\" : \"ins\";
                    : Y_REG_P (operands[0]) ? \"iny\" : \"ins\";
    }
    }
  else
  else
    {
    {
      val  = -val;
      val  = -val;
      insn_code = X_REG_P (operands[0]) ? \"dex\"
      insn_code = X_REG_P (operands[0]) ? \"dex\"
                    : Y_REG_P (operands[0]) ? \"dey\" : \"des\";
                    : Y_REG_P (operands[0]) ? \"dey\" : \"des\";
    }
    }
  /* For X and Y increment, the flags are not complete.  Only the Z flag
  /* For X and Y increment, the flags are not complete.  Only the Z flag
     is updated.  For SP increment, flags are not changed.  */
     is updated.  For SP increment, flags are not changed.  */
  if (SP_REG_P (operands[0]))
  if (SP_REG_P (operands[0]))
    {
    {
      cc_status = cc_prev_status;
      cc_status = cc_prev_status;
      if (INTVAL (operands[2]) < 0)
      if (INTVAL (operands[2]) < 0)
        {
        {
          while (val >= 2)
          while (val >= 2)
            {
            {
              output_asm_insn (\"pshx\", operands);
              output_asm_insn (\"pshx\", operands);
              val -= 2;
              val -= 2;
            }
            }
        }
        }
      else if (optimize && dead_register_here (insn, ix_reg))
      else if (optimize && dead_register_here (insn, ix_reg))
        {
        {
          while (val >= 2)
          while (val >= 2)
            {
            {
              output_asm_insn (\"pulx\", operands);
              output_asm_insn (\"pulx\", operands);
              val -= 2;
              val -= 2;
            }
            }
        }
        }
    }
    }
  else
  else
    {
    {
      CC_STATUS_INIT;
      CC_STATUS_INIT;
    }
    }
  while (val)
  while (val)
    {
    {
      output_asm_insn (insn_code, operands);
      output_asm_insn (insn_code, operands);
      val--;
      val--;
    }
    }
  return \"\";
  return \"\";
}")
}")
(define_insn "*addhi3_zext"
(define_insn "*addhi3_zext"
  [(set (match_operand:HI 0 "hard_reg_operand" "=A,d")
  [(set (match_operand:HI 0 "hard_reg_operand" "=A,d")
        (plus:HI (zero_extend:HI
        (plus:HI (zero_extend:HI
                     (match_operand:QI 1 "nonimmediate_operand" "d,um*A"))
                     (match_operand:QI 1 "nonimmediate_operand" "d,um*A"))
                 (match_operand:HI 2 "general_operand" "0,0")))]
                 (match_operand:HI 2 "general_operand" "0,0")))]
  ""
  ""
  "*
  "*
{
{
  CC_STATUS_INIT;
  CC_STATUS_INIT;
  if (A_REG_P (operands[0]))
  if (A_REG_P (operands[0]))
    return \"ab%0\";
    return \"ab%0\";
  else if (A_REG_P (operands[1]))
  else if (A_REG_P (operands[1]))
    return \"st%1\\t%t0\\n\\taddb\\t%T0\\n\\tadca\\t#0\";
    return \"st%1\\t%t0\\n\\taddb\\t%T0\\n\\tadca\\t#0\";
  else
  else
    return \"addb\\t%b1\\n\\tadca\\t#0\";
    return \"addb\\t%b1\\n\\tadca\\t#0\";
}")
}")
;;
;;
;; Translate d = d + d into d = << 1
;; Translate d = d + d into d = << 1
;; We have to do this because adding a register to itself is not possible.
;; We have to do this because adding a register to itself is not possible.
;; ??? It's not clear whether this is really necessary.
;; ??? It's not clear whether this is really necessary.
;;
;;
(define_split
(define_split
  [(set (match_operand:QI 0 "hard_reg_operand" "")
  [(set (match_operand:QI 0 "hard_reg_operand" "")
        (plus:QI (match_dup 0)
        (plus:QI (match_dup 0)
                 (match_dup 0)))]
                 (match_dup 0)))]
  "0 && reload_completed"
  "0 && reload_completed"
  [(set (match_dup 0) (ashift:QI (match_dup 0) (const_int 1)))]
  [(set (match_dup 0) (ashift:QI (match_dup 0) (const_int 1)))]
  "")
  "")
(define_insn "addqi3"
(define_insn "addqi3"
  [(set (match_operand:QI 0 "nonimmediate_operand" "=!d*rm,dq,!*A")
  [(set (match_operand:QI 0 "nonimmediate_operand" "=!d*rm,dq,!*A")
        (plus:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,0")
        (plus:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,0")
                 (match_operand:QI 2 "general_operand" "N,ium*A*d,ium*A*d")))]
                 (match_operand:QI 2 "general_operand" "N,ium*A*d,ium*A*d")))]
  ""
  ""
  "*
  "*
{
{
  if (GET_CODE (operands[2]) == CONST_INT)
  if (GET_CODE (operands[2]) == CONST_INT)
    {
    {
      if (INTVAL (operands[2]) == 1)
      if (INTVAL (operands[2]) == 1)
        {
        {
          if (DA_REG_P (operands[0]))
          if (DA_REG_P (operands[0]))
            {
            {
              return \"inca\";
              return \"inca\";
            }
            }
          else if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
          else if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
           {
           {
             return \"incb\";
             return \"incb\";
           }
           }
          else if (A_REG_P (operands[0]))
          else if (A_REG_P (operands[0]))
           {
           {
             /* This applies on the 16-bit register.  This should be ok since
             /* This applies on the 16-bit register.  This should be ok since
                this is not a strict_low_part increment.  */
                this is not a strict_low_part increment.  */
             return \"in%0\";
             return \"in%0\";
           }
           }
          else
          else
           {
           {
             return \"inc\\t%b0\";
             return \"inc\\t%b0\";
           }
           }
        }
        }
      else if (INTVAL (operands[2]) == -1)
      else if (INTVAL (operands[2]) == -1)
        {
        {
          if (DA_REG_P (operands[0]))
          if (DA_REG_P (operands[0]))
            {
            {
              return \"deca\";
              return \"deca\";
            }
            }
          else if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
          else if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
            {
            {
              return \"decb\";
              return \"decb\";
            }
            }
          else if (A_REG_P (operands[0]))
          else if (A_REG_P (operands[0]))
            {
            {
             /* This applies on the 16-bit register.  This should be ok since
             /* This applies on the 16-bit register.  This should be ok since
                this is not a strict_low_part decrement.  */
                this is not a strict_low_part decrement.  */
              return \"de%0\";
              return \"de%0\";
            }
            }
          else
          else
            {
            {
              return \"dec\\t%b0\";
              return \"dec\\t%b0\";
            }
            }
        }
        }
    }
    }
  if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
  if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
    return \"#\";
    return \"#\";
  else if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
  else if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
    return \"addb\\t%b2\";
    return \"addb\\t%b2\";
  else
  else
    return \"adda\\t%b2\";
    return \"adda\\t%b2\";
}")
}")
;;
;;
;; add with carry is used for 32-bit add.
;; add with carry is used for 32-bit add.
;;
;;
(define_insn "*adcq"
(define_insn "*adcq"
  [(set (match_operand:QI 0 "register_operand" "=q")
  [(set (match_operand:QI 0 "register_operand" "=q")
        (plus:QI (plus:QI (reg:QI CC_REGNUM)
        (plus:QI (plus:QI (reg:QI CC_REGNUM)
                          (match_operand:QI 1 "register_operand" "%0"))
                          (match_operand:QI 1 "register_operand" "%0"))
                 (match_operand:QI 2 "general_operand" "ium")))]
                 (match_operand:QI 2 "general_operand" "ium")))]
  ""
  ""
  "adc%0\\t%b2")
  "adc%0\\t%b2")
;;--------------------------------------------------------------------
;;--------------------------------------------------------------------
;;- Subtract instructions.
;;- Subtract instructions.
;;--------------------------------------------------------------------
;;--------------------------------------------------------------------
(define_expand "subdi3"
(define_expand "subdi3"
  [(set (match_operand:DI 0 "nonimmediate_operand" "")
  [(set (match_operand:DI 0 "nonimmediate_operand" "")
        (minus:DI (match_operand:DI 1 "nonimmediate_operand" "")
        (minus:DI (match_operand:DI 1 "nonimmediate_operand" "")
                  (match_operand:DI 2 "general_operand" "")))]
                  (match_operand:DI 2 "general_operand" "")))]
  ""
  ""
  "m68hc11_emit_libcall (\"___subdi3\", MINUS, DImode, DImode, 3, operands);
  "m68hc11_emit_libcall (\"___subdi3\", MINUS, DImode, DImode, 3, operands);
   DONE;")
   DONE;")
;;
;;
;; 32-bit Subtract (see addsi3)
;; 32-bit Subtract (see addsi3)
;; Subtract with a constant are handled by addsi3.
;; Subtract with a constant are handled by addsi3.
;;
;;
;;
;;
;; - 32-bit Add.
;; - 32-bit Add.
;;
;;
(define_expand "subsi3"
(define_expand "subsi3"
  [(parallel [(set (match_operand:SI 0 "register_operand" "")
  [(parallel [(set (match_operand:SI 0 "register_operand" "")
                     (minus:SI (match_operand:SI 1 "register_operand" "")
                     (minus:SI (match_operand:SI 1 "register_operand" "")
                              (match_operand:SI 2 "general_operand" "")))
                              (match_operand:SI 2 "general_operand" "")))
              (clobber (match_scratch:HI 3 ""))])]
              (clobber (match_scratch:HI 3 ""))])]
  ""
  ""
  "")
  "")
(define_insn "*subsi3"
(define_insn "*subsi3"
  [(set (match_operand:SI 0 "register_operand" "=D,D,D,D,!u")
  [(set (match_operand:SI 0 "register_operand" "=D,D,D,D,!u")
        (minus:SI (match_operand:SI 1 "general_operand" "0,oi,0,!u,0")
        (minus:SI (match_operand:SI 1 "general_operand" "0,oi,0,!u,0")
                  (match_operand:SI 2 "general_operand" "oi,D,!u,D,!oui")))
                  (match_operand:SI 2 "general_operand" "oi,D,!u,D,!oui")))
   (clobber (match_scratch:HI 3 "=X,X,X,X,d"))]
   (clobber (match_scratch:HI 3 "=X,X,X,X,d"))]
  ""
  ""
  "#")
  "#")
(define_insn "*subsi3_zero_extendhi"
(define_insn "*subsi3_zero_extendhi"
  [(set (match_operand:SI 0 "register_operand" "=D")
  [(set (match_operand:SI 0 "register_operand" "=D")
        (minus:SI (match_operand:SI 1 "register_operand" "0")
        (minus:SI (match_operand:SI 1 "register_operand" "0")
            (zero_extend:SI (match_operand:HI 2 "general_operand" "dmui*A"))))
            (zero_extend:SI (match_operand:HI 2 "general_operand" "dmui*A"))))
   (clobber (match_scratch:HI 3 "=X"))]
   (clobber (match_scratch:HI 3 "=X"))]
  ""
  ""
  "*
  "*
{
{
  rtx ops[2];
  rtx ops[2];
  if (A_REG_P (operands[2]))
  if (A_REG_P (operands[2]))
    {
    {
      if (TARGET_M6812)
      if (TARGET_M6812)
        ops[0] = gen_rtx_MEM (HImode,
        ops[0] = gen_rtx_MEM (HImode,
                          gen_rtx_PRE_DEC (HImode,
                          gen_rtx_PRE_DEC (HImode,
                                   gen_rtx_REG (HImode, HARD_SP_REGNUM)));
                                   gen_rtx_REG (HImode, HARD_SP_REGNUM)));
      else
      else
        ops[0] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
        ops[0] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
      ops[1] = operands[2];
      ops[1] = operands[2];
      m68hc11_gen_movhi (insn, ops);
      m68hc11_gen_movhi (insn, ops);
      if (TARGET_M6812)
      if (TARGET_M6812)
        operands[2] = gen_rtx_MEM (HImode,
        operands[2] = gen_rtx_MEM (HImode,
                               gen_rtx_POST_INC (HImode,
                               gen_rtx_POST_INC (HImode,
                                        gen_rtx_REG (HImode, HARD_SP_REGNUM)));
                                        gen_rtx_REG (HImode, HARD_SP_REGNUM)));
      else
      else
        operands[2] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
        operands[2] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
    }
    }
  ops[0] = gen_label_rtx ();
  ops[0] = gen_label_rtx ();
  output_asm_insn (\"subd\\t%2\", operands);
  output_asm_insn (\"subd\\t%2\", operands);
  output_asm_insn (\"bcc\\t%l0\", ops);
  output_asm_insn (\"bcc\\t%l0\", ops);
  output_asm_insn (\"dex\", ops);
  output_asm_insn (\"dex\", ops);
  (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0]));
  (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0]));
  CC_STATUS_INIT;
  CC_STATUS_INIT;
  return \"\";
  return \"\";
}")
}")
(define_insn "*subsi3_zero_extendqi"
(define_insn "*subsi3_zero_extendqi"
  [(set (match_operand:SI 0 "register_operand" "=D")
  [(set (match_operand:SI 0 "register_operand" "=D")
        (minus:SI (match_operand:SI 1 "register_operand" "0")
        (minus:SI (match_operand:SI 1 "register_operand" "0")
            (zero_extend:SI (match_operand:QI 2 "general_operand" "dmui*A"))))
            (zero_extend:SI (match_operand:QI 2 "general_operand" "dmui*A"))))
   (clobber (match_scratch:HI 3 "=X"))]
   (clobber (match_scratch:HI 3 "=X"))]
  ""
  ""
  "*
  "*
{
{
  rtx ops[2];
  rtx ops[2];
  if (A_REG_P (operands[2]))
  if (A_REG_P (operands[2]))
    {
    {
      ops[0] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
      ops[0] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
      ops[1] = operands[2];
      ops[1] = operands[2];
      m68hc11_gen_movhi (insn, ops);
      m68hc11_gen_movhi (insn, ops);
      operands[2] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
      operands[2] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
    }
    }
  ops[0] = gen_label_rtx ();
  ops[0] = gen_label_rtx ();
  output_asm_insn (\"subb\\t%b2\", operands);
  output_asm_insn (\"subb\\t%b2\", operands);
  output_asm_insn (\"sbca\\t#0\", operands);
  output_asm_insn (\"sbca\\t#0\", operands);
  output_asm_insn (\"bcc\\t%l0\", ops);
  output_asm_insn (\"bcc\\t%l0\", ops);
  output_asm_insn (\"dex\", ops);
  output_asm_insn (\"dex\", ops);
  (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0]));
  (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0]));
  CC_STATUS_INIT;
  CC_STATUS_INIT;
  return \"\";
  return \"\";
}")
}")
;;
;;
;; reg:HI 1 -> d        reg:QI 6 -> B
;; reg:HI 1 -> d        reg:QI 6 -> B
;; reg:QI 7 -> ccr      reg:QI 5 -> A
;; reg:QI 7 -> ccr      reg:QI 5 -> A
;;
;;
(define_split /* "*subsi3" */
(define_split /* "*subsi3" */
  [(set (match_operand:SI 0 "register_operand" "")
  [(set (match_operand:SI 0 "register_operand" "")
        (minus:SI (match_operand:SI 1 "register_operand" "")
        (minus:SI (match_operand:SI 1 "register_operand" "")
                  (match_operand:SI 2 "general_operand" "")))
                  (match_operand:SI 2 "general_operand" "")))
   (clobber (match_scratch:HI 3 "=X"))]
   (clobber (match_scratch:HI 3 "=X"))]
  "reload_completed && z_replacement_completed == 2
  "reload_completed && z_replacement_completed == 2
   && X_REG_P (operands[1])"
   && X_REG_P (operands[1])"
  [(set (reg:HI D_REGNUM) (minus:HI (reg:HI D_REGNUM) (match_dup 3)))
  [(set (reg:HI D_REGNUM) (minus:HI (reg:HI D_REGNUM) (match_dup 3)))
   (parallel [(set (reg:HI X_REGNUM) (reg:HI D_REGNUM))
   (parallel [(set (reg:HI X_REGNUM) (reg:HI D_REGNUM))
              (set (reg:HI D_REGNUM) (reg:HI X_REGNUM))])
              (set (reg:HI D_REGNUM) (reg:HI X_REGNUM))])
   (set (reg:QI B_REGNUM) (minus:QI (minus:QI (reg:QI CC_REGNUM) (reg:QI B_REGNUM)) (match_dup 4)))
   (set (reg:QI B_REGNUM) (minus:QI (minus:QI (reg:QI CC_REGNUM) (reg:QI B_REGNUM)) (match_dup 4)))
   (set (reg:QI A_REGNUM) (minus:QI (minus:QI (reg:QI CC_REGNUM) (reg:QI A_REGNUM)) (match_dup 5)))
   (set (reg:QI A_REGNUM) (minus:QI (minus:QI (reg:QI CC_REGNUM) (reg:QI A_REGNUM)) (match_dup 5)))
   (parallel [(set (reg:HI X_REGNUM) (reg:HI D_REGNUM))
   (parallel [(set (reg:HI X_REGNUM) (reg:HI D_REGNUM))
              (set (reg:HI D_REGNUM) (reg:HI X_REGNUM))])]
              (set (reg:HI D_REGNUM) (reg:HI X_REGNUM))])]
  "operands[3] = m68hc11_gen_lowpart (HImode, operands[2]);
  "operands[3] = m68hc11_gen_lowpart (HImode, operands[2]);
   operands[4] = m68hc11_gen_highpart (HImode, operands[2]);
   operands[4] = m68hc11_gen_highpart (HImode, operands[2]);
   operands[5] = m68hc11_gen_highpart (QImode, operands[4]);
   operands[5] = m68hc11_gen_highpart (QImode, operands[4]);
   operands[4] = m68hc11_gen_lowpart (QImode, operands[4]);")
   operands[4] = m68hc11_gen_lowpart (QImode, operands[4]);")
(define_split /* "*subsi3" */
(define_split /* "*subsi3" */
  [(set (match_operand:SI 0 "register_operand" "")
  [(set (match_operand:SI 0 "register_operand" "")
        (minus:SI (match_operand:SI 1 "general_operand" "")
        (minus:SI (match_operand:SI 1 "general_operand" "")
                  (match_operand:SI 2 "register_operand" "")))
                  (match_operand:SI 2 "register_operand" "")))
   (clobber (match_scratch:HI 3 "=X"))]
   (clobber (match_scratch:HI 3 "=X"))]
  "reload_completed && z_replacement_completed == 2
  "reload_completed && z_replacement_completed == 2
   && X_REG_P (operands[2])"
   && X_REG_P (operands[2])"
  [(set (reg:HI D_REGNUM) (minus:HI (reg:HI D_REGNUM) (match_dup 3)))
  [(set (reg:HI D_REGNUM) (minus:HI (reg:HI D_REGNUM) (match_dup 3)))
   (parallel [(set (reg:HI X_REGNUM) (reg:HI D_REGNUM))
   (parallel [(set (reg:HI X_REGNUM) (reg:HI D_REGNUM))
              (set (reg:HI D_REGNUM) (reg:HI X_REGNUM))])
              (set (reg:HI D_REGNUM) (reg:HI X_REGNUM))])
   (set (reg:QI B_REGNUM) (minus:QI (minus:QI (reg:QI CC_REGNUM) (reg:QI B_REGNUM)) (match_dup 4)))
   (set (reg:QI B_REGNUM) (minus:QI (minus:QI (reg:QI CC_REGNUM) (reg:QI B_REGNUM)) (match_dup 4)))
   (set (reg:QI A_REGNUM) (minus:QI (minus:QI (reg:QI CC_REGNUM) (reg:QI A_REGNUM)) (match_dup 5)))
   (set (reg:QI A_REGNUM) (minus:QI (minus:QI (reg:QI CC_REGNUM) (reg:QI A_REGNUM)) (match_dup 5)))
   (parallel [(set (reg:HI X_REGNUM) (reg:HI D_REGNUM))
   (parallel [(set (reg:HI X_REGNUM) (reg:HI D_REGNUM))
              (set (reg:HI D_REGNUM) (reg:HI X_REGNUM))])
              (set (reg:HI D_REGNUM) (reg:HI X_REGNUM))])
   (set (reg:SI 0) (neg:SI (reg:SI 0)))]
   (set (reg:SI 0) (neg:SI (reg:SI 0)))]
  "operands[3] = m68hc11_gen_lowpart (HImode, operands[1]);
  "operands[3] = m68hc11_gen_lowpart (HImode, operands[1]);
   operands[4] = m68hc11_gen_highpart (HImode, operands[1]);
   operands[4] = m68hc11_gen_highpart (HImode, operands[1]);
   operands[5] = m68hc11_gen_highpart (QImode, operands[4]);
   operands[5] = m68hc11_gen_highpart (QImode, operands[4]);
   operands[4] = m68hc11_gen_lowpart (QImode, operands[4]);")
   operands[4] = m68hc11_gen_lowpart (QImode, operands[4]);")
(define_split /* "*subsi3" */
(define_split /* "*subsi3" */
  [(set (match_operand:SI 0 "nonimmediate_operand" "")
  [(set (match_operand:SI 0 "nonimmediate_operand" "")
        (minus:SI (match_operand:SI 1 "general_operand" "")
        (minus:SI (match_operand:SI 1 "general_operand" "")
                  (match_operand:SI 2 "general_operand" "")))
                  (match_operand:SI 2 "general_operand" "")))
   (clobber (match_scratch:HI 3 "=d"))]
   (clobber (match_scratch:HI 3 "=d"))]
  "reload_completed && z_replacement_completed == 2
  "reload_completed && z_replacement_completed == 2
   && !X_REG_P (operands[0])"
   && !X_REG_P (operands[0])"
  [(set (match_dup 3) (match_dup 4))
  [(set (match_dup 3) (match_dup 4))
   (set (match_dup 3) (minus:HI (match_dup 3) (match_dup 5)))
   (set (match_dup 3) (minus:HI (match_dup 3) (match_dup 5)))
   (set (match_dup 4) (match_dup 3))
   (set (match_dup 4) (match_dup 3))
   (set (match_dup 3) (match_dup 6))
   (set (match_dup 3) (match_dup 6))
   (set (reg:QI 6) (minus:QI (minus:QI (reg:QI 7) (reg:QI 6)) (match_dup 7)))
   (set (reg:QI 6) (minus:QI (minus:QI (reg:QI 7) (reg:QI 6)) (match_dup 7)))
   (set (reg:QI 5) (minus:QI (minus:QI (reg:QI 7) (reg:QI 5)) (match_dup 8)))
   (set (reg:QI 5) (minus:QI (minus:QI (reg:QI 7) (reg:QI 5)) (match_dup 8)))
   (set (match_dup 6) (match_dup 3))]
   (set (match_dup 6) (match_dup 3))]
  "operands[4] = m68hc11_gen_lowpart (HImode, operands[1]);
  "operands[4] = m68hc11_gen_lowpart (HImode, operands[1]);
   operands[5] = m68hc11_gen_lowpart (HImode, operands[2]);
   operands[5] = m68hc11_gen_lowpart (HImode, operands[2]);
   operands[6] = m68hc11_gen_highpart (HImode, operands[1]);
   operands[6] = m68hc11_gen_highpart (HImode, operands[1]);
   operands[7] = m68hc11_gen_highpart (HImode, operands[2]);
   operands[7] = m68hc11_gen_highpart (HImode, operands[2]);
   operands[8] = m68hc11_gen_highpart (QImode, operands[7]);
   operands[8] = m68hc11_gen_highpart (QImode, operands[7]);
   operands[7] = m68hc11_gen_lowpart (QImode, operands[7]);")
   operands[7] = m68hc11_gen_lowpart (QImode, operands[7]);")
;;
;;
;; - 16-bit Subtract.
;; - 16-bit Subtract.
;;
;;
(define_expand "subhi3"
(define_expand "subhi3"
  [(set (match_operand:HI 0 "register_operand" "=r")
  [(set (match_operand:HI 0 "register_operand" "=r")
        (minus:HI (match_operand:HI 1 "register_operand" "0")
        (minus:HI (match_operand:HI 1 "register_operand" "0")
                  (match_operand:HI 2 "general_operand" "g")))]
                  (match_operand:HI 2 "general_operand" "g")))]
  ""
  ""
  "")
  "")
;;
;;
;; Subtract from stack. This is better if we provide a pattern.
;; Subtract from stack. This is better if we provide a pattern.
;;
;;
(define_insn "*subhi3_sp"
(define_insn "*subhi3_sp"
  [(set (match_operand:HI 0 "stack_register_operand" "=w,w")
  [(set (match_operand:HI 0 "stack_register_operand" "=w,w")
        (minus:HI (match_operand:HI 1 "register_operand" "0,0")
        (minus:HI (match_operand:HI 1 "register_operand" "0,0")
                  (match_operand:HI 2 "general_operand" "im*d,!u*A")))
                  (match_operand:HI 2 "general_operand" "im*d,!u*A")))
   (clobber (match_scratch:HI 3 "=A*d,A*d"))]
   (clobber (match_scratch:HI 3 "=A*d,A*d"))]
  ""
  ""
  "*
  "*
{
{
  if (X_REG_P (operands[2]))
  if (X_REG_P (operands[2]))
    {
    {
      operands[2] = m68hc11_soft_tmp_reg;
      operands[2] = m68hc11_soft_tmp_reg;
      output_asm_insn (\"stx\\t%2\", operands);
      output_asm_insn (\"stx\\t%2\", operands);
    }
    }
  else if (Y_REG_P (operands[2]))
  else if (Y_REG_P (operands[2]))
    {
    {
      operands[2] = m68hc11_soft_tmp_reg;
      operands[2] = m68hc11_soft_tmp_reg;
      output_asm_insn (\"sty\\t%2\", operands);
      output_asm_insn (\"sty\\t%2\", operands);
    }
    }
  else if (D_REG_P (operands[2]))
  else if (D_REG_P (operands[2]))
    {
    {
      operands[2] = m68hc11_soft_tmp_reg;
      operands[2] = m68hc11_soft_tmp_reg;
      output_asm_insn (\"std\\t%2\", operands);
      output_asm_insn (\"std\\t%2\", operands);
    }
    }
  if (D_REG_P (operands[3]))
  if (D_REG_P (operands[3]))
    {
    {
      int save_x;
      int save_x;
      save_x = !dead_register_here (insn, ix_reg);
      save_x = !dead_register_here (insn, ix_reg);
      if (save_x)
      if (save_x)
        output_asm_insn (\"xgdx\", operands);
        output_asm_insn (\"xgdx\", operands);
      output_asm_insn (\"tsx\", operands);
      output_asm_insn (\"tsx\", operands);
      output_asm_insn (\"xgdx\", operands);
      output_asm_insn (\"xgdx\", operands);
      output_asm_insn (\"subd\\t%2\", operands);
      output_asm_insn (\"subd\\t%2\", operands);
      output_asm_insn (\"xgdx\", operands);
      output_asm_insn (\"xgdx\", operands);
      /* The status flags correspond to the addd. xgdx/y and tx/ys do not
      /* The status flags correspond to the addd. xgdx/y and tx/ys do not
         modify the flags.  */
         modify the flags.  */
      output_asm_insn (\"txs\", operands);
      output_asm_insn (\"txs\", operands);
      if (save_x)
      if (save_x)
        return \"xgdx\";
        return \"xgdx\";
      else
      else
        return \"\";
        return \"\";
    }
    }
  /* Need to transfer to SP to X,Y and then to D register.
  /* Need to transfer to SP to X,Y and then to D register.
     Register X,Y is lost, this is specified by the (clobber) statement.  */
     Register X,Y is lost, this is specified by the (clobber) statement.  */
  output_asm_insn (\"ts%3\", operands);
  output_asm_insn (\"ts%3\", operands);
  output_asm_insn (\"xgd%3\", operands);
  output_asm_insn (\"xgd%3\", operands);
  output_asm_insn (\"subd\\t%2\", operands);
  output_asm_insn (\"subd\\t%2\", operands);
  output_asm_insn (\"xgd%3\", operands);
  output_asm_insn (\"xgd%3\", operands);
   /* The status flags correspond to the addd. xgdx/y and tx/ys do not
   /* The status flags correspond to the addd. xgdx/y and tx/ys do not
      modify the flags.  */
      modify the flags.  */
  return \"t%3s\";
  return \"t%3s\";
}")
}")
(define_insn "*subhi3"
(define_insn "*subhi3"
  [(set (match_operand:HI 0 "register_operand" "=d,*A,d,*A")
  [(set (match_operand:HI 0 "register_operand" "=d,*A,d,*A")
        (minus:HI (match_operand:HI 1 "general_operand" "0,0,0,0")
        (minus:HI (match_operand:HI 1 "general_operand" "0,0,0,0")
                  (match_operand:HI 2 "general_operand" "im*A*d,im*d*A,u,!u")))]
                  (match_operand:HI 2 "general_operand" "im*A*d,im*d*A,u,!u")))]
  ""
  ""
  "*
  "*
{
{
  /* Adding to an address register or with another/same register
  /* Adding to an address register or with another/same register
     is not possible.  This must be replaced.  */
     is not possible.  This must be replaced.  */
  if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
  if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
    return \"#\";
    return \"#\";
  return \"subd\\t%2\";
  return \"subd\\t%2\";
}")
}")
(define_insn "*subhi3_zext"
(define_insn "*subhi3_zext"
  [(set (match_operand:HI 0 "hard_reg_operand" "=d,d")
  [(set (match_operand:HI 0 "hard_reg_operand" "=d,d")
        (minus:HI (match_operand:HI 1 "general_operand" "0,0")
        (minus:HI (match_operand:HI 1 "general_operand" "0,0")
           (zero_extend:HI (match_operand:QI 2 "general_operand" "mi*A,!u"))))]
           (zero_extend:HI (match_operand:QI 2 "general_operand" "mi*A,!u"))))]
  ""
  ""
  "*
  "*
{
{
  CC_STATUS_INIT;
  CC_STATUS_INIT;
  if (A_REG_P (operands[2]))
  if (A_REG_P (operands[2]))
    {
    {
      rtx ops[2];
      rtx ops[2];
      ops[0] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
      ops[0] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
      ops[1] = operands[2];
      ops[1] = operands[2];
      m68hc11_gen_movqi (insn, ops);
      m68hc11_gen_movqi (insn, ops);
      return \"subb\\t%T0\\n\\tsbca\\t#0\";
      return \"subb\\t%T0\\n\\tsbca\\t#0\";
    }
    }
  return \"subb\\t%b2\\n\\tsbca\\t#0\";
  return \"subb\\t%b2\\n\\tsbca\\t#0\";
}")
}")
(define_insn "subqi3"
(define_insn "subqi3"
  [(set (match_operand:QI 0 "hard_reg_operand" "=dq,!*x*y")
  [(set (match_operand:QI 0 "hard_reg_operand" "=dq,!*x*y")
        (minus:QI (match_operand:QI 1 "general_operand" "0,0")
        (minus:QI (match_operand:QI 1 "general_operand" "0,0")
                  (match_operand:QI 2 "general_operand" "uim*A*d,uim*A*d")))]
                  (match_operand:QI 2 "general_operand" "uim*A*d,uim*A*d")))]
  ""
  ""
  "*
  "*
{
{
  if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
  if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
    return \"#\";
    return \"#\";
  else if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
  else if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
    return \"subb\\t%b2\";
    return \"subb\\t%b2\";
  else
  else
    return \"suba\\t%b2\";
    return \"suba\\t%b2\";
}")
}")
;;
;;
;; subtract with carry is used for 32-bit subtract.
;; subtract with carry is used for 32-bit subtract.
;;
;;
(define_insn "*subcq"
(define_insn "*subcq"
  [(set (match_operand:QI 0 "register_operand" "=q")
  [(set (match_operand:QI 0 "register_operand" "=q")
        (minus:QI (minus:QI (reg:QI CC_REGNUM)
        (minus:QI (minus:QI (reg:QI CC_REGNUM)
                            (match_operand:QI 1 "register_operand" "0"))
                            (match_operand:QI 1 "register_operand" "0"))
                  (match_operand:QI 2 "general_operand" "ium")))]
                  (match_operand:QI 2 "general_operand" "ium")))]
  ""
  ""
  "sbc%0\\t%b2")
  "sbc%0\\t%b2")
;;--------------------------------------------------------------------
;;--------------------------------------------------------------------
;;- Multiply instructions.
;;- Multiply instructions.
;;--------------------------------------------------------------------
;;--------------------------------------------------------------------
;;
;;
;; 32 and 64-bit multiply are handled by the library
;; 32 and 64-bit multiply are handled by the library
;;
;;
(define_expand "mulsi3"
(define_expand "mulsi3"
  [(set (match_operand:SI 0 "nonimmediate_operand" "")
  [(set (match_operand:SI 0 "nonimmediate_operand" "")
        (mult:SI (match_operand:SI 1 "general_operand" "")
        (mult:SI (match_operand:SI 1 "general_operand" "")
                 (match_operand:SI 2 "general_operand" "")))]
                 (match_operand:SI 2 "general_operand" "")))]
  ""
  ""
  "m68hc11_emit_libcall (\"__mulsi3\", MULT, SImode, SImode, 3, operands);
  "m68hc11_emit_libcall (\"__mulsi3\", MULT, SImode, SImode, 3, operands);
   DONE;")
   DONE;")
(define_expand "mulhi3"
(define_expand "mulhi3"
  [(parallel [(set (match_operand:HI 0 "register_operand" "")
  [(parallel [(set (match_operand:HI 0 "register_operand" "")
                       (mult:HI (match_operand:HI 1 "register_operand" "")
                       (mult:HI (match_operand:HI 1 "register_operand" "")
                                (match_operand:HI 2 "register_operand" "")))
                                (match_operand:HI 2 "register_operand" "")))
              (clobber (match_scratch:HI 3 ""))])]
              (clobber (match_scratch:HI 3 ""))])]
  ""
  ""
  "")
  "")
(define_insn "mulhi3_m68hc11"
(define_insn "mulhi3_m68hc11"
  [(set (match_operand:HI 0 "register_operand" "=d")
  [(set (match_operand:HI 0 "register_operand" "=d")
        (mult:HI (match_operand:HI 1 "register_operand" "%0")
        (mult:HI (match_operand:HI 1 "register_operand" "%0")
                 (match_operand:HI 2 "register_operand" "x")))
                 (match_operand:HI 2 "register_operand" "x")))
   (clobber (match_scratch:HI 3 "=X"))]
   (clobber (match_scratch:HI 3 "=X"))]
  "TARGET_M6811"
  "TARGET_M6811"
  "*
  "*
{
{
  CC_STATUS_INIT;
  CC_STATUS_INIT;
  /* D * X -> D  (X and Y are preserved by this function call).  */
  /* D * X -> D  (X and Y are preserved by this function call).  */
  return \"jsr\\t___mulhi3\";
  return \"jsr\\t___mulhi3\";
}")
}")
(define_insn "mulhi3_m68hc12"
(define_insn "mulhi3_m68hc12"
  [(set (match_operand:HI 0 "register_operand" "=d,d")
  [(set (match_operand:HI 0 "register_operand" "=d,d")
        (mult:HI (match_operand:HI 1 "register_operand" "%0,0")
        (mult:HI (match_operand:HI 1 "register_operand" "%0,0")
                 (match_operand:HI 2 "register_operand" "y,x")))
                 (match_operand:HI 2 "register_operand" "y,x")))
   (clobber (match_scratch:HI 3 "=2,2"))]
   (clobber (match_scratch:HI 3 "=2,2"))]
  "TARGET_M6812"
  "TARGET_M6812"
  "*
  "*
{
{
  CC_STATUS_INIT;
  CC_STATUS_INIT;
  if (X_REG_P (operands[2]))
  if (X_REG_P (operands[2]))
    return \"exg\\tx,y\\n\\temul\\n\\texg\\tx,y\";
    return \"exg\\tx,y\\n\\temul\\n\\texg\\tx,y\";
  else
  else
    return \"emul\";
    return \"emul\";
}")
}")
(define_insn "umulhisi3"
(define_insn "umulhisi3"
  [(set (match_operand:SI 0 "register_operand" "=D,D")
  [(set (match_operand:SI 0 "register_operand" "=D,D")
        (mult:SI (zero_extend:SI
        (mult:SI (zero_extend:SI
                     (match_operand:HI 1 "register_operand" "%d,d"))
                     (match_operand:HI 1 "register_operand" "%d,d"))
                 (zero_extend:SI
                 (zero_extend:SI
                     (match_operand:HI 2 "register_operand" "y,x"))))
                     (match_operand:HI 2 "register_operand" "y,x"))))
   (clobber (match_scratch:HI 3 "=2,X"))]
   (clobber (match_scratch:HI 3 "=2,X"))]
  "TARGET_M6812"
  "TARGET_M6812"
  "*
  "*
{
{
  if (X_REG_P (operands [2]))
  if (X_REG_P (operands [2]))
    output_asm_insn (\"exg\\tx,y\", operands);
    output_asm_insn (\"exg\\tx,y\", operands);
  /* Can't use the carry after that; other flags are ok when testing
  /* Can't use the carry after that; other flags are ok when testing
     the 32-bit result.  */
     the 32-bit result.  */
  cc_status.flags |= CC_NO_OVERFLOW;
  cc_status.flags |= CC_NO_OVERFLOW;
  return \"emul\\n\\texg\\tx,y\";
  return \"emul\\n\\texg\\tx,y\";
}")
}")
(define_insn "mulhisi3"
(define_insn "mulhisi3"
  [(set (match_operand:SI 0 "register_operand" "=D,D")
  [(set (match_operand:SI 0 "register_operand" "=D,D")
        (mult:SI (sign_extend:SI
        (mult:SI (sign_extend:SI
                     (match_operand:HI 1 "register_operand" "%d,d"))
                     (match_operand:HI 1 "register_operand" "%d,d"))
                 (sign_extend:SI
                 (sign_extend:SI
                     (match_operand:HI 2 "register_operand" "y,x"))))
                     (match_operand:HI 2 "register_operand" "y,x"))))
   (clobber (match_scratch:HI 3 "=2,X"))]
   (clobber (match_scratch:HI 3 "=2,X"))]
  "TARGET_M6812"
  "TARGET_M6812"
  "*
  "*
{
{
  if (X_REG_P (operands [2]))
  if (X_REG_P (operands [2]))
    output_asm_insn (\"exg\\tx,y\", operands);
    output_asm_insn (\"exg\\tx,y\", operands);
  /* Can't use the carry after that; other flags are ok when testing
  /* Can't use the carry after that; other flags are ok when testing
     the 32-bit result.  */
     the 32-bit result.  */
  cc_status.flags |= CC_NO_OVERFLOW;
  cc_status.flags |= CC_NO_OVERFLOW;
  return \"emuls\\n\\texg\\tx,y\";
  return \"emuls\\n\\texg\\tx,y\";
}")
}")
(define_insn "umulqihi3"
(define_insn "umulqihi3"
  [(set (match_operand:HI 0 "register_operand" "=d")
  [(set (match_operand:HI 0 "register_operand" "=d")
        (mult:HI (zero_extend:HI
        (mult:HI (zero_extend:HI
                     (match_operand:QI 1 "nonimmediate_operand" "dm*u"))
                     (match_operand:QI 1 "nonimmediate_operand" "dm*u"))
                 (zero_extend:HI
                 (zero_extend:HI
                     (match_operand:QI 2 "nonimmediate_operand" "dm*u*A"))))]
                     (match_operand:QI 2 "nonimmediate_operand" "dm*u*A"))))]
  ""
  ""
  "*
  "*
{
{
  if (D_REG_P (operands[1]) && D_REG_P (operands[2]))
  if (D_REG_P (operands[1]) && D_REG_P (operands[2]))
    {
    {
      output_asm_insn (\"tba\", operands);
      output_asm_insn (\"tba\", operands);
    }
    }
  else
  else
    {
    {
      rtx ops[2];
      rtx ops[2];
      if (D_REG_P (operands[2]))
      if (D_REG_P (operands[2]))
        {
        {
          rtx temp = operands[2];
          rtx temp = operands[2];
          operands[2] = operands[1];
          operands[2] = operands[1];
          operands[1] = temp;
          operands[1] = temp;
        }
        }
      ops[0] = gen_rtx_REG (QImode, HARD_A_REGNUM);
      ops[0] = gen_rtx_REG (QImode, HARD_A_REGNUM);
      ops[1] = operands[2];
      ops[1] = operands[2];
      m68hc11_gen_movqi (insn, ops);
      m68hc11_gen_movqi (insn, ops);
      if (!D_REG_P (operands[1]))
      if (!D_REG_P (operands[1]))
        {
        {
          output_asm_insn (\"ldab\\t%b1\", operands);
          output_asm_insn (\"ldab\\t%b1\", operands);
        }
        }
    }
    }
  CC_STATUS_INIT;
  CC_STATUS_INIT;
  return \"mul\";
  return \"mul\";
}")
}")
(define_insn "mulqi3"
(define_insn "mulqi3"
  [(set (match_operand:QI 0 "register_operand" "=d,*x,*y")
  [(set (match_operand:QI 0 "register_operand" "=d,*x,*y")
        (mult:QI (match_operand:QI 1 "general_operand" "%di*um,0,0")
        (mult:QI (match_operand:QI 1 "general_operand" "%di*um,0,0")
                 (match_operand:QI 2 "general_operand" "di*um,*xium,*yium")))]
                 (match_operand:QI 2 "general_operand" "di*um,*xium,*yium")))]
  ""
  ""
  "*
  "*
{
{
  if (A_REG_P (operands[0]))
  if (A_REG_P (operands[0]))
    return \"#\";
    return \"#\";
  if (D_REG_P (operands[1]) && D_REG_P (operands[2]))
  if (D_REG_P (operands[1]) && D_REG_P (operands[2]))
    {
    {
      output_asm_insn (\"tba\", operands);
      output_asm_insn (\"tba\", operands);
    }
    }
  else
  else
    {
    {
      if (D_REG_P (operands[2]))
      if (D_REG_P (operands[2]))
        {
        {
          rtx temp = operands[2];
          rtx temp = operands[2];
          operands[2] = operands[1];
          operands[2] = operands[1];
          operands[1] = temp;
          operands[1] = temp;
        }
        }
      output_asm_insn (\"ldaa\\t%b2\", operands);
      output_asm_insn (\"ldaa\\t%b2\", operands);
      if (!D_REG_P (operands[1]))
      if (!D_REG_P (operands[1]))
        {
        {
          output_asm_insn (\"ldab\\t%b1\", operands);
          output_asm_insn (\"ldab\\t%b1\", operands);
        }
        }
    }
    }
  CC_STATUS_INIT;
  CC_STATUS_INIT;
  return \"mul\";
  return \"mul\";
}")
}")
(define_split
(define_split
  [(set (match_operand:QI 0 "hard_addr_reg_operand" "")
  [(set (match_operand:QI 0 "hard_addr_reg_operand" "")
        (mult:QI (match_operand:QI 1 "general_operand" "")
        (mult:QI (match_operand:QI 1 "general_operand" "")
                 (match_operand:QI 2 "general_operand" "")))]
                 (match_operand:QI 2 "general_operand" "")))]
  "z_replacement_completed == 2"
  "z_replacement_completed == 2"
  [(parallel [(set (reg:HI D_REGNUM) (match_dup 3))
  [(parallel [(set (reg:HI D_REGNUM) (match_dup 3))
              (set (match_dup 3) (reg:HI D_REGNUM))])
              (set (match_dup 3) (reg:HI D_REGNUM))])
   (set (reg:QI D_REGNUM) (mult:QI (match_dup 5) (match_dup 6)))
   (set (reg:QI D_REGNUM) (mult:QI (match_dup 5) (match_dup 6)))
   (parallel [(set (reg:HI D_REGNUM) (match_dup 3))
   (parallel [(set (reg:HI D_REGNUM) (match_dup 3))
              (set (match_dup 3) (reg:HI D_REGNUM))])]
              (set (match_dup 3) (reg:HI D_REGNUM))])]
  "
  "
   operands[3] = gen_rtx_REG (HImode, REGNO (operands[0]));
   operands[3] = gen_rtx_REG (HImode, REGNO (operands[0]));
   if (A_REG_P (operands[1]))
   if (A_REG_P (operands[1]))
     operands[5] = gen_rtx_REG (QImode, HARD_D_REGNUM);
     operands[5] = gen_rtx_REG (QImode, HARD_D_REGNUM);
   else
   else
     operands[5] = operands[1];
     operands[5] = operands[1];
   if (A_REG_P (operands[2]))
   if (A_REG_P (operands[2]))
     operands[6] = gen_rtx_REG (QImode, HARD_D_REGNUM);
     operands[6] = gen_rtx_REG (QImode, HARD_D_REGNUM);
   else
   else
     operands[6] = operands[2];
     operands[6] = operands[2];
  ")
  ")
(define_insn "mulqihi3"
(define_insn "mulqihi3"
  [(set (match_operand:HI 0 "register_operand" "=d,d,d")
  [(set (match_operand:HI 0 "register_operand" "=d,d,d")
        (mult:HI (sign_extend:HI
        (mult:HI (sign_extend:HI
                        (match_operand:QI 1 "register_operand" "%0,0,0"))
                        (match_operand:QI 1 "register_operand" "%0,0,0"))
                 (sign_extend:HI
                 (sign_extend:HI
                        (match_operand:QI 2 "general_operand" "mi*u,*A,0"))))]
                        (match_operand:QI 2 "general_operand" "mi*u,*A,0"))))]
  ""
  ""
  "*
  "*
{
{
  CC_STATUS_INIT;
  CC_STATUS_INIT;
  /* Special case when multiplying the register with itself.  */
  /* Special case when multiplying the register with itself.  */
  if (D_REG_P (operands[2]))
  if (D_REG_P (operands[2]))
    {
    {
      output_asm_insn (\"tba\", operands);
      output_asm_insn (\"tba\", operands);
      return \"mul\";
      return \"mul\";
    }
    }
  if (!H_REG_P (operands[2]))
  if (!H_REG_P (operands[2]))
    {
    {
      output_asm_insn (\"ldaa\\t%b2\", operands);
      output_asm_insn (\"ldaa\\t%b2\", operands);
    }
    }
  else
  else
    {
    {
      rtx ops[2];
      rtx ops[2];
      ops[0] = gen_rtx_REG (QImode, HARD_A_REGNUM);
      ops[0] = gen_rtx_REG (QImode, HARD_A_REGNUM);
      ops[1] = operands[2];
      ops[1] = operands[2];
      m68hc11_gen_movqi (insn, ops);
      m68hc11_gen_movqi (insn, ops);
    }
    }
  return \"jsr\\t___mulqi3\";
  return \"jsr\\t___mulqi3\";
}")
}")
;;--------------------------------------------------------------------
;;--------------------------------------------------------------------
;;- Divide instructions.
;;- Divide instructions.
;;--------------------------------------------------------------------
;;--------------------------------------------------------------------
(define_insn "divmodhi4"
(define_insn "divmodhi4"
  [(set (match_operand:HI 0 "register_operand" "=d,d")
  [(set (match_operand:HI 0 "register_operand" "=d,d")
          (div:HI (match_operand:HI 1 "register_operand" "0,0")
          (div:HI (match_operand:HI 1 "register_operand" "0,0")
                  (match_operand:HI 2 "general_operand" "A,ium")))
                  (match_operand:HI 2 "general_operand" "A,ium")))
   (set (match_operand:HI 3 "register_operand" "=&x,&x")
   (set (match_operand:HI 3 "register_operand" "=&x,&x")
        (mod:HI (match_dup 1) (match_dup 2)))]
        (mod:HI (match_dup 1) (match_dup 2)))]
  ""
  ""
  "*
  "*
{
{
  if (!X_REG_P (operands[2]))
  if (!X_REG_P (operands[2]))
    {
    {
      if (Y_REG_P (operands[2]))
      if (Y_REG_P (operands[2]))
        {
        {
          output_asm_insn (\"sty\\t%t1\", operands);
          output_asm_insn (\"sty\\t%t1\", operands);
          output_asm_insn (\"ldx\\t%t1\", operands);
          output_asm_insn (\"ldx\\t%t1\", operands);
        }
        }
      else
      else
        {
        {
          output_asm_insn (\"ldx\\t%2\", operands);
          output_asm_insn (\"ldx\\t%2\", operands);
        }
        }
    }
    }
  if (TARGET_M6812)
  if (TARGET_M6812)
    {
    {
      /* Flags are ok after that.  */
      /* Flags are ok after that.  */
      return \"idivs\\n\\txgdx\";
      return \"idivs\\n\\txgdx\";
    }
    }
  else
  else
    {
    {
      CC_STATUS_INIT;
      CC_STATUS_INIT;
      return \"bsr\\t__divmodhi4\";
      return \"bsr\\t__divmodhi4\";
    }
    }
}")
}")
(define_insn "udivmodhi4"
(define_insn "udivmodhi4"
  [(set (match_operand:HI 0 "register_operand" "=d,d")
  [(set (match_operand:HI 0 "register_operand" "=d,d")
          (udiv:HI (match_operand:HI 1 "register_operand" "0,0")
          (udiv:HI (match_operand:HI 1 "register_operand" "0,0")
                   (match_operand:HI 2 "general_operand" "A,ium")))
                   (match_operand:HI 2 "general_operand" "A,ium")))
   (set (match_operand:HI 3 "register_operand" "=x,x")
   (set (match_operand:HI 3 "register_operand" "=x,x")
        (umod:HI (match_dup 1) (match_dup 2)))]
        (umod:HI (match_dup 1) (match_dup 2)))]
  ""
  ""
  "*
  "*
{
{
  if (!X_REG_P (operands[2]))
  if (!X_REG_P (operands[2]))
    {
    {
      if (Y_REG_P (operands[2]))
      if (Y_REG_P (operands[2]))
        {
        {
          output_asm_insn (\"sty\\t%t1\", operands);
          output_asm_insn (\"sty\\t%t1\", operands);
          output_asm_insn (\"ldx\\t%t1\", operands);
          output_asm_insn (\"ldx\\t%t1\", operands);
        }
        }
      else
      else
        {
        {
          output_asm_insn (\"ldx\\t%2\", operands);
          output_asm_insn (\"ldx\\t%2\", operands);
        }
        }
    }
    }
  /* Z V and C flags are set but N is unchanged.
  /* Z V and C flags are set but N is unchanged.
     Since this is an unsigned divide, we can probably keep the flags
     Since this is an unsigned divide, we can probably keep the flags
     and indicate this.  */
     and indicate this.  */
  cc_status.flags |= CC_NOT_NEGATIVE;
  cc_status.flags |= CC_NOT_NEGATIVE;
  return \"idiv\\n\\txgdx\";
  return \"idiv\\n\\txgdx\";
}")
}")
;;--------------------------------------------------------------------
;;--------------------------------------------------------------------
;;- and instructions.
;;- and instructions.
;;--------------------------------------------------------------------
;;--------------------------------------------------------------------
(define_insn_and_split "anddi3"
(define_insn_and_split "anddi3"
  [(set (match_operand:DI 0 "reg_or_some_mem_operand" "=m,u")
  [(set (match_operand:DI 0 "reg_or_some_mem_operand" "=m,u")
        (and:DI (match_operand:DI 1 "reg_or_some_mem_operand" "%imu,imu")
        (and:DI (match_operand:DI 1 "reg_or_some_mem_operand" "%imu,imu")
                (match_operand:DI 2 "general_operand" "imu,imu")))
                (match_operand:DI 2 "general_operand" "imu,imu")))
   (clobber (match_scratch:HI 3 "=d,d"))]
   (clobber (match_scratch:HI 3 "=d,d"))]
  ""
  ""
  "#"
  "#"
  "reload_completed"
  "reload_completed"
  [(const_int 0)]
  [(const_int 0)]
  "m68hc11_split_logical (SImode, AND, operands);
  "m68hc11_split_logical (SImode, AND, operands);
   DONE;")
   DONE;")
(define_insn_and_split "andsi3"
(define_insn_and_split "andsi3"
  [(set (match_operand:SI 0 "register_operand" "=D,!u")
  [(set (match_operand:SI 0 "register_operand" "=D,!u")
        (and:SI (match_operand:SI 1 "register_operand" "%0,0")
        (and:SI (match_operand:SI 1 "register_operand" "%0,0")
                (match_operand:SI 2 "general_operand" "Dimu,imu")))
                (match_operand:SI 2 "general_operand" "Dimu,imu")))
   (clobber (match_scratch:HI 3 "=X,d"))]
   (clobber (match_scratch:HI 3 "=X,d"))]
  ""
  ""
  "#"
  "#"
  "reload_completed"
  "reload_completed"
  [(const_int 0)]
  [(const_int 0)]
  "m68hc11_split_logical (HImode, AND, operands);
  "m68hc11_split_logical (HImode, AND, operands);
   DONE;")
   DONE;")
(define_expand "andhi3"
(define_expand "andhi3"
  [(set (match_operand:HI 0 "register_operand" "")
  [(set (match_operand:HI 0 "register_operand" "")
        (and:HI (match_operand:HI 1 "register_operand" "")
        (and:HI (match_operand:HI 1 "register_operand" "")
                (match_operand:HI 2 "general_operand" "")))]
                (match_operand:HI 2 "general_operand" "")))]
  ""
  ""
  "")
  "")
(define_insn "*andhi3_mem"
(define_insn "*andhi3_mem"
  [(set (match_operand:HI 0 "memory_operand" "=R,Q")
  [(set (match_operand:HI 0 "memory_operand" "=R,Q")
        (and:HI (match_dup 0)
        (and:HI (match_dup 0)
                (match_operand:HI 1 "immediate_operand" "i,i")))
                (match_operand:HI 1 "immediate_operand" "i,i")))
   (clobber (match_scratch:HI 2 "=X,xy"))]
   (clobber (match_scratch:HI 2 "=X,xy"))]
  "TARGET_RELAX && !TARGET_M6812"
  "TARGET_RELAX && !TARGET_M6812"
  "*
  "*
{
{
  int val = INTVAL (operands[1]) & 0x0FFFF;
  int val = INTVAL (operands[1]) & 0x0FFFF;
  if (val == 0x0ffff)
  if (val == 0x0ffff)
    {
    {
      cc_status = cc_prev_status;
      cc_status = cc_prev_status;
      return \"\";
      return \"\";
    }
    }
  CC_STATUS_INIT;
  CC_STATUS_INIT;
  /* The bclr instruction uses an inverted mask.  */
  /* The bclr instruction uses an inverted mask.  */
  operands[1] = GEN_INT ((~val) & 0x0FFFF);
  operands[1] = GEN_INT ((~val) & 0x0FFFF);
  /* When destination is a global variable, generate a .relax instruction
  /* When destination is a global variable, generate a .relax instruction
     and load the address in the clobber register.  That load can be
     and load the address in the clobber register.  That load can be
     eliminated by the linker if the address is in page0.  */
     eliminated by the linker if the address is in page0.  */
  if (which_alternative == 1)
  if (which_alternative == 1)
    {
    {
      rtx ops[3];
      rtx ops[3];
      ops[0] = operands[2];
      ops[0] = operands[2];
      ops[1] = XEXP (operands[0], 0);
      ops[1] = XEXP (operands[0], 0);
      ops[2] = gen_label_rtx ();
      ops[2] = gen_label_rtx ();
      output_asm_insn (\".relax\\t%l2\", ops);
      output_asm_insn (\".relax\\t%l2\", ops);
      m68hc11_gen_movhi (insn, ops);
      m68hc11_gen_movhi (insn, ops);
      if ((val & 0x0FF) != 0x0FF)
      if ((val & 0x0FF) != 0x0FF)
        output_asm_insn (\"bclr\\t1,%2, %b1\", operands);
        output_asm_insn (\"bclr\\t1,%2, %b1\", operands);
      if ((val & 0x0FF00) != 0x0FF00)
      if ((val & 0x0FF00) != 0x0FF00)
        output_asm_insn (\"bclr\\t0,%2, %h1\", operands);
        output_asm_insn (\"bclr\\t0,%2, %h1\", operands);
      (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
      (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
                                 CODE_LABEL_NUMBER (ops[2]));
                                 CODE_LABEL_NUMBER (ops[2]));
      return \"\";
      return \"\";
    }
    }
  if ((val & 0x0FF) != 0x0FF)
  if ((val & 0x0FF) != 0x0FF)
    output_asm_insn (\"bclr\\t%b0, %b1\", operands);
    output_asm_insn (\"bclr\\t%b0, %b1\", operands);
  if ((val & 0x0FF00) != 0x0FF00)
  if ((val & 0x0FF00) != 0x0FF00)
    output_asm_insn (\"bclr\\t%h0, %h1\", operands);
    output_asm_insn (\"bclr\\t%h0, %h1\", operands);
  return \"\";
  return \"\";
}")
}")
(define_insn "*andhi3_const"
(define_insn "*andhi3_const"
  [(set (match_operand:HI 0 "reg_or_some_mem_operand" "=R,d,?*A")
  [(set (match_operand:HI 0 "reg_or_some_mem_operand" "=R,d,?*A")
        (and:HI (match_operand:HI 1 "reg_or_some_mem_operand" "%0,0,0")
        (and:HI (match_operand:HI 1 "reg_or_some_mem_operand" "%0,0,0")
                (match_operand:HI 2 "const_int_operand" "")))]
                (match_operand:HI 2 "const_int_operand" "")))]
  ""
  ""
  "*
  "*
{
{
  int val = INTVAL (operands[2]) & 0x0FFFF;
  int val = INTVAL (operands[2]) & 0x0FFFF;
  int lowpart_zero = 0;
  int lowpart_zero = 0;
  int highpart_zero = 0;
  int highpart_zero = 0;
  int lowpart_unknown = 0;
  int lowpart_unknown = 0;
  int highpart_unknown = 0;
  int highpart_unknown = 0;
  if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
  if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
    return \"#\";
    return \"#\";
  if (val == 0x0ffff)
  if (val == 0x0ffff)
    {
    {
      cc_status = cc_prev_status;
      cc_status = cc_prev_status;
      return \"\";
      return \"\";
    }
    }
  /* First, try to clear the low and high part.
  /* First, try to clear the low and high part.
     If that's possible, the second 'and' will give
     If that's possible, the second 'and' will give
     the good status flags and we can avoid a tsthi.  */
     the good status flags and we can avoid a tsthi.  */
  if ((val & 0x0FF) == 0)
  if ((val & 0x0FF) == 0)
    {
    {
      if (D_REG_P (operands[0]))
      if (D_REG_P (operands[0]))
        output_asm_insn (\"clrb\", operands);
        output_asm_insn (\"clrb\", operands);
      else
      else
        output_asm_insn (\"clr\\t%b0\", operands);
        output_asm_insn (\"clr\\t%b0\", operands);
      lowpart_zero = 1;
      lowpart_zero = 1;
    }
    }
  if ((val & 0x0FF00) == 0)
  if ((val & 0x0FF00) == 0)
    {
    {
      if (D_REG_P (operands[0]))
      if (D_REG_P (operands[0]))
        output_asm_insn (\"clra\", operands);
        output_asm_insn (\"clra\", operands);
      else
      else
        output_asm_insn (\"clr\\t%h0\", operands);
        output_asm_insn (\"clr\\t%h0\", operands);
      highpart_zero = 1;
      highpart_zero = 1;
    }
    }
  if ((val & 0x0FF) == 0x0FF)
  if ((val & 0x0FF) == 0x0FF)
    {
    {
      lowpart_unknown = 1;
      lowpart_unknown = 1;
    }
    }
  else if ((val & 0x0FF) != 0 && !H_REG_P (operands[0]))
  else if ((val & 0x0FF) != 0 && !H_REG_P (operands[0]))
    {
    {
      rtx ops[2];
      rtx ops[2];
      ops[0] = operands[0];
      ops[0] = operands[0];
      ops[1] = GEN_INT ((~val) & 0x0FF);
      ops[1] = GEN_INT ((~val) & 0x0FF);
      output_asm_insn (\"bclr\\t%b0, %1\", ops);
      output_asm_insn (\"bclr\\t%b0, %1\", ops);
    }
    }
  else if ((val & 0x0FF) != 0)
  else if ((val & 0x0FF) != 0)
    {
    {
      output_asm_insn (\"andb\\t%b2\", operands);
      output_asm_insn (\"andb\\t%b2\", operands);
    }
    }
  if ((val & 0x0FF00) == 0x0FF00)
  if ((val & 0x0FF00) == 0x0FF00)
    {
    {
      highpart_unknown = 1;
      highpart_unknown = 1;
    }
    }
  else if (((val & 0x0FF00) != 0) && !H_REG_P (operands[0]))
  else if (((val & 0x0FF00) != 0) && !H_REG_P (operands[0]))
    {
    {
      rtx ops[2];
      rtx ops[2];
      ops[0] = operands[0];
      ops[0] = operands[0];
      ops[1] = GEN_INT (((~val) & 0x0FF00) >> 8);
      ops[1] = GEN_INT (((~val) & 0x0FF00) >> 8);
      output_asm_insn (\"bclr\\t%h0, %1\", ops);
      output_asm_insn (\"bclr\\t%h0, %1\", ops);
    }
    }
  else if ((val & 0x0FF00) != 0)
  else if ((val & 0x0FF00) != 0)
    {
    {
      output_asm_insn (\"anda\\t%h2\", operands);
      output_asm_insn (\"anda\\t%h2\", operands);
    }
    }
  if (highpart_unknown || lowpart_unknown)
  if (highpart_unknown || lowpart_unknown)
     CC_STATUS_INIT;
     CC_STATUS_INIT;
  else if (highpart_zero == 0 && lowpart_zero == 0)
  else if (highpart_zero == 0 && lowpart_zero == 0)
     CC_STATUS_INIT;
     CC_STATUS_INIT;
  return \"\";
  return \"\";
}")
}")
(define_insn "*andhi3_gen"
(define_insn "*andhi3_gen"
  [(set (match_operand:HI 0 "register_operand" "=d,d,!*A")
  [(set (match_operand:HI 0 "register_operand" "=d,d,!*A")
        (and:HI (match_operand:HI 1 "splitable_operand" "%0,0,0")
        (and:HI (match_operand:HI 1 "splitable_operand" "%0,0,0")
                (match_operand:HI 2 "splitable_operand" "mi,!u*A,!um*Ai")))]
                (match_operand:HI 2 "splitable_operand" "mi,!u*A,!um*Ai")))]
  ""
  ""
  "*
  "*
{
{
  if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
  if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
    return \"#\";
    return \"#\";
  CC_STATUS_INIT;
  CC_STATUS_INIT;
  return \"anda\\t%h2\\n\\tandb\\t%b2\";
  return \"anda\\t%h2\\n\\tandb\\t%b2\";
}")
}")
(define_expand "andqi3"
(define_expand "andqi3"
  [(set (match_operand:QI 0 "register_operand" "")
  [(set (match_operand:QI 0 "register_operand" "")
        (and:QI (match_operand:QI 1 "register_operand" "")
        (and:QI (match_operand:QI 1 "register_operand" "")
                (match_operand:QI 2 "general_operand" "")))]
                (match_operand:QI 2 "general_operand" "")))]
  ""
  ""
  "")
  "")
(define_insn "*andqi3_mem"
(define_insn "*andqi3_mem"
  [(set (match_operand:QI 0 "memory_operand" "=R,Q")
  [(set (match_operand:QI 0 "memory_operand" "=R,Q")
        (and:QI (match_dup 0)
        (and:QI (match_dup 0)
                (match_operand:QI 1 "const_int_operand" "i,i")))
                (match_operand:QI 1 "const_int_operand" "i,i")))
   (clobber (match_scratch:HI 2 "=X,xy"))]
   (clobber (match_scratch:HI 2 "=X,xy"))]
  "TARGET_RELAX && !TARGET_M6812"
  "TARGET_RELAX && !TARGET_M6812"
  "*
  "*
{
{
  int val = INTVAL (operands[1]) & 0x0FF;
  int val = INTVAL (operands[1]) & 0x0FF;
  if (val == 0x0ff)
  if (val == 0x0ff)
    {
    {
      cc_status = cc_prev_status;
      cc_status = cc_prev_status;
      return \"\";
      return \"\";
    }
    }
  /* The bclr instruction uses an inverted mask.  */
  /* The bclr instruction uses an inverted mask.  */
  operands[1] = GEN_INT ((~val) & 0x0FF);
  operands[1] = GEN_INT ((~val) & 0x0FF);
  /* When destination is a global variable, generate a .relax instruction
  /* When destination is a global variable, generate a .relax instruction
     and load the address in the clobber register.  That load can be
     and load the address in the clobber register.  That load can be
     eliminated by the linker if the address is in page0.  */
     eliminated by the linker if the address is in page0.  */
  if (which_alternative == 1)
  if (which_alternative == 1)
    {
    {
      rtx ops[3];
      rtx ops[3];
      ops[0] = operands[2];
      ops[0] = operands[2];
      ops[1] = XEXP (operands[0], 0);
      ops[1] = XEXP (operands[0], 0);
      ops[2] = gen_label_rtx ();
      ops[2] = gen_label_rtx ();
      output_asm_insn (\".relax\\t%l2\", ops);
      output_asm_insn (\".relax\\t%l2\", ops);
      m68hc11_gen_movhi (insn, ops);
      m68hc11_gen_movhi (insn, ops);
      output_asm_insn (\"bclr\\t0,%2, %1\", operands);
      output_asm_insn (\"bclr\\t0,%2, %1\", operands);
      (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
      (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
                                 CODE_LABEL_NUMBER (ops[2]));
                                 CODE_LABEL_NUMBER (ops[2]));
      return \"\";
      return \"\";
    }
    }
  return \"bclr\\t%b0, %1\";
  return \"bclr\\t%b0, %1\";
}")
}")
(define_insn "*andqi3_const"
(define_insn "*andqi3_const"
  [(set (match_operand:QI 0 "reg_or_some_mem_operand" "=R,d,?*A*q")
  [(set (match_operand:QI 0 "reg_or_some_mem_operand" "=R,d,?*A*q")
        (and:QI (match_operand:QI 1 "reg_or_some_mem_operand" "%0,0,0")
        (and:QI (match_operand:QI 1 "reg_or_some_mem_operand" "%0,0,0")
                (match_operand:QI 2 "const_int_operand" "")))]
                (match_operand:QI 2 "const_int_operand" "")))]
  ""
  ""
  "*
  "*
{
{
  int val = INTVAL (operands[2]) & 0x0FF;
  int val = INTVAL (operands[2]) & 0x0FF;
  if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
  if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
    return \"#\";
    return \"#\";
  if (val == 0x0ff)
  if (val == 0x0ff)
    {
    {
      cc_status = cc_prev_status;
      cc_status = cc_prev_status;
      return \"\";
      return \"\";
    }
    }
  if (!H_REG_P (operands[0]))
  if (!H_REG_P (operands[0]))
    {
    {
      rtx ops[2];
      rtx ops[2];
      ops[0] = operands[0];
      ops[0] = operands[0];
      ops[1] = GEN_INT ((~val) & 0x0FF);
      ops[1] = GEN_INT ((~val) & 0x0FF);
      output_asm_insn (\"bclr\\t%b0, %b1\", ops);
      output_asm_insn (\"bclr\\t%b0, %b1\", ops);
      return \"\";
      return \"\";
    }
    }
  if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
  if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
    return \"andb\\t%b2\";
    return \"andb\\t%b2\";
  else if (DA_REG_P (operands[0]))
  else if (DA_REG_P (operands[0]))
    return \"anda\\t%b2\";
    return \"anda\\t%b2\";
  else
  else
    fatal_insn (\"Invalid operand in the instruction\", insn);
    fatal_insn (\"Invalid operand in the instruction\", insn);
}")
}")
(define_insn "*andqi3_gen"
(define_insn "*andqi3_gen"
  [(set (match_operand:QI 0 "register_operand" "=d,d,d,?*A,?*A,!*q")
  [(set (match_operand:QI 0 "register_operand" "=d,d,d,?*A,?*A,!*q")
        (and:QI (match_operand:QI 1 "general_operand" "%0,0,0,0,0,0")
        (and:QI (match_operand:QI 1 "general_operand" "%0,0,0,0,0,0")
             (match_operand:QI 2 "general_operand" "mi,!*u,?*A,!*um,?*A*d,!*um*A")))]
             (match_operand:QI 2 "general_operand" "mi,!*u,?*A,!*um,?*A*d,!*um*A")))]
  ""
  ""
  "*
  "*
{
{
  if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
  if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
    return \"#\";
    return \"#\";
  if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
  if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
    return \"andb\\t%b2\";
    return \"andb\\t%b2\";
  else if (DA_REG_P (operands[0]))
  else if (DA_REG_P (operands[0]))
    return \"anda\\t%b2\";
    return \"anda\\t%b2\";
  else
  else
    fatal_insn (\"Invalid operand in the instruction\", insn);
    fatal_insn (\"Invalid operand in the instruction\", insn);
}")
}")
;;--------------------------------------------------------------------
;;--------------------------------------------------------------------
;;- Bit set or instructions.
;;- Bit set or instructions.
;;--------------------------------------------------------------------
;;--------------------------------------------------------------------
(define_insn_and_split "iordi3"
(define_insn_and_split "iordi3"
  [(set (match_operand:DI 0 "reg_or_some_mem_operand" "=m,u")
  [(set (match_operand:DI 0 "reg_or_some_mem_operand" "=m,u")
        (ior:DI (match_operand:DI 1 "reg_or_some_mem_operand" "%imu,imu")
        (ior:DI (match_operand:DI 1 "reg_or_some_mem_operand" "%imu,imu")
                (match_operand:DI 2 "general_operand" "imu,imu")))
                (match_operand:DI 2 "general_operand" "imu,imu")))
   (clobber (match_scratch:HI 3 "=d,d"))]
   (clobber (match_scratch:HI 3 "=d,d"))]
  ""
  ""
  "#"
  "#"
  "reload_completed"
  "reload_completed"
  [(const_int 0)]
  [(const_int 0)]
  "m68hc11_split_logical (SImode, IOR, operands);
  "m68hc11_split_logical (SImode, IOR, operands);
   DONE;")
   DONE;")
(define_insn_and_split "iorsi3"
(define_insn_and_split "iorsi3"
  [(set (match_operand:SI 0 "register_operand" "=D,!u")
  [(set (match_operand:SI 0 "register_operand" "=D,!u")
        (ior:SI (match_operand:SI 1 "register_operand" "%0,0")
        (ior:SI (match_operand:SI 1 "register_operand" "%0,0")
                (match_operand:SI 2 "general_operand" "Dimu,imu")))
                (match_operand:SI 2 "general_operand" "Dimu,imu")))
   (clobber (match_scratch:HI 3 "=X,d"))]
   (clobber (match_scratch:HI 3 "=X,d"))]
  ""
  ""
  "#"
  "#"
  "reload_completed"
  "reload_completed"
  [(const_int 0)]
  [(const_int 0)]
  "m68hc11_split_logical (HImode, IOR, operands);
  "m68hc11_split_logical (HImode, IOR, operands);
   DONE;")
   DONE;")
(define_expand "iorhi3"
(define_expand "iorhi3"
  [(set (match_operand:HI 0 "register_operand" "")
  [(set (match_operand:HI 0 "register_operand" "")
        (ior:HI (match_operand:HI 1 "register_operand" "")
        (ior:HI (match_operand:HI 1 "register_operand" "")
                (match_operand:HI 2 "splitable_operand" "")))]
                (match_operand:HI 2 "splitable_operand" "")))]
  ""
  ""
  "")
  "")
(define_insn "*iorhi3_mem"
(define_insn "*iorhi3_mem"
  [(set (match_operand:HI 0 "memory_operand" "=R,Q")
  [(set (match_operand:HI 0 "memory_operand" "=R,Q")
        (ior:HI (match_dup 0)
        (ior:HI (match_dup 0)
                (match_operand:HI 1 "const_int_operand" "")))
                (match_operand:HI 1 "const_int_operand" "")))
   (clobber (match_scratch:HI 2 "=X,xy"))]
   (clobber (match_scratch:HI 2 "=X,xy"))]
  "TARGET_RELAX && !TARGET_M6812"
  "TARGET_RELAX && !TARGET_M6812"
  "*
  "*
{
{
  int val = INTVAL (operands[1]) & 0x0FFFF;
  int val = INTVAL (operands[1]) & 0x0FFFF;
  if (val == 0)
  if (val == 0)
    {
    {
      cc_status = cc_prev_status;
      cc_status = cc_prev_status;
      return \"\";
      return \"\";
    }
    }
  CC_STATUS_INIT;
  CC_STATUS_INIT;
  if (which_alternative == 1)
  if (which_alternative == 1)
    {
    {
      rtx ops[3];
      rtx ops[3];
      ops[0] = operands[2];
      ops[0] = operands[2];
      ops[1] = XEXP (operands[0], 0);
      ops[1] = XEXP (operands[0], 0);
      ops[2] = gen_label_rtx ();
      ops[2] = gen_label_rtx ();
      output_asm_insn (\".relax\\t%l2\", ops);
      output_asm_insn (\".relax\\t%l2\", ops);
      m68hc11_gen_movhi (insn, ops);
      m68hc11_gen_movhi (insn, ops);
      if ((val & 0x0FF) != 0)
      if ((val & 0x0FF) != 0)
        output_asm_insn (\"bset\\t1,%2, %b1\", operands);
        output_asm_insn (\"bset\\t1,%2, %b1\", operands);
      if ((val & 0x0FF00) != 0)
      if ((val & 0x0FF00) != 0)
        output_asm_insn (\"bset\\t0,%2, %h1\", operands);
        output_asm_insn (\"bset\\t0,%2, %h1\", operands);
      (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
      (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
                                 CODE_LABEL_NUMBER (ops[2]));
                                 CODE_LABEL_NUMBER (ops[2]));
      return \"\";
      return \"\";
    }
    }
  if ((val & 0x0FF) != 0)
  if ((val & 0x0FF) != 0)
    output_asm_insn (\"bset\\t%b0, %b1\", operands);
    output_asm_insn (\"bset\\t%b0, %b1\", operands);
  if ((val & 0x0FF00) != 0)
  if ((val & 0x0FF00) != 0)
    output_asm_insn (\"bset\\t%h0, %h1\", operands);
    output_asm_insn (\"bset\\t%h0, %h1\", operands);
  return \"\";
  return \"\";
}")
}")
(define_insn "*iorhi3_const"
(define_insn "*iorhi3_const"
  [(set (match_operand:HI 0 "reg_or_some_mem_operand" "=R,d,?*A")
  [(set (match_operand:HI 0 "reg_or_some_mem_operand" "=R,d,?*A")
        (ior:HI (match_operand:HI 1 "reg_or_some_mem_operand" "%0,0,0")
        (ior:HI (match_operand:HI 1 "reg_or_some_mem_operand" "%0,0,0")
                (match_operand:HI 2 "const_int_operand" "")))]
                (match_operand:HI 2 "const_int_operand" "")))]
  ""
  ""
  "*
  "*
{
{
  int val = INTVAL (operands[2]) & 0x0FFFF;
  int val = INTVAL (operands[2]) & 0x0FFFF;
  if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
  if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
    return \"#\";
    return \"#\";
  if (val == 0)
  if (val == 0)
    {
    {
      cc_status = cc_prev_status;
      cc_status = cc_prev_status;
      return \"\";
      return \"\";
    }
    }
  if ((val & 0x0FF) != 0)
  if ((val & 0x0FF) != 0)
    {
    {
      if (!H_REG_P (operands[0]))
      if (!H_REG_P (operands[0]))
        output_asm_insn (\"bset\\t%b0, %b2\", operands);
        output_asm_insn (\"bset\\t%b0, %b2\", operands);
      else
      else
        output_asm_insn (\"orab\\t%b2\", operands);
        output_asm_insn (\"orab\\t%b2\", operands);
    }
    }
  if ((val & 0x0FF00) != 0)
  if ((val & 0x0FF00) != 0)
    {
    {
      if (!H_REG_P (operands[0]))
      if (!H_REG_P (operands[0]))
         output_asm_insn (\"bset\\t%h0, %h2\", operands);
         output_asm_insn (\"bset\\t%h0, %h2\", operands);
      else
      else
         output_asm_insn (\"oraa\\t%h2\", operands);
         output_asm_insn (\"oraa\\t%h2\", operands);
    }
    }
  CC_STATUS_INIT;
  CC_STATUS_INIT;
  return \"\";
  return \"\";
}")
}")
(define_insn "*iorhi3_gen"
(define_insn "*iorhi3_gen"
  [(set (match_operand:HI 0 "register_operand" "=d,d,!*A")
  [(set (match_operand:HI 0 "register_operand" "=d,d,!*A")
        (ior:HI (match_operand:HI 1 "splitable_operand" "%0,0,0")
        (ior:HI (match_operand:HI 1 "splitable_operand" "%0,0,0")
                (match_operand:HI 2 "splitable_operand" "mi,!u*A,!um*Ai")))]
                (match_operand:HI 2 "splitable_operand" "mi,!u*A,!um*Ai")))]
  ""
  ""
  "*
  "*
{
{
  if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
  if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
    return \"#\";
    return \"#\";
  CC_STATUS_INIT;
  CC_STATUS_INIT;
  return \"oraa\\t%h2\\n\\torab\\t%b2\";
  return \"oraa\\t%h2\\n\\torab\\t%b2\";
}")
}")
(define_expand "iorqi3"
(define_expand "iorqi3"
  [(set (match_operand:QI 0 "register_operand" "")
  [(set (match_operand:QI 0 "register_operand" "")
        (ior:QI (match_operand:QI 1 "register_operand" "")
        (ior:QI (match_operand:QI 1 "register_operand" "")
                (match_operand:QI 2 "general_operand" "")))]
                (match_operand:QI 2 "general_operand" "")))]
  ""
  ""
  "")
  "")
(define_insn "*iorqi3_mem"
(define_insn "*iorqi3_mem"
  [(set (match_operand:QI 0 "memory_operand" "=R,Q")
  [(set (match_operand:QI 0 "memory_operand" "=R,Q")
        (ior:QI (match_dup 0)
        (ior:QI (match_dup 0)
                (match_operand:QI 1 "const_int_operand" "")))
                (match_operand:QI 1 "const_int_operand" "")))
   (clobber (match_scratch:HI 2 "=X,xy"))]
   (clobber (match_scratch:HI 2 "=X,xy"))]
  "TARGET_RELAX && !TARGET_M6812"
  "TARGET_RELAX && !TARGET_M6812"
  "*
  "*
{
{
  int val = INTVAL (operands[1]) & 0x0FF;
  int val = INTVAL (operands[1]) & 0x0FF;
  if (val == 0)
  if (val == 0)
    {
    {
      cc_status = cc_prev_status;
      cc_status = cc_prev_status;
      return \"\";
      return \"\";
    }
    }
  if (which_alternative == 1)
  if (which_alternative == 1)
    {
    {
      rtx ops[3];
      rtx ops[3];
      ops[0] = operands[2];
      ops[0] = operands[2];
      ops[1] = XEXP (operands[0], 0);
      ops[1] = XEXP (operands[0], 0);
      ops[2] = gen_label_rtx ();
      ops[2] = gen_label_rtx ();
      output_asm_insn (\".relax\\t%l2\", ops);
      output_asm_insn (\".relax\\t%l2\", ops);
      m68hc11_gen_movhi (insn, ops);
      m68hc11_gen_movhi (insn, ops);
      output_asm_insn (\"bset\\t0,%2, %1\", operands);
      output_asm_insn (\"bset\\t0,%2, %1\", operands);
      (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
      (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
                                 CODE_LABEL_NUMBER (ops[2]));
                                 CODE_LABEL_NUMBER (ops[2]));
      return \"\";
      return \"\";
    }
    }
  return \"bset\\t%b0, %1\";
  return \"bset\\t%b0, %1\";
}")
}")
(define_insn "*iorqi3_const"
(define_insn "*iorqi3_const"
  [(set (match_operand:QI 0 "reg_or_some_mem_operand" "=R,d,?*A*q")
  [(set (match_operand:QI 0 "reg_or_some_mem_operand" "=R,d,?*A*q")
        (ior:QI (match_operand:QI 1 "reg_or_some_mem_operand" "%0,0,0")
        (ior:QI (match_operand:QI 1 "reg_or_some_mem_operand" "%0,0,0")
                (match_operand:QI 2 "const_int_operand" "")))]
                (match_operand:QI 2 "const_int_operand" "")))]
  ""
  ""
  "*
  "*
{
{
  int val = INTVAL (operands[2]) & 0x0FF;
  int val = INTVAL (operands[2]) & 0x0FF;
  if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
  if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
    return \"#\";
    return \"#\";
  if (val == 0)
  if (val == 0)
    {
    {
      cc_status = cc_prev_status;
      cc_status = cc_prev_status;
      return \"\";
      return \"\";
    }
    }
  if (!H_REG_P (operands[0]))
  if (!H_REG_P (operands[0]))
    {
    {
      return \"bset\\t%b0, %2\";
      return \"bset\\t%b0, %2\";
    }
    }
  if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
  if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
    return \"orab\\t%b2\";
    return \"orab\\t%b2\";
  else if (DA_REG_P (operands[0]))
  else if (DA_REG_P (operands[0]))
    return \"oraa\\t%b2\";
    return \"oraa\\t%b2\";
  else
  else
    fatal_insn (\"Invalid operand in the instruction\", insn);
    fatal_insn (\"Invalid operand in the instruction\", insn);
}")
}")
(define_insn "*iorqi3_gen"
(define_insn "*iorqi3_gen"
  [(set (match_operand:QI 0 "register_operand" "=d,d,d,?*A,?*A,!*q")
  [(set (match_operand:QI 0 "register_operand" "=d,d,d,?*A,?*A,!*q")
        (ior:QI (match_operand:QI 1 "general_operand" "%0,0,0,0,0,0")
        (ior:QI (match_operand:QI 1 "general_operand" "%0,0,0,0,0,0")
             (match_operand:QI 2 "general_operand" "mi,!*u,!*A,!*um,?*A*d,!*um*A")))]
             (match_operand:QI 2 "general_operand" "mi,!*u,!*A,!*um,?*A*d,!*um*A")))]
  ""
  ""
  "*
  "*
{
{
  if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
  if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
    return \"#\";
    return \"#\";
  if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
  if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
    return \"orab\\t%b2\";
    return \"orab\\t%b2\";
  else if (DA_REG_P (operands[0]))
  else if (DA_REG_P (operands[0]))
    return \"oraa\\t%b2\";
    return \"oraa\\t%b2\";
  else
  else
    fatal_insn (\"Invalid operand in the instruction\", insn);
    fatal_insn (\"Invalid operand in the instruction\", insn);
}")
}")
;;--------------------------------------------------------------------
;;--------------------------------------------------------------------
;;- xor instructions.
;;- xor instructions.
;;--------------------------------------------------------------------
;;--------------------------------------------------------------------
(define_insn_and_split "xordi3"
(define_insn_and_split "xordi3"
  [(set (match_operand:DI 0 "reg_or_some_mem_operand" "=m,u")
  [(set (match_operand:DI 0 "reg_or_some_mem_operand" "=m,u")
        (xor:DI (match_operand:DI 1 "reg_or_some_mem_operand" "%imu,imu")
        (xor:DI (match_operand:DI 1 "reg_or_some_mem_operand" "%imu,imu")
                (match_operand:DI 2 "general_operand" "imu,imu")))
                (match_operand:DI 2 "general_operand" "imu,imu")))
   (clobber (match_scratch:HI 3 "=d,d"))]
   (clobber (match_scratch:HI 3 "=d,d"))]
  ""
  ""
  "#"
  "#"
  "reload_completed"
  "reload_completed"
  [(const_int 0)]
  [(const_int 0)]
  "m68hc11_split_logical (SImode, XOR, operands);
  "m68hc11_split_logical (SImode, XOR, operands);
   DONE;")
   DONE;")
(define_insn_and_split "xorsi3"
(define_insn_and_split "xorsi3"
  [(set (match_operand:SI 0 "register_operand" "=D,!u")
  [(set (match_operand:SI 0 "register_operand" "=D,!u")
        (xor:SI (match_operand:SI 1 "register_operand" "%0,0")
        (xor:SI (match_operand:SI 1 "register_operand" "%0,0")
                (match_operand:SI 2 "general_operand" "Dimu,imu")))
                (match_operand:SI 2 "general_operand" "Dimu,imu")))
   (clobber (match_scratch:HI 3 "=X,d"))]
   (clobber (match_scratch:HI 3 "=X,d"))]
  ""
  ""
  "#"
  "#"
  "reload_completed"
  "reload_completed"
  [(const_int 0)]
  [(const_int 0)]
  "m68hc11_split_logical (HImode, XOR, operands);
  "m68hc11_split_logical (HImode, XOR, operands);
   DONE;")
   DONE;")
(define_insn "xorhi3"
(define_insn "xorhi3"
  [(set (match_operand:HI 0 "register_operand" "=d,d,!*A")
  [(set (match_operand:HI 0 "register_operand" "=d,d,!*A")
        (xor:HI (match_operand:HI 1 "splitable_operand" "%0,0,0")
        (xor:HI (match_operand:HI 1 "splitable_operand" "%0,0,0")
                (match_operand:HI 2 "splitable_operand" "im,!u*A,!ium*A")))]
                (match_operand:HI 2 "splitable_operand" "im,!u*A,!ium*A")))]
  ""
  ""
  "*
  "*
{
{
  if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
  if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
    return \"#\";
    return \"#\";
  if (GET_CODE (operands[2]) == CONST_INT)
  if (GET_CODE (operands[2]) == CONST_INT)
    {
    {
      int val = INTVAL (operands[2]) & 0x0FFFF;
      int val = INTVAL (operands[2]) & 0x0FFFF;
      if (val == 0)
      if (val == 0)
        {
        {
          cc_status = cc_prev_status;
          cc_status = cc_prev_status;
          return \"\";
          return \"\";
        }
        }
      if ((val & 0x0FF) != 0)
      if ((val & 0x0FF) != 0)
        {
        {
          output_asm_insn (\"eorb\\t%b2\", operands);
          output_asm_insn (\"eorb\\t%b2\", operands);
        }
        }
      else if ((val & 0x0FF) == 0x0FF)
      else if ((val & 0x0FF) == 0x0FF)
        {
        {
          output_asm_insn (\"comb\", operands);
          output_asm_insn (\"comb\", operands);
        }
        }
      if ((val & 0x0FF00) != 0)
      if ((val & 0x0FF00) != 0)
        {
        {
          output_asm_insn (\"eora\\t%h2\", operands);
          output_asm_insn (\"eora\\t%h2\", operands);
        }
        }
      else if ((val & 0x0FF00) == 0x0FF00)
      else if ((val & 0x0FF00) == 0x0FF00)
        {
        {
          output_asm_insn (\"coma\", operands);
          output_asm_insn (\"coma\", operands);
        }
        }
      CC_STATUS_INIT;
      CC_STATUS_INIT;
      return \"\";
      return \"\";
    }
    }
  CC_STATUS_INIT;
  CC_STATUS_INIT;
  return \"eora\\t%h2\\n\\teorb\\t%b2\";
  return \"eora\\t%h2\\n\\teorb\\t%b2\";
}")
}")
(define_insn "xorqi3"
(define_insn "xorqi3"
  [(set (match_operand:QI 0 "register_operand" "=d,d,d,?*A,?*A,!*q")
  [(set (match_operand:QI 0 "register_operand" "=d,d,d,?*A,?*A,!*q")
        (xor:QI (match_operand:QI 1 "general_operand" "%0,0,0,0,0,0")
        (xor:QI (match_operand:QI 1 "general_operand" "%0,0,0,0,0,0")
             (match_operand:QI 2 "general_operand" "im,!*u,!*A,!i*um,?*A*d,!i*um*A")))]
             (match_operand:QI 2 "general_operand" "im,!*u,!*A,!i*um,?*A*d,!i*um*A")))]
  ""
  ""
  "*
  "*
{
{
  if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
  if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
    return \"#\";
    return \"#\";
  if (GET_CODE (operands[2]) == CONST_INT)
  if (GET_CODE (operands[2]) == CONST_INT)
    {
    {
      int val = INTVAL (operands[2]) & 0x0FF;
      int val = INTVAL (operands[2]) & 0x0FF;
      if (val == 0)
      if (val == 0)
        {
        {
          cc_status = cc_prev_status;
          cc_status = cc_prev_status;
          return \"\";
          return \"\";
        }
        }
      if (val == 0x0FF)
      if (val == 0x0FF)
        {
        {
          if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
          if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
            return \"comb\";
            return \"comb\";
          else
          else
            return \"coma\";
            return \"coma\";
        }
        }
    }
    }
  if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
  if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
    return \"eorb\\t%b2\";
    return \"eorb\\t%b2\";
  else if (DA_REG_P (operands[0]))
  else if (DA_REG_P (operands[0]))
    return \"eora\\t%b2\";
    return \"eora\\t%b2\";
  else
  else
    fatal_insn (\"Invalid operand in the instruction\", insn);
    fatal_insn (\"Invalid operand in the instruction\", insn);
}")
}")
;;--------------------------------------------------------------------
;;--------------------------------------------------------------------
;;- Bit set or instructions.
;;- Bit set or instructions.
;;--------------------------------------------------------------------
;;--------------------------------------------------------------------
(define_insn_and_split "*logicalsi3_zexthi"
(define_insn_and_split "*logicalsi3_zexthi"
  [(set (match_operand:SI 0 "register_operand" "=D")
  [(set (match_operand:SI 0 "register_operand" "=D")
        (match_operator:SI 3 "m68hc11_logical_operator"
        (match_operator:SI 3 "m68hc11_logical_operator"
                [(zero_extend:SI
                [(zero_extend:SI
                     (match_operand:HI 1 "general_operand" "imudA"))
                     (match_operand:HI 1 "general_operand" "imudA"))
                 (match_operand:SI 2 "general_operand" "Dimu")]))]
                 (match_operand:SI 2 "general_operand" "Dimu")]))]
  ""
  ""
  "#"
  "#"
  "reload_completed"
  "reload_completed"
  [(set (reg:HI D_REGNUM) (match_dup 4))
  [(set (reg:HI D_REGNUM) (match_dup 4))
   (set (reg:HI D_REGNUM) (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 5)]))
   (set (reg:HI D_REGNUM) (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 5)]))
   (set (reg:HI X_REGNUM) (match_dup 6))]
   (set (reg:HI X_REGNUM) (match_dup 6))]
  "PUT_MODE (operands[3], HImode);
  "PUT_MODE (operands[3], HImode);
   if (X_REG_P (operands[2]))
   if (X_REG_P (operands[2]))
     {
     {
       operands[5] = operands[1];
       operands[5] = operands[1];
       /* Make all the (set (REG:x) (REG:y)) a nop set.  */
       /* Make all the (set (REG:x) (REG:y)) a nop set.  */
       operands[4] = gen_rtx_REG (HImode, HARD_D_REGNUM);
       operands[4] = gen_rtx_REG (HImode, HARD_D_REGNUM);
       operands[6] = gen_rtx_REG (HImode, HARD_X_REGNUM);
       operands[6] = gen_rtx_REG (HImode, HARD_X_REGNUM);
     }
     }
   else
   else
     {
     {
       operands[4] = operands[1];
       operands[4] = operands[1];
       operands[5] = m68hc11_gen_lowpart (HImode, operands[2]);
       operands[5] = m68hc11_gen_lowpart (HImode, operands[2]);
       operands[6] = m68hc11_gen_highpart (HImode, operands[2]);
       operands[6] = m68hc11_gen_highpart (HImode, operands[2]);
     }
     }
   /* For an AND, make sure the high 16-bit part is cleared.  */
   /* For an AND, make sure the high 16-bit part is cleared.  */
   if (GET_CODE (operands[3]) == AND)
   if (GET_CODE (operands[3]) == AND)
     {
     {
       operands[6] = const0_rtx;
       operands[6] = const0_rtx;
     }
     }
   ")
   ")
(define_insn_and_split "*logicalsi3_zextqi"
(define_insn_and_split "*logicalsi3_zextqi"
  [(set (match_operand:SI 0 "register_operand" "=D,D,D")
  [(set (match_operand:SI 0 "register_operand" "=D,D,D")
        (match_operator:SI 3 "m68hc11_logical_operator"
        (match_operator:SI 3 "m68hc11_logical_operator"
                [(zero_extend:SI
                [(zero_extend:SI
                     (match_operand:QI 1 "general_operand" "d,*A,imu"))
                     (match_operand:QI 1 "general_operand" "d,*A,imu"))
                 (match_operand:SI 2 "general_operand" "imu,imu,0")]))]
                 (match_operand:SI 2 "general_operand" "imu,imu,0")]))]
  ""
  ""
  "#"
  "#"
  "z_replacement_completed == 2"
  "z_replacement_completed == 2"
  [(set (reg:QI A_REGNUM) (match_dup 4))
  [(set (reg:QI A_REGNUM) (match_dup 4))
   (set (reg:QI D_REGNUM) (match_dup 7))
   (set (reg:QI D_REGNUM) (match_dup 7))
   (set (reg:QI B_REGNUM) (match_op_dup 3 [(reg:QI B_REGNUM) (match_dup 5)]))
   (set (reg:QI B_REGNUM) (match_op_dup 3 [(reg:QI B_REGNUM) (match_dup 5)]))
   (set (reg:HI X_REGNUM) (match_dup 6))]
   (set (reg:HI X_REGNUM) (match_dup 6))]
  "PUT_MODE (operands[3], QImode);
  "PUT_MODE (operands[3], QImode);
   if (X_REG_P (operands[2]))
   if (X_REG_P (operands[2]))
     {
     {
       operands[5] = operands[1];
       operands[5] = operands[1];
       /* Make all the (set (REG:x) (REG:y)) a nop set.  */
       /* Make all the (set (REG:x) (REG:y)) a nop set.  */
       operands[4] = gen_rtx_REG (QImode, HARD_A_REGNUM);
       operands[4] = gen_rtx_REG (QImode, HARD_A_REGNUM);
       operands[7] = gen_rtx_REG (QImode, HARD_D_REGNUM);
       operands[7] = gen_rtx_REG (QImode, HARD_D_REGNUM);
       operands[6] = gen_rtx_REG (HImode, HARD_X_REGNUM);
       operands[6] = gen_rtx_REG (HImode, HARD_X_REGNUM);
     }
     }
   else
   else
     {
     {
       operands[4] = m68hc11_gen_lowpart (HImode, operands[2]);
       operands[4] = m68hc11_gen_lowpart (HImode, operands[2]);
       operands[7] = operands[1];
       operands[7] = operands[1];
       operands[5] = m68hc11_gen_lowpart (QImode, operands[4]);
       operands[5] = m68hc11_gen_lowpart (QImode, operands[4]);
       operands[4] = m68hc11_gen_highpart (QImode, operands[4]);
       operands[4] = m68hc11_gen_highpart (QImode, operands[4]);
       operands[6] = m68hc11_gen_highpart (HImode, operands[2]);
       operands[6] = m68hc11_gen_highpart (HImode, operands[2]);
     }
     }
   /* For an AND, make sure the high 24-bit part is cleared.  */
   /* For an AND, make sure the high 24-bit part is cleared.  */
   if (GET_CODE (operands[3]) == AND)
   if (GET_CODE (operands[3]) == AND)
     {
     {
       operands[4] = const0_rtx;
       operands[4] = const0_rtx;
       operands[6] = const0_rtx;
       operands[6] = const0_rtx;
     }
     }
   ")
   ")
(define_insn_and_split "*logicalhi3_zexthi_ashift8"
(define_insn_and_split "*logicalhi3_zexthi_ashift8"
  [(set (match_operand:HI 0 "register_operand" "=d")
  [(set (match_operand:HI 0 "register_operand" "=d")
        (match_operator:HI 3 "m68hc11_logical_operator"
        (match_operator:HI 3 "m68hc11_logical_operator"
                [(zero_extend:HI
                [(zero_extend:HI
                     (match_operand:QI 1 "general_operand" "imud*A"))
                     (match_operand:QI 1 "general_operand" "imud*A"))
                 (ashift:HI
                 (ashift:HI
                     (match_operand:HI 2 "general_operand" "imud*A")
                     (match_operand:HI 2 "general_operand" "imud*A")
                     (const_int 8))]))]
                     (const_int 8))]))]
  ""
  ""
  "#"
  "#"
  "z_replacement_completed == 2"
  "z_replacement_completed == 2"
  [(set (reg:QI A_REGNUM) (match_dup 4))
  [(set (reg:QI A_REGNUM) (match_dup 4))
   (set (reg:QI B_REGNUM) (match_dup 5))]
   (set (reg:QI B_REGNUM) (match_dup 5))]
  "
  "
   if (GET_CODE (operands[3]) == AND)
   if (GET_CODE (operands[3]) == AND)
     {
     {
       emit_insn (gen_movhi (operands[0], const0_rtx));
       emit_insn (gen_movhi (operands[0], const0_rtx));
       DONE;
       DONE;
     }
     }
   else
   else
     {
     {
       operands[5] = operands[1];
       operands[5] = operands[1];
       if (D_REG_P (operands[2]))
       if (D_REG_P (operands[2]))
         {
         {
           operands[4] = gen_rtx_REG (QImode, HARD_B_REGNUM);
           operands[4] = gen_rtx_REG (QImode, HARD_B_REGNUM);
         }
         }
       else
       else
         {
         {
           operands[4] = m68hc11_gen_lowpart (QImode, operands[2]);
           operands[4] = m68hc11_gen_lowpart (QImode, operands[2]);
         }
         }
     }
     }
  ")
  ")
(define_insn_and_split "*logicalhi3_zexthi"
(define_insn_and_split "*logicalhi3_zexthi"
  [(set (match_operand:HI 0 "register_operand" "=d,d")
  [(set (match_operand:HI 0 "register_operand" "=d,d")
        (match_operator:HI 3 "m68hc11_logical_operator"
        (match_operator:HI 3 "m68hc11_logical_operator"
                [(zero_extend:HI
                [(zero_extend:HI
                     (match_operand:QI 1 "general_operand" "imd*A,?u"))
                     (match_operand:QI 1 "general_operand" "imd*A,?u"))
                 (match_operand:HI 2 "general_operand" "dim,?dimu")]))]
                 (match_operand:HI 2 "general_operand" "dim,?dimu")]))]
  ""
  ""
  "#"
  "#"
  "z_replacement_completed == 2"
  "z_replacement_completed == 2"
  [(set (reg:QI B_REGNUM) (match_dup 6))
  [(set (reg:QI B_REGNUM) (match_dup 6))
   (set (reg:QI A_REGNUM) (match_dup 4))
   (set (reg:QI A_REGNUM) (match_dup 4))
   (set (reg:QI B_REGNUM) (match_op_dup 3 [(reg:QI B_REGNUM) (match_dup 5)]))]
   (set (reg:QI B_REGNUM) (match_op_dup 3 [(reg:QI B_REGNUM) (match_dup 5)]))]
  "
  "
   PUT_MODE (operands[3], QImode);
   PUT_MODE (operands[3], QImode);
   if (D_REG_P (operands[2]))
   if (D_REG_P (operands[2]))
     {
     {
       operands[4] = gen_rtx_REG (QImode, HARD_A_REGNUM);
       operands[4] = gen_rtx_REG (QImode, HARD_A_REGNUM);
       operands[5] = operands[1];
       operands[5] = operands[1];
       operands[6] = gen_rtx_REG (QImode, HARD_B_REGNUM);
       operands[6] = gen_rtx_REG (QImode, HARD_B_REGNUM);
     }
     }
   else
   else
     {
     {
       operands[4] = m68hc11_gen_highpart (QImode, operands[2]);
       operands[4] = m68hc11_gen_highpart (QImode, operands[2]);
       operands[5] = m68hc11_gen_lowpart (QImode, operands[2]);
       operands[5] = m68hc11_gen_lowpart (QImode, operands[2]);
       if (D_REG_P (operands[1]))
       if (D_REG_P (operands[1]))
         operands[6] = gen_rtx_REG (QImode, HARD_B_REGNUM);
         operands[6] = gen_rtx_REG (QImode, HARD_B_REGNUM);
       else
       else
         operands[6] = operands[1];
         operands[6] = operands[1];
     }
     }
   /* For an AND, make sure the high 8-bit part is cleared.  */
   /* For an AND, make sure the high 8-bit part is cleared.  */
   if (GET_CODE (operands[3]) == AND)
   if (GET_CODE (operands[3]) == AND)
     {
     {
       operands[4] = const0_rtx;
       operands[4] = const0_rtx;
     }
     }
  ")
  ")
(define_insn_and_split "*logicalsi3_silshr16"
(define_insn_and_split "*logicalsi3_silshr16"
  [(set (match_operand:SI 0 "register_operand" "=D,D,D,?D")
  [(set (match_operand:SI 0 "register_operand" "=D,D,D,?D")
          (match_operator:SI 3 "m68hc11_logical_operator"
          (match_operator:SI 3 "m68hc11_logical_operator"
              [(lshiftrt:SI
              [(lshiftrt:SI
                   (match_operand:SI 1 "general_operand" "uim,uim,0,0")
                   (match_operand:SI 1 "general_operand" "uim,uim,0,0")
                   (const_int 16))
                   (const_int 16))
                (match_operand:SI 2 "general_operand" "uim,0,uim,0")]))]
                (match_operand:SI 2 "general_operand" "uim,0,uim,0")]))]
  ""
  ""
  "#"
  "#"
  "reload_completed"
  "reload_completed"
  [(set (reg:HI D_REGNUM) (match_dup 4))
  [(set (reg:HI D_REGNUM) (match_dup 4))
   (set (reg:HI D_REGNUM) (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 5)]))
   (set (reg:HI D_REGNUM) (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 5)]))
   (set (reg:HI X_REGNUM) (match_dup 6))]
   (set (reg:HI X_REGNUM) (match_dup 6))]
  "operands[5] = m68hc11_gen_highpart (HImode, operands[1]);
  "operands[5] = m68hc11_gen_highpart (HImode, operands[1]);
   if (X_REG_P (operands[2]))
   if (X_REG_P (operands[2]))
     {
     {
       operands[4] = gen_rtx_REG (HImode, HARD_D_REGNUM);
       operands[4] = gen_rtx_REG (HImode, HARD_D_REGNUM);
       operands[6] = gen_rtx_REG (HImode, HARD_X_REGNUM);
       operands[6] = gen_rtx_REG (HImode, HARD_X_REGNUM);
     }
     }
   else
   else
     {
     {
       operands[4] = m68hc11_gen_lowpart (HImode, operands[2]);
       operands[4] = m68hc11_gen_lowpart (HImode, operands[2]);
       operands[6] = m68hc11_gen_highpart (HImode, operands[2]);
       operands[6] = m68hc11_gen_highpart (HImode, operands[2]);
     }
     }
   PUT_MODE (operands[3], HImode);
   PUT_MODE (operands[3], HImode);
   /* For an AND, make sure the high 16-bit part is cleared.  */
   /* For an AND, make sure the high 16-bit part is cleared.  */
   if (GET_CODE (operands[3]) == AND)
   if (GET_CODE (operands[3]) == AND)
     {
     {
       operands[6] = const0_rtx;
       operands[6] = const0_rtx;
     }
     }
")
")
(define_insn_and_split "*logicalsi3_silshl16"
(define_insn_and_split "*logicalsi3_silshl16"
  [(set (match_operand:SI 0 "register_operand" "=D,D")
  [(set (match_operand:SI 0 "register_operand" "=D,D")
          (match_operator:SI 3 "m68hc11_logical_operator"
          (match_operator:SI 3 "m68hc11_logical_operator"
              [(ashift:SI
              [(ashift:SI
                   (match_operand:SI 1 "general_operand" "uim,?D")
                   (match_operand:SI 1 "general_operand" "uim,?D")
                   (const_int 16))
                   (const_int 16))
                (match_operand:SI 2 "general_operand" "0,0")]))]
                (match_operand:SI 2 "general_operand" "0,0")]))]
  ""
  ""
  "#"
  "#"
  "z_replacement_completed == 2"
  "z_replacement_completed == 2"
  [(set (reg:HI X_REGNUM) (match_op_dup 3 [(reg:HI X_REGNUM) (match_dup 4)]))
  [(set (reg:HI X_REGNUM) (match_op_dup 3 [(reg:HI X_REGNUM) (match_dup 4)]))
   (set (reg:HI D_REGNUM) (match_dup 5))]
   (set (reg:HI D_REGNUM) (match_dup 5))]
  "operands[4] = m68hc11_gen_lowpart (HImode, operands[1]);
  "operands[4] = m68hc11_gen_lowpart (HImode, operands[1]);
   PUT_MODE (operands[3], HImode);
   PUT_MODE (operands[3], HImode);
   if (GET_CODE (operands[3]) == AND)
   if (GET_CODE (operands[3]) == AND)
     operands[5] = const0_rtx;
     operands[5] = const0_rtx;
   else
   else
     operands[5] = gen_rtx_REG (HImode, HARD_D_REGNUM);
     operands[5] = gen_rtx_REG (HImode, HARD_D_REGNUM);
   ")
   ")
(define_insn_and_split "*logicalsi3_silshl16_zext"
(define_insn_and_split "*logicalsi3_silshl16_zext"
  [(set (match_operand:SI 0 "register_operand" "=D,D,D")
  [(set (match_operand:SI 0 "register_operand" "=D,D,D")
          (match_operator:SI 3 "m68hc11_logical_operator"
          (match_operator:SI 3 "m68hc11_logical_operator"
              [(ashift:SI
              [(ashift:SI
                  (zero_extend:SI
                  (zero_extend:SI
                     (match_operand:HI 1 "general_operand" "uim,udA,!dA"))
                     (match_operand:HI 1 "general_operand" "uim,udA,!dA"))
                  (const_int 16))
                  (const_int 16))
            (zero_extend:SI (match_operand:HI 2 "general_operand" "uidA,um,!dA"))]))]
            (zero_extend:SI (match_operand:HI 2 "general_operand" "uidA,um,!dA"))]))]
  ""
  ""
  "#"
  "#"
  ;; Must split before z register replacement
  ;; Must split before z register replacement
  "reload_completed"
  "reload_completed"
  [(set (match_dup 4) (match_dup 5))
  [(set (match_dup 4) (match_dup 5))
   (set (match_dup 6) (match_dup 7))]
   (set (match_dup 6) (match_dup 7))]
  "
  "
    /* set (X_REGNUM) (d), set (D_REGNUM) (1) */
    /* set (X_REGNUM) (d), set (D_REGNUM) (1) */
   if (GET_CODE (operands[1]) == HARD_D_REGNUM
   if (GET_CODE (operands[1]) == HARD_D_REGNUM
       && GET_CODE (operands[3]) != AND)
       && GET_CODE (operands[3]) != AND)
     {
     {
       /* This particular case is too early to be split before
       /* This particular case is too early to be split before
          Z register replacement because the cse-reg pass we do
          Z register replacement because the cse-reg pass we do
          does not recognize the 'swap_areg'.  It is ok to handle
          does not recognize the 'swap_areg'.  It is ok to handle
          this case after.  */
          this case after.  */
       if (z_replacement_completed != 2)
       if (z_replacement_completed != 2)
         {
         {
           FAIL;
           FAIL;
         }
         }
       emit_move_insn (gen_rtx_REG (HImode, HARD_X_REGNUM), operands[2]);
       emit_move_insn (gen_rtx_REG (HImode, HARD_X_REGNUM), operands[2]);
       emit_insn (gen_swap_areg (gen_rtx_REG (HImode, HARD_D_REGNUM),
       emit_insn (gen_swap_areg (gen_rtx_REG (HImode, HARD_D_REGNUM),
                                 gen_rtx_REG (HImode, HARD_X_REGNUM)));
                                 gen_rtx_REG (HImode, HARD_X_REGNUM)));
     }
     }
   operands[4] = gen_rtx_REG (HImode, HARD_D_REGNUM);
   operands[4] = gen_rtx_REG (HImode, HARD_D_REGNUM);
   operands[6] = gen_rtx_REG (HImode, HARD_X_REGNUM);
   operands[6] = gen_rtx_REG (HImode, HARD_X_REGNUM);
   operands[5] = operands[2];
   operands[5] = operands[2];
   operands[7] = operands[1];
   operands[7] = operands[1];
   if (GET_CODE (operands[3]) == AND)
   if (GET_CODE (operands[3]) == AND)
     operands[5] = operands[7] = const0_rtx;
     operands[5] = operands[7] = const0_rtx;
   ")
   ")
;;--------------------------------------------------------------------
;;--------------------------------------------------------------------
;; 16-bit Arithmetic and logical operations on X and Y:
;; 16-bit Arithmetic and logical operations on X and Y:
;;
;;
;;      PLUS MINUS AND IOR XOR ASHIFT ASHIFTRT LSHIFTRT ROTATE ROTATERT
;;      PLUS MINUS AND IOR XOR ASHIFT ASHIFTRT LSHIFTRT ROTATE ROTATERT
;;
;;
;; Operations on X or Y registers are split here.  Instructions are
;; Operations on X or Y registers are split here.  Instructions are
;; changed into:
;; changed into:
;;   - xgdx/xgdy instruction pattern,
;;   - xgdx/xgdy instruction pattern,
;;   - The same operation on register D,
;;   - The same operation on register D,
;;   - xgdx/xgdy instruction pattern.
;;   - xgdx/xgdy instruction pattern.
;; This should allow the peephole to merge consecutive xgdx/xgdy instructions.
;; This should allow the peephole to merge consecutive xgdx/xgdy instructions.
;; We also handle the case were the address register is used in both source
;; We also handle the case were the address register is used in both source
;; operands, such as:
;; operands, such as:
;;
;;
;;     (set (REG:HI X) (PLUS:HI (REG:HI X) (mem:HI (REG:HI X))))
;;     (set (REG:HI X) (PLUS:HI (REG:HI X) (mem:HI (REG:HI X))))
;; or
;; or
;;     (set (REG:HI X) (PLUS:HI (REG:HI X) (REG:HI X)))
;;     (set (REG:HI X) (PLUS:HI (REG:HI X) (REG:HI X)))
;;
;;
;;
;;
(define_split
(define_split
  [(set (match_operand:HI 0 "hard_addr_reg_operand" "")
  [(set (match_operand:HI 0 "hard_addr_reg_operand" "")
        (match_operator:HI 3 "m68hc11_arith_operator"
        (match_operator:HI 3 "m68hc11_arith_operator"
            [(match_operand:HI 1 "hard_addr_reg_operand" "")
            [(match_operand:HI 1 "hard_addr_reg_operand" "")
             (match_operand:HI 2 "general_operand" "")]))]
             (match_operand:HI 2 "general_operand" "")]))]
  "z_replacement_completed == 2
  "z_replacement_completed == 2
   /* If we are adding a small constant to X or Y, it's
   /* If we are adding a small constant to X or Y, it's
     better to use one or several inx/iny instructions.  */
     better to use one or several inx/iny instructions.  */
   && !(GET_CODE (operands[3]) == PLUS
   && !(GET_CODE (operands[3]) == PLUS
        && ((TARGET_M6812
        && ((TARGET_M6812
             && (immediate_operand (operands[2], HImode)
             && (immediate_operand (operands[2], HImode)
                 || hard_reg_operand (operands[2], HImode)))
                 || hard_reg_operand (operands[2], HImode)))
            || (GET_CODE (operands[2]) == CONST_INT
            || (GET_CODE (operands[2]) == CONST_INT
                && INTVAL (operands[2]) >= -4
                && INTVAL (operands[2]) >= -4
                && INTVAL (operands[2]) <= 4)))"
                && INTVAL (operands[2]) <= 4)))"
  [(set (match_dup 9) (match_dup 0))
  [(set (match_dup 9) (match_dup 0))
   (set (match_dup 4) (match_dup 5))
   (set (match_dup 4) (match_dup 5))
   (set (match_dup 8) (match_dup 7))
   (set (match_dup 8) (match_dup 7))
   (set (match_dup 0) (match_dup 1))
   (set (match_dup 0) (match_dup 1))
   (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
   (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
              (set (match_dup 0) (reg:HI D_REGNUM))])
              (set (match_dup 0) (reg:HI D_REGNUM))])
   (set (reg:HI D_REGNUM) (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 6)]))
   (set (reg:HI D_REGNUM) (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 6)]))
   (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
   (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
              (set (match_dup 0) (reg:HI D_REGNUM))])]
              (set (match_dup 0) (reg:HI D_REGNUM))])]
  "
  "
   operands[9] = operands[0];
   operands[9] = operands[0];
   /* For 68HC12, push the value on the stack and do the operation
   /* For 68HC12, push the value on the stack and do the operation
      with a pop.  */
      with a pop.  */
   if (TARGET_M6812
   if (TARGET_M6812
       && m68hc11_non_shift_operator (operands[3], HImode)
       && m68hc11_non_shift_operator (operands[3], HImode)
       && (H_REG_P (operands[2])
       && (H_REG_P (operands[2])
           || (m68hc11_small_indexed_indirect_p (operands[2], HImode)
           || (m68hc11_small_indexed_indirect_p (operands[2], HImode)
               && reg_mentioned_p (operands[0], operands[2]))))
               && reg_mentioned_p (operands[0], operands[2]))))
     {
     {
       operands[4] = gen_rtx_MEM (HImode,
       operands[4] = gen_rtx_MEM (HImode,
                              gen_rtx_PRE_DEC (HImode,
                              gen_rtx_PRE_DEC (HImode,
                                       gen_rtx_REG (HImode, HARD_SP_REGNUM)));
                                       gen_rtx_REG (HImode, HARD_SP_REGNUM)));
       operands[6] = gen_rtx_MEM (HImode,
       operands[6] = gen_rtx_MEM (HImode,
                              gen_rtx_POST_INC (HImode,
                              gen_rtx_POST_INC (HImode,
                                       gen_rtx_REG (HImode, HARD_SP_REGNUM)));
                                       gen_rtx_REG (HImode, HARD_SP_REGNUM)));
       operands[5] = operands[2];
       operands[5] = operands[2];
       operands[8] = operands[7] = operands[0];
       operands[8] = operands[7] = operands[0];
     }
     }
   /* Save the operand2 in a temporary location and use it.  */
   /* Save the operand2 in a temporary location and use it.  */
   else if ((H_REG_P (operands[2])
   else if ((H_REG_P (operands[2])
             || reg_mentioned_p  (operands[0], operands[2]))
             || reg_mentioned_p  (operands[0], operands[2]))
            && !(SP_REG_P (operands[2]) && GET_CODE (operands[3]) == PLUS))
            && !(SP_REG_P (operands[2]) && GET_CODE (operands[3]) == PLUS))
     {
     {
       if (GET_CODE (operands[3]) == MINUS
       if (GET_CODE (operands[3]) == MINUS
           && reg_mentioned_p (operands[0], operands[2]))
           && reg_mentioned_p (operands[0], operands[2]))
         {
         {
           operands[9] = gen_rtx_MEM (HImode,
           operands[9] = gen_rtx_MEM (HImode,
                              gen_rtx_PRE_DEC (HImode,
                              gen_rtx_PRE_DEC (HImode,
                                       gen_rtx_REG (HImode, HARD_SP_REGNUM)));
                                       gen_rtx_REG (HImode, HARD_SP_REGNUM)));
           operands[1] = gen_rtx_MEM (HImode,
           operands[1] = gen_rtx_MEM (HImode,
                              gen_rtx_POST_INC (HImode,
                              gen_rtx_POST_INC (HImode,
                                       gen_rtx_REG (HImode, HARD_SP_REGNUM)));
                                       gen_rtx_REG (HImode, HARD_SP_REGNUM)));
           operands[8] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
           operands[8] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
           operands[4] = operands[7] = operands[0];
           operands[4] = operands[7] = operands[0];
           operands[6] = operands[8];
           operands[6] = operands[8];
           operands[5] = operands[2];
           operands[5] = operands[2];
         }
         }
       else
       else
         {
         {
       operands[4] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
       operands[4] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
       operands[6] = operands[4];
       operands[6] = operands[4];
       if (!H_REG_P (operands[2]))
       if (!H_REG_P (operands[2]))
         {
         {
           operands[5] = operands[0];
           operands[5] = operands[0];
           operands[7] = operands[2];
           operands[7] = operands[2];
           operands[8] = operands[0];
           operands[8] = operands[0];
         }
         }
       else
       else
         {
         {
           operands[5] = operands[2];
           operands[5] = operands[2];
           operands[8] = operands[7] = operands[0];
           operands[8] = operands[7] = operands[0];
         }
         }
         }
         }
     }
     }
   else
   else
     {
     {
       operands[4] = operands[5] = operands[0];
       operands[4] = operands[5] = operands[0];
       operands[6] = operands[2];
       operands[6] = operands[2];
       operands[8] = operands[7] = operands[0];
       operands[8] = operands[7] = operands[0];
     }
     }
   ")
   ")
(define_split
(define_split
  [(set (match_operand:HI 0 "hard_addr_reg_operand" "")
  [(set (match_operand:HI 0 "hard_addr_reg_operand" "")
        (match_operator:HI 3 "m68hc11_arith_operator"
        (match_operator:HI 3 "m68hc11_arith_operator"
            [(match_operand:HI 1 "general_operand" "")
            [(match_operand:HI 1 "general_operand" "")
             (match_operand:HI 2 "general_operand" "")]))]
             (match_operand:HI 2 "general_operand" "")]))]
  "z_replacement_completed == 2
  "z_replacement_completed == 2
   /* If we are adding a small constant to X or Y, it's
   /* If we are adding a small constant to X or Y, it's
     better to use one or several inx/iny instructions.  */
     better to use one or several inx/iny instructions.  */
   && !(GET_CODE (operands[3]) == PLUS
   && !(GET_CODE (operands[3]) == PLUS
        && ((TARGET_M6812
        && ((TARGET_M6812
            && (immediate_operand (operands[2], HImode)
            && (immediate_operand (operands[2], HImode)
                || hard_reg_operand (operands[2], HImode)))
                || hard_reg_operand (operands[2], HImode)))
            || (GET_CODE (operands[2]) == CONST_INT
            || (GET_CODE (operands[2]) == CONST_INT
                && INTVAL (operands[2]) >= -4
                && INTVAL (operands[2]) >= -4
                && INTVAL (operands[2]) <= 4)))"
                && INTVAL (operands[2]) <= 4)))"
  [(set (match_dup 0) (match_dup 1))
  [(set (match_dup 0) (match_dup 1))
   (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
   (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
              (set (match_dup 0) (reg:HI D_REGNUM))])
              (set (match_dup 0) (reg:HI D_REGNUM))])
   (set (reg:HI D_REGNUM) (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 2)]))
   (set (reg:HI D_REGNUM) (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 2)]))
   (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
   (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
              (set (match_dup 0) (reg:HI D_REGNUM))])]
              (set (match_dup 0) (reg:HI D_REGNUM))])]
  "
  "
   ")
   ")
;;
;;
;; Next split handles the logical operations on D register with
;; Next split handles the logical operations on D register with
;; another hard register for the second operand.  For this, we
;; another hard register for the second operand.  For this, we
;; have to save the second operand in a scratch location and use
;; have to save the second operand in a scratch location and use
;; it instead.  This must be supported because in some (rare) cases
;; it instead.  This must be supported because in some (rare) cases
;; the second operand can come in a hard register and the reload
;; the second operand can come in a hard register and the reload
;; pass doesn't know how to reload it in a memory location.
;; pass doesn't know how to reload it in a memory location.
;;
;;
;;      PLUS MINUS AND IOR XOR
;;      PLUS MINUS AND IOR XOR
;;
;;
;; The shift operators are special and must not appear here.
;; The shift operators are special and must not appear here.
;;
;;
(define_split
(define_split
  [(set (match_operand:HI 0 "d_register_operand" "")
  [(set (match_operand:HI 0 "d_register_operand" "")
        (match_operator:HI 3 "m68hc11_non_shift_operator"
        (match_operator:HI 3 "m68hc11_non_shift_operator"
            [(match_operand:HI 1 "d_register_operand" "")
            [(match_operand:HI 1 "d_register_operand" "")
             (match_operand:HI 2 "hard_reg_operand" "")]))]
             (match_operand:HI 2 "hard_reg_operand" "")]))]
  "TARGET_M6811
  "TARGET_M6811
   && z_replacement_completed == 2 && !SP_REG_P (operands[2])"
   && z_replacement_completed == 2 && !SP_REG_P (operands[2])"
  [(set (match_dup 4) (match_dup 2))
  [(set (match_dup 4) (match_dup 2))
   (set (match_dup 0) (match_op_dup 3 [(match_dup 0) (match_dup 4)]))]
   (set (match_dup 0) (match_op_dup 3 [(match_dup 0) (match_dup 4)]))]
  "operands[4] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);")
  "operands[4] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);")
;;
;;
;; For 68HC12, push the operand[2] value on the stack and do the
;; For 68HC12, push the operand[2] value on the stack and do the
;; logical/arithmetic operation with a pop.
;; logical/arithmetic operation with a pop.
;;
;;
(define_split
(define_split
  [(set (match_operand:HI 0 "d_register_operand" "")
  [(set (match_operand:HI 0 "d_register_operand" "")
        (match_operator:HI 3 "m68hc11_non_shift_operator"
        (match_operator:HI 3 "m68hc11_non_shift_operator"
            [(match_operand:HI 1 "d_register_operand" "")
            [(match_operand:HI 1 "d_register_operand" "")
             (match_operand:HI 2 "hard_reg_operand" "")]))]
             (match_operand:HI 2 "hard_reg_operand" "")]))]
  "TARGET_M6812
  "TARGET_M6812
   && z_replacement_completed == 2 && !SP_REG_P (operands[2])"
   && z_replacement_completed == 2 && !SP_REG_P (operands[2])"
  [(set (match_dup 4) (match_dup 2))
  [(set (match_dup 4) (match_dup 2))
   (set (match_dup 0) (match_op_dup 3 [(match_dup 0) (match_dup 5)]))]
   (set (match_dup 0) (match_op_dup 3 [(match_dup 0) (match_dup 5)]))]
  "operands[4] = gen_rtx_MEM (HImode,
  "operands[4] = gen_rtx_MEM (HImode,
                          gen_rtx_PRE_DEC (HImode,
                          gen_rtx_PRE_DEC (HImode,
                                   gen_rtx_REG (HImode, HARD_SP_REGNUM)));
                                   gen_rtx_REG (HImode, HARD_SP_REGNUM)));
   operands[5] = gen_rtx_MEM (HImode,
   operands[5] = gen_rtx_MEM (HImode,
                          gen_rtx_POST_INC (HImode,
                          gen_rtx_POST_INC (HImode,
                                   gen_rtx_REG (HImode, HARD_SP_REGNUM)));
                                   gen_rtx_REG (HImode, HARD_SP_REGNUM)));
   ")
   ")
;;--------------------------------------------------------------------
;;--------------------------------------------------------------------
;; 16-bit Unary operations on X and Y:
;; 16-bit Unary operations on X and Y:
;;
;;
;;              NOT NEG
;;              NOT NEG
;;
;;
;; Operations on X or Y registers are split here.  Instructions are
;; Operations on X or Y registers are split here.  Instructions are
;; changed into:
;; changed into:
;;   - xgdx/xgdy instruction pattern,
;;   - xgdx/xgdy instruction pattern,
;;   - The same operation on register D,
;;   - The same operation on register D,
;;   - xgdx/xgdy instruction pattern.
;;   - xgdx/xgdy instruction pattern.
;; This should allow the peephole to merge consecutive xgdx/xgdy instructions.
;; This should allow the peephole to merge consecutive xgdx/xgdy instructions.
;; We also handle the case were the address register is used in both source
;; We also handle the case were the address register is used in both source
;; operands, such as:
;; operands, such as:
;;
;;
;;     (set (REG:HI X) (PLUS:HI (REG:HI X) (mem:HI (REG:HI X))))
;;     (set (REG:HI X) (PLUS:HI (REG:HI X) (mem:HI (REG:HI X))))
;; or
;; or
;;     (set (REG:HI X) (PLUS:HI (REG:HI X) (REG:HI X)))
;;     (set (REG:HI X) (PLUS:HI (REG:HI X) (REG:HI X)))
;;
;;
(define_split
(define_split
  [(set (match_operand:HI 0 "hard_addr_reg_operand" "")
  [(set (match_operand:HI 0 "hard_addr_reg_operand" "")
        (match_operator:HI 2 "m68hc11_unary_operator"
        (match_operator:HI 2 "m68hc11_unary_operator"
            [(match_operand 1 "general_operand" "")]))]
            [(match_operand 1 "general_operand" "")]))]
  "z_replacement_completed == 2"
  "z_replacement_completed == 2"
  [(set (match_dup 4) (match_dup 5))
  [(set (match_dup 4) (match_dup 5))
   (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
   (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
              (set (match_dup 0) (reg:HI D_REGNUM))])
              (set (match_dup 0) (reg:HI D_REGNUM))])
   (set (reg:HI D_REGNUM) (match_op_dup 2 [(match_dup 3)]))
   (set (reg:HI D_REGNUM) (match_op_dup 2 [(match_dup 3)]))
   (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
   (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
              (set (match_dup 0) (reg:HI D_REGNUM))])]
              (set (match_dup 0) (reg:HI D_REGNUM))])]
  "
  "
{
{
  if ((H_REG_P (operands[1])
  if ((H_REG_P (operands[1])
       && !rtx_equal_p (operands[0], operands[1]))
       && !rtx_equal_p (operands[0], operands[1]))
      || reg_mentioned_p (operands[0], operands[1]))
      || reg_mentioned_p (operands[0], operands[1]))
    {
    {
      /* Move to the destination register, before the xgdx.  */
      /* Move to the destination register, before the xgdx.  */
      operands[4] = gen_rtx_REG (GET_MODE (operands[1]),
      operands[4] = gen_rtx_REG (GET_MODE (operands[1]),
                             REGNO (operands[0]));
                             REGNO (operands[0]));
      operands[5] = operands[1];
      operands[5] = operands[1];
      /* Apply the operation on D.  */
      /* Apply the operation on D.  */
      operands[3] = gen_rtx_REG (GET_MODE (operands[1]), HARD_D_REGNUM);
      operands[3] = gen_rtx_REG (GET_MODE (operands[1]), HARD_D_REGNUM);
    }
    }
  else
  else
    {
    {
      /* Generate a copy to same register (nop).  */
      /* Generate a copy to same register (nop).  */
      operands[4] = operands[5] = operands[0];
      operands[4] = operands[5] = operands[0];
      operands[3] = operands[1];
      operands[3] = operands[1];
    }
    }
}")
}")
;;
;;
;; 8-bit operations on address registers.
;; 8-bit operations on address registers.
;;
;;
;; We have to take care that the address register is not used for the
;; We have to take care that the address register is not used for the
;; source of operand2. If operand2 is the D register, we have to save
;; source of operand2. If operand2 is the D register, we have to save
;; that register in a temporary location.
;; that register in a temporary location.
;;
;;
;; AND OR XOR PLUS MINUS ASHIFT ASHIFTRT LSHIFTRT ROTATE ROTATERT
;; AND OR XOR PLUS MINUS ASHIFT ASHIFTRT LSHIFTRT ROTATE ROTATERT
;;
;;
(define_split
(define_split
  [(set (match_operand:QI 0 "hard_addr_reg_operand" "")
  [(set (match_operand:QI 0 "hard_addr_reg_operand" "")
        (match_operator:QI 3 "m68hc11_arith_operator"
        (match_operator:QI 3 "m68hc11_arith_operator"
            [(match_operand:QI 1 "hard_addr_reg_operand" "")
            [(match_operand:QI 1 "hard_addr_reg_operand" "")
             (match_operand:QI 2 "general_operand" "")]))]
             (match_operand:QI 2 "general_operand" "")]))]
  "z_replacement_completed == 2
  "z_replacement_completed == 2
   /* Reject a (plus:QI (reg:QI X) (const_int 1|-1)) because the
   /* Reject a (plus:QI (reg:QI X) (const_int 1|-1)) because the
      incqi pattern generates a better code.  */
      incqi pattern generates a better code.  */
   && !(GET_CODE (operands[3]) == PLUS
   && !(GET_CODE (operands[3]) == PLUS
        && GET_CODE (operands[2]) == CONST_INT
        && GET_CODE (operands[2]) == CONST_INT
        && (INTVAL (operands[2]) == 1 || INTVAL (operands[2]) == -1))"
        && (INTVAL (operands[2]) == 1 || INTVAL (operands[2]) == -1))"
  [(set (match_dup 5) (match_dup 6))
  [(set (match_dup 5) (match_dup 6))
   (parallel [(set (reg:HI D_REGNUM) (match_dup 4))
   (parallel [(set (reg:HI D_REGNUM) (match_dup 4))
              (set (match_dup 4) (reg:HI D_REGNUM))])
              (set (match_dup 4) (reg:HI D_REGNUM))])
   (set (reg:QI D_REGNUM) (match_op_dup 3 [(reg:QI D_REGNUM) (match_dup 7)]))
   (set (reg:QI D_REGNUM) (match_op_dup 3 [(reg:QI D_REGNUM) (match_dup 7)]))
   (parallel [(set (reg:HI D_REGNUM) (match_dup 4))
   (parallel [(set (reg:HI D_REGNUM) (match_dup 4))
              (set (match_dup 4) (reg:HI D_REGNUM))])]
              (set (match_dup 4) (reg:HI D_REGNUM))])]
  "operands[4] = gen_rtx_REG (HImode, REGNO (operands[0]));
  "operands[4] = gen_rtx_REG (HImode, REGNO (operands[0]));
   /* For the second operand is a hard register or if the address
   /* For the second operand is a hard register or if the address
      register appears in the source, we have to save the operand[2]
      register appears in the source, we have to save the operand[2]
      value in a temporary location and then use that temp.
      value in a temporary location and then use that temp.
      Otherwise, it's ok and we generate a (set (D) (D)) that
      Otherwise, it's ok and we generate a (set (D) (D)) that
      will result in a nop.  */
      will result in a nop.  */
   if (H_REG_P (operands[2]))
   if (H_REG_P (operands[2]))
     {
     {
       operands[5] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
       operands[5] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
       operands[6] = gen_rtx_REG (HImode, REGNO (operands[2]));
       operands[6] = gen_rtx_REG (HImode, REGNO (operands[2]));
       operands[7] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
       operands[7] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
     }
     }
   else if (reg_mentioned_p (operands[0], operands[2]))
   else if (reg_mentioned_p (operands[0], operands[2]))
     {
     {
       operands[5] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
       operands[5] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
       operands[6] = operands[2];
       operands[6] = operands[2];
       operands[7] = operands[5];
       operands[7] = operands[5];
     }
     }
   else
   else
     {
     {
       operands[5] = operands[6] = gen_rtx_REG (QImode, HARD_D_REGNUM);
       operands[5] = operands[6] = gen_rtx_REG (QImode, HARD_D_REGNUM);
       operands[7] = operands[2];
       operands[7] = operands[2];
     }
     }
  ")
  ")
;;
;;
;; Next split handles the logical operations on D register with
;; Next split handles the logical operations on D register with
;; another hard register for the second operand.  For this, we
;; another hard register for the second operand.  For this, we
;; have to save the second operand in a scratch location and use
;; have to save the second operand in a scratch location and use
;; it instead.  This must be supported because in some (rare) cases
;; it instead.  This must be supported because in some (rare) cases
;; the second operand can come in a hard register and the reload
;; the second operand can come in a hard register and the reload
;; pass doesn't know how to reload it in a memory location.
;; pass doesn't know how to reload it in a memory location.
;;
;;
;;      PLUS MINUS AND IOR XOR
;;      PLUS MINUS AND IOR XOR
;;
;;
;; The shift operators are special and must not appear here.
;; The shift operators are special and must not appear here.
;;
;;
(define_split
(define_split
  [(set (match_operand:QI 0 "d_register_operand" "")
  [(set (match_operand:QI 0 "d_register_operand" "")
        (match_operator:QI 3 "m68hc11_non_shift_operator"
        (match_operator:QI 3 "m68hc11_non_shift_operator"
            [(match_operand:QI 1 "d_register_operand" "")
            [(match_operand:QI 1 "d_register_operand" "")
             (match_operand:QI 2 "hard_reg_operand" "")]))]
             (match_operand:QI 2 "hard_reg_operand" "")]))]
  "reload_completed"
  "reload_completed"
  [(set (match_dup 5) (match_dup 6))
  [(set (match_dup 5) (match_dup 6))
   (set (match_dup 0) (match_op_dup 3 [(match_dup 0) (match_dup 4)]))]
   (set (match_dup 0) (match_op_dup 3 [(match_dup 0) (match_dup 4)]))]
  "operands[4] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
  "operands[4] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);
   operands[5] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
   operands[5] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);
   operands[6] = gen_rtx_REG (HImode, REGNO (operands[2]));")
   operands[6] = gen_rtx_REG (HImode, REGNO (operands[2]));")
;;--------------------------------------------------------------------
;;--------------------------------------------------------------------
;; 8-bit Unary operations on X and Y:
;; 8-bit Unary operations on X and Y:
;;
;;
;;              NOT NEG
;;              NOT NEG
;;
;;
;; Operations on X or Y registers are split here.  Instructions are
;; Operations on X or Y registers are split here.  Instructions are
;; changed into:
;; changed into:
;;   - xgdx/xgdy instruction pattern,
;;   - xgdx/xgdy instruction pattern,
;;   - The same operation on register D,
;;   - The same operation on register D,
;;   - xgdx/xgdy instruction pattern.
;;   - xgdx/xgdy instruction pattern.
;; This should allow the peephole to merge consecutive xgdx/xgdy instructions.
;; This should allow the peephole to merge consecutive xgdx/xgdy instructions.
;; We also handle the case were the address register is used in both source
;; We also handle the case were the address register is used in both source
;; operands, such as:
;; operands, such as:
;;
;;
;;     (set (REG:HI X) (PLUS:HI (REG:HI X) (mem:HI (REG:HI X))))
;;     (set (REG:HI X) (PLUS:HI (REG:HI X) (mem:HI (REG:HI X))))
;; or
;; or
;;     (set (REG:HI X) (PLUS:HI (REG:HI X) (REG:HI X)))
;;     (set (REG:HI X) (PLUS:HI (REG:HI X) (REG:HI X)))
;;
;;
(define_split
(define_split
  [(set (match_operand:QI 0 "hard_addr_reg_operand" "")
  [(set (match_operand:QI 0 "hard_addr_reg_operand" "")
        (match_operator:QI 2 "m68hc11_unary_operator"
        (match_operator:QI 2 "m68hc11_unary_operator"
            [(match_operand:QI 1 "general_operand" "")]))]
            [(match_operand:QI 1 "general_operand" "")]))]
  "z_replacement_completed == 2"
  "z_replacement_completed == 2"
  [(set (match_dup 4) (match_dup 5))
  [(set (match_dup 4) (match_dup 5))
   (parallel [(set (reg:HI D_REGNUM) (match_dup 3))
   (parallel [(set (reg:HI D_REGNUM) (match_dup 3))
              (set (match_dup 3) (reg:HI D_REGNUM))])
              (set (match_dup 3) (reg:HI D_REGNUM))])
   (set (reg:QI D_REGNUM) (match_op_dup 2 [(match_dup 6)]))
   (set (reg:QI D_REGNUM) (match_op_dup 2 [(match_dup 6)]))
   (parallel [(set (reg:HI D_REGNUM) (match_dup 3))
   (parallel [(set (reg:HI D_REGNUM) (match_dup 3))
              (set (match_dup 3) (reg:HI D_REGNUM))])]
              (set (match_dup 3) (reg:HI D_REGNUM))])]
  "
  "
{
{
  operands[3] = gen_rtx_REG (HImode, REGNO (operands[0]));
  operands[3] = gen_rtx_REG (HImode, REGNO (operands[0]));
  if ((H_REG_P (operands[1])
  if ((H_REG_P (operands[1])
       && !rtx_equal_p (operands[0], operands[1]))
       && !rtx_equal_p (operands[0], operands[1]))
      || reg_mentioned_p (operands[0], operands[1]))
      || reg_mentioned_p (operands[0], operands[1]))
    {
    {
      /* Move to the destination register, before the xgdx.  */
      /* Move to the destination register, before the xgdx.  */
      operands[4] = operands[0];
      operands[4] = operands[0];
      operands[5] = operands[1];
      operands[5] = operands[1];
      /* Apply the operation on D.  */
      /* Apply the operation on D.  */
      operands[6] = gen_rtx_REG (QImode, HARD_D_REGNUM);
      operands[6] = gen_rtx_REG (QImode, HARD_D_REGNUM);
    }
    }
  else
  else
    {
    {
      operands[4] = operands[5] = operands[0];
      operands[4] = operands[5] = operands[0];
      operands[6] = operands[1];
      operands[6] = operands[1];
    }
    }
}")
}")
;;--------------------------------------------------------------------
;;--------------------------------------------------------------------
;;-  Complements
;;-  Complements
;;--------------------------------------------------------------------
;;--------------------------------------------------------------------
(define_expand "negdi2"
(define_expand "negdi2"
  [(set (match_operand:DI 0 "nonimmediate_operand" "")
  [(set (match_operand:DI 0 "nonimmediate_operand" "")
        (neg:DI (match_operand:DI 1 "general_operand" "")))]
        (neg:DI (match_operand:DI 1 "general_operand" "")))]
  ""
  ""
  "m68hc11_emit_libcall (\"__negdi2\", NEG, DImode, DImode, 2, operands);
  "m68hc11_emit_libcall (\"__negdi2\", NEG, DImode, DImode, 2, operands);
   DONE;")
   DONE;")
(define_insn "negsi2"
(define_insn "negsi2"
  [(set (match_operand:SI 0 "register_operand" "=D")
  [(set (match_operand:SI 0 "register_operand" "=D")
        (neg:SI (match_operand:SI 1 "general_operand" "0")))]
        (neg:SI (match_operand:SI 1 "general_operand" "0")))]
  ""
  ""
  "*
  "*
{
{
  rtx ops[1];
  rtx ops[1];
  CC_STATUS_INIT;
  CC_STATUS_INIT;
  /* With -Os or without -O, use a special library call.  */
  /* With -Os or without -O, use a special library call.  */
  if (optimize_size || optimize == 0)
  if (optimize_size || optimize == 0)
    return \"bsr\\t___negsi2\";
    return \"bsr\\t___negsi2\";
  ops[0] = gen_label_rtx ();
  ops[0] = gen_label_rtx ();
  /* 32-bit complement and add 1.  */
  /* 32-bit complement and add 1.  */
  output_asm_insn (\"comb\\n\\tcoma\\n\\txgdx\", operands);
  output_asm_insn (\"comb\\n\\tcoma\\n\\txgdx\", operands);
  output_asm_insn (\"comb\\n\\tcoma\\n\\tinx\\n\\txgdx\", operands);
  output_asm_insn (\"comb\\n\\tcoma\\n\\tinx\\n\\txgdx\", operands);
  output_asm_insn (\"bne\\t%l0\", ops);
  output_asm_insn (\"bne\\t%l0\", ops);
  output_asm_insn (\"inx\", operands);
  output_asm_insn (\"inx\", operands);
  (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0]));
  (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0]));
  return \"\";
  return \"\";
}")
}")
(define_insn "neghi2"
(define_insn "neghi2"
  [(set (match_operand:HI 0 "register_operand" "=d,d,x*y")
  [(set (match_operand:HI 0 "register_operand" "=d,d,x*y")
        (neg:HI (match_operand:HI 1 "general_operand" "0,!duim,0")))]
        (neg:HI (match_operand:HI 1 "general_operand" "0,!duim,0")))]
  ""
  ""
  "@
  "@
   coma\\n\\tcomb\\n\\taddd\\t#1
   coma\\n\\tcomb\\n\\taddd\\t#1
   clra\\n\\tclrb\\n\\tsubd\\t%1
   clra\\n\\tclrb\\n\\tsubd\\t%1
   xgd%0\\n\\tcoma\\n\\tcomb\\n\\txgd%0\\n\\tin%0")
   xgd%0\\n\\tcoma\\n\\tcomb\\n\\txgd%0\\n\\tin%0")
(define_insn "negqi2"
(define_insn "negqi2"
  [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m,!u,!*A")
  [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m,!u,!*A")
        (neg:QI (match_operand:QI 1 "nonimmediate_operand" "0,0,0,0")))]
        (neg:QI (match_operand:QI 1 "nonimmediate_operand" "0,0,0,0")))]
  ""
  ""
  "@
  "@
   negb
   negb
   neg\\t%b0
   neg\\t%b0
   neg\\t%b0
   neg\\t%b0
   #")
   #")
;;
;;
;; - 32-bit complement.  GCC knows how to translate them but providing a
;; - 32-bit complement.  GCC knows how to translate them but providing a
;; pattern generates better/smaller code.
;; pattern generates better/smaller code.
;;
;;
(define_expand "one_cmpldi2"
(define_expand "one_cmpldi2"
  [(set (match_operand:DI 0 "nonimmediate_operand" "")
  [(set (match_operand:DI 0 "nonimmediate_operand" "")
        (not:DI (match_operand:DI 1 "general_operand" "")))]
        (not:DI (match_operand:DI 1 "general_operand" "")))]
  ""
  ""
  "m68hc11_emit_libcall (\"___notdi2\", NOT, DImode, DImode, 2, operands);
  "m68hc11_emit_libcall (\"___notdi2\", NOT, DImode, DImode, 2, operands);
   DONE;")
   DONE;")
(define_insn "one_cmplsi2"
(define_insn "one_cmplsi2"
  [(set (match_operand:SI 0 "non_push_operand" "=D,m,!u")
  [(set (match_operand:SI 0 "non_push_operand" "=D,m,!u")
        (not:SI (match_operand:SI 1 "general_operand" "0,m,0")))
        (not:SI (match_operand:SI 1 "general_operand" "0,m,0")))
   (clobber (match_scratch:HI 2 "=X,d,X"))]
   (clobber (match_scratch:HI 2 "=X,d,X"))]
  ""
  ""
  "@
  "@
   bsr\\t___one_cmplsi2
   bsr\\t___one_cmplsi2
   #
   #
   #")
   #")
(define_insn "one_cmplhi2"
(define_insn "one_cmplhi2"
  [(set (match_operand:HI 0 "non_push_operand" "=d,m,*A,u")
  [(set (match_operand:HI 0 "non_push_operand" "=d,m,*A,u")
        (not:HI (match_operand:HI 1 "general_operand" "0,0,0,0")))]
        (not:HI (match_operand:HI 1 "general_operand" "0,0,0,0")))]
  ""
  ""
  "@
  "@
   comb\\n\\tcoma
   comb\\n\\tcoma
   com\\t%b0\\n\\tcom\\t%h0
   com\\t%b0\\n\\tcom\\t%h0
   #
   #
   com\\t%b0\\n\\tcom\\t%h0")
   com\\t%b0\\n\\tcom\\t%h0")
(define_insn "one_cmplqi2"
(define_insn "one_cmplqi2"
  [(set (match_operand:QI 0 "non_push_operand" "=d,m,*A,u")
  [(set (match_operand:QI 0 "non_push_operand" "=d,m,*A,u")
        (not:QI (match_operand:QI 1 "general_operand" "0,0,0,0")))]
        (not:QI (match_operand:QI 1 "general_operand" "0,0,0,0")))]
  ""
  ""
  "@
  "@
   comb
   comb
   com\\t%b0
   com\\t%b0
   #
   #
   com\\t%b0")
   com\\t%b0")
(define_split /* "*one_cmplsi2" */
(define_split /* "*one_cmplsi2" */
  [(set (match_operand:SI 0 "non_push_operand" "")
  [(set (match_operand:SI 0 "non_push_operand" "")
        (not:SI (match_dup 0)))
        (not:SI (match_dup 0)))
   (clobber (match_scratch:HI 1 ""))]
   (clobber (match_scratch:HI 1 ""))]
  "z_replacement_completed == 2
  "z_replacement_completed == 2
   && (!X_REG_P (operands[0]) || (optimize && optimize_size == 0))"
   && (!X_REG_P (operands[0]) || (optimize && optimize_size == 0))"
  [(set (match_dup 2) (not:HI (match_dup 2)))
  [(set (match_dup 2) (not:HI (match_dup 2)))
   (set (match_dup 3) (not:HI (match_dup 3)))]
   (set (match_dup 3) (not:HI (match_dup 3)))]
  "operands[2] = m68hc11_gen_lowpart (HImode, operands[0]);
  "operands[2] = m68hc11_gen_lowpart (HImode, operands[0]);
   operands[3] = m68hc11_gen_highpart (HImode, operands[0]);")
   operands[3] = m68hc11_gen_highpart (HImode, operands[0]);")
(define_split /* "*one_cmplsi2" */
(define_split /* "*one_cmplsi2" */
  [(set (match_operand:SI 0 "non_push_operand" "")
  [(set (match_operand:SI 0 "non_push_operand" "")
        (not:SI (match_operand:SI 1 "non_push_operand" "")))
        (not:SI (match_operand:SI 1 "non_push_operand" "")))
   (clobber (match_operand:HI 2 "d_register_operand" ""))]
   (clobber (match_operand:HI 2 "d_register_operand" ""))]
  "z_replacement_completed == 2
  "z_replacement_completed == 2
   && (!X_REG_P (operands[0]) || (optimize && optimize_size == 0))"
   && (!X_REG_P (operands[0]) || (optimize && optimize_size == 0))"
  [(set (match_dup 2) (match_dup 3))
  [(set (match_dup 2) (match_dup 3))
   (set (match_dup 2) (not:HI (match_dup 2)))
   (set (match_dup 2) (not:HI (match_dup 2)))
   (set (match_dup 4) (match_dup 2))
   (set (match_dup 4) (match_dup 2))
   (set (match_dup 2) (match_dup 5))
   (set (match_dup 2) (match_dup 5))
   (set (match_dup 2) (not:HI (match_dup 2)))
   (set (match_dup 2) (not:HI (match_dup 2)))
   (set (match_dup 6) (match_dup 2))]
   (set (match_dup 6) (match_dup 2))]
  "operands[3] = m68hc11_gen_lowpart (HImode, operands[1]);
  "operands[3] = m68hc11_gen_lowpart (HImode, operands[1]);
   operands[5] = m68hc11_gen_highpart (HImode, operands[1]);
   operands[5] = m68hc11_gen_highpart (HImode, operands[1]);
   operands[4] = m68hc11_gen_lowpart (HImode, operands[0]);
   operands[4] = m68hc11_gen_lowpart (HImode, operands[0]);
   operands[6] = m68hc11_gen_highpart (HImode, operands[0]);")
   operands[6] = m68hc11_gen_highpart (HImode, operands[0]);")
;;--------------------------------------------------------------------
;;--------------------------------------------------------------------
;;- arithmetic shifts
;;- arithmetic shifts
;;--------------------------------------------------------------------
;;--------------------------------------------------------------------
;;
;;
;; Provide some 64-bit shift patterns.
;; Provide some 64-bit shift patterns.
(define_expand "ashldi3"
(define_expand "ashldi3"
  [(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "")
  [(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "")
                     (ashift:DI (match_operand:DI 1 "general_operand" "")
                     (ashift:DI (match_operand:DI 1 "general_operand" "")
                                (match_operand:HI 2 "general_operand" "")))
                                (match_operand:HI 2 "general_operand" "")))
              (clobber (match_scratch:HI 3 ""))])]
              (clobber (match_scratch:HI 3 ""))])]
   ""
   ""
   "
   "
{
{
  if (GET_CODE (operands[2]) != CONST_INT
  if (GET_CODE (operands[2]) != CONST_INT
      || (INTVAL (operands[2]) != 32 && INTVAL (operands[2]) != 1))
      || (INTVAL (operands[2]) != 32 && INTVAL (operands[2]) != 1))
    {
    {
      FAIL;
      FAIL;
    }
    }
}")
}")
(define_insn_and_split "*ashldi3_const32"
(define_insn_and_split "*ashldi3_const32"
  [(set (match_operand:DI 0 "nonimmediate_operand" "=<,m,u")
  [(set (match_operand:DI 0 "nonimmediate_operand" "=<,m,u")
        (ashift:DI (match_operand:DI 1 "general_operand" "umi,umi,umi")
        (ashift:DI (match_operand:DI 1 "general_operand" "umi,umi,umi")
                   (const_int 32)))
                   (const_int 32)))
   (clobber (match_scratch:HI 2 "=&A,d,d"))]
   (clobber (match_scratch:HI 2 "=&A,d,d"))]
   ""
   ""
   "#"
   "#"
   "reload_completed"
   "reload_completed"
   [(const_int 0)]
   [(const_int 0)]
   "/* Move the lowpart in the highpart first in case the shift
   "/* Move the lowpart in the highpart first in case the shift
       is applied on the source.  */
       is applied on the source.  */
    if (IS_STACK_PUSH (operands[0]))
    if (IS_STACK_PUSH (operands[0]))
      {
      {
         m68hc11_split_move (m68hc11_gen_lowpart (SImode, operands[0]),
         m68hc11_split_move (m68hc11_gen_lowpart (SImode, operands[0]),
                             const0_rtx, operands[2]);
                             const0_rtx, operands[2]);
         /* Adjust first operand if it uses SP so that we take into
         /* Adjust first operand if it uses SP so that we take into
            account the above push.  Can occur only for 68HC12.  */
            account the above push.  Can occur only for 68HC12.  */
         if (reg_mentioned_p (gen_rtx_REG (HImode, HARD_SP_REGNUM),
         if (reg_mentioned_p (gen_rtx_REG (HImode, HARD_SP_REGNUM),
                              operands[1]))
                              operands[1]))
           operands[1] = adjust_address (operands[1],
           operands[1] = adjust_address (operands[1],
                                         GET_MODE (operands[0]), 4);
                                         GET_MODE (operands[0]), 4);
      }
      }
    m68hc11_split_move (m68hc11_gen_highpart (SImode, operands[0]),
    m68hc11_split_move (m68hc11_gen_highpart (SImode, operands[0]),
                        m68hc11_gen_lowpart (SImode, operands[1]),
                        m68hc11_gen_lowpart (SImode, operands[1]),
                        operands[2]);
                        operands[2]);
    if (!IS_STACK_PUSH (operands[0]))
    if (!IS_STACK_PUSH (operands[0]))
      {
      {
        m68hc11_split_move (m68hc11_gen_lowpart (SImode, operands[0]),
        m68hc11_split_move (m68hc11_gen_lowpart (SImode, operands[0]),
                            const0_rtx, operands[2]);
                            const0_rtx, operands[2]);
      }
      }
    DONE;")
    DONE;")
(define_insn_and_split "*ashldi3_const1"
(define_insn_and_split "*ashldi3_const1"
  [(set (match_operand:DI 0 "non_push_operand" "=m,m,u")
  [(set (match_operand:DI 0 "non_push_operand" "=m,m,u")
        (ashift:DI (match_operand:DI 1 "general_operand" "mi,u,umi")
        (ashift:DI (match_operand:DI 1 "general_operand" "mi,u,umi")
                   (const_int 1)))
                   (const_int 1)))
   (clobber (match_scratch:HI 2 "=d,d,d"))]
   (clobber (match_scratch:HI 2 "=d,d,d"))]
   ""
   ""
   "#"
   "#"
   "z_replacement_completed == 2"
   "z_replacement_completed == 2"
   [(set (match_dup 2) (match_dup 3))
   [(set (match_dup 2) (match_dup 3))
    (set (match_dup 2) (ashift:HI (match_dup 2) (const_int 1)))
    (set (match_dup 2) (ashift:HI (match_dup 2) (const_int 1)))
    (set (match_dup 4) (match_dup 2))
    (set (match_dup 4) (match_dup 2))
    (set (match_dup 2) (match_dup 5))
    (set (match_dup 2) (match_dup 5))
    (parallel [(set (match_dup 2)
    (parallel [(set (match_dup 2)
                       (rotate:HI (match_dup 2) (const_int 1)))
                       (rotate:HI (match_dup 2) (const_int 1)))
               (clobber (reg:HI CC_REGNUM))])
               (clobber (reg:HI CC_REGNUM))])
    (set (match_dup 6) (match_dup 2))
    (set (match_dup 6) (match_dup 2))
    (set (match_dup 2) (match_dup 7))
    (set (match_dup 2) (match_dup 7))
    (parallel [(set (match_dup 2)
    (parallel [(set (match_dup 2)
                       (rotate:HI (match_dup 2) (const_int 1)))
                       (rotate:HI (match_dup 2) (const_int 1)))
               (clobber (reg:HI CC_REGNUM))])
               (clobber (reg:HI CC_REGNUM))])
    (set (match_dup 8) (match_dup 2))
    (set (match_dup 8) (match_dup 2))
    (set (match_dup 2) (match_dup 9))
    (set (match_dup 2) (match_dup 9))
    (parallel [(set (match_dup 2)
    (parallel [(set (match_dup 2)
                       (rotate:HI (match_dup 2) (const_int 1)))
                       (rotate:HI (match_dup 2) (const_int 1)))
               (clobber (reg:HI CC_REGNUM))])
               (clobber (reg:HI CC_REGNUM))])
    (set (match_dup 10) (match_dup 2))]
    (set (match_dup 10) (match_dup 2))]
   "operands[3] = m68hc11_gen_lowpart (SImode, operands[1]);
   "operands[3] = m68hc11_gen_lowpart (SImode, operands[1]);
    operands[5] = m68hc11_gen_highpart (HImode, operands[3]);
    operands[5] = m68hc11_gen_highpart (HImode, operands[3]);
    operands[3] = m68hc11_gen_lowpart (HImode, operands[3]);
    operands[3] = m68hc11_gen_lowpart (HImode, operands[3]);
    operands[4] = m68hc11_gen_lowpart (SImode, operands[0]);
    operands[4] = m68hc11_gen_lowpart (SImode, operands[0]);
    operands[6] = m68hc11_gen_highpart (HImode, operands[4]);
    operands[6] = m68hc11_gen_highpart (HImode, operands[4]);
    operands[4] = m68hc11_gen_lowpart (HImode, operands[4]);
    operands[4] = m68hc11_gen_lowpart (HImode, operands[4]);
    operands[7] = m68hc11_gen_highpart (SImode, operands[1]);
    operands[7] = m68hc11_gen_highpart (SImode, operands[1]);
    operands[9] = m68hc11_gen_highpart (HImode, operands[7]);
    operands[9] = m68hc11_gen_highpart (HImode, operands[7]);
    operands[7] = m68hc11_gen_lowpart (HImode, operands[7]);
    operands[7] = m68hc11_gen_lowpart (HImode, operands[7]);
    operands[8] = m68hc11_gen_highpart (SImode, operands[0]);
    operands[8] = m68hc11_gen_highpart (SImode, operands[0]);
    operands[10] = m68hc11_gen_highpart (HImode, operands[8]);
    operands[10] = m68hc11_gen_highpart (HImode, operands[8]);
    operands[8] = m68hc11_gen_lowpart (HImode, operands[8]);")
    operands[8] = m68hc11_gen_lowpart (HImode, operands[8]);")
(define_insn "addsi_silshr16"
(define_insn "addsi_silshr16"
  [(set (match_operand:SI 0 "register_operand" "=D,D,!D")
  [(set (match_operand:SI 0 "register_operand" "=D,D,!D")
          (plus:SI (lshiftrt:SI (match_operand:SI 1 "general_operand" "!*uim,0,0")
          (plus:SI (lshiftrt:SI (match_operand:SI 1 "general_operand" "!*uim,0,0")
                                (const_int 16))
                                (const_int 16))
                   (match_operand:SI 2 "general_operand" "0,m!*u,0")))]
                   (match_operand:SI 2 "general_operand" "0,m!*u,0")))]
  ""
  ""
  "#")
  "#")
(define_split
(define_split
  [(set (match_operand:SI 0 "register_operand" "")
  [(set (match_operand:SI 0 "register_operand" "")
          (plus:SI (lshiftrt:SI (match_operand:SI 1 "general_operand" "")
          (plus:SI (lshiftrt:SI (match_operand:SI 1 "general_operand" "")
                                (const_int 16))
                                (const_int 16))
                   (match_operand:SI 2 "general_operand" "")))]
                   (match_operand:SI 2 "general_operand" "")))]
  "z_replacement_completed == 2 && !X_REG_P (operands[1])"
  "z_replacement_completed == 2 && !X_REG_P (operands[1])"
  [(set (reg:HI D_REGNUM) (plus:HI (reg:HI D_REGNUM) (match_dup 3)))
  [(set (reg:HI D_REGNUM) (plus:HI (reg:HI D_REGNUM) (match_dup 3)))
   (set (reg:HI X_REGNUM) (plus:HI (plus:HI (reg:HI X_REGNUM)
   (set (reg:HI X_REGNUM) (plus:HI (plus:HI (reg:HI X_REGNUM)
                                            (const_int 0))
                                            (const_int 0))
                                   (reg:HI CC_REGNUM)))]
                                   (reg:HI CC_REGNUM)))]
  "operands[3] = m68hc11_gen_highpart (HImode, operands[1]);")
  "operands[3] = m68hc11_gen_highpart (HImode, operands[1]);")
(define_split
(define_split
  [(set (match_operand:SI 0 "register_operand" "")
  [(set (match_operand:SI 0 "register_operand" "")
          (plus:SI (lshiftrt:SI (match_operand:SI 1 "general_operand" "")
          (plus:SI (lshiftrt:SI (match_operand:SI 1 "general_operand" "")
                                (const_int 16))
                                (const_int 16))
                   (match_operand:SI 2 "general_operand" "")))]
                   (match_operand:SI 2 "general_operand" "")))]
  "z_replacement_completed == 2 && X_REG_P (operands[1])"
  "z_replacement_completed == 2 && X_REG_P (operands[1])"
  [(set (reg:HI D_REGNUM) (match_dup 5))
  [(set (reg:HI D_REGNUM) (match_dup 5))
   (set (reg:HI X_REGNUM) (match_dup 3))
   (set (reg:HI X_REGNUM) (match_dup 3))
   (set (reg:HI D_REGNUM) (plus:HI (reg:HI D_REGNUM) (match_dup 4)))
   (set (reg:HI D_REGNUM) (plus:HI (reg:HI D_REGNUM) (match_dup 4)))
   (set (reg:HI X_REGNUM) (plus:HI (plus:HI (reg:HI X_REGNUM)
   (set (reg:HI X_REGNUM) (plus:HI (plus:HI (reg:HI X_REGNUM)
                                            (const_int 0))
                                            (const_int 0))
                                   (reg:HI CC_REGNUM)))]
                                   (reg:HI CC_REGNUM)))]
  "operands[3] = m68hc11_gen_highpart (HImode, operands[2]);
  "operands[3] = m68hc11_gen_highpart (HImode, operands[2]);
   if (X_REG_P (operands[2]))
   if (X_REG_P (operands[2]))
     {
     {
       operands[4] = gen_rtx_REG (HImode, HARD_X_REGNUM);
       operands[4] = gen_rtx_REG (HImode, HARD_X_REGNUM);
       operands[5] = gen_rtx_REG (HImode, HARD_D_REGNUM);
       operands[5] = gen_rtx_REG (HImode, HARD_D_REGNUM);
     }
     }
   else
   else
     {
     {
       operands[4] = m68hc11_gen_lowpart (HImode, operands[2]);
       operands[4] = m68hc11_gen_lowpart (HImode, operands[2]);
       operands[5] = gen_rtx_REG (HImode, HARD_X_REGNUM);
       operands[5] = gen_rtx_REG (HImode, HARD_X_REGNUM);
     }
     }
")
")
(define_insn "addsi_ashift16"
(define_insn "addsi_ashift16"
  [(set (match_operand:SI 0 "register_operand" "=D")
  [(set (match_operand:SI 0 "register_operand" "=D")
          (plus:SI
          (plus:SI
                   (mult:SI (match_operand:SI 2 "general_operand" "uim")
                   (mult:SI (match_operand:SI 2 "general_operand" "uim")
                            (const_int 65536))
                            (const_int 65536))
                (match_operand:SI 1 "general_operand" "0")))
                (match_operand:SI 1 "general_operand" "0")))
   (clobber (match_scratch:HI 3 "=X"))]
   (clobber (match_scratch:HI 3 "=X"))]
  "0"
  "0"
  "#")
  "#")
(define_split
(define_split
  [(set (match_operand:SI 0 "register_operand" "")
  [(set (match_operand:SI 0 "register_operand" "")
          (plus:SI
          (plus:SI
                   (mult:SI (match_operand:SI 2 "general_operand" "")
                   (mult:SI (match_operand:SI 2 "general_operand" "")
                            (const_int 65536))
                            (const_int 65536))
                   (match_operand:SI 1 "general_operand" "")))
                   (match_operand:SI 1 "general_operand" "")))
   (clobber (match_scratch:HI 3 "=X"))]
   (clobber (match_scratch:HI 3 "=X"))]
  "0 && reload_completed && z_replacement_completed == 2"
  "0 && reload_completed && z_replacement_completed == 2"
  [(set (reg:HI X_REGNUM) (plus:HI (reg:HI X_REGNUM) (match_dup 4)))]
  [(set (reg:HI X_REGNUM) (plus:HI (reg:HI X_REGNUM) (match_dup 4)))]
  "
  "
{
{
  operands[4] = m68hc11_gen_lowpart (HImode, operands[2]);
  operands[4] = m68hc11_gen_lowpart (HImode, operands[2]);
}")
}")
(define_insn_and_split "addsi_andshr16"
(define_insn_and_split "addsi_andshr16"
  [(set (match_operand:SI 0 "register_operand" "=D")
  [(set (match_operand:SI 0 "register_operand" "=D")
          (plus:SI (and:SI (match_operand:SI 1 "general_operand" "%uim")
          (plus:SI (and:SI (match_operand:SI 1 "general_operand" "%uim")
                           (const_int 65535))
                           (const_int 65535))
                   (match_operand:SI 2 "general_operand" "0")))]
                   (match_operand:SI 2 "general_operand" "0")))]
  ""
  ""
  "#"
  "#"
  "z_replacement_completed == 2"
  "z_replacement_completed == 2"
  [(set (reg:HI D_REGNUM) (plus:HI (reg:HI D_REGNUM) (match_dup 3)))
  [(set (reg:HI D_REGNUM) (plus:HI (reg:HI D_REGNUM) (match_dup 3)))
   (set (reg:HI X_REGNUM) (plus:HI (plus:HI (reg:HI X_REGNUM) (const_int 0)) (reg:HI CC_REGNUM)))]
   (set (reg:HI X_REGNUM) (plus:HI (plus:HI (reg:HI X_REGNUM) (const_int 0)) (reg:HI CC_REGNUM)))]
  "operands[3] = m68hc11_gen_lowpart (HImode, operands[1]);")
  "operands[3] = m68hc11_gen_lowpart (HImode, operands[1]);")
;;
;;
;; 32-bit shifts are made by a small library routine that uses
;; 32-bit shifts are made by a small library routine that uses
;; a specific passing convention for parameters (for efficiency reasons).
;; a specific passing convention for parameters (for efficiency reasons).
;;
;;
;; [D + X] -> Value to be shifted
;; [D + X] -> Value to be shifted
;; Y       -> Shift count
;; Y       -> Shift count
;;
;;
;; The shift count is clobbered by the routine.
;; The shift count is clobbered by the routine.
;;
;;
(define_expand "ashlsi3"
(define_expand "ashlsi3"
  [(parallel
  [(parallel
       [(set (match_operand:SI 0 "register_operand" "")
       [(set (match_operand:SI 0 "register_operand" "")
             (match_operand:SI 1 "general_operand" ""))
             (match_operand:SI 1 "general_operand" ""))
        (clobber (scratch:HI))])
        (clobber (scratch:HI))])
   (parallel
   (parallel
     [(set (match_dup 0) (ashift:SI (match_dup 0)
     [(set (match_dup 0) (ashift:SI (match_dup 0)
                         (match_operand:HI 2 "nonmemory_operand" "")))
                         (match_operand:HI 2 "nonmemory_operand" "")))
      (clobber (scratch:HI))])]
      (clobber (scratch:HI))])]
   ""
   ""
   "")
   "")
(define_split
(define_split
  [(set (match_operand:SI 0 "nonimmediate_operand" "")
  [(set (match_operand:SI 0 "nonimmediate_operand" "")
        (ashift:SI (match_operand:SI 1 "general_operand" "")
        (ashift:SI (match_operand:SI 1 "general_operand" "")
                   (const_int 16)))
                   (const_int 16)))
   (clobber (match_scratch:HI 3 ""))]
   (clobber (match_scratch:HI 3 ""))]
   ""
   ""
  [(set (match_dup 2) (match_dup 3))
  [(set (match_dup 2) (match_dup 3))
   (set (match_dup 4) (const_int 0))]
   (set (match_dup 4) (const_int 0))]
   "operands[2] = m68hc11_gen_highpart (HImode, operands[0]);
   "operands[2] = m68hc11_gen_highpart (HImode, operands[0]);
    operands[4] = m68hc11_gen_lowpart (HImode, operands[0]);
    operands[4] = m68hc11_gen_lowpart (HImode, operands[0]);
    operands[3] = m68hc11_gen_lowpart (HImode, operands[1]);")
    operands[3] = m68hc11_gen_lowpart (HImode, operands[1]);")
(define_insn "*ashlsi3_const16"
(define_insn "*ashlsi3_const16"
  [(set (match_operand:SI 0 "nonimmediate_operand" "=D,m,*u")
  [(set (match_operand:SI 0 "nonimmediate_operand" "=D,m,*u")
        (ashift:SI (match_operand:SI 1 "general_operand" "Duim,D,D")
        (ashift:SI (match_operand:SI 1 "general_operand" "Duim,D,D")
                   (const_int 16)))
                   (const_int 16)))
   (clobber (match_scratch:HI 2 "=X,X,X"))]
   (clobber (match_scratch:HI 2 "=X,X,X"))]
   ""
   ""
   "#")
   "#")
(define_insn_and_split "*ashlsi3_const16_zexthi"
(define_insn_and_split "*ashlsi3_const16_zexthi"
  [(set (match_operand:SI 0 "nonimmediate_operand" "=D")
  [(set (match_operand:SI 0 "nonimmediate_operand" "=D")
        (ashift:SI (zero_extend:HI
        (ashift:SI (zero_extend:HI
                        (match_operand:HI 1 "general_operand" "duim*A"))
                        (match_operand:HI 1 "general_operand" "duim*A"))
                   (const_int 16)))
                   (const_int 16)))
   (clobber (match_scratch:HI 2 "=X"))]
   (clobber (match_scratch:HI 2 "=X"))]
   ""
   ""
   "#"
   "#"
   "reload_completed"
   "reload_completed"
   [(set (reg:HI X_REGNUM) (match_dup 1))
   [(set (reg:HI X_REGNUM) (match_dup 1))
    (set (reg:HI D_REGNUM) (const_int 0))]
    (set (reg:HI D_REGNUM) (const_int 0))]
   "")
   "")
(define_insn "*ashlsi3_const1"
(define_insn "*ashlsi3_const1"
  [(set (match_operand:SI 0 "non_push_operand" "=D,D,D,m,*u,*u")
  [(set (match_operand:SI 0 "non_push_operand" "=D,D,D,m,*u,*u")
        (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "0,m,*u,m,*u,m")
        (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "0,m,*u,m,*u,m")
                   (const_int 1)))
                   (const_int 1)))
   (clobber (match_scratch:HI 2 "=X,X,X,&d,&d,&d"))]
   (clobber (match_scratch:HI 2 "=X,X,X,&d,&d,&d"))]
   ""
   ""
   "*
   "*
{
{
  CC_STATUS_INIT;
  CC_STATUS_INIT;
  if (X_REG_P (operands[1]))
  if (X_REG_P (operands[1]))
    {
    {
      return \"lsld\\n\\txgdx\\n\\trolb\\n\\trola\\n\\txgdx\";
      return \"lsld\\n\\txgdx\\n\\trolb\\n\\trola\\n\\txgdx\";
    }
    }
  else
  else
    {
    {
      rtx ops[2];
      rtx ops[2];
      ops[1] = m68hc11_gen_lowpart (HImode, operands[1]);
      ops[1] = m68hc11_gen_lowpart (HImode, operands[1]);
      ops[0] = gen_rtx_REG (HImode, HARD_D_REGNUM);
      ops[0] = gen_rtx_REG (HImode, HARD_D_REGNUM);
      m68hc11_gen_movhi (insn, ops);
      m68hc11_gen_movhi (insn, ops);
      output_asm_insn (\"lsld\", ops);
      output_asm_insn (\"lsld\", ops);
      if (!X_REG_P (operands[0]))
      if (!X_REG_P (operands[0]))
        {
        {
          ops[1] = ops[0];
          ops[1] = ops[0];
          ops[0] = m68hc11_gen_lowpart (HImode, operands[0]);
          ops[0] = m68hc11_gen_lowpart (HImode, operands[0]);
          m68hc11_gen_movhi (insn, ops);
          m68hc11_gen_movhi (insn, ops);
          ops[0] = ops[1];
          ops[0] = ops[1];
          ops[1] = m68hc11_gen_highpart (HImode, operands[1]);
          ops[1] = m68hc11_gen_highpart (HImode, operands[1]);
          m68hc11_gen_movhi (insn, ops);
          m68hc11_gen_movhi (insn, ops);
        }
        }
      else
      else
        {
        {
          /* Load the high part in X in case the source operand
          /* Load the high part in X in case the source operand
             uses X as a memory pointer.  */
             uses X as a memory pointer.  */
          ops[0] = gen_rtx_REG (HImode, HARD_X_REGNUM);
          ops[0] = gen_rtx_REG (HImode, HARD_X_REGNUM);
          ops[1] = m68hc11_gen_highpart (HImode, operands[1]);
          ops[1] = m68hc11_gen_highpart (HImode, operands[1]);
          m68hc11_gen_movhi (insn, ops);
          m68hc11_gen_movhi (insn, ops);
          output_asm_insn (\"xgdx\", ops);
          output_asm_insn (\"xgdx\", ops);
        }
        }
      output_asm_insn (\"rolb\", ops);
      output_asm_insn (\"rolb\", ops);
      output_asm_insn (\"rola\", ops);
      output_asm_insn (\"rola\", ops);
      if (!X_REG_P (operands[0]))
      if (!X_REG_P (operands[0]))
        {
        {
          ops[1] = ops[0];
          ops[1] = ops[0];
          ops[0] = m68hc11_gen_highpart (HImode, operands[0]);
          ops[0] = m68hc11_gen_highpart (HImode, operands[0]);
          m68hc11_gen_movhi (insn, ops);
          m68hc11_gen_movhi (insn, ops);
        }
        }
      else
      else
        {
        {
          output_asm_insn (\"xgdx\", ops);
          output_asm_insn (\"xgdx\", ops);
        }
        }
      return \"\";
      return \"\";
    }
    }
}")
}")
(define_insn "*ashlsi3_const"
(define_insn "*ashlsi3_const"
  [(set (match_operand:SI 0 "register_operand" "+D")
  [(set (match_operand:SI 0 "register_operand" "+D")
        (ashift:SI (match_dup 0)
        (ashift:SI (match_dup 0)
                   (match_operand:HI 1 "const_int_operand" "")))
                   (match_operand:HI 1 "const_int_operand" "")))
   (clobber (match_scratch:HI 2 "=y"))]
   (clobber (match_scratch:HI 2 "=y"))]
   "TARGET_M6811 /* See *ashlsi3 note.  */"
   "TARGET_M6811 /* See *ashlsi3 note.  */"
   "*
   "*
{
{
  CC_STATUS_INIT;
  CC_STATUS_INIT;
  return \"ldy\\t%1\\n\\tbsr\\t___ashlsi3\";
  return \"ldy\\t%1\\n\\tbsr\\t___ashlsi3\";
}")
}")
(define_insn "*ashlsi3"
(define_insn "*ashlsi3"
  [(set (match_operand:SI 0 "register_operand" "+D,D")
  [(set (match_operand:SI 0 "register_operand" "+D,D")
        (ashift:SI (match_dup 0)
        (ashift:SI (match_dup 0)
                   (match_operand:HI 1 "general_operand" "y,mi")))
                   (match_operand:HI 1 "general_operand" "y,mi")))
   (clobber (match_scratch:HI 2 "=1,X"))]
   (clobber (match_scratch:HI 2 "=1,X"))]
   ""
   ""
   "*
   "*
{
{
  CC_STATUS_INIT;
  CC_STATUS_INIT;
  /* There is a reload problem if we don't accept 'm' for the shift value.
  /* There is a reload problem if we don't accept 'm' for the shift value.
     A RELOAD_OTHER reload can be generated for operand 0 (class A_REGS)
     A RELOAD_OTHER reload can be generated for operand 0 (class A_REGS)
     and this conflicts with all reloads.  Since X, Y, Z are used there
     and this conflicts with all reloads.  Since X, Y, Z are used there
     is not enough register in class A_REGS.
     is not enough register in class A_REGS.
     Assuming that 'operands[1]' does not refer to the stack (which
     Assuming that 'operands[1]' does not refer to the stack (which
     is true for 68hc11 only, we save temporary the value of Y.
     is true for 68hc11 only, we save temporary the value of Y.
     For 68HC12 we must also accept a constant because Z register is
     For 68HC12 we must also accept a constant because Z register is
     disabled when compiling with -fomit-frame-pointer.  We can come up
     disabled when compiling with -fomit-frame-pointer.  We can come up
     with a reload problem and the *lshrsi3_const pattern was disabled
     with a reload problem and the *lshrsi3_const pattern was disabled
     for that reason.  */
     for that reason.  */
  if (!Y_REG_P (operands[2]))
  if (!Y_REG_P (operands[2]))
    {
    {
      rtx ops[1];
      rtx ops[1];
      int y_dead = dead_register_here (insn, iy_reg);
      int y_dead = dead_register_here (insn, iy_reg);
      ops[0] = operands[1];
      ops[0] = operands[1];
      if (y_dead == 0)
      if (y_dead == 0)
        {
        {
          output_asm_insn (\"pshy\", operands);
          output_asm_insn (\"pshy\", operands);
          if (reg_mentioned_p (stack_pointer_rtx, operands[1]))
          if (reg_mentioned_p (stack_pointer_rtx, operands[1]))
            ops[0] = adjust_address (operands[1], GET_MODE (operands[1]), 2);
            ops[0] = adjust_address (operands[1], GET_MODE (operands[1]), 2);
        }
        }
      output_asm_insn (\"ldy\\t%0\", ops);
      output_asm_insn (\"ldy\\t%0\", ops);
      output_asm_insn (\"bsr\\t___ashlsi3\", operands);
      output_asm_insn (\"bsr\\t___ashlsi3\", operands);
      return y_dead == 0 ? \"puly\" : \"\";
      return y_dead == 0 ? \"puly\" : \"\";
    }
    }
  return \"bsr\\t___ashlsi3\";
  return \"bsr\\t___ashlsi3\";
}")
}")
(define_expand "ashlhi3"
(define_expand "ashlhi3"
  [(set (match_operand:HI 0 "register_operand" "")
  [(set (match_operand:HI 0 "register_operand" "")
        (ashift:HI (match_operand:HI 1 "register_operand" "")
        (ashift:HI (match_operand:HI 1 "register_operand" "")
                   (match_operand:HI 2 "general_operand" "")))]
                   (match_operand:HI 2 "general_operand" "")))]
   ""
   ""
   "
   "
{
{
  if (GET_CODE (operands[2]) != CONST_INT)
  if (GET_CODE (operands[2]) != CONST_INT)
    {
    {
      rtx scratch = gen_reg_rtx (HImode);
      rtx scratch = gen_reg_rtx (HImode);
      emit_move_insn (scratch, operands[2]);
      emit_move_insn (scratch, operands[2]);
      emit_insn (gen_rtx_PARALLEL (VOIDmode,
      emit_insn (gen_rtx_PARALLEL (VOIDmode,
                 gen_rtvec (2, gen_rtx_SET (VOIDmode,
                 gen_rtvec (2, gen_rtx_SET (VOIDmode,
                            operand0,
                            operand0,
                            gen_rtx_ASHIFT (HImode,
                            gen_rtx_ASHIFT (HImode,
                                        operand1, scratch)),
                                        operand1, scratch)),
                              gen_rtx_CLOBBER (VOIDmode, scratch))));
                              gen_rtx_CLOBBER (VOIDmode, scratch))));
      DONE;
      DONE;
    }
    }
}")
}")
(define_insn "*ashlhi3_const1"
(define_insn "*ashlhi3_const1"
  [(set (match_operand:HI 0 "non_push_operand" "=dm,!*u*A")
  [(set (match_operand:HI 0 "non_push_operand" "=dm,!*u*A")
        (ashift:HI (match_operand:HI 1 "non_push_operand" "0,0")
        (ashift:HI (match_operand:HI 1 "non_push_operand" "0,0")
                   (const_int 1)))]
                   (const_int 1)))]
  ""
  ""
  "*
  "*
{
{
  if (A_REG_P (operands[0]))
  if (A_REG_P (operands[0]))
    return \"#\";
    return \"#\";
  if (D_REG_P (operands[0]))
  if (D_REG_P (operands[0]))
    {
    {
      return \"asld\";
      return \"asld\";
    }
    }
  output_asm_insn (\"asl\\t%b0\", operands);
  output_asm_insn (\"asl\\t%b0\", operands);
  output_asm_insn (\"rol\\t%h0\", operands);
  output_asm_insn (\"rol\\t%h0\", operands);
  CC_STATUS_INIT;
  CC_STATUS_INIT;
  return \"\";
  return \"\";
}")
}")
(define_insn "*ashlhi3_2"
(define_insn "*ashlhi3_2"
  [(set (match_operand:HI 0 "register_operand" "=d,*x")
  [(set (match_operand:HI 0 "register_operand" "=d,*x")
        (ashift:HI (match_operand:HI 1 "register_operand" "0,0")
        (ashift:HI (match_operand:HI 1 "register_operand" "0,0")
                   (match_operand:HI 2 "register_operand" "+x,+d")))
                   (match_operand:HI 2 "register_operand" "+x,+d")))
   (clobber (match_dup 2))]
   (clobber (match_dup 2))]
  ""
  ""
  "*
  "*
{
{
  if (A_REG_P (operands[0]))
  if (A_REG_P (operands[0]))
    return \"#\";
    return \"#\";
  CC_STATUS_INIT;
  CC_STATUS_INIT;
  return \"bsr\\t___lshlhi3\";
  return \"bsr\\t___lshlhi3\";
}")
}")
(define_insn "*ashlhi3"
(define_insn "*ashlhi3"
  [(set (strict_low_part (match_operand:HI 0 "register_operand" "+d"))
  [(set (strict_low_part (match_operand:HI 0 "register_operand" "+d"))
        (ashift:HI (match_dup 0)
        (ashift:HI (match_dup 0)
                   (match_operand:HI 1 "register_operand" "+x")))
                   (match_operand:HI 1 "register_operand" "+x")))
   (clobber (match_dup 1))]
   (clobber (match_dup 1))]
  ""
  ""
  "*
  "*
{
{
  CC_STATUS_INIT;
  CC_STATUS_INIT;
  return \"bsr\\t___lshlhi3\";
  return \"bsr\\t___lshlhi3\";
}")
}")
(define_insn "*ashlhi3"
(define_insn "*ashlhi3"
  [(set (match_operand:HI 0 "register_operand" "=d,!*A")
  [(set (match_operand:HI 0 "register_operand" "=d,!*A")
        (ashift:HI (match_operand:HI 1 "register_operand" "0,0")
        (ashift:HI (match_operand:HI 1 "register_operand" "0,0")
                   (match_operand:HI 2 "const_int_operand" "")))]
                   (match_operand:HI 2 "const_int_operand" "")))]
  ""
  ""
  "*
  "*
{
{
  int   i;
  int   i;
  if (A_REG_P (operands[0]))
  if (A_REG_P (operands[0]))
    return \"#\";
    return \"#\";
  i = INTVAL (operands[2]);
  i = INTVAL (operands[2]);
  if (i >= 8)
  if (i >= 8)
    {
    {
      CC_STATUS_INIT;
      CC_STATUS_INIT;
      output_asm_insn (\"tba\", operands);
      output_asm_insn (\"tba\", operands);
      if (i == 15)
      if (i == 15)
        {
        {
          output_asm_insn (\"rora\", operands);
          output_asm_insn (\"rora\", operands);
          output_asm_insn (\"anda\\t#0\", operands);
          output_asm_insn (\"anda\\t#0\", operands);
          output_asm_insn (\"rora\", operands);
          output_asm_insn (\"rora\", operands);
        }
        }
      else
      else
        while (i != 8 )
        while (i != 8 )
          {
          {
            output_asm_insn (\"asla\", operands);
            output_asm_insn (\"asla\", operands);
            i--;
            i--;
          }
          }
      return \"clrb\";
      return \"clrb\";
    }
    }
  for (i = 0; i < INTVAL (operands[2]) - 1; i++)
  for (i = 0; i < INTVAL (operands[2]) - 1; i++)
    {
    {
      output_asm_insn (\"asld\", operands);
      output_asm_insn (\"asld\", operands);
    }
    }
  return \"asld\";
  return \"asld\";
}")
}")
(define_expand "ashlqi3"
(define_expand "ashlqi3"
  [(set (match_operand:QI 0 "register_operand" "")
  [(set (match_operand:QI 0 "register_operand" "")
        (ashift:QI (match_operand:QI 1 "register_operand" "")
        (ashift:QI (match_operand:QI 1 "register_operand" "")
                   (match_operand:QI 2 "general_operand" "")))]
                   (match_operand:QI 2 "general_operand" "")))]
   ""
   ""
   "")
   "")
(define_insn "*ashlqi3_const1"
(define_insn "*ashlqi3_const1"
  [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m,!u,!*q,!*A")
  [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m,!u,!*q,!*A")
        (ashift:QI (match_operand:QI 1 "nonimmediate_operand" "0,0,0,0,0")
        (ashift:QI (match_operand:QI 1 "nonimmediate_operand" "0,0,0,0,0")
                   (const_int 1)))]
                   (const_int 1)))]
  ""
  ""
  "@
  "@
   aslb
   aslb
   asl\\t%b0
   asl\\t%b0
   asl\\t%b0
   asl\\t%b0
   asl%0
   asl%0
   #")
   #")
(define_insn "*ashlqi3_const"
(define_insn "*ashlqi3_const"
  [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
  [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
        (ashift:QI (match_operand:QI 1 "register_operand" "0,0,0")
        (ashift:QI (match_operand:QI 1 "register_operand" "0,0,0")
                   (match_operand:QI 2 "const_int_operand" "")))]
                   (match_operand:QI 2 "const_int_operand" "")))]
  ""
  ""
  "*
  "*
{
{
  int i;
  int i;
  const char* insn_code;
  const char* insn_code;
  if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
  if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
    insn_code = \"aslb\";
    insn_code = \"aslb\";
  else if (DA_REG_P (operands[0]))
  else if (DA_REG_P (operands[0]))
    insn_code = \"asla\";
    insn_code = \"asla\";
  else
  else
    return \"#\";
    return \"#\";
  i = INTVAL (operands[2]);
  i = INTVAL (operands[2]);
  if (i >= 8)
  if (i >= 8)
    {
    {
      if (DA_REG_P (operands[0]))
      if (DA_REG_P (operands[0]))
        return \"clra\";
        return \"clra\";
      else
      else
        return \"clrb\";
        return \"clrb\";
    }
    }
  else if (i == 7)
  else if (i == 7)
    {
    {
      if (DA_REG_P (operands[0]))
      if (DA_REG_P (operands[0]))
        {
        {
          output_asm_insn (\"rora\", operands);
          output_asm_insn (\"rora\", operands);
          output_asm_insn (\"ldaa\\t#0\", operands);
          output_asm_insn (\"ldaa\\t#0\", operands);
          return \"rora\";
          return \"rora\";
        }
        }
      else
      else
        {
        {
          output_asm_insn (\"rorb\", operands);
          output_asm_insn (\"rorb\", operands);
          output_asm_insn (\"ldab\\t#0\", operands);
          output_asm_insn (\"ldab\\t#0\", operands);
          return \"rorb\";
          return \"rorb\";
        }
        }
    }
    }
  else if (i == 6)
  else if (i == 6)
    {
    {
      if (DA_REG_P (operands[0]))
      if (DA_REG_P (operands[0]))
        {
        {
          output_asm_insn (\"rora\", operands);
          output_asm_insn (\"rora\", operands);
          output_asm_insn (\"rora\", operands);
          output_asm_insn (\"rora\", operands);
          output_asm_insn (\"rora\", operands);
          output_asm_insn (\"rora\", operands);
          return \"anda\\t#0xC0\";
          return \"anda\\t#0xC0\";
        }
        }
      else
      else
        {
        {
          output_asm_insn (\"rorb\", operands);
          output_asm_insn (\"rorb\", operands);
          output_asm_insn (\"rorb\", operands);
          output_asm_insn (\"rorb\", operands);
          output_asm_insn (\"rorb\", operands);
          output_asm_insn (\"rorb\", operands);
          return \"andb\\t#0xC0\";
          return \"andb\\t#0xC0\";
        }
        }
    }
    }
  while (--i >= 0)
  while (--i >= 0)
    {
    {
      output_asm_insn (insn_code, operands);
      output_asm_insn (insn_code, operands);
    }
    }
  return \"\";
  return \"\";
}")
}")
(define_insn "*ashlqi3"
(define_insn "*ashlqi3"
  [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
  [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
        (ashift:QI (match_operand:QI 1 "register_operand" "0,0,0")
        (ashift:QI (match_operand:QI 1 "register_operand" "0,0,0")
                     (match_operand:QI 2 "nonimmediate_operand"
                     (match_operand:QI 2 "nonimmediate_operand"
                                         "m*u*d*A,m*u*d*A,m*u")))]
                                         "m*u*d*A,m*u*d*A,m*u")))]
  ""
  ""
  "*
  "*
{
{
  rtx ops[2];
  rtx ops[2];
  if (!D_REG_P (operands[0]) && !Q_REG_P (operands[0]))
  if (!D_REG_P (operands[0]) && !Q_REG_P (operands[0]))
    return \"#\";
    return \"#\";
  ops[0] = gen_rtx_REG (QImode, HARD_A_REGNUM);
  ops[0] = gen_rtx_REG (QImode, HARD_A_REGNUM);
  ops[1] = operands[2];
  ops[1] = operands[2];
  m68hc11_gen_movqi (insn, ops);
  m68hc11_gen_movqi (insn, ops);
  CC_STATUS_INIT;
  CC_STATUS_INIT;
  return \"bsr\\t___lshlqi3\";
  return \"bsr\\t___lshlqi3\";
}")
}")
(define_expand "ashrhi3"
(define_expand "ashrhi3"
  [(set (match_operand:HI 0 "register_operand" "")
  [(set (match_operand:HI 0 "register_operand" "")
        (ashiftrt:HI (match_operand:HI 1 "register_operand" "")
        (ashiftrt:HI (match_operand:HI 1 "register_operand" "")
                     (match_operand:HI 2 "general_operand" "")))]
                     (match_operand:HI 2 "general_operand" "")))]
   ""
   ""
   "
   "
{
{
  if (GET_CODE (operands[2]) != CONST_INT)
  if (GET_CODE (operands[2]) != CONST_INT)
    {
    {
      rtx scratch = gen_reg_rtx (HImode);
      rtx scratch = gen_reg_rtx (HImode);
      emit_move_insn (scratch, operands[2]);
      emit_move_insn (scratch, operands[2]);
      emit_insn (gen_rtx_PARALLEL (VOIDmode,
      emit_insn (gen_rtx_PARALLEL (VOIDmode,
                 gen_rtvec (2, gen_rtx_SET (VOIDmode,
                 gen_rtvec (2, gen_rtx_SET (VOIDmode,
                                operand0,
                                operand0,
                                gen_rtx_ASHIFTRT (HImode,
                                gen_rtx_ASHIFTRT (HImode,
                                        operand1, scratch)),
                                        operand1, scratch)),
                              gen_rtx_CLOBBER (VOIDmode, scratch))));
                              gen_rtx_CLOBBER (VOIDmode, scratch))));
       DONE;
       DONE;
    }
    }
}")
}")
(define_insn "*ashrhi3_const1"
(define_insn "*ashrhi3_const1"
  [(set (match_operand:HI 0 "non_push_operand" "=dm,!*u*A")
  [(set (match_operand:HI 0 "non_push_operand" "=dm,!*u*A")
        (ashiftrt:HI (match_operand:HI 1 "non_push_operand" "0,0")
        (ashiftrt:HI (match_operand:HI 1 "non_push_operand" "0,0")
                     (const_int 1)))]
                     (const_int 1)))]
  ""
  ""
  "*
  "*
{
{
  if (A_REG_P (operands[0]))
  if (A_REG_P (operands[0]))
    return \"#\";
    return \"#\";
  CC_STATUS_INIT;
  CC_STATUS_INIT;
  if (D_REG_P (operands[0]))
  if (D_REG_P (operands[0]))
    {
    {
      return \"asra\\n\\trorb\";
      return \"asra\\n\\trorb\";
    }
    }
  output_asm_insn (\"asr\\t%h0\", operands);
  output_asm_insn (\"asr\\t%h0\", operands);
  output_asm_insn (\"ror\\t%b0\", operands);
  output_asm_insn (\"ror\\t%b0\", operands);
  return \"\";
  return \"\";
}")
}")
(define_insn "*ashrhi3_const"
(define_insn "*ashrhi3_const"
  [(set (match_operand:HI 0 "register_operand" "=d,!*A")
  [(set (match_operand:HI 0 "register_operand" "=d,!*A")
        (ashiftrt:HI (match_operand:HI 1 "register_operand" "0,0")
        (ashiftrt:HI (match_operand:HI 1 "register_operand" "0,0")
                     (match_operand:HI 2 "const_int_operand" "")))]
                     (match_operand:HI 2 "const_int_operand" "")))]
  ""
  ""
  "*
  "*
{
{
  rtx ops[2];
  rtx ops[2];
  int val = INTVAL (operands[2]);
  int val = INTVAL (operands[2]);
  if (A_REG_P (operands[0]))
  if (A_REG_P (operands[0]))
    return \"#\";
    return \"#\";
  if (val >= 15)
  if (val >= 15)
    {
    {
      ops[0] = gen_label_rtx ();
      ops[0] = gen_label_rtx ();
      output_asm_insn (\"clrb\", operands);
      output_asm_insn (\"clrb\", operands);
      output_asm_insn (\"rola\", operands);
      output_asm_insn (\"rola\", operands);
        /* Clear A without clearing the carry flag.  */
        /* Clear A without clearing the carry flag.  */
      output_asm_insn (\"tba\", operands);
      output_asm_insn (\"tba\", operands);
      output_asm_insn (\"bcc\\t%l0\", ops);
      output_asm_insn (\"bcc\\t%l0\", ops);
      output_asm_insn (\"coma\", operands);
      output_asm_insn (\"coma\", operands);
      output_asm_insn (\"comb\", operands);
      output_asm_insn (\"comb\", operands);
      CC_STATUS_INIT;
      CC_STATUS_INIT;
      (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
      (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
                                 CODE_LABEL_NUMBER (ops[0]));
                                 CODE_LABEL_NUMBER (ops[0]));
      return \"\";
      return \"\";
    }
    }
  if (val >= 8)
  if (val >= 8)
    {
    {
      ops[0] = gen_label_rtx ();
      ops[0] = gen_label_rtx ();
      output_asm_insn (\"tab\", operands);
      output_asm_insn (\"tab\", operands);
      output_asm_insn (\"clra\", operands);
      output_asm_insn (\"clra\", operands);
      output_asm_insn (\"tstb\", operands);
      output_asm_insn (\"tstb\", operands);
      output_asm_insn (\"bge\\t%l0\", ops);
      output_asm_insn (\"bge\\t%l0\", ops);
      output_asm_insn (\"deca\", operands);
      output_asm_insn (\"deca\", operands);
      (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
      (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
                                 CODE_LABEL_NUMBER (ops[0]));
                                 CODE_LABEL_NUMBER (ops[0]));
      val -= 8;
      val -= 8;
      while (val > 0)
      while (val > 0)
        {
        {
          output_asm_insn (\"asrb\", operands);
          output_asm_insn (\"asrb\", operands);
          val--;
          val--;
        }
        }
        /* Status is ok.  */
        /* Status is ok.  */
      return \"\";
      return \"\";
    }
    }
  if (val == 7)
  if (val == 7)
    {
    {
      ops[0] = gen_label_rtx ();
      ops[0] = gen_label_rtx ();
      output_asm_insn (\"rolb\", operands);
      output_asm_insn (\"rolb\", operands);
      output_asm_insn (\"rola\", operands);
      output_asm_insn (\"rola\", operands);
      output_asm_insn (\"tab\", operands);
      output_asm_insn (\"tab\", operands);
      output_asm_insn (\"anda\\t#0\", operands);
      output_asm_insn (\"anda\\t#0\", operands);
      output_asm_insn (\"bcc\\t%l0\", ops);
      output_asm_insn (\"bcc\\t%l0\", ops);
      output_asm_insn (\"coma\", ops);
      output_asm_insn (\"coma\", ops);
      (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
      (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
                                 CODE_LABEL_NUMBER (ops[0]));
                                 CODE_LABEL_NUMBER (ops[0]));
      return \"\";
      return \"\";
    }
    }
  while (val > 0)
  while (val > 0)
    {
    {
      output_asm_insn (\"asra\", operands);
      output_asm_insn (\"asra\", operands);
      output_asm_insn (\"rorb\", operands);
      output_asm_insn (\"rorb\", operands);
      val--;
      val--;
    }
    }
  CC_STATUS_INIT;
  CC_STATUS_INIT;
  return \"\";
  return \"\";
}")
}")
(define_insn "*ashrhi3"
(define_insn "*ashrhi3"
  [(set (match_operand:HI 0 "register_operand" "=d,*x")
  [(set (match_operand:HI 0 "register_operand" "=d,*x")
        (ashiftrt:HI (match_operand:HI 1 "register_operand" "0,0")
        (ashiftrt:HI (match_operand:HI 1 "register_operand" "0,0")
                     (match_operand:HI 2 "register_operand" "+x,+d")))
                     (match_operand:HI 2 "register_operand" "+x,+d")))
   (clobber (match_dup 2))]
   (clobber (match_dup 2))]
  ""
  ""
  "*
  "*
{
{
  if (A_REG_P (operands[0]))
  if (A_REG_P (operands[0]))
    return \"#\";
    return \"#\";
  output_asm_insn (\"bsr\\t___ashrhi3\", operands);
  output_asm_insn (\"bsr\\t___ashrhi3\", operands);
  return \"\";
  return \"\";
}")
}")
(define_expand "ashrsi3"
(define_expand "ashrsi3"
  [(parallel
  [(parallel
       [(set (match_dup 0) (match_operand:SI 1 "general_operand" ""))
       [(set (match_dup 0) (match_operand:SI 1 "general_operand" ""))
        (clobber (scratch:HI))])
        (clobber (scratch:HI))])
   (parallel
   (parallel
       [(set (match_operand:SI 0 "register_operand" "")
       [(set (match_operand:SI 0 "register_operand" "")
                (ashiftrt:SI (match_dup 0)
                (ashiftrt:SI (match_dup 0)
                             (match_operand:HI 2 "general_operand" "")))
                             (match_operand:HI 2 "general_operand" "")))
        (clobber (scratch:HI))])]
        (clobber (scratch:HI))])]
   ""
   ""
   "")
   "")
(define_insn "*ashrsi3_const"
(define_insn "*ashrsi3_const"
  [(set (match_operand:SI 0 "register_operand" "+D")
  [(set (match_operand:SI 0 "register_operand" "+D")
        (ashiftrt:SI (match_dup 0)
        (ashiftrt:SI (match_dup 0)
                     (match_operand:HI 1 "const_int_operand" "")))
                     (match_operand:HI 1 "const_int_operand" "")))
   (clobber (match_scratch:HI 2 "=y"))]
   (clobber (match_scratch:HI 2 "=y"))]
   "TARGET_M6811 /* See *ashrsi3 note.  */"
   "TARGET_M6811 /* See *ashrsi3 note.  */"
   "*
   "*
{
{
  CC_STATUS_INIT;
  CC_STATUS_INIT;
  return \"ldy\\t%1\\n\\tbsr\\t___ashrsi3\";
  return \"ldy\\t%1\\n\\tbsr\\t___ashrsi3\";
}")
}")
(define_insn "*ashrsi3"
(define_insn "*ashrsi3"
  [(set (match_operand:SI 0 "register_operand" "+D,D")
  [(set (match_operand:SI 0 "register_operand" "+D,D")
        (ashiftrt:SI (match_dup 0)
        (ashiftrt:SI (match_dup 0)
                     (match_operand:HI 1 "general_operand" "y,mi")))
                     (match_operand:HI 1 "general_operand" "y,mi")))
   (clobber (match_scratch:HI 2 "=1,X"))]
   (clobber (match_scratch:HI 2 "=1,X"))]
   ""
   ""
   "*
   "*
{
{
  CC_STATUS_INIT;
  CC_STATUS_INIT;
  /* There is a reload problem if we don't accept 'm' for the shift value.
  /* There is a reload problem if we don't accept 'm' for the shift value.
     A RELOAD_OTHER reload can be generated for operand 0 (class A_REGS)
     A RELOAD_OTHER reload can be generated for operand 0 (class A_REGS)
     and this conflicts with all reloads.  Since X, Y, Z are used there
     and this conflicts with all reloads.  Since X, Y, Z are used there
     is not enough register in class A_REGS.
     is not enough register in class A_REGS.
     Assuming that 'operands[1]' does not refer to the stack (which
     Assuming that 'operands[1]' does not refer to the stack (which
     is true for 68hc11 only, we save temporary the value of Y.
     is true for 68hc11 only, we save temporary the value of Y.
     For 68HC12 we must also accept a constant because Z register is
     For 68HC12 we must also accept a constant because Z register is
     disabled when compiling with -fomit-frame-pointer.  We can come up
     disabled when compiling with -fomit-frame-pointer.  We can come up
     with a reload problem and the *lshrsi3_const pattern was disabled
     with a reload problem and the *lshrsi3_const pattern was disabled
     for that reason.  */
     for that reason.  */
  if (!Y_REG_P (operands[2]))
  if (!Y_REG_P (operands[2]))
    {
    {
      rtx ops[1];
      rtx ops[1];
      int y_dead = dead_register_here (insn, iy_reg);
      int y_dead = dead_register_here (insn, iy_reg);
      ops[0] = operands[1];
      ops[0] = operands[1];
      if (y_dead == 0)
      if (y_dead == 0)
        {
        {
          output_asm_insn (\"pshy\", operands);
          output_asm_insn (\"pshy\", operands);
          if (reg_mentioned_p (stack_pointer_rtx, operands[1]))
          if (reg_mentioned_p (stack_pointer_rtx, operands[1]))
            ops[0] = adjust_address (operands[1], GET_MODE (operands[1]), 2);
            ops[0] = adjust_address (operands[1], GET_MODE (operands[1]), 2);
        }
        }
      output_asm_insn (\"ldy\\t%0\", ops);
      output_asm_insn (\"ldy\\t%0\", ops);
      output_asm_insn (\"bsr\\t___ashrsi3\", operands);
      output_asm_insn (\"bsr\\t___ashrsi3\", operands);
      return y_dead == 0 ? \"puly\" : \"\";
      return y_dead == 0 ? \"puly\" : \"\";
    }
    }
  return \"bsr\\t___ashrsi3\";
  return \"bsr\\t___ashrsi3\";
}")
}")
(define_expand "ashrqi3"
(define_expand "ashrqi3"
  [(set (match_operand:QI 0 "register_operand" "")
  [(set (match_operand:QI 0 "register_operand" "")
        (ashiftrt:QI (match_operand:QI 1 "register_operand" "")
        (ashiftrt:QI (match_operand:QI 1 "register_operand" "")
                     (match_operand:QI 2 "general_operand" "")))]
                     (match_operand:QI 2 "general_operand" "")))]
   ""
   ""
   "")
   "")
(define_insn "*ashrqi3_const1"
(define_insn "*ashrqi3_const1"
  [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m,!u,!*q,!*A")
  [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m,!u,!*q,!*A")
        (ashiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0,0,0,0,0")
        (ashiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0,0,0,0,0")
                     (const_int 1)))]
                     (const_int 1)))]
  ""
  ""
  "@
  "@
   asrb
   asrb
   asr\\t%b0
   asr\\t%b0
   asr\\t%b0
   asr\\t%b0
   asr%0
   asr%0
   #")
   #")
(define_insn "*ashrqi3_const"
(define_insn "*ashrqi3_const"
  [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
  [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
        (ashiftrt:QI (match_operand:QI 1 "register_operand" "0,0,0")
        (ashiftrt:QI (match_operand:QI 1 "register_operand" "0,0,0")
                     (match_operand:QI 2 "const_int_operand" "")))]
                     (match_operand:QI 2 "const_int_operand" "")))]
  ""
  ""
  "*
  "*
{
{
  int i;
  int i;
  const char* insn_code;
  const char* insn_code;
  if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
  if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
    insn_code = \"asrb\";
    insn_code = \"asrb\";
  else if (DA_REG_P (operands[0]))
  else if (DA_REG_P (operands[0]))
    insn_code = \"asra\";
    insn_code = \"asra\";
  else
  else
    return \"#\";
    return \"#\";
  i = INTVAL (operands[2]);
  i = INTVAL (operands[2]);
  if (i > 8)
  if (i > 8)
    i = 8;
    i = 8;
  while (--i >= 0)
  while (--i >= 0)
    {
    {
      output_asm_insn (insn_code, operands);
      output_asm_insn (insn_code, operands);
    }
    }
  return \"\";
  return \"\";
}")
}")
(define_insn "*ashrqi3"
(define_insn "*ashrqi3"
  [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
  [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
        (ashiftrt:QI (match_operand:QI 1 "register_operand" "0,0,0")
        (ashiftrt:QI (match_operand:QI 1 "register_operand" "0,0,0")
                     (match_operand:QI 2 "nonimmediate_operand"
                     (match_operand:QI 2 "nonimmediate_operand"
                                         "m*u*d*A,m*u*d*A,m*u")))]
                                         "m*u*d*A,m*u*d*A,m*u")))]
  ""
  ""
  "*
  "*
{
{
  rtx ops[2];
  rtx ops[2];
  if (!D_REG_P (operands[0]) && !Q_REG_P (operands[0]))
  if (!D_REG_P (operands[0]) && !Q_REG_P (operands[0]))
    return \"#\";
    return \"#\";
  ops[0] = gen_rtx_REG (QImode, HARD_A_REGNUM);
  ops[0] = gen_rtx_REG (QImode, HARD_A_REGNUM);
  ops[1] = operands[2];
  ops[1] = operands[2];
  m68hc11_gen_movqi (insn, ops);
  m68hc11_gen_movqi (insn, ops);
  CC_STATUS_INIT;
  CC_STATUS_INIT;
  return \"bsr\\t___ashrqi3\";
  return \"bsr\\t___ashrqi3\";
}")
}")
;;--------------------------------------------------------------------
;;--------------------------------------------------------------------
;; logical shift instructions
;; logical shift instructions
;;--------------------------------------------------------------------
;;--------------------------------------------------------------------
(define_expand "lshrdi3"
(define_expand "lshrdi3"
  [(parallel [(set (match_operand:DI 0 "general_operand" "")
  [(parallel [(set (match_operand:DI 0 "general_operand" "")
                     (lshiftrt:DI (match_operand:DI 1 "general_operand" "")
                     (lshiftrt:DI (match_operand:DI 1 "general_operand" "")
                                  (match_operand:HI 2 "general_operand" "")))
                                  (match_operand:HI 2 "general_operand" "")))
              (clobber (match_scratch:HI 3 ""))])]
              (clobber (match_scratch:HI 3 ""))])]
   ""
   ""
   "
   "
{
{
  if (GET_CODE (operands[2]) != CONST_INT
  if (GET_CODE (operands[2]) != CONST_INT
     || (INTVAL (operands[2]) != 32 && INTVAL (operands[2]) < 48
     || (INTVAL (operands[2]) != 32 && INTVAL (operands[2]) < 48
         && INTVAL (operands[2]) != 1))
         && INTVAL (operands[2]) != 1))
    {
    {
      FAIL;
      FAIL;
    }
    }
}")
}")
(define_insn_and_split "*lshrdi3_const32"
(define_insn_and_split "*lshrdi3_const32"
  [(set (match_operand:DI 0 "nonimmediate_operand" "=<,m,u")
  [(set (match_operand:DI 0 "nonimmediate_operand" "=<,m,u")
        (lshiftrt:DI (match_operand:DI 1 "general_operand" "umi,umi,umi")
        (lshiftrt:DI (match_operand:DI 1 "general_operand" "umi,umi,umi")
                     (const_int 32)))
                     (const_int 32)))
   (clobber (match_scratch:HI 2 "=&A,d,d"))]
   (clobber (match_scratch:HI 2 "=&A,d,d"))]
   ""
   ""
   "#"
   "#"
   "reload_completed"
   "reload_completed"
   [(const_int 0)]
   [(const_int 0)]
   "m68hc11_split_move (m68hc11_gen_lowpart (SImode, operands[0]),
   "m68hc11_split_move (m68hc11_gen_lowpart (SImode, operands[0]),
                        m68hc11_gen_highpart (SImode, operands[1]),
                        m68hc11_gen_highpart (SImode, operands[1]),
                        operands[2]);
                        operands[2]);
    m68hc11_split_move (m68hc11_gen_highpart (SImode, operands[0]),
    m68hc11_split_move (m68hc11_gen_highpart (SImode, operands[0]),
                        const0_rtx, operands[2]);
                        const0_rtx, operands[2]);
    DONE;")
    DONE;")
(define_insn "*lshrdi3_const63"
(define_insn "*lshrdi3_const63"
  [(set (match_operand:DI 0 "nonimmediate_operand" "=m,u")
  [(set (match_operand:DI 0 "nonimmediate_operand" "=m,u")
        (lshiftrt:DI (match_operand:DI 1 "general_operand" "umi,umi")
        (lshiftrt:DI (match_operand:DI 1 "general_operand" "umi,umi")
                     (match_operand:DI 2 "const_int_operand" "")))
                     (match_operand:DI 2 "const_int_operand" "")))
   (clobber (match_scratch:HI 3 "=d,d"))]
   (clobber (match_scratch:HI 3 "=d,d"))]
   "INTVAL (operands[2]) >= 48"
   "INTVAL (operands[2]) >= 48"
   "#")
   "#")
(define_split
(define_split
  [(set (match_operand:DI 0 "nonimmediate_operand" "")
  [(set (match_operand:DI 0 "nonimmediate_operand" "")
        (lshiftrt:DI (match_operand:DI 1 "general_operand" "")
        (lshiftrt:DI (match_operand:DI 1 "general_operand" "")
                     (match_operand:DI 2 "const_int_operand" "")))
                     (match_operand:DI 2 "const_int_operand" "")))
   (clobber (match_scratch:HI 3 "=d"))]
   (clobber (match_scratch:HI 3 "=d"))]
   "z_replacement_completed && INTVAL (operands[2]) >= 56"
   "z_replacement_completed && INTVAL (operands[2]) >= 56"
   [(set (reg:QI D_REGNUM) (match_dup 9))
   [(set (reg:QI D_REGNUM) (match_dup 9))
    (set (reg:QI D_REGNUM) (lshiftrt:QI (reg:QI D_REGNUM) (match_dup 8)))
    (set (reg:QI D_REGNUM) (lshiftrt:QI (reg:QI D_REGNUM) (match_dup 8)))
    (set (reg:HI D_REGNUM) (zero_extend:HI (reg:QI D_REGNUM)))
    (set (reg:HI D_REGNUM) (zero_extend:HI (reg:QI D_REGNUM)))
    (set (match_dup 4) (reg:HI D_REGNUM))
    (set (match_dup 4) (reg:HI D_REGNUM))
    (set (reg:QI D_REGNUM) (const_int 0))
    (set (reg:QI D_REGNUM) (const_int 0))
    (set (match_dup 5) (reg:HI D_REGNUM))
    (set (match_dup 5) (reg:HI D_REGNUM))
    (set (match_dup 6) (reg:HI D_REGNUM))
    (set (match_dup 6) (reg:HI D_REGNUM))
    (set (match_dup 7) (reg:HI D_REGNUM))]
    (set (match_dup 7) (reg:HI D_REGNUM))]
   "operands[8] = GEN_INT (INTVAL (operands[2]) - 56);
   "operands[8] = GEN_INT (INTVAL (operands[2]) - 56);
    operands[4] = m68hc11_gen_lowpart (SImode, operands[0]);
    operands[4] = m68hc11_gen_lowpart (SImode, operands[0]);
    operands[5] = m68hc11_gen_highpart (HImode, operands[4]);
    operands[5] = m68hc11_gen_highpart (HImode, operands[4]);
    operands[4] = m68hc11_gen_lowpart (HImode, operands[4]);
    operands[4] = m68hc11_gen_lowpart (HImode, operands[4]);
    operands[9] = m68hc11_gen_highpart (SImode, operands[1]);
    operands[9] = m68hc11_gen_highpart (SImode, operands[1]);
    operands[9] = m68hc11_gen_highpart (HImode, operands[9]);
    operands[9] = m68hc11_gen_highpart (HImode, operands[9]);
    operands[9] = m68hc11_gen_highpart (QImode, operands[9]);
    operands[9] = m68hc11_gen_highpart (QImode, operands[9]);
    operands[6] = m68hc11_gen_highpart (SImode, operands[0]);
    operands[6] = m68hc11_gen_highpart (SImode, operands[0]);
    operands[7] = m68hc11_gen_highpart (HImode, operands[6]);
    operands[7] = m68hc11_gen_highpart (HImode, operands[6]);
    operands[6] = m68hc11_gen_lowpart (HImode, operands[6]);")
    operands[6] = m68hc11_gen_lowpart (HImode, operands[6]);")
(define_split
(define_split
  [(set (match_operand:DI 0 "nonimmediate_operand" "")
  [(set (match_operand:DI 0 "nonimmediate_operand" "")
        (lshiftrt:DI (match_operand:DI 1 "general_operand" "")
        (lshiftrt:DI (match_operand:DI 1 "general_operand" "")
                     (match_operand:DI 2 "const_int_operand" "")))
                     (match_operand:DI 2 "const_int_operand" "")))
   (clobber (match_scratch:HI 3 "=d"))]
   (clobber (match_scratch:HI 3 "=d"))]
   "z_replacement_completed && INTVAL (operands[2]) >= 48
   "z_replacement_completed && INTVAL (operands[2]) >= 48
    && INTVAL (operands[2]) < 56"
    && INTVAL (operands[2]) < 56"
   [(set (reg:HI D_REGNUM) (match_dup 9))
   [(set (reg:HI D_REGNUM) (match_dup 9))
    (set (reg:HI D_REGNUM) (lshiftrt:HI (reg:HI D_REGNUM) (match_dup 8)))
    (set (reg:HI D_REGNUM) (lshiftrt:HI (reg:HI D_REGNUM) (match_dup 8)))
    (set (match_dup 4) (reg:HI D_REGNUM))
    (set (match_dup 4) (reg:HI D_REGNUM))
    (set (reg:HI D_REGNUM) (const_int 0))
    (set (reg:HI D_REGNUM) (const_int 0))
    (set (match_dup 5) (reg:HI D_REGNUM))
    (set (match_dup 5) (reg:HI D_REGNUM))
    (set (match_dup 6) (reg:HI D_REGNUM))
    (set (match_dup 6) (reg:HI D_REGNUM))
    (set (match_dup 7) (reg:HI D_REGNUM))]
    (set (match_dup 7) (reg:HI D_REGNUM))]
   "operands[8] = GEN_INT (INTVAL (operands[2]) - 48);
   "operands[8] = GEN_INT (INTVAL (operands[2]) - 48);
    operands[4] = m68hc11_gen_lowpart (SImode, operands[0]);
    operands[4] = m68hc11_gen_lowpart (SImode, operands[0]);
    operands[5] = m68hc11_gen_highpart (HImode, operands[4]);
    operands[5] = m68hc11_gen_highpart (HImode, operands[4]);
    operands[4] = m68hc11_gen_lowpart (HImode, operands[4]);
    operands[4] = m68hc11_gen_lowpart (HImode, operands[4]);
    operands[9] = m68hc11_gen_highpart (SImode, operands[1]);
    operands[9] = m68hc11_gen_highpart (SImode, operands[1]);
    operands[9] = m68hc11_gen_highpart (HImode, operands[1]);
    operands[9] = m68hc11_gen_highpart (HImode, operands[1]);
    operands[6] = m68hc11_gen_highpart (SImode, operands[0]);
    operands[6] = m68hc11_gen_highpart (SImode, operands[0]);
    operands[7] = m68hc11_gen_highpart (HImode, operands[6]);
    operands[7] = m68hc11_gen_highpart (HImode, operands[6]);
    operands[6] = m68hc11_gen_lowpart (HImode, operands[6]);")
    operands[6] = m68hc11_gen_lowpart (HImode, operands[6]);")
(define_insn_and_split "*lshrdi_const1"
(define_insn_and_split "*lshrdi_const1"
  [(set (match_operand:DI 0 "non_push_operand" "=m,u")
  [(set (match_operand:DI 0 "non_push_operand" "=m,u")
        (lshiftrt:DI (match_operand:DI 1 "general_operand" "umi,umi")
        (lshiftrt:DI (match_operand:DI 1 "general_operand" "umi,umi")
                     (const_int 1)))
                     (const_int 1)))
   (clobber (match_scratch:HI 2 "=d,d"))]
   (clobber (match_scratch:HI 2 "=d,d"))]
   ""
   ""
   "#"
   "#"
   "z_replacement_completed == 2"
   "z_replacement_completed == 2"
   [(set (match_dup 2) (match_dup 3))
   [(set (match_dup 2) (match_dup 3))
    (set (match_dup 2) (lshiftrt:HI (match_dup 2) (const_int 1)))
    (set (match_dup 2) (lshiftrt:HI (match_dup 2) (const_int 1)))
    (set (match_dup 4) (match_dup 2))
    (set (match_dup 4) (match_dup 2))
    (set (match_dup 2) (match_dup 5))
    (set (match_dup 2) (match_dup 5))
    (parallel [(set (match_dup 2) (rotatert:HI (match_dup 2) (const_int 1)))
    (parallel [(set (match_dup 2) (rotatert:HI (match_dup 2) (const_int 1)))
               (clobber (reg:HI CC_REGNUM))])
               (clobber (reg:HI CC_REGNUM))])
    (set (match_dup 6) (match_dup 2))
    (set (match_dup 6) (match_dup 2))
    (set (match_dup 2) (match_dup 7))
    (set (match_dup 2) (match_dup 7))
    (parallel [(set (match_dup 2) (rotatert:HI (match_dup 2) (const_int 1)))
    (parallel [(set (match_dup 2) (rotatert:HI (match_dup 2) (const_int 1)))
               (clobber (reg:HI CC_REGNUM))])
               (clobber (reg:HI CC_REGNUM))])
    (set (match_dup 8) (match_dup 2))
    (set (match_dup 8) (match_dup 2))
    (set (match_dup 2) (match_dup 9))
    (set (match_dup 2) (match_dup 9))
    (parallel [(set (match_dup 2) (rotatert:HI (match_dup 2) (const_int 1)))
    (parallel [(set (match_dup 2) (rotatert:HI (match_dup 2) (const_int 1)))
               (clobber (reg:HI CC_REGNUM))])
               (clobber (reg:HI CC_REGNUM))])
    (set (match_dup 10) (match_dup 2))]
    (set (match_dup 10) (match_dup 2))]
   "operands[3] = m68hc11_gen_highpart (SImode, operands[1]);
   "operands[3] = m68hc11_gen_highpart (SImode, operands[1]);
    operands[5] = m68hc11_gen_lowpart (HImode, operands[3]);
    operands[5] = m68hc11_gen_lowpart (HImode, operands[3]);
    operands[3] = m68hc11_gen_highpart (HImode, operands[3]);
    operands[3] = m68hc11_gen_highpart (HImode, operands[3]);
    operands[4] = m68hc11_gen_highpart (SImode, operands[0]);
    operands[4] = m68hc11_gen_highpart (SImode, operands[0]);
    operands[6] = m68hc11_gen_lowpart (HImode, operands[4]);
    operands[6] = m68hc11_gen_lowpart (HImode, operands[4]);
    operands[4] = m68hc11_gen_highpart (HImode, operands[4]);
    operands[4] = m68hc11_gen_highpart (HImode, operands[4]);
    operands[7] = m68hc11_gen_lowpart (SImode, operands[1]);
    operands[7] = m68hc11_gen_lowpart (SImode, operands[1]);
    operands[9] = m68hc11_gen_lowpart (HImode, operands[7]);
    operands[9] = m68hc11_gen_lowpart (HImode, operands[7]);
    operands[7] = m68hc11_gen_highpart (HImode, operands[7]);
    operands[7] = m68hc11_gen_highpart (HImode, operands[7]);
    operands[8] = m68hc11_gen_lowpart (SImode, operands[0]);
    operands[8] = m68hc11_gen_lowpart (SImode, operands[0]);
    operands[10] = m68hc11_gen_lowpart (HImode, operands[8]);
    operands[10] = m68hc11_gen_lowpart (HImode, operands[8]);
    operands[8] = m68hc11_gen_highpart (HImode, operands[8]);")
    operands[8] = m68hc11_gen_highpart (HImode, operands[8]);")
(define_expand "lshrsi3"
(define_expand "lshrsi3"
  [(parallel
  [(parallel
       [(set (match_dup 0) (match_operand:SI 1 "general_operand" ""))
       [(set (match_dup 0) (match_operand:SI 1 "general_operand" ""))
        (clobber (scratch:HI))])
        (clobber (scratch:HI))])
   (parallel
   (parallel
       [(set (match_operand:SI 0 "register_operand" "")
       [(set (match_operand:SI 0 "register_operand" "")
             (lshiftrt:SI (match_dup 0)
             (lshiftrt:SI (match_dup 0)
                          (match_operand:HI 2 "general_operand" "")))
                          (match_operand:HI 2 "general_operand" "")))
        (clobber (scratch:HI))])]
        (clobber (scratch:HI))])]
   ""
   ""
   "")
   "")
(define_split
(define_split
  [(set (match_operand:SI 0 "non_push_operand" "")
  [(set (match_operand:SI 0 "non_push_operand" "")
        (lshiftrt:SI (match_operand:SI 1 "general_operand" "")
        (lshiftrt:SI (match_operand:SI 1 "general_operand" "")
                     (const_int 16)))
                     (const_int 16)))
   (clobber (match_scratch:HI 3 ""))]
   (clobber (match_scratch:HI 3 ""))]
   "reload_completed && !(X_REG_P (operands[0]) && X_REG_P (operands[1]))"
   "reload_completed && !(X_REG_P (operands[0]) && X_REG_P (operands[1]))"
  [(set (match_dup 2) (match_dup 3))
  [(set (match_dup 2) (match_dup 3))
   (set (match_dup 4) (const_int 0))]
   (set (match_dup 4) (const_int 0))]
   "operands[4] = m68hc11_gen_highpart (HImode, operands[0]);
   "operands[4] = m68hc11_gen_highpart (HImode, operands[0]);
    operands[2] = m68hc11_gen_lowpart (HImode, operands[0]);
    operands[2] = m68hc11_gen_lowpart (HImode, operands[0]);
    operands[3] = m68hc11_gen_highpart (HImode, operands[1]);")
    operands[3] = m68hc11_gen_highpart (HImode, operands[1]);")
(define_insn "*lshrsi3_const16"
(define_insn "*lshrsi3_const16"
  [(set (match_operand:SI 0 "non_push_operand" "=D,D,m,u")
  [(set (match_operand:SI 0 "non_push_operand" "=D,D,m,u")
        (lshiftrt:SI (match_operand:SI 1 "general_operand" "uim,0,D,D")
        (lshiftrt:SI (match_operand:SI 1 "general_operand" "uim,0,D,D")
                     (const_int 16)))
                     (const_int 16)))
   (clobber (match_scratch:HI 2 "=X,X,X,X"))]
   (clobber (match_scratch:HI 2 "=X,X,X,X"))]
   ""
   ""
   "@
   "@
    #
    #
    xgdx\\n\\tldx\\t#0
    xgdx\\n\\tldx\\t#0
    #
    #
    #")
    #")
(define_insn "*lshrsi3_const1"
(define_insn "*lshrsi3_const1"
  [(set (match_operand:SI 0 "non_push_operand" "=D,D,D,m,*u,*u")
  [(set (match_operand:SI 0 "non_push_operand" "=D,D,D,m,*u,*u")
        (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0,m,*u,m,*u,m")
        (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0,m,*u,m,*u,m")
                     (const_int 1)))
                     (const_int 1)))
   (clobber (match_scratch:HI 2 "=X,X,X,&d,&d,&d"))]
   (clobber (match_scratch:HI 2 "=X,X,X,&d,&d,&d"))]
   ""
   ""
   "*
   "*
{
{
  CC_STATUS_INIT;
  CC_STATUS_INIT;
  if (X_REG_P (operands[1]))
  if (X_REG_P (operands[1]))
    {
    {
      return \"xgdx\\n\\tlsrd\\n\\txgdx\\n\\trora\\n\\trorb\";
      return \"xgdx\\n\\tlsrd\\n\\txgdx\\n\\trora\\n\\trorb\";
    }
    }
  else
  else
    {
    {
      rtx ops[2];
      rtx ops[2];
      ops[1] = m68hc11_gen_highpart (HImode, operands[1]);
      ops[1] = m68hc11_gen_highpart (HImode, operands[1]);
      ops[0] = gen_rtx_REG (HImode, HARD_D_REGNUM);
      ops[0] = gen_rtx_REG (HImode, HARD_D_REGNUM);
      m68hc11_gen_movhi (insn, ops);
      m68hc11_gen_movhi (insn, ops);
      output_asm_insn (\"lsrd\", ops);
      output_asm_insn (\"lsrd\", ops);
      if (!X_REG_P (operands[0]))
      if (!X_REG_P (operands[0]))
        {
        {
          ops[1] = ops[0];
          ops[1] = ops[0];
          ops[0] = m68hc11_gen_highpart (HImode, operands[0]);
          ops[0] = m68hc11_gen_highpart (HImode, operands[0]);
          m68hc11_gen_movhi (insn, ops);
          m68hc11_gen_movhi (insn, ops);
          ops[0] = ops[1];
          ops[0] = ops[1];
          ops[1] = m68hc11_gen_lowpart (HImode, operands[1]);
          ops[1] = m68hc11_gen_lowpart (HImode, operands[1]);
          m68hc11_gen_movhi (insn, ops);
          m68hc11_gen_movhi (insn, ops);
        }
        }
      else
      else
        {
        {
          /* Load the lowpart in X in case the operands is some N,x.  */
          /* Load the lowpart in X in case the operands is some N,x.  */
          ops[0] = gen_rtx_REG (HImode, HARD_X_REGNUM);
          ops[0] = gen_rtx_REG (HImode, HARD_X_REGNUM);
          ops[1] = m68hc11_gen_lowpart (HImode, operands[1]);
          ops[1] = m68hc11_gen_lowpart (HImode, operands[1]);
          m68hc11_gen_movhi (insn, ops);
          m68hc11_gen_movhi (insn, ops);
          output_asm_insn (\"xgdx\", ops);
          output_asm_insn (\"xgdx\", ops);
        }
        }
      output_asm_insn (\"rora\", ops);
      output_asm_insn (\"rora\", ops);
      output_asm_insn (\"rorb\", ops);
      output_asm_insn (\"rorb\", ops);
      if (!X_REG_P (operands[0]))
      if (!X_REG_P (operands[0]))
        {
        {
          ops[1] = ops[0];
          ops[1] = ops[0];
          ops[0] = m68hc11_gen_lowpart (HImode, operands[0]);
          ops[0] = m68hc11_gen_lowpart (HImode, operands[0]);
          m68hc11_gen_movhi (insn, ops);
          m68hc11_gen_movhi (insn, ops);
        }
        }
      return \"\";
      return \"\";
    }
    }
}")
}")
(define_insn "*lshrsi3_const"
(define_insn "*lshrsi3_const"
  [(set (match_operand:SI 0 "register_operand" "+D")
  [(set (match_operand:SI 0 "register_operand" "+D")
        (lshiftrt:SI (match_dup 0)
        (lshiftrt:SI (match_dup 0)
                     (match_operand:HI 1 "const_int_operand" "")))
                     (match_operand:HI 1 "const_int_operand" "")))
   (clobber (match_scratch:HI 2 "=y"))]
   (clobber (match_scratch:HI 2 "=y"))]
   "TARGET_M6811 /* See *lshrsi3 note.  */"
   "TARGET_M6811 /* See *lshrsi3 note.  */"
   "*
   "*
{
{
  CC_STATUS_INIT;
  CC_STATUS_INIT;
  return \"ldy\\t%1\\n\\tbsr\\t___lshrsi3\";
  return \"ldy\\t%1\\n\\tbsr\\t___lshrsi3\";
}")
}")
(define_insn "*lshrsi3"
(define_insn "*lshrsi3"
  [(set (match_operand:SI 0 "register_operand" "+D,D")
  [(set (match_operand:SI 0 "register_operand" "+D,D")
        (lshiftrt:SI (match_dup 0)
        (lshiftrt:SI (match_dup 0)
                     (match_operand:HI 1 "general_operand" "y,mi")))
                     (match_operand:HI 1 "general_operand" "y,mi")))
   (clobber (match_scratch:HI 2 "=1,X"))]
   (clobber (match_scratch:HI 2 "=1,X"))]
   ""
   ""
   "*
   "*
{
{
  CC_STATUS_INIT;
  CC_STATUS_INIT;
  /* There is a reload problem if we don't accept 'm' for the shift value.
  /* There is a reload problem if we don't accept 'm' for the shift value.
     A RELOAD_OTHER reload can be generated for operand 0 (class A_REGS)
     A RELOAD_OTHER reload can be generated for operand 0 (class A_REGS)
     and this conflicts with all reloads.  Since X, Y, Z are used there
     and this conflicts with all reloads.  Since X, Y, Z are used there
     is not enough register in class A_REGS.
     is not enough register in class A_REGS.
     Assuming that 'operands[1]' does not refer to the stack (which
     Assuming that 'operands[1]' does not refer to the stack (which
     is true for 68hc11 only, we save temporary the value of Y.
     is true for 68hc11 only, we save temporary the value of Y.
     For 68HC12 we must also accept a constant because Z register is
     For 68HC12 we must also accept a constant because Z register is
     disabled when compiling with -fomit-frame-pointer.  We can come up
     disabled when compiling with -fomit-frame-pointer.  We can come up
     with a reload problem and the *lshrsi3_const pattern was disabled
     with a reload problem and the *lshrsi3_const pattern was disabled
     for that reason.  */
     for that reason.  */
  if (!Y_REG_P (operands[2]))
  if (!Y_REG_P (operands[2]))
    {
    {
      rtx ops[1];
      rtx ops[1];
      int y_dead = dead_register_here (insn, iy_reg);
      int y_dead = dead_register_here (insn, iy_reg);
      ops[0] = operands[1];
      ops[0] = operands[1];
      if (y_dead == 0)
      if (y_dead == 0)
        {
        {
          output_asm_insn (\"pshy\", operands);
          output_asm_insn (\"pshy\", operands);
          if (reg_mentioned_p (stack_pointer_rtx, operands[1]))
          if (reg_mentioned_p (stack_pointer_rtx, operands[1]))
            ops[0] = adjust_address (operands[1], GET_MODE (operands[1]), 2);
            ops[0] = adjust_address (operands[1], GET_MODE (operands[1]), 2);
        }
        }
      output_asm_insn (\"ldy\\t%0\", ops);
      output_asm_insn (\"ldy\\t%0\", ops);
      output_asm_insn (\"bsr\\t___lshrsi3\", operands);
      output_asm_insn (\"bsr\\t___lshrsi3\", operands);
      return y_dead == 0 ? \"puly\" : \"\";
      return y_dead == 0 ? \"puly\" : \"\";
    }
    }
  return \"bsr\\t___lshrsi3\";
  return \"bsr\\t___lshrsi3\";
}")
}")
(define_expand "lshrhi3"
(define_expand "lshrhi3"
  [(set (match_operand:HI 0 "register_operand" "")
  [(set (match_operand:HI 0 "register_operand" "")
        (lshiftrt:HI (match_operand:HI 1 "general_operand" "")
        (lshiftrt:HI (match_operand:HI 1 "general_operand" "")
                     (match_operand:HI 2 "general_operand" "")))]
                     (match_operand:HI 2 "general_operand" "")))]
   ""
   ""
   "
   "
{
{
  if (GET_CODE (operands[2]) != CONST_INT)
  if (GET_CODE (operands[2]) != CONST_INT)
    {
    {
      rtx scratch = gen_reg_rtx (HImode);
      rtx scratch = gen_reg_rtx (HImode);
      operand1 = force_reg (HImode, operand1);
      operand1 = force_reg (HImode, operand1);
      emit_move_insn (scratch, operands[2]);
      emit_move_insn (scratch, operands[2]);
      emit_insn (gen_rtx_PARALLEL (VOIDmode,
      emit_insn (gen_rtx_PARALLEL (VOIDmode,
                 gen_rtvec (2, gen_rtx_SET (VOIDmode,
                 gen_rtvec (2, gen_rtx_SET (VOIDmode,
                                        operand0,
                                        operand0,
                                        gen_rtx_LSHIFTRT (HImode,
                                        gen_rtx_LSHIFTRT (HImode,
                                                operand1, scratch)),
                                                operand1, scratch)),
                              gen_rtx_CLOBBER (VOIDmode, scratch))));
                              gen_rtx_CLOBBER (VOIDmode, scratch))));
     DONE;
     DONE;
  }
  }
}")
}")
(define_insn "lshrhi3_const1"
(define_insn "lshrhi3_const1"
  [(set (match_operand:HI 0 "non_push_operand" "=dm,!*u*A")
  [(set (match_operand:HI 0 "non_push_operand" "=dm,!*u*A")
        (lshiftrt:HI (match_operand:HI 1 "non_push_operand" "0,0")
        (lshiftrt:HI (match_operand:HI 1 "non_push_operand" "0,0")
                     (const_int 1)))]
                     (const_int 1)))]
  ""
  ""
  "*
  "*
{
{
  if (A_REG_P (operands[0]))
  if (A_REG_P (operands[0]))
    return \"#\";
    return \"#\";
  if (D_REG_P (operands[0]))
  if (D_REG_P (operands[0]))
    return \"lsrd\";
    return \"lsrd\";
  CC_STATUS_INIT;
  CC_STATUS_INIT;
  return \"lsr\\t%h0\\n\\tror\\t%b0\";
  return \"lsr\\t%h0\\n\\tror\\t%b0\";
}")
}")
(define_insn "lshrhi3_const"
(define_insn "lshrhi3_const"
  [(set (match_operand:HI 0 "nonimmediate_operand" "=d,d,!*A,!*A")
  [(set (match_operand:HI 0 "nonimmediate_operand" "=d,d,!*A,!*A")
        (lshiftrt:HI (match_operand:HI 1 "general_operand" "dm*A,!u,dm,!u")
        (lshiftrt:HI (match_operand:HI 1 "general_operand" "dm*A,!u,dm,!u")
                     (match_operand:HI 2 "const_int_operand" "i,i,i,i")))]
                     (match_operand:HI 2 "const_int_operand" "i,i,i,i")))]
  ""
  ""
  "*
  "*
{
{
  int val = INTVAL (operands[2]);
  int val = INTVAL (operands[2]);
  if (A_REG_P (operands[0]))
  if (A_REG_P (operands[0]))
    return \"#\";
    return \"#\";
  if (val >= 8)
  if (val >= 8)
    {
    {
      if (val == 8)
      if (val == 8)
        CC_STATUS_INIT;
        CC_STATUS_INIT;
      if (!H_REG_P (operands[1]))
      if (!H_REG_P (operands[1]))
        {
        {
          output_asm_insn (\"clra\", operands);
          output_asm_insn (\"clra\", operands);
          output_asm_insn (\"ldab\\t%h1\", operands);
          output_asm_insn (\"ldab\\t%h1\", operands);
        }
        }
      else if (A_REG_P (operands[1]))
      else if (A_REG_P (operands[1]))
        {
        {
          output_asm_insn (\"st%1\\t%t0\", operands);
          output_asm_insn (\"st%1\\t%t0\", operands);
          output_asm_insn (\"ldab\\t%t0\", operands);
          output_asm_insn (\"ldab\\t%t0\", operands);
          output_asm_insn (\"clra\", operands);
          output_asm_insn (\"clra\", operands);
        }
        }
      else
      else
        {
        {
          output_asm_insn (\"tab\", operands);
          output_asm_insn (\"tab\", operands);
          output_asm_insn (\"clra\", operands);
          output_asm_insn (\"clra\", operands);
        }
        }
      val -= 8;
      val -= 8;
      switch (val)
      switch (val)
        {
        {
        case 7:
        case 7:
          output_asm_insn (\"rolb\", operands);
          output_asm_insn (\"rolb\", operands);
          output_asm_insn (\"tab\", operands);
          output_asm_insn (\"tab\", operands);
          output_asm_insn (\"rolb\", operands);
          output_asm_insn (\"rolb\", operands);
          break;
          break;
        case 6:
        case 6:
          output_asm_insn (\"rolb\", operands);
          output_asm_insn (\"rolb\", operands);
          output_asm_insn (\"rolb\", operands);
          output_asm_insn (\"rolb\", operands);
          output_asm_insn (\"rolb\", operands);
          output_asm_insn (\"rolb\", operands);
          output_asm_insn (\"andb\\t#3\", operands);
          output_asm_insn (\"andb\\t#3\", operands);
          break;
          break;
        default:
        default:
           while (val > 0)
           while (val > 0)
             {
             {
                val --;
                val --;
                output_asm_insn (\"lsrb\", operands);
                output_asm_insn (\"lsrb\", operands);
             }
             }
           break;
           break;
        }
        }
      return \"\";
      return \"\";
    }
    }
  if (!D_REG_P (operands[1]))
  if (!D_REG_P (operands[1]))
    m68hc11_gen_movhi (insn, operands);
    m68hc11_gen_movhi (insn, operands);
  switch (val)
  switch (val)
    {
    {
    case 7:
    case 7:
      output_asm_insn (\"rolb\", operands);
      output_asm_insn (\"rolb\", operands);
      output_asm_insn (\"tab\", operands);
      output_asm_insn (\"tab\", operands);
      output_asm_insn (\"rolb\", operands);
      output_asm_insn (\"rolb\", operands);
      output_asm_insn (\"rola\", operands);
      output_asm_insn (\"rola\", operands);
      output_asm_insn (\"rola\", operands);
      output_asm_insn (\"rola\", operands);
      output_asm_insn (\"anda\\t#1\", operands);
      output_asm_insn (\"anda\\t#1\", operands);
      CC_STATUS_INIT;
      CC_STATUS_INIT;
      break;
      break;
    default:
    default:
      while (val > 0)
      while (val > 0)
        {
        {
          val --;
          val --;
          output_asm_insn (\"lsrd\", operands);
          output_asm_insn (\"lsrd\", operands);
        }
        }
     }
     }
  return \"\";
  return \"\";
}")
}")
(define_insn "*lshrhi3"
(define_insn "*lshrhi3"
  [(set (match_operand:HI 0 "register_operand" "=d,*x")
  [(set (match_operand:HI 0 "register_operand" "=d,*x")
        (lshiftrt:HI (match_operand:HI 1 "register_operand" "0,0")
        (lshiftrt:HI (match_operand:HI 1 "register_operand" "0,0")
                     (match_operand:HI 2 "register_operand" "+x,+d")))
                     (match_operand:HI 2 "register_operand" "+x,+d")))
   (clobber (match_dup 2))]
   (clobber (match_dup 2))]
  ""
  ""
  "*
  "*
{
{
  if (A_REG_P (operands[0]))
  if (A_REG_P (operands[0]))
    return \"#\";
    return \"#\";
  return \"bsr\\t___lshrhi3\";
  return \"bsr\\t___lshrhi3\";
}")
}")
(define_expand "lshrqi3"
(define_expand "lshrqi3"
  [(set (match_operand:QI 0 "register_operand" "")
  [(set (match_operand:QI 0 "register_operand" "")
        (lshiftrt:QI (match_operand:QI 1 "register_operand" "")
        (lshiftrt:QI (match_operand:QI 1 "register_operand" "")
                     (match_operand:QI 2 "general_operand" "")))]
                     (match_operand:QI 2 "general_operand" "")))]
   ""
   ""
   "")
   "")
(define_insn "*lshrqi3_const1"
(define_insn "*lshrqi3_const1"
  [(set (match_operand:QI 0 "nonimmediate_operand" "=m,d,!u,!*q,!*A")
  [(set (match_operand:QI 0 "nonimmediate_operand" "=m,d,!u,!*q,!*A")
        (lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0,0,0,0,0")
        (lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0,0,0,0,0")
                     (const_int 1)))]
                     (const_int 1)))]
  ""
  ""
  "@
  "@
   lsr\\t%b0
   lsr\\t%b0
   lsrb
   lsrb
   lsr\\t%b0
   lsr\\t%b0
   lsr%0
   lsr%0
   #")
   #")
(define_insn "*lshrqi3_const"
(define_insn "*lshrqi3_const"
  [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
  [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
        (lshiftrt:QI (match_operand:QI 1 "register_operand" "0,0,0")
        (lshiftrt:QI (match_operand:QI 1 "register_operand" "0,0,0")
                     (match_operand:QI 2 "const_int_operand" "")))]
                     (match_operand:QI 2 "const_int_operand" "")))]
  ""
  ""
  "*
  "*
{
{
  int i;
  int i;
  const char* insn_code;
  const char* insn_code;
  if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
  if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
    insn_code = \"lsrb\";
    insn_code = \"lsrb\";
  else if (DA_REG_P (operands[0]))
  else if (DA_REG_P (operands[0]))
    insn_code = \"lsra\";
    insn_code = \"lsra\";
  else
  else
    return \"#\";
    return \"#\";
  i = INTVAL (operands[2]);
  i = INTVAL (operands[2]);
  if (i >= 8)
  if (i >= 8)
    {
    {
      if (DA_REG_P (operands[0]))
      if (DA_REG_P (operands[0]))
        return \"clra\";
        return \"clra\";
      else
      else
        return \"clrb\";
        return \"clrb\";
    }
    }
  else if (i == 7)
  else if (i == 7)
    {
    {
      if (DA_REG_P (operands[0]))
      if (DA_REG_P (operands[0]))
        {
        {
          output_asm_insn (\"rola\", operands);
          output_asm_insn (\"rola\", operands);
          output_asm_insn (\"ldaa\\t#0\", operands);
          output_asm_insn (\"ldaa\\t#0\", operands);
          return \"rola\";
          return \"rola\";
        }
        }
      else
      else
        {
        {
          output_asm_insn (\"rolb\", operands);
          output_asm_insn (\"rolb\", operands);
          output_asm_insn (\"ldab\\t#0\", operands);
          output_asm_insn (\"ldab\\t#0\", operands);
          return \"rolb\";
          return \"rolb\";
        }
        }
    }
    }
  else if (i == 6)
  else if (i == 6)
    {
    {
      if (DA_REG_P (operands[0]))
      if (DA_REG_P (operands[0]))
        {
        {
          output_asm_insn (\"rola\", operands);
          output_asm_insn (\"rola\", operands);
          output_asm_insn (\"rola\", operands);
          output_asm_insn (\"rola\", operands);
          output_asm_insn (\"rola\", operands);
          output_asm_insn (\"rola\", operands);
          return \"anda\\t#3\";
          return \"anda\\t#3\";
        }
        }
      else
      else
        {
        {
          output_asm_insn (\"rolb\", operands);
          output_asm_insn (\"rolb\", operands);
          output_asm_insn (\"rolb\", operands);
          output_asm_insn (\"rolb\", operands);
          output_asm_insn (\"rolb\", operands);
          output_asm_insn (\"rolb\", operands);
          return \"andb\\t#3\";
          return \"andb\\t#3\";
        }
        }
    }
    }
  while (--i >= 0)
  while (--i >= 0)
    {
    {
      output_asm_insn (insn_code, operands);
      output_asm_insn (insn_code, operands);
    }
    }
  return \"\";
  return \"\";
}")
}")
(define_insn "*lshrqi3"
(define_insn "*lshrqi3"
  [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
  [(set (match_operand:QI 0 "register_operand" "=d,!*q,!*A")
        (lshiftrt:QI (match_operand:QI 1 "register_operand" "0,0,0")
        (lshiftrt:QI (match_operand:QI 1 "register_operand" "0,0,0")
                     (match_operand:QI 2 "nonimmediate_operand"
                     (match_operand:QI 2 "nonimmediate_operand"
                                         "m*u*d*A,m*u*d*A,m*u")))]
                                         "m*u*d*A,m*u*d*A,m*u")))]
  ""
  ""
  "*
  "*
{
{
  rtx ops[2];
  rtx ops[2];
  if (!D_REG_P (operands[0]) && !Q_REG_P (operands[0]))
  if (!D_REG_P (operands[0]) && !Q_REG_P (operands[0]))
    return \"#\";
    return \"#\";
  CC_STATUS_INIT;
  CC_STATUS_INIT;
  ops[0] = gen_rtx_REG (QImode, HARD_A_REGNUM);
  ops[0] = gen_rtx_REG (QImode, HARD_A_REGNUM);
  ops[1] = operands[2];
  ops[1] = operands[2];
  m68hc11_gen_movqi (insn, ops);
  m68hc11_gen_movqi (insn, ops);
  if (!optimize || optimize_size)
  if (!optimize || optimize_size)
    {
    {
      return \"bsr\\t___lshrqi3\";
      return \"bsr\\t___lshrqi3\";
    }
    }
  ops[0] = gen_label_rtx ();
  ops[0] = gen_label_rtx ();
  ops[1] = gen_label_rtx ();
  ops[1] = gen_label_rtx ();
  output_asm_insn (\"ble\\t%l1\", ops);
  output_asm_insn (\"ble\\t%l1\", ops);
  (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
  (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
                             CODE_LABEL_NUMBER (ops[0]));
                             CODE_LABEL_NUMBER (ops[0]));
  output_asm_insn (\"lsrb\", operands);
  output_asm_insn (\"lsrb\", operands);
  output_asm_insn (\"deca\", operands);
  output_asm_insn (\"deca\", operands);
  output_asm_insn (\"bne\\t%l0\", ops);
  output_asm_insn (\"bne\\t%l0\", ops);
  (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
  (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
                             CODE_LABEL_NUMBER (ops[1]));
                             CODE_LABEL_NUMBER (ops[1]));
  return \"\";
  return \"\";
}")
}")
(define_insn "*rotlqi3_with_carry"
(define_insn "*rotlqi3_with_carry"
  [(set (match_operand:QI 0 "register_operand" "=d,!q")
  [(set (match_operand:QI 0 "register_operand" "=d,!q")
        (rotate:QI (match_operand:QI 1 "register_operand" "0,0")
        (rotate:QI (match_operand:QI 1 "register_operand" "0,0")
                   (reg:QI CC_REGNUM)))]
                   (reg:QI CC_REGNUM)))]
  ""
  ""
  "*
  "*
{
{
  if (DA_REG_P (operands[0]))
  if (DA_REG_P (operands[0]))
    return \"rola\";
    return \"rola\";
  else
  else
    return \"rolb\";
    return \"rolb\";
}")
}")
(define_insn "*rotlhi3_with_carry"
(define_insn "*rotlhi3_with_carry"
  [(set (match_operand:HI 0 "register_operand" "=d")
  [(set (match_operand:HI 0 "register_operand" "=d")
        (rotate:HI (match_operand:HI 1 "register_operand" "0")
        (rotate:HI (match_operand:HI 1 "register_operand" "0")
                   (const_int 1)))
                   (const_int 1)))
   (clobber (reg:HI CC_REGNUM))]
   (clobber (reg:HI CC_REGNUM))]
  ""
  ""
  "*
  "*
{
{
  CC_STATUS_INIT;
  CC_STATUS_INIT;
  return \"rolb\\n\\trola\";
  return \"rolb\\n\\trola\";
}")
}")
(define_insn "*rotrhi3_with_carry"
(define_insn "*rotrhi3_with_carry"
  [(set (match_operand:HI 0 "register_operand" "=d")
  [(set (match_operand:HI 0 "register_operand" "=d")
        (rotatert:HI (match_operand:HI 1 "register_operand" "0")
        (rotatert:HI (match_operand:HI 1 "register_operand" "0")
                     (const_int 1)))
                     (const_int 1)))
   (clobber (reg:HI CC_REGNUM))]
   (clobber (reg:HI CC_REGNUM))]
  ""
  ""
  "*
  "*
{
{
  CC_STATUS_INIT;
  CC_STATUS_INIT;
  return \"rora\\n\\trorb\";
  return \"rora\\n\\trorb\";
}")
}")
(define_insn "rotlqi3"
(define_insn "rotlqi3"
  [(set (match_operand:QI 0 "register_operand" "=d,!q")
  [(set (match_operand:QI 0 "register_operand" "=d,!q")
        (rotate:QI (match_operand:QI 1 "register_operand" "0,0")
        (rotate:QI (match_operand:QI 1 "register_operand" "0,0")
                   (match_operand:QI 2 "const_int_operand" "i,i")))]
                   (match_operand:QI 2 "const_int_operand" "i,i")))]
  ""
  ""
  "*
  "*
{
{
  m68hc11_gen_rotate (ROTATE, insn, operands);
  m68hc11_gen_rotate (ROTATE, insn, operands);
  return \"\";
  return \"\";
}")
}")
(define_insn "rotrqi3"
(define_insn "rotrqi3"
  [(set (match_operand:QI 0 "register_operand" "=d,!q")
  [(set (match_operand:QI 0 "register_operand" "=d,!q")
        (rotatert:QI (match_operand:QI 1 "register_operand" "0,0")
        (rotatert:QI (match_operand:QI 1 "register_operand" "0,0")
                     (match_operand:QI 2 "const_int_operand" "i,i")))]
                     (match_operand:QI 2 "const_int_operand" "i,i")))]
  ""
  ""
  "*
  "*
{
{
  m68hc11_gen_rotate (ROTATERT, insn, operands);
  m68hc11_gen_rotate (ROTATERT, insn, operands);
  return \"\";
  return \"\";
}")
}")
(define_expand "rotlhi3"
(define_expand "rotlhi3"
  [(set (match_operand:HI 0 "register_operand" "")
  [(set (match_operand:HI 0 "register_operand" "")
        (rotate:HI (match_operand:HI 1 "register_operand" "")
        (rotate:HI (match_operand:HI 1 "register_operand" "")
                   (match_operand:HI 2 "general_operand" "")))]
                   (match_operand:HI 2 "general_operand" "")))]
   ""
   ""
   "
   "
{
{
  if (GET_CODE (operands[2]) != CONST_INT)
  if (GET_CODE (operands[2]) != CONST_INT)
    {
    {
      rtx scratch = gen_reg_rtx (HImode);
      rtx scratch = gen_reg_rtx (HImode);
      operand1 = force_reg (HImode, operand1);
      operand1 = force_reg (HImode, operand1);
      emit_move_insn (scratch, operands[2]);
      emit_move_insn (scratch, operands[2]);
      emit_insn (gen_rtx_PARALLEL (VOIDmode,
      emit_insn (gen_rtx_PARALLEL (VOIDmode,
                 gen_rtvec (2, gen_rtx_SET (VOIDmode,
                 gen_rtvec (2, gen_rtx_SET (VOIDmode,
                                        operand0,
                                        operand0,
                                        gen_rtx_ROTATE (HImode,
                                        gen_rtx_ROTATE (HImode,
                                                operand1, scratch)),
                                                operand1, scratch)),
                              gen_rtx_CLOBBER (VOIDmode, scratch))));
                              gen_rtx_CLOBBER (VOIDmode, scratch))));
      DONE;
      DONE;
    }
    }
}")
}")
(define_insn "rotlhi3_const"
(define_insn "rotlhi3_const"
  [(set (match_operand:HI 0 "register_operand" "=d")
  [(set (match_operand:HI 0 "register_operand" "=d")
        (rotate:HI (match_operand:HI 1 "register_operand" "0")
        (rotate:HI (match_operand:HI 1 "register_operand" "0")
                   (match_operand:HI 2 "const_int_operand" "i")))]
                   (match_operand:HI 2 "const_int_operand" "i")))]
  ""
  ""
  "*
  "*
{
{
  m68hc11_gen_rotate (ROTATE, insn, operands);
  m68hc11_gen_rotate (ROTATE, insn, operands);
  return \"\";
  return \"\";
}")
}")
(define_insn "*rotlhi3"
(define_insn "*rotlhi3"
  [(set (match_operand:HI 0 "register_operand" "=d,*x")
  [(set (match_operand:HI 0 "register_operand" "=d,*x")
        (rotate:HI (match_operand:HI 1 "register_operand" "0,0")
        (rotate:HI (match_operand:HI 1 "register_operand" "0,0")
                   (match_operand:HI 2 "general_operand" "+x,+d")))
                   (match_operand:HI 2 "general_operand" "+x,+d")))
   (clobber (match_dup 2))]
   (clobber (match_dup 2))]
  ""
  ""
  "*
  "*
{
{
  if (A_REG_P (operands[0]))
  if (A_REG_P (operands[0]))
    return \"#\";
    return \"#\";
  return \"bsr\\t___rotlhi3\";
  return \"bsr\\t___rotlhi3\";
}")
}")
(define_expand "rotrhi3"
(define_expand "rotrhi3"
  [(set (match_operand:HI 0 "register_operand" "")
  [(set (match_operand:HI 0 "register_operand" "")
        (rotatert:HI (match_operand:HI 1 "general_operand" "")
        (rotatert:HI (match_operand:HI 1 "general_operand" "")
                     (match_operand:HI 2 "general_operand" "")))]
                     (match_operand:HI 2 "general_operand" "")))]
   ""
   ""
   "
   "
{
{
  if (GET_CODE (operands[2]) != CONST_INT)
  if (GET_CODE (operands[2]) != CONST_INT)
    {
    {
      rtx scratch = gen_reg_rtx (HImode);
      rtx scratch = gen_reg_rtx (HImode);
      operand1 = force_reg (HImode, operand1);
      operand1 = force_reg (HImode, operand1);
      emit_move_insn (scratch, operands[2]);
      emit_move_insn (scratch, operands[2]);
      emit_insn (gen_rtx_PARALLEL (VOIDmode,
      emit_insn (gen_rtx_PARALLEL (VOIDmode,
                 gen_rtvec (2, gen_rtx_SET (VOIDmode,
                 gen_rtvec (2, gen_rtx_SET (VOIDmode,
                                        operand0,
                                        operand0,
                                        gen_rtx_ROTATERT (HImode,
                                        gen_rtx_ROTATERT (HImode,
                                                operand1, scratch)),
                                                operand1, scratch)),
                              gen_rtx_CLOBBER (VOIDmode, scratch))));
                              gen_rtx_CLOBBER (VOIDmode, scratch))));
      DONE;
      DONE;
    }
    }
}")
}")
(define_insn "rotrhi3_const"
(define_insn "rotrhi3_const"
  [(set (match_operand:HI 0 "register_operand" "=d")
  [(set (match_operand:HI 0 "register_operand" "=d")
        (rotatert:HI (match_operand:HI 1 "register_operand" "0")
        (rotatert:HI (match_operand:HI 1 "register_operand" "0")
                     (match_operand:HI 2 "const_int_operand" "i")))]
                     (match_operand:HI 2 "const_int_operand" "i")))]
  ""
  ""
  "*
  "*
{
{
  m68hc11_gen_rotate (ROTATERT, insn, operands);
  m68hc11_gen_rotate (ROTATERT, insn, operands);
  return \"\";
  return \"\";
}")
}")
(define_insn "*rotrhi3"
(define_insn "*rotrhi3"
  [(set (match_operand:HI 0 "register_operand" "=d,*x")
  [(set (match_operand:HI 0 "register_operand" "=d,*x")
        (rotatert:HI (match_operand:HI 1 "register_operand" "0,0")
        (rotatert:HI (match_operand:HI 1 "register_operand" "0,0")
                     (match_operand:HI 2 "general_operand" "+x,+d")))
                     (match_operand:HI 2 "general_operand" "+x,+d")))
   (clobber (match_dup 2))]
   (clobber (match_dup 2))]
  ""
  ""
  "*
  "*
{
{
  if (A_REG_P (operands[0]))
  if (A_REG_P (operands[0]))
    return \"#\";
    return \"#\";
  return \"bsr\\t___rotrhi3\";
  return \"bsr\\t___rotrhi3\";
}")
}")
;; Split a shift operation on an address register in a shift
;; Split a shift operation on an address register in a shift
;; on D_REGNUM.
;; on D_REGNUM.
(define_split /* "*rotrhi3_addr" */
(define_split /* "*rotrhi3_addr" */
  [(set (match_operand:HI 0 "hard_addr_reg_operand" "")
  [(set (match_operand:HI 0 "hard_addr_reg_operand" "")
        (match_operator:HI 3 "m68hc11_shift_operator"
        (match_operator:HI 3 "m68hc11_shift_operator"
            [(match_operand:HI 1 "register_operand" "")
            [(match_operand:HI 1 "register_operand" "")
             (match_operand:HI 2 "register_operand" "")]))
             (match_operand:HI 2 "register_operand" "")]))
   (clobber (match_dup 2))]
   (clobber (match_dup 2))]
  "z_replacement_completed == 2"
  "z_replacement_completed == 2"
  [(parallel [(set (reg:HI D_REGNUM) (match_dup 0))
  [(parallel [(set (reg:HI D_REGNUM) (match_dup 0))
              (set (match_dup 0) (reg:HI D_REGNUM))])
              (set (match_dup 0) (reg:HI D_REGNUM))])
   (parallel [(set (reg:HI D_REGNUM)
   (parallel [(set (reg:HI D_REGNUM)
                   (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 0)]))
                   (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 0)]))
              (clobber (match_dup 0))])
              (clobber (match_dup 0))])
   (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
   (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
              (set (match_dup 0) (reg:HI D_REGNUM))])]
              (set (match_dup 0) (reg:HI D_REGNUM))])]
  "")
  "")
;;--------------------------------------------------------------------
;;--------------------------------------------------------------------
;;-  68HC12 Decrement/Increment and branch
;;-  68HC12 Decrement/Increment and branch
;;--------------------------------------------------------------------
;;--------------------------------------------------------------------
;; These patterns are used by loop optimization as well as peephole2
;; These patterns are used by loop optimization as well as peephole2
;; They must handle reloading themselves and the scratch register
;; They must handle reloading themselves and the scratch register
;; is used for that.  Even if we accept memory operand, we must not
;; is used for that.  Even if we accept memory operand, we must not
;; accept them on the predicate because it might create too many reloads.
;; accept them on the predicate because it might create too many reloads.
;; (specially on HC12 due to its auto-incdec addressing modes).
;; (specially on HC12 due to its auto-incdec addressing modes).
;;
;;
(define_expand "decrement_and_branch_until_zero"
(define_expand "decrement_and_branch_until_zero"
  [(parallel [(set (pc)
  [(parallel [(set (pc)
                   (if_then_else
                   (if_then_else
                    (ne (plus:HI (match_operand:HI 0 "register_operand" "")
                    (ne (plus:HI (match_operand:HI 0 "register_operand" "")
                                 (const_int 0))
                                 (const_int 0))
                        (const_int 1))
                        (const_int 1))
                    (label_ref (match_operand 1 "" ""))
                    (label_ref (match_operand 1 "" ""))
                    (pc)))
                    (pc)))
              (set (match_dup 0)
              (set (match_dup 0)
                   (plus:HI (match_dup 0)
                   (plus:HI (match_dup 0)
                            (const_int -1)))
                            (const_int -1)))
              (clobber (match_scratch:HI 2 ""))])]
              (clobber (match_scratch:HI 2 ""))])]
  "TARGET_M6812"
  "TARGET_M6812"
  "")
  "")
(define_expand "doloop_end"
(define_expand "doloop_end"
  [(use (match_operand 0 "" ""))        ; loop pseudo
  [(use (match_operand 0 "" ""))        ; loop pseudo
   (use (match_operand 1 "" ""))        ; iterations; zero if unknown
   (use (match_operand 1 "" ""))        ; iterations; zero if unknown
   (use (match_operand 2 "" ""))        ; max iterations
   (use (match_operand 2 "" ""))        ; max iterations
   (use (match_operand 3 "" ""))        ; loop level
   (use (match_operand 3 "" ""))        ; loop level
   (use (match_operand 4 "" ""))]       ; label
   (use (match_operand 4 "" ""))]       ; label
  "TARGET_M6812"
  "TARGET_M6812"
  "
  "
{
{
  /* Reject non-constant loops as it generates bigger code due to
  /* Reject non-constant loops as it generates bigger code due to
     the handling of the loop register.  We can do better by using
     the handling of the loop register.  We can do better by using
     the peephole2 dbcc/ibcc patterns.  */
     the peephole2 dbcc/ibcc patterns.  */
  if (INTVAL (operands[1]) == 0)
  if (INTVAL (operands[1]) == 0)
    {
    {
      FAIL;
      FAIL;
    }
    }
  /* Note that for xxx_dbcc_dec_yy the gen_rtx_NE is only used to pass
  /* Note that for xxx_dbcc_dec_yy the gen_rtx_NE is only used to pass
     the operator and its operands are not relevant.  */
     the operator and its operands are not relevant.  */
  if (GET_MODE (operands[0]) == HImode)
  if (GET_MODE (operands[0]) == HImode)
    {
    {
      emit_jump_insn (gen_m68hc12_dbcc_dec_hi (operands[0],
      emit_jump_insn (gen_m68hc12_dbcc_dec_hi (operands[0],
                                               gen_rtx_NE (HImode,
                                               gen_rtx_NE (HImode,
                                                           operands[0],
                                                           operands[0],
                                                           const1_rtx),
                                                           const1_rtx),
                                               operands[4]));
                                               operands[4]));
      DONE;
      DONE;
    }
    }
  if (GET_MODE (operands[0]) == QImode)
  if (GET_MODE (operands[0]) == QImode)
    {
    {
      emit_jump_insn (gen_m68hc12_dbcc_dec_qi (operands[0],
      emit_jump_insn (gen_m68hc12_dbcc_dec_qi (operands[0],
                                               gen_rtx_NE (QImode,
                                               gen_rtx_NE (QImode,
                                                           operands[0],
                                                           operands[0],
                                                           const1_rtx),
                                                           const1_rtx),
                                               operands[4]));
                                               operands[4]));
      DONE;
      DONE;
    }
    }
  FAIL;
  FAIL;
}")
}")
;; Decrement-and-branch insns.
;; Decrement-and-branch insns.
(define_insn "m68hc12_dbcc_dec_hi"
(define_insn "m68hc12_dbcc_dec_hi"
  [(set (pc)
  [(set (pc)
        (if_then_else
        (if_then_else
          (match_operator 1 "m68hc11_eq_compare_operator"
          (match_operator 1 "m68hc11_eq_compare_operator"
             [(match_operand:HI 0 "register_operand" "+dxy,m*u*z")
             [(match_operand:HI 0 "register_operand" "+dxy,m*u*z")
              (const_int 1)])
              (const_int 1)])
         (label_ref (match_operand 2 "" ""))
         (label_ref (match_operand 2 "" ""))
         (pc)))
         (pc)))
   (set (match_dup 0)
   (set (match_dup 0)
        (plus:HI (match_dup 0) (const_int -1)))
        (plus:HI (match_dup 0) (const_int -1)))
   (clobber (match_scratch:HI 3 "=X,dxy"))]
   (clobber (match_scratch:HI 3 "=X,dxy"))]
  "TARGET_M6812"
  "TARGET_M6812"
  "*
  "*
{
{
  if (!H_REG_P (operands[0]))
  if (!H_REG_P (operands[0]))
    return \"#\";
    return \"#\";
  CC_STATUS_INIT;
  CC_STATUS_INIT;
  if (GET_CODE (operands[1]) == EQ)
  if (GET_CODE (operands[1]) == EQ)
    return \"dbeq\\t%0,%l2\";
    return \"dbeq\\t%0,%l2\";
  else
  else
    return \"dbne\\t%0,%l2\";
    return \"dbne\\t%0,%l2\";
}")
}")
;; Decrement-and-branch insns.
;; Decrement-and-branch insns.
(define_insn "m68hc12_dbcc_inc_hi"
(define_insn "m68hc12_dbcc_inc_hi"
  [(set (pc)
  [(set (pc)
        (if_then_else
        (if_then_else
          (match_operator 1 "m68hc11_eq_compare_operator"
          (match_operator 1 "m68hc11_eq_compare_operator"
             [(match_operand:HI 0 "register_operand" "+dxy,m*u*z")
             [(match_operand:HI 0 "register_operand" "+dxy,m*u*z")
              (const_int -1)])
              (const_int -1)])
         (label_ref (match_operand 2 "" ""))
         (label_ref (match_operand 2 "" ""))
         (pc)))
         (pc)))
   (set (match_dup 0)
   (set (match_dup 0)
        (plus:HI (match_dup 0) (const_int 1)))
        (plus:HI (match_dup 0) (const_int 1)))
   (clobber (match_scratch:HI 3 "=X,dxy"))]
   (clobber (match_scratch:HI 3 "=X,dxy"))]
  "TARGET_M6812"
  "TARGET_M6812"
  "*
  "*
{
{
  if (!H_REG_P (operands[0]))
  if (!H_REG_P (operands[0]))
    return \"#\";
    return \"#\";
  CC_STATUS_INIT;
  CC_STATUS_INIT;
  if (GET_CODE (operands[1]) == EQ)
  if (GET_CODE (operands[1]) == EQ)
    return \"ibeq\\t%0,%l2\";
    return \"ibeq\\t%0,%l2\";
  else
  else
    return \"ibeq\\t%0,%l2\";
    return \"ibeq\\t%0,%l2\";
}")
}")
;; Decrement-and-branch (QImode).
;; Decrement-and-branch (QImode).
(define_insn "m68hc12_dbcc_dec_qi"
(define_insn "m68hc12_dbcc_dec_qi"
  [(set (pc)
  [(set (pc)
        (if_then_else
        (if_then_else
          (match_operator 1 "m68hc11_eq_compare_operator"
          (match_operator 1 "m68hc11_eq_compare_operator"
             [(match_operand:QI 0 "register_operand" "+d,m*u*A")
             [(match_operand:QI 0 "register_operand" "+d,m*u*A")
              (const_int 1)])
              (const_int 1)])
         (label_ref (match_operand 2 "" ""))
         (label_ref (match_operand 2 "" ""))
         (pc)))
         (pc)))
   (set (match_dup 0)
   (set (match_dup 0)
        (plus:QI (match_dup 0) (const_int -1)))
        (plus:QI (match_dup 0) (const_int -1)))
   (clobber (match_scratch:QI 3 "=X,d"))]
   (clobber (match_scratch:QI 3 "=X,d"))]
  "TARGET_M6812"
  "TARGET_M6812"
  "*
  "*
{
{
  if (!D_REG_P (operands[0]))
  if (!D_REG_P (operands[0]))
    return \"#\";
    return \"#\";
  CC_STATUS_INIT;
  CC_STATUS_INIT;
  if (GET_CODE (operands[1]) == EQ)
  if (GET_CODE (operands[1]) == EQ)
    return \"dbeq\\tb,%l2\";
    return \"dbeq\\tb,%l2\";
  else
  else
    return \"dbne\\tb,%l2\";
    return \"dbne\\tb,%l2\";
}")
}")
;; Increment-and-branch (QImode).
;; Increment-and-branch (QImode).
(define_insn "m68hc12_dbcc_inc_qi"
(define_insn "m68hc12_dbcc_inc_qi"
  [(set (pc)
  [(set (pc)
        (if_then_else
        (if_then_else
          (match_operator 1 "m68hc11_eq_compare_operator"
          (match_operator 1 "m68hc11_eq_compare_operator"
             [(match_operand:QI 0 "register_operand" "+d,m*u*A")
             [(match_operand:QI 0 "register_operand" "+d,m*u*A")
              (const_int -1)])
              (const_int -1)])
         (label_ref (match_operand 2 "" ""))
         (label_ref (match_operand 2 "" ""))
         (pc)))
         (pc)))
   (set (match_dup 0)
   (set (match_dup 0)
        (plus:QI (match_dup 0) (const_int 1)))
        (plus:QI (match_dup 0) (const_int 1)))
   (clobber (match_scratch:QI 3 "=X,d"))]
   (clobber (match_scratch:QI 3 "=X,d"))]
  "TARGET_M6812"
  "TARGET_M6812"
  "*
  "*
{
{
  if (!D_REG_P (operands[0]))
  if (!D_REG_P (operands[0]))
    return \"#\";
    return \"#\";
  CC_STATUS_INIT;
  CC_STATUS_INIT;
  if (GET_CODE (operands[1]) == EQ)
  if (GET_CODE (operands[1]) == EQ)
    return \"ibeq\\tb,%l2\";
    return \"ibeq\\tb,%l2\";
  else
  else
    return \"ibeq\\tb,%l2\";
    return \"ibeq\\tb,%l2\";
}")
}")
;; Split the above to handle the case where operand 0 is in memory
;; Split the above to handle the case where operand 0 is in memory
;; (a register that couldn't get a hard register)
;; (a register that couldn't get a hard register)
(define_split
(define_split
  [(set (pc)
  [(set (pc)
        (if_then_else
        (if_then_else
          (match_operator 3 "m68hc11_eq_compare_operator"
          (match_operator 3 "m68hc11_eq_compare_operator"
             [(match_operand:HI 0 "general_operand" "")
             [(match_operand:HI 0 "general_operand" "")
              (match_operand:HI 1 "const_int_operand" "")])
              (match_operand:HI 1 "const_int_operand" "")])
         (label_ref (match_operand 4 "" ""))
         (label_ref (match_operand 4 "" ""))
         (pc)))
         (pc)))
   (set (match_dup 0)
   (set (match_dup 0)
        (plus:HI (match_dup 0) (match_operand 2 "const_int_operand" "")))
        (plus:HI (match_dup 0) (match_operand 2 "const_int_operand" "")))
   (clobber (match_operand:HI 5 "hard_reg_operand" ""))]
   (clobber (match_operand:HI 5 "hard_reg_operand" ""))]
  "TARGET_M6812 && reload_completed"
  "TARGET_M6812 && reload_completed"
  [(set (match_dup 5) (match_dup 0))
  [(set (match_dup 5) (match_dup 0))
   (set (match_dup 5) (plus:HI (match_dup 5) (match_dup 2)))
   (set (match_dup 5) (plus:HI (match_dup 5) (match_dup 2)))
   (set (match_dup 0) (match_dup 5))
   (set (match_dup 0) (match_dup 5))
   (set (pc)
   (set (pc)
        (if_then_else (match_op_dup 3
        (if_then_else (match_op_dup 3
                            [(match_dup 5) (const_int 0)])
                            [(match_dup 5) (const_int 0)])
                      (label_ref (match_dup 4)) (pc)))]
                      (label_ref (match_dup 4)) (pc)))]
  "")
  "")
;; Split the above to handle the case where operand 0 is in memory
;; Split the above to handle the case where operand 0 is in memory
;; (a register that couldn't get a hard register)
;; (a register that couldn't get a hard register)
(define_split
(define_split
  [(set (pc)
  [(set (pc)
        (if_then_else
        (if_then_else
          (match_operator 3 "m68hc11_eq_compare_operator"
          (match_operator 3 "m68hc11_eq_compare_operator"
             [(match_operand:QI 0 "general_operand" "")
             [(match_operand:QI 0 "general_operand" "")
              (match_operand:QI 1 "const_int_operand" "")])
              (match_operand:QI 1 "const_int_operand" "")])
         (label_ref (match_operand 4 "" ""))
         (label_ref (match_operand 4 "" ""))
         (pc)))
         (pc)))
   (set (match_dup 0)
   (set (match_dup 0)
        (plus:QI (match_dup 0) (match_operand 2 "const_int_operand" "")))
        (plus:QI (match_dup 0) (match_operand 2 "const_int_operand" "")))
   (clobber (match_operand:QI 5 "hard_reg_operand" ""))]
   (clobber (match_operand:QI 5 "hard_reg_operand" ""))]
  "TARGET_M6812 && reload_completed"
  "TARGET_M6812 && reload_completed"
  [(set (match_dup 5) (match_dup 0))
  [(set (match_dup 5) (match_dup 0))
   (set (match_dup 5) (plus:QI (match_dup 5) (match_dup 2)))
   (set (match_dup 5) (plus:QI (match_dup 5) (match_dup 2)))
   (set (match_dup 0) (match_dup 5))
   (set (match_dup 0) (match_dup 5))
   (set (pc)
   (set (pc)
        (if_then_else (match_op_dup 3
        (if_then_else (match_op_dup 3
                            [(match_dup 5) (const_int 0)])
                            [(match_dup 5) (const_int 0)])
                      (label_ref (match_dup 4)) (pc)))]
                      (label_ref (match_dup 4)) (pc)))]
  "")
  "")
;;--------------------------------------------------------------------
;;--------------------------------------------------------------------
;;-  Jumps and transfers
;;-  Jumps and transfers
;;--------------------------------------------------------------------
;;--------------------------------------------------------------------
(define_insn "jump"
(define_insn "jump"
  [(set (pc)
  [(set (pc)
        (label_ref (match_operand 0 "" "")))]
        (label_ref (match_operand 0 "" "")))]
  ""
  ""
  "bra\\t%l0")
  "bra\\t%l0")
(define_expand "beq"
(define_expand "beq"
  [(set (pc)
  [(set (pc)
        (if_then_else (eq (cc0)
        (if_then_else (eq (cc0)
                          (const_int 0))
                          (const_int 0))
                      (label_ref (match_operand 0 "" ""))
                      (label_ref (match_operand 0 "" ""))
                      (pc)))]
                      (pc)))]
  ""
  ""
  "
  "
{
{
  m68hc11_expand_compare_and_branch (EQ, m68hc11_compare_op0,
  m68hc11_expand_compare_and_branch (EQ, m68hc11_compare_op0,
                                     m68hc11_compare_op1,
                                     m68hc11_compare_op1,
                                     operands[0]);
                                     operands[0]);
  DONE;
  DONE;
}")
}")
(define_expand "bne"
(define_expand "bne"
  [(set (pc)
  [(set (pc)
        (if_then_else (ne (cc0)
        (if_then_else (ne (cc0)
                          (const_int 0))
                          (const_int 0))
                      (label_ref (match_operand 0 "" ""))
                      (label_ref (match_operand 0 "" ""))
                      (pc)))]
                      (pc)))]
  ""
  ""
  "
  "
{
{
  m68hc11_expand_compare_and_branch (NE, m68hc11_compare_op0,
  m68hc11_expand_compare_and_branch (NE, m68hc11_compare_op0,
                                     m68hc11_compare_op1,
                                     m68hc11_compare_op1,
                                     operands[0]);
                                     operands[0]);
  DONE;
  DONE;
}")
}")
(define_expand "bgt"
(define_expand "bgt"
  [(set (pc)
  [(set (pc)
        (if_then_else (gt (cc0)
        (if_then_else (gt (cc0)
                          (const_int 0))
                          (const_int 0))
                      (label_ref (match_operand 0 "" ""))
                      (label_ref (match_operand 0 "" ""))
                      (pc)))]
                      (pc)))]
  ""
  ""
  "
  "
{
{
  m68hc11_expand_compare_and_branch (GT, m68hc11_compare_op0,
  m68hc11_expand_compare_and_branch (GT, m68hc11_compare_op0,
                                     m68hc11_compare_op1,
                                     m68hc11_compare_op1,
                                     operands[0]);
                                     operands[0]);
  DONE;
  DONE;
}")
}")
(define_expand "bgtu"
(define_expand "bgtu"
  [(set (pc)
  [(set (pc)
        (if_then_else (gtu (cc0)
        (if_then_else (gtu (cc0)
                           (const_int 0))
                           (const_int 0))
                      (label_ref (match_operand 0 "" ""))
                      (label_ref (match_operand 0 "" ""))
                      (pc)))]
                      (pc)))]
  ""
  ""
  "
  "
{
{
  m68hc11_expand_compare_and_branch (GTU, m68hc11_compare_op0,
  m68hc11_expand_compare_and_branch (GTU, m68hc11_compare_op0,
                                     m68hc11_compare_op1,
                                     m68hc11_compare_op1,
                                     operands[0]);
                                     operands[0]);
  DONE;
  DONE;
}")
}")
(define_expand "blt"
(define_expand "blt"
  [(set (pc)
  [(set (pc)
        (if_then_else (lt (cc0)
        (if_then_else (lt (cc0)
                          (const_int 0))
                          (const_int 0))
                      (label_ref (match_operand 0 "" ""))
                      (label_ref (match_operand 0 "" ""))
                      (pc)))]
                      (pc)))]
  ""
  ""
  "
  "
{
{
  m68hc11_expand_compare_and_branch (LT, m68hc11_compare_op0,
  m68hc11_expand_compare_and_branch (LT, m68hc11_compare_op0,
                                     m68hc11_compare_op1,
                                     m68hc11_compare_op1,
                                     operands[0]);
                                     operands[0]);
  DONE;
  DONE;
}")
}")
(define_expand "bltu"
(define_expand "bltu"
  [(set (pc)
  [(set (pc)
        (if_then_else (ltu (cc0)
        (if_then_else (ltu (cc0)
                           (const_int 0))
                           (const_int 0))
                      (label_ref (match_operand 0 "" ""))
                      (label_ref (match_operand 0 "" ""))
                      (pc)))]
                      (pc)))]
  ""
  ""
  "
  "
{
{
  m68hc11_expand_compare_and_branch (LTU, m68hc11_compare_op0,
  m68hc11_expand_compare_and_branch (LTU, m68hc11_compare_op0,
                                     m68hc11_compare_op1,
                                     m68hc11_compare_op1,
                                     operands[0]);
                                     operands[0]);
  DONE;
  DONE;
}")
}")
(define_expand "bge"
(define_expand "bge"
  [(set (pc)
  [(set (pc)
        (if_then_else (ge (cc0)
        (if_then_else (ge (cc0)
                           (const_int 0))
                           (const_int 0))
                      (label_ref (match_operand 0 "" ""))
                      (label_ref (match_operand 0 "" ""))
                      (pc)))]
                      (pc)))]
  ""
  ""
  "
  "
{
{
  m68hc11_expand_compare_and_branch (GE, m68hc11_compare_op0,
  m68hc11_expand_compare_and_branch (GE, m68hc11_compare_op0,
                                     m68hc11_compare_op1,
                                     m68hc11_compare_op1,
                                     operands[0]);
                                     operands[0]);
  DONE;
  DONE;
}")
}")
(define_expand "bgeu"
(define_expand "bgeu"
  [(set (pc)
  [(set (pc)
        (if_then_else (geu (cc0)
        (if_then_else (geu (cc0)
                           (const_int 0))
                           (const_int 0))
                      (label_ref (match_operand 0 "" ""))
                      (label_ref (match_operand 0 "" ""))
                      (pc)))]
                      (pc)))]
  ""
  ""
  "
  "
{
{
  m68hc11_expand_compare_and_branch (GEU, m68hc11_compare_op0,
  m68hc11_expand_compare_and_branch (GEU, m68hc11_compare_op0,
                                     m68hc11_compare_op1,
                                     m68hc11_compare_op1,
                                     operands[0]);
                                     operands[0]);
  DONE;
  DONE;
}")
}")
(define_expand "ble"
(define_expand "ble"
  [(set (pc)
  [(set (pc)
        (if_then_else (le (cc0)
        (if_then_else (le (cc0)
                           (const_int 0))
                           (const_int 0))
                      (label_ref (match_operand 0 "" ""))
                      (label_ref (match_operand 0 "" ""))
                      (pc)))]
                      (pc)))]
  ""
  ""
  "
  "
{
{
  m68hc11_expand_compare_and_branch (LE, m68hc11_compare_op0,
  m68hc11_expand_compare_and_branch (LE, m68hc11_compare_op0,
                                     m68hc11_compare_op1,
                                     m68hc11_compare_op1,
                                     operands[0]);
                                     operands[0]);
  DONE;
  DONE;
}")
}")
(define_expand "bleu"
(define_expand "bleu"
  [(set (pc)
  [(set (pc)
        (if_then_else (leu (cc0)
        (if_then_else (leu (cc0)
                           (const_int 0))
                           (const_int 0))
                      (label_ref (match_operand 0 "" ""))
                      (label_ref (match_operand 0 "" ""))
                      (pc)))]
                      (pc)))]
  ""
  ""
  "
  "
{
{
  m68hc11_expand_compare_and_branch (LEU, m68hc11_compare_op0,
  m68hc11_expand_compare_and_branch (LEU, m68hc11_compare_op0,
                                     m68hc11_compare_op1,
                                     m68hc11_compare_op1,
                                     operands[0]);
                                     operands[0]);
  DONE;
  DONE;
}")
}")
;;
;;
;; Test and branch instructions for 68HC12 for EQ and NE.
;; Test and branch instructions for 68HC12 for EQ and NE.
;; 'z' must not appear in the constraints because the z replacement
;; 'z' must not appear in the constraints because the z replacement
;; pass does not know how to restore the replacement register.
;; pass does not know how to restore the replacement register.
;;
;;
(define_insn "*tbeq"
(define_insn "*tbeq"
  [(set (pc)
  [(set (pc)
        (if_then_else (eq (match_operand:HI 0 "register_operand" "dxy")
        (if_then_else (eq (match_operand:HI 0 "register_operand" "dxy")
                          (const_int 0))
                          (const_int 0))
                      (label_ref (match_operand 1 "" ""))
                      (label_ref (match_operand 1 "" ""))
                      (pc)))]
                      (pc)))]
  "TARGET_M6812"
  "TARGET_M6812"
  "*
  "*
{
{
   /* If the flags are already set correctly, use 'bne/beq' which are
   /* If the flags are already set correctly, use 'bne/beq' which are
      smaller and a little bit faster.  This happens quite often due
      smaller and a little bit faster.  This happens quite often due
      to reloading of operands[0].  In that case, flags are set correctly
      to reloading of operands[0].  In that case, flags are set correctly
      due to the load instruction.  */
      due to the load instruction.  */
  if ((cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0]))
  if ((cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0]))
      || (cc_status.value2 && rtx_equal_p (cc_status.value2, operands[0])))
      || (cc_status.value2 && rtx_equal_p (cc_status.value2, operands[0])))
    return \"beq\\t%l1\";
    return \"beq\\t%l1\";
  else
  else
    return \"tbeq\\t%0,%l1\";
    return \"tbeq\\t%0,%l1\";
}")
}")
(define_insn "*tbne"
(define_insn "*tbne"
  [(set (pc)
  [(set (pc)
        (if_then_else (ne (match_operand:HI 0 "register_operand" "dxy")
        (if_then_else (ne (match_operand:HI 0 "register_operand" "dxy")
                          (const_int 0))
                          (const_int 0))
                      (label_ref (match_operand 1 "" ""))
                      (label_ref (match_operand 1 "" ""))
                      (pc)))]
                      (pc)))]
  "TARGET_M6812"
  "TARGET_M6812"
  "*
  "*
{
{
   if ((cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0]))
   if ((cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0]))
       || (cc_status.value2 && rtx_equal_p (cc_status.value2, operands[0])))
       || (cc_status.value2 && rtx_equal_p (cc_status.value2, operands[0])))
     return \"bne\\t%l1\";
     return \"bne\\t%l1\";
   else
   else
     return \"tbne\\t%0,%l1\";
     return \"tbne\\t%0,%l1\";
}")
}")
;;
;;
;; Test and branch with 8-bit register.  Register must be B (or A).
;; Test and branch with 8-bit register.  Register must be B (or A).
;;
;;
(define_insn "*tbeq8"
(define_insn "*tbeq8"
  [(set (pc)
  [(set (pc)
        (if_then_else (eq (match_operand:QI 0 "register_operand" "d")
        (if_then_else (eq (match_operand:QI 0 "register_operand" "d")
                          (const_int 0))
                          (const_int 0))
                      (label_ref (match_operand 1 "" ""))
                      (label_ref (match_operand 1 "" ""))
                      (pc)))]
                      (pc)))]
  "TARGET_M6812"
  "TARGET_M6812"
  "*
  "*
{
{
   if ((cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0]))
   if ((cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0]))
       || (cc_status.value2 && rtx_equal_p (cc_status.value2, operands[0])))
       || (cc_status.value2 && rtx_equal_p (cc_status.value2, operands[0])))
     return \"beq\\t%l1\";
     return \"beq\\t%l1\";
   else
   else
     return \"tbeq\\tb,%l1\";
     return \"tbeq\\tb,%l1\";
}")
}")
(define_insn "*tbne8"
(define_insn "*tbne8"
  [(set (pc)
  [(set (pc)
        (if_then_else (ne (match_operand:QI 0 "register_operand" "d")
        (if_then_else (ne (match_operand:QI 0 "register_operand" "d")
                          (const_int 0))
                          (const_int 0))
                      (label_ref (match_operand 1 "" ""))
                      (label_ref (match_operand 1 "" ""))
                      (pc)))]
                      (pc)))]
  "TARGET_M6812"
  "TARGET_M6812"
  "*
  "*
{
{
   if ((cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0]))
   if ((cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0]))
       || (cc_status.value2 && rtx_equal_p (cc_status.value2, operands[0])))
       || (cc_status.value2 && rtx_equal_p (cc_status.value2, operands[0])))
     return \"bne\\t%l1\";
     return \"bne\\t%l1\";
   else
   else
     return \"tbne\\tb,%l1\";
     return \"tbne\\tb,%l1\";
}")
}")
(define_insn "*beq"
(define_insn "*beq"
  [(set (pc)
  [(set (pc)
        (if_then_else (eq (cc0)
        (if_then_else (eq (cc0)
                          (const_int 0))
                          (const_int 0))
                      (label_ref (match_operand 0 "" ""))
                      (label_ref (match_operand 0 "" ""))
                      (pc)))]
                      (pc)))]
  ""
  ""
  "beq\\t%l0")
  "beq\\t%l0")
(define_insn "*bne"
(define_insn "*bne"
  [(set (pc)
  [(set (pc)
        (if_then_else (ne (cc0)
        (if_then_else (ne (cc0)
                          (const_int 0))
                          (const_int 0))
                      (label_ref (match_operand 0 "" ""))
                      (label_ref (match_operand 0 "" ""))
                      (pc)))]
                      (pc)))]
  ""
  ""
  "bne\\t%l0")
  "bne\\t%l0")
(define_insn "*bgt"
(define_insn "*bgt"
  [(set (pc)
  [(set (pc)
        (if_then_else (gt (cc0)
        (if_then_else (gt (cc0)
                          (const_int 0))
                          (const_int 0))
                      (label_ref (match_operand 0 "" ""))
                      (label_ref (match_operand 0 "" ""))
                      (pc)))]
                      (pc)))]
  ""
  ""
  "bgt\\t%l0")
  "bgt\\t%l0")
(define_insn "*bgtu"
(define_insn "*bgtu"
  [(set (pc)
  [(set (pc)
        (if_then_else (gtu (cc0)
        (if_then_else (gtu (cc0)
                           (const_int 0))
                           (const_int 0))
                      (label_ref (match_operand 0 "" ""))
                      (label_ref (match_operand 0 "" ""))
                      (pc)))]
                      (pc)))]
  ""
  ""
  "bhi\\t%l0")
  "bhi\\t%l0")
(define_insn "*blt"
(define_insn "*blt"
  [(set (pc)
  [(set (pc)
        (if_then_else (lt (cc0)
        (if_then_else (lt (cc0)
                          (const_int 0))
                          (const_int 0))
                      (label_ref (match_operand 0 "" ""))
                      (label_ref (match_operand 0 "" ""))
                      (pc)))]
                      (pc)))]
  ""
  ""
  "*
  "*
{
{
  if (cc_prev_status.flags & CC_NO_OVERFLOW)
  if (cc_prev_status.flags & CC_NO_OVERFLOW)
    return \"bmi\\t%l0\";
    return \"bmi\\t%l0\";
  else
  else
    return \"blt\\t%l0\";
    return \"blt\\t%l0\";
}")
}")
(define_insn "*bltu"
(define_insn "*bltu"
  [(set (pc)
  [(set (pc)
        (if_then_else (ltu (cc0)
        (if_then_else (ltu (cc0)
                           (const_int 0))
                           (const_int 0))
                      (label_ref (match_operand 0 "" ""))
                      (label_ref (match_operand 0 "" ""))
                      (pc)))]
                      (pc)))]
  ""
  ""
  "blo\\t%l0")
  "blo\\t%l0")
(define_insn "*bge"
(define_insn "*bge"
  [(set (pc)
  [(set (pc)
        (if_then_else (ge (cc0)
        (if_then_else (ge (cc0)
                          (const_int 0))
                          (const_int 0))
                      (label_ref (match_operand 0 "" ""))
                      (label_ref (match_operand 0 "" ""))
                      (pc)))]
                      (pc)))]
  ""
  ""
  "*
  "*
{
{
  if (cc_prev_status.flags & CC_NO_OVERFLOW)
  if (cc_prev_status.flags & CC_NO_OVERFLOW)
    return \"bpl\\t%l0\";
    return \"bpl\\t%l0\";
  else
  else
    return \"bge\\t%l0\";
    return \"bge\\t%l0\";
}")
}")
(define_insn "*bgeu"
(define_insn "*bgeu"
  [(set (pc)
  [(set (pc)
        (if_then_else (geu (cc0)
        (if_then_else (geu (cc0)
                           (const_int 0))
                           (const_int 0))
                      (label_ref (match_operand 0 "" ""))
                      (label_ref (match_operand 0 "" ""))
                      (pc)))]
                      (pc)))]
  ""
  ""
  "bhs\\t%l0")
  "bhs\\t%l0")
(define_insn "*ble"
(define_insn "*ble"
  [(set (pc)
  [(set (pc)
        (if_then_else (le (cc0)
        (if_then_else (le (cc0)
                          (const_int 0))
                          (const_int 0))
                      (label_ref (match_operand 0 "" ""))
                      (label_ref (match_operand 0 "" ""))
                      (pc)))]
                      (pc)))]
  ""
  ""
  "*
  "*
{
{
  if (cc_prev_status.flags & CC_NO_OVERFLOW)
  if (cc_prev_status.flags & CC_NO_OVERFLOW)
    return \"bmi\\t%l0\\n\\tbeq\\t%l0\";
    return \"bmi\\t%l0\\n\\tbeq\\t%l0\";
  else
  else
    return \"ble\\t%l0\";
    return \"ble\\t%l0\";
}")
}")
(define_insn "*bleu"
(define_insn "*bleu"
  [(set (pc)
  [(set (pc)
        (if_then_else (leu (cc0)
        (if_then_else (leu (cc0)
                           (const_int 0))
                           (const_int 0))
                      (label_ref (match_operand 0 "" ""))
                      (label_ref (match_operand 0 "" ""))
                      (pc)))]
                      (pc)))]
  ""
  ""
  "bls\\t%l0")
  "bls\\t%l0")
;;--------------------------------------------------------------------
;;--------------------------------------------------------------------
;;- Negative test and branch
;;- Negative test and branch
;;--------------------------------------------------------------------
;;--------------------------------------------------------------------
(define_insn ""
(define_insn ""
  [(set (pc)
  [(set (pc)
        (if_then_else (eq (cc0)
        (if_then_else (eq (cc0)
                          (const_int 0))
                          (const_int 0))
                      (pc)
                      (pc)
                      (label_ref (match_operand 0 "" ""))))]
                      (label_ref (match_operand 0 "" ""))))]
  ""
  ""
  "bne\\t%l0")
  "bne\\t%l0")
(define_insn ""
(define_insn ""
  [(set (pc)
  [(set (pc)
        (if_then_else (ne (cc0)
        (if_then_else (ne (cc0)
                          (const_int 0))
                          (const_int 0))
                      (pc)
                      (pc)
                      (label_ref (match_operand 0 "" ""))))]
                      (label_ref (match_operand 0 "" ""))))]
  ""
  ""
  "beq\\t%l0")
  "beq\\t%l0")
(define_insn ""
(define_insn ""
  [(set (pc)
  [(set (pc)
        (if_then_else (gt (cc0)
        (if_then_else (gt (cc0)
                          (const_int 0))
                          (const_int 0))
                      (pc)
                      (pc)
                      (label_ref (match_operand 0 "" ""))))]
                      (label_ref (match_operand 0 "" ""))))]
  ""
  ""
  "*
  "*
{
{
  if (cc_prev_status.flags & CC_NO_OVERFLOW)
  if (cc_prev_status.flags & CC_NO_OVERFLOW)
    return \"bmi\\t%l0\\n\\tbeq\\t%l0\";
    return \"bmi\\t%l0\\n\\tbeq\\t%l0\";
  else
  else
    return \"ble\\t%l0\";
    return \"ble\\t%l0\";
}")
}")
(define_insn ""
(define_insn ""
  [(set (pc)
  [(set (pc)
        (if_then_else (gtu (cc0)
        (if_then_else (gtu (cc0)
                           (const_int 0))
                           (const_int 0))
                      (pc)
                      (pc)
                      (label_ref (match_operand 0 "" ""))))]
                      (label_ref (match_operand 0 "" ""))))]
  ""
  ""
  "bls\\t%l0")
  "bls\\t%l0")
(define_insn ""
(define_insn ""
  [(set (pc)
  [(set (pc)
        (if_then_else (lt (cc0)
        (if_then_else (lt (cc0)
                          (const_int 0))
                          (const_int 0))
                      (pc)
                      (pc)
                      (label_ref (match_operand 0 "" ""))))]
                      (label_ref (match_operand 0 "" ""))))]
  ""
  ""
  "*
  "*
{
{
  if (cc_prev_status.flags & CC_NO_OVERFLOW)
  if (cc_prev_status.flags & CC_NO_OVERFLOW)
    return \"bpl\\t%l0\";
    return \"bpl\\t%l0\";
  else
  else
    return \"bge\\t%l0\";
    return \"bge\\t%l0\";
}")
}")
(define_insn ""
(define_insn ""
  [(set (pc)
  [(set (pc)
        (if_then_else (ltu (cc0)
        (if_then_else (ltu (cc0)
                           (const_int 0))
                           (const_int 0))
                      (pc)
                      (pc)
                      (label_ref (match_operand 0 "" ""))))]
                      (label_ref (match_operand 0 "" ""))))]
  ""
  ""
  "bhs\\t%l0")
  "bhs\\t%l0")
(define_insn ""
(define_insn ""
  [(set (pc)
  [(set (pc)
        (if_then_else (ge (cc0)
        (if_then_else (ge (cc0)
                          (const_int 0))
                          (const_int 0))
                      (pc)
                      (pc)
                      (label_ref (match_operand 0 "" ""))))]
                      (label_ref (match_operand 0 "" ""))))]
  ""
  ""
  "*
  "*
{
{
  if (cc_prev_status.flags & CC_NO_OVERFLOW)
  if (cc_prev_status.flags & CC_NO_OVERFLOW)
    return \"bmi\\t%l0\";
    return \"bmi\\t%l0\";
  else
  else
    return \"blt\\t%l0\";
    return \"blt\\t%l0\";
}")
}")
(define_insn ""
(define_insn ""
  [(set (pc)
  [(set (pc)
        (if_then_else (geu (cc0)
        (if_then_else (geu (cc0)
                           (const_int 0))
                           (const_int 0))
                      (pc)
                      (pc)
                      (label_ref (match_operand 0 "" ""))))]
                      (label_ref (match_operand 0 "" ""))))]
  ""
  ""
  "blo\\t%l0")
  "blo\\t%l0")
(define_insn ""
(define_insn ""
  [(set (pc)
  [(set (pc)
        (if_then_else (le (cc0)
        (if_then_else (le (cc0)
                          (const_int 0))
                          (const_int 0))
                      (pc)
                      (pc)
                      (label_ref (match_operand 0 "" ""))))]
                      (label_ref (match_operand 0 "" ""))))]
  ""
  ""
  "bgt\\t%l0")
  "bgt\\t%l0")
(define_insn ""
(define_insn ""
  [(set (pc)
  [(set (pc)
        (if_then_else (leu (cc0)
        (if_then_else (leu (cc0)
                           (const_int 0))
                           (const_int 0))
                      (pc)
                      (pc)
                      (label_ref (match_operand 0 "" ""))))]
                      (label_ref (match_operand 0 "" ""))))]
  ""
  ""
  "bhi\\t%l0")
  "bhi\\t%l0")
;;--------------------------------------------------------------------
;;--------------------------------------------------------------------
;;-  Calls
;;-  Calls
;;--------------------------------------------------------------------
;;--------------------------------------------------------------------
;;
;;
;;- Call a function that returns no value.
;;- Call a function that returns no value.
(define_insn "call"
(define_insn "call"
  [(call (match_operand:QI 0 "memory_operand" "m")
  [(call (match_operand:QI 0 "memory_operand" "m")
         (match_operand:SI 1 "general_operand" "g"))]
         (match_operand:SI 1 "general_operand" "g"))]
  ;; Operand 1 not really used on the m68hc11.
  ;; Operand 1 not really used on the m68hc11.
  ""
  ""
 "*
 "*
{
{
  if (GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF)
  if (GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF)
    {
    {
      if (m68hc11_is_far_symbol (operands[0]))
      if (m68hc11_is_far_symbol (operands[0]))
        {
        {
          if (TARGET_M6812)
          if (TARGET_M6812)
            {
            {
              output_asm_insn (\"call\\t%0\", operands);
              output_asm_insn (\"call\\t%0\", operands);
              return \"\";
              return \"\";
            }
            }
          else
          else
            {
            {
              output_asm_insn (\"pshb\", operands);
              output_asm_insn (\"pshb\", operands);
              output_asm_insn (\"ldab\\t#%%page(%0)\", operands);
              output_asm_insn (\"ldab\\t#%%page(%0)\", operands);
              output_asm_insn (\"ldy\\t#%%addr(%0)\", operands);
              output_asm_insn (\"ldy\\t#%%addr(%0)\", operands);
              return \"jsr\\t__call_a32\";
              return \"jsr\\t__call_a32\";
            }
            }
        }
        }
      if (m68hc11_is_trap_symbol (operands[0]))
      if (m68hc11_is_trap_symbol (operands[0]))
        return \"swi\";
        return \"swi\";
      else
      else
        return \"bsr\\t%0\";
        return \"bsr\\t%0\";
    }
    }
  else
  else
    {
    {
      return \"jsr\\t%0\";
      return \"jsr\\t%0\";
    }
    }
}")
}")
(define_insn "call_value"
(define_insn "call_value"
  [(set (match_operand 0 "" "=g")
  [(set (match_operand 0 "" "=g")
        (call (match_operand:QI 1 "memory_operand" "m")
        (call (match_operand:QI 1 "memory_operand" "m")
              (match_operand:SI 2 "general_operand" "g")))]
              (match_operand:SI 2 "general_operand" "g")))]
  ""
  ""
 "*
 "*
{
{
  if (GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
  if (GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
    {
    {
      if (m68hc11_is_far_symbol (operands[1]))
      if (m68hc11_is_far_symbol (operands[1]))
        {
        {
          if (TARGET_M6812)
          if (TARGET_M6812)
            {
            {
              output_asm_insn (\"call\\t%1\", operands);
              output_asm_insn (\"call\\t%1\", operands);
              return \"\";
              return \"\";
            }
            }
          else
          else
            {
            {
              output_asm_insn (\"pshb\", operands);
              output_asm_insn (\"pshb\", operands);
              output_asm_insn (\"ldab\\t#%%page(%1)\", operands);
              output_asm_insn (\"ldab\\t#%%page(%1)\", operands);
              output_asm_insn (\"ldy\\t#%%addr(%1)\", operands);
              output_asm_insn (\"ldy\\t#%%addr(%1)\", operands);
              return \"jsr\\t__call_a32\";
              return \"jsr\\t__call_a32\";
            }
            }
        }
        }
      if (m68hc11_is_trap_symbol (operands[1]))
      if (m68hc11_is_trap_symbol (operands[1]))
        return \"swi\";
        return \"swi\";
      else
      else
        return \"bsr\\t%1\";
        return \"bsr\\t%1\";
    }
    }
  else
  else
    {
    {
      return \"jsr\\t%1\";
      return \"jsr\\t%1\";
    }
    }
}")
}")
;; Call subroutine returning any type.
;; Call subroutine returning any type.
(define_expand "untyped_call"
(define_expand "untyped_call"
  [(parallel [(call (match_operand 0 "" "")
  [(parallel [(call (match_operand 0 "" "")
                    (const_int 0))
                    (const_int 0))
              (match_operand 1 "" "")
              (match_operand 1 "" "")
              (match_operand 2 "" "")])]
              (match_operand 2 "" "")])]
  ""
  ""
  "
  "
{
{
  int i;
  int i;
  emit_call_insn (gen_call (operands[0], const0_rtx));
  emit_call_insn (gen_call (operands[0], const0_rtx));
  for (i = 0; i < XVECLEN (operands[2], 0); i++)
  for (i = 0; i < XVECLEN (operands[2], 0); i++)
    {
    {
      rtx set = XVECEXP (operands[2], 0, i);
      rtx set = XVECEXP (operands[2], 0, i);
      emit_move_insn (SET_DEST (set), SET_SRC (set));
      emit_move_insn (SET_DEST (set), SET_SRC (set));
    }
    }
  /* The optimizer does not know that the call sets the function value
  /* The optimizer does not know that the call sets the function value
     registers we stored in the result block.  We avoid problems by
     registers we stored in the result block.  We avoid problems by
     claiming that all hard registers are used and clobbered at this
     claiming that all hard registers are used and clobbered at this
     point.  */
     point.  */
  emit_insn (gen_blockage ());
  emit_insn (gen_blockage ());
  DONE;
  DONE;
}")
}")
;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
;; all of memory.  This blocks insns from being moved across this point.
;; all of memory.  This blocks insns from being moved across this point.
(define_insn "blockage"
(define_insn "blockage"
  [(unspec_volatile [(const_int 0)] 0)]
  [(unspec_volatile [(const_int 0)] 0)]
  ""
  ""
  "")
  "")
(define_insn "nop"
(define_insn "nop"
  [(const_int 0)]
  [(const_int 0)]
  ""
  ""
  "nop")
  "nop")
(define_expand "prologue"
(define_expand "prologue"
  [(const_int 0)]
  [(const_int 0)]
  ""
  ""
  "
  "
{
{
  expand_prologue ();
  expand_prologue ();
  DONE;
  DONE;
}")
}")
(define_expand "epilogue"
(define_expand "epilogue"
  [(return)]
  [(return)]
  ""
  ""
  "
  "
{
{
  expand_epilogue ();
  expand_epilogue ();
  DONE;
  DONE;
}")
}")
;; Used for frameless functions which save no regs and allocate no locals.
;; Used for frameless functions which save no regs and allocate no locals.
(define_expand "return"
(define_expand "return"
  [(return)]
  [(return)]
  "reload_completed && m68hc11_total_frame_size () == 0"
  "reload_completed && m68hc11_total_frame_size () == 0"
  "
  "
{
{
  int ret_size = 0;
  int ret_size = 0;
  if (current_function_return_rtx)
  if (current_function_return_rtx)
    ret_size = GET_MODE_SIZE (GET_MODE (current_function_return_rtx));
    ret_size = GET_MODE_SIZE (GET_MODE (current_function_return_rtx));
  /* Emit use notes only when HAVE_return is true.  */
  /* Emit use notes only when HAVE_return is true.  */
  if (m68hc11_total_frame_size () != 0)
  if (m68hc11_total_frame_size () != 0)
    ret_size = 0;
    ret_size = 0;
  if (ret_size && ret_size <= 2)
  if (ret_size && ret_size <= 2)
    {
    {
      emit_jump_insn (gen_rtx_PARALLEL (VOIDmode,
      emit_jump_insn (gen_rtx_PARALLEL (VOIDmode,
                      gen_rtvec (2, gen_rtx_RETURN (VOIDmode),
                      gen_rtvec (2, gen_rtx_RETURN (VOIDmode),
                                 gen_rtx_USE (VOIDmode,
                                 gen_rtx_USE (VOIDmode,
                                              gen_rtx_REG (HImode, 1)))));
                                              gen_rtx_REG (HImode, 1)))));
      DONE;
      DONE;
    }
    }
  if (ret_size)
  if (ret_size)
    {
    {
      emit_jump_insn (gen_rtx_PARALLEL (VOIDmode,
      emit_jump_insn (gen_rtx_PARALLEL (VOIDmode,
                      gen_rtvec (2, gen_rtx_RETURN (VOIDmode),
                      gen_rtvec (2, gen_rtx_RETURN (VOIDmode),
                                 gen_rtx_USE (VOIDmode,
                                 gen_rtx_USE (VOIDmode,
                                              gen_rtx_REG (SImode, 0)))));
                                              gen_rtx_REG (SImode, 0)))));
      DONE;
      DONE;
    }
    }
}")
}")
(define_insn "*return_void"
(define_insn "*return_void"
  [(return)]
  [(return)]
  "reload_completed"
  "reload_completed"
  "*
  "*
{
{
  rtx next = next_active_insn (insn);
  rtx next = next_active_insn (insn);
  if (next
  if (next
      && GET_CODE (next) == JUMP_INSN
      && GET_CODE (next) == JUMP_INSN
      && GET_CODE (PATTERN (next)) == RETURN)
      && GET_CODE (PATTERN (next)) == RETURN)
    return \"\";
    return \"\";
  if (current_function_interrupt || current_function_trap)
  if (current_function_interrupt || current_function_trap)
    return \"rti\";
    return \"rti\";
  else if (!current_function_far)
  else if (!current_function_far)
    return \"rts\";
    return \"rts\";
  else if (TARGET_M6812)
  else if (TARGET_M6812)
    return \"rtc\";
    return \"rtc\";
  else
  else
    {
    {
      int ret_size = 0;
      int ret_size = 0;
      if (current_function_return_rtx)
      if (current_function_return_rtx)
        ret_size = GET_MODE_SIZE (GET_MODE (current_function_return_rtx));
        ret_size = GET_MODE_SIZE (GET_MODE (current_function_return_rtx));
      if (ret_size == 0)
      if (ret_size == 0)
        return \"jmp\\t__return_void\";
        return \"jmp\\t__return_void\";
      if (ret_size <= 2)
      if (ret_size <= 2)
        return \"jmp\\t__return_16\";
        return \"jmp\\t__return_16\";
      if (ret_size <= 4)
      if (ret_size <= 4)
        return \"jmp\\t__return_32\";
        return \"jmp\\t__return_32\";
      return \"jmp\\t__return_16\";
      return \"jmp\\t__return_16\";
    }
    }
}")
}")
(define_insn "*return_16bit"
(define_insn "*return_16bit"
  [(return)
  [(return)
   (use (reg:HI D_REGNUM))]
   (use (reg:HI D_REGNUM))]
  "reload_completed && m68hc11_total_frame_size () == 0"
  "reload_completed && m68hc11_total_frame_size () == 0"
  "*
  "*
{
{
  rtx next = next_active_insn (insn);
  rtx next = next_active_insn (insn);
  if (next
  if (next
      && GET_CODE (next) == JUMP_INSN
      && GET_CODE (next) == JUMP_INSN
      && GET_CODE (PATTERN (next)) == RETURN)
      && GET_CODE (PATTERN (next)) == RETURN)
    return \"\";
    return \"\";
  if (current_function_interrupt || current_function_trap)
  if (current_function_interrupt || current_function_trap)
    return \"rti\";
    return \"rti\";
  else if (!current_function_far)
  else if (!current_function_far)
    return \"rts\";
    return \"rts\";
  else if (TARGET_M6812)
  else if (TARGET_M6812)
    return \"rtc\";
    return \"rtc\";
  else
  else
    return \"jmp\\t__return_16\";
    return \"jmp\\t__return_16\";
}")
}")
(define_insn "*return_32bit"
(define_insn "*return_32bit"
  [(return)
  [(return)
   (use (reg:SI 0))]
   (use (reg:SI 0))]
  "reload_completed && m68hc11_total_frame_size () == 0"
  "reload_completed && m68hc11_total_frame_size () == 0"
  "*
  "*
{
{
  rtx next = next_active_insn (insn);
  rtx next = next_active_insn (insn);
  if (next
  if (next
      && GET_CODE (next) == JUMP_INSN
      && GET_CODE (next) == JUMP_INSN
      && GET_CODE (PATTERN (next)) == RETURN)
      && GET_CODE (PATTERN (next)) == RETURN)
    return \"\";
    return \"\";
  if (current_function_interrupt || current_function_trap)
  if (current_function_interrupt || current_function_trap)
    return \"rti\";
    return \"rti\";
  else if (!current_function_far)
  else if (!current_function_far)
    return \"rts\";
    return \"rts\";
  else if (TARGET_M6812)
  else if (TARGET_M6812)
    return \"rtc\";
    return \"rtc\";
  else
  else
    return \"jmp\\t__return_32\";
    return \"jmp\\t__return_32\";
}")
}")
(define_insn "indirect_jump"
(define_insn "indirect_jump"
  [(set (pc) (match_operand:HI 0 "nonimmediate_operand" "xy"))]
  [(set (pc) (match_operand:HI 0 "nonimmediate_operand" "xy"))]
  ""
  ""
  "jmp\\t0,%0")
  "jmp\\t0,%0")
;;--------------------------------------------------------------------
;;--------------------------------------------------------------------
;;-  Table jump
;;-  Table jump
;;--------------------------------------------------------------------
;;--------------------------------------------------------------------
;;
;;
;; Operand 0 is the address of the table element to use
;; Operand 0 is the address of the table element to use
;; operand 1 is the CODE_LABEL for the table
;; operand 1 is the CODE_LABEL for the table
;;--------------------------------------------------------------------
;;--------------------------------------------------------------------
(define_expand "tablejump"
(define_expand "tablejump"
  [(parallel [(set (pc) (match_operand 0 "" ""))
  [(parallel [(set (pc) (match_operand 0 "" ""))
              (use (label_ref (match_operand 1 "" "")))])]
              (use (label_ref (match_operand 1 "" "")))])]
  ""
  ""
  "")
  "")
(define_insn "*jump_indirect"
(define_insn "*jump_indirect"
   [(parallel [
   [(parallel [
        (set (pc) (match_operand:HI 0 "register_operand" "xy"))
        (set (pc) (match_operand:HI 0 "register_operand" "xy"))
        (use (label_ref (match_operand 1 "" "")))])]
        (use (label_ref (match_operand 1 "" "")))])]
   ""
   ""
  "jmp\\t0,%0")
  "jmp\\t0,%0")
;;--------------------------------------------------------------------
;;--------------------------------------------------------------------
;;- Peepholes
;;- Peepholes
;;--------------------------------------------------------------------
;;--------------------------------------------------------------------
;;--------------------------------------------------------------------
;;--------------------------------------------------------------------
;;- 68HC12 dbcc/ibcc peepholes
;;- 68HC12 dbcc/ibcc peepholes
;;--------------------------------------------------------------------
;;--------------------------------------------------------------------
;;
;;
;; Replace: "addd #-1; bne L1" into "dbne d,L1"
;; Replace: "addd #-1; bne L1" into "dbne d,L1"
;;          "addd #-1; beq L1" into "dbeq d,L1"
;;          "addd #-1; beq L1" into "dbeq d,L1"
;;          "addd #1; bne L1" into "ibne d,L1"
;;          "addd #1; bne L1" into "ibne d,L1"
;;          "addd #1; beq L1" into "ibeq d,L1"
;;          "addd #1; beq L1" into "ibeq d,L1"
;;
;;
(define_peephole2
(define_peephole2
  [(set (match_operand:HI 0 "hard_reg_operand" "")
  [(set (match_operand:HI 0 "hard_reg_operand" "")
        (plus:HI (match_dup 0)
        (plus:HI (match_dup 0)
                 (match_operand:HI 1 "const_int_operand" "")))
                 (match_operand:HI 1 "const_int_operand" "")))
   (set (pc)
   (set (pc)
        (if_then_else (match_operator 2 "m68hc11_eq_compare_operator"
        (if_then_else (match_operator 2 "m68hc11_eq_compare_operator"
                         [(match_dup 0)
                         [(match_dup 0)
                          (const_int 0)])
                          (const_int 0)])
                      (label_ref (match_operand 3 "" "")) (pc)))]
                      (label_ref (match_operand 3 "" "")) (pc)))]
  "TARGET_M6812 && (INTVAL (operands[1]) == 1 || INTVAL (operands[1]) == -1)"
  "TARGET_M6812 && (INTVAL (operands[1]) == 1 || INTVAL (operands[1]) == -1)"
  [(parallel [
  [(parallel [
      (set (pc) (if_then_else (match_op_dup 2 [(match_dup 0) (match_dup 5)])
      (set (pc) (if_then_else (match_op_dup 2 [(match_dup 0) (match_dup 5)])
                              (label_ref (match_dup 3)) (pc)))
                              (label_ref (match_dup 3)) (pc)))
      (set (match_dup 0) (plus:HI (match_dup 0) (match_dup 1)))
      (set (match_dup 0) (plus:HI (match_dup 0) (match_dup 1)))
      (clobber (match_dup 4))])]
      (clobber (match_dup 4))])]
  "operands[4] = gen_rtx_SCRATCH(HImode);
  "operands[4] = gen_rtx_SCRATCH(HImode);
   operands[5] = GEN_INT (-INTVAL (operands[1]));")
   operands[5] = GEN_INT (-INTVAL (operands[1]));")
;;
;;
;; Replace: "addb #-1; bne L1" into "dbne b,L1"
;; Replace: "addb #-1; bne L1" into "dbne b,L1"
;;          "addb #-1; beq L1" into "dbeq b,L1"
;;          "addb #-1; beq L1" into "dbeq b,L1"
;;
;;
(define_peephole2
(define_peephole2
  [(set (match_operand:QI 0 "hard_reg_operand" "")
  [(set (match_operand:QI 0 "hard_reg_operand" "")
        (plus:QI (match_dup 0)
        (plus:QI (match_dup 0)
                 (match_operand:QI 1 "const_int_operand" "")))
                 (match_operand:QI 1 "const_int_operand" "")))
   (set (pc)
   (set (pc)
        (if_then_else (match_operator 2 "m68hc11_eq_compare_operator"
        (if_then_else (match_operator 2 "m68hc11_eq_compare_operator"
                         [(match_dup 0)
                         [(match_dup 0)
                          (const_int 0)])
                          (const_int 0)])
                      (label_ref (match_operand 3 "" "")) (pc)))]
                      (label_ref (match_operand 3 "" "")) (pc)))]
  "TARGET_M6812 && D_REG_P (operands[0])
  "TARGET_M6812 && D_REG_P (operands[0])
   && (INTVAL (operands[1]) == 1 || INTVAL (operands[1]) == -1)"
   && (INTVAL (operands[1]) == 1 || INTVAL (operands[1]) == -1)"
  [(parallel [
  [(parallel [
      (set (pc) (if_then_else (match_op_dup 2 [(match_dup 0) (match_dup 5)])
      (set (pc) (if_then_else (match_op_dup 2 [(match_dup 0) (match_dup 5)])
                              (label_ref (match_dup 3)) (pc)))
                              (label_ref (match_dup 3)) (pc)))
      (set (match_dup 0) (plus:QI (match_dup 0) (match_dup 1)))
      (set (match_dup 0) (plus:QI (match_dup 0) (match_dup 1)))
      (clobber (match_dup 4))])]
      (clobber (match_dup 4))])]
  "operands[4] = gen_rtx_SCRATCH(QImode);
  "operands[4] = gen_rtx_SCRATCH(QImode);
   operands[5] = GEN_INT (-INTVAL (operands[1]));")
   operands[5] = GEN_INT (-INTVAL (operands[1]));")
;;--------------------------------------------------------------------
;;--------------------------------------------------------------------
;;- Move peephole2
;;- Move peephole2
;;--------------------------------------------------------------------
;;--------------------------------------------------------------------
;;
;;
;; Replace "leas 2,sp" with a "pulx" or a "puly".
;; Replace "leas 2,sp" with a "pulx" or a "puly".
;; On 68HC12, this is one cycle slower but one byte smaller.
;; On 68HC12, this is one cycle slower but one byte smaller.
;; pr target/6899: This peephole was not valid because a register CSE
;; pr target/6899: This peephole was not valid because a register CSE
;; pass removes the pulx/puly.  The 'use' clause ensure that the pulx is
;; pass removes the pulx/puly.  The 'use' clause ensure that the pulx is
;; not removed.
;; not removed.
;;
;;
(define_peephole2
(define_peephole2
  [(set (reg:HI SP_REGNUM) (plus:HI (reg:HI SP_REGNUM) (const_int 2)))
  [(set (reg:HI SP_REGNUM) (plus:HI (reg:HI SP_REGNUM) (const_int 2)))
   (match_scratch:HI 0 "xy")]
   (match_scratch:HI 0 "xy")]
  "TARGET_M6812 && optimize_size"
  "TARGET_M6812 && optimize_size"
  [(set (match_dup 0) (match_dup 1))
  [(set (match_dup 0) (match_dup 1))
   (use (match_dup 0))]
   (use (match_dup 0))]
  "operands[1] = gen_rtx_MEM (HImode,
  "operands[1] = gen_rtx_MEM (HImode,
                          gen_rtx_POST_INC (HImode,
                          gen_rtx_POST_INC (HImode,
                                   gen_rtx_REG (HImode, HARD_SP_REGNUM)));")
                                   gen_rtx_REG (HImode, HARD_SP_REGNUM)));")
;; Replace: "pshx; tfr d,x; stx 0,sp" into "pshd; tfr d,x"
;; Replace: "pshx; tfr d,x; stx 0,sp" into "pshd; tfr d,x"
;;
;;
;; PR 14542: emit a use to pretend we need the value of initial register.
;; PR 14542: emit a use to pretend we need the value of initial register.
;; Otherwise verify_local_live_at_start will die due to a live change
;; Otherwise verify_local_live_at_start will die due to a live change
;; of that register.
;; of that register.
;;
;;
(define_peephole2
(define_peephole2
  [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
  [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
        (match_operand:HI 0 "hard_reg_operand" ""))
        (match_operand:HI 0 "hard_reg_operand" ""))
   (set (match_dup 0)
   (set (match_dup 0)
        (match_operand:HI 1 "hard_reg_operand" ""))
        (match_operand:HI 1 "hard_reg_operand" ""))
   (set (mem:HI (reg:HI SP_REGNUM))
   (set (mem:HI (reg:HI SP_REGNUM))
        (match_dup 0))]
        (match_dup 0))]
  "TARGET_M6812"
  "TARGET_M6812"
  [(use (match_dup 0))
  [(use (match_dup 0))
   (set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
   (set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
        (match_dup 1))
        (match_dup 1))
   (set (match_dup 0) (match_dup 1))]
   (set (match_dup 0) (match_dup 1))]
  "")
  "")
;;
;;
;; Change: "ldd 0,sp; pulx" into  "puld"
;; Change: "ldd 0,sp; pulx" into  "puld"
;; This sequence usually appears at end a functions.
;; This sequence usually appears at end a functions.
(define_peephole2
(define_peephole2
  [(set (match_operand:HI 0 "hard_reg_operand" "")
  [(set (match_operand:HI 0 "hard_reg_operand" "")
        (mem:HI (reg:HI SP_REGNUM)))
        (mem:HI (reg:HI SP_REGNUM)))
   (use (match_dup 0))
   (use (match_dup 0))
   (set (match_operand:HI 1 "hard_reg_operand" "")
   (set (match_operand:HI 1 "hard_reg_operand" "")
        (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))]
        (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))]
  "peep2_reg_dead_p (2, operands[1])"
  "peep2_reg_dead_p (2, operands[1])"
  [(set (match_dup 0) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))
  [(set (match_dup 0) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))
   (use (match_dup 0))]
   (use (match_dup 0))]
  "")
  "")
;; Replace: "pshx; clr 0,sp; clr 1,sp" by "clr 1,-sp; clr 1,-sp"
;; Replace: "pshx; clr 0,sp; clr 1,sp" by "clr 1,-sp; clr 1,-sp"
;; Appears to allocate local variables.
;; Appears to allocate local variables.
(define_peephole2
(define_peephole2
  [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
  [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
        (match_operand:HI 0 "hard_reg_operand" ""))
        (match_operand:HI 0 "hard_reg_operand" ""))
   (set (mem:QI (plus:HI (reg:HI SP_REGNUM) (const_int 1)))
   (set (mem:QI (plus:HI (reg:HI SP_REGNUM) (const_int 1)))
        (const_int 0))
        (const_int 0))
   (set (mem:QI (reg:HI SP_REGNUM))
   (set (mem:QI (reg:HI SP_REGNUM))
        (const_int 0))]
        (const_int 0))]
  "TARGET_M6812"
  "TARGET_M6812"
  [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
  [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
        (const_int 0))]
        (const_int 0))]
  "")
  "")
;; Likewise for HI mode
;; Likewise for HI mode
(define_peephole2
(define_peephole2
  [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
  [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
        (match_operand:HI 0 "hard_reg_operand" ""))
        (match_operand:HI 0 "hard_reg_operand" ""))
   (set (mem:HI (reg:HI SP_REGNUM))
   (set (mem:HI (reg:HI SP_REGNUM))
        (const_int 0))]
        (const_int 0))]
  "TARGET_M6812"
  "TARGET_M6812"
  [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
  [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
        (const_int 0))]
        (const_int 0))]
  "")
  "")
;;--------------------------------------------------------------------
;;--------------------------------------------------------------------
;;-
;;-
;;--------------------------------------------------------------------
;;--------------------------------------------------------------------
;;
;;
;; Optimize memory<->memory moves when the value is also loaded in
;; Optimize memory<->memory moves when the value is also loaded in
;; a register.
;; a register.
;;
;;
(define_peephole2
(define_peephole2
  [(set (match_operand:QI 0 "memory_operand" "")
  [(set (match_operand:QI 0 "memory_operand" "")
        (match_operand:QI 1 "memory_operand" ""))
        (match_operand:QI 1 "memory_operand" ""))
   (set (reg:QI D_REGNUM)
   (set (reg:QI D_REGNUM)
        (match_operand:QI 2 "memory_operand" ""))]
        (match_operand:QI 2 "memory_operand" ""))]
  "(rtx_equal_p (operands[0], operands[2]) && !side_effects_p (operands[0]))
  "(rtx_equal_p (operands[0], operands[2]) && !side_effects_p (operands[0]))
   || (GET_CODE (XEXP (operands[0], 0)) == REG
   || (GET_CODE (XEXP (operands[0], 0)) == REG
       && GET_CODE (XEXP (operands[2], 0)) == POST_INC
       && GET_CODE (XEXP (operands[2], 0)) == POST_INC
       && rtx_equal_p (XEXP (operands[0], 0), XEXP (XEXP (operands[2], 0), 0)))"
       && rtx_equal_p (XEXP (operands[0], 0), XEXP (XEXP (operands[2], 0), 0)))"
  [(set (reg:QI D_REGNUM) (match_dup 1))
  [(set (reg:QI D_REGNUM) (match_dup 1))
   (set (match_dup 2) (reg:QI D_REGNUM))]
   (set (match_dup 2) (reg:QI D_REGNUM))]
  "")
  "")
;;
;;
;; Remove a possible move before a compare instruction when that
;; Remove a possible move before a compare instruction when that
;; move will go in a dead register.  Compare with the source then.
;; move will go in a dead register.  Compare with the source then.
;;
;;
(define_peephole2
(define_peephole2
  [(set (match_operand:HI 0 "hard_reg_operand" "")
  [(set (match_operand:HI 0 "hard_reg_operand" "")
        (match_operand:HI 1 "hard_reg_operand" ""))
        (match_operand:HI 1 "hard_reg_operand" ""))
   (set (cc0)
   (set (cc0)
        (compare (match_dup 0)
        (compare (match_dup 0)
                 (match_operand:HI 2 "cmp_operand" "")))]
                 (match_operand:HI 2 "cmp_operand" "")))]
  "(X_REG_P (operands[1]) || Y_REG_P (operands[1]))
  "(X_REG_P (operands[1]) || Y_REG_P (operands[1]))
   && peep2_reg_dead_p (2, operands[0])
   && peep2_reg_dead_p (2, operands[0])
   && !reg_mentioned_p (operands[0], operands[2])"
   && !reg_mentioned_p (operands[0], operands[2])"
  [(set (cc0) (compare (match_dup 1) (match_dup 2)))]
  [(set (cc0) (compare (match_dup 1) (match_dup 2)))]
  "")
  "")
;;
;;
;; Optimize loading a constant to memory when that same constant
;; Optimize loading a constant to memory when that same constant
;; is loaded to a hard register.  Switch the two to use the register
;; is loaded to a hard register.  Switch the two to use the register
;; for memory initialization.  In most cases, the constant is 0.
;; for memory initialization.  In most cases, the constant is 0.
;;
;;
(define_peephole2
(define_peephole2
  [(set (match_operand:HI 0 "memory_operand" "")
  [(set (match_operand:HI 0 "memory_operand" "")
        (match_operand:HI 1 "immediate_operand" ""))
        (match_operand:HI 1 "immediate_operand" ""))
   (set (match_operand:HI 2 "hard_reg_operand" "")
   (set (match_operand:HI 2 "hard_reg_operand" "")
        (match_dup 1))]
        (match_dup 1))]
  "(D_REG_P (operands[2]) || X_REG_P (operands[2]) || Y_REG_P (operands[2]))
  "(D_REG_P (operands[2]) || X_REG_P (operands[2]) || Y_REG_P (operands[2]))
   && !reg_mentioned_p (operands[2], operands[0])"
   && !reg_mentioned_p (operands[2], operands[0])"
  [(set (match_dup 2) (match_dup 1))
  [(set (match_dup 2) (match_dup 1))
   (set (match_dup 0) (match_dup 2))]
   (set (match_dup 0) (match_dup 2))]
  "")
  "")
;;
;;
;; Reorganize to optimize address computations.
;; Reorganize to optimize address computations.
;;
;;
(define_peephole2
(define_peephole2
  [(set (match_operand:HI 0 "hard_reg_operand" "")
  [(set (match_operand:HI 0 "hard_reg_operand" "")
        (match_operand:HI 1 "const_int_operand" ""))
        (match_operand:HI 1 "const_int_operand" ""))
   (set (match_dup 0)
   (set (match_dup 0)
        (plus:HI (match_dup 0)
        (plus:HI (match_dup 0)
                 (match_operand:HI 2 "general_operand" "")))]
                 (match_operand:HI 2 "general_operand" "")))]
  "(INTVAL (operands[1]) >= -2 && INTVAL (operands[1]) <= 2)"
  "(INTVAL (operands[1]) >= -2 && INTVAL (operands[1]) <= 2)"
  [(set (match_dup 0) (match_dup 2))
  [(set (match_dup 0) (match_dup 2))
   (set (match_dup 0) (plus:HI (match_dup 0) (match_dup 1)))]
   (set (match_dup 0) (plus:HI (match_dup 0) (match_dup 1)))]
  "")
  "")
;;
;;
;; Replace: "ldx #N; xgdx; addd ; xgdx" by "ldab #N; ldx ; abx"
;; Replace: "ldx #N; xgdx; addd ; xgdx" by "ldab #N; ldx ; abx"
;;
;;
(define_peephole2
(define_peephole2
  [(set (match_operand:HI 0 "hard_reg_operand" "")
  [(set (match_operand:HI 0 "hard_reg_operand" "")
        (match_operand:HI 1 "const_int_operand" ""))
        (match_operand:HI 1 "const_int_operand" ""))
   (set (match_dup 0)
   (set (match_dup 0)
        (plus:HI (match_dup 0)
        (plus:HI (match_dup 0)
                 (match_operand:HI 2 "general_operand" "")))
                 (match_operand:HI 2 "general_operand" "")))
   (match_scratch:QI 3 "d")]
   (match_scratch:QI 3 "d")]
  "TARGET_M6811 && (INTVAL (operands[1]) >= 0 && INTVAL (operands[1]) <= 0x0ff)"
  "TARGET_M6811 && (INTVAL (operands[1]) >= 0 && INTVAL (operands[1]) <= 0x0ff)"
  [(set (match_dup 3) (match_dup 4))
  [(set (match_dup 3) (match_dup 4))
   (set (match_dup 0) (match_dup 2))
   (set (match_dup 0) (match_dup 2))
   (set (match_dup 0) (plus:HI (zero_extend:HI (match_dup 3)) (match_dup 0)))]
   (set (match_dup 0) (plus:HI (zero_extend:HI (match_dup 3)) (match_dup 0)))]
  "operands[4] = m68hc11_gen_lowpart (QImode, operands[1]);")
  "operands[4] = m68hc11_gen_lowpart (QImode, operands[1]);")
;;
;;
;; Replace: "ldx #N; xgdx; addd ; xgdx" by "ldab #N; ldx ; abx"
;; Replace: "ldx #N; xgdx; addd ; xgdx" by "ldab #N; ldx ; abx"
;;
;;
(define_peephole2
(define_peephole2
  [(set (match_operand:HI 0 "hard_reg_operand" "")
  [(set (match_operand:HI 0 "hard_reg_operand" "")
        (match_operand:HI 1 "const_int_operand" ""))
        (match_operand:HI 1 "const_int_operand" ""))
   (set (match_dup 0)
   (set (match_dup 0)
        (plus:HI (match_dup 0)
        (plus:HI (match_dup 0)
                 (match_operand:HI 2 "general_operand" "")))]
                 (match_operand:HI 2 "general_operand" "")))]
  "TARGET_M6812"
  "TARGET_M6812"
  [(set (match_dup 0) (match_dup 2))
  [(set (match_dup 0) (match_dup 2))
   (set (match_dup 0) (plus:HI (match_dup 0) (match_dup 1)))]
   (set (match_dup 0) (plus:HI (match_dup 0) (match_dup 1)))]
  "")
  "")
;;
;;
;; Optimize an address register increment and a compare to use
;; Optimize an address register increment and a compare to use
;; a PRE_INC or PRE_DEC addressing mode (disabled on the tst insn
;; a PRE_INC or PRE_DEC addressing mode (disabled on the tst insn
;; before reload, but can be enabled after).
;; before reload, but can be enabled after).
;;
;;
(define_peephole2
(define_peephole2
  [(set (match_operand:HI 0 "hard_reg_operand" "")
  [(set (match_operand:HI 0 "hard_reg_operand" "")
        (plus:HI (match_dup 0)
        (plus:HI (match_dup 0)
                 (match_operand:HI 1 "const_int_operand" "")))
                 (match_operand:HI 1 "const_int_operand" "")))
   (set (cc0)
   (set (cc0)
        (match_operand:QI 2 "memory_operand" ""))]
        (match_operand:QI 2 "memory_operand" ""))]
  "TARGET_AUTO_INC_DEC
  "TARGET_AUTO_INC_DEC
   && (INTVAL (operands[1]) == -1 || INTVAL (operands[1]) == 1)
   && (INTVAL (operands[1]) == -1 || INTVAL (operands[1]) == 1)
   && reg_mentioned_p (operands[0], operands[2])"
   && reg_mentioned_p (operands[0], operands[2])"
  [(set (cc0) (match_dup 3))]
  [(set (cc0) (match_dup 3))]
  "if (INTVAL (operands[1]) == 1)
  "if (INTVAL (operands[1]) == 1)
     operands[3] = gen_rtx_MEM (QImode,
     operands[3] = gen_rtx_MEM (QImode,
                            gen_rtx_PRE_INC (HImode, operands[0]));
                            gen_rtx_PRE_INC (HImode, operands[0]));
   else
   else
     operands[3] = gen_rtx_MEM (QImode,
     operands[3] = gen_rtx_MEM (QImode,
                            gen_rtx_PRE_DEC (HImode, operands[0]));
                            gen_rtx_PRE_DEC (HImode, operands[0]));
  ")
  ")
;;
;;
;; Likewise for compare.
;; Likewise for compare.
;;
;;
(define_peephole2
(define_peephole2
  [(set (match_operand:HI 0 "hard_reg_operand" "")
  [(set (match_operand:HI 0 "hard_reg_operand" "")
        (plus:HI (match_dup 0)
        (plus:HI (match_dup 0)
                 (match_operand:HI 1 "const_int_operand" "")))
                 (match_operand:HI 1 "const_int_operand" "")))
   (set (cc0)
   (set (cc0)
        (compare (match_operand:QI 2 "hard_reg_operand" "")
        (compare (match_operand:QI 2 "hard_reg_operand" "")
                 (match_operand:QI 3 "memory_operand" "")))]
                 (match_operand:QI 3 "memory_operand" "")))]
  "TARGET_AUTO_INC_DEC
  "TARGET_AUTO_INC_DEC
   && (INTVAL (operands[1]) == -1 || INTVAL (operands[1]) == 1)
   && (INTVAL (operands[1]) == -1 || INTVAL (operands[1]) == 1)
   && reg_mentioned_p (operands[0], operands[3])"
   && reg_mentioned_p (operands[0], operands[3])"
  [(set (cc0) (compare (match_dup 2) (match_dup 4)))]
  [(set (cc0) (compare (match_dup 2) (match_dup 4)))]
  "if (INTVAL (operands[1]) == 1)
  "if (INTVAL (operands[1]) == 1)
     operands[4] = gen_rtx_MEM (QImode,
     operands[4] = gen_rtx_MEM (QImode,
                            gen_rtx_PRE_INC (HImode, operands[0]));
                            gen_rtx_PRE_INC (HImode, operands[0]));
   else
   else
     operands[4] = gen_rtx_MEM (QImode,
     operands[4] = gen_rtx_MEM (QImode,
                            gen_rtx_PRE_DEC (HImode, operands[0]));
                            gen_rtx_PRE_DEC (HImode, operands[0]));
  ")
  ")
(define_peephole2
(define_peephole2
  [(set (match_operand:HI 0 "hard_reg_operand" "")
  [(set (match_operand:HI 0 "hard_reg_operand" "")
        (plus:HI (match_dup 0)
        (plus:HI (match_dup 0)
                 (match_operand:HI 1 "const_int_operand" "")))
                 (match_operand:HI 1 "const_int_operand" "")))
   (set (cc0)
   (set (cc0)
        (compare (match_operand:QI 2 "memory_operand" "")
        (compare (match_operand:QI 2 "memory_operand" "")
                 (match_operand:QI 3 "hard_reg_operand" "")))]
                 (match_operand:QI 3 "hard_reg_operand" "")))]
  "TARGET_AUTO_INC_DEC
  "TARGET_AUTO_INC_DEC
   && (INTVAL (operands[1]) == -1 || INTVAL (operands[1]) == 1)
   && (INTVAL (operands[1]) == -1 || INTVAL (operands[1]) == 1)
   && reg_mentioned_p (operands[0], operands[2])"
   && reg_mentioned_p (operands[0], operands[2])"
  [(set (cc0) (compare (match_dup 4) (match_dup 3)))]
  [(set (cc0) (compare (match_dup 4) (match_dup 3)))]
  "if (INTVAL (operands[1]) == 1)
  "if (INTVAL (operands[1]) == 1)
     operands[4] = gen_rtx_MEM (QImode,
     operands[4] = gen_rtx_MEM (QImode,
                            gen_rtx_PRE_INC (HImode, operands[0]));
                            gen_rtx_PRE_INC (HImode, operands[0]));
   else
   else
     operands[4] = gen_rtx_MEM (QImode,
     operands[4] = gen_rtx_MEM (QImode,
                            gen_rtx_PRE_DEC (HImode, operands[0]));
                            gen_rtx_PRE_DEC (HImode, operands[0]));
  ")
  ")
;;
;;
;; Replace a "ldx #N; addx " with a "ldx ; addx #n"
;; Replace a "ldx #N; addx " with a "ldx ; addx #n"
;; (avoids many temporary moves because we can't add sp to another reg easily)
;; (avoids many temporary moves because we can't add sp to another reg easily)
;;
;;
(define_peephole2
(define_peephole2
  [(set (match_operand:HI 0 "hard_reg_operand" "")
  [(set (match_operand:HI 0 "hard_reg_operand" "")
        (match_operand:HI 1 "const_int_operand" ""))
        (match_operand:HI 1 "const_int_operand" ""))
   (set (match_dup 0) (plus:HI (match_dup 0) (reg:HI SP_REGNUM)))]
   (set (match_dup 0) (plus:HI (match_dup 0) (reg:HI SP_REGNUM)))]
  ""
  ""
  [(set (match_dup 0) (reg:HI SP_REGNUM))
  [(set (match_dup 0) (reg:HI SP_REGNUM))
   (set (match_dup 0) (plus:HI (match_dup 0) (match_dup 1)))]
   (set (match_dup 0) (plus:HI (match_dup 0) (match_dup 1)))]
  "")
  "")
;;
;;
;; Replace "ldd #N; addd " with "ldd ; addd #N".
;; Replace "ldd #N; addd " with "ldd ; addd #N".
;;
;;
(define_peephole2
(define_peephole2
  [(set (match_operand:HI 0 "hard_reg_operand" "")
  [(set (match_operand:HI 0 "hard_reg_operand" "")
        (match_operand:HI 1 "const_int_operand" ""))
        (match_operand:HI 1 "const_int_operand" ""))
   (set (match_dup 0)
   (set (match_dup 0)
        (plus:HI (match_dup 0)
        (plus:HI (match_dup 0)
                 (match_operand:HI 2 "general_operand" "")))]
                 (match_operand:HI 2 "general_operand" "")))]
  "(INTVAL (operands[1]) >= -2 && INTVAL (operands[1]) <= 2)"
  "(INTVAL (operands[1]) >= -2 && INTVAL (operands[1]) <= 2)"
  [(set (match_dup 0) (match_dup 2))
  [(set (match_dup 0) (match_dup 2))
   (set (match_dup 0) (plus:HI (match_dup 0) (match_dup 1)))]
   (set (match_dup 0) (plus:HI (match_dup 0) (match_dup 1)))]
  "")
  "")
;;
;;
;;
;;
;;
;;
(define_peephole2
(define_peephole2
  [(parallel
  [(parallel
     [(set (match_operand:SI 0 "hard_reg_operand" "")
     [(set (match_operand:SI 0 "hard_reg_operand" "")
        (ashift:SI (match_operand:SI 1 "general_operand" "")
        (ashift:SI (match_operand:SI 1 "general_operand" "")
                   (const_int 1)))
                   (const_int 1)))
      (clobber (match_scratch:HI 2 ""))])
      (clobber (match_scratch:HI 2 ""))])
   (set (match_operand:HI 3 "nonimmediate_operand" "") (reg:HI D_REGNUM))
   (set (match_operand:HI 3 "nonimmediate_operand" "") (reg:HI D_REGNUM))
   (set (match_operand:HI 4 "nonimmediate_operand" "") (reg:HI X_REGNUM))]
   (set (match_operand:HI 4 "nonimmediate_operand" "") (reg:HI X_REGNUM))]
  "!X_REG_P (operands[1])
  "!X_REG_P (operands[1])
   && peep2_reg_dead_p (2, gen_rtx_REG (HImode, D_REGNUM))
   && peep2_reg_dead_p (2, gen_rtx_REG (HImode, D_REGNUM))
   && peep2_reg_dead_p (3, gen_rtx_REG (HImode, X_REGNUM))"
   && peep2_reg_dead_p (3, gen_rtx_REG (HImode, X_REGNUM))"
  [(set (reg:HI D_REGNUM) (match_dup 5))
  [(set (reg:HI D_REGNUM) (match_dup 5))
   (set (reg:HI D_REGNUM) (ashift:HI (reg:HI D_REGNUM) (const_int 1)))
   (set (reg:HI D_REGNUM) (ashift:HI (reg:HI D_REGNUM) (const_int 1)))
   (set (match_dup 3) (reg:HI D_REGNUM))
   (set (match_dup 3) (reg:HI D_REGNUM))
   (set (reg:HI D_REGNUM) (match_dup 6))
   (set (reg:HI D_REGNUM) (match_dup 6))
   (parallel [(set (reg:HI D_REGNUM)
   (parallel [(set (reg:HI D_REGNUM)
                   (rotate:HI (reg:HI D_REGNUM) (const_int 1)))
                   (rotate:HI (reg:HI D_REGNUM) (const_int 1)))
              (clobber (reg:HI CC_REGNUM))])
              (clobber (reg:HI CC_REGNUM))])
   (set (match_dup 4) (reg:HI D_REGNUM))]
   (set (match_dup 4) (reg:HI D_REGNUM))]
  "operands[5] = m68hc11_gen_lowpart (HImode, operands[1]);
  "operands[5] = m68hc11_gen_lowpart (HImode, operands[1]);
   operands[6] = m68hc11_gen_highpart (HImode, operands[1]);")
   operands[6] = m68hc11_gen_highpart (HImode, operands[1]);")
;;
;;
;; Replace a "ldd ; psha; pshb" with a "ldx ; pshx".
;; Replace a "ldd ; psha; pshb" with a "ldx ; pshx".
;;
;;
(define_peephole2
(define_peephole2
  [(set (match_operand:HI 0 "hard_reg_operand" "")
  [(set (match_operand:HI 0 "hard_reg_operand" "")
        (match_operand:HI 1 "memory_operand" ""))
        (match_operand:HI 1 "memory_operand" ""))
   (set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
   (set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM)))
        (match_dup 0))
        (match_dup 0))
   (match_scratch:HI 2 "x")]
   (match_scratch:HI 2 "x")]
  "TARGET_M6811 && D_REG_P (operands[0]) && peep2_reg_dead_p (2, operands[0])"
  "TARGET_M6811 && D_REG_P (operands[0]) && peep2_reg_dead_p (2, operands[0])"
  [(set (match_dup 2) (match_dup 1))
  [(set (match_dup 2) (match_dup 1))
   (set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 2))]
   (set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 2))]
  "")
  "")
;;
;;
;; Remove one load when copying a value to/from memory and also
;; Remove one load when copying a value to/from memory and also
;; to a register.  Take care not clobbering a possible register used
;; to a register.  Take care not clobbering a possible register used
;; by operand 2.
;; by operand 2.
;; Replace: "ldd 0,y; std 2,y; ldx 0,y" into "ldx 0,y; stx 2,y"
;; Replace: "ldd 0,y; std 2,y; ldx 0,y" into "ldx 0,y; stx 2,y"
;;
;;
(define_peephole2
(define_peephole2
  [(set (match_operand:HI 0 "hard_reg_operand" "")
  [(set (match_operand:HI 0 "hard_reg_operand" "")
        (match_operand:HI 1 "general_operand" ""))
        (match_operand:HI 1 "general_operand" ""))
   (set (match_operand:HI 2 "nonimmediate_operand" "") (match_dup 0))
   (set (match_operand:HI 2 "nonimmediate_operand" "") (match_dup 0))
   (set (match_operand:HI 3 "hard_reg_operand" "") (match_dup 1))]
   (set (match_operand:HI 3 "hard_reg_operand" "") (match_dup 1))]
  "peep2_reg_dead_p (2, operands[0])
  "peep2_reg_dead_p (2, operands[0])
   && !side_effects_p (operands[1])
   && !side_effects_p (operands[1])
   && !side_effects_p (operands[2])
   && !side_effects_p (operands[2])
   && !reg_mentioned_p (operands[3], operands[2])"
   && !reg_mentioned_p (operands[3], operands[2])"
  [(set (match_dup 3) (match_dup 1))
  [(set (match_dup 3) (match_dup 1))
   (set (match_dup 2) (match_dup 3))]
   (set (match_dup 2) (match_dup 3))]
  "")
  "")
;;
;;
;; Replace a "ldd ; addd #N; std " into a
;; Replace a "ldd ; addd #N; std " into a
;; "ldx ; leax; stx " if we have a free X/Y register
;; "ldx ; leax; stx " if we have a free X/Y register
;; and the constant is small.
;; and the constant is small.
;;
;;
(define_peephole2
(define_peephole2
  [(set (match_operand:HI 0 "hard_reg_operand" "")
  [(set (match_operand:HI 0 "hard_reg_operand" "")
        (match_operand:HI 1 "general_operand" ""))
        (match_operand:HI 1 "general_operand" ""))
   (set (match_dup 0) (plus:HI (match_dup 0)
   (set (match_dup 0) (plus:HI (match_dup 0)
                               (match_operand:HI 2 "const_int_operand" "")))
                               (match_operand:HI 2 "const_int_operand" "")))
   (set (match_operand:HI 3 "nonimmediate_operand" "")
   (set (match_operand:HI 3 "nonimmediate_operand" "")
        (match_dup 0))
        (match_dup 0))
   (match_scratch:HI 4 "xy")]
   (match_scratch:HI 4 "xy")]
  "D_REG_P (operands[0])
  "D_REG_P (operands[0])
   && (TARGET_M6812
   && (TARGET_M6812
       || (INTVAL (operands[2]) >= -2 && INTVAL (operands[2]) <= 2))
       || (INTVAL (operands[2]) >= -2 && INTVAL (operands[2]) <= 2))
   && peep2_reg_dead_p (3, operands[0])"
   && peep2_reg_dead_p (3, operands[0])"
  [(set (match_dup 4) (match_dup 1))
  [(set (match_dup 4) (match_dup 1))
   (set (match_dup 4) (plus:HI (match_dup 4) (match_dup 2)))
   (set (match_dup 4) (plus:HI (match_dup 4) (match_dup 2)))
   (set (match_dup 3) (match_dup 4))]
   (set (match_dup 3) (match_dup 4))]
  "if (reg_mentioned_p (operands[4], operands[1])) FAIL;
  "if (reg_mentioned_p (operands[4], operands[1])) FAIL;
   if (reg_mentioned_p (operands[4], operands[3])) FAIL;")
   if (reg_mentioned_p (operands[4], operands[3])) FAIL;")
;;--------------------------------------------------------------------
;;--------------------------------------------------------------------
;;- Bset peephole2
;;- Bset peephole2
;;--------------------------------------------------------------------
;;--------------------------------------------------------------------
;; These peepholes try to replace some logical sequences by 'bset' and 'bclr'.
;; These peepholes try to replace some logical sequences by 'bset' and 'bclr'.
;;
;;
;; Replace 'ldab ; orab #N; stab ' by 'bset  #N'.
;; Replace 'ldab ; orab #N; stab ' by 'bset  #N'.
;; Register D must be dead and there must be no register side effects for mem.
;; Register D must be dead and there must be no register side effects for mem.
;; The  *can* be volatile this is why we must not use 'side_effects_p'.
;; The  *can* be volatile this is why we must not use 'side_effects_p'.
;; The good side effect is that it makes the sequence atomic.
;; The good side effect is that it makes the sequence atomic.
;;
;;
(define_peephole2
(define_peephole2
  [(set (match_operand:QI 0 "hard_reg_operand" "")
  [(set (match_operand:QI 0 "hard_reg_operand" "")
        (match_operand:QI 1 "nonimmediate_operand" ""))
        (match_operand:QI 1 "nonimmediate_operand" ""))
   (set (match_dup 0) (ior:QI (match_dup 0)
   (set (match_dup 0) (ior:QI (match_dup 0)
                              (match_operand:QI 2 "const_int_operand" "")))
                              (match_operand:QI 2 "const_int_operand" "")))
   (set (match_dup 1) (match_dup 0))]
   (set (match_dup 1) (match_dup 0))]
  "(TARGET_M6812 || m68hc11_indirect_p (operands[1], QImode))
  "(TARGET_M6812 || m68hc11_indirect_p (operands[1], QImode))
   && (GET_CODE (operands[1]) != MEM || !auto_inc_p (XEXP (operands[1], 0)))
   && (GET_CODE (operands[1]) != MEM || !auto_inc_p (XEXP (operands[1], 0)))
   && peep2_reg_dead_p (3, operands[0])"
   && peep2_reg_dead_p (3, operands[0])"
  [(set (match_dup 1) (ior:QI (match_dup 1) (match_dup 2)))]
  [(set (match_dup 1) (ior:QI (match_dup 1) (match_dup 2)))]
  "")
  "")
(define_peephole2
(define_peephole2
  [(set (match_operand:HI 0 "hard_reg_operand" "")
  [(set (match_operand:HI 0 "hard_reg_operand" "")
        (match_operand:HI 1 "nonimmediate_operand" ""))
        (match_operand:HI 1 "nonimmediate_operand" ""))
   (set (match_dup 0) (ior:HI (match_dup 0)
   (set (match_dup 0) (ior:HI (match_dup 0)
                              (match_operand:HI 2 "const_int_operand" "")))
                              (match_operand:HI 2 "const_int_operand" "")))
   (set (match_dup 1) (match_dup 0))]
   (set (match_dup 1) (match_dup 0))]
  "(TARGET_M6812 || m68hc11_indirect_p (operands[1], HImode))
  "(TARGET_M6812 || m68hc11_indirect_p (operands[1], HImode))
   && (GET_CODE (operands[1]) != MEM || !auto_inc_p (XEXP (operands[1], 0)))
   && (GET_CODE (operands[1]) != MEM || !auto_inc_p (XEXP (operands[1], 0)))
   && peep2_reg_dead_p (3, operands[0])"
   && peep2_reg_dead_p (3, operands[0])"
  [(set (match_dup 1) (ior:HI (match_dup 1) (match_dup 2)))]
  [(set (match_dup 1) (ior:HI (match_dup 1) (match_dup 2)))]
  "")
  "")
;;--------------------------------------------------------------------
;;--------------------------------------------------------------------
;;- Bclr peephole2
;;- Bclr peephole2
;;--------------------------------------------------------------------
;;--------------------------------------------------------------------
;; Replace 'ldab ; andab #N; stab ' by 'bclr  #N'.
;; Replace 'ldab ; andab #N; stab ' by 'bclr  #N'.
;; See Bset peephole2.
;; See Bset peephole2.
;;
;;
(define_peephole2
(define_peephole2
  [(set (match_operand:QI 0 "hard_reg_operand" "")
  [(set (match_operand:QI 0 "hard_reg_operand" "")
        (match_operand:QI 1 "nonimmediate_operand" ""))
        (match_operand:QI 1 "nonimmediate_operand" ""))
   (set (match_dup 0) (and:QI (match_dup 0)
   (set (match_dup 0) (and:QI (match_dup 0)
                              (match_operand:QI 2 "const_int_operand" "")))
                              (match_operand:QI 2 "const_int_operand" "")))
   (set (match_dup 1) (match_dup 0))]
   (set (match_dup 1) (match_dup 0))]
  "(TARGET_M6812 || m68hc11_indirect_p (operands[1], QImode))
  "(TARGET_M6812 || m68hc11_indirect_p (operands[1], QImode))
   && (GET_CODE (operands[1]) != MEM || !auto_inc_p (XEXP (operands[1], 0)))
   && (GET_CODE (operands[1]) != MEM || !auto_inc_p (XEXP (operands[1], 0)))
   && peep2_reg_dead_p (3, operands[0])"
   && peep2_reg_dead_p (3, operands[0])"
  [(set (match_dup 1) (and:QI (match_dup 1) (match_dup 2)))]
  [(set (match_dup 1) (and:QI (match_dup 1) (match_dup 2)))]
  "")
  "")
(define_peephole2
(define_peephole2
  [(set (match_operand:HI 0 "hard_reg_operand" "")
  [(set (match_operand:HI 0 "hard_reg_operand" "")
        (match_operand:HI 1 "nonimmediate_operand" ""))
        (match_operand:HI 1 "nonimmediate_operand" ""))
   (set (match_dup 0) (and:HI (match_dup 0)
   (set (match_dup 0) (and:HI (match_dup 0)
                              (match_operand:HI 2 "const_int_operand" "")))
                              (match_operand:HI 2 "const_int_operand" "")))
   (set (match_dup 1) (match_dup 0))]
   (set (match_dup 1) (match_dup 0))]
  "(TARGET_M6812 || m68hc11_indirect_p (operands[1], HImode))
  "(TARGET_M6812 || m68hc11_indirect_p (operands[1], HImode))
   && (GET_CODE (operands[1]) != MEM || !auto_inc_p (XEXP (operands[1], 0)))
   && (GET_CODE (operands[1]) != MEM || !auto_inc_p (XEXP (operands[1], 0)))
   && peep2_reg_dead_p (3, operands[0])"
   && peep2_reg_dead_p (3, operands[0])"
  [(set (match_dup 1) (and:HI (match_dup 1) (match_dup 2)))]
  [(set (match_dup 1) (and:HI (match_dup 1) (match_dup 2)))]
  "")
  "")
;;--------------------------------------------------------------------
;;--------------------------------------------------------------------
;;- Compare peephole2
;;- Compare peephole2
;;--------------------------------------------------------------------
;;--------------------------------------------------------------------
(define_peephole2
(define_peephole2
  [(set (match_operand:HI 0 "hard_reg_operand" "")
  [(set (match_operand:HI 0 "hard_reg_operand" "")
        (match_operand:HI 1 "hard_reg_operand" ""))
        (match_operand:HI 1 "hard_reg_operand" ""))
   (set (match_dup 1) (plus:HI (match_dup 1)
   (set (match_dup 1) (plus:HI (match_dup 1)
                               (match_operand:HI 2 "const_int_operand" "")))
                               (match_operand:HI 2 "const_int_operand" "")))
   (set (cc0) (match_dup 0))]
   (set (cc0) (match_dup 0))]
  "peep2_reg_dead_p (3, operands[0]) && !Z_REG_P (operands[1])"
  "peep2_reg_dead_p (3, operands[0]) && !Z_REG_P (operands[1])"
  [(set (match_dup 1) (plus:HI (match_dup 1) (match_dup 2)))
  [(set (match_dup 1) (plus:HI (match_dup 1) (match_dup 2)))
   (set (cc0) (compare (match_dup 1) (match_dup 2)))]
   (set (cc0) (compare (match_dup 1) (match_dup 2)))]
  "")
  "")
(define_peephole2
(define_peephole2
  [(set (match_operand:HI 0 "hard_reg_operand" "")
  [(set (match_operand:HI 0 "hard_reg_operand" "")
        (match_operand:HI 1 "hard_reg_operand" ""))
        (match_operand:HI 1 "hard_reg_operand" ""))
   (set (match_operand:HI 2 "hard_reg_operand" "")
   (set (match_operand:HI 2 "hard_reg_operand" "")
        (plus:HI (match_dup 2)
        (plus:HI (match_dup 2)
                 (match_operand:HI 3 "const_int_operand" "")))
                 (match_operand:HI 3 "const_int_operand" "")))
   (set (match_operand:HI 4 "memory_operand" "") (match_dup 2))
   (set (match_operand:HI 4 "memory_operand" "") (match_dup 2))
   (set (cc0) (match_operand:HI 5 "hard_reg_operand" ""))]
   (set (cc0) (match_operand:HI 5 "hard_reg_operand" ""))]
  "peep2_reg_dead_p (4, operands[5]) && !Z_REG_P (operands[2])
  "peep2_reg_dead_p (4, operands[5]) && !Z_REG_P (operands[2])
   && !reg_mentioned_p (operands[2], operands[4])
   && !reg_mentioned_p (operands[2], operands[4])
   && ((rtx_equal_p (operands[5], operands[0])
   && ((rtx_equal_p (operands[5], operands[0])
        && rtx_equal_p (operands[2], operands[1]))
        && rtx_equal_p (operands[2], operands[1]))
       || (rtx_equal_p (operands[5], operands[1])
       || (rtx_equal_p (operands[5], operands[1])
           && rtx_equal_p (operands[2], operands[0])))"
           && rtx_equal_p (operands[2], operands[0])))"
  [(set (match_dup 2) (match_dup 1))
  [(set (match_dup 2) (match_dup 1))
   (set (match_dup 2) (plus:HI (match_dup 2) (match_dup 3)))
   (set (match_dup 2) (plus:HI (match_dup 2) (match_dup 3)))
   (set (match_dup 4) (match_dup 2))
   (set (match_dup 4) (match_dup 2))
   (set (cc0) (compare (match_dup 2) (match_dup 3)))]
   (set (cc0) (compare (match_dup 2) (match_dup 3)))]
  "")
  "")
;;--------------------------------------------------------------------
;;--------------------------------------------------------------------
;;- Load peephole2
;;- Load peephole2
;;--------------------------------------------------------------------
;;--------------------------------------------------------------------
;;
;;
;; Optimize initialization of 2 hard regs from the same memory location
;; Optimize initialization of 2 hard regs from the same memory location
;; Since we can't copy easily X, Y and D to each other, load the 2 registers
;; Since we can't copy easily X, Y and D to each other, load the 2 registers
;; from the same memory location.
;; from the same memory location.
;;
;;
(define_peephole2
(define_peephole2
  [(set (match_operand:HI 0 "hard_reg_operand" "")
  [(set (match_operand:HI 0 "hard_reg_operand" "")
        (match_operand:HI 1 "memory_operand" ""))
        (match_operand:HI 1 "memory_operand" ""))
   (set (match_operand:HI 2 "hard_reg_operand" "") (match_dup 0))]
   (set (match_operand:HI 2 "hard_reg_operand" "") (match_dup 0))]
  "TARGET_M6811
  "TARGET_M6811
   && !side_effects_p (operands[1])
   && !side_effects_p (operands[1])
   && !reg_mentioned_p (operands[0], operands[1])"
   && !reg_mentioned_p (operands[0], operands[1])"
  [(set (match_dup 0) (match_dup 1))
  [(set (match_dup 0) (match_dup 1))
   (set (match_dup 2) (match_dup 1))]
   (set (match_dup 2) (match_dup 1))]
  "")
  "")
;; Replace "ldd #N; addd " with "ldd ; addd #N".
;; Replace "ldd #N; addd " with "ldd ; addd #N".
;;
;;
(define_peephole2
(define_peephole2
  [(set (match_operand:HI 0 "nonimmediate_operand" "") (const_int 0))
  [(set (match_operand:HI 0 "nonimmediate_operand" "") (const_int 0))
   (set (match_operand:HI 1 "nonimmediate_operand" "") (const_int 0))
   (set (match_operand:HI 1 "nonimmediate_operand" "") (const_int 0))
   (set (match_operand:HI 2 "nonimmediate_operand" "") (const_int 0))
   (set (match_operand:HI 2 "nonimmediate_operand" "") (const_int 0))
   (set (match_operand:HI 3 "nonimmediate_operand" "") (const_int 0))
   (set (match_operand:HI 3 "nonimmediate_operand" "") (const_int 0))
   (match_scratch:HI 4 "d")]
   (match_scratch:HI 4 "d")]
  ""
  ""
  [(set (match_dup 4) (const_int 0))
  [(set (match_dup 4) (const_int 0))
   (set (match_dup 0) (match_dup 4))
   (set (match_dup 0) (match_dup 4))
   (set (match_dup 1) (match_dup 4))
   (set (match_dup 1) (match_dup 4))
   (set (match_dup 2) (match_dup 4))
   (set (match_dup 2) (match_dup 4))
   (set (match_dup 3) (match_dup 4))]
   (set (match_dup 3) (match_dup 4))]
  "")
  "")
;;
;;
;; Replace "ldd #N; addd " with "ldd ; addd #N".
;; Replace "ldd #N; addd " with "ldd ; addd #N".
;;
;;
(define_peephole2
(define_peephole2
  [(set (match_operand:HI 0 "nonimmediate_operand" "") (const_int 0))
  [(set (match_operand:HI 0 "nonimmediate_operand" "") (const_int 0))
   (set (match_operand:HI 1 "nonimmediate_operand" "") (const_int 0))
   (set (match_operand:HI 1 "nonimmediate_operand" "") (const_int 0))
   (set (match_operand:HI 2 "nonimmediate_operand" "") (const_int 0))
   (set (match_operand:HI 2 "nonimmediate_operand" "") (const_int 0))
   (match_scratch:HI 3 "d")]
   (match_scratch:HI 3 "d")]
  ""
  ""
  [(set (match_dup 3) (const_int 0))
  [(set (match_dup 3) (const_int 0))
   (set (match_dup 0) (match_dup 3))
   (set (match_dup 0) (match_dup 3))
   (set (match_dup 1) (match_dup 3))
   (set (match_dup 1) (match_dup 3))
   (set (match_dup 2) (match_dup 3))]
   (set (match_dup 2) (match_dup 3))]
  "")
  "")
;;
;;
;; Replace "ldd #N; addd " with "ldd ; addd #N".
;; Replace "ldd #N; addd " with "ldd ; addd #N".
;;
;;
(define_peephole2
(define_peephole2
  [(set (match_operand:HI 0 "hard_reg_operand" "") (const_int 0))
  [(set (match_operand:HI 0 "hard_reg_operand" "") (const_int 0))
   (set (match_operand:HI 1 "push_operand" "") (match_dup 0))
   (set (match_operand:HI 1 "push_operand" "") (match_dup 0))
   (set (match_operand:HI 2 "push_operand" "") (match_dup 0))
   (set (match_operand:HI 2 "push_operand" "") (match_dup 0))
   (set (match_operand:HI 3 "push_operand" "") (match_dup 0))
   (set (match_operand:HI 3 "push_operand" "") (match_dup 0))
   (match_scratch:HI 4 "x")]
   (match_scratch:HI 4 "x")]
  "TARGET_M6811 && D_REG_P (operands[0]) && peep2_reg_dead_p (4, operands[0])"
  "TARGET_M6811 && D_REG_P (operands[0]) && peep2_reg_dead_p (4, operands[0])"
  [(set (match_dup 4) (const_int 0))
  [(set (match_dup 4) (const_int 0))
   (set (match_dup 1) (match_dup 4))
   (set (match_dup 1) (match_dup 4))
   (set (match_dup 2) (match_dup 4))
   (set (match_dup 2) (match_dup 4))
   (set (match_dup 3) (match_dup 4))]
   (set (match_dup 3) (match_dup 4))]
  "")
  "")
;;
;;
;; This peephole catches the address computations generated by the reload
;; This peephole catches the address computations generated by the reload
;; pass.
;; pass.
(define_peephole
(define_peephole
  [(set (match_operand:HI 0 "hard_reg_operand" "xy")
  [(set (match_operand:HI 0 "hard_reg_operand" "xy")
        (match_operand:HI 1 "const_int_operand" ""))
        (match_operand:HI 1 "const_int_operand" ""))
   (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
   (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
              (set (match_dup 0) (reg:HI D_REGNUM))])
              (set (match_dup 0) (reg:HI D_REGNUM))])
   (set (reg:HI D_REGNUM)
   (set (reg:HI D_REGNUM)
        (plus (reg:HI D_REGNUM)
        (plus (reg:HI D_REGNUM)
              (match_operand:HI 2 "general_operand" "")))
              (match_operand:HI 2 "general_operand" "")))
   (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
   (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
              (set (match_dup 0) (reg:HI D_REGNUM))])]
              (set (match_dup 0) (reg:HI D_REGNUM))])]
  "(INTVAL (operands[1]) & 0x0FF) == 0"
  "(INTVAL (operands[1]) & 0x0FF) == 0"
  "*
  "*
{
{
  int value_loaded = 1;
  int value_loaded = 1;
  if (X_REG_P (operands[0]) || SP_REG_P (operands[2]))
  if (X_REG_P (operands[0]) || SP_REG_P (operands[2]))
    {
    {
      rtx ops[2];
      rtx ops[2];
      ops[0] = operands[0];
      ops[0] = operands[0];
      ops[1] = operands[2];
      ops[1] = operands[2];
      m68hc11_gen_movhi (insn, ops);
      m68hc11_gen_movhi (insn, ops);
      output_asm_insn (\"xgd%0\", operands);
      output_asm_insn (\"xgd%0\", operands);
    }
    }
  else if (Y_REG_P (operands[0]))
  else if (Y_REG_P (operands[0]))
    {
    {
      if (reg_mentioned_p (iy_reg, operands[2]))
      if (reg_mentioned_p (iy_reg, operands[2]))
        output_asm_insn (\"ldy\\t%2\", operands);
        output_asm_insn (\"ldy\\t%2\", operands);
      else
      else
        value_loaded = 0;
        value_loaded = 0;
      output_asm_insn (\"xgdy\", operands);
      output_asm_insn (\"xgdy\", operands);
    }
    }
  else
  else
    {
    {
      output_asm_insn (\"ldd\\t%2\", operands);
      output_asm_insn (\"ldd\\t%2\", operands);
    }
    }
  if (value_loaded == 0)
  if (value_loaded == 0)
    output_asm_insn (\"ldd\\t%2\", operands);
    output_asm_insn (\"ldd\\t%2\", operands);
  if ((INTVAL (operands[1]) & 0x0ff00) == 0x100)
  if ((INTVAL (operands[1]) & 0x0ff00) == 0x100)
    output_asm_insn (\"inca\", operands);
    output_asm_insn (\"inca\", operands);
  else if ((INTVAL (operands[1]) & 0x0ff00) == 0xff00)
  else if ((INTVAL (operands[1]) & 0x0ff00) == 0xff00)
    output_asm_insn (\"deca\", operands);
    output_asm_insn (\"deca\", operands);
  else if (INTVAL (operands[1]) != 0)
  else if (INTVAL (operands[1]) != 0)
    output_asm_insn (\"adda\\t%h1\", operands);
    output_asm_insn (\"adda\\t%h1\", operands);
  if (X_REG_P (operands[0]))
  if (X_REG_P (operands[0]))
    return \"xgdx\";
    return \"xgdx\";
  else if (Y_REG_P (operands[0]))
  else if (Y_REG_P (operands[0]))
    return \"xgdy\";
    return \"xgdy\";
  else
  else
    return \"\";
    return \"\";
}
}
")
")
(define_peephole
(define_peephole
  [(set (match_operand:HI 0 "hard_reg_operand" "h")
  [(set (match_operand:HI 0 "hard_reg_operand" "h")
        (match_operand:HI 1 "non_push_operand" "g"))
        (match_operand:HI 1 "non_push_operand" "g"))
   (set (match_operand:HI 2 "hard_reg_operand" "h")
   (set (match_operand:HI 2 "hard_reg_operand" "h")
        (match_dup 0))]
        (match_dup 0))]
  "find_regno_note (insn, REG_DEAD, REGNO (operands[0]))
  "find_regno_note (insn, REG_DEAD, REGNO (operands[0]))
   && !S_REG_P (operands[2])"
   && !S_REG_P (operands[2])"
  "*
  "*
{
{
  rtx ops[2];
  rtx ops[2];
  ops[0] = operands[2];
  ops[0] = operands[2];
  ops[1] = operands[1];
  ops[1] = operands[1];
  m68hc11_gen_movhi (insn, ops);
  m68hc11_gen_movhi (insn, ops);
  return \"\";
  return \"\";
}
}
")
")
(define_peephole
(define_peephole
  [(set (match_operand:HI 0 "hard_reg_operand" "h")
  [(set (match_operand:HI 0 "hard_reg_operand" "h")
        (match_operand:HI 1 "hard_reg_operand" "h"))
        (match_operand:HI 1 "hard_reg_operand" "h"))
   (set (match_operand:HI 2 "non_push_operand" "g")
   (set (match_operand:HI 2 "non_push_operand" "g")
        (match_dup 0))]
        (match_dup 0))]
  "find_regno_note (insn, REG_DEAD, REGNO (operands[0]))
  "find_regno_note (insn, REG_DEAD, REGNO (operands[0]))
   && !S_REG_P (operands[2])"
   && !S_REG_P (operands[2])"
  "*
  "*
{
{
  rtx ops[2];
  rtx ops[2];
  ops[0] = operands[2];
  ops[0] = operands[2];
  ops[1] = operands[1];
  ops[1] = operands[1];
  m68hc11_gen_movhi (insn, ops);
  m68hc11_gen_movhi (insn, ops);
  return \"\";
  return \"\";
}
}
")
")
;;
;;
;; Catch a (set X/Y D) followed by a swap. In this form, D is dead after
;; Catch a (set X/Y D) followed by a swap. In this form, D is dead after
;; the set, so we don't need to emit anything. 'ins1' refers to the
;; the set, so we don't need to emit anything. 'ins1' refers to the
;; (set ...) insn.
;; (set ...) insn.
;;
;;
(define_peephole
(define_peephole
  [(set (match_operand:HI 0 "hard_reg_operand" "A") (reg:HI D_REGNUM))
  [(set (match_operand:HI 0 "hard_reg_operand" "A") (reg:HI D_REGNUM))
   (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
   (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
              (set (match_dup 0) (reg:HI D_REGNUM))])]
              (set (match_dup 0) (reg:HI D_REGNUM))])]
  "find_regno_note (ins1, REG_DEAD, HARD_D_REGNUM)"
  "find_regno_note (ins1, REG_DEAD, HARD_D_REGNUM)"
  "*
  "*
{
{
   cc_status = cc_prev_status;
   cc_status = cc_prev_status;
   return \"\";
   return \"\";
}
}
")
")
;; Same as above but due to some split, there may be a noop set
;; Same as above but due to some split, there may be a noop set
;; between the two.
;; between the two.
(define_peephole
(define_peephole
  [(set (match_operand:HI 0 "hard_reg_operand" "A") (reg:HI D_REGNUM))
  [(set (match_operand:HI 0 "hard_reg_operand" "A") (reg:HI D_REGNUM))
   (set (match_dup 0) (match_dup 0))
   (set (match_dup 0) (match_dup 0))
   (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
   (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
              (set (match_dup 0) (reg:HI D_REGNUM))])]
              (set (match_dup 0) (reg:HI D_REGNUM))])]
  "find_regno_note (ins1, REG_DEAD, HARD_D_REGNUM)"
  "find_regno_note (ins1, REG_DEAD, HARD_D_REGNUM)"
  "*
  "*
{
{
   cc_status = cc_prev_status;
   cc_status = cc_prev_status;
   return \"\";
   return \"\";
}
}
")
")
;;
;;
;; Catch a (set X/Y D) followed by an xgdx/xgdy. D is not dead
;; Catch a (set X/Y D) followed by an xgdx/xgdy. D is not dead
;; and we must, at least, setup X/Y with value of D.
;; and we must, at least, setup X/Y with value of D.
;;
;;
(define_peephole
(define_peephole
  [(set (match_operand:HI 0 "hard_reg_operand" "A") (reg:HI D_REGNUM))
  [(set (match_operand:HI 0 "hard_reg_operand" "A") (reg:HI D_REGNUM))
   (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
   (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
              (set (match_dup 0) (reg:HI D_REGNUM))])]
              (set (match_dup 0) (reg:HI D_REGNUM))])]
  ""
  ""
  "*
  "*
{
{
  rtx ops[2];
  rtx ops[2];
  ops[0] = operands[0];
  ops[0] = operands[0];
  ops[1] = gen_rtx_REG (HImode, HARD_D_REGNUM);
  ops[1] = gen_rtx_REG (HImode, HARD_D_REGNUM);
  m68hc11_gen_movhi (insn, ops);
  m68hc11_gen_movhi (insn, ops);
  return \"\";
  return \"\";
}
}
")
")
;;;
;;;
;;; Catch an xgdx/xgdy followed by a (set D X/Y). If X/Y is dead, we don't
;;; Catch an xgdx/xgdy followed by a (set D X/Y). If X/Y is dead, we don't
;;; need to emit anything. Otherwise, we just need a copy of D to X/Y.
;;; need to emit anything. Otherwise, we just need a copy of D to X/Y.
;;;
;;;
(define_peephole
(define_peephole
  [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A"))
  [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A"))
              (set (match_dup 0) (reg:HI D_REGNUM))])
              (set (match_dup 0) (reg:HI D_REGNUM))])
   (set (reg:HI D_REGNUM) (match_dup 0))]
   (set (reg:HI D_REGNUM) (match_dup 0))]
  "find_regno_note (insn, REG_DEAD, REGNO (operands[0]))"
  "find_regno_note (insn, REG_DEAD, REGNO (operands[0]))"
  "*
  "*
{
{
  cc_status = cc_prev_status;
  cc_status = cc_prev_status;
  return \"\";
  return \"\";
}
}
")
")
;;;
;;;
;;; Catch an xgdx/xgdy followed by a (set D X/Y). If X/Y is dead, we don't
;;; Catch an xgdx/xgdy followed by a (set D X/Y). If X/Y is dead, we don't
;;; need to emit anything. Otherwise, we just need a copy of D to X/Y.
;;; need to emit anything. Otherwise, we just need a copy of D to X/Y.
;;;
;;;
(define_peephole
(define_peephole
  [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A"))
  [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A"))
              (set (match_dup 0) (reg:HI D_REGNUM))])
              (set (match_dup 0) (reg:HI D_REGNUM))])
   (set (reg:QI D_REGNUM) (match_operand:QI 1 "hard_reg_operand" "A"))]
   (set (reg:QI D_REGNUM) (match_operand:QI 1 "hard_reg_operand" "A"))]
  "REGNO (operands[0]) == REGNO (operands[1])
  "REGNO (operands[0]) == REGNO (operands[1])
   && find_regno_note (insn, REG_DEAD, REGNO (operands[0]))"
   && find_regno_note (insn, REG_DEAD, REGNO (operands[0]))"
  "*
  "*
{
{
  cc_status = cc_prev_status;
  cc_status = cc_prev_status;
  return \"\";
  return \"\";
}
}
")
")
;;;
;;;
;;; Catch an xgdx/xgdy followed by a (set D X/Y). If X/Y is dead, we don't
;;; Catch an xgdx/xgdy followed by a (set D X/Y). If X/Y is dead, we don't
;;; need to emit anything. Otherwise, we just need a copy of D to X/Y.
;;; need to emit anything. Otherwise, we just need a copy of D to X/Y.
;;;
;;;
(define_peephole
(define_peephole
  [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A"))
  [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A"))
              (set (match_dup 0) (reg:HI D_REGNUM))])
              (set (match_dup 0) (reg:HI D_REGNUM))])
   (set (reg:HI D_REGNUM) (match_dup 0))]
   (set (reg:HI D_REGNUM) (match_dup 0))]
  ""
  ""
  "*
  "*
{
{
  rtx ops[2];
  rtx ops[2];
  ops[0] = operands[0];
  ops[0] = operands[0];
  ops[1] = gen_rtx_REG (HImode, HARD_D_REGNUM);
  ops[1] = gen_rtx_REG (HImode, HARD_D_REGNUM);
  m68hc11_gen_movhi (insn, ops);
  m68hc11_gen_movhi (insn, ops);
  return \"\";
  return \"\";
}
}
")
")
;;;
;;;
;;; Same peephole with a QI set.  The copy is made as 16-bit to comply
;;; Same peephole with a QI set.  The copy is made as 16-bit to comply
;;; with the xgdx.
;;; with the xgdx.
;;;
;;;
(define_peephole
(define_peephole
  [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A"))
  [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A"))
              (set (match_dup 0) (reg:HI D_REGNUM))])
              (set (match_dup 0) (reg:HI D_REGNUM))])
   (set (reg:QI D_REGNUM) (match_operand:QI 1 "hard_reg_operand" "A"))]
   (set (reg:QI D_REGNUM) (match_operand:QI 1 "hard_reg_operand" "A"))]
  "REGNO (operands[0]) == REGNO (operands[1])"
  "REGNO (operands[0]) == REGNO (operands[1])"
  "*
  "*
{
{
  rtx ops[2];
  rtx ops[2];
  ops[0] = operands[0];
  ops[0] = operands[0];
  ops[1] = gen_rtx_REG (HImode, HARD_D_REGNUM);
  ops[1] = gen_rtx_REG (HImode, HARD_D_REGNUM);
  m68hc11_gen_movhi (insn, ops);
  m68hc11_gen_movhi (insn, ops);
  return \"\";
  return \"\";
}
}
")
")
;;;
;;;
;;; Catch two consecutive xgdx or xgdy, emit nothing.
;;; Catch two consecutive xgdx or xgdy, emit nothing.
;;;
;;;
(define_peephole
(define_peephole
  [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A"))
  [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A"))
              (set (match_dup 0) (reg:HI D_REGNUM))])
              (set (match_dup 0) (reg:HI D_REGNUM))])
   (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
   (parallel [(set (reg:HI D_REGNUM) (match_dup 0))
              (set (match_dup 0) (reg:HI D_REGNUM))])]
              (set (match_dup 0) (reg:HI D_REGNUM))])]
  ""
  ""
  "*
  "*
{
{
  cc_status = cc_prev_status;
  cc_status = cc_prev_status;
  return \"\";
  return \"\";
}
}
")
")
(define_peephole
(define_peephole
  [(set (match_operand:HI 0 "hard_reg_operand" "")
  [(set (match_operand:HI 0 "hard_reg_operand" "")
        (match_operand:HI 1 "stack_register_operand" ""))
        (match_operand:HI 1 "stack_register_operand" ""))
   (set (match_operand:HI 2 "hard_reg_operand" "")
   (set (match_operand:HI 2 "hard_reg_operand" "")
        (match_operand:HI 3 "memory_operand" "m"))
        (match_operand:HI 3 "memory_operand" "m"))
   (set (match_dup 0)
   (set (match_dup 0)
        (match_operand:HI 4 "memory_operand" "m"))]
        (match_operand:HI 4 "memory_operand" "m"))]
  "IS_STACK_POP (operands[4])
  "IS_STACK_POP (operands[4])
   && (GET_CODE (operands[3]) == MEM &&
   && (GET_CODE (operands[3]) == MEM &&
       rtx_equal_p (operands[0], XEXP (operands[3], 0)))"
       rtx_equal_p (operands[0], XEXP (operands[3], 0)))"
  "*
  "*
{
{
  rtx ops[2];
  rtx ops[2];
  ops[0] = operands[2];
  ops[0] = operands[2];
  ops[1] = gen_rtx_MEM (HImode,
  ops[1] = gen_rtx_MEM (HImode,
                    gen_rtx_POST_INC (HImode, stack_pointer_rtx));
                    gen_rtx_POST_INC (HImode, stack_pointer_rtx));
  m68hc11_gen_movhi (insn, ops);
  m68hc11_gen_movhi (insn, ops);
  return \"\";
  return \"\";
}
}
")
")
;;
;;
;; Catch (d = -1) (d = d + sp) to avoid 2 adjust of SP.
;; Catch (d = -1) (d = d + sp) to avoid 2 adjust of SP.
;;
;;
(define_peephole
(define_peephole
  [(set (match_operand:HI 0 "hard_reg_operand" "dA") (const_int -1))
  [(set (match_operand:HI 0 "hard_reg_operand" "dA") (const_int -1))
   (set (match_dup 0) (plus:HI (match_dup 0) (reg:HI SP_REGNUM)))]
   (set (match_dup 0) (plus:HI (match_dup 0) (reg:HI SP_REGNUM)))]
  "TARGET_M6811"
  "TARGET_M6811"
  "*
  "*
{
{
  return \"sts\\t%t0\\n\\tld%0\\t%t0\";
  return \"sts\\t%t0\\n\\tld%0\\t%t0\";
}
}
")
")
(define_peephole
(define_peephole
  [(set (match_operand:HI 0 "hard_reg_operand" "")
  [(set (match_operand:HI 0 "hard_reg_operand" "")
        (match_operand:HI 1 "memory_operand" ""))
        (match_operand:HI 1 "memory_operand" ""))
   (set (match_operand:HI 2 "hard_reg_operand" "") (match_dup 0))]
   (set (match_operand:HI 2 "hard_reg_operand" "") (match_dup 0))]
  "TARGET_M6811
  "TARGET_M6811
   && !side_effects_p (operands[1])
   && !side_effects_p (operands[1])
   && !reg_mentioned_p (operands[0], operands[1])"
   && !reg_mentioned_p (operands[0], operands[1])"
  "*
  "*
{
{
  rtx ops[2];
  rtx ops[2];
  ops[0] = operands[0];
  ops[0] = operands[0];
  ops[1] = operands[1];
  ops[1] = operands[1];
  m68hc11_gen_movhi (insn, ops);
  m68hc11_gen_movhi (insn, ops);
  ops[0] = operands[2];
  ops[0] = operands[2];
  m68hc11_gen_movhi (insn, ops);
  m68hc11_gen_movhi (insn, ops);
  return \"\";
  return \"\";
}")
}")
;; Peephole for Z register replacement.
;; Peephole for Z register replacement.
;; Avoid to use _.tmp register when comparing D and X if we can compare
;; Avoid to use _.tmp register when comparing D and X if we can compare
;; with soft register
;; with soft register
(define_peephole
(define_peephole
  [(set (match_operand:HI 0 "hard_reg_operand" "") (reg:HI SOFT_XY_REGNUM))
  [(set (match_operand:HI 0 "hard_reg_operand" "") (reg:HI SOFT_XY_REGNUM))
   (set (reg:HI SOFT_TMP_REGNUM) (match_dup 0))
   (set (reg:HI SOFT_TMP_REGNUM) (match_dup 0))
   (set (cc0) (compare (match_operand:HI 2 "hard_reg_operand" "")
   (set (cc0) (compare (match_operand:HI 2 "hard_reg_operand" "")
                       (reg:HI SOFT_TMP_REGNUM)))]
                       (reg:HI SOFT_TMP_REGNUM)))]
  "X_REG_P (operands[0]) || Y_REG_P (operands[0])"
  "X_REG_P (operands[0]) || Y_REG_P (operands[0])"
  "*
  "*
{
{
  rtx ops[2];
  rtx ops[2];
  ops[0] = operands[0];
  ops[0] = operands[0];
  ops[1] = operands[1];
  ops[1] = operands[1];
  m68hc11_gen_movhi (insn, ops);
  m68hc11_gen_movhi (insn, ops);
  return \"cp%2\\t%1\";
  return \"cp%2\\t%1\";
}")
}")
 
 

powered by: WebSVN 2.1.0

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