From 9d46df7ae76533833c26df9f0b0bf24e086c25b2 Mon Sep 17 00:00:00 2001 From: Jose Antonio Ortega Ruiz Date: Thu, 19 Jul 2001 00:24:23 +0000 Subject: cond bp support --- mixlib/Makefile.am | 5 +- mixlib/mix_config.c | 19 ++-- mixlib/mix_predicate.c | 207 ++++++++++++++++++++++++++++++++++++++++++++ mixlib/mix_predicate.h | 75 ++++++++++++++++ mixlib/mix_predicate_list.c | 111 ++++++++++++++++++++++++ mixlib/mix_predicate_list.h | 61 +++++++++++++ mixlib/mix_vm.c | 41 ++++++++- mixlib/mix_vm.h | 11 +++ mixlib/mix_vm_command.c | 9 +- mixlib/xmix_vm.h | 3 + 10 files changed, 528 insertions(+), 14 deletions(-) create mode 100644 mixlib/mix_predicate.c create mode 100644 mixlib/mix_predicate.h create mode 100644 mixlib/mix_predicate_list.c create mode 100644 mixlib/mix_predicate_list.h (limited to 'mixlib') diff --git a/mixlib/Makefile.am b/mixlib/Makefile.am index 2c1f818..475fad3 100644 --- a/mixlib/Makefile.am +++ b/mixlib/Makefile.am @@ -29,7 +29,10 @@ libmix_a_SOURCES = mix.h mix.c \ mix_src_file.c mix_src_file.h \ mix_vm_clock.c mix_vm_clock.h \ mix_vm_command.c mix_vm_command.h \ - mix_config.c mix_config.h + mix_config.c mix_config.h \ + mix_predicate.c mix_predicate.h \ + mix_predicate_list.c mix_predicate_list.h + diff --git a/mixlib/mix_config.c b/mixlib/mix_config.c index ba9ad19..fd3505e 100644 --- a/mixlib/mix_config.c +++ b/mixlib/mix_config.c @@ -143,24 +143,28 @@ mix_config_get_integer (const mix_config_t *config, const gchar *key) void mix_config_update (mix_config_t *config, const gchar *key, const gchar *value) { - gpointer tmp = NULL; + gpointer okey = NULL; + gpointer oval = NULL; g_return_if_fail (config != NULL); g_return_if_fail (key != NULL); g_return_if_fail (value != NULL); - tmp = g_hash_table_lookup (config->items, key); - if (tmp) + if (g_hash_table_lookup_extended (config->items, key, &okey, &oval)) { - g_free (tmp); - tmp = (gpointer)key; + if (oval != value) + { + g_free (oval); + oval = (gpointer)g_strdup (value); + } } else { - tmp = (gpointer)g_strdup (key); + okey = (gpointer)g_strdup (key); + oval = (gpointer)g_strdup (value); } - g_hash_table_insert (config->items, tmp, g_strdup (value)); + g_hash_table_insert (config->items, okey, oval); } void @@ -170,7 +174,6 @@ mix_config_update_integer (mix_config_t *config, const gchar *key, gint value) g_return_if_fail (config != NULL); g_return_if_fail (key != NULL); - g_return_if_fail (value != NULL); val = g_strdup_printf ("%d", value); mix_config_update (config, key, val); diff --git a/mixlib/mix_predicate.c b/mixlib/mix_predicate.c new file mode 100644 index 0000000..544da64 --- /dev/null +++ b/mixlib/mix_predicate.c @@ -0,0 +1,207 @@ +/* -*-c-*- -------------- mix_predicate.c : + * Implementation of the functions declared in mix_predicate.h + * ------------------------------------------------------------------ + * Last change: Time-stamp: "2001-07-16 01:15:51 jao" + * ------------------------------------------------------------------ + * Copyright (C) 2001 Free Software Foundation, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include "mix_vm.h" +#include "mix_predicate.h" + +/* predicate data */ +typedef union pred_data_t +{ + mix_word_t regA; + mix_word_t regX; + mix_short_t regI; + mix_cmpflag_t cmp; + gboolean over; + mix_word_t mem; +} pred_data_t; + +/* the predicate function type */ +typedef gboolean (*mix_predicate_fun_t) (mix_predicate_t *pred, + const mix_vm_t *vm); + +/* the predicate type */ +struct mix_predicate_t +{ + mix_predicate_type_t type; + pred_data_t data; + guint control; +}; + +/* predicate funcs */ +static gboolean +pred_func_rA (mix_predicate_t *pred, const mix_vm_t *vm) +{ + mix_word_t val = mix_vm_get_rA (vm); + if (pred->data.regA == val) return FALSE; + pred->data.regA = val; + return TRUE; +} + +static gboolean +pred_func_rX (mix_predicate_t *pred, const mix_vm_t *vm) +{ + mix_word_t val = mix_vm_get_rX (vm); + if (pred->data.regX == val) return FALSE; + pred->data.regX = val; + return TRUE; +} + +static gboolean +pred_func_rI (mix_predicate_t *pred, const mix_vm_t *vm) +{ + mix_short_t val = (pred->control == 0) ? mix_vm_get_rJ (vm) + : mix_vm_get_rI (vm, pred->control); + if (pred->data.regI == val) return FALSE; + pred->data.regI = val; + return TRUE; +} + +static gboolean +pred_func_mem (mix_predicate_t *pred, const mix_vm_t *vm) +{ + mix_word_t val = + mix_vm_get_addr_contents (vm, (mix_address_t)pred->control); + if (pred->data.mem == val) return FALSE; + pred->data.mem = val; + return TRUE; +} + +static gboolean +pred_func_cmp (mix_predicate_t *pred, const mix_vm_t *vm) +{ + mix_cmpflag_t val = mix_vm_get_cmpflag (vm); + if (pred->data.cmp == val) return FALSE; + pred->data.cmp = val; + return TRUE; +} + +static gboolean +pred_func_over (mix_predicate_t *pred, const mix_vm_t *vm) +{ + gboolean val = mix_vm_get_overflow (vm); + if (pred->data.over == val) return FALSE; + pred->data.over = val; + return TRUE; +} + +static mix_predicate_fun_t PRED_FUNCS_[] = { + pred_func_rA, pred_func_rX, pred_func_rI, pred_func_rI, pred_func_rI, + pred_func_rI, pred_func_rI, pred_func_rI, pred_func_rI, + pred_func_over, pred_func_cmp, pred_func_mem +}; + +/* create predicates based on vm status */ +mix_predicate_t * +mix_predicate_new (mix_predicate_type_t type) +{ + mix_predicate_t *result; + g_return_val_if_fail (type <= MIX_PRED_MEM, NULL); + result = g_new (mix_predicate_t, 1); + result->type = type; + result->data.regA = MIX_WORD_ZERO; + if (type >= MIX_PRED_REG_I1 && type <= MIX_PRED_REG_I6) + result->control = 1 + type - MIX_PRED_REG_I1; + else + result->control = 0; + return result; +} + +/* delete a predicate */ +void +mix_predicate_delete (mix_predicate_t *predicate) +{ + g_return_if_fail (predicate != NULL); + g_free (predicate); +} + +/* test a predicate */ +gboolean +mix_predicate_eval(mix_predicate_t *pred, const mix_vm_t *vm) +{ + g_return_val_if_fail (pred != NULL, FALSE); + g_return_val_if_fail (vm != NULL, FALSE); + return PRED_FUNCS_[pred->type] (pred, vm); +} + +/* change mem address of a MIX_PRED_MEM predicate */ +void +mix_predicate_set_mem_address (mix_predicate_t *predicate, + mix_address_t address) +{ + g_return_if_fail (predicate != NULL); + predicate->control = address; +} + +/* get message about predicate evaluation */ +const gchar * +mix_predicate_get_message (const mix_predicate_t *predicate) +{ + enum {SIZE = 256}; + static gchar BUFFER[SIZE]; + static const gchar *CMP_STRINGS[] = { "L", "E", "G"}; + + g_return_val_if_fail (predicate != NULL, NULL); + + switch (predicate->type) + { + case MIX_PRED_REG_A: + snprintf (BUFFER, SIZE, "Register A changed to %s%d", + mix_word_is_negative (predicate->data.regA)? "-" : "+", + mix_word_magnitude (predicate->data.regA)); + break; + case MIX_PRED_REG_X: + snprintf (BUFFER, SIZE, "Register X changed to %s%d", + mix_word_is_negative (predicate->data.regX)? "-" : "+", + mix_word_magnitude (predicate->data.regX)); + break; + case MIX_PRED_REG_J: + snprintf (BUFFER, SIZE, "Register J changed to %d", + mix_short_magnitude (predicate->data.regI)); + break; + case MIX_PRED_REG_I1: case MIX_PRED_REG_I2: case MIX_PRED_REG_I3: + case MIX_PRED_REG_I4: case MIX_PRED_REG_I5: case MIX_PRED_REG_I6: + snprintf (BUFFER, SIZE, "Register I%d changed to %s%d", + predicate->control, + mix_short_is_negative (predicate->data.regI)? "-" : "+", + mix_short_magnitude (predicate->data.regI)); + break; + case MIX_PRED_CMP: + snprintf (BUFFER, SIZE, "Comparison flag changed to %s", + CMP_STRINGS[predicate->data.cmp]); + break; + case MIX_PRED_OVER: + snprintf (BUFFER, SIZE, "Overflow toggled %s", + predicate->data.over ? "ON" : "OFF"); + break; + case MIX_PRED_MEM: + snprintf (BUFFER, SIZE, "Memory address %d changed to %s%d", + predicate->control, + mix_word_is_negative (predicate->data.mem)? "-" : "+", + mix_word_magnitude (predicate->data.mem)); + break; + default: + g_assert_not_reached (); + } + return BUFFER; +} + diff --git a/mixlib/mix_predicate.h b/mixlib/mix_predicate.h new file mode 100644 index 0000000..df76afb --- /dev/null +++ b/mixlib/mix_predicate.h @@ -0,0 +1,75 @@ +/* -*-c-*- ---------------- mix_predicate.h : + * Predicates and lists of predicates testing vm status. + * ------------------------------------------------------------------ + * Last change: Time-stamp: <2001-07-13 22:32:42 jao> + * ------------------------------------------------------------------ + * Copyright (C) 2001 Free Software Foundation, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + + +#ifndef MIX_PREDICATE_H +#define MIX_PREDICATE_H + +#include "mix.h" +#include "mix_types.h" +#include "mix_ins.h" + +/* the predicate type */ +typedef struct mix_predicate_t mix_predicate_t; + +/* predicate types */ +typedef enum { + MIX_PRED_REG_A, + MIX_PRED_REG_X, + MIX_PRED_REG_J, + MIX_PRED_REG_I1, + MIX_PRED_REG_I2, + MIX_PRED_REG_I3, + MIX_PRED_REG_I4, + MIX_PRED_REG_I5, + MIX_PRED_REG_I6, + MIX_PRED_OVER, + MIX_PRED_CMP, + MIX_PRED_MEM +} mix_predicate_type_t; + +/* create predicates based on vm status */ +extern mix_predicate_t * +mix_predicate_new (mix_predicate_type_t type); + +/* delete a predicate */ +extern void +mix_predicate_delete (mix_predicate_t *predicate); + +/* change mem address of a MIX_PRED_MEM predicate */ +extern void +mix_predicate_set_mem_address (mix_predicate_t *predicate, + mix_address_t address); + +/* get message about predicate evaluation */ +extern const gchar * +mix_predicate_get_message (const mix_predicate_t *predicate); + +/* test a predicate */ +#include "mix_vm.h" + +extern gboolean +mix_predicate_eval(mix_predicate_t *pred, const mix_vm_t *vm); + +#endif /* MIX_PREDICATE_H */ + diff --git a/mixlib/mix_predicate_list.c b/mixlib/mix_predicate_list.c new file mode 100644 index 0000000..3e4fe08 --- /dev/null +++ b/mixlib/mix_predicate_list.c @@ -0,0 +1,111 @@ +/* -*-c-*- -------------- mix_predicate_list.c : + * Implementation of the functions declared in mix_predicate_list.h + * ------------------------------------------------------------------ + * Last change: Time-stamp: "01/07/18 23:02:26 jao" + * ------------------------------------------------------------------ + * Copyright (C) 2001 Free Software Foundation, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + + +#include "mix_predicate_list.h" + +/* the predicate list type */ +struct mix_predicate_list_t +{ + GSList *predicates; + const mix_vm_t *vm; + const mix_predicate_t *last; +}; + +/* a list of predicates */ +mix_predicate_list_t * +mix_predicate_list_new (const mix_vm_t *vm) +{ + mix_predicate_list_t *result; + g_return_val_if_fail (vm != NULL, NULL); + result = g_new (mix_predicate_list_t, 1); + result->predicates = NULL; + result->vm = vm; + result->last = NULL; + return result; +} + +void +mix_predicate_list_delete (mix_predicate_list_t *list) +{ + g_return_if_fail (list != NULL); + g_slist_free (list->predicates); + g_free (list); +} + +/* evaluate the predicate list */ +gboolean +mix_predicate_list_eval (mix_predicate_list_t *list) +{ + GSList *node; + + g_return_val_if_fail (list != NULL, FALSE); + node = list->predicates; + while (node) { + mix_predicate_t *pred = (mix_predicate_t *)(node->data); + if (mix_predicate_eval (pred, list->vm)) + { + list->last = pred; + return TRUE; + } + node = node->next; + } + list->last = NULL; + return FALSE; +} + +/* add/remove predicates to the list */ +void +mix_predicate_list_add (mix_predicate_list_t *list, mix_predicate_t *predicate) +{ + g_return_if_fail (list != NULL); + g_return_if_fail (predicate != NULL); + if (!g_slist_find (list->predicates, predicate)) + list->predicates = g_slist_append (list->predicates, (gpointer)predicate); + (void)mix_predicate_eval (predicate, list->vm); +} + +void +mix_predicate_list_remove (mix_predicate_list_t *list, + mix_predicate_t *predicate) +{ + g_return_if_fail (list != NULL); + g_return_if_fail (predicate != NULL); + list->predicates = g_slist_remove (list->predicates, predicate); +} + +void +mix_predicate_list_clear (mix_predicate_list_t *list) +{ + g_return_if_fail (list != NULL); + g_slist_free (list->predicates); + list->predicates = NULL; + list->last = NULL; +} + +const mix_predicate_t * +mix_predicate_list_last_true_eval (const mix_predicate_list_t *list) +{ + g_return_val_if_fail (list != NULL, NULL); + return list->last; +} diff --git a/mixlib/mix_predicate_list.h b/mixlib/mix_predicate_list.h new file mode 100644 index 0000000..416f3db --- /dev/null +++ b/mixlib/mix_predicate_list.h @@ -0,0 +1,61 @@ +/* -*-c-*- ---------------- mix_predicate_list.h : + * A list of predicates. + * ------------------------------------------------------------------ + * Last change: Time-stamp: <01/07/18 23:02:40 jao> + * ------------------------------------------------------------------ + * Copyright (C) 2001 Free Software Foundation, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + + +#ifndef MIX_PREDICATE_LIST_H +#define MIX_PREDICATE_LIST_H + +#include "mix.h" +#include "mix_vm.h" +#include "mix_predicate.h" + +/* the predicate list type */ +typedef struct mix_predicate_list_t mix_predicate_list_t; + +/* create/destroy a list of predicates */ +extern mix_predicate_list_t * +mix_predicate_list_new (const mix_vm_t *vm); + +extern void +mix_predicate_list_delete (mix_predicate_list_t *list); + +/* evaluate the predicate list */ +extern gboolean +mix_predicate_list_eval (mix_predicate_list_t *list); + +extern const mix_predicate_t * +mix_predicate_list_last_true_eval (const mix_predicate_list_t *list); + +/* add/remove predicates to the list */ +extern void +mix_predicate_list_add (mix_predicate_list_t *list, mix_predicate_t *predicate); + +extern void +mix_predicate_list_remove (mix_predicate_list_t *list, + mix_predicate_t *predicate); + +extern void +mix_predicate_list_clear (mix_predicate_list_t *list); + +#endif /* MIX_PREDICATE_LIST_H */ + diff --git a/mixlib/mix_vm.c b/mixlib/mix_vm.c index f41c60a..8929527 100644 --- a/mixlib/mix_vm.c +++ b/mixlib/mix_vm.c @@ -65,7 +65,8 @@ vm_reset_reload_ (mix_vm_t *vm, gboolean is_reload) mix_device_delete (vm->devices[k]); vm->devices[k] = NULL; } - if (!is_reload) bp_clear_all_ (vm); + if (!is_reload) + mix_vm_clear_all_breakpoints (vm); } @@ -80,6 +81,7 @@ mix_vm_new (void) vm->address_table = NULL; vm->symbol_table = NULL; vm->src_file = NULL; + vm->pred_list = mix_predicate_list_new (vm); for (i = 0; i < BD_NO_; ++i) vm->devices[i] = NULL; @@ -451,6 +453,8 @@ mix_vm_run (mix_vm_t *vm) update_time_ (vm, &ins); if (bp_is_set_ (vm, get_loc_ (vm))) return MIX_VM_BREAK; + if (mix_predicate_list_eval (get_pred_list_ (vm))) + return MIX_VM_COND_BREAK; if (get_loc_ (vm) >= MIX_VM_CELL_NO) halt_ (vm, TRUE); } return MIX_VM_HALT; @@ -470,7 +474,10 @@ mix_vm_exec_next (mix_vm_t *vm) else update_time_ (vm, &ins); if (is_halted_ (vm)) return MIX_VM_HALT; - return bp_is_set_ (vm, get_loc_ (vm)) ? MIX_VM_BREAK : MIX_VM_OK; + if (bp_is_set_ (vm, get_loc_ (vm))) return MIX_VM_BREAK; + if (mix_predicate_list_eval (get_pred_list_ (vm))) + return MIX_VM_COND_BREAK; + return MIX_VM_OK; } /* Breakpoints */ @@ -590,6 +597,36 @@ mix_vm_clear_all_breakpoints (mix_vm_t *vm) { g_return_if_fail (vm != NULL); bp_clear_all_ (vm); + mix_predicate_list_clear (get_pred_list_ (vm)); +} + + +gint +mix_vm_set_conditional_breakpoint (mix_vm_t *vm, mix_predicate_t *pred) +{ + g_return_val_if_fail (vm != NULL, MIX_VM_BP_ERROR); + g_return_val_if_fail (pred != NULL, MIX_VM_BP_ERROR); + mix_predicate_list_add (get_pred_list_ (vm), pred); + return MIX_VM_BP_OK; +} + +gint +mix_vm_clear_conditional_breakpoint (mix_vm_t *vm, mix_predicate_t *pred) +{ + g_return_val_if_fail (vm != NULL, MIX_VM_BP_ERROR); + g_return_val_if_fail (pred != NULL, MIX_VM_BP_ERROR); + mix_predicate_list_remove (get_pred_list_ (vm), pred); + return MIX_VM_BP_OK; +} + +const gchar * +mix_vm_get_last_breakpoint_message (const mix_vm_t *vm) +{ + const mix_predicate_t *last = NULL; + g_return_val_if_fail (vm != NULL, NULL); + if ((last = mix_predicate_list_last_true_eval (get_pred_list_ (vm))) != NULL) + return mix_predicate_get_message (last); + return NULL; } /* Get the vm uptime, defined as the time spent executing instructions */ diff --git a/mixlib/mix_vm.h b/mixlib/mix_vm.h index a8b826e..663062b 100644 --- a/mixlib/mix_vm.h +++ b/mixlib/mix_vm.h @@ -162,6 +162,7 @@ mix_vm_reset_program (mix_vm_t *vm); enum { MIX_VM_ERROR, /* error executing instructions */ MIX_VM_BREAK, /* breakpoint found */ + MIX_VM_COND_BREAK, /* conditional breakpoint found */ MIX_VM_HALT, /* end of execution */ MIX_VM_OK /* successful instruction execution */ }; @@ -205,6 +206,16 @@ mix_vm_has_breakpoint_at_address (const mix_vm_t *vm, guint address); extern void mix_vm_clear_all_breakpoints (mix_vm_t *vm); +#include "mix_predicate.h" +extern gint +mix_vm_set_conditional_breakpoint (mix_vm_t *vm, mix_predicate_t *pred); + +extern gint +mix_vm_clear_conditional_breakpoint (mix_vm_t *vm, mix_predicate_t *pred); + +extern const gchar * +mix_vm_get_last_breakpoint_message (const mix_vm_t *vm); + /* Get the vm uptime, defined as the time spent executing instructions */ extern mix_time_t mix_vm_get_uptime (const mix_vm_t *vm); diff --git a/mixlib/mix_vm_command.c b/mixlib/mix_vm_command.c index bb4b67f..9344618 100644 --- a/mixlib/mix_vm_command.c +++ b/mixlib/mix_vm_command.c @@ -37,6 +37,9 @@ # include #endif +#ifdef HAVE_LIBREADLINE +# include +#endif /* hooks */ typedef struct @@ -268,14 +271,14 @@ mix_vm_cmd_dispatcher_new_with_config (FILE *out, FILE *err, val = mix_config_get (result->config, TIMING_KEY_); if (val) cmd_timing_ (result, val); val = mix_config_get_devices_dir (result->config); - if (!val) + if (!val || !mix_stat_dir (val, "devices")) { gchar *dirname = g_dirname (mix_config_get_filename (config)); cmd_devdir_ (result, dirname); g_free (dirname); } else - cmd_devdir_ (result, val); + mix_device_set_dir (val); #ifdef HAVE_LIBHISTORY val = mix_config_get_history_file (result->config); hsize = mix_config_get_history_size (result->config); @@ -361,7 +364,7 @@ mix_vm_cmd_dispatcher_get_src_file_path (const mix_vm_cmd_dispatcher_t *dis) g_free (PATH); PATH = NULL; } - + if (f) PATH = mix_file_complete_name (mix_src_file_get_path (f), MIX_SRC_DEFEXT); diff --git a/mixlib/xmix_vm.h b/mixlib/xmix_vm.h index d5cbff4..4ed1e42 100644 --- a/mixlib/xmix_vm.h +++ b/mixlib/xmix_vm.h @@ -29,6 +29,7 @@ #include "mix_symbol_table.h" #include "mix_device.h" #include "mix_src_file.h" +#include "mix_predicate_list.h" #include "mix_vm.h" /* The mix_vm_t type */ @@ -50,6 +51,7 @@ struct mix_vm_t mix_symbol_table_t *symbol_table; mix_src_file_t *src_file; /* source of last loaded code file */ mix_device_factory_t factory; /* the factory for new devices */ + mix_predicate_list_t *pred_list; /* predicates for conditional bps */ }; /* Macros for accessing/modifying the above structure. @@ -72,6 +74,7 @@ enum { A_ = 0, X_, J_, I1_, I2_, I3_, I4_, I5_, I6_ }; #define get_over_(vm) (vm->overflow) #define get_loc_(vm) (vm->loc_count) #define get_clock_(vm) (vm->clock) +#define get_pred_list_(vm) (vm->pred_list) #define set_reg_(vm,r,x) \ do { \ -- cgit v1.2.3