Patchwork target-arm: Don't update base register on abort in Thumb T1 LDM

login
register
mail settings
Submitter 오유연
Date April 27, 2011, 7:14 a.m.
Message ID <27709420.119791303888470736.JavaMail.weblogic@epml08>
Download mbox | patch
Permalink /patch/92990/
State New
Headers show

Comments

오유연 - April 27, 2011, 7:14 a.m.
It looks very good. I hope that it will patch soon.
Thank you.

------- Original Message -------
Sender : Peter Maydell<peter.maydell@linaro.org>
Date : 2011-04-27 02:17 (GMT+09:00)
Title : [PATCH] target-arm: Don't update base register on abort in Thumb T1 LDM
 
Make sure the base register isn't updated if it is in the load list
for a Thumb LDM (T1 encoding) which aborts partway through the load.

Signed-off-by: Peter Maydell 
---
target-arm/translate.c |   17 ++++++++++++++---
1 files changed, 14 insertions(+), 3 deletions(-)

Patch

diff --git a/target-arm/translate.c b/target-arm/translate.c
index d8da514..a1af436 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -9454,7 +9454,10 @@  static void disas_thumb_insn(CPUState *env, DisasContext *s)
         break;

     case 12:
+    {
         /* load/store multiple */
+        TCGv loaded_var;
+        TCGV_UNUSED(loaded_var);
         rn = (insn >> 8) & 0x7;
         addr = load_reg(s, rn);
         for (i = 0; i < 8; i++) {
@@ -9462,7 +9465,11 @@  static void disas_thumb_insn(CPUState *env, DisasContext *s)
                 if (insn & (1 << 11)) {
                     /* load */
                     tmp = gen_ld32(addr, IS_USER(s));
-                    store_reg(s, i, tmp);
+                    if (i == rn) {
+                        loaded_var = tmp;
+                    } else {
+                        store_reg(s, i, tmp);
+                    }
                 } else {
                     /* store */
                     tmp = load_reg(s, i);
@@ -9472,14 +9479,18 @@  static void disas_thumb_insn(CPUState *env, DisasContext *s)
                 tcg_gen_addi_i32(addr, addr, 4);
             }
         }
-        /* Base register writeback.  */
         if ((insn & (1 << rn)) == 0) {
+            /* base reg not in list: base register writeback */
             store_reg(s, rn, addr);
         } else {
+            /* base reg in list: if load, complete it now */
+            if (insn & (1 << 11)) {
+                store_reg(s, rn, loaded_var);
+            }
             tcg_temp_free_i32(addr);
         }
         break;
-
+    }
     case 13:
         /* conditional branch or swi */
         cond = (insn >> 8) & 0xf;