diff --git a/src/tests/VirtualMachineTest.cpp b/src/tests/VirtualMachineTest.cpp index 0bf9bef97..ee9299978 100644 --- a/src/tests/VirtualMachineTest.cpp +++ b/src/tests/VirtualMachineTest.cpp @@ -7,8 +7,10 @@ int main(int argc, char * argv[]) { vm::VirtualMachine * vm = new vm::VirtualMachine(2); vm->LoadProgram("test.qvm"); - vm->Call(0/*, 0, 88, 12*/); - std::cout << "Return value: " << vm->Pop() << std::endl; - //vm->Run(); + while(true) + { + vm->Call(0/*, 0, 88, 12*/); + std::cout << "Return value: " << vm->Pop() << std::endl; + } } #endif \ No newline at end of file diff --git a/src/virtualmachine/Operations.cpp b/src/virtualmachine/Operations.cpp new file mode 100644 index 000000000..1223c8132 --- /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(0); /* init zero */ + parameter.int4 -= sizeof(word); + } + RPush(Pop()); //Program Counter + RPush(0); //Unknown + return 0; + } + + OPDEF(LEAVE) /* ??? */ + { + RPop(); //Unknown + parameter.int4 -= sizeof(word); + PC = RPop(); //Program counter + parameter.int4 -= sizeof(word); + while (parameter.int4 > 0) + { + RPop(); + parameter.int4 -= sizeof(word); + } + return 0; + } + + OPDEF(CALL) /* Call subroutine. */ + { + R0 = Pop(); + Push(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(RP + parameter.int4); + return 0; + } + + OPDEF(JUMP) /* PC <- [DP] */ + { + PC = Pop(); + return 0; + } + + #define CMP(type, op) \ + { \ + R0 = Pop(); \ + cm = (Pop() 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(Get(Pop())); + return 0; + } + + OPDEF(LOAD2) /* [DP] <- [[DP]] */ + { + Push(Get(Pop())); + return 0; + } + + OPDEF(LOAD4) /* [DP] <- [[DP]] */ + { + Push(Get(Pop())); + return 0; + } + + OPDEF(STORE1) /* [DP-1] <- [DP]; DP <- DP-2 */ + { + Set(Pop(), Pop()); + return 0; + } + + OPDEF(STORE2) /* [DP-1] <- [DP]; DP <- DP-2 */ + { + Set(Pop(), Pop()); + return 0; + } + + OPDEF(STORE4) /* [DP-1] <- [DP]; DP <- DP-2 */ + { + Set(Pop(), Pop()); + 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(op Pop()); \ + return 0; \ + } + + #define BINOP(type, op) \ + { \ + R0 = Pop(); \ + Push(Pop() 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(); + R0.int4 = Pop(); + 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(Pop()); + return 0; + } + + OPDEF(CVFI) /* [DP] <- [DP] */ + { + Push(Pop()); + return 0; + } +} \ No newline at end of file diff --git a/src/virtualmachine/OpCodes.inl b/src/virtualmachine/Operations.inl similarity index 100% rename from src/virtualmachine/OpCodes.inl rename to src/virtualmachine/Operations.inl diff --git a/src/virtualmachine/Syscalls.cpp b/src/virtualmachine/Syscalls.cpp new file mode 100644 index 000000000..5358833ac --- /dev/null +++ b/src/virtualmachine/Syscalls.cpp @@ -0,0 +1,33 @@ +#include "VirtualMachine.h" +#include +#include + +namespace vm +{ + #define ARG(n) (Get(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 similarity index 100% rename from src/virtualmachine/Traps.inl rename to src/virtualmachine/Syscalls.inl diff --git a/src/virtualmachine/VirtualMachine.cpp b/src/virtualmachine/VirtualMachine.cpp index ce12b8774..a5f661e77 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++; - } - crumb("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 */ - ram = hunk; - crumb("Searching for .data @ %d from %d\n", qvminfo.dataoff, ftell(qvmfile)); - while (ftell(qvmfile) < qvminfo.dataoff) - readByte(qvmfile); - for (n = 0; n < (qvminfo.datalen / sizeof(uint1_t)); n++) - { - i = fread(&x, 1, sizeof(x), qvmfile); + 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); - *((word*)(ram + ramSize)) = w; - ramSize += sizeof(word); } - /* lit segment follows data segment. */ - /* Assembler should have already padded properly. */ - crumb("Loading .lit\n"); + 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 */ + ram = hunk; + DEBUGTRACE("Searching for .data @ %d from %d\n", qvminfo.dataoff, ftell(qvmfile)); + while (ftell(qvmfile) < qvminfo.dataoff) + 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. */ + 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(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(0); /* init zero */ - parameter.int4 -= sizeof(word); - } - RPush(Pop()); //Program Counter - RPush(0); //Unknown - return 0; - } - - OPDEF(LEAVE) /* ??? */ - { - RPop(); //Unknown - parameter.int4 -= sizeof(word); - PC = RPop(); //Program counter - parameter.int4 -= sizeof(word); - while (parameter.int4 > 0) - { - RPop(); - parameter.int4 -= sizeof(word); - } - return 0; - } - - OPDEF(CALL) /* Call subroutine. */ - { - R0 = Pop(); - Push(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(RP + parameter.int4); - return 0; - } - - OPDEF(JUMP) /* PC <- [DP] */ - { - PC = Pop(); - return 0; - } - - #define CMP(type, op) \ - { \ - R0 = Pop(); \ - cm = (Pop() 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(Get(Pop())); - return 0; - } - - OPDEF(LOAD2) /* [DP] <- [[DP]] */ - { - Push(Get(Pop())); - return 0; - } - - OPDEF(LOAD4) /* [DP] <- [[DP]] */ - { - Push(Get(Pop())); - return 0; - } - - OPDEF(STORE1) /* [DP-1] <- [DP]; DP <- DP-2 */ - { - Set(Pop(), Pop()); - return 0; - } - - OPDEF(STORE2) /* [DP-1] <- [DP]; DP <- DP-2 */ - { - Set(Pop(), Pop()); - return 0; - } - - OPDEF(STORE4) /* [DP-1] <- [DP]; DP <- DP-2 */ - { - Set(Pop(), Pop()); - 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(op Pop()); \ - return 0; \ - } - - #define BINOP(type, op) \ - { \ - R0 = Pop(); \ - Push(Pop() 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(); - R0.int4 = Pop(); - #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(Pop()); - return 0; - } - - OPDEF(CVFI) /* [DP] <- [DP] */ - { - Push(Pop()); - return 0; - } } \ No newline at end of file diff --git a/src/virtualmachine/VirtualMachine.h b/src/virtualmachine/VirtualMachine.h index 9a41e24bc..eb293b9f7 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();