libmicroemu 0.2.0
ARM Microcontroller Emulator Library
Loading...
Searching...
No Matches
mnemonic_builder_special_instr.h
1#pragma once
2
3#include "libmicroemu/internal/trace/instr/generic/relative_adr_builder.h"
4
6#include "libmicroemu/types.h"
7
8namespace libmicroemu::internal {
9
13template <typename TContext> class MnemonicBuilderSpecialInstr {
14public:
15 using It = typename TContext::It;
16 using Reg = typename TContext::Reg;
17 using SReg = typename TContext::SReg;
18
19 template <typename TDest, typename TArg0>
20 static void BuildUbfx(const char *instr_spec, TContext &mctx,
21 const MnemonicBuilderFlagsSet &bflags, const InstrFlagsSet &iflags,
22 const TDest &rd, const TArg0 &rn, const u8 &lsbit, const u8 &widthminus1) {
23 static_cast<void>(iflags);
24 static_cast<void>(bflags);
25 mctx.builder.AddString(instr_spec)
26 .AddChar(' ')
27 .AddString(Reg::GetRegisterName(rd.Get()))
28 .AddString(", ")
29 .AddString(Reg::GetRegisterName(rn.Get()))
30 .AddString(", #")
31 .AddUInt(lsbit)
32 .AddString(", #")
33 .AddUInt(widthminus1 + 1U);
34
35 mctx.builder.Terminate();
36 }
37
38 template <typename TDest, typename TArg0>
39 static void BuildBfi(const char *instr_spec, TContext &mctx,
40 const MnemonicBuilderFlagsSet &bflags, const InstrFlagsSet &iflags,
41 const TDest &rd, const TArg0 &rn, const u8 &lsbit, const u8 &msbit) {
42 static_cast<void>(iflags);
43 static_cast<void>(bflags);
44
45 auto width = msbit - lsbit + 1;
46 mctx.builder.AddString(instr_spec)
47 .AddChar(' ')
48 .AddString(Reg::GetRegisterName(rd.Get()))
49 .AddString(", ")
50 .AddString(Reg::GetRegisterName(rn.Get()))
51 .AddString(", #")
52 .AddUInt(lsbit)
53 .AddString(", #")
54 .AddUInt(width);
55
56 mctx.builder.Terminate();
57 }
58
59 template <typename TTgt>
60 static void BuildLdrLiteral(const char *instr_spec, TContext &mctx,
61 const MnemonicBuilderFlagsSet &bflags, const InstrFlagsSet &iflags,
62 const TTgt &rt, const u32 imm32) {
63 static_cast<void>(iflags);
64 static_cast<void>(bflags);
65 mctx.builder.AddString(instr_spec)
66 .AddString(It::GetConditionAsStr(mctx.cpua))
67 .AddChar(' ')
68 .AddString(Reg::GetRegisterName(rt.Get()))
69 .AddString(", [PC, #")
70 .AddInt(imm32)
71 .AddChar(']')
72 .Terminate();
73 }
74
75 static void BuildMsrMrs(TContext &mctx, const u8 &mask, const u8 &SYSm) {
76 const auto SYSm_7_3 = Bm32::ExtractBits1R<7U, 3U>(SYSm);
77 switch (SYSm_7_3) {
78 case 0b00000U: {
79 if (mask & 0x1) {
80 mctx.builder.AddString("APSR_g"); // Application Program Status Register
81 } else {
82 mctx.builder.AddString("APSR_nzcvq"); // Application Program Status Register
83 }
84 break;
85 }
86 case 0b00001U: {
87 const auto SYSm_2_0 = Bm32::ExtractBits1R<2U, 0U>(SYSm);
88 switch (SYSm_2_0) {
89 case 0b000U:
90 mctx.builder.AddString("MSP"); // Main Stack Pointer
91 break;
92 case 0b001U:
93 mctx.builder.AddString("PSP"); // Process Stack Pointer
94 break;
95 default:
96 mctx.builder.AddString("undefined");
97 break;
98 }
99 break;
100 }
101 case 0b00010U: {
102 const auto SYSm_2_0 = Bm32::ExtractBits1R<2U, 0U>(SYSm);
103 switch (SYSm_2_0) {
104 case 0b000U:
105 mctx.builder.AddString("PRIMASK"); // Priority Mask
106 break;
107 case 0b001U:
108 mctx.builder.AddString("BASEPRI"); // Base Priority
109 break;
110 case 0b010U:
111 mctx.builder.AddString("BASEPRI_MAX"); // Base Priority Max
112 break;
113 case 0b011U:
114 mctx.builder.AddString("FAULTMASK"); // Fault Mask
115 break;
116 case 0b100U:
117 mctx.builder.AddString("CONTROL"); // Control
118 break;
119 default:
120 mctx.builder.AddString("undefined");
121 break;
122 }
123 } break;
124 default:
125 mctx.builder.AddString("undefined");
126 break;
127 }
128 }
129
130 template <typename TDest>
131 static void BuildMrs(const char *instr_spec, TContext &mctx,
132 const MnemonicBuilderFlagsSet &bflags, const InstrFlagsSet &iflags,
133 const TDest &rd, const u8 &mask, const u8 &SYSm) {
134 static_cast<void>(iflags);
135 static_cast<void>(bflags);
136 mctx.builder.AddString(instr_spec).AddString(It::GetConditionAsStr(mctx.cpua)).AddChar(' ');
137 mctx.builder.AddString(Reg::GetRegisterName(rd.Get())).AddString(", ");
138 BuildMsrMrs(mctx, mask, SYSm);
139 mctx.builder.Terminate();
140 }
141
142 template <typename TArg0>
143 static void BuildMsr(const char *instr_spec, TContext &mctx,
144 const MnemonicBuilderFlagsSet &bflags, const InstrFlagsSet &iflags,
145 const TArg0 &rn, const u8 &mask, const u8 &SYSm) {
146 static_cast<void>(iflags);
147 static_cast<void>(bflags);
148 mctx.builder.AddString(instr_spec).AddString(It::GetConditionAsStr(mctx.cpua)).AddChar(' ');
149 BuildMsrMrs(mctx, mask, SYSm);
150 mctx.builder.AddString(", ").AddString(Reg::GetRegisterName(rn.Get())).Terminate();
151 }
152
153 template <typename TTgt, typename TArg0, typename TArg1>
154 static void BuildLdrdStrd(const char *instr_spec, TContext &mctx,
155 const MnemonicBuilderFlagsSet &bflags, const InstrFlagsSet &iflags,
156 const TTgt &rt, const TArg0 &t2, const TArg1 &rn, const u32 imm32) {
157 static_cast<void>(bflags);
158 const bool is_wback = (iflags & static_cast<InstrFlagsSet>(InstrFlags::kWBack)) != 0U;
159 const bool is_index = (iflags & static_cast<InstrFlagsSet>(InstrFlags::kIndex)) != 0U;
160 const bool is_add = (iflags & static_cast<InstrFlagsSet>(InstrFlags::kAdd)) != 0U;
161 mctx.builder.AddString(instr_spec)
162 .AddString(It::GetConditionAsStr(mctx.cpua))
163 .AddChar(' ')
164 .AddString(Reg::GetRegisterName(rt.Get()))
165 .AddString(", ")
166 .AddString(Reg::GetRegisterName(t2.Get()))
167 .AddString(", ");
168
169 RelativeAdrBuilder::Build<decltype(mctx.builder), Reg>(mctx.builder, is_add, is_index, is_wback,
170 rn, imm32);
171 mctx.builder.Terminate();
172 }
173
174 static void BuildBCond(const char *instr_spec, TContext &mctx,
175 const MnemonicBuilderFlagsSet &bflags, const InstrFlagsSet &iflags,
176 const u8 &cond, const u32 &imm) {
177 static_cast<void>(iflags);
178 static_cast<void>(bflags);
179 mctx.builder.AddString(instr_spec)
180 .AddString(It::ConditionToString(cond))
181 .AddString(" #")
182 .AddInt(static_cast<i32>(imm))
183 .Terminate();
184 }
185
186 static void BuildIt(const char *instr_spec, TContext &mctx, const MnemonicBuilderFlagsSet &bflags,
187 const InstrFlagsSet &iflags, const u8 &firstcond, const u8 &mask) {
188 static_cast<void>(iflags);
189 static_cast<void>(bflags);
190 auto then_or_else = [](u8 cond) {
191 if (cond == 0x1U) {
192 return "T";
193 } else {
194 return "E";
195 }
196 };
197 const char *x_spec = "";
198 const char *y_spec = "";
199 const char *z_spec = "";
200 switch (mask) {
201 case 0b1000U:
202 // do nothing
203 break;
204 case 0b0100U:
205 x_spec = then_or_else(Bm32::ExtractBits1R<0U, 0U>(firstcond) != 0x1U);
206 break;
207 case 0b1100U:
208 x_spec = then_or_else(Bm32::ExtractBits1R<0U, 0U>(firstcond) == 0x1U);
209 break;
210 case 0b0010U:
211 x_spec = then_or_else(Bm32::ExtractBits1R<0U, 0U>(firstcond) != 0x1U);
212 y_spec = then_or_else(Bm32::ExtractBits1R<0U, 0U>(firstcond) != 0x1U);
213 break;
214 case 0b0110U:
215 x_spec = then_or_else(Bm32::ExtractBits1R<0U, 0U>(firstcond) != 0x1U);
216 y_spec = then_or_else(Bm32::ExtractBits1R<0U, 0U>(firstcond) == 0x1U);
217 break;
218 case 0b1010U:
219 x_spec = then_or_else(Bm32::ExtractBits1R<0U, 0U>(firstcond) == 0x1U);
220 y_spec = then_or_else(Bm32::ExtractBits1R<0U, 0U>(firstcond) != 0x1U);
221 break;
222 case 0b1110U:
223 x_spec = then_or_else(Bm32::ExtractBits1R<0U, 0U>(firstcond) == 0x1U);
224 y_spec = then_or_else(Bm32::ExtractBits1R<0U, 0U>(firstcond) == 0x1U);
225 break;
226 case 0b0001U:
227 x_spec = then_or_else(Bm32::ExtractBits1R<0U, 0U>(firstcond) != 0x1U);
228 y_spec = then_or_else(Bm32::ExtractBits1R<0U, 0U>(firstcond) != 0x1U);
229 z_spec = then_or_else(Bm32::ExtractBits1R<0U, 0U>(firstcond) != 0x1U);
230 break;
231 case 0b0011U:
232 x_spec = then_or_else(Bm32::ExtractBits1R<0U, 0U>(firstcond) != 0x1U);
233 y_spec = then_or_else(Bm32::ExtractBits1R<0U, 0U>(firstcond) != 0x1U);
234 z_spec = then_or_else(Bm32::ExtractBits1R<0U, 0U>(firstcond) == 0x1U);
235 break;
236 case 0b0101U:
237 x_spec = then_or_else(Bm32::ExtractBits1R<0U, 0U>(firstcond) != 0x1U);
238 y_spec = then_or_else(Bm32::ExtractBits1R<0U, 0U>(firstcond) == 0x1U);
239 z_spec = then_or_else(Bm32::ExtractBits1R<0U, 0U>(firstcond) != 0x1U);
240 break;
241 case 0b0111U:
242 x_spec = then_or_else(Bm32::ExtractBits1R<0U, 0U>(firstcond) != 0x1U);
243 y_spec = then_or_else(Bm32::ExtractBits1R<0U, 0U>(firstcond) == 0x1U);
244 z_spec = then_or_else(Bm32::ExtractBits1R<0U, 0U>(firstcond) == 0x1U);
245 break;
246 case 0b1001U:
247 x_spec = then_or_else(Bm32::ExtractBits1R<0U, 0U>(firstcond) == 0x1U);
248 y_spec = then_or_else(Bm32::ExtractBits1R<0U, 0U>(firstcond) != 0x1U);
249 z_spec = then_or_else(Bm32::ExtractBits1R<0U, 0U>(firstcond) != 0x1U);
250 break;
251 case 0b1011U:
252 x_spec = then_or_else(Bm32::ExtractBits1R<0U, 0U>(firstcond) == 0x1U);
253 y_spec = then_or_else(Bm32::ExtractBits1R<0U, 0U>(firstcond) != 0x1U);
254 z_spec = then_or_else(Bm32::ExtractBits1R<0U, 0U>(firstcond) == 0x1U);
255 break;
256 case 0b1101U:
257 x_spec = then_or_else(Bm32::ExtractBits1R<0U, 0U>(firstcond) == 0x1U);
258 y_spec = then_or_else(Bm32::ExtractBits1R<0U, 0U>(firstcond) == 0x1U);
259 z_spec = then_or_else(Bm32::ExtractBits1R<0U, 0U>(firstcond) != 0x1U);
260 break;
261 case 0b1111U:
262 x_spec = then_or_else(Bm32::ExtractBits1R<0U, 0U>(firstcond) == 0x1U);
263 y_spec = then_or_else(Bm32::ExtractBits1R<0U, 0U>(firstcond) == 0x1U);
264 z_spec = then_or_else(Bm32::ExtractBits1R<0U, 0U>(firstcond) == 0x1U);
265 break;
266 default:
267 break;
268 }
269
270 mctx.builder.AddString(instr_spec)
271 .AddString(x_spec)
272 .AddString(y_spec)
273 .AddString(z_spec)
274 .AddChar(' ')
275 .AddString(It::ConditionToString(firstcond))
276 .Terminate();
277 }
278
279private:
283 MnemonicBuilderSpecialInstr() = delete;
284
288 ~MnemonicBuilderSpecialInstr() = delete;
289
294 MnemonicBuilderSpecialInstr(const MnemonicBuilderSpecialInstr &r_src) = default;
295
300 MnemonicBuilderSpecialInstr &operator=(const MnemonicBuilderSpecialInstr &r_src) = delete;
301
306 MnemonicBuilderSpecialInstr(MnemonicBuilderSpecialInstr &&r_src) = delete;
307
312 MnemonicBuilderSpecialInstr &operator=(MnemonicBuilderSpecialInstr &&r_src) = delete;
313};
314
315} // namespace libmicroemu::internal
static constexpr u32 ExtractBits1R(const u32 &value)
Definition bit_manip.h:136
static void Build(TMnemonicBuilder &builder, const bool &is_add, const bool &is_index, const bool &is_wback, const TArg0 &rn, const u32 &imm)
Uses the given str builder to build a string representing the different addressing modes of instructi...
Definition relative_adr_builder.h:23
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.