OSDN Git Service

* config/m68hc11/m68hc11.c (m68hc11_symbolic_p): New function.
authorciceron <ciceron@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 15 Mar 2002 22:04:49 +0000 (22:04 +0000)
committerciceron <ciceron@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 15 Mar 2002 22:04:49 +0000 (22:04 +0000)
(m68hc11_indirect_p): New function.
(m68hc11_override_options): Must set MASK_NO_DIRECT_MODE for 68HC12.
(m68hc11_gen_highpart): Use TARGET_NO_DIRECT_MODE instead of
TARGET_M6812.
(asm_print_register): Likewise.
* config/m68hc11/m68hc11-protos.h (m68hc11_symbolic_p): Declare.
(m68hc11_indirect_p): Declare.
* config/m68hc11/m68hc11.h (EXTRA_CONSTRAINT): New constraint 'R', 'Q'.
(TARGET_NO_DIRECT_MODE, TARGET_RELAX): New.
(TARGET_SWITCHES): New option -mrelax.
* config/m68hc11/m68hc11.md ("andsi3"): Allow soft register for
destination.
("iorsi3", "xorsi3"): Likewise.
("andhi3", "andqi3", "iorhi3", "iorqi3"): Use a define_expand.
("*andhi3_mem"): New to handle destination in memory with bclr
and a scratch register.
("*andqi3_mem", "*iorhi3_mem", "*iorqi3_mem"): Likewise.
("*andhi3_const"): New when operand2 is constant.
("*andqi3_const", "*iorhi3_const", "*iorqi3_const"): Likewise.
("*andhi3_gen"): Cleanup of the old "andhi3".
("*andqi3_gen", "*iorhi3_gen", "*iorqi3_gen"): Likewise.
("xorqi3"): Update constraints.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@50843 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/m68hc11/m68hc11-protos.h
gcc/config/m68hc11/m68hc11.c
gcc/config/m68hc11/m68hc11.h
gcc/config/m68hc11/m68hc11.md

index a3619d8..2aa5993 100644 (file)
@@ -1,5 +1,31 @@
 2002-03-15  Stephane Carrez  <Stephane.Carrez@worldnet.fr>
 
+       * config/m68hc11/m68hc11.c (m68hc11_symbolic_p): New function.
+       (m68hc11_indirect_p): New function.
+       (m68hc11_override_options): Must set MASK_NO_DIRECT_MODE for 68HC12.
+       (m68hc11_gen_highpart): Use TARGET_NO_DIRECT_MODE instead of
+       TARGET_M6812.
+       (asm_print_register): Likewise.
+       * config/m68hc11/m68hc11-protos.h (m68hc11_symbolic_p): Declare.
+       (m68hc11_indirect_p): Declare.
+       * config/m68hc11/m68hc11.h (EXTRA_CONSTRAINT): New constraint 'R', 'Q'.
+       (TARGET_NO_DIRECT_MODE, TARGET_RELAX): New.
+       (TARGET_SWITCHES): New option -mrelax.
+       * config/m68hc11/m68hc11.md ("andsi3"): Allow soft register for
+       destination.
+       ("iorsi3", "xorsi3"): Likewise.
+       ("andhi3", "andqi3", "iorhi3", "iorqi3"): Use a define_expand.
+       ("*andhi3_mem"): New to handle destination in memory with bclr
+       and a scratch register.
+       ("*andqi3_mem", "*iorhi3_mem", "*iorqi3_mem"): Likewise.
+       ("*andhi3_const"): New when operand2 is constant.
+       ("*andqi3_const", "*iorhi3_const", "*iorqi3_const"): Likewise.
+       ("*andhi3_gen"): Cleanup of the old "andhi3".
+       ("*andqi3_gen", "*iorhi3_gen", "*iorqi3_gen"): Likewise.
+       ("xorqi3"): Update constraints.
+
+2002-03-15  Stephane Carrez  <Stephane.Carrez@worldnet.fr>
+
        * config/m68hc11/m68hc11.c (m68hc11_small_indexed_indirect_p): Look
        for reg_equiv_memory_loc when the operand is a register that does
        not get a hard register (stack location).
