#define HAVE_64BIT_OBJECTS (mips_abi == N64_ABI)
-/* We can only have 64bit addresses if the object file format
- supports it. */
+/* We can only have 64bit addresses if the object file format supports it. */
#define HAVE_32BIT_ADDRESSES \
(HAVE_32BIT_GPRS \
- || ((bfd_arch_bits_per_address (stdoutput) == 32 \
- || ! HAVE_64BIT_OBJECTS) \
- && mips_pic != EMBEDDED_PIC))
+ || (bfd_arch_bits_per_address (stdoutput) == 32 \
+ || ! HAVE_64BIT_OBJECTS)) \
#define HAVE_64BIT_ADDRESSES (! HAVE_32BIT_ADDRESSES)
|| (mips_opts.mips16
&& (pinfo & MIPS16_INSN_WRITE_31)
&& insn_uses_reg (&prev_insn, RA, MIPS_GR_REG))
- /* If we are generating embedded PIC code, the branch
- might be expanded into a sequence which uses $at, so
- we can't swap with an instruction which reads it. */
- || (mips_pic == EMBEDDED_PIC
- && insn_uses_reg (&prev_insn, AT, MIPS_GR_REG))
/* If the previous previous instruction has a load
delay, and sets a register that the branch reads, we
can not swap. */
|| *r == BFD_RELOC_MIPS_GOT_PAGE
|| *r == BFD_RELOC_MIPS_GOT_OFST
|| *r == BFD_RELOC_MIPS_GOT_LO16
- || *r == BFD_RELOC_MIPS_CALL_LO16
- || (ep->X_op == O_subtract
- && *r == BFD_RELOC_PCREL_LO16));
+ || *r == BFD_RELOC_MIPS_CALL_LO16);
continue;
case 'u':
|| *r == BFD_RELOC_HI16
|| *r == BFD_RELOC_GPREL16
|| *r == BFD_RELOC_MIPS_GOT_HI16
- || *r == BFD_RELOC_MIPS_CALL_HI16))
- || (ep->X_op == O_subtract
- && *r == BFD_RELOC_PCREL_HI16_S)));
+ || *r == BFD_RELOC_MIPS_CALL_HI16))));
continue;
case 'p':
}
}
}
- else if (mips_pic == EMBEDDED_PIC)
- {
- /* We always do
- addiu $reg,$gp,<sym> (BFD_RELOC_GPREL16)
- */
- macro_build (ep, ADDRESS_ADDI_INSN, "t,r,j",
- reg, mips_gp_register, BFD_RELOC_GPREL16);
- }
else
abort ();
}
used_at = 0;
}
- /* When generating embedded PIC code, we permit expressions of
- the form
- la $treg,foo-bar
- la $treg,foo-bar($breg)
- where bar is an address in the current section. These are used
- when getting the addresses of functions. We don't permit
- X_add_number to be non-zero, because if the symbol is
- external the relaxing code needs to know that any addend is
- purely the offset to X_op_symbol. */
- if (mips_pic == EMBEDDED_PIC
- && offset_expr.X_op == O_subtract
- && (symbol_constant_p (offset_expr.X_op_symbol)
- ? S_GET_SEGMENT (offset_expr.X_op_symbol) == now_seg
- : (symbol_equated_p (offset_expr.X_op_symbol)
- && (S_GET_SEGMENT
- (symbol_get_value_expression (offset_expr.X_op_symbol)
- ->X_add_symbol)
- == now_seg)))
- && (offset_expr.X_add_number == 0
- || OUTPUT_FLAVOR == bfd_target_elf_flavour))
- {
- if (breg == 0)
- {
- tempreg = treg;
- used_at = 0;
- macro_build (&offset_expr, "lui", "t,u",
- tempreg, BFD_RELOC_PCREL_HI16_S);
- }
- else
- {
- macro_build (&offset_expr, "lui", "t,u",
- tempreg, BFD_RELOC_PCREL_HI16_S);
- macro_build (NULL,
- (dbl || HAVE_64BIT_ADDRESSES) ? "daddu" : "addu",
- "d,v,t", tempreg, tempreg, breg);
- }
- macro_build (&offset_expr,
- (dbl || HAVE_64BIT_ADDRESSES) ? "daddiu" : "addiu",
- "t,r,j", treg, tempreg, BFD_RELOC_PCREL_LO16);
- if (! used_at)
- return;
- break;
- }
-
if (offset_expr.X_op != O_symbol
&& offset_expr.X_op != O_constant)
{
if (offset_expr.X_op == O_constant)
load_register (tempreg, &offset_expr,
- ((mips_pic == EMBEDDED_PIC || mips_pic == NO_PIC)
+ (mips_pic == NO_PIC
? (dbl || HAVE_64BIT_ADDRESSES)
: HAVE_64BIT_ADDRESSES));
else if (mips_pic == NO_PIC)
}
relax_end ();
}
- else if (mips_pic == EMBEDDED_PIC)
- {
- /* We use
- addiu $tempreg,$gp,<sym> (BFD_RELOC_GPREL16)
- */
- macro_build (&offset_expr, ADDRESS_ADDI_INSN, "t,r,j", tempreg,
- mips_gp_register, BFD_RELOC_GPREL16);
- }
else
abort ();
{
char *s;
- if (mips_pic == EMBEDDED_PIC || mips_pic == NO_PIC)
+ if (mips_pic == NO_PIC)
s = (dbl || HAVE_64BIT_ADDRESSES) ? "daddu" : "addu";
else
s = ADDRESS_ADD_INSN;
dreg = RA;
/* Fall through. */
case M_JAL_2:
- if (mips_pic == NO_PIC
- || mips_pic == EMBEDDED_PIC)
+ if (mips_pic == NO_PIC)
macro_build (NULL, "jalr", "d,s", dreg, sreg);
else if (mips_pic == SVR4_PIC)
{
}
}
}
- else if (mips_pic == EMBEDDED_PIC)
- {
- macro_build (&offset_expr, "bal", "p");
- /* The linker may expand the call to a longer sequence which
- uses $at, so we must break rather than return. */
- break;
- }
else
abort ();
^ 0x80000000) - 0x80000000);
}
- /* For embedded PIC, we allow loads where the offset is calculated
- by subtracting a symbol in the current segment from an unknown
- symbol, relative to a base register, e.g.:
- <op> $treg, <sym>-<localsym>($breg)
- This is used by the compiler for switch statements. */
- if (mips_pic == EMBEDDED_PIC
- && offset_expr.X_op == O_subtract
- && (symbol_constant_p (offset_expr.X_op_symbol)
- ? S_GET_SEGMENT (offset_expr.X_op_symbol) == now_seg
- : (symbol_equated_p (offset_expr.X_op_symbol)
- && (S_GET_SEGMENT
- (symbol_get_value_expression (offset_expr.X_op_symbol)
- ->X_add_symbol)
- == now_seg)))
- && breg != 0
- && (offset_expr.X_add_number == 0
- || OUTPUT_FLAVOR == bfd_target_elf_flavour))
- {
- /* For this case, we output the instructions:
- lui $tempreg,<sym> (BFD_RELOC_PCREL_HI16_S)
- addiu $tempreg,$tempreg,$breg
- <op> $treg,<sym>($tempreg) (BFD_RELOC_PCREL_LO16)
- If the relocation would fit entirely in 16 bits, it would be
- nice to emit:
- <op> $treg,<sym>($breg) (BFD_RELOC_PCREL_LO16)
- instead, but that seems quite difficult. */
- macro_build (&offset_expr, "lui", "t,u", tempreg,
- BFD_RELOC_PCREL_HI16_S);
- macro_build (NULL,
- ((bfd_arch_bits_per_address (stdoutput) == 32
- || ! ISA_HAS_64BIT_REGS (mips_opts.isa))
- ? "addu" : "daddu"),
- "d,v,t", tempreg, tempreg, breg);
- macro_build (&offset_expr, s, fmt, treg,
- BFD_RELOC_PCREL_LO16, tempreg);
- if (! used_at)
- return;
- break;
- }
-
if (offset_expr.X_op != O_constant
&& offset_expr.X_op != O_symbol)
{
BFD_RELOC_MIPS_GOT_OFST, tempreg);
relax_end ();
}
- else if (mips_pic == EMBEDDED_PIC)
- {
- /* If there is no base register, we want
- <op> $treg,<sym>($gp) (BFD_RELOC_GPREL16)
- If there is a base register, we want
- addu $tempreg,$breg,$gp
- <op> $treg,<sym>($tempreg) (BFD_RELOC_GPREL16)
- */
- assert (offset_expr.X_op == O_symbol);
- if (breg == 0)
- {
- macro_build (&offset_expr, s, fmt, treg, BFD_RELOC_GPREL16,
- mips_gp_register);
- used_at = 0;
- }
- else
- {
- macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t",
- tempreg, breg, mips_gp_register);
- macro_build (&offset_expr, s, fmt, treg,
- BFD_RELOC_GPREL16, tempreg);
- }
- }
else
abort ();
macro_build (&offset_expr, ADDRESS_LOAD_INSN, "t,o(b)", AT,
BFD_RELOC_MIPS_GOT16, mips_gp_register);
}
- else if (mips_pic == EMBEDDED_PIC)
- {
- /* For embedded PIC we pick up the entire address off $gp in
- a single instruction. */
- macro_build (&offset_expr, ADDRESS_ADDI_INSN, "t,r,j", AT,
- mips_gp_register, BFD_RELOC_GPREL16);
- offset_expr.X_op = O_constant;
- offset_expr.X_add_number = 0;
- }
else
abort ();
fmt = "t,o(b)";
ldd_std:
- /* We do _not_ bother to allow embedded PIC (symbol-local_symbol)
- loads for the case of doing a pair of loads to simulate an 'ld'.
- This is not currently done by the compiler, and assembly coders
- writing embedded-pic code can cope. */
-
if (offset_expr.X_op != O_symbol
&& offset_expr.X_op != O_constant)
{
mips_optimize = hold_mips_optimize;
relax_end ();
}
- else if (mips_pic == EMBEDDED_PIC)
- {
- /* If there is no base register, we use
- <op> $treg,<sym>($gp) (BFD_RELOC_GPREL16)
- <op> $treg+1,<sym>+4($gp) (BFD_RELOC_GPREL16)
- If we have a base register, we use
- addu $at,$breg,$gp
- <op> $treg,<sym>($at) (BFD_RELOC_GPREL16)
- <op> $treg+1,<sym>+4($at) (BFD_RELOC_GPREL16)
- */
- if (breg == 0)
- {
- tempreg = mips_gp_register;
- used_at = 0;
- }
- else
- {
- macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t",
- AT, breg, mips_gp_register);
- tempreg = AT;
- used_at = 1;
- }
-
- /* Itbl support may require additional care here. */
- macro_build (&offset_expr, s, fmt, coproc ? treg + 1 : treg,
- BFD_RELOC_GPREL16, tempreg);
- offset_expr.X_add_number += 4;
- /* Itbl support may require additional care here. */
- macro_build (&offset_expr, s, fmt, coproc ? treg : treg + 1,
- BFD_RELOC_GPREL16, tempreg);
- }
else
abort ();
The .lit4 and .lit8 sections are only used if
permitted by the -G argument.
- When generating embedded PIC code, we use the
- .lit8 section but not the .lit4 section (we can do
- .lit4 inline easily; we need to put .lit8
- somewhere in the data segment, and using .lit8
- permits the linker to eventually combine identical
- .lit8 entries).
-
The code below needs to know whether the target register
is 32 or 64 bits wide. It relies on the fact 'f' and
'F' are used with GPR-based instructions and 'l' and
if (*args == 'f'
|| (*args == 'l'
- && (mips_pic == EMBEDDED_PIC
- || g_switch_value < 4
+ && (g_switch_value < 4
|| (temp[0] == 0 && temp[1] == 0)
|| (temp[2] == 0 && temp[3] == 0))))
{
default: /* unused default case avoids warnings. */
case 'L':
newname = RDATA_SECTION_NAME;
- if ((g_switch_value >= 8)
- || mips_pic == EMBEDDED_PIC)
+ if (g_switch_value >= 8)
newname = ".lit8";
break;
case 'F':
- if (mips_pic == EMBEDDED_PIC)
- newname = ".lit8";
- else
- newname = RDATA_SECTION_NAME;
+ newname = RDATA_SECTION_NAME;
break;
case 'l':
assert (g_switch_value >= 4);
#endif /* OBJ_ELF */
case 'G':
- if (mips_pic == SVR4_PIC || mips_pic == EMBEDDED_PIC)
+ if (mips_pic == SVR4_PIC)
{
- as_bad (_("-G may not be used with SVR4 or embedded PIC code"));
+ as_bad (_("-G may not be used with SVR4 PIC code"));
return 0;
}
else
}
}
-/* When generating embedded PIC code we need to use a special
- relocation to represent the difference of two symbols in the .text
- section (switch tables use a difference of this sort). See
- include/coff/mips.h for details. This macro checks whether this
- fixup requires the special reloc. */
-#define SWITCH_TABLE(fixp) \
- ((fixp)->fx_r_type == BFD_RELOC_32 \
- && OUTPUT_FLAVOR != bfd_target_elf_flavour \
- && (fixp)->fx_addsy != NULL \
- && (fixp)->fx_subsy != NULL \
- && S_GET_SEGMENT ((fixp)->fx_addsy) == text_section \
- && S_GET_SEGMENT ((fixp)->fx_subsy) == text_section)
-
-/* When generating embedded PIC code we must keep all PC relative
- relocations, in case the linker has to relax a call. We also need
- to keep relocations for switch table entries.
-
- We may have combined relocations without symbols in the N32/N64 ABI.
+/* We may have combined relocations without symbols in the N32/N64 ABI.
We have to prevent gas from dropping them. */
int
|| fixp->fx_r_type == BFD_RELOC_LO16))
return 1;
- return (mips_pic == EMBEDDED_PIC
- && (fixp->fx_pcrel
- || SWITCH_TABLE (fixp)
- || fixp->fx_r_type == BFD_RELOC_PCREL_HI16_S
- || fixp->fx_r_type == BFD_RELOC_PCREL_LO16));
+ return 0;
}
/* This hook is called before a fix is simplified. We don't really
whole function). */
if (fixP->fx_r_type == BFD_RELOC_16_PCREL_S2
- && (((OUTPUT_FLAVOR == bfd_target_ecoff_flavour
- || OUTPUT_FLAVOR == bfd_target_elf_flavour)
- && mips_pic != EMBEDDED_PIC)
+ && ((OUTPUT_FLAVOR == bfd_target_ecoff_flavour
+ || OUTPUT_FLAVOR == bfd_target_elf_flavour)
|| bfd_reloc_type_lookup (stdoutput, BFD_RELOC_16_PCREL_S2) == NULL)
&& fixP->fx_addsy)
{
buf = (bfd_byte *) (fixP->fx_frag->fr_literal + fixP->fx_where);
/* We are not done if this is a composite relocation to set up gp. */
- if (fixP->fx_addsy == NULL && ! fixP->fx_pcrel
+ assert (! fixP->fx_pcrel);
+ if (fixP->fx_addsy == NULL
&& !(fixP->fx_r_type == BFD_RELOC_MIPS_SUB
|| (fixP->fx_r_type == BFD_RELOC_64
&& (previous_fx_r_type == BFD_RELOC_GPREL32
case BFD_RELOC_MIPS_CALL_HI16:
case BFD_RELOC_MIPS_CALL_LO16:
case BFD_RELOC_MIPS16_GPREL:
- if (fixP->fx_pcrel)
- as_bad_where (fixP->fx_file, fixP->fx_line,
- _("Invalid PC relative reloc"));
+ assert (! fixP->fx_pcrel);
/* Nothing needed to do. The value comes from the reloc entry */
break;
*valP = 0;
break;
- case BFD_RELOC_PCREL_HI16_S:
- /* The addend for this is tricky if it is internal, so we just
- do everything here rather than in bfd_install_relocation. */
- if (OUTPUT_FLAVOR == bfd_target_elf_flavour && !fixP->fx_done)
- break;
- if (fixP->fx_addsy
- && (symbol_get_bfdsym (fixP->fx_addsy)->flags & BSF_SECTION_SYM) == 0)
- {
- /* For an external symbol adjust by the address to make it
- pcrel_offset. We use the address of the RELLO reloc
- which follows this one. */
- *valP += (fixP->fx_next->fx_frag->fr_address
- + fixP->fx_next->fx_where);
- }
- *valP = ((*valP + 0x8000) >> 16) & 0xffff;
- if (target_big_endian)
- buf += 2;
- md_number_to_chars (buf, *valP, 2);
- break;
-
- case BFD_RELOC_PCREL_LO16:
- /* The addend for this is tricky if it is internal, so we just
- do everything here rather than in bfd_install_relocation. */
- if (OUTPUT_FLAVOR == bfd_target_elf_flavour && !fixP->fx_done)
- break;
- if (fixP->fx_addsy
- && (symbol_get_bfdsym (fixP->fx_addsy)->flags & BSF_SECTION_SYM) == 0)
- *valP += fixP->fx_frag->fr_address + fixP->fx_where;
- if (target_big_endian)
- buf += 2;
- md_number_to_chars (buf, *valP, 2);
- break;
-
case BFD_RELOC_64:
/* This is handled like BFD_RELOC_32, but we output a sign
extended value if we are only 32 bits. */
- if (fixP->fx_done
- || (mips_pic == EMBEDDED_PIC && SWITCH_TABLE (fixP)))
+ if (fixP->fx_done)
{
if (8 <= sizeof (valueT))
md_number_to_chars (buf, *valP, 8);
case BFD_RELOC_32:
/* If we are deleting this reloc entry, we must fill in the
value now. This can happen if we have a .word which is not
- resolved when it appears but is later defined. We also need
- to fill in the value if this is an embedded PIC switch table
- entry. */
- if (fixP->fx_done
- || (mips_pic == EMBEDDED_PIC && SWITCH_TABLE (fixP)))
+ resolved when it appears but is later defined. */
+ if (fixP->fx_done)
md_number_to_chars (buf, *valP, 4);
break;
break;
case BFD_RELOC_LO16:
+ /* FIXME: Now that embedded-PIC is gone, some of this code/comment
+ may be safe to remove, but if so it's not obvious. */
/* When handling an embedded PIC switch statement, we can wind
up deleting a LO16 reloc. See the 'o' case in mips_ip. */
if (fixP->fx_done)
{
segT seg;
- /* When generating embedded PIC code, we only use the .text, .lit8,
- .sdata and .sbss sections. We change the .data and .rdata
- pseudo-ops to use .sdata. */
- if (mips_pic == EMBEDDED_PIC
- && (sec == 'd' || sec == 'r'))
- sec = 's';
-
#ifdef OBJ_ELF
/* The ELF backend needs to know that we are changing sections, so
that .previous works correctly. We could do something like check
#ifdef OBJ_ELF
/* A global or weak symbol is treated as external. */
&& (OUTPUT_FLAVOR != bfd_target_elf_flavour
- || (! S_IS_WEAK (sym)
- && (! S_IS_EXTERNAL (sym)
- || mips_pic == EMBEDDED_PIC)))
+ || (! S_IS_WEAK (sym) && ! S_IS_EXTERNAL (sym)))
#endif
);
}
*reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
- if (mips_pic == EMBEDDED_PIC
- && SWITCH_TABLE (fixp))
- {
- /* For a switch table entry we use a special reloc. The addend
- is actually the difference between the reloc address and the
- subtrahend. */
- reloc->addend = reloc->address - S_GET_VALUE (fixp->fx_subsy);
- if (OUTPUT_FLAVOR != bfd_target_ecoff_flavour)
- as_fatal (_("Double check fx_r_type in tc-mips.c:tc_gen_reloc"));
- fixp->fx_r_type = BFD_RELOC_GPREL32;
- }
- else if (fixp->fx_pcrel)
- {
- bfd_vma pcrel_address;
-
- /* Set PCREL_ADDRESS to this relocation's "PC". The PC for high
- high-part relocs is the address of the low-part reloc. */
- if (fixp->fx_r_type == BFD_RELOC_PCREL_HI16_S)
- {
- assert (fixp->fx_next != NULL
- && fixp->fx_next->fx_r_type == BFD_RELOC_PCREL_LO16);
- pcrel_address = (fixp->fx_next->fx_where
- + fixp->fx_next->fx_frag->fr_address);
- }
- else
- pcrel_address = reloc->address;
-
- if (OUTPUT_FLAVOR == bfd_target_elf_flavour)
- {
- /* At this point, fx_addnumber is "symbol offset - pcrel_address".
- Relocations want only the symbol offset. */
- reloc->addend = fixp->fx_addnumber + pcrel_address;
- }
- else if (fixp->fx_r_type == BFD_RELOC_PCREL_LO16
- || fixp->fx_r_type == BFD_RELOC_PCREL_HI16_S)
- {
- /* We use a special addend for an internal RELLO or RELHI reloc. */
- if (symbol_section_p (fixp->fx_addsy))
- reloc->addend = pcrel_address - S_GET_VALUE (fixp->fx_subsy);
- else
- reloc->addend = fixp->fx_addnumber + pcrel_address;
- }
- else
- {
- /* A gruesome hack which is a result of the gruesome gas reloc
- handling. */
- reloc->addend = pcrel_address;
- }
- }
- else
- reloc->addend = fixp->fx_addnumber;
+ assert (! fixp->fx_pcrel);
+ reloc->addend = fixp->fx_addnumber;
/* Since the old MIPS ELF ABI uses Rel instead of Rela, encode the vtable
entry to be used in the relocation's section offset. */
reloc->addend = 0;
}
- /* Since DIFF_EXPR_OK is defined in tc-mips.h, it is possible that
- fixup_segment converted a non-PC relative reloc into a PC
- relative reloc. In such a case, we need to convert the reloc
- code. */
code = fixp->fx_r_type;
- if (fixp->fx_pcrel)
- {
- switch (code)
- {
- case BFD_RELOC_8:
- code = BFD_RELOC_8_PCREL;
- break;
- case BFD_RELOC_16:
- code = BFD_RELOC_16_PCREL;
- break;
- case BFD_RELOC_32:
- code = BFD_RELOC_32_PCREL;
- break;
- case BFD_RELOC_64:
- code = BFD_RELOC_64_PCREL;
- break;
- case BFD_RELOC_8_PCREL:
- case BFD_RELOC_16_PCREL:
- case BFD_RELOC_32_PCREL:
- case BFD_RELOC_64_PCREL:
- case BFD_RELOC_16_PCREL_S2:
- case BFD_RELOC_PCREL_HI16_S:
- case BFD_RELOC_PCREL_LO16:
- break;
- default:
- as_bad_where (fixp->fx_file, fixp->fx_line,
- _("Cannot make %s relocation PC relative"),
- bfd_get_reloc_code_name (code));
- }
- }
- /* To support a PC relative reloc when generating embedded PIC code
- for ECOFF, we use a Cygnus extension. We check for that here to
- make sure that we don't let such a reloc escape normally. */
+ /* To support a PC relative reloc, we used a Cygnus extension.
+ We check for that here to make sure that we don't let such a
+ reloc escape normally. (FIXME: This was formerly used by
+ embedded-PIC support, but is now used by branch handling in
+ general. That probably should be fixed.) */
if ((OUTPUT_FLAVOR == bfd_target_ecoff_flavour
|| OUTPUT_FLAVOR == bfd_target_elf_flavour)
- && code == BFD_RELOC_16_PCREL_S2
- && mips_pic != EMBEDDED_PIC)
+ && code == BFD_RELOC_16_PCREL_S2)
reloc->howto = NULL;
else
reloc->howto = bfd_reloc_type_lookup (stdoutput, code);