📄 mix_vm.c
字号:
mix_src_file_get_path (sfile))); } vm_reset_reload_ (vm, reload); if ( mix_code_file_is_debug (file) ) { vm->symbol_table = mix_code_file_get_symbol_table (file); vm->line_table = g_tree_new (cmp_uint_); vm->address_table = g_tree_new (cmp_uint_); } vm->src_file = sfile; 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->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)); mix_code_file_delete (file); set_status_ (vm, MIX_VM_LOADED); return TRUE;}const mix_src_file_t *mix_vm_get_src_file (const mix_vm_t *vm){ g_return_val_if_fail (vm != NULL, NULL); return vm->src_file;}const mix_symbol_table_t *mix_vm_get_symbol_table (const mix_vm_t *vm){ g_return_val_if_fail (vm != NULL, NULL); return vm->symbol_table;}mix_address_t mix_vm_get_prog_count (const mix_vm_t *vm){ g_return_val_if_fail (vm != NULL, MIX_SHORT_ZERO); return get_loc_ (vm);}/* Get the source line number for a given address */guintmix_vm_get_address_lineno (const mix_vm_t *vm, mix_address_t addr){ gpointer gp_addr = GUINT_TO_POINTER ((guint)addr); guint lineno; g_return_val_if_fail (vm != NULL, 0); g_return_val_if_fail (MEMOK_ (addr), 0); lineno = GPOINTER_TO_UINT (g_tree_lookup (vm->address_table, gp_addr)); return lineno;}/* Get the address for a given source line number */typedef struct { guint lineno; mix_address_t result;} addr_traverse_t;static gintget_address_ (gpointer key, gpointer value, gpointer data){ addr_traverse_t *tr = (addr_traverse_t *)data; if (GPOINTER_TO_UINT (key) == tr->lineno) { tr->result = mix_short_new (GPOINTER_TO_UINT (value)); return TRUE; } return (GPOINTER_TO_UINT (key) < tr->lineno)? FALSE:TRUE;}mix_address_tmix_vm_get_lineno_address (const mix_vm_t *vm, guint lineno){ addr_traverse_t tr; g_return_val_if_fail (vm != NULL, MIX_VM_CELL_NO); if (!vm->line_table) return MIX_VM_CELL_NO; tr.lineno = lineno; tr.result = MIX_VM_CELL_NO; g_tree_traverse (vm->line_table, get_address_, G_IN_ORDER, (gpointer)&tr); return tr.result;}/* continue execution of instructions in memory */mix_vm_status_tmix_vm_run (mix_vm_t *vm){ mix_ins_t ins; g_return_val_if_fail (vm != NULL, MIX_VM_ERROR); 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 set_status_ (vm, MIX_VM_ERROR); else update_time_ (vm, &ins); if (bp_is_set_ (vm, get_loc_ (vm))) return set_status_ (vm, MIX_VM_BREAK); if (mix_predicate_list_eval (get_pred_list_ (vm))) return set_status_ (vm, MIX_VM_COND_BREAK); if (get_loc_ (vm) >= MIX_VM_CELL_NO) halt_ (vm, TRUE); } return set_status_ (vm, MIX_VM_HALT);}/* execute next memory instruction */mix_vm_status_tmix_vm_exec_next (mix_vm_t *vm){ mix_ins_t ins; 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 set_status_ (vm, 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 set_status_ (vm, MIX_VM_ERROR); else update_time_ (vm, &ins); if (is_halted_ (vm)) return set_status_ (vm, MIX_VM_HALT); if (bp_is_set_ (vm, get_loc_ (vm))) return set_status_ (vm, MIX_VM_BREAK); if (mix_predicate_list_eval (get_pred_list_ (vm))) return set_status_ (vm, MIX_VM_COND_BREAK); return set_status_ (vm, MIX_VM_RUNNING);}/* get the current execution status */mix_vm_status_tmix_vm_get_run_status (const mix_vm_t *vm){ g_return_val_if_fail (vm != NULL, MIX_VM_ERROR); return get_status_ (vm);}/* Breakpoints */gulongmix_vm_get_break_lineno (const mix_vm_t *vm){ g_return_val_if_fail (vm != NULL, 0); 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 { mix_vm_t *vm; guint lineno; gint result;} bp_traverse_t;static gintset_break_ (gpointer key, gpointer value, gpointer data){ bp_traverse_t *tr = (bp_traverse_t *)data; if (GPOINTER_TO_UINT (key) >= tr->lineno) { bp_set_ (tr->vm, mix_short_new (GPOINTER_TO_UINT (value))); tr->lineno = GPOINTER_TO_UINT (key); tr->result = MIX_VM_BP_OK; return TRUE; } return FALSE;}gint /* if >0 the line no. of the break point */mix_vm_set_breakpoint (mix_vm_t *vm, guint lineno){ bp_traverse_t tr; g_return_val_if_fail (vm != NULL, MIX_VM_BP_ERROR); if (!vm->line_table) return MIX_VM_BP_NDEBUG; tr.lineno = lineno; tr.vm = vm; tr.result = MIX_VM_BP_INV_LINE; g_tree_traverse (vm->line_table, set_break_, G_IN_ORDER, (gpointer)&tr); if (tr.result == MIX_VM_BP_OK) return tr.lineno; else return tr.result;}gintmix_vm_set_breakpoint_address (mix_vm_t *vm, guint address) { g_return_val_if_fail (vm != NULL, MIX_VM_BP_ERROR); if (address >= MIX_VM_CELL_NO) return MIX_VM_BP_INV_ADDRESS; else bp_set_ (vm, mix_short_new (address)); return MIX_VM_BP_OK;}gbooleanmix_vm_has_breakpoint_at_address (const mix_vm_t *vm, guint address){ g_return_val_if_fail (vm != NULL, FALSE); if (address >= MIX_VM_CELL_NO) return FALSE; return (bp_is_set_ (vm, address));}static gintclear_break_ (gpointer key, gpointer value, gpointer data){ bp_traverse_t *tr = (bp_traverse_t *)data; if (GPOINTER_TO_UINT (key) == tr->lineno) { bp_clear_ (tr->vm, mix_short_new (GPOINTER_TO_UINT (value))); tr->result = MIX_VM_BP_OK; return TRUE; } else if (GPOINTER_TO_UINT (key) > tr->lineno) return TRUE; return FALSE;}gint /* one of MIX_VM_BP_ */mix_vm_clear_breakpoint (mix_vm_t *vm, guint lineno){ bp_traverse_t tr; g_return_val_if_fail (vm != NULL, MIX_VM_BP_ERROR); if (!vm->line_table) return MIX_VM_BP_NDEBUG; tr.lineno = lineno; tr.vm = vm; tr.result = MIX_VM_BP_INV_LINE; g_tree_traverse (vm->line_table, clear_break_, G_IN_ORDER, (gpointer)&tr); return tr.result;}gintmix_vm_clear_breakpoint_address (mix_vm_t *vm, guint address) { g_return_val_if_fail (vm != NULL, MIX_VM_BP_ERROR); if (address >= MIX_VM_CELL_NO) return MIX_VM_BP_INV_ADDRESS; else bp_clear_ (vm, mix_short_new (address)); return MIX_VM_BP_OK;}voidmix_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));}gbooleanmix_vm_set_conditional_breakpoint (mix_vm_t *vm, mix_predicate_t *pred){ g_return_val_if_fail (vm != NULL, FALSE); g_return_val_if_fail (pred != NULL, FALSE); mix_predicate_list_add (get_pred_list_ (vm), pred); return TRUE;}gbooleanmix_vm_clear_conditional_breakpoint (mix_vm_t *vm, mix_predicate_t *pred){ g_return_val_if_fail (vm != NULL, FALSE); g_return_val_if_fail (pred != NULL, FALSE); return mix_predicate_list_remove (get_pred_list_ (vm), pred);}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;}mix_predicate_type_tmix_vm_get_last_conditional_breakpoint_type (const mix_vm_t *vm){ const mix_predicate_t *last = NULL; g_return_val_if_fail (vm != NULL, MIX_PRED_INVALID); last = mix_predicate_list_last_true_eval (get_pred_list_ (vm)); return last? mix_predicate_get_type (last) : MIX_PRED_INVALID;}/* Get the vm uptime, defined as the time spent executing instructions */mix_time_tmix_vm_get_uptime (const mix_vm_t *vm){ g_return_val_if_fail (vm != NULL, 0); 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);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -