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 BFL instructions which is one of the first instructions in Arm that have more than one relocations in them.
This adds a new relocation R_ARM_THM_BF18.
The inconsistency between external R_ARM_THM_BF18 and internal
BFD_RELOC_ARM_THUMB_BF19 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_BF19): New
	* libbfd.h: Regenerated.
	* bfd-in2.h: Regenerated.
	* bfd-elf32-arm.c (elf32_arm_howto_table_1): New entry for R_ARM_THM_BF18.
	(elf32_arm_reloc_map elf32_arm_reloc_map): Map BFD_RELOC_ARM_THUMB_BF19
	and R_ARM_THM_BF18 together.
	(elf32_arm_final_link_relocate): New switch case for R_ARM_THM_BF19.
*** elfcpp/ChangeLog ***
2019-04-15  Sudakshina Das  <sudi.das@arm.com>
	* arm.h (R_ARM_THM_BF18): 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_BF19.
	(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_BF18.
*** opcodes/ChangeLog ***
2019-04-15  Sudakshina Das  <sudi.das@arm.com>
	* arm-dis.c (print_insn_thumb32): Updated to accept new %Y pattern.
+2019-04-15  Sudakshina Das  <sudi.das@arm.com>
+
+       * reloc.c (BFD_RELOC_ARM_THUMB_BF19): New
+       * libbfd.h: Regenerated.
+       * bfd-in2.h: Regenerated.
+       * bfd-elf32-arm.c (elf32_arm_howto_table_1): New entry for R_ARM_THM_BF18.
+       (elf32_arm_reloc_map elf32_arm_reloc_map): Map BFD_RELOC_ARM_THUMB_BF19
+       and R_ARM_THM_BF18 together.
+       (elf32_arm_final_link_relocate): New switch case for R_ARM_THM_BF19.
+
 2019-04-15  Sudakshina Das  <sudi.das@arm.com>
 
        * reloc.c (BFD_RELOC_ARM_THUMB_BF17): New enum.
 
 /* ARM 17-bit pc-relative branch for Branch Future instructions.  */
   BFD_RELOC_ARM_THUMB_BF17,
 
+/* ARM 19-bit pc-relative branch for Branch Future Link instruction.  */
+  BFD_RELOC_ARM_THUMB_BF19,
+
 /* 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
 
         0x001f0ffe,            /* src_mask.  */
         0x001f0ffe,            /* dst_mask.  */
         TRUE),                 /* pcrel_offset.  */
+  EMPTY_HOWTO (137),
+  HOWTO (R_ARM_THM_BF18,       /* type.  */
+        0,                     /* rightshift.  */
+        1,                     /* size (0 = byte, 1 = short, 2 = long).  */
+        18,                    /* bitsize.  */
+        TRUE,                  /* pc_relative.  */
+        0,                     /* bitpos.  */
+        complain_overflow_dont,/* do not complain_on_overflow.  */
+        bfd_elf_generic_reloc, /* special_function.  */
+        "R_ARM_THM_BF18",      /* name.  */
+        FALSE,                 /* partial_inplace.  */
+        0x007f0ffe,            /* src_mask.  */
+        0x007f0ffe,            /* dst_mask.  */
+        TRUE),                 /* pcrel_offset.  */
 };
 
 /* 160 onwards: */
     {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_BF17, R_ARM_THM_BF16}
+    {BFD_RELOC_ARM_THUMB_BF17, R_ARM_THM_BF16},
+    {BFD_RELOC_ARM_THUMB_BF19, R_ARM_THM_BF18}
   };
 
 static reloc_howto_type *
        return bfd_reloc_ok;
       }
 
+    case R_ARM_THM_BF18:
+      {
+       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 & 0x007f);
+           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 & 0x40000) ? addend - (1 << 19) : 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 & 0x0007f000) >> 12;
+         bfd_vma immB = (relocation & 0x00000ffc) >> 2;
+         bfd_vma immC = (relocation & 0x00000002) >> 1;
+
+         upper_insn = (upper_insn & 0xff80) | 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_JUMP",
   "BFD_RELOC_THUMB_PCREL_BRANCH5",
   "BFD_RELOC_ARM_THUMB_BF17",
