X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gas%2Fconfig%2Ftc-arm.c;h=a72b0b08aad2c29ee00b7861cce1a2c403059aab;hb=ceb0a680b14c984392861edbe0c023f3aee7fc7d;hp=4cd27451048d8bbc6ef0f8d834f619d31823b0f3;hpb=bacebabc8edc98e5651097a1d2640ffe81736004;p=deliverable%2Fbinutils-gdb.git diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c index 4cd2745104..a72b0b08aa 100644 --- a/gas/config/tc-arm.c +++ b/gas/config/tc-arm.c @@ -1,7 +1,5 @@ /* tc-arm.c -- Assemble for the ARM - Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, - 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 - Free Software Foundation, Inc. + Copyright 1994-2013 Free Software Foundation, Inc. Contributed by Richard Earnshaw (rwe@pegasus.esprit.ec.org) Modified by David Taylor (dtaylor@armltd.co.uk) Cirrus coprocessor mods by Aldy Hernandez (aldyh@redhat.com) @@ -240,6 +238,8 @@ static const arm_feature_set fpu_neon_ext_armv8 = ARM_FEATURE (0, FPU_NEON_EXT_ARMV8); static const arm_feature_set fpu_crypto_ext_armv8 = ARM_FEATURE (0, FPU_CRYPTO_EXT_ARMV8); +static const arm_feature_set crc_ext_armv8 = + ARM_FEATURE (0, CRC_EXT_ARMV8); static int mfloat_abi_opt = -1; /* Record user cpu selection for object attributes. */ @@ -750,6 +750,7 @@ struct asm_opcode #define BAD_PC_WRITEBACK \ _("cannot use writeback with PC-relative addressing") #define BAD_RANGE _("branch out of range") +#define UNPRED_REG(R) _("using " R " results in unpredictable behaviour") static struct hash_control * arm_ops_hsh; static struct hash_control * arm_cond_hsh; @@ -885,6 +886,9 @@ const char FLT_CHARS[] = "rRsSfFdDxXeEpP"; static inline int skip_past_char (char ** str, char c) { + /* PR gas/14987: Allow for whitespace before the expected character. */ + skip_whitespace (*str); + if (**str == c) { (*str)++; @@ -5168,6 +5172,9 @@ parse_address_main (char **str, int i, int group_relocations, return PARSE_OPERAND_SUCCESS; } + /* PR gas/14887: Allow for whitespace after the opening bracket. */ + skip_whitespace (p); + if ((reg = arm_reg_parse (&p, REG_TYPE_RN)) == FAIL) { inst.error = _(reg_expected_msgs[REG_TYPE_RN]); @@ -6331,22 +6338,16 @@ parse_operands (char *str, const unsigned int *pattern, bfd_boolean thumb) do \ { \ val = parse_barrier (&str); \ - if (val == FAIL) \ - { \ - if (ISALPHA (*str)) \ - goto failure; \ - else \ - goto immediate; \ - } \ - else \ + if (val == FAIL && ! ISALPHA (*str)) \ + goto immediate; \ + if (val == FAIL \ + /* ISB can only take SY as an option. */ \ + || ((inst.instruction & 0xf0) == 0x60 \ + && val != 0xf)) \ { \ - if ((inst.instruction & 0xf0) == 0x60 \ - && val != 0xf) \ - { \ - /* ISB can only take SY as an option. */ \ - inst.error = _("invalid barrier type"); \ - goto failure; \ - } \ + inst.error = _("invalid barrier type"); \ + backtrack_pos = 0; \ + goto failure; \ } \ } \ while (0) @@ -7195,8 +7196,10 @@ encode_arm_addr_mode_3 (int i, bfd_boolean is_t) if (inst.operands[i].immisreg) { constraint ((inst.operands[i].imm == REG_PC - || inst.operands[i].reg == REG_PC), + || (is_t && inst.operands[i].reg == REG_PC)), BAD_PC_ADDRESSING); + constraint (inst.operands[i].reg == REG_PC && inst.operands[i].writeback, + BAD_PC_WRITEBACK); inst.instruction |= inst.operands[i].imm; if (!inst.operands[i].negative) inst.instruction |= INDEX_UP; @@ -7534,13 +7537,7 @@ static void do_barrier (void) { if (inst.operands[0].present) - { - constraint ((inst.instruction & 0xf0) != 0x40 - && inst.operands[0].imm > 0xf - && inst.operands[0].imm < 0x0, - _("bad barrier type")); - inst.instruction |= inst.operands[0].imm; - } + inst.instruction |= inst.operands[0].imm; else inst.instruction |= 0xf; } @@ -7821,7 +7818,7 @@ do_co_reg (void) && inst.operands[4].reg == r->crm && inst.operands[5].imm == r->opc2) { - if (!check_obsolete (&r->obsoleted, r->obs_msg) + if (! ARM_CPU_IS_ANY (cpu_variant) && warn_on_deprecated && ARM_CPU_HAS_FEATURE (cpu_variant, r->deprecated)) as_warn ("%s", r->dep_msg); @@ -8249,32 +8246,22 @@ do_vmrs (void) { unsigned Rt = inst.operands[0].reg; - if (thumb_mode && inst.operands[0].reg == REG_SP) + if (thumb_mode && Rt == REG_SP) { inst.error = BAD_SP; return; } /* APSR_ sets isvec. All other refs to PC are illegal. */ - if (!inst.operands[0].isvec && inst.operands[0].reg == REG_PC) + if (!inst.operands[0].isvec && Rt == REG_PC) { inst.error = BAD_PC; return; } - switch (inst.operands[1].reg) - { - case 0: /* FPSID */ - case 1: /* FPSCR */ - case 6: /* MVFR1 */ - case 7: /* MVFR0 */ - case 8: /* FPEXC */ - inst.instruction |= (inst.operands[1].reg << 16); - break; - default: - first_error (_("operand 1 must be a VFP extension System Register")); - } - + /* If we get through parsing the register name, we just insert the number + generated into the instruction without further validation. */ + inst.instruction |= (inst.operands[1].reg << 16); inst.instruction |= (Rt << 12); } @@ -8291,17 +8278,9 @@ do_vmsr (void) return; } - switch (inst.operands[0].reg) - { - case 0: /* FPSID */ - case 1: /* FPSCR */ - case 8: /* FPEXC */ - inst.instruction |= (inst.operands[0].reg << 16); - break; - default: - first_error (_("operand 0 must be FPSID or FPSCR pr FPEXC")); - } - + /* If we get through parsing the register name, we just insert the number + generated into the instruction without further validation. */ + inst.instruction |= (inst.operands[0].reg << 16); inst.instruction |= (Rt << 12); } @@ -9464,8 +9443,8 @@ encode_thumb32_addr_mode (int i, bfd_boolean is_t, bfd_boolean is_d) constraint (is_pc && inst.operands[i].writeback, BAD_PC_WRITEBACK); constraint (is_t && inst.operands[i].writeback, _("cannot use writeback with this instruction")); - constraint (is_pc && ((inst.instruction & THUMB2_LOAD_BIT) == 0) - && !inst.reloc.pc_rel, BAD_PC_ADDRESSING); + constraint (is_pc && ((inst.instruction & THUMB2_LOAD_BIT) == 0), + BAD_PC_ADDRESSING); if (is_d) { @@ -10061,21 +10040,6 @@ do_t_arit3c (void) } } -static void -do_t_barrier (void) -{ - if (inst.operands[0].present) - { - constraint ((inst.instruction & 0xf0) != 0x40 - && inst.operands[0].imm > 0xf - && inst.operands[0].imm < 0x0, - _("bad barrier type")); - inst.instruction |= inst.operands[0].imm; - } - else - inst.instruction |= 0xf; -} - static void do_t_bfc (void) { @@ -15353,6 +15317,16 @@ do_neon_mov (void) unsigned dn = NEON_SCALAR_REG (inst.operands[0].reg); unsigned x = NEON_SCALAR_INDEX (inst.operands[0].reg); + /* . is optional here, defaulting to .32. */ + if (inst.vectype.elems == 0 + && inst.operands[0].vectype.type == NT_invtype + && inst.operands[1].vectype.type == NT_invtype) + { + inst.vectype.el[0].type = NT_untyped; + inst.vectype.el[0].size = 32; + inst.vectype.elems = 1; + } + et = neon_check_type (2, NS_NULL, N_8 | N_16 | N_32 | N_KEY, N_EQK); logsize = neon_logbits (et.size); @@ -15402,6 +15376,16 @@ do_neon_mov (void) unsigned x = NEON_SCALAR_INDEX (inst.operands[1].reg); unsigned abcdebits = 0; + /* .
is optional here, defaulting to .32. */ + if (inst.vectype.elems == 0 + && inst.operands[0].vectype.type == NT_invtype + && inst.operands[1].vectype.type == NT_invtype) + { + inst.vectype.el[0].type = NT_untyped; + inst.vectype.el[0].size = 32; + inst.vectype.elems = 1; + } + et = neon_check_type (2, NS_NULL, N_EQK, N_S8 | N_S16 | N_U8 | N_U16 | N_32 | N_KEY); logsize = neon_logbits (et.size); @@ -15490,6 +15474,11 @@ do_neon_mov (void) do_vfp_nsyn_opcode ("fmsrr"); break; + case NS_NULL: + /* neon_select_shape has determined that the instruction + shape is wrong and has already set the error message. */ + break; + default: abort (); } @@ -15678,12 +15667,12 @@ do_neon_ldr_str (void) And is UNPREDICTABLE in thumb mode. */ if (!is_ldr && inst.operands[1].reg == REG_PC - && ARM_CPU_HAS_FEATURE (selected_cpu, arm_ext_v7)) + && (ARM_CPU_HAS_FEATURE (selected_cpu, arm_ext_v7) || thumb_mode)) { - if (!thumb_mode && warn_on_deprecated) - as_warn (_("Use of PC here is deprecated")); - else + if (thumb_mode) inst.error = _("Use of PC here is UNPREDICTABLE"); + else if (warn_on_deprecated) + as_warn (_("Use of PC here is deprecated")); } if (inst.operands[0].issingle) @@ -15987,6 +15976,11 @@ do_neon_ldx_stx (void) case NEON_ALL_LANES: NEON_ENCODE (DUP, inst); + if (inst.instruction == N_INV) + { + first_error ("only loads support such operands"); + break; + } do_neon_ld_dup (); break; @@ -16305,6 +16299,63 @@ do_sha256su0 (void) { do_crypto_2op_1 (N_32, 1); } + +static void +do_crc32_1 (unsigned int poly, unsigned int sz) +{ + unsigned int Rd = inst.operands[0].reg; + unsigned int Rn = inst.operands[1].reg; + unsigned int Rm = inst.operands[2].reg; + + set_it_insn_type (OUTSIDE_IT_INSN); + inst.instruction |= LOW4 (Rd) << (thumb_mode ? 8 : 12); + inst.instruction |= LOW4 (Rn) << 16; + inst.instruction |= LOW4 (Rm); + inst.instruction |= sz << (thumb_mode ? 4 : 21); + inst.instruction |= poly << (thumb_mode ? 20 : 9); + + if (Rd == REG_PC || Rn == REG_PC || Rm == REG_PC) + as_warn (UNPRED_REG ("r15")); + if (thumb_mode && (Rd == REG_SP || Rn == REG_SP || Rm == REG_SP)) + as_warn (UNPRED_REG ("r13")); +} + +static void +do_crc32b (void) +{ + do_crc32_1 (0, 0); +} + +static void +do_crc32h (void) +{ + do_crc32_1 (0, 1); +} + +static void +do_crc32w (void) +{ + do_crc32_1 (0, 2); +} + +static void +do_crc32cb (void) +{ + do_crc32_1 (1, 0); +} + +static void +do_crc32ch (void) +{ + do_crc32_1 (1, 1); +} + +static void +do_crc32cw (void) +{ + do_crc32_1 (1, 2); +} + /* Overall per-instruction processing. */ @@ -17469,7 +17520,7 @@ static const struct reg_entry reg_names[] = REGDEF(R10_fiq,512|(10<<16),RNB), REGDEF(r10_fiq,512|(10<<16),RNB), REGDEF(R11_fiq,512|(11<<16),RNB), REGDEF(r11_fiq,512|(11<<16),RNB), REGDEF(R12_fiq,512|(12<<16),RNB), REGDEF(r12_fiq,512|(12<<16),RNB), - REGDEF(SP_fiq,512|(13<<16),RNB), REGDEF(SP_fiq,512|(13<<16),RNB), + REGDEF(SP_fiq,512|(13<<16),RNB), REGDEF(sp_fiq,512|(13<<16),RNB), REGDEF(LR_fiq,512|(14<<16),RNB), REGDEF(lr_fiq,512|(14<<16),RNB), REGDEF(SPSR_fiq,512|(14<<16)|SPSR_BIT,RNB), REGDEF(spsr_fiq,512|(14<<16)|SPSR_BIT,RNB), @@ -17790,6 +17841,13 @@ static struct asm_barrier_opt barrier_opt_names[] = { mnem, OPS##nops ops, OT_unconditional, 0x##op, 0x##top, ARM_VARIANT, \ THUMB_VARIANT, do_##ae, do_##te } +/* Same as TUE but the encoding function for ARM and Thumb modes is the same. + Used by mnemonics that have very minimal differences in the encoding for + ARM and Thumb variants and can be handled in a common function. */ +#define TUEc(mnem, op, top, nops, ops, en) \ + { mnem, OPS##nops ops, OT_unconditional, 0x##op, 0x##top, ARM_VARIANT, \ + THUMB_VARIANT, do_##en, do_##en } + /* Mnemonic that cannot be conditionalized, and bears 0xF in its ARM condition code field. */ #define TUF(mnem, op, top, nops, ops, ae, te) \ @@ -18189,17 +18247,23 @@ static const struct asm_opcode insns[] = #undef THUMB_VARIANT #define THUMB_VARIANT & arm_ext_v6_notm TUF("rfeia", 8900a00, e990c000, 1, (RRw), rfe, rfe), + TUF("rfe", 8900a00, e990c000, 1, (RRw), rfe, rfe), UF(rfeib, 9900a00, 1, (RRw), rfe), UF(rfeda, 8100a00, 1, (RRw), rfe), TUF("rfedb", 9100a00, e810c000, 1, (RRw), rfe, rfe), TUF("rfefd", 8900a00, e990c000, 1, (RRw), rfe, rfe), - UF(rfefa, 9900a00, 1, (RRw), rfe), - UF(rfeea, 8100a00, 1, (RRw), rfe), - TUF("rfeed", 9100a00, e810c000, 1, (RRw), rfe, rfe), + UF(rfefa, 8100a00, 1, (RRw), rfe), + TUF("rfeea", 9100a00, e810c000, 1, (RRw), rfe, rfe), + UF(rfeed, 9900a00, 1, (RRw), rfe), TUF("srsia", 8c00500, e980c000, 2, (oRRw, I31w), srs, srs), + TUF("srs", 8c00500, e980c000, 2, (oRRw, I31w), srs, srs), + TUF("srsea", 8c00500, e980c000, 2, (oRRw, I31w), srs, srs), UF(srsib, 9c00500, 2, (oRRw, I31w), srs), + UF(srsfa, 9c00500, 2, (oRRw, I31w), srs), UF(srsda, 8400500, 2, (oRRw, I31w), srs), + UF(srsed, 8400500, 2, (oRRw, I31w), srs), TUF("srsdb", 9400500, e800c000, 2, (oRRw, I31w), srs, srs), + TUF("srsfd", 9400500, e800c000, 2, (oRRw, I31w), srs, srs), /* ARM V6 not included in V7M (eg. integer SIMD). */ #undef THUMB_VARIANT @@ -18421,9 +18485,9 @@ static const struct asm_opcode insns[] = #undef THUMB_VARIANT #define THUMB_VARIANT & arm_ext_barrier - TUF("dmb", 57ff050, f3bf8f50, 1, (oBARRIER_I15), barrier, t_barrier), - TUF("dsb", 57ff040, f3bf8f40, 1, (oBARRIER_I15), barrier, t_barrier), - TUF("isb", 57ff060, f3bf8f60, 1, (oBARRIER_I15), barrier, t_barrier), + TUF("dmb", 57ff050, f3bf8f50, 1, (oBARRIER_I15), barrier, barrier), + TUF("dsb", 57ff040, f3bf8f40, 1, (oBARRIER_I15), barrier, barrier), + TUF("isb", 57ff060, f3bf8f60, 1, (oBARRIER_I15), barrier, barrier), /* ARM V7 instructions. */ #undef ARM_VARIANT @@ -18521,6 +18585,17 @@ static const struct asm_opcode insns[] = nUF(sha1su1, _sha2op, 2, (RNQ, RNQ), sha1su1), nUF(sha256su0, _sha2op, 2, (RNQ, RNQ), sha256su0), +#undef ARM_VARIANT +#define ARM_VARIANT & crc_ext_armv8 +#undef THUMB_VARIANT +#define THUMB_VARIANT & crc_ext_armv8 + TUEc("crc32b", 1000040, fac0f080, 3, (RR, oRR, RR), crc32b), + TUEc("crc32h", 1200040, fac0f090, 3, (RR, oRR, RR), crc32h), + TUEc("crc32w", 1400040, fac0f0a0, 3, (RR, oRR, RR), crc32w), + TUEc("crc32cb",1000240, fad0f080, 3, (RR, oRR, RR), crc32cb), + TUEc("crc32ch",1200240, fad0f090, 3, (RR, oRR, RR), crc32ch), + TUEc("crc32cw",1400240, fad0f0a0, 3, (RR, oRR, RR), crc32cw), + #undef ARM_VARIANT #define ARM_VARIANT & fpu_fpa_ext_v1 /* Core FPA instruction set (V1). */ #undef THUMB_VARIANT @@ -21537,8 +21612,9 @@ md_apply_fix (fixS * fixP, as_bad_where (fixP->fx_file, fixP->fx_line, _("invalid literal constant: pool needs to be closer")); else - as_bad (_("bad immediate value for 8-bit offset (%ld)"), - (long) value); + as_bad_where (fixP->fx_file, fixP->fx_line, + _("bad immediate value for 8-bit offset (%ld)"), + (long) value); break; } @@ -22040,18 +22116,18 @@ md_apply_fix (fixS * fixP, thumb_bl_common: -#ifdef OBJ_ELF - if (EF_ARM_EABI_VERSION (meabi_flags) >= EF_ARM_EABI_VER4 - && fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX) - fixP->fx_r_type = BFD_RELOC_THUMB_PCREL_BRANCH23; -#endif - if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX) /* For a BLX instruction, make sure that the relocation is rounded up to a word boundary. This follows the semantics of the instruction which specifies that bit 1 of the target address will come from bit 1 of the base address. */ - value = (value + 1) & ~ 1; + value = (value + 3) & ~ 3; + +#ifdef OBJ_ELF + if (EF_ARM_EABI_VERSION (meabi_flags) >= EF_ARM_EABI_VER4 + && fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX) + fixP->fx_r_type = BFD_RELOC_THUMB_PCREL_BRANCH23; +#endif if ((value & ~0x3fffff) && ((value & ~0x3fffff) != ~0x3fffff)) { @@ -23872,11 +23948,18 @@ static const struct arm_cpu_option_table arm_cpus[] = ARM_CPU_OPT ("cortex-a15", ARM_ARCH_V7A_IDIV_MP_SEC_VIRT, FPU_ARCH_NEON_VFP_V4, "Cortex-A15"), + ARM_CPU_OPT ("cortex-a53", ARM_ARCH_V8A, FPU_ARCH_CRYPTO_NEON_VFP_ARMV8, + "Cortex-A53"), + ARM_CPU_OPT ("cortex-a57", ARM_ARCH_V8A, FPU_ARCH_CRYPTO_NEON_VFP_ARMV8, + "Cortex-A57"), 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"), ARM_CPU_OPT ("cortex-r5", ARM_ARCH_V7R_IDIV, FPU_NONE, "Cortex-R5"), + ARM_CPU_OPT ("cortex-r7", ARM_ARCH_V7R_IDIV, + FPU_ARCH_VFP_V3D16, + "Cortex-R7"), ARM_CPU_OPT ("cortex-m4", ARM_ARCH_V7EM, FPU_NONE, "Cortex-M4"), ARM_CPU_OPT ("cortex-m3", ARM_ARCH_V7M, FPU_NONE, "Cortex-M3"), ARM_CPU_OPT ("cortex-m1", ARM_ARCH_V6SM, FPU_NONE, "Cortex-M1"), @@ -23890,8 +23973,11 @@ static const struct arm_cpu_option_table arm_cpus[] = 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), - FPU_ARCH_MAVERICK, - "ARM920T"), + FPU_ARCH_MAVERICK, "ARM920T"), + /* Marvell processors. */ + ARM_CPU_OPT ("marvell-pj4", ARM_FEATURE (ARM_AEXT_V7A | ARM_EXT_MP | ARM_EXT_SEC, 0), + FPU_ARCH_VFP_V3D16, NULL), + { NULL, 0, ARM_ARCH_NONE, ARM_ARCH_NONE, NULL } }; #undef ARM_CPU_OPT @@ -23969,6 +24055,7 @@ struct arm_option_extension_value_table #define ARM_EXT_OPT(N, V, AA) { N, sizeof (N) - 1, V, AA } static const struct arm_option_extension_value_table arm_extensions[] = { + ARM_EXT_OPT ("crc", ARCH_CRC_ARMV8, ARM_FEATURE (ARM_EXT_V8, 0)), ARM_EXT_OPT ("crypto", FPU_ARCH_CRYPTO_NEON_VFP_ARMV8, ARM_FEATURE (ARM_EXT_V8, 0)), ARM_EXT_OPT ("fp", FPU_ARCH_VFP_ARMV8,