ColdFire patches (free of MODE_INDEX_REG_CLASS), and ping

Richard Sandiford richard@codesourcery.com
Thu Mar 1 10:29:00 GMT 2007


As per the MODE_INDEX_REG_CLASS thread, the MODE_INDEX_REG_CLASS
patch has been rejected.  We don't yet have a solution that is
acceptable to both parties (the submitter and approver) so I'll
leave fixing that particular bug to someone who is prepared to do
it Jeff's way.

I've therefore updated the unapplied patches so that they no
longer depend on MODE_INDEX_REG_CLASS.  I think the changes to the
already-approved patches are obvious and don't need to be re-reviewed.
There are two unreviewed patches at this point:

    [ColdFire 27/63] Addressing mode changes and fixes
    http://gcc.gnu.org/ml/gcc-patches/2007-01/msg00784.html

    [ColdFire 57/63] Automatically generate SYSROOT_SUFFIX on uClinux
    http://gcc.gnu.org/ml/gcc-patches/2007-01/msg00814.html

The former patch depended on MODE_INDEX_REG_CLASS and I've attached
the M_I_R_C-free version below.  For avoidance of doubt, the patch is
conceptually independent of M_I_R_C; it is no better or worse than the
current code in terms of triggering the bug that M_I_R_C was designed
to fix.  The dependency was only there because I happened to write the
M_I_R_C patch first.

The latter patch is completely independent of the index handling and
stands as-is.  OK to install?

Richard


gcc/
	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.

Index: gcc/config/m68k/m68k-protos.h
===================================================================
*** gcc/config/m68k/m68k-protos.h	2007-03-01 01:57:27.000000000 -0800
--- gcc/config/m68k/m68k-protos.h	2007-03-01 02:09:46.000000000 -0800
*************** extern int standard_68881_constant_p (rt
*** 50,56 ****
--- 50,61 ----
  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: gcc/config/m68k/m68k.h
===================================================================
*** gcc/config/m68k/m68k.h	2007-03-01 01:57:27.000000000 -0800
--- gcc/config/m68k/m68k.h	2007-03-01 02:09:46.000000000 -0800
*************** #define EXTRA_CONSTRAINT(OP,CODE)			\
*** 535,548 ****
  	  || GET_CODE (OP) == CONST))			\
     :							\
     (CODE) == 'Q'					\
!    ? (GET_CODE (OP) == MEM 				\
!       && GET_CODE (XEXP (OP, 0)) == REG)		\
     :							\
     (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) \
     :							\
     (CODE) == 'W'					\
     ? const_call_operand (OP, VOIDmode)			\
--- 535,544 ----
  	  || GET_CODE (OP) == CONST))			\
     :							\
     (CODE) == 'Q'					\
!    ? m68k_matches_q_p (OP)				\
     :							\
     (CODE) == 'U'					\
!    ? m68k_matches_u_p (OP)				\
     :							\
     (CODE) == 'W'					\
     ? const_call_operand (OP, VOIDmode)			\
*************** #define LEGITIMATE_CONSTANT_P(X)				\
*** 807,959 ****
     && !m68k_illegitimate_symbolic_constant_p (X))
  
  #ifndef REG_OK_STRICT
! #define PCREL_GENERAL_OPERAND_OK 0
  #else
! #define PCREL_GENERAL_OPERAND_OK (TARGET_PCREL)
  #endif
  
! #define LEGITIMATE_PIC_OPERAND_P(X)	\
!   (! symbolic_operand (X, VOIDmode)				\
!    || PCREL_GENERAL_OPERAND_OK)
  
- #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)))
! 
! #else
! 
! /* 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
! 
! /* 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))	\
      {									\
!       GO_IF_COLDFIRE_FPU_LEGITIMATE_ADDRESS (MODE, X, 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;							\
!     }}
  
  /* Don't call memory_address_noforce for the address to fetch
!    the switch offset.  This address is ok as it stands (see above),
     but memory_address_noforce would alter it.  */
  #define PIC_CASE_VECTOR_ADDRESS(index) index
  
--- 803,833 ----
     && !m68k_illegitimate_symbolic_constant_p (X))
  
  #ifndef REG_OK_STRICT
! #define REG_STRICT_P 0
  #else
! #define REG_STRICT_P 1
  #endif
  
! #define LEGITIMATE_PIC_OPERAND_P(X)				\
!   (!symbolic_operand (X, VOIDmode)				\
!    || (TARGET_PCREL && REG_STRICT_P))
  
  #define REG_OK_FOR_BASE_P(X) \
!   m68k_legitimate_base_reg_p (X, REG_STRICT_P)
  
! #define REG_OK_FOR_INDEX_P(X) \
!   m68k_legitimate_index_reg_p (X, REG_STRICT_P)
  
  #define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR)				\
