#include "xtensa-isa.h"
#include "xtensa-config.h"
+/* All users of this file have bfd_octets_per_byte (abfd, sec) == 1. */
+#define OCTETS_PER_BYTE(ABFD, SEC) 1
+
#define XTENSA_NO_NOP_REMOVAL 0
/* Local helper functions. */
static bfd_boolean is_operand_relocation (int);
static bfd_size_type insn_decode_len
(bfd_byte *, bfd_size_type, bfd_size_type);
+static int insn_num_slots
+ (bfd_byte *, bfd_size_type, bfd_size_type);
static xtensa_opcode insn_decode_opcode
(bfd_byte *, bfd_size_type, bfd_size_type, int);
static bfd_boolean check_branch_target_aligned
/* Mark the ".got.plt" section READONLY. */
if (htab->elf.sgotplt == NULL
- || ! bfd_set_section_flags (dynobj, htab->elf.sgotplt, flags))
+ || !bfd_set_section_flags (htab->elf.sgotplt, flags))
return FALSE;
/* Create ".got.loc" (literal tables for use by dynamic linker). */
htab->sgotloc = bfd_make_section_anyway_with_flags (dynobj, ".got.loc",
flags);
if (htab->sgotloc == NULL
- || ! bfd_set_section_alignment (dynobj, htab->sgotloc, 2))
+ || !bfd_set_section_alignment (htab->sgotloc, 2))
return FALSE;
/* Create ".xt.lit.plt" (literal table for ".got.plt*"). */
htab->spltlittbl = bfd_make_section_anyway_with_flags (dynobj, ".xt.lit.plt",
noalloc_flags);
if (htab->spltlittbl == NULL
- || ! bfd_set_section_alignment (dynobj, htab->spltlittbl, 2))
+ || !bfd_set_section_alignment (htab->spltlittbl, 2))
return FALSE;
return TRUE;
sprintf (sname, ".plt.%u", chunk);
s = bfd_make_section_anyway_with_flags (dynobj, sname, flags | SEC_CODE);
if (s == NULL
- || ! bfd_set_section_alignment (dynobj, s, 2))
+ || !bfd_set_section_alignment (s, 2))
return FALSE;
sname = (char *) bfd_malloc (14);
sprintf (sname, ".got.plt.%u", chunk);
s = bfd_make_section_anyway_with_flags (dynobj, sname, flags);
if (s == NULL
- || ! bfd_set_section_alignment (dynobj, s, 2))
+ || !bfd_set_section_alignment (s, 2))
return FALSE;
}
/* It's OK to base decisions on the section name, because none
of the dynobj section names depend upon the input files. */
- name = bfd_get_section_name (dynobj, s);
+ name = bfd_section_name (s);
if (CONST_STRNEQ (name, ".rela"))
{
{
bfd_vma relocation;
bfd_reloc_status_type flag;
- bfd_size_type octets = reloc_entry->address * bfd_octets_per_byte (abfd);
+ bfd_size_type octets = (reloc_entry->address
+ * OCTETS_PER_BYTE (abfd, input_section));
bfd_vma output_base = 0;
reloc_howto_type *howto = reloc_entry->howto;
asection *reloc_target_output_section;
name = (bfd_elf_string_from_elf_section
(input_bfd, symtab_hdr->sh_link, sym->st_name));
if (name == NULL || *name == '\0')
- name = bfd_section_name (input_bfd, sec);
+ name = bfd_section_name (sec);
}
if (r_symndx != STN_UNDEF
file. This gets the Xtensa architecture right based on the machine
number. */
-static void
-elf_xtensa_final_write_processing (bfd *abfd,
- bfd_boolean linker ATTRIBUTE_UNUSED)
+static bfd_boolean
+elf_xtensa_final_write_processing (bfd *abfd)
{
int mach;
- unsigned long val;
+ unsigned long val = elf_elfheader (abfd)->e_flags & EF_XTENSA_MACH;
switch (mach = bfd_get_mach (abfd))
{
val = E_XTENSA_MACH;
break;
default:
- return;
+ break;
}
- elf_elfheader (abfd)->e_flags &= (~ EF_XTENSA_MACH);
+ elf_elfheader (abfd)->e_flags &= ~EF_XTENSA_MACH;
elf_elfheader (abfd)->e_flags |= val;
+ return _bfd_elf_final_write_processing (abfd);
}
}
+static xtensa_opcode
+get_rsr_lend_opcode (void)
+{
+ static xtensa_opcode rsr_lend_opcode = XTENSA_UNDEFINED;
+ static bfd_boolean done_lookup = FALSE;
+ if (!done_lookup)
+ {
+ rsr_lend_opcode = xtensa_opcode_lookup (xtensa_default_isa, "rsr.lend");
+ done_lookup = TRUE;
+ }
+ return rsr_lend_opcode;
+}
+
+static xtensa_opcode
+get_wsr_lbeg_opcode (void)
+{
+ static xtensa_opcode wsr_lbeg_opcode = XTENSA_UNDEFINED;
+ static bfd_boolean done_lookup = FALSE;
+ if (!done_lookup)
+ {
+ wsr_lbeg_opcode = xtensa_opcode_lookup (xtensa_default_isa, "wsr.lbeg");
+ done_lookup = TRUE;
+ }
+ return wsr_lbeg_opcode;
+}
+
+
static int
get_relocation_opnd (xtensa_opcode opcode, int r_type)
{
return insn_len;
}
+int
+insn_num_slots (bfd_byte *contents,
+ bfd_size_type content_len,
+ bfd_size_type offset)
+{
+ xtensa_isa isa = xtensa_default_isa;
+ xtensa_format fmt;
+ static xtensa_insnbuf ibuff = NULL;
+
+ if (offset + MIN_INSN_LENGTH > content_len)
+ return XTENSA_UNDEFINED;
+
+ if (ibuff == NULL)
+ ibuff = xtensa_insnbuf_alloc (isa);
+ xtensa_insnbuf_from_chars (isa, ibuff, &contents[offset],
+ content_len - offset);
+ fmt = xtensa_format_decode (isa, ibuff);
+ if (fmt == XTENSA_UNDEFINED)
+ return XTENSA_UNDEFINED;
+ return xtensa_format_num_slots (isa, fmt);
+}
+
/* Decode the opcode for a single slot instruction.
Return 0 if it fails to decode or the instruction is multi-slot. */
return FALSE;
}
+ /* If this is relaxed loop, analyze first instruction of the actual loop
+ body. It must be at offset 27 from the loop instruction address. */
+ if (insn_len == 3
+ && insn_num_slots (contents, content_length, offset + loop_len) == 1
+ && insn_decode_opcode (contents, content_length,
+ offset + loop_len, 0) == get_rsr_lend_opcode()
+ && insn_decode_len (contents, content_length, offset + loop_len + 3) == 3
+ && insn_num_slots (contents, content_length, offset + loop_len + 3) == 1
+ && insn_decode_opcode (contents, content_length,
+ offset + loop_len + 3, 0) == get_wsr_lbeg_opcode())
+ {
+ loop_len = 27;
+ insn_len = insn_decode_len (contents, content_length, offset + loop_len);
+ }
return check_branch_target_aligned_address (address + loop_len, insn_len);
}
if (! prop_sec)
{
flagword flags = (SEC_RELOC | SEC_HAS_CONTENTS | SEC_READONLY);
- flags |= (bfd_get_section_flags (sec->owner, sec)
+ flags |= (bfd_section_flags (sec)
& (SEC_LINK_ONCE | SEC_LINK_DUPLICATES));
prop_sec = bfd_make_section_anyway_with_flags