rtl.h (subreg_lsb): Declare.
authorJohn Wehle <john@feith.com>
Sat, 22 Dec 2001 17:23:52 +0000 (17:23 +0000)
committerJohn Wehle <wehle@gcc.gnu.org>
Sat, 22 Dec 2001 17:23:52 +0000 (17:23 +0000)
* rtl.h (subreg_lsb): Declare.
* rtlanal.c (subreg_lsb): Implement.

From-SVN: r48272

gcc/ChangeLog
gcc/rtl.h
gcc/rtlanal.c

index bcc8012..99f7c5b 100644 (file)
@@ -1,3 +1,8 @@
+Sat Dec 22 12:20:20 EST 2001  John Wehle  (john@feith.com)
+
+       * rtl.h (subreg_lsb): Declare.
+       * rtlanal.c (subreg_lsb): Implement.
+
 Sat Dec 22 08:59:50 2001  Richard Kenner  <kenner@vlsi1.ultra.nyu.edu>
 
        * predict.c: Reformatting and minor cleanups.
index ff29333..e4360d6 100644 (file)
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -818,6 +818,7 @@ extern const char * const note_insn_name[NOTE_INSN_MAX - NOTE_INSN_BIAS];
 #define SUBREG_BYTE(RTX) XCUINT(RTX, 1, SUBREG)
 
 /* in rtlanal.c */
+extern unsigned int subreg_lsb         PARAMS ((rtx));
 extern unsigned int subreg_regno_offset        PARAMS ((unsigned int, 
                                                         enum machine_mode, 
                                                         unsigned int, 
index c2de74b..b6056de 100644 (file)
@@ -2881,6 +2881,49 @@ loc_mentioned_in_p (loc, in)
   return 0;
 }
 
+/* Given a subreg X, return the bit offset where the subreg begins
+   (counting from the least significant bit of the reg).  */
+
+unsigned int
+subreg_lsb (x)
+     rtx x;
+{
+  enum machine_mode inner_mode = GET_MODE (SUBREG_REG (x));
+  enum machine_mode mode = GET_MODE (x);
+  unsigned int bitpos;
+  unsigned int byte;
+  unsigned int word;
+
+  /* A paradoxical subreg begins at bit position 0.  */
+  if (GET_MODE_BITSIZE (mode) > GET_MODE_BITSIZE (inner_mode))
+    return 0;
+
+  if (WORDS_BIG_ENDIAN != BYTES_BIG_ENDIAN)
+    /* If the subreg crosses a word boundary ensure that
+       it also begins and ends on a word boundary.  */
+    if ((SUBREG_BYTE (x) % UNITS_PER_WORD
+        + GET_MODE_SIZE (mode)) > UNITS_PER_WORD
+       && (SUBREG_BYTE (x) % UNITS_PER_WORD
+           || GET_MODE_SIZE (mode) % UNITS_PER_WORD))
+       abort ();
+
+  if (WORDS_BIG_ENDIAN)
+    word = (GET_MODE_SIZE (inner_mode)
+           - (SUBREG_BYTE (x) + GET_MODE_SIZE (mode))) / UNITS_PER_WORD;
+  else
+    word = SUBREG_BYTE (x) / UNITS_PER_WORD;
+  bitpos = word * BITS_PER_WORD;
+
+  if (BYTES_BIG_ENDIAN)
+    byte = (GET_MODE_SIZE (inner_mode)
+           - (SUBREG_BYTE (x) + GET_MODE_SIZE (mode))) % UNITS_PER_WORD;
+  else
+    byte = SUBREG_BYTE (x) % UNITS_PER_WORD;
+  bitpos += byte * BITS_PER_UNIT;
+
+  return bitpos;
+}
+
 /* This function returns the regno offset of a subreg expression.
    xregno - A regno of an inner hard subreg_reg (or what will become one).
    xmode  - The mode of xregno.