libmicroemu 0.2.0
ARM Microcontroller Emulator Library
Loading...
Searching...
No Matches
spec_reg_ops.h
1#pragma once
2
4#include "libmicroemu/internal/utils/bit_manip.h"
5#include "libmicroemu/logger.h"
6#include "libmicroemu/register_details.h"
8#include "libmicroemu/types.h"
9
10#include <array>
11#include <cstddef>
12#include <cstdint>
13
14namespace libmicroemu::internal {
15
16//----
17
18template <typename TCpuStates, typename TLogger = NullLogger> class SpecRegOps {
19public:
20 static std::string_view GetRegisterName(const SpecialRegisterId &reg_id) {
21 switch (reg_id) {
23 return "SYSCTRL";
25 return "APSR";
27 return "ISTATE";
29 return "SYSTICK_CSR";
31 return "SYSTICK_RVR";
33 return "SYSTICK_CVR";
35 return "SYSTICK_CALIB";
37 return "XPSR";
38 default:
39 return "UNDEFINED";
40 }
41 }
42
43 template <SpecialRegisterId SId> static inline u32 ReadRegister(const TCpuStates &cpus) {
44 constexpr auto RegId = static_cast<u8>(SId);
45 static_assert(RegId < CountSpecialRegisters(), "Invalid special register id");
46
47 switch (SId) {
49 return ReadEpsr(cpus);
51 return ReadXpsr(cpus);
53 return ReadControl(cpus);
54 default:
55 // Persistent special register access
56 return cpus.GetSpecialRegisters()[RegId];
57 }
58 // Not reachable
59 return 0U;
60 }
61
62 static inline u32 ReadRegister(const TCpuStates &cpus, const SpecialRegisterId &reg_id) {
63 assert(static_cast<u8>(reg_id) < CountSpecialRegisters() && "Invalid special register id");
64 switch (reg_id) {
66 return ReadEpsr(cpus);
68 return ReadXpsr(cpus);
70 return ReadControl(cpus);
71 default:
72 // Persistent special register access
73 return cpus.GetSpecialRegisters()[static_cast<u8>(reg_id)];
74 }
75 // Not reachable
76 return 0U;
77 }
78
79 template <SpecialRegisterId SId> static inline void WriteRegister(TCpuStates &cpus, u32 value) {
80 constexpr auto RegId = static_cast<u8>(SId);
81 static_assert(RegId < CountSpecialRegisters(), "Invalid special register id");
82
83 switch (SId) {
85 return WriteEpsr(cpus, value);
87 return WriteXpsr(cpus, value);
89 return WriteControl(cpus, value);
90 default:
91 // Persistent special register access
92 cpus.GetSpecialRegisters()[RegId] = value;
93 }
94
95 // not reachable
96 }
97
98 static inline void WriteRegister(TCpuStates &cpus, const SpecialRegisterId &reg_id, u32 value) {
99 assert(static_cast<u8>(reg_id) < CountSpecialRegisters() && "Invalid special register id");
100 switch (reg_id) {
102 return WriteEpsr(cpus, value);
104 return WriteXpsr(cpus, value);
106 return WriteControl(cpus, value);
107 default:
108 const auto rid = static_cast<u8>(reg_id);
109 // Persistent special register access
110 cpus.GetSpecialRegisters()[rid] = value;
111 }
112 }
113
114 static inline u32 ReadEpsr(const TCpuStates &cpus) {
115 u32 epsr = 0U;
116 auto sys_ctrl = ReadRegister<SpecialRegisterId::kSysCtrl>(cpus);
117 auto BitT = (sys_ctrl & SysCtrlRegister::kTMsk) >> SysCtrlRegister::kTPos; // Thumb mode bit
118 epsr |= BitT << EpsrRegister::kTPos;
119
120 // extract it bits from Istate and write them to epsr
121 auto istate = ReadRegister<SpecialRegisterId::kIstate>(cpus);
122 auto it_1_0 = (istate & IstateRegister::kItBit1to0Msk) >> IstateRegister::kItBit0Pos;
123 auto it_7_2 = (istate & IstateRegister::kItBit7to2Msk) >> IstateRegister::kItBit2Pos;
124 epsr |= (it_1_0 << EpsrRegister::kItBit0Pos) | (it_7_2 << EpsrRegister::kItBit2Pos);
125 return epsr;
126 }
127
128 static inline void WriteEpsr(TCpuStates &cpus, u32 value) {
129 auto sys_ctrl = ReadRegister<SpecialRegisterId::kSysCtrl>(cpus);
130 auto BitT = (value & EpsrRegister::kTMsk) >> EpsrRegister::kTPos; // Thumb mode bit
131 sys_ctrl &= ~SysCtrlRegister::kTMsk;
132 sys_ctrl |= BitT << SysCtrlRegister::kTPos;
133 WriteRegister<SpecialRegisterId::kSysCtrl>(cpus, sys_ctrl);
134
135 // extract it bits from "value" and write them to Istate register
136 u32 istate = 0U;
137 auto it_1_0 = (value & EpsrRegister::kItBit1to0Msk) >> EpsrRegister::kItBit0Pos;
138 auto it_7_2 = (value & EpsrRegister::kItBit7to2Msk) >> EpsrRegister::kItBit2Pos;
139 istate |= (it_1_0 << IstateRegister::kItBit0Pos) | (it_7_2 << IstateRegister::kItBit2Pos);
140 WriteRegister<SpecialRegisterId::kIstate>(cpus, istate);
141 }
142
143 static inline u32 ReadXpsr(const TCpuStates &cpus) {
144 auto xpsr = 0U;
145 auto apsr = ReadRegister<SpecialRegisterId::kApsr>(cpus);
146 xpsr |= apsr;
147
148 auto epsr = ReadEpsr(cpus);
149 xpsr |= epsr;
150
151 auto ipsr = ReadRegister<SpecialRegisterId::kIpsr>(cpus);
152 xpsr |= ipsr;
153
154 return xpsr;
155 }
156
157 static inline void WriteXpsr(TCpuStates &cpus, u32 value) {
158 static_cast<void>(cpus);
159 static_cast<void>(value);
160 assert(false && "Not implemented");
161 }
162
163 static inline u32 ReadControl(const TCpuStates &cpus) {
164 const auto sys_ctrl = ReadRegister<SpecialRegisterId::kSysCtrl>(cpus);
165 const auto npriv = (sys_ctrl & static_cast<u32>(SysCtrlRegister::kControlNPrivMsk)) >>
166 SysCtrlRegister::kControlNPrivPos;
167 const auto spsel = (sys_ctrl & static_cast<u32>(SysCtrlRegister::kControlSpSelMsk)) >>
168 SysCtrlRegister::kControlSpSelPos;
169 const auto fpca = (sys_ctrl & static_cast<u32>(SysCtrlRegister::kControlFpcaMsk)) >>
170 SysCtrlRegister::kControlFpcaPos;
171
172 auto control{0U};
173 control |= npriv << ControlRegister::kNPrivPos;
174 control |= spsel << ControlRegister::kSpselPos;
175 control |= fpca << ControlRegister::kFpcaPos;
176 static_cast<void>(cpus);
177 return control;
178 }
179
180 static inline void WriteControl(TCpuStates &cpus, u32 value) {
181 const auto npriv =
182 (value & static_cast<u32>(ControlRegister::kNPrivMsk)) >> ControlRegister::kNPrivPos;
183 const auto spsel =
184 (value & static_cast<u32>(ControlRegister::kSpselMsk)) >> ControlRegister::kSpselPos;
185
186 const auto fpca =
187 (value & static_cast<u32>(ControlRegister::kFpcaMsk)) >> ControlRegister::kFpcaPos;
188
189 auto sys_ctrl = ReadRegister<SpecialRegisterId::kSysCtrl>(cpus);
190 sys_ctrl &= ~SysCtrlRegister::kControlNPrivMsk;
191 sys_ctrl |= npriv << SysCtrlRegister::kControlNPrivPos;
192
193 sys_ctrl &= ~SysCtrlRegister::kControlSpSelMsk;
194 sys_ctrl |= spsel << SysCtrlRegister::kControlSpSelPos;
195
196 sys_ctrl &= ~SysCtrlRegister::kControlFpcaMsk;
197 sys_ctrl |= fpca << SysCtrlRegister::kControlFpcaPos;
198
199 WriteRegister<SpecialRegisterId::kSysCtrl>(cpus, sys_ctrl);
200 }
201
202private:
203 SpecRegOps() = delete;
204 ~SpecRegOps() = delete;
205 SpecRegOps &operator=(const SpecRegOps &r_src) = delete;
206 SpecRegOps(SpecRegOps &&r_src) = delete;
207 SpecRegOps &operator=(SpecRegOps &&r_src) = delete;
208 SpecRegOps(const SpecRegOps &r_src) = delete;
209};
210
211} // namespace libmicroemu::internal
The libmicroemu::internal namespace contains all classes and functions of libmicroemu which are priva...
Definition bkpt_flags.h:6
SpecialRegisterId
Enumeration of special register IDs.
Definition special_register_id.h:18
@ kSysTickCsr
SYSTICK_CSR - SysTick Control and Status Register.
Definition special_register_id.h:35
@ kEpsr
Execution Program Status Register, EPSR.
Definition special_register_id.h:44
@ kSysTickCalib
SYST_CALIB - SysTick Calibration Value Register.
Definition special_register_id.h:38
@ kSysTickCvr
SYST_CVR - SysTick Current Value Register.
Definition special_register_id.h:37
@ kIstate
If-Then Execution state bits.
Definition special_register_id.h:27
@ kSysTickRvr
SYSTICK_RVR - SysTick Reload Value Register.
Definition special_register_id.h:36
@ kSysCtrl
System Control Register, SYSCTRL.
Definition special_register_id.h:25
@ kApsr
Application Program Status Register, APSR.
Definition special_register_id.h:26
@ kControl
Control register, CONTROL.
Definition special_register_id.h:46
@ kXpsr
Program status register, XPSR.
Definition special_register_id.h:45
static constexpr u32 CountSpecialRegisters() noexcept
Returns the number of special registers.
Definition special_register_id.h:73
Contains the Result class which is used to return the result of a function.
This file contains the declaration of the SpecialRegisterId enumeration and related functions.
Definition register_details.h:254