15template <
typename TLoadOp,
typename TInstrContext>
class TernaryLoadInstrWithShift {
17 using It =
typename TInstrContext::It;
18 using Pc =
typename TInstrContext::Pc;
20 using ExcTrig =
typename TInstrContext::ExcTrig;
22 template <
typename TTgt,
typename TArg0,
typename TArg1>
24 const TTgt &rt,
const TArg0 &rn,
const TArg1 &rm,
26 const bool is_wback = (iflags &
static_cast<InstrFlagsSet
>(InstrFlags::kWBack)) != 0U;
27 const bool is_index = (iflags &
static_cast<InstrFlagsSet
>(InstrFlags::kIndex)) != 0U;
28 const bool is_add = (iflags &
static_cast<InstrFlagsSet
>(InstrFlags::kAdd)) != 0U;
31 if (!condition_passed) {
32 PostExecAdvancePcAndIt::Call(ictx, iflags);
35 const auto n = ictx.cpua.ReadRegister(rn.Get());
36 const auto m = ictx.cpua.ReadRegister(rm.Get());
38 auto apsr = ictx.cpua.template ReadSpecialRegister<SpecialRegisterId::kApsr>();
39 auto offset = Alu32::Shift(m, shift_res.type, shift_res.value,
40 (apsr & ApsrRegister::kCMsk) == ApsrRegister::kCMsk);
42 const u32 offset_addr = is_add ==
true ? n + offset : n - offset;
43 const u32 address = is_index ==
true ? offset_addr : n;
47 PostExecWriteRegPcExcluded::Call(ictx, rn, offset_addr);
49 const bool is_aligned = (address & 0x3U) == 0U;
50 TRY(
InstrExecResult, PostExecWriteRegPcIncluded::Call(ictx, iflags, rt, data, is_aligned));
58 TernaryLoadInstrWithShift() =
delete;
63 ~TernaryLoadInstrWithShift() =
delete;
69 TernaryLoadInstrWithShift(
const TernaryLoadInstrWithShift &r_src) =
delete;
75 TernaryLoadInstrWithShift &operator=(
const TernaryLoadInstrWithShift &r_src) =
delete;
81 TernaryLoadInstrWithShift(TernaryLoadInstrWithShift &&r_src) =
delete;
87 TernaryLoadInstrWithShift &operator=(TernaryLoadInstrWithShift &&r_src) =
delete;
#define TRY_ASSIGN(NAME, OUT_TYPE, CALL)
Try to assign a value to a variable and return an error if the assignment fails.
Definition result.h:123
#define TRY(OUT_TYPE, CALL)
Try to call a function and return an error if the call fails.
Definition result.h:138