aboutsummaryrefslogtreecommitdiff
path: root/gcc/emit-rtl.c
diff options
context:
space:
mode:
authorRichard Stallman <rms@gnu.org>1992-09-09 06:43:57 +0000
committerRichard Stallman <rms@gnu.org>1992-09-09 06:43:57 +0000
commitccba022bcbcc0c36a02c9176fb7517731848aff0 (patch)
tree364fa1346917c5be27189f2b0c961bdc638b09b6 /gcc/emit-rtl.c
parent89b48889f143b299ad4ee218c740594e8f71406e (diff)
downloadgcc-ccba022bcbcc0c36a02c9176fb7517731848aff0.zip
gcc-ccba022bcbcc0c36a02c9176fb7517731848aff0.tar.gz
gcc-ccba022bcbcc0c36a02c9176fb7517731848aff0.tar.bz2
(gen_highpart): New function.
From-SVN: r2084
Diffstat (limited to 'gcc/emit-rtl.c')
-rw-r--r--gcc/emit-rtl.c65
1 files changed, 65 insertions, 0 deletions
diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c
index b7c66ab..2f2cdcc 100644
--- a/gcc/emit-rtl.c
+++ b/gcc/emit-rtl.c
@@ -692,6 +692,71 @@ gen_lowpart (mode, x)
abort ();
}
+/* Like `gen_lowpart', but refer to the most significant part.
+ This is used to access the imaginary part of a complex number. */
+
+rtx
+gen_highpart (mode, x)
+ enum machine_mode mode;
+ register rtx x;
+{
+ /* This case loses if X is a subreg. To catch bugs early,
+ complain if an invalid MODE is used even in other cases. */
+ if (GET_MODE_SIZE (mode) > UNITS_PER_WORD
+ && GET_MODE_SIZE (mode) != GET_MODE_UNIT_SIZE (GET_MODE (x)))
+ abort ();
+ if (GET_CODE (x) == CONST_DOUBLE
+#if !(TARGET_FLOAT_FORMAT != HOST_FLOAT_FORMAT || defined(REAL_IS_NOT_DOUBLE))
+ && GET_MODE_CLASS (GET_MODE (x)) != MODE_FLOAT
+#endif
+ )
+ return gen_rtx (CONST_INT, VOIDmode,
+ CONST_DOUBLE_HIGH (x) & GET_MODE_MASK (mode));
+ else if (GET_CODE (x) == CONST_INT)
+ return const0_rtx;
+ else if (GET_CODE (x) == MEM)
+ {
+ register int offset = 0;
+#if !WORDS_BIG_ENDIAN
+ offset = (MAX (GET_MODE_SIZE (GET_MODE (x)), UNITS_PER_WORD)
+ - MAX (GET_MODE_SIZE (mode), UNITS_PER_WORD));
+#endif
+#if !BYTES_BIG_ENDIAN
+ if (GET_MODE_SIZE (mode) < UNITS_PER_WORD)
+ offset -= (GET_MODE_SIZE (mode)
+ - MIN (UNITS_PER_WORD,
+ GET_MODE_SIZE (GET_MODE (x))));
+#endif
+ return change_address (x, mode, plus_constant (XEXP (x, 0), offset));
+ }
+ else if (GET_CODE (x) == SUBREG)
+ {
+ /* The only time this should occur is when we are looking at a
+ multi-word item with a SUBREG whose mode is the same as that of the
+ item. It isn't clear what we would do if it wasn't. */
+ if (SUBREG_WORD (x) != 0)
+ abort ();
+ return gen_highpart (mode, SUBREG_REG (x));
+ }
+ else if (GET_CODE (x) == REG)
+ {
+ int word = 0;
+
+#if !WORDS_BIG_ENDIAN
+ if (GET_MODE_SIZE (GET_MODE (x)) > UNITS_PER_WORD)
+ word = ((GET_MODE_SIZE (GET_MODE (x))
+ - MAX (GET_MODE_SIZE (mode), UNITS_PER_WORD))
+ / UNITS_PER_WORD);
+#endif
+ if (REGNO (x) < FIRST_PSEUDO_REGISTER)
+ return gen_rtx (REG, mode, REGNO (x) + word);
+ else
+ return gen_rtx (SUBREG, mode, x, word);
+ }
+ else
+ abort ();
+}
+
/* Return 1 iff X, assumed to be a SUBREG,
refers to the least significant part of its containing reg.
If X is not a SUBREG, always return 1 (it is its own low part!). */