Created
May 16, 2024 05:40
-
-
Save dmateos/00291b31885c5072c847c5cfffae9b4c to your computer and use it in GitHub Desktop.
tinyvm.c
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdbool.h> | |
#include <stdint.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <unistd.h> | |
#define PROGRAM_SIZE 1024 | |
enum INSTRUCTIONS { | |
ADD = 0x01, | |
SUB, | |
}; | |
typedef struct { | |
uint32_t *program_data; | |
uint32_t *ip; | |
uint32_t reg0; | |
} VM_T; | |
void assemble_file(const char *file) { | |
char opcode[32]; | |
int parameter; | |
FILE *fp, *new_fp; | |
uint32_t opcode_b; | |
bool write = false; | |
fp = fopen(file, "r"); | |
if (!fp) { | |
printf("could not open file %s\n", file); | |
return; | |
} | |
new_fp = fopen("output", "wb"); | |
if (!new_fp) { | |
printf("could not open file output\n"); | |
fclose(fp); | |
return; | |
} | |
while (fscanf(fp, "%s %d\n", opcode, ¶meter) != EOF) { | |
printf("opcode: %s, parameter: %d\n", opcode, parameter); | |
if (strcmp(opcode, "ADD") == 0) { | |
printf("ADD found\n"); | |
opcode_b = ADD; | |
write = true; | |
} else if (strcmp(opcode, "SUB") == 0) { | |
printf("SUB found\n"); | |
opcode_b = SUB; | |
write = true; | |
} else { | |
printf("unknown opcode\n"); | |
} | |
if (write) { | |
fwrite(&opcode_b, sizeof(uint32_t), 1, new_fp); | |
fwrite(¶meter, sizeof(uint32_t), 1, new_fp); | |
write = false; | |
} | |
} | |
fclose(fp); | |
fclose(new_fp); | |
} | |
void print_vm_state(VM_T *vm) { | |
printf("\nVM State:\n"); | |
printf("reg0: %d\n", vm->reg0); | |
printf("ip: %p\n", vm->ip); | |
printf("*ip: %d\n\n", *vm->ip); | |
return; | |
} | |
void run_vm(VM_T *vm) { | |
while (true) { | |
switch (*vm->ip) { | |
case ADD: | |
printf("found add!\n"); | |
vm->ip++; | |
printf("parameter: %d\n", *vm->ip); | |
vm->reg0 += *vm->ip; | |
vm->ip++; | |
print_vm_state(vm); | |
break; | |
case SUB: | |
printf("found sub!\n"); | |
vm->ip++; | |
printf("parameter: %d\n", *vm->ip); | |
vm->reg0 -= *vm->ip; | |
vm->ip++; | |
print_vm_state(vm); | |
break; | |
} | |
} | |
} | |
void init_vm(VM_T *vm, const char *file) { | |
FILE *fp = fopen(file, "rb"); | |
uint32_t length; | |
if (!fp) { | |
printf("could not open file %s\n", file); | |
return; | |
} | |
memset(vm, 0, sizeof(VM_T)); | |
vm->program_data = malloc(PROGRAM_SIZE * sizeof(uint32_t)); | |
memset(vm->program_data, 0, PROGRAM_SIZE * sizeof(uint32_t)); | |
vm->ip = vm->program_data; | |
fseek(fp, 0, SEEK_END); | |
length = ftell(fp); | |
fseek(fp, 0, SEEK_SET); | |
fread(vm->program_data, sizeof(uint32_t), length / sizeof(uint32_t), fp); | |
fclose(fp); | |
} | |
void free_vm(VM_T *vm) { | |
free(vm->program_data); | |
return; | |
} | |
int main() { | |
VM_T vm; | |
assemble_file("test.s"); | |
init_vm(&vm, "output"); | |
print_vm_state(&vm); | |
run_vm(&vm); | |
free_vm(&vm); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment