Exemplo n.º 1
0
static
#endif
void reinitialize(void) {
#if !TESTING
    ASSERT_ON_CPU_THREAD();
#endif

    cycles_count_total = 0;
    cycles_video_frame = 0;
#if !TEST_CPU
    video_scannerReset();
#endif

#if TESTING
    extern unsigned long (*testing_getCyclesCount)(void);
    if (testing_getCyclesCount) {
        cycles_count_total = testing_getCyclesCount();
    }
#endif

    vm_initialize();

    cpu65_init();

    timing_initialize();

    MB_Reset();
}
Exemplo n.º 2
0
static
#endif
void reinitialize(void) {
#if !TESTING
    assert(pthread_self() == cpu_thread_id);
#endif

    cycles_count_total = 0;

    vm_initialize();

    softswitches = SS_TEXT | SS_IOUDIS | SS_C3ROM | SS_LCWRT | SS_LCSEC;

    video_setpage( 0 );

    video_redraw();

    cpu65_init();

    timing_initialize();

#ifdef AUDIO_ENABLED
    MB_Reset();
#endif
}
Exemplo n.º 3
0
/* VM_RESERVESPACE -- Reserve VM space for file data.  This directive is
 * useful if VM is being used but the VM space could not be preallocated
 * at file access time, e.g., when opening a new file.
 */
int
vm_reservespace (long nbytes)
{
	char buf[SZ_CMDBUF];
	int status;

	if (!vm_initialized)
	    vm_initialize();
	if (!vm_enabled || vm_dioenabled)
	    return (-1);
	if (vm_connect() < 0)
	    return (-1);

	/* Format and send the file access directive to the VMcache daemon.
	 * The status from the server is returned as an ascii integer value
	 * on the same socket.
	 */
	sprintf (buf, "reservespace %ld\n", nbytes);
	if (vm_debug)
	    fprintf (stderr, "vmclient (%s): %s", vm_client, buf);

	if (vm_write (vm_server, buf, strlen(buf)) < 0) {
	    vm_shutdown();
	    return (-1);
	}
	if (read (vm_server, buf, SZ_CMDBUF) <= 0) {
	    if (vm_debug)
		fprintf (stderr,
		    "vmclient (%s): server not responding\n", vm_client);
	    vm_shutdown();
	    return (-1);
	}

	status = atoi (buf);
	return (status);
}
Exemplo n.º 4
0
/*
 *   Run pre-initialization 
 */
void vm_run_preinit(CVmFile *origfp, const char *image_fname,
                    CVmFile *newfp, class CVmHostIfc *hostifc,
                    class CVmMainClientIfc *clientifc, 
                    const char *const *argv, int argc,
                    class CVmRuntimeSymbols *runtime_symtab,
                    class CVmRuntimeSymbols *runtime_macros)
{
    vm_globals *vmg__;
    CVmImageLoader *volatile loader = 0;
    CVmImageFile *volatile imagefp = 0;

    /* initialize the VM */
    vm_init_options opts(hostifc, clientifc);
    vm_initialize(&vmg__, &opts);

    /* 
     *   turn off "more" on the console - when running preinitialization,
     *   any output is purely diagnostic information for the programmer
     *   and thus should be formatted as simple stdio-style console output 
     */
    G_console->set_more_state(FALSE);

