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;
memset(mem, 0, MEMORY_SIZE*sizeof(u8));
code = lcode;
sp = 0;
lc = 0;
mp = 0;
cp = 0;
pc = 0;
interrupt = 0;
status = 0;
return true;
}

179
vm/vm.c
View File

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

31
vm/vm.h
View File

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