2007-06-14 Paul Brook <paul@codesourcery.com>
authorPaul Brook <paul@codesourcery.com>
Thu, 14 Jun 2007 22:06:19 +0000 (22:06 +0000)
committerPaul Brook <paul@codesourcery.com>
Thu, 14 Jun 2007 22:06:19 +0000 (22:06 +0000)
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.

gas/ChangeLog
gas/config/tc-arm.c
gas/testsuite/ChangeLog
gas/testsuite/gas/arm/thumb32.d
gas/testsuite/gas/arm/thumb32.s

index dd470e75cb9119409860a5802a62fe81df751cd6..a418e704887b7e56ea600a780c8673124c8218cf 100644 (file)
@@ -1,3 +1,8 @@
+2007-06-14  Paul Brook  <paul@codesourcery.com>
+
+       * config/tc-arm.c (do_t_mov_cmp): Handle shift by register and
+       narrow shift by immediate.
+
 2007-06-14  H.J. Lu  <hongjiu.lu@intel.com>
 
        * Makefile.am (ACLOCAL_AMFLAGS): Add -I ../config -I ../bfd.
index 339cab5db8f1dbc8527a7860c9beafb8078be2ab..54e8483418c762f56c6e3147e3cdbd39d3952f59 100644 (file)
@@ -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 2803af8eab78c44a9bd6399cf4a7114acd594590..e6ea7aeaf05d109dfce2c494527eb808b39694b5 100644 (file)
@@ -1,3 +1,8 @@
+2007-06-14  Paul Brook  <paul@codesourcery.com>
+
+       * gas/arm/thumb32.s: Add tests for shift instructions.
+       * gas/arm/thumb32.d: Ditto.
+
 2007-06-06  Paul Brook  <paul@codesourcery.com>
 
        * gas/arm/thumb.d: Update expected output.
index 5bb76a5392e2f0e30e1aa50a03dd054fb73797ff..0d96818858e20a5fd286f0a154fb794e7d0ea80a 100644 (file)
@@ -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 4f602df35d823d259aaa77532f068dcb43d37cb3..697dfd240f3481ff9ed5cfbcd00f712f398932dd 100644 (file)
@@ -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