    err_try
    {
        /* note where the image file starts */
        long start_pos = origfp->get_pos();
        
        /* create the loader */
        imagefp = new CVmImageFileExt(origfp);
        loader = new CVmImageLoader(imagefp, image_fname, 0);

        /* load the image */
        loader->load(vmg0_);

        /* set pre-init mode */
        G_preinit_mode = TRUE;

        /* run it, using the runtime symbols the caller sent us */
        loader->run(vmg_ argv, argc, runtime_symtab, runtime_macros, 0);

        /* 
         *   seek back to the start of the image file, since we need to
         *   copy parts of the original file to the new file 
         */
        origfp->set_pos(start_pos);

        /* save the new image file */
        vm_rewrite_image(vmg_ origfp, newfp, loader->get_static_cs_ofs());
    }
    err_finally
    {
        /* detach the pools from the image file */
        if (loader != 0)
            loader->unload(vmg0_);

        /* delete the loader and the image file object */
        if (loader != 0)
            delete loader;
        if (imagefp != 0)
            delete imagefp;

        /* terminate the VM */
        vm_terminate(vmg__, clientifc);
    }
    err_end;
}
Exemplo n.º 5
0
/*
 *   Execute an image file.  If an exception occurs, we'll display a
 *   message on the console, and we'll return the error code; we'll return
 *   zero on success.  If an error occurs, we'll fill in 'errbuf' with a
 *   message describing the problem.  
 */
