libmicroemu 0.2.0
ARM Microcontroller Emulator Library
Loading...
Searching...
No Matches
variadic_store_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
17template <typename TInstrContext> class VariadicStoreInstr {
18public:
19 using It = typename TInstrContext::It;
20 using Pc = typename TInstrContext::Pc;
21
22 template <typename TArg0>
23 static Result<InstrExecResult> Call(TInstrContext &ictx, const InstrFlagsSet &iflags,
24 const TArg0 &rn, const u32 &registers) {
25 TRY_ASSIGN(condition_passed, InstrExecResult, It::ConditionPassed(ictx.cpua));
26
27 if (!condition_passed) {
28 PostExecAdvancePcAndIt::Call(ictx, iflags);
29 return Ok(InstrExecResult{kNoInstrExecFlags});
30 }
31
32 const auto n = ictx.cpua.ReadRegister(rn.Get());
33 auto reg_count = Bm32::BitCount(registers);
34 u32 address = n;
35 const bool is_wback = (iflags & static_cast<InstrFlagsSet>(InstrFlags::kWBack)) != 0U;
36 const bool lowest_bit_set = Bm8::LowestBitSet(registers);
37 for (u32 reg = 0U; reg <= 14U; ++reg) {
38 u32 bm = 0x1U << reg;
39 if ((registers & bm) != 0U) {
40 if ((reg == static_cast<u32>(rn.Get())) && (is_wback) && (lowest_bit_set == reg)) {
41 return Err<InstrExecResult>(StatusCode::kExecutorUndefined);
42 } else {
43 const auto r = ictx.cpua.ReadRegister(static_cast<RegisterId>(reg));
45 ictx.bus.template WriteOrRaise<u32>(ictx.cpua, address, r,
46 BusExceptionType::kRaisePreciseDataBusError));
47 }
48
49 address += 4U;
50 }
51 }
52
53 // For debugging purposes
54 // MemoryViewer<TMemAccess> mem_view(bus_);
55 // mem_view.Print(0x80000 - 0x32, 0x64);
56
57 if (is_wback) {
58 const auto wback_val = n + 4U * reg_count;
59
60 // Update n register
61 PostExecWriteRegPcExcluded::Call(ictx, rn, wback_val);
62 }
63 PostExecAdvancePcAndIt::Call(ictx, iflags);
64
65 return Ok(InstrExecResult{kNoInstrExecFlags});
66 }
67
68private:
72 VariadicStoreInstr() = delete;
73
77 ~VariadicStoreInstr() = delete;
78
83 VariadicStoreInstr(const VariadicStoreInstr &r_src) = delete;
84
89 VariadicStoreInstr &operator=(const VariadicStoreInstr &r_src) = delete;
90
95 VariadicStoreInstr(VariadicStoreInstr &&r_src) = delete;
96
101 VariadicStoreInstr &operator=(VariadicStoreInstr &&r_src) = delete;
102};
103
104} // namespace libmicroemu::internal
static u8 LowestBitSet(const u8 &value)
Definition bit_manip.h:257
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
@ kExecutorUndefined
Executor encountered an undefined operation.
Definition status_code.h:79
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