diff options
-rw-r--r-- | NEWS | 2 | ||||
-rw-r--r-- | doc/mdk_gstart.texi | 3 | ||||
-rw-r--r-- | doc/mdk_mixvm.texi | 47 | ||||
-rw-r--r-- | mixlib/mix_vm.c | 41 | ||||
-rw-r--r-- | mixlib/mix_vm.h | 10 | ||||
-rw-r--r-- | mixlib/mix_vm_command.c | 37 | ||||
-rw-r--r-- | mixlib/mix_vm_command.h | 1 | ||||
-rw-r--r-- | samples/.cvsignore | 2 | ||||
-rw-r--r-- | samples/bt.mixal | 6 | ||||
-rw-r--r-- | samples/cbp.mixal | 1 |
10 files changed, 122 insertions, 28 deletions
@@ -6,7 +6,7 @@ See the end for copying conditions. Please send mdk bug reports to bug-mdk@gnu.org. --------------------------------------------------------------------------- -* Version 0.4 +* Version 0.4 (22/07/01) ** Split mode: gmixvm can now be run with the MIXVM, MIXAL and Devices windows detached (instead of arranged in a notebook). diff --git a/doc/mdk_gstart.texi b/doc/mdk_gstart.texi index 25764a0..70ded05 100644 --- a/doc/mdk_gstart.texi +++ b/doc/mdk_gstart.texi @@ -445,6 +445,7 @@ MIX > @end example Other useful commands for debugging are @code{tracing} (which turns on -tracing of executed intructions) and @code{weval} (which evaluates +tracing of executed intructions), @code{pbt} (which prints a backtrace +of executed instructions) and @code{weval} (which evaluates w-expressions on the fly). For a complete description of all available MIX commands, @xref{mixvm}. diff --git a/doc/mdk_mixvm.texi b/doc/mdk_mixvm.texi index f5538cd..480abbc 100644 --- a/doc/mdk_mixvm.texi +++ b/doc/mdk_mixvm.texi @@ -373,6 +373,53 @@ actual MIXAL code that was compiled into the executed instruction. The tracing behaviour is stored as a configuration parameter in @file{~/.mdk}. @end deffn +@deffn {debug command} pbt [INS_NUMBER] +This command prints a backtrace of executed instructions. Its optional +argument @var{ins_number} is the number of instructions to print. If it +is omitted or equals zero, all executed instructions are printed. For +instance, if you compile and load the following program (@file{bt.mixal}): + +@example + ORIG 0 +BEG JMP *+1 + JMP *+1 +FOO JMP BAR +BAR HLT + END BEG +@end example + +@noindent +you could get the following traces: + +@example +MIX > load bt +Program loaded. Start address: 0 +MIX > next +MIX > pbt +#0 BEG in bt.mixal:2 +MIX > next +MIX > pbt +#0 1 in bt.mixal:3 +#1 BEG in bt.mixal:2 +MIX > run +Running ... +... done +MIX > pbt 3 +#0 BAR in bt.mixal:5 +#1 FOO in bt.mixal:4 +#2 1 in bt.mixal:3 +MIX > pbt +#0 BAR in bt.mixal:5 +#1 FOO in bt.mixal:4 +#2 1 in bt.mixal:3 +#3 BEG in bt.mixal:2 +MIX > +@end example + +Note that the executed instruction trace gives you the label of the +executed line or, if it has no label, the its address. +@end deffn + As you have probably observed, @code{mixvm} prints timing statistics when running programs. This behaviour can be controlled using the @code{timing} command (@pxref{Configuration commands}). diff --git a/mixlib/mix_vm.c b/mixlib/mix_vm.c index 0e9f61b..692f84d 100644 --- a/mixlib/mix_vm.c +++ b/mixlib/mix_vm.c @@ -67,6 +67,12 @@ vm_reset_reload_ (mix_vm_t *vm, gboolean is_reload) } if (!is_reload) mix_vm_clear_all_breakpoints (vm); + + if (vm->address_list) + { + g_slist_free (vm->address_list); + vm->address_list = NULL; + } } @@ -82,6 +88,7 @@ mix_vm_new (void) vm->symbol_table = NULL; vm->src_file = NULL; vm->pred_list = mix_predicate_list_new (vm); + vm->address_list = NULL; for (i = 0; i < BD_NO_; ++i) vm->devices[i] = NULL; @@ -106,6 +113,8 @@ mix_vm_delete (mix_vm_t * vm) if (vm->address_table != NULL) g_tree_destroy (vm->address_table); if (vm->symbol_table != NULL) mix_symbol_table_delete (vm->symbol_table); if (vm->src_file != NULL) mix_src_file_delete (vm->src_file); + if (vm->pred_list != NULL) mix_predicate_list_delete (vm->pred_list); + if (vm->address_list != NULL) g_slist_free (vm->address_list); for (i = 0; i < BD_NO_; ++i) mix_device_delete (vm->devices[i]); mix_vm_clock_delete (vm->clock); @@ -418,25 +427,6 @@ mix_vm_get_lineno_address (const mix_vm_t *vm, guint lineno) } -/* Reposition program counter and reset state so that a loaded - program can be restarted. -*/ -void -mix_vm_reset_program (mix_vm_t *vm) -{ - guint k; - g_return_if_fail (vm != NULL); - reset_loc_ (vm); - halt_ (vm, FALSE); - set_rA_ (vm, MIX_WORD_ZERO); - set_rX_ (vm, MIX_WORD_ZERO); - set_rJ_ (vm, MIX_WORD_ZERO); - for ( k = 1; k < IREG_NO_+1; ++k ) - set_rI_ (vm, k, MIX_WORD_ZERO); - set_over_ (vm, FALSE); - set_cmp_ (vm, mix_EQ); -} - /* continue execution of instructions in memory */ int mix_vm_run (mix_vm_t *vm) @@ -447,6 +437,9 @@ mix_vm_run (mix_vm_t *vm) while ( !is_halted_ (vm) ) { mix_word_to_ins_uncheck (get_cell_ (vm, get_loc_ (vm)), ins); + vm->address_list = + g_slist_prepend (vm->address_list, + GINT_TO_POINTER ((gint)get_loc_ (vm))); if ( !(*ins_handlers_[ins.opcode]) (vm,&ins) ) return MIX_VM_ERROR; else @@ -468,6 +461,9 @@ mix_vm_exec_next (mix_vm_t *vm) g_return_val_if_fail (vm != NULL, MIX_VM_ERROR); if (get_loc_ (vm) >= MIX_VM_CELL_NO) halt_ (vm, TRUE); if (is_halted_ (vm)) return MIX_VM_HALT; + vm->address_list = + g_slist_prepend (vm->address_list, + GINT_TO_POINTER ((gint)get_loc_ (vm))); mix_word_to_ins_uncheck (get_cell_ (vm, get_loc_ (vm)), ins); if (!(*ins_handlers_[ins.opcode]) (vm, &ins)) return MIX_VM_ERROR; @@ -636,3 +632,10 @@ mix_vm_get_uptime (const mix_vm_t *vm) return mix_vm_clock_get_time (get_clock_ (vm)); } +/* Get the list of addresses for executed instructions */ +const GSList * +mix_vm_get_backtrace (const mix_vm_t *vm) +{ + g_return_val_if_fail (vm != NULL, NULL); + return get_address_list_ (vm); +} diff --git a/mixlib/mix_vm.h b/mixlib/mix_vm.h index d0403cc..d3f4e3f 100644 --- a/mixlib/mix_vm.h +++ b/mixlib/mix_vm.h @@ -151,12 +151,6 @@ mix_vm_get_address_lineno (const mix_vm_t *vm, mix_address_t addr); extern mix_address_t mix_vm_get_lineno_address (const mix_vm_t *vm, guint lineno); -/* Reposition program counter and reset state so that a loaded - program can be restarted. -*/ -extern void -mix_vm_reset_program (mix_vm_t *vm); - /* continue execution of instructions in memory */ /* Possible outcomes */ enum { @@ -220,6 +214,10 @@ mix_vm_get_last_breakpoint_message (const mix_vm_t *vm); extern mix_time_t mix_vm_get_uptime (const mix_vm_t *vm); +/* Get the list of addresses for executed instructions */ +extern const GSList * +mix_vm_get_backtrace (const mix_vm_t *vm); + #endif /* MIX_VM_H */ diff --git a/mixlib/mix_vm_command.c b/mixlib/mix_vm_command.c index 264c9ff..0ccfd7b 100644 --- a/mixlib/mix_vm_command.c +++ b/mixlib/mix_vm_command.c @@ -126,6 +126,7 @@ DEC_FUN (cbpr_); DEC_FUN (cbpm_); DEC_FUN (cbpc_); DEC_FUN (cbpo_); +DEC_FUN (pbt_); /* internal command info struct */ @@ -198,6 +199,8 @@ command_ commands_[] = { "w2d WORD"}, { "tracing", cmd_tracing_, N_("Turn on/off instruction tracing"), "tracing [on|off]"}, + { "pbt", cmd_pbt_, N_("Print backtrace of executed instructions"), + "pbt [INS_NO] (e.g pbt 5)"}, { "timing", cmd_timing_, N_("Turn on/off timing statistics"), "timing [on|off]"}, { "devdir", cmd_devdir_, N_("Print/set devices directory"), @@ -1699,4 +1702,36 @@ cmd_cbpc_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg) return TRUE; } - +static gboolean +cmd_pbt_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg) +{ + enum {SIZE = 256}; + static gchar BUFFER[SIZE]; + gint no = atoi (arg); + gint k = 0, address; + guint line; + const mix_src_file_t *file = mix_vm_get_src_file (dis->vm); + char *name = file ? g_basename (mix_src_file_get_path (file)) : NULL; + + const GSList *add = mix_vm_get_backtrace (dis->vm); + while (add && (no == 0 || k < no)) + { + BUFFER[0] = '\0'; + address = GPOINTER_TO_INT (add->data); + line = mix_vm_get_address_lineno (dis->vm, address); + if (line && file) + { + int j = 0; + snprintf (BUFFER, SIZE, "%s", mix_src_file_get_line (file, line)); + while (!isspace (BUFFER[j])) j++; + BUFFER[j] = '\0'; + } + if (strlen (BUFFER) == 0) snprintf (BUFFER, SIZE, "%d", address); + fprintf (dis->out, "#%d\t%s\tin %s%s:%d\n", k, BUFFER, name, + MIX_SRC_DEFEXT, line); + ++k; + add = add->next; + } + /* if (name) g_free (name); */ + return TRUE; +} diff --git a/mixlib/mix_vm_command.h b/mixlib/mix_vm_command.h index 6c60264..5d5ebca 100644 --- a/mixlib/mix_vm_command.h +++ b/mixlib/mix_vm_command.h @@ -75,6 +75,7 @@ typedef enum { MIX_CMD_WEVAL, /* evaluate a w-expression */ MIX_CMD_W2D, /* print word in decimal notation */ MIX_CMD_TRACING, /* enable/disable instruction traces */ + MIX_CMD_PBT, /* print backtrace */ MIX_CMD_TIMING, /* enable/disable timing statistics */ MIX_CMD_DEVDIR, /* print/set device directory */ MIX_CMD_INVALID, /* invalid command identifier */ diff --git a/samples/.cvsignore b/samples/.cvsignore index bebe302..21be91e 100644 --- a/samples/.cvsignore +++ b/samples/.cvsignore @@ -1,7 +1,9 @@ Makefile Makefile.in +bt.mix cardwr.dev cbp.mix +cbp.mls disk0.dev disk1.dev disk2.dev diff --git a/samples/bt.mixal b/samples/bt.mixal new file mode 100644 index 0000000..00306ae --- /dev/null +++ b/samples/bt.mixal @@ -0,0 +1,6 @@ + ORIG 0 +BEG JMP *+1 + JMP *+1 +FOO JMP BAR +BAR HLT + END BEG diff --git a/samples/cbp.mixal b/samples/cbp.mixal index b436c8c..8c7b394 100644 --- a/samples/cbp.mixal +++ b/samples/cbp.mixal @@ -7,6 +7,7 @@ START ENTA 100 CMPA 1001 * cmp flag changed CMPX 1000 * cmp flag changed DIV 1002 * over toggle + HLT END START |