153 lines
5.4 KiB
C
153 lines
5.4 KiB
C
#include "../../Headers/Sagittarius.h"
|
|
#include "../../Headers/SagittariusInternal.h"
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
SAGITTARIUS_API SagittariusVM* sagittarius_vm_new(uint64_t memory_size){
|
|
SagittariusVM* vm = malloc(sizeof(SagittariusVM));
|
|
if (!vm) return NULL;
|
|
|
|
vm->Memory.data = malloc(memory_size);
|
|
vm->Memory.size = memory_size;
|
|
|
|
// Clear registers
|
|
memset(vm->core.reg.head, 0, sizeof(vm->core.reg.head));
|
|
|
|
// Link core
|
|
vm->core.memory = &vm->Memory;
|
|
vm->core.vm = vm;
|
|
vm->core.pc = 0;
|
|
|
|
// Initialize syscalls
|
|
vm->SagittariusSyscallEntries = NULL;
|
|
vm->SagittariusSyscallCount = 0;
|
|
vm->SagittariusSyscallCapacity = 0;
|
|
|
|
vm->panic_handler = NULL;
|
|
|
|
return vm;
|
|
}
|
|
|
|
SAGITTARIUS_API void sagittarius_vm_free(SagittariusVM* vm){
|
|
if (vm) {
|
|
if (vm->Memory.data) free(vm->Memory.data);
|
|
if (vm->SagittariusSyscallEntries) free(vm->SagittariusSyscallEntries);
|
|
free(vm);
|
|
}
|
|
}
|
|
|
|
SAGITTARIUS_API void sagittarius_register_syscall(SagittariusVM *vm, uint64_t id, SagittariusSyscall syscall) {
|
|
if (!vm) return;
|
|
if (vm->SagittariusSyscallCount >= vm->SagittariusSyscallCapacity) {
|
|
vm->SagittariusSyscallCapacity = vm->SagittariusSyscallCapacity == 0 ? 4 : vm->SagittariusSyscallCapacity * 2;
|
|
vm->SagittariusSyscallEntries = realloc(vm->SagittariusSyscallEntries, vm->SagittariusSyscallCapacity * sizeof(SagittariusSyscallEntry));
|
|
}
|
|
vm->SagittariusSyscallEntries[vm->SagittariusSyscallCount].id = id;
|
|
vm->SagittariusSyscallEntries[vm->SagittariusSyscallCount].syscall = syscall;
|
|
vm->SagittariusSyscallCount++;
|
|
}
|
|
|
|
SAGITTARIUS_API void sagittarius_mem_resize(SagittariusVM* vm, uint64_t new_size){
|
|
if (vm) {
|
|
vm->Memory.data = realloc(vm->Memory.data, new_size);
|
|
vm->Memory.size = new_size;
|
|
}
|
|
}
|
|
|
|
SAGITTARIUS_API uint64_t sagittarius_mem_getsize(SagittariusVM* vm){
|
|
return vm ? vm->Memory.size : 0;
|
|
}
|
|
|
|
SAGITTARIUS_API void sagittarius_load_program_to_mem(SagittariusVM *vm, SagittariusProgram *program, uint64_t offset) {
|
|
if (!vm || !program) return;
|
|
|
|
uint64_t required_size = offset + program->instCount * 8 + program->data_size;
|
|
if (required_size > vm->Memory.size) {
|
|
sagittarius_mem_resize(vm, required_size);
|
|
}
|
|
|
|
if (program->instCount > 0) {
|
|
memcpy(vm->Memory.data + offset, program->instructions, program->instCount * 8);
|
|
}
|
|
if (program->data_size > 0) {
|
|
memcpy(vm->Memory.data + offset + program->instCount * 8, program->data, program->data_size);
|
|
}
|
|
|
|
vm->core.pc = offset;
|
|
}
|
|
|
|
SAGITTARIUS_API SagittariusProgram *sagittarius_load_program_from_byte_array(uint8_t *data, uint64_t size) {
|
|
if (size < 28) return NULL;
|
|
if (memcmp(data, SAGITTARUIS_PROGRAM_HEAD, 7) != 0) return NULL;
|
|
|
|
uint32_t version;
|
|
memcpy(&version, data + 8, 4);
|
|
if (version != SAGITTARIUS_PROGRAM_FORMAT_VERSION) return NULL;
|
|
|
|
uint64_t instCount;
|
|
memcpy(&instCount, data + 12, 8);
|
|
|
|
uint64_t data_size;
|
|
memcpy(&data_size, data + 20, 8);
|
|
|
|
if (size < 28 + instCount * 8 + data_size) return NULL;
|
|
|
|
SagittariusProgram *prog = malloc(sizeof(SagittariusProgram));
|
|
prog->instCount = instCount;
|
|
if (instCount > 0) {
|
|
prog->instructions = malloc(instCount * sizeof(SagittariusInst));
|
|
memcpy(prog->instructions, data + 28, instCount * 8);
|
|
} else {
|
|
prog->instructions = NULL;
|
|
}
|
|
|
|
prog->data_size = data_size;
|
|
if (data_size > 0) {
|
|
prog->data = malloc(data_size);
|
|
memcpy(prog->data, data + 28 + instCount * 8, data_size);
|
|
} else {
|
|
prog->data = NULL;
|
|
}
|
|
|
|
return prog;
|
|
}
|
|
|
|
SAGITTARIUS_API void sagittarius_step(SagittariusVM *vm) {
|
|
if (!vm) return;
|
|
if (vm->core.pc >= vm->Memory.size) {
|
|
if (vm->panic_handler) vm->panic_handler(&vm->core, Sagittarius_Msg_OOB, "PC out of bounds");
|
|
return;
|
|
}
|
|
|
|
SagittariusInst inst;
|
|
memcpy(&inst, &vm->Memory.data[vm->core.pc], sizeof(SagittariusInst));
|
|
|
|
uint8_t opcode = inst.data & 0xFF;
|
|
bool success = false;
|
|
|
|
switch ((SagittariusInstDef)opcode) {
|
|
case math2: success = Math2Op(&vm->core, inst); break;
|
|
case math1: success = Math1Op(&vm->core, inst); break;
|
|
case cvt: success = SagCvt(&vm->core, inst); break;
|
|
case set: success = SagSet(&vm->core, inst); break;
|
|
case mv: success = SagMv(&vm->core, inst); break;
|
|
case cp: success = SagCp(&vm->core, inst); break;
|
|
case save: success = SagSave(&vm->core, inst); break;
|
|
case load: success = SagLoad(&vm->core, inst); break;
|
|
case jmp: success = SagJmp(&vm->core, inst); break;
|
|
case jmp_if: success = SagJmpIf(&vm->core, inst); break;
|
|
case call: success = SagCall(&vm->core, inst); break;
|
|
case ret: success = SagRet(&vm->core, inst); break;
|
|
case cmp: success = SagCmp(&vm->core, inst); break;
|
|
case mathv: success = SagMathV(&vm->core, inst); break;
|
|
case halt: success = SagHalt(&vm->core, inst); break;
|
|
case syscall: success = SagSyscall(&vm->core, inst); break;
|
|
case tsyscall: success = SagTSyscall(&vm->core, inst); break;
|
|
default: {
|
|
if (vm->panic_handler) vm->panic_handler(&vm->core, Sagittarius_Msg_Unknown, "Unknown opcode");
|
|
break;
|
|
}
|
|
}
|
|
|
|
(void)success;
|
|
} |