#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)
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;
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));
#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 */
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
#define REG_LR 14
#define REG_SP 13
-/* These are the standard names; Users can add aliases with .req */
+/* These are the standard names. Users can add aliases with .req */
static CONST struct reg_entry reg_table[] =
{
- /* Processor Register Numbers */
+ /* Processor Register Numbers. */
{"r0", 0}, {"r1", 1}, {"r2", 2}, {"r3", 3},
{"r4", 4}, {"r5", 5}, {"r6", 6}, {"r7", 7},
{"r8", 8}, {"r9", 9}, {"r10", 10}, {"r11", 11},
{"r12", 12}, {"r13", REG_SP},{"r14", REG_LR},{"r15", REG_PC},
- /* APCS conventions */
+ /* APCS conventions. */
{"a1", 0}, {"a2", 1}, {"a3", 2}, {"a4", 3},
{"v1", 4}, {"v2", 5}, {"v3", 6}, {"v4", 7}, {"v5", 8},
{"v6", 9}, {"sb", 9}, {"v7", 10}, {"sl", 10},
{"fp", 11}, {"ip", 12}, {"sp", REG_SP},{"lr", REG_LR},{"pc", REG_PC},
- /* FP Registers */
+ /* ATPCS additions to APCS conventions. */
+ {"wr", 7}, {"v8", 11},
+ /* FP Registers. */
{"f0", 16}, {"f1", 17}, {"f2", 18}, {"f3", 19},
{"f4", 20}, {"f5", 21}, {"f6", 22}, {"f7", 23},
{"c0", 32}, {"c1", 33}, {"c2", 34}, {"c3", 35},
{"cr4", 36}, {"cr5", 37}, {"cr6", 38}, {"cr7", 39},
{"cr8", 40}, {"cr9", 41}, {"cr10", 42}, {"cr11", 43},
{"cr12", 44}, {"cr13", 45}, {"cr14", 46}, {"cr15", 47},
+ /* ATPCS additions to float register names. */
+ {"s0",16}, {"s1",17}, {"s2",18}, {"s3",19},
+ {"s4",20}, {"s5",21}, {"s6",22}, {"s7",23},
+ {"d0",16}, {"d1",17}, {"d2",18}, {"d3",19},
+ {"d4",20}, {"d5",21}, {"d6",22}, {"d7",23},
+ /* FIXME: At some point we need to add VFP register names. */
+ /* Array terminator. */
{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;
if (! thumb_mode)
{
- thumb_mode = 1;
+ thumb_mode = 2;
record_alignment (now_seg, 1);
}
THUMB_SET_FUNC (symbolP, 1);
ARM_SET_THUMB (symbolP, 1);
-#if defined OBJ_COFF || defined OBJ_ELF
+#if defined OBJ_ELF || defined OBJ_COFF
ARM_SET_INTERWORK (symbolP, support_interwork);
#endif
}
if (now_seg != text_section)
s_ltorg (0);
+#ifdef OBJ_ELF
+ obj_elf_text (ignore);
+#else
s_text (ignore);
+#endif
}
static void
else if (now_seg != data_section)
s_ltorg (0);
+#ifdef OBJ_ELF
+ obj_elf_data (ignore);
+#else
s_data (ignore);
+#endif
}
#ifdef OBJ_ELF
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)
if (reg_required_here (&str, 12) == FAIL)
{
- inst.error = bad_args;
+ inst.error = BAD_ARGS;
return;
}
if (skip_past_comma (&str) == FAIL
|| (reg = reg_required_here (&str, 0)) == FAIL)
{
- inst.error = bad_args;
+ inst.error = BAD_ARGS;
return;
}
}
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;
}
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;
}
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;
}
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;
}
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;
}
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;
}
|| 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;
}
|| data_op2 (&str) == FAIL)
{
if (!inst.error)
- inst.error = bad_args;
+ inst.error = BAD_ARGS;
return;
}
|| 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
|| my_get_expression (& inst.reloc.exp, & str))
{
if (!inst.error)
- inst.error = bad_args;
+ inst.error = BAD_ARGS;
return;
}
if (reg_required_here (&str, 16) == FAIL)
{
if (!inst.error)
- inst.error = bad_args;
+ inst.error = BAD_ARGS;
return;
}
|| data_op2 (&str) == FAIL)
{
if (!inst.error)
- inst.error = bad_args;
+ inst.error = BAD_ARGS;
return;
}
if (reg_required_here (&str, 12) == FAIL)
{
if (!inst.error)
- inst.error = bad_args;
+ inst.error = BAD_ARGS;
return;
}
|| data_op2 (&str) == FAIL)
{
if (!inst.error)
- inst.error = bad_args;
+ inst.error = BAD_ARGS;
return;
}
if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
{
if (!inst.error)
- inst.error = bad_args;
+ inst.error = BAD_ARGS;
return;
}
|| (range = reg_list (&str)) == FAIL)
{
if (! inst.error)
- inst.error = bad_args;
+ inst.error = BAD_ARGS;
return;
}
|| (reg = reg_required_here (&str, 0)) == FAIL)
{
if (!inst.error)
- inst.error = bad_args;
+ inst.error = BAD_ARGS;
return;
}
if (skip_past_comma (&str) == FAIL
|| *str++ != '[')
{
- inst.error = bad_args;
+ inst.error = BAD_ARGS;
return;
}
if (reg == REG_PC)
{
- inst.error = bad_pc;
+ inst.error = BAD_PC;
return;
}
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
if (co_proc_number (&str) == FAIL)
{
if (!inst.error)
- inst.error = bad_args;
+ inst.error = BAD_ARGS;
return;
}
|| cp_opc_expr (&str, 20,4) == FAIL)
{
if (!inst.error)
- inst.error = bad_args;
+ inst.error = BAD_ARGS;
return;
}
|| cp_reg_required_here (&str, 12) == FAIL)
{
if (!inst.error)
- inst.error = bad_args;
+ inst.error = BAD_ARGS;
return;
}
|| cp_reg_required_here (&str, 16) == FAIL)
{
if (!inst.error)
- inst.error = bad_args;
+ inst.error = BAD_ARGS;
return;
}
|| cp_reg_required_here (&str, 0) == FAIL)
{
if (!inst.error)
- inst.error = bad_args;
+ inst.error = BAD_ARGS;
return;
}
if (cp_opc_expr (&str, 5, 3) == FAIL)
{
if (!inst.error)
- inst.error = bad_args;
+ inst.error = BAD_ARGS;
return;
}
}
if (co_proc_number (&str) == FAIL)
{
if (!inst.error)
- inst.error = bad_args;
+ inst.error = BAD_ARGS;
return;
}
|| cp_reg_required_here (&str, 12) == FAIL)
{
if (!inst.error)
- inst.error = bad_args;
+ inst.error = BAD_ARGS;
return;
}
|| cp_address_required_here (&str) == FAIL)
{
if (! inst.error)
- inst.error = bad_args;
+ inst.error = BAD_ARGS;
return;
}
if (co_proc_number (&str) == FAIL)
{
if (!inst.error)
- inst.error = bad_args;
+ inst.error = BAD_ARGS;
return;
}
|| cp_opc_expr (&str, 21, 3) == FAIL)
{
if (!inst.error)
- inst.error = bad_args;
+ inst.error = BAD_ARGS;
return;
}
|| reg_required_here (&str, 12) == FAIL)
{
if (!inst.error)
- inst.error = bad_args;
+ inst.error = BAD_ARGS;
return;
}
|| cp_reg_required_here (&str, 16) == FAIL)
{
if (!inst.error)
- inst.error = bad_args;
+ inst.error = BAD_ARGS;
return;
}
|| cp_reg_required_here (&str, 0) == FAIL)
{
if (!inst.error)
- inst.error = bad_args;
+ inst.error = BAD_ARGS;
return;
}
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;
if (reg_required_here (&str, 12) == FAIL)
{
if (!inst.error)
- inst.error = bad_args;
+ inst.error = BAD_ARGS;
return;
}
if (fp_reg_required_here (&str, 12) == FAIL)
{
if (!inst.error)
- inst.error = bad_args;
+ inst.error = BAD_ARGS;
return;
}
|| cp_address_required_here (&str) == FAIL)
{
if (!inst.error)
- inst.error = bad_args;
+ inst.error = BAD_ARGS;
return;
}
if (fp_reg_required_here (&str, 12) == FAIL)
{
if (! inst.error)
- inst.error = bad_args;
+ inst.error = BAD_ARGS;
return;
}
|| *str != '[')
{
if (! inst.error)
- inst.error = bad_args;
+ inst.error = BAD_ARGS;
return;
}
if (*str != ']')
{
- inst.error = bad_args;
+ inst.error = BAD_ARGS;
return;
}
|| cp_address_required_here (&str) == FAIL)
{
if (! inst.error)
- inst.error = bad_args;
+ inst.error = BAD_ARGS;
return;
}
if (fp_reg_required_here (&str, 12) == FAIL)
{
if (! inst.error)
- inst.error = bad_args;
+ inst.error = BAD_ARGS;
return;
}
|| fp_reg_required_here (&str, 16) == FAIL)
{
if (! inst.error)
- inst.error = bad_args;
+ inst.error = BAD_ARGS;
return;
}
|| fp_op2 (&str) == FAIL)
{
if (! inst.error)
- inst.error = bad_args;
+ inst.error = BAD_ARGS;
return;
}
if (fp_reg_required_here (&str, 12) == FAIL)
{
if (! inst.error)
- inst.error = bad_args;
+ inst.error = BAD_ARGS;
return;
}
|| fp_op2 (&str) == FAIL)
{
if (! inst.error)
- inst.error = bad_args;
+ inst.error = BAD_ARGS;
return;
}
if (fp_reg_required_here (&str, 16) == FAIL)
{
if (! inst.error)
- inst.error = bad_args;
+ inst.error = BAD_ARGS;
return;
}
|| fp_op2 (&str) == FAIL)
{
if (! inst.error)
- inst.error = bad_args;
+ inst.error = BAD_ARGS;
return;
}
if (fp_reg_required_here (&str, 16) == FAIL)
{
if (! inst.error)
- inst.error = bad_args;
+ inst.error = BAD_ARGS;
return;
}
|| reg_required_here (&str, 12) == FAIL)
{
if (! inst.error)
- inst.error = bad_args;
+ inst.error = BAD_ARGS;
return;
}
|| fp_reg_required_here (&str, 0) == FAIL)
{
if (! inst.error)
- inst.error = bad_args;
+ inst.error = BAD_ARGS;
return;
}
|| skip_past_comma (&str) == FAIL)
{
if (! inst.error)
- inst.error = bad_args;
+ inst.error = BAD_ARGS;
return;
}
|| skip_past_comma (&str) == FAIL)
{
if (! inst.error)
- inst.error = bad_args;
+ inst.error = BAD_ARGS;
return;
}
|| skip_past_comma (&str) == FAIL)
{
if (! inst.error)
- inst.error = bad_args;
+ inst.error = BAD_ARGS;
return;
}
|| skip_past_comma (&str) == FAIL)
{
if (! inst.error)
- inst.error = bad_args;
+ inst.error = BAD_ARGS;
return;
}
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)
|| inst.instruction == T_OPCODE_NEG
|| inst.instruction == T_OPCODE_MVN)
{
- inst.error = bad_args;
+ inst.error = BAD_ARGS;
return;
}
|| (range = reg_list (&str)) == FAIL)
{
if (! inst.error)
- inst.error = bad_args;
+ inst.error = BAD_ARGS;
return;
}
if ((range = reg_list (&str)) == FAIL)
{
if (! inst.error)
- inst.error = bad_args;
+ inst.error = BAD_ARGS;
return;
}
|| my_get_expression (&inst.reloc.exp, &str))
{
if (!inst.error)
- inst.error = bad_args;
+ inst.error = BAD_ARGS;
return;
}
&& 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);
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);
{
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);
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
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);
}
return;
}
- /* Now check for a conditional. */
+ /* Not just a simple opcode. Check if extra is a conditional. */
r = q;
if (p - r >= 2)
{
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;
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)
{
* -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
}
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
case 70:
case 700:
case 710:
+ case 720:
case 7100:
case 7500:
break;
else
goto bad;
break;
+
case 's':
if (streq (str, "strongarm")
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;
}
_("\
ARM Specific Assembler Options:\n\
-m[arm][<processor name>] 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\
{
if (ARM_IS_THUMB (sym))
{
+ elf_sym = elf_symbol (symbol_get_bfdsym (sym));
+ bind = ELF_ST_BIND (elf_sym);
+
+ /* If it's a .thumb_func, declare it as so, else tag label as .code 16. */
if (THUMB_IS_FUNC (sym))
- {
- elf_sym = elf_symbol (symbol_get_bfdsym (sym));
- bind = ELF_ST_BIND (elf_sym);
- elf_sym->internal_elf_sym.st_info = ELF_ST_INFO (bind, STT_ARM_TFUNC);
- }
+ elf_sym->internal_elf_sym.st_info = ELF_ST_INFO (bind, STT_ARM_TFUNC);
+ else
+ elf_sym->internal_elf_sym.st_info = ELF_ST_INFO (bind, STT_ARM_16BIT);
}
}
#endif
/* 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
};