This patch is part of a series of patches to add support for Armv8.1-M Mainline instructions to binutils.
This adds infrastructure for the BF instructions which is one of the first instructions in Arm that have more than one relocations in them.
This is the third infrastructure patch that adds a new relocation R_ARM_THM_BF16.
The inconsistency between external R_ARM_THM_BF16 and internal
BFD_RELOC_ARM_THUMB_BF17 is because internally we count the static bit-0 of the immediate and we don't externally.
ChangeLog entries are as follows :
*** bfd/ChangeLog ***
2019-04-15 Sudakshina Das <sudi.das@arm.com>
* reloc.c (BFD_RELOC_ARM_THUMB_BF17): New enum.
* bfd-in2.h: Regenerated.
* libbfd.h: Regenerated.
* bfd-elf32-arm.c (elf32_arm_howto_table_1): New entry for R_ARM_THM_BF16.
(elf32_arm_reloc_map elf32_arm_reloc_map): Map BFD_RELOC_ARM_THUMB_BF17
and R_ARM_THM_BF16 together.
(get_value_helper): New reloc helper.
(elf32_arm_final_link_relocate): New switch case for R_ARM_THM_BF16.
*** elfcpp/ChangeLog ***
2019-04-15 Sudakshina Das <sudi.das@arm.com>
* arm.h (R_ARM_THM_BF16): New relocation code.
*** gas/ChangeLog ***
2019-04-15 Sudakshina Das <sudi.das@arm.com>
* config/tc-arm.c (md_pcrel_from_section): New switch case for
BFD_RELOC_ARM_THUMB_BF17.
(md_appdy_fix): Likewise.
(tc_gen_reloc): Likewise.
*** include/ChangeLog ***
2019-04-15 Sudakshina Das <sudi.das@arm.com>
* elf/arm.h (START_RELOC_NUMBERS): New entry for R_ARM_THM_BF16.
*** opcodes/ChangeLog ***
2019-04-15 Sudakshina Das <sudi.das@arm.com>
* arm-dis.c (print_insn_thumb32): Updated to accept new %W pattern.
+2019-04-15 Sudakshina Das <sudi.das@arm.com>
+
+ * reloc.c (BFD_RELOC_ARM_THUMB_BF17): New enum.
+ * bfd-in2.h: Regenerated.
+ * libbfd.h: Regenerated.
+ * bfd-elf32-arm.c (elf32_arm_howto_table_1): New entry for R_ARM_THM_BF16.
+ (elf32_arm_reloc_map elf32_arm_reloc_map): Map BFD_RELOC_ARM_THUMB_BF17
+ and R_ARM_THM_BF16 together.
+ (get_value_helper): New reloc helper.
+ (elf32_arm_final_link_relocate): New switch case for R_ARM_THM_BF16.
+
2019-04-15 Sudakshina Das <sudi.das@arm.com>
* reloc.c (BFD_RELOC_THUMB_PCREL_BRANCH5): New enum.
/* ARM 5-bit pc-relative branch for Branch Future instructions. */
BFD_RELOC_THUMB_PCREL_BRANCH5,
+/* ARM 17-bit pc-relative branch for Branch Future instructions. */
+ BFD_RELOC_ARM_THUMB_BF17,
+
/* Thumb 7-, 9-, 12-, 20-, 23-, and 25-bit pc-relative branches.
The lowest bit must be zero and is not stored in the instruction.
Note that the corresponding ELF R_ARM_THM_JUMPnn constant has an
0x00000000, /* src_mask. */
0x00000000, /* dst_mask. */
FALSE), /* pcrel_offset. */
+ /* Relocations for Armv8.1-M Mainline. */
+ HOWTO (R_ARM_THM_BF16, /* type. */
+ 0, /* rightshift. */
+ 1, /* size (0 = byte, 1 = short, 2 = long). */
+ 16, /* bitsize. */
+ TRUE, /* pc_relative. */
+ 0, /* bitpos. */
+ complain_overflow_dont,/* do not complain_on_overflow. */
+ bfd_elf_generic_reloc, /* special_function. */
+ "R_ARM_THM_BF16", /* name. */
+ FALSE, /* partial_inplace. */
+ 0x001f0ffe, /* src_mask. */
+ 0x001f0ffe, /* dst_mask. */
+ TRUE), /* pcrel_offset. */
};
/* 160 onwards: */
{BFD_RELOC_ARM_THUMB_ALU_ABS_G3_NC, R_ARM_THM_ALU_ABS_G3_NC},
{BFD_RELOC_ARM_THUMB_ALU_ABS_G2_NC, R_ARM_THM_ALU_ABS_G2_NC},
{BFD_RELOC_ARM_THUMB_ALU_ABS_G1_NC, R_ARM_THM_ALU_ABS_G1_NC},
- {BFD_RELOC_ARM_THUMB_ALU_ABS_G0_NC, R_ARM_THM_ALU_ABS_G0_NC}
+ {BFD_RELOC_ARM_THUMB_ALU_ABS_G0_NC, R_ARM_THM_ALU_ABS_G0_NC},
+ {BFD_RELOC_ARM_THUMB_BF17, R_ARM_THM_BF16}
};
static reloc_howto_type *
return 0;
}
+/* Helper function to compute the Addend for Armv8.1-M Mainline relocations. */
+static bfd_vma
+get_value_helper (bfd_vma plt_offset,
+ asection *splt,
+ asection *input_section,
+ asection *sym_sec,
+ struct elf_link_hash_entry * h,
+ struct bfd_link_info *info,
+ bfd *input_bfd,
+ Elf_Internal_Rela *rel,
+ const char *sym_name,
+ unsigned char st_type,
+ struct elf32_arm_link_hash_table *globals,
+ bfd_boolean *unresolved_reloc_p)
+{
+ bfd_vma value = 0;
+ enum arm_st_branch_type branch_type;
+ enum elf32_arm_stub_type stub_type = arm_stub_none;
+ struct elf32_arm_stub_hash_entry *stub_entry;
+ struct elf32_arm_link_hash_entry *hash
+ = (struct elf32_arm_link_hash_entry *)h;
+
+
+ if (plt_offset != (bfd_vma) -1)
+ {
+ value = (splt->output_section->vma
+ + splt->output_offset
+ + plt_offset);
+ value -= PLT_THUMB_STUB_SIZE;
+ *unresolved_reloc_p = FALSE;
+ }
+
+ stub_type = arm_type_of_stub (info, input_section, rel,
+ st_type, &branch_type,
+ hash, value, sym_sec,
+ input_bfd, sym_name);
+
+ if (stub_type != arm_stub_none)
+ {
+ stub_entry = elf32_arm_get_stub_entry (input_section,
+ sym_sec, h,
+ rel, globals,
+ stub_type);
+ if (stub_entry != NULL)
+ {
+ value = (stub_entry->stub_offset
+ + stub_entry->stub_sec->output_offset
+ + stub_entry->stub_sec->output_section->vma);
+ }
+ }
+ return value;
+}
+
/* Perform a relocation as part of a final link. */
static bfd_reloc_status_type
*unresolved_reloc_p = FALSE;
return bfd_reloc_ok;
+ case R_ARM_THM_BF16:
+ {
+ bfd_vma relocation;
+ bfd_vma upper_insn = bfd_get_16 (input_bfd, hit_data);
+ bfd_vma lower_insn = bfd_get_16 (input_bfd, hit_data + 2);
+
+ if (globals->use_rel)
+ {
+ bfd_vma immA = (upper_insn & 0x001f);
+ bfd_vma immB = (lower_insn & 0x07fe) >> 1;
+ bfd_vma immC = (lower_insn & 0x0800) >> 11;
+ addend = (immA << 12);
+ addend |= (immB << 2);
+ addend |= (immC << 1);
+ addend |= 1;
+ /* Sign extend. */
+ addend = (addend & 0x10000) ? addend - (1 << 17) : addend;
+ }
+
+ value = get_value_helper (plt_offset, splt, input_section, sym_sec, h,
+ info, input_bfd, rel, sym_name, st_type,
+ globals, unresolved_reloc_p);
+
+ relocation = value + addend;
+ relocation -= (input_section->output_section->vma
+ + input_section->output_offset
+ + rel->r_offset);
+
+ /* Put RELOCATION back into the insn. */
+ {
+ bfd_vma immA = (relocation & 0x0001f000) >> 12;
+ bfd_vma immB = (relocation & 0x00000ffc) >> 2;
+ bfd_vma immC = (relocation & 0x00000002) >> 1;
+
+ upper_insn = (upper_insn & 0xffe0) | immA;
+ lower_insn = (lower_insn & 0xf001) | (immC << 11) | (immB << 1);
+ }
+
+ /* Put the relocated value back in the object file: */
+ bfd_put_16 (input_bfd, upper_insn, hit_data);
+ bfd_put_16 (input_bfd, lower_insn, hit_data + 2);
+
+ return bfd_reloc_ok;
+ }
+
default:
return bfd_reloc_notsupported;
}
"BFD_RELOC_ARM_PCREL_CALL",
"BFD_RELOC_ARM_PCREL_JUMP",
"BFD_RELOC_THUMB_PCREL_BRANCH5",
+ "BFD_RELOC_ARM_THUMB_BF17",
"BFD_RELOC_THUMB_PCREL_BRANCH7",
"BFD_RELOC_THUMB_PCREL_BRANCH9",
"BFD_RELOC_THUMB_PCREL_BRANCH12",
ENUMDOC
ARM 5-bit pc-relative branch for Branch Future instructions.
+ENUM
+ BFD_RELOC_ARM_THUMB_BF17
+ENUMDOC
+ ARM 17-bit pc-relative branch for Branch Future instructions.
+
ENUM
BFD_RELOC_THUMB_PCREL_BRANCH7
ENUMX
+2019-04-15 Sudakshina Das <sudi.das@arm.com>
+
+ * arm.h (R_ARM_THM_BF16): New relocation code.
+
2018-06-24 Nick Clifton <nickc@redhat.com>
2.32 branch created.
R_ARM_ME_TOO = 128, // Obsolete
R_ARM_THM_TLS_DESCSEQ16 = 129,// Static Thumb16
R_ARM_THM_TLS_DESCSEQ32 = 130,// Static Thumb32
- // 131 - 139 Unallocated
+ // 131 - 135 Unallocated
+ // Relocations for Armv8.1-M Mainline (BF/BFL)
+ R_ARM_THM_BF16 = 136, // Static Thumb32 ((S + A) | T) – P
+ // 139 Unallocated
// 140 - 159 Dynamic Reserved for future allocation
R_ARM_IRELATIVE = 160, // Dynamic
// 161 - 255 Unallocated
+2019-04-15 Sudakshina Das <sudi.das@arm.com>
+
+ * config/tc-arm.c (md_pcrel_from_section): New switch case for
+ BFD_RELOC_ARM_THUMB_BF17.
+ (md_appdy_fix): Likewise.
+ (tc_gen_reloc): Likewise.
+
2019-04-15 Sudakshina Das <sudi.das@arm.com>
* config/tc-arm.c (ARM_IT_MAX_RELOCS): New macro.
case BFD_RELOC_THUMB_PCREL_BRANCH12:
case BFD_RELOC_THUMB_PCREL_BRANCH20:
case BFD_RELOC_THUMB_PCREL_BRANCH25:
+ case BFD_RELOC_ARM_THUMB_BF17:
return base + 4;
case BFD_RELOC_THUMB_PCREL_BRANCH23:
}
break;
+ case BFD_RELOC_ARM_THUMB_BF17:
+ if (fixP->fx_addsy
+ && (S_GET_SEGMENT (fixP->fx_addsy) == seg)
+ && !S_FORCE_RELOC (fixP->fx_addsy, TRUE)
+ && ARM_IS_FUNC (fixP->fx_addsy)
+ && ARM_CPU_HAS_FEATURE (selected_cpu, arm_ext_v8_1m_main))
+ {
+ /* Force a relocation for a branch 17 bits wide. */
+ fixP->fx_done = 0;
+ }
+
+ if (v8_1_branch_value_check (value, 17, TRUE) == FAIL)
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ BAD_BRANCH_OFF);
+
+ if (fixP->fx_done || !seg->use_rela_p)
+ {
+ offsetT newval2;
+ addressT immA, immB, immC;
+
+ immA = (value & 0x0001f000) >> 12;
+ immB = (value & 0x00000ffc) >> 2;
+ immC = (value & 0x00000002) >> 1;
+
+ newval = md_chars_to_number (buf, THUMB_SIZE);
+ newval2 = md_chars_to_number (buf + THUMB_SIZE, THUMB_SIZE);
+ newval |= immA;
+ newval2 |= (immC << 11) | (immB << 1);
+ md_number_to_chars (buf, newval, THUMB_SIZE);
+ md_number_to_chars (buf + THUMB_SIZE, newval2, THUMB_SIZE);
+ }
+ break;
+
case BFD_RELOC_ARM_V4BX:
/* This will need to go in the object file. */
fixP->fx_done = 0;
case BFD_RELOC_ARM_GOTFUNCDESC:
case BFD_RELOC_ARM_GOTOFFFUNCDESC:
case BFD_RELOC_ARM_FUNCDESC:
+ case BFD_RELOC_ARM_THUMB_BF17:
code = fixp->fx_r_type;
break;
+2019-04-15 Sudakshina Das <sudi.das@arm.com>
+
+ * elf/arm.h (START_RELOC_NUMBERS): New entry for R_ARM_THM_BF16.
+
2019-04-15 Thomas Preud'homme <thomas.preudhomme@arm.com>
* elf/arm.h (TAG_CPU_ARCH_V8_1M_MAIN): new macro.
RELOC_NUMBER (R_ARM_THM_ALU_ABS_G1_NC,133)
RELOC_NUMBER (R_ARM_THM_ALU_ABS_G2_NC,134)
RELOC_NUMBER (R_ARM_THM_ALU_ABS_G3_NC,135)
+ RELOC_NUMBER (R_ARM_THM_BF16, 136)
RELOC_NUMBER (R_ARM_IRELATIVE, 160)
RELOC_NUMBER (R_ARM_GOTFUNCDESC, 161)
+2019-04-15 Sudakshina Das <sudi.das@arm.com>
+
+ * arm-dis.c (print_insn_thumb32): Updated to accept new %W pattern.
+
2019-04-15 Sudakshina Das <sudi.das@arm.com>
* arm-dis.c (print_insn_thumb32): Updated to accept new %G pattern.
%E print the lsb and width fields of a bfc/bfi instruction
%F print the lsb and width fields of a sbfx/ubfx instruction
%G print a fallback offset for Branch Future instructions
+ %W print an offset for BF instruction
%b print a conditional branch offset
%B print an unconditional branch offset
%s print the shift field of an SSAT instruction
}
break;
+ case 'W':
+ {
+ unsigned int immA = (given & 0x001f0000u) >> 16;
+ unsigned int immB = (given & 0x000007feu) >> 1;
+ unsigned int immC = (given & 0x00000800u) >> 11;
+ bfd_vma offset = 0;
+
+ offset |= immA << 12;
+ offset |= immB << 2;
+ offset |= immC << 1;
+ /* Sign extend. */
+ offset = (offset & 0x10000) ? offset - (1 << 17) : offset;
+
+ info->print_address_func (pc + 4 + offset, info);
+ }
+ break;
+
case 'b':
{
unsigned int S = (given & 0x04000000u) >> 26;