umx

UMX VM implementation (ifcfc '06)
git clone git://bsandro.tech/umx
Log | Files | Refs

commit 1ca2c2fcdc0645612f90f8a0e6a152ab9ac110dc
parent 05ba1a534e7081c3aaed75570bf6715175db2108
Author: bsandro <brian.drosan@gmail.com>
Date:   Mon, 10 Jan 2022 00:23:34 +0200

rest of the opcodes

Diffstat:
Mmain.c | 74+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------
1 file changed, 63 insertions(+), 11 deletions(-)

diff --git a/main.c b/main.c @@ -4,9 +4,10 @@ #include <assert.h> #include <stdint.h> #include <stdlib.h> +#include <string.h> #include <sys/stat.h> -#define FILENAME "um.um" +#define FILENAME "sandmark.umz" #define PLATTER_SIZE 4 struct array_t { @@ -22,6 +23,7 @@ struct arena_t { struct state_t { struct arena_t arena; uint32_t registers[8]; + uint32_t finger; }; enum opcode_t { @@ -50,22 +52,26 @@ struct instruction_t { char * int2bin(uint32_t num); void print_instruction(struct instruction_t instruction); void exec_instruction(struct state_t *state, struct instruction_t in); -uint32_t array_add(struct arena_t *arena, uint32_t size); +uint32_t array_new(struct arena_t *arena, uint32_t size); +void array_free(struct arena_t *arena, uint32_t index); +void array_dup(struct arena_t *arena, uint32_t index); int main(void) { FILE *f = fopen(FILENAME, "r"); - uint32_t finger = 0; + struct state_t state = {0}; struct stat fileinfo; size_t read_platters = 0; - struct state_t state = {0}; + + state.finger = 0; state.arena.arrays = NULL; state.arena.size = 0; + assert(f != NULL); stat(FILENAME, &fileinfo); assert(fileinfo.st_size % PLATTER_SIZE == 0); printf("%s (%lu bytes):\n", FILENAME, fileinfo.st_size); - array_add(&state.arena, fileinfo.st_size); // Initial array #0 + array_new(&state.arena, fileinfo.st_size / PLATTER_SIZE); // Initial array #0 read_platters = fread(state.arena.arrays[0].data, PLATTER_SIZE, fileinfo.st_size / PLATTER_SIZE, f); assert(fileinfo.st_size == read_platters * PLATTER_SIZE); printf("read ok, %lu platters (%lu bytes)\n", read_platters, state.arena.arrays[0].size); @@ -73,7 +79,7 @@ int main(void) while (1) { uint32_t platter; struct instruction_t instruction = {0}; - platter = state.arena.arrays[0].data[finger]; + platter = state.arena.arrays[0].data[state.finger]; instruction.opcode = platter >> 28; if (instruction.opcode == ORTH) { instruction.reg_a = ((platter >> 25) & 7); @@ -84,9 +90,9 @@ int main(void) instruction.reg_c = platter & 7; // mask 000 000 111 = 7 } //print_instruction(instruction); + state.finger++; exec_instruction(&state, instruction); - finger++; - if (finger >= state.arena.arrays[0].size / PLATTER_SIZE) { + if (state.finger >= state.arena.arrays[0].size / PLATTER_SIZE) { break; } } @@ -135,15 +141,61 @@ void exec_instruction(struct state_t *state, struct instruction_t in) { case NOTA: state->registers[in.reg_a] = ~(state->registers[in.reg_b] & state->registers[in.reg_c]); break; + case HALT: + printf("HALT\n"); + exit(0); + break; + case ALLO: + state->registers[in.reg_b] = array_new(&state->arena, state->registers[in.reg_c]); + break; + case ABAN: + array_free(&state->arena, state->registers[in.reg_c]); + break; + case OUTP: + putchar(state->registers[in.reg_c]); + break; + case INP: + { + int c = getchar(); + state->registers[in.reg_c] = (c == EOF) ? 0xFFFFFFFF : c; + } + break; + case LOAD: + { + array_dup(&state->arena, state->registers[in.reg_b]); + state->finger = state->registers[in.reg_c]; + } + break; + case ORTH: + state->registers[in.reg_a] = in.value; + break; + default: + printf("invalid opcode\n"); + exit(1); } } -uint32_t array_add(struct arena_t *arena, uint32_t size) { +uint32_t array_new(struct arena_t *arena, uint32_t size) { uint32_t array_index = arena->size++; - assert(size != NULL); + assert(arena != NULL); + assert(size != 0); arena->arrays = (struct array_t *)realloc(arena->arrays, arena->size * sizeof(struct array_t)); - arena->arrays[array_index].data = (uint32_t *)malloc(size); + arena->arrays[array_index].data = (uint32_t *)calloc(size, PLATTER_SIZE); arena->arrays[array_index].size = size; assert(arena->arrays[array_index].data != NULL); return array_index; +} + +void array_free(struct arena_t *arena, uint32_t index) { + assert(index < arena->size); + free(arena->arrays[index].data); + arena->arrays[index].size = 0; +} + +void array_dup(struct arena_t *arena, uint32_t index) { + assert(index < arena->size); + array_free(arena, 0); + arena->arrays[0].data = (uint32_t *)malloc(arena->arrays[index].size * PLATTER_SIZE); + memcpy(arena->arrays[0].data, arena->arrays[index].data, arena->arrays[index].size * PLATTER_SIZE); + arena->arrays[0].size = arena->arrays[index].size; } \ No newline at end of file