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(); }
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 }
/* 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); }
/* * 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; }
/* * 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; }
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; }
/* 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); }
/* 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); }
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); }
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); }
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; }