X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gas%2Fconfig%2Ftc-arm.c;h=1793965785c32f868c8cf4bd00bdfa4b1e3083b1;hb=c12d2c9d48cf18d818f79b89bffda934c354fdac;hp=ded989aa390bd2f92c122d0e5b4ff1a9c3622571;hpb=4e9aaefbd0042f5372509cd51ef2791a68aa30b0;p=deliverable%2Fbinutils-gdb.git diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c index ded989aa39..1793965785 100644 --- a/gas/config/tc-arm.c +++ b/gas/config/tc-arm.c @@ -168,82 +168,99 @@ static const arm_feature_set fpu_endian_pure = FPU_ARCH_ENDIAN_PURE; static const arm_feature_set cpu_default = CPU_DEFAULT; #endif -static const arm_feature_set arm_ext_v1 = ARM_FEATURE (ARM_EXT_V1, 0); -static const arm_feature_set arm_ext_v2 = ARM_FEATURE (ARM_EXT_V1, 0); -static const arm_feature_set arm_ext_v2s = ARM_FEATURE (ARM_EXT_V2S, 0); -static const arm_feature_set arm_ext_v3 = ARM_FEATURE (ARM_EXT_V3, 0); -static const arm_feature_set arm_ext_v3m = ARM_FEATURE (ARM_EXT_V3M, 0); -static const arm_feature_set arm_ext_v4 = ARM_FEATURE (ARM_EXT_V4, 0); -static const arm_feature_set arm_ext_v4t = ARM_FEATURE (ARM_EXT_V4T, 0); -static const arm_feature_set arm_ext_v5 = ARM_FEATURE (ARM_EXT_V5, 0); +static const arm_feature_set arm_ext_v1 = ARM_FEATURE_CORE_LOW (ARM_EXT_V1); +static const arm_feature_set arm_ext_v2 = ARM_FEATURE_CORE_LOW (ARM_EXT_V1); +static const arm_feature_set arm_ext_v2s = ARM_FEATURE_CORE_LOW (ARM_EXT_V2S); +static const arm_feature_set arm_ext_v3 = ARM_FEATURE_CORE_LOW (ARM_EXT_V3); +static const arm_feature_set arm_ext_v3m = ARM_FEATURE_CORE_LOW (ARM_EXT_V3M); +static const arm_feature_set arm_ext_v4 = ARM_FEATURE_CORE_LOW (ARM_EXT_V4); +static const arm_feature_set arm_ext_v4t = ARM_FEATURE_CORE_LOW (ARM_EXT_V4T); +static const arm_feature_set arm_ext_v5 = ARM_FEATURE_CORE_LOW (ARM_EXT_V5); static const arm_feature_set arm_ext_v4t_5 = - ARM_FEATURE (ARM_EXT_V4T | ARM_EXT_V5, 0); -static const arm_feature_set arm_ext_v5t = ARM_FEATURE (ARM_EXT_V5T, 0); -static const arm_feature_set arm_ext_v5e = ARM_FEATURE (ARM_EXT_V5E, 0); -static const arm_feature_set arm_ext_v5exp = ARM_FEATURE (ARM_EXT_V5ExP, 0); -static const arm_feature_set arm_ext_v5j = ARM_FEATURE (ARM_EXT_V5J, 0); -static const arm_feature_set arm_ext_v6 = ARM_FEATURE (ARM_EXT_V6, 0); -static const arm_feature_set arm_ext_v6k = ARM_FEATURE (ARM_EXT_V6K, 0); -static const arm_feature_set arm_ext_v6t2 = ARM_FEATURE (ARM_EXT_V6T2, 0); -static const arm_feature_set arm_ext_v6m = ARM_FEATURE (ARM_EXT_V6M, 0); -static const arm_feature_set arm_ext_v6_notm = ARM_FEATURE (ARM_EXT_V6_NOTM, 0); -static const arm_feature_set arm_ext_v6_dsp = ARM_FEATURE (ARM_EXT_V6_DSP, 0); -static const arm_feature_set arm_ext_barrier = ARM_FEATURE (ARM_EXT_BARRIER, 0); -static const arm_feature_set arm_ext_msr = ARM_FEATURE (ARM_EXT_THUMB_MSR, 0); -static const arm_feature_set arm_ext_div = ARM_FEATURE (ARM_EXT_DIV, 0); -static const arm_feature_set arm_ext_v7 = ARM_FEATURE (ARM_EXT_V7, 0); -static const arm_feature_set arm_ext_v7a = ARM_FEATURE (ARM_EXT_V7A, 0); -static const arm_feature_set arm_ext_v7r = ARM_FEATURE (ARM_EXT_V7R, 0); -static const arm_feature_set arm_ext_v7m = ARM_FEATURE (ARM_EXT_V7M, 0); -static const arm_feature_set arm_ext_v8 = ARM_FEATURE (ARM_EXT_V8, 0); + ARM_FEATURE_CORE_LOW (ARM_EXT_V4T | ARM_EXT_V5); +static const arm_feature_set arm_ext_v5t = ARM_FEATURE_CORE_LOW (ARM_EXT_V5T); +static const arm_feature_set arm_ext_v5e = ARM_FEATURE_CORE_LOW (ARM_EXT_V5E); +static const arm_feature_set arm_ext_v5exp = ARM_FEATURE_CORE_LOW (ARM_EXT_V5ExP); +static const arm_feature_set arm_ext_v5j = ARM_FEATURE_CORE_LOW (ARM_EXT_V5J); +static const arm_feature_set arm_ext_v6 = ARM_FEATURE_CORE_LOW (ARM_EXT_V6); +static const arm_feature_set arm_ext_v6k = ARM_FEATURE_CORE_LOW (ARM_EXT_V6K); +static const arm_feature_set arm_ext_v6t2 = ARM_FEATURE_CORE_LOW (ARM_EXT_V6T2); +static const arm_feature_set arm_ext_v6m = ARM_FEATURE_CORE_LOW (ARM_EXT_V6M); +static const arm_feature_set arm_ext_v6_notm = + ARM_FEATURE_CORE_LOW (ARM_EXT_V6_NOTM); +static const arm_feature_set arm_ext_v6_dsp = + ARM_FEATURE_CORE_LOW (ARM_EXT_V6_DSP); +static const arm_feature_set arm_ext_barrier = + ARM_FEATURE_CORE_LOW (ARM_EXT_BARRIER); +static const arm_feature_set arm_ext_msr = + ARM_FEATURE_CORE_LOW (ARM_EXT_THUMB_MSR); +static const arm_feature_set arm_ext_div = ARM_FEATURE_CORE_LOW (ARM_EXT_DIV); +static const arm_feature_set arm_ext_v7 = ARM_FEATURE_CORE_LOW (ARM_EXT_V7); +static const arm_feature_set arm_ext_v7a = ARM_FEATURE_CORE_LOW (ARM_EXT_V7A); +static const arm_feature_set arm_ext_v7r = ARM_FEATURE_CORE_LOW (ARM_EXT_V7R); +static const arm_feature_set arm_ext_v7m = ARM_FEATURE_CORE_LOW (ARM_EXT_V7M); +static const arm_feature_set arm_ext_v8 = ARM_FEATURE_CORE_LOW (ARM_EXT_V8); static const arm_feature_set arm_ext_m = - ARM_FEATURE (ARM_EXT_V6M | ARM_EXT_OS | ARM_EXT_V7M, 0); -static const arm_feature_set arm_ext_mp = ARM_FEATURE (ARM_EXT_MP, 0); -static const arm_feature_set arm_ext_sec = ARM_FEATURE (ARM_EXT_SEC, 0); -static const arm_feature_set arm_ext_os = ARM_FEATURE (ARM_EXT_OS, 0); -static const arm_feature_set arm_ext_adiv = ARM_FEATURE (ARM_EXT_ADIV, 0); -static const arm_feature_set arm_ext_virt = ARM_FEATURE (ARM_EXT_VIRT, 0); + ARM_FEATURE_CORE_LOW (ARM_EXT_V6M | ARM_EXT_OS | ARM_EXT_V7M); +static const arm_feature_set arm_ext_mp = ARM_FEATURE_CORE_LOW (ARM_EXT_MP); +static const arm_feature_set arm_ext_sec = ARM_FEATURE_CORE_LOW (ARM_EXT_SEC); +static const arm_feature_set arm_ext_os = ARM_FEATURE_CORE_LOW (ARM_EXT_OS); +static const arm_feature_set arm_ext_adiv = ARM_FEATURE_CORE_LOW (ARM_EXT_ADIV); +static const arm_feature_set arm_ext_virt = ARM_FEATURE_CORE_LOW (ARM_EXT_VIRT); +static const arm_feature_set arm_ext_pan = ARM_FEATURE_CORE_HIGH (ARM_EXT2_PAN); static const arm_feature_set arm_arch_any = ARM_ANY; -static const arm_feature_set arm_arch_full = ARM_FEATURE (-1, -1); +static const arm_feature_set arm_arch_full = ARM_FEATURE (-1, -1, -1); static const arm_feature_set arm_arch_t2 = ARM_ARCH_THUMB2; static const arm_feature_set arm_arch_none = ARM_ARCH_NONE; static const arm_feature_set arm_arch_v6m_only = ARM_ARCH_V6M_ONLY; static const arm_feature_set arm_cext_iwmmxt2 = - ARM_FEATURE (0, ARM_CEXT_IWMMXT2); + ARM_FEATURE_COPROC (ARM_CEXT_IWMMXT2); static const arm_feature_set arm_cext_iwmmxt = - ARM_FEATURE (0, ARM_CEXT_IWMMXT); + ARM_FEATURE_COPROC (ARM_CEXT_IWMMXT); static const arm_feature_set arm_cext_xscale = - ARM_FEATURE (0, ARM_CEXT_XSCALE); + ARM_FEATURE_COPROC (ARM_CEXT_XSCALE); static const arm_feature_set arm_cext_maverick = - ARM_FEATURE (0, ARM_CEXT_MAVERICK); -static const arm_feature_set fpu_fpa_ext_v1 = ARM_FEATURE (0, FPU_FPA_EXT_V1); -static const arm_feature_set fpu_fpa_ext_v2 = ARM_FEATURE (0, FPU_FPA_EXT_V2); + ARM_FEATURE_COPROC (ARM_CEXT_MAVERICK); +static const arm_feature_set fpu_fpa_ext_v1 = + ARM_FEATURE_COPROC (FPU_FPA_EXT_V1); +static const arm_feature_set fpu_fpa_ext_v2 = + ARM_FEATURE_COPROC (FPU_FPA_EXT_V2); static const arm_feature_set fpu_vfp_ext_v1xd = - ARM_FEATURE (0, FPU_VFP_EXT_V1xD); -static const arm_feature_set fpu_vfp_ext_v1 = ARM_FEATURE (0, FPU_VFP_EXT_V1); -static const arm_feature_set fpu_vfp_ext_v2 = ARM_FEATURE (0, FPU_VFP_EXT_V2); -static const arm_feature_set fpu_vfp_ext_v3xd = ARM_FEATURE (0, FPU_VFP_EXT_V3xD); -static const arm_feature_set fpu_vfp_ext_v3 = ARM_FEATURE (0, FPU_VFP_EXT_V3); + ARM_FEATURE_COPROC (FPU_VFP_EXT_V1xD); +static const arm_feature_set fpu_vfp_ext_v1 = + ARM_FEATURE_COPROC (FPU_VFP_EXT_V1); +static const arm_feature_set fpu_vfp_ext_v2 = + ARM_FEATURE_COPROC (FPU_VFP_EXT_V2); +static const arm_feature_set fpu_vfp_ext_v3xd = + ARM_FEATURE_COPROC (FPU_VFP_EXT_V3xD); +static const arm_feature_set fpu_vfp_ext_v3 = + ARM_FEATURE_COPROC (FPU_VFP_EXT_V3); static const arm_feature_set fpu_vfp_ext_d32 = - ARM_FEATURE (0, FPU_VFP_EXT_D32); -static const arm_feature_set fpu_neon_ext_v1 = ARM_FEATURE (0, FPU_NEON_EXT_V1); + ARM_FEATURE_COPROC (FPU_VFP_EXT_D32); +static const arm_feature_set fpu_neon_ext_v1 = + ARM_FEATURE_COPROC (FPU_NEON_EXT_V1); static const arm_feature_set fpu_vfp_v3_or_neon_ext = - ARM_FEATURE (0, FPU_NEON_EXT_V1 | FPU_VFP_EXT_V3); -static const arm_feature_set fpu_vfp_fp16 = ARM_FEATURE (0, FPU_VFP_EXT_FP16); -static const arm_feature_set fpu_neon_ext_fma = ARM_FEATURE (0, FPU_NEON_EXT_FMA); -static const arm_feature_set fpu_vfp_ext_fma = ARM_FEATURE (0, FPU_VFP_EXT_FMA); + ARM_FEATURE_COPROC (FPU_NEON_EXT_V1 | FPU_VFP_EXT_V3); +static const arm_feature_set fpu_vfp_fp16 = + ARM_FEATURE_COPROC (FPU_VFP_EXT_FP16); +static const arm_feature_set fpu_neon_ext_fma = + ARM_FEATURE_COPROC (FPU_NEON_EXT_FMA); +static const arm_feature_set fpu_vfp_ext_fma = + ARM_FEATURE_COPROC (FPU_VFP_EXT_FMA); static const arm_feature_set fpu_vfp_ext_armv8 = - ARM_FEATURE (0, FPU_VFP_EXT_ARMV8); + ARM_FEATURE_COPROC (FPU_VFP_EXT_ARMV8); static const arm_feature_set fpu_vfp_ext_armv8xd = - ARM_FEATURE (0, FPU_VFP_EXT_ARMV8xD); + ARM_FEATURE_COPROC (FPU_VFP_EXT_ARMV8xD); static const arm_feature_set fpu_neon_ext_armv8 = - ARM_FEATURE (0, FPU_NEON_EXT_ARMV8); + ARM_FEATURE_COPROC (FPU_NEON_EXT_ARMV8); static const arm_feature_set fpu_crypto_ext_armv8 = - ARM_FEATURE (0, FPU_CRYPTO_EXT_ARMV8); + ARM_FEATURE_COPROC (FPU_CRYPTO_EXT_ARMV8); static const arm_feature_set crc_ext_armv8 = - ARM_FEATURE (0, CRC_EXT_ARMV8); + ARM_FEATURE_COPROC (CRC_EXT_ARMV8); +static const arm_feature_set fpu_neon_ext_v8_1 = + ARM_FEATURE_COPROC (FPU_NEON_EXT_ARMV8 | FPU_NEON_EXT_RDMA); static int mfloat_abi_opt = -1; /* Record user cpu selection for object attributes. */ @@ -257,8 +274,7 @@ extern FLONUM_TYPE generic_floating_point_number; static bfd_boolean no_cpu_selected (void) { - return selected_cpu.core == arm_arch_none.core - && selected_cpu.coproc == arm_arch_none.coproc; + return ARM_FEATURE_EQUAL (selected_cpu, arm_arch_none); } #ifdef OBJ_ELF @@ -4908,7 +4924,9 @@ parse_fpa_immediate (char ** str) { /* FIXME: 5 = X_PRECISION, should be #define'd where we can use it. Ditto for 15. */ - if (gen_to_words (words, 5, (long) 15) == 0) +#define X_PRECISION 5 +#define E_PRECISION 15L + if (gen_to_words (words, X_PRECISION, E_PRECISION) == 0) { for (i = 0; i < NUM_FLOAT_VALS; i++) { @@ -5769,7 +5787,7 @@ parse_psr (char **str, bfd_boolean lhs) /* PR gas/12698: If the user has specified -march=all then m_profile will be TRUE, but we want to ignore it in this case as we are building for any CPU type, including non-m variants. */ - if (selected_cpu.core == arm_arch_any.core) + if (ARM_FEATURE_CORE_EQUAL (selected_cpu, arm_arch_any)) m_profile = FALSE; /* CPSR's and SPSR's can now be lowercase. This is just a convenience @@ -7038,7 +7056,7 @@ parse_operands (char *str, const unsigned int *pattern, bfd_boolean thumb) val = parse_reg_list (&str); if (*str == '^') { - inst.operands[1].writeback = 1; + inst.operands[i].writeback = 1; str++; } break; @@ -7734,6 +7752,54 @@ neon_cmode_for_move_imm (unsigned immlo, unsigned immhi, int float_p, return FAIL; } +#if defined BFD_HOST_64_BIT +/* Returns TRUE if double precision value V may be cast + to single precision without loss of accuracy. */ + +static bfd_boolean +is_double_a_single (bfd_int64_t v) +{ + int exp = (int)((v >> 52) & 0x7FF); + bfd_int64_t mantissa = (v & (bfd_int64_t)0xFFFFFFFFFFFFF); + + return (exp == 0 || exp == 0x7FF + || (exp >= 1023 - 126 && exp <= 1023 + 127)) + && (mantissa & 0x1FFFFFFFl) == 0; +} + +/* Returns a double precision value casted to single precision + (ignoring the least significant bits in exponent and mantissa). */ + +static int +double_to_single (bfd_int64_t v) +{ + int sign = (int) ((v >> 63) & 1l); + int exp = (int) ((v >> 52) & 0x7FF); + bfd_int64_t mantissa = (v & (bfd_int64_t)0xFFFFFFFFFFFFF); + + if (exp == 0x7FF) + exp = 0xFF; + else + { + exp = exp - 1023 + 127; + if (exp >= 0xFF) + { + /* Infinity. */ + exp = 0x7F; + mantissa = 0; + } + else if (exp < 0) + { + /* No denormalized numbers. */ + exp = 0; + mantissa = 0; + } + } + mantissa >>= 29; + return (sign << 31) | (exp << 23) | mantissa; +} +#endif /* BFD_HOST_64_BIT */ + enum lit_type { CONST_THUMB, @@ -7741,6 +7807,8 @@ enum lit_type CONST_VEC }; +static void do_vfp_nsyn_opcode (const char *); + /* inst.reloc.exp describes an "=expr" load pseudo-operation. Determine whether it can be performed with a move instruction; if it can, convert inst.instruction to that move instruction and @@ -7756,7 +7824,6 @@ move_or_literal_pool (int i, enum lit_type t, bfd_boolean mode_3) unsigned long tbit; bfd_boolean thumb_p = (t == CONST_THUMB); bfd_boolean arm_p = (t == CONST_ARM); - bfd_boolean vec64_p = (t == CONST_VEC) && !inst.operands[i].issingle; if (thumb_p) tbit = (inst.instruction > 0xffff) ? THUMB2_LOAD_BIT : THUMB_LOAD_BIT; @@ -7768,6 +7835,7 @@ move_or_literal_pool (int i, enum lit_type t, bfd_boolean mode_3) inst.error = _("invalid pseudo operation"); return TRUE; } + if (inst.reloc.exp.X_op != O_constant && inst.reloc.exp.X_op != O_symbol && inst.reloc.exp.X_op != O_big) @@ -7775,77 +7843,204 @@ move_or_literal_pool (int i, enum lit_type t, bfd_boolean mode_3) inst.error = _("constant expression expected"); return TRUE; } - if ((inst.reloc.exp.X_op == O_constant - || inst.reloc.exp.X_op == O_big) - && !inst.operands[i].issingle) + + if (inst.reloc.exp.X_op == O_constant + || inst.reloc.exp.X_op == O_big) { - if (thumb_p && inst.reloc.exp.X_op == O_constant) +#if defined BFD_HOST_64_BIT + bfd_int64_t v; +#else + offsetT v; +#endif + if (inst.reloc.exp.X_op == O_big) { - if (!unified_syntax && (inst.reloc.exp.X_add_number & ~0xFF) == 0) + LITTLENUM_TYPE w[X_PRECISION]; + LITTLENUM_TYPE * l; + + if (inst.reloc.exp.X_add_number == -1) { - /* This can be done with a mov(1) instruction. */ - inst.instruction = T_OPCODE_MOV_I8 | (inst.operands[i].reg << 8); - inst.instruction |= inst.reloc.exp.X_add_number; - return TRUE; + gen_to_words (w, X_PRECISION, E_PRECISION); + l = w; + /* FIXME: Should we check words w[2..5] ? */ } + else + l = generic_bignum; + +#if defined BFD_HOST_64_BIT + v = + ((((((((bfd_int64_t) l[3] & LITTLENUM_MASK) + << LITTLENUM_NUMBER_OF_BITS) + | ((bfd_int64_t) l[2] & LITTLENUM_MASK)) + << LITTLENUM_NUMBER_OF_BITS) + | ((bfd_int64_t) l[1] & LITTLENUM_MASK)) + << LITTLENUM_NUMBER_OF_BITS) + | ((bfd_int64_t) l[0] & LITTLENUM_MASK)); +#else + v = ((l[1] & LITTLENUM_MASK) << LITTLENUM_NUMBER_OF_BITS) + | (l[0] & LITTLENUM_MASK); +#endif } - else if (arm_p && inst.reloc.exp.X_op == O_constant) + else + v = inst.reloc.exp.X_add_number; + + if (!inst.operands[i].issingle) { - int value = encode_arm_immediate (inst.reloc.exp.X_add_number); - if (value != FAIL) + if (thumb_p) { - /* This can be done with a mov instruction. */ - inst.instruction &= LITERAL_MASK; - inst.instruction |= INST_IMMEDIATE | (OPCODE_MOV << DATA_OP_SHIFT); - inst.instruction |= value & 0xfff; - return TRUE; + if ((v & ~0xFF) == 0) + { + /* This can be done with a mov(1) instruction. */ + inst.instruction = T_OPCODE_MOV_I8 | (inst.operands[i].reg << 8); + inst.instruction |= v; + return TRUE; + } + + if (ARM_CPU_HAS_FEATURE (cpu_variant, arm_arch_t2) + && ARM_CPU_HAS_FEATURE (cpu_variant, arm_ext_v6t2)) + { + /* Check if on thumb2 it can be done with a mov.w or mvn.w instruction. */ + unsigned int newimm; + bfd_boolean isNegated; + + newimm = encode_thumb32_immediate (v); + if (newimm != (unsigned int) FAIL) + isNegated = FALSE; + else + { + newimm = encode_thumb32_immediate (~ v); + if (newimm != (unsigned int) FAIL) + isNegated = TRUE; + } + + if (newimm != (unsigned int) FAIL) + { + inst.instruction = 0xf04f0000 | (inst.operands[i].reg << 8); + inst.instruction |= (isNegated?0x200000:0); + inst.instruction |= (newimm & 0x800) << 15; + inst.instruction |= (newimm & 0x700) << 4; + inst.instruction |= (newimm & 0x0ff); + return TRUE; + } + else if ((v & ~0xFFFF) == 0 || (v & ~0xFFFF0000) == 0) + { + /* The number may be loaded with a movw/movt instruction. */ + int imm; + + if ((inst.reloc.exp.X_add_number & ~0xFFFF) == 0) + { + inst.instruction= 0xf2400000; + imm = v; + } + else + { + inst.instruction = 0xf2c00000; + imm = v >> 16; + } + + inst.instruction |= (inst.operands[i].reg << 8); + inst.instruction |= (imm & 0xf000) << 4; + inst.instruction |= (imm & 0x0800) << 15; + inst.instruction |= (imm & 0x0700) << 4; + inst.instruction |= (imm & 0x00ff); + return TRUE; + } + } } + else if (arm_p) + { + int value = encode_arm_immediate (v); - value = encode_arm_immediate (~inst.reloc.exp.X_add_number); - if (value != FAIL) + if (value != FAIL) + { + /* This can be done with a mov instruction. */ + inst.instruction &= LITERAL_MASK; + inst.instruction |= INST_IMMEDIATE | (OPCODE_MOV << DATA_OP_SHIFT); + inst.instruction |= value & 0xfff; + return TRUE; + } + + value = encode_arm_immediate (~ v); + if (value != FAIL) + { + /* This can be done with a mvn instruction. */ + inst.instruction &= LITERAL_MASK; + inst.instruction |= INST_IMMEDIATE | (OPCODE_MVN << DATA_OP_SHIFT); + inst.instruction |= value & 0xfff; + return TRUE; + } + } + else if (t == CONST_VEC) { - /* This can be done with a mvn instruction. */ - inst.instruction &= LITERAL_MASK; - inst.instruction |= INST_IMMEDIATE | (OPCODE_MVN << DATA_OP_SHIFT); - inst.instruction |= value & 0xfff; - return TRUE; + int op = 0; + unsigned immbits = 0; + unsigned immlo = inst.operands[1].imm; + unsigned immhi = inst.operands[1].regisimm + ? inst.operands[1].reg + : inst.reloc.exp.X_unsigned + ? 0 + : ((bfd_int64_t)((int) immlo)) >> 32; + int cmode = neon_cmode_for_move_imm (immlo, immhi, FALSE, &immbits, + &op, 64, NT_invtype); + + if (cmode == FAIL) + { + neon_invert_size (&immlo, &immhi, 64); + op = !op; + cmode = neon_cmode_for_move_imm (immlo, immhi, FALSE, &immbits, + &op, 64, NT_invtype); + } + + if (cmode != FAIL) + { + inst.instruction = (inst.instruction & VLDR_VMOV_SAME) + | (1 << 23) + | (cmode << 8) + | (op << 5) + | (1 << 4); + + /* Fill other bits in vmov encoding for both thumb and arm. */ + if (thumb_mode) + inst.instruction |= (0x7 << 29) | (0xF << 24); + else + inst.instruction |= (0xF << 28) | (0x1 << 25); + neon_write_immbits (immbits); + return TRUE; + } } } - else if (vec64_p) - { - int op = 0; - unsigned immbits = 0; - unsigned immlo = inst.operands[1].imm; - unsigned immhi = inst.operands[1].regisimm - ? inst.operands[1].reg - : inst.reloc.exp.X_unsigned - ? 0 - : ((bfd_int64_t)((int) immlo)) >> 32; - int cmode = neon_cmode_for_move_imm (immlo, immhi, FALSE, &immbits, - &op, 64, NT_invtype); - if (cmode == FAIL) + if (t == CONST_VEC) + { + /* Check if vldr Rx, =constant could be optimized to vmov Rx, #constant. */ + if (inst.operands[i].issingle + && is_quarter_float (inst.operands[1].imm) + && ARM_CPU_HAS_FEATURE (cpu_variant, fpu_vfp_ext_v3xd)) { - neon_invert_size (&immlo, &immhi, 64); - op = !op; - cmode = neon_cmode_for_move_imm (immlo, immhi, FALSE, &immbits, - &op, 64, NT_invtype); + inst.operands[1].imm = + neon_qfloat_bits (v); + do_vfp_nsyn_opcode ("fconsts"); + return TRUE; } - if (cmode != FAIL) + + /* If our host does not support a 64-bit type then we cannot perform + the following optimization. This mean that there will be a + discrepancy between the output produced by an assembler built for + a 32-bit-only host and the output produced from a 64-bit host, but + this cannot be helped. */ +#if defined BFD_HOST_64_BIT + else if (!inst.operands[1].issingle + && ARM_CPU_HAS_FEATURE (cpu_variant, fpu_vfp_ext_v3)) { - inst.instruction = (inst.instruction & VLDR_VMOV_SAME) - | (1 << 23) - | (cmode << 8) - | (op << 5) - | (1 << 4); - /* Fill other bits in vmov encoding for both thumb and arm. */ - if (thumb_mode) - inst.instruction |= (0x7 << 29) | (0xF << 24); - else - inst.instruction |= (0xF << 28) | (0x1 << 25); - neon_write_immbits (immbits); - return TRUE; + if (is_double_a_single (v) + && is_quarter_float (double_to_single (v))) + { + inst.operands[1].imm = + neon_qfloat_bits (double_to_single (v)); + do_vfp_nsyn_opcode ("fconstd"); + return TRUE; + } } +#endif } } @@ -7878,7 +8073,12 @@ encode_arm_cp_address (int i, int wb_ok, int unind_ok, int reloc_override) { if (!inst.operands[i].isreg) { - gas_assert (inst.operands[0].isvec); + /* PR 18256 */ + if (! inst.operands[0].isvec) + { + inst.error = _("invalid co-processor operand"); + return FAIL; + } if (move_or_literal_pool (0, CONST_VEC, /*mode_3=*/FALSE)) return SUCCESS; } @@ -8331,19 +8531,19 @@ struct deprecated_coproc_regs_s static struct deprecated_coproc_regs_s deprecated_coproc_regs[] = { {15, 0, 7, 10, 5, /* CP15DMB. */ - ARM_FEATURE (ARM_EXT_V8, 0), ARM_FEATURE (0, 0), + ARM_FEATURE_CORE_LOW (ARM_EXT_V8), ARM_ARCH_NONE, DEPR_ACCESS_V8, NULL}, {15, 0, 7, 10, 4, /* CP15DSB. */ - ARM_FEATURE (ARM_EXT_V8, 0), ARM_FEATURE (0, 0), + ARM_FEATURE_CORE_LOW (ARM_EXT_V8), ARM_ARCH_NONE, DEPR_ACCESS_V8, NULL}, {15, 0, 7, 5, 4, /* CP15ISB. */ - ARM_FEATURE (ARM_EXT_V8, 0), ARM_FEATURE (0, 0), + ARM_FEATURE_CORE_LOW (ARM_EXT_V8), ARM_ARCH_NONE, DEPR_ACCESS_V8, NULL}, {14, 6, 1, 0, 0, /* TEEHBR. */ - ARM_FEATURE (ARM_EXT_V8, 0), ARM_FEATURE (0, 0), + ARM_FEATURE_CORE_LOW (ARM_EXT_V8), ARM_ARCH_NONE, DEPR_ACCESS_V8, NULL}, {14, 6, 0, 0, 0, /* TEECR. */ - ARM_FEATURE (ARM_EXT_V8, 0), ARM_FEATURE (0, 0), + ARM_FEATURE_CORE_LOW (ARM_EXT_V8), ARM_ARCH_NONE, DEPR_ACCESS_V8, NULL}, }; @@ -8778,8 +8978,6 @@ do_mov16 (void) } } -static void do_vfp_nsyn_opcode (const char *); - static int do_vfp_nsyn_mrs (void) { @@ -9036,6 +9234,8 @@ do_pli (void) static void do_push_pop (void) { + constraint (inst.operands[0].writeback, + _("push/pop do not support {reglist}^")); inst.operands[1] = inst.operands[0]; memset (&inst.operands[0], 0, sizeof inst.operands[0]); inst.operands[0].isreg = 1; @@ -9161,6 +9361,24 @@ do_swi (void) inst.reloc.pc_rel = 0; } +static void +do_setpan (void) +{ + constraint (!ARM_CPU_HAS_FEATURE (cpu_variant, arm_ext_pan), + _("selected processor does not support SETPAN instruction")); + + inst.instruction |= ((inst.operands[0].imm & 1) << 9); +} + +static void +do_t_setpan (void) +{ + constraint (!ARM_CPU_HAS_FEATURE (cpu_variant, arm_ext_pan), + _("selected processor does not support SETPAN instruction")); + + inst.instruction |= (inst.operands[0].imm << 3); +} + /* ARM V5E (El Segundo) signed-multiply-accumulate (argument parse) SMLAxy{cond} Rd,Rm,Rs,Rn SMLAWy{cond} Rd,Rm,Rs,Rn @@ -11918,7 +12136,8 @@ do_t_mrs (void) /* PR gas/12698: The constraint is only applied for m_profile. If the user has specified -march=all, we want to ignore it as we are building for any CPU type, including non-m variants. */ - bfd_boolean m_profile = selected_cpu.core != arm_arch_any.core; + bfd_boolean m_profile = + !ARM_FEATURE_CORE_EQUAL (selected_cpu, arm_arch_any); constraint ((flags != 0) && m_profile, _("selected processor does " "not support requested special purpose register")); } @@ -11958,7 +12177,8 @@ do_t_msr (void) /* PR gas/12698: The constraint is only applied for m_profile. If the user has specified -march=all, we want to ignore it as we are building for any CPU type, including non-m variants. */ - bfd_boolean m_profile = selected_cpu.core != arm_arch_any.core; + bfd_boolean m_profile = + !ARM_FEATURE_CORE_EQUAL (selected_cpu, arm_arch_any); constraint (((ARM_CPU_HAS_FEATURE (selected_cpu, arm_ext_v6_dsp) && (bits & ~(PSR_s | PSR_f)) != 0) || (!ARM_CPU_HAS_FEATURE (selected_cpu, arm_ext_v6_dsp) @@ -12875,6 +13095,8 @@ struct neon_tab_entry X(vqdmull, 0x0800d00, N_INV, 0x0800b40), \ X(vqdmulh, 0x0000b00, N_INV, 0x0800c40), \ X(vqrdmulh, 0x1000b00, N_INV, 0x0800d40), \ + X(vqrdmlah, 0x3000b10, N_INV, 0x0800e40), \ + X(vqrdmlsh, 0x3000c10, N_INV, 0x0800f40), \ X(vshl, 0x0000400, N_INV, 0x0800510), \ X(vqshl, 0x0000410, N_INV, 0x0800710), \ X(vand, 0x0000110, N_INV, 0x0800030), \ @@ -18205,8 +18427,8 @@ static const struct asm_cond conds[] = }; #define UL_BARRIER(L,U,CODE,FEAT) \ - { L, CODE, ARM_FEATURE (FEAT, 0) }, \ - { U, CODE, ARM_FEATURE (FEAT, 0) } + { L, CODE, ARM_FEATURE_CORE_LOW (FEAT) }, \ + { U, CODE, ARM_FEATURE_CORE_LOW (FEAT) } static struct asm_barrier_opt barrier_opt_names[] = { @@ -18862,6 +19084,13 @@ static const struct asm_opcode insns[] = TCE("hvc", 1400070, f7e08000, 1, (EXPi), hvc, t_hvc), TCE("eret", 160006e, f3de8f00, 0, (), noargs, noargs), +#undef ARM_VARIANT +#define ARM_VARIANT & arm_ext_pan +#undef THUMB_VARIANT +#define THUMB_VARIANT & arm_ext_pan + + TUF("setpan", 1100000, b610, 1, (I7), setpan, t_setpan), + #undef ARM_VARIANT #define ARM_VARIANT & arm_ext_v6t2 #undef THUMB_VARIANT @@ -19767,6 +19996,11 @@ static const struct asm_opcode insns[] = NUF(vrecpsq, 0000f10, 3, (RNQ, oRNQ, RNQ), neon_step), NUF(vrsqrts, 0200f10, 3, (RNDQ, oRNDQ, RNDQ), neon_step), NUF(vrsqrtsq, 0200f10, 3, (RNQ, oRNQ, RNQ), neon_step), + /* ARM v8.1 extension. */ + nUF(vqrdmlah, _vqrdmlah, 3, (RNDQ, oRNDQ, RNDQ_RNSC), neon_qdmulh), + nUF(vqrdmlahq, _vqrdmlah, 3, (RNQ, oRNQ, RNDQ_RNSC), neon_qdmulh), + nUF(vqrdmlsh, _vqrdmlsh, 3, (RNDQ, oRNDQ, RNDQ_RNSC), neon_qdmulh), + nUF(vqrdmlshq, _vqrdmlsh, 3, (RNQ, oRNQ, RNDQ_RNSC), neon_qdmulh), /* Two address, int/float. Types S8 S16 S32 F32. */ NUF(vabsq, 1b10300, 2, (RNQ, RNQ), neon_abs_neg), @@ -21008,27 +21242,29 @@ arm_init_frag (fragS * fragP, int max_chars ATTRIBUTE_UNUSED) void arm_init_frag (fragS * fragP, int max_chars) { + int frag_thumb_mode; + /* If the current ARM vs THUMB mode has not already been recorded into this frag then do so now. */ if ((fragP->tc_frag_data.thumb_mode & MODE_RECORDED) == 0) - { - fragP->tc_frag_data.thumb_mode = thumb_mode | MODE_RECORDED; + fragP->tc_frag_data.thumb_mode = thumb_mode | MODE_RECORDED; - /* Record a mapping symbol for alignment frags. We will delete this - later if the alignment ends up empty. */ - switch (fragP->fr_type) - { - case rs_align: - case rs_align_test: - case rs_fill: - mapping_state_2 (MAP_DATA, max_chars); - break; - case rs_align_code: - mapping_state_2 (thumb_mode ? MAP_THUMB : MAP_ARM, max_chars); - break; - default: - break; - } + frag_thumb_mode = fragP->tc_frag_data.thumb_mode ^ MODE_RECORDED; + + /* Record a mapping symbol for alignment frags. We will delete this + later if the alignment ends up empty. */ + switch (fragP->fr_type) + { + case rs_align: + case rs_align_test: + case rs_fill: + mapping_state_2 (MAP_DATA, max_chars); + break; + case rs_align_code: + mapping_state_2 (frag_thumb_mode ? MAP_THUMB : MAP_ARM, max_chars); + break; + default: + break; } } @@ -21603,6 +21839,51 @@ md_pcrel_from_section (fixS * fixP, segT seg) } } +static bfd_boolean flag_warn_syms = TRUE; + +bfd_boolean +arm_tc_equal_in_insn (int c ATTRIBUTE_UNUSED, char * name) +{ + /* PR 18347 - Warn if the user attempts to create a symbol with the same + name as an ARM instruction. Whilst strictly speaking it is allowed, it + does mean that the resulting code might be very confusing to the reader. + Also this warning can be triggered if the user omits an operand before + an immediate address, eg: + + LDR =foo + + GAS treats this as an assignment of the value of the symbol foo to a + symbol LDR, and so (without this code) it will not issue any kind of + warning or error message. + + Note - ARM instructions are case-insensitive but the strings in the hash + table are all stored in lower case, so we must first ensure that name is + lower case too. */ + if (flag_warn_syms && arm_ops_hsh) + { + char * nbuf = strdup (name); + char * p; + + for (p = nbuf; *p; p++) + *p = TOLOWER (*p); + if (hash_find (arm_ops_hsh, nbuf) != NULL) + { + static struct hash_control * already_warned = NULL; + + if (already_warned == NULL) + already_warned = hash_new (); + /* Only warn about the symbol once. To keep the code + simple we let hash_insert do the lookup for us. */ + if (hash_insert (already_warned, name, NULL) == NULL) + as_warn (_("[-mwarn-syms]: Assignment makes a symbol match an ARM instruction: %s"), name); + } + else + free (nbuf); + } + + return FALSE; +} + /* Under ELF we need to default _GLOBAL_OFFSET_TABLE. Otherwise we have no need to default values of symbols. */ @@ -22869,7 +23150,7 @@ md_apply_fix (fixS * fixP, if (rd == REG_SP) { - if (value & ~0x1fc) + if (value & ~0x1fc) as_bad_where (fixP->fx_file, fixP->fx_line, _("invalid immediate for stack address calculation")); newval = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST; @@ -22877,10 +23158,49 @@ md_apply_fix (fixS * fixP, } else if (rs == REG_PC || rs == REG_SP) { + /* PR gas/18541. If the addition is for a defined symbol + within range of an ADR instruction then accept it. */ + if (subtract + && value == 4 + && fixP->fx_addsy != NULL) + { + subtract = 0; + + if (! S_IS_DEFINED (fixP->fx_addsy) + || S_GET_SEGMENT (fixP->fx_addsy) != seg + || S_IS_WEAK (fixP->fx_addsy)) + { + as_bad_where (fixP->fx_file, fixP->fx_line, + _("address calculation needs a strongly defined nearby symbol")); + } + else + { + offsetT v = fixP->fx_where + fixP->fx_frag->fr_address; + + /* Round up to the next 4-byte boundary. */ + if (v & 3) + v = (v + 3) & ~ 3; + else + v += 4; + v = S_GET_VALUE (fixP->fx_addsy) - v; + + if (v & ~0x3fc) + { + as_bad_where (fixP->fx_file, fixP->fx_line, + _("symbol too far away")); + } + else + { + fixP->fx_done = 1; + value = v; + } + } + } + if (subtract || value & ~0x3fc) as_bad_where (fixP->fx_file, fixP->fx_line, _("invalid immediate for address calculation (value = 0x%08lX)"), - (unsigned long) value); + (unsigned long) (subtract ? - value : value)); newval = (rs == REG_PC ? T_OPCODE_ADD_PC : T_OPCODE_ADD_SP); newval |= rd << 8; newval |= value >> 2; @@ -23283,7 +23603,6 @@ tc_gen_reloc (asection *section, fixS *fixp) case BFD_RELOC_ARM_SBREL32: case BFD_RELOC_ARM_PREL31: case BFD_RELOC_ARM_TARGET2: - case BFD_RELOC_ARM_TLS_LE32: case BFD_RELOC_ARM_TLS_LDO32: case BFD_RELOC_ARM_PCREL_CALL: case BFD_RELOC_ARM_PCREL_JUMP: @@ -23321,6 +23640,7 @@ tc_gen_reloc (asection *section, fixS *fixp) case BFD_RELOC_ARM_TLS_GOTDESC: case BFD_RELOC_ARM_TLS_GD32: + case BFD_RELOC_ARM_TLS_LE32: case BFD_RELOC_ARM_TLS_IE32: case BFD_RELOC_ARM_TLS_LDM32: /* BFD will include the symbol's address in the addend. @@ -24096,6 +24416,7 @@ md_begin (void) -mthumb-interwork Code supports ARM/Thumb interworking -m[no-]warn-deprecated Warn about deprecated features + -m[no-]warn-syms Warn when symbols match instructions For now we will also provide support for: @@ -24164,6 +24485,7 @@ struct option md_longopts[] = {NULL, no_argument, NULL, 0} }; + size_t md_longopts_size = sizeof (md_longopts); struct arm_option_table @@ -24198,6 +24520,8 @@ struct arm_option_table arm_opts[] = {"mwarn-deprecated", NULL, &warn_on_deprecated, 1, NULL}, {"mno-warn-deprecated", N_("do not warn on use of deprecated feature"), &warn_on_deprecated, 0, NULL}, + {"mwarn-syms", N_("warn about symbols that match instruction names [default]"), (int *) (& flag_warn_syms), TRUE, NULL}, + {"mno-warn-syms", N_("disable warnings about symobls that match instructions"), (int *) (& flag_warn_syms), FALSE, NULL}, {NULL, NULL, NULL, 0, NULL} }; @@ -24431,11 +24755,11 @@ static const struct arm_cpu_option_table arm_cpus[] = ARM_CPU_OPT ("cortex-a7", ARM_ARCH_V7VE, FPU_ARCH_NEON_VFP_V4, "Cortex-A7"), ARM_CPU_OPT ("cortex-a8", ARM_ARCH_V7A_SEC, - ARM_FEATURE (0, FPU_VFP_V3 + ARM_FEATURE_COPROC (FPU_VFP_V3 | FPU_NEON_EXT_V1), "Cortex-A8"), ARM_CPU_OPT ("cortex-a9", ARM_ARCH_V7A_MP_SEC, - ARM_FEATURE (0, FPU_VFP_V3 + ARM_FEATURE_COPROC (FPU_VFP_V3 | FPU_NEON_EXT_V1), "Cortex-A9"), ARM_CPU_OPT ("cortex-a12", ARM_ARCH_V7VE, FPU_ARCH_NEON_VFP_V4, @@ -24464,6 +24788,9 @@ static const struct arm_cpu_option_table arm_cpus[] = ARM_CPU_OPT ("cortex-m1", ARM_ARCH_V6SM, FPU_NONE, "Cortex-M1"), ARM_CPU_OPT ("cortex-m0", ARM_ARCH_V6SM, FPU_NONE, "Cortex-M0"), ARM_CPU_OPT ("cortex-m0plus", ARM_ARCH_V6SM, FPU_NONE, "Cortex-M0+"), + ARM_CPU_OPT ("exynos-m1", ARM_ARCH_V8A, FPU_ARCH_CRYPTO_NEON_VFP_ARMV8, + "Samsung " \ + "Exynos M1"), /* ??? XSCALE is really an architecture. */ ARM_CPU_OPT ("xscale", ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2, NULL), /* ??? iwmmxt is not a processor. */ @@ -24471,13 +24798,14 @@ static const struct arm_cpu_option_table arm_cpus[] = ARM_CPU_OPT ("iwmmxt2", ARM_ARCH_IWMMXT2,FPU_ARCH_VFP_V2, NULL), ARM_CPU_OPT ("i80200", ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2, NULL), /* Maverick */ - ARM_CPU_OPT ("ep9312", ARM_FEATURE (ARM_AEXT_V4T, ARM_CEXT_MAVERICK), + ARM_CPU_OPT ("ep9312", ARM_FEATURE_LOW (ARM_AEXT_V4T, ARM_CEXT_MAVERICK), FPU_ARCH_MAVERICK, "ARM920T"), /* Marvell processors. */ - ARM_CPU_OPT ("marvell-pj4", ARM_FEATURE (ARM_AEXT_V7A | ARM_EXT_MP | ARM_EXT_SEC, 0), + ARM_CPU_OPT ("marvell-pj4", ARM_FEATURE_CORE_LOW (ARM_AEXT_V7A | ARM_EXT_MP + | ARM_EXT_SEC), FPU_ARCH_VFP_V3D16, NULL), - ARM_CPU_OPT ("marvell-whitney", ARM_FEATURE (ARM_AEXT_V7A | ARM_EXT_MP - | ARM_EXT_SEC, 0), + ARM_CPU_OPT ("marvell-whitney", ARM_FEATURE_CORE_LOW (ARM_AEXT_V7A | ARM_EXT_MP + | ARM_EXT_SEC), FPU_ARCH_NEON_VFP_V4, NULL), /* APM X-Gene family. */ ARM_CPU_OPT ("xgene1", ARM_ARCH_V8A, FPU_ARCH_CRYPTO_NEON_VFP_ARMV8, @@ -24542,6 +24870,7 @@ static const struct arm_arch_option_table arm_archs[] = ARM_ARCH_OPT ("armv7-m", ARM_ARCH_V7M, FPU_ARCH_VFP), ARM_ARCH_OPT ("armv7e-m", ARM_ARCH_V7EM, FPU_ARCH_VFP), ARM_ARCH_OPT ("armv8-a", ARM_ARCH_V8A, FPU_ARCH_VFP), + ARM_ARCH_OPT ("armv8.1-a", ARM_ARCH_V8_1A, FPU_ARCH_VFP), ARM_ARCH_OPT ("xscale", ARM_ARCH_XSCALE, FPU_ARCH_VFP), ARM_ARCH_OPT ("iwmmxt", ARM_ARCH_IWMMXT, FPU_ARCH_VFP), ARM_ARCH_OPT ("iwmmxt2", ARM_ARCH_IWMMXT2,FPU_ARCH_VFP), @@ -24564,40 +24893,46 @@ struct arm_option_extension_value_table #define ARM_EXT_OPT(N, M, C, AA) { N, sizeof (N) - 1, M, C, AA } static const struct arm_option_extension_value_table arm_extensions[] = { - ARM_EXT_OPT ("crc", ARCH_CRC_ARMV8, ARM_FEATURE (0, CRC_EXT_ARMV8), - ARM_FEATURE (ARM_EXT_V8, 0)), + ARM_EXT_OPT ("crc", ARCH_CRC_ARMV8, ARM_FEATURE_COPROC (CRC_EXT_ARMV8), + ARM_FEATURE_CORE_LOW (ARM_EXT_V8)), ARM_EXT_OPT ("crypto", FPU_ARCH_CRYPTO_NEON_VFP_ARMV8, - ARM_FEATURE (0, FPU_CRYPTO_ARMV8), - ARM_FEATURE (ARM_EXT_V8, 0)), - ARM_EXT_OPT ("fp", FPU_ARCH_VFP_ARMV8, ARM_FEATURE (0, FPU_VFP_ARMV8), - ARM_FEATURE (ARM_EXT_V8, 0)), - ARM_EXT_OPT ("idiv", ARM_FEATURE (ARM_EXT_ADIV | ARM_EXT_DIV, 0), - ARM_FEATURE (ARM_EXT_ADIV | ARM_EXT_DIV, 0), - ARM_FEATURE (ARM_EXT_V7A | ARM_EXT_V7R, 0)), - ARM_EXT_OPT ("iwmmxt",ARM_FEATURE (0, ARM_CEXT_IWMMXT), - ARM_FEATURE (0, ARM_CEXT_IWMMXT), ARM_ANY), - ARM_EXT_OPT ("iwmmxt2", ARM_FEATURE (0, ARM_CEXT_IWMMXT2), - ARM_FEATURE (0, ARM_CEXT_IWMMXT2), ARM_ANY), - ARM_EXT_OPT ("maverick", ARM_FEATURE (0, ARM_CEXT_MAVERICK), - ARM_FEATURE (0, ARM_CEXT_MAVERICK), ARM_ANY), - ARM_EXT_OPT ("mp", ARM_FEATURE (ARM_EXT_MP, 0), - ARM_FEATURE (ARM_EXT_MP, 0), - ARM_FEATURE (ARM_EXT_V7A | ARM_EXT_V7R, 0)), + ARM_FEATURE_COPROC (FPU_CRYPTO_ARMV8), + ARM_FEATURE_CORE_LOW (ARM_EXT_V8)), + ARM_EXT_OPT ("fp", FPU_ARCH_VFP_ARMV8, ARM_FEATURE_COPROC (FPU_VFP_ARMV8), + ARM_FEATURE_CORE_LOW (ARM_EXT_V8)), + ARM_EXT_OPT ("idiv", ARM_FEATURE_CORE_LOW (ARM_EXT_ADIV | ARM_EXT_DIV), + ARM_FEATURE_CORE_LOW (ARM_EXT_ADIV | ARM_EXT_DIV), + ARM_FEATURE_CORE_LOW (ARM_EXT_V7A | ARM_EXT_V7R)), + ARM_EXT_OPT ("iwmmxt",ARM_FEATURE_COPROC (ARM_CEXT_IWMMXT), + ARM_FEATURE_COPROC (ARM_CEXT_IWMMXT), ARM_ANY), + ARM_EXT_OPT ("iwmmxt2", ARM_FEATURE_COPROC (ARM_CEXT_IWMMXT2), + ARM_FEATURE_COPROC (ARM_CEXT_IWMMXT2), ARM_ANY), + ARM_EXT_OPT ("maverick", ARM_FEATURE_COPROC (ARM_CEXT_MAVERICK), + ARM_FEATURE_COPROC (ARM_CEXT_MAVERICK), ARM_ANY), + ARM_EXT_OPT ("mp", ARM_FEATURE_CORE_LOW (ARM_EXT_MP), + ARM_FEATURE_CORE_LOW (ARM_EXT_MP), + ARM_FEATURE_CORE_LOW (ARM_EXT_V7A | ARM_EXT_V7R)), ARM_EXT_OPT ("simd", FPU_ARCH_NEON_VFP_ARMV8, - ARM_FEATURE(0, FPU_NEON_ARMV8), - ARM_FEATURE (ARM_EXT_V8, 0)), - ARM_EXT_OPT ("os", ARM_FEATURE (ARM_EXT_OS, 0), - ARM_FEATURE (ARM_EXT_OS, 0), - ARM_FEATURE (ARM_EXT_V6M, 0)), - ARM_EXT_OPT ("sec", ARM_FEATURE (ARM_EXT_SEC, 0), - ARM_FEATURE (ARM_EXT_SEC, 0), - ARM_FEATURE (ARM_EXT_V6K | ARM_EXT_V7A, 0)), - ARM_EXT_OPT ("virt", ARM_FEATURE (ARM_EXT_VIRT | ARM_EXT_ADIV - | ARM_EXT_DIV, 0), - ARM_FEATURE (ARM_EXT_VIRT, 0), - ARM_FEATURE (ARM_EXT_V7A, 0)), - ARM_EXT_OPT ("xscale",ARM_FEATURE (0, ARM_CEXT_XSCALE), - ARM_FEATURE (0, ARM_CEXT_XSCALE), ARM_ANY), + ARM_FEATURE_COPROC (FPU_NEON_ARMV8), + ARM_FEATURE_CORE_LOW (ARM_EXT_V8)), + ARM_EXT_OPT ("os", ARM_FEATURE_CORE_LOW (ARM_EXT_OS), + ARM_FEATURE_CORE_LOW (ARM_EXT_OS), + ARM_FEATURE_CORE_LOW (ARM_EXT_V6M)), + ARM_EXT_OPT ("pan", ARM_FEATURE_CORE_HIGH (ARM_EXT2_PAN), + ARM_FEATURE (ARM_EXT_V8, ARM_EXT2_PAN, 0), + ARM_FEATURE_CORE_LOW (ARM_EXT_V8)), + ARM_EXT_OPT ("sec", ARM_FEATURE_CORE_LOW (ARM_EXT_SEC), + ARM_FEATURE_CORE_LOW (ARM_EXT_SEC), + ARM_FEATURE_CORE_LOW (ARM_EXT_V6K | ARM_EXT_V7A)), + ARM_EXT_OPT ("virt", ARM_FEATURE_CORE_LOW (ARM_EXT_VIRT | ARM_EXT_ADIV + | ARM_EXT_DIV), + ARM_FEATURE_CORE_LOW (ARM_EXT_VIRT), + ARM_FEATURE_CORE_LOW (ARM_EXT_V7A)), + ARM_EXT_OPT ("rdma", FPU_ARCH_NEON_VFP_ARMV8, + ARM_FEATURE_COPROC (FPU_NEON_ARMV8 | FPU_NEON_EXT_RDMA), + ARM_FEATURE_CORE_LOW (ARM_EXT_V8)), + ARM_EXT_OPT ("xscale",ARM_FEATURE_COPROC (ARM_CEXT_XSCALE), + ARM_FEATURE_COPROC (ARM_CEXT_XSCALE), ARM_ANY), { NULL, 0, ARM_ARCH_NONE, ARM_ARCH_NONE, ARM_ARCH_NONE } }; #undef ARM_EXT_OPT @@ -24653,6 +24988,7 @@ static const struct arm_option_fpu_value_table arm_fpus[] = {"neon-fp-armv8", FPU_ARCH_NEON_VFP_ARMV8}, {"crypto-neon-fp-armv8", FPU_ARCH_CRYPTO_NEON_VFP_ARMV8}, + {"neon-fp-armv8.1", FPU_ARCH_NEON_VFP_ARMV8_1}, {NULL, ARM_ARCH_NONE} }; @@ -25645,14 +25981,18 @@ arm_convert_symbolic_attribute (const char *name) } -/* Apply sym value for relocations only in the case that - they are for local symbols and you have the respective - architectural feature for blx and simple switches. */ +/* Apply sym value for relocations only in the case that they are for + local symbols in the same segment as the fixup and you have the + respective architectural feature for blx and simple switches. */ int -arm_apply_sym_value (struct fix * fixP) +arm_apply_sym_value (struct fix * fixP, segT this_seg) { if (fixP->fx_addsy && ARM_CPU_HAS_FEATURE (selected_cpu, arm_ext_v5t) + /* PR 17444: If the local symbol is in a different section then a reloc + will always be generated for it, so applying the symbol value now + will result in a double offset being stored in the relocation. */ + && (S_GET_SEGMENT (fixP->fx_addsy) == this_seg) && !S_FORCE_RELOC (fixP->fx_addsy, TRUE)) { switch (fixP->fx_r_type) @@ -25666,7 +26006,7 @@ arm_apply_sym_value (struct fix * fixP) case BFD_RELOC_ARM_PCREL_CALL: case BFD_RELOC_THUMB_PCREL_BLX: if (THUMB_IS_FUNC (fixP->fx_addsy)) - return 1; + return 1; break; default: