some speed enhancements

This commit is contained in:
zongor 2026-01-10 23:23:28 -08:00
parent 3eb121d5b8
commit c1b629e368
3 changed files with 84 additions and 129 deletions

View File

@ -11,11 +11,12 @@ bool init_vm() {
mem = lmem; mem = lmem;
memset(mem, 0, MEMORY_SIZE*sizeof(u8)); memset(mem, 0, MEMORY_SIZE*sizeof(u8));
code = lcode; code = lcode;
sp = 0; lc = 0;
mp = 0; mp = 0;
cp = 0; cp = 0;
pc = 0; pc = 0;
interrupt = 0; interrupt = 0;
status = 0;
return true; return true;
} }

179
vm/vm.c
View File

@ -5,8 +5,8 @@ u32 pc; /* program counter */
u32 cp; /* code pointer */ u32 cp; /* code pointer */
u32 mp; /* memory pointer */ u32 mp; /* memory pointer */
u32 fp; /* frame pointer */ u32 fp; /* frame pointer */
u8 sp; /* child local count */ u8 lc; /* child local count */
u32 flag; /* flag */ u8 status; /* status flag */
u8 interrupt; /* device interrupt */ u8 interrupt; /* device interrupt */
u32 *code; /* code */ u32 *code; /* code */
u8 *mem; /* memory */ u8 *mem; /* memory */
@ -15,6 +15,8 @@ bool step_vm() {
u32 instruction = code[pc++]; u32 instruction = code[pc++];
u8 opcode = DECODE_OP(instruction); u8 opcode = DECODE_OP(instruction);
u32 *locals = (u32*)(&mem[fp]);
u32 *globals = (u32*)(mem);
switch (opcode) { switch (opcode) {
case OP_HALT: { case OP_HALT: {
@ -23,28 +25,24 @@ bool step_vm() {
} }
case OP_CALL: { case OP_CALL: {
DECODE_A(instruction) DECODE_A(instruction)
u32 fn_ptr; /* function to jump to */
u32 fn_ptr = locals[dest];
u32 rd = fp + (dest * 4);/* function to jump to */ /* get mp in 'global indexing mode' */
u32 r1 = src1; /* locals count */ u32 gmp = mp / 4;
u32 r2 = fp + (src2 * 4);/* local child return value to*/ /* reset child locals counter */
lc = 0;
fn_ptr = READ_U32(rd);
sp = 0;
/* push parents frame value to reset the heap to */ /* push parents frame value to reset the heap to */
WRITE_U32(mp, fp); globals[gmp] = fp;
mp += 4;
/* push return address to child frame */ /* push return address to child frame */
WRITE_U32(mp, pc); globals[gmp + 1] = pc;
mp += 4;
/* push local address to return the value to */ /* push local address to return the value to */
WRITE_U32(mp, r2); globals[gmp + 2] = fp + (src2 * 4);
mp += 4; /* increase the mp to new size */
mp += FRAME_HEADER_SIZE;
/* now set the frame pointer, where the locals start */ /* now set the frame pointer, where the locals start */
fp = mp; fp = mp;
/* move mp forward by count many locals */ /* move mp forward by count many locals */
mp += (4 * r1); mp += (4 * src1);
/* jump to dest_ptr */ /* jump to dest_ptr */
pc = fn_ptr; pc = fn_ptr;
return true; return true;
@ -52,16 +50,15 @@ bool step_vm() {
case OP_RETURN: { case OP_RETURN: {
DECODE_B(instruction) DECODE_B(instruction)
u32 i, size = 0; u32 i, size = 0;
u32 return_local = fp + (dest * 4); u32 return_value = locals[dest];
u32 return_value = READ_U32(return_local);
bool is_ptr = (((u32)(1)) << 15) & imm; bool is_ptr = (((u32)(1)) << 15) & imm;
bool replaces_value = (((u32)(1)) << 14) & imm; bool replaces_value = (((u32)(1)) << 14) & imm;
/* reset mp to saved mp, use header size to get "real" start of frame */ /* reset mp to saved mp, use header size to get "real" start of frame */
u32 frame_start = fp - FRAME_HEADER_SIZE; u32 frame_start = (fp / 4) - 3;
u32 parent_fp = READ_U32(frame_start); u32 parent_fp = globals[frame_start];
u32 return_address = READ_U32(frame_start + 4); u32 return_address = globals[frame_start + 1];
u32 parent_local_return_address = READ_U32(frame_start + 8); u32 parent_local_return_address = globals[frame_start + 2];
USED(replaces_value); USED(replaces_value);
/* reset memory to parents end of memory */ /* reset memory to parents end of memory */
@ -94,36 +91,32 @@ bool step_vm() {
u32 id = dest; /* syscall id */ u32 id = dest; /* syscall id */
u32 size = src1; /* size of heap at that pointer */ u32 size = src1; /* size of heap at that pointer */
u32 rd = fp + (src2 * 4); /* the pointer */ u32 rd = fp + (src2 * 4); /* the pointer */
flag = syscall(id, size, rd); status = syscall(id, size, rd);
return true; return true;
} }
case OP_PUSH: { case OP_PUSH: {
DECODE_B(instruction) DECODE_B(instruction)
u32 rd = fp + (dest * 4);
u32 val = READ_U32(rd);
USED(imm); USED(imm);
WRITE_U32((mp + ((4 * sp) + FRAME_HEADER_SIZE)), val); globals[(mp / 4) + lc + 3] = locals[dest];
sp++; lc++;
return true; return true;
} }
case OP_POP: { case OP_POP: {
DECODE_C(instruction) DECODE_C(instruction)
USED(imm); USED(imm);
mp -= 4; mp -= 4;
sp--; lc--;
return true; return true;
} }
case OP_LOAD_IMM: { case OP_LOAD_IMM: {
DECODE_B(instruction) DECODE_B(instruction)
u32 rd = fp + (dest * 4); locals[dest] = imm;
WRITE_U32(rd, imm);
return true; return true;
} }
case OP_LOAD_UPPER_IMM: { case OP_LOAD_UPPER_IMM: {
DECODE_B(instruction) DECODE_B(instruction)
u32 rd = fp + (dest * 4); u32 value = locals[dest];
u32 value = READ_U32(rd); locals[dest] = (value | (((u32)(imm)) << 16));
WRITE_U32(rd, (value | (((u32)(imm)) << 16)));
return true; return true;
} }
case OP_LOAD_IND_8: { case OP_LOAD_IND_8: {
@ -172,48 +165,37 @@ bool step_vm() {
WRITE_U32(ldest, mp); WRITE_U32(ldest, mp);
size = READ_U32(r1); size = READ_U32(r1);
WRITE_U32(mp, size); WRITE_U32(mp, size);
mp += (size + 4); mp += (4 * (size + 4));
return true; return true;
} }
case OP_MEM_CPY_8: { case OP_MEM_CPY_8: {
DECODE_A(instruction) DECODE_A(instruction)
u32 i, count, mdest, msrc; u32 i = 0;
u32 mdest = locals[dest];
u32 rd = fp + (dest * 4); u32 msrc = locals[src1];
u32 r1 = fp + (src1 * 4); u32 count = locals[src2];
u32 r2 = fp + (src2 * 4);
mdest = READ_U32(rd);
msrc = READ_U32(r1);
count = READ_U32(r2);
if (mdest + count >= mp) { if (mdest + count >= mp) {
flag = 1; status = 1;
return true; return true;
} }
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
u8 value = READ_U8(mdest + i); mem[msrc + i] = mem[mdest + i];
WRITE_U8(msrc + i, value);
} }
flag = 0; status = 0;
return true; return true;
} }
case OP_MEM_CPY_16: { case OP_MEM_CPY_16: {
DECODE_A(instruction) DECODE_A(instruction)
u32 i, count, mdest, msrc; u32 i = 0;
u32 mdest = locals[dest];
u32 rd = fp + (dest * 4); u32 msrc = locals[src1];
u32 r1 = fp + (src1 * 4); u32 count = locals[src2] * 2;
u32 r2 = fp + (src2 * 4);
mdest = READ_U32(rd);
msrc = READ_U32(r1);
count = READ_U32(r2);
if (mdest + count >= mp) { if (mdest + count >= mp) {
flag = 1; status = 1;
return true; return true;
} }
@ -222,32 +204,26 @@ bool step_vm() {
WRITE_U16(msrc + i, value); WRITE_U16(msrc + i, value);
} }
flag = 0; status = 0;
return true; return true;
} }
case OP_MEM_CPY_32: { case OP_MEM_CPY_32: {
DECODE_A(instruction) DECODE_A(instruction)
u32 i, count, mdest, msrc; u32 i = 0;
u32 mdest = locals[dest];
u32 rd = fp + (dest * 4); u32 msrc = locals[src1];
u32 r1 = fp + (src1 * 4); u32 count = locals[src2];
u32 r2 = fp + (src2 * 4);
mdest = READ_U32(rd);
msrc = READ_U32(r1);
count = READ_U32(r2);
if (mdest + count >= mp) { if (mdest + count >= mp) {
flag = 1; status = 1;
return true; return true;
} }
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
u32 value = READ_U32(mdest + i); globals[msrc + i] = globals[mdest + i];
WRITE_U32(msrc + i, value);
} }
flag = 0; status = 0;
return true; return true;
} }
case OP_MEM_SET_8: { case OP_MEM_SET_8: {
@ -262,7 +238,7 @@ bool step_vm() {
u32 count = READ_U32(r2); u32 count = READ_U32(r2);
if (r2 == 0) { if (r2 == 0) {
flag = 1; status = 1;
return true; return true;
} }
@ -270,15 +246,15 @@ bool step_vm() {
end = start + count; end = start + count;
if (start >= mp || r2 > mp || end > mp) { if (start >= mp || r2 > mp || end > mp) {
flag = 1; status = 1;
return true; return true;
} }
for (i = start; i < end; i++) { for (i = start; i < end; i++) {
WRITE_U8(i, value); mem[i] = value;
} }
flag = 0; status = 0;
return true; return true;
} }
case OP_MEM_SET_16: { case OP_MEM_SET_16: {
@ -293,7 +269,7 @@ bool step_vm() {
u32 count = READ_U32(r2); u32 count = READ_U32(r2);
if (r2 == 0) { if (r2 == 0) {
flag = 1; status = 1;
return true; return true;
} }
@ -301,7 +277,7 @@ bool step_vm() {
end = start + count; end = start + count;
if (start >= mp || r2 > mp || end > mp) { if (start >= mp || r2 > mp || end > mp) {
flag = 1; status = 1;
return true; return true;
} }
@ -309,7 +285,7 @@ bool step_vm() {
WRITE_U16(i, value); WRITE_U16(i, value);
} }
flag = 0; status = 0;
return true; return true;
} }
case OP_MEM_SET_32: { case OP_MEM_SET_32: {
@ -324,7 +300,7 @@ bool step_vm() {
u32 count = READ_U32(r2); u32 count = READ_U32(r2);
if (r2 == 0) { if (r2 == 0) {
flag = 1; status = 1;
return true; return true;
} }
@ -332,7 +308,7 @@ bool step_vm() {
end = start + count; end = start + count;
if (start >= mp || r2 > mp || end > mp) { if (start >= mp || r2 > mp || end > mp) {
flag = 1; status = 1;
return true; return true;
} }
@ -340,7 +316,7 @@ bool step_vm() {
WRITE_U32(i, value); WRITE_U32(i, value);
} }
flag = 0; status = 0;
return true; return true;
} }
case OP_MOV: { case OP_MOV: {
@ -384,33 +360,26 @@ bool step_vm() {
} }
case OP_MUL_REAL: { case OP_MUL_REAL: {
DECODE_A(instruction) DECODE_A(instruction)
u32 rd = fp + (dest * 4);
u32 r1 = fp + (src1 * 4);
u32 r2 = fp + (src2 * 4);
i32 src1_whole = (i32)READ_U32(r1) >> 16; i32 src1_whole = (i32)locals[src1] >> 16;
i32 src2_whole = (i32)READ_U32(r2) >> 16; i32 src2_whole = (i32)locals[src2] >> 16;
i32 src1_decimal = (i32)READ_U32(r1) & 16; i32 src1_decimal = (i32)locals[src1] & 16;
i32 src2_decimal = (i32)READ_U32(r2) & 16; i32 src2_decimal = (i32)locals[src2] & 16;
i32 result = 0; i32 result = 0;
result += (src1_whole * src2_whole) << 16; result += (src1_whole * src2_whole) << 16;
result += (src1_whole * src2_decimal); result += (src1_whole * src2_decimal);
result += (src1_decimal * src2_whole); result += (src1_decimal * src2_whole);
result += ((src1_decimal * src2_decimal) >> 16) & 16; result += ((src1_decimal * src2_decimal) >> 16) & 16;
WRITE_U32(rd, result); locals[dest] = result;
return true; return true;
} }
case OP_DIV_REAL: { case OP_DIV_REAL: {
DECODE_A(instruction) DECODE_A(instruction)
i32 result; i32 result;
u32 rd = fp + (dest * 4); i32 src1_val = (i32)locals[src1];
u32 r1 = fp + (src1 * 4); i32 src2_val = (i32)locals[src2];
u32 r2 = fp + (src2 * 4);
i32 src1_val = (i32)READ_U32(r1);
i32 src2_val = (i32)READ_U32(r2);
u32 src2_reciprocal = 1; u32 src2_reciprocal = 1;
src2_reciprocal <<= 31; src2_reciprocal <<= 31;
@ -418,7 +387,8 @@ bool step_vm() {
result = src1_val * src2_reciprocal; result = src1_val * src2_reciprocal;
result <<= 1; result <<= 1;
WRITE_U32(rd, result);
locals[dest] = result;
return true; return true;
} }
case OP_INT_TO_REAL: { case OP_INT_TO_REAL: {
@ -503,7 +473,7 @@ bool step_vm() {
u32 rd = fp + (dest * 4); u32 rd = fp + (dest * 4);
u32 jmp_dest = READ_U32(rd); u32 jmp_dest = READ_U32(rd);
if (jmp_dest > cp) { if (jmp_dest > cp) {
flag = 1; status = 1;
return true; return true;
} }
USED(src1); USED(src1);
@ -519,7 +489,7 @@ bool step_vm() {
u32 jmp_dest = READ_U32(rd) + READ_U32(r1); u32 jmp_dest = READ_U32(rd) + READ_U32(r1);
if (jmp_dest > cp) { if (jmp_dest > cp) {
flag = 1; status = 1;
return true; return true;
} }
USED(src2); USED(src2);
@ -530,16 +500,15 @@ bool step_vm() {
case OP_JMP_FLAG: { case OP_JMP_FLAG: {
DECODE_A(instruction) DECODE_A(instruction)
u32 mask; u32 mask;
u32 rd = fp + (dest * 4); u32 jmp_dest = locals[dest];
u32 jmp_dest = READ_U32(rd);
if (jmp_dest > cp) { if (jmp_dest > cp) {
flag = 1; status = 1;
return true; return true;
} }
USED(src1); USED(src1);
USED(src2); USED(src2);
mask = -(u32)(flag == 0); mask = -(u32)(status == 0);
pc = (jmp_dest & mask) | (pc & ~mask); pc = (jmp_dest & mask) | (pc & ~mask);
return true; return true;
} }
@ -600,6 +569,6 @@ bool step_vm() {
} }
/* something went very wrong */ /* something went very wrong */
flag = 255; status = 255;
return false; return false;
} }

31
vm/vm.h
View File

@ -127,8 +127,8 @@ extern u32 pc; /* program counter */
extern u32 cp; /* code pointer */ extern u32 cp; /* code pointer */
extern u32 mp; /* memory pointer */ extern u32 mp; /* memory pointer */
extern u32 fp; /* frame pointer */ extern u32 fp; /* frame pointer */
extern u8 sp; /* child local count */ extern u8 lc; /* child local count */
extern u32 flag; /* flag */ extern u8 status; /* status flag */
extern u8 interrupt; /* device interrupt */ extern u8 interrupt; /* device interrupt */
extern u32 *code; /* code */ extern u32 *code; /* code */
extern u8 *mem; /* memory */ extern u8 *mem; /* memory */
@ -165,24 +165,14 @@ extern u8 *mem; /* memory */
#define MATH_OP(type, op) \ #define MATH_OP(type, op) \
do { \ do { \
DECODE_A(instruction) \ DECODE_A(instruction) \
u32 rd = fp + (dest * 4); \ locals[dest] = ((type)locals[src1] op (type)locals[src2]); \
u32 r1 = fp + (src1 * 4); \
u32 r2 = fp + (src2 * 4); \
type result = ((type)READ_U32(r1) op (type)READ_U32(r2)); \
mem[(rd)] = (result) & 0xFF; \
mem[(rd) + 1] = ((result) >> 8) & 0xFF; \
mem[(rd) + 2] = ((result) >> 16) & 0xFF; \
mem[(rd) + 3] = ((result) >> 24) & 0xFF; \
return true; \ return true; \
} while (0) } while (0)
#define MATH_OP_NO_CAST(op) \ #define MATH_OP_NO_CAST(op) \
do { \ do { \
DECODE_A(instruction) \ DECODE_A(instruction) \
u32 rd = fp + (dest * 4); \ locals[dest] = (locals[src1] op locals[src2]); \
u32 r1 = fp + (src1 * 4); \
u32 r2 = fp + (src2 * 4); \
WRITE_U32(rd, (READ_U32(r1) op READ_U32(r2))); \
return true; \ return true; \
} while (0) } while (0)
@ -190,15 +180,10 @@ extern u8 *mem; /* memory */
do { \ do { \
DECODE_A(instruction) \ DECODE_A(instruction) \
i32 cond; \ i32 cond; \
u32 mask, target; \ u32 mask; \
type value; \ u32 target = locals[dest]; \
type value2; \ type value = (type)locals[src1]; \
u32 rd = fp + (dest * 4); \ type value2 = (type)locals[src2]; \
u32 r1 = fp + (src1 * 4); \
u32 r2 = fp + (src2 * 4); \
target = READ_U32(rd); \
value = (type)READ_U32(r1); \
value2 = (type)READ_U32(r2); \
cond = !!(value op value2); \ cond = !!(value op value2); \
mask = -(u32)cond; \ mask = -(u32)cond; \
pc = (target & mask) | (pc & ~mask); \ pc = (target & mask) | (pc & ~mask); \