aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/sparc/sparc.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config/sparc/sparc.c')
-rw-r--r--gcc/config/sparc/sparc.c122
1 files changed, 67 insertions, 55 deletions
diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c
index 43aa2f17c87..9d92dba6601 100644
--- a/gcc/config/sparc/sparc.c
+++ b/gcc/config/sparc/sparc.c
@@ -311,7 +311,8 @@ static rtx sparc_builtin_saveregs (void);
static int epilogue_renumber (rtx *, int);
static bool sparc_assemble_integer (rtx, unsigned int, int);
static int set_extends (rtx);
-static void load_pic_register (void);
+static void emit_pic_helper (void);
+static void load_pic_register (bool);
static int save_or_restore_regs (int, int, rtx, int, int);
static void emit_save_regs (void);
static void emit_restore_regs (void);
@@ -359,6 +360,7 @@ static bool sparc_pass_by_reference (CUMULATIVE_ARGS *,
static int sparc_arg_partial_bytes (CUMULATIVE_ARGS *,
enum machine_mode, tree, bool);
static void sparc_dwarf_handle_frame_unspec (const char *, rtx, int);
+static void sparc_file_end (void);
#ifdef SUBTARGET_ATTRIBUTE_TABLE
const struct attribute_spec sparc_attribute_table[];
#endif
@@ -501,6 +503,9 @@ enum processor_type sparc_cpu;
#undef TARGET_RELAXED_ORDERING
#define TARGET_RELAXED_ORDERING SPARC_RELAXED_ORDERING
+#undef TARGET_ASM_FILE_END
+#define TARGET_ASM_FILE_END sparc_file_end
+
struct gcc_target targetm = TARGET_INITIALIZER;
/* Validate and override various options, and do some machine dependent
@@ -3351,13 +3356,12 @@ sparc_cannot_force_const_mem (rtx x)
}
}
-/* The table we use to reference PIC data. */
+/* PIC support. */
+static GTY(()) char pic_helper_symbol_name[256];
+static GTY(()) rtx pic_helper_symbol;
+static GTY(()) bool pic_helper_emitted_p = false;
static GTY(()) rtx global_offset_table;
-/* The function we use to get at it. */
-static GTY(()) rtx add_pc_to_pic_symbol;
-static GTY(()) char add_pc_to_pic_symbol_name[256];
-
/* Ensure that we are not using patterns that are not OK with PIC. */
int
@@ -3492,7 +3496,7 @@ legitimate_pic_operand_p (rtx x)
int
legitimate_address_p (enum machine_mode mode, rtx addr, int strict)
{
- rtx rs1 = NULL, rs2 = NULL, imm1 = NULL, imm2;
+ rtx rs1 = NULL, rs2 = NULL, imm1 = NULL;
if (REG_P (addr) || GET_CODE (addr) == SUBREG)
rs1 = addr;
@@ -3556,7 +3560,6 @@ legitimate_address_p (enum machine_mode mode, rtx addr, int strict)
&& ! TARGET_CM_MEDMID
&& RTX_OK_FOR_OLO10_P (rs2))
{
- imm2 = rs2;
rs2 = NULL;
imm1 = XEXP (rs1, 1);
rs1 = XEXP (rs1, 0);
@@ -3572,25 +3575,10 @@ legitimate_address_p (enum machine_mode mode, rtx addr, int strict)
if (! CONSTANT_P (imm1) || tls_symbolic_operand (rs1))
return 0;
- if (USE_AS_OFFSETABLE_LO10)
- {
- /* We can't allow TFmode, because an offset greater than or equal to
- the alignment (8) may cause the LO_SUM to overflow if !v9. */
- if (mode == TFmode && ! TARGET_V9)
- return 0;
- }
- else
- {
- /* We prohibit LO_SUM for TFmode when there are no quad move insns
- and we consequently need to split. We do this because LO_SUM
- is not an offsettable address. If we get the situation in reload
- where source and destination of a movtf pattern are both MEMs with
- LO_SUM address, then only one of them gets converted to an
- offsettable address. */
- if (mode == TFmode
- && ! (TARGET_FPU && TARGET_ARCH64 && TARGET_HARD_QUAD))
- return 0;
- }
+ /* We can't allow TFmode in 32-bit mode, because an offset greater
+ than the alignment (8) may cause the LO_SUM to overflow. */
+ if (mode == TFmode && !TARGET_64BIT)
+ return 0;
}
else if (GET_CODE (addr) == CONST_INT && SMALL_INT (addr))
return 1;
@@ -3947,46 +3935,57 @@ legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED, enum machine_mode mode)
return x;
}
-/* Emit the special PIC prologue. */
+/* Emit the special PIC helper function. */
static void
-load_pic_register (void)
+emit_pic_helper (void)
{
- int orig_flag_pic = flag_pic;
+ const char *pic_name = reg_names[REGNO (pic_offset_table_rtx)];
+ int align;
- /* If we haven't emitted the special helper function, do so now. */
- if (add_pc_to_pic_symbol_name[0] == 0)
- {
- const char *pic_name = reg_names[REGNO (pic_offset_table_rtx)];
- int align;
+ text_section ();
- ASM_GENERATE_INTERNAL_LABEL (add_pc_to_pic_symbol_name, "LADDPC", 0);
- text_section ();
+ align = floor_log2 (FUNCTION_BOUNDARY / BITS_PER_UNIT);
+ if (align > 0)
+ ASM_OUTPUT_ALIGN (asm_out_file, align);
+ ASM_OUTPUT_LABEL (asm_out_file, pic_helper_symbol_name);
+ if (flag_delayed_branch)
+ fprintf (asm_out_file, "\tjmp\t%%o7+8\n\t add\t%%o7, %s, %s\n",
+ pic_name, pic_name);
+ else
+ fprintf (asm_out_file, "\tadd\t%%o7, %s, %s\n\tjmp\t%%o7+8\n\t nop\n",
+ pic_name, pic_name);
- align = floor_log2 (FUNCTION_BOUNDARY / BITS_PER_UNIT);
- if (align > 0)
- ASM_OUTPUT_ALIGN (asm_out_file, align);
- ASM_OUTPUT_LABEL (asm_out_file, add_pc_to_pic_symbol_name);
- if (flag_delayed_branch)
- fprintf (asm_out_file, "\tjmp %%o7+8\n\t add\t%%o7, %s, %s\n",
- pic_name, pic_name);
- else
- fprintf (asm_out_file, "\tadd\t%%o7, %s, %s\n\tjmp %%o7+8\n\t nop\n",
- pic_name, pic_name);
+ pic_helper_emitted_p = true;
+}
+
+/* Emit code to load the PIC register. */
+
+static void
+load_pic_register (bool delay_pic_helper)
+{
+ int orig_flag_pic = flag_pic;
+
+ /* If we haven't initialized the special PIC symbols, do so now. */
+ if (!pic_helper_symbol_name[0])
+ {
+ ASM_GENERATE_INTERNAL_LABEL (pic_helper_symbol_name, "LADDPC", 0);
+ pic_helper_symbol = gen_rtx_SYMBOL_REF (Pmode, pic_helper_symbol_name);
+ global_offset_table = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_");
}
- /* Initialize every time through, since we can't easily
- know this to be permanent. */
- global_offset_table = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_");
- add_pc_to_pic_symbol = gen_rtx_SYMBOL_REF (Pmode, add_pc_to_pic_symbol_name);
+ /* If we haven't emitted the special PIC helper function, do so now unless
+ we are requested to delay it. */
+ if (!delay_pic_helper && !pic_helper_emitted_p)
+ emit_pic_helper ();
flag_pic = 0;
if (TARGET_ARCH64)
emit_insn (gen_load_pcrel_symdi (pic_offset_table_rtx, global_offset_table,
- add_pc_to_pic_symbol));
+ pic_helper_symbol));
else
emit_insn (gen_load_pcrel_symsi (pic_offset_table_rtx, global_offset_table,
- add_pc_to_pic_symbol));
+ pic_helper_symbol));
flag_pic = orig_flag_pic;
/* Need to emit this whether or not we obey regdecls,
@@ -4635,7 +4634,7 @@ sparc_expand_prologue (void)
/* Load the PIC register if needed. */
if (flag_pic && current_function_uses_pic_offset_table)
- load_pic_register ();
+ load_pic_register (false);
}
/* This function generates the assembly code for function entry, which boils
@@ -9052,7 +9051,9 @@ sparc_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
{
spill_reg = gen_rtx_REG (word_mode, 15); /* %o7 */
start_sequence ();
- load_pic_register (); /* clobbers %o7 */
+ /* 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);
seq = get_insns ();
end_sequence ();
@@ -9203,4 +9204,15 @@ sparc_output_dwarf_dtprel (FILE *file, int size, rtx x)
fputs (")", file);
}
+static
+void sparc_file_end (void)
+{
+ /* If we haven't emitted the special PIC helper function, do so now. */
+ if (pic_helper_symbol_name[0] && !pic_helper_emitted_p)
+ emit_pic_helper ();
+
+ if (NEED_INDICATE_EXEC_STACK)
+ file_end_indicate_exec_stack ();
+}
+
#include "gt-sparc.h"