commit 1b530a6dfcfe4510f66cb90a1717698063ac7a4f
Author: aurel32 <aurel32@c046a42c-6fe2-441c-8c8c-71466251a162>
Date:   Sun Apr 5 20:08:59 2009 +0000

    Add new command line option -singlestep for tcg single stepping.
    
    This replaces a compile time option for some targets and adds
    this feature to targets which did not have a compile time option.
    
    Add monitor command to enable or disable single step mode.
    
    Modify monitor command "info status" to display single step mode.
    
    Signed-off-by: Stefan Weil <weil@mail.berlios.de>
    Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
    
    git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@7004 c046a42c-6fe2-441c-8c8c-71466251a162

diff --git a/bsd-user/main.c b/bsd-user/main.c
index 0dc9b99..34a6b07 100644
--- a/bsd-user/main.c
+++ b/bsd-user/main.c
@@ -33,6 +33,8 @@
 
 #define DEBUG_LOGFILE "/tmp/qemu.log"
 
+int singlestep;
+
 static const char *interp_prefix = CONFIG_QEMU_PREFIX;
 const char *qemu_uname_release = CONFIG_UNAME_RELEASE;
 extern char **environ;
@@ -378,6 +380,7 @@ static void usage(void)
            "Debug options:\n"
            "-d options   activate log (logfile=%s)\n"
            "-p pagesize  set the host page size to 'pagesize'\n"
+           "-singlestep  always run in singlestep mode\n"
            "-strace      log system calls\n"
            "\n"
            "Environment variables:\n"
@@ -500,6 +503,8 @@ int main(int argc, char **argv)
                 usage();
             }
             optind++;
+        } else if (!strcmp(r, "singlestep")) {
+            singlestep = 1;
         } else if (!strcmp(r, "strace")) {
             do_strace = 1;
         } else
diff --git a/darwin-user/main.c b/darwin-user/main.c
index 9b8a3dc..51c6aa0 100644
--- a/darwin-user/main.c
+++ b/darwin-user/main.c
@@ -41,6 +41,8 @@
 #include <mach/mach_init.h>
 #include <mach/vm_map.h>
 
+int singlestep;
+
 const char *interp_prefix = "";
 
 asm(".zerofill __STD_PROG_ZONE, __STD_PROG_ZONE, __std_prog_zone, 0x0dfff000");
@@ -751,6 +753,7 @@ void usage(void)
            "-d options   activate log (logfile='%s')\n"
            "-g wait for gdb on port 1234\n"
            "-p pagesize  set the host page size to 'pagesize'\n",
+           "-singlestep  always run in singlestep mode\n"
            TARGET_ARCH,
            TARGET_ARCH,
            interp_prefix,
@@ -842,6 +845,8 @@ int main(int argc, char **argv)
 #endif
                 exit(1);
             }
+        } else if (!strcmp(r, "singlestep")) {
+            singlestep = 1;
         } else
         {
             usage();
diff --git a/exec-all.h b/exec-all.h
index 143aca1..33ccb7b 100644
--- a/exec-all.h
+++ b/exec-all.h
@@ -384,4 +384,8 @@ static inline int kqemu_is_ok(CPUState *env)
 typedef void (CPUDebugExcpHandler)(CPUState *env);
 
 CPUDebugExcpHandler *cpu_set_debug_excp_handler(CPUDebugExcpHandler *handler);
+
+/* vl.c */
+extern int singlestep;
+
 #endif
diff --git a/linux-user/main.c b/linux-user/main.c
index feb3036..3b9dfc7 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -39,6 +39,8 @@
 
 char *exec_path;
 
+int singlestep;
+
 static const char *interp_prefix = CONFIG_QEMU_PREFIX;
 const char *qemu_uname_release = CONFIG_UNAME_RELEASE;
 
@@ -2217,6 +2219,7 @@ static void usage(void)
            "Debug options:\n"
            "-d options   activate log (logfile=%s)\n"
            "-p pagesize  set the host page size to 'pagesize'\n"
+           "-singlestep  always run in singlestep mode\n"
            "-strace      log system calls\n"
            "\n"
            "Environment variables:\n"
@@ -2359,6 +2362,8 @@ int main(int argc, char **argv, char **envp)
             }
         } else if (!strcmp(r, "drop-ld-preload")) {
             (void) envlist_unsetenv(envlist, "LD_PRELOAD");
+        } else if (!strcmp(r, "singlestep")) {
+            singlestep = 1;
         } else if (!strcmp(r, "strace")) {
             do_strace = 1;
         } else
diff --git a/monitor.c b/monitor.c
index 75c8663..ca1c11c 100644
--- a/monitor.c
+++ b/monitor.c
@@ -527,6 +527,17 @@ static void do_log(Monitor *mon, const char *items)
     cpu_set_log(mask);
 }
 
