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 | namespace | 21 | namespace |
| 22 | { | 22 | { |
| 23 | #include "address_decoding.inc" | ||
| 24 | |||
| 23 | // Update VM registers based on the instruction. | 25 | // Update VM registers based on the instruction. |
| 24 | void decode_address(const vm_exec_op_t &inst, vm_registers_t ®) | 26 | void decode_address(const vm_exec_op_t &inst, vm_registers_t ®) |
| 25 | { | 27 | { |
| 26 | switch (inst.source.mode) | 28 | decode_table[inst.addr_code](inst, reg); |
| 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 | } | ||
| 104 | 29 | ||
| 105 | #ifndef NDEBUG | 30 | #ifndef NDEBUG |
| 106 | // This is a perf critical function so logging is only available in debug builds | 31 | // This is a perf critical function so logging is only available in debug builds |