libmicroemu 0.2.0
ARM Microcontroller Emulator Library
Loading...
Searching...
No Matches
post_exec.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
12struct OpResult {
13 u32 value;
14 bool carry_out;
15 bool overflow;
16};
17
19public:
20 template <typename TInstrContext, typename OpResult>
21 static inline void Call(const TInstrContext &ictx, const OpResult &result) {
22 auto apsr = ictx.cpua.template ReadSpecialRegister<SpecialRegisterId::kApsr>();
23
24 // Clear N, Z, C, V flags
25 apsr &=
26 ~(ApsrRegister::kNMsk | ApsrRegister::kZMsk | ApsrRegister::kCMsk | ApsrRegister::kVMsk);
27
28 apsr |= ((result.value >> 31U) & 0x1U) << ApsrRegister::kNPos; // N
29 apsr |= Bm32::IsZeroBit(result.value) << ApsrRegister::kZPos; // Z
30 apsr |= (result.carry_out == true ? 0x1U : 0x0U) << ApsrRegister::kCPos; // C
31 apsr |= (result.overflow == true ? 0x1U : 0x0U) << ApsrRegister::kVPos; // V
32 ictx.cpua.template WriteSpecialRegister<SpecialRegisterId::kApsr>(apsr);
33 }
34};
35
37public:
38 template <typename TInstrContext, typename OpResult>
39 static inline void Call(const TInstrContext &ictx, const InstrFlagsSet &iflags,
40 const OpResult &result) {
41 if ((iflags & static_cast<InstrFlagsSet>(InstrFlags::kSetFlags)) != 0U) {
42 PostExecSetFlags::Call(ictx, result);
43 }
44 }
45};
46
48public:
49 template <typename TInstrContext>
50 static inline void Call(const TInstrContext &ictx, const InstrFlagsSet &iflags) {
51 using It = typename TInstrContext::It;
52 using Pc = typename TInstrContext::Pc;
53
54 const auto is_32bit = (iflags & static_cast<InstrFlagsSet>(InstrFlags::k32Bit)) != 0U;
55 It::ITAdvance(ictx.cpua);
56 Pc::AdvanceInstr(ictx.cpua, is_32bit);
57 }
58};
59
61public:
62 template <typename TInstrContext>
63 static inline void Call(const TInstrContext &ictx, const me_adr_t &new_pc) {
64 using It = typename TInstrContext::It;
65 using Pc = typename TInstrContext::Pc;
66
67 Pc::BranchWritePC(ictx.cpua, new_pc);
68 It::ITAdvance(ictx.cpua);
69 }
70};
71
73public:
74 template <typename TInstrContext>
75 static inline Result<void> Call(const TInstrContext &ictx, const me_adr_t &new_pc) {
76 using It = typename TInstrContext::It;
77 using Pc = typename TInstrContext::Pc;
78
79 TRY(void, Pc::LoadWritePC(ictx.cpua, ictx.bus, new_pc));
80 It::ITAdvance(ictx.cpua);
81 return Ok();
82 }
83};
84
86public:
87 template <typename TInstrContext>
88 static inline Result<void> Call(const TInstrContext &ictx, const me_adr_t &new_pc) {
89 using It = typename TInstrContext::It;
90 using Pc = typename TInstrContext::Pc;
91
92 TRY(void, Pc::BXWritePC(ictx.cpua, ictx.bus, new_pc));
93 It::ITAdvance(ictx.cpua);
94 return Ok();
95 }
96};
97
99public:
100 template <typename TInstrContext>
101 static inline void Call(const TInstrContext &ictx, const me_adr_t &new_pc) {
102 using It = typename TInstrContext::It;
103 using Pc = typename TInstrContext::Pc;
104
105 Pc::BLXWritePC(ictx.cpua, new_pc);
106 It::ITAdvance(ictx.cpua);
107 }
108};
109
111public:
112 template <typename TInstrContext, typename TArg>
113 static void Call(const TInstrContext &ictx, const TArg &arg, const u32 &value) {
114 assert(arg.Get() != RegisterId::kPc);
115 ictx.cpua.WriteRegister(arg.Get(), value);
116 }
117};
118
120public:
121 template <typename TInstrContext, typename TArg>
122 static Result<void> Call(const TInstrContext &ictx, const InstrFlagsSet &iflags, const TArg &arg,
123 const u32 &value, const bool is_aligned) {
124 // This instruction is a branch instruction
125 // It fails if the address from which is was loaded is not aligned
126 if (arg.Get() == RegisterId::kPc) {
127 if (is_aligned) {
128 TRY(void, PostExecLoadWritePc::Call(ictx, value));
129 } else {
131 }
132 } else {
133 ictx.cpua.WriteRegister(arg.Get(), value);
134 PostExecAdvancePcAndIt::Call(ictx, iflags);
135 }
136 return Ok();
137 }
138};
139
140} // namespace libmicroemu::internal
static u32 IsZeroBit(const u32 &value)
Definition bit_manip.h:234
Definition post_exec.h:47
Definition post_exec.h:98
Definition post_exec.h:60
Definition post_exec.h:85
Definition post_exec.h:72
Definition post_exec.h:36
Definition post_exec.h:18
Definition post_exec.h:110
Definition post_exec.h:119
The libmicroemu::internal namespace contains all classes and functions of libmicroemu which are priva...
Definition bkpt_flags.h:6
@ kExecutorUnpredictable
Executor encountered an unpredictable operation.
Definition status_code.h:76
@ kPc
Program-counter register.
Definition register_id.h:34
Contains the Result class which is used to return the result of a function.
#define TRY(OUT_TYPE, CALL)
Try to call a function and return an error if the call fails.
Definition result.h:138
Definition post_exec.h:12
Definition result.h:15