Compare commits
No commits in common. "2d72240652d7ecded098697041c39a0731a996e2" and "b8832a71166cf95df92a7a53c3b4c92e0e64cc93" have entirely different histories.
2d72240652
...
b8832a7116
|
|
@ -6,7 +6,6 @@
|
||||||
typedef enum {
|
typedef enum {
|
||||||
OP_HALT, /* halt : terminate execution */
|
OP_HALT, /* halt : terminate execution */
|
||||||
OP_JMP, /* jump : jump to address dest unconditionally */
|
OP_JMP, /* jump : jump to address dest unconditionally */
|
||||||
OP_JMPF, /* jmpf : jump to address dest if flag is ne 0 */
|
|
||||||
OP_CALL, /* call : creates a new frame */
|
OP_CALL, /* call : creates a new frame */
|
||||||
OP_RETURN, /* retn : returns from a frame to the parent frame */
|
OP_RETURN, /* retn : returns from a frame to the parent frame */
|
||||||
OP_LOAD, /* load : dest = &[next memory location] */
|
OP_LOAD, /* load : dest = &[next memory location] */
|
||||||
|
|
@ -48,11 +47,6 @@ typedef enum {
|
||||||
OP_JLT_REAL, /* jler : jump to address dest if src1 as real < src2 as real */
|
OP_JLT_REAL, /* jler : jump to address dest if src1 as real < src2 as real */
|
||||||
OP_JLE_REAL, /* jger : jump to address dest if src1 as real <= src2 as real */
|
OP_JLE_REAL, /* jger : jump to address dest if src1 as real <= src2 as real */
|
||||||
OP_STRLEN, /* strl : dest = length of str at src1 ptr */
|
OP_STRLEN, /* strl : dest = length of str at src1 ptr */
|
||||||
OP_STREQ, /* steq : dest = src1 ptr string == src2 ptr string */
|
|
||||||
OP_STRCAT, /* scat : dest = ptr of src1 ptr string + src2 ptr string */
|
|
||||||
OP_STR_GET_CHAR, /* sgch : dest = ptr of src1 ptr string, src2 index of string */
|
|
||||||
OP_STR_FIND_CHAR, /* sfch : dest = ptr of src1 ptr string, src2 uint8 char */
|
|
||||||
OP_STR_SLICE, /* ssli : dest = ptr of src1 ptr string, src2 start index, src3 end index */
|
|
||||||
OP_INT_TO_STRING, /* itos : dest = src1 as str */
|
OP_INT_TO_STRING, /* itos : dest = src1 as str */
|
||||||
OP_UINT_TO_STRING, /* utos : dest = src1 as str */
|
OP_UINT_TO_STRING, /* utos : dest = src1 as str */
|
||||||
OP_REAL_TO_STRING, /* rtos : dest = src1 as str */
|
OP_REAL_TO_STRING, /* rtos : dest = src1 as str */
|
||||||
|
|
@ -111,7 +105,7 @@ typedef struct vm_s {
|
||||||
u32 rp; /* return stack pointer (top of stack) */
|
u32 rp; /* return stack pointer (top of stack) */
|
||||||
u32 mp; /* memory pointer (last allocated value) */
|
u32 mp; /* memory pointer (last allocated value) */
|
||||||
u32 dc; /* device count */
|
u32 dc; /* device count */
|
||||||
u32 flag; /* flag (temporary results like SYSCALL status) */
|
u32 acc; /* accumulator (temporary results like SYSCALL status) */
|
||||||
Frame frames[FRAMES_SIZE]; /* function call frames */
|
Frame frames[FRAMES_SIZE]; /* function call frames */
|
||||||
u32 stack[STACK_SIZE]; /* main stack */
|
u32 stack[STACK_SIZE]; /* main stack */
|
||||||
u32 return_stack[STACK_SIZE]; /* return stack (for call recursion) */
|
u32 return_stack[STACK_SIZE]; /* return stack (for call recursion) */
|
||||||
|
|
|
||||||
25
src/test.c
25
src/test.c
|
|
@ -48,21 +48,16 @@ bool compile_internal_test(const char *filename, VM *vm) {
|
||||||
|
|
||||||
bool test_simple_compile(VM *vm) {
|
bool test_simple_compile(VM *vm) {
|
||||||
u32 ptr;
|
u32 ptr;
|
||||||
u32 newline_addr =
|
u32 terminal_path_addr = str_alloc(vm, "/dev/term/0", 12);
|
||||||
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++] = OP_LOAD;
|
||||||
vm->code[vm->cp++] = 0;
|
vm->code[vm->cp++] = 0;
|
||||||
ptr = real_alloc(vm, 1.0f);
|
ptr = real_alloc(vm, 1.0f);
|
||||||
write_u32(vm, code, vm->cp, ptr);
|
write_u32(vm, code, vm->cp, ptr); vm->cp+=4;
|
||||||
vm->cp += 4;
|
|
||||||
|
|
||||||
vm->code[vm->cp++] = OP_LOAD;
|
vm->code[vm->cp++] = OP_LOAD;
|
||||||
vm->code[vm->cp++] = 1;
|
vm->code[vm->cp++] = 1;
|
||||||
ptr = real_alloc(vm, 2.0f);
|
ptr = real_alloc(vm, 2.0f);
|
||||||
write_u32(vm, code, vm->cp, ptr);
|
write_u32(vm, code, vm->cp, ptr); vm->cp+=4;
|
||||||
vm->cp += 4;
|
|
||||||
|
|
||||||
vm->code[vm->cp++] = OP_ADD_REAL;
|
vm->code[vm->cp++] = OP_ADD_REAL;
|
||||||
vm->code[vm->cp++] = 2;
|
vm->code[vm->cp++] = 2;
|
||||||
|
|
@ -73,22 +68,16 @@ bool test_simple_compile(VM *vm) {
|
||||||
vm->code[vm->cp++] = 3;
|
vm->code[vm->cp++] = 3;
|
||||||
vm->code[vm->cp++] = 2;
|
vm->code[vm->cp++] = 2;
|
||||||
|
|
||||||
vm->code[vm->cp++] = OP_REAL_TO_STRING;
|
|
||||||
vm->code[vm->cp++] = 3;
|
|
||||||
vm->code[vm->cp++] = 2;
|
|
||||||
|
|
||||||
vm->code[vm->cp++] = OP_LOAD_IMM;
|
vm->code[vm->cp++] = OP_LOAD_IMM;
|
||||||
vm->code[vm->cp++] = 2;
|
vm->code[vm->cp++] = 2;
|
||||||
write_u32(vm, code, vm->cp, terminal_path_addr);
|
write_u32(vm, code, vm->cp, terminal_path_addr); vm->cp+=4;
|
||||||
vm->cp += 4;
|
|
||||||
|
|
||||||
vm->code[vm->cp++] = OP_STRLEN;
|
vm->code[vm->cp++] = OP_STRLEN;
|
||||||
vm->code[vm->cp++] = 4;
|
vm->code[vm->cp++] = 4;
|
||||||
vm->code[vm->cp++] = 3;
|
vm->code[vm->cp++] = 3;
|
||||||
|
|
||||||
vm->code[vm->cp++] = OP_SYSCALL;
|
vm->code[vm->cp++] = OP_SYSCALL;
|
||||||
write_u32(vm, code, vm->cp, AS_UINT(SYSCALL_DEVICE_WRITE));
|
write_u32(vm, code, vm->cp, AS_UINT(SYSCALL_DEVICE_WRITE)); vm->cp+=4;
|
||||||
vm->cp += 4;
|
|
||||||
vm->code[vm->cp++] = 3; /* arg_count */
|
vm->code[vm->cp++] = 3; /* arg_count */
|
||||||
vm->code[vm->cp++] = 2; /* first_reg */
|
vm->code[vm->cp++] = 2; /* first_reg */
|
||||||
/* syscall_id=WRITE, arg_count=2, start_reg=3 ; print(sum.toS()); */
|
/* syscall_id=WRITE, arg_count=2, start_reg=3 ; print(sum.toS()); */
|
||||||
|
|
@ -97,9 +86,7 @@ bool test_simple_compile(VM *vm) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool test_window_click_compile(VM *vm) {
|
bool test_window_click_compile(VM *vm) {
|
||||||
u32 test_pixel_addr, loop_start,
|
u32 test_pixel_addr, loop_start, screen_path_addr = str_alloc(vm, "/dev/screen/0", 14);
|
||||||
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++] = OP_LOAD; /* R0 = screen path */
|
||||||
vm->code[vm->cp++] = 0;
|
vm->code[vm->cp++] = 0;
|
||||||
|
|
|
||||||
180
src/vm.c
180
src/vm.c
|
|
@ -3,25 +3,19 @@
|
||||||
#include "opcodes.h"
|
#include "opcodes.h"
|
||||||
#include "str.h"
|
#include "str.h"
|
||||||
|
|
||||||
|
/* no inline fn in ANSI C :( */
|
||||||
#define COMPARE_AND_JUMP(type, op) \
|
#define COMPARE_AND_JUMP(type, op) \
|
||||||
do { \
|
do { \
|
||||||
i32 cond; \
|
type value, value2; \
|
||||||
u32 mask, target; \
|
|
||||||
u8 dest, src1, src2; \
|
|
||||||
type value; \
|
|
||||||
type value2; \
|
|
||||||
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++; \
|
||||||
value = frame.registers[src1]; \
|
value = vm->frames[vm->fp].registers[src1]; \
|
||||||
value2 = frame.registers[src2]; \
|
value2 = vm->frames[vm->fp].registers[src2]; \
|
||||||
cond = !!(value op value2); \
|
vm->pc = (value op value2) ? vm->frames[vm->fp].registers[dest] : vm->pc; \
|
||||||
mask = -(u32)cond; \
|
|
||||||
target = frame.registers[dest]; \
|
|
||||||
vm->pc = (target & mask) | (vm->pc & ~mask); \
|
|
||||||
return true; \
|
return true; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
|
@ -33,12 +27,14 @@
|
||||||
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] = \
|
vm->frames[vm->fp].registers[dest] = (type)vm->frames[vm->fp] \
|
||||||
(type)frame.registers[src1] op(type) frame.registers[src2]; \
|
.registers[src1] op(type) \
|
||||||
|
vm->frames[vm->fp] \
|
||||||
|
.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, const char *str, u32 length) {
|
||||||
u32 str_addr = vm->mp;
|
u32 str_addr = vm->mp;
|
||||||
u32 i = 0;
|
u32 i = 0;
|
||||||
vm->mp += 4;
|
vm->mp += 4;
|
||||||
|
|
@ -48,7 +44,7 @@ u32 str_alloc(VM *vm, Frame *frame, const char *str, u32 length) {
|
||||||
vm->memory[vm->mp++] = '\0';
|
vm->memory[vm->mp++] = '\0';
|
||||||
|
|
||||||
write_u32(vm, memory, str_addr, length);
|
write_u32(vm, memory, str_addr, length);
|
||||||
frame->end = vm->mp;
|
vm->frames[vm->fp].end = vm->mp;
|
||||||
return str_addr;
|
return str_addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -59,11 +55,9 @@ bool step_vm(VM *vm) {
|
||||||
u8 opcode, dest, src1, src2;
|
u8 opcode, dest, src1, src2;
|
||||||
u32 v, ptr;
|
u32 v, ptr;
|
||||||
i32 value;
|
i32 value;
|
||||||
Frame frame;
|
|
||||||
|
|
||||||
/* Get current instruction & Advance to next instruction */
|
/* Get current instruction & Advance to next instruction */
|
||||||
opcode = vm->code[vm->pc++];
|
opcode = vm->code[vm->pc++];
|
||||||
frame = vm->frames[vm->fp];
|
|
||||||
|
|
||||||
switch (opcode) {
|
switch (opcode) {
|
||||||
case OP_HALT: {
|
case OP_HALT: {
|
||||||
|
|
@ -79,7 +73,7 @@ bool step_vm(VM *vm) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case OP_RETURN: {
|
case OP_RETURN: {
|
||||||
frame.rp = 0; /* reset register ptr */
|
vm->frames[vm->fp].rp = 0; /* reset register ptr */
|
||||||
vm->pc = vm->return_stack[--vm->rp]; /* set pc to return address */
|
vm->pc = vm->return_stack[--vm->rp]; /* set pc to return address */
|
||||||
vm->mp =
|
vm->mp =
|
||||||
vm->frames[vm->fp--].start; /* reset memory pointer to start
|
vm->frames[vm->fp--].start; /* reset memory pointer to start
|
||||||
|
|
@ -91,7 +85,7 @@ bool step_vm(VM *vm) {
|
||||||
vm->pc++;
|
vm->pc++;
|
||||||
v = read_u32(vm, code, vm->pc);
|
v = read_u32(vm, code, vm->pc);
|
||||||
vm->pc += 4;
|
vm->pc += 4;
|
||||||
frame.registers[dest] = v;
|
vm->frames[vm->fp].registers[dest] = v;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case OP_LOAD: {
|
case OP_LOAD: {
|
||||||
|
|
@ -100,7 +94,7 @@ bool step_vm(VM *vm) {
|
||||||
ptr = read_u32(vm, code, vm->pc);
|
ptr = read_u32(vm, code, vm->pc);
|
||||||
vm->pc += 4;
|
vm->pc += 4;
|
||||||
v = read_u32(vm, memory, ptr);
|
v = read_u32(vm, memory, ptr);
|
||||||
frame.registers[dest] = v;
|
vm->frames[vm->fp].registers[dest] = v;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case OP_STORE: {
|
case OP_STORE: {
|
||||||
|
|
@ -108,20 +102,20 @@ bool step_vm(VM *vm) {
|
||||||
vm->pc++;
|
vm->pc++;
|
||||||
ptr = read_u32(vm, code, vm->pc);
|
ptr = read_u32(vm, code, vm->pc);
|
||||||
vm->pc += 4;
|
vm->pc += 4;
|
||||||
v = frame.registers[src1];
|
v = vm->frames[vm->fp].registers[src1];
|
||||||
write_u32(vm, memory, ptr, v);
|
write_u32(vm, memory, ptr, v);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case OP_PUSH: {
|
case OP_PUSH: {
|
||||||
dest = read_u8(vm, code, vm->pc);
|
dest = read_u8(vm, code, vm->pc);
|
||||||
vm->pc++;
|
vm->pc++;
|
||||||
vm->stack[++vm->sp] = frame.registers[dest];
|
vm->stack[++vm->sp] = vm->frames[vm->fp].registers[dest];
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case OP_POP: {
|
case OP_POP: {
|
||||||
dest = read_u8(vm, code, vm->pc);
|
dest = read_u8(vm, code, vm->pc);
|
||||||
vm->pc++;
|
vm->pc++;
|
||||||
frame.registers[dest] = vm->stack[vm->sp--];
|
vm->frames[vm->fp].registers[dest] = vm->stack[vm->sp--];
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case OP_REG_MOV: {
|
case OP_REG_MOV: {
|
||||||
|
|
@ -129,21 +123,13 @@ bool step_vm(VM *vm) {
|
||||||
vm->pc++;
|
vm->pc++;
|
||||||
src1 = read_u8(vm, code, vm->pc);
|
src1 = read_u8(vm, code, vm->pc);
|
||||||
vm->pc++;
|
vm->pc++;
|
||||||
frame.registers[dest] = frame.registers[src1];
|
vm->frames[vm->fp].registers[dest] = vm->frames[vm->fp].registers[src1];
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case OP_JMP: {
|
case OP_JMP: {
|
||||||
dest = read_u8(vm, code, vm->pc);
|
dest = read_u8(vm, code, vm->pc);
|
||||||
vm->pc++;
|
vm->pc++;
|
||||||
vm->pc = frame.registers[dest]; /* Jump to address */
|
vm->pc = vm->frames[vm->fp].registers[dest]; /* Jump to address */
|
||||||
return true;
|
|
||||||
}
|
|
||||||
case OP_JMPF: { /* error handling for syscall, jump if flag == 0 */
|
|
||||||
u32 mask;
|
|
||||||
dest = read_u8(vm, code, vm->pc);
|
|
||||||
vm->pc++;
|
|
||||||
mask = -(u32)(vm->flag == 0);
|
|
||||||
vm->pc = (dest & mask) | (vm->pc & ~mask);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case OP_SYSCALL: {
|
case OP_SYSCALL: {
|
||||||
|
|
@ -162,21 +148,22 @@ bool step_vm(VM *vm) {
|
||||||
if (arg_count >= 2) {
|
if (arg_count >= 2) {
|
||||||
Device *dev;
|
Device *dev;
|
||||||
u32 path_ptr, mode;
|
u32 path_ptr, mode;
|
||||||
path_ptr = frame.registers[first_reg]; /* R0: path pointer */
|
path_ptr =
|
||||||
mode = frame.registers[first_reg + 1]; /* R1: mode */
|
vm->frames[vm->fp].registers[first_reg]; /* R0: path pointer */
|
||||||
|
mode = vm->frames[vm->fp].registers[first_reg + 1]; /* R1: mode */
|
||||||
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) {
|
if (dev) {
|
||||||
if (dev->ops->open) {
|
if (dev->ops->open) {
|
||||||
vm->flag = dev->ops->open(dev->data, mode);
|
vm->acc = dev->ops->open(dev->data, mode);
|
||||||
} else {
|
} else {
|
||||||
vm->flag = 1; /* success, no open needed */
|
vm->acc = 1; /* success, no open needed */
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
vm->flag = 0; /* error */
|
vm->acc = 0; /* error */
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
vm->flag = 0; /* error: not enough arguments */
|
vm->acc = 0; /* error: not enough arguments */
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -186,40 +173,44 @@ bool step_vm(VM *vm) {
|
||||||
Device *dev;
|
Device *dev;
|
||||||
u32 path_ptr, buffer_ptr, size;
|
u32 path_ptr, buffer_ptr, size;
|
||||||
|
|
||||||
path_ptr = frame.registers[first_reg]; /* R0: path pointer */
|
path_ptr =
|
||||||
buffer_ptr = frame.registers[first_reg + 1]; /* R1: buffer pointer */
|
vm->frames[vm->fp].registers[first_reg]; /* R0: path pointer */
|
||||||
size = frame.registers[first_reg + 2]; /* R2: size */
|
buffer_ptr = vm->frames[vm->fp]
|
||||||
|
.registers[first_reg + 1]; /* R1: buffer pointer */
|
||||||
|
size = vm->frames[vm->fp].registers[first_reg + 2]; /* R2: size */
|
||||||
|
|
||||||
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->acc =
|
||||||
dev->ops->read(dev->data, (u8 *)&vm->memory[buffer_ptr], size);
|
dev->ops->read(dev->data, (u8 *)&vm->memory[buffer_ptr], size);
|
||||||
} else {
|
} else {
|
||||||
vm->flag = 0;
|
vm->acc = 0;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
vm->flag = 0; /* error: not enough arguments */
|
vm->acc = 0; /* error: not enough arguments */
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
case SYSCALL_DEVICE_WRITE: {
|
case SYSCALL_DEVICE_WRITE: {
|
||||||
if (arg_count >= 3) {
|
if (arg_count >= 2) {
|
||||||
Device *dev;
|
Device *dev;
|
||||||
u32 path_ptr, buffer_ptr, size;
|
u32 path_ptr, buffer_ptr, size;
|
||||||
path_ptr = frame.registers[first_reg]; /* R0: path pointer */
|
path_ptr =
|
||||||
buffer_ptr = frame.registers[first_reg + 1]; /* R1: buffer pointer */
|
vm->frames[vm->fp].registers[first_reg]; /* R0: path pointer */
|
||||||
size = frame.registers[first_reg + 2]; /* R2: size */
|
buffer_ptr = vm->frames[vm->fp]
|
||||||
|
.registers[first_reg + 1]; /* R1: buffer pointer */
|
||||||
|
size = vm->frames[vm->fp].registers[first_reg + 2]; /* R2: size */
|
||||||
|
|
||||||
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->write) {
|
if (dev && dev->ops->write) {
|
||||||
vm->flag = dev->ops->write(
|
vm->acc = dev->ops->write(dev->data, (const u8 *)&vm->memory[buffer_ptr + 4],
|
||||||
dev->data, (const u8 *)&vm->memory[buffer_ptr + 4], size);
|
size);
|
||||||
} else {
|
} else {
|
||||||
vm->flag = 0;
|
vm->acc = 0;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
vm->flag = 0; /* error: not enough arguments */
|
vm->acc = 0; /* error: not enough arguments */
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -228,18 +219,19 @@ bool step_vm(VM *vm) {
|
||||||
if (arg_count >= 1) {
|
if (arg_count >= 1) {
|
||||||
Device *dev;
|
Device *dev;
|
||||||
u32 path_ptr;
|
u32 path_ptr;
|
||||||
path_ptr = frame.registers[first_reg]; /* R0: path pointer */
|
path_ptr =
|
||||||
|
vm->frames[vm->fp].registers[first_reg]; /* R0: path 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->close) {
|
if (dev && dev->ops->close) {
|
||||||
i32 result = dev->ops->close(dev->data);
|
i32 result = dev->ops->close(dev->data);
|
||||||
vm->flag = result;
|
vm->acc = result;
|
||||||
} else {
|
} else {
|
||||||
vm->flag = 0;
|
vm->acc = 0;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
vm->flag = 0; /* error: not enough arguments */
|
vm->acc = 0; /* error: not enough arguments */
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -248,20 +240,23 @@ bool step_vm(VM *vm) {
|
||||||
if (arg_count >= 3) {
|
if (arg_count >= 3) {
|
||||||
Device *dev;
|
Device *dev;
|
||||||
u32 path_ptr, args_ptr, cmd;
|
u32 path_ptr, args_ptr, cmd;
|
||||||
path_ptr = frame.registers[first_reg]; /* R0: device path */
|
path_ptr =
|
||||||
cmd = frame.registers[first_reg + 1]; /* R1: ioctl command */
|
vm->frames[vm->fp].registers[first_reg]; /* R0: device path */
|
||||||
args_ptr = frame.registers[first_reg + 2]; /* R2: args pointer */
|
cmd =
|
||||||
|
vm->frames[vm->fp].registers[first_reg + 1]; /* R1: ioctl command */
|
||||||
|
args_ptr =
|
||||||
|
vm->frames[vm->fp].registers[first_reg + 2]; /* R2: args 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 && dev->ops->ioctl) {
|
if (dev && dev->ops && dev->ops->ioctl) {
|
||||||
i32 result = dev->ops->ioctl(dev->data, cmd, &vm->memory[args_ptr]);
|
i32 result = dev->ops->ioctl(dev->data, cmd, &vm->memory[args_ptr]);
|
||||||
vm->flag = result;
|
vm->acc = result;
|
||||||
} else {
|
} else {
|
||||||
vm->flag = 0; /* error or no ioctl support */
|
vm->acc = 0; /* error or no ioctl support */
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
vm->flag = 0; /* error: not enough arguments */
|
vm->acc = 0; /* error: not enough arguments */
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -271,7 +266,7 @@ bool step_vm(VM *vm) {
|
||||||
}
|
}
|
||||||
|
|
||||||
default: {
|
default: {
|
||||||
vm->flag = 0; /* unknown syscall */
|
vm->acc = 0; /* unknown syscall */
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -300,8 +295,9 @@ bool step_vm(VM *vm) {
|
||||||
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] =
|
vm->frames[vm->fp].registers[dest] = (vm->frames[vm->fp].registers[src1] *
|
||||||
(frame.registers[src1] * frame.registers[src2]) >> 16;
|
vm->frames[vm->fp].registers[src2]) >>
|
||||||
|
16;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -312,8 +308,9 @@ bool step_vm(VM *vm) {
|
||||||
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] =
|
vm->frames[vm->fp].registers[dest] =
|
||||||
(frame.registers[src1] << 16) / frame.registers[src2];
|
(vm->frames[vm->fp].registers[src1] << 16) /
|
||||||
|
vm->frames[vm->fp].registers[src2];
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -324,7 +321,8 @@ bool step_vm(VM *vm) {
|
||||||
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[src1] + frame.registers[src2];
|
vm->frames[vm->fp].registers[dest] =
|
||||||
|
vm->frames[vm->fp].registers[src1] + vm->frames[vm->fp].registers[src2];
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -335,7 +333,8 @@ bool step_vm(VM *vm) {
|
||||||
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[src1] - frame.registers[src2];
|
vm->frames[vm->fp].registers[dest] =
|
||||||
|
vm->frames[vm->fp].registers[src1] - vm->frames[vm->fp].registers[src2];
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case OP_REAL_TO_INT: {
|
case OP_REAL_TO_INT: {
|
||||||
|
|
@ -343,12 +342,12 @@ bool step_vm(VM *vm) {
|
||||||
vm->pc++;
|
vm->pc++;
|
||||||
src1 = read_u8(vm, code, vm->pc);
|
src1 = read_u8(vm, code, vm->pc);
|
||||||
vm->pc++;
|
vm->pc++;
|
||||||
value = frame.registers[src1];
|
value = vm->frames[vm->fp].registers[src1];
|
||||||
|
|
||||||
if (value >= 0) {
|
if (value >= 0) {
|
||||||
frame.registers[dest] = value >> 16;
|
vm->frames[vm->fp].registers[dest] = value >> 16;
|
||||||
} else {
|
} else {
|
||||||
frame.registers[dest] = -((-value) >> 16);
|
vm->frames[vm->fp].registers[dest] = -((-value) >> 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -358,7 +357,8 @@ bool step_vm(VM *vm) {
|
||||||
vm->pc++;
|
vm->pc++;
|
||||||
src1 = read_u8(vm, code, vm->pc);
|
src1 = read_u8(vm, code, vm->pc);
|
||||||
vm->pc++;
|
vm->pc++;
|
||||||
frame.registers[dest] = (frame.registers[src1] << 16);
|
vm->frames[vm->fp].registers[dest] =
|
||||||
|
(vm->frames[vm->fp].registers[src1] << 16);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case OP_REAL_TO_UINT: {
|
case OP_REAL_TO_UINT: {
|
||||||
|
|
@ -366,11 +366,11 @@ bool step_vm(VM *vm) {
|
||||||
vm->pc++;
|
vm->pc++;
|
||||||
src1 = read_u8(vm, code, vm->pc);
|
src1 = read_u8(vm, code, vm->pc);
|
||||||
vm->pc++;
|
vm->pc++;
|
||||||
value = frame.registers[src1];
|
value = vm->frames[vm->fp].registers[src1];
|
||||||
if (value < 0) {
|
if (value < 0) {
|
||||||
frame.registers[dest] = 0;
|
vm->frames[vm->fp].registers[dest] = 0;
|
||||||
} else {
|
} else {
|
||||||
frame.registers[dest] = AS_UINT(value >> 16);
|
vm->frames[vm->fp].registers[dest] = AS_UINT(value >> 16);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -379,7 +379,8 @@ bool step_vm(VM *vm) {
|
||||||
vm->pc++;
|
vm->pc++;
|
||||||
src1 = read_u8(vm, code, vm->pc);
|
src1 = read_u8(vm, code, vm->pc);
|
||||||
vm->pc++;
|
vm->pc++;
|
||||||
frame.registers[dest] = AS_INT(frame.registers[src1] << 16);
|
vm->frames[vm->fp].registers[dest] =
|
||||||
|
AS_INT(vm->frames[vm->fp].registers[src1] << 16);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case OP_JEQ_UINT: {
|
case OP_JEQ_UINT: {
|
||||||
|
|
@ -433,9 +434,9 @@ bool step_vm(VM *vm) {
|
||||||
vm->pc++;
|
vm->pc++;
|
||||||
src1 = read_u8(vm, code, vm->pc);
|
src1 = read_u8(vm, code, vm->pc);
|
||||||
vm->pc++;
|
vm->pc++;
|
||||||
int_to_string(AS_INT(frame.registers[src1]), buffer);
|
int_to_string(AS_INT(vm->frames[vm->fp].registers[src1]), buffer);
|
||||||
ptr = str_alloc(vm, &frame, buffer, strlen(buffer));
|
ptr = str_alloc(vm, buffer, strlen(buffer));
|
||||||
frame.registers[dest] = ptr;
|
vm->frames[vm->fp].registers[dest] = ptr;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case OP_UINT_TO_STRING: {
|
case OP_UINT_TO_STRING: {
|
||||||
|
|
@ -444,9 +445,9 @@ bool step_vm(VM *vm) {
|
||||||
vm->pc++;
|
vm->pc++;
|
||||||
src1 = read_u8(vm, code, vm->pc);
|
src1 = read_u8(vm, code, vm->pc);
|
||||||
vm->pc++;
|
vm->pc++;
|
||||||
uint_to_string(frame.registers[src1], buffer);
|
uint_to_string(vm->frames[vm->fp].registers[src1], buffer);
|
||||||
ptr = str_alloc(vm, &frame, buffer, strlen(buffer));
|
ptr = str_alloc(vm, buffer, strlen(buffer));
|
||||||
frame.registers[dest] = ptr;
|
vm->frames[vm->fp].registers[dest] = ptr;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case OP_REAL_TO_STRING: {
|
case OP_REAL_TO_STRING: {
|
||||||
|
|
@ -455,10 +456,9 @@ bool step_vm(VM *vm) {
|
||||||
vm->pc++;
|
vm->pc++;
|
||||||
src1 = read_u8(vm, code, vm->pc);
|
src1 = read_u8(vm, code, vm->pc);
|
||||||
vm->pc++;
|
vm->pc++;
|
||||||
fixed_to_string(AS_INT(frame.registers[src1]), buffer);
|
fixed_to_string(AS_INT(vm->frames[vm->fp].registers[src1]), buffer);
|
||||||
ptr =
|
ptr = str_alloc(vm, buffer, strlen(buffer)); /* copy buffer to dest */
|
||||||
str_alloc(vm, &frame, buffer, strlen(buffer)); /* copy buffer to dest */
|
vm->frames[vm->fp].registers[dest] = ptr;
|
||||||
frame.registers[dest] = ptr;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case OP_STRLEN: {
|
case OP_STRLEN: {
|
||||||
|
|
@ -468,9 +468,9 @@ bool step_vm(VM *vm) {
|
||||||
src1 = read_u8(vm, code, vm->pc);
|
src1 = read_u8(vm, code, vm->pc);
|
||||||
vm->pc++;
|
vm->pc++;
|
||||||
|
|
||||||
ptr = frame.registers[src1];
|
ptr = vm->frames[vm->fp].registers[src1];
|
||||||
length = read_u32(vm, memory, ptr);
|
length = read_u32(vm, memory, ptr);
|
||||||
frame.registers[dest] = length;
|
vm->frames[vm->fp].registers[dest] = length;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case OP_STRING_TO_INT: {
|
case OP_STRING_TO_INT: {
|
||||||
|
|
|
||||||
2
src/vm.h
2
src/vm.h
|
|
@ -4,7 +4,7 @@
|
||||||
#include "opcodes.h"
|
#include "opcodes.h"
|
||||||
|
|
||||||
bool step_vm(VM *vm);
|
bool step_vm(VM *vm);
|
||||||
u32 str_alloc(VM *vm, Frame *frame, const char *str, u32 length);
|
u32 str_alloc(VM *vm, const char *str, u32 length);
|
||||||
void fixed_to_string(i32 value, char *buffer);
|
void fixed_to_string(i32 value, char *buffer);
|
||||||
void int_to_string(i32 value, char *buffer);
|
void int_to_string(i32 value, char *buffer);
|
||||||
void uint_to_string(u32 value, char *buffer);
|
void uint_to_string(u32 value, char *buffer);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue