#include "explow.h"
#include "expr.h"
#include "debug.h"
+#include "cfgrtl.h"
#include "common/common-target.h"
#include "gimplify.h"
#include "langhooks.h"
static bool sparc_can_eliminate (const int, const int);
static rtx sparc_builtin_setjmp_frame_value (void);
static void sparc_conditional_register_usage (void);
+static bool sparc_use_pseudo_pic_reg (void);
+static void sparc_init_pic_reg (void);
#ifdef TARGET_ALTERNATE_LONG_DOUBLE_MANGLING
static const char *sparc_mangle_type (const_tree);
#endif
#undef TARGET_CONDITIONAL_REGISTER_USAGE
#define TARGET_CONDITIONAL_REGISTER_USAGE sparc_conditional_register_usage
+#undef TARGET_INIT_PIC_REG
+#define TARGET_INIT_PIC_REG sparc_init_pic_reg
+
+#undef TARGET_USE_PSEUDO_PIC_REG
+#define TARGET_USE_PSEUDO_PIC_REG sparc_use_pseudo_pic_reg
+
#ifdef TARGET_ALTERNATE_LONG_DOUBLE_MANGLING
#undef TARGET_MANGLE_TYPE
#define TARGET_MANGLE_TYPE sparc_mangle_type
return true;
}
+/* Return true if X is a representation of the PIC register. */
+
+static bool
+sparc_pic_register_p (rtx x)
+{
+ if (!REG_P (x) || !pic_offset_table_rtx)
+ return false;
+
+ if (x == pic_offset_table_rtx)
+ return true;
+
+ if (!HARD_REGISTER_P (pic_offset_table_rtx)
+ && (HARD_REGISTER_P (x) || lra_in_progress)
+ && ORIGINAL_REGNO (x) == REGNO (pic_offset_table_rtx))
+ return true;
+
+ return false;
+}
+
#define RTX_OK_FOR_OFFSET_P(X, MODE) \
(CONST_INT_P (X) \
&& INTVAL (X) >= -0x1000 \
}
if ((flag_pic == 1
- && rs1 == pic_offset_table_rtx
+ && sparc_pic_register_p (rs1)
&& !REG_P (rs2)
&& GET_CODE (rs2) != SUBREG
&& GET_CODE (rs2) != LO_SUM
rtx base, offset;
if (GET_CODE (XEXP (orig, 0)) == PLUS
- && XEXP (XEXP (orig, 0), 0) == pic_offset_table_rtx)
+ && sparc_pic_register_p (XEXP (XEXP (orig, 0), 0)))
return orig;
if (reg == 0)
/* This is generated by mov{si,di}_pic_label_ref in PIC mode. */
if (GET_CODE (x) == MINUS
- && REG_P (XEXP (x, 0))
- && REGNO (XEXP (x, 0)) == PIC_OFFSET_TABLE_REGNUM
+ && sparc_pic_register_p (XEXP (x, 0))
&& GET_CODE (XEXP (x, 1)) == LO_SUM
&& GET_CODE (XEXP (XEXP (x, 1), 1)) == UNSPEC
&& XINT (XEXP (XEXP (x, 1), 1), 1) == UNSPEC_MOVE_PIC_LABEL)
sparc_mode_dependent_address_p (const_rtx addr,
addr_space_t as ATTRIBUTE_UNUSED)
{
- if (flag_pic && GET_CODE (addr) == PLUS)
- {
- rtx op0 = XEXP (addr, 0);
- rtx op1 = XEXP (addr, 1);
- if (op0 == pic_offset_table_rtx
- && symbolic_operand (op1, VOIDmode))
- return true;
- }
+ if (GET_CODE (addr) == PLUS
+ && sparc_pic_register_p (XEXP (addr, 0))
+ && symbolic_operand (XEXP (addr, 1), VOIDmode))
+ return true;
return false;
}
/* Wrapper around the load_pcrel_sym{si,di} patterns. */
static rtx
-gen_load_pcrel_sym (rtx op0, rtx op1, rtx op2, rtx op3)
+gen_load_pcrel_sym (rtx op0, rtx op1, rtx op2)
{
int orig_flag_pic = flag_pic;
rtx insn;
/* The load_pcrel_sym{si,di} patterns require absolute addressing. */
flag_pic = 0;
if (TARGET_ARCH64)
- insn = gen_load_pcrel_symdi (op0, op1, op2, op3);
+ insn = gen_load_pcrel_symdi (op0, op1, op2, GEN_INT (REGNO (op0)));
else
- insn = gen_load_pcrel_symsi (op0, op1, op2, op3);
+ insn = gen_load_pcrel_symsi (op0, op1, op2, GEN_INT (REGNO (op0)));
flag_pic = orig_flag_pic;
return insn;
void
load_got_register (void)
{
- /* In PIC mode, this will retrieve pic_offset_table_rtx. */
if (!global_offset_table_rtx)
global_offset_table_rtx = gen_rtx_REG (Pmode, GLOBAL_OFFSET_TABLE_REGNUM);
}
emit_insn (gen_load_pcrel_sym (global_offset_table_rtx, sparc_got (),
- got_helper_rtx,
- GEN_INT (GLOBAL_OFFSET_TABLE_REGNUM)));
+ got_helper_rtx));
}
-
- /* Need to emit this whether or not we obey regdecls,
- since setjmp/longjmp can cause life info to screw up.
- ??? In the case where we don't obey regdecls, this is not sufficient
- since we may not fall out the bottom. */
- emit_use (global_offset_table_rtx);
}
/* Emit a call instruction with the pattern given by PAT. ADDR is the
- sparc_apparent_frame_size,
SORR_SAVE);
- /* Load the GOT register if needed. */
- if (crtl->uses_pic_offset_table)
- load_got_register ();
-
/* Advertise that the data calculated just above are now valid. */
sparc_prologue_data_valid_p = true;
}
- sparc_apparent_frame_size,
SORR_SAVE);
- /* Load the GOT register if needed. */
- if (crtl->uses_pic_offset_table)
- load_got_register ();
-
/* Advertise that the data calculated just above are now valid. */
sparc_prologue_data_valid_p = true;
}
spill_reg = gen_rtx_REG (word_mode, 15); /* %o7 */
start_sequence ();
load_got_register (); /* clobbers %o7 */
+ if (!TARGET_VXWORKS_RTP)
+ pic_offset_table_rtx = global_offset_table_rtx;
scratch = sparc_legitimize_pic_address (funexp, scratch);
seq = get_insns ();
end_sequence ();
global_regs[SPARC_GSR_REG] = 1;
}
+/* Implement TARGET_USE_PSEUDO_PIC_REG. */
+
+static bool
+sparc_use_pseudo_pic_reg (void)
+{
+ return !TARGET_VXWORKS_RTP && flag_pic;
+}
+
+/* Implement TARGET_INIT_PIC_REG. */
+
+static void
+sparc_init_pic_reg (void)
+{
+ edge entry_edge;
+ rtx_insn *seq;
+
+ if (!crtl->uses_pic_offset_table)
+ return;
+
+ start_sequence ();
+ load_got_register ();
+ if (!TARGET_VXWORKS_RTP)
+ emit_move_insn (pic_offset_table_rtx, global_offset_table_rtx);
+ seq = get_insns ();
+ end_sequence ();
+
+ entry_edge = single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun));
+ insert_insn_on_edge (seq, entry_edge);
+ commit_one_edge_insertion (entry_edge);
+}
+
/* Implement TARGET_PREFERRED_RELOAD_CLASS:
- We can't load constants into FP registers.