gcc/
authorrsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 6 Mar 2007 08:54:31 +0000 (08:54 +0000)
committerrsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 6 Mar 2007 08:54:31 +0000 (08:54 +0000)
PR target/23482
PR target/17114
* config/m68k/m68k-protos.h (m68k_legitimate_base_reg_p): Declare.
(m68k_legitimate_index_reg_p, m68k_legitimate_address_p): Likewise.
(m68k_matches_q_p, m68k_matches_u_p): Likewise.
* config/m68k/m68k.h (EXTRA_CONSTRAINT): Use m68k_matches_q_p
and m68k_matches_u_p.
(PCREL_GENERAL_OPERAND_OK, LEGITIMATE_BASE_REG_P): Delete.
(INDIRECTABLE_1_ADDRESS_P, GO_IF_NONINDEXED_ADDRESS): Delete.
(GO_IF_INDEXABLE_BASE, GO_IF_INDEXING, GO_IF_INDEXED_ADDRESS): Delete.
(LEGITIMATE_INDEX_REG_P, LEGITIMATE_INDEX_P): Delete.
(GO_IF_COLDFIRE_FPU_LEGITIMATE_ADDRESS): Delete.
(REG_STRICT_P): New macro.
(LEGITIMATE_PIC_OPERAND_P): Use REG_STRICT_P rather than
PCREL_GENERAL_OPERAND_OK.
(REG_OK_FOR_BASE_P): Merge definitions.  Use REG_STRICT_P and
m68k_legitimate_base_reg_p.
(REG_MODE_OK_FOR_INDEX_P): Likewise m68k_legitimate_index_reg_p.
(GO_IF_LEGITIMATE_ADDRESS): Likewise m68k_legitimate_address_p.
(PIC_CASE_VECTOR_ADDRESS): Update comment.
* config/m68k/m68k.c (m68k_address): New structure.
(m68k_legitimate_base_reg_p, m68k_legitimate_index_reg_p)
(m68k_decompose_index, m68k_legitimate_constant_address_p)
(m68k_jump_table_ref_p, m68k_decompose_address)
(m68k_legitimate_address_p, m68k_legitimate_mem_p, m68k_matches_q_p)
(m68k_matches_u_p): New functions.
(print_operand_address): Rewrite to use m68k_decompose_index.

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

gcc/ChangeLog
gcc/config/m68k/m68k-protos.h
gcc/config/m68k/m68k.c
gcc/config/m68k/m68k.h

index 6b19d77..c22df68 100644 (file)
@@ -1,3 +1,33 @@
+2007-03-06  Richard Sandiford  <richard@codesourcery.com>
+
+       PR target/23482
+       PR target/17114
+       * config/m68k/m68k-protos.h (m68k_legitimate_base_reg_p): Declare.
+       (m68k_legitimate_index_reg_p, m68k_legitimate_address_p): Likewise.
+       (m68k_matches_q_p, m68k_matches_u_p): Likewise.
+       * config/m68k/m68k.h (EXTRA_CONSTRAINT): Use m68k_matches_q_p
+       and m68k_matches_u_p.
+       (PCREL_GENERAL_OPERAND_OK, LEGITIMATE_BASE_REG_P): Delete.
+       (INDIRECTABLE_1_ADDRESS_P, GO_IF_NONINDEXED_ADDRESS): Delete.
+       (GO_IF_INDEXABLE_BASE, GO_IF_INDEXING, GO_IF_INDEXED_ADDRESS): Delete.
+       (LEGITIMATE_INDEX_REG_P, LEGITIMATE_INDEX_P): Delete.
+       (GO_IF_COLDFIRE_FPU_LEGITIMATE_ADDRESS): Delete.
+       (REG_STRICT_P): New macro.
+       (LEGITIMATE_PIC_OPERAND_P): Use REG_STRICT_P rather than
+       PCREL_GENERAL_OPERAND_OK.
+       (REG_OK_FOR_BASE_P): Merge definitions.  Use REG_STRICT_P and
+       m68k_legitimate_base_reg_p.
+       (REG_MODE_OK_FOR_INDEX_P): Likewise m68k_legitimate_index_reg_p.
+       (GO_IF_LEGITIMATE_ADDRESS): Likewise m68k_legitimate_address_p.
+       (PIC_CASE_VECTOR_ADDRESS): Update comment.
+       * config/m68k/m68k.c (m68k_address): New structure.
+       (m68k_legitimate_base_reg_p, m68k_legitimate_index_reg_p)
+       (m68k_decompose_index, m68k_legitimate_constant_address_p)
+       (m68k_jump_table_ref_p, m68k_decompose_address)
+       (m68k_legitimate_address_p, m68k_legitimate_mem_p, m68k_matches_q_p)
+       (m68k_matches_u_p): New functions.
+       (print_operand_address): Rewrite to use m68k_decompose_index.
+
 2007/03/05  David Taylor  <dtaylor@emc.com>
 
        * gcc.c: Correct copyright date in --version output.
index d0ff670..ba137d6 100644 (file)
@@ -50,7 +50,12 @@ extern int standard_68881_constant_p (rtx);
 extern void print_operand_address (FILE *, rtx);
 extern void print_operand (FILE *, rtx, int);
 extern void notice_update_cc (rtx, rtx);
+extern bool m68k_legitimate_base_reg_p (rtx, bool);
+extern bool m68k_legitimate_index_reg_p (rtx, bool);
 extern bool m68k_illegitimate_symbolic_constant_p (rtx);
