[ARM,3/16] BF insns infrastructure with new bfd_reloc_code_real for fallback branch

Message ID 828e7e11-c886-9d98-461e-2fbb150b8e96@arm.com
State New
Headers show
Series
  • Add support for Armv8.1-M Mainline
Related show

Commit Message

Andre Vieira (lists) April 4, 2019, 1:34 p.m.
Hi

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 Branch Future instructions (BF, BFX, 
BFL, BFLX, BFCSEL). These are the first instructions in ARM that
have more than one relocations in them.

This is the first infrastructure patch that adds a new 
bfd_reloc_code_real enum for the fallback branch offset.
This is common for all such instructions and needs to be resolvable by 
the assembler.

Testing: Builds successfully and no regressions.

Thanks
Sudi


ChangeLog entries are as follows :
*** bfd/ChnageLog ***

2019-04-04  Sudakshina Das  <sudi.das@arm.com>

	* reloc.c (BFD_RELOC_THUMB_PCREL_BRANCH5): New enum.
	* bfd-in2.h: Regenerate.
	* libbfd.h: Regenerate.

*** gas/ChangeLog ***

2019-04-04  Sudakshina Das  <sudi.das@arm.com>

	* config/tc-arm.c (md_pcrel_from_section): New switch case
	for BFD_RELOC_THUMB_PCREL_BRANCH5.
	(v8_1_branch_value_check): New function to check branch
	offsets.
	(md_appdy_fix): New switch case for
	BFD_RELOC_THUMB_PCREL_BRANCH5.
	(tc_gen_reloc): Likewise.

*** opcodes/ChangeLog ***

2019-04-04  Sudakshina Das  <sudi.das@arm.com>

	* arm-dis.c (print_insn_thumb32): Updated to accept new %G pattern.

Patch

diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index 4f63fe50e6bf8003fb25beec9e64927a672e444b..3493d4f0de41cb184710248ce6664700bca78cca 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -3564,6 +3564,9 @@  field in the instruction.  */
 /* ARM 26-bit pc-relative branch for B or conditional BL instruction.  */
   BFD_RELOC_ARM_PCREL_JUMP,
 
+/* ARM 5-bit pc-relative branch for Branch Future instructions.  */
+  BFD_RELOC_THUMB_PCREL_BRANCH5,
+
 /* 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
diff --git a/bfd/libbfd.h b/bfd/libbfd.h
index 36284d71a9bdb0237ad678027441ccf0fe880430..02daa29b433e390507fe91e7a045f43eb85d548d 100644
--- a/bfd/libbfd.h
+++ b/bfd/libbfd.h
@@ -1529,6 +1529,7 @@  static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
   "BFD_RELOC_THUMB_PCREL_BLX",
   "BFD_RELOC_ARM_PCREL_CALL",
   "BFD_RELOC_ARM_PCREL_JUMP",
+  "BFD_RELOC_THUMB_PCREL_BRANCH5",
   "BFD_RELOC_THUMB_PCREL_BRANCH7",
   "BFD_RELOC_THUMB_PCREL_BRANCH9",
   "BFD_RELOC_THUMB_PCREL_BRANCH12",
diff --git a/bfd/reloc.c b/bfd/reloc.c
index e6446a78098602d91d3c7f4a0b20807b805bb829..a071dc75c0499192077da30aba8ee7fc3d62dacb 100644
--- a/bfd/reloc.c
+++ b/bfd/reloc.c
@@ -3014,6 +3014,11 @@  ENUM
 ENUMDOC
   ARM 26-bit pc-relative branch for B or conditional BL instruction.
 
+ENUM
+  BFD_RELOC_THUMB_PCREL_BRANCH5
+ENUMDOC
+  ARM 5-bit pc-relative branch for Branch Future instructions.
+
 ENUM
   BFD_RELOC_THUMB_PCREL_BRANCH7
 ENUMX
diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c
index 11d593c2626199d0dad4f4d81a276decb0300d3c..a13baa603486623836977d4c8f68ac283d02cbab 100644
--- a/gas/config/tc-arm.c
+++ b/gas/config/tc-arm.c
@@ -235,6 +235,8 @@  static const arm_feature_set arm_ext_pan = ARM_FEATURE_CORE_HIGH (ARM_EXT2_PAN);
 static const arm_feature_set arm_ext_v8m = ARM_FEATURE_CORE_HIGH (ARM_EXT2_V8M);
 static const arm_feature_set arm_ext_v8m_main =
   ARM_FEATURE_CORE_HIGH (ARM_EXT2_V8M_MAIN);
+static const arm_feature_set arm_ext_v8_1m_main =
+ARM_FEATURE_CORE_HIGH (ARM_EXT2_V8_1M_MAIN);
 /* Instructions in ARMv8-M only found in M profile architectures.  */
 static const arm_feature_set arm_ext_v8m_m_only =
   ARM_FEATURE_CORE_HIGH (ARM_EXT2_V8M | ARM_EXT2_V8M_MAIN);
