refactor to step intead of loop

This commit is contained in:
zongor 2025-06-14 11:30:27 -04:00
parent 4cb02c41d0
commit 838f3800cb
3 changed files with 242 additions and 240 deletions

View File

@ -1,13 +1,24 @@
#include "vm.h"
#include "debug.h" #include "debug.h"
#include "vm.h"
/* #define MEMORY_SIZE 65536 /\* 64KB memory (adjustable) *\/ */ /* #define MEMORY_SIZE 65536 /\* 64KB memory (adjustable) *\/ */
#define MEMORY_SIZE 1024 #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() { int main() {
Data memory[MEMORY_SIZE] = {0}; /* Memory array */ 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 = OP_ADD_REAL;
memory[i++].u = 102; memory[i++].u = 102;
memory[i++].u = 103; memory[i++].u = 103;
@ -19,27 +30,27 @@ int main() {
memory[i++].u = OP_JGT_INT; memory[i++].u = OP_JGT_INT;
memory[i++].u = 100; memory[i++].u = 100;
memory[i++].u = 99; memory[i++].u = 99;
memory[i++].u = 0; memory[i++].u = 1;
memory[i++].u = OP_REAL_TO_INT; memory[i++].u = OP_REAL_TO_INT;
memory[i++].u = 103; memory[i++].u = 103;
memory[i++].u = 0; memory[i++].u = 1;
memory[i++].u = 103; memory[i++].u = 103;
memory[i++].u = OP_INT_TO_STRING; memory[i++].u = OP_INT_TO_STRING;
memory[i++].u = 103; memory[i++].u = 103;
memory[i++].u = 0; memory[i++].u = 1;
memory[i++].u = 104; memory[i++].u = 104;
memory[i++].u = OP_PRINT_STRING; memory[i++].u = OP_PRINT_STRING;
memory[i++].u = 105; memory[i++].u = 105;
memory[i++].u = 0; memory[i++].u = 1;
memory[i++].u = 0; memory[i++].u = 1;
memory[i++].u = OP_READ_STRING; memory[i++].u = OP_READ_STRING;
memory[i++].u = 0; memory[i++].u = 1;
memory[i++].u = 0; memory[i++].u = 1;
memory[i++].u = 109; memory[i++].u = 109;
memory[i++].u = OP_PRINT_STRING; memory[i++].u = OP_PRINT_STRING;
memory[i++].u = 110; memory[i++].u = 110;
memory[i++].u = 0; memory[i++].u = 1;
memory[i++].u = 0; memory[i++].u = 1;
memory[i++].u = OP_HALT; memory[i++].u = OP_HALT;
memory[i++].u = 0; memory[i++].u = 0;
memory[i++].u = 0; memory[i++].u = 0;

157
src/vm.c
View File

@ -9,22 +9,16 @@ void mem_strcpy(Data *memory, const char *str, uint32_t length,
uint32_t dest_addr) { uint32_t dest_addr) {
memory[dest_addr].u = length; memory[dest_addr].u = length;
uint32_t buffer_addr = dest_addr + 1; uint32_t buffer_addr = dest_addr + 1;
uint32_t i = 0; uint32_t i;
while (i < length) { for (i = 0; i < length; i++) {
char ch = str[i]; memory[buffer_addr + (i / 4)].c[i % 4] = str[i];
if (ch == '\0') {
break;
}
memory[buffer_addr + (i / 4)].c[i % 4] = ch;
i++;
} }
} }
void run_vm(Data *memory, uint32_t memory_size) { /**
uint32_t pc = 0; /* Program counter */ * Step to the next opcode in the vm.
*/
while (pc < memory_size - 4) { uint32_t step_vm(Data *memory, uint32_t memory_size, uint32_t pc) {
Opcode opcode = memory[pc].u; Opcode opcode = memory[pc].u;
uint32_t src1_addr = memory[pc + 1].u; uint32_t src1_addr = memory[pc + 1].u;
uint32_t src2_addr = memory[pc + 2].u; uint32_t src2_addr = memory[pc + 2].u;
@ -34,68 +28,76 @@ void run_vm(Data *memory, uint32_t memory_size) {
if (src1_addr >= memory_size || src2_addr >= memory_size || if (src1_addr >= memory_size || src2_addr >= memory_size ||
dest_addr >= memory_size) { dest_addr >= memory_size) {
printf("Invalid memory address!\n"); printf("Invalid memory address!\n");
exit(1); return 0;
} }
switch (opcode) { switch (opcode) {
case OP_HALT: case OP_HALT:
return; return 0;
case OP_ADD: case OP_ADD:
memory[dest_addr].u = memory[src1_addr].u + memory[src2_addr].u; memory[dest_addr].u = memory[src1_addr].u + memory[src2_addr].u;
break; return pc;
case OP_SUB: case OP_SUB:
memory[dest_addr].u = memory[src1_addr].u - memory[src2_addr].u; memory[dest_addr].u = memory[src1_addr].u - memory[src2_addr].u;
break; return pc;
case OP_MUL: case OP_MUL:
memory[dest_addr].u = memory[src1_addr].u * memory[src2_addr].u; memory[dest_addr].u = memory[src1_addr].u * memory[src2_addr].u;
break; return pc;
case OP_DIV: case OP_DIV:
memory[dest_addr].u = memory[src1_addr].u / memory[src2_addr].u; memory[dest_addr].u = memory[src1_addr].u / memory[src2_addr].u;
break; return pc;
case OP_ADD_REAL: case OP_ADD_REAL:
memory[dest_addr].f = memory[src1_addr].f + memory[src2_addr].f; memory[dest_addr].f = memory[src1_addr].f + memory[src2_addr].f;
break; return pc;
case OP_SUB_REAL: case OP_SUB_REAL:
memory[dest_addr].f = memory[src1_addr].f - memory[src2_addr].f; memory[dest_addr].f = memory[src1_addr].f - memory[src2_addr].f;
break; return pc;
case OP_MUL_REAL: case OP_MUL_REAL:
memory[dest_addr].f = memory[src1_addr].f * memory[src2_addr].f; memory[dest_addr].f = memory[src1_addr].f * memory[src2_addr].f;
break; return pc;
case OP_DIV_REAL: case OP_DIV_REAL:
if (memory[src2_addr].f == 0.0f) { if (memory[src2_addr].f == 0.0f) {
printf("Division by zero error at address %d\n", pc - 4); printf("Division by zero error at address %d\n", pc - 4);
exit(1); return 0;
} }
memory[dest_addr].f = memory[src1_addr].f / memory[src2_addr].f; memory[dest_addr].f = memory[src1_addr].f / memory[src2_addr].f;
break; return pc;
case OP_REAL_TO_INT: { case OP_REAL_TO_INT: {
memory[dest_addr].u = (uint32_t)memory[src1_addr].f; memory[dest_addr].u = (uint32_t)memory[src1_addr].f;
break; return pc;
} }
case OP_INT_TO_REAL: { case OP_INT_TO_REAL: {
memory[dest_addr].f = (float)memory[src1_addr].u; memory[dest_addr].f = (float)memory[src1_addr].u;
break; return pc;
} }
case OP_MOV: case OP_MOV:
memory[dest_addr] = memory[src1_addr]; memory[dest_addr] = memory[src1_addr];
break; return pc;
case OP_JMP: case OP_JMP:
pc = src1_addr; /* Jump to address */ pc = src1_addr; /* Jump to address */
break; 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: { case OP_JGT_INT: {
uint32_t value = memory[src1_addr].u; uint32_t value = memory[src1_addr].u;
uint32_t value2 = memory[src2_addr].u; uint32_t value2 = memory[src2_addr].u;
uint32_t jump_target = dest_addr; uint32_t jump_target = dest_addr;
pc = (value > value2) ? jump_target : pc; pc = (value > value2) ? jump_target : pc;
break; return pc;
} }
case OP_JLT_INT: { case OP_JLT_INT: {
uint32_t value = memory[src1_addr].u; uint32_t value = memory[src1_addr].u;
@ -103,47 +105,7 @@ void run_vm(Data *memory, uint32_t memory_size) {
uint32_t jump_target = dest_addr; uint32_t jump_target = dest_addr;
pc = (value < value2) ? jump_target : pc; pc = (value < value2) ? jump_target : pc;
break; 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;
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: { case OP_JLE_INT: {
uint32_t value = memory[src1_addr].u; uint32_t value = memory[src1_addr].u;
@ -151,7 +113,39 @@ void run_vm(Data *memory, uint32_t memory_size) {
uint32_t jump_target = dest_addr; uint32_t jump_target = dest_addr;
pc = (value <= value2) ? jump_target : pc; pc = (value <= value2) ? jump_target : pc;
break; 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: { case OP_JGE_REAL: {
float value = memory[src1_addr].f; float value = memory[src1_addr].f;
@ -159,7 +153,7 @@ void run_vm(Data *memory, uint32_t memory_size) {
uint32_t jump_target = dest_addr; uint32_t jump_target = dest_addr;
pc = (value >= value2) ? jump_target : pc; pc = (value >= value2) ? jump_target : pc;
break; return pc;
} }
case OP_JLE_REAL: { case OP_JLE_REAL: {
float value = memory[src1_addr].f; float value = memory[src1_addr].f;
@ -167,21 +161,21 @@ void run_vm(Data *memory, uint32_t memory_size) {
uint32_t jump_target = dest_addr; uint32_t jump_target = dest_addr;
pc = (value <= value2) ? jump_target : pc; pc = (value <= value2) ? jump_target : pc;
break; return pc;
} }
case OP_INT_TO_STRING: { case OP_INT_TO_STRING: {
int32_t a = (int32_t)memory[src1_addr].u; int32_t a = (int32_t)memory[src1_addr].u;
char buffer[32]; char buffer[32];
sprintf(buffer, "%d", a); sprintf(buffer, "%d", a);
mem_strcpy(memory, buffer, strlen(buffer), dest_addr); mem_strcpy(memory, buffer, strlen(buffer), dest_addr);
break; return pc;
} }
case OP_REAL_TO_STRING: { case OP_REAL_TO_STRING: {
float a = memory[src1_addr].f; float a = memory[src1_addr].f;
char buffer[32]; char buffer[32];
sprintf(buffer, "%f", a); sprintf(buffer, "%f", a);
mem_strcpy(memory, buffer, strlen(buffer), dest_addr); mem_strcpy(memory, buffer, strlen(buffer), dest_addr);
break; return pc;
} }
case OP_READ_STRING: { case OP_READ_STRING: {
uint32_t buffer_addr = dest_addr + 1; uint32_t buffer_addr = dest_addr + 1;
@ -196,7 +190,7 @@ void run_vm(Data *memory, uint32_t memory_size) {
length++; length++;
} }
memory[dest_addr].u = length; memory[dest_addr].u = length;
break; return pc;
} }
case OP_PRINT_STRING: { case OP_PRINT_STRING: {
uint32_t string_addr = src1_addr; uint32_t string_addr = src1_addr;
@ -209,7 +203,7 @@ void run_vm(Data *memory, uint32_t memory_size) {
putchar(ch); putchar(ch);
} }
putchar('\n'); putchar('\n');
break; return pc;
} }
case OP_CMP_STRING: { case OP_CMP_STRING: {
uint32_t addr1 = src1_addr; uint32_t addr1 = src1_addr;
@ -230,15 +224,12 @@ void run_vm(Data *memory, uint32_t memory_size) {
break; break;
} }
if ((char1 & 0xFF) == '\0' && (char2 & 0xFF) == '\0') if ((char1 & 0xFF) == '\0' && (char2 & 0xFF) == '\0')
break; return pc;
} }
} }
memory[dest_addr].u = equal; memory[dest_addr].u = equal;
break; return pc;
}
default:
printf("Unknown opcode: %d\n", opcode);
return;
} }
} }
return 0;
} }

View File

@ -40,6 +40,6 @@ typedef enum {
OP_CMP_STRING, /* dest = src1 */ OP_CMP_STRING, /* dest = src1 */
} Opcode; } Opcode;
void run_vm(Data *memory, uint32_t memory_size); uint32_t step_vm(Data *memory, uint32_t memory_size, uint32_t pc);
#endif #endif