This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Question on ARM legitimate address for DImode


Hi,

While working on a bug, I found some code in ARM port that I don't understand.

In ARM_LEGITIMIZE_RELOAD_ADDRESS and arm_legitimize_address, we allow a very small offset for DImode addressing.

In ARM_LEGITIMIZE_RELOAD_ADDRESS:

if (MODE == DImode || (MODE == DFmode && TARGET_SOFT_FLOAT))     \
  low = ((val & 0xf) ^ 0x8) - 0x8;                               \

In arm_legitimize_address

  /* VFP addressing modes actually allow greater offsets, but for
     now we just stick with the lowest common denominator.  */
  if (mode == DImode
      || ((TARGET_SOFT_FLOAT || TARGET_VFP) && mode == DFmode))
    {
      low_n = n & 0x0f;
      n &= ~0x0f;
      if (low_n > 4)
        {
          n += 16;
          low_n -= 16;
        }
    }

AFAIK, we could use two LDRs, or one LDRD, or one VLDR to access DImode in memory when the address is in the form of (REG + CONST_INT). The offset ranges for these three cases are:

LDR  -4095,4091
LDRD -255,255
VLDR -1020,1020 && (ADDR & 3) == 0

so the lowest common denominator is

-1020,1020 && (ADDR & 3) == 0 if ! TARGET_LDRD
 -255,255  && (ADDR & 3) == 0 if TARGET_LDRD

Both are much larger than what we have now in the ARM port.

Did I miss some other cases? That two pieces of code are rather old (more than 15 years). The main code was added by

svn: revision 7536 by erich, Thu Jun 23 16:02:41 1994 UTC in arm.h
git: fac435147512513c1b8fa55bee061c8e3a767ba9
log: (LEGITIMIZE_ADDRESS): Push constants that will never be legitimate -- symbols
and labels -- into registers. Handle DImode better.


I checked out that revision to take a look but didn't find an obvious reason for such small index range. Did I miss something tricky?

If there is nothing I missed, I'd like to propose the attached patch.


Regards, -- Jie Zhang

Index: config/arm/arm.c
===================================================================
--- config/arm/arm.c	(revision 168085)
+++ config/arm/arm.c	(working copy)
@@ -6221,13 +6221,9 @@ arm_legitimize_address (rtx x, rtx orig_
 	  if (mode == DImode
 	      || ((TARGET_SOFT_FLOAT || TARGET_VFP) && mode == DFmode))
 	    {
-	      low_n = n & 0x0f;
-	      n &= ~0x0f;
-	      if (low_n > 4)
-		{
-		  n += 16;
-		  low_n -= 16;
-		}
+	      HOST_WIDE_INT mask = (TARGET_LDRD ? 0xfc : 0x3fc);
+	      low_n = (n >= 0 ? (n & mask) : -((-n) & mask));
+	      n -= low_n;
 	    }
 	  else
 	    {
Index: config/arm/arm.h
===================================================================
--- config/arm/arm.h	(revision 168085)
+++ config/arm/arm.h	(working copy)
@@ -1283,7 +1283,12 @@ enum reg_class
 	  HOST_WIDE_INT low, high;					   \
 									   \
 	  if (MODE == DImode || (MODE == DFmode && TARGET_SOFT_FLOAT))	   \
-	    low = ((val & 0xf) ^ 0x8) - 0x8;				   \
+	    {								   \
+	      /* VFP addressing modes actually allow greater offsets, but for \
+		 now we just stick with the lowest common denominator.  */ \
+	      HOST_WIDE_INT mask = (TARGET_LDRD ? 0xfc : 0x3fc);	   \
+	      low = (val >= 0 ? (val & mask) : -((-val) & mask));          \
+	    }								   \
 	  else if (TARGET_MAVERICK && TARGET_HARD_FLOAT)		   \
 	    /* Need to be careful, -256 is not a valid offset.  */	   \
 	    low = val >= 0 ? (val & 0xff) : -((-val) & 0xff);		   \

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]