wip stack based
This commit is contained in:
parent
ee8f9b63b0
commit
1b77649e36
|
|
@ -1,15 +1,13 @@
|
|||
#include "../../../vm/vm.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#define CODE_SIZE 8192
|
||||
#define MEMORY_SIZE 65536
|
||||
u8 lmem[MEMORY_SIZE] = {0};
|
||||
u32 lcode[CODE_SIZE] = {0};
|
||||
u8 lcode[CODE_SIZE] = {0};
|
||||
|
||||
bool init_vm() {
|
||||
mem = lmem;
|
||||
memset(mem, 0, MEMORY_SIZE*sizeof(u8));
|
||||
code = lcode;
|
||||
lc = 0;
|
||||
mp = 0;
|
||||
|
|
@ -52,77 +50,22 @@ u32 syscall(u32 id, u32 size, u32 mem_ptr) {
|
|||
}
|
||||
|
||||
void test_add_two_num() {
|
||||
i32 main_local_count = 5;
|
||||
mp += (4 * main_local_count);
|
||||
code[cp++] = ENCODE_B(OP_LOAD_IMM, 0, 1);
|
||||
code[cp++] = ENCODE_B(OP_PUSH, 0, 0);
|
||||
code[cp++] = ENCODE_B(OP_LOAD_IMM, 1, 1);
|
||||
code[cp++] = ENCODE_B(OP_PUSH, 1, 0);
|
||||
i32 add = cp + 5;
|
||||
code[cp++] = ENCODE_B(OP_LOAD_IMM, 2, add);
|
||||
|
||||
code[cp++] = ENCODE_A(OP_CALL, 2, 3, 0);
|
||||
code[cp++] = ENCODE_A(OP_INT_TO_STR, 4, 3, 0);
|
||||
code[cp++] = ENCODE_A(OP_SYSCALL, SYSCALL_CONSOLE_WRITE, 1, 4);
|
||||
code[cp++] = ENCODE_A(OP_HALT, 0, 0, 0);
|
||||
|
||||
code[cp++] = OP_GET;
|
||||
code[cp++] = OP_GET;
|
||||
code[cp++] = OP_GET;
|
||||
code[cp++] = OP_CALL;
|
||||
code[cp++] = OP_INT_TO_STR;
|
||||
code[cp++] = OP_SYSCALL;
|
||||
code[cp++] = OP_HALT;
|
||||
/* add */
|
||||
code[cp++] = ENCODE_A(OP_ADD_INT, 2, 1, 0);
|
||||
code[cp++] = ENCODE_B(OP_RETURN, 2, 0);
|
||||
}
|
||||
|
||||
void test_fibonacci() {
|
||||
i32 fib = 7;
|
||||
i32 base_case = 21;
|
||||
/* function main() */
|
||||
i32 main_local_count = 4;
|
||||
mp += (4 * main_local_count);
|
||||
/* fib(35) */
|
||||
code[cp++] = ENCODE_B(OP_LOAD_IMM, 0, 35);
|
||||
code[cp++] = ENCODE_B(OP_PUSH, 0, 0);
|
||||
code[cp++] = ENCODE_B(OP_LOAD_IMM, 1, fib);
|
||||
code[cp++] = ENCODE_A(OP_CALL, 1, 9, 2);
|
||||
/* print */
|
||||
code[cp++] = ENCODE_A(OP_INT_TO_STR, 3, 2, 0);
|
||||
code[cp++] = ENCODE_A(OP_SYSCALL, SYSCALL_CONSOLE_WRITE, 1, 3);
|
||||
code[cp++] = ENCODE_A(OP_HALT, 0, 0, 0);
|
||||
/* function fib (int n) int */
|
||||
//code[cp++] = ENCODE_A(OP_SYSCALL, SYSCALL_DBG_PRINT, 1, 0);
|
||||
code[cp++] = ENCODE_B(OP_LOAD_IMM, 8, fib);
|
||||
code[cp++] = ENCODE_B(OP_LOAD_IMM, 1, 2);
|
||||
code[cp++] = ENCODE_B(OP_LOAD_IMM, 2, base_case);
|
||||
code[cp++] = ENCODE_A(OP_JLT_INT, 2, 0, 1);
|
||||
code[cp++] = ENCODE_B(OP_LOAD_IMM, 3, 2);
|
||||
code[cp++] = ENCODE_A(OP_SUB_INT, 4, 0, 3);
|
||||
code[cp++] = ENCODE_B(OP_PUSH, 4, 0);
|
||||
code[cp++] = ENCODE_A(OP_CALL, 8, 9, 5);
|
||||
code[cp++] = ENCODE_B(OP_LOAD_IMM, 3, 1);
|
||||
code[cp++] = ENCODE_A(OP_SUB_INT, 4, 0, 3);
|
||||
code[cp++] = ENCODE_B(OP_PUSH, 4, 0);
|
||||
code[cp++] = ENCODE_A(OP_CALL, 8, 9, 6);
|
||||
code[cp++] = ENCODE_A(OP_ADD_INT, 7, 6, 5);
|
||||
code[cp++] = ENCODE_B(OP_RETURN, 7, 0);
|
||||
code[cp++] = ENCODE_B(OP_RETURN, 0, 0);
|
||||
}
|
||||
|
||||
void test_hello() {
|
||||
u32 hello =str_alloc("nuqneH 'u'?", 12);
|
||||
u32 new_line = str_alloc("\n", 1);
|
||||
fp = mp;
|
||||
/* function main() */
|
||||
i32 main_local_count = 3;
|
||||
mp += (4 * main_local_count);
|
||||
code[cp++] = ENCODE_B(OP_LOAD_IMM, 0, hello);
|
||||
code[cp++] = ENCODE_A(OP_SYSCALL, SYSCALL_CONSOLE_WRITE, 12, 0);
|
||||
code[cp++] = ENCODE_B(OP_LOAD_IMM, 0, new_line);
|
||||
code[cp++] = ENCODE_A(OP_SYSCALL, SYSCALL_CONSOLE_WRITE, 1, 0);
|
||||
code[cp++] = ENCODE_A(OP_HALT, 0, 0, 0);
|
||||
code[cp++] = OP_ADD_INT;
|
||||
code[cp++] = OP_RETURN;
|
||||
}
|
||||
|
||||
i32 main() {
|
||||
init_vm();
|
||||
|
||||
test_hello();
|
||||
test_add_two_num();
|
||||
|
||||
while(step_vm()) {
|
||||
// do stuff
|
||||
|
|
|
|||
357
vm/vm.c
357
vm/vm.c
|
|
@ -5,10 +5,11 @@ u32 pc; /* program counter */
|
|||
u32 cp; /* code pointer */
|
||||
u32 mp; /* memory pointer */
|
||||
u32 fp; /* frame pointer */
|
||||
u8 lc; /* child local count */
|
||||
u32 sp; /* frame pointer */
|
||||
u8 status; /* status flag */
|
||||
u8 interrupt; /* device interrupt */
|
||||
u32 *code; /* code */
|
||||
u32 *stack; /* stack */
|
||||
u8 *code; /* code */
|
||||
u8 *mem; /* memory */
|
||||
|
||||
#define MAX_LEN_INT32 11
|
||||
|
|
@ -28,8 +29,8 @@ u32 str_alloc(char *str, u32 length) {
|
|||
}
|
||||
|
||||
bool step_vm() {
|
||||
u32 instruction = code[pc++];
|
||||
u8 opcode = DECODE_OP(instruction);
|
||||
|
||||
u8 opcode = code[pc++];
|
||||
u32 *locals = (u32*)(&mem[fp]);
|
||||
u32 *globals = (u32*)(mem);
|
||||
|
||||
|
|
@ -39,9 +40,9 @@ bool step_vm() {
|
|||
return false;
|
||||
}
|
||||
case OP_CALL: {
|
||||
DECODE_A(instruction)
|
||||
/* TODO: Fix this one so it makes sense with a stack based system */
|
||||
/* function to jump to */
|
||||
u32 fn_ptr = locals[dest];
|
||||
u32 fn_ptr = stack[--sp];
|
||||
/* get mp in 'global indexing mode' */
|
||||
u32 *header = &globals[mp / 4];
|
||||
/* reset child locals counter */
|
||||
|
|
@ -49,25 +50,22 @@ bool step_vm() {
|
|||
/* push parents frame value to reset the heap to */
|
||||
(*header++) = fp;
|
||||
/* push return address to child frame */
|
||||
(*header++) = pc;
|
||||
/* push local address to return the value to */
|
||||
(*header++) = fp + (src2 * 4);
|
||||
globals[gmp + 1] = pc;
|
||||
/* increase the mp to new size */
|
||||
mp += FRAME_HEADER_SIZE;
|
||||
/* now set the frame pointer, where the locals start */
|
||||
fp = mp;
|
||||
/* move mp forward by count many locals */
|
||||
mp += (src1 * 4);
|
||||
mp += stack[--sp];
|
||||
/* jump to dest_ptr */
|
||||
pc = fn_ptr;
|
||||
return true;
|
||||
}
|
||||
case OP_RETURN: {
|
||||
DECODE_B(instruction)
|
||||
u32 size = 0;
|
||||
u32 return_value = locals[dest];
|
||||
bool is_ptr = (((u32)(1)) << 15) & imm;
|
||||
bool replaces_value = (((u32)(1)) << 14) & imm;
|
||||
/* TODO: Fix this one so it makes sense with a stack based system */
|
||||
u32 i, size = 0;
|
||||
u32 return_value = stack[--sp];
|
||||
bool is_ptr = (((u32)(1)) << 15) & return_value;
|
||||
|
||||
/* reset mp to saved mp, use header size to get "real" start of frame */
|
||||
u32 *frame_start = &globals[(fp / 4) - 3];
|
||||
|
|
@ -75,7 +73,6 @@ bool step_vm() {
|
|||
u32 return_address = *frame_start++;
|
||||
u32 parent_local_return_address = *frame_start++;
|
||||
|
||||
USED(replaces_value);
|
||||
/* reset memory to parents end of memory */
|
||||
mp = fp - FRAME_HEADER_SIZE;
|
||||
/* reset the frame pointer */
|
||||
|
|
@ -99,150 +96,24 @@ bool step_vm() {
|
|||
return true;
|
||||
}
|
||||
case OP_SYSCALL: {
|
||||
DECODE_A(instruction)
|
||||
u32 id = dest; /* syscall id */
|
||||
u32 size = src1; /* size of heap at that pointer */
|
||||
u32 rd = locals[src2]; /* the pointer */
|
||||
u32 id = stack[--sp]; /* syscall id */
|
||||
u32 size = stack[--sp]; /* size of heap at that pointer */
|
||||
u32 rd = stack[--sp]; /* the pointer */
|
||||
status = syscall(id, size, rd);
|
||||
return true;
|
||||
}
|
||||
case OP_PUSH: {
|
||||
DECODE_B(instruction)
|
||||
USED(imm);
|
||||
globals[(mp / 4) + lc + 3] = locals[dest];
|
||||
lc++;
|
||||
return true;
|
||||
}
|
||||
case OP_POP: {
|
||||
DECODE_B(instruction)
|
||||
USED(dest);
|
||||
USED(imm);
|
||||
mp -= 4;
|
||||
lc--;
|
||||
return true;
|
||||
}
|
||||
case OP_LOAD_IMM: {
|
||||
DECODE_B(instruction)
|
||||
locals[dest] = imm;
|
||||
return true;
|
||||
}
|
||||
case OP_LOAD_UPPER_IMM: {
|
||||
DECODE_B(instruction)
|
||||
u32 value = locals[dest];
|
||||
locals[dest] = (value | (((u32)(imm)) << 16));
|
||||
return true;
|
||||
}
|
||||
case OP_LOAD_IND_8: {
|
||||
DECODE_A(instruction)
|
||||
USED(src2);
|
||||
locals[dest] = READ_U8(locals[src1]);
|
||||
return true;
|
||||
}
|
||||
case OP_LOAD_IND_16: {
|
||||
DECODE_A(instruction)
|
||||
USED(src2);
|
||||
locals[dest] = READ_U16(locals[src1]);
|
||||
return true;
|
||||
}
|
||||
case OP_LOAD_IND_32: {
|
||||
DECODE_A(instruction)
|
||||
USED(src2);
|
||||
locals[dest] = READ_U32(locals[src1]);
|
||||
return true;
|
||||
}
|
||||
case OP_LOAD_ABS_8: {
|
||||
/* need multibyte for this, ignore for now */
|
||||
status = 250;
|
||||
return false;
|
||||
}
|
||||
case OP_LOAD_ABS_16: {
|
||||
/* need multibyte for this, ignore for now */
|
||||
status = 250;
|
||||
return false;
|
||||
}
|
||||
case OP_LOAD_ABS_32: {
|
||||
/* need multibyte for this, ignore for now */
|
||||
status = 250;
|
||||
return false;
|
||||
}
|
||||
case OP_LOAD_OFF_8: {
|
||||
DECODE_A(instruction)
|
||||
locals[dest] = READ_U8((locals[src1] + locals[src2]));
|
||||
return true;
|
||||
}
|
||||
case OP_LOAD_OFF_16: {
|
||||
DECODE_A(instruction)
|
||||
locals[dest] = READ_U16((locals[src1] + locals[src2]));
|
||||
return true;
|
||||
}
|
||||
case OP_LOAD_OFF_32: {
|
||||
DECODE_A(instruction)
|
||||
locals[dest] = READ_U32((locals[src1] + locals[src2]));
|
||||
return true;
|
||||
}
|
||||
case OP_STORE_ABS_8: {
|
||||
/* need multibyte for this, ignore for now */
|
||||
status = 250;
|
||||
return false;
|
||||
}
|
||||
case OP_STORE_ABS_16: {
|
||||
/* need multibyte for this, ignore for now */
|
||||
status = 250;
|
||||
return false;
|
||||
}
|
||||
case OP_STORE_ABS_32: {
|
||||
/* need multibyte for this, ignore for now */
|
||||
status = 250;
|
||||
return false;
|
||||
}
|
||||
case OP_STORE_IND_8: {
|
||||
DECODE_A(instruction)
|
||||
USED(src2);
|
||||
WRITE_U8(locals[dest], locals[src1]);
|
||||
return true;
|
||||
}
|
||||
case OP_STORE_IND_16: {
|
||||
DECODE_A(instruction)
|
||||
USED(src2);
|
||||
WRITE_U16(locals[dest], locals[src1]);
|
||||
return true;
|
||||
}
|
||||
case OP_STORE_IND_32: {
|
||||
DECODE_A(instruction)
|
||||
USED(src2);
|
||||
WRITE_U32(locals[dest], locals[src1]);
|
||||
return true;
|
||||
}
|
||||
case OP_STORE_OFF_8: {
|
||||
DECODE_A(instruction)
|
||||
WRITE_U8((locals[dest] + locals[src2]), locals[src1]);
|
||||
return true;
|
||||
}
|
||||
case OP_STORE_OFF_16: {
|
||||
DECODE_A(instruction)
|
||||
WRITE_U16((locals[dest] + locals[src2]), locals[src1]);
|
||||
return true;
|
||||
}
|
||||
case OP_STORE_OFF_32: {
|
||||
DECODE_A(instruction)
|
||||
WRITE_U32((locals[dest] + locals[src2]), locals[src1]);
|
||||
return true;
|
||||
}
|
||||
case OP_MEM_ALLOC: {
|
||||
DECODE_A(instruction)
|
||||
u32 size = locals[src1];
|
||||
locals[dest] = mp;
|
||||
u32 size = stack[--sp];
|
||||
stack[sp++] = mp;
|
||||
WRITE_U32(mp, size);
|
||||
USED(src2);
|
||||
mp += (size + 4);
|
||||
return true;
|
||||
}
|
||||
case OP_MEM_CPY_8: {
|
||||
DECODE_A(instruction)
|
||||
u32 i = 0;
|
||||
u32 mdest = locals[dest];
|
||||
u32 msrc = locals[src1];
|
||||
u32 count = locals[src2];
|
||||
u32 count = stack[--sp];
|
||||
u32 msrc = stack[--sp];
|
||||
u32 mdest = stack[--sp];
|
||||
|
||||
if (mdest + count >= mp) {
|
||||
status = 1;
|
||||
|
|
@ -257,11 +128,10 @@ bool step_vm() {
|
|||
return true;
|
||||
}
|
||||
case OP_MEM_CPY_16: {
|
||||
DECODE_A(instruction)
|
||||
u32 i = 0;
|
||||
u32 mdest = locals[dest];
|
||||
u32 msrc = locals[src1];
|
||||
u32 count = locals[src2] * 2;
|
||||
u32 count = stack[--sp];
|
||||
u32 msrc = stack[--sp];
|
||||
u32 mdest = stack[--sp];
|
||||
|
||||
if (mdest + count >= mp) {
|
||||
status = 1;
|
||||
|
|
@ -277,11 +147,10 @@ bool step_vm() {
|
|||
return true;
|
||||
}
|
||||
case OP_MEM_CPY_32: {
|
||||
DECODE_A(instruction)
|
||||
u32 i = 0;
|
||||
u32 mdest = locals[dest];
|
||||
u32 msrc = locals[src1];
|
||||
u32 count = locals[src2];
|
||||
u32 count = stack[--sp];
|
||||
u32 msrc = stack[--sp];
|
||||
u32 mdest = stack[--sp];
|
||||
|
||||
if (mdest + count >= mp) {
|
||||
status = 1;
|
||||
|
|
@ -296,25 +165,13 @@ bool step_vm() {
|
|||
return true;
|
||||
}
|
||||
case OP_MEM_SET_8: {
|
||||
DECODE_A(instruction)
|
||||
u32 i, start, end;
|
||||
|
||||
u32 rd = fp + (dest * 4);
|
||||
u32 r1 = fp + (src1 * 4);
|
||||
u32 r2 = fp + (src2 * 4);
|
||||
|
||||
u8 value = (u8)READ_U32(r1);
|
||||
u32 count = READ_U32(r2);
|
||||
|
||||
if (r2 == 0) {
|
||||
status = 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
start = READ_U32(rd);
|
||||
u8 value = (u8)stack[--sp];
|
||||
u32 count = stack[--sp];
|
||||
start = stack[--sp];
|
||||
end = start + count;
|
||||
|
||||
if (start >= mp || r2 > mp || end > mp) {
|
||||
if (start >= mp || end > mp) {
|
||||
status = 1;
|
||||
return true;
|
||||
}
|
||||
|
|
@ -327,25 +184,13 @@ bool step_vm() {
|
|||
return true;
|
||||
}
|
||||
case OP_MEM_SET_16: {
|
||||
DECODE_A(instruction)
|
||||
u32 i, start, end;
|
||||
|
||||
u32 rd = fp + (dest * 4);
|
||||
u32 r1 = fp + (src1 * 4);
|
||||
u32 r2 = fp + (src2 * 4);
|
||||
|
||||
u16 value = (u16)READ_U32(r1);
|
||||
u32 count = READ_U32(r2);
|
||||
|
||||
if (r2 == 0) {
|
||||
status = 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
start = READ_U32(rd);
|
||||
u8 value = (u8)stack[--sp];
|
||||
u32 count = stack[--sp];
|
||||
start = stack[--sp];
|
||||
end = start + count;
|
||||
|
||||
if (start >= mp || r2 > mp || end > mp) {
|
||||
if (start >= mp || end > mp) {
|
||||
status = 1;
|
||||
return true;
|
||||
}
|
||||
|
|
@ -358,21 +203,13 @@ bool step_vm() {
|
|||
return true;
|
||||
}
|
||||
case OP_MEM_SET_32: {
|
||||
DECODE_A(instruction)
|
||||
u32 i, start, end;
|
||||
|
||||
u32 value = locals[src1];
|
||||
u32 count = locals[src2];
|
||||
|
||||
if (count == 0) {
|
||||
status = 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
start = READ_U32(locals[dest]);
|
||||
u8 value = (u8)stack[--sp];
|
||||
u32 count = stack[--sp];
|
||||
start = stack[--sp];
|
||||
end = start + count;
|
||||
|
||||
if (start >= mp || count > mp || end > mp) {
|
||||
if (start >= mp || end > mp) {
|
||||
status = 1;
|
||||
return true;
|
||||
}
|
||||
|
|
@ -384,12 +221,6 @@ bool step_vm() {
|
|||
status = 0;
|
||||
return true;
|
||||
}
|
||||
case OP_MOV: {
|
||||
DECODE_A(instruction)
|
||||
USED(src2);
|
||||
locals[dest] = locals[src1];
|
||||
return true;
|
||||
}
|
||||
case OP_ADD_INT: {
|
||||
MATH_OP(i32, +);
|
||||
}
|
||||
|
|
@ -421,27 +252,27 @@ bool step_vm() {
|
|||
MATH_OP(i32, -);
|
||||
}
|
||||
case OP_MUL_REAL: {
|
||||
DECODE_A(instruction)
|
||||
i32 src1 = (i32)stack[--sp];
|
||||
i32 src2 = (i32)stack[--sp];
|
||||
|
||||
i32 src1_whole = (i32)locals[src1] >> 16;
|
||||
i32 src2_whole = (i32)locals[src2] >> 16;
|
||||
i32 src1_whole = src1 >> 16;
|
||||
i32 src2_whole = src2 >> 16;
|
||||
|
||||
i32 src1_decimal = (i32)locals[src1] & 16;
|
||||
i32 src2_decimal = (i32)locals[src2] & 16;
|
||||
i32 src1_decimal = src1 & 16;
|
||||
i32 src2_decimal = src2 & 16;
|
||||
|
||||
i32 result = 0;
|
||||
result += (src1_whole * src2_whole) << 16;
|
||||
result += (src1_whole * src2_decimal);
|
||||
result += (src1_decimal * src2_whole);
|
||||
result += ((src1_decimal * src2_decimal) >> 16) & 16;
|
||||
locals[dest] = result;
|
||||
stack[sp++] = result;
|
||||
return true;
|
||||
}
|
||||
case OP_DIV_REAL: {
|
||||
DECODE_A(instruction)
|
||||
i32 result;
|
||||
i32 src1_val = (i32)locals[src1];
|
||||
i32 src2_val = (i32)locals[src2];
|
||||
i32 src1_val = (i32)stack[--sp];
|
||||
i32 src2_val = (i32)stack[--sp];
|
||||
|
||||
u32 src2_reciprocal = 1;
|
||||
src2_reciprocal <<= 31;
|
||||
|
|
@ -450,49 +281,37 @@ bool step_vm() {
|
|||
result = src1_val * src2_reciprocal;
|
||||
result <<= 1;
|
||||
|
||||
locals[dest] = result;
|
||||
stack[sp++] = result;
|
||||
return true;
|
||||
}
|
||||
case OP_INT_TO_REAL: {
|
||||
DECODE_A(instruction)
|
||||
i32 result = (i32)locals[src1] << 16;
|
||||
USED(src2);
|
||||
locals[dest] = result;
|
||||
i32 result = (i32)stack[--sp] << 16;
|
||||
stack[sp++] = result;
|
||||
return true;
|
||||
}
|
||||
case OP_INT_TO_NAT: {
|
||||
DECODE_A(instruction)
|
||||
u32 result = (u32)locals[src1];
|
||||
USED(src2);
|
||||
locals[dest] = result;
|
||||
u32 result = (u32)stack[--sp];
|
||||
stack[sp++] = result;
|
||||
return true;
|
||||
}
|
||||
case OP_NAT_TO_REAL: {
|
||||
DECODE_A(instruction)
|
||||
i32 result = (i32)locals[src1] << 16;
|
||||
USED(src2);
|
||||
locals[dest] = result;
|
||||
i32 result = (i32)stack[--sp] << 16;
|
||||
stack[sp++] = result;
|
||||
return true;
|
||||
}
|
||||
case OP_NAT_TO_INT: {
|
||||
DECODE_A(instruction)
|
||||
i32 result = (i32)locals[src1];
|
||||
USED(src2);
|
||||
locals[dest] = result;
|
||||
i32 result = (i32)stack[--sp];
|
||||
stack[sp++] = result;
|
||||
return true;
|
||||
}
|
||||
case OP_REAL_TO_INT: {
|
||||
DECODE_A(instruction)
|
||||
i32 result = (i32)locals[src1] >> 16;
|
||||
USED(src2);
|
||||
locals[dest] = result;
|
||||
i32 result = (i32)stack[--sp] >> 16;
|
||||
stack[sp++] = result;
|
||||
return true;
|
||||
}
|
||||
case OP_REAL_TO_NAT: {
|
||||
DECODE_A(instruction)
|
||||
u32 result = (u32)locals[src1] >> 16;
|
||||
USED(src2);
|
||||
locals[dest] = result;
|
||||
u32 result = (u32)stack[--sp] >> 16;
|
||||
stack[sp++] = result;
|
||||
return true;
|
||||
}
|
||||
case OP_BIT_SHIFT_LEFT: {
|
||||
|
|
@ -513,49 +332,23 @@ bool step_vm() {
|
|||
case OP_BIT_XOR: {
|
||||
MATH_OP_NO_CAST(^);
|
||||
}
|
||||
case OP_JMP_IMM: {
|
||||
u32 imm = (((u32)code[(pc) + 3] << 24) |
|
||||
((u32)code[(pc) + 2] << 16) |
|
||||
((u32)code[(pc) + 1] << 8) |
|
||||
((u32)code[(pc)]));
|
||||
pc = imm;
|
||||
return true;
|
||||
}
|
||||
case OP_JMP_ABS: {
|
||||
DECODE_A(instruction)
|
||||
u32 jmp_dest = locals[dest];
|
||||
case OP_JMP: {
|
||||
u32 jmp_dest = stack[--sp];
|
||||
if (jmp_dest > cp) {
|
||||
status = 1;
|
||||
return true;
|
||||
}
|
||||
USED(src1);
|
||||
USED(src2);
|
||||
|
||||
pc = jmp_dest;
|
||||
return true;
|
||||
}
|
||||
case OP_JMP_OFF: {
|
||||
DECODE_A(instruction)
|
||||
u32 jmp_dest = locals[dest] + locals[src1];
|
||||
if (jmp_dest > cp) {
|
||||
status = 1;
|
||||
return true;
|
||||
}
|
||||
USED(src2);
|
||||
|
||||
pc = jmp_dest;
|
||||
return true;
|
||||
}
|
||||
case OP_JMP_FLAG: {
|
||||
DECODE_A(instruction)
|
||||
u32 mask;
|
||||
u32 jmp_dest = locals[dest];
|
||||
u32 jmp_dest = stack[--sp];
|
||||
if (jmp_dest > cp) {
|
||||
status = 1;
|
||||
return true;
|
||||
}
|
||||
USED(src1);
|
||||
USED(src2);
|
||||
|
||||
mask = -(u32)(status == 0);
|
||||
pc = (jmp_dest & mask) | (pc & ~mask);
|
||||
|
|
@ -616,14 +409,11 @@ bool step_vm() {
|
|||
COMPARE_AND_JUMP(i32, <=);
|
||||
}
|
||||
case OP_INT_TO_STR: {
|
||||
DECODE_A(instruction)
|
||||
|
||||
u32 i = MAX_LEN_INT32;
|
||||
i32 v = (i32)locals[src1];
|
||||
i32 v = (i32)stack[--sp];
|
||||
char buffer[MAX_LEN_INT32];
|
||||
i32 n = v;
|
||||
bool neg = n < 0;
|
||||
USED(src2);
|
||||
|
||||
if (neg)
|
||||
n = -n;
|
||||
|
|
@ -639,18 +429,16 @@ bool step_vm() {
|
|||
buffer[--i] = '0';
|
||||
|
||||
/* Copy from buffer[i] to buffer + MAX_LEN_INT32 */
|
||||
locals[dest] = str_alloc(buffer + i, MAX_LEN_INT32 - i);
|
||||
stack[sp++] = str_alloc(buffer + i, MAX_LEN_INT32 - i);
|
||||
|
||||
return pc;
|
||||
}
|
||||
case OP_NAT_TO_STR: {
|
||||
DECODE_A(instruction)
|
||||
|
||||
u32 v = (i32)locals[src1];
|
||||
u32 v = (i32)stack[--sp];
|
||||
char buffer[MAX_LEN_INT32];
|
||||
u32 n = v;
|
||||
u32 i = MAX_LEN_INT32;
|
||||
USED(src2);
|
||||
|
||||
do {
|
||||
buffer[--i] = radix_set[n % 10];
|
||||
n /= 10;
|
||||
|
|
@ -659,15 +447,13 @@ bool step_vm() {
|
|||
if (v == 0)
|
||||
buffer[--i] = '0';
|
||||
/* Copy from buffer[i] to buffer + MAX_LEN_INT32 */
|
||||
locals[dest] = str_alloc(buffer + i, MAX_LEN_INT32 - i);
|
||||
stack[sp++] = str_alloc(buffer + i, MAX_LEN_INT32 - i);
|
||||
|
||||
return pc;
|
||||
}
|
||||
case OP_REAL_TO_STR: {
|
||||
DECODE_A(instruction)
|
||||
|
||||
u32 i = 0, j = 0;
|
||||
i32 q = (i32)locals[src1];
|
||||
i32 q = (i32)stack[--sp];
|
||||
char buffer[MAX_LEN_INT32];
|
||||
u32 int_part, frac_part;
|
||||
|
||||
|
|
@ -678,7 +464,6 @@ bool step_vm() {
|
|||
|
||||
int_part = q >> 16;
|
||||
frac_part = q & 0xFFFF;
|
||||
USED(src2);
|
||||
|
||||
if (int_part == 0) {
|
||||
buffer[i++] = radix_set[0];
|
||||
|
|
@ -701,7 +486,7 @@ bool step_vm() {
|
|||
frac_part &= 0xFFFF;
|
||||
}
|
||||
|
||||
locals[dest] = str_alloc(buffer + i, MAX_LEN_INT32 - i);
|
||||
stack[sp++] = str_alloc(buffer + i, MAX_LEN_INT32 - i);
|
||||
|
||||
return pc;
|
||||
}
|
||||
|
|
|
|||
227
vm/vm.h
227
vm/vm.h
|
|
@ -3,121 +3,77 @@
|
|||
|
||||
#include "libc.h"
|
||||
|
||||
/**
|
||||
* Instruction Types
|
||||
*
|
||||
* A : [8:opcode][8:dest][8:src1][8:src2]
|
||||
* B : [8:opcode][8:dest][16:immediate]
|
||||
* C : [8:opcode][24:immediate]
|
||||
*/
|
||||
#define DECODE_OP(instruction) ((((u32)(instruction)) >> 24) & 0xFF)
|
||||
|
||||
#define ENCODE_A(opcode, dest, src1, src2) ((((u32)(opcode) & 0xFF) << 24) | \
|
||||
(((u32)(dest) & 0xFF) << 16) | \
|
||||
(((u32)(src1) & 0xFF) << 8) | \
|
||||
(((u32)(src2) & 0xFF)))
|
||||
|
||||
#define DECODE_A(instruction) \
|
||||
u8 dest = (((u32)(instruction)) >> 16) & 0xFF; \
|
||||
u8 src1 = (((u32)(instruction)) >> 8) & 0xFF; \
|
||||
u8 src2 = ((u32)(instruction)) & 0xFF;
|
||||
|
||||
#define ENCODE_B(opcode, dest, imm) ((((u32)(opcode) & 0xFF) << 24) | \
|
||||
(((u32)(dest) & 0xFF) << 16) | \
|
||||
(((u32)(imm)) & 0xFFFF))
|
||||
#define DECODE_B(instruction) \
|
||||
u8 dest = (((u32)(instruction)) >> 16) & 0xFF; \
|
||||
u16 imm = ((u32)(instruction)) & 0xFFFF;
|
||||
|
||||
#define ENCODE_C(opcode, imm) ((((u32)(opcode) & 0xFF) << 24) | \
|
||||
(((u32)(imm)) & 0xFFFFFF))
|
||||
#define DECODE_C(instruction) \
|
||||
u32 imm = ((u32)(instruction)) & 0xFFFFFF;
|
||||
|
||||
typedef enum {
|
||||
OP_HALT, /* halt : A : all zeros : halt execution */
|
||||
OP_CALL, /* call : A : dest args return : creates a new frame */
|
||||
OP_RETURN, /* return : B : dest return_flags: returns from a frame to the parent frame */
|
||||
OP_SYSCALL, /* syscall : A : id args mem_ptr : does a system call based on id with args */
|
||||
OP_LOAD_IMM, /* load_immediate : B : locals[dest] = const as u16 */
|
||||
OP_LOAD_UPPER_IMM, /* load_upper_immediate : B : locals[dest] = const as u32 << 16 | u16 */
|
||||
OP_LOAD_IND_8, /* load_indirect_8 : A : locals[dest] = memory[locals[src1]] as u8 */
|
||||
OP_LOAD_IND_16, /* load_indirect_16 : A : locals[dest] = memory[locals[src1]] as u16 */
|
||||
OP_LOAD_IND_32, /* load_indirect_32 : A : locals[dest] = memory[locals[src1]] as u32 */
|
||||
OP_LOAD_ABS_8, /* load_absolute_8 : E : locals[dest] = memory[src1:u32] as u8 */
|
||||
OP_LOAD_ABS_16, /* load_absolute_16 : E : locals[dest] = memory[src1:u32] as u16 */
|
||||
OP_LOAD_ABS_32, /* load_absolute_32 : E : locals[dest] = memory[src1:u32] as u32 */
|
||||
OP_LOAD_OFF_8, /* load_offset_8 : A : locals[dest] = memory[locals[src1] + locals[src2]] as u8 */
|
||||
OP_LOAD_OFF_16, /* load_offset_16 : A : locals[dest] = memory[locals[src1] + locals[src2]] as u16 */
|
||||
OP_LOAD_OFF_32, /* load_offset_32 : A : locals[dest] = memory[locals[src1] + locals[src2]] as u32 */
|
||||
OP_STORE_ABS_8, /* store_absolute_8 : E : memory[dest] = src1 && 0xFF */
|
||||
OP_STORE_ABS_16, /* store_absolute_16 : E : memory[dest] = src1 && 0xFFFF */
|
||||
OP_STORE_ABS_32, /* store_absolute_32 : E : memory[dest] = src1 */
|
||||
OP_STORE_IND_8, /* store_indirect_8 : A : memory[locals[dest]] = locals[src1] && 0xFF */
|
||||
OP_STORE_IND_16, /* store_indirect_16 : A : memory[locals[dest]] = locals[src1] && 0xFFFF*/
|
||||
OP_STORE_IND_32, /* store_indirect_32 : A : memory[locals[dest]] = locals[src1] */
|
||||
OP_STORE_OFF_8, /* store_offset_8 : A : memory[locals[dest] + locals[src2]] = locals[src1] && 0xFF */
|
||||
OP_STORE_OFF_16, /* store_offset_16 : A : memory[locals[dest] + locals[src2]] = locals[src1] && 0xFFFF */
|
||||
OP_STORE_OFF_32, /* store_offset_32 : A : memory[locals[dest] + locals[src2]] = locals[src1] */
|
||||
OP_MEM_ALLOC, /* alloc : A : memory[dest] = [locals[src1] as size + 4] */
|
||||
OP_MEM_CPY_8, /* memcpy_8 : A : memory[src1..src1+src2] = memory[dest..dest+src2] */
|
||||
OP_MEM_CPY_16, /* memcpy_16 : A : memory[src1..src1+src2] = memory[dest..dest+src2] */
|
||||
OP_MEM_CPY_32, /* memcpy_32 : A : memory[src1..src1+src2] = memory[dest..dest+src2] */
|
||||
OP_MEM_SET_8, /* memset_8 : A : memory[dest..dest+src2] = local[src1] as u8 */
|
||||
OP_MEM_SET_16, /* memset_16 : A : memory[dest..dest+src2] = local[src1] as u16 */
|
||||
OP_MEM_SET_32, /* memset_32 : A : memory[dest..dest+src2] = local[src1] as u32 */
|
||||
OP_MOV, /* mov : A : locals[dest] = locals[src1] */
|
||||
OP_PUSH, /* push : B : push u32 value onto the childs locals */
|
||||
OP_POP, /* pop : C : pop u32 value off the stack (move MP back) */
|
||||
OP_ADD_INT, /* add_int : A : locals[dest] = locals[src1] + locals[src2] */
|
||||
OP_SUB_INT, /* sub_int : A : locals[dest] = locals[src1] - locals[src2] */
|
||||
OP_MUL_INT, /* mul_int : A : locals[dest] = locals[src1] * locals[src2] */
|
||||
OP_DIV_INT, /* div_int : A : locals[dest] = locals[src1] / locals[src2] */
|
||||
OP_ADD_NAT, /* add_nat : A : locals[dest] = locals[src1] + locals[src2] */
|
||||
OP_SUB_NAT, /* sub_nat : A : locals[dest] = locals[src1] - locals[src2] */
|
||||
OP_MUL_NAT, /* mul_nat : A : locals[dest] = locals[src1] * locals[src2] */
|
||||
OP_DIV_NAT, /* div_nat : A : locals[dest] = locals[src1] / locals[src2] */
|
||||
OP_ADD_REAL, /* add_real : A : locals[dest] = locals[src1] + locals[src2] */
|
||||
OP_SUB_REAL, /* sub_real : A : locals[dest] = locals[src1] - locals[src2] */
|
||||
OP_MUL_REAL, /* mul_real : A : locals[dest] = locals[src1] * locals[src2] */
|
||||
OP_DIV_REAL, /* div_real : A : locals[dest] = locals[src1] / locals[src2] */
|
||||
OP_INT_TO_REAL, /* int_to_real : A : locals[dest] = locals[src1] as real */
|
||||
OP_INT_TO_NAT, /* int_to_nat : A : locals[dest] = locals[src1] as nat */
|
||||
OP_NAT_TO_REAL, /* nat_to_real : A : locals[dest] = locals[src1] as real */
|
||||
OP_NAT_TO_INT, /* nat_to_int : A : locals[dest] = locals[src1] as int */
|
||||
OP_REAL_TO_INT, /* real_to_int : A : locals[dest] = locals[src1] as int */
|
||||
OP_REAL_TO_NAT, /* real_to_nat : A : locals[dest] = locals[src1] as nat */
|
||||
OP_BIT_SHIFT_LEFT, /* bit_shift_left : A : locals[dest] = locals[src1] << locals[src2] */
|
||||
OP_BIT_SHIFT_RIGHT,/* bit_shift_right : A : locals[dest] = locals[src1] >> locals[src2] */
|
||||
OP_BIT_SHIFT_R_EXT,/* bit_shift_r_ext : A : locals[dest] as i32 = locals[src1] >> locals[src2] */
|
||||
OP_BIT_AND, /* bit_and : A : locals[dest] = locals[src1] & locals[src2] */
|
||||
OP_BIT_OR, /* bit_or : A : locals[dest] = locals[src1] | locals[src2] */
|
||||
OP_BIT_XOR, /* bit_xor : A : locals[dest] = locals[src1] ^ locals[src2] */
|
||||
OP_JMP_IMM, /* jump_immediate : E : jump to imm unconditionally */
|
||||
OP_JMP_ABS, /* jump_absolute : A : jump to locals[dest] unconditionally */
|
||||
OP_JMP_OFF, /* jump_offset : A : jump to locals[dest] + locals[src1] unconditionally */
|
||||
OP_JMP_FLAG, /* jump_if_flag : A : jump to locals[dest] if flag > 0 */
|
||||
OP_JEQ_INT, /* jump_eq_int : A : jump to locals[dest] if locals[src1] as int == locals[src2] as int */
|
||||
OP_JNE_INT, /* jump_neq_int : A : jump to locals[dest] if locals[src1] as int != locals[src2] as int */
|
||||
OP_JGT_INT, /* jump_gt_int : A : jump to locals[dest] if locals[src1] as int > locals[src2] as int */
|
||||
OP_JLT_INT, /* jump_lt_int : A : jump to locals[dest] if locals[src1] as int < locals[src2] as int */
|
||||
OP_JLE_INT, /* jump_le_int : A : jump to locals[dest] if locals[src1] as int <= locals[src2] as int */
|
||||
OP_JGE_INT, /* jump_ge_int : A : jump to locals[dest] if locals[src1] as int >= locals[src2] as int */
|
||||
OP_JEQ_NAT, /* jump_eq_nat : A : jump to locals[dest] if locals[src1] as nat == locals[src2] as nat */
|
||||
OP_JNE_NAT, /* jump_neq_nat : A : jump to locals[dest] if locals[src1] as nat != locals[src2] as nat */
|
||||
OP_JGT_NAT, /* jump_gt_nat : A : jump to locals[dest] if locals[src1] as nat > locals[src2] as nat */
|
||||
OP_JLT_NAT, /* jump_lt_nat : A : jump to locals[dest] if locals[src1] as nat < locals[src2] as nat */
|
||||
OP_JLE_NAT, /* jump_le_nat : A : jump to locals[dest] if locals[src1] as nat <= locals[src2] as nat */
|
||||
OP_JGE_NAT, /* jump_ge_nat : A : jump to locals[dest] if locals[src1] as nat >= locals[src2] as nat */
|
||||
OP_JEQ_REAL, /* jump_eq_real : A : jump to locals[dest] if locals[src1] as real == locals[src2] as real */
|
||||
OP_JNE_REAL, /* jump_neq_real : A : jump to locals[dest] if locals[src1] as real != locals[src2] as real */
|
||||
OP_JGE_REAL, /* jump_ge_real : A : jump to locals[dest] if locals[src1] as real >= locals[src2] as real */
|
||||
OP_JGT_REAL, /* jump_gt_real : A : jump to locals[dest] if locals[src1] as real > locals[src2] as real */
|
||||
OP_JLT_REAL, /* jump_lt_real : A : jump to locals[dest] if locals[src1] as real < locals[src2] as real */
|
||||
OP_JLE_REAL, /* jump_le_real : A : jump to locals[dest] if locals[src1] as real <= locals[src2] as real */
|
||||
OP_INT_TO_STR, /* int_to_str : A : locals[dest] = &mem[mp..] locals[src1] as str */
|
||||
OP_NAT_TO_STR, /* nat_to_str : A : locals[dest] = &mem[mp..] locals[src1] as str */
|
||||
OP_REAL_TO_STR, /* real_to_str : A : locals[dest] = &mem[mp..] locals[src1] as str */
|
||||
OP_HALT, /* `halt` | halt execution */
|
||||
OP_CALL, /* ptr `call` | creates a new frame */
|
||||
OP_RETURN, /* `return` | returns from a frame to the parent frame */
|
||||
OP_SYSCALL, /* `syscall` | id args mem_ptr : does a system call based on id with args */
|
||||
OP_LOAD_8, /* &dest `load-8` u8 | push memory[obj1] onto stack as u8 */
|
||||
OP_LOAD_16, /* &dest `load-16` u16 | push memory[obj1] onto stack as u16 */
|
||||
OP_LOAD_32, /* &dest `load` u32 | push memory[obj1] onto stack as u32 */
|
||||
OP_STORE_8, /* &dest obj1 `store-8` - | memory[dest] = obj1 << 8 */
|
||||
OP_STORE_16, /* &dest obj1 `store-16`- | memory[dest] = obj1 << 16 */
|
||||
OP_STORE_32, /* &dest obj1 `store` - | memory[dest] = obj1 */
|
||||
OP_MALLOC, /* size `malloc` ptr | allocate 'size + 4' of memory and push ptr to memory on stack */
|
||||
OP_GET, /* &local `get` obj1 | get the value from the local slot */
|
||||
OP_SET, /* obj1 &local `set` - | set the value of the local slot */
|
||||
OP_MEM_ALLOC, /* size `alloc` ptr | allocate 'size + 4' of memory and push ptr to memory on stack */
|
||||
OP_MEM_CPY_8, /* `memcpy_8` | memory[src1..src1+src2] = memory[dest..dest+src2] */
|
||||
OP_MEM_CPY_16, /* `memcpy_16` | memory[src1..src1+src2] = memory[dest..dest+src2] */
|
||||
OP_MEM_CPY_32, /* `memcpy_32` | memory[src1..src1+src2] = memory[dest..dest+src2] */
|
||||
OP_MEM_SET_8, /* `memset_8` | memory[dest..dest+src2] = local[src1] as u8 */
|
||||
OP_MEM_SET_16, /* `memset_16` | memory[dest..dest+src2] = local[src1] as u16 */
|
||||
OP_MEM_SET_32, /* `memset_32` | memory[dest..dest+src2] = local[src1] as u32 */
|
||||
OP_ADD_INT, /* obj2 obj1 `add_int` obj | obj1 + obj2 then push result on stack */
|
||||
OP_SUB_INT, /* obj2 obj1 `sub_int` obj | obj1 - obj2 then push result on stack */
|
||||
OP_MUL_INT, /* obj2 obj1 `mul_int` obj | obj1 * obj2 then push result on stack */
|
||||
OP_DIV_INT, /* obj2 obj1 `div_int` obj | obj1 / obj2 then push result on stack */
|
||||
OP_ADD_NAT, /* obj2 obj1 `add_nat` obj | obj1 + obj2 then push result on stack */
|
||||
OP_SUB_NAT, /* obj2 obj1 `sub_nat` obj | obj1 - obj2 then push result on stack */
|
||||
OP_MUL_NAT, /* obj2 obj1 `mul_nat` obj | obj1 * obj2 then push result on stack */
|
||||
OP_DIV_NAT, /* obj2 obj1 `div_nat` obj | obj1 / obj2 then push result on stack */
|
||||
OP_ADD_REAL, /* obj2 obj1 `add_real` obj | obj1 + obj2 then push result on stack */
|
||||
OP_SUB_REAL, /* obj2 obj1 `sub_real` obj | obj1 - obj2 then push result on stack */
|
||||
OP_MUL_REAL, /* obj2 obj1 `mul_real` obj | obj1 * obj2 then push result on stack */
|
||||
OP_DIV_REAL, /* obj2 obj1 `div_real` obj | obj1 / obj2 then push result on stack */
|
||||
OP_INT_TO_REAL, /* obj1 `int_to_real` obj1 as real | casts an int to a fixed number */
|
||||
OP_INT_TO_NAT, /* obj1 `int_to_nat` obj1 as nat | casts an int to a unsigned int */
|
||||
OP_NAT_TO_REAL, /* obj1 `nat_to_real` obj1 as real | casts a unsigned int to a fixed number */
|
||||
OP_NAT_TO_INT, /* obj1 `nat_to_int` obj1 as int | casts a unsigned int to an int */
|
||||
OP_REAL_TO_INT, /* obj1 `real_to_int` obj1 as int | casts a fixed number to an int */
|
||||
OP_REAL_TO_NAT, /* obj1 `real_to_nat` obj1 as nat | casts a fixed number to an unsigned int */
|
||||
OP_BIT_SHIFT_LEFT, /* obj2 obj1 `bit_shift_left` obj | src1] << locals[src2] */
|
||||
OP_BIT_SHIFT_RIGHT,/* obj2 obj1 `bit_shift_right` obj | src1] >> locals[src2] */
|
||||
OP_BIT_SHIFT_R_EXT,/* obj2 obj1 `bit_shift_r_ext` obj | src1 >> src2 then cast result as i32 */
|
||||
OP_BIT_AND, /* obj2 obj1 `bit_and` obj | obj1 & obj2 */
|
||||
OP_BIT_OR, /* obj2 obj1 `bit_or` obj | obj1 | obj2 */
|
||||
OP_BIT_XOR, /* obj2 obj1 `bit_xor` obj | obj1 ^ obj2 */
|
||||
OP_JMP, /* pc `jump` | jump unconditionally */
|
||||
OP_JMP_FLAG, /* pc `jump_if_flag` | jump to pc if flag > 0 */
|
||||
OP_JEQ_INT, /* obj2 obj1 pc `jump_eq_int` | jump to pc if obj1 as int == obj2 as int */
|
||||
OP_JNE_INT, /* obj2 obj1 pc `jump_neq_int` | jump to pc if obj1 as int != obj2 as int */
|
||||
OP_JGT_INT, /* obj2 obj1 pc `jump_gt_int` | jump to pc if obj1 as int > obj2 as int */
|
||||
OP_JLT_INT, /* obj2 obj1 pc `jump_lt_int` | jump to pc if obj1 as int < obj2 as int */
|
||||
OP_JLE_INT, /* obj2 obj1 pc `jump_le_int` | jump to pc if obj1 as int <= obj2 as int */
|
||||
OP_JGE_INT, /* obj2 obj1 pc `jump_ge_int` | jump to pc if obj1 as int >= obj2 as int */
|
||||
OP_JEQ_NAT, /* obj2 obj1 pc `jump_eq_nat` | jump to pc if obj1 as nat == obj2 as nat */
|
||||
OP_JNE_NAT, /* obj2 obj1 pc `jump_neq_nat` | jump to pc if obj1 as nat != obj2 as nat */
|
||||
OP_JGT_NAT, /* obj2 obj1 pc `jump_gt_nat` | jump to pc if obj1 as nat > obj2 as nat */
|
||||
OP_JLT_NAT, /* obj2 obj1 pc `jump_lt_nat` | jump to pc if obj1 as nat < obj2 as nat */
|
||||
OP_JLE_NAT, /* obj2 obj1 pc `jump_le_nat` | jump to pc if obj1 as nat <= obj2 as nat */
|
||||
OP_JGE_NAT, /* obj2 obj1 pc `jump_ge_nat` | jump to pc if obj1 as nat >= obj2 as nat */
|
||||
OP_JEQ_REAL, /* obj2 obj1 pc `jump_eq_real` | jump to pc if obj1 as real == obj2 as real */
|
||||
OP_JNE_REAL, /* obj2 obj1 pc `jump_neq_real` | jump to pc if obj1 as real != obj2 as real */
|
||||
OP_JGE_REAL, /* obj2 obj1 pc `jump_ge_real` | jump to pc if obj1 as real >= obj2 as real */
|
||||
OP_JGT_REAL, /* obj2 obj1 pc `jump_gt_real` | jump to pc if obj1 as real > obj2 as real */
|
||||
OP_JLT_REAL, /* obj2 obj1 pc `jump_lt_real` | jump to pc if obj1 as real < obj2 as real */
|
||||
OP_JLE_REAL, /* obj2 obj1 pc `jump_le_real` | jump to pc if obj1 as real <= obj2 as real */
|
||||
OP_INT_TO_STR, /* obj1 `int-to-string` str_ptr | convert obj1 to str */
|
||||
OP_NAT_TO_STR, /* obj1 `nat-to-string` str_ptr | convert obj1 to str */
|
||||
OP_REAL_TO_STR, /* obj1 `real-to-string` str_ptr | convert obj1 to str */
|
||||
OP_STR_TO_INT, /* str_ptr `string-to-int` obj | convert obj1 to int */
|
||||
OP_STR_TO_NAT, /* str_ptr `string-to-nat` obj | convert obj1 to nat */
|
||||
OP_STR_TO_REAL, /* str_ptr `string-to-real` obj | convert obj1 to real */
|
||||
OP_MAX_OPCODE /* not an opcode count of instructions */
|
||||
} Opcode;
|
||||
|
||||
|
|
@ -131,10 +87,12 @@ extern u32 pc; /* program counter */
|
|||
extern u32 cp; /* code pointer */
|
||||
extern u32 mp; /* memory pointer */
|
||||
extern u32 fp; /* frame pointer */
|
||||
extern u32 sp; /* stack pointer */
|
||||
extern u8 lc; /* child local count */
|
||||
extern u8 status; /* status flag */
|
||||
extern u8 interrupt; /* device interrupt */
|
||||
extern u32 *code; /* code */
|
||||
extern u32 *stack; /* stack */
|
||||
extern u8 *code; /* code */
|
||||
extern u8 *mem; /* memory */
|
||||
|
||||
#define READ_U8(addr) (mem[addr])
|
||||
|
|
@ -166,31 +124,34 @@ extern u8 *mem; /* memory */
|
|||
mem[addr + 3] = ((value) >> 24) & 0xFF; \
|
||||
} while (0)
|
||||
|
||||
#define COMPARE_AND_JUMP(type, op) \
|
||||
do { \
|
||||
i32 cond; \
|
||||
u32 mask, target; \
|
||||
type value; \
|
||||
type value2; \
|
||||
value2 = (type)stack[--sp]; \
|
||||
value = (type)stack[--sp]; \
|
||||
target = stack[--sp]; \
|
||||
cond = !!(value op value2); \
|
||||
mask = -(u32)cond; \
|
||||
pc = (target & mask) | (pc & ~mask); \
|
||||
return true; \
|
||||
} while (0)
|
||||
|
||||
#define MATH_OP(type, op) \
|
||||
do { \
|
||||
DECODE_A(instruction) \
|
||||
locals[dest] = ((type)locals[src1] op (type)locals[src2]); \
|
||||
type b = (type)stack[--sp]; \
|
||||
type a = (type)stack[--sp]; \
|
||||
stack[sp++] = (type)(a op b); \
|
||||
return true; \
|
||||
} while (0)
|
||||
|
||||
#define MATH_OP_NO_CAST(op) \
|
||||
do { \
|
||||
DECODE_A(instruction) \
|
||||
locals[dest] = (locals[src1] op locals[src2]); \
|
||||
return true; \
|
||||
} while (0)
|
||||
|
||||
#define COMPARE_AND_JUMP(type, op) \
|
||||
do { \
|
||||
DECODE_A(instruction) \
|
||||
i32 cond; \
|
||||
u32 mask; \
|
||||
u32 target = locals[dest]; \
|
||||
type value = (type)locals[src1]; \
|
||||
type value2 = (type)locals[src2]; \
|
||||
cond = !!(value op value2); \
|
||||
mask = -(u32)cond; \
|
||||
pc = (target & mask) | (pc & ~mask); \
|
||||
u32 a = stack[--sp]; \
|
||||
u32 b = stack[--sp]; \
|
||||
stack[sp++] = a op b; \
|
||||
return true; \
|
||||
} while (0)
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue