aboutsummaryrefslogtreecommitdiff
path: root/riscv/execute.cc
diff options
context:
space:
mode:
Diffstat (limited to 'riscv/execute.cc')
-rw-r--r--riscv/execute.cc55
1 files changed, 12 insertions, 43 deletions
diff --git a/riscv/execute.cc b/riscv/execute.cc
index ee8257f..62ae019 100644
--- a/riscv/execute.cc
+++ b/riscv/execute.cc
@@ -256,6 +256,7 @@ void processor_t::step(size_t n)
if (unlikely(slow_path()))
{
+ // Main simulation loop, slow path.
while (instret < n)
{
if (unlikely(!state.serialized && state.single_step == state.STEP_STEPPED)) {
@@ -280,49 +281,17 @@ void processor_t::step(size_t n)
}
else while (instret < n)
{
- // This code uses a modified Duff's Device to improve the performance
- // of executing instructions. While typical Duff's Devices are used
- // for software pipelining, the switch statement below primarily
- // benefits from separate call points for the fetch.func function call
- // found in each execute_insn. This function call is an indirect jump
- // that depends on the current instruction. By having an indirect jump
- // dedicated for each icache entry, you improve the performance of the
- // host's next address predictor. Each case in the switch statement
- // allows for the program flow to contine to the next case if it
- // corresponds to the next instruction in the program and instret is
- // still less than n.
- //
- // According to Andrew Waterman's recollection, this optimization
- // resulted in approximately a 2x performance increase.
-
- // This figures out where to jump to in the switch statement
- size_t idx = _mmu->icache_index(pc);
-
- // This gets the cached decoded instruction from the MMU. If the MMU
- // does not have the current pc cached, it will refill the MMU and
- // return the correct entry. ic_entry->data.func is the C++ function
- // corresponding to the instruction.
- auto ic_entry = _mmu->access_icache(pc);
-
- // This macro is included in "icache.h" included within the switch
- // statement below. The indirect jump corresponding to the instruction
- // is located within the execute_insn() function call.
- #define ICACHE_ACCESS(i) { \
- insn_fetch_t fetch = ic_entry->data; \
- pc = execute_insn(this, pc, fetch); \
- ic_entry = ic_entry->next; \
- if (i == mmu_t::ICACHE_ENTRIES-1) break; \
- if (unlikely(ic_entry->tag != pc)) break; \
- if (unlikely(instret+1 == n)) break; \
- instret++; \
- state.pc = pc; \
- }
-
- // This switch statement implements the modified Duff's device as
- // explained above.
- switch (idx) {
- // "icache.h" is generated by the gen_icache script
- #include "icache.h"
+ // Main simulation loop, fast path.
+ for (auto ic_entry = _mmu->access_icache(pc); ; ) {
+ auto fetch = ic_entry->data;
+ pc = execute_insn(this, pc, fetch);
+ ic_entry = ic_entry->next;
+ if (unlikely(ic_entry->tag != pc))
+ break;
+ if (unlikely(instret + 1 == n))
+ break;
+ instret++;
+ state.pc = pc;
}
advance_pc();