2010-09-17 Tejas Belagod <tejas.belagod@arm.com>
authorMatthew Gretton-Dann <matthew.gretton-dann@arm.com>
Fri, 17 Sep 2010 15:19:14 +0000 (15:19 +0000)
committerMatthew Gretton-Dann <matthew.gretton-dann@arm.com>
Fri, 17 Sep 2010 15:19:14 +0000 (15:19 +0000)
* config/tc-arm.c (do_t_ldmstm): Add logic to handle single-register
list for ldm/stm.

2010-09-17  Tejas Belagod  <tejas.belagod@arm.com>

* gas/arm/thumb2_ldmstm.d: Change single-register stmia to use 16-bit
str encoding instead of str.w.  Likewise for ldmia.
* gas/arm/thumb2_ldmstm.s: Change stmia comment.  Add tests for T1
ldmia-to-ldr.

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

index 789b4362673d8deb00efcdc5b7f20b4208176619..416b1fece45327648073f0c44a3329b61c077bc1 100644 (file)
@@ -1,3 +1,8 @@
+2010-09-17  Tejas Belagod  <tejas.belagod@arm.com>
+
+       * config/tc-arm.c (do_t_ldmstm): Add logic to handle single-register
+       list for ldm/stm.
+
 2010-09-17  Tejas Belagod  <tejas.belagod@arm.com>
 
        * config/tc-arm.c (parse_psr): Add condition for matching "APSR" on
index 9bba5e4949f40320cf2ad721db3fb65176df8ffc..deb78cefa5639db21422e68d762eccae50131cb7 100644 (file)
@@ -9943,30 +9943,68 @@ do_t_ldmstm (void)
        {
          mask = 1 << inst.operands[0].reg;
 
-         if (inst.operands[0].reg <= 7
-             && (inst.instruction == T_MNEM_stmia
-                 ? inst.operands[0].writeback
-                 : (inst.operands[0].writeback
-                    == !(inst.operands[1].imm & mask))))
+         if (inst.operands[0].reg <= 7)
            {
              if (inst.instruction == T_MNEM_stmia
-                 && (inst.operands[1].imm & mask)
-                 && (inst.operands[1].imm & (mask - 1)))
-               as_warn (_("value stored for r%d is UNKNOWN"),
-                        inst.operands[0].reg);
+                 ? inst.operands[0].writeback
+                 : (inst.operands[0].writeback
+                    == !(inst.operands[1].imm & mask)))
+               {
+                 if (inst.instruction == T_MNEM_stmia
+                     && (inst.operands[1].imm & mask)
+                     && (inst.operands[1].imm & (mask - 1)))
+                   as_warn (_("value stored for r%d is UNKNOWN"),
+                            inst.operands[0].reg);
 
-             inst.instruction = THUMB_OP16 (inst.instruction);
-             inst.instruction |= inst.operands[0].reg << 8;
-             inst.instruction |= inst.operands[1].imm;
-             narrow = TRUE;
+                 inst.instruction = THUMB_OP16 (inst.instruction);
+                 inst.instruction |= inst.operands[0].reg << 8;
+                 inst.instruction |= inst.operands[1].imm;
+                 narrow = TRUE;
+               }
+             else if ((inst.operands[1].imm & (inst.operands[1].imm-1)) == 0)
+               {
+                 /* This means 1 register in reg list one of 3 situations:
+                    1. Instruction is stmia, but without writeback.
+                    2. lmdia without writeback, but with Rn not in
+                       reglist.
+                    3. ldmia with writeback, but with Rn in reglist.
+                    Case 3 is UNPREDICTABLE behaviour, so we handle
+                    case 1 and 2 which can be converted into a 16-bit
+                    str or ldr. The SP cases are handled below.  */
+                 unsigned long opcode;
+                 /* First, record an error for Case 3.  */
+                 if (inst.operands[1].imm & mask
+                     && inst.operands[0].writeback)
+                   inst.error = 
+                       _("having the base register in the register list when "
+                         "using write back is UNPREDICTABLE");
+                   
+                 opcode = (inst.instruction == T_MNEM_stmia ? T_MNEM_str 
+                                                            : T_MNEM_ldr);
+                 inst.instruction = THUMB_OP16 (opcode);
+                 inst.instruction |= inst.operands[0].reg << 3;
+                 inst.instruction |= (ffs (inst.operands[1].imm)-1);
+                 narrow = TRUE;
+               }
            }
