First working prototype for assembler!
This commit is contained in:
parent
6d1beb24ae
commit
91061fe3c0
14
Makefile
14
Makefile
|
@ -39,7 +39,7 @@ endif
|
|||
ifeq ($(PLATFORM), linux)
|
||||
PLATFORM_CFLAGS += $(shell pkg-config --cflags sdl2 2>/dev/null)
|
||||
LDFLAGS += $(shell pkg-config --libs sdl2 2>/dev/null) -lm
|
||||
TARGET = $(BUILD_DIR)/zre-$(PLATFORM)$(TARGET_SUFFIX)
|
||||
TARGET = $(BUILD_DIR)/undar-$(PLATFORM)$(TARGET_SUFFIX)
|
||||
endif
|
||||
|
||||
# --- EMSCRIPTEN-SPECIFIC ---
|
||||
|
@ -60,12 +60,12 @@ ifeq ($(PLATFORM), emscripten)
|
|||
endif
|
||||
|
||||
# Output: HTML + JS + WASM
|
||||
TARGET = $(BUILD_DIR)/zre.html
|
||||
TARGET = $(BUILD_DIR)/undar.html
|
||||
endif
|
||||
|
||||
# --- FALLBACK TARGET (if no platform matched) ---
|
||||
ifndef TARGET
|
||||
TARGET = $(BUILD_DIR)/zre-$(PLATFORM)$(TARGET_SUFFIX)
|
||||
TARGET = $(BUILD_DIR)/undar-$(PLATFORM)$(TARGET_SUFFIX)
|
||||
endif
|
||||
|
||||
# --- VM CORE SOURCES ---
|
||||
|
@ -80,8 +80,8 @@ ifeq ($(BUILD_MODE), deploy)
|
|||
else
|
||||
PLATFORM_SOURCE := $(ARCH_DIR)/main.c \
|
||||
$(ARCH_DIR)/devices.c \
|
||||
$(SRC_DIR)/tools/test.c \
|
||||
$(SRC_DIR)/tools/parser.c
|
||||
$(SRC_DIR)/tools/parser.c \
|
||||
$(SRC_DIR)/tools/assembler.c
|
||||
endif
|
||||
|
||||
# --- OBJECT FILES ---
|
||||
|
@ -159,5 +159,5 @@ help:
|
|||
@echo " make PLATFORM=avr -> (example) AVR-GCC"
|
||||
@echo ""
|
||||
@echo "Output:"
|
||||
@echo " Linux: build/linux/zre-linux-<debug|release>"
|
||||
@echo " Web: build/emscripten/zre.html (+ .js, .wasm)"
|
||||
@echo " Linux: build/linux/undar-linux-<debug|release>"
|
||||
@echo " Web: build/emscripten/undar.html (+ .js, .wasm)"
|
||||
|
|
|
@ -141,7 +141,7 @@ Devices are memory-mapped:
|
|||
- Function calls are equivelent to redraws
|
||||
- Child calls define spacial location in code as well as the UI
|
||||
|
||||
**3D Primitives**
|
||||
**3D Primitives + Constructive solid geometry**
|
||||
Built-in support for:
|
||||
- =Cube(pos, size)=
|
||||
- =Plane(pos, radius)=
|
||||
|
@ -203,7 +203,7 @@ cd undar-lang && make
|
|||
(label main
|
||||
(load $0 &terminal-str)
|
||||
(load $1 &hello-str)
|
||||
(strlen $2 $1)
|
||||
(string-length $2 $1)
|
||||
(syscall DEVICE_WRITE $0 $1 $2)
|
||||
(load $3 &new-line)
|
||||
(string-length $4 $3)
|
||||
|
|
|
@ -37,9 +37,9 @@ print_section "zlc ($FILENAME.zl)"
|
|||
echo "test input" | time zlc "$FILENAME.zl"
|
||||
|
||||
#Old ZRE
|
||||
print_section "zre ($FILENAME.ul)"
|
||||
print_section "zre ($FILENAME.t.ul)"
|
||||
echo "test input" | time ../build/old/zre -t "$FILENAME.ul"
|
||||
|
||||
# ZRE Implementation
|
||||
print_section "zre ($FILENAME.ul)"
|
||||
echo "test input" | time ../build/linux/zre-linux-release -t "$FILENAME.ul"
|
||||
# Undâr Implementation
|
||||
#print_section "zre ($FILENAME.asm.lisp)"
|
||||
# echo "test input" | time ../build/linux/zre-linux-release "../test/$FILENAME.asm.lisp"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#include "../../tools/test.h"
|
||||
#include "../../tools/assembler.h"
|
||||
#include "../../tools/parser.h"
|
||||
#include "../../vm/vm.h"
|
||||
#include "devices.h"
|
||||
|
@ -40,8 +40,6 @@ static MouseDeviceData mouse_data = {0};
|
|||
static KeyboardDeviceData keyboard_data = {0};
|
||||
|
||||
void compileFile(const char *path, VM *vm) {
|
||||
USED(vm);
|
||||
|
||||
FILE *f = fopen(path, "rb");
|
||||
if (!f) {
|
||||
perror("fopen");
|
||||
|
@ -60,80 +58,91 @@ void compileFile(const char *path, VM *vm) {
|
|||
size_t read = fread(source, 1, len, f);
|
||||
source[read] = '\0';
|
||||
fclose(f);
|
||||
ExprNode *ast = expr_parse(source, strlen(source));
|
||||
if (!ast) {
|
||||
printf("Parse failed.\n");
|
||||
} else {
|
||||
assemble(vm, ast);
|
||||
expr_free(ast);
|
||||
}
|
||||
}
|
||||
|
||||
void repl(VM *vm) {
|
||||
USED(vm);
|
||||
USED(vm);
|
||||
|
||||
char buffer[1024 * 10] = {0}; // Larger buffer for multi-line input
|
||||
char line[1024];
|
||||
char buffer[1024 * 10] = {0}; // Larger buffer for multi-line input
|
||||
char line[1024];
|
||||
|
||||
for (;;) {
|
||||
// Count current parentheses balance
|
||||
int paren_balance = 0;
|
||||
for (int i = 0; buffer[i]; i++) {
|
||||
if (buffer[i] == '(') paren_balance++;
|
||||
else if (buffer[i] == ')') paren_balance--;
|
||||
}
|
||||
|
||||
// Show appropriate prompt
|
||||
if (paren_balance > 0) {
|
||||
printf(".. "); // Continuation prompt when unbalanced
|
||||
} else {
|
||||
printf("> "); // Normal prompt when balanced
|
||||
}
|
||||
fflush(stdout);
|
||||
|
||||
if (!fgets(line, sizeof(line), stdin)) {
|
||||
printf("\n");
|
||||
break;
|
||||
}
|
||||
|
||||
// Append the new line to buffer
|
||||
strncat(buffer, line, sizeof(buffer) - strlen(buffer) - 1);
|
||||
|
||||
// Recalculate balance after adding new line
|
||||
paren_balance = 0;
|
||||
for (int i = 0; buffer[i]; i++) {
|
||||
if (buffer[i] == '(') paren_balance++;
|
||||
else if (buffer[i] == ')') paren_balance--;
|
||||
}
|
||||
|
||||
// Only parse when parentheses are balanced
|
||||
if (paren_balance == 0) {
|
||||
// Check if buffer has actual content (not just whitespace)
|
||||
int has_content = 0;
|
||||
for (int i = 0; buffer[i]; i++) {
|
||||
if (!isspace(buffer[i])) {
|
||||
has_content = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (has_content) {
|
||||
ExprNode *ast = expr_parse(buffer, strlen(buffer));
|
||||
if (!ast) {
|
||||
printf("Parse failed.\n");
|
||||
} else {
|
||||
printf("AST:\n");
|
||||
expr_print(ast, 0);
|
||||
expr_free(ast);
|
||||
}
|
||||
}
|
||||
|
||||
// Reset buffer for next input
|
||||
buffer[0] = '\0';
|
||||
}
|
||||
// If unbalanced, continue reading more lines
|
||||
for (;;) {
|
||||
// Count current parentheses balance
|
||||
int paren_balance = 0;
|
||||
for (int i = 0; buffer[i]; i++) {
|
||||
if (buffer[i] == '(')
|
||||
paren_balance++;
|
||||
else if (buffer[i] == ')')
|
||||
paren_balance--;
|
||||
}
|
||||
exit(0);
|
||||
|
||||
// Show appropriate prompt
|
||||
if (paren_balance > 0) {
|
||||
printf(".. "); // Continuation prompt when unbalanced
|
||||
} else {
|
||||
printf("> "); // Normal prompt when balanced
|
||||
}
|
||||
fflush(stdout);
|
||||
|
||||
if (!fgets(line, sizeof(line), stdin)) {
|
||||
printf("\n");
|
||||
break;
|
||||
}
|
||||
|
||||
// Append the new line to buffer
|
||||
strncat(buffer, line, sizeof(buffer) - strlen(buffer) - 1);
|
||||
|
||||
// Recalculate balance after adding new line
|
||||
paren_balance = 0;
|
||||
for (int i = 0; buffer[i]; i++) {
|
||||
if (buffer[i] == '(')
|
||||
paren_balance++;
|
||||
else if (buffer[i] == ')')
|
||||
paren_balance--;
|
||||
}
|
||||
|
||||
// Only parse when parentheses are balanced
|
||||
if (paren_balance == 0) {
|
||||
// Check if buffer has actual content (not just whitespace)
|
||||
int has_content = 0;
|
||||
for (int i = 0; buffer[i]; i++) {
|
||||
if (!isspace(buffer[i])) {
|
||||
has_content = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (has_content) {
|
||||
ExprNode *ast = expr_parse(buffer, strlen(buffer));
|
||||
if (!ast) {
|
||||
printf("Parse failed.\n");
|
||||
} else {
|
||||
assemble(vm, ast);
|
||||
while (step_vm(vm)) {
|
||||
}
|
||||
expr_free(ast);
|
||||
}
|
||||
}
|
||||
|
||||
// Reset buffer for next input
|
||||
buffer[0] = '\0';
|
||||
}
|
||||
// If unbalanced, continue reading more lines
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
|
||||
enum FlagType {
|
||||
FLAG_NONE = 0,
|
||||
FLAG_TEST_MODE = 1,
|
||||
FLAG_DUMP_ROM = 2,
|
||||
FLAG_GUI_MODE = 4,
|
||||
FLAG_DUMP_ROM = 1,
|
||||
FLAG_GUI_MODE = 2,
|
||||
};
|
||||
|
||||
#define MAX_INPUT_FILES 16 /* Adjust based on your system's constraints */
|
||||
|
@ -161,8 +170,6 @@ i32 parse_arguments(i32 argc, char *argv[], struct CompilerConfig *config) {
|
|||
/* Long and short flag handling */
|
||||
if (strcmp(argv[i], "-g") == 0 || strcmp(argv[i], "--gui") == 0) {
|
||||
config->flags |= FLAG_GUI_MODE;
|
||||
} else if (strcmp(argv[i], "-t") == 0 || strcmp(argv[i], "--test") == 0) {
|
||||
config->flags |= FLAG_TEST_MODE;
|
||||
} else if (strcmp(argv[i], "-o") == 0 ||
|
||||
strcmp(argv[i], "--dump-rom") == 0) {
|
||||
config->flags |= FLAG_DUMP_ROM;
|
||||
|
@ -178,6 +185,14 @@ i32 parse_arguments(i32 argc, char *argv[], struct CompilerConfig *config) {
|
|||
return -1;
|
||||
}
|
||||
config->input_files[config->input_file_count++] = argv[i];
|
||||
} else if (strstr(argv[i], ".lisp") != NULL) {
|
||||
/* Collect input files */
|
||||
if (config->input_file_count >= MAX_INPUT_FILES) {
|
||||
fprintf(stderr, "Too many input files. Maximum is %d\n",
|
||||
MAX_INPUT_FILES);
|
||||
return -1;
|
||||
}
|
||||
config->input_files[config->input_file_count++] = argv[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -216,7 +231,7 @@ i32 main(i32 argc, char *argv[]) {
|
|||
struct CompilerConfig config = {0};
|
||||
|
||||
if (parse_arguments(argc, argv, &config) != 0) {
|
||||
fprintf(stderr, "Usage: %s [-d] [-t] [-g] [-o] <file1.ul> [file2.ul] ...\n",
|
||||
fprintf(stderr, "Usage: %s [-d] [-g] [-o] <file1.ul> [file2.ul] ...\n",
|
||||
argv[0]);
|
||||
return 64;
|
||||
}
|
||||
|
@ -225,13 +240,9 @@ i32 main(i32 argc, char *argv[]) {
|
|||
if (config.input_file_count == 0) {
|
||||
repl(&vm);
|
||||
} else {
|
||||
if (config.flags & FLAG_TEST_MODE) {
|
||||
compile_internal_test(config.input_files[0], &vm);
|
||||
} else {
|
||||
i32 j;
|
||||
for (j = 0; j < config.input_file_count; j++) {
|
||||
compileFile(config.input_files[j], &vm);
|
||||
}
|
||||
i32 j;
|
||||
for (j = 0; j < config.input_file_count; j++) {
|
||||
compileFile(config.input_files[j], &vm);
|
||||
}
|
||||
|
||||
if (config.flags & FLAG_DUMP_ROM) {
|
||||
|
|
|
@ -0,0 +1,603 @@
|
|||
#include "assembler.h"
|
||||
|
||||
Label labels[256]; // For simplicity
|
||||
int label_count = 0;
|
||||
|
||||
void add_label(const char *name, u32 address) {
|
||||
Label *l = &labels[label_count++];
|
||||
l->name = strdup(name);
|
||||
l->address = address;
|
||||
}
|
||||
|
||||
u32 find_label(const char *name) {
|
||||
for (int i = 0; i < label_count; ++i) {
|
||||
if (strcmp(labels[i].name, name) == 0)
|
||||
return labels[i].address;
|
||||
}
|
||||
fprintf(stderr, "Error: Undefined label '%s'\n", name);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
u32 real_alloc(VM *vm, float v) {
|
||||
i32 fixed = TO_FIXED(v);
|
||||
u32 addr = vm->mp;
|
||||
write_u32(vm, memory, vm->mp, fixed);
|
||||
vm->mp += 4;
|
||||
vm->frames[vm->fp].end += 4;
|
||||
return addr;
|
||||
}
|
||||
|
||||
u32 nat_alloc(VM *vm, u32 v) {
|
||||
u32 addr = vm->mp;
|
||||
write_u32(vm, memory, vm->mp, v);
|
||||
vm->mp += 4;
|
||||
vm->frames[vm->fp].end += 4;
|
||||
return addr;
|
||||
}
|
||||
|
||||
u32 int_alloc(VM *vm, i32 v) {
|
||||
u32 addr = vm->mp;
|
||||
write_u32(vm, memory, vm->mp, v);
|
||||
vm->mp += 4;
|
||||
vm->frames[vm->fp].end += 4;
|
||||
return addr;
|
||||
}
|
||||
|
||||
void emit_byte(VM *vm, u8 byte) { vm->code[vm->cp++] = byte; }
|
||||
|
||||
void emit_u32(VM *vm, u32 value) {
|
||||
write_u32(vm, code, vm->cp, value);
|
||||
vm->cp += 4;
|
||||
}
|
||||
|
||||
void emit_opcode(VM *vm, Opcode op) { emit_byte(vm, op); }
|
||||
|
||||
int parse_register(const char *reg_str) {
|
||||
if (reg_str[0] != '$')
|
||||
return -1;
|
||||
return atoi(reg_str + 1);
|
||||
}
|
||||
|
||||
u32 parse_memory_ref(const char *ref) {
|
||||
if (ref[0] == '&') {
|
||||
return find_label(ref + 1);
|
||||
}
|
||||
// Or parse as immediate number?
|
||||
return 0;
|
||||
}
|
||||
|
||||
void codegen_expr(VM *vm, ExprNode *node);
|
||||
|
||||
void codegen_code_block(VM *vm, ExprNode *block) {
|
||||
for (size_t i = 0; i < block->child_count; ++i) {
|
||||
ExprNode *stmt = block->children[i];
|
||||
codegen_expr(vm, stmt);
|
||||
}
|
||||
}
|
||||
|
||||
static char *unwrap_string(const char *quoted_str) {
|
||||
if (!quoted_str)
|
||||
return NULL;
|
||||
|
||||
size_t len = strlen(quoted_str);
|
||||
if (len >= 2 && quoted_str[0] == '"' && quoted_str[len - 1] == '"') {
|
||||
// Remove quotes and process escape sequences
|
||||
const char *src = quoted_str + 1;
|
||||
size_t src_len = len - 2;
|
||||
|
||||
// First pass: calculate the actual length needed after escape processing
|
||||
size_t actual_len = 0;
|
||||
for (size_t i = 0; i < src_len; ++i) {
|
||||
if (src[i] == '\\' && i + 1 < src_len) {
|
||||
// Escape sequence
|
||||
actual_len++;
|
||||
i++; // Skip the next character
|
||||
} else {
|
||||
actual_len++;
|
||||
}
|
||||
}
|
||||
|
||||
char *unwrapped = (char *)malloc(actual_len + 1);
|
||||
size_t dst_idx = 0;
|
||||
|
||||
// Second pass: process escape sequences
|
||||
for (size_t i = 0; i < src_len; ++i) {
|
||||
if (src[i] == '\\' && i + 1 < src_len) {
|
||||
// Handle escape sequences
|
||||
switch (src[i + 1]) {
|
||||
case 'n': unwrapped[dst_idx++] = '\n'; break;
|
||||
case 't': unwrapped[dst_idx++] = '\t'; break;
|
||||
case 'r': unwrapped[dst_idx++] = '\r'; break;
|
||||
case '\\': unwrapped[dst_idx++] = '\\'; break;
|
||||
case '"': unwrapped[dst_idx++] = '"'; break;
|
||||
case '\'': unwrapped[dst_idx++] = '\''; break;
|
||||
default:
|
||||
// Unknown escape, keep both characters
|
||||
unwrapped[dst_idx++] = src[i];
|
||||
unwrapped[dst_idx++] = src[i + 1];
|
||||
break;
|
||||
}
|
||||
i++; // Skip the next character
|
||||
} else {
|
||||
unwrapped[dst_idx++] = src[i];
|
||||
}
|
||||
}
|
||||
unwrapped[dst_idx] = '\0';
|
||||
return unwrapped;
|
||||
}
|
||||
// Not quoted, return copy
|
||||
return strdup(quoted_str);
|
||||
}
|
||||
|
||||
void codegen_data_block(VM *vm, ExprNode *block) {
|
||||
for (size_t i = 0; i < block->child_count; ++i) {
|
||||
ExprNode *item = block->children[i];
|
||||
if (strcmp(item->token, "label") == 0 && item->child_count >= 2) {
|
||||
const char *name = item->children[0]->token;
|
||||
ExprNode *val = item->children[1];
|
||||
|
||||
if (val->child_count == 0) {
|
||||
if (strchr(val->token, '.')) {
|
||||
float f = atof(val->token);
|
||||
u32 addr = real_alloc(vm, f);
|
||||
add_label(name, addr);
|
||||
} else {
|
||||
// Assume string
|
||||
char *unwrapped = unwrap_string(val->token);
|
||||
u32 addr = str_alloc(vm, &vm->frames[vm->fp], unwrapped,
|
||||
strlen(unwrapped) + 1);
|
||||
free(unwrapped);
|
||||
add_label(name, addr);
|
||||
}
|
||||
} else {
|
||||
// Complex expression?
|
||||
fprintf(stderr, "Unsupported data item\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void codegen_expr(VM *vm, ExprNode *node) {
|
||||
if (node->child_count == 0)
|
||||
return;
|
||||
|
||||
const char *opname = node->token;
|
||||
|
||||
if (strcmp(opname, "label") == 0) {
|
||||
if (node->child_count < 2) {
|
||||
fprintf(stderr, "Error: label requires at least a name\n");
|
||||
return;
|
||||
}
|
||||
|
||||
const char *label_name = node->children[0]->token;
|
||||
add_label(label_name, vm->cp);
|
||||
|
||||
for (size_t i = 1; i < node->child_count; ++i) {
|
||||
codegen_expr(vm, node->children[i]);
|
||||
}
|
||||
} else if (strcmp(opname, "halt") == 0) {
|
||||
emit_opcode(vm, OP_HALT);
|
||||
} else if (strcmp(opname, "jump") == 0) {
|
||||
emit_opcode(vm, OP_JMP);
|
||||
u32 addr = find_label(node->children[0]->token);
|
||||
emit_u32(vm, addr);
|
||||
} else if (strcmp(opname, "jump-if-flag") == 0) {
|
||||
emit_opcode(vm, OP_JMPF);
|
||||
u32 addr = find_label(node->children[0]->token);
|
||||
emit_u32(vm, addr);
|
||||
} else if (strcmp(opname, "call") == 0) {
|
||||
emit_opcode(vm, OP_CALL);
|
||||
u32 addr = find_label(node->children[0]->token);
|
||||
emit_u32(vm, addr);
|
||||
} else if (strcmp(opname, "return") == 0) {
|
||||
emit_opcode(vm, OP_RETURN);
|
||||
} else if (strcmp(opname, "load") == 0) {
|
||||
emit_opcode(vm, OP_LOAD);
|
||||
int reg = parse_register(node->children[0]->token);
|
||||
u32 addr = parse_memory_ref(node->children[1]->token);
|
||||
emit_byte(vm, reg);
|
||||
emit_u32(vm, addr);
|
||||
} else if (strcmp(opname, "load-immediate") == 0) {
|
||||
emit_opcode(vm, OP_LOAD_IMM);
|
||||
int reg = parse_register(node->children[0]->token);
|
||||
if (strchr(node->children[1]->token, '&')) {
|
||||
u32 addr = parse_memory_ref(node->children[1]->token);
|
||||
emit_byte(vm, reg);
|
||||
emit_u32(vm, addr);
|
||||
} else {
|
||||
u32 val = (u32)atoi(node->children[1]->token);
|
||||
emit_byte(vm, reg);
|
||||
emit_u32(vm, val);
|
||||
}
|
||||
} else if (strcmp(opname, "store") == 0) {
|
||||
emit_opcode(vm, OP_STORE);
|
||||
int reg = parse_register(node->children[0]->token);
|
||||
u32 addr = parse_memory_ref(node->children[1]->token);
|
||||
emit_byte(vm, reg);
|
||||
emit_u32(vm, addr);
|
||||
} else if (strcmp(opname, "push") == 0) {
|
||||
emit_opcode(vm, OP_PUSH);
|
||||
int reg = parse_register(node->children[0]->token);
|
||||
emit_byte(vm, reg);
|
||||
} else if (strcmp(opname, "pop") == 0) {
|
||||
emit_opcode(vm, OP_POP);
|
||||
int reg = parse_register(node->children[0]->token);
|
||||
emit_byte(vm, reg);
|
||||
} else if (strcmp(opname, "register-move") == 0) {
|
||||
emit_opcode(vm, OP_REG_MOV);
|
||||
int dest = parse_register(node->children[0]->token);
|
||||
int src = parse_register(node->children[1]->token);
|
||||
emit_byte(vm, dest);
|
||||
emit_byte(vm, src);
|
||||
} else if (strcmp(opname, "syscall") == 0) {
|
||||
emit_opcode(vm, OP_SYSCALL);
|
||||
|
||||
// Parse syscall ID
|
||||
u32 syscall_id = 0;
|
||||
const char *syscall_name = node->children[0]->token;
|
||||
if (strcmp(syscall_name, "DEVICE-EXIT") == 0)
|
||||
syscall_id = SYSCALL_EXIT;
|
||||
else if (strcmp(syscall_name, "DEVICE-OPEN") == 0)
|
||||
syscall_id = SYSCALL_DEVICE_OPEN;
|
||||
else if (strcmp(syscall_name, "DEVICE-READ") == 0)
|
||||
syscall_id = SYSCALL_DEVICE_READ;
|
||||
else if (strcmp(syscall_name, "DEVICE-WRITE") == 0)
|
||||
syscall_id = SYSCALL_DEVICE_WRITE;
|
||||
else if (strcmp(syscall_name, "DEVICE-CLOSE") == 0)
|
||||
syscall_id = SYSCALL_DEVICE_CLOSE;
|
||||
else if (strcmp(syscall_name, "DEVICE-IOCTL") == 0)
|
||||
syscall_id = SYSCALL_DEVICE_IOCTL;
|
||||
|
||||
emit_u32(vm, syscall_id);
|
||||
|
||||
// Emit register arguments
|
||||
for (size_t i = 1; i < node->child_count; ++i) {
|
||||
int reg = parse_register(node->children[i]->token);
|
||||
emit_byte(vm, reg);
|
||||
}
|
||||
} else if (strcmp(opname, "add-int") == 0) {
|
||||
emit_opcode(vm, OP_ADD_INT);
|
||||
int dest = parse_register(node->children[0]->token);
|
||||
int src1 = parse_register(node->children[1]->token);
|
||||
int src2 = parse_register(node->children[2]->token);
|
||||
emit_byte(vm, dest);
|
||||
emit_byte(vm, src1);
|
||||
emit_byte(vm, src2);
|
||||
} else if (strcmp(opname, "sub-int") == 0) {
|
||||
emit_opcode(vm, OP_SUB_INT);
|
||||
int dest = parse_register(node->children[0]->token);
|
||||
int src1 = parse_register(node->children[1]->token);
|
||||
int src2 = parse_register(node->children[2]->token);
|
||||
emit_byte(vm, dest);
|
||||
emit_byte(vm, src1);
|
||||
emit_byte(vm, src2);
|
||||
} else if (strcmp(opname, "mul-int") == 0) {
|
||||
emit_opcode(vm, OP_MUL_INT);
|
||||
int dest = parse_register(node->children[0]->token);
|
||||
int src1 = parse_register(node->children[1]->token);
|
||||
int src2 = parse_register(node->children[2]->token);
|
||||
emit_byte(vm, dest);
|
||||
emit_byte(vm, src1);
|
||||
emit_byte(vm, src2);
|
||||
} else if (strcmp(opname, "div-int") == 0) {
|
||||
emit_opcode(vm, OP_DIV_INT);
|
||||
int dest = parse_register(node->children[0]->token);
|
||||
int src1 = parse_register(node->children[1]->token);
|
||||
int src2 = parse_register(node->children[2]->token);
|
||||
emit_byte(vm, dest);
|
||||
emit_byte(vm, src1);
|
||||
emit_byte(vm, src2);
|
||||
} else if (strcmp(opname, "add-nat") == 0) {
|
||||
emit_opcode(vm, OP_ADD_UINT);
|
||||
int dest = parse_register(node->children[0]->token);
|
||||
int src1 = parse_register(node->children[1]->token);
|
||||
int src2 = parse_register(node->children[2]->token);
|
||||
emit_byte(vm, dest);
|
||||
emit_byte(vm, src1);
|
||||
emit_byte(vm, src2);
|
||||
} else if (strcmp(opname, "sub-nat") == 0) {
|
||||
emit_opcode(vm, OP_SUB_UINT);
|
||||
int dest = parse_register(node->children[0]->token);
|
||||
int src1 = parse_register(node->children[1]->token);
|
||||
int src2 = parse_register(node->children[2]->token);
|
||||
emit_byte(vm, dest);
|
||||
emit_byte(vm, src1);
|
||||
emit_byte(vm, src2);
|
||||
} else if (strcmp(opname, "mul-nat") == 0) {
|
||||
emit_opcode(vm, OP_MUL_UINT);
|
||||
int dest = parse_register(node->children[0]->token);
|
||||
int src1 = parse_register(node->children[1]->token);
|
||||
int src2 = parse_register(node->children[2]->token);
|
||||
emit_byte(vm, dest);
|
||||
emit_byte(vm, src1);
|
||||
emit_byte(vm, src2);
|
||||
} else if (strcmp(opname, "div-nat") == 0) {
|
||||
emit_opcode(vm, OP_DIV_UINT);
|
||||
int dest = parse_register(node->children[0]->token);
|
||||
int src1 = parse_register(node->children[1]->token);
|
||||
int src2 = parse_register(node->children[2]->token);
|
||||
emit_byte(vm, dest);
|
||||
emit_byte(vm, src1);
|
||||
emit_byte(vm, src2);
|
||||
} else if (strcmp(opname, "add-real") == 0) {
|
||||
emit_opcode(vm, OP_ADD_REAL);
|
||||
int dest = parse_register(node->children[0]->token);
|
||||
int src1 = parse_register(node->children[1]->token);
|
||||
int src2 = parse_register(node->children[2]->token);
|
||||
emit_byte(vm, dest);
|
||||
emit_byte(vm, src1);
|
||||
emit_byte(vm, src2);
|
||||
} else if (strcmp(opname, "sub-real") == 0) {
|
||||
emit_opcode(vm, OP_SUB_REAL);
|
||||
int dest = parse_register(node->children[0]->token);
|
||||
int src1 = parse_register(node->children[1]->token);
|
||||
int src2 = parse_register(node->children[2]->token);
|
||||
emit_byte(vm, dest);
|
||||
emit_byte(vm, src1);
|
||||
emit_byte(vm, src2);
|
||||
} else if (strcmp(opname, "mul-real") == 0) {
|
||||
emit_opcode(vm, OP_MUL_REAL);
|
||||
int dest = parse_register(node->children[0]->token);
|
||||
int src1 = parse_register(node->children[1]->token);
|
||||
int src2 = parse_register(node->children[2]->token);
|
||||
emit_byte(vm, dest);
|
||||
emit_byte(vm, src1);
|
||||
emit_byte(vm, src2);
|
||||
} else if (strcmp(opname, "div-real") == 0) {
|
||||
emit_opcode(vm, OP_DIV_REAL);
|
||||
int dest = parse_register(node->children[0]->token);
|
||||
int src1 = parse_register(node->children[1]->token);
|
||||
int src2 = parse_register(node->children[2]->token);
|
||||
emit_byte(vm, dest);
|
||||
emit_byte(vm, src1);
|
||||
emit_byte(vm, src2);
|
||||
} else if (strcmp(opname, "int-to-real") == 0) {
|
||||
emit_opcode(vm, OP_INT_TO_REAL);
|
||||
int dest = parse_register(node->children[0]->token);
|
||||
int src = parse_register(node->children[1]->token);
|
||||
emit_byte(vm, dest);
|
||||
emit_byte(vm, src);
|
||||
} else if (strcmp(opname, "nat-to-real") == 0) {
|
||||
emit_opcode(vm, OP_UINT_TO_REAL);
|
||||
int dest = parse_register(node->children[0]->token);
|
||||
int src = parse_register(node->children[1]->token);
|
||||
emit_byte(vm, dest);
|
||||
emit_byte(vm, src);
|
||||
} else if (strcmp(opname, "real-to-int") == 0) {
|
||||
emit_opcode(vm, OP_REAL_TO_INT);
|
||||
int dest = parse_register(node->children[0]->token);
|
||||
int src = parse_register(node->children[1]->token);
|
||||
emit_byte(vm, dest);
|
||||
emit_byte(vm, src);
|
||||
} else if (strcmp(opname, "real-to-nat") == 0) {
|
||||
emit_opcode(vm, OP_REAL_TO_UINT);
|
||||
int dest = parse_register(node->children[0]->token);
|
||||
int src = parse_register(node->children[1]->token);
|
||||
emit_byte(vm, dest);
|
||||
emit_byte(vm, src);
|
||||
} else if (strcmp(opname, "jump-eq-int") == 0) {
|
||||
emit_opcode(vm, OP_JEQ_INT);
|
||||
u32 addr = find_label(node->children[0]->token);
|
||||
int src1 = parse_register(node->children[1]->token);
|
||||
int src2 = parse_register(node->children[2]->token);
|
||||
emit_u32(vm, addr);
|
||||
emit_byte(vm, src1);
|
||||
emit_byte(vm, src2);
|
||||
} else if (strcmp(opname, "jump-gt-int") == 0) {
|
||||
emit_opcode(vm, OP_JGT_INT);
|
||||
u32 addr = find_label(node->children[0]->token);
|
||||
int src1 = parse_register(node->children[1]->token);
|
||||
int src2 = parse_register(node->children[2]->token);
|
||||
emit_u32(vm, addr);
|
||||
emit_byte(vm, src1);
|
||||
emit_byte(vm, src2);
|
||||
} else if (strcmp(opname, "jump-lt-int") == 0) {
|
||||
emit_opcode(vm, OP_JLT_INT);
|
||||
u32 addr = find_label(node->children[0]->token);
|
||||
int src1 = parse_register(node->children[1]->token);
|
||||
int src2 = parse_register(node->children[2]->token);
|
||||
emit_u32(vm, addr);
|
||||
emit_byte(vm, src1);
|
||||
emit_byte(vm, src2);
|
||||
} else if (strcmp(opname, "jump-le-int") == 0) {
|
||||
emit_opcode(vm, OP_JLE_INT);
|
||||
u32 addr = find_label(node->children[0]->token);
|
||||
int src1 = parse_register(node->children[1]->token);
|
||||
int src2 = parse_register(node->children[2]->token);
|
||||
emit_u32(vm, addr);
|
||||
emit_byte(vm, src1);
|
||||
emit_byte(vm, src2);
|
||||
} else if (strcmp(opname, "jump-ge-int") == 0) {
|
||||
emit_opcode(vm, OP_JGE_INT);
|
||||
u32 addr = find_label(node->children[0]->token);
|
||||
int src1 = parse_register(node->children[1]->token);
|
||||
int src2 = parse_register(node->children[2]->token);
|
||||
emit_u32(vm, addr);
|
||||
emit_byte(vm, src1);
|
||||
emit_byte(vm, src2);
|
||||
} else if (strcmp(opname, "jump-eq-nat") == 0) {
|
||||
emit_opcode(vm, OP_JEQ_UINT);
|
||||
u32 addr = find_label(node->children[0]->token);
|
||||
int src1 = parse_register(node->children[1]->token);
|
||||
int src2 = parse_register(node->children[2]->token);
|
||||
emit_u32(vm, addr);
|
||||
emit_byte(vm, src1);
|
||||
emit_byte(vm, src2);
|
||||
} else if (strcmp(opname, "jump-gt-nat") == 0) {
|
||||
emit_opcode(vm, OP_JGT_UINT);
|
||||
u32 addr = find_label(node->children[0]->token);
|
||||
int src1 = parse_register(node->children[1]->token);
|
||||
int src2 = parse_register(node->children[2]->token);
|
||||
emit_u32(vm, addr);
|
||||
emit_byte(vm, src1);
|
||||
emit_byte(vm, src2);
|
||||
} else if (strcmp(opname, "jump-lt-nat") == 0) {
|
||||
emit_opcode(vm, OP_JLT_UINT);
|
||||
u32 addr = find_label(node->children[0]->token);
|
||||
int src1 = parse_register(node->children[1]->token);
|
||||
int src2 = parse_register(node->children[2]->token);
|
||||
emit_u32(vm, addr);
|
||||
emit_byte(vm, src1);
|
||||
emit_byte(vm, src2);
|
||||
} else if (strcmp(opname, "jump-le-nat") == 0) {
|
||||
emit_opcode(vm, OP_JLE_UINT);
|
||||
u32 addr = find_label(node->children[0]->token);
|
||||
int src1 = parse_register(node->children[1]->token);
|
||||
int src2 = parse_register(node->children[2]->token);
|
||||
emit_u32(vm, addr);
|
||||
emit_byte(vm, src1);
|
||||
emit_byte(vm, src2);
|
||||
} else if (strcmp(opname, "jump-ge-nat") == 0) {
|
||||
emit_opcode(vm, OP_JGE_UINT);
|
||||
u32 addr = find_label(node->children[0]->token);
|
||||
int src1 = parse_register(node->children[1]->token);
|
||||
int src2 = parse_register(node->children[2]->token);
|
||||
emit_u32(vm, addr);
|
||||
emit_byte(vm, src1);
|
||||
emit_byte(vm, src2);
|
||||
} else if (strcmp(opname, "jump-eq-real") == 0) {
|
||||
emit_opcode(vm, OP_JEQ_REAL);
|
||||
u32 addr = find_label(node->children[0]->token);
|
||||
int src1 = parse_register(node->children[1]->token);
|
||||
int src2 = parse_register(node->children[2]->token);
|
||||
emit_u32(vm, addr);
|
||||
emit_byte(vm, src1);
|
||||
emit_byte(vm, src2);
|
||||
} else if (strcmp(opname, "jump-gt-real") == 0) {
|
||||
emit_opcode(vm, OP_JGT_REAL);
|
||||
u32 addr = find_label(node->children[0]->token);
|
||||
int src1 = parse_register(node->children[1]->token);
|
||||
int src2 = parse_register(node->children[2]->token);
|
||||
emit_u32(vm, addr);
|
||||
emit_byte(vm, src1);
|
||||
emit_byte(vm, src2);
|
||||
} else if (strcmp(opname, "jump-lt-real") == 0) {
|
||||
emit_opcode(vm, OP_JLT_REAL);
|
||||
u32 addr = find_label(node->children[0]->token);
|
||||
int src1 = parse_register(node->children[1]->token);
|
||||
int src2 = parse_register(node->children[2]->token);
|
||||
emit_u32(vm, addr);
|
||||
emit_byte(vm, src1);
|
||||
emit_byte(vm, src2);
|
||||
} else if (strcmp(opname, "jump-le-real") == 0) {
|
||||
emit_opcode(vm, OP_JLE_REAL);
|
||||
u32 addr = find_label(node->children[0]->token);
|
||||
int src1 = parse_register(node->children[1]->token);
|
||||
int src2 = parse_register(node->children[2]->token);
|
||||
emit_u32(vm, addr);
|
||||
emit_byte(vm, src1);
|
||||
emit_byte(vm, src2);
|
||||
} else if (strcmp(opname, "jump-ge-real") == 0) {
|
||||
emit_opcode(vm, OP_JGE_REAL);
|
||||
u32 addr = find_label(node->children[0]->token);
|
||||
int src1 = parse_register(node->children[1]->token);
|
||||
int src2 = parse_register(node->children[2]->token);
|
||||
emit_u32(vm, addr);
|
||||
emit_byte(vm, src1);
|
||||
emit_byte(vm, src2);
|
||||
} else if (strcmp(opname, "string-length") == 0) {
|
||||
emit_opcode(vm, OP_STRLEN);
|
||||
int dest = parse_register(node->children[0]->token);
|
||||
int src = parse_register(node->children[1]->token);
|
||||
emit_byte(vm, dest);
|
||||
emit_byte(vm, src);
|
||||
} else if (strcmp(opname, "string-eq") == 0) {
|
||||
emit_opcode(vm, OP_STREQ);
|
||||
int dest = parse_register(node->children[0]->token);
|
||||
int src1 = parse_register(node->children[1]->token);
|
||||
int src2 = parse_register(node->children[2]->token);
|
||||
emit_byte(vm, dest);
|
||||
emit_byte(vm, src1);
|
||||
emit_byte(vm, src2);
|
||||
} else if (strcmp(opname, "string-concat") == 0) {
|
||||
emit_opcode(vm, OP_STRCAT);
|
||||
int dest = parse_register(node->children[0]->token);
|
||||
int src1 = parse_register(node->children[1]->token);
|
||||
int src2 = parse_register(node->children[2]->token);
|
||||
emit_byte(vm, dest);
|
||||
emit_byte(vm, src1);
|
||||
emit_byte(vm, src2);
|
||||
} else if (strcmp(opname, "string-get-char") == 0) {
|
||||
emit_opcode(vm, OP_STR_GET_CHAR);
|
||||
int dest = parse_register(node->children[0]->token);
|
||||
int src1 = parse_register(node->children[1]->token);
|
||||
int src2 = parse_register(node->children[2]->token);
|
||||
emit_byte(vm, dest);
|
||||
emit_byte(vm, src1);
|
||||
emit_byte(vm, src2);
|
||||
} else if (strcmp(opname, "string-find-char") == 0) {
|
||||
emit_opcode(vm, OP_STR_FIND_CHAR);
|
||||
int dest = parse_register(node->children[0]->token);
|
||||
int src1 = parse_register(node->children[1]->token);
|
||||
int src2 = parse_register(node->children[2]->token);
|
||||
emit_byte(vm, dest);
|
||||
emit_byte(vm, src1);
|
||||
emit_byte(vm, src2);
|
||||
} else if (strcmp(opname, "string-slice") == 0) {
|
||||
emit_opcode(vm, OP_STR_SLICE);
|
||||
int dest = parse_register(node->children[0]->token);
|
||||
int src1 = parse_register(node->children[1]->token);
|
||||
int src2 = parse_register(node->children[2]->token);
|
||||
int src3 = parse_register(node->children[3]->token);
|
||||
emit_byte(vm, dest);
|
||||
emit_byte(vm, src1);
|
||||
emit_byte(vm, src2);
|
||||
emit_byte(vm, src3);
|
||||
} else if (strcmp(opname, "int-to-string") == 0) {
|
||||
emit_opcode(vm, OP_INT_TO_STRING);
|
||||
int dest = parse_register(node->children[0]->token);
|
||||
int src = parse_register(node->children[1]->token);
|
||||
emit_byte(vm, dest);
|
||||
emit_byte(vm, src);
|
||||
} else if (strcmp(opname, "nat-to-string") == 0) {
|
||||
emit_opcode(vm, OP_UINT_TO_STRING);
|
||||
int dest = parse_register(node->children[0]->token);
|
||||
int src = parse_register(node->children[1]->token);
|
||||
emit_byte(vm, dest);
|
||||
emit_byte(vm, src);
|
||||
} else if (strcmp(opname, "real-to-string") == 0) {
|
||||
emit_opcode(vm, OP_REAL_TO_STRING);
|
||||
int dest = parse_register(node->children[0]->token);
|
||||
int src = parse_register(node->children[1]->token);
|
||||
emit_byte(vm, dest);
|
||||
emit_byte(vm, src);
|
||||
} else if (strcmp(opname, "string-to-int") == 0) {
|
||||
emit_opcode(vm, OP_STRING_TO_INT);
|
||||
int dest = parse_register(node->children[0]->token);
|
||||
int src = parse_register(node->children[1]->token);
|
||||
emit_byte(vm, dest);
|
||||
emit_byte(vm, src);
|
||||
} else if (strcmp(opname, "string-to-nat") == 0) {
|
||||
emit_opcode(vm, OP_STRING_TO_UINT);
|
||||
int dest = parse_register(node->children[0]->token);
|
||||
int src = parse_register(node->children[1]->token);
|
||||
emit_byte(vm, dest);
|
||||
emit_byte(vm, src);
|
||||
} else if (strcmp(opname, "string-to-real") == 0) {
|
||||
emit_opcode(vm, OP_STRING_TO_REAL);
|
||||
int dest = parse_register(node->children[0]->token);
|
||||
int src = parse_register(node->children[1]->token);
|
||||
emit_byte(vm, dest);
|
||||
emit_byte(vm, src);
|
||||
} else {
|
||||
fprintf(stderr, "Unknown opcode: %s\n", opname);
|
||||
}
|
||||
}
|
||||
|
||||
void assemble(VM *vm, ExprNode *program) {
|
||||
// First pass: process data section to define all labels
|
||||
for (size_t i = 0; i < program->child_count; ++i) {
|
||||
ExprNode *section = program->children[i];
|
||||
if (strcmp(section->token, "data") == 0) {
|
||||
codegen_data_block(vm, section);
|
||||
}
|
||||
}
|
||||
|
||||
// Second pass: process code section now that all labels are defined
|
||||
for (size_t i = 0; i < program->child_count; ++i) {
|
||||
ExprNode *section = program->children[i];
|
||||
if (strcmp(section->token, "code") == 0) {
|
||||
codegen_code_block(vm, section);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
#ifndef ASSEMBLER_H
|
||||
#define ASSEMBLER_H
|
||||
|
||||
#include "../vm/common.h"
|
||||
#include "../vm/vm.h"
|
||||
#include "parser.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#define AS_FIXED(v) ((float)(i32)(v) / 65536.0f)
|
||||
#define TO_FIXED(f) ((u32)((i32)( \
|
||||
((f) >= 0.0f) ? ((f) * 65536.0f + 0.5f) : ((f) * 65536.0f - 0.5f) \
|
||||
)))
|
||||
|
||||
typedef struct {
|
||||
char *name;
|
||||
u32 address;
|
||||
} Label;
|
||||
|
||||
void assemble(VM *vm, ExprNode *program);
|
||||
|
||||
#endif
|
|
@ -5,7 +5,7 @@
|
|||
#include <ctype.h>
|
||||
|
||||
// Helper function to allocate memory and handle errors
|
||||
static void *safe_malloc(size_t size) {
|
||||
void *safe_malloc(size_t size) {
|
||||
void *ptr = malloc(size);
|
||||
if (!ptr) {
|
||||
fprintf(stderr, "Memory allocation failed\n");
|
||||
|
|
|
@ -24,4 +24,6 @@ void expr_free(ExprNode *node);
|
|||
// Debug: print AST (for dev)
|
||||
void expr_print(ExprNode *node, int indent);
|
||||
|
||||
void *safe_malloc(size_t size);
|
||||
|
||||
#endif
|
166
src/tools/test.c
166
src/tools/test.c
|
@ -1,166 +0,0 @@
|
|||
#include "test.h"
|
||||
#include "../vm/opcodes.h"
|
||||
#include "../vm/vm.h"
|
||||
#include "string.h"
|
||||
#include <stdint.h>
|
||||
|
||||
u32 real_alloc(VM *vm, float v) {
|
||||
i32 fixed = TO_FIXED(v);
|
||||
u32 addr = vm->mp;
|
||||
write_u32(vm, memory, vm->mp, fixed);
|
||||
vm->mp += 4;
|
||||
vm->frames[vm->fp].end += 4;
|
||||
return addr;
|
||||
}
|
||||
|
||||
u32 nat_alloc(VM *vm, u32 v) {
|
||||
u32 addr = vm->mp;
|
||||
write_u32(vm, memory, vm->mp, v);
|
||||
vm->mp += 4;
|
||||
vm->frames[vm->fp].end += 4;
|
||||
return addr;
|
||||
}
|
||||
|
||||
u32 int_alloc(VM *vm, i32 v) {
|
||||
u32 addr = vm->mp;
|
||||
write_u32(vm, memory, vm->mp, v);
|
||||
vm->mp += 4;
|
||||
vm->frames[vm->fp].end += 4;
|
||||
return addr;
|
||||
}
|
||||
|
||||
/* Array of test mappings */
|
||||
struct TestMapping internal_tests[] = {
|
||||
{"simple.ul", test_simple_compile},
|
||||
{"window.ul", test_window_click_compile},
|
||||
{NULL, NULL} /* Sentinel to mark end of array */
|
||||
};
|
||||
|
||||
bool compile_internal_test(const char *filename, VM *vm) {
|
||||
i32 i;
|
||||
for (i = 0; internal_tests[i].filename != NULL; i++) {
|
||||
if (strcmp(internal_tests[i].filename, filename) == 0) {
|
||||
return internal_tests[i].test_func(vm);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool test_simple_compile(VM *vm) {
|
||||
u32 ptr;
|
||||
u32 newline_addr = str_alloc(vm, &vm->frames[vm->fp], "\n", 2);
|
||||
u32 terminal_path_addr =
|
||||
str_alloc(vm, &vm->frames[vm->fp], "/dev/term/0", 12);
|
||||
vm->code[vm->cp++] = OP_LOAD;
|
||||
vm->code[vm->cp++] = 0;
|
||||
ptr = real_alloc(vm, 1.0f);
|
||||
write_u32(vm, code, vm->cp, ptr);
|
||||
vm->cp += 4;
|
||||
|
||||
vm->code[vm->cp++] = OP_LOAD;
|
||||
vm->code[vm->cp++] = 1;
|
||||
ptr = real_alloc(vm, 2.0f);
|
||||
write_u32(vm, code, vm->cp, ptr);
|
||||
vm->cp += 4;
|
||||
|
||||
vm->code[vm->cp++] = OP_ADD_REAL;
|
||||
vm->code[vm->cp++] = 2;
|
||||
vm->code[vm->cp++] = 1;
|
||||
vm->code[vm->cp++] = 0; /* let sum = 1 + 2; */
|
||||
|
||||
vm->code[vm->cp++] = OP_REAL_TO_STRING;
|
||||
vm->code[vm->cp++] = 3;
|
||||
vm->code[vm->cp++] = 2;
|
||||
|
||||
vm->code[vm->cp++] = OP_STRLEN;
|
||||
vm->code[vm->cp++] = 4;
|
||||
vm->code[vm->cp++] = 3;
|
||||
|
||||
vm->code[vm->cp++] = OP_LOAD_IMM;
|
||||
vm->code[vm->cp++] = 5;
|
||||
write_u32(vm, code, vm->cp, terminal_path_addr);
|
||||
vm->cp += 4;
|
||||
|
||||
vm->code[vm->cp++] = OP_SYSCALL;
|
||||
write_u32(vm, code, vm->cp, AS_UINT(SYSCALL_DEVICE_WRITE));
|
||||
vm->cp += 4;
|
||||
vm->code[vm->cp++] = 5;
|
||||
vm->code[vm->cp++] = 3;
|
||||
vm->code[vm->cp++] = 4;
|
||||
|
||||
vm->code[vm->cp++] = OP_LOAD_IMM;
|
||||
vm->code[vm->cp++] = 6;
|
||||
write_u32(vm, code, vm->cp, newline_addr);
|
||||
vm->cp += 4;
|
||||
|
||||
vm->code[vm->cp++] = OP_STRLEN;
|
||||
vm->code[vm->cp++] = 7;
|
||||
vm->code[vm->cp++] = 6;
|
||||
|
||||
vm->code[vm->cp++] = OP_SYSCALL;
|
||||
write_u32(vm, code, vm->cp, AS_UINT(SYSCALL_DEVICE_WRITE));
|
||||
vm->cp += 4;
|
||||
vm->code[vm->cp++] = 5;
|
||||
vm->code[vm->cp++] = 6;
|
||||
vm->code[vm->cp++] = 7;
|
||||
|
||||
/* syscall_id=WRITE, device-str-ptr=5, ptr, length ; print(sum.toS()); */
|
||||
vm->code[vm->cp++] = OP_HALT; /* explicit halt */
|
||||
return true;
|
||||
}
|
||||
|
||||
bool test_window_click_compile(VM *vm) {
|
||||
u32 test_pixel_addr, loop_start,
|
||||
screen_path_addr =
|
||||
str_alloc(vm, &vm->frames[vm->fp], "/dev/screen/0", 14);
|
||||
|
||||
vm->code[vm->cp++] = OP_LOAD; /* R0 = screen path */
|
||||
vm->code[vm->cp++] = 0;
|
||||
vm->code[vm->cp++] = nat_alloc(vm, screen_path_addr);
|
||||
|
||||
vm->code[vm->cp++] = OP_LOAD; /* R1 = mode (0) */
|
||||
vm->code[vm->cp++] = 1;
|
||||
vm->code[vm->cp++] = int_alloc(vm, 0);
|
||||
|
||||
vm->code[vm->cp++] = OP_SYSCALL;
|
||||
vm->code[vm->cp++] = SYSCALL_DEVICE_OPEN;
|
||||
vm->code[vm->cp++] = 0;
|
||||
vm->code[vm->cp++] = 1;
|
||||
|
||||
test_pixel_addr = vm->mp;
|
||||
vm->memory[vm->mp++] = (char)((255 / 32) << 5) | ((0 / 32) << 2) | (0 / 64);
|
||||
vm->memory[vm->mp++] = (char)((255 / 32) << 5) | ((0 / 32) << 2) | (0 / 64);
|
||||
vm->memory[vm->mp++] = (char)((255 / 32) << 5) | ((0 / 32) << 2) | (0 / 64);
|
||||
vm->memory[vm->mp++] = (char)((255 / 32) << 5) | ((0 / 32) << 2) | (0 / 64);
|
||||
vm->frames[vm->fp].end += 4;
|
||||
|
||||
vm->code[vm->cp++] = OP_LOAD;
|
||||
vm->code[vm->cp++] = 0;
|
||||
vm->code[vm->cp++] = nat_alloc(vm, screen_path_addr);
|
||||
|
||||
vm->code[vm->cp++] = OP_LOAD;
|
||||
vm->code[vm->cp++] = 1;
|
||||
vm->code[vm->cp++] = nat_alloc(vm, test_pixel_addr);
|
||||
|
||||
vm->code[vm->cp++] = OP_LOAD;
|
||||
vm->code[vm->cp++] = 2;
|
||||
vm->code[vm->cp++] = int_alloc(vm, 1);
|
||||
|
||||
vm->code[vm->cp++] = OP_LOAD;
|
||||
vm->code[vm->cp++] = 3;
|
||||
loop_start = vm->cp + 2; /* here + after alloc */
|
||||
vm->code[vm->cp++] = nat_alloc(vm, loop_start);
|
||||
|
||||
vm->code[vm->cp++] = OP_SYSCALL;
|
||||
vm->code[vm->cp++] = SYSCALL_DEVICE_WRITE;
|
||||
vm->code[vm->cp++] = 0;
|
||||
vm->code[vm->cp++] = 1;
|
||||
vm->code[vm->cp++] = 2;
|
||||
|
||||
vm->code[vm->cp++] = OP_JMP;
|
||||
vm->code[vm->cp++] = 3;
|
||||
|
||||
vm->code[vm->cp++] = OP_HALT;
|
||||
|
||||
return true;
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
#ifndef ZRE_TEST_H
|
||||
#define ZRE_TEST_H
|
||||
|
||||
#include "../vm/opcodes.h"
|
||||
|
||||
#define AS_FIXED(v) ((float)(i32)(v) / 65536.0f)
|
||||
#define TO_FIXED(f) ((u32)((i32)( \
|
||||
((f) >= 0.0f) ? ((f) * 65536.0f + 0.5f) : ((f) * 65536.0f - 0.5f) \
|
||||
)))
|
||||
|
||||
/* Test function type definition */
|
||||
typedef bool (*TestFunction)(VM *vm);
|
||||
|
||||
/* Test mapping structure */
|
||||
struct TestMapping {
|
||||
const char* filename;
|
||||
TestFunction test_func;
|
||||
};
|
||||
|
||||
bool compile_internal_test(const char* filename, VM* vm);
|
||||
bool test_simple_compile (VM *vm);
|
||||
bool test_loop_compile (VM *vm);
|
||||
bool test_add_function_compile(VM *vm);
|
||||
bool test_recursive_function_compile(VM *vm);
|
||||
bool test_window_click_compile(VM *vm);
|
||||
|
||||
#endif
|
|
@ -8,7 +8,7 @@
|
|||
(int-to-string $1 $0)
|
||||
(load $3 &terminal-str)
|
||||
(string-length $2 $1)
|
||||
(syscall DEVICE-WRITE, $3, $1, $2)
|
||||
(syscall DEVICE-WRITE $3 $1 $2)
|
||||
(halt))
|
||||
|
||||
(label add
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
(pop $0)
|
||||
(int-to-string $1 $0)
|
||||
(load $2, &terminal-str)
|
||||
(strlen $4, $3)
|
||||
(string-length $4, $3)
|
||||
(syscall DEVICE-WRITE, $2, $1, $4)
|
||||
(halt))
|
||||
(label fib
|
||||
|
|
|
@ -2,11 +2,11 @@
|
|||
(label main
|
||||
(load $0 &terminal-str)
|
||||
(load $1 &hello-str)
|
||||
(strlen $2 $1)
|
||||
(string-length $2 $1)
|
||||
(syscall DEVICE_WRITE $0 $1 $2)
|
||||
(load $3 &new-line)
|
||||
(string-length $4 $3)
|
||||
(syscall DEVICE-WRITE, $0, $3, $4)
|
||||
(syscall DEVICE-WRITE $0 $3 $4)
|
||||
(halt)))
|
||||
(data
|
||||
(label terminal-str "/dev/term/0")
|
||||
|
|
|
@ -5,11 +5,11 @@
|
|||
(add-real $2 $1 $0)
|
||||
(real-to-string $3 $2)
|
||||
(string-length $4 $3)
|
||||
(load $5 &terminal-str)
|
||||
(syscall DEVICE-WRITE, $5, $3, $4)
|
||||
(load $6 &new-line)
|
||||
(load-immediate $5 &terminal-str)
|
||||
(syscall DEVICE-WRITE $5 $3 $4)
|
||||
(load-immediate $6 &new-line)
|
||||
(string-length $7 $6)
|
||||
(syscall DEVICE-WRITE, $5, $6, $7)
|
||||
(syscall DEVICE-WRITE $5 $6 $7)
|
||||
(halt)))
|
||||
(data (label terminal-str "/dev/term/0")
|
||||
(label new-line "\n")
|
||||
|
|
Loading…
Reference in New Issue