diff mbox

C6X port 6/11: REG_WORDS_BIG_ENDIAN

Message ID 4DC95C46.4040809@codesourcery.com
State New
Headers show

Commit Message

Bernd Schmidt May 10, 2011, 3:39 p.m. UTC
C6X has little- and big-endian modes, but in both modes, registers are
in little-endian order. This patch adds code to support this model in gcc.


Bernd
* reload.c (operands_match_p): Take it into account.
	(reload_adjust_reg_for_mode): Likewise.
	* rtlanal.c (subreg_get_info): Likewise.
	* defaults.h (REG_WORDS_BIG_ENDIAN): Provide a default.
	* doc/tm.texi.in (WORDS_BIG_ENDIAN): Mention REG_WORDS_BIG_ENDIAN.
	(REG_WORDS_BIG_ENDIAN): Document.
	* doc/tm.texi: Regenerate.
diff mbox

Patch

Index: doc/tm.texi
===================================================================
--- doc/tm.texi.orig
+++ doc/tm.texi
@@ -863,11 +863,18 @@  word has the lowest number.  This macro
 @defmac WORDS_BIG_ENDIAN
 Define this macro to have the value 1 if, in a multiword object, the
 most significant word has the lowest number.  This applies to both
-memory locations and registers; GCC fundamentally assumes that the
-order of words in memory is the same as the order in registers.  This
+memory locations and registers; see @code{REG_WORDS_BIG_ENDIAN} if the
+order of words in memory is not the same as the order in registers.  This
 macro need not be a constant.
 @end defmac
 
+@defmac REG_WORDS_BIG_ENDIAN
+On some machines, the order of words in a multiword object differs between
+registers in memory.  In such a situation, define this macro to describe
+the order of words in a register.  The macro @code{WORDS_BIG_ENDIAN} controls
+the order of words in memory.
+@end defmac
+
 @defmac FLOAT_WORDS_BIG_ENDIAN
 Define this macro to have the value 1 if @code{DFmode}, @code{XFmode} or
 @code{TFmode} floating point numbers are stored in memory with the word
Index: doc/tm.texi.in
===================================================================
--- doc/tm.texi.in.orig
+++ doc/tm.texi.in
@@ -853,11 +853,18 @@  word has the lowest number.  This macro
 @defmac WORDS_BIG_ENDIAN
 Define this macro to have the value 1 if, in a multiword object, the
 most significant word has the lowest number.  This applies to both
-memory locations and registers; GCC fundamentally assumes that the
-order of words in memory is the same as the order in registers.  This
+memory locations and registers; see @code{REG_WORDS_BIG_ENDIAN} if the
+order of words in memory is not the same as the order in registers.  This
 macro need not be a constant.
 @end defmac
 
+@defmac REG_WORDS_BIG_ENDIAN
+On some machines, the order of words in a multiword object differs between
+registers in memory.  In such a situation, define this macro to describe
+the order of words in a register.  The macro @code{WORDS_BIG_ENDIAN} controls
+the order of words in memory.
+@end defmac
+
 @defmac FLOAT_WORDS_BIG_ENDIAN
 Define this macro to have the value 1 if @code{DFmode}, @code{XFmode} or
 @code{TFmode} floating point numbers are stored in memory with the word
Index: defaults.h
===================================================================
--- defaults.h.orig
+++ defaults.h
@@ -882,6 +882,10 @@  see the files COPYING3 and COPYING.RUNTI
 #define FLOAT_WORDS_BIG_ENDIAN WORDS_BIG_ENDIAN
 #endif
 
+#ifndef REG_WORDS_BIG_ENDIAN
+#define REG_WORDS_BIG_ENDIAN WORDS_BIG_ENDIAN
+#endif
+
 #ifdef TARGET_FLT_EVAL_METHOD
 #define TARGET_FLT_EVAL_METHOD_NON_DEFAULT 1
 #else
Index: reload.c
===================================================================
--- reload.c.orig
+++ reload.c
@@ -2217,15 +2217,15 @@  operands_match_p (rtx x, rtx y)
       else
 	j = REGNO (y);
 
-      /* On a WORDS_BIG_ENDIAN machine, point to the last register of a
+      /* On a REG_WORDS_BIG_ENDIAN machine, point to the last register of a
 	 multiple hard register group of scalar integer registers, so that
 	 for example (reg:DI 0) and (reg:SI 1) will be considered the same
 	 register.  */
-      if (WORDS_BIG_ENDIAN && GET_MODE_SIZE (GET_MODE (x)) > UNITS_PER_WORD
+      if (REG_WORDS_BIG_ENDIAN && GET_MODE_SIZE (GET_MODE (x)) > UNITS_PER_WORD
 	  && SCALAR_INT_MODE_P (GET_MODE (x))
 	  && i < FIRST_PSEUDO_REGISTER)
 	i += hard_regno_nregs[i][GET_MODE (x)] - 1;
-      if (WORDS_BIG_ENDIAN && GET_MODE_SIZE (GET_MODE (y)) > UNITS_PER_WORD
+      if (REG_WORDS_BIG_ENDIAN && GET_MODE_SIZE (GET_MODE (y)) > UNITS_PER_WORD
 	  && SCALAR_INT_MODE_P (GET_MODE (y))
 	  && j < FIRST_PSEUDO_REGISTER)
 	j += hard_regno_nregs[j][GET_MODE (y)] - 1;
@@ -7305,7 +7305,7 @@  reload_adjust_reg_for_mode (rtx reloadre
 
   regno = REGNO (reloadreg);
 
-  if (WORDS_BIG_ENDIAN)
+  if (REG_WORDS_BIG_ENDIAN)
     regno += (int) hard_regno_nregs[regno][GET_MODE (reloadreg)]
       - (int) hard_regno_nregs[regno][mode];
 
Index: rtlanal.c
===================================================================
--- rtlanal.c.orig
+++ rtlanal.c
@@ -3289,7 +3289,7 @@  subreg_get_info (unsigned int xregno, en
 	 return a negative offset so that we find the proper highpart
 	 of the register.  */
       if (GET_MODE_SIZE (ymode) > UNITS_PER_WORD
-	  ? WORDS_BIG_ENDIAN : BYTES_BIG_ENDIAN)
+	  ? REG_WORDS_BIG_ENDIAN : BYTES_BIG_ENDIAN)
 	info->offset = nregs_xmode - nregs_ymode;
       else
 	info->offset = 0;
@@ -3344,6 +3344,15 @@  subreg_get_info (unsigned int xregno, en
   gcc_assert ((GET_MODE_SIZE (xmode) % GET_MODE_SIZE (ymode)) == 0);
   gcc_assert ((nregs_xmode % nregs_ymode) == 0);
 
+  if (WORDS_BIG_ENDIAN != REG_WORDS_BIG_ENDIAN
+      && GET_MODE_SIZE (xmode) > UNITS_PER_WORD)
+    {
+      HOST_WIDE_INT xsize = GET_MODE_SIZE (xmode);
+      HOST_WIDE_INT ysize = GET_MODE_SIZE (ymode);
+      HOST_WIDE_INT off_low = offset & (ysize - 1);
+      HOST_WIDE_INT off_high = offset & ~(ysize - 1);
+      offset = (xsize - ysize - off_high) | off_low;
+    }
   /* The XMODE value can be seen as a vector of NREGS_XMODE
      values.  The subreg must represent a lowpart of given field.
      Compute what field it is.  */