X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gas%2Fconfig%2Ftc-arm.c;h=a8d9556c05b4f24f28cc266a3d40c6ab70ddc6ab;hb=b126985ec3f922f86a9fa164cc0f443b1aa9e0bb;hp=4d1660331d3de14bc676d30925049864e0908c0d;hpb=589a7d88306628fb332ba0a98ac4a4b3b84b7b2c;p=deliverable%2Fbinutils-gdb.git diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c index 4d1660331d..a8d9556c05 100644 --- a/gas/config/tc-arm.c +++ b/gas/config/tc-arm.c @@ -155,13 +155,15 @@ static const arm_feature_set *object_arch = NULL; /* Constants for known architecture features. */ static const arm_feature_set fpu_default = FPU_DEFAULT; -static const arm_feature_set fpu_arch_vfp_v1 = FPU_ARCH_VFP_V1; +static const arm_feature_set fpu_arch_vfp_v1 ATTRIBUTE_UNUSED = FPU_ARCH_VFP_V1; static const arm_feature_set fpu_arch_vfp_v2 = FPU_ARCH_VFP_V2; -static const arm_feature_set fpu_arch_vfp_v3 = FPU_ARCH_VFP_V3; -static const arm_feature_set fpu_arch_neon_v1 = FPU_ARCH_NEON_V1; +static const arm_feature_set fpu_arch_vfp_v3 ATTRIBUTE_UNUSED = FPU_ARCH_VFP_V3; +static const arm_feature_set fpu_arch_neon_v1 ATTRIBUTE_UNUSED = FPU_ARCH_NEON_V1; static const arm_feature_set fpu_arch_fpa = FPU_ARCH_FPA; static const arm_feature_set fpu_any_hard = FPU_ANY_HARD; +#ifdef OBJ_ELF static const arm_feature_set fpu_arch_maverick = FPU_ARCH_MAVERICK; +#endif static const arm_feature_set fpu_endian_pure = FPU_ARCH_ENDIAN_PURE; #ifdef CPU_DEFAULT @@ -198,10 +200,13 @@ 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); +#ifdef OBJ_ELF static const arm_feature_set arm_ext_v7m = ARM_FEATURE_CORE_LOW (ARM_EXT_V7M); +#endif 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_CORE (ARM_EXT_V6M | ARM_EXT_OS | ARM_EXT_V7M, ARM_EXT2_V8M); + ARM_FEATURE_CORE (ARM_EXT_V6M | ARM_EXT_OS | ARM_EXT_V7M, + ARM_EXT2_V8M | ARM_EXT2_V8M_MAIN); 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); @@ -209,22 +214,34 @@ 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_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); +/* 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); static const arm_feature_set arm_ext_v6t2_v8m = ARM_FEATURE_CORE_HIGH (ARM_EXT2_V6T2_V8M); /* Instructions shared between ARMv8-A and ARMv8-M. */ static const arm_feature_set arm_ext_atomics = ARM_FEATURE_CORE_HIGH (ARM_EXT2_ATOMICS); -static const arm_feature_set arm_ext_v8_2 = - ARM_FEATURE_CORE_HIGH (ARM_EXT2_V8_2A); +#ifdef OBJ_ELF +/* DSP instructions Tag_DSP_extension refers to. */ +static const arm_feature_set arm_ext_dsp = + ARM_FEATURE_CORE_LOW (ARM_EXT_V5E | ARM_EXT_V5ExP | ARM_EXT_V6_DSP); +#endif +static const arm_feature_set arm_ext_ras = + ARM_FEATURE_CORE_HIGH (ARM_EXT2_RAS); /* FP16 instructions. */ static const arm_feature_set arm_ext_fp16 = ARM_FEATURE_CORE_HIGH (ARM_EXT2_FP16_INST); static const arm_feature_set arm_arch_any = ARM_ANY; -static const arm_feature_set arm_arch_full = ARM_FEATURE (-1, -1, -1); +static const arm_feature_set arm_arch_full ATTRIBUTE_UNUSED = 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; +#ifdef OBJ_ELF static const arm_feature_set arm_arch_v6m_only = ARM_ARCH_V6M_ONLY; +#endif static const arm_feature_set arm_cext_iwmmxt2 = ARM_FEATURE_COPROC (ARM_CEXT_IWMMXT2); @@ -254,10 +271,12 @@ 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_COPROC (FPU_NEON_EXT_V1 | FPU_VFP_EXT_V3); +#ifdef OBJ_ELF 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); +#endif 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 = @@ -1988,6 +2007,10 @@ parse_neon_el_struct_list (char **str, unsigned *pbase, const char *const incr_error = _("register stride must be 1 or 2"); const char *const type_error = _("mismatched element/structure types in list"); struct neon_typed_alias firsttype; + firsttype.defined = 0; + firsttype.eltype.type = NT_invtype; + firsttype.eltype.size = -1; + firsttype.index = -1; if (skip_past_char (&ptr, '{') == SUCCESS) leading_brace = 1; @@ -2254,9 +2277,7 @@ create_register_alias (char * newname, char *p) nlen = strlen (newname); #endif - nbuf = xmalloc (nlen + 1); - memcpy (nbuf, newname, nlen); - nbuf[nlen] = '\0'; + nbuf = xmemdup0 (newname, nlen); /* Create aliases under the new name as stated; an all-lowercase version of the new name; and an all-uppercase version of the new @@ -2419,9 +2440,7 @@ create_neon_reg_alias (char *newname, char *p) namelen = strlen (newname); #endif - namebuf = xmalloc (namelen + 1); - strncpy (namebuf, newname, namelen); - namebuf[namelen] = '\0'; + namebuf = xmemdup0 (newname, namelen); insert_neon_reg_alias (namebuf, basereg->number, basetype, typeinfo.defined != 0 ? &typeinfo : NULL); @@ -3275,6 +3294,7 @@ add_to_lit_pool (unsigned int nbytes) } pool->literals[entry] = inst.reloc.exp; + pool->literals[entry].X_op = O_constant; pool->literals[entry].X_add_number = 0; pool->literals[entry++].X_md = (PADDING_SLOT << 8) | 4; pool->next_free_entry += 1; @@ -7990,7 +8010,7 @@ move_or_literal_pool (int i, enum lit_type t, bfd_boolean mode_3) return TRUE; } } - else if (t == CONST_VEC) + else if (t == CONST_VEC && ARM_CPU_HAS_FEATURE (cpu_variant, fpu_neon_ext_v1)) { int op = 0; unsigned immbits = 0; @@ -8173,6 +8193,12 @@ do_rd (void) inst.instruction |= inst.operands[0].reg << 12; } +static void +do_rn (void) +{ + inst.instruction |= inst.operands[0].reg << 16; +} + static void do_rd_rm (void) { @@ -14364,6 +14390,11 @@ static void do_vfp_nsyn_push (void) { nsyn_insert_sp (); + + constraint (inst.operands[1].imm < 1 || inst.operands[1].imm > 16, + _("register list must contain at least 1 and at most 16 " + "registers")); + if (inst.operands[1].issingle) do_vfp_nsyn_opcode ("fstmdbs"); else @@ -14374,6 +14405,11 @@ static void do_vfp_nsyn_pop (void) { nsyn_insert_sp (); + + constraint (inst.operands[1].imm < 1 || inst.operands[1].imm > 16, + _("register list must contain at least 1 and at most 16 " + "registers")); + if (inst.operands[1].issingle) do_vfp_nsyn_opcode ("fldmias"); else @@ -18185,8 +18221,8 @@ known_t32_only_insn (const struct asm_opcode *opcode) || ARM_CPU_HAS_FEATURE (*opcode->tvariant, arm_ext_barrier)) return TRUE; - /* Wide-only instruction added to ARMv8-M. */ - if (ARM_CPU_HAS_FEATURE (*opcode->tvariant, arm_ext_v8m) + /* Wide-only instruction added to ARMv8-M Baseline. */ + if (ARM_CPU_HAS_FEATURE (*opcode->tvariant, arm_ext_v8m_m_only) || ARM_CPU_HAS_FEATURE (*opcode->tvariant, arm_ext_atomics) || ARM_CPU_HAS_FEATURE (*opcode->tvariant, arm_ext_v6t2_v8m) || ARM_CPU_HAS_FEATURE (*opcode->tvariant, arm_ext_div)) @@ -18762,14 +18798,16 @@ static const struct asm_psr v7m_psrs[] = {"ipsr", 5 }, {"IPSR", 5 }, {"epsr", 6 }, {"EPSR", 6 }, {"iepsr", 7 }, {"IEPSR", 7 }, - {"msp", 8 }, {"MSP", 8 }, - {"psp", 9 }, {"PSP", 9 }, + {"msp", 8 }, {"MSP", 8 }, {"msp_s", 8 }, {"MSP_S", 8 }, + {"psp", 9 }, {"PSP", 9 }, {"psp_s", 9 }, {"PSP_S", 9 }, {"primask", 16}, {"PRIMASK", 16}, {"basepri", 17}, {"BASEPRI", 17}, {"basepri_max", 18}, {"BASEPRI_MAX", 18}, {"basepri_max", 18}, {"BASEPRI_MASK", 18}, /* Typo, preserved for backwards compatibility. */ {"faultmask", 19}, {"FAULTMASK", 19}, - {"control", 20}, {"CONTROL", 20} + {"control", 20}, {"CONTROL", 20}, + {"msp_ns", 0x88}, {"MSP_NS", 0x88}, + {"psp_ns", 0x89}, {"PSP_NS", 0x89} }; /* Table of all shift-in-operand names. */ @@ -19695,9 +19733,9 @@ static const struct asm_opcode insns[] = /* ARMv8.2 RAS extension. */ #undef ARM_VARIANT -#define ARM_VARIANT & arm_ext_v8_2 +#define ARM_VARIANT & arm_ext_ras #undef THUMB_VARIANT -#define THUMB_VARIANT & arm_ext_v8_2 +#define THUMB_VARIANT & arm_ext_ras TUE ("esb", 320f010, f3af8010, 0, (), noargs, noargs), #undef ARM_VARIANT @@ -20944,12 +20982,25 @@ static const struct asm_opcode insns[] = cCE("cfmadda32", e200600, 4, (RMAX, RMAX, RMFX, RMFX), mav_quad), cCE("cfmsuba32", e300600, 4, (RMAX, RMAX, RMFX, RMFX), mav_quad), + /* ARMv8-M instructions. */ #undef ARM_VARIANT #define ARM_VARIANT NULL #undef THUMB_VARIANT #define THUMB_VARIANT & arm_ext_v8m + TUE("sg", 0, e97fe97f, 0, (), 0, noargs), + TUE("blxns", 0, 4784, 1, (RRnpc), 0, t_blx), + TUE("bxns", 0, 4704, 1, (RRnpc), 0, t_bx), TUE("tt", 0, e840f000, 2, (RRnpc, RRnpc), 0, tt), TUE("ttt", 0, e840f040, 2, (RRnpc, RRnpc), 0, tt), + TUE("tta", 0, e840f080, 2, (RRnpc, RRnpc), 0, tt), + TUE("ttat", 0, e840f0c0, 2, (RRnpc, RRnpc), 0, tt), + + /* FP for ARMv8-M Mainline. Enabled for ARMv8-M Mainline because the + instructions behave as nop if no VFP is present. */ +#undef THUMB_VARIANT +#define THUMB_VARIANT & arm_ext_v8m_main + TUEc("vlldm", 0, ec300a00, 1, (RRnpc), rn), + TUEc("vlstm", 0, ec200a00, 1, (RRnpc), rn), }; #undef ARM_VARIANT #undef THUMB_VARIANT @@ -21866,10 +21917,7 @@ start_unwind_section (const segT text_seg, int idx) const char * prefix; const char * prefix_once; const char * group_name; - size_t prefix_len; - size_t text_len; char * sec_name; - size_t sec_name_len; int type; int flags; int linkonce; @@ -21898,13 +21946,7 @@ start_unwind_section (const segT text_seg, int idx) text_name += strlen (".gnu.linkonce.t."); } - prefix_len = strlen (prefix); - text_len = strlen (text_name); - sec_name_len = prefix_len + text_len; - sec_name = (char *) xmalloc (sec_name_len + 1); - memcpy (sec_name, prefix, prefix_len); - memcpy (sec_name + prefix_len, text_name, text_len); - sec_name[prefix_len + text_len] = '\0'; + sec_name = concat (prefix, text_name, (char *) NULL); flags = SHF_ALLOC; linkonce = 0; @@ -24660,8 +24702,8 @@ arm_adjust_symtab (void) /* If it's a .thumb_func, declare it as so, otherwise tag label as .code 16. */ if (THUMB_IS_FUNC (sym)) - elf_sym->internal_elf_sym.st_target_internal - = ST_BRANCH_TO_THUMB; + ARM_SET_SYM_BRANCH_TYPE (elf_sym->internal_elf_sym.st_target_internal, + ST_BRANCH_TO_THUMB); else if (EF_ARM_EABI_VERSION (meabi_flags) < EF_ARM_EABI_VER4) elf_sym->internal_elf_sym.st_info = ELF_ST_INFO (bind, STT_ARM_16BIT); @@ -25310,6 +25352,8 @@ static const struct arm_cpu_option_table arm_cpus[] = "Cortex-A57"), ARM_CPU_OPT ("cortex-a72", ARM_ARCH_V8A, FPU_ARCH_CRYPTO_NEON_VFP_ARMV8, "Cortex-A72"), + ARM_CPU_OPT ("cortex-a73", ARM_ARCH_V8A, FPU_ARCH_CRYPTO_NEON_VFP_ARMV8, + "Cortex-A73"), ARM_CPU_OPT ("cortex-r4", ARM_ARCH_V7R, FPU_NONE, "Cortex-R4"), ARM_CPU_OPT ("cortex-r4f", ARM_ARCH_V7R, FPU_ARCH_VFP_V3D16, "Cortex-R4F"), @@ -25439,12 +25483,16 @@ struct arm_option_extension_value_table size_t name_len; const arm_feature_set merge_value; const arm_feature_set clear_value; - const arm_feature_set allowed_archs; + /* List of architectures for which an extension is available. ARM_ARCH_NONE + indicates that an extension is available for all architectures while + ARM_ANY marks an empty entry. */ + const arm_feature_set allowed_archs[2]; }; /* The following table must be in alphabetical order with a NULL last entry. */ -#define ARM_EXT_OPT(N, M, C, AA) { N, sizeof (N) - 1, M, C, AA } +#define ARM_EXT_OPT(N, M, C, AA) { N, sizeof (N) - 1, M, C, { AA, ARM_ANY } } +#define ARM_EXT_OPT2(N, M, C, AA1, AA2) { N, sizeof (N) - 1, M, C, {AA1, AA2} } static const struct arm_option_extension_value_table arm_extensions[] = { ARM_EXT_OPT ("crc", ARCH_CRC_ARMV8, ARM_FEATURE_COPROC (CRC_EXT_ARMV8), @@ -25452,35 +25500,44 @@ static const struct arm_option_extension_value_table arm_extensions[] = ARM_EXT_OPT ("crypto", FPU_ARCH_CRYPTO_NEON_VFP_ARMV8, ARM_FEATURE_COPROC (FPU_CRYPTO_ARMV8), ARM_FEATURE_CORE_LOW (ARM_EXT_V8)), + ARM_EXT_OPT ("dsp", ARM_FEATURE_CORE_LOW (ARM_EXT_V5ExP | ARM_EXT_V6_DSP), + ARM_FEATURE_CORE_LOW (ARM_EXT_V5ExP | ARM_EXT_V6_DSP), + ARM_FEATURE_CORE (ARM_EXT_V7M, ARM_EXT2_V8M)), ARM_EXT_OPT ("fp", FPU_ARCH_VFP_ARMV8, ARM_FEATURE_COPROC (FPU_VFP_ARMV8), ARM_FEATURE_CORE_LOW (ARM_EXT_V8)), ARM_EXT_OPT ("fp16", ARM_FEATURE_CORE_HIGH (ARM_EXT2_FP16_INST), ARM_FEATURE_CORE_HIGH (ARM_EXT2_FP16_INST), ARM_ARCH_V8_2A), - ARM_EXT_OPT ("idiv", ARM_FEATURE_CORE_LOW (ARM_EXT_ADIV | ARM_EXT_DIV), + ARM_EXT_OPT2 ("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_FEATURE_CORE_LOW (ARM_EXT_V7A), + ARM_FEATURE_CORE_LOW (ARM_EXT_V7R)), ARM_EXT_OPT ("iwmmxt",ARM_FEATURE_COPROC (ARM_CEXT_IWMMXT), - ARM_FEATURE_COPROC (ARM_CEXT_IWMMXT), ARM_ANY), + ARM_FEATURE_COPROC (ARM_CEXT_IWMMXT), ARM_ARCH_NONE), ARM_EXT_OPT ("iwmmxt2", ARM_FEATURE_COPROC (ARM_CEXT_IWMMXT2), - ARM_FEATURE_COPROC (ARM_CEXT_IWMMXT2), ARM_ANY), + ARM_FEATURE_COPROC (ARM_CEXT_IWMMXT2), ARM_ARCH_NONE), 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_COPROC (ARM_CEXT_MAVERICK), ARM_ARCH_NONE), + ARM_EXT_OPT2 ("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_FEATURE_CORE_LOW (ARM_EXT_V7A), + ARM_FEATURE_CORE_LOW (ARM_EXT_V7R)), 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 ("ras", ARM_FEATURE_CORE_HIGH (ARM_EXT2_RAS), + ARM_FEATURE (ARM_EXT_V8, ARM_EXT2_RAS, 0), + ARM_FEATURE_CORE_LOW (ARM_EXT_V8)), ARM_EXT_OPT ("rdma", FPU_ARCH_NEON_VFP_ARMV8_1, ARM_FEATURE_COPROC (FPU_NEON_ARMV8 | FPU_NEON_EXT_RDMA), ARM_FEATURE_CORE_LOW (ARM_EXT_V8)), - ARM_EXT_OPT ("sec", ARM_FEATURE_CORE_LOW (ARM_EXT_SEC), + ARM_EXT_OPT2 ("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_FEATURE_CORE_LOW (ARM_EXT_V6K), + ARM_FEATURE_CORE_LOW (ARM_EXT_V7A)), ARM_EXT_OPT ("simd", FPU_ARCH_NEON_VFP_ARMV8, ARM_FEATURE_COPROC (FPU_NEON_ARMV8), ARM_FEATURE_CORE_LOW (ARM_EXT_V8)), @@ -25489,8 +25546,8 @@ static const struct arm_option_extension_value_table arm_extensions[] = ARM_FEATURE_CORE_LOW (ARM_EXT_VIRT), ARM_FEATURE_CORE_LOW (ARM_EXT_V7A)), 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 } + ARM_FEATURE_COPROC (ARM_CEXT_XSCALE), ARM_ARCH_NONE), + { NULL, 0, ARM_ARCH_NONE, ARM_ARCH_NONE, { ARM_ARCH_NONE, ARM_ARCH_NONE } } }; #undef ARM_EXT_OPT @@ -25596,6 +25653,7 @@ arm_parse_extension (const char *str, const arm_feature_set **opt_p) or removing it (0) and only allowing it to change in the order -1 -> 1 -> 0. */ const struct arm_option_extension_value_table * opt = NULL; + const arm_feature_set arm_any = ARM_ANY; int adding_value = -1; /* Copy the feature set, so that we can modify it. */ @@ -25660,8 +25718,18 @@ arm_parse_extension (const char *str, const arm_feature_set **opt_p) for (; opt->name != NULL; opt++) if (opt->name_len == len && strncmp (opt->name, str, len) == 0) { + int i, nb_allowed_archs = + sizeof (opt->allowed_archs) / sizeof (opt->allowed_archs[0]); /* Check we can apply the extension to this architecture. */ - if (!ARM_CPU_HAS_FEATURE (*ext_set, opt->allowed_archs)) + for (i = 0; i < nb_allowed_archs; i++) + { + /* Empty entry. */ + if (ARM_FEATURE_EQUAL (opt->allowed_archs[i], arm_any)) + continue; + if (ARM_FSET_CPU_SUBSET (opt->allowed_archs[i], *ext_set)) + break; + } + if (i == nb_allowed_archs) { as_bad (_("extension does not apply to the base architecture")); return FALSE; @@ -26075,6 +26143,7 @@ aeabi_set_public_attributes (void) char profile; int virt_sec = 0; int fp16_optional = 0; + arm_feature_set arm_arch = ARM_ARCH_NONE; arm_feature_set flags; arm_feature_set tmp; arm_feature_set arm_arch_v8m_base = ARM_ARCH_V8M_BASE; @@ -26114,6 +26183,7 @@ aeabi_set_public_attributes (void) if (ARM_CPU_HAS_FEATURE (tmp, p->flags)) { arch = p->val; + arm_arch = p->flags; ARM_CLEAR_FEATURE (tmp, tmp, p->flags); } } @@ -26130,18 +26200,27 @@ aeabi_set_public_attributes (void) && !ARM_CPU_HAS_FEATURE (flags, arm_ext_v7a) && ARM_CPU_HAS_FEATURE (flags, arm_ext_v7m) && ARM_CPU_HAS_FEATURE (flags, arm_ext_v6_dsp)) - arch = TAG_CPU_ARCH_V7E_M; + { + arch = TAG_CPU_ARCH_V7E_M; + arm_arch = (arm_feature_set) ARM_ARCH_V7EM; + } ARM_CLEAR_FEATURE (tmp, flags, arm_arch_v8m_base); if (arch == TAG_CPU_ARCH_V8M_BASE && ARM_CPU_HAS_FEATURE (tmp, arm_arch_any)) - arch = TAG_CPU_ARCH_V8M_MAIN; + { + arch = TAG_CPU_ARCH_V8M_MAIN; + arm_arch = (arm_feature_set) ARM_ARCH_V8M_MAIN; + } /* In cpu_arch_ver ARMv8-A is before ARMv8-M for atomics to be detected as coming from ARMv8-A. However, since ARMv8-A has more instructions than ARMv8-M, -march=all must be detected as ARMv8-A. */ if (arch == TAG_CPU_ARCH_V8M_MAIN && ARM_FEATURE_CORE_EQUAL (selected_cpu, arm_arch_any)) - arch = TAG_CPU_ARCH_V8; + { + arch = TAG_CPU_ARCH_V8; + arm_arch = (arm_feature_set) ARM_ARCH_V8A; + } /* Tag_CPU_name. */ if (selected_cpu_name[0]) @@ -26167,7 +26246,7 @@ aeabi_set_public_attributes (void) if (ARM_CPU_HAS_FEATURE (flags, arm_ext_v7a) || ARM_CPU_HAS_FEATURE (flags, arm_ext_v8) || (ARM_CPU_HAS_FEATURE (flags, arm_ext_atomics) - && !ARM_CPU_HAS_FEATURE (flags, arm_ext_v8m))) + && !ARM_CPU_HAS_FEATURE (flags, arm_ext_v8m_m_only))) profile = 'A'; else if (ARM_CPU_HAS_FEATURE (flags, arm_ext_v7r)) profile = 'R'; @@ -26179,6 +26258,17 @@ aeabi_set_public_attributes (void) if (profile != '\0') aeabi_set_attribute_int (Tag_CPU_arch_profile, profile); + /* Tag_DSP_extension. */ + if (ARM_CPU_HAS_FEATURE (flags, arm_ext_dsp)) + { + arm_feature_set ext; + + /* DSP instructions not in architecture. */ + ARM_CLEAR_FEATURE (ext, flags, arm_arch); + if (ARM_CPU_HAS_FEATURE (ext, arm_ext_dsp)) + aeabi_set_attribute_int (Tag_DSP_extension, 1); + } + /* Tag_ARM_ISA_use. */ if (ARM_CPU_HAS_FEATURE (flags, arm_ext_v1) || arch == 0) @@ -26191,7 +26281,7 @@ aeabi_set_public_attributes (void) int thumb_isa_use; if (!ARM_CPU_HAS_FEATURE (flags, arm_ext_v8) - && ARM_CPU_HAS_FEATURE (flags, arm_ext_v8m)) + && ARM_CPU_HAS_FEATURE (flags, arm_ext_v8m_m_only)) thumb_isa_use = 3; else if (ARM_CPU_HAS_FEATURE (flags, arm_arch_t2)) thumb_isa_use = 2; @@ -26417,6 +26507,7 @@ static void s_arm_arch_extension (int ignored ATTRIBUTE_UNUSED) { const struct arm_option_extension_value_table *opt; + const arm_feature_set arm_any = ARM_ANY; char saved_char; char *name; int adding_value = 1; @@ -26437,7 +26528,18 @@ s_arm_arch_extension (int ignored ATTRIBUTE_UNUSED) for (opt = arm_extensions; opt->name != NULL; opt++) if (streq (opt->name, name)) { - if (!ARM_CPU_HAS_FEATURE (*mcpu_cpu_opt, opt->allowed_archs)) + int i, nb_allowed_archs = + sizeof (opt->allowed_archs) / sizeof (opt->allowed_archs[i]); + for (i = 0; i < nb_allowed_archs; i++) + { + /* Empty entry. */ + if (ARM_FEATURE_EQUAL (opt->allowed_archs[i], arm_any)) + continue; + if (ARM_FSET_CPU_SUBSET (opt->allowed_archs[i], *mcpu_cpu_opt)) + break; + } + + if (i == nb_allowed_archs) { as_bad (_("architectural extension `%s' is not allowed for the " "current base architecture"), name); @@ -26562,6 +26664,7 @@ arm_convert_symbolic_attribute (const char *name) T (Tag_conformance), T (Tag_T2EE_use), T (Tag_Virtualization_use), + T (Tag_DSP_extension), /* We deliberately do not include Tag_MPextension_use_legacy. */ #undef T };