This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
Thumb32 assembler (5/69)
- From: Zack Weinberg <zack at codesourcery dot com>
- To: binutils <binutils at sourceware dot org>
- Date: Tue, 26 Apr 2005 02:52:52 -0700
- Subject: Thumb32 assembler (5/69)
This introduces a less cumbersome, macro-based notation for the very
common operation of trying to parse something, and if that failed,
setting inst.error and returning. Also, more redundant do_* functions
are collapsed together, and the i18n friendliness of some diagnostics
is improved.
zw
* config/tc-arm.c (ERR_NO_ACCUM): Rename BAD_ACCUM.
(my_get_expression): Set inst.error here ...
(md_operand): ... not here.
(accum0_required_here): Rename to xsc_reg_required_here.
Avoid modifying input stream.
(comma_or_fail, expression_or_fail, immediate_or_fail)
(reg_or_fail, note_reg_or_fail): New convenience macros.
(do_adr, do_adrl, do_arit, bfci_lsb_and_width, do_bfc, do_bfi)
(do_bfx, do_branch, do_branch25, do_blx, do_cdp, do_clz, do_cmp)
(do_co_reg, do_co_reg2c, do_ldrex, do_ldst, do_ldstt, do_ldstv4)
(do_ldsttv4, do_lstc, do_mlas, do_mov, do_mov16, do_mrs, do_mul)
(do_mull, do_pkh_core, do_pld, do_qadd, do_qadd16, do_rbit, do_rev)
(do_rfe, do_sat, do_sat16, do_smla, do_smlal, do_smul, do_strex)
(do_swap, do_sxtah, do_sxth, do_vfp_reg_from_sp, do_vfp_reg_from_ctrl)
(vfp_sp_ldstm, vfp_dp_ldstm, do_fpa_ctrl, do_fpa_to_reg, do_xsc_mia)
(do_xsc_mar, do_xsc_mra): Use new convenience macros.
(do_ldst, do_ldstt, do_ldstv4, do_ldsttv4):
Do not translate words in isolation from their sentences.
(do_sat, do_sat16): Take char *, not char **, argument.
Call end_of_line here.
(do_ssat, do_usat, do_ssat16, do_usat16): Adjust to match.
(do_cdp2, do_co_reg2, do_lstc2): Delete.
(insns): Replace do_cdp2, do_co_reg2, and do_lstc2 with
do_cdp, do_co_reg, and do_lstc respectively.
===================================================================
Index: gas/config/tc-arm.c
--- gas/config/tc-arm.c (revision 5)
+++ gas/config/tc-arm.c (revision 6)
@@ -938,7 +938,7 @@
#define BAD_ARGS _("bad arguments to instruction")
#define BAD_PC _("r15 not allowed here")
#define BAD_COND _("instruction is not conditional")
-#define ERR_NO_ACCUM _("acc0 expected")
+#define BAD_ACCUM _("acc0 expected")
static struct hash_control * arm_ops_hsh = NULL;
static struct hash_control * arm_tops_hsh = NULL;
@@ -1040,6 +1040,15 @@
return comma ? SUCCESS : FAIL;
}
+#define comma_or_fail(str) \
+do { \
+ if (skip_past_comma (str) == FAIL) \
+ { \
+ inst.error = BAD_ARGS; \
+ return; \
+ } \
+ } while (0)
+
/* Arithmetic expressions (possibly involving symbols). */
/* Return TRUE if anything in the expression is a bignum. */
@@ -1081,6 +1090,8 @@
/* We found a bad expression in md_operand(). */
*str = input_line_pointer;
input_line_pointer = save_in;
+ if (inst.error == NULL)
+ inst.error = _("bad expression");
return 1;
}
@@ -1091,7 +1102,7 @@
&& seg != bss_section
&& seg != undefined_section)
{
- inst.error = _("bad_segment");
+ inst.error = _("bad segment");
*str = input_line_pointer;
input_line_pointer = save_in;
return 1;
@@ -1118,6 +1129,12 @@
return 0;
}
+#define expression_or_fail(exp, str) \
+do { \
+ if (my_get_expression (exp, str)) \
+ return; \
+ } while (0)
+
/* Turn a string in input_line_pointer into a floating point constant
of type TYPE, and store the appropriate bytes in *LITP. The number
of LITTLENUMS emitted is stored in *SIZEP. An error message is
@@ -1281,11 +1298,7 @@
md_operand (expressionS * expr)
{
if (in_my_get_expression)
- {
- expr->X_op = O_illegal;
- if (inst.error == NULL)
- inst.error = _("bad expression");
- }
+ expr->X_op = O_illegal;
}
/* Immediate values. */
@@ -1329,6 +1342,12 @@
return SUCCESS;
}
+#define immediate_or_fail(str, var, min, max, popt) \
+do { \
+ if (immediate_required_here (str, var, min, max, popt) == FAIL) \
+ return; \
+ } while (0)
+
/* As above, but for use in directives, and does not provide
range checking. */
@@ -1515,7 +1534,18 @@
return FAIL;
}
+#define reg_or_fail(str, shift, no_pc) \
+do { \
+ if (reg_required_here (str, shift, no_pc) == FAIL) \
+ return; \
+ } while (0)
+#define note_reg_or_fail(var, str, shift, no_pc) \
+do { \
+ if ((var = reg_required_here (str, shift, no_pc)) == FAIL) \
+ return; \
+ } while (0)
+
/* Parse and validate that a register is of the right form, this saves
repeated checking of this information in many similar cases.
Unlike the 32-bit case we do not insert the register into the opcode
@@ -1788,32 +1818,17 @@
At that time this routine and its callers can be upgraded to suit.) */
static int
-accum0_required_here (char ** str)
+xsc_reg_required_here (char ** str)
{
- static char buff [128]; /* Note the address is taken. Hence, static. */
- char * p = * str;
- char c;
- int result = 0; /* The accum number. */
+ skip_whitespace (*str);
- skip_whitespace (p);
-
- *str = p; /* Advance caller's string pointer too. */
- c = *p++;
- while (ISALNUM (c))
- c = *p++;
-
- *--p = 0; /* Aap nul into input buffer at non-alnum. */
-
- if (! ( streq (*str, "acc0") || streq (*str, "ACC0")))
+ if (strncasecmp (*str, "acc0", 4) != 0 || ISALNUM ((*str)[4]))
{
- sprintf (buff, _("acc0 expected, not '%.100s'"), *str);
- inst.error = buff;
- result = FAIL;
+ inst.error = BAD_ACCUM;
+ return FAIL;
}
-
- *p = c; /* Unzap. */
- *str = p; /* Caller's string pointer to after match. */
- return result;
+ *str += 4;
+ return 0;
}
/* Register lists. */
@@ -5025,17 +5040,13 @@
{
/* This is a pseudo-op of the form "adr rd, label" to be converted
into a relative address of the form "add rd, pc, #label-.-8". */
+
skip_whitespace (str);
+ reg_or_fail (&str, 12, FALSE);
+ comma_or_fail (&str);
+ expression_or_fail (&inst.reloc.exp, &str);
+ end_of_line (str);
- if (reg_required_here (&str, 12, FALSE) == FAIL
- || skip_past_comma (&str) == FAIL
- || my_get_expression (&inst.reloc.exp, &str))
- {
- if (!inst.error)
- inst.error = BAD_ARGS;
- return;
- }
-
/* Frag hacking will turn this into a sub instruction if the offset turns
out to be negative. */
inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
@@ -5043,8 +5054,6 @@
inst.reloc.exp.X_add_number -= 8; /* PC relative adjust. */
#endif
inst.reloc.pc_rel = 1;
-
- end_of_line (str);
}
static void
@@ -5056,18 +5065,11 @@
add rd, rd, #high(label-.-8)" */
skip_whitespace (str);
-
- if (reg_required_here (&str, 12, FALSE) == FAIL
- || skip_past_comma (&str) == FAIL
- || my_get_expression (&inst.reloc.exp, &str))
- {
- if (!inst.error)
- inst.error = BAD_ARGS;
-
- return;
- }
-
+ reg_or_fail (&str, 12, FALSE);
+ comma_or_fail (&str);
+ expression_or_fail (&inst.reloc.exp, &str);
end_of_line (str);
+
/* Frag hacking will turn this into a sub instruction if the offset turns
out to be negative. */
inst.reloc.type = BFD_RELOC_ARM_ADRL_IMMEDIATE;
@@ -5082,12 +5084,12 @@
do_arit (char * str)
{
skip_whitespace (str);
+ reg_or_fail (&str, 12, FALSE);
+ comma_or_fail (&str);
+ reg_or_fail (&str, 16, FALSE);
+ comma_or_fail (&str);
- if (reg_required_here (&str, 12, FALSE) == FAIL
- || skip_past_comma (&str) == FAIL
- || reg_required_here (&str, 16, FALSE) == FAIL
- || skip_past_comma (&str) == FAIL
- || data_op2 (&str) == FAIL)
+ if (data_op2 (&str) == FAIL)
{
if (!inst.error)
inst.error = BAD_ARGS;
@@ -5102,17 +5104,10 @@
{
int lsb, width;
- if (immediate_required_here (&str, &lsb, 0, 31, FALSE) == FAIL)
- return;
-
- if (skip_past_comma (&str) == FAIL)
- {
- inst.error = BAD_ARGS;
- return;
- }
- if (immediate_required_here (&str, &width, 1, 32, FALSE) == FAIL)
- return;
-
+ comma_or_fail (&str);
+ immediate_or_fail (&str, &lsb, 0, 31, FALSE);
+ comma_or_fail (&str);
+ immediate_or_fail (&str, &width, 1, 32, FALSE);
end_of_line (str);
if (width + lsb > 32)
@@ -5129,16 +5124,8 @@
static void
do_bfc (char *str)
{
- /* Rd. */
skip_whitespace (str);
- if (reg_required_here (&str, 12, TRUE) == FAIL)
- return;
- if (skip_past_comma (&str) == FAIL)
- {
- inst.error = BAD_ARGS;
- return;
- }
-
+ reg_or_fail (&str, 12, TRUE);
bfci_lsb_and_width (str);
}
@@ -5147,33 +5134,19 @@
{
/* Rd. */
skip_whitespace (str);
- if (reg_required_here (&str, 12, TRUE) == FAIL)
- return;
- if (skip_past_comma (&str) == FAIL)
- {
- inst.error = BAD_ARGS;
- return;
- }
+ reg_or_fail (&str, 12, TRUE);
+ comma_or_fail (&str);
/* Rm. Accept #0 in this position as an alternative syntax for bfc. */
- skip_whitespace (str);
- if (is_immediate_prefix (*str))
+ if (reg_required_here (&str, 0, TRUE) == FAIL)
{
- int val;
- if (immediate_required_here (&str, &val, 0, 0, FALSE) == FAIL)
+ int dummy;
+
+ inst.error = 0;
+ if (immediate_required_here (&str, &dummy, 0, 0, FALSE) == FAIL)
return;
inst.instruction |= 0x0000000f; /* Rm = PC -> bfc, not bfi. */
}
- else
- {
- if (reg_required_here (&str, 0, TRUE) == FAIL)
- return;
- }
- if (skip_past_comma (&str) == FAIL)
- {
- inst.error = BAD_ARGS;
- return;
- }
bfci_lsb_and_width (str);
}
@@ -5185,34 +5158,17 @@
/* Rd. */
skip_whitespace (str);
- if (reg_required_here (&str, 12, FALSE) == FAIL)
- return;
- if (skip_past_comma (&str) == FAIL)
- {
- inst.error = BAD_ARGS;
- return;
- }
+ reg_or_fail (&str, 12, FALSE);
+ comma_or_fail (&str);
/* Rm. */
- skip_whitespace (str);
- if (reg_required_here (&str, 0, FALSE) == FAIL
- || skip_past_comma (&str) == FAIL)
- {
- inst.error = BAD_ARGS;
- return;
- }
+ reg_or_fail (&str, 0, FALSE);
+ comma_or_fail (&str);
- if (immediate_required_here (&str, &lsb, 0, 31, FALSE) == FAIL)
- return;
-
- if (skip_past_comma (&str) == FAIL)
- {
- inst.error = BAD_ARGS;
- return;
- }
- if (immediate_required_here (&str, &width, 1, 32, FALSE) == FAIL)
- return;
-
+ /* lsb, width. */
+ immediate_or_fail (&str, &lsb, 0, 31, FALSE);
+ comma_or_fail (&str);
+ immediate_or_fail (&str, &width, 1, 32, FALSE);
end_of_line (str);
if (width + lsb > 32)
@@ -5255,8 +5211,7 @@
static void
do_branch (char * str)
{
- if (my_get_expression (&inst.reloc.exp, &str))
- return;
+ expression_or_fail (&inst.reloc.exp, &str);
#ifdef OBJ_ELF
{
@@ -5303,8 +5258,7 @@
static void
do_branch25 (char * str)
{
- if (my_get_expression (& inst.reloc.exp, & str))
- return;
+ expression_or_fail (&inst.reloc.exp, &str);
#ifdef OBJ_ELF
{
@@ -5351,18 +5305,12 @@
int reg;
skip_whitespace (str);
+ note_reg_or_fail (reg, &str, 0, FALSE);
+ end_of_line (str);
- if ((reg = reg_required_here (&str, 0, FALSE)) == FAIL)
- {
- inst.error = BAD_ARGS;
- return;
- }
-
/* Note - it is not illegal to do a "bx pc". Useless, but not illegal. */
if (reg == REG_PC)
as_tsktsk (_("use of r15 in bx in ARM mode is not really useful"));
-
- end_of_line (str);
}
/* ARM V5 branch-link-exchange instruction (argument parse)
@@ -5376,26 +5324,25 @@
static void
do_blx (char * str)
{
- char * mystr = str;
int rm;
- skip_whitespace (mystr);
- rm = reg_required_here (& mystr, 0, FALSE);
+ skip_whitespace (str);
+ rm = reg_required_here (&str, 0, FALSE);
- /* The above may set inst.error. Ignore his opinion. */
- inst.error = 0;
-
if (rm != FAIL)
{
- /* Arg is a register.
- Use the condition code our caller put in inst.instruction.
- Pass ourselves off as a BX with a funny opcode. */
+ /* Arg is a register. Use the condition code our caller put in
+ inst.instruction, and zap the opcode. */
inst.instruction |= 0x012fff30;
- do_bx (str);
+
+ /* It is not illegal to do "blx pc", just useless. */
+ if (rm == REG_PC)
+ as_tsktsk (_("use of r15 in blx in ARM mode is not really useful"));
+ end_of_line (str);
}
else
{
- /* This must be is BLX <target address>, no condition allowed. */
+ /* This must be BLX <target address>, no condition allowed. */
if (inst.instruction != COND_ALWAYS)
{
inst.error = BAD_COND;
@@ -5418,135 +5365,49 @@
int reg;
skip_whitespace (str);
+ note_reg_or_fail (reg, &str, 0, FALSE);
+ end_of_line (str);
- if ((reg = reg_required_here (&str, 0, FALSE)) == FAIL)
- return;
-
/* Note - it is not illegal to do a "bxj pc". Useless, but not illegal. */
if (reg == REG_PC)
as_tsktsk (_("use of r15 in bxj is not really useful"));
-
- end_of_line (str);
}
+/* Co-processor data operation:
+ CDP{cond} <coproc>, <opcode_1>, <CRd>, <CRn>, <CRm>{, <opcode_2>}
+ CDP2 <coproc>, <opcode_1>, <CRd>, <CRn>, <CRm>{, <opcode_2>} */
static void
do_cdp (char * str)
{
- /* Co-processor data operation.
- Format: CDP{cond} CP#,<expr>,CRd,CRn,CRm{,<expr>} */
skip_whitespace (str);
if (co_proc_number (&str) == FAIL)
- {
- if (!inst.error)
- inst.error = BAD_ARGS;
- return;
- }
+ return;
- if (skip_past_comma (&str) == FAIL
- || cp_opc_expr (&str, 20,4) == FAIL)
- {
- if (!inst.error)
- inst.error = BAD_ARGS;
- return;
- }
+ comma_or_fail (&str);
- if (skip_past_comma (&str) == FAIL
- || cp_reg_required_here (&str, 12) == FAIL)
- {
- if (!inst.error)
- inst.error = BAD_ARGS;
- return;
- }
+ if (cp_opc_expr (&str, 20, 4) == FAIL)
+ return;
- if (skip_past_comma (&str) == FAIL
- || cp_reg_required_here (&str, 16) == FAIL)
- {
- if (!inst.error)
- inst.error = BAD_ARGS;
- return;
- }
+ comma_or_fail (&str);
- if (skip_past_comma (&str) == FAIL
- || cp_reg_required_here (&str, 0) == FAIL)
- {
- if (!inst.error)
- inst.error = BAD_ARGS;
- return;
- }
+ if (cp_reg_required_here (&str, 12) == FAIL)
+ return;
- if (skip_past_comma (&str) == SUCCESS)
- {
- if (cp_opc_expr (&str, 5, 3) == FAIL)
- {
- if (!inst.error)
- inst.error = BAD_ARGS;
- return;
- }
- }
+ comma_or_fail (&str);
- end_of_line (str);
-}
+ if (cp_reg_required_here (&str, 16) == FAIL)
+ return;
-/* ARM V5 (argument parse)
- CDP2 <coproc>, <opcode_1>, <CRd>, <CRn>, <CRm>, <opcode_2>
- Instruction is not conditional, and has 0xf in the condition field.
- Otherwise, it's the same as CDP. */
+ comma_or_fail (&str);
+
+ if (cp_reg_required_here (&str, 0) == FAIL)
+ return;
-static void
-do_cdp2 (char * str)
-{
- skip_whitespace (str);
-
- if (co_proc_number (& str) == FAIL)
- {
- if (!inst.error)
- inst.error = BAD_ARGS;
+ if (skip_past_comma (&str) == SUCCESS)
+ if (cp_opc_expr (&str, 5, 3) == FAIL)
return;
- }
- if (skip_past_comma (& str) == FAIL
- || cp_opc_expr (& str, 20,4) == FAIL)
- {
- if (!inst.error)
- inst.error = BAD_ARGS;
- return;
- }
-
- if (skip_past_comma (& str) == FAIL
- || cp_reg_required_here (& str, 12) == FAIL)
- {
- if (!inst.error)
- inst.error = BAD_ARGS;
- return;
- }
-
- if (skip_past_comma (& str) == FAIL
- || cp_reg_required_here (& str, 16) == FAIL)
- {
- if (!inst.error)
- inst.error = BAD_ARGS;
- return;
- }
-
- if (skip_past_comma (& str) == FAIL
- || cp_reg_required_here (& str, 0) == FAIL)
- {
- if (!inst.error)
- inst.error = BAD_ARGS;
- return;
- }
-
- if (skip_past_comma (& str) == SUCCESS)
- {
- if (cp_opc_expr (& str, 5, 3) == FAIL)
- {
- if (!inst.error)
- inst.error = BAD_ARGS;
- return;
- }
- }
-
end_of_line (str);
}
@@ -5560,16 +5421,9 @@
{
skip_whitespace (str);
- if (reg_required_here (& str, 12, TRUE) == FAIL)
- return;
- if (skip_past_comma (& str) == FAIL)
- {
- inst.error = BAD_ARGS;
- return;
- }
- if (reg_required_here (& str, 0, TRUE) == FAIL)
- return;
-
+ reg_or_fail (&str, 12, TRUE);
+ comma_or_fail (&str);
+ reg_or_fail (&str, 0, TRUE);
end_of_line (str);
}
@@ -5578,11 +5432,10 @@
{
skip_whitespace (str);
- if (reg_required_here (&str, 16, FALSE) == FAIL)
- return;
+ reg_or_fail (&str, 16, FALSE);
+ comma_or_fail (&str);
- if (skip_past_comma (&str) == FAIL
- || data_op2 (&str) == FAIL)
+ if (data_op2 (&str) == FAIL)
{
if (!inst.error)
inst.error = BAD_ARGS;
@@ -5592,189 +5445,85 @@
end_of_line (str);
}
+/* Transfer between coprocessor and ARM registers.
+ MRC{cond} <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>{, <opcode_2>}
+ MRC2
+ MCR{cond}
+ MCR2
+
+ No special properties. */
+
static void
do_co_reg (char * str)
{
- /* Co-processor register transfer.
- Format: <MCR|MRC>{cond} CP#,<expr1>,Rd,CRn,CRm{,<expr2>} */
-
skip_whitespace (str);
if (co_proc_number (&str) == FAIL)
- {
- if (!inst.error)
- inst.error = BAD_ARGS;
- return;
- }
+ return;
- if (skip_past_comma (&str) == FAIL
- || cp_opc_expr (&str, 21, 3) == FAIL)
- {
- if (!inst.error)
- inst.error = BAD_ARGS;
- return;
- }
+ comma_or_fail (&str);
+
+ if (cp_opc_expr (&str, 21, 3) == FAIL)
+ return;
- if (skip_past_comma (&str) == FAIL
- || reg_required_here (&str, 12, FALSE) == FAIL)
- {
- if (!inst.error)
- inst.error = BAD_ARGS;
- return;
- }
+ comma_or_fail (&str);
- if (skip_past_comma (&str) == FAIL
- || cp_reg_required_here (&str, 16) == FAIL)
- {
- if (!inst.error)
- inst.error = BAD_ARGS;
- return;
- }
+ reg_or_fail (&str, 12, FALSE);
- if (skip_past_comma (&str) == FAIL
- || cp_reg_required_here (&str, 0) == FAIL)
- {
- if (!inst.error)
- inst.error = BAD_ARGS;
- return;
- }
+ comma_or_fail (&str);
- if (skip_past_comma (&str) == SUCCESS)
- {
- if (cp_opc_expr (&str, 5, 3) == FAIL)
- {
- if (!inst.error)
- inst.error = BAD_ARGS;
- return;
- }
- }
+ if (cp_reg_required_here (&str, 16) == FAIL)
+ return;
- end_of_line (str);
-}
+ comma_or_fail (&str);
-/* ARM V5 (argument parse)
- MCR2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
- MRC2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
- Instruction is not conditional, and has 0xf in the condition field.
- Otherwise, it's the same as MCR/MRC. */
+ if (cp_reg_required_here (&str, 0) == FAIL)
+ return;
-static void
-do_co_reg2 (char * str)
-{
- skip_whitespace (str);
-
- if (co_proc_number (& str) == FAIL)
- {
- if (!inst.error)
- inst.error = BAD_ARGS;
+ if (skip_past_comma (&str) == SUCCESS)
+ if (cp_opc_expr (&str, 5, 3) == FAIL)
return;
- }
- if (skip_past_comma (& str) == FAIL
- || cp_opc_expr (& str, 21, 3) == FAIL)
- {
- if (!inst.error)
- inst.error = BAD_ARGS;
- return;
- }
-
- if (skip_past_comma (& str) == FAIL
- || reg_required_here (& str, 12, FALSE) == FAIL)
- {
- if (!inst.error)
- inst.error = BAD_ARGS;
- return;
- }
-
- if (skip_past_comma (& str) == FAIL
- || cp_reg_required_here (& str, 16) == FAIL)
- {
- if (!inst.error)
- inst.error = BAD_ARGS;
- return;
- }
-
- if (skip_past_comma (& str) == FAIL
- || cp_reg_required_here (& str, 0) == FAIL)
- {
- if (!inst.error)
- inst.error = BAD_ARGS;
- return;
- }
-
- if (skip_past_comma (& str) == SUCCESS)
- {
- if (cp_opc_expr (& str, 5, 3) == FAIL)
- {
- if (!inst.error)
- inst.error = BAD_ARGS;
- return;
- }
- }
-
end_of_line (str);
}
-/* ARM V5E (el Segundo)
- MCRRcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
- MRRCcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
+/* Transfer between coprocessor register and pair of ARM registers.
+ MCRR{cond} <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
+ MCRR2
+ MRRC{cond}
+ MRRC2
- These are equivalent to the XScale instructions MAR and MRA,
- respectively, when coproc == 0, opcode == 0, and CRm == 0.
+ Two XScale instructions are special cases of these:
+ MAR{cond} acc0, <RdLo>, <RdHi> == MCRR{cond} p0, #0, <RdLo>, <RdHi>, c0
+ MRA{cond} acc0, <RdLo>, <RdHi> == MRRC{cond} p0, #0, <RdLo>, <RdHi>, c0
+
Result unpredicatable if Rd or Rn is R15. */
static void
do_co_reg2c (char * str)
{
- int rd, rn;
-
skip_whitespace (str);
if (co_proc_number (& str) == FAIL)
- {
- if (!inst.error)
- inst.error = BAD_ARGS;
- return;
- }
+ return;
- if (skip_past_comma (& str) == FAIL
- || cp_opc_expr (& str, 4, 4) == FAIL)
- {
- if (!inst.error)
- inst.error = BAD_ARGS;
- return;
- }
+ comma_or_fail (&str);
- if (skip_past_comma (& str) == FAIL
- || (rd = reg_required_here (& str, 12, FALSE)) == FAIL)
- {
- if (!inst.error)
- inst.error = BAD_ARGS;
- return;
- }
+ if (cp_opc_expr (&str, 4, 4) == FAIL)
+ return;
- if (skip_past_comma (& str) == FAIL
- || (rn = reg_required_here (& str, 16, FALSE)) == FAIL)
- {
- if (!inst.error)
- inst.error = BAD_ARGS;
- return;
- }
+ comma_or_fail (&str);
+ reg_or_fail (&str, 12, TRUE);
- /* Unpredictable result if rd or rn is R15. */
- if (rd == REG_PC || rn == REG_PC)
- as_tsktsk
- (_("Warning: instruction unpredictable when using r15"));
+ comma_or_fail (&str);
+ reg_or_fail (&str, 16, TRUE);
- if (skip_past_comma (& str) == FAIL
- || cp_reg_required_here (& str, 0) == FAIL)
- {
- if (!inst.error)
- inst.error = BAD_ARGS;
- return;
- }
+ comma_or_fail (&str);
+ if (cp_reg_required_here (& str, 0) == FAIL)
+ return;
+
end_of_line (str);
}
@@ -5809,8 +5558,7 @@
skip_whitespace (str);
- if ((base_reg = reg_required_here (&str, 16, TRUE)) == FAIL)
- return;
+ note_reg_or_fail (base_reg, &str, 16, TRUE);
skip_whitespace (str);
@@ -5820,14 +5568,11 @@
str++;
}
- if (skip_past_comma (&str) == FAIL
- || (range = reg_list (&str)) == FAIL)
- {
- if (! inst.error)
- inst.error = BAD_ARGS;
- return;
- }
+ comma_or_fail (&str);
+ if ((range = reg_list (&str)) == FAIL)
+ return;
+
if (*str == '^')
{
str++;
@@ -5877,14 +5622,11 @@
skip_whitespace (str);
- if ((rd = reg_required_here (& str, 12, FALSE)) == FAIL)
- {
- inst.error = BAD_ARGS;
- return;
- }
+ note_reg_or_fail (rd, &str, 12, FALSE);
- if (skip_past_comma (& str) == FAIL
- || (rn = ld_mode_required_here (& str)) == FAIL)
+ comma_or_fail (&str);
+
+ if ((rn = ld_mode_required_here (& str)) == FAIL)
{
if (!inst.error)
inst.error = BAD_ARGS;
@@ -5924,7 +5666,7 @@
}
/* ARM V6 Load Register Exclusive instruction (argument parse).
- LDREX{,B,D,H}{<cond>} <Rd, [<Rn>]
+ LDREX{,B,D,H}{<cond>} <Rd>, [<Rn>]
Condition defaults to COND_ALWAYS.
Error if Rd or Rn are R15.
See ARMARMv6 A4.1.27: LDREX. */
@@ -5935,13 +5677,8 @@
skip_whitespace (str);
/* Parse Rd. */
- if (reg_required_here (&str, 12, TRUE) == FAIL)
- return;
- if (skip_past_comma (&str) == FAIL)
- {
- inst.error = BAD_ARGS;
- return;
- }
+ reg_or_fail (&str, 12, TRUE);
+ comma_or_fail (&str);
/* Skip past '['. */
skip_whitespace (str);
@@ -5952,10 +5689,7 @@
}
str++;
- /* Parse Rn. */
- skip_whitespace (str);
- if (reg_required_here (&str, 16, TRUE) == FAIL)
- return;
+ reg_or_fail (&str, 16, TRUE);
/* Skip past ']'. */
skip_whitespace (str);
@@ -5977,19 +5711,9 @@
skip_whitespace (str);
- if ((conflict_reg = reg_required_here (&str, 12, FALSE)) == FAIL)
- {
- if (!inst.error)
- inst.error = BAD_ARGS;
- return;
- }
+ note_reg_or_fail (conflict_reg, &str, 12, FALSE);
+ comma_or_fail (&str);
- if (skip_past_comma (&str) == FAIL)
- {
- inst.error = _("address expected");
- return;
- }
-
if (*str == '[')
{
int reg;
@@ -5998,8 +5722,7 @@
skip_whitespace (str);
- if ((reg = reg_required_here (&str, 16, FALSE)) == FAIL)
- return;
+ note_reg_or_fail (reg, &str, 16, FALSE);
/* Conflicts can occur on stores as well as loads. */
conflict_reg = (conflict_reg == reg);
@@ -6016,9 +5739,9 @@
if (ldst_extend (&str) == FAIL)
return;
if (conflict_reg)
- as_warn (_("%s register same as write-back base"),
- ((inst.instruction & LOAD_BIT)
- ? _("destination") : _("source")));
+ as_warn ((inst.instruction & LOAD_BIT)
+ ? _("destination register same as write-back base")
+ : _("source register same as write-back base"));
}
else
{
@@ -6028,9 +5751,9 @@
if (*str == '!')
{
if (conflict_reg)
- as_warn (_("%s register same as write-back base"),
- ((inst.instruction & LOAD_BIT)
- ? _("destination") : _("source")));
+ as_warn ((inst.instruction & LOAD_BIT)
+ ? _("destination register same as write-back base")
+ : _("source register same as write-back base"));
str++;
inst.instruction |= WRITE_BACK;
}
@@ -6042,11 +5765,7 @@
else
{
/* [Rn,...] */
- if (skip_past_comma (&str) == FAIL)
- {
- inst.error = _("pre-indexed expression expected");
- return;
- }
+ comma_or_fail (&str);
pre_inc = 1;
if (ldst_extend (&str) == FAIL)
@@ -6065,9 +5784,9 @@
if (*str == '!')
{
if (conflict_reg)
- as_warn (_("%s register same as write-back base"),
- ((inst.instruction & LOAD_BIT)
- ? _("destination") : _("source")));
+ as_warn ((inst.instruction & LOAD_BIT)
+ ? _("destination register same as write-back base")
+ : _("source register same as write-back base"));
str++;
inst.instruction |= WRITE_BACK;
}
@@ -6085,10 +5804,8 @@
str++;
skip_whitespace (str);
+ expression_or_fail (&inst.reloc.exp, &str);
- if (my_get_expression (&inst.reloc.exp, &str))
- return;
-
if (inst.reloc.exp.X_op != O_constant
&& inst.reloc.exp.X_op != O_symbol)
{
@@ -6141,8 +5858,7 @@
}
else
{
- if (my_get_expression (&inst.reloc.exp, &str))
- return;
+ expression_or_fail (&inst.reloc.exp, &str);
inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
#ifndef TE_WINCE
@@ -6164,20 +5880,9 @@
int conflict_reg;
skip_whitespace (str);
+ note_reg_or_fail (conflict_reg, &str, 12, FALSE);
+ comma_or_fail (&str);
- if ((conflict_reg = reg_required_here (& str, 12, FALSE)) == FAIL)
- {
- if (!inst.error)
- inst.error = BAD_ARGS;
- return;
- }
-
- if (skip_past_comma (& str) == FAIL)
- {
- inst.error = _("address expected");
- return;
- }
-
if (*str == '[')
{
int reg;
@@ -6185,16 +5890,14 @@
str++;
skip_whitespace (str);
+ note_reg_or_fail (reg, &str, 16, FALSE);
- if ((reg = reg_required_here (&str, 16, FALSE)) == FAIL)
- return;
-
/* ldrt/strt always use post-indexed addressing, so if the base is
the same as Rd, we warn. */
if (conflict_reg == reg)
- as_warn (_("%s register same as write-back base"),
- ((inst.instruction & LOAD_BIT)
- ? _("destination") : _("source")));
+ as_warn ((inst.instruction & LOAD_BIT)
+ ? _("destination register same as write-back base")
+ : _("source register same as write-back base"));
skip_whitespace (str);
@@ -6245,20 +5948,9 @@
int value;
skip_whitespace (str);
+ note_reg_or_fail (conflict_reg, &str, 12, FALSE);
+ comma_or_fail (&str);
- if ((conflict_reg = reg_required_here (& str, 12, FALSE)) == FAIL)
- {
- if (!inst.error)
- inst.error = BAD_ARGS;
- return;
- }
-
- if (skip_past_comma (& str) == FAIL)
- {
- inst.error = _("address expected");
- return;
- }
-
if (*str == '[')
{
int reg;
@@ -6267,8 +5959,7 @@
skip_whitespace (str);
- if ((reg = reg_required_here (&str, 16, FALSE)) == FAIL)
- return;
+ note_reg_or_fail (reg, &str, 16, FALSE);
/* Conflicts can occur on stores as well as loads. */
conflict_reg = (conflict_reg == reg);
@@ -6285,9 +5976,9 @@
if (ldst_extend_v4 (&str) == FAIL)
return;
if (conflict_reg)
- as_warn (_("%s register same as write-back base"),
- ((inst.instruction & LOAD_BIT)
- ? _("destination") : _("source")));
+ as_warn ((inst.instruction & LOAD_BIT)
+ ? _("destination register same as write-back base")
+ : _("source register same as write-back base"));
}
else
{
@@ -6299,9 +5990,9 @@
if (*str == '!')
{
if (conflict_reg)
- as_warn (_("%s register same as write-back base"),
- ((inst.instruction & LOAD_BIT)
- ? _("destination") : _("source")));
+ as_warn ((inst.instruction & LOAD_BIT)
+ ? _("destination register same as write-back base")
+ : _("source register same as write-back base"));
str++;
inst.instruction |= WRITE_BACK;
}
@@ -6336,9 +6027,9 @@
if (*str == '!')
{
if (conflict_reg)
- as_warn (_("%s register same as write-back base"),
- ((inst.instruction & LOAD_BIT)
- ? _("destination") : _("source")));
+ as_warn ((inst.instruction & LOAD_BIT)
+ ? _("destination register same as write-back base")
+ : _("source register same as write-back base"));
str++;
inst.instruction |= WRITE_BACK;
}
@@ -6437,19 +6128,9 @@
skip_whitespace (str);
- if ((conflict_reg = reg_required_here (& str, 12, FALSE)) == FAIL)
- {
- if (!inst.error)
- inst.error = BAD_ARGS;
- return;
- }
+ note_reg_or_fail (conflict_reg, &str, 12, FALSE);
+ comma_or_fail (&str);
- if (skip_past_comma (& str) == FAIL)
- {
- inst.error = _("address expected");
- return;
- }
-
if (*str == '[')
{
int reg;
@@ -6457,19 +6138,16 @@
str++;
skip_whitespace (str);
+ note_reg_or_fail (reg, &str, 16, FALSE);
- if ((reg = reg_required_here (&str, 16, FALSE)) == FAIL)
- return;
-
/* ldrt/strt always use post-indexed addressing, so if the base is
the same as Rd, we warn. */
- if (conflict_reg == reg)
- as_warn (_("%s register same as write-back base"),
- ((inst.instruction & LOAD_BIT)
- ? _("destination") : _("source")));
+ if (reg == conflict_reg)
+ as_warn ((inst.instruction & LOAD_BIT)
+ ? _("destination register same as write-back base")
+ : _("source register same as write-back base"));
skip_whitespace (str);
-
if (*str == ']')
{
str ++;
@@ -6516,61 +6194,19 @@
skip_whitespace (str);
if (co_proc_number (&str) == FAIL)
- {
- if (!inst.error)
- inst.error = BAD_ARGS;
- return;
- }
+ return;
- if (skip_past_comma (&str) == FAIL
- || cp_reg_required_here (&str, 12) == FAIL)
- {
- if (!inst.error)
- inst.error = BAD_ARGS;
- return;
- }
+ comma_or_fail (&str);
- if (skip_past_comma (&str) == FAIL
- || cp_address_required_here (&str, CP_WB_OK) == FAIL)
- {
- if (! inst.error)
- inst.error = BAD_ARGS;
- return;
- }
+ if (cp_reg_required_here (&str, 12) == FAIL)
+ return;
- end_of_line (str);
-}
+ comma_or_fail (&str);
-/* ARM V5 (argument parse)
- LDC2{L} <coproc>, <CRd>, <addressing mode>
- STC2{L} <coproc>, <CRd>, <addressing mode>
- Instruction is not conditional, and has 0xf in the condition field.
- Otherwise, it's the same as LDC/STC. */
+ if (cp_address_required_here (&str, CP_WB_OK) == FAIL)
+ return;
-static void
-do_lstc2 (char * str)
-{
- skip_whitespace (str);
-
- if (co_proc_number (& str) == FAIL)
- {
- if (!inst.error)
- inst.error = BAD_ARGS;
- }
- else if (skip_past_comma (& str) == FAIL
- || cp_reg_required_here (& str, 12) == FAIL)
- {
- if (!inst.error)
- inst.error = BAD_ARGS;
- }
- else if (skip_past_comma (& str) == FAIL
- || cp_address_required_here (&str, CP_WB_OK) == FAIL)
- {
- if (! inst.error)
- inst.error = BAD_ARGS;
- }
- else
- end_of_line (str);
+ end_of_line (str);
}
static void
@@ -6581,41 +6217,22 @@
/* Only one format "rd, rm, rs, rn". */
skip_whitespace (str);
- if ((rd = reg_required_here (&str, 16, TRUE)) == FAIL)
- return;
+ note_reg_or_fail (rd, &str, 16, TRUE);
+ comma_or_fail (&str);
- if (skip_past_comma (&str) == FAIL)
- {
- inst.error = BAD_ARGS;
- return;
- }
- if ((rm = reg_required_here (&str, 0, TRUE)) == FAIL)
- return;
+ note_reg_or_fail (rm, &str, 0, TRUE);
+ comma_or_fail (&str);
+ reg_or_fail (&str, 8, TRUE);
+ comma_or_fail (&str);
+
+ reg_or_fail (&str, 12, TRUE);
+ end_of_line (str);
+
/* This restriction does not apply to mls (nor to mla in v6, but
that's hard to detect at present). */
if (rm == rd && !is_mls)
as_tsktsk (_("rd and rm should be different in mla"));
-
- /* Rs. */
- if (skip_past_comma (&str) == FAIL)
- {
- inst.error = BAD_ARGS;
- return;
- }
- if ((rm = reg_required_here (&str, 8, TRUE)) == FAIL)
- return;
-
- /* Rn. */
- if (skip_past_comma (&str) == FAIL)
- {
- inst.error = BAD_ARGS;
- return;
- }
- if ((rm = reg_required_here (&str, 12, TRUE)) == FAIL)
- return;
-
- end_of_line (str);
}
static void
@@ -6635,11 +6252,10 @@
{
skip_whitespace (str);
- if (reg_required_here (&str, 12, FALSE) == FAIL)
- return;
+ reg_or_fail (&str, 12, FALSE);
+ comma_or_fail (&str);
- if (skip_past_comma (&str) == FAIL
- || data_op2 (&str) == FAIL)
+ if (data_op2 (&str) == FAIL)
{
if (!inst.error)
inst.error = BAD_ARGS;
@@ -6656,20 +6272,10 @@
{
int val;
- /* Rd. */
skip_whitespace (str);
- if (reg_required_here (&str, 12, TRUE) == FAIL)
- return;
- if (skip_past_comma (&str) == FAIL)
- {
- inst.error = BAD_ARGS;
- return;
- }
-
- /* Imm16. */
- if (immediate_required_here (&str, &val, 0, 65535, FALSE) == FAIL)
- return;
-
+ reg_or_fail (&str, 12, TRUE);
+ comma_or_fail (&str);
+ immediate_or_fail (&str, &val, 0, 65535, FALSE);
end_of_line (str);
/* The value is in two pieces: 0:11, 16:19. */
@@ -6680,42 +6286,37 @@
static void
do_mrs (char * str)
{
- int skip = 0;
-
/* Only one syntax. */
skip_whitespace (str);
- if (reg_required_here (&str, 12, FALSE) == FAIL)
- return;
+ reg_or_fail (&str, 12, FALSE);
+ comma_or_fail (&str);
- if (skip_past_comma (&str) == FAIL)
+ skip_whitespace (str);
+
+ /* Lower case accepted for backwards compatibility. */
+ if (*str == 'c' || *str == 'C')
+ ; /* SPSR bit is already clear. */
+ else if (*str == 's' || *str == 'S')
+ inst.instruction |= SPSR_BIT;
+ else
{
- inst.error = _("comma expected after register name");
+ inst.error = _("'CPSR' or 'SPSR' expected");
return;
}
+ str++;
- skip_whitespace (str);
-
- if ( streq (str, "CPSR")
- || streq (str, "SPSR")
- /* Lower case versions for backwards compatibility. */
- || streq (str, "cpsr")
- || streq (str, "spsr"))
- skip = 4;
-
- /* This is for backwards compatibility with older toolchains. */
- else if ( streq (str, "cpsr_all")
- || streq (str, "spsr_all"))
- skip = 8;
- else
+ if (strncasecmp (str, "PSR", 3) != 0)
{
- inst.error = _("CPSR or SPSR expected");
+ inst.error = _("'CPSR' or 'SPSR' expected");
return;
}
+ str += 3;
- if (* str == 's' || * str == 'S')
- inst.instruction |= SPSR_BIT;
- str += skip;
+ /* For backward compatibility, allow a trailing "_all"
+ (lowercase only). */
+ if (strncmp (str, "_all", 4) == 0)
+ str += 4;
end_of_line (str);
}
@@ -6729,18 +6330,14 @@
{
skip_whitespace (str);
- if (psr_required_here (& str) == FAIL)
+ if (psr_required_here (&str) == FAIL)
return;
- if (skip_past_comma (& str) == FAIL)
- {
- inst.error = _("comma missing after psr flags");
- return;
- }
+ comma_or_fail (&str);
skip_whitespace (str);
- if (reg_required_here (& str, 0, FALSE) != FAIL)
+ if (reg_required_here (&str, 0, FALSE) != FAIL)
{
inst.error = NULL;
end_of_line (str);
@@ -6796,31 +6393,17 @@
/* Only one format "rd, rm, rs". */
skip_whitespace (str);
- if ((rd = reg_required_here (&str, 16, TRUE)) == FAIL)
- return;
+ note_reg_or_fail (rd, &str, 16, TRUE);
+ comma_or_fail (&str);
- if (skip_past_comma (&str) == FAIL)
- {
- inst.error = BAD_ARGS;
- return;
- }
+ note_reg_or_fail (rm, &str, 0, TRUE);
+ comma_or_fail (&str);
- if ((rm = reg_required_here (&str, 0, TRUE)) == FAIL)
- return;
+ reg_required_here (&str, 8, TRUE);
+ end_of_line (str);
if (rm == rd)
as_tsktsk (_("rd and rm should be different in mul"));
-
- if (skip_past_comma (&str) == FAIL)
- {
- inst.error = BAD_ARGS;
- return;
- }
-
- if (reg_required_here (&str, 8, TRUE) == FAIL)
- return;
-
- end_of_line (str);
}
/* Long Multiply Parser
@@ -6837,41 +6420,21 @@
/* Only one format "rdlo, rdhi, rm, rs". */
skip_whitespace (str);
- if ((rdlo = reg_required_here (&str, 12, TRUE)) == FAIL)
- return;
+ note_reg_or_fail (rdlo, &str, 12, TRUE);
+ comma_or_fail (&str);
- if (skip_past_comma (&str) == FAIL)
- {
- inst.error = BAD_ARGS;
- return;
- }
-
- if ((rdhi = reg_required_here (&str, 16, TRUE)) == FAIL)
- return;
-
- if (skip_past_comma (&str) == FAIL)
- {
- inst.error = BAD_ARGS;
- return;
- }
+ note_reg_or_fail (rdhi, &str, 16, TRUE);
+ comma_or_fail (&str);
- if ((rm = reg_required_here (&str, 0, TRUE)) == FAIL)
- return;
+ note_reg_or_fail (rm, &str, 0, TRUE);
+ comma_or_fail (&str);
- if (skip_past_comma (&str) == FAIL)
- {
- inst.error = BAD_ARGS;
- return;
- }
+ reg_or_fail (&str, 8, TRUE);
+ end_of_line (str);
- if (reg_required_here (&str, 8, TRUE) == FAIL)
- return;
-
/* rdhi, rdlo and rm must all be different. */
if (rdlo == rdhi || rdlo == rm || rdhi == rm)
as_tsktsk (_("rdhi, rdlo and rm must all be different"));
-
- end_of_line (str);
}
static void
@@ -6908,28 +6471,15 @@
skip_whitespace (str);
- if (reg_required_here (&str, 12, TRUE) == FAIL)
- return;
+ reg_or_fail (&str, 12, TRUE);
+ comma_or_fail (&str);
- if (skip_past_comma (&str) == FAIL)
- {
- inst.error = BAD_ARGS;
- return;
- }
+ note_reg_or_fail (rn, &str, 16, TRUE);
+ comma_or_fail (&str);
- if ((rn = reg_required_here (&str, 16, TRUE)) == FAIL)
- return;
+ note_reg_or_fail (rm, &str, 0, TRUE);
- if (skip_past_comma (&str) == FAIL)
- {
- inst.error = BAD_ARGS;
- return;
- }
- if ((rm = reg_required_here (&str, 0, TRUE)) == FAIL)
- return;
-
-
/* Check for optional shift immediate constant. */
if (skip_past_comma (&str) == FAIL)
{
@@ -6989,8 +6539,7 @@
++str;
skip_whitespace (str);
- if ((rd = reg_required_here (& str, 16, FALSE)) == FAIL)
- return;
+ note_reg_or_fail (rd, &str, 16, FALSE);
skip_whitespace (str);
@@ -7058,24 +6607,13 @@
{
skip_whitespace (str);
- if (reg_required_here (&str, 12, TRUE) == FAIL)
- return;
- if (skip_past_comma (&str) == FAIL)
- {
- inst.error = BAD_ARGS;
- return;
- }
+ reg_or_fail (&str, 12, TRUE);
+ comma_or_fail (&str);
- if (reg_required_here (&str, 0, TRUE) == FAIL)
- return;
- if (skip_past_comma (&str) == FAIL)
- {
- inst.error = BAD_ARGS;
- return;
- }
- if (reg_required_here (&str, 16, TRUE) == FAIL)
- return;
+ reg_or_fail (&str, 0, TRUE);
+ comma_or_fail (&str);
+ reg_or_fail (&str, 16, TRUE);
end_of_line (str);
}
@@ -7089,24 +6627,13 @@
{
skip_whitespace (str);
- if (reg_required_here (&str, 12, TRUE) == FAIL)
- return;
- if (skip_past_comma (&str) == FAIL)
- {
- inst.error = BAD_ARGS;
- return;
- }
+ reg_or_fail (&str, 12, TRUE);
+ comma_or_fail (&str);
- if (reg_required_here (&str, 16, TRUE) == FAIL)
- return;
- if (skip_past_comma (&str) == FAIL)
- {
- inst.error = BAD_ARGS;
- return;
- }
- if (reg_required_here (&str, 0, TRUE) == FAIL)
- return;
+ reg_or_fail (&str, 16, TRUE);
+ comma_or_fail (&str);
+ reg_or_fail (&str, 0, TRUE);
end_of_line (str);
}
@@ -7114,17 +6641,10 @@
do_rbit (char *str)
{
skip_whitespace (str);
- if (reg_required_here (&str, 12, FALSE) == FAIL)
- return;
- if (skip_past_comma (&str) == FAIL)
- {
- inst.error = BAD_ARGS;
- return;
- }
+ reg_or_fail (&str, 12, FALSE);
+ comma_or_fail (&str);
- if (reg_required_here (&str, 0, FALSE) == FAIL)
- return;
-
+ reg_or_fail (&str, 0, FALSE);
end_of_line (str);
}
@@ -7138,17 +6658,11 @@
do_rev (char * str)
{
skip_whitespace (str);
- if (reg_required_here (&str, 12, TRUE) == FAIL)
- return;
- if (skip_past_comma (&str) == FAIL)
- {
- inst.error = BAD_ARGS;
- return;
- }
- if (reg_required_here (&str, 0, TRUE) == FAIL)
- return;
+ reg_or_fail (&str, 12, TRUE);
+ comma_or_fail (&str);
+ reg_or_fail (&str, 0, TRUE);
end_of_line (str);
}
@@ -7163,8 +6677,7 @@
{
skip_whitespace (str);
- if (reg_required_here (&str, 16, TRUE) == FAIL)
- return;
+ reg_or_fail (&str, 16, TRUE);
skip_whitespace (str);
@@ -7177,38 +6690,28 @@
}
static void
-do_sat (char ** str, int bias)
+do_sat (char *str, int bias)
{
int val;
- skip_whitespace (*str);
+ skip_whitespace (str);
/* Parse <Rd>, field. */
- if (reg_required_here (str, 12, TRUE) == FAIL)
- return;
- if (skip_past_comma (str) == FAIL)
- {
- inst.error = BAD_ARGS;
- return;
- }
+ reg_or_fail (&str, 12, TRUE);
+ comma_or_fail (&str);
/* Parse #<immed>, field. */
- if (immediate_required_here (str, &val, 0 - bias, 31 - bias, FALSE) == FAIL)
- return;
-
+ immediate_or_fail (&str, &val, 0 - bias, 31 - bias, FALSE);
+ comma_or_fail (&str);
inst.instruction |= (val + bias) << 16;
- if (skip_past_comma (str) == FAIL)
- {
- inst.error = BAD_ARGS;
- return;
- }
/* Parse <Rm> field. */
- if (reg_required_here (str, 0, TRUE) == FAIL)
- return;
+ reg_or_fail (&str, 0, TRUE);
- if (skip_past_comma (str) == SUCCESS)
- decode_shift (str, SHIFT_LSL_OR_ASR_IMMEDIATE);
+ if (skip_past_comma (&str) == SUCCESS)
+ decode_shift (&str, SHIFT_LSL_OR_ASR_IMMEDIATE);
+
+ end_of_line (str);
}
/* ARM V6 ssat (argument parse). */
@@ -7216,8 +6719,7 @@
static void
do_ssat (char * str)
{
- do_sat (&str, /*bias=*/-1);
- end_of_line (str);
+ do_sat (str, /*bias=*/-1);
}
/* ARM V6 usat (argument parse). */
@@ -7225,40 +6727,28 @@
static void
do_usat (char * str)
{
- do_sat (&str, /*bias=*/0);
- end_of_line (str);
+ do_sat (str, /*bias=*/0);
}
static void
-do_sat16 (char ** str, int bias)
+do_sat16 (char *str, int bias)
{
int val;
- skip_whitespace (*str);
+ skip_whitespace (str);
/* Parse the <Rd> field. */
- if (reg_required_here (str, 12, TRUE) == FAIL)
- return;
- if (skip_past_comma (str) == FAIL)
- {
- inst.error = BAD_ARGS;
- return;
- }
+ reg_or_fail (&str, 12, TRUE);
+ comma_or_fail (&str);
/* Parse #<immed>, field. */
- if (immediate_required_here (str, &val, 0 - bias, 15 - bias, FALSE) == FAIL)
- return;
-
+ immediate_or_fail (&str, &val, 0 - bias, 15 - bias, FALSE);
+ comma_or_fail (&str);
inst.instruction |= (val + bias) << 16;
- if (skip_past_comma (str) == FAIL)
- {
- inst.error = BAD_ARGS;
- return;
- }
/* Parse <Rm> field. */
- if (reg_required_here (str, 0, TRUE) == FAIL)
- return;
+ reg_or_fail (&str, 0, TRUE);
+ end_of_line (str);
}
/* ARM V6 ssat16 (argument parse). */
@@ -7266,15 +6756,13 @@
static void
do_ssat16 (char * str)
{
- do_sat16 (&str, /*bias=*/-1);
- end_of_line (str);
+ do_sat16 (str, /*bias=*/-1);
}
static void
do_usat16 (char * str)
{
- do_sat16 (&str, /*bias=*/0);
- end_of_line (str);
+ do_sat16 (str, /*bias=*/0);
}
/* ARM V6 SETEND (argument parse). Sets the E bit in the CPSR while
@@ -7334,32 +6822,16 @@
{
skip_whitespace (str);
- if (reg_required_here (& str, 16, TRUE) == FAIL)
- return;
- if (skip_past_comma (& str) == FAIL)
- {
- inst.error = BAD_ARGS;
- return;
- }
+ reg_or_fail (&str, 16, TRUE);
+ comma_or_fail (&str);
- if (reg_required_here (& str, 0, TRUE) == FAIL)
- return;
- if (skip_past_comma (& str) == FAIL)
- {
- inst.error = BAD_ARGS;
- return;
- }
+ reg_or_fail (&str, 0, TRUE);
+ comma_or_fail (&str);
- if (reg_required_here (& str, 8, TRUE) == FAIL)
- return;
- if (skip_past_comma (& str) == FAIL)
- {
- inst.error = BAD_ARGS;
- return;
- }
+ reg_or_fail (&str, 8, TRUE);
+ comma_or_fail (&str);
- if (reg_required_here (& str, 12, TRUE) == FAIL)
- return;
+ reg_or_fail (&str, 12, TRUE);
end_of_line (str);
}
@@ -7376,32 +6848,16 @@
skip_whitespace (str);
- if ((rdlo = reg_required_here (& str, 12, TRUE)) == FAIL)
- return;
- if (skip_past_comma (& str) == FAIL)
- {
- inst.error = BAD_ARGS;
- return;
- }
+ note_reg_or_fail (rdlo, &str, 12, TRUE);
+ comma_or_fail (&str);
- if ((rdhi = reg_required_here (& str, 16, TRUE)) == FAIL)
- return;
- if (skip_past_comma (& str) == FAIL)
- {
- inst.error = BAD_ARGS;
- return;
- }
+ note_reg_or_fail (rdhi, &str, 16, TRUE);
+ comma_or_fail (&str);
- if (reg_required_here (& str, 0, TRUE) == FAIL)
- return;
- if (skip_past_comma (& str) == FAIL)
- {
- inst.error = BAD_ARGS;
- return;
- }
+ reg_or_fail (&str, 0, TRUE);
+ comma_or_fail (&str);
- if (reg_required_here (& str, 8, TRUE) == FAIL)
- return;
+ reg_or_fail (&str, 8, TRUE);
if (rdlo == rdhi)
as_tsktsk (_("rdhi and rdlo must be different"));
@@ -7417,24 +6873,13 @@
do_smul (char * str)
{
skip_whitespace (str);
- if (reg_required_here (& str, 16, TRUE) == FAIL)
- return;
- if (skip_past_comma (& str) == FAIL)
- {
- inst.error = BAD_ARGS;
- return;
- }
+ reg_or_fail (&str, 16, TRUE);
+ comma_or_fail (&str);
- if (reg_required_here (& str, 0, TRUE) == FAIL)
- return;
- if (skip_past_comma (& str) == FAIL)
- {
- inst.error = BAD_ARGS;
- return;
- }
+ reg_or_fail (&str, 0, TRUE);
+ comma_or_fail (&str);
- if (reg_required_here (& str, 8, TRUE) == FAIL)
- return;
+ reg_or_fail (&str, 8, TRUE);
end_of_line (str);
}
@@ -7469,21 +6914,11 @@
/* Parse Rd, Rm,. */
skip_whitespace (str);
- if ((rd = reg_required_here (& str, 12, TRUE)) == FAIL)
- return;
- if (skip_past_comma (& str) == FAIL)
- {
- inst.error = BAD_ARGS;
- return;
- }
+ note_reg_or_fail (rd, &str, 12, TRUE);
+ comma_or_fail (&str);
- if ((rm = reg_required_here (& str, 0, TRUE)) == FAIL)
- return;
- if (skip_past_comma (& str) == FAIL)
- {
- inst.error = BAD_ARGS;
- return;
- }
+ note_reg_or_fail (rm, &str, 0, TRUE);
+ comma_or_fail (&str);
if (rd == rm)
{
@@ -7501,8 +6936,7 @@
skip_whitespace (str);
/* Parse Rn. */
- if ((rn = reg_required_here (& str, 16, TRUE)) == FAIL)
- return;
+ note_reg_or_fail (rn, &str, 16, TRUE);
if (rd == rn)
{
inst.error = _("Rd equal to Rm or Rn yields unpredictable results");
@@ -7528,18 +6962,11 @@
skip_whitespace (str);
- if (reg_required_here (&str, 12, TRUE) == FAIL)
- return;
+ reg_or_fail (&str, 12, TRUE);
+ comma_or_fail (&str);
- if (skip_past_comma (&str) == FAIL)
- {
- inst.error = BAD_ARGS;
- return;
- }
+ reg_or_fail (&str, 0, TRUE);
- if (reg_required_here (&str, 0, TRUE) == FAIL)
- return;
-
if (skip_past_comma (&str) == FAIL
|| *str++ != '[')
{
@@ -7549,8 +6976,7 @@
skip_whitespace (str);
- if ((reg = reg_required_here (&str, 16, TRUE)) == FAIL)
- return;
+ note_reg_or_fail (reg, &str, 16, TRUE);
skip_whitespace (str);
@@ -7581,24 +7007,13 @@
int rotation_twenty_four_mask = 0x00000c00;
skip_whitespace (str);
- if (reg_required_here (& str, 12, TRUE) == FAIL)
- return;
- if (skip_past_comma (& str) == FAIL)
- {
- inst.error = BAD_ARGS;
- return;
- }
+ reg_or_fail (&str, 12, TRUE);
+ comma_or_fail (&str);
- if (reg_required_here (& str, 16, TRUE) == FAIL)
- return;
- if (skip_past_comma (& str) == FAIL)
- {
- inst.error = BAD_ARGS;
- return;
- }
+ reg_or_fail (&str, 16, TRUE);
+ comma_or_fail (&str);
- if (reg_required_here (& str, 0, TRUE) == FAIL)
- return;
+ reg_or_fail (&str, 0, TRUE);
/* Zero out the rotation field. */
inst.instruction &= rotation_clear_mask;
@@ -7667,16 +7082,10 @@
int rotation_twenty_four_mask = 0x00000c00;
skip_whitespace (str);
- if (reg_required_here (& str, 12, TRUE) == FAIL)
- return;
- if (skip_past_comma (& str) == FAIL)
- {
- inst.error = BAD_ARGS;
- return;
- }
+ reg_or_fail (&str, 12, TRUE);
+ comma_or_fail (&str);
- if (reg_required_here (& str, 0, TRUE) == FAIL)
- return;
+ reg_or_fail (&str, 0, TRUE);
/* Zero out the rotation field. */
inst.instruction &= rotation_clear_mask;
@@ -8891,8 +8300,7 @@
{
skip_whitespace (str);
- if (reg_required_here (&str, 12, FALSE) == FAIL)
- return;
+ reg_or_fail (&str, 12, FALSE);
if (skip_past_comma (&str) == FAIL
|| vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL)
@@ -8985,8 +8393,7 @@
{
skip_whitespace (str);
- if (reg_required_here (&str, 12, FALSE) == FAIL)
- return;
+ reg_or_fail (&str, 12, FALSE);
if (skip_past_comma (&str) == FAIL
|| vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL)
@@ -9004,8 +8411,7 @@
{
skip_whitespace (str);
- if (reg_required_here (&str, 12, FALSE) == FAIL)
- return;
+ reg_or_fail (&str, 12, FALSE);
if (skip_past_comma (&str) == FAIL
|| reg_required_here (&str, 16, FALSE) == FAIL
@@ -9065,8 +8471,7 @@
{
skip_whitespace (str);
- if (reg_required_here (&str, 12, FALSE) == FAIL)
- return;
+ reg_or_fail (&str, 12, FALSE);
if (skip_past_comma (&str) == FAIL
|| vfp_psr_required_here (&str) == FAIL)
@@ -9153,8 +8558,7 @@
skip_whitespace (str);
- if (reg_required_here (&str, 16, FALSE) == FAIL)
- return;
+ reg_or_fail (&str, 16, FALSE);
skip_whitespace (str);
@@ -9190,8 +8594,7 @@
skip_whitespace (str);
- if (reg_required_here (&str, 16, FALSE) == FAIL)
- return;
+ reg_or_fail (&str, 16, FALSE);
skip_whitespace (str);
@@ -9269,8 +8672,7 @@
skip_whitespace (str);
- if (reg_required_here (&str, 12, FALSE) == FAIL)
- return;
+ reg_or_fail (&str, 12, FALSE);
end_of_line (str);
}
@@ -9380,8 +8782,7 @@
{
skip_whitespace (str);
- if (reg_required_here (&str, 12, FALSE) == FAIL)
- return;
+ reg_or_fail (&str, 12, FALSE);
if (skip_past_comma (&str) == FAIL
|| fp_reg_required_here (&str, 0) == FAIL)
@@ -10445,27 +9846,14 @@
static void
do_xsc_mia (char * str)
{
- if (accum0_required_here (& str) == FAIL)
- inst.error = ERR_NO_ACCUM;
-
- if (skip_past_comma (& str) == FAIL)
- {
- inst.error = BAD_ARGS;
- return;
- }
-
- if (reg_required_here (& str, 0, TRUE) == FAIL)
+ if (xsc_reg_required_here (&str) == FAIL)
return;
+ comma_or_fail (&str);
- if (skip_past_comma (& str) == FAIL)
- {
- inst.error = BAD_ARGS;
- return;
- }
+ reg_or_fail (&str, 0, TRUE);
+ comma_or_fail (&str);
- if (reg_required_here (& str, 12, TRUE) == FAIL)
- return;
-
+ reg_or_fail (&str, 12, TRUE);
end_of_line (str);
}
@@ -10476,27 +9864,14 @@
static void
do_xsc_mar (char * str)
{
- if (accum0_required_here (& str) == FAIL)
- inst.error = ERR_NO_ACCUM;
-
- if (skip_past_comma (& str) == FAIL)
- {
- inst.error = BAD_ARGS;
- return;
- }
-
- if (reg_required_here (& str, 12, TRUE) == FAIL)
+ if (xsc_reg_required_here (& str) == FAIL)
return;
+ comma_or_fail (&str);
- if (skip_past_comma (& str) == FAIL)
- {
- inst.error = BAD_ARGS;
- return;
- }
+ reg_or_fail (&str, 12, TRUE);
+ comma_or_fail (&str);
- if (reg_required_here (& str, 16, TRUE) == FAIL)
- return;
-
+ reg_or_fail (&str, 16, TRUE);
end_of_line (str);
}
@@ -10512,36 +9887,19 @@
skip_whitespace (str);
- if ((rdlo = reg_required_here (& str, 12, TRUE)) == FAIL)
- return;
- if (skip_past_comma (& str) == FAIL)
- {
- inst.error = BAD_ARGS;
- return;
- }
+ note_reg_or_fail (rdlo, &str, 12, TRUE);
+ comma_or_fail (&str);
- if ((rdhi = reg_required_here (& str, 16, TRUE)) == FAIL)
+ note_reg_or_fail (rdhi, &str, 16, TRUE);
+ comma_or_fail (&str);
+
+ if (xsc_reg_required_here (& str) == FAIL)
return;
+ end_of_line (str);
- if (skip_past_comma (& str) == FAIL)
- {
- inst.error = BAD_ARGS;
- return;
- }
- if (accum0_required_here (& str) == FAIL)
- {
- inst.error = ERR_NO_ACCUM;
- return;
- }
-
/* inst.instruction has now been zapped with both rdlo and rdhi. */
if (rdlo == rdhi)
- {
- inst.error = BAD_ARGS; /* Undefined result if 2 writes to same reg. */
- return;
- }
-
- end_of_line (str);
+ inst.error = BAD_ARGS; /* Undefined result if 2 writes to same reg. */
}
/* Overall per-instruction processing. */
@@ -10945,13 +10303,13 @@
{"blx", 0xe0000000, 3, ARM_EXT_V5, do_blx},
{"clz", 0xe16f0f10, 3, ARM_EXT_V5, do_clz},
{"bkpt", 0xe1200070, 0, ARM_EXT_V5, do_bkpt},
- {"ldc2", 0xfc100000, 0, ARM_EXT_V5, do_lstc2},
- {"ldc2l", 0xfc500000, 0, ARM_EXT_V5, do_lstc2},
- {"stc2", 0xfc000000, 0, ARM_EXT_V5, do_lstc2},
- {"stc2l", 0xfc400000, 0, ARM_EXT_V5, do_lstc2},
- {"cdp2", 0xfe000000, 0, ARM_EXT_V5, do_cdp2},
- {"mcr2", 0xfe000010, 0, ARM_EXT_V5, do_co_reg2},
- {"mrc2", 0xfe100010, 0, ARM_EXT_V5, do_co_reg2},
+ {"ldc2", 0xfc100000, 0, ARM_EXT_V5, do_lstc},
+ {"ldc2l", 0xfc500000, 0, ARM_EXT_V5, do_lstc},
+ {"stc2", 0xfc000000, 0, ARM_EXT_V5, do_lstc},
+ {"stc2l", 0xfc400000, 0, ARM_EXT_V5, do_lstc},
+ {"cdp2", 0xfe000000, 0, ARM_EXT_V5, do_cdp},
+ {"mcr2", 0xfe000010, 0, ARM_EXT_V5, do_co_reg},
+ {"mrc2", 0xfe100010, 0, ARM_EXT_V5, do_co_reg},
/* ARM Architecture 5TExP. */
{"smlabb", 0xe1000080, 6, ARM_EXT_V5ExP, do_smla},