1 // See LICENSE for license details.
15 processor_t::processor_t(sim_t
* _sim
, mmu_t
* _mmu
, uint32_t _id
)
16 : sim(*_sim
), mmu(*_mmu
), id(_id
), opcode_bits(0)
19 mmu
.set_processor(this);
21 #define DECLARE_INSN(name, match, mask) \
22 extern reg_t rv32_##name(processor_t*, insn_t, reg_t); \
23 extern reg_t rv64_##name(processor_t*, insn_t, reg_t); \
24 register_insn(match, mask, rv32_##name, rv64_##name);
29 processor_t::~processor_t()
35 // the ISA guarantees on boot that the PC is 0x2000 and the the processor
36 // is in supervisor mode, and in 64-bit mode, if supported, with traps
37 // and virtual memory disabled.
39 #ifdef RISCV_ENABLE_64BIT
44 // the following state is undefined upon boot-up,
45 // but we zero it for determinism
60 load_reservation
= -1;
63 void processor_t::reset(bool value
)
72 uint32_t processor_t::set_fsr(uint32_t val
)
74 uint32_t old_fsr
= state
.fsr
;
75 state
.fsr
= val
& ~FSR_ZERO
; // clear FSR bits that read as zero
79 void processor_t::take_interrupt()
81 uint32_t interrupts
= (state
.sr
& SR_IP
) >> SR_IP_SHIFT
;
82 interrupts
&= (state
.sr
& SR_IM
) >> SR_IM_SHIFT
;
84 if (interrupts
&& (state
.sr
& SR_EI
))
85 for (int i
= 0; ; i
++, interrupts
>>= 1)
87 throw trap_t((1ULL << ((state
.sr
& SR_S64
) ? 63 : 31)) + i
);
90 void processor_t::step(size_t n
, bool noisy
)
103 // execute_insn fetches and executes one instruction
104 #define execute_insn(noisy) \
106 mmu_t::insn_fetch_t fetch = _mmu.load_insn(npc); \
107 if(noisy) disasm(fetch.insn, npc); \
108 npc = fetch.func(this, fetch.insn, npc); \
111 if(noisy
) for( ; i
< n
; i
++) // print out instructions as we go
115 // unrolled for speed
116 for( ; n
> 3 && i
< n
-3; i
+=4)
131 take_trap(npc
, t
, noisy
);
136 // update timer and possibly register a timer interrupt
137 uint32_t old_count
= state
.count
;
139 if(old_count
< state
.compare
&& uint64_t(old_count
) + i
>= state
.compare
)
140 set_interrupt(IRQ_TIMER
, true);
143 void processor_t::take_trap(reg_t pc
, trap_t
& t
, bool noisy
)
147 if ((sreg_t
)t
.cause() < 0)
148 fprintf(stderr
, "core %3d: interrupt %d, epc 0x%016" PRIx64
"\n",
149 id
, uint8_t(t
.cause()), pc
);
151 fprintf(stderr
, "core %3d: trap %s, epc 0x%016" PRIx64
"\n",
155 // switch to supervisor, set previous supervisor bit, disable interrupts
156 set_pcr(PCR_SR
, (((state
.sr
& ~SR_EI
) | SR_S
) & ~SR_PS
& ~SR_PEI
) |
157 ((state
.sr
& SR_S
) ? SR_PS
: 0) |
158 ((state
.sr
& SR_EI
) ? SR_PEI
: 0));
159 yield_load_reservation();
160 state
.cause
= t
.cause();
162 state
.pc
= state
.evec
;
164 t
.side_effects(&state
); // might set badvaddr etc.
167 void processor_t::deliver_ipi()
170 set_pcr(PCR_CLR_IPI
, 1);
173 void processor_t::disasm(insn_t insn
, reg_t pc
)
175 // the disassembler is stateless, so we share it
176 static disassembler disasm
;
177 fprintf(stderr
, "core %3d: 0x%016" PRIx64
" (0x%08" PRIxFAST32
") %s\n",
178 id
, state
.pc
, insn
.bits
, disasm
.disassemble(insn
).c_str());
181 reg_t
processor_t::set_pcr(int which
, reg_t val
)
183 reg_t old_pcr
= get_pcr(which
);
188 state
.sr
= (val
& ~SR_IP
) | (state
.sr
& SR_IP
);
189 #ifndef RISCV_ENABLE_64BIT
190 state
.sr
&= ~(SR_S64
| SR_U64
);
192 #ifndef RISCV_ENABLE_FPU
195 #ifndef RISCV_ENABLE_VEC
198 state
.sr
&= ~SR_ZERO
;
211 set_interrupt(IRQ_TIMER
, false);
215 state
.ptbr
= val
& ~(PGSIZE
-1);
221 set_interrupt(IRQ_IPI
, val
& 1);
230 if (state
.tohost
== 0)
234 set_interrupt(IRQ_HOST
, val
!= 0);
235 state
.fromhost
= val
;
242 reg_t
processor_t::get_pcr(int which
)
251 return state
.badvaddr
;
257 return state
.compare
;
278 return state
.fromhost
;
283 void processor_t::set_interrupt(int which
, bool on
)
285 uint32_t mask
= (1 << (which
+ SR_IP_SHIFT
)) & SR_IP
;
292 static reg_t
illegal_instruction(processor_t
* p
, insn_t insn
, reg_t pc
)
294 throw trap_illegal_instruction();
297 insn_func_t
processor_t::decode_insn(insn_t insn
)
299 bool rv64
= (state
.sr
& SR_S
) ? (state
.sr
& SR_S64
) : (state
.sr
& SR_U64
);
301 auto key
= insn
.bits
& ((1L << opcode_bits
)-1);
302 for (auto it
= opcode_map
.find(key
); it
!= opcode_map
.end() && it
->first
== key
; ++it
)
303 if ((insn
.bits
& it
->second
.mask
) == it
->second
.match
)
304 return rv64
? it
->second
.rv64
: it
->second
.rv32
;
306 return &illegal_instruction
;
309 void processor_t::register_insn(uint32_t match
, uint32_t mask
, insn_func_t rv32
, insn_func_t rv64
)
312 if (opcode_bits
== 0 || (mask
& ((1L << opcode_bits
)-1)) != ((1L << opcode_bits
)-1))
315 while ((mask
& ((1L << (x
+1))-1)) == ((1L << (x
+1))-1) &&
316 (opcode_bits
== 0 || x
<= opcode_bits
))
320 decltype(opcode_map
) new_map
;
321 for (auto it
= opcode_map
.begin(); it
!= opcode_map
.end(); ++it
)
322 new_map
.insert(std::make_pair(it
->second
.match
& ((1L<<x
)-1), it
->second
));
323 opcode_map
= new_map
;
326 opcode_map
.insert(std::make_pair(match
& ((1L<<opcode_bits
)-1),
327 (opcode_map_entry_t
){match
, mask
, rv32
, rv64
}));