index e974348..27358b7 100644 (file)
@@ -106,6 +106,8 @@ extern void m68hc11_emit_libcall PARAMS((const char*, enum rtx_code,
                                          enum machine_mode, enum machine_mode,
                                          int, rtx*));
 extern int m68hc11_small_indexed_indirect_p PARAMS((rtx, enum machine_mode));
+extern int m68hc11_symbolic_p PARAMS((rtx, enum machine_mode));
+extern int m68hc11_indirect_p PARAMS((rtx, enum machine_mode));
 extern int go_if_legitimate_address2 PARAMS((rtx, enum machine_mode, int));
 
 extern int reg_or_indexed_operand PARAMS((rtx,enum machine_mode));
index bcaeae6..041b596 100644 (file)
@@ -276,6 +276,7 @@ m68hc11_override_options ()
       m68hc11_sp_correction = 0;
       m68hc11_tmp_regs_class = TMP_REGS;
       target_flags &= ~MASK_M6811;
+      target_flags |= MASK_NO_DIRECT_MODE;
       if (m68hc11_soft_reg_count == 0)
        m68hc11_soft_reg_count = "2";
     }
@@ -927,6 +928,42 @@ reg_or_some_mem_operand (operand, mode)
 }
 
 int
+m68hc11_symbolic_p (operand, mode)
+     rtx operand;
+     enum machine_mode mode;
+{
+  if (GET_CODE (operand) == MEM)
+    {
+      rtx op = XEXP (operand, 0);
+
+      if (symbolic_memory_operand (op, mode))
+       return 1;
+    }
+  return 0;
+}
+
+int
+m68hc11_indirect_p (operand, mode)
+     rtx operand;
+     enum machine_mode mode;
+{
+  if (GET_CODE (operand) == MEM)
+    {
+      rtx op = XEXP (operand, 0);
+
+      if (symbolic_memory_operand (op, mode))
+       return 0;
+
+      if (reload_in_progress)
+        return 1;
+
+      operand = XEXP (operand, 0);
+      return register_indirect_p (operand, mode, reload_completed);
+    }
+  return 0;
+}
+
+int
 stack_register_operand (operand, mode)
      rtx operand;
      enum machine_mode mode ATTRIBUTE_UNUSED;