+extern bool m68k_legitimate_address_p (enum machine_mode, rtx, bool);
+extern bool m68k_matches_q_p (rtx);
+extern bool m68k_matches_u_p (rtx);
 extern rtx legitimize_pic_address (rtx, enum machine_mode, rtx);
 extern int valid_dbcc_comparison_p_2 (rtx, enum machine_mode);
 extern rtx m68k_libcall_value (enum machine_mode);
index 90e2491..57e15c8 100644 (file)
@@ -103,6 +103,27 @@ struct m68k_frame
 /* Current frame information calculated by m68k_compute_frame_layout().  */
 static struct m68k_frame current_frame;
 
+/* Structure describing an m68k address.
+
+   If CODE is UNKNOWN, the address is BASE + INDEX * SCALE + OFFSET,
+   with null fields evaluating to 0.  Here:
+
+   - BASE satisfies m68k_legitimate_base_reg_p
+   - INDEX satisfies m68k_legitimate_index_reg_p
+   - OFFSET satisfies m68k_legitimate_constant_address_p
+
+   INDEX is either HImode or SImode.  The other fields are SImode.
+
+   If CODE is PRE_DEC, the address is -(BASE).  If CODE is POST_INC,
+   the address is (BASE)+.  */
+struct m68k_address {
+  enum rtx_code code;
+  rtx base;
+  rtx index;
+  rtx offset;
+  int scale;
+};
+
 static bool m68k_handle_option (size_t, const char *, int);
 static rtx find_addr_reg (rtx);
 static const char *singlemove_string (rtx *);
@@ -1666,6 +1687,76 @@ output_btst (rtx *operands, rtx countop, rtx dataop, rtx insn, int signpos)
   return "btst %0,%1";
 }
 \f
+/* Return true if X is a legitimate base register.  STRICT_P says
+   whether we need strict checking.  */
+
+bool
+m68k_legitimate_base_reg_p (rtx x, bool strict_p)
+{
+  /* Allow SUBREG everywhere we allow REG.  This results in better code.  */
+  if (!strict_p && GET_CODE (x) == SUBREG)
+    x = SUBREG_REG (x);
+
+  return (REG_P (x)
+         && (strict_p
+             ? REGNO_OK_FOR_BASE_P (REGNO (x))
+             : !DATA_REGNO_P (REGNO (x)) && !FP_REGNO_P (REGNO (x))));
+}
+
+/* Return true if X is a legitimate index register.  STRICT_P says
+   whether we need strict checking.  */
+
+bool
+m68k_legitimate_index_reg_p (rtx x, bool strict_p)
+{
+  if (!strict_p && GET_CODE (x) == SUBREG)
+    x = SUBREG_REG (x);
+
+  return (REG_P (x)
+         && (strict_p
+             ? REGNO_OK_FOR_INDEX_P (REGNO (x))
+             : !FP_REGNO_P (REGNO (x))));
+}
+
+/* Return true if X is a legitimate index expression for a (d8,An,Xn) or
+   (bd,An,Xn) addressing mode.  Fill in the INDEX and SCALE fields of
+   ADDRESS if so.  STRICT_P says whether we need strict checking.  */
+
+static bool
+m68k_decompose_index (rtx x, bool strict_p, struct m68k_address *address)
+{
+  int scale;
+
+  /* Check for a scale factor.  */
+  scale = 1;
+  if ((TARGET_68020 || TARGET_COLDFIRE)
+      && GET_CODE (x) == MULT
+      && GET_CODE (XEXP (x, 1)) == CONST_INT
+      && (INTVAL (XEXP (x, 1)) == 2
+         || INTVAL (XEXP (x, 1)) == 4
+         || (INTVAL (XEXP (x, 1)) == 8
+             && (TARGET_COLDFIRE_FPU || !TARGET_COLDFIRE))))
+    {
+      scale = INTVAL (XEXP (x, 1));
+      x = XEXP (x, 0);
+    }
+
+  /* Check for a word extension.  */
+  if (!TARGET_COLDFIRE
+      && GET_CODE (x) == SIGN_EXTEND
+      && GET_MODE (XEXP (x, 0)) == HImode)
+    x = XEXP (x, 0);
+
+  if (m68k_legitimate_index_reg_p (x, strict_p))
+    {
+      address->scale = scale;
+      address->index = x;
+      return true;
+    }
+
+  return false;
+}
+
 /* Return true if X is an illegitimate symbolic constant.  */
 
 bool
@@ -1683,6 +1774,251 @@ m68k_illegitimate_symbolic_constant_p (rtx x)
   return false;
 }
 
