+2008-08-17 Daniel Jacobowitz <dan@codesourcery.com>
+ Richard Sandiford <rdsandiford@googlemail.com>
+
+ * doc/install.texi (--with-mips-plt): Document.
+ * doc/invoke.texi (-mplt, -mno-plt): Document.
+ * config.gcc (mips*-*-*): Add mips-plt to supported_defaults
+ and handle ${with_mips_plt}.
+ * config/mips/mips.opt (mplt): New option.
+ * config/mips/mips.h (TARGET_ABICALLS_PIC0): New macro.
+ (TARGET_ABICALLS_PIC2): Likewise.
+ (TARGET_GPWORD): Return false for TARGET_ABSOLUTE_ABICALLS.
+ (OPTION_DEFAULT_SPECS): Add a mips-plt entry.
+ (ASM_SPEC): Use !mabi=* instead of !mabi*.
+ (MIPS_CALL): Use TARGET_ABICALLS_PIC2 instead of TARGET_ABICALLS
+ to decide whether to output ".option picX" directives.
+ * config/mips/linux.h (SUBTARGET_ASM_SPEC): Remove -mabi=64 handling.
+ Pass -call_nonpic rather than -KPIC for -mplt.
+ (BASE_DRIVER_SELF_SPECS): Remove -mplt if -mno-shared is not present
+ on the command line. Also remove it when -mabi=64 is used without
+ -msym32.
+ * config/mips/linux64.h (SUBTARGET_ASM_SPEC): Delete.
+ * config/mips/mips.c (mips_use_pic_fn_addr_reg_p): Handle
+ TARGET_ABICALLS_PIC0.
+ (mips_classify_symbol): Use TARGET_ABICALLS_PIC2 instead of
+ TARGET_ABICALLS.
+ (mips16_build_function_stub): Only output ".option pic" directives
+ and PIC stubs if TARGET_ABICALLS_PIC2. Call through $25 instead of $1.
+ (mips16_build_call_stub): Fix comment and remove redundant
+ ".set at"/"set .noat" directives.
+ (mips_function_rodata_section): Use the default behaviour for
+ TARGET_ABSOLUTE_ABICALLS.
+ (mips_file_start): Emit ".option pic0" for TARGET_ABICALLS_PIC0.
+ (mips_global_pointer): Handle TARGET_ABICALLS_PIC0.
+ (mips_restore_gp): Do nothing if the current function doesn't use
+ a global pointer.
+ (mips_expand_prologue): Only save $gp if the current function uses it.
+ Use a normal move for TARGET_ABICALLS_PIC0.
+ (mips_override_options): Only set flag_pic if TARGET_ABICALLS_PIC2.
+
2008-08-17 Richard Sandiford <rdsandiford@googlemail.com>
* config/mips/mips.c (mips_save_reg_p): Don't short-circuit rest
if (mips16_stub_function_p (x))
return false;
- /* When TARGET_ABSOLUTE_ABICALLS is true, locally-defined functions
- use absolute accesses to set up the global pointer. */
- if (TARGET_ABSOLUTE_ABICALLS
- && GET_CODE (x) == SYMBOL_REF
- && mips_symbol_binds_local_p (x)
- && !SYMBOL_REF_EXTERNAL_P (x))
- return false;
+ if (GET_CODE (x) == SYMBOL_REF)
+ {
+ /* If PLTs and copy relocations are available, the static linker
+ will make sure that $25 is valid on entry to the target function. */
+ if (TARGET_ABICALLS_PIC0)
+ return false;
+
+ /* Locally-defined functions use absolute accesses to set up
+ the global pointer. */
+ if (TARGET_ABSOLUTE_ABICALLS
+ && mips_symbol_binds_local_p (x)
+ && !SYMBOL_REF_EXTERNAL_P (x))
+ return false;
+ }
return true;
}
/* Don't use GOT accesses for locally-binding symbols when -mno-shared
is in effect. */
- if (TARGET_ABICALLS
+ if (TARGET_ABICALLS_PIC2
&& !(TARGET_ABSOLUTE_ABICALLS && mips_symbol_binds_local_p (x)))
{
/* There are three cases to consider:
assemble_start_function (stubdecl, stubname);
mips_start_function_definition (stubname, false);
- /* If generating abicalls code, either set up the global pointer or
- switch to absolute mode. */
- if (TARGET_ABSOLUTE_ABICALLS)
- fprintf (asm_out_file, "\t.option\tpic0\n");
- else if (TARGET_ABICALLS)
+ /* If generating pic2 code, either set up the global pointer or
+ switch to pic0. */
+ if (TARGET_ABICALLS_PIC2)
{
- output_asm_insn ("%(.cpload\t%^%)", NULL);
- /* Emit an R_MIPS_NONE relocation to tell the linker what the
- target function is. Use a local GOT access when loading the
- symbol, to cut down on the number of unnecessary GOT entries
- for stubs that aren't needed. */
- output_asm_insn (".reloc\t0,R_MIPS_NONE,%0", &symbol);
- symbol = alias;
+ if (TARGET_ABSOLUTE_ABICALLS)
+ fprintf (asm_out_file, "\t.option\tpic0\n");
+ else
+ {
+ output_asm_insn ("%(.cpload\t%^%)", NULL);
+ /* Emit an R_MIPS_NONE relocation to tell the linker what the
+ target function is. Use a local GOT access when loading the
+ symbol, to cut down on the number of unnecessary GOT entries
+ for stubs that aren't needed. */
+ output_asm_insn (".reloc\t0,R_MIPS_NONE,%0", &symbol);
+ symbol = alias;
+ }
}
- /* Load the address of the MIPS16 function into $at. Do this first so
+ /* Load the address of the MIPS16 function into $25. Do this first so
that targets with coprocessor interlocks can use an MFC1 to fill the
delay slot. */
- fprintf (asm_out_file, "\t.set\tnoat\n");
- output_asm_insn ("la\t%@,%0", &symbol);
+ output_asm_insn ("la\t%^,%0", &symbol);
/* Move the arguments from floating-point registers to general registers. */
mips_output_args_xfer (crtl->args.info.fp_code, 'f');
/* Jump to the MIPS16 function. */
- output_asm_insn ("jr\t%@", NULL);
- fprintf (asm_out_file, "\t.set\tat\n");
+ output_asm_insn ("jr\t%^", NULL);
- if (TARGET_ABSOLUTE_ABICALLS)
+ if (TARGET_ABICALLS_PIC2 && TARGET_ABSOLUTE_ABICALLS)
fprintf (asm_out_file, "\t.option\tpic2\n");
mips_end_function_definition (stubname);
if (!fp_ret_p)
{
- /* Load the address of the MIPS16 function into $at. Do this
+ /* Load the address of the MIPS16 function into $25. Do this
first so that targets with coprocessor interlocks can use
an MFC1 to fill the delay slot. */
- fprintf (asm_out_file, "\t.set\tnoat\n");
if (TARGET_EXPLICIT_RELOCS)
{
output_asm_insn ("lui\t%^,%%hi(%0)", &fn);
{
/* Jump to the previously-loaded address. */
output_asm_insn ("jr\t%^", NULL);
- fprintf (asm_out_file, "\t.set\tat\n");
}
else
{
/* Implement TARGET_ASM_FUNCTION_RODATA_SECTION.
The complication here is that, with the combination TARGET_ABICALLS
- && !TARGET_GPWORD, jump tables will use absolute addresses, and should
- therefore not be included in the read-only part of a DSO. Handle such
- cases by selecting a normal data section instead of a read-only one.
- The logic apes that in default_function_rodata_section. */
+ && !TARGET_ABSOLUTE_ABICALLS && !TARGET_GPWORD, jump tables will use
+ absolute addresses, and should therefore not be included in the
+ read-only part of a DSO. Handle such cases by selecting a normal
+ data section instead of a read-only one. The logic apes that in
+ default_function_rodata_section. */
static section *
mips_function_rodata_section (tree decl)
{
- if (!TARGET_ABICALLS || TARGET_GPWORD)
+ if (!TARGET_ABICALLS || TARGET_ABSOLUTE_ABICALLS || TARGET_GPWORD)
return default_function_rodata_section (decl);
if (decl && DECL_SECTION_NAME (decl))
/* If TARGET_ABICALLS, tell GAS to generate -KPIC code. */
if (TARGET_ABICALLS)
- fprintf (asm_out_file, "\t.abicalls\n");
+ {
+ fprintf (asm_out_file, "\t.abicalls\n");
+ if (TARGET_ABICALLS_PIC0)
+ fprintf (asm_out_file, "\t.option\tpic0\n");
+ }
if (flag_verbose_asm)
fprintf (asm_out_file, "\n%s -G value = %d, Arch = %s, ISA = %d\n",
if (crtl->has_nonlocal_goto)
return GLOBAL_POINTER_REGNUM;
- /* If the gp is never referenced, there's no need to initialize it.
- Note that reload can sometimes introduce constant pool references
- into a function that otherwise didn't need them. For example,
- suppose we have an instruction like:
+ /* There's no need to initialize $gp if it isn't referenced now,
+ and if we can be sure that no new references will be added during
+ or after reload. */
+ if (!df_regs_ever_live_p (GLOBAL_POINTER_REGNUM)
+ && !mips_function_has_gp_insn ())
+ {
+ /* The function doesn't use $gp at the moment. If we're generating
+ -call_nonpic code, no new uses will be introduced during or after
+ reload. */
+ if (TARGET_ABICALLS_PIC0)
+ return 0;
- (set (reg:DF R1) (float:DF (reg:SI R2)))
+ /* We need to handle the following implicit gp references:
- If R2 turns out to be constant such as 1, the instruction may have a
- REG_EQUAL note saying that R1 == 1.0. Reload then has the option of
- using this constant if R2 doesn't get allocated to a register.
+ - Reload can sometimes introduce constant pool references
+ into a function that otherwise didn't need them. For example,
+ suppose we have an instruction like:
- In cases like these, reload will have added the constant to the pool
- but no instruction will yet refer to it. */
- if (!df_regs_ever_live_p (GLOBAL_POINTER_REGNUM)
- && !crtl->uses_const_pool
- && !mips16_cfun_returns_in_fpr_p ()
- && !mips_function_has_gp_insn ())
- return 0;
+ (set (reg:DF R1) (float:DF (reg:SI R2)))
+
+ If R2 turns out to be constant such as 1, the instruction may
+ have a REG_EQUAL note saying that R1 == 1.0. Reload then has
+ the option of using this constant if R2 doesn't get allocated
+ to a register.
+
+ In cases like these, reload will have added the constant to the
+ pool but no instruction will yet refer to it.
+
+ - MIPS16 functions that return in FPRs need to call an
+ external libgcc routine. */
+ if (!crtl->uses_const_pool
+ && !mips16_cfun_returns_in_fpr_p ())
+ return 0;
+ }
/* We need a global pointer, but perhaps we can use a call-clobbered
register instead of $gp. */
{
gcc_assert (TARGET_ABICALLS && TARGET_OLDABI);
+ if (cfun->machine->global_pointer == 0)
+ return;
+
if (TARGET_MIPS16)
{
mips_emit_move (temp, mips_cprestore_slot (temp));
mips_emit_loadgp ();
/* Initialize the $gp save slot. */
- if (frame->cprestore_size > 0)
+ if (frame->cprestore_size > 0
+ && cfun->machine->global_pointer != 0)
{
if (TARGET_MIPS16)
mips_emit_move (mips_cprestore_slot (MIPS_PROLOGUE_TEMP (Pmode)),
MIPS16_PIC_TEMP);
- else
+ else if (TARGET_ABICALLS_PIC2)
emit_insn (gen_cprestore (GEN_INT (frame->args_size)));
+ else
+ emit_move_insn (mips_cprestore_slot (MIPS_PROLOGUE_TEMP (Pmode)),
+ pic_offset_table_rtx);
}
/* If we are profiling, make sure no instructions are scheduled before
target_flags &= ~MASK_ABICALLS;
}
- if (TARGET_ABICALLS)
+ if (TARGET_ABICALLS_PIC2)
/* We need to set flag_pic for executables as well as DSOs
because we may reference symbols that are not defined in
the final executable. (MIPS does not use things like
copy relocs, for example.)
- Also, there is a body of code that uses __PIC__ to distinguish
- between -mabicalls and -mno-abicalls code. */
+ There is a body of code that uses __PIC__ to distinguish
+ between -mabicalls and -mno-abicalls code. The non-__PIC__
+ variant is usually appropriate for TARGET_ABICALLS_PIC0, as
+ long as any indirect jumps use $25. */
flag_pic = 1;
/* -mvr4130-align is a "speed over size" optimization: it usually produces
/* True if we are generating position-independent VxWorks RTP code. */
#define TARGET_RTP_PIC (TARGET_VXWORKS_RTP && flag_pic)
+/* True if the output file is marked as ".abicalls; .option pic0"
+ (-call_nonpic). */
+#define TARGET_ABICALLS_PIC0 \
+ (TARGET_ABSOLUTE_ABICALLS && TARGET_PLT)
+
+/* True if the output file is marked as ".abicalls; .option pic2" (-KPIC). */
+#define TARGET_ABICALLS_PIC2 \
+ (TARGET_ABICALLS && !TARGET_ABICALLS_PIC0)
+
/* True if the call patterns should be split into a jalr followed by
an instruction to restore $gp. It is only safe to split the load
from the call when every use of $gp is explicit. */
Although GAS does understand .gpdword, the SGI linker mishandles
the relocations GAS generates (R_MIPS_GPREL32 followed by R_MIPS_64).
We therefore disable GP-relative switch tables for n64 on IRIX targets. */
-#define TARGET_GPWORD (TARGET_ABICALLS && !(mips_abi == ABI_64 && TARGET_IRIX))
+#define TARGET_GPWORD \
+ (TARGET_ABICALLS \
+ && !TARGET_ABSOLUTE_ABICALLS \
+ && !(mips_abi == ABI_64 && TARGET_IRIX))
/* Generate mips16 code */
#define TARGET_MIPS16 ((target_flags & MASK_MIPS16) != 0)
{"abi", "%{!mabi=*:-mabi=%(VALUE)}" }, \
{"float", "%{!msoft-float:%{!mhard-float:-m%(VALUE)-float}}" }, \
{"divide", "%{!mdivide-traps:%{!mdivide-breaks:-mdivide-%(VALUE)}}" }, \
- {"llsc", "%{!mllsc:%{!mno-llsc:-m%(VALUE)}}" }
+ {"llsc", "%{!mllsc:%{!mno-llsc:-m%(VALUE)}}" }, \
+ {"mips-plt", "%{!mplt:%{!mno-plt:-m%(VALUE)}}" }
#define GENERATE_DIVIDE_TRAPS (TARGET_DIVIDE_TRAPS \
%{mfix-vr4120} %{mfix-vr4130} \
%(subtarget_asm_optimizing_spec) \
%(subtarget_asm_debugging_spec) \
-%{mabi=*} %{!mabi*: %(asm_abi_default_spec)} \
+%{mabi=*} %{!mabi=*: %(asm_abi_default_spec)} \
%{mgp32} %{mgp64} %{march=*} %{mxgot:-xgot} \
%{mfp32} %{mfp64} \
%{mshared} %{mno-shared} \
? "%*" INSN "\t%" #OPNO "%/" \
: REG_P (OPERANDS[OPNO]) \
? "%*" INSN "r\t%" #OPNO "%/" \
- : TARGET_ABICALLS \
+ : TARGET_ABICALLS_PIC2 \
? (".option\tpic0\n\t" \
"%*" INSN "\t%" #OPNO "%/\n\t" \
".option\tpic2") \