This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
Thumb32 assembler (33/69)
- From: Zack Weinberg <zack at codesourcery dot com>
- To: binutils <binutils at sourceware dot org>
- Date: Tue, 26 Apr 2005 02:54:56 -0700
- Subject: Thumb32 assembler (33/69)
parse_operands conversion for MSR, and some tidying to parse_operands
itself. Also, this patch begins a trend of removing code from the
operand encoding functions which is redundant with code in
md_apply_fix3.
zw
* config/tc-arm.c (psr_required_here): Rename parse_psr. Return the
PSR mask rather than poking it into inst.instruction.
(OP_PSR, OP_RR_iEX): New operand parse codes.
(parse_operands): Handle them.
(po_reg_or_goto): New parse_operands shorthand macro; use it to
implement RR_EX, RR_EXr, RR_iEX, RL_iEX, and RRnpc_I0.
(do_msr): Use parse_operands. Defer processing of immediate value
to md_apply_fix3.
===================================================================
Index: gas/config/tc-arm.c
--- gas/config/tc-arm.c (revision 34)
+++ gas/config/tc-arm.c (revision 35)
@@ -2122,21 +2122,21 @@
/* Miscellaneous: PSR flags, endian specifiers, coprocessor
operands. */
-/* Parse the input looking for a PSR flag. */
+/* Parse a PSR flag operand. The value returned is FAIL on syntax error,
+ or a bitmask suitable to be or-ed into the ARM msr instruction. */
static int
-psr_required_here (char **str)
+parse_psr (char **str)
{
char *p;
- bfd_boolean is_spsr;
unsigned long psr_field;
/* CPSR's and SPSR's can now be lowercase. This is just a convenience
feature for ease of use and backwards compatibility. */
p = *str;
if (*p == 's' || *p == 'S')
- is_spsr = TRUE;
+ psr_field = SPSR_BIT;
else if (*p == 'c' || *p == 'C')
- is_spsr = FALSE;
+ psr_field = 0;
else
goto error;
@@ -2162,24 +2162,17 @@
if (!psr)
goto error;
- psr_field = psr->field;
+ psr_field |= psr->field;
}
else
{
if (ISALNUM (*p))
goto error; /* Garbage after "[CS]PSR". */
- psr_field = (PSR_c | PSR_f);
+ psr_field |= (PSR_c | PSR_f);
}
-
- /* If this is the SPSR that is being modified, set the R bit. */
- if (is_spsr)
- inst.instruction |= SPSR_BIT;
-
- /* Set the psr flags in the MSR instruction. */
- inst.instruction |= psr_field;
*str = p;
- return SUCCESS;
+ return psr_field;
error:
inst.error = _("flag for {c}psr instruction expected");
@@ -4344,12 +4337,14 @@
#define OP_CPSF 060 /* CPS flags */
#define OP_ENDI 061 /* Endianness specifier */
+#define OP_PSR 062 /* CPSR/SPSR mask for msr */
/* This-or-that operands. All have bit 7 set. */
#define OP_RR_EX 100 /* ARM register or expression */
#define OP_RL_iEX 101 /* Thumb low register or expression with imm prefix */
#define OP_RRnpc_I0 102 /* ARM register or literal 0 */
#define OP_RR_EXr 103 /* ARM register or expression with opt. reloc suff. */
+#define OP_RR_iEX 104 /* ARM register or expression with imm prefix */
/* Optional operands. All have the high bit set. */
#define OP_obI7 200 /* optional, prefix optional, immediate 0 .. 7 */
@@ -4410,6 +4405,15 @@
inst.operands[i].isreg = 1; \
} while (0)
+#define po_reg_or_goto(regtype, label) do { \
+ int reg_ = arm_reg_parse (&str, regtype); \
+ if (reg_ == FAIL) \
+ goto label; \
+ \
+ inst.operands[i].reg = reg_; \
+ inst.operands[i].isreg = 1; \
+} while (0)
+
#define po_imm_or_fail(min, max, popt) do { \
int imm_; \
if (immediate_required_here (&str, &imm_, min, max, popt) == FAIL) \
@@ -4496,6 +4500,7 @@
break;
/* Immediates */
+ I0:
case OP_(I0): po_imm_or_fail ( 0, 0, FALSE); break;
case OP_(I4): po_imm_or_fail ( 1, 4, FALSE); break;
case OP_(I7): po_imm_or_fail ( 0, 7, FALSE); break;
@@ -4542,11 +4547,13 @@
/* Expressions */
case OP_(iEXP):
+ iEXP:
if (is_immediate_prefix (*str))
str++;
/* fall through */
case OP_(EXP):
+ EXP:
if (my_get_expression (&inst.reloc.exp, &str))
return FAIL;
break;
@@ -4572,62 +4579,22 @@
break;
/* Register or expression */
- case OP_(RR_EX):
- {
- int reg_ = arm_reg_parse (&str, REG_TYPE_RN);
- if (reg_ != FAIL)
- {
- inst.operands[i].reg = reg_;
- inst.operands[i].isreg = 1;
- }
- else if (my_get_expression (&inst.reloc.exp, &str))
- return FAIL;
- }
- break;
+ case OP_(RR_EX): po_reg_or_goto (REG_TYPE_RN, EXP); break;
+ case OP_(RR_EXr): po_reg_or_goto (REG_TYPE_RN, EXPr); break;
+ case OP_(RR_iEX): po_reg_or_goto (REG_TYPE_RN, iEXP); break;
- case OP_(RR_EXr):
- {
- int reg_ = arm_reg_parse (&str, REG_TYPE_RN);
- if (reg_ != FAIL)
- {
- inst.operands[i].reg = reg_;
- inst.operands[i].isreg = 1;
- }
- else
- goto EXPr;
- }
- break;
-
case OP_(oRL_iEX):
case OP_(RL_iEX):
- if (is_immediate_prefix (*str))
- {
- str++;
- if (my_get_expression (&inst.reloc.exp, &str))
- return FAIL;
- }
- else
- {
- po_reg_or_fail (REG_TYPE_RN);
- if (inst.operands[i].reg > 7)
- inst.error = BAD_HIREG;
- }
+ po_reg_or_goto (REG_TYPE_RN, iEXP);
+ if (inst.operands[i].reg > 7)
+ inst.error = BAD_HIREG;
break;
/* Register or immediate */
case OP_(RRnpc_I0):
- {
- int reg_ = arm_reg_parse (&str, REG_TYPE_RN);
- if (reg_ != FAIL)
- {
- inst.operands[i].reg = reg_;
- inst.operands[i].isreg = 1;
- if (reg_ == REG_PC)
- inst.error = BAD_PC;
- }
- else
- po_imm_or_fail (0, 0, FALSE);
- }
+ po_reg_or_goto (REG_TYPE_RN, I0);
+ if (inst.operands[i].reg == REG_PC)
+ inst.error = BAD_PC;
break;
/* Misc */
@@ -4645,6 +4612,15 @@
if (parse_ror (&inst.operands[i].imm, &str))
return FAIL;
break;
+
+ case OP_(PSR):
+ {
+ int psrmask = parse_psr (&str);
+ if (psrmask == FAIL)
+ return FAIL;
+ inst.operands[i].imm = psrmask;
+ }
+ break;
default:
as_fatal ("unhandled operand code %03o", *p);
@@ -5764,56 +5740,18 @@
static void
do_msr (char * str)
{
- if (psr_required_here (&str) == FAIL)
+ if (parse_operands (str, OPERANDS2(PSR,RR_iEX)))
return;
- comma_or_fail (&str);
-
- if (reg_required_here (&str, 0, REG_TYPE_RN) != FAIL)
+ inst.instruction |= inst.operands[0].imm;
+ if (inst.operands[1].isreg)
+ inst.instruction |= inst.operands[1].reg;
+ else
{
- end_of_line (str);
- return;
- }
-
- if (! is_immediate_prefix (* str))
- {
- inst.error =
- _("only a register or immediate value can follow a psr flag");
- return;
- }
-
- str ++;
- inst.error = NULL;
-
- if (my_get_expression (& inst.reloc.exp, & str))
- {
- inst.error =
- _("only a register or immediate value can follow a psr flag");
- return;
- }
-
- inst.instruction |= INST_IMMEDIATE;
-
- if (inst.reloc.exp.X_add_symbol)
- {
+ inst.instruction |= INST_IMMEDIATE;
inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
inst.reloc.pc_rel = 0;
}
- else
- {
- unsigned value = validate_immediate (inst.reloc.exp.X_add_number);
-
- if (value == (unsigned) FAIL)
- {
- inst.error = _("invalid constant");
- return;
- }
-
- inst.instruction |= value;
- }
-
- inst.error = NULL;
- end_of_line (str);
}
static void