From e12437dc862690eeaa4a487fee35a237703d2b29 Mon Sep 17 00:00:00 2001 From: Andre Vieira Date: Mon, 15 Apr 2019 11:06:30 +0100 Subject: [PATCH] [binutils, ARM, 3/16] BF insns infrastructure with new bfd_reloc_code_real for fallback branch 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. ChangeLog entries are as follows : *** bfd/ChangeLog *** 2019-04-15 Sudakshina Das * reloc.c (BFD_RELOC_THUMB_PCREL_BRANCH5): New enum. * bfd-in2.h: Regenerate. * libbfd.h: Regenerate. *** gas/ChangeLog *** 2019-04-15 Sudakshina Das * 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-15 Sudakshina Das * arm-dis.c (print_insn_thumb32): Updated to accept new %G pattern. --- bfd/ChangeLog | 6 +++++ bfd/bfd-in2.h | 3 +++ bfd/libbfd.h | 1 + bfd/reloc.c | 5 +++++ gas/ChangeLog | 10 +++++++++ gas/config/tc-arm.c | 54 +++++++++++++++++++++++++++++++++++++++++++++ opcodes/ChangeLog | 4 ++++ opcodes/arm-dis.c | 8 +++++++ 8 files changed, 91 insertions(+) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index d9d1e9b3067..bbb251a000f 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,9 @@ +2019-04-15 Sudakshina Das + + * reloc.c (BFD_RELOC_THUMB_PCREL_BRANCH5): New enum. + * bfd-in2.h: Regenerate. + * libbfd.h: Regenerate. + 2019-04-15 Thomas Preud'homme * archures.c (bfd_mach_arm_8_1M_MAIN): Define. diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index 4f63fe50e6b..3493d4f0de4 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 36284d71a9b..02daa29b433 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 e6446a78098..a071dc75c04 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/ChangeLog b/gas/ChangeLog index 483823ca11a..02f28f24dc1 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,13 @@ +2019-04-15 Sudakshina Das + + * 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. + 2019-04-15 Andre Vieira * config/tc-arm.c (do_neon_movhf): Remove fp-armv8 check. diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c index 11d593c2626..a13baa60348 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/ChangeLog b/opcodes/ChangeLog index 5027e9a573f..fc9697b83d8 100644 --- a/opcodes/ChangeLog +++ b/opcodes/ChangeLog @@ -1,3 +1,7 @@ +2019-04-15 Sudakshina Das + + * arm-dis.c (print_insn_thumb32): Updated to accept new %G pattern. + 2019-04-15 Thomas Preud'homme * arm-dis.c (select_arm_features): Add logic for Armv8.1-M Mainline. diff --git a/opcodes/arm-dis.c b/opcodes/arm-dis.c index e38296edea9..0ed893b01ac 100644 --- a/opcodes/arm-dis.c +++ b/opcodes/arm-dis.c @@ -2713,6 +2713,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 @@ -5862,6 +5863,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; -- 2.30.2