static int toc_hash_eq (const void *, const void *);
static int constant_pool_expr_1 (rtx, int *, int *);
static bool constant_pool_expr_p (rtx);
-static bool legitimate_small_data_p (enum machine_mode, rtx);
static bool legitimate_indexed_address_p (rtx, int);
static bool legitimate_lo_sum_address_p (enum machine_mode, rtx, int);
static struct machine_function * rs6000_init_machine_status (void);
case CONST_INT:
#if HOST_BITS_PER_WIDE_INT == 64
if ((INTVAL (op) >> 31) != 0 && (INTVAL (op) >> 31) != -1
- && mask_operand (op, mode))
+ && mask64_operand (op, mode))
return 2;
else
#endif
|| (high == -1 && low < 0))
return num_insns_constant_wide (low);
- else if (mask_operand (op, mode))
+ else if (mask64_operand (op, mode))
return 2;
else if (low == 0)
{
rtx copy = copy_rtx (vals);
- /* Load constant part of vector, substititute neighboring value for
+ /* Load constant part of vector, substitute neighboring value for
varying element. */
XVECEXP (copy, 0, one_var) = XVECEXP (vals, 0, (one_var + 1) % n_elts);
rs6000_expand_vector_init (target, copy);
emit_move_insn (target, adjust_address_nv (mem, inner_mode, 0));
}
-int
-mask64_1or2_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED,
- bool allow_one)
-{
- if (GET_CODE (op) == CONST_INT)
- {
- HOST_WIDE_INT c, lsb;
- bool one_ok;
-
- c = INTVAL (op);
-
- /* Disallow all zeros. */
- if (c == 0)
- return 0;
-
- /* We can use a single rlwinm insn if no upper bits of C are set
- AND there are zero, one or two transitions in the _whole_ of
- C. */
- one_ok = !(c & ~(HOST_WIDE_INT)0xffffffff);
-
- /* We don't change the number of transitions by inverting,
- so make sure we start with the LS bit zero. */
- if (c & 1)
- c = ~c;
-
- /* Find the first transition. */
- lsb = c & -c;
-
- /* Invert to look for a second transition. */
- c = ~c;
-
- /* Erase first transition. */
- c &= -lsb;
-
- /* Find the second transition. */
- lsb = c & -c;
-
- /* Invert to look for a third transition. */
- c = ~c;
-
- /* Erase second transition. */
- c &= -lsb;
-
- if (one_ok && !(allow_one || c))
- return 0;
-
- /* Find the third transition (if any). */
- lsb = c & -c;
-
- /* Match if all the bits above are 1's (or c is zero). */
- return c == -lsb;
- }
- return 0;
-}
-
/* Generates shifts and masks for a pair of rldicl or rldicr insns to
implement ANDing by the mask IN. */
void
&& constant_pool_expr_p (XEXP (x, 1)));
}
-static bool
-legitimate_small_data_p (enum machine_mode mode, rtx x)
+bool
+rs6000_legitimate_small_data_p (enum machine_mode mode, rtx x)
{
return (DEFAULT_ABI == ABI_V4
&& !flag_pic && !TARGET_TOC
{
rtx r3, got, tga, tmp1, tmp2, eqv;
+ /* We currently use relocations like @got@tlsgd for tls, which
+ means the linker will handle allocation of tls entries, placing
+ them in the .got section. So use a pointer to the .got section,
+ not one to secondary TOC sections used by 64-bit -mminimal-toc,
+ or to secondary GOT sections used by 32-bit -fPIC. */
if (TARGET_64BIT)
- got = gen_rtx_REG (Pmode, TOC_REGISTER);
+ got = gen_rtx_REG (Pmode, 2);
else
{
if (flag_pic == 1)
return x;
}
-#if TARGET_MACHO
if (GET_CODE (x) == SYMBOL_REF
- && DEFAULT_ABI == ABI_DARWIN
&& !ALTIVEC_VECTOR_MODE (mode)
+#if TARGET_MACHO
+ && DEFAULT_ABI == ABI_DARWIN
&& (flag_pic || MACHO_DYNAMIC_NO_PIC_P)
+#else
+ && DEFAULT_ABI == ABI_V4
+ && !flag_pic
+#endif
/* Don't do this for TFmode, since the result isn't offsettable.
The same goes for DImode without 64-bit gprs. */
&& mode != TFmode
&& (mode != DImode || TARGET_POWERPC64))
{
+#if TARGET_MACHO
if (flag_pic)
{
rtx offset = gen_rtx_CONST (Pmode,
gen_rtx_HIGH (Pmode, offset)), offset);
}
else
+#endif
x = gen_rtx_LO_SUM (GET_MODE (x),
gen_rtx_HIGH (Pmode, x), x);
*win = 1;
return x;
}
-#endif
+
+ /* Reload an offset address wrapped by an AND that represents the
+ masking of the lower bits. Strip the outer AND and let reload
+ convert the offset address into an indirect address. */
+ if (TARGET_ALTIVEC
+ && ALTIVEC_VECTOR_MODE (mode)
+ && GET_CODE (x) == AND
+ && GET_CODE (XEXP (x, 0)) == PLUS
+ && GET_CODE (XEXP (XEXP (x, 0), 0)) == REG
+ && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
+ && GET_CODE (XEXP (x, 1)) == CONST_INT
+ && INTVAL (XEXP (x, 1)) == -16)
+ {
+ x = XEXP (x, 0);
+ *win = 1;
+ return x;
+ }
if (TARGET_TOC
&& constant_pool_expr_p (x)
&& TARGET_UPDATE
&& legitimate_indirect_address_p (XEXP (x, 0), reg_ok_strict))
return 1;
- if (legitimate_small_data_p (mode, x))
+ if (rs6000_legitimate_small_data_p (mode, x))
return 1;
if (legitimate_constant_pool_address_p (x))
return 1;
if (mode == VOIDmode)
{
if (abi == ABI_V4
- && cum->nargs_prototype < 0
&& (cum->call_cookie & CALL_LIBCALL) == 0
- && (cum->prototype || TARGET_NO_PROTOTYPE))
+ && (cum->stdarg
+ || (cum->nargs_prototype < 0
+ && (cum->prototype || TARGET_NO_PROTOTYPE))))
{
/* For the SPE, we need to crxor CR6 always. */
if (TARGET_SPE_ABI)
mem = gen_rtx_MEM (BLKmode,
plus_constant (save_area,
- first_reg_offset * reg_size)),
+ first_reg_offset * reg_size));
+ MEM_NOTRAP_P (mem) = 1;
set_mem_alias_set (mem, set);
set_mem_align (mem, BITS_PER_WORD);
fregno++, off += UNITS_PER_FP_WORD, nregs++)
{
mem = gen_rtx_MEM (DFmode, plus_constant (save_area, off));
+ MEM_NOTRAP_P (mem) = 1;
set_mem_alias_set (mem, set);
set_mem_align (mem, GET_MODE_ALIGNMENT (DFmode));
emit_move_insn (mem, gen_rtx_REG (DFmode, fregno));
clear_bytes = 4;
mode = SImode;
}
- else if (bytes == 2 && (align >= 16 || !STRICT_ALIGNMENT))
+ else if (bytes >= 2 && (align >= 16 || !STRICT_ALIGNMENT))
{ /* move 2 bytes */
clear_bytes = 2;
mode = HImode;
mode = SImode;
gen_func.mov = gen_movsi;
}
- else if (bytes == 2 && (align >= 16 || !STRICT_ALIGNMENT))
+ else if (bytes >= 2 && (align >= 16 || !STRICT_ALIGNMENT))
{ /* move 2 bytes */
move_bytes = 2;
mode = HImode;
/* PowerPC64 mask position. All 0's is excluded.
CONST_INT 32-bit mask is considered sign-extended so any
transition must occur within the CONST_INT, not on the boundary. */
- if (! mask_operand (x, DImode))
+ if (! mask64_operand (x, DImode))
output_operand_lossage ("invalid %%S value");
uval = INT_LOWPART (x);
emit_insn (TARGET_32BIT
? gen_addsi3 (breg, breg, delta_rtx)
: gen_adddi3 (breg, breg, delta_rtx));
- src = gen_rtx_MEM (mode, breg);
+ src = replace_equiv_address (src, breg);
}
else if (! offsettable_memref_p (src))
{
- rtx newsrc, basereg;
+ rtx basereg;
basereg = gen_rtx_REG (Pmode, reg);
emit_insn (gen_rtx_SET (VOIDmode, basereg, XEXP (src, 0)));
- newsrc = gen_rtx_MEM (GET_MODE (src), basereg);
- MEM_COPY_ATTRIBUTES (newsrc, src);
- src = newsrc;
+ src = replace_equiv_address (src, basereg);
}
breg = XEXP (src, 0);
emit_insn (TARGET_32BIT
? gen_addsi3 (breg, breg, delta_rtx)
: gen_adddi3 (breg, breg, delta_rtx));
- dst = gen_rtx_MEM (mode, breg);
+ dst = replace_equiv_address (dst, breg);
}
else
gcc_assert (offsettable_memref_p (dst));
|| current_function_calls_alloca
|| info->total_size > 32767)
{
- emit_move_insn (operands[1], gen_rtx_MEM (Pmode, frame_rtx));
+ tmp = gen_rtx_MEM (Pmode, frame_rtx);
+ MEM_NOTRAP_P (tmp) = 1;
+ set_mem_alias_set (tmp, rs6000_sr_alias_set);
+ emit_move_insn (operands[1], tmp);
frame_rtx = operands[1];
}
else if (info->push_p)
tmp = plus_constant (frame_rtx, info->lr_save_offset + sp_offset);
tmp = gen_rtx_MEM (Pmode, tmp);
+ MEM_NOTRAP_P (tmp) = 1;
+ set_mem_alias_set (tmp, rs6000_sr_alias_set);
emit_move_insn (tmp, operands[0]);
}
else
rtx tocompare = gen_reg_rtx (SImode);
rtx no_toc_save_needed = gen_label_rtx ();
- mem = gen_rtx_MEM (Pmode, hard_frame_pointer_rtx);
+ mem = gen_frame_mem (Pmode, hard_frame_pointer_rtx);
emit_move_insn (stack_top, mem);
- mem = gen_rtx_MEM (Pmode,
- gen_rtx_PLUS (Pmode, stack_top,
- GEN_INT (2 * GET_MODE_SIZE (Pmode))));
+ mem = gen_frame_mem (Pmode,
+ gen_rtx_PLUS (Pmode, stack_top,
+ GEN_INT (2 * GET_MODE_SIZE (Pmode))));
emit_move_insn (opcode_addr, mem);
emit_move_insn (opcode, gen_rtx_MEM (SImode, opcode_addr));
emit_move_insn (tocompare, gen_int_mode (TARGET_32BIT ? 0x80410014
SImode, NULL_RTX, NULL_RTX,
no_toc_save_needed);
- mem = gen_rtx_MEM (Pmode,
- gen_rtx_PLUS (Pmode, stack_top,
- GEN_INT (5 * GET_MODE_SIZE (Pmode))));
+ mem = gen_frame_mem (Pmode,
+ gen_rtx_PLUS (Pmode, stack_top,
+ GEN_INT (5 * GET_MODE_SIZE (Pmode))));
emit_move_insn (mem, gen_rtx_REG (Pmode, 2));
emit_label (no_toc_save_needed);
}
const char *name = buf;
const char *real_name;
rtx base = x;
- int offset = 0;
+ HOST_WIDE_INT offset = 0;
gcc_assert (!TARGET_NO_TOC);
fprintf (file, "\t.tc %s", real_name);
if (offset < 0)
- fprintf (file, ".N%d", - offset);
+ fprintf (file, ".N" HOST_WIDE_INT_PRINT_UNSIGNED, - offset);
else if (offset)
- fprintf (file, ".P%d", offset);
+ fprintf (file, ".P" HOST_WIDE_INT_PRINT_UNSIGNED, offset);
fputs ("[TC],", file);
}
{
RS6000_OUTPUT_BASENAME (file, name);
if (offset < 0)
- fprintf (file, "%d", offset);
+ fprintf (file, HOST_WIDE_INT_PRINT_DEC, offset);
else if (offset > 0)
- fprintf (file, "+%d", offset);
+ fprintf (file, "+" HOST_WIDE_INT_PRINT_DEC, offset);
}
else
output_addr_const (file, x);
static rtx
get_next_active_insn (rtx insn, rtx tail)
{
- rtx next_insn;
-
- if (!insn || insn == tail)
+ if (insn == NULL_RTX || insn == tail)
return NULL_RTX;
- next_insn = NEXT_INSN (insn);
-
- while (next_insn
- && next_insn != tail
- && (GET_CODE (next_insn) == NOTE
- || GET_CODE (PATTERN (next_insn)) == USE
- || GET_CODE (PATTERN (next_insn)) == CLOBBER))
+ while (1)
{
- next_insn = NEXT_INSN (next_insn);
- }
-
- if (!next_insn || next_insn == tail)
- return NULL_RTX;
+ insn = NEXT_INSN (insn);
+ if (insn == NULL_RTX || insn == tail)
+ return NULL_RTX;
- return next_insn;
+ if (CALL_P (insn)
+ || JUMP_P (insn)
+ || (NONJUMP_INSN_P (insn)
+ && GET_CODE (PATTERN (insn)) != USE
+ && GET_CODE (PATTERN (insn)) != CLOBBER
+ && INSN_CODE (insn) != CODE_FOR_stack_tie))
+ break;
+ }
+ return insn;
}
/* Return whether the presence of INSN causes a dispatch group termination
&& (CONST_OK_FOR_LETTER_P (INTVAL (x), 'K')
|| (CONST_OK_FOR_LETTER_P (INTVAL (x),
mode == SImode ? 'L' : 'J'))
- || mask_operand (x, VOIDmode)))
+ || mask_operand (x, mode)
+ || (mode == DImode
+ && mask64_operand (x, DImode))))
|| ((outer_code == IOR || outer_code == XOR)
&& (CONST_OK_FOR_LETTER_P (INTVAL (x), 'K')
|| (CONST_OK_FOR_LETTER_P (INTVAL (x),
&& ((outer_code == AND
&& (CONST_OK_FOR_LETTER_P (INTVAL (x), 'K')
|| CONST_OK_FOR_LETTER_P (INTVAL (x), 'L')
- || mask_operand (x, DImode)))
+ || mask_operand (x, DImode)
+ || mask64_operand (x, DImode)))
|| ((outer_code == IOR || outer_code == XOR)
&& CONST_DOUBLE_HIGH (x) == 0
&& (CONST_DOUBLE_LOW (x)
else
*total = rs6000_cost->fp;
}
- else if (GET_CODE (XEXP (x, 0)) == MULT)
- {
- /* The rs6000 doesn't have shift-and-add instructions. */
- rs6000_rtx_costs (XEXP (x, 0), MULT, PLUS, total);
- *total += COSTS_N_INSNS (1);
- }
else
*total = COSTS_N_INSNS (1);
return false;
else
*total = rs6000_cost->fp;
}
- else if (GET_CODE (XEXP (x, 0)) == MULT)
- {
- /* The rs6000 doesn't have shift-and-sub instructions. */
- rs6000_rtx_costs (XEXP (x, 0), MULT, MINUS, total);
- *total += COSTS_N_INSNS (1);
- }
else
*total = COSTS_N_INSNS (1);
return false;
GP_ARG_RETURN + 1),
GEN_INT (4))));
}
-
+ if (TARGET_32BIT && TARGET_POWERPC64 && TYPE_MODE (valtype) == DCmode)
+ {
+ return gen_rtx_PARALLEL (DCmode,
+ gen_rtvec (4,
+ gen_rtx_EXPR_LIST (VOIDmode,
+ gen_rtx_REG (SImode, GP_ARG_RETURN),
+ const0_rtx),
+ gen_rtx_EXPR_LIST (VOIDmode,
+ gen_rtx_REG (SImode,
+ GP_ARG_RETURN + 1),
+ GEN_INT (4)),
+ gen_rtx_EXPR_LIST (VOIDmode,
+ gen_rtx_REG (SImode,
+ GP_ARG_RETURN + 2),
+ GEN_INT (8)),
+ gen_rtx_EXPR_LIST (VOIDmode,
+ gen_rtx_REG (SImode,
+ GP_ARG_RETURN + 3),
+ GEN_INT (12))));
+ }
if ((INTEGRAL_TYPE_P (valtype)
&& TYPE_PRECISION (valtype) < BITS_PER_WORD)
|| POINTER_TYPE_P (valtype))