[LoongArch] Supports FP_TO_SINT operation for fp16 (#118303)
[llvm-project.git] / lldb / source / Plugins / Instruction / ARM / EmulateInstructionARM.cpp
blob147c00e51b40dcd616a77c824aaca0137a6340a5
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 //===----------------------------------------------------------------------===//
9 #include <cstdlib>
10 #include <optional>
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"
23 #include "Plugins/Process/Utility/ARMDefines.h"
24 #include "Plugins/Process/Utility/ARMUtils.h"
25 #include "Utility/ARM_DWARF_Registers.h"
27 #include "llvm/ADT/STLExtras.h"
28 #include "llvm/Support/MathExtras.h"
30 using namespace lldb;
31 using namespace lldb_private;
33 LLDB_PLUGIN_DEFINE_ADV(EmulateInstructionARM, InstructionARM)
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)
39 #define AlignPC(pc_val) (pc_val & 0xFFFFFFFC)
42 // ITSession implementation
45 static std::optional<RegisterInfo> GetARMDWARFRegisterInfo(unsigned reg_num) {
46 RegisterInfo reg_info;
47 ::memset(&reg_info, 0, sizeof(RegisterInfo));
48 ::memset(reg_info.kinds, LLDB_INVALID_REGNUM, sizeof(reg_info.kinds));
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;
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;
74 reg_info.kinds[eRegisterKindDWARF] = reg_num;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
597 default:
598 return {};
600 return reg_info;
603 // A8.6.50
604 // Valid return values are {1, 2, 3, 4}, with 0 signifying an error condition.
605 static uint32_t CountITSize(uint32_t ITMask) {
606 // First count the trailing zeros of the IT mask.
607 uint32_t TZ = llvm::countr_zero(ITMask);
608 if (TZ > 3) {
609 return 0;
611 return (4 - TZ);
614 // Init ITState. Note that at least one bit is always 1 in mask.
615 bool ITSession::InitIT(uint32_t bits7_0) {
616 ITCounter = CountITSize(Bits32(bits7_0, 3, 0));
617 if (ITCounter == 0)
618 return false;
620 // A8.6.50 IT
621 unsigned short FirstCond = Bits32(bits7_0, 7, 4);
622 if (FirstCond == 0xF) {
623 return false;
625 if (FirstCond == 0xE && ITCounter != 1) {
626 return false;
629 ITState = bits7_0;
630 return true;
633 // Update ITState if necessary.
634 void ITSession::ITAdvance() {
635 // assert(ITCounter);
636 --ITCounter;
637 if (ITCounter == 0)
638 ITState = 0;
639 else {
640 unsigned short NewITState4_0 = Bits32(ITState, 4, 0) << 1;
641 SetBits32(ITState, 4, 0, NewITState4_0);
645 // Return true if we're inside an IT Block.
646 bool ITSession::InITBlock() { return ITCounter != 0; }
648 // Return true if we're the last instruction inside an IT Block.
649 bool ITSession::LastInITBlock() { return ITCounter == 1; }
651 // Get condition bits for the current thumb instruction.
652 uint32_t ITSession::GetCond() {
653 if (InITBlock())
654 return Bits32(ITState, 7, 4);
655 else
656 return COND_AL;
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
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)
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)
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)
700 #define VFPv1_ABOVE (VFPv1 | VFPv2 | VFPv3 | AdvancedSIMD)
701 #define VFPv2_ABOVE (VFPv2 | VFPv3 | AdvancedSIMD)
702 #define VFPv2v3 (VFPv2 | VFPv3)
705 // EmulateInstructionARM implementation
708 void EmulateInstructionARM::Initialize() {
709 PluginManager::RegisterPlugin(GetPluginNameStatic(),
710 GetPluginDescriptionStatic(), CreateInstance);
713 void EmulateInstructionARM::Terminate() {
714 PluginManager::UnregisterPlugin(CreateInstance);
717 llvm::StringRef EmulateInstructionARM::GetPluginDescriptionStatic() {
718 return "Emulate instructions for the ARM architecture.";
721 EmulateInstruction *
722 EmulateInstructionARM::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));
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));
736 if (emulate_insn_up)
737 return emulate_insn_up.release();
741 return nullptr;
744 bool 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;
750 return false;
753 // Write "bits (32) UNKNOWN" to memory address "address". Helper function for
754 // many ARM instructions.
755 bool EmulateInstructionARM::WriteBits32UnknownToMemory(addr_t address) {
756 EmulateInstruction::Context context;
757 context.type = EmulateInstruction::eContextWriteMemoryRandomBits;
758 context.SetNoArgs();
760 uint32_t random_data = rand();
761 const uint32_t addr_byte_size = GetAddressByteSize();
763 return MemAWrite(context, address, random_data, addr_byte_size);
766 // Write "bits (32) UNKNOWN" to register n. Helper function for many ARM
767 // instructions.
768 bool EmulateInstructionARM::WriteBits32Unknown(int n) {
769 EmulateInstruction::Context context;
770 context.type = EmulateInstruction::eContextWriteRegisterRandomBits;
771 context.SetNoArgs();
773 bool success;
774 uint32_t data =
775 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
777 if (!success)
778 return false;
780 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, data))
781 return false;
783 return true;
786 std::optional<RegisterInfo>
787 EmulateInstructionARM::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 {};
816 if (reg_kind == eRegisterKindDWARF)
817 return GetARMDWARFRegisterInfo(reg_num);
818 return {};
821 uint32_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;
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.
846 uint32_t fp_regnum = 11;
848 if (is_apple)
849 fp_regnum = 7;
851 if (m_opcode_mode == eModeThumb && !m_arch.GetTriple().isOSWindows())
852 fp_regnum = 7;
854 return fp_regnum;
857 uint32_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;
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.
876 uint32_t fp_regnum = dwarf_r11;
878 if (is_apple)
879 fp_regnum = dwarf_r7;
881 if (m_opcode_mode == eModeThumb && !m_arch.GetTriple().isOSWindows())
882 fp_regnum = dwarf_r7;
884 return fp_regnum;
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.
891 bool EmulateInstructionARM::EmulatePUSH(const uint32_t opcode,
892 const ARMEncoding encoding) {
893 #if 0
894 // ARM pseudo code...
895 if (ConditionPassed())
897 EncodingSpecificOperations();
898 NullCheckIfThumbEE(13);
899 address = SP - 4*BitCount(registers);
901 for (i = 0 to 14)
903 if (registers<i> == '1')
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;
913 if (registers<15> == '1') // Only possible for encoding A1 or A2
914 MemA[address,4] = PCStoreValue();
916 SP = SP - 4*BitCount(registers);
918 #endif
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);
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(opcode, 7, 0);
931 // The M bit represents LR.
932 if (Bit32(opcode, 8))
933 registers |= (1u << 14);
934 // if BitCount(registers) < 1 then UNPREDICTABLE;
935 if (BitCount(registers) < 1)
936 return false;
937 break;
938 case eEncodingT2:
939 // Ignore bits 15 & 13.
940 registers = Bits32(opcode, 15, 0) & ~0xa000;
941 // if BitCount(registers) < 2 then UNPREDICTABLE;
942 if (BitCount(registers) < 2)
943 return false;
944 break;
945 case eEncodingT3:
946 Rt = Bits32(opcode, 15, 12);
947 // if BadReg(t) then UNPREDICTABLE;
948 if (BadReg(Rt))
949 return false;
950 registers = (1u << Rt);
951 break;
952 case eEncodingA1:
953 registers = Bits32(opcode, 15, 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(opcode, 15, 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;
968 addr_t sp_offset = addr_byte_size * BitCount(registers);
969 addr_t addr = sp - sp_offset;
970 uint32_t i;
972 EmulateInstruction::Context context;
973 context.type = EmulateInstruction::eContextPushRegisterOnStack;
974 std::optional<RegisterInfo> sp_reg =
975 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp);
976 for (i = 0; i < 15; ++i) {
977 if (BitIsSet(registers, i)) {
978 std::optional<RegisterInfo> reg_info =
979 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + i);
980 context.SetRegisterToRegisterPlusOffset(*reg_info, *sp_reg, addr - sp);
981 uint32_t reg_value = ReadCoreReg(i, &success);
982 if (!success)
983 return false;
984 if (!MemAWrite(context, addr, reg_value, addr_byte_size))
985 return false;
986 addr += addr_byte_size;
990 if (BitIsSet(registers, 15)) {
991 std::optional<RegisterInfo> reg_info =
992 GetRegisterInfo(eRegisterKindDWARF, dwarf_pc);
993 context.SetRegisterToRegisterPlusOffset(*reg_info, *sp_reg, addr - sp);
994 const uint32_t pc = ReadCoreReg(PC_REG, &success);
995 if (!success)
996 return false;
997 if (!MemAWrite(context, addr, pc, addr_byte_size))
998 return false;
1001 context.type = EmulateInstruction::eContextAdjustStackPointer;
1002 context.SetImmediateSigned(-sp_offset);
1004 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
1005 LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
1006 return false;
1008 return true;
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.
1014 bool EmulateInstructionARM::EmulatePOP(const uint32_t opcode,
1015 const ARMEncoding encoding) {
1016 #if 0
1017 // ARM pseudo code...
1018 if (ConditionPassed())
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;
1033 #endif
1035 bool success = false;
1037 if (ConditionPassed(opcode)) {
1038 const uint32_t addr_byte_size = GetAddressByteSize();
1039 const addr_t sp = ReadCoreReg(SP_REG, &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(opcode, 7, 0);
1047 // The P bit represents PC.
1048 if (Bit32(opcode, 8))
1049 registers |= (1u << 15);
1050 // if BitCount(registers) < 1 then UNPREDICTABLE;
1051 if (BitCount(registers) < 1)
1052 return false;
1053 break;
1054 case eEncodingT2:
1055 // Ignore bit 13.
1056 registers = Bits32(opcode, 15, 0) & ~0x2000;
1057 // if BitCount(registers) < 2 || (P == '1' && M == '1') then
1058 // UNPREDICTABLE;
1059 if (BitCount(registers) < 2 || (Bit32(opcode, 15) && Bit32(opcode, 14)))
1060 return false;
1061 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then
1062 // UNPREDICTABLE;
1063 if (BitIsSet(registers, 15) && InITBlock() && !LastInITBlock())
1064 return false;
1065 break;
1066 case eEncodingT3:
1067 Rt = Bits32(opcode, 15, 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(opcode, 15, 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;
1082 // if registers<13> == '1' && ArchVersion() >= 7 then UNPREDICTABLE;
1083 if (BitIsSet(opcode, 13) && ArchVersion() >= ARMv7)
1084 return false;
1085 break;
1086 case eEncodingA2:
1087 Rt = Bits32(opcode, 15, 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;
1096 addr_t sp_offset = addr_byte_size * BitCount(registers);
1097 addr_t addr = sp;
1098 uint32_t i, data;
1100 EmulateInstruction::Context context;
1101 context.type = EmulateInstruction::eContextPopRegisterOffStack;
1103 std::optional<RegisterInfo> sp_reg =
1104 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp);
1106 for (i = 0; i < 15; ++i) {
1107 if (BitIsSet(registers, i)) {
1108 context.SetAddress(addr);
1109 data = MemARead(context, addr, 4, 0, &success);
1110 if (!success)
1111 return false;
1112 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + i,
1113 data))
1114 return false;
1115 addr += addr_byte_size;
1119 if (BitIsSet(registers, 15)) {
1120 context.SetRegisterPlusOffset(*sp_reg, addr - sp);
1121 data = MemARead(context, addr, 4, 0, &success);
1122 if (!success)
1123 return false;
1124 // In ARMv5T and above, this is an interworking branch.
1125 if (!LoadWritePC(context, data))
1126 return false;
1127 // addr += addr_byte_size;
1130 context.type = EmulateInstruction::eContextAdjustStackPointer;
1131 context.SetImmediateSigned(sp_offset);
1133 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
1134 LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
1135 return false;
1137 return true;
1140 // Set r7 or ip to point to saved value residing within the stack.
1141 // ADD (SP plus immediate)
1142 bool EmulateInstructionARM::EmulateADDRdSPImm(const uint32_t opcode,
1143 const ARMEncoding encoding) {
1144 #if 0
1145 // ARM pseudo code...
1146 if (ConditionPassed())
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;
1160 #endif
1162 bool success = false;
1164 if (ConditionPassed(opcode)) {
1165 const addr_t sp = ReadCoreReg(SP_REG, &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(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32)
1174 break;
1175 case eEncodingA1:
1176 Rd = Bits32(opcode, 15, 12);
1177 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
1178 break;
1179 default:
1180 return false;
1182 addr_t sp_offset = imm32;
1183 addr_t addr = sp + sp_offset; // a pointer to the stack area
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(eRegisterKindDWARF, dwarf_sp);
1192 context.SetRegisterPlusOffset(*sp_reg, sp_offset);
1194 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + Rd,
1195 addr))
1196 return false;
1198 return true;
1201 // Set r7 or ip to the current stack pointer.
1202 // MOV (register)
1203 bool EmulateInstructionARM::EmulateMOVRdSP(const uint32_t opcode,
1204 const ARMEncoding encoding) {
1205 #if 0
1206 // ARM pseudo code...
1207 if (ConditionPassed())
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
1221 #endif
1223 bool success = false;
1225 if (ConditionPassed(opcode)) {
1226 const addr_t sp = ReadCoreReg(SP_REG, &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;
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(eRegisterKindDWARF, dwarf_sp);
1248 context.SetRegisterPlusOffset(*sp_reg, 0);
1250 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + Rd, sp))
1251 return false;
1253 return true;
1256 // Move from high register (r8-r15) to low register (r0-r7).
1257 // MOV (register)
1258 bool EmulateInstructionARM::EmulateMOVLowHigh(const uint32_t opcode,
1259 const ARMEncoding encoding) {
1260 return EmulateMOVRdRm(opcode, encoding);
1263 // Move from register to register.
1264 // MOV (register)
1265 bool EmulateInstructionARM::EmulateMOVRdRm(const uint32_t opcode,
1266 const ARMEncoding encoding) {
1267 #if 0
1268 // ARM pseudo code...
1269 if (ConditionPassed())
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
1283 #endif
1285 bool success = false;
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(opcode, 7) << 3 | Bits32(opcode, 2, 0);
1294 Rm = Bits32(opcode, 6, 3);
1295 setflags = false;
1296 if (Rd == 15 && InITBlock() && !LastInITBlock())
1297 return false;
1298 break;
1299 case eEncodingT2:
1300 Rd = Bits32(opcode, 2, 0);
1301 Rm = Bits32(opcode, 5, 3);
1302 setflags = true;
1303 if (InITBlock())
1304 return false;
1305 break;
1306 case eEncodingT3:
1307 Rd = Bits32(opcode, 11, 8);
1308 Rm = Bits32(opcode, 3, 0);
1309 setflags = BitIsSet(opcode, 20);
1310 // if setflags && (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
1311 if (setflags && (BadReg(Rd) || BadReg(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(opcode, 15, 12);
1320 Rm = Bits32(opcode, 3, 0);
1321 setflags = BitIsSet(opcode, 20);
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;
1331 uint32_t result = ReadCoreReg(Rm, &success);
1332 if (!success)
1333 return false;
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(eRegisterKindDWARF, dwarf_r0 + Rm);
1345 context.SetRegisterPlusOffset(*dwarf_reg, 0);
1347 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags))
1348 return false;
1350 return true;
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)
1356 bool EmulateInstructionARM::EmulateMOVRdImm(const uint32_t opcode,
1357 const ARMEncoding encoding) {
1358 #if 0
1359 // ARM pseudo code...
1360 if (ConditionPassed())
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
1374 #endif
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(opcode, 10, 8);
1387 setflags = !InITBlock();
1388 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
1389 carry = APSR_C;
1391 break;
1393 case eEncodingT2:
1394 Rd = Bits32(opcode, 11, 8);
1395 setflags = BitIsSet(opcode, 20);
1396 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry);
1397 if (BadReg(Rd))
1398 return false;
1400 break;
1402 case eEncodingT3: {
1403 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm4:i:imm3:imm8,
1404 // 32);
1405 Rd = Bits32(opcode, 11, 8);
1406 setflags = false;
1407 uint32_t imm4 = Bits32(opcode, 19, 16);
1408 uint32_t imm3 = Bits32(opcode, 14, 12);
1409 uint32_t i = Bit32(opcode, 26);
1410 uint32_t imm8 = Bits32(opcode, 7, 0);
1411 imm32 = (imm4 << 12) | (i << 11) | (imm3 << 8) | imm8;
1413 // if BadReg(d) then UNPREDICTABLE;
1414 if (BadReg(Rd))
1415 return false;
1416 } break;
1418 case eEncodingA1:
1419 // d = UInt(Rd); setflags = (S == '1'); (imm32, carry) =
1420 // ARMExpandImm_C(imm12, APSR.C);
1421 Rd = Bits32(opcode, 15, 12);
1422 setflags = BitIsSet(opcode, 20);
1423 imm32 = ARMExpandImm_C(opcode, APSR_C, carry);
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);
1430 break;
1432 case eEncodingA2: {
1433 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm4:imm12, 32);
1434 Rd = Bits32(opcode, 15, 12);
1435 setflags = false;
1436 uint32_t imm4 = Bits32(opcode, 19, 16);
1437 uint32_t imm12 = Bits32(opcode, 11, 0);
1438 imm32 = (imm4 << 12) | imm12;
1440 // if d == 15 then UNPREDICTABLE;
1441 if (Rd == 15)
1442 return false;
1443 } break;
1445 default:
1446 return false;
1448 uint32_t result = imm32;
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();
1455 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
1456 return false;
1458 return true;
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.
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.
1469 bool 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
1487 if (ConditionPassed(opcode)) {
1488 uint32_t d;
1489 uint32_t n;
1490 uint32_t m;
1491 bool setflags;
1493 // EncodingSpecificOperations();
1494 switch (encoding) {
1495 case eEncodingT1:
1496 // d = UInt(Rdm); n = UInt(Rn); m = UInt(Rdm); setflags = !InITBlock();
1497 d = Bits32(opcode, 2, 0);
1498 n = Bits32(opcode, 5, 3);
1499 m = Bits32(opcode, 2, 0);
1500 setflags = !InITBlock();
1502 // if ArchVersion() < 6 && d == n then UNPREDICTABLE;
1503 if ((ArchVersion() < ARMv6) && (d == n))
1504 return false;
1506 break;
1508 case eEncodingT2:
1509 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = FALSE;
1510 d = Bits32(opcode, 11, 8);
1511 n = Bits32(opcode, 19, 16);
1512 m = Bits32(opcode, 3, 0);
1513 setflags = false;
1515 // if BadReg(d) || BadReg(n) || BadReg(m) then UNPREDICTABLE;
1516 if (BadReg(d) || BadReg(n) || BadReg(m))
1517 return false;
1519 break;
1521 case eEncodingA1:
1522 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == '1');
1523 d = Bits32(opcode, 19, 16);
1524 n = Bits32(opcode, 3, 0);
1525 m = Bits32(opcode, 11, 8);
1526 setflags = BitIsSet(opcode, 20);
1528 // if d == 15 || n == 15 || m == 15 then UNPREDICTABLE;
1529 if ((d == 15) || (n == 15) || (m == 15))
1530 return false;
1532 // if ArchVersion() < 6 && d == n then UNPREDICTABLE;
1533 if ((ArchVersion() < ARMv6) && (d == n))
1534 return false;
1536 break;
1538 default:
1539 return false;
1542 bool success = false;
1544 // operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final
1545 // results
1546 uint64_t operand1 =
1547 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
1548 if (!success)
1549 return false;
1551 // operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final
1552 // results
1553 uint64_t operand2 =
1554 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
1555 if (!success)
1556 return false;
1558 // result = operand1 * operand2;
1559 uint64_t result = operand1 * operand2;
1561 // R[d] = result<31:0>;
1562 std::optional<RegisterInfo> op1_reg =
1563 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
1564 std::optional<RegisterInfo> op2_reg =
1565 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m);
1567 EmulateInstruction::Context context;
1568 context.type = eContextArithmetic;
1569 context.SetRegisterRegisterOperands(*op1_reg, *op2_reg);
1571 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d,
1572 (0x0000ffff & result)))
1573 return false;
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(m_new_inst_cpsr, CPSR_N_POS, Bit32(result, 31));
1581 SetBit32(m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0);
1582 if (m_new_inst_cpsr != m_opcode_cpsr) {
1583 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
1584 LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
1585 return false;
1588 // if ArchVersion() == 4 then
1589 // APSR.C = bit UNKNOWN;
1592 return true;
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.
1598 bool EmulateInstructionARM::EmulateMVNImm(const uint32_t opcode,
1599 const ARMEncoding encoding) {
1600 #if 0
1601 // ARM pseudo code...
1602 if (ConditionPassed())
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
1616 #endif
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(opcode, 11, 8);
1626 setflags = BitIsSet(opcode, 20);
1627 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry);
1628 break;
1629 case eEncodingA1:
1630 Rd = Bits32(opcode, 15, 12);
1631 setflags = BitIsSet(opcode, 20);
1632 imm32 = ARMExpandImm_C(opcode, APSR_C, carry);
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;
1642 uint32_t result = ~imm32;
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();
1649 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
1650 return false;
1652 return true;
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.
1658 bool EmulateInstructionARM::EmulateMVNReg(const uint32_t opcode,
1659 const ARMEncoding encoding) {
1660 #if 0
1661 // ARM pseudo code...
1662 if (ConditionPassed())
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
1677 #endif
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(opcode, 2, 0);
1689 Rm = Bits32(opcode, 5, 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(opcode, 11, 8);
1698 Rm = Bits32(opcode, 3, 0);
1699 setflags = BitIsSet(opcode, 20);
1700 shift_n = DecodeImmShiftThumb(opcode, shift_t);
1701 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
1702 if (BadReg(Rd) || BadReg(Rm))
1703 return false;
1704 break;
1705 case eEncodingA1:
1706 Rd = Bits32(opcode, 15, 12);
1707 Rm = Bits32(opcode, 3, 0);
1708 setflags = BitIsSet(opcode, 20);
1709 shift_n = DecodeImmShiftARM(opcode, shift_t);
1710 break;
1711 default:
1712 return false;
1714 bool success = false;
1715 uint32_t value = ReadCoreReg(Rm, &success);
1716 if (!success)
1717 return false;
1719 uint32_t shifted =
1720 Shift_C(value, shift_t, shift_n, APSR_C, carry, &success);
1721 if (!success)
1722 return false;
1723 uint32_t result = ~shifted;
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();
1730 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
1731 return false;
1733 return true;
1736 // PC relative immediate load into register, possibly followed by ADD (SP plus
1737 // register).
1738 // LDR (literal)
1739 bool EmulateInstructionARM::EmulateLDRRtPCRelative(const uint32_t opcode,
1740 const ARMEncoding encoding) {
1741 #if 0
1742 // ARM pseudo code...
1743 if (ConditionPassed())
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;
1759 #endif
1761 if (ConditionPassed(opcode)) {
1762 bool success = false;
1763 const uint32_t pc = ReadCoreReg(PC_REG, &success);
1764 if (!success)
1765 return false;
1767 // PC relative immediate load context
1768 EmulateInstruction::Context context;
1769 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1770 std::optional<RegisterInfo> pc_reg =
1771 GetRegisterInfo(eRegisterKindDWARF, dwarf_pc);
1772 context.SetRegisterPlusOffset(*pc_reg, 0);
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(opcode, 10, 8);
1783 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32);
1784 add = true;
1785 break;
1786 case eEncodingT2:
1787 Rt = Bits32(opcode, 15, 12);
1788 imm32 = Bits32(opcode, 11, 0) << 2; // imm32 = ZeroExtend(imm12, 32);
1789 add = BitIsSet(opcode, 23);
1790 if (Rt == 15 && InITBlock() && !LastInITBlock())
1791 return false;
1792 break;
1793 default:
1794 return false;
1797 base = Align(pc, 4);
1798 if (add)
1799 address = base + imm32;
1800 else
1801 address = base - imm32;
1803 context.SetRegisterPlusOffset(*pc_reg, address - base);
1804 data = MemURead(context, address, 4, 0, &success);
1805 if (!success)
1806 return false;
1808 if (Rt == 15) {
1809 if (Bits32(address, 1, 0) == 0) {
1810 // In ARMv5T and above, this is an interworking branch.
1811 if (!LoadWritePC(context, data))
1812 return false;
1813 } else
1814 return false;
1815 } else if (UnalignedSupport() || Bits32(address, 1, 0) == 0) {
1816 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + Rt,
1817 data))
1818 return false;
1819 } else // We don't handle ARM for now.
1820 return false;
1822 return true;
1825 // An add operation to adjust the SP.
1826 // ADD (SP plus immediate)
1827 bool EmulateInstructionARM::EmulateADDSPImm(const uint32_t opcode,
1828 const ARMEncoding encoding) {
1829 #if 0
1830 // ARM pseudo code...
1831 if (ConditionPassed())
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;
1845 #endif
1847 bool success = false;
1849 if (ConditionPassed(opcode)) {
1850 const addr_t sp = ReadCoreReg(SP_REG, &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(opcode, 10, 8);
1860 imm32 = (Bits32(opcode, 7, 0) << 2);
1861 setflags = false;
1862 break;
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;
1871 case eEncodingT3:
1872 // d = UInt(Rd); setflags = (S == "1"); imm32 =
1873 // ThumbExpandImm(i:imm3:imm8);
1874 d = Bits32(opcode, 11, 8);
1875 imm32 = ThumbExpandImm(opcode);
1876 setflags = Bit32(opcode, 20);
1878 // if Rd == "1111" && S == "1" then SEE CMN (immediate);
1879 if (d == 15 && setflags == 1)
1880 return false; // CMN (immediate) not yet supported
1882 // if d == 15 && S == "0" then UNPREDICTABLE;
1883 if (d == 15 && setflags == 0)
1884 return false;
1885 break;
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(opcode, 11, 8);
1891 setflags = false;
1892 uint32_t i = Bit32(opcode, 26);
1893 uint32_t imm3 = Bits32(opcode, 14, 12);
1894 uint32_t imm8 = Bits32(opcode, 7, 0);
1895 imm32 = (i << 11) | (imm3 << 8) | imm8;
1897 // if d == 15 then UNPREDICTABLE;
1898 if (d == 15)
1899 return false;
1900 } break;
1902 default:
1903 return false;
1905 // (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
1906 AddWithCarryResult res = AddWithCarry(sp, imm32, 0);
1908 EmulateInstruction::Context context;
1909 if (d == 13)
1910 context.type = EmulateInstruction::eContextAdjustStackPointer;
1911 else
1912 context.type = EmulateInstruction::eContextRegisterPlusOffset;
1914 std::optional<RegisterInfo> sp_reg =
1915 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp);
1916 context.SetRegisterPlusOffset(*sp_reg, res.result - sp);
1918 if (d == 15) {
1919 if (!ALUWritePC(context, 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, res.result, d, setflags,
1929 res.carry_out, res.overflow))
1930 return false;
1933 return true;
1936 // An add operation to adjust the SP.
1937 // ADD (SP plus register)
1938 bool EmulateInstructionARM::EmulateADDSPRm(const uint32_t opcode,
1939 const ARMEncoding encoding) {
1940 #if 0
1941 // ARM pseudo code...
1942 if (ConditionPassed())
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;
1957 #endif
1959 bool success = false;
1961 if (ConditionPassed(opcode)) {
1962 const addr_t sp = ReadCoreReg(SP_REG, &success);
1963 if (!success)
1964 return false;
1965 uint32_t Rm; // the second operand
1966 switch (encoding) {
1967 case eEncodingT2:
1968 Rm = Bits32(opcode, 6, 3);
1969 break;
1970 default:
1971 return false;
1973 int32_t reg_value = ReadCoreReg(Rm, &success);
1974 if (!success)
1975 return false;
1977 addr_t addr = (int32_t)sp + reg_value; // the adjusted stack pointer value
1979 EmulateInstruction::Context context;
1980 context.type = eContextArithmetic;
1981 std::optional<RegisterInfo> sp_reg =
1982 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp);
1983 std::optional<RegisterInfo> other_reg =
1984 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rm);
1985 context.SetRegisterRegisterOperands(*sp_reg, *other_reg);
1987 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
1988 LLDB_REGNUM_GENERIC_SP, addr))
1989 return false;
1991 return true;
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)
1998 bool EmulateInstructionARM::EmulateBLXImmediate(const uint32_t opcode,
1999 const ARMEncoding encoding) {
2000 #if 0
2001 // ARM pseudo code...
2002 if (ConditionPassed())
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);
2016 #endif
2018 bool success = true;
2020 if (ConditionPassed(opcode)) {
2021 EmulateInstruction::Context context;
2022 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
2023 const uint32_t pc = ReadCoreReg(PC_REG, &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(opcode, 26);
2033 uint32_t imm10 = Bits32(opcode, 25, 16);
2034 uint32_t J1 = Bit32(opcode, 13);
2035 uint32_t J2 = Bit32(opcode, 11);
2036 uint32_t imm11 = Bits32(opcode, 10, 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>(imm25);
2042 target = pc + imm32;
2043 SelectInstrSet(eModeThumb);
2044 context.SetISAAndImmediateSigned(eModeThumb, 4 + imm32);
2045 if (InITBlock() && !LastInITBlock())
2046 return false;
2047 break;
2049 case eEncodingT2: {
2050 lr = pc | 1u; // return address
2051 uint32_t S = Bit32(opcode, 26);
2052 uint32_t imm10H = Bits32(opcode, 25, 16);
2053 uint32_t J1 = Bit32(opcode, 13);
2054 uint32_t J2 = Bit32(opcode, 11);
2055 uint32_t imm10L = Bits32(opcode, 10, 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>(imm25);
2061 target = Align(pc, 4) + imm32;
2062 SelectInstrSet(eModeARM);
2063 context.SetISAAndImmediateSigned(eModeARM, 4 + imm32);
2064 if (InITBlock() && !LastInITBlock())
2065 return false;
2066 break;
2068 case eEncodingA1:
2069 lr = pc - 4; // return address
2070 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
2071 target = Align(pc, 4) + imm32;
2072 SelectInstrSet(eModeARM);
2073 context.SetISAAndImmediateSigned(eModeARM, 8 + imm32);
2074 break;
2075 case eEncodingA2:
2076 lr = pc - 4; // return address
2077 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2 |
2078 Bits32(opcode, 24, 24) << 1);
2079 target = pc + imm32;
2080 SelectInstrSet(eModeThumb);
2081 context.SetISAAndImmediateSigned(eModeThumb, 8 + imm32);
2082 break;
2083 default:
2084 return false;
2086 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
2087 LLDB_REGNUM_GENERIC_RA, lr))
2088 return false;
2089 if (!BranchWritePC(context, target))
2090 return false;
2091 if (m_opcode_cpsr != m_new_inst_cpsr)
2092 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
2093 LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
2094 return false;
2096 return true;
2099 // Branch with Link and Exchange (register) calls a subroutine at an address
2100 // and instruction set specified by a register.
2101 // BLX (register)
2102 bool EmulateInstructionARM::EmulateBLXRm(const uint32_t opcode,
2103 const ARMEncoding encoding) {
2104 #if 0
2105 // ARM pseudo code...
2106 if (ConditionPassed())
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);
2118 #endif
2120 bool success = false;
2122 if (ConditionPassed(opcode)) {
2123 EmulateInstruction::Context context;
2124 context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
2125 const uint32_t pc = ReadCoreReg(PC_REG, &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(opcode, 6, 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(opcode, 3, 0);
2143 // if m == 15 then UNPREDICTABLE;
2144 if (Rm == 15)
2145 return false;
2146 break;
2147 default:
2148 return false;
2150 addr_t target = ReadCoreReg(Rm, &success);
2151 if (!success)
2152 return false;
2153 std::optional<RegisterInfo> dwarf_reg =
2154 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rm);
2155 context.SetRegister(*dwarf_reg);
2156 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
2157 LLDB_REGNUM_GENERIC_RA, lr))
2158 return false;
2159 if (!BXWritePC(context, target))
2160 return false;
2162 return true;
2165 // Branch and Exchange causes a branch to an address and instruction set
2166 // specified by a register.
2167 bool EmulateInstructionARM::EmulateBXRm(const uint32_t opcode,
2168 const ARMEncoding encoding) {
2169 #if 0
2170 // ARM pseudo code...
2171 if (ConditionPassed())
2173 EncodingSpecificOperations();
2174 BXWritePC(R[m]);
2176 #endif
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(opcode, 6, 3);
2185 if (InITBlock() && !LastInITBlock())
2186 return false;
2187 break;
2188 case eEncodingA1:
2189 Rm = Bits32(opcode, 3, 0);
2190 break;
2191 default:
2192 return false;
2194 bool success = false;
2195 addr_t target = ReadCoreReg(Rm, &success);
2196 if (!success)
2197 return false;
2199 std::optional<RegisterInfo> dwarf_reg =
2200 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rm);
2201 context.SetRegister(*dwarf_reg);
2202 if (!BXWritePC(context, target))
2203 return false;
2205 return true;
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.
2212 // TODO: Emulate Jazelle architecture?
2213 // We currently assume that switching to Jazelle state fails, thus
2214 // treating BXJ as a BX operation.
2215 bool EmulateInstructionARM::EmulateBXJRm(const uint32_t opcode,
2216 const ARMEncoding encoding) {
2217 #if 0
2218 // ARM pseudo code...
2219 if (ConditionPassed())
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;
2230 #endif
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(opcode, 19, 16);
2239 if (BadReg(Rm))
2240 return false;
2241 if (InITBlock() && !LastInITBlock())
2242 return false;
2243 break;
2244 case eEncodingA1:
2245 Rm = Bits32(opcode, 3, 0);
2246 if (Rm == 15)
2247 return false;
2248 break;
2249 default:
2250 return false;
2252 bool success = false;
2253 addr_t target = ReadCoreReg(Rm, &success);
2254 if (!success)
2255 return false;
2257 std::optional<RegisterInfo> dwarf_reg =
2258 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rm);
2259 context.SetRegister(*dwarf_reg);
2260 if (!BXWritePC(context, target))
2261 return false;
2263 return true;
2266 // Set r7 to point to some ip offset.
2267 // SUB (immediate)
2268 bool EmulateInstructionARM::EmulateSUBR7IPImm(const uint32_t opcode,
2269 const ARMEncoding encoding) {
2270 #if 0
2271 // ARM pseudo code...
2272 if (ConditionPassed())
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;
2286 #endif
2288 if (ConditionPassed(opcode)) {
2289 bool success = false;
2290 const addr_t ip = ReadCoreReg(12, &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;
2301 addr_t ip_offset = imm32;
2302 addr_t addr = ip - ip_offset; // the adjusted ip value
2304 EmulateInstruction::Context context;
2305 context.type = EmulateInstruction::eContextRegisterPlusOffset;
2306 std::optional<RegisterInfo> dwarf_reg =
2307 GetRegisterInfo(eRegisterKindDWARF, dwarf_r12);
2308 context.SetRegisterPlusOffset(*dwarf_reg, -ip_offset);
2310 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r7, addr))
2311 return false;
2313 return true;
2316 // Set ip to point to some stack offset.
2317 // SUB (SP minus immediate)
2318 bool EmulateInstructionARM::EmulateSUBIPSPImm(const uint32_t opcode,
2319 const ARMEncoding encoding) {
2320 #if 0
2321 // ARM pseudo code...
2322 if (ConditionPassed())
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;
2336 #endif
2338 if (ConditionPassed(opcode)) {
2339 bool success = false;
2340 const addr_t sp = ReadCoreReg(SP_REG, &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;
2351 addr_t sp_offset = imm32;
2352 addr_t addr = sp - sp_offset; // the adjusted stack pointer value
2354 EmulateInstruction::Context context;
2355 context.type = EmulateInstruction::eContextRegisterPlusOffset;
2356 std::optional<RegisterInfo> dwarf_reg =
2357 GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
2358 context.SetRegisterPlusOffset(*dwarf_reg, -sp_offset);
2360 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r12, addr))
2361 return false;
2363 return true;
2366 // This instruction subtracts an immediate value from the SP value, and writes
2367 // the result to the destination register.
2369 // If Rd == 13 => A sub operation to adjust the SP -- allocate space for local
2370 // storage.
2371 bool EmulateInstructionARM::EmulateSUBSPImm(const uint32_t opcode,
2372 const ARMEncoding encoding) {
2373 #if 0
2374 // ARM pseudo code...
2375 if (ConditionPassed())
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;
2389 #endif
2391 bool success = false;
2392 if (ConditionPassed(opcode)) {
2393 const addr_t sp = ReadCoreReg(SP_REG, &success);
2394 if (!success)
2395 return false;
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(opcode, 11, 8);
2408 setflags = BitIsSet(opcode, 20);
2409 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
2410 if (Rd == 15 && setflags)
2411 return EmulateCMPImm(opcode, eEncodingT2);
2412 if (Rd == 15 && !setflags)
2413 return false;
2414 break;
2415 case eEncodingT3:
2416 Rd = Bits32(opcode, 11, 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(opcode, 15, 12);
2424 setflags = BitIsSet(opcode, 20);
2425 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
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;
2435 AddWithCarryResult res = AddWithCarry(sp, ~imm32, 1);
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();
2449 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
2450 res.carry_out, res.overflow))
2451 return false;
2453 return true;
2456 // A store operation to the stack that also updates the SP.
2457 bool EmulateInstructionARM::EmulateSTRRtSP(const uint32_t opcode,
2458 const ARMEncoding encoding) {
2459 #if 0
2460 // ARM pseudo code...
2461 if (ConditionPassed())
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;
2469 #endif
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);
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.
2482 bool index;
2483 bool add;
2484 bool wback;
2485 switch (encoding) {
2486 case eEncodingA1:
2487 Rt = Bits32(opcode, 15, 12);
2488 imm12 = Bits32(opcode, 11, 0);
2489 Rn = Bits32(opcode, 19, 16);
2491 if (Rn != 13) // 13 is the SP reg on ARM. Verify that Rn == SP.
2492 return false;
2494 index = BitIsSet(opcode, 24);
2495 add = BitIsSet(opcode, 23);
2496 wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21));
2498 if (wback && ((Rn == 15) || (Rn == Rt)))
2499 return false;
2500 break;
2501 default:
2502 return false;
2504 addr_t offset_addr;
2505 if (add)
2506 offset_addr = sp + imm12;
2507 else
2508 offset_addr = sp - imm12;
2510 addr_t addr;
2511 if (index)
2512 addr = offset_addr;
2513 else
2514 addr = sp;
2516 EmulateInstruction::Context context;
2517 context.type = EmulateInstruction::eContextPushRegisterOnStack;
2518 std::optional<RegisterInfo> sp_reg =
2519 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp);
2520 std::optional<RegisterInfo> dwarf_reg =
2521 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rt);
2523 context.SetRegisterToRegisterPlusOffset(*dwarf_reg, *sp_reg, addr - sp);
2524 if (Rt != 15) {
2525 uint32_t reg_value = ReadCoreReg(Rt, &success);
2526 if (!success)
2527 return false;
2528 if (!MemUWrite(context, addr, reg_value, addr_byte_size))
2529 return false;
2530 } else {
2531 const uint32_t pc = ReadCoreReg(PC_REG, &success);
2532 if (!success)
2533 return false;
2534 if (!MemUWrite(context, addr, pc, addr_byte_size))
2535 return false;
2538 if (wback) {
2539 context.type = EmulateInstruction::eContextAdjustStackPointer;
2540 context.SetImmediateSigned(addr - sp);
2541 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
2542 LLDB_REGNUM_GENERIC_SP, offset_addr))
2543 return false;
2546 return true;
2549 // Vector Push stores multiple extension registers to the stack. It also
2550 // updates SP to point to the start of the stored data.
2551 bool EmulateInstructionARM::EmulateVPUSH(const uint32_t opcode,
2552 const ARMEncoding encoding) {
2553 #if 0
2554 // ARM pseudo code...
2555 if (ConditionPassed())
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;
2571 #endif
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);
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(opcode, 22) << 4 | Bits32(opcode, 15, 12);
2588 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
2589 // If UInt(imm8) is odd, see "FSTMX".
2590 regs = Bits32(opcode, 7, 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(opcode, 15, 12) << 1 | Bit32(opcode, 22);
2599 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
2600 regs = Bits32(opcode, 7, 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;
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;
2614 EmulateInstruction::Context context;
2615 context.type = EmulateInstruction::eContextPushRegisterOnStack;
2617 std::optional<RegisterInfo> sp_reg =
2618 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp);
2619 for (i = 0; i < regs; ++i) {
2620 std::optional<RegisterInfo> dwarf_reg =
2621 GetRegisterInfo(eRegisterKindDWARF, start_reg + d + i);
2622 context.SetRegisterToRegisterPlusOffset(*dwarf_reg, *sp_reg, addr - sp);
2623 // uint64_t to accommodate 64-bit registers.
2624 uint64_t reg_value = ReadRegisterUnsigned(*dwarf_reg, 0, &success);
2625 if (!success)
2626 return false;
2627 if (!MemAWrite(context, addr, reg_value, reg_byte_size))
2628 return false;
2629 addr += reg_byte_size;
2632 context.type = EmulateInstruction::eContextAdjustStackPointer;
2633 context.SetImmediateSigned(-sp_offset);
2635 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
2636 LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
2637 return false;
2639 return true;
2642 // Vector Pop loads multiple extension registers from the stack. It also
2643 // updates SP to point just above the loaded data.
2644 bool EmulateInstructionARM::EmulateVPOP(const uint32_t opcode,
2645 const ARMEncoding encoding) {
2646 #if 0
2647 // ARM pseudo code...
2648 if (ConditionPassed())
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;
2663 #endif
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);
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(opcode, 22) << 4 | Bits32(opcode, 15, 12);
2680 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
2681 // If UInt(imm8) is odd, see "FLDMX".
2682 regs = Bits32(opcode, 7, 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(opcode, 15, 12) << 1 | Bit32(opcode, 22);
2691 imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
2692 regs = Bits32(opcode, 7, 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;
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.
2707 EmulateInstruction::Context context;
2708 context.type = EmulateInstruction::eContextPopRegisterOffStack;
2710 for (i = 0; i < regs; ++i) {
2711 std::optional<RegisterInfo> dwarf_reg =
2712 GetRegisterInfo(eRegisterKindDWARF, start_reg + d + i);
2713 context.SetAddress(addr);
2714 data = MemARead(context, addr, reg_byte_size, 0, &success);
2715 if (!success)
2716 return false;
2717 if (!WriteRegisterUnsigned(context, *dwarf_reg, data))
2718 return false;
2719 addr += reg_byte_size;
2722 context.type = EmulateInstruction::eContextAdjustStackPointer;
2723 context.SetImmediateSigned(sp_offset);
2725 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
2726 LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
2727 return false;
2729 return true;
2732 // SVC (previously SWI)
2733 bool EmulateInstructionARM::EmulateSVC(const uint32_t opcode,
2734 const ARMEncoding encoding) {
2735 #if 0
2736 // ARM pseudo code...
2737 if (ConditionPassed())
2739 EncodingSpecificOperations();
2740 CallSupervisor();
2742 #endif
2744 bool success = false;
2746 if (ConditionPassed(opcode)) {
2747 const uint32_t pc = ReadCoreReg(PC_REG, &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(opcode, 7, 0);
2757 mode = eModeThumb;
2758 break;
2759 case eEncodingA1:
2760 lr = pc + 4; // return address
2761 imm32 = Bits32(opcode, 23, 0);
2762 mode = eModeARM;
2763 break;
2764 default:
2765 return false;
2768 EmulateInstruction::Context context;
2769 context.type = EmulateInstruction::eContextSupervisorCall;
2770 context.SetISAAndImmediate(mode, imm32);
2771 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
2772 LLDB_REGNUM_GENERIC_RA, lr))
2773 return false;
2775 return true;
2778 // If Then makes up to four following instructions (the IT block) conditional.
2779 bool 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
2787 m_it_session.InitIT(Bits32(opcode, 7, 0));
2788 return true;
2791 bool EmulateInstructionARM::EmulateNop(const uint32_t opcode,
2792 const ARMEncoding encoding) {
2793 // NOP, nothing to do...
2794 return true;
2797 // Branch causes a branch to a target address.
2798 bool EmulateInstructionARM::EmulateB(const uint32_t opcode,
2799 const ARMEncoding encoding) {
2800 #if 0
2801 // ARM pseudo code...
2802 if (ConditionPassed())
2804 EncodingSpecificOperations();
2805 BranchWritePC(PC + imm32);
2807 #endif
2809 bool success = false;
2811 if (ConditionPassed(opcode)) {
2812 EmulateInstruction::Context context;
2813 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
2814 const uint32_t pc = ReadCoreReg(PC_REG, &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>(Bits32(opcode, 7, 0) << 1);
2823 target = pc + imm32;
2824 context.SetISAAndImmediateSigned(eModeThumb, 4 + imm32);
2825 break;
2826 case eEncodingT2:
2827 imm32 = llvm::SignExtend32<12>(Bits32(opcode, 10, 0) << 1);
2828 target = pc + imm32;
2829 context.SetISAAndImmediateSigned(eModeThumb, 4 + imm32);
2830 break;
2831 case eEncodingT3:
2832 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
2834 if (Bits32(opcode, 25, 23) == 7)
2835 return false; // See Branches and miscellaneous control on page
2836 // A6-235.
2838 uint32_t S = Bit32(opcode, 26);
2839 uint32_t imm6 = Bits32(opcode, 21, 16);
2840 uint32_t J1 = Bit32(opcode, 13);
2841 uint32_t J2 = Bit32(opcode, 11);
2842 uint32_t imm11 = Bits32(opcode, 10, 0);
2843 uint32_t imm21 =
2844 (S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) | (imm11 << 1);
2845 imm32 = llvm::SignExtend32<21>(imm21);
2846 target = pc + imm32;
2847 context.SetISAAndImmediateSigned(eModeThumb, 4 + imm32);
2848 break;
2850 case eEncodingT4: {
2851 uint32_t S = Bit32(opcode, 26);
2852 uint32_t imm10 = Bits32(opcode, 25, 16);
2853 uint32_t J1 = Bit32(opcode, 13);
2854 uint32_t J2 = Bit32(opcode, 11);
2855 uint32_t imm11 = Bits32(opcode, 10, 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>(imm25);
2861 target = pc + imm32;
2862 context.SetISAAndImmediateSigned(eModeThumb, 4 + imm32);
2863 break;
2865 case eEncodingA1:
2866 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
2867 target = pc + imm32;
2868 context.SetISAAndImmediateSigned(eModeARM, 8 + imm32);
2869 break;
2870 default:
2871 return false;
2873 if (!BranchWritePC(context, target))
2874 return false;
2876 return true;
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
2882 bool 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
2891 bool success = false;
2893 // Read the register value from the operand register Rn.
2894 uint32_t reg_val = ReadCoreReg(Bits32(opcode, 2, 0), &success);
2895 if (!success)
2896 return false;
2898 EmulateInstruction::Context context;
2899 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
2900 const uint32_t pc = ReadCoreReg(PC_REG, &success);
2901 if (!success)
2902 return false;
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(opcode, 9) << 6 | Bits32(opcode, 7, 3) << 1;
2910 nonzero = BitIsSet(opcode, 11);
2911 target = pc + imm32;
2912 context.SetISAAndImmediateSigned(eModeThumb, 4 + imm32);
2913 break;
2914 default:
2915 return false;
2917 if (m_ignore_conditions || (nonzero ^ (reg_val == 0)))
2918 if (!BranchWritePC(context, target))
2919 return false;
2921 return true;
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.
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
2936 bool 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
2948 bool success = false;
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(opcode, 19, 16);
2959 Rm = Bits32(opcode, 3, 0);
2960 is_tbh = BitIsSet(opcode, 4);
2961 if (Rn == 13 || BadReg(Rm))
2962 return false;
2963 if (InITBlock() && !LastInITBlock())
2964 return false;
2965 break;
2966 default:
2967 return false;
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(Rn, &success);
2973 if (!success)
2974 return false;
2976 // the table index
2977 uint32_t index = ReadCoreReg(Rm, &success);
2978 if (!success)
2979 return false;
2981 // the offsetted table address
2982 addr_t addr = base + (is_tbh ? index * 2 : index);
2984 // PC-relative offset to branch forward
2985 EmulateInstruction::Context context;
2986 context.type = EmulateInstruction::eContextTableBranchReadMemory;
2987 uint32_t offset = MemURead(context, addr, is_tbh ? 2 : 1, 0, &success) * 2;
2988 if (!success)
2989 return false;
2991 const uint32_t pc = ReadCoreReg(PC_REG, &success);
2992 if (!success)
2993 return false;
2995 // target address
2996 addr_t target = pc + offset;
2997 context.type = EmulateInstruction::eContextRelativeBranchImmediate;
2998 context.SetISAAndImmediateSigned(eModeThumb, 4 + offset);
3000 if (!BranchWritePC(context, target))
3001 return false;
3004 return true;
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.
3010 bool 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
3024 bool success = false;
3026 if (ConditionPassed(opcode)) {
3027 uint32_t d;
3028 uint32_t n;
3029 bool setflags;
3030 uint32_t imm32;
3031 uint32_t carry_out;
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(opcode, 2, 0);
3039 n = Bits32(opcode, 5, 3);
3040 setflags = !InITBlock();
3041 imm32 = Bits32(opcode, 8, 6);
3043 break;
3045 case eEncodingT2:
3046 // d = UInt(Rdn); n = UInt(Rdn); setflags = !InITBlock(); imm32 =
3047 // ZeroExtend(imm8, 32);
3048 d = Bits32(opcode, 10, 8);
3049 n = Bits32(opcode, 10, 8);
3050 setflags = !InITBlock();
3051 imm32 = Bits32(opcode, 7, 0);
3053 break;
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(opcode, 11, 8);
3060 n = Bits32(opcode, 19, 16);
3061 setflags = BitIsSet(opcode, 20);
3062 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry_out);
3064 // if Rn == '1101' then SEE ADD (SP plus immediate);
3065 if (n == 13)
3066 return EmulateADDSPImm(opcode, eEncodingT3);
3068 // if BadReg(d) || n == 15 then UNPREDICTABLE;
3069 if (BadReg(d) || (n == 15))
3070 return false;
3072 break;
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(opcode, 11, 8);
3079 n = Bits32(opcode, 19, 16);
3080 setflags = false;
3081 uint32_t i = Bit32(opcode, 26);
3082 uint32_t imm3 = Bits32(opcode, 14, 12);
3083 uint32_t imm8 = Bits32(opcode, 7, 0);
3084 imm32 = (i << 11) | (imm3 << 8) | imm8;
3086 // if Rn == '1101' then SEE ADD (SP plus immediate);
3087 if (n == 13)
3088 return EmulateADDSPImm(opcode, eEncodingT4);
3090 // if BadReg(d) then UNPREDICTABLE;
3091 if (BadReg(d))
3092 return false;
3094 break;
3097 default:
3098 return false;
3101 uint64_t Rn =
3102 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3103 if (!success)
3104 return false;
3106 //(result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
3107 AddWithCarryResult res = AddWithCarry(Rn, imm32, 0);
3109 std::optional<RegisterInfo> reg_n =
3110 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
3111 EmulateInstruction::Context context;
3112 context.type = eContextArithmetic;
3113 context.SetRegisterPlusOffset(*reg_n, imm32);
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, res.result, d, setflags,
3122 res.carry_out, res.overflow))
3123 return false;
3125 return true;
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.
3131 bool 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
3149 bool success = false;
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(opcode, 15, 12);
3159 Rn = Bits32(opcode, 19, 16);
3160 setflags = BitIsSet(opcode, 20);
3161 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
3162 break;
3163 default:
3164 return false;
3167 // Read the first operand.
3168 uint32_t val1 = ReadCoreReg(Rn, &success);
3169 if (!success)
3170 return false;
3172 AddWithCarryResult res = AddWithCarry(val1, imm32, 0);
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;
3182 std::optional<RegisterInfo> dwarf_reg =
3183 GetRegisterInfo(eRegisterKindDWARF, Rn);
3184 context.SetRegisterPlusOffset(*dwarf_reg, imm32);
3186 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
3187 res.carry_out, res.overflow))
3188 return false;
3190 return true;
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.
3196 bool 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
3215 bool success = false;
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(opcode, 2, 0);
3225 Rn = Bits32(opcode, 5, 3);
3226 Rm = Bits32(opcode, 8, 6);
3227 setflags = !InITBlock();
3228 shift_t = SRType_LSL;
3229 shift_n = 0;
3230 break;
3231 case eEncodingT2:
3232 Rd = Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
3233 Rm = Bits32(opcode, 6, 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(opcode, 15, 12);
3244 Rn = Bits32(opcode, 19, 16);
3245 Rm = Bits32(opcode, 3, 0);
3246 setflags = BitIsSet(opcode, 20);
3247 shift_n = DecodeImmShiftARM(opcode, shift_t);
3248 break;
3249 default:
3250 return false;
3253 // Read the first operand.
3254 uint32_t val1 = ReadCoreReg(Rn, &success);
3255 if (!success)
3256 return false;
3258 // Read the second operand.
3259 uint32_t val2 = ReadCoreReg(Rm, &success);
3260 if (!success)
3261 return false;
3263 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
3264 if (!success)
3265 return false;
3266 AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
3268 EmulateInstruction::Context context;
3269 context.type = eContextArithmetic;
3270 std::optional<RegisterInfo> op1_reg =
3271 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rn);
3272 std::optional<RegisterInfo> op2_reg =
3273 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rm);
3274 context.SetRegisterRegisterOperands(*op1_reg, *op2_reg);
3276 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
3277 res.carry_out, res.overflow))
3278 return false;
3280 return true;
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.
3285 bool 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
3298 bool success = false;
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(opcode, 19, 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(opcode, 19, 16);
3311 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
3312 break;
3313 default:
3314 return false;
3316 // Read the register value from the operand register Rn.
3317 uint32_t reg_val = ReadCoreReg(Rn, &success);
3318 if (!success)
3319 return false;
3321 AddWithCarryResult res = AddWithCarry(reg_val, imm32, 0);
3323 EmulateInstruction::Context context;
3324 context.type = EmulateInstruction::eContextImmediate;
3325 context.SetNoArgs();
3326 return WriteFlags(context, res.result, res.carry_out, res.overflow);
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.
3332 bool 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
3346 bool success = false;
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(opcode, 2, 0);
3355 Rm = Bits32(opcode, 5, 3);
3356 shift_t = SRType_LSL;
3357 shift_n = 0;
3358 break;
3359 case eEncodingT2:
3360 Rn = Bits32(opcode, 19, 16);
3361 Rm = Bits32(opcode, 3, 0);
3362 shift_n = DecodeImmShiftThumb(opcode, shift_t);
3363 // if n == 15 || BadReg(m) then UNPREDICTABLE;
3364 if (Rn == 15 || BadReg(Rm))
3365 return false;
3366 break;
3367 case eEncodingA1:
3368 Rn = Bits32(opcode, 19, 16);
3369 Rm = Bits32(opcode, 3, 0);
3370 shift_n = DecodeImmShiftARM(opcode, shift_t);
3371 break;
3372 default:
3373 return false;
3375 // Read the register value from register Rn.
3376 uint32_t val1 = ReadCoreReg(Rn, &success);
3377 if (!success)
3378 return false;
3380 // Read the register value from register Rm.
3381 uint32_t val2 = ReadCoreReg(Rm, &success);
3382 if (!success)
3383 return false;
3385 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
3386 if (!success)
3387 return false;
3388 AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
3390 EmulateInstruction::Context context;
3391 context.type = EmulateInstruction::eContextImmediate;
3392 context.SetNoArgs();
3393 return WriteFlags(context, res.result, res.carry_out, res.overflow);
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.
3398 bool 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
3411 bool success = false;
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(opcode, 10, 8);
3418 imm32 = Bits32(opcode, 7, 0);
3419 break;
3420 case eEncodingT2:
3421 Rn = Bits32(opcode, 19, 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(opcode, 19, 16);
3428 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
3429 break;
3430 default:
3431 return false;
3433 // Read the register value from the operand register Rn.
3434 uint32_t reg_val = ReadCoreReg(Rn, &success);
3435 if (!success)
3436 return false;
3438 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
3440 EmulateInstruction::Context context;
3441 context.type = EmulateInstruction::eContextImmediate;
3442 context.SetNoArgs();
3443 return WriteFlags(context, res.result, res.carry_out, res.overflow);
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.
3449 bool 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
3463 bool success = false;
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(opcode, 2, 0);
3472 Rm = Bits32(opcode, 5, 3);
3473 shift_t = SRType_LSL;
3474 shift_n = 0;
3475 break;
3476 case eEncodingT2:
3477 Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
3478 Rm = Bits32(opcode, 6, 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(opcode, 19, 16);
3488 Rm = Bits32(opcode, 3, 0);
3489 shift_n = DecodeImmShiftThumb(opcode, shift_t);
3490 if (Rn == 15 || BadReg(Rm))
3491 return false;
3492 break;
3493 case eEncodingA1:
3494 Rn = Bits32(opcode, 19, 16);
3495 Rm = Bits32(opcode, 3, 0);
3496 shift_n = DecodeImmShiftARM(opcode, shift_t);
3497 break;
3498 default:
3499 return false;
3501 // Read the register value from register Rn.
3502 uint32_t val1 = ReadCoreReg(Rn, &success);
3503 if (!success)
3504 return false;
3506 // Read the register value from register Rm.
3507 uint32_t val2 = ReadCoreReg(Rm, &success);
3508 if (!success)
3509 return false;
3511 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
3512 if (!success)
3513 return false;
3514 AddWithCarryResult res = AddWithCarry(val1, ~shifted, 1);
3516 EmulateInstruction::Context context;
3517 context.type = EmulateInstruction::eContextImmediate;
3518 context.SetNoArgs();
3519 return WriteFlags(context, res.result, res.carry_out, res.overflow);
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.
3526 bool 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
3544 return EmulateShiftImm(opcode, encoding, SRType_ASR);
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.
3552 bool 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
3568 return EmulateShiftReg(opcode, encoding, SRType_ASR);
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.
3574 bool 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
3592 return EmulateShiftImm(opcode, encoding, SRType_LSL);
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.
3599 bool 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
3615 return EmulateShiftReg(opcode, encoding, SRType_LSL);
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.
3622 bool 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
3640 return EmulateShiftImm(opcode, encoding, SRType_LSR);
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.
3647 bool 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
3663 return EmulateShiftReg(opcode, encoding, SRType_LSR);
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.
3670 bool 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
3688 return EmulateShiftImm(opcode, encoding, SRType_ROR);
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.
3696 bool 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
3712 return EmulateShiftReg(opcode, encoding, SRType_ROR);
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].
3718 // RRX can optionally update the condition flags based on the result.
3719 // In that case, bit [0] is shifted into the carry flag.
3720 bool 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
3738 return EmulateShiftImm(opcode, encoding, SRType_RRX);
3741 bool 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);
3750 bool success = false;
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;
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;
3769 switch (use_encoding) {
3770 case eEncodingT1:
3771 Rd = Bits32(opcode, 2, 0);
3772 Rm = Bits32(opcode, 5, 3);
3773 setflags = !InITBlock();
3774 imm5 = Bits32(opcode, 10, 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;
3782 Rd = Bits32(opcode, 11, 8);
3783 Rm = Bits32(opcode, 3, 0);
3784 setflags = BitIsSet(opcode, 20);
3785 imm5 = Bits32(opcode, 14, 12) << 2 | Bits32(opcode, 7, 6);
3786 if (BadReg(Rd) || BadReg(Rm))
3787 return false;
3788 break;
3789 case eEncodingA1:
3790 Rd = Bits32(opcode, 15, 12);
3791 Rm = Bits32(opcode, 3, 0);
3792 setflags = BitIsSet(opcode, 20);
3793 imm5 = Bits32(opcode, 11, 7);
3794 break;
3795 default:
3796 return false;
3799 // A8.6.139 ROR (immediate)
3800 if (shift_type == SRType_ROR && imm5 == 0)
3801 shift_type = SRType_RRX;
3803 // Get the first operand.
3804 uint32_t value = ReadCoreReg(Rm, &success);
3805 if (!success)
3806 return false;
3808 // Decode the shift amount if not RRX.
3809 uint32_t amt =
3810 (shift_type == SRType_RRX ? 1 : DecodeImmShift(shift_type, imm5));
3812 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry, &success);
3813 if (!success)
3814 return false;
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();
3821 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
3822 return false;
3824 return true;
3827 bool 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);
3835 bool success = false;
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(opcode, 2, 0);
3847 Rn = Rd;
3848 Rm = Bits32(opcode, 5, 3);
3849 setflags = !InITBlock();
3850 break;
3851 case eEncodingT2:
3852 Rd = Bits32(opcode, 11, 8);
3853 Rn = Bits32(opcode, 19, 16);
3854 Rm = Bits32(opcode, 3, 0);
3855 setflags = BitIsSet(opcode, 20);
3856 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
3857 return false;
3858 break;
3859 case eEncodingA1:
3860 Rd = Bits32(opcode, 15, 12);
3861 Rn = Bits32(opcode, 3, 0);
3862 Rm = Bits32(opcode, 11, 8);
3863 setflags = BitIsSet(opcode, 20);
3864 if (Rd == 15 || Rn == 15 || Rm == 15)
3865 return false;
3866 break;
3867 default:
3868 return false;
3871 // Get the first operand.
3872 uint32_t value = ReadCoreReg(Rn, &success);
3873 if (!success)
3874 return false;
3875 // Get the Rm register content.
3876 uint32_t val = ReadCoreReg(Rm, &success);
3877 if (!success)
3878 return false;
3880 // Get the shift amount.
3881 uint32_t amt = Bits32(val, 7, 0);
3883 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry, &success);
3884 if (!success)
3885 return false;
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();
3892 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
3893 return false;
3895 return true;
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.
3901 bool 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];
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]);
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
3918 #endif
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(opcode, 10, 8);
3931 registers = Bits32(opcode, 7, 0);
3932 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
3933 wback = BitIsClear(registers, n);
3934 // if BitCount(registers) < 1 then UNPREDICTABLE;
3935 if (BitCount(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(opcode, 19, 16);
3942 registers = Bits32(opcode, 15, 0);
3943 registers = registers & 0xdfff; // Make sure bit 13 is zero.
3944 wback = BitIsSet(opcode, 21);
3946 // if n == 15 || BitCount(registers) < 2 || (P == '1' && M == '1') then
3947 // UNPREDICTABLE;
3948 if ((n == 15) || (BitCount(registers) < 2) ||
3949 (BitIsSet(opcode, 14) && BitIsSet(opcode, 15)))
3950 return false;
3952 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then
3953 // UNPREDICTABLE;
3954 if (BitIsSet(registers, 15) && InITBlock() && !LastInITBlock())
3955 return false;
3957 // if wback && registers<n> == '1' then UNPREDICTABLE;
3958 if (wback && BitIsSet(registers, n))
3959 return false;
3960 break;
3962 case eEncodingA1:
3963 n = Bits32(opcode, 19, 16);
3964 registers = Bits32(opcode, 15, 0);
3965 wback = BitIsSet(opcode, 21);
3966 if ((n == 15) || (BitCount(registers) < 1))
3967 return false;
3968 break;
3969 default:
3970 return false;
3973 int32_t offset = 0;
3974 const addr_t base_address =
3975 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
3976 if (!success)
3977 return false;
3979 EmulateInstruction::Context context;
3980 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3981 std::optional<RegisterInfo> dwarf_reg =
3982 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
3983 context.SetRegisterPlusOffset(*dwarf_reg, offset);
3985 for (int i = 0; i < 14; ++i) {
3986 if (BitIsSet(registers, i)) {
3987 context.type = EmulateInstruction::eContextRegisterPlusOffset;
3988 context.SetRegisterPlusOffset(*dwarf_reg, offset);
3989 if (wback && (n == 13)) // Pop Instruction
3991 context.type = EmulateInstruction::eContextPopRegisterOffStack;
3992 context.SetAddress(base_address + offset);
3995 // R[i] = MemA [address, 4]; address = address + 4;
3996 uint32_t data = MemARead(context, base_address + offset, addr_byte_size,
3997 0, &success);
3998 if (!success)
3999 return false;
4001 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + i,
4002 data))
4003 return false;
4005 offset += addr_byte_size;
4009 if (BitIsSet(registers, 15)) {
4010 // LoadWritePC (MemA [address, 4]);
4011 context.type = EmulateInstruction::eContextRegisterPlusOffset;
4012 context.SetRegisterPlusOffset(*dwarf_reg, offset);
4013 uint32_t data =
4014 MemARead(context, base_address + offset, addr_byte_size, 0, &success);
4015 if (!success)
4016 return false;
4017 // In ARMv5T and above, this is an interworking branch.
4018 if (!LoadWritePC(context, data))
4019 return false;
4022 if (wback && BitIsClear(registers, n)) {
4023 // R[n] = R[n] + 4 * BitCount (registers)
4024 int32_t offset = addr_byte_size * BitCount(registers);
4025 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4026 context.SetRegisterPlusOffset(*dwarf_reg, offset);
4028 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
4029 base_address + offset))
4030 return false;
4032 if (wback && BitIsSet(registers, n))
4033 // R[n] bits(32) UNKNOWN;
4034 return WriteBits32Unknown(n);
4036 return true;
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.
4044 bool 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;
4052 for i = 0 to 14
4053 if registers<i> == '1' then
4054 R[i] = MemA[address,4]; address = address + 4;
4056 if registers<15> == '1' then
4057 LoadWritePC(MemA[address,4]);
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
4063 bool success = false;
4065 if (ConditionPassed(opcode)) {
4066 uint32_t n;
4067 uint32_t registers = 0;
4068 bool wback;
4069 const uint32_t addr_byte_size = GetAddressByteSize();
4071 // EncodingSpecificOperations();
4072 switch (encoding) {
4073 case eEncodingA1:
4074 // n = UInt(Rn); registers = register_list; wback = (W == '1');
4075 n = Bits32(opcode, 19, 16);
4076 registers = Bits32(opcode, 15, 0);
4077 wback = BitIsSet(opcode, 21);
4079 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4080 if ((n == 15) || (BitCount(registers) < 1))
4081 return false;
4083 break;
4085 default:
4086 return false;
4088 // address = R[n] - 4*BitCount(registers) + 4;
4090 int32_t offset = 0;
4091 addr_t Rn = ReadCoreReg(n, &success);
4093 if (!success)
4094 return false;
4096 addr_t address =
4097 Rn - (addr_byte_size * BitCount(registers)) + addr_byte_size;
4099 EmulateInstruction::Context context;
4100 context.type = EmulateInstruction::eContextRegisterPlusOffset;
4101 std::optional<RegisterInfo> dwarf_reg =
4102 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
4103 context.SetRegisterPlusOffset(*dwarf_reg, offset);
4105 // for i = 0 to 14
4106 for (int i = 0; i < 14; ++i) {
4107 // if registers<i> == '1' then
4108 if (BitIsSet(registers, i)) {
4109 // R[i] = MemA[address,4]; address = address + 4;
4110 context.SetRegisterPlusOffset(*dwarf_reg, Rn - (address + offset));
4111 uint32_t data =
4112 MemARead(context, address + offset, addr_byte_size, 0, &success);
4113 if (!success)
4114 return false;
4115 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + i,
4116 data))
4117 return false;
4118 offset += addr_byte_size;
4122 // if registers<15> == '1' then
4123 // LoadWritePC(MemA[address,4]);
4124 if (BitIsSet(registers, 15)) {
4125 context.SetRegisterPlusOffset(*dwarf_reg, offset);
4126 uint32_t data =
4127 MemARead(context, address + offset, addr_byte_size, 0, &success);
4128 if (!success)
4129 return false;
4130 // In ARMv5T and above, this is an interworking branch.
4131 if (!LoadWritePC(context, data))
4132 return false;
4135 // if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
4136 if (wback && BitIsClear(registers, n)) {
4138 offset = (addr_byte_size * BitCount(registers)) * -1;
4139 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4140 context.SetImmediateSigned(offset);
4141 addr_t addr = Rn + offset;
4142 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
4143 addr))
4144 return false;
4147 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
4148 if (wback && BitIsSet(registers, n))
4149 return WriteBits32Unknown(n);
4151 return true;
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.
4159 bool 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);
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]);
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
4177 bool success = false;
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(opcode, 19, 16);
4188 registers = Bits32(opcode, 15, 0);
4189 registers = registers & 0xdfff; // Make sure bit 13 is a zero.
4190 wback = BitIsSet(opcode, 21);
4192 // if n == 15 || BitCount(registers) < 2 || (P == '1' && M == '1') then
4193 // UNPREDICTABLE;
4194 if ((n == 15) || (BitCount(registers) < 2) ||
4195 (BitIsSet(opcode, 14) && BitIsSet(opcode, 15)))
4196 return false;
4198 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then
4199 // UNPREDICTABLE;
4200 if (BitIsSet(registers, 15) && InITBlock() && !LastInITBlock())
4201 return false;
4203 // if wback && registers<n> == '1' then UNPREDICTABLE;
4204 if (wback && BitIsSet(registers, n))
4205 return false;
4207 break;
4209 case eEncodingA1:
4210 // n = UInt(Rn); registers = register_list; wback = (W == '1');
4211 n = Bits32(opcode, 19, 16);
4212 registers = Bits32(opcode, 15, 0);
4213 wback = BitIsSet(opcode, 21);
4215 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4216 if ((n == 15) || (BitCount(registers) < 1))
4217 return false;
4219 break;
4221 default:
4222 return false;
4225 // address = R[n] - 4*BitCount(registers);
4227 int32_t offset = 0;
4228 addr_t Rn =
4229 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4231 if (!success)
4232 return false;
4234 addr_t address = Rn - (addr_byte_size * BitCount(registers));
4235 EmulateInstruction::Context context;
4236 context.type = EmulateInstruction::eContextRegisterPlusOffset;
4237 std::optional<RegisterInfo> dwarf_reg =
4238 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
4239 context.SetRegisterPlusOffset(*dwarf_reg, Rn - address);
4241 for (int i = 0; i < 14; ++i) {
4242 if (BitIsSet(registers, i)) {
4243 // R[i] = MemA[address,4]; address = address + 4;
4244 context.SetRegisterPlusOffset(*dwarf_reg, Rn - (address + offset));
4245 uint32_t data =
4246 MemARead(context, address + offset, addr_byte_size, 0, &success);
4247 if (!success)
4248 return false;
4250 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + i,
4251 data))
4252 return false;
4254 offset += addr_byte_size;
4258 // if registers<15> == '1' then
4259 // LoadWritePC(MemA[address,4]);
4260 if (BitIsSet(registers, 15)) {
4261 context.SetRegisterPlusOffset(*dwarf_reg, offset);
4262 uint32_t data =
4263 MemARead(context, address + offset, addr_byte_size, 0, &success);
4264 if (!success)
4265 return false;
4266 // In ARMv5T and above, this is an interworking branch.
4267 if (!LoadWritePC(context, data))
4268 return false;
4271 // if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
4272 if (wback && BitIsClear(registers, n)) {
4274 offset = (addr_byte_size * BitCount(registers)) * -1;
4275 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4276 context.SetImmediateSigned(offset);
4277 addr_t addr = Rn + offset;
4278 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
4279 addr))
4280 return false;
4283 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only
4284 // possible for encoding A1
4285 if (wback && BitIsSet(registers, n))
4286 return WriteBits32Unknown(n);
4288 return true;
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.
4296 bool EmulateInstructionARM::EmulateLDMIB(const uint32_t opcode,
4297 const ARMEncoding encoding) {
4298 #if 0
4299 if ConditionPassed() then
4300 EncodingSpecificOperations();
4301 address = R[n] + 4;
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]);
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
4313 bool success = false;
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(opcode, 19, 16);
4324 registers = Bits32(opcode, 15, 0);
4325 wback = BitIsSet(opcode, 21);
4327 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4328 if ((n == 15) || (BitCount(registers) < 1))
4329 return false;
4331 break;
4332 default:
4333 return false;
4335 // address = R[n] + 4;
4337 int32_t offset = 0;
4338 addr_t Rn =
4339 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4341 if (!success)
4342 return false;
4344 addr_t address = Rn + addr_byte_size;
4346 EmulateInstruction::Context context;
4347 context.type = EmulateInstruction::eContextRegisterPlusOffset;
4348 std::optional<RegisterInfo> dwarf_reg =
4349 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
4350 context.SetRegisterPlusOffset(*dwarf_reg, offset);
4352 for (int i = 0; i < 14; ++i) {
4353 if (BitIsSet(registers, i)) {
4354 // R[i] = MemA[address,4]; address = address + 4;
4356 context.SetRegisterPlusOffset(*dwarf_reg, offset + addr_byte_size);
4357 uint32_t data =
4358 MemARead(context, address + offset, addr_byte_size, 0, &success);
4359 if (!success)
4360 return false;
4362 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + i,
4363 data))
4364 return false;
4366 offset += addr_byte_size;
4370 // if registers<15> == '1' then
4371 // LoadWritePC(MemA[address,4]);
4372 if (BitIsSet(registers, 15)) {
4373 context.SetRegisterPlusOffset(*dwarf_reg, offset);
4374 uint32_t data =
4375 MemARead(context, address + offset, addr_byte_size, 0, &success);
4376 if (!success)
4377 return false;
4378 // In ARMv5T and above, this is an interworking branch.
4379 if (!LoadWritePC(context, data))
4380 return false;
4383 // if wback && registers<n> == '0' then R[n] = R[n] + 4*BitCount(registers);
4384 if (wback && BitIsClear(registers, n)) {
4386 offset = addr_byte_size * BitCount(registers);
4387 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4388 context.SetImmediateSigned(offset);
4389 addr_t addr = Rn + offset;
4390 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
4391 addr))
4392 return false;
4395 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only
4396 // possible for encoding A1
4397 if (wback && BitIsSet(registers, n))
4398 return WriteBits32Unknown(n);
4400 return true;
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)
4406 bool EmulateInstructionARM::EmulateLDRRtRnImm(const uint32_t opcode,
4407 const ARMEncoding encoding) {
4408 #if 0
4409 // ARM pseudo code...
4410 if (ConditionPassed())
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
4423 #endif
4425 bool success = false;
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(opcode, 2, 0);
4438 Rn = Bits32(opcode, 5, 3);
4439 imm32 = Bits32(opcode, 10, 6) << 2; // imm32 = ZeroExtend(imm5:'00', 32);
4440 // index = TRUE; add = TRUE; wback = FALSE
4441 add = true;
4442 index = true;
4443 wback = false;
4445 break;
4447 case eEncodingT2:
4448 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:'00', 32);
4449 Rt = Bits32(opcode, 10, 8);
4450 Rn = 13;
4451 imm32 = Bits32(opcode, 7, 0) << 2;
4453 // index = TRUE; add = TRUE; wback = FALSE;
4454 index = true;
4455 add = true;
4456 wback = false;
4458 break;
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(opcode, 15, 12);
4464 Rn = Bits32(opcode, 19, 16);
4465 imm32 = Bits32(opcode, 11, 0);
4467 // index = TRUE; add = TRUE; wback = FALSE;
4468 index = true;
4469 add = true;
4470 wback = false;
4472 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
4473 if ((Rt == 15) && InITBlock() && !LastInITBlock())
4474 return false;
4476 break;
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(opcode, 10) && BitIsClear(opcode, 8))
4485 return false;
4487 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
4488 Rt = Bits32(opcode, 15, 12);
4489 Rn = Bits32(opcode, 19, 16);
4490 imm32 = Bits32(opcode, 7, 0);
4492 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
4493 index = BitIsSet(opcode, 10);
4494 add = BitIsSet(opcode, 9);
4495 wback = BitIsSet(opcode, 8);
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;
4503 break;
4505 default:
4506 return false;
4508 uint32_t base = ReadCoreReg(Rn, &success);
4509 if (!success)
4510 return false;
4511 if (add)
4512 offset_addr = base + imm32;
4513 else
4514 offset_addr = base - imm32;
4516 address = (index ? offset_addr : base);
4518 std::optional<RegisterInfo> base_reg =
4519 GetRegisterInfo(eRegisterKindDWARF, 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, (int32_t)(offset_addr - base));
4528 } else {
4529 ctx.type = EmulateInstruction::eContextAdjustBaseRegister;
4530 ctx.SetRegisterPlusOffset(*base_reg, (int32_t)(offset_addr - base));
4533 if (!WriteRegisterUnsigned(ctx, eRegisterKindDWARF, dwarf_r0 + Rn,
4534 offset_addr))
4535 return false;
4538 // Prepare to write to the Rt register.
4539 EmulateInstruction::Context context;
4540 context.type = EmulateInstruction::eContextRegisterLoad;
4541 context.SetRegisterPlusOffset(*base_reg, (int32_t)(offset_addr - base));
4543 // Read memory from the address.
4544 data = MemURead(context, address, 4, 0, &success);
4545 if (!success)
4546 return false;
4548 if (Rt == 15) {
4549 if (Bits32(address, 1, 0) == 0) {
4550 if (!LoadWritePC(context, data))
4551 return false;
4552 } else
4553 return false;
4554 } else if (UnalignedSupport() || Bits32(address, 1, 0) == 0) {
4555 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + Rt,
4556 data))
4557 return false;
4558 } else
4559 WriteBits32Unknown(Rt);
4561 return true;
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.
4569 bool 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];
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;
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
4589 bool success = false;
4591 if (ConditionPassed(opcode)) {
4592 uint32_t n;
4593 uint32_t registers = 0;
4594 bool wback;
4595 const uint32_t addr_byte_size = GetAddressByteSize();
4597 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4598 switch (encoding) {
4599 case eEncodingT1:
4600 // n = UInt(Rn); registers = '00000000':register_list; wback = TRUE;
4601 n = Bits32(opcode, 10, 8);
4602 registers = Bits32(opcode, 7, 0);
4603 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.
4604 wback = true;
4606 // if BitCount(registers) < 1 then UNPREDICTABLE;
4607 if (BitCount(registers) < 1)
4608 return false;
4610 break;
4612 case eEncodingT2:
4613 // n = UInt(Rn); registers = '0':M:'0':register_list; wback = (W == '1');
4614 n = Bits32(opcode, 19, 16);
4615 registers = Bits32(opcode, 15, 0);
4616 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
4617 wback = BitIsSet(opcode, 21);
4619 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
4620 if ((n == 15) || (BitCount(registers) < 2))
4621 return false;
4623 // if wback && registers<n> == '1' then UNPREDICTABLE;
4624 if (wback && BitIsSet(registers, n))
4625 return false;
4627 break;
4629 case eEncodingA1:
4630 // n = UInt(Rn); registers = register_list; wback = (W == '1');
4631 n = Bits32(opcode, 19, 16);
4632 registers = Bits32(opcode, 15, 0);
4633 wback = BitIsSet(opcode, 21);
4635 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4636 if ((n == 15) || (BitCount(registers) < 1))
4637 return false;
4639 break;
4641 default:
4642 return false;
4645 // address = R[n];
4646 int32_t offset = 0;
4647 const addr_t address =
4648 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4649 if (!success)
4650 return false;
4652 EmulateInstruction::Context context;
4653 context.type = EmulateInstruction::eContextRegisterStore;
4654 std::optional<RegisterInfo> base_reg =
4655 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
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(registers, 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 + offset);
4669 else {
4670 // MemA[address,4] = R[i];
4671 uint32_t data = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + i,
4672 0, &success);
4673 if (!success)
4674 return false;
4676 std::optional<RegisterInfo> data_reg =
4677 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + i);
4678 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, offset);
4679 if (!MemAWrite(context, address + offset, data, addr_byte_size))
4680 return false;
4683 // address = address + 4;
4684 offset += addr_byte_size;
4688 // if registers<15> == '1' then // Only possible for encoding A1
4689 // MemA[address,4] = PCStoreValue();
4690 if (BitIsSet(registers, 15)) {
4691 std::optional<RegisterInfo> pc_reg =
4692 GetRegisterInfo(eRegisterKindDWARF, dwarf_pc);
4693 context.SetRegisterPlusOffset(*pc_reg, 8);
4694 const uint32_t pc = ReadCoreReg(PC_REG, &success);
4695 if (!success)
4696 return false;
4698 if (!MemAWrite(context, address + offset, pc, addr_byte_size))
4699 return false;
4702 // if wback then R[n] = R[n] + 4*BitCount(registers);
4703 if (wback) {
4704 offset = addr_byte_size * BitCount(registers);
4705 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4706 context.SetImmediateSigned(offset);
4707 addr_t data = address + offset;
4708 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
4709 data))
4710 return false;
4713 return true;
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.
4721 bool 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;
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;
4736 if registers<15> == '1' then
4737 MemA[address,4] = PCStoreValue();
4739 if wback then R[n] = R[n] - 4*BitCount(registers);
4740 #endif
4742 bool success = false;
4744 if (ConditionPassed(opcode)) {
4745 uint32_t n;
4746 uint32_t registers = 0;
4747 bool wback;
4748 const uint32_t addr_byte_size = GetAddressByteSize();
4750 // EncodingSpecificOperations();
4751 switch (encoding) {
4752 case eEncodingA1:
4753 // n = UInt(Rn); registers = register_list; wback = (W == '1');
4754 n = Bits32(opcode, 19, 16);
4755 registers = Bits32(opcode, 15, 0);
4756 wback = BitIsSet(opcode, 21);
4758 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4759 if ((n == 15) || (BitCount(registers) < 1))
4760 return false;
4761 break;
4762 default:
4763 return false;
4766 // address = R[n] - 4*BitCount(registers) + 4;
4767 int32_t offset = 0;
4768 addr_t Rn = ReadCoreReg(n, &success);
4769 if (!success)
4770 return false;
4772 addr_t address = Rn - (addr_byte_size * BitCount(registers)) + 4;
4774 EmulateInstruction::Context context;
4775 context.type = EmulateInstruction::eContextRegisterStore;
4776 std::optional<RegisterInfo> base_reg =
4777 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
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(registers, 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 + offset);
4790 else {
4791 // MemA[address,4] = R[i];
4792 uint32_t data = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + i,
4793 0, &success);
4794 if (!success)
4795 return false;
4797 std::optional<RegisterInfo> data_reg =
4798 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + i);
4799 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg,
4800 Rn - (address + offset));
4801 if (!MemAWrite(context, address + offset, data, addr_byte_size))
4802 return false;
4805 // address = address + 4;
4806 offset += addr_byte_size;
4810 // if registers<15> == '1' then
4811 // MemA[address,4] = PCStoreValue();
4812 if (BitIsSet(registers, 15)) {
4813 std::optional<RegisterInfo> pc_reg =
4814 GetRegisterInfo(eRegisterKindDWARF, dwarf_pc);
4815 context.SetRegisterPlusOffset(*pc_reg, 8);
4816 const uint32_t pc = ReadCoreReg(PC_REG, &success);
4817 if (!success)
4818 return false;
4820 if (!MemAWrite(context, address + offset, pc, addr_byte_size))
4821 return false;
4824 // if wback then R[n] = R[n] - 4*BitCount(registers);
4825 if (wback) {
4826 offset = (addr_byte_size * BitCount(registers)) * -1;
4827 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4828 context.SetImmediateSigned(offset);
4829 addr_t data = Rn + offset;
4830 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
4831 data))
4832 return false;
4835 return true;
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.
4843 bool 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);
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;
4858 if registers<15> == '1' then // Only possible for encoding A1
4859 MemA[address,4] = PCStoreValue();
4861 if wback then R[n] = R[n] - 4*BitCount(registers);
4862 #endif
4864 bool success = false;
4866 if (ConditionPassed(opcode)) {
4867 uint32_t n;
4868 uint32_t registers = 0;
4869 bool wback;
4870 const uint32_t addr_byte_size = GetAddressByteSize();
4872 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
4873 switch (encoding) {
4874 case eEncodingT1:
4875 // if W == '1' && Rn == '1101' then SEE PUSH;
4876 if ((BitIsSet(opcode, 21)) && (Bits32(opcode, 19, 16) == 13)) {
4877 // See PUSH
4879 // n = UInt(Rn); registers = '0':M:'0':register_list; wback = (W == '1');
4880 n = Bits32(opcode, 19, 16);
4881 registers = Bits32(opcode, 15, 0);
4882 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
4883 wback = BitIsSet(opcode, 21);
4884 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
4885 if ((n == 15) || BitCount(registers) < 2)
4886 return false;
4887 // if wback && registers<n> == '1' then UNPREDICTABLE;
4888 if (wback && BitIsSet(registers, n))
4889 return false;
4890 break;
4892 case eEncodingA1:
4893 // if W == '1' && Rn == '1101' && BitCount(register_list) >= 2 then SEE
4894 // PUSH;
4895 if (BitIsSet(opcode, 21) && (Bits32(opcode, 19, 16) == 13) &&
4896 BitCount(Bits32(opcode, 15, 0)) >= 2) {
4897 // See Push
4899 // n = UInt(Rn); registers = register_list; wback = (W == '1');
4900 n = Bits32(opcode, 19, 16);
4901 registers = Bits32(opcode, 15, 0);
4902 wback = BitIsSet(opcode, 21);
4903 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
4904 if ((n == 15) || BitCount(registers) < 1)
4905 return false;
4906 break;
4908 default:
4909 return false;
4912 // address = R[n] - 4*BitCount(registers);
4914 int32_t offset = 0;
4915 addr_t Rn =
4916 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
4917 if (!success)
4918 return false;
4920 addr_t address = Rn - (addr_byte_size * BitCount(registers));
4922 EmulateInstruction::Context context;
4923 context.type = EmulateInstruction::eContextRegisterStore;
4924 std::optional<RegisterInfo> base_reg =
4925 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
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(registers, 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 + offset);
4939 else {
4940 // MemA[address,4] = R[i];
4941 uint32_t data = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + i,
4942 0, &success);
4943 if (!success)
4944 return false;
4946 std::optional<RegisterInfo> data_reg =
4947 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + i);
4948 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg,
4949 Rn - (address + offset));
4950 if (!MemAWrite(context, address + offset, data, addr_byte_size))
4951 return false;
4954 // address = address + 4;
4955 offset += addr_byte_size;
4959 // if registers<15> == '1' then // Only possible for encoding A1
4960 // MemA[address,4] = PCStoreValue();
4961 if (BitIsSet(registers, 15)) {
4962 std::optional<RegisterInfo> pc_reg =
4963 GetRegisterInfo(eRegisterKindDWARF, dwarf_pc);
4964 context.SetRegisterPlusOffset(*pc_reg, 8);
4965 const uint32_t pc = ReadCoreReg(PC_REG, &success);
4966 if (!success)
4967 return false;
4969 if (!MemAWrite(context, address + offset, pc, addr_byte_size))
4970 return false;
4973 // if wback then R[n] = R[n] - 4*BitCount(registers);
4974 if (wback) {
4975 offset = (addr_byte_size * BitCount(registers)) * -1;
4976 context.type = EmulateInstruction::eContextAdjustBaseRegister;
4977 context.SetImmediateSigned(offset);
4978 addr_t data = Rn + offset;
4979 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
4980 data))
4981 return false;
4984 return true;
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.
4992 bool EmulateInstructionARM::EmulateSTMIB(const uint32_t opcode,
4993 const ARMEncoding encoding) {
4994 #if 0
4995 if ConditionPassed() then
4996 EncodingSpecificOperations();
4997 address = R[n] + 4;
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;
5007 if registers<15> == '1' then
5008 MemA[address,4] = PCStoreValue();
5010 if wback then R[n] = R[n] + 4*BitCount(registers);
5011 #endif
5013 bool success = false;
5015 if (ConditionPassed(opcode)) {
5016 uint32_t n;
5017 uint32_t registers = 0;
5018 bool wback;
5019 const uint32_t addr_byte_size = GetAddressByteSize();
5021 // EncodingSpecificOperations();
5022 switch (encoding) {
5023 case eEncodingA1:
5024 // n = UInt(Rn); registers = register_list; wback = (W == '1');
5025 n = Bits32(opcode, 19, 16);
5026 registers = Bits32(opcode, 15, 0);
5027 wback = BitIsSet(opcode, 21);
5029 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
5030 if ((n == 15) && (BitCount(registers) < 1))
5031 return false;
5032 break;
5033 default:
5034 return false;
5036 // address = R[n] + 4;
5038 int32_t offset = 0;
5039 addr_t Rn = ReadCoreReg(n, &success);
5040 if (!success)
5041 return false;
5043 addr_t address = Rn + addr_byte_size;
5045 EmulateInstruction::Context context;
5046 context.type = EmulateInstruction::eContextRegisterStore;
5047 std::optional<RegisterInfo> base_reg =
5048 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
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(registers, 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 + offset);
5061 // else
5062 else {
5063 // MemA[address,4] = R[i];
5064 uint32_t data = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + i,
5065 0, &success);
5066 if (!success)
5067 return false;
5069 std::optional<RegisterInfo> data_reg =
5070 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + i);
5071 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg,
5072 offset + addr_byte_size);
5073 if (!MemAWrite(context, address + offset, data, addr_byte_size))
5074 return false;
5077 // address = address + 4;
5078 offset += addr_byte_size;
5082 // if registers<15> == '1' then
5083 // MemA[address,4] = PCStoreValue();
5084 if (BitIsSet(registers, 15)) {
5085 std::optional<RegisterInfo> pc_reg =
5086 GetRegisterInfo(eRegisterKindDWARF, dwarf_pc);
5087 context.SetRegisterPlusOffset(*pc_reg, 8);
5088 const uint32_t pc = ReadCoreReg(PC_REG, &success);
5089 if (!success)
5090 return false;
5092 if (!MemAWrite(context, address + offset, pc, addr_byte_size))
5093 return false;
5096 // if wback then R[n] = R[n] + 4*BitCount(registers);
5097 if (wback) {
5098 offset = addr_byte_size * BitCount(registers);
5099 context.type = EmulateInstruction::eContextAdjustBaseRegister;
5100 context.SetImmediateSigned(offset);
5101 addr_t data = Rn + offset;
5102 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
5103 data))
5104 return false;
5107 return true;
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.
5114 bool 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
5128 bool success = false;
5130 if (ConditionPassed(opcode)) {
5131 const uint32_t addr_byte_size = GetAddressByteSize();
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(opcode, 2, 0);
5144 n = Bits32(opcode, 5, 3);
5145 imm32 = Bits32(opcode, 10, 6) << 2;
5147 // index = TRUE; add = TRUE; wback = FALSE;
5148 index = true;
5149 add = false;
5150 wback = false;
5151 break;
5153 case eEncodingT2:
5154 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:'00', 32);
5155 t = Bits32(opcode, 10, 8);
5156 n = 13;
5157 imm32 = Bits32(opcode, 7, 0) << 2;
5159 // index = TRUE; add = TRUE; wback = FALSE;
5160 index = true;
5161 add = true;
5162 wback = false;
5163 break;
5165 case eEncodingT3:
5166 // if Rn == '1111' then UNDEFINED;
5167 if (Bits32(opcode, 19, 16) == 15)
5168 return false;
5170 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
5171 t = Bits32(opcode, 15, 12);
5172 n = Bits32(opcode, 19, 16);
5173 imm32 = Bits32(opcode, 11, 0);
5175 // index = TRUE; add = TRUE; wback = FALSE;
5176 index = true;
5177 add = true;
5178 wback = false;
5180 // if t == 15 then UNPREDICTABLE;
5181 if (t == 15)
5182 return false;
5183 break;
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(opcode, 19, 16) == 15) ||
5191 (BitIsClear(opcode, 10) && BitIsClear(opcode, 8)))
5192 return false;
5194 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
5195 t = Bits32(opcode, 15, 12);
5196 n = Bits32(opcode, 19, 16);
5197 imm32 = Bits32(opcode, 7, 0);
5199 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
5200 index = BitIsSet(opcode, 10);
5201 add = BitIsSet(opcode, 9);
5202 wback = BitIsSet(opcode, 8);
5204 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
5205 if ((t == 15) || (wback && (n == t)))
5206 return false;
5207 break;
5209 default:
5210 return false;
5213 addr_t offset_addr;
5214 addr_t address;
5216 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
5217 uint32_t base_address = ReadCoreReg(n, &success);
5218 if (!success)
5219 return false;
5221 if (add)
5222 offset_addr = base_address + imm32;
5223 else
5224 offset_addr = base_address - imm32;
5226 // address = if index then offset_addr else R[n];
5227 if (index)
5228 address = offset_addr;
5229 else
5230 address = base_address;
5232 EmulateInstruction::Context context;
5233 if (n == 13)
5234 context.type = eContextPushRegisterOnStack;
5235 else
5236 context.type = eContextRegisterStore;
5238 std::optional<RegisterInfo> base_reg =
5239 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
5241 // if UnalignedSupport() || address<1:0> == '00' then
5242 if (UnalignedSupport() ||
5243 (BitIsClear(address, 1) && BitIsClear(address, 0))) {
5244 // MemU[address,4] = R[t];
5245 uint32_t data =
5246 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
5247 if (!success)
5248 return false;
5250 std::optional<RegisterInfo> data_reg =
5251 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t);
5252 int32_t offset = address - base_address;
5253 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, offset);
5254 if (!MemUWrite(context, address, data, addr_byte_size))
5255 return false;
5256 } else {
5257 // MemU[address,4] = bits(32) UNKNOWN;
5258 WriteBits32UnknownToMemory(address);
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);
5269 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
5270 offset_addr))
5271 return false;
5274 return true;
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.
5281 bool 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
5300 bool success = false;
5302 if (ConditionPassed(opcode)) {
5303 const uint32_t addr_byte_size = GetAddressByteSize();
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;
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(opcode, 2, 0);
5321 n = Bits32(opcode, 5, 3);
5322 m = Bits32(opcode, 8, 6);
5324 // index = TRUE; add = TRUE; wback = FALSE;
5325 index = true;
5326 add = true;
5327 wback = false;
5329 // (shift_t, shift_n) = (SRType_LSL, 0);
5330 shift_t = SRType_LSL;
5331 shift_n = 0;
5332 break;
5334 case eEncodingT2:
5335 // if Rn == '1111' then UNDEFINED;
5336 if (Bits32(opcode, 19, 16) == 15)
5337 return false;
5339 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5340 t = Bits32(opcode, 15, 12);
5341 n = Bits32(opcode, 19, 16);
5342 m = Bits32(opcode, 3, 0);
5344 // index = TRUE; add = TRUE; wback = FALSE;
5345 index = true;
5346 add = true;
5347 wback = false;
5349 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
5350 shift_t = SRType_LSL;
5351 shift_n = Bits32(opcode, 5, 4);
5353 // if t == 15 || BadReg(m) then UNPREDICTABLE;
5354 if ((t == 15) || (BadReg(m)))
5355 return false;
5356 break;
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(opcode, 15, 12);
5362 n = Bits32(opcode, 19, 16);
5363 m = Bits32(opcode, 3, 0);
5365 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
5366 // (W == '1');
5367 index = BitIsSet(opcode, 24);
5368 add = BitIsSet(opcode, 23);
5369 wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21));
5371 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
5372 uint32_t typ = Bits32(opcode, 6, 5);
5373 uint32_t imm5 = Bits32(opcode, 11, 7);
5374 shift_n = DecodeImmShift(typ, imm5, shift_t);
5376 // if m == 15 then UNPREDICTABLE;
5377 if (m == 15)
5378 return false;
5380 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
5381 if (wback && ((n == 15) || (n == t)))
5382 return false;
5384 break;
5386 default:
5387 return false;
5390 addr_t offset_addr;
5391 addr_t address;
5392 int32_t offset = 0;
5394 addr_t base_address =
5395 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
5396 if (!success)
5397 return false;
5399 uint32_t Rm_data =
5400 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
5401 if (!success)
5402 return false;
5404 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
5405 offset = Shift(Rm_data, shift_t, shift_n, APSR_C, &success);
5406 if (!success)
5407 return false;
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;
5415 // address = if index then offset_addr else R[n];
5416 if (index)
5417 address = offset_addr;
5418 else
5419 address = base_address;
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);
5426 else
5427 // data = R[t];
5428 data =
5429 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
5431 if (!success)
5432 return false;
5434 EmulateInstruction::Context context;
5435 context.type = eContextRegisterStore;
5437 // if UnalignedSupport() || address<1:0> == '00' || CurrentInstrSet() ==
5438 // InstrSet_ARM then
5439 if (UnalignedSupport() ||
5440 (BitIsClear(address, 1) && BitIsClear(address, 0)) ||
5441 CurrentInstrSet() == eModeARM) {
5442 // MemU[address,4] = data;
5444 std::optional<RegisterInfo> base_reg =
5445 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
5446 std::optional<RegisterInfo> data_reg =
5447 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t);
5449 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg,
5450 address - base_address);
5451 if (!MemUWrite(context, address, data, addr_byte_size))
5452 return false;
5454 } else
5455 // MemU[address,4] = bits(32) UNKNOWN;
5456 WriteBits32UnknownToMemory(address);
5458 // if wback then R[n] = offset_addr;
5459 if (wback) {
5460 context.type = eContextRegisterLoad;
5461 context.SetAddress(offset_addr);
5462 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
5463 offset_addr))
5464 return false;
5467 return true;
5470 bool 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
5481 bool success = false;
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(opcode, 2, 0);
5495 n = Bits32(opcode, 5, 3);
5496 imm32 = Bits32(opcode, 10, 6);
5498 // index = TRUE; add = TRUE; wback = FALSE;
5499 index = true;
5500 add = true;
5501 wback = false;
5502 break;
5504 case eEncodingT2:
5505 // if Rn == '1111' then UNDEFINED;
5506 if (Bits32(opcode, 19, 16) == 15)
5507 return false;
5509 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
5510 t = Bits32(opcode, 15, 12);
5511 n = Bits32(opcode, 19, 16);
5512 imm32 = Bits32(opcode, 11, 0);
5514 // index = TRUE; add = TRUE; wback = FALSE;
5515 index = true;
5516 add = true;
5517 wback = false;
5519 // if BadReg(t) then UNPREDICTABLE;
5520 if (BadReg(t))
5521 return false;
5522 break;
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(opcode, 19, 16) == 15)
5528 return false;
5530 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
5531 t = Bits32(opcode, 15, 12);
5532 n = Bits32(opcode, 19, 16);
5533 imm32 = Bits32(opcode, 7, 0);
5535 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
5536 index = BitIsSet(opcode, 10);
5537 add = BitIsSet(opcode, 9);
5538 wback = BitIsSet(opcode, 8);
5540 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE
5541 if ((BadReg(t)) || (wback && (n == t)))
5542 return false;
5543 break;
5545 default:
5546 return false;
5549 addr_t offset_addr;
5550 addr_t address;
5551 addr_t base_address =
5552 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
5553 if (!success)
5554 return false;
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;
5562 // address = if index then offset_addr else R[n];
5563 if (index)
5564 address = offset_addr;
5565 else
5566 address = base_address;
5568 // MemU[address,1] = R[t]<7:0>
5569 std::optional<RegisterInfo> base_reg =
5570 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
5571 std::optional<RegisterInfo> data_reg =
5572 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t);
5574 EmulateInstruction::Context context;
5575 context.type = eContextRegisterStore;
5576 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg,
5577 address - base_address);
5579 uint32_t data =
5580 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
5581 if (!success)
5582 return false;
5584 data = Bits32(data, 7, 0);
5586 if (!MemUWrite(context, address, data, 1))
5587 return false;
5589 // if wback then R[n] = offset_addr;
5590 if (wback) {
5591 context.type = eContextRegisterLoad;
5592 context.SetAddress(offset_addr);
5593 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
5594 offset_addr))
5595 return false;
5599 return true;
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.
5606 bool 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
5621 bool success = false;
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;
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(opcode, 2, 0);
5640 n = Bits32(opcode, 5, 3);
5641 m = Bits32(opcode, 8, 6);
5643 // index = TRUE; add = TRUE; wback = FALSE;
5644 index = true;
5645 add = true;
5646 wback = false;
5648 // (shift_t, shift_n) = (SRType_LSL, 0);
5649 shift_t = SRType_LSL;
5650 shift_n = 0;
5652 break;
5654 case eEncodingT2:
5655 // if Rn == '1111' then UNDEFINED;
5656 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
5657 t = Bits32(opcode, 15, 12);
5658 n = Bits32(opcode, 19, 16);
5659 m = Bits32(opcode, 3, 0);
5660 if (n == 15)
5661 return false;
5663 // index = TRUE; add = TRUE; wback = FALSE;
5664 index = true;
5665 add = true;
5666 wback = false;
5668 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
5669 shift_t = SRType_LSL;
5670 shift_n = Bits32(opcode, 5, 4);
5672 // if BadReg(t) || BadReg(m) then UNPREDICTABLE;
5673 if (BadReg(t) || BadReg(m))
5674 return false;
5676 break;
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(opcode, 15, 12);
5682 n = Bits32(opcode, 19, 16);
5683 m = Bits32(opcode, 3, 0);
5685 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
5686 // (W == '1');
5687 index = BitIsSet(opcode, 24);
5688 add = BitIsSet(opcode, 23);
5689 wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21));
5691 // (shift_t, shift_n) = (SRType_LSL, 0);
5692 shift_t = SRType_LSL;
5693 shift_n = 0;
5695 // if t == 15 || m == 15 then UNPREDICTABLE;
5696 if ((t == 15) || (m == 15))
5697 return false;
5699 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
5700 if (wback && ((n == 15) || (n == t)))
5701 return false;
5703 break;
5705 default:
5706 return false;
5709 uint32_t Rm = ReadCoreReg(m, &success);
5710 if (!success)
5711 return false;
5713 uint32_t Rn = ReadCoreReg(n, &success);
5714 if (!success)
5715 return false;
5717 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
5718 uint32_t offset = Shift(Rm, shift_t, shift_n, APSR_C, &success);
5719 if (!success)
5720 return false;
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;
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;
5736 EmulateInstruction::Context context;
5737 context.type = eContextRegisterStore;
5739 // if UnalignedSupport() || address<0> == '0' then
5740 if (UnalignedSupport() || BitIsClear(address, 0)) {
5741 // MemU[address,2] = R[t]<15:0>;
5742 uint32_t Rt = ReadCoreReg(t, &success);
5743 if (!success)
5744 return false;
5746 EmulateInstruction::Context context;
5747 context.type = eContextRegisterStore;
5748 std::optional<RegisterInfo> base_reg =
5749 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
5750 std::optional<RegisterInfo> offset_reg =
5751 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m);
5752 std::optional<RegisterInfo> data_reg =
5753 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t);
5754 context.SetRegisterToRegisterPlusIndirectOffset(*base_reg, *offset_reg,
5755 *data_reg);
5757 if (!MemUWrite(context, address, Bits32(Rt, 15, 0), 2))
5758 return false;
5759 } else // Can only occur before ARMv7
5761 // MemU[address,2] = bits(16) UNKNOWN;
5764 // if wback then R[n] = offset_addr;
5765 if (wback) {
5766 context.type = eContextAdjustBaseRegister;
5767 context.SetAddress(offset_addr);
5768 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
5769 offset_addr))
5770 return false;
5774 return true;
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.
5780 bool 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
5798 bool success = false;
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(opcode, 11, 8);
5808 Rn = Bits32(opcode, 19, 16);
5809 setflags = BitIsSet(opcode, 20);
5810 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
5811 if (BadReg(Rd) || BadReg(Rn))
5812 return false;
5813 break;
5814 case eEncodingA1:
5815 Rd = Bits32(opcode, 15, 12);
5816 Rn = Bits32(opcode, 19, 16);
5817 setflags = BitIsSet(opcode, 20);
5818 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
5820 if (Rd == 15 && setflags)
5821 return EmulateSUBSPcLrEtc(opcode, encoding);
5822 break;
5823 default:
5824 return false;
5827 // Read the first operand.
5828 int32_t val1 = ReadCoreReg(Rn, &success);
5829 if (!success)
5830 return false;
5832 AddWithCarryResult res = AddWithCarry(val1, imm32, APSR_C);
5834 EmulateInstruction::Context context;
5835 context.type = EmulateInstruction::eContextImmediate;
5836 context.SetNoArgs();
5838 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
5839 res.carry_out, res.overflow))
5840 return false;
5842 return true;
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.
5849 bool 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
5868 bool success = false;
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(opcode, 2, 0);
5878 Rm = Bits32(opcode, 5, 3);
5879 setflags = !InITBlock();
5880 shift_t = SRType_LSL;
5881 shift_n = 0;
5882 break;
5883 case eEncodingT2:
5884 Rd = Bits32(opcode, 11, 8);
5885 Rn = Bits32(opcode, 19, 16);
5886 Rm = Bits32(opcode, 3, 0);
5887 setflags = BitIsSet(opcode, 20);
5888 shift_n = DecodeImmShiftThumb(opcode, shift_t);
5889 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
5890 return false;
5891 break;
5892 case eEncodingA1:
5893 Rd = Bits32(opcode, 15, 12);
5894 Rn = Bits32(opcode, 19, 16);
5895 Rm = Bits32(opcode, 3, 0);
5896 setflags = BitIsSet(opcode, 20);
5897 shift_n = DecodeImmShiftARM(opcode, shift_t);
5899 if (Rd == 15 && setflags)
5900 return EmulateSUBSPcLrEtc(opcode, encoding);
5901 break;
5902 default:
5903 return false;
5906 // Read the first operand.
5907 int32_t val1 = ReadCoreReg(Rn, &success);
5908 if (!success)
5909 return false;
5911 // Read the second operand.
5912 int32_t val2 = ReadCoreReg(Rm, &success);
5913 if (!success)
5914 return false;
5916 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
5917 if (!success)
5918 return false;
5919 AddWithCarryResult res = AddWithCarry(val1, shifted, APSR_C);
5921 EmulateInstruction::Context context;
5922 context.type = EmulateInstruction::eContextImmediate;
5923 context.SetNoArgs();
5925 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
5926 res.carry_out, res.overflow))
5927 return false;
5929 return true;
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.
5934 bool 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
5947 bool success = false;
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(opcode, 10, 8);
5956 imm32 = ThumbImm8Scaled(opcode); // imm32 = ZeroExtend(imm8:'00', 32)
5957 add = true;
5958 break;
5959 case eEncodingT2:
5960 case eEncodingT3:
5961 Rd = Bits32(opcode, 11, 8);
5962 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
5963 add = (Bits32(opcode, 24, 21) == 0); // 0b0000 => ADD; 0b0101 => SUB
5964 if (BadReg(Rd))
5965 return false;
5966 break;
5967 case eEncodingA1:
5968 case eEncodingA2:
5969 Rd = Bits32(opcode, 15, 12);
5970 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
5971 add = (Bits32(opcode, 24, 21) == 0x4); // 0b0100 => ADD; 0b0010 => SUB
5972 break;
5973 default:
5974 return false;
5977 // Read the PC value.
5978 uint32_t pc = ReadCoreReg(PC_REG, &success);
5979 if (!success)
5980 return false;
5982 uint32_t result = (add ? Align(pc, 4) + imm32 : Align(pc, 4) - imm32);
5984 EmulateInstruction::Context context;
5985 context.type = EmulateInstruction::eContextImmediate;
5986 context.SetNoArgs();
5988 if (!WriteCoreReg(context, result, Rd))
5989 return false;
5991 return true;
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.
5997 bool 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
6015 bool success = false;
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(opcode, 11, 8);
6026 Rn = Bits32(opcode, 19, 16);
6027 setflags = BitIsSet(opcode, 20);
6028 imm32 = ThumbExpandImm_C(
6029 opcode, APSR_C,
6030 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, eEncodingT1);
6034 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
6035 return false;
6036 break;
6037 case eEncodingA1:
6038 Rd = Bits32(opcode, 15, 12);
6039 Rn = Bits32(opcode, 19, 16);
6040 setflags = BitIsSet(opcode, 20);
6041 imm32 =
6042 ARMExpandImm_C(opcode, APSR_C,
6043 carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
6045 if (Rd == 15 && setflags)
6046 return EmulateSUBSPcLrEtc(opcode, encoding);
6047 break;
6048 default:
6049 return false;
6052 // Read the first operand.
6053 uint32_t val1 = ReadCoreReg(Rn, &success);
6054 if (!success)
6055 return false;
6057 uint32_t result = val1 & imm32;
6059 EmulateInstruction::Context context;
6060 context.type = EmulateInstruction::eContextImmediate;
6061 context.SetNoArgs();
6063 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
6064 return false;
6066 return true;
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.
6072 bool 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
6091 bool success = false;
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(opcode, 2, 0);
6102 Rm = Bits32(opcode, 5, 3);
6103 setflags = !InITBlock();
6104 shift_t = SRType_LSL;
6105 shift_n = 0;
6106 break;
6107 case eEncodingT2:
6108 Rd = Bits32(opcode, 11, 8);
6109 Rn = Bits32(opcode, 19, 16);
6110 Rm = Bits32(opcode, 3, 0);
6111 setflags = BitIsSet(opcode, 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, eEncodingT2);
6116 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
6117 return false;
6118 break;
6119 case eEncodingA1:
6120 Rd = Bits32(opcode, 15, 12);
6121 Rn = Bits32(opcode, 19, 16);
6122 Rm = Bits32(opcode, 3, 0);
6123 setflags = BitIsSet(opcode, 20);
6124 shift_n = DecodeImmShiftARM(opcode, shift_t);
6126 if (Rd == 15 && setflags)
6127 return EmulateSUBSPcLrEtc(opcode, encoding);
6128 break;
6129 default:
6130 return false;
6133 // Read the first operand.
6134 uint32_t val1 = ReadCoreReg(Rn, &success);
6135 if (!success)
6136 return false;
6138 // Read the second operand.
6139 uint32_t val2 = ReadCoreReg(Rm, &success);
6140 if (!success)
6141 return false;
6143 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
6144 if (!success)
6145 return false;
6146 uint32_t result = val1 & shifted;
6148 EmulateInstruction::Context context;
6149 context.type = EmulateInstruction::eContextImmediate;
6150 context.SetNoArgs();
6152 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
6153 return false;
6155 return true;
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.
6162 bool 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
6180 bool success = false;
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(opcode, 11, 8);
6191 Rn = Bits32(opcode, 19, 16);
6192 setflags = BitIsSet(opcode, 20);
6193 imm32 = ThumbExpandImm_C(
6194 opcode, APSR_C,
6195 carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
6196 if (BadReg(Rd) || BadReg(Rn))
6197 return false;
6198 break;
6199 case eEncodingA1:
6200 Rd = Bits32(opcode, 15, 12);
6201 Rn = Bits32(opcode, 19, 16);
6202 setflags = BitIsSet(opcode, 20);
6203 imm32 =
6204 ARMExpandImm_C(opcode, APSR_C,
6205 carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
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;
6216 // Read the first operand.
6217 uint32_t val1 = ReadCoreReg(Rn, &success);
6218 if (!success)
6219 return false;
6221 uint32_t result = val1 & ~imm32;
6223 EmulateInstruction::Context context;
6224 context.type = EmulateInstruction::eContextImmediate;
6225 context.SetNoArgs();
6227 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
6228 return false;
6230 return true;
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.
6237 bool 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
6256 bool success = false;
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(opcode, 2, 0);
6267 Rm = Bits32(opcode, 5, 3);
6268 setflags = !InITBlock();
6269 shift_t = SRType_LSL;
6270 shift_n = 0;
6271 break;
6272 case eEncodingT2:
6273 Rd = Bits32(opcode, 11, 8);
6274 Rn = Bits32(opcode, 19, 16);
6275 Rm = Bits32(opcode, 3, 0);
6276 setflags = BitIsSet(opcode, 20);
6277 shift_n = DecodeImmShiftThumb(opcode, shift_t);
6278 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
6279 return false;
6280 break;
6281 case eEncodingA1:
6282 Rd = Bits32(opcode, 15, 12);
6283 Rn = Bits32(opcode, 19, 16);
6284 Rm = Bits32(opcode, 3, 0);
6285 setflags = BitIsSet(opcode, 20);
6286 shift_n = DecodeImmShiftARM(opcode, shift_t);
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;
6297 // Read the first operand.
6298 uint32_t val1 = ReadCoreReg(Rn, &success);
6299 if (!success)
6300 return false;
6302 // Read the second operand.
6303 uint32_t val2 = ReadCoreReg(Rm, &success);
6304 if (!success)
6305 return false;
6307 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
6308 if (!success)
6309 return false;
6310 uint32_t result = val1 & ~shifted;
6312 EmulateInstruction::Context context;
6313 context.type = EmulateInstruction::eContextImmediate;
6314 context.SetNoArgs();
6316 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
6317 return false;
6319 return true;
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.
6326 bool 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
6343 bool success = false;
6345 if (ConditionPassed(opcode)) {
6346 const uint32_t addr_byte_size = GetAddressByteSize();
6348 uint32_t t;
6349 uint32_t n;
6350 uint32_t imm32;
6351 bool index;
6352 bool add;
6353 bool wback;
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(opcode, 15, 12);
6363 n = Bits32(opcode, 19, 16);
6364 imm32 = Bits32(opcode, 11, 0);
6366 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
6367 // (W == '1');
6368 index = BitIsSet(opcode, 24);
6369 add = BitIsSet(opcode, 23);
6370 wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21));
6372 // if wback && n == t then UNPREDICTABLE;
6373 if (wback && (n == t))
6374 return false;
6376 break;
6378 default:
6379 return false;
6382 addr_t address;
6383 addr_t offset_addr;
6384 addr_t base_address = ReadCoreReg(n, &success);
6385 if (!success)
6386 return false;
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;
6394 // address = if index then offset_addr else R[n];
6395 if (index)
6396 address = offset_addr;
6397 else
6398 address = base_address;
6400 // data = MemU[address,4];
6402 std::optional<RegisterInfo> base_reg =
6403 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
6404 EmulateInstruction::Context context;
6405 context.type = eContextRegisterLoad;
6406 context.SetRegisterPlusOffset(*base_reg, address - base_address);
6408 uint64_t data = MemURead(context, address, addr_byte_size, 0, &success);
6409 if (!success)
6410 return false;
6412 // if wback then R[n] = offset_addr;
6413 if (wback) {
6414 context.type = eContextAdjustBaseRegister;
6415 context.SetAddress(offset_addr);
6416 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
6417 offset_addr))
6418 return false;
6421 // if t == 15 then
6422 if (t == 15) {
6423 // if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
6424 if (BitIsClear(address, 1) && BitIsClear(address, 0)) {
6425 // LoadWritePC (data);
6426 context.type = eContextRegisterLoad;
6427 context.SetRegisterPlusOffset(*base_reg, address - base_address);
6428 LoadWritePC(context, data);
6429 } else
6430 return false;
6432 // elsif UnalignedSupport() || address<1:0> = '00' then
6433 else if (UnalignedSupport() ||
6434 (BitIsClear(address, 1) && BitIsClear(address, 0))) {
6435 // R[t] = data;
6436 context.type = eContextRegisterLoad;
6437 context.SetRegisterPlusOffset(*base_reg, address - base_address);
6438 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
6439 data))
6440 return false;
6442 // else // Can only apply before ARMv7
6443 else {
6444 // R[t] = ROR(data, 8*UInt(address<1:0>));
6445 data = ROR(data, Bits32(address, 1, 0), &success);
6446 if (!success)
6447 return false;
6448 context.type = eContextRegisterLoad;
6449 context.SetImmediate(data);
6450 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
6451 data))
6452 return false;
6455 return true;
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.
6462 bool 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
6483 bool success = false;
6485 if (ConditionPassed(opcode)) {
6486 const uint32_t addr_byte_size = GetAddressByteSize();
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;
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(opcode, 2, 0);
6503 n = Bits32(opcode, 5, 3);
6504 m = Bits32(opcode, 8, 6);
6506 // index = TRUE; add = TRUE; wback = FALSE;
6507 index = true;
6508 add = true;
6509 wback = false;
6511 // (shift_t, shift_n) = (SRType_LSL, 0);
6512 shift_t = SRType_LSL;
6513 shift_n = 0;
6515 break;
6517 case eEncodingT2:
6518 // if Rn == '1111' then SEE LDR (literal);
6519 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6520 t = Bits32(opcode, 15, 12);
6521 n = Bits32(opcode, 19, 16);
6522 m = Bits32(opcode, 3, 0);
6524 // index = TRUE; add = TRUE; wback = FALSE;
6525 index = true;
6526 add = true;
6527 wback = false;
6529 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
6530 shift_t = SRType_LSL;
6531 shift_n = Bits32(opcode, 5, 4);
6533 // if BadReg(m) then UNPREDICTABLE;
6534 if (BadReg(m))
6535 return false;
6537 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
6538 if ((t == 15) && InITBlock() && !LastInITBlock())
6539 return false;
6541 break;
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(opcode, 15, 12);
6547 n = Bits32(opcode, 19, 16);
6548 m = Bits32(opcode, 3, 0);
6550 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
6551 // (W == '1');
6552 index = BitIsSet(opcode, 24);
6553 add = BitIsSet(opcode, 23);
6554 wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21));
6556 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
6557 uint32_t type = Bits32(opcode, 6, 5);
6558 uint32_t imm5 = Bits32(opcode, 11, 7);
6559 shift_n = DecodeImmShift(type, imm5, shift_t);
6561 // if m == 15 then UNPREDICTABLE;
6562 if (m == 15)
6563 return false;
6565 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
6566 if (wback && ((n == 15) || (n == t)))
6567 return false;
6568 } break;
6570 default:
6571 return false;
6574 uint32_t Rm =
6575 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
6576 if (!success)
6577 return false;
6579 uint32_t Rn =
6580 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6581 if (!success)
6582 return false;
6584 addr_t offset_addr;
6585 addr_t address;
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(Rm, shift_t, shift_n, Bit32(m_opcode_cpsr, APSR_C), &success);
6591 if (!success)
6592 return false;
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;
6600 // address = if index then offset_addr else R[n];
6601 if (index)
6602 address = offset_addr;
6603 else
6604 address = Rn;
6606 // data = MemU[address,4];
6607 std::optional<RegisterInfo> base_reg =
6608 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
6609 EmulateInstruction::Context context;
6610 context.type = eContextRegisterLoad;
6611 context.SetRegisterPlusOffset(*base_reg, address - Rn);
6613 uint64_t data = MemURead(context, address, addr_byte_size, 0, &success);
6614 if (!success)
6615 return false;
6617 // if wback then R[n] = offset_addr;
6618 if (wback) {
6619 context.type = eContextAdjustBaseRegister;
6620 context.SetAddress(offset_addr);
6621 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
6622 offset_addr))
6623 return false;
6626 // if t == 15 then
6627 if (t == 15) {
6628 // if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
6629 if (BitIsClear(address, 1) && BitIsClear(address, 0)) {
6630 context.type = eContextRegisterLoad;
6631 context.SetRegisterPlusOffset(*base_reg, address - Rn);
6632 LoadWritePC(context, data);
6633 } else
6634 return false;
6636 // elsif UnalignedSupport() || address<1:0> = '00' then
6637 else if (UnalignedSupport() ||
6638 (BitIsClear(address, 1) && BitIsClear(address, 0))) {
6639 // R[t] = data;
6640 context.type = eContextRegisterLoad;
6641 context.SetRegisterPlusOffset(*base_reg, address - Rn);
6642 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
6643 data))
6644 return false;
6645 } else // Can only apply before ARMv7
6647 // if CurrentInstrSet() == InstrSet_ARM then
6648 if (CurrentInstrSet() == eModeARM) {
6649 // R[t] = ROR(data, 8*UInt(address<1:0>));
6650 data = ROR(data, Bits32(address, 1, 0), &success);
6651 if (!success)
6652 return false;
6653 context.type = eContextRegisterLoad;
6654 context.SetImmediate(data);
6655 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
6656 data))
6657 return false;
6658 } else {
6659 // R[t] = bits(32) UNKNOWN;
6660 WriteBits32Unknown(t);
6664 return true;
6667 // LDRB (immediate, Thumb)
6668 bool 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
6679 bool success = false;
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;
6689 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6690 switch (encoding) {
6691 case eEncodingT1:
6692 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
6693 t = Bits32(opcode, 2, 0);
6694 n = Bits32(opcode, 5, 3);
6695 imm32 = Bits32(opcode, 10, 6);
6697 // index = TRUE; add = TRUE; wback = FALSE;
6698 index = true;
6699 add = true;
6700 wback = false;
6702 break;
6704 case eEncodingT2:
6705 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
6706 t = Bits32(opcode, 15, 12);
6707 n = Bits32(opcode, 19, 16);
6708 imm32 = Bits32(opcode, 11, 0);
6710 // index = TRUE; add = TRUE; wback = FALSE;
6711 index = true;
6712 add = true;
6713 wback = false;
6715 // if Rt == '1111' then SEE PLD;
6716 if (t == 15)
6717 return false; // PLD is not implemented yet
6719 // if Rn == '1111' then SEE LDRB (literal);
6720 if (n == 15)
6721 return EmulateLDRBLiteral(opcode, eEncodingT1);
6723 // if t == 13 then UNPREDICTABLE;
6724 if (t == 13)
6725 return false;
6727 break;
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(opcode, 10) && BitIsClear(opcode, 8))
6733 return false;
6735 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
6736 t = Bits32(opcode, 15, 12);
6737 n = Bits32(opcode, 19, 16);
6738 imm32 = Bits32(opcode, 7, 0);
6740 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
6741 index = BitIsSet(opcode, 10);
6742 add = BitIsSet(opcode, 9);
6743 wback = BitIsSet(opcode, 8);
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
6749 // if Rn == '1111' then SEE LDRB (literal);
6750 if (n == 15)
6751 return EmulateLDRBLiteral(opcode, eEncodingT1);
6753 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
6754 if (BadReg(t) || (wback && (n == t)))
6755 return false;
6757 break;
6759 default:
6760 return false;
6763 uint32_t Rn =
6764 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
6765 if (!success)
6766 return false;
6768 addr_t address;
6769 addr_t offset_addr;
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;
6777 // address = if index then offset_addr else R[n];
6778 if (index)
6779 address = offset_addr;
6780 else
6781 address = Rn;
6783 // R[t] = ZeroExtend(MemU[address,1], 32);
6784 std::optional<RegisterInfo> base_reg =
6785 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
6786 std::optional<RegisterInfo> data_reg =
6787 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t);
6789 EmulateInstruction::Context context;
6790 context.type = eContextRegisterLoad;
6791 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, address - Rn);
6793 uint64_t data = MemURead(context, address, 1, 0, &success);
6794 if (!success)
6795 return false;
6797 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, data))
6798 return false;
6800 // if wback then R[n] = offset_addr;
6801 if (wback) {
6802 context.type = eContextAdjustBaseRegister;
6803 context.SetAddress(offset_addr);
6804 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
6805 offset_addr))
6806 return false;
6809 return true;
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.
6815 bool 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
6825 bool success = false;
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(opcode, 15, 12);
6835 imm32 = Bits32(opcode, 11, 0);
6836 add = BitIsSet(opcode, 23);
6838 // if Rt == '1111' then SEE PLD;
6839 if (t == 15)
6840 return false; // PLD is not implemented yet
6842 // if t == 13 then UNPREDICTABLE;
6843 if (t == 13)
6844 return false;
6846 break;
6848 case eEncodingA1:
6849 // t == UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');
6850 t = Bits32(opcode, 15, 12);
6851 imm32 = Bits32(opcode, 11, 0);
6852 add = BitIsSet(opcode, 23);
6854 // if t == 15 then UNPREDICTABLE;
6855 if (t == 15)
6856 return false;
6857 break;
6859 default:
6860 return false;
6863 // base = Align(PC,4);
6864 uint32_t pc_val = ReadCoreReg(PC_REG, &success);
6865 if (!success)
6866 return false;
6868 uint32_t base = AlignPC(pc_val);
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;
6877 // R[t] = ZeroExtend(MemU[address,1], 32);
6878 EmulateInstruction::Context context;
6879 context.type = eContextRelativeBranchImmediate;
6880 context.SetImmediate(address - base);
6882 uint64_t data = MemURead(context, address, 1, 0, &success);
6883 if (!success)
6884 return false;
6886 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, data))
6887 return false;
6889 return true;
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.
6896 bool 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
6908 bool success = false;
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;
6920 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
6921 switch (encoding) {
6922 case eEncodingT1:
6923 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6924 t = Bits32(opcode, 2, 0);
6925 n = Bits32(opcode, 5, 3);
6926 m = Bits32(opcode, 8, 6);
6928 // index = TRUE; add = TRUE; wback = FALSE;
6929 index = true;
6930 add = true;
6931 wback = false;
6933 // (shift_t, shift_n) = (SRType_LSL, 0);
6934 shift_t = SRType_LSL;
6935 shift_n = 0;
6936 break;
6938 case eEncodingT2:
6939 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
6940 t = Bits32(opcode, 15, 12);
6941 n = Bits32(opcode, 19, 16);
6942 m = Bits32(opcode, 3, 0);
6944 // index = TRUE; add = TRUE; wback = FALSE;
6945 index = true;
6946 add = true;
6947 wback = false;
6949 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
6950 shift_t = SRType_LSL;
6951 shift_n = Bits32(opcode, 5, 4);
6953 // if Rt == '1111' then SEE PLD;
6954 if (t == 15)
6955 return false; // PLD is not implemented yet
6957 // if Rn == '1111' then SEE LDRB (literal);
6958 if (n == 15)
6959 return EmulateLDRBLiteral(opcode, eEncodingT1);
6961 // if t == 13 || BadReg(m) then UNPREDICTABLE;
6962 if ((t == 13) || BadReg(m))
6963 return false;
6964 break;
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(opcode, 15, 12);
6970 n = Bits32(opcode, 19, 16);
6971 m = Bits32(opcode, 3, 0);
6973 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
6974 // (W == '1');
6975 index = BitIsSet(opcode, 24);
6976 add = BitIsSet(opcode, 23);
6977 wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21));
6979 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
6980 uint32_t type = Bits32(opcode, 6, 5);
6981 uint32_t imm5 = Bits32(opcode, 11, 7);
6982 shift_n = DecodeImmShift(type, imm5, shift_t);
6984 // if t == 15 || m == 15 then UNPREDICTABLE;
6985 if ((t == 15) || (m == 15))
6986 return false;
6988 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
6989 if (wback && ((n == 15) || (n == t)))
6990 return false;
6991 } break;
6993 default:
6994 return false;
6997 addr_t offset_addr;
6998 addr_t address;
7000 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
7001 uint32_t Rm =
7002 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7003 if (!success)
7004 return false;
7006 addr_t offset = Shift(Rm, shift_t, shift_n, APSR_C, &success);
7007 if (!success)
7008 return false;
7010 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7011 uint32_t Rn =
7012 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7013 if (!success)
7014 return false;
7016 if (add)
7017 offset_addr = Rn + offset;
7018 else
7019 offset_addr = Rn - offset;
7021 // address = if index then offset_addr else R[n];
7022 if (index)
7023 address = offset_addr;
7024 else
7025 address = Rn;
7027 // R[t] = ZeroExtend(MemU[address,1],32);
7028 std::optional<RegisterInfo> base_reg =
7029 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
7031 EmulateInstruction::Context context;
7032 context.type = eContextRegisterLoad;
7033 context.SetRegisterPlusOffset(*base_reg, address - Rn);
7035 uint64_t data = MemURead(context, address, 1, 0, &success);
7036 if (!success)
7037 return false;
7039 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, data))
7040 return false;
7042 // if wback then R[n] = offset_addr;
7043 if (wback) {
7044 context.type = eContextAdjustBaseRegister;
7045 context.SetAddress(offset_addr);
7046 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
7047 offset_addr))
7048 return false;
7051 return true;
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.
7058 bool 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
7073 bool success = false;
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;
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(opcode, 2, 0);
7088 n = Bits32(opcode, 5, 3);
7089 imm32 = Bits32(opcode, 10, 6) << 1;
7091 // index = TRUE; add = TRUE; wback = FALSE;
7092 index = true;
7093 add = true;
7094 wback = false;
7096 break;
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(opcode, 15, 12);
7103 n = Bits32(opcode, 19, 16);
7104 imm32 = Bits32(opcode, 11, 0);
7106 // index = TRUE; add = TRUE; wback = FALSE;
7107 index = true;
7108 add = true;
7109 wback = false;
7111 // if t == 13 then UNPREDICTABLE;
7112 if (t == 13)
7113 return false;
7114 break;
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(opcode, 10) && BitIsClear(opcode, 8))
7123 return false;
7125 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
7126 t = Bits32(opcode, 15, 12);
7127 n = Bits32(opcode, 19, 16);
7128 imm32 = Bits32(opcode, 7, 0);
7130 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
7131 index = BitIsSet(opcode, 10);
7132 add = BitIsSet(opcode, 9);
7133 wback = BitIsSet(opcode, 8);
7135 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
7136 if (BadReg(t) || (wback && (n == t)))
7137 return false;
7138 break;
7140 default:
7141 return false;
7144 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7145 uint32_t Rn =
7146 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7147 if (!success)
7148 return false;
7150 addr_t offset_addr;
7151 addr_t address;
7153 if (add)
7154 offset_addr = Rn + imm32;
7155 else
7156 offset_addr = Rn - imm32;
7158 // address = if index then offset_addr else R[n];
7159 if (index)
7160 address = offset_addr;
7161 else
7162 address = Rn;
7164 // data = MemU[address,2];
7165 std::optional<RegisterInfo> base_reg =
7166 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
7168 EmulateInstruction::Context context;
7169 context.type = eContextRegisterLoad;
7170 context.SetRegisterPlusOffset(*base_reg, address - Rn);
7172 uint64_t data = MemURead(context, address, 2, 0, &success);
7173 if (!success)
7174 return false;
7176 // if wback then R[n] = offset_addr;
7177 if (wback) {
7178 context.type = eContextAdjustBaseRegister;
7179 context.SetAddress(offset_addr);
7180 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
7181 offset_addr))
7182 return false;
7185 // if UnalignedSupport() || address<0> = '0' then
7186 if (UnalignedSupport() || BitIsClear(address, 0)) {
7187 // R[t] = ZeroExtend(data, 32);
7188 context.type = eContextRegisterLoad;
7189 context.SetRegisterPlusOffset(*base_reg, address - Rn);
7190 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
7191 data))
7192 return false;
7193 } else // Can only apply before ARMv7
7195 // R[t] = bits(32) UNKNOWN;
7196 WriteBits32Unknown(t);
7199 return true;
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.
7205 bool 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
7219 bool success = false;
7221 if (ConditionPassed(opcode)) {
7222 uint32_t t;
7223 uint32_t imm32;
7224 bool add;
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(opcode, 15, 12);
7232 imm32 = Bits32(opcode, 11, 0);
7233 add = BitIsSet(opcode, 23);
7235 // if t == 13 then UNPREDICTABLE;
7236 if (t == 13)
7237 return false;
7239 break;
7241 case eEncodingA1: {
7242 uint32_t imm4H = Bits32(opcode, 11, 8);
7243 uint32_t imm4L = Bits32(opcode, 3, 0);
7245 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
7246 t = Bits32(opcode, 15, 12);
7247 imm32 = (imm4H << 4) | imm4L;
7248 add = BitIsSet(opcode, 23);
7250 // if t == 15 then UNPREDICTABLE;
7251 if (t == 15)
7252 return false;
7253 break;
7256 default:
7257 return false;
7260 // base = Align(PC,4);
7261 uint64_t pc_value = ReadCoreReg(PC_REG, &success);
7262 if (!success)
7263 return false;
7265 addr_t base = AlignPC(pc_value);
7266 addr_t address;
7268 // address = if add then (base + imm32) else (base - imm32);
7269 if (add)
7270 address = base + imm32;
7271 else
7272 address = base - imm32;
7274 // data = MemU[address,2];
7275 std::optional<RegisterInfo> base_reg =
7276 GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
7278 EmulateInstruction::Context context;
7279 context.type = eContextRegisterLoad;
7280 context.SetRegisterPlusOffset(*base_reg, address - base);
7282 uint64_t data = MemURead(context, address, 2, 0, &success);
7283 if (!success)
7284 return false;
7286 // if UnalignedSupport() || address<0> = '0' then
7287 if (UnalignedSupport() || BitIsClear(address, 0)) {
7288 // R[t] = ZeroExtend(data, 32);
7289 context.type = eContextRegisterLoad;
7290 context.SetRegisterPlusOffset(*base_reg, address - base);
7291 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
7292 data))
7293 return false;
7295 } else // Can only apply before ARMv7
7297 // R[t] = bits(32) UNKNOWN;
7298 WriteBits32Unknown(t);
7301 return true;
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.
7309 bool 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
7325 bool success = false;
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;
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(opcode, 2, 0);
7344 n = Bits32(opcode, 5, 3);
7345 m = Bits32(opcode, 8, 6);
7347 // index = TRUE; add = TRUE; wback = FALSE;
7348 index = true;
7349 add = true;
7350 wback = false;
7352 // (shift_t, shift_n) = (SRType_LSL, 0);
7353 shift_t = SRType_LSL;
7354 shift_n = 0;
7356 break;
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(opcode, 15, 12);
7363 n = Bits32(opcode, 19, 16);
7364 m = Bits32(opcode, 3, 0);
7366 // index = TRUE; add = TRUE; wback = FALSE;
7367 index = true;
7368 add = true;
7369 wback = false;
7371 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
7372 shift_t = SRType_LSL;
7373 shift_n = Bits32(opcode, 5, 4);
7375 // if t == 13 || BadReg(m) then UNPREDICTABLE;
7376 if ((t == 13) || BadReg(m))
7377 return false;
7378 break;
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(opcode, 15, 12);
7384 n = Bits32(opcode, 19, 16);
7385 m = Bits32(opcode, 3, 0);
7387 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
7388 // (W == '1');
7389 index = BitIsSet(opcode, 24);
7390 add = BitIsSet(opcode, 23);
7391 wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21));
7393 // (shift_t, shift_n) = (SRType_LSL, 0);
7394 shift_t = SRType_LSL;
7395 shift_n = 0;
7397 // if t == 15 || m == 15 then UNPREDICTABLE;
7398 if ((t == 15) || (m == 15))
7399 return false;
7401 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
7402 if (wback && ((n == 15) || (n == t)))
7403 return false;
7405 break;
7407 default:
7408 return false;
7411 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
7413 uint64_t Rm =
7414 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7415 if (!success)
7416 return false;
7418 addr_t offset = Shift(Rm, shift_t, shift_n, APSR_C, &success);
7419 if (!success)
7420 return false;
7422 addr_t offset_addr;
7423 addr_t address;
7425 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7426 uint64_t Rn =
7427 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7428 if (!success)
7429 return false;
7431 if (add)
7432 offset_addr = Rn + offset;
7433 else
7434 offset_addr = Rn - offset;
7436 // address = if index then offset_addr else R[n];
7437 if (index)
7438 address = offset_addr;
7439 else
7440 address = Rn;
7442 // data = MemU[address,2];
7443 std::optional<RegisterInfo> base_reg =
7444 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
7445 std::optional<RegisterInfo> offset_reg =
7446 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m);
7448 EmulateInstruction::Context context;
7449 context.type = eContextRegisterLoad;
7450 context.SetRegisterPlusIndirectOffset(*base_reg, *offset_reg);
7451 uint64_t data = MemURead(context, address, 2, 0, &success);
7452 if (!success)
7453 return false;
7455 // if wback then R[n] = offset_addr;
7456 if (wback) {
7457 context.type = eContextAdjustBaseRegister;
7458 context.SetAddress(offset_addr);
7459 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
7460 offset_addr))
7461 return false;
7464 // if UnalignedSupport() || address<0> = '0' then
7465 if (UnalignedSupport() || BitIsClear(address, 0)) {
7466 // R[t] = ZeroExtend(data, 32);
7467 context.type = eContextRegisterLoad;
7468 context.SetRegisterPlusIndirectOffset(*base_reg, *offset_reg);
7469 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
7470 data))
7471 return false;
7472 } else // Can only apply before ARMv7
7474 // R[t] = bits(32) UNKNOWN;
7475 WriteBits32Unknown(t);
7478 return true;
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.
7485 bool 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
7496 bool success = false;
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;
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(opcode, 15, 12);
7513 n = Bits32(opcode, 19, 16);
7514 imm32 = Bits32(opcode, 11, 0);
7516 // index = TRUE; add = TRUE; wback = FALSE;
7517 index = true;
7518 add = true;
7519 wback = false;
7521 // if t == 13 then UNPREDICTABLE;
7522 if (t == 13)
7523 return false;
7525 break;
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(opcode, 10) && BitIsClear(opcode, 8))
7533 return false;
7535 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
7536 t = Bits32(opcode, 15, 12);
7537 n = Bits32(opcode, 19, 16);
7538 imm32 = Bits32(opcode, 7, 0);
7540 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
7541 index = BitIsSet(opcode, 10);
7542 add = BitIsSet(opcode, 9);
7543 wback = BitIsSet(opcode, 8);
7545 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
7546 if (((t == 13) ||
7547 ((t == 15) && (BitIsClear(opcode, 10) || BitIsSet(opcode, 9) ||
7548 BitIsSet(opcode, 8)))) ||
7549 (wback && (n == t)))
7550 return false;
7552 break;
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(opcode, 15, 12);
7559 n = Bits32(opcode, 19, 16);
7561 uint32_t imm4H = Bits32(opcode, 11, 8);
7562 uint32_t imm4L = Bits32(opcode, 3, 0);
7563 imm32 = (imm4H << 4) | imm4L;
7565 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
7566 // (W == '1');
7567 index = BitIsSet(opcode, 24);
7568 add = BitIsSet(opcode, 23);
7569 wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21));
7571 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
7572 if ((t == 15) || (wback && (n == t)))
7573 return false;
7575 break;
7578 default:
7579 return false;
7582 uint64_t Rn = ReadCoreReg(n, &success);
7583 if (!success)
7584 return false;
7586 addr_t offset_addr;
7587 addr_t address;
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;
7595 // address = if index then offset_addr else R[n];
7596 if (index)
7597 address = offset_addr;
7598 else
7599 address = Rn;
7601 // R[t] = SignExtend(MemU[address,1], 32);
7602 std::optional<RegisterInfo> base_reg =
7603 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
7605 EmulateInstruction::Context context;
7606 context.type = eContextRegisterLoad;
7607 context.SetRegisterPlusOffset(*base_reg, address - Rn);
7609 uint64_t unsigned_data = MemURead(context, address, 1, 0, &success);
7610 if (!success)
7611 return false;
7613 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
7614 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
7615 (uint64_t)signed_data))
7616 return false;
7618 // if wback then R[n] = offset_addr;
7619 if (wback) {
7620 context.type = eContextAdjustBaseRegister;
7621 context.SetAddress(offset_addr);
7622 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
7623 offset_addr))
7624 return false;
7628 return true;
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.
7634 bool 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
7644 bool success = false;
7646 if (ConditionPassed(opcode)) {
7647 uint32_t t;
7648 uint32_t imm32;
7649 bool add;
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(opcode, 15, 12);
7657 imm32 = Bits32(opcode, 11, 0);
7658 add = BitIsSet(opcode, 23);
7660 // if t == 13 then UNPREDICTABLE;
7661 if (t == 13)
7662 return false;
7664 break;
7666 case eEncodingA1: {
7667 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
7668 t = Bits32(opcode, 15, 12);
7669 uint32_t imm4H = Bits32(opcode, 11, 8);
7670 uint32_t imm4L = Bits32(opcode, 3, 0);
7671 imm32 = (imm4H << 4) | imm4L;
7672 add = BitIsSet(opcode, 23);
7674 // if t == 15 then UNPREDICTABLE;
7675 if (t == 15)
7676 return false;
7678 break;
7681 default:
7682 return false;
7685 // base = Align(PC,4);
7686 uint64_t pc_value = ReadCoreReg(PC_REG, &success);
7687 if (!success)
7688 return false;
7689 uint64_t base = AlignPC(pc_value);
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;
7698 // R[t] = SignExtend(MemU[address,1], 32);
7699 std::optional<RegisterInfo> base_reg =
7700 GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
7702 EmulateInstruction::Context context;
7703 context.type = eContextRegisterLoad;
7704 context.SetRegisterPlusOffset(*base_reg, address - base);
7706 uint64_t unsigned_data = MemURead(context, address, 1, 0, &success);
7707 if (!success)
7708 return false;
7710 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
7711 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
7712 (uint64_t)signed_data))
7713 return false;
7715 return true;
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.
7722 bool 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
7734 bool success = false;
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;
7746 // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
7747 switch (encoding) {
7748 case eEncodingT1:
7749 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
7750 t = Bits32(opcode, 2, 0);
7751 n = Bits32(opcode, 5, 3);
7752 m = Bits32(opcode, 8, 6);
7754 // index = TRUE; add = TRUE; wback = FALSE;
7755 index = true;
7756 add = true;
7757 wback = false;
7759 // (shift_t, shift_n) = (SRType_LSL, 0);
7760 shift_t = SRType_LSL;
7761 shift_n = 0;
7763 break;
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(opcode, 15, 12);
7770 n = Bits32(opcode, 19, 16);
7771 m = Bits32(opcode, 3, 0);
7773 // index = TRUE; add = TRUE; wback = FALSE;
7774 index = true;
7775 add = true;
7776 wback = false;
7778 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
7779 shift_t = SRType_LSL;
7780 shift_n = Bits32(opcode, 5, 4);
7782 // if t == 13 || BadReg(m) then UNPREDICTABLE;
7783 if ((t == 13) || BadReg(m))
7784 return false;
7785 break;
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(opcode, 15, 12);
7791 n = Bits32(opcode, 19, 16);
7792 m = Bits32(opcode, 3, 0);
7794 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
7795 // (W == '1');
7796 index = BitIsSet(opcode, 24);
7797 add = BitIsSet(opcode, 23);
7798 wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);
7800 // (shift_t, shift_n) = (SRType_LSL, 0);
7801 shift_t = SRType_LSL;
7802 shift_n = 0;
7804 // if t == 15 || m == 15 then UNPREDICTABLE;
7805 if ((t == 15) || (m == 15))
7806 return false;
7808 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
7809 if (wback && ((n == 15) || (n == t)))
7810 return false;
7811 break;
7813 default:
7814 return false;
7817 uint64_t Rm =
7818 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
7819 if (!success)
7820 return false;
7822 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
7823 addr_t offset = Shift(Rm, shift_t, shift_n, APSR_C, &success);
7824 if (!success)
7825 return false;
7827 addr_t offset_addr;
7828 addr_t address;
7830 // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
7831 uint64_t Rn =
7832 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7833 if (!success)
7834 return false;
7836 if (add)
7837 offset_addr = Rn + offset;
7838 else
7839 offset_addr = Rn - offset;
7841 // address = if index then offset_addr else R[n];
7842 if (index)
7843 address = offset_addr;
7844 else
7845 address = Rn;
7847 // R[t] = SignExtend(MemU[address,1], 32);
7848 std::optional<RegisterInfo> base_reg =
7849 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
7850 std::optional<RegisterInfo> offset_reg =
7851 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m);
7853 EmulateInstruction::Context context;
7854 context.type = eContextRegisterLoad;
7855 context.SetRegisterPlusIndirectOffset(*base_reg, *offset_reg);
7857 uint64_t unsigned_data = MemURead(context, address, 1, 0, &success);
7858 if (!success)
7859 return false;
7861 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
7862 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
7863 (uint64_t)signed_data))
7864 return false;
7866 // if wback then R[n] = offset_addr;
7867 if (wback) {
7868 context.type = eContextAdjustBaseRegister;
7869 context.SetAddress(offset_addr);
7870 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
7871 offset_addr))
7872 return false;
7875 return true;
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.
7882 bool 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
7897 bool success = false;
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;
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(opcode, 15, 12);
7914 n = Bits32(opcode, 19, 16);
7915 imm32 = Bits32(opcode, 11, 0);
7917 // index = TRUE; add = TRUE; wback = FALSE;
7918 index = true;
7919 add = true;
7920 wback = false;
7922 // if t == 13 then UNPREDICTABLE;
7923 if (t == 13)
7924 return false;
7926 break;
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(opcode, 10) && BitIsClear(opcode, 8))
7935 return false;
7937 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
7938 t = Bits32(opcode, 15, 12);
7939 n = Bits32(opcode, 19, 16);
7940 imm32 = Bits32(opcode, 7, 0);
7942 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
7943 index = BitIsSet(opcode, 10);
7944 add = BitIsSet(opcode, 9);
7945 wback = BitIsSet(opcode, 8);
7947 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
7948 if (BadReg(t) || (wback && (n == t)))
7949 return false;
7951 break;
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(opcode, 15, 12);
7958 n = Bits32(opcode, 19, 16);
7959 uint32_t imm4H = Bits32(opcode, 11, 8);
7960 uint32_t imm4L = Bits32(opcode, 3, 0);
7961 imm32 = (imm4H << 4) | imm4L;
7963 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
7964 // (W == '1');
7965 index = BitIsSet(opcode, 24);
7966 add = BitIsSet(opcode, 23);
7967 wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);
7969 // if t == 15 || (wback && n == t) then UNPREDICTABLE;
7970 if ((t == 15) || (wback && (n == t)))
7971 return false;
7973 break;
7976 default:
7977 return false;
7980 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
7981 uint64_t Rn =
7982 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
7983 if (!success)
7984 return false;
7986 addr_t offset_addr;
7987 if (add)
7988 offset_addr = Rn + imm32;
7989 else
7990 offset_addr = Rn - imm32;
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;
7999 // data = MemU[address,2];
8000 std::optional<RegisterInfo> base_reg =
8001 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
8003 EmulateInstruction::Context context;
8004 context.type = eContextRegisterLoad;
8005 context.SetRegisterPlusOffset(*base_reg, address - Rn);
8007 uint64_t data = MemURead(context, address, 2, 0, &success);
8008 if (!success)
8009 return false;
8011 // if wback then R[n] = offset_addr;
8012 if (wback) {
8013 context.type = eContextAdjustBaseRegister;
8014 context.SetAddress(offset_addr);
8015 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
8016 offset_addr))
8017 return false;
8020 // if UnalignedSupport() || address<0> = '0' then
8021 if (UnalignedSupport() || BitIsClear(address, 0)) {
8022 // R[t] = SignExtend(data, 32);
8023 int64_t signed_data = llvm::SignExtend64<16>(data);
8024 context.type = eContextRegisterLoad;
8025 context.SetRegisterPlusOffset(*base_reg, address - Rn);
8026 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
8027 (uint64_t)signed_data))
8028 return false;
8029 } else // Can only apply before ARMv7
8031 // R[t] = bits(32) UNKNOWN;
8032 WriteBits32Unknown(t);
8035 return true;
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.
8041 bool 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
8055 bool success = false;
8057 if (ConditionPassed(opcode)) {
8058 uint32_t t;
8059 uint32_t imm32;
8060 bool add;
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(opcode, 15, 12);
8068 imm32 = Bits32(opcode, 11, 0);
8069 add = BitIsSet(opcode, 23);
8071 // if t == 13 then UNPREDICTABLE;
8072 if (t == 13)
8073 return false;
8075 break;
8077 case eEncodingA1: {
8078 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
8079 t = Bits32(opcode, 15, 12);
8080 uint32_t imm4H = Bits32(opcode, 11, 8);
8081 uint32_t imm4L = Bits32(opcode, 3, 0);
8082 imm32 = (imm4H << 4) | imm4L;
8083 add = BitIsSet(opcode, 23);
8085 // if t == 15 then UNPREDICTABLE;
8086 if (t == 15)
8087 return false;
8089 break;
8091 default:
8092 return false;
8095 // base = Align(PC,4);
8096 uint64_t pc_value = ReadCoreReg(PC_REG, &success);
8097 if (!success)
8098 return false;
8100 uint64_t base = AlignPC(pc_value);
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;
8109 // data = MemU[address,2];
8110 std::optional<RegisterInfo> base_reg =
8111 GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
8113 EmulateInstruction::Context context;
8114 context.type = eContextRegisterLoad;
8115 context.SetRegisterPlusOffset(*base_reg, imm32);
8117 uint64_t data = MemURead(context, address, 2, 0, &success);
8118 if (!success)
8119 return false;
8121 // if UnalignedSupport() || address<0> = '0' then
8122 if (UnalignedSupport() || BitIsClear(address, 0)) {
8123 // R[t] = SignExtend(data, 32);
8124 int64_t signed_data = llvm::SignExtend64<16>(data);
8125 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
8126 (uint64_t)signed_data))
8127 return false;
8128 } else // Can only apply before ARMv7
8130 // R[t] = bits(32) UNKNOWN;
8131 WriteBits32Unknown(t);
8134 return true;
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.
8142 bool 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
8158 bool success = false;
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;
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(opcode, 2, 0);
8177 n = Bits32(opcode, 5, 3);
8178 m = Bits32(opcode, 8, 6);
8180 // index = TRUE; add = TRUE; wback = FALSE;
8181 index = true;
8182 add = true;
8183 wback = false;
8185 // (shift_t, shift_n) = (SRType_LSL, 0);
8186 shift_t = SRType_LSL;
8187 shift_n = 0;
8189 break;
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(opcode, 15, 12);
8196 n = Bits32(opcode, 19, 16);
8197 m = Bits32(opcode, 3, 0);
8199 // index = TRUE; add = TRUE; wback = FALSE;
8200 index = true;
8201 add = true;
8202 wback = false;
8204 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
8205 shift_t = SRType_LSL;
8206 shift_n = Bits32(opcode, 5, 4);
8208 // if t == 13 || BadReg(m) then UNPREDICTABLE;
8209 if ((t == 13) || BadReg(m))
8210 return false;
8212 break;
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(opcode, 15, 12);
8218 n = Bits32(opcode, 19, 16);
8219 m = Bits32(opcode, 3, 0);
8221 // index = (P == '1'); add = (U == '1'); wback = (P == '0') ||
8222 // (W == '1');
8223 index = BitIsSet(opcode, 24);
8224 add = BitIsSet(opcode, 23);
8225 wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);
8227 // (shift_t, shift_n) = (SRType_LSL, 0);
8228 shift_t = SRType_LSL;
8229 shift_n = 0;
8231 // if t == 15 || m == 15 then UNPREDICTABLE;
8232 if ((t == 15) || (m == 15))
8233 return false;
8235 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
8236 if (wback && ((n == 15) || (n == t)))
8237 return false;
8239 break;
8241 default:
8242 return false;
8245 uint64_t Rm =
8246 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
8247 if (!success)
8248 return false;
8250 uint64_t Rn =
8251 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
8252 if (!success)
8253 return false;
8255 // offset = Shift(R[m], shift_t, shift_n, APSR.C);
8256 addr_t offset = Shift(Rm, shift_t, shift_n, APSR_C, &success);
8257 if (!success)
8258 return false;
8260 addr_t offset_addr;
8261 addr_t address;
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;
8269 // address = if index then offset_addr else R[n];
8270 if (index)
8271 address = offset_addr;
8272 else
8273 address = Rn;
8275 // data = MemU[address,2];
8276 std::optional<RegisterInfo> base_reg =
8277 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
8278 std::optional<RegisterInfo> offset_reg =
8279 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m);
8281 EmulateInstruction::Context context;
8282 context.type = eContextRegisterLoad;
8283 context.SetRegisterPlusIndirectOffset(*base_reg, *offset_reg);
8285 uint64_t data = MemURead(context, address, 2, 0, &success);
8286 if (!success)
8287 return false;
8289 // if wback then R[n] = offset_addr;
8290 if (wback) {
8291 context.type = eContextAdjustBaseRegister;
8292 context.SetAddress(offset_addr);
8293 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
8294 offset_addr))
8295 return false;
8298 // if UnalignedSupport() || address<0> = '0' then
8299 if (UnalignedSupport() || BitIsClear(address, 0)) {
8300 // R[t] = SignExtend(data, 32);
8301 context.type = eContextRegisterLoad;
8302 context.SetRegisterPlusIndirectOffset(*base_reg, *offset_reg);
8304 int64_t signed_data = llvm::SignExtend64<16>(data);
8305 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,
8306 (uint64_t)signed_data))
8307 return false;
8308 } else // Can only apply before ARMv7
8310 // R[t] = bits(32) UNKNOWN;
8311 WriteBits32Unknown(t);
8314 return true;
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.
8321 bool 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
8330 bool success = false;
8332 if (ConditionPassed(opcode)) {
8333 uint32_t d;
8334 uint32_t m;
8335 uint32_t rotation;
8337 // EncodingSpecificOperations();
8338 switch (encoding) {
8339 case eEncodingT1:
8340 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
8341 d = Bits32(opcode, 2, 0);
8342 m = Bits32(opcode, 5, 3);
8343 rotation = 0;
8345 break;
8347 case eEncodingT2:
8348 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8349 d = Bits32(opcode, 11, 8);
8350 m = Bits32(opcode, 3, 0);
8351 rotation = Bits32(opcode, 5, 4) << 3;
8353 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
8354 if (BadReg(d) || BadReg(m))
8355 return false;
8357 break;
8359 case eEncodingA1:
8360 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8361 d = Bits32(opcode, 15, 12);
8362 m = Bits32(opcode, 3, 0);
8363 rotation = Bits32(opcode, 11, 10) << 3;
8365 // if d == 15 || m == 15 then UNPREDICTABLE;
8366 if ((d == 15) || (m == 15))
8367 return false;
8369 break;
8371 default:
8372 return false;
8375 uint64_t Rm =
8376 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
8377 if (!success)
8378 return false;
8380 // rotated = ROR(R[m], rotation);
8381 uint64_t rotated = ROR(Rm, rotation, &success);
8382 if (!success)
8383 return false;
8385 // R[d] = SignExtend(rotated<7:0>, 32);
8386 int64_t data = llvm::SignExtend64<8>(rotated);
8388 std::optional<RegisterInfo> source_reg =
8389 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m);
8391 EmulateInstruction::Context context;
8392 context.type = eContextRegisterLoad;
8393 context.SetRegister(*source_reg);
8395 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d,
8396 (uint64_t)data))
8397 return false;
8399 return true;
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.
8406 bool 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
8415 bool success = false;
8417 if (ConditionPassed(opcode)) {
8418 uint32_t d;
8419 uint32_t m;
8420 uint32_t rotation;
8422 // EncodingSpecificOperations();
8423 switch (encoding) {
8424 case eEncodingT1:
8425 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
8426 d = Bits32(opcode, 2, 0);
8427 m = Bits32(opcode, 5, 3);
8428 rotation = 0;
8430 break;
8432 case eEncodingT2:
8433 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8434 d = Bits32(opcode, 11, 8);
8435 m = Bits32(opcode, 3, 0);
8436 rotation = Bits32(opcode, 5, 4) << 3;
8438 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
8439 if (BadReg(d) || BadReg(m))
8440 return false;
8442 break;
8444 case eEncodingA1:
8445 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8446 d = Bits32(opcode, 15, 12);
8447 m = Bits32(opcode, 3, 0);
8448 rotation = Bits32(opcode, 11, 10) << 3;
8450 // if d == 15 || m == 15 then UNPREDICTABLE;
8451 if ((d == 15) || (m == 15))
8452 return false;
8454 break;
8456 default:
8457 return false;
8460 uint64_t Rm =
8461 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
8462 if (!success)
8463 return false;
8465 // rotated = ROR(R[m], rotation);
8466 uint64_t rotated = ROR(Rm, rotation, &success);
8467 if (!success)
8468 return false;
8470 // R[d] = SignExtend(rotated<15:0>, 32);
8471 std::optional<RegisterInfo> source_reg =
8472 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m);
8474 EmulateInstruction::Context context;
8475 context.type = eContextRegisterLoad;
8476 context.SetRegister(*source_reg);
8478 int64_t data = llvm::SignExtend64<16>(rotated);
8479 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d,
8480 (uint64_t)data))
8481 return false;
8484 return true;
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.
8491 bool 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
8500 bool success = false;
8502 if (ConditionPassed(opcode)) {
8503 uint32_t d;
8504 uint32_t m;
8505 uint32_t rotation;
8507 // EncodingSpecificOperations();
8508 switch (encoding) {
8509 case eEncodingT1:
8510 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
8511 d = Bits32(opcode, 2, 0);
8512 m = Bits32(opcode, 5, 3);
8513 rotation = 0;
8515 break;
8517 case eEncodingT2:
8518 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8519 d = Bits32(opcode, 11, 8);
8520 m = Bits32(opcode, 3, 0);
8521 rotation = Bits32(opcode, 5, 4) << 3;
8523 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
8524 if (BadReg(d) || BadReg(m))
8525 return false;
8527 break;
8529 case eEncodingA1:
8530 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8531 d = Bits32(opcode, 15, 12);
8532 m = Bits32(opcode, 3, 0);
8533 rotation = Bits32(opcode, 11, 10) << 3;
8535 // if d == 15 || m == 15 then UNPREDICTABLE;
8536 if ((d == 15) || (m == 15))
8537 return false;
8539 break;
8541 default:
8542 return false;
8545 uint64_t Rm =
8546 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
8547 if (!success)
8548 return false;
8550 // rotated = ROR(R[m], rotation);
8551 uint64_t rotated = ROR(Rm, rotation, &success);
8552 if (!success)
8553 return false;
8555 // R[d] = ZeroExtend(rotated<7:0>, 32);
8556 std::optional<RegisterInfo> source_reg =
8557 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m);
8559 EmulateInstruction::Context context;
8560 context.type = eContextRegisterLoad;
8561 context.SetRegister(*source_reg);
8563 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d,
8564 Bits32(rotated, 7, 0)))
8565 return false;
8567 return true;
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.
8574 bool 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
8583 bool success = false;
8585 if (ConditionPassed(opcode)) {
8586 uint32_t d;
8587 uint32_t m;
8588 uint32_t rotation;
8590 switch (encoding) {
8591 case eEncodingT1:
8592 // d = UInt(Rd); m = UInt(Rm); rotation = 0;
8593 d = Bits32(opcode, 2, 0);
8594 m = Bits32(opcode, 5, 3);
8595 rotation = 0;
8597 break;
8599 case eEncodingT2:
8600 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8601 d = Bits32(opcode, 11, 8);
8602 m = Bits32(opcode, 3, 0);
8603 rotation = Bits32(opcode, 5, 4) << 3;
8605 // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
8606 if (BadReg(d) || BadReg(m))
8607 return false;
8609 break;
8611 case eEncodingA1:
8612 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');
8613 d = Bits32(opcode, 15, 12);
8614 m = Bits32(opcode, 3, 0);
8615 rotation = Bits32(opcode, 11, 10) << 3;
8617 // if d == 15 || m == 15 then UNPREDICTABLE;
8618 if ((d == 15) || (m == 15))
8619 return false;
8621 break;
8623 default:
8624 return false;
8627 uint64_t Rm =
8628 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
8629 if (!success)
8630 return false;
8632 // rotated = ROR(R[m], rotation);
8633 uint64_t rotated = ROR(Rm, rotation, &success);
8634 if (!success)
8635 return false;
8637 // R[d] = ZeroExtend(rotated<15:0>, 32);
8638 std::optional<RegisterInfo> source_reg =
8639 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m);
8641 EmulateInstruction::Context context;
8642 context.type = eContextRegisterLoad;
8643 context.SetRegister(*source_reg);
8645 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d,
8646 Bits32(rotated, 15, 0)))
8647 return false;
8649 return true;
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.
8655 bool 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
8670 bool success = false;
8672 if (ConditionPassed(opcode)) {
8673 uint32_t n;
8674 bool wback;
8675 bool increment;
8676 bool wordhigher;
8678 // EncodingSpecificOperations();
8679 switch (encoding) {
8680 case eEncodingT1:
8681 // n = UInt(Rn); wback = (W == '1'); increment = FALSE; wordhigher =
8682 // FALSE;
8683 n = Bits32(opcode, 19, 16);
8684 wback = BitIsSet(opcode, 21);
8685 increment = false;
8686 wordhigher = false;
8688 // if n == 15 then UNPREDICTABLE;
8689 if (n == 15)
8690 return false;
8692 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
8693 if (InITBlock() && !LastInITBlock())
8694 return false;
8696 break;
8698 case eEncodingT2:
8699 // n = UInt(Rn); wback = (W == '1'); increment = TRUE; wordhigher = FALSE;
8700 n = Bits32(opcode, 19, 16);
8701 wback = BitIsSet(opcode, 21);
8702 increment = true;
8703 wordhigher = false;
8705 // if n == 15 then UNPREDICTABLE;
8706 if (n == 15)
8707 return false;
8709 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
8710 if (InITBlock() && !LastInITBlock())
8711 return false;
8713 break;
8715 case eEncodingA1:
8716 // n = UInt(Rn);
8717 n = Bits32(opcode, 19, 16);
8719 // wback = (W == '1'); inc = (U == '1'); wordhigher = (P == U);
8720 wback = BitIsSet(opcode, 21);
8721 increment = BitIsSet(opcode, 23);
8722 wordhigher = (Bit32(opcode, 24) == Bit32(opcode, 23));
8724 // if n == 15 then UNPREDICTABLE;
8725 if (n == 15)
8726 return false;
8728 break;
8730 default:
8731 return false;
8734 // if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE
8735 // then
8736 if (!CurrentModeIsPrivileged())
8737 // UNPREDICTABLE;
8738 return false;
8739 else {
8740 uint64_t Rn =
8741 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
8742 if (!success)
8743 return false;
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;
8752 // if wordhigher then address = address+4;
8753 if (wordhigher)
8754 address = address + 4;
8756 // CPSRWriteByInstr(MemA[address+4,4], '1111', TRUE);
8757 std::optional<RegisterInfo> base_reg =
8758 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
8760 EmulateInstruction::Context context;
8761 context.type = eContextReturnFromException;
8762 context.SetRegisterPlusOffset(*base_reg, address - Rn);
8764 uint64_t data = MemARead(context, address + 4, 4, 0, &success);
8765 if (!success)
8766 return false;
8768 CPSRWriteByInstr(data, 15, true);
8770 // BranchWritePC(MemA[address,4]);
8771 uint64_t data2 = MemARead(context, address, 4, 0, &success);
8772 if (!success)
8773 return false;
8775 BranchWritePC(context, data2);
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, eRegisterKindDWARF, dwarf_r0 + n,
8783 Rn + 8))
8784 return false;
8785 } else {
8786 context.SetOffset(-8);
8787 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
8788 Rn - 8))
8789 return false;
8791 } // if wback
8793 } // if ConditionPassed()
8794 return true;
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.
8801 bool 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
8819 bool success = false;
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(opcode, 11, 8);
8830 Rn = Bits32(opcode, 19, 16);
8831 setflags = BitIsSet(opcode, 20);
8832 imm32 = ThumbExpandImm_C(
8833 opcode, APSR_C,
8834 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, eEncodingT1);
8838 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
8839 return false;
8840 break;
8841 case eEncodingA1:
8842 Rd = Bits32(opcode, 15, 12);
8843 Rn = Bits32(opcode, 19, 16);
8844 setflags = BitIsSet(opcode, 20);
8845 imm32 =
8846 ARMExpandImm_C(opcode, APSR_C,
8847 carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
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;
8858 // Read the first operand.
8859 uint32_t val1 = ReadCoreReg(Rn, &success);
8860 if (!success)
8861 return false;
8863 uint32_t result = val1 ^ imm32;
8865 EmulateInstruction::Context context;
8866 context.type = EmulateInstruction::eContextImmediate;
8867 context.SetNoArgs();
8869 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8870 return false;
8872 return true;
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.
8879 bool 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
8898 bool success = false;
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(opcode, 2, 0);
8909 Rm = Bits32(opcode, 5, 3);
8910 setflags = !InITBlock();
8911 shift_t = SRType_LSL;
8912 shift_n = 0;
8913 break;
8914 case eEncodingT2:
8915 Rd = Bits32(opcode, 11, 8);
8916 Rn = Bits32(opcode, 19, 16);
8917 Rm = Bits32(opcode, 3, 0);
8918 setflags = BitIsSet(opcode, 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, eEncodingT1);
8923 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
8924 return false;
8925 break;
8926 case eEncodingA1:
8927 Rd = Bits32(opcode, 15, 12);
8928 Rn = Bits32(opcode, 19, 16);
8929 Rm = Bits32(opcode, 3, 0);
8930 setflags = BitIsSet(opcode, 20);
8931 shift_n = DecodeImmShiftARM(opcode, shift_t);
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;
8942 // Read the first operand.
8943 uint32_t val1 = ReadCoreReg(Rn, &success);
8944 if (!success)
8945 return false;
8947 // Read the second operand.
8948 uint32_t val2 = ReadCoreReg(Rm, &success);
8949 if (!success)
8950 return false;
8952 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
8953 if (!success)
8954 return false;
8955 uint32_t result = val1 ^ shifted;
8957 EmulateInstruction::Context context;
8958 context.type = EmulateInstruction::eContextImmediate;
8959 context.SetNoArgs();
8961 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
8962 return false;
8964 return true;
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.
8970 bool 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
8988 bool success = false;
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(opcode, 11, 8);
8999 Rn = Bits32(opcode, 19, 16);
9000 setflags = BitIsSet(opcode, 20);
9001 imm32 = ThumbExpandImm_C(
9002 opcode, APSR_C,
9003 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, eEncodingT2);
9007 if (BadReg(Rd) || Rn == 13)
9008 return false;
9009 break;
9010 case eEncodingA1:
9011 Rd = Bits32(opcode, 15, 12);
9012 Rn = Bits32(opcode, 19, 16);
9013 setflags = BitIsSet(opcode, 20);
9014 imm32 =
9015 ARMExpandImm_C(opcode, APSR_C,
9016 carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
9018 if (Rd == 15 && setflags)
9019 return EmulateSUBSPcLrEtc(opcode, encoding);
9020 break;
9021 default:
9022 return false;
9025 // Read the first operand.
9026 uint32_t val1 = ReadCoreReg(Rn, &success);
9027 if (!success)
9028 return false;
9030 uint32_t result = val1 | imm32;
9032 EmulateInstruction::Context context;
9033 context.type = EmulateInstruction::eContextImmediate;
9034 context.SetNoArgs();
9036 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
9037 return false;
9039 return true;
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.
9046 bool 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
9065 bool success = false;
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(opcode, 2, 0);
9076 Rm = Bits32(opcode, 5, 3);
9077 setflags = !InITBlock();
9078 shift_t = SRType_LSL;
9079 shift_n = 0;
9080 break;
9081 case eEncodingT2:
9082 Rd = Bits32(opcode, 11, 8);
9083 Rn = Bits32(opcode, 19, 16);
9084 Rm = Bits32(opcode, 3, 0);
9085 setflags = BitIsSet(opcode, 20);
9086 shift_n = DecodeImmShiftThumb(opcode, shift_t);
9087 // if Rn == '1111' then SEE MOV (register);
9088 if (Rn == 15)
9089 return EmulateMOVRdRm(opcode, eEncodingT3);
9090 if (BadReg(Rd) || Rn == 13 || BadReg(Rm))
9091 return false;
9092 break;
9093 case eEncodingA1:
9094 Rd = Bits32(opcode, 15, 12);
9095 Rn = Bits32(opcode, 19, 16);
9096 Rm = Bits32(opcode, 3, 0);
9097 setflags = BitIsSet(opcode, 20);
9098 shift_n = DecodeImmShiftARM(opcode, shift_t);
9100 if (Rd == 15 && setflags)
9101 return EmulateSUBSPcLrEtc(opcode, encoding);
9102 break;
9103 default:
9104 return false;
9107 // Read the first operand.
9108 uint32_t val1 = ReadCoreReg(Rn, &success);
9109 if (!success)
9110 return false;
9112 // Read the second operand.
9113 uint32_t val2 = ReadCoreReg(Rm, &success);
9114 if (!success)
9115 return false;
9117 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
9118 if (!success)
9119 return false;
9120 uint32_t result = val1 | shifted;
9122 EmulateInstruction::Context context;
9123 context.type = EmulateInstruction::eContextImmediate;
9124 context.SetNoArgs();
9126 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
9127 return false;
9129 return true;
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.
9135 bool 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
9153 bool success = false;
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(opcode, 2, 0);
9163 Rn = Bits32(opcode, 5, 3);
9164 setflags = !InITBlock();
9165 imm32 = 0;
9166 break;
9167 case eEncodingT2:
9168 Rd = Bits32(opcode, 11, 8);
9169 Rn = Bits32(opcode, 19, 16);
9170 setflags = BitIsSet(opcode, 20);
9171 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
9172 if (BadReg(Rd) || BadReg(Rn))
9173 return false;
9174 break;
9175 case eEncodingA1:
9176 Rd = Bits32(opcode, 15, 12);
9177 Rn = Bits32(opcode, 19, 16);
9178 setflags = BitIsSet(opcode, 20);
9179 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
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;
9189 // Read the register value from the operand register Rn.
9190 uint32_t reg_val = ReadCoreReg(Rn, &success);
9191 if (!success)
9192 return false;
9194 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, 1);
9196 EmulateInstruction::Context context;
9197 context.type = EmulateInstruction::eContextImmediate;
9198 context.SetNoArgs();
9200 return WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
9201 res.carry_out, res.overflow);
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.
9207 bool 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
9226 bool success = false;
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(opcode, 11, 8);
9237 Rn = Bits32(opcode, 19, 16);
9238 Rm = Bits32(opcode, 3, 0);
9239 setflags = BitIsSet(opcode, 20);
9240 shift_n = DecodeImmShiftThumb(opcode, shift_t);
9241 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
9242 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
9243 return false;
9244 break;
9245 case eEncodingA1:
9246 Rd = Bits32(opcode, 15, 12);
9247 Rn = Bits32(opcode, 19, 16);
9248 Rm = Bits32(opcode, 3, 0);
9249 setflags = BitIsSet(opcode, 20);
9250 shift_n = DecodeImmShiftARM(opcode, shift_t);
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;
9260 // Read the register value from register Rn.
9261 uint32_t val1 = ReadCoreReg(Rn, &success);
9262 if (!success)
9263 return false;
9265 // Read the register value from register Rm.
9266 uint32_t val2 = ReadCoreReg(Rm, &success);
9267 if (!success)
9268 return false;
9270 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
9271 if (!success)
9272 return false;
9273 AddWithCarryResult res = AddWithCarry(~val1, shifted, 1);
9275 EmulateInstruction::Context context;
9276 context.type = EmulateInstruction::eContextImmediate;
9277 context.SetNoArgs();
9278 return WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
9279 res.carry_out, res.overflow);
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.
9286 bool 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
9304 bool success = false;
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(opcode, 15, 12);
9314 Rn = Bits32(opcode, 19, 16);
9315 setflags = BitIsSet(opcode, 20);
9316 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
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;
9326 // Read the register value from the operand register Rn.
9327 uint32_t reg_val = ReadCoreReg(Rn, &success);
9328 if (!success)
9329 return false;
9331 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, APSR_C);
9333 EmulateInstruction::Context context;
9334 context.type = EmulateInstruction::eContextImmediate;
9335 context.SetNoArgs();
9337 return WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
9338 res.carry_out, res.overflow);
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.
9345 bool 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
9364 bool success = false;
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(opcode, 15, 12);
9375 Rn = Bits32(opcode, 19, 16);
9376 Rm = Bits32(opcode, 3, 0);
9377 setflags = BitIsSet(opcode, 20);
9378 shift_n = DecodeImmShiftARM(opcode, shift_t);
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;
9388 // Read the register value from register Rn.
9389 uint32_t val1 = ReadCoreReg(Rn, &success);
9390 if (!success)
9391 return false;
9393 // Read the register value from register Rm.
9394 uint32_t val2 = ReadCoreReg(Rm, &success);
9395 if (!success)
9396 return false;
9398 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
9399 if (!success)
9400 return false;
9401 AddWithCarryResult res = AddWithCarry(~val1, shifted, APSR_C);
9403 EmulateInstruction::Context context;
9404 context.type = EmulateInstruction::eContextImmediate;
9405 context.SetNoArgs();
9406 return WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
9407 res.carry_out, res.overflow);
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.
9415 bool 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
9433 bool success = false;
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(opcode, 11, 8);
9443 Rn = Bits32(opcode, 19, 16);
9444 setflags = BitIsSet(opcode, 20);
9445 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
9446 if (BadReg(Rd) || BadReg(Rn))
9447 return false;
9448 break;
9449 case eEncodingA1:
9450 Rd = Bits32(opcode, 15, 12);
9451 Rn = Bits32(opcode, 19, 16);
9452 setflags = BitIsSet(opcode, 20);
9453 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
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;
9463 // Read the register value from the operand register Rn.
9464 uint32_t reg_val = ReadCoreReg(Rn, &success);
9465 if (!success)
9466 return false;
9468 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, APSR_C);
9470 EmulateInstruction::Context context;
9471 context.type = EmulateInstruction::eContextImmediate;
9472 context.SetNoArgs();
9474 return WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
9475 res.carry_out, res.overflow);
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.
9483 bool 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
9502 bool success = false;
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(opcode, 2, 0);
9513 Rm = Bits32(opcode, 5, 3);
9514 setflags = !InITBlock();
9515 shift_t = SRType_LSL;
9516 shift_n = 0;
9517 break;
9518 case eEncodingT2:
9519 Rd = Bits32(opcode, 11, 8);
9520 Rn = Bits32(opcode, 19, 16);
9521 Rm = Bits32(opcode, 3, 0);
9522 setflags = BitIsSet(opcode, 20);
9523 shift_n = DecodeImmShiftThumb(opcode, shift_t);
9524 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
9525 return false;
9526 break;
9527 case eEncodingA1:
9528 Rd = Bits32(opcode, 15, 12);
9529 Rn = Bits32(opcode, 19, 16);
9530 Rm = Bits32(opcode, 3, 0);
9531 setflags = BitIsSet(opcode, 20);
9532 shift_n = DecodeImmShiftARM(opcode, shift_t);
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;
9542 // Read the register value from register Rn.
9543 uint32_t val1 = ReadCoreReg(Rn, &success);
9544 if (!success)
9545 return false;
9547 // Read the register value from register Rm.
9548 uint32_t val2 = ReadCoreReg(Rm, &success);
9549 if (!success)
9550 return false;
9552 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
9553 if (!success)
9554 return false;
9555 AddWithCarryResult res = AddWithCarry(val1, ~shifted, APSR_C);
9557 EmulateInstruction::Context context;
9558 context.type = EmulateInstruction::eContextImmediate;
9559 context.SetNoArgs();
9560 return WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
9561 res.carry_out, res.overflow);
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.
9567 bool 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
9582 bool success = false;
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(opcode, 2, 0);
9592 Rn = Bits32(opcode, 5, 3);
9593 setflags = !InITBlock();
9594 imm32 = Bits32(opcode, 8, 6); // imm32 = ZeroExtend(imm3, 32)
9595 break;
9596 case eEncodingT2:
9597 Rd = Rn = Bits32(opcode, 10, 8);
9598 setflags = !InITBlock();
9599 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
9600 break;
9601 case eEncodingT3:
9602 Rd = Bits32(opcode, 11, 8);
9603 Rn = Bits32(opcode, 19, 16);
9604 setflags = BitIsSet(opcode, 20);
9605 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
9607 // if Rd == '1111' && S == '1' then SEE CMP (immediate);
9608 if (Rd == 15 && setflags)
9609 return EmulateCMPImm(opcode, eEncodingT2);
9611 // if Rn == '1101' then SEE SUB (SP minus immediate);
9612 if (Rn == 13)
9613 return EmulateSUBSPImm(opcode, eEncodingT2);
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(opcode, 11, 8);
9621 Rn = Bits32(opcode, 19, 16);
9622 setflags = BitIsSet(opcode, 20);
9623 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
9625 // if Rn == '1111' then SEE ADR;
9626 if (Rn == 15)
9627 return EmulateADR(opcode, eEncodingT2);
9629 // if Rn == '1101' then SEE SUB (SP minus immediate);
9630 if (Rn == 13)
9631 return EmulateSUBSPImm(opcode, eEncodingT3);
9633 if (BadReg(Rd))
9634 return false;
9635 break;
9636 default:
9637 return false;
9639 // Read the register value from the operand register Rn.
9640 uint32_t reg_val = ReadCoreReg(Rn, &success);
9641 if (!success)
9642 return false;
9644 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
9646 EmulateInstruction::Context context;
9647 context.type = EmulateInstruction::eContextImmediate;
9648 context.SetNoArgs();
9650 return WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
9651 res.carry_out, res.overflow);
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.
9657 bool 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
9675 bool success = false;
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(opcode, 15, 12);
9686 Rn = Bits32(opcode, 19, 16);
9687 setflags = BitIsSet(opcode, 20);
9688 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
9690 // if Rn == '1111' && S == '0' then SEE ADR;
9691 if (Rn == 15 && !setflags)
9692 return EmulateADR(opcode, eEncodingA2);
9694 // if Rn == '1101' then SEE SUB (SP minus immediate);
9695 if (Rn == 13)
9696 return EmulateSUBSPImm(opcode, eEncodingA1);
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;
9706 // Read the register value from the operand register Rn.
9707 uint32_t reg_val = ReadCoreReg(Rn, &success);
9708 if (!success)
9709 return false;
9711 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
9713 EmulateInstruction::Context context;
9714 if (Rd == 13)
9715 context.type = EmulateInstruction::eContextAdjustStackPointer;
9716 else
9717 context.type = EmulateInstruction::eContextRegisterPlusOffset;
9719 std::optional<RegisterInfo> dwarf_reg =
9720 GetRegisterInfo(eRegisterKindDWARF, Rn);
9721 int64_t imm32_signed = imm32;
9722 context.SetRegisterPlusOffset(*dwarf_reg, -imm32_signed);
9724 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
9725 res.carry_out, res.overflow))
9726 return false;
9728 return true;
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.
9734 bool 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
9747 bool success = false;
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(opcode, 19, 16);
9757 imm32 = ThumbExpandImm_C(
9758 opcode, APSR_C,
9759 carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
9760 if (BadReg(Rn))
9761 return false;
9762 break;
9763 case eEncodingA1:
9764 Rn = Bits32(opcode, 19, 16);
9765 imm32 =
9766 ARMExpandImm_C(opcode, APSR_C,
9767 carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
9768 break;
9769 default:
9770 return false;
9773 // Read the first operand.
9774 uint32_t val1 = ReadCoreReg(Rn, &success);
9775 if (!success)
9776 return false;
9778 uint32_t result = val1 ^ imm32;
9780 EmulateInstruction::Context context;
9781 context.type = EmulateInstruction::eContextImmediate;
9782 context.SetNoArgs();
9784 if (!WriteFlags(context, result, carry))
9785 return false;
9787 return true;
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.
9793 bool 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
9807 bool success = false;
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(opcode, 19, 16);
9817 Rm = Bits32(opcode, 3, 0);
9818 shift_n = DecodeImmShiftThumb(opcode, shift_t);
9819 if (BadReg(Rn) || BadReg(Rm))
9820 return false;
9821 break;
9822 case eEncodingA1:
9823 Rn = Bits32(opcode, 19, 16);
9824 Rm = Bits32(opcode, 3, 0);
9825 shift_n = DecodeImmShiftARM(opcode, shift_t);
9826 break;
9827 default:
9828 return false;
9831 // Read the first operand.
9832 uint32_t val1 = ReadCoreReg(Rn, &success);
9833 if (!success)
9834 return false;
9836 // Read the second operand.
9837 uint32_t val2 = ReadCoreReg(Rm, &success);
9838 if (!success)
9839 return false;
9841 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
9842 if (!success)
9843 return false;
9844 uint32_t result = val1 ^ shifted;
9846 EmulateInstruction::Context context;
9847 context.type = EmulateInstruction::eContextImmediate;
9848 context.SetNoArgs();
9850 if (!WriteFlags(context, result, carry))
9851 return false;
9853 return true;
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.
9859 bool 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
9872 bool success = false;
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(opcode, 19, 16);
9882 imm32 = ThumbExpandImm_C(
9883 opcode, APSR_C,
9884 carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
9885 if (BadReg(Rn))
9886 return false;
9887 break;
9888 case eEncodingA1:
9889 Rn = Bits32(opcode, 19, 16);
9890 imm32 =
9891 ARMExpandImm_C(opcode, APSR_C,
9892 carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
9893 break;
9894 default:
9895 return false;
9898 // Read the first operand.
9899 uint32_t val1 = ReadCoreReg(Rn, &success);
9900 if (!success)
9901 return false;
9903 uint32_t result = val1 & imm32;
9905 EmulateInstruction::Context context;
9906 context.type = EmulateInstruction::eContextImmediate;
9907 context.SetNoArgs();
9909 if (!WriteFlags(context, result, carry))
9910 return false;
9912 return true;
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.
9918 bool 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
9932 bool success = false;
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(opcode, 2, 0);
9942 Rm = Bits32(opcode, 5, 3);
9943 shift_t = SRType_LSL;
9944 shift_n = 0;
9945 break;
9946 case eEncodingT2:
9947 Rn = Bits32(opcode, 19, 16);
9948 Rm = Bits32(opcode, 3, 0);
9949 shift_n = DecodeImmShiftThumb(opcode, shift_t);
9950 if (BadReg(Rn) || BadReg(Rm))
9951 return false;
9952 break;
9953 case eEncodingA1:
9954 Rn = Bits32(opcode, 19, 16);
9955 Rm = Bits32(opcode, 3, 0);
9956 shift_n = DecodeImmShiftARM(opcode, shift_t);
9957 break;
9958 default:
9959 return false;
9962 // Read the first operand.
9963 uint32_t val1 = ReadCoreReg(Rn, &success);
9964 if (!success)
9965 return false;
9967 // Read the second operand.
9968 uint32_t val2 = ReadCoreReg(Rm, &success);
9969 if (!success)
9970 return false;
9972 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
9973 if (!success)
9974 return false;
9975 uint32_t result = val1 & shifted;
9977 EmulateInstruction::Context context;
9978 context.type = EmulateInstruction::eContextImmediate;
9979 context.SetNoArgs();
9981 if (!WriteFlags(context, result, carry))
9982 return false;
9984 return true;
9987 // A8.6.216 SUB (SP minus register)
9988 bool 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
10006 bool success = false;
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;
10015 switch (encoding) {
10016 case eEncodingT1:
10017 // d = UInt(Rd); m = UInt(Rm); setflags = (S == '1');
10018 d = Bits32(opcode, 11, 8);
10019 m = Bits32(opcode, 3, 0);
10020 setflags = BitIsSet(opcode, 20);
10022 // (shift_t, shift_n) = DecodeImmShift(type, imm3:imm2);
10023 shift_n = DecodeImmShiftThumb(opcode, shift_t);
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;
10030 // if d == 15 || BadReg(m) then UNPREDICTABLE;
10031 if ((d == 15) || BadReg(m))
10032 return false;
10033 break;
10035 case eEncodingA1:
10036 // d = UInt(Rd); m = UInt(Rm); setflags = (S == '1');
10037 d = Bits32(opcode, 15, 12);
10038 m = Bits32(opcode, 3, 0);
10039 setflags = BitIsSet(opcode, 20);
10041 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
10042 // instructions;
10043 if (d == 15 && setflags)
10044 EmulateSUBSPcLrEtc(opcode, encoding);
10046 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
10047 shift_n = DecodeImmShiftARM(opcode, shift_t);
10048 break;
10050 default:
10051 return false;
10054 // shifted = Shift(R[m], shift_t, shift_n, APSR.C);
10055 uint32_t Rm = ReadCoreReg(m, &success);
10056 if (!success)
10057 return false;
10059 uint32_t shifted = Shift(Rm, shift_t, shift_n, APSR_C, &success);
10060 if (!success)
10061 return false;
10063 // (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), '1');
10064 uint32_t sp_val = ReadCoreReg(SP_REG, &success);
10065 if (!success)
10066 return false;
10068 AddWithCarryResult res = AddWithCarry(sp_val, ~shifted, 1);
10070 EmulateInstruction::Context context;
10071 context.type = eContextArithmetic;
10072 std::optional<RegisterInfo> sp_reg =
10073 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp);
10074 std::optional<RegisterInfo> dwarf_reg =
10075 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m);
10076 context.SetRegisterRegisterOperands(*sp_reg, *dwarf_reg);
10078 if (!WriteCoreRegOptionalFlags(context, res.result, dwarf_r0 + d, setflags,
10079 res.carry_out, res.overflow))
10080 return false;
10082 return true;
10085 // A8.6.7 ADD (register-shifted register)
10086 bool 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
10102 bool success = false;
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;
10112 switch (encoding) {
10113 case eEncodingA1:
10114 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); s = UInt(Rs);
10115 d = Bits32(opcode, 15, 12);
10116 n = Bits32(opcode, 19, 16);
10117 m = Bits32(opcode, 3, 0);
10118 s = Bits32(opcode, 11, 8);
10120 // setflags = (S == '1'); shift_t = DecodeRegShift(type);
10121 setflags = BitIsSet(opcode, 20);
10122 shift_t = DecodeRegShift(Bits32(opcode, 6, 5));
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;
10129 default:
10130 return false;
10133 // shift_n = UInt(R[s]<7:0>);
10134 uint32_t Rs = ReadCoreReg(s, &success);
10135 if (!success)
10136 return false;
10138 uint32_t shift_n = Bits32(Rs, 7, 0);
10140 // shifted = Shift(R[m], shift_t, shift_n, APSR.C);
10141 uint32_t Rm = ReadCoreReg(m, &success);
10142 if (!success)
10143 return false;
10145 uint32_t shifted = Shift(Rm, shift_t, shift_n, APSR_C, &success);
10146 if (!success)
10147 return false;
10149 // (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
10150 uint32_t Rn = ReadCoreReg(n, &success);
10151 if (!success)
10152 return false;
10154 AddWithCarryResult res = AddWithCarry(Rn, shifted, 0);
10156 // R[d] = result;
10157 EmulateInstruction::Context context;
10158 context.type = eContextArithmetic;
10159 std::optional<RegisterInfo> reg_n =
10160 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
10161 std::optional<RegisterInfo> reg_m =
10162 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m);
10164 context.SetRegisterRegisterOperands(*reg_n, *reg_m);
10166 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d,
10167 res.result))
10168 return false;
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, res.result, res.carry_out, res.overflow);
10178 return true;
10181 // A8.6.213 SUB (register)
10182 bool 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
10200 bool success = false;
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;
10210 switch (encoding) {
10211 case eEncodingT1:
10212 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = !InITBlock();
10213 d = Bits32(opcode, 2, 0);
10214 n = Bits32(opcode, 5, 3);
10215 m = Bits32(opcode, 8, 6);
10216 setflags = !InITBlock();
10218 // (shift_t, shift_n) = (SRType_LSL, 0);
10219 shift_t = SRType_LSL;
10220 shift_n = 0;
10222 break;
10224 case eEncodingT2:
10225 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S =="1");
10226 d = Bits32(opcode, 11, 8);
10227 n = Bits32(opcode, 19, 16);
10228 m = Bits32(opcode, 3, 0);
10229 setflags = BitIsSet(opcode, 20);
10231 // if Rd == "1111" && S == "1" then SEE CMP (register);
10232 if (d == 15 && setflags == 1)
10233 return EmulateCMPImm(opcode, eEncodingT3);
10235 // if Rn == "1101" then SEE SUB (SP minus register);
10236 if (n == 13)
10237 return EmulateSUBSPReg(opcode, eEncodingT1);
10239 // (shift_t, shift_n) = DecodeImmShift(type, imm3:imm2);
10240 shift_n = DecodeImmShiftThumb(opcode, shift_t);
10242 // if d == 13 || (d == 15 && S == '0') || n == 15 || BadReg(m) then
10243 // UNPREDICTABLE;
10244 if ((d == 13) || ((d == 15) && BitIsClear(opcode, 20)) || (n == 15) ||
10245 BadReg(m))
10246 return false;
10248 break;
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(opcode, 15, 12);
10254 n = Bits32(opcode, 19, 16);
10255 m = Bits32(opcode, 3, 0);
10256 setflags = BitIsSet(opcode, 20);
10258 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related
10259 // instructions;
10260 if ((d == 15) && setflags)
10261 EmulateSUBSPcLrEtc(opcode, encoding);
10263 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
10264 shift_n = DecodeImmShiftARM(opcode, shift_t);
10266 break;
10268 default:
10269 return false;
10272 // shifted = Shift(R[m], shift_t, shift_n, APSR.C);
10273 uint32_t Rm = ReadCoreReg(m, &success);
10274 if (!success)
10275 return false;
10277 uint32_t shifted = Shift(Rm, shift_t, shift_n, APSR_C, &success);
10278 if (!success)
10279 return false;
10281 // (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');
10282 uint32_t Rn = ReadCoreReg(n, &success);
10283 if (!success)
10284 return false;
10286 AddWithCarryResult res = AddWithCarry(Rn, ~shifted, 1);
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;
10297 EmulateInstruction::Context context;
10298 context.type = eContextArithmetic;
10299 std::optional<RegisterInfo> reg_n =
10300 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
10301 std::optional<RegisterInfo> reg_m =
10302 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m);
10303 context.SetRegisterRegisterOperands(*reg_n, *reg_m);
10305 if (!WriteCoreRegOptionalFlags(context, res.result, dwarf_r0 + d, setflags,
10306 res.carry_out, res.overflow))
10307 return false;
10309 return true;
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.
10316 bool 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
10329 bool success = false;
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();
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(opcode, 11, 8);
10344 t = Bits32(opcode, 15, 12);
10345 n = Bits32(opcode, 19, 16);
10346 imm32 = Bits32(opcode, 7, 0) << 2;
10348 // if BadReg(d) || BadReg(t) || n == 15 then UNPREDICTABLE;
10349 if (BadReg(d) || BadReg(t) || (n == 15))
10350 return false;
10352 // if d == n || d == t then UNPREDICTABLE;
10353 if ((d == n) || (d == t))
10354 return false;
10356 break;
10358 case eEncodingA1:
10359 // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 = Zeros(32); // Zero
10360 // offset
10361 d = Bits32(opcode, 15, 12);
10362 t = Bits32(opcode, 3, 0);
10363 n = Bits32(opcode, 19, 16);
10364 imm32 = 0;
10366 // if d == 15 || t == 15 || n == 15 then UNPREDICTABLE;
10367 if ((d == 15) || (t == 15) || (n == 15))
10368 return false;
10370 // if d == n || d == t then UNPREDICTABLE;
10371 if ((d == n) || (d == t))
10372 return false;
10374 break;
10376 default:
10377 return false;
10380 // address = R[n] + imm32;
10381 uint32_t Rn = ReadCoreReg(n, &success);
10382 if (!success)
10383 return false;
10385 addr_t address = Rn + imm32;
10387 std::optional<RegisterInfo> base_reg =
10388 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
10389 std::optional<RegisterInfo> data_reg =
10390 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t);
10391 EmulateInstruction::Context context;
10392 context.type = eContextRegisterStore;
10393 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, imm32);
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(eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
10404 if (!success)
10405 return false;
10407 if (!MemAWrite(context, address, Rt, addr_byte_size))
10408 return false;
10410 // R[d] = 0;
10411 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, 0))
10412 return false;
10414 #if 0 // unreachable because if true
10415 else
10417 // R[d] = 1;
10418 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, 1))
10419 return false;
10421 #endif // unreachable because if true
10423 return true;
10426 // A8.6.197 STRB (immediate, ARM)
10427 bool 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
10438 bool success = false;
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;
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(opcode, 15, 12);
10453 n = Bits32(opcode, 19, 16);
10454 imm32 = Bits32(opcode, 11, 0);
10456 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
10457 index = BitIsSet(opcode, 24);
10458 add = BitIsSet(opcode, 23);
10459 wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);
10461 // if t == 15 then UNPREDICTABLE;
10462 if (t == 15)
10463 return false;
10465 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
10466 if (wback && ((n == 15) || (n == t)))
10467 return false;
10469 break;
10471 default:
10472 return false;
10475 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10476 uint32_t Rn = ReadCoreReg(n, &success);
10477 if (!success)
10478 return false;
10480 addr_t offset_addr;
10481 if (add)
10482 offset_addr = Rn + imm32;
10483 else
10484 offset_addr = Rn - imm32;
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;
10493 // MemU[address,1] = R[t]<7:0>;
10494 uint32_t Rt = ReadCoreReg(t, &success);
10495 if (!success)
10496 return false;
10498 std::optional<RegisterInfo> base_reg =
10499 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
10500 std::optional<RegisterInfo> data_reg =
10501 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t);
10502 EmulateInstruction::Context context;
10503 context.type = eContextRegisterStore;
10504 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, address - Rn);
10506 if (!MemUWrite(context, address, Bits32(Rt, 7, 0), 1))
10507 return false;
10509 // if wback then R[n] = offset_addr;
10510 if (wback) {
10511 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
10512 offset_addr))
10513 return false;
10516 return true;
10519 // A8.6.194 STR (immediate, ARM)
10520 bool 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
10531 bool success = false;
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;
10541 const uint32_t addr_byte_size = GetAddressByteSize();
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(opcode, 15, 12);
10550 n = Bits32(opcode, 19, 16);
10551 imm32 = Bits32(opcode, 11, 0);
10553 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
10554 index = BitIsSet(opcode, 24);
10555 add = BitIsSet(opcode, 23);
10556 wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);
10558 // if wback && (n == 15 || n == t) then UNPREDICTABLE;
10559 if (wback && ((n == 15) || (n == t)))
10560 return false;
10562 break;
10564 default:
10565 return false;
10568 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10569 uint32_t Rn = ReadCoreReg(n, &success);
10570 if (!success)
10571 return false;
10573 addr_t offset_addr;
10574 if (add)
10575 offset_addr = Rn + imm32;
10576 else
10577 offset_addr = Rn - imm32;
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;
10586 std::optional<RegisterInfo> base_reg =
10587 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
10588 std::optional<RegisterInfo> data_reg =
10589 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t);
10590 EmulateInstruction::Context context;
10591 context.type = eContextRegisterStore;
10592 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, address - Rn);
10594 // MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
10595 uint32_t Rt = ReadCoreReg(t, &success);
10596 if (!success)
10597 return false;
10599 if (t == 15) {
10600 uint32_t pc_value = ReadCoreReg(PC_REG, &success);
10601 if (!success)
10602 return false;
10604 if (!MemUWrite(context, address, pc_value, addr_byte_size))
10605 return false;
10606 } else {
10607 if (!MemUWrite(context, address, Rt, addr_byte_size))
10608 return false;
10611 // if wback then R[n] = offset_addr;
10612 if (wback) {
10613 context.type = eContextAdjustBaseRegister;
10614 context.SetImmediate(offset_addr);
10616 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
10617 offset_addr))
10618 return false;
10621 return true;
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.
10629 bool 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
10641 bool success = false;
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;
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(opcode, 15, 12);
10659 t2 = Bits32(opcode, 11, 8);
10660 n = Bits32(opcode, 19, 16);
10661 imm32 = Bits32(opcode, 7, 0) << 2;
10663 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
10664 index = BitIsSet(opcode, 24);
10665 add = BitIsSet(opcode, 23);
10666 wback = BitIsSet(opcode, 21);
10668 // if wback && (n == t || n == t2) then UNPREDICTABLE;
10669 if (wback && ((n == t) || (n == t2)))
10670 return false;
10672 // if BadReg(t) || BadReg(t2) || t == t2 then UNPREDICTABLE;
10673 if (BadReg(t) || BadReg(t2) || (t == t2))
10674 return false;
10676 break;
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(opcode, 15, 12);
10684 if (BitIsSet(t, 0))
10685 return false;
10686 t2 = t + 1;
10687 n = Bits32(opcode, 19, 16);
10688 imm32 = (Bits32(opcode, 11, 8) << 4) | Bits32(opcode, 3, 0);
10690 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
10691 index = BitIsSet(opcode, 24);
10692 add = BitIsSet(opcode, 23);
10693 wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);
10695 // if P == '0' && W == '1' then UNPREDICTABLE;
10696 if (BitIsClear(opcode, 24) && BitIsSet(opcode, 21))
10697 return false;
10699 // if wback && (n == t || n == t2) then UNPREDICTABLE;
10700 if (wback && ((n == t) || (n == t2)))
10701 return false;
10703 // if t2 == 15 then UNPREDICTABLE;
10704 if (t2 == 15)
10705 return false;
10707 break;
10709 default:
10710 return false;
10713 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
10714 uint32_t Rn = ReadCoreReg(n, &success);
10715 if (!success)
10716 return false;
10718 addr_t offset_addr;
10719 if (add)
10720 offset_addr = Rn + imm32;
10721 else
10722 offset_addr = Rn - imm32;
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;
10731 // R[t] = MemA[address,4];
10733 EmulateInstruction::Context context;
10734 if (n == 13)
10735 context.type = eContextPopRegisterOffStack;
10736 else
10737 context.type = eContextRegisterLoad;
10738 context.SetAddress(address);
10740 const uint32_t addr_byte_size = GetAddressByteSize();
10741 uint32_t data = MemARead(context, address, addr_byte_size, 0, &success);
10742 if (!success)
10743 return false;
10745 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, data))
10746 return false;
10748 // R[t2] = MemA[address+4,4];
10749 context.SetAddress(address + 4);
10750 data = MemARead(context, address + 4, addr_byte_size, 0, &success);
10751 if (!success)
10752 return false;
10754 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t2,
10755 data))
10756 return false;
10758 // if wback then R[n] = offset_addr;
10759 if (wback) {
10760 context.type = eContextAdjustBaseRegister;
10761 context.SetAddress(offset_addr);
10763 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
10764 offset_addr))
10765 return false;
10768 return true;
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.
10775 bool 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
10787 bool success = false;
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;
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(opcode, 15, 12);
10803 if (BitIsSet(t, 0))
10804 return false;
10805 t2 = t + 1;
10806 n = Bits32(opcode, 19, 16);
10807 m = Bits32(opcode, 3, 0);
10809 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
10810 index = BitIsSet(opcode, 24);
10811 add = BitIsSet(opcode, 23);
10812 wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);
10814 // if P == '0' && W == '1' then UNPREDICTABLE;
10815 if (BitIsClear(opcode, 24) && BitIsSet(opcode, 21))
10816 return false;
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;
10822 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;
10823 if (wback && ((n == 15) || (n == t) || (n == t2)))
10824 return false;
10826 // if ArchVersion() < 6 && wback && m == n then UNPREDICTABLE;
10827 if ((ArchVersion() < 6) && wback && (m == n))
10828 return false;
10829 break;
10831 default:
10832 return false;
10835 uint32_t Rn = ReadCoreReg(n, &success);
10836 if (!success)
10837 return false;
10839 uint32_t Rm = ReadCoreReg(m, &success);
10840 if (!success)
10841 return false;
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;
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;
10857 EmulateInstruction::Context context;
10858 if (n == 13)
10859 context.type = eContextPopRegisterOffStack;
10860 else
10861 context.type = eContextRegisterLoad;
10862 context.SetAddress(address);
10864 // R[t] = MemA[address,4];
10865 const uint32_t addr_byte_size = GetAddressByteSize();
10866 uint32_t data = MemARead(context, address, addr_byte_size, 0, &success);
10867 if (!success)
10868 return false;
10870 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, data))
10871 return false;
10873 // R[t2] = MemA[address+4,4];
10875 data = MemARead(context, address + 4, addr_byte_size, 0, &success);
10876 if (!success)
10877 return false;
10879 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t2,
10880 data))
10881 return false;
10883 // if wback then R[n] = offset_addr;
10884 if (wback) {
10885 context.type = eContextAdjustBaseRegister;
10886 context.SetAddress(offset_addr);
10888 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
10889 offset_addr))
10890 return false;
10893 return true;
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.
10900 bool 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
10912 bool success = false;
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;
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(opcode, 15, 12);
10929 t2 = Bits32(opcode, 11, 8);
10930 n = Bits32(opcode, 19, 16);
10931 imm32 = Bits32(opcode, 7, 0) << 2;
10933 // index = (P == '1'); add = (U == '1'); wback = (W == '1');
10934 index = BitIsSet(opcode, 24);
10935 add = BitIsSet(opcode, 23);
10936 wback = BitIsSet(opcode, 21);
10938 // if wback && (n == t || n == t2) then UNPREDICTABLE;
10939 if (wback && ((n == t) || (n == t2)))
10940 return false;
10942 // if n == 15 || BadReg(t) || BadReg(t2) then UNPREDICTABLE;
10943 if ((n == 15) || BadReg(t) || BadReg(t2))
10944 return false;
10946 break;
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(opcode, 15, 12);
10953 if (BitIsSet(t, 0))
10954 return false;
10956 t2 = t + 1;
10957 n = Bits32(opcode, 19, 16);
10958 imm32 = (Bits32(opcode, 11, 8) << 4) | Bits32(opcode, 3, 0);
10960 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
10961 index = BitIsSet(opcode, 24);
10962 add = BitIsSet(opcode, 23);
10963 wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);
10965 // if P == '0' && W == '1' then UNPREDICTABLE;
10966 if (BitIsClear(opcode, 24) && BitIsSet(opcode, 21))
10967 return false;
10969 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;
10970 if (wback && ((n == 15) || (n == t) || (n == t2)))
10971 return false;
10973 // if t2 == 15 then UNPREDICTABLE;
10974 if (t2 == 15)
10975 return false;
10977 break;
10979 default:
10980 return false;
10983 std::optional<RegisterInfo> base_reg =
10984 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
10986 uint32_t Rn = ReadCoreReg(n, &success);
10987 if (!success)
10988 return false;
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;
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;
11004 // MemA[address,4] = R[t];
11005 std::optional<RegisterInfo> data_reg =
11006 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t);
11008 uint32_t data = ReadCoreReg(t, &success);
11009 if (!success)
11010 return false;
11012 EmulateInstruction::Context context;
11013 if (n == 13)
11014 context.type = eContextPushRegisterOnStack;
11015 else
11016 context.type = eContextRegisterStore;
11017 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, address - Rn);
11019 const uint32_t addr_byte_size = GetAddressByteSize();
11021 if (!MemAWrite(context, address, data, addr_byte_size))
11022 return false;
11024 // MemA[address+4,4] = R[t2];
11025 data_reg = GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t2);
11026 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg,
11027 (address + 4) - Rn);
11029 data = ReadCoreReg(t2, &success);
11030 if (!success)
11031 return false;
11033 if (!MemAWrite(context, address + 4, data, addr_byte_size))
11034 return false;
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);
11044 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
11045 offset_addr))
11046 return false;
11049 return true;
11052 // A8.6.201 STRD (register)
11053 bool 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
11065 bool success = false;
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;
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(opcode, 15, 12);
11081 if (BitIsSet(t, 0))
11082 return false;
11084 t2 = t + 1;
11085 n = Bits32(opcode, 19, 16);
11086 m = Bits32(opcode, 3, 0);
11088 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');
11089 index = BitIsSet(opcode, 24);
11090 add = BitIsSet(opcode, 23);
11091 wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);
11093 // if P == '0' && W == '1' then UNPREDICTABLE;
11094 if (BitIsClear(opcode, 24) && BitIsSet(opcode, 21))
11095 return false;
11097 // if t2 == 15 || m == 15 then UNPREDICTABLE;
11098 if ((t2 == 15) || (m == 15))
11099 return false;
11101 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;
11102 if (wback && ((n == 15) || (n == t) || (n == t2)))
11103 return false;
11105 // if ArchVersion() < 6 && wback && m == n then UNPREDICTABLE;
11106 if ((ArchVersion() < 6) && wback && (m == n))
11107 return false;
11109 break;
11111 default:
11112 return false;
11115 uint32_t Rn = ReadCoreReg(n, &success);
11116 if (!success)
11117 return false;
11119 uint32_t Rm = ReadCoreReg(m, &success);
11120 if (!success)
11121 return false;
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;
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(t, &success);
11138 if (!success)
11139 return false;
11141 EmulateInstruction::Context context;
11142 if (t == 13)
11143 context.type = eContextPushRegisterOnStack;
11144 else
11145 context.type = eContextRegisterStore;
11147 std::optional<RegisterInfo> base_reg =
11148 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
11149 std::optional<RegisterInfo> offset_reg =
11150 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m);
11151 std::optional<RegisterInfo> data_reg =
11152 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t);
11153 context.SetRegisterToRegisterPlusIndirectOffset(*base_reg, *offset_reg,
11154 *data_reg);
11156 const uint32_t addr_byte_size = GetAddressByteSize();
11158 if (!MemAWrite(context, address, Rt, addr_byte_size))
11159 return false;
11161 // MemA[address+4,4] = R[t2];
11162 uint32_t Rt2 = ReadCoreReg(t2, &success);
11163 if (!success)
11164 return false;
11166 data_reg = GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t2);
11168 context.SetRegisterToRegisterPlusIndirectOffset(*base_reg, *offset_reg,
11169 *data_reg);
11171 if (!MemAWrite(context, address + 4, Rt2, addr_byte_size))
11172 return false;
11174 // if wback then R[n] = offset_addr;
11175 if (wback) {
11176 context.type = eContextAdjustBaseRegister;
11177 context.SetAddress(offset_addr);
11179 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
11180 offset_addr))
11181 return false;
11184 return true;
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.
11190 bool 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
11207 bool success = false;
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;
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(opcode, 24) == Bit32(opcode, 23)) && BitIsSet(opcode, 21))
11226 return false;
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(opcode, 23);
11233 wback = BitIsSet(opcode, 21);
11235 // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:'00', 32);
11236 d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);
11237 n = Bits32(opcode, 19, 16);
11238 imm32 = Bits32(opcode, 7, 0) << 2;
11240 // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see 'FLDMX'.
11241 regs = Bits32(opcode, 7, 0) / 2;
11243 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then
11244 // UNPREDICTABLE;
11245 if (n == 15 && (wback || CurrentInstrSet() != eModeARM))
11246 return false;
11248 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
11249 if ((regs == 0) || (regs > 16) || ((d + regs) > 32))
11250 return false;
11252 break;
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(opcode, 24) == Bit32(opcode, 23)) && BitIsSet(opcode, 21))
11261 return false;
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(opcode, 23);
11269 wback = BitIsSet(opcode, 21);
11270 d = (Bits32(opcode, 15, 12) << 1) | Bit32(opcode, 22);
11271 n = Bits32(opcode, 19, 16);
11273 // imm32 = ZeroExtend(imm8:'00', 32); regs = UInt(imm8);
11274 imm32 = Bits32(opcode, 7, 0) << 2;
11275 regs = Bits32(opcode, 7, 0);
11277 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then
11278 // UNPREDICTABLE;
11279 if ((n == 15) && (wback || (CurrentInstrSet() != eModeARM)))
11280 return false;
11282 // if regs == 0 || (d+regs) > 32 then UNPREDICTABLE;
11283 if ((regs == 0) || ((d + regs) > 32))
11284 return false;
11285 break;
11287 default:
11288 return false;
11291 uint32_t Rn = ReadCoreReg(n, &success);
11292 if (!success)
11293 return false;
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;
11302 // if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;
11303 EmulateInstruction::Context context;
11305 if (wback) {
11306 uint32_t value;
11307 if (add)
11308 value = Rn + imm32;
11309 else
11310 value = Rn - imm32;
11312 context.type = eContextAdjustBaseRegister;
11313 context.SetImmediateSigned(value - Rn);
11314 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
11315 value))
11316 return false;
11319 const uint32_t addr_byte_size = GetAddressByteSize();
11320 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
11322 context.type = eContextRegisterLoad;
11324 std::optional<RegisterInfo> base_reg =
11325 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
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, address - Rn);
11333 uint32_t data = MemARead(context, address, addr_byte_size, 0, &success);
11334 if (!success)
11335 return false;
11337 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF,
11338 start_reg + d + r, data))
11339 return false;
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, address - Rn);
11346 uint32_t word1 =
11347 MemARead(context, address, addr_byte_size, 0, &success);
11348 if (!success)
11349 return false;
11351 context.SetRegisterPlusOffset(*base_reg, (address + 4) - Rn);
11352 uint32_t word2 =
11353 MemARead(context, address + 4, addr_byte_size, 0, &success);
11354 if (!success)
11355 return false;
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;
11370 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF,
11371 start_reg + d + r, data))
11372 return false;
11376 return true;
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.
11383 bool 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
11401 bool success = false;
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;
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(opcode, 24) == Bit32(opcode, 23)) && BitIsSet(opcode, 21))
11420 return false;
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(opcode, 23);
11427 wback = BitIsSet(opcode, 21);
11429 // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:'00', 32);
11430 d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);
11431 n = Bits32(opcode, 19, 16);
11432 imm32 = Bits32(opcode, 7, 0) << 2;
11434 // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see 'FSTMX'.
11435 regs = Bits32(opcode, 7, 0) / 2;
11437 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then
11438 // UNPREDICTABLE;
11439 if ((n == 15) && (wback || (CurrentInstrSet() != eModeARM)))
11440 return false;
11442 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
11443 if ((regs == 0) || (regs > 16) || ((d + regs) > 32))
11444 return false;
11446 break;
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(opcode, 24) == Bit32(opcode, 23)) && BitIsSet(opcode, 21))
11455 return false;
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(opcode, 23);
11463 wback = BitIsSet(opcode, 21);
11464 d = (Bits32(opcode, 15, 12) << 1) | Bit32(opcode, 22);
11465 n = Bits32(opcode, 19, 16);
11467 // imm32 = ZeroExtend(imm8:'00', 32); regs = UInt(imm8);
11468 imm32 = Bits32(opcode, 7, 0) << 2;
11469 regs = Bits32(opcode, 7, 0);
11471 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then
11472 // UNPREDICTABLE;
11473 if ((n == 15) && (wback || (CurrentInstrSet() != eModeARM)))
11474 return false;
11476 // if regs == 0 || (d+regs) > 32 then UNPREDICTABLE;
11477 if ((regs == 0) || ((d + regs) > 32))
11478 return false;
11480 break;
11482 default:
11483 return false;
11486 std::optional<RegisterInfo> base_reg =
11487 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
11489 uint32_t Rn = ReadCoreReg(n, &success);
11490 if (!success)
11491 return false;
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;
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;
11509 context.type = eContextAdjustBaseRegister;
11510 context.SetRegisterPlusOffset(*base_reg, value - Rn);
11512 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
11513 value))
11514 return false;
11517 const uint32_t addr_byte_size = GetAddressByteSize();
11518 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
11520 context.type = eContextRegisterStore;
11521 // for r = 0 to regs-1
11522 for (uint32_t r = 0; r < regs; ++r) {
11524 if (single_regs) {
11525 // MemA[address,4] = S[d+r]; address = address+4;
11526 uint32_t data = ReadRegisterUnsigned(eRegisterKindDWARF,
11527 start_reg + d + r, 0, &success);
11528 if (!success)
11529 return false;
11531 std::optional<RegisterInfo> data_reg =
11532 GetRegisterInfo(eRegisterKindDWARF, start_reg + d + r);
11533 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg,
11534 address - Rn);
11535 if (!MemAWrite(context, address, data, addr_byte_size))
11536 return false;
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(eRegisterKindDWARF,
11546 start_reg + d + r, 0, &success);
11547 if (!success)
11548 return false;
11550 std::optional<RegisterInfo> data_reg =
11551 GetRegisterInfo(eRegisterKindDWARF, start_reg + d + r);
11553 if (GetByteOrder() == eByteOrderBig) {
11554 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg,
11555 address - Rn);
11556 if (!MemAWrite(context, address, Bits64(data, 63, 32),
11557 addr_byte_size))
11558 return false;
11560 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg,
11561 (address + 4) - Rn);
11562 if (!MemAWrite(context, address + 4, Bits64(data, 31, 0),
11563 addr_byte_size))
11564 return false;
11565 } else {
11566 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg,
11567 address - Rn);
11568 if (!MemAWrite(context, address, Bits64(data, 31, 0), addr_byte_size))
11569 return false;
11571 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg,
11572 (address + 4) - Rn);
11573 if (!MemAWrite(context, address + 4, Bits64(data, 63, 32),
11574 addr_byte_size))
11575 return false;
11577 // address = address+8;
11578 address = address + 8;
11582 return true;
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.
11588 bool 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
11604 bool success = false;
11606 if (ConditionPassed(opcode)) {
11607 bool single_reg;
11608 bool add;
11609 uint32_t imm32;
11610 uint32_t d;
11611 uint32_t n;
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(opcode, 23);
11620 imm32 = Bits32(opcode, 7, 0) << 2;
11622 // d = UInt(D:Vd); n = UInt(Rn);
11623 d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);
11624 n = Bits32(opcode, 19, 16);
11626 break;
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(opcode, 23);
11633 imm32 = Bits32(opcode, 7, 0) << 2;
11635 // d = UInt(Vd:D); n = UInt(Rn);
11636 d = (Bits32(opcode, 15, 12) << 1) | Bit32(opcode, 22);
11637 n = Bits32(opcode, 19, 16);
11639 break;
11641 default:
11642 return false;
11644 std::optional<RegisterInfo> base_reg =
11645 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
11647 uint32_t Rn = ReadCoreReg(n, &success);
11648 if (!success)
11649 return false;
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;
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;
11665 const uint32_t addr_byte_size = GetAddressByteSize();
11666 uint32_t start_reg = single_reg ? dwarf_s0 : dwarf_d0;
11668 EmulateInstruction::Context context;
11669 context.type = eContextRegisterLoad;
11670 context.SetRegisterPlusOffset(*base_reg, address - base);
11672 if (single_reg) {
11673 // S[d] = MemA[address,4];
11674 uint32_t data = MemARead(context, address, addr_byte_size, 0, &success);
11675 if (!success)
11676 return false;
11678 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, start_reg + d,
11679 data))
11680 return false;
11681 } else {
11682 // word1 = MemA[address,4]; word2 = MemA[address+4,4];
11683 uint32_t word1 = MemARead(context, address, addr_byte_size, 0, &success);
11684 if (!success)
11685 return false;
11687 context.SetRegisterPlusOffset(*base_reg, (address + 4) - base);
11688 uint32_t word2 =
11689 MemARead(context, address + 4, addr_byte_size, 0, &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;
11704 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, start_reg + d,
11705 data64))
11706 return false;
11709 return true;
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.
11715 bool 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
11730 bool success = false;
11732 if (ConditionPassed(opcode)) {
11733 bool single_reg;
11734 bool add;
11735 uint32_t imm32;
11736 uint32_t d;
11737 uint32_t n;
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(opcode, 23);
11746 imm32 = Bits32(opcode, 7, 0) << 2;
11748 // d = UInt(D:Vd); n = UInt(Rn);
11749 d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);
11750 n = Bits32(opcode, 19, 16);
11752 // if n == 15 && CurrentInstrSet() != InstrSet_ARM then UNPREDICTABLE;
11753 if ((n == 15) && (CurrentInstrSet() != eModeARM))
11754 return false;
11756 break;
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(opcode, 23);
11763 imm32 = Bits32(opcode, 7, 0) << 2;
11765 // d = UInt(Vd:D); n = UInt(Rn);
11766 d = (Bits32(opcode, 15, 12) << 1) | Bit32(opcode, 22);
11767 n = Bits32(opcode, 19, 16);
11769 // if n == 15 && CurrentInstrSet() != InstrSet_ARM then UNPREDICTABLE;
11770 if ((n == 15) && (CurrentInstrSet() != eModeARM))
11771 return false;
11773 break;
11775 default:
11776 return false;
11779 uint32_t Rn = ReadCoreReg(n, &success);
11780 if (!success)
11781 return false;
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;
11790 const uint32_t addr_byte_size = GetAddressByteSize();
11791 uint32_t start_reg = single_reg ? dwarf_s0 : dwarf_d0;
11793 std::optional<RegisterInfo> base_reg =
11794 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
11795 std::optional<RegisterInfo> data_reg =
11796 GetRegisterInfo(eRegisterKindDWARF, start_reg + d);
11797 EmulateInstruction::Context context;
11798 context.type = eContextRegisterStore;
11799 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, address - Rn);
11801 if (single_reg) {
11802 // MemA[address,4] = S[d];
11803 uint32_t data =
11804 ReadRegisterUnsigned(eRegisterKindDWARF, start_reg + d, 0, &success);
11805 if (!success)
11806 return false;
11808 if (!MemAWrite(context, address, data, 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(eRegisterKindDWARF, start_reg + d, 0, &success);
11817 if (!success)
11818 return false;
11820 if (GetByteOrder() == eByteOrderBig) {
11821 if (!MemAWrite(context, address, Bits64(data, 63, 32), addr_byte_size))
11822 return false;
11824 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg,
11825 (address + 4) - Rn);
11826 if (!MemAWrite(context, address + 4, Bits64(data, 31, 0),
11827 addr_byte_size))
11828 return false;
11829 } else {
11830 if (!MemAWrite(context, address, Bits64(data, 31, 0), addr_byte_size))
11831 return false;
11833 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg,
11834 (address + 4) - Rn);
11835 if (!MemAWrite(context, address + 4, Bits64(data, 63, 32),
11836 addr_byte_size))
11837 return false;
11841 return true;
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.
11847 bool 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
11860 bool success = false;
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;
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(opcode, 11, 8);
11889 uint32_t align = Bits32(opcode, 5, 4);
11890 if (type == 7) // '0111'
11892 regs = 1;
11893 if (BitIsSet(align, 1))
11894 return false;
11895 } else if (type == 10) // '1010'
11897 regs = 2;
11898 if (align == 3)
11899 return false;
11901 } else if (type == 6) // '0110'
11903 regs = 3;
11904 if (BitIsSet(align, 1))
11905 return false;
11906 } else if (type == 2) // '0010'
11908 regs = 4;
11909 } else
11910 return false;
11912 // alignment = if align == '00' then 1 else 4 << UInt(align);
11913 if (align == 0)
11914 alignment = 1;
11915 else
11916 alignment = 4 << align;
11918 // ebytes = 1 << UInt(size); esize = 8 * ebytes; elements = 8 DIV ebytes;
11919 ebytes = 1 << Bits32(opcode, 7, 6);
11920 esize = 8 * ebytes;
11921 elements = 8 / ebytes;
11923 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
11924 d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);
11925 n = Bits32(opcode, 19, 15);
11926 m = Bits32(opcode, 3, 0);
11928 // wback = (m != 15); register_index = (m != 15 && m != 13);
11929 wback = (m != 15);
11930 register_index = ((m != 15) && (m != 13));
11932 // if d+regs > 32 then UNPREDICTABLE;
11933 if ((d + regs) > 32)
11934 return false;
11935 } break;
11937 default:
11938 return false;
11941 std::optional<RegisterInfo> base_reg =
11942 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
11944 uint32_t Rn = ReadCoreReg(n, &success);
11945 if (!success)
11946 return false;
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;
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(m, &success);
11958 if (!success)
11959 return false;
11961 uint32_t offset;
11962 if (register_index)
11963 offset = Rm;
11964 else
11965 offset = 8 * regs;
11967 uint32_t value = Rn + offset;
11968 context.type = eContextAdjustBaseRegister;
11969 context.SetRegisterPlusOffset(*base_reg, offset);
11971 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
11972 value))
11973 return false;
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, address - Rn);
11984 uint64_t data = MemURead(context, address, ebytes, 0, &success);
11985 if (!success)
11986 return false;
11988 assembled_data =
11989 (data << (e * esize)) |
11990 assembled_data; // New data goes to the left of existing data
11992 // address = address + ebytes;
11993 address = address + ebytes;
11995 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_d0 + d + r,
11996 assembled_data))
11997 return false;
12000 return true;
12003 // A8.6.308 VLD1 (single element to one lane)
12005 bool 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
12015 bool success = false;
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;
12028 switch (encoding) {
12029 case eEncodingT1:
12030 case eEncodingA1: {
12031 uint32_t size = Bits32(opcode, 11, 10);
12032 uint32_t index_align = Bits32(opcode, 7, 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'
12039 // if index_align<0> != '0' then UNDEFINED;
12040 if (BitIsClear(index_align, 0))
12041 return false;
12043 // ebytes = 1; esize = 8; index = UInt(index_align<3:1>); alignment = 1;
12044 ebytes = 1;
12045 esize = 8;
12046 index = Bits32(index_align, 3, 1);
12047 alignment = 1;
12048 } else if (size == 1) // when '01'
12050 // if index_align<1> != '0' then UNDEFINED;
12051 if (BitIsClear(index_align, 1))
12052 return false;
12054 // ebytes = 2; esize = 16; index = UInt(index_align<3:2>);
12055 ebytes = 2;
12056 esize = 16;
12057 index = Bits32(index_align, 3, 2);
12059 // alignment = if index_align<0> == '0' then 1 else 2;
12060 if (BitIsClear(index_align, 0))
12061 alignment = 1;
12062 else
12063 alignment = 2;
12064 } else if (size == 2) // when '10'
12066 // if index_align<2> != '0' then UNDEFINED;
12067 if (BitIsClear(index_align, 2))
12068 return false;
12070 // if index_align<1:0> != '00' && index_align<1:0> != '11' then
12071 // UNDEFINED;
12072 if ((Bits32(index_align, 1, 0) != 0) &&
12073 (Bits32(index_align, 1, 0) != 3))
12074 return false;
12076 // ebytes = 4; esize = 32; index = UInt(index_align<3>);
12077 ebytes = 4;
12078 esize = 32;
12079 index = Bit32(index_align, 3);
12081 // alignment = if index_align<1:0> == '00' then 1 else 4;
12082 if (Bits32(index_align, 1, 0) == 0)
12083 alignment = 1;
12084 else
12085 alignment = 4;
12086 } else {
12087 return false;
12089 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
12090 d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);
12091 n = Bits32(opcode, 19, 16);
12092 m = Bits32(opcode, 3, 0);
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));
12099 if (n == 15)
12100 return false;
12102 } break;
12104 default:
12105 return false;
12108 uint32_t Rn = ReadCoreReg(n, &success);
12109 if (!success)
12110 return false;
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;
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(m, &success);
12122 if (!success)
12123 return false;
12125 uint32_t offset;
12126 if (register_index)
12127 offset = Rm;
12128 else
12129 offset = ebytes;
12131 uint32_t value = Rn + offset;
12133 context.type = eContextAdjustBaseRegister;
12134 std::optional<RegisterInfo> base_reg =
12135 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
12136 context.SetRegisterPlusOffset(*base_reg, offset);
12138 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
12139 value))
12140 return false;
12143 // Elem[D[d],index,esize] = MemU[address,ebytes];
12144 uint32_t element = MemURead(context, address, esize, 0, &success);
12145 if (!success)
12146 return false;
12148 element = element << (index * esize);
12150 uint64_t reg_data =
12151 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_d0 + d, 0, &success);
12152 if (!success)
12153 return false;
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(all_ones, (index * esize) - 1,
12162 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.
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.
12170 context.type = eContextRegisterLoad;
12171 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d,
12172 reg_data))
12173 return false;
12175 return true;
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.
12181 bool 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
12194 bool success = false;
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;
12208 switch (encoding) {
12209 case eEncodingT1:
12210 case eEncodingA1: {
12211 uint32_t type = Bits32(opcode, 11, 8);
12212 uint32_t align = Bits32(opcode, 5, 4);
12214 // case type of
12215 if (type == 7) // when '0111'
12217 // regs = 1; if align<1> == '1' then UNDEFINED;
12218 regs = 1;
12219 if (BitIsSet(align, 1))
12220 return false;
12221 } else if (type == 10) // when '1010'
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'
12229 // regs = 3; if align<1> == '1' then UNDEFINED;
12230 regs = 3;
12231 if (BitIsSet(align, 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;
12240 // alignment = if align == '00' then 1 else 4 << UInt(align);
12241 if (align == 0)
12242 alignment = 1;
12243 else
12244 alignment = 4 << align;
12246 // ebytes = 1 << UInt(size); esize = 8 * ebytes; elements = 8 DIV ebytes;
12247 ebytes = 1 << Bits32(opcode, 7, 6);
12248 esize = 8 * ebytes;
12249 elements = 8 / ebytes;
12251 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
12252 d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);
12253 n = Bits32(opcode, 19, 16);
12254 m = Bits32(opcode, 3, 0);
12256 // wback = (m != 15); register_index = (m != 15 && m != 13);
12257 wback = (m != 15);
12258 register_index = ((m != 15) && (m != 13));
12260 // if d+regs > 32 then UNPREDICTABLE; if n == 15 then UNPREDICTABLE;
12261 if ((d + regs) > 32)
12262 return false;
12264 if (n == 15)
12265 return false;
12267 } break;
12269 default:
12270 return false;
12273 std::optional<RegisterInfo> base_reg =
12274 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
12276 uint32_t Rn = ReadCoreReg(n, &success);
12277 if (!success)
12278 return false;
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;
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(m, &success);
12290 if (!success)
12291 return false;
12293 uint32_t offset;
12294 if (register_index)
12295 offset = Rm;
12296 else
12297 offset = 8 * regs;
12299 context.type = eContextAdjustBaseRegister;
12300 context.SetRegisterPlusOffset(*base_reg, offset);
12302 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
12303 Rn + offset))
12304 return false;
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(eRegisterKindDWARF, dwarf_d0 + d + r);
12312 uint64_t register_data = ReadRegisterUnsigned(
12313 eRegisterKindDWARF, dwarf_d0 + d + r, 0, &success);
12314 if (!success)
12315 return false;
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(register_data, ((e + 1) * esize) - 1, e * esize);
12322 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg,
12323 address - Rn);
12324 if (!MemUWrite(context, address, word, ebytes))
12325 return false;
12327 // address = address + ebytes;
12328 address = address + ebytes;
12332 return true;
12335 // A8.6.392 VST1 (single element from one lane) This instruction stores one
12336 // element to memory from one element of a register.
12337 bool 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
12347 bool success = false;
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;
12360 switch (encoding) {
12361 case eEncodingT1:
12362 case eEncodingA1: {
12363 uint32_t size = Bits32(opcode, 11, 10);
12364 uint32_t index_align = Bits32(opcode, 7, 4);
12366 // if size == '11' then UNDEFINED;
12367 if (size == 3)
12368 return false;
12370 // case size of
12371 if (size == 0) // when '00'
12373 // if index_align<0> != '0' then UNDEFINED;
12374 if (BitIsClear(index_align, 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(index_align, 3, 1);
12380 alignment = 1;
12381 } else if (size == 1) // when '01'
12383 // if index_align<1> != '0' then UNDEFINED;
12384 if (BitIsClear(index_align, 1))
12385 return false;
12387 // ebytes = 2; esize = 16; index = UInt(index_align<3:2>);
12388 ebytes = 2;
12389 esize = 16;
12390 index = Bits32(index_align, 3, 2);
12392 // alignment = if index_align<0> == '0' then 1 else 2;
12393 if (BitIsClear(index_align, 0))
12394 alignment = 1;
12395 else
12396 alignment = 2;
12397 } else if (size == 2) // when '10'
12399 // if index_align<2> != '0' then UNDEFINED;
12400 if (BitIsClear(index_align, 2))
12401 return false;
12403 // if index_align<1:0> != '00' && index_align<1:0> != '11' then
12404 // UNDEFINED;
12405 if ((Bits32(index_align, 1, 0) != 0) &&
12406 (Bits32(index_align, 1, 0) != 3))
12407 return false;
12409 // ebytes = 4; esize = 32; index = UInt(index_align<3>);
12410 ebytes = 4;
12411 esize = 32;
12412 index = Bit32(index_align, 3);
12414 // alignment = if index_align<1:0> == '00' then 1 else 4;
12415 if (Bits32(index_align, 1, 0) == 0)
12416 alignment = 1;
12417 else
12418 alignment = 4;
12419 } else {
12420 return false;
12422 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
12423 d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);
12424 n = Bits32(opcode, 19, 16);
12425 m = Bits32(opcode, 3, 0);
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));
12432 if (n == 15)
12433 return false;
12434 } break;
12436 default:
12437 return false;
12440 std::optional<RegisterInfo> base_reg =
12441 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
12443 uint32_t Rn = ReadCoreReg(n, &success);
12444 if (!success)
12445 return false;
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;
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(m, &success);
12457 if (!success)
12458 return false;
12460 uint32_t offset;
12461 if (register_index)
12462 offset = Rm;
12463 else
12464 offset = ebytes;
12466 context.type = eContextAdjustBaseRegister;
12467 context.SetRegisterPlusOffset(*base_reg, offset);
12469 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
12470 Rn + offset))
12471 return false;
12474 // MemU[address,ebytes] = Elem[D[d],index,esize];
12475 uint64_t register_data =
12476 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_d0 + d, 0, &success);
12477 if (!success)
12478 return false;
12480 uint64_t word =
12481 Bits64(register_data, ((index + 1) * esize) - 1, index * esize);
12483 std::optional<RegisterInfo> data_reg =
12484 GetRegisterInfo(eRegisterKindDWARF, dwarf_d0 + d);
12485 context.type = eContextRegisterStore;
12486 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, address - Rn);
12488 if (!MemUWrite(context, address, word, ebytes))
12489 return false;
12491 return true;
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.
12496 bool 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
12508 bool success = false;
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;
12521 switch (encoding) {
12522 case eEncodingT1:
12523 case eEncodingA1: {
12524 // if size == '11' || (size == '00' && a == '1') then UNDEFINED;
12525 uint32_t size = Bits32(opcode, 7, 6);
12526 if ((size == 3) || ((size == 0) && BitIsSet(opcode, 4)))
12527 return false;
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(opcode, 5))
12534 regs = 1;
12535 else
12536 regs = 2;
12538 // alignment = if a == '0' then 1 else ebytes;
12539 if (BitIsClear(opcode, 4))
12540 alignment = 1;
12541 else
12542 alignment = ebytes;
12544 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
12545 d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);
12546 n = Bits32(opcode, 19, 16);
12547 m = Bits32(opcode, 3, 0);
12549 // wback = (m != 15); register_index = (m != 15 && m != 13);
12550 wback = (m != 15);
12551 register_index = ((m != 15) && (m != 13));
12553 // if d+regs > 32 then UNPREDICTABLE; if n == 15 then UNPREDICTABLE;
12554 if ((d + regs) > 32)
12555 return false;
12557 if (n == 15)
12558 return false;
12559 } break;
12561 default:
12562 return false;
12565 uint32_t Rn = ReadCoreReg(n, &success);
12566 if (!success)
12567 return false;
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;
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(m, &success);
12579 if (!success)
12580 return false;
12582 uint32_t offset;
12583 if (register_index)
12584 offset = Rm;
12585 else
12586 offset = ebytes;
12588 context.type = eContextAdjustBaseRegister;
12589 std::optional<RegisterInfo> base_reg =
12590 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);
12591 context.SetRegisterPlusOffset(*base_reg, offset);
12593 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,
12594 Rn + offset))
12595 return false;
12598 // replicated_element = Replicate(MemU[address,ebytes], elements);
12600 context.type = eContextRegisterLoad;
12601 uint64_t word = MemURead(context, address, ebytes, 0, &success);
12602 if (!success)
12603 return false;
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(word, esize - 1, 0);
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, eRegisterKindDWARF, dwarf_d0 + d + r,
12615 replicated_element))
12616 return false;
12619 return true;
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.
12626 bool 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
12651 bool success = false;
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;
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(opcode, 7, 0);
12669 register_form = false;
12670 code = 2;
12672 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
12673 if (InITBlock() && !LastInITBlock())
12674 return false;
12676 break;
12678 case eEncodingA1:
12679 // n = UInt(Rn); imm32 = ARMExpandImm(imm12); register_form = FALSE;
12680 n = Bits32(opcode, 19, 16);
12681 imm32 = ARMExpandImm(opcode);
12682 register_form = false;
12683 code = Bits32(opcode, 24, 21);
12685 break;
12687 case eEncodingA2:
12688 // n = UInt(Rn); m = UInt(Rm); register_form = TRUE;
12689 n = Bits32(opcode, 19, 16);
12690 m = Bits32(opcode, 3, 0);
12691 register_form = true;
12693 // (shift_t, shift_n) = DecodeImmShift(type, imm5);
12694 shift_n = DecodeImmShiftARM(opcode, shift_t);
12696 break;
12698 default:
12699 return false;
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(m, &success);
12707 if (!success)
12708 return false;
12710 operand2 = Shift(Rm, shift_t, shift_n, APSR_C, &success);
12711 if (!success)
12712 return false;
12713 } else {
12714 operand2 = imm32;
12717 uint32_t Rn = ReadCoreReg(n, &success);
12718 if (!success)
12719 return false;
12721 AddWithCarryResult result;
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;
12730 case 1: // when '0001'
12731 // result = R[n] EOR operand2; // EOR
12732 result.result = Rn ^ operand2;
12733 break;
12735 case 2: // when '0010'
12736 // (result, -, -) = AddWithCarry(R[n], NOT(operand2), '1'); // SUB
12737 result = AddWithCarry(Rn, ~(operand2), 1);
12738 break;
12740 case 3: // when '0011'
12741 // (result, -, -) = AddWithCarry(NOT(R[n]), operand2, '1'); // RSB
12742 result = AddWithCarry(~(Rn), operand2, 1);
12743 break;
12745 case 4: // when '0100'
12746 // (result, -, -) = AddWithCarry(R[n], operand2, '0'); // ADD
12747 result = AddWithCarry(Rn, operand2, 0);
12748 break;
12750 case 5: // when '0101'
12751 // (result, -, -) = AddWithCarry(R[n], operand2, APSR.c); // ADC
12752 result = AddWithCarry(Rn, operand2, APSR_C);
12753 break;
12755 case 6: // when '0110'
12756 // (result, -, -) = AddWithCarry(R[n], NOT(operand2), APSR.C); // SBC
12757 result = AddWithCarry(Rn, ~(operand2), APSR_C);
12758 break;
12760 case 7: // when '0111'
12761 // (result, -, -) = AddWithCarry(NOT(R[n]), operand2, APSR.C); // RSC
12762 result = AddWithCarry(~(Rn), operand2, APSR_C);
12763 break;
12765 case 10: // when '1100'
12766 // result = R[n] OR operand2; // ORR
12767 result.result = Rn | operand2;
12768 break;
12770 case 11: // when '1101'
12771 // result = operand2; // MOV
12772 result.result = operand2;
12773 break;
12775 case 12: // when '1110'
12776 // result = R[n] AND NOT(operand2); // BIC
12777 result.result = Rn & ~(operand2);
12778 break;
12780 case 15: // when '1111'
12781 // result = NOT(operand2); // MVN
12782 result.result = ~(operand2);
12783 break;
12785 default:
12786 return false;
12788 // CPSRWriteByInstr(SPSR[], '1111', TRUE);
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(eRegisterKindDWARF, dwarf_cpsr, 0, &success);
12794 if (!success)
12795 return false;
12797 CPSRWriteByInstr(spsr, 15, true);
12799 // BranchWritePC(result);
12800 EmulateInstruction::Context context;
12801 context.type = eContextAdjustPC;
12802 context.SetImmediate(result.result);
12804 BranchWritePC(context, result.result);
12806 return true;
12809 EmulateInstructionARM::ARMOpcode *
12810 EmulateInstructionARM::GetARMOpcodeForInstruction(const uint32_t opcode,
12811 uint32_t arm_isa) {
12812 static ARMOpcode g_arm_opcodes[] = {
12813 // Prologue instructions
12815 // push register(s)
12816 {0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12817 &EmulateInstructionARM::EmulatePUSH, "push <registers>"},
12818 {0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, No_VFP, eSize32,
12819 &EmulateInstructionARM::EmulatePUSH, "push <register>"},
12821 // set r7 to point to a stack offset
12822 {0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12823 &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #<const>"},
12824 {0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12825 &EmulateInstructionARM::EmulateSUBR7IPImm, "sub r7, ip, #<const>"},
12826 // copy the stack pointer to ip
12827 {0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, No_VFP, eSize32,
12828 &EmulateInstructionARM::EmulateMOVRdSP, "mov ip, sp"},
12829 {0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12830 &EmulateInstructionARM::EmulateADDRdSPImm, "add ip, sp, #<const>"},
12831 {0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12832 &EmulateInstructionARM::EmulateSUBIPSPImm, "sub ip, sp, #<const>"},
12834 // adjust the stack pointer
12835 {0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12836 &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #<const>"},
12837 {0x0fef0010, 0x004d0000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12838 &EmulateInstructionARM::EmulateSUBSPReg,
12839 "sub{s}<c> <Rd>, sp, <Rm>{,<shift>}"},
12841 // push one register
12842 // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH;
12843 {0x0e5f0000, 0x040d0000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12844 &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!"},
12846 // vector push consecutive extension register(s)
12847 {0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, No_VFP, eSize32,
12848 &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
12849 {0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32,
12850 &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
12852 // Epilogue instructions
12854 {0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12855 &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
12856 {0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, No_VFP, eSize32,
12857 &EmulateInstructionARM::EmulatePOP, "pop <register>"},
12858 {0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, No_VFP, eSize32,
12859 &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
12860 {0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32,
12861 &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
12863 // Supervisor Call (previously Software Interrupt)
12864 {0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12865 &EmulateInstructionARM::EmulateSVC, "svc #imm24"},
12867 // Branch instructions
12868 // To resolve ambiguity, "blx <label>" should come before "b #imm24" and
12869 // "bl <label>".
12870 {0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, No_VFP, eSize32,
12871 &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
12872 {0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12873 &EmulateInstructionARM::EmulateB, "b #imm24"},
12874 {0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12875 &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
12876 {0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, No_VFP, eSize32,
12877 &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
12878 // for example, "bx lr"
12879 {0x0ffffff0, 0x012fff10, ARMvAll, eEncodingA1, No_VFP, eSize32,
12880 &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
12881 // bxj
12882 {0x0ffffff0, 0x012fff20, ARMvAll, eEncodingA1, No_VFP, eSize32,
12883 &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},
12885 // Data-processing instructions
12886 // adc (immediate)
12887 {0x0fe00000, 0x02a00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12888 &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #const"},
12889 // adc (register)
12890 {0x0fe00010, 0x00a00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12891 &EmulateInstructionARM::EmulateADCReg,
12892 "adc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12893 // add (immediate)
12894 {0x0fe00000, 0x02800000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12895 &EmulateInstructionARM::EmulateADDImmARM,
12896 "add{s}<c> <Rd>, <Rn>, #const"},
12897 // add (register)
12898 {0x0fe00010, 0x00800000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12899 &EmulateInstructionARM::EmulateADDReg,
12900 "add{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12901 // add (register-shifted register)
12902 {0x0fe00090, 0x00800010, ARMvAll, eEncodingA1, No_VFP, eSize32,
12903 &EmulateInstructionARM::EmulateADDRegShift,
12904 "add{s}<c> <Rd>, <Rn>, <Rm>, <type> <RS>"},
12905 // adr
12906 {0x0fff0000, 0x028f0000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12907 &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
12908 {0x0fff0000, 0x024f0000, ARMvAll, eEncodingA2, No_VFP, eSize32,
12909 &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
12910 // and (immediate)
12911 {0x0fe00000, 0x02000000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12912 &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #const"},
12913 // and (register)
12914 {0x0fe00010, 0x00000000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12915 &EmulateInstructionARM::EmulateANDReg,
12916 "and{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12917 // bic (immediate)
12918 {0x0fe00000, 0x03c00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12919 &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #const"},
12920 // bic (register)
12921 {0x0fe00010, 0x01c00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12922 &EmulateInstructionARM::EmulateBICReg,
12923 "bic{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12924 // eor (immediate)
12925 {0x0fe00000, 0x02200000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12926 &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #const"},
12927 // eor (register)
12928 {0x0fe00010, 0x00200000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12929 &EmulateInstructionARM::EmulateEORReg,
12930 "eor{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12931 // orr (immediate)
12932 {0x0fe00000, 0x03800000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12933 &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #const"},
12934 // orr (register)
12935 {0x0fe00010, 0x01800000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12936 &EmulateInstructionARM::EmulateORRReg,
12937 "orr{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12938 // rsb (immediate)
12939 {0x0fe00000, 0x02600000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12940 &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c> <Rd>, <Rn>, #<const>"},
12941 // rsb (register)
12942 {0x0fe00010, 0x00600000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12943 &EmulateInstructionARM::EmulateRSBReg,
12944 "rsb{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12945 // rsc (immediate)
12946 {0x0fe00000, 0x02e00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12947 &EmulateInstructionARM::EmulateRSCImm, "rsc{s}<c> <Rd>, <Rn>, #<const>"},
12948 // rsc (register)
12949 {0x0fe00010, 0x00e00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12950 &EmulateInstructionARM::EmulateRSCReg,
12951 "rsc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12952 // sbc (immediate)
12953 {0x0fe00000, 0x02c00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12954 &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
12955 // sbc (register)
12956 {0x0fe00010, 0x00c00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12957 &EmulateInstructionARM::EmulateSBCReg,
12958 "sbc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
12959 // sub (immediate, ARM)
12960 {0x0fe00000, 0x02400000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12961 &EmulateInstructionARM::EmulateSUBImmARM,
12962 "sub{s}<c> <Rd>, <Rn>, #<const>"},
12963 // sub (sp minus immediate)
12964 {0x0fef0000, 0x024d0000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12965 &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}<c> <Rd>, sp, #<const>"},
12966 // sub (register)
12967 {0x0fe00010, 0x00400000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12968 &EmulateInstructionARM::EmulateSUBReg,
12969 "sub{s}<c> <Rd>, <Rn>, <Rm>{,<shift>}"},
12970 // teq (immediate)
12971 {0x0ff0f000, 0x03300000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12972 &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #const"},
12973 // teq (register)
12974 {0x0ff0f010, 0x01300000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12975 &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
12976 // tst (immediate)
12977 {0x0ff0f000, 0x03100000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12978 &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #const"},
12979 // tst (register)
12980 {0x0ff0f010, 0x01100000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12981 &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rn>, <Rm> {,<shift>}"},
12983 // mov (immediate)
12984 {0x0fef0000, 0x03a00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12985 &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c> <Rd>, #<const>"},
12986 {0x0ff00000, 0x03000000, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32,
12987 &EmulateInstructionARM::EmulateMOVRdImm, "movw<c> <Rd>, #<imm16>"},
12988 // mov (register)
12989 {0x0fef0ff0, 0x01a00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12990 &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c> <Rd>, <Rm>"},
12991 // mvn (immediate)
12992 {0x0fef0000, 0x03e00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12993 &EmulateInstructionARM::EmulateMVNImm, "mvn{s}<c> <Rd>, #<const>"},
12994 // mvn (register)
12995 {0x0fef0010, 0x01e00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
12996 &EmulateInstructionARM::EmulateMVNReg,
12997 "mvn{s}<c> <Rd>, <Rm> {,<shift>}"},
12998 // cmn (immediate)
12999 {0x0ff0f000, 0x03700000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13000 &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
13001 // cmn (register)
13002 {0x0ff0f010, 0x01700000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13003 &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
13004 // cmp (immediate)
13005 {0x0ff0f000, 0x03500000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13006 &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #<const>"},
13007 // cmp (register)
13008 {0x0ff0f010, 0x01500000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13009 &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm> {,<shift>}"},
13010 // asr (immediate)
13011 {0x0fef0070, 0x01a00040, ARMvAll, eEncodingA1, No_VFP, eSize32,
13012 &EmulateInstructionARM::EmulateASRImm, "asr{s}<c> <Rd>, <Rm>, #imm"},
13013 // asr (register)
13014 {0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, No_VFP, eSize32,
13015 &EmulateInstructionARM::EmulateASRReg, "asr{s}<c> <Rd>, <Rn>, <Rm>"},
13016 // lsl (immediate)
13017 {0x0fef0070, 0x01a00000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13018 &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c> <Rd>, <Rm>, #imm"},
13019 // lsl (register)
13020 {0x0fef00f0, 0x01a00010, ARMvAll, eEncodingA1, No_VFP, eSize32,
13021 &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c> <Rd>, <Rn>, <Rm>"},
13022 // lsr (immediate)
13023 {0x0fef0070, 0x01a00020, ARMvAll, eEncodingA1, No_VFP, eSize32,
13024 &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c> <Rd>, <Rm>, #imm"},
13025 // lsr (register)
13026 {0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, No_VFP, eSize32,
13027 &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c> <Rd>, <Rn>, <Rm>"},
13028 // rrx is a special case encoding of ror (immediate)
13029 {0x0fef0ff0, 0x01a00060, ARMvAll, eEncodingA1, No_VFP, eSize32,
13030 &EmulateInstructionARM::EmulateRRX, "rrx{s}<c> <Rd>, <Rm>"},
13031 // ror (immediate)
13032 {0x0fef0070, 0x01a00060, ARMvAll, eEncodingA1, No_VFP, eSize32,
13033 &EmulateInstructionARM::EmulateRORImm, "ror{s}<c> <Rd>, <Rm>, #imm"},
13034 // ror (register)
13035 {0x0fef00f0, 0x01a00070, ARMvAll, eEncodingA1, No_VFP, eSize32,
13036 &EmulateInstructionARM::EmulateRORReg, "ror{s}<c> <Rd>, <Rn>, <Rm>"},
13037 // mul
13038 {0x0fe000f0, 0x00000090, ARMvAll, eEncodingA1, No_VFP, eSize32,
13039 &EmulateInstructionARM::EmulateMUL, "mul{s}<c> <Rd>,<R>,<Rm>"},
13041 // subs pc, lr and related instructions
13042 {0x0e10f000, 0x0210f000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13043 &EmulateInstructionARM::EmulateSUBSPcLrEtc,
13044 "<opc>S<c> PC,#<const> | <Rn>,#<const>"},
13045 {0x0e10f010, 0x0010f000, ARMvAll, eEncodingA2, No_VFP, eSize32,
13046 &EmulateInstructionARM::EmulateSUBSPcLrEtc,
13047 "<opc>S<c> PC,<Rn>,<Rm{,<shift>}"},
13049 // Load instructions
13050 {0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13051 &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>"},
13052 {0x0fd00000, 0x08100000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13053 &EmulateInstructionARM::EmulateLDMDA, "ldmda<c> <Rn>{!} <registers>"},
13054 {0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13055 &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>"},
13056 {0x0fd00000, 0x09900000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13057 &EmulateInstructionARM::EmulateLDMIB, "ldmib<c> <Rn<{!} <registers>"},
13058 {0x0e500000, 0x04100000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13059 &EmulateInstructionARM::EmulateLDRImmediateARM,
13060 "ldr<c> <Rt> [<Rn> {#+/-<imm12>}]"},
13061 {0x0e500010, 0x06100000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13062 &EmulateInstructionARM::EmulateLDRRegister,
13063 "ldr<c> <Rt> [<Rn> +/-<Rm> {<shift>}] {!}"},
13064 {0x0e5f0000, 0x045f0000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13065 &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>, [...]"},
13066 {0xfe500010, 0x06500000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13067 &EmulateInstructionARM::EmulateLDRBRegister,
13068 "ldrb<c> <Rt>, [<Rn>,+/-<Rm>{, <shift>}]{!}"},
13069 {0x0e5f00f0, 0x005f00b0, ARMvAll, eEncodingA1, No_VFP, eSize32,
13070 &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>"},
13071 {0x0e5000f0, 0x001000b0, ARMvAll, eEncodingA1, No_VFP, eSize32,
13072 &EmulateInstructionARM::EmulateLDRHRegister,
13073 "ldrh<c> <Rt>,[<Rn>,+/-<Rm>]{!}"},
13074 {0x0e5000f0, 0x005000d0, ARMvAll, eEncodingA1, No_VFP, eSize32,
13075 &EmulateInstructionARM::EmulateLDRSBImmediate,
13076 "ldrsb<c> <Rt>, [<Rn>{,#+/-<imm8>}]"},
13077 {0x0e5f00f0, 0x005f00d0, ARMvAll, eEncodingA1, No_VFP, eSize32,
13078 &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt> <label>"},
13079 {0x0e5000f0, 0x001000d0, ARMvAll, eEncodingA1, No_VFP, eSize32,
13080 &EmulateInstructionARM::EmulateLDRSBRegister,
13081 "ldrsb<c> <Rt>,[<Rn>,+/-<Rm>]{!}"},
13082 {0x0e5000f0, 0x005000f0, ARMvAll, eEncodingA1, No_VFP, eSize32,
13083 &EmulateInstructionARM::EmulateLDRSHImmediate,
13084 "ldrsh<c> <Rt>,[<Rn>{,#+/-<imm8>}]"},
13085 {0x0e5f00f0, 0x005f00f0, ARMvAll, eEncodingA1, No_VFP, eSize32,
13086 &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>"},
13087 {0x0e5000f0, 0x001000f0, ARMvAll, eEncodingA1, No_VFP, eSize32,
13088 &EmulateInstructionARM::EmulateLDRSHRegister,
13089 "ldrsh<c> <Rt>,[<Rn>,+/-<Rm>]{!}"},
13090 {0x0e5000f0, 0x004000d0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32,
13091 &EmulateInstructionARM::EmulateLDRDImmediate,
13092 "ldrd<c> <Rt>, <Rt2>, [<Rn>,#+/-<imm8>]!"},
13093 {0x0e500ff0, 0x000000d0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32,
13094 &EmulateInstructionARM::EmulateLDRDRegister,
13095 "ldrd<c> <Rt>, <Rt2>, [<Rn>, +/-<Rm>]{!}"},
13096 {0x0e100f00, 0x0c100b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32,
13097 &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},
13098 {0x0e100f00, 0x0c100a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32,
13099 &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},
13100 {0x0f300f00, 0x0d100b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32,
13101 &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},
13102 {0x0f300f00, 0x0d100a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32,
13103 &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Sd>, [<Rn>{,#+/-<imm>}]"},
13104 {0xffb00000, 0xf4200000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32,
13105 &EmulateInstructionARM::EmulateVLD1Multiple,
13106 "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
13107 {0xffb00300, 0xf4a00000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32,
13108 &EmulateInstructionARM::EmulateVLD1Single,
13109 "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
13110 {0xffb00f00, 0xf4a00c00, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32,
13111 &EmulateInstructionARM::EmulateVLD1SingleAll,
13112 "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
13114 // Store instructions
13115 {0x0fd00000, 0x08800000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13116 &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>"},
13117 {0x0fd00000, 0x08000000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13118 &EmulateInstructionARM::EmulateSTMDA, "stmda<c> <Rn>{!} <registers>"},
13119 {0x0fd00000, 0x09000000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13120 &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>"},
13121 {0x0fd00000, 0x09800000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13122 &EmulateInstructionARM::EmulateSTMIB, "stmib<c> <Rn>{!} <registers>"},
13123 {0x0e500010, 0x06000000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13124 &EmulateInstructionARM::EmulateSTRRegister,
13125 "str<c> <Rt> [<Rn> +/-<Rm> {<shift>}]{!}"},
13126 {0x0e5000f0, 0x000000b0, ARMvAll, eEncodingA1, No_VFP, eSize32,
13127 &EmulateInstructionARM::EmulateSTRHRegister,
13128 "strh<c> <Rt>,[<Rn>,+/-<Rm>[{!}"},
13129 {0x0ff00ff0, 0x01800f90, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32,
13130 &EmulateInstructionARM::EmulateSTREX, "strex<c> <Rd>, <Rt>, [<Rn>]"},
13131 {0x0e500000, 0x04400000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13132 &EmulateInstructionARM::EmulateSTRBImmARM,
13133 "strb<c> <Rt>,[<Rn>,#+/-<imm12>]!"},
13134 {0x0e500000, 0x04000000, ARMvAll, eEncodingA1, No_VFP, eSize32,
13135 &EmulateInstructionARM::EmulateSTRImmARM,
13136 "str<c> <Rt>,[<Rn>,#+/-<imm12>]!"},
13137 {0x0e5000f0, 0x004000f0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32,
13138 &EmulateInstructionARM::EmulateSTRDImm,
13139 "strd<c> <Rt>, <Rt2>, [<Rn> #+/-<imm8>]!"},
13140 {0x0e500ff0, 0x000000f0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32,
13141 &EmulateInstructionARM::EmulateSTRDReg,
13142 "strd<c> <Rt>, <Rt2>, [<Rn>, +/-<Rm>]{!}"},
13143 {0x0e100f00, 0x0c000b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32,
13144 &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!} <list>"},
13145 {0x0e100f00, 0x0c000a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32,
13146 &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!} <list>"},
13147 {0x0f300f00, 0x0d000b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32,
13148 &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Dd> [<Rn>{,#+/-<imm>}]"},
13149 {0x0f300f00, 0x0d000a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32,
13150 &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Sd> [<Rn>{,#+/-<imm>}]"},
13151 {0xffb00000, 0xf4000000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32,
13152 &EmulateInstructionARM::EmulateVST1Multiple,
13153 "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
13154 {0xffb00300, 0xf4800000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32,
13155 &EmulateInstructionARM::EmulateVST1Single,
13156 "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
13158 // Other instructions
13159 {0x0fff00f0, 0x06af00f0, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32,
13160 &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>{,<rotation>}"},
13161 {0x0fff00f0, 0x06bf0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32,
13162 &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>{,<rotation>}"},
13163 {0x0fff00f0, 0x06ef0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32,
13164 &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>{,<rotation>}"},
13165 {0x0fff00f0, 0x06ff0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32,
13166 &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>{,<rotation>}"},
13167 {0xfe500000, 0xf8100000, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32,
13168 &EmulateInstructionARM::EmulateRFE, "rfe{<amode>} <Rn>{!}"}
13171 static const size_t k_num_arm_opcodes = std::size(g_arm_opcodes);
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];
13178 return nullptr;
13181 EmulateInstructionARM::ARMOpcode *
13182 EmulateInstructionARM::GetThumbOpcodeForInstruction(const uint32_t opcode,
13183 uint32_t arm_isa) {
13185 static ARMOpcode g_thumb_opcodes[] = {
13186 // Prologue instructions
13188 // push register(s)
13189 {0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, No_VFP, eSize16,
13190 &EmulateInstructionARM::EmulatePUSH, "push <registers>"},
13191 {0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13192 &EmulateInstructionARM::EmulatePUSH, "push.w <registers>"},
13193 {0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13194 &EmulateInstructionARM::EmulatePUSH, "push.w <register>"},
13196 // set r7 to point to a stack offset
13197 {0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, No_VFP, eSize16,
13198 &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #imm"},
13199 // copy the stack pointer to r7
13200 {0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, No_VFP, eSize16,
13201 &EmulateInstructionARM::EmulateMOVRdSP, "mov r7, sp"},
13202 // move from high register to low register (comes after "mov r7, sp" to
13203 // resolve ambiguity)
13204 {0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, No_VFP, eSize16,
13205 &EmulateInstructionARM::EmulateMOVLowHigh, "mov r0-r7, r8-r15"},
13207 // PC-relative load into register (see also EmulateADDSPRm)
13208 {0xfffff800, 0x00004800, ARMvAll, eEncodingT1, No_VFP, eSize16,
13209 &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr <Rt>, [PC, #imm]"},
13211 // adjust the stack pointer
13212 {0xffffff87, 0x00004485, ARMvAll, eEncodingT2, No_VFP, eSize16,
13213 &EmulateInstructionARM::EmulateADDSPRm, "add sp, <Rm>"},
13214 {0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, No_VFP, eSize16,
13215 &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #imm"},
13216 {0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13217 &EmulateInstructionARM::EmulateSUBSPImm, "sub.w sp, sp, #<const>"},
13218 {0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13219 &EmulateInstructionARM::EmulateSUBSPImm, "subw sp, sp, #imm12"},
13220 {0xffef8000, 0xebad0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13221 &EmulateInstructionARM::EmulateSUBSPReg,
13222 "sub{s}<c> <Rd>, sp, <Rm>{,<shift>}"},
13224 // vector push consecutive extension register(s)
13225 {0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13226 &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
13227 {0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13228 &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
13230 // Epilogue instructions
13232 {0xfffff800, 0x0000a800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13233 &EmulateInstructionARM::EmulateADDSPImm, "add<c> <Rd>, sp, #imm"},
13234 {0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, No_VFP, eSize16,
13235 &EmulateInstructionARM::EmulateADDSPImm, "add sp, #imm"},
13236 {0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, No_VFP, eSize16,
13237 &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
13238 {0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13239 &EmulateInstructionARM::EmulatePOP, "pop.w <registers>"},
13240 {0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13241 &EmulateInstructionARM::EmulatePOP, "pop.w <register>"},
13242 {0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13243 &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
13244 {0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13245 &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
13247 // Supervisor Call (previously Software Interrupt)
13248 {0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, No_VFP, eSize16,
13249 &EmulateInstructionARM::EmulateSVC, "svc #imm8"},
13251 // If Then makes up to four following instructions conditional.
13252 // The next 5 opcode _must_ come before the if then instruction
13253 {0xffffffff, 0x0000bf00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16,
13254 &EmulateInstructionARM::EmulateNop, "nop"},
13255 {0xffffffff, 0x0000bf10, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16,
13256 &EmulateInstructionARM::EmulateNop, "nop YIELD (yield hint)"},
13257 {0xffffffff, 0x0000bf20, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16,
13258 &EmulateInstructionARM::EmulateNop, "nop WFE (wait for event hint)"},
13259 {0xffffffff, 0x0000bf30, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16,
13260 &EmulateInstructionARM::EmulateNop, "nop WFI (wait for interrupt hint)"},
13261 {0xffffffff, 0x0000bf40, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16,
13262 &EmulateInstructionARM::EmulateNop, "nop SEV (send event hint)"},
13263 {0xffffff00, 0x0000bf00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16,
13264 &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"},
13266 // Branch instructions
13267 // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8".
13268 {0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, No_VFP, eSize16,
13269 &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"},
13270 {0xfffff800, 0x0000e000, ARMvAll, eEncodingT2, No_VFP, eSize16,
13271 &EmulateInstructionARM::EmulateB, "b<c> #imm11 (outside or last in IT)"},
13272 {0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13273 &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"},
13274 {0xf800d000, 0xf0009000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32,
13275 &EmulateInstructionARM::EmulateB,
13276 "b<c>.w #imm8 (outside or last in IT)"},
13277 // J1 == J2 == 1
13278 {0xf800d000, 0xf000d000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize32,
13279 &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
13280 // J1 == J2 == 1
13281 {0xf800d001, 0xf000c000, ARMV5_ABOVE, eEncodingT2, No_VFP, eSize32,
13282 &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
13283 {0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, No_VFP, eSize16,
13284 &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
13285 // for example, "bx lr"
13286 {0xffffff87, 0x00004700, ARMvAll, eEncodingT1, No_VFP, eSize32,
13287 &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
13288 // bxj
13289 {0xfff0ffff, 0xf3c08f00, ARMV5J_ABOVE, eEncodingT1, No_VFP, eSize32,
13290 &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},
13291 // compare and branch
13292 {0xfffff500, 0x0000b100, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16,
13293 &EmulateInstructionARM::EmulateCB, "cb{n}z <Rn>, <label>"},
13294 // table branch byte
13295 {0xfff0fff0, 0xe8d0f000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13296 &EmulateInstructionARM::EmulateTB, "tbb<c> <Rn>, <Rm>"},
13297 // table branch halfword
13298 {0xfff0fff0, 0xe8d0f010, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13299 &EmulateInstructionARM::EmulateTB, "tbh<c> <Rn>, <Rm>, lsl #1"},
13301 // Data-processing instructions
13302 // adc (immediate)
13303 {0xfbe08000, 0xf1400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13304 &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #<const>"},
13305 // adc (register)
13306 {0xffffffc0, 0x00004140, ARMvAll, eEncodingT1, No_VFP, eSize16,
13307 &EmulateInstructionARM::EmulateADCReg, "adcs|adc<c> <Rdn>, <Rm>"},
13308 {0xffe08000, 0xeb400000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13309 &EmulateInstructionARM::EmulateADCReg,
13310 "adc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
13311 // add (register)
13312 {0xfffffe00, 0x00001800, ARMvAll, eEncodingT1, No_VFP, eSize16,
13313 &EmulateInstructionARM::EmulateADDReg, "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 {0xffffff00, 0x00004400, ARMvAll, eEncodingT2, No_VFP, eSize16,
13317 &EmulateInstructionARM::EmulateADDReg, "add<c> <Rdn>, <Rm>"},
13318 // adr
13319 {0xfffff800, 0x0000a000, ARMvAll, eEncodingT1, No_VFP, eSize16,
13320 &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
13321 {0xfbff8000, 0xf2af0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13322 &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
13323 {0xfbff8000, 0xf20f0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13324 &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
13325 // and (immediate)
13326 {0xfbe08000, 0xf0000000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13327 &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #<const>"},
13328 // and (register)
13329 {0xffffffc0, 0x00004000, ARMvAll, eEncodingT1, No_VFP, eSize16,
13330 &EmulateInstructionARM::EmulateANDReg, "ands|and<c> <Rdn>, <Rm>"},
13331 {0xffe08000, 0xea000000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13332 &EmulateInstructionARM::EmulateANDReg,
13333 "and{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
13334 // bic (immediate)
13335 {0xfbe08000, 0xf0200000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13336 &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #<const>"},
13337 // bic (register)
13338 {0xffffffc0, 0x00004380, ARMvAll, eEncodingT1, No_VFP, eSize16,
13339 &EmulateInstructionARM::EmulateBICReg, "bics|bic<c> <Rdn>, <Rm>"},
13340 {0xffe08000, 0xea200000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13341 &EmulateInstructionARM::EmulateBICReg,
13342 "bic{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
13343 // eor (immediate)
13344 {0xfbe08000, 0xf0800000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13345 &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #<const>"},
13346 // eor (register)
13347 {0xffffffc0, 0x00004040, ARMvAll, eEncodingT1, No_VFP, eSize16,
13348 &EmulateInstructionARM::EmulateEORReg, "eors|eor<c> <Rdn>, <Rm>"},
13349 {0xffe08000, 0xea800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13350 &EmulateInstructionARM::EmulateEORReg,
13351 "eor{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
13352 // orr (immediate)
13353 {0xfbe08000, 0xf0400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13354 &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #<const>"},
13355 // orr (register)
13356 {0xffffffc0, 0x00004300, ARMvAll, eEncodingT1, No_VFP, eSize16,
13357 &EmulateInstructionARM::EmulateORRReg, "orrs|orr<c> <Rdn>, <Rm>"},
13358 {0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13359 &EmulateInstructionARM::EmulateORRReg,
13360 "orr{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
13361 // rsb (immediate)
13362 {0xffffffc0, 0x00004240, ARMvAll, eEncodingT1, No_VFP, eSize16,
13363 &EmulateInstructionARM::EmulateRSBImm, "rsbs|rsb<c> <Rd>, <Rn>, #0"},
13364 {0xfbe08000, 0xf1c00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13365 &EmulateInstructionARM::EmulateRSBImm,
13366 "rsb{s}<c>.w <Rd>, <Rn>, #<const>"},
13367 // rsb (register)
13368 {0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13369 &EmulateInstructionARM::EmulateRSBReg,
13370 "rsb{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
13371 // sbc (immediate)
13372 {0xfbe08000, 0xf1600000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13373 &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
13374 // sbc (register)
13375 {0xffffffc0, 0x00004180, ARMvAll, eEncodingT1, No_VFP, eSize16,
13376 &EmulateInstructionARM::EmulateSBCReg, "sbcs|sbc<c> <Rdn>, <Rm>"},
13377 {0xffe08000, 0xeb600000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13378 &EmulateInstructionARM::EmulateSBCReg,
13379 "sbc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
13380 // add (immediate, Thumb)
13381 {0xfffffe00, 0x00001c00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13382 &EmulateInstructionARM::EmulateADDImmThumb,
13383 "adds|add<c> <Rd>,<Rn>,#<imm3>"},
13384 {0xfffff800, 0x00003000, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16,
13385 &EmulateInstructionARM::EmulateADDImmThumb, "adds|add<c> <Rdn>,#<imm8>"},
13386 {0xfbe08000, 0xf1000000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13387 &EmulateInstructionARM::EmulateADDImmThumb,
13388 "add{s}<c>.w <Rd>,<Rn>,#<const>"},
13389 {0xfbf08000, 0xf2000000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32,
13390 &EmulateInstructionARM::EmulateADDImmThumb,
13391 "addw<c> <Rd>,<Rn>,#<imm12>"},
13392 // sub (immediate, Thumb)
13393 {0xfffffe00, 0x00001e00, ARMvAll, eEncodingT1, No_VFP, eSize16,
13394 &EmulateInstructionARM::EmulateSUBImmThumb,
13395 "subs|sub<c> <Rd>, <Rn> #imm3"},
13396 {0xfffff800, 0x00003800, ARMvAll, eEncodingT2, No_VFP, eSize16,
13397 &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rdn>, #imm8"},
13398 {0xfbe08000, 0xf1a00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13399 &EmulateInstructionARM::EmulateSUBImmThumb,
13400 "sub{s}<c>.w <Rd>, <Rn>, #<const>"},
13401 {0xfbf08000, 0xf2a00000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32,
13402 &EmulateInstructionARM::EmulateSUBImmThumb,
13403 "subw<c> <Rd>, <Rn>, #imm12"},
13404 // sub (sp minus immediate)
13405 {0xfbef8000, 0xf1ad0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13406 &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}.w <Rd>, sp, #<const>"},
13407 {0xfbff8000, 0xf2ad0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13408 &EmulateInstructionARM::EmulateSUBSPImm, "subw<c> <Rd>, sp, #imm12"},
13409 // sub (register)
13410 {0xfffffe00, 0x00001a00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13411 &EmulateInstructionARM::EmulateSUBReg, "subs|sub<c> <Rd>, <Rn>, <Rm>"},
13412 {0xffe08000, 0xeba00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13413 &EmulateInstructionARM::EmulateSUBReg,
13414 "sub{s}<c>.w <Rd>, <Rn>, <Rm>{,<shift>}"},
13415 // teq (immediate)
13416 {0xfbf08f00, 0xf0900f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13417 &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #<const>"},
13418 // teq (register)
13419 {0xfff08f00, 0xea900f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13420 &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
13421 // tst (immediate)
13422 {0xfbf08f00, 0xf0100f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13423 &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #<const>"},
13424 // tst (register)
13425 {0xffffffc0, 0x00004200, ARMvAll, eEncodingT1, No_VFP, eSize16,
13426 &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rdn>, <Rm>"},
13427 {0xfff08f00, 0xea100f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13428 &EmulateInstructionARM::EmulateTSTReg, "tst<c>.w <Rn>, <Rm> {,<shift>}"},
13430 // move from high register to high register
13431 {0xffffff00, 0x00004600, ARMvAll, eEncodingT1, No_VFP, eSize16,
13432 &EmulateInstructionARM::EmulateMOVRdRm, "mov<c> <Rd>, <Rm>"},
13433 // move from low register to low register
13434 {0xffffffc0, 0x00000000, ARMvAll, eEncodingT2, No_VFP, eSize16,
13435 &EmulateInstructionARM::EmulateMOVRdRm, "movs <Rd>, <Rm>"},
13436 // mov{s}<c>.w <Rd>, <Rm>
13437 {0xffeff0f0, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13438 &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c>.w <Rd>, <Rm>"},
13439 // move immediate
13440 {0xfffff800, 0x00002000, ARMvAll, eEncodingT1, No_VFP, eSize16,
13441 &EmulateInstructionARM::EmulateMOVRdImm, "movs|mov<c> <Rd>, #imm8"},
13442 {0xfbef8000, 0xf04f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13443 &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c>.w <Rd>, #<const>"},
13444 {0xfbf08000, 0xf2400000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13445 &EmulateInstructionARM::EmulateMOVRdImm, "movw<c> <Rd>,#<imm16>"},
13446 // mvn (immediate)
13447 {0xfbef8000, 0xf06f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13448 &EmulateInstructionARM::EmulateMVNImm, "mvn{s} <Rd>, #<const>"},
13449 // mvn (register)
13450 {0xffffffc0, 0x000043c0, ARMvAll, eEncodingT1, No_VFP, eSize16,
13451 &EmulateInstructionARM::EmulateMVNReg, "mvns|mvn<c> <Rd>, <Rm>"},
13452 {0xffef8000, 0xea6f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13453 &EmulateInstructionARM::EmulateMVNReg,
13454 "mvn{s}<c>.w <Rd>, <Rm> {,<shift>}"},
13455 // cmn (immediate)
13456 {0xfbf08f00, 0xf1100f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13457 &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
13458 // cmn (register)
13459 {0xffffffc0, 0x000042c0, ARMvAll, eEncodingT1, No_VFP, eSize16,
13460 &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm>"},
13461 {0xfff08f00, 0xeb100f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13462 &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
13463 // cmp (immediate)
13464 {0xfffff800, 0x00002800, ARMvAll, eEncodingT1, No_VFP, eSize16,
13465 &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #imm8"},
13466 {0xfbf08f00, 0xf1b00f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13467 &EmulateInstructionARM::EmulateCMPImm, "cmp<c>.w <Rn>, #<const>"},
13468 // cmp (register) (Rn and Rm both from r0-r7)
13469 {0xffffffc0, 0x00004280, ARMvAll, eEncodingT1, No_VFP, eSize16,
13470 &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
13471 // cmp (register) (Rn and Rm not both from r0-r7)
13472 {0xffffff00, 0x00004500, ARMvAll, eEncodingT2, No_VFP, eSize16,
13473 &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
13474 {0xfff08f00, 0xebb00f00, ARMvAll, eEncodingT3, No_VFP, eSize16,
13475 &EmulateInstructionARM::EmulateCMPReg,
13476 "cmp<c>.w <Rn>, <Rm> {, <shift>}"},
13477 // asr (immediate)
13478 {0xfffff800, 0x00001000, ARMvAll, eEncodingT1, No_VFP, eSize16,
13479 &EmulateInstructionARM::EmulateASRImm, "asrs|asr<c> <Rd>, <Rm>, #imm"},
13480 {0xffef8030, 0xea4f0020, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13481 &EmulateInstructionARM::EmulateASRImm, "asr{s}<c>.w <Rd>, <Rm>, #imm"},
13482 // asr (register)
13483 {0xffffffc0, 0x00004100, ARMvAll, eEncodingT1, No_VFP, eSize16,
13484 &EmulateInstructionARM::EmulateASRReg, "asrs|asr<c> <Rdn>, <Rm>"},
13485 {0xffe0f0f0, 0xfa40f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13486 &EmulateInstructionARM::EmulateASRReg, "asr{s}<c>.w <Rd>, <Rn>, <Rm>"},
13487 // lsl (immediate)
13488 {0xfffff800, 0x00000000, ARMvAll, eEncodingT1, No_VFP, eSize16,
13489 &EmulateInstructionARM::EmulateLSLImm, "lsls|lsl<c> <Rd>, <Rm>, #imm"},
13490 {0xffef8030, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13491 &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c>.w <Rd>, <Rm>, #imm"},
13492 // lsl (register)
13493 {0xffffffc0, 0x00004080, ARMvAll, eEncodingT1, No_VFP, eSize16,
13494 &EmulateInstructionARM::EmulateLSLReg, "lsls|lsl<c> <Rdn>, <Rm>"},
13495 {0xffe0f0f0, 0xfa00f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13496 &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c>.w <Rd>, <Rn>, <Rm>"},
13497 // lsr (immediate)
13498 {0xfffff800, 0x00000800, ARMvAll, eEncodingT1, No_VFP, eSize16,
13499 &EmulateInstructionARM::EmulateLSRImm, "lsrs|lsr<c> <Rd>, <Rm>, #imm"},
13500 {0xffef8030, 0xea4f0010, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13501 &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c>.w <Rd>, <Rm>, #imm"},
13502 // lsr (register)
13503 {0xffffffc0, 0x000040c0, ARMvAll, eEncodingT1, No_VFP, eSize16,
13504 &EmulateInstructionARM::EmulateLSRReg, "lsrs|lsr<c> <Rdn>, <Rm>"},
13505 {0xffe0f0f0, 0xfa20f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13506 &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c>.w <Rd>, <Rn>, <Rm>"},
13507 // rrx is a special case encoding of ror (immediate)
13508 {0xffeff0f0, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13509 &EmulateInstructionARM::EmulateRRX, "rrx{s}<c>.w <Rd>, <Rm>"},
13510 // ror (immediate)
13511 {0xffef8030, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13512 &EmulateInstructionARM::EmulateRORImm, "ror{s}<c>.w <Rd>, <Rm>, #imm"},
13513 // ror (register)
13514 {0xffffffc0, 0x000041c0, ARMvAll, eEncodingT1, No_VFP, eSize16,
13515 &EmulateInstructionARM::EmulateRORReg, "rors|ror<c> <Rdn>, <Rm>"},
13516 {0xffe0f0f0, 0xfa60f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13517 &EmulateInstructionARM::EmulateRORReg, "ror{s}<c>.w <Rd>, <Rn>, <Rm>"},
13518 // mul
13519 {0xffffffc0, 0x00004340, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13520 &EmulateInstructionARM::EmulateMUL, "muls <Rdm>,<Rn>,<Rdm>"},
13521 // mul
13522 {0xfff0f0f0, 0xfb00f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13523 &EmulateInstructionARM::EmulateMUL, "mul<c> <Rd>,<Rn>,<Rm>"},
13525 // subs pc, lr and related instructions
13526 {0xffffff00, 0xf3de8f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13527 &EmulateInstructionARM::EmulateSUBSPcLrEtc, "SUBS<c> PC, LR, #<imm8>"},
13529 // RFE instructions *** IMPORTANT *** THESE MUST BE LISTED **BEFORE** THE
13530 // LDM.. Instructions in this table;
13531 // otherwise the wrong instructions will be selected.
13533 {0xffd0ffff, 0xe810c000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13534 &EmulateInstructionARM::EmulateRFE, "rfedb<c> <Rn>{!}"},
13535 {0xffd0ffff, 0xe990c000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13536 &EmulateInstructionARM::EmulateRFE, "rfe{ia}<c> <Rn>{!}"},
13538 // Load instructions
13539 {0xfffff800, 0x0000c800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13540 &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>"},
13541 {0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13542 &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>"},
13543 {0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13544 &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>"},
13545 {0xfffff800, 0x00006800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13546 &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#imm}]"},
13547 {0xfffff800, 0x00009800, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16,
13548 &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [SP{,#imm}]"},
13549 {0xfff00000, 0xf8d00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13550 &EmulateInstructionARM::EmulateLDRRtRnImm,
13551 "ldr<c>.w <Rt>, [<Rn>{,#imm12}]"},
13552 {0xfff00800, 0xf8500800, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32,
13553 &EmulateInstructionARM::EmulateLDRRtRnImm,
13554 "ldr<c> <Rt>, [<Rn>{,#+/-<imm8>}]{!}"},
13555 // Thumb2 PC-relative load into register
13556 {0xff7f0000, 0xf85f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13557 &EmulateInstructionARM::EmulateLDRRtPCRelative,
13558 "ldr<c>.w <Rt>, [PC, +/-#imm}]"},
13559 {0xfffffe00, 0x00005800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13560 &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt>, [<Rn>, <Rm>]"},
13561 {0xfff00fc0, 0xf8500000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13562 &EmulateInstructionARM::EmulateLDRRegister,
13563 "ldr<c>.w <Rt>, [<Rn>,<Rm>{,LSL #<imm2>}]"},
13564 {0xfffff800, 0x00007800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13565 &EmulateInstructionARM::EmulateLDRBImmediate,
13566 "ldrb<c> <Rt>,[<Rn>{,#<imm5>}]"},
13567 {0xfff00000, 0xf8900000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13568 &EmulateInstructionARM::EmulateLDRBImmediate,
13569 "ldrb<c>.w <Rt>,[<Rn>{,#<imm12>}]"},
13570 {0xfff00800, 0xf8100800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13571 &EmulateInstructionARM::EmulateLDRBImmediate,
13572 "ldrb<c> <Rt>,[<Rn>, #+/-<imm8>]{!}"},
13573 {0xff7f0000, 0xf81f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13574 &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>,[...]"},
13575 {0xfffffe00, 0x00005c00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16,
13576 &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>,[<Rn>,<Rm>]"},
13577 {0xfff00fc0, 0xf8100000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13578 &EmulateInstructionARM::EmulateLDRBRegister,
13579 "ldrb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]"},
13580 {0xfffff800, 0x00008800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13581 &EmulateInstructionARM::EmulateLDRHImmediate,
13582 "ldrh<c> <Rt>, [<Rn>{,#<imm>}]"},
13583 {0xfff00000, 0xf8b00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13584 &EmulateInstructionARM::EmulateLDRHImmediate,
13585 "ldrh<c>.w <Rt>,[<Rn>{,#<imm12>}]"},
13586 {0xfff00800, 0xf8300800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13587 &EmulateInstructionARM::EmulateLDRHImmediate,
13588 "ldrh<c> <Rt>,[<Rn>,#+/-<imm8>]{!}"},
13589 {0xff7f0000, 0xf83f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13590 &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>"},
13591 {0xfffffe00, 0x00005a00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13592 &EmulateInstructionARM::EmulateLDRHRegister,
13593 "ldrh<c> <Rt>, [<Rn>,<Rm>]"},
13594 {0xfff00fc0, 0xf8300000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13595 &EmulateInstructionARM::EmulateLDRHRegister,
13596 "ldrh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]"},
13597 {0xfff00000, 0xf9900000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13598 &EmulateInstructionARM::EmulateLDRSBImmediate,
13599 "ldrsb<c> <Rt>,[<Rn>,#<imm12>]"},
13600 {0xfff00800, 0xf9100800, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13601 &EmulateInstructionARM::EmulateLDRSBImmediate,
13602 "ldrsb<c> <Rt>,[<Rn>,#+/-<imm8>]"},
13603 {0xff7f0000, 0xf91f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13604 &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt>, <label>"},
13605 {0xfffffe00, 0x00005600, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13606 &EmulateInstructionARM::EmulateLDRSBRegister,
13607 "ldrsb<c> <Rt>,[<Rn>,<Rm>]"},
13608 {0xfff00fc0, 0xf9100000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13609 &EmulateInstructionARM::EmulateLDRSBRegister,
13610 "ldrsb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]"},
13611 {0xfff00000, 0xf9b00000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13612 &EmulateInstructionARM::EmulateLDRSHImmediate,
13613 "ldrsh<c> <Rt>,[<Rn>,#<imm12>]"},
13614 {0xfff00800, 0xf9300800, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13615 &EmulateInstructionARM::EmulateLDRSHImmediate,
13616 "ldrsh<c> <Rt>,[<Rn>,#+/-<imm8>]"},
13617 {0xff7f0000, 0xf93f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13618 &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>"},
13619 {0xfffffe00, 0x00005e00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13620 &EmulateInstructionARM::EmulateLDRSHRegister,
13621 "ldrsh<c> <Rt>,[<Rn>,<Rm>]"},
13622 {0xfff00fc0, 0xf9300000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13623 &EmulateInstructionARM::EmulateLDRSHRegister,
13624 "ldrsh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]"},
13625 {0xfe500000, 0xe8500000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13626 &EmulateInstructionARM::EmulateLDRDImmediate,
13627 "ldrd<c> <Rt>, <Rt2>, [<Rn>,#+/-<imm>]!"},
13628 {0xfe100f00, 0xec100b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32,
13629 &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},
13630 {0xfe100f00, 0xec100a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32,
13631 &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},
13632 {0xffe00f00, 0xed100b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32,
13633 &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},
13634 {0xff300f00, 0xed100a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32,
13635 &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Sd>, {<Rn>{,#+/-<imm>}]"},
13636 {0xffb00000, 0xf9200000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32,
13637 &EmulateInstructionARM::EmulateVLD1Multiple,
13638 "vld1<c>.<size> <list>, [<Rn>{@<align>}],<Rm>"},
13639 {0xffb00300, 0xf9a00000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32,
13640 &EmulateInstructionARM::EmulateVLD1Single,
13641 "vld1<c>.<size> <list>, [<Rn>{@<align>}],<Rm>"},
13642 {0xffb00f00, 0xf9a00c00, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32,
13643 &EmulateInstructionARM::EmulateVLD1SingleAll,
13644 "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
13646 // Store instructions
13647 {0xfffff800, 0x0000c000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13648 &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>"},
13649 {0xffd00000, 0xe8800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13650 &EmulateInstructionARM::EmulateSTM, "stm<c>.w <Rn>{!} <registers>"},
13651 {0xffd00000, 0xe9000000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13652 &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>"},
13653 {0xfffff800, 0x00006000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13654 &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>{,#<imm>}]"},
13655 {0xfffff800, 0x00009000, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16,
13656 &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [SP,#<imm>]"},
13657 {0xfff00000, 0xf8c00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13658 &EmulateInstructionARM::EmulateSTRThumb,
13659 "str<c>.w <Rt>, [<Rn>,#<imm12>]"},
13660 {0xfff00800, 0xf8400800, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32,
13661 &EmulateInstructionARM::EmulateSTRThumb,
13662 "str<c> <Rt>, [<Rn>,#+/-<imm8>]"},
13663 {0xfffffe00, 0x00005000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13664 &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> ,{<Rn>, <Rm>]"},
13665 {0xfff00fc0, 0xf8400000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13666 &EmulateInstructionARM::EmulateSTRRegister,
13667 "str<c>.w <Rt>, [<Rn>, <Rm> {lsl #imm2>}]"},
13668 {0xfffff800, 0x00007000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13669 &EmulateInstructionARM::EmulateSTRBThumb,
13670 "strb<c> <Rt>, [<Rn>, #<imm5>]"},
13671 {0xfff00000, 0xf8800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13672 &EmulateInstructionARM::EmulateSTRBThumb,
13673 "strb<c>.w <Rt>, [<Rn>, #<imm12>]"},
13674 {0xfff00800, 0xf8000800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,
13675 &EmulateInstructionARM::EmulateSTRBThumb,
13676 "strb<c> <Rt> ,[<Rn>, #+/-<imm8>]{!}"},
13677 {0xfffffe00, 0x00005200, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,
13678 &EmulateInstructionARM::EmulateSTRHRegister, "strh<c> <Rt>,[<Rn>,<Rm>]"},
13679 {0xfff00fc0, 0xf8200000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13680 &EmulateInstructionARM::EmulateSTRHRegister,
13681 "strh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]"},
13682 {0xfff00000, 0xe8400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13683 &EmulateInstructionARM::EmulateSTREX,
13684 "strex<c> <Rd>, <Rt>, [<Rn{,#<imm>}]"},
13685 {0xfe500000, 0xe8400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,
13686 &EmulateInstructionARM::EmulateSTRDImm,
13687 "strd<c> <Rt>, <Rt2>, [<Rn>, #+/-<imm>]!"},
13688 {0xfe100f00, 0xec000b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32,
13689 &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!}, <list>"},
13690 {0xfea00f00, 0xec000a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32,
13691 &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!}, <list>"},
13692 {0xff300f00, 0xed000b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32,
13693 &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},
13694 {0xff300f00, 0xed000a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32,
13695 &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Sd>, [<Rn>{,#+/-<imm>}]"},
13696 {0xffb00000, 0xf9000000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32,
13697 &EmulateInstructionARM::EmulateVST1Multiple,
13698 "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
13699 {0xffb00300, 0xf9800000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32,
13700 &EmulateInstructionARM::EmulateVST1Single,
13701 "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
13703 // Other instructions
13704 {0xffffffc0, 0x0000b240, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16,
13705 &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>"},
13706 {0xfffff080, 0xfa4ff080, ARMV6_ABOVE, eEncodingT2, No_VFP, eSize32,
13707 &EmulateInstructionARM::EmulateSXTB, "sxtb<c>.w <Rd>,<Rm>{,<rotation>}"},
13708 {0xffffffc0, 0x0000b200, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16,
13709 &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>"},
13710 {0xfffff080, 0xfa0ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13711 &EmulateInstructionARM::EmulateSXTH, "sxth<c>.w <Rd>,<Rm>{,<rotation>}"},
13712 {0xffffffc0, 0x0000b2c0, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16,
13713 &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>"},
13714 {0xfffff080, 0xfa5ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13715 &EmulateInstructionARM::EmulateUXTB, "uxtb<c>.w <Rd>,<Rm>{,<rotation>}"},
13716 {0xffffffc0, 0x0000b280, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16,
13717 &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>"},
13718 {0xfffff080, 0xfa1ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,
13719 &EmulateInstructionARM::EmulateUXTH, "uxth<c>.w <Rd>,<Rm>{,<rotation>}"},
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];
13728 return nullptr;
13731 bool 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("armv4t"))
13736 m_arm_isa = ARMv4T;
13737 else if (arch_cstr.equals_insensitive("armv5tej"))
13738 m_arm_isa = ARMv5TEJ;
13739 else if (arch_cstr.equals_insensitive("armv5te"))
13740 m_arm_isa = ARMv5TE;
13741 else if (arch_cstr.equals_insensitive("armv5t"))
13742 m_arm_isa = ARMv5T;
13743 else if (arch_cstr.equals_insensitive("armv6k"))
13744 m_arm_isa = ARMv6K;
13745 else if (arch_cstr.equals_insensitive("armv6t2"))
13746 m_arm_isa = ARMv6T2;
13747 else if (arch_cstr.equals_insensitive("armv7s"))
13748 m_arm_isa = ARMv7S;
13749 else if (arch_cstr.equals_insensitive("arm"))
13750 m_arm_isa = ARMvAll;
13751 else if (arch_cstr.equals_insensitive("thumb"))
13752 m_arm_isa = ARMvAll;
13753 else if (arch_cstr.starts_with_insensitive("armv4"))
13754 m_arm_isa = ARMv4;
13755 else if (arch_cstr.starts_with_insensitive("armv6"))
13756 m_arm_isa = ARMv6;
13757 else if (arch_cstr.starts_with_insensitive("armv7"))
13758 m_arm_isa = ARMv7;
13759 else if (arch_cstr.starts_with_insensitive("armv8"))
13760 m_arm_isa = ARMv8;
13761 return m_arm_isa != 0;
13764 bool 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();
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;
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;
13788 return false;
13791 bool EmulateInstructionARM::ReadInstruction() {
13792 bool success = false;
13793 m_opcode_cpsr = ReadRegisterUnsigned(eRegisterKindGeneric,
13794 LLDB_REGNUM_GENERIC_FLAGS, 0, &success);
13795 if (success) {
13796 addr_t pc =
13797 ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC,
13798 LLDB_INVALID_ADDRESS, &success);
13799 if (success) {
13800 Context read_inst_context;
13801 read_inst_context.type = eContextReadOpcode;
13802 read_inst_context.SetNoArgs();
13804 if ((m_opcode_cpsr & MASK_CPSR_T) || m_arch.IsAlwaysThumbInstructions()) {
13805 m_opcode_mode = eModeThumb;
13806 uint32_t thumb_opcode = MemARead(read_inst_context, pc, 2, 0, &success);
13808 if (success) {
13809 if ((thumb_opcode & 0xe000) != 0xe000 ||
13810 ((thumb_opcode & 0x1800u) == 0)) {
13811 m_opcode.SetOpcode16(thumb_opcode, GetByteOrder());
13812 } else {
13813 m_opcode.SetOpcode32(
13814 (thumb_opcode << 16) |
13815 MemARead(read_inst_context, pc + 2, 2, 0, &success),
13816 GetByteOrder());
13819 } else {
13820 m_opcode_mode = eModeARM;
13821 m_opcode.SetOpcode32(MemARead(read_inst_context, pc, 4, 0, &success),
13822 GetByteOrder());
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(m_opcode_cpsr, 15, 10) << 2) |
13829 Bits32(m_opcode_cpsr, 26, 25);
13830 if (it != 0)
13831 m_it_session.InitIT(it);
13835 if (!success) {
13836 m_opcode_mode = eModeInvalid;
13837 m_addr = LLDB_INVALID_ADDRESS;
13839 return success;
13842 uint32_t EmulateInstructionARM::ArchVersion() { return m_arm_isa; }
13844 bool 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;
13851 const uint32_t cond = CurrentCond(opcode);
13852 if (cond == UINT32_MAX)
13853 return false;
13855 bool result = false;
13856 switch (UnsignedBits(cond, 3, 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;
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);
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;
13912 if (cond & 1)
13913 result = !result;
13914 return result;
13917 uint32_t EmulateInstructionARM::CurrentCond(const uint32_t opcode) {
13918 switch (m_opcode_mode) {
13919 case eModeInvalid:
13920 break;
13922 case eModeARM:
13923 return UnsignedBits(opcode, 31, 28);
13925 case eModeThumb:
13926 // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit
13927 // 'cond' field of the encoding.
13929 const uint32_t byte_size = m_opcode.GetByteSize();
13930 if (byte_size == 2) {
13931 if (Bits32(opcode, 15, 12) == 0x0d && Bits32(opcode, 11, 8) != 0x0f)
13932 return Bits32(opcode, 11, 8);
13933 } else if (byte_size == 4) {
13934 if (Bits32(opcode, 31, 27) == 0x1e && Bits32(opcode, 15, 14) == 0x02 &&
13935 Bits32(opcode, 12, 12) == 0x00 && Bits32(opcode, 25, 22) <= 0x0d) {
13936 return Bits32(opcode, 25, 22);
13938 } else
13939 // We have an invalid thumb instruction, let's bail out.
13940 break;
13942 return m_it_session.GetCond();
13945 return UINT32_MAX; // Return invalid value
13948 bool EmulateInstructionARM::InITBlock() {
13949 return CurrentInstrSet() == eModeThumb && m_it_session.InITBlock();
13952 bool EmulateInstructionARM::LastInITBlock() {
13953 return CurrentInstrSet() == eModeThumb && m_it_session.LastInITBlock();
13956 bool EmulateInstructionARM::BadMode(uint32_t mode) {
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;
13978 return true;
13981 bool EmulateInstructionARM::CurrentModeIsPrivileged() {
13982 uint32_t mode = Bits32(m_opcode_cpsr, 4, 0);
13984 if (BadMode(mode))
13985 return false;
13987 if (mode == 16)
13988 return false;
13990 return true;
13993 void EmulateInstructionARM::CPSRWriteByInstr(uint32_t value, uint32_t bytemask,
13994 bool affect_execstate) {
13995 bool privileged = CurrentModeIsPrivileged();
13997 uint32_t tmp_cpsr = Bits32(m_opcode_cpsr, 23, 20) << 20;
13999 if (BitIsSet(bytemask, 3)) {
14000 tmp_cpsr = tmp_cpsr | (Bits32(value, 31, 27) << 27);
14001 if (affect_execstate)
14002 tmp_cpsr = tmp_cpsr | (Bits32(value, 26, 24) << 24);
14005 if (BitIsSet(bytemask, 2)) {
14006 tmp_cpsr = tmp_cpsr | (Bits32(value, 19, 16) << 16);
14009 if (BitIsSet(bytemask, 1)) {
14010 if (affect_execstate)
14011 tmp_cpsr = tmp_cpsr | (Bits32(value, 15, 10) << 10);
14012 tmp_cpsr = tmp_cpsr | (Bit32(value, 9) << 9);
14013 if (privileged)
14014 tmp_cpsr = tmp_cpsr | (Bit32(value, 8) << 8);
14017 if (BitIsSet(bytemask, 0)) {
14018 if (privileged)
14019 tmp_cpsr = tmp_cpsr | (Bits32(value, 7, 6) << 6);
14020 if (affect_execstate)
14021 tmp_cpsr = tmp_cpsr | (Bit32(value, 5) << 5);
14022 if (privileged)
14023 tmp_cpsr = tmp_cpsr | Bits32(value, 4, 0);
14026 m_opcode_cpsr = tmp_cpsr;
14029 bool EmulateInstructionARM::BranchWritePC(const Context &context,
14030 uint32_t addr) {
14031 addr_t target;
14033 // Check the current instruction set.
14034 if (CurrentInstrSet() == eModeARM)
14035 target = addr & 0xfffffffc;
14036 else
14037 target = addr & 0xfffffffe;
14039 return WriteRegisterUnsigned(context, eRegisterKindGeneric,
14040 LLDB_REGNUM_GENERIC_PC, target);
14043 // As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by
14044 // inspecting addr.
14045 bool 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;
14052 if (BitIsSet(addr, 0)) {
14053 if (CurrentInstrSet() != eModeThumb) {
14054 SelectInstrSet(eModeThumb);
14055 cpsr_changed = true;
14057 target = addr & 0xfffffffe;
14058 context.SetISA(eModeThumb);
14059 } else if (BitIsClear(addr, 1)) {
14060 if (CurrentInstrSet() != eModeARM) {
14061 SelectInstrSet(eModeARM);
14062 cpsr_changed = true;
14064 target = addr & 0xfffffffc;
14065 context.SetISA(eModeARM);
14066 } else
14067 return false; // address<1:0> == '10' => UNPREDICTABLE
14069 if (cpsr_changed) {
14070 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
14071 LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
14072 return false;
14074 return WriteRegisterUnsigned(context, eRegisterKindGeneric,
14075 LLDB_REGNUM_GENERIC_PC, target);
14078 // Dispatches to either BXWritePC or BranchWritePC based on architecture
14079 // versions.
14080 bool EmulateInstructionARM::LoadWritePC(Context &context, uint32_t addr) {
14081 if (ArchVersion() >= ARMv5T)
14082 return BXWritePC(context, addr);
14083 else
14084 return BranchWritePC((const Context)context, addr);
14087 // Dispatches to either BXWritePC or BranchWritePC based on architecture
14088 // versions and current instruction set.
14089 bool EmulateInstructionARM::ALUWritePC(Context &context, uint32_t addr) {
14090 if (ArchVersion() >= ARMv7 && CurrentInstrSet() == eModeARM)
14091 return BXWritePC(context, addr);
14092 else
14093 return BranchWritePC((const Context)context, addr);
14096 EmulateInstructionARM::Mode EmulateInstructionARM::CurrentInstrSet() {
14097 return m_opcode_mode;
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.
14103 bool 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;
14117 return true;
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.
14123 bool EmulateInstructionARM::UnalignedSupport() {
14124 return (ArchVersion() >= ARMv7);
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.
14131 EmulateInstructionARM::AddWithCarryResult
14132 EmulateInstructionARM::AddWithCarry(uint32_t x, uint32_t y, uint8_t carry_in) {
14133 uint32_t result;
14134 uint8_t carry_out;
14135 uint8_t overflow;
14137 uint64_t unsigned_sum = x + y + carry_in;
14138 int64_t signed_sum = (int32_t)x + (int32_t)y + (int32_t)carry_in;
14140 result = UnsignedBits(unsigned_sum, 31, 0);
14141 // carry_out = (result == unsigned_sum ? 0 : 1);
14142 overflow = ((int32_t)result == signed_sum ? 0 : 1);
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;
14149 AddWithCarryResult res = {result, carry_out, overflow};
14150 return res;
14153 uint32_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;
14178 break;
14181 // Read our register.
14182 uint32_t val = ReadRegisterUnsigned(reg_kind, reg_num, 0, success);
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;
14194 return val;
14197 // Write the result to the ARM core register Rd, and optionally update the
14198 // condition flags based on the result.
14200 // This helper method tries to encapsulate the following pseudocode from the
14201 // ARM Architecture Reference Manual:
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
14213 // In the above case, the API client does not pass in the overflow arg, which
14214 // defaults to ~0u.
14215 bool 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, 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;
14237 if (!WriteRegisterUnsigned(context, reg_kind, reg_num, result))
14238 return false;
14239 if (setflags)
14240 return WriteFlags(context, result, carry, overflow);
14242 return true;
14245 // This helper method tries to encapsulate the following pseudocode from the
14246 // ARM Architecture Reference Manual:
14248 // APSR.N = result<31>;
14249 // APSR.Z = IsZeroBit(result);
14250 // APSR.C = carry;
14251 // APSR.V = overflow
14253 // Default arguments can be specified for carry and overflow parameters, which
14254 // means not to update the respective flags.
14255 bool 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(m_new_inst_cpsr, CPSR_N_POS, Bit32(result, CPSR_N_POS));
14260 SetBit32(m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0);
14261 if (carry != ~0u)
14262 SetBit32(m_new_inst_cpsr, CPSR_C_POS, carry);
14263 if (overflow != ~0u)
14264 SetBit32(m_new_inst_cpsr, CPSR_V_POS, overflow);
14265 if (m_new_inst_cpsr != m_opcode_cpsr) {
14266 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
14267 LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
14268 return false;
14270 return true;
14273 bool EmulateInstructionARM::EvaluateInstruction(uint32_t evaluate_options) {
14274 ARMOpcode *opcode_data = nullptr;
14276 if (m_opcode_mode == eModeThumb)
14277 opcode_data =
14278 GetThumbOpcodeForInstruction(m_opcode.GetOpcode32(), m_arm_isa);
14279 else if (m_opcode_mode == eModeARM)
14280 opcode_data = GetARMOpcodeForInstruction(m_opcode.GetOpcode32(), m_arm_isa);
14282 const bool auto_advance_pc =
14283 evaluate_options & eEmulateInstructionOptionAutoAdvancePC;
14284 m_ignore_conditions =
14285 evaluate_options & eEmulateInstructionOptionIgnoreConditions;
14287 bool success = false;
14288 if (m_opcode_cpsr == 0 || !m_ignore_conditions) {
14289 m_opcode_cpsr =
14290 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_cpsr, 0, &success);
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;
14298 uint32_t orig_pc_value = 0;
14299 if (auto_advance_pc) {
14300 orig_pc_value =
14301 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc, 0, &success);
14302 if (!success)
14303 return false;
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;
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();
14321 if (auto_advance_pc) {
14322 uint32_t after_pc_value =
14323 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc, 0, &success);
14324 if (!success)
14325 return false;
14327 if (after_pc_value == orig_pc_value) {
14328 after_pc_value += m_opcode.GetByteSize();
14330 EmulateInstruction::Context context;
14331 context.type = eContextAdvancePC;
14332 context.SetNoArgs();
14333 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc,
14334 after_pc_value))
14335 return false;
14338 return true;
14341 EmulateInstruction::InstructionCondition
14342 EmulateInstructionARM::GetInstructionCondition() {
14343 const uint32_t cond = CurrentCond(m_opcode.GetOpcode32());
14344 if (cond == 0xe || cond == 0xf || cond == UINT32_MAX)
14345 return EmulateInstruction::UnconditionalCondition;
14346 return cond;
14349 bool EmulateInstructionARM::TestEmulation(Stream &out_stream, ArchSpec &arch,
14350 OptionValueDictionary *test_data) {
14351 if (!test_data) {
14352 out_stream.Printf("TestEmulation: Missing test data.\n");
14353 return false;
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");
14360 OptionValueSP value_sp = test_data->GetValueForKey(opcode_key);
14362 uint32_t test_opcode;
14363 if ((value_sp.get() == nullptr) ||
14364 (value_sp->GetType() != OptionValue::eTypeUInt64)) {
14365 out_stream.Printf("TestEmulation: Error reading opcode from test file.\n");
14366 return false;
14368 test_opcode = value_sp->GetValueAs<uint64_t>().value_or(0);
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(test_opcode, endian::InlHostByteOrder());
14375 else
14376 m_opcode.SetOpcode32(test_opcode, endian::InlHostByteOrder());
14377 } else if (arch.GetTriple().getArch() == llvm::Triple::arm) {
14378 m_opcode_mode = eModeARM;
14379 m_opcode.SetOpcode32(test_opcode, endian::InlHostByteOrder());
14380 } else {
14381 out_stream.Printf("TestEmulation: Invalid arch.\n");
14382 return false;
14385 EmulationStateARM before_state;
14386 EmulationStateARM after_state;
14388 value_sp = test_data->GetValueForKey(before_key);
14389 if ((value_sp.get() == nullptr) ||
14390 (value_sp->GetType() != OptionValue::eTypeDictionary)) {
14391 out_stream.Printf("TestEmulation: Failed to find 'before' state.\n");
14392 return false;
14395 OptionValueDictionary *state_dictionary = value_sp->GetAsDictionary();
14396 if (!before_state.LoadStateFromDictionary(state_dictionary)) {
14397 out_stream.Printf("TestEmulation: Failed loading 'before' state.\n");
14398 return false;
14401 value_sp = test_data->GetValueForKey(after_key);
14402 if ((value_sp.get() == nullptr) ||
14403 (value_sp->GetType() != OptionValue::eTypeDictionary)) {
14404 out_stream.Printf("TestEmulation: Failed to find 'after' state.\n");
14405 return false;
14408 state_dictionary = value_sp->GetAsDictionary();
14409 if (!after_state.LoadStateFromDictionary(state_dictionary)) {
14410 out_stream.Printf("TestEmulation: Failed loading 'after' state.\n");
14411 return false;
14414 SetBaton((void *)&before_state);
14415 SetCallbacks(&EmulationStateARM::ReadPseudoMemory,
14416 &EmulationStateARM::WritePseudoMemory,
14417 &EmulationStateARM::ReadPseudoRegister,
14418 &EmulationStateARM::WritePseudoRegister);
14420 bool success = EvaluateInstruction(eEmulateInstructionOptionAutoAdvancePC);
14421 if (!success) {
14422 out_stream.Printf("TestEmulation: EvaluateInstruction() failed.\n");
14423 return false;
14426 success = before_state.CompareState(after_state, out_stream);
14427 if (!success)
14428 out_stream.Printf("TestEmulation: State after emulation does not match "
14429 "'after' state.\n");
14431 return success;
14435 // const char *
14436 // EmulateInstructionARM::GetRegisterName (uint32_t reg_kind, uint32_t reg_num)
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;
14457 bool EmulateInstructionARM::CreateFunctionEntryUnwind(UnwindPlan &unwind_plan) {
14458 unwind_plan.Clear();
14459 unwind_plan.SetRegisterKind(eRegisterKindDWARF);
14461 UnwindPlan::RowSP row(new UnwindPlan::Row);
14463 // Our previous Call Frame Address is the stack pointer
14464 row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_sp, 0);
14466 unwind_plan.AppendRow(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;