aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDonald Lindsay <dlindsay@redhat.com>1999-11-16 04:15:55 +0000
committerDonald Lindsay <dlindsay@redhat.com>1999-11-16 04:15:55 +0000
commit92a66162a2507f0707996b707f22f27d62055bf8 (patch)
treed6273ca91029a1ff536219ab9dff337c80677ec8
parenteb726e5db16fc3d27fe4eee10d93324121486b2f (diff)
downloadgdb-92a66162a2507f0707996b707f22f27d62055bf8.zip
gdb-92a66162a2507f0707996b707f22f27d62055bf8.tar.gz
gdb-92a66162a2507f0707996b707f22f27d62055bf8.tar.bz2
tc-arm.c: minor changes and support for upcoming V5E variant.
-rw-r--r--gas/config/tc-arm.c103
1 files changed, 75 insertions, 28 deletions
diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c
index d842941..fa61988 100644
--- a/gas/config/tc-arm.c
+++ b/gas/config/tc-arm.c
@@ -52,11 +52,12 @@
#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)
#define ARM_ARCH_V4T (ARM_ARCH_V4 | ARM_THUMB)
-#define ARM_ARCH_V5 (ARM_ARCH_V4 | ARM_EXT_V5)
+#define ARM_ARCH_V5 (ARM_ARCH_V4 | ARM_EXT_V5 )
#define ARM_ARCH_V5T (ARM_ARCH_V5 | ARM_THUMB)
/* Some useful combinations: */
@@ -439,6 +440,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 +506,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 */
@@ -876,8 +883,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;
@@ -1360,7 +1369,7 @@ s_thumb_set (equiv)
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
}
@@ -3320,13 +3329,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
@@ -3487,6 +3498,10 @@ do_co_reg (str, flags)
return;
}
}
+ if (flags)
+ {
+ inst.error = BAD_COND;
+ }
end_of_line (str);
return;
@@ -4502,15 +4517,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)
@@ -5326,7 +5338,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);
@@ -5524,6 +5537,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);
{
@@ -6053,6 +6067,13 @@ md_assemble (str)
if (opcode)
{
+ /* Check that this instruction is supported for this CPU. */
+ if ((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);
@@ -6063,6 +6084,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
@@ -6089,11 +6111,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 <%s>\n"),
+ 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);
}
@@ -6101,7 +6130,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)
{
@@ -6117,18 +6146,34 @@ 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;
@@ -6228,7 +6273,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)
{
@@ -6265,7 +6310,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
@@ -6532,6 +6577,7 @@ md_parse_option (c, arg)
else
goto bad;
break;
+
case 's':
if (streq (str, "strongarm")
@@ -6576,17 +6622,18 @@ 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;
}
break;
+
default:
as_bad (_("Invalid architecture variant -m%s"), arg);