24 using It =
typename TProcessorOps::It;
25 using Exc =
typename TProcessorOps::Exc;
26 using Pc =
typename TProcessorOps::Pc;
27 using ExcTrig =
typename TProcessorOps::ExcTrig;
30 static bool IsThumbModeOrRaise(TCpuAccessor &cpua) {
35 auto cfsr = cpua.template ReadSpecialRegister<SpecialRegisterId::kCfsr>();
36 cfsr |= CfsrUsageFault::kInvStateMsk;
37 cpua.template WriteSpecialRegister<SpecialRegisterId::kCfsr>(cfsr);
44 template <
typename TDelegates>
46 static constexpr u8 kRaw32BitMsk =
static_cast<RawInstrFlagsSet
>(RawInstrFlagsMsk::k32Bit);
48 StepFlagsSet step_flags{0U};
55 const me_adr_t pc =
static_cast<me_adr_t
>(cpua.template ReadRegister<RegisterId::kPc>());
56 me_adr_t pc_this_instr =
static_cast<me_adr_t
>(pc - 4U);
60 TRY_ASSIGN(if_pre_fetch_exception, StepFlagsSet,
61 Exc::template CheckExceptions<ExceptionPreFetch>(cpua, bus, exc_ctx_pre_fetch));
65 if (if_pre_fetch_exception) {
66 const me_adr_t pc =
static_cast<me_adr_t
>(cpua.template ReadRegister<RegisterId::kPc>());
67 pc_this_instr =
static_cast<me_adr_t
>(pc - 4U);
73 if (IsThumbModeOrRaise(cpua)) {
74 auto r_raw_instr = TFetcher::Fetch(cpua, bus, pc_this_instr);
75 if (r_raw_instr.IsErr()) {
76 ErrorHandler(cpua, r_raw_instr, bus);
77 return Err<RawInstr, StepFlagsSet>(r_raw_instr);
79 raw_instr = r_raw_instr.content;
87 Exc::template CheckExceptions<ExceptionPostFetch>(cpua, bus, exc_ctx_post_fetch));
89 if (is_fetch_exception) {
94 step_flags |=
static_cast<StepFlagsSet
>(StepFlags::kStepOk);
95 return Ok<StepFlagsSet>(step_flags);
99 auto r_instr = TDecoder::Decode(cpua, raw_instr);
100 if (r_instr.IsErr()) {
101 ErrorHandler(cpua, r_instr, bus);
102 return Err<Instr, StepFlagsSet>(r_instr);
104 const auto &instr = r_instr.content;
108 static constexpr u8 k32BitMsk =
static_cast<InstrFlagsSet
>(InstrFlags::k32Bit);
110 assert(((((raw_instr.flags & kRaw32BitMsk) != 0U) && ((instr.nop.flags & k32BitMsk) != 0U)) ||
111 (((raw_instr.flags & kRaw32BitMsk) == 0U) && ((instr.nop.flags & k32BitMsk) == 0U))));
115 if (delegates.IsPreExecSet()) {
116 const auto is_32bit = (raw_instr.flags & kRaw32BitMsk) == kRaw32BitMsk;
117 auto op_code =
OpCode{raw_instr.low, raw_instr.high, is_32bit};
123 EmuContext(pc_this_instr, op_code, instr_to_mnemonic, reg_access, spec_reg_access);
124 delegates.PreExec(emu_ctx);
128 const auto r_execute = TExecutor::Execute(cpua, bus, instr, delegates);
129 if (r_execute.IsErr()) {
130 ErrorHandler(cpua, r_execute, bus);
131 return Err<InstrExecResult, StepFlagsSet>(r_execute);
134 if (delegates.IsPostExecSet()) {
135 const auto is_32bit = (raw_instr.flags & kRaw32BitMsk) == kRaw32BitMsk;
136 auto op_code =
OpCode{raw_instr.low, raw_instr.high, is_32bit};
141 EmuContext(pc_this_instr, op_code, instr_to_mnemonic, reg_access, spec_reg_access);
142 delegates.PostExec(emu_ctx);
146 const auto &eflags = r_execute.content.flags;
149 if ((eflags & kExitFlagsMask) != 0U) {
150 if ((eflags &
static_cast<InstrExecFlagsSet
>(InstrExecFlags::kBkptReqExit)) != 0U) {
151 step_flags |=
static_cast<StepFlagsSet
>(StepFlags::kStepTerminationRequest);
152 return Ok<StepFlagsSet>(step_flags);
154 if ((eflags &
static_cast<InstrExecFlagsSet
>(InstrExecFlags::kSvcReqExit)) != 0U) {
155 step_flags |=
static_cast<StepFlagsSet
>(StepFlags::kStepTerminationRequest);
156 return Ok<StepFlagsSet>(step_flags);
158 if ((eflags &
static_cast<InstrExecFlagsSet
>(InstrExecFlags::kBkptReqErrorExit)) != 0U) {
161 if ((eflags &
static_cast<InstrExecFlagsSet
>(InstrExecFlags::kSvcReqErrorExit)) != 0U) {
170 Exc::template CheckExceptions<ExceptionPostExecution>(cpua, bus, exc_ctc_post_exec));
172 step_flags |=
static_cast<StepFlagsSet
>(StepFlags::kStepOk);
173 return Ok<StepFlagsSet>(step_flags);
176 template <
typename TResult>
177 static void ErrorHandler(TCpuAccessor &cpua,
const TResult &res,
const TBus &bus) {
178 printf(
"ERROR: Emulator panic - StatusCode: %s(%i)\n", res.ToString().data(),
179 static_cast<u32
>(res.status_code));
182 const me_adr_t pc =
static_cast<me_adr_t
>(cpua.template ReadRegister<RegisterId::kPc>());
183 me_adr_t pc_this_instr =
static_cast<me_adr_t
>(pc - 0x4U);
184 printf(
" # System state:\n");
185 printf(
" Actual PC: 0x%x\n\n", pc_this_instr);
186 printf(
" # Memory dump from PC:\n");
192 Processor() =
delete;
193 ~Processor() =
delete;
194 Processor(Processor &r_src) =
delete;
195 Processor &operator=(
const Processor &r_src) =
delete;
196 Processor(Processor &&r_src) =
delete;
197 Processor &operator=(Processor &&r_src) =
delete;