summaryrefslogtreecommitdiff
path: root/src/virtualmachine
diff options
context:
space:
mode:
authorSimon Robertshaw <simon@hardwired.org.uk>2012-09-09 16:55:03 (GMT)
committer Simon Robertshaw <simon@hardwired.org.uk>2012-09-09 16:55:03 (GMT)
commit2d2f8713bc86fe02aa6eae3fcb56365d39a65b21 (patch)
tree81232229f92b7684bfcdf0af82e4d17dbef4ab43 /src/virtualmachine
parent7b05862cfe69ece782493b9f3f78338262e569bd (diff)
downloadpowder-2d2f8713bc86fe02aa6eae3fcb56365d39a65b21.zip
powder-2d2f8713bc86fe02aa6eae3fcb56365d39a65b21.tar.gz
Move opcodes and syscalls out of main virtualmachine coee
Diffstat (limited to 'src/virtualmachine')
-rw-r--r--src/virtualmachine/Operations.cpp356
-rw-r--r--src/virtualmachine/Operations.inl (renamed from src/virtualmachine/OpCodes.inl)0
-rw-r--r--src/virtualmachine/Syscalls.cpp33
-rw-r--r--src/virtualmachine/Syscalls.inl (renamed from src/virtualmachine/Traps.inl)0
-rw-r--r--src/virtualmachine/VirtualMachine.cpp502
-rw-r--r--src/virtualmachine/VirtualMachine.h11
6 files changed, 455 insertions, 447 deletions
diff --git a/src/virtualmachine/Operations.cpp b/src/virtualmachine/Operations.cpp
new file mode 100644
index 0000000..1223c81
--- /dev/null
+++ b/src/virtualmachine/Operations.cpp
@@ -0,0 +1,356 @@
+#include "VirtualMachine.h"
+
+namespace vm
+{
+ #define OPDEF(n) &VirtualMachine::Op##n,
+ OperationFunction VirtualMachine::operations[] =
+ {
+ #include "Operations.inl"
+ };
+ #undef OPDEF
+
+ #define OPDEF(n) int VirtualMachine::Op##n(word parameter)
+
+ #define R0 (r[0])
+ #define R1 (r[1])
+ #define R2 (r[2])
+
+
+ OPDEF(UNDEF)
+ {
+ /* Die horribly. */
+ throw RuntimeException();
+ return -1;
+ }
+
+ OPDEF(IGNORE)
+ {
+ /* NOP */
+ throw RuntimeException();
+ return 0;
+ }
+
+ OPDEF(BREAK)
+ {
+ /* Usage never spotted. */
+ /* Die horribly? */
+ throw RuntimeException();
+ return -1;
+ }
+
+ /*
+ Stack on entering...
+
+ no locals: ENTER 8
+ 1 words locals: ENTER 16
+ 2 words locals: ENTER 20
+ 3 words locals: ENTER 24
+ etc.
+
+ address of argument:
+ ADDRFP4 v => OP_LOCAL (16 + currentLocals + currentArgs + v)
+ address of local:
+ ADDRLP4 v => OP_LOCAL (8 + currentArgs + v)
+
+ RP [ ] ??? (oldPC?)
+ [ ] ???
+ [ ] \
+ ... > locals (args marshalling)
+ [ ] /
+ [ ] \
+ ... > locals
+ [ ] / (ADDRLP4 v => OP_LOCAL (8 + currentArgs + v))
+ (oldRP?) [ ] ???
+ [ ] ???
+ [ ] (my args?)
+ ...
+ [ ]
+ */
+
+ OPDEF(ENTER) /* ??? */
+ {
+ while (parameter.int4 > (2 * sizeof(word)))
+ {
+ RPush<int4_t>(0); /* init zero */
+ parameter.int4 -= sizeof(word);
+ }
+ RPush(Pop()); //Program Counter
+ RPush<int4_t>(0); //Unknown
+ return 0;
+ }
+
+ OPDEF(LEAVE) /* ??? */
+ {
+ RPop(); //Unknown
+ parameter.int4 -= sizeof(word);
+ PC = RPop<int4_t>(); //Program counter
+ parameter.int4 -= sizeof(word);
+ while (parameter.int4 > 0)
+ {
+ RPop();
+ parameter.int4 -= sizeof(word);
+ }
+ return 0;
+ }
+
+ OPDEF(CALL) /* Call subroutine. */
+ {
+ R0 = Pop();
+ Push<int4_t>(PC);
+ PC = R0.int4;
+ return 0;
+ }
+
+ OPDEF(PUSH) /* [DP] <- 0; DP++ */
+ {
+ Push(0);
+ return 0;
+ }
+
+ OPDEF(POP) /* DP-- */
+ {
+ Pop();
+ return 0;
+ }
+
+ OPDEF(CONST) /* [DP] <- parm; DP++ */
+ {
+ Push(parameter);
+ return 0;
+ }
+
+ OPDEF(LOCAL) /* [DP] <- [RP-n] */
+ {
+ Push<int4_t>(RP + parameter.int4);
+ return 0;
+ }
+
+ OPDEF(JUMP) /* PC <- [DP] */
+ {
+ PC = Pop<int4_t>();
+ return 0;
+ }
+
+ #define CMP(type, op) \
+ { \
+ R0 = Pop(); \
+ cm = (Pop<type##_t>() op R0.type); \
+ if (cm) \
+ PC = parameter.uint4; \
+ return 0; \
+ }
+
+ OPDEF(EQ) /* if [DP] == [DP-1] then PC <- parm; DP <- DP-2 */
+ CMP(int4, ==)
+
+ OPDEF(NE) /* if [DP] == [DP-1] then PC <- parm; DP <- DP-2 */
+ CMP(int4, !=)
+
+ OPDEF(LTI) /* if [DP] < [DP-1] then PC <- parm; DP <- DP-2 */
+ CMP(int4, <)
+
+ OPDEF(LEI) /* if [DP] <= [DP-1] then PC <- parm; DP <- DP-2 */
+ CMP(int4, <=)
+
+ OPDEF(GTI) /* if [DP] > [DP-1] then PC <- parm; DP <- DP-2 */
+ CMP(int4, >)
+
+ OPDEF(GEI) /* if [DP] >= [DP-1] then PC <- parm; DP <- DP-2 */
+ CMP(int4, >=)
+
+ OPDEF(LTU) /* if [DP] < [DP-1] then PC <- parm; DP <- DP-2 */
+ CMP(uint4, <)
+
+ OPDEF(LEU) /* if [DP] <= [DP-1] then PC <- parm; DP <- DP-2 */
+ CMP(uint4, <=)
+
+ OPDEF(GTU) /* if [DP] > [DP-1] then PC <- parm; DP <- DP-2 */
+ CMP(uint4, >)
+
+ OPDEF(GEU) /* if [DP] >= [DP-1] then PC <- parm; DP <- DP-2 */
+ CMP(uint4, >=)
+
+ OPDEF(EQF) /* if [DP] == [DP-1] then PC <- parm; DP <- DP-2 */
+ CMP(float4, ==)
+
+ OPDEF(NEF) /* if [DP] != [DP-1] then PC <- parm; DP <- DP-2 */
+ CMP(float4, !=)
+
+ OPDEF(LTF) /* if [DP] < [DP-1] then PC <- parm; DP <- DP-2 */
+ CMP(float4, <)
+
+ OPDEF(LEF) /* if [DP] <= [DP-1] then PC <- parm; DP <- DP-2 */
+ CMP(float4, <=)
+
+ OPDEF(GTF) /* if [DP] > [DP-1] then PC <- parm; DP <- DP-2 */
+ CMP(float4, >)
+
+ OPDEF(GEF) /* if [DP] >= [DP-1] then PC <- parm; DP <- DP-2 */
+ CMP(float4, >=)
+
+
+ OPDEF(LOAD1) /* [DP] <- [[DP]] */
+ {
+ Push<uint1_t>(Get<uint1_t>(Pop<uint4_t>()));
+ return 0;
+ }
+
+ OPDEF(LOAD2) /* [DP] <- [[DP]] */
+ {
+ Push<uint2_t>(Get<uint2_t>(Pop<uint4_t>()));
+ return 0;
+ }
+
+ OPDEF(LOAD4) /* [DP] <- [[DP]] */
+ {
+ Push<uint4_t>(Get<uint4_t>(Pop<uint4_t>()));
+ return 0;
+ }
+
+ OPDEF(STORE1) /* [DP-1] <- [DP]; DP <- DP-2 */
+ {
+ Set<uint1_t>(Pop<uint4_t>(), Pop<uint1_t>());
+ return 0;
+ }
+
+ OPDEF(STORE2) /* [DP-1] <- [DP]; DP <- DP-2 */
+ {
+ Set<uint2_t>(Pop<uint4_t>(), Pop<uint2_t>());
+ return 0;
+ }
+
+ OPDEF(STORE4) /* [DP-1] <- [DP]; DP <- DP-2 */
+ {
+ Set<uint4_t>(Pop<uint4_t>(), Pop<uint4_t>());
+ return 0;
+ }
+
+ OPDEF(ARG) /* Marshal TOS to to-call argument list */
+ {
+ Marshal(parameter.int4, Pop());
+ return 0;
+ }
+
+ OPDEF(BLOCK_COPY) /* XXX */
+ {
+ R1 = Pop();
+ R0 = Pop();
+ if(R0.int4 >= 0 && R0.int4 + parameter.int4 < ramSize && R1.int4 >= 0 && R1.int4 + parameter.int4 < ramSize)
+ memcpy(ram + R0.int4, ram + R1.int4, parameter.int4);
+ else
+ throw AccessViolationException();
+ return -1;
+ }
+
+ OPDEF(SEX8) /* Sign-extend 8-bit */
+ {
+ R0 = Pop();
+ if(R0.uint4 & 0x80)
+ R0.uint4 |= 0xFFFFFF80;
+ Push(R0);
+ return 0;
+ }
+
+ OPDEF(SEX16) /* Sign-extend 16-bit */
+ {
+ R0 = Pop();
+ if(R0.uint4 & 0x8000)
+ R0.uint4 |= 0xFFFF8000;
+ Push(R0);
+ return 0;
+ }
+
+ #define UNOP(type, op) \
+ { \
+ Push<type##_t>(op Pop<type##_t>()); \
+ return 0; \
+ }
+
+ #define BINOP(type, op) \
+ { \
+ R0 = Pop(); \
+ Push<type##_t>(Pop<type##_t>() op R0.type); \
+ return 0; \
+ }
+
+ OPDEF(NEGI) /* [DP] <- -[DP] */
+ UNOP(int4, -)
+
+ OPDEF(ADD) /* [DP-1] <- [DP-1] + [DP]; DP <- DP-1 */
+ BINOP(int4, +)
+
+ OPDEF(SUB) /* [DP-1] <- [DP-1] - [DP]; DP <- DP-1 */
+ BINOP(int4, -)
+
+ OPDEF(DIVI) /* [DP-1] <- [DP-1] / [DP]; DP <- DP-1 */
+ BINOP(int4, /)
+
+ OPDEF(DIVU) /* [DP-1] <- [DP-1] / [DP]; DP <- DP-1 */
+ BINOP(uint4, /)
+
+ OPDEF(MODI) /* [DP-1] <- [DP-1] % [DP]; DP <- DP-1 */
+ BINOP(int4, %)
+
+ OPDEF(MODU) /* [DP-1] <- [DP-1] % [DP]; DP <- DP-1 */
+ BINOP(uint4, %)
+
+ OPDEF(MULI) /* [DP-1] <- [DP-1] * [DP]; DP <- DP-1 */
+ BINOP(int4, *)
+
+ OPDEF(MULU) /* [DP-1] <- [DP-1] * [DP]; DP <- OP-1 */
+ BINOP(uint4, *)
+
+ OPDEF(BAND) /* [DP-1] <- [DP-1] & [DP]; DP <- DP-1 */
+ BINOP(uint4, &)
+
+ OPDEF(BOR) /* [DP-1] <- [DP-1] | [DP]; DP <- DP-1 */
+ BINOP(uint4, |)
+
+ OPDEF(BXOR) /* [DP-1] <- [DP-1] ^ [DP]; DP <- DP-1 */
+ BINOP(uint4, ^)
+
+ OPDEF(BCOM) /* [DP] <- ~[DP] */
+ UNOP(uint4, ~)
+
+ OPDEF(LSH) /* [DP-1] <- [DP-1] << [DP]; DP <- DP-1 */
+ BINOP(uint4, <<)
+
+ OPDEF(RSHI) /* [DP-1] <- [DP-1] >> [DP]; DP <- DP-1 */
+ {
+ R1.int4 = Pop<int4_t>();
+ R0.int4 = Pop<int4_t>();
+ R2.int4 = R0.int4 >> R1.int4;
+ Push(R2);
+ return 0;
+ }
+
+ OPDEF(RSHU) /* [DP-1] <- [DP-1] >> [DP]; DP <- DP-1 */
+ BINOP(uint4, >>)
+
+ OPDEF(NEGF) /* [DP] <- -[DP] */
+ UNOP(float4, -)
+
+ OPDEF(ADDF) /* [DP-1] <- [DP-1] + [DP]; DP <- DP-1 */
+ BINOP(float4, +)
+
+ OPDEF(SUBF) /* [DP-1] <- [DP-1] - [DP]; DP <- DP-1 */
+ BINOP(float4, -)
+
+ OPDEF(DIVF) /* [DP-1] <- [DP-1] / [DP]; DP <- DP-1 */
+ BINOP(float4, /)
+
+ OPDEF(MULF) /* [DP-1] <- [DP-1] / [DP]; DP <- DP-1 */
+ BINOP(float4, *)
+
+ OPDEF(CVIF) /* [DP] <- [DP] */
+ {
+ Push<float4_t>(Pop<int4_t>());
+ return 0;
+ }
+
+ OPDEF(CVFI) /* [DP] <- [DP] */
+ {
+ Push<int4_t>(Pop<float4_t>());
+ return 0;
+ }
+} \ No newline at end of file
diff --git a/src/virtualmachine/OpCodes.inl b/src/virtualmachine/Operations.inl
index a1d4b43..a1d4b43 100644
--- a/src/virtualmachine/OpCodes.inl
+++ b/src/virtualmachine/Operations.inl
diff --git a/src/virtualmachine/Syscalls.cpp b/src/virtualmachine/Syscalls.cpp
new file mode 100644
index 0000000..5358833
--- /dev/null
+++ b/src/virtualmachine/Syscalls.cpp
@@ -0,0 +1,33 @@
+#include "VirtualMachine.h"
+#include <cstdio>
+#include <cstdlib>
+
+namespace vm
+{
+ #define ARG(n) (Get<int4_t>(RP + ((2 + n) * sizeof(word))))
+
+ #define TRAPDEF(f) int VirtualMachine::trap##f()
+
+ TRAPDEF(Print)
+ {
+
+ char *text;
+
+ //crumb("SYSCALL Print [%d]\n", ARG(0));
+ text = (char*)(ram) + ARG(0);
+ //crumb("PRINTING [%s]\n", text);
+ printf("%s", text);
+ return 0;
+ }
+
+
+ TRAPDEF(Error)
+ {
+ char *msg;
+
+ msg = (char*)(ram) + ARG(0);
+ printf("%s", msg);
+ PC = romSize + 1;
+ return 0;
+ }
+} \ No newline at end of file
diff --git a/src/virtualmachine/Traps.inl b/src/virtualmachine/Syscalls.inl
index 0da71d2..0da71d2 100644
--- a/src/virtualmachine/Traps.inl
+++ b/src/virtualmachine/Syscalls.inl
diff --git a/src/virtualmachine/VirtualMachine.cpp b/src/virtualmachine/VirtualMachine.cpp
index ce12b87..a5f661e 100644
--- a/src/virtualmachine/VirtualMachine.cpp
+++ b/src/virtualmachine/VirtualMachine.cpp
@@ -33,7 +33,7 @@ namespace vm
delete[] hunk;
}
- #define crumb printf
+ #define DEBUGTRACE(args...) printf(args);
int VirtualMachine::opcodeParameterSize(int opcode)
{
@@ -101,16 +101,16 @@ namespace vm
uint1_t x[4];
word w;
- crumb("Loading file...\n");
+ DEBUGTRACE("Loading file...\n");
qvminfo.magic = readInt(qvmfile); /* magic. */
if (qvminfo.magic != QVM_MAGIC)
{
- crumb("Invalid magic");
+ DEBUGTRACE("Invalid magic");
//q3vm_error("Does not appear to be a QVM file.");
/* XXX: option to force continue. */
return 0;
}
- crumb("Magic OK\n");
+ DEBUGTRACE("Magic OK\n");
/* variable-length instructions mean instruction count != code length */
qvminfo.inscount = readInt(qvmfile);
qvminfo.codeoff = readInt(qvmfile);
@@ -120,67 +120,68 @@ namespace vm
qvminfo.litlen = readInt(qvmfile);
qvminfo.bsslen = readInt(qvmfile);
- /* Code segment should follow... */
- /* XXX: use fseek with SEEK_CUR? */
- crumb("Searching for .code @ %d from %d\n", qvminfo.codeoff, ftell(qvmfile));
- // rom = (q3vm_rom_t*)(hunk); /* ROM-in-hunk */
+ /* Code segment should follow... */
+ /* XXX: use fseek with SEEK_CUR? */
+ DEBUGTRACE("Searching for .code @ %d from %d\n", qvminfo.codeoff, ftell(qvmfile));
+ // rom = (q3vm_rom_t*)(hunk); /* ROM-in-hunk */
rom = (Instruction*)calloc(qvminfo.inscount, sizeof(rom[0]));
while (ftell(qvmfile) < qvminfo.codeoff)
- readByte(qvmfile);
+ readByte(qvmfile);
while (romSize < qvminfo.inscount)
+ {
+ n = readByte(qvmfile);
+ w.int4 = 0;
+ if ((i = opcodeParameterSize(n)))
{
- n = readByte(qvmfile);
- w.int4 = 0;
- if ((i = opcodeParameterSize(n)))
- {
- x[0] = x[1] = x[2] = x[3] = 0;
- fread(&x, 1, i, qvmfile);
- w.uint4 = (x[0]) | (x[1] << 8) | (x[2] << 16) | (x[3] << 24);
- }
- rom[romSize].Operation = n;
- rom[romSize].Parameter = w;
- romSize++;
+ x[0] = x[1] = x[2] = x[3] = 0;
+ fread(&x, 1, i, qvmfile);
+ w.uint4 = (x[0]) | (x[1] << 8) | (x[2] << 16) | (x[3] << 24);
}
- crumb("After loading code: at %d, should be %d\n", ftell(qvmfile), qvminfo.codeoff + qvminfo.codelen);
+ rom[romSize].Operation = n;
+ rom[romSize].Parameter = w;
+ romSize++;
+ }
+ DEBUGTRACE("After loading code: at %d, should be %d\n", ftell(qvmfile), qvminfo.codeoff + qvminfo.codelen);
- /* Then data segment. */
- // ram = hunk + ((romlen + 3) & ~3); /* RAM-in-hunk */
+ /* Then data segment. */
+ // ram = hunk + ((romlen + 3) & ~3); /* RAM-in-hunk */
ram = hunk;
- crumb("Searching for .data @ %d from %d\n", qvminfo.dataoff, ftell(qvmfile));
+ DEBUGTRACE("Searching for .data @ %d from %d\n", qvminfo.dataoff, ftell(qvmfile));
while (ftell(qvmfile) < qvminfo.dataoff)
- readByte(qvmfile);
+ readByte(qvmfile);
for (n = 0; n < (qvminfo.datalen / sizeof(uint1_t)); n++)
- {
- i = fread(&x, 1, sizeof(x), qvmfile);
- w.uint4 = (x[0]) | (x[1] << 8) | (x[2] << 16) | (x[3] << 24);
- *((word*)(ram + ramSize)) = w;
- ramSize += sizeof(word);
- }
- /* lit segment follows data segment. */
- /* Assembler should have already padded properly. */
- crumb("Loading .lit\n");
+ {
+ i = fread(&x, 1, sizeof(x), qvmfile);
+ w.uint4 = (x[0]) | (x[1] << 8) | (x[2] << 16) | (x[3] << 24);
+ *((word*)(ram + ramSize)) = w;
+ ramSize += sizeof(word);
+ }
+
+ /* lit segment follows data segment. */
+ /* Assembler should have already padded properly. */
+ DEBUGTRACE("Loading .lit\n");
for (n = 0; n < (qvminfo.litlen / sizeof(uint1_t)); n++)
- {
- i = fread(&x, 1, sizeof(x), qvmfile);
- memcpy(&(w.uint1), &x, sizeof(x)); /* no byte-swapping. */
- *((word*)(ram + ramSize)) = w;
- ramSize += sizeof(word);
- }
- /* bss segment. */
- crumb("Allocating .bss %d (%X) bytes\n", qvminfo.bsslen, qvminfo.bsslen);
+ {
+ i = fread(&x, 1, sizeof(x), qvmfile);
+ memcpy(&(w.uint1), &x, sizeof(x)); /* no byte-swapping. */
+ *((word*)(ram + ramSize)) = w;
+ ramSize += sizeof(word);
+ }
+ /* bss segment. */
+ DEBUGTRACE("Allocating .bss %d (%X) bytes\n", qvminfo.bsslen, qvminfo.bsslen);
/* huge empty chunk. */
ramSize += qvminfo.bsslen;
hunkFree = hunkSize - ((ramSize * sizeof(uint1_t)) + 4);
- crumb("VM hunk has %d of %d bytes free (RAM = %d B).\n", hunkFree, hunkSize, ramSize);
+ DEBUGTRACE("VM hunk has %d of %d bytes free (RAM = %d B).\n", hunkFree, hunkSize, ramSize);
if (ramSize > hunkSize)
- {
- throw OutOfMemoryException();
- return 0;
- }
+ {
+ throw OutOfMemoryException();
+ return 0;
+ }
- /* set up stack. */
+ /* set up stack. */
{
int stacksize = 0x10000;
returnStack = ramSize;
@@ -189,7 +190,7 @@ namespace vm
DP = dataStack;
}
- /* set up PC for return-to-termination. */
+ /* set up PC for return-to-termination. */
PC = romSize + 1;
return 1;
@@ -198,13 +199,13 @@ namespace vm
int VirtualMachine::Call(int address)
{
word w;
- int i, argCount = 13;
+ int i, argCount = 0;
/* Set up call. */
- opPUSH(w);
- crumb("Starting with PC=%d, DP=%d, RP=%d to %d\n", PC, DP, RP, address);
+ OpPUSH(w);
+ DEBUGTRACE("Starting with PC=%d, DP=%d, RP=%d to %d\n", PC, DP, RP, address);
w.int4 = (argCount + 2) * sizeof(word);
- opENTER(w);
+ OpENTER(w);
i = 8;
/**w.int4 = arg0; Marshal(i, w); i += 4;
w.int4 = arg1; Marshal(i, w); i += 4;
@@ -221,12 +222,13 @@ namespace vm
w.int4 = arg12; Marshal(i, w); i += 4;*/
w.int4 = address;
Push(w);
- opCALL(w);
- printf("Upon running PC=%d, DP=%d, RP=%d\n", PC, DP, RP);
+ OpCALL(w);
+ DEBUGTRACE("Upon running PC=%d, DP=%d, RP=%d\n", PC, DP, RP);
Run();
- printf("At finish PC=%d, DP=%d, RP=%d\n", PC, DP, RP);
+ DEBUGTRACE("At finish PC=%d, DP=%d, RP=%d\n", PC, DP, RP);
w.int4 = (argCount + 2) * sizeof(word);
- opLEAVE(w);
+ OpLEAVE(w);
+ PC = romSize + 1;
return 0;
}
@@ -267,7 +269,7 @@ namespace vm
switch (trap)
{
#define TRAPDEF(n, f) case n: retval = trap##f(); break;
- #include "Traps.inl"
+ #include "Syscalls.inl"
#undef TRAPDEF
}
@@ -277,388 +279,4 @@ namespace vm
Push(w);
return 1;
}
-
- #define ARG(n) (Get<int4_t>(RP + ((2 + n) * sizeof(word))))
-
- #define TRAPDEF(f) int VirtualMachine::trap##f()
-
- TRAPDEF(Print)
- {
- char *text;
-
- //crumb("SYSCALL Print [%d]\n", ARG(0));
- text = (char*)(ram) + ARG(0);
- //crumb("PRINTING [%s]\n", text);
- printf("%s", text);
- return 0;
- }
-
-
- TRAPDEF(Error)
- {
- char *msg;
-
- msg = (char*)(ram) + ARG(0);
- printf("%s", msg);
- PC = romSize + 1;
- return 0;
- }
-
- #define OPDEF(n) &VirtualMachine::op##n,
- OperationFunction VirtualMachine::operations[] =
- {
- #include "OpCodes.inl"
- };
- #undef OPDEF
-
- #define OPDEF(n) int VirtualMachine::op##n(word parameter)
-
- #define R0 (r[0])
- #define R1 (r[1])
- #define R2 (r[2])
-
-
- OPDEF(UNDEF)
- {
- /* Die horribly. */
- throw RuntimeException();
- return -1;
- }
-
- OPDEF(IGNORE)
- {
- /* NOP */
- throw RuntimeException();
- return 0;
- }
-
- OPDEF(BREAK)
- {
- /* Usage never spotted. */
- /* Die horribly? */
- throw RuntimeException();
- return -1;
- }
-
- /*
- Stack on entering...
-
- no locals: ENTER 8
- 1 words locals: ENTER 16
- 2 words locals: ENTER 20
- 3 words locals: ENTER 24
- etc.
-
- address of argument:
- ADDRFP4 v => OP_LOCAL (16 + currentLocals + currentArgs + v)
- address of local:
- ADDRLP4 v => OP_LOCAL (8 + currentArgs + v)
-
- RP [ ] ??? (oldPC?)
- [ ] ???
- [ ] \
- ... > locals (args marshalling)
- [ ] /
- [ ] \
- ... > locals
- [ ] / (ADDRLP4 v => OP_LOCAL (8 + currentArgs + v))
- (oldRP?) [ ] ???
- [ ] ???
- [ ] (my args?)
- ...
- [ ]
- */
-
- OPDEF(ENTER) /* ??? */
- {
- while (parameter.int4 > (2 * sizeof(word)))
- {
- RPush<int4_t>(0); /* init zero */
- parameter.int4 -= sizeof(word);
- }
- RPush(Pop()); //Program Counter
- RPush<int4_t>(0); //Unknown
- return 0;
- }
-
- OPDEF(LEAVE) /* ??? */
- {
- RPop(); //Unknown
- parameter.int4 -= sizeof(word);
- PC = RPop<int4_t>(); //Program counter
- parameter.int4 -= sizeof(word);
- while (parameter.int4 > 0)
- {
- RPop();
- parameter.int4 -= sizeof(word);
- }
- return 0;
- }
-
- OPDEF(CALL) /* Call subroutine. */
- {
- R0 = Pop();
- Push<int4_t>(PC);
- PC = R0.int4;
- return 0;
- }
-
- OPDEF(PUSH) /* [DP] <- 0; DP++ */
- {
- Push(0);
- return 0;
- }
-
- OPDEF(POP) /* DP-- */
- {
- Pop();
- return 0;
- }
-
- OPDEF(CONST) /* [DP] <- parm; DP++ */
- {
- Push(parameter);
- return 0;
- }
-
- OPDEF(LOCAL) /* [DP] <- [RP-n] */
- {
- Push<int4_t>(RP + parameter.int4);
- return 0;
- }
-
- OPDEF(JUMP) /* PC <- [DP] */
- {
- PC = Pop<int4_t>();
- return 0;
- }
-
- #define CMP(type, op) \
- { \
- R0 = Pop(); \
- cm = (Pop<type##_t>() op R0.type); \
- if (cm) \
- PC = parameter.uint4; \
- return 0; \
- }
-
- OPDEF(EQ) /* if [DP] == [DP-1] then PC <- parm; DP <- DP-2 */
- CMP(int4, ==)
-
- OPDEF(NE) /* if [DP] == [DP-1] then PC <- parm; DP <- DP-2 */
- CMP(int4, !=)
-
- OPDEF(LTI) /* if [DP] < [DP-1] then PC <- parm; DP <- DP-2 */
- CMP(int4, <)
-
- OPDEF(LEI) /* if [DP] <= [DP-1] then PC <- parm; DP <- DP-2 */
- CMP(int4, <=)
-
- OPDEF(GTI) /* if [DP] > [DP-1] then PC <- parm; DP <- DP-2 */
- CMP(int4, >)
-
- OPDEF(GEI) /* if [DP] >= [DP-1] then PC <- parm; DP <- DP-2 */
- CMP(int4, >=)
-
- OPDEF(LTU) /* if [DP] < [DP-1] then PC <- parm; DP <- DP-2 */
- CMP(uint4, <)
-
- OPDEF(LEU) /* if [DP] <= [DP-1] then PC <- parm; DP <- DP-2 */
- CMP(uint4, <=)
-
- OPDEF(GTU) /* if [DP] > [DP-1] then PC <- parm; DP <- DP-2 */
- CMP(uint4, >)
-
- OPDEF(GEU) /* if [DP] >= [DP-1] then PC <- parm; DP <- DP-2 */
- CMP(uint4, >=)
-
- OPDEF(EQF) /* if [DP] == [DP-1] then PC <- parm; DP <- DP-2 */
- CMP(float4, ==)
-
- OPDEF(NEF) /* if [DP] != [DP-1] then PC <- parm; DP <- DP-2 */
- CMP(float4, !=)
-
- OPDEF(LTF) /* if [DP] < [DP-1] then PC <- parm; DP <- DP-2 */
- CMP(float4, <)
-
- OPDEF(LEF) /* if [DP] <= [DP-1] then PC <- parm; DP <- DP-2 */
- CMP(float4, <=)
-
- OPDEF(GTF) /* if [DP] > [DP-1] then PC <- parm; DP <- DP-2 */
- CMP(float4, >)
-
- OPDEF(GEF) /* if [DP] >= [DP-1] then PC <- parm; DP <- DP-2 */
- CMP(float4, >=)
-
-
- OPDEF(LOAD1) /* [DP] <- [[DP]] */
- {
- Push<uint1_t>(Get<uint1_t>(Pop<uint4_t>()));
- return 0;
- }
-
- OPDEF(LOAD2) /* [DP] <- [[DP]] */
- {
- Push<uint2_t>(Get<uint2_t>(Pop<uint4_t>()));
- return 0;
- }
-
- OPDEF(LOAD4) /* [DP] <- [[DP]] */
- {
- Push<uint4_t>(Get<uint4_t>(Pop<uint4_t>()));
- return 0;
- }
-
- OPDEF(STORE1) /* [DP-1] <- [DP]; DP <- DP-2 */
- {
- Set<uint1_t>(Pop<uint4_t>(), Pop<uint1_t>());
- return 0;
- }
-
- OPDEF(STORE2) /* [DP-1] <- [DP]; DP <- DP-2 */
- {
- Set<uint2_t>(Pop<uint4_t>(), Pop<uint2_t>());
- return 0;
- }
-
- OPDEF(STORE4) /* [DP-1] <- [DP]; DP <- DP-2 */
- {
- Set<uint4_t>(Pop<uint4_t>(), Pop<uint4_t>());
- return 0;
- }
-
- OPDEF(ARG) /* Marshal TOS to to-call argument list */
- {
- Marshal(parameter.int4, Pop());
- return 0;
- }
-
- OPDEF(BLOCK_COPY) /* XXX */
- {
- R1 = Pop();
- R0 = Pop();
- if(R0.int4 >= 0 && R0.int4 + parameter.int4 < ramSize && R1.int4 >= 0 && R1.int4 + parameter.int4 < ramSize)
- memcpy(ram + R0.int4, ram + R1.int4, parameter.int4);
- else
- throw AccessViolationException();
- return -1;
- }
-
- OPDEF(SEX8) /* Sign-extend 8-bit */
- {
- R0 = Pop();
- if(R0.uint4 & 0x80)
- R0.uint4 |= 0xFFFFFF80;
- Push(R0);
- return 0;
- }
-
- OPDEF(SEX16) /* Sign-extend 16-bit */
- {
- R0 = Pop();
- if(R0.uint4 & 0x8000)
- R0.uint4 |= 0xFFFF8000;
- Push(R0);
- return 0;
- }
-
- #define UNOP(type, op) \
- { \
- Push<type##_t>(op Pop<type##_t>()); \
- return 0; \
- }
-
- #define BINOP(type, op) \
- { \
- R0 = Pop(); \
- Push<type##_t>(Pop<type##_t>() op R0.type); \
- return 0; \
- }
-
- OPDEF(NEGI) /* [DP] <- -[DP] */
- UNOP(int4, -)
-
- OPDEF(ADD) /* [DP-1] <- [DP-1] + [DP]; DP <- DP-1 */
- BINOP(int4, +)
-
- OPDEF(SUB) /* [DP-1] <- [DP-1] - [DP]; DP <- DP-1 */
- BINOP(int4, -)
-
- OPDEF(DIVI) /* [DP-1] <- [DP-1] / [DP]; DP <- DP-1 */
- BINOP(int4, /)
-
- OPDEF(DIVU) /* [DP-1] <- [DP-1] / [DP]; DP <- DP-1 */
- BINOP(uint4, /)
-
- OPDEF(MODI) /* [DP-1] <- [DP-1] % [DP]; DP <- DP-1 */
- BINOP(int4, %)
-
- OPDEF(MODU) /* [DP-1] <- [DP-1] % [DP]; DP <- DP-1 */
- BINOP(uint4, %)
-
- OPDEF(MULI) /* [DP-1] <- [DP-1] * [DP]; DP <- DP-1 */
- BINOP(int4, *)
-
- OPDEF(MULU) /* [DP-1] <- [DP-1] * [DP]; DP <- OP-1 */
- BINOP(uint4, *)
-
- OPDEF(BAND) /* [DP-1] <- [DP-1] & [DP]; DP <- DP-1 */
- BINOP(uint4, &)
-
- OPDEF(BOR) /* [DP-1] <- [DP-1] | [DP]; DP <- DP-1 */
- BINOP(uint4, |)
-
- OPDEF(BXOR) /* [DP-1] <- [DP-1] ^ [DP]; DP <- DP-1 */
- BINOP(uint4, ^)
-
- OPDEF(BCOM) /* [DP] <- ~[DP] */
- UNOP(uint4, ~)
-
- OPDEF(LSH) /* [DP-1] <- [DP-1] << [DP]; DP <- DP-1 */
- BINOP(uint4, <<)
-
- OPDEF(RSHI) /* [DP-1] <- [DP-1] >> [DP]; DP <- DP-1 */
- {
- R1.int4 = Pop<int4_t>();
- R0.int4 = Pop<int4_t>();
- #if 0
- while (R1.int4-- > 0)
- R0.int4 /= 2;
- R2 = R0;
- #else
- R2.int4 = R0.int4 >> R1.int4;
- #endif
- Push(R2);
- return 0;
- }
-
- OPDEF(RSHU) /* [DP-1] <- [DP-1] >> [DP]; DP <- DP-1 */
- BINOP(uint4, >>)
-
- OPDEF(NEGF) /* [DP] <- -[DP] */
- UNOP(float4, -)
-
- OPDEF(ADDF) /* [DP-1] <- [DP-1] + [DP]; DP <- DP-1 */
- BINOP(float4, +)
-
- OPDEF(SUBF) /* [DP-1] <- [DP-1] - [DP]; DP <- DP-1 */
- BINOP(float4, -)
-
- OPDEF(DIVF) /* [DP-1] <- [DP-1] / [DP]; DP <- DP-1 */
- BINOP(float4, /)
-
- OPDEF(MULF) /* [DP-1] <- [DP-1] / [DP]; DP <- DP-1 */
- BINOP(float4, *)
-
- OPDEF(CVIF) /* [DP] <- [DP] */
- {
- Push<float4_t>(Pop<int4_t>());
- return 0;
- }
-
- OPDEF(CVFI) /* [DP] <- [DP] */
- {
- Push<int4_t>(Pop<float4_t>());
- return 0;
- }
} \ No newline at end of file
diff --git a/src/virtualmachine/VirtualMachine.h b/src/virtualmachine/VirtualMachine.h
index 9a41e24..eb293b9 100644
--- a/src/virtualmachine/VirtualMachine.h
+++ b/src/virtualmachine/VirtualMachine.h
@@ -93,18 +93,15 @@ namespace vm
int cycles;
#define TRAPDEF(n, f) int trap##f();
- #include "Traps.inl"
+ #include "Syscalls.inl"
#undef TRAPDEF
static OperationFunction operations[];
- #define OPDEF(n) int op##n(word parameter);
- #include "OpCodes.inl"
- #undef OPDEF
#define OPDEF(n) OP##n,
enum {
- #include "OpCodes.inl"
+ #include "Operations.inl"
};
#undef OPDEF
@@ -113,6 +110,10 @@ namespace vm
int opcodeParameterSize(int opcode);
int syscall(int programCounter);
public:
+ #define OPDEF(n) int Op##n(word parameter);
+ #include "Operations.inl"
+ #undef OPDEF
+
VirtualMachine(int hunkMbytes);
virtual ~VirtualMachine();