int vm_run_image(CVmMainClientIfc *clientifc,
                 const char *image_file_name,
                 class CVmHostIfc *hostifc,
                 const char *const *prog_argv, int prog_argc,
                 const char *script_file, int script_quiet,
                 const char *log_file, const char *cmd_log_file,
                 int load_from_exe, int show_banner,
                 const char *charset, const char *log_charset,
                 const char *saved_state, const char *res_dir)
{
    CVmFile *fp = 0;
    CVmImageLoader *volatile loader = 0;
    CVmImageFile *volatile imagefp = 0;
    unsigned long image_file_base = 0;
    int retval;
    vm_globals *vmg__;

    /* presume we will return success */
    retval = 0;

    /* create the file object */
    fp = new CVmFile();

    /* initialize the VM */
    vm_init_options opts(hostifc, clientifc, charset, log_charset);
    vm_initialize(&vmg__, &opts);

    /* tell the client system to initialize */
    clientifc->client_init(VMGLOB_ADDR, script_file, script_quiet,
                           log_file, cmd_log_file,
                           show_banner ? T3VM_BANNER_STRING : 0);

    /* catch any errors that occur during loading and running */
    err_try
    {
        /* remember the name of the byte-code file */
        strncpy(G_os_gamename, image_file_name, sizeof(G_os_gamename));
        G_os_gamename[sizeof(G_os_gamename) - 1] = '\0';

        if (load_from_exe)
        {
            osfildef *exe_fp;

            /* find the image within the executable */
            exe_fp = os_exeseek(image_file_name, "TGAM");
            if (exe_fp == 0)
                err_throw(VMERR_NO_IMAGE_IN_EXE);

            /* 
             *   set up to read from the executable at the location of the
             *   embedded image file that we just found 
             */
            image_file_base = osfpos(exe_fp);
            fp->set_file(exe_fp, image_file_base);
        }
        else
        {
            /* reading from a normal file - open the file */
            fp->open_read(image_file_name, OSFTT3IMG);
        }

        /* create the loader */
        imagefp = new CVmImageFileExt(fp);
        loader = new CVmImageLoader(imagefp, image_file_name,
                                    image_file_base);

        /* load the image */
        loader->load(vmg0_);

        /* if we have a resource root path, tell the host interface */
        if (res_dir != 0)
            hostifc->set_res_dir(res_dir);

        /* let the client prepare for execution */
        clientifc->pre_exec(VMGLOB_ADDR);

        /* run the program from the main entrypoint */
        loader->run(vmg_ prog_argv, prog_argc, 0, saved_state);

        /* tell the client we're done with execution */
        clientifc->post_exec(VMGLOB_ADDR);
    }
    err_catch(exc)
    {
        char errbuf[512];

        /* tell the client execution failed due to an error */
        clientifc->post_exec_err(VMGLOB_ADDR);

        /* note the error code for returning to the caller */
        retval = exc->get_error_code();

        /* get the message for the error */
        CVmRun::get_exc_message(vmg_ exc, errbuf, sizeof(errbuf), TRUE);
        
        /* display the message */
        clientifc->display_error(VMGLOB_ADDR, errbuf, FALSE);
    }
    err_end;

    /* unload the image */
    if (loader != 0)
        loader->unload(vmg0_);

    /* delete the loader and the image file object */
    if (loader != 0)
        delete loader;
    if (imagefp != 0)
        delete imagefp;

    /* notify the client */
    clientifc->client_terminate(VMGLOB_ADDR);

    /* terminate the VM */
    vm_terminate(vmg__, clientifc);

    /* delete the file */
    if (fp != 0)
        delete fp;

    /* return the status code */
    return retval;
}
Exemplo n.º 6
0
int main(int argc, char **argv)
{
    CImageFile *imagefp;
    vm_val_t val;
    vm_val_t *stkval;
    vm_globals *vmg__;
    CVmHostIfc *hostifc;
    CVmMainClientConsole clientifc;

    /* initialize for testing */
    test_init();

    /* initialize the VM */
    hostifc = new CVmHostIfcStdio(argv[0]);
    vm_initialize(&vmg__, &vm_init_options(hostifc, &clientifc,
                                           "us-ascii", "us_ascii"));

    /* create a fake host file object */
    imagefp = new CImageFile();

    /* create the constant pool */
    G_const_pool->attach_backing_store(imagefp);

    /* create a couple of objects and push them on the stack */
    val.set_obj(CVmObjTads::create(vmg_ FALSE, 0, 4));
    G_stk->push(&val);
    val.set_obj(CVmObjTads::create(vmg_ FALSE, 0, 4));
    G_stk->push(&val);

    /* 
     *   create another object, and store it in a property of the first
     *   object 
     */
    val.set_obj(CVmObjTads::create(vmg_ FALSE, 0, 4));
    stkval = G_stk->get(1);
    vm_objp(vmg_ stkval->val.obj)->
        set_prop(vmg_ G_undo, stkval->val.obj, PROP_A, &val);

    /* collect garbage - nothing should be deleted at this point */
    G_obj_table->gc_full(vmg0_);

    /* 
     *   forget about the second object by popping it off the stack, then
     *   collect garbage again -- the second object should be deleted at
     *   this point, because it's no longer reachable 
     */
    G_stk->discard();
    G_obj_table->gc_full(vmg0_);

    /*
     *   Force the first object's property table to expand by filling up
     *   its initial table 
     */
    stkval = G_stk->get(0);
    val.set_nil();
    vm_objp(vmg_ stkval->val.obj)->
        set_prop(vmg_ G_undo, stkval->val.obj, PROP_A, &val);
    vm_objp(vmg_ stkval->val.obj)->
        set_prop(vmg_ G_undo, stkval->val.obj, PROP_B, &val);
    vm_objp(vmg_ stkval->val.obj)->
        set_prop(vmg_ G_undo, stkval->val.obj, PROP_C, &val);
    vm_objp(vmg_ stkval->val.obj)->
        set_prop(vmg_ G_undo, stkval->val.obj, PROP_D, &val);
    vm_objp(vmg_ stkval->val.obj)->
        set_prop(vmg_ G_undo, stkval->val.obj, PROP_E, &val);

    /* set an existing property */
    vm_objp(vmg_ stkval->val.obj)->
        set_prop(vmg_ G_undo, stkval->val.obj, PROP_B, &val);
    
    /* we're done, so delete all of our managers */
    G_const_pool->detach_backing_store();
    delete imagefp;

    /* shut down the VM */
    vm_terminate(vmg__, &clientifc);

    /* delete the host interface */
    delete hostifc;

    /* terminate */
    return 0;
}
Exemplo n.º 7
0
/* VM_DELETE -- Delete any VM space used by a file, e.g., because the file
 * is being physically deleted.  This should be called before the file is
 * actually deleted so that the cache can determine its device and inode
 * values.
 */
