libmicroemu 0.2.0
ARM Microcontroller Emulator Library
Loading...
Searching...
No Matches
ternary_store_instr_with_shift.h
1#pragma once
2#include "libmicroemu/internal/decoder/decoder.h"
3#include "libmicroemu/internal/executor/instr_context.h"
4#include "libmicroemu/internal/executor/instr_exec_results.h"
6#include "libmicroemu/internal/utils/rarg.h"
7#include "libmicroemu/register_details.h"
8#include "libmicroemu/types.h"
9
10namespace libmicroemu::internal {
11
15template <typename TStoreOp, typename TInstrContext> class TernaryStoreInstrWithShift {
16public:
17 using It = typename TInstrContext::It;
18 using Pc = typename TInstrContext::Pc;
19
20 template <typename TTgt, typename TArg0, typename TArg1>
21 static Result<InstrExecResult> Call(TInstrContext &ictx, const InstrFlagsSet &iflags,
22 const TTgt &rt, const TArg0 &rn, const TArg1 &rm,
23 const ImmShiftResults &shift_res) {
24 const bool is_index = (iflags & static_cast<InstrFlagsSet>(InstrFlags::kIndex)) != 0U;
25 const bool is_add = (iflags & static_cast<InstrFlagsSet>(InstrFlags::kAdd)) != 0U;
26
27 TRY_ASSIGN(condition_passed, InstrExecResult, It::ConditionPassed(ictx.cpua));
28 if (!condition_passed) {
29 PostExecAdvancePcAndIt::Call(ictx, iflags);
30 return Ok(InstrExecResult{kNoInstrExecFlags});
31 }
32
33 InstrExecFlagsSet eflags{kNoInstrExecFlags};
34 const auto n = ictx.cpua.ReadRegister(rn.Get());
35 const auto m = ictx.cpua.ReadRegister(rm.Get());
36
37 auto apsr = ictx.cpua.template ReadSpecialRegister<SpecialRegisterId::kApsr>();
38
39 auto offset = Alu32::Shift(m, shift_res.type, shift_res.value,
40 (apsr & ApsrRegister::kCMsk) == ApsrRegister::kCMsk);
41
42 assert(is_add == true); // other mode is currently not supported
43 const u32 offset_addr = is_add == true ? n + offset : n - offset;
44 const u32 address = is_index == true ? offset_addr : n;
45
46 const auto t = ictx.cpua.ReadRegister(rt.Get());
47 TRY(InstrExecResult, TStoreOp::Write(ictx, address, t));
48
49 const bool is_wback = (iflags & static_cast<InstrFlagsSet>(InstrFlags::kWBack)) != 0U;
50 if (is_wback) {
51 PostExecWriteRegPcExcluded::Call(ictx, rn, offset_addr);
52 }
53 PostExecAdvancePcAndIt::Call(ictx, iflags);
54 return Ok(InstrExecResult{eflags});
55 }
56
57private:
61 TernaryStoreInstrWithShift() = delete;
62
66 ~TernaryStoreInstrWithShift() = delete;
67
72 TernaryStoreInstrWithShift(const TernaryStoreInstrWithShift &r_src) = delete;
73
78 TernaryStoreInstrWithShift &operator=(const TernaryStoreInstrWithShift &r_src) = delete;
79
84 TernaryStoreInstrWithShift(TernaryStoreInstrWithShift &&r_src) = delete;
85
90 TernaryStoreInstrWithShift &operator=(TernaryStoreInstrWithShift &&r_src) = delete;
91};
92
93} // namespace libmicroemu::internal
The libmicroemu::internal namespace contains all classes and functions of libmicroemu which are priva...
Definition bkpt_flags.h:6
Contains the Result class which is used to return the result of a function.
#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
Definition imm_shift_results.h:15
Definition instr_exec_results.h:23
Definition result.h:15