Don't allow 32-bit instructions to take up multiple slots in I$
authorAndrew Waterman <andrew@sifive.com>
Wed, 21 Feb 2018 21:25:44 +0000 (13:25 -0800)
committerAndrew Waterman <andrew@sifive.com>
Wed, 21 Feb 2018 23:35:19 +0000 (15:35 -0800)
I$ indices now maintain a 1:N relationship with PCs.  This is somewhat
faster and also simpler.

riscv/execute.cc
riscv/mmu.h

index 878893c80d18b840ee985e4c792004bd7304eb21..e60ffd117ebeb58a0f8f16c46bb5161ce1d58053 100644 (file)
@@ -171,13 +171,6 @@ void processor_t::step(size_t n)
         //
         // According to Andrew Waterman's recollection, this optimization
         // resulted in approximately a 2x performance increase.
-        //
-        // If there is support for compressed instructions, the mmu and the
-        // switch statement get more complicated. Each branch target is stored
-        // in the index corresponding to mmu->icache_index(), but consecutive
-        // non-branching instructions are stored in consecutive indices even if
-        // mmu->icache_index() specifies a different index (which is the case
-        // for 32-bit instructions in the presence of compressed instructions).
 
         // This figures out where to jump to in the switch statement
         size_t idx = _mmu->icache_index(pc);
@@ -193,10 +186,10 @@ void processor_t::step(size_t n)
         // is located within the execute_insn() function call.
         #define ICACHE_ACCESS(i) { \
           insn_fetch_t fetch = ic_entry->data; \
-          ic_entry++; \
           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)) goto miss; \
+          if (unlikely(ic_entry->tag != pc)) break; \
           if (unlikely(instret+1 == n)) break; \
           instret++; \
           state.pc = pc; \
@@ -210,13 +203,6 @@ void processor_t::step(size_t n)
         }
 
         advance_pc();
-        continue;
-
-miss:
-        advance_pc();
-        // refill I$ if it looks like there wasn't a taken branch
-        if (pc > (ic_entry-1)->tag && pc <= (ic_entry-1)->tag + MAX_INSN_LENGTH)
-          _mmu->refill_icache(pc, ic_entry);
       }
     }
     catch(trap_t& t)
index 0b58f69ce96df85aa988dddff581946d497897b7..d275ab2baa2e412319c0a6ada72f41b932058e14 100644 (file)
@@ -26,7 +26,7 @@ struct insn_fetch_t
 
 struct icache_entry_t {
   reg_t tag;
-  reg_t pad;
+  struct icache_entry_t* next;
   insn_fetch_t data;
 };
 
@@ -209,6 +209,7 @@ public:
 
     insn_fetch_t fetch = {proc->decode_insn(insn), insn};
     entry->tag = addr;
+    entry->next = &icache[icache_index(addr + length)];
     entry->data = fetch;
 
     reg_t paddr = tlb_entry.target_offset + addr;;