quick-n-dirty num to str

This commit is contained in:
zongor 2025-06-08 18:07:19 -04:00
parent a1c74760a1
commit af01b5afae
1 changed files with 113 additions and 67 deletions

150
src/vm.c
View File

@ -7,7 +7,7 @@
#include <unistd.h> #include <unistd.h>
/* #define MEMORY_SIZE 65536 /\* 64KB memory (adjustable) *\/ */ /* #define MEMORY_SIZE 65536 /\* 64KB memory (adjustable) *\/ */
#define MEMORY_SIZE 200 #define MEMORY_SIZE 1024
typedef union { typedef union {
float f; float f;
uint32_t u; uint32_t u;
@ -27,16 +27,66 @@ typedef enum {
OP_MOV, /* dest = src1 */ OP_MOV, /* dest = src1 */
OP_JMP, /* jump to address src1 unconditionally */ OP_JMP, /* jump to address src1 unconditionally */
OP_JGZ, /* jump to address dest if src1 > 0 */ OP_JGZ, /* jump to address dest if src1 > 0 */
OP_INT_TO_STRING, /* dest = src1 as str */
OP_F32_TO_STRING, /* dest = src2 as str */
OP_READ_STRING, OP_READ_STRING,
OP_PRINT_STRING, OP_PRINT_STRING,
} Opcode; } Opcode;
int core_dump() {
FILE *file = fopen("memory_dump.bin", "wb");
if (!file) {
perror("Failed to open file");
return EXIT_FAILURE;
}
size_t written = fwrite(memory, 1, MEMORY_SIZE, file);
if (written != MEMORY_SIZE) {
fprintf(stderr, "Incomplete write: %zu bytes written out of %u\n", written,
MEMORY_SIZE);
fclose(file);
return EXIT_FAILURE;
}
fclose(file);
return EXIT_SUCCESS;
}
uint8_t get_char(uint32_t word, int index) { uint8_t get_char(uint32_t word, int index) {
return (word >> (8 * index)) & 0xFF; return (word >> (8 * (3 - index))) & 0xFF;
} }
uint32_t set_char(uint32_t word, int index, uint8_t ch) { uint32_t set_char(uint32_t word, int index, uint8_t ch) {
return (word & ~(0xFF << (8 * index))) | (ch << (8 * index)); return (word & ~(0xFF << (8 * (3 - index)))) | (ch << (8 * (3 - index)));
}
/* Pack string into union-based memory */
void pack_string(const char *str, uint32_t length, uint32_t dest_addr) {
memory[dest_addr].u = length;
uint32_t buffer_addr = dest_addr + 1;
int word_index = 0;
int char_index = 0;
uint32_t i = 0;
while (i < length) {
char ch = str[i++];
if (ch == '\0' || ch == EOF) {
uint32_t word = memory[buffer_addr + word_index].u;
word = set_char(word, char_index, '\0');
memory[buffer_addr + word_index].u = word;
break;
}
uint32_t word = memory[buffer_addr + word_index].u;
word = set_char(word, char_index, ch);
memory[buffer_addr + word_index].u = word;
char_index++;
if (char_index == 4) {
char_index = 0;
word_index++;
}
length++;
}
} }
void run_vm() { void run_vm() {
@ -109,22 +159,32 @@ void run_vm() {
pc = (jump_target & mask) | (pc & ~mask); pc = (jump_target & mask) | (pc & ~mask);
break; break;
} }
case OP_INT_TO_STRING: {
int32_t a = (int32_t)memory[src1_addr].u;
char buffer[32];
sprintf(buffer, "%d", a);
pack_string(buffer, strlen(buffer), dest_addr);
break;
}
case OP_F32_TO_STRING: {
float a = memory[src1_addr].f;
char buffer[32];
sprintf(buffer, "%f", a);
pack_string(buffer, strlen(buffer), dest_addr);
break;
}
case OP_PRINT_STRING: { case OP_PRINT_STRING: {
uint32_t string_addr = src1_addr; uint32_t string_addr = src1_addr;
uint32_t length = memory[src1_addr - 1].u; uint32_t length = memory[src1_addr - 1].u;
uint32_t i; uint32_t i;
while (i < length) { for (i = 0; i < length;) {
int j = 0; uint32_t word = memory[string_addr + (i / 4)].u;
uint32_t word = memory[string_addr + (i++)].u; uint8_t ch = get_char(word, i % 4);
for (j = 0; j < 4; j++) {
char ch = (word >> (8 * j)) & 0xFF;
if (ch == '\0') if (ch == '\0')
goto done; break;
putchar(ch); putchar(ch);
i++;
} }
}
done:
putchar('\n'); putchar('\n');
break; break;
} }
@ -132,31 +192,30 @@ void run_vm() {
putchar('>'); putchar('>');
putchar(' '); putchar(' ');
uint32_t buffer_addr = dest_addr + 1; uint32_t buffer_addr = dest_addr + 1;
uint32_t length = 0;
int word_index = 0; int word_index = 0;
int char_index = 0; int char_index = 0;
uint32_t length = 1;
while (1) { while (1) {
int ch = getchar(); int ch = getchar();
if (ch == '\n' || ch == EOF) { if (ch == '\n' || ch == EOF) {
/* Store null terminator */
uint32_t word = memory[buffer_addr + word_index].u; uint32_t word = memory[buffer_addr + word_index].u;
word = set_char(word, char_index, '\0'); word = set_char(word, char_index, '\0');
memory[buffer_addr + word_index].u = word; memory[buffer_addr + word_index].u = word;
break; break;
} }
uint32_t word = memory[buffer_addr + word_index].u; uint32_t word = memory[buffer_addr + word_index].u;
word = set_char(word, char_index, ch); word = set_char(word, char_index, ch);
memory[buffer_addr + word_index].u = word; memory[buffer_addr + word_index].u = word;
length++;
char_index++; char_index++;
if (char_index == 4) { if (char_index == 4) {
char_index = 0; char_index = 0;
word_index++; word_index++;
} }
length++;
} }
memory[dest_addr].u = length; memory[dest_addr].u = length;
break; break;
} }
@ -168,27 +227,28 @@ void run_vm() {
} }
int main() { int main() {
memory[0].u = OP_READ_STRING; int i = 0;
memory[1].u = 0; memory[i++].u = OP_ADD_F32;
memory[2].u = 0; memory[i++].u = 102;
memory[3].u = 104; memory[i++].u = 103;
memory[4].u = OP_ADD_F32; memory[i++].u = 103;
memory[5].u = 102; memory[i++].u = OP_SUB;
memory[6].u = 103; memory[i++].u = 100;
memory[7].u = 103; memory[i++].u = 101;
memory[8].u = OP_SUB; memory[i++].u = 100;
memory[9].u = 100; memory[i++].u = OP_JGZ;
memory[10].u = 101; memory[i++].u = 100;
memory[11].u = 100; memory[i++].u = 4;
memory[12].u = OP_JGZ; memory[i++].u = 4;
memory[13].u = 100; memory[i++].u = OP_F32_TO_STRING;
memory[14].u = 4; memory[i++].u = 103;
memory[15].u = 4; memory[i++].u = 0;
memory[16].u = OP_PRINT_STRING; memory[i++].u = 104;
memory[17].u = 105; memory[i++].u = OP_PRINT_STRING;
memory[18].u = 0; memory[i++].u = 105;
memory[19].u = 0; memory[i++].u = 0;
memory[20].u = OP_HALT; memory[i++].u = 0;
memory[i++].u = OP_HALT;
memory[100].u = 5; memory[100].u = 5;
memory[101].u = 1; memory[101].u = 1;
memory[102].f = 5.f; memory[102].f = 5.f;
@ -196,19 +256,5 @@ int main() {
run_vm(); run_vm();
FILE *file = fopen("memory_dump.bin", "wb"); return core_dump();
if (!file) {
perror("Failed to open file");
return EXIT_FAILURE;
}
size_t written = fwrite(memory, 1, MEMORY_SIZE, file);
if (written != MEMORY_SIZE) {
fprintf(stderr, "Incomplete write: %zu bytes written out of %u\n", written, MEMORY_SIZE);
fclose(file);
return EXIT_FAILURE;
}
fclose(file);
return 0;
} }