static void sparc_va_start (tree, rtx);
static tree sparc_gimplify_va_arg (tree, tree, gimple_seq *, gimple_seq *);
static bool sparc_vector_mode_supported_p (enum machine_mode);
+static bool sparc_tls_referenced_p (rtx);
+static rtx legitimize_tls_address (rtx);
+static rtx legitimize_pic_address (rtx, rtx);
static rtx sparc_legitimize_address (rtx, rtx, enum machine_mode);
static bool sparc_pass_by_reference (CUMULATIVE_ARGS *,
enum machine_mode, const_tree, bool);
/* Fixup TLS cases. */
if (TARGET_HAVE_TLS
&& CONSTANT_P (operands[1])
- && GET_CODE (operands[1]) != HIGH
&& sparc_tls_referenced_p (operands [1]))
{
- rtx sym = operands[1];
- rtx addend = NULL;
-
- if (GET_CODE (sym) == CONST && GET_CODE (XEXP (sym, 0)) == PLUS)
- {
- addend = XEXP (XEXP (sym, 0), 1);
- sym = XEXP (XEXP (sym, 0), 0);
- }
-
- gcc_assert (SPARC_SYMBOL_REF_TLS_P (sym));
-
- sym = legitimize_tls_address (sym);
- if (addend)
- {
- sym = gen_rtx_PLUS (mode, sym, addend);
- sym = force_operand (sym, operands[0]);
- }
- operands[1] = sym;
+ operands[1] = legitimize_tls_address (operands[1]);
+ return false;
}
/* Fixup PIC cases. */
if (flag_pic && CONSTANT_P (operands[1]))
{
if (pic_address_needs_scratch (operands[1]))
- operands[1] = legitimize_pic_address (operands[1], mode, 0);
+ operands[1] = legitimize_pic_address (operands[1], NULL_RTX);
/* VxWorks does not impose a fixed gap between segments; the run-time
gap can be different from the object-file gap. We therefore can't
if (symbolic_operand (operands[1], mode))
{
operands[1] = legitimize_pic_address (operands[1],
- mode,
- (reload_in_progress ?
- operands[0] :
- NULL_RTX));
+ reload_in_progress
+ ? operands[0] : NULL_RTX);
return false;
}
}
bool
legitimate_constant_p (rtx x)
{
- rtx inner;
-
switch (GET_CODE (x))
{
- case SYMBOL_REF:
- /* TLS symbols are not constant. */
- if (SYMBOL_REF_TLS_MODEL (x))
- return false;
- break;
-
case CONST:
- inner = XEXP (x, 0);
-
- /* Offsets of TLS symbols are never valid.
- Discourage CSE from creating them. */
- if (GET_CODE (inner) == PLUS
- && SPARC_SYMBOL_REF_TLS_P (XEXP (inner, 0)))
+ case SYMBOL_REF:
+ if (sparc_tls_referenced_p (x))
return false;
break;
{
if (pic_address_needs_scratch (x))
return false;
- if (SPARC_SYMBOL_REF_TLS_P (x)
- || (GET_CODE (x) == CONST
- && GET_CODE (XEXP (x, 0)) == PLUS
- && SPARC_SYMBOL_REF_TLS_P (XEXP (XEXP (x, 0), 0))))
+ if (sparc_tls_referenced_p (x))
return false;
return true;
}
&& GET_CODE (rs2) != SUBREG
&& GET_CODE (rs2) != LO_SUM
&& GET_CODE (rs2) != MEM
- && ! SPARC_SYMBOL_REF_TLS_P (rs2)
+ && !(GET_CODE (rs2) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL (rs2))
&& (! symbolic_operand (rs2, VOIDmode) || mode == Pmode)
&& (GET_CODE (rs2) != CONST_INT || SMALL_INT (rs2)))
|| ((REG_P (rs1)
rs2 = NULL;
imm1 = XEXP (rs1, 1);
rs1 = XEXP (rs1, 0);
- if (! CONSTANT_P (imm1) || SPARC_SYMBOL_REF_TLS_P (rs1))
+ if (!CONSTANT_P (imm1)
+ || (GET_CODE (rs1) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL (rs1)))
return 0;
}
}
rs1 = XEXP (addr, 0);
imm1 = XEXP (addr, 1);
- if (! CONSTANT_P (imm1) || SPARC_SYMBOL_REF_TLS_P (rs1))
+ if (!CONSTANT_P (imm1)
+ || (GET_CODE (rs1) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL (rs1)))
return 0;
/* We can't allow TFmode in 32-bit mode, because an offset greater
return temp;
}
-/* Return 1 if *X is a thread-local symbol. */
-
-static int
-sparc_tls_symbol_ref_1 (rtx *x, void *data ATTRIBUTE_UNUSED)
-{
- return SPARC_SYMBOL_REF_TLS_P (*x);
-}
-
-/* Return 1 if X contains a thread-local symbol. */
+/* Return true if X contains a thread-local symbol. */
-bool
+static bool
sparc_tls_referenced_p (rtx x)
{
if (!TARGET_HAVE_TLS)
return false;
- return for_each_rtx (&x, &sparc_tls_symbol_ref_1, 0);
+ if (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == PLUS)
+ x = XEXP (XEXP (x, 0), 0);
+
+ if (GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL (x))
+ return true;
+
+ /* That's all we handle in legitimize_tls_address for now. */
+ return false;
}
/* ADDR contains a thread-local SYMBOL_REF. Generate code to compute
this (thread-local) address. */
-rtx
+static rtx
legitimize_tls_address (rtx addr)
{
rtx temp1, temp2, temp3, ret, o0, got, insn;
gcc_unreachable ();
}
+ else if (GET_CODE (addr) == CONST)
+ {
+ rtx base, offset;
+
+ gcc_assert (GET_CODE (XEXP (addr, 0)) == PLUS);
+
+ base = legitimize_tls_address (XEXP (XEXP (addr, 0), 0));
+ offset = XEXP (XEXP (addr, 0), 1);
+
+ base = force_operand (base, NULL_RTX);
+ if (!(GET_CODE (offset) == CONST_INT && SMALL_INT (offset)))
+ offset = force_reg (Pmode, offset);
+ ret = gen_rtx_PLUS (Pmode, base, offset);
+ }
+
else
gcc_unreachable (); /* for now ... */
return ret;
}
-
/* Legitimize PIC addresses. If the address is already position-independent,
we return ORIG. Newly generated position-independent addresses go into a
reg. This is REG if nonzero, otherwise we allocate register(s) as
necessary. */
-rtx
-legitimize_pic_address (rtx orig, enum machine_mode mode ATTRIBUTE_UNUSED,
- rtx reg)
+static rtx
+legitimize_pic_address (rtx orig, rtx reg)
{
if (GET_CODE (orig) == SYMBOL_REF
/* See the comment in sparc_expand_move. */
}
gcc_assert (GET_CODE (XEXP (orig, 0)) == PLUS);
- base = legitimize_pic_address (XEXP (XEXP (orig, 0), 0), Pmode, reg);
- offset = legitimize_pic_address (XEXP (XEXP (orig, 0), 1), Pmode,
- base == reg ? 0 : reg);
+ base = legitimize_pic_address (XEXP (XEXP (orig, 0), 0), reg);
+ offset = legitimize_pic_address (XEXP (XEXP (orig, 0), 1),
+ base == reg ? NULL_RTX : reg);
if (GET_CODE (offset) == CONST_INT)
{
On SPARC, change REG+N into REG+REG, and REG+(X*Y) into REG+REG. */
-rtx
+static rtx
sparc_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
enum machine_mode mode)
{
if (x != orig_x && sparc_legitimate_address_p (mode, x, FALSE))
return x;
- if (SPARC_SYMBOL_REF_TLS_P (x))
+ if (sparc_tls_referenced_p (x))
x = legitimize_tls_address (x);
else if (flag_pic)
- x = legitimize_pic_address (x, mode, 0);
+ x = legitimize_pic_address (x, NULL_RTX);
else if (GET_CODE (x) == PLUS && CONSTANT_ADDRESS_P (XEXP (x, 1)))
x = gen_rtx_PLUS (Pmode, XEXP (x, 0),
copy_to_mode_reg (Pmode, XEXP (x, 1)));
copy_to_mode_reg (Pmode, XEXP (x, 0)));
else if (GET_CODE (x) == SYMBOL_REF
|| GET_CODE (x) == CONST
- || GET_CODE (x) == LABEL_REF)
+ || GET_CODE (x) == LABEL_REF)
x = copy_to_suggested_reg (x, NULL_RTX, Pmode);
+
return x;
}
/* Delay emitting the PIC helper function because it needs to
change the section and we are emitting assembly code. */
load_pic_register (true); /* clobbers %o7 */
- scratch = legitimize_pic_address (funexp, Pmode, scratch);
+ scratch = legitimize_pic_address (funexp, scratch);
seq = get_insns ();
end_sequence ();
emit_and_preserve (seq, spill_reg, spill_reg2);