From eab4f823f7793e025759fb47748b4b71bb88dac9 Mon Sep 17 00:00:00 2001 From: Matthew Gretton-Dann Date: Fri, 17 Sep 2010 15:19:14 +0000 Subject: [PATCH] 2010-09-17 Tejas Belagod * config/tc-arm.c (do_t_ldmstm): Add logic to handle single-register list for ldm/stm. 2010-09-17 Tejas Belagod * 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 | 5 ++ gas/config/tc-arm.c | 76 ++++++++++++++++++++------- gas/testsuite/ChangeLog | 7 +++ gas/testsuite/gas/arm/thumb2_ldmstm.d | 8 ++- gas/testsuite/gas/arm/thumb2_ldmstm.s | 8 ++- 5 files changed, 83 insertions(+), 21 deletions(-) diff --git a/gas/ChangeLog b/gas/ChangeLog index 789b4362673..416b1fece45 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,8 @@ +2010-09-17 Tejas Belagod + + * config/tc-arm.c (do_t_ldmstm): Add logic to handle single-register + list for ldm/stm. + 2010-09-17 Tejas Belagod * config/tc-arm.c (parse_psr): Add condition for matching "APSR" on diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c index 9bba5e4949f..deb78cefa56 100644 --- a/gas/config/tc-arm.c +++ b/gas/config/tc-arm.c @@ -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; + } } } diff --git a/gas/testsuite/ChangeLog b/gas/testsuite/ChangeLog index 971329e61c8..4cdb1f2d9f6 100644 --- a/gas/testsuite/ChangeLog +++ b/gas/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2010-09-17 Tejas Belagod + + * 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 * gas/arm/msr-reg.s: New file. diff --git a/gas/testsuite/gas/arm/thumb2_ldmstm.d b/gas/testsuite/gas/arm/thumb2_ldmstm.d index 50d3ee68588..f89bf16812f 100644 --- a/gas/testsuite/gas/arm/thumb2_ldmstm.d +++ b/gas/testsuite/gas/arm/thumb2_ldmstm.d @@ -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\] diff --git a/gas/testsuite/gas/arm/thumb2_ldmstm.s b/gas/testsuite/gas/arm/thumb2_ldmstm.s index 6cbcc1779b0..ab7701c7bab 100644 --- a/gas/testsuite/gas/arm/thumb2_ldmstm.s +++ b/gas/testsuite/gas/arm/thumb2_ldmstm.s @@ -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] -- 2.30.2