int
vm_delete (char *fname, int force)
{
	struct stat st;
	char buf[SZ_COMMAND];
	char pathname[SZ_PATHNAME];
	int status = 0;

	/* One-time process initialization. */
	if (!vm_initialized)
	    vm_initialize();

	if (stat (fname, &st) < 0) {
	    status = -1;
	    goto done;
	}

	/* If VMcache is not being used we are done. */
	if (vm_dioenabled && (st.st_size >= dio_threshold))
	    goto done;
	else if (!vm_enabled || st.st_size < vm_threshold)
	    goto done;

	/* Don't delete the VM space used by the file if it has hard links
	 * and only a link is being deleted (force flag will override).
	 */
	if (st.st_nlink > 1 && !force)
	    goto done;

	/* Connect to the VMcache server if not already connected. */
	if (!vm_server)
	    if (vm_connect() < 0) {
		status = -1;
		goto done;
	    }

	/* Format and send the delete directive to the VMcache daemon.
	 * The status from the server is returned as an ascii integer value
	 * on the same socket.
	 */
	sprintf (buf, "delete %s\n", realpath(fname,pathname));
	if (vm_write (vm_server, buf, strlen(buf)) < 0) {
	    vm_shutdown();
	    status = -1;
	    goto done;
	}
	if (read (vm_server, buf, SZ_CMDBUF) <= 0) {
	    if (vm_debug)
		fprintf (stderr,
		    "vmclient (%s): server not responding\n", vm_client);
	    vm_shutdown();
	    status = -1;
	    goto done;
	}

	status = atoi (buf);
done:
	if (vm_debug)
	    fprintf (stderr, "vmclient (%s): delete `%s' -> %d\n",
		vm_client, fname, status);

	return (status < 0 ? -1 : status);
}
Exemplo n.º 8
0
/* VM_ACCESS -- Access a file via the VM subsystem.  A return value of 1
 * indicates that the file is (or will be) "cached" in virtual memory, i.e.,
 * that normal virtual memory file system (normal file i/o) should be used
 * to access the file.  A return value of 0 indicates that direct i/o should
 * be used to access the file, bypassing the virtual memory file system.
 */