@@ -1950,8 +1987,9 @@ m68hc11_gen_highpart (mode, x)
     {
       int pos;
 
-      /* For 68HC12, avoid the '*' for direct addressing mode.  */
-      pos = TARGET_M6812 ? 1 : 0;
+      /* Avoid the '*' for direct addressing mode when this
+         addressing mode is disabled.  */
+      pos = TARGET_NO_DIRECT_MODE ? 1 : 0;
       return gen_rtx (MEM, QImode,
                      gen_rtx (SYMBOL_REF, Pmode,
                               &reg_names[REGNO (x)][pos]));
@@ -2079,7 +2117,7 @@ asm_print_register (file, regno)
 {
   const char *name = reg_names[regno];
 
-  if (TARGET_M6812 && name[0] == '*')
+  if (TARGET_NO_DIRECT_MODE && name[0] == '*')
     name++;
 
   asm_fprintf (file, "%s", name);
index ee2a805..865e2eb 100644 (file)
@@ -118,12 +118,15 @@ extern short *reg_renumber;       /* def in local_alloc.c */
 #define MASK_AUTO_INC_DEC       0004
 #define MASK_M6811              0010
 #define MASK_M6812              0020
+#define MASK_NO_DIRECT_MODE     0040
 
 #define TARGET_OP_TIME         (optimize && optimize_size == 0)
 #define TARGET_SHORT            (target_flags & MASK_SHORT)
 #define TARGET_M6811            (target_flags & MASK_M6811)
 #define TARGET_M6812            (target_flags & MASK_M6812)
 #define TARGET_AUTO_INC_DEC     (target_flags & MASK_AUTO_INC_DEC)
+#define TARGET_NO_DIRECT_MODE   (target_flags & MASK_NO_DIRECT_MODE)
+#define TARGET_RELAX            (TARGET_NO_DIRECT_MODE)
 
 /* Default target_flags if no switches specified.  */
 #ifndef TARGET_DEFAULT
@@ -156,6 +159,8 @@ extern short *reg_renumber; /* def in local_alloc.c */
     N_("Auto pre/post decrement increment allowed")},          \
   { "noauto-incdec", - MASK_AUTO_INC_DEC,                      \
     N_("Auto pre/post decrement increment not allowed")},      \
+  { "relax", MASK_NO_DIRECT_MODE,                               \
+    N_("Do not use direct addressing mode for soft registers")},\
   { "68hc11", MASK_M6811,                                      \
     N_("Compile for a 68HC11")},                               \
   { "68hc12", MASK_M6812,                                      \
@@ -830,7 +835,9 @@ extern enum reg_class m68hc11_tmp_regs_class;
 /* 'U' represents certain kind of memory indexed operand for 68HC12.
    and any memory operand for 68HC11.  */
 #define EXTRA_CONSTRAINT(OP, C)                         \
-((C) == 'U' ? m68hc11_small_indexed_indirect_p (OP, GET_MODE (OP)) : 0)
+((C) == 'U' ? m68hc11_small_indexed_indirect_p (OP, GET_MODE (OP)) \
+ : (C) == 'Q' ? m68hc11_symbolic_p (OP, GET_MODE (OP)) \
+ : (C) == 'R' ? m68hc11_indirect_p (OP, GET_MODE (OP)) : 0)
 
 
 \f
index 7f13e69..1871d47 100644 (file)
 ;;
 ;; Other constraints:
 ;;
-;; T    an operand that can be accessed with 68HC1X direct addressing
-;;      mode.  For 68HC11 this includes the pseudo soft registers and
-;;      any memory operand that is a direct addressing (.page0).
+;; Q    an operand which is in memory but whose address is constant
+;;      (ie, a (MEM (SYMBOL_REF x))).  This constraint is used by
+;;      bset/bclr instructions together with linker relaxation.  The
+;;      operand can be translated to a page0 addressing mode if the
+;;      symbol address is in page0 (0..255).
+;;
+;; R    an operand which is in memory and whose address is expressed
+;;      with 68HC11/68HC12 indexed addressing mode.  In general this
+;;      is any valid (MEM) except a (MEM (SYMBOL_REF x)).
+;;
+;; 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
+;;      used by 68HC12 movb/movw instructions since they do not accept
+;;      the full 16-bit offset range (as other insn do).
 ;;
 ;;
 ;; Immediate integer operand constraints:
 ;;             some values in bad registers. 
 ;;
 ;; 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
-;;     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.
 ;;
 ;;
 ;;   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'
-;;   register directory (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
 ;;   because flow/cse is not aware that D is composed of {a, b}.
 ;;
   "#")
 
 (define_insn "andsi3"
-  [(set (match_operand:SI 0 "register_operand" "=D")
-       (and:SI (match_operand:SI 1 "register_operand" "%0")
-               (match_operand:SI 2 "general_operand" "Dimu")))]
+  [(set (match_operand:SI 0 "register_operand" "=D,!u")
+       (and:SI (match_operand:SI 1 "register_operand" "%0,0")
+               (match_operand:SI 2 "general_operand" "Dimu,imu")))
+   (clobber (match_scratch:HI 3 "=X,d"))]
   ""
   "#")
 
-(define_insn "andhi3"
-  [(set (match_operand:HI 0 "register_operand" "=d,!u,d,!*A")
-       (and:HI (match_operand:HI 1 "register_operand" "%0,0,0,0")
-               (match_operand:HI 2 "general_operand" "i,i,!um*A,!ium*A")))]
+(define_expand "andhi3"
+  [(set (match_operand:HI 0 "register_operand" "")
+       (and:HI (match_operand:HI 1 "register_operand" "")
+               (match_operand:HI 2 "general_operand" "")))]
   ""
+  "")
+
+(define_insn "*andhi3_mem"
+  [(set (match_operand:HI 0 "memory_operand" "=Q,R")
+       (and:HI (match_dup 0)
+               (match_operand:HI 1 "immediate_operand" "i,i")))
+   (clobber (match_scratch:HI 2 "=xy,X"))]
+  "TARGET_RELAX && !TARGET_M6812"
   "*
 {
-  if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
-    return \"#\";
+  int val = INTVAL (operands[1]) & 0x0FFFF;
 
-  if (GET_CODE (operands[2]) == CONST_INT)
+  if (val == 0x0ffff)
     {
-      int val = INTVAL (operands[2]) & 0x0FFFF;
-      char lowpart_zero     = 0;
-      char lowpart_unknown  = 0;
-      char highpart_zero    = 0;
-      char highpart_unknown = 0;
+      cc_status = cc_prev_status;
+      return \"\";
+    }
 
-      if (val == 0xFFFF)
-       {
-         cc_status = cc_prev_status;
-         return \"\";
-       }
+  CC_STATUS_INIT;
 
-      /* First, try to clear the low and high part.
-        If that's possible, the second 'and' will give
-        the good status flags and we can avoid a tsthi.  */
-      if ((val & 0x0FF) == 0)
-       {
-          if (D_REG_P (operands[0]))
-           output_asm_insn (\"clrb\", operands);
-         else
-           output_asm_insn (\"clr\\t%b0\", operands);
-         lowpart_zero = 1;
-       }
-      if ((val & 0x0FF00) == 0)
-       {
-         if (D_REG_P (operands[0]))
-           output_asm_insn (\"clra\", operands);
-         else
-           output_asm_insn (\"clr\\t%h0\", operands);
-         highpart_zero = 1;
-       }
+  /* The bclr instruction uses an inverted mask.  */
+  operands[1] = gen_rtx (CONST_INT, VOIDmode, (~val) & 0x0FFFF);
 
-      if ((val & 0x0FF) == 0x0FF)
-        {
-         lowpart_unknown = 1;
-        }
-      else if ((val & 0x0FF) != 0 && !H_REG_P (operands[0]))
-        {
-         rtx ops[2];
+  /* When destination is a global variable, generate a .relax instruction
+     and load the address in the clobber register.  That load can be
+     eliminated by the linker if the address is in page0.  */
+  if (which_alternative == 0)
+    {
+      rtx ops[3];
 
-         ops[0] = operands[0];
-         ops[1] = gen_rtx (CONST_INT, VOIDmode, (~val) & 0x0FF);
-          output_asm_insn (\"bclr\\t%b0, %1\", ops);
-        }
-      else if ((val & 0x0FF) != 0)
-       {
-         output_asm_insn (\"andb\\t%b2\", operands);
-       }
+      ops[0] = operands[2];
+      ops[1] = XEXP (operands[0], 0);
+      ops[2] = gen_label_rtx ();
+      output_asm_insn (\".relax\\t%l2\", ops);
+      m68hc11_gen_movhi (insn, ops);
+      if ((val & 0x0FF) != 0x0FF)
+        output_asm_insn (\"bclr\\t1,%2, %b1\", operands);
 
-      if ((val & 0x0FF00) == 0x0FF00)
-       {
-         highpart_unknown = 1;
-       }
-      else if (((val & 0x0FF00) != 0) && !H_REG_P (operands[0]))
-        {
-         rtx ops[2];
+      if ((val & 0x0FF00) != 0x0FF00)
+        output_asm_insn (\"bclr\\t0,%2, %h1\", operands);
 
-         ops[0] = operands[0];
-         ops[1] = gen_rtx (CONST_INT, VOIDmode, ((~val) & 0x0FF00) >> 8);
-          output_asm_insn (\"bclr\\t%h0, %1\", ops);
-        }
-      else if ((val & 0x0FF00) != 0)
-       {
-         output_asm_insn (\"anda\\t%h2\", operands);
-       }
+      ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
+                                CODE_LABEL_NUMBER (ops[2]));
+      return \"\";
+    }
+
+  if ((val & 0x0FF) != 0x0FF)
+    output_asm_insn (\"bclr\\t%b0, %b1\", operands);
+
+  if ((val & 0x0FF00) != 0x0FF00)
+    output_asm_insn (\"bclr\\t%h0, %h1\", operands);
 
-      if (highpart_unknown || lowpart_unknown)
-        CC_STATUS_INIT;
-      else if (highpart_zero == 0 && lowpart_zero == 0)
-        CC_STATUS_INIT;
+  return \"\";
+}")
+
+(define_insn "*andhi3_const"
+  [(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")
+               (match_operand:HI 2 "const_int_operand" "")))]
+  ""
+  "*
+{
+  int val = INTVAL (operands[2]) & 0x0FFFF;
+  int lowpart_zero = 0;
+  int highpart_zero = 0;
+  int lowpart_unknown = 0;
+  int highpart_unknown = 0;
+
+  if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
+    return \"#\";
 
+  if (val == 0x0ffff)
+    {
+      cc_status = cc_prev_status;
       return \"\";
     }
 
+  /* First, try to clear the low and high part.
+     If that's possible, the second 'and' will give
+     the good status flags and we can avoid a tsthi.  */
+  if ((val & 0x0FF) == 0)
+    {
+      if (D_REG_P (operands[0]))
+       output_asm_insn (\"clrb\", operands);
+      else
+       output_asm_insn (\"clr\\t%b0\", operands);
+      lowpart_zero = 1;
+    }
+  if ((val & 0x0FF00) == 0)
+    {
+      if (D_REG_P (operands[0]))
+       output_asm_insn (\"clra\", operands);
+      else
+       output_asm_insn (\"clr\\t%h0\", operands);
+      highpart_zero = 1;
+    }
+
+  if ((val & 0x0FF) == 0x0FF)
+    {
+      lowpart_unknown = 1;
+    }
+  else if ((val & 0x0FF) != 0 && !H_REG_P (operands[0]))
+    {
+      rtx ops[2];
+
+      ops[0] = operands[0];
+      ops[1] = gen_rtx (CONST_INT, VOIDmode, (~val) & 0x0FF);
+      output_asm_insn (\"bclr\\t%b0, %1\", ops);
+    }
+  else if ((val & 0x0FF) != 0)
+    {
+      output_asm_insn (\"andb\\t%b2\", operands);
+    }
+
+  if ((val & 0x0FF00) == 0x0FF00)
+    {
+      highpart_unknown = 1;
+    }
+  else if (((val & 0x0FF00) != 0) && !H_REG_P (operands[0]))
+    {
+      rtx ops[2];
+
+      ops[0] = operands[0];
+      ops[1] = gen_rtx (CONST_INT, VOIDmode, ((~val) & 0x0FF00) >> 8);
+      output_asm_insn (\"bclr\\t%h0, %1\", ops);
+    }
+  else if ((val & 0x0FF00) != 0)
+    {
+      output_asm_insn (\"anda\\t%h2\", operands);
+    }
+
+  if (highpart_unknown || lowpart_unknown)
+     CC_STATUS_INIT;
+  else if (highpart_zero == 0 && lowpart_zero == 0)
+     CC_STATUS_INIT;
+
+  return \"\";
+}")
+
+(define_insn "*andhi3_gen"
+  [(set (match_operand:HI 0 "register_operand" "=d,d,!*A")
+       (and:HI (match_operand:HI 1 "register_operand" "%0,0,0")
+               (match_operand:HI 2 "general_operand" "mi,!u*A,!um*A")))]
+  ""
+  "*
+{
+  if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
+    return \"#\";
+
   CC_STATUS_INIT;
   return \"andb\\t%b2\\n\\tanda\\t%h2\";
 }")
 
-(define_insn "andqi3"
-  [(set (match_operand:QI 0 "register_operand" "=d,!u,d,d,?*A,?*A,!*q")
-        (and:QI (match_operand:QI 1 "register_operand" "%0,0,0,0,0,0,0")
-             (match_operand:QI 2 "general_operand" "i,i,!um,?*A,!ium,?*A*d,!ium*A")))]
+(define_expand "andqi3"
+  [(set (match_operand:QI 0 "register_operand" "")
+        (and:QI (match_operand:QI 1 "register_operand" "")
+                (match_operand:QI 2 "general_operand" "")))]
+  ""
+  "")
+
+(define_insn "*andqi3_mem"
+  [(set (match_operand:QI 0 "memory_operand" "=Q,R")
+       (and:QI (match_dup 0)
+               (match_operand:QI 1 "const_int_operand" "i,i")))
+   (clobber (match_scratch:HI 2 "=xy,X"))]
+  "TARGET_RELAX && !TARGET_M6812"
+  "*
+{
+  int val = INTVAL (operands[1]) & 0x0FF;
+
+  if (val == 0x0ff)
+    {
+      cc_status = cc_prev_status;
+      return \"\";
+    }
+
+  /* The bclr instruction uses an inverted mask.  */
+  operands[1] = gen_rtx (CONST_INT, VOIDmode, (~val) & 0x0FF);
+
+  /* When destination is a global variable, generate a .relax instruction
+     and load the address in the clobber register.  That load can be
+     eliminated by the linker if the address is in page0.  */
+  if (which_alternative == 0)
+    {
+      rtx ops[3];
+
+      ops[0] = operands[2];
+      ops[1] = XEXP (operands[0], 0);
+      ops[2] = gen_label_rtx ();
+      output_asm_insn (\".relax\\t%l2\", ops);
+      m68hc11_gen_movhi (insn, ops);
+      output_asm_insn (\"bclr\\t0,%2, %1\", operands);
+      ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
+                                CODE_LABEL_NUMBER (ops[2]));
+      return \"\";
+    }
+  return \"bclr\\t%b0, %1\";
+}")
+
+(define_insn "*andqi3_const"
+  [(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")
+               (match_operand:QI 2 "const_int_operand" "")))]
   ""
   "*
 {
+  int val = INTVAL (operands[2]) & 0x0FF;
+
   if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
     return \"#\";
 
-  if (GET_CODE (operands[2]) == CONST_INT)
+  if (val == 0x0ff)
     {
-      int val = INTVAL (operands[2]) & 0x0FF;
+      cc_status = cc_prev_status;
+      return \"\";
+    }
+  if (!H_REG_P (operands[0]))
+    {
+      rtx ops[2];
 
-      if (val == 0xFF)
-       {
-         cc_status = cc_prev_status;
-         return \"\";
-       }
-      if (val == 0)
-       {
-          if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
-           return \"clrb\";
-         else if (DA_REG_P (operands[0]))
-           return \"clra\";
-         else
-           return \"clr\\t%b0\";
-       }
-      if (!H_REG_P (operands[0]))
-        {
-          rtx ops[2];
-          ops[0] = operands[0];
-          ops[1] = gen_rtx (CONST_INT, VOIDmode, (~val) & 0x0FF);
-          output_asm_insn (\"bclr\\t%b0, %b1\", ops);
-          return \"\";
-        }
+      ops[0] = operands[0];
+      ops[1] = gen_rtx (CONST_INT, VOIDmode, (~val) & 0x0FF);
+      output_asm_insn (\"bclr\\t%b0, %b1\", ops);
+      return \"\";
     }
   if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
     return \"andb\\t%b2\";
     fatal_insn (\"Invalid operand in the instruction\", insn);
 }")
 
+(define_insn "*andqi3_gen"
+  [(set (match_operand:QI 0 "register_operand" "=d,d,d,?*A,?*A,!*q")
+        (and:QI (match_operand:QI 1 "register_operand" "%0,0,0,0,0,0")
+             (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]))
+    return \"#\";
+
+  if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
+    return \"andb\\t%b2\";
+  else if (DA_REG_P (operands[0]))
+    return \"anda\\t%b2\";
+  else
+    fatal_insn (\"Invalid operand in the instruction\", insn);
+}")
+
 ;;--------------------------------------------------------------------
 ;;- Bit set or instructions.
 ;;--------------------------------------------------------------------
   "#")
 
 (define_insn "iorsi3"
-  [(set (match_operand:SI 0 "register_operand" "=D")
-       (ior:SI (match_operand:SI 1 "register_operand" "%0")
-               (match_operand:SI 2 "general_operand" "Dimu")))]
+  [(set (match_operand:SI 0 "register_operand" "=D,!u")
+       (ior:SI (match_operand:SI 1 "register_operand" "%0,0")
+               (match_operand:SI 2 "general_operand" "Dimu,imu")))
+   (clobber (match_scratch:HI 3 "=X,d"))]
   ""
   "#")
 
-(define_insn "iorhi3"
-  [(set (match_operand:HI 0 "register_operand" "=d,!u,d,!*A")
-       (ior:HI (match_operand:HI 1 "register_operand" "%0,0,0,0")
-               (match_operand:HI 2 "general_operand" "i,i,!um*A,!ium*A")))]
+(define_expand "iorhi3"
+  [(set (match_operand:HI 0 "register_operand" "")
+       (ior:HI (match_operand:HI 1 "register_operand" "")
+               (match_operand:HI 2 "general_operand" "")))]
   ""
+  "")
+
+(define_insn "*iorhi3_mem"
+  [(set (match_operand:HI 0 "memory_operand" "=Q,R")
+       (ior:HI (match_dup 0)
+               (match_operand:HI 1 "const_int_operand" "")))
+   (clobber (match_scratch:HI 2 "=xy,X"))]
+  "TARGET_RELAX && !TARGET_M6812"
   "*
 {
-  if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
-    return \"#\";
+  int val = INTVAL (operands[1]) & 0x0FFFF;
 
-  if (GET_CODE (operands[2]) == CONST_INT)
+  if (val == 0)
     {
-      int val = INTVAL (operands[2]) & 0x0FFFF;
+      cc_status = cc_prev_status;
+      return \"\";
+    }
+  CC_STATUS_INIT;
+  if (which_alternative == 0)
+    {
+      rtx ops[3];
 
-      if (val == 0)
-       {
-         cc_status = cc_prev_status;
-         return \"\";
-       }
+      ops[0] = operands[2];
+      ops[1] = XEXP (operands[0], 0);
+      ops[2] = gen_label_rtx ();
+      output_asm_insn (\".relax\\t%l2\", ops);
+      m68hc11_gen_movhi (insn, ops);
       if ((val & 0x0FF) != 0)
-        {
-          if (!H_REG_P (operands[0]))
-            output_asm_insn (\"bset\\t%b0, %b2\", operands);
-          else
-           output_asm_insn (\"orab\\t%b2\", operands);
-       }
+        output_asm_insn (\"bset\\t1,%2, %b1\", operands);
 
       if ((val & 0x0FF00) != 0)
-        {
-          if (!H_REG_P (operands[0]))
-            output_asm_insn (\"bset\\t%h0, %h2\", operands);
-          else
-           output_asm_insn (\"oraa\\t%h2\", operands);
-       }
+        output_asm_insn (\"bset\\t0,%2, %h1\", operands);
+      ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
+                                CODE_LABEL_NUMBER (ops[2]));
+      return \"\";
+    }
 
-      CC_STATUS_INIT;
+  if ((val & 0x0FF) != 0)
+    output_asm_insn (\"bset\\t%b0, %b1\", operands);
+
+  if ((val & 0x0FF00) != 0)
+    output_asm_insn (\"bset\\t%h0, %h1\", operands);
+
+  return \"\";
+}")
+
+(define_insn "*iorhi3_const"
+  [(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")
+               (match_operand:HI 2 "const_int_operand" "")))]
+  ""
+  "*
+{
+  int val = INTVAL (operands[2]) & 0x0FFFF;
+
+  if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
+    return \"#\";
+
+  if (val == 0)
+    {
+      cc_status = cc_prev_status;
       return \"\";
     }
 
+  if ((val & 0x0FF) != 0)
+    {
+      if (!H_REG_P (operands[0]))
+        output_asm_insn (\"bset\\t%b0, %b2\", operands);
+      else
+       output_asm_insn (\"orab\\t%b2\", operands);
+    }
+
+  if ((val & 0x0FF00) != 0)
+    {
+      if (!H_REG_P (operands[0]))
+         output_asm_insn (\"bset\\t%h0, %h2\", operands);
+      else
+        output_asm_insn (\"oraa\\t%h2\", operands);
+    }
+
   CC_STATUS_INIT;
-  return \"orab\\t%b2\\n\\toraa\\t%h2\";
+  return \"\";
 }")
 
-(define_insn "iorqi3"
-  [(set (match_operand:QI 0 "register_operand" "=d,!u,d,d,?*A,?*A,!*q")
-       (ior:QI (match_operand:QI 1 "register_operand" "%0,0,0,0,0,0,0")
-            (match_operand:QI 2 "general_operand" "i,i,!um,!*A,!ium,?*A*d,!ium*A")))]
+(define_insn "*iorhi3_gen"
+  [(set (match_operand:HI 0 "register_operand" "=d,d,!*A")
+       (ior:HI (match_operand:HI 1 "register_operand" "%0,0,0")
+               (match_operand:HI 2 "general_operand" "mi,!u*A,!um*A")))]
   ""
   "*
 {
   if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
     return \"#\";
 
-  if (GET_CODE (operands[2]) == CONST_INT)
+  CC_STATUS_INIT;
+  return \"orab\\t%b2\\n\\toraa\\t%h2\";
+}")
+
+(define_expand "iorqi3"
+  [(set (match_operand:QI 0 "register_operand" "")
+       (ior:QI (match_operand:QI 1 "register_operand" "")
+               (match_operand:QI 2 "general_operand" "")))]
+  ""
+  "")
+
+(define_insn "*iorqi3_mem"
+  [(set (match_operand:QI 0 "memory_operand" "=Q,R")
+       (ior:QI (match_dup 0)
+               (match_operand:QI 1 "const_int_operand" "")))
+   (clobber (match_scratch:HI 2 "=xy,X"))]
+  "TARGET_RELAX && !TARGET_M6812"
+  "*
+{
+  int val = INTVAL (operands[1]) & 0x0FF;
+
+  if (val == 0)
     {
-      int val = INTVAL (operands[2]) & 0x0FF;
+      cc_status = cc_prev_status;
+      return \"\";
+    }
+  if (which_alternative == 0)
+    {
+      rtx ops[3];
 
-      if (val == 0)
-       {
-         cc_status = cc_prev_status;
-         return \"\";
-       }
-      if (!H_REG_P (operands[0]))
-        {
-          return \"bset\\t%b0, %2\";
-        }
+      ops[0] = operands[2];
+      ops[1] = XEXP (operands[0], 0);
+      ops[2] = gen_label_rtx ();
+      output_asm_insn (\".relax\\t%l2\", ops);
+      m68hc11_gen_movhi (insn, ops);
+      output_asm_insn (\"bset\\t0,%2, %1\", operands);
+      ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
+                                CODE_LABEL_NUMBER (ops[2]));
+      return \"\";
+    }
+  return \"bset\\t%b0, %1\";
+}")
+
+(define_insn "*iorqi3_const"
+  [(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")
+               (match_operand:QI 2 "const_int_operand" "")))]
+  ""
+  "*
+{
+  int val = INTVAL (operands[2]) & 0x0FF;
+
+  if (A_REG_P (operands[0]) || H_REG_P (operands[2]))
+    return \"#\";
+
+  if (val == 0)
+    {
+      cc_status = cc_prev_status;
+      return \"\";
+    }
+  if (!H_REG_P (operands[0]))
+    {
+      return \"bset\\t%b0, %2\";
     }
+
+  if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
+    return \"orab\\t%b2\";
+  else if (DA_REG_P (operands[0]))
+    return \"oraa\\t%b2\";
+  else
+    fatal_insn (\"Invalid operand in the instruction\", insn);
+}")
+
+(define_insn "*iorqi3_gen"
+  [(set (match_operand:QI 0 "register_operand" "=d,d,d,?*A,?*A,!*q")
+       (ior:QI (match_operand:QI 1 "register_operand" "%0,0,0,0,0,0")
+            (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]))
+    return \"#\";
+
   if (D_REG_P (operands[0]) || DB_REG_P (operands[0]))
     return \"orab\\t%b2\";
   else if (DA_REG_P (operands[0]))
     fatal_insn (\"Invalid operand in the instruction\", insn);
 }")
 
+
 ;;--------------------------------------------------------------------
 ;;- xor instructions.
 ;;--------------------------------------------------------------------
   "#")
 
 (define_insn "xorsi3"
-  [(set (match_operand:SI 0 "register_operand" "=D")
-       (xor:SI (match_operand:SI 1 "register_operand" "%0")
-               (match_operand:SI 2 "general_operand" "Dimu")))]
+  [(set (match_operand:SI 0 "register_operand" "=D,!u")
+       (xor:SI (match_operand:SI 1 "register_operand" "%0,0")
+               (match_operand:SI 2 "general_operand" "Dimu,imu")))
+   (clobber (match_scratch:HI 3 "=X,d"))]
   ""
   "#")
 
 (define_insn "xorqi3"
   [(set (match_operand:QI 0 "register_operand" "=d,d,d,?*A,?*A,!*q")
         (xor:QI (match_operand:QI 1 "register_operand" "%0,0,0,0,0,0")
-             (match_operand:QI 2 "general_operand" "i,!um,!*A,!ium,?*A*d,!ium*A")))]
+             (match_operand:QI 2 "general_operand" "im,!u,!*A,!ium,?*A*d,!ium*A")))]
   ""
   "*
 {