/* Copyright (C) 2016 Jeremiah Orians * This file is part of stage0. * * stage0 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 3 of the License, or * (at your option) any later version. * * stage0 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 stage0. If not, see . */ #include "vm.h" #define DEBUG true extern uint32_t performance_counter; static struct lilith* Globalvm; void unpack_byte(uint8_t a, char* c); /* Load program tape into Memory */ size_t load_program(struct lilith* vm, char* name) { FILE* program; program = fopen(name, "r"); /* Figure out how much we need to load */ fseek(program, 0, SEEK_END); size_t end = ftell(program); rewind(program); /* Load the entire tape into memory */ fread(vm->memory, 1, end, program); fclose(program); return end; } void execute_vm(struct lilith* vm) { struct Instruction* current; current = calloc(1, sizeof(struct Instruction)); read_instruction(vm, current); eval_instruction(vm, current); free(current); return; } void initialize_lilith(unsigned int size, unsigned int posix) { POSIX_MODE = posix; tape_01_name = "tape_01"; tape_02_name = "tape_02"; struct lilith* vm; vm = create_vm(size); Globalvm = vm; } void load_lilith(char* name) { load_program(Globalvm, name); } unsigned int step_lilith() { if(!Globalvm->halted) { execute_vm(Globalvm); } return Globalvm->ip; } unsigned int get_register(unsigned int reg) { unsigned int i; switch(reg) { case 0 ... 15: { i = Globalvm->reg[reg]; break; } case 16: /* Get PC */ { i = Globalvm->ip; break; } case 17: /* Instruction count */ { i = performance_counter; break; } default: { fprintf(stderr, "What have you done????\n"); exit(EXIT_FAILURE); } } return i; } void set_register(unsigned int reg, unsigned int value) { switch(reg) { case 0 ... 15: { Globalvm->reg[reg] = value; break; } case 16: /* Set PC */ { Globalvm->ip = value; break; } case 17: /* No one mess with the Instruction count */ { fprintf(stderr, "Don't be a moron!!!!\n"); break; } default: { fprintf(stderr, "What are you trying to do????\n"); exit(EXIT_FAILURE); } } } void set_memory(unsigned int address, unsigned char value) { outside_of_world(Globalvm, address, "Address outside of World"); Globalvm->memory[address] = value; } unsigned char get_byte(unsigned int add) { outside_of_world(Globalvm, add, "Address outside of World"); return Globalvm->memory[add]; } void insert_address(char* p, uint32_t value) { char* segment; segment = p; unpack_byte((value >> 24), segment); segment = segment + 2; unpack_byte((value >> 16)%256, segment); segment = segment + 2; unpack_byte((value >> 8)%256, segment); segment = segment + 2; unpack_byte((value%256), segment); } void process_Memory_Row(char* p, uint32_t addr) { char* segment = p; strncpy(segment, "\n", 9); segment = segment + 9; insert_address(segment, addr); segment = segment + 8; strncpy(segment, "", 5); segment = segment + 5; int i; for(i = 0; i < 16; i = i + 1) { strncpy(segment, "", 4); segment = segment + 4; unpack_byte(Globalvm->memory[i + addr], segment); segment = segment + 2; strncpy(segment, "", 5); segment = segment + 5; } strncpy(segment, "\n\n", 7); } char* get_memory(unsigned int start) { char* result = calloc(4096 * 205 + 1, sizeof(char)); int i, point; point = 0; for(i = 0; i < 4096; i = i + 16) { process_Memory_Row(result + point, start + i); point = point + 205; } return result; }