#pragma once #include #include "bsuml.h" #include #include #include #include namespace bio { namespace emu { using instruction_set = std::vector*, std::map*>>; memory_dependent using mem_buffer = unsigned char[memsize]; struct symbol { unsigned offset; }; struct application { std::vector symbols; // contents unsigned bufferLength; unsigned char* buffer; }; memory_dependent class emulator_base { public: instruction_set isa; mem_buffer memory; std::vector symbols; std::vector callStack; std::map registers; virtual void load_app(application& app) = 0; virtual bool run_symbol(int symbol) = 0; void clear_registers() { registers.clear(); } void clear_memory() { times(memsize) { memory[___i] = 0; } } }; memory_dependent class linear_emulator_base : public memory_passdown(emulator_base) { public: int instructionPointer; bool run_symbol(int symbol) { // check symbol ID is within symbol count if (symbol > this->symbols.size() && symbol != -1) throw std::out_of_range( std::format("Symbol is outside of the symbol range ({} > {}, described as a maximum of {})", symbol, this->symbols.size(), this->symbols.size() - 1 ) ); // check if symbol ID is erroneous if (symbol < -1) throw std::out_of_range( std::format("Symbol ID for entry at start is explicitly -1 (received {} instead)", symbol ) ); // apply instruction pointer if (symbol >= 0) instructionPointer = this->symbols[symbol].offset; else instructionPointer = 0; // execute bool returned = false; until(returned || instructionPointer >= memsize) { this->instructionPointer += this->isa[this->memory[instructionPointer]](instructionPointer, this->memory, &returned, &this->callStack, &this->registers); if (instructionPointer < 0 || instructionPointer > memsize) { throw std::out_of_range("Symbol causes instruction pointer to err out of memory"); } } if (returned) { std::print("Exited through conventional means [returned out of symbol]\n"); return true; } return false; } }; } }