+/* Return true if X is a legitimate constant address that can reach
+   bytes in the range [X, X + REACH).  STRICT_P says whether we need
+   strict checking.  */
+
+static bool
+m68k_legitimate_constant_address_p (rtx x, unsigned int reach, bool strict_p)
+{
+  rtx base, offset;
+
+  if (!CONSTANT_ADDRESS_P (x))
+    return false;
+
+  if (flag_pic
+      && !(strict_p && TARGET_PCREL)
+      && symbolic_operand (x, VOIDmode))
+    return false;
+
+  if (M68K_OFFSETS_MUST_BE_WITHIN_SECTIONS_P && reach > 1)
+    {
+      split_const (x, &base, &offset);
+      if (GET_CODE (base) == SYMBOL_REF
+         && !offset_within_block_p (base, INTVAL (offset) + reach - 1))
+       return false;
+    }
+
+  return true;
+}
+
+/* Return true if X is a LABEL_REF for a jump table.  Assume that unplaced
+   labels will become jump tables.  */
+
+static bool
+m68k_jump_table_ref_p (rtx x)
+{
+  if (GET_CODE (x) != LABEL_REF)
+    return false;
+
+  x = XEXP (x, 0);
+  if (!NEXT_INSN (x) && !PREV_INSN (x))
+    return true;
+
+  x = next_nonnote_insn (x);
+  return x && JUMP_TABLE_DATA_P (x);
+}
+
+/* Return true if X is a legitimate address for values of mode MODE.
+   STRICT_P says whether strict checking is needed.  If the address
+   is valid, describe its components in *ADDRESS.  */
+
+static bool
+m68k_decompose_address (enum machine_mode mode, rtx x,
+                       bool strict_p, struct m68k_address *address)
+{
+  unsigned int reach;
+
+  memset (address, 0, sizeof (*address));
+
+  if (mode == BLKmode)
+    reach = 1;
+  else
+    reach = GET_MODE_SIZE (mode);
+
+  /* Check for (An) (mode 2).  */
+  if (m68k_legitimate_base_reg_p (x, strict_p))
+    {
+      address->base = x;
+      return true;
+    }
+
+  /* Check for -(An) and (An)+ (modes 3 and 4).  */
+  if ((GET_CODE (x) == PRE_DEC || GET_CODE (x) == POST_INC)
+      && m68k_legitimate_base_reg_p (XEXP (x, 0), strict_p))
+    {
+      address->code = GET_CODE (x);
+      address->base = XEXP (x, 0);
+      return true;
+    }
+
+  /* Check for (d16,An) (mode 5).  */
+  if (GET_CODE (x) == PLUS
+      && GET_CODE (XEXP (x, 1)) == CONST_INT
+      && IN_RANGE (INTVAL (XEXP (x, 1)), -0x8000, 0x8000 - reach)
+      && m68k_legitimate_base_reg_p (XEXP (x, 0), strict_p))
+    {
+      address->base = XEXP (x, 0);
+      address->offset = XEXP (x, 1);
+      return true;
+    }
+
+  /* Check for GOT loads.  These are (bd,An,Xn) addresses if
+     TARGET_68020 && flag_pic == 2, otherwise they are (d16,An)
+     addresses.  */
+  if (flag_pic
+      && GET_CODE (x) == PLUS
+      && XEXP (x, 0) == pic_offset_table_rtx
+      && (GET_CODE (XEXP (x, 1)) == SYMBOL_REF
+         || GET_CODE (XEXP (x, 1)) == LABEL_REF))
+    {
+      address->base = XEXP (x, 0);
+      address->offset = XEXP (x, 1);
+      return true;
+    }
+
+  /* The ColdFire FPU only accepts addressing modes 2-5.  */
+  if (TARGET_COLDFIRE_FPU && GET_MODE_CLASS (mode) == MODE_FLOAT)
+    return false;
+
+  /* Check for (xxx).w and (xxx).l.  Also, in the TARGET_PCREL case,
+     check for (d16,PC) or (bd,PC,Xn) with a suppressed index register.
+     All these modes are variations of mode 7.  */
+  if (m68k_legitimate_constant_address_p (x, reach, strict_p))
+    {
+      address->offset = x;
+      return true;
+    }
+
+  /* Check for (d8,PC,Xn), a mode 7 form.  This case is needed for
+     tablejumps.
+
+     ??? do_tablejump creates these addresses before placing the target
+     label, so we have to assume that unplaced labels are jump table
+     references.  It seems unlikely that we would ever generate indexed
+     accesses to unplaced labels in other cases.  */
+  if (GET_CODE (x) == PLUS
+      && m68k_jump_table_ref_p (XEXP (x, 1))
+      && m68k_decompose_index (XEXP (x, 0), strict_p, address))
+    {
+      address->offset = XEXP (x, 1);
+      return true;
+    }
+
+  /* Everything hereafter deals with (d8,An,Xn.SIZE*SCALE) or
+     (bd,An,Xn.SIZE*SCALE) addresses.  */
+
+  if (TARGET_68020)
+    {
+      /* Check for a nonzero base displacement.  */
+      if (GET_CODE (x) == PLUS
+         && m68k_legitimate_constant_address_p (XEXP (x, 1), reach, strict_p))
+       {
+         address->offset = XEXP (x, 1);
+         x = XEXP (x, 0);
+       }
+
+      /* Check for a suppressed index register.  */
+      if (m68k_legitimate_base_reg_p (x, strict_p))
+       {
+         address->base = x;
+         return true;
+       }
+
+      /* Check for a suppressed base register.  Do not allow this case
+        for non-symbolic offsets as it effectively gives gcc freedom
+        to treat data registers as base registers, which can generate
+        worse code.  */
+      if (address->offset
+         && symbolic_operand (address->offset, VOIDmode)
+         && m68k_decompose_index (x, strict_p, address))
+       return true;
+    }
+  else
+    {
+      /* Check for a nonzero base displacement.  */
+      if (GET_CODE (x) == PLUS
+         && GET_CODE (XEXP (x, 1)) == CONST_INT
+         && IN_RANGE (INTVAL (XEXP (x, 1)), -0x80, 0x80 - reach))
+       {
+         address->offset = XEXP (x, 1);
+         x = XEXP (x, 0);
+       }
+    }
+
+  /* We now expect the sum of a base and an index.  */
+  if (GET_CODE (x) == PLUS)
+    {
+      if (m68k_legitimate_base_reg_p (XEXP (x, 0), strict_p)
+         && m68k_decompose_index (XEXP (x, 1), strict_p, address))
+       {
+         address->base = XEXP (x, 0);
+         return true;
+       }
+
+      if (m68k_legitimate_base_reg_p (XEXP (x, 1), strict_p)
+         && m68k_decompose_index (XEXP (x, 0), strict_p, address))
+       {
+         address->base = XEXP (x, 1);
+         return true;
+       }
+    }
+  return false;
+}
+
+/* Return true if X is a legitimate address for values of mode MODE.
+   STRICT_P says whether strict checking is needed.  */
+
+bool
+m68k_legitimate_address_p (enum machine_mode mode, rtx x, bool strict_p)
+{
+  struct m68k_address address;
+
+  return m68k_decompose_address (mode, x, strict_p, &address);
+}
+
+/* Return true if X is a memory, describing its address in ADDRESS if so.
+   Apply strict checking if called during or after reload.  */
+
+static bool
+m68k_legitimate_mem_p (rtx x, struct m68k_address *address)
+{
+  return (MEM_P (x)
+         && m68k_decompose_address (GET_MODE (x), XEXP (x, 0),
+                                    reload_in_progress || reload_completed,
+                                    address));
+}
+
+/* Return true if X matches the 'Q' constraint.  It must be a memory
+   with a base address and no constant offset or index.  */
+
+bool
+m68k_matches_q_p (rtx x)
+{
+  struct m68k_address address;
+
+  return (m68k_legitimate_mem_p (x, &address)
+         && address.code == UNKNOWN
+         && address.base
+         && !address.offset
+         && !address.index);
+}
+
+/* Return true if X matches the 'U' constraint.  It must be a base address
+   with a constant offset and no index.  */
+
+bool
+m68k_matches_u_p (rtx x)
+{
+  struct m68k_address address;
+
+  return (m68k_legitimate_mem_p (x, &address)
+         && address.code == UNKNOWN
+         && address.base
+         && address.offset
+         && !address.index);
+}
+
 /* Legitimize PIC addresses.  If the address is already
    position-independent, we return ORIG.  Newly generated
    position-independent addresses go to REG.  If we need more
@@ -3271,265 +3607,142 @@ print_operand (FILE *file, rtx op, int letter)
    offset is output in word mode (e.g. movel a5@(_foo:w), a0).  When generating
    -fPIC code the offset is output in long mode (e.g. movel a5@(_foo:l), a0) */
 
