LIVM/livm.c
2022-04-16 01:22:30 +10:00

174 lines
No EOL
3.6 KiB
C

/*
(C) M. Ærþ.
*/
struct VMinst;
struct IODevice;
struct IODevice { // input/output device
void* buffer;
void (*write)(struct VMinst* vm, void* data, uint64_t length);
void (*out)(struct VMinst* vm);
void (*read)(struct VMinst* vm, void* buffer, uint64_t length, uint64_t where);
void (*wait)(struct VMinst* vm, uint64_t data);
void (*poweroff)(struct VMinst* vm);
};
struct VMinst {
void* ram;
void* raw_ram;
uint64_t ram_size;
uint64_t ip;
uint64_t sp;
uint64_t dp;
struct IODevice* devices;
};
char* dev_rom[] = {"sda"};
#ifndef DEV_ROM_COUNT
# define DEV_ROM_COUNT 1
#endif
#ifdef LIVMDEBUG
# define LIVMCREATION printf("LIVM instance [%p] created.\n", &vm);
# define LIVMSTARTWORK printf("LIVM instance [%p] started.\n", vm)
# define LIVMENDWORK printf("LIVM instance [%p] ended it's work.\n", vm)
# define LIVMDELETING printf("LIVM instance [%p] was deleted.\n", &vm)
# define LIVMARGOVERFLOW { printf("ERROR: arg overflow at [ip=%ld, op=%ld]\n", ip, op); continue; }
#else
# define LIVMCREATION
# define LIVMSTARTWORK
# define LIVMENDWORK
# define LIVMDELETING
# define LIVMARGOVERFLOW continue;
#endif
#include "devices.c"
struct VMinst createVM(uint64_t ram_size) {
struct VMinst vm;
vm.ip = 0;
vm.sp = 0;
vm.dp = 0;
vm.raw_ram = malloc(ram_size);
vm.ram = vm.raw_ram;
vm.ram_size = ram_size;
if (vm.ram == NULL) exit(-1);
LIVMCREATION
dev_init(&vm);
return vm;
}
struct VMinst* loadRAM(struct VMinst* vm, uint64_t* RAM, uint64_t length) {
for (uint64_t i = 0; i < length; ++i) ((uint64_t*)vm->raw_ram)[i] = RAM[i];
return vm;
}
struct VMinst* deleteVM(struct VMinst* vm) {
LIVMDELETING;
free(vm->raw_ram);
dev_delete(vm);
return vm;
}
void print_ullram(struct VMinst* vm) {
for (uint64_t i = 0; i < vm->ram_size / 8; i++)
printf("%p\t|\t%lu\n", ((uint64_t*)vm->ram)+i, ((uint64_t*)vm->raw_ram)[i]);
printf("\n");
}
struct VMinst* runVM(struct VMinst* vm) {
LIVMSTARTWORK;
register uint64_t ip = vm->ip,
sp = vm->sp,
dp = vm->dp;
void* raw_ram = vm->raw_ram;
void* ram = vm->ram;
register uint64_t op = 0;
register uint8_t cmp = 0;
register uint8_t argc = 0;
register uint8_t cargc = 0;
uint64_t args[8];
#define code_ram ((uint64_t*)raw_ram)
#define uram64 ((uint64_t*)ram)
#define ram64 ((int64_t*)ram)
#define ramd ((double*)ram)
#define uram32 ((uint32_t*)ram)
#define ram32 ((int32_t*)ram)
#define ramf ((float*)ram)
#define uram16 ((uint16_t*)ram)
#define ram16 ((int16_t*)ram)
#define uram8 ((uint8_t*)ram)
#define ram8 ((int8_t*)ram)
struct IODevice* devices = vm->devices;
while (1) {
#ifdef LLLIVMDEBUG
printf("%ld\t|\t", ip);
printf("%ld <- %ld -> %ld\t", code_ram[ip - 1], code_ram[ip], code_ram[ip + 1]);
#endif
op = code_ram[ip++];
argc = code_ram[ip++];
#ifdef LLLIVMDEBUG
printf("c=%d\t[", argc);
#endif
cargc = 0;
if (argc > 8) LIVMARGOVERFLOW;
while(cargc < argc)
args[cargc++] = code_ram[ip++];
#ifdef LLLIVMDEBUG
for (register uint8_t x = 0; x < (argc - 1); x++)
printf("%ld, ", args[x]);
if (argc == 0) printf("]\t");
else printf("%ld]\t", args[argc - 1]);
printf("|\t%lld\n", dp);
#endif
switch (op) {
#include "xcase.c"
}
#ifdef LLLIVMDEBUG
if (getchar() == 'x') {
print_ullram(vm);
getchar();
};
#endif
}
end: LIVMENDWORK;
#undef code_ram
#undef uram64
#undef ram64
#undef ramd
#undef uram32
#undef ram32
#undef ramf
#undef uram16p
#undef ram16
#undef uram8
#undef ram8
vm->ip = ip;
vm->sp = sp;
vm->dp = dp;
vm->ram = ram;
return vm;
}
# undef LIVMCREATION
# undef LIVMSTARTWORK
# undef LIVMENDWORK
# undef LIVMDELETING
# undef LIVMARGOVERFLOW