This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
Thumb32 assembler (39/69)
- From: Zack Weinberg <zack at codesourcery dot com>
- To: binutils <binutils at sourceware dot org>
- Date: Tue, 26 Apr 2005 02:55:12 -0700
- Subject: Thumb32 assembler (39/69)
Refactor thumb_mov_compare so it can be used directly as an encoder
function in tinsns[]. Also, minor adjustments to md_apply_fix3.
zw
* config/tc-arm.c (THUMB_MOVE, THUMB_COMPARE, THUMB_CPY, do_t_compare)
(do_t_mov): Delete.
(thumb_mov_compare): Rename do_t_mov_cmp. Don't handle cpy here.
Use parse_operands. Remove 'move' argument; look at inst.instruction
to distinguish mov from cmp. Assume inst.instruction is correct for
HR case. Defer all immediate value handling to md_apply_fix3.
(tinsns): Use do_t_mov_cmp for mov and cmp. Set their opcodes to
T_OPCODE_MOV_HR and T_OPCODE_CMP_HR respectively.
(md_apply_fix3 <case BFD_RELOC_ARM_THUMB_IMM>): For consistency with
other cases, remove extra sanity checks.
===================================================================
Index: gas/config/tc-arm.c
--- gas/config/tc-arm.c (revision 41)
+++ gas/config/tc-arm.c (revision 42)
@@ -560,10 +560,6 @@
#define THUMB_H1 0x0080
#define THUMB_H2 0x0040
-#define THUMB_MOVE 0
-#define THUMB_COMPARE 1
-#define THUMB_CPY 2
-
#define THUMB_LOAD 0
#define THUMB_STORE 1
@@ -6566,86 +6562,49 @@
}
static void
-thumb_mov_compare (char * str, int move)
+do_t_mov_cmp (char * str)
{
- int Rd, Rs = FAIL;
-
- if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
- || skip_past_comma (&str) == FAIL)
- {
- if (! inst.error)
- inst.error = BAD_ARGS;
- return;
- }
-
- if (move != THUMB_CPY && is_immediate_prefix (*str))
- {
- str++;
- expression_or_fail (&inst.reloc.exp, &str);
- }
- else if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
+ if (parse_operands (str, OPERANDS2(RR,RR_iEX)))
return;
- if (Rs != FAIL)
+ if (inst.operands[1].isreg)
{
- if (move != THUMB_CPY && Rs < 8 && Rd < 8)
+ if (inst.operands[0].reg < 8 && inst.operands[1].reg < 8)
{
- if (move == THUMB_MOVE)
- /* A move of two lowregs is encoded as ADD Rd, Rs, #0
- since a MOV instruction produces unpredictable results. */
+ /* A move of two lowregs is encoded as ADD Rd, Rs, #0
+ since a MOV instruction produces unpredictable results. */
+ if (inst.instruction == T_OPCODE_MOV_HR)
inst.instruction = T_OPCODE_ADD_I3;
else
inst.instruction = T_OPCODE_CMP_LR;
- inst.instruction |= Rd | (Rs << 3);
+
+ inst.instruction |= inst.operands[0].reg;
+ inst.instruction |= inst.operands[1].reg << 3;
}
else
{
- if (move == THUMB_MOVE)
- inst.instruction = T_OPCODE_MOV_HR;
- else if (move != THUMB_CPY)
- inst.instruction = T_OPCODE_CMP_HR;
-
- if (Rd > 7)
- inst.instruction |= THUMB_H1;
-
- if (Rs > 7)
- inst.instruction |= THUMB_H2;
-
- inst.instruction |= (Rd & 7) | ((Rs & 7) << 3);
+ /* Opcode in inst.instruction is already correct. */
+ inst.instruction |= (inst.operands[0].reg & 0x8) << 4;
+ inst.instruction |= (inst.operands[0].reg & 0x7);
+ inst.instruction |= inst.operands[1].reg << 3;
}
}
else
{
- if (Rd > 7)
+ if (inst.operands[0].reg > 7)
{
inst.error = _("only lo regs allowed with immediate");
return;
}
- if (move == THUMB_MOVE)
+ if (inst.instruction == T_OPCODE_MOV_HR)
inst.instruction = T_OPCODE_MOV_I8;
else
inst.instruction = T_OPCODE_CMP_I8;
- inst.instruction |= Rd << 8;
-
- if (inst.reloc.exp.X_op != O_constant)
- inst.reloc.type = BFD_RELOC_ARM_THUMB_IMM;
- else
- {
- unsigned value = inst.reloc.exp.X_add_number;
-
- if (value > 255)
- {
- inst.error = _("invalid immediate");
- return;
- }
-
- inst.instruction |= value;
- }
+ inst.instruction |= inst.operands[0].reg << 8;
+ inst.reloc.type = BFD_RELOC_ARM_THUMB_IMM;
}
-
- end_of_line (str);
}
static void
@@ -6848,12 +6807,6 @@
because BX PC only works if the instruction is word aligned. */
}
-static void
-do_t_compare (char * str)
-{
- thumb_mov_compare (str, THUMB_COMPARE);
-}
-
/* THUMB CPS instruction (argument parse). */
static void
@@ -6870,7 +6823,12 @@
static void
do_t_cpy (char * str)
{
- thumb_mov_compare (str, THUMB_CPY);
+ if (parse_operands (str, OPERANDS2(RR,RR)))
+ return;
+
+ inst.instruction |= (inst.operands[0].reg & 0x8) << 4;
+ inst.instruction |= (inst.operands[0].reg & 0x7) << 0;
+ inst.instruction |= inst.operands[1].reg << 3;
}
static void
@@ -6933,12 +6891,6 @@
}
static void
-do_t_mov (char * str)
-{
- thumb_mov_compare (str, THUMB_MOVE);
-}
-
-static void
do_t_push_pop (char * str)
{
if (parse_operands (str, OPERANDS1(REGLST)))
@@ -9781,7 +9733,7 @@
{"bl", 0xf7fffffe, 4, ARM_EXT_V4T, do_t_branch23},
{"bx", 0x4700, 2, ARM_EXT_V4T, do_t_bx},
{"cmn", T_OPCODE_CMN, 2, ARM_EXT_V4T, do_t_arit},
- {"cmp", 0x0000, 2, ARM_EXT_V4T, do_t_compare},
+ {"cmp", T_OPCODE_CMP_HR,2, ARM_EXT_V4T, do_t_mov_cmp},
{"eor", 0x4040, 2, ARM_EXT_V4T, do_t_arit},
{"ldmia", 0xc800, 2, ARM_EXT_V4T, do_t_ldmstm},
{"ldr", 0x0000, 2, ARM_EXT_V4T, do_t_ldr},
@@ -9793,7 +9745,7 @@
{"ldsh", 0x5e00, 2, ARM_EXT_V4T, do_t_lds},
{"lsl", 0x4080, 2, ARM_EXT_V4T, do_t_shift},
{"lsr", 0x40c0, 2, ARM_EXT_V4T, do_t_shift},
- {"mov", 0x0000, 2, ARM_EXT_V4T, do_t_mov},
+ {"mov", T_OPCODE_MOV_HR,2, ARM_EXT_V4T, do_t_mov_cmp},
{"mul", T_OPCODE_MUL, 2, ARM_EXT_V4T, do_t_arit},
{"mvn", T_OPCODE_MVN, 2, ARM_EXT_V4T, do_t_arit},
{"neg", T_OPCODE_NEG, 2, ARM_EXT_V4T, do_t_arit},
@@ -11174,20 +11126,11 @@
case BFD_RELOC_ARM_THUMB_IMM:
newval = md_chars_to_number (buf, THUMB_SIZE);
- switch (newval >> 11)
- {
- case 0x04: /* 8bit immediate MOV. */
- case 0x05: /* 8bit immediate CMP. */
- if (value < 0 || value > 255)
- as_bad_where (fixP->fx_file, fixP->fx_line,
- _("invalid immediate: %ld is too large"),
- (long) value);
- newval |= value;
- break;
-
- default:
- abort ();
- }
+ if (value < 0 || value > 255)
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("invalid immediate: %ld is too large"),
+ (long) value);
+ newval |= value;
md_number_to_chars (buf, newval, THUMB_SIZE);
break;