fix drawing, add ioctl for screen (wip), assembler fixes
This commit is contained in:
parent
7a42429cf2
commit
807d5b8705
4
Makefile
4
Makefile
|
@ -99,11 +99,11 @@ DEPS := $(VM_OBJS:.o=.d) $(PLATFORM_OBJ:.o=.d)
|
||||||
all: $(TARGET)
|
all: $(TARGET)
|
||||||
|
|
||||||
# 'debug' target — just set BUILD_MODE and build
|
# 'debug' target — just set BUILD_MODE and build
|
||||||
debug: BUILD_MODE = debug
|
debug: BUILD_MODE=debug
|
||||||
debug: $(TARGET)
|
debug: $(TARGET)
|
||||||
|
|
||||||
# 'release' target — just set BUILD_MODE and build
|
# 'release' target — just set BUILD_MODE and build
|
||||||
release: BUILD_MODE = release
|
release: BUILD_MODE=release
|
||||||
release: $(TARGET)
|
release: $(TARGET)
|
||||||
|
|
||||||
# --- COMPILE VM CORE (freestanding) ---
|
# --- COMPILE VM CORE (freestanding) ---
|
||||||
|
|
|
@ -1,54 +1,52 @@
|
||||||
#include "devices.h"
|
#include "devices.h"
|
||||||
#include <unistd.h>
|
#include <string.h>
|
||||||
#include <string.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
i32 console_open(void *data, u32 mode) {
|
i32 console_open(void *data, u32 mode) {
|
||||||
USED(mode);
|
USED(mode);
|
||||||
USED(data);
|
USED(data);
|
||||||
/* Nothing to open — stdin/stdout are always available */
|
/* Nothing to open — stdin/stdout are always available */
|
||||||
return 0; /* Success */
|
return 0; /* Success */
|
||||||
}
|
}
|
||||||
|
|
||||||
i32 console_read(void *data, u8 *buffer, u32 size) {
|
i32 console_read(void *data, u8 *buffer, u32 size) {
|
||||||
USED(data);
|
USED(data);
|
||||||
for (u32 i = 0; i < size; i++) {
|
for (u32 i = 0; i < size; i++) {
|
||||||
u8 ch = getchar();
|
u8 ch = getchar();
|
||||||
if (ch == '\0')
|
if (ch == '\0')
|
||||||
break;
|
break;
|
||||||
if (ch == '\n')
|
if (ch == '\n')
|
||||||
break;
|
break;
|
||||||
buffer[i] = ch;
|
buffer[i] = ch;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
i32 console_write(void *data, const u8 *buffer, u32 size) {
|
i32 console_write(void *data, const u8 *buffer, u32 size) {
|
||||||
USED(data);
|
USED(data);
|
||||||
for (u32 i = 0; i < size; i++) {
|
for (u32 i = 0; i < size; i++) {
|
||||||
putchar(buffer[i]);
|
putchar(buffer[i]);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
i32 console_close(void *data) {
|
i32 console_close(void *data) {
|
||||||
USED(data);
|
USED(data);
|
||||||
/* Nothing to close — stdin/stdout are process-owned */
|
/* Nothing to close — stdin/stdout are process-owned */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
i32 console_ioctl(void *data, u32 cmd, void *args) {
|
i32 console_ioctl(void *data, u32 cmd, void *args) {
|
||||||
USED(data);
|
USED(data);
|
||||||
USED(cmd);
|
USED(cmd);
|
||||||
USED(args);
|
USED(args);
|
||||||
return -1; /* Unsupported */
|
return -1; /* Unsupported */
|
||||||
}
|
}
|
||||||
|
|
||||||
i32 screen_open(void *data, u32 mode) {
|
i32 screen_open(void *data, u32 mode) {
|
||||||
USED(mode);
|
USED(mode);
|
||||||
ScreenDeviceData *screen = (ScreenDeviceData *)data;
|
ScreenDeviceData *screen = (ScreenDeviceData *)data;
|
||||||
|
|
||||||
|
|
||||||
screen->window =
|
screen->window =
|
||||||
SDL_CreateWindow("Reality Engine VM", SDL_WINDOWPOS_CENTERED,
|
SDL_CreateWindow("Reality Engine VM", SDL_WINDOWPOS_CENTERED,
|
||||||
SDL_WINDOWPOS_CENTERED, screen->width, screen->height,
|
SDL_WINDOWPOS_CENTERED, screen->width, screen->height,
|
||||||
|
@ -62,9 +60,9 @@ i32 screen_open(void *data, u32 mode) {
|
||||||
if (!screen->renderer)
|
if (!screen->renderer)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
screen->texture = SDL_CreateTexture(
|
screen->texture = SDL_CreateTexture(screen->renderer, SDL_PIXELFORMAT_RGB332,
|
||||||
screen->renderer, SDL_PIXELFORMAT_RGB332, SDL_TEXTUREACCESS_STREAMING,
|
SDL_TEXTUREACCESS_STREAMING,
|
||||||
screen->width, screen->height);
|
screen->width, screen->height);
|
||||||
if (!screen->texture)
|
if (!screen->texture)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
@ -72,21 +70,43 @@ i32 screen_open(void *data, u32 mode) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
i32 screen_read(void *data, u8 *buffer, u32 size) {
|
i32 screen_read(void *data, u8 *buffer, u32 size) {
|
||||||
USED(data);
|
USED(data);
|
||||||
USED(buffer);
|
USED(buffer);
|
||||||
USED(size);
|
USED(size);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
i32 screen_write(void *data, const u8 *buffer, u32 size) {
|
i32 screen_write(void *data, const u8 *buffer, u32 size) {
|
||||||
ScreenDeviceData *screen = (ScreenDeviceData *)data;
|
ScreenDeviceData *screen = (ScreenDeviceData *)data;
|
||||||
|
USED(buffer);
|
||||||
|
|
||||||
if (size > screen->framebuffer_size * sizeof(u8)) {
|
if (size > screen->framebuffer_size * sizeof(u8)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(&screen->vm->memory[screen->framebuffer_pos], buffer, size);
|
if (screen->texture && screen->renderer) {
|
||||||
|
SDL_UpdateTexture(screen->texture, nil,
|
||||||
|
&screen->vm->memory[screen->framebuffer_pos],
|
||||||
|
screen->width);
|
||||||
|
|
||||||
|
SDL_RenderClear(screen->renderer);
|
||||||
|
|
||||||
|
SDL_Rect output_rect;
|
||||||
|
SDL_RenderGetViewport(screen->renderer, &output_rect);
|
||||||
|
float scale_x = (float)output_rect.w / screen->width;
|
||||||
|
float scale_y = (float)output_rect.h / screen->height;
|
||||||
|
float scale = SDL_min(scale_x, scale_y);
|
||||||
|
|
||||||
|
SDL_Rect dstrect = {(i32)((output_rect.w - screen->width * scale) / 2),
|
||||||
|
(i32)((output_rect.h - screen->height * scale) / 2),
|
||||||
|
(i32)(screen->width * scale),
|
||||||
|
(i32)(screen->height * scale)};
|
||||||
|
|
||||||
|
SDL_RenderCopy(screen->renderer, screen->texture, nil, &dstrect);
|
||||||
|
SDL_RenderPresent(screen->renderer);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,11 +128,29 @@ i32 screen_close(void *data) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
i32 screen_ioctl(void *data, u32 cmd, void *args) {
|
||||||
|
ScreenDeviceData *screen = (ScreenDeviceData *)data;
|
||||||
|
|
||||||
|
switch (cmd) {
|
||||||
|
case IOCTL_GET_INFO: {
|
||||||
|
u32 *info = (u32 *)args;
|
||||||
|
memcpy(&screen->vm->memory[*info], &screen->framebuffer_pos, sizeof(u32));
|
||||||
|
memcpy(&screen->vm->memory[*info + 1], &screen->framebuffer_size, sizeof(u32));
|
||||||
|
memcpy(&screen->vm->memory[*info + 2], &screen->width, sizeof(u32));
|
||||||
|
memcpy(&screen->vm->memory[*info + 3], &screen->height, sizeof(u32));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
return -1; // Error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* MOUSE */
|
/* MOUSE */
|
||||||
i32 mouse_open(void *data, u32 mode) {
|
i32 mouse_open(void *data, u32 mode) {
|
||||||
USED(data);
|
USED(data);
|
||||||
USED(mode);
|
USED(mode);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
i32 mouse_read(void *data, u8 *buffer, u32 size) {
|
i32 mouse_read(void *data, u8 *buffer, u32 size) {
|
||||||
|
@ -129,22 +167,22 @@ i32 mouse_read(void *data, u8 *buffer, u32 size) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
i32 mouse_write(void *data, const u8 *buffer, u32 size) {
|
i32 mouse_write(void *data, const u8 *buffer, u32 size) {
|
||||||
USED(data);
|
USED(data);
|
||||||
USED(buffer);
|
USED(buffer);
|
||||||
USED(size);
|
USED(size);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
i32 mouse_close(void *data) {
|
i32 mouse_close(void *data) {
|
||||||
USED(data);
|
USED(data);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
i32 keyboard_open(void *data, u32 mode) {
|
i32 keyboard_open(void *data, u32 mode) {
|
||||||
USED(data);
|
USED(data);
|
||||||
USED(mode);
|
USED(mode);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
i32 keyboard_read(void *data, u8 *buffer, u32 size) {
|
i32 keyboard_read(void *data, u8 *buffer, u32 size) {
|
||||||
|
@ -164,7 +202,7 @@ i32 keyboard_write(void *data, const u8 *buffer, u32 size) {
|
||||||
return -1; /* not writable */
|
return -1; /* not writable */
|
||||||
}
|
}
|
||||||
|
|
||||||
i32 keyboard_close(void *data) {
|
i32 keyboard_close(void *data) {
|
||||||
USED(data);
|
USED(data);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
#include "../../vm/vm.h"
|
#include "../../vm/vm.h"
|
||||||
#include <SDL2/SDL.h>
|
#include <SDL2/SDL.h>
|
||||||
|
|
||||||
|
#define IOCTL_GET_INFO 0x01
|
||||||
|
|
||||||
/* Screen device data */
|
/* Screen device data */
|
||||||
typedef struct screen_device_data_s {
|
typedef struct screen_device_data_s {
|
||||||
u32 width;
|
u32 width;
|
||||||
|
@ -34,6 +36,7 @@ i32 screen_open(void *data, u32 mode);
|
||||||
i32 screen_read(void *data, u8 *buffer, u32 size);
|
i32 screen_read(void *data, u8 *buffer, u32 size);
|
||||||
i32 screen_write(void *data, const u8 *buffer, u32 size);
|
i32 screen_write(void *data, const u8 *buffer, u32 size);
|
||||||
i32 screen_close(void *data);
|
i32 screen_close(void *data);
|
||||||
|
i32 screen_ioctl(void *data, u32 cmd, void *args);
|
||||||
|
|
||||||
i32 mouse_open(void *data, u32 mode);
|
i32 mouse_open(void *data, u32 mode);
|
||||||
i32 mouse_read(void *data, u8 *buffer, u32 size);
|
i32 mouse_read(void *data, u8 *buffer, u32 size);
|
||||||
|
|
|
@ -14,7 +14,7 @@ static DeviceOps screen_ops = {.open = screen_open,
|
||||||
.read = screen_read,
|
.read = screen_read,
|
||||||
.write = screen_write,
|
.write = screen_write,
|
||||||
.close = screen_close,
|
.close = screen_close,
|
||||||
.ioctl = nil};
|
.ioctl = screen_ioctl};
|
||||||
|
|
||||||
static DeviceOps mouse_ops = {.open = mouse_open,
|
static DeviceOps mouse_ops = {.open = mouse_open,
|
||||||
.read = mouse_read,
|
.read = mouse_read,
|
||||||
|
@ -242,7 +242,10 @@ void register_sdl_devices(VM *vm) {
|
||||||
screen_data.height = 480;
|
screen_data.height = 480;
|
||||||
screen_data.framebuffer_size = 640 * 480;
|
screen_data.framebuffer_size = 640 * 480;
|
||||||
screen_data.framebuffer_pos = vm->mp;
|
screen_data.framebuffer_pos = vm->mp;
|
||||||
vm->mp += screen_data.framebuffer_size / 4; /* advance memory pointer */
|
vm->mp += screen_data.framebuffer_size; /* advance memory pointer */
|
||||||
|
vm->frames[vm->fp].end = vm->mp;
|
||||||
|
|
||||||
|
printf("%d\n", screen_data.framebuffer_pos );
|
||||||
|
|
||||||
vm_register_device(vm, "/dev/screen/0", "screen", &screen_data, &screen_ops);
|
vm_register_device(vm, "/dev/screen/0", "screen", &screen_data, &screen_ops);
|
||||||
|
|
||||||
|
@ -292,9 +295,6 @@ i32 main(i32 argc, char *argv[]) {
|
||||||
|
|
||||||
VM vm = {0};
|
VM vm = {0};
|
||||||
|
|
||||||
// Register terminal device first
|
|
||||||
vm_register_device(&vm, "/dev/term/0", "terminal", nil, &console_device_ops);
|
|
||||||
|
|
||||||
bool compilation_success = true;
|
bool compilation_success = true;
|
||||||
if (input_file) {
|
if (input_file) {
|
||||||
if (is_rom) {
|
if (is_rom) {
|
||||||
|
@ -330,6 +330,8 @@ i32 main(i32 argc, char *argv[]) {
|
||||||
|
|
||||||
bool running = true;
|
bool running = true;
|
||||||
|
|
||||||
|
vm_register_device(&vm, "/dev/term/0", "terminal", nil, &console_device_ops);
|
||||||
|
|
||||||
if (gui_mode) {
|
if (gui_mode) {
|
||||||
register_sdl_devices(&vm);
|
register_sdl_devices(&vm);
|
||||||
|
|
||||||
|
@ -375,35 +377,6 @@ i32 main(i32 argc, char *argv[]) {
|
||||||
}
|
}
|
||||||
|
|
||||||
step_vm(&vm);
|
step_vm(&vm);
|
||||||
|
|
||||||
for (u32 i = 0; i < vm.dc; i++) {
|
|
||||||
Device *dev = &vm.devices[i];
|
|
||||||
if (strcmp(dev->type, "screen") == 0) {
|
|
||||||
ScreenDeviceData *screen = (ScreenDeviceData *)dev->data;
|
|
||||||
if (screen->texture && screen->renderer) {
|
|
||||||
SDL_UpdateTexture(screen->texture, nil,
|
|
||||||
&vm.memory[screen->framebuffer_pos],
|
|
||||||
screen->width * sizeof(u32));
|
|
||||||
|
|
||||||
SDL_RenderClear(screen->renderer);
|
|
||||||
|
|
||||||
SDL_Rect output_rect;
|
|
||||||
SDL_RenderGetViewport(screen->renderer, &output_rect);
|
|
||||||
float scale_x = (float)output_rect.w / screen->width;
|
|
||||||
float scale_y = (float)output_rect.h / screen->height;
|
|
||||||
float scale = SDL_min(scale_x, scale_y);
|
|
||||||
|
|
||||||
SDL_Rect dstrect = {
|
|
||||||
(i32)((output_rect.w - screen->width * scale) / 2),
|
|
||||||
(i32)((output_rect.h - screen->height * scale) / 2),
|
|
||||||
(i32)(screen->width * scale), (i32)(screen->height * scale)};
|
|
||||||
|
|
||||||
SDL_RenderCopy(screen->renderer, screen->texture, nil, &dstrect);
|
|
||||||
SDL_RenderPresent(screen->renderer);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
while (running) {
|
while (running) {
|
||||||
|
|
|
@ -76,8 +76,8 @@ int get_instruction_byte_size(ExprNode *node) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register-based opcodes (2 bytes: opcode + register)
|
// Register-based opcodes (2 bytes: opcode + register)
|
||||||
if (strcmp(opname, "pop") == 0 || strcmp(opname, "push") == 0 ||
|
if (strcmp(opname, "pop") == 0 || strcmp(opname, "jump-if-flag") == 0 ||
|
||||||
strcmp(opname, "jump") == 0 || strcmp(opname, "jump-if-flag") == 0) {
|
strcmp(opname, "jump") == 0 || strcmp(opname, "push") == 0) {
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,19 +89,14 @@ int get_instruction_byte_size(ExprNode *node) {
|
||||||
strcmp(opname, "real-to-int") == 0 ||
|
strcmp(opname, "real-to-int") == 0 ||
|
||||||
strcmp(opname, "real-to-nat") == 0 || strcmp(opname, "int-to-nat") == 0 ||
|
strcmp(opname, "real-to-nat") == 0 || strcmp(opname, "int-to-nat") == 0 ||
|
||||||
strcmp(opname, "nat-to-int") == 0 ||
|
strcmp(opname, "nat-to-int") == 0 ||
|
||||||
strcmp(opname, "string-length") == 0) {
|
strcmp(opname, "string-length") == 0 || strcmp(opname, "load") == 0 ||
|
||||||
|
strcmp(opname, "store") == 0 || strcmp(opname, "load-u8") == 0 ||
|
||||||
|
strcmp(opname, "load-i8") == 0 || strcmp(opname, "store-8") == 0 ||
|
||||||
|
strcmp(opname, "load-u16") == 0 || strcmp(opname, "load-i16") == 0 ||
|
||||||
|
strcmp(opname, "store-16") == 0 || strcmp(opname, "register-move") == 0) {
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load/store with register and address (5 bytes: 1 + 1 + 4)
|
|
||||||
if (strcmp(opname, "load") == 0 || strcmp(opname, "store") == 0 ||
|
|
||||||
strcmp(opname, "load-u8") == 0 || strcmp(opname, "load-i8") == 0 ||
|
|
||||||
strcmp(opname, "store-8") == 0 || strcmp(opname, "load-u16") == 0 ||
|
|
||||||
strcmp(opname, "load-i16") == 0 || strcmp(opname, "store-16") == 0 ||
|
|
||||||
strcmp(opname, "call") == 0) {
|
|
||||||
return 5;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Register-register-register opcodes (4 bytes: 1 + 3)
|
// Register-register-register opcodes (4 bytes: 1 + 3)
|
||||||
if (strcmp(opname, "add-int") == 0 || strcmp(opname, "sub-int") == 0 ||
|
if (strcmp(opname, "add-int") == 0 || strcmp(opname, "sub-int") == 0 ||
|
||||||
strcmp(opname, "mul-int") == 0 || strcmp(opname, "div-int") == 0 ||
|
strcmp(opname, "mul-int") == 0 || strcmp(opname, "div-int") == 0 ||
|
||||||
|
@ -116,9 +111,13 @@ int get_instruction_byte_size(ExprNode *node) {
|
||||||
return 4;
|
return 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load, Load-immediate (5 bytes: 1 + 1 + 4)
|
// (5 bytes: 1 + 4)
|
||||||
if (strcmp(opname, "load-immediate") == 0 || strcmp(opname, "load") == 0 ||
|
if (strcmp(opname, "call") == 0) {
|
||||||
strcmp(opname, "store") == 0) {
|
return 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load, Load-immediate (6 bytes: 1 + 1 + 4)
|
||||||
|
if (strcmp(opname, "load-immediate") == 0) {
|
||||||
return 6;
|
return 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -163,12 +162,16 @@ void collect_symbols_in_node(SymbolTable *table, ExprNode *node,
|
||||||
for (int i = 0; i < depth; i++)
|
for (int i = 0; i < depth; i++)
|
||||||
strcat(indent, " ");
|
strcat(indent, " ");
|
||||||
|
|
||||||
// printf("%s%d %s ", indent, *current_addr, node->token);
|
#ifdef ASM_DEBUG
|
||||||
|
printf("%s%d %s ", indent, *current_addr, node->token);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (strcmp(node->token, "label") == 0) {
|
if (strcmp(node->token, "label") == 0) {
|
||||||
if (node->child_count >= 1) {
|
if (node->child_count >= 1) {
|
||||||
const char *name = node->children[0]->token;
|
const char *name = node->children[0]->token;
|
||||||
// printf(" %s -> %d\n", name, *current_addr);
|
#ifdef ASM_DEBUG
|
||||||
|
printf(" %s -> %d\n", name, *current_addr);
|
||||||
|
#endif
|
||||||
symbol_table_add(table, name, *current_addr, SYMBOL_CODE);
|
symbol_table_add(table, name, *current_addr, SYMBOL_CODE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -179,8 +182,9 @@ void collect_symbols_in_node(SymbolTable *table, ExprNode *node,
|
||||||
} else {
|
} else {
|
||||||
int size = get_instruction_byte_size(node);
|
int size = get_instruction_byte_size(node);
|
||||||
*current_addr += size;
|
*current_addr += size;
|
||||||
// printf(" +%d bytes -> %d\n", size, *current_addr);
|
#ifdef ASM_DEBUG
|
||||||
// printf("\n");
|
printf(" +%d bytes -> %d\n", size, *current_addr);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -242,15 +246,37 @@ int parse_register(const char *reg_str) {
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 resolve_symbol(SymbolTable *table, const char *ref) {
|
u32 resolve_symbol(SymbolTable *table, const char *ref) {
|
||||||
|
// Handle symbol references (e.g., &label)
|
||||||
if (ref[0] == '&') {
|
if (ref[0] == '&') {
|
||||||
return find_label_in_table(table, ref + 1);
|
return find_label_in_table(table, ref + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle immediate values
|
// Handle fixed-point numbers (e.g., 0.5)
|
||||||
if (strchr(ref, '.')) {
|
if (strchr(ref, '.')) {
|
||||||
return TO_FIXED(atof(ref));
|
return TO_FIXED(atof(ref));
|
||||||
}
|
}
|
||||||
return (u32)atoi(ref);
|
|
||||||
|
// Handle hexadecimal literals (e.g., 0x7)
|
||||||
|
if (ref[0] == '0' && (ref[1] == 'x' || ref[1] == 'X')) {
|
||||||
|
char *endptr;
|
||||||
|
u32 value = (u32)strtoul(ref + 2, &endptr, 16); // Skip "0x"
|
||||||
|
|
||||||
|
if (endptr == ref + 2 || *endptr != '\0') {
|
||||||
|
fprintf(stderr, "Invalid hex literal: %s\n", ref);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle decimal literals (e.g., 7)
|
||||||
|
char *endptr;
|
||||||
|
u32 value = (u32)strtoul(ref, &endptr, 10);
|
||||||
|
|
||||||
|
if (endptr == ref || *endptr != '\0') {
|
||||||
|
fprintf(stderr, "Invalid decimal literal: %s\n", ref);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *unwrap_string(const char *quoted_str) {
|
static char *unwrap_string(const char *quoted_str) {
|
||||||
|
@ -327,26 +353,59 @@ void process_data_block(VM *vm, SymbolTable *table, ExprNode *block) {
|
||||||
ExprNode *val = item->children[1];
|
ExprNode *val = item->children[1];
|
||||||
|
|
||||||
if (val->child_count == 0) {
|
if (val->child_count == 0) {
|
||||||
if (strchr(val->token, '.')) {
|
const char *token = val->token;
|
||||||
float f = atof(val->token);
|
|
||||||
u32 addr = allocate_data(vm, table, name, 4);
|
// Case 1: String literal (enclosed in quotes)
|
||||||
write_u32(vm, memory, addr, TO_FIXED(f));
|
if (token[0] == '"' && token[strlen(token) - 1] == '"') {
|
||||||
} else {
|
char *unwrapped = unwrap_string(token);
|
||||||
// unwrap deals with control characters and "" literals
|
int len = strlen(unwrapped) + 1;
|
||||||
char *unwrapped = unwrap_string(val->token);
|
|
||||||
int len = strlen(unwrapped) + 1; // Include length + null terminator
|
|
||||||
u32 addr = allocate_data(vm, table, name, len + 4);
|
u32 addr = allocate_data(vm, table, name, len + 4);
|
||||||
|
|
||||||
write_u32(vm, memory, addr, len);
|
write_u32(vm, memory, addr, len);
|
||||||
// Copy string to memory
|
|
||||||
for (int i = 0; i < len; i++) {
|
for (int i = 0; i < len; i++) {
|
||||||
write_u8(vm, memory, addr + 4 + i, unwrapped[i]);
|
write_u8(vm, memory, addr + 4 + i, unwrapped[i]);
|
||||||
}
|
}
|
||||||
|
vm->mp += 4 + len;
|
||||||
free(unwrapped);
|
free(unwrapped);
|
||||||
}
|
}
|
||||||
|
// Case 2: Hexadecimal integer (0x...)
|
||||||
|
else if (token[0] == '0' && (token[1] == 'x' || token[1] == 'X')) {
|
||||||
|
char *endptr;
|
||||||
|
u32 value = (u32)strtoul(token + 2, &endptr, 16);
|
||||||
|
|
||||||
|
if (endptr != token + strlen(token)) {
|
||||||
|
fprintf(stderr, "Invalid hex in data block: %s\n", token);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 addr = allocate_data(vm, table, name, 4);
|
||||||
|
write_u32(vm, memory, addr, value);
|
||||||
|
vm->mp += 4;
|
||||||
|
}
|
||||||
|
// Case 3: Floating-point (has decimal point)
|
||||||
|
else if (strchr(token, '.')) {
|
||||||
|
float f = atof(token);
|
||||||
|
u32 addr = allocate_data(vm, table, name, 4);
|
||||||
|
write_u32(vm, memory, addr, TO_FIXED(f));
|
||||||
|
vm->mp += 4;
|
||||||
|
}
|
||||||
|
// Case 4: Decimal integer
|
||||||
|
else {
|
||||||
|
char *endptr;
|
||||||
|
u32 value = (u32)strtoul(token, &endptr, 10);
|
||||||
|
|
||||||
|
if (endptr != token + strlen(token)) {
|
||||||
|
fprintf(stderr, "Invalid decimal in data block: %s\n", token);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 addr = allocate_data(vm, table, name, 4);
|
||||||
|
write_u32(vm, memory, addr, value);
|
||||||
|
vm->mp += 4;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "Unsupported data item\n");
|
fprintf(stderr, "Unsupported data item\n");
|
||||||
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -374,24 +433,60 @@ void process_code_expr(VM *vm, SymbolTable *table, ExprNode *node) {
|
||||||
emit_u32(vm, addr);
|
emit_u32(vm, addr);
|
||||||
} else if (strcmp(opname, "return") == 0) {
|
} else if (strcmp(opname, "return") == 0) {
|
||||||
emit_opcode(vm, OP_RETURN);
|
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 = resolve_symbol(table, node->children[1]->token);
|
|
||||||
emit_byte(vm, reg);
|
|
||||||
emit_u32(vm, addr);
|
|
||||||
} else if (strcmp(opname, "load-immediate") == 0) {
|
} else if (strcmp(opname, "load-immediate") == 0) {
|
||||||
emit_opcode(vm, OP_LOAD_IMM);
|
emit_opcode(vm, OP_LOAD_IMM);
|
||||||
int reg = parse_register(node->children[0]->token);
|
int reg = parse_register(node->children[0]->token);
|
||||||
u32 addr = resolve_symbol(table, node->children[1]->token);
|
u32 addr = resolve_symbol(table, node->children[1]->token);
|
||||||
emit_byte(vm, reg);
|
emit_byte(vm, reg);
|
||||||
emit_u32(vm, addr);
|
emit_u32(vm, addr);
|
||||||
|
} else if (strcmp(opname, "load") == 0) {
|
||||||
|
emit_opcode(vm, OP_LOAD);
|
||||||
|
int dest = parse_register(node->children[0]->token);
|
||||||
|
int src1 = parse_register(node->children[1]->token);
|
||||||
|
emit_byte(vm, dest);
|
||||||
|
emit_byte(vm, src1);
|
||||||
|
} else if (strcmp(opname, "load-i8") == 0) {
|
||||||
|
emit_opcode(vm, OP_LOADI8);
|
||||||
|
int dest = parse_register(node->children[0]->token);
|
||||||
|
int src1 = parse_register(node->children[1]->token);
|
||||||
|
emit_byte(vm, dest);
|
||||||
|
emit_byte(vm, src1);
|
||||||
|
} else if (strcmp(opname, "load-u8") == 0) {
|
||||||
|
emit_opcode(vm, OP_LOADU8);
|
||||||
|
int dest = parse_register(node->children[0]->token);
|
||||||
|
int src1 = parse_register(node->children[1]->token);
|
||||||
|
emit_byte(vm, dest);
|
||||||
|
emit_byte(vm, src1);
|
||||||
|
} else if (strcmp(opname, "load-u16") == 0) {
|
||||||
|
emit_opcode(vm, OP_LOADU16);
|
||||||
|
int dest = parse_register(node->children[0]->token);
|
||||||
|
int src1 = parse_register(node->children[1]->token);
|
||||||
|
emit_byte(vm, dest);
|
||||||
|
emit_byte(vm, src1);
|
||||||
|
} else if (strcmp(opname, "load-i16") == 0) {
|
||||||
|
emit_opcode(vm, OP_LOADI16);
|
||||||
|
int dest = parse_register(node->children[0]->token);
|
||||||
|
int src1 = parse_register(node->children[1]->token);
|
||||||
|
emit_byte(vm, dest);
|
||||||
|
emit_byte(vm, src1);
|
||||||
} else if (strcmp(opname, "store") == 0) {
|
} else if (strcmp(opname, "store") == 0) {
|
||||||
emit_opcode(vm, OP_STORE);
|
emit_opcode(vm, OP_STORE);
|
||||||
int reg = parse_register(node->children[0]->token);
|
int dest = parse_register(node->children[0]->token);
|
||||||
u32 addr = resolve_symbol(table, node->children[1]->token);
|
int src1 = parse_register(node->children[1]->token);
|
||||||
emit_byte(vm, reg);
|
emit_byte(vm, dest);
|
||||||
emit_u32(vm, addr);
|
emit_byte(vm, src1);
|
||||||
|
} else if (strcmp(opname, "store-8") == 0) {
|
||||||
|
emit_opcode(vm, OP_STORE8);
|
||||||
|
int dest = parse_register(node->children[0]->token);
|
||||||
|
int src1 = parse_register(node->children[1]->token);
|
||||||
|
emit_byte(vm, dest);
|
||||||
|
emit_byte(vm, src1);
|
||||||
|
} else if (strcmp(opname, "store-16") == 0) {
|
||||||
|
emit_opcode(vm, OP_STORE16);
|
||||||
|
int dest = parse_register(node->children[0]->token);
|
||||||
|
int src1 = parse_register(node->children[1]->token);
|
||||||
|
emit_byte(vm, dest);
|
||||||
|
emit_byte(vm, src1);
|
||||||
} else if (strcmp(opname, "push") == 0) {
|
} else if (strcmp(opname, "push") == 0) {
|
||||||
emit_opcode(vm, OP_PUSH);
|
emit_opcode(vm, OP_PUSH);
|
||||||
int reg = parse_register(node->children[0]->token);
|
int reg = parse_register(node->children[0]->token);
|
||||||
|
@ -432,6 +527,54 @@ void process_code_expr(VM *vm, SymbolTable *table, ExprNode *node) {
|
||||||
int reg = parse_register(node->children[i]->token);
|
int reg = parse_register(node->children[i]->token);
|
||||||
emit_byte(vm, reg);
|
emit_byte(vm, reg);
|
||||||
}
|
}
|
||||||
|
} else if (strcmp(opname, "bit-shift-left") == 0) {
|
||||||
|
emit_opcode(vm, OP_SLL);
|
||||||
|
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, "bit-shift-right") == 0) {
|
||||||
|
emit_opcode(vm, OP_SRL);
|
||||||
|
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, "bit-shift-right-extend") == 0) {
|
||||||
|
emit_opcode(vm, OP_SRE);
|
||||||
|
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, "bit-and") == 0) {
|
||||||
|
emit_opcode(vm, OP_BAND);
|
||||||
|
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, "bit-or") == 0) {
|
||||||
|
emit_opcode(vm, OP_BOR);
|
||||||
|
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, "bit-xor") == 0) {
|
||||||
|
emit_opcode(vm, OP_BXOR);
|
||||||
|
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-int") == 0) {
|
} else if (strcmp(opname, "add-int") == 0) {
|
||||||
emit_opcode(vm, OP_ADD_INT);
|
emit_opcode(vm, OP_ADD_INT);
|
||||||
int dest = parse_register(node->children[0]->token);
|
int dest = parse_register(node->children[0]->token);
|
||||||
|
@ -780,14 +923,18 @@ void assemble(VM *vm, ExprNode *program) {
|
||||||
for (size_t i = 0; i < program->child_count; ++i) {
|
for (size_t i = 0; i < program->child_count; ++i) {
|
||||||
ExprNode *section = program->children[i];
|
ExprNode *section = program->children[i];
|
||||||
if (strcmp(section->token, "code") == 0) {
|
if (strcmp(section->token, "code") == 0) {
|
||||||
for (size_t i = 0; i < section->child_count; ++i) {
|
for (size_t j = 0; j < section->child_count; ++j) {
|
||||||
process_code_expr(vm, &table, section->children[i]);
|
process_code_expr(vm, &table, section->children[j]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cleanup symbol table
|
// Cleanup symbol table
|
||||||
for (int i = 0; i < table.count; i++) {
|
for (int i = 0; i < table.count; i++) {
|
||||||
|
#ifdef ASM_DEBUG
|
||||||
|
Symbol s = table.symbols[i];
|
||||||
|
printf("%s[%d]\n", s.name, s.address);
|
||||||
|
#endif
|
||||||
free(table.symbols[i].name);
|
free(table.symbols[i].name);
|
||||||
}
|
}
|
||||||
free(table.symbols);
|
free(table.symbols);
|
||||||
|
|
94
src/vm/vm.c
94
src/vm/vm.c
|
@ -37,19 +37,17 @@
|
||||||
return true; \
|
return true; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define BIT_OP(op) \
|
#define BIT_OP(op) \
|
||||||
do { \
|
do { \
|
||||||
dest = read_u8(vm, code, vm->pc); \
|
dest = read_u8(vm, code, vm->pc); \
|
||||||
vm->pc++; \
|
vm->pc++; \
|
||||||
src1 = read_u8(vm, code, vm->pc); \
|
src1 = read_u8(vm, code, vm->pc); \
|
||||||
vm->pc++; \
|
vm->pc++; \
|
||||||
src2 = read_u8(vm, code, vm->pc); \
|
src2 = read_u8(vm, code, vm->pc); \
|
||||||
vm->pc++; \
|
vm->pc++; \
|
||||||
frame->registers[dest] = \
|
frame->registers[dest] = frame->registers[src1] op frame->registers[src2]; \
|
||||||
frame->registers[src1] op frame->registers[src2]; \
|
return true; \
|
||||||
return true; \
|
} while (0)
|
||||||
} while (0)
|
|
||||||
|
|
||||||
|
|
||||||
u32 str_alloc(VM *vm, Frame *frame, const char *str, u32 length) {
|
u32 str_alloc(VM *vm, Frame *frame, const char *str, u32 length) {
|
||||||
u32 str_addr = vm->mp;
|
u32 str_addr = vm->mp;
|
||||||
|
@ -110,8 +108,10 @@ bool step_vm(VM *vm) {
|
||||||
case OP_LOAD: {
|
case OP_LOAD: {
|
||||||
dest = read_u8(vm, code, vm->pc);
|
dest = read_u8(vm, code, vm->pc);
|
||||||
vm->pc++;
|
vm->pc++;
|
||||||
ptr = read_u32(vm, code, vm->pc);
|
src1 = read_u8(vm, code, vm->pc);
|
||||||
vm->pc += 4;
|
vm->pc++;
|
||||||
|
v = frame->registers[src1];
|
||||||
|
ptr = frame->registers[dest];
|
||||||
v = read_u32(vm, memory, ptr);
|
v = read_u32(vm, memory, ptr);
|
||||||
frame->registers[dest] = v;
|
frame->registers[dest] = v;
|
||||||
return true;
|
return true;
|
||||||
|
@ -120,28 +120,33 @@ bool step_vm(VM *vm) {
|
||||||
i8 v8;
|
i8 v8;
|
||||||
dest = read_u8(vm, code, vm->pc);
|
dest = read_u8(vm, code, vm->pc);
|
||||||
vm->pc++;
|
vm->pc++;
|
||||||
ptr = read_u32(vm, code, vm->pc);
|
src1 = read_u8(vm, code, vm->pc);
|
||||||
vm->pc += 4;
|
vm->pc++;
|
||||||
|
v = frame->registers[src1];
|
||||||
|
ptr = frame->registers[dest];
|
||||||
v8 = (i8)read_u8(vm, memory, ptr);
|
v8 = (i8)read_u8(vm, memory, ptr);
|
||||||
frame->registers[dest] = v8;
|
frame->registers[ptr] = v8;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case OP_LOADU8: {
|
case OP_LOADU8: {
|
||||||
u8 v8;
|
u8 v8;
|
||||||
dest = read_u8(vm, code, vm->pc);
|
dest = read_u8(vm, code, vm->pc);
|
||||||
vm->pc++;
|
vm->pc++;
|
||||||
ptr = read_u32(vm, code, vm->pc);
|
src1 = read_u8(vm, code, vm->pc);
|
||||||
vm->pc += 4;
|
vm->pc++;
|
||||||
|
ptr = frame->registers[src1];
|
||||||
v8 = read_u8(vm, memory, ptr);
|
v8 = read_u8(vm, memory, ptr);
|
||||||
frame->registers[dest] = v8;
|
frame->registers[ptr] = v8;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case OP_LOADI16: {
|
case OP_LOADI16: {
|
||||||
i16 v16;
|
i16 v16;
|
||||||
dest = read_u8(vm, code, vm->pc);
|
dest = read_u8(vm, code, vm->pc);
|
||||||
vm->pc++;
|
vm->pc++;
|
||||||
ptr = read_u32(vm, code, vm->pc);
|
src1 = read_u8(vm, code, vm->pc);
|
||||||
vm->pc += 4;
|
vm->pc++;
|
||||||
|
v = frame->registers[src1];
|
||||||
|
ptr = frame->registers[dest];
|
||||||
v16 = (i16)read_u16(vm, memory, ptr);
|
v16 = (i16)read_u16(vm, memory, ptr);
|
||||||
frame->registers[dest] = v16;
|
frame->registers[dest] = v16;
|
||||||
return true;
|
return true;
|
||||||
|
@ -150,34 +155,41 @@ bool step_vm(VM *vm) {
|
||||||
u16 v16;
|
u16 v16;
|
||||||
dest = read_u8(vm, code, vm->pc);
|
dest = read_u8(vm, code, vm->pc);
|
||||||
vm->pc++;
|
vm->pc++;
|
||||||
ptr = read_u32(vm, code, vm->pc);
|
src1 = read_u8(vm, code, vm->pc);
|
||||||
vm->pc += 4;
|
vm->pc++;
|
||||||
|
v = frame->registers[src1];
|
||||||
|
ptr = frame->registers[dest];
|
||||||
v16 = read_u16(vm, memory, ptr);
|
v16 = read_u16(vm, memory, ptr);
|
||||||
frame->registers[dest] = v16;
|
frame->registers[ptr] = v16;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case OP_STORE: {
|
case OP_STORE: {
|
||||||
|
dest = read_u8(vm, code, vm->pc);
|
||||||
|
vm->pc++;
|
||||||
src1 = read_u8(vm, code, vm->pc);
|
src1 = read_u8(vm, code, vm->pc);
|
||||||
vm->pc++;
|
vm->pc++;
|
||||||
ptr = read_u32(vm, code, vm->pc);
|
|
||||||
vm->pc += 4;
|
|
||||||
v = frame->registers[src1];
|
v = frame->registers[src1];
|
||||||
|
ptr = frame->registers[dest];
|
||||||
write_u32(vm, memory, ptr, v);
|
write_u32(vm, memory, ptr, v);
|
||||||
return true;
|
return true;
|
||||||
}case OP_STORE8: {
|
}
|
||||||
|
case OP_STORE8: {
|
||||||
|
dest = read_u8(vm, code, vm->pc);
|
||||||
|
vm->pc++;
|
||||||
src1 = read_u8(vm, code, vm->pc);
|
src1 = read_u8(vm, code, vm->pc);
|
||||||
vm->pc++;
|
vm->pc++;
|
||||||
ptr = read_u32(vm, code, vm->pc);
|
|
||||||
vm->pc += 4;
|
|
||||||
v = frame->registers[src1];
|
v = frame->registers[src1];
|
||||||
|
ptr = frame->registers[dest];
|
||||||
write_u8(vm, memory, ptr, v);
|
write_u8(vm, memory, ptr, v);
|
||||||
return true;
|
return true;
|
||||||
}case OP_STORE16: {
|
}
|
||||||
|
case OP_STORE16: {
|
||||||
|
dest = read_u8(vm, code, vm->pc);
|
||||||
|
vm->pc++;
|
||||||
src1 = read_u8(vm, code, vm->pc);
|
src1 = read_u8(vm, code, vm->pc);
|
||||||
vm->pc++;
|
vm->pc++;
|
||||||
ptr = read_u32(vm, code, vm->pc);
|
|
||||||
vm->pc += 4;
|
|
||||||
v = frame->registers[src1];
|
v = frame->registers[src1];
|
||||||
|
ptr = frame->registers[dest];
|
||||||
write_u16(vm, memory, ptr, v);
|
write_u16(vm, memory, ptr, v);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -261,16 +273,22 @@ bool step_vm(VM *vm) {
|
||||||
vm->pc++;
|
vm->pc++;
|
||||||
|
|
||||||
path_ptr = frame->registers[path_reg]; /* path pointer */
|
path_ptr = frame->registers[path_reg]; /* path pointer */
|
||||||
size = frame->registers[size_reg]; /* size */
|
size = frame->registers[size_reg]; /* size */
|
||||||
buffer_ptr = (dest > 32) ? vm->mp : dest; /* dest ptr, if > 32 then use memory pointer*/
|
buffer_ptr = (dest > 32)
|
||||||
|
? vm->mp
|
||||||
|
: dest; /* dest ptr, if > 32 then use memory pointer*/
|
||||||
|
|
||||||
dev = find_device_by_path(vm, (const char *)&vm->memory[path_ptr + 4]);
|
dev = find_device_by_path(vm, (const char *)&vm->memory[path_ptr + 4]);
|
||||||
if (dev && dev->ops->read) {
|
if (dev && dev->ops->read) {
|
||||||
vm->flag =
|
vm->flag =
|
||||||
dev->ops->read(dev->data, (u8 *)&vm->memory[buffer_ptr + 4], size);
|
dev->ops->read(dev->data, (u8 *)&vm->memory[buffer_ptr + 4], size);
|
||||||
if (dest > 32) { vm->mp += size + 4;}
|
if (dest > 32) {
|
||||||
|
vm->mp += size + 4;
|
||||||
|
}
|
||||||
write_u32(vm, memory, buffer_ptr, size);
|
write_u32(vm, memory, buffer_ptr, size);
|
||||||
if (dest > 32) { frame->end = vm->mp; }
|
if (dest > 32) {
|
||||||
|
frame->end = vm->mp;
|
||||||
|
}
|
||||||
frame->registers[buffer_reg] = buffer_ptr;
|
frame->registers[buffer_reg] = buffer_ptr;
|
||||||
} else {
|
} else {
|
||||||
vm->flag = 0;
|
vm->flag = 0;
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
((code
|
||||||
|
(label main
|
||||||
|
(load-immediate $0 &screen-namespace)
|
||||||
|
(load-immediate $1 0)
|
||||||
|
(syscall DEVICE-OPEN $0 $1)
|
||||||
|
|
||||||
|
(load-immediate $3 0xE0)
|
||||||
|
(load-immediate $4 36)
|
||||||
|
|
||||||
|
(load-immediate $1 1)
|
||||||
|
(load-immediate $5 50)
|
||||||
|
(label loop-x
|
||||||
|
(store-8 $4 $3)
|
||||||
|
(add-int $4 $4 $1)
|
||||||
|
(jump-lt-int &loop-x $4 $5))
|
||||||
|
|
||||||
|
(syscall DEVICE-WRITE $0 $0 $0)
|
||||||
|
(halt)))
|
||||||
|
(data
|
||||||
|
(label screen-namespace "/dev/screen/0")))
|
|
@ -1,16 +1,21 @@
|
||||||
((code
|
((code
|
||||||
(label main
|
(label main
|
||||||
(load $0 &x)
|
(load-immediate $0 &x)
|
||||||
(load $1 &y)
|
(load-immediate $1 &y)
|
||||||
(add-real $2 $1 $0)
|
(add-real $2 $1 $0)
|
||||||
(real-to-string $3 $2)
|
(real-to-string $3 $2)
|
||||||
(string-length $4 $3)
|
(push $3)
|
||||||
(load-immediate $5 &terminal-namespace)
|
(call &println)
|
||||||
(syscall DEVICE-WRITE $5 $3 $4)
|
(halt))
|
||||||
(load-immediate $6 &new-line)
|
(label println
|
||||||
(string-length $7 $6)
|
(load-immediate $0 &terminal-namespace)
|
||||||
(syscall DEVICE-WRITE $5 $6 $7)
|
(load-immediate $3 &new-line)
|
||||||
(halt)))
|
(pop $1)
|
||||||
|
(string-length $2 $1)
|
||||||
|
(syscall DEVICE-WRITE $0 $1 $2)
|
||||||
|
(string-length $4 $3)
|
||||||
|
(syscall DEVICE-WRITE $0 $3 $4)
|
||||||
|
(return)))
|
||||||
(data (label terminal-namespace "/dev/term/0")
|
(data (label terminal-namespace "/dev/term/0")
|
||||||
(label new-line "\n")
|
(label new-line "\n")
|
||||||
(label x 1.0)
|
(label x 1.0)
|
||||||
|
|
|
@ -1,9 +1,14 @@
|
||||||
((code
|
((code
|
||||||
(label main
|
(label main
|
||||||
(load-immediate $0 &screen-namespace)
|
(load-immediate $0 &screen-namespace)
|
||||||
(load-immediate $1 0) ; mode 0
|
(load-immediate $1 0)
|
||||||
(syscall DEVICE-OPEN $0 $2)
|
(syscall DEVICE-OPEN $0 $2)
|
||||||
|
|
||||||
|
|
||||||
(halt)))
|
(load-immediate $3 0x55)
|
||||||
(data (label screen-namespace "/dev/term/0")))
|
(load-immediate $4 36)
|
||||||
|
(store-8 $4 $3)
|
||||||
|
(syscall DEVICE-WRITE $0 $0 $0)
|
||||||
|
|
||||||
|
(halt)))
|
||||||
|
(data
|
||||||
|
(label screen-namespace "/dev/screen/0")))
|
||||||
|
|
Loading…
Reference in New Issue