#include "cfglayout.h"
#include "gimple.h"
#include "langhooks.h"
+#include "reload.h"
#include "params.h"
#include "df.h"
#include "dwarf2out.h"
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_tls_address (rtx);
+static rtx sparc_legitimize_pic_address (rtx, rtx);
static rtx sparc_legitimize_address (rtx, rtx, enum machine_mode);
static bool sparc_mode_dependent_address_p (const_rtx);
static bool sparc_pass_by_reference (CUMULATIVE_ARGS *,
&& CONSTANT_P (operands[1])
&& sparc_tls_referenced_p (operands [1]))
{
- operands[1] = legitimize_tls_address (operands[1]);
+ operands[1] = sparc_legitimize_tls_address (operands[1]);
return false;
}
if (flag_pic && CONSTANT_P (operands[1]))
{
if (pic_address_needs_scratch (operands[1]))
- operands[1] = legitimize_pic_address (operands[1], NULL_RTX);
+ operands[1] = sparc_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],
- reload_in_progress
- ? operands[0] : NULL_RTX);
+ operands[1]
+ = sparc_legitimize_pic_address (operands[1],
+ reload_in_progress
+ ? operands[0] : NULL_RTX);
return false;
}
}
if (GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL (x))
return true;
- /* That's all we handle in legitimize_tls_address for now. */
+ /* That's all we handle in sparc_legitimize_tls_address for now. */
return false;
}
this (thread-local) address. */
static rtx
-legitimize_tls_address (rtx addr)
+sparc_legitimize_tls_address (rtx addr)
{
rtx temp1, temp2, temp3, ret, o0, got, insn;
gcc_assert (GET_CODE (XEXP (addr, 0)) == PLUS);
- base = legitimize_tls_address (XEXP (XEXP (addr, 0), 0));
+ base = sparc_legitimize_tls_address (XEXP (XEXP (addr, 0), 0));
offset = XEXP (XEXP (addr, 0), 1);
base = force_operand (base, NULL_RTX);
necessary. */
static rtx
-legitimize_pic_address (rtx orig, rtx reg)
+sparc_legitimize_pic_address (rtx orig, rtx reg)
{
bool gotdata_op = false;
if (gotdata_op)
{
if (TARGET_ARCH64)
- insn = emit_insn (gen_movdi_pic_gotdata_op (reg, pic_offset_table_rtx,
+ insn = emit_insn (gen_movdi_pic_gotdata_op (reg,
+ pic_offset_table_rtx,
address, orig));
else
- insn = emit_insn (gen_movsi_pic_gotdata_op (reg, pic_offset_table_rtx,
+ insn = emit_insn (gen_movsi_pic_gotdata_op (reg,
+ pic_offset_table_rtx,
address, orig));
}
else
}
gcc_assert (GET_CODE (XEXP (orig, 0)) == PLUS);
- base = legitimize_pic_address (XEXP (XEXP (orig, 0), 0), reg);
- offset = legitimize_pic_address (XEXP (XEXP (orig, 0), 1),
- base == reg ? NULL_RTX : reg);
+ base = sparc_legitimize_pic_address (XEXP (XEXP (orig, 0), 0), reg);
+ offset = sparc_legitimize_pic_address (XEXP (XEXP (orig, 0), 1),
+ base == reg ? NULL_RTX : reg);
if (GET_CODE (offset) == CONST_INT)
{
return x;
if (sparc_tls_referenced_p (x))
- x = legitimize_tls_address (x);
+ x = sparc_legitimize_tls_address (x);
else if (flag_pic)
- x = legitimize_pic_address (x, NULL_RTX);
+ x = sparc_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)));
return x;
}
+/* SPARC implementation of LEGITIMIZE_RELOAD_ADDRESS. Returns a value to
+ replace the input X, or the original X if no replacement is called for.
+ The output parameter *WIN is 1 if the calling macro should goto WIN,
+ 0 if it should not.
+
+ For SPARC, we wish to handle addresses by splitting them into
+ HIGH+LO_SUM pairs, retaining the LO_SUM in the memory reference.
+ This cuts the number of extra insns by one.
+
+ Do nothing when generating PIC code and the address is a symbolic
+ operand or requires a scratch register. */
+
+rtx
+sparc_legitimize_reload_address (rtx x, enum machine_mode mode,
+ int opnum, int type,
+ int ind_levels ATTRIBUTE_UNUSED, int *win)
+{
+ /* Decompose SImode constants into HIGH+LO_SUM. */
+ if (CONSTANT_P (x)
+ && (mode != TFmode || TARGET_ARCH64)
+ && GET_MODE (x) == SImode
+ && GET_CODE (x) != LO_SUM
+ && GET_CODE (x) != HIGH
+ && sparc_cmodel <= CM_MEDLOW
+ && !(flag_pic
+ && (symbolic_operand (x, Pmode) || pic_address_needs_scratch (x))))
+ {
+ x = gen_rtx_LO_SUM (GET_MODE (x), gen_rtx_HIGH (GET_MODE (x), x), x);
+ push_reload (XEXP (x, 0), NULL_RTX, &XEXP (x, 0), NULL,
+ BASE_REG_CLASS, GET_MODE (x), VOIDmode, 0, 0,
+ opnum, (enum reload_type)type);
+ *win = 1;
+ return x;
+ }
+
+ /* We have to recognize what we have already generated above. */
+ if (GET_CODE (x) == LO_SUM && GET_CODE (XEXP (x, 0)) == HIGH)
+ {
+ push_reload (XEXP (x, 0), NULL_RTX, &XEXP (x, 0), NULL,
+ BASE_REG_CLASS, GET_MODE (x), VOIDmode, 0, 0,
+ opnum, (enum reload_type)type);
+ *win = 1;
+ return x;
+ }
+
+ *win = 0;
+ return x;
+}
+
/* Return true if ADDR (a legitimate address expression)
has an effect that depends on the machine mode it is used for.
/* Delay emitting the PIC helper function because it needs to
change the section and we are emitting assembly code. */
load_pic_register (); /* clobbers %o7 */
- scratch = legitimize_pic_address (funexp, scratch);
+ scratch = sparc_legitimize_pic_address (funexp, scratch);
seq = get_insns ();
end_sequence ();
emit_and_preserve (seq, spill_reg, spill_reg2);
\f
/* Try a machine-dependent way of reloading an illegitimate address
operand. If we find one, push the reload and jump to WIN. This
- macro is used in only one place: `find_reloads_address' in reload.c.
-
- For SPARC 32, we wish to handle addresses by splitting them into
- HIGH+LO_SUM pairs, retaining the LO_SUM in the memory reference.
- This cuts the number of extra insns by one.
-
- Do nothing when generating PIC code and the address is a
- symbolic operand or requires a scratch register. */
-
-#define LEGITIMIZE_RELOAD_ADDRESS(X,MODE,OPNUM,TYPE,IND_LEVELS,WIN) \
-do { \
- /* Decompose SImode constants into hi+lo_sum. We do have to \
- rerecognize what we produce, so be careful. */ \
- if (CONSTANT_P (X) \
- && (MODE != TFmode || TARGET_ARCH64) \
- && GET_MODE (X) == SImode \
- && GET_CODE (X) != LO_SUM && GET_CODE (X) != HIGH \
- && ! (flag_pic \
- && (symbolic_operand (X, Pmode) \
- || pic_address_needs_scratch (X))) \
- && sparc_cmodel <= CM_MEDLOW) \
- { \
- X = gen_rtx_LO_SUM (GET_MODE (X), \
- gen_rtx_HIGH (GET_MODE (X), X), X); \
- push_reload (XEXP (X, 0), NULL_RTX, &XEXP (X, 0), NULL, \
- BASE_REG_CLASS, GET_MODE (X), VOIDmode, 0, 0, \
- OPNUM, TYPE); \
- goto WIN; \
- } \
- /* ??? 64-bit reloads. */ \
+ macro is used in only one place: `find_reloads_address' in reload.c. */
+#define LEGITIMIZE_RELOAD_ADDRESS(X,MODE,OPNUM,TYPE,IND_LEVELS,WIN) \
+do { \
+ int win; \
+ (X) = sparc_legitimize_reload_address ((X), (MODE), (OPNUM), \
+ (int)(TYPE), (IND_LEVELS), &win); \
+ if (win) \
+ goto WIN; \
} while (0)
\f
/* Specify the machine mode that this machine uses