#define THUMB_SIZE 2 /* Size of thumb instruction. */
#define THUMB_PP_PC_LR 0x0100
#define THUMB_LOAD_BIT 0x0800
+#define THUMB2_LOAD_BIT 0x00100000
#define BAD_ARGS _("bad arguments to instruction")
#define BAD_PC _("r15 not allowed here")
as_bad (_("expected <tag> , <value>"));
ignore_rest_of_line ();
}
+#endif /* OBJ_ELF */
static void s_arm_arch (int);
static void s_arm_cpu (int);
static void s_arm_fpu (int);
-#endif /* OBJ_ELF */
/* This table describes all the machine specific pseudo-ops the assembler
has to support. The fields are:
{ "ltorg", s_ltorg, 0 },
{ "pool", s_ltorg, 0 },
{ "syntax", s_syntax, 0 },
+ { "cpu", s_arm_cpu, 0 },
+ { "arch", s_arm_arch, 0 },
+ { "fpu", s_arm_fpu, 0 },
#ifdef OBJ_ELF
{ "word", s_arm_elf_cons, 4 },
{ "long", s_arm_elf_cons, 4 },
{ "pad", s_arm_unwind_pad, 0 },
{ "setfp", s_arm_unwind_setfp, 0 },
{ "unwind_raw", s_arm_unwind_raw, 0 },
- { "cpu", s_arm_cpu, 0 },
- { "arch", s_arm_arch, 0 },
- { "fpu", s_arm_fpu, 0 },
{ "eabi_attribute", s_arm_eabi_attribute, 0 },
#else
{ "word", cons, 4},
int reg;
if (skip_past_char (&p, '[') == FAIL)
- return FAIL;
+ {
+ inst.error = _("'[' expected");
+ return FAIL;
+ }
if ((reg = arm_reg_parse (&p, REG_TYPE_RN)) == FAIL)
{
inst.operands[0].reg = reg;
if (skip_past_comma (&p) == FAIL)
- return FAIL;
+ {
+ inst.error = _("',' expected");
+ return FAIL;
+ }
if ((reg = arm_reg_parse (&p, REG_TYPE_RN)) == FAIL)
{
failure:
if (!backtrack_pos)
- return FAIL;
+ {
+ /* The parse routine should already have set inst.error, but set a
+ defaut here just in case. */
+ if (!inst.error)
+ inst.error = _("syntax error");
+ return FAIL;
+ }
/* Do not backtrack over a trailing optional argument that
absorbed some text. We will only fail again, with the
probably less helpful than the current one. */
if (backtrack_index == i && backtrack_pos != str
&& upat[i+1] == OP_stop)
- return FAIL;
+ {
+ if (!inst.error)
+ inst.error = _("syntax error");
+ return FAIL;
+ }
/* Try again, skipping the optional argument at backtrack_pos. */
str = backtrack_pos;
static int
move_or_literal_pool (int i, bfd_boolean thumb_p, bfd_boolean mode_3)
{
- if ((inst.instruction & (thumb_p ? THUMB_LOAD_BIT : LOAD_BIT)) == 0)
+ unsigned long tbit;
+
+ if (thumb_p)
+ tbit = (inst.instruction > 0xffff) ? THUMB2_LOAD_BIT : THUMB_LOAD_BIT;
+ else
+ tbit = LOAD_BIT;
+
+ if ((inst.instruction & tbit) == 0)
{
inst.error = _("invalid pseudo operation");
return 1;
{
if (thumb_p)
{
- if ((inst.reloc.exp.X_add_number & ~0xFF) == 0)
+ if (!unified_syntax && (inst.reloc.exp.X_add_number & ~0xFF) == 0)
{
/* This can be done with a mov(1) instruction. */
inst.instruction = T_OPCODE_MOV_I8 | (inst.operands[i].reg << 8);
bfd_boolean is_pc = (inst.operands[i].reg == REG_PC);
constraint (!inst.operands[i].isreg,
- _("Thumb does not support the ldr =N pseudo-operation"));
+ _("Instruction does not support =N addresses"));
inst.instruction |= inst.operands[i].reg << 16;
if (inst.operands[i].immisreg)
opcode = inst.instruction;
if (unified_syntax)
{
+ if (!inst.operands[1].isreg)
+ {
+ if (opcode <= 0xffff)
+ inst.instruction = THUMB_OP32 (opcode);
+ if (move_or_literal_pool (0, /*thumb_p=*/TRUE, /*mode_3=*/FALSE))
+ return;
+ }
if (inst.operands[1].isreg
&& !inst.operands[1].writeback
&& !inst.operands[1].shifted && !inst.operands[1].postind
{
newval = md_chars_to_number (buf, INSN_SIZE);
newval |= (value >> 2) & 0x00ffffff;
+ /* Set the H bit on BLX instructions. */
+ if (temp == 1)
+ {
+ if (value & 2)
+ newval |= 0x01000000;
+ else
+ newval &= ~0x01000000;
+ }
md_number_to_chars (buf, newval, INSN_SIZE);
}
break;
p = frag_more (size);
elf32_arm_set_eabi_attr_contents (stdoutput, (bfd_byte *)p, size);
}
+#endif /* OBJ_ELF */
/* Parse a .cpu directive. */
*input_line_pointer = saved_char;
ignore_rest_of_line ();
}
-#endif /* OBJ_ELF */