/** * Runs the instruction at the program counters position in memory. */ void vm_exec() { cycles++; Instruction* op = mem_load_instr(pcounter); print_instr(op); switch(op->op) { case OP_NAP: break; case OP_ADD: op_add(op); break; case OP_SUB: op_sub(op); break; case OP_EXP: op_exp(op); break; case OP_SIN: op_sin(op); break; case OP_COS: op_cos(op); break; case OP_TAN: op_tan(op); break; case OP_LW: op_lw(op); break; case OP_SW: op_sw(op); break; case OP_SB: op_sb(op); break; case OP_J: op_j(op); return; // Jump case OP_JR: op_jr(op); return; case OP_JAL: op_jal(op); return; case OP_JZ: op_jz(op); return; case OP_JNZ: op_jnz(op); return; case OP_JEQ: op_jeq(op); return; case OP_JNQ: op_jnq(op); return; case OP_PUSH: op_push(op); break; case OP_POP: op_pop(op); break; case OP_PRTI: op_prti(op); break; case OP_EXIT: vm_exit(op->k); return; /* Unsupported operation */ default: printf("Error: Invalid operation at %d\n", pcounter); print_instr(op); vm_exit(-1); return; } pcounter = pcounter + 8; }
int main(int argc, char* argv[]) { char* image = "image"; if (argc > 1) image = argv[1]; vm_init(); mop_add(0, 1, 0, 0, 10); // r1 = 10 mop_add(8, 2, 0, 0, 20); // r2 = 20 mop_push(16, 1); // push r1 mop_push(24, 2); // push r2 mop_add(32, 2, 0, 0, 0); // r2 = 0 mop_sub(40, 1, 1, 0, 1); // r1-- mop_prti(48, 1); // print r1 mop_jnz(64, 1, 32); mop_pop(72, 2); // pop r2 mop_pop(80, 1); // pop r1 mop_prti(88, 1); // print r1, should be 10 mop_prti(96, 2); // print r2 mop_exit(104); vm_run(0); vm_exit(); /* vm_init(); vm_load(image); vm_run(ENTRY_POINT); */ return exitval; }
void *vm_exit_message(struct context *context, const char *format, ...) { // make error variable va_list list; va_start(list, format); set_error(context, format, list); va_end(list); vm_exit(); return NULL; }
void vm_assert(struct context *context, bool assertion, const char *format, ...) { if (!assertion) { // make error variable va_list list; va_start(list, format); set_error(context, format, list); va_end(list); vm_exit(); } }
/** * Loads an image into virtual memory * Sets instruction pointer to ENTRY_POINT */ void vm_load(char* image) { printf("Loading image '%s'...\n", image); FILE *fp = fopen(image, "rb"); if (fp == NULL) { printf("Error reading image '%s'\n", image); vm_exit(-1); return; } fseek(fp, 0L, SEEK_END); dword imgsize = ftell(fp); fseek(fp, 0L, SEEK_SET); printf("IMAGE SIZE: %lu\n", imgsize); if (imgsize > (MEM_SIZE - ENTRY_POINT)) { printf("Error: Image size does not fit within allocated memory\n"); fclose(fp); vm_exit(-1); return; } size_t blocks_read = fread(memory + ENTRY_POINT, imgsize, 1, fp); if (blocks_read != 1) { printf("Error: Could not read image into memory\n"); fclose(fp); vm_exit(-1); return; } pcounter = ENTRY_POINT; // Set program counter to image entry point fclose(fp); }
/******************** * dres_exit ********************/ EXPORTED void dres_exit(dres_t *dres) { if (dres == NULL) return; dres_store_free(dres); if (DRES_TST_FLAG(dres, COMPILED)) free(dres); else { dres_free_targets(dres); dres_free_factvars(dres); dres_free_dresvars(dres); free_initializers(dres); vm_exit(&dres->vm); FREE(dres); } }