[PATCH] ARM add thumb_legitimize_address

Richard Earnshaw rearnsha@arm.com
Wed Feb 25 17:53:00 GMT 2004


This patch adds a legitimize_address implementation for Thumb code.  I've 
picked some of the values based on the results of the CSiBE tests.

Regression-tested on arm-elf.

R.

2004-02-25  Richard Earnshaw  <rearnsha@arm.com>

	* arm.c (thumb_legitimize_address): New function.
	* arm-protos.h: Prototype it.
	* arm.h (THUMB_LEGITIMIZE_ADDRESS): Define.
	(LEGITIMIZE_ADDRESS): Use it.


-------------- next part --------------
Index: config/arm/arm-protos.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/arm/arm-protos.h,v
retrieving revision 1.62
diff -p -r1.62 arm-protos.h
*** config/arm/arm-protos.h	3 Feb 2004 14:44:10 -0000	1.62
--- config/arm/arm-protos.h	25 Feb 2004 16:59:53 -0000
*************** extern int arm_legitimate_address_p  (en
*** 54,59 ****
--- 54,60 ----
  extern int thumb_legitimate_address_p (enum machine_mode, rtx, int);
  extern int thumb_legitimate_offset_p (enum machine_mode, HOST_WIDE_INT);
  extern rtx arm_legitimize_address (rtx, rtx, enum machine_mode);
+ extern rtx thumb_legitimize_address (rtx, rtx, enum machine_mode);
  extern int arm_const_double_rtx (rtx);
  extern int neg_const_double_rtx_ok_for_fpa (rtx);
  extern enum reg_class vfp_secondary_reload_class (enum machine_mode, rtx);
Index: config/arm/arm.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/arm/arm.c,v
retrieving revision 1.334
diff -p -r1.334 arm.c
*** config/arm/arm.c	25 Feb 2004 12:30:13 -0000	1.334
--- config/arm/arm.c	25 Feb 2004 16:59:54 -0000
*************** arm_legitimize_address (rtx x, rtx orig_
*** 3232,3237 ****
--- 3232,3305 ----
    return x;
  }
  
+ 
+ /* Try machine-dependent ways of modifying an illegitimate Thumb address
+    to be legitimate.  If we find one, return the new, valid address.  */
+ rtx
+ thumb_legitimize_address (rtx x, rtx orig_x, enum machine_mode mode)
+ {
+   if (GET_CODE (x) == PLUS
+       && GET_CODE (XEXP (x, 1)) == CONST_INT
+       && (INTVAL (XEXP (x, 1)) >= 32 * GET_MODE_SIZE (mode)
+ 	  || INTVAL (XEXP (x, 1)) < 0))
+     {
+       rtx xop0 = XEXP (x, 0);
+       rtx xop1 = XEXP (x, 1);
+       HOST_WIDE_INT offset = INTVAL (xop1);
+ 
+       /* Try and fold the offset into a biasing of the base register and
+ 	 then offsetting that.  Don't do this when optimizing for space
+ 	 since it can cause too many CSEs.  */
+       if (optimize_size && offset >= 0
+ 	  && offset < 256 + 31 * GET_MODE_SIZE (mode))
+ 	{
+ 	  HOST_WIDE_INT delta;
+ 
+ 	  if (offset >= 256)
+ 	    delta = offset - (256 - GET_MODE_SIZE (mode));
+ 	  else if (offset < 32 * GET_MODE_SIZE (mode) + 8)
+ 	    delta = 31 * GET_MODE_SIZE (mode);
+ 	  else
+ 	    delta = offset & (~31 * GET_MODE_SIZE (mode));
+ 
+ 	  xop0 = force_operand (plus_constant (xop0, offset - delta),
+ 				NULL_RTX);
+ 	  x = plus_constant (xop0, delta);
+ 	}
+       else if (offset < 0 && offset > -256)
+ 	/* Small negative offsets are best done with a subtract before the
+ 	   dereference, forcing these into a register normally takes two
+ 	   instructions.  */
+ 	x = force_operand (x, NULL_RTX);
+       else
+ 	{
+ 	  /* For the remaining cases, force the constant into a register.  */
+ 	  xop1 = force_reg (SImode, xop1);
+ 	  x = gen_rtx_PLUS (SImode, xop0, xop1);
+ 	}
+     }
+   else if (GET_CODE (x) == PLUS
+ 	   && s_register_operand (XEXP (x, 1), SImode)
+ 	   && !s_register_operand (XEXP (x, 0), SImode))
+     {
+       rtx xop0 = force_operand (XEXP (x, 0), NULL_RTX);
+ 
+       x = gen_rtx_PLUS (SImode, xop0, XEXP (x, 1));
+     }
+ 
+   if (flag_pic)
+     {
+       /* We need to find and carefully transform any SYMBOL and LABEL
+ 	 references; so go back to the original address expression.  */
+       rtx new_x = legitimize_pic_address (orig_x, mode, NULL_RTX);
+ 
+       if (new_x != orig_x)
+ 	x = new_x;
+     }
+ 
+   return x;
+ }
+ 
  
  
  #define REG_OR_SUBREG_REG(X)						\
Index: config/arm/arm.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/arm/arm.h,v
retrieving revision 1.223
diff -p -r1.223 arm.h
*** config/arm/arm.h	19 Feb 2004 10:56:55 -0000	1.223
--- config/arm/arm.h	25 Feb 2004 16:59:54 -0000
*************** typedef struct
*** 2361,2375 ****
  #define ARM_LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN)	\
  do {							\
    X = arm_legitimize_address (X, OLDX, MODE);		\
- 							\
-   if (memory_address_p (MODE, X))			\
-     goto WIN;						\
  } while (0)
  
! #define THUMB_LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN)		\
! do {								\
!   if (flag_pic)							\
!     (X) = legitimize_pic_address (OLDX, MODE, NULL_RTX);	\
  } while (0)
  
  #define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN)		\
--- 2361,2371 ----
  #define ARM_LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN)	\
  do {							\
    X = arm_legitimize_address (X, OLDX, MODE);		\
  } while (0)
  
! #define THUMB_LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN)	\
! do {							\
!   X = thumb_legitimize_address (X, OLDX, MODE);		\
  } while (0)
  
  #define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN)		\
*************** do {							\
*** 2378,2383 ****
--- 2374,2382 ----
      ARM_LEGITIMIZE_ADDRESS (X, OLDX, MODE, WIN);	\
    else							\
      THUMB_LEGITIMIZE_ADDRESS (X, OLDX, MODE, WIN);	\
+ 							\
+   if (memory_address_p (MODE, X))			\
+     goto WIN;						\
  } while (0)
       
  /* Go to LABEL if ADDR (a legitimate address expression)


More information about the Gcc-patches mailing list