-#if MOTOROLA
-#  define ASM_OUTPUT_CASE_FETCH(file, labelno, regname) \
-  asm_fprintf (file, "%LL%d-%LLI%d.b(%Rpc,%s.", labelno, labelno, regname)
-#else /* !MOTOROLA */
-# define ASM_OUTPUT_CASE_FETCH(file, labelno, regname) \
-  asm_fprintf (file, "%Rpc@(%LL%d-%LLI%d-2:b,%s:", labelno, labelno, regname)
-#endif /* !MOTOROLA */
-
 void
 print_operand_address (FILE *file, rtx addr)
 {
-  register rtx reg1, reg2, breg, ireg;
-  rtx offset;
-
-  switch (GET_CODE (addr))
-    {
-    case REG:
-      fprintf (file, MOTOROLA ? "(%s)" : "%s@", M68K_REGNAME (REGNO (addr)));
-      break;
-    case PRE_DEC:
-      fprintf (file, MOTOROLA ? "-(%s)" : "%s@-",
-              M68K_REGNAME (REGNO (XEXP (addr, 0))));
-      break;
-    case POST_INC:
-      fprintf (file, MOTOROLA ? "(%s)+" : "%s@+",
-              M68K_REGNAME (REGNO (XEXP (addr, 0))));
-      break;
-    case PLUS:
-      reg1 = reg2 = ireg = breg = offset = 0;
-      if (CONSTANT_ADDRESS_P (XEXP (addr, 0)))
-       {
-         offset = XEXP (addr, 0);
-         addr = XEXP (addr, 1);
-       }
-      else if (CONSTANT_ADDRESS_P (XEXP (addr, 1)))
-       {
-         offset = XEXP (addr, 1);
-         addr = XEXP (addr, 0);
-       }
-      if (GET_CODE (addr) != PLUS)
-       {
-         ;
-       }
-      else if (GET_CODE (XEXP (addr, 0)) == SIGN_EXTEND)
-       {
-         reg1 = XEXP (addr, 0);
-         addr = XEXP (addr, 1);
-       }
-      else if (GET_CODE (XEXP (addr, 1)) == SIGN_EXTEND)
-       {
-         reg1 = XEXP (addr, 1);
-         addr = XEXP (addr, 0);
-       }
-      else if (GET_CODE (XEXP (addr, 0)) == MULT)
-       {
-         reg1 = XEXP (addr, 0);
-         addr = XEXP (addr, 1);
-       }
-      else if (GET_CODE (XEXP (addr, 1)) == MULT)
-       {
-         reg1 = XEXP (addr, 1);
-         addr = XEXP (addr, 0);
-       }
-      else if (GET_CODE (XEXP (addr, 0)) == REG)
-       {
-         reg1 = XEXP (addr, 0);
-         addr = XEXP (addr, 1);
-       }
-      else if (GET_CODE (XEXP (addr, 1)) == REG)
-       {
-         reg1 = XEXP (addr, 1);
-         addr = XEXP (addr, 0);
-       }
-      if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT
-         || GET_CODE (addr) == SIGN_EXTEND)
+  struct m68k_address address;
+
+  if (!m68k_decompose_address (QImode, addr, true, &address))
+    gcc_unreachable ();
+
+  if (address.code == PRE_DEC)
+    fprintf (file, MOTOROLA ? "-(%s)" : "%s@-",
+            M68K_REGNAME (REGNO (address.base)));
+  else if (address.code == POST_INC)
+    fprintf (file, MOTOROLA ? "(%s)+" : "%s@+",
+            M68K_REGNAME (REGNO (address.base)));
+  else if (!address.base && !address.index)
+    {
+      /* A constant address.  */
+      gcc_assert (address.offset == addr);
+      if (GET_CODE (addr) == CONST_INT)
        {
-         if (reg1 == 0)
-           reg1 = addr;
+         /* (xxx).w or (xxx).l.  */
+         if (IN_RANGE (INTVAL (addr), -0x8000, 0x7fff))
+           fprintf (file, MOTOROLA ? "%d.w" : "%d:w", (int) INTVAL (addr));
          else
-           reg2 = addr;
-         addr = 0;
-       }
-#if 0  /* for OLD_INDEXING */
-      else if (GET_CODE (addr) == PLUS)
-       {
-         if (GET_CODE (XEXP (addr, 0)) == REG)
-           {
-             reg2 = XEXP (addr, 0);
-             addr = XEXP (addr, 1);
-           }
-         else if (GET_CODE (XEXP (addr, 1)) == REG)
-           {
-             reg2 = XEXP (addr, 1);
-             addr = XEXP (addr, 0);
-           }
-       }
-#endif
-      if (offset != 0)
-       {
-         gcc_assert (!addr);
-         addr = offset;
+           fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (addr));
        }
-      if ((reg1 && (GET_CODE (reg1) == SIGN_EXTEND
-                   || GET_CODE (reg1) == MULT))
-         || (reg2 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg2))))
-       {
-         breg = reg2;
-         ireg = reg1;
-       }
-      else if (reg1 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg1)))
+      else if (TARGET_PCREL)
        {
-         breg = reg1;
-         ireg = reg2;
+         /* (d16,PC) or (bd,PC,Xn) (with suppressed index register).  */
+         fputc ('(', file);
+         output_addr_const (file, addr);
+         asm_fprintf (file, flag_pic == 1 ? ":w,%Rpc)" : ":l,%Rpc)");
        }
