m68hc11.c (m68hc11_addr_mode): New variable.
authorStephane Carrez <stcarrez@nerim.fr>
Tue, 2 Mar 2004 22:40:57 +0000 (23:40 +0100)
committerStephane Carrez <ciceron@gcc.gnu.org>
Tue, 2 Mar 2004 22:40:57 +0000 (23:40 +0100)
* config/m68hc11/m68hc11.c (m68hc11_addr_mode): New variable.
(m68hc11_mov_addr_mode): Likewise.
(m68hc11_override_options): Initialize them based on target.
(register_indirect_p): Allow a MEM for indirect addressing modes and
use flags to control what is allowed.
(m68hc11_small_indexed_indirect_p): Use m68hc11_mov_addr_mode for
supported addressing modes.
(m68hc11_register_indirect_p): Use m68hc11_addr_mode.
(go_if_legitimate_address_internal): Likewise.
(m68hc11_indirect_p): Likewise and check the mode.
(print_operand): Allow a (MEM (MEM)) and generate indirect addressing.

From-SVN: r78792

gcc/ChangeLog
gcc/config/m68hc11/m68hc11.c

index eed83b2..8bc1d5a 100644 (file)
@@ -1,3 +1,17 @@
+2004-03-02  Stephane Carrez  <stcarrez@nerim.fr>
+
+       * config/m68hc11/m68hc11.c (m68hc11_addr_mode): New variable.
+       (m68hc11_mov_addr_mode): Likewise.
+       (m68hc11_override_options): Initialize them based on target.
+       (register_indirect_p): Allow a MEM for indirect addressing modes and
+       use flags to control what is allowed.
+       (m68hc11_small_indexed_indirect_p): Use m68hc11_mov_addr_mode for
+       supported addressing modes.
+       (m68hc11_register_indirect_p): Use m68hc11_addr_mode.
+       (go_if_legitimate_address_internal): Likewise.
+       (m68hc11_indirect_p): Likewise and check the mode.
+       (print_operand): Allow a (MEM (MEM)) and generate indirect addressing.
+
 2004-03-02  Kazu Hirata  <kazu@cs.umass.edu>
 
        * builtins.c (BUILTIN_SETJMP_FRAME_VALUE): Remove.
index a0e83c3..cca40ed 100644 (file)
@@ -139,6 +139,16 @@ unsigned char m68hc11_reg_valid_for_index[FIRST_PSEUDO_REGISTER];
    This is 1 for 68HC11 and 0 for 68HC12.  */
 int m68hc11_sp_correction;
 
+#define ADDR_STRICT       0x01  /* Accept only registers in class A_REGS  */
+#define ADDR_INCDEC       0x02  /* Post/Pre inc/dec */
+#define ADDR_INDEXED      0x04  /* D-reg index */
+#define ADDR_OFFSET       0x08
+#define ADDR_INDIRECT     0x10  /* Accept (mem (mem ...)) for [n,X] */
+#define ADDR_CONST        0x20  /* Accept const and symbol_ref  */
+
+int m68hc11_addr_mode;
+int m68hc11_mov_addr_mode;
+
 /* Comparison operands saved by the "tstxx" and "cmpxx" expand patterns.  */
 rtx m68hc11_compare_op0;
 rtx m68hc11_compare_op1;
@@ -298,6 +308,8 @@ m68hc11_override_options (void)
       m68hc11_reg_valid_for_base[HARD_Z_REGNUM] = 1;
       m68hc11_sp_correction = 1;
       m68hc11_tmp_regs_class = D_REGS;
+      m68hc11_addr_mode = ADDR_OFFSET;
+      m68hc11_mov_addr_mode = 0;
       if (m68hc11_soft_reg_count == 0 && !TARGET_M6812)
        m68hc11_soft_reg_count = "4";
     }
@@ -317,6 +329,10 @@ m68hc11_override_options (void)
       m68hc11_reg_valid_for_index[HARD_D_REGNUM] = 1;
       m68hc11_sp_correction = 0;
       m68hc11_tmp_regs_class = TMP_REGS;
