This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
Thumb32 assembler (36/69)
- From: Zack Weinberg <zack at codesourcery dot com>
- To: binutils <binutils at sourceware dot org>
- Date: Tue, 26 Apr 2005 02:55:05 -0700
- Subject: Thumb32 assembler (36/69)
Teach parse_operands about VFP register lists.
zw
* config/tc-arm.c (OP_REGLST, OP_VRSLST, OP_VRDLST): New operand parse
codes.
(parse_operands): Declare function-global scratch variable 'val', and
use it throughout instead of block-local scratches. Implement
VRSLST and VRDLST.
(do_vfp_reg2_from_sp2, do_vfp_sp2_from_reg, vfp_sp_ldstm, vfp_dp_ldstm):
Use parse_operands.
===================================================================
Index: gas/config/tc-arm.c
--- gas/config/tc-arm.c (revision 38)
+++ gas/config/tc-arm.c (revision 39)
@@ -4307,6 +4307,9 @@
#define OP_CPSF 060 /* CPS flags */
#define OP_ENDI 061 /* Endianness specifier */
#define OP_PSR 062 /* CPSR/SPSR mask for msr */
+#define OP_REGLST 063 /* ARM register list */
+#define OP_VRSLST 064 /* VFP single-precision register list */
+#define OP_VRDLST 065 /* VFP double-precision register list */
/* This-or-that operands. All have bit 7 set. */
#define OP_RR_EX 100 /* ARM register or expression */
@@ -4357,6 +4360,7 @@
parse_operands (char *str, const char *pattern)
{
int i;
+ int val;
unsigned const char *p = pattern;
#define po_char_or_fail(chr) do { \
@@ -4365,30 +4369,29 @@
} while (0)
#define po_reg_or_fail(regtype) do { \
- int reg_ = reg_required_here (&str, -1, regtype); \
- if (reg_ == FAIL) \
+ val = reg_required_here (&str, -1, regtype); \
+ if (val == FAIL) \
{ \
inst.error = _(reg_expected_msgs[regtype]); \
return FAIL; \
} \
- inst.operands[i].reg = reg_; \
+ inst.operands[i].reg = val; \
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) \
+ val = arm_reg_parse (&str, regtype); \
+ if (val == FAIL) \
goto label; \
\
- inst.operands[i].reg = reg_; \
+ inst.operands[i].reg = val; \
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) \
+ if (immediate_required_here (&str, &val, min, max, popt) == FAIL) \
return FAIL; \
- inst.operands[i].imm = imm_; \
+ inst.operands[i].imm = val; \
} while (0)
/* Check for a no-operand instruction, or an instruction with only
@@ -4534,15 +4537,15 @@
return FAIL;
if (inst.reloc.exp.X_op == O_symbol)
{
- int reloc = parse_reloc (&str);
- if (reloc == -1)
+ val = parse_reloc (&str);
+ if (val == -1)
{
inst.error = _("unrecognized relocation suffix");
return FAIL;
}
- else if (reloc != BFD_RELOC_UNUSED)
+ else if (val != BFD_RELOC_UNUSED)
{
- inst.operands[i].imm = reloc;
+ inst.operands[i].imm = val;
inst.operands[i].hasreloc = 1;
}
}
@@ -4572,14 +4575,13 @@
po_reg_or_fail (REG_TYPE_FN);
else
{
- int reg_;
str++;
- reg_ = fpa_immediate (&str);
- if (reg_ == FAIL)
+ val = fpa_immediate (&str);
+ if (val == FAIL)
return FAIL;
/* FPA immediates are encoded as registers 8-15.
fpa_immediate has already applied the offset. */
- inst.operands[i].reg = reg_;
+ inst.operands[i].reg = val;
inst.operands[i].isreg = 1;
}
break;
@@ -4601,14 +4603,24 @@
break;
case OP_(PSR):
- {
- int psrmask = parse_psr (&str);
- if (psrmask == FAIL)
- return FAIL;
- inst.operands[i].imm = psrmask;
- }
+ if ((val = parse_psr (&str)) == FAIL)
+ return FAIL;
+ inst.operands[i].imm = val;
break;
+ case OP_(VRSLST):
+ val = vfp_parse_reg_list (&str, &inst.operands[i].reg, 0);
+ goto vfp_reglist;
+
+ case OP_(VRDLST):
+ val = vfp_parse_reg_list (&str, &inst.operands[i].reg, 1);
+
+ vfp_reglist:
+ if (val == FAIL)
+ return FAIL;
+ inst.operands[i].imm = val;
+ break;
+
default:
as_fatal ("unhandled operand code %03o", *p);
}
@@ -7133,23 +7145,17 @@
static void
do_vfp_reg2_from_sp2 (char * str)
{
- int reg;
-
- reg_or_fail (&str, 12, REG_TYPE_RN);
- comma_or_fail (&str);
-
- reg_or_fail (&str, 16, REG_TYPE_RN);
- comma_or_fail (&str);
-
- /* We require exactly two consecutive SP registers. */
- if (vfp_parse_reg_list (&str, ®, 0) != 2)
+ if (parse_operands (str, OPERANDS3(RR,RR,VRSLST)))
+ return;
+ if (inst.operands[2].imm != 2)
{
- if (! inst.error)
- inst.error = _("only two consecutive VFP SP registers allowed here");
+ inst.error = _("only two consecutive VFP SP registers allowed here");
+ return;
}
- vfp_sp_encode_reg (reg, VFP_REG_Sm);
- end_of_line (str);
+ inst.instruction |= (inst.operands[0].reg << 12);
+ inst.instruction |= (inst.operands[1].reg << 16);
+ vfp_sp_encode_reg (inst.operands[2].reg, VFP_REG_Sm);
}
static void
@@ -7165,22 +7171,17 @@
static void
do_vfp_sp2_from_reg2 (char * str)
{
- int reg;
-
- /* We require exactly two consecutive SP registers. */
- if (vfp_parse_reg_list (&str, ®, 0) != 2)
+ if (parse_operands (str, OPERANDS3(VRSLST,RR,RR)))
+ return;
+ if (inst.operands[0].imm != 2)
{
- if (! inst.error)
- inst.error = _("only two consecutive VFP SP registers allowed here");
+ inst.error = _("only two consecutive VFP SP registers allowed here");
+ return;
}
- vfp_sp_encode_reg (reg, VFP_REG_Sm);
- comma_or_fail (&str);
- reg_or_fail (&str, 12, REG_TYPE_RN);
- comma_or_fail (&str);
-
- reg_or_fail (&str, 16, REG_TYPE_RN);
- end_of_line (str);
+ vfp_sp_encode_reg (inst.operands[0].reg, VFP_REG_Sm);
+ inst.instruction |= (inst.operands[1].reg << 12);
+ inst.instruction |= (inst.operands[2].reg << 16);
}
static void
@@ -7273,62 +7274,44 @@
static void
vfp_sp_ldstm (char * str, enum vfp_ldstm_type ldstm_type)
{
- int count;
- int reg;
-
- reg_or_fail (&str, 16, REG_TYPE_RN);
-
- if (*str == '!')
- {
- inst.instruction |= WRITE_BACK;
- str++;
- }
+ if (parse_operands (str, OPERANDS2(RRw,VRSLST)))
+ return;
+ if (inst.operands[0].writeback)
+ inst.instruction |= WRITE_BACK;
else if (ldstm_type != VFP_LDSTMIA)
{
inst.error = _("this addressing mode requires base-register writeback");
return;
}
- comma_or_fail (&str);
-
- if ((count = vfp_parse_reg_list (&str, ®, 0)) == FAIL)
- return;
- end_of_line (str);
-
- vfp_sp_encode_reg (reg, VFP_REG_Sd);
- inst.instruction |= count;
+ inst.instruction |= inst.operands[0].reg << 16;
+ vfp_sp_encode_reg (inst.operands[1].reg, VFP_REG_Sd);
+ inst.instruction |= inst.operands[1].imm;
}
static void
vfp_dp_ldstm (char * str, enum vfp_ldstm_type ldstm_type)
{
int count;
- int reg;
- reg_or_fail (&str, 16, REG_TYPE_RN);
-
- if (*str == '!')
- {
- inst.instruction |= WRITE_BACK;
- str++;
- }
+ if (parse_operands (str, OPERANDS2(RRw,VRDLST)))
+ return;
+ if (inst.operands[0].writeback)
+ inst.instruction |= WRITE_BACK;
else if (ldstm_type != VFP_LDSTMIA && ldstm_type != VFP_LDSTMIAX)
{
inst.error = _("this addressing mode requires base-register writeback");
return;
}
- comma_or_fail (&str);
+ inst.instruction |= inst.operands[0].reg << 16;
+ inst.instruction |= inst.operands[1].reg << 12;
- if ((count = vfp_parse_reg_list (&str, ®, 1)) == FAIL)
- return;
-
- count <<= 1;
+ count = inst.operands[1].imm << 1;
if (ldstm_type == VFP_LDSTMIAX || ldstm_type == VFP_LDSTMDBX)
count += 1;
- inst.instruction |= (reg << 12) | count;
- end_of_line (str);
+ inst.instruction |= count;
}
static void