-      if (ireg != 0 && breg == 0 && GET_CODE (addr) == LABEL_REF
-         && ! (flag_pic && ireg == pic_offset_table_rtx))
+      else
        {
-         int scale = 1;
-         if (GET_CODE (ireg) == MULT)
-           {
-             scale = INTVAL (XEXP (ireg, 1));
-             ireg = XEXP (ireg, 0);
-           }
-         if (GET_CODE (ireg) == SIGN_EXTEND)
+         /* (xxx).l.  We need a special case for SYMBOL_REF if the symbol
+            name ends in `.<letter>', as the last 2 characters can be
+            mistaken as a size suffix.  Put the name in parentheses.  */
+         if (GET_CODE (addr) == SYMBOL_REF
+             && strlen (XSTR (addr, 0)) > 2
+             && XSTR (addr, 0)[strlen (XSTR (addr, 0)) - 2] == '.')
            {
-             ASM_OUTPUT_CASE_FETCH (file,
-                                    CODE_LABEL_NUMBER (XEXP (addr, 0)),
-                                    M68K_REGNAME (REGNO (XEXP (ireg, 0))));
-             fprintf (file, "w");
+             putc ('(', file);
+             output_addr_const (file, addr);
+             putc (')', file);
            }
          else
-           {
-             ASM_OUTPUT_CASE_FETCH (file,
-                                    CODE_LABEL_NUMBER (XEXP (addr, 0)),
-                                    M68K_REGNAME (REGNO (ireg)));
-             fprintf (file, "l");
-           }
-         if (scale != 1)
-           fprintf (file, MOTOROLA ? "*%d" : ":%d", scale);
-         putc (')', file);
-         break;
-       }
-      if (breg != 0 && ireg == 0 && GET_CODE (addr) == LABEL_REF
-         && ! (flag_pic && breg == pic_offset_table_rtx))
-       {
-         ASM_OUTPUT_CASE_FETCH (file,
-                                CODE_LABEL_NUMBER (XEXP (addr, 0)),
-                                M68K_REGNAME (REGNO (breg)));
-         fprintf (file, "l)");
-         break;
+           output_addr_const (file, addr);
        }
