151 lines
4.2 KiB
C
151 lines
4.2 KiB
C
#include "VM/VM.h"
|
|
#include "instructions/instructions.h"
|
|
#include "collections/List.h"
|
|
#include "compiler/compiler.h"
|
|
|
|
#define arg_is(STR) (strcmp(argv[argi], STR) == 0)
|
|
|
|
i32 compileSources(cstr source_file, cstr out_file);
|
|
i32 bootFromImage(cstr image_file);
|
|
|
|
i32 main(const i32 argc, cstr* argv){
|
|
if(argc < 2){
|
|
printfe("ERROR: no arguments provided. Use --help to know more.\n");
|
|
return 1;
|
|
}
|
|
|
|
bool boot = false;
|
|
cstr NULLABLE(image_file) = NULL;
|
|
|
|
bool compile = false;
|
|
cstr NULLABLE(out_file) = NULL;
|
|
cstr NULLABLE(source_file) = NULL;
|
|
|
|
for(i32 argi = 1; argi < argc; argi++){
|
|
if(arg_is("-h") || arg_is("--help")){
|
|
printf(
|
|
"-h, --help Show this message.\n"
|
|
"-op, --opcodes Show list of all instructions.\n"
|
|
"-i, --image [FILE] Boot VM using image file.\n"
|
|
"-c, --compile [SOURCE_FILE] [OUT_FILE] Compile assembly source files to machine code.\n"
|
|
);
|
|
return 0;
|
|
}
|
|
else if(arg_is("-op") || arg_is("--opcodes")){
|
|
for(u8 opcode = 0; opcode < 255; opcode++){
|
|
const Instruction* instr = Instruction_getByOpcode(opcode);
|
|
if(instr != NULL){
|
|
printf("%02X %s\n", opcode, instr->name);
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
else if(arg_is("-i") || arg_is("--image")){
|
|
if(boot){
|
|
printfe("--image flag is set already\n");
|
|
return 1;
|
|
}
|
|
|
|
boot = true;
|
|
if(++argi >= argc){
|
|
printfe("ERROR: no image file specified\n");
|
|
return 1;
|
|
}
|
|
image_file = argv[argi];
|
|
}
|
|
else if(arg_is("-c") || arg_is("--compile")){
|
|
if(compile){
|
|
printfe("--compile flag is set already\n");
|
|
return 1;
|
|
}
|
|
|
|
compile = true;
|
|
if(++argi >= argc){
|
|
printfe("ERROR: no source file file specified\n");
|
|
return 1;
|
|
}
|
|
source_file = argv[argi];
|
|
|
|
if(++argi >= argc){
|
|
printfe("ERROR: no output file file specified\n");
|
|
return 1;
|
|
}
|
|
out_file = argv[argi];
|
|
}
|
|
else {
|
|
printfe("ERROR: unknown argument '%s'\n", argv[argi]);
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
i32 exit_code = 0;
|
|
if(compile){
|
|
exit_code = compileSources(source_file, out_file);
|
|
}
|
|
if(exit_code == 0 && boot){
|
|
exit_code = bootFromImage(image_file);
|
|
}
|
|
|
|
return exit_code;
|
|
}
|
|
|
|
i32 bootFromImage(cstr image_file){
|
|
FILE* file = fopen(image_file, "rb");
|
|
if(file == NULL){
|
|
printfe("ERROR: can't open file '%s'\n", image_file);
|
|
return 1;
|
|
}
|
|
|
|
const size_t buffer_size = 1024*1024;
|
|
u8* vm_memory = malloc(buffer_size);
|
|
memset(vm_memory, 0, buffer_size);
|
|
|
|
size_t bytes_read = fread(vm_memory, 1, buffer_size, file);
|
|
fclose(file);
|
|
if(bytes_read == (size_t)EOF){
|
|
printfe("ERROR: can't read file '%s'\n", image_file);
|
|
free(vm_memory);
|
|
return 1;
|
|
}
|
|
|
|
VM vm;
|
|
VM_init(&vm);
|
|
|
|
i32 exit_code = 1;
|
|
if(VM_setMemory(&vm, vm_memory, bytes_read)){
|
|
exit_code = VM_boot(&vm);
|
|
}
|
|
if(vm.state == VMState_InternalError){
|
|
if(vm.error_message){
|
|
printfe("VM ERROR: %s\n", vm.error_message);
|
|
free(vm.error_message);
|
|
}
|
|
else printfe("VM ERROR: unknown (error_message is null)\n");
|
|
}
|
|
|
|
if(exit_code != 0){
|
|
printfe("program exited with code %i\n", exit_code);
|
|
}
|
|
|
|
free(vm_memory);
|
|
return exit_code;
|
|
}
|
|
|
|
i32 compileSources(cstr source_file, cstr out_file){
|
|
Compiler cmp;
|
|
Compiler_init(&cmp);
|
|
bool success = Compiler_compile(&cmp, source_file, out_file, true);
|
|
if(!success){
|
|
if(cmp.error_message){
|
|
printfe("COMPILER ERROR: %s\n", cmp.error_message);
|
|
free(cmp.error_message);
|
|
}
|
|
else printfe("COMPILER ERROR: unknown (error_message is null)\n");
|
|
Compiler_free(&cmp);
|
|
return 111;
|
|
}
|
|
|
|
Compiler_free(&cmp);
|
|
return 0;
|
|
}
|