!   do									\
      {									\
!       if (m68k_legitimate_address_p (MODE, X, REG_STRICT_P))		\
!         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,
     but memory_address_noforce would alter it.  */
  #define PIC_CASE_VECTOR_ADDRESS(index) index
  
Index: gcc/config/m68k/m68k.c
===================================================================
*** gcc/config/m68k/m68k.c	2007-03-01 01:57:27.000000000 -0800
--- gcc/config/m68k/m68k.c	2007-03-01 02:10:53.000000000 -0800
*************** struct m68k_frame
*** 103,108 ****
--- 103,129 ----
  /* 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 *);
*************** output_btst (rtx *operands, rtx countop,
*** 1666,1671 ****
--- 1687,1762 ----
    return "btst %0,%1";
  }
  
+ /* 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
*************** m68k_illegitimate_symbolic_constant_p (r
*** 1683,1688 ****
--- 1774,2024 ----
    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
*************** print_operand (FILE *file, rtx op, int l
*** 3271,3535 ****
     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)
! 	{
! 	  if (reg1 == 0)
! 	    reg1 = 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;
  	}
!       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)))
  	{
! 	  breg = reg1;
! 	  ireg = reg2;
  	}
!       if (ireg != 0 && breg == 0 && GET_CODE (addr) == LABEL_REF
! 	  && ! (flag_pic && ireg == pic_offset_table_rtx))
  	{
! 	  int scale = 1;
! 	  if (GET_CODE (ireg) == MULT)
! 	    {
! 	      scale = INTVAL (XEXP (ireg, 1));
! 	      ireg = XEXP (ireg, 0);
! 	    }
! 	  if (GET_CODE (ireg) == SIGN_EXTEND)
  	    {
! 	      ASM_OUTPUT_CASE_FETCH (file,
! 				     CODE_LABEL_NUMBER (XEXP (addr, 0)),
! 				     M68K_REGNAME (REGNO (XEXP (ireg, 0))));
! 	      fprintf (file, "w");
  	    }
  	  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;
! 	}
!       if (ireg != 0 || breg != 0)
! 	{
! 	  int scale = 1;
! 	    
! 	  gcc_assert (breg);
! 	  gcc_assert (flag_pic || !addr || GET_CODE (addr) != LABEL_REF);
! 	    
! 	  if (MOTOROLA)
  	    {
! 	      if (addr != 0)
  		{
! 		  output_addr_const (file, addr);
! 		  if (flag_pic && (breg == pic_offset_table_rtx))
  		    {
  		      fprintf (file, "@GOT");
! 		      if (flag_pic == 1)
  			fprintf (file, ".w");
  		    }
  		}
! 	      fprintf (file, "(%s", M68K_REGNAME (REGNO (breg)));
! 	      if (ireg != 0)
! 		putc (',', file);
  	    }
! 	  else /* !MOTOROLA */
! 	    {
! 	      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 (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)
  	{
! 	  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)");
  	  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);
  	      putc (')', file);
  	    }
- 	  else
- 	    output_addr_const (file, addr);
  	}
-       break;
      }
  }
  
--- 3607,3748 ----
     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) */
  
  void
  print_operand_address (FILE *file, rtx addr)
  {
!   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)
! 	{
! 	  /* (xxx).w or (xxx).l.  */
! 	  if (IN_RANGE (INTVAL (addr), -0x8000, 0x7fff))
! 	    fprintf (file, MOTOROLA ? "%d.w" : "%d:w", (int) INTVAL (addr));
  	  else
! 	    fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (addr));
  	}
!       else if (TARGET_PCREL)
  	{
! 	  /* (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)");
  	}
!       else
  	{
! 	  /* (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] == '.')
  	    {
! 	      putc ('(', file);
! 	      output_addr_const (file, addr);
! 	      putc (')', file);
  	    }
  	  else
! 	    output_addr_const (file, addr);
  	}
!     }
!   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)
  	{
! 	  /* Print the "offset(base" component.  */
! 	  if (labelno >= 0)
! 	    asm_fprintf (file, "%LL%d-%LLI%d.b(%Rpc,", labelno, labelno);
! 	  else
  	    {
! 	      if (address.offset)
  		{
! 		  output_addr_const (file, address.offset);
! 		  if (flag_pic && address.base == pic_offset_table_rtx)
  		    {
  		      fprintf (file, "@GOT");
! 		      if (flag_pic == 1 && TARGET_68020)
  			fprintf (file, ".w");
  		    }
  		}
! 	      putc ('(', file);
! 	      if (address.base)
! 		fputs (M68K_REGNAME (REGNO (address.base)), file);
  	    }
! 	  /* Print the ",index" component, if any.  */
! 	  if (address.index)
  	    {
! 	      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);
  	    }
  	  putc (')', file);
  	}
!       else /* !MOTOROLA */
  	{
! 	  if (!address.offset && !address.index)
! 	    fprintf (file, "%s@", M68K_REGNAME (REGNO (address.base)));
  	  else
  	    {
! 	      /* 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);
  	    }
  	}
      }
  }
  



More information about the Gcc-patches mailing list