-      if (ireg != 0 || breg != 0)
+    }
+  else
+    {
+      int labelno;
+
+      /* If ADDR is a (d8,pc,Xn) address, this is the number of the
+        label being acceesed, otherwise it is -1.  */
+      labelno = (address.offset
+                && !address.base
+                && GET_CODE (address.offset) == LABEL_REF
+                ? CODE_LABEL_NUMBER (XEXP (address.offset, 0))
+                : -1);
+      if (MOTOROLA)
        {
-         int scale = 1;
-           
-         gcc_assert (breg);
-         gcc_assert (flag_pic || !addr || GET_CODE (addr) != LABEL_REF);
-           
-         if (MOTOROLA)
+         /* Print the "offset(base" component.  */
+         if (labelno >= 0)
+           asm_fprintf (file, "%LL%d-%LLI%d.b(%Rpc,", labelno, labelno);
+         else
            {
-             if (addr != 0)
+             if (address.offset)
                {
-                 output_addr_const (file, addr);
-                 if (flag_pic && (breg == pic_offset_table_rtx))
+                 output_addr_const (file, address.offset);
+                 if (flag_pic && address.base == pic_offset_table_rtx)
                    {
                      fprintf (file, "@GOT");
-                     if (flag_pic == 1)
+                     if (flag_pic == 1 && TARGET_68020)
                        fprintf (file, ".w");
                    }
                }
-             fprintf (file, "(%s", M68K_REGNAME (REGNO (breg)));
-             if (ireg != 0)
-               putc (',', file);
+             putc ('(', file);
+             if (address.base)
+               fputs (M68K_REGNAME (REGNO (address.base)), file);
            }
-         else /* !MOTOROLA */
+         /* Print the ",index" component, if any.  */
+         if (address.index)
            {
-             fprintf (file, "%s@(", M68K_REGNAME (REGNO (breg)));
-             if (addr != 0)
-               {
-                 output_addr_const (file, addr);
-                 if (breg == pic_offset_table_rtx)
-                   switch (flag_pic)
-                     {
-                     case 1:
-                       fprintf (file, ":w");
-                       break;
-                     case 2:
-                       fprintf (file, ":l");
-                       break;
-                     default:
-                       break;
-                     }
-                 if (ireg != 0)
-                   putc (',', file);
-               }
-           } /* !MOTOROLA */
-         if (ireg != 0 && GET_CODE (ireg) == MULT)
-           {
-             scale = INTVAL (XEXP (ireg, 1));
-             ireg = XEXP (ireg, 0);
+             if (address.base)
+               putc (',', file);
+             fprintf (file, "%s.%c",
+                      M68K_REGNAME (REGNO (address.index)),
+                      GET_MODE (address.index) == HImode ? 'w' : 'l');
+             if (address.scale != 1)
+               fprintf (file, "*%d", address.scale);
            }
-         if (ireg != 0 && GET_CODE (ireg) == SIGN_EXTEND)
-           fprintf (file, MOTOROLA ? "%s.w" : "%s:w",
-                    M68K_REGNAME (REGNO (XEXP (ireg, 0))));
-         else if (ireg != 0)
-           fprintf (file, MOTOROLA ? "%s.l" : "%s:l",
-                    M68K_REGNAME (REGNO (ireg)));
-         if (scale != 1)
-           fprintf (file, MOTOROLA ? "*%d" : ":%d", scale);
          putc (')', file);
-         break;
-       }
-      else if (reg1 != 0 && GET_CODE (addr) == LABEL_REF
-              && ! (flag_pic && reg1 == pic_offset_table_rtx))
-       {
-         ASM_OUTPUT_CASE_FETCH (file,
-                                CODE_LABEL_NUMBER (XEXP (addr, 0)),
-                                M68K_REGNAME (REGNO (reg1)));
-         fprintf (file, "l)");
-         break;
        }
-      /* FALL-THROUGH (is this really what we want?)  */
-    default:
-      if (GET_CODE (addr) == CONST_INT
-         && INTVAL (addr) < 0x8000
-         && INTVAL (addr) >= -0x8000)
-       {
-         fprintf (file, MOTOROLA ? "%d.w" : "%d:w", (int) INTVAL (addr));
-       }
-      else if (GET_CODE (addr) == CONST_INT)
+      else /* !MOTOROLA */
        {
-         fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (addr));
-       }
-      else if (TARGET_PCREL)
-       {
-         fputc ('(', file);
-         output_addr_const (file, addr);
-         if (flag_pic == 1)
-           asm_fprintf (file, ":w,%Rpc)");
+         if (!address.offset && !address.index)
+           fprintf (file, "%s@", M68K_REGNAME (REGNO (address.base)));
          else
-           asm_fprintf (file, ":l,%Rpc)");
-       }
-      else
-       {
-         /* Special case for SYMBOL_REF if the symbol name ends in
-            `.<letter>', this can be mistaken as a size suffix.  Put
-            the name in parentheses.  */
-         if (GET_CODE (addr) == SYMBOL_REF
-             && strlen (XSTR (addr, 0)) > 2
-             && XSTR (addr, 0)[strlen (XSTR (addr, 0)) - 2] == '.')
            {
-             putc ('(', file);
-             output_addr_const (file, addr);
+             /* Print the "base@(offset" component.  */
+             if (labelno >= 0)
+               asm_fprintf (file, "%Rpc@(%LL%d-%LLI%d-2:b", labelno, labelno);
+             else
+               {
+                 if (address.base)
+                   fputs (M68K_REGNAME (REGNO (address.base)), file);
+                 fprintf (file, "@(");
+                 if (address.offset)
+                   {
+                     output_addr_const (file, address.offset);
+                     if (address.base == pic_offset_table_rtx && TARGET_68020)
+                       switch (flag_pic)
+                         {
+                         case 1:
+                           fprintf (file, ":w"); break;
+                         case 2:
+                           fprintf (file, ":l"); break;
+                         default:
+                           break;
+                         }
+                   }
+               }
+             /* Print the ",index" component, if any.  */
+             if (address.index)
+               {
+                 fprintf (file, ",%s:%c",
+                          M68K_REGNAME (REGNO (address.index)),
+                          GET_MODE (address.index) == HImode ? 'w' : 'l');
+                 if (address.scale != 1)
+                   fprintf (file, ":%d", address.scale);
+               }
              putc (')', file);
            }
-         else
-           output_addr_const (file, addr);
        }
-      break;
     }
 }
 \f
index f960f3b..0465688 100644 (file)
@@ -535,14 +535,10 @@ extern enum reg_class regno_reg_class[];
          || GET_CODE (OP) == CONST))                   \
    :                                                   \
    (CODE) == 'Q'                                       \
