+ /* MIPS64 extensions. */
+ { bfd_mach_mipsisa64r2, bfd_mach_mipsisa64 },
+ { bfd_mach_mips_sb1, bfd_mach_mipsisa64 },
+ { bfd_mach_mips_xlr, bfd_mach_mipsisa64 },
+
+ /* MIPS V extensions. */
+ { bfd_mach_mipsisa64, bfd_mach_mips5 },
+
+ /* R10000 extensions. */
+ { bfd_mach_mips12000, bfd_mach_mips10000 },
+ { bfd_mach_mips14000, bfd_mach_mips10000 },
+ { bfd_mach_mips16000, bfd_mach_mips10000 },
+
+ /* R5000 extensions. Note: the vr5500 ISA is an extension of the core
+ vr5400 ISA, but doesn't include the multimedia stuff. It seems
+ better to allow vr5400 and vr5500 code to be merged anyway, since
+ many libraries will just use the core ISA. Perhaps we could add
+ some sort of ASE flag if this ever proves a problem. */
+ { bfd_mach_mips5500, bfd_mach_mips5400 },
+ { bfd_mach_mips5400, bfd_mach_mips5000 },
+
+ /* MIPS IV extensions. */
+ { bfd_mach_mips5, bfd_mach_mips8000 },
+ { bfd_mach_mips10000, bfd_mach_mips8000 },
+ { bfd_mach_mips5000, bfd_mach_mips8000 },
+ { bfd_mach_mips7000, bfd_mach_mips8000 },
+ { bfd_mach_mips9000, bfd_mach_mips8000 },
+
+ /* VR4100 extensions. */
+ { bfd_mach_mips4120, bfd_mach_mips4100 },
+ { bfd_mach_mips4111, bfd_mach_mips4100 },
+
+ /* MIPS III extensions. */
+ { bfd_mach_mips_loongson_2e, bfd_mach_mips4000 },
+ { bfd_mach_mips_loongson_2f, bfd_mach_mips4000 },
+ { bfd_mach_mips8000, bfd_mach_mips4000 },
+ { bfd_mach_mips4650, bfd_mach_mips4000 },
+ { bfd_mach_mips4600, bfd_mach_mips4000 },
+ { bfd_mach_mips4400, bfd_mach_mips4000 },
+ { bfd_mach_mips4300, bfd_mach_mips4000 },
+ { bfd_mach_mips4100, bfd_mach_mips4000 },
+ { bfd_mach_mips5900, bfd_mach_mips4000 },
+
+ /* MIPS32r3 extensions. */
+ { bfd_mach_mips_interaptiv_mr2, bfd_mach_mipsisa32r3 },
+
+ /* MIPS32r2 extensions. */
+ { bfd_mach_mipsisa32r3, bfd_mach_mipsisa32r2 },
+
+ /* MIPS32 extensions. */
+ { bfd_mach_mipsisa32r2, bfd_mach_mipsisa32 },
+
+ /* MIPS II extensions. */
+ { bfd_mach_mips4000, bfd_mach_mips6000 },
+ { bfd_mach_mipsisa32, bfd_mach_mips6000 },
+ { bfd_mach_mips4010, bfd_mach_mips6000 },
+
+ /* MIPS I extensions. */
+ { bfd_mach_mips6000, bfd_mach_mips3000 },
+ { bfd_mach_mips3900, bfd_mach_mips3000 }
+};
+
+/* Return true if bfd machine EXTENSION is an extension of machine BASE. */
+
+static bfd_boolean
+mips_mach_extends_p (unsigned long base, unsigned long extension)
+{
+ size_t i;
+
+ if (extension == base)
+ return TRUE;
+
+ if (base == bfd_mach_mipsisa32
+ && mips_mach_extends_p (bfd_mach_mipsisa64, extension))
+ return TRUE;
+
+ if (base == bfd_mach_mipsisa32r2
+ && mips_mach_extends_p (bfd_mach_mipsisa64r2, extension))
+ return TRUE;
+
+ for (i = 0; i < ARRAY_SIZE (mips_mach_extensions); i++)
+ if (extension == mips_mach_extensions[i].extension)
+ {
+ extension = mips_mach_extensions[i].base;
+ if (extension == base)
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/* Return the BFD mach for each .MIPS.abiflags ISA Extension. */
+
+static unsigned long
+bfd_mips_isa_ext_mach (unsigned int isa_ext)
+{
+ switch (isa_ext)
+ {
+ case AFL_EXT_3900: return bfd_mach_mips3900;
+ case AFL_EXT_4010: return bfd_mach_mips4010;
+ case AFL_EXT_4100: return bfd_mach_mips4100;
+ case AFL_EXT_4111: return bfd_mach_mips4111;
+ case AFL_EXT_4120: return bfd_mach_mips4120;
+ case AFL_EXT_4650: return bfd_mach_mips4650;
+ case AFL_EXT_5400: return bfd_mach_mips5400;
+ case AFL_EXT_5500: return bfd_mach_mips5500;
+ case AFL_EXT_5900: return bfd_mach_mips5900;
+ case AFL_EXT_10000: return bfd_mach_mips10000;
+ case AFL_EXT_LOONGSON_2E: return bfd_mach_mips_loongson_2e;
+ case AFL_EXT_LOONGSON_2F: return bfd_mach_mips_loongson_2f;
+ case AFL_EXT_SB1: return bfd_mach_mips_sb1;
+ case AFL_EXT_OCTEON: return bfd_mach_mips_octeon;
+ case AFL_EXT_OCTEONP: return bfd_mach_mips_octeonp;
+ case AFL_EXT_OCTEON2: return bfd_mach_mips_octeon2;
+ case AFL_EXT_XLR: return bfd_mach_mips_xlr;
+ default: return bfd_mach_mips3000;
+ }
+}
+
+/* Return the .MIPS.abiflags value representing each ISA Extension. */
+
+unsigned int
+bfd_mips_isa_ext (bfd *abfd)
+{
+ switch (bfd_get_mach (abfd))
+ {
+ case bfd_mach_mips3900: return AFL_EXT_3900;
+ case bfd_mach_mips4010: return AFL_EXT_4010;
+ case bfd_mach_mips4100: return AFL_EXT_4100;
+ case bfd_mach_mips4111: return AFL_EXT_4111;
+ case bfd_mach_mips4120: return AFL_EXT_4120;
+ case bfd_mach_mips4650: return AFL_EXT_4650;
+ case bfd_mach_mips5400: return AFL_EXT_5400;
+ case bfd_mach_mips5500: return AFL_EXT_5500;
+ case bfd_mach_mips5900: return AFL_EXT_5900;
+ case bfd_mach_mips10000: return AFL_EXT_10000;
+ case bfd_mach_mips_loongson_2e: return AFL_EXT_LOONGSON_2E;
+ case bfd_mach_mips_loongson_2f: return AFL_EXT_LOONGSON_2F;
+ case bfd_mach_mips_sb1: return AFL_EXT_SB1;
+ case bfd_mach_mips_octeon: return AFL_EXT_OCTEON;
+ case bfd_mach_mips_octeonp: return AFL_EXT_OCTEONP;
+ case bfd_mach_mips_octeon3: return AFL_EXT_OCTEON3;
+ case bfd_mach_mips_octeon2: return AFL_EXT_OCTEON2;
+ case bfd_mach_mips_xlr: return AFL_EXT_XLR;
+ case bfd_mach_mips_interaptiv_mr2:
+ return AFL_EXT_INTERAPTIV_MR2;
+ default: return 0;
+ }
+}
+
+/* Encode ISA level and revision as a single value. */
+#define LEVEL_REV(LEV,REV) ((LEV) << 3 | (REV))
+
+/* Decode a single value into level and revision. */
+#define ISA_LEVEL(LEVREV) ((LEVREV) >> 3)
+#define ISA_REV(LEVREV) ((LEVREV) & 0x7)
+
+/* Update the isa_level, isa_rev, isa_ext fields of abiflags. */
+
+static void
+update_mips_abiflags_isa (bfd *abfd, Elf_Internal_ABIFlags_v0 *abiflags)
+{
+ int new_isa = 0;
+ switch (elf_elfheader (abfd)->e_flags & EF_MIPS_ARCH)
+ {
+ case E_MIPS_ARCH_1: new_isa = LEVEL_REV (1, 0); break;
+ case E_MIPS_ARCH_2: new_isa = LEVEL_REV (2, 0); break;
+ case E_MIPS_ARCH_3: new_isa = LEVEL_REV (3, 0); break;
+ case E_MIPS_ARCH_4: new_isa = LEVEL_REV (4, 0); break;
+ case E_MIPS_ARCH_5: new_isa = LEVEL_REV (5, 0); break;
+ case E_MIPS_ARCH_32: new_isa = LEVEL_REV (32, 1); break;
+ case E_MIPS_ARCH_32R2: new_isa = LEVEL_REV (32, 2); break;
+ case E_MIPS_ARCH_32R6: new_isa = LEVEL_REV (32, 6); break;
+ case E_MIPS_ARCH_64: new_isa = LEVEL_REV (64, 1); break;
+ case E_MIPS_ARCH_64R2: new_isa = LEVEL_REV (64, 2); break;
+ case E_MIPS_ARCH_64R6: new_isa = LEVEL_REV (64, 6); break;
+ default:
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%pB: unknown architecture %s"),
+ abfd, bfd_printable_name (abfd));
+ }
+
+ if (new_isa > LEVEL_REV (abiflags->isa_level, abiflags->isa_rev))
+ {
+ abiflags->isa_level = ISA_LEVEL (new_isa);
+ abiflags->isa_rev = ISA_REV (new_isa);
+ }
+
+ /* Update the isa_ext if ABFD describes a further extension. */
+ if (mips_mach_extends_p (bfd_mips_isa_ext_mach (abiflags->isa_ext),
+ bfd_get_mach (abfd)))
+ abiflags->isa_ext = bfd_mips_isa_ext (abfd);
+}
+
+/* Return true if the given ELF header flags describe a 32-bit binary. */
+
+static bfd_boolean
+mips_32bit_flags_p (flagword flags)
+{
+ return ((flags & EF_MIPS_32BITMODE) != 0
+ || (flags & EF_MIPS_ABI) == E_MIPS_ABI_O32
+ || (flags & EF_MIPS_ABI) == E_MIPS_ABI_EABI32
+ || (flags & EF_MIPS_ARCH) == E_MIPS_ARCH_1
+ || (flags & EF_MIPS_ARCH) == E_MIPS_ARCH_2
+ || (flags & EF_MIPS_ARCH) == E_MIPS_ARCH_32
+ || (flags & EF_MIPS_ARCH) == E_MIPS_ARCH_32R2
+ || (flags & EF_MIPS_ARCH) == E_MIPS_ARCH_32R6);
+}
+
+/* Infer the content of the ABI flags based on the elf header. */
+
+static void
+infer_mips_abiflags (bfd *abfd, Elf_Internal_ABIFlags_v0* abiflags)
+{
+ obj_attribute *in_attr;
+
+ memset (abiflags, 0, sizeof (Elf_Internal_ABIFlags_v0));
+ update_mips_abiflags_isa (abfd, abiflags);
+
+ if (mips_32bit_flags_p (elf_elfheader (abfd)->e_flags))
+ abiflags->gpr_size = AFL_REG_32;
+ else
+ abiflags->gpr_size = AFL_REG_64;
+
+ abiflags->cpr1_size = AFL_REG_NONE;
+
+ in_attr = elf_known_obj_attributes (abfd)[OBJ_ATTR_GNU];
+ abiflags->fp_abi = in_attr[Tag_GNU_MIPS_ABI_FP].i;
+
+ if (abiflags->fp_abi == Val_GNU_MIPS_ABI_FP_SINGLE
+ || abiflags->fp_abi == Val_GNU_MIPS_ABI_FP_XX
+ || (abiflags->fp_abi == Val_GNU_MIPS_ABI_FP_DOUBLE
+ && abiflags->gpr_size == AFL_REG_32))
+ abiflags->cpr1_size = AFL_REG_32;
+ else if (abiflags->fp_abi == Val_GNU_MIPS_ABI_FP_DOUBLE
+ || abiflags->fp_abi == Val_GNU_MIPS_ABI_FP_64
+ || abiflags->fp_abi == Val_GNU_MIPS_ABI_FP_64A)
+ abiflags->cpr1_size = AFL_REG_64;
+
+ abiflags->cpr2_size = AFL_REG_NONE;
+
+ if (elf_elfheader (abfd)->e_flags & EF_MIPS_ARCH_ASE_MDMX)
+ abiflags->ases |= AFL_ASE_MDMX;
+ if (elf_elfheader (abfd)->e_flags & EF_MIPS_ARCH_ASE_M16)
+ abiflags->ases |= AFL_ASE_MIPS16;
+ if (elf_elfheader (abfd)->e_flags & EF_MIPS_ARCH_ASE_MICROMIPS)
+ abiflags->ases |= AFL_ASE_MICROMIPS;
+
+ if (abiflags->fp_abi != Val_GNU_MIPS_ABI_FP_ANY
+ && abiflags->fp_abi != Val_GNU_MIPS_ABI_FP_SOFT
+ && abiflags->fp_abi != Val_GNU_MIPS_ABI_FP_64A
+ && abiflags->isa_level >= 32
+ && abiflags->ases != AFL_ASE_LOONGSON_EXT)
+ abiflags->flags1 |= AFL_FLAGS1_ODDSPREG;
+}
+
+/* We need to use a special link routine to handle the .reginfo and
+ the .mdebug sections. We need to merge all instances of these
+ sections together, not write them all out sequentially. */
+
+bfd_boolean
+_bfd_mips_elf_final_link (bfd *abfd, struct bfd_link_info *info)
+{
+ asection *o;
+ struct bfd_link_order *p;
+ asection *reginfo_sec, *mdebug_sec, *gptab_data_sec, *gptab_bss_sec;
+ asection *rtproc_sec, *abiflags_sec;
+ Elf32_RegInfo reginfo;
+ struct ecoff_debug_info debug;
+ struct mips_htab_traverse_info hti;
+ const struct elf_backend_data *bed = get_elf_backend_data (abfd);
+ const struct ecoff_debug_swap *swap = bed->elf_backend_ecoff_debug_swap;
+ HDRR *symhdr = &debug.symbolic_header;
+ void *mdebug_handle = NULL;
+ asection *s;
+ EXTR esym;
+ unsigned int i;
+ bfd_size_type amt;
+ struct mips_elf_link_hash_table *htab;
+
+ static const char * const secname[] =
+ {
+ ".text", ".init", ".fini", ".data",
+ ".rodata", ".sdata", ".sbss", ".bss"
+ };
+ static const int sc[] =
+ {
+ scText, scInit, scFini, scData,
+ scRData, scSData, scSBss, scBss
+ };
+
+ htab = mips_elf_hash_table (info);
+ BFD_ASSERT (htab != NULL);
+
+ /* Sort the dynamic symbols so that those with GOT entries come after
+ those without. */
+ if (!mips_elf_sort_hash_table (abfd, info))
+ return FALSE;
+
+ /* Create any scheduled LA25 stubs. */
+ hti.info = info;
+ hti.output_bfd = abfd;
+ hti.error = FALSE;
+ htab_traverse (htab->la25_stubs, mips_elf_create_la25_stub, &hti);
+ if (hti.error)
+ return FALSE;
+
+ /* Get a value for the GP register. */
+ if (elf_gp (abfd) == 0)
+ {
+ struct bfd_link_hash_entry *h;
+
+ h = bfd_link_hash_lookup (info->hash, "_gp", FALSE, FALSE, TRUE);
+ if (h != NULL && h->type == bfd_link_hash_defined)
+ elf_gp (abfd) = (h->u.def.value
+ + h->u.def.section->output_section->vma
+ + h->u.def.section->output_offset);
+ else if (htab->is_vxworks
+ && (h = bfd_link_hash_lookup (info->hash,
+ "_GLOBAL_OFFSET_TABLE_",
+ FALSE, FALSE, TRUE))
+ && h->type == bfd_link_hash_defined)
+ elf_gp (abfd) = (h->u.def.section->output_section->vma
+ + h->u.def.section->output_offset
+ + h->u.def.value);
+ else if (bfd_link_relocatable (info))
+ {
+ bfd_vma lo = MINUS_ONE;
+
+ /* Find the GP-relative section with the lowest offset. */
+ for (o = abfd->sections; o != NULL; o = o->next)
+ if (o->vma < lo
+ && (elf_section_data (o)->this_hdr.sh_flags & SHF_MIPS_GPREL))
+ lo = o->vma;
+
+ /* And calculate GP relative to that. */
+ elf_gp (abfd) = lo + ELF_MIPS_GP_OFFSET (info);
+ }
+ else
+ {
+ /* If the relocate_section function needs to do a reloc
+ involving the GP value, it should make a reloc_dangerous
+ callback to warn that GP is not defined. */
+ }
+ }