int
vm_access (char *fname, int mode)
{
	struct stat st;
	char *modestr = NULL, buf[SZ_COMMAND];
	char pathname[SZ_PATHNAME];
	int status;


	/* One-time process initialization. */
	if (!vm_initialized)
	    vm_initialize();

	if (stat (fname, &st) < 0) {
	    status = DEF_ACCESSVAL;
	    goto done;
	}

	/* If directio is enabled and the file exceeds the directio threshold
	 * use directio to access the file (access=0).  If vmcache is
	 * disabled use normal VM-based i/o to access the file (access=1).
	 * If VMcache is enabled we still only use it if the file size
	 * exceeds vm_threshold.
	 */
	if (vm_dioenabled) {
	    status = (st.st_size >= dio_threshold) ? 0 : 1;
	    goto done;
	} else if (!vm_enabled || st.st_size < vm_threshold) {
	    status = DEF_ACCESSVAL;
	    goto done;
	}

	/* Use of VMcache is enabled and the file equals or exceeds the 
	 * minimum size threshold.  Initialization has already been performed.
	 * Open a VMcache daemon server connection if we don't already have
	 * one.  If the server connection fails we are done, but we will try
	 * to open a connection again in the next file access.
	 */
	if (!vm_server)
	    if (vm_connect() < 0) {
		status = DEF_ACCESSVAL;
		goto done;
	    }

	/* Compute the mode string for the server request. */
	switch (mode) {
	case READ_ONLY:
	    modestr = "ro";
	    break;
	case NEW_FILE:
	case READ_WRITE:
	case APPEND:
	    modestr = "rw";
	    break;
	}

	/* Format and send the file access directive to the VMcache daemon.
	 * The status from the server is returned as an ascii integer value
	 * on the same socket.
	 */
	sprintf (buf, "access %s %s\n", realpath(fname,pathname), modestr);
	if (vm_write (vm_server, buf, strlen(buf)) < 0) {
	    vm_shutdown();
	    status = DEF_ACCESSVAL;
	    goto done;
	}
	if (read (vm_server, buf, SZ_CMDBUF) <= 0) {
	    if (vm_debug)
		fprintf (stderr,
		    "vmclient (%s): server not responding\n", vm_client);
	    vm_shutdown();
	    status = DEF_ACCESSVAL;
	    goto done;
	}

	status = atoi (buf);
done:
	if (vm_debug)
	    fprintf (stderr, "vmclient (%s): access `%s' -> %d\n",
		vm_client, fname, status);

	return (status < 0 ? DEF_ACCESSVAL : status);
}
Exemplo n.º 9
0
int main(int ac, char** av)
{
	t_vm*		vm		= vm_initialize();
	t_process*	process = (t_process*) malloc(sizeof(t_process));
	int32		i;
	t_display*		display;
	int32			update_display = 0;
	int32			was_pressed = 0;
	t_ring_buffer*	ring_buffer;

	ring_buffer = ring_buffer_initialize(10, free);

	if (load_cores(vm, ac, av) <= 0)
		return -1;

	display = display_initialize(800, 600);
	vm_set_print_callback(vm, main_debug_print, ring_buffer);

	if (1)
	{
		while (vm->process_count && !display_should_exit(display))
		{
			vm->cycle_current++;
			update_display = 1;
			int process_count = vm->process_count;
			for (i = 0; i < process_count; ++i)
			{
				t_process* process = vm->processes[i];
				if (process->cycle_wait <= 0)
				{
					update_display = 0;

					vm_reset_process_io_op(process);
					if (process->current_opcode)
						vm_execute(vm, process);
					vm_get_opcode(vm, process);
				}
				else
					process->cycle_wait--;
			}

			if (vm->cycle_current > vm->cycle_to_die)
			{
				vm->cycle_current = 0;
				vm_kill_process_if_no_live(vm);
			}

			vm_clean_dead_process(vm);
//			update_display = 0;
			if (display_update_input(display) || update_display == 0)
			{
				display_print_ring_buffer(display, 0, 0, ring_buffer);
				display_step(vm, display);
			}

		}
	}
	else
	{
		int32 execute_one = 0;

		int32 current_keys_state[GLFW_KEY_LAST];
		int32 previous_keys_state[GLFW_KEY_LAST];

		memset(previous_keys_state, 0, GLFW_KEY_LAST * sizeof(int32));
		memset(current_keys_state, 0, GLFW_KEY_LAST * sizeof(int32));
		display_step(vm, display);
		while (vm->process_count && !display_should_exit(display))
		{
			int32 executed = 0;
			int32 print_processes;
			int32 process_count = 0;

			current_keys_state[GLFW_KEY_S] = display_key_pressed(display, GLFW_KEY_S);
			current_keys_state[GLFW_KEY_P] = display_key_pressed(display, GLFW_KEY_P);

			if (!execute_one)
				execute_one = previous_keys_state[GLFW_KEY_S] && !current_keys_state[GLFW_KEY_S];
			print_processes = previous_keys_state[GLFW_KEY_P] && !current_keys_state[GLFW_KEY_P];
			memcpy(previous_keys_state, current_keys_state, sizeof(int32) * GLFW_KEY_LAST);

			if (execute_one)
				vm->cycle_current++;
			for (i = 0; i < vm->process_count; ++i)
			{
				t_process* process = vm->processes[i];
				if (print_processes)
					vm_debug_print_process(vm, process);
				if (execute_one)
				{
					if (process->cycle_wait <= 0)
					{
						vm_reset_process_io_op(process);
						vm_execute(vm, process);
						vm_get_opcode(vm, process);
						executed++;
						if (vm->live_count >= NBR_LIVE)
						{
							vm->live_count = 0;
							vm->cycle_to_die -= vm->cycle_delta;
						}
					}
					process->cycle_wait--;
				}
			}
			if (executed)
				execute_one = 0;
			if (vm->cycle_current > vm->cycle_to_die)
			{
				vm->cycle_current = 0;
				vm_kill_process_if_no_live(vm);
			}
			vm_clean_dead_process(vm);
			executed += display_update_input(display);
			if (executed)
				display_step(vm, display);
			else
				glfwPollEvents();
		}
	}


	ring_buffer_destroy(ring_buffer);
	display_destroy(display);
	vm_destroy(vm);
}
Exemplo n.º 10
0
int main(int ac, char** av) {
	vm_t*					vm;
	display_gl_t*	display = NULL;
	int						bound;
	int						i;
	debugger_t*		debugger = NULL;

	vm = vm_initialize();

	if ( (parse_arguments(vm, ac, av) <= 0) || (check_core_endianess(vm) < 0)) {
		return -1;
	}

	bound = VM_MEMORY_SIZE / (vm->core_count - 1);
	for (i = 0; i < vm->core_count; ++i) {
		vm->cores[i]->bound.start = vm->cores[i]->start_address;
		vm->cores[i]->bound.size = bound;
	}

	memory_access_initialize(is_cpu_big_endian() != vm->big_endian);

#if defined(_DEBUG)
		vm->full_screen = 0;
#endif

#ifdef RENDER_GL
	display = display_gl_initialize(1980, 1080, vm->full_screen);
	if (vm->step != -1) {
		debugger = debugger_init(vm->dbg_same_window ? display_gl_get_window(display) : NULL);
	}
#endif

	while (vm->process_count && !display_gl_should_exit(display)) {
		int32 i;
		int update_display = 0;


		if (vm->cycle_barrier == vm->cycle_total) {
			for (i = 0; i < vm->core_count; ++i) {
				vm->cores[i]->bound.start = 0;
				vm->cores[i]->bound.size = vm->memory_size;
			}
		}

		if (vm->step != 0) {
			vm->cycle_current++;
			vm->cycle_total++;

			int32 process_count = vm->process_count;
			for (i = process_count; i > 0; --i) {
				process_t* process = vm->processes[i - 1];
				process->cycle_wait--;
				if (process->cycle_wait <= 0) {
					vm_reset_process_io_op(process);
					vm_execute(vm, process);
					update_display = 1;
					if (vm->step > 0 && (vm->step_process == NULL || vm->step_process == process) ) {
						vm->step --;
					}
				}
			}

			if (vm->cycle_current > vm->cycle_to_die) {
				vm->cycle_current = 0;
				vm_kill_process_if_no_live(vm);
				vm_clean_dead_process(vm);
			}
		} else {
			update_display = 1;
		}

	#ifdef RENDER_GL
		update_display |= display_gl_update_input(display);
		if (update_display)
		{
			float y = 1;
			y = display_gl_text(display, 0, y, 0xffffffff, "cycle to die   %d", vm->cycle_to_die);
			y = display_gl_text(display, 0, y, 0xffffffff, "live count     %d ", vm->live_count);
			y = display_gl_text(display, 0, y, 0xffffffff, "process count  %d ", vm->process_count);
			y = display_gl_text(display, 0, y, 0xffffffff, "cycle          %d ", vm->cycle_total);
			y = display_gl_text(display, 0, y, 0xffffffff, "barrier        %d ", vm->cycle_barrier);
			for (i = 0; i < vm->core_count; ++i) {
				core_t* core = vm->cores[i];
				char* name = core->header ? core->header->name : "Unknow";
				y = display_gl_text(display, 0, y, 0xffffffff, "%s %d", name, core->live_count);
			}
			display_gl_step(vm, display);
			display_gl_swap(display);
		}

		if (debugger && vm->step != 1) {
			debugger_render(debugger, vm);
		}
	#endif
	}

	print_winning_core(vm);
	if (debugger) {
		debugger_destroy(debugger);
	}
#ifdef RENDER_GL
	display_gl_destroy(display);
#endif
	vm_destroy(vm);
}
Exemplo n.º 11
0
Arquivo: vm.c Projeto: endeav0r/ravm
int main (int argc, char * argv[]) {
    char * filename = NULL;
    char * output_filename = NULL;
    int opt_god_mode = 0;
    int c;
    int memory_view_offset = VM_MEMORY_SIZE - 32;
    int memory_view_bytes  = 32;
    int print_info = 0;
    int step = 0;
    int error;
    struct _vm * vm;
    
    while ((c = getopt(argc, argv, "b:gi:m:o:sp")) != -1) {
        switch (c) {
            case 'b' :
                memory_view_bytes = strtoul(optarg, NULL, 16);
                break;
            case 'g' :
                opt_god_mode = 1;
                break;
            case 'i' :
                filename = optarg;
                break;
            case 'm' :
                memory_view_offset = strtoul(optarg, NULL, 16);
                break;
            case 'o' :
                output_filename = optarg;
                break;
            case 'p' :
                print_info = 1;
                break;
            case 's' :
                step = 1;
                print_info = 1;
                break;
            case '?' :
                if ((optopt == 'f') || (optopt == 'o')) {
                    fprintf(stderr, "option %c requires argument\n", optopt);
                    exit(0);
                }
                else {
                    fprintf(stderr, "Unknown option: %c\n", optopt);
                    exit(0);
                }
        }
    }
    
    if (filename == NULL) {
        fprintf(stderr, "Usage: %s [-ps] [-o output] -i image\n", argv[0]);
        fprintf(stderr, "Runs an assembled image for the rnp_vm\n");
        fprintf(stderr, "\n");
        fprintf(stderr, "  -b [hex]   BYTES of memory to view in debug output\n");
        fprintf(stderr, "  -g         god mode allows visualization of memory\n");
        fprintf(stderr, "  -i [path]  path to IMAGE\n");
        fprintf(stderr, "  -m [hex]   OFFSET in memory to view in debug output\n");
        fprintf(stderr, "  -o [path]  path to OUTPUT memory dump at HLT\n");
        fprintf(stderr, "  -p         PRINT info at each step\n");
        fprintf(stderr, "  -s         STEP through instruction (implies PRINT)\n");
        exit(0);
    }
    
    vm = (struct _vm *) malloc(sizeof(struct _vm));
    vm_initialize(vm);
    
    if ((error = image_load(vm, filename)) != 0) {
        fprintf(stderr, "error %d\n", error);
        exit(error);
    }
    
    if (opt_god_mode) {
        god_mode(vm);
    }
    else {    
        if (step | print_info)
            vm->step = 1;

        if (print_info) {
            debug_view_memory(vm,
                              memory_view_offset,
                              memory_view_bytes);
            debug_view_registers(vm);
            fflush(stdout);
            printf("%s\n", debug_instruction_description(&(vm->memory[vm->IP])));
            printf("\n");
        }

        while (vm_run(vm)) {
            if (print_info) {
                debug_view_memory(vm,
                                  memory_view_offset,
                                  memory_view_bytes);
                debug_view_registers(vm);
                fflush(stdout);
                printf("%s\n", debug_instruction_description(&(vm->memory[vm->IP])));
                printf("\n");
            }
            if (step) getc(stdin);
        }
    }
    
    if (output_filename != NULL) {
        if ((error = image_dump(vm, output_filename)) != 0) {
            fprintf(stderr, "error dumping memory to file: %d\n", error);
            exit(error);
        }
    }
    
    free(vm);
    
    return 0;
}