libmicroemu 0.2.0
ARM Microcontroller Emulator Library
Loading...
Searching...
No Matches
variadic_load_instr.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
18template <typename TInstrContext> class VariadicLoadInstr {
19public:
20 using It = typename TInstrContext::It;
21 using Pc = typename TInstrContext::Pc;
22
23 using ExcTrig = typename TInstrContext::ExcTrig;
24
25 template <typename TArg0>
26 static Result<InstrExecResult> Call(TInstrContext &ictx, const InstrFlagsSet &iflags,
27 const TArg0 &rn, const u32 &registers) {
28 TRY_ASSIGN(condition_passed, InstrExecResult, It::ConditionPassed(ictx.cpua));
29
30 if (!condition_passed) {
31 PostExecAdvancePcAndIt::Call(ictx, iflags);
32 return Ok(InstrExecResult{kNoInstrExecFlags});
33 }
34
35 const auto n = ictx.cpua.ReadRegister(rn.Get());
36 auto address = static_cast<me_adr_t>(n);
37
38 for (u32 rid = 0U; rid <= 14U; ++rid) {
39 const u32 bm = 0x1U << rid;
40 if ((registers & bm) != 0U) {
42 ictx.bus.template ReadOrRaise<u32>(ictx.cpua, address,
43 BusExceptionType::kRaisePreciseDataBusError));
44 ictx.cpua.WriteRegister(static_cast<RegisterId>(rid), rdat);
45 address += static_cast<me_adr_t>(4U);
46 }
47 }
48
49 if (Bm32::ExtractBits1R<15U, 15U>(registers) == 0x1U) {
51 ictx.bus.template ReadOrRaise<u32>(ictx.cpua, address,
52 BusExceptionType::kRaisePreciseDataBusError));
53 TRY(InstrExecResult, PostExecLoadWritePc::Call(ictx, rdat));
54
55 // do not advance pc
56 } else {
57 PostExecAdvancePcAndIt::Call(ictx, iflags);
58 }
59
60 // For debugging purposes
61 // MemoryViewer<TMemAccess> mem_view(mem_acs_);
62 // mem_view.Print(0x80000 - 0x32, 0x64);
63
64 const bool is_wback = (iflags & static_cast<InstrFlagsSet>(InstrFlags::kWBack)) != 0U;
65 const auto n_mask = 1U << static_cast<u32>(rn.Get());
66 const bool is_rn_in_set = (registers & n_mask) != 0;
67
68 if ((is_wback) && (!is_rn_in_set)) {
69 auto regcount = Bm32::BitCount(registers);
70 const auto wback_val = n + 4U * regcount;
71
72 // Update n register
73 ictx.cpua.WriteRegister(rn.Get(), wback_val);
74 }
75
76 return Ok(InstrExecResult{kNoInstrExecFlags});
77 }
78
79private:
83 VariadicLoadInstr() = delete;
84
88 ~VariadicLoadInstr() = delete;
89
94 VariadicLoadInstr(const VariadicLoadInstr &r_src) = delete;
95
100 VariadicLoadInstr &operator=(const VariadicLoadInstr &r_src) = delete;
101
106 VariadicLoadInstr(VariadicLoadInstr &&r_src) = delete;
107
112 VariadicLoadInstr &operator=(VariadicLoadInstr &&r_src) = delete;
113};
114
115} // namespace libmicroemu::internal
static constexpr u32 ExtractBits1R(const u32 &value)
Definition bit_manip.h:136
static u32 BitCount(const u32 &value)
Definition bit_manip.h:243
The libmicroemu::internal namespace contains all classes and functions of libmicroemu which are priva...
Definition bkpt_flags.h:6
RegisterId
Enumeration of register IDs.
Definition register_id.h:13
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 instr_exec_results.h:23
Definition result.h:15