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 }