This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
Thumb32 assembler (56/69)
- From: Zack Weinberg <zack at codesourcery dot com>
- To: binutils <binutils at sourceware dot org>
- Date: Tue, 26 Apr 2005 03:00:28 -0700
- Subject: Thumb32 assembler (56/69)
Introduce more compact notation for the very common construction
if (expr)
{
inst.error = diagnostic;
return;
}
zw
* config/tc-arm.c (BAD_COND): Clarify message.
(reject_overlap): Delete.
(constraint): New macro.
(do_bfc, do_bfi, do_bfx, encode_branch, do_blx, do_ldrd, do_ldstt)
(do_ldsttv4, do_mrs, do_pld, do_strex, do_t_add_sub, do_t_arit3)
(do_t_ldmstm, do_t_lds, do_t_ldst, do_t_mov_cmp, do_t_shift)
(do_t_push_pop, do_vfp_reg2_from_sp2, do_vfp_sp2_from_reg2)
(vfp_sp_ldstm, vfp_dp_ldstm, do_fpa_ldmstm, do_iwmmxt_tandorc)
(do_iwmmxt_wldstw, do_xsc_mra): Use constraint.
===================================================================
Index: gas/config/tc-arm.c
--- gas/config/tc-arm.c (revision 58)
+++ gas/config/tc-arm.c (revision 59)
@@ -452,7 +452,7 @@
#define BAD_ARGS _("bad arguments to instruction")
#define BAD_PC _("r15 not allowed here")
-#define BAD_COND _("instruction is not conditional")
+#define BAD_COND _("instruction cannot be conditional")
#define BAD_OVERLAP _("registers may not be the same")
#define BAD_HIREG _("lo register required")
@@ -4147,31 +4147,16 @@
#undef po_reg_or_goto
#undef po_imm_or_fail
-/* Operand validation functions. */
-
-/* Set inst.error to BAD_OVERLAP and return FAIL if any of the
- specified pairs of register operands are the same. N is the number
- of pairs. */
-static int
-reject_overlap (int n, ...)
-{
- va_list ap;
- va_start (ap, n);
- while (n--)
- {
- int op1 = va_arg (ap, int);
- int op2 = va_arg (ap, int);
- if (inst.operands[op1].reg == inst.operands[op2].reg)
- {
- inst.error = BAD_OVERLAP;
- return FAIL;
- }
- }
- va_end (ap);
- return SUCCESS;
-}
-
+/* Shorthand macro for instruction encoding functions issuing errors. */
+#define constraint(expr, err) do { \
+ if (expr) \
+ { \
+ inst.error = err; \
+ return; \
+ } \
+} while (0)
+
/* Functions for instruction encoding, sorted by subarchitecture.
First some generics; their names are taken from the conventional
bit positions for register arguments in ARM format instructions. */
@@ -4298,12 +4283,7 @@
do_bfc (void)
{
unsigned int msb = inst.operands[1].imm + inst.operands[2].imm;
- if (msb > 32)
- {
- inst.error = _("bit-field extends past end of register");
- return;
- }
-
+ constraint (msb > 32, _("bit-field extends past end of register"));
/* The instruction encoding stores the LSB and MSB,
not the LSB and width. */
inst.instruction |= inst.operands[0].reg << 12;
@@ -4322,12 +4302,7 @@
inst.operands[1].reg = REG_PC;
msb = inst.operands[2].imm + inst.operands[3].imm;
- if (msb > 32)
- {
- inst.error = _("bit-field extends past end of register");
- return;
- }
-
+ constraint (msb > 32, _("bit-field extends past end of register"));
/* The instruction encoding stores the LSB and MSB,
not the LSB and width. */
inst.instruction |= inst.operands[0].reg << 12;
@@ -4339,12 +4314,8 @@
static void
do_bfx (void)
{
- if (inst.operands[2].imm + inst.operands[3].imm > 32)
- {
- inst.error = _("bit-field extends past end of register");
- return;
- }
-
+ constraint (inst.operands[2].imm + inst.operands[3].imm > 32,
+ _("bit-field extends past end of register"));
inst.instruction |= inst.operands[0].reg << 12;
inst.instruction |= inst.operands[1].reg;
inst.instruction |= inst.operands[2].imm << 7;
@@ -4372,11 +4343,8 @@
{
if (inst.operands[0].hasreloc)
{
- if (inst.operands[0].imm != BFD_RELOC_ARM_PLT32)
- {
- inst.error = _("the only suffix valid here is '(plt)'");
- return;
- }
+ constraint (inst.operands[0].imm != BFD_RELOC_ARM_PLT32,
+ _("the only suffix valid here is '(plt)'"));
inst.reloc.type = BFD_RELOC_ARM_PLT32;
inst.reloc.pc_rel = 0;
}
@@ -4417,11 +4385,7 @@
{
/* Arg is an address; this instruction cannot be executed
conditionally, and the opcode must be adjusted. */
- if ((inst.instruction & COND_MASK) != COND_ALWAYS)
- {
- inst.error = BAD_COND;
- return;
- }
+ constraint ((inst.instruction & COND_MASK) != COND_ALWAYS, BAD_COND);
inst.instruction = 0xfafffffe;
encode_branch (BFD_RELOC_ARM_PCREL_BLX);
}
@@ -4566,23 +4530,10 @@
static void
do_ldrd (void)
{
- if (!inst.operands[1].isreg)
- {
- inst.error = _("'[' expected");
- return;
- }
-
- if (inst.operands[0].reg % 2 != 0)
- {
- inst.error = _("destination register must be even");
- return;
- }
- if (inst.operands[0].reg == REG_LR)
- {
- inst.error = _("r14 not allowed here");
- return;
- }
-
+ constraint (!inst.operands[1].isreg, _("'[' expected"));
+ constraint (inst.operands[0].reg % 2 != 0,
+ _("destination register must be even"));
+ constraint (inst.operands[0].reg == REG_LR, _("r14 not allowed here"));
if (inst.instruction & LOAD_BIT)
{
/* encode_addr_mode_3_arm will diagnose overlap between the base
@@ -4623,17 +4574,13 @@
reject [Rn,...]. */
if (inst.operands[1].preind)
{
- if (inst.reloc.exp.X_op == O_constant && inst.reloc.exp.X_add_number == 0)
- {
- inst.operands[1].preind = 0;
- inst.operands[1].postind = 1;
- inst.operands[1].writeback = 1;
- }
- else
- {
- inst.error = _("this instruction requires a post-indexed address");
- return;
- }
+ constraint (inst.reloc.exp.X_op != O_constant ||
+ inst.reloc.exp.X_add_number != 0,
+ _("this instruction requires a post-indexed address"));
+
+ inst.operands[1].preind = 0;
+ inst.operands[1].postind = 1;
+ inst.operands[1].writeback = 1;
}
inst.instruction |= inst.operands[0].reg << 12;
encode_addr_mode_2_arm (1, /*is_t=*/TRUE);
@@ -4658,17 +4605,13 @@
reject [Rn,...]. */
if (inst.operands[1].preind)
{
- if (inst.reloc.exp.X_op == O_constant && inst.reloc.exp.X_add_number == 0)
- {
- inst.operands[1].preind = 0;
- inst.operands[1].postind = 1;
- inst.operands[1].writeback = 1;
- }
- else
- {
- inst.error = _("this instruction requires a post-indexed address");
- return;
- }
+ constraint (inst.reloc.exp.X_op != O_constant ||
+ inst.reloc.exp.X_add_number != 0,
+ _("this instruction requires a post-indexed address"));
+
+ inst.operands[1].preind = 0;
+ inst.operands[1].postind = 1;
+ inst.operands[1].writeback = 1;
}
inst.instruction |= inst.operands[0].reg << 12;
encode_addr_mode_3_arm (1, /*is_t=*/TRUE);
@@ -4721,12 +4664,9 @@
do_mrs (void)
{
/* mrs only accepts CPSR/SPSR/CPSR_all/SPSR_all. */
- if ((inst.operands[1].imm & (PSR_c|PSR_x|PSR_s|PSR_f)) != (PSR_c|PSR_f))
- {
- inst.error = _("'CPSR' or 'SPSR' expected");
- return;
- }
-
+ constraint ((inst.operands[1].imm & (PSR_c|PSR_x|PSR_s|PSR_f))
+ != (PSR_c|PSR_f),
+ _("'CPSR' or 'SPSR' expected"));
inst.instruction |= inst.operands[0].reg << 12;
inst.instruction |= (inst.operands[1].imm & SPSR_BIT);
}
@@ -4839,27 +4779,14 @@
static void
do_pld (void)
{
- if (!inst.operands[0].isreg)
- {
- inst.error = _("'[' expected after PLD mnemonic");
- return;
- }
- if (inst.operands[0].postind)
- {
- inst.error = _("post-indexed expression used in preload instruction");
- return;
- }
- if (inst.operands[0].writeback)
- {
- inst.error = _("writeback used in preload instruction");
- return;
- }
- if (!inst.operands[0].preind)
- {
- inst.error = _("unindexed addressing used in preload instruction");
- return;
- }
-
+ constraint (!inst.operands[0].isreg,
+ _("'[' expected after PLD mnemonic"));
+ constraint (inst.operands[0].postind,
+ _("post-indexed expression used in preload instruction"));
+ constraint (inst.operands[0].writeback,
+ _("writeback used in preload instruction"));
+ constraint (!inst.operands[0].preind,
+ _("unindexed addressing used in preload instruction"));
inst.instruction |= inst.operands[0].reg;
encode_addr_mode_2_arm (0, /*is_t=*/FALSE);
}
@@ -5007,8 +4934,8 @@
static void
do_strex (void)
{
- if (reject_overlap (2, 0,1, 0,2))
- return;
+ constraint (inst.operands[0].reg == inst.operands[1].reg
+ || inst.operands[0].reg == inst.operands[2].reg, BAD_OVERLAP);
inst.instruction |= inst.operands[0].reg << 12;
inst.instruction |= inst.operands[1].reg;
@@ -5075,19 +5002,9 @@
/* We now have Rd, Rs, and Rn set to registers. */
if (Rd > 7 || Rs > 7 || Rn > 7)
{
- if (Rs != Rd)
- {
- inst.error = _("dest and source1 must be the same register");
- return;
- }
-
+ constraint (Rs != Rd, _("dest and source1 must be the same register"));
/* Can't do this for SUB. */
- if (subtract)
- {
- inst.error = _("subtract valid only on lo regs");
- return;
- }
-
+ constraint (subtract, _("subtract valid only on lo regs"));
inst.instruction = T_OPCODE_ADD_HI;
inst.instruction |= (Rd & 8) << 4;
inst.instruction |= (Rd & 7);
@@ -5130,12 +5047,10 @@
static void
do_t_arit3 (void)
{
- if (inst.operands[1].present
- && inst.operands[0].reg != inst.operands[1].reg)
- {
- inst.error = _("dest and source1 must be the same register");
- return;
- }
+ constraint (inst.operands[1].present
+ && inst.operands[0].reg != inst.operands[1].reg,
+ _("dest and source1 must be the same register"));
+
inst.instruction |= inst.operands[0].reg;
inst.instruction |= inst.operands[2].reg << 3;
}
@@ -5217,23 +5132,13 @@
static void
do_t_ldmstm (void)
{
- if (inst.reloc.type != BFD_RELOC_UNUSED)
- {
- /* This really doesn't seem worth it. */
- inst.reloc.type = BFD_RELOC_UNUSED;
- inst.error = _("expression too complex");
- return;
- }
- if (inst.operands[1].imm & ~0xff)
- {
- inst.error = _("only lo-regs valid in load/store multiple");
- return;
- }
- if (inst.operands[1].writeback)
- {
- inst.error = _("Thumb load/store multiple does not support {reglist}^");
- return;
- }
+ /* This really doesn't seem worth it. */
+ constraint (inst.reloc.type != BFD_RELOC_UNUSED,
+ _("expression too complex"));
+ constraint (inst.operands[1].imm & ~0xff,
+ _("only lo-regs valid in load/store multiple"));
+ constraint (inst.operands[1].writeback,
+ _("Thumb load/store multiple does not support {reglist}^"));
if (!inst.operands[0].writeback)
as_warn (_("Thumb load/store multiple always writes back base register"));
@@ -5245,18 +5150,11 @@
do_t_lds (void)
{
/* Only [Rn,Rm] is acceptable. */
- if (!inst.operands[1].isreg || !inst.operands[1].immisreg
- || inst.operands[1].postind || inst.operands[1].shifted
- || inst.operands[1].negative)
- {
- inst.error = _("invalid addressing mode");
- return;
- }
- if (inst.operands[1].reg > 7 || inst.operands[1].imm > 7)
- {
- inst.error = BAD_HIREG;
- return;
- }
+ constraint (!inst.operands[1].isreg || !inst.operands[1].immisreg
+ || inst.operands[1].postind || inst.operands[1].shifted
+ || inst.operands[1].negative,
+ _("invalid addressing mode"));
+ constraint (inst.operands[1].reg > 7 || inst.operands[1].imm > 7, BAD_HIREG);
inst.instruction |= inst.operands[0].reg;
inst.instruction |= inst.operands[1].reg << 3;
@@ -5270,30 +5168,17 @@
if (move_or_literal_pool (0, /*thumb_p=*/TRUE, /*mode_3=*/FALSE))
return;
- if (!inst.operands[1].preind || inst.operands[1].shifted)
- {
- inst.error = _("Thumb does not support this addressing mode");
- return;
- }
-
+ constraint (!inst.operands[1].preind || inst.operands[1].shifted,
+ _("Thumb does not support this addressing mode"));
if (inst.operands[1].reg == REG_PC || inst.operands[1].reg == REG_SP)
{
- if (inst.instruction & 0x0600)
- {
- inst.error = _("byte or halfword not valid for base register");
- return;
- }
- else if (inst.operands[1].reg == REG_PC
- && !(inst.instruction & THUMB_LOAD_BIT))
- {
- inst.error = _("r15 based store not allowed");
- return;
- }
- else if (inst.operands[1].immisreg)
- {
- inst.error = _("invalid base register for register offset");
- return;
- }
+ constraint (inst.instruction & 0x0600,
+ _("byte or halfword not valid for base register"));
+ constraint (inst.operands[1].reg == REG_PC
+ && !(inst.instruction & THUMB_LOAD_BIT),
+ _("r15 based store not allowed"));
+ constraint (inst.operands[1].immisreg,
+ _("invalid base register for register offset"));
if (inst.operands[1].reg == REG_PC)
inst.instruction = T_OPCODE_LDR_PC;
@@ -5309,11 +5194,7 @@
return;
}
- if (inst.operands[0].reg > 7)
- {
- inst.error = BAD_HIREG;
- return;
- }
+ constraint (inst.operands[0].reg > 7, BAD_HIREG);
if (!inst.operands[1].immisreg)
{
@@ -5336,16 +5217,9 @@
else
{
/* Register offset. Opcode is already correct. */
- if (inst.operands[1].reg > 7)
- {
- inst.error = BAD_HIREG;
- return;
- }
- else if (inst.operands[1].negative)
- {
- inst.error = _("Thumb does not support [Rn,-Rm] addressing");
- return;
- }
+ constraint (inst.operands[1].reg > 7, BAD_HIREG);
+ constraint (inst.operands[1].negative,
+ _("Thumb does not support [Rn,-Rm] addressing"));
inst.instruction |= inst.operands[0].reg;
inst.instruction |= inst.operands[1].reg << 3;
inst.instruction |= inst.operands[1].imm << 6;
@@ -5374,12 +5248,8 @@
}
else
{
- if (inst.operands[0].reg > 7)
- {
- inst.error = _("only lo regs allowed with immediate");
- return;
- }
-
+ constraint (inst.operands[0].reg > 7,
+ _("only lo regs allowed with immediate"));
if (inst.instruction == T_OPCODE_MOV_HR)
inst.instruction = T_OPCODE_MOV_I8;
else
@@ -5407,11 +5277,8 @@
if (inst.operands[2].isreg) /* Rd, {Rs,} Rn */
{
- if (inst.operands[0].reg != Rs)
- {
- inst.error = _("source1 and dest must be same register");
- return;
- }
+ constraint (inst.operands[0].reg != Rs,
+ _("source1 and dest must be same register"));
inst.instruction |= inst.operands[0].reg;
inst.instruction |= inst.operands[2].reg << 3;
return;
@@ -5438,18 +5305,11 @@
static void
do_t_push_pop (void)
{
- if (inst.operands[0].writeback)
- {
- inst.error = _("push/pop do not support {reglist}^");
- return;
- }
- if (inst.reloc.type != BFD_RELOC_UNUSED)
- {
- /* This really doesn't seem worth it. */
- inst.reloc.type = BFD_RELOC_UNUSED;
- inst.error = _("expression too complex");
- return;
- }
+ constraint (inst.operands[0].writeback,
+ _("push/pop do not support {reglist}^"));
+ constraint (inst.reloc.type != BFD_RELOC_UNUSED,
+ _("expression too complex"));
+
if (inst.operands[0].imm & ~0xff)
{
if ((inst.instruction == T_OPCODE_PUSH
@@ -5518,12 +5378,8 @@
static void
do_vfp_reg2_from_sp2 (void)
{
- if (inst.operands[2].imm != 2)
- {
- inst.error = _("only two consecutive VFP SP registers allowed here");
- return;
- }
-
+ constraint (inst.operands[2].imm != 2,
+ _("only two consecutive VFP SP registers allowed here"));
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);
@@ -5539,12 +5395,8 @@
static void
do_vfp_sp2_from_reg2 (void)
{
- if (inst.operands[0].imm != 2)
- {
- inst.error = _("only two consecutive VFP SP registers allowed here");
- return;
- }
-
+ constraint (inst.operands[0].imm != 2,
+ _("only two consecutive VFP SP registers allowed here"));
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;
@@ -5570,12 +5422,9 @@
{
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;
- }
-
+ else
+ constraint (ldstm_type != VFP_LDSTMIA,
+ _("this addressing mode requires base-register writeback"));
inst.instruction |= inst.operands[0].reg << 16;
vfp_sp_encode_reg (inst.operands[1].reg, VFP_REG_Sd);
inst.instruction |= inst.operands[1].imm;
@@ -5588,11 +5437,9 @@
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;
- }
+ else
+ constraint (ldstm_type != VFP_LDSTMIA && ldstm_type != VFP_LDSTMIAX,
+ _("this addressing mode requires base-register writeback"));
inst.instruction |= inst.operands[0].reg << 16;
inst.instruction |= inst.operands[1].reg << 12;
@@ -5669,12 +5516,9 @@
[Rn]{!}. The instruction does not really support stacking or
unstacking, so we have to emulate these by setting appropriate
bits and offsets. */
- if (inst.reloc.exp.X_op != O_constant
- || inst.reloc.exp.X_add_number != 0)
- {
- inst.error = _("this instruction does not support indexing");
- return;
- }
+ constraint (inst.reloc.exp.X_op != O_constant
+ || inst.reloc.exp.X_add_number != 0,
+ _("this instruction does not support indexing"));
if (inst.operands[2].writeback)
inst.instruction |= WRITE_BACK;
if (inst.instruction & (PRE_INDEX | WRITE_BACK))
@@ -5697,8 +5541,7 @@
static void
do_iwmmxt_tandorc (void)
{
- if (inst.operands[0].reg != REG_PC)
- inst.error = _("only r15 allowed here");
+ constraint (inst.operands[0].reg != REG_PC, _("only r15 allowed here"));
}
static void
@@ -5763,12 +5606,7 @@
/* RIWR_RIWC clears .isreg for a control register. */
if (!inst.operands[0].isreg)
{
- if ((inst.instruction & COND_MASK) != COND_ALWAYS)
- {
- inst.error = _("conditional execution not supported "
- "with control register");
- return;
- }
+ constraint ((inst.instruction & COND_MASK) != COND_ALWAYS, BAD_COND);
inst.instruction |= 0xf0000000;
}
@@ -5878,9 +5716,7 @@
static void
do_xsc_mra (void)
{
- if (reject_overlap (1, 0,1))
- return;
-
+ constraint (inst.operands[0].reg == inst.operands[1].reg, BAD_OVERLAP);
inst.instruction |= inst.operands[0].reg << 12;
inst.instruction |= inst.operands[1].reg << 16;
}