/* Convert tree expression to rtl instructions, for GNU compiler.
Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- 2000, 2001 Free Software Foundation, Inc.
+ 2000, 2001, 2002 Free Software Foundation, Inc.
This file is part of GCC.
if ((code = can_extend_p (to_mode, from_mode, unsignedp))
!= CODE_FOR_nothing)
{
+ if (flag_force_mem)
+ from = force_not_mem (from);
+
emit_unop_insn (code, to, from, equiv_code);
return;
}
from1 = adjust_address (data->from, mode, data->offset);
if (HAVE_PRE_DECREMENT && data->explicit_inc_to < 0)
- emit_insn (gen_add2_insn (data->to_addr, GEN_INT (-size)));
+ emit_insn (gen_add2_insn (data->to_addr,
+ GEN_INT (-(HOST_WIDE_INT)size)));
if (HAVE_PRE_DECREMENT && data->explicit_inc_from < 0)
- emit_insn (gen_add2_insn (data->from_addr, GEN_INT (-size)));
+ emit_insn (gen_add2_insn (data->from_addr,
+ GEN_INT (-(HOST_WIDE_INT)size)));
if (data->to)
emit_insn ((*genfun) (to1, from1));
enum machine_mode mode = GET_MODE (x);
enum machine_mode submode;
enum mode_class class = GET_MODE_CLASS (mode);
- unsigned int i;
if ((unsigned int) mode >= (unsigned int) MAX_MACHINE_MODE)
abort ();
/* 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))
+ && (PUSH_ROUNDING (GET_MODE_SIZE (submode))
+ != GET_MODE_SIZE (submode)))
{
rtx temp;
- int offset1, offset2;
+ HOST_WIDE_INT offset1, offset2;
/* Do not use anti_adjust_stack, since we don't want to update
stack_pointer_delta. */
#endif
stack_pointer_rtx,
GEN_INT
- (PUSH_ROUNDING (GET_MODE_SIZE (GET_MODE (x)))),
- stack_pointer_rtx,
- 0,
- OPTAB_LIB_WIDEN);
+ (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);
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,
if (GET_MODE_BITSIZE (mode) < 2 * BITS_PER_WORD
&& (reload_in_progress | reload_completed) == 0)
{
- int packed_dest_p = (REG_P (x) && REGNO (x) < FIRST_PSEUDO_REGISTER);
- int packed_src_p = (REG_P (y) && REGNO (y) < FIRST_PSEUDO_REGISTER);
+ int packed_dest_p
+ = (REG_P (x) && REGNO (x) < FIRST_PSEUDO_REGISTER);
+ int packed_src_p
+ = (REG_P (y) && REGNO (y) < FIRST_PSEUDO_REGISTER);
if (packed_dest_p || packed_src_p)
{
if (packed_dest_p)
{
rtx sreg = gen_rtx_SUBREG (reg_mode, x, 0);
+
emit_move_insn_1 (cmem, y);
return emit_move_insn_1 (sreg, mem);
}
else
{
rtx sreg = gen_rtx_SUBREG (reg_mode, y, 0);
+
emit_move_insn_1 (mem, sreg);
return emit_move_insn_1 (x, cmem);
}
&& ! (reload_in_progress || reload_completed)
&& (GET_CODE (realpart_x) == SUBREG
|| GET_CODE (imagpart_x) == SUBREG))
- {
- emit_insn (gen_rtx_CLOBBER (VOIDmode, x));
- }
+ emit_insn (gen_rtx_CLOBBER (VOIDmode, x));
emit_insn (GEN_FCN (mov_optab->handlers[(int) submode].insn_code)
(realpart_x, realpart_y));
rtx last_insn = 0;
rtx seq, inner;
int need_clobber;
+ int i;
#ifdef PUSH_ROUNDING
#endif
stack_pointer_rtx,
GEN_INT
- (PUSH_ROUNDING (GET_MODE_SIZE (GET_MODE (x)))),
- stack_pointer_rtx,
- 0,
- OPTAB_LIB_WIDEN);
+ (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);
code = GET_CODE (XEXP (x, 0));
+
/* Just hope that small offsets off SP are OK. */
if (code == POST_INC)
temp = gen_rtx_PLUS (Pmode, stack_pointer_rtx,
- GEN_INT (-(HOST_WIDE_INT)
- GET_MODE_SIZE (GET_MODE (x))));
+ GEN_INT (-((HOST_WIDE_INT)
+ GET_MODE_SIZE (GET_MODE (x)))));
else if (code == POST_DEC)
temp = gen_rtx_PLUS (Pmode, stack_pointer_rtx,
GEN_INT (GET_MODE_SIZE (GET_MODE (x))));
if (x != y
&& ! (reload_in_progress || reload_completed)
&& need_clobber != 0)
- {
- emit_insn (gen_rtx_CLOBBER (VOIDmode, x));
- }
+ emit_insn (gen_rtx_CLOBBER (VOIDmode, x));
emit_insn (seq);
if (icode != CODE_FOR_nothing)
{
if (((pred = insn_data[(int) icode].operand[0].predicate)
- && !((*pred) (x, mode))))
+ && !((*pred) (x, mode))))
x = force_reg (mode, x);
emit_insn (GEN_FCN (icode) (x));
return;
{
#ifdef STACK_GROWS_DOWNWARD
dest_addr = gen_rtx_PLUS (Pmode, stack_pointer_rtx,
- GEN_INT (-(HOST_WIDE_INT)rounded_size));
+ GEN_INT (-(HOST_WIDE_INT) rounded_size));
#else
dest_addr = gen_rtx_PLUS (Pmode, stack_pointer_rtx,
GEN_INT (rounded_size));
RTX_UNCHANGING_P (to_rtx) = 1;
}
- if (! can_address_p (to))
+ if (GET_CODE (to_rtx) == MEM && ! can_address_p (to))
{
if (to_rtx == orig_to_rtx)
to_rtx = copy_rtx (to_rtx);
target. Otherwise, the caller might get confused by a result whose
mode is larger than expected. */
- if (want_value && GET_MODE (temp) != GET_MODE (target)
- && GET_MODE (temp) != VOIDmode)
+ if (want_value && GET_MODE (temp) != GET_MODE (target))
{
- temp = gen_lowpart_SUBREG (GET_MODE (target), temp);
- SUBREG_PROMOTED_VAR_P (temp) = 1;
- SUBREG_PROMOTED_UNSIGNED_P (temp)
- = SUBREG_PROMOTED_UNSIGNED_P (target);
+ if (GET_MODE (temp) != VOIDmode)
+ {
+ temp = gen_lowpart_SUBREG (GET_MODE (target), temp);
+ SUBREG_PROMOTED_VAR_P (temp) = 1;
+ SUBREG_PROMOTED_UNSIGNED_P (temp)
+ = SUBREG_PROMOTED_UNSIGNED_P (target);
+ }
+ else
+ temp = convert_modes (GET_MODE (target),
+ GET_MODE (SUBREG_REG (target)),
+ temp, SUBREG_PROMOTED_UNSIGNED_P (target));
}
return want_value ? temp : NULL_RTX;
= assign_temp
(build_qualified_type (type, TYPE_QUALS (type) | TYPE_QUAL_CONST),
0, 1, 1);
- rtx blk_object = copy_rtx (object);
-
- PUT_MODE (blk_object, BLKmode);
+ rtx blk_object = adjust_address (object, BLKmode, 0);
if (bitsize != (HOST_WIDE_INT) GET_MODE_BITSIZE (GET_MODE (target)))
emit_move_insn (object, target);
else if (host_integerp (exp, 0))
{
c0 = tree_low_cst (exp, 0);
- return c0 < 0 ? - c0 : c0;
+ c0 = c0 < 0 ? - c0 : c0;
+ return c0 & -c0;
}
break;
set_mem_attributes (value, exp, 1);
SET_DECL_RTL (exp, value);
}
- }
+ }
/* ... fall through ... */
case LABELED_BLOCK_EXPR:
if (LABELED_BLOCK_BODY (exp))
- expand_expr_stmt (LABELED_BLOCK_BODY (exp));
+ expand_expr_stmt_value (LABELED_BLOCK_BODY (exp), 0, 1);
/* Should perhaps use expand_label, but this is simpler and safer. */
do_pending_stack_adjust ();
emit_label (label_rtx (LABELED_BLOCK_LABEL (exp)));
case LOOP_EXPR:
push_temp_slots ();
expand_start_loop (1);
- expand_expr_stmt (TREE_OPERAND (exp, 0));
+ expand_expr_stmt_value (TREE_OPERAND (exp, 0), 0, 1);
expand_end_loop ();
pop_temp_slots ();
(HOST_WIDE_INT) GET_MODE_SIZE (TYPE_MODE (type)));
rtx new = assign_stack_temp_for_type (TYPE_MODE (type),
temp_size, 0, type);
- rtx new_with_op0_mode = copy_rtx (new);
+ rtx new_with_op0_mode = adjust_address (new, GET_MODE (op0), 0);
if (TREE_ADDRESSABLE (exp))
abort ();
- PUT_MODE (new_with_op0_mode, GET_MODE (op0));
if (GET_MODE (op0) == BLKmode)
emit_block_move (new_with_op0_mode, op0,
GEN_INT (GET_MODE_SIZE (TYPE_MODE (type))));
op0 = new;
}
- PUT_MODE (op0, TYPE_MODE (type));
+ op0 = adjust_address (op0, TYPE_MODE (type), 0);
}
return op0;
|| GET_CODE (op0) == CONCAT || GET_CODE (op0) == ADDRESSOF
|| GET_CODE (op0) == PARALLEL)
{
- /* If this object is in a register, it must can't be BLKmode. */
- tree inner_type = TREE_TYPE (TREE_OPERAND (exp, 0));
- tree nt = build_qualified_type (inner_type,
- (TYPE_QUALS (inner_type)
- | TYPE_QUAL_CONST));
- rtx memloc = assign_temp (nt, 1, 1, 1);
-
- if (GET_CODE (op0) == PARALLEL)
- /* Handle calls that pass values in multiple non-contiguous
- locations. The Irix 6 ABI has examples of this. */
- emit_group_store (memloc, op0, int_size_in_bytes (inner_type));
+ /* If the operand is a SAVE_EXPR, we can deal with this by
+ forcing the SAVE_EXPR into memory. */
+ if (TREE_CODE (TREE_OPERAND (exp, 0)) == SAVE_EXPR)
+ {
+ put_var_into_stack (TREE_OPERAND (exp, 0));
+ op0 = SAVE_EXPR_RTL (TREE_OPERAND (exp, 0));
+ }
else
- emit_move_insn (memloc, op0);
-
- op0 = memloc;
+ {
+ /* If this object is in a register, it can't be BLKmode. */
+ tree inner_type = TREE_TYPE (TREE_OPERAND (exp, 0));
+ rtx memloc = assign_temp (inner_type, 1, 1, 1);
+
+ if (GET_CODE (op0) == PARALLEL)
+ /* Handle calls that pass values in multiple
+ non-contiguous locations. The Irix 6 ABI has examples
+ of this. */
+ emit_group_store (memloc, op0,
+ int_size_in_bytes (inner_type));
+ else
+ emit_move_insn (memloc, op0);
+
+ op0 = memloc;
+ }
}
if (GET_CODE (op0) != MEM)
}
if (TYPE_TRAP_SIGNED (TREE_TYPE (exp)))
- this_optab = this_optab == add_optab ? addv_optab : subv_optab;
+ this_optab = this_optab == add_optab ? addv_optab : subv_optab;
/* For a preincrement, see if we can do this with a single instruction. */
if (!post)
|| (result != const0_rtx && invert))
? const0_rtx : const1_rtx);
+ /* The code of RESULT may not match CODE if compare_from_rtx
+ decided to swap its operands and reverse the original code.
+
+ We know that compare_from_rtx returns either a CONST_INT or
+ a new comparison code, so it is safe to just extract the
+ code from RESULT. */
+ code = GET_CODE (result);
+
label = gen_label_rtx ();
if (bcc_gen_fctn[(int) code] == 0)
abort ();