History

Alter register address decoding using a lookup table instead of single function with multiple switch blocks. Reduced scheduler sleep time during tool dispatch setting.

arr committed 10 years ago

Commit 824a71a1 parent fcc75fd7 files · +500 −86Browse files

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

Unified · Split

src/vm/thread.cpp+3−78
@@ -20,87 +20,12 @@ using namespace disvm::runtime; · 19 unmodified lines
2020
2121 namespace
2222 {
23+#include "address_decoding.inc"
24+
2325 // Update VM registers based on the instruction.
2426 void decode_address(const vm_exec_op_t &inst, vm_registers_t &reg)
2527 {
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);
10429
10530 #ifndef NDEBUG
10631 // This is a perf critical function so logging is only available in debug builds