static bool constant_pool_expr_p (rtx);
static bool toc_relative_expr_p (rtx);
static bool legitimate_small_data_p (enum machine_mode, rtx);
-static bool legitimate_offset_address_p (enum machine_mode, rtx, int);
static bool legitimate_indexed_address_p (rtx, int);
static bool legitimate_indirect_address_p (rtx, int);
static bool macho_lo_sum_memory_operand (rtx x, enum machine_mode mode);
static int rs6000_ra_ever_killed (void);
static tree rs6000_handle_longcall_attribute (tree *, tree, tree, int, bool *);
static tree rs6000_handle_altivec_attribute (tree *, tree, tree, int, bool *);
+static void rs6000_eliminate_indexed_memrefs (rtx operands[2]);
static const char *rs6000_mangle_fundamental_type (tree);
extern const struct attribute_spec rs6000_attribute_table[];
static void rs6000_set_default_type_attributes (tree);
&& small_data_operand (x, mode));
}
-static bool
-legitimate_offset_address_p (enum machine_mode mode, rtx x, int strict)
+bool
+rs6000_legitimate_offset_address_p (enum machine_mode mode, rtx x, int strict)
{
unsigned HOST_WIDE_INT offset, extra;
word aligned.
For modes spanning multiple registers (DFmode in 32-bit GPRs,
- 32-bit DImode, TImode), indexed addressing cannot be used because
+ 32-bit DImode, TImode, TFmode), indexed addressing cannot be used because
adjacent memory cells are accessed by adding word-sized offsets
during assembly output. */
int
|| XEXP (x, 0) == arg_pointer_rtx)
&& GET_CODE (XEXP (x, 1)) == CONST_INT)
return 1;
- if (legitimate_offset_address_p (mode, x, reg_ok_strict))
+ if (rs6000_legitimate_offset_address_p (mode, x, reg_ok_strict))
return 1;
if (mode != TImode
+ && mode != TFmode
&& ((TARGET_HARD_FLOAT && TARGET_FPRS)
|| TARGET_POWERPC64
|| (mode != DFmode && mode != TFmode))
return dest;
}
+/* Helper for the following. Get rid of [r+r] memory refs
+ in cases where it won't work (TImode, TFmode). */
+
+static void
+rs6000_eliminate_indexed_memrefs (rtx operands[2])
+{
+ if (GET_CODE (operands[0]) == MEM
+ && GET_CODE (XEXP (operands[0], 0)) != REG
+ && ! reload_in_progress)
+ operands[0]
+ = replace_equiv_address (operands[0],
+ copy_addr_to_reg (XEXP (operands[0], 0)));
+
+ if (GET_CODE (operands[1]) == MEM
+ && GET_CODE (XEXP (operands[1], 0)) != REG
+ && ! reload_in_progress)
+ operands[1]
+ = replace_equiv_address (operands[1],
+ copy_addr_to_reg (XEXP (operands[1], 0)));
+}
+
/* Emit a move from SOURCE to DEST in mode MODE. */
void
rs6000_emit_move (rtx dest, rtx source, enum machine_mode mode)
break;
case TFmode:
+ rs6000_eliminate_indexed_memrefs (operands);
+ /* fall through */
+
case DFmode:
case SFmode:
if (CONSTANT_P (operands[1])
break;
case TImode:
- if (GET_CODE (operands[0]) == MEM
- && GET_CODE (XEXP (operands[0], 0)) != REG
- && ! reload_in_progress)
- operands[0]
- = replace_equiv_address (operands[0],
- copy_addr_to_reg (XEXP (operands[0], 0)));
-
- if (GET_CODE (operands[1]) == MEM
- && GET_CODE (XEXP (operands[1], 0)) != REG
- && ! reload_in_progress)
- operands[1]
- = replace_equiv_address (operands[1],
- copy_addr_to_reg (XEXP (operands[1], 0)));
+ rs6000_eliminate_indexed_memrefs (operands);
+
if (TARGET_POWER)
{
emit_insn (gen_rtx_PARALLEL (VOIDmode,
if (base_regno == 0)
return 0;
}
- else if (legitimate_offset_address_p (SImode, src_addr, 0))
+ else if (rs6000_legitimate_offset_address_p (SImode, src_addr, 0))
{
offset = INTVAL (XEXP (src_addr, 1));
base_regno = REGNO (XEXP (src_addr, 0));
newoffset = 0;
addr_reg = newaddr;
}
- else if (legitimate_offset_address_p (SImode, newaddr, 0))
+ else if (rs6000_legitimate_offset_address_p (SImode, newaddr, 0))
{
addr_reg = XEXP (newaddr, 0);
newoffset = INTVAL (XEXP (newaddr, 1));
if (base_regno == 0)
return 0;
}
- else if (legitimate_offset_address_p (SImode, dest_addr, 0))
+ else if (rs6000_legitimate_offset_address_p (SImode, dest_addr, 0))
{
offset = INTVAL (XEXP (dest_addr, 1));
base_regno = REGNO (XEXP (dest_addr, 0));
newoffset = 0;
addr_reg = newaddr;
}
- else if (legitimate_offset_address_p (SImode, newaddr, 0))
+ else if (rs6000_legitimate_offset_address_p (SImode, newaddr, 0))
{
addr_reg = XEXP (newaddr, 0);
newoffset = INTVAL (XEXP (newaddr, 1));
else
return \"mr %0,%1\;mr %L0,%L1\";
case 1:
- if (offsettable_memref_p (operands[1])
- || (GET_CODE (operands[1]) == MEM
- && (GET_CODE (XEXP (operands[1], 0)) == LO_SUM
+ if (GET_CODE (operands[1]) == MEM
+ && (rs6000_legitimate_offset_address_p (DFmode, XEXP (operands[1], 0),
+ reload_completed || reload_in_progress)
+ || GET_CODE (XEXP (operands[1], 0)) == REG
+ || GET_CODE (XEXP (operands[1], 0)) == LO_SUM
|| GET_CODE (XEXP (operands[1], 0)) == PRE_INC
- || GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)))
+ || GET_CODE (XEXP (operands[1], 0)) == PRE_DEC))
{
/* If the low-address word is used in the address, we must load
it last. Otherwise, load it first. Note that we cannot have
}
}
case 2:
- if (offsettable_memref_p (operands[0])
- || (GET_CODE (operands[0]) == MEM
- && (GET_CODE (XEXP (operands[0], 0)) == LO_SUM
+ if (GET_CODE (operands[0]) == MEM
+ && (rs6000_legitimate_offset_address_p (DFmode, XEXP (operands[0], 0),
+ reload_completed || reload_in_progress)
+ || GET_CODE (XEXP (operands[0], 0)) == REG
+ || GET_CODE (XEXP (operands[0], 0)) == LO_SUM
|| GET_CODE (XEXP (operands[0], 0)) == PRE_INC
- || GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)))
+ || GET_CODE (XEXP (operands[0], 0)) == PRE_DEC))
return \"{st%U0|stw%U0} %1,%0\;{st|stw} %L1,%L0\";
else
{