aboutsummaryrefslogtreecommitdiff
path: root/gcc/expr.c
diff options
context:
space:
mode:
authorJan Hubicka <jh@suse.cz>2001-03-14 16:38:55 +0100
committerJan Hubicka <hubicka@gcc.gnu.org>2001-03-14 15:38:55 +0000
commit1a06f5fe3fe23768a0336c4a2dc97f42207a3b10 (patch)
tree1c2e5b34b8e26aee9ad132104f2e0aeaee5463b4 /gcc/expr.c
parent2f2aa235bd3f79727d2ebfd4faab2f0a2048ea30 (diff)
downloadgcc-1a06f5fe3fe23768a0336c4a2dc97f42207a3b10.zip
gcc-1a06f5fe3fe23768a0336c4a2dc97f42207a3b10.tar.gz
gcc-1a06f5fe3fe23768a0336c4a2dc97f42207a3b10.tar.bz2
expr.c (emit_move_insn_1): Split push of complex value when no suitable push instruction exist.
* expr.c (emit_move_insn_1): Split push of complex value when no suitable push instruction exist. * i386.md (QImode move/add/shift patterns): Use ANY_QI_REG_P instead of QI_REG_P. From-SVN: r40454
Diffstat (limited to 'gcc/expr.c')
-rw-r--r--gcc/expr.c45
1 files changed, 44 insertions, 1 deletions
diff --git a/gcc/expr.c b/gcc/expr.c
index 382bb23..44900a6 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -2786,12 +2786,55 @@ emit_move_insn_1 (x, y)
/* Don't split destination if it is a stack push. */
int stack = push_operand (x, GET_MODE (x));
+ /* In case we output to the stack, but the size is smaller machine can
+ push exactly, we need to use move instructions. */
+ if (stack
+ && PUSH_ROUNDING (GET_MODE_SIZE (submode)) != GET_MODE_SIZE (submode))
+ {
+ rtx temp;
+ int offset1, offset2;
+
+ /* Do not use anti_adjust_stack, since we don't want to update
+ stack_pointer_delta. */
+ temp = expand_binop (Pmode,
+#ifdef STACK_GROWS_DOWNWARD
+ sub_optab,
+#else
+ add_optab,
+#endif
+ stack_pointer_rtx,
+ GEN_INT
+ (PUSH_ROUNDING (GET_MODE_SIZE (GET_MODE (x)))),
+ stack_pointer_rtx,
+ 0,
+ OPTAB_LIB_WIDEN);
+ if (temp != stack_pointer_rtx)
+ emit_move_insn (stack_pointer_rtx, temp);
+#ifdef STACK_GROWS_DOWNWARD
+ offset1 = 0;
+ offset2 = GET_MODE_SIZE (submode);
+#else
+ offset1 = -PUSH_ROUNDING (GET_MODE_SIZE (GET_MODE (x)));
+ offset2 = (-PUSH_ROUNDING (GET_MODE_SIZE (GET_MODE (x)))
+ + GET_MODE_SIZE (submode));
+#endif
+ emit_move_insn (change_address (x, submode,
+ gen_rtx_PLUS (Pmode,
+ stack_pointer_rtx,
+ GEN_INT (offset1))),
+ gen_realpart (submode, y));
+ emit_move_insn (change_address (x, submode,
+ gen_rtx_PLUS (Pmode,
+ stack_pointer_rtx,
+ GEN_INT (offset2))),
+ gen_imagpart (submode, y));
+ }
/* If this is a stack, push the highpart first, so it
will be in the argument order.
In that case, change_address is used only to convert
the mode, not to change the address. */
- if (stack)
+ else if (stack)
{
/* Note that the real part always precedes the imag part in memory
regardless of machine's endianness. */