qemu-devel
[Top][All Lists]
Advanced

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

[Qemu-devel] [patch] Arm singlestep mode.


From: Paul Brook
Subject: [Qemu-devel] [patch] Arm singlestep mode.
Date: Mon, 18 Apr 2005 02:13:16 +0100
User-agent: KMail/1.7.2

The attached patch implements single-step mode for arm targets. It doesn't 
stop when the instruction condition fails, but I'll fix that later.

Paul
Index: translate.c
===================================================================
RCS file: /cvsroot/qemu/qemu/target-arm/translate.c,v
retrieving revision 1.20
diff -u -p -r1.20 translate.c
--- translate.c 17 Apr 2005 19:16:13 -0000      1.20
+++ translate.c 18 Apr 2005 01:08:50 -0000
@@ -33,6 +33,7 @@ typedef struct DisasContext {
     target_ulong pc;
     int is_jmp;
     struct TranslationBlock *tb;
+    int singlestep_enabled;
 } DisasContext;
 
 #define DISAS_JUMP_NEXT 4
@@ -888,6 +889,18 @@ static int disas_vfp_insn(CPUState * env
     return 0;
 }
 
+static inline void gen_jmp (DisasContext *s, uint32_t dest)
+{
+    if (__builtin_expect(s->singlestep_enabled, 0)) {
+        /* An indirect jump so that we still trigger the debug exception.  */
+        gen_op_movl_T0_im(dest);
+        gen_bx(s);
+    } else {
+        gen_op_jmp((long)s->tb, dest);
+        s->is_jmp = DISAS_TB_JUMP;
+    }
+}
+
 static void disas_arm_insn(CPUState * env, DisasContext *s)
 {
     unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh;
@@ -1469,8 +1482,7 @@ static void disas_arm_insn(CPUState * en
                 }
                 offset = (((int32_t)insn << 8) >> 8);
                 val += (offset << 2) + 4;
-                gen_op_jmp((long)s->tb, val);
-                s->is_jmp = DISAS_TB_JUMP;
+                gen_jmp(s, val);
             }
             break;
         case 0xc:
@@ -1957,8 +1969,7 @@ static void disas_thumb_insn(DisasContex
         val = (uint32_t)s->pc;
         offset = ((int32_t)insn << 24) >> 24;
         val += (offset << 1) + 2;
-        gen_op_jmp((long)s->tb, val);
-        s->is_jmp = DISAS_TB_JUMP;
+        gen_jmp(s, val);
         break;
 
     case 14:
@@ -1968,8 +1979,7 @@ static void disas_thumb_insn(DisasContex
         val = (uint32_t)s->pc;
         offset = ((int32_t)insn << 21) >> 21;
         val += (offset << 1) + 2;
-        gen_op_jmp((long)s->tb, val);
-        s->is_jmp = DISAS_TB_JUMP;
+        gen_jmp(s, val);
         break;
 
     case 15:
@@ -1985,8 +1995,7 @@ static void disas_thumb_insn(DisasContex
         val += offset;
         if (insn & (1 << 11)) {
             /* bl */
-            gen_op_jmp((long)s->tb, val);
-            s->is_jmp = DISAS_TB_JUMP;
+            gen_jmp(s, val);
         } else {
             /* blx */
             gen_op_movl_T0_im(val);
@@ -2024,6 +2033,7 @@ static inline int gen_intermediate_code_
 
     dc->is_jmp = DISAS_NEXT;
     dc->pc = pc_start;
+    dc->singlestep_enabled = env->singlestep_enabled;
     lj = -1;
     do {
         if (env->nb_breakpoints > 0) {
@@ -2054,21 +2064,30 @@ static inline int gen_intermediate_code_
     } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&
              !env->singlestep_enabled &&
              (dc->pc - pc_start) < (TARGET_PAGE_SIZE - 32));
-    switch(dc->is_jmp) {
-    case DISAS_JUMP_NEXT:
-    case DISAS_NEXT:
-        gen_op_jmp((long)dc->tb, (long)dc->pc);
-        break;
-    default:
-    case DISAS_JUMP:
-    case DISAS_UPDATE:
-        /* indicate that the hash table must be used to find the next TB */
-        gen_op_movl_T0_0();
-        gen_op_exit_tb();
-        break;
-    case DISAS_TB_JUMP:
-        /* nothing more to generate */
-        break;
+    if (__builtin_expect(env->singlestep_enabled, 0)) {
+        /* Make sure the pc is updated, and raise a debug exception.  */
+        if (dc->is_jmp == DISAS_NEXT || dc->is_jmp == DISAS_JUMP_NEXT) {
+            gen_op_movl_T0_im((long)dc->pc);
+            gen_op_movl_reg_TN[0][15]();
+        }
+        gen_op_debug();
+    } else {
+        switch(dc->is_jmp) {
+        case DISAS_JUMP_NEXT:
+        case DISAS_NEXT:
+            gen_op_jmp((long)dc->tb, (long)dc->pc);
+            break;
+        default:
+        case DISAS_JUMP:
+        case DISAS_UPDATE:
+            /* indicate that the hash table must be used to find the next TB */
+            gen_op_movl_T0_0();
+            gen_op_exit_tb();
+            break;
+        case DISAS_TB_JUMP:
+            /* nothing more to generate */
+            break;
+        }
     }
     *gen_opc_ptr = INDEX_op_end;
 

reply via email to

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