+ BFD_ASSERT (addr % 2 == 0);
+ BFD_ASSERT (count % 2 == 0);
+
+ /* Adjust the local symbols defined in this section. */
+ symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
+ isym = (Elf_Internal_Sym *) symtab_hdr->contents;
+ for (isymend = isym + symtab_hdr->sh_info; isym < isymend; isym++)
+ if (isym->st_shndx == sec_shndx && isym->st_value > addr)
+ isym->st_value -= count;
+
+ /* Now adjust the global symbols defined in this section. */
+ symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)
+ - symtab_hdr->sh_info);
+ sym_hashes = start_hashes = elf_sym_hashes (abfd);
+ end_hashes = sym_hashes + symcount;
+
+ for (; sym_hashes < end_hashes; sym_hashes++)
+ {
+ struct elf_link_hash_entry *sym_hash = *sym_hashes;
+
+ if ((sym_hash->root.type == bfd_link_hash_defined
+ || sym_hash->root.type == bfd_link_hash_defweak)
+ && sym_hash->root.u.def.section == sec)
+ {
+ bfd_vma value = sym_hash->root.u.def.value;
+
+ if (ELF_ST_IS_MICROMIPS (sym_hash->other))
+ value &= MINUS_TWO;
+ if (value > addr)
+ sym_hash->root.u.def.value -= count;
+ }
+ }
+
+ return TRUE;
+}
+
+
+/* Opcodes needed for microMIPS relaxation as found in
+ opcodes/micromips-opc.c. */
+
+struct opcode_descriptor {
+ unsigned long match;
+ unsigned long mask;
+};
+
+/* The $ra register aka $31. */
+
+#define RA 31
+
+/* 32-bit instruction format register fields. */
+
+#define OP32_SREG(opcode) (((opcode) >> 16) & 0x1f)
+#define OP32_TREG(opcode) (((opcode) >> 21) & 0x1f)
+
+/* Check if a 5-bit register index can be abbreviated to 3 bits. */
+
+#define OP16_VALID_REG(r) \
+ ((2 <= (r) && (r) <= 7) || (16 <= (r) && (r) <= 17))
+
+
+/* 32-bit and 16-bit branches. */
+
+static const struct opcode_descriptor b_insns_32[] = {
+ { /* "b", "p", */ 0x40400000, 0xffff0000 }, /* bgez 0 */
+ { /* "b", "p", */ 0x94000000, 0xffff0000 }, /* beq 0, 0 */
+ { 0, 0 } /* End marker for find_match(). */
+};
+
+static const struct opcode_descriptor bc_insn_32 =
+ { /* "bc(1|2)(ft)", "N,p", */ 0x42800000, 0xfec30000 };
+
+static const struct opcode_descriptor bz_insn_32 =
+ { /* "b(g|l)(e|t)z", "s,p", */ 0x40000000, 0xff200000 };
+
+static const struct opcode_descriptor bzal_insn_32 =
+ { /* "b(ge|lt)zal", "s,p", */ 0x40200000, 0xffa00000 };
+
+static const struct opcode_descriptor beq_insn_32 =
+ { /* "b(eq|ne)", "s,t,p", */ 0x94000000, 0xdc000000 };
+
+static const struct opcode_descriptor b_insn_16 =
+ { /* "b", "mD", */ 0xcc00, 0xfc00 };
+
+static const struct opcode_descriptor bz_insn_16 =
+ { /* "b(eq|ne)z", "md,mE", */ 0x8c00, 0xdc00 };
+
+
+/* 32-bit and 16-bit branch EQ and NE zero. */
+
+/* NOTE: All opcode tables have BEQ/BNE in the same order: first the
+ eq and second the ne. This convention is used when replacing a
+ 32-bit BEQ/BNE with the 16-bit version. */
+
+#define BZC32_REG_FIELD(r) (((r) & 0x1f) << 16)
+
+static const struct opcode_descriptor bz_rs_insns_32[] = {
+ { /* "beqz", "s,p", */ 0x94000000, 0xffe00000 },
+ { /* "bnez", "s,p", */ 0xb4000000, 0xffe00000 },
+ { 0, 0 } /* End marker for find_match(). */
+};
+
+static const struct opcode_descriptor bz_rt_insns_32[] = {
+ { /* "beqz", "t,p", */ 0x94000000, 0xfc01f000 },
+ { /* "bnez", "t,p", */ 0xb4000000, 0xfc01f000 },
+ { 0, 0 } /* End marker for find_match(). */
+};
+
+static const struct opcode_descriptor bzc_insns_32[] = {
+ { /* "beqzc", "s,p", */ 0x40e00000, 0xffe00000 },
+ { /* "bnezc", "s,p", */ 0x40a00000, 0xffe00000 },
+ { 0, 0 } /* End marker for find_match(). */
+};
+
+static const struct opcode_descriptor bz_insns_16[] = {
+ { /* "beqz", "md,mE", */ 0x8c00, 0xfc00 },
+ { /* "bnez", "md,mE", */ 0xac00, 0xfc00 },
+ { 0, 0 } /* End marker for find_match(). */
+};
+
+/* Switch between a 5-bit register index and its 3-bit shorthand. */
+
+#define BZ16_REG(opcode) ((((((opcode) >> 7) & 7) + 0x1e) & 0x17) + 2)
+#define BZ16_REG_FIELD(r) \
+ (((2 <= (r) && (r) <= 7) ? (r) : ((r) - 16)) << 7)
+
+
+/* 32-bit instructions with a delay slot. */
+
+static const struct opcode_descriptor jal_insn_32_bd16 =
+ { /* "jals", "a", */ 0x74000000, 0xfc000000 };
+
+static const struct opcode_descriptor jal_insn_32_bd32 =
+ { /* "jal", "a", */ 0xf4000000, 0xfc000000 };
+
+static const struct opcode_descriptor jal_x_insn_32_bd32 =
+ { /* "jal[x]", "a", */ 0xf0000000, 0xf8000000 };
+
+static const struct opcode_descriptor j_insn_32 =
+ { /* "j", "a", */ 0xd4000000, 0xfc000000 };
+
+static const struct opcode_descriptor jalr_insn_32 =
+ { /* "jalr[.hb]", "t,s", */ 0x00000f3c, 0xfc00efff };
+
+/* This table can be compacted, because no opcode replacement is made. */
+
+static const struct opcode_descriptor ds_insns_32_bd16[] = {
+ { /* "jals", "a", */ 0x74000000, 0xfc000000 },
+
+ { /* "jalrs[.hb]", "t,s", */ 0x00004f3c, 0xfc00efff },
+ { /* "b(ge|lt)zals", "s,p", */ 0x42200000, 0xffa00000 },
+
+ { /* "b(g|l)(e|t)z", "s,p", */ 0x40000000, 0xff200000 },
+ { /* "b(eq|ne)", "s,t,p", */ 0x94000000, 0xdc000000 },
+ { /* "j", "a", */ 0xd4000000, 0xfc000000 },
+ { 0, 0 } /* End marker for find_match(). */
+};
+
+/* This table can be compacted, because no opcode replacement is made. */
+
+static const struct opcode_descriptor ds_insns_32_bd32[] = {
+ { /* "jal[x]", "a", */ 0xf0000000, 0xf8000000 },
+
+ { /* "jalr[.hb]", "t,s", */ 0x00000f3c, 0xfc00efff },
+ { /* "b(ge|lt)zal", "s,p", */ 0x40200000, 0xffa00000 },
+ { 0, 0 } /* End marker for find_match(). */
+};
+
+
+/* 16-bit instructions with a delay slot. */
+
+static const struct opcode_descriptor jalr_insn_16_bd16 =
+ { /* "jalrs", "my,mj", */ 0x45e0, 0xffe0 };
+
+static const struct opcode_descriptor jalr_insn_16_bd32 =
+ { /* "jalr", "my,mj", */ 0x45c0, 0xffe0 };
+
+static const struct opcode_descriptor jr_insn_16 =
+ { /* "jr", "mj", */ 0x4580, 0xffe0 };
+
+#define JR16_REG(opcode) ((opcode) & 0x1f)
+
+/* This table can be compacted, because no opcode replacement is made. */
+
+static const struct opcode_descriptor ds_insns_16_bd16[] = {
+ { /* "jalrs", "my,mj", */ 0x45e0, 0xffe0 },
+
+ { /* "b", "mD", */ 0xcc00, 0xfc00 },
+ { /* "b(eq|ne)z", "md,mE", */ 0x8c00, 0xdc00 },
+ { /* "jr", "mj", */ 0x4580, 0xffe0 },
+ { 0, 0 } /* End marker for find_match(). */
+};
+
+
+/* LUI instruction. */
+
+static const struct opcode_descriptor lui_insn =
+ { /* "lui", "s,u", */ 0x41a00000, 0xffe00000 };
+
+
+/* ADDIU instruction. */
+
+static const struct opcode_descriptor addiu_insn =
+ { /* "addiu", "t,r,j", */ 0x30000000, 0xfc000000 };
+
+static const struct opcode_descriptor addiupc_insn =
+ { /* "addiu", "mb,$pc,mQ", */ 0x78000000, 0xfc000000 };
+
+#define ADDIUPC_REG_FIELD(r) \
+ (((2 <= (r) && (r) <= 7) ? (r) : ((r) - 16)) << 23)
+
+
+/* Relaxable instructions in a JAL delay slot: MOVE. */
+
+/* The 16-bit move has rd in 9:5 and rs in 4:0. The 32-bit moves
+ (ADDU, OR) have rd in 15:11 and rs in 10:16. */
+#define MOVE32_RD(opcode) (((opcode) >> 11) & 0x1f)
+#define MOVE32_RS(opcode) (((opcode) >> 16) & 0x1f)
+
+#define MOVE16_RD_FIELD(r) (((r) & 0x1f) << 5)
+#define MOVE16_RS_FIELD(r) (((r) & 0x1f) )
+
+static const struct opcode_descriptor move_insns_32[] = {
+ { /* "move", "d,s", */ 0x00000150, 0xffe007ff }, /* addu d,s,$0 */
+ { /* "move", "d,s", */ 0x00000290, 0xffe007ff }, /* or d,s,$0 */
+ { 0, 0 } /* End marker for find_match(). */
+};
+
+static const struct opcode_descriptor move_insn_16 =
+ { /* "move", "mp,mj", */ 0x0c00, 0xfc00 };
+
+
+/* NOP instructions. */
+
+static const struct opcode_descriptor nop_insn_32 =
+ { /* "nop", "", */ 0x00000000, 0xffffffff };
+
+static const struct opcode_descriptor nop_insn_16 =
+ { /* "nop", "", */ 0x0c00, 0xffff };
+
+
+/* Instruction match support. */
+
+#define MATCH(opcode, insn) ((opcode & insn.mask) == insn.match)
+
+static int
+find_match (unsigned long opcode, const struct opcode_descriptor insn[])
+{
+ unsigned long indx;
+
+ for (indx = 0; insn[indx].mask != 0; indx++)
+ if (MATCH (opcode, insn[indx]))
+ return indx;
+
+ return -1;
+}
+
+
+/* Branch and delay slot decoding support. */
+
+/* If PTR points to what *might* be a 16-bit branch or jump, then
+ return the minimum length of its delay slot, otherwise return 0.
+ Non-zero results are not definitive as we might be checking against
+ the second half of another instruction. */
+
+static int
+check_br16_dslot (bfd *abfd, bfd_byte *ptr)
+{
+ unsigned long opcode;
+ int bdsize;
+
+ opcode = bfd_get_16 (abfd, ptr);
+ if (MATCH (opcode, jalr_insn_16_bd32) != 0)
+ /* 16-bit branch/jump with a 32-bit delay slot. */
+ bdsize = 4;
+ else if (MATCH (opcode, jalr_insn_16_bd16) != 0
+ || find_match (opcode, ds_insns_16_bd16) >= 0)
+ /* 16-bit branch/jump with a 16-bit delay slot. */
+ bdsize = 2;
+ else
+ /* No delay slot. */
+ bdsize = 0;
+
+ return bdsize;
+}
+
+/* If PTR points to what *might* be a 32-bit branch or jump, then
+ return the minimum length of its delay slot, otherwise return 0.
+ Non-zero results are not definitive as we might be checking against
+ the second half of another instruction. */
+
+static int
+check_br32_dslot (bfd *abfd, bfd_byte *ptr)
+{
+ unsigned long opcode;
+ int bdsize;
+
+ opcode = bfd_get_micromips_32 (abfd, ptr);
+ if (find_match (opcode, ds_insns_32_bd32) >= 0)
+ /* 32-bit branch/jump with a 32-bit delay slot. */
+ bdsize = 4;
+ else if (find_match (opcode, ds_insns_32_bd16) >= 0)
+ /* 32-bit branch/jump with a 16-bit delay slot. */
+ bdsize = 2;
+ else
+ /* No delay slot. */
+ bdsize = 0;
+
+ return bdsize;
+}
+
+/* If PTR points to a 16-bit branch or jump with a 32-bit delay slot
+ that doesn't fiddle with REG, then return TRUE, otherwise FALSE. */
+
+static bfd_boolean
+check_br16 (bfd *abfd, bfd_byte *ptr, unsigned long reg)
+{
+ unsigned long opcode;
+
+ opcode = bfd_get_16 (abfd, ptr);
+ if (MATCH (opcode, b_insn_16)
+ /* B16 */
+ || (MATCH (opcode, jr_insn_16) && reg != JR16_REG (opcode))
+ /* JR16 */
+ || (MATCH (opcode, bz_insn_16) && reg != BZ16_REG (opcode))
+ /* BEQZ16, BNEZ16 */
+ || (MATCH (opcode, jalr_insn_16_bd32)
+ /* JALR16 */
+ && reg != JR16_REG (opcode) && reg != RA))
+ return TRUE;
+
+ return FALSE;
+}
+
+/* If PTR points to a 32-bit branch or jump that doesn't fiddle with REG,
+ then return TRUE, otherwise FALSE. */
+
+static bfd_boolean
+check_br32 (bfd *abfd, bfd_byte *ptr, unsigned long reg)
+{
+ unsigned long opcode;
+
+ opcode = bfd_get_micromips_32 (abfd, ptr);
+ if (MATCH (opcode, j_insn_32)
+ /* J */
+ || MATCH (opcode, bc_insn_32)
+ /* BC1F, BC1T, BC2F, BC2T */
+ || (MATCH (opcode, jal_x_insn_32_bd32) && reg != RA)
+ /* JAL, JALX */
+ || (MATCH (opcode, bz_insn_32) && reg != OP32_SREG (opcode))
+ /* BGEZ, BGTZ, BLEZ, BLTZ */
+ || (MATCH (opcode, bzal_insn_32)
+ /* BGEZAL, BLTZAL */
+ && reg != OP32_SREG (opcode) && reg != RA)
+ || ((MATCH (opcode, jalr_insn_32) || MATCH (opcode, beq_insn_32))
+ /* JALR, JALR.HB, BEQ, BNE */
+ && reg != OP32_SREG (opcode) && reg != OP32_TREG (opcode)))
+ return TRUE;
+
+ return FALSE;
+}
+
+/* If the instruction encoding at PTR and relocations [INTERNAL_RELOCS,
+ IRELEND) at OFFSET indicate that there must be a compact branch there,
+ then return TRUE, otherwise FALSE. */
+
+static bfd_boolean
+check_relocated_bzc (bfd *abfd, const bfd_byte *ptr, bfd_vma offset,
+ const Elf_Internal_Rela *internal_relocs,
+ const Elf_Internal_Rela *irelend)
+{
+ const Elf_Internal_Rela *irel;
+ unsigned long opcode;
+
+ opcode = bfd_get_micromips_32 (abfd, ptr);
+ if (find_match (opcode, bzc_insns_32) < 0)
+ return FALSE;
+
+ for (irel = internal_relocs; irel < irelend; irel++)
+ if (irel->r_offset == offset
+ && ELF32_R_TYPE (irel->r_info) == R_MICROMIPS_PC16_S1)
+ return TRUE;
+
+ return FALSE;
+}
+
+/* Bitsize checking. */
+#define IS_BITSIZE(val, N) \
+ (((((val) & ((1ULL << (N)) - 1)) ^ (1ULL << ((N) - 1))) \
+ - (1ULL << ((N) - 1))) == (val))
+
+\f
+bfd_boolean
+_bfd_mips_elf_relax_section (bfd *abfd, asection *sec,
+ struct bfd_link_info *link_info,
+ bfd_boolean *again)
+{
+ Elf_Internal_Shdr *symtab_hdr;
+ Elf_Internal_Rela *internal_relocs;
+ Elf_Internal_Rela *irel, *irelend;
+ bfd_byte *contents = NULL;
+ Elf_Internal_Sym *isymbuf = NULL;
+
+ /* Assume nothing changes. */
+ *again = FALSE;
+
+ /* We don't have to do anything for a relocatable link, if
+ this section does not have relocs, or if this is not a
+ code section. */
+
+ if (link_info->relocatable
+ || (sec->flags & SEC_RELOC) == 0
+ || sec->reloc_count == 0
+ || (sec->flags & SEC_CODE) == 0)
+ return TRUE;
+
+ symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
+
+ /* Get a copy of the native relocations. */
+ internal_relocs = (_bfd_elf_link_read_relocs
+ (abfd, sec, NULL, (Elf_Internal_Rela *) NULL,
+ link_info->keep_memory));
+ if (internal_relocs == NULL)
+ goto error_return;
+
+ /* Walk through them looking for relaxing opportunities. */
+ irelend = internal_relocs + sec->reloc_count;
+ for (irel = internal_relocs; irel < irelend; irel++)
+ {
+ unsigned long r_symndx = ELF32_R_SYM (irel->r_info);
+ unsigned int r_type = ELF32_R_TYPE (irel->r_info);
+ bfd_boolean target_is_micromips_code_p;
+ unsigned long opcode;
+ bfd_vma symval;
+ bfd_vma pcrval;
+ bfd_byte *ptr;
+ int fndopc;
+
+ /* The number of bytes to delete for relaxation and from where
+ to delete these bytes starting at irel->r_offset. */
+ int delcnt = 0;
+ int deloff = 0;
+
+ /* If this isn't something that can be relaxed, then ignore
+ this reloc. */
+ if (r_type != R_MICROMIPS_HI16
+ && r_type != R_MICROMIPS_PC16_S1
+ && r_type != R_MICROMIPS_26_S1)
+ continue;
+
+ /* Get the section contents if we haven't done so already. */
+ if (contents == NULL)
+ {
+ /* Get cached copy if it exists. */
+ if (elf_section_data (sec)->this_hdr.contents != NULL)
+ contents = elf_section_data (sec)->this_hdr.contents;
+ /* Go get them off disk. */
+ else if (!bfd_malloc_and_get_section (abfd, sec, &contents))
+ goto error_return;
+ }
+ ptr = contents + irel->r_offset;
+
+ /* Read this BFD's local symbols if we haven't done so already. */
+ if (isymbuf == NULL && symtab_hdr->sh_info != 0)
+ {
+ isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
+ if (isymbuf == NULL)
+ isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
+ symtab_hdr->sh_info, 0,
+ NULL, NULL, NULL);
+ if (isymbuf == NULL)
+ goto error_return;
+ }
+
+ /* Get the value of the symbol referred to by the reloc. */
+ if (r_symndx < symtab_hdr->sh_info)
+ {
+ /* A local symbol. */
+ Elf_Internal_Sym *isym;
+ asection *sym_sec;
+
+ isym = isymbuf + r_symndx;
+ if (isym->st_shndx == SHN_UNDEF)
+ sym_sec = bfd_und_section_ptr;
+ else if (isym->st_shndx == SHN_ABS)
+ sym_sec = bfd_abs_section_ptr;
+ else if (isym->st_shndx == SHN_COMMON)
+ sym_sec = bfd_com_section_ptr;
+ else
+ sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
+ symval = (isym->st_value
+ + sym_sec->output_section->vma
+ + sym_sec->output_offset);
+ target_is_micromips_code_p = ELF_ST_IS_MICROMIPS (isym->st_other);
+ }
+ else
+ {
+ unsigned long indx;
+ struct elf_link_hash_entry *h;
+
+ /* An external symbol. */
+ indx = r_symndx - symtab_hdr->sh_info;
+ h = elf_sym_hashes (abfd)[indx];
+ BFD_ASSERT (h != NULL);
+
+ if (h->root.type != bfd_link_hash_defined
+ && h->root.type != bfd_link_hash_defweak)
+ /* This appears to be a reference to an undefined
+ symbol. Just ignore it -- it will be caught by the
+ regular reloc processing. */
+ continue;
+
+ symval = (h->root.u.def.value
+ + h->root.u.def.section->output_section->vma
+ + h->root.u.def.section->output_offset);
+ target_is_micromips_code_p = (!h->needs_plt
+ && ELF_ST_IS_MICROMIPS (h->other));
+ }
+
+
+ /* For simplicity of coding, we are going to modify the
+ section contents, the section relocs, and the BFD symbol
+ table. We must tell the rest of the code not to free up this
+ information. It would be possible to instead create a table
+ of changes which have to be made, as is done in coff-mips.c;
+ that would be more work, but would require less memory when
+ the linker is run. */
+
+ /* Only 32-bit instructions relaxed. */
+ if (irel->r_offset + 4 > sec->size)
+ continue;
+
+ opcode = bfd_get_micromips_32 (abfd, ptr);
+
+ /* This is the pc-relative distance from the instruction the
+ relocation is applied to, to the symbol referred. */
+ pcrval = (symval
+ - (sec->output_section->vma + sec->output_offset)
+ - irel->r_offset);
+
+ /* R_MICROMIPS_HI16 / LUI relaxation to nil, performing relaxation
+ of corresponding R_MICROMIPS_LO16 to R_MICROMIPS_HI0_LO16 or
+ R_MICROMIPS_PC23_S2. The R_MICROMIPS_PC23_S2 condition is
+
+ (symval % 4 == 0 && IS_BITSIZE (pcrval, 25))
+
+ where pcrval has first to be adjusted to apply against the LO16
+ location (we make the adjustment later on, when we have figured
+ out the offset). */
+ if (r_type == R_MICROMIPS_HI16 && MATCH (opcode, lui_insn))
+ {
+ bfd_boolean bzc = FALSE;
+ unsigned long nextopc;
+ unsigned long reg;
+ bfd_vma offset;
+
+ /* Give up if the previous reloc was a HI16 against this symbol
+ too. */
+ if (irel > internal_relocs
+ && ELF32_R_TYPE (irel[-1].r_info) == R_MICROMIPS_HI16
+ && ELF32_R_SYM (irel[-1].r_info) == r_symndx)
+ continue;
+
+ /* Or if the next reloc is not a LO16 against this symbol. */
+ if (irel + 1 >= irelend
+ || ELF32_R_TYPE (irel[1].r_info) != R_MICROMIPS_LO16
+ || ELF32_R_SYM (irel[1].r_info) != r_symndx)
+ continue;
+
+ /* Or if the second next reloc is a LO16 against this symbol too. */
+ if (irel + 2 >= irelend
+ && ELF32_R_TYPE (irel[2].r_info) == R_MICROMIPS_LO16
+ && ELF32_R_SYM (irel[2].r_info) == r_symndx)
+ continue;
+
+ /* See if the LUI instruction *might* be in a branch delay slot.
+ We check whether what looks like a 16-bit branch or jump is
+ actually an immediate argument to a compact branch, and let
+ it through if so. */
+ if (irel->r_offset >= 2
+ && check_br16_dslot (abfd, ptr - 2)
+ && !(irel->r_offset >= 4
+ && (bzc = check_relocated_bzc (abfd,
+ ptr - 4, irel->r_offset - 4,
+ internal_relocs, irelend))))
+ continue;
+ if (irel->r_offset >= 4
+ && !bzc
+ && check_br32_dslot (abfd, ptr - 4))
+ continue;
+
+ reg = OP32_SREG (opcode);
+
+ /* We only relax adjacent instructions or ones separated with
+ a branch or jump that has a delay slot. The branch or jump
+ must not fiddle with the register used to hold the address.
+ Subtract 4 for the LUI itself. */
+ offset = irel[1].r_offset - irel[0].r_offset;
+ switch (offset - 4)
+ {
+ case 0:
+ break;
+ case 2:
+ if (check_br16 (abfd, ptr + 4, reg))
+ break;
+ continue;
+ case 4:
+ if (check_br32 (abfd, ptr + 4, reg))
+ break;
+ continue;
+ default:
+ continue;
+ }
+
+ nextopc = bfd_get_micromips_32 (abfd, contents + irel[1].r_offset);
+
+ /* Give up unless the same register is used with both
+ relocations. */
+ if (OP32_SREG (nextopc) != reg)
+ continue;
+
+ /* Now adjust pcrval, subtracting the offset to the LO16 reloc
+ and rounding up to take masking of the two LSBs into account. */
+ pcrval = ((pcrval - offset + 3) | 3) ^ 3;
+
+ /* R_MICROMIPS_LO16 relaxation to R_MICROMIPS_HI0_LO16. */
+ if (IS_BITSIZE (symval, 16))
+ {
+ /* Fix the relocation's type. */
+ irel[1].r_info = ELF32_R_INFO (r_symndx, R_MICROMIPS_HI0_LO16);
+
+ /* Instructions using R_MICROMIPS_LO16 have the base or
+ source register in bits 20:16. This register becomes $0
+ (zero) as the result of the R_MICROMIPS_HI16 being 0. */
+ nextopc &= ~0x001f0000;
+ bfd_put_16 (abfd, (nextopc >> 16) & 0xffff,
+ contents + irel[1].r_offset);
+ }
+
+ /* R_MICROMIPS_LO16 / ADDIU relaxation to R_MICROMIPS_PC23_S2.
+ We add 4 to take LUI deletion into account while checking
+ the PC-relative distance. */
+ else if (symval % 4 == 0
+ && IS_BITSIZE (pcrval + 4, 25)
+ && MATCH (nextopc, addiu_insn)
+ && OP32_TREG (nextopc) == OP32_SREG (nextopc)
+ && OP16_VALID_REG (OP32_TREG (nextopc)))
+ {
+ /* Fix the relocation's type. */
+ irel[1].r_info = ELF32_R_INFO (r_symndx, R_MICROMIPS_PC23_S2);
+
+ /* Replace ADDIU with the ADDIUPC version. */
+ nextopc = (addiupc_insn.match
+ | ADDIUPC_REG_FIELD (OP32_TREG (nextopc)));
+
+ bfd_put_micromips_32 (abfd, nextopc,
+ contents + irel[1].r_offset);
+ }
+
+ /* Can't do anything, give up, sigh... */
+ else
+ continue;
+
+ /* Fix the relocation's type. */
+ irel->r_info = ELF32_R_INFO (r_symndx, R_MIPS_NONE);
+
+ /* Delete the LUI instruction: 4 bytes at irel->r_offset. */
+ delcnt = 4;
+ deloff = 0;
+ }
+
+ /* Compact branch relaxation -- due to the multitude of macros
+ employed by the compiler/assembler, compact branches are not
+ always generated. Obviously, this can/will be fixed elsewhere,
+ but there is no drawback in double checking it here. */
+ else if (r_type == R_MICROMIPS_PC16_S1
+ && irel->r_offset + 5 < sec->size
+ && ((fndopc = find_match (opcode, bz_rs_insns_32)) >= 0
+ || (fndopc = find_match (opcode, bz_rt_insns_32)) >= 0)
+ && MATCH (bfd_get_16 (abfd, ptr + 4), nop_insn_16))
+ {
+ unsigned long reg;
+
+ reg = OP32_SREG (opcode) ? OP32_SREG (opcode) : OP32_TREG (opcode);
+
+ /* Replace BEQZ/BNEZ with the compact version. */
+ opcode = (bzc_insns_32[fndopc].match
+ | BZC32_REG_FIELD (reg)
+ | (opcode & 0xffff)); /* Addend value. */
+
+ bfd_put_micromips_32 (abfd, opcode, ptr);
+
+ /* Delete the 16-bit delay slot NOP: two bytes from
+ irel->offset + 4. */
+ delcnt = 2;
+ deloff = 4;
+ }
+
+ /* R_MICROMIPS_PC16_S1 relaxation to R_MICROMIPS_PC10_S1. We need
+ to check the distance from the next instruction, so subtract 2. */
+ else if (r_type == R_MICROMIPS_PC16_S1
+ && IS_BITSIZE (pcrval - 2, 11)
+ && find_match (opcode, b_insns_32) >= 0)
+ {
+ /* Fix the relocation's type. */
+ irel->r_info = ELF32_R_INFO (r_symndx, R_MICROMIPS_PC10_S1);
+
+ /* Replace the 32-bit opcode with a 16-bit opcode. */
+ bfd_put_16 (abfd,
+ (b_insn_16.match
+ | (opcode & 0x3ff)), /* Addend value. */
+ ptr);
+
+ /* Delete 2 bytes from irel->r_offset + 2. */
+ delcnt = 2;
+ deloff = 2;
+ }
+
+ /* R_MICROMIPS_PC16_S1 relaxation to R_MICROMIPS_PC7_S1. We need
+ to check the distance from the next instruction, so subtract 2. */
+ else if (r_type == R_MICROMIPS_PC16_S1
+ && IS_BITSIZE (pcrval - 2, 8)
+ && (((fndopc = find_match (opcode, bz_rs_insns_32)) >= 0
+ && OP16_VALID_REG (OP32_SREG (opcode)))
+ || ((fndopc = find_match (opcode, bz_rt_insns_32)) >= 0
+ && OP16_VALID_REG (OP32_TREG (opcode)))))
+ {
+ unsigned long reg;
+
+ reg = OP32_SREG (opcode) ? OP32_SREG (opcode) : OP32_TREG (opcode);
+
+ /* Fix the relocation's type. */
+ irel->r_info = ELF32_R_INFO (r_symndx, R_MICROMIPS_PC7_S1);
+
+ /* Replace the 32-bit opcode with a 16-bit opcode. */
+ bfd_put_16 (abfd,
+ (bz_insns_16[fndopc].match
+ | BZ16_REG_FIELD (reg)
+ | (opcode & 0x7f)), /* Addend value. */
+ ptr);
+
+ /* Delete 2 bytes from irel->r_offset + 2. */
+ delcnt = 2;
+ deloff = 2;
+ }
+
+ /* R_MICROMIPS_26_S1 -- JAL to JALS relaxation for microMIPS targets. */
+ else if (r_type == R_MICROMIPS_26_S1
+ && target_is_micromips_code_p
+ && irel->r_offset + 7 < sec->size
+ && MATCH (opcode, jal_insn_32_bd32))
+ {
+ unsigned long n32opc;
+ bfd_boolean relaxed = FALSE;
+
+ n32opc = bfd_get_micromips_32 (abfd, ptr + 4);
+
+ if (MATCH (n32opc, nop_insn_32))
+ {
+ /* Replace delay slot 32-bit NOP with a 16-bit NOP. */
+ bfd_put_16 (abfd, nop_insn_16.match, ptr + 4);
+
+ relaxed = TRUE;
+ }
+ else if (find_match (n32opc, move_insns_32) >= 0)
+ {
+ /* Replace delay slot 32-bit MOVE with 16-bit MOVE. */
+ bfd_put_16 (abfd,
+ (move_insn_16.match
+ | MOVE16_RD_FIELD (MOVE32_RD (n32opc))
+ | MOVE16_RS_FIELD (MOVE32_RS (n32opc))),
+ ptr + 4);
+
+ relaxed = TRUE;
+ }
+ /* Other 32-bit instructions relaxable to 16-bit
+ instructions will be handled here later. */
+
+ if (relaxed)
+ {
+ /* JAL with 32-bit delay slot that is changed to a JALS
+ with 16-bit delay slot. */
+ bfd_put_micromips_32 (abfd, jal_insn_32_bd16.match, ptr);
+
+ /* Delete 2 bytes from irel->r_offset + 6. */
+ delcnt = 2;
+ deloff = 6;
+ }
+ }
+
+ if (delcnt != 0)
+ {
+ /* Note that we've changed the relocs, section contents, etc. */
+ elf_section_data (sec)->relocs = internal_relocs;
+ elf_section_data (sec)->this_hdr.contents = contents;
+ symtab_hdr->contents = (unsigned char *) isymbuf;
+
+ /* Delete bytes depending on the delcnt and deloff. */
+ if (!mips_elf_relax_delete_bytes (abfd, sec,
+ irel->r_offset + deloff, delcnt))
+ goto error_return;
+
+ /* That will change things, so we should relax again.
+ Note that this is not required, and it may be slow. */
+ *again = TRUE;
+ }
+ }
+
+ if (isymbuf != NULL
+ && symtab_hdr->contents != (unsigned char *) isymbuf)
+ {
+ if (! link_info->keep_memory)
+ free (isymbuf);
+ else
+ {
+ /* Cache the symbols for elf_link_input_bfd. */
+ symtab_hdr->contents = (unsigned char *) isymbuf;
+ }
+ }
+
+ if (contents != NULL
+ && elf_section_data (sec)->this_hdr.contents != contents)
+ {
+ if (! link_info->keep_memory)
+ free (contents);
+ else
+ {
+ /* Cache the section contents for elf_link_input_bfd. */
+ elf_section_data (sec)->this_hdr.contents = contents;
+ }
+ }
+
+ if (internal_relocs != NULL
+ && elf_section_data (sec)->relocs != internal_relocs)
+ free (internal_relocs);
+
+ return TRUE;
+
+ error_return:
+ if (isymbuf != NULL
+ && symtab_hdr->contents != (unsigned char *) isymbuf)
+ free (isymbuf);
+ if (contents != NULL
+ && elf_section_data (sec)->this_hdr.contents != contents)
+ free (contents);
+ if (internal_relocs != NULL
+ && elf_section_data (sec)->relocs != internal_relocs)
+ free (internal_relocs);
+
+ return FALSE;
+}
+\f
+/* Create a MIPS ELF linker hash table. */
+
+struct bfd_link_hash_table *
+_bfd_mips_elf_link_hash_table_create (bfd *abfd)
+{
+ struct mips_elf_link_hash_table *ret;
+ bfd_size_type amt = sizeof (struct mips_elf_link_hash_table);
+
+ ret = bfd_malloc (amt);
+ if (ret == NULL)
+ return NULL;
+
+ if (!_bfd_elf_link_hash_table_init (&ret->root, abfd,
+ mips_elf_link_hash_newfunc,
+ sizeof (struct mips_elf_link_hash_entry),
+ MIPS_ELF_DATA))
+ {
+ free (ret);
+ return NULL;
+ }
+
+#if 0
+ /* We no longer use this. */
+ for (i = 0; i < SIZEOF_MIPS_DYNSYM_SECNAMES; i++)
+ ret->dynsym_sec_strindex[i] = (bfd_size_type) -1;
+#endif