From 838f3800cb62f57cf5d3a5f8a3408b2f1eea8255 Mon Sep 17 00:00:00 2001 From: zongor Date: Sat, 14 Jun 2025 11:30:27 -0400 Subject: [PATCH] refactor to step intead of loop --- src/main.c | 33 ++-- src/vm.c | 447 ++++++++++++++++++++++++++--------------------------- src/vm.h | 2 +- 3 files changed, 242 insertions(+), 240 deletions(-) diff --git a/src/main.c b/src/main.c index 751c876..eb64e54 100644 --- a/src/main.c +++ b/src/main.c @@ -1,13 +1,24 @@ -#include "vm.h" #include "debug.h" +#include "vm.h" /* #define MEMORY_SIZE 65536 /\* 64KB memory (adjustable) *\/ */ #define MEMORY_SIZE 1024 +void run_vm(Data *memory, uint32_t memory_size) { + uint32_t pc = 1; /* Program counter */ + while (pc) { + pc = step_vm(memory, memory_size, pc); + } +} + int main() { Data memory[MEMORY_SIZE] = {0}; /* Memory array */ - int i = 0; + int i = 1; + memory[0].c[0] = 'z'; + memory[0].c[1] = '0'; + memory[0].c[2] = '0'; + memory[0].c[3] = '0'; memory[i++].u = OP_ADD_REAL; memory[i++].u = 102; memory[i++].u = 103; @@ -19,27 +30,27 @@ int main() { memory[i++].u = OP_JGT_INT; memory[i++].u = 100; memory[i++].u = 99; - memory[i++].u = 0; + memory[i++].u = 1; memory[i++].u = OP_REAL_TO_INT; memory[i++].u = 103; - memory[i++].u = 0; + memory[i++].u = 1; memory[i++].u = 103; memory[i++].u = OP_INT_TO_STRING; memory[i++].u = 103; - memory[i++].u = 0; + memory[i++].u = 1; memory[i++].u = 104; memory[i++].u = OP_PRINT_STRING; memory[i++].u = 105; - memory[i++].u = 0; - memory[i++].u = 0; + memory[i++].u = 1; + memory[i++].u = 1; memory[i++].u = OP_READ_STRING; - memory[i++].u = 0; - memory[i++].u = 0; + memory[i++].u = 1; + memory[i++].u = 1; memory[i++].u = 109; memory[i++].u = OP_PRINT_STRING; memory[i++].u = 110; - memory[i++].u = 0; - memory[i++].u = 0; + memory[i++].u = 1; + memory[i++].u = 1; memory[i++].u = OP_HALT; memory[i++].u = 0; memory[i++].u = 0; diff --git a/src/vm.c b/src/vm.c index da2b387..381c762 100644 --- a/src/vm.c +++ b/src/vm.c @@ -6,239 +6,230 @@ * String copy in data memory. */ void mem_strcpy(Data *memory, const char *str, uint32_t length, - uint32_t dest_addr) { + uint32_t dest_addr) { memory[dest_addr].u = length; uint32_t buffer_addr = dest_addr + 1; - uint32_t i = 0; - while (i < length) { - char ch = str[i]; - if (ch == '\0') { - break; - } - memory[buffer_addr + (i / 4)].c[i % 4] = ch; - i++; + uint32_t i; + for (i = 0; i < length; i++) { + memory[buffer_addr + (i / 4)].c[i % 4] = str[i]; } } -void run_vm(Data *memory, uint32_t memory_size) { - uint32_t pc = 0; /* Program counter */ +/** + * Step to the next opcode in the vm. + */ +uint32_t step_vm(Data *memory, uint32_t memory_size, uint32_t pc) { + Opcode opcode = memory[pc].u; + uint32_t src1_addr = memory[pc + 1].u; + uint32_t src2_addr = memory[pc + 2].u; + uint32_t dest_addr = memory[pc + 3].u; + pc += 4; /* Advance to next instruction */ - while (pc < memory_size - 4) { - - Opcode opcode = memory[pc].u; - uint32_t src1_addr = memory[pc + 1].u; - uint32_t src2_addr = memory[pc + 2].u; - uint32_t dest_addr = memory[pc + 3].u; - pc += 4; /* Advance to next instruction */ - - if (src1_addr >= memory_size || src2_addr >= memory_size || - dest_addr >= memory_size) { - printf("Invalid memory address!\n"); - exit(1); - } - - switch (opcode) { - case OP_HALT: - return; - case OP_ADD: - memory[dest_addr].u = memory[src1_addr].u + memory[src2_addr].u; - break; - - case OP_SUB: - memory[dest_addr].u = memory[src1_addr].u - memory[src2_addr].u; - break; - - case OP_MUL: - memory[dest_addr].u = memory[src1_addr].u * memory[src2_addr].u; - break; - - case OP_DIV: - memory[dest_addr].u = memory[src1_addr].u / memory[src2_addr].u; - break; - - case OP_ADD_REAL: - memory[dest_addr].f = memory[src1_addr].f + memory[src2_addr].f; - break; - - case OP_SUB_REAL: - memory[dest_addr].f = memory[src1_addr].f - memory[src2_addr].f; - break; - - case OP_MUL_REAL: - memory[dest_addr].f = memory[src1_addr].f * memory[src2_addr].f; - break; - - case OP_DIV_REAL: - if (memory[src2_addr].f == 0.0f) { - printf("Division by zero error at address %d\n", pc - 4); - exit(1); - } - memory[dest_addr].f = memory[src1_addr].f / memory[src2_addr].f; - break; - case OP_REAL_TO_INT: { - memory[dest_addr].u = (uint32_t)memory[src1_addr].f; - break; - } - case OP_INT_TO_REAL: { - memory[dest_addr].f = (float)memory[src1_addr].u; - break; - } - case OP_MOV: - memory[dest_addr] = memory[src1_addr]; - break; - case OP_JMP: - pc = src1_addr; /* Jump to address */ - break; - case OP_JGT_INT: { - uint32_t value = memory[src1_addr].u; - uint32_t value2 = memory[src2_addr].u; - uint32_t jump_target = dest_addr; - - pc = (value > value2) ? jump_target : pc; - break; - } - case OP_JLT_INT: { - uint32_t value = memory[src1_addr].u; - uint32_t value2 = memory[src2_addr].u; - uint32_t jump_target = dest_addr; - - pc = (value < value2) ? jump_target : pc; - break; - } - case OP_JEQ_REAL: { - float value = memory[src1_addr].f; - float value2 = memory[src2_addr].f; - uint32_t jump_target = dest_addr; - - pc = (value == value2) ? jump_target : pc; - break; - } - case OP_JGT_REAL: { - float value = memory[src1_addr].f; - float value2 = memory[src2_addr].f; - uint32_t jump_target = dest_addr; - - pc = (value > value2) ? jump_target : pc; - break; - } - case OP_JLT_REAL: { - float value = memory[src1_addr].f; - float value2 = memory[src2_addr].f; - uint32_t jump_target = dest_addr; - - pc = (value < value2) ? jump_target : pc; - break; - } - case OP_JEQ_INT: { - uint32_t value = memory[src1_addr].u; - uint32_t value2 = memory[src2_addr].u; - uint32_t jump_target = dest_addr; - - pc = (value == value2) ? jump_target : pc; - break; - } - case OP_JGE_INT: { - uint32_t value = memory[src1_addr].u; - uint32_t value2 = memory[src2_addr].u; - uint32_t jump_target = dest_addr; - - pc = (value >= value2) ? jump_target : pc; - break; - } - case OP_JLE_INT: { - uint32_t value = memory[src1_addr].u; - uint32_t value2 = memory[src2_addr].u; - uint32_t jump_target = dest_addr; - - pc = (value <= value2) ? jump_target : pc; - break; - } - case OP_JGE_REAL: { - float value = memory[src1_addr].f; - float value2 = memory[src2_addr].f; - uint32_t jump_target = dest_addr; - - pc = (value >= value2) ? jump_target : pc; - break; - } - case OP_JLE_REAL: { - float value = memory[src1_addr].f; - float value2 = memory[src2_addr].f; - uint32_t jump_target = dest_addr; - - pc = (value <= value2) ? jump_target : pc; - break; - } - case OP_INT_TO_STRING: { - int32_t a = (int32_t)memory[src1_addr].u; - char buffer[32]; - sprintf(buffer, "%d", a); - mem_strcpy(memory, buffer, strlen(buffer), dest_addr); - break; - } - case OP_REAL_TO_STRING: { - float a = memory[src1_addr].f; - char buffer[32]; - sprintf(buffer, "%f", a); - mem_strcpy(memory, buffer, strlen(buffer), dest_addr); - break; - } - case OP_READ_STRING: { - uint32_t buffer_addr = dest_addr + 1; - uint32_t length = 0; - while (1) { - int ch = getchar(); - if (ch == '\n' || ch == EOF) { - memory[buffer_addr + (length / 4)].c[length % 4] = '\0'; - break; - } - memory[buffer_addr + (length / 4)].c[length % 4] = ch; - length++; - } - memory[dest_addr].u = length; - break; - } - case OP_PRINT_STRING: { - uint32_t string_addr = src1_addr; - uint32_t length = memory[src1_addr - 1].u; - uint32_t i; - for (i = 0; i < length; i++) { - uint8_t ch = memory[string_addr + (i / 4)].c[i % 4]; - if (ch == '\0') - break; - putchar(ch); - } - putchar('\n'); - break; - } - case OP_CMP_STRING: { - uint32_t addr1 = src1_addr; - uint32_t addr2 = src2_addr; - uint32_t length1 = memory[src1_addr - 1].u; - uint32_t length2 = memory[src2_addr - 1].u; - uint32_t equal = 1; - - if (length1 != length2) { - equal = 0; - } else { - uint32_t i = 0; - while (i < length1) { - uint32_t char1 = memory[addr1 + i].u; - uint32_t char2 = memory[addr2 + i].u; - if (char1 != char2) { - equal = 0; - break; - } - if ((char1 & 0xFF) == '\0' && (char2 & 0xFF) == '\0') - break; - } - } - memory[dest_addr].u = equal; - break; - } - default: - printf("Unknown opcode: %d\n", opcode); - return; - } + if (src1_addr >= memory_size || src2_addr >= memory_size || + dest_addr >= memory_size) { + printf("Invalid memory address!\n"); + return 0; } + + switch (opcode) { + case OP_HALT: + return 0; + case OP_ADD: + memory[dest_addr].u = memory[src1_addr].u + memory[src2_addr].u; + return pc; + + case OP_SUB: + memory[dest_addr].u = memory[src1_addr].u - memory[src2_addr].u; + return pc; + + case OP_MUL: + memory[dest_addr].u = memory[src1_addr].u * memory[src2_addr].u; + return pc; + + case OP_DIV: + memory[dest_addr].u = memory[src1_addr].u / memory[src2_addr].u; + return pc; + + case OP_ADD_REAL: + memory[dest_addr].f = memory[src1_addr].f + memory[src2_addr].f; + return pc; + + case OP_SUB_REAL: + memory[dest_addr].f = memory[src1_addr].f - memory[src2_addr].f; + return pc; + + case OP_MUL_REAL: + memory[dest_addr].f = memory[src1_addr].f * memory[src2_addr].f; + return pc; + + case OP_DIV_REAL: + if (memory[src2_addr].f == 0.0f) { + printf("Division by zero error at address %d\n", pc - 4); + return 0; + } + memory[dest_addr].f = memory[src1_addr].f / memory[src2_addr].f; + return pc; + case OP_REAL_TO_INT: { + memory[dest_addr].u = (uint32_t)memory[src1_addr].f; + return pc; + } + case OP_INT_TO_REAL: { + memory[dest_addr].f = (float)memory[src1_addr].u; + return pc; + } + case OP_MOV: + memory[dest_addr] = memory[src1_addr]; + return pc; + case OP_JMP: + pc = src1_addr; /* Jump to address */ + return pc; + case OP_JEQ_INT: { + uint32_t value = memory[src1_addr].u; + uint32_t value2 = memory[src2_addr].u; + uint32_t jump_target = dest_addr; + + pc = (value == value2) ? jump_target : pc; + return pc; + } + case OP_JGT_INT: { + uint32_t value = memory[src1_addr].u; + uint32_t value2 = memory[src2_addr].u; + uint32_t jump_target = dest_addr; + + pc = (value > value2) ? jump_target : pc; + return pc; + } + case OP_JLT_INT: { + uint32_t value = memory[src1_addr].u; + uint32_t value2 = memory[src2_addr].u; + uint32_t jump_target = dest_addr; + + pc = (value < value2) ? jump_target : pc; + return pc; + } + case OP_JLE_INT: { + uint32_t value = memory[src1_addr].u; + uint32_t value2 = memory[src2_addr].u; + uint32_t jump_target = dest_addr; + + pc = (value <= value2) ? jump_target : pc; + return pc; + } + case OP_JGE_INT: { + uint32_t value = memory[src1_addr].u; + uint32_t value2 = memory[src2_addr].u; + uint32_t jump_target = dest_addr; + + pc = (value >= value2) ? jump_target : pc; + return pc; + } + case OP_JEQ_REAL: { + float value = memory[src1_addr].f; + float value2 = memory[src2_addr].f; + uint32_t jump_target = dest_addr; + + pc = (value == value2) ? jump_target : pc; + return pc; + } + case OP_JGT_REAL: { + float value = memory[src1_addr].f; + float value2 = memory[src2_addr].f; + uint32_t jump_target = dest_addr; + + pc = (value > value2) ? jump_target : pc; + return pc; + } + case OP_JLT_REAL: { + float value = memory[src1_addr].f; + float value2 = memory[src2_addr].f; + uint32_t jump_target = dest_addr; + + pc = (value < value2) ? jump_target : pc; + return pc; + } + case OP_JGE_REAL: { + float value = memory[src1_addr].f; + float value2 = memory[src2_addr].f; + uint32_t jump_target = dest_addr; + + pc = (value >= value2) ? jump_target : pc; + return pc; + } + case OP_JLE_REAL: { + float value = memory[src1_addr].f; + float value2 = memory[src2_addr].f; + uint32_t jump_target = dest_addr; + + pc = (value <= value2) ? jump_target : pc; + return pc; + } + case OP_INT_TO_STRING: { + int32_t a = (int32_t)memory[src1_addr].u; + char buffer[32]; + sprintf(buffer, "%d", a); + mem_strcpy(memory, buffer, strlen(buffer), dest_addr); + return pc; + } + case OP_REAL_TO_STRING: { + float a = memory[src1_addr].f; + char buffer[32]; + sprintf(buffer, "%f", a); + mem_strcpy(memory, buffer, strlen(buffer), dest_addr); + return pc; + } + case OP_READ_STRING: { + uint32_t buffer_addr = dest_addr + 1; + uint32_t length = 0; + while (1) { + int ch = getchar(); + if (ch == '\n' || ch == EOF) { + memory[buffer_addr + (length / 4)].c[length % 4] = '\0'; + break; + } + memory[buffer_addr + (length / 4)].c[length % 4] = ch; + length++; + } + memory[dest_addr].u = length; + return pc; + } + case OP_PRINT_STRING: { + uint32_t string_addr = src1_addr; + uint32_t length = memory[src1_addr - 1].u; + uint32_t i; + for (i = 0; i < length; i++) { + uint8_t ch = memory[string_addr + (i / 4)].c[i % 4]; + if (ch == '\0') + break; + putchar(ch); + } + putchar('\n'); + return pc; + } + case OP_CMP_STRING: { + uint32_t addr1 = src1_addr; + uint32_t addr2 = src2_addr; + uint32_t length1 = memory[src1_addr - 1].u; + uint32_t length2 = memory[src2_addr - 1].u; + uint32_t equal = 1; + + if (length1 != length2) { + equal = 0; + } else { + uint32_t i = 0; + while (i < length1) { + uint32_t char1 = memory[addr1 + i].u; + uint32_t char2 = memory[addr2 + i].u; + if (char1 != char2) { + equal = 0; + break; + } + if ((char1 & 0xFF) == '\0' && (char2 & 0xFF) == '\0') + return pc; + } + } + memory[dest_addr].u = equal; + return pc; + } + } + return 0; } diff --git a/src/vm.h b/src/vm.h index 6f50fbe..2856a78 100644 --- a/src/vm.h +++ b/src/vm.h @@ -40,6 +40,6 @@ typedef enum { OP_CMP_STRING, /* dest = src1 */ } Opcode; -void run_vm(Data *memory, uint32_t memory_size); +uint32_t step_vm(Data *memory, uint32_t memory_size, uint32_t pc); #endif