This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
Thumb32 assembler (28/69)
- From: Zack Weinberg <zack at codesourcery dot com>
- To: binutils <binutils at sourceware dot org>
- Date: Tue, 26 Apr 2005 02:54:42 -0700
- Subject: Thumb32 assembler (28/69)
More miscellaneous parse_operands conversions. The most interesting
bit here is .writeback, which we will see a lot more of.
zw
* tc-arm.c (struct arm_it): Add writeback field to operands struct.
(parse_ror): New function.
(OP_I31w, OP_RRw, OP_oROR): New operand parse codes.
(parse_operands): Handle them.
(do_rfe, do_srs, do_sxtah, do_sxth): Use parse_operands.
===================================================================
Index: gas/config/tc-arm.c
--- gas/config/tc-arm.c (revision 29)
+++ gas/config/tc-arm.c (revision 30)
@@ -195,7 +195,8 @@
{
int reg;
int imm;
- int present : 1;
+ int present : 1; /* operand present */
+ int writeback : 1; /* operand has trailing ! */
} operands[6];
};
@@ -2608,6 +2609,42 @@
return SUCCESS;
}
+/* Parse a rotation specifier: ROR #0, #8, #16, #24. *val receives a
+ value suitable for poking into the rotate field of an sxt or sxta
+ instruction. */
+
+static int
+parse_ror (int *val, char **str)
+{
+ int rot;
+ char *s = *str;
+
+ if (strncasecmp (s, "ROR", 3) == 0)
+ s += 3;
+ else
+ {
+ inst.error = _("missing rotation field after comma");
+ return FAIL;
+ }
+
+ if (immediate_required_here (&s, &rot, 0, 24, FALSE) == FAIL)
+ return FAIL;
+
+ switch (rot)
+ {
+ case 0: *val = 0x0; break;
+ case 8: *val = 0x1; break;
+ case 16: *val = 0x2; break;
+ case 24: *val = 0x3; break;
+
+ default:
+ inst.error = _("rotation can only be 0, 8, 16, or 24");
+ return FAIL;
+ }
+ *str = s;
+ return SUCCESS;
+}
+
/* Directives: register aliases. */
static void
@@ -4313,6 +4350,9 @@
#define OP_bI15 041 /* 0 .. 15 */
#define OP_bI31 042 /* 0 .. 31 */
+#define OP_I31w 050 /* 0 .. 31, optional trailing ! */
+#define OP_RRw 051 /* ARM register, not the PC, optional trailing ! */
+
#define OP_CPSF 060 /* CPS flags */
#define OP_ENDI 061 /* Endianness specifier */
@@ -4323,7 +4363,9 @@
#define OP_ocI255 210 /* optional, curly-brace enclosed, imm 0 .. 255 */
+#define OP_oROR 220 /* optional rotate right 0/8/16/24 */
+
/* Macro for referring to one of the above constants as a number.
Should appear solely in parse_operands(). */
#define OP_(x) OP__(OP_##x)
@@ -4423,6 +4465,17 @@
inst.error = BAD_PC;
break;
+ case OP_(RRw):
+ po_reg_or_fail (REG_TYPE_RN);
+ if (inst.operands[i].reg == REG_PC)
+ inst.error = BAD_PC;
+ if (*str == '!')
+ {
+ inst.operands[i].writeback = 1;
+ str++;
+ }
+ break;
+
/* Immediates */
case OP_(I0): po_imm_or_fail ( 0, 0, FALSE); break;
case OP_(I4): po_imm_or_fail ( 1, 4, FALSE); break;
@@ -4442,11 +4495,30 @@
case OP_(bI31): po_imm_or_fail ( 0, 31, TRUE); break;
case OP_(obIffff): po_imm_or_fail (0, 0xffff, TRUE); break;
+ /* Immediate variants */
case OP_(ocI255):
po_char_or_fail ('{');
po_imm_or_fail (0, 255, TRUE);
po_char_or_fail ('}');
break;
+
+ case OP_(I31w):
+ /* The expression parser chokes on a trailing !, so we have
+ to find it first and zap it. */
+ {
+ char *s = str;
+ while (*s && *s != ',')
+ s++;
+ if (s[-1] == '!')
+ {
+ s[-1] = '\0';
+ inst.operands[i].writeback = 1;
+ }
+ po_imm_or_fail (0, 31, TRUE);
+ if (str == s - 1)
+ str = s;
+ }
+ break;
/* Expressions */
case OP_(iEXP):
@@ -4470,6 +4542,11 @@
return FAIL;
break;
+ case OP_(oROR):
+ if (parse_ror (&inst.operands[i].imm, &str))
+ return FAIL;
+ break;
+
default:
as_fatal ("unhandled operand code %03o", *p);
}
@@ -5967,14 +6044,12 @@
static void
do_rfe (char * str)
{
- reg_nonpc_or_fail (&str, 16);
+ if (parse_operands (str, OPERANDS1(RRw)))
+ return;
- if (*str == '!')
- {
- inst.instruction |= WRITE_BACK;
- str++;
- }
- end_of_line (str);
+ inst.instruction |= (inst.operands[0].reg << 16);
+ if (inst.operands[0].writeback)
+ inst.instruction |= WRITE_BACK;
}
static void
@@ -6133,24 +6208,12 @@
static void
do_srs (char * str)
{
- int val;
- /* This is necessary because the generic expression parser will
- choke on "#16!". */
- char *exclam = strchr (str, '!');
- if (exclam)
- *exclam = '\0';
+ if (parse_operands (str, OPERANDS1(I31w)))
+ return;
- immediate_or_fail (&str, &val, 0, 31, TRUE);
- inst.instruction |= val;
-
- if (exclam)
- *exclam = '!';
- if (*str == '!')
- {
- inst.instruction |= WRITE_BACK;
- str++;
- }
- end_of_line (str);
+ inst.instruction |= inst.operands[0].imm;
+ if (inst.operands[0].writeback)
+ inst.instruction |= WRITE_BACK;
}
/* ARM V6 strex (argument parse). */
@@ -6190,67 +6253,13 @@
static void
do_sxtah (char * str)
{
- int rot;
- int rotation_clear_mask = 0xfffff3ff;
- int rotation_eight_mask = 0x00000400;
- int rotation_sixteen_mask = 0x00000800;
- int rotation_twenty_four_mask = 0x00000c00;
-
- reg_nonpc_or_fail (&str, 12);
- comma_or_fail (&str);
-
- reg_nonpc_or_fail (&str, 16);
- comma_or_fail (&str);
-
- reg_nonpc_or_fail (&str, 0);
-
- /* Zero out the rotation field. */
- inst.instruction &= rotation_clear_mask;
-
- /* Check for lack of optional rotation field. */
- if (skip_past_comma (&str) == FAIL)
- {
- end_of_line (str);
- return;
- }
-
- /* Move past 'ROR'. */
- if (strncasecmp (str, "ROR", 3) == 0)
- str += 3;
- else
- {
- inst.error = _("missing rotation field after comma");
- return;
- }
-
- /* Get the immediate constant. */
- if (immediate_required_here (&str, &rot, 0, 24, FALSE) == FAIL)
+ if (parse_operands (str, OPERANDS4(RRnpc,RRnpc,RRnpc,oROR)))
return;
- switch (rot)
- {
- case 0:
- /* Rotation field has already been zeroed. */
- break;
-
- case 8:
- inst.instruction |= rotation_eight_mask;
- break;
-
- case 16:
- inst.instruction |= rotation_sixteen_mask;
- break;
-
- case 24:
- inst.instruction |= rotation_twenty_four_mask;
- break;
-
- default:
- inst.error = _("rotation can be 8, 16, 24 or 0 when field is ommited");
- break;
- }
-
- end_of_line (str);
+ inst.instruction |= (inst.operands[0].reg << 12);
+ inst.instruction |= (inst.operands[1].reg << 16);
+ inst.instruction |= (inst.operands[2].reg << 0);
+ inst.instruction |= (inst.operands[3].imm << 10);
}
/* ARM V6 SXTH.
@@ -6262,63 +6271,12 @@
static void
do_sxth (char * str)
{
- int rot;
-
- int rotation_clear_mask = 0xfffff3ff;
- int rotation_eight_mask = 0x00000400;
- int rotation_sixteen_mask = 0x00000800;
- int rotation_twenty_four_mask = 0x00000c00;
-
- reg_nonpc_or_fail (&str, 12);
- comma_or_fail (&str);
-
- reg_nonpc_or_fail (&str, 0);
-
- /* Zero out the rotation field. */
- inst.instruction &= rotation_clear_mask;
-
- /* Check for lack of optional rotation field. */
- if (skip_past_comma (&str) == FAIL)
- {
- end_of_line (str);
- return;
- }
-
- /* Move past 'ROR'. */
- if (strncasecmp (str, "ROR", 3) == 0)
- str += 3;
- else
- {
- inst.error = _("missing rotation field after comma");
- return;
- }
-
- /* Get the immediate constant. */
- if (immediate_required_here (&str, &rot, 0, 24, FALSE) == FAIL)
+ if (parse_operands (str, OPERANDS3(RRnpc,RRnpc,oROR)))
return;
- switch (rot)
- {
- case 0:
- /* Rotation field has already been zeroed. */
- break;
- case 8:
- inst.instruction |= rotation_eight_mask;
- break;
- case 16:
- inst.instruction |= rotation_sixteen_mask;
- break;
-
- case 24:
- inst.instruction |= rotation_twenty_four_mask;
- break;
-
- default:
- inst.error = _("rotation can be 8, 16, 24 or 0 when field is ommited");
- break;
- }
-
- end_of_line (str);
+ inst.instruction |= (inst.operands[0].reg << 12);
+ inst.instruction |= (inst.operands[1].reg << 0);
+ inst.instruction |= (inst.operands[2].imm << 10);
}