Showing the changes to src/vm/thread.cpp (1 of 7 files). Show all
Unified · Split
| @@ -20,87 +20,12 @@ using namespace disvm::runtime; · 19 unmodified lines | ||
| 20 | 20 | |
| 21 | 21 | namespace |
| 22 | 22 | { |
| 23 | +#include "address_decoding.inc" | |
| 24 | + | |
| 23 | 25 | // Update VM registers based on the instruction. |
| 24 | 26 | void decode_address(const vm_exec_op_t &inst, vm_registers_t ®) |
| 25 | 27 | { |
| 26 | − switch (inst.source.mode) | |
| 27 | − { | |
| 28 | − case address_mode_t::offset_indirect_fp: | |
| 29 | − reg.src = reinterpret_cast<pointer_t>(reinterpret_cast<uint8_t *>(reg.stack.peek_frame()->base()) + inst.source.register1); | |
| 30 | − break; | |
| 31 | − case address_mode_t::offset_indirect_mp: | |
| 32 | − reg.src = reinterpret_cast<pointer_t>(reinterpret_cast<uint8_t *>(reg.mp_base->get_allocation()) + inst.source.register1); | |
| 33 | − break; | |
| 34 | − case address_mode_t::offset_double_indirect_fp: | |
| 35 | − { | |
| 36 | − const auto frame_offset = *reinterpret_cast<std::size_t *>(reinterpret_cast<uint8_t *>(reg.stack.peek_frame()->base()) + inst.source.register1); | |
| 37 | − reg.src = reinterpret_cast<pointer_t>(frame_offset + inst.source.register2); | |
| 38 | − break; | |
| 39 | − } | |
| 40 | − case address_mode_t::offset_double_indirect_mp: | |
| 41 | − { | |
| 42 | − const auto mp_offset = *reinterpret_cast<std::size_t *>(reinterpret_cast<uint8_t *>(reg.mp_base->get_allocation()) + inst.source.register1); | |
| 43 | − reg.src = reinterpret_cast<pointer_t>(mp_offset + inst.source.register2); | |
| 44 | − break; | |
| 45 | − } | |
| 46 | − case address_mode_t::immediate: | |
| 47 | − reg.src = reinterpret_cast<pointer_t>(const_cast<word_t *>(&inst.source.register1)); | |
| 48 | − break; | |
| 49 | − case address_mode_t::none: | |
| 50 | − reg.src = nullptr; | |
| 51 | − break; | |
| 52 | − default: | |
| 53 | − assert(false && "Unknown source addressing"); | |
| 54 | − } | |
| 55 | − | |
| 56 | − switch (inst.destination.mode) | |
| 57 | − { | |
| 58 | − case address_mode_t::offset_indirect_fp: | |
| 59 | − reg.dest = reinterpret_cast<pointer_t>(reinterpret_cast<uint8_t *>(reg.stack.peek_frame()->base()) + inst.destination.register1); | |
| 60 | − break; | |
| 61 | − case address_mode_t::offset_indirect_mp: | |
| 62 | − reg.dest = reinterpret_cast<pointer_t>(reinterpret_cast<uint8_t *>(reg.mp_base->get_allocation()) + inst.destination.register1); | |
| 63 | − break; | |
| 64 | − case address_mode_t::offset_double_indirect_fp: | |
| 65 | − { | |
| 66 | − const auto frame_offset = *reinterpret_cast<std::size_t *>(reinterpret_cast<uint8_t *>(reg.stack.peek_frame()->base()) + inst.destination.register1); | |
| 67 | − reg.dest = reinterpret_cast<pointer_t>(frame_offset + inst.destination.register2); | |
| 68 | − break; | |
| 69 | − } | |
| 70 | − case address_mode_t::offset_double_indirect_mp: | |
| 71 | − { | |
| 72 | − const auto mp_offset = *reinterpret_cast<std::size_t *>(reinterpret_cast<uint8_t *>(reg.mp_base->get_allocation()) + inst.destination.register1); | |
| 73 | − reg.dest = reinterpret_cast<pointer_t>(mp_offset + inst.destination.register2); | |
| 74 | − break; | |
| 75 | − } | |
| 76 | − case address_mode_t::immediate: | |
| 77 | − reg.dest = reinterpret_cast<pointer_t>(const_cast<word_t *>(&inst.destination.register1)); | |
| 78 | − break; | |
| 79 | − case address_mode_t::none: | |
| 80 | − reg.dest = nullptr; | |
| 81 | − break; | |
| 82 | − default: | |
| 83 | − assert(false && "Unknown destination addressing"); | |
| 84 | − } | |
| 85 | − | |
| 86 | − switch (inst.middle.mode) | |
| 87 | − { | |
| 88 | − case address_mode_middle_t::small_offset_indirect_fp: | |
| 89 | − reg.mid = reinterpret_cast<pointer_t>(reinterpret_cast<uint8_t *>(reg.stack.peek_frame()->base()) + inst.middle.register1); | |
| 90 | − break; | |
| 91 | − case address_mode_middle_t::small_offset_indirect_mp: | |
| 92 | − reg.mid = reinterpret_cast<pointer_t>(reinterpret_cast<uint8_t *>(reg.mp_base->get_allocation()) + inst.middle.register1); | |
| 93 | − break; | |
| 94 | − case address_mode_middle_t::small_immediate: | |
| 95 | − reg.mid = reinterpret_cast<pointer_t>(const_cast<word_t *>(&inst.middle.register1)); | |
| 96 | − break; | |
| 97 | − case address_mode_middle_t::none: | |
| 98 | − // [SPEC] This is an undocumented expectation but required in many operations (e.g. i++). | |
| 99 | − reg.mid = reg.dest; | |
| 100 | − break; | |
| 101 | − default: | |
| 102 | − assert(false && "Unknown middle addressing"); | |
| 103 | − } | |
| 28 | + decode_table[inst.addr_code](inst, reg); | |
| 104 | 29 | |
| 105 | 30 | #ifndef NDEBUG |
| 106 | 31 | // This is a perf critical function so logging is only available in debug builds |