summaryrefslogtreecommitdiffhomepage
path: root/mixlib/mix_vm.c
diff options
context:
space:
mode:
Diffstat (limited to 'mixlib/mix_vm.c')
-rw-r--r--mixlib/mix_vm.c59
1 files changed, 27 insertions, 32 deletions
diff --git a/mixlib/mix_vm.c b/mixlib/mix_vm.c
index 37a0c6d..d1ad6e7 100644
--- a/mixlib/mix_vm.c
+++ b/mixlib/mix_vm.c
@@ -47,6 +47,11 @@ vm_reset_ (mix_vm_t *vm)
g_tree_destroy (vm->line_table);
vm->line_table = NULL;
}
+ if (vm->address_table != NULL)
+ {
+ g_tree_destroy (vm->address_table);
+ vm->address_table = NULL;
+ }
bp_clear_all_ (vm);
}
@@ -59,6 +64,7 @@ mix_vm_new (void)
mix_vm_t *vm = g_new (struct mix_vm_t,1);
vm->line_table = NULL;
+ vm->address_table = NULL;
vm->symbol_table = NULL;
for (i = 0; i < BD_NO_; ++i)
@@ -68,12 +74,14 @@ mix_vm_new (void)
return vm;
}
+
void
mix_vm_delete (mix_vm_t * vm)
{
int i;
if (vm->line_table != NULL) g_tree_destroy (vm->line_table);
+ if (vm->address_table != NULL) g_tree_destroy (vm->address_table);
if (vm->symbol_table != NULL) mix_symbol_table_delete (vm->symbol_table);
for (i = 0; i < BD_NO_; ++i)
mix_device_delete (vm->devices[i]);
@@ -224,9 +232,9 @@ mix_vm_exec_ins (mix_vm_t *vm, const mix_ins_t *ins)
return (*ins_handlers_[ins->opcode]) (vm,ins);
}
-/* comparison function for the line table tree */
+/* comparison function for the line and address tables tree */
static gint
-cmp_lineno_ (gconstpointer a, gconstpointer b)
+cmp_uint_ (gconstpointer a, gconstpointer b)
{
return GPOINTER_TO_UINT (a) - GPOINTER_TO_UINT (b);
}
@@ -244,15 +252,21 @@ mix_vm_load_file (mix_vm_t *vm, const gchar *name)
if ( mix_code_file_is_debug (file) )
{
vm->symbol_table = mix_code_file_get_symbol_table (file);
- vm->line_table = g_tree_new (cmp_lineno_);
+ vm->line_table = g_tree_new (cmp_uint_);
+ vm->address_table = g_tree_new (cmp_uint_);
}
while ( mix_code_file_get_ins (file, &ins) )
{
set_cell_ (vm, ins.address, ins.ins);
if ( vm->line_table != NULL )
- g_tree_insert (vm->line_table,
- GUINT_TO_POINTER (ins.lineno),
- GUINT_TO_POINTER ((guint)ins.address));
+ {
+ g_tree_insert (vm->line_table,
+ GUINT_TO_POINTER (ins.lineno),
+ GUINT_TO_POINTER ((guint)ins.address));
+ g_tree_insert (vm->address_table,
+ GUINT_TO_POINTER ((guint)ins.address),
+ GUINT_TO_POINTER (ins.lineno));
+ }
}
set_loc_ (vm, mix_code_file_get_start_addr (file));
set_start_ (vm, get_loc_ (vm));
@@ -314,36 +328,17 @@ mix_vm_exec_next (mix_vm_t *vm)
}
/* Breakpoints */
-typedef struct
-{
- mix_address_t address;
- gulong lineno;
-} fline_t;
-
-static int
-find_break_ (gpointer key, gpointer value, gpointer data)
-{
- fline_t *fl = (fline_t *)data;
-
- if ( mix_short_new (GPOINTER_TO_UINT (value)) == fl->address )
- {
- fl->lineno = GPOINTER_TO_UINT (key);
- return TRUE;
- }
- return FALSE;
-}
-
gulong
mix_vm_get_break_lineno (const mix_vm_t *vm)
{
- fline_t fl;
-
g_return_val_if_fail (vm != NULL, 0);
- if (vm->line_table == NULL) return 0;
- fl.lineno = 0;
- fl.address = get_loc_ (vm);
- g_tree_traverse (vm->line_table, find_break_, G_IN_ORDER, (gpointer) &fl);
- return fl.lineno;
+ if (vm->address_table == NULL)
+ return 0;
+ else
+ {
+ gpointer loc = GUINT_TO_POINTER ((guint)get_loc_ (vm));
+ return GPOINTER_TO_UINT (g_tree_lookup (vm->address_table,loc));
+ }
}
typedef struct