X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gas%2Fconfig%2Ftc-arm.c;h=19ead2e3b7337f36ab59a1256f261345508ea4b9;hb=fa3061313cf6689dc5c4df66d29fe56209c689e0;hp=c6347a2a5f72301d464bc79f8e1734466292e998;hpb=231b5e29367532b1154e608c86761bebd1db80d5;p=deliverable%2Fbinutils-gdb.git diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c index c6347a2a5f..19ead2e3b7 100644 --- a/gas/config/tc-arm.c +++ b/gas/config/tc-arm.c @@ -52,6 +52,7 @@ #define ARM_HALFWORD 0x00000020 /* allow half word loads */ #define ARM_THUMB 0x00000040 /* allow BX instruction */ #define ARM_EXT_V5 0x00000080 /* allow CLZ etc */ +#define ARM_EXT_V5E 0x00000200 /* "El Segundo" */ /* Architectures are the sum of the base and extensions */ #define ARM_ARCH_V4 (ARM_7 | ARM_LONGMUL | ARM_HALFWORD) @@ -138,10 +139,11 @@ CONST char FLT_CHARS[] = "rRsSfFdDxXeEpP"; symbolS * GOT_symbol; /* Pre-defined "_GLOBAL_OFFSET_TABLE_" */ #endif -CONST int md_reloc_size = 8; /* Size of relocation record */ - -static int thumb_mode = 0; /* non-zero if assembling thumb instructions */ +CONST int md_reloc_size = 8; /* Size of relocation record */ +static int thumb_mode = 0; /* 0: assemble for ARM, 1: assemble for Thumb, + 2: assemble for Thumb even though target cpu + does not support thumb instructions */ typedef struct arm_fix { int thumb_mode; @@ -439,6 +441,7 @@ static void do_mrs PARAMS ((char *, unsigned long)); static void do_mull PARAMS ((char *, unsigned long)); /* ARM THUMB */ static void do_bx PARAMS ((char *, unsigned long)); + /* Coprocessor Instructions */ static void do_cdp PARAMS ((char *, unsigned long)); @@ -504,11 +507,16 @@ static bfd_reloc_code_real_type arm_parse_reloc PARAMS ((void)); #define LONGEST_INST 5 + struct asm_opcode { CONST char * template; /* Basic string to match */ unsigned long value; /* Basic instruction code */ - CONST char * comp_suffix; /* Compulsory suffix that must follow conds */ + + /* Compulsory suffix that must follow conds. If "", then the + instruction is not conditional and must have no suffix. */ + CONST char * comp_suffix; + CONST struct asm_flg * flags; /* Bits to toggle if flag 'n' set */ unsigned long variants; /* Which CPU variants this exists for */ /* Function to call to parse args */ @@ -635,7 +643,7 @@ static CONST struct asm_opcode insns[] = #define PRE_INDEX 0x01000000 #define INDEX_UP 0x00800000 #define WRITE_BACK 0x00200000 -#define MULTI_SET_PSR 0x00400000 +#define LDM_TYPE_2_OR_3 0x00400000 #define LITERAL_MASK 0xf000f000 #define COND_MASK 0xf0000000 @@ -770,68 +778,69 @@ struct thumb_opcode CONST char * template; /* Basic string to match */ unsigned long value; /* Basic instruction code */ int size; + unsigned long variants; /* Which CPU variants this exists for */ void (* parms) PARAMS ((char *)); /* Function to call to parse args */ }; static CONST struct thumb_opcode tinsns[] = { - {"adc", 0x4140, 2, do_t_arit}, - {"add", 0x0000, 2, do_t_add}, - {"and", 0x4000, 2, do_t_arit}, - {"asr", 0x0000, 2, do_t_asr}, - {"b", T_OPCODE_BRANCH, 2, do_t_branch12}, - {"beq", 0xd0fe, 2, do_t_branch9}, - {"bne", 0xd1fe, 2, do_t_branch9}, - {"bcs", 0xd2fe, 2, do_t_branch9}, - {"bhs", 0xd2fe, 2, do_t_branch9}, - {"bcc", 0xd3fe, 2, do_t_branch9}, - {"bul", 0xd3fe, 2, do_t_branch9}, - {"blo", 0xd3fe, 2, do_t_branch9}, - {"bmi", 0xd4fe, 2, do_t_branch9}, - {"bpl", 0xd5fe, 2, do_t_branch9}, - {"bvs", 0xd6fe, 2, do_t_branch9}, - {"bvc", 0xd7fe, 2, do_t_branch9}, - {"bhi", 0xd8fe, 2, do_t_branch9}, - {"bls", 0xd9fe, 2, do_t_branch9}, - {"bge", 0xdafe, 2, do_t_branch9}, - {"blt", 0xdbfe, 2, do_t_branch9}, - {"bgt", 0xdcfe, 2, do_t_branch9}, - {"ble", 0xddfe, 2, do_t_branch9}, - {"bic", 0x4380, 2, do_t_arit}, - {"bl", 0xf7fffffe, 4, do_t_branch23}, - {"bx", 0x4700, 2, do_t_bx}, - {"cmn", T_OPCODE_CMN, 2, do_t_arit}, - {"cmp", 0x0000, 2, do_t_compare}, - {"eor", 0x4040, 2, do_t_arit}, - {"ldmia", 0xc800, 2, do_t_ldmstm}, - {"ldr", 0x0000, 2, do_t_ldr}, - {"ldrb", 0x0000, 2, do_t_ldrb}, - {"ldrh", 0x0000, 2, do_t_ldrh}, - {"ldrsb", 0x5600, 2, do_t_lds}, - {"ldrsh", 0x5e00, 2, do_t_lds}, - {"ldsb", 0x5600, 2, do_t_lds}, - {"ldsh", 0x5e00, 2, do_t_lds}, - {"lsl", 0x0000, 2, do_t_lsl}, - {"lsr", 0x0000, 2, do_t_lsr}, - {"mov", 0x0000, 2, do_t_mov}, - {"mul", T_OPCODE_MUL, 2, do_t_arit}, - {"mvn", T_OPCODE_MVN, 2, do_t_arit}, - {"neg", T_OPCODE_NEG, 2, do_t_arit}, - {"orr", 0x4300, 2, do_t_arit}, - {"pop", 0xbc00, 2, do_t_push_pop}, - {"push", 0xb400, 2, do_t_push_pop}, - {"ror", 0x41c0, 2, do_t_arit}, - {"sbc", 0x4180, 2, do_t_arit}, - {"stmia", 0xc000, 2, do_t_ldmstm}, - {"str", 0x0000, 2, do_t_str}, - {"strb", 0x0000, 2, do_t_strb}, - {"strh", 0x0000, 2, do_t_strh}, - {"swi", 0xdf00, 2, do_t_swi}, - {"sub", 0x0000, 2, do_t_sub}, - {"tst", T_OPCODE_TST, 2, do_t_arit}, + {"adc", 0x4140, 2, ARM_THUMB, do_t_arit}, + {"add", 0x0000, 2, ARM_THUMB, do_t_add}, + {"and", 0x4000, 2, ARM_THUMB, do_t_arit}, + {"asr", 0x0000, 2, ARM_THUMB, do_t_asr}, + {"b", T_OPCODE_BRANCH, 2, ARM_THUMB, do_t_branch12}, + {"beq", 0xd0fe, 2, ARM_THUMB, do_t_branch9}, + {"bne", 0xd1fe, 2, ARM_THUMB, do_t_branch9}, + {"bcs", 0xd2fe, 2, ARM_THUMB, do_t_branch9}, + {"bhs", 0xd2fe, 2, ARM_THUMB, do_t_branch9}, + {"bcc", 0xd3fe, 2, ARM_THUMB, do_t_branch9}, + {"bul", 0xd3fe, 2, ARM_THUMB, do_t_branch9}, + {"blo", 0xd3fe, 2, ARM_THUMB, do_t_branch9}, + {"bmi", 0xd4fe, 2, ARM_THUMB, do_t_branch9}, + {"bpl", 0xd5fe, 2, ARM_THUMB, do_t_branch9}, + {"bvs", 0xd6fe, 2, ARM_THUMB, do_t_branch9}, + {"bvc", 0xd7fe, 2, ARM_THUMB, do_t_branch9}, + {"bhi", 0xd8fe, 2, ARM_THUMB, do_t_branch9}, + {"bls", 0xd9fe, 2, ARM_THUMB, do_t_branch9}, + {"bge", 0xdafe, 2, ARM_THUMB, do_t_branch9}, + {"blt", 0xdbfe, 2, ARM_THUMB, do_t_branch9}, + {"bgt", 0xdcfe, 2, ARM_THUMB, do_t_branch9}, + {"ble", 0xddfe, 2, ARM_THUMB, do_t_branch9}, + {"bic", 0x4380, 2, ARM_THUMB, do_t_arit}, + {"bl", 0xf7fffffe, 4, ARM_THUMB, do_t_branch23}, + {"bx", 0x4700, 2, ARM_THUMB, do_t_bx}, + {"cmn", T_OPCODE_CMN, 2, ARM_THUMB, do_t_arit}, + {"cmp", 0x0000, 2, ARM_THUMB, do_t_compare}, + {"eor", 0x4040, 2, ARM_THUMB, do_t_arit}, + {"ldmia", 0xc800, 2, ARM_THUMB, do_t_ldmstm}, + {"ldr", 0x0000, 2, ARM_THUMB, do_t_ldr}, + {"ldrb", 0x0000, 2, ARM_THUMB, do_t_ldrb}, + {"ldrh", 0x0000, 2, ARM_THUMB, do_t_ldrh}, + {"ldrsb", 0x5600, 2, ARM_THUMB, do_t_lds}, + {"ldrsh", 0x5e00, 2, ARM_THUMB, do_t_lds}, + {"ldsb", 0x5600, 2, ARM_THUMB, do_t_lds}, + {"ldsh", 0x5e00, 2, ARM_THUMB, do_t_lds}, + {"lsl", 0x0000, 2, ARM_THUMB, do_t_lsl}, + {"lsr", 0x0000, 2, ARM_THUMB, do_t_lsr}, + {"mov", 0x0000, 2, ARM_THUMB, do_t_mov}, + {"mul", T_OPCODE_MUL, 2, ARM_THUMB, do_t_arit}, + {"mvn", T_OPCODE_MVN, 2, ARM_THUMB, do_t_arit}, + {"neg", T_OPCODE_NEG, 2, ARM_THUMB, do_t_arit}, + {"orr", 0x4300, 2, ARM_THUMB, do_t_arit}, + {"pop", 0xbc00, 2, ARM_THUMB, do_t_push_pop}, + {"push", 0xb400, 2, ARM_THUMB, do_t_push_pop}, + {"ror", 0x41c0, 2, ARM_THUMB, do_t_arit}, + {"sbc", 0x4180, 2, ARM_THUMB, do_t_arit}, + {"stmia", 0xc000, 2, ARM_THUMB, do_t_ldmstm}, + {"str", 0x0000, 2, ARM_THUMB, do_t_str}, + {"strb", 0x0000, 2, ARM_THUMB, do_t_strb}, + {"strh", 0x0000, 2, ARM_THUMB, do_t_strh}, + {"swi", 0xdf00, 2, ARM_THUMB, do_t_swi}, + {"sub", 0x0000, 2, ARM_THUMB, do_t_sub}, + {"tst", T_OPCODE_TST, 2, ARM_THUMB, do_t_arit}, /* Pseudo ops: */ - {"adr", 0x0000, 2, do_t_adr}, - {"nop", 0x46C0, 2, do_t_nop}, /* mov r8,r8 */ + {"adr", 0x0000, 2, ARM_THUMB, do_t_adr}, + {"nop", 0x46C0, 2, ARM_THUMB, do_t_nop}, /* mov r8,r8 */ }; struct reg_entry @@ -875,8 +884,10 @@ static CONST struct reg_entry reg_table[] = {NULL, 0} }; -#define bad_args _("Bad arguments to instruction"); -#define bad_pc _("r15 not allowed here"); +#define BAD_ARGS _("Bad arguments to instruction") +#define BAD_PC _("r15 not allowed here") +#define BAD_FLAGS _("Instruction should not have flags") +#define BAD_COND _("Instruction is not conditional") static struct hash_control * arm_ops_hsh = NULL; static struct hash_control * arm_tops_hsh = NULL; @@ -1250,7 +1261,7 @@ s_force_thumb (ignore) if (! thumb_mode) { - thumb_mode = 1; + thumb_mode = 2; record_alignment (now_seg, 1); } @@ -1359,7 +1370,9 @@ s_thumb_set (equiv) THUMB_SET_FUNC (symbolP, 1); ARM_SET_THUMB (symbolP, 1); +#if defined OBJ_ELF || defined OBJ_COFF ARM_SET_INTERWORK (symbolP, support_interwork); +#endif } /* If we change section we must dump the literal pool first. */ @@ -1370,7 +1383,11 @@ arm_s_text (ignore) if (now_seg != text_section) s_ltorg (0); +#ifdef OBJ_ELF + obj_elf_text (ignore); +#else s_text (ignore); +#endif } static void @@ -1385,7 +1402,11 @@ arm_s_data (ignore) else if (now_seg != data_section) s_ltorg (0); +#ifdef OBJ_ELF + obj_elf_data (ignore); +#else s_data (ignore); +#endif } #ifdef OBJ_ELF @@ -1500,8 +1521,10 @@ skip_past_comma (str) return comma ? SUCCESS : FAIL; } -/* A standard register must be given at this point. Shift is the place to - put it in the instruction. */ +/* A standard register must be given at this point. + Shift is the place to put it in inst.instruction. + Restores input start point on err. + Returns the reg#, or FAIL. */ static int reg_required_here (str, shift) @@ -1838,7 +1861,7 @@ do_mrs (str, flags) if (reg_required_here (&str, 12) == FAIL) { - inst.error = bad_args; + inst.error = BAD_ARGS; return; } @@ -1872,7 +1895,7 @@ do_msr (str, flags) if (skip_past_comma (&str) == FAIL || (reg = reg_required_here (&str, 0)) == FAIL) { - inst.error = bad_args; + inst.error = BAD_ARGS; return; } } @@ -1884,13 +1907,13 @@ do_msr (str, flags) inst.instruction |= PSR_CONTROL; else { - inst.error = bad_args; + inst.error = BAD_ARGS; return; } if (skip_past_comma (&str) == FAIL) { - inst.error = bad_args; + inst.error = BAD_ARGS; return; } @@ -1960,21 +1983,21 @@ do_mull (str, flags) if ((rdlo = reg_required_here (&str, 12)) == FAIL) { - inst.error = bad_args; + inst.error = BAD_ARGS; return; } if (skip_past_comma (&str) == FAIL || (rdhi = reg_required_here (&str, 16)) == FAIL) { - inst.error = bad_args; + inst.error = BAD_ARGS; return; } if (skip_past_comma (&str) == FAIL || (rm = reg_required_here (&str, 0)) == FAIL) { - inst.error = bad_args; + inst.error = BAD_ARGS; return; } @@ -1985,13 +2008,13 @@ do_mull (str, flags) if (skip_past_comma (&str) == FAIL || (rs = reg_required_here (&str, 8)) == FAIL) { - inst.error = bad_args; + inst.error = BAD_ARGS; return; } if (rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC) { - inst.error = bad_pc; + inst.error = BAD_PC; return; } @@ -2012,26 +2035,26 @@ do_mul (str, flags) if ((rd = reg_required_here (&str, 16)) == FAIL) { - inst.error = bad_args; + inst.error = BAD_ARGS; return; } if (rd == REG_PC) { - inst.error = bad_pc; + inst.error = BAD_PC; return; } if (skip_past_comma (&str) == FAIL || (rm = reg_required_here (&str, 0)) == FAIL) { - inst.error = bad_args; + inst.error = BAD_ARGS; return; } if (rm == REG_PC) { - inst.error = bad_pc; + inst.error = BAD_PC; return; } @@ -2041,13 +2064,13 @@ do_mul (str, flags) if (skip_past_comma (&str) == FAIL || (rm = reg_required_here (&str, 8)) == FAIL) { - inst.error = bad_args; + inst.error = BAD_ARGS; return; } if (rm == REG_PC) { - inst.error = bad_pc; + inst.error = BAD_PC; return; } @@ -2068,26 +2091,26 @@ do_mla (str, flags) if ((rd = reg_required_here (&str, 16)) == FAIL) { - inst.error = bad_args; + inst.error = BAD_ARGS; return; } if (rd == REG_PC) { - inst.error = bad_pc; + inst.error = BAD_PC; return; } if (skip_past_comma (&str) == FAIL || (rm = reg_required_here (&str, 0)) == FAIL) { - inst.error = bad_args; + inst.error = BAD_ARGS; return; } if (rm == REG_PC) { - inst.error = bad_pc; + inst.error = BAD_PC; return; } @@ -2099,13 +2122,13 @@ do_mla (str, flags) || skip_past_comma (&str) == FAIL || (rm = reg_required_here (&str, 12)) == FAIL) { - inst.error = bad_args; + inst.error = BAD_ARGS; return; } if (rd == REG_PC || rm == REG_PC) { - inst.error = bad_pc; + inst.error = BAD_PC; return; } @@ -2595,7 +2618,7 @@ do_arit (str, flags) || data_op2 (&str) == FAIL) { if (!inst.error) - inst.error = bad_args; + inst.error = BAD_ARGS; return; } @@ -2619,7 +2642,7 @@ do_adr (str, flags) || my_get_expression (&inst.reloc.exp, &str)) { if (!inst.error) - inst.error = bad_args; + inst.error = BAD_ARGS; return; } /* Frag hacking will turn this into a sub instruction if the offset turns @@ -2649,7 +2672,7 @@ do_adrl (str, flags) || my_get_expression (& inst.reloc.exp, & str)) { if (!inst.error) - inst.error = bad_args; + inst.error = BAD_ARGS; return; } @@ -2676,7 +2699,7 @@ do_cmp (str, flags) if (reg_required_here (&str, 16) == FAIL) { if (!inst.error) - inst.error = bad_args; + inst.error = BAD_ARGS; return; } @@ -2684,7 +2707,7 @@ do_cmp (str, flags) || data_op2 (&str) == FAIL) { if (!inst.error) - inst.error = bad_args; + inst.error = BAD_ARGS; return; } @@ -2706,7 +2729,7 @@ do_mov (str, flags) if (reg_required_here (&str, 12) == FAIL) { if (!inst.error) - inst.error = bad_args; + inst.error = BAD_ARGS; return; } @@ -2714,7 +2737,7 @@ do_mov (str, flags) || data_op2 (&str) == FAIL) { if (!inst.error) - inst.error = bad_args; + inst.error = BAD_ARGS; return; } @@ -2832,7 +2855,7 @@ do_ldst (str, flags) if ((conflict_reg = reg_required_here (& str, 12)) == FAIL) { if (!inst.error) - inst.error = bad_args; + inst.error = BAD_ARGS; return; } @@ -3158,14 +3181,14 @@ do_ldmstm (str, flags) || (range = reg_list (&str)) == FAIL) { if (! inst.error) - inst.error = bad_args; + inst.error = BAD_ARGS; return; } if (*str == '^') { str++; - flags |= MULTI_SET_PSR; + flags |= LDM_TYPE_2_OR_3; } inst.instruction |= flags | range; @@ -3218,7 +3241,7 @@ do_swap (str, flags) || (reg = reg_required_here (&str, 0)) == FAIL) { if (!inst.error) - inst.error = bad_args; + inst.error = BAD_ARGS; return; } @@ -3231,7 +3254,7 @@ do_swap (str, flags) if (skip_past_comma (&str) == FAIL || *str++ != '[') { - inst.error = bad_args; + inst.error = BAD_ARGS; return; } @@ -3242,7 +3265,7 @@ do_swap (str, flags) if (reg == REG_PC) { - inst.error = bad_pc; + inst.error = BAD_PC; return; } @@ -3315,13 +3338,15 @@ do_bx (str, flags) skip_whitespace (str); if ((reg = reg_required_here (&str, 0)) == FAIL) - return; + { + inst.error = BAD_ARGS; + return; + } if (reg == REG_PC) - as_tsktsk (_("Use of r15 in bx has undefined behaviour")); + inst.error = BAD_PC; end_of_line (str); - return; } static void @@ -3336,7 +3361,7 @@ do_cdp (str, flags) if (co_proc_number (&str) == FAIL) { if (!inst.error) - inst.error = bad_args; + inst.error = BAD_ARGS; return; } @@ -3344,7 +3369,7 @@ do_cdp (str, flags) || cp_opc_expr (&str, 20,4) == FAIL) { if (!inst.error) - inst.error = bad_args; + inst.error = BAD_ARGS; return; } @@ -3352,7 +3377,7 @@ do_cdp (str, flags) || cp_reg_required_here (&str, 12) == FAIL) { if (!inst.error) - inst.error = bad_args; + inst.error = BAD_ARGS; return; } @@ -3360,7 +3385,7 @@ do_cdp (str, flags) || cp_reg_required_here (&str, 16) == FAIL) { if (!inst.error) - inst.error = bad_args; + inst.error = BAD_ARGS; return; } @@ -3368,7 +3393,7 @@ do_cdp (str, flags) || cp_reg_required_here (&str, 0) == FAIL) { if (!inst.error) - inst.error = bad_args; + inst.error = BAD_ARGS; return; } @@ -3377,7 +3402,7 @@ do_cdp (str, flags) if (cp_opc_expr (&str, 5, 3) == FAIL) { if (!inst.error) - inst.error = bad_args; + inst.error = BAD_ARGS; return; } } @@ -3399,7 +3424,7 @@ do_lstc (str, flags) if (co_proc_number (&str) == FAIL) { if (!inst.error) - inst.error = bad_args; + inst.error = BAD_ARGS; return; } @@ -3407,7 +3432,7 @@ do_lstc (str, flags) || cp_reg_required_here (&str, 12) == FAIL) { if (!inst.error) - inst.error = bad_args; + inst.error = BAD_ARGS; return; } @@ -3415,7 +3440,7 @@ do_lstc (str, flags) || cp_address_required_here (&str) == FAIL) { if (! inst.error) - inst.error = bad_args; + inst.error = BAD_ARGS; return; } @@ -3437,7 +3462,7 @@ do_co_reg (str, flags) if (co_proc_number (&str) == FAIL) { if (!inst.error) - inst.error = bad_args; + inst.error = BAD_ARGS; return; } @@ -3445,7 +3470,7 @@ do_co_reg (str, flags) || cp_opc_expr (&str, 21, 3) == FAIL) { if (!inst.error) - inst.error = bad_args; + inst.error = BAD_ARGS; return; } @@ -3453,7 +3478,7 @@ do_co_reg (str, flags) || reg_required_here (&str, 12) == FAIL) { if (!inst.error) - inst.error = bad_args; + inst.error = BAD_ARGS; return; } @@ -3461,7 +3486,7 @@ do_co_reg (str, flags) || cp_reg_required_here (&str, 16) == FAIL) { if (!inst.error) - inst.error = bad_args; + inst.error = BAD_ARGS; return; } @@ -3469,7 +3494,7 @@ do_co_reg (str, flags) || cp_reg_required_here (&str, 0) == FAIL) { if (!inst.error) - inst.error = bad_args; + inst.error = BAD_ARGS; return; } @@ -3478,10 +3503,14 @@ do_co_reg (str, flags) if (cp_opc_expr (&str, 5, 3) == FAIL) { if (!inst.error) - inst.error = bad_args; + inst.error = BAD_ARGS; return; } } + if (flags) + { + inst.error = BAD_COND; + } end_of_line (str); return; @@ -3500,7 +3529,7 @@ do_fp_ctrl (str, flags) if (reg_required_here (&str, 12) == FAIL) { if (!inst.error) - inst.error = bad_args; + inst.error = BAD_ARGS; return; } @@ -3535,7 +3564,7 @@ do_fp_ldst (str, flags) if (fp_reg_required_here (&str, 12) == FAIL) { if (!inst.error) - inst.error = bad_args; + inst.error = BAD_ARGS; return; } @@ -3543,7 +3572,7 @@ do_fp_ldst (str, flags) || cp_address_required_here (&str) == FAIL) { if (!inst.error) - inst.error = bad_args; + inst.error = BAD_ARGS; return; } @@ -3562,7 +3591,7 @@ do_fp_ldmstm (str, flags) if (fp_reg_required_here (&str, 12) == FAIL) { if (! inst.error) - inst.error = bad_args; + inst.error = BAD_ARGS; return; } @@ -3620,7 +3649,7 @@ do_fp_ldmstm (str, flags) || *str != '[') { if (! inst.error) - inst.error = bad_args; + inst.error = BAD_ARGS; return; } @@ -3634,7 +3663,7 @@ do_fp_ldmstm (str, flags) if (*str != ']') { - inst.error = bad_args; + inst.error = BAD_ARGS; return; } @@ -3682,7 +3711,7 @@ do_fp_ldmstm (str, flags) || cp_address_required_here (&str) == FAIL) { if (! inst.error) - inst.error = bad_args; + inst.error = BAD_ARGS; return; } @@ -3713,7 +3742,7 @@ do_fp_dyadic (str, flags) if (fp_reg_required_here (&str, 12) == FAIL) { if (! inst.error) - inst.error = bad_args; + inst.error = BAD_ARGS; return; } @@ -3721,7 +3750,7 @@ do_fp_dyadic (str, flags) || fp_reg_required_here (&str, 16) == FAIL) { if (! inst.error) - inst.error = bad_args; + inst.error = BAD_ARGS; return; } @@ -3729,7 +3758,7 @@ do_fp_dyadic (str, flags) || fp_op2 (&str) == FAIL) { if (! inst.error) - inst.error = bad_args; + inst.error = BAD_ARGS; return; } @@ -3762,7 +3791,7 @@ do_fp_monadic (str, flags) if (fp_reg_required_here (&str, 12) == FAIL) { if (! inst.error) - inst.error = bad_args; + inst.error = BAD_ARGS; return; } @@ -3770,7 +3799,7 @@ do_fp_monadic (str, flags) || fp_op2 (&str) == FAIL) { if (! inst.error) - inst.error = bad_args; + inst.error = BAD_ARGS; return; } @@ -3789,7 +3818,7 @@ do_fp_cmp (str, flags) if (fp_reg_required_here (&str, 16) == FAIL) { if (! inst.error) - inst.error = bad_args; + inst.error = BAD_ARGS; return; } @@ -3797,7 +3826,7 @@ do_fp_cmp (str, flags) || fp_op2 (&str) == FAIL) { if (! inst.error) - inst.error = bad_args; + inst.error = BAD_ARGS; return; } @@ -3830,7 +3859,7 @@ do_fp_from_reg (str, flags) if (fp_reg_required_here (&str, 16) == FAIL) { if (! inst.error) - inst.error = bad_args; + inst.error = BAD_ARGS; return; } @@ -3838,7 +3867,7 @@ do_fp_from_reg (str, flags) || reg_required_here (&str, 12) == FAIL) { if (! inst.error) - inst.error = bad_args; + inst.error = BAD_ARGS; return; } @@ -3861,7 +3890,7 @@ do_fp_to_reg (str, flags) || fp_reg_required_here (&str, 0) == FAIL) { if (! inst.error) - inst.error = bad_args; + inst.error = BAD_ARGS; return; } @@ -3927,7 +3956,7 @@ thumb_add_sub (str, subtract) || skip_past_comma (&str) == FAIL) { if (! inst.error) - inst.error = bad_args; + inst.error = BAD_ARGS; return; } @@ -4094,7 +4123,7 @@ thumb_shift (str, shift) || skip_past_comma (&str) == FAIL) { if (! inst.error) - inst.error = bad_args; + inst.error = BAD_ARGS; return; } @@ -4203,7 +4232,7 @@ thumb_mov_compare (str, move) || skip_past_comma (&str) == FAIL) { if (! inst.error) - inst.error = bad_args; + inst.error = BAD_ARGS; return; } @@ -4292,7 +4321,7 @@ thumb_load_store (str, load_store, size) || skip_past_comma (&str) == FAIL) { if (! inst.error) - inst.error = bad_args; + inst.error = BAD_ARGS; return; } @@ -4497,15 +4526,12 @@ do_t_arit (str) skip_whitespace (str); - if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL) - return; - - if (skip_past_comma (&str) == FAIL + if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL + || skip_past_comma (&str) == FAIL || (Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL) { - if (! inst.error) - inst.error = bad_args; - return; + inst.error = BAD_ARGS; + return; } if (skip_past_comma (&str) != FAIL) @@ -4518,7 +4544,7 @@ do_t_arit (str) || inst.instruction == T_OPCODE_NEG || inst.instruction == T_OPCODE_MVN) { - inst.error = bad_args; + inst.error = BAD_ARGS; return; } @@ -4687,7 +4713,7 @@ do_t_ldmstm (str) || (range = reg_list (&str)) == FAIL) { if (! inst.error) - inst.error = bad_args; + inst.error = BAD_ARGS; return; } @@ -4787,7 +4813,7 @@ do_t_push_pop (str) if ((range = reg_list (&str)) == FAIL) { if (! inst.error) - inst.error = bad_args; + inst.error = BAD_ARGS; return; } @@ -4875,7 +4901,7 @@ do_t_adr (str) || my_get_expression (&inst.reloc.exp, &str)) { if (!inst.error) - inst.error = bad_args; + inst.error = BAD_ARGS; return; } @@ -5321,7 +5347,8 @@ md_apply_fix3 (fixP, val, seg) && S_GET_SEGMENT (fixP->fx_addsy) != seg) { if (target_oabi - && fixP->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH) + && (fixP->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH + )) value = 0; else value += md_pcrel_from (fixP); @@ -5519,6 +5546,7 @@ md_apply_fix3 (fixP, val, seg) md_number_to_chars (buf, newval, INSN_SIZE); break; + case BFD_RELOC_THUMB_PCREL_BRANCH9: /* conditional branch */ newval = md_chars_to_number (buf, THUMB_SIZE); { @@ -6048,6 +6076,13 @@ md_assemble (str) if (opcode) { + /* Check that this instruction is supported for this CPU. */ + if (thumb_mode == 1 && (opcode->variants & cpu_variant) == 0) + { + as_bad (_("selected processor does not support this opcode")); + return; + } + inst.instruction = opcode->value; inst.size = opcode->size; (*opcode->parms)(p); @@ -6058,6 +6093,7 @@ md_assemble (str) else { CONST struct asm_opcode * opcode; + unsigned long cond_code; inst.size = INSN_SIZE; /* p now points to the end of the opcode, probably white space, but we @@ -6084,11 +6120,18 @@ md_assemble (str) inst.instruction = opcode->value; if (q == p) /* Just a simple opcode. */ { - if (opcode->comp_suffix != 0) - as_bad (_("Opcode `%s' must have suffix from <%s>\n"), str, - opcode->comp_suffix); + if (opcode->comp_suffix) + { + if (*opcode->comp_suffix != '\0') + as_bad (_("Opcode `%s' must have suffix from list: <%s>"), + str, opcode->comp_suffix); + else + /* Not a conditional instruction. */ + (*opcode->parms)(q, 0); + } else { + /* A conditional instruction with default condition. */ inst.instruction |= COND_ALWAYS; (*opcode->parms)(q, 0); } @@ -6096,7 +6139,7 @@ md_assemble (str) return; } - /* Now check for a conditional. */ + /* Not just a simple opcode. Check if extra is a conditional. */ r = q; if (p - r >= 2) { @@ -6112,18 +6155,33 @@ md_assemble (str) as_tsktsk ( _("Warning: Use of the 'nv' conditional is deprecated\n")); - inst.instruction |= cond->value; + cond_code = cond->value; r += 2; } else - inst.instruction |= COND_ALWAYS; + cond_code = COND_ALWAYS; } else - inst.instruction |= COND_ALWAYS; + cond_code = COND_ALWAYS; + + /* Apply the conditional, or complain it's not allowed. */ + if (opcode->comp_suffix && *opcode->comp_suffix == '\0') + { + /* Instruction isn't conditional */ + if (cond_code != COND_ALWAYS) + { + as_bad (_("Opcode `%s' is unconditional\n"), str); + return; + } + } + else + /* Instruction is conditional: set the condition into it. */ + inst.instruction |= cond_code; + /* If there is a compulsory suffix, it should come here, before any optional flags. */ - if (opcode->comp_suffix) + if (opcode->comp_suffix && *opcode->comp_suffix != '\0') { CONST char *s = opcode->comp_suffix; @@ -6223,7 +6281,7 @@ _("Warning: Use of the 'nv' conditional is deprecated\n")); if (regnum != FAIL) insert_reg_alias (str, regnum); else - as_warn (_("register '%s' does not exist"), q); + as_warn (_("register '%s' does not exist\n"), q); } else if (regnum != FAIL) { @@ -6260,7 +6318,7 @@ _("Warning: Use of the 'nv' conditional is deprecated\n")); * -m[arm]8[10] Arm 8 processors * -m[arm]9[20][tdmi] Arm 9 processors * -mstrongarm[110[0]] StrongARM processors - * -m[arm]v[2345] Arm architecures + * -m[arm]v[2345] Arm architectures * -mall All (except the ARM1) * FP variants: * -mfpa10, -mfpa11 FPA10 and 11 co-processor instructions @@ -6349,7 +6407,8 @@ md_parse_option (c, arg) } else if (streq (str, "thumb-interwork")) { - cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_THUMB | ARM_ARCH_V4; + if ((cpu_variant & ARM_THUMB) == 0) + cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_ARCH_V4T; #if defined OBJ_COFF || defined OBJ_ELF support_interwork = true; #endif @@ -6471,6 +6530,7 @@ md_parse_option (c, arg) case 70: case 700: case 710: + case 720: case 7100: case 7500: break; @@ -6527,6 +6587,7 @@ md_parse_option (c, arg) else goto bad; break; + case 's': if (streq (str, "strongarm") @@ -6571,13 +6632,13 @@ md_parse_option (c, arg) default: as_bad (_("Invalid architecture variant -m%s"), arg); break; } break; - + case '5': cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_ARCH_V5; - switch (*++str) { case 't': cpu_variant |= ARM_THUMB; break; + case 'e': cpu_variant |= ARM_EXT_V5E; break; case 0: break; default: as_bad (_("Invalid architecture variant -m%s"), arg); break; } @@ -6597,9 +6658,11 @@ md_parse_option (c, arg) } break; +#if defined OBJ_ELF || defined OBJ_COFF case 'k': pic_code = 1; break; +#endif default: return 0; @@ -6616,7 +6679,7 @@ md_show_usage (fp) _("\ ARM Specific Assembler Options:\n\ -m[arm][] select processor variant\n\ - -m[arm]v[2|2a|3|3m|4|4t|5]select architecture variant\n\ + -m[arm]v[2|2a|3|3m|4|4t|5[t][e]] select architecture variant\n\ -mthumb only allow Thumb instructions\n\ -mthumb-interwork mark the assembled code as supporting interworking\n\ -mall allow any instruction\n\ @@ -6980,7 +7043,7 @@ arm_parse_reloc () /* Added support for parsing "var(PLT)" branch instructions */ /* generated by GCC for PLT relocs */ MAP ("(plt)", BFD_RELOC_ARM_PLT32), - NULL, 0, BFD_RELOC_UNUSED + { NULL, 0, BFD_RELOC_UNUSED } #undef MAP };