31template <
typename TCpuStates>
class Emulator {
33 class ExceptionTrigger;
34 class ExceptionReturn;
38 using SpecRegOps = SpecRegOps<TCpuStates, StaticLogger>;
39 using RegOps = RegOps<TCpuStates, SpecRegOps, StaticLogger>;
41 using CpuAccessor = CpuAccessor<TCpuStates, RegOps, SpecRegOps>;
44 using SysCtrlBlock = SysCtrlBlock<CpuAccessor, StaticLogger>;
45 using SysTick = SysTick<CpuAccessor, ExceptionTrigger, StaticLogger>;
49 using Flash = MemRo<0U, CpuAccessor, EndConv>;
54 using Peripherals =
MemMapRw<3U, 0xE0000000U, 0xFFFFU,
76 using Semihosting = Semihosting<CpuAccessor, Bus, StaticLogger>;
79 using PcOps = PcOps<CpuAccessor, Bus, ExceptionReturn, StaticLogger>;
82 using CpuOps = CpuOps<ItOps, PcOps, ExcOps, ExceptionTrigger>;
85 using Fetcher = Fetcher<CpuAccessor, Bus>;
86 using Decoder = Decoder<CpuAccessor, ItOps>;
87 using Executor = Executor<CpuAccessor, Bus, CpuOps, StaticLogger>;
90 using ResetLogic = ResetLogic<CpuAccessor, Bus, CpuOps, StaticLogger>;
91 using Processor = Processor<CpuAccessor, Bus, CpuOps, Fetcher, Decoder, Executor, StaticLogger>;
93 Emulator(TCpuStates &cpu_states) : cpu_states_(cpu_states) {}
95 void SetFlashSegment(
const u8 *seg_ptr, me_size_t seg_size, me_adr_t seg_vadr) {
97 flash_size_ = seg_size;
98 flash_vadr_ = seg_vadr;
101 void SetRam1Segment(u8 *seg_ptr, me_size_t seg_size, me_adr_t seg_vadr) {
103 ram1_size_ = seg_size;
104 ram1_vadr_ = seg_vadr;
107 void SetRam2Segment(u8 *seg_ptr, me_size_t seg_size, me_adr_t seg_vadr) {
109 ram2_size_ = seg_size;
110 ram2_vadr_ = seg_vadr;
114 Flash code_access(
const_cast<u8 *
>(flash_), flash_size_, flash_vadr_);
115 Ram0 rw_mem_access(ram1_, ram1_size_, ram1_vadr_);
116 Ram1 rw_stack_access(ram2_, ram2_size_, ram2_vadr_);
117 Peripherals peripheral_access;
119 Bus bus(code_access, rw_mem_access, rw_stack_access, peripheral_access);
124 auto bus = BuildBus();
125 auto &cpua =
static_cast<CpuAccessor &
>(cpu_states_);
132 void SetEntryPoint(u32 entry_point) {
133 const auto aligned_entry_point = entry_point & (~0x1U);
135 LOG_INFO(
StaticLogger,
"Overwrite entry point to 0x%X", aligned_entry_point);
136 auto &cpua =
static_cast<CpuAccessor &
>(cpu_states_);
137 PcOps::BranchTo(cpua, aligned_entry_point);
142 auto bus = BuildBus();
143 auto &cpua =
static_cast<CpuAccessor &
>(cpu_states_);
144 auto semihosting = Semihosting(cpua, bus);
147 bool is_instr_limit = instr_limit > 0;
148 u64 u_instr_limit =
static_cast<u64
>(instr_limit);
151 cb_pre_exec, cb_post_exec,
153 return semihosting.Call(imm32);
156 SvcFlagsSet svc_flags{0U};
159 svc_flags |=
static_cast<SvcFlagsSet
>(SvcFlags::kOmitException);
160 svc_flags |=
static_cast<SvcFlagsSet
>(SvcFlags::kRequestExit);
161 return Ok<SvcFlagsSet>(svc_flags);
164 return Ok<SvcFlagsSet>(svc_flags);
168 const auto step_ret = Processor::Step(cpua, bus, delegates);
169 if (step_ret.IsErr()) {
170 return ExecResult(step_ret.status_code, EXIT_FAILURE);
173 const auto step_flags = step_ret.content;
174 if (step_flags &
static_cast<StepFlagsSet
>(StepFlags::kStepTerminationRequest)) {
178 const auto systick_ret = SysTick::Step(cpua);
179 if (systick_ret.IsErr()) {
180 return ExecResult(systick_ret.status_code, EXIT_FAILURE);
184 if (is_instr_limit && instr_count >= u_instr_limit) {
195 class ExceptionTrigger {
197 template <
typename... Args>
static void SetPending(Args &&...args) {
198 ExcOps::SetExceptionPending(std::forward<Args>(args)...);
201 ExceptionTrigger() =
delete;
202 ~ExceptionTrigger() =
delete;
203 ExceptionTrigger(
const ExceptionTrigger &) =
delete;
204 ExceptionTrigger(ExceptionTrigger &&) =
delete;
206 auto &operator=(
const ExceptionTrigger &) =
delete;
207 auto &operator=(ExceptionTrigger &&) =
delete;
211 class ExceptionReturn {
213 template <
typename... Args>
static Result<void> Return(Args &&...args) {
214 return ExcOps::ExceptionReturn(std::forward<Args>(args)...);
217 ExceptionReturn() =
delete;
218 ~ExceptionReturn() =
delete;
219 ExceptionReturn(
const ExceptionReturn &) =
delete;
220 ExceptionReturn(ExceptionReturn &&) =
delete;
222 auto &operator=(
const ExceptionReturn &) =
delete;
223 auto &operator=(ExceptionReturn &&) =
delete;
226 const u8 *flash_{
nullptr};
227 me_size_t flash_size_{0U};
228 me_adr_t flash_vadr_{0U};
231 me_size_t ram1_size_{0U};
232 me_adr_t ram1_vadr_{0U};
235 me_size_t ram2_size_{0U};
236 me_adr_t ram2_vadr_{0U};
238 TCpuStates &cpu_states_;