libmicroemu 0.2.0
ARM Microcontroller Emulator Library
Loading...
Searching...
No Matches
mnemonic_builder.h
1#pragma once
2
3#include "libmicroemu/internal/trace/instr/mnemonic_builder_binary64bit_instr.h"
4#include "libmicroemu/internal/trace/instr/mnemonic_builder_binary_instr.h"
5#include "libmicroemu/internal/trace/instr/mnemonic_builder_binary_instr_with_imm.h"
6#include "libmicroemu/internal/trace/instr/mnemonic_builder_binary_instr_with_imm_carry.h"
7#include "libmicroemu/internal/trace/instr/mnemonic_builder_binary_instr_with_rotation.h"
8#include "libmicroemu/internal/trace/instr/mnemonic_builder_binary_instr_with_shift.h"
9#include "libmicroemu/internal/trace/instr/mnemonic_builder_binary_loadstore_instr_with_imm.h"
10#include "libmicroemu/internal/trace/instr/mnemonic_builder_binary_null_instr.h"
11#include "libmicroemu/internal/trace/instr/mnemonic_builder_binary_null_instr_with_imm.h"
12#include "libmicroemu/internal/trace/instr/mnemonic_builder_binary_null_instr_with_imm_carry.h"
13#include "libmicroemu/internal/trace/instr/mnemonic_builder_nullary_instr.h"
14#include "libmicroemu/internal/trace/instr/mnemonic_builder_special_instr.h"
15#include "libmicroemu/internal/trace/instr/mnemonic_builder_ternary_instr.h"
16#include "libmicroemu/internal/trace/instr/mnemonic_builder_ternary_instr_with_shift.h"
17#include "libmicroemu/internal/trace/instr/mnemonic_builder_ternary_loadstore_instr_with_imm.h"
18#include "libmicroemu/internal/trace/instr/mnemonic_builder_ternary_loadstore_instr_with_shift.h"
19#include "libmicroemu/internal/trace/instr/mnemonic_builder_ternary_null_instr_with_shift.h"
20#include "libmicroemu/internal/trace/instr/mnemonic_builder_unary_branch_instr.h"
21#include "libmicroemu/internal/trace/instr/mnemonic_builder_unary_branch_instr_with_imm.h"
22#include "libmicroemu/internal/trace/instr/mnemonic_builder_unary_instr.h"
23#include "libmicroemu/internal/trace/instr/mnemonic_builder_unary_instr_with_imm_carry.h"
24#include "libmicroemu/internal/trace/instr/mnemonic_builder_unary_null_instr_with_imm.h"
25#include "libmicroemu/internal/trace/instr/mnemonic_builder_variadic_loadstore_instr.h"
26#include "libmicroemu/internal/trace/mnemonic_builder_context.h"
27#include "libmicroemu/internal/trace/mnemonic_builder_flags.h"
28#include "libmicroemu/internal/utils/rarg.h"
29#include "libmicroemu/types.h"
30#include <cstddef>
31
32namespace libmicroemu::internal {
33
34class MnemonicBuilder {
35public:
36 template <typename TCpuAccessor, typename TItOps, typename TRegOps, typename TSpecRegOps>
37 static void Build(const TCpuAccessor &cpua, const Instr &instr, char *buf, std::size_t buf_len) {
38
39 auto cstr_builder = ConstStringBuilder(buf, buf_len);
40 using TMnemonicBuilderContext =
42 auto mctx = TMnemonicBuilderContext{cpua, cstr_builder};
43 MnemonicBuilderFlagsSet bflags =
44 static_cast<MnemonicBuilderFlagsSet>(MnemonicBuilderFlags::kNone);
45 switch (instr.id) {
46 case InstrId::kLdrLiteral: {
47 const auto &iargs = instr.ldr_literal;
48 MnemonicBuilderSpecialInstr<TMnemonicBuilderContext>::BuildLdrLiteral(
49 "LDR", mctx, bflags, iargs.flags, RArg(iargs.t), iargs.imm32);
50 break;
51 }
52 case InstrId::kLdrsbImmediate: {
53 const auto &iargs = instr.ldrsb_immediate;
54 MnemonicBuilderBinaryLoadStoreInstrWithImm<TMnemonicBuilderContext>::Build(
55 "LDRSB", mctx, bflags, iargs.flags, RArg(iargs.t), RArg(iargs.n), iargs.imm32);
56 break;
57 }
58 case InstrId::kLdrbImmediate: {
59 const auto &iargs = instr.ldrb_immediate;
60 MnemonicBuilderBinaryLoadStoreInstrWithImm<TMnemonicBuilderContext>::Build(
61 "LDRB", mctx, bflags, iargs.flags, RArg(iargs.t), RArg(iargs.n), iargs.imm32);
62 break;
63 }
64 case InstrId::kLdrshImmediate: {
65 const auto &iargs = instr.ldrsh_immediate;
66 MnemonicBuilderBinaryLoadStoreInstrWithImm<TMnemonicBuilderContext>::Build(
67 "LDRSH", mctx, bflags, iargs.flags, RArg(iargs.t), RArg(iargs.n), iargs.imm32);
68 break;
69 }
70 case InstrId::kLdrhImmediate: {
71 const auto &iargs = instr.ldrh_immediate;
72 MnemonicBuilderBinaryLoadStoreInstrWithImm<TMnemonicBuilderContext>::Build(
73 "LDRH", mctx, bflags, iargs.flags, RArg(iargs.t), RArg(iargs.n), iargs.imm32);
74 break;
75 }
76 case InstrId::kLdrImmediate: {
77 const auto &iargs = instr.ldr_immediate;
78 MnemonicBuilderBinaryLoadStoreInstrWithImm<TMnemonicBuilderContext>::Build(
79 "LDR", mctx, bflags, iargs.flags, RArg(iargs.t), RArg(iargs.n), iargs.imm32);
80 break;
81 }
82 case InstrId::kLdrex: {
83 const auto &iargs = instr.ldr_immediate;
84 MnemonicBuilderBinaryLoadStoreInstrWithImm<TMnemonicBuilderContext>::Build(
85 "LDREX", mctx, bflags, iargs.flags, RArg(iargs.t), RArg(iargs.n), iargs.imm32);
86 break;
87 }
88 case InstrId::kMsr: {
89 const auto &iargs = instr.msr;
90 MnemonicBuilderSpecialInstr<TMnemonicBuilderContext>::BuildMsr(
91 "MSR", mctx, bflags, iargs.flags, RArg(iargs.n), iargs.mask, iargs.SYSm);
92 break;
93 }
94 case InstrId::kMrs: {
95 const auto &iargs = instr.mrs;
96 MnemonicBuilderSpecialInstr<TMnemonicBuilderContext>::BuildMrs(
97 "MRS", mctx, bflags, iargs.flags, RArg(iargs.d), iargs.mask, iargs.SYSm);
98 break;
99 }
100 case InstrId::kUmlal: {
101 const auto &iargs = instr.umlal;
102 MnemonicBuilderBinary64bitInstr<TMnemonicBuilderContext>::Build(
103 "UMLAL", mctx, bflags, iargs.flags, RArg(iargs.dLo), RArg(iargs.dHi), RArg(iargs.n),
104 RArg(iargs.m));
105 break;
106 }
107 case InstrId::kUmull: {
108 const auto &iargs = instr.umull;
109 MnemonicBuilderBinary64bitInstr<TMnemonicBuilderContext>::Build(
110 "UMULL", mctx, bflags, iargs.flags, RArg(iargs.dLo), RArg(iargs.dHi), RArg(iargs.n),
111 RArg(iargs.m));
112 break;
113 }
114 case InstrId::kSmull: {
115 const auto &iargs = instr.umull;
116 MnemonicBuilderBinary64bitInstr<TMnemonicBuilderContext>::Build(
117 "SMULL", mctx, bflags, iargs.flags, RArg(iargs.dLo), RArg(iargs.dHi), RArg(iargs.n),
118 RArg(iargs.m));
119 break;
120 }
121 case InstrId::kLdrdImmediate: {
122 const auto &iargs = instr.ldrd_immediate;
123 MnemonicBuilderSpecialInstr<TMnemonicBuilderContext>::BuildLdrdStrd(
124 "LDRD", mctx, bflags, iargs.flags, RArg(iargs.t), RArg(iargs.t2), RArg(iargs.n),
125 iargs.imm32);
126 break;
127 }
128 case InstrId::kCmpImmediate: {
129 const auto &iargs = instr.cmp_immediate;
130 MnemonicBuilderBinaryNullInstrWithImm<TMnemonicBuilderContext>::Build(
131 "CMP", mctx, bflags, iargs.flags, RArg(iargs.n), iargs.imm32);
132 break;
133 }
134 case InstrId::kCmnImmediate: {
135 const auto &iargs = instr.cmn_immediate;
136 MnemonicBuilderBinaryNullInstrWithImm<TMnemonicBuilderContext>::Build(
137 "CMN", mctx, bflags, iargs.flags, RArg(iargs.n), iargs.imm32);
138 break;
139 }
140 case InstrId::kIt: {
141 const auto &iargs = instr.it;
142 MnemonicBuilderSpecialInstr<TMnemonicBuilderContext>::BuildIt("IT", mctx, bflags, iargs.flags,
143 iargs.firstcond, iargs.mask);
144 break;
145 }
146 case InstrId::kMovImmediate: {
147 const auto &iargs = instr.mov_immediate;
148 MnemonicBuilderUnaryInstrWithImmCarry<TMnemonicBuilderContext>::Build(
149 "MOV", mctx, bflags, iargs.flags, RArg(iargs.d), iargs.imm32_carry);
150 break;
151 }
152 case InstrId::kMvnImmediate: {
153 const auto &iargs = instr.mvn_immediate;
154 MnemonicBuilderUnaryInstrWithImmCarry<TMnemonicBuilderContext>::Build(
155 "MVN", mctx, bflags, iargs.flags, RArg(iargs.d), iargs.imm32_carry);
156 break;
157 }
158 case InstrId::kMovRegister: {
159 const auto &iargs = instr.mov_register;
160 MnemonicBuilderUnaryInstr<TMnemonicBuilderContext>::Build("MOV", mctx, bflags, iargs.flags,
161 RArg(iargs.d), RArg(iargs.m));
162 break;
163 }
164 case InstrId::kRrx: {
165 const auto &iargs = instr.rrx;
166 MnemonicBuilderUnaryInstr<TMnemonicBuilderContext>::Build("RRX", mctx, bflags, iargs.flags,
167 RArg(iargs.d), RArg(iargs.m));
168 break;
169 }
170 case InstrId::kBl: {
171 const auto &iargs = instr.bl;
172 MnemonicBuilderUnaryBranchInstrWithImm<TMnemonicBuilderContext>::Build(
173 "BL", mctx, bflags, iargs.flags, iargs.imm32);
174 break;
175 }
176 case InstrId::kBx: {
177 const auto &iargs = instr.bx;
178 MnemonicBuilderUnaryBranchInstr<TMnemonicBuilderContext>::Build("BX", mctx, bflags,
179 iargs.flags, RArg(iargs.m));
180 break;
181 }
182 case InstrId::kBlx: {
183 const auto &iargs = instr.blx;
184 MnemonicBuilderUnaryBranchInstr<TMnemonicBuilderContext>::Build("BLX", mctx, bflags,
185 iargs.flags, RArg(iargs.m));
186 break;
187 }
188 case InstrId::kBCond: {
189 const auto &iargs = instr.b_cond;
190 MnemonicBuilderSpecialInstr<TMnemonicBuilderContext>::BuildBCond(
191 "B", mctx, bflags, iargs.flags, iargs.cond, iargs.imm32);
192 break;
193 }
194 case InstrId::kB: {
195 const auto &iargs = instr.b;
196 MnemonicBuilderUnaryBranchInstrWithImm<TMnemonicBuilderContext>::Build(
197 "B", mctx, bflags, iargs.flags, iargs.imm32);
198 break;
199 }
200 case InstrId::kSubImmediate: {
201 const auto &iargs = instr.sub_immediate;
202 bflags |= static_cast<MnemonicBuilderFlagsSet>(MnemonicBuilderFlags::kReduceRd);
203 MnemonicBuilderBinaryInstrWithImm<TMnemonicBuilderContext>::Build(
204 "SUB", mctx, bflags, iargs.flags, RArg(iargs.d), RArg(iargs.n), iargs.imm32);
205 break;
206 }
207 case InstrId::kSbcImmediate: {
208 const auto &iargs = instr.sbc_immediate;
209 bflags |= static_cast<MnemonicBuilderFlagsSet>(MnemonicBuilderFlags::kReduceRd);
210 MnemonicBuilderBinaryInstrWithImm<TMnemonicBuilderContext>::Build(
211 "SBC", mctx, bflags, iargs.flags, RArg(iargs.d), RArg(iargs.n), iargs.imm32);
212 break;
213 }
214 case InstrId::kRsbImmediate: {
215 const auto &iargs = instr.rsb_immediate;
216 bflags |= static_cast<MnemonicBuilderFlagsSet>(MnemonicBuilderFlags::kReduceRd);
217 MnemonicBuilderBinaryInstrWithImm<TMnemonicBuilderContext>::Build(
218 "RSB", mctx, bflags, iargs.flags, RArg(iargs.d), RArg(iargs.n), iargs.imm32);
219 break;
220 }
221 case InstrId::kSubSpMinusImmediate: {
222 const auto &iargs = instr.sub_sp_minus_immediate;
223 bflags |= static_cast<MnemonicBuilderFlagsSet>(MnemonicBuilderFlags::kReduceRd);
224 MnemonicBuilderBinaryInstrWithImm<TMnemonicBuilderContext>::Build(
225 "SUB", mctx, bflags, iargs.flags, RArg(iargs.d), RArgConst<RegisterId::kSp>(),
226 iargs.imm32);
227 break;
228 }
229 case InstrId::kAddSpPlusImmediate: {
230 const auto &iargs = instr.add_sp_plus_immediate;
231 bflags |= static_cast<MnemonicBuilderFlagsSet>(MnemonicBuilderFlags::kReduceRd);
232 MnemonicBuilderBinaryInstrWithImm<TMnemonicBuilderContext>::Build(
233 "ADD", mctx, bflags, iargs.flags, RArg(iargs.d), RArgConst<RegisterId::kSp>(),
234 iargs.imm32);
235 break;
236 }
237 case InstrId::kAddImmediate: {
238 const auto &iargs = instr.add_immediate;
239 bflags |= static_cast<MnemonicBuilderFlagsSet>(MnemonicBuilderFlags::kReduceRd);
240 MnemonicBuilderBinaryInstrWithImm<TMnemonicBuilderContext>::Build(
241 "ADD", mctx, bflags, iargs.flags, RArg(iargs.d), RArg(iargs.n), iargs.imm32);
242 break;
243 }
244 case InstrId::kAdcImmediate: {
245 const auto &iargs = instr.adc_immediate;
246 bflags |= static_cast<MnemonicBuilderFlagsSet>(MnemonicBuilderFlags::kReduceRd);
247 MnemonicBuilderBinaryInstrWithImm<TMnemonicBuilderContext>::Build(
248 "ADC", mctx, bflags, iargs.flags, RArg(iargs.d), RArg(iargs.n), iargs.imm32);
249 break;
250 }
251 case InstrId::kAddPcPlusImmediate: {
252 const auto &iargs = instr.add_pc_plus_immediate;
253 bflags |= static_cast<MnemonicBuilderFlagsSet>(MnemonicBuilderFlags::kReduceRd);
254 MnemonicBuilderBinaryInstrWithImm<TMnemonicBuilderContext>::Build(
255 "ADD", mctx, bflags, iargs.flags, RArg(iargs.d), RArgConst<RegisterId::kPc>(),
256 iargs.imm32);
257 break;
258 }
259 case InstrId::kClz: {
260 const auto &iargs = instr.clz;
261 MnemonicBuilderUnaryInstr<TMnemonicBuilderContext>::Build("CLZ", mctx, bflags, iargs.flags,
262 RArg(iargs.d), RArg(iargs.m));
263 break;
264 }
265 case InstrId::kSubRegister: {
266 const auto &iargs = instr.sub_register;
267 bflags |= static_cast<MnemonicBuilderFlagsSet>(MnemonicBuilderFlags::kReduceRd);
268 MnemonicBuilderTernaryInstrWithShift<TMnemonicBuilderContext>::Build(
269 "SUB", mctx, bflags, iargs.flags, RArg(iargs.d), RArg(iargs.n), RArg(iargs.m),
270 iargs.shift_res);
271 break;
272 }
273 case InstrId::kRsbRegister: {
274 const auto &iargs = instr.rsb_register;
275 bflags |= static_cast<MnemonicBuilderFlagsSet>(MnemonicBuilderFlags::kReduceRd);
276 MnemonicBuilderTernaryInstrWithShift<TMnemonicBuilderContext>::Build(
277 "RSB", mctx, bflags, iargs.flags, RArg(iargs.d), RArg(iargs.n), RArg(iargs.m),
278 iargs.shift_res);
279 break;
280 }
281 case InstrId::kUdiv: {
282 const auto &iargs = instr.udiv;
283 bflags |= static_cast<MnemonicBuilderFlagsSet>(MnemonicBuilderFlags::kReduceRd);
284 MnemonicBuilderBinaryInstr<TMnemonicBuilderContext>::Build(
285 "UDIV", mctx, bflags, iargs.flags, RArg(iargs.d), RArg(iargs.n), RArg(iargs.m));
286 break;
287 }
288 case InstrId::kSdiv: {
289 const auto &iargs = instr.sdiv;
290 bflags |= static_cast<MnemonicBuilderFlagsSet>(MnemonicBuilderFlags::kReduceRd);
291 MnemonicBuilderBinaryInstr<TMnemonicBuilderContext>::Build(
292 "SDIV", mctx, bflags, iargs.flags, RArg(iargs.d), RArg(iargs.n), RArg(iargs.m));
293 break;
294 }
295 case InstrId::kMls: {
296 const auto &iargs = instr.mls;
297 MnemonicBuilderTernaryInstr<TMnemonicBuilderContext>::Build("MLS", mctx, bflags, iargs.flags,
298 RArg(iargs.d), RArg(iargs.n),
299 RArg(iargs.m), RArg(iargs.a));
300 break;
301 }
302 case InstrId::kMla: {
303 const auto &iargs = instr.mla;
304 MnemonicBuilderTernaryInstr<TMnemonicBuilderContext>::Build("MLA", mctx, bflags, iargs.flags,
305 RArg(iargs.d), RArg(iargs.n),
306 RArg(iargs.m), RArg(iargs.a));
307 break;
308 }
309 case InstrId::kMul: {
310 const auto &iargs = instr.mul;
311 bflags |= static_cast<MnemonicBuilderFlagsSet>(MnemonicBuilderFlags::kReduceRd);
312 MnemonicBuilderBinaryInstr<TMnemonicBuilderContext>::Build(
313 "MUL", mctx, bflags, iargs.flags, RArg(iargs.d), RArg(iargs.n), RArg(iargs.m));
314 break;
315 }
316 case InstrId::kAddRegister: {
317 const auto &iargs = instr.add_register;
318 bflags |= static_cast<MnemonicBuilderFlagsSet>(MnemonicBuilderFlags::kReduceRd);
319 MnemonicBuilderTernaryInstrWithShift<TMnemonicBuilderContext>::Build(
320 "ADD", mctx, bflags, iargs.flags, RArg(iargs.d), RArg(iargs.n), RArg(iargs.m),
321 iargs.shift_res);
322 break;
323 }
324 case InstrId::kAdcRegister: {
325 const auto &iargs = instr.adc_register;
326 bflags |= static_cast<MnemonicBuilderFlagsSet>(MnemonicBuilderFlags::kReduceRd);
327 MnemonicBuilderTernaryInstrWithShift<TMnemonicBuilderContext>::Build(
328 "ADC", mctx, bflags, iargs.flags, RArg(iargs.d), RArg(iargs.n), RArg(iargs.m),
329 iargs.shift_res);
330 break;
331 }
332 case InstrId::kMvnRegister: {
333 const auto &iargs = instr.mvn_register;
334 bflags |= static_cast<MnemonicBuilderFlagsSet>(MnemonicBuilderFlags::kReduceRd);
335 MnemonicBuilderBinaryInstrWithShift<TMnemonicBuilderContext>::Build(
336 "MVN", mctx, bflags, iargs.flags, RArg(iargs.d), RArg(iargs.m), iargs.shift_res);
337 break;
338 }
339 case InstrId::kLsrImmediate: {
340 const auto &iargs = instr.lsr_immediate;
341 bflags |= static_cast<MnemonicBuilderFlagsSet>(MnemonicBuilderFlags::kSupressShiftType);
342 MnemonicBuilderBinaryInstrWithShift<TMnemonicBuilderContext>::Build(
343 "LSR", mctx, bflags, iargs.flags, RArg(iargs.d), RArg(iargs.m), iargs.shift_res);
344 break;
345 }
346 case InstrId::kAsrImmediate: {
347 const auto &iargs = instr.asr_immediate;
348 bflags |= static_cast<MnemonicBuilderFlagsSet>(MnemonicBuilderFlags::kSupressShiftType);
349 MnemonicBuilderBinaryInstrWithShift<TMnemonicBuilderContext>::Build(
350 "ASR", mctx, bflags, iargs.flags, RArg(iargs.d), RArg(iargs.m), iargs.shift_res);
351 break;
352 }
353 case InstrId::kLslImmediate: {
354 const auto &iargs = instr.lsl_immediate;
355 bflags |= static_cast<MnemonicBuilderFlagsSet>(MnemonicBuilderFlags::kSupressShiftType);
356 MnemonicBuilderBinaryInstrWithShift<TMnemonicBuilderContext>::Build(
357 "LSL", mctx, bflags, iargs.flags, RArg(iargs.d), RArg(iargs.m), iargs.shift_res);
358 break;
359 }
360 case InstrId::kLsrRegister: {
361 const auto &iargs = instr.lsr_register;
362 bflags |= static_cast<MnemonicBuilderFlagsSet>(MnemonicBuilderFlags::kReduceRd);
363 MnemonicBuilderBinaryInstr<TMnemonicBuilderContext>::Build(
364 "LSR", mctx, bflags, iargs.flags, RArg(iargs.d), RArg(iargs.n), RArg(iargs.m));
365 break;
366 }
367 case InstrId::kAsrRegister: {
368 const auto &iargs = instr.asr_register;
369 bflags |= static_cast<MnemonicBuilderFlagsSet>(MnemonicBuilderFlags::kReduceRd);
370 MnemonicBuilderBinaryInstr<TMnemonicBuilderContext>::Build(
371 "ASR", mctx, bflags, iargs.flags, RArg(iargs.d), RArg(iargs.n), RArg(iargs.m));
372 break;
373 }
374 case InstrId::kLslRegister: {
375 const auto &iargs = instr.lsl_register;
376 bflags |= static_cast<MnemonicBuilderFlagsSet>(MnemonicBuilderFlags::kReduceRd);
377 MnemonicBuilderBinaryInstr<TMnemonicBuilderContext>::Build(
378 "LSL", mctx, bflags, iargs.flags, RArg(iargs.d), RArg(iargs.n), RArg(iargs.m));
379 break;
380 }
381 case InstrId::kStm: {
382 const auto &iargs = instr.stm;
383 MnemonicBuilderVariadicLoadStoreInstr<TMnemonicBuilderContext>::Build(
384 "STM", mctx, bflags, iargs.flags, RArg(iargs.n), iargs.registers, false);
385 break;
386 }
387 case InstrId::kPush: {
388 const auto &iargs = instr.push;
389 MnemonicBuilderVariadicLoadStoreInstr<TMnemonicBuilderContext>::Build(
390 "PUSH", mctx, bflags, iargs.flags, RArgConst<RegisterId::kSp>(), iargs.registers, true);
391 break;
392 }
393 case InstrId::kLdm: {
394 const auto &iargs = instr.ldm;
395 MnemonicBuilderVariadicLoadStoreInstr<TMnemonicBuilderContext>::Build(
396 "LDM", mctx, bflags, iargs.flags, RArg(iargs.n), iargs.registers, false);
397 break;
398 }
399 case InstrId::kPop: {
400 const auto &iargs = instr.pop;
401 MnemonicBuilderVariadicLoadStoreInstr<TMnemonicBuilderContext>::Build(
402 "POP", mctx, bflags, iargs.flags, RArgConst<RegisterId::kSp>(), iargs.registers, true);
403 break;
404 }
405 case InstrId::kSxtb: {
406 const auto &iargs = instr.sxtb;
407 MnemonicBuilderBinaryInstrWithRotation<TMnemonicBuilderContext>::Build(
408 "SXTB", mctx, bflags, iargs.flags, RArg(iargs.d), RArg(iargs.m), iargs.rotation);
409 break;
410 }
411 case InstrId::kUxtb: {
412 const auto &iargs = instr.uxtb;
413 MnemonicBuilderBinaryInstrWithRotation<TMnemonicBuilderContext>::Build(
414 "UXTB", mctx, bflags, iargs.flags, RArg(iargs.d), RArg(iargs.m), iargs.rotation);
415 break;
416 }
417 case InstrId::kSxth: {
418 const auto &iargs = instr.sxth;
419 MnemonicBuilderBinaryInstrWithRotation<TMnemonicBuilderContext>::Build(
420 "SXTH", mctx, bflags, iargs.flags, RArg(iargs.d), RArg(iargs.m), iargs.rotation);
421 break;
422 }
423 case InstrId::kUxth: {
424 const auto &iargs = instr.uxth;
425 MnemonicBuilderBinaryInstrWithRotation<TMnemonicBuilderContext>::Build(
426 "UXTH", mctx, bflags, iargs.flags, RArg(iargs.d), RArg(iargs.m), iargs.rotation);
427 break;
428 }
429 case InstrId::kUbfx: {
430 const auto &iargs = instr.ubfx;
431 MnemonicBuilderSpecialInstr<TMnemonicBuilderContext>::BuildUbfx(
432 "UBFX", mctx, bflags, iargs.flags, RArg(iargs.d), RArg(iargs.n), iargs.lsbit,
433 iargs.widthminus1);
434 break;
435 }
436 case InstrId::kBfi: {
437 const auto &iargs = instr.bfi;
438 MnemonicBuilderSpecialInstr<TMnemonicBuilderContext>::BuildBfi(
439 "BFI", mctx, bflags, iargs.flags, RArg(iargs.d), RArg(iargs.n), iargs.lsbit, iargs.msbit);
440 break;
441 }
442 case InstrId::kSbcRegister: {
443 const auto &iargs = instr.sbc_register;
444 bflags |= static_cast<MnemonicBuilderFlagsSet>(MnemonicBuilderFlags::kReduceRd);
445 MnemonicBuilderTernaryInstrWithShift<TMnemonicBuilderContext>::Build(
446 "SBC", mctx, bflags, iargs.flags, RArg(iargs.d), RArg(iargs.n), RArg(iargs.m),
447 iargs.shift_res);
448 break;
449 }
450 case InstrId::kEorRegister: {
451 const auto &iargs = instr.eor_register;
452 bflags |= static_cast<MnemonicBuilderFlagsSet>(MnemonicBuilderFlags::kReduceRd);
453 MnemonicBuilderTernaryInstrWithShift<TMnemonicBuilderContext>::Build(
454 "EOR", mctx, bflags, iargs.flags, RArg(iargs.d), RArg(iargs.n), RArg(iargs.m),
455 iargs.shift_res);
456 break;
457 }
458 case InstrId::kOrrRegister: {
459 const auto &iargs = instr.orr_register;
460 bflags |= static_cast<MnemonicBuilderFlagsSet>(MnemonicBuilderFlags::kReduceRd);
461 MnemonicBuilderTernaryInstrWithShift<TMnemonicBuilderContext>::Build(
462 "ORR", mctx, bflags, iargs.flags, RArg(iargs.d), RArg(iargs.n), RArg(iargs.m),
463 iargs.shift_res);
464 break;
465 }
466 case InstrId::kAndRegister: {
467 const auto &iargs = instr.and_register;
468 bflags |= static_cast<MnemonicBuilderFlagsSet>(MnemonicBuilderFlags::kReduceRd);
469 MnemonicBuilderTernaryInstrWithShift<TMnemonicBuilderContext>::Build(
470 "AND", mctx, bflags, iargs.flags, RArg(iargs.d), RArg(iargs.n), RArg(iargs.m),
471 iargs.shift_res);
472 break;
473 }
474 case InstrId::kBicRegister: {
475 const auto &iargs = instr.bic_register;
476 bflags |= static_cast<MnemonicBuilderFlagsSet>(MnemonicBuilderFlags::kReduceRd);
477 MnemonicBuilderTernaryInstrWithShift<TMnemonicBuilderContext>::Build(
478 "BIC", mctx, bflags, iargs.flags, RArg(iargs.d), RArg(iargs.n), RArg(iargs.m),
479 iargs.shift_res);
480 break;
481 }
482 case InstrId::kBicImmediate: {
483 const auto &iargs = instr.bic_immediate;
484 bflags |= static_cast<MnemonicBuilderFlagsSet>(MnemonicBuilderFlags::kReduceRd);
485 MnemonicBuilderBinaryInstrWithImmCarry<TMnemonicBuilderContext>::Build(
486 "BIC", mctx, bflags, iargs.flags, RArg(iargs.d), RArg(iargs.n), iargs.imm32_carry);
487 break;
488 }
489 case InstrId::kStrdImmediate: {
490 const auto &iargs = instr.strd_immediate;
491 MnemonicBuilderSpecialInstr<TMnemonicBuilderContext>::BuildLdrdStrd(
492 "STRD", mctx, bflags, iargs.flags, RArg(iargs.t), RArg(iargs.t2), RArg(iargs.n),
493 iargs.imm32);
494 break;
495 }
496 case InstrId::kCmpRegister: {
497 const auto &iargs = instr.cmp_register;
498 MnemonicBuilderTernaryNullInstrWithShift<TMnemonicBuilderContext>::Build(
499 "CMP", mctx, bflags, iargs.flags, RArg(iargs.n), RArg(iargs.m), iargs.shift_res, false);
500 break;
501 }
502 case InstrId::kTeqImmediate: {
503 const auto &iargs = instr.teq_immediate;
504 MnemonicBuilderBinaryNullInstrWithImmCarry<TMnemonicBuilderContext>::Build(
505 "TEQ", mctx, bflags, iargs.flags, RArg(iargs.n), iargs.imm32_carry);
506 break;
507 }
508 case InstrId::kTstImmediate: {
509 const auto &iargs = instr.tst_immediate;
510 MnemonicBuilderBinaryNullInstrWithImmCarry<TMnemonicBuilderContext>::Build(
511 "TST", mctx, bflags, iargs.flags, RArg(iargs.n), iargs.imm32_carry);
512 break;
513 }
514 case InstrId::kTstRegister: {
515 const auto &iargs = instr.tst_register;
516 MnemonicBuilderTernaryNullInstrWithShift<TMnemonicBuilderContext>::Build(
517 "TST", mctx, bflags, iargs.flags, RArg(iargs.n), RArg(iargs.m), iargs.shift_res, false);
518 break;
519 }
520 case InstrId::kTeqRegister: {
521 const auto &iargs = instr.teq_register;
522 MnemonicBuilderTernaryNullInstrWithShift<TMnemonicBuilderContext>::Build(
523 "TEQ", mctx, bflags, iargs.flags, RArg(iargs.n), RArg(iargs.m), iargs.shift_res, false);
524 break;
525 }
526 case InstrId::kEorImmediate: {
527 const auto &iargs = instr.eor_immediate;
528 bflags |= static_cast<MnemonicBuilderFlagsSet>(MnemonicBuilderFlags::kReduceRd);
529 MnemonicBuilderBinaryInstrWithImmCarry<TMnemonicBuilderContext>::Build(
530 "EOR", mctx, bflags, iargs.flags, RArg(iargs.d), RArg(iargs.n), iargs.imm32_carry);
531 break;
532 }
533 case InstrId::kOrrImmediate: {
534 const auto &iargs = instr.orr_immediate;
535 bflags |= static_cast<MnemonicBuilderFlagsSet>(MnemonicBuilderFlags::kReduceRd);
536 MnemonicBuilderBinaryInstrWithImmCarry<TMnemonicBuilderContext>::Build(
537 "ORR", mctx, bflags, iargs.flags, RArg(iargs.d), RArg(iargs.n), iargs.imm32_carry);
538 break;
539 }
540 case InstrId::kAndImmediate: {
541 const auto &iargs = instr.and_immediate;
542 bflags |= static_cast<MnemonicBuilderFlagsSet>(MnemonicBuilderFlags::kReduceRd);
543 MnemonicBuilderBinaryInstrWithImmCarry<TMnemonicBuilderContext>::Build(
544 "AND", mctx, bflags, iargs.flags, RArg(iargs.d), RArg(iargs.n), iargs.imm32_carry);
545 break;
546 }
547 case InstrId::kStrhImmediate: {
548 const auto &iargs = instr.strh_immediate;
549 MnemonicBuilderBinaryLoadStoreInstrWithImm<TMnemonicBuilderContext>::Build(
550 "STRH", mctx, bflags, iargs.flags, RArg(iargs.t), RArg(iargs.n), iargs.imm32);
551 break;
552 }
553 case InstrId::kTbbH: {
554 const auto &iargs = instr.tbb_h;
555 const auto &iflags = iargs.flags;
556 const bool is_tbh = (iflags & static_cast<InstrFlagsSet>(InstrFlags::kTbh)) != 0U;
557 if (is_tbh == true) {
558 MnemonicBuilderBinaryNullInstr<TMnemonicBuilderContext>::Build(
559 "TBH", mctx, bflags, iargs.flags, RArg(iargs.m), RArg(iargs.n), "");
560 } else {
561 MnemonicBuilderBinaryNullInstr<TMnemonicBuilderContext>::Build(
562 "TBB", mctx, bflags, iargs.flags, RArg(iargs.m), RArg(iargs.n), ", LSL #1");
563 }
564 break;
565 }
566 case InstrId::kStrbImmediate: {
567 const auto &iargs = instr.strb_immediate;
568 MnemonicBuilderBinaryLoadStoreInstrWithImm<TMnemonicBuilderContext>::Build(
569 "STRB", mctx, bflags, iargs.flags, RArg(iargs.t), RArg(iargs.n), iargs.imm32);
570 break;
571 }
572 case InstrId::kStrImmediate: {
573 const auto &iargs = instr.str_immediate;
574 MnemonicBuilderBinaryLoadStoreInstrWithImm<TMnemonicBuilderContext>::Build(
575 "STR", mctx, bflags, iargs.flags, RArg(iargs.t), RArg(iargs.n), iargs.imm32);
576 break;
577 }
578 case InstrId::kStrex: {
579 const auto &iargs = instr.strex;
580 MnemonicBuilderTernaryLoadStoreInstrWithImm<TMnemonicBuilderContext>::Build(
581 "STREX", mctx, bflags, iargs.flags, RArg(iargs.d), RArg(iargs.t), RArg(iargs.n),
582 iargs.imm32);
583 break;
584 }
585 case InstrId::kLdrhRegister: {
586 const auto &iargs = instr.ldrh_register;
587 MnemonicBuilderTernaryLoadStoreInstrWithShift<TMnemonicBuilderContext>::Build(
588 "LDRH", mctx, bflags, iargs.flags, RArg(iargs.t), RArg(iargs.n), RArg(iargs.m),
589 iargs.shift_res);
590 break;
591 }
592 case InstrId::kLdrbRegister: {
593 const auto &iargs = instr.ldrb_register;
594 MnemonicBuilderTernaryLoadStoreInstrWithShift<TMnemonicBuilderContext>::Build(
595 "LDRB", mctx, bflags, iargs.flags, RArg(iargs.t), RArg(iargs.n), RArg(iargs.m),
596 iargs.shift_res);
597 break;
598 }
599 case InstrId::kLdrRegister: {
600 const auto &iargs = instr.ldr_register;
601 MnemonicBuilderTernaryLoadStoreInstrWithShift<TMnemonicBuilderContext>::Build(
602 "LDR", mctx, bflags, iargs.flags, RArg(iargs.t), RArg(iargs.n), RArg(iargs.m),
603 iargs.shift_res);
604 break;
605 }
606 case InstrId::kStrRegister: {
607 const auto &iargs = instr.str_register;
608 MnemonicBuilderTernaryLoadStoreInstrWithShift<TMnemonicBuilderContext>::Build(
609 "STR", mctx, bflags, iargs.flags, RArg(iargs.t), RArg(iargs.n), RArg(iargs.m),
610 iargs.shift_res);
611 break;
612 }
613 case InstrId::kStrbRegister: {
614 const auto &iargs = instr.strb_register;
615 MnemonicBuilderTernaryLoadStoreInstrWithShift<TMnemonicBuilderContext>::Build(
616 "STRB", mctx, bflags, iargs.flags, RArg(iargs.t), RArg(iargs.n), RArg(iargs.m),
617 iargs.shift_res);
618 break;
619 }
620 case InstrId::kStrhRegister: {
621 const auto &iargs = instr.strh_register;
622 MnemonicBuilderTernaryLoadStoreInstrWithShift<TMnemonicBuilderContext>::Build(
623 "STRH", mctx, bflags, iargs.flags, RArg(iargs.t), RArg(iargs.n), RArg(iargs.m),
624 iargs.shift_res);
625 break;
626 }
627 case InstrId::kCbNZ: {
628 const auto &iargs = instr.cb_n_z;
629 const auto &iflags = iargs.flags;
630 const bool is_non_zero = (iflags & static_cast<InstrFlagsSet>(InstrFlags::kNonZero)) != 0U;
631
632 if (is_non_zero == true) {
633 MnemonicBuilderBinaryNullInstrWithImm<TMnemonicBuilderContext>::Build(
634 "CBNZ", mctx, bflags, iargs.flags, RArg(iargs.n), iargs.imm32);
635 } else {
636
637 MnemonicBuilderBinaryNullInstrWithImm<TMnemonicBuilderContext>::Build(
638 "CBZ", mctx, bflags, iargs.flags, RArg(iargs.n), iargs.imm32);
639 break;
640 }
641
642 break;
643 }
644 case InstrId::kSvc: {
645 const auto &iargs = instr.svc;
646 MnemonicBuilderUnaryNullInstrWithImm<TMnemonicBuilderContext>::Build(
647 "SVC", mctx, bflags, iargs.flags, iargs.imm32);
648 break;
649 }
650 case InstrId::kBkpt: {
651 const auto &iargs = instr.bkpt;
652 MnemonicBuilderUnaryNullInstrWithImm<TMnemonicBuilderContext>::Build(
653 "BKPT", mctx, bflags, iargs.flags, iargs.imm32);
654 break;
655 }
656 case InstrId::kNop: {
657 const auto &iargs = instr.nop;
658 MnemonicBuilderNullaryInstr<TMnemonicBuilderContext>::Build("NOP", mctx, bflags, iargs.flags);
659 break;
660 }
661 case InstrId::kDmb: {
662 const auto &iargs = instr.dmb;
663 MnemonicBuilderNullaryInstr<TMnemonicBuilderContext>::Build("DMB", mctx, bflags, iargs.flags);
664 break;
665 }
666 default:
667 ConstStringBuilder(buf, sizeof(buf)).AddString("invalid op").Terminate();
668 break;
669 };
670 }
671
672private:
676 MnemonicBuilder() = delete;
677
681 ~MnemonicBuilder() = delete;
682
687 MnemonicBuilder(MnemonicBuilder &r_src) = delete;
688
693 MnemonicBuilder &operator=(const MnemonicBuilder &r_src) = delete;
694
699 MnemonicBuilder(MnemonicBuilder &&r_src) = delete;
700
705 MnemonicBuilder &operator=(MnemonicBuilder &&r_src) = delete;
706};
707
708} // namespace libmicroemu::internal
Register argument constant class.
Definition rarg.h:12
Register argument class.
Definition rarg.h:75
A class to build a const string in a buffer.
Definition const_string_builder.h:14
ConstStringBuilder & AddString(const std::string_view &str)
Add a string to the buffer.
Definition const_string_builder.h:23
The libmicroemu::internal namespace contains all classes and functions of libmicroemu which are priva...
Definition bkpt_flags.h:6
Definition mnemonic_builder_context.h:8
Definition instr.h:734