History

Update registers struct to include next_pc member. This allows the pc member to always point at the current PC instead of having been incremented to the 'next' PC.

arr committed 9 years ago

Commit a46f30c1 parent 87f2d5b6 files · +67 −68Browse files

Showing the changes to src/vm/thread.cpp (1 of 6 files). Show all

Unified · Split

src/vm/thread.cpp+18−17
@@ -59,6 +59,7 @@ vm_registers_t::vm_registers_t( · 58 unmodified lines
59 , mp_base{ entry.mp_base }59 , mp_base{ entry.mp_base }
60 , thread{ thread }60 , thread{ thread }
61 , pc{ entry.module->header.entry_pc }61 , pc{ entry.module->header.entry_pc }
62 , next_pc { entry.module->header.entry_pc }
62 , stack{ static_cast<std::size_t>(entry.module->header.stack_extent) }63 , stack{ static_cast<std::size_t>(entry.module->header.stack_extent) }
63 , tool_dispatch{ nullptr }64 , tool_dispatch{ nullptr }
64 , src{ nullptr }65 , src{ nullptr }
@@ -171,9 +172,9 @@ vm_thread_t::~vm_thread_t() · 106 unmodified lines
171 172
172namespace173namespace
173{174{
174 struct execute_with_tool_t175 struct execute_with_tool_t final
175 {176 {
176 void begin_exec_loop(vm_registers_t &registers, vm_t &)177 static void begin_exec_loop(vm_registers_t &registers, vm_t &)
177 {178 {
178 auto tool_dispatch = registers.tool_dispatch.load();179 auto tool_dispatch = registers.tool_dispatch.load();
179 assert(tool_dispatch != nullptr);180 assert(tool_dispatch != nullptr);
@@ -182,36 +183,36 @@ namespace · 2 unmodified lines
182 }183 }
183 };184 };
184 185
185 struct execute_normal_t186 struct execute_normal_t final
186 {187 {
187 void begin_exec_loop(vm_registers_t &, vm_t &) { }188 static void begin_exec_loop(vm_registers_t &, vm_t &) { }
188 };189 };
189 190
190 template<typename EXEC_DETOUR>191 template<typename EXEC_DETOUR>
191 void execute_impl(vm_registers_t &registers, vm_t &vm)192 void execute_impl(vm_registers_t &r, vm_t &vm)
192 {193 {
193 EXEC_DETOUR detour{};194 auto &execution_duration = r.current_thread_quanta;
194 auto &execution_duration = registers.current_thread_quanta;
195 for (; 0 != execution_duration; --execution_duration)195 for (; 0 != execution_duration; --execution_duration)
196 {196 {
197 detour.begin_exec_loop(registers, vm);197 EXEC_DETOUR::begin_exec_loop(r, vm);
198 assert(registers.stack.peek_frame() != nullptr && "Thread state should not be running with empty stack");198 assert(r.stack.peek_frame() != nullptr && "Thread state should not be running with empty stack");
199 199
200 const auto &code_section = registers.module_ref->code_section;200 const auto &code_section = r.module_ref->code_section;
201 assert(static_cast<std::size_t>(registers.pc) < code_section.size());201 assert(static_cast<std::size_t>(r.pc) < code_section.size());
202 202
203 assert(!registers.module_ref->is_builtin_module() && "Interpreter thread is unable to execute native instructions");203 assert(!r.module_ref->is_builtin_module() && "Interpreter thread is unable to execute native instructions");
204 const auto &inst = code_section[registers.pc].op;204 const auto &inst = code_section[r.pc].op;
205 const auto opcode = static_cast<std::size_t>(inst.opcode);205 const auto opcode = static_cast<std::size_t>(inst.opcode);
206 if (static_cast<std::size_t>(opcode_t::last_opcode) < opcode)206 if (static_cast<std::size_t>(opcode_t::last_opcode) < opcode)
207 throw vm_system_exception{ "Unknown op-code" };207 throw vm_system_exception{ "Unknown op-code" };
208 208
209 // Instruction is valid, decode and update registers for operation209 // Instruction is valid, decode and update registers for operation
210 decode_address(inst, registers);210 decode_address(inst, r);
211 registers.pc++;211 r.next_pc = (r.pc + 1);
212 vm_exec_table[opcode](registers, vm);212 vm_exec_table[opcode](r, vm);
213 r.pc = r.next_pc;
213 214
214 if (registers.current_thread_state != vm_thread_state_t::running)215 if (r.current_thread_state != vm_thread_state_t::running)
215 break;216 break;
216 }217 }
217 }218 }