-   ? (GET_CODE (OP) == MEM                             \
-      && GET_CODE (XEXP (OP, 0)) == REG)               \
+   ? m68k_matches_q_p (OP)                             \
    :                                                   \
    (CODE) == 'U'                                       \
-   ? (GET_CODE (OP) == MEM                             \
-      && GET_CODE (XEXP (OP, 0)) == PLUS               \
-      && GET_CODE (XEXP (XEXP (OP, 0), 0)) == REG      \
-      && GET_CODE (XEXP (XEXP (OP, 0), 1)) == CONST_INT) \
+   ? m68k_matches_u_p (OP)                             \
    :                                                   \
    (CODE) == 'W'                                       \
    ? const_call_operand (OP, VOIDmode)                 \
@@ -807,153 +803,31 @@ __transfer_from_trampoline ()                                    \
    && !m68k_illegitimate_symbolic_constant_p (X))
 
 #ifndef REG_OK_STRICT
-#define PCREL_GENERAL_OPERAND_OK 0
+#define REG_STRICT_P 0
 #else
-#define PCREL_GENERAL_OPERAND_OK (TARGET_PCREL)
+#define REG_STRICT_P 1
 #endif
 
-#define LEGITIMATE_PIC_OPERAND_P(X)    \
-  (! symbolic_operand (X, VOIDmode)                            \
-   || PCREL_GENERAL_OPERAND_OK)
+#define LEGITIMATE_PIC_OPERAND_P(X)                            \
+  (!symbolic_operand (X, VOIDmode)                             \
+   || (TARGET_PCREL && REG_STRICT_P))
 
-#ifndef REG_OK_STRICT
-
-/* Nonzero if X is a hard reg that can be used as an index
-   or if it is a pseudo reg.  */
-#define REG_OK_FOR_INDEX_P(X) !FP_REGNO_P (REGNO (X))
-/* Nonzero if X is a hard reg that can be used as a base reg
-   or if it is a pseudo reg.  */
 #define REG_OK_FOR_BASE_P(X) \
-  (!DATA_REGNO_P (REGNO (X)) && !FP_REGNO_P (REGNO (X)))
+  m68k_legitimate_base_reg_p (X, REG_STRICT_P)
 
-#else
+#define REG_OK_FOR_INDEX_P(X) \
+  m68k_legitimate_index_reg_p (X, REG_STRICT_P)
 
