X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gas%2Fconfig%2Ftc-arm.c;h=81378687b2aec21f5c75faa61e17ee391ce8d08d;hb=87975d2a60adf249212c1c031abb4dd0dbb800ac;hp=04b3f703248fec08b8f2fcbba2d673e1e2ce0a5d;hpb=cd21e5460f664d311f34645388138a44c228dc97;p=deliverable%2Fbinutils-gdb.git diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c index 04b3f70324..81378687b2 100644 --- a/gas/config/tc-arm.c +++ b/gas/config/tc-arm.c @@ -1,6 +1,6 @@ /* tc-arm.c -- Assemble for the ARM Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, - 2004, 2005, 2006, 2007, 2008, 2009 + 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. Contributed by Richard Earnshaw (rwe@pegasus.esprit.ec.org) Modified by David Taylor (dtaylor@armltd.co.uk) @@ -97,13 +97,12 @@ enum arm_float_abi /* Types of processor to assemble for. */ #ifndef CPU_DEFAULT -#if defined __XSCALE__ -#define CPU_DEFAULT ARM_ARCH_XSCALE -#else -#if defined __thumb__ -#define CPU_DEFAULT ARM_ARCH_V5T -#endif -#endif +/* The code that was here used to select a default CPU depending on compiler + pre-defines which were only present when doing native builds, thus + changing gas' default behaviour depending upon the build host. + + If you have a target that requires a default CPU option then the you + should define CPU_DEFAULT here. */ #endif #ifndef FPU_DEFAULT @@ -943,6 +942,8 @@ my_get_expression (expressionS * ep, char ** str, int prefix_mode) input_line_pointer = save_in; return 1; } +#else + (void) seg; #endif /* Get rid of any bignums now, so that we don't generate an error for which @@ -1882,7 +1883,6 @@ parse_neon_el_struct_list (char **str, unsigned *pbase, int lane = -1; int leading_brace = 0; enum arm_reg_type rtype = REG_TYPE_NDQ; - int addregs = 1; 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; @@ -1907,7 +1907,6 @@ parse_neon_el_struct_list (char **str, unsigned *pbase, if (rtype == REG_TYPE_NQ) { reg_incr = 1; - addregs = 2; } firsttype = atype; } @@ -2494,14 +2493,27 @@ make_mapping_symbol (enum mstate state, valueT value, fragS *frag) /* Save the mapping symbols for future reference. Also check that we do not place two mapping symbols at the same offset within a frag. We'll handle overlap between frags in - check_mapping_symbols. */ + check_mapping_symbols. + + If .fill or other data filling directive generates zero sized data, + the mapping symbol for the following code will have the same value + as the one generated for the data filling directive. In this case, + we replace the old symbol with the new one at the same address. */ if (value == 0) { - know (frag->tc_frag_data.first_map == NULL); + if (frag->tc_frag_data.first_map != NULL) + { + know (S_GET_VALUE (frag->tc_frag_data.first_map) == 0); + symbol_remove (frag->tc_frag_data.first_map, &symbol_rootP, &symbol_lastP); + } frag->tc_frag_data.first_map = symbolP; } if (frag->tc_frag_data.last_map != NULL) - know (S_GET_VALUE (frag->tc_frag_data.last_map) < S_GET_VALUE (symbolP)); + { + know (S_GET_VALUE (frag->tc_frag_data.last_map) <= S_GET_VALUE (symbolP)); + if (S_GET_VALUE (frag->tc_frag_data.last_map) == S_GET_VALUE (symbolP)) + symbol_remove (frag->tc_frag_data.last_map, &symbol_rootP, &symbol_lastP); + } frag->tc_frag_data.last_map = symbolP; } @@ -4936,6 +4948,33 @@ parse_shifter_operand_group_reloc (char **str, int i) /* Never reached. */ } +/* Parse a Neon alignment expression. Information is written to + inst.operands[i]. We assume the initial ':' has been skipped. + + align .imm = align << 8, .immisalign=1, .preind=0 */ +static parse_operand_result +parse_neon_alignment (char **str, int i) +{ + char *p = *str; + expressionS exp; + + my_get_expression (&exp, &p, GE_NO_PREFIX); + + if (exp.X_op != O_constant) + { + inst.error = _("alignment must be constant"); + return PARSE_OPERAND_FAIL; + } + + inst.operands[i].imm = exp.X_add_number << 8; + inst.operands[i].immisalign = 1; + /* Alignments are not pre-indexes. */ + inst.operands[i].preind = 0; + + *str = p; + return PARSE_OPERAND_SUCCESS; +} + /* Parse all forms of an ARM address expression. Information is written to inst.operands[i] and/or inst.reloc. @@ -5019,22 +5058,15 @@ parse_address_main (char **str, int i, int group_relocations, return PARSE_OPERAND_FAIL; } else if (skip_past_char (&p, ':') == SUCCESS) - { - /* FIXME: '@' should be used here, but it's filtered out by generic - code before we get to see it here. This may be subject to - change. */ - expressionS exp; - my_get_expression (&exp, &p, GE_NO_PREFIX); - if (exp.X_op != O_constant) - { - inst.error = _("alignment must be constant"); - return PARSE_OPERAND_FAIL; - } - inst.operands[i].imm = exp.X_add_number << 8; - inst.operands[i].immisalign = 1; - /* Alignments are not pre-indexes. */ - inst.operands[i].preind = 0; - } + { + /* FIXME: '@' should be used here, but it's filtered out by generic + code before we get to see it here. This may be subject to + change. */ + parse_operand_result result = parse_neon_alignment (&p, i); + + if (result != PARSE_OPERAND_SUCCESS) + return result; + } else { if (inst.operands[i].negative) @@ -5098,6 +5130,15 @@ parse_address_main (char **str, int i, int group_relocations, return PARSE_OPERAND_FAIL; } } + else if (skip_past_char (&p, ':') == SUCCESS) + { + /* FIXME: '@' should be used here, but it's filtered out by generic code + before we get to see it here. This may be subject to change. */ + parse_operand_result result = parse_neon_alignment (&p, i); + + if (result != PARSE_OPERAND_SUCCESS) + return result; + } if (skip_past_char (&p, ']') == FAIL) { @@ -5747,6 +5788,8 @@ enum operand_parse_code OP_RRnpc, /* ARM register, not r15 */ OP_RRnpcsp, /* ARM register, neither r15 nor r13 (a.k.a. 'BadReg') */ OP_RRnpcb, /* ARM register, not r15, in square brackets */ + OP_RRnpctw, /* ARM register, not r15 in Thumb-state or with writeback, + optional trailing ! */ OP_RRw, /* ARM register, not r15, optional trailing ! */ OP_RCP, /* Coprocessor number */ OP_RCN, /* Coprocessor register */ @@ -6116,6 +6159,7 @@ parse_operands (char *str, const unsigned int *pattern, bfd_boolean thumb) po_char_or_fail (']'); break; + case OP_RRnpctw: case OP_RRw: case OP_oRRw: po_reg_or_fail (REG_TYPE_RN); @@ -6424,6 +6468,13 @@ parse_operands (char *str, const unsigned int *pattern, bfd_boolean thumb) } break; + case OP_RRnpctw: + if (inst.operands[i].isreg + && inst.operands[i].reg == REG_PC + && (inst.operands[i].writeback || thumb)) + inst.error = BAD_PC; + break; + case OP_CPSF: case OP_ENDI: case OP_oROR: @@ -6971,8 +7022,16 @@ do_rd_rm_rn (void) unsigned Rn = inst.operands[2].reg; /* Enforce restrictions on SWP instruction. */ if ((inst.instruction & 0x0fbfffff) == 0x01000090) - constraint (Rn == inst.operands[0].reg || Rn == inst.operands[1].reg, - _("Rn must not overlap other operands")); + { + constraint (Rn == inst.operands[0].reg || Rn == inst.operands[1].reg, + _("Rn must not overlap other operands")); + + /* SWP{b} is deprecated for ARMv6* and ARMv7. */ + if (warn_on_deprecated + && ARM_CPU_HAS_FEATURE (selected_cpu, arm_ext_v6)) + as_warn (_("swp{b} use is deprecated for this architecture")); + + } inst.instruction |= inst.operands[0].reg << 12; inst.instruction |= inst.operands[1].reg; inst.instruction |= Rn << 16; @@ -9740,6 +9799,12 @@ encode_thumb2_ldmstm (int base, unsigned mask, bfd_boolean writeback) if (mask & (1 << 13)) inst.error = _("SP not allowed in register list"); + + if ((mask & (1 << base)) != 0 + && writeback) + inst.error = _("having the base register in the register list when " + "using write back is UNPREDICTABLE"); + if (load) { if (mask & (1 << 15)) @@ -9749,19 +9814,11 @@ encode_thumb2_ldmstm (int base, unsigned mask, bfd_boolean writeback) else set_it_insn_type_last (); } - - if ((mask & (1 << base)) != 0 - && writeback) - as_warn (_("base register should not be in register list " - "when written back")); } else { if (mask & (1 << 15)) inst.error = _("PC not allowed in register list"); - - if (mask & (1 << base)) - as_warn (_("value stored for r%d is UNPREDICTABLE"), base); } if ((mask & (mask - 1)) == 0) @@ -9827,7 +9884,7 @@ do_t_ldmstm (void) if (inst.instruction == T_MNEM_stmia && (inst.operands[1].imm & mask) && (inst.operands[1].imm & (mask - 1))) - as_warn (_("value stored for r%d is UNPREDICTABLE"), + as_warn (_("value stored for r%d is UNKNOWN"), inst.operands[0].reg); inst.instruction = THUMB_OP16 (inst.instruction); @@ -9867,7 +9924,7 @@ do_t_ldmstm (void) as_warn (_("this instruction will write back the base register")); if ((inst.operands[1].imm & (1 << inst.operands[0].reg)) && (inst.operands[1].imm & ((1 << inst.operands[0].reg) - 1))) - as_warn (_("value stored for r%d is UNPREDICTABLE"), + as_warn (_("value stored for r%d is UNKNOWN"), inst.operands[0].reg); } else @@ -10351,8 +10408,8 @@ do_t_mov_cmp (void) case T_MNEM_movs: /* We know we have low registers at this point. - Generate ADD Rd, Rs, #0. */ - inst.instruction = T_OPCODE_ADD_I3; + Generate LSLS Rd, Rs, #0. */ + inst.instruction = T_OPCODE_LSL_I; inst.instruction |= Rn; inst.instruction |= Rm << 3; break; @@ -11268,8 +11325,7 @@ do_t_strexd (void) constraint (inst.operands[0].reg == inst.operands[1].reg || inst.operands[0].reg == inst.operands[2].reg - || inst.operands[0].reg == inst.operands[3].reg - || inst.operands[1].reg == inst.operands[2].reg, + || inst.operands[0].reg == inst.operands[3].reg, BAD_OVERLAP); inst.instruction |= inst.operands[0].reg; @@ -11783,6 +11839,8 @@ neon_select_shape (enum neon_shape shape, ...) case SE_L: break; } + if (!matches) + break; } if (matches) break; @@ -14655,12 +14713,13 @@ do_neon_ld_st_interleave (void) { case 64: alignbits = 1; break; case 128: - if (NEON_REGLIST_LENGTH (inst.operands[0].imm) == 3) + if (NEON_REGLIST_LENGTH (inst.operands[0].imm) != 2 + && NEON_REGLIST_LENGTH (inst.operands[0].imm) != 4) goto bad_alignment; alignbits = 2; break; case 256: - if (NEON_REGLIST_LENGTH (inst.operands[0].imm) == 3) + if (NEON_REGLIST_LENGTH (inst.operands[0].imm) != 4) goto bad_alignment; alignbits = 3; break; @@ -15697,7 +15756,7 @@ md_assemble (char *str) || (thumb_mode == 1 && !ARM_CPU_HAS_FEATURE (variant, *opcode->tvariant))) { - as_bad (_("selected processor does not support `%s'"), str); + as_bad (_("selected processor does not support Thumb mode `%s'"), str); return; } if (inst.cond != COND_ALWAYS && !unified_syntax @@ -15722,7 +15781,7 @@ md_assemble (char *str) inst.size_req = 2; else if (inst.size_req == 4) { - as_bad (_("selected processor does not support `%s'"), str); + as_bad (_("selected processor does not support Thumb-2 mode `%s'"), str); return; } } @@ -15788,7 +15847,7 @@ md_assemble (char *str) && !(opcode->avariant && ARM_CPU_HAS_FEATURE (cpu_variant, *opcode->avariant))) { - as_bad (_("selected processor does not support `%s'"), str); + as_bad (_("selected processor does not support ARM mode `%s'"), str); return; } if (inst.size_req) @@ -16182,7 +16241,8 @@ static struct reloc_entry reloc_names[] = { "tlsldm", BFD_RELOC_ARM_TLS_LDM32}, { "TLSLDM", BFD_RELOC_ARM_TLS_LDM32}, { "tlsldo", BFD_RELOC_ARM_TLS_LDO32}, { "TLSLDO", BFD_RELOC_ARM_TLS_LDO32}, { "gottpoff",BFD_RELOC_ARM_TLS_IE32}, { "GOTTPOFF",BFD_RELOC_ARM_TLS_IE32}, - { "tpoff", BFD_RELOC_ARM_TLS_LE32}, { "TPOFF", BFD_RELOC_ARM_TLS_LE32} + { "tpoff", BFD_RELOC_ARM_TLS_LE32}, { "TPOFF", BFD_RELOC_ARM_TLS_LE32}, + { "got_prel", BFD_RELOC_ARM_GOT_PREL}, { "GOT_PREL", BFD_RELOC_ARM_GOT_PREL} }; #endif @@ -16416,9 +16476,6 @@ static struct asm_barrier_opt barrier_opt_names[] = #define do_0 0 -/* Thumb-only, unconditional. */ -#define UT(mnem, op, nops, ops, te) TUE (mnem, 0, op, nops, ops, 0, te) - static const struct asm_opcode insns[] = { #define ARM_VARIANT &arm_ext_v1 /* Core ARM Instructions. */ @@ -16875,8 +16932,11 @@ static const struct asm_opcode insns[] = TC3("ldrsbt", 03000d0, f9100e00, 2, (RRnpc_npcsp, ADDR), ldsttv4, t_ldstt), TC3("strht", 02000b0, f8200e00, 2, (RRnpc_npcsp, ADDR), ldsttv4, t_ldstt), - UT("cbnz", b900, 2, (RR, EXP), t_cbz), - UT("cbz", b100, 2, (RR, EXP), t_cbz), + /* Thumb-only instructions. */ +#undef ARM_VARIANT +#define ARM_VARIANT NULL + TUE("cbnz", 0, b900, 2, (RR, EXP), 0, t_cbz), + TUE("cbz", 0, b100, 2, (RR, EXP), 0, t_cbz), /* ARM does not really have an IT instruction, so always allow it. The opcode is copied from Thumb in order to allow warnings in @@ -17405,22 +17465,22 @@ static const struct asm_opcode insns[] = /* Memory operations. */ cCE("flds", d100a00, 2, (RVS, ADDRGLDC), vfp_sp_ldst), cCE("fsts", d000a00, 2, (RVS, ADDRGLDC), vfp_sp_ldst), - cCE("fldmias", c900a00, 2, (RRw, VRSLST), vfp_sp_ldstmia), - cCE("fldmfds", c900a00, 2, (RRw, VRSLST), vfp_sp_ldstmia), - cCE("fldmdbs", d300a00, 2, (RRw, VRSLST), vfp_sp_ldstmdb), - cCE("fldmeas", d300a00, 2, (RRw, VRSLST), vfp_sp_ldstmdb), - cCE("fldmiax", c900b00, 2, (RRw, VRDLST), vfp_xp_ldstmia), - cCE("fldmfdx", c900b00, 2, (RRw, VRDLST), vfp_xp_ldstmia), - cCE("fldmdbx", d300b00, 2, (RRw, VRDLST), vfp_xp_ldstmdb), - cCE("fldmeax", d300b00, 2, (RRw, VRDLST), vfp_xp_ldstmdb), - cCE("fstmias", c800a00, 2, (RRw, VRSLST), vfp_sp_ldstmia), - cCE("fstmeas", c800a00, 2, (RRw, VRSLST), vfp_sp_ldstmia), - cCE("fstmdbs", d200a00, 2, (RRw, VRSLST), vfp_sp_ldstmdb), - cCE("fstmfds", d200a00, 2, (RRw, VRSLST), vfp_sp_ldstmdb), - cCE("fstmiax", c800b00, 2, (RRw, VRDLST), vfp_xp_ldstmia), - cCE("fstmeax", c800b00, 2, (RRw, VRDLST), vfp_xp_ldstmia), - cCE("fstmdbx", d200b00, 2, (RRw, VRDLST), vfp_xp_ldstmdb), - cCE("fstmfdx", d200b00, 2, (RRw, VRDLST), vfp_xp_ldstmdb), + cCE("fldmias", c900a00, 2, (RRnpctw, VRSLST), vfp_sp_ldstmia), + cCE("fldmfds", c900a00, 2, (RRnpctw, VRSLST), vfp_sp_ldstmia), + cCE("fldmdbs", d300a00, 2, (RRnpctw, VRSLST), vfp_sp_ldstmdb), + cCE("fldmeas", d300a00, 2, (RRnpctw, VRSLST), vfp_sp_ldstmdb), + cCE("fldmiax", c900b00, 2, (RRnpctw, VRDLST), vfp_xp_ldstmia), + cCE("fldmfdx", c900b00, 2, (RRnpctw, VRDLST), vfp_xp_ldstmia), + cCE("fldmdbx", d300b00, 2, (RRnpctw, VRDLST), vfp_xp_ldstmdb), + cCE("fldmeax", d300b00, 2, (RRnpctw, VRDLST), vfp_xp_ldstmdb), + cCE("fstmias", c800a00, 2, (RRnpctw, VRSLST), vfp_sp_ldstmia), + cCE("fstmeas", c800a00, 2, (RRnpctw, VRSLST), vfp_sp_ldstmia), + cCE("fstmdbs", d200a00, 2, (RRnpctw, VRSLST), vfp_sp_ldstmdb), + cCE("fstmfds", d200a00, 2, (RRnpctw, VRSLST), vfp_sp_ldstmdb), + cCE("fstmiax", c800b00, 2, (RRnpctw, VRDLST), vfp_xp_ldstmia), + cCE("fstmeax", c800b00, 2, (RRnpctw, VRDLST), vfp_xp_ldstmia), + cCE("fstmdbx", d200b00, 2, (RRnpctw, VRDLST), vfp_xp_ldstmdb), + cCE("fstmfdx", d200b00, 2, (RRnpctw, VRDLST), vfp_xp_ldstmdb), /* Monadic operations. */ cCE("fabss", eb00ac0, 2, (RVS, RVS), vfp_sp_monadic), @@ -17448,14 +17508,14 @@ static const struct asm_opcode insns[] = implementations. */ cCE("fldd", d100b00, 2, (RVD, ADDRGLDC), vfp_dp_ldst), cCE("fstd", d000b00, 2, (RVD, ADDRGLDC), vfp_dp_ldst), - cCE("fldmiad", c900b00, 2, (RRw, VRDLST), vfp_dp_ldstmia), - cCE("fldmfdd", c900b00, 2, (RRw, VRDLST), vfp_dp_ldstmia), - cCE("fldmdbd", d300b00, 2, (RRw, VRDLST), vfp_dp_ldstmdb), - cCE("fldmead", d300b00, 2, (RRw, VRDLST), vfp_dp_ldstmdb), - cCE("fstmiad", c800b00, 2, (RRw, VRDLST), vfp_dp_ldstmia), - cCE("fstmead", c800b00, 2, (RRw, VRDLST), vfp_dp_ldstmia), - cCE("fstmdbd", d200b00, 2, (RRw, VRDLST), vfp_dp_ldstmdb), - cCE("fstmfdd", d200b00, 2, (RRw, VRDLST), vfp_dp_ldstmdb), + cCE("fldmiad", c900b00, 2, (RRnpctw, VRDLST), vfp_dp_ldstmia), + cCE("fldmfdd", c900b00, 2, (RRnpctw, VRDLST), vfp_dp_ldstmia), + cCE("fldmdbd", d300b00, 2, (RRnpctw, VRDLST), vfp_dp_ldstmdb), + cCE("fldmead", d300b00, 2, (RRnpctw, VRDLST), vfp_dp_ldstmdb), + cCE("fstmiad", c800b00, 2, (RRnpctw, VRDLST), vfp_dp_ldstmia), + cCE("fstmead", c800b00, 2, (RRnpctw, VRDLST), vfp_dp_ldstmia), + cCE("fstmdbd", d200b00, 2, (RRnpctw, VRDLST), vfp_dp_ldstmdb), + cCE("fstmfdd", d200b00, 2, (RRnpctw, VRDLST), vfp_dp_ldstmdb), #undef ARM_VARIANT #define ARM_VARIANT & fpu_vfp_ext_v1 /* VFP V1 (Double precision). */ @@ -17535,12 +17595,12 @@ static const struct asm_opcode insns[] = NCEF(vabs, 1b10300, 2, (RNSDQ, RNSDQ), neon_abs_neg), NCEF(vneg, 1b10380, 2, (RNSDQ, RNSDQ), neon_abs_neg), - NCE(vldm, c900b00, 2, (RRw, VRSDLST), neon_ldm_stm), - NCE(vldmia, c900b00, 2, (RRw, VRSDLST), neon_ldm_stm), - NCE(vldmdb, d100b00, 2, (RRw, VRSDLST), neon_ldm_stm), - NCE(vstm, c800b00, 2, (RRw, VRSDLST), neon_ldm_stm), - NCE(vstmia, c800b00, 2, (RRw, VRSDLST), neon_ldm_stm), - NCE(vstmdb, d000b00, 2, (RRw, VRSDLST), neon_ldm_stm), + NCE(vldm, c900b00, 2, (RRnpctw, VRSDLST), neon_ldm_stm), + NCE(vldmia, c900b00, 2, (RRnpctw, VRSDLST), neon_ldm_stm), + NCE(vldmdb, d100b00, 2, (RRnpctw, VRSDLST), neon_ldm_stm), + NCE(vstm, c800b00, 2, (RRnpctw, VRSDLST), neon_ldm_stm), + NCE(vstmia, c800b00, 2, (RRnpctw, VRSDLST), neon_ldm_stm), + NCE(vstmdb, d000b00, 2, (RRnpctw, VRSDLST), neon_ldm_stm), NCE(vldr, d100b00, 2, (RVSD, ADDRGLDC), neon_ldr_str), NCE(vstr, d000b00, 2, (RVSD, ADDRGLDC), neon_ldr_str), @@ -18507,7 +18567,8 @@ relax_adr (fragS *fragp, asection *sec, long stretch) /* Assume worst case for symbols not known to be in the same section. */ if (fragp->fr_symbol == NULL || !S_IS_DEFINED (fragp->fr_symbol) - || sec != S_GET_SEGMENT (fragp->fr_symbol)) + || sec != S_GET_SEGMENT (fragp->fr_symbol) + || S_IS_WEAK (fragp->fr_symbol)) return 4; val = relaxed_symbol_addr (fragp, stretch); @@ -18550,7 +18611,8 @@ relax_branch (fragS *fragp, asection *sec, int bits, long stretch) /* Assume worst case for symbols not known to be in the same section. */ if (!S_IS_DEFINED (fragp->fr_symbol) - || sec != S_GET_SEGMENT (fragp->fr_symbol)) + || sec != S_GET_SEGMENT (fragp->fr_symbol) + || S_IS_WEAK (fragp->fr_symbol)) return 4; #ifdef OBJ_ELF @@ -19761,22 +19823,23 @@ md_apply_fix (fixS * fixP, not have a reloc for it, so tc_gen_reloc will reject it. */ fixP->fx_done = 1; - if (fixP->fx_addsy - && ! S_IS_DEFINED (fixP->fx_addsy)) + if (fixP->fx_addsy) { - as_bad_where (fixP->fx_file, fixP->fx_line, - _("undefined symbol %s used as an immediate value"), - S_GET_NAME (fixP->fx_addsy)); - break; - } + const char *msg = 0; - if (fixP->fx_addsy - && S_GET_SEGMENT (fixP->fx_addsy) != seg) - { - as_bad_where (fixP->fx_file, fixP->fx_line, - _("symbol %s is in a different section"), - S_GET_NAME (fixP->fx_addsy)); - break; + if (! S_IS_DEFINED (fixP->fx_addsy)) + msg = _("undefined symbol %s used as an immediate value"); + else if (S_GET_SEGMENT (fixP->fx_addsy) != seg) + msg = _("symbol %s is in a different section"); + else if (S_IS_WEAK (fixP->fx_addsy)) + msg = _("symbol %s is weak and may be overridden later"); + + if (msg) + { + as_bad_where (fixP->fx_file, fixP->fx_line, + msg, S_GET_NAME (fixP->fx_addsy)); + break; + } } newimm = encode_arm_immediate (value); @@ -19802,24 +19865,25 @@ md_apply_fix (fixS * fixP, unsigned int highpart = 0; unsigned int newinsn = 0xe1a00000; /* nop. */ - if (fixP->fx_addsy - && ! S_IS_DEFINED (fixP->fx_addsy)) + if (fixP->fx_addsy) { - as_bad_where (fixP->fx_file, fixP->fx_line, - _("undefined symbol %s used as an immediate value"), - S_GET_NAME (fixP->fx_addsy)); - break; - } + const char *msg = 0; - if (fixP->fx_addsy - && S_GET_SEGMENT (fixP->fx_addsy) != seg) - { - as_bad_where (fixP->fx_file, fixP->fx_line, - _("symbol %s is in a different section"), - S_GET_NAME (fixP->fx_addsy)); - break; - } + if (! S_IS_DEFINED (fixP->fx_addsy)) + msg = _("undefined symbol %s used as an immediate value"); + else if (S_GET_SEGMENT (fixP->fx_addsy) != seg) + msg = _("symbol %s is in a different section"); + else if (S_IS_WEAK (fixP->fx_addsy)) + msg = _("symbol %s is weak and may be overridden later"); + if (msg) + { + as_bad_where (fixP->fx_file, fixP->fx_line, + msg, S_GET_NAME (fixP->fx_addsy)); + break; + } + } + newimm = encode_arm_immediate (value); temp = md_chars_to_number (buf, INSN_SIZE); @@ -20468,7 +20532,12 @@ md_apply_fix (fixS * fixP, if (fixP->fx_done || !seg->use_rela_p) md_number_to_chars (buf, 0, 4); break; - + + case BFD_RELOC_ARM_GOT_PREL: + if (fixP->fx_done || !seg->use_rela_p) + md_number_to_chars (buf, value, 4); + break; + case BFD_RELOC_ARM_TARGET2: /* TARGET2 is not partial-inplace, so we need to write the addend here for REL targets, because it won't be written out @@ -21053,6 +21122,7 @@ tc_gen_reloc (asection *section, fixS *fixp) #ifdef OBJ_ELF case BFD_RELOC_ARM_GOT32: case BFD_RELOC_ARM_GOTOFF: + case BFD_RELOC_ARM_GOT_PREL: case BFD_RELOC_ARM_PLT32: case BFD_RELOC_ARM_TARGET1: case BFD_RELOC_ARM_ROSEGREL32: @@ -22170,6 +22240,7 @@ static const struct arm_cpu_option_table arm_cpus[] = NULL}, {"cortex-r4", ARM_ARCH_V7R, FPU_NONE, NULL}, {"cortex-r4f", ARM_ARCH_V7R, FPU_ARCH_VFP_V3D16, NULL}, + {"cortex-m4", ARM_ARCH_V7EM, FPU_NONE, NULL}, {"cortex-m3", ARM_ARCH_V7M, FPU_NONE, NULL}, {"cortex-m1", ARM_ARCH_V6M, FPU_NONE, NULL}, {"cortex-m0", ARM_ARCH_V6M, FPU_NONE, NULL}, @@ -22822,6 +22893,11 @@ aeabi_set_public_attributes (void) || ARM_CPU_HAS_FEATURE (flags, fpu_vfp_ext_v1xd)) aeabi_set_attribute_int (Tag_VFP_arch, 1); + /* Tag_ABI_HardFP_use. */ + if (ARM_CPU_HAS_FEATURE (flags, fpu_vfp_ext_v1xd) + && !ARM_CPU_HAS_FEATURE (flags, fpu_vfp_ext_v1)) + aeabi_set_attribute_int (Tag_ABI_HardFP_use, 1); + /* Tag_WMMX_arch. */ if (ARM_CPU_HAS_FEATURE (flags, arm_cext_iwmmxt2)) aeabi_set_attribute_int (Tag_WMMX_arch, 2); @@ -22837,6 +22913,15 @@ aeabi_set_public_attributes (void) /* Tag_VFP_HP_extension (formerly Tag_NEON_FP16_arch). */ if (ARM_CPU_HAS_FEATURE (flags, fpu_vfp_fp16)) aeabi_set_attribute_int (Tag_VFP_HP_extension, 1); + + /* Tag_DIV_use. */ + if (ARM_CPU_HAS_FEATURE (flags, arm_ext_div)) + aeabi_set_attribute_int (Tag_DIV_use, 0); + /* Fill this in when gas supports v7a sdiv/udiv. + else if (... v7a with div extension used ...) + aeabi_set_attribute_int (Tag_DIV_use, 2); */ + else + aeabi_set_attribute_int (Tag_DIV_use, 1); } /* Add the default contents for the .ARM.attributes section. */ @@ -23017,6 +23102,7 @@ arm_convert_symbolic_attribute (const char *name) T (Tag_CPU_arch_profile), T (Tag_ARM_ISA_use), T (Tag_THUMB_ISA_use), + T (Tag_FP_arch), T (Tag_VFP_arch), T (Tag_WMMX_arch), T (Tag_Advanced_SIMD_arch), @@ -23031,7 +23117,9 @@ arm_convert_symbolic_attribute (const char *name) T (Tag_ABI_FP_exceptions), T (Tag_ABI_FP_user_exceptions), T (Tag_ABI_FP_number_model), + T (Tag_ABI_align_needed), T (Tag_ABI_align8_needed), + T (Tag_ABI_align_preserved), T (Tag_ABI_align8_preserved), T (Tag_ABI_enum_size), T (Tag_ABI_HardFP_use), @@ -23041,6 +23129,7 @@ arm_convert_symbolic_attribute (const char *name) T (Tag_ABI_FP_optimization_goals), T (Tag_compatibility), T (Tag_CPU_unaligned_access), + T (Tag_FP_HP_extension), T (Tag_VFP_HP_extension), T (Tag_ABI_FP_16bit_format), T (Tag_MPextension_use),