This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
Thumb32 assembler (29/69)
- From: Zack Weinberg <zack at codesourcery dot com>
- To: binutils <binutils at sourceware dot org>
- Date: Tue, 26 Apr 2005 02:54:45 -0700
- Subject: Thumb32 assembler (29/69)
Remove THUMB_REG_HI, which is never used. Teach parse_operands about
low registers, allowing a few Thumb encode functions to be converted.
Also, t_adr would always or a constant value into inst.instruction;
squash that into the opcode in tinsns[].
zw
* config/tc-arm.c (THUMB_REG_HI): Delete.
(thumb_reg): Delete case THUMB_REG_HI.
(OP_RL, OP_RLlb, OP_RLtb, OP_obI255, OP_oRL): New operand parse codes.
(parse_operands): Handle them.
(do_t_adr, do_t_arit, do_t_bkpt, do_t_lds): Use parse_operands.
(tinsns): Adjust opcode for adr.
===================================================================
Index: gas/config/tc-arm.c
--- gas/config/tc-arm.c (revision 30)
+++ gas/config/tc-arm.c (revision 31)
@@ -547,7 +547,6 @@
#define THUMB_SIZE 2 /* Size of thumb instruction. */
#define THUMB_REG_LO 0x1
-#define THUMB_REG_HI 0x2
#define THUMB_REG_ANY 0x3
#define THUMB_H1 0x0080
@@ -1275,14 +1274,6 @@
}
break;
- case THUMB_REG_HI:
- if (reg < 8)
- {
- inst.error = _("hi register required");
- return FAIL;
- }
- break;
-
default:
break;
}
@@ -4330,7 +4321,7 @@
#define OP_RIWR 020 /* iWMMXt wR register */
#define OP_RIWC 021 /* iWMMXt wC register */
#define OP_RIWG 022 /* iWMMXt wCG register */
-#define OP_RXA 023 /* XScale accumulator register */
+#define OP_RXA 023 /* XScale accumulator register */
#define OP_EXP 024 /* arbitrary expression */
#define OP_iEXP 025 /* same, with optional immediate prefix */
@@ -4353,19 +4344,23 @@
#define OP_I31w 050 /* 0 .. 31, optional trailing ! */
#define OP_RRw 051 /* ARM register, not the PC, optional trailing ! */
+#define OP_RL 052 /* Thumb low register */
+#define OP_RLlb 053 /* Thumb low register, leading [ */
+#define OP_RLtb 054 /* Thumb low register. trailing ] */
+
#define OP_CPSF 060 /* CPS flags */
#define OP_ENDI 061 /* Endianness specifier */
/* Optional operands. All have the high bit set. */
#define OP_obI7 200 /* optional, prefix optional, immediate 0 .. 7 */
#define OP_obI31 201 /* 0 .. 31 */
-#define OP_obIffff 202 /* 0 .. 65535 */
+#define OP_obI255 202 /* 0 .. 255 */
+#define OP_obIffff 203 /* 0 .. 65535 */
+#define OP_ocI255 204 /* optional, curly-brace enclosed, imm 0 .. 255 */
-#define OP_ocI255 210 /* optional, curly-brace enclosed, imm 0 .. 255 */
+#define OP_oROR 210 /* optional rotate right 0/8/16/24 */
+#define OP_oRL 211 /* optional Thumb low register */
-#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)
@@ -4476,6 +4471,27 @@
}
break;
+ case OP_(oRL):
+ case OP_(RL):
+ po_reg_or_fail (REG_TYPE_RN);
+ if (inst.operands[i].reg > 7)
+ inst.error = _("lo register required");
+ break;
+
+ case OP_(RLlb):
+ po_char_or_fail ('[');
+ po_reg_or_fail (REG_TYPE_RN);
+ if (inst.operands[i].reg > 7)
+ inst.error = _("lo register required");
+ break;
+
+ case OP_(RLtb):
+ po_reg_or_fail (REG_TYPE_RN);
+ po_char_or_fail (']');
+ if (inst.operands[i].reg > 7)
+ inst.error = _("lo register required");
+ break;
+
/* Immediates */
case OP_(I0): po_imm_or_fail ( 0, 0, FALSE); break;
case OP_(I4): po_imm_or_fail ( 1, 4, FALSE); break;
@@ -4493,6 +4509,7 @@
case OP_(bI15): po_imm_or_fail ( 0, 15, TRUE); break;
case OP_(obI31):
case OP_(bI31): po_imm_or_fail ( 0, 31, TRUE); break;
+ case OP_(obI255): po_imm_or_fail ( 0, 255, TRUE); break;
case OP_(obIffff): po_imm_or_fail (0, 0xffff, TRUE); break;
/* Immediate variants */
@@ -6842,26 +6859,14 @@
static void
do_t_adr (char * str)
{
- int reg;
-
- /* This is a pseudo-op of the form "adr rd, label" to be converted
- into a relative address of the form "add rd, pc, #label-.-4". */
-
- /* Store Rd in temporary location inside instruction. */
- if ((reg = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
+ if (parse_operands (str, OPERANDS2(RL,EXP)))
return;
-
- comma_or_fail (&str);
- expression_or_fail (&inst.reloc.exp, &str);
inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
inst.reloc.exp.X_add_number -= 4; /* PC relative adjust. */
inst.reloc.pc_rel = 1;
- inst.instruction |= reg << 4;
- inst.instruction |= REG_PC;
-
- end_of_line (str);
+ inst.instruction |= inst.operands[0].reg << 4;
}
/* Handle the Format 4 instructions that do not have equivalents in other
@@ -6871,18 +6876,11 @@
static void
do_t_arit (char * str)
{
- int Rd, Rs, Rn;
+ if (parse_operands (str, OPERANDS3(RL,RL,oRL)))
+ return;
- if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
- || skip_past_comma (&str) == FAIL
- || (Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
+ if (inst.operands[2].present)
{
- inst.error = BAD_ARGS;
- return;
- }
-
- if (skip_past_comma (&str) != FAIL)
- {
/* Three operand format not allowed for TST, CMN, NEG and MVN.
(It isn't allowed for CMP either, but that isn't handled by this
function.) */
@@ -6894,24 +6892,19 @@
inst.error = BAD_ARGS;
return;
}
-
- if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
- return;
-
- if (Rs != Rd)
+ if (inst.operands[0].reg != inst.operands[1].reg)
{
inst.error = _("dest and source1 must be the same register");
return;
}
- Rs = Rn;
+ inst.operands[1].reg = inst.operands[2].reg;
}
-
if (inst.instruction == T_OPCODE_MUL
- && Rs == Rd)
+ && inst.operands[0].reg == inst.operands[2].reg)
as_tsktsk (_("Rs and Rd must be different in MUL"));
- inst.instruction |= Rd | (Rs << 3);
- end_of_line (str);
+ inst.instruction |= inst.operands[0].reg;
+ inst.instruction |= inst.operands[1].reg << 3;
}
static void
@@ -6926,16 +6919,10 @@
static void
do_t_bkpt (char * str)
{
- int number = 0;
+ if (parse_operands (str, OPERANDS1(obI255)))
+ return;
- /* As a convenience we allow 'bkpt' without an operand. */
- if (is_immediate_prefix (*str) || ISDIGIT (*str))
- if (immediate_required_here (&str, &number, 0, 255, TRUE) == FAIL)
- return;
-
- inst.instruction |= number;
-
- end_of_line (str);
+ inst.instruction |= inst.operands[0].imm;
}
/* ARM V5 Thumb BLX (argument parse)
@@ -7115,23 +7102,12 @@
static void
do_t_lds (char * str)
{
- int Rd, Rb, Ro;
+ if (parse_operands (str, OPERANDS3(RL,RLlb,RLtb)))
+ return;
- if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
- || skip_past_comma (&str) == FAIL
- || *str++ != '['
- || (Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL
- || skip_past_comma (&str) == FAIL
- || (Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL
- || *str++ != ']')
- {
- if (! inst.error)
- inst.error = _("syntax: ldrs[b] Rd, [Rb, Ro]");
- return;
- }
-
- inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
- end_of_line (str);
+ inst.instruction |= inst.operands[0].reg;
+ inst.instruction |= inst.operands[1].reg << 3;
+ inst.instruction |= inst.operands[2].reg << 6;
}
static void
@@ -10054,7 +10030,7 @@
{"sub", 0x0000, 2, ARM_EXT_V4T, do_t_sub},
{"tst", T_OPCODE_TST, 2, ARM_EXT_V4T, do_t_arit},
/* Pseudo ops: */
- {"adr", 0x0000, 2, ARM_EXT_V4T, do_t_adr},
+ {"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},