96 lines
2.4 KiB
C++
96 lines
2.4 KiB
C++
#pragma once
|
|
#include <vector>
|
|
#include "bsuml.h"
|
|
#include <stdexcept>
|
|
#include <format>
|
|
#include <map>
|
|
#include <print>
|
|
|
|
namespace bio {
|
|
namespace emu {
|
|
|
|
using instruction_set = std::vector<native_callable<int, int, unsigned char*, bool*, std::vector<int>*, std::map<std::string, unsigned long long>*>>;
|
|
|
|
memory_dependent using mem_buffer = unsigned char[memsize];
|
|
|
|
struct symbol {
|
|
unsigned offset;
|
|
};
|
|
|
|
struct application {
|
|
|
|
std::vector<symbol> symbols;
|
|
|
|
// contents
|
|
unsigned bufferLength;
|
|
unsigned char* buffer;
|
|
|
|
};
|
|
|
|
memory_dependent class emulator_base {
|
|
public:
|
|
|
|
instruction_set isa;
|
|
mem_buffer<memsize> memory;
|
|
std::vector<symbol> symbols;
|
|
std::vector<int> callStack;
|
|
std::map<std::string, unsigned long long> 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;
|
|
}
|
|
};
|
|
|
|
}
|
|
} |