+static void do_singlestep(Monitor *mon, const char *option)
+{
+    if (!option || !strcmp(option, "on")) {
+        singlestep = 1;
+    } else if (!strcmp(option, "off")) {
+        singlestep = 0;
+    } else {
+        monitor_printf(mon, "unexpected option %s\n", option);
+    }
+}
+
 static void do_stop(Monitor *mon)
 {
     vm_stop(EXCP_INTERRUPT);
@@ -1511,9 +1522,13 @@ static void do_inject_nmi(Monitor *mon, int cpu_index)
 
 static void do_info_status(Monitor *mon)
 {
-    if (vm_running)
-       monitor_printf(mon, "VM status: running\n");
-    else
+    if (vm_running) {
+        if (singlestep) {
+            monitor_printf(mon, "VM status: running (single step mode)\n");
+        } else {
+            monitor_printf(mon, "VM status: running\n");
+        }
+    } else
        monitor_printf(mon, "VM status: paused\n");
 }
 
@@ -1644,6 +1659,8 @@ static const mon_cmd_t mon_cmds[] = {
       "tag|id", "restore a VM snapshot from its tag or id" },
     { "delvm", "s", do_delvm,
       "tag|id", "delete a VM snapshot from its tag or id" },
+    { "singlestep", "s?", do_singlestep,
+      "[on|off]", "run emulation in singlestep mode or switch to normal mode", },
     { "stop", "", do_stop,
       "", "stop emulation", },
     { "c|cont", "", do_cont,
diff --git a/qemu-doc.texi b/qemu-doc.texi
index 61a08ee..3742b45 100644
--- a/qemu-doc.texi
+++ b/qemu-doc.texi
@@ -490,6 +490,10 @@ Set the whole virtual machine to the snapshot identified by the tag
 @item delvm @var{tag}|@var{id}
 Delete the snapshot identified by @var{tag} or @var{id}.
 
+@item singlestep [off]
+Run the emulation in single step mode.
+If called with option off, the emulation returns to normal mode.
+
 @item stop
 Stop emulation.
 
@@ -2370,6 +2374,8 @@ Activate log (logfile=/tmp/qemu.log)
 Act as if the host page size was 'pagesize' bytes
 @item -g port
 Wait gdb connection to port
+@item -singlestep
+Run the emulation in single step mode.
 @end table
 
 Environment variables:
@@ -2488,6 +2494,8 @@ Debug options:
 Activate log (logfile=/tmp/qemu.log)
 @item -p pagesize
 Act as if the host page size was 'pagesize' bytes
+@item -singlestep
+Run the emulation in single step mode.
 @end table
 
 @node BSD User space emulator
@@ -2550,6 +2558,8 @@ Debug options:
 Activate log (logfile=/tmp/qemu.log)
 @item -p pagesize
 Act as if the host page size was 'pagesize' bytes
+@item -singlestep
+Run the emulation in single step mode.
 @end table
 
 @node compilation
diff --git a/qemu-options.hx b/qemu-options.hx
index 51593a3..4c7012e 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -1209,6 +1209,13 @@ Store the QEMU process PID in @var{file}. It is useful if you launch QEMU
 from a script.
 ETEXI
 
+DEF("singlestep", 0, QEMU_OPTION_singlestep, \
+    "-singlestep   always run in singlestep mode\n")
+STEXI
+@item -singlestep
+Run the emulation in single step mode.
+ETEXI
+
 DEF("S", 0, QEMU_OPTION_S, \
     "-S              freeze CPU at startup (use 'c' to start execution)\n")
 STEXI
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index 6156fb5..1e1da54 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -2412,11 +2412,11 @@ static always_inline void gen_intermediate_code_internal (CPUState *env,
         if (env->singlestep_enabled) {
             gen_excp(&ctx, EXCP_DEBUG, 0);
             break;
-	}
+        }
 
-#if defined (DO_SINGLE_STEP)
-        break;
-#endif
+        if (singlestep) {
+            break;
+        }
     }
     if (ret != 1 && ret != 3) {
         tcg_gen_movi_i64(cpu_pc, ctx.pc);
diff --git a/target-arm/translate.c b/target-arm/translate.c
index f7f2a8d..9aff619 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -8791,6 +8791,7 @@ static inline void gen_intermediate_code_internal(CPUState *env,
         num_insns ++;
     } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&
              !env->singlestep_enabled &&
+             !singlestep &&
              dc->pc < next_page_start &&
              num_insns < max_insns);
 
diff --git a/target-cris/translate.c b/target-cris/translate.c
index d5fcb9e..d9256ca 100644
--- a/target-cris/translate.c
+++ b/target-cris/translate.c
@@ -3272,6 +3272,7 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb,
 			break;
 	} while (!dc->is_jmp && !dc->cpustate_changed
 		 && gen_opc_ptr < gen_opc_end
+                 && !singlestep
 		 && (dc->pc < next_page_start)
                  && num_insns < max_insns);
 
