Mercurial > LightClone
comparison LightClone/Source/VirtualMachine.cpp @ 54:95677f648a2c VirtualMachine Mk2
Refactored VirtualMachine
author | koryspansel |
---|---|
date | Fri, 30 Sep 2011 18:37:54 -0700 |
parents | 4663f93aefc4 |
children | dc1f4a668d50 |
comparison
equal
deleted
inserted
replaced
53:8cefb65577cc | 54:95677f648a2c |
---|---|
5 #include "VirtualMachine.h" | 5 #include "VirtualMachine.h" |
6 | 6 |
7 /* | 7 /* |
8 * VirtualMachine | 8 * VirtualMachine |
9 */ | 9 */ |
10 VirtualMachine::VirtualMachine() : nInstructionPointer(0), nFunctionCount(0) | 10 VirtualMachine::VirtualMachine() : nInstructionPointer(0), pFrame(NULL) |
11 { | 11 { |
12 ClearMemory(); | 12 Clear(); |
13 } | 13 } |
14 | 14 |
15 /* | 15 /* |
16 * Step | 16 * Step |
17 */ | 17 */ |
18 uint32 VirtualMachine::Step() | 18 uint32 VirtualMachine::Step() |
19 { | 19 { |
20 // decode and validate instruction pointer function and offset | 20 const uint8 nInstruction = Advance(); |
21 const uint8 nSourceFunction = DecodeAddressFunction(nInstructionPointer); | 21 TRACE("Read instruction %d at address %d\n", nInstruction, nInstructionPointer - 1); |
22 const uint8 nSourceOffset = DecodeAddressOffset(nInstructionPointer); | 22 |
23 if(nInstruction == Instruction_Action) | |
24 { | |
25 const uint8 nParameter = Advance(); | |
26 TRACE(" -- Action Decoded: %d\n", nParameter); | |
23 | 27 |
24 if(nSourceFunction < nFunctionCount && nSourceOffset <= kFunction[nSourceFunction].nSize) | 28 return nParameter; |
29 } | |
30 else | |
31 | |
32 if(nInstruction == Instruction_Call) | |
25 { | 33 { |
26 TRACE("Reading address %d\n", nInstructionPointer); | 34 const uint8 nParameter = Advance(); |
35 TRACE(" -- Call Decoded: %d\n", nParameter); | |
27 | 36 |
28 // read the next instruction | 37 const uint32 nFunction = nParameter; |
29 const uint8 nInstruction = Read(); | 38 const uint32 nContinuation = nInstructionPointer; |
30 const uint8 nParameter = Read(); | |
31 | 39 |
32 TRACE("Decoded I:%d P:%d\n", nInstruction, nParameter); | 40 PushFrame(nFunction, nContinuation); |
41 } | |
42 else | |
33 | 43 |
34 if(nInstruction == Instruction_None) | 44 if(nInstruction == Instruction_Return) |
45 { | |
46 if(pFrame) | |
35 { | 47 { |
36 return Action_Default; | 48 PopFrame(); |
37 } | 49 } |
38 else | 50 else |
39 | |
40 if(nInstruction == Instruction_Action) | |
41 { | 51 { |
42 // action instruction, the parameter is the action | 52 // no frame to pop, we are done |
43 TRACE(" -- Action Decoded: %d\n", nParameter); | 53 return Action_Complete; |
44 return nParameter; | |
45 } | |
46 else | |
47 | |
48 if(nInstruction == Instruction_Call) | |
49 { | |
50 TRACE(" -- Call Decoded: %d\n", nParameter); | |
51 | |
52 // set instruction pointer to destination | |
53 if(nParameter < nFunctionCount) | |
54 { | |
55 const uint8 nDestinationSize = kFunction[nParameter].nSize; | |
56 | |
57 // insert continuation jump into destination function | |
58 nMemory[nParameter * FunctionStride + nDestinationSize + 0] = Instruction_Jump; | |
59 nMemory[nParameter * FunctionStride + nDestinationSize + 1] = nInstructionPointer; | |
60 | |
61 TRACE(" - Inserting continuation\n"); | |
62 TRACE(" Instruction: %d\n", Instruction_Jump); | |
63 TRACE(" Destination: %d\n", nInstructionPointer); | |
64 | |
65 // update instruction pointer to destination address | |
66 nInstructionPointer = nParameter * FunctionStride; | |
67 | |
68 // signal that we're not yet done | |
69 return Action_Default; | |
70 } | |
71 } | |
72 else | |
73 | |
74 if(nInstruction == Instruction_Jump) | |
75 { | |
76 TRACE(" -- Jump Decoded: %d\n", nParameter); | |
77 | |
78 // decode and validate destination function and offset | |
79 const uint8 nDestinationFunction = DecodeAddressFunction(nParameter); | |
80 const uint8 nDestinationOffset = DecodeAddressOffset(nParameter); | |
81 | |
82 TRACE(" - Function: %d\n", nDestinationFunction); | |
83 TRACE(" - Offset : %d\n", nDestinationOffset); | |
84 | |
85 // set instruction pointer to destination | |
86 if(nDestinationFunction < nFunctionCount && nDestinationOffset <= kFunction[nDestinationFunction].nSize) | |
87 { | |
88 // update instruction pointer to destination address | |
89 nInstructionPointer = nParameter; | |
90 | |
91 // signal that we're not yet done | |
92 return Action_Default; | |
93 } | |
94 } | 54 } |
95 } | 55 } |
96 | 56 |
97 return Action_Complete; | 57 return Action_None; |
98 } | 58 } |
99 | 59 |
100 /* | 60 /* |
101 * Reset | 61 * Reset |
102 */ | 62 */ |
104 { | 64 { |
105 nInstructionPointer = 0; | 65 nInstructionPointer = 0; |
106 } | 66 } |
107 | 67 |
108 /* | 68 /* |
109 * SetMemory | 69 * Clear |
110 */ | 70 */ |
111 bool VirtualMachine::SetMemory(uint8 nFunction, const uint8* pData, uint8 nSize) | 71 void VirtualMachine::Clear() |
112 { | 72 { |
113 if(nFunction < nFunctionCount) | 73 for(uint32 i = 0; i < Capacity; ++i) |
114 { | 74 { |
115 const uint8 nFunctionAddress = kFunction[nFunction].nAddress; | 75 nMemory[i] = 0; |
116 const uint8 nFunctionSize = kFunction[nFunction].nSize; | |
117 | |
118 for(uint8 nOffset = 0; nOffset < Min(nFunctionSize, nSize); ++nOffset) | |
119 { | |
120 nMemory[nFunctionAddress + nOffset] = pData[nOffset]; | |
121 } | |
122 | |
123 return true; | |
124 } | |
125 | |
126 return false; | |
127 } | |
128 | |
129 /* | |
130 * ClearMemory | |
131 */ | |
132 void VirtualMachine::ClearMemory() | |
133 { | |
134 for(uint8 nFunction = 0; nFunction < MaximumFunctionCount; ++nFunction) | |
135 { | |
136 for(uint8 nLocation = 0; nLocation < MaximumInstructionCount; ++nLocation) | |
137 { | |
138 nMemory[nFunction * FunctionStride + nLocation] = Instruction_None; | |
139 } | |
140 | |
141 nMemory[nFunction * FunctionStride + FunctionStride - ContinuationInstructionSize + 0] = Instruction_Jump; | |
142 nMemory[nFunction * FunctionStride + FunctionStride - ContinuationInstructionSize + 1] = 0; | |
143 | |
144 } | 76 } |
145 } | 77 } |
146 | 78 |
147 /* | 79 /* |
148 * AddFunction | 80 * GetMemorySize |
149 */ | 81 */ |
150 bool VirtualMachine::AddFunction(uint8 nFunction, uint8 nSize) | 82 uint32 VirtualMachine::GetMemorySize() const |
151 { | 83 { |
152 if(nFunctionCount + 1 < MaximumFunctionCount) | 84 return Capacity; |
153 { | |
154 kFunction[nFunctionCount].nAddress = nFunctionCount * FunctionStride; | |
155 kFunction[nFunctionCount].nSize = nSize * 2; | |
156 | |
157 ++nFunctionCount; | |
158 | |
159 return true; | |
160 } | |
161 | |
162 return false; | |
163 } | 85 } |
164 | 86 |
165 /* | 87 /* |
166 * RemoveAllFunctions | 88 * GetMemoryPointer |
167 */ | 89 */ |
168 void VirtualMachine::RemoveAllFunctions() | 90 uint8* VirtualMachine::GetMemoryPointer() |
169 { | 91 { |
170 nFunctionCount = 0; | 92 return &nMemory[0]; |
171 } | 93 } |
172 | 94 |
173 /* | 95 /* |
174 * GetFunctionSize | 96 * PushFrame |
175 */ | 97 */ |
176 uint32 VirtualMachine::GetFunctionSize(uint32 nIndex) const | 98 void VirtualMachine::PushFrame(uint32 nFunctionAddress, uint32 nContinuationAddress) |
177 { | 99 { |
178 return nIndex < nFunctionCount ? kFunction[nIndex].nSize : 0; | 100 Frame* pInstance = pFrame; |
101 | |
102 while(pInstance) | |
103 { | |
104 if(pInstance->nAddress == nFunctionAddress && pInstance->nContinuation == nContinuationAddress) | |
105 { | |
106 break; | |
107 } | |
108 | |
109 pInstance = pInstance->pLast; | |
110 } | |
111 | |
112 if(pInstance) | |
113 { | |
114 while(pFrame && pFrame != pInstance) | |
115 { | |
116 Frame* pValue = pFrame; | |
117 pFrame = pValue->pLast; | |
118 | |
119 kFrameAllocator.Free(pValue); | |
120 } | |
121 | |
122 //ASSERT(pFrame != NULL); | |
123 } | |
124 else | |
125 { | |
126 pInstance = kFrameAllocator.Allocate(); | |
127 pInstance->nAddress = nFunctionAddress; | |
128 pInstance->nContinuation = nContinuationAddress; | |
129 pInstance->pLast = pFrame; | |
130 | |
131 pFrame = pInstance; | |
132 } | |
133 | |
134 nInstructionPointer = nFunctionAddress; | |
179 } | 135 } |
180 | 136 |
181 /* | 137 /* |
182 * GetFunctionMemory | 138 * PopFrame |
183 */ | 139 */ |
184 uint8* VirtualMachine::GetFunctionMemory(uint32 nIndex) | 140 void VirtualMachine::PopFrame() |
185 { | 141 { |
186 return nIndex < nFunctionCount ? &nMemory[kFunction[nIndex].nAddress] : 0; | 142 if(pFrame) |
143 { | |
144 nInstructionPointer = pFrame->nContinuation; | |
145 | |
146 Frame* pInstance = pFrame; | |
147 pFrame = pInstance->pLast; | |
148 | |
149 kFrameAllocator.Free(pInstance); | |
150 } | |
151 else | |
152 { | |
153 } | |
187 } | 154 } |