1 // See LICENSE for license details.
7 static void commit_log(state_t
* state
, reg_t pc
, insn_t insn
)
9 #ifdef RISCV_ENABLE_COMMITLOG
10 int32_t priv
= get_field(state
->mstatus
, MSTATUS_PRV
);
11 uint64_t mask
= (insn
.length() == 8 ? uint64_t(0) : (uint64_t(1) << (insn
.length() * 8))) - 1;
12 if (state
->log_reg_write
.addr
) {
13 fprintf(stderr
, "%1d 0x%016" PRIx64
" (0x%08" PRIx64
") %c%2" PRIu64
" 0x%016" PRIx64
"\n",
17 state
->log_reg_write
.addr
& 1 ? 'f' : 'x',
18 state
->log_reg_write
.addr
>> 1,
19 state
->log_reg_write
.data
);
21 fprintf(stderr
, "%1d 0x%016" PRIx64
" (0x%08" PRIx64
")\n", priv
, pc
, insn
.bits() & mask
);
23 state
->log_reg_write
.addr
= 0;
27 inline void processor_t::update_histogram(size_t pc
)
29 #ifdef RISCV_ENABLE_HISTOGRAM
35 static reg_t
execute_insn(processor_t
* p
, reg_t pc
, insn_fetch_t fetch
)
37 reg_t npc
= fetch
.func(p
, fetch
.insn
, pc
);
38 if (npc
!= PC_SERIALIZE
) {
39 commit_log(p
->get_state(), pc
, fetch
.insn
);
40 p
->update_histogram(pc
);
45 // fetch/decode/execute loop
46 void processor_t::step(size_t n
)
48 while (run
&& n
> 0) {
53 #define advance_pc() \
54 if (unlikely(pc == PC_SERIALIZE)) { \
56 state.serialized = true; \
72 insn_fetch_t fetch
= mmu
->load_insn(pc
);
73 if (!state
.serialized
)
75 pc
= execute_insn(this, pc
, fetch
);
79 else while (instret
< n
)
81 size_t idx
= _mmu
->icache_index(pc
);
82 auto ic_entry
= _mmu
->access_icache(pc
);
84 #define ICACHE_ACCESS(i) { \
85 insn_fetch_t fetch = ic_entry->data; \
87 pc = execute_insn(this, pc, fetch); \
88 if (i == mmu_t::ICACHE_ENTRIES-1) break; \
89 if (unlikely(ic_entry->tag != pc)) goto miss; \
90 if (unlikely(instret+1 == n)) break; \
104 // refill I$ if it looks like there wasn't a taken branch
105 if (pc
> (ic_entry
-1)->tag
&& pc
<= (ic_entry
-1)->tag
+ MAX_INSN_LENGTH
)
106 _mmu
->refill_icache(pc
, ic_entry
);
114 state
.minstret
+= instret
;