qemu-devel
[Top][All Lists]
Advanced

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

[Qemu-devel] [PATCH 05/18] Fix SRS/RFE instructions


From: Filip Navara
Subject: [Qemu-devel] [PATCH 05/18] Fix SRS/RFE instructions
Date: Sun, 19 Jul 2009 15:19:48 -0000

The encoding of 'IA' and 'DB' conditions was swapped.
SRS instruction must store banked SPSR instead of CPSR at the specific address.
Missing 'return' statement at the end of RFE handling.
Fixed write-back code to reference correct registers.

From: Hyeonsung Jang <address@hidden>
Signed-off-by: Filip Navara <address@hidden>
---
 target-arm/translate.c |   31 ++++++++++++++++---------------
 1 files changed, 16 insertions(+), 15 deletions(-)

diff --git a/target-arm/translate.c b/target-arm/translate.c
index 9584a9c..f74411a 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -5753,7 +5753,7 @@ static void disas_arm_insn(CPUState * env, DisasContext 
*s)
             }
         } else if ((insn & 0x0e5fffe0) == 0x084d0500) {
             /* srs */
-            uint32_t offset;
+            int32_t offset;
             if (IS_USER(s))
                 goto illegal_op;
             ARCH(6);
@@ -5767,8 +5767,8 @@ static void disas_arm_insn(CPUState * env, DisasContext 
*s)
             i = (insn >> 23) & 3;
             switch (i) {
             case 0: offset = -4; break; /* DA */
-            case 1: offset = -8; break; /* DB */
-            case 2: offset = 0; break; /* IA */
+            case 1: offset = 0; break; /* IA */
+            case 2: offset = -8; break; /* DB */
             case 3: offset = 4; break; /* IB */
             default: abort();
             }
@@ -5776,32 +5776,32 @@ static void disas_arm_insn(CPUState * env, DisasContext 
*s)
                 tcg_gen_addi_i32(addr, addr, offset);
             tmp = load_reg(s, 14);
             gen_st32(tmp, addr, 0);
-            tmp = new_tmp();
-            gen_helper_cpsr_read(tmp);
+            tmp = load_cpu_field(spsr);
             tcg_gen_addi_i32(addr, addr, 4);
             gen_st32(tmp, addr, 0);
             if (insn & (1 << 21)) {
                 /* Base writeback.  */
                 switch (i) {
                 case 0: offset = -8; break;
-                case 1: offset = -4; break;
-                case 2: offset = 4; break;
+                case 1: offset = 4; break;
+                case 2: offset = -4; break;
                 case 3: offset = 0; break;
                 default: abort();
                 }
                 if (offset)
-                    tcg_gen_addi_i32(addr, tmp, offset);
+                    tcg_gen_addi_i32(addr, addr, offset);
                 if (op1 == (env->uncached_cpsr & CPSR_M)) {
-                    gen_movl_reg_T1(s, 13);
+                    store_reg(s, 13, addr);
                 } else {
-                    gen_helper_set_r13_banked(cpu_env, tcg_const_i32(op1), 
cpu_T[1]);
+                    gen_helper_set_r13_banked(cpu_env, tcg_const_i32(op1), 
addr);
+                    dead_tmp(addr);
                 }
             } else {
                 dead_tmp(addr);
             }
         } else if ((insn & 0x0e5fffe0) == 0x081d0a00) {
             /* rfe */
-            uint32_t offset;
+            int32_t offset;
             if (IS_USER(s))
                 goto illegal_op;
             ARCH(6);
@@ -5810,8 +5810,8 @@ static void disas_arm_insn(CPUState * env, DisasContext 
*s)
             i = (insn >> 23) & 3;
             switch (i) {
             case 0: offset = -4; break; /* DA */
-            case 1: offset = -8; break; /* DB */
-            case 2: offset = 0; break; /* IA */
+            case 1: offset = 0; break; /* IA */
+            case 2: offset = -8; break; /* DB */
             case 3: offset = 4; break; /* IB */
             default: abort();
             }
@@ -5825,8 +5825,8 @@ static void disas_arm_insn(CPUState * env, DisasContext 
*s)
                 /* Base writeback.  */
                 switch (i) {
                 case 0: offset = -8; break;
-                case 1: offset = -4; break;
-                case 2: offset = 4; break;
+                case 1: offset = 4; break;
+                case 2: offset = -4; break;
                 case 3: offset = 0; break;
                 default: abort();
                 }
@@ -5837,6 +5837,7 @@ static void disas_arm_insn(CPUState * env, DisasContext 
*s)
                 dead_tmp(addr);
             }
             gen_rfe(s, tmp, tmp2);
+            return;
         } else if ((insn & 0x0e000000) == 0x0a000000) {
             /* branch link and change to thumb (blx <offset>) */
             int32_t offset;
-- 
1.6.3.2.1299.gee46c






reply via email to

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