-         else if (inst.operands[0] .reg == REG_SP
-                  && inst.operands[0].writeback)
+         else if (inst.operands[0] .reg == REG_SP)
            {
-             inst.instruction = THUMB_OP16 (inst.instruction == T_MNEM_stmia
-                                            ? T_MNEM_push : T_MNEM_pop);
-             inst.instruction |= inst.operands[1].imm;
-             narrow = TRUE;
+             if (inst.operands[0].writeback)
+               {
+                 inst.instruction = 
+                       THUMB_OP16 (inst.instruction == T_MNEM_stmia
+                                   ? T_MNEM_push : T_MNEM_pop);
+                 inst.instruction |= inst.operands[1].imm;
+                 narrow = TRUE;
+               }
+             else if ((inst.operands[1].imm & (inst.operands[1].imm-1)) == 0)
+               {
+                 inst.instruction = 
+                       THUMB_OP16 (inst.instruction == T_MNEM_stmia
+                                   ? T_MNEM_str_sp : T_MNEM_ldr_sp);
+                 inst.instruction |= ((ffs (inst.operands[1].imm)-1) << 8);
+                 narrow = TRUE;
+               }
            }
        }
 
index 971329e61c82f57244699b2f97cd9988099d75b8..4cdb1f2d9f62e3081beaca404149c899d1629375 100644 (file)
@@ -1,3 +1,10 @@
+2010-09-17  Tejas Belagod  <tejas.belagod@arm.com>
+
+       * gas/arm/thumb2_ldmstm.d: Change single-register stmia to use 16-bit
+       str encoding instead of str.w.  Likewise for ldmia.
+       * gas/arm/thumb2_ldmstm.s: Change stmia comment.  Add tests for T1
+       ldmia-to-ldr.
+
 2010-09-17  Tejas Belagod  <tejas.belagod@arm.com>
 
        * gas/arm/msr-reg.s: New file.
index 50d3ee6858870d8b2f58ec62d61541cd64466eb5..f89bf16812fd8177c54405e9aaf6869bbc1fb5a9 100644 (file)
@@ -48,6 +48,12 @@ Disassembly of section .text:
 0[0-9a-f]+ <[^>]+> f858 9b04   ldr.w   r9, \[r8\], #4
 0[0-9a-f]+ <[^>]+> f8d8 9000   ldr.w   r9, \[r8\]
 0[0-9a-f]+ <[^>]+> f840 1b04   str.w   r1, \[r0\], #4
-0[0-9a-f]+ <[^>]+> f8c0 1000   str.w   r1, \[r0\]
+0[0-9a-f]+ <[^>]+> 6001        str     r1, \[r0, #0\]
+0[0-9a-f]+ <[^>]+> 680a        ldr     r2, \[r1, #0\]
+0[0-9a-f]+ <[^>]+> 6807        ldr     r7, \[r0, #0\]
+0[0-9a-f]+ <[^>]+> 9700        str     r7, \[sp, #0\]
+0[0-9a-f]+ <[^>]+> 9000        str     r0, \[sp, #0\]
+0[0-9a-f]+ <[^>]+> 9f00        ldr     r7, \[sp, #0\]
+0[0-9a-f]+ <[^>]+> 9800        ldr     r0, \[sp, #0\]
 0[0-9a-f]+ <[^>]+> f848 9b04   str.w   r9, \[r8\], #4
 0[0-9a-f]+ <[^>]+> f8c8 9000   str.w   r9, \[r8\]
index 6cbcc1779b0f8c26bcc45925e64b9b6b63fe4241..ab7701c7babfc5a76f512182f9e812c2d6ecb5a1 100644 (file)
@@ -52,6 +52,12 @@ ldmstm:
        ldmia r8!, {r9}         @ ldr.w r9, [r8], #4
         ldmia r8, {r9}         @ ldr.w r9, [r8]
        stmia.w r0!, {r1}       @ str.w r1, [r0], #4
-       stmia r0, {r1}          @ str.w r1, [r0]
+       stmia r0, {r1}          @ T1 str r1, [r0]
+       ldmia r1, {r2}          @ T1 ldr r2, [r1]
+       ldmia r0, {r7}          @ T1 ldr r7, [r0]
+       stmia sp, {r7}          @ T1 str r7, [sp]
+       stmia sp, {r0}          @ T1 str r0, [sp]
+       ldmia sp, {r7}          @ T1 ldr r7, [sp]
+       ldmia sp, {r0}          @ T1 ldr r0, [sp]
        stmia r8!, {r9}         @ str.w r9, [r8], #4
        stmia r8, {r9}          @ str.w r9, [r8]