summaryrefslogtreecommitdiff
path: root/gcc/expmed.c
diff options
context:
space:
mode:
authorbstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4>2008-03-25 13:36:19 +0000
committerbstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4>2008-03-25 13:36:19 +0000
commite0f97db9eb84d304602eb35815ba9d188cd69e46 (patch)
tree84bddb2ec09b31241a95c5b1ded74d60cdff6239 /gcc/expmed.c
parentf80df6b2af919960ad08a6f1901ddebb654f981b (diff)
downloadgcc-e0f97db9eb84d304602eb35815ba9d188cd69e46.tar.gz
2008-03-24 Basile Starynkevitch <basile@starynkevitch.net>
MELT branch merged with trunk r133512 git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/melt-branch@133515 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/expmed.c')
-rw-r--r--gcc/expmed.c60
1 files changed, 60 insertions, 0 deletions
diff --git a/gcc/expmed.c b/gcc/expmed.c
index 04071d375ed..2f2e3cc657d 100644
--- a/gcc/expmed.c
+++ b/gcc/expmed.c
@@ -2098,6 +2098,66 @@ extract_split_bit_field (rtx op0, unsigned HOST_WIDE_INT bitsize,
NULL_RTX, 0);
}
+/* Try to read the low bits of SRC as an rvalue of mode MODE, preserving
+ the bit pattern. SRC_MODE is the mode of SRC; if this is smaller than
+ MODE, fill the upper bits with zeros. Fail if the layout of either
+ mode is unknown (as for CC modes) or if the extraction would involve
+ unprofitable mode punning. Return the value on success, otherwise
+ return null.
+
+ This is different from gen_lowpart* in these respects:
+
+ - the returned value must always be considered an rvalue
+
+ - when MODE is wider than SRC_MODE, the extraction involves
+ a zero extension
+
+ - when MODE is smaller than SRC_MODE, the extraction involves
+ a truncation (and is thus subject to TRULY_NOOP_TRUNCATION).
+
+ In other words, this routine performs a computation, whereas the
+ gen_lowpart* routines are conceptually lvalue or rvalue subreg
+ operations. */
+
+rtx
+extract_low_bits (enum machine_mode mode, enum machine_mode src_mode, rtx src)
+{
+ enum machine_mode int_mode, src_int_mode;
+
+ if (mode == src_mode)
+ return src;
+
+ if (CONSTANT_P (src))
+ return simplify_gen_subreg (mode, src, src_mode,
+ subreg_lowpart_offset (mode, src_mode));
+
+ if (GET_MODE_CLASS (mode) == MODE_CC || GET_MODE_CLASS (src_mode) == MODE_CC)
+ return NULL_RTX;
+
+ if (GET_MODE_BITSIZE (mode) == GET_MODE_BITSIZE (src_mode)
+ && MODES_TIEABLE_P (mode, src_mode))
+ {
+ rtx x = gen_lowpart_common (mode, src);
+ if (x)
+ return x;
+ }
+
+ src_int_mode = int_mode_for_mode (src_mode);
+ int_mode = int_mode_for_mode (mode);
+ if (src_int_mode == BLKmode || int_mode == BLKmode)
+ return NULL_RTX;
+
+ if (!MODES_TIEABLE_P (src_int_mode, src_mode))
+ return NULL_RTX;
+ if (!MODES_TIEABLE_P (int_mode, mode))
+ return NULL_RTX;
+
+ src = gen_lowpart (src_int_mode, src);
+ src = convert_modes (int_mode, src_int_mode, src, true);
+ src = gen_lowpart (mode, src);
+ return src;
+}
+
/* Add INC into TARGET. */
void