1//===-- EmulateInstructionARM.cpp -----------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include <cstdlib>
10#include <optional>
11
12#include "EmulateInstructionARM.h"
13#include "EmulationStateARM.h"
14#include "lldb/Core/Address.h"
15#include "lldb/Core/PluginManager.h"
16#include "lldb/Host/PosixApi.h"
17#include "lldb/Interpreter/OptionValueArray.h"
18#include "lldb/Interpreter/OptionValueDictionary.h"
19#include "lldb/Symbol/UnwindPlan.h"
20#include "lldb/Utility/ArchSpec.h"
21#include "lldb/Utility/Stream.h"
22
23#include "Plugins/Process/Utility/ARMDefines.h"
24#include "Plugins/Process/Utility/ARMUtils.h"
25#include "Utility/ARM_DWARF_Registers.h"
26
27#include "llvm/ADT/STLExtras.h"
28#include "llvm/Support/MathExtras.h"
29
30using namespace lldb;
31using namespace lldb_private;
32
33LLDB_PLUGIN_DEFINE_ADV(EmulateInstructionARM, InstructionARM)
34
35// Convenient macro definitions.
36#define APSR_C Bit32(m_opcode_cpsr, CPSR_C_POS)
37#define APSR_V Bit32(m_opcode_cpsr, CPSR_V_POS)
38
39#define AlignPC(pc_val) (pc_val & 0xFFFFFFFC)
40
41//
42// ITSession implementation
43//
44
45static std::optional<RegisterInfo> GetARMDWARFRegisterInfo(unsigned reg_num) {
46 RegisterInfo reg_info;
47 ::memset(s: &reg_info, c: 0, n: sizeof(RegisterInfo));
48 ::memset(s: reg_info.kinds, LLDB_INVALID_REGNUM, n: sizeof(reg_info.kinds));
49
50 if (reg_num >= dwarf_q0 && reg_num <= dwarf_q15) {
51 reg_info.byte_size = 16;
52 reg_info.format = eFormatVectorOfUInt8;
53 reg_info.encoding = eEncodingVector;
54 }
55
56 if (reg_num >= dwarf_d0 && reg_num <= dwarf_d31) {
57 reg_info.byte_size = 8;
58 reg_info.format = eFormatFloat;
59 reg_info.encoding = eEncodingIEEE754;
60 } else if (reg_num >= dwarf_s0 && reg_num <= dwarf_s31) {
61 reg_info.byte_size = 4;
62 reg_info.format = eFormatFloat;
63 reg_info.encoding = eEncodingIEEE754;
64 } else if (reg_num >= dwarf_f0 && reg_num <= dwarf_f7) {
65 reg_info.byte_size = 12;
66 reg_info.format = eFormatFloat;
67 reg_info.encoding = eEncodingIEEE754;
68 } else {
69 reg_info.byte_size = 4;
70 reg_info.format = eFormatHex;
71 reg_info.encoding = eEncodingUint;
72 }
73
74 reg_info.kinds[eRegisterKindDWARF] = reg_num;
75
76 switch (reg_num) {
77 case dwarf_r0:
78 reg_info.name = "r0";
79 break;
80 case dwarf_r1:
81 reg_info.name = "r1";
82 break;
83 case dwarf_r2:
84 reg_info.name = "r2";
85 break;
86 case dwarf_r3:
87 reg_info.name = "r3";
88 break;
89 case dwarf_r4:
90 reg_info.name = "r4";
91 break;
92 case dwarf_r5:
93 reg_info.name = "r5";
94 break;
95 case dwarf_r6:
96 reg_info.name = "r6";
97 break;
98 case dwarf_r7:
99 reg_info.name = "r7";
100 reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP;
101 break;
102 case dwarf_r8:
103 reg_info.name = "r8";
104 break;
105 case dwarf_r9:
106 reg_info.name = "r9";
107 break;
108 case dwarf_r10:
109 reg_info.name = "r10";
110 break;
111 case dwarf_r11:
112 reg_info.name = "r11";
113 break;
114 case dwarf_r12:
115 reg_info.name = "r12";
116 break;
117 case dwarf_sp:
118 reg_info.name = "sp";
119 reg_info.alt_name = "r13";
120 reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_SP;
121 break;
122 case dwarf_lr:
123 reg_info.name = "lr";
124 reg_info.alt_name = "r14";
125 reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_RA;
126 break;
127 case dwarf_pc:
128 reg_info.name = "pc";
129 reg_info.alt_name = "r15";
130 reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC;
131 break;
132 case dwarf_cpsr:
133 reg_info.name = "cpsr";
134 reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FLAGS;
135 break;
136
137 case dwarf_s0:
138 reg_info.name = "s0";
139 break;
140 case dwarf_s1:
141 reg_info.name = "s1";
142 break;
143 case dwarf_s2:
144 reg_info.name = "s2";
145 break;
146 case dwarf_s3:
147 reg_info.name = "s3";
148 break;
149 case dwarf_s4:
150 reg_info.name = "s4";
151 break;
152 case dwarf_s5:
153 reg_info.name = "s5";
154 break;
155 case dwarf_s6:
156 reg_info.name = "s6";
157 break;
158 case dwarf_s7:
159 reg_info.name = "s7";
160 break;
161 case dwarf_s8:
162 reg_info.name = "s8";
163 break;
164 case dwarf_s9:
165 reg_info.name = "s9";
166 break;
167 case dwarf_s10:
168 reg_info.name = "s10";
169 break;
170 case dwarf_s11:
171 reg_info.name = "s11";
172 break;
173 case dwarf_s12:
174 reg_info.name = "s12";
175 break;
176 case dwarf_s13:
177 reg_info.name = "s13";
178 break;
179 case dwarf_s14:
180 reg_info.name = "s14";
181 break;
182 case dwarf_s15:
183 reg_info.name = "s15";
184 break;
185 case dwarf_s16:
186 reg_info.name = "s16";
187 break;
188 case dwarf_s17:
189 reg_info.name = "s17";
190 break;
191 case dwarf_s18:
192 reg_info.name = "s18";
193 break;
194 case dwarf_s19:
195 reg_info.name = "s19";
196 break;
197 case dwarf_s20:
198 reg_info.name = "s20";
199 break;
200 case dwarf_s21:
201 reg_info.name = "s21";
202 break;
203 case dwarf_s22:
204 reg_info.name = "s22";
205 break;
206 case dwarf_s23:
207 reg_info.name = "s23";
208 break;
209 case dwarf_s24:
210 reg_info.name = "s24";
211 break;
212 case dwarf_s25:
213 reg_info.name = "s25";
214 break;
215 case dwarf_s26:
216 reg_info.name = "s26";
217 break;
218 case dwarf_s27:
219 reg_info.name = "s27";
220 break;
221 case dwarf_s28:
222 reg_info.name = "s28";
223 break;
224 case dwarf_s29:
225 reg_info.name = "s29";
226 break;
227 case dwarf_s30:
228 reg_info.name = "s30";
229 break;
230 case dwarf_s31:
231 reg_info.name = "s31";
232 break;
233
234 // FPA Registers 0-7
235 case dwarf_f0:
236 reg_info.name = "f0";
237 break;
238 case dwarf_f1:
239 reg_info.name = "f1";
240 break;
241 case dwarf_f2:
242 reg_info.name = "f2";
243 break;
244 case dwarf_f3:
245 reg_info.name = "f3";
246 break;
247 case dwarf_f4:
248 reg_info.name = "f4";
249 break;
250 case dwarf_f5:
251 reg_info.name = "f5";
252 break;
253 case dwarf_f6:
254 reg_info.name = "f6";
255 break;
256 case dwarf_f7:
257 reg_info.name = "f7";
258 break;
259
260 // Intel wireless MMX general purpose registers 0 - 7 XScale accumulator
261 // register 0 - 7 (they do overlap with wCGR0 - wCGR7)
262 case dwarf_wCGR0:
263 reg_info.name = "wCGR0/ACC0";
264 break;
265 case dwarf_wCGR1:
266 reg_info.name = "wCGR1/ACC1";
267 break;
268 case dwarf_wCGR2:
269 reg_info.name = "wCGR2/ACC2";
270 break;
271 case dwarf_wCGR3:
272 reg_info.name = "wCGR3/ACC3";
273 break;
274 case dwarf_wCGR4:
275 reg_info.name = "wCGR4/ACC4";
276 break;
277 case dwarf_wCGR5:
278 reg_info.name = "wCGR5/ACC5";
279 break;
280 case dwarf_wCGR6:
281 reg_info.name = "wCGR6/ACC6";
282 break;
283 case dwarf_wCGR7:
284 reg_info.name = "wCGR7/ACC7";
285 break;
286
287 // Intel wireless MMX data registers 0 - 15
288 case dwarf_wR0:
289 reg_info.name = "wR0";
290 break;
291 case dwarf_wR1:
292 reg_info.name = "wR1";
293 break;
294 case dwarf_wR2:
295 reg_info.name = "wR2";
296 break;
297 case dwarf_wR3:
298 reg_info.name = "wR3";
299 break;
300 case dwarf_wR4:
301 reg_info.name = "wR4";
302 break;
303 case dwarf_wR5:
304 reg_info.name = "wR5";
305 break;
306 case dwarf_wR6:
307 reg_info.name = "wR6";
308 break;
309 case dwarf_wR7:
310 reg_info.name = "wR7";
311 break;
312 case dwarf_wR8:
313 reg_info.name = "wR8";
314 break;
315 case dwarf_wR9:
316 reg_info.name = "wR9";
317 break;
318 case dwarf_wR10:
319 reg_info.name = "wR10";
320 break;
321 case dwarf_wR11:
322 reg_info.name = "wR11";
323 break;
324 case dwarf_wR12:
325 reg_info.name = "wR12";
326 break;
327 case dwarf_wR13:
328 reg_info.name = "wR13";
329 break;
330 case dwarf_wR14:
331 reg_info.name = "wR14";
332 break;
333 case dwarf_wR15:
334 reg_info.name = "wR15";
335 break;
336
337 case dwarf_spsr:
338 reg_info.name = "spsr";
339 break;
340 case dwarf_spsr_fiq:
341 reg_info.name = "spsr_fiq";
342 break;
343 case dwarf_spsr_irq:
344 reg_info.name = "spsr_irq";
345 break;
346 case dwarf_spsr_abt:
347 reg_info.name = "spsr_abt";
348 break;
349 case dwarf_spsr_und:
350 reg_info.name = "spsr_und";
351 break;
352 case dwarf_spsr_svc:
353 reg_info.name = "spsr_svc";
354 break;
355
356 case dwarf_r8_usr:
357 reg_info.name = "r8_usr";
358 break;
359 case dwarf_r9_usr:
360 reg_info.name = "r9_usr";
361 break;
362 case dwarf_r10_usr:
363 reg_info.name = "r10_usr";
364 break;
365 case dwarf_r11_usr:
366 reg_info.name = "r11_usr";
367 break;
368 case dwarf_r12_usr:
369 reg_info.name = "r12_usr";
370 break;
371 case dwarf_r13_usr:
372 reg_info.name = "r13_usr";
373 break;
374 case dwarf_r14_usr:
375 reg_info.name = "r14_usr";
376 break;
377 case dwarf_r8_fiq:
378 reg_info.name = "r8_fiq";
379 break;
380 case dwarf_r9_fiq:
381 reg_info.name = "r9_fiq";
382 break;
383 case dwarf_r10_fiq:
384 reg_info.name = "r10_fiq";
385 break;
386 case dwarf_r11_fiq:
387 reg_info.name = "r11_fiq";
388 break;
389 case dwarf_r12_fiq:
390 reg_info.name = "r12_fiq";
391 break;
392 case dwarf_r13_fiq:
393 reg_info.name = "r13_fiq";
394 break;
395 case dwarf_r14_fiq:
396 reg_info.name = "r14_fiq";
397 break;
398 case dwarf_r13_irq:
399 reg_info.name = "r13_irq";
400 break;
401 case dwarf_r14_irq:
402 reg_info.name = "r14_irq";
403 break;
404 case dwarf_r13_abt:
405 reg_info.name = "r13_abt";
406 break;
407 case dwarf_r14_abt:
408 reg_info.name = "r14_abt";
409 break;
410 case dwarf_r13_und:
411 reg_info.name = "r13_und";
412 break;
413 case dwarf_r14_und:
414 reg_info.name = "r14_und";
415 break;
416 case dwarf_r13_svc:
417 reg_info.name = "r13_svc";
418 break;
419 case dwarf_r14_svc:
420 reg_info.name = "r14_svc";
421 break;
422
423 // Intel wireless MMX control register in co-processor 0 - 7
424 case dwarf_wC0:
425 reg_info.name = "wC0";
426 break;
427 case dwarf_wC1:
428 reg_info.name = "wC1";
429 break;
430 case dwarf_wC2:
431 reg_info.name = "wC2";
432 break;
433 case dwarf_wC3:
434 reg_info.name = "wC3";
435 break;
436 case dwarf_wC4:
437 reg_info.name = "wC4";
438 break;
439 case dwarf_wC5:
440 reg_info.name = "wC5";
441 break;
442 case dwarf_wC6:
443 reg_info.name = "wC6";
444 break;
445 case dwarf_wC7:
446 reg_info.name = "wC7";
447 break;
448
449 // VFP-v3/Neon
450 case dwarf_d0:
451 reg_info.name = "d0";
452 break;
453 case dwarf_d1:
454 reg_info.name = "d1";
455 break;
456 case dwarf_d2:
457 reg_info.name = "d2";
458 break;
459 case dwarf_d3:
460 reg_info.name = "d3";
461 break;
462 case dwarf_d4:
463 reg_info.name = "d4";
464 break;
465 case dwarf_d5:
466 reg_info.name = "d5";
467 break;
468 case dwarf_d6:
469 reg_info.name = "d6";
470 break;
471 case dwarf_d7:
472 reg_info.name = "d7";
473 break;
474 case dwarf_d8:
475 reg_info.name = "d8";
476 break;
477 case dwarf_d9:
478 reg_info.name = "d9";
479 break;
480 case dwarf_d10:
481 reg_info.name = "d10";
482 break;
483 case dwarf_d11:
484 reg_info.name = "d11";
485 break;
486 case dwarf_d12:
487 reg_info.name = "d12";
488 break;
489 case dwarf_d13:
490 reg_info.name = "d13";
491 break;
492 case dwarf_d14:
493 reg_info.name = "d14";
494 break;
495 case dwarf_d15:
496 reg_info.name = "d15";
497 break;
498 case dwarf_d16:
499 reg_info.name = "d16";
500 break;
501 case dwarf_d17:
502 reg_info.name = "d17";
503 break;
504 case dwarf_d18:
505 reg_info.name = "d18";
506 break;
507 case dwarf_d19:
508 reg_info.name = "d19";
509 break;
510 case dwarf_d20:
511 reg_info.name = "d20";
512 break;
513 case dwarf_d21:
514 reg_info.name = "d21";
515 break;
516 case dwarf_d22:
517 reg_info.name = "d22";
518 break;
519 case dwarf_d23:
520 reg_info.name = "d23";
521 break;
522 case dwarf_d24:
523 reg_info.name = "d24";
524 break;
525 case dwarf_d25:
526 reg_info.name = "d25";
527 break;
528 case dwarf_d26:
529 reg_info.name = "d26";
530 break;
531 case dwarf_d27:
532 reg_info.name = "d27";
533 break;
534 case dwarf_d28:
535 reg_info.name = "d28";
536 break;
537 case dwarf_d29:
538 reg_info.name = "d29";
539 break;
540 case dwarf_d30:
541 reg_info.name = "d30";
542 break;
543 case dwarf_d31:
544 reg_info.name = "d31";
545 break;
546
547 // NEON 128-bit vector registers (overlays the d registers)
548 case dwarf_q0:
549 reg_info.name = "q0";
550 break;
551 case dwarf_q1:
552 reg_info.name = "q1";
553 break;
554 case dwarf_q2:
555 reg_info.name = "q2";
556 break;
557 case dwarf_q3:
558 reg_info.name = "q3";
559 break;
560 case dwarf_q4:
561 reg_info.name = "q4";
562 break;
563 case dwarf_q5:
564 reg_info.name = "q5";
565 break;
566 case dwarf_q6:
567 reg_info.name = "q6";
568 break;
569 case dwarf_q7:
570 reg_info.name = "q7";
571 break;
572 case dwarf_q8:
573 reg_info.name = "q8";
574 break;
575 case dwarf_q9:
576 reg_info.name = "q9";
577 break;
578 case dwarf_q10:
579 reg_info.name = "q10";
580 break;
581 case dwarf_q11:
582 reg_info.name = "q11";
583 break;
584 case dwarf_q12:
585 reg_info.name = "q12";
586 break;
587 case dwarf_q13:
588 reg_info.name = "q13";
589 break;
590 case dwarf_q14:
591 reg_info.name = "q14";
592 break;
593 case dwarf_q15:
594 reg_info.name = "q15";
595 break;
596
597 default:
598 return {};
599 }
600 return reg_info;
601}
602
603// A8.6.50
604// Valid return values are {1, 2, 3, 4}, with 0 signifying an error condition.
605static uint32_t CountITSize(uint32_t ITMask) {
606 // First count the trailing zeros of the IT mask.
607 uint32_t TZ = llvm::countr_zero(Val: ITMask);
608 if (TZ > 3) {
609 return 0;
610 }
611 return (4 - TZ);
612}
613
614// Init ITState. Note that at least one bit is always 1 in mask.
615bool ITSession::InitIT(uint32_t bits7_0) {
616 ITCounter = CountITSize(ITMask: Bits32(bits: bits7_0, msbit: 3, lsbit: 0));
617 if (ITCounter == 0)
618 return false;
619
620 // A8.6.50 IT
621 unsigned short FirstCond = Bits32(bits: bits7_0, msbit: 7, lsbit: 4);
622 if (FirstCond == 0xF) {
623 return false;
624 }
625 if (FirstCond == 0xE && ITCounter != 1) {
626 return false;
627 }
628
629 ITState = bits7_0;
630 return true;
631}
632
633// Update ITState if necessary.
634void ITSession::ITAdvance() {
635 // assert(ITCounter);
636 --ITCounter;
637 if (ITCounter == 0)
638 ITState = 0;
639 else {
640 unsigned short NewITState4_0 = Bits32(bits: ITState, msbit: 4, lsbit: 0) << 1;
641 SetBits32(bits&: ITState, msbit: 4, lsbit: 0, val: NewITState4_0);
642 }
643}
644
645// Return true if we're inside an IT Block.
646bool ITSession::InITBlock() { return ITCounter != 0; }
647
648// Return true if we're the last instruction inside an IT Block.
649bool ITSession::LastInITBlock() { return ITCounter == 1; }
650
651// Get condition bits for the current thumb instruction.
652uint32_t ITSession::GetCond() {
653 if (InITBlock())
654 return Bits32(bits: ITState, msbit: 7, lsbit: 4);
655 else
656 return COND_AL;
657}
658
659// ARM constants used during decoding
660#define REG_RD 0
661#define LDM_REGLIST 1
662#define SP_REG 13
663#define LR_REG 14
664#define PC_REG 15
665#define PC_REGLIST_BIT 0x8000
666
667#define ARMv4 (1u << 0)
668#define ARMv4T (1u << 1)
669#define ARMv5T (1u << 2)
670#define ARMv5TE (1u << 3)
671#define ARMv5TEJ (1u << 4)
672#define ARMv6 (1u << 5)
673#define ARMv6K (1u << 6)
674#define ARMv6T2 (1u << 7)
675#define ARMv7 (1u << 8)
676#define ARMv7S (1u << 9)
677#define ARMv8 (1u << 10)
678#define ARMvAll (0xffffffffu)
679
680#define ARMV4T_ABOVE \
681 (ARMv4T | ARMv5T | ARMv5TE | ARMv5TEJ | ARMv6 | ARMv6K | ARMv6T2 | ARMv7 | \
682 ARMv7S | ARMv8)
683#define ARMV5_ABOVE \
684 (ARMv5T | ARMv5TE | ARMv5TEJ | ARMv6 | ARMv6K | ARMv6T2 | ARMv7 | ARMv7S | \
685 ARMv8)
686#define ARMV5TE_ABOVE \
687 (ARMv5TE | ARMv5TEJ | ARMv6 | ARMv6K | ARMv6T2 | ARMv7 | ARMv7S | ARMv8)
688#define ARMV5J_ABOVE \
689 (ARMv5TEJ | ARMv6 | ARMv6K | ARMv6T2 | ARMv7 | ARMv7S | ARMv8)
690#define ARMV6_ABOVE (ARMv6 | ARMv6K | ARMv6T2 | ARMv7 | ARMv7S | ARMv8)
691#define ARMV6T2_ABOVE (ARMv6T2 | ARMv7 | ARMv7S | ARMv8)
692#define ARMV7_ABOVE (ARMv7 | ARMv7S | ARMv8)
693
694#define No_VFP 0
695#define VFPv1 (1u << 1)
696#define VFPv2 (1u << 2)
697#define VFPv3 (1u << 3)
698#define AdvancedSIMD (1u << 4)
699
700#define VFPv1_ABOVE (VFPv1 | VFPv2 | VFPv3 | AdvancedSIMD)
701#define VFPv2_ABOVE (VFPv2 | VFPv3 | AdvancedSIMD)
702#define VFPv2v3 (VFPv2 | VFPv3)
703
704//
705// EmulateInstructionARM implementation
706//
707
708void EmulateInstructionARM::Initialize() {
709 PluginManager::RegisterPlugin(name: GetPluginNameStatic(),
710 description: GetPluginDescriptionStatic(), create_callback: CreateInstance);
711}
712
713void EmulateInstructionARM::Terminate() {
714 PluginManager::UnregisterPlugin(create_callback: CreateInstance);
715}
716
717llvm::StringRef EmulateInstructionARM::GetPluginDescriptionStatic() {
718 return "Emulate instructions for the ARM architecture.";
719}
720
721EmulateInstruction *
722EmulateInstructionARM::CreateInstance(const ArchSpec &arch,
723 InstructionType inst_type) {
724 if (EmulateInstructionARM::SupportsEmulatingInstructionsOfTypeStatic(
725 inst_type)) {
726 if (arch.GetTriple().getArch() == llvm::Triple::arm) {
727 std::unique_ptr<EmulateInstructionARM> emulate_insn_up(
728 new EmulateInstructionARM(arch));
729
730 if (emulate_insn_up)
731 return emulate_insn_up.release();
732 } else if (arch.GetTriple().getArch() == llvm::Triple::thumb) {
733 std::unique_ptr<EmulateInstructionARM> emulate_insn_up(
734 new EmulateInstructionARM(arch));
735
736 if (emulate_insn_up)
737 return emulate_insn_up.release();
738 }
739 }
740
741 return nullptr;
742}
743
744bool EmulateInstructionARM::SetTargetTriple(const ArchSpec &arch) {
745 if (arch.GetTriple().getArch() == llvm::Triple::arm)
746 return true;
747 else if (arch.GetTriple().getArch() == llvm::Triple::thumb)
748 return true;
749
750 return false;
751}
752
753// Write "bits (32) UNKNOWN" to memory address "address". Helper function for
754// many ARM instructions.
755bool EmulateInstructionARM::WriteBits32UnknownToMemory(addr_t address) {
756 EmulateInstruction::Context context;
757 context.type = EmulateInstruction::eContextWriteMemoryRandomBits;
758 context.SetNoArgs();
759
760 uint32_t random_data = rand();
761 const uint32_t addr_byte_size = GetAddressByteSize();
762
763 return MemAWrite(context, address, data_val: random_data, size: addr_byte_size);
764}
765
766// Write "bits (32) UNKNOWN" to register n. Helper function for many ARM
767// instructions.
768bool EmulateInstructionARM::WriteBits32Unknown(int n) {
769 EmulateInstruction::Context context;
770 context.type = EmulateInstruction::eContextWriteRegisterRandomBits;
771 context.SetNoArgs();
772
773 bool success;
774 uint32_t data =
775 ReadRegisterUnsigned(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n, fail_value: 0, success_ptr: &success);
776
777 if (!success)
778 return false;
779
780 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n, reg_value: data))
781 return false;
782
783 return true;
784}
785
786std::optional<RegisterInfo>
787EmulateInstructionARM::GetRegisterInfo(lldb::RegisterKind reg_kind,
788 uint32_t reg_num) {
789 if (reg_kind == eRegisterKindGeneric) {
790 switch (reg_num) {
791 case LLDB_REGNUM_GENERIC_PC:
792 reg_kind = eRegisterKindDWARF;
793 reg_num = dwarf_pc;
794 break;
795 case LLDB_REGNUM_GENERIC_SP:
796 reg_kind = eRegisterKindDWARF;
797 reg_num = dwarf_sp;
798 break;
799 case LLDB_REGNUM_GENERIC_FP:
800 reg_kind = eRegisterKindDWARF;
801 reg_num = dwarf_r7;
802 break;
803 case LLDB_REGNUM_GENERIC_RA:
804 reg_kind = eRegisterKindDWARF;
805 reg_num = dwarf_lr;
806 break;
807 case LLDB_REGNUM_GENERIC_FLAGS:
808 reg_kind = eRegisterKindDWARF;
809 reg_num = dwarf_cpsr;
810 break;
811 default:
812 return {};
813 }
814 }
815
816 if (reg_kind == eRegisterKindDWARF)
817 return GetARMDWARFRegisterInfo(reg_num);
818 return {};
819}
820
821uint32_t EmulateInstructionARM::GetFramePointerRegisterNumber() const {
822 if (m_arch.GetTriple().isAndroid())
823 return LLDB_INVALID_REGNUM; // Don't use frame pointer on android
824 bool is_apple = false;
825 if (m_arch.GetTriple().getVendor() == llvm::Triple::Apple)
826 is_apple = true;
827 switch (m_arch.GetTriple().getOS()) {
828 case llvm::Triple::Darwin:
829 case llvm::Triple::MacOSX:
830 case llvm::Triple::IOS:
831 case llvm::Triple::TvOS:
832 case llvm::Triple::WatchOS:
833 case llvm::Triple::XROS:
834 case llvm::Triple::BridgeOS:
835 is_apple = true;
836 break;
837 default:
838 break;
839 }
840
841 /* On Apple iOS et al, the frame pointer register is always r7.
842 * Typically on other ARM systems, thumb code uses r7; arm code uses r11.
843 * Windows on ARM, which is in thumb mode, uses r11 though.
844 */
845
846 uint32_t fp_regnum = 11;
847
848 if (is_apple)
849 fp_regnum = 7;
850
851 if (m_opcode_mode == eModeThumb && !m_arch.GetTriple().isOSWindows())
852 fp_regnum = 7;
853
854 return fp_regnum;
855}
856
857uint32_t EmulateInstructionARM::GetFramePointerDWARFRegisterNumber() const {
858 bool is_apple = false;
859 if (m_arch.GetTriple().getVendor() == llvm::Triple::Apple)
860 is_apple = true;
861 switch (m_arch.GetTriple().getOS()) {
862 case llvm::Triple::Darwin:
863 case llvm::Triple::MacOSX:
864 case llvm::Triple::IOS:
865 is_apple = true;
866 break;
867 default:
868 break;
869 }
870
871 /* On Apple iOS et al, the frame pointer register is always r7.
872 * Typically on other ARM systems, thumb code uses r7; arm code uses r11.
873 * Windows on ARM, which is in thumb mode, uses r11 though.
874 */
875
876 uint32_t fp_regnum = dwarf_r11;
877
878 if (is_apple)
879 fp_regnum = dwarf_r7;
880
881 if (m_opcode_mode == eModeThumb && !m_arch.GetTriple().isOSWindows())
882 fp_regnum = dwarf_r7;
883
884 return fp_regnum;
885}
886
887// Push Multiple Registers stores multiple registers to the stack, storing to
888// consecutive memory locations ending just below the address in SP, and
889// updates
890// SP to point to the start of the stored data.
891bool EmulateInstructionARM::EmulatePUSH(const uint32_t opcode,
892 const ARMEncoding encoding) {
893#if 0
894 // ARM pseudo code...
895 if (ConditionPassed())
896 {
897 EncodingSpecificOperations();
898 NullCheckIfThumbEE(13);
899 address = SP - 4*BitCount(registers);
900
901 for (i = 0 to 14)
902 {
903 if (registers<i> == '1')
904 {
905 if i == 13 && i != LowestSetBit(registers) // Only possible for encoding A1
906 MemA[address,4] = bits(32) UNKNOWN;
907 else
908 MemA[address,4] = R[i];
909 address = address + 4;
910 }
911 }
912
913 if (registers<15> == '1') // Only possible for encoding A1 or A2
914 MemA[address,4] = PCStoreValue();
915
916 SP = SP - 4*BitCount(registers);
917 }
918#endif
919
920 bool success = false;
921 if (ConditionPassed(opcode)) {
922 const uint32_t addr_byte_size = GetAddressByteSize();
923 const addr_t sp = ReadCoreReg(SP_REG, success: &success);
924 if (!success)
925 return false;
926 uint32_t registers = 0;
927 uint32_t Rt; // the source register
928 switch (encoding) {
929 case eEncodingT1:
930 registers = Bits32(bits: opcode, msbit: 7, lsbit: 0);
931 // The M bit represents LR.
932 if (Bit32(bits: opcode, bit: 8))
933 registers |= (1u << 14);
934 // if BitCount(registers) < 1 then UNPREDICTABLE;
935 if (BitCount(x: registers) < 1)
936 return false;
937 break;
938 case eEncodingT2:
939 // Ignore bits 15 & 13.
940 registers = Bits32(bits: opcode, msbit: 15, lsbit: 0) & ~0xa000;
941 // if BitCount(registers) < 2 then UNPREDICTABLE;
942 if (BitCount(x: registers) < 2)
943 return false;
944 break;
945 case eEncodingT3:
946 Rt = Bits32(bits: opcode, msbit: 15, lsbit: 12);
947 // if BadReg(t) then UNPREDICTABLE;
948 if (BadReg(n: Rt))
949 return false;
950 registers = (1u << Rt);
951 break;
952 case eEncodingA1:
953 registers = Bits32(bits: opcode, msbit: 15, lsbit: 0);
954 // Instead of return false, let's handle the following case as well,
955 // which amounts to pushing one reg onto the full descending stacks.
956 // if BitCount(register_list) < 2 then SEE STMDB / STMFD;
957 break;
958 case eEncodingA2:
959 Rt = Bits32(bits: opcode, msbit: 15, lsbit: 12);
960 // if t == 13 then UNPREDICTABLE;
961 if (Rt == dwarf_sp)
962 return false;
963 registers = (1u << Rt);
964 break;
965 default:
966 return false;
967 }
968 addr_t sp_offset = addr_byte_size * BitCount(x: registers);
969 addr_t addr = sp - sp_offset;
970 uint32_t i;
971
972 EmulateInstruction::Context context;
973 context.type = EmulateInstruction::eContextPushRegisterOnStack;
974 std::optional<RegisterInfo> sp_reg =
975 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_sp);
976 for (i = 0; i < 15; ++i) {
977 if (BitIsSet(value: registers, bit: i)) {
978 std::optional<RegisterInfo> reg_info =
979 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + i);
980 context.SetRegisterToRegisterPlusOffset(data_reg: *reg_info, base_reg: *sp_reg, offset: addr - sp);
981 uint32_t reg_value = ReadCoreReg(regnum: i, success: &success);
982 if (!success)
983 return false;
984 if (!MemAWrite(context, address: addr, data_val: reg_value, size: addr_byte_size))
985 return false;
986 addr += addr_byte_size;
987 }
988 }
989
990 if (BitIsSet(value: registers, bit: 15)) {
991 std::optional<RegisterInfo> reg_info =
992 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_pc);
993 context.SetRegisterToRegisterPlusOffset(data_reg: *reg_info, base_reg: *sp_reg, offset: addr - sp);
994 const uint32_t pc = ReadCoreReg(PC_REG, success: &success);
995 if (!success)
996 return false;
997 if (!MemAWrite(context, address: addr, data_val: pc, size: addr_byte_size))
998 return false;
999 }
1000
1001 context.type = EmulateInstruction::eContextAdjustStackPointer;
1002 context.SetImmediateSigned(-sp_offset);
1003
1004 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindGeneric,
1005 LLDB_REGNUM_GENERIC_SP, reg_value: sp - sp_offset))
1006 return false;
1007 }
1008 return true;
1009}
1010
1011// Pop Multiple Registers loads multiple registers from the stack, loading from
1012// consecutive memory locations staring at the address in SP, and updates
1013// SP to point just above the loaded data.
1014bool EmulateInstructionARM::EmulatePOP(const uint32_t opcode,
1015 const ARMEncoding encoding) {
1016#if 0
1017 // ARM pseudo code...
1018 if (ConditionPassed())
1019 {
1020 EncodingSpecificOperations(); NullCheckIfThumbEE(13);
1021 address = SP;
1022 for i = 0 to 14
1023 if registers<i> == '1' then
1024 R[i] = if UnalignedAllowed then MemU[address,4] else MemA[address,4]; address = address + 4;
1025 if registers<15> == '1' then
1026 if UnalignedAllowed then
1027 LoadWritePC(MemU[address,4]);
1028 else
1029 LoadWritePC(MemA[address,4]);
1030 if registers<13> == '0' then SP = SP + 4*BitCount(registers);
1031 if registers<13> == '1' then SP = bits(32) UNKNOWN;
1032 }
1033#endif
1034
1035 bool success = false;
1036
1037 if (ConditionPassed(opcode)) {
1038 const uint32_t addr_byte_size = GetAddressByteSize();
1039 const addr_t sp = ReadCoreReg(SP_REG, success: &success);
1040 if (!success)
1041 return false;
1042 uint32_t registers = 0;
1043 uint32_t Rt; // the destination register
1044 switch (encoding) {
1045 case eEncodingT1:
1046 registers = Bits32(bits: opcode, msbit: 7, lsbit: 0);
1047 // The P bit represents PC.
1048 if (Bit32(bits: opcode, bit: 8))
1049 registers |= (1u << 15);
1050 // if BitCount(registers) < 1 then UNPREDICTABLE;
1051 if (BitCount(x: registers) < 1)
1052 return false;
1053 break;
1054 case eEncodingT2:
1055 // Ignore bit 13.
1056 registers = Bits32(bits: opcode, msbit: 15, lsbit: 0) & ~0x2000;
1057 // if BitCount(registers) < 2 || (P == '1' && M == '1') then
1058 // UNPREDICTABLE;
1059 if (BitCount(x: registers) < 2 || (Bit32(bits: opcode, bit: 15) && Bit32(bits: opcode, bit: 14)))
1060 return false;
1061 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then
1062 // UNPREDICTABLE;
1063 if (BitIsSet(value: registers, bit: 15) && InITBlock() && !LastInITBlock())
1064 return false;
1065 break;
1066 case eEncodingT3:
1067 Rt = Bits32(bits: opcode, msbit: 15, lsbit: 12);
1068 // if t == 13 || (t == 15 && InITBlock() && !LastInITBlock()) then
1069 // UNPREDICTABLE;
1070 if (Rt == 13)
1071 return false;
1072 if (Rt == 15 && InITBlock() && !LastInITBlock())
1073 return false;
1074 registers = (1u << Rt);
1075 break;
1076 case eEncodingA1:
1077 registers = Bits32(bits: opcode, msbit: 15, lsbit: 0);
1078 // Instead of return false, let's handle the following case as well,
1079 // which amounts to popping one reg from the full descending stacks.
1080 // if BitCount(register_list) < 2 then SEE LDM / LDMIA / LDMFD;
1081
1082 // if registers<13> == '1' && ArchVersion() >= 7 then UNPREDICTABLE;
1083 if (BitIsSet(value: opcode, bit: 13) && ArchVersion() >= ARMv7)
1084 return false;
1085 break;
1086 case eEncodingA2:
1087 Rt = Bits32(bits: opcode, msbit: 15, lsbit: 12);
1088 // if t == 13 then UNPREDICTABLE;
1089 if (Rt == dwarf_sp)
1090 return false;
1091 registers = (1u << Rt);
1092 break;
1093 default:
1094 return false;
1095 }
1096 addr_t sp_offset = addr_byte_size * BitCount(x: registers);
1097 addr_t addr = sp;
1098 uint32_t i, data;
1099
1100 EmulateInstruction::Context context;
1101 context.type = EmulateInstruction::eContextPopRegisterOffStack;
1102
1103 std::optional<RegisterInfo> sp_reg =
1104 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_sp);
1105
1106 for (i = 0; i < 15; ++i) {
1107 if (BitIsSet(value: registers, bit: i)) {
1108 context.SetAddress(addr);
1109 data = MemARead(context, address: addr, size: 4, fail_value: 0, success_ptr: &success);
1110 if (!success)
1111 return false;
1112 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + i,
1113 reg_value: data))
1114 return false;
1115 addr += addr_byte_size;
1116 }
1117 }
1118
1119 if (BitIsSet(value: registers, bit: 15)) {
1120 context.SetRegisterPlusOffset(base_reg: *sp_reg, signed_offset: addr - sp);
1121 data = MemARead(context, address: addr, size: 4, fail_value: 0, success_ptr: &success);
1122 if (!success)
1123 return false;
1124 // In ARMv5T and above, this is an interworking branch.
1125 if (!LoadWritePC(context, addr: data))
1126 return false;
1127 // addr += addr_byte_size;
1128 }
1129
1130 context.type = EmulateInstruction::eContextAdjustStackPointer;
1131 context.SetImmediateSigned(sp_offset);
1132
1133 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindGeneric,
1134 LLDB_REGNUM_GENERIC_SP, reg_value: sp + sp_offset))
1135 return false;
1136 }
1137 return true;
1138}
1139
1140// Set r7 or ip to point to saved value residing within the stack.
1141// ADD (SP plus immediate)
1142bool EmulateInstructionARM::EmulateADDRdSPImm(const uint32_t opcode,
1143 const ARMEncoding encoding) {
1144#if 0
1145 // ARM pseudo code...
1146 if (ConditionPassed())
1147 {
1148 EncodingSpecificOperations();
1149 (result, carry, overflow) = AddWithCarry(SP, imm32, '0');
1150 if d == 15 then
1151 ALUWritePC(result); // setflags is always FALSE here
1152 else
1153 R[d] = result;
1154 if setflags then
1155 APSR.N = result<31>;
1156 APSR.Z = IsZeroBit(result);
1157 APSR.C = carry;
1158 APSR.V = overflow;
1159 }
1160#endif
1161
1162 bool success = false;
1163
1164 if (ConditionPassed(opcode)) {
1165 const addr_t sp = ReadCoreReg(SP_REG, success: &success);
1166 if (!success)
1167 return false;
1168 uint32_t Rd; // the destination register
1169 uint32_t imm32;
1170 switch (encoding) {
1171 case eEncodingT1:
1172 Rd = 7;
1173 imm32 = Bits32(bits: opcode, msbit: 7, lsbit: 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32)
1174 break;
1175 case eEncodingA1:
1176 Rd = Bits32(bits: opcode, msbit: 15, lsbit: 12);
1177 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1178 break;
1179 default:
1180 return false;
1181 }
1182 addr_t sp_offset = imm32;
1183 addr_t addr = sp + sp_offset; // a pointer to the stack area
1184
1185 EmulateInstruction::Context context;
1186 if (Rd == GetFramePointerRegisterNumber())
1187 context.type = eContextSetFramePointer;
1188 else
1189 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1190 std::optional<RegisterInfo> sp_reg =
1191 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_sp);
1192 context.SetRegisterPlusOffset(base_reg: *sp_reg, signed_offset: sp_offset);
1193
1194 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + Rd,
1195 reg_value: addr))
1196 return false;
1197 }
1198 return true;
1199}
1200
1201// Set r7 or ip to the current stack pointer.
1202// MOV (register)
1203bool EmulateInstructionARM::EmulateMOVRdSP(const uint32_t opcode,
1204 const ARMEncoding encoding) {
1205#if 0
1206 // ARM pseudo code...
1207 if (ConditionPassed())
1208 {
1209 EncodingSpecificOperations();
1210 result = R[m];
1211 if d == 15 then
1212 ALUWritePC(result); // setflags is always FALSE here
1213 else
1214 R[d] = result;
1215 if setflags then
1216 APSR.N = result<31>;
1217 APSR.Z = IsZeroBit(result);
1218 // APSR.C unchanged
1219 // APSR.V unchanged
1220 }
1221#endif
1222
1223 bool success = false;
1224
1225 if (ConditionPassed(opcode)) {
1226 const addr_t sp = ReadCoreReg(SP_REG, success: &success);
1227 if (!success)
1228 return false;
1229 uint32_t Rd; // the destination register
1230 switch (encoding) {
1231 case eEncodingT1:
1232 Rd = 7;
1233 break;
1234 case eEncodingA1:
1235 Rd = 12;
1236 break;
1237 default:
1238 return false;
1239 }
1240
1241 EmulateInstruction::Context context;
1242 if (Rd == GetFramePointerRegisterNumber())
1243 context.type = EmulateInstruction::eContextSetFramePointer;
1244 else
1245 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1246 std::optional<RegisterInfo> sp_reg =
1247 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_sp);
1248 context.SetRegisterPlusOffset(base_reg: *sp_reg, signed_offset: 0);
1249
1250 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + Rd, reg_value: sp))
1251 return false;
1252 }
1253 return true;
1254}
1255
1256// Move from high register (r8-r15) to low register (r0-r7).
1257// MOV (register)
1258bool EmulateInstructionARM::EmulateMOVLowHigh(const uint32_t opcode,
1259 const ARMEncoding encoding) {
1260 return EmulateMOVRdRm(opcode, encoding);
1261}
1262
1263// Move from register to register.
1264// MOV (register)
1265bool EmulateInstructionARM::EmulateMOVRdRm(const uint32_t opcode,
1266 const ARMEncoding encoding) {
1267#if 0
1268 // ARM pseudo code...
1269 if (ConditionPassed())
1270 {
1271 EncodingSpecificOperations();
1272 result = R[m];
1273 if d == 15 then
1274 ALUWritePC(result); // setflags is always FALSE here
1275 else
1276 R[d] = result;
1277 if setflags then
1278 APSR.N = result<31>;
1279 APSR.Z = IsZeroBit(result);
1280 // APSR.C unchanged
1281 // APSR.V unchanged
1282 }
1283#endif
1284
1285 bool success = false;
1286
1287 if (ConditionPassed(opcode)) {
1288 uint32_t Rm; // the source register
1289 uint32_t Rd; // the destination register
1290 bool setflags;
1291 switch (encoding) {
1292 case eEncodingT1:
1293 Rd = Bit32(bits: opcode, bit: 7) << 3 | Bits32(bits: opcode, msbit: 2, lsbit: 0);
1294 Rm = Bits32(bits: opcode, msbit: 6, lsbit: 3);
1295 setflags = false;
1296 if (Rd == 15 && InITBlock() && !LastInITBlock())
1297 return false;
1298 break;
1299 case eEncodingT2:
1300 Rd = Bits32(bits: opcode, msbit: 2, lsbit: 0);
1301 Rm = Bits32(bits: opcode, msbit: 5, lsbit: 3);
1302 setflags = true;
1303 if (InITBlock())
1304 return false;
1305 break;
1306 case eEncodingT3:
1307 Rd = Bits32(bits: opcode, msbit: 11, lsbit: 8);
1308 Rm = Bits32(bits: opcode, msbit: 3, lsbit: 0);
1309 setflags = BitIsSet(value: opcode, bit: 20);
1310 // if setflags && (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
1311 if (setflags && (BadReg(n: Rd) || BadReg(n: Rm)))
1312 return false;
1313 // if !setflags && (d == 15 || m == 15 || (d == 13 && m == 13)) then
1314 // UNPREDICTABLE;
1315 if (!setflags && (Rd == 15 || Rm == 15 || (Rd == 13 && Rm == 13)))
1316 return false;
1317 break;
1318 case eEncodingA1:
1319 Rd = Bits32(bits: opcode, msbit: 15, lsbit: 12);
1320 Rm = Bits32(bits: opcode, msbit: 3, lsbit: 0);
1321 setflags = BitIsSet(value: opcode, bit: 20);
1322
1323 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
1324 // instructions;
1325 if (Rd == 15 && setflags)
1326 return EmulateSUBSPcLrEtc(opcode, encoding);
1327 break;
1328 default:
1329 return false;
1330 }
1331 uint32_t result = ReadCoreReg(regnum: Rm, success: &success);
1332 if (!success)
1333 return false;
1334
1335 // The context specifies that Rm is to be moved into Rd.
1336 EmulateInstruction::Context context;
1337 if (Rd == 13)
1338 context.type = EmulateInstruction::eContextAdjustStackPointer;
1339 else if (Rd == GetFramePointerRegisterNumber() && Rm == 13)
1340 context.type = EmulateInstruction::eContextSetFramePointer;
1341 else
1342 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1343 std::optional<RegisterInfo> dwarf_reg =
1344 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + Rm);
1345 context.SetRegisterPlusOffset(base_reg: *dwarf_reg, signed_offset: 0);
1346
1347 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags))
1348 return false;
1349 }
1350 return true;
1351}
1352
1353// Move (immediate) writes an immediate value to the destination register. It
1354// can optionally update the condition flags based on the value.
1355// MOV (immediate)
1356bool EmulateInstructionARM::EmulateMOVRdImm(const uint32_t opcode,
1357 const ARMEncoding encoding) {
1358#if 0
1359 // ARM pseudo code...
1360 if (ConditionPassed())
1361 {
1362 EncodingSpecificOperations();
1363 result = imm32;
1364 if d == 15 then // Can only occur for ARM encoding
1365 ALUWritePC(result); // setflags is always FALSE here
1366 else
1367 R[d] = result;
1368 if setflags then
1369 APSR.N = result<31>;
1370 APSR.Z = IsZeroBit(result);
1371 APSR.C = carry;
1372 // APSR.V unchanged
1373 }
1374#endif
1375
1376 if (ConditionPassed(opcode)) {
1377 uint32_t Rd; // the destination register
1378 uint32_t imm32; // the immediate value to be written to Rd
1379 uint32_t carry =
1380 0; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C.
1381 // for setflags == false, this value is a don't care initialized to
1382 // 0 to silence the static analyzer
1383 bool setflags;
1384 switch (encoding) {
1385 case eEncodingT1:
1386 Rd = Bits32(bits: opcode, msbit: 10, lsbit: 8);
1387 setflags = !InITBlock();
1388 imm32 = Bits32(bits: opcode, msbit: 7, lsbit: 0); // imm32 = ZeroExtend(imm8, 32)
1389 carry = APSR_C;
1390
1391 break;
1392
1393 case eEncodingT2:
1394 Rd = Bits32(bits: opcode, msbit: 11, lsbit: 8);
1395 setflags = BitIsSet(value: opcode, bit: 20);
1396 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry_out&: carry);
1397 if (BadReg(n: Rd))
1398 return false;
1399
1400 break;
1401
1402 case eEncodingT3: {
1403 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm4:i:imm3:imm8,
1404 // 32);
1405 Rd = Bits32(bits: opcode, msbit: 11, lsbit: 8);
1406 setflags = false;
1407 uint32_t imm4 = Bits32(bits: opcode, msbit: 19, lsbit: 16);
1408 uint32_t imm3 = Bits32(bits: opcode, msbit: 14, lsbit: 12);
1409 uint32_t i = Bit32(bits: opcode, bit: 26);
1410 uint32_t imm8 = Bits32(bits: opcode, msbit: 7, lsbit: 0);
1411 imm32 = (imm4 << 12) | (i << 11) | (imm3 << 8) | imm8;
1412
1413 // if BadReg(d) then UNPREDICTABLE;
1414 if (BadReg(n: Rd))
1415 return false;
1416 } break;
1417
1418 case eEncodingA1:
1419 // d = UInt(Rd); setflags = (S == '1'); (imm32, carry) =
1420 // ARMExpandImm_C(imm12, APSR.C);
1421 Rd = Bits32(bits: opcode, msbit: 15, lsbit: 12);
1422 setflags = BitIsSet(value: opcode, bit: 20);
1423 imm32 = ARMExpandImm_C(opcode, APSR_C, carry_out&: carry);
1424
1425 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
1426 // instructions;
1427 if ((Rd == 15) && setflags)
1428 return EmulateSUBSPcLrEtc(opcode, encoding);
1429
1430 break;
1431
1432 case eEncodingA2: {
1433 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm4:imm12, 32);
1434 Rd = Bits32(bits: opcode, msbit: 15, lsbit: 12);
1435 setflags = false;
1436 uint32_t imm4 = Bits32(bits: opcode, msbit: 19, lsbit: 16);
1437 uint32_t imm12 = Bits32(bits: opcode, msbit: 11, lsbit: 0);
1438 imm32 = (imm4 << 12) | imm12;
1439
1440 // if d == 15 then UNPREDICTABLE;
1441 if (Rd == 15)
1442 return false;
1443 } break;
1444
1445 default:
1446 return false;
1447 }
1448 uint32_t result = imm32;
1449
1450 // The context specifies that an immediate is to be moved into Rd.
1451 EmulateInstruction::Context context;
1452 context.type = EmulateInstruction::eContextImmediate;
1453 context.SetNoArgs();
1454
1455 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
1456 return false;
1457 }
1458 return true;
1459}
1460
1461// MUL multiplies two register values. The least significant 32 bits of the
1462// result are written to the destination
1463// register. These 32 bits do not depend on whether the source register values
1464// are considered to be signed values or unsigned values.
1465//
1466// Optionally, it can update the condition flags based on the result. In the
1467// Thumb instruction set, this option is limited to only a few forms of the
1468// instruction.
1469bool EmulateInstructionARM::EmulateMUL(const uint32_t opcode,
1470 const ARMEncoding encoding) {
1471#if 0
1472 if ConditionPassed() then
1473 EncodingSpecificOperations();
1474 operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final results
1475 operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final results
1476 result = operand1 * operand2;
1477 R[d] = result<31:0>;
1478 if setflags then
1479 APSR.N = result<31>;
1480 APSR.Z = IsZeroBit(result);
1481 if ArchVersion() == 4 then
1482 APSR.C = bit UNKNOWN;
1483 // else APSR.C unchanged
1484 // APSR.V always unchanged
1485#endif
1486
1487 if (ConditionPassed(opcode)) {
1488 uint32_t d;
1489 uint32_t n;
1490 uint32_t m;
1491 bool setflags;
1492
1493 // EncodingSpecificOperations();
1494 switch (encoding) {
1495 case eEncodingT1:
1496 // d = UInt(Rdm); n = UInt(Rn); m = UInt(Rdm); setflags = !InITBlock();
1497 d = Bits32(bits: opcode, msbit: 2, lsbit: 0);
1498 n = Bits32(bits: opcode, msbit: 5, lsbit: 3);
1499 m = Bits32(bits: opcode, msbit: 2, lsbit: 0);
1500 setflags = !InITBlock();
1501
1502 // if ArchVersion() < 6 && d == n then UNPREDICTABLE;
1503 if ((ArchVersion() < ARMv6) && (d == n))
1504 return false;
1505
1506 break;
1507
1508 case eEncodingT2:
1509 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = FALSE;
1510 d = Bits32(bits: opcode, msbit: 11, lsbit: 8);
1511 n = Bits32(bits: opcode, msbit: 19, lsbit: 16);
1512 m = Bits32(bits: opcode, msbit: 3, lsbit: 0);
1513 setflags = false;
1514
1515 // if BadReg(d) || BadReg(n) || BadReg(m) then UNPREDICTABLE;
1516 if (BadReg(n: d) || BadReg(n) || BadReg(n: m))
1517 return false;
1518
1519 break;
1520
1521 case eEncodingA1:
1522 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == '1');
1523 d = Bits32(bits: opcode, msbit: 19, lsbit: 16);
1524 n = Bits32(bits: opcode, msbit: 3, lsbit: 0);
1525 m = Bits32(bits: opcode, msbit: 11, lsbit: 8);
1526 setflags = BitIsSet(value: opcode, bit: 20);
1527
1528 // if d == 15 || n == 15 || m == 15 then UNPREDICTABLE;
1529 if ((d == 15) || (n == 15) || (m == 15))
1530 return false;
1531
1532 // if ArchVersion() < 6 && d == n then UNPREDICTABLE;
1533 if ((ArchVersion() < ARMv6) && (d == n))
1534 return false;
1535
1536 break;
1537
1538 default:
1539 return false;
1540 }
1541
1542 bool success = false;
1543
1544 // operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final
1545 // results
1546 uint64_t operand1 =
1547 ReadRegisterUnsigned(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n, fail_value: 0, success_ptr: &success);
1548 if (!success)
1549 return false;
1550
1551 // operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final
1552 // results
1553 uint64_t operand2 =
1554 ReadRegisterUnsigned(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + m, fail_value: 0, success_ptr: &success);
1555 if (!success)
1556 return false;
1557
1558 // result = operand1 * operand2;
1559 uint64_t result = operand1 * operand2;
1560
1561 // R[d] = result<31:0>;
1562 std::optional<RegisterInfo> op1_reg =
1563 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n);
1564 std::optional<RegisterInfo> op2_reg =
1565 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + m);
1566
1567 EmulateInstruction::Context context;
1568 context.type = eContextArithmetic;
1569 context.SetRegisterRegisterOperands(op1_reg: *op1_reg, op2_reg: *op2_reg);
1570
1571 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + d,
1572 reg_value: (0x0000ffff & result)))
1573 return false;
1574
1575 // if setflags then
1576 if (setflags) {
1577 // APSR.N = result<31>;
1578 // APSR.Z = IsZeroBit(result);
1579 m_new_inst_cpsr = m_opcode_cpsr;
1580 SetBit32(bits&: m_new_inst_cpsr, CPSR_N_POS, val: Bit32(bits: result, bit: 31));
1581 SetBit32(bits&: m_new_inst_cpsr, CPSR_Z_POS, val: result == 0 ? 1 : 0);
1582 if (m_new_inst_cpsr != m_opcode_cpsr) {
1583 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindGeneric,
1584 LLDB_REGNUM_GENERIC_FLAGS, reg_value: m_new_inst_cpsr))
1585 return false;
1586 }
1587
1588 // if ArchVersion() == 4 then
1589 // APSR.C = bit UNKNOWN;
1590 }
1591 }
1592 return true;
1593}
1594
1595// Bitwise NOT (immediate) writes the bitwise inverse of an immediate value to
1596// the destination register. It can optionally update the condition flags based
1597// on the value.
1598bool EmulateInstructionARM::EmulateMVNImm(const uint32_t opcode,
1599 const ARMEncoding encoding) {
1600#if 0
1601 // ARM pseudo code...
1602 if (ConditionPassed())
1603 {
1604 EncodingSpecificOperations();
1605 result = NOT(imm32);
1606 if d == 15 then // Can only occur for ARM encoding
1607 ALUWritePC(result); // setflags is always FALSE here
1608 else
1609 R[d] = result;
1610 if setflags then
1611 APSR.N = result<31>;
1612 APSR.Z = IsZeroBit(result);
1613 APSR.C = carry;
1614 // APSR.V unchanged
1615 }
1616#endif
1617
1618 if (ConditionPassed(opcode)) {
1619 uint32_t Rd; // the destination register
1620 uint32_t imm32; // the output after ThumbExpandImm_C or ARMExpandImm_C
1621 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C
1622 bool setflags;
1623 switch (encoding) {
1624 case eEncodingT1:
1625 Rd = Bits32(bits: opcode, msbit: 11, lsbit: 8);
1626 setflags = BitIsSet(value: opcode, bit: 20);
1627 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry_out&: carry);
1628 break;
1629 case eEncodingA1:
1630 Rd = Bits32(bits: opcode, msbit: 15, lsbit: 12);
1631 setflags = BitIsSet(value: opcode, bit: 20);
1632 imm32 = ARMExpandImm_C(opcode, APSR_C, carry_out&: carry);
1633
1634 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
1635 // instructions;
1636 if (Rd == 15 && setflags)
1637 return EmulateSUBSPcLrEtc(opcode, encoding);
1638 break;
1639 default:
1640 return false;
1641 }
1642 uint32_t result = ~imm32;
1643
1644 // The context specifies that an immediate is to be moved into Rd.
1645 EmulateInstruction::Context context;
1646 context.type = EmulateInstruction::eContextImmediate;
1647 context.SetNoArgs();
1648
1649 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
1650 return false;
1651 }
1652 return true;
1653}
1654
1655// Bitwise NOT (register) writes the bitwise inverse of a register value to the
1656// destination register. It can optionally update the condition flags based on
1657// the result.
1658bool EmulateInstructionARM::EmulateMVNReg(const uint32_t opcode,
1659 const ARMEncoding encoding) {
1660#if 0
1661 // ARM pseudo code...
1662 if (ConditionPassed())
1663 {
1664 EncodingSpecificOperations();
1665 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
1666 result = NOT(shifted);
1667 if d == 15 then // Can only occur for ARM encoding
1668 ALUWritePC(result); // setflags is always FALSE here
1669 else
1670 R[d] = result;
1671 if setflags then
1672 APSR.N = result<31>;
1673 APSR.Z = IsZeroBit(result);
1674 APSR.C = carry;
1675 // APSR.V unchanged
1676 }
1677#endif
1678
1679 if (ConditionPassed(opcode)) {
1680 uint32_t Rm; // the source register
1681 uint32_t Rd; // the destination register
1682 ARM_ShifterType shift_t;
1683 uint32_t shift_n; // the shift applied to the value read from Rm
1684 bool setflags;
1685 uint32_t carry; // the carry bit after the shift operation
1686 switch (encoding) {
1687 case eEncodingT1:
1688 Rd = Bits32(bits: opcode, msbit: 2, lsbit: 0);
1689 Rm = Bits32(bits: opcode, msbit: 5, lsbit: 3);
1690 setflags = !InITBlock();
1691 shift_t = SRType_LSL;
1692 shift_n = 0;
1693 if (InITBlock())
1694 return false;
1695 break;
1696 case eEncodingT2:
1697 Rd = Bits32(bits: opcode, msbit: 11, lsbit: 8);
1698 Rm = Bits32(bits: opcode, msbit: 3, lsbit: 0);
1699 setflags = BitIsSet(value: opcode, bit: 20);
1700 shift_n = DecodeImmShiftThumb(opcode, shift_t);
1701 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
1702 if (BadReg(n: Rd) || BadReg(n: Rm))
1703 return false;
1704 break;
1705 case eEncodingA1:
1706 Rd = Bits32(bits: opcode, msbit: 15, lsbit: 12);
1707 Rm = Bits32(bits: opcode, msbit: 3, lsbit: 0);
1708 setflags = BitIsSet(value: opcode, bit: 20);
1709 shift_n = DecodeImmShiftARM(opcode, shift_t);
1710 break;
1711 default:
1712 return false;
1713 }
1714 bool success = false;
1715 uint32_t value = ReadCoreReg(regnum: Rm, success: &success);
1716 if (!success)
1717 return false;
1718
1719 uint32_t shifted =
1720 Shift_C(value, type: shift_t, amount: shift_n, APSR_C, carry_out&: carry, success: &success);
1721 if (!success)
1722 return false;
1723 uint32_t result = ~shifted;
1724
1725 // The context specifies that an immediate is to be moved into Rd.
1726 EmulateInstruction::Context context;
1727 context.type = EmulateInstruction::eContextImmediate;
1728 context.SetNoArgs();
1729
1730 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
1731 return false;
1732 }
1733 return true;
1734}
1735
1736// PC relative immediate load into register, possibly followed by ADD (SP plus
1737// register).
1738// LDR (literal)
1739bool EmulateInstructionARM::EmulateLDRRtPCRelative(const uint32_t opcode,
1740 const ARMEncoding encoding) {
1741#if 0
1742 // ARM pseudo code...
1743 if (ConditionPassed())
1744 {
1745 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
1746 base = Align(PC,4);
1747 address = if add then (base + imm32) else (base - imm32);
1748 data = MemU[address,4];
1749 if t == 15 then
1750 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
1751 elsif UnalignedSupport() || address<1:0> = '00' then
1752 R[t] = data;
1753 else // Can only apply before ARMv7
1754 if CurrentInstrSet() == InstrSet_ARM then
1755 R[t] = ROR(data, 8*UInt(address<1:0>));
1756 else
1757 R[t] = bits(32) UNKNOWN;
1758 }
1759#endif
1760
1761 if (ConditionPassed(opcode)) {
1762 bool success = false;
1763 const uint32_t pc = ReadCoreReg(PC_REG, success: &success);
1764 if (!success)
1765 return false;
1766
1767 // PC relative immediate load context
1768 EmulateInstruction::Context context;
1769 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1770 std::optional<RegisterInfo> pc_reg =
1771 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_pc);
1772 context.SetRegisterPlusOffset(base_reg: *pc_reg, signed_offset: 0);
1773
1774 uint32_t Rt; // the destination register
1775 uint32_t imm32; // immediate offset from the PC
1776 bool add; // +imm32 or -imm32?
1777 addr_t base; // the base address
1778 addr_t address; // the PC relative address
1779 uint32_t data; // the literal data value from the PC relative load
1780 switch (encoding) {
1781 case eEncodingT1:
1782 Rt = Bits32(bits: opcode, msbit: 10, lsbit: 8);
1783 imm32 = Bits32(bits: opcode, msbit: 7, lsbit: 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32);
1784 add = true;
1785 break;
1786 case eEncodingT2:
1787 Rt = Bits32(bits: opcode, msbit: 15, lsbit: 12);
1788 imm32 = Bits32(bits: opcode, msbit: 11, lsbit: 0) << 2; // imm32 = ZeroExtend(imm12, 32);
1789 add = BitIsSet(value: opcode, bit: 23);
1790 if (Rt == 15 && InITBlock() && !LastInITBlock())
1791 return false;
1792 break;
1793 default:
1794 return false;
1795 }
1796
1797 base = Align(val: pc, alignment: 4);
1798 if (add)
1799 address = base + imm32;
1800 else
1801 address = base - imm32;
1802
1803 context.SetRegisterPlusOffset(base_reg: *pc_reg, signed_offset: address - base);
1804 data = MemURead(context, address, size: 4, fail_value: 0, success_ptr: &success);
1805 if (!success)
1806 return false;
1807
1808 if (Rt == 15) {
1809 if (Bits32(bits: address, msbit: 1, lsbit: 0) == 0) {
1810 // In ARMv5T and above, this is an interworking branch.
1811 if (!LoadWritePC(context, addr: data))
1812 return false;
1813 } else
1814 return false;
1815 } else if (UnalignedSupport() || Bits32(bits: address, msbit: 1, lsbit: 0) == 0) {
1816 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + Rt,
1817 reg_value: data))
1818 return false;
1819 } else // We don't handle ARM for now.
1820 return false;
1821 }
1822 return true;
1823}
1824
1825// An add operation to adjust the SP.
1826// ADD (SP plus immediate)
1827bool EmulateInstructionARM::EmulateADDSPImm(const uint32_t opcode,
1828 const ARMEncoding encoding) {
1829#if 0
1830 // ARM pseudo code...
1831 if (ConditionPassed())
1832 {
1833 EncodingSpecificOperations();
1834 (result, carry, overflow) = AddWithCarry(SP, imm32, '0');
1835 if d == 15 then // Can only occur for ARM encoding
1836 ALUWritePC(result); // setflags is always FALSE here
1837 else
1838 R[d] = result;
1839 if setflags then
1840 APSR.N = result<31>;
1841 APSR.Z = IsZeroBit(result);
1842 APSR.C = carry;
1843 APSR.V = overflow;
1844 }
1845#endif
1846
1847 bool success = false;
1848
1849 if (ConditionPassed(opcode)) {
1850 const addr_t sp = ReadCoreReg(SP_REG, success: &success);
1851 if (!success)
1852 return false;
1853 uint32_t imm32; // the immediate operand
1854 uint32_t d;
1855 bool setflags;
1856 switch (encoding) {
1857 case eEncodingT1:
1858 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm8:'00', 32);
1859 d = Bits32(bits: opcode, msbit: 10, lsbit: 8);
1860 imm32 = (Bits32(bits: opcode, msbit: 7, lsbit: 0) << 2);
1861 setflags = false;
1862 break;
1863
1864 case eEncodingT2:
1865 // d = 13; setflags = FALSE; imm32 = ZeroExtend(imm7:'00', 32);
1866 d = 13;
1867 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
1868 setflags = false;
1869 break;
1870
1871 case eEncodingT3:
1872 // d = UInt(Rd); setflags = (S == "1"); imm32 =
1873 // ThumbExpandImm(i:imm3:imm8);
1874 d = Bits32(bits: opcode, msbit: 11, lsbit: 8);
1875 imm32 = ThumbExpandImm(opcode);
1876 setflags = Bit32(bits: opcode, bit: 20);
1877
1878 // if Rd == "1111" && S == "1" then SEE CMN (immediate);
1879 if (d == 15 && setflags == 1)
1880 return false; // CMN (immediate) not yet supported
1881
1882 // if d == 15 && S == "0" then UNPREDICTABLE;
1883 if (d == 15 && setflags == 0)
1884 return false;
1885 break;
1886
1887 case eEncodingT4: {
1888 // if Rn == '1111' then SEE ADR;
1889 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(i:imm3:imm8, 32);
1890 d = Bits32(bits: opcode, msbit: 11, lsbit: 8);
1891 setflags = false;
1892 uint32_t i = Bit32(bits: opcode, bit: 26);
1893 uint32_t imm3 = Bits32(bits: opcode, msbit: 14, lsbit: 12);
1894 uint32_t imm8 = Bits32(bits: opcode, msbit: 7, lsbit: 0);
1895 imm32 = (i << 11) | (imm3 << 8) | imm8;
1896
1897 // if d == 15 then UNPREDICTABLE;
1898 if (d == 15)
1899 return false;
1900 } break;
1901
1902 default:
1903 return false;
1904 }
1905 // (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
1906 AddWithCarryResult res = AddWithCarry(x: sp, y: imm32, carry_in: 0);
1907
1908 EmulateInstruction::Context context;
1909 if (d == 13)
1910 context.type = EmulateInstruction::eContextAdjustStackPointer;
1911 else
1912 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1913
1914 std::optional<RegisterInfo> sp_reg =
1915 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_sp);
1916 context.SetRegisterPlusOffset(base_reg: *sp_reg, signed_offset: res.result - sp);
1917
1918 if (d == 15) {
1919 if (!ALUWritePC(context, addr: res.result))
1920 return false;
1921 } else {
1922 // R[d] = result;
1923 // if setflags then
1924 // APSR.N = result<31>;
1925 // APSR.Z = IsZeroBit(result);
1926 // APSR.C = carry;
1927 // APSR.V = overflow;
1928 if (!WriteCoreRegOptionalFlags(context, result: res.result, Rd: d, setflags,
1929 carry: res.carry_out, overflow: res.overflow))
1930 return false;
1931 }
1932 }
1933 return true;
1934}
1935
1936// An add operation to adjust the SP.
1937// ADD (SP plus register)
1938bool EmulateInstructionARM::EmulateADDSPRm(const uint32_t opcode,
1939 const ARMEncoding encoding) {
1940#if 0
1941 // ARM pseudo code...
1942 if (ConditionPassed())
1943 {
1944 EncodingSpecificOperations();
1945 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
1946 (result, carry, overflow) = AddWithCarry(SP, shifted, '0');
1947 if d == 15 then
1948 ALUWritePC(result); // setflags is always FALSE here
1949 else
1950 R[d] = result;
1951 if setflags then
1952 APSR.N = result<31>;
1953 APSR.Z = IsZeroBit(result);
1954 APSR.C = carry;
1955 APSR.V = overflow;
1956 }
1957#endif
1958
1959 bool success = false;
1960
1961 if (ConditionPassed(opcode)) {
1962 const addr_t sp = ReadCoreReg(SP_REG, success: &success);
1963 if (!success)
1964 return false;
1965 uint32_t Rm; // the second operand
1966 switch (encoding) {
1967 case eEncodingT2:
1968 Rm = Bits32(bits: opcode, msbit: 6, lsbit: 3);
1969 break;
1970 default:
1971 return false;
1972 }
1973 int32_t reg_value = ReadCoreReg(regnum: Rm, success: &success);
1974 if (!success)
1975 return false;
1976
1977 addr_t addr = (int32_t)sp + reg_value; // the adjusted stack pointer value
1978
1979 EmulateInstruction::Context context;
1980 context.type = eContextArithmetic;
1981 std::optional<RegisterInfo> sp_reg =
1982 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_sp);
1983 std::optional<RegisterInfo> other_reg =
1984 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + Rm);
1985 context.SetRegisterRegisterOperands(op1_reg: *sp_reg, op2_reg: *other_reg);
1986
1987 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindGeneric,
1988 LLDB_REGNUM_GENERIC_SP, reg_value: addr))
1989 return false;
1990 }
1991 return true;
1992}
1993
1994// Branch with Link and Exchange Instruction Sets (immediate) calls a
1995// subroutine at a PC-relative address, and changes instruction set from ARM to
1996// Thumb, or from Thumb to ARM.
1997// BLX (immediate)
1998bool EmulateInstructionARM::EmulateBLXImmediate(const uint32_t opcode,
1999 const ARMEncoding encoding) {
2000#if 0
2001 // ARM pseudo code...
2002 if (ConditionPassed())
2003 {
2004 EncodingSpecificOperations();
2005 if CurrentInstrSet() == InstrSet_ARM then
2006 LR = PC - 4;
2007 else
2008 LR = PC<31:1> : '1';
2009 if targetInstrSet == InstrSet_ARM then
2010 targetAddress = Align(PC,4) + imm32;
2011 else
2012 targetAddress = PC + imm32;
2013 SelectInstrSet(targetInstrSet);
2014 BranchWritePC(targetAddress);
2015 }
2016#endif
2017
2018 bool success = true;
2019
2020 if (ConditionPassed(opcode)) {
2021 EmulateInstruction::Context context;
2022 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
2023 const uint32_t pc = ReadCoreReg(PC_REG, success: &success);
2024 if (!success)
2025 return false;
2026 addr_t lr; // next instruction address
2027 addr_t target; // target address
2028 int32_t imm32; // PC-relative offset
2029 switch (encoding) {
2030 case eEncodingT1: {
2031 lr = pc | 1u; // return address
2032 uint32_t S = Bit32(bits: opcode, bit: 26);
2033 uint32_t imm10 = Bits32(bits: opcode, msbit: 25, lsbit: 16);
2034 uint32_t J1 = Bit32(bits: opcode, bit: 13);
2035 uint32_t J2 = Bit32(bits: opcode, bit: 11);
2036 uint32_t imm11 = Bits32(bits: opcode, msbit: 10, lsbit: 0);
2037 uint32_t I1 = !(J1 ^ S);
2038 uint32_t I2 = !(J2 ^ S);
2039 uint32_t imm25 =
2040 (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
2041 imm32 = llvm::SignExtend32<25>(X: imm25);
2042 target = pc + imm32;
2043 SelectInstrSet(arm_or_thumb: eModeThumb);
2044 context.SetISAAndImmediateSigned(isa: eModeThumb, data: 4 + imm32);
2045 if (InITBlock() && !LastInITBlock())
2046 return false;
2047 break;
2048 }
2049 case eEncodingT2: {
2050 lr = pc | 1u; // return address
2051 uint32_t S = Bit32(bits: opcode, bit: 26);
2052 uint32_t imm10H = Bits32(bits: opcode, msbit: 25, lsbit: 16);
2053 uint32_t J1 = Bit32(bits: opcode, bit: 13);
2054 uint32_t J2 = Bit32(bits: opcode, bit: 11);
2055 uint32_t imm10L = Bits32(bits: opcode, msbit: 10, lsbit: 1);
2056 uint32_t I1 = !(J1 ^ S);
2057 uint32_t I2 = !(J2 ^ S);
2058 uint32_t imm25 =
2059 (S << 24) | (I1 << 23) | (I2 << 22) | (imm10H << 12) | (imm10L << 2);
2060 imm32 = llvm::SignExtend32<25>(X: imm25);
2061 target = Align(val: pc, alignment: 4) + imm32;
2062 SelectInstrSet(arm_or_thumb: eModeARM);
2063 context.SetISAAndImmediateSigned(isa: eModeARM, data: 4 + imm32);
2064 if (InITBlock() && !LastInITBlock())
2065 return false;
2066 break;
2067 }
2068 case eEncodingA1:
2069 lr = pc - 4; // return address
2070 imm32 = llvm::SignExtend32<26>(X: Bits32(bits: opcode, msbit: 23, lsbit: 0) << 2);
2071 target = Align(val: pc, alignment: 4) + imm32;
2072 SelectInstrSet(arm_or_thumb: eModeARM);
2073 context.SetISAAndImmediateSigned(isa: eModeARM, data: 8 + imm32);
2074 break;
2075 case eEncodingA2:
2076 lr = pc - 4; // return address
2077 imm32 = llvm::SignExtend32<26>(X: Bits32(bits: opcode, msbit: 23, lsbit: 0) << 2 |
2078 Bits32(bits: opcode, msbit: 24, lsbit: 24) << 1);
2079 target = pc + imm32;
2080 SelectInstrSet(arm_or_thumb: eModeThumb);
2081 context.SetISAAndImmediateSigned(isa: eModeThumb, data: 8 + imm32);
2082 break;
2083 default:
2084 return false;
2085 }
2086 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindGeneric,
2087 LLDB_REGNUM_GENERIC_RA, reg_value: lr))
2088 return false;
2089 if (!BranchWritePC(context, addr: target))
2090 return false;
2091 if (m_opcode_cpsr != m_new_inst_cpsr)
2092 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindGeneric,
2093 LLDB_REGNUM_GENERIC_FLAGS, reg_value: m_new_inst_cpsr))
2094 return false;
2095 }
2096 return true;
2097}
2098
2099// Branch with Link and Exchange (register) calls a subroutine at an address
2100// and instruction set specified by a register.
2101// BLX (register)
2102bool EmulateInstructionARM::EmulateBLXRm(const uint32_t opcode,
2103 const ARMEncoding encoding) {
2104#if 0
2105 // ARM pseudo code...
2106 if (ConditionPassed())
2107 {
2108 EncodingSpecificOperations();
2109 target = R[m];
2110 if CurrentInstrSet() == InstrSet_ARM then
2111 next_instr_addr = PC - 4;
2112 LR = next_instr_addr;
2113 else
2114 next_instr_addr = PC - 2;
2115 LR = next_instr_addr<31:1> : '1';
2116 BXWritePC(target);
2117 }
2118#endif
2119
2120 bool success = false;
2121
2122 if (ConditionPassed(opcode)) {
2123 EmulateInstruction::Context context;
2124 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
2125 const uint32_t pc = ReadCoreReg(PC_REG, success: &success);
2126 addr_t lr; // next instruction address
2127 if (!success)
2128 return false;
2129 uint32_t Rm; // the register with the target address
2130 switch (encoding) {
2131 case eEncodingT1:
2132 lr = (pc - 2) | 1u; // return address
2133 Rm = Bits32(bits: opcode, msbit: 6, lsbit: 3);
2134 // if m == 15 then UNPREDICTABLE;
2135 if (Rm == 15)
2136 return false;
2137 if (InITBlock() && !LastInITBlock())
2138 return false;
2139 break;
2140 case eEncodingA1:
2141 lr = pc - 4; // return address
2142 Rm = Bits32(bits: opcode, msbit: 3, lsbit: 0);
2143 // if m == 15 then UNPREDICTABLE;
2144 if (Rm == 15)
2145 return false;
2146 break;
2147 default:
2148 return false;
2149 }
2150 addr_t target = ReadCoreReg(regnum: Rm, success: &success);
2151 if (!success)
2152 return false;
2153 std::optional<RegisterInfo> dwarf_reg =
2154 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + Rm);
2155 context.SetRegister(*dwarf_reg);
2156 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindGeneric,
2157 LLDB_REGNUM_GENERIC_RA, reg_value: lr))
2158 return false;
2159 if (!BXWritePC(context, addr: target))
2160 return false;
2161 }
2162 return true;
2163}
2164
2165// Branch and Exchange causes a branch to an address and instruction set
2166// specified by a register.
2167bool EmulateInstructionARM::EmulateBXRm(const uint32_t opcode,
2168 const ARMEncoding encoding) {
2169#if 0
2170 // ARM pseudo code...
2171 if (ConditionPassed())
2172 {
2173 EncodingSpecificOperations();
2174 BXWritePC(R[m]);
2175 }
2176#endif
2177
2178 if (ConditionPassed(opcode)) {
2179 EmulateInstruction::Context context;
2180 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
2181 uint32_t Rm; // the register with the target address
2182 switch (encoding) {
2183 case eEncodingT1:
2184 Rm = Bits32(bits: opcode, msbit: 6, lsbit: 3);
2185 if (InITBlock() && !LastInITBlock())
2186 return false;
2187 break;
2188 case eEncodingA1:
2189 Rm = Bits32(bits: opcode, msbit: 3, lsbit: 0);
2190 break;
2191 default:
2192 return false;
2193 }
2194 bool success = false;
2195 addr_t target = ReadCoreReg(regnum: Rm, success: &success);
2196 if (!success)
2197 return false;
2198
2199 std::optional<RegisterInfo> dwarf_reg =
2200 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + Rm);
2201 context.SetRegister(*dwarf_reg);
2202 if (!BXWritePC(context, addr: target))
2203 return false;
2204 }
2205 return true;
2206}
2207
2208// Branch and Exchange Jazelle attempts to change to Jazelle state. If the
2209// attempt fails, it branches to an address and instruction set specified by a
2210// register as though it were a BX instruction.
2211//
2212// TODO: Emulate Jazelle architecture?
2213// We currently assume that switching to Jazelle state fails, thus
2214// treating BXJ as a BX operation.
2215bool EmulateInstructionARM::EmulateBXJRm(const uint32_t opcode,
2216 const ARMEncoding encoding) {
2217#if 0
2218 // ARM pseudo code...
2219 if (ConditionPassed())
2220 {
2221 EncodingSpecificOperations();
2222 if JMCR.JE == '0' || CurrentInstrSet() == InstrSet_ThumbEE then
2223 BXWritePC(R[m]);
2224 else
2225 if JazelleAcceptsExecution() then
2226 SwitchToJazelleExecution();
2227 else
2228 SUBARCHITECTURE_DEFINED handler call;
2229 }
2230#endif
2231
2232 if (ConditionPassed(opcode)) {
2233 EmulateInstruction::Context context;
2234 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
2235 uint32_t Rm; // the register with the target address
2236 switch (encoding) {
2237 case eEncodingT1:
2238 Rm = Bits32(bits: opcode, msbit: 19, lsbit: 16);
2239 if (BadReg(n: Rm))
2240 return false;
2241 if (InITBlock() && !LastInITBlock())
2242 return false;
2243 break;
2244 case eEncodingA1:
2245 Rm = Bits32(bits: opcode, msbit: 3, lsbit: 0);
2246 if (Rm == 15)
2247 return false;
2248 break;
2249 default:
2250 return false;
2251 }
2252 bool success = false;
2253 addr_t target = ReadCoreReg(regnum: Rm, success: &success);
2254 if (!success)
2255 return false;
2256
2257 std::optional<RegisterInfo> dwarf_reg =
2258 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + Rm);
2259 context.SetRegister(*dwarf_reg);
2260 if (!BXWritePC(context, addr: target))
2261 return false;
2262 }
2263 return true;
2264}
2265
2266// Set r7 to point to some ip offset.
2267// SUB (immediate)
2268bool EmulateInstructionARM::EmulateSUBR7IPImm(const uint32_t opcode,
2269 const ARMEncoding encoding) {
2270#if 0
2271 // ARM pseudo code...
2272 if (ConditionPassed())
2273 {
2274 EncodingSpecificOperations();
2275 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
2276 if d == 15 then // Can only occur for ARM encoding
2277 ALUWritePC(result); // setflags is always FALSE here
2278 else
2279 R[d] = result;
2280 if setflags then
2281 APSR.N = result<31>;
2282 APSR.Z = IsZeroBit(result);
2283 APSR.C = carry;
2284 APSR.V = overflow;
2285 }
2286#endif
2287
2288 if (ConditionPassed(opcode)) {
2289 bool success = false;
2290 const addr_t ip = ReadCoreReg(regnum: 12, success: &success);
2291 if (!success)
2292 return false;
2293 uint32_t imm32;
2294 switch (encoding) {
2295 case eEncodingA1:
2296 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2297 break;
2298 default:
2299 return false;
2300 }
2301 addr_t ip_offset = imm32;
2302 addr_t addr = ip - ip_offset; // the adjusted ip value
2303
2304 EmulateInstruction::Context context;
2305 context.type = EmulateInstruction::eContextRegisterPlusOffset;
2306 std::optional<RegisterInfo> dwarf_reg =
2307 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r12);
2308 context.SetRegisterPlusOffset(base_reg: *dwarf_reg, signed_offset: -ip_offset);
2309
2310 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindDWARF, reg_num: dwarf_r7, reg_value: addr))
2311 return false;
2312 }
2313 return true;
2314}
2315
2316// Set ip to point to some stack offset.
2317// SUB (SP minus immediate)
2318bool EmulateInstructionARM::EmulateSUBIPSPImm(const uint32_t opcode,
2319 const ARMEncoding encoding) {
2320#if 0
2321 // ARM pseudo code...
2322 if (ConditionPassed())
2323 {
2324 EncodingSpecificOperations();
2325 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
2326 if d == 15 then // Can only occur for ARM encoding
2327 ALUWritePC(result); // setflags is always FALSE here
2328 else
2329 R[d] = result;
2330 if setflags then
2331 APSR.N = result<31>;
2332 APSR.Z = IsZeroBit(result);
2333 APSR.C = carry;
2334 APSR.V = overflow;
2335 }
2336#endif
2337
2338 if (ConditionPassed(opcode)) {
2339 bool success = false;
2340 const addr_t sp = ReadCoreReg(SP_REG, success: &success);
2341 if (!success)
2342 return false;
2343 uint32_t imm32;
2344 switch (encoding) {
2345 case eEncodingA1:
2346 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2347 break;
2348 default:
2349 return false;
2350 }
2351 addr_t sp_offset = imm32;
2352 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
2353
2354 EmulateInstruction::Context context;
2355 context.type = EmulateInstruction::eContextRegisterPlusOffset;
2356 std::optional<RegisterInfo> dwarf_reg =
2357 GetRegisterInfo(reg_kind: eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
2358 context.SetRegisterPlusOffset(base_reg: *dwarf_reg, signed_offset: -sp_offset);
2359
2360 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindDWARF, reg_num: dwarf_r12, reg_value: addr))
2361 return false;
2362 }
2363 return true;
2364}
2365
2366// This instruction subtracts an immediate value from the SP value, and writes
2367// the result to the destination register.
2368//
2369// If Rd == 13 => A sub operation to adjust the SP -- allocate space for local
2370// storage.
2371bool EmulateInstructionARM::EmulateSUBSPImm(const uint32_t opcode,
2372 const ARMEncoding encoding) {
2373#if 0
2374 // ARM pseudo code...
2375 if (ConditionPassed())
2376 {
2377 EncodingSpecificOperations();
2378 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
2379 if d == 15 then // Can only occur for ARM encoding
2380 ALUWritePC(result); // setflags is always FALSE here
2381 else
2382 R[d] = result;
2383 if setflags then
2384 APSR.N = result<31>;
2385 APSR.Z = IsZeroBit(result);
2386 APSR.C = carry;
2387 APSR.V = overflow;
2388 }
2389#endif
2390
2391 bool success = false;
2392 if (ConditionPassed(opcode)) {
2393 const addr_t sp = ReadCoreReg(SP_REG, success: &success);
2394 if (!success)
2395 return false;
2396
2397 uint32_t Rd;
2398 bool setflags;
2399 uint32_t imm32;
2400 switch (encoding) {
2401 case eEncodingT1:
2402 Rd = 13;
2403 setflags = false;
2404 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
2405 break;
2406 case eEncodingT2:
2407 Rd = Bits32(bits: opcode, msbit: 11, lsbit: 8);
2408 setflags = BitIsSet(value: opcode, bit: 20);
2409 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
2410 if (Rd == 15 && setflags)
2411 return EmulateCMPImm(opcode, encoding: eEncodingT2);
2412 if (Rd == 15 && !setflags)
2413 return false;
2414 break;
2415 case eEncodingT3:
2416 Rd = Bits32(bits: opcode, msbit: 11, lsbit: 8);
2417 setflags = false;
2418 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
2419 if (Rd == 15)
2420 return false;
2421 break;
2422 case eEncodingA1:
2423 Rd = Bits32(bits: opcode, msbit: 15, lsbit: 12);
2424 setflags = BitIsSet(value: opcode, bit: 20);
2425 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
2426
2427 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
2428 // instructions;
2429 if (Rd == 15 && setflags)
2430 return EmulateSUBSPcLrEtc(opcode, encoding);
2431 break;
2432 default:
2433 return false;
2434 }
2435 AddWithCarryResult res = AddWithCarry(x: sp, y: ~imm32, carry_in: 1);
2436
2437 EmulateInstruction::Context context;
2438 if (Rd == 13) {
2439 uint64_t imm64 = imm32; // Need to expand it to 64 bits before attempting
2440 // to negate it, or the wrong
2441 // value gets passed down to context.SetImmediateSigned.
2442 context.type = EmulateInstruction::eContextAdjustStackPointer;
2443 context.SetImmediateSigned(-imm64); // the stack pointer offset
2444 } else {
2445 context.type = EmulateInstruction::eContextImmediate;
2446 context.SetNoArgs();
2447 }
2448
2449 if (!WriteCoreRegOptionalFlags(context, result: res.result, Rd, setflags,
2450 carry: res.carry_out, overflow: res.overflow))
2451 return false;
2452 }
2453 return true;
2454}
2455
2456// A store operation to the stack that also updates the SP.
2457bool EmulateInstructionARM::EmulateSTRRtSP(const uint32_t opcode,
2458 const ARMEncoding encoding) {
2459#if 0
2460 // ARM pseudo code...
2461 if (ConditionPassed())
2462 {
2463 EncodingSpecificOperations();
2464 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
2465 address = if index then offset_addr else R[n];
2466 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
2467 if wback then R[n] = offset_addr;
2468 }
2469#endif
2470
2471 bool success = false;
2472 if (ConditionPassed(opcode)) {
2473 const uint32_t addr_byte_size = GetAddressByteSize();
2474 const addr_t sp = ReadCoreReg(SP_REG, success: &success);
2475 if (!success)
2476 return false;
2477 uint32_t Rt; // the source register
2478 uint32_t imm12;
2479 uint32_t
2480 Rn; // This function assumes Rn is the SP, but we should verify that.
2481
2482 bool index;
2483 bool add;
2484 bool wback;
2485 switch (encoding) {
2486 case eEncodingA1:
2487 Rt = Bits32(bits: opcode, msbit: 15, lsbit: 12);
2488 imm12 = Bits32(bits: opcode, msbit: 11, lsbit: 0);
2489 Rn = Bits32(bits: opcode, msbit: 19, lsbit: 16);
2490
2491 if (Rn != 13) // 13 is the SP reg on ARM. Verify that Rn == SP.
2492 return false;
2493
2494 index = BitIsSet(value: opcode, bit: 24);
2495 add = BitIsSet(value: opcode, bit: 23);
2496 wback = (BitIsClear(value: opcode, bit: 24) || BitIsSet(value: opcode, bit: 21));
2497
2498 if (wback && ((Rn == 15) || (Rn == Rt)))
2499 return false;
2500 break;
2501 default:
2502 return false;
2503 }
2504 addr_t offset_addr;
2505 if (add)
2506 offset_addr = sp + imm12;
2507 else
2508 offset_addr = sp - imm12;
2509
2510 addr_t addr;
2511 if (index)
2512 addr = offset_addr;
2513 else
2514 addr = sp;
2515
2516 EmulateInstruction::Context context;
2517 context.type = EmulateInstruction::eContextPushRegisterOnStack;
2518 std::optional<RegisterInfo> sp_reg =
2519 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_sp);
2520 std::optional<RegisterInfo> dwarf_reg =
2521 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + Rt);
2522
2523 context.SetRegisterToRegisterPlusOffset(data_reg: *dwarf_reg, base_reg: *sp_reg, offset: addr - sp);
2524 if (Rt != 15) {
2525 uint32_t reg_value = ReadCoreReg(regnum: Rt, success: &success);
2526 if (!success)
2527 return false;
2528 if (!MemUWrite(context, address: addr, data_val: reg_value, size: addr_byte_size))
2529 return false;
2530 } else {
2531 const uint32_t pc = ReadCoreReg(PC_REG, success: &success);
2532 if (!success)
2533 return false;
2534 if (!MemUWrite(context, address: addr, data_val: pc, size: addr_byte_size))
2535 return false;
2536 }
2537
2538 if (wback) {
2539 context.type = EmulateInstruction::eContextAdjustStackPointer;
2540 context.SetImmediateSigned(addr - sp);
2541 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindGeneric,
2542 LLDB_REGNUM_GENERIC_SP, reg_value: offset_addr))
2543 return false;
2544 }
2545 }
2546 return true;
2547}
2548
2549// Vector Push stores multiple extension registers to the stack. It also
2550// updates SP to point to the start of the stored data.
2551bool EmulateInstructionARM::EmulateVPUSH(const uint32_t opcode,
2552 const ARMEncoding encoding) {
2553#if 0
2554 // ARM pseudo code...
2555 if (ConditionPassed())
2556 {
2557 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
2558 address = SP - imm32;
2559 SP = SP - imm32;
2560 if single_regs then
2561 for r = 0 to regs-1
2562 MemA[address,4] = S[d+r]; address = address+4;
2563 else
2564 for r = 0 to regs-1
2565 // Store as two word-aligned words in the correct order for
2566 // current endianness.
2567 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
2568 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
2569 address = address+8;
2570 }
2571#endif
2572
2573 bool success = false;
2574 if (ConditionPassed(opcode)) {
2575 const uint32_t addr_byte_size = GetAddressByteSize();
2576 const addr_t sp = ReadCoreReg(SP_REG, success: &success);
2577 if (!success)
2578 return false;
2579 bool single_regs;
2580 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
2581 uint32_t imm32; // stack offset
2582 uint32_t regs; // number of registers
2583 switch (encoding) {
2584 case eEncodingT1:
2585 case eEncodingA1:
2586 single_regs = false;
2587 d = Bit32(bits: opcode, bit: 22) << 4 | Bits32(bits: opcode, msbit: 15, lsbit: 12);
2588 imm32 = Bits32(bits: opcode, msbit: 7, lsbit: 0) * addr_byte_size;
2589 // If UInt(imm8) is odd, see "FSTMX".
2590 regs = Bits32(bits: opcode, msbit: 7, lsbit: 0) / 2;
2591 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
2592 if (regs == 0 || regs > 16 || (d + regs) > 32)
2593 return false;
2594 break;
2595 case eEncodingT2:
2596 case eEncodingA2:
2597 single_regs = true;
2598 d = Bits32(bits: opcode, msbit: 15, lsbit: 12) << 1 | Bit32(bits: opcode, bit: 22);
2599 imm32 = Bits32(bits: opcode, msbit: 7, lsbit: 0) * addr_byte_size;
2600 regs = Bits32(bits: opcode, msbit: 7, lsbit: 0);
2601 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
2602 if (regs == 0 || regs > 16 || (d + regs) > 32)
2603 return false;
2604 break;
2605 default:
2606 return false;
2607 }
2608 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
2609 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
2610 addr_t sp_offset = imm32;
2611 addr_t addr = sp - sp_offset;
2612 uint32_t i;
2613
2614 EmulateInstruction::Context context;
2615 context.type = EmulateInstruction::eContextPushRegisterOnStack;
2616
2617 std::optional<RegisterInfo> sp_reg =
2618 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_sp);
2619 for (i = 0; i < regs; ++i) {
2620 std::optional<RegisterInfo> dwarf_reg =
2621 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: start_reg + d + i);
2622 context.SetRegisterToRegisterPlusOffset(data_reg: *dwarf_reg, base_reg: *sp_reg, offset: addr - sp);
2623 // uint64_t to accommodate 64-bit registers.
2624 uint64_t reg_value = ReadRegisterUnsigned(reg_info: *dwarf_reg, fail_value: 0, success_ptr: &success);
2625 if (!success)
2626 return false;
2627 if (!MemAWrite(context, address: addr, data_val: reg_value, size: reg_byte_size))
2628 return false;
2629 addr += reg_byte_size;
2630 }
2631
2632 context.type = EmulateInstruction::eContextAdjustStackPointer;
2633 context.SetImmediateSigned(-sp_offset);
2634
2635 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindGeneric,
2636 LLDB_REGNUM_GENERIC_SP, reg_value: sp - sp_offset))
2637 return false;
2638 }
2639 return true;
2640}
2641
2642// Vector Pop loads multiple extension registers from the stack. It also
2643// updates SP to point just above the loaded data.
2644bool EmulateInstructionARM::EmulateVPOP(const uint32_t opcode,
2645 const ARMEncoding encoding) {
2646#if 0
2647 // ARM pseudo code...
2648 if (ConditionPassed())
2649 {
2650 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
2651 address = SP;
2652 SP = SP + imm32;
2653 if single_regs then
2654 for r = 0 to regs-1
2655 S[d+r] = MemA[address,4]; address = address+4;
2656 else
2657 for r = 0 to regs-1
2658 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
2659 // Combine the word-aligned words in the correct order for
2660 // current endianness.
2661 D[d+r] = if BigEndian() then word1:word2 else word2:word1;
2662 }
2663#endif
2664
2665 bool success = false;
2666 if (ConditionPassed(opcode)) {
2667 const uint32_t addr_byte_size = GetAddressByteSize();
2668 const addr_t sp = ReadCoreReg(SP_REG, success: &success);
2669 if (!success)
2670 return false;
2671 bool single_regs;
2672 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register
2673 uint32_t imm32; // stack offset
2674 uint32_t regs; // number of registers
2675 switch (encoding) {
2676 case eEncodingT1:
2677 case eEncodingA1:
2678 single_regs = false;
2679 d = Bit32(bits: opcode, bit: 22) << 4 | Bits32(bits: opcode, msbit: 15, lsbit: 12);
2680 imm32 = Bits32(bits: opcode, msbit: 7, lsbit: 0) * addr_byte_size;
2681 // If UInt(imm8) is odd, see "FLDMX".
2682 regs = Bits32(bits: opcode, msbit: 7, lsbit: 0) / 2;
2683 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
2684 if (regs == 0 || regs > 16 || (d + regs) > 32)
2685 return false;
2686 break;
2687 case eEncodingT2:
2688 case eEncodingA2:
2689 single_regs = true;
2690 d = Bits32(bits: opcode, msbit: 15, lsbit: 12) << 1 | Bit32(bits: opcode, bit: 22);
2691 imm32 = Bits32(bits: opcode, msbit: 7, lsbit: 0) * addr_byte_size;
2692 regs = Bits32(bits: opcode, msbit: 7, lsbit: 0);
2693 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
2694 if (regs == 0 || regs > 16 || (d + regs) > 32)
2695 return false;
2696 break;
2697 default:
2698 return false;
2699 }
2700 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
2701 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
2702 addr_t sp_offset = imm32;
2703 addr_t addr = sp;
2704 uint32_t i;
2705 uint64_t data; // uint64_t to accommodate 64-bit registers.
2706
2707 EmulateInstruction::Context context;
2708 context.type = EmulateInstruction::eContextPopRegisterOffStack;
2709
2710 for (i = 0; i < regs; ++i) {
2711 std::optional<RegisterInfo> dwarf_reg =
2712 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: start_reg + d + i);
2713 context.SetAddress(addr);
2714 data = MemARead(context, address: addr, size: reg_byte_size, fail_value: 0, success_ptr: &success);
2715 if (!success)
2716 return false;
2717 if (!WriteRegisterUnsigned(context, reg_info: *dwarf_reg, reg_value: data))
2718 return false;
2719 addr += reg_byte_size;
2720 }
2721
2722 context.type = EmulateInstruction::eContextAdjustStackPointer;
2723 context.SetImmediateSigned(sp_offset);
2724
2725 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindGeneric,
2726 LLDB_REGNUM_GENERIC_SP, reg_value: sp + sp_offset))
2727 return false;
2728 }
2729 return true;
2730}
2731
2732// SVC (previously SWI)
2733bool EmulateInstructionARM::EmulateSVC(const uint32_t opcode,
2734 const ARMEncoding encoding) {
2735#if 0
2736 // ARM pseudo code...
2737 if (ConditionPassed())
2738 {
2739 EncodingSpecificOperations();
2740 CallSupervisor();
2741 }
2742#endif
2743
2744 bool success = false;
2745
2746 if (ConditionPassed(opcode)) {
2747 const uint32_t pc = ReadCoreReg(PC_REG, success: &success);
2748 addr_t lr; // next instruction address
2749 if (!success)
2750 return false;
2751 uint32_t imm32; // the immediate constant
2752 uint32_t mode; // ARM or Thumb mode
2753 switch (encoding) {
2754 case eEncodingT1:
2755 lr = (pc + 2) | 1u; // return address
2756 imm32 = Bits32(bits: opcode, msbit: 7, lsbit: 0);
2757 mode = eModeThumb;
2758 break;
2759 case eEncodingA1:
2760 lr = pc + 4; // return address
2761 imm32 = Bits32(bits: opcode, msbit: 23, lsbit: 0);
2762 mode = eModeARM;
2763 break;
2764 default:
2765 return false;
2766 }
2767
2768 EmulateInstruction::Context context;
2769 context.type = EmulateInstruction::eContextSupervisorCall;
2770 context.SetISAAndImmediate(isa: mode, data: imm32);
2771 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindGeneric,
2772 LLDB_REGNUM_GENERIC_RA, reg_value: lr))
2773 return false;
2774 }
2775 return true;
2776}
2777
2778// If Then makes up to four following instructions (the IT block) conditional.
2779bool EmulateInstructionARM::EmulateIT(const uint32_t opcode,
2780 const ARMEncoding encoding) {
2781#if 0
2782 // ARM pseudo code...
2783 EncodingSpecificOperations();
2784 ITSTATE.IT<7:0> = firstcond:mask;
2785#endif
2786
2787 m_it_session.InitIT(bits7_0: Bits32(bits: opcode, msbit: 7, lsbit: 0));
2788 return true;
2789}
2790
2791bool EmulateInstructionARM::EmulateNop(const uint32_t opcode,
2792 const ARMEncoding encoding) {
2793 // NOP, nothing to do...
2794 return true;
2795}
2796
2797// Branch causes a branch to a target address.
2798bool EmulateInstructionARM::EmulateB(const uint32_t opcode,
2799 const ARMEncoding encoding) {
2800#if 0
2801 // ARM pseudo code...
2802 if (ConditionPassed())
2803 {
2804 EncodingSpecificOperations();
2805 BranchWritePC(PC + imm32);
2806 }
2807#endif
2808
2809 bool success = false;
2810
2811 if (ConditionPassed(opcode)) {
2812 EmulateInstruction::Context context;
2813 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
2814 const uint32_t pc = ReadCoreReg(PC_REG, success: &success);
2815 if (!success)
2816 return false;
2817 addr_t target; // target address
2818 int32_t imm32; // PC-relative offset
2819 switch (encoding) {
2820 case eEncodingT1:
2821 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
2822 imm32 = llvm::SignExtend32<9>(X: Bits32(bits: opcode, msbit: 7, lsbit: 0) << 1);
2823 target = pc + imm32;
2824 context.SetISAAndImmediateSigned(isa: eModeThumb, data: 4 + imm32);
2825 break;
2826 case eEncodingT2:
2827 imm32 = llvm::SignExtend32<12>(X: Bits32(bits: opcode, msbit: 10, lsbit: 0) << 1);
2828 target = pc + imm32;
2829 context.SetISAAndImmediateSigned(isa: eModeThumb, data: 4 + imm32);
2830 break;
2831 case eEncodingT3:
2832 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
2833 {
2834 if (Bits32(bits: opcode, msbit: 25, lsbit: 23) == 7)
2835 return false; // See Branches and miscellaneous control on page
2836 // A6-235.
2837
2838 uint32_t S = Bit32(bits: opcode, bit: 26);
2839 uint32_t imm6 = Bits32(bits: opcode, msbit: 21, lsbit: 16);
2840 uint32_t J1 = Bit32(bits: opcode, bit: 13);
2841 uint32_t J2 = Bit32(bits: opcode, bit: 11);
2842 uint32_t imm11 = Bits32(bits: opcode, msbit: 10, lsbit: 0);
2843 uint32_t imm21 =
2844 (S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) | (imm11 << 1);
2845 imm32 = llvm::SignExtend32<21>(X: imm21);
2846 target = pc + imm32;
2847 context.SetISAAndImmediateSigned(isa: eModeThumb, data: 4 + imm32);
2848 break;
2849 }
2850 case eEncodingT4: {
2851 uint32_t S = Bit32(bits: opcode, bit: 26);
2852 uint32_t imm10 = Bits32(bits: opcode, msbit: 25, lsbit: 16);
2853 uint32_t J1 = Bit32(bits: opcode, bit: 13);
2854 uint32_t J2 = Bit32(bits: opcode, bit: 11);
2855 uint32_t imm11 = Bits32(bits: opcode, msbit: 10, lsbit: 0);
2856 uint32_t I1 = !(J1 ^ S);
2857 uint32_t I2 = !(J2 ^ S);
2858 uint32_t imm25 =
2859 (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
2860 imm32 = llvm::SignExtend32<25>(X: imm25);
2861 target = pc + imm32;
2862 context.SetISAAndImmediateSigned(isa: eModeThumb, data: 4 + imm32);
2863 break;
2864 }
2865 case eEncodingA1:
2866 imm32 = llvm::SignExtend32<26>(X: Bits32(bits: opcode, msbit: 23, lsbit: 0) << 2);
2867 target = pc + imm32;
2868 context.SetISAAndImmediateSigned(isa: eModeARM, data: 8 + imm32);
2869 break;
2870 default:
2871 return false;
2872 }
2873 if (!BranchWritePC(context, addr: target))
2874 return false;
2875 }
2876 return true;
2877}
2878
2879// Compare and Branch on Nonzero and Compare and Branch on Zero compare the
2880// value in a register with zero and conditionally branch forward a constant
2881// value. They do not affect the condition flags. CBNZ, CBZ
2882bool EmulateInstructionARM::EmulateCB(const uint32_t opcode,
2883 const ARMEncoding encoding) {
2884#if 0
2885 // ARM pseudo code...
2886 EncodingSpecificOperations();
2887 if nonzero ^ IsZero(R[n]) then
2888 BranchWritePC(PC + imm32);
2889#endif
2890
2891 bool success = false;
2892
2893 // Read the register value from the operand register Rn.
2894 uint32_t reg_val = ReadCoreReg(regnum: Bits32(bits: opcode, msbit: 2, lsbit: 0), success: &success);
2895 if (!success)
2896 return false;
2897
2898 EmulateInstruction::Context context;
2899 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
2900 const uint32_t pc = ReadCoreReg(PC_REG, success: &success);
2901 if (!success)
2902 return false;
2903
2904 addr_t target; // target address
2905 uint32_t imm32; // PC-relative offset to branch forward
2906 bool nonzero;
2907 switch (encoding) {
2908 case eEncodingT1:
2909 imm32 = Bit32(bits: opcode, bit: 9) << 6 | Bits32(bits: opcode, msbit: 7, lsbit: 3) << 1;
2910 nonzero = BitIsSet(value: opcode, bit: 11);
2911 target = pc + imm32;
2912 context.SetISAAndImmediateSigned(isa: eModeThumb, data: 4 + imm32);
2913 break;
2914 default:
2915 return false;
2916 }
2917 if (m_ignore_conditions || (nonzero ^ (reg_val == 0)))
2918 if (!BranchWritePC(context, addr: target))
2919 return false;
2920
2921 return true;
2922}
2923
2924// Table Branch Byte causes a PC-relative forward branch using a table of
2925// single byte offsets.
2926// A base register provides a pointer to the table, and a second register
2927// supplies an index into the table.
2928// The branch length is twice the value of the byte returned from the table.
2929//
2930// Table Branch Halfword causes a PC-relative forward branch using a table of
2931// single halfword offsets.
2932// A base register provides a pointer to the table, and a second register
2933// supplies an index into the table.
2934// The branch length is twice the value of the halfword returned from the
2935// table. TBB, TBH
2936bool EmulateInstructionARM::EmulateTB(const uint32_t opcode,
2937 const ARMEncoding encoding) {
2938#if 0
2939 // ARM pseudo code...
2940 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
2941 if is_tbh then
2942 halfwords = UInt(MemU[R[n]+LSL(R[m],1), 2]);
2943 else
2944 halfwords = UInt(MemU[R[n]+R[m], 1]);
2945 BranchWritePC(PC + 2*halfwords);
2946#endif
2947
2948 bool success = false;
2949
2950 if (ConditionPassed(opcode)) {
2951 uint32_t Rn; // the base register which contains the address of the table of
2952 // branch lengths
2953 uint32_t Rm; // the index register which contains an integer pointing to a
2954 // byte/halfword in the table
2955 bool is_tbh; // true if table branch halfword
2956 switch (encoding) {
2957 case eEncodingT1:
2958 Rn = Bits32(bits: opcode, msbit: 19, lsbit: 16);
2959 Rm = Bits32(bits: opcode, msbit: 3, lsbit: 0);
2960 is_tbh = BitIsSet(value: opcode, bit: 4);
2961 if (Rn == 13 || BadReg(n: Rm))
2962 return false;
2963 if (InITBlock() && !LastInITBlock())
2964 return false;
2965 break;
2966 default:
2967 return false;
2968 }
2969
2970 // Read the address of the table from the operand register Rn. The PC can
2971 // be used, in which case the table immediately follows this instruction.
2972 uint32_t base = ReadCoreReg(regnum: Rn, success: &success);
2973 if (!success)
2974 return false;
2975
2976 // the table index
2977 uint32_t index = ReadCoreReg(regnum: Rm, success: &success);
2978 if (!success)
2979 return false;
2980
2981 // the offsetted table address
2982 addr_t addr = base + (is_tbh ? index * 2 : index);
2983
2984 // PC-relative offset to branch forward
2985 EmulateInstruction::Context context;
2986 context.type = EmulateInstruction::eContextTableBranchReadMemory;
2987 uint32_t offset = MemURead(context, address: addr, size: is_tbh ? 2 : 1, fail_value: 0, success_ptr: &success) * 2;
2988 if (!success)
2989 return false;
2990
2991 const uint32_t pc = ReadCoreReg(PC_REG, success: &success);
2992 if (!success)
2993 return false;
2994
2995 // target address
2996 addr_t target = pc + offset;
2997 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
2998 context.SetISAAndImmediateSigned(isa: eModeThumb, data: 4 + offset);
2999
3000 if (!BranchWritePC(context, addr: target))
3001 return false;
3002 }
3003
3004 return true;
3005}
3006
3007// This instruction adds an immediate value to a register value, and writes the
3008// result to the destination register. It can optionally update the condition
3009// flags based on the result.
3010bool EmulateInstructionARM::EmulateADDImmThumb(const uint32_t opcode,
3011 const ARMEncoding encoding) {
3012#if 0
3013 if ConditionPassed() then
3014 EncodingSpecificOperations();
3015 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
3016 R[d] = result;
3017 if setflags then
3018 APSR.N = result<31>;
3019 APSR.Z = IsZeroBit(result);
3020 APSR.C = carry;
3021 APSR.V = overflow;
3022#endif
3023
3024 bool success = false;
3025
3026 if (ConditionPassed(opcode)) {
3027 uint32_t d;
3028 uint32_t n;
3029 bool setflags;
3030 uint32_t imm32;
3031 uint32_t carry_out;
3032
3033 // EncodingSpecificOperations();
3034 switch (encoding) {
3035 case eEncodingT1:
3036 // d = UInt(Rd); n = UInt(Rn); setflags = !InITBlock(); imm32 =
3037 // ZeroExtend(imm3, 32);
3038 d = Bits32(bits: opcode, msbit: 2, lsbit: 0);
3039 n = Bits32(bits: opcode, msbit: 5, lsbit: 3);
3040 setflags = !InITBlock();
3041 imm32 = Bits32(bits: opcode, msbit: 8, lsbit: 6);
3042
3043 break;
3044
3045 case eEncodingT2:
3046 // d = UInt(Rdn); n = UInt(Rdn); setflags = !InITBlock(); imm32 =
3047 // ZeroExtend(imm8, 32);
3048 d = Bits32(bits: opcode, msbit: 10, lsbit: 8);
3049 n = Bits32(bits: opcode, msbit: 10, lsbit: 8);
3050 setflags = !InITBlock();
3051 imm32 = Bits32(bits: opcode, msbit: 7, lsbit: 0);
3052
3053 break;
3054
3055 case eEncodingT3:
3056 // if Rd == '1111' && S == '1' then SEE CMN (immediate);
3057 // d = UInt(Rd); n = UInt(Rn); setflags = (S == '1'); imm32 =
3058 // ThumbExpandImm(i:imm3:imm8);
3059 d = Bits32(bits: opcode, msbit: 11, lsbit: 8);
3060 n = Bits32(bits: opcode, msbit: 19, lsbit: 16);
3061 setflags = BitIsSet(value: opcode, bit: 20);
3062 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry_out);
3063
3064 // if Rn == '1101' then SEE ADD (SP plus immediate);
3065 if (n == 13)
3066 return EmulateADDSPImm(opcode, encoding: eEncodingT3);
3067
3068 // if BadReg(d) || n == 15 then UNPREDICTABLE;
3069 if (BadReg(n: d) || (n == 15))
3070 return false;
3071
3072 break;
3073
3074 case eEncodingT4: {
3075 // if Rn == '1111' then SEE ADR;
3076 // d = UInt(Rd); n = UInt(Rn); setflags = FALSE; imm32 =
3077 // ZeroExtend(i:imm3:imm8, 32);
3078 d = Bits32(bits: opcode, msbit: 11, lsbit: 8);
3079 n = Bits32(bits: opcode, msbit: 19, lsbit: 16);
3080 setflags = false;
3081 uint32_t i = Bit32(bits: opcode, bit: 26);
3082 uint32_t imm3 = Bits32(bits: opcode, msbit: 14, lsbit: 12);
3083 uint32_t imm8 = Bits32(bits: opcode, msbit: 7, lsbit: 0);
3084 imm32 = (i << 11) | (imm3 << 8) | imm8;
3085
3086 // if Rn == '1101' then SEE ADD (SP plus immediate);
3087 if (n == 13)
3088 return EmulateADDSPImm(opcode, encoding: eEncodingT4);
3089
3090 // if BadReg(d) then UNPREDICTABLE;
3091 if (BadReg(n: d))
3092 return false;
3093
3094 break;
3095 }
3096
3097 default:
3098 return false;
3099 }
3100
3101 uint64_t Rn =
3102 ReadRegisterUnsigned(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n, fail_value: 0, success_ptr: &success);
3103 if (!success)
3104 return false;
3105
3106 //(result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
3107 AddWithCarryResult res = AddWithCarry(x: Rn, y: imm32, carry_in: 0);
3108
3109 std::optional<RegisterInfo> reg_n =
3110 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n);
3111 EmulateInstruction::Context context;
3112 context.type = eContextArithmetic;
3113 context.SetRegisterPlusOffset(base_reg: *reg_n, signed_offset: imm32);
3114
3115 // R[d] = result;
3116 // if setflags then
3117 // APSR.N = result<31>;
3118 // APSR.Z = IsZeroBit(result);
3119 // APSR.C = carry;
3120 // APSR.V = overflow;
3121 if (!WriteCoreRegOptionalFlags(context, result: res.result, Rd: d, setflags,
3122 carry: res.carry_out, overflow: res.overflow))
3123 return false;
3124 }
3125 return true;
3126}
3127
3128// This instruction adds an immediate value to a register value, and writes the
3129// result to the destination register. It can optionally update the condition
3130// flags based on the result.
3131bool EmulateInstructionARM::EmulateADDImmARM(const uint32_t opcode,
3132 const ARMEncoding encoding) {
3133#if 0
3134 // ARM pseudo code...
3135 if ConditionPassed() then
3136 EncodingSpecificOperations();
3137 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
3138 if d == 15 then
3139 ALUWritePC(result); // setflags is always FALSE here
3140 else
3141 R[d] = result;
3142 if setflags then
3143 APSR.N = result<31>;
3144 APSR.Z = IsZeroBit(result);
3145 APSR.C = carry;
3146 APSR.V = overflow;
3147#endif
3148
3149 bool success = false;
3150
3151 if (ConditionPassed(opcode)) {
3152 uint32_t Rd, Rn;
3153 uint32_t
3154 imm32; // the immediate value to be added to the value obtained from Rn
3155 bool setflags;
3156 switch (encoding) {
3157 case eEncodingA1:
3158 Rd = Bits32(bits: opcode, msbit: 15, lsbit: 12);
3159 Rn = Bits32(bits: opcode, msbit: 19, lsbit: 16);
3160 setflags = BitIsSet(value: opcode, bit: 20);
3161 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
3162 break;
3163 default:
3164 return false;
3165 }
3166
3167 // Read the first operand.
3168 uint32_t val1 = ReadCoreReg(regnum: Rn, success: &success);
3169 if (!success)
3170 return false;
3171
3172 AddWithCarryResult res = AddWithCarry(x: val1, y: imm32, carry_in: 0);
3173
3174 EmulateInstruction::Context context;
3175 if (Rd == 13)
3176 context.type = EmulateInstruction::eContextAdjustStackPointer;
3177 else if (Rd == GetFramePointerRegisterNumber())
3178 context.type = EmulateInstruction::eContextSetFramePointer;
3179 else
3180 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3181
3182 std::optional<RegisterInfo> dwarf_reg =
3183 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: Rn);
3184 context.SetRegisterPlusOffset(base_reg: *dwarf_reg, signed_offset: imm32);
3185
3186 if (!WriteCoreRegOptionalFlags(context, result: res.result, Rd, setflags,
3187 carry: res.carry_out, overflow: res.overflow))
3188 return false;
3189 }
3190 return true;
3191}
3192
3193// This instruction adds a register value and an optionally-shifted register
3194// value, and writes the result to the destination register. It can optionally
3195// update the condition flags based on the result.
3196bool EmulateInstructionARM::EmulateADDReg(const uint32_t opcode,
3197 const ARMEncoding encoding) {
3198#if 0
3199 // ARM pseudo code...
3200 if ConditionPassed() then
3201 EncodingSpecificOperations();
3202 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
3203 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
3204 if d == 15 then
3205 ALUWritePC(result); // setflags is always FALSE here
3206 else
3207 R[d] = result;
3208 if setflags then
3209 APSR.N = result<31>;
3210 APSR.Z = IsZeroBit(result);
3211 APSR.C = carry;
3212 APSR.V = overflow;
3213#endif
3214
3215 bool success = false;
3216
3217 if (ConditionPassed(opcode)) {
3218 uint32_t Rd, Rn, Rm;
3219 ARM_ShifterType shift_t;
3220 uint32_t shift_n; // the shift applied to the value read from Rm
3221 bool setflags;
3222 switch (encoding) {
3223 case eEncodingT1:
3224 Rd = Bits32(bits: opcode, msbit: 2, lsbit: 0);
3225 Rn = Bits32(bits: opcode, msbit: 5, lsbit: 3);
3226 Rm = Bits32(bits: opcode, msbit: 8, lsbit: 6);
3227 setflags = !InITBlock();
3228 shift_t = SRType_LSL;
3229 shift_n = 0;
3230 break;
3231 case eEncodingT2:
3232 Rd = Rn = Bit32(bits: opcode, bit: 7) << 3 | Bits32(bits: opcode, msbit: 2, lsbit: 0);
3233 Rm = Bits32(bits: opcode, msbit: 6, lsbit: 3);
3234 setflags = false;
3235 shift_t = SRType_LSL;
3236 shift_n = 0;
3237 if (Rn == 15 && Rm == 15)
3238 return false;
3239 if (Rd == 15 && InITBlock() && !LastInITBlock())
3240 return false;
3241 break;
3242 case eEncodingA1:
3243 Rd = Bits32(bits: opcode, msbit: 15, lsbit: 12);
3244 Rn = Bits32(bits: opcode, msbit: 19, lsbit: 16);
3245 Rm = Bits32(bits: opcode, msbit: 3, lsbit: 0);
3246 setflags = BitIsSet(value: opcode, bit: 20);
3247 shift_n = DecodeImmShiftARM(opcode, shift_t);
3248 break;
3249 default:
3250 return false;
3251 }
3252
3253 // Read the first operand.
3254 uint32_t val1 = ReadCoreReg(regnum: Rn, success: &success);
3255 if (!success)
3256 return false;
3257
3258 // Read the second operand.
3259 uint32_t val2 = ReadCoreReg(regnum: Rm, success: &success);
3260 if (!success)
3261 return false;
3262
3263 uint32_t shifted = Shift(value: val2, type: shift_t, amount: shift_n, APSR_C, success: &success);
3264 if (!success)
3265 return false;
3266 AddWithCarryResult res = AddWithCarry(x: val1, y: shifted, carry_in: 0);
3267
3268 EmulateInstruction::Context context;
3269 context.type = eContextArithmetic;
3270 std::optional<RegisterInfo> op1_reg =
3271 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + Rn);
3272 std::optional<RegisterInfo> op2_reg =
3273 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + Rm);
3274 context.SetRegisterRegisterOperands(op1_reg: *op1_reg, op2_reg: *op2_reg);
3275
3276 if (!WriteCoreRegOptionalFlags(context, result: res.result, Rd, setflags,
3277 carry: res.carry_out, overflow: res.overflow))
3278 return false;
3279 }
3280 return true;
3281}
3282
3283// Compare Negative (immediate) adds a register value and an immediate value.
3284// It updates the condition flags based on the result, and discards the result.
3285bool EmulateInstructionARM::EmulateCMNImm(const uint32_t opcode,
3286 const ARMEncoding encoding) {
3287#if 0
3288 // ARM pseudo code...
3289 if ConditionPassed() then
3290 EncodingSpecificOperations();
3291 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
3292 APSR.N = result<31>;
3293 APSR.Z = IsZeroBit(result);
3294 APSR.C = carry;
3295 APSR.V = overflow;
3296#endif
3297
3298 bool success = false;
3299
3300 uint32_t Rn; // the first operand
3301 uint32_t imm32; // the immediate value to be compared with
3302 switch (encoding) {
3303 case eEncodingT1:
3304 Rn = Bits32(bits: opcode, msbit: 19, lsbit: 16);
3305 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
3306 if (Rn == 15)
3307 return false;
3308 break;
3309 case eEncodingA1:
3310 Rn = Bits32(bits: opcode, msbit: 19, lsbit: 16);
3311 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
3312 break;
3313 default:
3314 return false;
3315 }
3316 // Read the register value from the operand register Rn.
3317 uint32_t reg_val = ReadCoreReg(regnum: Rn, success: &success);
3318 if (!success)
3319 return false;
3320
3321 AddWithCarryResult res = AddWithCarry(x: reg_val, y: imm32, carry_in: 0);
3322
3323 EmulateInstruction::Context context;
3324 context.type = EmulateInstruction::eContextImmediate;
3325 context.SetNoArgs();
3326 return WriteFlags(context, result: res.result, carry: res.carry_out, overflow: res.overflow);
3327}
3328
3329// Compare Negative (register) adds a register value and an optionally-shifted
3330// register value. It updates the condition flags based on the result, and
3331// discards the result.
3332bool EmulateInstructionARM::EmulateCMNReg(const uint32_t opcode,
3333 const ARMEncoding encoding) {
3334#if 0
3335 // ARM pseudo code...
3336 if ConditionPassed() then
3337 EncodingSpecificOperations();
3338 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
3339 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
3340 APSR.N = result<31>;
3341 APSR.Z = IsZeroBit(result);
3342 APSR.C = carry;
3343 APSR.V = overflow;
3344#endif
3345
3346 bool success = false;
3347
3348 uint32_t Rn; // the first operand
3349 uint32_t Rm; // the second operand
3350 ARM_ShifterType shift_t;
3351 uint32_t shift_n; // the shift applied to the value read from Rm
3352 switch (encoding) {
3353 case eEncodingT1:
3354 Rn = Bits32(bits: opcode, msbit: 2, lsbit: 0);
3355 Rm = Bits32(bits: opcode, msbit: 5, lsbit: 3);
3356 shift_t = SRType_LSL;
3357 shift_n = 0;
3358 break;
3359 case eEncodingT2:
3360 Rn = Bits32(bits: opcode, msbit: 19, lsbit: 16);
3361 Rm = Bits32(bits: opcode, msbit: 3, lsbit: 0);
3362 shift_n = DecodeImmShiftThumb(opcode, shift_t);
3363 // if n == 15 || BadReg(m) then UNPREDICTABLE;
3364 if (Rn == 15 || BadReg(n: Rm))
3365 return false;
3366 break;
3367 case eEncodingA1:
3368 Rn = Bits32(bits: opcode, msbit: 19, lsbit: 16);
3369 Rm = Bits32(bits: opcode, msbit: 3, lsbit: 0);
3370 shift_n = DecodeImmShiftARM(opcode, shift_t);
3371 break;
3372 default:
3373 return false;
3374 }
3375 // Read the register value from register Rn.
3376 uint32_t val1 = ReadCoreReg(regnum: Rn, success: &success);
3377 if (!success)
3378 return false;
3379
3380 // Read the register value from register Rm.
3381 uint32_t val2 = ReadCoreReg(regnum: Rm, success: &success);
3382 if (!success)
3383 return false;
3384
3385 uint32_t shifted = Shift(value: val2, type: shift_t, amount: shift_n, APSR_C, success: &success);
3386 if (!success)
3387 return false;
3388 AddWithCarryResult res = AddWithCarry(x: val1, y: shifted, carry_in: 0);
3389
3390 EmulateInstruction::Context context;
3391 context.type = EmulateInstruction::eContextImmediate;
3392 context.SetNoArgs();
3393 return WriteFlags(context, result: res.result, carry: res.carry_out, overflow: res.overflow);
3394}
3395
3396// Compare (immediate) subtracts an immediate value from a register value. It
3397// updates the condition flags based on the result, and discards the result.
3398bool EmulateInstructionARM::EmulateCMPImm(const uint32_t opcode,
3399 const ARMEncoding encoding) {
3400#if 0
3401 // ARM pseudo code...
3402 if ConditionPassed() then
3403 EncodingSpecificOperations();
3404 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
3405 APSR.N = result<31>;
3406 APSR.Z = IsZeroBit(result);
3407 APSR.C = carry;
3408 APSR.V = overflow;
3409#endif
3410
3411 bool success = false;
3412
3413 uint32_t Rn; // the first operand
3414 uint32_t imm32; // the immediate value to be compared with
3415 switch (encoding) {
3416 case eEncodingT1:
3417 Rn = Bits32(bits: opcode, msbit: 10, lsbit: 8);
3418 imm32 = Bits32(bits: opcode, msbit: 7, lsbit: 0);
3419 break;
3420 case eEncodingT2:
3421 Rn = Bits32(bits: opcode, msbit: 19, lsbit: 16);
3422 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
3423 if (Rn == 15)
3424 return false;
3425 break;
3426 case eEncodingA1:
3427 Rn = Bits32(bits: opcode, msbit: 19, lsbit: 16);
3428 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
3429 break;
3430 default:
3431 return false;
3432 }
3433 // Read the register value from the operand register Rn.
3434 uint32_t reg_val = ReadCoreReg(regnum: Rn, success: &success);
3435 if (!success)
3436 return false;
3437
3438 AddWithCarryResult res = AddWithCarry(x: reg_val, y: ~imm32, carry_in: 1);
3439
3440 EmulateInstruction::Context context;
3441 context.type = EmulateInstruction::eContextImmediate;
3442 context.SetNoArgs();
3443 return WriteFlags(context, result: res.result, carry: res.carry_out, overflow: res.overflow);
3444}
3445
3446// Compare (register) subtracts an optionally-shifted register value from a
3447// register value. It updates the condition flags based on the result, and
3448// discards the result.
3449bool EmulateInstructionARM::EmulateCMPReg(const uint32_t opcode,
3450 const ARMEncoding encoding) {
3451#if 0
3452 // ARM pseudo code...
3453 if ConditionPassed() then
3454 EncodingSpecificOperations();
3455 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
3456 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');
3457 APSR.N = result<31>;
3458 APSR.Z = IsZeroBit(result);
3459 APSR.C = carry;
3460 APSR.V = overflow;
3461#endif
3462
3463 bool success = false;
3464
3465 uint32_t Rn; // the first operand
3466 uint32_t Rm; // the second operand
3467 ARM_ShifterType shift_t;
3468 uint32_t shift_n; // the shift applied to the value read from Rm
3469 switch (encoding) {
3470 case eEncodingT1:
3471 Rn = Bits32(bits: opcode, msbit: 2, lsbit: 0);
3472 Rm = Bits32(bits: opcode, msbit: 5, lsbit: 3);
3473 shift_t = SRType_LSL;
3474 shift_n = 0;
3475 break;
3476 case eEncodingT2:
3477 Rn = Bit32(bits: opcode, bit: 7) << 3 | Bits32(bits: opcode, msbit: 2, lsbit: 0);
3478 Rm = Bits32(bits: opcode, msbit: 6, lsbit: 3);
3479 shift_t = SRType_LSL;
3480 shift_n = 0;
3481 if (Rn < 8 && Rm < 8)
3482 return false;
3483 if (Rn == 15 || Rm == 15)
3484 return false;
3485 break;
3486 case eEncodingT3:
3487 Rn = Bits32(bits: opcode, msbit: 19, lsbit: 16);
3488 Rm = Bits32(bits: opcode, msbit: 3, lsbit: 0);
3489 shift_n = DecodeImmShiftThumb(opcode, shift_t);
3490 if (Rn == 15 || BadReg(n: Rm))
3491 return false;
3492 break;
3493 case eEncodingA1:
3494 Rn = Bits32(bits: opcode, msbit: 19, lsbit: 16);
3495 Rm = Bits32(bits: opcode, msbit: 3, lsbit: 0);
3496 shift_n = DecodeImmShiftARM(opcode, shift_t);
3497 break;
3498 default:
3499 return false;
3500 }
3501 // Read the register value from register Rn.
3502 uint32_t val1 = ReadCoreReg(regnum: Rn, success: &success);
3503 if (!success)
3504 return false;
3505
3506 // Read the register value from register Rm.
3507 uint32_t val2 = ReadCoreReg(regnum: Rm, success: &success);
3508 if (!success)
3509 return false;
3510
3511 uint32_t shifted = Shift(value: val2, type: shift_t, amount: shift_n, APSR_C, success: &success);
3512 if (!success)
3513 return false;
3514 AddWithCarryResult res = AddWithCarry(x: val1, y: ~shifted, carry_in: 1);
3515
3516 EmulateInstruction::Context context;
3517 context.type = EmulateInstruction::eContextImmediate;
3518 context.SetNoArgs();
3519 return WriteFlags(context, result: res.result, carry: res.carry_out, overflow: res.overflow);
3520}
3521
3522// Arithmetic Shift Right (immediate) shifts a register value right by an
3523// immediate number of bits, shifting in copies of its sign bit, and writes the
3524// result to the destination register. It can optionally update the condition
3525// flags based on the result.
3526bool EmulateInstructionARM::EmulateASRImm(const uint32_t opcode,
3527 const ARMEncoding encoding) {
3528#if 0
3529 // ARM pseudo code...
3530 if ConditionPassed() then
3531 EncodingSpecificOperations();
3532 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
3533 if d == 15 then // Can only occur for ARM encoding
3534 ALUWritePC(result); // setflags is always FALSE here
3535 else
3536 R[d] = result;
3537 if setflags then
3538 APSR.N = result<31>;
3539 APSR.Z = IsZeroBit(result);
3540 APSR.C = carry;
3541 // APSR.V unchanged
3542#endif
3543
3544 return EmulateShiftImm(opcode, encoding, shift_type: SRType_ASR);
3545}
3546
3547// Arithmetic Shift Right (register) shifts a register value right by a
3548// variable number of bits, shifting in copies of its sign bit, and writes the
3549// result to the destination register. The variable number of bits is read from
3550// the bottom byte of a register. It can optionally update the condition flags
3551// based on the result.
3552bool EmulateInstructionARM::EmulateASRReg(const uint32_t opcode,
3553 const ARMEncoding encoding) {
3554#if 0
3555 // ARM pseudo code...
3556 if ConditionPassed() then
3557 EncodingSpecificOperations();
3558 shift_n = UInt(R[m]<7:0>);
3559 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
3560 R[d] = result;
3561 if setflags then
3562 APSR.N = result<31>;
3563 APSR.Z = IsZeroBit(result);
3564 APSR.C = carry;
3565 // APSR.V unchanged
3566#endif
3567
3568 return EmulateShiftReg(opcode, encoding, shift_type: SRType_ASR);
3569}
3570
3571// Logical Shift Left (immediate) shifts a register value left by an immediate
3572// number of bits, shifting in zeros, and writes the result to the destination
3573// register. It can optionally update the condition flags based on the result.
3574bool EmulateInstructionARM::EmulateLSLImm(const uint32_t opcode,
3575 const ARMEncoding encoding) {
3576#if 0
3577 // ARM pseudo code...
3578 if ConditionPassed() then
3579 EncodingSpecificOperations();
3580 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
3581 if d == 15 then // Can only occur for ARM encoding
3582 ALUWritePC(result); // setflags is always FALSE here
3583 else
3584 R[d] = result;
3585 if setflags then
3586 APSR.N = result<31>;
3587 APSR.Z = IsZeroBit(result);
3588 APSR.C = carry;
3589 // APSR.V unchanged
3590#endif
3591
3592 return EmulateShiftImm(opcode, encoding, shift_type: SRType_LSL);
3593}
3594
3595// Logical Shift Left (register) shifts a register value left by a variable
3596// number of bits, shifting in zeros, and writes the result to the destination
3597// register. The variable number of bits is read from the bottom byte of a
3598// register. It can optionally update the condition flags based on the result.
3599bool EmulateInstructionARM::EmulateLSLReg(const uint32_t opcode,
3600 const ARMEncoding encoding) {
3601#if 0
3602 // ARM pseudo code...
3603 if ConditionPassed() then
3604 EncodingSpecificOperations();
3605 shift_n = UInt(R[m]<7:0>);
3606 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
3607 R[d] = result;
3608 if setflags then
3609 APSR.N = result<31>;
3610 APSR.Z = IsZeroBit(result);
3611 APSR.C = carry;
3612 // APSR.V unchanged
3613#endif
3614
3615 return EmulateShiftReg(opcode, encoding, shift_type: SRType_LSL);
3616}
3617
3618// Logical Shift Right (immediate) shifts a register value right by an
3619// immediate number of bits, shifting in zeros, and writes the result to the
3620// destination register. It can optionally update the condition flags based on
3621// the result.
3622bool EmulateInstructionARM::EmulateLSRImm(const uint32_t opcode,
3623 const ARMEncoding encoding) {
3624#if 0
3625 // ARM pseudo code...
3626 if ConditionPassed() then
3627 EncodingSpecificOperations();
3628 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
3629 if d == 15 then // Can only occur for ARM encoding
3630 ALUWritePC(result); // setflags is always FALSE here
3631 else
3632 R[d] = result;
3633 if setflags then
3634 APSR.N = result<31>;
3635 APSR.Z = IsZeroBit(result);
3636 APSR.C = carry;
3637 // APSR.V unchanged
3638#endif
3639
3640 return EmulateShiftImm(opcode, encoding, shift_type: SRType_LSR);
3641}
3642
3643// Logical Shift Right (register) shifts a register value right by a variable
3644// number of bits, shifting in zeros, and writes the result to the destination
3645// register. The variable number of bits is read from the bottom byte of a
3646// register. It can optionally update the condition flags based on the result.
3647bool EmulateInstructionARM::EmulateLSRReg(const uint32_t opcode,
3648 const ARMEncoding encoding) {
3649#if 0
3650 // ARM pseudo code...
3651 if ConditionPassed() then
3652 EncodingSpecificOperations();
3653 shift_n = UInt(R[m]<7:0>);
3654 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
3655 R[d] = result;
3656 if setflags then
3657 APSR.N = result<31>;
3658 APSR.Z = IsZeroBit(result);
3659 APSR.C = carry;
3660 // APSR.V unchanged
3661#endif
3662
3663 return EmulateShiftReg(opcode, encoding, shift_type: SRType_LSR);
3664}
3665
3666// Rotate Right (immediate) provides the value of the contents of a register
3667// rotated by a constant value. The bits that are rotated off the right end are
3668// inserted into the vacated bit positions on the left. It can optionally
3669// update the condition flags based on the result.
3670bool EmulateInstructionARM::EmulateRORImm(const uint32_t opcode,
3671 const ARMEncoding encoding) {
3672#if 0
3673 // ARM pseudo code...
3674 if ConditionPassed() then
3675 EncodingSpecificOperations();
3676 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
3677 if d == 15 then // Can only occur for ARM encoding
3678 ALUWritePC(result); // setflags is always FALSE here
3679 else
3680 R[d] = result;
3681 if setflags then
3682 APSR.N = result<31>;
3683 APSR.Z = IsZeroBit(result);
3684 APSR.C = carry;
3685 // APSR.V unchanged
3686#endif
3687
3688 return EmulateShiftImm(opcode, encoding, shift_type: SRType_ROR);
3689}
3690
3691// Rotate Right (register) provides the value of the contents of a register
3692// rotated by a variable number of bits. The bits that are rotated off the
3693// right end are inserted into the vacated bit positions on the left. The
3694// variable number of bits is read from the bottom byte of a register. It can
3695// optionally update the condition flags based on the result.
3696bool EmulateInstructionARM::EmulateRORReg(const uint32_t opcode,
3697 const ARMEncoding encoding) {
3698#if 0
3699 // ARM pseudo code...
3700 if ConditionPassed() then
3701 EncodingSpecificOperations();
3702 shift_n = UInt(R[m]<7:0>);
3703 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
3704 R[d] = result;
3705 if setflags then
3706 APSR.N = result<31>;
3707 APSR.Z = IsZeroBit(result);
3708 APSR.C = carry;
3709 // APSR.V unchanged
3710#endif
3711
3712 return EmulateShiftReg(opcode, encoding, shift_type: SRType_ROR);
3713}
3714
3715// Rotate Right with Extend provides the value of the contents of a register
3716// shifted right by one place, with the carry flag shifted into bit [31].
3717//
3718// RRX can optionally update the condition flags based on the result.
3719// In that case, bit [0] is shifted into the carry flag.
3720bool EmulateInstructionARM::EmulateRRX(const uint32_t opcode,
3721 const ARMEncoding encoding) {
3722#if 0
3723 // ARM pseudo code...
3724 if ConditionPassed() then
3725 EncodingSpecificOperations();
3726 (result, carry) = Shift_C(R[m], SRType_RRX, 1, APSR.C);
3727 if d == 15 then // Can only occur for ARM encoding
3728 ALUWritePC(result); // setflags is always FALSE here
3729 else
3730 R[d] = result;
3731 if setflags then
3732 APSR.N = result<31>;
3733 APSR.Z = IsZeroBit(result);
3734 APSR.C = carry;
3735 // APSR.V unchanged
3736#endif
3737
3738 return EmulateShiftImm(opcode, encoding, shift_type: SRType_RRX);
3739}
3740
3741bool EmulateInstructionARM::EmulateShiftImm(const uint32_t opcode,
3742 const ARMEncoding encoding,
3743 ARM_ShifterType shift_type) {
3744 // assert(shift_type == SRType_ASR
3745 // || shift_type == SRType_LSL
3746 // || shift_type == SRType_LSR
3747 // || shift_type == SRType_ROR
3748 // || shift_type == SRType_RRX);
3749
3750 bool success = false;
3751
3752 if (ConditionPassed(opcode)) {
3753 uint32_t Rd; // the destination register
3754 uint32_t Rm; // the first operand register
3755 uint32_t imm5; // encoding for the shift amount
3756 uint32_t carry; // the carry bit after the shift operation
3757 bool setflags;
3758
3759 // Special case handling!
3760 // A8.6.139 ROR (immediate) -- Encoding T1
3761 ARMEncoding use_encoding = encoding;
3762 if (shift_type == SRType_ROR && use_encoding == eEncodingT1) {
3763 // Morph the T1 encoding from the ARM Architecture Manual into T2
3764 // encoding to have the same decoding of bit fields as the other Thumb2
3765 // shift operations.
3766 use_encoding = eEncodingT2;
3767 }
3768
3769 switch (use_encoding) {
3770 case eEncodingT1:
3771 Rd = Bits32(bits: opcode, msbit: 2, lsbit: 0);
3772 Rm = Bits32(bits: opcode, msbit: 5, lsbit: 3);
3773 setflags = !InITBlock();
3774 imm5 = Bits32(bits: opcode, msbit: 10, lsbit: 6);
3775 break;
3776 case eEncodingT2:
3777 // A8.6.141 RRX
3778 // There's no imm form of RRX instructions.
3779 if (shift_type == SRType_RRX)
3780 return false;
3781
3782 Rd = Bits32(bits: opcode, msbit: 11, lsbit: 8);
3783 Rm = Bits32(bits: opcode, msbit: 3, lsbit: 0);
3784 setflags = BitIsSet(value: opcode, bit: 20);
3785 imm5 = Bits32(bits: opcode, msbit: 14, lsbit: 12) << 2 | Bits32(bits: opcode, msbit: 7, lsbit: 6);
3786 if (BadReg(n: Rd) || BadReg(n: Rm))
3787 return false;
3788 break;
3789 case eEncodingA1:
3790 Rd = Bits32(bits: opcode, msbit: 15, lsbit: 12);
3791 Rm = Bits32(bits: opcode, msbit: 3, lsbit: 0);
3792 setflags = BitIsSet(value: opcode, bit: 20);
3793 imm5 = Bits32(bits: opcode, msbit: 11, lsbit: 7);
3794 break;
3795 default:
3796 return false;
3797 }
3798
3799 // A8.6.139 ROR (immediate)
3800 if (shift_type == SRType_ROR && imm5 == 0)
3801 shift_type = SRType_RRX;
3802
3803 // Get the first operand.
3804 uint32_t value = ReadCoreReg(regnum: Rm, success: &success);
3805 if (!success)
3806 return false;
3807
3808 // Decode the shift amount if not RRX.
3809 uint32_t amt =
3810 (shift_type == SRType_RRX ? 1 : DecodeImmShift(shift_t: shift_type, imm5));
3811
3812 uint32_t result = Shift_C(value, type: shift_type, amount: amt, APSR_C, carry_out&: carry, success: &success);
3813 if (!success)
3814 return false;
3815
3816 // The context specifies that an immediate is to be moved into Rd.
3817 EmulateInstruction::Context context;
3818 context.type = EmulateInstruction::eContextImmediate;
3819 context.SetNoArgs();
3820
3821 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
3822 return false;
3823 }
3824 return true;
3825}
3826
3827bool EmulateInstructionARM::EmulateShiftReg(const uint32_t opcode,
3828 const ARMEncoding encoding,
3829 ARM_ShifterType shift_type) {
3830 // assert(shift_type == SRType_ASR
3831 // || shift_type == SRType_LSL
3832 // || shift_type == SRType_LSR
3833 // || shift_type == SRType_ROR);
3834
3835 bool success = false;
3836
3837 if (ConditionPassed(opcode)) {
3838 uint32_t Rd; // the destination register
3839 uint32_t Rn; // the first operand register
3840 uint32_t
3841 Rm; // the register whose bottom byte contains the amount to shift by
3842 uint32_t carry; // the carry bit after the shift operation
3843 bool setflags;
3844 switch (encoding) {
3845 case eEncodingT1:
3846 Rd = Bits32(bits: opcode, msbit: 2, lsbit: 0);
3847 Rn = Rd;
3848 Rm = Bits32(bits: opcode, msbit: 5, lsbit: 3);
3849 setflags = !InITBlock();
3850 break;
3851 case eEncodingT2:
3852 Rd = Bits32(bits: opcode, msbit: 11, lsbit: 8);
3853 Rn = Bits32(bits: opcode, msbit: 19, lsbit: 16);
3854 Rm = Bits32(bits: opcode, msbit: 3, lsbit: 0);
3855 setflags = BitIsSet(value: opcode, bit: 20);
3856 if (BadReg(n: Rd) || BadReg(n: Rn) || BadReg(n: Rm))
3857 return false;
3858 break;
3859 case eEncodingA1:
3860 Rd = Bits32(bits: opcode, msbit: 15, lsbit: 12);
3861 Rn = Bits32(bits: opcode, msbit: 3, lsbit: 0);
3862 Rm = Bits32(bits: opcode, msbit: 11, lsbit: 8);
3863 setflags = BitIsSet(value: opcode, bit: 20);
3864 if (Rd == 15 || Rn == 15 || Rm == 15)
3865 return false;
3866 break;
3867 default:
3868 return false;
3869 }
3870
3871 // Get the first operand.
3872 uint32_t value = ReadCoreReg(regnum: Rn, success: &success);
3873 if (!success)
3874 return false;
3875 // Get the Rm register content.
3876 uint32_t val = ReadCoreReg(regnum: Rm, success: &success);
3877 if (!success)
3878 return false;
3879
3880 // Get the shift amount.
3881 uint32_t amt = Bits32(bits: val, msbit: 7, lsbit: 0);
3882
3883 uint32_t result = Shift_C(value, type: shift_type, amount: amt, APSR_C, carry_out&: carry, success: &success);
3884 if (!success)
3885 return false;
3886
3887 // The context specifies that an immediate is to be moved into Rd.
3888 EmulateInstruction::Context context;
3889 context.type = EmulateInstruction::eContextImmediate;
3890 context.SetNoArgs();
3891
3892 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
3893 return false;
3894 }
3895 return true;
3896}
3897
3898// LDM loads multiple registers from consecutive memory locations, using an
3899// address from a base register. Optionally the address just above the highest
3900// of those locations can be written back to the base register.
3901bool EmulateInstructionARM::EmulateLDM(const uint32_t opcode,
3902 const ARMEncoding encoding) {
3903#if 0
3904 // ARM pseudo code...
3905 if ConditionPassed()
3906 EncodingSpecificOperations(); NullCheckIfThumbEE (n);
3907 address = R[n];
3908
3909 for i = 0 to 14
3910 if registers<i> == '1' then
3911 R[i] = MemA[address, 4]; address = address + 4;
3912 if registers<15> == '1' then
3913 LoadWritePC (MemA[address, 4]);
3914
3915 if wback && registers<n> == '0' then R[n] = R[n] + 4 * BitCount (registers);
3916 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
3917
3918#endif
3919
3920 bool success = false;
3921 if (ConditionPassed(opcode)) {
3922 uint32_t n;
3923 uint32_t registers = 0;
3924 bool wback;
3925 const uint32_t addr_byte_size = GetAddressByteSize();
3926 switch (encoding) {
3927 case eEncodingT1:
3928 // n = UInt(Rn); registers = '00000000':register_list; wback =
3929 // (registers<n> == '0');
3930 n = Bits32(bits: opcode, msbit: 10, lsbit: 8);
3931 registers = Bits32(bits: opcode, msbit: 7, lsbit: 0);
3932 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
3933 wback = BitIsClear(value: registers, bit: n);
3934 // if BitCount(registers) < 1 then UNPREDICTABLE;
3935 if (BitCount(x: registers) < 1)
3936 return false;
3937 break;
3938 case eEncodingT2:
3939 // if W == '1' && Rn == '1101' then SEE POP;
3940 // n = UInt(Rn); registers = P:M:'0':register_list; wback = (W == '1');
3941 n = Bits32(bits: opcode, msbit: 19, lsbit: 16);
3942 registers = Bits32(bits: opcode, msbit: 15, lsbit: 0);
3943 registers = registers & 0xdfff; // Make sure bit 13 is zero.
3944 wback = BitIsSet(value: opcode, bit: 21);
3945
3946 // if n == 15 || BitCount(registers) < 2 || (P == '1' && M == '1') then
3947 // UNPREDICTABLE;
3948 if ((n == 15) || (BitCount(x: registers) < 2) ||
3949 (BitIsSet(value: opcode, bit: 14) && BitIsSet(value: opcode, bit: 15)))
3950 return false;
3951
3952 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then
3953 // UNPREDICTABLE;
3954 if (BitIsSet(value: registers, bit: 15) && InITBlock() && !LastInITBlock())
3955 return false;
3956
3957 // if wback && registers<n> == '1' then UNPREDICTABLE;
3958 if (wback && BitIsSet(value: registers, bit: n))
3959 return false;
3960 break;
3961
3962 case eEncodingA1:
3963 n = Bits32(bits: opcode, msbit: 19, lsbit: 16);
3964 registers = Bits32(bits: opcode, msbit: 15, lsbit: 0);
3965 wback = BitIsSet(value: opcode, bit: 21);
3966 if ((n == 15) || (BitCount(x: registers) < 1))
3967 return false;
3968 break;
3969 default:
3970 return false;
3971 }
3972
3973 int32_t offset = 0;
3974 const addr_t base_address =
3975 ReadRegisterUnsigned(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n, fail_value: 0, success_ptr: &success);
3976 if (!success)
3977 return false;
3978
3979 EmulateInstruction::Context context;
3980 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3981 std::optional<RegisterInfo> dwarf_reg =
3982 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n);
3983 context.SetRegisterPlusOffset(base_reg: *dwarf_reg, signed_offset: offset);
3984
3985 for (int i = 0; i < 14; ++i) {
3986 if (BitIsSet(value: registers, bit: i)) {
3987 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3988 context.SetRegisterPlusOffset(base_reg: *dwarf_reg, signed_offset: offset);
3989 if (wback && (n == 13)) // Pop Instruction
3990 {
3991 context.type = EmulateInstruction::eContextPopRegisterOffStack;
3992 context.SetAddress(base_address + offset);
3993 }
3994
3995 // R[i] = MemA [address, 4]; address = address + 4;
3996 uint32_t data = MemARead(context, address: base_address + offset, size: addr_byte_size,
3997 fail_value: 0, success_ptr: &success);
3998 if (!success)
3999 return false;
4000
4001 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + i,
4002 reg_value: data))
4003 return false;
4004
4005 offset += addr_byte_size;
4006 }
4007 }
4008
4009 if (BitIsSet(value: registers, bit: 15)) {
4010 // LoadWritePC (MemA [address, 4]);
4011 context.type = EmulateInstruction::eContextRegisterPlusOffset;
4012 context.SetRegisterPlusOffset(base_reg: *dwarf_reg, signed_offset: offset);
4013 uint32_t data =
4014 MemARead(context, address: base_address + offset, size: addr_byte_size, fail_value: 0, success_ptr: &success);
4015 if (!success)
4016 return false;
4017 // In ARMv5T and above, this is an interworking branch.
4018 if (!LoadWritePC(context, addr: data))
4019 return false;
4020 }
4021
4022 if (wback && BitIsClear(value: registers, bit: n)) {
4023 // R[n] = R[n] + 4 * BitCount (registers)
4024 int32_t offset = addr_byte_size * BitCount(x: registers);
4025 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4026 context.SetRegisterPlusOffset(base_reg: *dwarf_reg, signed_offset: offset);
4027
4028 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n,
4029 reg_value: base_address + offset))
4030 return false;
4031 }
4032 if (wback && BitIsSet(value: registers, bit: n))
4033 // R[n] bits(32) UNKNOWN;
4034 return WriteBits32Unknown(n);
4035 }
4036 return true;
4037}
4038
4039// LDMDA loads multiple registers from consecutive memory locations using an
4040// address from a base register.
4041// The consecutive memory locations end at this address and the address just
4042// below the lowest of those locations can optionally be written back to the
4043// base register.
4044bool EmulateInstructionARM::EmulateLDMDA(const uint32_t opcode,
4045 const ARMEncoding encoding) {
4046#if 0
4047 // ARM pseudo code...
4048 if ConditionPassed() then
4049 EncodingSpecificOperations();
4050 address = R[n] - 4*BitCount(registers) + 4;
4051
4052 for i = 0 to 14
4053 if registers<i> == '1' then
4054 R[i] = MemA[address,4]; address = address + 4;
4055
4056 if registers<15> == '1' then
4057 LoadWritePC(MemA[address,4]);
4058
4059 if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
4060 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
4061#endif
4062
4063 bool success = false;
4064
4065 if (ConditionPassed(opcode)) {
4066 uint32_t n;
4067 uint32_t registers = 0;
4068 bool wback;
4069 const uint32_t addr_byte_size = GetAddressByteSize();
4070
4071 // EncodingSpecificOperations();
4072 switch (encoding) {
4073 case eEncodingA1:
4074 // n = UInt(Rn); registers = register_list; wback = (W == '1');
4075 n = Bits32(bits: opcode, msbit: 19, lsbit: 16);
4076 registers = Bits32(bits: opcode, msbit: 15, lsbit: 0);
4077 wback = BitIsSet(value: opcode, bit: 21);
4078
4079 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4080 if ((n == 15) || (BitCount(x: registers) < 1))
4081 return false;
4082
4083 break;
4084
4085 default:
4086 return false;
4087 }
4088 // address = R[n] - 4*BitCount(registers) + 4;
4089
4090 int32_t offset = 0;
4091 addr_t Rn = ReadCoreReg(regnum: n, success: &success);
4092
4093 if (!success)
4094 return false;
4095
4096 addr_t address =
4097 Rn - (addr_byte_size * BitCount(x: registers)) + addr_byte_size;
4098
4099 EmulateInstruction::Context context;
4100 context.type = EmulateInstruction::eContextRegisterPlusOffset;
4101 std::optional<RegisterInfo> dwarf_reg =
4102 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n);
4103 context.SetRegisterPlusOffset(base_reg: *dwarf_reg, signed_offset: offset);
4104
4105 // for i = 0 to 14
4106 for (int i = 0; i < 14; ++i) {
4107 // if registers<i> == '1' then
4108 if (BitIsSet(value: registers, bit: i)) {
4109 // R[i] = MemA[address,4]; address = address + 4;
4110 context.SetRegisterPlusOffset(base_reg: *dwarf_reg, signed_offset: Rn - (address + offset));
4111 uint32_t data =
4112 MemARead(context, address: address + offset, size: addr_byte_size, fail_value: 0, success_ptr: &success);
4113 if (!success)
4114 return false;
4115 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + i,
4116 reg_value: data))
4117 return false;
4118 offset += addr_byte_size;
4119 }
4120 }
4121
4122 // if registers<15> == '1' then
4123 // LoadWritePC(MemA[address,4]);
4124 if (BitIsSet(value: registers, bit: 15)) {
4125 context.SetRegisterPlusOffset(base_reg: *dwarf_reg, signed_offset: offset);
4126 uint32_t data =
4127 MemARead(context, address: address + offset, size: addr_byte_size, fail_value: 0, success_ptr: &success);
4128 if (!success)
4129 return false;
4130 // In ARMv5T and above, this is an interworking branch.
4131 if (!LoadWritePC(context, addr: data))
4132 return false;
4133 }
4134
4135 // if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
4136 if (wback && BitIsClear(value: registers, bit: n)) {
4137
4138 offset = (addr_byte_size * BitCount(x: registers)) * -1;
4139 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4140 context.SetImmediateSigned(offset);
4141 addr_t addr = Rn + offset;
4142 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n,
4143 reg_value: addr))
4144 return false;
4145 }
4146
4147 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
4148 if (wback && BitIsSet(value: registers, bit: n))
4149 return WriteBits32Unknown(n);
4150 }
4151 return true;
4152}
4153
4154// LDMDB loads multiple registers from consecutive memory locations using an
4155// address from a base register. The
4156// consecutive memory locations end just below this address, and the address of
4157// the lowest of those locations can be optionally written back to the base
4158// register.
4159bool EmulateInstructionARM::EmulateLDMDB(const uint32_t opcode,
4160 const ARMEncoding encoding) {
4161#if 0
4162 // ARM pseudo code...
4163 if ConditionPassed() then
4164 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4165 address = R[n] - 4*BitCount(registers);
4166
4167 for i = 0 to 14
4168 if registers<i> == '1' then
4169 R[i] = MemA[address,4]; address = address + 4;
4170 if registers<15> == '1' then
4171 LoadWritePC(MemA[address,4]);
4172
4173 if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
4174 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
4175#endif
4176
4177 bool success = false;
4178
4179 if (ConditionPassed(opcode)) {
4180 uint32_t n;
4181 uint32_t registers = 0;
4182 bool wback;
4183 const uint32_t addr_byte_size = GetAddressByteSize();
4184 switch (encoding) {
4185 case eEncodingT1:
4186 // n = UInt(Rn); registers = P:M:'0':register_list; wback = (W == '1');
4187 n = Bits32(bits: opcode, msbit: 19, lsbit: 16);
4188 registers = Bits32(bits: opcode, msbit: 15, lsbit: 0);
4189 registers = registers & 0xdfff; // Make sure bit 13 is a zero.
4190 wback = BitIsSet(value: opcode, bit: 21);
4191
4192 // if n == 15 || BitCount(registers) < 2 || (P == '1' && M == '1') then
4193 // UNPREDICTABLE;
4194 if ((n == 15) || (BitCount(x: registers) < 2) ||
4195 (BitIsSet(value: opcode, bit: 14) && BitIsSet(value: opcode, bit: 15)))
4196 return false;
4197
4198 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then
4199 // UNPREDICTABLE;
4200 if (BitIsSet(value: registers, bit: 15) && InITBlock() && !LastInITBlock())
4201 return false;
4202
4203 // if wback && registers<n> == '1' then UNPREDICTABLE;
4204 if (wback && BitIsSet(value: registers, bit: n))
4205 return false;
4206
4207 break;
4208
4209 case eEncodingA1:
4210 // n = UInt(Rn); registers = register_list; wback = (W == '1');
4211 n = Bits32(bits: opcode, msbit: 19, lsbit: 16);
4212 registers = Bits32(bits: opcode, msbit: 15, lsbit: 0);
4213 wback = BitIsSet(value: opcode, bit: 21);
4214
4215 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4216 if ((n == 15) || (BitCount(x: registers) < 1))
4217 return false;
4218
4219 break;
4220
4221 default:
4222 return false;
4223 }
4224
4225 // address = R[n] - 4*BitCount(registers);
4226
4227 int32_t offset = 0;
4228 addr_t Rn =
4229 ReadRegisterUnsigned(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n, fail_value: 0, success_ptr: &success);
4230
4231 if (!success)
4232 return false;
4233
4234 addr_t address = Rn - (addr_byte_size * BitCount(x: registers));
4235 EmulateInstruction::Context context;
4236 context.type = EmulateInstruction::eContextRegisterPlusOffset;
4237 std::optional<RegisterInfo> dwarf_reg =
4238 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n);
4239 context.SetRegisterPlusOffset(base_reg: *dwarf_reg, signed_offset: Rn - address);
4240
4241 for (int i = 0; i < 14; ++i) {
4242 if (BitIsSet(value: registers, bit: i)) {
4243 // R[i] = MemA[address,4]; address = address + 4;
4244 context.SetRegisterPlusOffset(base_reg: *dwarf_reg, signed_offset: Rn - (address + offset));
4245 uint32_t data =
4246 MemARead(context, address: address + offset, size: addr_byte_size, fail_value: 0, success_ptr: &success);
4247 if (!success)
4248 return false;
4249
4250 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + i,
4251 reg_value: data))
4252 return false;
4253
4254 offset += addr_byte_size;
4255 }
4256 }
4257
4258 // if registers<15> == '1' then
4259 // LoadWritePC(MemA[address,4]);
4260 if (BitIsSet(value: registers, bit: 15)) {
4261 context.SetRegisterPlusOffset(base_reg: *dwarf_reg, signed_offset: offset);
4262 uint32_t data =
4263 MemARead(context, address: address + offset, size: addr_byte_size, fail_value: 0, success_ptr: &success);
4264 if (!success)
4265 return false;
4266 // In ARMv5T and above, this is an interworking branch.
4267 if (!LoadWritePC(context, addr: data))
4268 return false;
4269 }
4270
4271 // if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
4272 if (wback && BitIsClear(value: registers, bit: n)) {
4273
4274 offset = (addr_byte_size * BitCount(x: registers)) * -1;
4275 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4276 context.SetImmediateSigned(offset);
4277 addr_t addr = Rn + offset;
4278 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n,
4279 reg_value: addr))
4280 return false;
4281 }
4282
4283 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only
4284 // possible for encoding A1
4285 if (wback && BitIsSet(value: registers, bit: n))
4286 return WriteBits32Unknown(n);
4287 }
4288 return true;
4289}
4290
4291// LDMIB loads multiple registers from consecutive memory locations using an
4292// address from a base register. The
4293// consecutive memory locations start just above this address, and thea ddress
4294// of the last of those locations can optinoally be written back to the base
4295// register.
4296bool EmulateInstructionARM::EmulateLDMIB(const uint32_t opcode,
4297 const ARMEncoding encoding) {
4298#if 0
4299 if ConditionPassed() then
4300 EncodingSpecificOperations();
4301 address = R[n] + 4;
4302
4303 for i = 0 to 14
4304 if registers<i> == '1' then
4305 R[i] = MemA[address,4]; address = address + 4;
4306 if registers<15> == '1' then
4307 LoadWritePC(MemA[address,4]);
4308
4309 if wback && registers<n> == '0' then R[n] = R[n] + 4*BitCount(registers);
4310 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
4311#endif
4312
4313 bool success = false;
4314
4315 if (ConditionPassed(opcode)) {
4316 uint32_t n;
4317 uint32_t registers = 0;
4318 bool wback;
4319 const uint32_t addr_byte_size = GetAddressByteSize();
4320 switch (encoding) {
4321 case eEncodingA1:
4322 // n = UInt(Rn); registers = register_list; wback = (W == '1');
4323 n = Bits32(bits: opcode, msbit: 19, lsbit: 16);
4324 registers = Bits32(bits: opcode, msbit: 15, lsbit: 0);
4325 wback = BitIsSet(value: opcode, bit: 21);
4326
4327 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4328 if ((n == 15) || (BitCount(x: registers) < 1))
4329 return false;
4330
4331 break;
4332 default:
4333 return false;
4334 }
4335 // address = R[n] + 4;
4336
4337 int32_t offset = 0;
4338 addr_t Rn =
4339 ReadRegisterUnsigned(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n, fail_value: 0, success_ptr: &success);
4340
4341 if (!success)
4342 return false;
4343
4344 addr_t address = Rn + addr_byte_size;
4345
4346 EmulateInstruction::Context context;
4347 context.type = EmulateInstruction::eContextRegisterPlusOffset;
4348 std::optional<RegisterInfo> dwarf_reg =
4349 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n);
4350 context.SetRegisterPlusOffset(base_reg: *dwarf_reg, signed_offset: offset);
4351
4352 for (int i = 0; i < 14; ++i) {
4353 if (BitIsSet(value: registers, bit: i)) {
4354 // R[i] = MemA[address,4]; address = address + 4;
4355
4356 context.SetRegisterPlusOffset(base_reg: *dwarf_reg, signed_offset: offset + addr_byte_size);
4357 uint32_t data =
4358 MemARead(context, address: address + offset, size: addr_byte_size, fail_value: 0, success_ptr: &success);
4359 if (!success)
4360 return false;
4361
4362 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + i,
4363 reg_value: data))
4364 return false;
4365
4366 offset += addr_byte_size;
4367 }
4368 }
4369
4370 // if registers<15> == '1' then
4371 // LoadWritePC(MemA[address,4]);
4372 if (BitIsSet(value: registers, bit: 15)) {
4373 context.SetRegisterPlusOffset(base_reg: *dwarf_reg, signed_offset: offset);
4374 uint32_t data =
4375 MemARead(context, address: address + offset, size: addr_byte_size, fail_value: 0, success_ptr: &success);
4376 if (!success)
4377 return false;
4378 // In ARMv5T and above, this is an interworking branch.
4379 if (!LoadWritePC(context, addr: data))
4380 return false;
4381 }
4382
4383 // if wback && registers<n> == '0' then R[n] = R[n] + 4*BitCount(registers);
4384 if (wback && BitIsClear(value: registers, bit: n)) {
4385
4386 offset = addr_byte_size * BitCount(x: registers);
4387 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4388 context.SetImmediateSigned(offset);
4389 addr_t addr = Rn + offset;
4390 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n,
4391 reg_value: addr))
4392 return false;
4393 }
4394
4395 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only
4396 // possible for encoding A1
4397 if (wback && BitIsSet(value: registers, bit: n))
4398 return WriteBits32Unknown(n);
4399 }
4400 return true;
4401}
4402
4403// Load Register (immediate) calculates an address from a base register value
4404// and an immediate offset, loads a word from memory, and writes to a register.
4405// LDR (immediate, Thumb)
4406bool EmulateInstructionARM::EmulateLDRRtRnImm(const uint32_t opcode,
4407 const ARMEncoding encoding) {
4408#if 0
4409 // ARM pseudo code...
4410 if (ConditionPassed())
4411 {
4412 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
4413 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
4414 address = if index then offset_addr else R[n];
4415 data = MemU[address,4];
4416 if wback then R[n] = offset_addr;
4417 if t == 15 then
4418 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
4419 elsif UnalignedSupport() || address<1:0> = '00' then
4420 R[t] = data;
4421 else R[t] = bits(32) UNKNOWN; // Can only apply before ARMv7
4422 }
4423#endif
4424
4425 bool success = false;
4426
4427 if (ConditionPassed(opcode)) {
4428 uint32_t Rt; // the destination register
4429 uint32_t Rn; // the base register
4430 uint32_t imm32; // the immediate offset used to form the address
4431 addr_t offset_addr; // the offset address
4432 addr_t address; // the calculated address
4433 uint32_t data; // the literal data value from memory load
4434 bool add, index, wback;
4435 switch (encoding) {
4436 case eEncodingT1:
4437 Rt = Bits32(bits: opcode, msbit: 2, lsbit: 0);
4438 Rn = Bits32(bits: opcode, msbit: 5, lsbit: 3);
4439 imm32 = Bits32(bits: opcode, msbit: 10, lsbit: 6) << 2; // imm32 = ZeroExtend(imm5:'00', 32);
4440 // index = TRUE; add = TRUE; wback = FALSE
4441 add = true;
4442 index = true;
4443 wback = false;
4444
4445 break;
4446
4447 case eEncodingT2:
4448 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:'00', 32);
4449 Rt = Bits32(bits: opcode, msbit: 10, lsbit: 8);
4450 Rn = 13;
4451 imm32 = Bits32(bits: opcode, msbit: 7, lsbit: 0) << 2;
4452
4453 // index = TRUE; add = TRUE; wback = FALSE;
4454 index = true;
4455 add = true;
4456 wback = false;
4457
4458 break;
4459
4460 case eEncodingT3:
4461 // if Rn == '1111' then SEE LDR (literal);
4462 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
4463 Rt = Bits32(bits: opcode, msbit: 15, lsbit: 12);
4464 Rn = Bits32(bits: opcode, msbit: 19, lsbit: 16);
4465 imm32 = Bits32(bits: opcode, msbit: 11, lsbit: 0);
4466
4467 // index = TRUE; add = TRUE; wback = FALSE;
4468 index = true;
4469 add = true;
4470 wback = false;
4471
4472 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
4473 if ((Rt == 15) && InITBlock() && !LastInITBlock())
4474 return false;
4475
4476 break;
4477
4478 case eEncodingT4:
4479 // if Rn == '1111' then SEE LDR (literal);
4480 // if P == '1' && U == '1' && W == '0' then SEE LDRT;
4481 // if Rn == '1101' && P == '0' && U == '1' && W == '1' && imm8 ==
4482 // '00000100' then SEE POP;
4483 // if P == '0' && W == '0' then UNDEFINED;
4484 if (BitIsClear(value: opcode, bit: 10) && BitIsClear(value: opcode, bit: 8))
4485 return false;
4486
4487 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4488 Rt = Bits32(bits: opcode, msbit: 15, lsbit: 12);
4489 Rn = Bits32(bits: opcode, msbit: 19, lsbit: 16);
4490 imm32 = Bits32(bits: opcode, msbit: 7, lsbit: 0);
4491
4492 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
4493 index = BitIsSet(value: opcode, bit: 10);
4494 add = BitIsSet(value: opcode, bit: 9);
4495 wback = BitIsSet(value: opcode, bit: 8);
4496
4497 // if (wback && n == t) || (t == 15 && InITBlock() && !LastInITBlock())
4498 // then UNPREDICTABLE;
4499 if ((wback && (Rn == Rt)) ||
4500 ((Rt == 15) && InITBlock() && !LastInITBlock()))
4501 return false;
4502
4503 break;
4504
4505 default:
4506 return false;
4507 }
4508 uint32_t base = ReadCoreReg(regnum: Rn, success: &success);
4509 if (!success)
4510 return false;
4511 if (add)
4512 offset_addr = base + imm32;
4513 else
4514 offset_addr = base - imm32;
4515
4516 address = (index ? offset_addr : base);
4517
4518 std::optional<RegisterInfo> base_reg =
4519 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + Rn);
4520 if (wback) {
4521 EmulateInstruction::Context ctx;
4522 if (Rn == 13) {
4523 ctx.type = eContextAdjustStackPointer;
4524 ctx.SetImmediateSigned((int32_t)(offset_addr - base));
4525 } else if (Rn == GetFramePointerRegisterNumber()) {
4526 ctx.type = eContextSetFramePointer;
4527 ctx.SetRegisterPlusOffset(base_reg: *base_reg, signed_offset: (int32_t)(offset_addr - base));
4528 } else {
4529 ctx.type = EmulateInstruction::eContextAdjustBaseRegister;
4530 ctx.SetRegisterPlusOffset(base_reg: *base_reg, signed_offset: (int32_t)(offset_addr - base));
4531 }
4532
4533 if (!WriteRegisterUnsigned(context: ctx, reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + Rn,
4534 reg_value: offset_addr))
4535 return false;
4536 }
4537
4538 // Prepare to write to the Rt register.
4539 EmulateInstruction::Context context;
4540 context.type = EmulateInstruction::eContextRegisterLoad;
4541 context.SetRegisterPlusOffset(base_reg: *base_reg, signed_offset: (int32_t)(offset_addr - base));
4542
4543 // Read memory from the address.
4544 data = MemURead(context, address, size: 4, fail_value: 0, success_ptr: &success);
4545 if (!success)
4546 return false;
4547
4548 if (Rt == 15) {
4549 if (Bits32(bits: address, msbit: 1, lsbit: 0) == 0) {
4550 if (!LoadWritePC(context, addr: data))
4551 return false;
4552 } else
4553 return false;
4554 } else if (UnalignedSupport() || Bits32(bits: address, msbit: 1, lsbit: 0) == 0) {
4555 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + Rt,
4556 reg_value: data))
4557 return false;
4558 } else
4559 WriteBits32Unknown(n: Rt);
4560 }
4561 return true;
4562}
4563
4564// STM (Store Multiple Increment After) stores multiple registers to consecutive
4565// memory locations using an address
4566// from a base register. The consecutive memory locations start at this
4567// address, and the address just above the last of those locations can
4568// optionally be written back to the base register.
4569bool EmulateInstructionARM::EmulateSTM(const uint32_t opcode,
4570 const ARMEncoding encoding) {
4571#if 0
4572 if ConditionPassed() then
4573 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4574 address = R[n];
4575
4576 for i = 0 to 14
4577 if registers<i> == '1' then
4578 if i == n && wback && i != LowestSetBit(registers) then
4579 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
4580 else
4581 MemA[address,4] = R[i];
4582 address = address + 4;
4583
4584 if registers<15> == '1' then // Only possible for encoding A1
4585 MemA[address,4] = PCStoreValue();
4586 if wback then R[n] = R[n] + 4*BitCount(registers);
4587#endif
4588
4589 bool success = false;
4590
4591 if (ConditionPassed(opcode)) {
4592 uint32_t n;
4593 uint32_t registers = 0;
4594 bool wback;
4595 const uint32_t addr_byte_size = GetAddressByteSize();
4596
4597 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4598 switch (encoding) {
4599 case eEncodingT1:
4600 // n = UInt(Rn); registers = '00000000':register_list; wback = TRUE;
4601 n = Bits32(bits: opcode, msbit: 10, lsbit: 8);
4602 registers = Bits32(bits: opcode, msbit: 7, lsbit: 0);
4603 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
4604 wback = true;
4605
4606 // if BitCount(registers) < 1 then UNPREDICTABLE;
4607 if (BitCount(x: registers) < 1)
4608 return false;
4609
4610 break;
4611
4612 case eEncodingT2:
4613 // n = UInt(Rn); registers = '0':M:'0':register_list; wback = (W == '1');
4614 n = Bits32(bits: opcode, msbit: 19, lsbit: 16);
4615 registers = Bits32(bits: opcode, msbit: 15, lsbit: 0);
4616 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
4617 wback = BitIsSet(value: opcode, bit: 21);
4618
4619 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
4620 if ((n == 15) || (BitCount(x: registers) < 2))
4621 return false;
4622
4623 // if wback && registers<n> == '1' then UNPREDICTABLE;
4624 if (wback && BitIsSet(value: registers, bit: n))
4625 return false;
4626
4627 break;
4628
4629 case eEncodingA1:
4630 // n = UInt(Rn); registers = register_list; wback = (W == '1');
4631 n = Bits32(bits: opcode, msbit: 19, lsbit: 16);
4632 registers = Bits32(bits: opcode, msbit: 15, lsbit: 0);
4633 wback = BitIsSet(value: opcode, bit: 21);
4634
4635 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4636 if ((n == 15) || (BitCount(x: registers) < 1))
4637 return false;
4638
4639 break;
4640
4641 default:
4642 return false;
4643 }
4644
4645 // address = R[n];
4646 int32_t offset = 0;
4647 const addr_t address =
4648 ReadRegisterUnsigned(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n, fail_value: 0, success_ptr: &success);
4649 if (!success)
4650 return false;
4651
4652 EmulateInstruction::Context context;
4653 context.type = EmulateInstruction::eContextRegisterStore;
4654 std::optional<RegisterInfo> base_reg =
4655 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n);
4656
4657 // for i = 0 to 14
4658 uint32_t lowest_set_bit = 14;
4659 for (uint32_t i = 0; i < 14; ++i) {
4660 // if registers<i> == '1' then
4661 if (BitIsSet(value: registers, bit: i)) {
4662 if (i < lowest_set_bit)
4663 lowest_set_bit = i;
4664 // if i == n && wback && i != LowestSetBit(registers) then
4665 if ((i == n) && wback && (i != lowest_set_bit))
4666 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings
4667 // T1 and A1
4668 WriteBits32UnknownToMemory(address: address + offset);
4669 else {
4670 // MemA[address,4] = R[i];
4671 uint32_t data = ReadRegisterUnsigned(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + i,
4672 fail_value: 0, success_ptr: &success);
4673 if (!success)
4674 return false;
4675
4676 std::optional<RegisterInfo> data_reg =
4677 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + i);
4678 context.SetRegisterToRegisterPlusOffset(data_reg: *data_reg, base_reg: *base_reg, offset);
4679 if (!MemAWrite(context, address: address + offset, data_val: data, size: addr_byte_size))
4680 return false;
4681 }
4682
4683 // address = address + 4;
4684 offset += addr_byte_size;
4685 }
4686 }
4687
4688 // if registers<15> == '1' then // Only possible for encoding A1
4689 // MemA[address,4] = PCStoreValue();
4690 if (BitIsSet(value: registers, bit: 15)) {
4691 std::optional<RegisterInfo> pc_reg =
4692 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_pc);
4693 context.SetRegisterPlusOffset(base_reg: *pc_reg, signed_offset: 8);
4694 const uint32_t pc = ReadCoreReg(PC_REG, success: &success);
4695 if (!success)
4696 return false;
4697
4698 if (!MemAWrite(context, address: address + offset, data_val: pc, size: addr_byte_size))
4699 return false;
4700 }
4701
4702 // if wback then R[n] = R[n] + 4*BitCount(registers);
4703 if (wback) {
4704 offset = addr_byte_size * BitCount(x: registers);
4705 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4706 context.SetImmediateSigned(offset);
4707 addr_t data = address + offset;
4708 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n,
4709 reg_value: data))
4710 return false;
4711 }
4712 }
4713 return true;
4714}
4715
4716// STMDA (Store Multiple Decrement After) stores multiple registers to
4717// consecutive memory locations using an address from a base register. The
4718// consecutive memory locations end at this address, and the address just below
4719// the lowest of those locations can optionally be written back to the base
4720// register.
4721bool EmulateInstructionARM::EmulateSTMDA(const uint32_t opcode,
4722 const ARMEncoding encoding) {
4723#if 0
4724 if ConditionPassed() then
4725 EncodingSpecificOperations();
4726 address = R[n] - 4*BitCount(registers) + 4;
4727
4728 for i = 0 to 14
4729 if registers<i> == '1' then
4730 if i == n && wback && i != LowestSetBit(registers) then
4731 MemA[address,4] = bits(32) UNKNOWN;
4732 else
4733 MemA[address,4] = R[i];
4734 address = address + 4;
4735
4736 if registers<15> == '1' then
4737 MemA[address,4] = PCStoreValue();
4738
4739 if wback then R[n] = R[n] - 4*BitCount(registers);
4740#endif
4741
4742 bool success = false;
4743
4744 if (ConditionPassed(opcode)) {
4745 uint32_t n;
4746 uint32_t registers = 0;
4747 bool wback;
4748 const uint32_t addr_byte_size = GetAddressByteSize();
4749
4750 // EncodingSpecificOperations();
4751 switch (encoding) {
4752 case eEncodingA1:
4753 // n = UInt(Rn); registers = register_list; wback = (W == '1');
4754 n = Bits32(bits: opcode, msbit: 19, lsbit: 16);
4755 registers = Bits32(bits: opcode, msbit: 15, lsbit: 0);
4756 wback = BitIsSet(value: opcode, bit: 21);
4757
4758 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4759 if ((n == 15) || (BitCount(x: registers) < 1))
4760 return false;
4761 break;
4762 default:
4763 return false;
4764 }
4765
4766 // address = R[n] - 4*BitCount(registers) + 4;
4767 int32_t offset = 0;
4768 addr_t Rn = ReadCoreReg(regnum: n, success: &success);
4769 if (!success)
4770 return false;
4771
4772 addr_t address = Rn - (addr_byte_size * BitCount(x: registers)) + 4;
4773
4774 EmulateInstruction::Context context;
4775 context.type = EmulateInstruction::eContextRegisterStore;
4776 std::optional<RegisterInfo> base_reg =
4777 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n);
4778
4779 // for i = 0 to 14
4780 uint32_t lowest_bit_set = 14;
4781 for (uint32_t i = 0; i < 14; ++i) {
4782 // if registers<i> == '1' then
4783 if (BitIsSet(value: registers, bit: i)) {
4784 if (i < lowest_bit_set)
4785 lowest_bit_set = i;
4786 // if i == n && wback && i != LowestSetBit(registers) then
4787 if ((i == n) && wback && (i != lowest_bit_set))
4788 // MemA[address,4] = bits(32) UNKNOWN;
4789 WriteBits32UnknownToMemory(address: address + offset);
4790 else {
4791 // MemA[address,4] = R[i];
4792 uint32_t data = ReadRegisterUnsigned(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + i,
4793 fail_value: 0, success_ptr: &success);
4794 if (!success)
4795 return false;
4796
4797 std::optional<RegisterInfo> data_reg =
4798 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + i);
4799 context.SetRegisterToRegisterPlusOffset(data_reg: *data_reg, base_reg: *base_reg,
4800 offset: Rn - (address + offset));
4801 if (!MemAWrite(context, address: address + offset, data_val: data, size: addr_byte_size))
4802 return false;
4803 }
4804
4805 // address = address + 4;
4806 offset += addr_byte_size;
4807 }
4808 }
4809
4810 // if registers<15> == '1' then
4811 // MemA[address,4] = PCStoreValue();
4812 if (BitIsSet(value: registers, bit: 15)) {
4813 std::optional<RegisterInfo> pc_reg =
4814 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_pc);
4815 context.SetRegisterPlusOffset(base_reg: *pc_reg, signed_offset: 8);
4816 const uint32_t pc = ReadCoreReg(PC_REG, success: &success);
4817 if (!success)
4818 return false;
4819
4820 if (!MemAWrite(context, address: address + offset, data_val: pc, size: addr_byte_size))
4821 return false;
4822 }
4823
4824 // if wback then R[n] = R[n] - 4*BitCount(registers);
4825 if (wback) {
4826 offset = (addr_byte_size * BitCount(x: registers)) * -1;
4827 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4828 context.SetImmediateSigned(offset);
4829 addr_t data = Rn + offset;
4830 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n,
4831 reg_value: data))
4832 return false;
4833 }
4834 }
4835 return true;
4836}
4837
4838// STMDB (Store Multiple Decrement Before) stores multiple registers to
4839// consecutive memory locations using an address from a base register. The
4840// consecutive memory locations end just below this address, and the address of
4841// the first of those locations can optionally be written back to the base
4842// register.
4843bool EmulateInstructionARM::EmulateSTMDB(const uint32_t opcode,
4844 const ARMEncoding encoding) {
4845#if 0
4846 if ConditionPassed() then
4847 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4848 address = R[n] - 4*BitCount(registers);
4849
4850 for i = 0 to 14
4851 if registers<i> == '1' then
4852 if i == n && wback && i != LowestSetBit(registers) then
4853 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
4854 else
4855 MemA[address,4] = R[i];
4856 address = address + 4;
4857
4858 if registers<15> == '1' then // Only possible for encoding A1
4859 MemA[address,4] = PCStoreValue();
4860
4861 if wback then R[n] = R[n] - 4*BitCount(registers);
4862#endif
4863
4864 bool success = false;
4865
4866 if (ConditionPassed(opcode)) {
4867 uint32_t n;
4868 uint32_t registers = 0;
4869 bool wback;
4870 const uint32_t addr_byte_size = GetAddressByteSize();
4871
4872 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4873 switch (encoding) {
4874 case eEncodingT1:
4875 // if W == '1' && Rn == '1101' then SEE PUSH;
4876 if ((BitIsSet(value: opcode, bit: 21)) && (Bits32(bits: opcode, msbit: 19, lsbit: 16) == 13)) {
4877 // See PUSH
4878 }
4879 // n = UInt(Rn); registers = '0':M:'0':register_list; wback = (W == '1');
4880 n = Bits32(bits: opcode, msbit: 19, lsbit: 16);
4881 registers = Bits32(bits: opcode, msbit: 15, lsbit: 0);
4882 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
4883 wback = BitIsSet(value: opcode, bit: 21);
4884 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
4885 if ((n == 15) || BitCount(x: registers) < 2)
4886 return false;
4887 // if wback && registers<n> == '1' then UNPREDICTABLE;
4888 if (wback && BitIsSet(value: registers, bit: n))
4889 return false;
4890 break;
4891
4892 case eEncodingA1:
4893 // if W == '1' && Rn == '1101' && BitCount(register_list) >= 2 then SEE
4894 // PUSH;
4895 if (BitIsSet(value: opcode, bit: 21) && (Bits32(bits: opcode, msbit: 19, lsbit: 16) == 13) &&
4896 BitCount(x: Bits32(bits: opcode, msbit: 15, lsbit: 0)) >= 2) {
4897 // See Push
4898 }
4899 // n = UInt(Rn); registers = register_list; wback = (W == '1');
4900 n = Bits32(bits: opcode, msbit: 19, lsbit: 16);
4901 registers = Bits32(bits: opcode, msbit: 15, lsbit: 0);
4902 wback = BitIsSet(value: opcode, bit: 21);
4903 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4904 if ((n == 15) || BitCount(x: registers) < 1)
4905 return false;
4906 break;
4907
4908 default:
4909 return false;
4910 }
4911
4912 // address = R[n] - 4*BitCount(registers);
4913
4914 int32_t offset = 0;
4915 addr_t Rn =
4916 ReadRegisterUnsigned(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n, fail_value: 0, success_ptr: &success);
4917 if (!success)
4918 return false;
4919
4920 addr_t address = Rn - (addr_byte_size * BitCount(x: registers));
4921
4922 EmulateInstruction::Context context;
4923 context.type = EmulateInstruction::eContextRegisterStore;
4924 std::optional<RegisterInfo> base_reg =
4925 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n);
4926
4927 // for i = 0 to 14
4928 uint32_t lowest_set_bit = 14;
4929 for (uint32_t i = 0; i < 14; ++i) {
4930 // if registers<i> == '1' then
4931 if (BitIsSet(value: registers, bit: i)) {
4932 if (i < lowest_set_bit)
4933 lowest_set_bit = i;
4934 // if i == n && wback && i != LowestSetBit(registers) then
4935 if ((i == n) && wback && (i != lowest_set_bit))
4936 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding
4937 // A1
4938 WriteBits32UnknownToMemory(address: address + offset);
4939 else {
4940 // MemA[address,4] = R[i];
4941 uint32_t data = ReadRegisterUnsigned(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + i,
4942 fail_value: 0, success_ptr: &success);
4943 if (!success)
4944 return false;
4945
4946 std::optional<RegisterInfo> data_reg =
4947 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + i);
4948 context.SetRegisterToRegisterPlusOffset(data_reg: *data_reg, base_reg: *base_reg,
4949 offset: Rn - (address + offset));
4950 if (!MemAWrite(context, address: address + offset, data_val: data, size: addr_byte_size))
4951 return false;
4952 }
4953
4954 // address = address + 4;
4955 offset += addr_byte_size;
4956 }
4957 }
4958
4959 // if registers<15> == '1' then // Only possible for encoding A1
4960 // MemA[address,4] = PCStoreValue();
4961 if (BitIsSet(value: registers, bit: 15)) {
4962 std::optional<RegisterInfo> pc_reg =
4963 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_pc);
4964 context.SetRegisterPlusOffset(base_reg: *pc_reg, signed_offset: 8);
4965 const uint32_t pc = ReadCoreReg(PC_REG, success: &success);
4966 if (!success)
4967 return false;
4968
4969 if (!MemAWrite(context, address: address + offset, data_val: pc, size: addr_byte_size))
4970 return false;
4971 }
4972
4973 // if wback then R[n] = R[n] - 4*BitCount(registers);
4974 if (wback) {
4975 offset = (addr_byte_size * BitCount(x: registers)) * -1;
4976 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4977 context.SetImmediateSigned(offset);
4978 addr_t data = Rn + offset;
4979 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n,
4980 reg_value: data))
4981 return false;
4982 }
4983 }
4984 return true;
4985}
4986
4987// STMIB (Store Multiple Increment Before) stores multiple registers to
4988// consecutive memory locations using an address from a base register. The
4989// consecutive memory locations start just above this address, and the address
4990// of the last of those locations can optionally be written back to the base
4991// register.
4992bool EmulateInstructionARM::EmulateSTMIB(const uint32_t opcode,
4993 const ARMEncoding encoding) {
4994#if 0
4995 if ConditionPassed() then
4996 EncodingSpecificOperations();
4997 address = R[n] + 4;
4998
4999 for i = 0 to 14
5000 if registers<i> == '1' then
5001 if i == n && wback && i != LowestSetBit(registers) then
5002 MemA[address,4] = bits(32) UNKNOWN;
5003 else
5004 MemA[address,4] = R[i];
5005 address = address + 4;
5006
5007 if registers<15> == '1' then
5008 MemA[address,4] = PCStoreValue();
5009
5010 if wback then R[n] = R[n] + 4*BitCount(registers);
5011#endif
5012
5013 bool success = false;
5014
5015 if (ConditionPassed(opcode)) {
5016 uint32_t n;
5017 uint32_t registers = 0;
5018 bool wback;
5019 const uint32_t addr_byte_size = GetAddressByteSize();
5020
5021 // EncodingSpecificOperations();
5022 switch (encoding) {
5023 case eEncodingA1:
5024 // n = UInt(Rn); registers = register_list; wback = (W == '1');
5025 n = Bits32(bits: opcode, msbit: 19, lsbit: 16);
5026 registers = Bits32(bits: opcode, msbit: 15, lsbit: 0);
5027 wback = BitIsSet(value: opcode, bit: 21);
5028
5029 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
5030 if ((n == 15) && (BitCount(x: registers) < 1))
5031 return false;
5032 break;
5033 default:
5034 return false;
5035 }
5036 // address = R[n] + 4;
5037
5038 int32_t offset = 0;
5039 addr_t Rn = ReadCoreReg(regnum: n, success: &success);
5040 if (!success)
5041 return false;
5042
5043 addr_t address = Rn + addr_byte_size;
5044
5045 EmulateInstruction::Context context;
5046 context.type = EmulateInstruction::eContextRegisterStore;
5047 std::optional<RegisterInfo> base_reg =
5048 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n);
5049
5050 uint32_t lowest_set_bit = 14;
5051 // for i = 0 to 14
5052 for (uint32_t i = 0; i < 14; ++i) {
5053 // if registers<i> == '1' then
5054 if (BitIsSet(value: registers, bit: i)) {
5055 if (i < lowest_set_bit)
5056 lowest_set_bit = i;
5057 // if i == n && wback && i != LowestSetBit(registers) then
5058 if ((i == n) && wback && (i != lowest_set_bit))
5059 // MemA[address,4] = bits(32) UNKNOWN;
5060 WriteBits32UnknownToMemory(address: address + offset);
5061 // else
5062 else {
5063 // MemA[address,4] = R[i];
5064 uint32_t data = ReadRegisterUnsigned(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + i,
5065 fail_value: 0, success_ptr: &success);
5066 if (!success)
5067 return false;
5068
5069 std::optional<RegisterInfo> data_reg =
5070 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + i);
5071 context.SetRegisterToRegisterPlusOffset(data_reg: *data_reg, base_reg: *base_reg,
5072 offset: offset + addr_byte_size);
5073 if (!MemAWrite(context, address: address + offset, data_val: data, size: addr_byte_size))
5074 return false;
5075 }
5076
5077 // address = address + 4;
5078 offset += addr_byte_size;
5079 }
5080 }
5081
5082 // if registers<15> == '1' then
5083 // MemA[address,4] = PCStoreValue();
5084 if (BitIsSet(value: registers, bit: 15)) {
5085 std::optional<RegisterInfo> pc_reg =
5086 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_pc);
5087 context.SetRegisterPlusOffset(base_reg: *pc_reg, signed_offset: 8);
5088 const uint32_t pc = ReadCoreReg(PC_REG, success: &success);
5089 if (!success)
5090 return false;
5091
5092 if (!MemAWrite(context, address: address + offset, data_val: pc, size: addr_byte_size))
5093 return false;
5094 }
5095
5096 // if wback then R[n] = R[n] + 4*BitCount(registers);
5097 if (wback) {
5098 offset = addr_byte_size * BitCount(x: registers);
5099 context.type = EmulateInstruction::eContextAdjustBaseRegister;
5100 context.SetImmediateSigned(offset);
5101 addr_t data = Rn + offset;
5102 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n,
5103 reg_value: data))
5104 return false;
5105 }
5106 }
5107 return true;
5108}
5109
5110// STR (store immediate) calculates an address from a base register value and an
5111// immediate offset, and stores a word
5112// from a register to memory. It can use offset, post-indexed, or pre-indexed
5113// addressing.
5114bool EmulateInstructionARM::EmulateSTRThumb(const uint32_t opcode,
5115 const ARMEncoding encoding) {
5116#if 0
5117 if ConditionPassed() then
5118 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5119 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5120 address = if index then offset_addr else R[n];
5121 if UnalignedSupport() || address<1:0> == '00' then
5122 MemU[address,4] = R[t];
5123 else // Can only occur before ARMv7
5124 MemU[address,4] = bits(32) UNKNOWN;
5125 if wback then R[n] = offset_addr;
5126#endif
5127
5128 bool success = false;
5129
5130 if (ConditionPassed(opcode)) {
5131 const uint32_t addr_byte_size = GetAddressByteSize();
5132
5133 uint32_t t;
5134 uint32_t n;
5135 uint32_t imm32;
5136 bool index;
5137 bool add;
5138 bool wback;
5139 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
5140 switch (encoding) {
5141 case eEncodingT1:
5142 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:'00', 32);
5143 t = Bits32(bits: opcode, msbit: 2, lsbit: 0);
5144 n = Bits32(bits: opcode, msbit: 5, lsbit: 3);
5145 imm32 = Bits32(bits: opcode, msbit: 10, lsbit: 6) << 2;
5146
5147 // index = TRUE; add = TRUE; wback = FALSE;
5148 index = true;
5149 add = false;
5150 wback = false;
5151 break;
5152
5153 case eEncodingT2:
5154 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:'00', 32);
5155 t = Bits32(bits: opcode, msbit: 10, lsbit: 8);
5156 n = 13;
5157 imm32 = Bits32(bits: opcode, msbit: 7, lsbit: 0) << 2;
5158
5159 // index = TRUE; add = TRUE; wback = FALSE;
5160 index = true;
5161 add = true;
5162 wback = false;
5163 break;
5164
5165 case eEncodingT3:
5166 // if Rn == '1111' then UNDEFINED;
5167 if (Bits32(bits: opcode, msbit: 19, lsbit: 16) == 15)
5168 return false;
5169
5170 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
5171 t = Bits32(bits: opcode, msbit: 15, lsbit: 12);
5172 n = Bits32(bits: opcode, msbit: 19, lsbit: 16);
5173 imm32 = Bits32(bits: opcode, msbit: 11, lsbit: 0);
5174
5175 // index = TRUE; add = TRUE; wback = FALSE;
5176 index = true;
5177 add = true;
5178 wback = false;
5179
5180 // if t == 15 then UNPREDICTABLE;
5181 if (t == 15)
5182 return false;
5183 break;
5184
5185 case eEncodingT4:
5186 // if P == '1' && U == '1' && W == '0' then SEE STRT;
5187 // if Rn == '1101' && P == '1' && U == '0' && W == '1' && imm8 ==
5188 // '00000100' then SEE PUSH;
5189 // if Rn == '1111' || (P == '0' && W == '0') then UNDEFINED;
5190 if ((Bits32(bits: opcode, msbit: 19, lsbit: 16) == 15) ||
5191 (BitIsClear(value: opcode, bit: 10) && BitIsClear(value: opcode, bit: 8)))
5192 return false;
5193
5194 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
5195 t = Bits32(bits: opcode, msbit: 15, lsbit: 12);
5196 n = Bits32(bits: opcode, msbit: 19, lsbit: 16);
5197 imm32 = Bits32(bits: opcode, msbit: 7, lsbit: 0);
5198
5199 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
5200 index = BitIsSet(value: opcode, bit: 10);
5201 add = BitIsSet(value: opcode, bit: 9);
5202 wback = BitIsSet(value: opcode, bit: 8);
5203
5204 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
5205 if ((t == 15) || (wback && (n == t)))
5206 return false;
5207 break;
5208
5209 default:
5210 return false;
5211 }
5212
5213 addr_t offset_addr;
5214 addr_t address;
5215
5216 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5217 uint32_t base_address = ReadCoreReg(regnum: n, success: &success);
5218 if (!success)
5219 return false;
5220
5221 if (add)
5222 offset_addr = base_address + imm32;
5223 else
5224 offset_addr = base_address - imm32;
5225
5226 // address = if index then offset_addr else R[n];
5227 if (index)
5228 address = offset_addr;
5229 else
5230 address = base_address;
5231
5232 EmulateInstruction::Context context;
5233 if (n == 13)
5234 context.type = eContextPushRegisterOnStack;
5235 else
5236 context.type = eContextRegisterStore;
5237
5238 std::optional<RegisterInfo> base_reg =
5239 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n);
5240
5241 // if UnalignedSupport() || address<1:0> == '00' then
5242 if (UnalignedSupport() ||
5243 (BitIsClear(value: address, bit: 1) && BitIsClear(value: address, bit: 0))) {
5244 // MemU[address,4] = R[t];
5245 uint32_t data =
5246 ReadRegisterUnsigned(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + t, fail_value: 0, success_ptr: &success);
5247 if (!success)
5248 return false;
5249
5250 std::optional<RegisterInfo> data_reg =
5251 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + t);
5252 int32_t offset = address - base_address;
5253 context.SetRegisterToRegisterPlusOffset(data_reg: *data_reg, base_reg: *base_reg, offset);
5254 if (!MemUWrite(context, address, data_val: data, size: addr_byte_size))
5255 return false;
5256 } else {
5257 // MemU[address,4] = bits(32) UNKNOWN;
5258 WriteBits32UnknownToMemory(address);
5259 }
5260
5261 // if wback then R[n] = offset_addr;
5262 if (wback) {
5263 if (n == 13)
5264 context.type = eContextAdjustStackPointer;
5265 else
5266 context.type = eContextAdjustBaseRegister;
5267 context.SetAddress(offset_addr);
5268
5269 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n,
5270 reg_value: offset_addr))
5271 return false;
5272 }
5273 }
5274 return true;
5275}
5276
5277// STR (Store Register) calculates an address from a base register value and an
5278// offset register value, stores a
5279// word from a register to memory. The offset register value can optionally
5280// be shifted.
5281bool EmulateInstructionARM::EmulateSTRRegister(const uint32_t opcode,
5282 const ARMEncoding encoding) {
5283#if 0
5284 if ConditionPassed() then
5285 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5286 offset = Shift(R[m], shift_t, shift_n, APSR.C);
5287 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5288 address = if index then offset_addr else R[n];
5289 if t == 15 then // Only possible for encoding A1
5290 data = PCStoreValue();
5291 else
5292 data = R[t];
5293 if UnalignedSupport() || address<1:0> == '00' || CurrentInstrSet() == InstrSet_ARM then
5294 MemU[address,4] = data;
5295 else // Can only occur before ARMv7
5296 MemU[address,4] = bits(32) UNKNOWN;
5297 if wback then R[n] = offset_addr;
5298#endif
5299
5300 bool success = false;
5301
5302 if (ConditionPassed(opcode)) {
5303 const uint32_t addr_byte_size = GetAddressByteSize();
5304
5305 uint32_t t;
5306 uint32_t n;
5307 uint32_t m;
5308 ARM_ShifterType shift_t;
5309 uint32_t shift_n;
5310 bool index;
5311 bool add;
5312 bool wback;
5313
5314 // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
5315 switch (encoding) {
5316 case eEncodingT1:
5317 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation
5318 // in ThumbEE";
5319 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5320 t = Bits32(bits: opcode, msbit: 2, lsbit: 0);
5321 n = Bits32(bits: opcode, msbit: 5, lsbit: 3);
5322 m = Bits32(bits: opcode, msbit: 8, lsbit: 6);
5323
5324 // index = TRUE; add = TRUE; wback = FALSE;
5325 index = true;
5326 add = true;
5327 wback = false;
5328
5329 // (shift_t, shift_n) = (SRType_LSL, 0);
5330 shift_t = SRType_LSL;
5331 shift_n = 0;
5332 break;
5333
5334 case eEncodingT2:
5335 // if Rn == '1111' then UNDEFINED;
5336 if (Bits32(bits: opcode, msbit: 19, lsbit: 16) == 15)
5337 return false;
5338
5339 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5340 t = Bits32(bits: opcode, msbit: 15, lsbit: 12);
5341 n = Bits32(bits: opcode, msbit: 19, lsbit: 16);
5342 m = Bits32(bits: opcode, msbit: 3, lsbit: 0);
5343
5344 // index = TRUE; add = TRUE; wback = FALSE;
5345 index = true;
5346 add = true;
5347 wback = false;
5348
5349 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
5350 shift_t = SRType_LSL;
5351 shift_n = Bits32(bits: opcode, msbit: 5, lsbit: 4);
5352
5353 // if t == 15 || BadReg(m) then UNPREDICTABLE;
5354 if ((t == 15) || (BadReg(n: m)))
5355 return false;
5356 break;
5357
5358 case eEncodingA1: {
5359 // if P == '0' && W == '1' then SEE STRT;
5360 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5361 t = Bits32(bits: opcode, msbit: 15, lsbit: 12);
5362 n = Bits32(bits: opcode, msbit: 19, lsbit: 16);
5363 m = Bits32(bits: opcode, msbit: 3, lsbit: 0);
5364
5365 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
5366 // (W == '1');
5367 index = BitIsSet(value: opcode, bit: 24);
5368 add = BitIsSet(value: opcode, bit: 23);
5369 wback = (BitIsClear(value: opcode, bit: 24) || BitIsSet(value: opcode, bit: 21));
5370
5371 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
5372 uint32_t typ = Bits32(bits: opcode, msbit: 6, lsbit: 5);
5373 uint32_t imm5 = Bits32(bits: opcode, msbit: 11, lsbit: 7);
5374 shift_n = DecodeImmShift(type: typ, imm5, shift_t);
5375
5376 // if m == 15 then UNPREDICTABLE;
5377 if (m == 15)
5378 return false;
5379
5380 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
5381 if (wback && ((n == 15) || (n == t)))
5382 return false;
5383
5384 break;
5385 }
5386 default:
5387 return false;
5388 }
5389
5390 addr_t offset_addr;
5391 addr_t address;
5392 int32_t offset = 0;
5393
5394 addr_t base_address =
5395 ReadRegisterUnsigned(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n, fail_value: 0, success_ptr: &success);
5396 if (!success)
5397 return false;
5398
5399 uint32_t Rm_data =
5400 ReadRegisterUnsigned(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + m, fail_value: 0, success_ptr: &success);
5401 if (!success)
5402 return false;
5403
5404 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
5405 offset = Shift(value: Rm_data, type: shift_t, amount: shift_n, APSR_C, success: &success);
5406 if (!success)
5407 return false;
5408
5409 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5410 if (add)
5411 offset_addr = base_address + offset;
5412 else
5413 offset_addr = base_address - offset;
5414
5415 // address = if index then offset_addr else R[n];
5416 if (index)
5417 address = offset_addr;
5418 else
5419 address = base_address;
5420
5421 uint32_t data;
5422 // if t == 15 then // Only possible for encoding A1
5423 if (t == 15)
5424 // data = PCStoreValue();
5425 data = ReadCoreReg(PC_REG, success: &success);
5426 else
5427 // data = R[t];
5428 data =
5429 ReadRegisterUnsigned(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + t, fail_value: 0, success_ptr: &success);
5430
5431 if (!success)
5432 return false;
5433
5434 EmulateInstruction::Context context;
5435 context.type = eContextRegisterStore;
5436
5437 // if UnalignedSupport() || address<1:0> == '00' || CurrentInstrSet() ==
5438 // InstrSet_ARM then
5439 if (UnalignedSupport() ||
5440 (BitIsClear(value: address, bit: 1) && BitIsClear(value: address, bit: 0)) ||
5441 CurrentInstrSet() == eModeARM) {
5442 // MemU[address,4] = data;
5443
5444 std::optional<RegisterInfo> base_reg =
5445 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n);
5446 std::optional<RegisterInfo> data_reg =
5447 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + t);
5448
5449 context.SetRegisterToRegisterPlusOffset(data_reg: *data_reg, base_reg: *base_reg,
5450 offset: address - base_address);
5451 if (!MemUWrite(context, address, data_val: data, size: addr_byte_size))
5452 return false;
5453
5454 } else
5455 // MemU[address,4] = bits(32) UNKNOWN;
5456 WriteBits32UnknownToMemory(address);
5457
5458 // if wback then R[n] = offset_addr;
5459 if (wback) {
5460 context.type = eContextRegisterLoad;
5461 context.SetAddress(offset_addr);
5462 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n,
5463 reg_value: offset_addr))
5464 return false;
5465 }
5466 }
5467 return true;
5468}
5469
5470bool EmulateInstructionARM::EmulateSTRBThumb(const uint32_t opcode,
5471 const ARMEncoding encoding) {
5472#if 0
5473 if ConditionPassed() then
5474 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5475 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5476 address = if index then offset_addr else R[n];
5477 MemU[address,1] = R[t]<7:0>;
5478 if wback then R[n] = offset_addr;
5479#endif
5480
5481 bool success = false;
5482
5483 if (ConditionPassed(opcode)) {
5484 uint32_t t;
5485 uint32_t n;
5486 uint32_t imm32;
5487 bool index;
5488 bool add;
5489 bool wback;
5490 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5491 switch (encoding) {
5492 case eEncodingT1:
5493 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
5494 t = Bits32(bits: opcode, msbit: 2, lsbit: 0);
5495 n = Bits32(bits: opcode, msbit: 5, lsbit: 3);
5496 imm32 = Bits32(bits: opcode, msbit: 10, lsbit: 6);
5497
5498 // index = TRUE; add = TRUE; wback = FALSE;
5499 index = true;
5500 add = true;
5501 wback = false;
5502 break;
5503
5504 case eEncodingT2:
5505 // if Rn == '1111' then UNDEFINED;
5506 if (Bits32(bits: opcode, msbit: 19, lsbit: 16) == 15)
5507 return false;
5508
5509 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
5510 t = Bits32(bits: opcode, msbit: 15, lsbit: 12);
5511 n = Bits32(bits: opcode, msbit: 19, lsbit: 16);
5512 imm32 = Bits32(bits: opcode, msbit: 11, lsbit: 0);
5513
5514 // index = TRUE; add = TRUE; wback = FALSE;
5515 index = true;
5516 add = true;
5517 wback = false;
5518
5519 // if BadReg(t) then UNPREDICTABLE;
5520 if (BadReg(n: t))
5521 return false;
5522 break;
5523
5524 case eEncodingT3:
5525 // if P == '1' && U == '1' && W == '0' then SEE STRBT;
5526 // if Rn == '1111' || (P == '0' && W == '0') then UNDEFINED;
5527 if (Bits32(bits: opcode, msbit: 19, lsbit: 16) == 15)
5528 return false;
5529
5530 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
5531 t = Bits32(bits: opcode, msbit: 15, lsbit: 12);
5532 n = Bits32(bits: opcode, msbit: 19, lsbit: 16);
5533 imm32 = Bits32(bits: opcode, msbit: 7, lsbit: 0);
5534
5535 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
5536 index = BitIsSet(value: opcode, bit: 10);
5537 add = BitIsSet(value: opcode, bit: 9);
5538 wback = BitIsSet(value: opcode, bit: 8);
5539
5540 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE
5541 if ((BadReg(n: t)) || (wback && (n == t)))
5542 return false;
5543 break;
5544
5545 default:
5546 return false;
5547 }
5548
5549 addr_t offset_addr;
5550 addr_t address;
5551 addr_t base_address =
5552 ReadRegisterUnsigned(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n, fail_value: 0, success_ptr: &success);
5553 if (!success)
5554 return false;
5555
5556 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5557 if (add)
5558 offset_addr = base_address + imm32;
5559 else
5560 offset_addr = base_address - imm32;
5561
5562 // address = if index then offset_addr else R[n];
5563 if (index)
5564 address = offset_addr;
5565 else
5566 address = base_address;
5567
5568 // MemU[address,1] = R[t]<7:0>
5569 std::optional<RegisterInfo> base_reg =
5570 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n);
5571 std::optional<RegisterInfo> data_reg =
5572 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + t);
5573
5574 EmulateInstruction::Context context;
5575 context.type = eContextRegisterStore;
5576 context.SetRegisterToRegisterPlusOffset(data_reg: *data_reg, base_reg: *base_reg,
5577 offset: address - base_address);
5578
5579 uint32_t data =
5580 ReadRegisterUnsigned(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + t, fail_value: 0, success_ptr: &success);
5581 if (!success)
5582 return false;
5583
5584 data = Bits32(bits: data, msbit: 7, lsbit: 0);
5585
5586 if (!MemUWrite(context, address, data_val: data, size: 1))
5587 return false;
5588
5589 // if wback then R[n] = offset_addr;
5590 if (wback) {
5591 context.type = eContextRegisterLoad;
5592 context.SetAddress(offset_addr);
5593 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n,
5594 reg_value: offset_addr))
5595 return false;
5596 }
5597 }
5598
5599 return true;
5600}
5601
5602// STRH (register) calculates an address from a base register value and an
5603// offset register value, and stores a
5604// halfword from a register to memory. The offset register value can be
5605// shifted left by 0, 1, 2, or 3 bits.
5606bool EmulateInstructionARM::EmulateSTRHRegister(const uint32_t opcode,
5607 const ARMEncoding encoding) {
5608#if 0
5609 if ConditionPassed() then
5610 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5611 offset = Shift(R[m], shift_t, shift_n, APSR.C);
5612 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5613 address = if index then offset_addr else R[n];
5614 if UnalignedSupport() || address<0> == '0' then
5615 MemU[address,2] = R[t]<15:0>;
5616 else // Can only occur before ARMv7
5617 MemU[address,2] = bits(16) UNKNOWN;
5618 if wback then R[n] = offset_addr;
5619#endif
5620
5621 bool success = false;
5622
5623 if (ConditionPassed(opcode)) {
5624 uint32_t t;
5625 uint32_t n;
5626 uint32_t m;
5627 bool index;
5628 bool add;
5629 bool wback;
5630 ARM_ShifterType shift_t;
5631 uint32_t shift_n;
5632
5633 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
5634 switch (encoding) {
5635 case eEncodingT1:
5636 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation
5637 // in ThumbEE";
5638 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5639 t = Bits32(bits: opcode, msbit: 2, lsbit: 0);
5640 n = Bits32(bits: opcode, msbit: 5, lsbit: 3);
5641 m = Bits32(bits: opcode, msbit: 8, lsbit: 6);
5642
5643 // index = TRUE; add = TRUE; wback = FALSE;
5644 index = true;
5645 add = true;
5646 wback = false;
5647
5648 // (shift_t, shift_n) = (SRType_LSL, 0);
5649 shift_t = SRType_LSL;
5650 shift_n = 0;
5651
5652 break;
5653
5654 case eEncodingT2:
5655 // if Rn == '1111' then UNDEFINED;
5656 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5657 t = Bits32(bits: opcode, msbit: 15, lsbit: 12);
5658 n = Bits32(bits: opcode, msbit: 19, lsbit: 16);
5659 m = Bits32(bits: opcode, msbit: 3, lsbit: 0);
5660 if (n == 15)
5661 return false;
5662
5663 // index = TRUE; add = TRUE; wback = FALSE;
5664 index = true;
5665 add = true;
5666 wback = false;
5667
5668 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
5669 shift_t = SRType_LSL;
5670 shift_n = Bits32(bits: opcode, msbit: 5, lsbit: 4);
5671
5672 // if BadReg(t) || BadReg(m) then UNPREDICTABLE;
5673 if (BadReg(n: t) || BadReg(n: m))
5674 return false;
5675
5676 break;
5677
5678 case eEncodingA1:
5679 // if P == '0' && W == '1' then SEE STRHT;
5680 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5681 t = Bits32(bits: opcode, msbit: 15, lsbit: 12);
5682 n = Bits32(bits: opcode, msbit: 19, lsbit: 16);
5683 m = Bits32(bits: opcode, msbit: 3, lsbit: 0);
5684
5685 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
5686 // (W == '1');
5687 index = BitIsSet(value: opcode, bit: 24);
5688 add = BitIsSet(value: opcode, bit: 23);
5689 wback = (BitIsClear(value: opcode, bit: 24) || BitIsSet(value: opcode, bit: 21));
5690
5691 // (shift_t, shift_n) = (SRType_LSL, 0);
5692 shift_t = SRType_LSL;
5693 shift_n = 0;
5694
5695 // if t == 15 || m == 15 then UNPREDICTABLE;
5696 if ((t == 15) || (m == 15))
5697 return false;
5698
5699 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
5700 if (wback && ((n == 15) || (n == t)))
5701 return false;
5702
5703 break;
5704
5705 default:
5706 return false;
5707 }
5708
5709 uint32_t Rm = ReadCoreReg(regnum: m, success: &success);
5710 if (!success)
5711 return false;
5712
5713 uint32_t Rn = ReadCoreReg(regnum: n, success: &success);
5714 if (!success)
5715 return false;
5716
5717 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
5718 uint32_t offset = Shift(value: Rm, type: shift_t, amount: shift_n, APSR_C, success: &success);
5719 if (!success)
5720 return false;
5721
5722 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
5723 addr_t offset_addr;
5724 if (add)
5725 offset_addr = Rn + offset;
5726 else
5727 offset_addr = Rn - offset;
5728
5729 // address = if index then offset_addr else R[n];
5730 addr_t address;
5731 if (index)
5732 address = offset_addr;
5733 else
5734 address = Rn;
5735
5736 EmulateInstruction::Context context;
5737 context.type = eContextRegisterStore;
5738
5739 // if UnalignedSupport() || address<0> == '0' then
5740 if (UnalignedSupport() || BitIsClear(value: address, bit: 0)) {
5741 // MemU[address,2] = R[t]<15:0>;
5742 uint32_t Rt = ReadCoreReg(regnum: t, success: &success);
5743 if (!success)
5744 return false;
5745
5746 EmulateInstruction::Context context;
5747 context.type = eContextRegisterStore;
5748 std::optional<RegisterInfo> base_reg =
5749 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n);
5750 std::optional<RegisterInfo> offset_reg =
5751 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + m);
5752 std::optional<RegisterInfo> data_reg =
5753 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + t);
5754 context.SetRegisterToRegisterPlusIndirectOffset(base_reg: *base_reg, offset_reg: *offset_reg,
5755 data_reg: *data_reg);
5756
5757 if (!MemUWrite(context, address, data_val: Bits32(bits: Rt, msbit: 15, lsbit: 0), size: 2))
5758 return false;
5759 } else // Can only occur before ARMv7
5760 {
5761 // MemU[address,2] = bits(16) UNKNOWN;
5762 }
5763
5764 // if wback then R[n] = offset_addr;
5765 if (wback) {
5766 context.type = eContextAdjustBaseRegister;
5767 context.SetAddress(offset_addr);
5768 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n,
5769 reg_value: offset_addr))
5770 return false;
5771 }
5772 }
5773
5774 return true;
5775}
5776
5777// Add with Carry (immediate) adds an immediate value and the carry flag value
5778// to a register value, and writes the result to the destination register. It
5779// can optionally update the condition flags based on the result.
5780bool EmulateInstructionARM::EmulateADCImm(const uint32_t opcode,
5781 const ARMEncoding encoding) {
5782#if 0
5783 // ARM pseudo code...
5784 if ConditionPassed() then
5785 EncodingSpecificOperations();
5786 (result, carry, overflow) = AddWithCarry(R[n], imm32, APSR.C);
5787 if d == 15 then // Can only occur for ARM encoding
5788 ALUWritePC(result); // setflags is always FALSE here
5789 else
5790 R[d] = result;
5791 if setflags then
5792 APSR.N = result<31>;
5793 APSR.Z = IsZeroBit(result);
5794 APSR.C = carry;
5795 APSR.V = overflow;
5796#endif
5797
5798 bool success = false;
5799
5800 if (ConditionPassed(opcode)) {
5801 uint32_t Rd, Rn;
5802 uint32_t
5803 imm32; // the immediate value to be added to the value obtained from Rn
5804 bool setflags;
5805 switch (encoding) {
5806 case eEncodingT1:
5807 Rd = Bits32(bits: opcode, msbit: 11, lsbit: 8);
5808 Rn = Bits32(bits: opcode, msbit: 19, lsbit: 16);
5809 setflags = BitIsSet(value: opcode, bit: 20);
5810 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
5811 if (BadReg(n: Rd) || BadReg(n: Rn))
5812 return false;
5813 break;
5814 case eEncodingA1:
5815 Rd = Bits32(bits: opcode, msbit: 15, lsbit: 12);
5816 Rn = Bits32(bits: opcode, msbit: 19, lsbit: 16);
5817 setflags = BitIsSet(value: opcode, bit: 20);
5818 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
5819
5820 if (Rd == 15 && setflags)
5821 return EmulateSUBSPcLrEtc(opcode, encoding);
5822 break;
5823 default:
5824 return false;
5825 }
5826
5827 // Read the first operand.
5828 int32_t val1 = ReadCoreReg(regnum: Rn, success: &success);
5829 if (!success)
5830 return false;
5831
5832 AddWithCarryResult res = AddWithCarry(x: val1, y: imm32, APSR_C);
5833
5834 EmulateInstruction::Context context;
5835 context.type = EmulateInstruction::eContextImmediate;
5836 context.SetNoArgs();
5837
5838 if (!WriteCoreRegOptionalFlags(context, result: res.result, Rd, setflags,
5839 carry: res.carry_out, overflow: res.overflow))
5840 return false;
5841 }
5842 return true;
5843}
5844
5845// Add with Carry (register) adds a register value, the carry flag value, and
5846// an optionally-shifted register value, and writes the result to the
5847// destination register. It can optionally update the condition flags based on
5848// the result.
5849bool EmulateInstructionARM::EmulateADCReg(const uint32_t opcode,
5850 const ARMEncoding encoding) {
5851#if 0
5852 // ARM pseudo code...
5853 if ConditionPassed() then
5854 EncodingSpecificOperations();
5855 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
5856 (result, carry, overflow) = AddWithCarry(R[n], shifted, APSR.C);
5857 if d == 15 then // Can only occur for ARM encoding
5858 ALUWritePC(result); // setflags is always FALSE here
5859 else
5860 R[d] = result;
5861 if setflags then
5862 APSR.N = result<31>;
5863 APSR.Z = IsZeroBit(result);
5864 APSR.C = carry;
5865 APSR.V = overflow;
5866#endif
5867
5868 bool success = false;
5869
5870 if (ConditionPassed(opcode)) {
5871 uint32_t Rd, Rn, Rm;
5872 ARM_ShifterType shift_t;
5873 uint32_t shift_n; // the shift applied to the value read from Rm
5874 bool setflags;
5875 switch (encoding) {
5876 case eEncodingT1:
5877 Rd = Rn = Bits32(bits: opcode, msbit: 2, lsbit: 0);
5878 Rm = Bits32(bits: opcode, msbit: 5, lsbit: 3);
5879 setflags = !InITBlock();
5880 shift_t = SRType_LSL;
5881 shift_n = 0;
5882 break;
5883 case eEncodingT2:
5884 Rd = Bits32(bits: opcode, msbit: 11, lsbit: 8);
5885 Rn = Bits32(bits: opcode, msbit: 19, lsbit: 16);
5886 Rm = Bits32(bits: opcode, msbit: 3, lsbit: 0);
5887 setflags = BitIsSet(value: opcode, bit: 20);
5888 shift_n = DecodeImmShiftThumb(opcode, shift_t);
5889 if (BadReg(n: Rd) || BadReg(n: Rn) || BadReg(n: Rm))
5890 return false;
5891 break;
5892 case eEncodingA1:
5893 Rd = Bits32(bits: opcode, msbit: 15, lsbit: 12);
5894 Rn = Bits32(bits: opcode, msbit: 19, lsbit: 16);
5895 Rm = Bits32(bits: opcode, msbit: 3, lsbit: 0);
5896 setflags = BitIsSet(value: opcode, bit: 20);
5897 shift_n = DecodeImmShiftARM(opcode, shift_t);
5898
5899 if (Rd == 15 && setflags)
5900 return EmulateSUBSPcLrEtc(opcode, encoding);
5901 break;
5902 default:
5903 return false;
5904 }
5905
5906 // Read the first operand.
5907 int32_t val1 = ReadCoreReg(regnum: Rn, success: &success);
5908 if (!success)
5909 return false;
5910
5911 // Read the second operand.
5912 int32_t val2 = ReadCoreReg(regnum: Rm, success: &success);
5913 if (!success)
5914 return false;
5915
5916 uint32_t shifted = Shift(value: val2, type: shift_t, amount: shift_n, APSR_C, success: &success);
5917 if (!success)
5918 return false;
5919 AddWithCarryResult res = AddWithCarry(x: val1, y: shifted, APSR_C);
5920
5921 EmulateInstruction::Context context;
5922 context.type = EmulateInstruction::eContextImmediate;
5923 context.SetNoArgs();
5924
5925 if (!WriteCoreRegOptionalFlags(context, result: res.result, Rd, setflags,
5926 carry: res.carry_out, overflow: res.overflow))
5927 return false;
5928 }
5929 return true;
5930}
5931
5932// This instruction adds an immediate value to the PC value to form a PC-
5933// relative address, and writes the result to the destination register.
5934bool EmulateInstructionARM::EmulateADR(const uint32_t opcode,
5935 const ARMEncoding encoding) {
5936#if 0
5937 // ARM pseudo code...
5938 if ConditionPassed() then
5939 EncodingSpecificOperations();
5940 result = if add then (Align(PC,4) + imm32) else (Align(PC,4) - imm32);
5941 if d == 15 then // Can only occur for ARM encodings
5942 ALUWritePC(result);
5943 else
5944 R[d] = result;
5945#endif
5946
5947 bool success = false;
5948
5949 if (ConditionPassed(opcode)) {
5950 uint32_t Rd;
5951 uint32_t imm32; // the immediate value to be added/subtracted to/from the PC
5952 bool add;
5953 switch (encoding) {
5954 case eEncodingT1:
5955 Rd = Bits32(bits: opcode, msbit: 10, lsbit: 8);
5956 imm32 = ThumbImm8Scaled(opcode); // imm32 = ZeroExtend(imm8:'00', 32)
5957 add = true;
5958 break;
5959 case eEncodingT2:
5960 case eEncodingT3:
5961 Rd = Bits32(bits: opcode, msbit: 11, lsbit: 8);
5962 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
5963 add = (Bits32(bits: opcode, msbit: 24, lsbit: 21) == 0); // 0b0000 => ADD; 0b0101 => SUB
5964 if (BadReg(n: Rd))
5965 return false;
5966 break;
5967 case eEncodingA1:
5968 case eEncodingA2:
5969 Rd = Bits32(bits: opcode, msbit: 15, lsbit: 12);
5970 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
5971 add = (Bits32(bits: opcode, msbit: 24, lsbit: 21) == 0x4); // 0b0100 => ADD; 0b0010 => SUB
5972 break;
5973 default:
5974 return false;
5975 }
5976
5977 // Read the PC value.
5978 uint32_t pc = ReadCoreReg(PC_REG, success: &success);
5979 if (!success)
5980 return false;
5981
5982 uint32_t result = (add ? Align(val: pc, alignment: 4) + imm32 : Align(val: pc, alignment: 4) - imm32);
5983
5984 EmulateInstruction::Context context;
5985 context.type = EmulateInstruction::eContextImmediate;
5986 context.SetNoArgs();
5987
5988 if (!WriteCoreReg(context, result, Rd))
5989 return false;
5990 }
5991 return true;
5992}
5993
5994// This instruction performs a bitwise AND of a register value and an immediate
5995// value, and writes the result to the destination register. It can optionally
5996// update the condition flags based on the result.
5997bool EmulateInstructionARM::EmulateANDImm(const uint32_t opcode,
5998 const ARMEncoding encoding) {
5999#if 0
6000 // ARM pseudo code...
6001 if ConditionPassed() then
6002 EncodingSpecificOperations();
6003 result = R[n] AND imm32;
6004 if d == 15 then // Can only occur for ARM encoding
6005 ALUWritePC(result); // setflags is always FALSE here
6006 else
6007 R[d] = result;
6008 if setflags then
6009 APSR.N = result<31>;
6010 APSR.Z = IsZeroBit(result);
6011 APSR.C = carry;
6012 // APSR.V unchanged
6013#endif
6014
6015 bool success = false;
6016
6017 if (ConditionPassed(opcode)) {
6018 uint32_t Rd, Rn;
6019 uint32_t
6020 imm32; // the immediate value to be ANDed to the value obtained from Rn
6021 bool setflags;
6022 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
6023 switch (encoding) {
6024 case eEncodingT1:
6025 Rd = Bits32(bits: opcode, msbit: 11, lsbit: 8);
6026 Rn = Bits32(bits: opcode, msbit: 19, lsbit: 16);
6027 setflags = BitIsSet(value: opcode, bit: 20);
6028 imm32 = ThumbExpandImm_C(
6029 opcode, APSR_C,
6030 carry_out&: carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
6031 // if Rd == '1111' && S == '1' then SEE TST (immediate);
6032 if (Rd == 15 && setflags)
6033 return EmulateTSTImm(opcode, encoding: eEncodingT1);
6034 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(n: Rn))
6035 return false;
6036 break;
6037 case eEncodingA1:
6038 Rd = Bits32(bits: opcode, msbit: 15, lsbit: 12);
6039 Rn = Bits32(bits: opcode, msbit: 19, lsbit: 16);
6040 setflags = BitIsSet(value: opcode, bit: 20);
6041 imm32 =
6042 ARMExpandImm_C(opcode, APSR_C,
6043 carry_out&: carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
6044
6045 if (Rd == 15 && setflags)
6046 return EmulateSUBSPcLrEtc(opcode, encoding);
6047 break;
6048 default:
6049 return false;
6050 }
6051
6052 // Read the first operand.
6053 uint32_t val1 = ReadCoreReg(regnum: Rn, success: &success);
6054 if (!success)
6055 return false;
6056
6057 uint32_t result = val1 & imm32;
6058
6059 EmulateInstruction::Context context;
6060 context.type = EmulateInstruction::eContextImmediate;
6061 context.SetNoArgs();
6062
6063 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
6064 return false;
6065 }
6066 return true;
6067}
6068
6069// This instruction performs a bitwise AND of a register value and an
6070// optionally-shifted register value, and writes the result to the destination
6071// register. It can optionally update the condition flags based on the result.
6072bool EmulateInstructionARM::EmulateANDReg(const uint32_t opcode,
6073 const ARMEncoding encoding) {
6074#if 0
6075 // ARM pseudo code...
6076 if ConditionPassed() then
6077 EncodingSpecificOperations();
6078 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
6079 result = R[n] AND shifted;
6080 if d == 15 then // Can only occur for ARM encoding
6081 ALUWritePC(result); // setflags is always FALSE here
6082 else
6083 R[d] = result;
6084 if setflags then
6085 APSR.N = result<31>;
6086 APSR.Z = IsZeroBit(result);
6087 APSR.C = carry;
6088 // APSR.V unchanged
6089#endif
6090
6091 bool success = false;
6092
6093 if (ConditionPassed(opcode)) {
6094 uint32_t Rd, Rn, Rm;
6095 ARM_ShifterType shift_t;
6096 uint32_t shift_n; // the shift applied to the value read from Rm
6097 bool setflags;
6098 uint32_t carry;
6099 switch (encoding) {
6100 case eEncodingT1:
6101 Rd = Rn = Bits32(bits: opcode, msbit: 2, lsbit: 0);
6102 Rm = Bits32(bits: opcode, msbit: 5, lsbit: 3);
6103 setflags = !InITBlock();
6104 shift_t = SRType_LSL;
6105 shift_n = 0;
6106 break;
6107 case eEncodingT2:
6108 Rd = Bits32(bits: opcode, msbit: 11, lsbit: 8);
6109 Rn = Bits32(bits: opcode, msbit: 19, lsbit: 16);
6110 Rm = Bits32(bits: opcode, msbit: 3, lsbit: 0);
6111 setflags = BitIsSet(value: opcode, bit: 20);
6112 shift_n = DecodeImmShiftThumb(opcode, shift_t);
6113 // if Rd == '1111' && S == '1' then SEE TST (register);
6114 if (Rd == 15 && setflags)
6115 return EmulateTSTReg(opcode, encoding: eEncodingT2);
6116 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(n: Rn) || BadReg(n: Rm))
6117 return false;
6118 break;
6119 case eEncodingA1:
6120 Rd = Bits32(bits: opcode, msbit: 15, lsbit: 12);
6121 Rn = Bits32(bits: opcode, msbit: 19, lsbit: 16);
6122 Rm = Bits32(bits: opcode, msbit: 3, lsbit: 0);
6123 setflags = BitIsSet(value: opcode, bit: 20);
6124 shift_n = DecodeImmShiftARM(opcode, shift_t);
6125
6126 if (Rd == 15 && setflags)
6127 return EmulateSUBSPcLrEtc(opcode, encoding);
6128 break;
6129 default:
6130 return false;
6131 }
6132
6133 // Read the first operand.
6134 uint32_t val1 = ReadCoreReg(regnum: Rn, success: &success);
6135 if (!success)
6136 return false;
6137
6138 // Read the second operand.
6139 uint32_t val2 = ReadCoreReg(regnum: Rm, success: &success);
6140 if (!success)
6141 return false;
6142
6143 uint32_t shifted = Shift_C(value: val2, type: shift_t, amount: shift_n, APSR_C, carry_out&: carry, success: &success);
6144 if (!success)
6145 return false;
6146 uint32_t result = val1 & shifted;
6147
6148 EmulateInstruction::Context context;
6149 context.type = EmulateInstruction::eContextImmediate;
6150 context.SetNoArgs();
6151
6152 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
6153 return false;
6154 }
6155 return true;
6156}
6157
6158// Bitwise Bit Clear (immediate) performs a bitwise AND of a register value and
6159// the complement of an immediate value, and writes the result to the
6160// destination register. It can optionally update the condition flags based on
6161// the result.
6162bool EmulateInstructionARM::EmulateBICImm(const uint32_t opcode,
6163 const ARMEncoding encoding) {
6164#if 0
6165 // ARM pseudo code...
6166 if ConditionPassed() then
6167 EncodingSpecificOperations();
6168 result = R[n] AND NOT(imm32);
6169 if d == 15 then // Can only occur for ARM encoding
6170 ALUWritePC(result); // setflags is always FALSE here
6171 else
6172 R[d] = result;
6173 if setflags then
6174 APSR.N = result<31>;
6175 APSR.Z = IsZeroBit(result);
6176 APSR.C = carry;
6177 // APSR.V unchanged
6178#endif
6179
6180 bool success = false;
6181
6182 if (ConditionPassed(opcode)) {
6183 uint32_t Rd, Rn;
6184 uint32_t imm32; // the immediate value to be bitwise inverted and ANDed to
6185 // the value obtained from Rn
6186 bool setflags;
6187 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
6188 switch (encoding) {
6189 case eEncodingT1:
6190 Rd = Bits32(bits: opcode, msbit: 11, lsbit: 8);
6191 Rn = Bits32(bits: opcode, msbit: 19, lsbit: 16);
6192 setflags = BitIsSet(value: opcode, bit: 20);
6193 imm32 = ThumbExpandImm_C(
6194 opcode, APSR_C,
6195 carry_out&: carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
6196 if (BadReg(n: Rd) || BadReg(n: Rn))
6197 return false;
6198 break;
6199 case eEncodingA1:
6200 Rd = Bits32(bits: opcode, msbit: 15, lsbit: 12);
6201 Rn = Bits32(bits: opcode, msbit: 19, lsbit: 16);
6202 setflags = BitIsSet(value: opcode, bit: 20);
6203 imm32 =
6204 ARMExpandImm_C(opcode, APSR_C,
6205 carry_out&: carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
6206
6207 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
6208 // instructions;
6209 if (Rd == 15 && setflags)
6210 return EmulateSUBSPcLrEtc(opcode, encoding);
6211 break;
6212 default:
6213 return false;
6214 }
6215
6216 // Read the first operand.
6217 uint32_t val1 = ReadCoreReg(regnum: Rn, success: &success);
6218 if (!success)
6219 return false;
6220
6221 uint32_t result = val1 & ~imm32;
6222
6223 EmulateInstruction::Context context;
6224 context.type = EmulateInstruction::eContextImmediate;
6225 context.SetNoArgs();
6226
6227 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
6228 return false;
6229 }
6230 return true;
6231}
6232
6233// Bitwise Bit Clear (register) performs a bitwise AND of a register value and
6234// the complement of an optionally-shifted register value, and writes the
6235// result to the destination register. It can optionally update the condition
6236// flags based on the result.
6237bool EmulateInstructionARM::EmulateBICReg(const uint32_t opcode,
6238 const ARMEncoding encoding) {
6239#if 0
6240 // ARM pseudo code...
6241 if ConditionPassed() then
6242 EncodingSpecificOperations();
6243 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
6244 result = R[n] AND NOT(shifted);
6245 if d == 15 then // Can only occur for ARM encoding
6246 ALUWritePC(result); // setflags is always FALSE here
6247 else
6248 R[d] = result;
6249 if setflags then
6250 APSR.N = result<31>;
6251 APSR.Z = IsZeroBit(result);
6252 APSR.C = carry;
6253 // APSR.V unchanged
6254#endif
6255
6256 bool success = false;
6257
6258 if (ConditionPassed(opcode)) {
6259 uint32_t Rd, Rn, Rm;
6260 ARM_ShifterType shift_t;
6261 uint32_t shift_n; // the shift applied to the value read from Rm
6262 bool setflags;
6263 uint32_t carry;
6264 switch (encoding) {
6265 case eEncodingT1:
6266 Rd = Rn = Bits32(bits: opcode, msbit: 2, lsbit: 0);
6267 Rm = Bits32(bits: opcode, msbit: 5, lsbit: 3);
6268 setflags = !InITBlock();
6269 shift_t = SRType_LSL;
6270 shift_n = 0;
6271 break;
6272 case eEncodingT2:
6273 Rd = Bits32(bits: opcode, msbit: 11, lsbit: 8);
6274 Rn = Bits32(bits: opcode, msbit: 19, lsbit: 16);
6275 Rm = Bits32(bits: opcode, msbit: 3, lsbit: 0);
6276 setflags = BitIsSet(value: opcode, bit: 20);
6277 shift_n = DecodeImmShiftThumb(opcode, shift_t);
6278 if (BadReg(n: Rd) || BadReg(n: Rn) || BadReg(n: Rm))
6279 return false;
6280 break;
6281 case eEncodingA1:
6282 Rd = Bits32(bits: opcode, msbit: 15, lsbit: 12);
6283 Rn = Bits32(bits: opcode, msbit: 19, lsbit: 16);
6284 Rm = Bits32(bits: opcode, msbit: 3, lsbit: 0);
6285 setflags = BitIsSet(value: opcode, bit: 20);
6286 shift_n = DecodeImmShiftARM(opcode, shift_t);
6287
6288 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
6289 // instructions;
6290 if (Rd == 15 && setflags)
6291 return EmulateSUBSPcLrEtc(opcode, encoding);
6292 break;
6293 default:
6294 return false;
6295 }
6296
6297 // Read the first operand.
6298 uint32_t val1 = ReadCoreReg(regnum: Rn, success: &success);
6299 if (!success)
6300 return false;
6301
6302 // Read the second operand.
6303 uint32_t val2 = ReadCoreReg(regnum: Rm, success: &success);
6304 if (!success)
6305 return false;
6306
6307 uint32_t shifted = Shift_C(value: val2, type: shift_t, amount: shift_n, APSR_C, carry_out&: carry, success: &success);
6308 if (!success)
6309 return false;
6310 uint32_t result = val1 & ~shifted;
6311
6312 EmulateInstruction::Context context;
6313 context.type = EmulateInstruction::eContextImmediate;
6314 context.SetNoArgs();
6315
6316 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
6317 return false;
6318 }
6319 return true;
6320}
6321
6322// LDR (immediate, ARM) calculates an address from a base register value and an
6323// immediate offset, loads a word
6324// from memory, and writes it to a register. It can use offset, post-indexed,
6325// or pre-indexed addressing.
6326bool EmulateInstructionARM::EmulateLDRImmediateARM(const uint32_t opcode,
6327 const ARMEncoding encoding) {
6328#if 0
6329 if ConditionPassed() then
6330 EncodingSpecificOperations();
6331 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6332 address = if index then offset_addr else R[n];
6333 data = MemU[address,4];
6334 if wback then R[n] = offset_addr;
6335 if t == 15 then
6336 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
6337 elsif UnalignedSupport() || address<1:0> = '00' then
6338 R[t] = data;
6339 else // Can only apply before ARMv7
6340 R[t] = ROR(data, 8*UInt(address<1:0>));
6341#endif
6342
6343 bool success = false;
6344
6345 if (ConditionPassed(opcode)) {
6346 const uint32_t addr_byte_size = GetAddressByteSize();
6347
6348 uint32_t t;
6349 uint32_t n;
6350 uint32_t imm32;
6351 bool index;
6352 bool add;
6353 bool wback;
6354
6355 switch (encoding) {
6356 case eEncodingA1:
6357 // if Rn == '1111' then SEE LDR (literal);
6358 // if P == '0' && W == '1' then SEE LDRT;
6359 // if Rn == '1101' && P == '0' && U == '1' && W == '0' && imm12 ==
6360 // '000000000100' then SEE POP;
6361 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6362 t = Bits32(bits: opcode, msbit: 15, lsbit: 12);
6363 n = Bits32(bits: opcode, msbit: 19, lsbit: 16);
6364 imm32 = Bits32(bits: opcode, msbit: 11, lsbit: 0);
6365
6366 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
6367 // (W == '1');
6368 index = BitIsSet(value: opcode, bit: 24);
6369 add = BitIsSet(value: opcode, bit: 23);
6370 wback = (BitIsClear(value: opcode, bit: 24) || BitIsSet(value: opcode, bit: 21));
6371
6372 // if wback && n == t then UNPREDICTABLE;
6373 if (wback && (n == t))
6374 return false;
6375
6376 break;
6377
6378 default:
6379 return false;
6380 }
6381
6382 addr_t address;
6383 addr_t offset_addr;
6384 addr_t base_address = ReadCoreReg(regnum: n, success: &success);
6385 if (!success)
6386 return false;
6387
6388 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6389 if (add)
6390 offset_addr = base_address + imm32;
6391 else
6392 offset_addr = base_address - imm32;
6393
6394 // address = if index then offset_addr else R[n];
6395 if (index)
6396 address = offset_addr;
6397 else
6398 address = base_address;
6399
6400 // data = MemU[address,4];
6401
6402 std::optional<RegisterInfo> base_reg =
6403 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n);
6404 EmulateInstruction::Context context;
6405 context.type = eContextRegisterLoad;
6406 context.SetRegisterPlusOffset(base_reg: *base_reg, signed_offset: address - base_address);
6407
6408 uint64_t data = MemURead(context, address, size: addr_byte_size, fail_value: 0, success_ptr: &success);
6409 if (!success)
6410 return false;
6411
6412 // if wback then R[n] = offset_addr;
6413 if (wback) {
6414 context.type = eContextAdjustBaseRegister;
6415 context.SetAddress(offset_addr);
6416 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n,
6417 reg_value: offset_addr))
6418 return false;
6419 }
6420
6421 // if t == 15 then
6422 if (t == 15) {
6423 // if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
6424 if (BitIsClear(value: address, bit: 1) && BitIsClear(value: address, bit: 0)) {
6425 // LoadWritePC (data);
6426 context.type = eContextRegisterLoad;
6427 context.SetRegisterPlusOffset(base_reg: *base_reg, signed_offset: address - base_address);
6428 LoadWritePC(context, addr: data);
6429 } else
6430 return false;
6431 }
6432 // elsif UnalignedSupport() || address<1:0> = '00' then
6433 else if (UnalignedSupport() ||
6434 (BitIsClear(value: address, bit: 1) && BitIsClear(value: address, bit: 0))) {
6435 // R[t] = data;
6436 context.type = eContextRegisterLoad;
6437 context.SetRegisterPlusOffset(base_reg: *base_reg, signed_offset: address - base_address);
6438 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + t,
6439 reg_value: data))
6440 return false;
6441 }
6442 // else // Can only apply before ARMv7
6443 else {
6444 // R[t] = ROR(data, 8*UInt(address<1:0>));
6445 data = ROR(value: data, amount: Bits32(bits: address, msbit: 1, lsbit: 0), success: &success);
6446 if (!success)
6447 return false;
6448 context.type = eContextRegisterLoad;
6449 context.SetImmediate(data);
6450 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + t,
6451 reg_value: data))
6452 return false;
6453 }
6454 }
6455 return true;
6456}
6457
6458// LDR (register) calculates an address from a base register value and an offset
6459// register value, loads a word
6460// from memory, and writes it to a register. The offset register value can
6461// optionally be shifted.
6462bool EmulateInstructionARM::EmulateLDRRegister(const uint32_t opcode,
6463 const ARMEncoding encoding) {
6464#if 0
6465 if ConditionPassed() then
6466 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6467 offset = Shift(R[m], shift_t, shift_n, APSR.C);
6468 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6469 address = if index then offset_addr else R[n];
6470 data = MemU[address,4];
6471 if wback then R[n] = offset_addr;
6472 if t == 15 then
6473 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
6474 elsif UnalignedSupport() || address<1:0> = '00' then
6475 R[t] = data;
6476 else // Can only apply before ARMv7
6477 if CurrentInstrSet() == InstrSet_ARM then
6478 R[t] = ROR(data, 8*UInt(address<1:0>));
6479 else
6480 R[t] = bits(32) UNKNOWN;
6481#endif
6482
6483 bool success = false;
6484
6485 if (ConditionPassed(opcode)) {
6486 const uint32_t addr_byte_size = GetAddressByteSize();
6487
6488 uint32_t t;
6489 uint32_t n;
6490 uint32_t m;
6491 bool index;
6492 bool add;
6493 bool wback;
6494 ARM_ShifterType shift_t;
6495 uint32_t shift_n;
6496
6497 switch (encoding) {
6498 case eEncodingT1:
6499 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation
6500 // in ThumbEE";
6501 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6502 t = Bits32(bits: opcode, msbit: 2, lsbit: 0);
6503 n = Bits32(bits: opcode, msbit: 5, lsbit: 3);
6504 m = Bits32(bits: opcode, msbit: 8, lsbit: 6);
6505
6506 // index = TRUE; add = TRUE; wback = FALSE;
6507 index = true;
6508 add = true;
6509 wback = false;
6510
6511 // (shift_t, shift_n) = (SRType_LSL, 0);
6512 shift_t = SRType_LSL;
6513 shift_n = 0;
6514
6515 break;
6516
6517 case eEncodingT2:
6518 // if Rn == '1111' then SEE LDR (literal);
6519 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6520 t = Bits32(bits: opcode, msbit: 15, lsbit: 12);
6521 n = Bits32(bits: opcode, msbit: 19, lsbit: 16);
6522 m = Bits32(bits: opcode, msbit: 3, lsbit: 0);
6523
6524 // index = TRUE; add = TRUE; wback = FALSE;
6525 index = true;
6526 add = true;
6527 wback = false;
6528
6529 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
6530 shift_t = SRType_LSL;
6531 shift_n = Bits32(bits: opcode, msbit: 5, lsbit: 4);
6532
6533 // if BadReg(m) then UNPREDICTABLE;
6534 if (BadReg(n: m))
6535 return false;
6536
6537 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
6538 if ((t == 15) && InITBlock() && !LastInITBlock())
6539 return false;
6540
6541 break;
6542
6543 case eEncodingA1: {
6544 // if P == '0' && W == '1' then SEE LDRT;
6545 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6546 t = Bits32(bits: opcode, msbit: 15, lsbit: 12);
6547 n = Bits32(bits: opcode, msbit: 19, lsbit: 16);
6548 m = Bits32(bits: opcode, msbit: 3, lsbit: 0);
6549
6550 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
6551 // (W == '1');
6552 index = BitIsSet(value: opcode, bit: 24);
6553 add = BitIsSet(value: opcode, bit: 23);
6554 wback = (BitIsClear(value: opcode, bit: 24) || BitIsSet(value: opcode, bit: 21));
6555
6556 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
6557 uint32_t type = Bits32(bits: opcode, msbit: 6, lsbit: 5);
6558 uint32_t imm5 = Bits32(bits: opcode, msbit: 11, lsbit: 7);
6559 shift_n = DecodeImmShift(type, imm5, shift_t);
6560
6561 // if m == 15 then UNPREDICTABLE;
6562 if (m == 15)
6563 return false;
6564
6565 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
6566 if (wback && ((n == 15) || (n == t)))
6567 return false;
6568 } break;
6569
6570 default:
6571 return false;
6572 }
6573
6574 uint32_t Rm =
6575 ReadRegisterUnsigned(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + m, fail_value: 0, success_ptr: &success);
6576 if (!success)
6577 return false;
6578
6579 uint32_t Rn =
6580 ReadRegisterUnsigned(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n, fail_value: 0, success_ptr: &success);
6581 if (!success)
6582 return false;
6583
6584 addr_t offset_addr;
6585 addr_t address;
6586
6587 // offset = Shift(R[m], shift_t, shift_n, APSR.C); -- Note "The APSR is
6588 // an application level alias for the CPSR".
6589 addr_t offset =
6590 Shift(value: Rm, type: shift_t, amount: shift_n, carry_in: Bit32(bits: m_opcode_cpsr, APSR_C), success: &success);
6591 if (!success)
6592 return false;
6593
6594 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6595 if (add)
6596 offset_addr = Rn + offset;
6597 else
6598 offset_addr = Rn - offset;
6599
6600 // address = if index then offset_addr else R[n];
6601 if (index)
6602 address = offset_addr;
6603 else
6604 address = Rn;
6605
6606 // data = MemU[address,4];
6607 std::optional<RegisterInfo> base_reg =
6608 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n);
6609 EmulateInstruction::Context context;
6610 context.type = eContextRegisterLoad;
6611 context.SetRegisterPlusOffset(base_reg: *base_reg, signed_offset: address - Rn);
6612
6613 uint64_t data = MemURead(context, address, size: addr_byte_size, fail_value: 0, success_ptr: &success);
6614 if (!success)
6615 return false;
6616
6617 // if wback then R[n] = offset_addr;
6618 if (wback) {
6619 context.type = eContextAdjustBaseRegister;
6620 context.SetAddress(offset_addr);
6621 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n,
6622 reg_value: offset_addr))
6623 return false;
6624 }
6625
6626 // if t == 15 then
6627 if (t == 15) {
6628 // if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
6629 if (BitIsClear(value: address, bit: 1) && BitIsClear(value: address, bit: 0)) {
6630 context.type = eContextRegisterLoad;
6631 context.SetRegisterPlusOffset(base_reg: *base_reg, signed_offset: address - Rn);
6632 LoadWritePC(context, addr: data);
6633 } else
6634 return false;
6635 }
6636 // elsif UnalignedSupport() || address<1:0> = '00' then
6637 else if (UnalignedSupport() ||
6638 (BitIsClear(value: address, bit: 1) && BitIsClear(value: address, bit: 0))) {
6639 // R[t] = data;
6640 context.type = eContextRegisterLoad;
6641 context.SetRegisterPlusOffset(base_reg: *base_reg, signed_offset: address - Rn);
6642 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + t,
6643 reg_value: data))
6644 return false;
6645 } else // Can only apply before ARMv7
6646 {
6647 // if CurrentInstrSet() == InstrSet_ARM then
6648 if (CurrentInstrSet() == eModeARM) {
6649 // R[t] = ROR(data, 8*UInt(address<1:0>));
6650 data = ROR(value: data, amount: Bits32(bits: address, msbit: 1, lsbit: 0), success: &success);
6651 if (!success)
6652 return false;
6653 context.type = eContextRegisterLoad;
6654 context.SetImmediate(data);
6655 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + t,
6656 reg_value: data))
6657 return false;
6658 } else {
6659 // R[t] = bits(32) UNKNOWN;
6660 WriteBits32Unknown(n: t);
6661 }
6662 }
6663 }
6664 return true;
6665}
6666
6667// LDRB (immediate, Thumb)
6668bool EmulateInstructionARM::EmulateLDRBImmediate(const uint32_t opcode,
6669 const ARMEncoding encoding) {
6670#if 0
6671 if ConditionPassed() then
6672 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6673 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6674 address = if index then offset_addr else R[n];
6675 R[t] = ZeroExtend(MemU[address,1], 32);
6676 if wback then R[n] = offset_addr;
6677#endif
6678
6679 bool success = false;
6680
6681 if (ConditionPassed(opcode)) {
6682 uint32_t t;
6683 uint32_t n;
6684 uint32_t imm32;
6685 bool index;
6686 bool add;
6687 bool wback;
6688
6689 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6690 switch (encoding) {
6691 case eEncodingT1:
6692 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
6693 t = Bits32(bits: opcode, msbit: 2, lsbit: 0);
6694 n = Bits32(bits: opcode, msbit: 5, lsbit: 3);
6695 imm32 = Bits32(bits: opcode, msbit: 10, lsbit: 6);
6696
6697 // index = TRUE; add = TRUE; wback = FALSE;
6698 index = true;
6699 add = true;
6700 wback = false;
6701
6702 break;
6703
6704 case eEncodingT2:
6705 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6706 t = Bits32(bits: opcode, msbit: 15, lsbit: 12);
6707 n = Bits32(bits: opcode, msbit: 19, lsbit: 16);
6708 imm32 = Bits32(bits: opcode, msbit: 11, lsbit: 0);
6709
6710 // index = TRUE; add = TRUE; wback = FALSE;
6711 index = true;
6712 add = true;
6713 wback = false;
6714
6715 // if Rt == '1111' then SEE PLD;
6716 if (t == 15)
6717 return false; // PLD is not implemented yet
6718
6719 // if Rn == '1111' then SEE LDRB (literal);
6720 if (n == 15)
6721 return EmulateLDRBLiteral(opcode, encoding: eEncodingT1);
6722
6723 // if t == 13 then UNPREDICTABLE;
6724 if (t == 13)
6725 return false;
6726
6727 break;
6728
6729 case eEncodingT3:
6730 // if P == '1' && U == '1' && W == '0' then SEE LDRBT;
6731 // if P == '0' && W == '0' then UNDEFINED;
6732 if (BitIsClear(value: opcode, bit: 10) && BitIsClear(value: opcode, bit: 8))
6733 return false;
6734
6735 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6736 t = Bits32(bits: opcode, msbit: 15, lsbit: 12);
6737 n = Bits32(bits: opcode, msbit: 19, lsbit: 16);
6738 imm32 = Bits32(bits: opcode, msbit: 7, lsbit: 0);
6739
6740 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
6741 index = BitIsSet(value: opcode, bit: 10);
6742 add = BitIsSet(value: opcode, bit: 9);
6743 wback = BitIsSet(value: opcode, bit: 8);
6744
6745 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLD;
6746 if (t == 15)
6747 return false; // PLD is not implemented yet
6748
6749 // if Rn == '1111' then SEE LDRB (literal);
6750 if (n == 15)
6751 return EmulateLDRBLiteral(opcode, encoding: eEncodingT1);
6752
6753 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
6754 if (BadReg(n: t) || (wback && (n == t)))
6755 return false;
6756
6757 break;
6758
6759 default:
6760 return false;
6761 }
6762
6763 uint32_t Rn =
6764 ReadRegisterUnsigned(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n, fail_value: 0, success_ptr: &success);
6765 if (!success)
6766 return false;
6767
6768 addr_t address;
6769 addr_t offset_addr;
6770
6771 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
6772 if (add)
6773 offset_addr = Rn + imm32;
6774 else
6775 offset_addr = Rn - imm32;
6776
6777 // address = if index then offset_addr else R[n];
6778 if (index)
6779 address = offset_addr;
6780 else
6781 address = Rn;
6782
6783 // R[t] = ZeroExtend(MemU[address,1], 32);
6784 std::optional<RegisterInfo> base_reg =
6785 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n);
6786 std::optional<RegisterInfo> data_reg =
6787 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + t);
6788
6789 EmulateInstruction::Context context;
6790 context.type = eContextRegisterLoad;
6791 context.SetRegisterToRegisterPlusOffset(data_reg: *data_reg, base_reg: *base_reg, offset: address - Rn);
6792
6793 uint64_t data = MemURead(context, address, size: 1, fail_value: 0, success_ptr: &success);
6794 if (!success)
6795 return false;
6796
6797 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + t, reg_value: data))
6798 return false;
6799
6800 // if wback then R[n] = offset_addr;
6801 if (wback) {
6802 context.type = eContextAdjustBaseRegister;
6803 context.SetAddress(offset_addr);
6804 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n,
6805 reg_value: offset_addr))
6806 return false;
6807 }
6808 }
6809 return true;
6810}
6811
6812// LDRB (literal) calculates an address from the PC value and an immediate
6813// offset, loads a byte from memory,
6814// zero-extends it to form a 32-bit word and writes it to a register.
6815bool EmulateInstructionARM::EmulateLDRBLiteral(const uint32_t opcode,
6816 const ARMEncoding encoding) {
6817#if 0
6818 if ConditionPassed() then
6819 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
6820 base = Align(PC,4);
6821 address = if add then (base + imm32) else (base - imm32);
6822 R[t] = ZeroExtend(MemU[address,1], 32);
6823#endif
6824
6825 bool success = false;
6826
6827 if (ConditionPassed(opcode)) {
6828 uint32_t t;
6829 uint32_t imm32;
6830 bool add;
6831 switch (encoding) {
6832 case eEncodingT1:
6833 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
6834 t = Bits32(bits: opcode, msbit: 15, lsbit: 12);
6835 imm32 = Bits32(bits: opcode, msbit: 11, lsbit: 0);
6836 add = BitIsSet(value: opcode, bit: 23);
6837
6838 // if Rt == '1111' then SEE PLD;
6839 if (t == 15)
6840 return false; // PLD is not implemented yet
6841
6842 // if t == 13 then UNPREDICTABLE;
6843 if (t == 13)
6844 return false;
6845
6846 break;
6847
6848 case eEncodingA1:
6849 // t == UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
6850 t = Bits32(bits: opcode, msbit: 15, lsbit: 12);
6851 imm32 = Bits32(bits: opcode, msbit: 11, lsbit: 0);
6852 add = BitIsSet(value: opcode, bit: 23);
6853
6854 // if t == 15 then UNPREDICTABLE;
6855 if (t == 15)
6856 return false;
6857 break;
6858
6859 default:
6860 return false;
6861 }
6862
6863 // base = Align(PC,4);
6864 uint32_t pc_val = ReadCoreReg(PC_REG, success: &success);
6865 if (!success)
6866 return false;
6867
6868 uint32_t base = AlignPC(pc_val);
6869
6870 addr_t address;
6871 // address = if add then (base + imm32) else (base - imm32);
6872 if (add)
6873 address = base + imm32;
6874 else
6875 address = base - imm32;
6876
6877 // R[t] = ZeroExtend(MemU[address,1], 32);
6878 EmulateInstruction::Context context;
6879 context.type = eContextRelativeBranchImmediate;
6880 context.SetImmediate(address - base);
6881
6882 uint64_t data = MemURead(context, address, size: 1, fail_value: 0, success_ptr: &success);
6883 if (!success)
6884 return false;
6885
6886 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + t, reg_value: data))
6887 return false;
6888 }
6889 return true;
6890}
6891
6892// LDRB (register) calculates an address from a base register value and an
6893// offset rigister value, loads a byte from memory, zero-extends it to form a
6894// 32-bit word, and writes it to a register. The offset register value can
6895// optionally be shifted.
6896bool EmulateInstructionARM::EmulateLDRBRegister(const uint32_t opcode,
6897 const ARMEncoding encoding) {
6898#if 0
6899 if ConditionPassed() then
6900 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6901 offset = Shift(R[m], shift_t, shift_n, APSR.C);
6902 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
6903 address = if index then offset_addr else R[n];
6904 R[t] = ZeroExtend(MemU[address,1],32);
6905 if wback then R[n] = offset_addr;
6906#endif
6907
6908 bool success = false;
6909
6910 if (ConditionPassed(opcode)) {
6911 uint32_t t;
6912 uint32_t n;
6913 uint32_t m;
6914 bool index;
6915 bool add;
6916 bool wback;
6917 ARM_ShifterType shift_t;
6918 uint32_t shift_n;
6919
6920 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6921 switch (encoding) {
6922 case eEncodingT1:
6923 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6924 t = Bits32(bits: opcode, msbit: 2, lsbit: 0);
6925 n = Bits32(bits: opcode, msbit: 5, lsbit: 3);
6926 m = Bits32(bits: opcode, msbit: 8, lsbit: 6);
6927
6928 // index = TRUE; add = TRUE; wback = FALSE;
6929 index = true;
6930 add = true;
6931 wback = false;
6932
6933 // (shift_t, shift_n) = (SRType_LSL, 0);
6934 shift_t = SRType_LSL;
6935 shift_n = 0;
6936 break;
6937
6938 case eEncodingT2:
6939 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6940 t = Bits32(bits: opcode, msbit: 15, lsbit: 12);
6941 n = Bits32(bits: opcode, msbit: 19, lsbit: 16);
6942 m = Bits32(bits: opcode, msbit: 3, lsbit: 0);
6943
6944 // index = TRUE; add = TRUE; wback = FALSE;
6945 index = true;
6946 add = true;
6947 wback = false;
6948
6949 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
6950 shift_t = SRType_LSL;
6951 shift_n = Bits32(bits: opcode, msbit: 5, lsbit: 4);
6952
6953 // if Rt == '1111' then SEE PLD;
6954 if (t == 15)
6955 return false; // PLD is not implemented yet
6956
6957 // if Rn == '1111' then SEE LDRB (literal);
6958 if (n == 15)
6959 return EmulateLDRBLiteral(opcode, encoding: eEncodingT1);
6960
6961 // if t == 13 || BadReg(m) then UNPREDICTABLE;
6962 if ((t == 13) || BadReg(n: m))
6963 return false;
6964 break;
6965
6966 case eEncodingA1: {
6967 // if P == '0' && W == '1' then SEE LDRBT;
6968 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6969 t = Bits32(bits: opcode, msbit: 15, lsbit: 12);
6970 n = Bits32(bits: opcode, msbit: 19, lsbit: 16);
6971 m = Bits32(bits: opcode, msbit: 3, lsbit: 0);
6972
6973 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
6974 // (W == '1');
6975 index = BitIsSet(value: opcode, bit: 24);
6976 add = BitIsSet(value: opcode, bit: 23);
6977 wback = (BitIsClear(value: opcode, bit: 24) || BitIsSet(value: opcode, bit: 21));
6978
6979 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
6980 uint32_t type = Bits32(bits: opcode, msbit: 6, lsbit: 5);
6981 uint32_t imm5 = Bits32(bits: opcode, msbit: 11, lsbit: 7);
6982 shift_n = DecodeImmShift(type, imm5, shift_t);
6983
6984 // if t == 15 || m == 15 then UNPREDICTABLE;
6985 if ((t == 15) || (m == 15))
6986 return false;
6987
6988 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
6989 if (wback && ((n == 15) || (n == t)))
6990 return false;
6991 } break;
6992
6993 default:
6994 return false;
6995 }
6996
6997 addr_t offset_addr;
6998 addr_t address;
6999
7000 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
7001 uint32_t Rm =
7002 ReadRegisterUnsigned(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + m, fail_value: 0, success_ptr: &success);
7003 if (!success)
7004 return false;
7005
7006 addr_t offset = Shift(value: Rm, type: shift_t, amount: shift_n, APSR_C, success: &success);
7007 if (!success)
7008 return false;
7009
7010 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7011 uint32_t Rn =
7012 ReadRegisterUnsigned(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n, fail_value: 0, success_ptr: &success);
7013 if (!success)
7014 return false;
7015
7016 if (add)
7017 offset_addr = Rn + offset;
7018 else
7019 offset_addr = Rn - offset;
7020
7021 // address = if index then offset_addr else R[n];
7022 if (index)
7023 address = offset_addr;
7024 else
7025 address = Rn;
7026
7027 // R[t] = ZeroExtend(MemU[address,1],32);
7028 std::optional<RegisterInfo> base_reg =
7029 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n);
7030
7031 EmulateInstruction::Context context;
7032 context.type = eContextRegisterLoad;
7033 context.SetRegisterPlusOffset(base_reg: *base_reg, signed_offset: address - Rn);
7034
7035 uint64_t data = MemURead(context, address, size: 1, fail_value: 0, success_ptr: &success);
7036 if (!success)
7037 return false;
7038
7039 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + t, reg_value: data))
7040 return false;
7041
7042 // if wback then R[n] = offset_addr;
7043 if (wback) {
7044 context.type = eContextAdjustBaseRegister;
7045 context.SetAddress(offset_addr);
7046 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n,
7047 reg_value: offset_addr))
7048 return false;
7049 }
7050 }
7051 return true;
7052}
7053
7054// LDRH (immediate, Thumb) calculates an address from a base register value and
7055// an immediate offset, loads a
7056// halfword from memory, zero-extends it to form a 32-bit word, and writes it
7057// to a register. It can use offset, post-indexed, or pre-indexed addressing.
7058bool EmulateInstructionARM::EmulateLDRHImmediate(const uint32_t opcode,
7059 const ARMEncoding encoding) {
7060#if 0
7061 if ConditionPassed() then
7062 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7063 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7064 address = if index then offset_addr else R[n];
7065 data = MemU[address,2];
7066 if wback then R[n] = offset_addr;
7067 if UnalignedSupport() || address<0> = '0' then
7068 R[t] = ZeroExtend(data, 32);
7069 else // Can only apply before ARMv7
7070 R[t] = bits(32) UNKNOWN;
7071#endif
7072
7073 bool success = false;
7074
7075 if (ConditionPassed(opcode)) {
7076 uint32_t t;
7077 uint32_t n;
7078 uint32_t imm32;
7079 bool index;
7080 bool add;
7081 bool wback;
7082
7083 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7084 switch (encoding) {
7085 case eEncodingT1:
7086 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:'0', 32);
7087 t = Bits32(bits: opcode, msbit: 2, lsbit: 0);
7088 n = Bits32(bits: opcode, msbit: 5, lsbit: 3);
7089 imm32 = Bits32(bits: opcode, msbit: 10, lsbit: 6) << 1;
7090
7091 // index = TRUE; add = TRUE; wback = FALSE;
7092 index = true;
7093 add = true;
7094 wback = false;
7095
7096 break;
7097
7098 case eEncodingT2:
7099 // if Rt == '1111' then SEE "Unallocated memory hints";
7100 // if Rn == '1111' then SEE LDRH (literal);
7101 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
7102 t = Bits32(bits: opcode, msbit: 15, lsbit: 12);
7103 n = Bits32(bits: opcode, msbit: 19, lsbit: 16);
7104 imm32 = Bits32(bits: opcode, msbit: 11, lsbit: 0);
7105
7106 // index = TRUE; add = TRUE; wback = FALSE;
7107 index = true;
7108 add = true;
7109 wback = false;
7110
7111 // if t == 13 then UNPREDICTABLE;
7112 if (t == 13)
7113 return false;
7114 break;
7115
7116 case eEncodingT3:
7117 // if Rn == '1111' then SEE LDRH (literal);
7118 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE
7119 // "Unallocated memory hints";
7120 // if P == '1' && U == '1' && W == '0' then SEE LDRHT;
7121 // if P == '0' && W == '0' then UNDEFINED;
7122 if (BitIsClear(value: opcode, bit: 10) && BitIsClear(value: opcode, bit: 8))
7123 return false;
7124
7125 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
7126 t = Bits32(bits: opcode, msbit: 15, lsbit: 12);
7127 n = Bits32(bits: opcode, msbit: 19, lsbit: 16);
7128 imm32 = Bits32(bits: opcode, msbit: 7, lsbit: 0);
7129
7130 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
7131 index = BitIsSet(value: opcode, bit: 10);
7132 add = BitIsSet(value: opcode, bit: 9);
7133 wback = BitIsSet(value: opcode, bit: 8);
7134
7135 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
7136 if (BadReg(n: t) || (wback && (n == t)))
7137 return false;
7138 break;
7139
7140 default:
7141 return false;
7142 }
7143
7144 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7145 uint32_t Rn =
7146 ReadRegisterUnsigned(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n, fail_value: 0, success_ptr: &success);
7147 if (!success)
7148 return false;
7149
7150 addr_t offset_addr;
7151 addr_t address;
7152
7153 if (add)
7154 offset_addr = Rn + imm32;
7155 else
7156 offset_addr = Rn - imm32;
7157
7158 // address = if index then offset_addr else R[n];
7159 if (index)
7160 address = offset_addr;
7161 else
7162 address = Rn;
7163
7164 // data = MemU[address,2];
7165 std::optional<RegisterInfo> base_reg =
7166 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n);
7167
7168 EmulateInstruction::Context context;
7169 context.type = eContextRegisterLoad;
7170 context.SetRegisterPlusOffset(base_reg: *base_reg, signed_offset: address - Rn);
7171
7172 uint64_t data = MemURead(context, address, size: 2, fail_value: 0, success_ptr: &success);
7173 if (!success)
7174 return false;
7175
7176 // if wback then R[n] = offset_addr;
7177 if (wback) {
7178 context.type = eContextAdjustBaseRegister;
7179 context.SetAddress(offset_addr);
7180 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n,
7181 reg_value: offset_addr))
7182 return false;
7183 }
7184
7185 // if UnalignedSupport() || address<0> = '0' then
7186 if (UnalignedSupport() || BitIsClear(value: address, bit: 0)) {
7187 // R[t] = ZeroExtend(data, 32);
7188 context.type = eContextRegisterLoad;
7189 context.SetRegisterPlusOffset(base_reg: *base_reg, signed_offset: address - Rn);
7190 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + t,
7191 reg_value: data))
7192 return false;
7193 } else // Can only apply before ARMv7
7194 {
7195 // R[t] = bits(32) UNKNOWN;
7196 WriteBits32Unknown(n: t);
7197 }
7198 }
7199 return true;
7200}
7201
7202// LDRH (literal) calculates an address from the PC value and an immediate
7203// offset, loads a halfword from memory,
7204// zero-extends it to form a 32-bit word, and writes it to a register.
7205bool EmulateInstructionARM::EmulateLDRHLiteral(const uint32_t opcode,
7206 const ARMEncoding encoding) {
7207#if 0
7208 if ConditionPassed() then
7209 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7210 base = Align(PC,4);
7211 address = if add then (base + imm32) else (base - imm32);
7212 data = MemU[address,2];
7213 if UnalignedSupport() || address<0> = '0' then
7214 R[t] = ZeroExtend(data, 32);
7215 else // Can only apply before ARMv7
7216 R[t] = bits(32) UNKNOWN;
7217#endif
7218
7219 bool success = false;
7220
7221 if (ConditionPassed(opcode)) {
7222 uint32_t t;
7223 uint32_t imm32;
7224 bool add;
7225
7226 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7227 switch (encoding) {
7228 case eEncodingT1:
7229 // if Rt == '1111' then SEE "Unallocated memory hints";
7230 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
7231 t = Bits32(bits: opcode, msbit: 15, lsbit: 12);
7232 imm32 = Bits32(bits: opcode, msbit: 11, lsbit: 0);
7233 add = BitIsSet(value: opcode, bit: 23);
7234
7235 // if t == 13 then UNPREDICTABLE;
7236 if (t == 13)
7237 return false;
7238
7239 break;
7240
7241 case eEncodingA1: {
7242 uint32_t imm4H = Bits32(bits: opcode, msbit: 11, lsbit: 8);
7243 uint32_t imm4L = Bits32(bits: opcode, msbit: 3, lsbit: 0);
7244
7245 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
7246 t = Bits32(bits: opcode, msbit: 15, lsbit: 12);
7247 imm32 = (imm4H << 4) | imm4L;
7248 add = BitIsSet(value: opcode, bit: 23);
7249
7250 // if t == 15 then UNPREDICTABLE;
7251 if (t == 15)
7252 return false;
7253 break;
7254 }
7255
7256 default:
7257 return false;
7258 }
7259
7260 // base = Align(PC,4);
7261 uint64_t pc_value = ReadCoreReg(PC_REG, success: &success);
7262 if (!success)
7263 return false;
7264
7265 addr_t base = AlignPC(pc_value);
7266 addr_t address;
7267
7268 // address = if add then (base + imm32) else (base - imm32);
7269 if (add)
7270 address = base + imm32;
7271 else
7272 address = base - imm32;
7273
7274 // data = MemU[address,2];
7275 std::optional<RegisterInfo> base_reg =
7276 GetRegisterInfo(reg_kind: eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
7277
7278 EmulateInstruction::Context context;
7279 context.type = eContextRegisterLoad;
7280 context.SetRegisterPlusOffset(base_reg: *base_reg, signed_offset: address - base);
7281
7282 uint64_t data = MemURead(context, address, size: 2, fail_value: 0, success_ptr: &success);
7283 if (!success)
7284 return false;
7285
7286 // if UnalignedSupport() || address<0> = '0' then
7287 if (UnalignedSupport() || BitIsClear(value: address, bit: 0)) {
7288 // R[t] = ZeroExtend(data, 32);
7289 context.type = eContextRegisterLoad;
7290 context.SetRegisterPlusOffset(base_reg: *base_reg, signed_offset: address - base);
7291 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + t,
7292 reg_value: data))
7293 return false;
7294
7295 } else // Can only apply before ARMv7
7296 {
7297 // R[t] = bits(32) UNKNOWN;
7298 WriteBits32Unknown(n: t);
7299 }
7300 }
7301 return true;
7302}
7303
7304// LDRH (literal) calculates an address from a base register value and an offset
7305// register value, loads a halfword
7306// from memory, zero-extends it to form a 32-bit word, and writes it to a
7307// register. The offset register value can be shifted left by 0, 1, 2, or 3
7308// bits.
7309bool EmulateInstructionARM::EmulateLDRHRegister(const uint32_t opcode,
7310 const ARMEncoding encoding) {
7311#if 0
7312 if ConditionPassed() then
7313 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7314 offset = Shift(R[m], shift_t, shift_n, APSR.C);
7315 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7316 address = if index then offset_addr else R[n];
7317 data = MemU[address,2];
7318 if wback then R[n] = offset_addr;
7319 if UnalignedSupport() || address<0> = '0' then
7320 R[t] = ZeroExtend(data, 32);
7321 else // Can only apply before ARMv7
7322 R[t] = bits(32) UNKNOWN;
7323#endif
7324
7325 bool success = false;
7326
7327 if (ConditionPassed(opcode)) {
7328 uint32_t t;
7329 uint32_t n;
7330 uint32_t m;
7331 bool index;
7332 bool add;
7333 bool wback;
7334 ARM_ShifterType shift_t;
7335 uint32_t shift_n;
7336
7337 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7338 switch (encoding) {
7339 case eEncodingT1:
7340 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation
7341 // in ThumbEE";
7342 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7343 t = Bits32(bits: opcode, msbit: 2, lsbit: 0);
7344 n = Bits32(bits: opcode, msbit: 5, lsbit: 3);
7345 m = Bits32(bits: opcode, msbit: 8, lsbit: 6);
7346
7347 // index = TRUE; add = TRUE; wback = FALSE;
7348 index = true;
7349 add = true;
7350 wback = false;
7351
7352 // (shift_t, shift_n) = (SRType_LSL, 0);
7353 shift_t = SRType_LSL;
7354 shift_n = 0;
7355
7356 break;
7357
7358 case eEncodingT2:
7359 // if Rn == '1111' then SEE LDRH (literal);
7360 // if Rt == '1111' then SEE "Unallocated memory hints";
7361 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7362 t = Bits32(bits: opcode, msbit: 15, lsbit: 12);
7363 n = Bits32(bits: opcode, msbit: 19, lsbit: 16);
7364 m = Bits32(bits: opcode, msbit: 3, lsbit: 0);
7365
7366 // index = TRUE; add = TRUE; wback = FALSE;
7367 index = true;
7368 add = true;
7369 wback = false;
7370
7371 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
7372 shift_t = SRType_LSL;
7373 shift_n = Bits32(bits: opcode, msbit: 5, lsbit: 4);
7374
7375 // if t == 13 || BadReg(m) then UNPREDICTABLE;
7376 if ((t == 13) || BadReg(n: m))
7377 return false;
7378 break;
7379
7380 case eEncodingA1:
7381 // if P == '0' && W == '1' then SEE LDRHT;
7382 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7383 t = Bits32(bits: opcode, msbit: 15, lsbit: 12);
7384 n = Bits32(bits: opcode, msbit: 19, lsbit: 16);
7385 m = Bits32(bits: opcode, msbit: 3, lsbit: 0);
7386
7387 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
7388 // (W == '1');
7389 index = BitIsSet(value: opcode, bit: 24);
7390 add = BitIsSet(value: opcode, bit: 23);
7391 wback = (BitIsClear(value: opcode, bit: 24) || BitIsSet(value: opcode, bit: 21));
7392
7393 // (shift_t, shift_n) = (SRType_LSL, 0);
7394 shift_t = SRType_LSL;
7395 shift_n = 0;
7396
7397 // if t == 15 || m == 15 then UNPREDICTABLE;
7398 if ((t == 15) || (m == 15))
7399 return false;
7400
7401 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
7402 if (wback && ((n == 15) || (n == t)))
7403 return false;
7404
7405 break;
7406
7407 default:
7408 return false;
7409 }
7410
7411 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
7412
7413 uint64_t Rm =
7414 ReadRegisterUnsigned(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + m, fail_value: 0, success_ptr: &success);
7415 if (!success)
7416 return false;
7417
7418 addr_t offset = Shift(value: Rm, type: shift_t, amount: shift_n, APSR_C, success: &success);
7419 if (!success)
7420 return false;
7421
7422 addr_t offset_addr;
7423 addr_t address;
7424
7425 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7426 uint64_t Rn =
7427 ReadRegisterUnsigned(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n, fail_value: 0, success_ptr: &success);
7428 if (!success)
7429 return false;
7430
7431 if (add)
7432 offset_addr = Rn + offset;
7433 else
7434 offset_addr = Rn - offset;
7435
7436 // address = if index then offset_addr else R[n];
7437 if (index)
7438 address = offset_addr;
7439 else
7440 address = Rn;
7441
7442 // data = MemU[address,2];
7443 std::optional<RegisterInfo> base_reg =
7444 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n);
7445 std::optional<RegisterInfo> offset_reg =
7446 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + m);
7447
7448 EmulateInstruction::Context context;
7449 context.type = eContextRegisterLoad;
7450 context.SetRegisterPlusIndirectOffset(base_reg: *base_reg, offset_reg: *offset_reg);
7451 uint64_t data = MemURead(context, address, size: 2, fail_value: 0, success_ptr: &success);
7452 if (!success)
7453 return false;
7454
7455 // if wback then R[n] = offset_addr;
7456 if (wback) {
7457 context.type = eContextAdjustBaseRegister;
7458 context.SetAddress(offset_addr);
7459 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n,
7460 reg_value: offset_addr))
7461 return false;
7462 }
7463
7464 // if UnalignedSupport() || address<0> = '0' then
7465 if (UnalignedSupport() || BitIsClear(value: address, bit: 0)) {
7466 // R[t] = ZeroExtend(data, 32);
7467 context.type = eContextRegisterLoad;
7468 context.SetRegisterPlusIndirectOffset(base_reg: *base_reg, offset_reg: *offset_reg);
7469 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + t,
7470 reg_value: data))
7471 return false;
7472 } else // Can only apply before ARMv7
7473 {
7474 // R[t] = bits(32) UNKNOWN;
7475 WriteBits32Unknown(n: t);
7476 }
7477 }
7478 return true;
7479}
7480
7481// LDRSB (immediate) calculates an address from a base register value and an
7482// immediate offset, loads a byte from
7483// memory, sign-extends it to form a 32-bit word, and writes it to a register.
7484// It can use offset, post-indexed, or pre-indexed addressing.
7485bool EmulateInstructionARM::EmulateLDRSBImmediate(const uint32_t opcode,
7486 const ARMEncoding encoding) {
7487#if 0
7488 if ConditionPassed() then
7489 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7490 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7491 address = if index then offset_addr else R[n];
7492 R[t] = SignExtend(MemU[address,1], 32);
7493 if wback then R[n] = offset_addr;
7494#endif
7495
7496 bool success = false;
7497
7498 if (ConditionPassed(opcode)) {
7499 uint32_t t;
7500 uint32_t n;
7501 uint32_t imm32;
7502 bool index;
7503 bool add;
7504 bool wback;
7505
7506 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7507 switch (encoding) {
7508 case eEncodingT1:
7509 // if Rt == '1111' then SEE PLI;
7510 // if Rn == '1111' then SEE LDRSB (literal);
7511 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
7512 t = Bits32(bits: opcode, msbit: 15, lsbit: 12);
7513 n = Bits32(bits: opcode, msbit: 19, lsbit: 16);
7514 imm32 = Bits32(bits: opcode, msbit: 11, lsbit: 0);
7515
7516 // index = TRUE; add = TRUE; wback = FALSE;
7517 index = true;
7518 add = true;
7519 wback = false;
7520
7521 // if t == 13 then UNPREDICTABLE;
7522 if (t == 13)
7523 return false;
7524
7525 break;
7526
7527 case eEncodingT2:
7528 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLI;
7529 // if Rn == '1111' then SEE LDRSB (literal);
7530 // if P == '1' && U == '1' && W == '0' then SEE LDRSBT;
7531 // if P == '0' && W == '0' then UNDEFINED;
7532 if (BitIsClear(value: opcode, bit: 10) && BitIsClear(value: opcode, bit: 8))
7533 return false;
7534
7535 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
7536 t = Bits32(bits: opcode, msbit: 15, lsbit: 12);
7537 n = Bits32(bits: opcode, msbit: 19, lsbit: 16);
7538 imm32 = Bits32(bits: opcode, msbit: 7, lsbit: 0);
7539
7540 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
7541 index = BitIsSet(value: opcode, bit: 10);
7542 add = BitIsSet(value: opcode, bit: 9);
7543 wback = BitIsSet(value: opcode, bit: 8);
7544
7545 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
7546 if (((t == 13) ||
7547 ((t == 15) && (BitIsClear(value: opcode, bit: 10) || BitIsSet(value: opcode, bit: 9) ||
7548 BitIsSet(value: opcode, bit: 8)))) ||
7549 (wback && (n == t)))
7550 return false;
7551
7552 break;
7553
7554 case eEncodingA1: {
7555 // if Rn == '1111' then SEE LDRSB (literal);
7556 // if P == '0' && W == '1' then SEE LDRSBT;
7557 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
7558 t = Bits32(bits: opcode, msbit: 15, lsbit: 12);
7559 n = Bits32(bits: opcode, msbit: 19, lsbit: 16);
7560
7561 uint32_t imm4H = Bits32(bits: opcode, msbit: 11, lsbit: 8);
7562 uint32_t imm4L = Bits32(bits: opcode, msbit: 3, lsbit: 0);
7563 imm32 = (imm4H << 4) | imm4L;
7564
7565 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
7566 // (W == '1');
7567 index = BitIsSet(value: opcode, bit: 24);
7568 add = BitIsSet(value: opcode, bit: 23);
7569 wback = (BitIsClear(value: opcode, bit: 24) || BitIsSet(value: opcode, bit: 21));
7570
7571 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
7572 if ((t == 15) || (wback && (n == t)))
7573 return false;
7574
7575 break;
7576 }
7577
7578 default:
7579 return false;
7580 }
7581
7582 uint64_t Rn = ReadCoreReg(regnum: n, success: &success);
7583 if (!success)
7584 return false;
7585
7586 addr_t offset_addr;
7587 addr_t address;
7588
7589 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7590 if (add)
7591 offset_addr = Rn + imm32;
7592 else
7593 offset_addr = Rn - imm32;
7594
7595 // address = if index then offset_addr else R[n];
7596 if (index)
7597 address = offset_addr;
7598 else
7599 address = Rn;
7600
7601 // R[t] = SignExtend(MemU[address,1], 32);
7602 std::optional<RegisterInfo> base_reg =
7603 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n);
7604
7605 EmulateInstruction::Context context;
7606 context.type = eContextRegisterLoad;
7607 context.SetRegisterPlusOffset(base_reg: *base_reg, signed_offset: address - Rn);
7608
7609 uint64_t unsigned_data = MemURead(context, address, size: 1, fail_value: 0, success_ptr: &success);
7610 if (!success)
7611 return false;
7612
7613 int64_t signed_data = llvm::SignExtend64<8>(x: unsigned_data);
7614 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + t,
7615 reg_value: (uint64_t)signed_data))
7616 return false;
7617
7618 // if wback then R[n] = offset_addr;
7619 if (wback) {
7620 context.type = eContextAdjustBaseRegister;
7621 context.SetAddress(offset_addr);
7622 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n,
7623 reg_value: offset_addr))
7624 return false;
7625 }
7626 }
7627
7628 return true;
7629}
7630
7631// LDRSB (literal) calculates an address from the PC value and an immediate
7632// offset, loads a byte from memory,
7633// sign-extends it to form a 32-bit word, and writes tit to a register.
7634bool EmulateInstructionARM::EmulateLDRSBLiteral(const uint32_t opcode,
7635 const ARMEncoding encoding) {
7636#if 0
7637 if ConditionPassed() then
7638 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7639 base = Align(PC,4);
7640 address = if add then (base + imm32) else (base - imm32);
7641 R[t] = SignExtend(MemU[address,1], 32);
7642#endif
7643
7644 bool success = false;
7645
7646 if (ConditionPassed(opcode)) {
7647 uint32_t t;
7648 uint32_t imm32;
7649 bool add;
7650
7651 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
7652 switch (encoding) {
7653 case eEncodingT1:
7654 // if Rt == '1111' then SEE PLI;
7655 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
7656 t = Bits32(bits: opcode, msbit: 15, lsbit: 12);
7657 imm32 = Bits32(bits: opcode, msbit: 11, lsbit: 0);
7658 add = BitIsSet(value: opcode, bit: 23);
7659
7660 // if t == 13 then UNPREDICTABLE;
7661 if (t == 13)
7662 return false;
7663
7664 break;
7665
7666 case eEncodingA1: {
7667 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
7668 t = Bits32(bits: opcode, msbit: 15, lsbit: 12);
7669 uint32_t imm4H = Bits32(bits: opcode, msbit: 11, lsbit: 8);
7670 uint32_t imm4L = Bits32(bits: opcode, msbit: 3, lsbit: 0);
7671 imm32 = (imm4H << 4) | imm4L;
7672 add = BitIsSet(value: opcode, bit: 23);
7673
7674 // if t == 15 then UNPREDICTABLE;
7675 if (t == 15)
7676 return false;
7677
7678 break;
7679 }
7680
7681 default:
7682 return false;
7683 }
7684
7685 // base = Align(PC,4);
7686 uint64_t pc_value = ReadCoreReg(PC_REG, success: &success);
7687 if (!success)
7688 return false;
7689 uint64_t base = AlignPC(pc_value);
7690
7691 // address = if add then (base + imm32) else (base - imm32);
7692 addr_t address;
7693 if (add)
7694 address = base + imm32;
7695 else
7696 address = base - imm32;
7697
7698 // R[t] = SignExtend(MemU[address,1], 32);
7699 std::optional<RegisterInfo> base_reg =
7700 GetRegisterInfo(reg_kind: eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
7701
7702 EmulateInstruction::Context context;
7703 context.type = eContextRegisterLoad;
7704 context.SetRegisterPlusOffset(base_reg: *base_reg, signed_offset: address - base);
7705
7706 uint64_t unsigned_data = MemURead(context, address, size: 1, fail_value: 0, success_ptr: &success);
7707 if (!success)
7708 return false;
7709
7710 int64_t signed_data = llvm::SignExtend64<8>(x: unsigned_data);
7711 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + t,
7712 reg_value: (uint64_t)signed_data))
7713 return false;
7714 }
7715 return true;
7716}
7717
7718// LDRSB (register) calculates an address from a base register value and an
7719// offset register value, loadsa byte from
7720// memory, sign-extends it to form a 32-bit word, and writes it to a register.
7721// The offset register value can be shifted left by 0, 1, 2, or 3 bits.
7722bool EmulateInstructionARM::EmulateLDRSBRegister(const uint32_t opcode,
7723 const ARMEncoding encoding) {
7724#if 0
7725 if ConditionPassed() then
7726 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7727 offset = Shift(R[m], shift_t, shift_n, APSR.C);
7728 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7729 address = if index then offset_addr else R[n];
7730 R[t] = SignExtend(MemU[address,1], 32);
7731 if wback then R[n] = offset_addr;
7732#endif
7733
7734 bool success = false;
7735
7736 if (ConditionPassed(opcode)) {
7737 uint32_t t;
7738 uint32_t n;
7739 uint32_t m;
7740 bool index;
7741 bool add;
7742 bool wback;
7743 ARM_ShifterType shift_t;
7744 uint32_t shift_n;
7745
7746 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7747 switch (encoding) {
7748 case eEncodingT1:
7749 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7750 t = Bits32(bits: opcode, msbit: 2, lsbit: 0);
7751 n = Bits32(bits: opcode, msbit: 5, lsbit: 3);
7752 m = Bits32(bits: opcode, msbit: 8, lsbit: 6);
7753
7754 // index = TRUE; add = TRUE; wback = FALSE;
7755 index = true;
7756 add = true;
7757 wback = false;
7758
7759 // (shift_t, shift_n) = (SRType_LSL, 0);
7760 shift_t = SRType_LSL;
7761 shift_n = 0;
7762
7763 break;
7764
7765 case eEncodingT2:
7766 // if Rt == '1111' then SEE PLI;
7767 // if Rn == '1111' then SEE LDRSB (literal);
7768 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7769 t = Bits32(bits: opcode, msbit: 15, lsbit: 12);
7770 n = Bits32(bits: opcode, msbit: 19, lsbit: 16);
7771 m = Bits32(bits: opcode, msbit: 3, lsbit: 0);
7772
7773 // index = TRUE; add = TRUE; wback = FALSE;
7774 index = true;
7775 add = true;
7776 wback = false;
7777
7778 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
7779 shift_t = SRType_LSL;
7780 shift_n = Bits32(bits: opcode, msbit: 5, lsbit: 4);
7781
7782 // if t == 13 || BadReg(m) then UNPREDICTABLE;
7783 if ((t == 13) || BadReg(n: m))
7784 return false;
7785 break;
7786
7787 case eEncodingA1:
7788 // if P == '0' && W == '1' then SEE LDRSBT;
7789 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7790 t = Bits32(bits: opcode, msbit: 15, lsbit: 12);
7791 n = Bits32(bits: opcode, msbit: 19, lsbit: 16);
7792 m = Bits32(bits: opcode, msbit: 3, lsbit: 0);
7793
7794 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
7795 // (W == '1');
7796 index = BitIsSet(value: opcode, bit: 24);
7797 add = BitIsSet(value: opcode, bit: 23);
7798 wback = BitIsClear(value: opcode, bit: 24) || BitIsSet(value: opcode, bit: 21);
7799
7800 // (shift_t, shift_n) = (SRType_LSL, 0);
7801 shift_t = SRType_LSL;
7802 shift_n = 0;
7803
7804 // if t == 15 || m == 15 then UNPREDICTABLE;
7805 if ((t == 15) || (m == 15))
7806 return false;
7807
7808 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
7809 if (wback && ((n == 15) || (n == t)))
7810 return false;
7811 break;
7812
7813 default:
7814 return false;
7815 }
7816
7817 uint64_t Rm =
7818 ReadRegisterUnsigned(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + m, fail_value: 0, success_ptr: &success);
7819 if (!success)
7820 return false;
7821
7822 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
7823 addr_t offset = Shift(value: Rm, type: shift_t, amount: shift_n, APSR_C, success: &success);
7824 if (!success)
7825 return false;
7826
7827 addr_t offset_addr;
7828 addr_t address;
7829
7830 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7831 uint64_t Rn =
7832 ReadRegisterUnsigned(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n, fail_value: 0, success_ptr: &success);
7833 if (!success)
7834 return false;
7835
7836 if (add)
7837 offset_addr = Rn + offset;
7838 else
7839 offset_addr = Rn - offset;
7840
7841 // address = if index then offset_addr else R[n];
7842 if (index)
7843 address = offset_addr;
7844 else
7845 address = Rn;
7846
7847 // R[t] = SignExtend(MemU[address,1], 32);
7848 std::optional<RegisterInfo> base_reg =
7849 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n);
7850 std::optional<RegisterInfo> offset_reg =
7851 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + m);
7852
7853 EmulateInstruction::Context context;
7854 context.type = eContextRegisterLoad;
7855 context.SetRegisterPlusIndirectOffset(base_reg: *base_reg, offset_reg: *offset_reg);
7856
7857 uint64_t unsigned_data = MemURead(context, address, size: 1, fail_value: 0, success_ptr: &success);
7858 if (!success)
7859 return false;
7860
7861 int64_t signed_data = llvm::SignExtend64<8>(x: unsigned_data);
7862 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + t,
7863 reg_value: (uint64_t)signed_data))
7864 return false;
7865
7866 // if wback then R[n] = offset_addr;
7867 if (wback) {
7868 context.type = eContextAdjustBaseRegister;
7869 context.SetAddress(offset_addr);
7870 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n,
7871 reg_value: offset_addr))
7872 return false;
7873 }
7874 }
7875 return true;
7876}
7877
7878// LDRSH (immediate) calculates an address from a base register value and an
7879// immediate offset, loads a halfword from
7880// memory, sign-extends it to form a 32-bit word, and writes it to a register.
7881// It can use offset, post-indexed, or pre-indexed addressing.
7882bool EmulateInstructionARM::EmulateLDRSHImmediate(const uint32_t opcode,
7883 const ARMEncoding encoding) {
7884#if 0
7885 if ConditionPassed() then
7886 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7887 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7888 address = if index then offset_addr else R[n];
7889 data = MemU[address,2];
7890 if wback then R[n] = offset_addr;
7891 if UnalignedSupport() || address<0> = '0' then
7892 R[t] = SignExtend(data, 32);
7893 else // Can only apply before ARMv7
7894 R[t] = bits(32) UNKNOWN;
7895#endif
7896
7897 bool success = false;
7898
7899 if (ConditionPassed(opcode)) {
7900 uint32_t t;
7901 uint32_t n;
7902 uint32_t imm32;
7903 bool index;
7904 bool add;
7905 bool wback;
7906
7907 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7908 switch (encoding) {
7909 case eEncodingT1:
7910 // if Rn == '1111' then SEE LDRSH (literal);
7911 // if Rt == '1111' then SEE "Unallocated memory hints";
7912 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
7913 t = Bits32(bits: opcode, msbit: 15, lsbit: 12);
7914 n = Bits32(bits: opcode, msbit: 19, lsbit: 16);
7915 imm32 = Bits32(bits: opcode, msbit: 11, lsbit: 0);
7916
7917 // index = TRUE; add = TRUE; wback = FALSE;
7918 index = true;
7919 add = true;
7920 wback = false;
7921
7922 // if t == 13 then UNPREDICTABLE;
7923 if (t == 13)
7924 return false;
7925
7926 break;
7927
7928 case eEncodingT2:
7929 // if Rn == '1111' then SEE LDRSH (literal);
7930 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE
7931 // "Unallocated memory hints";
7932 // if P == '1' && U == '1' && W == '0' then SEE LDRSHT;
7933 // if P == '0' && W == '0' then UNDEFINED;
7934 if (BitIsClear(value: opcode, bit: 10) && BitIsClear(value: opcode, bit: 8))
7935 return false;
7936
7937 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
7938 t = Bits32(bits: opcode, msbit: 15, lsbit: 12);
7939 n = Bits32(bits: opcode, msbit: 19, lsbit: 16);
7940 imm32 = Bits32(bits: opcode, msbit: 7, lsbit: 0);
7941
7942 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
7943 index = BitIsSet(value: opcode, bit: 10);
7944 add = BitIsSet(value: opcode, bit: 9);
7945 wback = BitIsSet(value: opcode, bit: 8);
7946
7947 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
7948 if (BadReg(n: t) || (wback && (n == t)))
7949 return false;
7950
7951 break;
7952
7953 case eEncodingA1: {
7954 // if Rn == '1111' then SEE LDRSH (literal);
7955 // if P == '0' && W == '1' then SEE LDRSHT;
7956 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
7957 t = Bits32(bits: opcode, msbit: 15, lsbit: 12);
7958 n = Bits32(bits: opcode, msbit: 19, lsbit: 16);
7959 uint32_t imm4H = Bits32(bits: opcode, msbit: 11, lsbit: 8);
7960 uint32_t imm4L = Bits32(bits: opcode, msbit: 3, lsbit: 0);
7961 imm32 = (imm4H << 4) | imm4L;
7962
7963 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
7964 // (W == '1');
7965 index = BitIsSet(value: opcode, bit: 24);
7966 add = BitIsSet(value: opcode, bit: 23);
7967 wback = BitIsClear(value: opcode, bit: 24) || BitIsSet(value: opcode, bit: 21);
7968
7969 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
7970 if ((t == 15) || (wback && (n == t)))
7971 return false;
7972
7973 break;
7974 }
7975
7976 default:
7977 return false;
7978 }
7979
7980 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7981 uint64_t Rn =
7982 ReadRegisterUnsigned(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n, fail_value: 0, success_ptr: &success);
7983 if (!success)
7984 return false;
7985
7986 addr_t offset_addr;
7987 if (add)
7988 offset_addr = Rn + imm32;
7989 else
7990 offset_addr = Rn - imm32;
7991
7992 // address = if index then offset_addr else R[n];
7993 addr_t address;
7994 if (index)
7995 address = offset_addr;
7996 else
7997 address = Rn;
7998
7999 // data = MemU[address,2];
8000 std::optional<RegisterInfo> base_reg =
8001 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n);
8002
8003 EmulateInstruction::Context context;
8004 context.type = eContextRegisterLoad;
8005 context.SetRegisterPlusOffset(base_reg: *base_reg, signed_offset: address - Rn);
8006
8007 uint64_t data = MemURead(context, address, size: 2, fail_value: 0, success_ptr: &success);
8008 if (!success)
8009 return false;
8010
8011 // if wback then R[n] = offset_addr;
8012 if (wback) {
8013 context.type = eContextAdjustBaseRegister;
8014 context.SetAddress(offset_addr);
8015 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n,
8016 reg_value: offset_addr))
8017 return false;
8018 }
8019
8020 // if UnalignedSupport() || address<0> = '0' then
8021 if (UnalignedSupport() || BitIsClear(value: address, bit: 0)) {
8022 // R[t] = SignExtend(data, 32);
8023 int64_t signed_data = llvm::SignExtend64<16>(x: data);
8024 context.type = eContextRegisterLoad;
8025 context.SetRegisterPlusOffset(base_reg: *base_reg, signed_offset: address - Rn);
8026 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + t,
8027 reg_value: (uint64_t)signed_data))
8028 return false;
8029 } else // Can only apply before ARMv7
8030 {
8031 // R[t] = bits(32) UNKNOWN;
8032 WriteBits32Unknown(n: t);
8033 }
8034 }
8035 return true;
8036}
8037
8038// LDRSH (literal) calculates an address from the PC value and an immediate
8039// offset, loads a halfword from memory,
8040// sign-extends it to from a 32-bit word, and writes it to a register.
8041bool EmulateInstructionARM::EmulateLDRSHLiteral(const uint32_t opcode,
8042 const ARMEncoding encoding) {
8043#if 0
8044 if ConditionPassed() then
8045 EncodingSpecificOperations(); NullCheckIfThumbEE(15);
8046 base = Align(PC,4);
8047 address = if add then (base + imm32) else (base - imm32);
8048 data = MemU[address,2];
8049 if UnalignedSupport() || address<0> = '0' then
8050 R[t] = SignExtend(data, 32);
8051 else // Can only apply before ARMv7
8052 R[t] = bits(32) UNKNOWN;
8053#endif
8054
8055 bool success = false;
8056
8057 if (ConditionPassed(opcode)) {
8058 uint32_t t;
8059 uint32_t imm32;
8060 bool add;
8061
8062 // EncodingSpecificOperations(); NullCheckIfThumbEE(15);
8063 switch (encoding) {
8064 case eEncodingT1:
8065 // if Rt == '1111' then SEE "Unallocated memory hints";
8066 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
8067 t = Bits32(bits: opcode, msbit: 15, lsbit: 12);
8068 imm32 = Bits32(bits: opcode, msbit: 11, lsbit: 0);
8069 add = BitIsSet(value: opcode, bit: 23);
8070
8071 // if t == 13 then UNPREDICTABLE;
8072 if (t == 13)
8073 return false;
8074
8075 break;
8076
8077 case eEncodingA1: {
8078 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
8079 t = Bits32(bits: opcode, msbit: 15, lsbit: 12);
8080 uint32_t imm4H = Bits32(bits: opcode, msbit: 11, lsbit: 8);
8081 uint32_t imm4L = Bits32(bits: opcode, msbit: 3, lsbit: 0);
8082 imm32 = (imm4H << 4) | imm4L;
8083 add = BitIsSet(value: opcode, bit: 23);
8084
8085 // if t == 15 then UNPREDICTABLE;
8086 if (t == 15)
8087 return false;
8088
8089 break;
8090 }
8091 default:
8092 return false;
8093 }
8094
8095 // base = Align(PC,4);
8096 uint64_t pc_value = ReadCoreReg(PC_REG, success: &success);
8097 if (!success)
8098 return false;
8099
8100 uint64_t base = AlignPC(pc_value);
8101
8102 addr_t address;
8103 // address = if add then (base + imm32) else (base - imm32);
8104 if (add)
8105 address = base + imm32;
8106 else
8107 address = base - imm32;
8108
8109 // data = MemU[address,2];
8110 std::optional<RegisterInfo> base_reg =
8111 GetRegisterInfo(reg_kind: eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
8112
8113 EmulateInstruction::Context context;
8114 context.type = eContextRegisterLoad;
8115 context.SetRegisterPlusOffset(base_reg: *base_reg, signed_offset: imm32);
8116
8117 uint64_t data = MemURead(context, address, size: 2, fail_value: 0, success_ptr: &success);
8118 if (!success)
8119 return false;
8120
8121 // if UnalignedSupport() || address<0> = '0' then
8122 if (UnalignedSupport() || BitIsClear(value: address, bit: 0)) {
8123 // R[t] = SignExtend(data, 32);
8124 int64_t signed_data = llvm::SignExtend64<16>(x: data);
8125 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + t,
8126 reg_value: (uint64_t)signed_data))
8127 return false;
8128 } else // Can only apply before ARMv7
8129 {
8130 // R[t] = bits(32) UNKNOWN;
8131 WriteBits32Unknown(n: t);
8132 }
8133 }
8134 return true;
8135}
8136
8137// LDRSH (register) calculates an address from a base register value and an
8138// offset register value, loads a halfword
8139// from memory, sign-extends it to form a 32-bit word, and writes it to a
8140// register. The offset register value can be shifted left by 0, 1, 2, or 3
8141// bits.
8142bool EmulateInstructionARM::EmulateLDRSHRegister(const uint32_t opcode,
8143 const ARMEncoding encoding) {
8144#if 0
8145 if ConditionPassed() then
8146 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
8147 offset = Shift(R[m], shift_t, shift_n, APSR.C);
8148 offset_addr = if add then (R[n] + offset) else (R[n] - offset);
8149 address = if index then offset_addr else R[n];
8150 data = MemU[address,2];
8151 if wback then R[n] = offset_addr;
8152 if UnalignedSupport() || address<0> = '0' then
8153 R[t] = SignExtend(data, 32);
8154 else // Can only apply before ARMv7
8155 R[t] = bits(32) UNKNOWN;
8156#endif
8157
8158 bool success = false;
8159
8160 if (ConditionPassed(opcode)) {
8161 uint32_t t;
8162 uint32_t n;
8163 uint32_t m;
8164 bool index;
8165 bool add;
8166 bool wback;
8167 ARM_ShifterType shift_t;
8168 uint32_t shift_n;
8169
8170 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
8171 switch (encoding) {
8172 case eEncodingT1:
8173 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation
8174 // in ThumbEE";
8175 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
8176 t = Bits32(bits: opcode, msbit: 2, lsbit: 0);
8177 n = Bits32(bits: opcode, msbit: 5, lsbit: 3);
8178 m = Bits32(bits: opcode, msbit: 8, lsbit: 6);
8179
8180 // index = TRUE; add = TRUE; wback = FALSE;
8181 index = true;
8182 add = true;
8183 wback = false;
8184
8185 // (shift_t, shift_n) = (SRType_LSL, 0);
8186 shift_t = SRType_LSL;
8187 shift_n = 0;
8188
8189 break;
8190
8191 case eEncodingT2:
8192 // if Rn == '1111' then SEE LDRSH (literal);
8193 // if Rt == '1111' then SEE "Unallocated memory hints";
8194 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
8195 t = Bits32(bits: opcode, msbit: 15, lsbit: 12);
8196 n = Bits32(bits: opcode, msbit: 19, lsbit: 16);
8197 m = Bits32(bits: opcode, msbit: 3, lsbit: 0);
8198
8199 // index = TRUE; add = TRUE; wback = FALSE;
8200 index = true;
8201 add = true;
8202 wback = false;
8203
8204 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
8205 shift_t = SRType_LSL;
8206 shift_n = Bits32(bits: opcode, msbit: 5, lsbit: 4);
8207
8208 // if t == 13 || BadReg(m) then UNPREDICTABLE;
8209 if ((t == 13) || BadReg(n: m))
8210 return false;
8211
8212 break;
8213
8214 case eEncodingA1:
8215 // if P == '0' && W == '1' then SEE LDRSHT;
8216 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
8217 t = Bits32(bits: opcode, msbit: 15, lsbit: 12);
8218 n = Bits32(bits: opcode, msbit: 19, lsbit: 16);
8219 m = Bits32(bits: opcode, msbit: 3, lsbit: 0);
8220
8221 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
8222 // (W == '1');
8223 index = BitIsSet(value: opcode, bit: 24);
8224 add = BitIsSet(value: opcode, bit: 23);
8225 wback = BitIsClear(value: opcode, bit: 24) || BitIsSet(value: opcode, bit: 21);
8226
8227 // (shift_t, shift_n) = (SRType_LSL, 0);
8228 shift_t = SRType_LSL;
8229 shift_n = 0;
8230
8231 // if t == 15 || m == 15 then UNPREDICTABLE;
8232 if ((t == 15) || (m == 15))
8233 return false;
8234
8235 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
8236 if (wback && ((n == 15) || (n == t)))
8237 return false;
8238
8239 break;
8240
8241 default:
8242 return false;
8243 }
8244
8245 uint64_t Rm =
8246 ReadRegisterUnsigned(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + m, fail_value: 0, success_ptr: &success);
8247 if (!success)
8248 return false;
8249
8250 uint64_t Rn =
8251 ReadRegisterUnsigned(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n, fail_value: 0, success_ptr: &success);
8252 if (!success)
8253 return false;
8254
8255 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
8256 addr_t offset = Shift(value: Rm, type: shift_t, amount: shift_n, APSR_C, success: &success);
8257 if (!success)
8258 return false;
8259
8260 addr_t offset_addr;
8261 addr_t address;
8262
8263 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
8264 if (add)
8265 offset_addr = Rn + offset;
8266 else
8267 offset_addr = Rn - offset;
8268
8269 // address = if index then offset_addr else R[n];
8270 if (index)
8271 address = offset_addr;
8272 else
8273 address = Rn;
8274
8275 // data = MemU[address,2];
8276 std::optional<RegisterInfo> base_reg =
8277 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n);
8278 std::optional<RegisterInfo> offset_reg =
8279 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + m);
8280
8281 EmulateInstruction::Context context;
8282 context.type = eContextRegisterLoad;
8283 context.SetRegisterPlusIndirectOffset(base_reg: *base_reg, offset_reg: *offset_reg);
8284
8285 uint64_t data = MemURead(context, address, size: 2, fail_value: 0, success_ptr: &success);
8286 if (!success)
8287 return false;
8288
8289 // if wback then R[n] = offset_addr;
8290 if (wback) {
8291 context.type = eContextAdjustBaseRegister;
8292 context.SetAddress(offset_addr);
8293 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n,
8294 reg_value: offset_addr))
8295 return false;
8296 }
8297
8298 // if UnalignedSupport() || address<0> = '0' then
8299 if (UnalignedSupport() || BitIsClear(value: address, bit: 0)) {
8300 // R[t] = SignExtend(data, 32);
8301 context.type = eContextRegisterLoad;
8302 context.SetRegisterPlusIndirectOffset(base_reg: *base_reg, offset_reg: *offset_reg);
8303
8304 int64_t signed_data = llvm::SignExtend64<16>(x: data);
8305 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + t,
8306 reg_value: (uint64_t)signed_data))
8307 return false;
8308 } else // Can only apply before ARMv7
8309 {
8310 // R[t] = bits(32) UNKNOWN;
8311 WriteBits32Unknown(n: t);
8312 }
8313 }
8314 return true;
8315}
8316
8317// SXTB extracts an 8-bit value from a register, sign-extends it to 32 bits, and
8318// writes the result to the destination
8319// register. You can specifiy a rotation by 0, 8, 16, or 24 bits before
8320// extracting the 8-bit value.
8321bool EmulateInstructionARM::EmulateSXTB(const uint32_t opcode,
8322 const ARMEncoding encoding) {
8323#if 0
8324 if ConditionPassed() then
8325 EncodingSpecificOperations();
8326 rotated = ROR(R[m], rotation);
8327 R[d] = SignExtend(rotated<7:0>, 32);
8328#endif
8329
8330 bool success = false;
8331
8332 if (ConditionPassed(opcode)) {
8333 uint32_t d;
8334 uint32_t m;
8335 uint32_t rotation;
8336
8337 // EncodingSpecificOperations();
8338 switch (encoding) {
8339 case eEncodingT1:
8340 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
8341 d = Bits32(bits: opcode, msbit: 2, lsbit: 0);
8342 m = Bits32(bits: opcode, msbit: 5, lsbit: 3);
8343 rotation = 0;
8344
8345 break;
8346
8347 case eEncodingT2:
8348 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8349 d = Bits32(bits: opcode, msbit: 11, lsbit: 8);
8350 m = Bits32(bits: opcode, msbit: 3, lsbit: 0);
8351 rotation = Bits32(bits: opcode, msbit: 5, lsbit: 4) << 3;
8352
8353 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
8354 if (BadReg(n: d) || BadReg(n: m))
8355 return false;
8356
8357 break;
8358
8359 case eEncodingA1:
8360 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8361 d = Bits32(bits: opcode, msbit: 15, lsbit: 12);
8362 m = Bits32(bits: opcode, msbit: 3, lsbit: 0);
8363 rotation = Bits32(bits: opcode, msbit: 11, lsbit: 10) << 3;
8364
8365 // if d == 15 || m == 15 then UNPREDICTABLE;
8366 if ((d == 15) || (m == 15))
8367 return false;
8368
8369 break;
8370
8371 default:
8372 return false;
8373 }
8374
8375 uint64_t Rm =
8376 ReadRegisterUnsigned(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + m, fail_value: 0, success_ptr: &success);
8377 if (!success)
8378 return false;
8379
8380 // rotated = ROR(R[m], rotation);
8381 uint64_t rotated = ROR(value: Rm, amount: rotation, success: &success);
8382 if (!success)
8383 return false;
8384
8385 // R[d] = SignExtend(rotated<7:0>, 32);
8386 int64_t data = llvm::SignExtend64<8>(x: rotated);
8387
8388 std::optional<RegisterInfo> source_reg =
8389 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + m);
8390
8391 EmulateInstruction::Context context;
8392 context.type = eContextRegisterLoad;
8393 context.SetRegister(*source_reg);
8394
8395 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + d,
8396 reg_value: (uint64_t)data))
8397 return false;
8398 }
8399 return true;
8400}
8401
8402// SXTH extracts a 16-bit value from a register, sign-extends it to 32 bits, and
8403// writes the result to the destination
8404// register. You can specify a rotation by 0, 8, 16, or 24 bits before
8405// extracting the 16-bit value.
8406bool EmulateInstructionARM::EmulateSXTH(const uint32_t opcode,
8407 const ARMEncoding encoding) {
8408#if 0
8409 if ConditionPassed() then
8410 EncodingSpecificOperations();
8411 rotated = ROR(R[m], rotation);
8412 R[d] = SignExtend(rotated<15:0>, 32);
8413#endif
8414
8415 bool success = false;
8416
8417 if (ConditionPassed(opcode)) {
8418 uint32_t d;
8419 uint32_t m;
8420 uint32_t rotation;
8421
8422 // EncodingSpecificOperations();
8423 switch (encoding) {
8424 case eEncodingT1:
8425 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
8426 d = Bits32(bits: opcode, msbit: 2, lsbit: 0);
8427 m = Bits32(bits: opcode, msbit: 5, lsbit: 3);
8428 rotation = 0;
8429
8430 break;
8431
8432 case eEncodingT2:
8433 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8434 d = Bits32(bits: opcode, msbit: 11, lsbit: 8);
8435 m = Bits32(bits: opcode, msbit: 3, lsbit: 0);
8436 rotation = Bits32(bits: opcode, msbit: 5, lsbit: 4) << 3;
8437
8438 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
8439 if (BadReg(n: d) || BadReg(n: m))
8440 return false;
8441
8442 break;
8443
8444 case eEncodingA1:
8445 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8446 d = Bits32(bits: opcode, msbit: 15, lsbit: 12);
8447 m = Bits32(bits: opcode, msbit: 3, lsbit: 0);
8448 rotation = Bits32(bits: opcode, msbit: 11, lsbit: 10) << 3;
8449
8450 // if d == 15 || m == 15 then UNPREDICTABLE;
8451 if ((d == 15) || (m == 15))
8452 return false;
8453
8454 break;
8455
8456 default:
8457 return false;
8458 }
8459
8460 uint64_t Rm =
8461 ReadRegisterUnsigned(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + m, fail_value: 0, success_ptr: &success);
8462 if (!success)
8463 return false;
8464
8465 // rotated = ROR(R[m], rotation);
8466 uint64_t rotated = ROR(value: Rm, amount: rotation, success: &success);
8467 if (!success)
8468 return false;
8469
8470 // R[d] = SignExtend(rotated<15:0>, 32);
8471 std::optional<RegisterInfo> source_reg =
8472 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + m);
8473
8474 EmulateInstruction::Context context;
8475 context.type = eContextRegisterLoad;
8476 context.SetRegister(*source_reg);
8477
8478 int64_t data = llvm::SignExtend64<16>(x: rotated);
8479 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + d,
8480 reg_value: (uint64_t)data))
8481 return false;
8482 }
8483
8484 return true;
8485}
8486
8487// UXTB extracts an 8-bit value from a register, zero-extends it to 32 bits, and
8488// writes the result to the destination
8489// register. You can specify a rotation by 0, 8, 16, or 24 bits before
8490// extracting the 8-bit value.
8491bool EmulateInstructionARM::EmulateUXTB(const uint32_t opcode,
8492 const ARMEncoding encoding) {
8493#if 0
8494 if ConditionPassed() then
8495 EncodingSpecificOperations();
8496 rotated = ROR(R[m], rotation);
8497 R[d] = ZeroExtend(rotated<7:0>, 32);
8498#endif
8499
8500 bool success = false;
8501
8502 if (ConditionPassed(opcode)) {
8503 uint32_t d;
8504 uint32_t m;
8505 uint32_t rotation;
8506
8507 // EncodingSpecificOperations();
8508 switch (encoding) {
8509 case eEncodingT1:
8510 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
8511 d = Bits32(bits: opcode, msbit: 2, lsbit: 0);
8512 m = Bits32(bits: opcode, msbit: 5, lsbit: 3);
8513 rotation = 0;
8514
8515 break;
8516
8517 case eEncodingT2:
8518 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8519 d = Bits32(bits: opcode, msbit: 11, lsbit: 8);
8520 m = Bits32(bits: opcode, msbit: 3, lsbit: 0);
8521 rotation = Bits32(bits: opcode, msbit: 5, lsbit: 4) << 3;
8522
8523 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
8524 if (BadReg(n: d) || BadReg(n: m))
8525 return false;
8526
8527 break;
8528
8529 case eEncodingA1:
8530 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8531 d = Bits32(bits: opcode, msbit: 15, lsbit: 12);
8532 m = Bits32(bits: opcode, msbit: 3, lsbit: 0);
8533 rotation = Bits32(bits: opcode, msbit: 11, lsbit: 10) << 3;
8534
8535 // if d == 15 || m == 15 then UNPREDICTABLE;
8536 if ((d == 15) || (m == 15))
8537 return false;
8538
8539 break;
8540
8541 default:
8542 return false;
8543 }
8544
8545 uint64_t Rm =
8546 ReadRegisterUnsigned(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + m, fail_value: 0, success_ptr: &success);
8547 if (!success)
8548 return false;
8549
8550 // rotated = ROR(R[m], rotation);
8551 uint64_t rotated = ROR(value: Rm, amount: rotation, success: &success);
8552 if (!success)
8553 return false;
8554
8555 // R[d] = ZeroExtend(rotated<7:0>, 32);
8556 std::optional<RegisterInfo> source_reg =
8557 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + m);
8558
8559 EmulateInstruction::Context context;
8560 context.type = eContextRegisterLoad;
8561 context.SetRegister(*source_reg);
8562
8563 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + d,
8564 reg_value: Bits32(bits: rotated, msbit: 7, lsbit: 0)))
8565 return false;
8566 }
8567 return true;
8568}
8569
8570// UXTH extracts a 16-bit value from a register, zero-extends it to 32 bits, and
8571// writes the result to the destination
8572// register. You can specify a rotation by 0, 8, 16, or 24 bits before
8573// extracting the 16-bit value.
8574bool EmulateInstructionARM::EmulateUXTH(const uint32_t opcode,
8575 const ARMEncoding encoding) {
8576#if 0
8577 if ConditionPassed() then
8578 EncodingSpecificOperations();
8579 rotated = ROR(R[m], rotation);
8580 R[d] = ZeroExtend(rotated<15:0>, 32);
8581#endif
8582
8583 bool success = false;
8584
8585 if (ConditionPassed(opcode)) {
8586 uint32_t d;
8587 uint32_t m;
8588 uint32_t rotation;
8589
8590 switch (encoding) {
8591 case eEncodingT1:
8592 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
8593 d = Bits32(bits: opcode, msbit: 2, lsbit: 0);
8594 m = Bits32(bits: opcode, msbit: 5, lsbit: 3);
8595 rotation = 0;
8596
8597 break;
8598
8599 case eEncodingT2:
8600 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8601 d = Bits32(bits: opcode, msbit: 11, lsbit: 8);
8602 m = Bits32(bits: opcode, msbit: 3, lsbit: 0);
8603 rotation = Bits32(bits: opcode, msbit: 5, lsbit: 4) << 3;
8604
8605 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
8606 if (BadReg(n: d) || BadReg(n: m))
8607 return false;
8608
8609 break;
8610
8611 case eEncodingA1:
8612 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8613 d = Bits32(bits: opcode, msbit: 15, lsbit: 12);
8614 m = Bits32(bits: opcode, msbit: 3, lsbit: 0);
8615 rotation = Bits32(bits: opcode, msbit: 11, lsbit: 10) << 3;
8616
8617 // if d == 15 || m == 15 then UNPREDICTABLE;
8618 if ((d == 15) || (m == 15))
8619 return false;
8620
8621 break;
8622
8623 default:
8624 return false;
8625 }
8626
8627 uint64_t Rm =
8628 ReadRegisterUnsigned(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + m, fail_value: 0, success_ptr: &success);
8629 if (!success)
8630 return false;
8631
8632 // rotated = ROR(R[m], rotation);
8633 uint64_t rotated = ROR(value: Rm, amount: rotation, success: &success);
8634 if (!success)
8635 return false;
8636
8637 // R[d] = ZeroExtend(rotated<15:0>, 32);
8638 std::optional<RegisterInfo> source_reg =
8639 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + m);
8640
8641 EmulateInstruction::Context context;
8642 context.type = eContextRegisterLoad;
8643 context.SetRegister(*source_reg);
8644
8645 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + d,
8646 reg_value: Bits32(bits: rotated, msbit: 15, lsbit: 0)))
8647 return false;
8648 }
8649 return true;
8650}
8651
8652// RFE (Return From Exception) loads the PC and the CPSR from the word at the
8653// specified address and the following
8654// word respectively.
8655bool EmulateInstructionARM::EmulateRFE(const uint32_t opcode,
8656 const ARMEncoding encoding) {
8657#if 0
8658 if ConditionPassed() then
8659 EncodingSpecificOperations();
8660 if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE then
8661 UNPREDICTABLE;
8662 else
8663 address = if increment then R[n] else R[n]-8;
8664 if wordhigher then address = address+4;
8665 CPSRWriteByInstr(MemA[address+4,4], '1111', TRUE);
8666 BranchWritePC(MemA[address,4]);
8667 if wback then R[n] = if increment then R[n]+8 else R[n]-8;
8668#endif
8669
8670 bool success = false;
8671
8672 if (ConditionPassed(opcode)) {
8673 uint32_t n;
8674 bool wback;
8675 bool increment;
8676 bool wordhigher;
8677
8678 // EncodingSpecificOperations();
8679 switch (encoding) {
8680 case eEncodingT1:
8681 // n = UInt(Rn); wback = (W == '1'); increment = FALSE; wordhigher =
8682 // FALSE;
8683 n = Bits32(bits: opcode, msbit: 19, lsbit: 16);
8684 wback = BitIsSet(value: opcode, bit: 21);
8685 increment = false;
8686 wordhigher = false;
8687
8688 // if n == 15 then UNPREDICTABLE;
8689 if (n == 15)
8690 return false;
8691
8692 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
8693 if (InITBlock() && !LastInITBlock())
8694 return false;
8695
8696 break;
8697
8698 case eEncodingT2:
8699 // n = UInt(Rn); wback = (W == '1'); increment = TRUE; wordhigher = FALSE;
8700 n = Bits32(bits: opcode, msbit: 19, lsbit: 16);
8701 wback = BitIsSet(value: opcode, bit: 21);
8702 increment = true;
8703 wordhigher = false;
8704
8705 // if n == 15 then UNPREDICTABLE;
8706 if (n == 15)
8707 return false;
8708
8709 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
8710 if (InITBlock() && !LastInITBlock())
8711 return false;
8712
8713 break;
8714
8715 case eEncodingA1:
8716 // n = UInt(Rn);
8717 n = Bits32(bits: opcode, msbit: 19, lsbit: 16);
8718
8719 // wback = (W == '1'); inc = (U == '1'); wordhigher = (P == U);
8720 wback = BitIsSet(value: opcode, bit: 21);
8721 increment = BitIsSet(value: opcode, bit: 23);
8722 wordhigher = (Bit32(bits: opcode, bit: 24) == Bit32(bits: opcode, bit: 23));
8723
8724 // if n == 15 then UNPREDICTABLE;
8725 if (n == 15)
8726 return false;
8727
8728 break;
8729
8730 default:
8731 return false;
8732 }
8733
8734 // if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE
8735 // then
8736 if (!CurrentModeIsPrivileged())
8737 // UNPREDICTABLE;
8738 return false;
8739 else {
8740 uint64_t Rn =
8741 ReadRegisterUnsigned(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n, fail_value: 0, success_ptr: &success);
8742 if (!success)
8743 return false;
8744
8745 addr_t address;
8746 // address = if increment then R[n] else R[n]-8;
8747 if (increment)
8748 address = Rn;
8749 else
8750 address = Rn - 8;
8751
8752 // if wordhigher then address = address+4;
8753 if (wordhigher)
8754 address = address + 4;
8755
8756 // CPSRWriteByInstr(MemA[address+4,4], '1111', TRUE);
8757 std::optional<RegisterInfo> base_reg =
8758 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n);
8759
8760 EmulateInstruction::Context context;
8761 context.type = eContextReturnFromException;
8762 context.SetRegisterPlusOffset(base_reg: *base_reg, signed_offset: address - Rn);
8763
8764 uint64_t data = MemARead(context, address: address + 4, size: 4, fail_value: 0, success_ptr: &success);
8765 if (!success)
8766 return false;
8767
8768 CPSRWriteByInstr(value: data, bytemask: 15, affect_execstate: true);
8769
8770 // BranchWritePC(MemA[address,4]);
8771 uint64_t data2 = MemARead(context, address, size: 4, fail_value: 0, success_ptr: &success);
8772 if (!success)
8773 return false;
8774
8775 BranchWritePC(context, addr: data2);
8776
8777 // if wback then R[n] = if increment then R[n]+8 else R[n]-8;
8778 if (wback) {
8779 context.type = eContextAdjustBaseRegister;
8780 if (increment) {
8781 context.SetOffset(8);
8782 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n,
8783 reg_value: Rn + 8))
8784 return false;
8785 } else {
8786 context.SetOffset(-8);
8787 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n,
8788 reg_value: Rn - 8))
8789 return false;
8790 }
8791 } // if wback
8792 }
8793 } // if ConditionPassed()
8794 return true;
8795}
8796
8797// Bitwise Exclusive OR (immediate) performs a bitwise exclusive OR of a
8798// register value and an immediate value, and writes the result to the
8799// destination register. It can optionally update the condition flags based on
8800// the result.
8801bool EmulateInstructionARM::EmulateEORImm(const uint32_t opcode,
8802 const ARMEncoding encoding) {
8803#if 0
8804 // ARM pseudo code...
8805 if ConditionPassed() then
8806 EncodingSpecificOperations();
8807 result = R[n] EOR imm32;
8808 if d == 15 then // Can only occur for ARM encoding
8809 ALUWritePC(result); // setflags is always FALSE here
8810 else
8811 R[d] = result;
8812 if setflags then
8813 APSR.N = result<31>;
8814 APSR.Z = IsZeroBit(result);
8815 APSR.C = carry;
8816 // APSR.V unchanged
8817#endif
8818
8819 bool success = false;
8820
8821 if (ConditionPassed(opcode)) {
8822 uint32_t Rd, Rn;
8823 uint32_t
8824 imm32; // the immediate value to be ORed to the value obtained from Rn
8825 bool setflags;
8826 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
8827 switch (encoding) {
8828 case eEncodingT1:
8829 Rd = Bits32(bits: opcode, msbit: 11, lsbit: 8);
8830 Rn = Bits32(bits: opcode, msbit: 19, lsbit: 16);
8831 setflags = BitIsSet(value: opcode, bit: 20);
8832 imm32 = ThumbExpandImm_C(
8833 opcode, APSR_C,
8834 carry_out&: carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
8835 // if Rd == '1111' && S == '1' then SEE TEQ (immediate);
8836 if (Rd == 15 && setflags)
8837 return EmulateTEQImm(opcode, encoding: eEncodingT1);
8838 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(n: Rn))
8839 return false;
8840 break;
8841 case eEncodingA1:
8842 Rd = Bits32(bits: opcode, msbit: 15, lsbit: 12);
8843 Rn = Bits32(bits: opcode, msbit: 19, lsbit: 16);
8844 setflags = BitIsSet(value: opcode, bit: 20);
8845 imm32 =
8846 ARMExpandImm_C(opcode, APSR_C,
8847 carry_out&: carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
8848
8849 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
8850 // instructions;
8851 if (Rd == 15 && setflags)
8852 return EmulateSUBSPcLrEtc(opcode, encoding);
8853 break;
8854 default:
8855 return false;
8856 }
8857
8858 // Read the first operand.
8859 uint32_t val1 = ReadCoreReg(regnum: Rn, success: &success);
8860 if (!success)
8861 return false;
8862
8863 uint32_t result = val1 ^ imm32;
8864
8865 EmulateInstruction::Context context;
8866 context.type = EmulateInstruction::eContextImmediate;
8867 context.SetNoArgs();
8868
8869 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8870 return false;
8871 }
8872 return true;
8873}
8874
8875// Bitwise Exclusive OR (register) performs a bitwise exclusive OR of a
8876// register value and an optionally-shifted register value, and writes the
8877// result to the destination register. It can optionally update the condition
8878// flags based on the result.
8879bool EmulateInstructionARM::EmulateEORReg(const uint32_t opcode,
8880 const ARMEncoding encoding) {
8881#if 0
8882 // ARM pseudo code...
8883 if ConditionPassed() then
8884 EncodingSpecificOperations();
8885 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
8886 result = R[n] EOR shifted;
8887 if d == 15 then // Can only occur for ARM encoding
8888 ALUWritePC(result); // setflags is always FALSE here
8889 else
8890 R[d] = result;
8891 if setflags then
8892 APSR.N = result<31>;
8893 APSR.Z = IsZeroBit(result);
8894 APSR.C = carry;
8895 // APSR.V unchanged
8896#endif
8897
8898 bool success = false;
8899
8900 if (ConditionPassed(opcode)) {
8901 uint32_t Rd, Rn, Rm;
8902 ARM_ShifterType shift_t;
8903 uint32_t shift_n; // the shift applied to the value read from Rm
8904 bool setflags;
8905 uint32_t carry;
8906 switch (encoding) {
8907 case eEncodingT1:
8908 Rd = Rn = Bits32(bits: opcode, msbit: 2, lsbit: 0);
8909 Rm = Bits32(bits: opcode, msbit: 5, lsbit: 3);
8910 setflags = !InITBlock();
8911 shift_t = SRType_LSL;
8912 shift_n = 0;
8913 break;
8914 case eEncodingT2:
8915 Rd = Bits32(bits: opcode, msbit: 11, lsbit: 8);
8916 Rn = Bits32(bits: opcode, msbit: 19, lsbit: 16);
8917 Rm = Bits32(bits: opcode, msbit: 3, lsbit: 0);
8918 setflags = BitIsSet(value: opcode, bit: 20);
8919 shift_n = DecodeImmShiftThumb(opcode, shift_t);
8920 // if Rd == '1111' && S == '1' then SEE TEQ (register);
8921 if (Rd == 15 && setflags)
8922 return EmulateTEQReg(opcode, encoding: eEncodingT1);
8923 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(n: Rn) || BadReg(n: Rm))
8924 return false;
8925 break;
8926 case eEncodingA1:
8927 Rd = Bits32(bits: opcode, msbit: 15, lsbit: 12);
8928 Rn = Bits32(bits: opcode, msbit: 19, lsbit: 16);
8929 Rm = Bits32(bits: opcode, msbit: 3, lsbit: 0);
8930 setflags = BitIsSet(value: opcode, bit: 20);
8931 shift_n = DecodeImmShiftARM(opcode, shift_t);
8932
8933 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
8934 // instructions;
8935 if (Rd == 15 && setflags)
8936 return EmulateSUBSPcLrEtc(opcode, encoding);
8937 break;
8938 default:
8939 return false;
8940 }
8941
8942 // Read the first operand.
8943 uint32_t val1 = ReadCoreReg(regnum: Rn, success: &success);
8944 if (!success)
8945 return false;
8946
8947 // Read the second operand.
8948 uint32_t val2 = ReadCoreReg(regnum: Rm, success: &success);
8949 if (!success)
8950 return false;
8951
8952 uint32_t shifted = Shift_C(value: val2, type: shift_t, amount: shift_n, APSR_C, carry_out&: carry, success: &success);
8953 if (!success)
8954 return false;
8955 uint32_t result = val1 ^ shifted;
8956
8957 EmulateInstruction::Context context;
8958 context.type = EmulateInstruction::eContextImmediate;
8959 context.SetNoArgs();
8960
8961 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8962 return false;
8963 }
8964 return true;
8965}
8966
8967// Bitwise OR (immediate) performs a bitwise (inclusive) OR of a register value
8968// and an immediate value, and writes the result to the destination register.
8969// It can optionally update the condition flags based on the result.
8970bool EmulateInstructionARM::EmulateORRImm(const uint32_t opcode,
8971 const ARMEncoding encoding) {
8972#if 0
8973 // ARM pseudo code...
8974 if ConditionPassed() then
8975 EncodingSpecificOperations();
8976 result = R[n] OR imm32;
8977 if d == 15 then // Can only occur for ARM encoding
8978 ALUWritePC(result); // setflags is always FALSE here
8979 else
8980 R[d] = result;
8981 if setflags then
8982 APSR.N = result<31>;
8983 APSR.Z = IsZeroBit(result);
8984 APSR.C = carry;
8985 // APSR.V unchanged
8986#endif
8987
8988 bool success = false;
8989
8990 if (ConditionPassed(opcode)) {
8991 uint32_t Rd, Rn;
8992 uint32_t
8993 imm32; // the immediate value to be ORed to the value obtained from Rn
8994 bool setflags;
8995 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
8996 switch (encoding) {
8997 case eEncodingT1:
8998 Rd = Bits32(bits: opcode, msbit: 11, lsbit: 8);
8999 Rn = Bits32(bits: opcode, msbit: 19, lsbit: 16);
9000 setflags = BitIsSet(value: opcode, bit: 20);
9001 imm32 = ThumbExpandImm_C(
9002 opcode, APSR_C,
9003 carry_out&: carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
9004 // if Rn == '1111' then SEE MOV (immediate);
9005 if (Rn == 15)
9006 return EmulateMOVRdImm(opcode, encoding: eEncodingT2);
9007 if (BadReg(n: Rd) || Rn == 13)
9008 return false;
9009 break;
9010 case eEncodingA1:
9011 Rd = Bits32(bits: opcode, msbit: 15, lsbit: 12);
9012 Rn = Bits32(bits: opcode, msbit: 19, lsbit: 16);
9013 setflags = BitIsSet(value: opcode, bit: 20);
9014 imm32 =
9015 ARMExpandImm_C(opcode, APSR_C,
9016 carry_out&: carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
9017
9018 if (Rd == 15 && setflags)
9019 return EmulateSUBSPcLrEtc(opcode, encoding);
9020 break;
9021 default:
9022 return false;
9023 }
9024
9025 // Read the first operand.
9026 uint32_t val1 = ReadCoreReg(regnum: Rn, success: &success);
9027 if (!success)
9028 return false;
9029
9030 uint32_t result = val1 | imm32;
9031
9032 EmulateInstruction::Context context;
9033 context.type = EmulateInstruction::eContextImmediate;
9034 context.SetNoArgs();
9035
9036 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
9037 return false;
9038 }
9039 return true;
9040}
9041
9042// Bitwise OR (register) performs a bitwise (inclusive) OR of a register value
9043// and an optionally-shifted register value, and writes the result to the
9044// destination register. It can optionally update the condition flags based on
9045// the result.
9046bool EmulateInstructionARM::EmulateORRReg(const uint32_t opcode,
9047 const ARMEncoding encoding) {
9048#if 0
9049 // ARM pseudo code...
9050 if ConditionPassed() then
9051 EncodingSpecificOperations();
9052 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
9053 result = R[n] OR shifted;
9054 if d == 15 then // Can only occur for ARM encoding
9055 ALUWritePC(result); // setflags is always FALSE here
9056 else
9057 R[d] = result;
9058 if setflags then
9059 APSR.N = result<31>;
9060 APSR.Z = IsZeroBit(result);
9061 APSR.C = carry;
9062 // APSR.V unchanged
9063#endif
9064
9065 bool success = false;
9066
9067 if (ConditionPassed(opcode)) {
9068 uint32_t Rd, Rn, Rm;
9069 ARM_ShifterType shift_t;
9070 uint32_t shift_n; // the shift applied to the value read from Rm
9071 bool setflags;
9072 uint32_t carry;
9073 switch (encoding) {
9074 case eEncodingT1:
9075 Rd = Rn = Bits32(bits: opcode, msbit: 2, lsbit: 0);
9076 Rm = Bits32(bits: opcode, msbit: 5, lsbit: 3);
9077 setflags = !InITBlock();
9078 shift_t = SRType_LSL;
9079 shift_n = 0;
9080 break;
9081 case eEncodingT2:
9082 Rd = Bits32(bits: opcode, msbit: 11, lsbit: 8);
9083 Rn = Bits32(bits: opcode, msbit: 19, lsbit: 16);
9084 Rm = Bits32(bits: opcode, msbit: 3, lsbit: 0);
9085 setflags = BitIsSet(value: opcode, bit: 20);
9086 shift_n = DecodeImmShiftThumb(opcode, shift_t);
9087 // if Rn == '1111' then SEE MOV (register);
9088 if (Rn == 15)
9089 return EmulateMOVRdRm(opcode, encoding: eEncodingT3);
9090 if (BadReg(n: Rd) || Rn == 13 || BadReg(n: Rm))
9091 return false;
9092 break;
9093 case eEncodingA1:
9094 Rd = Bits32(bits: opcode, msbit: 15, lsbit: 12);
9095 Rn = Bits32(bits: opcode, msbit: 19, lsbit: 16);
9096 Rm = Bits32(bits: opcode, msbit: 3, lsbit: 0);
9097 setflags = BitIsSet(value: opcode, bit: 20);
9098 shift_n = DecodeImmShiftARM(opcode, shift_t);
9099
9100 if (Rd == 15 && setflags)
9101 return EmulateSUBSPcLrEtc(opcode, encoding);
9102 break;
9103 default:
9104 return false;
9105 }
9106
9107 // Read the first operand.
9108 uint32_t val1 = ReadCoreReg(regnum: Rn, success: &success);
9109 if (!success)
9110 return false;
9111
9112 // Read the second operand.
9113 uint32_t val2 = ReadCoreReg(regnum: Rm, success: &success);
9114 if (!success)
9115 return false;
9116
9117 uint32_t shifted = Shift_C(value: val2, type: shift_t, amount: shift_n, APSR_C, carry_out&: carry, success: &success);
9118 if (!success)
9119 return false;
9120 uint32_t result = val1 | shifted;
9121
9122 EmulateInstruction::Context context;
9123 context.type = EmulateInstruction::eContextImmediate;
9124 context.SetNoArgs();
9125
9126 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
9127 return false;
9128 }
9129 return true;
9130}
9131
9132// Reverse Subtract (immediate) subtracts a register value from an immediate
9133// value, and writes the result to the destination register. It can optionally
9134// update the condition flags based on the result.
9135bool EmulateInstructionARM::EmulateRSBImm(const uint32_t opcode,
9136 const ARMEncoding encoding) {
9137#if 0
9138 // ARM pseudo code...
9139 if ConditionPassed() then
9140 EncodingSpecificOperations();
9141 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, '1');
9142 if d == 15 then // Can only occur for ARM encoding
9143 ALUWritePC(result); // setflags is always FALSE here
9144 else
9145 R[d] = result;
9146 if setflags then
9147 APSR.N = result<31>;
9148 APSR.Z = IsZeroBit(result);
9149 APSR.C = carry;
9150 APSR.V = overflow;
9151#endif
9152
9153 bool success = false;
9154
9155 uint32_t Rd; // the destination register
9156 uint32_t Rn; // the first operand
9157 bool setflags;
9158 uint32_t
9159 imm32; // the immediate value to be added to the value obtained from Rn
9160 switch (encoding) {
9161 case eEncodingT1:
9162 Rd = Bits32(bits: opcode, msbit: 2, lsbit: 0);
9163 Rn = Bits32(bits: opcode, msbit: 5, lsbit: 3);
9164 setflags = !InITBlock();
9165 imm32 = 0;
9166 break;
9167 case eEncodingT2:
9168 Rd = Bits32(bits: opcode, msbit: 11, lsbit: 8);
9169 Rn = Bits32(bits: opcode, msbit: 19, lsbit: 16);
9170 setflags = BitIsSet(value: opcode, bit: 20);
9171 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
9172 if (BadReg(n: Rd) || BadReg(n: Rn))
9173 return false;
9174 break;
9175 case eEncodingA1:
9176 Rd = Bits32(bits: opcode, msbit: 15, lsbit: 12);
9177 Rn = Bits32(bits: opcode, msbit: 19, lsbit: 16);
9178 setflags = BitIsSet(value: opcode, bit: 20);
9179 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
9180
9181 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
9182 // instructions;
9183 if (Rd == 15 && setflags)
9184 return EmulateSUBSPcLrEtc(opcode, encoding);
9185 break;
9186 default:
9187 return false;
9188 }
9189 // Read the register value from the operand register Rn.
9190 uint32_t reg_val = ReadCoreReg(regnum: Rn, success: &success);
9191 if (!success)
9192 return false;
9193
9194 AddWithCarryResult res = AddWithCarry(x: ~reg_val, y: imm32, carry_in: 1);
9195
9196 EmulateInstruction::Context context;
9197 context.type = EmulateInstruction::eContextImmediate;
9198 context.SetNoArgs();
9199
9200 return WriteCoreRegOptionalFlags(context, result: res.result, Rd, setflags,
9201 carry: res.carry_out, overflow: res.overflow);
9202}
9203
9204// Reverse Subtract (register) subtracts a register value from an optionally-
9205// shifted register value, and writes the result to the destination register.
9206// It can optionally update the condition flags based on the result.
9207bool EmulateInstructionARM::EmulateRSBReg(const uint32_t opcode,
9208 const ARMEncoding encoding) {
9209#if 0
9210 // ARM pseudo code...
9211 if ConditionPassed() then
9212 EncodingSpecificOperations();
9213 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9214 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, '1');
9215 if d == 15 then // Can only occur for ARM encoding
9216 ALUWritePC(result); // setflags is always FALSE here
9217 else
9218 R[d] = result;
9219 if setflags then
9220 APSR.N = result<31>;
9221 APSR.Z = IsZeroBit(result);
9222 APSR.C = carry;
9223 APSR.V = overflow;
9224#endif
9225
9226 bool success = false;
9227
9228 uint32_t Rd; // the destination register
9229 uint32_t Rn; // the first operand
9230 uint32_t Rm; // the second operand
9231 bool setflags;
9232 ARM_ShifterType shift_t;
9233 uint32_t shift_n; // the shift applied to the value read from Rm
9234 switch (encoding) {
9235 case eEncodingT1:
9236 Rd = Bits32(bits: opcode, msbit: 11, lsbit: 8);
9237 Rn = Bits32(bits: opcode, msbit: 19, lsbit: 16);
9238 Rm = Bits32(bits: opcode, msbit: 3, lsbit: 0);
9239 setflags = BitIsSet(value: opcode, bit: 20);
9240 shift_n = DecodeImmShiftThumb(opcode, shift_t);
9241 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
9242 if (BadReg(n: Rd) || BadReg(n: Rn) || BadReg(n: Rm))
9243 return false;
9244 break;
9245 case eEncodingA1:
9246 Rd = Bits32(bits: opcode, msbit: 15, lsbit: 12);
9247 Rn = Bits32(bits: opcode, msbit: 19, lsbit: 16);
9248 Rm = Bits32(bits: opcode, msbit: 3, lsbit: 0);
9249 setflags = BitIsSet(value: opcode, bit: 20);
9250 shift_n = DecodeImmShiftARM(opcode, shift_t);
9251
9252 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
9253 // instructions;
9254 if (Rd == 15 && setflags)
9255 return EmulateSUBSPcLrEtc(opcode, encoding);
9256 break;
9257 default:
9258 return false;
9259 }
9260 // Read the register value from register Rn.
9261 uint32_t val1 = ReadCoreReg(regnum: Rn, success: &success);
9262 if (!success)
9263 return false;
9264
9265 // Read the register value from register Rm.
9266 uint32_t val2 = ReadCoreReg(regnum: Rm, success: &success);
9267 if (!success)
9268 return false;
9269
9270 uint32_t shifted = Shift(value: val2, type: shift_t, amount: shift_n, APSR_C, success: &success);
9271 if (!success)
9272 return false;
9273 AddWithCarryResult res = AddWithCarry(x: ~val1, y: shifted, carry_in: 1);
9274
9275 EmulateInstruction::Context context;
9276 context.type = EmulateInstruction::eContextImmediate;
9277 context.SetNoArgs();
9278 return WriteCoreRegOptionalFlags(context, result: res.result, Rd, setflags,
9279 carry: res.carry_out, overflow: res.overflow);
9280}
9281
9282// Reverse Subtract with Carry (immediate) subtracts a register value and the
9283// value of NOT (Carry flag) from an immediate value, and writes the result to
9284// the destination register. It can optionally update the condition flags based
9285// on the result.
9286bool EmulateInstructionARM::EmulateRSCImm(const uint32_t opcode,
9287 const ARMEncoding encoding) {
9288#if 0
9289 // ARM pseudo code...
9290 if ConditionPassed() then
9291 EncodingSpecificOperations();
9292 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, APSR.C);
9293 if d == 15 then
9294 ALUWritePC(result); // setflags is always FALSE here
9295 else
9296 R[d] = result;
9297 if setflags then
9298 APSR.N = result<31>;
9299 APSR.Z = IsZeroBit(result);
9300 APSR.C = carry;
9301 APSR.V = overflow;
9302#endif
9303
9304 bool success = false;
9305
9306 uint32_t Rd; // the destination register
9307 uint32_t Rn; // the first operand
9308 bool setflags;
9309 uint32_t
9310 imm32; // the immediate value to be added to the value obtained from Rn
9311 switch (encoding) {
9312 case eEncodingA1:
9313 Rd = Bits32(bits: opcode, msbit: 15, lsbit: 12);
9314 Rn = Bits32(bits: opcode, msbit: 19, lsbit: 16);
9315 setflags = BitIsSet(value: opcode, bit: 20);
9316 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
9317
9318 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
9319 // instructions;
9320 if (Rd == 15 && setflags)
9321 return EmulateSUBSPcLrEtc(opcode, encoding);
9322 break;
9323 default:
9324 return false;
9325 }
9326 // Read the register value from the operand register Rn.
9327 uint32_t reg_val = ReadCoreReg(regnum: Rn, success: &success);
9328 if (!success)
9329 return false;
9330
9331 AddWithCarryResult res = AddWithCarry(x: ~reg_val, y: imm32, APSR_C);
9332
9333 EmulateInstruction::Context context;
9334 context.type = EmulateInstruction::eContextImmediate;
9335 context.SetNoArgs();
9336
9337 return WriteCoreRegOptionalFlags(context, result: res.result, Rd, setflags,
9338 carry: res.carry_out, overflow: res.overflow);
9339}
9340
9341// Reverse Subtract with Carry (register) subtracts a register value and the
9342// value of NOT (Carry flag) from an optionally-shifted register value, and
9343// writes the result to the destination register. It can optionally update the
9344// condition flags based on the result.
9345bool EmulateInstructionARM::EmulateRSCReg(const uint32_t opcode,
9346 const ARMEncoding encoding) {
9347#if 0
9348 // ARM pseudo code...
9349 if ConditionPassed() then
9350 EncodingSpecificOperations();
9351 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9352 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, APSR.C);
9353 if d == 15 then
9354 ALUWritePC(result); // setflags is always FALSE here
9355 else
9356 R[d] = result;
9357 if setflags then
9358 APSR.N = result<31>;
9359 APSR.Z = IsZeroBit(result);
9360 APSR.C = carry;
9361 APSR.V = overflow;
9362#endif
9363
9364 bool success = false;
9365
9366 uint32_t Rd; // the destination register
9367 uint32_t Rn; // the first operand
9368 uint32_t Rm; // the second operand
9369 bool setflags;
9370 ARM_ShifterType shift_t;
9371 uint32_t shift_n; // the shift applied to the value read from Rm
9372 switch (encoding) {
9373 case eEncodingA1:
9374 Rd = Bits32(bits: opcode, msbit: 15, lsbit: 12);
9375 Rn = Bits32(bits: opcode, msbit: 19, lsbit: 16);
9376 Rm = Bits32(bits: opcode, msbit: 3, lsbit: 0);
9377 setflags = BitIsSet(value: opcode, bit: 20);
9378 shift_n = DecodeImmShiftARM(opcode, shift_t);
9379
9380 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
9381 // instructions;
9382 if (Rd == 15 && setflags)
9383 return EmulateSUBSPcLrEtc(opcode, encoding);
9384 break;
9385 default:
9386 return false;
9387 }
9388 // Read the register value from register Rn.
9389 uint32_t val1 = ReadCoreReg(regnum: Rn, success: &success);
9390 if (!success)
9391 return false;
9392
9393 // Read the register value from register Rm.
9394 uint32_t val2 = ReadCoreReg(regnum: Rm, success: &success);
9395 if (!success)
9396 return false;
9397
9398 uint32_t shifted = Shift(value: val2, type: shift_t, amount: shift_n, APSR_C, success: &success);
9399 if (!success)
9400 return false;
9401 AddWithCarryResult res = AddWithCarry(x: ~val1, y: shifted, APSR_C);
9402
9403 EmulateInstruction::Context context;
9404 context.type = EmulateInstruction::eContextImmediate;
9405 context.SetNoArgs();
9406 return WriteCoreRegOptionalFlags(context, result: res.result, Rd, setflags,
9407 carry: res.carry_out, overflow: res.overflow);
9408}
9409
9410// Subtract with Carry (immediate) subtracts an immediate value and the value
9411// of
9412// NOT (Carry flag) from a register value, and writes the result to the
9413// destination register.
9414// It can optionally update the condition flags based on the result.
9415bool EmulateInstructionARM::EmulateSBCImm(const uint32_t opcode,
9416 const ARMEncoding encoding) {
9417#if 0
9418 // ARM pseudo code...
9419 if ConditionPassed() then
9420 EncodingSpecificOperations();
9421 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), APSR.C);
9422 if d == 15 then // Can only occur for ARM encoding
9423 ALUWritePC(result); // setflags is always FALSE here
9424 else
9425 R[d] = result;
9426 if setflags then
9427 APSR.N = result<31>;
9428 APSR.Z = IsZeroBit(result);
9429 APSR.C = carry;
9430 APSR.V = overflow;
9431#endif
9432
9433 bool success = false;
9434
9435 uint32_t Rd; // the destination register
9436 uint32_t Rn; // the first operand
9437 bool setflags;
9438 uint32_t
9439 imm32; // the immediate value to be added to the value obtained from Rn
9440 switch (encoding) {
9441 case eEncodingT1:
9442 Rd = Bits32(bits: opcode, msbit: 11, lsbit: 8);
9443 Rn = Bits32(bits: opcode, msbit: 19, lsbit: 16);
9444 setflags = BitIsSet(value: opcode, bit: 20);
9445 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
9446 if (BadReg(n: Rd) || BadReg(n: Rn))
9447 return false;
9448 break;
9449 case eEncodingA1:
9450 Rd = Bits32(bits: opcode, msbit: 15, lsbit: 12);
9451 Rn = Bits32(bits: opcode, msbit: 19, lsbit: 16);
9452 setflags = BitIsSet(value: opcode, bit: 20);
9453 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
9454
9455 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
9456 // instructions;
9457 if (Rd == 15 && setflags)
9458 return EmulateSUBSPcLrEtc(opcode, encoding);
9459 break;
9460 default:
9461 return false;
9462 }
9463 // Read the register value from the operand register Rn.
9464 uint32_t reg_val = ReadCoreReg(regnum: Rn, success: &success);
9465 if (!success)
9466 return false;
9467
9468 AddWithCarryResult res = AddWithCarry(x: reg_val, y: ~imm32, APSR_C);
9469
9470 EmulateInstruction::Context context;
9471 context.type = EmulateInstruction::eContextImmediate;
9472 context.SetNoArgs();
9473
9474 return WriteCoreRegOptionalFlags(context, result: res.result, Rd, setflags,
9475 carry: res.carry_out, overflow: res.overflow);
9476}
9477
9478// Subtract with Carry (register) subtracts an optionally-shifted register
9479// value and the value of
9480// NOT (Carry flag) from a register value, and writes the result to the
9481// destination register.
9482// It can optionally update the condition flags based on the result.
9483bool EmulateInstructionARM::EmulateSBCReg(const uint32_t opcode,
9484 const ARMEncoding encoding) {
9485#if 0
9486 // ARM pseudo code...
9487 if ConditionPassed() then
9488 EncodingSpecificOperations();
9489 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9490 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), APSR.C);
9491 if d == 15 then // Can only occur for ARM encoding
9492 ALUWritePC(result); // setflags is always FALSE here
9493 else
9494 R[d] = result;
9495 if setflags then
9496 APSR.N = result<31>;
9497 APSR.Z = IsZeroBit(result);
9498 APSR.C = carry;
9499 APSR.V = overflow;
9500#endif
9501
9502 bool success = false;
9503
9504 uint32_t Rd; // the destination register
9505 uint32_t Rn; // the first operand
9506 uint32_t Rm; // the second operand
9507 bool setflags;
9508 ARM_ShifterType shift_t;
9509 uint32_t shift_n; // the shift applied to the value read from Rm
9510 switch (encoding) {
9511 case eEncodingT1:
9512 Rd = Rn = Bits32(bits: opcode, msbit: 2, lsbit: 0);
9513 Rm = Bits32(bits: opcode, msbit: 5, lsbit: 3);
9514 setflags = !InITBlock();
9515 shift_t = SRType_LSL;
9516 shift_n = 0;
9517 break;
9518 case eEncodingT2:
9519 Rd = Bits32(bits: opcode, msbit: 11, lsbit: 8);
9520 Rn = Bits32(bits: opcode, msbit: 19, lsbit: 16);
9521 Rm = Bits32(bits: opcode, msbit: 3, lsbit: 0);
9522 setflags = BitIsSet(value: opcode, bit: 20);
9523 shift_n = DecodeImmShiftThumb(opcode, shift_t);
9524 if (BadReg(n: Rd) || BadReg(n: Rn) || BadReg(n: Rm))
9525 return false;
9526 break;
9527 case eEncodingA1:
9528 Rd = Bits32(bits: opcode, msbit: 15, lsbit: 12);
9529 Rn = Bits32(bits: opcode, msbit: 19, lsbit: 16);
9530 Rm = Bits32(bits: opcode, msbit: 3, lsbit: 0);
9531 setflags = BitIsSet(value: opcode, bit: 20);
9532 shift_n = DecodeImmShiftARM(opcode, shift_t);
9533
9534 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
9535 // instructions;
9536 if (Rd == 15 && setflags)
9537 return EmulateSUBSPcLrEtc(opcode, encoding);
9538 break;
9539 default:
9540 return false;
9541 }
9542 // Read the register value from register Rn.
9543 uint32_t val1 = ReadCoreReg(regnum: Rn, success: &success);
9544 if (!success)
9545 return false;
9546
9547 // Read the register value from register Rm.
9548 uint32_t val2 = ReadCoreReg(regnum: Rm, success: &success);
9549 if (!success)
9550 return false;
9551
9552 uint32_t shifted = Shift(value: val2, type: shift_t, amount: shift_n, APSR_C, success: &success);
9553 if (!success)
9554 return false;
9555 AddWithCarryResult res = AddWithCarry(x: val1, y: ~shifted, APSR_C);
9556
9557 EmulateInstruction::Context context;
9558 context.type = EmulateInstruction::eContextImmediate;
9559 context.SetNoArgs();
9560 return WriteCoreRegOptionalFlags(context, result: res.result, Rd, setflags,
9561 carry: res.carry_out, overflow: res.overflow);
9562}
9563
9564// This instruction subtracts an immediate value from a register value, and
9565// writes the result to the destination register. It can optionally update the
9566// condition flags based on the result.
9567bool EmulateInstructionARM::EmulateSUBImmThumb(const uint32_t opcode,
9568 const ARMEncoding encoding) {
9569#if 0
9570 // ARM pseudo code...
9571 if ConditionPassed() then
9572 EncodingSpecificOperations();
9573 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
9574 R[d] = result;
9575 if setflags then
9576 APSR.N = result<31>;
9577 APSR.Z = IsZeroBit(result);
9578 APSR.C = carry;
9579 APSR.V = overflow;
9580#endif
9581
9582 bool success = false;
9583
9584 uint32_t Rd; // the destination register
9585 uint32_t Rn; // the first operand
9586 bool setflags;
9587 uint32_t imm32; // the immediate value to be subtracted from the value
9588 // obtained from Rn
9589 switch (encoding) {
9590 case eEncodingT1:
9591 Rd = Bits32(bits: opcode, msbit: 2, lsbit: 0);
9592 Rn = Bits32(bits: opcode, msbit: 5, lsbit: 3);
9593 setflags = !InITBlock();
9594 imm32 = Bits32(bits: opcode, msbit: 8, lsbit: 6); // imm32 = ZeroExtend(imm3, 32)
9595 break;
9596 case eEncodingT2:
9597 Rd = Rn = Bits32(bits: opcode, msbit: 10, lsbit: 8);
9598 setflags = !InITBlock();
9599 imm32 = Bits32(bits: opcode, msbit: 7, lsbit: 0); // imm32 = ZeroExtend(imm8, 32)
9600 break;
9601 case eEncodingT3:
9602 Rd = Bits32(bits: opcode, msbit: 11, lsbit: 8);
9603 Rn = Bits32(bits: opcode, msbit: 19, lsbit: 16);
9604 setflags = BitIsSet(value: opcode, bit: 20);
9605 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
9606
9607 // if Rd == '1111' && S == '1' then SEE CMP (immediate);
9608 if (Rd == 15 && setflags)
9609 return EmulateCMPImm(opcode, encoding: eEncodingT2);
9610
9611 // if Rn == '1101' then SEE SUB (SP minus immediate);
9612 if (Rn == 13)
9613 return EmulateSUBSPImm(opcode, encoding: eEncodingT2);
9614
9615 // if d == 13 || (d == 15 && S == '0') || n == 15 then UNPREDICTABLE;
9616 if (Rd == 13 || (Rd == 15 && !setflags) || Rn == 15)
9617 return false;
9618 break;
9619 case eEncodingT4:
9620 Rd = Bits32(bits: opcode, msbit: 11, lsbit: 8);
9621 Rn = Bits32(bits: opcode, msbit: 19, lsbit: 16);
9622 setflags = BitIsSet(value: opcode, bit: 20);
9623 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
9624
9625 // if Rn == '1111' then SEE ADR;
9626 if (Rn == 15)
9627 return EmulateADR(opcode, encoding: eEncodingT2);
9628
9629 // if Rn == '1101' then SEE SUB (SP minus immediate);
9630 if (Rn == 13)
9631 return EmulateSUBSPImm(opcode, encoding: eEncodingT3);
9632
9633 if (BadReg(n: Rd))
9634 return false;
9635 break;
9636 default:
9637 return false;
9638 }
9639 // Read the register value from the operand register Rn.
9640 uint32_t reg_val = ReadCoreReg(regnum: Rn, success: &success);
9641 if (!success)
9642 return false;
9643
9644 AddWithCarryResult res = AddWithCarry(x: reg_val, y: ~imm32, carry_in: 1);
9645
9646 EmulateInstruction::Context context;
9647 context.type = EmulateInstruction::eContextImmediate;
9648 context.SetNoArgs();
9649
9650 return WriteCoreRegOptionalFlags(context, result: res.result, Rd, setflags,
9651 carry: res.carry_out, overflow: res.overflow);
9652}
9653
9654// This instruction subtracts an immediate value from a register value, and
9655// writes the result to the destination register. It can optionally update the
9656// condition flags based on the result.
9657bool EmulateInstructionARM::EmulateSUBImmARM(const uint32_t opcode,
9658 const ARMEncoding encoding) {
9659#if 0
9660 // ARM pseudo code...
9661 if ConditionPassed() then
9662 EncodingSpecificOperations();
9663 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
9664 if d == 15 then
9665 ALUWritePC(result); // setflags is always FALSE here
9666 else
9667 R[d] = result;
9668 if setflags then
9669 APSR.N = result<31>;
9670 APSR.Z = IsZeroBit(result);
9671 APSR.C = carry;
9672 APSR.V = overflow;
9673#endif
9674
9675 bool success = false;
9676
9677 if (ConditionPassed(opcode)) {
9678 uint32_t Rd; // the destination register
9679 uint32_t Rn; // the first operand
9680 bool setflags;
9681 uint32_t imm32; // the immediate value to be subtracted from the value
9682 // obtained from Rn
9683 switch (encoding) {
9684 case eEncodingA1:
9685 Rd = Bits32(bits: opcode, msbit: 15, lsbit: 12);
9686 Rn = Bits32(bits: opcode, msbit: 19, lsbit: 16);
9687 setflags = BitIsSet(value: opcode, bit: 20);
9688 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
9689
9690 // if Rn == '1111' && S == '0' then SEE ADR;
9691 if (Rn == 15 && !setflags)
9692 return EmulateADR(opcode, encoding: eEncodingA2);
9693
9694 // if Rn == '1101' then SEE SUB (SP minus immediate);
9695 if (Rn == 13)
9696 return EmulateSUBSPImm(opcode, encoding: eEncodingA1);
9697
9698 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
9699 // instructions;
9700 if (Rd == 15 && setflags)
9701 return EmulateSUBSPcLrEtc(opcode, encoding);
9702 break;
9703 default:
9704 return false;
9705 }
9706 // Read the register value from the operand register Rn.
9707 uint32_t reg_val = ReadCoreReg(regnum: Rn, success: &success);
9708 if (!success)
9709 return false;
9710
9711 AddWithCarryResult res = AddWithCarry(x: reg_val, y: ~imm32, carry_in: 1);
9712
9713 EmulateInstruction::Context context;
9714 if (Rd == 13)
9715 context.type = EmulateInstruction::eContextAdjustStackPointer;
9716 else
9717 context.type = EmulateInstruction::eContextRegisterPlusOffset;
9718
9719 std::optional<RegisterInfo> dwarf_reg =
9720 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: Rn);
9721 int64_t imm32_signed = imm32;
9722 context.SetRegisterPlusOffset(base_reg: *dwarf_reg, signed_offset: -imm32_signed);
9723
9724 if (!WriteCoreRegOptionalFlags(context, result: res.result, Rd, setflags,
9725 carry: res.carry_out, overflow: res.overflow))
9726 return false;
9727 }
9728 return true;
9729}
9730
9731// Test Equivalence (immediate) performs a bitwise exclusive OR operation on a
9732// register value and an immediate value. It updates the condition flags based
9733// on the result, and discards the result.
9734bool EmulateInstructionARM::EmulateTEQImm(const uint32_t opcode,
9735 const ARMEncoding encoding) {
9736#if 0
9737 // ARM pseudo code...
9738 if ConditionPassed() then
9739 EncodingSpecificOperations();
9740 result = R[n] EOR imm32;
9741 APSR.N = result<31>;
9742 APSR.Z = IsZeroBit(result);
9743 APSR.C = carry;
9744 // APSR.V unchanged
9745#endif
9746
9747 bool success = false;
9748
9749 if (ConditionPassed(opcode)) {
9750 uint32_t Rn;
9751 uint32_t
9752 imm32; // the immediate value to be ANDed to the value obtained from Rn
9753 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
9754 switch (encoding) {
9755 case eEncodingT1:
9756 Rn = Bits32(bits: opcode, msbit: 19, lsbit: 16);
9757 imm32 = ThumbExpandImm_C(
9758 opcode, APSR_C,
9759 carry_out&: carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
9760 if (BadReg(n: Rn))
9761 return false;
9762 break;
9763 case eEncodingA1:
9764 Rn = Bits32(bits: opcode, msbit: 19, lsbit: 16);
9765 imm32 =
9766 ARMExpandImm_C(opcode, APSR_C,
9767 carry_out&: carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
9768 break;
9769 default:
9770 return false;
9771 }
9772
9773 // Read the first operand.
9774 uint32_t val1 = ReadCoreReg(regnum: Rn, success: &success);
9775 if (!success)
9776 return false;
9777
9778 uint32_t result = val1 ^ imm32;
9779
9780 EmulateInstruction::Context context;
9781 context.type = EmulateInstruction::eContextImmediate;
9782 context.SetNoArgs();
9783
9784 if (!WriteFlags(context, result, carry))
9785 return false;
9786 }
9787 return true;
9788}
9789
9790// Test Equivalence (register) performs a bitwise exclusive OR operation on a
9791// register value and an optionally-shifted register value. It updates the
9792// condition flags based on the result, and discards the result.
9793bool EmulateInstructionARM::EmulateTEQReg(const uint32_t opcode,
9794 const ARMEncoding encoding) {
9795#if 0
9796 // ARM pseudo code...
9797 if ConditionPassed() then
9798 EncodingSpecificOperations();
9799 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
9800 result = R[n] EOR shifted;
9801 APSR.N = result<31>;
9802 APSR.Z = IsZeroBit(result);
9803 APSR.C = carry;
9804 // APSR.V unchanged
9805#endif
9806
9807 bool success = false;
9808
9809 if (ConditionPassed(opcode)) {
9810 uint32_t Rn, Rm;
9811 ARM_ShifterType shift_t;
9812 uint32_t shift_n; // the shift applied to the value read from Rm
9813 uint32_t carry;
9814 switch (encoding) {
9815 case eEncodingT1:
9816 Rn = Bits32(bits: opcode, msbit: 19, lsbit: 16);
9817 Rm = Bits32(bits: opcode, msbit: 3, lsbit: 0);
9818 shift_n = DecodeImmShiftThumb(opcode, shift_t);
9819 if (BadReg(n: Rn) || BadReg(n: Rm))
9820 return false;
9821 break;
9822 case eEncodingA1:
9823 Rn = Bits32(bits: opcode, msbit: 19, lsbit: 16);
9824 Rm = Bits32(bits: opcode, msbit: 3, lsbit: 0);
9825 shift_n = DecodeImmShiftARM(opcode, shift_t);
9826 break;
9827 default:
9828 return false;
9829 }
9830
9831 // Read the first operand.
9832 uint32_t val1 = ReadCoreReg(regnum: Rn, success: &success);
9833 if (!success)
9834 return false;
9835
9836 // Read the second operand.
9837 uint32_t val2 = ReadCoreReg(regnum: Rm, success: &success);
9838 if (!success)
9839 return false;
9840
9841 uint32_t shifted = Shift_C(value: val2, type: shift_t, amount: shift_n, APSR_C, carry_out&: carry, success: &success);
9842 if (!success)
9843 return false;
9844 uint32_t result = val1 ^ shifted;
9845
9846 EmulateInstruction::Context context;
9847 context.type = EmulateInstruction::eContextImmediate;
9848 context.SetNoArgs();
9849
9850 if (!WriteFlags(context, result, carry))
9851 return false;
9852 }
9853 return true;
9854}
9855
9856// Test (immediate) performs a bitwise AND operation on a register value and an
9857// immediate value. It updates the condition flags based on the result, and
9858// discards the result.
9859bool EmulateInstructionARM::EmulateTSTImm(const uint32_t opcode,
9860 const ARMEncoding encoding) {
9861#if 0
9862 // ARM pseudo code...
9863 if ConditionPassed() then
9864 EncodingSpecificOperations();
9865 result = R[n] AND imm32;
9866 APSR.N = result<31>;
9867 APSR.Z = IsZeroBit(result);
9868 APSR.C = carry;
9869 // APSR.V unchanged
9870#endif
9871
9872 bool success = false;
9873
9874 if (ConditionPassed(opcode)) {
9875 uint32_t Rn;
9876 uint32_t
9877 imm32; // the immediate value to be ANDed to the value obtained from Rn
9878 uint32_t carry; // the carry bit after ARM/Thumb Expand operation
9879 switch (encoding) {
9880 case eEncodingT1:
9881 Rn = Bits32(bits: opcode, msbit: 19, lsbit: 16);
9882 imm32 = ThumbExpandImm_C(
9883 opcode, APSR_C,
9884 carry_out&: carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
9885 if (BadReg(n: Rn))
9886 return false;
9887 break;
9888 case eEncodingA1:
9889 Rn = Bits32(bits: opcode, msbit: 19, lsbit: 16);
9890 imm32 =
9891 ARMExpandImm_C(opcode, APSR_C,
9892 carry_out&: carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
9893 break;
9894 default:
9895 return false;
9896 }
9897
9898 // Read the first operand.
9899 uint32_t val1 = ReadCoreReg(regnum: Rn, success: &success);
9900 if (!success)
9901 return false;
9902
9903 uint32_t result = val1 & imm32;
9904
9905 EmulateInstruction::Context context;
9906 context.type = EmulateInstruction::eContextImmediate;
9907 context.SetNoArgs();
9908
9909 if (!WriteFlags(context, result, carry))
9910 return false;
9911 }
9912 return true;
9913}
9914
9915// Test (register) performs a bitwise AND operation on a register value and an
9916// optionally-shifted register value. It updates the condition flags based on
9917// the result, and discards the result.
9918bool EmulateInstructionARM::EmulateTSTReg(const uint32_t opcode,
9919 const ARMEncoding encoding) {
9920#if 0
9921 // ARM pseudo code...
9922 if ConditionPassed() then
9923 EncodingSpecificOperations();
9924 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
9925 result = R[n] AND shifted;
9926 APSR.N = result<31>;
9927 APSR.Z = IsZeroBit(result);
9928 APSR.C = carry;
9929 // APSR.V unchanged
9930#endif
9931
9932 bool success = false;
9933
9934 if (ConditionPassed(opcode)) {
9935 uint32_t Rn, Rm;
9936 ARM_ShifterType shift_t;
9937 uint32_t shift_n; // the shift applied to the value read from Rm
9938 uint32_t carry;
9939 switch (encoding) {
9940 case eEncodingT1:
9941 Rn = Bits32(bits: opcode, msbit: 2, lsbit: 0);
9942 Rm = Bits32(bits: opcode, msbit: 5, lsbit: 3);
9943 shift_t = SRType_LSL;
9944 shift_n = 0;
9945 break;
9946 case eEncodingT2:
9947 Rn = Bits32(bits: opcode, msbit: 19, lsbit: 16);
9948 Rm = Bits32(bits: opcode, msbit: 3, lsbit: 0);
9949 shift_n = DecodeImmShiftThumb(opcode, shift_t);
9950 if (BadReg(n: Rn) || BadReg(n: Rm))
9951 return false;
9952 break;
9953 case eEncodingA1:
9954 Rn = Bits32(bits: opcode, msbit: 19, lsbit: 16);
9955 Rm = Bits32(bits: opcode, msbit: 3, lsbit: 0);
9956 shift_n = DecodeImmShiftARM(opcode, shift_t);
9957 break;
9958 default:
9959 return false;
9960 }
9961
9962 // Read the first operand.
9963 uint32_t val1 = ReadCoreReg(regnum: Rn, success: &success);
9964 if (!success)
9965 return false;
9966
9967 // Read the second operand.
9968 uint32_t val2 = ReadCoreReg(regnum: Rm, success: &success);
9969 if (!success)
9970 return false;
9971
9972 uint32_t shifted = Shift_C(value: val2, type: shift_t, amount: shift_n, APSR_C, carry_out&: carry, success: &success);
9973 if (!success)
9974 return false;
9975 uint32_t result = val1 & shifted;
9976
9977 EmulateInstruction::Context context;
9978 context.type = EmulateInstruction::eContextImmediate;
9979 context.SetNoArgs();
9980
9981 if (!WriteFlags(context, result, carry))
9982 return false;
9983 }
9984 return true;
9985}
9986
9987// A8.6.216 SUB (SP minus register)
9988bool EmulateInstructionARM::EmulateSUBSPReg(const uint32_t opcode,
9989 const ARMEncoding encoding) {
9990#if 0
9991 if ConditionPassed() then
9992 EncodingSpecificOperations();
9993 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
9994 (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), '1');
9995 if d == 15 then // Can only occur for ARM encoding
9996 ALUWritePC(result); // setflags is always FALSE here
9997 else
9998 R[d] = result;
9999 if setflags then
10000 APSR.N = result<31>;
10001 APSR.Z = IsZeroBit(result);
10002 APSR.C = carry;
10003 APSR.V = overflow;
10004#endif
10005
10006 bool success = false;
10007
10008 if (ConditionPassed(opcode)) {
10009 uint32_t d;
10010 uint32_t m;
10011 bool setflags;
10012 ARM_ShifterType shift_t;
10013 uint32_t shift_n;
10014
10015 switch (encoding) {
10016 case eEncodingT1:
10017 // d = UInt(Rd); m = UInt(Rm); setflags = (S == '1');
10018 d = Bits32(bits: opcode, msbit: 11, lsbit: 8);
10019 m = Bits32(bits: opcode, msbit: 3, lsbit: 0);
10020 setflags = BitIsSet(value: opcode, bit: 20);
10021
10022 // (shift_t, shift_n) = DecodeImmShift(type, imm3:imm2);
10023 shift_n = DecodeImmShiftThumb(opcode, shift_t);
10024
10025 // if d == 13 && (shift_t != SRType_LSL || shift_n > 3) then
10026 // UNPREDICTABLE;
10027 if ((d == 13) && ((shift_t != SRType_LSL) || (shift_n > 3)))
10028 return false;
10029
10030 // if d == 15 || BadReg(m) then UNPREDICTABLE;
10031 if ((d == 15) || BadReg(n: m))
10032 return false;
10033 break;
10034
10035 case eEncodingA1:
10036 // d = UInt(Rd); m = UInt(Rm); setflags = (S == '1');
10037 d = Bits32(bits: opcode, msbit: 15, lsbit: 12);
10038 m = Bits32(bits: opcode, msbit: 3, lsbit: 0);
10039 setflags = BitIsSet(value: opcode, bit: 20);
10040
10041 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
10042 // instructions;
10043 if (d == 15 && setflags)
10044 EmulateSUBSPcLrEtc(opcode, encoding);
10045
10046 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
10047 shift_n = DecodeImmShiftARM(opcode, shift_t);
10048 break;
10049
10050 default:
10051 return false;
10052 }
10053
10054 // shifted = Shift(R[m], shift_t, shift_n, APSR.C);
10055 uint32_t Rm = ReadCoreReg(regnum: m, success: &success);
10056 if (!success)
10057 return false;
10058
10059 uint32_t shifted = Shift(value: Rm, type: shift_t, amount: shift_n, APSR_C, success: &success);
10060 if (!success)
10061 return false;
10062
10063 // (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), '1');
10064 uint32_t sp_val = ReadCoreReg(SP_REG, success: &success);
10065 if (!success)
10066 return false;
10067
10068 AddWithCarryResult res = AddWithCarry(x: sp_val, y: ~shifted, carry_in: 1);
10069
10070 EmulateInstruction::Context context;
10071 context.type = eContextArithmetic;
10072 std::optional<RegisterInfo> sp_reg =
10073 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_sp);
10074 std::optional<RegisterInfo> dwarf_reg =
10075 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + m);
10076 context.SetRegisterRegisterOperands(op1_reg: *sp_reg, op2_reg: *dwarf_reg);
10077
10078 if (!WriteCoreRegOptionalFlags(context, result: res.result, Rd: dwarf_r0 + d, setflags,
10079 carry: res.carry_out, overflow: res.overflow))
10080 return false;
10081 }
10082 return true;
10083}
10084
10085// A8.6.7 ADD (register-shifted register)
10086bool EmulateInstructionARM::EmulateADDRegShift(const uint32_t opcode,
10087 const ARMEncoding encoding) {
10088#if 0
10089 if ConditionPassed() then
10090 EncodingSpecificOperations();
10091 shift_n = UInt(R[s]<7:0>);
10092 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
10093 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
10094 R[d] = result;
10095 if setflags then
10096 APSR.N = result<31>;
10097 APSR.Z = IsZeroBit(result);
10098 APSR.C = carry;
10099 APSR.V = overflow;
10100#endif
10101
10102 bool success = false;
10103
10104 if (ConditionPassed(opcode)) {
10105 uint32_t d;
10106 uint32_t n;
10107 uint32_t m;
10108 uint32_t s;
10109 bool setflags;
10110 ARM_ShifterType shift_t;
10111
10112 switch (encoding) {
10113 case eEncodingA1:
10114 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); s = UInt(Rs);
10115 d = Bits32(bits: opcode, msbit: 15, lsbit: 12);
10116 n = Bits32(bits: opcode, msbit: 19, lsbit: 16);
10117 m = Bits32(bits: opcode, msbit: 3, lsbit: 0);
10118 s = Bits32(bits: opcode, msbit: 11, lsbit: 8);
10119
10120 // setflags = (S == '1'); shift_t = DecodeRegShift(type);
10121 setflags = BitIsSet(value: opcode, bit: 20);
10122 shift_t = DecodeRegShift(type: Bits32(bits: opcode, msbit: 6, lsbit: 5));
10123
10124 // if d == 15 || n == 15 || m == 15 || s == 15 then UNPREDICTABLE;
10125 if ((d == 15) || (n == 15) || (m == 15) || (s == 15))
10126 return false;
10127 break;
10128
10129 default:
10130 return false;
10131 }
10132
10133 // shift_n = UInt(R[s]<7:0>);
10134 uint32_t Rs = ReadCoreReg(regnum: s, success: &success);
10135 if (!success)
10136 return false;
10137
10138 uint32_t shift_n = Bits32(bits: Rs, msbit: 7, lsbit: 0);
10139
10140 // shifted = Shift(R[m], shift_t, shift_n, APSR.C);
10141 uint32_t Rm = ReadCoreReg(regnum: m, success: &success);
10142 if (!success)
10143 return false;
10144
10145 uint32_t shifted = Shift(value: Rm, type: shift_t, amount: shift_n, APSR_C, success: &success);
10146 if (!success)
10147 return false;
10148
10149 // (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
10150 uint32_t Rn = ReadCoreReg(regnum: n, success: &success);
10151 if (!success)
10152 return false;
10153
10154 AddWithCarryResult res = AddWithCarry(x: Rn, y: shifted, carry_in: 0);
10155
10156 // R[d] = result;
10157 EmulateInstruction::Context context;
10158 context.type = eContextArithmetic;
10159 std::optional<RegisterInfo> reg_n =
10160 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n);
10161 std::optional<RegisterInfo> reg_m =
10162 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + m);
10163
10164 context.SetRegisterRegisterOperands(op1_reg: *reg_n, op2_reg: *reg_m);
10165
10166 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + d,
10167 reg_value: res.result))
10168 return false;
10169
10170 // if setflags then
10171 // APSR.N = result<31>;
10172 // APSR.Z = IsZeroBit(result);
10173 // APSR.C = carry;
10174 // APSR.V = overflow;
10175 if (setflags)
10176 return WriteFlags(context, result: res.result, carry: res.carry_out, overflow: res.overflow);
10177 }
10178 return true;
10179}
10180
10181// A8.6.213 SUB (register)
10182bool EmulateInstructionARM::EmulateSUBReg(const uint32_t opcode,
10183 const ARMEncoding encoding) {
10184#if 0
10185 if ConditionPassed() then
10186 EncodingSpecificOperations();
10187 shifted = Shift(R[m], shift_t, shift_n, APSR.C);
10188 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');
10189 if d == 15 then // Can only occur for ARM encoding
10190 ALUWritePC(result); // setflags is always FALSE here
10191 else
10192 R[d] = result;
10193 if setflags then
10194 APSR.N = result<31>;
10195 APSR.Z = IsZeroBit(result);
10196 APSR.C = carry;
10197 APSR.V = overflow;
10198#endif
10199
10200 bool success = false;
10201
10202 if (ConditionPassed(opcode)) {
10203 uint32_t d;
10204 uint32_t n;
10205 uint32_t m;
10206 bool setflags;
10207 ARM_ShifterType shift_t;
10208 uint32_t shift_n;
10209
10210 switch (encoding) {
10211 case eEncodingT1:
10212 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = !InITBlock();
10213 d = Bits32(bits: opcode, msbit: 2, lsbit: 0);
10214 n = Bits32(bits: opcode, msbit: 5, lsbit: 3);
10215 m = Bits32(bits: opcode, msbit: 8, lsbit: 6);
10216 setflags = !InITBlock();
10217
10218 // (shift_t, shift_n) = (SRType_LSL, 0);
10219 shift_t = SRType_LSL;
10220 shift_n = 0;
10221
10222 break;
10223
10224 case eEncodingT2:
10225 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S =="1");
10226 d = Bits32(bits: opcode, msbit: 11, lsbit: 8);
10227 n = Bits32(bits: opcode, msbit: 19, lsbit: 16);
10228 m = Bits32(bits: opcode, msbit: 3, lsbit: 0);
10229 setflags = BitIsSet(value: opcode, bit: 20);
10230
10231 // if Rd == "1111" && S == "1" then SEE CMP (register);
10232 if (d == 15 && setflags == 1)
10233 return EmulateCMPImm(opcode, encoding: eEncodingT3);
10234
10235 // if Rn == "1101" then SEE SUB (SP minus register);
10236 if (n == 13)
10237 return EmulateSUBSPReg(opcode, encoding: eEncodingT1);
10238
10239 // (shift_t, shift_n) = DecodeImmShift(type, imm3:imm2);
10240 shift_n = DecodeImmShiftThumb(opcode, shift_t);
10241
10242 // if d == 13 || (d == 15 && S == '0') || n == 15 || BadReg(m) then
10243 // UNPREDICTABLE;
10244 if ((d == 13) || ((d == 15) && BitIsClear(value: opcode, bit: 20)) || (n == 15) ||
10245 BadReg(n: m))
10246 return false;
10247
10248 break;
10249
10250 case eEncodingA1:
10251 // if Rn == '1101' then SEE SUB (SP minus register);
10252 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == '1');
10253 d = Bits32(bits: opcode, msbit: 15, lsbit: 12);
10254 n = Bits32(bits: opcode, msbit: 19, lsbit: 16);
10255 m = Bits32(bits: opcode, msbit: 3, lsbit: 0);
10256 setflags = BitIsSet(value: opcode, bit: 20);
10257
10258 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
10259 // instructions;
10260 if ((d == 15) && setflags)
10261 EmulateSUBSPcLrEtc(opcode, encoding);
10262
10263 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
10264 shift_n = DecodeImmShiftARM(opcode, shift_t);
10265
10266 break;
10267
10268 default:
10269 return false;
10270 }
10271
10272 // shifted = Shift(R[m], shift_t, shift_n, APSR.C);
10273 uint32_t Rm = ReadCoreReg(regnum: m, success: &success);
10274 if (!success)
10275 return false;
10276
10277 uint32_t shifted = Shift(value: Rm, type: shift_t, amount: shift_n, APSR_C, success: &success);
10278 if (!success)
10279 return false;
10280
10281 // (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');
10282 uint32_t Rn = ReadCoreReg(regnum: n, success: &success);
10283 if (!success)
10284 return false;
10285
10286 AddWithCarryResult res = AddWithCarry(x: Rn, y: ~shifted, carry_in: 1);
10287
10288 // if d == 15 then // Can only occur for ARM encoding ALUWritePC(result);
10289 // // setflags is always FALSE here else
10290 // R[d] = result;
10291 // if setflags then
10292 // APSR.N = result<31>;
10293 // APSR.Z = IsZeroBit(result);
10294 // APSR.C = carry;
10295 // APSR.V = overflow;
10296
10297 EmulateInstruction::Context context;
10298 context.type = eContextArithmetic;
10299 std::optional<RegisterInfo> reg_n =
10300 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n);
10301 std::optional<RegisterInfo> reg_m =
10302 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + m);
10303 context.SetRegisterRegisterOperands(op1_reg: *reg_n, op2_reg: *reg_m);
10304
10305 if (!WriteCoreRegOptionalFlags(context, result: res.result, Rd: dwarf_r0 + d, setflags,
10306 carry: res.carry_out, overflow: res.overflow))
10307 return false;
10308 }
10309 return true;
10310}
10311
10312// A8.6.202 STREX
10313// Store Register Exclusive calculates an address from a base register value
10314// and an immediate offset, and stores a word from a register to memory if the
10315// executing processor has exclusive access to the memory addressed.
10316bool EmulateInstructionARM::EmulateSTREX(const uint32_t opcode,
10317 const ARMEncoding encoding) {
10318#if 0
10319 if ConditionPassed() then
10320 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
10321 address = R[n] + imm32;
10322 if ExclusiveMonitorsPass(address,4) then
10323 MemA[address,4] = R[t];
10324 R[d] = 0;
10325 else
10326 R[d] = 1;
10327#endif
10328
10329 bool success = false;
10330
10331 if (ConditionPassed(opcode)) {
10332 uint32_t d;
10333 uint32_t t;
10334 uint32_t n;
10335 uint32_t imm32;
10336 const uint32_t addr_byte_size = GetAddressByteSize();
10337
10338 switch (encoding) {
10339 case eEncodingT1:
10340 // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 =
10341 // ZeroExtend(imm8:'00',
10342 // 32);
10343 d = Bits32(bits: opcode, msbit: 11, lsbit: 8);
10344 t = Bits32(bits: opcode, msbit: 15, lsbit: 12);
10345 n = Bits32(bits: opcode, msbit: 19, lsbit: 16);
10346 imm32 = Bits32(bits: opcode, msbit: 7, lsbit: 0) << 2;
10347
10348 // if BadReg(d) || BadReg(t) || n == 15 then UNPREDICTABLE;
10349 if (BadReg(n: d) || BadReg(n: t) || (n == 15))
10350 return false;
10351
10352 // if d == n || d == t then UNPREDICTABLE;
10353 if ((d == n) || (d == t))
10354 return false;
10355
10356 break;
10357
10358 case eEncodingA1:
10359 // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 = Zeros(32); // Zero
10360 // offset
10361 d = Bits32(bits: opcode, msbit: 15, lsbit: 12);
10362 t = Bits32(bits: opcode, msbit: 3, lsbit: 0);
10363 n = Bits32(bits: opcode, msbit: 19, lsbit: 16);
10364 imm32 = 0;
10365
10366 // if d == 15 || t == 15 || n == 15 then UNPREDICTABLE;
10367 if ((d == 15) || (t == 15) || (n == 15))
10368 return false;
10369
10370 // if d == n || d == t then UNPREDICTABLE;
10371 if ((d == n) || (d == t))
10372 return false;
10373
10374 break;
10375
10376 default:
10377 return false;
10378 }
10379
10380 // address = R[n] + imm32;
10381 uint32_t Rn = ReadCoreReg(regnum: n, success: &success);
10382 if (!success)
10383 return false;
10384
10385 addr_t address = Rn + imm32;
10386
10387 std::optional<RegisterInfo> base_reg =
10388 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n);
10389 std::optional<RegisterInfo> data_reg =
10390 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + t);
10391 EmulateInstruction::Context context;
10392 context.type = eContextRegisterStore;
10393 context.SetRegisterToRegisterPlusOffset(data_reg: *data_reg, base_reg: *base_reg, offset: imm32);
10394
10395 // if ExclusiveMonitorsPass(address,4) then if (ExclusiveMonitorsPass
10396 // (address, addr_byte_size)) -- For now, for the sake of emulation, we
10397 // will say this
10398 // always return
10399 // true.
10400 if (true) {
10401 // MemA[address,4] = R[t];
10402 uint32_t Rt =
10403 ReadRegisterUnsigned(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + t, fail_value: 0, success_ptr: &success);
10404 if (!success)
10405 return false;
10406
10407 if (!MemAWrite(context, address, data_val: Rt, size: addr_byte_size))
10408 return false;
10409
10410 // R[d] = 0;
10411 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + t, reg_value: 0))
10412 return false;
10413 }
10414#if 0 // unreachable because if true
10415 else
10416 {
10417 // R[d] = 1;
10418 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, 1))
10419 return false;
10420 }
10421#endif // unreachable because if true
10422 }
10423 return true;
10424}
10425
10426// A8.6.197 STRB (immediate, ARM)
10427bool EmulateInstructionARM::EmulateSTRBImmARM(const uint32_t opcode,
10428 const ARMEncoding encoding) {
10429#if 0
10430 if ConditionPassed() then
10431 EncodingSpecificOperations();
10432 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10433 address = if index then offset_addr else R[n];
10434 MemU[address,1] = R[t]<7:0>;
10435 if wback then R[n] = offset_addr;
10436#endif
10437
10438 bool success = false;
10439
10440 if (ConditionPassed(opcode)) {
10441 uint32_t t;
10442 uint32_t n;
10443 uint32_t imm32;
10444 bool index;
10445 bool add;
10446 bool wback;
10447
10448 switch (encoding) {
10449 case eEncodingA1:
10450 // if P == '0' && W == '1' then SEE STRBT;
10451 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
10452 t = Bits32(bits: opcode, msbit: 15, lsbit: 12);
10453 n = Bits32(bits: opcode, msbit: 19, lsbit: 16);
10454 imm32 = Bits32(bits: opcode, msbit: 11, lsbit: 0);
10455
10456 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
10457 index = BitIsSet(value: opcode, bit: 24);
10458 add = BitIsSet(value: opcode, bit: 23);
10459 wback = BitIsClear(value: opcode, bit: 24) || BitIsSet(value: opcode, bit: 21);
10460
10461 // if t == 15 then UNPREDICTABLE;
10462 if (t == 15)
10463 return false;
10464
10465 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
10466 if (wback && ((n == 15) || (n == t)))
10467 return false;
10468
10469 break;
10470
10471 default:
10472 return false;
10473 }
10474
10475 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10476 uint32_t Rn = ReadCoreReg(regnum: n, success: &success);
10477 if (!success)
10478 return false;
10479
10480 addr_t offset_addr;
10481 if (add)
10482 offset_addr = Rn + imm32;
10483 else
10484 offset_addr = Rn - imm32;
10485
10486 // address = if index then offset_addr else R[n];
10487 addr_t address;
10488 if (index)
10489 address = offset_addr;
10490 else
10491 address = Rn;
10492
10493 // MemU[address,1] = R[t]<7:0>;
10494 uint32_t Rt = ReadCoreReg(regnum: t, success: &success);
10495 if (!success)
10496 return false;
10497
10498 std::optional<RegisterInfo> base_reg =
10499 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n);
10500 std::optional<RegisterInfo> data_reg =
10501 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + t);
10502 EmulateInstruction::Context context;
10503 context.type = eContextRegisterStore;
10504 context.SetRegisterToRegisterPlusOffset(data_reg: *data_reg, base_reg: *base_reg, offset: address - Rn);
10505
10506 if (!MemUWrite(context, address, data_val: Bits32(bits: Rt, msbit: 7, lsbit: 0), size: 1))
10507 return false;
10508
10509 // if wback then R[n] = offset_addr;
10510 if (wback) {
10511 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n,
10512 reg_value: offset_addr))
10513 return false;
10514 }
10515 }
10516 return true;
10517}
10518
10519// A8.6.194 STR (immediate, ARM)
10520bool EmulateInstructionARM::EmulateSTRImmARM(const uint32_t opcode,
10521 const ARMEncoding encoding) {
10522#if 0
10523 if ConditionPassed() then
10524 EncodingSpecificOperations();
10525 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10526 address = if index then offset_addr else R[n];
10527 MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
10528 if wback then R[n] = offset_addr;
10529#endif
10530
10531 bool success = false;
10532
10533 if (ConditionPassed(opcode)) {
10534 uint32_t t;
10535 uint32_t n;
10536 uint32_t imm32;
10537 bool index;
10538 bool add;
10539 bool wback;
10540
10541 const uint32_t addr_byte_size = GetAddressByteSize();
10542
10543 switch (encoding) {
10544 case eEncodingA1:
10545 // if P == '0' && W == '1' then SEE STRT;
10546 // if Rn == '1101' && P == '1' && U == '0' && W == '1' && imm12 ==
10547 // '000000000100' then SEE PUSH;
10548 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
10549 t = Bits32(bits: opcode, msbit: 15, lsbit: 12);
10550 n = Bits32(bits: opcode, msbit: 19, lsbit: 16);
10551 imm32 = Bits32(bits: opcode, msbit: 11, lsbit: 0);
10552
10553 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
10554 index = BitIsSet(value: opcode, bit: 24);
10555 add = BitIsSet(value: opcode, bit: 23);
10556 wback = BitIsClear(value: opcode, bit: 24) || BitIsSet(value: opcode, bit: 21);
10557
10558 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
10559 if (wback && ((n == 15) || (n == t)))
10560 return false;
10561
10562 break;
10563
10564 default:
10565 return false;
10566 }
10567
10568 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10569 uint32_t Rn = ReadCoreReg(regnum: n, success: &success);
10570 if (!success)
10571 return false;
10572
10573 addr_t offset_addr;
10574 if (add)
10575 offset_addr = Rn + imm32;
10576 else
10577 offset_addr = Rn - imm32;
10578
10579 // address = if index then offset_addr else R[n];
10580 addr_t address;
10581 if (index)
10582 address = offset_addr;
10583 else
10584 address = Rn;
10585
10586 std::optional<RegisterInfo> base_reg =
10587 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n);
10588 std::optional<RegisterInfo> data_reg =
10589 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + t);
10590 EmulateInstruction::Context context;
10591 context.type = eContextRegisterStore;
10592 context.SetRegisterToRegisterPlusOffset(data_reg: *data_reg, base_reg: *base_reg, offset: address - Rn);
10593
10594 // MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
10595 uint32_t Rt = ReadCoreReg(regnum: t, success: &success);
10596 if (!success)
10597 return false;
10598
10599 if (t == 15) {
10600 uint32_t pc_value = ReadCoreReg(PC_REG, success: &success);
10601 if (!success)
10602 return false;
10603
10604 if (!MemUWrite(context, address, data_val: pc_value, size: addr_byte_size))
10605 return false;
10606 } else {
10607 if (!MemUWrite(context, address, data_val: Rt, size: addr_byte_size))
10608 return false;
10609 }
10610
10611 // if wback then R[n] = offset_addr;
10612 if (wback) {
10613 context.type = eContextAdjustBaseRegister;
10614 context.SetImmediate(offset_addr);
10615
10616 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n,
10617 reg_value: offset_addr))
10618 return false;
10619 }
10620 }
10621 return true;
10622}
10623
10624// A8.6.66 LDRD (immediate)
10625// Load Register Dual (immediate) calculates an address from a base register
10626// value and an immediate offset, loads two words from memory, and writes them
10627// to two registers. It can use offset, post-indexed, or pre-indexed
10628// addressing.
10629bool EmulateInstructionARM::EmulateLDRDImmediate(const uint32_t opcode,
10630 const ARMEncoding encoding) {
10631#if 0
10632 if ConditionPassed() then
10633 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
10634 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10635 address = if index then offset_addr else R[n];
10636 R[t] = MemA[address,4];
10637 R[t2] = MemA[address+4,4];
10638 if wback then R[n] = offset_addr;
10639#endif
10640
10641 bool success = false;
10642
10643 if (ConditionPassed(opcode)) {
10644 uint32_t t;
10645 uint32_t t2;
10646 uint32_t n;
10647 uint32_t imm32;
10648 bool index;
10649 bool add;
10650 bool wback;
10651
10652 switch (encoding) {
10653 case eEncodingT1:
10654 // if P == '0' && W == '0' then SEE 'Related encodings';
10655 // if Rn == '1111' then SEE LDRD (literal);
10656 // t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 =
10657 // ZeroExtend(imm8:'00', 32);
10658 t = Bits32(bits: opcode, msbit: 15, lsbit: 12);
10659 t2 = Bits32(bits: opcode, msbit: 11, lsbit: 8);
10660 n = Bits32(bits: opcode, msbit: 19, lsbit: 16);
10661 imm32 = Bits32(bits: opcode, msbit: 7, lsbit: 0) << 2;
10662
10663 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
10664 index = BitIsSet(value: opcode, bit: 24);
10665 add = BitIsSet(value: opcode, bit: 23);
10666 wback = BitIsSet(value: opcode, bit: 21);
10667
10668 // if wback && (n == t || n == t2) then UNPREDICTABLE;
10669 if (wback && ((n == t) || (n == t2)))
10670 return false;
10671
10672 // if BadReg(t) || BadReg(t2) || t == t2 then UNPREDICTABLE;
10673 if (BadReg(n: t) || BadReg(n: t2) || (t == t2))
10674 return false;
10675
10676 break;
10677
10678 case eEncodingA1:
10679 // if Rn == '1111' then SEE LDRD (literal);
10680 // if Rt<0> == '1' then UNPREDICTABLE;
10681 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L,
10682 // 32);
10683 t = Bits32(bits: opcode, msbit: 15, lsbit: 12);
10684 if (BitIsSet(value: t, bit: 0))
10685 return false;
10686 t2 = t + 1;
10687 n = Bits32(bits: opcode, msbit: 19, lsbit: 16);
10688 imm32 = (Bits32(bits: opcode, msbit: 11, lsbit: 8) << 4) | Bits32(bits: opcode, msbit: 3, lsbit: 0);
10689
10690 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
10691 index = BitIsSet(value: opcode, bit: 24);
10692 add = BitIsSet(value: opcode, bit: 23);
10693 wback = BitIsClear(value: opcode, bit: 24) || BitIsSet(value: opcode, bit: 21);
10694
10695 // if P == '0' && W == '1' then UNPREDICTABLE;
10696 if (BitIsClear(value: opcode, bit: 24) && BitIsSet(value: opcode, bit: 21))
10697 return false;
10698
10699 // if wback && (n == t || n == t2) then UNPREDICTABLE;
10700 if (wback && ((n == t) || (n == t2)))
10701 return false;
10702
10703 // if t2 == 15 then UNPREDICTABLE;
10704 if (t2 == 15)
10705 return false;
10706
10707 break;
10708
10709 default:
10710 return false;
10711 }
10712
10713 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10714 uint32_t Rn = ReadCoreReg(regnum: n, success: &success);
10715 if (!success)
10716 return false;
10717
10718 addr_t offset_addr;
10719 if (add)
10720 offset_addr = Rn + imm32;
10721 else
10722 offset_addr = Rn - imm32;
10723
10724 // address = if index then offset_addr else R[n];
10725 addr_t address;
10726 if (index)
10727 address = offset_addr;
10728 else
10729 address = Rn;
10730
10731 // R[t] = MemA[address,4];
10732
10733 EmulateInstruction::Context context;
10734 if (n == 13)
10735 context.type = eContextPopRegisterOffStack;
10736 else
10737 context.type = eContextRegisterLoad;
10738 context.SetAddress(address);
10739
10740 const uint32_t addr_byte_size = GetAddressByteSize();
10741 uint32_t data = MemARead(context, address, size: addr_byte_size, fail_value: 0, success_ptr: &success);
10742 if (!success)
10743 return false;
10744
10745 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + t, reg_value: data))
10746 return false;
10747
10748 // R[t2] = MemA[address+4,4];
10749 context.SetAddress(address + 4);
10750 data = MemARead(context, address: address + 4, size: addr_byte_size, fail_value: 0, success_ptr: &success);
10751 if (!success)
10752 return false;
10753
10754 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + t2,
10755 reg_value: data))
10756 return false;
10757
10758 // if wback then R[n] = offset_addr;
10759 if (wback) {
10760 context.type = eContextAdjustBaseRegister;
10761 context.SetAddress(offset_addr);
10762
10763 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n,
10764 reg_value: offset_addr))
10765 return false;
10766 }
10767 }
10768 return true;
10769}
10770
10771// A8.6.68 LDRD (register)
10772// Load Register Dual (register) calculates an address from a base register
10773// value and a register offset, loads two words from memory, and writes them to
10774// two registers. It can use offset, post-indexed or pre-indexed addressing.
10775bool EmulateInstructionARM::EmulateLDRDRegister(const uint32_t opcode,
10776 const ARMEncoding encoding) {
10777#if 0
10778 if ConditionPassed() then
10779 EncodingSpecificOperations();
10780 offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
10781 address = if index then offset_addr else R[n];
10782 R[t] = MemA[address,4];
10783 R[t2] = MemA[address+4,4];
10784 if wback then R[n] = offset_addr;
10785#endif
10786
10787 bool success = false;
10788
10789 if (ConditionPassed(opcode)) {
10790 uint32_t t;
10791 uint32_t t2;
10792 uint32_t n;
10793 uint32_t m;
10794 bool index;
10795 bool add;
10796 bool wback;
10797
10798 switch (encoding) {
10799 case eEncodingA1:
10800 // if Rt<0> == '1' then UNPREDICTABLE;
10801 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); m = UInt(Rm);
10802 t = Bits32(bits: opcode, msbit: 15, lsbit: 12);
10803 if (BitIsSet(value: t, bit: 0))
10804 return false;
10805 t2 = t + 1;
10806 n = Bits32(bits: opcode, msbit: 19, lsbit: 16);
10807 m = Bits32(bits: opcode, msbit: 3, lsbit: 0);
10808
10809 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
10810 index = BitIsSet(value: opcode, bit: 24);
10811 add = BitIsSet(value: opcode, bit: 23);
10812 wback = BitIsClear(value: opcode, bit: 24) || BitIsSet(value: opcode, bit: 21);
10813
10814 // if P == '0' && W == '1' then UNPREDICTABLE;
10815 if (BitIsClear(value: opcode, bit: 24) && BitIsSet(value: opcode, bit: 21))
10816 return false;
10817
10818 // if t2 == 15 || m == 15 || m == t || m == t2 then UNPREDICTABLE;
10819 if ((t2 == 15) || (m == 15) || (m == t) || (m == t2))
10820 return false;
10821
10822 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;
10823 if (wback && ((n == 15) || (n == t) || (n == t2)))
10824 return false;
10825
10826 // if ArchVersion() < 6 && wback && m == n then UNPREDICTABLE;
10827 if ((ArchVersion() < 6) && wback && (m == n))
10828 return false;
10829 break;
10830
10831 default:
10832 return false;
10833 }
10834
10835 uint32_t Rn = ReadCoreReg(regnum: n, success: &success);
10836 if (!success)
10837 return false;
10838
10839 uint32_t Rm = ReadCoreReg(regnum: m, success: &success);
10840 if (!success)
10841 return false;
10842
10843 // offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
10844 addr_t offset_addr;
10845 if (add)
10846 offset_addr = Rn + Rm;
10847 else
10848 offset_addr = Rn - Rm;
10849
10850 // address = if index then offset_addr else R[n];
10851 addr_t address;
10852 if (index)
10853 address = offset_addr;
10854 else
10855 address = Rn;
10856
10857 EmulateInstruction::Context context;
10858 if (n == 13)
10859 context.type = eContextPopRegisterOffStack;
10860 else
10861 context.type = eContextRegisterLoad;
10862 context.SetAddress(address);
10863
10864 // R[t] = MemA[address,4];
10865 const uint32_t addr_byte_size = GetAddressByteSize();
10866 uint32_t data = MemARead(context, address, size: addr_byte_size, fail_value: 0, success_ptr: &success);
10867 if (!success)
10868 return false;
10869
10870 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + t, reg_value: data))
10871 return false;
10872
10873 // R[t2] = MemA[address+4,4];
10874
10875 data = MemARead(context, address: address + 4, size: addr_byte_size, fail_value: 0, success_ptr: &success);
10876 if (!success)
10877 return false;
10878
10879 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + t2,
10880 reg_value: data))
10881 return false;
10882
10883 // if wback then R[n] = offset_addr;
10884 if (wback) {
10885 context.type = eContextAdjustBaseRegister;
10886 context.SetAddress(offset_addr);
10887
10888 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n,
10889 reg_value: offset_addr))
10890 return false;
10891 }
10892 }
10893 return true;
10894}
10895
10896// A8.6.200 STRD (immediate)
10897// Store Register Dual (immediate) calculates an address from a base register
10898// value and an immediate offset, and stores two words from two registers to
10899// memory. It can use offset, post-indexed, or pre-indexed addressing.
10900bool EmulateInstructionARM::EmulateSTRDImm(const uint32_t opcode,
10901 const ARMEncoding encoding) {
10902#if 0
10903 if ConditionPassed() then
10904 EncodingSpecificOperations(); NullCheckIfThumbEE(n);
10905 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10906 address = if index then offset_addr else R[n];
10907 MemA[address,4] = R[t];
10908 MemA[address+4,4] = R[t2];
10909 if wback then R[n] = offset_addr;
10910#endif
10911
10912 bool success = false;
10913
10914 if (ConditionPassed(opcode)) {
10915 uint32_t t;
10916 uint32_t t2;
10917 uint32_t n;
10918 uint32_t imm32;
10919 bool index;
10920 bool add;
10921 bool wback;
10922
10923 switch (encoding) {
10924 case eEncodingT1:
10925 // if P == '0' && W == '0' then SEE 'Related encodings';
10926 // t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 =
10927 // ZeroExtend(imm8:'00', 32);
10928 t = Bits32(bits: opcode, msbit: 15, lsbit: 12);
10929 t2 = Bits32(bits: opcode, msbit: 11, lsbit: 8);
10930 n = Bits32(bits: opcode, msbit: 19, lsbit: 16);
10931 imm32 = Bits32(bits: opcode, msbit: 7, lsbit: 0) << 2;
10932
10933 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
10934 index = BitIsSet(value: opcode, bit: 24);
10935 add = BitIsSet(value: opcode, bit: 23);
10936 wback = BitIsSet(value: opcode, bit: 21);
10937
10938 // if wback && (n == t || n == t2) then UNPREDICTABLE;
10939 if (wback && ((n == t) || (n == t2)))
10940 return false;
10941
10942 // if n == 15 || BadReg(t) || BadReg(t2) then UNPREDICTABLE;
10943 if ((n == 15) || BadReg(n: t) || BadReg(n: t2))
10944 return false;
10945
10946 break;
10947
10948 case eEncodingA1:
10949 // if Rt<0> == '1' then UNPREDICTABLE;
10950 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L,
10951 // 32);
10952 t = Bits32(bits: opcode, msbit: 15, lsbit: 12);
10953 if (BitIsSet(value: t, bit: 0))
10954 return false;
10955
10956 t2 = t + 1;
10957 n = Bits32(bits: opcode, msbit: 19, lsbit: 16);
10958 imm32 = (Bits32(bits: opcode, msbit: 11, lsbit: 8) << 4) | Bits32(bits: opcode, msbit: 3, lsbit: 0);
10959
10960 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
10961 index = BitIsSet(value: opcode, bit: 24);
10962 add = BitIsSet(value: opcode, bit: 23);
10963 wback = BitIsClear(value: opcode, bit: 24) || BitIsSet(value: opcode, bit: 21);
10964
10965 // if P == '0' && W == '1' then UNPREDICTABLE;
10966 if (BitIsClear(value: opcode, bit: 24) && BitIsSet(value: opcode, bit: 21))
10967 return false;
10968
10969 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;
10970 if (wback && ((n == 15) || (n == t) || (n == t2)))
10971 return false;
10972
10973 // if t2 == 15 then UNPREDICTABLE;
10974 if (t2 == 15)
10975 return false;
10976
10977 break;
10978
10979 default:
10980 return false;
10981 }
10982
10983 std::optional<RegisterInfo> base_reg =
10984 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n);
10985
10986 uint32_t Rn = ReadCoreReg(regnum: n, success: &success);
10987 if (!success)
10988 return false;
10989
10990 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10991 addr_t offset_addr;
10992 if (add)
10993 offset_addr = Rn + imm32;
10994 else
10995 offset_addr = Rn - imm32;
10996
10997 // address = if index then offset_addr else R[n];
10998 addr_t address;
10999 if (index)
11000 address = offset_addr;
11001 else
11002 address = Rn;
11003
11004 // MemA[address,4] = R[t];
11005 std::optional<RegisterInfo> data_reg =
11006 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + t);
11007
11008 uint32_t data = ReadCoreReg(regnum: t, success: &success);
11009 if (!success)
11010 return false;
11011
11012 EmulateInstruction::Context context;
11013 if (n == 13)
11014 context.type = eContextPushRegisterOnStack;
11015 else
11016 context.type = eContextRegisterStore;
11017 context.SetRegisterToRegisterPlusOffset(data_reg: *data_reg, base_reg: *base_reg, offset: address - Rn);
11018
11019 const uint32_t addr_byte_size = GetAddressByteSize();
11020
11021 if (!MemAWrite(context, address, data_val: data, size: addr_byte_size))
11022 return false;
11023
11024 // MemA[address+4,4] = R[t2];
11025 data_reg = GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + t2);
11026 context.SetRegisterToRegisterPlusOffset(data_reg: *data_reg, base_reg: *base_reg,
11027 offset: (address + 4) - Rn);
11028
11029 data = ReadCoreReg(regnum: t2, success: &success);
11030 if (!success)
11031 return false;
11032
11033 if (!MemAWrite(context, address: address + 4, data_val: data, size: addr_byte_size))
11034 return false;
11035
11036 // if wback then R[n] = offset_addr;
11037 if (wback) {
11038 if (n == 13)
11039 context.type = eContextAdjustStackPointer;
11040 else
11041 context.type = eContextAdjustBaseRegister;
11042 context.SetAddress(offset_addr);
11043
11044 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n,
11045 reg_value: offset_addr))
11046 return false;
11047 }
11048 }
11049 return true;
11050}
11051
11052// A8.6.201 STRD (register)
11053bool EmulateInstructionARM::EmulateSTRDReg(const uint32_t opcode,
11054 const ARMEncoding encoding) {
11055#if 0
11056 if ConditionPassed() then
11057 EncodingSpecificOperations();
11058 offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
11059 address = if index then offset_addr else R[n];
11060 MemA[address,4] = R[t];
11061 MemA[address+4,4] = R[t2];
11062 if wback then R[n] = offset_addr;
11063#endif
11064
11065 bool success = false;
11066
11067 if (ConditionPassed(opcode)) {
11068 uint32_t t;
11069 uint32_t t2;
11070 uint32_t n;
11071 uint32_t m;
11072 bool index;
11073 bool add;
11074 bool wback;
11075
11076 switch (encoding) {
11077 case eEncodingA1:
11078 // if Rt<0> == '1' then UNPREDICTABLE;
11079 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); m = UInt(Rm);
11080 t = Bits32(bits: opcode, msbit: 15, lsbit: 12);
11081 if (BitIsSet(value: t, bit: 0))
11082 return false;
11083
11084 t2 = t + 1;
11085 n = Bits32(bits: opcode, msbit: 19, lsbit: 16);
11086 m = Bits32(bits: opcode, msbit: 3, lsbit: 0);
11087
11088 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
11089 index = BitIsSet(value: opcode, bit: 24);
11090 add = BitIsSet(value: opcode, bit: 23);
11091 wback = BitIsClear(value: opcode, bit: 24) || BitIsSet(value: opcode, bit: 21);
11092
11093 // if P == '0' && W == '1' then UNPREDICTABLE;
11094 if (BitIsClear(value: opcode, bit: 24) && BitIsSet(value: opcode, bit: 21))
11095 return false;
11096
11097 // if t2 == 15 || m == 15 then UNPREDICTABLE;
11098 if ((t2 == 15) || (m == 15))
11099 return false;
11100
11101 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;
11102 if (wback && ((n == 15) || (n == t) || (n == t2)))
11103 return false;
11104
11105 // if ArchVersion() < 6 && wback && m == n then UNPREDICTABLE;
11106 if ((ArchVersion() < 6) && wback && (m == n))
11107 return false;
11108
11109 break;
11110
11111 default:
11112 return false;
11113 }
11114
11115 uint32_t Rn = ReadCoreReg(regnum: n, success: &success);
11116 if (!success)
11117 return false;
11118
11119 uint32_t Rm = ReadCoreReg(regnum: m, success: &success);
11120 if (!success)
11121 return false;
11122
11123 // offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
11124 addr_t offset_addr;
11125 if (add)
11126 offset_addr = Rn + Rm;
11127 else
11128 offset_addr = Rn - Rm;
11129
11130 // address = if index then offset_addr else R[n];
11131 addr_t address;
11132 if (index)
11133 address = offset_addr;
11134 else
11135 address = Rn;
11136 // MemA[address,4] = R[t];
11137 uint32_t Rt = ReadCoreReg(regnum: t, success: &success);
11138 if (!success)
11139 return false;
11140
11141 EmulateInstruction::Context context;
11142 if (t == 13)
11143 context.type = eContextPushRegisterOnStack;
11144 else
11145 context.type = eContextRegisterStore;
11146
11147 std::optional<RegisterInfo> base_reg =
11148 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n);
11149 std::optional<RegisterInfo> offset_reg =
11150 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + m);
11151 std::optional<RegisterInfo> data_reg =
11152 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + t);
11153 context.SetRegisterToRegisterPlusIndirectOffset(base_reg: *base_reg, offset_reg: *offset_reg,
11154 data_reg: *data_reg);
11155
11156 const uint32_t addr_byte_size = GetAddressByteSize();
11157
11158 if (!MemAWrite(context, address, data_val: Rt, size: addr_byte_size))
11159 return false;
11160
11161 // MemA[address+4,4] = R[t2];
11162 uint32_t Rt2 = ReadCoreReg(regnum: t2, success: &success);
11163 if (!success)
11164 return false;
11165
11166 data_reg = GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + t2);
11167
11168 context.SetRegisterToRegisterPlusIndirectOffset(base_reg: *base_reg, offset_reg: *offset_reg,
11169 data_reg: *data_reg);
11170
11171 if (!MemAWrite(context, address: address + 4, data_val: Rt2, size: addr_byte_size))
11172 return false;
11173
11174 // if wback then R[n] = offset_addr;
11175 if (wback) {
11176 context.type = eContextAdjustBaseRegister;
11177 context.SetAddress(offset_addr);
11178
11179 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n,
11180 reg_value: offset_addr))
11181 return false;
11182 }
11183 }
11184 return true;
11185}
11186
11187// A8.6.319 VLDM
11188// Vector Load Multiple loads multiple extension registers from consecutive
11189// memory locations using an address from an ARM core register.
11190bool EmulateInstructionARM::EmulateVLDM(const uint32_t opcode,
11191 const ARMEncoding encoding) {
11192#if 0
11193 if ConditionPassed() then
11194 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
11195 address = if add then R[n] else R[n]-imm32;
11196 if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;
11197 for r = 0 to regs-1
11198 if single_regs then
11199 S[d+r] = MemA[address,4]; address = address+4;
11200 else
11201 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
11202 // Combine the word-aligned words in the correct order for
11203 // current endianness.
11204 D[d+r] = if BigEndian() then word1:word2 else word2:word1;
11205#endif
11206
11207 bool success = false;
11208
11209 if (ConditionPassed(opcode)) {
11210 bool single_regs;
11211 bool add;
11212 bool wback;
11213 uint32_t d;
11214 uint32_t n;
11215 uint32_t imm32;
11216 uint32_t regs;
11217
11218 switch (encoding) {
11219 case eEncodingT1:
11220 case eEncodingA1:
11221 // if P == '0' && U == '0' && W == '0' then SEE 'Related encodings';
11222 // if P == '0' && U == '1' && W == '1' && Rn == '1101' then SEE VPOP;
11223 // if P == '1' && W == '0' then SEE VLDR;
11224 // if P == U && W == '1' then UNDEFINED;
11225 if ((Bit32(bits: opcode, bit: 24) == Bit32(bits: opcode, bit: 23)) && BitIsSet(value: opcode, bit: 21))
11226 return false;
11227
11228 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with
11229 // !), 101 (DB with !)
11230 // single_regs = FALSE; add = (U == '1'); wback = (W == '1');
11231 single_regs = false;
11232 add = BitIsSet(value: opcode, bit: 23);
11233 wback = BitIsSet(value: opcode, bit: 21);
11234
11235 // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:'00', 32);
11236 d = (Bit32(bits: opcode, bit: 22) << 4) | Bits32(bits: opcode, msbit: 15, lsbit: 12);
11237 n = Bits32(bits: opcode, msbit: 19, lsbit: 16);
11238 imm32 = Bits32(bits: opcode, msbit: 7, lsbit: 0) << 2;
11239
11240 // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see 'FLDMX'.
11241 regs = Bits32(bits: opcode, msbit: 7, lsbit: 0) / 2;
11242
11243 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then
11244 // UNPREDICTABLE;
11245 if (n == 15 && (wback || CurrentInstrSet() != eModeARM))
11246 return false;
11247
11248 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
11249 if ((regs == 0) || (regs > 16) || ((d + regs) > 32))
11250 return false;
11251
11252 break;
11253
11254 case eEncodingT2:
11255 case eEncodingA2:
11256 // if P == '0' && U == '0' && W == '0' then SEE 'Related encodings';
11257 // if P == '0' && U == '1' && W == '1' && Rn == '1101' then SEE VPOP;
11258 // if P == '1' && W == '0' then SEE VLDR;
11259 // if P == U && W == '1' then UNDEFINED;
11260 if ((Bit32(bits: opcode, bit: 24) == Bit32(bits: opcode, bit: 23)) && BitIsSet(value: opcode, bit: 21))
11261 return false;
11262
11263 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with
11264 // !), 101 (DB with !) single_regs = TRUE; add = (U == '1'); wback = (W
11265 // == '1'); d =
11266 // UInt(Vd:D); n = UInt(Rn);
11267 single_regs = true;
11268 add = BitIsSet(value: opcode, bit: 23);
11269 wback = BitIsSet(value: opcode, bit: 21);
11270 d = (Bits32(bits: opcode, msbit: 15, lsbit: 12) << 1) | Bit32(bits: opcode, bit: 22);
11271 n = Bits32(bits: opcode, msbit: 19, lsbit: 16);
11272
11273 // imm32 = ZeroExtend(imm8:'00', 32); regs = UInt(imm8);
11274 imm32 = Bits32(bits: opcode, msbit: 7, lsbit: 0) << 2;
11275 regs = Bits32(bits: opcode, msbit: 7, lsbit: 0);
11276
11277 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then
11278 // UNPREDICTABLE;
11279 if ((n == 15) && (wback || (CurrentInstrSet() != eModeARM)))
11280 return false;
11281
11282 // if regs == 0 || (d+regs) > 32 then UNPREDICTABLE;
11283 if ((regs == 0) || ((d + regs) > 32))
11284 return false;
11285 break;
11286
11287 default:
11288 return false;
11289 }
11290
11291 uint32_t Rn = ReadCoreReg(regnum: n, success: &success);
11292 if (!success)
11293 return false;
11294
11295 // address = if add then R[n] else R[n]-imm32;
11296 addr_t address;
11297 if (add)
11298 address = Rn;
11299 else
11300 address = Rn - imm32;
11301
11302 // if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;
11303 EmulateInstruction::Context context;
11304
11305 if (wback) {
11306 uint32_t value;
11307 if (add)
11308 value = Rn + imm32;
11309 else
11310 value = Rn - imm32;
11311
11312 context.type = eContextAdjustBaseRegister;
11313 context.SetImmediateSigned(value - Rn);
11314 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n,
11315 reg_value: value))
11316 return false;
11317 }
11318
11319 const uint32_t addr_byte_size = GetAddressByteSize();
11320 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
11321
11322 context.type = eContextRegisterLoad;
11323
11324 std::optional<RegisterInfo> base_reg =
11325 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n);
11326
11327 // for r = 0 to regs-1
11328 for (uint32_t r = 0; r < regs; ++r) {
11329 if (single_regs) {
11330 // S[d+r] = MemA[address,4]; address = address+4;
11331 context.SetRegisterPlusOffset(base_reg: *base_reg, signed_offset: address - Rn);
11332
11333 uint32_t data = MemARead(context, address, size: addr_byte_size, fail_value: 0, success_ptr: &success);
11334 if (!success)
11335 return false;
11336
11337 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindDWARF,
11338 reg_num: start_reg + d + r, reg_value: data))
11339 return false;
11340
11341 address = address + 4;
11342 } else {
11343 // word1 = MemA[address,4]; word2 = MemA[address+4,4]; address =
11344 // address+8;
11345 context.SetRegisterPlusOffset(base_reg: *base_reg, signed_offset: address - Rn);
11346 uint32_t word1 =
11347 MemARead(context, address, size: addr_byte_size, fail_value: 0, success_ptr: &success);
11348 if (!success)
11349 return false;
11350
11351 context.SetRegisterPlusOffset(base_reg: *base_reg, signed_offset: (address + 4) - Rn);
11352 uint32_t word2 =
11353 MemARead(context, address: address + 4, size: addr_byte_size, fail_value: 0, success_ptr: &success);
11354 if (!success)
11355 return false;
11356
11357 address = address + 8;
11358 // // Combine the word-aligned words in the correct order for current
11359 // endianness.
11360 // D[d+r] = if BigEndian() then word1:word2 else word2:word1;
11361 uint64_t data;
11362 if (GetByteOrder() == eByteOrderBig) {
11363 data = word1;
11364 data = (data << 32) | word2;
11365 } else {
11366 data = word2;
11367 data = (data << 32) | word1;
11368 }
11369
11370 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindDWARF,
11371 reg_num: start_reg + d + r, reg_value: data))
11372 return false;
11373 }
11374 }
11375 }
11376 return true;
11377}
11378
11379// A8.6.399 VSTM
11380// Vector Store Multiple stores multiple extension registers to consecutive
11381// memory locations using an address from an
11382// ARM core register.
11383bool EmulateInstructionARM::EmulateVSTM(const uint32_t opcode,
11384 const ARMEncoding encoding) {
11385#if 0
11386 if ConditionPassed() then
11387 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
11388 address = if add then R[n] else R[n]-imm32;
11389 if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;
11390 for r = 0 to regs-1
11391 if single_regs then
11392 MemA[address,4] = S[d+r]; address = address+4;
11393 else
11394 // Store as two word-aligned words in the correct order for
11395 // current endianness.
11396 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
11397 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
11398 address = address+8;
11399#endif
11400
11401 bool success = false;
11402
11403 if (ConditionPassed(opcode)) {
11404 bool single_regs;
11405 bool add;
11406 bool wback;
11407 uint32_t d;
11408 uint32_t n;
11409 uint32_t imm32;
11410 uint32_t regs;
11411
11412 switch (encoding) {
11413 case eEncodingT1:
11414 case eEncodingA1:
11415 // if P == '0' && U == '0' && W == '0' then SEE 'Related encodings';
11416 // if P == '1' && U == '0' && W == '1' && Rn == '1101' then SEE VPUSH;
11417 // if P == '1' && W == '0' then SEE VSTR;
11418 // if P == U && W == '1' then UNDEFINED;
11419 if ((Bit32(bits: opcode, bit: 24) == Bit32(bits: opcode, bit: 23)) && BitIsSet(value: opcode, bit: 21))
11420 return false;
11421
11422 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with
11423 // !), 101 (DB with !)
11424 // single_regs = FALSE; add = (U == '1'); wback = (W == '1');
11425 single_regs = false;
11426 add = BitIsSet(value: opcode, bit: 23);
11427 wback = BitIsSet(value: opcode, bit: 21);
11428
11429 // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:'00', 32);
11430 d = (Bit32(bits: opcode, bit: 22) << 4) | Bits32(bits: opcode, msbit: 15, lsbit: 12);
11431 n = Bits32(bits: opcode, msbit: 19, lsbit: 16);
11432 imm32 = Bits32(bits: opcode, msbit: 7, lsbit: 0) << 2;
11433
11434 // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see 'FSTMX'.
11435 regs = Bits32(bits: opcode, msbit: 7, lsbit: 0) / 2;
11436
11437 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then
11438 // UNPREDICTABLE;
11439 if ((n == 15) && (wback || (CurrentInstrSet() != eModeARM)))
11440 return false;
11441
11442 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
11443 if ((regs == 0) || (regs > 16) || ((d + regs) > 32))
11444 return false;
11445
11446 break;
11447
11448 case eEncodingT2:
11449 case eEncodingA2:
11450 // if P == '0' && U == '0' && W == '0' then SEE 'Related encodings';
11451 // if P == '1' && U == '0' && W == '1' && Rn == '1101' then SEE VPUSH;
11452 // if P == '1' && W == '0' then SEE VSTR;
11453 // if P == U && W == '1' then UNDEFINED;
11454 if ((Bit32(bits: opcode, bit: 24) == Bit32(bits: opcode, bit: 23)) && BitIsSet(value: opcode, bit: 21))
11455 return false;
11456
11457 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with
11458 // !), 101 (DB with !) single_regs = TRUE; add = (U == '1'); wback = (W
11459 // == '1'); d =
11460 // UInt(Vd:D); n = UInt(Rn);
11461 single_regs = true;
11462 add = BitIsSet(value: opcode, bit: 23);
11463 wback = BitIsSet(value: opcode, bit: 21);
11464 d = (Bits32(bits: opcode, msbit: 15, lsbit: 12) << 1) | Bit32(bits: opcode, bit: 22);
11465 n = Bits32(bits: opcode, msbit: 19, lsbit: 16);
11466
11467 // imm32 = ZeroExtend(imm8:'00', 32); regs = UInt(imm8);
11468 imm32 = Bits32(bits: opcode, msbit: 7, lsbit: 0) << 2;
11469 regs = Bits32(bits: opcode, msbit: 7, lsbit: 0);
11470
11471 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then
11472 // UNPREDICTABLE;
11473 if ((n == 15) && (wback || (CurrentInstrSet() != eModeARM)))
11474 return false;
11475
11476 // if regs == 0 || (d+regs) > 32 then UNPREDICTABLE;
11477 if ((regs == 0) || ((d + regs) > 32))
11478 return false;
11479
11480 break;
11481
11482 default:
11483 return false;
11484 }
11485
11486 std::optional<RegisterInfo> base_reg =
11487 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n);
11488
11489 uint32_t Rn = ReadCoreReg(regnum: n, success: &success);
11490 if (!success)
11491 return false;
11492
11493 // address = if add then R[n] else R[n]-imm32;
11494 addr_t address;
11495 if (add)
11496 address = Rn;
11497 else
11498 address = Rn - imm32;
11499
11500 EmulateInstruction::Context context;
11501 // if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;
11502 if (wback) {
11503 uint32_t value;
11504 if (add)
11505 value = Rn + imm32;
11506 else
11507 value = Rn - imm32;
11508
11509 context.type = eContextAdjustBaseRegister;
11510 context.SetRegisterPlusOffset(base_reg: *base_reg, signed_offset: value - Rn);
11511
11512 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n,
11513 reg_value: value))
11514 return false;
11515 }
11516
11517 const uint32_t addr_byte_size = GetAddressByteSize();
11518 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
11519
11520 context.type = eContextRegisterStore;
11521 // for r = 0 to regs-1
11522 for (uint32_t r = 0; r < regs; ++r) {
11523
11524 if (single_regs) {
11525 // MemA[address,4] = S[d+r]; address = address+4;
11526 uint32_t data = ReadRegisterUnsigned(reg_kind: eRegisterKindDWARF,
11527 reg_num: start_reg + d + r, fail_value: 0, success_ptr: &success);
11528 if (!success)
11529 return false;
11530
11531 std::optional<RegisterInfo> data_reg =
11532 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: start_reg + d + r);
11533 context.SetRegisterToRegisterPlusOffset(data_reg: *data_reg, base_reg: *base_reg,
11534 offset: address - Rn);
11535 if (!MemAWrite(context, address, data_val: data, size: addr_byte_size))
11536 return false;
11537
11538 address = address + 4;
11539 } else {
11540 // // Store as two word-aligned words in the correct order for current
11541 // endianness. MemA[address,4] = if BigEndian() then D[d+r]<63:32> else
11542 // D[d+r]<31:0>;
11543 // MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else
11544 // D[d+r]<63:32>;
11545 uint64_t data = ReadRegisterUnsigned(reg_kind: eRegisterKindDWARF,
11546 reg_num: start_reg + d + r, fail_value: 0, success_ptr: &success);
11547 if (!success)
11548 return false;
11549
11550 std::optional<RegisterInfo> data_reg =
11551 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: start_reg + d + r);
11552
11553 if (GetByteOrder() == eByteOrderBig) {
11554 context.SetRegisterToRegisterPlusOffset(data_reg: *data_reg, base_reg: *base_reg,
11555 offset: address - Rn);
11556 if (!MemAWrite(context, address, data_val: Bits64(bits: data, msbit: 63, lsbit: 32),
11557 size: addr_byte_size))
11558 return false;
11559
11560 context.SetRegisterToRegisterPlusOffset(data_reg: *data_reg, base_reg: *base_reg,
11561 offset: (address + 4) - Rn);
11562 if (!MemAWrite(context, address: address + 4, data_val: Bits64(bits: data, msbit: 31, lsbit: 0),
11563 size: addr_byte_size))
11564 return false;
11565 } else {
11566 context.SetRegisterToRegisterPlusOffset(data_reg: *data_reg, base_reg: *base_reg,
11567 offset: address - Rn);
11568 if (!MemAWrite(context, address, data_val: Bits64(bits: data, msbit: 31, lsbit: 0), size: addr_byte_size))
11569 return false;
11570
11571 context.SetRegisterToRegisterPlusOffset(data_reg: *data_reg, base_reg: *base_reg,
11572 offset: (address + 4) - Rn);
11573 if (!MemAWrite(context, address: address + 4, data_val: Bits64(bits: data, msbit: 63, lsbit: 32),
11574 size: addr_byte_size))
11575 return false;
11576 }
11577 // address = address+8;
11578 address = address + 8;
11579 }
11580 }
11581 }
11582 return true;
11583}
11584
11585// A8.6.320
11586// This instruction loads a single extension register from memory, using an
11587// address from an ARM core register, with an optional offset.
11588bool EmulateInstructionARM::EmulateVLDR(const uint32_t opcode,
11589 ARMEncoding encoding) {
11590#if 0
11591 if ConditionPassed() then
11592 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
11593 base = if n == 15 then Align(PC,4) else R[n];
11594 address = if add then (base + imm32) else (base - imm32);
11595 if single_reg then
11596 S[d] = MemA[address,4];
11597 else
11598 word1 = MemA[address,4]; word2 = MemA[address+4,4];
11599 // Combine the word-aligned words in the correct order for current
11600 // endianness.
11601 D[d] = if BigEndian() then word1:word2 else word2:word1;
11602#endif
11603
11604 bool success = false;
11605
11606 if (ConditionPassed(opcode)) {
11607 bool single_reg;
11608 bool add;
11609 uint32_t imm32;
11610 uint32_t d;
11611 uint32_t n;
11612
11613 switch (encoding) {
11614 case eEncodingT1:
11615 case eEncodingA1:
11616 // single_reg = FALSE; add = (U == '1'); imm32 = ZeroExtend(imm8:'00',
11617 // 32);
11618 single_reg = false;
11619 add = BitIsSet(value: opcode, bit: 23);
11620 imm32 = Bits32(bits: opcode, msbit: 7, lsbit: 0) << 2;
11621
11622 // d = UInt(D:Vd); n = UInt(Rn);
11623 d = (Bit32(bits: opcode, bit: 22) << 4) | Bits32(bits: opcode, msbit: 15, lsbit: 12);
11624 n = Bits32(bits: opcode, msbit: 19, lsbit: 16);
11625
11626 break;
11627
11628 case eEncodingT2:
11629 case eEncodingA2:
11630 // single_reg = TRUE; add = (U == '1'); imm32 = ZeroExtend(imm8:'00', 32);
11631 single_reg = true;
11632 add = BitIsSet(value: opcode, bit: 23);
11633 imm32 = Bits32(bits: opcode, msbit: 7, lsbit: 0) << 2;
11634
11635 // d = UInt(Vd:D); n = UInt(Rn);
11636 d = (Bits32(bits: opcode, msbit: 15, lsbit: 12) << 1) | Bit32(bits: opcode, bit: 22);
11637 n = Bits32(bits: opcode, msbit: 19, lsbit: 16);
11638
11639 break;
11640
11641 default:
11642 return false;
11643 }
11644 std::optional<RegisterInfo> base_reg =
11645 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n);
11646
11647 uint32_t Rn = ReadCoreReg(regnum: n, success: &success);
11648 if (!success)
11649 return false;
11650
11651 // base = if n == 15 then Align(PC,4) else R[n];
11652 uint32_t base;
11653 if (n == 15)
11654 base = AlignPC(Rn);
11655 else
11656 base = Rn;
11657
11658 // address = if add then (base + imm32) else (base - imm32);
11659 addr_t address;
11660 if (add)
11661 address = base + imm32;
11662 else
11663 address = base - imm32;
11664
11665 const uint32_t addr_byte_size = GetAddressByteSize();
11666 uint32_t start_reg = single_reg ? dwarf_s0 : dwarf_d0;
11667
11668 EmulateInstruction::Context context;
11669 context.type = eContextRegisterLoad;
11670 context.SetRegisterPlusOffset(base_reg: *base_reg, signed_offset: address - base);
11671
11672 if (single_reg) {
11673 // S[d] = MemA[address,4];
11674 uint32_t data = MemARead(context, address, size: addr_byte_size, fail_value: 0, success_ptr: &success);
11675 if (!success)
11676 return false;
11677
11678 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindDWARF, reg_num: start_reg + d,
11679 reg_value: data))
11680 return false;
11681 } else {
11682 // word1 = MemA[address,4]; word2 = MemA[address+4,4];
11683 uint32_t word1 = MemARead(context, address, size: addr_byte_size, fail_value: 0, success_ptr: &success);
11684 if (!success)
11685 return false;
11686
11687 context.SetRegisterPlusOffset(base_reg: *base_reg, signed_offset: (address + 4) - base);
11688 uint32_t word2 =
11689 MemARead(context, address: address + 4, size: addr_byte_size, fail_value: 0, success_ptr: &success);
11690 if (!success)
11691 return false;
11692 // // Combine the word-aligned words in the correct order for current
11693 // endianness.
11694 // D[d] = if BigEndian() then word1:word2 else word2:word1;
11695 uint64_t data64;
11696 if (GetByteOrder() == eByteOrderBig) {
11697 data64 = word1;
11698 data64 = (data64 << 32) | word2;
11699 } else {
11700 data64 = word2;
11701 data64 = (data64 << 32) | word1;
11702 }
11703
11704 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindDWARF, reg_num: start_reg + d,
11705 reg_value: data64))
11706 return false;
11707 }
11708 }
11709 return true;
11710}
11711
11712// A8.6.400 VSTR
11713// This instruction stores a signle extension register to memory, using an
11714// address from an ARM core register, with an optional offset.
11715bool EmulateInstructionARM::EmulateVSTR(const uint32_t opcode,
11716 ARMEncoding encoding) {
11717#if 0
11718 if ConditionPassed() then
11719 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
11720 address = if add then (R[n] + imm32) else (R[n] - imm32);
11721 if single_reg then
11722 MemA[address,4] = S[d];
11723 else
11724 // Store as two word-aligned words in the correct order for current
11725 // endianness.
11726 MemA[address,4] = if BigEndian() then D[d]<63:32> else D[d]<31:0>;
11727 MemA[address+4,4] = if BigEndian() then D[d]<31:0> else D[d]<63:32>;
11728#endif
11729
11730 bool success = false;
11731
11732 if (ConditionPassed(opcode)) {
11733 bool single_reg;
11734 bool add;
11735 uint32_t imm32;
11736 uint32_t d;
11737 uint32_t n;
11738
11739 switch (encoding) {
11740 case eEncodingT1:
11741 case eEncodingA1:
11742 // single_reg = FALSE; add = (U == '1'); imm32 = ZeroExtend(imm8:'00',
11743 // 32);
11744 single_reg = false;
11745 add = BitIsSet(value: opcode, bit: 23);
11746 imm32 = Bits32(bits: opcode, msbit: 7, lsbit: 0) << 2;
11747
11748 // d = UInt(D:Vd); n = UInt(Rn);
11749 d = (Bit32(bits: opcode, bit: 22) << 4) | Bits32(bits: opcode, msbit: 15, lsbit: 12);
11750 n = Bits32(bits: opcode, msbit: 19, lsbit: 16);
11751
11752 // if n == 15 && CurrentInstrSet() != InstrSet_ARM then UNPREDICTABLE;
11753 if ((n == 15) && (CurrentInstrSet() != eModeARM))
11754 return false;
11755
11756 break;
11757
11758 case eEncodingT2:
11759 case eEncodingA2:
11760 // single_reg = TRUE; add = (U == '1'); imm32 = ZeroExtend(imm8:'00', 32);
11761 single_reg = true;
11762 add = BitIsSet(value: opcode, bit: 23);
11763 imm32 = Bits32(bits: opcode, msbit: 7, lsbit: 0) << 2;
11764
11765 // d = UInt(Vd:D); n = UInt(Rn);
11766 d = (Bits32(bits: opcode, msbit: 15, lsbit: 12) << 1) | Bit32(bits: opcode, bit: 22);
11767 n = Bits32(bits: opcode, msbit: 19, lsbit: 16);
11768
11769 // if n == 15 && CurrentInstrSet() != InstrSet_ARM then UNPREDICTABLE;
11770 if ((n == 15) && (CurrentInstrSet() != eModeARM))
11771 return false;
11772
11773 break;
11774
11775 default:
11776 return false;
11777 }
11778
11779 uint32_t Rn = ReadCoreReg(regnum: n, success: &success);
11780 if (!success)
11781 return false;
11782
11783 // address = if add then (R[n] + imm32) else (R[n] - imm32);
11784 addr_t address;
11785 if (add)
11786 address = Rn + imm32;
11787 else
11788 address = Rn - imm32;
11789
11790 const uint32_t addr_byte_size = GetAddressByteSize();
11791 uint32_t start_reg = single_reg ? dwarf_s0 : dwarf_d0;
11792
11793 std::optional<RegisterInfo> base_reg =
11794 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n);
11795 std::optional<RegisterInfo> data_reg =
11796 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: start_reg + d);
11797 EmulateInstruction::Context context;
11798 context.type = eContextRegisterStore;
11799 context.SetRegisterToRegisterPlusOffset(data_reg: *data_reg, base_reg: *base_reg, offset: address - Rn);
11800
11801 if (single_reg) {
11802 // MemA[address,4] = S[d];
11803 uint32_t data =
11804 ReadRegisterUnsigned(reg_kind: eRegisterKindDWARF, reg_num: start_reg + d, fail_value: 0, success_ptr: &success);
11805 if (!success)
11806 return false;
11807
11808 if (!MemAWrite(context, address, data_val: data, size: addr_byte_size))
11809 return false;
11810 } else {
11811 // // Store as two word-aligned words in the correct order for current
11812 // endianness.
11813 // MemA[address,4] = if BigEndian() then D[d]<63:32> else D[d]<31:0>;
11814 // MemA[address+4,4] = if BigEndian() then D[d]<31:0> else D[d]<63:32>;
11815 uint64_t data =
11816 ReadRegisterUnsigned(reg_kind: eRegisterKindDWARF, reg_num: start_reg + d, fail_value: 0, success_ptr: &success);
11817 if (!success)
11818 return false;
11819
11820 if (GetByteOrder() == eByteOrderBig) {
11821 if (!MemAWrite(context, address, data_val: Bits64(bits: data, msbit: 63, lsbit: 32), size: addr_byte_size))
11822 return false;
11823
11824 context.SetRegisterToRegisterPlusOffset(data_reg: *data_reg, base_reg: *base_reg,
11825 offset: (address + 4) - Rn);
11826 if (!MemAWrite(context, address: address + 4, data_val: Bits64(bits: data, msbit: 31, lsbit: 0),
11827 size: addr_byte_size))
11828 return false;
11829 } else {
11830 if (!MemAWrite(context, address, data_val: Bits64(bits: data, msbit: 31, lsbit: 0), size: addr_byte_size))
11831 return false;
11832
11833 context.SetRegisterToRegisterPlusOffset(data_reg: *data_reg, base_reg: *base_reg,
11834 offset: (address + 4) - Rn);
11835 if (!MemAWrite(context, address: address + 4, data_val: Bits64(bits: data, msbit: 63, lsbit: 32),
11836 size: addr_byte_size))
11837 return false;
11838 }
11839 }
11840 }
11841 return true;
11842}
11843
11844// A8.6.307 VLDI1 (multiple single elements) This instruction loads elements
11845// from memory into one, two, three or four registers, without de-interleaving.
11846// Every element of each register is loaded.
11847bool EmulateInstructionARM::EmulateVLD1Multiple(const uint32_t opcode,
11848 ARMEncoding encoding) {
11849#if 0
11850 if ConditionPassed() then
11851 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
11852 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
11853 if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
11854 for r = 0 to regs-1
11855 for e = 0 to elements-1
11856 Elem[D[d+r],e,esize] = MemU[address,ebytes];
11857 address = address + ebytes;
11858#endif
11859
11860 bool success = false;
11861
11862 if (ConditionPassed(opcode)) {
11863 uint32_t regs;
11864 uint32_t alignment;
11865 uint32_t ebytes;
11866 uint32_t esize;
11867 uint32_t elements;
11868 uint32_t d;
11869 uint32_t n;
11870 uint32_t m;
11871 bool wback;
11872 bool register_index;
11873
11874 switch (encoding) {
11875 case eEncodingT1:
11876 case eEncodingA1: {
11877 // case type of
11878 // when '0111'
11879 // regs = 1; if align<1> == '1' then UNDEFINED;
11880 // when '1010'
11881 // regs = 2; if align == '11' then UNDEFINED;
11882 // when '0110'
11883 // regs = 3; if align<1> == '1' then UNDEFINED;
11884 // when '0010'
11885 // regs = 4;
11886 // otherwise
11887 // SEE 'Related encodings';
11888 uint32_t type = Bits32(bits: opcode, msbit: 11, lsbit: 8);
11889 uint32_t align = Bits32(bits: opcode, msbit: 5, lsbit: 4);
11890 if (type == 7) // '0111'
11891 {
11892 regs = 1;
11893 if (BitIsSet(value: align, bit: 1))
11894 return false;
11895 } else if (type == 10) // '1010'
11896 {
11897 regs = 2;
11898 if (align == 3)
11899 return false;
11900
11901 } else if (type == 6) // '0110'
11902 {
11903 regs = 3;
11904 if (BitIsSet(value: align, bit: 1))
11905 return false;
11906 } else if (type == 2) // '0010'
11907 {
11908 regs = 4;
11909 } else
11910 return false;
11911
11912 // alignment = if align == '00' then 1 else 4 << UInt(align);
11913 if (align == 0)
11914 alignment = 1;
11915 else
11916 alignment = 4 << align;
11917
11918 // ebytes = 1 << UInt(size); esize = 8 * ebytes; elements = 8 DIV ebytes;
11919 ebytes = 1 << Bits32(bits: opcode, msbit: 7, lsbit: 6);
11920 esize = 8 * ebytes;
11921 elements = 8 / ebytes;
11922
11923 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
11924 d = (Bit32(bits: opcode, bit: 22) << 4) | Bits32(bits: opcode, msbit: 15, lsbit: 12);
11925 n = Bits32(bits: opcode, msbit: 19, lsbit: 15);
11926 m = Bits32(bits: opcode, msbit: 3, lsbit: 0);
11927
11928 // wback = (m != 15); register_index = (m != 15 && m != 13);
11929 wback = (m != 15);
11930 register_index = ((m != 15) && (m != 13));
11931
11932 // if d+regs > 32 then UNPREDICTABLE;
11933 if ((d + regs) > 32)
11934 return false;
11935 } break;
11936
11937 default:
11938 return false;
11939 }
11940
11941 std::optional<RegisterInfo> base_reg =
11942 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n);
11943
11944 uint32_t Rn = ReadCoreReg(regnum: n, success: &success);
11945 if (!success)
11946 return false;
11947
11948 // address = R[n]; if (address MOD alignment) != 0 then
11949 // GenerateAlignmentException();
11950 addr_t address = Rn;
11951 if ((address % alignment) != 0)
11952 return false;
11953
11954 EmulateInstruction::Context context;
11955 // if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
11956 if (wback) {
11957 uint32_t Rm = ReadCoreReg(regnum: m, success: &success);
11958 if (!success)
11959 return false;
11960
11961 uint32_t offset;
11962 if (register_index)
11963 offset = Rm;
11964 else
11965 offset = 8 * regs;
11966
11967 uint32_t value = Rn + offset;
11968 context.type = eContextAdjustBaseRegister;
11969 context.SetRegisterPlusOffset(base_reg: *base_reg, signed_offset: offset);
11970
11971 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n,
11972 reg_value: value))
11973 return false;
11974 }
11975
11976 // for r = 0 to regs-1
11977 for (uint32_t r = 0; r < regs; ++r) {
11978 // for e = 0 to elements-1
11979 uint64_t assembled_data = 0;
11980 for (uint32_t e = 0; e < elements; ++e) {
11981 // Elem[D[d+r],e,esize] = MemU[address,ebytes];
11982 context.type = eContextRegisterLoad;
11983 context.SetRegisterPlusOffset(base_reg: *base_reg, signed_offset: address - Rn);
11984 uint64_t data = MemURead(context, address, size: ebytes, fail_value: 0, success_ptr: &success);
11985 if (!success)
11986 return false;
11987
11988 assembled_data =
11989 (data << (e * esize)) |
11990 assembled_data; // New data goes to the left of existing data
11991
11992 // address = address + ebytes;
11993 address = address + ebytes;
11994 }
11995 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindDWARF, reg_num: dwarf_d0 + d + r,
11996 reg_value: assembled_data))
11997 return false;
11998 }
11999 }
12000 return true;
12001}
12002
12003// A8.6.308 VLD1 (single element to one lane)
12004//
12005bool EmulateInstructionARM::EmulateVLD1Single(const uint32_t opcode,
12006 const ARMEncoding encoding) {
12007#if 0
12008 if ConditionPassed() then
12009 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
12010 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
12011 if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
12012 Elem[D[d],index,esize] = MemU[address,ebytes];
12013#endif
12014
12015 bool success = false;
12016
12017 if (ConditionPassed(opcode)) {
12018 uint32_t ebytes;
12019 uint32_t esize;
12020 uint32_t index;
12021 uint32_t alignment;
12022 uint32_t d;
12023 uint32_t n;
12024 uint32_t m;
12025 bool wback;
12026 bool register_index;
12027
12028 switch (encoding) {
12029 case eEncodingT1:
12030 case eEncodingA1: {
12031 uint32_t size = Bits32(bits: opcode, msbit: 11, lsbit: 10);
12032 uint32_t index_align = Bits32(bits: opcode, msbit: 7, lsbit: 4);
12033 // if size == '11' then SEE VLD1 (single element to all lanes);
12034 if (size == 3)
12035 return EmulateVLD1SingleAll(opcode, encoding);
12036 // case size of
12037 if (size == 0) // when '00'
12038 {
12039 // if index_align<0> != '0' then UNDEFINED;
12040 if (BitIsClear(value: index_align, bit: 0))
12041 return false;
12042
12043 // ebytes = 1; esize = 8; index = UInt(index_align<3:1>); alignment = 1;
12044 ebytes = 1;
12045 esize = 8;
12046 index = Bits32(bits: index_align, msbit: 3, lsbit: 1);
12047 alignment = 1;
12048 } else if (size == 1) // when '01'
12049 {
12050 // if index_align<1> != '0' then UNDEFINED;
12051 if (BitIsClear(value: index_align, bit: 1))
12052 return false;
12053
12054 // ebytes = 2; esize = 16; index = UInt(index_align<3:2>);
12055 ebytes = 2;
12056 esize = 16;
12057 index = Bits32(bits: index_align, msbit: 3, lsbit: 2);
12058
12059 // alignment = if index_align<0> == '0' then 1 else 2;
12060 if (BitIsClear(value: index_align, bit: 0))
12061 alignment = 1;
12062 else
12063 alignment = 2;
12064 } else if (size == 2) // when '10'
12065 {
12066 // if index_align<2> != '0' then UNDEFINED;
12067 if (BitIsClear(value: index_align, bit: 2))
12068 return false;
12069
12070 // if index_align<1:0> != '00' && index_align<1:0> != '11' then
12071 // UNDEFINED;
12072 if ((Bits32(bits: index_align, msbit: 1, lsbit: 0) != 0) &&
12073 (Bits32(bits: index_align, msbit: 1, lsbit: 0) != 3))
12074 return false;
12075
12076 // ebytes = 4; esize = 32; index = UInt(index_align<3>);
12077 ebytes = 4;
12078 esize = 32;
12079 index = Bit32(bits: index_align, bit: 3);
12080
12081 // alignment = if index_align<1:0> == '00' then 1 else 4;
12082 if (Bits32(bits: index_align, msbit: 1, lsbit: 0) == 0)
12083 alignment = 1;
12084 else
12085 alignment = 4;
12086 } else {
12087 return false;
12088 }
12089 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
12090 d = (Bit32(bits: opcode, bit: 22) << 4) | Bits32(bits: opcode, msbit: 15, lsbit: 12);
12091 n = Bits32(bits: opcode, msbit: 19, lsbit: 16);
12092 m = Bits32(bits: opcode, msbit: 3, lsbit: 0);
12093
12094 // wback = (m != 15); register_index = (m != 15 && m != 13); if n == 15
12095 // then UNPREDICTABLE;
12096 wback = (m != 15);
12097 register_index = ((m != 15) && (m != 13));
12098
12099 if (n == 15)
12100 return false;
12101
12102 } break;
12103
12104 default:
12105 return false;
12106 }
12107
12108 uint32_t Rn = ReadCoreReg(regnum: n, success: &success);
12109 if (!success)
12110 return false;
12111
12112 // address = R[n]; if (address MOD alignment) != 0 then
12113 // GenerateAlignmentException();
12114 addr_t address = Rn;
12115 if ((address % alignment) != 0)
12116 return false;
12117
12118 EmulateInstruction::Context context;
12119 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
12120 if (wback) {
12121 uint32_t Rm = ReadCoreReg(regnum: m, success: &success);
12122 if (!success)
12123 return false;
12124
12125 uint32_t offset;
12126 if (register_index)
12127 offset = Rm;
12128 else
12129 offset = ebytes;
12130
12131 uint32_t value = Rn + offset;
12132
12133 context.type = eContextAdjustBaseRegister;
12134 std::optional<RegisterInfo> base_reg =
12135 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n);
12136 context.SetRegisterPlusOffset(base_reg: *base_reg, signed_offset: offset);
12137
12138 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n,
12139 reg_value: value))
12140 return false;
12141 }
12142
12143 // Elem[D[d],index,esize] = MemU[address,ebytes];
12144 uint32_t element = MemURead(context, address, size: esize, fail_value: 0, success_ptr: &success);
12145 if (!success)
12146 return false;
12147
12148 element = element << (index * esize);
12149
12150 uint64_t reg_data =
12151 ReadRegisterUnsigned(reg_kind: eRegisterKindDWARF, reg_num: dwarf_d0 + d, fail_value: 0, success_ptr: &success);
12152 if (!success)
12153 return false;
12154
12155 uint64_t all_ones = -1;
12156 uint64_t mask = all_ones
12157 << ((index + 1) * esize); // mask is all 1's to left of
12158 // where 'element' goes, & all 0's
12159 // at element & to the right of element.
12160 if (index > 0)
12161 mask = mask | Bits64(bits: all_ones, msbit: (index * esize) - 1,
12162 lsbit: 0); // add 1's to the right of where 'element' goes.
12163 // now mask should be 0's where element goes & 1's everywhere else.
12164
12165 uint64_t masked_reg =
12166 reg_data & mask; // Take original reg value & zero out 'element' bits
12167 reg_data =
12168 masked_reg & element; // Put 'element' into those bits in reg_data.
12169
12170 context.type = eContextRegisterLoad;
12171 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + d,
12172 reg_value: reg_data))
12173 return false;
12174 }
12175 return true;
12176}
12177
12178// A8.6.391 VST1 (multiple single elements) Vector Store (multiple single
12179// elements) stores elements to memory from one, two, three, or four registers,
12180// without interleaving. Every element of each register is stored.
12181bool EmulateInstructionARM::EmulateVST1Multiple(const uint32_t opcode,
12182 ARMEncoding encoding) {
12183#if 0
12184 if ConditionPassed() then
12185 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
12186 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
12187 if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
12188 for r = 0 to regs-1
12189 for e = 0 to elements-1
12190 MemU[address,ebytes] = Elem[D[d+r],e,esize];
12191 address = address + ebytes;
12192#endif
12193
12194 bool success = false;
12195
12196 if (ConditionPassed(opcode)) {
12197 uint32_t regs;
12198 uint32_t alignment;
12199 uint32_t ebytes;
12200 uint32_t esize;
12201 uint32_t elements;
12202 uint32_t d;
12203 uint32_t n;
12204 uint32_t m;
12205 bool wback;
12206 bool register_index;
12207
12208 switch (encoding) {
12209 case eEncodingT1:
12210 case eEncodingA1: {
12211 uint32_t type = Bits32(bits: opcode, msbit: 11, lsbit: 8);
12212 uint32_t align = Bits32(bits: opcode, msbit: 5, lsbit: 4);
12213
12214 // case type of
12215 if (type == 7) // when '0111'
12216 {
12217 // regs = 1; if align<1> == '1' then UNDEFINED;
12218 regs = 1;
12219 if (BitIsSet(value: align, bit: 1))
12220 return false;
12221 } else if (type == 10) // when '1010'
12222 {
12223 // regs = 2; if align == '11' then UNDEFINED;
12224 regs = 2;
12225 if (align == 3)
12226 return false;
12227 } else if (type == 6) // when '0110'
12228 {
12229 // regs = 3; if align<1> == '1' then UNDEFINED;
12230 regs = 3;
12231 if (BitIsSet(value: align, bit: 1))
12232 return false;
12233 } else if (type == 2) // when '0010'
12234 // regs = 4;
12235 regs = 4;
12236 else // otherwise
12237 // SEE 'Related encodings';
12238 return false;
12239
12240 // alignment = if align == '00' then 1 else 4 << UInt(align);
12241 if (align == 0)
12242 alignment = 1;
12243 else
12244 alignment = 4 << align;
12245
12246 // ebytes = 1 << UInt(size); esize = 8 * ebytes; elements = 8 DIV ebytes;
12247 ebytes = 1 << Bits32(bits: opcode, msbit: 7, lsbit: 6);
12248 esize = 8 * ebytes;
12249 elements = 8 / ebytes;
12250
12251 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
12252 d = (Bit32(bits: opcode, bit: 22) << 4) | Bits32(bits: opcode, msbit: 15, lsbit: 12);
12253 n = Bits32(bits: opcode, msbit: 19, lsbit: 16);
12254 m = Bits32(bits: opcode, msbit: 3, lsbit: 0);
12255
12256 // wback = (m != 15); register_index = (m != 15 && m != 13);
12257 wback = (m != 15);
12258 register_index = ((m != 15) && (m != 13));
12259
12260 // if d+regs > 32 then UNPREDICTABLE; if n == 15 then UNPREDICTABLE;
12261 if ((d + regs) > 32)
12262 return false;
12263
12264 if (n == 15)
12265 return false;
12266
12267 } break;
12268
12269 default:
12270 return false;
12271 }
12272
12273 std::optional<RegisterInfo> base_reg =
12274 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n);
12275
12276 uint32_t Rn = ReadCoreReg(regnum: n, success: &success);
12277 if (!success)
12278 return false;
12279
12280 // address = R[n]; if (address MOD alignment) != 0 then
12281 // GenerateAlignmentException();
12282 addr_t address = Rn;
12283 if ((address % alignment) != 0)
12284 return false;
12285
12286 EmulateInstruction::Context context;
12287 // if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
12288 if (wback) {
12289 uint32_t Rm = ReadCoreReg(regnum: m, success: &success);
12290 if (!success)
12291 return false;
12292
12293 uint32_t offset;
12294 if (register_index)
12295 offset = Rm;
12296 else
12297 offset = 8 * regs;
12298
12299 context.type = eContextAdjustBaseRegister;
12300 context.SetRegisterPlusOffset(base_reg: *base_reg, signed_offset: offset);
12301
12302 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n,
12303 reg_value: Rn + offset))
12304 return false;
12305 }
12306
12307 context.type = eContextRegisterStore;
12308 // for r = 0 to regs-1
12309 for (uint32_t r = 0; r < regs; ++r) {
12310 std::optional<RegisterInfo> data_reg =
12311 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_d0 + d + r);
12312 uint64_t register_data = ReadRegisterUnsigned(
12313 reg_kind: eRegisterKindDWARF, reg_num: dwarf_d0 + d + r, fail_value: 0, success_ptr: &success);
12314 if (!success)
12315 return false;
12316
12317 // for e = 0 to elements-1
12318 for (uint32_t e = 0; e < elements; ++e) {
12319 // MemU[address,ebytes] = Elem[D[d+r],e,esize];
12320 uint64_t word = Bits64(bits: register_data, msbit: ((e + 1) * esize) - 1, lsbit: e * esize);
12321
12322 context.SetRegisterToRegisterPlusOffset(data_reg: *data_reg, base_reg: *base_reg,
12323 offset: address - Rn);
12324 if (!MemUWrite(context, address, data_val: word, size: ebytes))
12325 return false;
12326
12327 // address = address + ebytes;
12328 address = address + ebytes;
12329 }
12330 }
12331 }
12332 return true;
12333}
12334
12335// A8.6.392 VST1 (single element from one lane) This instruction stores one
12336// element to memory from one element of a register.
12337bool EmulateInstructionARM::EmulateVST1Single(const uint32_t opcode,
12338 ARMEncoding encoding) {
12339#if 0
12340 if ConditionPassed() then
12341 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
12342 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
12343 if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
12344 MemU[address,ebytes] = Elem[D[d],index,esize];
12345#endif
12346
12347 bool success = false;
12348
12349 if (ConditionPassed(opcode)) {
12350 uint32_t ebytes;
12351 uint32_t esize;
12352 uint32_t index;
12353 uint32_t alignment;
12354 uint32_t d;
12355 uint32_t n;
12356 uint32_t m;
12357 bool wback;
12358 bool register_index;
12359
12360 switch (encoding) {
12361 case eEncodingT1:
12362 case eEncodingA1: {
12363 uint32_t size = Bits32(bits: opcode, msbit: 11, lsbit: 10);
12364 uint32_t index_align = Bits32(bits: opcode, msbit: 7, lsbit: 4);
12365
12366 // if size == '11' then UNDEFINED;
12367 if (size == 3)
12368 return false;
12369
12370 // case size of
12371 if (size == 0) // when '00'
12372 {
12373 // if index_align<0> != '0' then UNDEFINED;
12374 if (BitIsClear(value: index_align, bit: 0))
12375 return false;
12376 // ebytes = 1; esize = 8; index = UInt(index_align<3:1>); alignment = 1;
12377 ebytes = 1;
12378 esize = 8;
12379 index = Bits32(bits: index_align, msbit: 3, lsbit: 1);
12380 alignment = 1;
12381 } else if (size == 1) // when '01'
12382 {
12383 // if index_align<1> != '0' then UNDEFINED;
12384 if (BitIsClear(value: index_align, bit: 1))
12385 return false;
12386
12387 // ebytes = 2; esize = 16; index = UInt(index_align<3:2>);
12388 ebytes = 2;
12389 esize = 16;
12390 index = Bits32(bits: index_align, msbit: 3, lsbit: 2);
12391
12392 // alignment = if index_align<0> == '0' then 1 else 2;
12393 if (BitIsClear(value: index_align, bit: 0))
12394 alignment = 1;
12395 else
12396 alignment = 2;
12397 } else if (size == 2) // when '10'
12398 {
12399 // if index_align<2> != '0' then UNDEFINED;
12400 if (BitIsClear(value: index_align, bit: 2))
12401 return false;
12402
12403 // if index_align<1:0> != '00' && index_align<1:0> != '11' then
12404 // UNDEFINED;
12405 if ((Bits32(bits: index_align, msbit: 1, lsbit: 0) != 0) &&
12406 (Bits32(bits: index_align, msbit: 1, lsbit: 0) != 3))
12407 return false;
12408
12409 // ebytes = 4; esize = 32; index = UInt(index_align<3>);
12410 ebytes = 4;
12411 esize = 32;
12412 index = Bit32(bits: index_align, bit: 3);
12413
12414 // alignment = if index_align<1:0> == '00' then 1 else 4;
12415 if (Bits32(bits: index_align, msbit: 1, lsbit: 0) == 0)
12416 alignment = 1;
12417 else
12418 alignment = 4;
12419 } else {
12420 return false;
12421 }
12422 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
12423 d = (Bit32(bits: opcode, bit: 22) << 4) | Bits32(bits: opcode, msbit: 15, lsbit: 12);
12424 n = Bits32(bits: opcode, msbit: 19, lsbit: 16);
12425 m = Bits32(bits: opcode, msbit: 3, lsbit: 0);
12426
12427 // wback = (m != 15); register_index = (m != 15 && m != 13); if n == 15
12428 // then UNPREDICTABLE;
12429 wback = (m != 15);
12430 register_index = ((m != 15) && (m != 13));
12431
12432 if (n == 15)
12433 return false;
12434 } break;
12435
12436 default:
12437 return false;
12438 }
12439
12440 std::optional<RegisterInfo> base_reg =
12441 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n);
12442
12443 uint32_t Rn = ReadCoreReg(regnum: n, success: &success);
12444 if (!success)
12445 return false;
12446
12447 // address = R[n]; if (address MOD alignment) != 0 then
12448 // GenerateAlignmentException();
12449 addr_t address = Rn;
12450 if ((address % alignment) != 0)
12451 return false;
12452
12453 EmulateInstruction::Context context;
12454 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
12455 if (wback) {
12456 uint32_t Rm = ReadCoreReg(regnum: m, success: &success);
12457 if (!success)
12458 return false;
12459
12460 uint32_t offset;
12461 if (register_index)
12462 offset = Rm;
12463 else
12464 offset = ebytes;
12465
12466 context.type = eContextAdjustBaseRegister;
12467 context.SetRegisterPlusOffset(base_reg: *base_reg, signed_offset: offset);
12468
12469 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n,
12470 reg_value: Rn + offset))
12471 return false;
12472 }
12473
12474 // MemU[address,ebytes] = Elem[D[d],index,esize];
12475 uint64_t register_data =
12476 ReadRegisterUnsigned(reg_kind: eRegisterKindDWARF, reg_num: dwarf_d0 + d, fail_value: 0, success_ptr: &success);
12477 if (!success)
12478 return false;
12479
12480 uint64_t word =
12481 Bits64(bits: register_data, msbit: ((index + 1) * esize) - 1, lsbit: index * esize);
12482
12483 std::optional<RegisterInfo> data_reg =
12484 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_d0 + d);
12485 context.type = eContextRegisterStore;
12486 context.SetRegisterToRegisterPlusOffset(data_reg: *data_reg, base_reg: *base_reg, offset: address - Rn);
12487
12488 if (!MemUWrite(context, address, data_val: word, size: ebytes))
12489 return false;
12490 }
12491 return true;
12492}
12493
12494// A8.6.309 VLD1 (single element to all lanes) This instruction loads one
12495// element from memory into every element of one or two vectors.
12496bool EmulateInstructionARM::EmulateVLD1SingleAll(const uint32_t opcode,
12497 const ARMEncoding encoding) {
12498#if 0
12499 if ConditionPassed() then
12500 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
12501 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
12502 if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
12503 replicated_element = Replicate(MemU[address,ebytes], elements);
12504 for r = 0 to regs-1
12505 D[d+r] = replicated_element;
12506#endif
12507
12508 bool success = false;
12509
12510 if (ConditionPassed(opcode)) {
12511 uint32_t ebytes;
12512 uint32_t elements;
12513 uint32_t regs;
12514 uint32_t alignment;
12515 uint32_t d;
12516 uint32_t n;
12517 uint32_t m;
12518 bool wback;
12519 bool register_index;
12520
12521 switch (encoding) {
12522 case eEncodingT1:
12523 case eEncodingA1: {
12524 // if size == '11' || (size == '00' && a == '1') then UNDEFINED;
12525 uint32_t size = Bits32(bits: opcode, msbit: 7, lsbit: 6);
12526 if ((size == 3) || ((size == 0) && BitIsSet(value: opcode, bit: 4)))
12527 return false;
12528
12529 // ebytes = 1 << UInt(size); elements = 8 DIV ebytes; regs = if T == '0'
12530 // then 1 else 2;
12531 ebytes = 1 << size;
12532 elements = 8 / ebytes;
12533 if (BitIsClear(value: opcode, bit: 5))
12534 regs = 1;
12535 else
12536 regs = 2;
12537
12538 // alignment = if a == '0' then 1 else ebytes;
12539 if (BitIsClear(value: opcode, bit: 4))
12540 alignment = 1;
12541 else
12542 alignment = ebytes;
12543
12544 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
12545 d = (Bit32(bits: opcode, bit: 22) << 4) | Bits32(bits: opcode, msbit: 15, lsbit: 12);
12546 n = Bits32(bits: opcode, msbit: 19, lsbit: 16);
12547 m = Bits32(bits: opcode, msbit: 3, lsbit: 0);
12548
12549 // wback = (m != 15); register_index = (m != 15 && m != 13);
12550 wback = (m != 15);
12551 register_index = ((m != 15) && (m != 13));
12552
12553 // if d+regs > 32 then UNPREDICTABLE; if n == 15 then UNPREDICTABLE;
12554 if ((d + regs) > 32)
12555 return false;
12556
12557 if (n == 15)
12558 return false;
12559 } break;
12560
12561 default:
12562 return false;
12563 }
12564
12565 uint32_t Rn = ReadCoreReg(regnum: n, success: &success);
12566 if (!success)
12567 return false;
12568
12569 // address = R[n]; if (address MOD alignment) != 0 then
12570 // GenerateAlignmentException();
12571 addr_t address = Rn;
12572 if ((address % alignment) != 0)
12573 return false;
12574
12575 EmulateInstruction::Context context;
12576 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
12577 if (wback) {
12578 uint32_t Rm = ReadCoreReg(regnum: m, success: &success);
12579 if (!success)
12580 return false;
12581
12582 uint32_t offset;
12583 if (register_index)
12584 offset = Rm;
12585 else
12586 offset = ebytes;
12587
12588 context.type = eContextAdjustBaseRegister;
12589 std::optional<RegisterInfo> base_reg =
12590 GetRegisterInfo(reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n);
12591 context.SetRegisterPlusOffset(base_reg: *base_reg, signed_offset: offset);
12592
12593 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindDWARF, reg_num: dwarf_r0 + n,
12594 reg_value: Rn + offset))
12595 return false;
12596 }
12597
12598 // replicated_element = Replicate(MemU[address,ebytes], elements);
12599
12600 context.type = eContextRegisterLoad;
12601 uint64_t word = MemURead(context, address, size: ebytes, fail_value: 0, success_ptr: &success);
12602 if (!success)
12603 return false;
12604
12605 uint64_t replicated_element = 0;
12606 uint32_t esize = ebytes * 8;
12607 for (uint32_t e = 0; e < elements; ++e)
12608 replicated_element =
12609 (replicated_element << esize) | Bits64(bits: word, msbit: esize - 1, lsbit: 0);
12610
12611 // for r = 0 to regs-1
12612 for (uint32_t r = 0; r < regs; ++r) {
12613 // D[d+r] = replicated_element;
12614 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindDWARF, reg_num: dwarf_d0 + d + r,
12615 reg_value: replicated_element))
12616 return false;
12617 }
12618 }
12619 return true;
12620}
12621
12622// B6.2.13 SUBS PC, LR and related instructions The SUBS PC, LR, #<const?
12623// instruction provides an exception return without the use of the stack. It
12624// subtracts the immediate constant from the LR, branches to the resulting
12625// address, and also copies the SPSR to the CPSR.
12626bool EmulateInstructionARM::EmulateSUBSPcLrEtc(const uint32_t opcode,
12627 const ARMEncoding encoding) {
12628#if 0
12629 if ConditionPassed() then
12630 EncodingSpecificOperations();
12631 if CurrentInstrSet() == InstrSet_ThumbEE then
12632 UNPREDICTABLE;
12633 operand2 = if register_form then Shift(R[m], shift_t, shift_n, APSR.C) else imm32;
12634 case opcode of
12635 when '0000' result = R[n] AND operand2; // AND
12636 when '0001' result = R[n] EOR operand2; // EOR
12637 when '0010' (result, -, -) = AddWithCarry(R[n], NOT(operand2), '1'); // SUB
12638 when '0011' (result, -, -) = AddWithCarry(NOT(R[n]), operand2, '1'); // RSB
12639 when '0100' (result, -, -) = AddWithCarry(R[n], operand2, '0'); // ADD
12640 when '0101' (result, -, -) = AddWithCarry(R[n], operand2, APSR.c); // ADC
12641 when '0110' (result, -, -) = AddWithCarry(R[n], NOT(operand2), APSR.C); // SBC
12642 when '0111' (result, -, -) = AddWithCarry(NOT(R[n]), operand2, APSR.C); // RSC
12643 when '1100' result = R[n] OR operand2; // ORR
12644 when '1101' result = operand2; // MOV
12645 when '1110' result = R[n] AND NOT(operand2); // BIC
12646 when '1111' result = NOT(operand2); // MVN
12647 CPSRWriteByInstr(SPSR[], '1111', TRUE);
12648 BranchWritePC(result);
12649#endif
12650
12651 bool success = false;
12652
12653 if (ConditionPassed(opcode)) {
12654 uint32_t n;
12655 uint32_t m;
12656 uint32_t imm32;
12657 bool register_form;
12658 ARM_ShifterType shift_t;
12659 uint32_t shift_n;
12660 uint32_t code;
12661
12662 switch (encoding) {
12663 case eEncodingT1:
12664 // if CurrentInstrSet() == InstrSet_ThumbEE then UNPREDICTABLE n = 14;
12665 // imm32 = ZeroExtend(imm8, 32); register_form = FALSE; opcode = '0010';
12666 // // = SUB
12667 n = 14;
12668 imm32 = Bits32(bits: opcode, msbit: 7, lsbit: 0);
12669 register_form = false;
12670 code = 2;
12671
12672 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
12673 if (InITBlock() && !LastInITBlock())
12674 return false;
12675
12676 break;
12677
12678 case eEncodingA1:
12679 // n = UInt(Rn); imm32 = ARMExpandImm(imm12); register_form = FALSE;
12680 n = Bits32(bits: opcode, msbit: 19, lsbit: 16);
12681 imm32 = ARMExpandImm(opcode);
12682 register_form = false;
12683 code = Bits32(bits: opcode, msbit: 24, lsbit: 21);
12684
12685 break;
12686
12687 case eEncodingA2:
12688 // n = UInt(Rn); m = UInt(Rm); register_form = TRUE;
12689 n = Bits32(bits: opcode, msbit: 19, lsbit: 16);
12690 m = Bits32(bits: opcode, msbit: 3, lsbit: 0);
12691 register_form = true;
12692
12693 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
12694 shift_n = DecodeImmShiftARM(opcode, shift_t);
12695
12696 break;
12697
12698 default:
12699 return false;
12700 }
12701
12702 // operand2 = if register_form then Shift(R[m], shift_t, shift_n, APSR.C)
12703 // else imm32;
12704 uint32_t operand2;
12705 if (register_form) {
12706 uint32_t Rm = ReadCoreReg(regnum: m, success: &success);
12707 if (!success)
12708 return false;
12709
12710 operand2 = Shift(value: Rm, type: shift_t, amount: shift_n, APSR_C, success: &success);
12711 if (!success)
12712 return false;
12713 } else {
12714 operand2 = imm32;
12715 }
12716
12717 uint32_t Rn = ReadCoreReg(regnum: n, success: &success);
12718 if (!success)
12719 return false;
12720
12721 AddWithCarryResult result;
12722
12723 // case opcode of
12724 switch (code) {
12725 case 0: // when '0000'
12726 // result = R[n] AND operand2; // AND
12727 result.result = Rn & operand2;
12728 break;
12729
12730 case 1: // when '0001'
12731 // result = R[n] EOR operand2; // EOR
12732 result.result = Rn ^ operand2;
12733 break;
12734
12735 case 2: // when '0010'
12736 // (result, -, -) = AddWithCarry(R[n], NOT(operand2), '1'); // SUB
12737 result = AddWithCarry(x: Rn, y: ~(operand2), carry_in: 1);
12738 break;
12739
12740 case 3: // when '0011'
12741 // (result, -, -) = AddWithCarry(NOT(R[n]), operand2, '1'); // RSB
12742 result = AddWithCarry(x: ~(Rn), y: operand2, carry_in: 1);
12743 break;
12744
12745 case 4: // when '0100'
12746 // (result, -, -) = AddWithCarry(R[n], operand2, '0'); // ADD
12747 result = AddWithCarry(x: Rn, y: operand2, carry_in: 0);
12748 break;
12749
12750 case 5: // when '0101'
12751 // (result, -, -) = AddWithCarry(R[n], operand2, APSR.c); // ADC
12752 result = AddWithCarry(x: Rn, y: operand2, APSR_C);
12753 break;
12754
12755 case 6: // when '0110'
12756 // (result, -, -) = AddWithCarry(R[n], NOT(operand2), APSR.C); // SBC
12757 result = AddWithCarry(x: Rn, y: ~(operand2), APSR_C);
12758 break;
12759
12760 case 7: // when '0111'
12761 // (result, -, -) = AddWithCarry(NOT(R[n]), operand2, APSR.C); // RSC
12762 result = AddWithCarry(x: ~(Rn), y: operand2, APSR_C);
12763 break;
12764
12765 case 10: // when '1100'
12766 // result = R[n] OR operand2; // ORR
12767 result.result = Rn | operand2;
12768 break;
12769
12770 case 11: // when '1101'
12771 // result = operand2; // MOV
12772 result.result = operand2;
12773 break;
12774
12775 case 12: // when '1110'
12776 // result = R[n] AND NOT(operand2); // BIC
12777 result.result = Rn & ~(operand2);
12778 break;
12779
12780 case 15: // when '1111'
12781 // result = NOT(operand2); // MVN
12782 result.result = ~(operand2);
12783 break;
12784
12785 default:
12786 return false;
12787 }
12788 // CPSRWriteByInstr(SPSR[], '1111', TRUE);
12789
12790 // For now, in emulation mode, we don't have access to the SPSR, so we will
12791 // use the CPSR instead, and hope for the best.
12792 uint32_t spsr =
12793 ReadRegisterUnsigned(reg_kind: eRegisterKindDWARF, reg_num: dwarf_cpsr, fail_value: 0, success_ptr: &success);
12794 if (!success)
12795 return false;
12796
12797 CPSRWriteByInstr(value: spsr, bytemask: 15, affect_execstate: true);
12798
12799 // BranchWritePC(result);
12800 EmulateInstruction::Context context;
12801 context.type = eContextAdjustPC;
12802 context.SetImmediate(result.result);
12803
12804 BranchWritePC(context, addr: result.result);
12805 }
12806 return true;
12807}
12808
12809EmulateInstructionARM::ARMOpcode *
12810EmulateInstructionARM::GetARMOpcodeForInstruction(const uint32_t opcode,
12811 uint32_t arm_isa) {
12812 static ARMOpcode g_arm_opcodes[] = {
12813 // Prologue instructions
12814
12815 // push register(s)
12816 {.mask: 0x0fff0000, .value: 0x092d0000, ARMvAll, .encoding: eEncodingA1, No_VFP, .size: eSize32,
12817 .callback: &EmulateInstructionARM::EmulatePUSH, .name: "push <registers>"},
12818 {.mask: 0x0fff0fff, .value: 0x052d0004, ARMvAll, .encoding: eEncodingA2, No_VFP, .size: eSize32,
12819 .callback: &EmulateInstructionARM::EmulatePUSH, .name: "push <register>"},
12820
12821 // set r7 to point to a stack offset
12822 {.mask: 0x0ffff000, .value: 0x028d7000, ARMvAll, .encoding: eEncodingA1, No_VFP, .size: eSize32,
12823 .callback: &EmulateInstructionARM::EmulateADDRdSPImm, .name: "add r7, sp, #<const>"},
12824 {.mask: 0x0ffff000, .value: 0x024c7000, ARMvAll, .encoding: eEncodingA1, No_VFP, .size: eSize32,
12825 .callback: &EmulateInstructionARM::EmulateSUBR7IPImm, .name: "sub r7, ip, #<const>"},
12826 // copy the stack pointer to ip
12827 {.mask: 0x0fffffff, .value: 0x01a0c00d, ARMvAll, .encoding: eEncodingA1, No_VFP, .size: eSize32,
12828 .callback: &EmulateInstructionARM::EmulateMOVRdSP, .name: "mov ip, sp"},
12829 {.mask: 0x0ffff000, .value: 0x028dc000, ARMvAll, .encoding: eEncodingA1, No_VFP, .size: eSize32,
12830 .callback: &EmulateInstructionARM::EmulateADDRdSPImm, .name: "add ip, sp, #<const>"},
12831 {.mask: 0x0ffff000, .value: 0x024dc000, ARMvAll, .encoding: eEncodingA1, No_VFP, .size: eSize32,
12832 .callback: &EmulateInstructionARM::EmulateSUBIPSPImm, .name: "sub ip, sp, #<const>"},
12833
12834 // adjust the stack pointer
12835 {.mask: 0x0ffff000, .value: 0x024dd000, ARMvAll, .encoding: eEncodingA1, No_VFP, .size: eSize32,
12836 .callback: &EmulateInstructionARM::EmulateSUBSPImm, .name: "sub sp, sp, #<const>"},
12837 {.mask: 0x0fef0010, .value: 0x004d0000, ARMvAll, .encoding: eEncodingA1, No_VFP, .size: eSize32,
12838 .callback: &EmulateInstructionARM::EmulateSUBSPReg,
12839 .name: "sub{s}<c> <Rd>, sp, <Rm>{,<shift>}"},
12840
12841 // push one register
12842 // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH;
12843 {.mask: 0x0e5f0000, .value: 0x040d0000, ARMvAll, .encoding: eEncodingA1, No_VFP, .size: eSize32,
12844 .callback: &EmulateInstructionARM::EmulateSTRRtSP, .name: "str Rt, [sp, #-imm12]!"},
12845
12846 // vector push consecutive extension register(s)
12847 {.mask: 0x0fbf0f00, .value: 0x0d2d0b00, ARMV6T2_ABOVE, .encoding: eEncodingA1, No_VFP, .size: eSize32,
12848 .callback: &EmulateInstructionARM::EmulateVPUSH, .name: "vpush.64 <list>"},
12849 {.mask: 0x0fbf0f00, .value: 0x0d2d0a00, ARMV6T2_ABOVE, .encoding: eEncodingA2, No_VFP, .size: eSize32,
12850 .callback: &EmulateInstructionARM::EmulateVPUSH, .name: "vpush.32 <list>"},
12851
12852 // Epilogue instructions
12853
12854 {.mask: 0x0fff0000, .value: 0x08bd0000, ARMvAll, .encoding: eEncodingA1, No_VFP, .size: eSize32,
12855 .callback: &EmulateInstructionARM::EmulatePOP, .name: "pop <registers>"},
12856 {.mask: 0x0fff0fff, .value: 0x049d0004, ARMvAll, .encoding: eEncodingA2, No_VFP, .size: eSize32,
12857 .callback: &EmulateInstructionARM::EmulatePOP, .name: "pop <register>"},
12858 {.mask: 0x0fbf0f00, .value: 0x0cbd0b00, ARMV6T2_ABOVE, .encoding: eEncodingA1, No_VFP, .size: eSize32,
12859 .callback: &EmulateInstructionARM::EmulateVPOP, .name: "vpop.64 <list>"},
12860 {.mask: 0x0fbf0f00, .value: 0x0cbd0a00, ARMV6T2_ABOVE, .encoding: eEncodingA2, No_VFP, .size: eSize32,
12861 .callback: &EmulateInstructionARM::EmulateVPOP, .name: "vpop.32 <list>"},
12862
12863 // Supervisor Call (previously Software Interrupt)
12864 {.mask: 0x0f000000, .value: 0x0f000000, ARMvAll, .encoding: eEncodingA1, No_VFP, .size: eSize32,
12865 .callback: &EmulateInstructionARM::EmulateSVC, .name: "svc #imm24"},
12866
12867 // Branch instructions
12868 // To resolve ambiguity, "blx <label>" should come before "b #imm24" and
12869 // "bl <label>".
12870 {.mask: 0xfe000000, .value: 0xfa000000, ARMV5_ABOVE, .encoding: eEncodingA2, No_VFP, .size: eSize32,
12871 .callback: &EmulateInstructionARM::EmulateBLXImmediate, .name: "blx <label>"},
12872 {.mask: 0x0f000000, .value: 0x0a000000, ARMvAll, .encoding: eEncodingA1, No_VFP, .size: eSize32,
12873 .callback: &EmulateInstructionARM::EmulateB, .name: "b #imm24"},
12874 {.mask: 0x0f000000, .value: 0x0b000000, ARMvAll, .encoding: eEncodingA1, No_VFP, .size: eSize32,
12875 .callback: &EmulateInstructionARM::EmulateBLXImmediate, .name: "bl <label>"},
12876 {.mask: 0x0ffffff0, .value: 0x012fff30, ARMV5_ABOVE, .encoding: eEncodingA1, No_VFP, .size: eSize32,
12877 .callback: &EmulateInstructionARM::EmulateBLXRm, .name: "blx <Rm>"},
12878 // for example, "bx lr"
12879 {.mask: 0x0ffffff0, .value: 0x012fff10, ARMvAll, .encoding: eEncodingA1, No_VFP, .size: eSize32,
12880 .callback: &EmulateInstructionARM::EmulateBXRm, .name: "bx <Rm>"},
12881 // bxj
12882 {.mask: 0x0ffffff0, .value: 0x012fff20, ARMvAll, .encoding: eEncodingA1, No_VFP, .size: eSize32,
12883 .callback: &EmulateInstructionARM::EmulateBXJRm, .name: "bxj <Rm>"},
12884
12885 // Data-processing instructions
12886 // adc (immediate)
12887 {.mask: 0x0fe00000, .value: 0x02a00000, ARMvAll, .encoding: eEncodingA1, No_VFP, .size: eSize32,
12888 .callback: &EmulateInstructionARM::EmulateADCImm, .name: "adc{s}<c> <Rd>, <Rn>, #const"},
12889 // adc (register)
12890 {.mask: 0x0fe00010, .value: 0x00a00000, ARMvAll, .encoding: eEncodingA1, No_VFP, .size: eSize32,
12891 .callback: &EmulateInstructionARM::EmulateADCReg,
12892 .name: "adc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12893 // add (immediate)
12894 {.mask: 0x0fe00000, .value: 0x02800000, ARMvAll, .encoding: eEncodingA1, No_VFP, .size: eSize32,
12895 .callback: &EmulateInstructionARM::EmulateADDImmARM,
12896 .name: "add{s}<c> <Rd>, <Rn>, #const"},
12897 // add (register)
12898 {.mask: 0x0fe00010, .value: 0x00800000, ARMvAll, .encoding: eEncodingA1, No_VFP, .size: eSize32,
12899 .callback: &EmulateInstructionARM::EmulateADDReg,
12900 .name: "add{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12901 // add (register-shifted register)
12902 {.mask: 0x0fe00090, .value: 0x00800010, ARMvAll, .encoding: eEncodingA1, No_VFP, .size: eSize32,
12903 .callback: &EmulateInstructionARM::EmulateADDRegShift,
12904 .name: "add{s}<c> <Rd>, <Rn>, <Rm>, <type> <RS>"},
12905 // adr
12906 {.mask: 0x0fff0000, .value: 0x028f0000, ARMvAll, .encoding: eEncodingA1, No_VFP, .size: eSize32,
12907 .callback: &EmulateInstructionARM::EmulateADR, .name: "add<c> <Rd>, PC, #<const>"},
12908 {.mask: 0x0fff0000, .value: 0x024f0000, ARMvAll, .encoding: eEncodingA2, No_VFP, .size: eSize32,
12909 .callback: &EmulateInstructionARM::EmulateADR, .name: "sub<c> <Rd>, PC, #<const>"},
12910 // and (immediate)
12911 {.mask: 0x0fe00000, .value: 0x02000000, ARMvAll, .encoding: eEncodingA1, No_VFP, .size: eSize32,
12912 .callback: &EmulateInstructionARM::EmulateANDImm, .name: "and{s}<c> <Rd>, <Rn>, #const"},
12913 // and (register)
12914 {.mask: 0x0fe00010, .value: 0x00000000, ARMvAll, .encoding: eEncodingA1, No_VFP, .size: eSize32,
12915 .callback: &EmulateInstructionARM::EmulateANDReg,
12916 .name: "and{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12917 // bic (immediate)
12918 {.mask: 0x0fe00000, .value: 0x03c00000, ARMvAll, .encoding: eEncodingA1, No_VFP, .size: eSize32,
12919 .callback: &EmulateInstructionARM::EmulateBICImm, .name: "bic{s}<c> <Rd>, <Rn>, #const"},
12920 // bic (register)
12921 {.mask: 0x0fe00010, .value: 0x01c00000, ARMvAll, .encoding: eEncodingA1, No_VFP, .size: eSize32,
12922 .callback: &EmulateInstructionARM::EmulateBICReg,
12923 .name: "bic{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12924 // eor (immediate)
12925 {.mask: 0x0fe00000, .value: 0x02200000, ARMvAll, .encoding: eEncodingA1, No_VFP, .size: eSize32,
12926 .callback: &EmulateInstructionARM::EmulateEORImm, .name: "eor{s}<c> <Rd>, <Rn>, #const"},
12927 // eor (register)
12928 {.mask: 0x0fe00010, .value: 0x00200000, ARMvAll, .encoding: eEncodingA1, No_VFP, .size: eSize32,
12929 .callback: &EmulateInstructionARM::EmulateEORReg,
12930 .name: "eor{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12931 // orr (immediate)
12932 {.mask: 0x0fe00000, .value: 0x03800000, ARMvAll, .encoding: eEncodingA1, No_VFP, .size: eSize32,
12933 .callback: &EmulateInstructionARM::EmulateORRImm, .name: "orr{s}<c> <Rd>, <Rn>, #const"},
12934 // orr (register)
12935 {.mask: 0x0fe00010, .value: 0x01800000, ARMvAll, .encoding: eEncodingA1, No_VFP, .size: eSize32,
12936 .callback: &EmulateInstructionARM::EmulateORRReg,
12937 .name: "orr{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12938 // rsb (immediate)
12939 {.mask: 0x0fe00000, .value: 0x02600000, ARMvAll, .encoding: eEncodingA1, No_VFP, .size: eSize32,
12940 .callback: &EmulateInstructionARM::EmulateRSBImm, .name: "rsb{s}<c> <Rd>, <Rn>, #<const>"},
12941 // rsb (register)
12942 {.mask: 0x0fe00010, .value: 0x00600000, ARMvAll, .encoding: eEncodingA1, No_VFP, .size: eSize32,
12943 .callback: &EmulateInstructionARM::EmulateRSBReg,
12944 .name: "rsb{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12945 // rsc (immediate)
12946 {.mask: 0x0fe00000, .value: 0x02e00000, ARMvAll, .encoding: eEncodingA1, No_VFP, .size: eSize32,
12947 .callback: &EmulateInstructionARM::EmulateRSCImm, .name: "rsc{s}<c> <Rd>, <Rn>, #<const>"},
12948 // rsc (register)
12949 {.mask: 0x0fe00010, .value: 0x00e00000, ARMvAll, .encoding: eEncodingA1, No_VFP, .size: eSize32,
12950 .callback: &EmulateInstructionARM::EmulateRSCReg,
12951 .name: "rsc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12952 // sbc (immediate)
12953 {.mask: 0x0fe00000, .value: 0x02c00000, ARMvAll, .encoding: eEncodingA1, No_VFP, .size: eSize32,
12954 .callback: &EmulateInstructionARM::EmulateSBCImm, .name: "sbc{s}<c> <Rd>, <Rn>, #<const>"},
12955 // sbc (register)
12956 {.mask: 0x0fe00010, .value: 0x00c00000, ARMvAll, .encoding: eEncodingA1, No_VFP, .size: eSize32,
12957 .callback: &EmulateInstructionARM::EmulateSBCReg,
12958 .name: "sbc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12959 // sub (immediate, ARM)
12960 {.mask: 0x0fe00000, .value: 0x02400000, ARMvAll, .encoding: eEncodingA1, No_VFP, .size: eSize32,
12961 .callback: &EmulateInstructionARM::EmulateSUBImmARM,
12962 .name: "sub{s}<c> <Rd>, <Rn>, #<const>"},
12963 // sub (sp minus immediate)
12964 {.mask: 0x0fef0000, .value: 0x024d0000, ARMvAll, .encoding: eEncodingA1, No_VFP, .size: eSize32,
12965 .callback: &EmulateInstructionARM::EmulateSUBSPImm, .name: "sub{s}<c> <Rd>, sp, #<const>"},
12966 // sub (register)
12967 {.mask: 0x0fe00010, .value: 0x00400000, ARMvAll, .encoding: eEncodingA1, No_VFP, .size: eSize32,
12968 .callback: &EmulateInstructionARM::EmulateSUBReg,
12969 .name: "sub{s}<c> <Rd>, <Rn>, <Rm>{,<shift>}"},
12970 // teq (immediate)
12971 {.mask: 0x0ff0f000, .value: 0x03300000, ARMvAll, .encoding: eEncodingA1, No_VFP, .size: eSize32,
12972 .callback: &EmulateInstructionARM::EmulateTEQImm, .name: "teq<c> <Rn>, #const"},
12973 // teq (register)
12974 {.mask: 0x0ff0f010, .value: 0x01300000, ARMvAll, .encoding: eEncodingA1, No_VFP, .size: eSize32,
12975 .callback: &EmulateInstructionARM::EmulateTEQReg, .name: "teq<c> <Rn>, <Rm> {,<shift>}"},
12976 // tst (immediate)
12977 {.mask: 0x0ff0f000, .value: 0x03100000, ARMvAll, .encoding: eEncodingA1, No_VFP, .size: eSize32,
12978 .callback: &EmulateInstructionARM::EmulateTSTImm, .name: "tst<c> <Rn>, #const"},
12979 // tst (register)
12980 {.mask: 0x0ff0f010, .value: 0x01100000, ARMvAll, .encoding: eEncodingA1, No_VFP, .size: eSize32,
12981 .callback: &EmulateInstructionARM::EmulateTSTReg, .name: "tst<c> <Rn>, <Rm> {,<shift>}"},
12982
12983 // mov (immediate)
12984 {.mask: 0x0fef0000, .value: 0x03a00000, ARMvAll, .encoding: eEncodingA1, No_VFP, .size: eSize32,
12985 .callback: &EmulateInstructionARM::EmulateMOVRdImm, .name: "mov{s}<c> <Rd>, #<const>"},
12986 {.mask: 0x0ff00000, .value: 0x03000000, ARMV6T2_ABOVE, .encoding: eEncodingA2, No_VFP, .size: eSize32,
12987 .callback: &EmulateInstructionARM::EmulateMOVRdImm, .name: "movw<c> <Rd>, #<imm16>"},
12988 // mov (register)
12989 {.mask: 0x0fef0ff0, .value: 0x01a00000, ARMvAll, .encoding: eEncodingA1, No_VFP, .size: eSize32,
12990 .callback: &EmulateInstructionARM::EmulateMOVRdRm, .name: "mov{s}<c> <Rd>, <Rm>"},
12991 // mvn (immediate)
12992 {.mask: 0x0fef0000, .value: 0x03e00000, ARMvAll, .encoding: eEncodingA1, No_VFP, .size: eSize32,
12993 .callback: &EmulateInstructionARM::EmulateMVNImm, .name: "mvn{s}<c> <Rd>, #<const>"},
12994 // mvn (register)
12995 {.mask: 0x0fef0010, .value: 0x01e00000, ARMvAll, .encoding: eEncodingA1, No_VFP, .size: eSize32,
12996 .callback: &EmulateInstructionARM::EmulateMVNReg,
12997 .name: "mvn{s}<c> <Rd>, <Rm> {,<shift>}"},
12998 // cmn (immediate)
12999 {.mask: 0x0ff0f000, .value: 0x03700000, ARMvAll, .encoding: eEncodingA1, No_VFP, .size: eSize32,
13000 .callback: &EmulateInstructionARM::EmulateCMNImm, .name: "cmn<c> <Rn>, #<const>"},
13001 // cmn (register)
13002 {.mask: 0x0ff0f010, .value: 0x01700000, ARMvAll, .encoding: eEncodingA1, No_VFP, .size: eSize32,
13003 .callback: &EmulateInstructionARM::EmulateCMNReg, .name: "cmn<c> <Rn>, <Rm> {,<shift>}"},
13004 // cmp (immediate)
13005 {.mask: 0x0ff0f000, .value: 0x03500000, ARMvAll, .encoding: eEncodingA1, No_VFP, .size: eSize32,
13006 .callback: &EmulateInstructionARM::EmulateCMPImm, .name: "cmp<c> <Rn>, #<const>"},
13007 // cmp (register)
13008 {.mask: 0x0ff0f010, .value: 0x01500000, ARMvAll, .encoding: eEncodingA1, No_VFP, .size: eSize32,
13009 .callback: &EmulateInstructionARM::EmulateCMPReg, .name: "cmp<c> <Rn>, <Rm> {,<shift>}"},
13010 // asr (immediate)
13011 {.mask: 0x0fef0070, .value: 0x01a00040, ARMvAll, .encoding: eEncodingA1, No_VFP, .size: eSize32,
13012 .callback: &EmulateInstructionARM::EmulateASRImm, .name: "asr{s}<c> <Rd>, <Rm>, #imm"},
13013 // asr (register)
13014 {.mask: 0x0fef00f0, .value: 0x01a00050, ARMvAll, .encoding: eEncodingA1, No_VFP, .size: eSize32,
13015 .callback: &EmulateInstructionARM::EmulateASRReg, .name: "asr{s}<c> <Rd>, <Rn>, <Rm>"},
13016 // lsl (immediate)
13017 {.mask: 0x0fef0070, .value: 0x01a00000, ARMvAll, .encoding: eEncodingA1, No_VFP, .size: eSize32,
13018 .callback: &EmulateInstructionARM::EmulateLSLImm, .name: "lsl{s}<c> <Rd>, <Rm>, #imm"},
13019 // lsl (register)
13020 {.mask: 0x0fef00f0, .value: 0x01a00010, ARMvAll, .encoding: eEncodingA1, No_VFP, .size: eSize32,
13021 .callback: &EmulateInstructionARM::EmulateLSLReg, .name: "lsl{s}<c> <Rd>, <Rn>, <Rm>"},
13022 // lsr (immediate)
13023 {.mask: 0x0fef0070, .value: 0x01a00020, ARMvAll, .encoding: eEncodingA1, No_VFP, .size: eSize32,
13024 .callback: &EmulateInstructionARM::EmulateLSRImm, .name: "lsr{s}<c> <Rd>, <Rm>, #imm"},
13025 // lsr (register)
13026 {.mask: 0x0fef00f0, .value: 0x01a00050, ARMvAll, .encoding: eEncodingA1, No_VFP, .size: eSize32,
13027 .callback: &EmulateInstructionARM::EmulateLSRReg, .name: "lsr{s}<c> <Rd>, <Rn>, <Rm>"},
13028 // rrx is a special case encoding of ror (immediate)
13029 {.mask: 0x0fef0ff0, .value: 0x01a00060, ARMvAll, .encoding: eEncodingA1, No_VFP, .size: eSize32,
13030 .callback: &EmulateInstructionARM::EmulateRRX, .name: "rrx{s}<c> <Rd>, <Rm>"},
13031 // ror (immediate)
13032 {.mask: 0x0fef0070, .value: 0x01a00060, ARMvAll, .encoding: eEncodingA1, No_VFP, .size: eSize32,
13033 .callback: &EmulateInstructionARM::EmulateRORImm, .name: "ror{s}<c> <Rd>, <Rm>, #imm"},
13034 // ror (register)
13035 {.mask: 0x0fef00f0, .value: 0x01a00070, ARMvAll, .encoding: eEncodingA1, No_VFP, .size: eSize32,
13036 .callback: &EmulateInstructionARM::EmulateRORReg, .name: "ror{s}<c> <Rd>, <Rn>, <Rm>"},
13037 // mul
13038 {.mask: 0x0fe000f0, .value: 0x00000090, ARMvAll, .encoding: eEncodingA1, No_VFP, .size: eSize32,
13039 .callback: &EmulateInstructionARM::EmulateMUL, .name: "mul{s}<c> <Rd>,<R>,<Rm>"},
13040
13041 // subs pc, lr and related instructions
13042 {.mask: 0x0e10f000, .value: 0x0210f000, ARMvAll, .encoding: eEncodingA1, No_VFP, .size: eSize32,
13043 .callback: &EmulateInstructionARM::EmulateSUBSPcLrEtc,
13044 .name: "<opc>S<c> PC,#<const> | <Rn>,#<const>"},
13045 {.mask: 0x0e10f010, .value: 0x0010f000, ARMvAll, .encoding: eEncodingA2, No_VFP, .size: eSize32,
13046 .callback: &EmulateInstructionARM::EmulateSUBSPcLrEtc,
13047 .name: "<opc>S<c> PC,<Rn>,<Rm{,<shift>}"},
13048
13049 // Load instructions
13050 {.mask: 0x0fd00000, .value: 0x08900000, ARMvAll, .encoding: eEncodingA1, No_VFP, .size: eSize32,
13051 .callback: &EmulateInstructionARM::EmulateLDM, .name: "ldm<c> <Rn>{!} <registers>"},
13052 {.mask: 0x0fd00000, .value: 0x08100000, ARMvAll, .encoding: eEncodingA1, No_VFP, .size: eSize32,
13053 .callback: &EmulateInstructionARM::EmulateLDMDA, .name: "ldmda<c> <Rn>{!} <registers>"},
13054 {.mask: 0x0fd00000, .value: 0x09100000, ARMvAll, .encoding: eEncodingA1, No_VFP, .size: eSize32,
13055 .callback: &EmulateInstructionARM::EmulateLDMDB, .name: "ldmdb<c> <Rn>{!} <registers>"},
13056 {.mask: 0x0fd00000, .value: 0x09900000, ARMvAll, .encoding: eEncodingA1, No_VFP, .size: eSize32,
13057 .callback: &EmulateInstructionARM::EmulateLDMIB, .name: "ldmib<c> <Rn<{!} <registers>"},
13058 {.mask: 0x0e500000, .value: 0x04100000, ARMvAll, .encoding: eEncodingA1, No_VFP, .size: eSize32,
13059 .callback: &EmulateInstructionARM::EmulateLDRImmediateARM,
13060 .name: "ldr<c> <Rt> [<Rn> {#+/-<imm12>}]"},
13061 {.mask: 0x0e500010, .value: 0x06100000, ARMvAll, .encoding: eEncodingA1, No_VFP, .size: eSize32,
13062 .callback: &EmulateInstructionARM::EmulateLDRRegister,
13063 .name: "ldr<c> <Rt> [<Rn> +/-<Rm> {<shift>}] {!}"},
13064 {.mask: 0x0e5f0000, .value: 0x045f0000, ARMvAll, .encoding: eEncodingA1, No_VFP, .size: eSize32,
13065 .callback: &EmulateInstructionARM::EmulateLDRBLiteral, .name: "ldrb<c> <Rt>, [...]"},
13066 {.mask: 0xfe500010, .value: 0x06500000, ARMvAll, .encoding: eEncodingA1, No_VFP, .size: eSize32,
13067 .callback: &EmulateInstructionARM::EmulateLDRBRegister,
13068 .name: "ldrb<c> <Rt>, [<Rn>,+/-<Rm>{, <shift>}]{!}"},
13069 {.mask: 0x0e5f00f0, .value: 0x005f00b0, ARMvAll, .encoding: eEncodingA1, No_VFP, .size: eSize32,
13070 .callback: &EmulateInstructionARM::EmulateLDRHLiteral, .name: "ldrh<c> <Rt>, <label>"},
13071 {.mask: 0x0e5000f0, .value: 0x001000b0, ARMvAll, .encoding: eEncodingA1, No_VFP, .size: eSize32,
13072 .callback: &EmulateInstructionARM::EmulateLDRHRegister,
13073 .name: "ldrh<c> <Rt>,[<Rn>,+/-<Rm>]{!}"},
13074 {.mask: 0x0e5000f0, .value: 0x005000d0, ARMvAll, .encoding: eEncodingA1, No_VFP, .size: eSize32,
13075 .callback: &EmulateInstructionARM::EmulateLDRSBImmediate,
13076 .name: "ldrsb<c> <Rt>, [<Rn>{,#+/-<imm8>}]"},
13077 {.mask: 0x0e5f00f0, .value: 0x005f00d0, ARMvAll, .encoding: eEncodingA1, No_VFP, .size: eSize32,
13078 .callback: &EmulateInstructionARM::EmulateLDRSBLiteral, .name: "ldrsb<c> <Rt> <label>"},
13079 {.mask: 0x0e5000f0, .value: 0x001000d0, ARMvAll, .encoding: eEncodingA1, No_VFP, .size: eSize32,
13080 .callback: &EmulateInstructionARM::EmulateLDRSBRegister,
13081 .name: "ldrsb<c> <Rt>,[<Rn>,+/-<Rm>]{!}"},
13082 {.mask: 0x0e5000f0, .value: 0x005000f0, ARMvAll, .encoding: eEncodingA1, No_VFP, .size: eSize32,
13083 .callback: &EmulateInstructionARM::EmulateLDRSHImmediate,
13084 .name: "ldrsh<c> <Rt>,[<Rn>{,#+/-<imm8>}]"},
13085 {.mask: 0x0e5f00f0, .value: 0x005f00f0, ARMvAll, .encoding: eEncodingA1, No_VFP, .size: eSize32,
13086 .callback: &EmulateInstructionARM::EmulateLDRSHLiteral, .name: "ldrsh<c> <Rt>,<label>"},
13087 {.mask: 0x0e5000f0, .value: 0x001000f0, ARMvAll, .encoding: eEncodingA1, No_VFP, .size: eSize32,
13088 .callback: &EmulateInstructionARM::EmulateLDRSHRegister,
13089 .name: "ldrsh<c> <Rt>,[<Rn>,+/-<Rm>]{!}"},
13090 {.mask: 0x0e5000f0, .value: 0x004000d0, ARMV5TE_ABOVE, .encoding: eEncodingA1, No_VFP, .size: eSize32,
13091 .callback: &EmulateInstructionARM::EmulateLDRDImmediate,
13092 .name: "ldrd<c> <Rt>, <Rt2>, [<Rn>,#+/-<imm8>]!"},
13093 {.mask: 0x0e500ff0, .value: 0x000000d0, ARMV5TE_ABOVE, .encoding: eEncodingA1, No_VFP, .size: eSize32,
13094 .callback: &EmulateInstructionARM::EmulateLDRDRegister,
13095 .name: "ldrd<c> <Rt>, <Rt2>, [<Rn>, +/-<Rm>]{!}"},
13096 {.mask: 0x0e100f00, .value: 0x0c100b00, ARMvAll, .encoding: eEncodingA1, VFPv2_ABOVE, .size: eSize32,
13097 .callback: &EmulateInstructionARM::EmulateVLDM, .name: "vldm{mode}<c> <Rn>{!}, <list>"},
13098 {.mask: 0x0e100f00, .value: 0x0c100a00, ARMvAll, .encoding: eEncodingA2, VFPv2v3, .size: eSize32,
13099 .callback: &EmulateInstructionARM::EmulateVLDM, .name: "vldm{mode}<c> <Rn>{!}, <list>"},
13100 {.mask: 0x0f300f00, .value: 0x0d100b00, ARMvAll, .encoding: eEncodingA1, VFPv2_ABOVE, .size: eSize32,
13101 .callback: &EmulateInstructionARM::EmulateVLDR, .name: "vldr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},
13102 {.mask: 0x0f300f00, .value: 0x0d100a00, ARMvAll, .encoding: eEncodingA2, VFPv2v3, .size: eSize32,
13103 .callback: &EmulateInstructionARM::EmulateVLDR, .name: "vldr<c> <Sd>, [<Rn>{,#+/-<imm>}]"},
13104 {.mask: 0xffb00000, .value: 0xf4200000, ARMvAll, .encoding: eEncodingA1, AdvancedSIMD, .size: eSize32,
13105 .callback: &EmulateInstructionARM::EmulateVLD1Multiple,
13106 .name: "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
13107 {.mask: 0xffb00300, .value: 0xf4a00000, ARMvAll, .encoding: eEncodingA1, AdvancedSIMD, .size: eSize32,
13108 .callback: &EmulateInstructionARM::EmulateVLD1Single,
13109 .name: "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
13110 {.mask: 0xffb00f00, .value: 0xf4a00c00, ARMvAll, .encoding: eEncodingA1, AdvancedSIMD, .size: eSize32,
13111 .callback: &EmulateInstructionARM::EmulateVLD1SingleAll,
13112 .name: "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
13113
13114 // Store instructions
13115 {.mask: 0x0fd00000, .value: 0x08800000, ARMvAll, .encoding: eEncodingA1, No_VFP, .size: eSize32,
13116 .callback: &EmulateInstructionARM::EmulateSTM, .name: "stm<c> <Rn>{!} <registers>"},
13117 {.mask: 0x0fd00000, .value: 0x08000000, ARMvAll, .encoding: eEncodingA1, No_VFP, .size: eSize32,
13118 .callback: &EmulateInstructionARM::EmulateSTMDA, .name: "stmda<c> <Rn>{!} <registers>"},
13119 {.mask: 0x0fd00000, .value: 0x09000000, ARMvAll, .encoding: eEncodingA1, No_VFP, .size: eSize32,
13120 .callback: &EmulateInstructionARM::EmulateSTMDB, .name: "stmdb<c> <Rn>{!} <registers>"},
13121 {.mask: 0x0fd00000, .value: 0x09800000, ARMvAll, .encoding: eEncodingA1, No_VFP, .size: eSize32,
13122 .callback: &EmulateInstructionARM::EmulateSTMIB, .name: "stmib<c> <Rn>{!} <registers>"},
13123 {.mask: 0x0e500010, .value: 0x06000000, ARMvAll, .encoding: eEncodingA1, No_VFP, .size: eSize32,
13124 .callback: &EmulateInstructionARM::EmulateSTRRegister,
13125 .name: "str<c> <Rt> [<Rn> +/-<Rm> {<shift>}]{!}"},
13126 {.mask: 0x0e5000f0, .value: 0x000000b0, ARMvAll, .encoding: eEncodingA1, No_VFP, .size: eSize32,
13127 .callback: &EmulateInstructionARM::EmulateSTRHRegister,
13128 .name: "strh<c> <Rt>,[<Rn>,+/-<Rm>[{!}"},
13129 {.mask: 0x0ff00ff0, .value: 0x01800f90, ARMV6_ABOVE, .encoding: eEncodingA1, No_VFP, .size: eSize32,
13130 .callback: &EmulateInstructionARM::EmulateSTREX, .name: "strex<c> <Rd>, <Rt>, [<Rn>]"},
13131 {.mask: 0x0e500000, .value: 0x04400000, ARMvAll, .encoding: eEncodingA1, No_VFP, .size: eSize32,
13132 .callback: &EmulateInstructionARM::EmulateSTRBImmARM,
13133 .name: "strb<c> <Rt>,[<Rn>,#+/-<imm12>]!"},
13134 {.mask: 0x0e500000, .value: 0x04000000, ARMvAll, .encoding: eEncodingA1, No_VFP, .size: eSize32,
13135 .callback: &EmulateInstructionARM::EmulateSTRImmARM,
13136 .name: "str<c> <Rt>,[<Rn>,#+/-<imm12>]!"},
13137 {.mask: 0x0e5000f0, .value: 0x004000f0, ARMV5TE_ABOVE, .encoding: eEncodingA1, No_VFP, .size: eSize32,
13138 .callback: &EmulateInstructionARM::EmulateSTRDImm,
13139 .name: "strd<c> <Rt>, <Rt2>, [<Rn> #+/-<imm8>]!"},
13140 {.mask: 0x0e500ff0, .value: 0x000000f0, ARMV5TE_ABOVE, .encoding: eEncodingA1, No_VFP, .size: eSize32,
13141 .callback: &EmulateInstructionARM::EmulateSTRDReg,
13142 .name: "strd<c> <Rt>, <Rt2>, [<Rn>, +/-<Rm>]{!}"},
13143 {.mask: 0x0e100f00, .value: 0x0c000b00, ARMvAll, .encoding: eEncodingA1, VFPv2_ABOVE, .size: eSize32,
13144 .callback: &EmulateInstructionARM::EmulateVSTM, .name: "vstm{mode}<c> <Rn>{!} <list>"},
13145 {.mask: 0x0e100f00, .value: 0x0c000a00, ARMvAll, .encoding: eEncodingA2, VFPv2v3, .size: eSize32,
13146 .callback: &EmulateInstructionARM::EmulateVSTM, .name: "vstm{mode}<c> <Rn>{!} <list>"},
13147 {.mask: 0x0f300f00, .value: 0x0d000b00, ARMvAll, .encoding: eEncodingA1, VFPv2_ABOVE, .size: eSize32,
13148 .callback: &EmulateInstructionARM::EmulateVSTR, .name: "vstr<c> <Dd> [<Rn>{,#+/-<imm>}]"},
13149 {.mask: 0x0f300f00, .value: 0x0d000a00, ARMvAll, .encoding: eEncodingA2, VFPv2v3, .size: eSize32,
13150 .callback: &EmulateInstructionARM::EmulateVSTR, .name: "vstr<c> <Sd> [<Rn>{,#+/-<imm>}]"},
13151 {.mask: 0xffb00000, .value: 0xf4000000, ARMvAll, .encoding: eEncodingA1, AdvancedSIMD, .size: eSize32,
13152 .callback: &EmulateInstructionARM::EmulateVST1Multiple,
13153 .name: "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
13154 {.mask: 0xffb00300, .value: 0xf4800000, ARMvAll, .encoding: eEncodingA1, AdvancedSIMD, .size: eSize32,
13155 .callback: &EmulateInstructionARM::EmulateVST1Single,
13156 .name: "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
13157
13158 // Other instructions
13159 {.mask: 0x0fff00f0, .value: 0x06af00f0, ARMV6_ABOVE, .encoding: eEncodingA1, No_VFP, .size: eSize32,
13160 .callback: &EmulateInstructionARM::EmulateSXTB, .name: "sxtb<c> <Rd>,<Rm>{,<rotation>}"},
13161 {.mask: 0x0fff00f0, .value: 0x06bf0070, ARMV6_ABOVE, .encoding: eEncodingA1, No_VFP, .size: eSize32,
13162 .callback: &EmulateInstructionARM::EmulateSXTH, .name: "sxth<c> <Rd>,<Rm>{,<rotation>}"},
13163 {.mask: 0x0fff00f0, .value: 0x06ef0070, ARMV6_ABOVE, .encoding: eEncodingA1, No_VFP, .size: eSize32,
13164 .callback: &EmulateInstructionARM::EmulateUXTB, .name: "uxtb<c> <Rd>,<Rm>{,<rotation>}"},
13165 {.mask: 0x0fff00f0, .value: 0x06ff0070, ARMV6_ABOVE, .encoding: eEncodingA1, No_VFP, .size: eSize32,
13166 .callback: &EmulateInstructionARM::EmulateUXTH, .name: "uxth<c> <Rd>,<Rm>{,<rotation>}"},
13167 {.mask: 0xfe500000, .value: 0xf8100000, ARMV6_ABOVE, .encoding: eEncodingA1, No_VFP, .size: eSize32,
13168 .callback: &EmulateInstructionARM::EmulateRFE, .name: "rfe{<amode>} <Rn>{!}"}
13169
13170 };
13171 static const size_t k_num_arm_opcodes = std::size(g_arm_opcodes);
13172
13173 for (size_t i = 0; i < k_num_arm_opcodes; ++i) {
13174 if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value &&
13175 (g_arm_opcodes[i].variants & arm_isa) != 0)
13176 return &g_arm_opcodes[i];
13177 }
13178 return nullptr;
13179}
13180
13181EmulateInstructionARM::ARMOpcode *
13182EmulateInstructionARM::GetThumbOpcodeForInstruction(const uint32_t opcode,
13183 uint32_t arm_isa) {
13184
13185 static ARMOpcode g_thumb_opcodes[] = {
13186 // Prologue instructions
13187
13188 // push register(s)
13189 {.mask: 0xfffffe00, .value: 0x0000b400, ARMvAll, .encoding: eEncodingT1, No_VFP, .size: eSize16,
13190 .callback: &EmulateInstructionARM::EmulatePUSH, .name: "push <registers>"},
13191 {.mask: 0xffff0000, .value: 0xe92d0000, ARMV6T2_ABOVE, .encoding: eEncodingT2, No_VFP, .size: eSize32,
13192 .callback: &EmulateInstructionARM::EmulatePUSH, .name: "push.w <registers>"},
13193 {.mask: 0xffff0fff, .value: 0xf84d0d04, ARMV6T2_ABOVE, .encoding: eEncodingT3, No_VFP, .size: eSize32,
13194 .callback: &EmulateInstructionARM::EmulatePUSH, .name: "push.w <register>"},
13195
13196 // set r7 to point to a stack offset
13197 {.mask: 0xffffff00, .value: 0x0000af00, ARMvAll, .encoding: eEncodingT1, No_VFP, .size: eSize16,
13198 .callback: &EmulateInstructionARM::EmulateADDRdSPImm, .name: "add r7, sp, #imm"},
13199 // copy the stack pointer to r7
13200 {.mask: 0xffffffff, .value: 0x0000466f, ARMvAll, .encoding: eEncodingT1, No_VFP, .size: eSize16,
13201 .callback: &EmulateInstructionARM::EmulateMOVRdSP, .name: "mov r7, sp"},
13202 // move from high register to low register (comes after "mov r7, sp" to
13203 // resolve ambiguity)
13204 {.mask: 0xffffffc0, .value: 0x00004640, ARMvAll, .encoding: eEncodingT1, No_VFP, .size: eSize16,
13205 .callback: &EmulateInstructionARM::EmulateMOVLowHigh, .name: "mov r0-r7, r8-r15"},
13206
13207 // PC-relative load into register (see also EmulateADDSPRm)
13208 {.mask: 0xfffff800, .value: 0x00004800, ARMvAll, .encoding: eEncodingT1, No_VFP, .size: eSize16,
13209 .callback: &EmulateInstructionARM::EmulateLDRRtPCRelative, .name: "ldr <Rt>, [PC, #imm]"},
13210
13211 // adjust the stack pointer
13212 {.mask: 0xffffff87, .value: 0x00004485, ARMvAll, .encoding: eEncodingT2, No_VFP, .size: eSize16,
13213 .callback: &EmulateInstructionARM::EmulateADDSPRm, .name: "add sp, <Rm>"},
13214 {.mask: 0xffffff80, .value: 0x0000b080, ARMvAll, .encoding: eEncodingT1, No_VFP, .size: eSize16,
13215 .callback: &EmulateInstructionARM::EmulateSUBSPImm, .name: "sub sp, sp, #imm"},
13216 {.mask: 0xfbef8f00, .value: 0xf1ad0d00, ARMV6T2_ABOVE, .encoding: eEncodingT2, No_VFP, .size: eSize32,
13217 .callback: &EmulateInstructionARM::EmulateSUBSPImm, .name: "sub.w sp, sp, #<const>"},
13218 {.mask: 0xfbff8f00, .value: 0xf2ad0d00, ARMV6T2_ABOVE, .encoding: eEncodingT3, No_VFP, .size: eSize32,
13219 .callback: &EmulateInstructionARM::EmulateSUBSPImm, .name: "subw sp, sp, #imm12"},
13220 {.mask: 0xffef8000, .value: 0xebad0000, ARMV6T2_ABOVE, .encoding: eEncodingT1, No_VFP, .size: eSize32,
13221 .callback: &EmulateInstructionARM::EmulateSUBSPReg,
13222 .name: "sub{s}<c> <Rd>, sp, <Rm>{,<shift>}"},
13223
13224 // vector push consecutive extension register(s)
13225 {.mask: 0xffbf0f00, .value: 0xed2d0b00, ARMV6T2_ABOVE, .encoding: eEncodingT1, No_VFP, .size: eSize32,
13226 .callback: &EmulateInstructionARM::EmulateVPUSH, .name: "vpush.64 <list>"},
13227 {.mask: 0xffbf0f00, .value: 0xed2d0a00, ARMV6T2_ABOVE, .encoding: eEncodingT2, No_VFP, .size: eSize32,
13228 .callback: &EmulateInstructionARM::EmulateVPUSH, .name: "vpush.32 <list>"},
13229
13230 // Epilogue instructions
13231
13232 {.mask: 0xfffff800, .value: 0x0000a800, ARMV4T_ABOVE, .encoding: eEncodingT1, No_VFP, .size: eSize16,
13233 .callback: &EmulateInstructionARM::EmulateADDSPImm, .name: "add<c> <Rd>, sp, #imm"},
13234 {.mask: 0xffffff80, .value: 0x0000b000, ARMvAll, .encoding: eEncodingT2, No_VFP, .size: eSize16,
13235 .callback: &EmulateInstructionARM::EmulateADDSPImm, .name: "add sp, #imm"},
13236 {.mask: 0xfffffe00, .value: 0x0000bc00, ARMvAll, .encoding: eEncodingT1, No_VFP, .size: eSize16,
13237 .callback: &EmulateInstructionARM::EmulatePOP, .name: "pop <registers>"},
13238 {.mask: 0xffff0000, .value: 0xe8bd0000, ARMV6T2_ABOVE, .encoding: eEncodingT2, No_VFP, .size: eSize32,
13239 .callback: &EmulateInstructionARM::EmulatePOP, .name: "pop.w <registers>"},
13240 {.mask: 0xffff0fff, .value: 0xf85d0d04, ARMV6T2_ABOVE, .encoding: eEncodingT3, No_VFP, .size: eSize32,
13241 .callback: &EmulateInstructionARM::EmulatePOP, .name: "pop.w <register>"},
13242 {.mask: 0xffbf0f00, .value: 0xecbd0b00, ARMV6T2_ABOVE, .encoding: eEncodingT1, No_VFP, .size: eSize32,
13243 .callback: &EmulateInstructionARM::EmulateVPOP, .name: "vpop.64 <list>"},
13244 {.mask: 0xffbf0f00, .value: 0xecbd0a00, ARMV6T2_ABOVE, .encoding: eEncodingT2, No_VFP, .size: eSize32,
13245 .callback: &EmulateInstructionARM::EmulateVPOP, .name: "vpop.32 <list>"},
13246
13247 // Supervisor Call (previously Software Interrupt)
13248 {.mask: 0xffffff00, .value: 0x0000df00, ARMvAll, .encoding: eEncodingT1, No_VFP, .size: eSize16,
13249 .callback: &EmulateInstructionARM::EmulateSVC, .name: "svc #imm8"},
13250
13251 // If Then makes up to four following instructions conditional.
13252 // The next 5 opcode _must_ come before the if then instruction
13253 {.mask: 0xffffffff, .value: 0x0000bf00, ARMV6T2_ABOVE, .encoding: eEncodingT1, No_VFP, .size: eSize16,
13254 .callback: &EmulateInstructionARM::EmulateNop, .name: "nop"},
13255 {.mask: 0xffffffff, .value: 0x0000bf10, ARMV7_ABOVE, .encoding: eEncodingT1, No_VFP, .size: eSize16,
13256 .callback: &EmulateInstructionARM::EmulateNop, .name: "nop YIELD (yield hint)"},
13257 {.mask: 0xffffffff, .value: 0x0000bf20, ARMV7_ABOVE, .encoding: eEncodingT1, No_VFP, .size: eSize16,
13258 .callback: &EmulateInstructionARM::EmulateNop, .name: "nop WFE (wait for event hint)"},
13259 {.mask: 0xffffffff, .value: 0x0000bf30, ARMV7_ABOVE, .encoding: eEncodingT1, No_VFP, .size: eSize16,
13260 .callback: &EmulateInstructionARM::EmulateNop, .name: "nop WFI (wait for interrupt hint)"},
13261 {.mask: 0xffffffff, .value: 0x0000bf40, ARMV7_ABOVE, .encoding: eEncodingT1, No_VFP, .size: eSize16,
13262 .callback: &EmulateInstructionARM::EmulateNop, .name: "nop SEV (send event hint)"},
13263 {.mask: 0xffffff00, .value: 0x0000bf00, ARMV6T2_ABOVE, .encoding: eEncodingT1, No_VFP, .size: eSize16,
13264 .callback: &EmulateInstructionARM::EmulateIT, .name: "it{<x>{<y>{<z>}}} <firstcond>"},
13265
13266 // Branch instructions
13267 // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8".
13268 {.mask: 0xfffff000, .value: 0x0000d000, ARMvAll, .encoding: eEncodingT1, No_VFP, .size: eSize16,
13269 .callback: &EmulateInstructionARM::EmulateB, .name: "b<c> #imm8 (outside IT)"},
13270 {.mask: 0xfffff800, .value: 0x0000e000, ARMvAll, .encoding: eEncodingT2, No_VFP, .size: eSize16,
13271 .callback: &EmulateInstructionARM::EmulateB, .name: "b<c> #imm11 (outside or last in IT)"},
13272 {.mask: 0xf800d000, .value: 0xf0008000, ARMV6T2_ABOVE, .encoding: eEncodingT3, No_VFP, .size: eSize32,
13273 .callback: &EmulateInstructionARM::EmulateB, .name: "b<c>.w #imm8 (outside IT)"},
13274 {.mask: 0xf800d000, .value: 0xf0009000, ARMV6T2_ABOVE, .encoding: eEncodingT4, No_VFP, .size: eSize32,
13275 .callback: &EmulateInstructionARM::EmulateB,
13276 .name: "b<c>.w #imm8 (outside or last in IT)"},
13277 // J1 == J2 == 1
13278 {.mask: 0xf800d000, .value: 0xf000d000, ARMV4T_ABOVE, .encoding: eEncodingT1, No_VFP, .size: eSize32,
13279 .callback: &EmulateInstructionARM::EmulateBLXImmediate, .name: "bl <label>"},
13280 // J1 == J2 == 1
13281 {.mask: 0xf800d001, .value: 0xf000c000, ARMV5_ABOVE, .encoding: eEncodingT2, No_VFP, .size: eSize32,
13282 .callback: &EmulateInstructionARM::EmulateBLXImmediate, .name: "blx <label>"},
13283 {.mask: 0xffffff87, .value: 0x00004780, ARMV5_ABOVE, .encoding: eEncodingT1, No_VFP, .size: eSize16,
13284 .callback: &EmulateInstructionARM::EmulateBLXRm, .name: "blx <Rm>"},
13285 // for example, "bx lr"
13286 {.mask: 0xffffff87, .value: 0x00004700, ARMvAll, .encoding: eEncodingT1, No_VFP, .size: eSize32,
13287 .callback: &EmulateInstructionARM::EmulateBXRm, .name: "bx <Rm>"},
13288 // bxj
13289 {.mask: 0xfff0ffff, .value: 0xf3c08f00, ARMV5J_ABOVE, .encoding: eEncodingT1, No_VFP, .size: eSize32,
13290 .callback: &EmulateInstructionARM::EmulateBXJRm, .name: "bxj <Rm>"},
13291 // compare and branch
13292 {.mask: 0xfffff500, .value: 0x0000b100, ARMV6T2_ABOVE, .encoding: eEncodingT1, No_VFP, .size: eSize16,
13293 .callback: &EmulateInstructionARM::EmulateCB, .name: "cb{n}z <Rn>, <label>"},
13294 // table branch byte
13295 {.mask: 0xfff0fff0, .value: 0xe8d0f000, ARMV6T2_ABOVE, .encoding: eEncodingT1, No_VFP, .size: eSize32,
13296 .callback: &EmulateInstructionARM::EmulateTB, .name: "tbb<c> <Rn>, <Rm>"},
13297 // table branch halfword
13298 {.mask: 0xfff0fff0, .value: 0xe8d0f010, ARMV6T2_ABOVE, .encoding: eEncodingT1, No_VFP, .size: eSize32,
13299 .callback: &EmulateInstructionARM::EmulateTB, .name: "tbh<c> <Rn>, <Rm>, lsl #1"},
13300
13301 // Data-processing instructions
13302 // adc (immediate)
13303 {.mask: 0xfbe08000, .value: 0xf1400000, ARMV6T2_ABOVE, .encoding: eEncodingT1, No_VFP, .size: eSize32,
13304 .callback: &EmulateInstructionARM::EmulateADCImm, .name: "adc{s}<c> <Rd>, <Rn>, #<const>"},
13305 // adc (register)
13306 {.mask: 0xffffffc0, .value: 0x00004140, ARMvAll, .encoding: eEncodingT1, No_VFP, .size: eSize16,
13307 .callback: &EmulateInstructionARM::EmulateADCReg, .name: "adcs|adc<c> <Rdn>, <Rm>"},
13308 {.mask: 0xffe08000, .value: 0xeb400000, ARMV6T2_ABOVE, .encoding: eEncodingT2, No_VFP, .size: eSize32,
13309 .callback: &EmulateInstructionARM::EmulateADCReg,
13310 .name: "adc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
13311 // add (register)
13312 {.mask: 0xfffffe00, .value: 0x00001800, ARMvAll, .encoding: eEncodingT1, No_VFP, .size: eSize16,
13313 .callback: &EmulateInstructionARM::EmulateADDReg, .name: "adds|add<c> <Rd>, <Rn>, <Rm>"},
13314 // Make sure "add sp, <Rm>" comes before this instruction, so there's no
13315 // ambiguity decoding the two.
13316 {.mask: 0xffffff00, .value: 0x00004400, ARMvAll, .encoding: eEncodingT2, No_VFP, .size: eSize16,
13317 .callback: &EmulateInstructionARM::EmulateADDReg, .name: "add<c> <Rdn>, <Rm>"},
13318 // adr
13319 {.mask: 0xfffff800, .value: 0x0000a000, ARMvAll, .encoding: eEncodingT1, No_VFP, .size: eSize16,
13320 .callback: &EmulateInstructionARM::EmulateADR, .name: "add<c> <Rd>, PC, #<const>"},
13321 {.mask: 0xfbff8000, .value: 0xf2af0000, ARMV6T2_ABOVE, .encoding: eEncodingT2, No_VFP, .size: eSize32,
13322 .callback: &EmulateInstructionARM::EmulateADR, .name: "sub<c> <Rd>, PC, #<const>"},
13323 {.mask: 0xfbff8000, .value: 0xf20f0000, ARMV6T2_ABOVE, .encoding: eEncodingT3, No_VFP, .size: eSize32,
13324 .callback: &EmulateInstructionARM::EmulateADR, .name: "add<c> <Rd>, PC, #<const>"},
13325 // and (immediate)
13326 {.mask: 0xfbe08000, .value: 0xf0000000, ARMV6T2_ABOVE, .encoding: eEncodingT1, No_VFP, .size: eSize32,
13327 .callback: &EmulateInstructionARM::EmulateANDImm, .name: "and{s}<c> <Rd>, <Rn>, #<const>"},
13328 // and (register)
13329 {.mask: 0xffffffc0, .value: 0x00004000, ARMvAll, .encoding: eEncodingT1, No_VFP, .size: eSize16,
13330 .callback: &EmulateInstructionARM::EmulateANDReg, .name: "ands|and<c> <Rdn>, <Rm>"},
13331 {.mask: 0xffe08000, .value: 0xea000000, ARMV6T2_ABOVE, .encoding: eEncodingT2, No_VFP, .size: eSize32,
13332 .callback: &EmulateInstructionARM::EmulateANDReg,
13333 .name: "and{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
13334 // bic (immediate)
13335 {.mask: 0xfbe08000, .value: 0xf0200000, ARMV6T2_ABOVE, .encoding: eEncodingT1, No_VFP, .size: eSize32,
13336 .callback: &EmulateInstructionARM::EmulateBICImm, .name: "bic{s}<c> <Rd>, <Rn>, #<const>"},
13337 // bic (register)
13338 {.mask: 0xffffffc0, .value: 0x00004380, ARMvAll, .encoding: eEncodingT1, No_VFP, .size: eSize16,
13339 .callback: &EmulateInstructionARM::EmulateBICReg, .name: "bics|bic<c> <Rdn>, <Rm>"},
13340 {.mask: 0xffe08000, .value: 0xea200000, ARMV6T2_ABOVE, .encoding: eEncodingT2, No_VFP, .size: eSize32,
13341 .callback: &EmulateInstructionARM::EmulateBICReg,
13342 .name: "bic{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
13343 // eor (immediate)
13344 {.mask: 0xfbe08000, .value: 0xf0800000, ARMV6T2_ABOVE, .encoding: eEncodingT1, No_VFP, .size: eSize32,
13345 .callback: &EmulateInstructionARM::EmulateEORImm, .name: "eor{s}<c> <Rd>, <Rn>, #<const>"},
13346 // eor (register)
13347 {.mask: 0xffffffc0, .value: 0x00004040, ARMvAll, .encoding: eEncodingT1, No_VFP, .size: eSize16,
13348 .callback: &EmulateInstructionARM::EmulateEORReg, .name: "eors|eor<c> <Rdn>, <Rm>"},
13349 {.mask: 0xffe08000, .value: 0xea800000, ARMV6T2_ABOVE, .encoding: eEncodingT2, No_VFP, .size: eSize32,
13350 .callback: &EmulateInstructionARM::EmulateEORReg,
13351 .name: "eor{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
13352 // orr (immediate)
13353 {.mask: 0xfbe08000, .value: 0xf0400000, ARMV6T2_ABOVE, .encoding: eEncodingT1, No_VFP, .size: eSize32,
13354 .callback: &EmulateInstructionARM::EmulateORRImm, .name: "orr{s}<c> <Rd>, <Rn>, #<const>"},
13355 // orr (register)
13356 {.mask: 0xffffffc0, .value: 0x00004300, ARMvAll, .encoding: eEncodingT1, No_VFP, .size: eSize16,
13357 .callback: &EmulateInstructionARM::EmulateORRReg, .name: "orrs|orr<c> <Rdn>, <Rm>"},
13358 {.mask: 0xffe08000, .value: 0xea400000, ARMV6T2_ABOVE, .encoding: eEncodingT2, No_VFP, .size: eSize32,
13359 .callback: &EmulateInstructionARM::EmulateORRReg,
13360 .name: "orr{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
13361 // rsb (immediate)
13362 {.mask: 0xffffffc0, .value: 0x00004240, ARMvAll, .encoding: eEncodingT1, No_VFP, .size: eSize16,
13363 .callback: &EmulateInstructionARM::EmulateRSBImm, .name: "rsbs|rsb<c> <Rd>, <Rn>, #0"},
13364 {.mask: 0xfbe08000, .value: 0xf1c00000, ARMV6T2_ABOVE, .encoding: eEncodingT2, No_VFP, .size: eSize32,
13365 .callback: &EmulateInstructionARM::EmulateRSBImm,
13366 .name: "rsb{s}<c>.w <Rd>, <Rn>, #<const>"},
13367 // rsb (register)
13368 {.mask: 0xffe08000, .value: 0xea400000, ARMV6T2_ABOVE, .encoding: eEncodingT1, No_VFP, .size: eSize32,
13369 .callback: &EmulateInstructionARM::EmulateRSBReg,
13370 .name: "rsb{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
13371 // sbc (immediate)
13372 {.mask: 0xfbe08000, .value: 0xf1600000, ARMV6T2_ABOVE, .encoding: eEncodingT1, No_VFP, .size: eSize32,
13373 .callback: &EmulateInstructionARM::EmulateSBCImm, .name: "sbc{s}<c> <Rd>, <Rn>, #<const>"},
13374 // sbc (register)
13375 {.mask: 0xffffffc0, .value: 0x00004180, ARMvAll, .encoding: eEncodingT1, No_VFP, .size: eSize16,
13376 .callback: &EmulateInstructionARM::EmulateSBCReg, .name: "sbcs|sbc<c> <Rdn>, <Rm>"},
13377 {.mask: 0xffe08000, .value: 0xeb600000, ARMV6T2_ABOVE, .encoding: eEncodingT2, No_VFP, .size: eSize32,
13378 .callback: &EmulateInstructionARM::EmulateSBCReg,
13379 .name: "sbc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
13380 // add (immediate, Thumb)
13381 {.mask: 0xfffffe00, .value: 0x00001c00, ARMV4T_ABOVE, .encoding: eEncodingT1, No_VFP, .size: eSize16,
13382 .callback: &EmulateInstructionARM::EmulateADDImmThumb,
13383 .name: "adds|add<c> <Rd>,<Rn>,#<imm3>"},
13384 {.mask: 0xfffff800, .value: 0x00003000, ARMV4T_ABOVE, .encoding: eEncodingT2, No_VFP, .size: eSize16,
13385 .callback: &EmulateInstructionARM::EmulateADDImmThumb, .name: "adds|add<c> <Rdn>,#<imm8>"},
13386 {.mask: 0xfbe08000, .value: 0xf1000000, ARMV6T2_ABOVE, .encoding: eEncodingT3, No_VFP, .size: eSize32,
13387 .callback: &EmulateInstructionARM::EmulateADDImmThumb,
13388 .name: "add{s}<c>.w <Rd>,<Rn>,#<const>"},
13389 {.mask: 0xfbf08000, .value: 0xf2000000, ARMV6T2_ABOVE, .encoding: eEncodingT4, No_VFP, .size: eSize32,
13390 .callback: &EmulateInstructionARM::EmulateADDImmThumb,
13391 .name: "addw<c> <Rd>,<Rn>,#<imm12>"},
13392 // sub (immediate, Thumb)
13393 {.mask: 0xfffffe00, .value: 0x00001e00, ARMvAll, .encoding: eEncodingT1, No_VFP, .size: eSize16,
13394 .callback: &EmulateInstructionARM::EmulateSUBImmThumb,
13395 .name: "subs|sub<c> <Rd>, <Rn> #imm3"},
13396 {.mask: 0xfffff800, .value: 0x00003800, ARMvAll, .encoding: eEncodingT2, No_VFP, .size: eSize16,
13397 .callback: &EmulateInstructionARM::EmulateSUBImmThumb, .name: "subs|sub<c> <Rdn>, #imm8"},
13398 {.mask: 0xfbe08000, .value: 0xf1a00000, ARMV6T2_ABOVE, .encoding: eEncodingT3, No_VFP, .size: eSize32,
13399 .callback: &EmulateInstructionARM::EmulateSUBImmThumb,
13400 .name: "sub{s}<c>.w <Rd>, <Rn>, #<const>"},
13401 {.mask: 0xfbf08000, .value: 0xf2a00000, ARMV6T2_ABOVE, .encoding: eEncodingT4, No_VFP, .size: eSize32,
13402 .callback: &EmulateInstructionARM::EmulateSUBImmThumb,
13403 .name: "subw<c> <Rd>, <Rn>, #imm12"},
13404 // sub (sp minus immediate)
13405 {.mask: 0xfbef8000, .value: 0xf1ad0000, ARMV6T2_ABOVE, .encoding: eEncodingT2, No_VFP, .size: eSize32,
13406 .callback: &EmulateInstructionARM::EmulateSUBSPImm, .name: "sub{s}.w <Rd>, sp, #<const>"},
13407 {.mask: 0xfbff8000, .value: 0xf2ad0000, ARMV6T2_ABOVE, .encoding: eEncodingT3, No_VFP, .size: eSize32,
13408 .callback: &EmulateInstructionARM::EmulateSUBSPImm, .name: "subw<c> <Rd>, sp, #imm12"},
13409 // sub (register)
13410 {.mask: 0xfffffe00, .value: 0x00001a00, ARMV4T_ABOVE, .encoding: eEncodingT1, No_VFP, .size: eSize16,
13411 .callback: &EmulateInstructionARM::EmulateSUBReg, .name: "subs|sub<c> <Rd>, <Rn>, <Rm>"},
13412 {.mask: 0xffe08000, .value: 0xeba00000, ARMV6T2_ABOVE, .encoding: eEncodingT2, No_VFP, .size: eSize32,
13413 .callback: &EmulateInstructionARM::EmulateSUBReg,
13414 .name: "sub{s}<c>.w <Rd>, <Rn>, <Rm>{,<shift>}"},
13415 // teq (immediate)
13416 {.mask: 0xfbf08f00, .value: 0xf0900f00, ARMV6T2_ABOVE, .encoding: eEncodingT1, No_VFP, .size: eSize32,
13417 .callback: &EmulateInstructionARM::EmulateTEQImm, .name: "teq<c> <Rn>, #<const>"},
13418 // teq (register)
13419 {.mask: 0xfff08f00, .value: 0xea900f00, ARMV6T2_ABOVE, .encoding: eEncodingT1, No_VFP, .size: eSize32,
13420 .callback: &EmulateInstructionARM::EmulateTEQReg, .name: "teq<c> <Rn>, <Rm> {,<shift>}"},
13421 // tst (immediate)
13422 {.mask: 0xfbf08f00, .value: 0xf0100f00, ARMV6T2_ABOVE, .encoding: eEncodingT1, No_VFP, .size: eSize32,
13423 .callback: &EmulateInstructionARM::EmulateTSTImm, .name: "tst<c> <Rn>, #<const>"},
13424 // tst (register)
13425 {.mask: 0xffffffc0, .value: 0x00004200, ARMvAll, .encoding: eEncodingT1, No_VFP, .size: eSize16,
13426 .callback: &EmulateInstructionARM::EmulateTSTReg, .name: "tst<c> <Rdn>, <Rm>"},
13427 {.mask: 0xfff08f00, .value: 0xea100f00, ARMV6T2_ABOVE, .encoding: eEncodingT2, No_VFP, .size: eSize32,
13428 .callback: &EmulateInstructionARM::EmulateTSTReg, .name: "tst<c>.w <Rn>, <Rm> {,<shift>}"},
13429
13430 // move from high register to high register
13431 {.mask: 0xffffff00, .value: 0x00004600, ARMvAll, .encoding: eEncodingT1, No_VFP, .size: eSize16,
13432 .callback: &EmulateInstructionARM::EmulateMOVRdRm, .name: "mov<c> <Rd>, <Rm>"},
13433 // move from low register to low register
13434 {.mask: 0xffffffc0, .value: 0x00000000, ARMvAll, .encoding: eEncodingT2, No_VFP, .size: eSize16,
13435 .callback: &EmulateInstructionARM::EmulateMOVRdRm, .name: "movs <Rd>, <Rm>"},
13436 // mov{s}<c>.w <Rd>, <Rm>
13437 {.mask: 0xffeff0f0, .value: 0xea4f0000, ARMV6T2_ABOVE, .encoding: eEncodingT3, No_VFP, .size: eSize32,
13438 .callback: &EmulateInstructionARM::EmulateMOVRdRm, .name: "mov{s}<c>.w <Rd>, <Rm>"},
13439 // move immediate
13440 {.mask: 0xfffff800, .value: 0x00002000, ARMvAll, .encoding: eEncodingT1, No_VFP, .size: eSize16,
13441 .callback: &EmulateInstructionARM::EmulateMOVRdImm, .name: "movs|mov<c> <Rd>, #imm8"},
13442 {.mask: 0xfbef8000, .value: 0xf04f0000, ARMV6T2_ABOVE, .encoding: eEncodingT2, No_VFP, .size: eSize32,
13443 .callback: &EmulateInstructionARM::EmulateMOVRdImm, .name: "mov{s}<c>.w <Rd>, #<const>"},
13444 {.mask: 0xfbf08000, .value: 0xf2400000, ARMV6T2_ABOVE, .encoding: eEncodingT3, No_VFP, .size: eSize32,
13445 .callback: &EmulateInstructionARM::EmulateMOVRdImm, .name: "movw<c> <Rd>,#<imm16>"},
13446 // mvn (immediate)
13447 {.mask: 0xfbef8000, .value: 0xf06f0000, ARMV6T2_ABOVE, .encoding: eEncodingT1, No_VFP, .size: eSize32,
13448 .callback: &EmulateInstructionARM::EmulateMVNImm, .name: "mvn{s} <Rd>, #<const>"},
13449 // mvn (register)
13450 {.mask: 0xffffffc0, .value: 0x000043c0, ARMvAll, .encoding: eEncodingT1, No_VFP, .size: eSize16,
13451 .callback: &EmulateInstructionARM::EmulateMVNReg, .name: "mvns|mvn<c> <Rd>, <Rm>"},
13452 {.mask: 0xffef8000, .value: 0xea6f0000, ARMV6T2_ABOVE, .encoding: eEncodingT2, No_VFP, .size: eSize32,
13453 .callback: &EmulateInstructionARM::EmulateMVNReg,
13454 .name: "mvn{s}<c>.w <Rd>, <Rm> {,<shift>}"},
13455 // cmn (immediate)
13456 {.mask: 0xfbf08f00, .value: 0xf1100f00, ARMV6T2_ABOVE, .encoding: eEncodingT1, No_VFP, .size: eSize32,
13457 .callback: &EmulateInstructionARM::EmulateCMNImm, .name: "cmn<c> <Rn>, #<const>"},
13458 // cmn (register)
13459 {.mask: 0xffffffc0, .value: 0x000042c0, ARMvAll, .encoding: eEncodingT1, No_VFP, .size: eSize16,
13460 .callback: &EmulateInstructionARM::EmulateCMNReg, .name: "cmn<c> <Rn>, <Rm>"},
13461 {.mask: 0xfff08f00, .value: 0xeb100f00, ARMV6T2_ABOVE, .encoding: eEncodingT2, No_VFP, .size: eSize32,
13462 .callback: &EmulateInstructionARM::EmulateCMNReg, .name: "cmn<c> <Rn>, <Rm> {,<shift>}"},
13463 // cmp (immediate)
13464 {.mask: 0xfffff800, .value: 0x00002800, ARMvAll, .encoding: eEncodingT1, No_VFP, .size: eSize16,
13465 .callback: &EmulateInstructionARM::EmulateCMPImm, .name: "cmp<c> <Rn>, #imm8"},
13466 {.mask: 0xfbf08f00, .value: 0xf1b00f00, ARMV6T2_ABOVE, .encoding: eEncodingT2, No_VFP, .size: eSize32,
13467 .callback: &EmulateInstructionARM::EmulateCMPImm, .name: "cmp<c>.w <Rn>, #<const>"},
13468 // cmp (register) (Rn and Rm both from r0-r7)
13469 {.mask: 0xffffffc0, .value: 0x00004280, ARMvAll, .encoding: eEncodingT1, No_VFP, .size: eSize16,
13470 .callback: &EmulateInstructionARM::EmulateCMPReg, .name: "cmp<c> <Rn>, <Rm>"},
13471 // cmp (register) (Rn and Rm not both from r0-r7)
13472 {.mask: 0xffffff00, .value: 0x00004500, ARMvAll, .encoding: eEncodingT2, No_VFP, .size: eSize16,
13473 .callback: &EmulateInstructionARM::EmulateCMPReg, .name: "cmp<c> <Rn>, <Rm>"},
13474 {.mask: 0xfff08f00, .value: 0xebb00f00, ARMvAll, .encoding: eEncodingT3, No_VFP, .size: eSize16,
13475 .callback: &EmulateInstructionARM::EmulateCMPReg,
13476 .name: "cmp<c>.w <Rn>, <Rm> {, <shift>}"},
13477 // asr (immediate)
13478 {.mask: 0xfffff800, .value: 0x00001000, ARMvAll, .encoding: eEncodingT1, No_VFP, .size: eSize16,
13479 .callback: &EmulateInstructionARM::EmulateASRImm, .name: "asrs|asr<c> <Rd>, <Rm>, #imm"},
13480 {.mask: 0xffef8030, .value: 0xea4f0020, ARMV6T2_ABOVE, .encoding: eEncodingT2, No_VFP, .size: eSize32,
13481 .callback: &EmulateInstructionARM::EmulateASRImm, .name: "asr{s}<c>.w <Rd>, <Rm>, #imm"},
13482 // asr (register)
13483 {.mask: 0xffffffc0, .value: 0x00004100, ARMvAll, .encoding: eEncodingT1, No_VFP, .size: eSize16,
13484 .callback: &EmulateInstructionARM::EmulateASRReg, .name: "asrs|asr<c> <Rdn>, <Rm>"},
13485 {.mask: 0xffe0f0f0, .value: 0xfa40f000, ARMV6T2_ABOVE, .encoding: eEncodingT2, No_VFP, .size: eSize32,
13486 .callback: &EmulateInstructionARM::EmulateASRReg, .name: "asr{s}<c>.w <Rd>, <Rn>, <Rm>"},
13487 // lsl (immediate)
13488 {.mask: 0xfffff800, .value: 0x00000000, ARMvAll, .encoding: eEncodingT1, No_VFP, .size: eSize16,
13489 .callback: &EmulateInstructionARM::EmulateLSLImm, .name: "lsls|lsl<c> <Rd>, <Rm>, #imm"},
13490 {.mask: 0xffef8030, .value: 0xea4f0000, ARMV6T2_ABOVE, .encoding: eEncodingT2, No_VFP, .size: eSize32,
13491 .callback: &EmulateInstructionARM::EmulateLSLImm, .name: "lsl{s}<c>.w <Rd>, <Rm>, #imm"},
13492 // lsl (register)
13493 {.mask: 0xffffffc0, .value: 0x00004080, ARMvAll, .encoding: eEncodingT1, No_VFP, .size: eSize16,
13494 .callback: &EmulateInstructionARM::EmulateLSLReg, .name: "lsls|lsl<c> <Rdn>, <Rm>"},
13495 {.mask: 0xffe0f0f0, .value: 0xfa00f000, ARMV6T2_ABOVE, .encoding: eEncodingT2, No_VFP, .size: eSize32,
13496 .callback: &EmulateInstructionARM::EmulateLSLReg, .name: "lsl{s}<c>.w <Rd>, <Rn>, <Rm>"},
13497 // lsr (immediate)
13498 {.mask: 0xfffff800, .value: 0x00000800, ARMvAll, .encoding: eEncodingT1, No_VFP, .size: eSize16,
13499 .callback: &EmulateInstructionARM::EmulateLSRImm, .name: "lsrs|lsr<c> <Rd>, <Rm>, #imm"},
13500 {.mask: 0xffef8030, .value: 0xea4f0010, ARMV6T2_ABOVE, .encoding: eEncodingT2, No_VFP, .size: eSize32,
13501 .callback: &EmulateInstructionARM::EmulateLSRImm, .name: "lsr{s}<c>.w <Rd>, <Rm>, #imm"},
13502 // lsr (register)
13503 {.mask: 0xffffffc0, .value: 0x000040c0, ARMvAll, .encoding: eEncodingT1, No_VFP, .size: eSize16,
13504 .callback: &EmulateInstructionARM::EmulateLSRReg, .name: "lsrs|lsr<c> <Rdn>, <Rm>"},
13505 {.mask: 0xffe0f0f0, .value: 0xfa20f000, ARMV6T2_ABOVE, .encoding: eEncodingT2, No_VFP, .size: eSize32,
13506 .callback: &EmulateInstructionARM::EmulateLSRReg, .name: "lsr{s}<c>.w <Rd>, <Rn>, <Rm>"},
13507 // rrx is a special case encoding of ror (immediate)
13508 {.mask: 0xffeff0f0, .value: 0xea4f0030, ARMV6T2_ABOVE, .encoding: eEncodingT1, No_VFP, .size: eSize32,
13509 .callback: &EmulateInstructionARM::EmulateRRX, .name: "rrx{s}<c>.w <Rd>, <Rm>"},
13510 // ror (immediate)
13511 {.mask: 0xffef8030, .value: 0xea4f0030, ARMV6T2_ABOVE, .encoding: eEncodingT1, No_VFP, .size: eSize32,
13512 .callback: &EmulateInstructionARM::EmulateRORImm, .name: "ror{s}<c>.w <Rd>, <Rm>, #imm"},
13513 // ror (register)
13514 {.mask: 0xffffffc0, .value: 0x000041c0, ARMvAll, .encoding: eEncodingT1, No_VFP, .size: eSize16,
13515 .callback: &EmulateInstructionARM::EmulateRORReg, .name: "rors|ror<c> <Rdn>, <Rm>"},
13516 {.mask: 0xffe0f0f0, .value: 0xfa60f000, ARMV6T2_ABOVE, .encoding: eEncodingT2, No_VFP, .size: eSize32,
13517 .callback: &EmulateInstructionARM::EmulateRORReg, .name: "ror{s}<c>.w <Rd>, <Rn>, <Rm>"},
13518 // mul
13519 {.mask: 0xffffffc0, .value: 0x00004340, ARMV4T_ABOVE, .encoding: eEncodingT1, No_VFP, .size: eSize16,
13520 .callback: &EmulateInstructionARM::EmulateMUL, .name: "muls <Rdm>,<Rn>,<Rdm>"},
13521 // mul
13522 {.mask: 0xfff0f0f0, .value: 0xfb00f000, ARMV6T2_ABOVE, .encoding: eEncodingT2, No_VFP, .size: eSize32,
13523 .callback: &EmulateInstructionARM::EmulateMUL, .name: "mul<c> <Rd>,<Rn>,<Rm>"},
13524
13525 // subs pc, lr and related instructions
13526 {.mask: 0xffffff00, .value: 0xf3de8f00, ARMV6T2_ABOVE, .encoding: eEncodingT1, No_VFP, .size: eSize32,
13527 .callback: &EmulateInstructionARM::EmulateSUBSPcLrEtc, .name: "SUBS<c> PC, LR, #<imm8>"},
13528
13529 // RFE instructions *** IMPORTANT *** THESE MUST BE LISTED **BEFORE** THE
13530 // LDM.. Instructions in this table;
13531 // otherwise the wrong instructions will be selected.
13532
13533 {.mask: 0xffd0ffff, .value: 0xe810c000, ARMV6T2_ABOVE, .encoding: eEncodingT1, No_VFP, .size: eSize32,
13534 .callback: &EmulateInstructionARM::EmulateRFE, .name: "rfedb<c> <Rn>{!}"},
13535 {.mask: 0xffd0ffff, .value: 0xe990c000, ARMV6T2_ABOVE, .encoding: eEncodingT2, No_VFP, .size: eSize32,
13536 .callback: &EmulateInstructionARM::EmulateRFE, .name: "rfe{ia}<c> <Rn>{!}"},
13537
13538 // Load instructions
13539 {.mask: 0xfffff800, .value: 0x0000c800, ARMV4T_ABOVE, .encoding: eEncodingT1, No_VFP, .size: eSize16,
13540 .callback: &EmulateInstructionARM::EmulateLDM, .name: "ldm<c> <Rn>{!} <registers>"},
13541 {.mask: 0xffd02000, .value: 0xe8900000, ARMV6T2_ABOVE, .encoding: eEncodingT2, No_VFP, .size: eSize32,
13542 .callback: &EmulateInstructionARM::EmulateLDM, .name: "ldm<c>.w <Rn>{!} <registers>"},
13543 {.mask: 0xffd00000, .value: 0xe9100000, ARMV6T2_ABOVE, .encoding: eEncodingT1, No_VFP, .size: eSize32,
13544 .callback: &EmulateInstructionARM::EmulateLDMDB, .name: "ldmdb<c> <Rn>{!} <registers>"},
13545 {.mask: 0xfffff800, .value: 0x00006800, ARMV4T_ABOVE, .encoding: eEncodingT1, No_VFP, .size: eSize16,
13546 .callback: &EmulateInstructionARM::EmulateLDRRtRnImm, .name: "ldr<c> <Rt>, [<Rn>{,#imm}]"},
13547 {.mask: 0xfffff800, .value: 0x00009800, ARMV4T_ABOVE, .encoding: eEncodingT2, No_VFP, .size: eSize16,
13548 .callback: &EmulateInstructionARM::EmulateLDRRtRnImm, .name: "ldr<c> <Rt>, [SP{,#imm}]"},
13549 {.mask: 0xfff00000, .value: 0xf8d00000, ARMV6T2_ABOVE, .encoding: eEncodingT3, No_VFP, .size: eSize32,
13550 .callback: &EmulateInstructionARM::EmulateLDRRtRnImm,
13551 .name: "ldr<c>.w <Rt>, [<Rn>{,#imm12}]"},
13552 {.mask: 0xfff00800, .value: 0xf8500800, ARMV6T2_ABOVE, .encoding: eEncodingT4, No_VFP, .size: eSize32,
13553 .callback: &EmulateInstructionARM::EmulateLDRRtRnImm,
13554 .name: "ldr<c> <Rt>, [<Rn>{,#+/-<imm8>}]{!}"},
13555 // Thumb2 PC-relative load into register
13556 {.mask: 0xff7f0000, .value: 0xf85f0000, ARMV6T2_ABOVE, .encoding: eEncodingT2, No_VFP, .size: eSize32,
13557 .callback: &EmulateInstructionARM::EmulateLDRRtPCRelative,
13558 .name: "ldr<c>.w <Rt>, [PC, +/-#imm}]"},
13559 {.mask: 0xfffffe00, .value: 0x00005800, ARMV4T_ABOVE, .encoding: eEncodingT1, No_VFP, .size: eSize16,
13560 .callback: &EmulateInstructionARM::EmulateLDRRegister, .name: "ldr<c> <Rt>, [<Rn>, <Rm>]"},
13561 {.mask: 0xfff00fc0, .value: 0xf8500000, ARMV6T2_ABOVE, .encoding: eEncodingT2, No_VFP, .size: eSize32,
13562 .callback: &EmulateInstructionARM::EmulateLDRRegister,
13563 .name: "ldr<c>.w <Rt>, [<Rn>,<Rm>{,LSL #<imm2>}]"},
13564 {.mask: 0xfffff800, .value: 0x00007800, ARMV4T_ABOVE, .encoding: eEncodingT1, No_VFP, .size: eSize16,
13565 .callback: &EmulateInstructionARM::EmulateLDRBImmediate,
13566 .name: "ldrb<c> <Rt>,[<Rn>{,#<imm5>}]"},
13567 {.mask: 0xfff00000, .value: 0xf8900000, ARMV6T2_ABOVE, .encoding: eEncodingT2, No_VFP, .size: eSize32,
13568 .callback: &EmulateInstructionARM::EmulateLDRBImmediate,
13569 .name: "ldrb<c>.w <Rt>,[<Rn>{,#<imm12>}]"},
13570 {.mask: 0xfff00800, .value: 0xf8100800, ARMV6T2_ABOVE, .encoding: eEncodingT3, No_VFP, .size: eSize32,
13571 .callback: &EmulateInstructionARM::EmulateLDRBImmediate,
13572 .name: "ldrb<c> <Rt>,[<Rn>, #+/-<imm8>]{!}"},
13573 {.mask: 0xff7f0000, .value: 0xf81f0000, ARMV6T2_ABOVE, .encoding: eEncodingT1, No_VFP, .size: eSize32,
13574 .callback: &EmulateInstructionARM::EmulateLDRBLiteral, .name: "ldrb<c> <Rt>,[...]"},
13575 {.mask: 0xfffffe00, .value: 0x00005c00, ARMV6T2_ABOVE, .encoding: eEncodingT1, No_VFP, .size: eSize16,
13576 .callback: &EmulateInstructionARM::EmulateLDRBRegister, .name: "ldrb<c> <Rt>,[<Rn>,<Rm>]"},
13577 {.mask: 0xfff00fc0, .value: 0xf8100000, ARMV6T2_ABOVE, .encoding: eEncodingT2, No_VFP, .size: eSize32,
13578 .callback: &EmulateInstructionARM::EmulateLDRBRegister,
13579 .name: "ldrb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]"},
13580 {.mask: 0xfffff800, .value: 0x00008800, ARMV4T_ABOVE, .encoding: eEncodingT1, No_VFP, .size: eSize16,
13581 .callback: &EmulateInstructionARM::EmulateLDRHImmediate,
13582 .name: "ldrh<c> <Rt>, [<Rn>{,#<imm>}]"},
13583 {.mask: 0xfff00000, .value: 0xf8b00000, ARMV6T2_ABOVE, .encoding: eEncodingT2, No_VFP, .size: eSize32,
13584 .callback: &EmulateInstructionARM::EmulateLDRHImmediate,
13585 .name: "ldrh<c>.w <Rt>,[<Rn>{,#<imm12>}]"},
13586 {.mask: 0xfff00800, .value: 0xf8300800, ARMV6T2_ABOVE, .encoding: eEncodingT3, No_VFP, .size: eSize32,
13587 .callback: &EmulateInstructionARM::EmulateLDRHImmediate,
13588 .name: "ldrh<c> <Rt>,[<Rn>,#+/-<imm8>]{!}"},
13589 {.mask: 0xff7f0000, .value: 0xf83f0000, ARMV6T2_ABOVE, .encoding: eEncodingT1, No_VFP, .size: eSize32,
13590 .callback: &EmulateInstructionARM::EmulateLDRHLiteral, .name: "ldrh<c> <Rt>, <label>"},
13591 {.mask: 0xfffffe00, .value: 0x00005a00, ARMV4T_ABOVE, .encoding: eEncodingT1, No_VFP, .size: eSize16,
13592 .callback: &EmulateInstructionARM::EmulateLDRHRegister,
13593 .name: "ldrh<c> <Rt>, [<Rn>,<Rm>]"},
13594 {.mask: 0xfff00fc0, .value: 0xf8300000, ARMV6T2_ABOVE, .encoding: eEncodingT2, No_VFP, .size: eSize32,
13595 .callback: &EmulateInstructionARM::EmulateLDRHRegister,
13596 .name: "ldrh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]"},
13597 {.mask: 0xfff00000, .value: 0xf9900000, ARMV6T2_ABOVE, .encoding: eEncodingT1, No_VFP, .size: eSize32,
13598 .callback: &EmulateInstructionARM::EmulateLDRSBImmediate,
13599 .name: "ldrsb<c> <Rt>,[<Rn>,#<imm12>]"},
13600 {.mask: 0xfff00800, .value: 0xf9100800, ARMV6T2_ABOVE, .encoding: eEncodingT2, No_VFP, .size: eSize32,
13601 .callback: &EmulateInstructionARM::EmulateLDRSBImmediate,
13602 .name: "ldrsb<c> <Rt>,[<Rn>,#+/-<imm8>]"},
13603 {.mask: 0xff7f0000, .value: 0xf91f0000, ARMV6T2_ABOVE, .encoding: eEncodingT1, No_VFP, .size: eSize32,
13604 .callback: &EmulateInstructionARM::EmulateLDRSBLiteral, .name: "ldrsb<c> <Rt>, <label>"},
13605 {.mask: 0xfffffe00, .value: 0x00005600, ARMV4T_ABOVE, .encoding: eEncodingT1, No_VFP, .size: eSize16,
13606 .callback: &EmulateInstructionARM::EmulateLDRSBRegister,
13607 .name: "ldrsb<c> <Rt>,[<Rn>,<Rm>]"},
13608 {.mask: 0xfff00fc0, .value: 0xf9100000, ARMV6T2_ABOVE, .encoding: eEncodingT2, No_VFP, .size: eSize32,
13609 .callback: &EmulateInstructionARM::EmulateLDRSBRegister,
13610 .name: "ldrsb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]"},
13611 {.mask: 0xfff00000, .value: 0xf9b00000, ARMV6T2_ABOVE, .encoding: eEncodingT1, No_VFP, .size: eSize32,
13612 .callback: &EmulateInstructionARM::EmulateLDRSHImmediate,
13613 .name: "ldrsh<c> <Rt>,[<Rn>,#<imm12>]"},
13614 {.mask: 0xfff00800, .value: 0xf9300800, ARMV6T2_ABOVE, .encoding: eEncodingT2, No_VFP, .size: eSize32,
13615 .callback: &EmulateInstructionARM::EmulateLDRSHImmediate,
13616 .name: "ldrsh<c> <Rt>,[<Rn>,#+/-<imm8>]"},
13617 {.mask: 0xff7f0000, .value: 0xf93f0000, ARMV6T2_ABOVE, .encoding: eEncodingT1, No_VFP, .size: eSize32,
13618 .callback: &EmulateInstructionARM::EmulateLDRSHLiteral, .name: "ldrsh<c> <Rt>,<label>"},
13619 {.mask: 0xfffffe00, .value: 0x00005e00, ARMV4T_ABOVE, .encoding: eEncodingT1, No_VFP, .size: eSize16,
13620 .callback: &EmulateInstructionARM::EmulateLDRSHRegister,
13621 .name: "ldrsh<c> <Rt>,[<Rn>,<Rm>]"},
13622 {.mask: 0xfff00fc0, .value: 0xf9300000, ARMV6T2_ABOVE, .encoding: eEncodingT2, No_VFP, .size: eSize32,
13623 .callback: &EmulateInstructionARM::EmulateLDRSHRegister,
13624 .name: "ldrsh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]"},
13625 {.mask: 0xfe500000, .value: 0xe8500000, ARMV6T2_ABOVE, .encoding: eEncodingT1, No_VFP, .size: eSize32,
13626 .callback: &EmulateInstructionARM::EmulateLDRDImmediate,
13627 .name: "ldrd<c> <Rt>, <Rt2>, [<Rn>,#+/-<imm>]!"},
13628 {.mask: 0xfe100f00, .value: 0xec100b00, ARMvAll, .encoding: eEncodingT1, VFPv2_ABOVE, .size: eSize32,
13629 .callback: &EmulateInstructionARM::EmulateVLDM, .name: "vldm{mode}<c> <Rn>{!}, <list>"},
13630 {.mask: 0xfe100f00, .value: 0xec100a00, ARMvAll, .encoding: eEncodingT2, VFPv2v3, .size: eSize32,
13631 .callback: &EmulateInstructionARM::EmulateVLDM, .name: "vldm{mode}<c> <Rn>{!}, <list>"},
13632 {.mask: 0xffe00f00, .value: 0xed100b00, ARMvAll, .encoding: eEncodingT1, VFPv2_ABOVE, .size: eSize32,
13633 .callback: &EmulateInstructionARM::EmulateVLDR, .name: "vldr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},
13634 {.mask: 0xff300f00, .value: 0xed100a00, ARMvAll, .encoding: eEncodingT2, VFPv2v3, .size: eSize32,
13635 .callback: &EmulateInstructionARM::EmulateVLDR, .name: "vldr<c> <Sd>, {<Rn>{,#+/-<imm>}]"},
13636 {.mask: 0xffb00000, .value: 0xf9200000, ARMvAll, .encoding: eEncodingT1, AdvancedSIMD, .size: eSize32,
13637 .callback: &EmulateInstructionARM::EmulateVLD1Multiple,
13638 .name: "vld1<c>.<size> <list>, [<Rn>{@<align>}],<Rm>"},
13639 {.mask: 0xffb00300, .value: 0xf9a00000, ARMvAll, .encoding: eEncodingT1, AdvancedSIMD, .size: eSize32,
13640 .callback: &EmulateInstructionARM::EmulateVLD1Single,
13641 .name: "vld1<c>.<size> <list>, [<Rn>{@<align>}],<Rm>"},
13642 {.mask: 0xffb00f00, .value: 0xf9a00c00, ARMvAll, .encoding: eEncodingT1, AdvancedSIMD, .size: eSize32,
13643 .callback: &EmulateInstructionARM::EmulateVLD1SingleAll,
13644 .name: "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
13645
13646 // Store instructions
13647 {.mask: 0xfffff800, .value: 0x0000c000, ARMV4T_ABOVE, .encoding: eEncodingT1, No_VFP, .size: eSize16,
13648 .callback: &EmulateInstructionARM::EmulateSTM, .name: "stm<c> <Rn>{!} <registers>"},
13649 {.mask: 0xffd00000, .value: 0xe8800000, ARMV6T2_ABOVE, .encoding: eEncodingT2, No_VFP, .size: eSize32,
13650 .callback: &EmulateInstructionARM::EmulateSTM, .name: "stm<c>.w <Rn>{!} <registers>"},
13651 {.mask: 0xffd00000, .value: 0xe9000000, ARMV6T2_ABOVE, .encoding: eEncodingT1, No_VFP, .size: eSize32,
13652 .callback: &EmulateInstructionARM::EmulateSTMDB, .name: "stmdb<c> <Rn>{!} <registers>"},
13653 {.mask: 0xfffff800, .value: 0x00006000, ARMV4T_ABOVE, .encoding: eEncodingT1, No_VFP, .size: eSize16,
13654 .callback: &EmulateInstructionARM::EmulateSTRThumb, .name: "str<c> <Rt>, [<Rn>{,#<imm>}]"},
13655 {.mask: 0xfffff800, .value: 0x00009000, ARMV4T_ABOVE, .encoding: eEncodingT2, No_VFP, .size: eSize16,
13656 .callback: &EmulateInstructionARM::EmulateSTRThumb, .name: "str<c> <Rt>, [SP,#<imm>]"},
13657 {.mask: 0xfff00000, .value: 0xf8c00000, ARMV6T2_ABOVE, .encoding: eEncodingT3, No_VFP, .size: eSize32,
13658 .callback: &EmulateInstructionARM::EmulateSTRThumb,
13659 .name: "str<c>.w <Rt>, [<Rn>,#<imm12>]"},
13660 {.mask: 0xfff00800, .value: 0xf8400800, ARMV6T2_ABOVE, .encoding: eEncodingT4, No_VFP, .size: eSize32,
13661 .callback: &EmulateInstructionARM::EmulateSTRThumb,
13662 .name: "str<c> <Rt>, [<Rn>,#+/-<imm8>]"},
13663 {.mask: 0xfffffe00, .value: 0x00005000, ARMV4T_ABOVE, .encoding: eEncodingT1, No_VFP, .size: eSize16,
13664 .callback: &EmulateInstructionARM::EmulateSTRRegister, .name: "str<c> <Rt> ,{<Rn>, <Rm>]"},
13665 {.mask: 0xfff00fc0, .value: 0xf8400000, ARMV6T2_ABOVE, .encoding: eEncodingT2, No_VFP, .size: eSize32,
13666 .callback: &EmulateInstructionARM::EmulateSTRRegister,
13667 .name: "str<c>.w <Rt>, [<Rn>, <Rm> {lsl #imm2>}]"},
13668 {.mask: 0xfffff800, .value: 0x00007000, ARMV4T_ABOVE, .encoding: eEncodingT1, No_VFP, .size: eSize16,
13669 .callback: &EmulateInstructionARM::EmulateSTRBThumb,
13670 .name: "strb<c> <Rt>, [<Rn>, #<imm5>]"},
13671 {.mask: 0xfff00000, .value: 0xf8800000, ARMV6T2_ABOVE, .encoding: eEncodingT2, No_VFP, .size: eSize32,
13672 .callback: &EmulateInstructionARM::EmulateSTRBThumb,
13673 .name: "strb<c>.w <Rt>, [<Rn>, #<imm12>]"},
13674 {.mask: 0xfff00800, .value: 0xf8000800, ARMV6T2_ABOVE, .encoding: eEncodingT3, No_VFP, .size: eSize32,
13675 .callback: &EmulateInstructionARM::EmulateSTRBThumb,
13676 .name: "strb<c> <Rt> ,[<Rn>, #+/-<imm8>]{!}"},
13677 {.mask: 0xfffffe00, .value: 0x00005200, ARMV4T_ABOVE, .encoding: eEncodingT1, No_VFP, .size: eSize16,
13678 .callback: &EmulateInstructionARM::EmulateSTRHRegister, .name: "strh<c> <Rt>,[<Rn>,<Rm>]"},
13679 {.mask: 0xfff00fc0, .value: 0xf8200000, ARMV6T2_ABOVE, .encoding: eEncodingT2, No_VFP, .size: eSize32,
13680 .callback: &EmulateInstructionARM::EmulateSTRHRegister,
13681 .name: "strh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]"},
13682 {.mask: 0xfff00000, .value: 0xe8400000, ARMV6T2_ABOVE, .encoding: eEncodingT1, No_VFP, .size: eSize32,
13683 .callback: &EmulateInstructionARM::EmulateSTREX,
13684 .name: "strex<c> <Rd>, <Rt>, [<Rn{,#<imm>}]"},
13685 {.mask: 0xfe500000, .value: 0xe8400000, ARMV6T2_ABOVE, .encoding: eEncodingT1, No_VFP, .size: eSize32,
13686 .callback: &EmulateInstructionARM::EmulateSTRDImm,
13687 .name: "strd<c> <Rt>, <Rt2>, [<Rn>, #+/-<imm>]!"},
13688 {.mask: 0xfe100f00, .value: 0xec000b00, ARMvAll, .encoding: eEncodingT1, VFPv2_ABOVE, .size: eSize32,
13689 .callback: &EmulateInstructionARM::EmulateVSTM, .name: "vstm{mode}<c> <Rn>{!}, <list>"},
13690 {.mask: 0xfea00f00, .value: 0xec000a00, ARMvAll, .encoding: eEncodingT2, VFPv2v3, .size: eSize32,
13691 .callback: &EmulateInstructionARM::EmulateVSTM, .name: "vstm{mode}<c> <Rn>{!}, <list>"},
13692 {.mask: 0xff300f00, .value: 0xed000b00, ARMvAll, .encoding: eEncodingT1, VFPv2_ABOVE, .size: eSize32,
13693 .callback: &EmulateInstructionARM::EmulateVSTR, .name: "vstr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},
13694 {.mask: 0xff300f00, .value: 0xed000a00, ARMvAll, .encoding: eEncodingT2, VFPv2v3, .size: eSize32,
13695 .callback: &EmulateInstructionARM::EmulateVSTR, .name: "vstr<c> <Sd>, [<Rn>{,#+/-<imm>}]"},
13696 {.mask: 0xffb00000, .value: 0xf9000000, ARMvAll, .encoding: eEncodingT1, AdvancedSIMD, .size: eSize32,
13697 .callback: &EmulateInstructionARM::EmulateVST1Multiple,
13698 .name: "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
13699 {.mask: 0xffb00300, .value: 0xf9800000, ARMvAll, .encoding: eEncodingT1, AdvancedSIMD, .size: eSize32,
13700 .callback: &EmulateInstructionARM::EmulateVST1Single,
13701 .name: "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
13702
13703 // Other instructions
13704 {.mask: 0xffffffc0, .value: 0x0000b240, ARMV6_ABOVE, .encoding: eEncodingT1, No_VFP, .size: eSize16,
13705 .callback: &EmulateInstructionARM::EmulateSXTB, .name: "sxtb<c> <Rd>,<Rm>"},
13706 {.mask: 0xfffff080, .value: 0xfa4ff080, ARMV6_ABOVE, .encoding: eEncodingT2, No_VFP, .size: eSize32,
13707 .callback: &EmulateInstructionARM::EmulateSXTB, .name: "sxtb<c>.w <Rd>,<Rm>{,<rotation>}"},
13708 {.mask: 0xffffffc0, .value: 0x0000b200, ARMV6_ABOVE, .encoding: eEncodingT1, No_VFP, .size: eSize16,
13709 .callback: &EmulateInstructionARM::EmulateSXTH, .name: "sxth<c> <Rd>,<Rm>"},
13710 {.mask: 0xfffff080, .value: 0xfa0ff080, ARMV6T2_ABOVE, .encoding: eEncodingT2, No_VFP, .size: eSize32,
13711 .callback: &EmulateInstructionARM::EmulateSXTH, .name: "sxth<c>.w <Rd>,<Rm>{,<rotation>}"},
13712 {.mask: 0xffffffc0, .value: 0x0000b2c0, ARMV6_ABOVE, .encoding: eEncodingT1, No_VFP, .size: eSize16,
13713 .callback: &EmulateInstructionARM::EmulateUXTB, .name: "uxtb<c> <Rd>,<Rm>"},
13714 {.mask: 0xfffff080, .value: 0xfa5ff080, ARMV6T2_ABOVE, .encoding: eEncodingT2, No_VFP, .size: eSize32,
13715 .callback: &EmulateInstructionARM::EmulateUXTB, .name: "uxtb<c>.w <Rd>,<Rm>{,<rotation>}"},
13716 {.mask: 0xffffffc0, .value: 0x0000b280, ARMV6_ABOVE, .encoding: eEncodingT1, No_VFP, .size: eSize16,
13717 .callback: &EmulateInstructionARM::EmulateUXTH, .name: "uxth<c> <Rd>,<Rm>"},
13718 {.mask: 0xfffff080, .value: 0xfa1ff080, ARMV6T2_ABOVE, .encoding: eEncodingT2, No_VFP, .size: eSize32,
13719 .callback: &EmulateInstructionARM::EmulateUXTH, .name: "uxth<c>.w <Rd>,<Rm>{,<rotation>}"},
13720 };
13721
13722 const size_t k_num_thumb_opcodes = std::size(g_thumb_opcodes);
13723 for (size_t i = 0; i < k_num_thumb_opcodes; ++i) {
13724 if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value &&
13725 (g_thumb_opcodes[i].variants & arm_isa) != 0)
13726 return &g_thumb_opcodes[i];
13727 }
13728 return nullptr;
13729}
13730
13731bool EmulateInstructionARM::SetArchitecture(const ArchSpec &arch) {
13732 m_arch = arch;
13733 m_arm_isa = 0;
13734 llvm::StringRef arch_cstr = arch.GetArchitectureName();
13735 if (arch_cstr.equals_insensitive(RHS: "armv4t"))
13736 m_arm_isa = ARMv4T;
13737 else if (arch_cstr.equals_insensitive(RHS: "armv5tej"))
13738 m_arm_isa = ARMv5TEJ;
13739 else if (arch_cstr.equals_insensitive(RHS: "armv5te"))
13740 m_arm_isa = ARMv5TE;
13741 else if (arch_cstr.equals_insensitive(RHS: "armv5t"))
13742 m_arm_isa = ARMv5T;
13743 else if (arch_cstr.equals_insensitive(RHS: "armv6k"))
13744 m_arm_isa = ARMv6K;
13745 else if (arch_cstr.equals_insensitive(RHS: "armv6t2"))
13746 m_arm_isa = ARMv6T2;
13747 else if (arch_cstr.equals_insensitive(RHS: "armv7s"))
13748 m_arm_isa = ARMv7S;
13749 else if (arch_cstr.equals_insensitive(RHS: "arm"))
13750 m_arm_isa = ARMvAll;
13751 else if (arch_cstr.equals_insensitive(RHS: "thumb"))
13752 m_arm_isa = ARMvAll;
13753 else if (arch_cstr.starts_with_insensitive(Prefix: "armv4"))
13754 m_arm_isa = ARMv4;
13755 else if (arch_cstr.starts_with_insensitive(Prefix: "armv6"))
13756 m_arm_isa = ARMv6;
13757 else if (arch_cstr.starts_with_insensitive(Prefix: "armv7"))
13758 m_arm_isa = ARMv7;
13759 else if (arch_cstr.starts_with_insensitive(Prefix: "armv8"))
13760 m_arm_isa = ARMv8;
13761 return m_arm_isa != 0;
13762}
13763
13764bool EmulateInstructionARM::SetInstruction(const Opcode &insn_opcode,
13765 const Address &inst_addr,
13766 Target *target) {
13767 if (EmulateInstruction::SetInstruction(insn_opcode, inst_addr, target)) {
13768 if (m_arch.GetTriple().getArch() == llvm::Triple::thumb ||
13769 m_arch.IsAlwaysThumbInstructions())
13770 m_opcode_mode = eModeThumb;
13771 else {
13772 AddressClass addr_class = inst_addr.GetAddressClass();
13773
13774 if ((addr_class == AddressClass::eCode) ||
13775 (addr_class == AddressClass::eUnknown))
13776 m_opcode_mode = eModeARM;
13777 else if (addr_class == AddressClass::eCodeAlternateISA)
13778 m_opcode_mode = eModeThumb;
13779 else
13780 return false;
13781 }
13782 if (m_opcode_mode == eModeThumb || m_arch.IsAlwaysThumbInstructions())
13783 m_opcode_cpsr = CPSR_MODE_USR | MASK_CPSR_T;
13784 else
13785 m_opcode_cpsr = CPSR_MODE_USR;
13786 return true;
13787 }
13788 return false;
13789}
13790
13791bool EmulateInstructionARM::ReadInstruction() {
13792 bool success = false;
13793 m_opcode_cpsr = ReadRegisterUnsigned(reg_kind: eRegisterKindGeneric,
13794 LLDB_REGNUM_GENERIC_FLAGS, fail_value: 0, success_ptr: &success);
13795 if (success) {
13796 addr_t pc =
13797 ReadRegisterUnsigned(reg_kind: eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC,
13798 LLDB_INVALID_ADDRESS, success_ptr: &success);
13799 if (success) {
13800 Context read_inst_context;
13801 read_inst_context.type = eContextReadOpcode;
13802 read_inst_context.SetNoArgs();
13803
13804 if ((m_opcode_cpsr & MASK_CPSR_T) || m_arch.IsAlwaysThumbInstructions()) {
13805 m_opcode_mode = eModeThumb;
13806 uint32_t thumb_opcode = MemARead(context&: read_inst_context, address: pc, size: 2, fail_value: 0, success_ptr: &success);
13807
13808 if (success) {
13809 if ((thumb_opcode & 0xe000) != 0xe000 ||
13810 ((thumb_opcode & 0x1800u) == 0)) {
13811 m_opcode.SetOpcode16(inst: thumb_opcode, order: GetByteOrder());
13812 } else {
13813 m_opcode.SetOpcode32(
13814 inst: (thumb_opcode << 16) |
13815 MemARead(context&: read_inst_context, address: pc + 2, size: 2, fail_value: 0, success_ptr: &success),
13816 order: GetByteOrder());
13817 }
13818 }
13819 } else {
13820 m_opcode_mode = eModeARM;
13821 m_opcode.SetOpcode32(inst: MemARead(context&: read_inst_context, address: pc, size: 4, fail_value: 0, success_ptr: &success),
13822 order: GetByteOrder());
13823 }
13824
13825 if (!m_ignore_conditions) {
13826 // If we are not ignoreing the conditions then init the it session from
13827 // the current value of cpsr.
13828 uint32_t it = (Bits32(bits: m_opcode_cpsr, msbit: 15, lsbit: 10) << 2) |
13829 Bits32(bits: m_opcode_cpsr, msbit: 26, lsbit: 25);
13830 if (it != 0)
13831 m_it_session.InitIT(bits7_0: it);
13832 }
13833 }
13834 }
13835 if (!success) {
13836 m_opcode_mode = eModeInvalid;
13837 m_addr = LLDB_INVALID_ADDRESS;
13838 }
13839 return success;
13840}
13841
13842uint32_t EmulateInstructionARM::ArchVersion() { return m_arm_isa; }
13843
13844bool EmulateInstructionARM::ConditionPassed(const uint32_t opcode) {
13845 // If we are ignoring conditions, then always return true. this allows us to
13846 // iterate over disassembly code and still emulate an instruction even if we
13847 // don't have all the right bits set in the CPSR register...
13848 if (m_ignore_conditions)
13849 return true;
13850
13851 const uint32_t cond = CurrentCond(opcode);
13852 if (cond == UINT32_MAX)
13853 return false;
13854
13855 bool result = false;
13856 switch (UnsignedBits(value: cond, msbit: 3, lsbit: 1)) {
13857 case 0:
13858 if (m_opcode_cpsr == 0)
13859 result = true;
13860 else
13861 result = (m_opcode_cpsr & MASK_CPSR_Z) != 0;
13862 break;
13863 case 1:
13864 if (m_opcode_cpsr == 0)
13865 result = true;
13866 else
13867 result = (m_opcode_cpsr & MASK_CPSR_C) != 0;
13868 break;
13869 case 2:
13870 if (m_opcode_cpsr == 0)
13871 result = true;
13872 else
13873 result = (m_opcode_cpsr & MASK_CPSR_N) != 0;
13874 break;
13875 case 3:
13876 if (m_opcode_cpsr == 0)
13877 result = true;
13878 else
13879 result = (m_opcode_cpsr & MASK_CPSR_V) != 0;
13880 break;
13881 case 4:
13882 if (m_opcode_cpsr == 0)
13883 result = true;
13884 else
13885 result = ((m_opcode_cpsr & MASK_CPSR_C) != 0) &&
13886 ((m_opcode_cpsr & MASK_CPSR_Z) == 0);
13887 break;
13888 case 5:
13889 if (m_opcode_cpsr == 0)
13890 result = true;
13891 else {
13892 bool n = (m_opcode_cpsr & MASK_CPSR_N);
13893 bool v = (m_opcode_cpsr & MASK_CPSR_V);
13894 result = n == v;
13895 }
13896 break;
13897 case 6:
13898 if (m_opcode_cpsr == 0)
13899 result = true;
13900 else {
13901 bool n = (m_opcode_cpsr & MASK_CPSR_N);
13902 bool v = (m_opcode_cpsr & MASK_CPSR_V);
13903 result = n == v && ((m_opcode_cpsr & MASK_CPSR_Z) == 0);
13904 }
13905 break;
13906 case 7:
13907 // Always execute (cond == 0b1110, or the special 0b1111 which gives
13908 // opcodes different meanings, but always means execution happens.
13909 return true;
13910 }
13911
13912 if (cond & 1)
13913 result = !result;
13914 return result;
13915}
13916
13917uint32_t EmulateInstructionARM::CurrentCond(const uint32_t opcode) {
13918 switch (m_opcode_mode) {
13919 case eModeInvalid:
13920 break;
13921
13922 case eModeARM:
13923 return UnsignedBits(value: opcode, msbit: 31, lsbit: 28);
13924
13925 case eModeThumb:
13926 // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit
13927 // 'cond' field of the encoding.
13928 {
13929 const uint32_t byte_size = m_opcode.GetByteSize();
13930 if (byte_size == 2) {
13931 if (Bits32(bits: opcode, msbit: 15, lsbit: 12) == 0x0d && Bits32(bits: opcode, msbit: 11, lsbit: 8) != 0x0f)
13932 return Bits32(bits: opcode, msbit: 11, lsbit: 8);
13933 } else if (byte_size == 4) {
13934 if (Bits32(bits: opcode, msbit: 31, lsbit: 27) == 0x1e && Bits32(bits: opcode, msbit: 15, lsbit: 14) == 0x02 &&
13935 Bits32(bits: opcode, msbit: 12, lsbit: 12) == 0x00 && Bits32(bits: opcode, msbit: 25, lsbit: 22) <= 0x0d) {
13936 return Bits32(bits: opcode, msbit: 25, lsbit: 22);
13937 }
13938 } else
13939 // We have an invalid thumb instruction, let's bail out.
13940 break;
13941
13942 return m_it_session.GetCond();
13943 }
13944 }
13945 return UINT32_MAX; // Return invalid value
13946}
13947
13948bool EmulateInstructionARM::InITBlock() {
13949 return CurrentInstrSet() == eModeThumb && m_it_session.InITBlock();
13950}
13951
13952bool EmulateInstructionARM::LastInITBlock() {
13953 return CurrentInstrSet() == eModeThumb && m_it_session.LastInITBlock();
13954}
13955
13956bool EmulateInstructionARM::BadMode(uint32_t mode) {
13957
13958 switch (mode) {
13959 case 16:
13960 return false; // '10000'
13961 case 17:
13962 return false; // '10001'
13963 case 18:
13964 return false; // '10010'
13965 case 19:
13966 return false; // '10011'
13967 case 22:
13968 return false; // '10110'
13969 case 23:
13970 return false; // '10111'
13971 case 27:
13972 return false; // '11011'
13973 case 31:
13974 return false; // '11111'
13975 default:
13976 return true;
13977 }
13978 return true;
13979}
13980
13981bool EmulateInstructionARM::CurrentModeIsPrivileged() {
13982 uint32_t mode = Bits32(bits: m_opcode_cpsr, msbit: 4, lsbit: 0);
13983
13984 if (BadMode(mode))
13985 return false;
13986
13987 if (mode == 16)
13988 return false;
13989
13990 return true;
13991}
13992
13993void EmulateInstructionARM::CPSRWriteByInstr(uint32_t value, uint32_t bytemask,
13994 bool affect_execstate) {
13995 bool privileged = CurrentModeIsPrivileged();
13996
13997 uint32_t tmp_cpsr = Bits32(bits: m_opcode_cpsr, msbit: 23, lsbit: 20) << 20;
13998
13999 if (BitIsSet(value: bytemask, bit: 3)) {
14000 tmp_cpsr = tmp_cpsr | (Bits32(bits: value, msbit: 31, lsbit: 27) << 27);
14001 if (affect_execstate)
14002 tmp_cpsr = tmp_cpsr | (Bits32(bits: value, msbit: 26, lsbit: 24) << 24);
14003 }
14004
14005 if (BitIsSet(value: bytemask, bit: 2)) {
14006 tmp_cpsr = tmp_cpsr | (Bits32(bits: value, msbit: 19, lsbit: 16) << 16);
14007 }
14008
14009 if (BitIsSet(value: bytemask, bit: 1)) {
14010 if (affect_execstate)
14011 tmp_cpsr = tmp_cpsr | (Bits32(bits: value, msbit: 15, lsbit: 10) << 10);
14012 tmp_cpsr = tmp_cpsr | (Bit32(bits: value, bit: 9) << 9);
14013 if (privileged)
14014 tmp_cpsr = tmp_cpsr | (Bit32(bits: value, bit: 8) << 8);
14015 }
14016
14017 if (BitIsSet(value: bytemask, bit: 0)) {
14018 if (privileged)
14019 tmp_cpsr = tmp_cpsr | (Bits32(bits: value, msbit: 7, lsbit: 6) << 6);
14020 if (affect_execstate)
14021 tmp_cpsr = tmp_cpsr | (Bit32(bits: value, bit: 5) << 5);
14022 if (privileged)
14023 tmp_cpsr = tmp_cpsr | Bits32(bits: value, msbit: 4, lsbit: 0);
14024 }
14025
14026 m_opcode_cpsr = tmp_cpsr;
14027}
14028
14029bool EmulateInstructionARM::BranchWritePC(const Context &context,
14030 uint32_t addr) {
14031 addr_t target;
14032
14033 // Check the current instruction set.
14034 if (CurrentInstrSet() == eModeARM)
14035 target = addr & 0xfffffffc;
14036 else
14037 target = addr & 0xfffffffe;
14038
14039 return WriteRegisterUnsigned(context, reg_kind: eRegisterKindGeneric,
14040 LLDB_REGNUM_GENERIC_PC, reg_value: target);
14041}
14042
14043// As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by
14044// inspecting addr.
14045bool EmulateInstructionARM::BXWritePC(Context &context, uint32_t addr) {
14046 addr_t target;
14047 // If the CPSR is changed due to switching between ARM and Thumb ISETSTATE,
14048 // we want to record it and issue a WriteRegister callback so the clients can
14049 // track the mode changes accordingly.
14050 bool cpsr_changed = false;
14051
14052 if (BitIsSet(value: addr, bit: 0)) {
14053 if (CurrentInstrSet() != eModeThumb) {
14054 SelectInstrSet(arm_or_thumb: eModeThumb);
14055 cpsr_changed = true;
14056 }
14057 target = addr & 0xfffffffe;
14058 context.SetISA(eModeThumb);
14059 } else if (BitIsClear(value: addr, bit: 1)) {
14060 if (CurrentInstrSet() != eModeARM) {
14061 SelectInstrSet(arm_or_thumb: eModeARM);
14062 cpsr_changed = true;
14063 }
14064 target = addr & 0xfffffffc;
14065 context.SetISA(eModeARM);
14066 } else
14067 return false; // address<1:0> == '10' => UNPREDICTABLE
14068
14069 if (cpsr_changed) {
14070 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindGeneric,
14071 LLDB_REGNUM_GENERIC_FLAGS, reg_value: m_new_inst_cpsr))
14072 return false;
14073 }
14074 return WriteRegisterUnsigned(context, reg_kind: eRegisterKindGeneric,
14075 LLDB_REGNUM_GENERIC_PC, reg_value: target);
14076}
14077
14078// Dispatches to either BXWritePC or BranchWritePC based on architecture
14079// versions.
14080bool EmulateInstructionARM::LoadWritePC(Context &context, uint32_t addr) {
14081 if (ArchVersion() >= ARMv5T)
14082 return BXWritePC(context, addr);
14083 else
14084 return BranchWritePC(context: (const Context)context, addr);
14085}
14086
14087// Dispatches to either BXWritePC or BranchWritePC based on architecture
14088// versions and current instruction set.
14089bool EmulateInstructionARM::ALUWritePC(Context &context, uint32_t addr) {
14090 if (ArchVersion() >= ARMv7 && CurrentInstrSet() == eModeARM)
14091 return BXWritePC(context, addr);
14092 else
14093 return BranchWritePC(context: (const Context)context, addr);
14094}
14095
14096EmulateInstructionARM::Mode EmulateInstructionARM::CurrentInstrSet() {
14097 return m_opcode_mode;
14098}
14099
14100// Set the 'T' bit of our CPSR. The m_opcode_mode gets updated when the next
14101// ReadInstruction() is performed. This function has a side effect of updating
14102// the m_new_inst_cpsr member variable if necessary.
14103bool EmulateInstructionARM::SelectInstrSet(Mode arm_or_thumb) {
14104 m_new_inst_cpsr = m_opcode_cpsr;
14105 switch (arm_or_thumb) {
14106 default:
14107 return false;
14108 case eModeARM:
14109 // Clear the T bit.
14110 m_new_inst_cpsr &= ~MASK_CPSR_T;
14111 break;
14112 case eModeThumb:
14113 // Set the T bit.
14114 m_new_inst_cpsr |= MASK_CPSR_T;
14115 break;
14116 }
14117 return true;
14118}
14119
14120// This function returns TRUE if the processor currently provides support for
14121// unaligned memory accesses, or FALSE otherwise. This is always TRUE in ARMv7,
14122// controllable by the SCTLR.U bit in ARMv6, and always FALSE before ARMv6.
14123bool EmulateInstructionARM::UnalignedSupport() {
14124 return (ArchVersion() >= ARMv7);
14125}
14126
14127// The main addition and subtraction instructions can produce status
14128// information about both unsigned carry and signed overflow conditions. This
14129// status information can be used to synthesize multi-word additions and
14130// subtractions.
14131EmulateInstructionARM::AddWithCarryResult
14132EmulateInstructionARM::AddWithCarry(uint32_t x, uint32_t y, uint8_t carry_in) {
14133 uint32_t result;
14134 uint8_t carry_out;
14135 uint8_t overflow;
14136
14137 uint64_t unsigned_sum = x + y + carry_in;
14138 int64_t signed_sum = (int32_t)x + (int32_t)y + (int32_t)carry_in;
14139
14140 result = UnsignedBits(value: unsigned_sum, msbit: 31, lsbit: 0);
14141 // carry_out = (result == unsigned_sum ? 0 : 1);
14142 overflow = ((int32_t)result == signed_sum ? 0 : 1);
14143
14144 if (carry_in)
14145 carry_out = ((int32_t)x >= (int32_t)(~y)) ? 1 : 0;
14146 else
14147 carry_out = ((int32_t)x > (int32_t)y) ? 1 : 0;
14148
14149 AddWithCarryResult res = {.result: result, .carry_out: carry_out, .overflow: overflow};
14150 return res;
14151}
14152
14153uint32_t EmulateInstructionARM::ReadCoreReg(uint32_t num, bool *success) {
14154 lldb::RegisterKind reg_kind;
14155 uint32_t reg_num;
14156 switch (num) {
14157 case SP_REG:
14158 reg_kind = eRegisterKindGeneric;
14159 reg_num = LLDB_REGNUM_GENERIC_SP;
14160 break;
14161 case LR_REG:
14162 reg_kind = eRegisterKindGeneric;
14163 reg_num = LLDB_REGNUM_GENERIC_RA;
14164 break;
14165 case PC_REG:
14166 reg_kind = eRegisterKindGeneric;
14167 reg_num = LLDB_REGNUM_GENERIC_PC;
14168 break;
14169 default:
14170 if (num < SP_REG) {
14171 reg_kind = eRegisterKindDWARF;
14172 reg_num = dwarf_r0 + num;
14173 } else {
14174 // assert(0 && "Invalid register number");
14175 *success = false;
14176 return UINT32_MAX;
14177 }
14178 break;
14179 }
14180
14181 // Read our register.
14182 uint32_t val = ReadRegisterUnsigned(reg_kind, reg_num, fail_value: 0, success_ptr: success);
14183
14184 // When executing an ARM instruction , PC reads as the address of the current
14185 // instruction plus 8. When executing a Thumb instruction , PC reads as the
14186 // address of the current instruction plus 4.
14187 if (num == 15) {
14188 if (CurrentInstrSet() == eModeARM)
14189 val += 8;
14190 else
14191 val += 4;
14192 }
14193
14194 return val;
14195}
14196
14197// Write the result to the ARM core register Rd, and optionally update the
14198// condition flags based on the result.
14199//
14200// This helper method tries to encapsulate the following pseudocode from the
14201// ARM Architecture Reference Manual:
14202//
14203// if d == 15 then // Can only occur for encoding A1
14204// ALUWritePC(result); // setflags is always FALSE here
14205// else
14206// R[d] = result;
14207// if setflags then
14208// APSR.N = result<31>;
14209// APSR.Z = IsZeroBit(result);
14210// APSR.C = carry;
14211// // APSR.V unchanged
14212//
14213// In the above case, the API client does not pass in the overflow arg, which
14214// defaults to ~0u.
14215bool EmulateInstructionARM::WriteCoreRegOptionalFlags(
14216 Context &context, const uint32_t result, const uint32_t Rd, bool setflags,
14217 const uint32_t carry, const uint32_t overflow) {
14218 if (Rd == 15) {
14219 if (!ALUWritePC(context, addr: result))
14220 return false;
14221 } else {
14222 lldb::RegisterKind reg_kind;
14223 uint32_t reg_num;
14224 switch (Rd) {
14225 case SP_REG:
14226 reg_kind = eRegisterKindGeneric;
14227 reg_num = LLDB_REGNUM_GENERIC_SP;
14228 break;
14229 case LR_REG:
14230 reg_kind = eRegisterKindGeneric;
14231 reg_num = LLDB_REGNUM_GENERIC_RA;
14232 break;
14233 default:
14234 reg_kind = eRegisterKindDWARF;
14235 reg_num = dwarf_r0 + Rd;
14236 }
14237 if (!WriteRegisterUnsigned(context, reg_kind, reg_num, reg_value: result))
14238 return false;
14239 if (setflags)
14240 return WriteFlags(context, result, carry, overflow);
14241 }
14242 return true;
14243}
14244
14245// This helper method tries to encapsulate the following pseudocode from the
14246// ARM Architecture Reference Manual:
14247//
14248// APSR.N = result<31>;
14249// APSR.Z = IsZeroBit(result);
14250// APSR.C = carry;
14251// APSR.V = overflow
14252//
14253// Default arguments can be specified for carry and overflow parameters, which
14254// means not to update the respective flags.
14255bool EmulateInstructionARM::WriteFlags(Context &context, const uint32_t result,
14256 const uint32_t carry,
14257 const uint32_t overflow) {
14258 m_new_inst_cpsr = m_opcode_cpsr;
14259 SetBit32(bits&: m_new_inst_cpsr, CPSR_N_POS, val: Bit32(bits: result, CPSR_N_POS));
14260 SetBit32(bits&: m_new_inst_cpsr, CPSR_Z_POS, val: result == 0 ? 1 : 0);
14261 if (carry != ~0u)
14262 SetBit32(bits&: m_new_inst_cpsr, CPSR_C_POS, val: carry);
14263 if (overflow != ~0u)
14264 SetBit32(bits&: m_new_inst_cpsr, CPSR_V_POS, val: overflow);
14265 if (m_new_inst_cpsr != m_opcode_cpsr) {
14266 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindGeneric,
14267 LLDB_REGNUM_GENERIC_FLAGS, reg_value: m_new_inst_cpsr))
14268 return false;
14269 }
14270 return true;
14271}
14272
14273bool EmulateInstructionARM::EvaluateInstruction(uint32_t evaluate_options) {
14274 ARMOpcode *opcode_data = nullptr;
14275
14276 if (m_opcode_mode == eModeThumb)
14277 opcode_data =
14278 GetThumbOpcodeForInstruction(opcode: m_opcode.GetOpcode32(), arm_isa: m_arm_isa);
14279 else if (m_opcode_mode == eModeARM)
14280 opcode_data = GetARMOpcodeForInstruction(opcode: m_opcode.GetOpcode32(), arm_isa: m_arm_isa);
14281
14282 const bool auto_advance_pc =
14283 evaluate_options & eEmulateInstructionOptionAutoAdvancePC;
14284 m_ignore_conditions =
14285 evaluate_options & eEmulateInstructionOptionIgnoreConditions;
14286
14287 bool success = false;
14288 if (m_opcode_cpsr == 0 || !m_ignore_conditions) {
14289 m_opcode_cpsr =
14290 ReadRegisterUnsigned(reg_kind: eRegisterKindDWARF, reg_num: dwarf_cpsr, fail_value: 0, success_ptr: &success);
14291 }
14292
14293 // Only return false if we are unable to read the CPSR if we care about
14294 // conditions
14295 if (!success && !m_ignore_conditions)
14296 return false;
14297
14298 uint32_t orig_pc_value = 0;
14299 if (auto_advance_pc) {
14300 orig_pc_value =
14301 ReadRegisterUnsigned(reg_kind: eRegisterKindDWARF, reg_num: dwarf_pc, fail_value: 0, success_ptr: &success);
14302 if (!success)
14303 return false;
14304 }
14305
14306 // Call the Emulate... function if we managed to decode the opcode.
14307 if (opcode_data) {
14308 success = (this->*opcode_data->callback)(m_opcode.GetOpcode32(),
14309 opcode_data->encoding);
14310 if (!success)
14311 return false;
14312 }
14313
14314 // Advance the ITSTATE bits to their values for the next instruction if we
14315 // haven't just executed an IT instruction what initialized it.
14316 if (m_opcode_mode == eModeThumb && m_it_session.InITBlock() &&
14317 (opcode_data == nullptr ||
14318 opcode_data->callback != &EmulateInstructionARM::EmulateIT))
14319 m_it_session.ITAdvance();
14320
14321 if (auto_advance_pc) {
14322 uint32_t after_pc_value =
14323 ReadRegisterUnsigned(reg_kind: eRegisterKindDWARF, reg_num: dwarf_pc, fail_value: 0, success_ptr: &success);
14324 if (!success)
14325 return false;
14326
14327 if (after_pc_value == orig_pc_value) {
14328 after_pc_value += m_opcode.GetByteSize();
14329
14330 EmulateInstruction::Context context;
14331 context.type = eContextAdvancePC;
14332 context.SetNoArgs();
14333 if (!WriteRegisterUnsigned(context, reg_kind: eRegisterKindDWARF, reg_num: dwarf_pc,
14334 reg_value: after_pc_value))
14335 return false;
14336 }
14337 }
14338 return true;
14339}
14340
14341EmulateInstruction::InstructionCondition
14342EmulateInstructionARM::GetInstructionCondition() {
14343 const uint32_t cond = CurrentCond(opcode: m_opcode.GetOpcode32());
14344 if (cond == 0xe || cond == 0xf || cond == UINT32_MAX)
14345 return EmulateInstruction::UnconditionalCondition;
14346 return cond;
14347}
14348
14349bool EmulateInstructionARM::TestEmulation(Stream &out_stream, ArchSpec &arch,
14350 OptionValueDictionary *test_data) {
14351 if (!test_data) {
14352 out_stream.Printf(format: "TestEmulation: Missing test data.\n");
14353 return false;
14354 }
14355
14356 static constexpr llvm::StringLiteral opcode_key("opcode");
14357 static constexpr llvm::StringLiteral before_key("before_state");
14358 static constexpr llvm::StringLiteral after_key("after_state");
14359
14360 OptionValueSP value_sp = test_data->GetValueForKey(key: opcode_key);
14361
14362 uint32_t test_opcode;
14363 if ((value_sp.get() == nullptr) ||
14364 (value_sp->GetType() != OptionValue::eTypeUInt64)) {
14365 out_stream.Printf(format: "TestEmulation: Error reading opcode from test file.\n");
14366 return false;
14367 }
14368 test_opcode = value_sp->GetValueAs<uint64_t>().value_or(u: 0);
14369
14370 if (arch.GetTriple().getArch() == llvm::Triple::thumb ||
14371 arch.IsAlwaysThumbInstructions()) {
14372 m_opcode_mode = eModeThumb;
14373 if (test_opcode < 0x10000)
14374 m_opcode.SetOpcode16(inst: test_opcode, order: endian::InlHostByteOrder());
14375 else
14376 m_opcode.SetOpcode32(inst: test_opcode, order: endian::InlHostByteOrder());
14377 } else if (arch.GetTriple().getArch() == llvm::Triple::arm) {
14378 m_opcode_mode = eModeARM;
14379 m_opcode.SetOpcode32(inst: test_opcode, order: endian::InlHostByteOrder());
14380 } else {
14381 out_stream.Printf(format: "TestEmulation: Invalid arch.\n");
14382 return false;
14383 }
14384
14385 EmulationStateARM before_state;
14386 EmulationStateARM after_state;
14387
14388 value_sp = test_data->GetValueForKey(key: before_key);
14389 if ((value_sp.get() == nullptr) ||
14390 (value_sp->GetType() != OptionValue::eTypeDictionary)) {
14391 out_stream.Printf(format: "TestEmulation: Failed to find 'before' state.\n");
14392 return false;
14393 }
14394
14395 OptionValueDictionary *state_dictionary = value_sp->GetAsDictionary();
14396 if (!before_state.LoadStateFromDictionary(test_data: state_dictionary)) {
14397 out_stream.Printf(format: "TestEmulation: Failed loading 'before' state.\n");
14398 return false;
14399 }
14400
14401 value_sp = test_data->GetValueForKey(key: after_key);
14402 if ((value_sp.get() == nullptr) ||
14403 (value_sp->GetType() != OptionValue::eTypeDictionary)) {
14404 out_stream.Printf(format: "TestEmulation: Failed to find 'after' state.\n");
14405 return false;
14406 }
14407
14408 state_dictionary = value_sp->GetAsDictionary();
14409 if (!after_state.LoadStateFromDictionary(test_data: state_dictionary)) {
14410 out_stream.Printf(format: "TestEmulation: Failed loading 'after' state.\n");
14411 return false;
14412 }
14413
14414 SetBaton((void *)&before_state);
14415 SetCallbacks(read_mem_callback: &EmulationStateARM::ReadPseudoMemory,
14416 write_mem_callback: &EmulationStateARM::WritePseudoMemory,
14417 read_reg_callback: &EmulationStateARM::ReadPseudoRegister,
14418 write_reg_callback: &EmulationStateARM::WritePseudoRegister);
14419
14420 bool success = EvaluateInstruction(evaluate_options: eEmulateInstructionOptionAutoAdvancePC);
14421 if (!success) {
14422 out_stream.Printf(format: "TestEmulation: EvaluateInstruction() failed.\n");
14423 return false;
14424 }
14425
14426 success = before_state.CompareState(other_state&: after_state, out_stream);
14427 if (!success)
14428 out_stream.Printf(format: "TestEmulation: State after emulation does not match "
14429 "'after' state.\n");
14430
14431 return success;
14432}
14433//
14434//
14435// const char *
14436// EmulateInstructionARM::GetRegisterName (uint32_t reg_kind, uint32_t reg_num)
14437//{
14438// if (reg_kind == eRegisterKindGeneric)
14439// {
14440// switch (reg_num)
14441// {
14442// case LLDB_REGNUM_GENERIC_PC: return "pc";
14443// case LLDB_REGNUM_GENERIC_SP: return "sp";
14444// case LLDB_REGNUM_GENERIC_FP: return "fp";
14445// case LLDB_REGNUM_GENERIC_RA: return "lr";
14446// case LLDB_REGNUM_GENERIC_FLAGS: return "cpsr";
14447// default: return NULL;
14448// }
14449// }
14450// else if (reg_kind == eRegisterKindDWARF)
14451// {
14452// return GetARMDWARFRegisterName (reg_num);
14453// }
14454// return NULL;
14455//}
14456//
14457bool EmulateInstructionARM::CreateFunctionEntryUnwind(UnwindPlan &unwind_plan) {
14458 unwind_plan.Clear();
14459 unwind_plan.SetRegisterKind(eRegisterKindDWARF);
14460
14461 UnwindPlan::RowSP row(new UnwindPlan::Row);
14462
14463 // Our previous Call Frame Address is the stack pointer
14464 row->GetCFAValue().SetIsRegisterPlusOffset(reg_num: dwarf_sp, offset: 0);
14465
14466 unwind_plan.AppendRow(row_sp: row);
14467 unwind_plan.SetSourceName("EmulateInstructionARM");
14468 unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
14469 unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolYes);
14470 unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo);
14471 unwind_plan.SetReturnAddressRegister(dwarf_lr);
14472 return true;
14473}
14474

source code of lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp