add fat pointers for strings, update makefile, test
This commit is contained in:
parent
2817e940e1
commit
a1c74760a1
|
@ -101,4 +101,5 @@ Module.symvers
|
||||||
Mkfile.old
|
Mkfile.old
|
||||||
dkms.conf
|
dkms.conf
|
||||||
|
|
||||||
zlc
|
zre
|
||||||
|
memory_dump.bin
|
|
@ -7,7 +7,7 @@ LDLIBS +=
|
||||||
# Source and build configuration
|
# Source and build configuration
|
||||||
SRC = $(wildcard *.c)
|
SRC = $(wildcard *.c)
|
||||||
OBJ = $(SRC:.c=.o)
|
OBJ = $(SRC:.c=.o)
|
||||||
EXEC = zlc
|
EXEC = zre
|
||||||
|
|
||||||
# Phony targets
|
# Phony targets
|
||||||
.PHONY: all clean test install
|
.PHONY: all clean test install
|
||||||
|
|
78
src/vm.c
78
src/vm.c
|
@ -4,15 +4,15 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/mman.h>
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#define MEMORY_SIZE 65536 /* 64KB memory (adjustable) */
|
/* #define MEMORY_SIZE 65536 /\* 64KB memory (adjustable) *\/ */
|
||||||
|
#define MEMORY_SIZE 200
|
||||||
typedef union {
|
typedef union {
|
||||||
float f;
|
float f;
|
||||||
uint32_t u;
|
uint32_t u;
|
||||||
} FloatUint32Union;
|
} Data;
|
||||||
FloatUint32Union memory[MEMORY_SIZE]; /* Memory array */
|
Data memory[MEMORY_SIZE]; /* Memory array */
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
OP_HALT, /* terminate execution */
|
OP_HALT, /* terminate execution */
|
||||||
|
@ -38,6 +38,7 @@ uint8_t get_char(uint32_t word, int index) {
|
||||||
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 * index))) | (ch << (8 * index));
|
||||||
}
|
}
|
||||||
|
|
||||||
void run_vm() {
|
void run_vm() {
|
||||||
uint32_t pc = 0; /* Program counter */
|
uint32_t pc = 0; /* Program counter */
|
||||||
|
|
||||||
|
@ -58,51 +59,30 @@ void run_vm() {
|
||||||
switch (opcode) {
|
switch (opcode) {
|
||||||
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;
|
||||||
printf("ADD;src1[%d]:%d;src2[%d]:%d;dest[%d]:%d\n", src1_addr,
|
|
||||||
memory[src1_addr].u, src2_addr, memory[src2_addr].u, dest_addr,
|
|
||||||
memory[dest_addr].u);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
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;
|
||||||
printf("ADD;src1[%d]:%d;src2[%d]:%d;dest[%d]:%d\n", src1_addr,
|
|
||||||
memory[src1_addr].u, src2_addr, memory[src2_addr].u, dest_addr,
|
|
||||||
memory[dest_addr].u);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
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;
|
||||||
printf("ADD;src1[%d]:%d;src2[%d]:%d;dest[%d]:%d\n", src1_addr,
|
|
||||||
memory[src1_addr].u, src2_addr, memory[src2_addr].u, dest_addr,
|
|
||||||
memory[dest_addr].u);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
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;
|
||||||
printf("ADD;src1[%d]:%d;src2[%d]:%d;dest[%d]:%d\n", src1_addr,
|
|
||||||
memory[src1_addr].u, src2_addr, memory[src2_addr].u, dest_addr,
|
|
||||||
memory[dest_addr].u);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OP_ADD_F32:
|
case OP_ADD_F32:
|
||||||
memory[dest_addr].f = memory[src1_addr].f + memory[src2_addr].f;
|
memory[dest_addr].f = memory[src1_addr].f + memory[src2_addr].f;
|
||||||
printf("ADD;src1[%d]:%f;src2[%d]:%f;dest[%d]:%f\n", src1_addr,
|
|
||||||
memory[src1_addr].f, src2_addr, memory[src2_addr].f, dest_addr,
|
|
||||||
memory[dest_addr].f);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OP_SUB_F32:
|
case OP_SUB_F32:
|
||||||
memory[dest_addr].f = memory[src1_addr].f - memory[src2_addr].f;
|
memory[dest_addr].f = memory[src1_addr].f - memory[src2_addr].f;
|
||||||
printf("ADD;src1[%d]:%f;src2[%d]:%f;dest[%d]:%f\n", src1_addr,
|
|
||||||
memory[src1_addr].f, src2_addr, memory[src2_addr].f, dest_addr,
|
|
||||||
memory[dest_addr].f);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OP_MUL_F32:
|
case OP_MUL_F32:
|
||||||
memory[dest_addr].f = memory[src1_addr].f * memory[src2_addr].f;
|
memory[dest_addr].f = memory[src1_addr].f * memory[src2_addr].f;
|
||||||
printf("ADD;src1[%d]:%f;src2[%d]:%f;dest[%d]:%f\n", src1_addr,
|
|
||||||
memory[src1_addr].f, src2_addr, memory[src2_addr].f, dest_addr,
|
|
||||||
memory[dest_addr].f);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OP_DIV_F32:
|
case OP_DIV_F32:
|
||||||
|
@ -111,31 +91,16 @@ void run_vm() {
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
memory[dest_addr].f = memory[src1_addr].f / memory[src2_addr].f;
|
memory[dest_addr].f = memory[src1_addr].f / memory[src2_addr].f;
|
||||||
printf("ADD;src1[%d]:%f;src2[%d]:%f;dest[%d]:%f\n", src1_addr,
|
|
||||||
memory[src1_addr].f, src2_addr, memory[src2_addr].f, dest_addr,
|
|
||||||
memory[dest_addr].f);
|
|
||||||
break;
|
break;
|
||||||
case OP_HALT:
|
case OP_HALT:
|
||||||
printf("ADD;src1[%d]:%d;src2[%d]:%d;dest[%d]:%d\n", src1_addr,
|
|
||||||
memory[src1_addr].u, src2_addr, memory[src2_addr].u, dest_addr,
|
|
||||||
memory[dest_addr].u);
|
|
||||||
return;
|
return;
|
||||||
case OP_MOV:
|
case OP_MOV:
|
||||||
printf("ADD;src1[%d]:%d;src2[%d]:%d;dest[%d]:%d\n", src1_addr,
|
|
||||||
memory[src1_addr].u, src2_addr, memory[src2_addr].u, dest_addr,
|
|
||||||
memory[dest_addr].u);
|
|
||||||
memory[dest_addr] = memory[src1_addr];
|
memory[dest_addr] = memory[src1_addr];
|
||||||
break;
|
break;
|
||||||
case OP_JMP:
|
case OP_JMP:
|
||||||
printf("ADD;src1[%d]:%d;src2[%d]:%d;dest[%d]:%d\n", src1_addr,
|
|
||||||
memory[src1_addr].u, src2_addr, memory[src2_addr].u, dest_addr,
|
|
||||||
memory[dest_addr].u);
|
|
||||||
pc = src1_addr; /* Jump to address */
|
pc = src1_addr; /* Jump to address */
|
||||||
break;
|
break;
|
||||||
case OP_JGZ: {
|
case OP_JGZ: {
|
||||||
printf("ADD;src1[%d]:%d;src2[%d]:%d;dest[%d]:%d\n", src1_addr,
|
|
||||||
memory[src1_addr].u, src2_addr, memory[src2_addr].u, dest_addr,
|
|
||||||
memory[dest_addr].u);
|
|
||||||
uint32_t value = memory[src1_addr].u;
|
uint32_t value = memory[src1_addr].u;
|
||||||
uint32_t jump_target = src2_addr;
|
uint32_t jump_target = src2_addr;
|
||||||
|
|
||||||
|
@ -145,10 +110,11 @@ void run_vm() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case OP_PRINT_STRING: {
|
case OP_PRINT_STRING: {
|
||||||
printf("PRINT_STRING;");
|
|
||||||
uint32_t string_addr = src1_addr;
|
uint32_t string_addr = src1_addr;
|
||||||
int i = 0;
|
uint32_t length = memory[src1_addr-1].u;
|
||||||
while (1) {
|
|
||||||
|
uint32_t i;
|
||||||
|
while (i < length) {
|
||||||
int j = 0;
|
int j = 0;
|
||||||
uint32_t word = memory[string_addr + (i++)].u;
|
uint32_t word = memory[string_addr + (i++)].u;
|
||||||
for (j = 0; j < 4; j++) {
|
for (j = 0; j < 4; j++) {
|
||||||
|
@ -163,10 +129,12 @@ void run_vm() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case OP_READ_STRING: {
|
case OP_READ_STRING: {
|
||||||
printf("> ");
|
putchar('>');
|
||||||
uint32_t buffer_addr = dest_addr;
|
putchar(' ');
|
||||||
|
uint32_t buffer_addr = dest_addr + 1;
|
||||||
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();
|
||||||
|
@ -180,6 +148,7 @@ void run_vm() {
|
||||||
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) {
|
||||||
|
@ -187,6 +156,8 @@ void run_vm() {
|
||||||
word_index++;
|
word_index++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
memory[dest_addr].u = length;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
@ -214,7 +185,7 @@ int main() {
|
||||||
memory[14].u = 4;
|
memory[14].u = 4;
|
||||||
memory[15].u = 4;
|
memory[15].u = 4;
|
||||||
memory[16].u = OP_PRINT_STRING;
|
memory[16].u = OP_PRINT_STRING;
|
||||||
memory[17].u = 104;
|
memory[17].u = 105;
|
||||||
memory[18].u = 0;
|
memory[18].u = 0;
|
||||||
memory[19].u = 0;
|
memory[19].u = 0;
|
||||||
memory[20].u = OP_HALT;
|
memory[20].u = OP_HALT;
|
||||||
|
@ -225,6 +196,19 @@ int main() {
|
||||||
|
|
||||||
run_vm();
|
run_vm();
|
||||||
|
|
||||||
printf("Dest at address 103: %f\n", memory[103].f);
|
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 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
1 + 2
|
print(1 + 2);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
for (let i = 0; i < 10; i = i + 1) {
|
for (let i = 0; i < 10; i = i + 1) {
|
||||||
print i;
|
print(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
let val = true;
|
let val = true;
|
||||||
|
@ -7,6 +7,6 @@ let j = 0;
|
||||||
while (val) {
|
while (val) {
|
||||||
j = j + 1;
|
j = j + 1;
|
||||||
if (j > 9) val = false;
|
if (j > 9) val = false;
|
||||||
print j;
|
print(j);
|
||||||
}
|
}
|
||||||
print "done";
|
print("done");
|
||||||
|
|
Loading…
Reference in New Issue