qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] Re: ARM page crossing inside insn? (Re: ARM ethernet fixes)


From: Antti P Miettinen
Subject: [Qemu-devel] Re: ARM page crossing inside insn? (Re: ARM ethernet fixes)
Date: Mon, 19 Dec 2005 21:25:17 +0200
User-agent: Gnus/5.110004 (No Gnus v0.4) Emacs/21.4 (gnu/linux)

Daniel Jacobowitz <address@hidden> writes:
> You don't need anything near this complicated: if the register being
> set is the base register, copy it into T2 instead of overwriting the
> base register.  Then at the end, if the base register was loaded, copy
> T2 into the base register.  That's all the atomicity you need; the
> instruction is being restarted after the base register was clobbered.

Eee.. I knew that. I was just.. practicing my fingers (ahem.. is there
a saying in english about how the whole body suffers from a stupid
head? :-)

Something like this?

Index: target-arm/op.c
===================================================================
RCS file: /sources/qemu/qemu/target-arm/op.c,v
retrieving revision 1.17
diff -u -r1.17 op.c
--- target-arm/op.c     26 Nov 2005 10:46:39 -0000      1.17
+++ target-arm/op.c     19 Dec 2005 19:14:45 -0000
@@ -106,6 +106,11 @@
     T0 = T1;
 }
 
+void OPPROTO op_movl_T2_T0(void)
+{
+    T2 = T0;
+}
+
 void OPPROTO op_movl_T1_im(void)
 {
     T1 = PARAM1;
@@ -1175,3 +1180,18 @@
     }
     FORCE_RET();
 }
+
+void OPPROTO op_movl_user_T2(void)
+{
+    int regno = PARAM1;
+    if (regno == 13) {
+        env->banked_r13[0] = T2;
+    } else if (regno == 14) {
+        env->banked_r14[0] = T2;
+    } else if ((env->uncached_cpsr & 0x1f) == ARM_CPU_MODE_FIQ) {
+        env->usr_regs[regno - 8] = T2;
+    } else {
+        env->regs[regno] = T2;
+    }
+    FORCE_RET();
+}
Index: target-arm/op_template.h
===================================================================
RCS file: /sources/qemu/qemu/target-arm/op_template.h,v
retrieving revision 1.2
diff -u -r1.2 op_template.h
--- target-arm/op_template.h    31 Jan 2005 20:43:28 -0000      1.2
+++ target-arm/op_template.h    19 Dec 2005 19:14:45 -0000
@@ -48,6 +48,11 @@
     SET_REG (T1);
 }
 
+void OPPROTO glue(glue(op_movl_, REGNAME), _T2)(void)
+{
+    SET_REG (T2);
+}
+
 #undef REG
 #undef REGNAME
 #undef SET_REG
Index: target-arm/translate.c
===================================================================
RCS file: /sources/qemu/qemu/target-arm/translate.c,v
retrieving revision 1.35
diff -u -r1.35 translate.c
--- target-arm/translate.c      18 Dec 2005 16:55:25 -0000      1.35
+++ target-arm/translate.c      19 Dec 2005 19:14:46 -0000
@@ -228,7 +228,7 @@
     },
 };
 
-static GenOpFunc *gen_op_movl_reg_TN[2][16] = {
+static GenOpFunc *gen_op_movl_reg_TN[3][16] = {
     {
         gen_op_movl_r0_T0,
         gen_op_movl_r1_T0,
@@ -265,6 +265,24 @@
         gen_op_movl_r14_T1,
         gen_op_movl_r15_T1,
     },
+    {
+        gen_op_movl_r0_T2,
+        gen_op_movl_r1_T2,
+        gen_op_movl_r2_T2,
+        gen_op_movl_r3_T2,
+        gen_op_movl_r4_T2,
+        gen_op_movl_r5_T2,
+        gen_op_movl_r6_T2,
+        gen_op_movl_r7_T2,
+        gen_op_movl_r8_T2,
+        gen_op_movl_r9_T2,
+        gen_op_movl_r10_T2,
+        gen_op_movl_r11_T2,
+        gen_op_movl_r12_T2,
+        gen_op_movl_r13_T2,
+        gen_op_movl_r14_T2,
+        gen_op_movl_r15_T2,
+    },
 };
 
 static GenOpFunc1 *gen_op_movl_TN_im[3] = {
@@ -1665,8 +1683,11 @@
                         if (insn & (1 << 20)) {
                             /* load */
                             gen_ldst(ldl, s);
-                            if (i == 15) {
-                                gen_bx(s);
+                           if (i == 15) {
+                               /* later */
+                           } else if (i == rn) {
+                               /* base register */
+                               gen_op_movl_T2_T0();
                             } else if (user) {
                                 gen_op_movl_user_T0(i);
                             } else {
@@ -1691,6 +1712,19 @@
                             gen_op_addl_T1_im(4);
                     }
                 }
+               if (insn & (1 << 20)) {
+                   /* check if base register and pc were loaded */
+                   if (insn & (1 << rn)) {
+                       if (user)
+                           gen_op_movl_user_T2(rn);
+                       else
+                           gen_op_movl_reg_TN[2][rn]();
+                   }
+                   if (insn & (1 << 15)) {
+                       /* r15 is loaded last - value should be in T0 */
+                       gen_bx(s);
+                   }
+               }
                 if (insn & (1 << 21)) {
                     /* write back */
                     if (insn & (1 << 23)) {


-- 
http://www.iki.fi/~ananaza/





reply via email to

[Prev in Thread] Current Thread [Next in Thread]