diff --git a/src/interp.c b/src/interp.c index 6b58f1a..c79fbe3 100644 --- a/src/interp.c +++ b/src/interp.c @@ -54,6 +54,17 @@ void memory_set8(uint64_t addr, unsigned char byte) { } } +void memory_set64(uint64_t addr, uint64_t x) { + memory_set8(addr+0, (x >> 56) & 0xFF); + memory_set8(addr+1, (x >> 48) & 0xFF); + memory_set8(addr+2, (x >> 40) & 0xFF); + memory_set8(addr+3, (x >> 32) & 0xFF); + memory_set8(addr+4, (x >> 24) & 0xFF); + memory_set8(addr+5, (x >> 16) & 0xFF); + memory_set8(addr+6, (x >> 8) & 0xFF); + memory_set8(addr+7, (x >> 0) & 0xFF); +} + unsigned char memory_get8(uint64_t addr) { if (isMMIO(addr)) { if (addr == UART_RX) { @@ -70,6 +81,19 @@ unsigned char memory_get8(uint64_t addr) { } } +uint64_t memory_get64(uint64_t addr) { + return + ((uint64_t) memory_get8(addr+0) << 56) + + ((uint64_t) memory_get8(addr+1) << 48) + + ((uint64_t) memory_get8(addr+2) << 40) + + ((uint64_t) memory_get8(addr+3) << 32) + + ((uint64_t) memory_get8(addr+4) << 24) + + ((uint64_t) memory_get8(addr+5) << 16) + + ((uint64_t) memory_get8(addr+6) << 8) + + ((uint64_t) memory_get8(addr+7) << 0); +} + + int load_program(const char *fname) { FILE *f = fopen(fname, "rb"); int byte; @@ -161,12 +185,24 @@ int main(int argc, char **argv) { negativeFlag = (val < 0); break; } - case 0x60: { // AddR64 + case 0x94: { // Mov64 + unsigned char dst = inputs[0]; + unsigned char src = inputs[1]; + registers[dst] = registers[src]; + break; + } + case 0x6E: { // AddR64 unsigned char dst = inputs[0]; unsigned char src = inputs[1]; registers[dst] += registers[src]; break; } + case 0x6F: { // SubR64 + unsigned char dst = inputs[0]; + unsigned char src = inputs[1]; + registers[dst] -= registers[src]; + break; + } case 0x70: { // MulR64 unsigned char dst = inputs[0]; unsigned char src = inputs[1]; @@ -198,6 +234,25 @@ int main(int argc, char **argv) { } break; } + case 0x46: { // Call + unsigned char addr = inputs[0]; + xSp -= 8; + memory_set64(xSp, xBp); + xSp -= 8; + memory_set64(xSp, xPc); + xBp = xSp; + xPc = registers[addr]; + break; + } + case 0x02: { // Ret + uint64_t addr = memory_get64(xBp); + uint64_t oldBase = memory_get64(xBp+8); + + xPc = addr; + xSp = xBp+16; + xBp = oldBase; + break; + } default: { printf("Unknown instruction: 0x%02X\n", inst); exit(1); diff --git a/tests/call.asm b/tests/call.asm new file mode 100644 index 0000000..e0eb369 --- /dev/null +++ b/tests/call.asm @@ -0,0 +1,15 @@ +include "fvm.inc" + +org 0x4000000000000000 +start: + MovI64 r95, UART_TX + call function + MovI64 r2, 0x69 + St8 r2, r95 + MovI64 r2, 0x0a + St8 r2, r95 + Halt +function: + MovI64 r2, 0x48 + St8 r2, r95 + Ret diff --git a/tests/fvm.inc b/tests/fvm.inc index 9ac7d46..342e980 100644 --- a/tests/fvm.inc +++ b/tests/fvm.inc @@ -13,7 +13,8 @@ define r9 9 define r10 10 define r11 11 define r12 12 -define r13 13 define r14 14 +define r13 13 +define r14 14 define r15 15 define r16 16 define r17 17 @@ -217,6 +218,12 @@ macro MovI64 dst, val _dq_be val end macro +macro Mov64 dst, src + db 0x94 + db dst + db src +end macro + macro Ld8 dst, addr db 0x93 db dst @@ -230,7 +237,13 @@ macro St8 dst, addr end macro macro AddR64 dst, src - db 0x60 + db 0x6E + db dst + db src +end macro + +macro SubR64 dst, src + db 0x6F db dst db src end macro @@ -278,6 +291,21 @@ macro JmpIZ addr JmpRIZ 127 end macro +macro callR addr + db 0x46 + db addr +end macro + +macro call val + MovI64 127, val + db 0x46 + db 127 +end macro + +macro Ret + db 2 +end macro + macro Halt db 0 end macro