+  "BFD_RELOC_ARM_THUMB_BF19",
   "BFD_RELOC_THUMB_PCREL_BRANCH7",
   "BFD_RELOC_THUMB_PCREL_BRANCH9",
   "BFD_RELOC_THUMB_PCREL_BRANCH12",
 
 ENUMDOC
   ARM 17-bit pc-relative branch for Branch Future instructions.
 
+ENUM
+  BFD_RELOC_ARM_THUMB_BF19
+ENUMDOC
+  ARM 19-bit pc-relative branch for Branch Future Link instruction.
+
 ENUM
   BFD_RELOC_THUMB_PCREL_BRANCH7
 ENUMX
 
+2019-04-15  Sudakshina Das  <sudi.das@arm.com>
+
+       * arm.h (R_ARM_THM_BF18): New relocation code.
+
 2019-04-15  Sudakshina Das  <sudi.das@arm.com>
 
        * arm.h (R_ARM_THM_BF16): New relocation code.
 
   // 131 - 135                 Unallocated
   // Relocations for Armv8.1-M Mainline (BF/BFL)
   R_ARM_THM_BF16 = 136,                // Static       Thumb32 ((S + A) | T) – P
+  R_ARM_THM_BF18 = 138,                // Static       Thumb32 ((S + A) | T) – P
   // 139                       Unallocated
   // 140 - 159                 Dynamic         Reserved for future allocation
   R_ARM_IRELATIVE = 160,       // Dynamic
 
+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_BF19.
+       (md_appdy_fix): Likewise.
+       (tc_gen_reloc): Likewise.
+
 2019-04-15  Sudakshina Das  <sudi.das@arm.com>
 
        * config/tc-arm.c (T16_32_TAB): New entries for bfx and bflx.
 
     case BFD_RELOC_THUMB_PCREL_BRANCH20:
     case BFD_RELOC_THUMB_PCREL_BRANCH25:
     case BFD_RELOC_ARM_THUMB_BF17:
+    case BFD_RELOC_ARM_THUMB_BF19:
       return base + 4;
 
     case BFD_RELOC_THUMB_PCREL_BRANCH23:
        }
       break;
 
+    case BFD_RELOC_ARM_THUMB_BF19:
+      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 19 bits wide.  */
+         fixP->fx_done = 0;
+       }
+
+      if (v8_1_branch_value_check (value, 19, 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 & 0x0007f000) >> 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_GOTOFFFUNCDESC:
     case BFD_RELOC_ARM_FUNCDESC:
     case BFD_RELOC_ARM_THUMB_BF17:
+    case BFD_RELOC_ARM_THUMB_BF19:
       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_BF18.
+
 2019-04-15  Sudakshina Das  <sudi.das@arm.com>
 
        * elf/arm.h (START_RELOC_NUMBERS): New entry for R_ARM_THM_BF16.
 
   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_THM_BF18,                138)
 
   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 %Y pattern.
+
 2019-04-15  Sudakshina Das  <sudi.das@arm.com>
 
        * arm-dis.c (print_insn_thumb32): Add '%<bitfield>S' to print an
 
        %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
+       %Y              print an offset for BFL instruction
        %b              print a conditional branch offset
        %B              print an unconditional branch offset
        %s              print the shift field of an SSAT instruction
                }
                break;
 
+             case 'Y':
+               {
+                 unsigned int immA = (given & 0x007f0000u) >> 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 & 0x40000) ? offset - (1 << 19) : offset;
+
+                 info->print_address_func (pc + 4 + offset, info);
+               }
+               break;
+
              case 'b':
                {
                  unsigned int S = (given & 0x04000000u) >> 26;