This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
Thumb32 assembler (31/69)
- From: Zack Weinberg <zack at codesourcery dot com>
- To: binutils <binutils at sourceware dot org>
- Date: Tue, 26 Apr 2005 02:54:50 -0700
- Subject: Thumb32 assembler (31/69)
Flesh out RR_EX, and use it for BLX; add a "register or immediate
zero" code, and use it for BFI.
zw
* config/tc-arm.c (thumb_reg): Simplify. Use BAD_HIREG.
(OP_RRnpc_I0): New operand parse code.
(parse_operands): Implement it and OP_RR_EX.
(do_bfi): Use parse_operands.
(do_t_blx): Likewise. Assume inst.instruction is preloaded
with BLX(2).
(tinsns): Preload opcode and size fields for blx with BLX(2).
===================================================================
Index: gas/config/tc-arm.c
--- gas/config/tc-arm.c (revision 32)
+++ gas/config/tc-arm.c (revision 33)
@@ -1262,20 +1262,11 @@
if ((reg = reg_required_here (strp, -1, REG_TYPE_RN)) == FAIL)
return FAIL;
- switch (hi_lo)
+ if (hi_lo == THUMB_REG_LO && reg > 7)
{
- case THUMB_REG_LO:
- if (reg > 7)
- {
- inst.error = _("lo register required");
- return FAIL;
- }
- break;
-
- default:
- break;
+ inst.error = BAD_HIREG;
+ return FAIL;
}
-
return reg;
}
@@ -4352,6 +4343,7 @@
/* 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 */
/* Optional operands. All have the high bit set. */
#define OP_obI7 200 /* optional, prefix optional, immediate 0 .. 7 */
@@ -4555,7 +4547,17 @@
/* Register or expression */
case OP_(RR_EX):
- abort ();
+ {
+ 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_(oRL_iEX):
case OP_(RL_iEX):
@@ -4573,6 +4575,22 @@
}
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);
+ }
+ break;
+
/* Misc */
case OP_(CPSF):
if (parse_cps_flags (&inst.operands[i].imm, &str))
@@ -4746,36 +4764,16 @@
static void
do_bfi (char *str)
{
- int rm, lsb, width, msb;
+ unsigned int msb;
+ if (parse_operands (str, OPERANDS4(RRnpc,RRnpc_I0,I31,I32)))
+ return;
- /* Rd. */
- reg_nonpc_or_fail (&str, 12);
- comma_or_fail (&str);
+ /* #0 in second position is alternative syntax for bfc, which is
+ the same instruction but with REG_PC in the Rm field. */
+ if (!inst.operands[1].isreg)
+ inst.operands[1].reg = REG_PC;
- /* Rm. Accept #0 in this position as an alternative syntax for bfc. */
- if ((rm = reg_required_here (&str, 0, REG_TYPE_RN)) == 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. */
- }
-
- if (rm == REG_PC)
- {
- inst.error = BAD_PC;
- 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);
-
- msb = width + lsb;
+ msb = inst.operands[2].imm + inst.operands[3].imm;
if (msb > 32)
{
inst.error = _("bit-field extends past end of register");
@@ -4784,7 +4782,9 @@
/* The instruction encoding stores the LSB and MSB,
not the LSB and width. */
- inst.instruction |= (lsb << 7);
+ inst.instruction |= (inst.operands[0].reg << 12);
+ inst.instruction |= (inst.operands[1].reg << 0);
+ inst.instruction |= (inst.operands[2].imm << 7);
inst.instruction |= (msb - 1) << 16;
}
@@ -6901,30 +6901,20 @@
static void
do_t_blx (char * str)
{
- int rm;
+ if (parse_operands (str, OPERANDS1(RR_EX)))
+ return;
- /* BLX(2) can be applied to any integer register. */
- rm = thumb_reg (&str, THUMB_REG_ANY);
-
- if (rm != FAIL)
- {
- /* We have a register, so this is BLX(2). */
- inst.instruction = 0x4780;
- inst.size = 2;
- inst.instruction |= (rm << 3);
- }
+ if (inst.operands[0].isreg)
+ /* We have a register, so this is BLX(2). */
+ inst.instruction |= (inst.operands[0].reg << 3);
else
{
/* No register. This must be BLX(1). */
- expression_or_fail (&inst.reloc.exp, &str);
-
inst.instruction = 0xf7ffeffe;
inst.size = 4;
inst.reloc.type = BFD_RELOC_THUMB_PCREL_BLX;
inst.reloc.pc_rel = 1;
}
-
- end_of_line (str);
}
static void
@@ -9987,7 +9977,7 @@
{"adr", 0x000f, 2, ARM_EXT_V4T, do_t_adr},
{"nop", 0x46C0, 2, ARM_EXT_V4T, do_empty}, /* mov r8,r8 */
/* Thumb v2 (ARMv5T). */
- {"blx", 0, 0, ARM_EXT_V5T, do_t_blx},
+ {"blx", 0x4780, 2, ARM_EXT_V5T, do_t_blx},
{"bkpt", 0xbe00, 2, ARM_EXT_V5T, do_t_bkpt},
/* ARM V6. */