aboutsummaryrefslogtreecommitdiff
path: root/gcc/rtlanal.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/rtlanal.c')
-rw-r--r--gcc/rtlanal.c39
1 files changed, 25 insertions, 14 deletions
diff --git a/gcc/rtlanal.c b/gcc/rtlanal.c
index 44a6c6c..4dda178 100644
--- a/gcc/rtlanal.c
+++ b/gcc/rtlanal.c
@@ -3187,48 +3187,59 @@ loc_mentioned_in_p (rtx *loc, rtx in)
return 0;
}
-/* Given a subreg X, return the bit offset where the subreg begins
- (counting from the least significant bit of the reg). */
+/* Helper function for subreg_lsb. Given a subreg's OUTER_MODE, INNER_MODE,
+ and SUBREG_BYTE, return the bit offset where the subreg begins
+ (counting from the least significant bit of the operand). */
unsigned int
-subreg_lsb (rtx x)
+subreg_lsb_1 (enum machine_mode outer_mode,
+ enum machine_mode inner_mode,
+ unsigned int subreg_byte)
{
- 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))
+ if (GET_MODE_BITSIZE (outer_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))
+ if ((subreg_byte % UNITS_PER_WORD
+ + GET_MODE_SIZE (outer_mode)) > UNITS_PER_WORD
+ && (subreg_byte % UNITS_PER_WORD
+ || GET_MODE_SIZE (outer_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;
+ - (subreg_byte + GET_MODE_SIZE (outer_mode))) / UNITS_PER_WORD;
else
- word = SUBREG_BYTE (x) / UNITS_PER_WORD;
+ word = subreg_byte / 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;
+ - (subreg_byte + GET_MODE_SIZE (outer_mode))) % UNITS_PER_WORD;
else
- byte = SUBREG_BYTE (x) % UNITS_PER_WORD;
+ byte = subreg_byte % UNITS_PER_WORD;
bitpos += byte * BITS_PER_UNIT;
return bitpos;
}
+/* 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 (rtx x)
+{
+ return subreg_lsb_1 (GET_MODE (x), GET_MODE (SUBREG_REG (x)),
+ SUBREG_BYTE (x));
+}
+
/* 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.