This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
Thumb-2 shift aliases
- From: Paul Brook <paul at codesourcery dot com>
- To: binutils at sourceware dot org
- Date: Thu, 14 Jun 2007 23:06:01 +0100
- Subject: Thumb-2 shift aliases
The patch below makes ARM gas accept
mov reg, reg, <shift> N
as an alias for
<shift> reg, reg, N
In unified syntax Thumb mode.
Also corresponding bits added to the testsuite.
Tested on arm-none-eabi.
Applied to CVS head.
Paul
2007-06-14 Paul Brook <paul@codesourcery.com>
gas/
* config/tc-arm.c (do_t_mov_cmp): Handle shift by register and
narrow shift by immediate.
gas/testsuite/
* gas/arm/thumb32.s: Add tests for shift instructions.
* gas/arm/thumb32.d: Ditto.
Index: gas/config/tc-arm.c
===================================================================
RCS file: /var/cvsroot/src-cvs/src/gas/config/tc-arm.c,v
retrieving revision 1.330
diff -u -p -r1.330 tc-arm.c
--- gas/config/tc-arm.c 6 Jun 2007 17:36:54 -0000 1.330
+++ gas/config/tc-arm.c 14 Jun 2007 17:05:22 -0000
@@ -9544,11 +9544,98 @@ do_t_mov_cmp (void)
inst.reloc.type = BFD_RELOC_ARM_T32_IMMEDIATE;
}
}
+ else if (inst.operands[1].shifted && inst.operands[1].immisreg
+ && (inst.instruction == T_MNEM_mov
+ || inst.instruction == T_MNEM_movs))
+ {
+ /* Register shifts are encoded as separate shift instructions. */
+ bfd_boolean flags = (inst.instruction == T_MNEM_movs);
+
+ if (current_it_mask)
+ narrow = !flags;
+ else
+ narrow = flags;
+
+ if (inst.size_req == 4)
+ narrow = FALSE;
+
+ if (!low_regs || inst.operands[1].imm > 7)
+ narrow = FALSE;
+
+ if (inst.operands[0].reg != inst.operands[1].reg)
+ narrow = FALSE;
+
+ switch (inst.operands[1].shift_kind)
+ {
+ case SHIFT_LSL:
+ opcode = narrow ? T_OPCODE_LSL_R : THUMB_OP32 (T_MNEM_lsl);
+ break;
+ case SHIFT_ASR:
+ opcode = narrow ? T_OPCODE_ASR_R : THUMB_OP32 (T_MNEM_asr);
+ break;
+ case SHIFT_LSR:
+ opcode = narrow ? T_OPCODE_LSR_R : THUMB_OP32 (T_MNEM_lsr);
+ break;
+ case SHIFT_ROR:
+ opcode = narrow ? T_OPCODE_ROR_R : THUMB_OP32 (T_MNEM_ror);
+ break;
+ default:
+ abort();
+ }
+
+ inst.instruction = opcode;
+ if (narrow)
+ {
+ inst.instruction |= inst.operands[0].reg;
+ inst.instruction |= inst.operands[1].imm << 3;
+ }
+ else
+ {
+ if (flags)
+ inst.instruction |= CONDS_BIT;
+
+ inst.instruction |= inst.operands[0].reg << 8;
+ inst.instruction |= inst.operands[1].reg << 16;
+ inst.instruction |= inst.operands[1].imm;
+ }
+ }
else if (!narrow)
{
- inst.instruction = THUMB_OP32 (inst.instruction);
- inst.instruction |= inst.operands[0].reg << r0off;
- encode_thumb32_shifted_operand (1);
+ /* Some mov with immediate shift have narrow variants.
+ Register shifts are handled above. */
+ if (low_regs && inst.operands[1].shifted
+ && (inst.instruction == T_MNEM_mov
+ || inst.instruction == T_MNEM_movs))
+ {
+ if (current_it_mask)
+ narrow = (inst.instruction == T_MNEM_mov);
+ else
+ narrow = (inst.instruction == T_MNEM_movs);
+ }
+
+ if (narrow)
+ {
+ switch (inst.operands[1].shift_kind)
+ {
+ case SHIFT_LSL: inst.instruction = T_OPCODE_LSL_I; break;
+ case SHIFT_LSR: inst.instruction = T_OPCODE_LSR_I; break;
+ case SHIFT_ASR: inst.instruction = T_OPCODE_ASR_I; break;
+ default: narrow = FALSE; break;
+ }
+ }
+
+ if (narrow)
+ {
+ inst.instruction |= inst.operands[0].reg;
+ inst.instruction |= inst.operands[1].reg << 3;
+ inst.reloc.type = BFD_RELOC_ARM_THUMB_SHIFT;
+ }
+ else
+ {
+ inst.instruction = THUMB_OP32 (inst.instruction);
+ inst.instruction |= inst.operands[0].reg << r0off;
+ encode_thumb32_shifted_operand (1);
+ }
}
else
switch (inst.instruction)
Index: gas/testsuite/gas/arm/thumb32.d
===================================================================
RCS file: /var/cvsroot/src-cvs/src/gas/testsuite/gas/arm/thumb32.d,v
retrieving revision 1.23
diff -u -p -r1.23 thumb32.d
--- gas/testsuite/gas/arm/thumb32.d 5 Jun 2007 22:02:46 -0000 1.23
+++ gas/testsuite/gas/arm/thumb32.d 14 Jun 2007 19:44:02 -0000
@@ -1001,3 +1001,32 @@ Disassembly of section .text:
0[0-9a-f]+ <[^>]+> f935 1b30 ldrsh.w r1, \[r5\], #48
0[0-9a-f]+ <[^>]+> f935 1930 ldrsh.w r1, \[r5\], #-48
0[0-9a-f]+ <[^>]+> f935 1009 ldrsh.w r1, \[r5, r9\]
+0[0-9a-f]+ <[^>]+> 00a1 lsls r1, r4, #2
+0[0-9a-f]+ <[^>]+> ea5f 0389 movs.w r3, r9, lsl #2
+0[0-9a-f]+ <[^>]+> fa12 f103 lsls.w r1, r2, r3
+0[0-9a-f]+ <[^>]+> 4099 lsls r1, r3
+0[0-9a-f]+ <[^>]+> fa11 f109 lsls.w r1, r1, r9
+0[0-9a-f]+ <[^>]+> fa02 f103 lsl.w r1, r2, r3
+0[0-9a-f]+ <[^>]+> fa01 f103 lsl.w r1, r1, r3
+0[0-9a-f]+ <[^>]+> 08a1 lsrs r1, r4, #2
+0[0-9a-f]+ <[^>]+> ea5f 0399 movs.w r3, r9, lsr #2
+0[0-9a-f]+ <[^>]+> fa32 f103 lsrs.w r1, r2, r3
+0[0-9a-f]+ <[^>]+> 40d9 lsrs r1, r3
+0[0-9a-f]+ <[^>]+> fa31 f109 lsrs.w r1, r1, r9
+0[0-9a-f]+ <[^>]+> fa22 f103 lsr.w r1, r2, r3
+0[0-9a-f]+ <[^>]+> fa21 f103 lsr.w r1, r1, r3
+0[0-9a-f]+ <[^>]+> 10a1 asrs r1, r4, #2
+0[0-9a-f]+ <[^>]+> ea5f 03a9 movs.w r3, r9, asr #2
+0[0-9a-f]+ <[^>]+> fa52 f103 asrs.w r1, r2, r3
+0[0-9a-f]+ <[^>]+> 4119 asrs r1, r3
+0[0-9a-f]+ <[^>]+> fa51 f109 asrs.w r1, r1, r9
+0[0-9a-f]+ <[^>]+> fa42 f103 asr.w r1, r2, r3
+0[0-9a-f]+ <[^>]+> fa41 f103 asr.w r1, r1, r3
+0[0-9a-f]+ <[^>]+> ea5f 01b4 movs.w r1, r4, ror #2
+0[0-9a-f]+ <[^>]+> ea5f 03b9 movs.w r3, r9, ror #2
+0[0-9a-f]+ <[^>]+> fa72 f103 rors.w r1, r2, r3
+0[0-9a-f]+ <[^>]+> 41d9 rors r1, r3
+0[0-9a-f]+ <[^>]+> fa71 f109 rors.w r1, r1, r9
+0[0-9a-f]+ <[^>]+> fa62 f103 ror.w r1, r2, r3
+0[0-9a-f]+ <[^>]+> fa61 f103 ror.w r1, r1, r3
+0[0-9a-f]+ <[^>]+> bf00 nop
Index: gas/testsuite/gas/arm/thumb32.s
===================================================================
RCS file: /var/cvsroot/src-cvs/src/gas/testsuite/gas/arm/thumb32.s,v
retrieving revision 1.13
diff -u -p -r1.13 thumb32.s
--- gas/testsuite/gas/arm/thumb32.s 5 Jun 2007 22:02:46 -0000 1.13
+++ gas/testsuite/gas/arm/thumb32.s 14 Jun 2007 19:43:49 -0000
@@ -803,3 +803,17 @@ srs:
ldaddr sb
ldaddr h
ldaddr sh
+ .macro movshift op s="s"
+ movs r1, r4, \op #2
+ movs r3, r9, \op #2
+ movs r1, r2, \op r3
+ movs r1, r1, \op r3
+ movs r1, r1, \op r9
+ mov r1, r2, \op r3
+ mov r1, r1, \op r3
+ .endm
+ movshift lsl
+ movshift lsr
+ movshift asr
+ movshift ror
+ nop