diff --git a/target-i386/translate.c b/target-i386/translate.c
index cd2e326..8df3ea4 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -7733,6 +7733,11 @@ static inline void gen_intermediate_code_internal(CPUState *env,
             gen_eob(dc);
             break;
         }
+        if (singlestep) {
+            gen_jmp_im(pc_ptr - dc->cs_base);
+            gen_eob(dc);
+            break;
+        }
     }
     if (tb->cflags & CF_LAST_IO)
         gen_io_end();
diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index 4e3cf4a..f9b36c9 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -3031,6 +3031,7 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb,
         num_insns++;
     } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&
              !env->singlestep_enabled &&
+             !singlestep &&
              (pc_offset) < (TARGET_PAGE_SIZE - 32) &&
              num_insns < max_insns);
 
diff --git a/target-mips/translate.c b/target-mips/translate.c
index 8adc89c..47a3062 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -38,7 +38,6 @@
 
 //#define MIPS_DEBUG_DISAS
 //#define MIPS_DEBUG_SIGN_EXTENSIONS
-//#define MIPS_SINGLE_STEP
 
 /* MIPS major opcodes */
 #define MASK_OP_MAJOR(op)  (op & (0x3F << 26))
@@ -8140,9 +8139,9 @@ gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
 
         if (num_insns >= max_insns)
             break;
-#if defined (MIPS_SINGLE_STEP)
-        break;
-#endif
+
+        if (singlestep)
+            break;
     }
     if (tb->cflags & CF_LAST_IO)
         gen_io_end();
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 870aec5..9ba4937 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -39,7 +39,6 @@
 #define GDBSTUB_SINGLE_STEP 0x4
 
 /* Include definitions for instructions classes and implementations flags */
-//#define DO_SINGLE_STEP
 //#define PPC_DEBUG_DISAS
 //#define DO_PPC_STATISTICS
 
@@ -8288,15 +8287,13 @@ static always_inline void gen_intermediate_code_internal (CPUState *env,
             gen_exception(ctxp, POWERPC_EXCP_TRACE);
         } else if (unlikely(((ctx.nip & (TARGET_PAGE_SIZE - 1)) == 0) ||
                             (env->singlestep_enabled) ||
+                            singlestep ||
                             num_insns >= max_insns)) {
             /* if we reach a page boundary or are single stepping, stop
              * generation
              */
             break;
         }
-#if defined (DO_SINGLE_STEP)
-        break;
-#endif
     }
     if (tb->cflags & CF_LAST_IO)
         gen_io_end();
diff --git a/target-sh4/translate.c b/target-sh4/translate.c
index 4ced176..aa3b9d4 100644
--- a/target-sh4/translate.c
+++ b/target-sh4/translate.c
@@ -1967,9 +1967,8 @@ gen_intermediate_code_internal(CPUState * env, TranslationBlock * tb,
 	    break;
         if (num_insns >= max_insns)
             break;
-#ifdef SH4_SINGLE_STEP
-	break;
-#endif
+        if (singlestep)
+            break;
     }
     if (tb->cflags & CF_LAST_IO)
         gen_io_end();
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index d059408..86319a7 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -4838,7 +4838,7 @@ static inline void gen_intermediate_code_internal(TranslationBlock * tb,
             break;
         /* if single step mode, we generate only one instruction and
            generate an exception */
-        if (env->singlestep_enabled) {
+        if (env->singlestep_enabled || singlestep) {
             tcg_gen_movi_tl(cpu_pc, dc->pc);
             tcg_gen_exit_tb(0);
             break;
diff --git a/vl.c b/vl.c
index b294380..4bd173f 100644
--- a/vl.c
+++ b/vl.c
@@ -236,6 +236,7 @@ int win2k_install_hack = 0;
 int rtc_td_hack = 0;
 #endif
 int usb_enabled = 0;
+int singlestep = 0;
 int smp_cpus = 1;
 const char *vnc_display;
 int acpi_enabled = 1;
@@ -4660,6 +4661,9 @@ int main(int argc, char **argv, char **envp)
             case QEMU_OPTION_bios:
                 bios_name = optarg;
                 break;
+            case QEMU_OPTION_singlestep:
+                singlestep = 1;
+                break;
             case QEMU_OPTION_S:
                 autostart = 0;
                 break;