+      m68hc11_addr_mode = ADDR_INDIRECT | ADDR_OFFSET | ADDR_CONST
+        | (TARGET_AUTO_INC_DEC ? ADDR_INCDEC : 0);
+      m68hc11_mov_addr_mode = ADDR_OFFSET | ADDR_CONST
+        | (TARGET_AUTO_INC_DEC ? ADDR_INCDEC : 0);
       target_flags &= ~MASK_M6811;
       target_flags |= MASK_NO_DIRECT_MODE;
       if (m68hc11_soft_reg_count == 0)
@@ -551,18 +567,25 @@ preferred_reload_class (rtx operand, enum reg_class class)
    For 68hc11:  n,r    with n in [0..255] and r in A_REGS class
    For 68hc12:  n,r    no constraint on the constant, r in A_REGS class.  */
 static int
-register_indirect_p (rtx operand, enum machine_mode mode, int strict)
+register_indirect_p (rtx operand, enum machine_mode mode, int addr_mode)
 {
   rtx base, offset;
 
   switch (GET_CODE (operand))
     {
+    case MEM:
+      if ((addr_mode & ADDR_INDIRECT) && GET_MODE_SIZE (mode) <= 2)
+        return register_indirect_p (XEXP (operand, 0), mode,
+                                    addr_mode & (ADDR_STRICT | ADDR_OFFSET));
+      return 0;
+
     case POST_INC:
     case PRE_INC:
     case POST_DEC:
     case PRE_DEC:
-      if (TARGET_M6812 && TARGET_AUTO_INC_DEC)
-       return register_indirect_p (XEXP (operand, 0), mode, strict);
+      if (addr_mode & ADDR_INCDEC)
+       return register_indirect_p (XEXP (operand, 0), mode,
+                                    addr_mode & ADDR_STRICT);
       return 0;
 
     case PLUS:
@@ -574,36 +597,57 @@ register_indirect_p (rtx operand, enum machine_mode mode, int strict)
       if (GET_CODE (offset) == MEM)
        return 0;
 
+      /* Indexed addressing mode with 2 registers.  */
+      if (GET_CODE (base) == REG && GET_CODE (offset) == REG)
+        {
+          if (!(addr_mode & ADDR_INDEXED))
+            return 0;
+
+          addr_mode &= ADDR_STRICT;
+          if (REGNO_OK_FOR_BASE_P2 (REGNO (base), addr_mode)
+              && REGNO_OK_FOR_INDEX_P2 (REGNO (offset), addr_mode))
+            return 1;
+
+          if (REGNO_OK_FOR_BASE_P2 (REGNO (offset), addr_mode)
+              && REGNO_OK_FOR_INDEX_P2 (REGNO (base), addr_mode))
+            return 1;
+
+          return 0;
+        }
+
+      if (!(addr_mode & ADDR_OFFSET))
+        return 0;
+
       if (GET_CODE (base) == REG)
        {
-         if (!VALID_CONSTANT_OFFSET_P (offset, mode))
+          if (!VALID_CONSTANT_OFFSET_P (offset, mode))
            return 0;
 
-         if (strict == 0)
+         if (!(addr_mode & ADDR_STRICT))
            return 1;
 
-         return REGNO_OK_FOR_BASE_P2 (REGNO (base), strict);
+         return REGNO_OK_FOR_BASE_P2 (REGNO (base), 1);
        }
+
       if (GET_CODE (offset) == REG)
        {
          if (!VALID_CONSTANT_OFFSET_P (base, mode))
            return 0;
 
-         if (strict == 0)
+         if (!(addr_mode & ADDR_STRICT))
            return 1;
 
-         return REGNO_OK_FOR_BASE_P2 (REGNO (offset), strict);
+         return REGNO_OK_FOR_BASE_P2 (REGNO (offset), 1);
        }
       return 0;
 
     case REG:
-      return REGNO_OK_FOR_BASE_P2 (REGNO (operand), strict);
+      return REGNO_OK_FOR_BASE_P2 (REGNO (operand), addr_mode & ADDR_STRICT);
 
     case CONST_INT:
-      if (TARGET_M6811)
-        return 0;
-
-      return VALID_CONSTANT_OFFSET_P (operand, mode);
+      if (addr_mode & ADDR_CONST)
+        return VALID_CONSTANT_OFFSET_P (operand, mode);
+      return 0;
 
     default:
       return 0;
@@ -616,6 +660,7 @@ int
 m68hc11_small_indexed_indirect_p (rtx operand, enum machine_mode mode)
 {
   rtx base, offset;
+  int addr_mode;
 
   if (GET_CODE (operand) == REG && reload_in_progress
       && REGNO (operand) >= FIRST_PSEUDO_REGISTER
@@ -635,7 +680,8 @@ m68hc11_small_indexed_indirect_p (rtx operand, enum machine_mode mode)
   if (PUSH_POP_ADDRESS_P (operand))
     return 1;
 
-  if (!register_indirect_p (operand, mode, reload_completed))
+  addr_mode = m68hc11_mov_addr_mode | (reload_completed ? ADDR_STRICT : 0);
+  if (!register_indirect_p (operand, mode, addr_mode))
     return 0;
 
   if (TARGET_M6812 && GET_CODE (operand) == PLUS
@@ -676,18 +722,29 @@ m68hc11_small_indexed_indirect_p (rtx operand, enum machine_mode mode)
 int
 m68hc11_register_indirect_p (rtx operand, enum machine_mode mode)
 {
+  int addr_mode;
+
+  if (GET_CODE (operand) == REG && reload_in_progress
+      && REGNO (operand) >= FIRST_PSEUDO_REGISTER
+      && reg_equiv_memory_loc[REGNO (operand)])
+    {
+      operand = reg_equiv_memory_loc[REGNO (operand)];
+      operand = eliminate_regs (operand, 0, NULL_RTX);
+    }
   if (GET_CODE (operand) != MEM)
     return 0;
 
   operand = XEXP (operand, 0);
-  return register_indirect_p (operand, mode,
-                              (reload_completed | reload_in_progress));
+  addr_mode = m68hc11_addr_mode | (reload_completed ? ADDR_STRICT : 0);
+  return register_indirect_p (operand, mode, addr_mode);
 }
 
 static int
 go_if_legitimate_address_internal (rtx operand, enum machine_mode mode,
                                    int strict)
 {
+  int addr_mode;
+
   if (CONSTANT_ADDRESS_P (operand) && TARGET_M6812)
     {
       /* Reject the global variables if they are too wide.  This forces
@@ -697,7 +754,8 @@ go_if_legitimate_address_internal (rtx operand, enum machine_mode mode,
 
       return 1;
     }
-  if (register_indirect_p (operand, mode, strict))
+  addr_mode = m68hc11_addr_mode | (strict ? ADDR_STRICT : 0);
+  if (register_indirect_p (operand, mode, addr_mode))
     {
       return 1;
     }
@@ -984,18 +1042,20 @@ m68hc11_symbolic_p (rtx operand, enum machine_mode mode)
 int
 m68hc11_indirect_p (rtx operand, enum machine_mode mode)
 {
-  if (GET_CODE (operand) == MEM)
+  if (GET_CODE (operand) == MEM && GET_MODE (operand) == mode)
     {
       rtx op = XEXP (operand, 0);
+      int addr_mode;
 
       if (symbolic_memory_operand (op, mode))
-       return 0;
+       return TARGET_M6812;
 
       if (reload_in_progress)
         return 1;
 
       operand = XEXP (operand, 0);
-      return register_indirect_p (operand, mode, reload_completed);
+      addr_mode = m68hc11_addr_mode | (reload_completed ? ADDR_STRICT : 0);
+      return register_indirect_p (operand, mode, addr_mode);
     }
   return 0;
 }
@@ -2247,7 +2307,21 @@ print_operand (FILE *file, rtx op, int letter)
            abort ();
          break;
 
+        case MEM:
+          if (TARGET_M6812)
+            {
+              fprintf (file, "[");
+              print_operand_address (file, XEXP (base, 0));
+              fprintf (file, "]");
+            }
+          else
+            abort ();
+          break;
+
        default:
+          if (m68hc11_page0_symbol_p (base))
+            fprintf (file, "*");
+
          output_address (base);
          break;
        }