@@ -843,6 +845,7 @@  struct asm_opcode
 #define BAD_THUMB32	_("instruction not supported in Thumb16 mode")
 #define BAD_ADDR_MODE   _("instruction does not accept this addressing mode");
 #define BAD_BRANCH	_("branch must be last instruction in IT block")
+#define BAD_BRANCH_OFF	_("branch out of range or not a multiple of 2")
 #define BAD_NOT_IT	_("instruction not allowed in IT block")
 #define BAD_FPU		_("selected FPU does not support instruction")
 #define BAD_OUT_IT 	_("thumb conditional instruction should be in IT block")
@@ -13272,6 +13275,26 @@  do_t_usat16 (void)
   inst.instruction |= Rn << 16;
 }
 
+/* Checking the range of the branch offset (VAL) with NBITS bits
+   and IS_SIGNED signedness.  Also checks the LSB to be 0.  */
+static int
+v8_1_branch_value_check (int val, int nbits, int is_signed)
+{
+  gas_assert (nbits > 0 && nbits <= 32);
+  if (is_signed)
+    {
+      int cmp = (1 << (nbits - 1));
+      if ((val < -cmp) || (val >= cmp) || (val & 0x01))
+	return FAIL;
+    }
+  else
+    {
+      if ((val <= 0) || (val >= (1 << nbits)) || (val & 0x1))
+	return FAIL;
+    }
+    return SUCCESS;
+}
+
 /* Neon instruction encoder helpers.  */
 
 /* Encodings for the different types for various Neon opcodes.  */
@@ -22791,6 +22814,7 @@  md_pcrel_from_section (fixS * fixP, segT seg)
       return (base + 4) & ~3;
 
       /* Thumb branches are simply offset by +4.  */
+    case BFD_RELOC_THUMB_PCREL_BRANCH5:
     case BFD_RELOC_THUMB_PCREL_BRANCH7:
     case BFD_RELOC_THUMB_PCREL_BRANCH9:
     case BFD_RELOC_THUMB_PCREL_BRANCH12:
@@ -24669,6 +24693,30 @@  md_apply_fix (fixS *	fixP,
 	}
       break;
 
+    case BFD_RELOC_THUMB_PCREL_BRANCH5:
+      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 5 bits wide.  */
+	  fixP->fx_done = 0;
+	}
+      if (v8_1_branch_value_check (value, 5, FALSE) == FAIL)
+	as_bad_where (fixP->fx_file, fixP->fx_line,
+		      BAD_BRANCH_OFF);
+
+      if (fixP->fx_done || !seg->use_rela_p)
+	{
+	  addressT boff = value >> 1;
+
+	  newval  = md_chars_to_number (buf, THUMB_SIZE);
+	  newval |= (boff << 7);
+	  md_number_to_chars (buf, newval, THUMB_SIZE);
+	}
+      break;
+
     case BFD_RELOC_ARM_V4BX:
       /* This will need to go in the object file.  */
       fixP->fx_done = 0;
@@ -24880,6 +24928,12 @@  tc_gen_reloc (asection *section, fixS *fixp)
 		    _("ADRL used for a symbol not defined in the same file"));
       return NULL;
 
+    case BFD_RELOC_THUMB_PCREL_BRANCH5:
+      as_bad_where (fixp->fx_file, fixp->fx_line,
+		    _("%s used for a symbol not defined in the same file"),
+		    bfd_get_reloc_code_name (fixp->fx_r_type));
+      return NULL;
+
     case BFD_RELOC_ARM_OFFSET_IMM:
       if (section->use_rela_p)
 	{
diff --git a/opcodes/arm-dis.c b/opcodes/arm-dis.c
index be9879da621c14e4dd8a816a371aaad6ccc4a696..0fe44877db243b8cbce50fed451e65fcacf9fabc 100644
--- a/opcodes/arm-dis.c
+++ b/opcodes/arm-dis.c
@@ -2714,6 +2714,7 @@  static const struct opcode16 thumb_opcodes[] =
 
        %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
        %b		print a conditional branch offset
        %B		print an unconditional branch offset
        %s		print the shift field of an SSAT instruction
@@ -5863,6 +5864,13 @@  print_insn_thumb32 (bfd_vma pc, struct disassemble_info *info, long given)
 		}
 		break;
 
+	      case 'G':
+		{
+		  unsigned int boff = (((given & 0x07800000) >> 23) << 1);
+		  func (stream, "%x", boff);
+		}
+		break;
+
 	      case 'b':
 		{
 		  unsigned int S = (given & 0x04000000u) >> 26;