-/* Nonzero if X is a hard reg that can be used as an index.  */
-#define REG_OK_FOR_INDEX_P(X) REGNO_OK_FOR_INDEX_P (REGNO (X))
-/* Nonzero if X is a hard reg that can be used as a base reg.  */
-#define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P (REGNO (X))
-
-#endif
-\f
-/* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression
-   that is a valid memory address for an instruction.
-   The MODE argument is the machine mode for the MEM expression
-   that wants to use this address.
-
-   When generating PIC, an address involving a SYMBOL_REF is legitimate
-   if and only if it is the sum of pic_offset_table_rtx and the SYMBOL_REF.
-   We use LEGITIMATE_PIC_OPERAND_P to throw out the illegitimate addresses,
-   and we explicitly check for the sum of pic_offset_table_rtx and a SYMBOL_REF.
-
-   Likewise for a LABEL_REF when generating PIC.
-
-   The other macros defined here are used only in GO_IF_LEGITIMATE_ADDRESS.  */
-
-/* Allow SUBREG everywhere we allow REG.  This results in better code.  It
-   also makes function inlining work when inline functions are called with
-   arguments that are SUBREGs.  */
-
-#define LEGITIMATE_BASE_REG_P(X)   \
-  ((GET_CODE (X) == REG && REG_OK_FOR_BASE_P (X))      \
-   || (GET_CODE (X) == SUBREG                          \
-       && GET_CODE (SUBREG_REG (X)) == REG             \
-       && REG_OK_FOR_BASE_P (SUBREG_REG (X))))
-
-#define INDIRECTABLE_1_ADDRESS_P(X)  \
-  ((CONSTANT_ADDRESS_P (X) && (!flag_pic || LEGITIMATE_PIC_OPERAND_P (X))) \
-   || LEGITIMATE_BASE_REG_P (X)                                                \
-   || ((GET_CODE (X) == PRE_DEC || GET_CODE (X) == POST_INC)           \
-       && LEGITIMATE_BASE_REG_P (XEXP (X, 0)))                         \
-   || (GET_CODE (X) == PLUS                                            \
-       && LEGITIMATE_BASE_REG_P (XEXP (X, 0))                          \
-       && GET_CODE (XEXP (X, 1)) == CONST_INT                          \
-       && (TARGET_68020                                                        \
-          || ((unsigned) INTVAL (XEXP (X, 1)) + 0x8000) < 0x10000))    \
-   || (GET_CODE (X) == PLUS && XEXP (X, 0) == pic_offset_table_rtx     \
-       && flag_pic && GET_CODE (XEXP (X, 1)) == SYMBOL_REF)            \
-   || (GET_CODE (X) == PLUS && XEXP (X, 0) == pic_offset_table_rtx     \
-       && flag_pic && GET_CODE (XEXP (X, 1)) == LABEL_REF))
-
-#define GO_IF_NONINDEXED_ADDRESS(X, ADDR)  \
-{ if (INDIRECTABLE_1_ADDRESS_P (X)) goto ADDR; }
-
-/* Only labels on dispatch tables are valid for indexing from.  */
-#define GO_IF_INDEXABLE_BASE(X, ADDR)                          \
-{ rtx temp;                                                    \
-  if (GET_CODE (X) == LABEL_REF                                        \
-      && (temp = next_nonnote_insn (XEXP (X, 0))) != 0         \
-      && GET_CODE (temp) == JUMP_INSN                          \
-      && (GET_CODE (PATTERN (temp)) == ADDR_VEC                        \
-         || GET_CODE (PATTERN (temp)) == ADDR_DIFF_VEC))       \
-    goto ADDR;                                                 \
-  if (LEGITIMATE_BASE_REG_P (X)) goto ADDR; }
-
-#define GO_IF_INDEXING(X, ADDR)        \
-{ if (GET_CODE (X) == PLUS && LEGITIMATE_INDEX_P (XEXP (X, 0)))                \
-    { GO_IF_INDEXABLE_BASE (XEXP (X, 1), ADDR); }                      \
-  if (GET_CODE (X) == PLUS && LEGITIMATE_INDEX_P (XEXP (X, 1)))                \
-    { GO_IF_INDEXABLE_BASE (XEXP (X, 0), ADDR); } }
-
-#define GO_IF_INDEXED_ADDRESS(X, ADDR)  \
-{ GO_IF_INDEXING (X, ADDR);                                            \
-  if (GET_CODE (X) == PLUS)                                            \
-    { if (GET_CODE (XEXP (X, 1)) == CONST_INT                          \
-         && (TARGET_68020 || (unsigned) INTVAL (XEXP (X, 1)) + 0x80 < 0x100))          \
-       { rtx go_temp = XEXP (X, 0); GO_IF_INDEXING (go_temp, ADDR); }  \
-      if (GET_CODE (XEXP (X, 0)) == CONST_INT                          \
-         && (TARGET_68020 || (unsigned) INTVAL (XEXP (X, 0)) + 0x80 < 0x100))          \
-       { rtx go_temp = XEXP (X, 1); GO_IF_INDEXING (go_temp, ADDR); } } }
-
-/* ColdFire/5200 does not allow HImode index registers.  */
-#define LEGITIMATE_INDEX_REG_P(X)   \
-  ((GET_CODE (X) == REG && REG_OK_FOR_INDEX_P (X))     \
-   || (! TARGET_COLDFIRE                                       \
-       && GET_CODE (X) == SIGN_EXTEND                  \
-       && GET_CODE (XEXP (X, 0)) == REG                        \
-       && GET_MODE (XEXP (X, 0)) == HImode             \
-       && REG_OK_FOR_INDEX_P (XEXP (X, 0)))            \
-   || (GET_CODE (X) == SUBREG                          \
-       && GET_CODE (SUBREG_REG (X)) == REG             \
-       && REG_OK_FOR_INDEX_P (SUBREG_REG (X))))
-
-#define LEGITIMATE_INDEX_P(X)   \
-   (LEGITIMATE_INDEX_REG_P (X)                         \
-    || ((TARGET_68020 || TARGET_COLDFIRE) && GET_CODE (X) == MULT \
-       && LEGITIMATE_INDEX_REG_P (XEXP (X, 0))         \
-       && GET_CODE (XEXP (X, 1)) == CONST_INT          \
-       && (INTVAL (XEXP (X, 1)) == 2                   \
-           || INTVAL (XEXP (X, 1)) == 4                \
-           || (INTVAL (XEXP (X, 1)) == 8               \
-               && (TARGET_COLDFIRE_FPU || !TARGET_COLDFIRE)))))
-
-/* ColdFire FPU only accepts addressing modes 2-5.  */
-#define GO_IF_COLDFIRE_FPU_LEGITIMATE_ADDRESS(MODE, X, ADDR)           \
-{ if (LEGITIMATE_BASE_REG_P (X)                                                \
-      || ((GET_CODE (X) == PRE_DEC || GET_CODE (X) == POST_INC)                \
-          && LEGITIMATE_BASE_REG_P (XEXP (X, 0)))                      \
-      || ((GET_CODE (X) == PLUS) && LEGITIMATE_BASE_REG_P (XEXP (X, 0))        \
-          && (GET_CODE (XEXP (X, 1)) == CONST_INT)                     \
-          && ((((unsigned) INTVAL (XEXP (X, 1)) + 0x8000) < 0x10000))))        \
-  goto ADDR;}
-
-/* If pic, we accept INDEX+LABEL, which is what do_tablejump makes.  */
 #define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR)                                \
-{ if (TARGET_COLDFIRE_FPU && (GET_MODE_CLASS (MODE) == MODE_FLOAT))    \
+  do                                                                   \
     {                                                                  \
-      GO_IF_COLDFIRE_FPU_LEGITIMATE_ADDRESS (MODE, X, ADDR);           \
+      if (m68k_legitimate_address_p (MODE, X, REG_STRICT_P))           \
+        goto ADDR;                                                     \
     }                                                                  \
-  else                                                                 \
-    {                                                                  \
-      GO_IF_NONINDEXED_ADDRESS (X, ADDR);                              \
-      GO_IF_INDEXED_ADDRESS (X, ADDR);                                 \
-      if (flag_pic && MODE == CASE_VECTOR_MODE && GET_CODE (X) == PLUS \
-         && LEGITIMATE_INDEX_P (XEXP (X, 0))                           \
-         && GET_CODE (XEXP (X, 1)) == LABEL_REF)                       \
-       goto ADDR;                                                      \
-    }}
+  while (0)
 
 /* Don't call memory_address_noforce for the address to fetch
-   the switch offset.  This address is ok as it stands (see above),
+   the switch offset.  This address is ok as it stands,
    but memory_address_noforce would alter it.  */
 #define PIC_CASE_VECTOR_ADDRESS(index) index
 \f