summaryrefslogtreecommitdiff
path: root/src/virtualmachine/VirtualMachine.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/virtualmachine/VirtualMachine.h')
-rw-r--r--src/virtualmachine/VirtualMachine.h243
1 files changed, 243 insertions, 0 deletions
diff --git a/src/virtualmachine/VirtualMachine.h b/src/virtualmachine/VirtualMachine.h
new file mode 100644
index 0000000..9a41e24
--- /dev/null
+++ b/src/virtualmachine/VirtualMachine.h
@@ -0,0 +1,243 @@
+#pragma once
+
+#include "Exceptions.h"
+
+namespace vm
+{
+
+ class VirtualMachine;
+
+ typedef char ram_t;
+
+
+
+ typedef unsigned int uint4_t;
+ typedef signed int int4_t;
+
+ typedef unsigned short uint2_t;
+ typedef signed short int2_t;
+
+ typedef unsigned char uint1_t;
+ typedef signed char int1_t;
+
+ typedef float float4_t;
+
+ union word
+ {
+ uint4_t uint4;
+ int4_t int4;
+ uint2_t uint2;
+ int2_t int2;
+ uint1_t uint1;
+ int1_t int1;
+ float4_t float4;
+ };
+
+ typedef int (VirtualMachine::*OperationFunction)(word parameter);
+
+ struct Instruction
+ {
+ int Operation;
+ word Parameter;
+ //opfunc opfunc;
+ };
+
+ enum
+ {
+ QVM_MAGIC = 0x12721444,
+ };
+
+ struct qvm_header_t
+ {
+ int magic;
+ /* not-entirely-RISC ISA, so instruction count != codelen */
+ int inscount; /* instruction count. */
+ int codeoff; /* file offset of code segment. */
+ int codelen; /* length of code segment, in octets. */
+ int dataoff; /* file offset of data segment. */
+ int datalen; /* length of data segment, in octets. */
+ int litlen; /* length of lit segment (which is embedded in data segment). */
+ int bsslen; /* length of bss segment. */
+ };
+
+ class VirtualMachine
+ {
+ bool bigEndian; /* host is big-endian (requires byte-swapping). */
+
+ /* Memory spaces. */
+ char * hunk; /* hunk space (malloc'd). */
+ int hunkSize; /* total hunk size. */
+ int hunkFree; /* free pointer. */
+
+ /* Read-Only Memory (code). */
+ Instruction * rom;
+ int romSize;
+
+ /* Random-Access Memory (data). */
+ ram_t *ram;
+ int ramSize;
+
+ int dataStack;
+ int returnStack;
+
+ word r[4]; /* registers. */
+ int DP; /* Datastack pointer. */
+ int RP; /* Return stack pointer. */
+ int PC; /* Program Counter. */
+ // int AP; /* Argument pointer. (hrm...) */
+
+ /* various flags. */
+ int cm:1;
+
+ /* Execution time */
+ int cycles;
+
+ #define TRAPDEF(n, f) int trap##f();
+ #include "Traps.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"
+ };
+ #undef OPDEF
+
+ int readByte(FILE *qvmfile);
+ int readInt(FILE *qvmfile);
+ int opcodeParameterSize(int opcode);
+ int syscall(int programCounter);
+public:
+ VirtualMachine(int hunkMbytes);
+ virtual ~VirtualMachine();
+
+ int LoadProgram(char * filename);
+ int Run();
+ int Call(int address);
+ void Marshal(int address, word element)
+ {
+ ram_t * ptr = ram+RP+address;
+ if(ptr < ram || ptr > ram+ramSize - sizeof(word))
+ throw AccessViolationException(RP+address);
+ *((word*)ptr) = element;
+ }
+
+ template <typename T> T Get(int address)
+ {
+ ram_t * ptr = ram+address;
+ if(ptr < ram || ptr > ram+ramSize - sizeof(word))
+ throw AccessViolationException(address);
+ return *((T*)ptr);
+ }
+
+ template <typename T> void Set(int address, T value)
+ {
+ ram_t * ptr = ram+address;
+ if(ptr < ram || ptr > ram+ramSize - sizeof(word))
+ throw AccessViolationException(address);
+ *((T*)ptr) = value;
+ }
+
+ template <typename T> T Pop ()
+ {
+ ram_t * ptr = ram+DP;
+ if(DP + sizeof(word) < hunkSize)
+ DP += sizeof(word);
+ else
+ throw StackUnderflowException();
+ return *((T*)ptr);
+ };
+
+ template <typename T> T RPop ()
+ {
+ ram_t * ptr = ram+RP;
+ if(RP + sizeof(word) < hunkSize)
+ RP += sizeof(word);
+ else
+ throw StackUnderflowException();
+ return *((T*)ptr);
+ };
+
+ template <typename T> void Push(T value)
+ {
+ if(DP - sizeof(word) >= 0)
+ DP -= sizeof(word);
+ else
+ throw StackOverflowException();
+ ram_t * ptr = ram+DP;
+ *((T*)ptr) = value;
+ };
+
+ template <typename T> void RPush(T value)
+ {
+ if(RP - sizeof(word) >= 0)
+ RP -= sizeof(word);
+ else
+ throw StackOverflowException();
+ ram_t * ptr = ram+RP;
+ *((T*)ptr) = value;
+ };
+
+ word Get(int address)
+ {
+ ram_t * ptr = ram+address;
+ if(ptr < ram || ptr > ram+ramSize - sizeof(word))
+ throw AccessViolationException(address);
+ return *((word*)ptr);
+ }
+
+ void Set(int address, word value)
+ {
+ ram_t * ptr = ram+address;
+ if(ptr < ram || ptr > ram+ramSize - sizeof(word))
+ throw AccessViolationException(address);
+ *((word*)ptr) = value;
+ }
+
+ word Pop()
+ {
+ ram_t * ptr = ram+DP;
+ if(DP + sizeof(word) < hunkSize)
+ DP += sizeof(word);
+ else
+ throw StackUnderflowException();
+ return *((word*)ptr);
+ };
+
+ void Push(word value)
+ {
+ if(DP - sizeof(word) >= 0)
+ DP -= sizeof(word);
+ else
+ throw StackOverflowException();
+ ram_t * ptr = ram+DP;
+ *((word*)ptr) = value;
+ };
+
+ word RPop()
+ {
+ ram_t * ptr = ram+RP;
+ if(RP + sizeof(word) < hunkSize)
+ RP += sizeof(word);
+ else
+ throw StackUnderflowException();
+ return *((word*)ptr);
+ };
+
+ void RPush(word value)
+ {
+ if(RP - sizeof(word) >= 0)
+ RP -= sizeof(word);
+ else
+ throw StackOverflowException();
+ ram_t * ptr = ram+RP;
+ *((word*)ptr) = value;
+ };
+ };
+
+} \ No newline at end of file